You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
mail-yubao/docx/产品UI-UX设计方案-邮件自动预报-v1.0.md

16 KiB

产品UI/UX设计方案 v1.0(邮件自动预报系统)

状态:可直接画原型 / 写前端(2026-07-23 现行口径回写)
依据:docx/需求规格-邮件自动预报-v0.2.md、docx/技术设计方案-邮件自动预报-v1.0.md
UI 栈锁定:Ant Design 5 + TanStack Virtual(货件表)+ 本规范 Token
回写要点:/settings;/logs=导入+拉取(无操作审计);空态无种子;详情业务意图摘要替代得分表;详见 docx/现行口径-修订说明-v1.md


1. 信息架构(Information Architecture)

1.1 页面列表

页面 路由 职责
登录页 /login 账号密码登录;写 session Cookie
邮件列表页 /mails 时间倒序展示邮件;按类型/状态筛选;进入详情
邮件详情页 /mails/[id] 摘要、正文、附件、证据、货件预览;重新解析;Admin 改类型;进入确认导入
确认导入页 /mails/[id]/confirm 柜头编辑;TransMode/OperationType;货件勾选(虚拟滚动);二次确认后提交 CC
导入日志/补偿页 /logs Tab:导入日志、拉取记录;失败重试
设置 /settings Admin:邮箱绑定、IMAP 间隔/过滤、CC、OAuth
Admin 改类型 详情页内 Modal(非独立路由) ENABLE_TYPE_OVERRIDE(及前端可见开关)+ role=admin;一期不写 audit_log

不设 /dashboard、不设 /admin/override 独立页。登录后默认落点:/mails。

1.2 页面关系图

/login
  → /mails
       → /mails/[id]
            → /mails/[id]/confirm   (mail_type=NEW_CONTAINER 且 status=PENDING_CONFIRM;或 Admin 改类型后满足条件)
                 → /logs            (提交结束:成功跳转;失败可停留 confirm 或跳 logs)
            ⇢ Modal「改类型」       (Admin)
            ⇢ 动作「重新解析」      (PARSE_FAILED / REJECTED_VALIDATION / 允许重解析的状态)
       → /logs                      (顶栏入口)

禁用路径:

  • mail_type ≠ NEW_CONTAINER 且未改类型成功 → 不可进入 confirm(直链访问重定向详情 + Toast)
  • status ∈ {IMPORTING, SUCCESS} → confirm 只读或重定向详情

1.3 路由结构(Next.js App Router)

/login
/mails
/mails/[id]
/mails/[id]/confirm
/logs

顶栏全局导航(登录后):邮件列表 | 日志 | 设置(Admin) | 健康/IMAP/CC 状态 | 用户名 | Admin 徽标 | 退出


2. 交互原型(Interaction Design)

2.0 全站壳层

┌──────────────────────────────────────────────────────────┐
│ TopNav: Logo「邮件预报」 | 导航链接 | 用户/Admin | 退出     │
├──────────────────────────────────────────────────────────┤
│ PageHeader: 标题 + 右侧主操作(按页)                      │
├──────────────────────────────────────────────────────────┤
│ MainContent(白底 Card 或铺满表)                          │
└──────────────────────────────────────────────────────────┘
  • 最小视口宽:1280px
  • 内容最大宽:1440px,水平居中
  • Toast:右上角;Modal:居中

2.1 登录页 /login

结构

  • 居中 Card(宽 400px)
  • 标题:邮件自动预报
  • 字段:用户名、密码
  • 主按钮:登录

交互

  • 提交 → 按钮 loading → 成功跳转 /mails;失败 Toast error + 字段下方文案
  • 已登录访问 /login → 重定向 /mails

空/错

  • 用户名或密码空 → 内联校验,不发请求

2.2 邮件列表页 /mails

结构

PageHeader: 「邮件列表」
FilterBar: [类型 Select] [状态 Select] [关键词 Input] [查询 Button]
MailTable(非卡片列表,密度优先用表格):
  列:类型Tag | 状态Pill | 主题 | 发件人 | 接收时间 | 柜号(若有)
Pagination: 底右,默认 pageSize=20

交互

  • 行点击(整行可点)→ /mails/[id]
  • 筛选变更 → 立即请求列表(防抖 300ms,关键词)
  • 手动「刷新」按钮 → 重新拉列表(无 WebSocket)

空态

  • 文案:暂无邮件,等待 IMAP 拉取
  • 次按钮:刷新

角标规则

  • 类型:左侧色点 8px + Tag 文字
  • 状态:StatusPill 文字(不只靠颜色)

2.3 邮件详情页 /mails/[id]

结构

PageHeader:
  [← 返回列表]  主题(H1)  StatusPill  TypeTag
  右侧操作组:
    [重新解析](条件可见)
    [改类型](Admin 条件可见)
    [确认导入](主按钮,条件启用)

SummaryStrip: 发件人 | 时间 | Message 状态

Tabs 或 纵向区块:
  1) 正文摘要(等宽可读,max-height 240px 可滚动)
  2) 附件列表:文件名 | 大小 | 下载
  3) 业务意图摘要(动作/关键字/操作内容/转仓对;不展示得分分值);type_evidence JSON 可选收起
  4) 货件预览表(前 50 行 + 「共 N 行,确认导入页查看全部」链接)

确认导入按钮启用条件(全部满足)

  • mail_type === NEW_CONTAINER
  • status === PENDING_CONFIRM
  • valid_shipment_count >= 1

禁用时 Tooltip / 旁注文案(写死)

  • 类型非 NEW:类型为 {mail_type},一期不可导入
  • 状态非 PENDING_CONFIRM:当前状态为 {status},不可导入
  • 无有效行:无有效货件行

交互

  • 确认导入 → /mails/[id]/confirm
  • 重新解析 → POST reparse → 按钮 loading → 成功 Toast → 重新拉详情;失败 Toast
  • 改类型 → 打开 TypeOverrideModal:
    • Select 目标类型
    • Input 原因(必填)
    • 展示当前 type_evidence 摘要
    • 确认 → loading → 审计成功 Toast → 刷新详情(可能出现确认导入可点)

直链保护

  • 非法 id → 404 页:邮件不存在 + 回列表

2.4 确认导入页 /mails/[id]/confirm(核心)

结构

PageHeader:
  [← 返回详情]  主题截断  | 柜号大号展示
  右侧无第二主按钮(主 CTA 在底栏)

Section「柜头」Card 两列表单:
  左列: TransMode* | OperationType* | ContainerNo* | CabinetType | Classis
  右列: ETD | ETA | ShippingLineId(Select 可搜索,可空)| MemoRemark | Instruction
  * 必填;ContainerNo 失焦触发 ISO 校验

Section「货件」Card:
  Toolbar: [全选有效] [反选] [SearchInput: FBACode/ShipmentID] [有效 m / 无效 k]
  VirtualTable 高度固定 480px:
    列: ☑ | # | 仓库ID | 渠道 | 件数 | FBA ID | Ref | ShipmentID | 行状态 | 警告
  INVALID 行: 背景 #F3F4F6,勾选 disabled,行状态 Tag=INVALID

StickyFooter(视口底):
  左: 已选 n / 有效 m
  右: [取消] [确认导入 Primary]

默认值

  • TransMode = 解析推荐或 0
  • OperationType = 解析推荐或 0
  • 勾选 = 全部 VALID 行
  • CHANNEL_UNMAPPED 行可勾选,提交前若存在未 ack → 额外确认勾选「已知晓未映射渠道」

二次确认 Modal

  • 标题:确认导入至 CarrierCentral
  • 正文:将向 CC 导入柜 {container_no},货件 {n} 行
  • 展示 TransMode / OperationType 文案
  • 按钮:取消 | 确认提交

提交交互

  1. Primary 点击 → 打开 Modal(本地校验先过)
  2. Modal 确认 → Primary+Modal 双 loading;disabled
  3. 成功 → Toast success → 跳转 /logs?mail_id={id}
  4. 失败 → Toast error(展示 error.message)→ 留在本页;可再改再提(若 status 已 IMPORTING 则整页只读 + 「导入中,请稍后刷新」)
  5. 409 VERSION_CONFLICT → Toast + 强制刷新页面数据

校验(内联)

  • TransMode / OperationType 空 → 阻止 Modal
  • ContainerNo 空或 ISO 失败 → 字段 Error
  • n=0 → Primary disabled,文案:请至少勾选一行有效货件

2.5 导入日志/补偿页 /logs

结构

PageHeader: 「导入日志」 [返回邮件列表]
Filter: 状态 Select | 柜号/主题 Search
Table 列:
  时间 | 邮件主题(链到详情) | 柜号 | 导入状态Pill | external_id | last_error | 操作
操作:
  FAILED / TIMEOUT_UNKNOWN / CONFLICT(可重试类) → [重试]
  SUCCESS → 显示 external_id,无重试

交互

  • 重试 → 按钮 loading → Toast → 刷新行
  • COMPENSATION_EXHAUSTED → 重试按钮对普通 ops 隐藏;Admin 显示「重置并重试」

空态

  • 暂无导入记录

2.6 统一交互规则(写死)

  1. 所有触发写操作的按钮:点击即 loading + disabled,防重复提交。
  2. 所有 API 失败:全局 Toast error;表单字段错误额外内联。
  3. 所有必填/格式:失焦或提交前校验,不通过不发请求。
  4. 导入类写操作:必须二次确认 Modal。
  5. 货件表 ≥50 行:必须虚拟滚动(本系统确认页固定启用)。
  6. 状态更新:一期无 WS;用户点「刷新」或返回列表重进。
  7. IMPORTING 期间:详情/确认页禁止再次提交;展示 Alert「导入进行中」。
  8. 色标旁必须有文字标签。

3. 视觉设计(Visual Design System)

3.1 色彩 Token

Token Hex 用途
--color-primary #2563EB 主按钮、链接、焦点
--color-primary-hover #1D4ED8 hover
--color-success #16A34A 成功
--color-warning #F59E0B 警告/部分成功
--color-error #DC2626 失败
--color-bg #F8FAFC 页面底
--color-surface #FFFFFF 卡片/表单
--color-text #111827 主文字
--color-text-secondary #6B7280 辅助
--color-border #E5E7EB 边框
--color-disabled #9CA3AF 禁用

类型色(Tag 背景 / 文字白或深按对比度)

mail_type 色
NEW_CONTAINER #2563EB
TRANSFER #F59E0B
INSTRUCTION_HOLD_SPLIT #8B5CF6
INSTRUCTION_LABEL #EC4899
WORK_ORDER #0D9488
UNKNOWN #6B7280

状态色(StatusPill)

status 色
FETCHED / PARSING / PARSED #9CA3AF
PENDING_CONFIRM #2563EB
IMPORTING #F59E0B
SUCCESS #16A34A
PARTIAL_SUCCESS #F59E0B
FAILED / PARSE_FAILED / REJECTED_VALIDATION #DC2626
IGNORED #6B7280

3.2 字体

  • 字体栈:Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif
  • H1:24px / 700 / 1.2
  • H2:20px / 600 / 1.3
  • Body:14px / 400 / 1.5
  • Caption:12px / 400 / 1.4
  • Small:11px / 400 / 1.3
  • 等宽(证据 JSON):ui-monospace, SFMono-Regular, Menlo, Consolas, monospace 12px

3.3 间距

4 / 8 / 12 / 16 / 24 / 32 / 48 / 64(px)
Card 内边距:16
区块间距:24
Filter 与表:16

3.4 圆角

元素 半径
Button / Input 6px
Card 8px
Modal 12px
Tag / Pill 12px

3.5 阴影

  • Card:0 1px 3px rgba(0,0,0,0.06), 0 1px 2px rgba(0,0,0,0.04)
  • Modal:0 20px 60px rgba(0,0,0,0.15)

3.6 组件视觉规格

组件 规格
PrimaryButton bg primary,文字白,h=36,px=16,radius 6;hover primary-hover;loading 内嵌 Spinner
SecondaryButton bg 白,border primary,文字 primary
DangerButton bg error,文字白
Input / Select h=36,border 1px border-color,focus:ring 2px primary 30%
Card surface + shadow + radius 8 + p16
Tag h=22,px=8,文字 12px
StatusPill 同 Tag
Table header bg #F9FAFB,文字 secondary,字重 600
INVALID 行 bg #F3F4F6,文字 secondary
StickyFooter 白底,上边框 border,h=56,z-index 10
Toast success/error/warning 对应色左边条 4px

4. 设计规范(Design System for AI Coding)

4.1 React 组件清单(映射 Antd)

设计组件 实现映射
PrimaryButton Button type="primary"
SecondaryButton Button
DangerButton Button danger
InputField Form.Item + Input
SelectField Form.Item + Select
DatePickerField Form.Item + DatePicker
Checkbox Checkbox
AppCard Card
MailTable Table
ShipmentVirtualTable 自研:TanStack Virtual + 行渲染
TypeTag Tag + 类型色
StatusPill Tag + 状态色
LoadingSpinner Spin
ErrorBanner Alert type="error"
AppToast message / notification
ConfirmModal Modal.confirm 或受控 Modal
SearchInput Input.Search
Pagination Pagination
TypeOverrideModal 受控 Modal + Form
TopNav Layout.Header + Menu
EmptyState Empty

页面组件命名:

  • LoginPage
  • MailListPage
  • MailDetailPage
  • MailConfirmPage
  • ImportLogsPage

4.2 组件状态

每个可交互组件支持:idle | loading | success | error | disabled | empty(按上下文取用)。

页面级状态机(前端):

  • pageStatus: idle | loading | error
  • 详情另:actionLoading: reparse | override | none
  • 确认页另:submitPhase: idle | validating | confirming | submitting

4.3 命名规范

  • 组件:PascalCase
  • 路由文件:page.tsx 于 app/mails/[id]/confirm/page.tsx
  • 状态布尔:isLoading isSubmitting isAdmin
  • 文案常量:src/constants/ui-copy.ts
  • Token CSS 变量:--color-* 写入 globals.css

4.4 UI 硬约束(编码强制)

  1. 写操作按钮必须 loading + 防重复。
  2. API 失败必须可见错误(禁止静默)。
  3. 表单校验失败禁止发请求。
  4. 导入提交必须二次确认 Modal。
  5. 货件表 ≥50 行必须虚拟滚动(confirm 页强制)。
  6. 空列表必须 EmptyState。
  7. 桌面优先,min-width 1280。
  8. Tag/Pill 必须带文字,不只靠颜色。
  9. confirm 直链:服务端/客户端双重校验 NEW + PENDING_CONFIRM。
  10. Admin 改类型按钮:仅 isAdmin && enableTypeOverride 渲染。

4.5 文案常量(摘录)

key 中文
empty.mails 暂无邮件,等待 IMAP 拉取
btn.confirmImport 确认导入
btn.reparse 重新解析
btn.overrideType 改类型
btn.retry 重试
modal.import.title 确认导入至 CarrierCentral
modal.import.body 将向 CC 导入柜 {no},货件 {n} 行
disable.notNew 类型为 {type},一期不可导入
disable.badStatus 当前状态为 {status},不可导入
alert.importing 导入进行中,请稍后刷新查看结果
ack.unmapped 已知晓存在未映射渠道,仍提交原值

4.6 线框尺寸速查

区域 尺寸
TopNav 高 56px
PageHeader 高 64px
FilterBar 高 48px
确认页 VirtualTable 高 480px
StickyFooter 高 56px
登录 Card 宽 400px
Modal 宽 480px(改类型)/ 520px(导入确认)

5. 页面 ↔ API 绑定(供前端直接接线)

页面 主要 API
Login POST /api/auth/login
MailList GET /api/mails
MailDetail GET /api/mails/:id;POST .../reparse;POST .../type
Confirm POST /api/mails/:id/import
Logs GET /api/imports;POST /api/imports/:id/retry

6. 文档索引

文档 路径
本设计 docx/产品UI-UX设计方案-邮件自动预报-v1.0.md
PRD docx/需求规格-邮件自动预报-v0.2.md
技术设计 docx/技术设计方案-邮件自动预报-v1.0.md