From 3b10a58d93f5d6973812d0316892a06f6b9c26c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=85=BE=E8=AE=AFWorkBuddy?= Date: Sat, 22 Aug 2026 22:18:24 +0800 Subject: [PATCH] =?UTF-8?q?HEL-34:=20=E7=99=BB=E5=BD=95=E9=A1=B5=E6=8C=89?= =?UTF-8?q?=E3=80=8C=E6=B7=B1=E6=B5=B7=E5=86=9B=E8=93=9D=20=C3=97=20?= =?UTF-8?q?=E8=B4=A6=E6=88=BF=E9=87=91=E3=80=8D=E6=96=B9=E6=A1=88=E6=94=B9?= =?UTF-8?q?=E9=80=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: multica-agent --- web/app.js | 34 ++++++- web/index.html | 75 +++++++++----- web/styles.css | 266 +++++++++++++++++++++++++++++++++++++++---------- 3 files changed, 293 insertions(+), 82 deletions(-) diff --git a/web/app.js b/web/app.js index 7590070..b0a1253 100644 --- a/web/app.js +++ b/web/app.js @@ -273,10 +273,16 @@ function initEntry() { const form = $("#loginForm"); if (!form) return; if (!motionQuery.matches) { - [$(".entry-brand"), $(".entry-statement"), ...$$(".entry-facts > div"), form].filter(Boolean).forEach((element, index) => { + [ + [$(".entry-form-wrap"), 0], + [$(".entry-statement h1"), 60], + [$(".entry-statement p"), 120], + [$(".entry-figure"), 120], + ].forEach(([element, delay]) => { + if (!element) return; element.animate( - [{ opacity: 0, transform: "translateY(16px)" }, { opacity: 1, transform: "translateY(0)" }], - { duration: 520, delay: index * 65, easing: "cubic-bezier(.22,1,.36,1)", fill: "both" }, + [{ opacity: 0, transform: "translateY(12px)" }, { opacity: 1, transform: "translateY(0)" }], + { duration: 300, delay, easing: "cubic-bezier(.16,1,.3,1)", fill: "both" }, ); }); } @@ -287,6 +293,22 @@ function initEntry() { const errorBox = $("#loginError"); const changeSection = $("#changePassword"); let pendingRole = null; + const submitButton = $('button[type="submit"]', form); + + function setLoading(loading) { + submitButton.disabled = loading; + submitButton.classList.toggle("is-loading", loading); + $$("input, button", form).forEach((el) => { + if (el !== submitButton) el.disabled = loading; + }); + if (loading) { + action.textContent = "登录中…"; + } else if (pendingRole) { + action.textContent = "设置新密码并进入"; + } else { + updateRole(); + } + } function showError(message) { errorBox.textContent = message; @@ -308,6 +330,7 @@ function initEntry() { form.addEventListener("submit", async (event) => { event.preventDefault(); errorBox.hidden = true; + setLoading(true); const role = pendingRole || $('input[name="role"]:checked', form).value; if (pendingRole) { @@ -315,6 +338,7 @@ function initEntry() { const confirmPassword = $('input[name="confirm_password"]', form).value; if (newPassword !== confirmPassword) { showError("两次输入的新密码不一致。"); + setLoading(false); return; } const changeResponse = await fetch("/api/password/change", { @@ -325,6 +349,7 @@ function initEntry() { const changeResult = await changeResponse?.json().catch(() => ({})); if (!changeResponse || !changeResponse.ok) { showError(changeResult?.message || "修改密码失败,请稍后重试。"); + setLoading(false); return; } window.location.href = role === "admin" ? "admin.html" : "company.html"; @@ -339,12 +364,13 @@ function initEntry() { const result = await response?.json().catch(() => ({})); if (!response || !response.ok) { showError(result?.message || "登录服务暂时不可用,请稍后重试。"); + setLoading(false); return; } if (result.must_change_password) { pendingRole = role; changeSection.hidden = false; - action.textContent = "设置新密码并进入"; + setLoading(false); $('input[name="new_password"]', form).focus(); return; } diff --git a/web/index.html b/web/index.html index 26c68b7..ce57708 100644 --- a/web/index.html +++ b/web/index.html @@ -3,46 +3,73 @@ - - 登录 · 河南金牛实业集团 - + + 登录 · 河南金牛实业集团有限公司资金往来管理系统 + -
-
-
河南金牛实业集团集团资金往来管理系统
+
+
+ + 河南金牛实业集团有限公司资金往来管理系统 +
+
+ +
+
+

集团资金往来管理

+

集团内部资金往来登记、核对及台账查询入口

+
+ +
+ +
-

登录

请选择与账号一致的工作端口

-
+
+

欢迎登录

+

请选择登录入口,使用账号和密码进入系统

+
+ + + +
+ + - - - + +
+ + 首次登录需修改密码 +
+ + + +

登录即表示你已阅读并遵守集团资金往来管理规范

-
-
全局起算日
2026.01.01
-
当前账期
2026 年 7 月
-
覆盖银行
已对接 6 家
-
- + diff --git a/web/styles.css b/web/styles.css index 4f20d46..e2ece2f 100644 --- a/web/styles.css +++ b/web/styles.css @@ -36,6 +36,26 @@ --duration-fast: 150ms; --duration-standard: 260ms; --ease-out: cubic-bezier(0.22, 1, 0.36, 1); + /* Login page — 深海军蓝 × 账房金 (HEL-32 已定稿) */ + --jn-navy-900: #0B2740; + --jn-navy-800: #123A5C; + --jn-navy-700: #1B4F7A; + --jn-blue-600: #1D4ED8; + --jn-blue-700: #1E40AF; + --jn-blue-800: #1E3A8A; + --jn-blue-50: #EFF6FF; + --jn-gold-500: #C9A227; + --jn-gold-400: #D9B84A; + --jn-bg-page: #F5F7FA; + --jn-bg-panel: #FFFFFF; + --jn-text-1: #1F2937; + --jn-text-2: #6B7280; + --jn-text-3: #9CA3AF; + --jn-border: #E5E7EB; + --jn-border-strong: #D1D5DB; + --jn-error: #DC2626; + --jn-error-bg: #FEF2F2; + --jn-disabled-bg: #F3F4F6; } * { box-sizing: border-box; } @@ -430,34 +450,199 @@ main { width: min(1560px, 100%); margin: 0 auto; padding: 12px 32px 58px; } .toast strong, .toast small { display: block; } .toast small { color: var(--color-ink-muted); } -/* Login */ -.entry-page { overflow-x: hidden; } -.entry-shell { min-height: 100vh; display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(430px, 0.85fr); } -.entry-context { position: relative; min-height: 100vh; display: flex; flex-direction: column; justify-content: space-between; padding: clamp(32px, 5vw, 76px); border-right: 1px solid var(--color-line); background: #080808; } -.entry-context::after { content: ""; position: absolute; inset: 12% 8% 12% auto; width: 1px; background: rgba(55, 235, 137, 0.32); box-shadow: 0 0 38px rgba(55, 235, 137, 0.45); } -.entry-brand { display: flex; align-items: center; gap: 12px; } -.entry-brand > span:last-child { display: flex; flex-direction: column; } -.entry-brand small { color: var(--color-ink-muted); } -.entry-statement { max-width: 680px; margin: 80px 0; } -.entry-statement h1 { max-width: 640px; font-size: clamp(38px, 5vw, 70px); line-height: 1.12; letter-spacing: 0; } -.entry-statement p { margin-top: 20px; color: var(--color-ink-muted); } -.entry-facts { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; max-width: 670px; } -.entry-facts div { padding: 15px; border: 1px solid var(--color-line); border-radius: var(--radius-md); background: var(--color-surface-muted); } -.entry-facts dt { color: var(--color-ink-muted); } -.entry-facts dd { margin-top: 4px; color: var(--color-primary); } -.entry-form-wrap { min-height: 100vh; display: grid; place-items: center; padding: 40px; background: var(--color-bg); } -.entry-form { width: min(420px, 100%); display: grid; gap: 18px; padding: 28px; border: 1px solid var(--color-line); border-radius: var(--radius-xl); background: var(--color-surface); box-shadow: var(--shadow-panel); backdrop-filter: blur(24px); } -.entry-form header h2 { font-size: 25px; } -.entry-form header p, .entry-note { color: var(--color-ink-muted); } -.role-switch { display: grid; grid-template-columns: 1fr 1fr; gap: 9px; } +/* Login — 深海军蓝 × 账房金 (HEL-32) */ +.entry-page { + color-scheme: light; + background: var(--jn-bg-page); + color: var(--jn-text-1); + overflow-x: hidden; +} +.entry-page::before { display: none; } +.entry-page :focus-visible { outline: 2px solid var(--jn-blue-600); outline-offset: 3px; } + +.entry-shell { + width: 100%; + margin: 0; + padding: 0; + min-height: 100vh; + min-height: 100dvh; + display: grid; + grid-template-columns: minmax(420px, 42%) minmax(0, 1fr); + grid-template-rows: 56px minmax(0, 1fr); + grid-template-areas: "topbar topbar" "context form"; +} + +.entry-topbar { + grid-area: topbar; + display: flex; + align-items: center; + padding: 0 24px; + background: var(--jn-bg-panel); + border-bottom: 1px solid var(--jn-border); +} +.entry-brand { display: flex; align-items: center; gap: 12px; min-width: 0; } +.entry-seal { + width: 28px; height: 28px; flex: 0 0 auto; + display: grid; place-items: center; + border: 1.5px solid var(--jn-gold-500); + border-radius: 6px; + background: var(--jn-bg-panel); + color: var(--jn-gold-500); + font-size: 17px; line-height: 1; font-weight: 700; +} +.entry-system-name { + font-size: 17px; line-height: 26px; font-weight: 600; + color: var(--jn-text-1); + white-space: nowrap; overflow: hidden; text-overflow: ellipsis; +} + +.entry-context { + grid-area: context; + position: relative; + display: flex; flex-direction: column; justify-content: center; + padding: 64px; + background: linear-gradient(160deg, var(--jn-navy-800), var(--jn-navy-900)); + overflow: hidden; +} +.entry-statement { max-width: 520px; } +.entry-statement h1 { font-size: 32px; line-height: 40px; font-weight: 700; color: #ffffff; letter-spacing: 0; } +.entry-statement p { margin-top: 12px; max-width: 440px; font-size: 14px; line-height: 22px; color: #B9CBDD; } +.entry-figure { width: 100%; height: auto; max-width: 520px; margin-top: 48px; display: block; } +.entry-figure .fig-bar { fill: none; stroke: var(--jn-navy-700); stroke-width: 1.5; } +.entry-figure .fig-arc { fill: none; stroke: var(--jn-navy-700); stroke-width: 80; opacity: 0.2; } +.entry-figure .fig-line { fill: none; stroke: var(--jn-gold-500); stroke-width: 1.5; } + +.entry-form-wrap { + grid-area: form; + display: grid; place-items: center; + padding: 48px 40px; + background: var(--jn-bg-panel); +} +.entry-form { width: min(400px, 100%); display: grid; gap: 20px; } +.entry-form header h2 { font-size: 24px; line-height: 32px; font-weight: 600; color: var(--jn-text-1); } +.entry-form header p { margin-top: 6px; font-size: 14px; line-height: 22px; color: var(--jn-text-2); } + +#loginError { + padding: 10px 14px; + border-left: 3px solid var(--jn-error); + border-radius: 8px; + background: var(--jn-error-bg); + color: var(--jn-error); + font-size: 13px; line-height: 18px; +} + +.role-switch { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; } .role-switch label { cursor: pointer; } .role-switch input { position: absolute; opacity: 0; } -.role-switch span { min-height: 83px; display: grid; grid-template-columns: 30px 1fr; align-content: center; gap: 1px 9px; padding: 12px; border: 1px solid var(--color-line); border-radius: var(--radius-md); background: rgba(0, 0, 0, 0.14); transition: border-color var(--duration-fast), background var(--duration-fast), transform var(--duration-fast); } -.role-switch svg { grid-row: 1 / 3; align-self: center; color: var(--color-ink-muted); } -.role-switch small { color: var(--color-ink-muted); } -.role-switch input:checked + span { border-color: rgba(55, 235, 137, 0.4); background: var(--color-primary-wash); transform: translateY(-1px); } -.role-switch input:checked + span svg { color: var(--color-primary); } -.entry-note { font-size: 10px; } +.role-switch span { + min-height: 76px; + display: grid; grid-template-columns: 24px 1fr; + align-content: center; gap: 2px 10px; + padding: 12px 14px; + border: 1px solid var(--jn-border); + border-radius: 8px; + background: var(--jn-bg-panel); + transition: border-color 150ms ease-out, background 150ms ease-out; +} +.role-switch span:hover { border-color: var(--jn-border-strong); } +.role-switch svg { grid-row: 1 / 3; align-self: center; color: var(--jn-text-3); } +.role-switch b { font-size: 15px; line-height: 22px; font-weight: 600; color: var(--jn-text-2); } +.role-switch small { font-size: 12px; line-height: 18px; color: var(--jn-text-3); } +.role-switch input:focus-visible + span { border-color: var(--jn-blue-600); box-shadow: 0 0 0 3px rgba(29, 78, 216, 0.15); } +.role-switch input:checked + span { border: 1.5px solid var(--jn-blue-600); background: var(--jn-blue-50); } +.role-switch input:checked + span svg { color: var(--jn-blue-600); } +.role-switch input:checked + span b { color: var(--jn-blue-600); } + +.entry-form .field { display: flex; flex-direction: column; gap: 8px; } +.entry-form .field > span { font-size: 14px; line-height: 20px; font-weight: 500; color: var(--jn-text-1); } +.entry-form .field input { + width: 100%; height: 44px; + padding: 0 14px; + border: 1px solid var(--jn-border); + border-radius: 8px; + outline: 0; + background: var(--jn-bg-panel); + color: var(--jn-text-1); + font-size: 15px; line-height: 22px; + transition: border-color 150ms ease-out, box-shadow 150ms ease-out; +} +.entry-form .field input::placeholder { color: var(--jn-text-3); } +.entry-form .field input:hover { border-color: var(--jn-border-strong); } +.entry-form .field input:focus { border-color: var(--jn-blue-600); box-shadow: 0 0 0 3px rgba(29, 78, 216, 0.15); } +.entry-form .password-field { + display: grid; grid-template-columns: 1fr 44px; + border: 1px solid var(--jn-border); + border-radius: 8px; + background: var(--jn-bg-panel); + transition: border-color 150ms ease-out, box-shadow 150ms ease-out; +} +.entry-form .password-field:hover { border-color: var(--jn-border-strong); } +.entry-form .password-field:focus-within { border-color: var(--jn-blue-600); box-shadow: 0 0 0 3px rgba(29, 78, 216, 0.15); } +.entry-form .password-field input { border: 0; box-shadow: none; background: transparent; } +.entry-form .password-field input:focus { border: 0; box-shadow: none; } +.entry-form .inside-icon { width: 44px; height: 44px; color: var(--jn-text-3); border: 0; background: transparent; } +.entry-form .inside-icon:hover { color: var(--jn-text-2); background: transparent; transform: none; } +.entry-form .inside-icon svg { width: 20px; height: 20px; } + +.entry-options { display: flex; align-items: center; justify-content: space-between; } +.entry-form .check-field { display: flex; align-items: center; gap: 8px; font-size: 13px; line-height: 18px; color: var(--jn-text-2); cursor: pointer; } +.entry-form .check-field input { width: 16px; height: 16px; accent-color: var(--jn-blue-600); } +.entry-hint { font-size: 13px; line-height: 18px; color: var(--jn-blue-600); } +.entry-hint:hover { color: var(--jn-blue-700); } + +.entry-form .entry-note { font-size: 12px; line-height: 18px; color: var(--jn-text-2); } + +.entry-form .button.primary { + width: 100%; height: 44px; + border-radius: 8px; + background: var(--jn-blue-600); + color: #ffffff; + box-shadow: none; + font-size: 15px; line-height: 22px; font-weight: 600; +} +.entry-form .button.primary:hover { background: var(--jn-blue-700); box-shadow: none; transform: none; } +.entry-form .button.primary:active { background: var(--jn-blue-800); transform: none; } +.entry-form .button.primary:disabled { background: var(--jn-disabled-bg); color: var(--jn-text-3); opacity: 1; cursor: not-allowed; transform: none; } +.entry-form .button.primary.is-loading:disabled { background: var(--jn-blue-600); color: #ffffff; opacity: 0.7; } +.spinner { + width: 16px; height: 16px; flex: 0 0 auto; + display: none; + border: 2px solid rgba(255, 255, 255, 0.35); + border-top-color: #ffffff; + border-radius: 50%; + animation: jn-spin 1s linear infinite; +} +.button.is-loading .spinner { display: inline-block; } +.button.is-loading .submit-arrow { display: none; } +@keyframes jn-spin { to { transform: rotate(360deg); } } + +.entry-compliance { font-size: 12px; line-height: 18px; color: var(--jn-text-3); text-align: center; } + +@media (max-width: 1023px) { + .entry-shell { grid-template-columns: 1fr; grid-template-rows: 56px 180px minmax(0, 1fr); grid-template-areas: "topbar" "context" "form"; } + .entry-context { padding: 32px 40px; justify-content: center; } + .entry-statement h1 { font-size: 24px; line-height: 32px; } + .entry-figure { display: none; } + .entry-form-wrap { padding: 48px 40px; } + .entry-form { width: min(440px, 100%); } +} + +@media (max-width: 767px) { + .entry-shell { grid-template-rows: 56px 96px minmax(0, 1fr); } + .entry-topbar { padding: 0 16px; } + .entry-seal { width: 24px; height: 24px; font-size: 14px; border-radius: 6px; } + .entry-system-name { font-size: 15px; line-height: 22px; } + .entry-context { padding: 24px; } + .entry-statement h1 { font-size: 18px; line-height: 26px; } + .entry-statement p { display: none; } + .entry-form-wrap { padding: 24px 16px; } + .entry-form { gap: 16px; } + .entry-form .field input { height: 48px; } + .entry-form .password-field { grid-template-columns: 1fr 48px; } + .entry-form .inside-icon { width: 48px; height: 48px; } + .entry-form .button.primary { height: 48px; } + .role-switch { grid-template-columns: 1fr; } +} @media (max-width: 1180px) { .app-shell { grid-template-columns: 88px minmax(0, 1fr); } @@ -494,9 +679,6 @@ main { width: min(1560px, 100%); margin: 0 auto; padding: 12px 32px 58px; } .subject-strip { grid-template-columns: repeat(3, 1fr); } .work-progress { grid-template-columns: 1fr 24px 1fr; row-gap: 16px; } .work-progress i:nth-of-type(2) { display: none; } - .entry-shell { grid-template-columns: 1fr; } - .entry-context { min-height: 58vh; border-right: 0; border-bottom: 1px solid var(--color-line); } - .entry-form-wrap { min-height: auto; } } @media (max-width: 720px) { @@ -570,12 +752,6 @@ main { width: min(1560px, 100%); margin: 0 auto; padding: 12px 32px 58px; } .form-grid { grid-template-columns: 1fr; } .toast-region { right: 12px; bottom: 12px; left: 12px; } .toast { min-width: 0; max-width: none; } - .entry-context { min-height: auto; padding: 30px 22px; } - .entry-statement { margin: 54px 0 42px; } - .entry-statement h1 { font-size: 39px; } - .entry-facts { grid-template-columns: 1fr; } - .entry-form-wrap { padding: 32px 16px 48px; } - .entry-form { padding: 22px; } } @media (max-width: 460px) { @@ -583,7 +759,6 @@ main { width: min(1560px, 100%); margin: 0 auto; padding: 12px 32px 58px; } .metric-copy { min-height: 52px; } .metric-label { font-size: 11px; } .metric-value { font-size: 23px; } - .role-switch { grid-template-columns: 1fr; } } @media (max-width: 1180px) { @@ -715,24 +890,7 @@ body::before { content: ""; position: fixed; inset: 0; z-index: 0; pointer-event .table-scroll { padding: 2px 14px 8px; } .table-summary { margin: 0 14px; } -/* ===== 登录页重做:居中集团登录卡 ===== */ -.entry-shell { display: grid; grid-template-columns: 1fr; place-items: center; min-height: 100vh; padding: 48px 20px; } -.entry-card { position: relative; width: min(470px, 100%); overflow: hidden; border: 1px solid rgba(255, 255, 255, 0.13); border-radius: var(--radius-xl); background: linear-gradient(165deg, rgba(36, 36, 36, 0.9) 0%, rgba(16, 16, 16, 0.92) 60%, rgba(10, 10, 10, 0.94) 100%); box-shadow: var(--shadow-panel), 0 0 60px rgba(55, 235, 137, 0.06); backdrop-filter: blur(28px) saturate(125%); } -.entry-card::before { content: ""; position: absolute; inset: 0; background: radial-gradient(150% 110% at 50% 118%, rgba(255, 255, 255, 0.07), transparent 55%), linear-gradient(165deg, rgba(255, 255, 255, 0.12) 0%, rgba(255, 255, 255, 0.03) 42%, transparent 70%); pointer-events: none; } -.entry-card::after { content: ""; position: absolute; top: 0; left: 18%; right: 18%; height: 2px; background: linear-gradient(90deg, transparent, rgba(55, 235, 137, 0.65), transparent); } -.entry-brand { flex-direction: column; justify-content: center; gap: 15px; min-height: 0; padding: 36px 28px 24px; border-bottom: 1px solid var(--color-line); text-align: center; } -.entry-brand .brand-mark { width: 54px; height: 54px; border-radius: 17px; font-size: 26px; } -.entry-brand > span:last-child { align-items: center; } -.entry-brand strong { font-size: 21px; letter-spacing: 0.03em; } -.entry-brand small { margin-top: 4px; font-size: 12px; letter-spacing: 0.08em; } -.entry-form { width: 100%; gap: 16px; padding: 24px 28px 10px; border: 0; background: transparent; box-shadow: none; backdrop-filter: none; } -.entry-form header { text-align: center; } -.entry-form header h2 { font-size: 22px; } -.entry-form header p { margin-top: 4px; color: var(--color-ink-muted); font-size: 12px; } -.entry-facts { max-width: none; gap: 10px; padding: 16px 28px 28px; } -.entry-facts div { padding: 12px; text-align: center; } -.entry-facts dd { margin-top: 2px; font-size: 12px; } - @media (prefers-reduced-motion: reduce) { *, *::before, *::after { scroll-behavior: auto !important; animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; } + .button.is-loading .spinner { animation-duration: 1s !important; animation-iteration-count: infinite !important; } } -- 2.54.0