|
|
|
|
# AGENTS.md — IGG4 微信小程序
|
|
|
|
|
|
|
|
|
|
## 项目概述
|
|
|
|
|
|
|
|
|
|
IGG4 重症肌无力(MG)患者社区微信小程序。两种用户角色:患者(loginType=1)和医生(loginType=2)。基于 TypeScript + SCSS 构建,无测试框架。
|
|
|
|
|
|
|
|
|
|
### 技术栈
|
|
|
|
|
|
|
|
|
|
| 类别 | 技术 |
|
|
|
|
|
|------|------|
|
|
|
|
|
| 语言 | TypeScript + SCSS + WXML |
|
|
|
|
|
| 包管理 | pnpm(非 npm/yarn) |
|
|
|
|
|
| UI 库 | Vant Weapp (`@vant/weapp`) |
|
|
|
|
|
| 图表 | ECharts(`ec-canvas` 组件)+ F2(JSX 语法,Babel 转译) |
|
|
|
|
|
| 日期 | dayjs(中文 locale + relativeTime 插件) |
|
|
|
|
|
| 工具库 | miniprogram-licia(curry、debounce 等) |
|
|
|
|
|
| 富文本 | mp-html |
|
|
|
|
|
| 精度计算 | number-precision |
|
|
|
|
|
| 代码规范 | @antfu/eslint-config + prettier(无分号、单引号、尾逗号、120 字符宽度) |
|
|
|
|
|
|
|
|
|
|
## 命令
|
|
|
|
|
|
|
|
|
|
- `pnpm install` — 安装依赖(使用 pnpm,非 npm/yarn)
|
|
|
|
|
- `pnpm run lint:fix` — eslint 自动修复(使用 @antfu/eslint-config + prettier,stylistic 已禁用)
|
|
|
|
|
- `pnpm run beforeCompile` — babel 转译 `src/pages` 中的 `.jsx` 文件(通过 `project.config.json` scripts 在微信开发者工具编译/预览/上传前自动执行)
|
|
|
|
|
|
|
|
|
|
无 `build`、`test` 或 `typecheck` 脚本。类型检查和编译由微信开发者工具处理。
|
|
|
|
|
|
|
|
|
|
## 架构
|
|
|
|
|
|
|
|
|
|
- **源码根目录**:`src/`(在 project.config.json 中设为 `miniprogramRoot`)
|
|
|
|
|
- **入口**:`src/app.ts` + `src/app.json`
|
|
|
|
|
- **路径别名**:`@/*` 映射到 `src/*`(tsconfig paths + app.json resolveAlias)
|
|
|
|
|
- **自定义 Page 包装器**:`src/utils/page.ts` 在 `app.ts` onLaunch 时全局替换 `Page()` — 注入 `imageUrl`/`Timestamp` 数据、滚动导航栏变色、默认分享行为、`handleMakePhoneCall`。所有页面都经过此包装器。
|
|
|
|
|
- **HTTP 请求**:`src/api/request.ts` 将 `wx.request` 封装为 `wx.ajax`(通过 `licia.curry` 柯里化基础 URL)。所有 API 调用使用 `wx.ajax()`,而非 `wx.request()`。自动在 header 和 body 中注入 `loginState`。
|
|
|
|
|
- **npm 包**:由微信开发者工具构建到 `src/miniprogram_npm/`(packNpmManually 配置)。不要直接编辑 miniprogram_npm。
|
|
|
|
|
|
|
|
|
|
### 登录与权限系统(app.ts)
|
|
|
|
|
|
|
|
|
|
- **登录流程**:`onShow` → `startLogin()` → `wx.login` 获取 code → 后端 `init-login` 返回 `loginState`
|
|
|
|
|
- **用户等级**(`UserType`):
|
|
|
|
|
- 1:空白用户 → 跳转登录页
|
|
|
|
|
- 2:已注册用户 → 需完善资料
|
|
|
|
|
- 3:已确诊患者 → 需上传认证
|
|
|
|
|
- 4:已用药患者(VIP)→ 完整权限
|
|
|
|
|
- **路由守卫**:`verifySys(pub)` 检查登录状态和角色,自动重定向:
|
|
|
|
|
- 未登录 + 医生端页面 → 医生登录页
|
|
|
|
|
- 未登录 + 患者端页面 → 患者登录页(若 anyWhere 为 true 则"随便看看"模式)
|
|
|
|
|
- 患者访问医生端页面 → 重定向到患者首页
|
|
|
|
|
- 医生访问患者端页面 → 重定向到医生中转页
|
|
|
|
|
- **权限校验**:`permissionVerification(grade, registChannel, backPage, regBusinessId)` 按等级拦截
|
|
|
|
|
- **注册验证**:`registrationVerification(callback, loginPage)` 根据审核状态引导用户(AuditStatus: 0=无证书, 1=审核中, 2=已拒绝)
|
|
|
|
|
- **关键全局变量**:`loginState`(令牌)、`isLogin`(0/1)、`isReg`、`loginType`(1=患者, 2=医生)、`anyWhere`(免登录浏览模式)、`first`(首次启动标志)
|
|
|
|
|
|
|
|
|
|
### 数据监听机制
|
|
|
|
|
|
|
|
|
|
- `app.watch(key, method)` — 通过 Object.defineProperty 监听 globalData 变化
|
|
|
|
|
- `app.registerListener(fn)` / `app.triggerListeners()` — 全局事件监听模式(custom-tab-bar 等使用)
|
|
|
|
|
- `setWatcher(page)`(来自 `utils/watch.ts`)— 页面级 watch 支持
|
|
|
|
|
|
|
|
|
|
### 自定义 TabBar(5 个 Tab)
|
|
|
|
|
|
|
|
|
|
| Tab | 页面路径 | 名称 |
|
|
|
|
|
|-----|---------|------|
|
|
|
|
|
| 1 | `/pages/index/index` | 首页 |
|
|
|
|
|
| 2 | `/pages/repository/index` | MG全知道 |
|
|
|
|
|
| 3 | `/pages/live/index` | 周三大咖说 |
|
|
|
|
|
| 4 | `/pages/story/index` | 向往的生活 |
|
|
|
|
|
| 5 | `/pages/my/index` | 我的 |
|
|
|
|
|
|
|
|
|
|
- 自定义 TabBar 使用 Vant `van-tabbar` 组件
|
|
|
|
|
- Tab 4(向往的生活)在 `anyWhere` 为 true 时隐藏(浏览模式)
|
|
|
|
|
- Tab 2(MG全知道)在 `config.picTextEbookStatus === 1` 时可能重定向到 webview
|
|
|
|
|
- Tab 5(我的)需要 `permissionVerification(grade=2)`
|
|
|
|
|
- 主题支持:DRUG / PATIENT(当前始终解析为 PATIENT)
|
|
|
|
|
|
|
|
|
|
### HTTP 响应约定(api/request.ts)
|
|
|
|
|
|
|
|
|
|
- 成功:`code === 0` → 返回 `data` 字段
|
|
|
|
|
- 错误且 `showMsg=true`(默认):显示 toast 错误提示
|
|
|
|
|
- `isJSON=true`:返回完整响应(不仅仅是 data)
|
|
|
|
|
- `loading=true`:显示/隐藏加载遮罩
|
|
|
|
|
- 错误信息提取顺序:`data` → `msg` → `errMsg` → `detail.errMsg` → "未知错误"
|
|
|
|
|
|
|
|
|
|
## 分包
|
|
|
|
|
|
|
|
|
|
| 分包 | 路径 | 页面数 | 说明 |
|
|
|
|
|
|------|------|--------|------|
|
|
|
|
|
| 主包 | `src/pages/` | 55+ | 患者端核心页面 |
|
|
|
|
|
| gift | `src/gift/` | 20 | 积分商城、健康档案、皮损记录 |
|
|
|
|
|
| doctor | `src/doctor/` | 22 | 医生端完整功能(含独立 tabbar 组件) |
|
|
|
|
|
| public | `src/public/` | 3 | 知情同意流程 |
|
|
|
|
|
| doc | `src/doc/` | 2 | 文档页面 |
|
|
|
|
|
| resource | `src/resource/` | 0 | 独立分包(当前为空) |
|
|
|
|
|
|
|
|
|
|
### 主包页面(src/pages/)
|
|
|
|
|
|
|
|
|
|
按功能分类:
|
|
|
|
|
- **认证流程**:`start`、`login`、`vipLogin`、`vipLoginReject`、`startReject`、`startPending`、`getUserInfo`
|
|
|
|
|
- **注册**:`enterInfo`、`uploadCert`、`certReslove`、`certPending`
|
|
|
|
|
- **首页**:`index`
|
|
|
|
|
- **知识库**:`repository`、`repositoryDetail`、`repositoryVideoDetail`
|
|
|
|
|
- **直播/会议**:`live`、`liveDetail`、`liveResult`、`myLive`
|
|
|
|
|
- **故事**:`story`、`storyDetail`、`storyEnter`、`storyEnterResult`、`storyList`、`storyGuide`、`publishStoryDetail`
|
|
|
|
|
- **ADL 评估**:`adl`、`adlShare`、`adlTest`、`adlResult`
|
|
|
|
|
- **个人中心**:`my`、`mySave`、`personalInformation`、`changePhone`、`changeUser`、`cancellation`
|
|
|
|
|
- **家庭**:`family`、`familyList`、`familyScan`
|
|
|
|
|
- **医疗**:`hospital`、`doctor`、`doctorDetail`、`drugRecord`、`infusionCenter`、`nrdl`、`nrdlDetail`、`nrdlTable`
|
|
|
|
|
- **其他**:`thePublic`、`privacyAgreement`、`taskAgreement`、`comIns`、`signIn`、`smallPage`、`webview`、`referral`、`interactivePatient`、`demo`
|
|
|
|
|
|
|
|
|
|
### 医生端分包页面(src/doctor/)
|
|
|
|
|
|
|
|
|
|
- **认证**:`d_login`
|
|
|
|
|
- **首页**:`d_home`
|
|
|
|
|
- **患者管理**:`d_patient`、`d_patientDetail`、`d_patientList`
|
|
|
|
|
- **任务**:`d_taskList`、`d_taskDetail`、`d_createTask`
|
|
|
|
|
- **互动**:`d_interactive`、`d_interactiveDoctor`
|
|
|
|
|
- **个人**:`d_my`、`d_userInfo`、`d_changePhone`、`d_changeDoctor`
|
|
|
|
|
- **邀请**:`d_invite`
|
|
|
|
|
- **导出**:`d_exportList`、`d_customExport`、`d_customExportMiddle`
|
|
|
|
|
- **转诊**:`d_transfer`、`d_transferLog`、`d_transferDetail`
|
|
|
|
|
- **路由中转**:`d_trans`(医生访问患者端页面的中转页)
|
|
|
|
|
|
|
|
|
|
### 礼品分包页面(src/gift/)
|
|
|
|
|
|
|
|
|
|
- **积分商城**:`giftList`、`giftDetail`、`conformOrder`
|
|
|
|
|
- **订单**:`orderEnd`、`orderDetail`
|
|
|
|
|
- **地址**:`siteList`、`siteEdit`
|
|
|
|
|
- **积分**:`myGift`、`priceDetail`、`scoreRule`
|
|
|
|
|
- **健康档案**:`myHealthRecord`、`myHealthRecordChart`
|
|
|
|
|
- **VIP**:`vipCert`、`vipReject`、`vipPending`、`vipStartPending`
|
|
|
|
|
- **DTP**:`dtpDurg`
|
|
|
|
|
- **皮损**:`cutaneous`、`cutaneousDetail`、`cutaneousVideo`
|
|
|
|
|
|
|
|
|
|
## 全局组件(src/components/)
|
|
|
|
|
|
|
|
|
|
| 组件 | 说明 |
|
|
|
|
|
|------|------|
|
|
|
|
|
| `calendar` | 日历选择器 |
|
|
|
|
|
| `customPoster` | 自定义海报生成 |
|
|
|
|
|
| `customTable` | 自定义数据表格 |
|
|
|
|
|
| `ec-canvas` | ECharts 画布包装器 |
|
|
|
|
|
| `freeAudio` | 音频播放 |
|
|
|
|
|
| `loginNavbar` | 登录页导航栏 |
|
|
|
|
|
| `navBar` | 通用导航栏 |
|
|
|
|
|
| `pageNavbar` | 页面级导航栏 |
|
|
|
|
|
| `pagination` | 分页组件(在 app.json 中全局注册) |
|
|
|
|
|
| `pickerArea` | 地区选择器 |
|
|
|
|
|
| `referralFrom` | 转诊来源选择器 |
|
|
|
|
|
| `star` | 星级评分 |
|
|
|
|
|
| `text-expandsion` | 文本展开/收起 |
|
|
|
|
|
| `timeOut` | 倒计时 |
|
|
|
|
|
| `toast` | 自定义弹窗提示 |
|
|
|
|
|
| `uploadFile` | 文件上传 |
|
|
|
|
|
| `viewFile` | 文件查看 |
|
|
|
|
|
| `viewVideo` | 视频播放器 |
|
|
|
|
|
|
|
|
|
|
## 工具函数(src/utils/)
|
|
|
|
|
|
|
|
|
|
| 文件 | 说明 |
|
|
|
|
|
|------|------|
|
|
|
|
|
| `page.ts` | Page() 全局替换:注入 imageUrl/Timestamp、滚动导航栏变色、默认分享、handleMakePhoneCall |
|
|
|
|
|
| `util.ts` | formatTime、formatNumber、getCurrentPageUrl、getCurrentPageUrlWithArgs、parseScene |
|
|
|
|
|
| `promisify.ts` | 基于 Proxy 的 wx API Promise 化(同步方法保留,异步方法返回 Promise) |
|
|
|
|
|
| `watch.ts` | 基于 Object.defineProperty 的页面级数据监听(setWatcher) |
|
|
|
|
|
| `doctorPatientTask.ts` | 医生端患者筛选列定义(ADL、激素剂量、抗体类型等) |
|
|
|
|
|
| `tools.wxs` | WXS 模板工具 |
|
|
|
|
|
| `dayjs/` | dayjs 插件(中文 locale、relativeTime) |
|
|
|
|
|
|
|
|
|
|
## 类型定义(typings/index.d.ts)
|
|
|
|
|
|
|
|
|
|
- `IAppOption` — App 实例接口,包含 globalData 结构和方法签名
|
|
|
|
|
- `IAgaxParams` — 扩展的请求选项,含 `showMsg`、`loading`、`isJSON`
|
|
|
|
|
- `Response<T>` — 通用 API 响应结构
|
|
|
|
|
- `globalSystemInfo` — 扩展的系统信息,含胶囊按钮位置
|
|
|
|
|
- `WechatMiniprogram.Wx.ajax` — wx.ajax 的类型增强
|
|
|
|
|
|
|
|
|
|
## 页面结构
|
|
|
|
|
|
|
|
|
|
每个页面是一个目录,包含 4 个文件:`index.ts`、`index.wxml`、`index.scss`、`index.json`。组件遵循相同的 4 文件模式。
|
|
|
|
|
|
|
|
|
|
### 新增页面
|
|
|
|
|
|
|
|
|
|
1. 在对应分包下创建目录(如 `src/pages/myPage/`)
|
|
|
|
|
2. 创建 4 个文件:`index.ts`、`index.wxml`、`index.scss`、`index.json`
|
|
|
|
|
3. 在 `src/app.json` 中注册:
|
|
|
|
|
- 主包页面 → `pages` 数组
|
|
|
|
|
- 分包页面 → `subpackages` 中对应分包的 `pages` 数组
|
|
|
|
|
4. 如页面使用组件,在页面的 `index.json` 的 `usingComponents` 中注册
|
|
|
|
|
|
|
|
|
|
### 新增组件
|
|
|
|
|
|
|
|
|
|
1. 在 `src/components/` 下创建目录(医生端在 `src/doctor/components/`)
|
|
|
|
|
2. 创建 4 个文件:`index.ts`、`index.wxml`、`index.scss`、`index.json`
|
|
|
|
|
3. 在页面的 `index.json` 中注册:`"usingComponents": { "my-comp": "/components/myComp/index" }`
|
|
|
|
|
4. 全局注册则在 `app.json` 的 `usingComponents` 中添加
|
|
|
|
|
|
|
|
|
|
## 关键约定
|
|
|
|
|
|
|
|
|
|
- **JSX/F2 图表**:Babel 插件 `@babel/plugin-transform-react-jsx`,`jsxImportSource: "@antv/f2"` — 页面中的 `.jsx` 文件使用 F2 图表语法,由 beforeCompile 脚本转译
|
|
|
|
|
- **微信全局变量**:`wx`、`App`、`Page`、`Component`、`getCurrentPages`、`getApp` 已在 ESLint globals 中声明
|
|
|
|
|
- **CSS 单位**:使用 `rpx`(微信响应式像素),布局中不用 `px`
|
|
|
|
|
- **图片**:存储在 `src/images/`,通过 SVN 部署(非 git,图片已 gitignore)。使用 `dist.ps1`/`dist.sh`/`dist.nu` 脚本部署
|
|
|
|
|
- **`noImplicitAny: false`** — 允许隐式 any
|
|
|
|
|
- **`removeComments: true`**(tsconfig)— 编译输出移除注释
|
|
|
|
|
- **Prettier**:无分号、单引号、尾逗号、120 字符宽度;`.wxml` 按 HTML 解析,`.wxss` 按 CSS 解析,`.wxs` 按 babel 解析
|
|
|
|
|
- **API URL 格式**:所有 API 调用使用 `?r=模块/动作` 格式(如 `?r=zd/user/init-login`、`?r=zd/account/info`)
|
|
|
|
|
- **默认分享**:患者端页面分享到 `/pages/index/index`,医生端页面分享到 `/doctor/pages/d_home/index`,标题:"重症肌无力加油站,重拾生活掌控感!"
|
|
|
|
|
- **客服电话**:全局 `handleMakePhoneCall` 拨打 `4008102299`
|
|
|
|
|
|
|
|
|
|
## 环境 / 部署
|
|
|
|
|
|
|
|
|
|
- 开发环境 API:`https://m.igg4.hbraas.com`(在 `app.ts` globalData 中硬编码)
|
|
|
|
|
- 生产环境 API:`https://m.igg4.hbsaas.com`(已注释,部署时切换)
|
|
|
|
|
- 上传 URL 与 API 同域名,末尾加 `/`
|
|
|
|
|
- 图片 URL:`{domain}/igg4/`
|
|
|
|
|
- 开发 AppID:`wxc3cdb3c4d4f62cea`,生产 AppID:`wx96f45ca4f1fa36ec`
|
|
|
|
|
- 微信开发者工具负责编译、npm 构建、预览和上传
|
|
|
|
|
- `project.private.config.json` 本地覆盖 `project.config.json`
|
|
|
|
|
- 切换环境:取消 `app.ts` globalData 中生产 URL 的注释 + 修改 `project.config.json` 中的 appid
|
|
|
|
|
- 图片通过 `project.config.json` 中的 `packOptions.ignore` 排除上传
|