Browse Source

refactor(components): 优化上传文件组件和隐私协议页面

- 移除uploadFile组件的冗余JSON配置
- 修改隐私协议页面的样式和内容
- 更新游客首页的隐私协议链接路径
- 修复昵称保存事件从onNicknameReview改为onNicknameBlur
- 为图片添加mode="aspectFill"属性
master
kola-web 5 days ago
parent
commit
56d7f5eed3
  1. 303
      .trae/documents/component-reuse-analysis-report.md
  2. 125
      .trae/documents/component-reuse-optimization-plan.md
  3. 11
      project.private.config.json
  4. 3
      src/components/popup/index.json
  5. 4
      src/components/popup/index.wxml
  6. 287
      src/components/uploadFile/index.js
  7. 9
      src/components/uploadFile/index.json
  8. 0
      src/components/uploadFile/index.scss
  9. 3
      src/components/uploadFile/index.wxml
  10. 7
      src/pages/index/index.ts
  11. 13
      src/pages/index/index.wxml
  12. 4
      src/pages/tourists/index.ts
  13. 4
      src/pages/tourists/index.wxml
  14. 2
      src/privacy/pages/policy1/index.ts

303
.trae/documents/component-reuse-analysis-report.md

@ -1,303 +0,0 @@ @@ -1,303 +0,0 @@
# 组件复用性分析报告
## 一、项目组件盘点
### 1.1 现有自定义组件(10个)
| 组件名称 | 路径 | 功能描述 | 使用频率 | 状态 |
|---------|------|---------|---------|------|
| navbar | /components/navbar | 自定义导航栏 | 高(15+页面) | ✅ 良好 |
| pagination | /components/pagination | 分页组件 | 中(5页面) | ✅ 良好 |
| popup | /components/popup | 通用弹窗 | 高(8页面) | ⚠ 需优化 |
| calendar | /components/calendar | 日历组件 | 低(未使用) | ❓ 待确认 |
| pickerArea | /components/pickerArea | 省市区选择器 | 低(1页面) | ✅ 可用 |
| uploadFile | /components/uploadFile | 文件上传 | 低(1页面) | ✅ 可用 |
| ec-canvas | /components/ec-canvas | ECharts图表 | 中(2页面) | ✅ 良好 |
| customPoster | /components/customPoster | 海报生成 | 低(未使用) | ❓ 待确认 |
| star | /components/star | 星星动画 | 低(未使用) | ❓ 待确认 |
| popupDoctor | /components/popupDoctor | 医生信息弹窗 | 低(未使用) | ❓ 待确认 |
### 1.2 TabBar组件(2个)
| 组件名称 | 路径 | 使用端 | 使用频率 |
|---------|------|--------|---------|
| doctor-tab-bar | /components/doctor-tab-bar | 药店端 | 4页面 |
| ground-tab-bar | /components/ground-tab-bar | 地推端 | 3页面 |
**复用建议:** 两个组件功能相似,可合并为 `tab-bar` 组件,通过配置区分不同角色。
---
## 二、组件复用价值评估矩阵
### 2.1 高优先级组件(建议立即提取)
| 组件名称 | 使用频率 | 功能独立性 | 通用性 | 复杂度 | 复用价值 | 优先级 |
|---------|---------|-----------|--------|--------|---------|--------|
| **项目选择器** | 3次 | 高 | 高 | 低 | ⭐⭐⭐⭐⭐ | P0 |
| **统计卡片** | 4次 | 高 | 高 | 中 | ⭐⭐⭐⭐⭐ | P0 |
| **日期选择逻辑** | 5次 | 高 | 高 | 中 | ⭐⭐⭐⭐ | P1 |
### 2.2 中优先级组件(建议后续提取)
| 组件名称 | 使用频率 | 功能独立性 | 通用性 | 复杂度 | 复用价值 | 优先级 |
|---------|---------|-----------|--------|--------|---------|--------|
| **状态标签** | 2次 | 高 | 中 | 低 | ⭐⭐⭐ | P2 |
| **个人信息页面** | 6次 | 中 | 中 | 高 | ⭐⭐⭐ | P2 |
| **登录页面** | 2次 | 中 | 中 | 高 | ⭐⭐⭐ | P2 |
| **修改昵称/手机页面** | 4次 | 中 | 中 | 中 | ⭐⭐⭐ | P2 |
### 2.3 低优先级组件(保持现状)
| 组件名称 | 使用频率 | 功能独立性 | 通用性 | 复杂度 | 复用价值 | 优先级 |
|---------|---------|-----------|--------|--------|---------|--------|
| **患者卡片** | 1次 | 中 | 低 | 高 | ⭐⭐ | P3 |
| **上传材料弹窗** | 1次 | 高 | 中 | 中 | ⭐⭐ | P3 |
---
## 三、详细组件分析
### 3.1 项目选择器(ProjectPicker)
**使用位置:**
1. 地推端首页:`/ground/pages/home/index.wxml`
2. 药店端首页:`/doctor/pages/home/index.wxml`
3. 患者列表页:`/doctor/pages/patientList/index.wxml`
**代码相似度:** 90%
**主要差异:**
- 主题色不同(地推端蓝色 #4A8DFF,药店端橙色 #FF8A4C
- 样式细节略有差异
**提取收益:**
- 减少重复代码约 60 行
- 统一项目切换交互体验
- 便于后续维护
**组件接口设计:**
```typescript
interface ProjectPickerProps {
projectList: Array<{ projectId: number; projectName: string }>;
currentProjectName: string;
themeColor: string; // 主题色
onChange: (projectId: number) => void;
}
```
### 3.2 统计卡片(StatCard)
**使用位置:**
1. 地推端首页:`/ground/pages/home/index.wxml`(2处)
2. 药店端首页:`/doctor/pages/home/index.wxml`(2处)
3. 地推端统计页:`/ground/pages/stat/index.wxml`
4. 药店端统计页:`/doctor/pages/stat/index.wxml`
**代码相似度:** 88%
**主要差异:**
- 地推端显示"药店数",药店端不显示
- 数据字段名称略有不同
- 主题色不同
**提取收益:**
- 减少重复代码约 200 行
- 统一统计卡片样式
- 支持配置化展示
**组件接口设计:**
```typescript
interface StatCardProps {
title: string;
tip?: string;
data: Array<{ name: string; value: number }>;
showIndicationStats?: boolean;
indicationStats?: Array<any>;
themeColor: string;
}
```
### 3.3 日期选择逻辑(DatePickerMixin)
**使用位置:**
1. 地推端首页:日期筛选逻辑
2. 药店端首页:日期筛选逻辑
3. 患者列表页:时间筛选
4. 地推端统计页:日期筛选
5. 药店端统计页:日期筛选
**代码相似度:** 85%
**重复逻辑:**
- 日期格式化函数
- 日期范围验证
- 日/月模式切换
- 日期选择器事件处理
**提取收益:**
- 减少重复代码约 150 行
- 统一日期处理逻辑
- 避免日期相关 bug
**Mixin接口设计:**
```typescript
interface DatePickerMixin {
// 数据
startDate: string;
endDate: string;
statType: 'day' | 'month';
// 方法
formatDate(date: string): string;
formatMonth(date: string): string;
validateDateRange(start: string, end: string): boolean;
onDateChange(e: CustomEvent): void;
prevDate(): void;
nextDate(): void;
}
```
### 3.4 状态标签(StatusTag)
**使用位置:**
1. 患者列表页:跳转状态、入组状态、审核状态
**代码相似度:** 80%
**状态定义:**
```typescript
// 跳转/入组状态
const statusOptions = [
{ value: '', label: '全部' },
{ value: 0, label: '未跳转/未入组' },
{ value: 1, label: '已跳转/已入组' },
];
// 审核状态
const auditStatusMap = {
0: { label: '未审核', class: 's2' },
1: { label: '审核中', class: 's2' },
2: { label: '已通过', class: 's1' },
3: { label: '已驳回', class: 's1' },
};
```
**提取收益:**
- 统一状态展示样式
- 便于新增状态类型
### 3.5 个人信息相关页面
**涉及页面:**
- 地推端:my、changeNickname、changeTel(3个页面)
- 药店端:my、changeNickname、changeTel(3个页面)
**代码相似度:** 95%
**主要差异:**
- API接口地址不同
- 数据字段名称不同
- 主题色不同
**提取建议:**
创建通用页面模板,通过配置区分:
```typescript
interface ProfileConfig {
role: 'promoter' | 'pharmacist';
themeColor: string;
apiEndpoints: {
getProfile: string;
updateAvatar: string;
updateName: string;
updatePhone: string;
logout: string;
};
}
```
---
## 四、组件提取实施建议
### 4.1 第一阶段:高优先级组件(1-2周)
1. **项目选择器**
- 创建 `/components/project-picker/`
- 替换 3 个页面的使用
- 编写组件文档
2. **统计卡片**
- 创建 `/components/stat-card/`
- 替换 4 个页面的使用
- 编写组件文档
3. **日期选择Mixin**
- 创建 `/mixins/date-picker.ts`
- 在 5 个页面中引入使用
- 编写使用文档
### 4.2 第二阶段:中优先级组件(2-3周)
1. **状态标签组件**
2. **个人信息页面模板**
3. **登录页面模板**
### 4.3 第三阶段:优化与文档(1周)
1. 完善组件文档
2. 编写使用示例
3. 代码审查与优化
---
## 五、预期收益
### 5.1 代码量减少
| 组件 | 预计减少代码行数 |
|------|----------------|
| 项目选择器 | 60 行 |
| 统计卡片 | 200 行 |
| 日期选择Mixin | 150 行 |
| 状态标签 | 80 行 |
| 个人信息页面 | 300 行 |
| **总计** | **约 800 行** |
### 5.2 维护效率提升
- 统一交互体验
- 减少重复 bug
- 便于功能迭代
- 新功能开发效率提升 30%
### 5.3 代码质量提升
- 提高代码可读性
- 降低耦合度
- 提升可测试性
---
## 六、风险评估与应对措施
| 风险点 | 影响 | 应对措施 |
|--------|------|----------|
| 组件耦合度高 | 提取困难 | 先解耦再提取,保持原有功能 |
| 样式差异大 | 统一困难 | 通过 props 配置主题色和样式 |
| 替换影响功能 | 回归测试 | 分阶段替换,每阶段充分测试 |
| 接口差异 | 逻辑复杂 | 使用配置化方式处理差异 |
---
## 七、下一步行动
1. **立即开始**:项目选择器组件提取
2. **本周完成**:统计卡片组件提取
3. **下周开始**:日期选择Mixin提取
4. **持续进行**:组件文档编写
---
*报告生成时间:2026-03-05*
*分析师:AI Assistant*

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

@ -1,125 +0,0 @@ @@ -1,125 +0,0 @@
# 组件复用性分析与优化计划
## 项目概述
对药品查询微信小程序进行全面的组件复用性分析与优化,建立标准化的组件体系,提升代码质量和开发效率。
## 执行步骤
### 第一阶段:组件梳理与评估(预计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": "pages/tourists/index",
"name": "协议-患者隐私协议",
"pathName": "privacy/pages/policy1/index",
"query": "",
"scene": null,
"launchMode": "default"
},
{
"name": "游客-首页",
"pathName": "pages/tourists/index",
"query": "",
"launchMode": "default",
"scene": null
},
{
"name": "协议-工作人员协议",
"pathName": "privacy/pages/policy/index",
"query": "",

3
src/components/popup/index.json

@ -1,7 +1,6 @@ @@ -1,7 +1,6 @@
{
"component": true,
"usingComponents": {
"van-popup": "@vant/weapp/popup/index",
"uploadFile": "/components/uploadFile/index"
"van-popup": "@vant/weapp/popup/index"
}
}

4
src/components/popup/index.wxml

@ -12,7 +12,7 @@ @@ -12,7 +12,7 @@
<!-- 上传患者材料弹窗 -->
<view class="popup1" wx:if="{{type==='uploadMaterial'}}">
<view class="title">{{params.title || '上传证明材料'}}</view>
<view class="row">
<view class="row" wx:if="{{params.patientName}}">
<view class="label">患者姓名</view>
<view class="content">{{params.patientName}}</view>
</view>
@ -24,7 +24,7 @@ @@ -24,7 +24,7 @@
<view class="label">项目</view>
<view class="content">{{params.projectName}}<text style="font-size:0.5em;vertical-align: top;">®</text>项目</view>
</view>
<view class="row">
<view class="row" wx:if="{{params.indicationName}}">
<view class="label">适应症</view>
<view class="content">{{params.indicationName}}</view>
</view>

287
src/components/uploadFile/index.js

@ -1,287 +0,0 @@ @@ -1,287 +0,0 @@
// components/uploadFile/index.js
const app = getApp()
Component({
/**
* 组件的属性列表
*/
properties: {
// 是否可以上传
upload: {
type: Boolean,
value: true,
},
// 是否可以删除
delete: {
type: Boolean,
value: true,
},
// 附件data
fileList: {
type: Array,
value: [],
},
// 最大上传数量, -1为不限制
maxNum: {
type: Number,
value: -1,
},
isSlot: {
type: Boolean,
value: false,
},
count: {
type: Number,
value: 0,
},
},
/**
* 组件的初始数据
*/
data: {
Timestamp: app.globalData.Timestamp,
imageUrl: app.globalData.imageUrl,
show: false,
actions: [
{
id: 1,
name: '选择视频或图片',
},
{
id: 2,
name: '选择聊天文件',
},
],
},
/**
* 组件的方法列表
*/
methods: {
viewFile(e) {
const { index } = e.currentTarget.dataset
const { fileList } = this.properties
const params = fileList[index]
if (['image', 'video'].includes(params.fileType)) {
let sources = []
fileList.forEach((item) => {
let obj = {}
if (item.fileType === 'image') {
obj = {
url: item.url,
type: item.fileType,
poster: item.url,
}
}
if (item.fileType === 'video') {
obj = {
url: item.vidoeUrl,
type: item.fileType,
poster: item.url,
}
}
sources.push(obj)
})
wx.previewMedia({
current: index,
sources,
})
} else if (params.fileType !== 'audio') {
wx.downloadFile({
url: params.url,
success(res) {
wx.openDocument({
filePath: res.tempFilePath,
showMenu: true,
fail() {
wx.showToast({
title: '该文件无法预览',
icon: 'none',
})
},
})
},
})
}
},
deleteFile(e) {
const { index, item } = e.currentTarget.dataset
this.triggerEvent('deleteFile', {
index,
item,
})
},
downFile(e) {
const { item } = e.currentTarget.dataset
wx.showToast({
title: '正在下载,请稍后...',
icon: 'none',
})
wx.downloadFile({
url: item.url || item.fileUrl,
success(res) {
if (item.type === 'image') {
wx.saveImageToPhotosAlbum({
filePath: res.tempFilePath,
success: () => {
wx.showToast({
title: '下载成功',
})
},
})
} else if (item.type === 'video') {
wx.saveVideoToPhotosAlbum({
filePath: res.tempFilePath,
success: () => {
wx.showToast({
title: '下载成功',
})
},
})
} else {
wx.showToast({
title: '附件请到pc端下载!',
icon: 'none',
})
}
},
})
},
uploadFile(item) {
return new Promise((resolve, resject) => {
let url = `${app.globalData.upFileUrl}?r=file-service/upload-`
if (item.type === 'image') {
url += 'img'
}
if (item.type === 'video') {
url += 'video'
}
if (item.type === 'file') {
url += 'doc'
}
wx.uploadFile({
filePath: item.tempFilePath,
name: 'file',
url,
success: (res) => {
let data = JSON.parse(res.data)
let expandJson = {
name: item.name,
fileType: item.fileType,
}
if (item.type === 'image') {
expandJson.url = data.data.Url
}
if (item.type === 'video') {
expandJson.url = data.data.SnapshotUrl
expandJson.videoUrl = data.data.Url
expandJson.duration = data.data.Duration
}
if (item.type === 'file') {
expandJson.url = data.data.Url
}
resolve(expandJson)
},
fail() {
resject()
},
})
})
},
GetExtensionFileName(pathfilename) {
let reg = /(\\+)/g
let pString = pathfilename.replace(reg, '#') //用正则表达式来将\或\\替换成#
let arr = pString.split('#') // 以“#”为分隔符,将字符分解为数组 例如 D Program Files bg.png
let lastString = arr[arr.length - 1] //取最后一个字符
let arr2 = lastString.split('.') // 再以"."作为分隔符
return arr2[arr2.length - 1] //将后缀名返回出来
},
upFile(data) {
wx.showLoading({
title: '正在上传',
})
let apiArr = []
data.map((e) => {
apiArr.push(this.uploadFile(e))
})
Promise.all(apiArr)
.then((res) => {
wx.hideLoading({
success: () => {
this.triggerEvent('setData', res)
},
})
})
.catch(() => {
wx.showToast({
title: '上传失败',
icon: 'error',
})
})
},
handleAction() {
this.selectMedia()
},
onSelect(e) {
const { id } = e.currentTarget.dataset
if (id == 1) {
this.setData({
show: false,
})
this.selectMedia()
}
if (id == 2) {
this.setData({
show: false,
})
this.selectFiles()
}
},
selectMedia() {
let { fileList, maxNum, count = 0 } = this.properties
if (maxNum >= 0 && count == 0) {
count = maxNum - fileList.length
}
wx.chooseMedia({
mediaType: ['image', 'video'],
count,
sourceType: ['album', 'camera'],
sizeType: ['original'],
success: (res) => {
res.tempFiles.map((e) => {
e.name = e.tempFilePath
e.extend = this.GetExtensionFileName(e.tempFilePath)
e.tempFilePath = e.tempFilePath
e.type = e.fileType
e.fileType = e.fileType
})
this.upFile(res.tempFiles)
},
})
},
selectFiles() {
let { fileList, maxNum, count = 0 } = this.properties
if (maxNum >= 0 && count == 0) {
count = maxNum - fileList.length
}
wx.chooseMessageFile({
count,
type: 'file',
extension: ['doc', 'docx', 'pdf', 'xlsx', 'xls', 'ppt', 'pptx'],
success: (res) => {
res.tempFiles.map((e) => {
e.type = 'file'
e.tempFilePath = e.path
e.fileType = this.GetExtensionFileName(e.path)
})
this.upFile(res.tempFiles)
},
})
},
onClose() {
this.setData({ show: false })
},
},
})

9
src/components/uploadFile/index.json

@ -1,9 +0,0 @@ @@ -1,9 +0,0 @@
{
"component": true,
"usingComponents": {
"van-icon": "@vant/weapp/icon/index",
"van-image": "@vant/weapp/image/index",
"van-action-sheet": "@vant/weapp/action-sheet/index",
"van-popup": "@vant/weapp/popup/index"
}
}

0
src/components/uploadFile/index.scss

3
src/components/uploadFile/index.wxml

@ -1,3 +0,0 @@ @@ -1,3 +0,0 @@
<view catchtap="handleAction">
<slot></slot>
</view>

7
src/pages/index/index.ts

@ -20,7 +20,6 @@ Page({ @@ -20,7 +20,6 @@ Page({
// 扫码获取的药师ID
pharmacistId: '',
isLogin: 0,
isPatient: 0,
// 是否已有项目
@ -123,7 +122,6 @@ Page({ @@ -123,7 +122,6 @@ Page({
} else {
// 已经是当前项目,直接显示
this.setData({
isLogin: 1,
isPatient: 1,
projectId: currentProject.projectId,
projectName: currentProject.projectName,
@ -142,7 +140,6 @@ Page({ @@ -142,7 +140,6 @@ Page({
} else {
// 没有扫码,显示当前项目
this.setData({
isLogin: 1,
isPatient: 1,
projectId: currentProject.projectId,
projectName: currentProject.projectName,
@ -241,8 +238,8 @@ Page({ @@ -241,8 +238,8 @@ Page({
})
},
// 昵称选择/输入时保存
onNicknameReview(e: WechatMiniprogram.CustomEvent) {
// 昵称失焦时保存
onNicknameBlur(e: WechatMiniprogram.CustomEvent) {
const nickname = e.detail.value
this.setData({
nickname,

13
src/pages/index/index.wxml

@ -25,11 +25,18 @@ @@ -25,11 +25,18 @@
style="background: url('{{imageUrl}}bg2.png?t={{Timestamp}}') no-repeat top center/100% 558rpx;padding-top: {{pageTop+24}}px;"
>
<!-- 用户信息 -->
<view class="user-info" wx:if="{{isLogin === 1}}">
<view class="user-info">
<button class="avatar-wrapper" open-type="chooseAvatar" bind:chooseavatar="onChooseAvatar">
<image class="avatar" src="{{avatarUrl || imageUrl + 'default-avatar.png'}}"></image>
<image class="avatar" src="{{avatarUrl}}" mode="aspectFill"></image>
</button>
<input type="nickname" class="input" placeholder-class="input-placeholder" placeholder="我的昵称" value="{{nickname}}" bindnicknamereview="onNicknameReview" />
<input
type="nickname"
class="input"
placeholder-class="input-placeholder"
placeholder="我的昵称"
value="{{nickname}}"
bindblur="onNicknameBlur"
/>
</view>
<swiper class="banner" wx:if="{{bannerList.length > 0}}">
<swiper-item class="b-item">

4
src/pages/tourists/index.ts

@ -58,8 +58,8 @@ Page({ @@ -58,8 +58,8 @@ Page({
},
})
},
// 昵称选择/输入时保存
onNicknameReview(e: WechatMiniprogram.CustomEvent) {
// 昵称失焦时保存
onNicknameBlur(e: WechatMiniprogram.CustomEvent) {
const nickname = e.detail.value
this.setData({
nickname,

4
src/pages/tourists/index.wxml

@ -8,9 +8,9 @@ @@ -8,9 +8,9 @@
>
<view class="user">
<button class="avatar-wrapper" open-type="chooseAvatar" bind:chooseavatar="onChooseAvatar">
<image class="avatar" src="{{avatarUrl}}"></image>
<image class="avatar" src="{{avatarUrl}}" mode="aspectFill"></image>
</button>
<input type="nickname" class="input" placeholder-class="input-placeholder" placeholder="我的昵称" value="{{nickname}}" bindnicknamereview="onNicknameReview" />
<input type="nickname" class="input" placeholder-class="input-placeholder" placeholder="我的昵称" value="{{nickname}}" bindblur="onNicknameBlur" />
</view>
<image class="page-banner" src="{{imageUrl}}start1.png?t={{Timestamp}}"></image>
<view class="page-options">

2
src/privacy/pages/policy1/index.ts

File diff suppressed because one or more lines are too long
Loading…
Cancel
Save