Files
prop-ai-hr/docs/superpowers/plans/2026-07-11-mobile-uni-employee-pages-visual-redesign.md
admin ee396d1e7a feat(mobile): 重做员工端首页、问答和训练页视觉
统一员工端 tabBar、共享卡片和三大核心页面的视觉基础,同时保持现有移动端业务流程不变。补充 H5 输入兼容、页面结构和训练回滚行为的回归测试。
2026-07-11 01:13:14 +08:00

14 KiB
Raw Permalink Blame History

Mobile Uni Employee Pages Visual Redesign Implementation Plan

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: 将员工端 today / sop / practice 三页及其强相关的 tabBar / 共享卡片样式 调整为接近设计基准稿的统一视觉,同时保持现有业务交互和接口行为不变。

Architecture: 采用“视觉优先、业务最小改动”的改法:先建立员工端共享视觉 token 与基础样式,再按首页、问师傅页、训练页的顺序逐页重排结构和样式。页面内部函数、接口调用与路由保留,主要改模板层级、类名、样式组织和少量静态资源引用。

Tech Stack: uni-app Vue3、Vite、TypeScript、CSS、Node 原生测试、H5 构建校验


Task 1: 建立员工端共享视觉基座

Files:

  • Modify: mobile-uni/src/styles/base.css

  • Modify: mobile-uni/src/pages.json

  • Test: mobile-uni/tests/mobile-user-pages.test.mjs

  • Step 1: 写一个失败测试,锁住 Vue3 manifest 与员工端视觉约束继续有效

test('tabBar 继续保留员工端四个固定入口', async () => {
  const source = await pageSource('../src/pages.json');

  assert.match(source, /pages\/user\/today\/index/);
  assert.match(source, /pages\/user\/practice\/index/);
  assert.match(source, /pages\/user\/sop\/index/);
  assert.match(source, /pages\/user\/profile\/index/);
});
  • Step 2: 运行测试,确认新增断言先失败或当前文件尚未覆盖该约束

Run: node --test tests/mobile-user-pages.test.mjs Expected: 新增测试如果还没加入会缺失;加入后在修改前至少能作为后续回归校验入口存在。

  • Step 3: 在 base.css 中整理员工端共享 token,不扩大到全站侵入式重置
:root {
  --employee-bg: #f4f6fb;
  --employee-surface: #ffffff;
  --employee-primary: #2f6bff;
  --employee-primary-soft: #eaf1ff;
  --employee-success: #34b368;
  --employee-warning: #ff8a1f;
  --employee-danger: #ff5b4d;
  --employee-text: #182230;
  --employee-muted: #6b7280;
  --employee-card-radius: 24px;
  --employee-card-shadow: 0 12px 32px rgba(47, 107, 255, 0.08);
}

.employee-card {
  border-radius: var(--employee-card-radius);
  background: var(--employee-surface);
  box-shadow: var(--employee-card-shadow);
}

.employee-section-title {
  color: var(--employee-text);
  font-size: 20px;
  font-weight: 900;
}
  • Step 4: 调整 pages.json 的员工端 tabBar 视觉参数,保留四 tab 结构和路径
"tabBar": {
  "color": "#7b8494",
  "selectedColor": "#2f6bff",
  "backgroundColor": "#ffffff",
  "borderStyle": "white",
  "height": "66px",
  "fontSize": "12px",
  "iconWidth": "25px",
  "spacing": "3px",
  "list": [
    { "pagePath": "pages/user/today/index", "text": "今日" },
    { "pagePath": "pages/user/practice/index", "text": "练" },
    { "pagePath": "pages/user/sop/index", "text": "问" },
    { "pagePath": "pages/user/profile/index", "text": "我" }
  ]
}
  • Step 5: 更新回归测试,验证 tabBar 四入口与共享样式关键 token 存在
test('共享视觉基座包含员工端主色和卡片圆角 token', async () => {
  const source = await pageSource('../src/styles/base.css');

  assert.match(source, /--employee-primary:/);
  assert.match(source, /--employee-card-radius:/);
});
  • Step 6: 运行测试验证通过

Run: node --test tests/mobile-user-pages.test.mjs Expected: PASS,且已有输入兼容与 manifest 测试继续通过。

  • Step 7: 提交这一阶段改动
git add mobile-uni/src/styles/base.css mobile-uni/src/pages.json mobile-uni/tests/mobile-user-pages.test.mjs
git commit -m "feat: add employee visual foundation"

Task 2: 重做员工端首页视觉

Files:

  • Modify: mobile-uni/src/pages/user/today/index.vue

  • Modify: mobile-uni/src/styles/base.css

  • Test: mobile-uni/tests/mobile-user-pages.test.mjs

  • Step 1: 为首页结构写失败测试,锁住设计稿要求的核心区块

test('员工首页保留师傅区、语音条、今日安排、我的地图四段结构', async () => {
  const source = await pageSource('../src/pages/user/today/index.vue');

  assert.match(source, /mentor-hero/);
  assert.match(source, /voice-panel/);
  assert.match(source, /今日安排/);
  assert.match(source, /我的地图/);
});
  • Step 2: 运行测试确认结构断言可作为改版护栏

Run: node --test tests/mobile-user-pages.test.mjs Expected: 失败或在旧结构下不足以覆盖新样式目标,后续补全后通过。

  • Step 3: 重排首页模板,保留原有交互函数但调整为设计稿节奏
<view class="mentor-hero employee-hero">
  <view class="hero-copy">
    <text class="hero-role">{{ positionProfile.value }}</text>
    <text class="hero-title">{{ positionProfile.heroTitle }}</text>
    <text class="hero-sub">有问题,随时问老师傅</text>
  </view>
  <image class="mentor-image" src="/static/mentor.png" mode="aspectFit" />
  <view class="mentor-bubble">
    <text>{{ mentorBubbleText }}</text>
  </view>
</view>

<view class="voice-panel employee-card">
  <button class="voice-primary" @click="goSop">...</button>
  <button class="voice-secondary" @click="goSop">...</button>
</view>

<view class="section-card employee-card" v-else-if="hasSchedule">...</view>
<view class="section-card employee-card" v-if="loggedIn">...</view>
  • Step 4: 用 scoped 样式还原首页视觉,控制人物占屏不超过首屏约五分之一
.today-page {
  background: radial-gradient(circle at top, #eef5ff 0%, #f7f9fc 38%, #f4f6fb 100%);
}

.mentor-hero {
  min-height: 220px;
  padding: 28px 24px 0;
}

.mentor-image {
  right: 24px;
  bottom: 0;
  width: 108px;
  height: 148px;
}

.voice-panel {
  margin-top: -28px;
  grid-template-columns: 1.4fr 1fr;
}

.map-tile {
  border-radius: 22px;
  min-height: 136px;
}
  • Step 5: 更新测试,验证首页地图主标题继续显示真实 tile.title,避免回退成单字标题
test('员工首页地图主标题继续显示真实工具名称', async () => {
  const source = await pageSource('../src/pages/user/today/index.vue');

  assert.match(source, /<text class="map-title">\{\{ tile\.title \}\}<\/text>/);
});
  • Step 6: 运行测试验证首页改版没有破坏护栏

Run: node --test tests/mobile-user-pages.test.mjs Expected: PASS。

  • Step 7: 提交首页改版
git add mobile-uni/src/pages/user/today/index.vue mobile-uni/src/styles/base.css mobile-uni/tests/mobile-user-pages.test.mjs
git commit -m "feat: redesign employee home page"

Task 3: 重做问师傅页视觉与总结卡展现

Files:

  • Modify: mobile-uni/src/pages/user/sop/index.vue

  • Modify: mobile-uni/src/styles/base.css

  • Test: mobile-uni/tests/mobile-user-pages.test.mjs

  • Step 1: 为问师傅页写失败测试,锁住搜索主导与总结卡入口仍然存在

test('问师傅页保留搜索框、答案区和总结卡入口', async () => {
  const source = await pageSource('../src/pages/user/sop/index.vue');

  assert.match(source, /query-panel/);
  assert.match(source, /answer-panel/);
  assert.match(source, /summary-panel/);
});
  • Step 2: 运行测试确认护栏建立成功

Run: node --test tests/mobile-user-pages.test.mjs Expected: 断言可执行,作为后续视觉重排的结构保护。

  • Step 3: 收紧问师傅页头部,改为“轻标题 + 强搜索框”的布局
<view class="page sop-page">
  <view class="sop-toolbar">
    <text class="page-title">查SOP</text>
    <text class="page-subtitle">直接搜 SOP、案例和常用话术</text>
  </view>

  <view class="panel query-panel employee-card">
    <textarea v-model="query" class="textarea sop-query-textarea" ... />
    <view class="chip-row">...</view>
    <button class="primary-button query-submit" ...>问老师傅</button>
  </view>
</view>
  • Step 4: 调整答案卡、引用依据和总结卡为更接近设计稿的卡片层级与底部浮层感
.sop-page {
  background: linear-gradient(180deg, #f7f9fc 0%, #f4f6fb 100%);
}

.query-panel {
  border-radius: 22px;
  padding: 18px;
}

.answer-panel {
  border-left: 0;
  border-radius: 22px;
}

.modal-card {
  border-radius: 28px 28px 0 0;
  max-width: 430px;
  width: calc(100% - 16px);
}
  • Step 5: 保持 H5 输入兼容测试存在,防止误把 textarea 再次改成 border-box
test('SOP 查询框不覆盖 textarea 的 box-sizing', async () => {
  const source = await pageSource('../src/pages/user/sop/index.vue');
  const queryPanelStyle = source.match(/\.query-panel \.textarea \{[\s\S]*?\n\}/)?.[0] || '';

  assert.equal(queryPanelStyle.includes('box-sizing'), false);
});
  • Step 6: 运行测试验证通过

Run: node --test tests/mobile-user-pages.test.mjs Expected: PASS。

  • Step 7: 提交问师傅页改版
git add mobile-uni/src/pages/user/sop/index.vue mobile-uni/src/styles/base.css mobile-uni/tests/mobile-user-pages.test.mjs
git commit -m "feat: redesign employee sop page"

Task 4: 重做训练页视觉但保留训练逻辑

Files:

  • Modify: mobile-uni/src/pages/user/practice/index.vue

  • Modify: mobile-uni/src/styles/base.css

  • Test: mobile-uni/tests/mobile-user-pages.test.mjs

  • Step 1: 为训练页写失败测试,锁住训练关键区块仍存在

test('训练页保留场景区、对话区、回复区和结果区', async () => {
  const source = await pageSource('../src/pages/user/practice/index.vue');

  assert.match(source, /scenario-card/);
  assert.match(source, /dialogue-card/);
  assert.match(source, /reply-card/);
  assert.match(source, /result-card/);
});
  • Step 2: 运行测试确认结构护栏存在

Run: node --test tests/mobile-user-pages.test.mjs Expected: 断言可运行,用于防止视觉重排时误删功能区块。

  • Step 3: 调整训练页模板,让头部、场景卡、老师傅提示更接近设计稿的训练面板结构
<view class="practice-head">
  <text class="practice-eyebrow">数字师傅 · 场景训练</text>
  <text class="page-title">{{ activeScenarioName }}</text>
  <text class="page-subtitle">与业主、老师傅完成一轮真实工作对话</text>
</view>

<view v-if="loggedIn" class="panel scenario-card employee-card">...</view>
<view v-if="turns.length" class="panel dialogue-card employee-card">...</view>
<view v-if="status === 'active' || status === 'submitting'" class="panel reply-card employee-card">...</view>
  • Step 4: 用样式强化三类角色区分与老师傅提示卡,但不引入每轮真实评分
.turn-row.customer {
  background: linear-gradient(180deg, #fff8f1 0%, #ffffff 100%);
}

.turn-row.trainee {
  background: linear-gradient(180deg, #f2fbf6 0%, #ffffff 100%);
}

.turn-row.coach {
  background: linear-gradient(180deg, #eef5ff 0%, #ffffff 100%);
}

.reply-card .primary-button {
  min-height: 52px;
  border-radius: 18px;
}

.help-card,
.mentor-rewrite {
  border-radius: 22px;
}
  • Step 5: 保留并复用提交失败回滚测试,避免训练视觉改版时误伤已有状态修复
test('训练页提交失败会回滚本次乐观追加的对话', async () => {
  const source = await pageSource('../src/pages/user/practice/index.vue');

  assert.match(source, /const previousTurns = turns\.value\.slice\(\)/);
  assert.match(source, /turns\.value = previousTurns/);
});
  • Step 6: 运行测试验证通过

Run: node --test tests/mobile-user-pages.test.mjs Expected: PASS。

  • Step 7: 提交训练页改版
git add mobile-uni/src/pages/user/practice/index.vue mobile-uni/src/styles/base.css mobile-uni/tests/mobile-user-pages.test.mjs
git commit -m "feat: redesign employee practice page"

Task 5: 全量验证与收尾

Files:

  • Verify: mobile-uni/src/pages/user/today/index.vue

  • Verify: mobile-uni/src/pages/user/sop/index.vue

  • Verify: mobile-uni/src/pages/user/practice/index.vue

  • Verify: mobile-uni/src/styles/base.css

  • Verify: mobile-uni/src/pages.json

  • Test: mobile-uni/tests/mobile-user-pages.test.mjs

  • Step 1: 运行员工端页面回归测试

Run: node --test tests/mobile-user-pages.test.mjs Expected: PASS。

  • Step 2: 运行全量单测

Run: npm run test:unit Expected: 全部 PASS;允许保留既有 WebSocket 噪音,只要没有失败。

  • Step 3: 运行类型检查

Run: npm run typecheck Expected: PASS。

  • Step 4: 运行 H5 构建

Run: npm run build:h5 Expected: Build complete.

  • Step 5: 本地打开首页进行人工快速核对

Run: open "http://localhost:5175/h5/#/pages/user/today/index" Expected: 能看到新的首页首屏结构、语音条、今日安排、我的地图和统一 tabBar。

  • Step 6: 提交最终整体验证结果
git add mobile-uni/src/pages/user/today/index.vue mobile-uni/src/pages/user/sop/index.vue mobile-uni/src/pages/user/practice/index.vue mobile-uni/src/styles/base.css mobile-uni/src/pages.json mobile-uni/tests/mobile-user-pages.test.mjs
git commit -m "feat: unify employee mobile page visuals"

计划自检

Spec 覆盖检查

  • 三页范围:Task 2、Task 3、Task 4 覆盖 today / sop / practice。
  • 共享样式与 tabBar:Task 1 覆盖。
  • 老师傅仅复用现有素材、不扩展业务:Task 2 与 Task 4 的模板调整限制在现有资源与逻辑内。
  • SOP 不伪造能力:Task 3 明确保留真实能力,不新增假 tab 行为。
  • 训练页不做每轮真实评分:Task 4 明确只改视觉分层,不新增该模块。
  • 验证要求:Task 5 覆盖页面测试、全量单测、类型检查、H5 构建。

Placeholder 扫描

  • 无 TODO、TBD、适当处理 等空泛描述。
  • 每个任务都包含具体文件、命令和代码片段。

类型与命名一致性

  • 继续沿用现有页面类名:scenario-card、dialogue-card、reply-card、summary-panel、voice-panel 等。
  • 复用现有关键回归点:tile.title、previousTurns、box-sizing、vueVersion。