detection-business/pages/index/UserInfo.vue
2025-06-16 17:17:24 +08:00

370 lines
9.4 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="content">
<!-- <view class="top-heder">-->
<!-- <view class="t-left" @click="handleBack">-->
<!-- <uni-icons type="left" size="18"></uni-icons>-->
<!-- </view>-->
<!-- <view class="c-title">个人信息</view>-->
<!-- <view style="width: 5%; height: 10px;"></view>-->
<!-- </view>-->
<headersVue titles="个人信息" style="position: static !important;">
<u-icon name="arrow-left" color="#fff" size="18"></u-icon>
</headersVue>
<view class="body">
<view class="formItem">
<image class="formIcon" mode="aspectFit" src="@/static/icons/userInfo_1.png"></image>
<text class="formLabel">头像</text>
<view class="formValue">
<image style="width: 64rpx;height: 64rpx;border-radius: 50%;"
v-if="customInfo && customInfo.avatar === null" :src="defaultAvatar" mode="scaleToFill"
class="avatar"></image>
<image v-else :src="customInfo.avatar" class="avatar" mode="scaleToFill"
style="width: 64rpx;height: 64rpx;border-radius: 50%;"></image>
</view>
</view>
<view class="formItem">
<image class="formIcon" mode="aspectFit" src="@/static/icons/userInfo_2.png"></image>
<text class="formLabel">账号昵称</text>
<text class="formValue">{{ customInfo.nickname }}</text>
<!-- <u-icon color="#999" name="arrow-right" size="12"></u-icon>-->
</view>
<view class="formItem">
<image class="formIcon" mode="aspectFit" src="@/static/icons/userInfo_3.png"></image>
<text class="formLabel">绑定电话</text>
<text class="formValue">{{ customInfo.mobile }}</text>
<!-- <u-icon color="#999" name="arrow-right" size="12"></u-icon>-->
</view>
<view class="formItem">
<image class="formIcon" mode="aspectFit" src="../../static/icons/userInfo_3.png"></image>
<text class="formLabel">我的邀请码</text>
<text class="formValue"></text>
</view>
<view style="padding-bottom: 60rpx;" class="formItem">
<canvas id="qrcode" canvas-id="qrcode" style="width: 200px;height: 200px;margin: auto"
@longpress="saveQRCode"></canvas>
</view>
<text
style="display: block; font-weight: bold; text-align: center; color: #000000; font-size: 30rpx; border-bottom: 1px solid #ddd;">
长按邀请码可保存到相册
</text>
<canvas canvas-id="saveCanvas"
style="position: fixed; left: -9999px; width: 240px; height: 240px;"></canvas>
<view class="btns">
<view class="btn" @click="logout">
退出登录
</view>
<view class="btn" @click="changePassword">
修改密码
</view>
</view>
</view>
<uni-popup ref="alertDialog" type="dialog">
<uni-popup-dialog :type="msgType" cancelText="关闭" confirmText="同意" title="通知" content="您确认要退出登录吗"
@confirm="dialogConfirm" @close="dialogClose"></uni-popup-dialog>
</uni-popup>
</view>
</template>
<script>
import {
getStorageWithExpiry,
setStorageWithExpiry
} from "../../utils/auth";
import request from '../../utils/request';
import config from '@/config'
const UQRCode = require('uqrcodejs');
import headersVue from "@/components/header/headers.vue";
export default {
name: "UserInfo",
components: {
headersVue
},
data() {
return {
customInfo: {},
defaultAvatar: require('@/static/icons/avatar.png'),
msgType: 'success',
shareUrl: config.shareUrl,
}
},
mounted() {
this.getCustomInfo()
},
methods: {
changePassword() {
uni.navigateTo({
url: '/pages/Login/modify'
})
},
dialogConfirm() {
uni.clearStorageSync();
uni.reLaunch({
url: '/pages/Login/login'
})
},
dialogClose() {},
logout() {
this.$refs.alertDialog.open()
},
getCustomInfo() {
let roleNames = getStorageWithExpiry("roleNames")
if (!roleNames) {
request({
url: '/inspection/util/getRoleName',
method: 'get'
}).then(res => {
roleNames = res.data
setStorageWithExpiry("roleNames", roleNames)
})
}
const data = getStorageWithExpiry("userInfo")
if (!data || !data.uniqueCode) {
request({
url: '/inspectionStaff/get',
method: 'get',
params: {
id: uni.getStorageSync('userId')
}
}).then(res => {
this.customInfo = res.data
if (this.customInfo) {
setStorageWithExpiry("userInfo", this.customInfo)
this.generateUniCode(this.customInfo.uniqueCode)
if (this.customInfo.avatar) {
this.customInfo.avatar = config.baseImageUrl + this.customInfo.avatar
}
this.customInfo.roleNames = roleNames
}
})
} else {
this.customInfo = data
this.generateUniCode(this.customInfo.uniqueCode)
}
},
handleBack() {
uni.navigateBack()
},
generateUniCode(code) {
this.$nextTick(() => {
// 获取uQRCode实例
const qr = new UQRCode();
// 设置二维码内容
qr.data = this.shareUrl + code;
// 设置二维码大小必须与canvas设置的宽高一致
qr.size = 200;
// 调用制作二维码方法
qr.make();
// 获取canvas上下文
const canvasContext = uni.createCanvasContext('qrcode', this); // 如果是组件this必须传入
// 设置uQRCode实例的canvas上下文
qr.canvasContext = canvasContext;
// 调用绘制方法将二维码图案绘制到canvas上
qr.drawCanvas();
})
},
// 弹窗提示
saveQRCode() {
uni.showModal({
title: '提示',
content: '确定要保存邀请码到相册吗?',
success: (res) => {
if (res.confirm) {
this.doSaveQRCode();
}
}
});
},
// 保存邀请码
async doSaveQRCode() {
uni.showLoading({
title: '保存中...',
mask: true
});
try {
// 获取原始二维码图片路径
const tempPath = await this.getCanvasTempPath('qrcode');
// 创建一个带留白的新canvas
const paddedPath = await this.createPaddedImage(tempPath);
// 保存带留白的图片
await this.saveToAlbum(paddedPath);
uni.showToast({
title: '保存成功',
icon: 'success'
});
} catch (err) {
console.error('保存失败:', err);
uni.showToast({
title: '保存失败: ' + (err.errMsg || '未知错误'),
icon: 'none',
duration: 3000
});
} finally {
uni.hideLoading();
}
},
getCanvasTempPath(canvasId) {
return new Promise((resolve, reject) => {
uni.canvasToTempFilePath({
canvasId: canvasId,
success: resolve,
fail: reject
}, this);
});
},
createPaddedImage(tempPath) {
return new Promise((resolve, reject) => {
const padding = 20; // 留白大小单位px
const qrSize = 200; // 二维码原始大小
const canvasSize = qrSize + padding * 2; // 带留白的总大小
const nameHeight = 30; // 姓名区域高度
const totalHeight = canvasSize + nameHeight; // 总高度(二维码 + 姓名)
const ctx = uni.createCanvasContext('saveCanvas', this);
// 1. 绘制白色背景(扩展到包含姓名区域)
ctx.setFillStyle('#ffffff');
ctx.fillRect(0, 0, canvasSize, totalHeight);
// 2. 绘制姓名(居中显示)
ctx.setFontSize(16); // 字体大小
ctx.setFillStyle('#000000'); // 字体颜色
ctx.setTextAlign('center'); // 水平居中
console.log('当前信息', this.customInfo);
ctx.fillText(this.customInfo.nickname || '未设置姓名', canvasSize / 2, nameHeight - 5);
// 3. 绘制二维码(在姓名下方)
ctx.drawImage(tempPath.tempFilePath, padding, nameHeight, qrSize, qrSize);
ctx.draw(false, () => {
setTimeout(() => {
this.getCanvasTempPath('saveCanvas')
.then(resolve)
.catch(reject);
}, 300);
});
});
},
saveToAlbum(filePath) {
return new Promise((resolve, reject) => {
uni.saveImageToPhotosAlbum({
filePath: filePath.tempFilePath,
success: resolve,
fail: (err) => {
// 处理权限问题
if (err.errMsg.includes('auth')) {
uni.showModal({
title: '提示',
content: '需要相册权限才能保存图片',
success: (res) => {
if (res.confirm) {
uni.openSetting();
}
}
});
}
reject(err);
}
});
});
},
}
}
</script>
<style scoped lang="scss">
.top-heder {
width: 100%;
height: 88px;
background: white;
display: flex;
justify-content: space-between;
align-items: center;
box-sizing: border-box;
padding: 5px 15px;
padding-top: 45px;
}
.t-left {
width: 10%;
}
.c-title {
font-weight: bold;
font-size: 18px;
}
.body {
border-top: 1px solid #ddd;
padding: 20rpx 32rpx;
}
.formItem {
box-sizing: border-box;
padding: 40rpx 0;
display: flex;
align-items: center;
justify-content: space-between;
column-gap: 20rpx;
}
.formIcon {
width: 44rpx;
height: 44rpx;
}
.formLabel {
font-size: 32rpx;
color: #333333;
}
.formValue {
flex: 1;
width: 0;
text-align: right;
font-size: 32rpx;
color: #999999;
}
.formBtn {
width: 24rpx;
height: 24rpx;
}
.avatar {
width: 108rpx;
height: 108rpx;
}
.btn {
width: 520rpx;
height: 80rpx;
border-radius: 40rpx 40rpx 40rpx 40rpx;
border: 1rpx solid #999999;
margin: 60rpx auto;
display: flex;
align-items: center;
justify-content: center;
font-size: 32rpx;
color: #999999;
}
.btns {
display: flex;
justify-content: space-between;
gap: 20px;
}
</style>