Browse Source

bug 处理

master
kola-web 6 days ago
parent
commit
4df82bb6bc
  1. 125
      .trae/documents/component-reuse-optimization-plan.md
  2. 11
      project.private.config.json
  3. 13
      src/doctor/pages/articleList/index.wxml
  4. 33
      src/doctor/pages/patientList/index.wxml
  5. 65
      src/pages/index/index.ts
  6. 66
      src/pages/start/index.ts
  7. 97
      src/privacy/pages/policy/index.ts
  8. 4
      src/privacy/pages/policy/index.wxml

125
.trae/documents/component-reuse-optimization-plan.md

@ -0,0 +1,125 @@ @@ -0,0 +1,125 @@
# 组件复用性分析与优化计划
## 项目概述
对药品查询微信小程序进行全面的组件复用性分析与优化,建立标准化的组件体系,提升代码质量和开发效率。
## 执行步骤
### 第一阶段:组件梳理与评估(预计2-3小时)
#### 1.1 组件盘点
- [ ] 扫描项目所有页面和组件目录
- [ ] 识别所有自定义组件(components目录)
- [ ] 识别页面内重复使用的UI片段
- [ ] 识别可复用的业务逻辑模块
#### 1.2 复用价值评估
建立评估矩阵,从以下维度评估:
- 使用频率(≥3次为高频)
- 功能独立性(是否耦合业务逻辑)
- 通用性(跨页面/跨业务可用性)
- 复杂度(提取难度)
### 第二阶段:公共控件提取(预计4-6小时)
#### 2.1 基础组件提取
- [ ] **导航栏组件(navbar)** - 已存在,评估优化空间
- [ ] **分页组件(pagination)** - 已存在,评估使用一致性
- [ ] **弹窗组件(popup)** - 已存在,评估功能扩展
- [ ] **标签栏组件(doctor-tab-bar/ground-tab-bar)** - 评估合并可能性
#### 2.2 业务组件提取
- [ ] **项目选择器** - 地推端/药店端/患者端均有项目切换功能
- [ ] **日期选择器** - 多处使用日期范围选择
- [ ] **状态标签** - 审核状态、跳转状态等标签展示
- [ ] **患者卡片** - 患者列表卡片展示
- [ ] **统计卡片** - 首页统计数据展示卡片
#### 2.3 复合组件提取
- [ ] **上传材料弹窗** - popup + 上传功能的复合组件
- [ ] **筛选栏组件** - 搜索+筛选条件的组合
### 第三阶段:组件体系构建(预计2-3小时)
#### 3.1 目录结构规划
```
src/
├── components/
│ ├── base/ # 基础组件
│ │ ├── navbar/
│ │ ├── pagination/
│ │ └── popup/
│ ├── business/ # 业务组件
│ │ ├── project-picker/
│ │ ├── date-picker/
│ │ ├── status-tag/
│ │ └── patient-card/
│ └── composite/ # 复合组件
│ ├── upload-material/
│ └── filter-bar/
```
#### 3.2 命名规范制定
- 基础组件:小写短横线命名
- 业务组件:业务前缀+功能命名
- 复合组件:功能组合命名
### 第四阶段:组件文档编写(预计3-4小时)
为每个提取的组件编写:
- 功能描述
- 使用场景
- 参数列表(类型、默认值、必填、说明)
- 使用示例
- 事件回调说明
- 注意事项
### 第五阶段:代码替换实施(预计6-8小时)
#### 5.1 组件替换
- [ ] 替换地推端首页项目选择器
- [ ] 替换药店端首页项目选择器
- [ ] 替换患者端首页项目选择器
- [ ] 替换患者列表日期筛选
- [ ] 替换统计页面日期筛选
- [ ] 替换审核状态标签
- [ ] 替换患者卡片
#### 5.2 验证测试
- [ ] 功能完整性测试
- [ ] 样式一致性测试
- [ ] 交互逻辑测试
### 第六阶段:成果交付(预计2小时)
#### 6.1 文档输出
- [ ] 组件复用性分析报告
- [ ] 组件库目录结构说明
- [ ] 组件使用文档
- [ ] 代码替换实施指南
#### 6.2 代码审查
- [ ] 组件代码质量检查
- [ ] 引用替换完整性检查
## 预期成果
1. **组件库目录**:标准化的组件分类体系
2. **公共组件**:提取5-8个高频复用组件
3. **技术文档**:完整的组件使用文档
4. **代码优化**:减少重复代码30%以上
## 时间预估
总计:约19-26小时
## 风险评估
| 风险点 | 影响 | 应对措施 |
|--------|------|----------|
| 组件耦合度高 | 提取困难 | 先解耦再提取 |
| 样式差异大 | 统一困难 | 制定样式规范 |
| 替换影响功能 | 回归测试 | 分阶段替换验证 |
## 下一步行动
等待用户确认计划后,开始第一阶段:组件梳理与评估。

11
project.private.config.json

@ -23,13 +23,20 @@ @@ -23,13 +23,20 @@
"miniprogram": {
"list": [
{
"name": "药店-教育详情",
"pathName": "doctor/pages/article/index",
"name": "协议-工作人员协议",
"pathName": "privacy/pages/policy/index",
"query": "",
"scene": null,
"launchMode": "default"
},
{
"name": "药店-教育详情",
"pathName": "doctor/pages/article/index",
"query": "",
"launchMode": "default",
"scene": null
},
{
"name": "药店-教育",
"pathName": "doctor/pages/articleList/index",
"query": "",

13
src/doctor/pages/articleList/index.wxml

@ -16,14 +16,18 @@ @@ -16,14 +16,18 @@
</view>
</view>
</view>
<swiper class="banner" wx:if="{{bannerList.length > 0}}" indicator-dots autoplay circular>
<swiper class="banner" wx:if="{{bannerList.length > 0}}" indicator-dots="{{false}}" autoplay circular>
<swiper-item class="swiper-item" wx:for="{{bannerList}}" wx:key="id">
<image class="s-img" src="{{item.imageUrl}}" mode="aspectFill"></image>
</swiper-item>
</swiper>
<view class="list">
<view class="card" wx:for="{{articleList}}" wx:key="id" data-id="{{item.id}}" bind:tap="handleDetail">
<image class="photo" src="{{item.imageUrl || imageUrl + 'cache/p1.png'}}?t={{Timestamp}}" mode="aspectFill"></image>
<image
class="photo"
src="{{item.imageUrl || imageUrl + 'cache/p1.png'}}?t={{Timestamp}}"
mode="aspectFill"
></image>
<view class="wrap">
<view class="title">{{item.title}}</view>
<view class="options">
@ -32,7 +36,10 @@ @@ -32,7 +36,10 @@
<text class="num">{{item.viewCount || 0}}</text>
</view>
<view class="o-item" catch:tap="handleLike" data-id="{{item.id}}" data-index="{{index}}">
<image class="icon" src="{{item.isLiked ? imageUrl + 'icon25.png' : imageUrl + 'icon23.png'}}?t={{Timestamp}}"></image>
<image
class="icon"
src="{{item.isLiked ? imageUrl + 'icon25.png' : imageUrl + 'icon23.png'}}?t={{Timestamp}}"
></image>
<text class="num {{item.isLiked ? 'liked' : ''}}">{{item.likeCount || 0}}</text>
</view>
</view>

33
src/doctor/pages/patientList/index.wxml

@ -28,14 +28,24 @@ @@ -28,14 +28,24 @@
/>
</view>
<view class="row">
<picker bindchange="handleJumpStatusChange" value="{{jumpStatusIndex}}" range="{{jumpStatusOptions}}" range-key="label">
<picker
bindchange="handleJumpStatusChange"
value="{{jumpStatusIndex}}"
range="{{jumpStatusOptions}}"
range-key="label"
>
<view class="col">
<view class="label">跳转:</view>
<view class="content">{{jumpStatusLabel}}</view>
<image class="icon" src="{{imageUrl}}icon2.png?t={{Timestamp}}"></image>
</view>
</picker>
<picker bindchange="handleEnrollStatusChange" value="{{enrollStatusIndex}}" range="{{enrollStatusOptions}}" range-key="label">
<picker
bindchange="handleEnrollStatusChange"
value="{{enrollStatusIndex}}"
range="{{enrollStatusOptions}}"
range-key="label"
>
<view class="col">
<view class="label">入组:</view>
<view class="content">{{enrollStatusLabel}}</view>
@ -84,7 +94,7 @@ @@ -84,7 +94,7 @@
<image class="avatar" src="{{item.patientAvatar}}" mode="aspectFill"></image>
<view class="wrap">
<view class="info">
<text class="name">{{item.patientName}}</text>
<text class="name" wx:if="{{item.patientName}}">{{item.patientName}}</text>
<text class="tel">{{item.phone}}</text>
</view>
<view class="site">{{item.pharmacyName}}</view>
@ -145,7 +155,7 @@ @@ -145,7 +155,7 @@
</view>
<view class="line-bottom"></view>
</view>
<view class="wrap" wx:if="{{item.jumpAuditStatus === 2}}">
<view class="wrap">
<view class="date" wx:if="{{item.enrollTimeFormatted}}">{{item.enrollTimeFormatted}}</view>
<view class="status">
<!-- 审核状态文本 -->
@ -156,7 +166,12 @@ @@ -156,7 +166,12 @@
{{item.enrollAuditStatusText}}
</view>
<!-- 未审核:提交 -->
<view class="btn2" wx:if="{{item.enrollAuditStatus === 0}}" catch:tap="handleUpload" data-id="{{item.id}}">
<view
class="btn2"
wx:if="{{item.enrollAuditStatus === 0}}"
catch:tap="handleUpload"
data-id="{{item.id}}"
>
提交
</view>
<!-- 审核中/已通过:查看提交材料(预览图片) -->
@ -169,7 +184,12 @@ @@ -169,7 +184,12 @@
查看提交材料
</view>
<!-- 已驳回:重新提交 -->
<view class="btn2" wx:if="{{item.enrollAuditStatus === 3}}" catch:tap="handleUpload" data-id="{{item.id}}">
<view
class="btn2"
wx:if="{{item.enrollAuditStatus === 3}}"
catch:tap="handleUpload"
data-id="{{item.id}}"
>
重新提交
</view>
</view>
@ -177,7 +197,6 @@ @@ -177,7 +197,6 @@
{{item.enrollRejectReason}}
</view>
</view>
<view class="none">---</view>
</view>
</view>
</view>

65
src/pages/index/index.ts

@ -124,11 +124,8 @@ Page({ @@ -124,11 +124,8 @@ Page({
// 检查扫码的项目是否与当前项目一致
const scanProjectId = this.data.projectId
if (scanProjectId && String(scanProjectId) !== String(res.projectId)) {
// 扫码的是新项目,进入选择流程
this.setData({
hasProject: false,
})
this.getProjectInfo()
// 扫码的是不同项目,检查患者是否已参与过该项目
this.checkAndSwitchProject(scanProjectId, res)
} else {
// 已有项目且与扫码项目一致,显示已参加项目状态
this.setData({
@ -157,6 +154,64 @@ Page({ @@ -157,6 +154,64 @@ Page({
})
},
// 检查并切换项目
checkAndSwitchProject(scanProjectId: string, currentProject: any) {
// 获取患者的项目列表
wx.ajax({
method: 'GET',
url: '/app/patient/patient/project-list',
}).then((projectRes: any) => {
const projectList = projectRes.list || []
// 检查扫码的项目是否在患者已参与的项目列表中
const hasProject = projectList.some((p: any) => String(p.projectId) === String(scanProjectId))
if (hasProject) {
// 患者已参与过该项目,自动切换
wx.ajax({
method: 'POST',
url: '/app/patient/patient/switch-project',
data: {
projectId: scanProjectId,
},
}).then(() => {
wx.showToast({
title: '已切换到该项目',
icon: 'success',
})
// 刷新页面数据
this.getProjectList()
this.checkStatus()
}).catch(() => {
// 切换失败,显示当前项目
this.setData({
isLogin: 1,
isPatient: 1,
projectId: currentProject.projectId,
projectName: currentProject.projectName,
hasProject: true,
selectedIndicationName: currentProject.indicationName,
})
})
} else {
// 患者未参与过该项目,进入选择流程
this.setData({
hasProject: false,
})
this.getProjectInfo()
}
}).catch(() => {
// 获取项目列表失败,显示当前项目
this.setData({
isLogin: 1,
isPatient: 1,
projectId: currentProject.projectId,
projectName: currentProject.projectName,
hasProject: true,
selectedIndicationName: currentProject.indicationName,
})
})
},
getProjectInfo() {
const params: any = {}
// 如果有 projectId,传入获取指定项目信息

66
src/pages/start/index.ts

@ -38,16 +38,18 @@ Page({ @@ -38,16 +38,18 @@ Page({
const { isLogin, isRegister, loginIdentity } = app.globalData.initLoginInfo
// 扫码进入用户处理
// t=1: 地推人员码,t=2: 药店人员码
if (t == '1') {
// 已登录的药店人员扫码,需要建立新的绑定关系
if (loginIdentity === 4 && isLogin && isRegister) {
wx.reLaunch({
url: '/doctor/pages/home/index?bind=1',
})
} else {
wx.reLaunch({
url: '/doctor/pages/login/index',
})
// 调用绑定接口
this.bindPharmacist(promoterId, projectId)
return
}
// 未登录或非药店人员,跳转到登录页
wx.reLaunch({
url: '/doctor/pages/login/index',
})
return
}
if (t == '2') {
@ -89,6 +91,56 @@ Page({ @@ -89,6 +91,56 @@ Page({
})
})
},
// 药店人员扫码绑定
bindPharmacist(promoterId: string, projectId: string) {
if (!promoterId || !projectId) {
wx.showToast({
title: '二维码参数错误',
icon: 'none',
})
setTimeout(() => {
wx.reLaunch({
url: '/doctor/pages/home/index',
})
}, 1500)
return
}
wx.showLoading({ title: '绑定中...' })
wx.ajax({
method: 'POST',
url: '/app/pharmacist/pharmacist/bind-promoter',
data: {
promoterId: Number.parseInt(promoterId),
projectId: Number.parseInt(projectId),
},
})
.then(() => {
wx.hideLoading()
wx.showToast({
title: '绑定成功',
icon: 'success',
})
setTimeout(() => {
wx.reLaunch({
url: '/doctor/pages/home/index',
})
}, 1500)
})
.catch((err: any) => {
wx.hideLoading()
wx.showToast({
title: err.msg || '绑定失败',
icon: 'none',
})
setTimeout(() => {
wx.reLaunch({
url: '/doctor/pages/home/index',
})
}, 1500)
})
},
})
export {}

97
src/privacy/pages/policy/index.ts

File diff suppressed because one or more lines are too long

4
src/privacy/pages/policy/index.wxml

@ -1,6 +1,4 @@ @@ -1,6 +1,4 @@
<navbar fixed title="个人信息及隐私保护政策" show-back bind:back="goBack" />
<view class="privacy-page" style="padding-top: {{pageTop}}px">
<view class="privacy-page">
<view class="content">
<mp-html content="{{content}}" />
</view>

Loading…
Cancel
Save