You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
15 KiB
15 KiB
AGENTS.md — IGG4 微信小程序
项目概述
愈见昕生(原 gMG给力加油站/重症肌无力加油站)— MG 患者社区微信小程序。两种用户角色:患者(loginType=1)和医生(loginType=2)。基于 TypeScript + SCSS 构建,无测试框架。
信达小程序项目位置 C:\Users\kola\project\xinda-miniprogram
技术栈
| 类别 | 技术 |
|---|---|
| 语言 | 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.jsonscripts 在微信开发者工具编译/预览/上传前自动执行)
无 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.tsonLaunch 时全局替换Page()— 注入imageUrl/Timestamp/theme数据、滚动导航栏变色、默认分享行为、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。
主题系统(DRUG / PATIENT)
用药患者(VIP,UserType >= 4)使用紫色 DRUG 主题,非用药患者使用绿色 PATIENT 主题。
app.getTheme():异步获取用户主题,返回'DRUG'或'PATIENT'。内部轮询等待userInfo加载完成。page.ts全局注入:在setImageParams中为所有非医生端页面注入data.theme,初始值'PATIENT',异步通过getTheme()更新为'DRUG'(如适用)。医生端页面不注入theme。- 页面根元素 id:所有患者端 WXML 页面根
<view>添加id="{{theme === 'DRUG' && 'drug-page'}}",用药患者时 id 为drug-page,非用药患者时 id 为空。 - CSS 覆盖方式:在 SCSS 中通过
#drug-page选择器覆盖用药患者样式,无需修改原有绿色样式。
用药患者(DRUG)主题色值
| 类型 | 色值 |
|---|---|
| 文字色 | rgba(89, 86, 233, 1) |
| 按钮渐变 | linear-gradient(270deg, #5956E9 0%, #B384F4 100%) |
| 浅色背景 | rgba(89, 86, 233, 0.1) |
主题使用示例(SCSS)
.btn { background: #0eb66d; }
#drug-page .btn { background: linear-gradient(270deg, #5956E9 0%, #B384F4 100%); }
.text { color: #0eb66d; }
#drug-page .text { color: rgba(89, 86, 233, 1); }
主题使用示例(WXML)
<image src="{{imageUrl}}{{theme === 'DRUG' ? 'bg22' : 'bg15'}}.png?t={{Timestamp}}" />
登录与权限系统(app.ts)
- 登录流程:
onShow→startLogin()→wx.login获取 code → 后端init-login返回loginState - 用户等级(
UserType):- 1:空白用户 → 跳转登录页
- 2:已注册用户 → 需完善资料
- 3:已确诊患者 → 需上传认证
- 4:已用药患者(VIP)→ 完整权限,使用 DRUG 主题
- 路由守卫:
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(
src/custom-tab-bar/):使用 Vantvan-tabbar组件,额外包含"用药提醒"自定义按钮(item.custom=true),仅theme === 'DRUG'时展示 - 医生端 TabBar(
src/doctor/components/tabbar/):自定义组件(非 Vant),纯 HTML/CSS 实现 - Tab 4(向往的生活)在
anyWhere为 true 时隐藏(浏览模式) - Tab 2(MG全知道)在
config.picTextEbookStatus === 1时可能重定向到 webview - Tab 5(我的)需要
permissionVerification(grade=2) - 患者 TabBar 通过
app.registerListener监听全局事件更新theme
医患互动消息类型
互动页面(d_interactive/d_interactiveDoctor/interactivePatient)仅支持以下消息类型:
| msgContentType | 类型 | 说明 |
|---|---|---|
| 1 | 文本(患者发送) | 患者发送的标准消息 |
| 2 | 出诊时间 | 医生出诊时间信息 |
| 5 | 欢迎语 | 欢迎引导消息 |
| 10 | ADL | ADL 评估相关消息 |
| 11 | 文本(患者) | 患者文本消息 |
| 12 | 文本(医生自定义) | 医生自定义文本回复 |
已移除的类型:audio(4)、info(6)、info(7)、referral(8)、referral-replay(9)。
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 - 互动:
interactivePatient - 其他:
thePublic、privacyAgreement、taskAgreement、comIns、signIn、smallPage、webview、referral、demo、qaForm
医生端分包页面(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/doctor/components/)
| 组件 | 说明 |
|---|---|
tabbar |
医生端自定义 TabBar(非 Vant,纯 HTML/CSS) |
工具函数(src/utils/)
| 文件 | 说明 |
|---|---|
page.ts |
Page() 全局替换:注入 imageUrl/Timestamp/theme、滚动导航栏变色、默认分享、handleMakePhoneCall。医生端页面不注入 theme。 |
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 结构和方法签名(含getTheme())IAgaxParams— 扩展的请求选项,含showMsg、loading、isJSONResponse<T>— 通用 API 响应结构globalSystemInfo— 扩展的系统信息,含胶囊按钮位置WechatMiniprogram.Wx.ajax— wx.ajax 的类型增强
页面结构
每个页面是一个目录,包含 4 个文件:index.ts、index.wxml、index.scss、index.json。组件遵循相同的 4 文件模式。
新增页面
- 在对应分包下创建目录(如
src/pages/myPage/) - 创建 4 个文件:
index.ts、index.wxml、index.scss、index.json - 在
src/app.json中注册:- 主包页面 →
pages数组 - 分包页面 →
subpackages中对应分包的pages数组
- 主包页面 →
- 如页面使用组件,在页面的
index.json的usingComponents中注册 - 患者端页面:根
<view>需添加id="{{theme === 'DRUG' && 'drug-page'}}"以支持 DRUG 主题覆盖
新增组件
- 在
src/components/下创建目录(医生端在src/doctor/components/) - 创建 4 个文件:
index.ts、index.wxml、index.scss、index.json - 在页面的
index.json中注册:"usingComponents": { "my-comp": "/components/myComp/index" } - 全局注册则在
app.json的usingComponents中添加
关键约定
- 品牌名称:项目品牌名"愈见昕生",不再使用"重症肌无力加油站"或"gMG给力加油站"
- 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— 允许隐式 anyremoveComments: 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 - 医生端页面禁止调用
getTheme():getTheme()仅在page.ts和患者端组件(如custom-tab-bar)中使用 - 患者端页面禁止重复调用
getTheme():page.ts已全局注入theme,页面中无需再次调用
环境 / 部署
- 开发环境 API:
https://m.igg4.hbraas.com(在app.tsglobalData 中硬编码) - 生产环境 API:
https://m.igg4.hbsaas.com(已注释,部署时切换) - 上传 URL 与 API 同域名,末尾加
/ - 图片 URL:
{domain}/igg4/ - 开发 AppID:
wxc3cdb3c4d4f62cea,生产 AppID:wx96f45ca4f1fa36ec - 微信开发者工具负责编译、npm 构建、预览和上传
project.private.config.json本地覆盖project.config.json- 切换环境:取消
app.tsglobalData 中生产 URL 的注释 + 修改project.config.json中的 appid - 图片通过
project.config.json中的packOptions.ignore排除上传