feat(system): 登录页重做、布局白化与首页 Bento 仪表盘(视觉体系统一落地)
- 登录页:雾灰点阵底 + 右上涟漪同心圆 + 顶部靛蓝天光;居中纸白卡片(品牌区/欢迎回来/表单);逻辑不变 - BasicLayout:侧栏深色面板改为中性灰微渐变 + 白底浮起当前项(左 2px 靛蓝条);logo 区水线;内容区雾灰点阵 - 首页:Bento Grid 仪表盘(参数 16 项/岗位 3 个为真实数据;绩效/回款/待办为业务上线前的精致空态) - AppMenu:激活项白底浮起样式,菜单变量随浅色侧栏调整 Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
1 parent
4c442b8cf2
commit
d7fbec1177
5 files changed
+545
-292
No files matched your search
+149
-233
@@ -77,53 +77,29 @@ onMounted(refreshCaptcha)
|
||||
|
||||
<template>
|
||||
<div class="login">
|
||||
<!-- 品牌面板:以「水」为意象 —— 公司名衍水,业务是流水之账 -->
|
||||
<section class="brand">
|
||||
<!-- 水纹层理:越往下越密,如潜向深处。纯装饰,对读屏隐藏 -->
|
||||
<svg class="brand-flow" viewBox="0 0 600 1000" preserveAspectRatio="xMidYMid slice" aria-hidden="true">
|
||||
<path class="brand-flow__line" style="--i: 0" d="M-40,150 C 150,95 260,205 420,155 S 620,95 660,120" />
|
||||
<path class="brand-flow__line" style="--i: 1" d="M-40,265 C 170,200 300,320 460,255 S 630,190 660,215" />
|
||||
<path class="brand-flow__line" style="--i: 2" d="M-40,372 C 160,318 320,420 470,360 S 640,300 660,320" />
|
||||
<path class="brand-flow__line" style="--i: 3" d="M-40,470 C 180,428 310,510 480,462 S 645,410 660,425" />
|
||||
<path class="brand-flow__line" style="--i: 4" d="M-40,562 C 150,532 330,596 470,560 S 640,520 660,530" />
|
||||
<path class="brand-flow__line" style="--i: 5" d="M-40,650 C 190,626 300,678 490,648 S 650,618 660,624" />
|
||||
<path class="brand-flow__line" style="--i: 6" d="M-40,732 C 160,714 320,752 460,730 S 640,708 660,712" />
|
||||
<path class="brand-flow__line" style="--i: 7" d="M-40,810 C 175,798 305,826 485,808 S 645,792 660,795" />
|
||||
<path class="brand-flow__line" style="--i: 8" d="M-40,882 C 155,873 330,894 470,880 S 645,868 660,870" />
|
||||
<path class="brand-flow__line" style="--i: 9" d="M-40,946 C 185,939 300,955 490,944 S 650,934 660,935" />
|
||||
</svg>
|
||||
<!-- 背景装饰:右上涟漪同心圆(「衍水」品牌意象);顶部天光由 .login::before 承担 -->
|
||||
<div class="login-ripple" aria-hidden="true">
|
||||
<i></i><i></i><i></i><i></i>
|
||||
</div>
|
||||
|
||||
<!-- 品牌内容整体居中成块。此前用 space-between 把品牌与标语顶到两端,
|
||||
中间空出大片,两处都成了孤岛;聚成一块才有构图 -->
|
||||
<div class="brand-inner">
|
||||
<div class="brand-block">
|
||||
<h1 class="brand-name">衍水集团</h1>
|
||||
<hr class="brand-rule" />
|
||||
<p class="brand-system">营销人员工资管理系统</p>
|
||||
|
||||
<!-- 断行位置显式控制:中文可在任意字间断行,交给浏览器自动换行
|
||||
会把「楚」这样的单字挤到末行 -->
|
||||
<p class="brand-hero">
|
||||
<span>每一笔回款,</span>
|
||||
<span>都算得清楚</span>
|
||||
</p>
|
||||
<p class="brand-stages">回款 · 计提 · 核算 · 发放</p>
|
||||
<div class="login-wrap">
|
||||
<div class="login-card">
|
||||
<div class="card-brand">
|
||||
<div class="card-brand__name">衍水集团</div>
|
||||
<p class="card-brand__slogan">把每一笔回款,算成一份踏实。</p>
|
||||
<span class="waterline"></span>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 表单面板 -->
|
||||
<section class="panel">
|
||||
<div class="panel-inner">
|
||||
<h2 class="panel-title">登录</h2>
|
||||
<p class="panel-hint">请使用管理员分配的账号</p>
|
||||
<div class="card-head">
|
||||
<h2 class="card-title">欢迎回来</h2>
|
||||
<p class="card-hint">请输入账号密码进入系统</p>
|
||||
</div>
|
||||
|
||||
<el-form
|
||||
ref="formRef"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
label-position="top"
|
||||
size="large"
|
||||
@keyup.enter="handleSubmit"
|
||||
>
|
||||
<el-form-item label="用户名" prop="username">
|
||||
@@ -173,175 +149,149 @@ onMounted(refreshCaptcha)
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<p class="panel-foot">衍水集团 · 内部系统</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<p class="login-foot">© 衍水集团 · 内部系统</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
/*
|
||||
* 配色:品牌 token 已提升为全局(见 assets/styles/index.css,布局框架与
|
||||
* 系统管理页面共用),此处只做局部别名,用法与取值均与原先一致。
|
||||
*/
|
||||
/* 视觉体系(2026-10-12 确认):企业级扁平 · 轻质感 · 品牌色点缀 · 微动效 */
|
||||
.login {
|
||||
--ink-900: var(--ys-ink-900);
|
||||
--ink-800: var(--ys-ink-800);
|
||||
--ink-700: var(--ys-ink-700);
|
||||
--ink-600: var(--ys-ink-600);
|
||||
--gold-bright: var(--ys-gold-bright);
|
||||
--gold-deep: var(--ys-gold-deep);
|
||||
--paper: var(--ys-paper);
|
||||
--text: var(--ys-text);
|
||||
--muted: var(--ys-muted);
|
||||
|
||||
display: flex;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/* ============ 品牌面板 ============ */
|
||||
|
||||
.brand {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex: 1 1 56%;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 100vh;
|
||||
padding: 40px 24px;
|
||||
overflow: hidden;
|
||||
background: linear-gradient(158deg, var(--ink-800) 0%, var(--ink-900) 62%, #04141b 100%);
|
||||
background-color: #f2f4f8;
|
||||
/* 点阵网格:秩序与密度 */
|
||||
background-image: radial-gradient(rgba(28, 35, 51, 0.07) 1px, transparent 1px);
|
||||
background-size: 24px 24px;
|
||||
}
|
||||
|
||||
/* 水下的光:给居中的内容一个落点,否则深色面板会显得空 */
|
||||
.brand::before {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
/* 顶部天光:靛蓝微光从上方洒下,给页面空气感 */
|
||||
.login::before {
|
||||
content: '';
|
||||
background: radial-gradient(58% 46% at 32% 46%, rgb(32 116 146 / 26%), transparent 72%);
|
||||
position: absolute;
|
||||
top: -180px;
|
||||
left: 50%;
|
||||
width: 900px;
|
||||
height: 480px;
|
||||
transform: translateX(-50%);
|
||||
pointer-events: none;
|
||||
background: radial-gradient(closest-side, rgba(46, 75, 168, 0.09), rgba(46, 75, 168, 0));
|
||||
}
|
||||
|
||||
/* 右上涟漪:同心圆水波,部分出画 */
|
||||
.login-ripple {
|
||||
position: absolute;
|
||||
top: -190px;
|
||||
right: -150px;
|
||||
width: 560px;
|
||||
height: 560px;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.brand-flow {
|
||||
.login-ripple i {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
border: 1px solid rgba(46, 75, 168, 0.1);
|
||||
}
|
||||
|
||||
.brand-flow__line {
|
||||
fill: none;
|
||||
stroke: var(--ink-600);
|
||||
stroke-width: 1;
|
||||
opacity: 0.55;
|
||||
/* 逐条画出:一个统一的入场动作,而非散落特效 */
|
||||
stroke-dasharray: 1200;
|
||||
stroke-dashoffset: 1200;
|
||||
animation: flow-draw 2.4s cubic-bezier(0.22, 0.61, 0.36, 1) forwards;
|
||||
animation-delay: calc(var(--i) * 0.13s);
|
||||
.login-ripple i:nth-child(2) {
|
||||
inset: 70px;
|
||||
border-color: rgba(46, 75, 168, 0.075);
|
||||
}
|
||||
|
||||
@keyframes flow-draw {
|
||||
to {
|
||||
stroke-dashoffset: 0;
|
||||
}
|
||||
.login-ripple i:nth-child(3) {
|
||||
inset: 140px;
|
||||
border-color: rgba(46, 75, 168, 0.055);
|
||||
}
|
||||
|
||||
.brand-inner {
|
||||
.login-ripple i:nth-child(4) {
|
||||
inset: 210px;
|
||||
border: none;
|
||||
background: radial-gradient(circle, rgba(46, 75, 168, 0.05), rgba(46, 75, 168, 0.015));
|
||||
}
|
||||
|
||||
.login-wrap {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
padding: 56px clamp(40px, 6vw, 104px);
|
||||
}
|
||||
|
||||
/* 内容成块并限宽:超宽屏下文字块不会被拉散 */
|
||||
.brand-block {
|
||||
max-width: 30rem;
|
||||
/* 登录卡:纸白微渐变 + 半透明描边 + 分层阴影 + 入场上浮 */
|
||||
.login-card {
|
||||
width: 400px;
|
||||
max-width: 100%;
|
||||
padding: 30px 36px 32px;
|
||||
overflow: hidden;
|
||||
animation: card-rise 320ms cubic-bezier(0.25, 0.1, 0.25, 1) backwards;
|
||||
background: linear-gradient(180deg, #ffffff, #fcfcfe);
|
||||
border: 1px solid rgba(28, 35, 51, 0.09);
|
||||
border-radius: 14px;
|
||||
box-shadow:
|
||||
0 2px 4px rgba(28, 35, 51, 0.04),
|
||||
0 16px 40px rgba(28, 35, 51, 0.1);
|
||||
}
|
||||
|
||||
.brand-name {
|
||||
margin: 0;
|
||||
font-family: 'Source Han Serif SC', 'Noto Serif SC', 'Songti SC', 'SimSun', serif;
|
||||
font-size: clamp(36px, 3.6vw, 54px);
|
||||
font-weight: 600;
|
||||
line-height: 1.15;
|
||||
letter-spacing: 0.2em;
|
||||
color: #f2f6f7;
|
||||
}
|
||||
|
||||
.brand-rule {
|
||||
width: 52px;
|
||||
height: 2px;
|
||||
margin: 24px 0 18px;
|
||||
background-color: var(--gold-bright);
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.brand-system {
|
||||
margin: 0;
|
||||
font-size: clamp(13px, 1.1vw, 16px);
|
||||
font-weight: 300;
|
||||
letter-spacing: 0.28em;
|
||||
color: #9db6c0;
|
||||
}
|
||||
|
||||
.brand-hero {
|
||||
margin: 58px 0 0;
|
||||
font-size: clamp(16px, 1.4vw, 21px);
|
||||
font-weight: 400;
|
||||
line-height: 1.8;
|
||||
letter-spacing: 0.06em;
|
||||
color: #d9e5ea;
|
||||
}
|
||||
|
||||
.brand-hero span {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* 三个业务环节:用间隔点连成一行,比带框的标签轻得多,
|
||||
也不会被误读成可点击的按钮 */
|
||||
.brand-stages {
|
||||
margin: 18px 0 0;
|
||||
font-size: 12px;
|
||||
letter-spacing: 0.24em;
|
||||
color: #6f8b97;
|
||||
}
|
||||
|
||||
/* ============ 表单面板 ============ */
|
||||
|
||||
.panel {
|
||||
display: flex;
|
||||
flex: 1 1 44%;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 48px clamp(28px, 5vw, 80px);
|
||||
background-color: var(--paper);
|
||||
}
|
||||
|
||||
.panel-inner {
|
||||
width: 100%;
|
||||
max-width: 356px;
|
||||
animation: panel-rise 0.7s cubic-bezier(0.22, 0.61, 0.36, 1) 0.35s both;
|
||||
}
|
||||
|
||||
@keyframes panel-rise {
|
||||
@keyframes card-rise {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(14px);
|
||||
transform: translateY(8px);
|
||||
}
|
||||
}
|
||||
|
||||
.panel-title {
|
||||
margin: 0 0 6px;
|
||||
font-size: 25px;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.16em;
|
||||
color: var(--text);
|
||||
.card-brand {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.panel-hint {
|
||||
margin: 0 0 30px;
|
||||
font-size: 13px;
|
||||
color: var(--muted);
|
||||
.card-brand__name {
|
||||
font-family: var(--ys-font-brand);
|
||||
font-size: 17px;
|
||||
font-weight: 500;
|
||||
letter-spacing: 0.34em;
|
||||
color: var(--ys-ink);
|
||||
}
|
||||
|
||||
.card-brand__slogan {
|
||||
margin-top: 8px;
|
||||
font-size: 12.5px;
|
||||
letter-spacing: 0.02em;
|
||||
color: var(--ys-ink-3);
|
||||
}
|
||||
|
||||
/* 签名元素:渐隐靛蓝水线 */
|
||||
.waterline {
|
||||
display: block;
|
||||
width: 40px;
|
||||
height: 2px;
|
||||
margin: 14px auto 0;
|
||||
border-radius: 1px;
|
||||
background: linear-gradient(90deg, var(--ys-indigo), rgba(46, 75, 168, 0));
|
||||
}
|
||||
|
||||
.card-head {
|
||||
margin-top: 26px;
|
||||
}
|
||||
|
||||
.card-title {
|
||||
margin: 0;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
color: var(--ys-ink);
|
||||
}
|
||||
|
||||
.card-hint {
|
||||
margin: 4px 0 0;
|
||||
font-size: 12px;
|
||||
color: var(--ys-ink-3);
|
||||
}
|
||||
|
||||
.captcha {
|
||||
@@ -370,14 +320,15 @@ onMounted(refreshCaptcha)
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
background-color: #fff;
|
||||
border: 1px solid #dcdfe6;
|
||||
border-radius: 4px;
|
||||
transition: border-color 0.2s;
|
||||
background: linear-gradient(180deg, #f7f8fb, #f1f3f8);
|
||||
border: 1px solid var(--ys-line);
|
||||
border-radius: 7px;
|
||||
box-shadow: inset 0 1px 2px rgba(28, 35, 51, 0.04);
|
||||
transition: border-color 150ms var(--ys-ease, ease);
|
||||
}
|
||||
|
||||
.captcha__image:hover {
|
||||
border-color: var(--gold-deep);
|
||||
border-color: var(--ys-indigo);
|
||||
}
|
||||
|
||||
.captcha__image img {
|
||||
@@ -389,89 +340,54 @@ onMounted(refreshCaptcha)
|
||||
|
||||
.captcha__placeholder {
|
||||
font-size: 12px;
|
||||
color: var(--muted);
|
||||
color: var(--ys-ink-3);
|
||||
}
|
||||
|
||||
.form-actions :deep(.el-form-item__content) {
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
/* 覆盖 Element Plus 的按钮变量而非直接写 background-color ——
|
||||
后者与 .el-button--primary 同权重,会受样式注入顺序影响而不稳定 */
|
||||
.submit {
|
||||
width: 100%;
|
||||
letter-spacing: 0.4em;
|
||||
--el-button-bg-color: var(--gold-deep);
|
||||
--el-button-border-color: var(--gold-deep);
|
||||
--el-button-hover-bg-color: #a3762a;
|
||||
--el-button-hover-border-color: #a3762a;
|
||||
--el-button-active-bg-color: #7d5719;
|
||||
--el-button-active-border-color: #7d5719;
|
||||
}
|
||||
|
||||
.panel-foot {
|
||||
margin: 32px 0 0;
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
letter-spacing: 0.1em;
|
||||
color: #9aa8af;
|
||||
.login-foot {
|
||||
margin: 16px 0 0;
|
||||
font-size: 11px;
|
||||
letter-spacing: 0.08em;
|
||||
color: var(--ys-ink-3);
|
||||
}
|
||||
|
||||
/* 输入框聚焦态也落在同一套配色上 */
|
||||
.panel :deep(.el-input__wrapper) {
|
||||
--el-input-focus-border-color: var(--gold-deep);
|
||||
/* 输入聚焦落在体系主色上(Element Plus 主色已随全局 token 换为靛蓝) */
|
||||
.login :deep(.el-input__wrapper) {
|
||||
box-shadow: 0 0 0 1px rgba(28, 35, 51, 0.13) inset;
|
||||
}
|
||||
|
||||
/* ============ 响应式 ============ */
|
||||
.login :deep(.el-input__wrapper.is-focus) {
|
||||
box-shadow:
|
||||
0 0 0 1px var(--ys-indigo) inset,
|
||||
0 0 0 3px rgba(46, 75, 168, 0.13);
|
||||
}
|
||||
|
||||
@media (max-width: 900px) {
|
||||
@media (max-width: 640px) {
|
||||
.login {
|
||||
flex-direction: column;
|
||||
padding: 24px 16px;
|
||||
}
|
||||
|
||||
.brand {
|
||||
flex: 0 0 auto;
|
||||
padding: 36px 26px 32px;
|
||||
.login-card {
|
||||
padding: 26px 24px 28px;
|
||||
}
|
||||
|
||||
.brand-inner {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.brand-flow {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.brand-name {
|
||||
font-size: 30px;
|
||||
letter-spacing: 0.16em;
|
||||
}
|
||||
|
||||
.brand-rule {
|
||||
margin: 16px 0 12px;
|
||||
}
|
||||
|
||||
/* 窄屏上只留品牌识别,标语与环节行让位给表单 */
|
||||
.brand-hero,
|
||||
.brand-stages {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.panel {
|
||||
flex: 1;
|
||||
padding: 38px 26px 46px;
|
||||
/* 窄屏上涟漪出画更多,避免挤压卡片 */
|
||||
.login-ripple {
|
||||
top: -260px;
|
||||
right: -240px;
|
||||
}
|
||||
}
|
||||
|
||||
/* 尊重系统的「减弱动效」偏好:保留终态,去掉过渡 */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.brand-flow__line {
|
||||
stroke-dashoffset: 0;
|
||||
animation: none;
|
||||
}
|
||||
|
||||
.panel-inner {
|
||||
opacity: 1;
|
||||
.login-card {
|
||||
animation: none;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user