login.jsx 6.94 KB
// Login screen. Original logo (geometric registration-mark), original product name.

const Login = ({ onLogin }) => {
  const [user, setUser] = React.useState("admin");
  const [pass, setPass] = React.useState("••••••••");
  const [company, setCompany] = React.useState("std");
  const [companyOpen, setCompanyOpen] = React.useState(false);
  const [submitting, setSubmitting] = React.useState(false);

  const submit = (e) => {
    e && e.preventDefault();
    if (!user || !pass) return;
    setSubmitting(true);
    setTimeout(() => onLogin({ user, company: XLY.COMPANIES.find(c => c.id === company)?.name }), 480);
  };

  return (
    <div style={{
      position: "fixed", inset: 0,
      background: "radial-gradient(ellipse at center, #424b60 0%, #2e3645 70%, #262d3a 100%)",
      display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center",
      fontFamily: "inherit",
    }}>
      <div style={{ width: 320, marginTop: -40 }}>
        {/* Logo + wordmark */}
        <div style={{ display: "flex", flexDirection: "column", alignItems: "center", marginBottom: 28 }}>
          <div style={{ position: "relative", marginBottom: 10 }}>
            <svg width="76" height="76" viewBox="0 0 76 76" fill="none">
              {/* Three overlapping registration squares — print-press metaphor */}
              <rect x="8" y="8" width="34" height="34" stroke="rgba(255,255,255,0.95)" strokeWidth="2" />
              <rect x="22" y="22" width="34" height="34" stroke="rgba(255,255,255,0.85)" strokeWidth="2" />
              <rect x="36" y="36" width="32" height="32" stroke="rgba(255,255,255,0.7)" strokeWidth="2" />
              {/* registration cross */}
              <circle cx="38" cy="38" r="4" stroke="#fff" strokeWidth="1.5" />
              <path d="M38 32v12M32 38h12" stroke="#fff" strokeWidth="1" />
            </svg>
          </div>
          <div style={{ color: "#fff", fontSize: 22, fontWeight: 600, letterSpacing: 4, marginBottom: 2 }}>
            XLY-ERP
          </div>
          <div style={{ color: "rgba(255,255,255,0.55)", fontSize: 11, letterSpacing: 2 }}>
            印刷制造管理平台
          </div>
        </div>

        <form onSubmit={submit}>
          {/* User */}
          <div style={loginStyles.fieldWrap}>
            <span style={loginStyles.fieldIcon}><Ic.user size={14} color="rgba(0,0,0,0.55)" /></span>
            <span style={loginStyles.fieldDivider} />
            <input
              value={user}
              onChange={(e) => setUser(e.target.value)}
              placeholder="请输入用户名"
              style={loginStyles.input}
            />
          </div>
          {/* Password */}
          <div style={loginStyles.fieldWrap}>
            <span style={loginStyles.fieldIcon}><Ic.lock size={14} color="rgba(0,0,0,0.55)" /></span>
            <span style={loginStyles.fieldDivider} />
            <input
              type="password"
              value={pass}
              onChange={(e) => setPass(e.target.value)}
              placeholder="请输入密码"
              style={loginStyles.input}
            />
          </div>
          {/* Company picker */}
          <div style={{ position: "relative", marginBottom: 14 }}>
            <button
              type="button"
              onClick={() => setCompanyOpen((v) => !v)}
              style={{
                ...loginStyles.fieldWrap,
                width: "100%",
                cursor: "pointer", textAlign: "left",
                paddingRight: 12,
              }}
            >
              <span style={{ flex: 1, color: company ? "#1a2332" : "rgba(0,0,0,0.5)", fontSize: 13, paddingLeft: 12 }}>
                {company ? XLY.COMPANIES.find(c => c.id === company)?.name : "请选择公司名"}
              </span>
              <span style={{ color: "rgba(0,0,0,0.5)", display: "inline-flex", paddingRight: 4 }}>
                <Ic.chevronDown size={14} style={{ transform: companyOpen ? "rotate(180deg)" : "none", transition: "transform 0.15s" }} />
              </span>
            </button>
            {companyOpen ? (
              <div style={{
                position: "absolute", top: "calc(100% + 2px)", left: 0, right: 0,
                background: "rgba(60,68,82,0.98)", border: "1px solid rgba(255,255,255,0.1)",
                zIndex: 10,
              }}>
                {XLY.COMPANIES.map((c, i) => {
                  const sel = c.id === company;
                  return (
                    <div
                      key={c.id}
                      onClick={() => { setCompany(c.id); setCompanyOpen(false); }}
                      style={{
                        padding: "9px 12px", color: "#fff", fontSize: 13,
                        cursor: "pointer",
                        background: sel ? "var(--accent)" : "transparent",
                        borderTop: i === 0 ? "none" : "1px solid rgba(255,255,255,0.04)",
                      }}
                      onMouseEnter={(e) => { if (!sel) e.currentTarget.style.background = "rgba(255,255,255,0.06)"; }}
                      onMouseLeave={(e) => { if (!sel) e.currentTarget.style.background = "transparent"; }}
                    >
                      {c.name}
                    </div>
                  );
                })}
              </div>
            ) : null}
          </div>
          {/* Submit */}
          <button
            type="submit"
            disabled={submitting}
            style={{
              width: "100%", height: 38,
              background: submitting ? "#3478b8" : "var(--accent)",
              border: "none", color: "#fff", fontSize: 14, letterSpacing: 8,
              cursor: submitting ? "wait" : "pointer",
              fontFamily: "inherit",
            }}
            onMouseEnter={(e) => { if (!submitting) e.currentTarget.style.background = "var(--accent-strong)"; }}
            onMouseLeave={(e) => { if (!submitting) e.currentTarget.style.background = "var(--accent)"; }}
          >
            {submitting ? "登 录 中…" : "登 录"}
          </button>
        </form>
      </div>

      {/* Footer */}
      <div style={{
        position: "absolute", bottom: 24, left: 0, right: 0, textAlign: "center",
        color: "rgba(255,255,255,0.3)", fontSize: 11, letterSpacing: 1,
      }}>
        XLY 软件 · 印刷制造管理平台 · 版权所有 © 2017–2026
      </div>
    </div>
  );
};

const loginStyles = {
  fieldWrap: {
    display: "flex", alignItems: "center", height: 38,
    background: "rgba(255,255,255,0.95)",
    border: "1px solid rgba(255,255,255,0.15)",
    marginBottom: 10,
  },
  fieldIcon: { width: 36, display: "inline-flex", alignItems: "center", justifyContent: "center", color: "rgba(0,0,0,0.5)" },
  fieldDivider: { width: 1, height: 18, background: "rgba(0,0,0,0.12)" },
  input: {
    flex: 1, height: "100%", border: "none", background: "transparent",
    paddingLeft: 10, paddingRight: 10, fontSize: 13, color: "#1a2332",
    outline: "none", fontFamily: "inherit",
  },
};

window.Login = Login;