feat: 对齐 vue 研发项目基础设施并落地列表页规范样板
- 新增 axios/utils/directives/api/assets 五大基础设施目录(与生产 vue 项目 1:1) - 重构 FilterBar / TableCard 支持 :table 对象与 default slot - 新增列表页/弹框/抽屉/详情页/Tabs 等代码规范文档 - arcEmployee 作为新规范标准列表页样板重构 - 清理 .claude/tmp 临时截图
This commit is contained in:
@@ -98,7 +98,7 @@ yx-platform-prototype/
|
||||
│ └── user_profile.md 用户画像
|
||||
│
|
||||
└── src/
|
||||
├── main.ts 应用入口:创建 Vue 实例、挂载 router
|
||||
├── main.ts 应用入口:创建 Vue 实例、挂载 router、注册指令、初始化 antd 静态方法、加载 mock handlers
|
||||
├── App.vue 根组件,仅 <router-view />
|
||||
├── style.css 全局设计令牌(CSS 变量)+ reset
|
||||
│
|
||||
@@ -113,6 +113,34 @@ yx-platform-prototype/
|
||||
│ - admin: adminApps;tenant: tenantApps(含 nutrition / monitor 完整三层菜单)
|
||||
│ - status + audience 字段控制可见性
|
||||
│
|
||||
├── axios/ 🆕 假 axios 层(与 vue 研发项目签名 1:1,研发接手时整体替换)
|
||||
│ ├── index.ts getRequest / postRequest / putRequest / deleteRequest / restfulRequest / uploadRequest / downloadRequest
|
||||
│ ├── mockBus.ts mock 总线(registerMock / dispatchMock / 200~500ms 模拟延迟)
|
||||
│ ├── types.ts ApiResponse / ServiceType / MockHandler 等
|
||||
│ └── handlers/ mock handler 注册(按 <模块>/<页面>.ts 组织)
|
||||
│ ├── index.ts 统一 import 触发副作用
|
||||
│ └── nutrition/employee.ts
|
||||
│
|
||||
├── api/
|
||||
│ └── index.ts 🆕 跨模块公共接口(字典 / 部门树 / 组织树)
|
||||
│
|
||||
├── utils/ 🆕 业务工具(与 vue 研发项目 @utils 1:1)
|
||||
│ └── antDesign/
|
||||
│ ├── table.ts TableState / TableSort / createPaginationConfig / createDataSourceChange / createResetTable / resizeColumn / createRowSelection
|
||||
│ ├── popUp.ts useAntdStaticMethods / initializeAntdStaticMethods
|
||||
│ └── select.ts filterOption
|
||||
│
|
||||
├── directives/ 🆕 自定义指令(与 vue 研发项目 @directives 1:1)
|
||||
│ ├── index.ts registerDirectives 全局注册
|
||||
│ ├── noSpace.ts v-no-space
|
||||
│ ├── onlyNumber.ts v-only-number
|
||||
│ ├── onlyAlphanumeric.ts v-only-alphanumeric
|
||||
│ └── onlyAlphanumericSpecial.ts v-only-alphanumeric-special
|
||||
│
|
||||
├── assets/ 🆕 静态资源 + 公共样式
|
||||
│ └── styles/
|
||||
│ └── listPage.less 列表页统一布局(listPageForm / listPageRow / listPageTable / page-header / page-footer)
|
||||
│
|
||||
├── composables/ 复用逻辑
|
||||
│ └── useVisibility.ts 可见性核心:角色、过滤、覆写存取
|
||||
│
|
||||
@@ -128,8 +156,8 @@ yx-platform-prototype/
|
||||
│
|
||||
├── components/ 公共业务组件(被自动注册到 AntDV 风格)
|
||||
│ ├── StatCard.vue 统计卡(4 色配色)
|
||||
│ ├── FilterBar.vue 配置驱动搜索栏(5 种字段类型)
|
||||
│ ├── TableCard.vue 表格卡(无 title;#toolbar 左上、#extra 右上、a-table 全部透传)
|
||||
│ ├── FilterBar.vue 搜索栏(default slot 裸 a-form-item / 兼容 fields 配置驱动)
|
||||
│ ├── TableCard.vue 表格卡(接 :table 对象 TableState;#toolbar 左上、#extra 右上)
|
||||
│ ├── PageHeader.vue 页头(保留供详情页用,列表页不应使用)
|
||||
│ ├── PlaceholderPage.vue 后台占位页(接 title/name)
|
||||
│ └── AppPlaceholder.vue 移动端占位页(接 title/name)
|
||||
@@ -153,7 +181,7 @@ yx-platform-prototype/
|
||||
│ │ │ └── AppGrid.vue 🌟 租户应用网格首页(卡片入口)
|
||||
│ │ ├── nutrition/ 营养管理应用
|
||||
│ │ │ ├── arc/ 档案(一级菜单)
|
||||
│ │ │ │ ├── arcEmployee/ ⭐ 标准列表页样板(六文件)
|
||||
│ │ │ │ ├── arcEmployee/ ⭐ 新规范标准列表页样板(TableState + reactive 搜索 + mock handler + addOrEdit 弹框)
|
||||
│ │ │ │ └── ArcUnit.vue
|
||||
│ │ │ └── farm/ 绿色种采(一级菜单)
|
||||
│ │ │ └── FarmLand.vue
|
||||
@@ -169,8 +197,16 @@ yx-platform-prototype/
|
||||
│ ├── arc-employee.md
|
||||
│ └── screenshots/<页面>/<状态>.jpg 截图(≤60KB)
|
||||
│
|
||||
├── docs/ 业务文档
|
||||
│ └── business-architecture.md 🌟 业务架构(AI 必读)
|
||||
├── docs/ 业务文档 + 代码规范(AI 必读)
|
||||
│ ├── business-architecture.md 🌟 业务架构
|
||||
│ ├── cross-project-mapping.md 🆕 原型 ↔ vue 研发项目对照表
|
||||
│ ├── list-page-spec.md 🆕 列表页规范
|
||||
│ ├── modal-spec.md 🆕 弹框规范
|
||||
│ ├── drawer-spec.md 🆕 抽屉规范
|
||||
│ ├── detail-page-spec.md 🆕 详情页规范
|
||||
│ ├── tabs-page-spec.md 🆕 Tabs 页规范
|
||||
│ ├── utils-table.md 🆕 表格工具文档
|
||||
│ └── utils-popup.md 🆕 弹窗工具文档
|
||||
│
|
||||
└── types/ 全局类型声明(自动生成 + 手写 shims)
|
||||
├── auto-imports.d.ts unplugin-auto-import 生成
|
||||
@@ -182,15 +218,20 @@ yx-platform-prototype/
|
||||
|
||||
## 路径别名
|
||||
|
||||
| 别名 | 指向 |
|
||||
|------|------|
|
||||
| `@` | `src/` |
|
||||
| `@meta` | `src/meta/` |
|
||||
| `@layouts` | `src/layouts/` |
|
||||
| `@components` | `src/components/` |
|
||||
| `@composables` | `src/composables/` |
|
||||
| `@pages` | `src/pages/` |
|
||||
| `@router` | `src/router/` |
|
||||
| 别名 | 指向 | 与 vue 研发项目对齐 |
|
||||
|------|------|-------------------|
|
||||
| `@` | `src/` | ✅ |
|
||||
| `@meta` | `src/meta/` | 原型特有(菜单数据) |
|
||||
| `@layouts` | `src/layouts/` | ✅ |
|
||||
| `@components` | `src/components/` | ✅ |
|
||||
| `@composables` | `src/composables/` | 原型特有 |
|
||||
| `@pages` | `src/pages/` | 研发项目用 `@views` |
|
||||
| `@router` | `src/router/` | ✅ |
|
||||
| `@utils` | `src/utils/` | ✅ 1:1 |
|
||||
| `@axios` | `src/axios/` | ✅ 1:1 |
|
||||
| `@assets` | `src/assets/` | ✅ 1:1 |
|
||||
| `@directives` | `src/directives/` | ✅ 1:1 |
|
||||
| `@api` | `src/api/` | ✅ 1:1 |
|
||||
|
||||
---
|
||||
|
||||
@@ -212,25 +253,65 @@ yx-platform-prototype/
|
||||
3. **URL 规范**:`/<portal>/<app>/<section>/<page>`,例:`/tenant-portal/nutrition/nutrition-farm/monitor/crop`
|
||||
4. **列表页 UI 规范(重要)**:
|
||||
- **不渲染 PageHeader**(菜单 + 顶部历史栏已经表达所在位置)
|
||||
- **TableCard 不显示 title**
|
||||
- **主操作按钮**(导出/新增/批量等)放在 `TableCard #toolbar` 左上方
|
||||
- **TableCard 接 `:table` 对象**(推荐)或拆分 props(兼容);不显示 title
|
||||
- **FilterBar 用 default slot** 写裸 a-form-item(推荐),或 `:fields` 配置驱动(兼容)
|
||||
- **顶部 toolbar 按钮**(导出/新增/导入/批量删除等)放 `TableCard #toolbar` 左上方,必须带 antd icon
|
||||
- **操作列 `<a-button type="link">` 一律不加图标**(对齐 vue 研发项目);多个按钮之间用 `<a-divider type="vertical" />` 分隔
|
||||
- **次要操作**放在 `TableCard #extra` 右上方
|
||||
- **统计卡**放在 `FilterBar` 上方(可选)
|
||||
- **顶栏高度**:固定 64px(对齐 vue 研发项目 `<a-layout-header>` 默认高度)
|
||||
- **CRUD 不是列表页标配**:是否有"新增/编辑/删除/导出"按由业务决定;只读查询页操作列可以只有"查看详情"
|
||||
5. **图标规范(强制)**:
|
||||
- 所有菜单图标 / 操作按钮图标必须取自 `@ant-design/icons-vue` 4.x,**禁止使用 emoji / 自定义 svg**
|
||||
- NavSection / NavGroup:必填 `icon: 'XxxOutlined'`
|
||||
- NavLeaf:可选;layouts 渲染时未指定则二级用 FileOutlined / 三级用 MinusOutlined 兜底
|
||||
- 操作按钮标准映射:查询=SearchOutlined / 重置=RedoOutlined / 新增=PlusOutlined / 编辑=EditOutlined / 删除=DeleteOutlined / 导入=UploadOutlined / 导出=DownloadOutlined / 查看详情=EyeOutlined / 查看任务=UnorderedListOutlined
|
||||
- 应用图标(NavApp.icon)允许 emoji(仅在应用网格首页 + 左上角应用切换器显示)
|
||||
5. **端隔离**:4 端不允许互相 import;共享仅通过 `@components` / `@layouts` / `@meta` / `@composables`
|
||||
6. **应用隔离**:同一 portal 下不同应用之间也不应相互 import(对齐 vue 项目"子应用独立部署");共享只能走 nav.ts 的公共抽象
|
||||
7. **列表页固定 6 文件结构**:`<页面>.vue + types + api + init/(usePage + useSearch + useTable)`
|
||||
8. **Mock 数据**:写在 `init/useTable.ts` 的 dataList
|
||||
9. **公共组件优先**:StatCard / FilterBar / TableCard / PlaceholderPage
|
||||
10. **TS 严格**:禁止 any
|
||||
11. **中文注释**
|
||||
12. **可见性**:每个 NavLeaf 有 `status`(draft/review/ready)+ `audience`(designer/all),dev 角色看不到 draft 或 designer-only 的页面
|
||||
13. **PRD 截图体积**:Web ≤ 60KB、小程序 ≤ 60KB、硬件 ≤ 80KB;优先 puppeteer,失真时降级 chrome-devtools MCP
|
||||
6. **端隔离**:4 端不允许互相 import;共享仅通过 `@components` / `@layouts` / `@meta` / `@composables`
|
||||
7. **应用隔离**:同一 portal 下不同应用之间也不应相互 import(对齐 vue 项目"子应用独立部署");共享只能走 nav.ts 的公共抽象
|
||||
8. **列表页固定 6 文件结构**:`<页面>.vue + types + api + init/(usePage + useSearch + useTable)`,子组件按需追加 `component/modal/<名>/` 或 `component/drawer/<名>/`
|
||||
9. **Mock 数据**:必须写在 `src/axios/handlers/<模块>/<页面>.ts`,通过 `registerMock(s)` 注册;**禁止写在 useTable.ts**;**单个 mock dataset 不得超过 10 条**(原型展示而非性能压测)
|
||||
10. **国际化**:根组件 `App.vue` 必须用 `<a-config-provider :locale="zhCN">` 包裹,分页等组件显示为"30 条/页"等中文格式
|
||||
11. **HTTP 调用**:业务层走 `src/axios` 的 `postRequest/getRequest/restfulRequest`(签名与 vue 研发项目 1:1),不直接 import axios
|
||||
12. **弹窗静态方法**:必须 `useAntdStaticMethods()` 获取 `message/Modal/notification`,禁直接 `import { message } from 'ant-design-vue'`
|
||||
13. **请求风格**:强制 `.then().catch().finally()` 链式,**禁用 `async/await`**
|
||||
14. **函数声明**:全部用箭头函数 `const x = () => {}`,**禁用 `function` 关键字**
|
||||
15. **表格状态**:`useTable` 必须返回 `TableState` 统一对象,`table.dataSource` 存数据,**禁单独 `dataList` ref**
|
||||
16. **搜索状态**:`useSearch` 必须用 `reactive + createSearchKey()` 工厂函数 + `Object.assign(search, createSearchKey())` 重置
|
||||
17. **子组件 ref**:必须在父 `usePage.ts` 定义(禁在 `.vue` 定义);打开方法命名 `open + 组件名`
|
||||
18. **子组件 emit**:Modal 用 `load`,Drawer 用 `ok`
|
||||
19. **删除二次确认**:必须 `Modal.confirm` + `okType: 'danger'`;批量按钮 `:disabled="!selectedRowKeys.length"`
|
||||
20. **空值展示**:统一 `{{ x ?? '—' }}`(禁空串/null)
|
||||
20. **时间格式**:时间 `YYYY-MM-DD HH:mm:ss`,日期 `YYYY-MM-DD`
|
||||
21. **ID 类型**:统一 `string | undefined`(禁 number)
|
||||
22. **公共组件优先**:StatCard / FilterBar / TableCard / PlaceholderPage
|
||||
23. **TS 严格**:禁止 any
|
||||
24. **中文注释**
|
||||
25. **可见性**:每个 NavLeaf 有 `status`(draft/review/ready)+ `audience`(designer/all),dev 角色看不到 draft 或 designer-only 的页面
|
||||
26. **PRD 截图体积**:Web ≤ 60KB、小程序 ≤ 60KB、硬件 ≤ 80KB;优先 puppeteer,失真时降级 chrome-devtools MCP
|
||||
27. **代码规范文档**:详见 `src/docs/`(list-page-spec / modal-spec / drawer-spec / detail-page-spec / tabs-page-spec / cross-project-mapping / utils-table / utils-popup)
|
||||
|
||||
---
|
||||
|
||||
## 与 vue 研发项目的对齐策略
|
||||
|
||||
本项目最高目标:**研发接手时改动最小**。详见 `src/docs/cross-project-mapping.md`。
|
||||
|
||||
| 对齐项 | 原型现状 | 研发项目 |
|
||||
|--------|---------|---------|
|
||||
| HTTP 签名 | 假 axios + mockBus + handlers | 真 axios + 拦截器 |
|
||||
| 业务代码(api/usePage/useTable/useSearch) | 100% 与研发一致 | 100% 与原型一致 |
|
||||
| 公共组件 | TableCard / FilterBar(支持 :table / default slot) | 裸 a-table / a-form |
|
||||
| Mock 数据 | `src/axios/handlers/` | 删除即可 |
|
||||
| 路径别名 | 与研发项目 1:1 | 同左 |
|
||||
|
||||
迁移步骤(研发接手时):
|
||||
1. 替换 `src/axios/` 为真实 axios 封装(保留方法签名)
|
||||
2. 删除 `src/axios/handlers/`
|
||||
3. 删除原型独有页面(gate / console / prd / overview)和 composables(useVisibility)
|
||||
4. 把 `<TableCard :table>` 拆为 `<a-row class="listPageTable">` + `<a-table>`
|
||||
5. 把 `<FilterBar v-model>` 拆为 `<a-row class="listPageForm">` + `<a-form>`
|
||||
6. 业务逻辑 100% 不改
|
||||
|
||||
---
|
||||
|
||||
@@ -262,19 +343,66 @@ yx-platform-prototype/
|
||||
|
||||
## 禁止事项
|
||||
|
||||
### 文件 / 跨模块
|
||||
- 禁止跨页面修改其他模块的代码
|
||||
- 禁止在 .vue 的 setup 里直接写表格 columns 数组、mock 数据数组
|
||||
- 禁止跨端引用页面(admin ↛ tenant ↛ miniprogram ↛ hardware)
|
||||
- 禁止跨应用引用页面(不同 NavApp 之间不能互相 import,模拟独立部署)
|
||||
- 禁止修改 `src/components/` 的公共组件(除非走 PR 评审)
|
||||
- 禁止把 Vant 组件用在后台页面(admin/tenant),反之亦然
|
||||
- 禁止在 `src/api/index.ts` 写业务私有接口(仅放跨模块公共接口)
|
||||
|
||||
### 列表页结构
|
||||
- 禁止省略 init 三件套(即使只有 1 列表格也要独立 useTable.ts)
|
||||
- 禁止把业务逻辑写在模板(所有逻辑通过 usePage 等 hook 暴露)
|
||||
- 禁止使用 `any` 类型
|
||||
- 禁止在列表页渲染 PageHeader(含面包屑/标题/副标题)
|
||||
- 禁止给 TableCard 传 title(菜单已表达所在位置)
|
||||
- 禁止给 TableCard 显式传 title(菜单已表达所在位置)
|
||||
- 禁止把主操作按钮放在页面顶部独立位置(必须放 TableCard #toolbar)
|
||||
|
||||
### Mock / 接口
|
||||
- 禁止把 mock 数据写在 `useTable.ts`,必须放 `src/axios/handlers/<模块>/<页面>.ts`
|
||||
- 禁止单个 mock dataset 超过 **8 条**(原型用于展示而非性能压测)
|
||||
- 禁止在业务代码直接 `import axios`,必须走 `src/axios` 的 postRequest / getRequest
|
||||
- 禁止在 `api/index.ts` 写业务判断(如 `if res.code === '00000'`),只做 HTTP 调用
|
||||
|
||||
### 代码风格
|
||||
- 禁止使用 `async/await`,请求统一 `.then().catch().finally()` 链式
|
||||
- 禁止使用 `function` 关键字,所有函数用箭头函数 `const x = () => {}`
|
||||
- 禁止直接 `import { message } from 'ant-design-vue'`,必须 `useAntdStaticMethods()`
|
||||
- 禁止使用 `any` 类型
|
||||
|
||||
### Hook 拆分
|
||||
- 禁止在 `useTable.ts` 调接口,列表请求只在 `usePage.ts` 发起
|
||||
- 禁止在 `usePage.ts` 维护独立 `dataList` ref,数据统一存 `table.dataSource`
|
||||
- 禁止在 `usePage.ts` 写表格列定义(应在 useTable.ts)或下拉请求(应在 useSearch.ts)
|
||||
- 禁止 `useSearch` 用 `Object.keys` 遍历清空,必须 `Object.assign(search, createSearchKey())`
|
||||
- 禁止 `searchQuery` 调 `resetTable()`(会清空排序),必须 `table.pagination.current = 1` 后 `listRequest()`
|
||||
- 禁止在父 `.vue` 中定义子组件 ref,必须在父 `usePage.ts` 中定义
|
||||
- 禁止子组件打开方法命名无意义(如 `open / show / visible`),必须 `open + 组件名`
|
||||
|
||||
### Modal / Drawer
|
||||
- 禁止在弹框/抽屉的 `.vue` 写业务逻辑
|
||||
- 禁止 a-modal 不加 `:keyboard="false" :mask-closable="false"`(防止编辑数据丢失)
|
||||
- 禁止省略 `finally` 中的 `pageInfo.spin = false`
|
||||
- 禁止用 `pageInfo.title / type` 文本做新增/编辑判断,必须用 `params.id`
|
||||
- 禁止 addRequest 中保留 id 字段(必须 `delete params.id`)
|
||||
- 禁止省略 a-drawer(含列表型)的 `destroy-on-close`
|
||||
|
||||
### 数据展示
|
||||
- 禁止删除/批量操作不经二次确认(必须 `Modal.confirm` + `okType:'danger'`)
|
||||
- 禁止批量操作按钮在未选中数据时可点击(必须 `:disabled="!selectedRowKeys.length"`)
|
||||
- 禁止空值字段展示为空字符串或 `null`(统一 `?? '—'`)
|
||||
- 禁止时间/日期格式不统一(时间 `YYYY-MM-DD HH:mm:ss`,日期 `YYYY-MM-DD`)
|
||||
|
||||
### 图标 / UI
|
||||
- 禁止使用 emoji / 自定义 svg 作为菜单或按钮图标(必须用 @ant-design/icons-vue)
|
||||
- 禁止把 Vant 组件用在后台页面(admin/tenant),反之亦然
|
||||
- **禁止给操作列的 `<a-button type="link">` 加任何图标**(对齐 vue 研发项目,操作列纯文字)
|
||||
- **禁止 AI 脚手架默认生成"新增/编辑/删除"按钮**(CRUD 不是列表页标配,必须由用户明确指定页面功能)
|
||||
- 禁止操作列多个按钮之间不加 `<a-divider type="vertical" />` 分隔
|
||||
- 禁止在列定义的 `customRender` 中写 JSX,统一用 `h()` 函数
|
||||
- 禁止 `a-input-number` 不设 `style="width: 100%"`
|
||||
- 禁止顶栏高度偏离 64px(必须与 vue 研发项目 `<a-layout-header>` 默认高度一致)
|
||||
- 禁止 App.vue 漏写 `<a-config-provider :locale="zhCN">`(否则分页等组件显示英文)
|
||||
|
||||
### 原型独有
|
||||
- 禁止把截图存到 PRD 目录之外(如 public/)
|
||||
- 禁止生成 > 60KB 的单张 Web/小程序截图
|
||||
- 禁止在 Web 后台调用 `/design-overview` skill(仅支持小程序/硬件)
|
||||
|
||||
Reference in New Issue
Block a user