From 9523f9c27e5eed3b12b26141bb941daf10d6ee60 Mon Sep 17 00:00:00 2001 From: kola-web Date: Tue, 21 Jul 2026 10:38:07 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E8=81=94=E8=B0=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api-doc/PSVT协议模块接口文档.md | 250 ++++++++++ api-doc/psvt-patient-api-doc.md | 848 ++++++++++++++++++++++++++++++++ project.config.json | 2 +- project.private.config.json | 32 +- src/app.json | 14 +- src/app.ts | 14 +- src/doc/pages/doc/index.json | 10 + src/doc/pages/doc/index.scss | 46 ++ src/doc/pages/doc/index.ts | 103 ++++ src/doc/pages/doc/index.wxml | 32 ++ src/images/icon40.png | Bin 0 -> 668 bytes src/images/icon41.png | Bin 0 -> 599 bytes src/images/icon42.png | Bin 0 -> 626 bytes src/images/icon9-active.png | Bin 0 -> 1067 bytes src/pages/myCollection/index.json | 12 + src/pages/myCollection/index.scss | 209 ++++++++ src/pages/myCollection/index.ts | 111 +++++ src/pages/myCollection/index.wxml | 74 +++ src/pages/myComment/index.json | 10 + src/pages/myComment/index.scss | 155 ++++++ src/pages/myComment/index.ts | 103 ++++ src/pages/myComment/index.wxml | 45 ++ src/pages/myWall/index.scss | 2 +- src/pages/userInfo/index.json | 10 + src/pages/userInfo/index.scss | 92 ++++ src/pages/userInfo/index.ts | 103 ++++ src/pages/userInfo/index.wxml | 60 +++ src/pages/wall/index.wxml | 1 - src/pages/wallDetail/index.json | 4 +- src/pages/wallDetail/index.scss | 68 ++- src/pages/wallDetail/index.ts | 1 + src/pages/wallDetail/index.wxml | 38 +- typings/index.d.ts | 3 +- 33 files changed, 2422 insertions(+), 30 deletions(-) create mode 100644 api-doc/PSVT协议模块接口文档.md create mode 100644 api-doc/psvt-patient-api-doc.md create mode 100644 src/doc/pages/doc/index.json create mode 100644 src/doc/pages/doc/index.scss create mode 100644 src/doc/pages/doc/index.ts create mode 100644 src/doc/pages/doc/index.wxml create mode 100644 src/images/icon40.png create mode 100644 src/images/icon41.png create mode 100644 src/images/icon42.png create mode 100644 src/images/icon9-active.png create mode 100644 src/pages/myCollection/index.json create mode 100644 src/pages/myCollection/index.scss create mode 100644 src/pages/myCollection/index.ts create mode 100644 src/pages/myCollection/index.wxml create mode 100644 src/pages/myComment/index.json create mode 100644 src/pages/myComment/index.scss create mode 100644 src/pages/myComment/index.ts create mode 100644 src/pages/myComment/index.wxml create mode 100644 src/pages/userInfo/index.json create mode 100644 src/pages/userInfo/index.scss create mode 100644 src/pages/userInfo/index.ts create mode 100644 src/pages/userInfo/index.wxml diff --git a/api-doc/PSVT协议模块接口文档.md b/api-doc/PSVT协议模块接口文档.md new file mode 100644 index 0000000..d80677f --- /dev/null +++ b/api-doc/PSVT协议模块接口文档.md @@ -0,0 +1,250 @@ +# PSVT协议模块接口文档 + +## 概述 +协议模块支持4种协议类型:隐私协议、用户协议、法律声明、健康敏感信息处理与AI服务授权告知书。初始4条数据,无创建接口,仅支持修改更新文案。 + +所有接口返回格式统一为: +```json +{ + "code": 0, + "message": "success", + "data": {} +} +``` + +协议类型常量值: +| 常量值 | 含义 | +|--------|------| +| 1 | 隐私协议 | +| 2 | 用户协议 | +| 3 | 法律声明 | +| 4 | 健康敏感信息处理与AI服务授权告知书 | + +--- + +## 一、小程序端接口 + +### 1. 按类型获取协议详情 + +- **路由**: `?r=psvt/agreement/get-by-type` +- **请求方式**: GET +- **是否需要登录**: 否(白名单路由) + +#### 请求参数 + +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| type | int | 是 | 协议类型:1-隐私协议,2-用户协议,3-法律声明,4-健康敏感信息处理与AI服务授权告知书 | + +#### 响应示例 + +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 1, + "type": 1, + "title": "隐私协议", + "content": "隐私协议内容...", + "version": "V1.0", + "updateTime": "2026-07-17 10:00:00" + } +} +``` + +#### data字段说明 + +| 字段名 | 类型 | 说明 | +|--------|------|------| +| id | int | 协议ID | +| type | int | 协议类型 | +| title | string | 协议标题 | +| content | string | 协议内容(富文本) | +| version | string | 版本号 | +| updateTime | string | 最后更新时间 | + +#### 错误码 + +| code | 说明 | +|------|------| +| 1 | 协议类型参数无效 | +| 1 | 协议不存在 | + +--- + +### 2. 获取协议列表 + +- **路由**: `?r=psvt/agreement/get-list` +- **请求方式**: GET +- **是否需要登录**: 否(白名单路由) + +#### 请求参数 + +无 + +#### 响应示例 + +```json +{ + "code": 0, + "message": "success", + "data": [ + { + "id": 1, + "type": 1, + "title": "隐私协议", + "content": "隐私协议内容...", + "version": "V1.0", + "updateTime": "2026-07-17 10:00:00" + }, + { + "id": 2, + "type": 2, + "title": "用户协议", + "content": "用户协议内容...", + "version": "V1.0", + "updateTime": "2026-07-17 10:00:00" + }, + { + "id": 3, + "type": 3, + "title": "法律声明", + "content": "法律声明内容...", + "version": "V1.0", + "updateTime": "2026-07-17 10:00:00" + }, + { + "id": 4, + "type": 4, + "title": "健康敏感信息处理与AI服务授权告知书", + "content": "健康敏感信息处理与AI服务授权告知书内容...", + "version": "V1.0", + "updateTime": "2026-07-17 10:00:00" + } + ] +} +``` + +#### data字段说明 + +data为数组类型,每个元素字段同"按类型获取协议详情"接口的data字段。 + +--- + +## 二、PC后台管理端接口 + +### 1. 获取协议列表 + +- **路由**: `?r=psvtw/agreement/get-list` +- **请求方式**: GET +- **是否需要登录**: 是 + +#### 请求参数 + +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| search | string | 否 | 搜索关键词(按标题模糊搜索) | +| page | int | 否 | 页码,默认1 | +| count | int | 否 | 每页条数,默认10 | + +#### 响应示例 + +```json +{ + "code": 0, + "message": "success", + "data": { + "total": 4, + "pages": 1, + "list": [ + { + "id": 1, + "type": 1, + "title": "隐私协议", + "content": "隐私协议内容...", + "version": "V1.0", + "updateTime": "2026-07-17 10:00:00" + }, + { + "id": 2, + "type": 2, + "title": "用户协议", + "content": "用户协议内容...", + "version": "V1.0", + "updateTime": "2026-07-17 10:00:00" + }, + { + "id": 3, + "type": 3, + "title": "法律声明", + "content": "法律声明内容...", + "version": "V1.0", + "updateTime": "2026-07-17 10:00:00" + }, + { + "id": 4, + "type": 4, + "title": "健康敏感信息处理与AI服务授权告知书", + "content": "健康敏感信息处理与AI服务授权告知书内容...", + "version": "V1.0", + "updateTime": "2026-07-17 10:00:00" + } + ] + } +} +``` + +#### data字段说明 + +| 字段名 | 类型 | 说明 | +|--------|------|------| +| total | int | 总记录数 | +| pages | int | 总页数 | +| list | array | 协议列表,每个元素字段同小程序端 | + +--- + +### 2. 更新协议文案 + +- **路由**: `?r=psvtw/agreement/update` +- **请求方式**: POST +- **是否需要登录**: 是 +- **事务**: 是 + +#### 请求参数 + +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| id | int | 是 | 协议ID | +| title | string | 否 | 协议标题 | +| content | string | 否 | 协议内容(富文本) | + +> 注:title和content至少传一个,传入的字段才会更新 + +#### 响应示例 + +```json +{ + "code": 0, + "message": "更新成功", + "data": { + "id": 1 + } +} +``` + +#### data字段说明 + +| 字段名 | 类型 | 说明 | +|--------|------|------| +| id | int | 更新的协议ID | + +#### 错误码 + +| code | 说明 | +|------|------| +| 1 | 用户未登录 | +| 1 | 协议ID不能为空 | +| 1 | 协议不存在 | +| 1 | 更新协议失败 | diff --git a/api-doc/psvt-patient-api-doc.md b/api-doc/psvt-patient-api-doc.md new file mode 100644 index 0000000..a42eb5a --- /dev/null +++ b/api-doc/psvt-patient-api-doc.md @@ -0,0 +1,848 @@ +# PSVT患者模块接口文档 + +## 一、小程序端接口 + +### 1.1 初始化登录 `GET ?r=psvt/user/init-login` + +**说明**: 小程序端通过wx.login获取code,发送到服务端完成登录初始化,返回登录态及用户状态信息。 + +**请求参数**: + +| 参数名 | 类型 | 必填 | 说明 | +|---|---|---|---| +| code | string | 是 | wx.login获取的登录凭证 | +| channelId | int | 否 | 扫码渠道ID | + +**响应示例**: +```json +{ + "code": 0, + "data": { + "loginState": "xxx", + "isLogin": true, + "isReg": true, + "userId": "xxx", + "openId": "xxx", + } +} +``` + +**响应字段说明**: + +| 字段名 | 类型 | 说明 | +|---|---|---| +| loginState | string | 登录态凭证,后续接口需携带 | +| isLogin | bool | 是否已登录 | +| userId | string | 用户ID | +| openId | string | 小程序OpenId | +| isPhoneRegistered | bool | 是否已手机号注册 | +| isInfoSubmitted | bool | 是否已提交信息 | + +**业务逻辑**: +1. 调用微信接口获取openid和session_key +2. 创建/更新PSVT用户记录(t_psvt_user_info) +3. 若有channelId参数,更新ScanChannelId(最终渠道,每次扫码都更新) +4. 首次打开时记录FirstOpenTime +5. 返回用户状态信息(isPhoneRegistered、isInfoSubmitted) + +--- + +### 1.2 手机号授权注册 `POST ?r=psvt/patient/phone-register` + +**说明**: 解密微信加密数据获取手机号,完成手机号注册。事务操作。 + +**请求参数**: + +| 参数名 | 类型 | 必填 | 说明 | +|---|---|---|---| +| encryptedData | string | 是 | 微信加密手机号数据 | +| iv | string | 是 | 微信加密iv | +| channelId | int | 否 | 手机号注册时的渠道ID | + +**响应示例**: +```json +{ + "code": 0, + "message": "success", + "data": { + "telephone": "138xxxx1234", + "isPhoneRegistered": true + } +} +``` + +**响应字段说明**: + +| 字段名 | 类型 | 说明 | +|---|---|---| +| telephone | string | 注册的手机号 | +| isPhoneRegistered | bool | 是否已手机号注册 | + +**业务逻辑**: +1. 解密微信加密数据获取手机号 +2. 更新t_psvt_user_info的Telephone、IsPhoneRegistered=1、PhoneRegisterTime +3. 若有channelId,记录TelChannelId(首次手机号注册渠道,仅记录首次,不更新) +4. 若有channelId,记录邀约记录(InviteType=2手机号注册)并更新统计表 +5. 更新IsFirstOpenPhoneRegistered(首次打开时间和手机号注册时间是同一天时为1) +6. 更新IsPhoneRegisteredNotLost(手机号注册时间和提交信息时间是同一天时为1) +7. 使用事务 + +--- + +### 1.3 患者信息提交注册 `POST ?r=psvt/patient/register` + +**说明**: 提交年龄段、性别、确诊状态、手术状态等信息完成注册。事务操作。 + +**请求参数**: + +| 参数名 | 类型 | 必填 | 说明 | +|---|---|---|---| +| ageRange | int | 是 | 年龄段:1-18~28岁,2-29~40岁,3-41~50岁,4-50岁以上 | +| gender | int | 是 | 性别:1-男,2-女 | +| provinceId | int | 否 | 省份ID | +| provinceName | string | 否 | 省份名称 | +| cityId | int | 否 | 市ID | +| cityName | string | 否 | 市名称 | +| diagnosisStatus | int | 是 | 确诊状态:1-疑似PSVT正在了解中,2-已确诊PSVT,3-心悸/心跳过快 尚未就诊,4-亲友相关 想了解更多 | +| diagnosisTime | string | 否 | 确诊时间(YYYY-MM格式) | +| surgeryStatus | int | 是 | 手术状态:1-已接收射频消融/相关手术,2-尚未接收手术,3-正在评估 | +| channelId | int | 否 | 提交信息渠道ID | + +**响应示例**: +```json +{ + "code": 0, + "message": "success", + "data": { + "userId": "xxx", + "nickName": "abcd12345678", + "avatar": "https://psvt.example.com/avatar/3.png", + "isRegistered": true + } +} +``` + +**响应字段说明**: + +| 字段名 | 类型 | 说明 | +|---|---|---| +| userId | string | 用户ID | +| nickName | string | 随机生成的昵称(4字母+8数字) | +| avatar | string | 随机分配的头像URL | +| isRegistered | bool | 是否已注册 | + +**业务逻辑**: +1. 生成随机昵称(4随机字母+8随机数字) +2. 随机分配头像(10张图片池中随机选1) +3. 创建t_psvt_patient_info记录(患者属性) +4. 更新t_psvt_user_info的PatientId、IsInfoSubmitted=1、InfoSubmitTime、SubmitChannelId +5. 更新IsFirstOpenInfoSubmitted(首次打开时间和信息提交时间是同一天时为1) +6. 更新IsPhoneRegisteredNotLost(手机号注册时间和信息提交时间是同一天时为1) +7. 若有channelId,记录邀约记录(InviteType=3信息提交)并更新统计表 +8. 使用事务 + +--- + +### 1.4 获取我的信息 `GET ?r=psvt/patient/my-info` + +**说明**: 返回当前登录用户的完整信息(用户信息+患者属性),小驼峰格式。 + +**请求参数**: 无(通过loginState获取userId) + +**响应示例**: +```json +{ + "code": 0, + "message": "success", + "data": { + "userId": "xxx", + "openId": "xxx", + "telephone": "138xxxx1234", + "isPhoneRegistered": true, + "isInfoSubmitted": true, + "isHeartRateTips": true, + "firstOpenTime": "2023-01-01 10:00:00", + "phoneRegisterTime": "2023-01-01 10:05:00", + "infoSubmitTime": "2023-01-01 10:10:00", + "nickName": "abcd12345678", + "avatar": "https://psvt.example.com/avatar/3.png", + "ageRange": 1, + "gender": 1, + "provinceName": "北京", + "cityName": "北京", + "diagnosisStatus": 2, + "diagnosisTime": "2023-06", + "surgeryStatus": 1 + } +} +``` + +**响应字段说明**: + +| 字段名 | 类型 | 说明 | +|---|---|---| +| userId | string | 用户ID | +| openId | string | 小程序OpenId | +| telephone | string | 手机号 | +| isPhoneRegistered | bool | 是否已手机号注册 | +| isInfoSubmitted | bool | 是否已提交信息 | +| isHeartRateTips | bool | 是否开启心率提醒 | +| firstOpenTime | string | 首次打开时间 | +| phoneRegisterTime | string | 手机号注册时间 | +| infoSubmitTime | string | 信息提交时间 | +| nickName | string | 昵称(未提交信息时为null) | +| avatar | string | 头像URL(未提交信息时为null) | +| ageRange | int | 年龄段(未提交信息时为null) | +| gender | int | 性别(未提交信息时为null) | +| provinceName | string | 省份名称(未提交信息时为null) | +| cityName | string | 市名称(未提交信息时为null) | +| diagnosisStatus | int | 确诊状态(未提交信息时为null) | +| diagnosisTime | string | 确诊时间(未提交信息时为null) | +| surgeryStatus | int | 手术状态(未提交信息时为null) | + +--- + +### 1.5 更新我的信息 `POST ?r=psvt/patient/update-my-info` + +**说明**: 更新当前登录用户的个人信息。若已确诊PSVT(DiagnosisStatus=2),确诊状态和手术状态不可修改。事务操作。 + +**请求参数**: + +| 参数名 | 类型 | 必填 | 说明 | +|---|---|---|---| +| avatar | string | 否 | 头像URL | +| nickName | string | 否 | 昵称 | +| telephone | string | 否 | 手机号 | +| ageRange | int | 否 | 年龄段 | +| gender | int | 否 | 性别 | +| provinceId | int | 否 | 省份ID | +| provinceName | string | 否 | 省份名称 | +| cityId | int | 否 | 市ID | +| cityName | string | 否 | 市名称 | +| diagnosisStatus | int | 否 | 确诊状态(已确诊PSVT后不可修改) | +| diagnosisTime | string | 否 | 确诊时间 | +| surgeryStatus | int | 否 | 手术状态(已确诊PSVT后不可修改) | + +**响应示例**: +```json +{ + "code": 0, + "message": "success", + "data": { + "userId": "xxx", + "openId": "xxx", + "telephone": "138xxxx1234", + "isPhoneRegistered": true, + "isInfoSubmitted": true, + "isHeartRateTips": true, + "firstOpenTime": "2023-01-01 10:00:00", + "phoneRegisterTime": "2023-01-01 10:05:00", + "infoSubmitTime": "2023-01-01 10:10:00", + "nickName": "newNickname", + "avatar": "https://...", + "ageRange": 2, + "gender": 1, + "provinceName": "上海", + "cityName": "上海", + "diagnosisStatus": 2, + "diagnosisTime": "2023-06", + "surgeryStatus": 1 + } +} +``` + +**响应字段说明**: 同1.4获取我的信息 + +**业务逻辑**: +1. 若已确诊PSVT(DiagnosisStatus=2),则diagnosisStatus和surgeryStatus不可修改 +2. 更新t_psvt_patient_info患者属性 +3. 若更新了手机号,同步更新t_psvt_user_info的Telephone +4. 使用事务 + +--- + +### 1.6 渠道码扫码记录 `POST ?r=psvt/?r=channel/scan-channel` + +**说明**: 记录扫码渠道信息,更新用户的ScanChannelId。事务操作。 + +**请求参数**: + +| 参数名 | 类型 | 必填 | 说明 | +|---|---|---|---| +| channelId | int | 是 | 渠道码ID | + +**响应示例**: +```json +{ + "code": 0, + "message": "success", + "data": { + "recorded": true + } +} +``` + +**响应字段说明**: + +| 字段名 | 类型 | 说明 | +|---|---|---| +| recorded | bool | 是否记录成功 | + +**业务逻辑**: +1. 验证渠道码存在 +2. 更新用户ScanChannelId(最终渠道,每次扫码都更新) +3. 记录邀约记录(InviteType=1用户打开) +4. 更新统计表 +5. 使用事务 + +--- + +### 1.7 获取基础数据列表 `GET ?r=psvt/patient/base-data` + +**说明**: 返回性别、年龄段、确诊状态、手术状态等枚举数据,供前端渲染下拉选项。 + +**请求参数**: 无 + +**响应示例**: +```json +{ + "code": 0, + "message": "success", + "data": { + "genderList": [{"1": "男"}, {"2": "女"}], + "ageRangeList": [{"1": "18~28岁"}, {"2": "29~40岁"}, {"3": "41~50岁"}, {"4": "50岁以上"}], + "diagnosisStatusList": [{"1": "疑似PSVT正在了解中"}, {"2": "已确诊PSVT"}, {"3": "心悸/心跳过快 尚未就诊"}, {"4": "亲友相关 想了解更多"}], + "surgeryStatusList": [{"1": "已接收射频消融/相关手术"}, {"2": "尚未接收手术"}, {"3": "正在评估"}] + } +} +``` + +**响应字段说明**: + +| 字段名 | 类型 | 说明 | +|---|---|---| +| genderList | array | 性别列表,每项为 {value: "label"} | +| ageRangeList | array | 年龄段列表,每项为 {value: "label"} | +| diagnosisStatusList | array | 确诊状态列表,每项为 {value: "label"} | +| surgeryStatusList | array | 手术状态列表,每项为 {value: "label"} | + +**genderList值说明**: + +| 值 | 说明 | +|---|---| +| 1 | 男 | +| 2 | 女 | + +**ageRangeList值说明**: + +| 值 | 说明 | +|---|---| +| 1 | 18~28岁 | +| 2 | 29~40岁 | +| 3 | 41~50岁 | +| 4 | 50岁以上 | + +**diagnosisStatusList值说明**: + +| 值 | 说明 | +|---|---| +| 1 | 疑似PSVT正在了解中 | +| 2 | 已确诊PSVT | +| 3 | 心悸/心跳过快 尚未就诊 | +| 4 | 亲友相关 想了解更多 | + +**surgeryStatusList值说明**: + +| 值 | 说明 | +|---|---| +| 1 | 已接收射频消融/相关手术 | +| 2 | 尚未接收手术 | +| 3 | 正在评估 | + +--- + +## 二、后台管理端接口 + +### 2.1 患者列表 `GET ?r=patient/list` + +**说明**: 获取PSVT患者列表,含分页、搜索、渠道筛选及汇总统计。 + +**请求参数**: + +| 参数名 | 类型 | 必填 | 说明 | +|---|---|---|---| +| search | string | 否 | 搜索关键字(手机号/UserId/省市) | +| channelId | int | 否 | 渠道ID筛选 | +| page | int | 否 | 页码,默认1 | +| count | int | 否 | 每页数量,默认10 | + +**响应示例**: +```json +{ + "code": 0, + "message": "success", + "data": { + "page": 1, + "pages": 10, + "count": 100, + "summary": { + "totalOpenCount": 1920, + "phoneRegisteredCount": 1900, + "phoneRegisteredRate": "19.9%", + "infoSubmittedCount": 1082, + "infoSubmittedRate": "56.3%", + "diagnosedPsvtCount": 980, + "diagnosedPsvtRate": "90.2%", + "firstOpenPhoneRegisteredCount": 800, + "firstOpenInfoSubmittedCount": 800, + "phoneRegisteredNotLostCount": 700 + }, + "list": [ + { + "userId": "xxx", + "telephone": "138xxxx1234", + "nickName": "abcd12345678", + "avatar": "https://...", + "ageRange": 1, + "gender": 1, + "provinceName": "北京", + "cityName": "北京", + "diagnosisStatus": 2, + "diagnosisTime": "2023-06", + "surgeryStatus": 1, + "firstOpenTime": "2023-01-01 10:00:00", + "phoneRegisterTime": "2023-01-01 10:05:00", + "infoSubmitTime": "2023-01-01 10:10:00", + "isFirstOpenPhoneRegistered": true, + "isFirstOpenInfoSubmitted": true, + "isPhoneRegisteredNotLost": true, + "scanChannelId": 1, + "scanChannelName": "渠道A", + "telChannelId": 2, + "telChannelName": "渠道B", + "submitChannelId": 3, + "submitChannelName": "渠道C" + } + ] + } +} +``` + +**响应字段说明(data层级)**: + +| 字段名 | 类型 | 说明 | +|---|---|---| +| page | int | 当前页码 | +| pages | int | 总页数 | +| count | int | 总记录数 | +| summary | object | 汇合统计数据 | +| list | array | 患者列表 | + +**summary字段说明**: + +| 字段名 | 类型 | 说明 | +|---|---|---| +| totalOpenCount | int | 总打开数 | +| phoneRegisteredCount | int | 手机号注册数 | +| phoneRegisteredRate | string | 手机号注册率(百分比) | +| infoSubmittedCount | int | 信息提交数 | +| infoSubmittedRate | string | 信息提交率(百分比) | +| diagnosedPsvtCount | int | 确诊PSVT数 | +| diagnosedPsvtRate | string | 确诊PSVT率(百分比) | +| firstOpenPhoneRegisteredCount | int | 首次打开完成手机号注册数 | +| firstOpenInfoSubmittedCount | int | 首次打开完成信息填写数 | +| phoneRegisteredNotLostCount | int | 手机号注册后未流失数 | + +**list行字段说明**: + +| 字段名 | 类型 | 说明 | +|---|---|---| +| userId | string | 用户ID | +| telephone | string | 手机号 | +| nickName | string | 昵称 | +| avatar | string | 头像URL | +| ageRange | int | 年龄段 | +| gender | int | 性别 | +| provinceName | string | 省份名称 | +| cityName | string | 市名称 | +| diagnosisStatus | int | 确诊状态 | +| diagnosisTime | string | 确诊时间 | +| surgeryStatus | int | 手术状态 | +| firstOpenTime | string | 首次打开时间 | +| phoneRegisterTime | string | 手机号注册时间 | +| infoSubmitTime | string | 信息提交时间 | +| isFirstOpenPhoneRegistered | bool | 首次打开完成手机号注册 | +| isFirstOpenInfoSubmitted | bool | 首次打开完成信息填写 | +| isPhoneRegisteredNotLost | bool | 手机号注册后未流失 | +| scanChannelId | int | 扫码渠道ID | +| scanChannelName | string | 扫码渠道名称 | +| telChannelId | int | 手机号注册渠道ID | +| telChannelName | string | 手机号注册渠道名称 | +| submitChannelId | int | 提交信息渠道ID | +| submitChannelName | string | 提交信息渠道名称 | + +--- + +### 2.2 患者详情 `GET ?r=patient/detail` + +**说明**: 根据用户信息表ID获取完整的用户+患者详情数据。 + +**请求参数**: + +| 参数名 | 类型 | 必填 | 说明 | +|---|---|---|---| +| id | int | 是 | 用户信息表ID | + +**响应示例**: +```json +{ + "code": 0, + "message": "success", + "data": { + "userId": "xxx", + "openId": "xxx", + "telephone": "138xxxx1234", + "isPhoneRegistered": true, + "isInfoSubmitted": true, + "isHeartRateTips": true, + "firstOpenTime": "2023-01-01 10:00:00", + "phoneRegisterTime": "2023-01-01 10:05:00", + "infoSubmitTime": "2023-01-01 10:10:00", + "nickName": "abcd12345678", + "avatar": "https://...", + "ageRange": 1, + "gender": 1, + "provinceName": "北京", + "cityName": "北京", + "diagnosisStatus": 2, + "diagnosisTime": "2023-06", + "surgeryStatus": 1, + "scanChannelId": 1, + "scanChannelName": "渠道A", + "telChannelId": 2, + "telChannelName": "渠道B", + "submitChannelId": 3, + "submitChannelName": "渠道C" + } +} +``` + +**响应字段说明**: 同1.4获取我的信息,额外包含渠道信息字段(scanChannelId/scanChannelName、telChannelId/telChannelName、submitChannelId/submitChannelName) + +--- + +### 2.3 渠道码列表 `GET ?r=?r=channel/list` + +**说明**: 获取所有有效渠道码列表。 + +**请求参数**: 无 + +**响应示例**: +```json +{ + "code": 0, + "message": "success", + "data": [ + { + "channelId": 1, + "channelName": "渠道A", + "channelDesc": "渠道A说明", + "miniCodeUrl": "https://xxx/minicode_1.png" + } + ] +} +``` + +**响应字段说明(每行)**: + +| 字段名 | 类型 | 说明 | +|---|---|---| +| channelId | int | 渠道ID | +| channelName | string | 渠道名称 | +| channelDesc | string | 渠道码说明 | +| miniCodeUrl | string | 小程序码图片URL | + +--- + +### 2.4 创建渠道码 `POST ?r=channel/create` + +**说明**: 创建新的渠道码。事务操作。 + +**请求参数**: + +| 参数名 | 类型 | 必填 | 说明 | +|---|---|---|---| +| channelName | string | 是 | 渠道名称 | +| channelDesc | string | 否 | 渠道码说明 | + +**响应示例**: +```json +{ + "code": 0, + "message": "success", + "data": { + "channelId": 1, + "channelName": "渠道A" + } +} +``` + +**响应字段说明**: + +| 字段名 | 类型 | 说明 | +|---|---|---| +| channelId | int | 新创建的渠道ID | +| channelName | string | 渠道名称 | + +--- + +### 2.5 更新渠道码 `POST ?r=channel/update` + +**说明**: 更新渠道码信息。事务操作。 + +**请求参数**: + +| 参数名 | 类型 | 必填 | 说明 | +|---|---|---|---| +| channelId | int | 是 | 渠道ID | +| channelName | string | 否 | 渠道名称 | +| channelDesc | string | 否 | 渠道码说明 | + +**响应示例**: +```json +{ + "code": 0, + "message": "success", + "data": { + "channelId": 1, + "channelName": "渠道A(已更新)" + } +} +``` + +**响应字段说明**: + +| 字段名 | 类型 | 说明 | +|---|---|---| +| channelId | int | 渠道ID | +| channelName | string | 更新后的渠道名称 | + +--- + +### 2.6 获取小程序渠道码 `GET ?r=channel/get-minicode` + +**说明**: 根据渠道ID获取或生成小程序码图片URL。 + +**请求参数**: + +| 参数名 | 类型 | 必填 | 说明 | +|---|---|---|---| +| channelId | int | 是 | 渠道ID | + +**响应示例**: +```json +{ + "code": 0, + "message": "success", + "data": { + "channelId": 1, + "channelName": "渠道A", + "miniCodeUrl": "https://xxx/minicode_1.png" + } +} +``` + +**响应字段说明**: + +| 字段名 | 类型 | 说明 | +|---|---|---| +| channelId | int | 渠道ID | +| channelName | string | 渠道名称 | +| miniCodeUrl | string | 小程序码图片URL | + +**业务逻辑**: +1. 若渠道已有小程序码URL(MiniCodeUrl),直接返回 +2. 若没有,调用微信接口生成小程序码(scene参数包含渠道ID) +3. 保存生成的MiniCodeUrl到渠道记录 + +--- + +### 2.7 渠道码统计 `GET ?r=channel/stat` + +**说明**: 根据日期范围和渠道ID获取渠道统计数据,从统计表获取。 + +**请求参数**: + +| 参数名 | 类型 | 必填 | 说明 | +|---|---|---|---| +| inviteDateBegin | string | 否 | 邀约日期开始(YYYY-MM-DD) | +| inviteDateEnd | string | 否 | 邀约日期结束(YYYY-MM-DD) | +| channelIds | string | 否 | 渠道ID筛选,逗号分隔(如"1,2,3") | + +**响应示例**: +```json +{ + "code": 0, + "message": "success", + "data": [ + { + "statDate": "2023-01-01", + "channelId": 1, + "channelName": "渠道A", + "openPatientCount": 100, + "phoneRegisteredCount": 80, + "infoSubmittedCount": 50, + "diagnosedPsvtCount": 30 + } + ] +} +``` + +**响应字段说明(每行)**: + +| 字段名 | 类型 | 说明 | +|---|---|---| +| statDate | string | 统计日期 | +| channelId | int | 渠道ID | +| channelName | string | 渠道名称 | +| openPatientCount | int | 邀约打开患者数 | +| phoneRegisteredCount | int | 邀约注册手机号患者数 | +| infoSubmittedCount | int | 邀约提交信息患者数 | +| diagnosedPsvtCount | int | 确诊PSVT患者数 | + +--- + +### 2.8 渠道码原始数据列表 `GET ?r=channel/raw-list` + +**说明**: 获取渠道邀约的原始记录列表,支持分页。通过JOIN t_psvt_user_info和t_psvt_patient_info获取用户属性和患者属性,不冗余存储。 + +**请求参数**: + +| 参数名 | 类型 | 必填 | 说明 | +|---|---|---|---| +| inviteDateBegin | string | 否 | 邀约日期开始(YYYY-MM-DD) | +| inviteDateEnd | string | 否 | 邀约日期结束(YYYY-MM-DD) | +| channelId | int | 否 | 渠道ID筛选 | +| inviteType | int | 否 | 邀约类型筛选:1-用户打开,2-手机号注册,3-信息提交 | +| page | int | 否 | 页码,默认1 | +| count | int | 否 | 每页数量,默认10 | + +**响应示例**: +```json +{ + "code": 0, + "message": "success", + "data": { + "page": 1, + "pages": 10, + "count": 100, + "list": [ + { + "id": 1, + "inviteTime": "2023-01-01 10:00:00", + "channelId": 1, + "channelName": "渠道A", + "inviteType": 1, + "userId": "xxx", + "patientId": 5, + "nickName": "abcd12345678", + "gender": 1, + "ageRange": 1, + "provinceName": "北京", + "cityName": "北京", + "diagnosisStatus": 2, + "diagnosisTime": "2023-06", + "surgeryStatus": 1, + "telephone": "138xxxx1234", + "firstOpenTime": "2023-01-01 10:00:00", + "phoneRegisterTime": "2023-01-01 10:05:00", + "infoSubmitTime": "2023-01-01 10:10:00", + "isFirstOpenPhoneRegistered": true, + "isFirstOpenInfoSubmitted": true, + "isPhoneRegisteredNotLost": true, + "scanChannelId": 1, + "scanChannelName": "渠道A", + "telChannelId": 2, + "telChannelName": "渠道B", + "submitChannelId": 3, + "submitChannelName": "渠道C" + } + ] + } +} +``` + +**响应字段说明(data层级)**: + +| 字段名 | 类型 | 说明 | +|---|---|---| +| page | int | 当前页码 | +| pages | int | 总页数 | +| count | int | 总记录数 | +| list | array | 原始数据列表 | + +**list行字段说明**: + +| 字段名 | 类型 | 说明 | +|---|---|---| +| id | int | 记录ID | +| inviteTime | string | 邀约时间 | +| channelId | int | 渠道ID | +| channelName | string | 渠道名称 | +| inviteType | int | 邀约类型 | +| userId | string | 用户ID | +| patientId | int | 患者ID | +| nickName | string | 昵称 | +| gender | int | 性别 | +| ageRange | int | 年龄段 | +| provinceName | string | 省份名称 | +| cityName | string | 市名称 | +| diagnosisStatus | int | 确诊状态 | +| diagnosisTime | string | 确诊时间 | +| surgeryStatus | int | 手术状态 | +| telephone | string | 手机号 | +| firstOpenTime | string | 首次打开时间 | +| phoneRegisterTime | string | 手机号注册时间 | +| infoSubmitTime | string | 信息提交时间 | +| isFirstOpenPhoneRegistered | bool | 首次打开完成手机号注册 | +| isFirstOpenInfoSubmitted | bool | 首次打开完成信息填写 | +| isPhoneRegisteredNotLost | bool | 手机号注册后未流失 | +| scanChannelId | int | 扫码渠道ID | +| scanChannelName | string | 扫码渠道名称 | +| telChannelId | int | 手机号注册渠道ID | +| telChannelName | string | 手机号注册渠道名称 | +| submitChannelId | int | 提交信息渠道ID | +| submitChannelName | string | 提交信息渠道名称 | + +--- + +### 2.9 获取基础数据列表 `GET ?r=patient/base-data` + +**说明**: 返回性别、年龄段、确诊状态、手术状态等枚举数据,供后台管理端渲染下拉选项。 + +**请求参数**: 无 + +**响应示例**: +```json +{ + "code": 0, + "message": "success", + "data": { + "genderList": [{"1": "男"}, {"2": "女"}], + "ageRangeList": [{"1": "18~28岁"}, {"2": "29~40岁"}, {"3": "41~50岁"}, {"4": "50岁以上"}], + "diagnosisStatusList": [{"1": "疑似PSVT正在了解中"}, {"2": "已确诊PSVT"}, {"3": "心悸/心跳过快 尚未就诊"}, {"4": "亲友相关 想了解更多"}], + "surgeryStatusList": [{"1": "已接收射频消融/相关手术"}, {"2": "尚未接收手术"}, {"3": "正在评估"}] + } +} +``` + +**响应字段说明**: + +| 字段名 | 类型 | 说明 | +|---|---|---| +| genderList | array | 性别列表,每项为 {value: "label"} | +| ageRangeList | array | 年龄段列表,每项为 {value: "label"} | +| diagnosisStatusList | array | 确诊状态列表,每项为 {value: "label"} | +| surgeryStatusList | array | 手术状态列表,每项为 {value: "label"} | + +--- \ No newline at end of file diff --git a/project.config.json b/project.config.json index d105a55..c0c8295 100644 --- a/project.config.json +++ b/project.config.json @@ -66,7 +66,7 @@ ], "include": [] }, - "appid": "wxfc95e2961d481f58", + "appid": "wx903aa29742dad363", "scripts": { "beforeCompile": "pnpm run beforeCompile", "beforePreview": "pnpm run beforeCompile", diff --git a/project.private.config.json b/project.private.config.json index 8f51ac2..5354cfd 100644 --- a/project.private.config.json +++ b/project.private.config.json @@ -23,13 +23,41 @@ "miniprogram": { "list": [ { - "name": "我的帖子", - "pathName": "pages/myWall/index", + "name": "隐私协议", + "pathName": "doc/pages/doc/index", "query": "", "scene": null, "launchMode": "default" }, { + "name": "个人信息", + "pathName": "pages/userInfo/index", + "query": "", + "launchMode": "default", + "scene": null + }, + { + "name": "我的收藏", + "pathName": "pages/myCollection/index", + "query": "", + "launchMode": "default", + "scene": null + }, + { + "name": "我的评论", + "pathName": "pages/myComment/index", + "query": "", + "launchMode": "default", + "scene": null + }, + { + "name": "我的帖子", + "pathName": "pages/myWall/index", + "query": "", + "launchMode": "default", + "scene": null + }, + { "name": "我的", "pathName": "pages/my/index", "query": "", diff --git a/src/app.json b/src/app.json index 8ba1b92..a6c1fbd 100644 --- a/src/app.json +++ b/src/app.json @@ -21,12 +21,22 @@ "pages/videoList/index", "pages/videoDetail/index", "pages/articleDetail/index", - "pages/myWall/index" + "pages/myWall/index", + "pages/myComment/index", + "pages/myCollection/index", + "pages/userInfo/index" ], "subPackages": [ { "root": "doc", - "pages": ["pages/doc1/index", "pages/doc2/index", "pages/doc3/index", "pages/doc4/index", "pages/doc5/index"] + "pages": [ + "pages/doc/index", + "pages/doc1/index", + "pages/doc2/index", + "pages/doc3/index", + "pages/doc4/index", + "pages/doc5/index" + ] } ], "tabBar": { diff --git a/src/app.ts b/src/app.ts index 31faf44..bcecd06 100644 --- a/src/app.ts +++ b/src/app.ts @@ -25,15 +25,15 @@ App({ globalData: { // dev // appid:wx903aa29742dad363 - // url: 'https://m.wtx.hbraas.com', - // upFileUrl: 'https://m.wtx.hbraas.com/', - // imageUrl: 'https://m.wtx.hbraas.com/GeneB/', + url: 'https://m.psvt.hbraas.com', + upFileUrl: 'https://m.psvt.hbraas.com/', + imageUrl: 'https://m.psvt.hbraas.com/psvt/', // pro // appid:wxfc95e2961d481f58 - url: 'https://m.hbgene.hbsaas.com', - upFileUrl: 'https://m.hbgene.hbsaas.com/', - imageUrl: 'https://m.hbgene.hbsaas.com/GeneB/', + // url: 'https://m.hbgene.hbsaas.com', + // upFileUrl: 'https://m.hbgene.hbsaas.com/', + // imageUrl: 'https://m.hbgene.hbsaas.com/GeneB/', Timestamp: new Date().getTime(), @@ -71,7 +71,7 @@ App({ success: (res) => { wx.ajax({ method: 'GET', - url: '?r=wtx/user/init-login', + url: '?r=psvt/user/init-login', data: { code: res.code, }, diff --git a/src/doc/pages/doc/index.json b/src/doc/pages/doc/index.json new file mode 100644 index 0000000..cde973f --- /dev/null +++ b/src/doc/pages/doc/index.json @@ -0,0 +1,10 @@ +{ + "navigationStyle": "custom", + "navigationBarTitleText": "隐私协议", + "usingComponents": { + "popup": "/components/popup/index", + "navbar": "/components/navbar/index", + "uploadFile": "/components/uploadFile/index", + "van-popup": "@vant/weapp/popup/index" + } +} diff --git a/src/doc/pages/doc/index.scss b/src/doc/pages/doc/index.scss new file mode 100644 index 0000000..ea056aa --- /dev/null +++ b/src/doc/pages/doc/index.scss @@ -0,0 +1,46 @@ +page { + background-color: #f7fafc; +} + +.page-title { + font-size: 36rpx; + color: rgba(51, 51, 51, 1); +} + +.page { + padding-bottom: 260rpx; + .list { + padding: 40rpx; + + .info-card { + padding: 32rpx; + background: rgba(255, 255, 255, 0.7); + border: 1rpx solid #fff; + border-radius: 32rpx; + } + + .info-row { + display: flex; + align-items: start; + justify-content: space-between; + padding: 24rpx 0; + border-bottom: 1rpx solid #f1f5f9; + + &:last-child { + border-bottom: none; + } + + .info-label { + font-size: 32rpx; + line-height: 48rpx; + color: #1e293b; + } + + .info-arrow { + margin-top: 8rpx; + color: #64748b; + margin-left: 8rpx; + } + } + } +} diff --git a/src/doc/pages/doc/index.ts b/src/doc/pages/doc/index.ts new file mode 100644 index 0000000..154aa29 --- /dev/null +++ b/src/doc/pages/doc/index.ts @@ -0,0 +1,103 @@ +const app = getApp() + +Page({ + data: { + popupShow: false, + popupType: '', + popupParams: { + position: 'bottom', + } as any, + + topicShow: false, + replayShow: true, + + fileList: [] as any[], + }, + onLoad() { + app.waitLogin({ type: 0 }).then(() => {}) + }, + handlePopupOk() { + const { popupType } = this.data + if (popupType === 'argument') { + app.mpBehavior({ PageName: 'BTN_PATIENTLOG' }) + wx.ajax({ + method: 'POST', + url: '?r=wtx/user/agree-guest-privacy', + data: { + WorkerId: app.globalData.scene?.workerId || '', + }, + }).then(() => { + this.setData({ + popupShow: false, + popupType: '', + popupParams: {}, + }) + const waitBindDoctorId = app.globalData.waitBindDoctorId + if (waitBindDoctorId) { + this.handleBindDoctor(waitBindDoctorId) + } + }) + } + if (popupType === 'conformBindDoctorConform') { + this.setData({ + popupShow: false, + }) + wx.ajax({ + method: 'POST', + url: '?r=wtx/account/wait-bind-doctor', + data: { + doctorId: app.globalData.waitBindDoctorId, + }, + }).then(() => { + wx.navigateTo({ + url: `/patient/pages/login/index`, + }) + }) + } + }, + handlePopupCancel() { + const { popupType } = this.data + if (popupType === 'argument') { + wx.exitMiniProgram() + } + if (popupType === 'conformBindDoctorConform') { + this.setData({ + popupShow: false, + }) + wx.ajax({ + method: 'POST', + url: '?r=wtx/account/wait-bind-doctor', + data: { + doctorId: app.globalData.waitBindDoctorId, + }, + }).then(() => { + app.globalData.waitBindDoctorId = '' + }) + } + }, + handleWechatWork() { + wx.navigateTo({ + url: '/pages/wechatWork/index', + }) + }, + handleSetData(e) { + const { fileList } = this.data + this.setData({ + fileList: [...fileList, ...e.detail], + }) + }, + handleDeleteFile(e) { + const { index } = e.detail + const { fileList } = this.data + this.setData({ + fileList: fileList.filter((_, i) => i !== index), + }) + }, + topicClose() { + this.setData({ + topicShow: false, + }) + }, +}) + +export {} diff --git a/src/doc/pages/doc/index.wxml b/src/doc/pages/doc/index.wxml new file mode 100644 index 0000000..a8ba1cd --- /dev/null +++ b/src/doc/pages/doc/index.wxml @@ -0,0 +1,32 @@ + + + + 个人信息 + + + + + + + + 《隐私政策》 + + + + 《用户协议》 + + + + 《法律声明》 + + + + 《健康敏感信息处理与AI服务授权告知书》 + + + + + diff --git a/src/images/icon40.png b/src/images/icon40.png new file mode 100644 index 0000000000000000000000000000000000000000..6806cd159a284332ac4bfe13c516a3e969061603 GIT binary patch literal 668 zcmV;N0%QG&P))yf5QSg2OsYsWI)Y9>DJMWaL5dB8Rg@DD zE`aQC0L%%JtX%AJ1Dq4!zy)*!ZwQ-cnr;~;Kjm1K5=r^0B#%nt={KXEnKy(DiL;Xs zgPj8r#DF9Kh58#V-_imkxfXJAIEQl=^YQz9lXj`9Li~A}2!ae^LF+)LR21VXArA^D zd(1l{A^CtuAPy6jD;09Mz@`G?Y#K?x-?bRwDG>WKZn$bRsP*6#BB+z#YedjZ@RLx2 z?H{cLza!#m_kT{Xf1wH2dT@gfIoi&ASi6-&Uo+c_o9jLFt}eN53cB#Gr6BS3lbHefNn;k%WQvWm!sk<8o+8^c|Lx#(AH+?962>(Qcgp1#TXq! zg_JS9BYJiG?TbDfp##LpR-40000wTQn4Whe#TK~h-O-jN_CNL7ez{-n$j1Rdo;>k{ zkhWDnJ@0{LijYD$&a2Fx*kyOGc8Km|JW#Do92meg`4|z}I>*nlcH zKRQT+7$U$q40p7Q3)P*qnjXdX&`k>6@#yuz9~K}P9FJAq{pm^TDBdsK9=g*~KX_xK zEjDc>Iv)pPplK`7!5IThTgiU)c&LM$*FucA;3Nl)HYwx$J@WS&wb_(JR<{vQcYD?& zqw9=-y0}H%x>lly<56le#yC+cQN-~?uHZ&EgE}qXwsBHm7H~pfR&Z;9S;DOVvxegd zwHY?aZI*B=Kz0_h0t0*7xK$v8u!C*mAKtEP$rJ>Jr`7U_vWMfj%RRE^?>k l8ySvz@Q7%>#d-c!egWMi1upB5@U{Q|002ovPDHLkV1fhb1VjJ; literal 0 HcmV?d00001 diff --git a/src/images/icon42.png b/src/images/icon42.png new file mode 100644 index 0000000000000000000000000000000000000000..4bf4268a1ba9470839bc2b6e987704210e70c9ea GIT binary patch literal 626 zcmV-&0*(ENP)#$0YUgSA*6fq*L0_+XMhQZ;7GW$TSycN7=WBW zMc$PwE)%)_6$zo%B??DeC2Bc45nBOlZ zP@&0z1PaWZS+JhpJ%Z5z0l4d%WuJqPGQNts?mcYe_fGXcNBB#aOVzl1+@8)4$*`mr z>SjJF;*0kD^=)zOSw_$BKv*aS>Z4w3&lRiUQ+#vzo2~U7TwD2Eg)iRU16$K+u7eHP zJoL6S%ZJXFgVv0qYJ7cW>&r>w1?~dfAkaalM70WKy1+yPy*n>0EY{LYtwUUA4&jTO z_&+(AE^v9-OG&Yz_O_IogQ)^#B^sMRQ+>4#v49BSiL8dCf8PnmERZm^FsES_$m0;m z(zI$HVpi6*D+~R^*|fE_7f9qypbOJ|NOUM9Mhr7a)4KH?WS=2+xR$j*V)iGHF$>KC zzS}y9QNwJkwcZ+5247P5g+4Ob5^=yk?`xFtw6YecFBqEEALDXK4<%SZGm?YjXclz& z8Y0Ba1g1`|6!n)Xh7VCazbWI8%)iYHi!sEBz5T4mPhaU;~(jX!V9#lva;EwV_fg&oG z?r?=f<+!Feodh*@LqUVxL1!e8qA1e2Oz9M<{USw*l*Sk5&pE%H$;|BT+kNL;a&@xO zdv9m=+xcd9zMTi~wl`cf!K2{-;KNFK^7N(vO^xFl^{cV#f@$RO1I6O_ze8A-&=%wQ zmUK78S_MP|W{%h+v3GFv|9-&!uqpPB(i^H7u?m#{;Q-i==Y#AJHly#?9rpi{MFTVs zb0Ch)&Iut8#8|(8Q-tz{ff^gXjlbSJxIoCiTpN<334($dx=}?3#W{-D>G>M&98R5@{>9mlsHvDd*y9`d zcw{28wJ$FY^ImtcY+t;*&3r_j)!!~T9!xq6}qj)%K zMMJ(hu%x#NY=wXnZ6)v|%9Sw?6|0I&oigXW;CIgq5REbcs>5-jiSf|^UF%8CnDskJX|bfAI~go0dwWSU>njoJZ3uo?($w;zm_nOGSB4i z0aX_meqH4+4C6q`K>Qwyq%V*yB-Hj`qpB{gz(k_`EL`H`F_ zTtth42`8eT@yGw%-+hy>r3ke>*!ZOCV{c11uD6R3r^J5e+1c6d=Lgg2GJcjOEQ#ea lyyW_;r_Y}3FH7|9w3i() + +Page({ + data: { + popupShow: false, + popupType: '', + popupParams: { + position: 'bottom', + } as any, + + topicShow: false, + replayShow: true, + + fileList: [] as any[], + + tab: 1, + offsetTop: 0, + }, + onLoad() { + app.waitLogin({ type: 0 }).then(() => {}) + }, + onReady() { + const { statusBarHeight } = wx.getSystemInfoSync() + const navBarHeight = 44 + this.setData({ offsetTop: statusBarHeight + navBarHeight }) + }, + handlePopupOk() { + const { popupType } = this.data + if (popupType === 'argument') { + app.mpBehavior({ PageName: 'BTN_PATIENTLOG' }) + wx.ajax({ + method: 'POST', + url: '?r=wtx/user/agree-guest-privacy', + data: { + WorkerId: app.globalData.scene?.workerId || '', + }, + }).then(() => { + this.setData({ + popupShow: false, + popupType: '', + popupParams: {}, + }) + const waitBindDoctorId = app.globalData.waitBindDoctorId + if (waitBindDoctorId) { + this.handleBindDoctor(waitBindDoctorId) + } + }) + } + if (popupType === 'conformBindDoctorConform') { + this.setData({ + popupShow: false, + }) + wx.ajax({ + method: 'POST', + url: '?r=wtx/account/wait-bind-doctor', + data: { + doctorId: app.globalData.waitBindDoctorId, + }, + }).then(() => { + wx.navigateTo({ + url: `/patient/pages/login/index`, + }) + }) + } + }, + handlePopupCancel() { + const { popupType } = this.data + if (popupType === 'argument') { + wx.exitMiniProgram() + } + if (popupType === 'conformBindDoctorConform') { + this.setData({ + popupShow: false, + }) + wx.ajax({ + method: 'POST', + url: '?r=wtx/account/wait-bind-doctor', + data: { + doctorId: app.globalData.waitBindDoctorId, + }, + }).then(() => { + app.globalData.waitBindDoctorId = '' + }) + } + }, + handleWechatWork() { + wx.navigateTo({ + url: '/pages/wechatWork/index', + }) + }, + handleSetData(e) { + const { fileList } = this.data + this.setData({ + fileList: [...fileList, ...e.detail], + }) + }, + handleDeleteFile(e) { + const { index } = e.detail + const { fileList } = this.data + this.setData({ + fileList: fileList.filter((_, i) => i !== index), + }) + }, + topicClose() { + this.setData({ + topicShow: false, + }) + }, +}) + +export {} diff --git a/src/pages/myCollection/index.wxml b/src/pages/myCollection/index.wxml new file mode 100644 index 0000000..3569dd5 --- /dev/null +++ b/src/pages/myCollection/index.wxml @@ -0,0 +1,74 @@ + + + + 我的收藏 + + + + + + + + + + + + + + + + + + + + 12 + + + + 12 + + + + PSVT长期管理专家分享:日常忌口、 PSVT长期管理专家分享:日常忌口、 + + + + + + + + + + + + 视频 + + + + 什么是 PSVT?3 分钟带您了 解阵发性室上性心动过速 + + + + 取消收藏 + + + + + + + + diff --git a/src/pages/myComment/index.json b/src/pages/myComment/index.json new file mode 100644 index 0000000..d3c67a1 --- /dev/null +++ b/src/pages/myComment/index.json @@ -0,0 +1,10 @@ +{ + "navigationStyle": "custom", + "navigationBarTitleText": "我的评论", + "usingComponents": { + "popup": "/components/popup/index", + "navbar": "/components/navbar/index", + "uploadFile": "/components/uploadFile/index", + "van-popup": "@vant/weapp/popup/index" + } +} diff --git a/src/pages/myComment/index.scss b/src/pages/myComment/index.scss new file mode 100644 index 0000000..2732b92 --- /dev/null +++ b/src/pages/myComment/index.scss @@ -0,0 +1,155 @@ +page { + background-color: #f7fafc; +} + +.page-title { + font-size: 36rpx; + color: rgba(51, 51, 51, 1); +} + +.page { + padding-bottom: 260rpx; + .list { + padding: 0 30rpx; + .list-card { + margin-top: 32rpx; + padding: 32rpx; + background: #fff; + border-radius: 32rpx; + display: flex; + flex-direction: column; + gap: 24rpx; + + .card-header { + display: flex; + justify-content: space-between; + align-items: center; + + .status-tag { + padding: 8rpx 16rpx; + border-radius: 12rpx; + font-size: 28rpx; + line-height: 36rpx; + text-align: center; + &.status1 { + color: #2f82a9; + background: rgba(47, 130, 169, 0.08); + } + &.status2 { + color: rgba(45, 190, 141, 1); + background: rgba(45, 190, 141, 0.08); + } + &.status3 { + color: rgba(186, 26, 26, 1); + background: rgba(186, 26, 26, 0.08); + } + } + + .time { + font-size: 24rpx; + line-height: 32rpx; + color: #94a3b8; + } + } + + .card-content { + font-size: 32rpx; + line-height: 52rpx; + font-weight: 500; + color: #1e293b; + } + + .card-reference { + padding: 24rpx; + background: #f7fafc; + border-radius: 24rpx; + display: flex; + flex-direction: column; + gap: 16rpx; + + .reference-tags { + display: flex; + gap: 16rpx; + + .tag { + font-size: 24rpx; + line-height: 32rpx; + color: #2f82a9; + } + } + + .reference-post { + display: flex; + gap: 24rpx; + + .post-thumbnail { + width: 96rpx; + height: 96rpx; + background: #e2e8f0; + border-radius: 16rpx; + } + + .post-desc { + width: 458rpx; + font-size: 28rpx; + line-height: 40rpx; + color: #64748b; + } + } + } + + .card-overlay { + padding: 16rpx 24rpx; + background: rgba(47, 130, 169, 0.08); + border-radius: 16rpx; + line-height: 32rpx; + + .icon { + margin-right: 16rpx; + width: 32rpx; + height: 32rpx; + vertical-align: -4rpx; + } + + .overlay-text { + display: inline; + font-size: 28rpx; + color: #2f82a9; + } + } + + .rejected { + padding: 16rpx 24rpx; + border-radius: 16rpx; + background: rgba(186, 26, 26, 0.08); + box-sizing: border-box; + font-size: 28rpx; + color: rgba(186, 26, 26, 1); + line-height: 32rpx; + .icon { + display: inline-block; + flex-shrink: 0; + margin-right: 16rpx; + width: 32rpx; + height: 32rpx; + vertical-align: -4rpx; + } + .blod { + display: inline-block; + font-weight: bold; + } + } + + .card-footer { + display: flex; + justify-content: flex-end; + + .delete-btn { + font-size: 28rpx; + line-height: 40rpx; + color: #94a3b8; + } + } + } + } +} diff --git a/src/pages/myComment/index.ts b/src/pages/myComment/index.ts new file mode 100644 index 0000000..154aa29 --- /dev/null +++ b/src/pages/myComment/index.ts @@ -0,0 +1,103 @@ +const app = getApp() + +Page({ + data: { + popupShow: false, + popupType: '', + popupParams: { + position: 'bottom', + } as any, + + topicShow: false, + replayShow: true, + + fileList: [] as any[], + }, + onLoad() { + app.waitLogin({ type: 0 }).then(() => {}) + }, + handlePopupOk() { + const { popupType } = this.data + if (popupType === 'argument') { + app.mpBehavior({ PageName: 'BTN_PATIENTLOG' }) + wx.ajax({ + method: 'POST', + url: '?r=wtx/user/agree-guest-privacy', + data: { + WorkerId: app.globalData.scene?.workerId || '', + }, + }).then(() => { + this.setData({ + popupShow: false, + popupType: '', + popupParams: {}, + }) + const waitBindDoctorId = app.globalData.waitBindDoctorId + if (waitBindDoctorId) { + this.handleBindDoctor(waitBindDoctorId) + } + }) + } + if (popupType === 'conformBindDoctorConform') { + this.setData({ + popupShow: false, + }) + wx.ajax({ + method: 'POST', + url: '?r=wtx/account/wait-bind-doctor', + data: { + doctorId: app.globalData.waitBindDoctorId, + }, + }).then(() => { + wx.navigateTo({ + url: `/patient/pages/login/index`, + }) + }) + } + }, + handlePopupCancel() { + const { popupType } = this.data + if (popupType === 'argument') { + wx.exitMiniProgram() + } + if (popupType === 'conformBindDoctorConform') { + this.setData({ + popupShow: false, + }) + wx.ajax({ + method: 'POST', + url: '?r=wtx/account/wait-bind-doctor', + data: { + doctorId: app.globalData.waitBindDoctorId, + }, + }).then(() => { + app.globalData.waitBindDoctorId = '' + }) + } + }, + handleWechatWork() { + wx.navigateTo({ + url: '/pages/wechatWork/index', + }) + }, + handleSetData(e) { + const { fileList } = this.data + this.setData({ + fileList: [...fileList, ...e.detail], + }) + }, + handleDeleteFile(e) { + const { index } = e.detail + const { fileList } = this.data + this.setData({ + fileList: fileList.filter((_, i) => i !== index), + }) + }, + topicClose() { + this.setData({ + topicShow: false, + }) + }, +}) + +export {} diff --git a/src/pages/myComment/index.wxml b/src/pages/myComment/index.wxml new file mode 100644 index 0000000..7fd0133 --- /dev/null +++ b/src/pages/myComment/index.wxml @@ -0,0 +1,45 @@ + + + + 我的评论 + + + + + + + + + 待审核 + 2026-01-01 13:00:09 + + 记录发作时间真的很重要,尤其是频率和持续时长 + + + # 我的心悸经历 + # PSVT急救常识 + + + + 今天把近期的状态、复诊资料和生活节奏整理了一下,也想记录一下最 + + + + + 评论正在审核中,预计1-2个工作日内完成审核。 + + + + 驳回原因: + 语言不当 语言不当 语言不当 语言不当 语言不当 语言不当 语言不当 语言不当 语言不当 语言不当 语言不当 语言不当 + 语言不当 语言不当 语言不当 语言不当 语言不当 语言不当 语言不当 语言不当 语言不当 + + + 删除 + + + + diff --git a/src/pages/myWall/index.scss b/src/pages/myWall/index.scss index 70e114d..d833c98 100644 --- a/src/pages/myWall/index.scss +++ b/src/pages/myWall/index.scss @@ -112,7 +112,7 @@ page { margin-right: 16rpx; width: 32rpx; height: 32rpx; - vertical-align: middle; + vertical-align: -4rpx; } .blod { display: inline-block; diff --git a/src/pages/userInfo/index.json b/src/pages/userInfo/index.json new file mode 100644 index 0000000..d3c67a1 --- /dev/null +++ b/src/pages/userInfo/index.json @@ -0,0 +1,10 @@ +{ + "navigationStyle": "custom", + "navigationBarTitleText": "我的评论", + "usingComponents": { + "popup": "/components/popup/index", + "navbar": "/components/navbar/index", + "uploadFile": "/components/uploadFile/index", + "van-popup": "@vant/weapp/popup/index" + } +} diff --git a/src/pages/userInfo/index.scss b/src/pages/userInfo/index.scss new file mode 100644 index 0000000..822f782 --- /dev/null +++ b/src/pages/userInfo/index.scss @@ -0,0 +1,92 @@ +page { + background-color: #f7fafc; +} + +.page-title { + font-size: 36rpx; + color: rgba(51, 51, 51, 1); +} + +.page { + padding-bottom: 260rpx; + .list { + padding: 40rpx; + + .info-card { + padding: 32rpx; + background: rgba(255, 255, 255, 0.7); + border: 1rpx solid #fff; + border-radius: 32rpx; + } + + .info-row { + display: flex; + align-items: center; + justify-content: space-between; + padding: 24rpx 0; + border-bottom: 1rpx solid #f1f5f9; + + &:last-child { + border-bottom: none; + } + + .info-label { + font-size: 32rpx; + line-height: 48rpx; + color: #1e293b; + } + + .info-value { + flex: 1; + font-size: 32rpx; + line-height: 48rpx; + color: #64748b; + text-align: right; + } + + .info-arrow { + color: #64748b; + margin-left: 8rpx; + } + + .avatar-wrap { + width: 112rpx; + height: 112rpx; + border-radius: 50%; + background: #d9d9d9; + overflow: hidden; + + .avatar { + width: 100%; + height: 100%; + } + } + } + + .btn-logout { + margin-top: 32rpx; + height: 96rpx; + display: flex; + align-items: center; + justify-content: center; + background: #fff; + border-radius: 54rpx; + font-size: 32rpx; + line-height: 48rpx; + color: #1e293b; + } + + .btn-cancel { + margin-top: 24rpx; + height: 96rpx; + display: flex; + align-items: center; + justify-content: center; + background: #fff; + border-radius: 54rpx; + font-size: 32rpx; + line-height: 48rpx; + color: #1e293b; + } + } +} diff --git a/src/pages/userInfo/index.ts b/src/pages/userInfo/index.ts new file mode 100644 index 0000000..154aa29 --- /dev/null +++ b/src/pages/userInfo/index.ts @@ -0,0 +1,103 @@ +const app = getApp() + +Page({ + data: { + popupShow: false, + popupType: '', + popupParams: { + position: 'bottom', + } as any, + + topicShow: false, + replayShow: true, + + fileList: [] as any[], + }, + onLoad() { + app.waitLogin({ type: 0 }).then(() => {}) + }, + handlePopupOk() { + const { popupType } = this.data + if (popupType === 'argument') { + app.mpBehavior({ PageName: 'BTN_PATIENTLOG' }) + wx.ajax({ + method: 'POST', + url: '?r=wtx/user/agree-guest-privacy', + data: { + WorkerId: app.globalData.scene?.workerId || '', + }, + }).then(() => { + this.setData({ + popupShow: false, + popupType: '', + popupParams: {}, + }) + const waitBindDoctorId = app.globalData.waitBindDoctorId + if (waitBindDoctorId) { + this.handleBindDoctor(waitBindDoctorId) + } + }) + } + if (popupType === 'conformBindDoctorConform') { + this.setData({ + popupShow: false, + }) + wx.ajax({ + method: 'POST', + url: '?r=wtx/account/wait-bind-doctor', + data: { + doctorId: app.globalData.waitBindDoctorId, + }, + }).then(() => { + wx.navigateTo({ + url: `/patient/pages/login/index`, + }) + }) + } + }, + handlePopupCancel() { + const { popupType } = this.data + if (popupType === 'argument') { + wx.exitMiniProgram() + } + if (popupType === 'conformBindDoctorConform') { + this.setData({ + popupShow: false, + }) + wx.ajax({ + method: 'POST', + url: '?r=wtx/account/wait-bind-doctor', + data: { + doctorId: app.globalData.waitBindDoctorId, + }, + }).then(() => { + app.globalData.waitBindDoctorId = '' + }) + } + }, + handleWechatWork() { + wx.navigateTo({ + url: '/pages/wechatWork/index', + }) + }, + handleSetData(e) { + const { fileList } = this.data + this.setData({ + fileList: [...fileList, ...e.detail], + }) + }, + handleDeleteFile(e) { + const { index } = e.detail + const { fileList } = this.data + this.setData({ + fileList: fileList.filter((_, i) => i !== index), + }) + }, + topicClose() { + this.setData({ + topicShow: false, + }) + }, +}) + +export {} diff --git a/src/pages/userInfo/index.wxml b/src/pages/userInfo/index.wxml new file mode 100644 index 0000000..1ffc972 --- /dev/null +++ b/src/pages/userInfo/index.wxml @@ -0,0 +1,60 @@ + + + + 个人信息 + + + + + + + + 头像 + + + + + + 昵称 + ZSX0092 + + + 手机号 + 153****0000 + + + + 年龄段 + 18-35岁 + + + + 性别 + + + + + 所在地区 + 北京/北京市 + + + + 我的健康状态 + 已确诊 + + + 确诊时间 + 2024-08-01 + + + 是否接受过手术治疗 + 正在评估 + + + 退出登录 + 注销 + + diff --git a/src/pages/wall/index.wxml b/src/pages/wall/index.wxml index 9e4dd12..de4f953 100644 --- a/src/pages/wall/index.wxml +++ b/src/pages/wall/index.wxml @@ -78,7 +78,6 @@ - diff --git a/src/pages/wallDetail/index.json b/src/pages/wallDetail/index.json index e3ceeb9..13d61b0 100644 --- a/src/pages/wallDetail/index.json +++ b/src/pages/wallDetail/index.json @@ -2,6 +2,8 @@ "navigationStyle": "custom", "usingComponents": { "popup": "/components/popup/index", - "navbar": "/components/navbar/index" + "navbar": "/components/navbar/index", + "van-action-sheet": "@vant/weapp/action-sheet/index", + "van-popup": "@vant/weapp/popup/index" } } diff --git a/src/pages/wallDetail/index.scss b/src/pages/wallDetail/index.scss index b33ff4e..2d526fa 100644 --- a/src/pages/wallDetail/index.scss +++ b/src/pages/wallDetail/index.scss @@ -234,21 +234,35 @@ page { .comment { margin-right: 12rpx; flex: 1; - min-height: 96rpx; + height: 96rpx; border-radius: 24rpx; - border: 2rpx solid #f1f5f9; + border: 1px solid #f1f5f9; + padding: 0 32rpx; background: #f9fafb; box-sizing: border-box; - .txa { - padding: 32rpx; - width: 100%; - min-height: 100%; - font-size: 28rpx; - color: rgba(30, 41, 59, 1); - box-sizing: border-box; + display: flex; + align-items: center; + font-size: 28rpx; + color: rgba(148, 163, 184, 1); + } + .auth { + flex: 1; + display: flex; + align-items: center; + gap: 22rpx; + .icon { + width: 35rpx; } - .txa-place { - color: rgba(148, 163, 184, 1); + .wrap { + .status { + font-size: 28rpx; + color: rgba(71, 85, 105, 1); + } + .content { + margin-top: 8rpx; + font-size: 24rpx; + color: rgba(47, 130, 169, 1); + } } } .op-wrap { @@ -417,3 +431,35 @@ page { } } } + +.action-popup { + background-color: #fff; + padding: 16rpx 0 0; + .a-list { + border-bottom: 8rpx solid rgba(247, 250, 252, 1); + .row { + margin: 0 30rpx; + border-bottom: 1px solid rgba(241, 245, 249, 1); + padding: 32rpx; + display: flex; + align-items: center; + justify-content: center; + gap: 24rpx; + font-size: 32rpx; + color: rgba(30, 41, 59, 1); + &:last-of-type { + border: none; + } + .icon { + width: 40rpx; + height: 40rpx; + } + } + } + .a-close{ + padding: 32rpx; + font-size: 32rpx; + line-height: 48rpx; + text-align: center; + } +} diff --git a/src/pages/wallDetail/index.ts b/src/pages/wallDetail/index.ts index 2d8f06f..2276271 100644 --- a/src/pages/wallDetail/index.ts +++ b/src/pages/wallDetail/index.ts @@ -10,6 +10,7 @@ Page({ topicShow: false, replayShow: false, + actionShow: false, }, onLoad() { app.waitLogin({ type: 0 }).then(() => {}) diff --git a/src/pages/wallDetail/index.wxml b/src/pages/wallDetail/index.wxml index f230305..68b452e 100644 --- a/src/pages/wallDetail/index.wxml +++ b/src/pages/wallDetail/index.wxml @@ -101,9 +101,27 @@ - - + + + + 公开可见 + + 编辑和设置权限 + + + + + + + + 仅自己可见 + + 编辑和设置权限 + + + + 我要评论 @@ -157,3 +175,19 @@ + + + + + + + 编辑 + + + + 删除 + + + 取消 + + diff --git a/typings/index.d.ts b/typings/index.d.ts index d718459..cce2c5c 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -36,10 +36,9 @@ interface IAppOption { waitBindDoctorId: string loginState: string initLoginInfo: Partial<{ + loginState: string isLogin: 0 | 1 isReg: 0 | 1 - loginType: 1 | 2 - guestPrivacyAgree: boolean }> [propName: string]: any