HTML部分
<div class="user-img" @click="editUserImg"><image style="height: 128rpx;width: 128rpx;border-radius: 999px;margin-right: 10px;":src="userInfo?.userImg" mode="scaleToFill" /></div>
TS部分
用户接口类型
interface User {id: number;userName: string;userImg: string;userPhone: string;userAddress: string;authenticated?: boolean;
}const userInfo = ref<User>()
具体代码
//修改用户信息
const updateUserInfo = () => {loading.value = trueconsole.log('修改用户信息', userInfo.value)http?.request({url: "api/User/updateUserInfoByOpenId",method: 'POST',data: {id: userInfo.value!.id,name: userInfo.value!.userName,address: userInfo.value!.userAddress,phone: userInfo.value!.userPhone,headshot: userInfo.value!.userImg,openId: uni.getStorageSync('openid')}}).then((res: any) => {if (res.code == 200) {uni.showToast({title: '修改成功!',icon: 'success'})getUserInfoByToken(uni.getStorageSync('openid'))} else {uni.showToast({title: '修改失败!',icon: 'error'})}}).catch((err: any) => {console.log(err)uni.showToast({title: '网络错误!',icon: 'error'})}).finally(() => {loading.value = false})editState.value = false
}//修改用户头像
const editUserImg = () => {console.log('修改用户头像')//@ts-ignorewx.chooseMedia({count: 1,mediaTypes: ['image'],sourceType: ['album', 'camera'],sizeType: 'compressed',camera: 'front',success: (res: any) => {loading.value = trueconst { tempFiles } = resconst tempUserImg = tempFiles[0]cutImgToSquare(tempUserImg.tempFilePath)},fail: (err: any) => {console.log("调用失败", err)},complete: (res: any) => {console.log("调用完成", res)}})
}//将用户图片自动剪切成正方形
const cutImgToSquare = (imgPath: string) => {//@ts-ignorewx.createSelectorQuery().select('#canvas').fields({ node: true, size: true }).exec((res: any) => {const canvas = res[0].nodeconst ctx = canvas.getContext('2d')const image = canvas.createImage()image.onload = () => {const size = Math.min(image.width, image.height)canvas.width = sizecanvas.height = sizectx.clearRect(0, 0, canvas.width, canvas.height)ctx.drawImage(image, (image.width - size) / 2, (image.height - size) / 2, size, size, 0, 0, size, size)//@ts-ignorewx.canvasToTempFilePath({canvas,success: (res: any) => {console.log("调用成功", res)//上传文件到服务器uploadUserImg(res)},fail: (err: any) => {console.log("调用失败", err)loading.value = falseuni.showToast({title: '图片上传失败!',icon: 'error'})},complete: (res: any) => {console.log("调用完成", res)}})}image.src = imgPath})
}//将文件上传到服务器
const uploadUserImg = (file: any) => {//@ts-ignorewx.uploadFile({url: uploadImg,filePath: file.tempFilePath,name: 'file',success: (res: any) => {const data = JSON.parse(res.data)if (data.code == 200) {console.log("图片路径", data.data.filePath)userInfo.value!.userImg = data.data.filePatheditState.value = true} else {uni.showToast({title: '上传失败!',icon: 'error'})}loading.value = false},fail: (err: any) => {console.log("上传失败", err)loading.value = falseuni.showToast({title: '上传失败!',icon: 'error'})},complete: (res: any) => {console.log("上传完成", res)}})
}
注意:这里上传的具体服务器是我自己的服务器,这里要把uploadUserImg中的uploadImg改成自己的接口地址,不会写文件传输的可以看我之前的文章
window下的:Java基于springboot上传文件(Windows系统)-CSDN博客
Linux下的:Java基于springboot上传文件(Linux系统)-CSDN博客
完整代码
<template><div class="header"><div class="goback" @click="goback"><image style="height: 3vh;" src="../../static/article/goback.png" mode="heightFix" /></div><div class="user-img" @click="editUserImg"><image style="height: 128rpx;width: 128rpx;border-radius: 999px;margin-right: 10px;":src="userInfo?.userImg" mode="scaleToFill" /></div></div><div class="bodyer"><div class="user-info"><view class="user-title"><view><image style="height: 32px;width: 32px;margin-right: 0.5em;"src="../../static/userinfo/user-info-title.png" /></view><view style="font-size: 18px;font-weight: bold;">用户信息</view></view><view class="user-info-box"><view class="user-info-item"><view style="display: flex;align-items: center;"><view class="decoration-blue"></view><view style="font-size: 15px;">用户名称</view></view><view class="base-info-item" v-if="!editState">{{ userInfo?.userName }}</view><view class="base-info-item" v-if="editState"><input v-model="userInfo!.userName" placeholder="请输入用户名" /></view></view><view class="user-info-item"><view style="display: flex;align-items: center;"><view class="decoration-blue"></view><view style="font-size: 15px;">手机号</view></view><view class="base-info-item" v-if="!editState">{{ userInfo?.userPhone == null ? '未绑定' :userInfo?.userPhone }}</view><view class="base-info-item" v-if="editState"><input v-model="userInfo!.userPhone" placeholder="绑定手机号" /></view></view><view class="user-info-item"><view style="display: flex;align-items: center;"><view class="decoration-blue"></view><view style="font-size: 15px;">居住地址</view></view><view class="base-info-item" v-if="!editState">{{ userInfo?.userAddress == null ? '未填写' :userInfo?.userAddress }}</view><view class="base-info-item" v-if="editState"><input v-model="userInfo!.userAddress" placeholder="请输入居住地址" /></view></view></view><!-- <view class="authenticated"><view @click.stop="goAuthenticated" class="goingauthenticated" v-if="!userInfo?.authenticated"><text style="font-size: 14px;margin-right: 0.5em;">去实名认证</text><image style="height: 16px;" src="../../static/seekhelp/goingseek.png" mode="heightFix" /></view></view> --></div></div><div class="footer"><view @click="editState = true" v-if="!editState">修改个人信息</view><view @click="updateUserInfo" v-if="editState">保存</view><view @click="logout">退出登录</view></div><canvas v-show="false" id="canvas" type="2d" style="position: absolute;z-index: -999;opacity: 0;" /><qgy-drawer ref="editAddressDrawer"></qgy-drawer><div class="back2"></div><qgy-loading style="position: absolute;top: 0px;left: 0px;" v-show="loading"></qgy-loading>
</template><script setup lang="ts">
import { Http } from '@/util/http';
import { inject, onMounted, ref } from 'vue';const http: Http | undefined = inject('$http');
const loading = ref(false);
const uploadImg: string | undefined = inject('$uploadImg');//修改状态
const editState = ref(false)onMounted(() => {getUserInfoByToken(uni.getStorageSync('openid'))
})//从服务器中获取用户信息
const getUserInfoByToken = (openid: string) => {loading.value = trueconsole.log("openid", openid)//从后端获得用户信息http?.request({url: 'api/User/findUserInfoByOpenId?openId=' + openid,method: 'GET'}).then((res: any) => {console.log(res)if (res.code == 200) {userInfo.value = {id: res.data.id,userName: res.data.name,userAddress: res.data.address,userImg: res.data.headshot,userPhone: res.data.phone}} else {uni.showToast({title: "网络错误!",duration: 2000,icon: 'error'})}}).catch((err: any) => {console.log(err)uni.showToast({title: '网络错误!',duration: 2000,icon: 'error'})}).finally(() => {loading.value = false})uni.setStorageSync('token', '孩子们我们现在没有token!')
}//退出登录
const logout = () => {console.log('退出登录')uni.clearStorageSync()uni.showToast({title: '退出成功',duration: 2000,icon: 'success'});setTimeout(() => {goback()}, 2000)
}interface User {id: number;userName: string;userImg: string;userPhone: string;userAddress: string;authenticated?: boolean;
}const userInfo = ref<User>()
//页面是否处于修改状态
const pageState = ref<boolean>(false)onMounted(() => {//从token中获取用户信息userInfo.value = {id: 0,userName: '乔冠宇',userImg: '../../static/my/default.png',userPhone: '15353365292',userAddress: '陕西省咸阳市秦都区人民路财富中心一号楼三单元114514号',authenticated: false}
})//返回上一页
const goback = () => {uni.navigateBack({fail: (err) => {console.log(err)uni.reLaunch({ url: '/pages/index/index' })}})
}//去实名认证
// const goAuthenticated = () => {
// console.log('去实名认证')
// userInfo.value!.authenticated = true
// }//修改用户信息
const updateUserInfo = () => {loading.value = trueconsole.log('修改用户信息', userInfo.value)http?.request({url: "api/User/updateUserInfoByOpenId",method: 'POST',data: {id: userInfo.value!.id,name: userInfo.value!.userName,address: userInfo.value!.userAddress,phone: userInfo.value!.userPhone,headshot: userInfo.value!.userImg,openId: uni.getStorageSync('openid')}}).then((res: any) => {if (res.code == 200) {uni.showToast({title: '修改成功!',icon: 'success'})getUserInfoByToken(uni.getStorageSync('openid'))} else {uni.showToast({title: '修改失败!',icon: 'error'})}}).catch((err: any) => {console.log(err)uni.showToast({title: '网络错误!',icon: 'error'})}).finally(() => {loading.value = false})editState.value = false
}//修改用户头像
const editUserImg = () => {console.log('修改用户头像')//@ts-ignorewx.chooseMedia({count: 1,mediaTypes: ['image'],sourceType: ['album', 'camera'],sizeType: 'compressed',camera: 'front',success: (res: any) => {loading.value = trueconst { tempFiles } = resconst tempUserImg = tempFiles[0]cutImgToSquare(tempUserImg.tempFilePath)},fail: (err: any) => {console.log("调用失败", err)},complete: (res: any) => {console.log("调用完成", res)}})
}//将用户图片自动剪切成正方形
const cutImgToSquare = (imgPath: string) => {//@ts-ignorewx.createSelectorQuery().select('#canvas').fields({ node: true, size: true }).exec((res: any) => {const canvas = res[0].nodeconst ctx = canvas.getContext('2d')const image = canvas.createImage()image.onload = () => {const size = Math.min(image.width, image.height)canvas.width = sizecanvas.height = sizectx.clearRect(0, 0, canvas.width, canvas.height)ctx.drawImage(image, (image.width - size) / 2, (image.height - size) / 2, size, size, 0, 0, size, size)//@ts-ignorewx.canvasToTempFilePath({canvas,success: (res: any) => {console.log("调用成功", res)//上传文件到服务器uploadUserImg(res)},fail: (err: any) => {console.log("调用失败", err)loading.value = falseuni.showToast({title: '图片上传失败!',icon: 'error'})},complete: (res: any) => {console.log("调用完成", res)}})}image.src = imgPath})
}//将文件上传到服务器
const uploadUserImg = (file: any) => {//@ts-ignorewx.uploadFile({url: uploadImg,filePath: file.tempFilePath,name: 'file',success: (res: any) => {const data = JSON.parse(res.data)if (data.code == 200) {console.log("图片路径", data.data.filePath)userInfo.value!.userImg = data.data.filePatheditState.value = true} else {uni.showToast({title: '上传失败!',icon: 'error'})}loading.value = false},fail: (err: any) => {console.log("上传失败", err)loading.value = falseuni.showToast({title: '上传失败!',icon: 'error'})},complete: (res: any) => {console.log("上传完成", res)}})
}
</script><style scoped>
.header {height: 25vh;width: 100vw;position: relative;display: flex;justify-content: center;align-items: center;
}.bodyer {height: fit-content;width: 100vw;
}.user-img {position: relative;top: 3vh;
}.footer {width: 100vw;font-size: 13px;text-align: center;display: flex;justify-content: space-around;padding: 2vh 0px;color: gray;
}.footer>view {padding: 5px 10px;
}.goback {position: absolute;top: 5vh;left: 5vw;
}.user-info {width: 90vw;margin: auto;height: fit-content;padding: 10px;background-color: #ffffff;border-radius: 30rpx;
}.user-title {display: flex;align-items: center;border-bottom: 2px solid #f4f7fc;
}.base-info-item {background-color: #f6f9ff;border-radius: 2px;padding: 5px 10px;margin-top: 5px;font-size: 14px;
}.user-info-item {margin: 10px 0px;
}.goingauthenticated {background-color: #ffffff;color: #F56C6C;padding: 5px 10px;border-radius: 10px 10px 0px 0px;display: flex;align-items: center;width: fit-content;margin-left: auto;
}
</style>