Files
xk-client-wx/subPackages/my/mycollection.vue
李琦 2d2a8abfd4 feat(home/chat): 列表骨架屏、聊天室己方头像与协议/医生详情优化
- 新增分包组件 ListSkeleton(doctor/message/product/article/category/zone)
- 首页/消息/资讯首次加载改用骨架屏,刷新不再清空旧数据避免闪空
  · 去掉 home getList、消息 onShow 中的数组清空
  · 三页 pages.json 增加 easycom 与 componentPlaceholder 主包异步引用
- 聊天室己方头像改为读取本地 userinfo.avatarurl(登录后微信头像),
  mycollection 上传头像成功后同步写回 storage
- 修复协议抽屉点不开:page-container 改为 v-if + :show;
  协议名单独可点节点,匹配放宽 name/desc 双向 includes
- 医生气泡头像可点击进入 doctor-detail?readonly=1 只读医生详情,
  隐藏预约挂号区
2026-07-19 16:08:04 +08:00

365 lines
8.3 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="container safe-area-inset-bottom">
<MessageNotification />
<!-- 头部 -->
<view class="head">
<view class="title">
头像
</view>
<view class="images">
<u-avatar class="img" :src="avatar" shape="circle" @click="changeUserPhoto()"></u-avatar>
<text class="iconfont icon-jiantou1" @click="changeUserPhoto()"></text>
</view>
</view>
<!-- 卡片 -->
<view class="card">
<view class="box">
<view class="title">
昵称
</view>
<!-- <text @click="">{{name}}</text> -->
<u-input v-model="name" :type="type" :border="border" input-align="right" placeholder=" " />
</view>
<view class="box">
<view class="title">
性别
</view>
<u-input v-model="sex" :type="type" :border="border" input-align="right" placeholder=" " />
</view>
<view class="box">
<view class="title">
电话
</view>
<u-input v-model="mobile" :type="type" :border="border" input-align="right" placeholder=" " />
</view>
<view class="box">
<view class="title">
身份证号码
</view>
<u-input v-model="idCard" :type="type" :border="border" input-align="right" placeholder=" " />
</view>
</view>
<view class="btn" @click="toAppion">
保存
</view>
<u-toast ref="uToast" />
</view>
</template>
<script>
import {
getEditUser,
getuserInfo
} from '../../request/api/api'
import { checkProfileTexts, checkImage, handleSecurityError, SCENE_PROFILE } from '@/utils/content-security.js';
export default {
data() {
return {
id: "",
info: [],
avatar: "",
idCard: "",
name: '',
sex: "",
mobile: "",
type: 'text',
border: false,
// 内容安全 baselinegetInfo 后快照 nickname
_securityBaseline: {},
}
},
onLoad(e) {
this.id = e.id
},
methods: {
getInfo() {
getuserInfo({
method: "post",
data: {
store_id: uni.getStorageSync('store_id') || '11001',
}
}).then((res) => {
if (res.data.errcode == 0) {
this.avatar = res.data.data.user.avatarurl
this.name = res.data.data.user.nickname
this.sex = res.data.data.sex
this.mobile = res.data.data.user.mobile
this.idCard = res.data.data.user.idcard
this._securityBaseline = { name: this.name }
// 写回本地 userinfo保证聊天室等页面能读到最新头像
this.syncUserinfoStorage(res.data.data.user)
}
})
},
/**
* 将最新用户资料合并进本地 userinfo尤其是 avatarurl
* 登录时存的是整份 user此处只覆盖接口返回的字段避免丢掉其它缓存键
*/
syncUserinfoStorage(user) {
if (!user) return
const cached = uni.getStorageSync('userinfo') || {}
uni.setStorageSync('userinfo', {
...cached,
...user,
avatarurl: user.avatarurl || cached.avatarurl || ''
})
},
// 点击头像触发click事件 changeUserPhoto
async changeUserPhoto() {
console.log('进入更新头像的功能')
// 先检查隐私授权
// #ifdef MP-WEIXIN
if (typeof uni.requirePrivacyAuthorize === 'function') {
try {
await new Promise((resolve, reject) => {
uni.requirePrivacyAuthorize({
success: () => resolve(),
fail: () => {
uni.showToast({ title: '需要同意隐私协议才能使用此功能', icon: 'none' });
reject(new Error('隐私授权被拒绝'));
}
});
});
} catch (e) {
return; // 用户拒绝隐私授权
}
}
// #endif
uni.chooseImage({
count: 1, //默认9
sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
sourceType: ['album', 'camera'],
success: async (res) => {
console.log('图片选择成功')
uni.showLoading({
title: '请稍后...'
})
const tempFiles = res.tempFiles;
let resSize = tempFiles[0].size;
// 1M=1024KB=1048576B
console.log(resSize)
if (resSize > 1048576) {
uni.hideLoading()
this.$refs.uToast.show({
title:"上传图片大小不能超过1MB",
type: 'default',
icon: false
})
return
}
try {
await checkImage(tempFiles[0]['path'], SCENE_PROFILE);
} catch (e) {
uni.hideLoading();
handleSecurityError(e);
return;
}
uni.uploadFile({
url: 'https://app.xiaokang88.com/member/v1/attachment/upload',
filePath: res.tempFiles[0]['path'],
name: 'file',
formData: {
store_id: uni.getStorageSync('store_id') || '11001',
},
header: {
authorization: `Bearer ${uni.getStorageSync('token')}`
},
success: res => {
uni.hideLoading()
let req = JSON.parse(res.data)
// console.log(req, 'req');
this.getAvator(req)
},
fail: (err) => {
uni.hideLoading()
uni.showToast({
title: '上传失败',
icon: 'error'
})
}
});
},
fail: (err) => {
console.error('选择图片失败:', err);
},
complete: () => {
console.log('选择图片完成');
}
})
},
// 编辑用户信息
getAvator(req) {
getEditUser({
method: "post",
data: {
store_id: uni.getStorageSync('store_id') || '11001',
avatarurl: req.data.url,
}
}).then((res) => {
// console.log(res, 'img');
if (res.data.errcode == 0) {
uni.showToast({
icon: "success",
title: '保存成功'
})
// 先写回 storage再拉详情避免聊天页 onShow 读到旧头像
const cached = uni.getStorageSync('userinfo') || {}
uni.setStorageSync('userinfo', {
...cached,
avatarurl: req.data.url
})
this.avatar = req.data.url
this.getInfo()
}
})
},
async toAppion() {
try {
await checkProfileTexts({ name: this.name }, this._securityBaseline, SCENE_PROFILE);
} catch (e) {
handleSecurityError(e);
return;
}
getEditUser({
method: "post",
data: {
store_id: uni.getStorageSync('store_id') || '11001',
nickname: this.name,
mobile: this.mobile,
gender: (this.sex) == '男' ? 1 : 2,
idcard: this.idCard,
}
}).then((res) => {
// console.log(res, 'img');
if (res.data.errcode == 0) {
setTimeout(() => {
uni.showToast({
icon: "success",
title: '保存成功'
})
this.getInfo()
}, 1000)
setTimeout(() => {
uni.navigateBack({
delta: 1
})
}, 2000)
}
})
},
},
mounted() {
this.getInfo()
},
onShow() {
this.getInfo()
}
}
</script>
<style lang="scss" scoped>
.container {
width: 100vw;
min-height: 100vh;
max-height: 100%;
background-color: #F8FAFC;
padding-bottom: env(safe-area-inset-bottom);
.head {
width: 750rpx;
height: 104rpx;
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 20rpx;
padding: 0 60rpx;
background: #FFFFFF;
.title {
font-size: 28rpx;
font-family: PingFang SC-Bold, PingFang SC;
font-weight: bold;
color: #475569;
}
.images {
display: flex;
align-items: center;
.img {
width: 96rpx;
height: 96rpx;
border-radius: 50%;
}
.iconfont {
color: #999999;
font-weight: 500;
font-size: 34rpx;
}
}
}
.card {
width: 750rpx;
margin: 10rpx 0;
padding: 0 60rpx;
background: #FFFFFF;
.box {
display: flex;
justify-content: space-between;
align-items: center;
height: 98rpx;
.title {
width: 250rpx;
font-size: 28rpx;
font-family: PingFang SC-Bold, PingFang SC;
font-weight: bold;
color: #475569;
}
.u-field {
flex: 1;
}
text {
font-size: 28rpx;
font-family: PingFang SC-Regular, PingFang SC;
font-weight: 400;
color: #999999;
}
}
}
.btn {
width: 686rpx;
height: 86rpx;
font-size: 32rpx;
line-height: 86rpx;
text-align: center;
font-family: PingFang SC-Medium, PingFang SC;
font-weight: 500;
color: #FFFFFF;
background: #4175EE;
border-radius: 64rpx;
margin: 80rpx auto;
}
}
</style>