Files
cz-web/docs/page-architecture.md
2026-09-28 09:21:34 +08:00

207 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 页面架构规划 — cz-web(auto-dev 阶段三产出)
> 依据 `docs/PRD.md` 梳理。规范遵循 vue-project-structure skill:三层数据流(页面 → store → api)、四者同名(views/api/store/types)、less 样式、`@/` 别名。
## 1. 页面清单表(模块 → 页面 → 功能点 → 数据字段)
### 模块 home(首页)
| 页面 | 功能点 | 数据字段 |
| --- | --- | --- |
| 首页 `/` | 欢迎区、数据看板、快捷入口、业务服务卡片、案例精选、服务 Tab、页脚 | stats{pending,inProgress,total}、quickLinks[]、businessLines[]、cases[] |
| 业务详情 `/business/:type` | 面包屑、业务介绍、服务内容富文本+视频、服务类型子 Tab | businessLine{id,name,slogan,serviceContent,serviceTypes[],video} |
### 模块 cases(案例库)
| 页面 | 功能点 | 数据字段 |
| --- | --- | --- |
| 案例列表 `/cases` | 四维筛选(业务类型/行业/规模/完成时间)+关键字、已选条件回显、案例卡片网格、分页 | Case(见 PRD 4.1)、CaseQuery{category,industries[],scales[],dateRange,keyword,page} |
| 案例详情 `/cases/:id` | 概览、收藏/分享、视频、富文本四段、一键填报类似案例 | Case 全量、isFavorite |
### 模块 demand(需求提报)
| 页面 | 功能点 | 数据字段 |
| --- | --- | --- |
| 需求提报 `/demand` | 三步表单:业务类型单选→需求信息+附件→确认备注;立即提报/保存草稿/重置 | Demand(见 PRD 4.2) |
### 模块 login(认证)
| 页面 | 功能点 | 数据字段 |
| --- | --- | --- |
| 登录 `/login` | 账号密码/手机验证码双模式、游客模式、协议勾选 | account,password,phone,smsCode,agreeTerms |
| 注册 `/register` | 手机+验证码+密码(强度指示)+确认密码、协议勾选 | phone,smsCode,password,confirmPassword |
| 找回密码 `/reset-password` | 手机+验证码+新密码+确认、确认修改 | phone,smsCode,newPassword,confirmPassword |
### 模块 project(项目中心)
| 页面 | 功能点 | 数据字段 |
| --- | --- | --- |
| 项目列表 `/project` | 三维筛选+关键字、状态 Tab、项目表格、分页 | Project(PRD 4.3)、ProjectQuery{businessType,status,dateRange,keyword,page} |
| 项目详情 `/project/:id` | 信息卡、项目团队、四 Tab(进度里程碑/项目文件/合同财务/售后信息) | Project 全量(milestones,team,files,paymentPlans,invoiceRecords,afterSales) |
| 申请售后 `/project/:id/after-sales` | 三步表单(业务类型/问题描述+附件/备注)、提交生成工单 | AfterSales{type,description,attachments,remark} |
### 模块 contract(合同中心)
| 页面 | 功能点 | 数据字段 |
| --- | --- | --- |
| 合同列表 `/contract` | 关键字搜索、合同表格、去签署/详情、分页 | Contract(PRD 4.4)、ContractQuery{keyword,page} |
| 合同详情 `/contract/:id` | 合同信息只读表单、关联项目跳转、合同文件、返回 | Contract 全量 |
| 签署合同 `/contract/:id/sign` | 支付宝扫码二维码(04:32 倒计时+刷新)、四步签署指引、完成自动跳转 | signQr{url,expiresAt} |
### 模块 finance(财务中心)
| 页面 | 功能点 | 数据字段 |
| --- | --- | --- |
| 财务概览 `/finance` | 累计消费总额+月份/季度/年度切换、业务类型分布图、待支付角标、快捷入口 | financeStats{totalExpense,month,distribution[],pendingCount} |
| 账单明细 `/finance/bills` | 状态 Tab、搜索、账单表格(多选)、汇总条、批量立即支付、分页 | Bill(PRD 4.5)、BillQuery{status,keyword,page} |
| 账单详情 `/finance/bills/:id` | 订单信息卡、待支付/已支付/未到期三态展示、返回 | Bill 全量、Payment |
| 扫码支付 `/finance/bills/:id/pay` | 支付二维码(倒计时+刷新)、微信/支付宝切换弹窗、订单明细、三步指引 | Payment{method,qrCode,expiresAt,amount} |
| 支付结果 `/finance/bills/:id/pay/result` | 支付成功卡、支付信息、已支付订单列表 | Payment 结果 |
| 发票申请 `/finance/invoices` | 默认抬头卡、状态 Tab、发票表格、申请开票/预览/下载/发送邮箱、分页 | Invoice(PRD 4.5) |
| 发票抬头管理 `/finance/invoice-titles` | 抬头列表卡、新增/编辑/删除(二次确认)、设为默认 | InvoiceTitle(PRD 4.5) |
### 模块 message(消息中心)
| 页面 | 功能点 | 数据字段 |
| --- | --- | --- |
| 消息中心 `/message` | 分类 Tab(全部/在线客服/状态通知/系统通知+未读数)、搜索、全部已读、消息列表、分页 | Message(PRD 4.6)、MessageQuery{type,keyword,page} |
| 通知详情 `/message/:id` | 标题/发布时间/富文本正文/附件、返回 | Message 全量 |
### 模块 service(在线客服)
| 页面 | 功能点 | 数据字段 |
| --- | --- | --- |
| 在线客服 `/service` | 聊天窗、历史消息分割线、未读标记、文本/文件消息、Enter 发送、拖拽上传 | ChatMessage{id,role,content,file?,time} |
### 模块 profile(个人中心,左菜单嵌套布局)
| 页面 | 功能点 | 数据字段 |
| --- | --- | --- |
| 账号安全 `/profile/security` | 修改密码、绑定手机换绑、绑定/解绑邮箱、注销账号(条件校验→风险提示→身份验证→二次确认) | User(PRD 4.7) |
| 地址管理 `/profile/address` | 地址卡列表、新增/编辑/删除(二次确认)、设为默认、分页 | Address(PRD 4.7) |
| 收藏列表 `/profile/favorites` | 收藏案例卡片网格 + 筛选、分页 | Case[](复用 cases 实体) |
| 资质列表 `/profile/qualifications` | 资质卡列表、新增/编辑/删除/重新上传、审核状态、分页 | Qualification(PRD 4.7) |
| 意见反馈 `/profile/feedback` | 标题+描述+附件表单、提交反馈/重置 | Feedback{title,description,attachments} |
| 帮助中心 `/profile/help` | FAQ 折叠组(三类 Q/A) | FaqGroup[](静态) |
| 关于我们 `/profile/about` | 简介/使命/核心优势/联系信息/版本信息 | 静态+site 配置 |
| 专属客服热线 `/profile/hotline` | 热线电话+工作时间 | 静态 |
## 2. 路由规划(`src/router/routes.ts`)
```ts
export const routes = [
// ── 公开 ──
{ path: '/', name: 'Home', component: () => import('@/views/home'), meta: { title: '首页' } },
{ path: '/business/:type', name: 'BusinessDetail', component: () => import('@/views/home/detail.vue'), meta: { title: '业务详情' } },
{ path: '/cases', name: 'Cases', component: () => import('@/views/cases'), meta: { title: '成功案例库' } },
{ path: '/cases/:id', name: 'CaseDetail', component: () => import('@/views/cases/detail.vue'), meta: { title: '案例详情' } },
{ path: '/demand', name: 'Demand', component: () => import('@/views/demand'), meta: { title: '需求提报' } },
// ── 游客区 ──
{ path: '/login', name: 'Login', component: () => import('@/views/login'), meta: { title: '登录' } },
{ path: '/register', name: 'Register', component: () => import('@/views/login/register.vue'), meta: { title: '注册' } },
{ path: '/reset-password', name: 'ResetPassword', component: () => import('@/views/login/reset.vue'), meta: { title: '找回密码' } },
// ── 登录区(需守卫)──
{ path: '/project', name: 'Project', component: () => import('@/views/project'), meta: { title: '项目中心', requiresAuth: true } },
{ path: '/project/:id', name: 'ProjectDetail', component: () => import('@/views/project/detail.vue'), meta: { title: '项目详情', requiresAuth: true } },
{ path: '/project/:id/after-sales', name: 'AfterSales', component: () => import('@/views/project/after-sales.vue'), meta: { title: '申请售后', requiresAuth: true } },
{ path: '/contract', name: 'Contract', component: () => import('@/views/contract'), meta: { title: '合同中心', requiresAuth: true } },
{ path: '/contract/:id', name: 'ContractDetail', component: () => import('@/views/contract/detail.vue'), meta: { title: '合同详情', requiresAuth: true } },
{ path: '/contract/:id/sign', name: 'ContractSign', component: () => import('@/views/contract/sign.vue'), meta: { title: '签署合同', requiresAuth: true } },
{ path: '/finance', name: 'Finance', component: () => import('@/views/finance'), meta: { title: '财务中心', requiresAuth: true } },
{ path: '/finance/bills', name: 'Bills', component: () => import('@/views/finance/bills.vue'), meta: { title: '账单明细', requiresAuth: true } },
{ path: '/finance/bills/:id', name: 'BillDetail', component: () => import('@/views/finance/bill-detail.vue'), meta: { title: '账单详情', requiresAuth: true } },
{ path: '/finance/bills/:id/pay', name: 'BillPay', component: () => import('@/views/finance/pay.vue'), meta: { title: '扫码支付', requiresAuth: true } },
{ path: '/finance/bills/:id/pay/result', name: 'PayResult', component: () => import('@/views/finance/pay-result.vue'), meta: { title: '支付结果', requiresAuth: true } },
{ path: '/finance/invoices', name: 'Invoices', component: () => import('@/views/finance/invoices.vue'), meta: { title: '发票申请', requiresAuth: true } },
{ path: '/finance/invoice-titles', name: 'InvoiceTitles', component: () => import('@/views/finance/invoice-titles.vue'), meta: { title: '发票抬头', requiresAuth: true } },
{ path: '/message', name: 'Message', component: () => import('@/views/message'), meta: { title: '消息中心', requiresAuth: true } },
{ path: '/message/:id', name: 'MessageDetail', component: () => import('@/views/message/detail.vue'), meta: { title: '通知详情', requiresAuth: true } },
{ path: '/service', name: 'Service', component: () => import('@/views/service'), meta: { title: '在线客服', requiresAuth: true } },
// ── 个人中心(左菜单布局嵌套)──
{
path: '/profile', component: () => import('@/views/profile'), meta: { title: '个人中心', requiresAuth: true },
children: [
{ path: '', redirect: '/profile/security' },
{ path: 'security', name: 'ProfileSecurity', component: () => import('@/views/profile/security.vue'), meta: { title: '账号安全', requiresAuth: true } },
{ path: 'address', name: 'ProfileAddress', component: () => import('@/views/profile/address.vue'), meta: { title: '地址管理', requiresAuth: true } },
{ path: 'favorites', name: 'ProfileFavorites', component: () => import('@/views/profile/favorites.vue'), meta: { title: '收藏列表', requiresAuth: true } },
{ path: 'qualifications', name: 'ProfileQualifications', component: () => import('@/views/profile/qualifications.vue'), meta: { title: '资质列表', requiresAuth: true } },
{ path: 'feedback', name: 'ProfileFeedback', component: () => import('@/views/profile/feedback.vue'), meta: { title: '意见反馈', requiresAuth: true } },
{ path: 'help', name: 'ProfileHelp', component: () => import('@/views/profile/help.vue'), meta: { title: '帮助中心', requiresAuth: true } },
{ path: 'about', name: 'ProfileAbout', component: () => import('@/views/profile/about.vue'), meta: { title: '关于我们', requiresAuth: true } },
{ path: 'hotline', name: 'ProfileHotline', component: () => import('@/views/profile/hotline.vue'), meta: { title: '专属客服热线', requiresAuth: true } },
],
},
{ path: '/:pathMatch(.*)*', name: 'NotFound', component: () => import('@/views/404.vue'), meta: { title: '页面不存在' } },
]
```
> 路由守卫(`router/guard.ts`):`meta.requiresAuth` 未登录 → 重定向 `/login`;登录页已登录 → 重定向 `/`;切换路由时设置 `document.title`。
## 3. 四者同名映射表(模块 → 文件)
| 模块 | views/ | api/ | stores/modules/ | types/business/ | Store 名 |
| --- | --- | --- | --- | --- | --- |
| home | `views/home/`(index.vue + detail.vue) | `api/home.ts` | `stores/modules/home.ts` | `types/business/home.d.ts` | useHomeStore |
| cases | `views/cases/`(index.vue + detail.vue) | `api/cases.ts` | `stores/modules/cases.ts` | `types/business/cases.d.ts` | useCasesStore |
| demand | `views/demand/` | `api/demand.ts` | `stores/modules/demand.ts` | `types/business/demand.d.ts` | useDemandStore |
| login | `views/login/`(index.vue + register.vue + reset.vue) | `api/auth.ts` | `stores/modules/user.ts` | `types/business/user.d.ts` | useUserStore |
| project | `views/project/`(index.vue + detail.vue + after-sales.vue) | `api/project.ts` | `stores/modules/project.ts` | `types/business/project.d.ts` | useProjectStore |
| contract | `views/contract/`(index.vue + detail.vue + sign.vue) | `api/contract.ts` | `stores/modules/contract.ts` | `types/business/contract.d.ts` | useContractStore |
| finance | `views/finance/`(index.vue + bills.vue + bill-detail.vue + pay.vue + pay-result.vue + invoices.vue + invoice-titles.vue) | `api/finance.ts` | `stores/modules/finance.ts` | `types/business/finance.d.ts` | useFinanceStore |
| message | `views/message/`(index.vue + detail.vue) | `api/message.ts` | `stores/modules/message.ts` | `types/business/message.d.ts` | useMessageStore |
| service | `views/service/` | `api/service.ts` | `stores/modules/service.ts` | `types/business/service.d.ts` | useServiceStore |
| profile | `views/profile/`(index.vue 布局 + 8 子页) | `api/profile.ts` | `stores/modules/profile.ts` | `types/business/profile.d.ts` | useProfileStore |
| 站点公共 | — | — | `stores/modules/site.ts` | — | useSiteStore(全局 loading/站点配置) |
## 4. 复用性分析
### 4.1 跨页面复用 → `src/components/`
| 组件 | 复用范围 | 判定依据 |
| --- | --- | --- |
| AppHeader / AppFooter | 全站 | layout 挂载 |
| AppButton / AppSwiper | 全站 | 通用基础件 |
| CaseCard | 首页精选、案例库、收藏列表 | ≥3 页面 |
| FilterPanel(含已选条件回显) | 案例库、项目中心、收藏列表 | ≥2 页面 |
| SearchBar | 案例/项目/合同/账单/发票/消息 | ≥2 页面 |
| PaginationBar | 所有列表页 | ≥2 页面 |
| FileList + UploadArea | 需求填报、项目文件、售后、资质、意见反馈 | ≥2 页面 |
| SmsCodeInput | 登录/注册/找回/换绑手机/换绑邮箱/注销验证 | ≥2 页面 |
| PasswordStrength | 注册、修改密码 | ≥2 页面 |
| QrCodePanel | 合同签署、扫码支付 | ≥2 页面 |
| StatusTag | 项目/合同/账单/发票/资质状态 | ≥2 页面 |
| ConfirmDialog | 删除/注销等二次确认 | ≥2 页面 |
| StepForm 骨架 | 需求提报、申请售后 | ≥2 页面 |
### 4.2 页面独有 → `views/<page>/cpns/`
详见 `docs/PRD.md` 第 5.2 节组件清单。判定:仅 1 个页面使用即入 cpns/,严禁跨页面 import。
### 4.3 逻辑复用
| 逻辑 | 归属 | 使用方 |
| --- | --- | --- |
| useCountDown(验证码倒计时/二维码失效倒计时) | composables/ | SmsCodeInput、QrCodePanel |
| useLoading | composables/ | 各 store 请求态(可选) |
| useScroll(吸顶/回到顶部) | composables/ | 长列表页 |
| useIntersection(懒加载) | composables/ | 案例卡片图片 |
| v-lazy / v-debounce / v-throttle | directives/ | 图片懒加载、搜索防抖 |
| format.ts(金额/日期/千分位) | utils/ | 财务/项目展示 |
| validate.ts(手机号/邮箱) | utils/ | 表单校验 |
| storage.ts(token/草稿缓存) | utils/ | user store、需求草稿 |
## 5. 静态资源规划
```
src/assets/
├── images/ # 案例封面、业务卡片图、banner(原型导出切图后语义化命名)
├── icons/ # 业务类型图标、消息类型图标、状态图标
└── fonts/ # 如需自定义字体
```
> 切图来源:蓝湖到位前使用原型占位图;到位后按蓝湖图层语义化命名替换。