Files
nl-admin-uniapp/.cursor/rules/Code-Standards.mdc
2026-08-13 19:02:16 +08:00

221 lines
10 KiB
Plaintext
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.
---
description: nl-admin uniappVue3 + 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 重复造轮子**
- 状态管理用 Piniastore 放 `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 用 queryPOST 用 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**
- **Appapp-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、通用组件约定