221 lines
10 KiB
Plaintext
221 lines
10 KiB
Plaintext
---
|
||
description: nl-admin uniapp(Vue3 + TS + Pinia + wot-design-uni)代码规范,含分包策略
|
||
alwaysApply: true
|
||
---
|
||
|
||
# 基础规范(所有项目通用)
|
||
|
||
1. 写代码的时候要补充详细的中文注释(每个方法是干嘛的,为什么要这样写),如果是工作区,则所有项目都适用该规则
|
||
2. 注意不要生成太多的空行,上一部分代码和下一部分代码中间的空行不要大于 2 行
|
||
3. 有封装好的方法、组件需要复用,不要重复造轮子
|
||
4. 小程序端的抽屉全部需要用 `page-container` 来防止用户意外退出页面(必须用 `v-if`,禁止用 `v-show`)
|
||
5. 数据库的(created_at、updated_at、deleted_at)统一使用时间戳,不要使用字符串,并且我在查询器中一级格式化成字符串了,无需再次格式化
|
||
|
||
# 技术栈与强制复用
|
||
|
||
- 技术栈:`uni-app` + `Vue 3` + `TypeScript` + `Pinia` + **`wot-design-uni`**
|
||
- UI 优先使用 `wd-*` 组件(已配置按需自动引入),**不要引入 uview / uni-ui 重复造轮子**
|
||
- 状态管理用 Pinia,store 放 `src/stores/`,命名 `useXxxStore`
|
||
- 路径别名 `@` → `src/`
|
||
- 业务组件放 `src/components/`(PascalCase 文件名,如 `AppFooter.vue`)
|
||
- wot 组件细节可参考仓库内 `.cursor/skill/wot-ui-v2/`(以 `wot-design-uni` 实际 API 为准)
|
||
|
||
# 目录结构规范
|
||
|
||
```
|
||
src/
|
||
├── api/ # 按业务域拆分请求(如 api/user.ts)
|
||
├── components/ # 跨页面复用组件(主包可引用;分包专用组件优先放分包内)
|
||
├── pages/ # 主包页面(尽量精简)
|
||
├── pages-sub/ # 业务分包根目录(推荐;可按域再拆)
|
||
│ └── <package>/
|
||
│ ├── pages/ # 该分包页面
|
||
│ └── components/ # 仅该分包使用的组件(可选)
|
||
├── stores/ # Pinia
|
||
├── utils/ # 工具与请求封装(如 utils/request.ts)
|
||
├── static/ # 主包静态资源(大图/低频资源放分包 static)
|
||
├── pages.json
|
||
└── App.vue
|
||
```
|
||
|
||
- 页面文件:目录小写 + 页面同名或 `index.vue`(现有如 `pages/mine/mine.vue`)
|
||
- 新增业务模块时,**默认进分包**,不要往主包堆页面
|
||
|
||
# 分包规范(合理情况下尽量使用分包)
|
||
|
||
微信小程序主包体积有限,本项目约定:**能进分包的业务页就进分包**,主包只保留启动与高频入口。
|
||
|
||
## 主包只放这些
|
||
|
||
- TabBar 页面(工作台、功能、我的)
|
||
- 登录 / 启动过渡 / 协议等冷启动必经页
|
||
- 全局强依赖且体积很小的公共组件与工具
|
||
|
||
## 必须进分包的场景
|
||
|
||
- 相对独立的业务域(订单、设置、详情、表单流程、活动页等)
|
||
- 非 Tab、非启动链路的列表/详情/编辑页
|
||
- 带较多图片、图表、富文本、第三方能力的页面
|
||
- 预计会持续扩页的模块(提前建分包,避免后期迁移)
|
||
|
||
## 可以留在主包的例外
|
||
|
||
- 体积很小、且被多个分包/Tab **同步高频**跳转的极少数页面
|
||
- 拆出去会导致首跳体验明显变差,又无法用 `preloadRule` 弥补时,可暂留主包(需在 PR/注释说明原因)
|
||
|
||
## pages.json 约定
|
||
|
||
```json
|
||
{
|
||
"pages": [
|
||
{ "path": "pages/index", "type": "home" },
|
||
{ "path": "pages/mine/mine" }
|
||
],
|
||
"subPackages": [
|
||
{
|
||
"root": "pages-sub/order",
|
||
"name": "order",
|
||
"pages": [
|
||
{ "path": "pages/list", "style": { "navigationBarTitleText": "订单列表" } },
|
||
{ "path": "pages/detail", "style": { "navigationBarTitleText": "订单详情" } }
|
||
]
|
||
}
|
||
],
|
||
"preloadRule": {
|
||
"pages/index": {
|
||
"network": "wifi",
|
||
"packages": ["order"]
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
- `subPackages[].root` 用 `pages-sub/<域>`,`name` 用短英文域名单词
|
||
- 跳转路径写完整:`/pages-sub/order/pages/list`(注意前导 `/`)
|
||
- 同一业务域页面放同一分包;**禁止**把无关页面塞进同一个大分包「垃圾桶」
|
||
- 单个分包也要控制体积;过大时按子域再拆(如 `order` / `order-aftersale`)
|
||
- 需要加速首跳时配置 `preloadRule`(优先 wifi;不要无脑预下载全部包)
|
||
- 分包之间避免强耦合互相引用页面内私有组件;跨包复用下沉到主包 `src/components/` 或 `src/utils/`
|
||
- 新增页面时同步改 `pages.json`,未注册会无法打开
|
||
|
||
# 抽屉 / 弹层规范
|
||
|
||
- **抽屉类全屏/半屏面板**(筛选、详情抽屉、复杂表单层):必须用微信 `page-container` + `v-if` 控制挂载,防止侧滑/返回直接退出页面
|
||
- 简单轻量反馈用 wot:`wd-popup` / `wd-toast` / `wd-message-box` 等;Toast/Dialog 按 wot 要求在页面内放置组件实例
|
||
- 禁止用 `v-show` 控制 `page-container` 显隐
|
||
|
||
```vue
|
||
<!-- 正确:抽屉用 page-container + v-if -->
|
||
<page-container v-if="drawerVisible" :show="drawerVisible" @afterleave="drawerVisible = false">
|
||
<!-- 抽屉内容 -->
|
||
</page-container>
|
||
```
|
||
|
||
# 请求与数据约定
|
||
|
||
- HTTP 统一走封装(建议 `src/utils/request.ts` + `src/api/<域>.ts`),**禁止**页面内直接 `uni.request`
|
||
- API 函数命名:`getXxxList` / `getXxxInfo` / `createXxx` / `updateXxx` / `deleteXxx`
|
||
- URL kebab-case,与后台自动路由风格对齐;GET 用 query,POST 用 body
|
||
- 接口字段保持后端 snake_case(如 `created_at`、`nick_name`),模板/入参不要擅自改成 camelCase
|
||
- 时间字段后端已格式化为字符串时,前端无需再次格式化
|
||
- Token / 登录态放 Pinia(或统一 storage 工具),在请求封装里集中注入与 401 处理
|
||
|
||
# 页面与组件写法
|
||
|
||
- 统一 `<script setup lang="ts">`
|
||
- 每个页面/组件 script 顶部用中文说明用途
|
||
- 有业务逻辑的函数必须写中文注释(做什么、为什么)
|
||
- 样式优先 `scoped`;尺寸用 rpx;颜色尽量走主题变量(`theme.json` / wot CSS 变量),避免散落魔法色值
|
||
- 列表分页、表单校验、空态/加载态要完整,不要只做「能点开」的半成品
|
||
- **下拉刷新(强制)**:有数据列表的页面必须支持下拉刷新;`pages.json` 开 `enablePullDownRefresh`,逻辑用 `usePullRefresh(reload)`(见 `src/composables/usePullRefresh.ts`);内层 `scroll-view`/`swiper` 页改用 `refresher-enabled`
|
||
|
||
# 命名规范
|
||
|
||
| 维度 | 规范 | 示例 |
|
||
|---|---|---|
|
||
| 页面目录/文件 | 小写或 kebab | `pages-sub/order/pages/list.vue` |
|
||
| 组件文件 | PascalCase | `OrderCard.vue` |
|
||
| Store | `useXxxStore` | `useUserStore` |
|
||
| API 函数 | camelCase | `getOrderList` |
|
||
| 常量 | UPPER_SNAKE_CASE | `ORDER_STATUS_OPTIONS` |
|
||
|
||
# 禁止事项
|
||
|
||
- 禁止把大量业务页塞进主包 `src/pages/`
|
||
- 禁止引入第二套 UI 库(uview 等)与 `wot-design-uni` 混用
|
||
- 禁止在业务页复制粘贴请求头、baseURL、token 逻辑
|
||
- 禁止抽屉不用 `page-container`、或用 `v-show` 控制抽屉
|
||
- 禁止提交无中文注释的复杂业务逻辑
|
||
- 禁止把 PC 后台表格/工具栏交互原样搬到小程序
|
||
- 禁止业务页自写一套分类 Tab / 顶部筛选(必须用通用组件)
|
||
|
||
# 三端兼容(强制)
|
||
|
||
业务代码与代码生成产物必须同时可运行于:
|
||
|
||
- **微信小程序(mp-weixin)**
|
||
- **App(app-plus)**
|
||
- **H5**
|
||
|
||
约定:
|
||
|
||
- 优先使用 `uni.*` 跨端 API;仅在确有差异处使用 `#ifdef MP-WEIXIN / APP-PLUS / H5`,并写中文注释说明原因
|
||
- 禁止依赖仅某一端可用的 DOM / BOM / 私有组件而不做兜底
|
||
- TabBar、分包、`page-container` 等能力按三端都能接受的方式实现
|
||
|
||
# C 端 UI 风格(强制)
|
||
|
||
能力可以是超管,**视觉与交互必须按 C 端消费级 App**,禁止做成缩小版 PC 后台:
|
||
|
||
- 信息架构:卡片流 / 分组列表 / 宫格入口;一行一事;禁止宽表、多列表头
|
||
- 触控:点击区域 ≥ 44px(约 88rpx);主操作底部大按钮或悬浮主按钮
|
||
- 视觉:大圆角、留白、主题色走 `theme.json` / `uni.scss` 中的 `$nl-*`(详见 `Uniapp-Scss.mdc`)
|
||
- 反馈:空态、Toast;危险操作再用确认框
|
||
- 登录 / 我的:品牌区 + 表单;头像 Hero + 单元格菜单
|
||
- **列表 CRUD 交互(强制)**:列表点击 → **详情页** → 底栏「编辑」→ **全屏表单页**;新增也走全屏表单
|
||
- **禁止**列表点开底部抽屉做主 CRUD(`AppFormDrawer` 仅轻量选择器可用)
|
||
- 系统配置:设置卡 / 入口列表,敏感信息脱敏
|
||
- 详情页结构:`AppDetailHero` + `AppInfoGroup` + `AppBottomBar`
|
||
- 表单页结构:`AppPageForm`(分组字段 + 底栏提交)
|
||
|
||
# TabBar 信息架构(强制)
|
||
|
||
主包 Tab 固定为三页:
|
||
|
||
| Tab | 路径 | 职责 |
|
||
|-----|------|------|
|
||
| 工作台 | `pages/workbench/index` | 概览、快捷入口、最近使用 |
|
||
| 功能 | `pages/feature/index` | 应用中心:分类浏览 + 筛选 + 入口列表 |
|
||
| 我的 | `pages/mine/mine` | 个人中心 |
|
||
|
||
登录页不进 TabBar。业务深度页进 `pages-sub/*`。
|
||
|
||
## 功能页约定
|
||
|
||
- 分类 Tab 默认 **全部**;支持点击与 **左右滑动(swiper)** 切换
|
||
- 分类选中态本地记忆(如 `nl_feature_tab_key`)
|
||
- 筛选项在分类 Tab **下方顶部**,默认收起摘要行,支持展开/收起;筛选条件可本地记忆
|
||
- 入口数据来自 `src/config/features.ts` 注册表;新增能力必须登记
|
||
|
||
# 通用组件优先(禁止重复造轮子)
|
||
|
||
优先复用 `src/components/`:
|
||
|
||
- `AppPageAtmosphere`:页面氛围底(色斑渐变),毛玻璃卡片必须叠在此上才有「透」感
|
||
- `AppGlassCard`:**统一毛玻璃卡片容器**(variant / pressable / title);禁止业务页自写半透明卡片
|
||
- `AppCategoryTabs`:分类 Tab + 可选本地记忆
|
||
- `AppFilterBar`:顶部可展开筛选壳
|
||
- `AppSearchBar` / `AppFeatureList` / `AppCardList` / `AppEmpty` / `AppSkeleton` / `AppLoading`
|
||
- `AppDetailHero` / `AppInfoGroup` / `AppBottomBar` / `AppPageForm`:详情与全屏表单
|
||
- `AppFormDrawer`:非主路径,仅轻量选择器;CRUD 禁止用
|
||
- `AppShortcutGrid`:工作台快捷宫格
|
||
- `AppTabBar`:悬浮自定义 TabBar(`wd-tabbar` shape=round)
|
||
|
||
新需求先扩展上述组件,禁止业务页复制一套 Tab/筛选/抽屉/毛玻璃卡片。
|
||
|
||
# 代码生成产物落点
|
||
|
||
- 粘贴目录:`src/pages-sub/my-gen/<dash-case>/`
|
||
- 同步改 `pages.json` 的 `my-gen` 分包,并在 `src/config/features.ts` 登记(`category: 'gen'`)
|
||
- 生成模板必须遵守本文件的三端兼容、C 端 UI、通用组件约定
|