mirror of
https://github.com/ialley-workshop-open/uni-halo.git
synced 2026-09-12 16:40:40 +08:00
refactor: 架构升级
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
# unibest · Hermes 规范
|
||||
|
||||
> Hermes = 项目的信使:把工程规范传递给每一位开发者(和 AI)。
|
||||
|
||||
基于 unibest 4.4.1(uni-app + Vue3 + TS + Vite5 + UnoCSS)的实际配置提炼。
|
||||
|
||||
## 三条铁律
|
||||
|
||||
1. **生成物不手改**:`src/pages.json`、`src/manifest.json`、`src/types/*.d.ts` 全部由 `*.config.ts` 生成,手改会在下次构建被覆盖
|
||||
2. **平台差异只用条件编译**:`#ifdef H5 / #ifdef MP-WEIXIN / #ifdef APP-PLUS`,编译期能确定的不留到运行时
|
||||
3. **UI 优先原子类**:先 UnoCSS 原子类,再考虑自定义 CSS
|
||||
|
||||
## 文档索引
|
||||
|
||||
| 文件 | 内容 |
|
||||
|------|------|
|
||||
| [architecture.md](./architecture.md) | 架构规范:事实源与生成物、平台接缝、校验边界、目录分层 |
|
||||
| [conventions.md](./conventions.md) | 代码规范:命名、SFC 结构、TS、状态、提交与验证命令 |
|
||||
| [platforms.md](./platforms.md) | 平台适配手册:差异决策树、条件编译速查、本项目差异点表、多端地址 |
|
||||
| [api.md](./api.md) | 请求层规范:分层、httpGet/Post 用法、错误四分类、401 双 token 策略 |
|
||||
| [sop-new-page.md](./sop-new-page.md) | 新页面/组件/分包/tabbar/hooks SOP 与验证清单 |
|
||||
| [performance.md](./performance.md) | 性能与分包:主包体积、内置优化表、包体积检查、编码侧规则 |
|
||||
| [release.md](./release.md) | 发布流程:upload:mp 全流程、changesets、uvm 升级、环境切换、合入门禁 |
|
||||
|
||||
## 常用命令
|
||||
|
||||
```bash
|
||||
pnpm dev # H5 开发
|
||||
pnpm dev:mp # 微信小程序开发
|
||||
pnpm dev:app # APP 开发
|
||||
pnpm build:mp # 微信小程序生产构建
|
||||
pnpm type-check # vue-tsc 类型检查(合入前必过)
|
||||
pnpm lint:fix # ESLint 修复
|
||||
pnpm test:run # vitest 单次运行
|
||||
```
|
||||
@@ -0,0 +1,67 @@
|
||||
# 请求层规范
|
||||
|
||||
> 事实源:`src/http/http.ts`(请求封装)+ `src/http/interceptor.ts`(拦截器)。本文规则均来自这两个文件的实际行为。
|
||||
|
||||
## 1. 分层
|
||||
|
||||
```
|
||||
页面/组件
|
||||
↓ 只调用
|
||||
src/api/* # 接口定义 + 类型声明
|
||||
↓ 只调用
|
||||
src/http/http.ts # httpGet/httpPost/httpPut/httpDelete
|
||||
↓ 自动经过
|
||||
src/http/interceptor.ts # URL 拼接、token 注入、超时
|
||||
↓
|
||||
uni.request / uni.uploadFile
|
||||
```
|
||||
|
||||
业务代码**禁止**直接调 `uni.request`;新接口一律在 `src/api/` 按模块建文件并声明入参/出参类型。
|
||||
|
||||
## 2. 调用方式
|
||||
|
||||
```ts
|
||||
import { httpGet, httpPost } from '@/http'
|
||||
|
||||
// GET(query 自动序列化拼接)
|
||||
const data = await httpGet<IUser>('/user/info', { id: 1 })
|
||||
|
||||
// POST:第二参是 body,第三参是 query(微信系接口常用,勿省)
|
||||
await httpPost<ILoginRes>('/login', { username, password }, { platform: 'wx' })
|
||||
```
|
||||
|
||||
- `http<T>` 直接 resolve 业务 `data`(响应契约 `{ code, data, ... }` 已在封装内拆包)
|
||||
- 超时 60s、`Authorization: Bearer <token>` 均由拦截器注入,**业务不手写请求头 token**
|
||||
|
||||
## 3. 错误处理(类型归一)
|
||||
|
||||
catch 到的永远是 `HttpError`,`type` 四选一,按需分支:
|
||||
|
||||
| type | 触发 | 默认行为 |
|
||||
|------|------|---------|
|
||||
| `Auth` | HTTP 401 或业务码 401 | 封装内已处理(见下),业务只需 catch |
|
||||
| `Business` | HTTP 2xx 但业务码失败 | 自动 toast 错误消息 |
|
||||
| `Http` | 非 2xx 状态码 | 自动 toast |
|
||||
| `Network` | 请求 fail | 自动 toast「网络错误」 |
|
||||
|
||||
静默场景(自己处理提示)传 `hideErrorToast`:
|
||||
|
||||
```ts
|
||||
await httpPost('/log/track', payload, undefined, undefined, { hideErrorToast: true })
|
||||
```
|
||||
|
||||
## 4. 401 / token(业务零处理)
|
||||
|
||||
由 `http.ts` 统一处理,受 `env/.env` 的 `VITE_AUTH_MODE` 控制:
|
||||
|
||||
- `single`:清用户态 → 跳登录页
|
||||
- `double`:用 refreshToken 无感刷新(并发请求进队列,刷新成功后自动重放;失败才登出)
|
||||
|
||||
**业务代码不要自行处理 401,也不要读 store 手动拼 Authorization。**
|
||||
|
||||
## 5. 地址与环境
|
||||
|
||||
- 基准地址 `VITE_SERVER_BASEURL`;第二后端用 `VITE_SERVER_BASEURL_SECONDARY`
|
||||
- H5 dev 开代理时(`VITE_APP_PROXY_ENABLE=true`)自动走 `/fg-api` 前缀,nginx 需同步该前缀
|
||||
- 微信三环境(开发/体验/正式)用 `VITE_SERVER_BASEURL__WEIXIN_*` 覆写,见 platforms.md 第 4 节
|
||||
- 对接多个后端:在 `interceptor.ts` 的 URL 拼接处扩展,不在业务层散落拼 URL
|
||||
@@ -0,0 +1,64 @@
|
||||
# 架构规范
|
||||
|
||||
## 1. 事实源与生成物(唯一事实源与投影)
|
||||
|
||||
配置的**事实源**是根目录的 `*.config.ts`,构建时投影为 JSON/d.ts。改投影不改源 = 改动丢失。
|
||||
|
||||
| 事实源(手改这里) | 生成物(禁止手改) | 生成者 |
|
||||
|------------------|------------------|--------|
|
||||
| `pages.config.ts` | `src/pages.json` | vite-plugin-uni-pages |
|
||||
| `manifest.config.ts` | `src/manifest.json` | vite-plugin-uni-manifest |
|
||||
| `src/tabbar/config.ts` | pages.json 的 tabBar 段 | 引入 pages.config.ts |
|
||||
| 组件目录 `src/components/**` | `src/types/components.d.ts` | vite-plugin-uni-components |
|
||||
| `src/pages/**` + `definePage` 宏 | `src/types/uni-pages.d.ts` | vite-plugin-uni-pages |
|
||||
| `src/hooks/**`、vue/uni-app API | `src/types/auto-import.d.ts` | unplugin-auto-import |
|
||||
|
||||
页面路由配置只写在页面内的 `definePage` 宏里,不写进 pages.config.ts 的页面列表。
|
||||
|
||||
## 2. 平台接缝
|
||||
|
||||
- **条件编译是唯一的平台分支手段**(编译期能确定的场景):JS 用 `// #ifdef` / `// #endif`,模板用 `<!-- #ifdef -->` / `<!-- #endif -->`
|
||||
- 运行时判断平台用 `uni.getSystemInfoSync().uniPlatform` 等 API,只用于编译期无法确定的场景
|
||||
- 仅 H5 生效的行为(如 devServer 代理 `VITE_APP_PROXY_*`、eruda 调试面板)不需要写条件编译,其他端构建时天然剔除
|
||||
- 小程序端 dev 也是 `build` command(无 devServer),不要在非 H5 端假设热更新代理可用
|
||||
|
||||
## 3. 校验只在真边界
|
||||
|
||||
以下边界的数据**不可信**,必须校验后才进业务层:
|
||||
|
||||
| 真边界 | 校验位置 |
|
||||
|--------|---------|
|
||||
| HTTP 响应 | `src/http` / alova 拦截器统一做,业务层不重复判空 |
|
||||
| `uni.getStorageSync` 读出的数据 | 读取处判类型/结构 |
|
||||
| URL 参数(onLoad options) | 页面入口处校验 |
|
||||
| postMessage / 第三方 SDK 回调 | 回调入口处校验 |
|
||||
|
||||
组件 props、store 内部传递信任 TS 类型,**不**重复运行时校验。
|
||||
|
||||
## 4. 目录分层与职责
|
||||
|
||||
```
|
||||
src/
|
||||
├── pages/ # 页面(约定式路由,文件即路径;分包页面不放这里)
|
||||
├── pages-demo/ # 分包目录(subPackages 配置,分包不能是 src/pages 的子目录)
|
||||
├── components/ # 全局组件(fg- 前缀,easycom 自动注册)
|
||||
├── layouts/ # 布局
|
||||
├── api/ # API 接口定义
|
||||
├── http/ # 请求封装(uni.request 为主;alova 为可选并行链路,拦截器中默认注释)
|
||||
├── store/ # Pinia store(持久化用 pinia-plugin-persistedstate)
|
||||
├── hooks/ # 组合式函数(auto-import,免 import)
|
||||
├── tabbar/ # 底部导航(config.ts 为唯一配置源)
|
||||
├── static/ # 静态资源(@img 别名指向 images 子目录)
|
||||
├── service/ # openapi 生成目录(`pnpm openapi`,eslint 忽略,勿手改)
|
||||
└── types/ # 类型声明(大部分为生成物,见第 1 节)
|
||||
```
|
||||
|
||||
- 别名:`@` → `src/`;`@img` → `src/static/images`(vite 与 tsconfig 已对齐)
|
||||
- 请求一律走 `src/http` 封装,业务代码不直接调 `uni.request`
|
||||
- 服务端状态以接口为事实源,store 只放需要跨页共享/持久化的状态;凡不能从 store 重建的 UI 状态都是刷新后丢失的隐患
|
||||
|
||||
## 5. 环境变量
|
||||
|
||||
- env 文件统一在 `env/` 目录(vite.config.ts 的 `envDir`),不在项目根
|
||||
- 变更部署相关变量(端口 `VITE_APP_PORT`、接口地址 `VITE_SERVER_BASEURL`、代理开关 `VITE_APP_PROXY_*` 等)改 env 文件,不在代码里硬编码
|
||||
- `VITE_DELETE_CONSOLE=true` 时构建移除 console/debugger,提交前不需要手工删
|
||||
@@ -0,0 +1,47 @@
|
||||
# 代码规范
|
||||
|
||||
## 1. Vue SFC
|
||||
|
||||
- `<script setup lang="ts">` 必须第一个,`<template>` 第二,`<style scoped>` 最后(eslint `vue/block-order` error 强制)
|
||||
- 页面配置用 `definePage` 宏,且放在最上面
|
||||
- 组件文件 PascalCase 命名;全局组件放 `src/components/`(fg- 前缀,easycom 自动注册),局部组件放页面的 `components/` 子目录
|
||||
- 列表页用 z-paging(已配置 easycom:`<z-paging>` 直接用)
|
||||
- 组合式 API + auto-import:vue/uni-app 的 API 和 `src/hooks/**` 不需要手写 import
|
||||
|
||||
## 2. TypeScript
|
||||
|
||||
- 禁止新增 `any`(团队约定;eslint 未单独强制)
|
||||
- 对象类型用 `interface`,联合类型用 `type`;导入类型用 `import type`
|
||||
- 不自动排序 import:条件编译注释可能包裹 import(eslint 已关 `perfectionist/sort-imports`,勿重新打开)
|
||||
- API 响应必须在 `src/api/` 定义接口类型,响应数据过边界校验后才使用
|
||||
|
||||
## 3. 样式(UnoCSS)
|
||||
|
||||
- 优先原子类,减少自定义 CSS;常用快捷方式:`center`(flex 居中)
|
||||
- 主题色用 `text-primary` / `bg-primary`(uno.config.ts theme 定义,含 wot-ui 联动变量)
|
||||
- 安全区用自定义规则:`p-safe` / `pt-safe` / `pb-safe`(刘海屏/底部横条)
|
||||
- 小字号:`text-2xs`(20rpx)/ `text-3xs`(18rpx)
|
||||
- **动态拼接的图标类名必须加入 uno.config.ts 的 safelist**,否则不生成样式
|
||||
- 本地 SVG 放 `src/static/my-icons/`,用 `i-my-icons-图标名` 调用
|
||||
|
||||
## 4. 状态管理
|
||||
|
||||
- store 放 `src/store/`,`defineStore` 定义
|
||||
- 需要持久化的状态配置 `pinia-plugin-persistedstate`,不手写 uni.setStorage 同步业务状态
|
||||
- uni.getStorageSync 读出的数据是真边界数据,使用前校验(见 architecture.md 第 3 节)
|
||||
|
||||
## 5. Git 提交
|
||||
|
||||
- commitlint 强制 conventional commits:`feat: / fix: / docs: / style: / refactor: / perf: / test: / chore:`
|
||||
- 版本发布走 changesets:`pnpm upload:changeset`
|
||||
- husky 钩子已启用,lint-staged 会拦截不合规提交
|
||||
|
||||
## 6. 合入前验证(三条命令)
|
||||
|
||||
```bash
|
||||
pnpm type-check # vue-tsc --noEmit,类型零错误
|
||||
pnpm lint # eslint 零 error
|
||||
pnpm test:run # vitest 全绿
|
||||
```
|
||||
|
||||
微信小程序上传:`pnpm upload:mp`(需 miniprogram-ci 配置)。
|
||||
@@ -0,0 +1,34 @@
|
||||
# 性能与分包规范
|
||||
|
||||
## 1. 分包(微信主包 2M 硬限制)
|
||||
|
||||
- 分包目录放 `src/pages/` 之外,注册到 `vite.config.ts` 的 `UniPages({ subPackages })`
|
||||
- 低频/独立业务(如 demo、设置二级页)优先进分包
|
||||
- bundle-optimizer 已启用(仅微信端):支持模块异步跨包调用、组件异步跨包引用,分包间复用代码不需要复制
|
||||
- 判断该不该分包:页面是否首屏必需?不是 → 分包
|
||||
|
||||
## 2. 构建内置优化(不要重复做)
|
||||
|
||||
| 优化 | 状态 | 说明 |
|
||||
|------|------|------|
|
||||
| console/debugger 移除 | `VITE_DELETE_CONSOLE=true` | 提交前不用手工删 console |
|
||||
| sourcemap | 关闭 | 需要时改 vite.config.ts,勿长期开 |
|
||||
| minify | esbuild | dev 不压缩、prod 压缩 |
|
||||
| build target | es6 | 兼容低版本 WebView |
|
||||
|
||||
## 3. 包体积日常检查
|
||||
|
||||
```bash
|
||||
pnpm build:h5 # H5 生产构建自动打开 visualizer 分析
|
||||
# 产物:node_modules/.cache/visualizer/stats.html
|
||||
```
|
||||
|
||||
小程序端看微信开发者工具的「代码依赖分析」。
|
||||
|
||||
## 4. 编码侧规则
|
||||
|
||||
- 静态图片:大图优先网络地址或压缩后放 `src/static`;SVG 图标走 `src/static/my-icons/`(i-my-icons-*)
|
||||
- UnoCSS `safelist` 只加**动态拼接类名**,每加一项全量注入,能不用则不用
|
||||
- 列表页一律 z-paging(虚拟分页),不手写 onReachBottom 加载
|
||||
- auto-import(`src/hooks`)按名导入即用;注意 eslint 已关闭 no-unused-vars,未使用导入无守卫,删改代码时自查
|
||||
- 新增第三方依赖前看体积:小程序端无 tree-shake 保障的库(如全量 UI 库)优先按需引入
|
||||
@@ -0,0 +1,67 @@
|
||||
# 平台适配手册
|
||||
|
||||
## 1. 差异处理决策树
|
||||
|
||||
```
|
||||
这个差异编译期就能确定吗?
|
||||
├── 能 → 条件编译(#ifdef / #ifndef)
|
||||
└── 不能 → 运行时 API 判断(uni.getSystemInfoSync().uniPlatform)
|
||||
```
|
||||
|
||||
- 构建脚本/插件层面:`process.env.UNI_PLATFORM`(仅 vite.config.ts、构建脚本内可用)
|
||||
- 禁止:用 UA 嗅探替代条件编译;在能编译期剔除的代码里留运行时 if
|
||||
|
||||
## 2. 条件编译速查
|
||||
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
// #ifdef H5
|
||||
import { h5Api } from '@/utils/h5'
|
||||
// #endif
|
||||
// #ifndef MP-WEIXIN
|
||||
// 所有平台生效,除微信小程序
|
||||
// #endif
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- #ifdef APP-PLUS -->
|
||||
<view>仅 APP</view>
|
||||
<!-- #endif -->
|
||||
</template>
|
||||
```
|
||||
|
||||
常用平台标识:`H5`、`MP-WEIXIN`、`MP-ALIPAY`、`MP-BAIDU`、`MP-TOUTIAO`、`MP-LARK`、`MP-QQ`、`MP-KUAISHOU`、`MP-JD`、`MP-XHS`、`APP-PLUS`(app-android / app-ios 可再细分)、`MP`(`%MP%` 或 `MP` 泛小程序)。
|
||||
|
||||
## 3. 本项目已存在的平台差异(改动时别破坏)
|
||||
|
||||
| 差异点 | 位置 | 规则 |
|
||||
|--------|------|------|
|
||||
| devServer 代理(`VITE_APP_PROXY_*`) | src/http/interceptor.ts | 仅 H5 dev 生效;非 H5 端 dev 也是 build command,无代理 |
|
||||
| `responseType: 'json'` | src/http/http.ts | 用 `#ifndef MP-WEIXIN` 包裹,微信小程序不支持 |
|
||||
| eruda 调试面板 | vite.config.ts | 仅 H5 development |
|
||||
| 打包分析 visualizer | vite.config.ts | 仅 H5 production,产物在 `node_modules/.cache/visualizer/stats.html` |
|
||||
| 自动打开开发者工具 | scripts/open-dev-tools.js | mp-weixin / mp-alipay / mp-lark 构建后自动打开对应工具;上传脚本用 `SKIP_OPEN_DEVTOOLS=true` 跳过 |
|
||||
| bundle-optimizer 分包优化 | vite.config.ts | `enable: isMpWeixin`,仅微信小程序端 |
|
||||
| 原生插件资源复制 | vite.config.ts | 仅 app 平台且 `VITE_COPY_NATIVE_RES_ENABLE=true` |
|
||||
|
||||
## 4. 多端请求地址
|
||||
|
||||
`env/.env` 支持按微信开发者工具 envVersion 覆写(不配则回退 `VITE_SERVER_BASEURL`):
|
||||
|
||||
```ini
|
||||
VITE_SERVER_BASEURL = 'https://api.example.com'
|
||||
VITE_SERVER_BASEURL__WEIXIN_DEVELOP = 'https://dev.xxx.com' # 开发版
|
||||
VITE_SERVER_BASEURL__WEIXIN_TRIAL = 'https://trial.xxx.com' # 体验版
|
||||
VITE_SERVER_BASEURL__WEIXIN_RELEASE = 'https://prod.xxx.com' # 正式版
|
||||
```
|
||||
|
||||
## 5. 平台命令
|
||||
|
||||
```bash
|
||||
pnpm dev # H5
|
||||
pnpm dev:mp # 微信小程序(其余 dev:mp-alipay / mp-baidu / mp-jd / mp-kuaishou / mp-lark / mp-qq / mp-toutiao / mp-xhs 同理)
|
||||
pnpm dev:app # APP(app-android / app-ios 可细分)
|
||||
pnpm build:mp # 微信小程序生产构建
|
||||
```
|
||||
|
||||
新增平台特定行为时,同步更新本文第 3 节的差异点表。
|
||||
@@ -0,0 +1,49 @@
|
||||
# 发布流程
|
||||
|
||||
## 1. 微信小程序上传(`pnpm upload:mp`)
|
||||
|
||||
脚本 `scripts/upload-weixin.js` 全自动:构建(`build:mp:prod`,跳过打开开发者工具)→ miniprogram-ci 上传。
|
||||
|
||||
```bash
|
||||
pnpm upload:mp # 版本取 package.json,描述取最新 Git commit
|
||||
pnpm upload:mp --version=1.0.1 # 指定版本号
|
||||
pnpm upload:mp --desc="修复登录bug" # 指定描述
|
||||
pnpm upload:mp --robot=2 # 指定机器人(1-30,多人协作避免互相覆盖)
|
||||
```
|
||||
|
||||
版本号优先级:命令行 > package.json;描述优先级:命令行 > Git commit > 时间戳。
|
||||
|
||||
**前置条件(缺一上传失败)**:
|
||||
1. 公众平台已开通「小程序代码上传」权限并配置 IP 白名单
|
||||
2. 根目录有私钥文件 `private.<appid>.key`(appid 与 `env/.env` 的 `VITE_WX_APPID` 一致)
|
||||
3. 上传后到公众平台「版本管理 → 开发版本」设为体验版
|
||||
|
||||
## 2. 版本管理(changesets)
|
||||
|
||||
```bash
|
||||
pnpm upload:changeset # 生成变更记录 + 消费变更(升版本)
|
||||
```
|
||||
|
||||
- 对外可见的变更(新页面、接口变动、依赖升级)提交 changeset
|
||||
- `pnpm bump-version` 单独升 package.json 版本(上传脚本读它)
|
||||
|
||||
## 3. uni-app 依赖升级
|
||||
|
||||
```bash
|
||||
pnpm uvm # 交互式升级 @dcloudio/* 全家桶
|
||||
pnpm uvm-rm # 清理升级残留
|
||||
```
|
||||
|
||||
升级后必跑:`pnpm type-check && pnpm test:run`,并三端冒烟(`dev` / `dev:mp` / `dev:app`)。
|
||||
|
||||
## 4. 环境切换
|
||||
|
||||
env 文件在 `env/` 目录,按 mode 叠加:`.env`(公共)→ `.env.development` / `.env.test` / `.env.production`。发布前核对生产 env:接口地址、微信三环境地址(`VITE_SERVER_BASEURL__WEIXIN_*`)、`VITE_DELETE_CONSOLE=true`。
|
||||
|
||||
## 5. 合入前门禁
|
||||
|
||||
```bash
|
||||
pnpm type-check && pnpm lint && pnpm test:run
|
||||
```
|
||||
|
||||
提交信息 conventional commits(commitlint 强制):`feat: / fix: / docs: / style: / refactor: / perf: / test: / chore:`。
|
||||
@@ -0,0 +1,48 @@
|
||||
# 新页面 / 新组件 SOP
|
||||
|
||||
## 1. 新建页面(3 步)
|
||||
|
||||
1. **建文件**:`src/pages/模块名/页面名.vue`(约定式路由,文件路径即路由,**无需注册**)
|
||||
2. **写 `definePage` 宏,放在 script 最上面**:
|
||||
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
definePage({
|
||||
style: { navigationBarTitleText: '页面标题' },
|
||||
})
|
||||
</script>
|
||||
```
|
||||
|
||||
3. **跑 `pnpm type-check`**:重新生成 `src/types/uni-pages.d.ts`,路由类型才可用
|
||||
|
||||
注意:
|
||||
- 页面私有组件放同目录 `components/` 子目录(构建时已排除,**不会被识别成页面**)
|
||||
- 需要登录态的页面按项目现有登录拦截方式处理,不自行在页面内写 token 判断
|
||||
|
||||
## 2. 新建全局组件(1 步)
|
||||
|
||||
放 `src/components/fg-组件名/fg-组件名.vue`,easycom 规则 `^fg-(.*)` 自动注册,任何页面直接 `<fg-组件名 />`,**无需 import**。
|
||||
|
||||
- z-paging 同理:`<z-paging>` 直接用
|
||||
- 其他第三方库组件按各自 easycom 规则
|
||||
|
||||
## 3. 新建分包页面(2 步)
|
||||
|
||||
1. 分包目录放 `src/pages/` **之外**(如 `src/pages-sub/xxx`),内建页面文件
|
||||
2. 在 `vite.config.ts` 的 `UniPages({ subPackages: [...] })` 数组加目录路径
|
||||
|
||||
## 4. 新增 tabbar 项(1 步)
|
||||
|
||||
只改 `src/tabbar/config.ts`(唯一配置源),pages.json 的 tabBar 段自动生成。图标等资源同步放约定目录。
|
||||
|
||||
## 5. 新增组合式函数(1 步)
|
||||
|
||||
放 `src/hooks/`,auto-import 已配置 `dirs: ['src/hooks']`,页面内**直接调用,无需 import**。
|
||||
|
||||
## 6. 验证清单(新建任何东西后)
|
||||
|
||||
```bash
|
||||
pnpm type-check # 路由/组件类型生成且零错误
|
||||
pnpm lint # 格式合规
|
||||
pnpm dev:mp # 目标平台真机/模拟器跑一遍
|
||||
```
|
||||
Reference in New Issue
Block a user