diff --git a/docs/superpowers/plans/2026-09-17-login-keji-visual-v1.md b/docs/superpowers/plans/2026-09-17-login-keji-visual-v1.md new file mode 100644 index 0000000..ee31b93 --- /dev/null +++ b/docs/superpowers/plans/2026-09-17-login-keji-visual-v1.md @@ -0,0 +1,505 @@ +# 登录页客迹视觉 V1 对齐 — 实现计划 + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** 将 admin 登录页从 Art Design Pro 模板原版重做为客迹视觉 V1(深蓝品牌区 + 浅色表单区双栏),对齐设计稿 assets/design/keji-admin-v1/03-login.png。 + +**Architecture:** 重写三页共用组件 LoginLeftView.vue(背景图 + logo + 标语叠加层),简化 login/index.vue(移除 AuthTopBar/账号下拉/注册与忘记密码链接)并重写 style.css(固定浅色 + Element Plus 变量覆盖防暗色污染),同步更新 zh/en i18n 文案。 + +**Tech Stack:** Vue3 + TS + Element Plus + Tailwind(Art Design Pro 模板),Playwright 视觉验证。 + +**Spec:** docs/superpowers/specs/2026-09-17-login-keji-visual-v1-design.md(含全部决策记录与色值) + +**TDD 说明:** 纯视觉重构、登录逻辑零改动(spec 明确),无新增单元测试。验证 = Playwright 截图对照设计稿 + `pnpm build` + 现有测试不受影响。 + +**工作目录:** 全程在 `admin/` 下操作(git 仓库根为 D:\project\cms-cj,分支 m1)。 + +--- + +### Task 1: i18n 文案更新 + +**Files:** +- Modify: `admin/src/locales/langs/zh.json:151-179`(login 对象) +- Modify: `admin/src/locales/langs/en.json:151-179`(login 对象) + +- [ ] **Step 1: 更新 zh.json 的 login 对象** + +将 `zh.json` 中 `"login"` 对象内以下 key 的值替换(其余 key 原样保留): + +```json +"leftView": { + "title": "看见来访,读懂客迹", + "subTitle": "网站访问与客户旅程分析", + "slogan": "数据驱动增长 · 洞察创造价值", + "footer": "让每一次来访都有价值" +}, +"title": "欢迎登录客迹", +"subTitle": "登录您的独立数据工作台", +``` + +并在 `"placeholder"` 对象同级新增三个 key(放在 `"btnText"` 之后): + +```json +"accountLabel": "账号", +"passwordLabel": "密码", +"adminAssigned": "账号由管理员分配", +``` + +同时把 `"rememberPwd": "记住密码"` 改为 `"rememberPwd": "保持登录"`。 + +删除 `"noAccount"` 和 `"register"` 两个 key(入口已移除)。 + +- [ ] **Step 2: 更新 en.json 的 login 对象** + +`en.json` 同结构对应更新: + +```json +"leftView": { + "title": "See every visit, understand every journey", + "subTitle": "Website visit & customer journey analytics", + "slogan": "Data-driven growth · Insight-driven value", + "footer": "Make every visit count" +}, +"title": "Welcome to KEJI", +"subTitle": "Sign in to your data workspace", +``` + +新增: + +```json +"accountLabel": "Account", +"passwordLabel": "Password", +"adminAssigned": "Accounts are assigned by the administrator", +``` + +`"rememberPwd": "Stay signed in"`;删除 `"noAccount"`、`"register"`。 + +**注意:** en.json 删除 noAccount/register 后,`register/index.vue` 等其他文件若引用 `$t('login.register')` 会显示 key 本身。先全局搜索确认只有 login/index.vue 引用(本任务后 Task 3 会移除该引用;若搜索发现其他引用处则保留 key 不删)。 + +- [ ] **Step 3: 验证 JSON 合法** + +Run: `python -c "import json; json.load(open('src/locales/langs/zh.json', encoding='utf-8')); json.load(open('src/locales/langs/en.json', encoding='utf-8')); print('OK')"` +Expected: `OK` + +- [ ] **Step 4: Commit** + +```bash +git add src/locales/langs/zh.json src/locales/langs/en.json +git commit -m "feat(admin): 登录页i18n文案对齐客迹V1" +``` + +--- + +### Task 2: 重写 LoginLeftView.vue(左侧品牌区) + +**Files:** +- Modify: `admin/src/components/core/views/login/LoginLeftView.vue`(整文件重写) + +资源(已存在,无需新增):`src/assets/images/logo-w.png`(1944×809 透明底白字)、`src/assets/images/login/login-left-background.png`(1196×1315)。 + +- [ ] **Step 1: 整文件替换为以下内容** + +```vue + + + + + + + {{ $t('login.leftView.title') }} + {{ $t('login.leftView.subTitle') }} + + {{ $t('login.leftView.slogan') }} + + + {{ $t('login.leftView.footer') }} + + + + + + +``` + +要点:背景图走 JS import + inline style(Vite 哈希 + 懒加载友好);`hideContent` prop 删除(已确认无调用方);`<=1600px` 中间宽度规则不再保留,仅 58vw 一档;`<=1180px` 直接 display:none。 + +- [ ] **Step 2: 类型检查编译通过** + +Run: `pnpm typecheck || pnpm run build`(若项目无 typecheck 脚本则跳过,Task 5 统一 build 验证) +Expected: 无错误(LoginLeftView 无外部引用变化,register/forget-password 自动获得新品牌区) + +- [ ] **Step 3: Commit** + +```bash +git add src/components/core/views/login/LoginLeftView.vue +git commit -m "feat(admin): 登录左侧品牌区重做为客迹V1深蓝视觉" +``` + +--- + +### Task 3: 简化 login/index.vue + 重写 style.css(右侧表单) + +**Files:** +- Modify: `admin/src/views/auth/login/index.vue`(模板 + script + style) +- Modify: `admin/src/views/auth/login/style.css`(整文件重写) + +- [ ] **Step 1: 替换 index.vue 的 template 部分** + +```vue + + + + + + + + + {{ $t('login.title') }} + {{ $t('login.subTitle') }} + + + + + + + + + + + + + + + {{ $t('login.placeholder.slider') }} + + + + + {{ + $t('login.rememberPwd') + }} + + + + + {{ $t('login.btnText') }} + + + + + + {{ $t('login.adminAssigned') }} + + + + + + + + +``` + +- [ ] **Step 2: 修改 index.vue 的 script 部分** + +1. 新增 import:`import { User, Lock } from '@element-plus/icons-vue'` +2. 删除:`import { useSettingStore } from '@/store/modules/setting'`、`const settingStore = useSettingStore()`、`const { isDark } = storeToRefs(settingStore)`(滑块已固定浅色,isDark 不再使用) +3. 删除:`type AccountKey`、`export interface Account`、`const accounts = computed...` 整块、`setupAccount` 函数、`onMounted(() => { setupAccount('admin') })` +4. `formData` 初始化改为 `username: 'admin'`(保持 M1 单管理员预填行为): + +```ts +const formData = reactive({ + account: '', + username: 'admin', + password: '', + rememberPassword: true +}) +``` + +5. 其余逻辑(handleSubmit、resetDragVerify、showLoginSuccessNotice、formKey/locale watch)**零改动**。 + +- [ ] **Step 3: index.vue 底部 scoped style 简化** + +删除 `:deep(.el-select__wrapper)` 覆盖块(ElSelect 已移除),`@import './style.css'` 保留。 + +- [ ] **Step 4: style.css 整文件替换** + +```css +@reference '@styles/core/tailwind.css'; + +/* 授权页右侧区域(客迹V1:固定浅色,不随暗色主题变化) */ +.auth-right-bg { + /* 覆盖 Element Plus 暗色变量,防止 html.dark 时表单控件变暗 */ + --el-bg-color: #ffffff; + --el-bg-color-overlay: #ffffff; + --el-fill-color-blank: #ffffff; + --el-fill-color-light: #f5f7fa; + --el-text-color-primary: #1a1a1a; + --el-text-color-regular: #303133; + --el-border-color: #dcdfe6; + --el-border-color-light: #e4e7ed; + --el-border-color-lighter: #ebeef5; + background-color: #f7f8fa; +} + +.auth-right-wrap { + @apply absolute inset-0 w-[440px] h-[680px] py-[5px] m-auto overflow-hidden + max-sm:px-7 max-sm:w-full + animate-[slideInRight_0.6s_cubic-bezier(0.25,0.46,0.45,0.94)_forwards] + max-md:animate-none; + + .form { + @apply h-full py-[40px]; + } + + .title { + @apply text-[#1A1A1A] text-[32px] font-semibold text-center; + } + + .sub-title { + @apply mt-[10px] text-[#8A94A6] text-[15px] text-center; + } + + .custom-height { + @apply !h-[56px]; + } + + /* 表单标签样式 */ + :deep(.el-form-item__label) { + color: #1a1a1a; + font-weight: 600; + } + + /* 账号由管理员分配 */ + .admin-assigned { + @apply flex-cc gap-3 mt-8; + + .line { + @apply inline-block w-6 h-px bg-[#D3D9E3]; + } + + .text { + @apply text-[13px] text-[#9AA3B2]; + } + } +} + +/* 滑入动画 */ +@keyframes slideInRight { + from { + opacity: 0; + transform: translateX(30px); + } + + to { + opacity: 1; + transform: translateX(0); + } +} +``` + +- [ ] **Step 5: 验证无残留引用** + +Run: `grep -rn "setupAccount\|AuthTopBar\|noAccount\|ElSelect" src/views/auth/login/` +Expected: 无输出(login 页内已无这些引用;register/forget-password 中的 AuthTopBar 不受影响) + +- [ ] **Step 6: Commit** + +```bash +git add src/views/auth/login/index.vue src/views/auth/login/style.css +git commit -m "feat(admin): 登录表单区对齐客迹V1——移除账号下拉/注册/忘记密码入口,固定浅色" +``` + +--- + +### Task 4: 视觉验证(Playwright 截图对照设计稿) + +**Files:** +- 无代码改动;产出截图到 `admin/exports/`(或临时目录,不入库) + +- [ ] **Step 1: 启动 dev server** + +Run: `cd admin && pnpm dev`(后台运行) +Expected: Vite 启动在 http://localhost:3006 + +- [ ] **Step 2: Playwright 三档截图** + +用 playwright MCP 打开 `http://localhost:3006/#/login`(或路由实际形态,先 navigate 探测),分别设置视口并截图: + +1. 1920×1080(桌面标准) +2. 1440×900(小桌面) +3. 375×812(移动,验证左侧隐藏 + 表单单栏) + +- [ ] **Step 3: 对照检查清单** + +- [ ] 左侧 58vw 深蓝背景图完整覆盖、无拉伸变形 +- [ ] logo-w.png 白字清晰可见(左上角) +- [ ] 主标语/副标题/短横线/口号/底部文案齐全、层级与留白接近设计稿 +- [ ] 右侧 #F7F8FA 底、标题居中、输入框 56px 高带图标 +- [ ] 滑块浅蓝灰底、文字 #4D5875 可读、验证通过后主色进度条 +- [ ] 登录按钮全宽主色 +- [ ] 底部"— 账号由管理员分配 —" +- [ ] 375px:左侧隐藏、表单居中占满 +- [ ] 浏览器切 html.dark 类(Playwright evaluate `document.documentElement.classList.add('dark')`)后右侧仍浅色 + +发现问题 → 回到对应 Task 修正(样式微调不新增任务)。 + +- [ ] **Step 4: 实际登录冒烟** + +本地 dev 直连生产 API 不可用时仅验证 UI 交互:滑块可拖动、按钮可点、空值提交报错提示正常。(真实登录冒烟放到 Task 5 线上验证时用管理员账号完成,密码不入库——问用户索取或由用户自测) + +--- + +### Task 5: 构建验证 + 部署上线 + +- [ ] **Step 1: pnpm build** + +Run: `cd admin && pnpm build` +Expected: 构建成功,dist/ 生成新哈希文件 + +- [ ] **Step 2: 标准部署流程(项目约定:测试通过后直接上线,无需等确认)** + +```bash +cd admin && pnpm build +tar -czf /tmp/admin-dist.tar.gz dist/ +scp -i ~/.ssh/id_ed25519 -J root@8.152.213.143 /tmp/admin-dist.tar.gz root@47.254.176.10:/tmp/ +ssh -i ~/.ssh/id_ed25519 -J root@8.152.213.143 root@47.254.176.10 "cd /opt/cms-cj && tar -xzf /tmp/admin-dist.tar.gz && rm /tmp/admin-dist.tar.gz" +``` + +(原地覆盖 dist 内容,bind mount 不受影响,无需重启容器) + +- [ ] **Step 3: 线上验证** + +Playwright 打开 https://tracker.12418113.xyz 登录页,截图确认新视觉生效;记录 `index-xxx.js` 哈希作为版本号。 + +- [ ] **Step 4: 汇报** + +汇报内容:完成项清单、三档截图、线上版本哈希、验证结果。 + +--- + +## 风险提示(执行者注意) + +1. **严格不动服务器其他项目**(1Panel、其他网站容器)——只解压覆盖 /opt/cms-cj 下的前端文件。 +2. `05-login-left-background.png` 为 AI 去字重建背景,与设计稿非逐像素一致是**预期内的**,不要试图"修正"背景图。 +3. register/forget-password 页共用 LoginLeftView,视觉同步变化是**预期行为**(spec 决策 4)。 +4. 若 grep 发现 `login.noAccount`/`login.register` 有 login 页之外的引用,保留对应 i18n key 不删,并在 commit message 中说明。
{{ $t('login.leftView.subTitle') }}
{{ $t('login.leftView.slogan') }}
{{ $t('login.leftView.footer') }}
{{ $t('login.subTitle') }}
+ {{ $t('login.placeholder.slider') }} +