|
|
@@ -1,196 +1,202 @@
|
|
|
-# zxyj-frontend
|
|
|
-
|
|
|
-uni-app 微信小程序前端,Vue 2 语法,家庭教育任务管理。
|
|
|
-
|
|
|
-## WHERE TO LOOK
|
|
|
-
|
|
|
-| Task | Location | Notes |
|
|
|
-|------|----------|-------|
|
|
|
-| 页面组件 | `pages/*/` | login, index, tasks, rewards, profile, guide, games等 |
|
|
|
-| 页面注册 | `pages.json` | TabBar配置和页面路径 |
|
|
|
-| 应用配置 | `manifest.json` | AppID: `wx5ba8038ef16fb245` |
|
|
|
-| 全局样式 | `uni.scss` | SCSS变量和全局样式 |
|
|
|
-| 应用入口 | `App.vue` | 全局生命周期和配置 |
|
|
|
-| 组件库 | `components/` | 地址选择器、任务卡片等可复用组件 |
|
|
|
-| API配置 | `config/` | baseUrl和请求封装 |
|
|
|
-
|
|
|
-## STRUCTURE
|
|
|
-
|
|
|
-### 主包(主包 = `pages.json` 的 `pages` 数组)
|
|
|
-
|
|
|
-仅含 5 个 TabBar 页面,主包大小已压缩至 ~1MB 以下:
|
|
|
-
|
|
|
-| 路径 | 说明 |
|
|
|
-|------|------|
|
|
|
-| `pages/index/index` | 首页(未登录态引流页 + 角色路由跳转) |
|
|
|
-| `pages/mind/index` | 心维度首页 |
|
|
|
-| `pages/body/index` | 身维度首页 |
|
|
|
-| `pages/wisdom/index` | 智维度首页 |
|
|
|
-| `pages/wealth/index` | 富维度首页 |
|
|
|
-
|
|
|
-> **登录用户路由**:`pages/index/index` 中 `parent-index` 和 `child-index` 已从静态组件改为 `redirectTo` 跳转到分包页面,不再计入主包体积。
|
|
|
-
|
|
|
-### 分包(`pages.json` 的 `subPackages` 数组,共 45 个)
|
|
|
-
|
|
|
-主要分包(按 `root`):
|
|
|
-
|
|
|
-| Root | 内容 |
|
|
|
-|------|------|
|
|
|
-| `pages/teacher` | 成长规划师中心(7 页) |
|
|
|
-| `pages/guide` | 任务模板、邀请、绑定等(11 页) |
|
|
|
-| `pages/parent` | 家长端市场、孩子详情(3 页) |
|
|
|
-| `pages/child` | 孩子端任务、心愿(2 页) |
|
|
|
-| `pages/tasks` | 任务列表/创建/审核(4 页) |
|
|
|
-| `pages/wishes` | 心愿管理(3 页) |
|
|
|
-| `pages/rewards` | 心愿单/勋章墙(2 页) |
|
|
|
-| `pages/games` | 小游戏(5 页) |
|
|
|
-| `pages/assessment` | 测评申请/报告(5 页) |
|
|
|
-| `pages/dan-assessment` | DAN 测评上传(1 页) |
|
|
|
-| `pages/growth` | 成长记录(6 页) |
|
|
|
-| `pages/shop` | 商城(15 页) |
|
|
|
-| `pages/vendor` | 服务商入驻/管理(5 页) |
|
|
|
-| `pages/health` | 健康功能(18 页) |
|
|
|
-| `pages/mind-detail` | 心智详情(11 页) |
|
|
|
-| `pages/body-detail` | 身体详情(6 页) |
|
|
|
-| `pages/wisdom-detail` | 智慧详情(4 页) |
|
|
|
-| `pages/action-detail` | 行动详情(4 页) |
|
|
|
-| `pages/tianpan` | 家庭天盘(6 页) |
|
|
|
-| `pages/article-center` | 文章中心(4 页) |
|
|
|
-| `pages/activity` | 活动(3 页) |
|
|
|
-| `pages/promotion` | 财富中心/推广(6 页) |
|
|
|
-| `pages/membership` | 会员(3 页) |
|
|
|
-| `pages/index` | 原主包页面(parent-index, child-index, member-home-detail) |
|
|
|
-| `pages/login` | 登录页 |
|
|
|
-| `pages/share` | 健康足迹 |
|
|
|
-| `pages/profile` | 个人中心(profile + index) |
|
|
|
-| `pages/profile-extra` | 孩子管理/优惠券(6 页) |
|
|
|
-| ... 共 45 个分包 | 详见 `pages.json` |
|
|
|
-
|
|
|
-> **注意**:分包页面在首次访问时异步下载,主包只加载必要的 TabBar 页面,确保主包 < 1.5MB。
|
|
|
-
|
|
|
-## TabBar 配置
|
|
|
-
|
|
|
-pages.json 中定义 5 个 TabBar 页面(TabBar 文案,非五维维度名):
|
|
|
-- 首页: `pages/index/index` - 角色分流入口
|
|
|
-- 身: `pages/body/index` - 身体健康维度
|
|
|
-- 智: `pages/wisdom/index` - 智慧维度(心智测评)
|
|
|
-- 心: `pages/mind/index` - 心理/情感维度
|
|
|
-- 我的: `pages/profile/profile` - 个人设置和积分
|
|
|
-
|
|
|
-## CONVENTIONS
|
|
|
-
|
|
|
-- **Vue 2:** 使用 Options API,生命周期 `onLoad`、`onShow`
|
|
|
-- **页面注册:** 新页面必须在 `pages.json` 中注册
|
|
|
-- **导航:** 使用 `uni.navigateTo`、`uni.redirectTo`
|
|
|
-- **API 调用:** 使用 `uni.request`,统一在 `config.baseUrl`
|
|
|
-- **地址选择:** 使用 `components/address-picker.vue` 四级联动组件
|
|
|
-- **角色切换:** 页面根据用户角色显示不同内容
|
|
|
-
|
|
|
-## 时间显示规范
|
|
|
-
|
|
|
-页面时间展示必须统一以下两种格式:
|
|
|
-
|
|
|
-| 使用场景 | 格式 | 示例 |
|
|
|
-|------|------|------|
|
|
|
-| **时间(年月日+时分秒)** | `yyyy-MM-dd HH:mm:ss` | `2026-08-15 14:30:00` |
|
|
|
-| **仅日期(不带时间)** | `yyyy-MM-dd` | `2026-08-15` |
|
|
|
-
|
|
|
-后端返回 ISO 8601 格式(`2026-08-15T14:30:00`),前端格式化:
|
|
|
-
|
|
|
-- **需展示时间**:字符串先经 `parseDate()` 解析(iOS 安全),再用 `getFullYear()`/`getMonth()`/`getDate()`/`getHours()`/`getMinutes()`/`getSeconds()` 拼出 `yyyy-MM-dd HH:mm:ss`
|
|
|
-- **仅需日期**:直接截取字符串前 10 位 → `yyyy-MM-dd`
|
|
|
-
|
|
|
-禁止 `new Date(str).toLocaleString()`(iOS 输出格式与渲染结果因人而异)。
|
|
|
-
|
|
|
-## ANTI-PATTERNS
|
|
|
-
|
|
|
-- **DO NOT** 创建页面后忘记在 `pages.json` 注册
|
|
|
-- **DO NOT** 硬编码 API 地址,使用 `config.baseUrl`
|
|
|
-- **DO NOT** 在前端存储敏感信息 (密码、密钥)
|
|
|
-- **NEVER** 跳过 JWT 认证直接调用需登录接口
|
|
|
-- **NEVER** 在本地存储中保存敏感用户信息
|
|
|
-- **NEVER** 在 WXML/Vue 模板中使用可选链 `?.`,微信小程序不支持 → 使用 `&&` 代替(如 `currentWish?.title` 改为 `currentWish && currentWish.title`)
|
|
|
-- **NEVER** 在 `:class` 绑定中调用方法(如 `:class="getStatusClass(item)"`),微信小程序模板编译器不支持带参数的方法调用 → 改用内联表达式(如 `:class="'status-' + item._cssClass"`)或计算属性
|
|
|
-- **NEVER** 在 CSS 类名、选择器中使用中文(如 `.val-偏高`、`.badge-低风险`),微信小程序 wxss 编译器不支持中文类名 → 使用英文(如 `.val-high`、`.badge-low`),数据中的中文状态通过 `_cssClass` 字段映射
|
|
|
-- **NEVER** 在 `:key` 中使用表达式(如 `:key="item.id || item.circleId"`),微信小程序模板编译器不支持带运算符的 `:key` 绑定 → 改用方法调用(如 `:key="getItemKey(item)"`,在 methods 中定义 `getItemKey(item) { return item.id || item.circleId }`)
|
|
|
-- **NEVER** 直接用 `new Date(string)` 解析日期字符串。部分 iOS(JavaScriptCore)的 `new Date()` 只支持 `yyyy/MM/dd`、`yyyy/MM/dd HH:mm:ss`、`yyyy-MM-dd`、`yyyy-MM-ddTHH:mm:ss`、`yyyy-MM-ddTHH:mm:ss+HH:mm` 格式,后端常见的 `"2026-08-22 14:00"`(空格分隔的 MySQL DATETIME 风格)和 Java 的 `"Sat Aug 22 14:00:00 CST 2026"` 会解析失败返回 Invalid Date → 一律使用 `utils/format.js` 的 `parseDate()`,它会自动归一化上述两种格式并返回 `Date|null`(如 `var d = parseDate(item.startTime); if (!d) return`)
|
|
|
-- **NEVER** 新增 `uni.getSystemInfoSync()` 调用。该 API 已在微信基础库 2.20.1+ 弃用,开发者工具会持续告警(`getSystemInfoSync is deprecated`)→ 改用 `uni.getWindowInfo()`(取 `windowWidth`/`pixelRatio`/`safeArea` 等窗口信息)或 `uni.getDeviceInfo()`(取 `system`/`brand`/`model` 等设备信息)。已有兼容代码(`components/mp-html/` 内的 `uni.canIUse('getWindowInfo')` 兜底)保持不变。参考替换:`uni.getSystemInfoSync().pixelRatio` → `uni.getWindowInfo().pixelRatio`
|
|
|
-- **NEVER** 给 `props` 传可能为非数组的值而不做兜底。组件接收 `Array` 类型 prop 时,父组件传值必须保证是数组(`|| []` 兜底 + `Array.isArray` 校验),否则触发 `Invalid prop: type check failed for prop "xxx". Expected Array, got Object` 告警。典型场景:接口返回结构不确定(`res.data.list` 可能为 `Object`)时,用 `var arr = (res.data && res.data.list) || (res.data instanceof Array ? res.data : [])` 三态兼容
|
|
|
-
|
|
|
-## UNIQUE FEATURES
|
|
|
-
|
|
|
-- 地址匹配页面: `pages/match/street-match.vue` - 街道地址匹配功能
|
|
|
-- 地址编辑页面: `pages/family/address-edit.vue` - 家庭地址管理
|
|
|
-- 四级地址选择: `components/address-picker.vue` - 省市区街道联动
|
|
|
-- 双角色界面: 根据用户角色(parent/child)显示不同UI
|
|
|
-
|
|
|
-## BUILD SYSTEM
|
|
|
-
|
|
|
-### 打包方式(强制规范)
|
|
|
-
|
|
|
-**小程序打包必须用 HBuilderX 完成,Agent 禁止自行执行 `npm run build:mp-weixin` 等打包命令。**
|
|
|
-
|
|
|
-- 打包工具:HBuilderX(导入 `cfc-frontend/` 目录 → 运行 → 运行到小程序模拟器 → 微信开发者工具)
|
|
|
-- 打包产物:**`cfc-frontend/unpackage/`** 目录(HBuilderX 输出位置,dev 产物在 `unpackage/dist/dev/mp-weixin/`)
|
|
|
-- 微信开发者工具导入的目录是 `unpackage/dist/dev/mp-weixin/`(或 HBuilderX 自动打开),**不是** `dist/`
|
|
|
-- `dist/` 目录是 npm CLI 打包的残留产物,**不可用**——`app.js` 仅有 89 字节(require 三行),非完整产物
|
|
|
-- Agent 修改代码后:只做**语法/结构校验**(如 `node --check` 提取的 script 块),**不打包、不运行 build 命令**
|
|
|
-- 页面白板排查第一步:确认用户是否在 HBuilderX 中**重新打包**过(改代码后未重新打包 → 产物过期 → 白板)
|
|
|
-
|
|
|
-### 依赖约束(2026-07-23 修复后锁定)
|
|
|
-
|
|
|
-| 包 | 版本 | 原因 |
|
|
|
-|----|------|------|
|
|
|
-| `@vue/cli-service` | `~4.5.0` | v5 使用 webpack 5,`@dcloudio/uni-mp-weixin` 依赖 `webpack/lib/GraphHelpers`(webpack 4 特有)|
|
|
|
-| `@vue/cli-plugin-babel` | `~4.5.0` | 与 cli-service v4 匹配 |
|
|
|
-| `postcss` (override + dependency) | `7.0.39` | `remove-scoped.js` 在 PostCSS 8 下会走 v8 插件路径,但 `spaces` 属性访问有兼容问题 |
|
|
|
-| `node-sass` | (devDependency) | `@dcloudio/vue-cli-plugin-uni` 内置的 sass-loader 需要 |
|
|
|
-| `copy-webpack-plugin` | `^5.1.2` | 与 cli-service v4 的 webpack 4 兼容 |
|
|
|
-
|
|
|
-### postinstall 自动补丁
|
|
|
-
|
|
|
-`npm install` 后会自动运行 `postinstall-fix.js`,修补 `remove-scoped.js` 中的 `spaces` 崩溃:
|
|
|
-
|
|
|
-```js
|
|
|
-// 问题: selector.first 可能为 undefined
|
|
|
-// 修改前: selector.first.spaces.before = '';
|
|
|
-// 修改后: if (selector.first) { selector.first.spaces.before = ''; }
|
|
|
-```
|
|
|
-
|
|
|
-### 已知编译错误处理
|
|
|
-
|
|
|
-| 错误 | 原因 | 处理 |
|
|
|
-|------|------|------|
|
|
|
-| `Cannot read properties of undefined (reading 'spaces')` in `remove-scoped.js` | PostCSS 节点没有 `spaces` 属性 | postinstall-fix.js 自动补丁 |
|
|
|
-| `Cannot find module 'webpack/lib/GraphHelpers'` | `@vue/cli-service v5` 的 webpack 5 不支持 | 保持 `@vue/cli-service ~4.5.0` |
|
|
|
-| `Cannot find module 'node-sass'` | uni-app sass-loader 需要 | `npm install node-sass --save-dev` |
|
|
|
-| `getPreCompileOptions` DevTools 内部错误 | `dist/dev/mp-weixin/` 缺少 `project.config.json` | 先 `npm run build:mp-weixin` 生成 dist |
|
|
|
-| `Unexpected token` in `.vue` | JS 语法错误,常见于方法被截断/拼接错误 | 检查 v-on:click/方法调用是否正确闭合 |
|
|
|
-
|
|
|
-### 修改 `remove-scoped.js` 的风险
|
|
|
-
|
|
|
-该文件在 `node_modules/@dcloudio/vue-cli-plugin-uni/` 内,每次 `npm install` 会通过 `postinstall-fix.js` 自动恢复补丁。如需手动执行:
|
|
|
-
|
|
|
-```bash
|
|
|
-node postinstall-fix.js
|
|
|
-```
|
|
|
-
|
|
|
-**不要**将 `@vue/cli-service` 升级到 v5,除非:
|
|
|
-- `@dcloudio/uni-mp-weixin` 确认移除了 `webpack/lib/GraphHelpers` 依赖
|
|
|
-- 或者找到替代方法处理独立分包插件
|
|
|
-
|
|
|
-## COMMANDS
|
|
|
-
|
|
|
-```bash
|
|
|
-npm install # 安装依赖(自动运行 postinstall-fix.js)
|
|
|
-# 注意:打包一律用 HBuilderX(产物在 unpackage/),Agent 不要执行 npm run build:mp-weixin
|
|
|
-```
|
|
|
-
|
|
|
-## NOTES
|
|
|
-
|
|
|
-- 小程序AppID: `wx5ba8038ef16fb245`
|
|
|
-- 后端API地址: 配置在 `config/index.js` 的 `baseUrl`
|
|
|
-- 地址数据: 使用后端街道API获取四级地址数据
|
|
|
-- 调试工具: 微信开发者工具需配置合法域名
|
|
|
-- **打包流程(HBuilderX)**:HBuilderX 打开 `cfc-frontend/` → 运行到微信开发者工具 → 产物输出至 `unpackage/dist/dev/mp-weixin/`。改代码后必须在 HBuilderX 中重新运行打包,否则小程序显示旧产物(甚至白板)
|
|
|
-- **禁止**在终端执行 `npm run build:mp-weixin` 或 `npm run dev:mp-weixin` 自行打包(产物进 `dist/` 而非 `unpackage/`,与 HBuilderX 工作流冲突)
|
|
|
+# zxyj-frontend
|
|
|
+
|
|
|
+uni-app 微信小程序前端,Vue 2 语法,家庭教育任务管理。
|
|
|
+
|
|
|
+## WHERE TO LOOK
|
|
|
+
|
|
|
+| Task | Location | Notes |
|
|
|
+|------|----------|-------|
|
|
|
+| 页面组件 | `pages/*/` | login, index, tasks, rewards, profile, guide, games等 |
|
|
|
+| 页面注册 | `pages.json` | TabBar配置和页面路径 |
|
|
|
+| 应用配置 | `manifest.json` | AppID: `wx5ba8038ef16fb245` |
|
|
|
+| 全局样式 | `uni.scss` | SCSS变量和全局样式 |
|
|
|
+| 应用入口 | `App.vue` | 全局生命周期和配置 |
|
|
|
+| 组件库 | `components/` | 地址选择器、任务卡片等可复用组件 |
|
|
|
+| API配置 | `config/` | baseUrl和请求封装 |
|
|
|
+
|
|
|
+## STRUCTURE
|
|
|
+
|
|
|
+### 主包(主包 = `pages.json` 的 `pages` 数组)
|
|
|
+
|
|
|
+仅含 5 个 TabBar 页面,主包大小已压缩至 ~1MB 以下:
|
|
|
+
|
|
|
+| 路径 | 说明 |
|
|
|
+|------|------|
|
|
|
+| `pages/index/index` | 首页(未登录态引流页 + 角色路由跳转) |
|
|
|
+| `pages/mind/index` | 心维度首页 |
|
|
|
+| `pages/body/index` | 身维度首页 |
|
|
|
+| `pages/wisdom/index` | 智维度首页 |
|
|
|
+| `pages/wealth/index` | 富维度首页 |
|
|
|
+
|
|
|
+> **登录用户路由**:`pages/index/index` 中 `parent-index` 和 `child-index` 已从静态组件改为 `redirectTo` 跳转到分包页面,不再计入主包体积。
|
|
|
+
|
|
|
+### 分包(`pages.json` 的 `subPackages` 数组,共 45 个)
|
|
|
+
|
|
|
+主要分包(按 `root`):
|
|
|
+
|
|
|
+| Root | 内容 |
|
|
|
+|------|------|
|
|
|
+| `pages/teacher` | 成长规划师中心(7 页) |
|
|
|
+| `pages/guide` | 任务模板、邀请、绑定等(11 页) |
|
|
|
+| `pages/parent` | 家长端市场、孩子详情(3 页) |
|
|
|
+| `pages/child` | 孩子端任务、心愿(2 页) |
|
|
|
+| `pages/tasks` | 任务列表/创建/审核(4 页) |
|
|
|
+| `pages/wishes` | 心愿管理(3 页) |
|
|
|
+| `pages/rewards` | 心愿单/勋章墙(2 页) |
|
|
|
+| `pages/games` | 小游戏(5 页) |
|
|
|
+| `pages/assessment` | 测评申请/报告(5 页) |
|
|
|
+| `pages/dan-assessment` | DAN 测评上传(1 页) |
|
|
|
+| `pages/growth` | 成长记录(6 页) |
|
|
|
+| `pages/shop` | 商城(15 页) |
|
|
|
+| `pages/vendor` | 服务商入驻/管理(5 页) |
|
|
|
+| `pages/health` | 健康功能(18 页) |
|
|
|
+| `pages/mind-detail` | 心智详情(11 页) |
|
|
|
+| `pages/body-detail` | 身体详情(6 页) |
|
|
|
+| `pages/wisdom-detail` | 智慧详情(4 页) |
|
|
|
+| `pages/action-detail` | 行动详情(4 页) |
|
|
|
+| `pages/tianpan` | 家庭天盘(6 页) |
|
|
|
+| `pages/article-center` | 文章中心(4 页) |
|
|
|
+| `pages/activity` | 活动(3 页) |
|
|
|
+| `pages/promotion` | 财富中心/推广(6 页) |
|
|
|
+| `pages/membership` | 会员(3 页) |
|
|
|
+| `pages/index` | 原主包页面(parent-index, child-index, member-home-detail) |
|
|
|
+| `pages/login` | 登录页 |
|
|
|
+| `pages/share` | 健康足迹 |
|
|
|
+| `pages/profile` | 个人中心(profile + index) |
|
|
|
+| `pages/profile-extra` | 孩子管理/优惠券(6 页) |
|
|
|
+| ... 共 45 个分包 | 详见 `pages.json` |
|
|
|
+
|
|
|
+> **注意**:分包页面在首次访问时异步下载,主包只加载必要的 TabBar 页面,确保主包 < 1.5MB。
|
|
|
+
|
|
|
+## TabBar 配置
|
|
|
+
|
|
|
+pages.json 中定义 5 个 TabBar 页面(TabBar 文案,非五维维度名):
|
|
|
+- 首页: `pages/index/index` - 角色分流入口
|
|
|
+- 身: `pages/body/index` - 身体健康维度
|
|
|
+- 智: `pages/wisdom/index` - 智慧维度(心智测评)
|
|
|
+- 心: `pages/mind/index` - 心理/情感维度
|
|
|
+- 我的: `pages/profile/profile` - 个人设置和积分
|
|
|
+
|
|
|
+## CONVENTIONS
|
|
|
+
|
|
|
+- **Vue 2:** 使用 Options API,生命周期 `onLoad`、`onShow`
|
|
|
+- **页面注册:** 新页面必须在 `pages.json` 中注册
|
|
|
+- **导航:** 使用 `uni.navigateTo`、`uni.redirectTo`
|
|
|
+- **API 调用:** 使用 `uni.request`,统一在 `config.baseUrl`
|
|
|
+- **地址选择:** 使用 `components/address-picker.vue` 四级联动组件
|
|
|
+- **角色切换:** 页面根据用户角色显示不同内容
|
|
|
+- **页面标题:** 所有页面的标题必须在 `pages.json` 的 `navigationBarTitleText` 中配置,禁止在 Vue 模板中手动写 `<text class="nav-title">`。仅动态标题页面(根据数据实时变化)可保留自定义 nav-bar
|
|
|
+- **API 调用去重:** 同一个接口在同一个页面生命周期内只调用一次。禁止在 onLoad/onShow/mounted 中多次调用同一 URL。如需依赖数据,在首次请求的 then 回调中处理后续逻辑
|
|
|
+
|
|
|
+## 时间显示规范
|
|
|
+
|
|
|
+页面时间展示必须统一以下两种格式:
|
|
|
+
|
|
|
+| 使用场景 | 格式 | 示例 |
|
|
|
+|------|------|------|
|
|
|
+| **时间(年月日+时分秒)** | `yyyy-MM-dd HH:mm:ss` | `2026-08-15 14:30:00` |
|
|
|
+| **仅日期(不带时间)** | `yyyy-MM-dd` | `2026-08-15` |
|
|
|
+
|
|
|
+后端返回 ISO 8601 格式(`2026-08-15T14:30:00`),前端格式化:
|
|
|
+
|
|
|
+- **需展示时间**:字符串先经 `parseDate()` 解析(iOS 安全),再用 `getFullYear()`/`getMonth()`/`getDate()`/`getHours()`/`getMinutes()`/`getSeconds()` 拼出 `yyyy-MM-dd HH:mm:ss`
|
|
|
+- **仅需日期**:直接截取字符串前 10 位 → `yyyy-MM-dd`
|
|
|
+
|
|
|
+禁止 `new Date(str).toLocaleString()`(iOS 输出格式与渲染结果因人而异)。
|
|
|
+
|
|
|
+## ANTI-PATTERNS
|
|
|
+
|
|
|
+- **DO NOT** 创建页面后忘记在 `pages.json` 注册
|
|
|
+- **DO NOT** 硬编码 API 地址,使用 `config.baseUrl`
|
|
|
+- **DO NOT** 在前端存储敏感信息 (密码、密钥)
|
|
|
+- **NEVER** 跳过 JWT 认证直接调用需登录接口
|
|
|
+- **NEVER** 在本地存储中保存敏感用户信息
|
|
|
+- **NEVER** 在 WXML/Vue 模板中使用可选链 `?.`,微信小程序不支持 → 使用 `&&` 代替(如 `currentWish?.title` 改为 `currentWish && currentWish.title`)
|
|
|
+- **NEVER** 在 `:class` 绑定中调用方法(如 `:class="getStatusClass(item)"`),微信小程序模板编译器不支持带参数的方法调用 → 改用内联表达式(如 `:class="'status-' + item._cssClass"`)或计算属性
|
|
|
+- **NEVER** 在 CSS 类名、选择器中使用中文(如 `.val-偏高`、`.badge-低风险`),微信小程序 wxss 编译器不支持中文类名 → 使用英文(如 `.val-high`、`.badge-low`),数据中的中文状态通过 `_cssClass` 字段映射
|
|
|
+- **NEVER** 在 `:key` 中使用表达式(如 `:key="item.id || item.circleId"`),微信小程序模板编译器不支持带运算符的 `:key` 绑定 → 改用方法调用(如 `:key="getItemKey(item)"`,在 methods 中定义 `getItemKey(item) { return item.id || item.circleId }`)
|
|
|
+- **NEVER** 直接用 `new Date(string)` 解析日期字符串。部分 iOS(JavaScriptCore)的 `new Date()` 只支持 `yyyy/MM/dd`、`yyyy/MM/dd HH:mm:ss`、`yyyy-MM-dd`、`yyyy-MM-ddTHH:mm:ss`、`yyyy-MM-ddTHH:mm:ss+HH:mm` 格式,后端常见的 `"2026-08-22 14:00"`(空格分隔的 MySQL DATETIME 风格)和 Java 的 `"Sat Aug 22 14:00:00 CST 2026"` 会解析失败返回 Invalid Date → 一律使用 `utils/format.js` 的 `parseDate()`,它会自动归一化上述两种格式并返回 `Date|null`(如 `var d = parseDate(item.startTime); if (!d) return`)
|
|
|
+- **NEVER** 新增 `uni.getSystemInfoSync()` 调用。该 API 已在微信基础库 2.20.1+ 弃用,开发者工具会持续告警(`getSystemInfoSync is deprecated`)→ 改用 `uni.getWindowInfo()`(取 `windowWidth`/`pixelRatio`/`safeArea` 等窗口信息)或 `uni.getDeviceInfo()`(取 `system`/`brand`/`model` 等设备信息)。已有兼容代码(`components/mp-html/` 内的 `uni.canIUse('getWindowInfo')` 兜底)保持不变。参考替换:`uni.getSystemInfoSync().pixelRatio` → `uni.getWindowInfo().pixelRatio`
|
|
|
+- **NEVER** 给 `props` 传可能为非数组的值而不做兜底。组件接收 `Array` 类型 prop 时,父组件传值必须保证是数组(`|| []` 兜底 + `Array.isArray` 校验),否则触发 `Invalid prop: type check failed for prop "xxx". Expected Array, got Object` 告警。典型场景:接口返回结构不确定(`res.data.list` 可能为 `Object`)时,用 `var arr = (res.data && res.data.list) || (res.data instanceof Array ? res.data : [])` 三态兼容
|
|
|
+
|
|
|
+
|
|
|
+- **NEVER** 在页面模板中写 `<text class="nav-title">` 或自定义 nav-bar 标题。所有静态标题统一在 `pages.json` 的 `navigationBarTitleText` 中配置。需要运行时动态标题时才用自定义 nav-bar
|
|
|
+- **NEVER** 在同一个页面中多次调用相同的 API 接口。如果第一次请求的结果需要用于后续请求的参数,在第一次请求的 success/then 回调中发起第二次请求,而不是并行调用
|
|
|
+
|
|
|
+## UNIQUE FEATURES
|
|
|
+
|
|
|
+- 地址匹配页面: `pages/match/street-match.vue` - 街道地址匹配功能
|
|
|
+- 地址编辑页面: `pages/family/address-edit.vue` - 家庭地址管理
|
|
|
+- 四级地址选择: `components/address-picker.vue` - 省市区街道联动
|
|
|
+- 双角色界面: 根据用户角色(parent/child)显示不同UI
|
|
|
+
|
|
|
+## BUILD SYSTEM
|
|
|
+
|
|
|
+### 打包方式(强制规范)
|
|
|
+
|
|
|
+**小程序打包必须用 HBuilderX 完成,Agent 禁止自行执行 `npm run build:mp-weixin` 等打包命令。**
|
|
|
+
|
|
|
+- 打包工具:HBuilderX(导入 `cfc-frontend/` 目录 → 运行 → 运行到小程序模拟器 → 微信开发者工具)
|
|
|
+- 打包产物:**`cfc-frontend/unpackage/`** 目录(HBuilderX 输出位置,dev 产物在 `unpackage/dist/dev/mp-weixin/`)
|
|
|
+- 微信开发者工具导入的目录是 `unpackage/dist/dev/mp-weixin/`(或 HBuilderX 自动打开),**不是** `dist/`
|
|
|
+- `dist/` 目录是 npm CLI 打包的残留产物,**不可用**——`app.js` 仅有 89 字节(require 三行),非完整产物
|
|
|
+- Agent 修改代码后:只做**语法/结构校验**(如 `node --check` 提取的 script 块),**不打包、不运行 build 命令**
|
|
|
+- 页面白板排查第一步:确认用户是否在 HBuilderX 中**重新打包**过(改代码后未重新打包 → 产物过期 → 白板)
|
|
|
+
|
|
|
+### 依赖约束(2026-07-23 修复后锁定)
|
|
|
+
|
|
|
+| 包 | 版本 | 原因 |
|
|
|
+|----|------|------|
|
|
|
+| `@vue/cli-service` | `~4.5.0` | v5 使用 webpack 5,`@dcloudio/uni-mp-weixin` 依赖 `webpack/lib/GraphHelpers`(webpack 4 特有)|
|
|
|
+| `@vue/cli-plugin-babel` | `~4.5.0` | 与 cli-service v4 匹配 |
|
|
|
+| `postcss` (override + dependency) | `7.0.39` | `remove-scoped.js` 在 PostCSS 8 下会走 v8 插件路径,但 `spaces` 属性访问有兼容问题 |
|
|
|
+| `node-sass` | (devDependency) | `@dcloudio/vue-cli-plugin-uni` 内置的 sass-loader 需要 |
|
|
|
+| `copy-webpack-plugin` | `^5.1.2` | 与 cli-service v4 的 webpack 4 兼容 |
|
|
|
+
|
|
|
+### postinstall 自动补丁
|
|
|
+
|
|
|
+`npm install` 后会自动运行 `postinstall-fix.js`,修补 `remove-scoped.js` 中的 `spaces` 崩溃:
|
|
|
+
|
|
|
+```js
|
|
|
+// 问题: selector.first 可能为 undefined
|
|
|
+// 修改前: selector.first.spaces.before = '';
|
|
|
+// 修改后: if (selector.first) { selector.first.spaces.before = ''; }
|
|
|
+```
|
|
|
+
|
|
|
+### 已知编译错误处理
|
|
|
+
|
|
|
+| 错误 | 原因 | 处理 |
|
|
|
+|------|------|------|
|
|
|
+| `Cannot read properties of undefined (reading 'spaces')` in `remove-scoped.js` | PostCSS 节点没有 `spaces` 属性 | postinstall-fix.js 自动补丁 |
|
|
|
+| `Cannot find module 'webpack/lib/GraphHelpers'` | `@vue/cli-service v5` 的 webpack 5 不支持 | 保持 `@vue/cli-service ~4.5.0` |
|
|
|
+| `Cannot find module 'node-sass'` | uni-app sass-loader 需要 | `npm install node-sass --save-dev` |
|
|
|
+| `getPreCompileOptions` DevTools 内部错误 | `dist/dev/mp-weixin/` 缺少 `project.config.json` | 先 `npm run build:mp-weixin` 生成 dist |
|
|
|
+| `Unexpected token` in `.vue` | JS 语法错误,常见于方法被截断/拼接错误 | 检查 v-on:click/方法调用是否正确闭合 |
|
|
|
+
|
|
|
+### 修改 `remove-scoped.js` 的风险
|
|
|
+
|
|
|
+该文件在 `node_modules/@dcloudio/vue-cli-plugin-uni/` 内,每次 `npm install` 会通过 `postinstall-fix.js` 自动恢复补丁。如需手动执行:
|
|
|
+
|
|
|
+```bash
|
|
|
+node postinstall-fix.js
|
|
|
+```
|
|
|
+
|
|
|
+**不要**将 `@vue/cli-service` 升级到 v5,除非:
|
|
|
+- `@dcloudio/uni-mp-weixin` 确认移除了 `webpack/lib/GraphHelpers` 依赖
|
|
|
+- 或者找到替代方法处理独立分包插件
|
|
|
+
|
|
|
+## COMMANDS
|
|
|
+
|
|
|
+```bash
|
|
|
+npm install # 安装依赖(自动运行 postinstall-fix.js)
|
|
|
+# 注意:打包一律用 HBuilderX(产物在 unpackage/),Agent 不要执行 npm run build:mp-weixin
|
|
|
+```
|
|
|
+
|
|
|
+## NOTES
|
|
|
+
|
|
|
+- 小程序AppID: `wx5ba8038ef16fb245`
|
|
|
+- 后端API地址: 配置在 `config/index.js` 的 `baseUrl`
|
|
|
+- 地址数据: 使用后端街道API获取四级地址数据
|
|
|
+- 调试工具: 微信开发者工具需配置合法域名
|
|
|
+- **打包流程(HBuilderX)**:HBuilderX 打开 `cfc-frontend/` → 运行到微信开发者工具 → 产物输出至 `unpackage/dist/dev/mp-weixin/`。改代码后必须在 HBuilderX 中重新运行打包,否则小程序显示旧产物(甚至白板)
|
|
|
+- **禁止**在终端执行 `npm run build:mp-weixin` 或 `npm run dev:mp-weixin` 自行打包(产物进 `dist/` 而非 `unpackage/`,与 HBuilderX 工作流冲突)
|