From 71fc51f84f33b9b3f614b3d09b11c0675bfdc172 Mon Sep 17 00:00:00 2001 From: yelan Date: Thu, 27 Aug 2026 13:51:31 +0800 Subject: [PATCH] =?UTF-8?q?refactor(web):=20=E5=B0=86=E5=85=A8=E5=B1=80?= =?UTF-8?q?=E6=A0=B7=E5=BC=8F=E8=BF=81=E7=A7=BB=E4=B8=BA=E7=BB=84=E4=BB=B6?= =?UTF-8?q?=E7=BA=A7=E6=A0=B7=E5=BC=8F=E5=B9=B6=E6=8A=BD=E5=8F=96=E5=8D=A0?= =?UTF-8?q?=E4=BD=8D=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/PagePlaceholder.vue | 72 +++ .../src/components/layout/Container.vue | 15 + clinical-web/src/components/layout/Header.vue | 71 +++ clinical-web/src/components/layout/Menu.vue | 156 ++++++ clinical-web/src/layouts/ClinicalLayout.vue | 17 + clinical-web/src/styles/index.css | 456 ------------------ clinical-web/src/views/auth/LoginView.vue | 154 ++++++ .../views/consent-tasks/ConsentTasksView.vue | 18 +- .../src/views/dashboard/DashboardView.vue | 18 +- .../DocumentPermissionsView.vue | 18 +- .../src/views/documents/DocumentsView.vue | 18 +- .../src/views/reports/ReportsView.vue | 18 +- .../src/views/settings/SettingsView.vue | 18 +- .../src/views/users/UserPermissionsView.vue | 18 +- 14 files changed, 555 insertions(+), 512 deletions(-) create mode 100644 clinical-web/src/components/PagePlaceholder.vue diff --git a/clinical-web/src/components/PagePlaceholder.vue b/clinical-web/src/components/PagePlaceholder.vue new file mode 100644 index 0000000..cf2b14a --- /dev/null +++ b/clinical-web/src/components/PagePlaceholder.vue @@ -0,0 +1,72 @@ + + + + + diff --git a/clinical-web/src/components/layout/Container.vue b/clinical-web/src/components/layout/Container.vue index 4689a1e..57e9849 100644 --- a/clinical-web/src/components/layout/Container.vue +++ b/clinical-web/src/components/layout/Container.vue @@ -3,3 +3,18 @@ + + diff --git a/clinical-web/src/components/layout/Header.vue b/clinical-web/src/components/layout/Header.vue index 4beb964..be5ea95 100644 --- a/clinical-web/src/components/layout/Header.vue +++ b/clinical-web/src/components/layout/Header.vue @@ -30,3 +30,74 @@ const pageGroup = computed(() => String(route.meta.group ?? '工作台')) {{ appStore.environment }} + + diff --git a/clinical-web/src/components/layout/Menu.vue b/clinical-web/src/components/layout/Menu.vue index c4cc8bd..2274a85 100644 --- a/clinical-web/src/components/layout/Menu.vue +++ b/clinical-web/src/components/layout/Menu.vue @@ -94,3 +94,159 @@ function handleLogout() { + + diff --git a/clinical-web/src/layouts/ClinicalLayout.vue b/clinical-web/src/layouts/ClinicalLayout.vue index 84ffaed..5494abc 100644 --- a/clinical-web/src/layouts/ClinicalLayout.vue +++ b/clinical-web/src/layouts/ClinicalLayout.vue @@ -17,3 +17,20 @@ import Menu from '@/components/layout/Menu.vue' + + diff --git a/clinical-web/src/styles/index.css b/clinical-web/src/styles/index.css index b92185e..225ade4 100644 --- a/clinical-web/src/styles/index.css +++ b/clinical-web/src/styles/index.css @@ -61,464 +61,8 @@ a { background: transparent; } -/* 主框架:侧边菜单 + 顶部 header + 内容 container */ -.clinical-layout { - display: flex; - width: 100%; - min-height: 100vh; - background: var(--bg); -} - -.clinical-main { - display: flex; - flex: 1; - flex-direction: column; - min-width: 0; - min-height: 100vh; -} - -.clinical-menu { - display: flex; - flex: 0 0 var(--sidebar-width); - flex-direction: column; - width: var(--sidebar-width); - color: #c8dde6; - background: var(--side); -} - -.menu-brand { - display: flex; - flex-shrink: 0; - gap: 10px; - align-items: center; - padding: 18px 16px 16px; - border-bottom: 1px solid rgb(255 255 255 / 8%); -} - -.menu-brand-icon { - display: grid; - flex-shrink: 0; - width: 34px; - height: 34px; - place-items: center; - border-radius: 9px; - background: linear-gradient(135deg, #18a0c0, var(--brand)); -} - -.menu-brand-copy strong, -.menu-brand-copy span { - display: block; -} - -.menu-brand-copy strong { - color: #fff; - font-size: 16px; - letter-spacing: 1px; -} - -.menu-brand-copy span { - color: #8fb3c2; - font-size: 10px; - letter-spacing: 1px; -} - -.menu-nav { - flex: 1; - padding: 12px 10px; - overflow-y: auto; -} - -.menu-group-title { - padding: 10px 10px 6px; - color: #7ba2b3; - font-size: 11px; - letter-spacing: 1px; -} - -.menu-item { - display: flex; - gap: 10px; - align-items: center; - margin-bottom: 2px; - padding: 10px 12px; - color: #c8dde6; - font-size: 13.5px; - text-decoration: none; - border-radius: 8px; - transition: - color 0.15s ease, - background 0.15s ease; -} - -.menu-item:hover { - color: #fff; - background: rgb(255 255 255 / 7%); -} - -.menu-item.is-active { - color: #fff; - font-weight: 700; - background: var(--brand); -} - -.menu-dot { - flex-shrink: 0; - width: 6px; - height: 6px; - background: transparent; - border-radius: 50%; -} - -.menu-item.is-active .menu-dot { - background: #5ee0a8; -} - -.menu-profile { - display: flex; - flex-shrink: 0; - gap: 10px; - align-items: center; - padding: 14px 16px; - border-top: 1px solid rgb(255 255 255 / 8%); -} - -.menu-profile-avatar { - display: grid; - flex-shrink: 0; - width: 34px; - height: 34px; - color: #fff; - font-size: 14px; - font-weight: 700; - place-items: center; - border-radius: 50%; - background: #18a0c0; -} - -.menu-profile-copy { - min-width: 0; -} - -.menu-profile-copy strong, -.menu-profile-copy span { - display: block; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.menu-profile-copy strong { - color: #fff; - font-size: 13px; -} - -.menu-profile-copy span { - margin-top: 2px; - color: #8fb3c2; - font-size: 11px; -} - -.menu-logout { - flex-shrink: 0; - margin-left: auto; - padding: 0; - color: #8fb3c2; - font-size: 11px; - background: transparent; -} - -.menu-logout:hover { - color: #fff; -} - -/* 原型中的顶部 header */ -.clinical-header { - display: flex; - flex-shrink: 0; - gap: 14px; - align-items: center; - height: var(--header-height); - padding: 0 20px; - background: #fff; - border-bottom: 1px solid var(--line); -} - -.header-page { - display: flex; - gap: 14px; - align-items: baseline; - min-width: 0; -} - -.header-title { - flex-shrink: 0; - color: var(--ink); - font-size: 16px; - font-weight: 700; -} - -.header-breadcrumb { - overflow: hidden; - color: var(--mut); - font-size: 12px; - text-overflow: ellipsis; - white-space: nowrap; -} - -.header-spacer { - flex: 1; -} - -.campus-selector { - display: flex; - flex-shrink: 0; - gap: 6px; - align-items: center; -} - -.campus-label { - color: var(--mut); - font-size: 12px; -} - -.campus-selector select { - width: auto; - padding: 4px 8px; - color: var(--brand-d); - font-size: 12.5px; - font-weight: 700; - background: var(--brand-l); - border: 1px solid var(--brand); - border-radius: 6px; -} - -.environment-badge { - flex-shrink: 0; - padding: 3px 8px; - color: var(--warn); - font-size: 11px; - background: var(--warn-l); - border-radius: 20px; -} - -/* container 只负责滚动和内边距,页面内容由各 View 提供 */ -.clinical-container { - flex: 1; - min-height: 0; - padding: 18px 20px; - overflow-y: auto; -} - -.page-section { - width: 100%; - max-width: 1440px; - margin: 0 auto; -} - -.page-placeholder { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - min-height: 380px; - padding: 48px 32px; - text-align: center; - background: var(--card); - border-radius: var(--r); - box-shadow: var(--sh); -} - -.placeholder-mark { - display: grid; - width: 54px; - height: 54px; - margin-bottom: 18px; - color: var(--brand); - font-size: 24px; - place-items: center; - background: var(--brand-l); - border-radius: 14px; -} - -.eyebrow { - margin-bottom: 6px; - color: var(--brand); - font-size: 11px; - font-weight: 700; - letter-spacing: 1px; -} - -.placeholder-title { - margin: 0; - color: var(--ink); - font-size: 22px; -} - -.placeholder-copy { - margin-top: 10px; - color: var(--mut); - font-size: 13px; -} - -@media (max-width: 1200px) { - .clinical-container { - padding: 16px; - } -} - -/* 原型登录页 */ -.login-page { - position: fixed; - inset: 0; - display: flex; - align-items: center; - justify-content: center; - background: var(--login-gradient); -} - -.login-card { - width: 380px; - padding: 30px 36px; - background: #fff; - border-radius: 14px; - box-shadow: var(--sh-login); -} - -.login-brand { - display: flex; - gap: 12px; - align-items: center; - justify-content: center; - margin-bottom: 8px; -} - -.login-brand-icon { - display: grid; - width: 46px; - height: 46px; - place-items: center; - border-radius: 12px; - background: linear-gradient(135deg, var(--brand), #18a0c0); -} - -.login-brand h1 { - margin: 0; - color: var(--ink); - font-size: 22px; - letter-spacing: 1px; -} - -.login-brand p { - margin: 2px 0 0; - color: #8aa7b3; - font-size: 11px; - letter-spacing: 2px; -} - -.login-subtitle { - margin: 0 0 20px; - color: var(--mut); - font-size: 12px; - text-align: center; -} - -.login-field { - margin-bottom: 10px; -} - -.login-field label { - display: block; - margin-bottom: 6px; - color: var(--mut); - font-size: 12px; -} - -.login-field input { - width: 100%; - padding: 7px 10px; - color: var(--ink); - font-size: 13px; - background: #fff; - border: 1px solid var(--line); - border-radius: 6px; - outline: none; -} - -.login-field input:focus { - border-color: var(--brand); -} - -.login-captcha-row { - display: flex; - gap: 8px; - align-items: center; -} - -.login-captcha-row input { - flex: 1; -} - -.login-captcha-image { - flex-shrink: 0; - padding: 8px 14px; - color: #5c7d8a; - font-size: 13px; - font-style: italic; - font-weight: 700; - letter-spacing: 6px; - user-select: none; - background: linear-gradient(120deg, #dfeef3, #c8dfe8); - border-radius: 6px; -} - -.login-error { - margin: -4px 0 10px; - color: var(--err); - font-size: 12px; -} - -.login-submit { - width: 100%; - margin-top: 6px; - padding: 9px; - color: #fff; - font-size: 13px; - font-weight: 700; - background: var(--brand); - border-radius: 7px; -} - -.login-submit:hover { - background: var(--brand-d); -} - -.login-tip { - margin: 12px 0 0; - padding: 7px; - color: var(--mut); - font-size: 12px; - text-align: center; - background: var(--brand-l); - border-radius: 8px; -} - -.login-footer { - position: absolute; - bottom: 18px; - width: 100%; - margin: 0; - color: rgb(255 255 255 / 55%); - font-size: 12px; - text-align: center; -} - @media (max-width: 520px) { body { min-width: 0; } - - .login-card { - width: calc(100% - 32px); - padding: 32px 24px; - } } diff --git a/clinical-web/src/views/auth/LoginView.vue b/clinical-web/src/views/auth/LoginView.vue index dc75414..df853a1 100644 --- a/clinical-web/src/views/auth/LoginView.vue +++ b/clinical-web/src/views/auth/LoginView.vue @@ -111,3 +111,157 @@ function handleLogin() { + + diff --git a/clinical-web/src/views/consent-tasks/ConsentTasksView.vue b/clinical-web/src/views/consent-tasks/ConsentTasksView.vue index 73d5557..d233180 100644 --- a/clinical-web/src/views/consent-tasks/ConsentTasksView.vue +++ b/clinical-web/src/views/consent-tasks/ConsentTasksView.vue @@ -1,10 +1,12 @@ + + diff --git a/clinical-web/src/views/dashboard/DashboardView.vue b/clinical-web/src/views/dashboard/DashboardView.vue index 6fe0773..fb93302 100644 --- a/clinical-web/src/views/dashboard/DashboardView.vue +++ b/clinical-web/src/views/dashboard/DashboardView.vue @@ -1,10 +1,12 @@ + + diff --git a/clinical-web/src/views/document-permissions/DocumentPermissionsView.vue b/clinical-web/src/views/document-permissions/DocumentPermissionsView.vue index cd4b4d9..a916892 100644 --- a/clinical-web/src/views/document-permissions/DocumentPermissionsView.vue +++ b/clinical-web/src/views/document-permissions/DocumentPermissionsView.vue @@ -1,10 +1,12 @@ + + diff --git a/clinical-web/src/views/documents/DocumentsView.vue b/clinical-web/src/views/documents/DocumentsView.vue index add5060..707c6de 100644 --- a/clinical-web/src/views/documents/DocumentsView.vue +++ b/clinical-web/src/views/documents/DocumentsView.vue @@ -1,10 +1,12 @@ + + diff --git a/clinical-web/src/views/reports/ReportsView.vue b/clinical-web/src/views/reports/ReportsView.vue index 27e9bd8..afacc51 100644 --- a/clinical-web/src/views/reports/ReportsView.vue +++ b/clinical-web/src/views/reports/ReportsView.vue @@ -1,10 +1,12 @@ + + diff --git a/clinical-web/src/views/settings/SettingsView.vue b/clinical-web/src/views/settings/SettingsView.vue index fd71f50..77f5ede 100644 --- a/clinical-web/src/views/settings/SettingsView.vue +++ b/clinical-web/src/views/settings/SettingsView.vue @@ -1,10 +1,12 @@ + + diff --git a/clinical-web/src/views/users/UserPermissionsView.vue b/clinical-web/src/views/users/UserPermissionsView.vue index 46b8276..b01dedf 100644 --- a/clinical-web/src/views/users/UserPermissionsView.vue +++ b/clinical-web/src/views/users/UserPermissionsView.vue @@ -1,10 +1,12 @@ + +