【UniApp开发小程序】”我的“界面实现+“信息修改“界面实现+登出账号实现+图片上传组件【基于若依管理系统开发】

文章目录

  • 界面实现
    • 界面效果
      • 我的
      • 修改信息
    • “我的”界面实现
      • api
      • 页面
        • 退出账号
        • 让自我介绍只显示一行,结尾多余的字使用...代替
        • 跳转到信息修改页面
    • 信息修改界面实现
      • api
      • 页面
        • 动态给对象设置属性名和值
        • 修改密码
        • 图片上传组件
  • 部分后端代码
    • Controller

界面实现

界面效果

我的

在这里插入图片描述

修改信息

修改信息

在这里插入图片描述
在这里插入图片描述

学校选择

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
校区选择

在这里插入图片描述
性别设置

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

“我的”界面实现

api

login.js

import httpRequest from '@/utils/request'

// 账号退出方法
export function logout() {
  return httpRequest.request({
    url: '/logout',
    method: 'post'
  })
}

logout方法用来向后端发起请求,让后端删除Redis中的登录token

在这里插入图片描述

在这里插入图片描述

user.js

import httpRequest from '@/utils/request'

// 查询用户个人信息Vo
export function getUserProfileVo() {
  return httpRequest.request({
    url: '/system/user/profile/vo',
    method: 'get'
  })
}



// 用户头像上传
export function uploadAvatar(data) {
  return httpRequest.request({
    url: '/system/user/profile/avatar',
    method: 'post',
    data: data
  })
}

页面

<template>
	<view class="container">

		<!-- 头像、昵称展示 -->
		<view class="userDisplay">
			<view class="avatar" @click="this.avatarChangeShow=true">
				<u--image :src="userInfo.avatar" width="60px" height="60px" @click="click" shape="circle"></u--image>
			</view>
			<view class="nameView">
				<view>
					<view style="font-weight: bold;font-size: 36rpx;color: #ffffff;">{{userInfo.nickName}}</view>
					<view style="font-size: 30rpx;display: flex;margin-top: 10rpx;color: #ffffff;">
						<text class="iconfont" style="margin-right: 7rpx;color: #ffffff;">&#xe654;</text>
						<text class="selfIntroductionText"> {{userInfo.selfIntroduction}}</text>
					</view>
				</view>
			</view>
		</view>

		<view class="userMessage">
			<view style="font-size: 18px;font-weight: bold;	padding: 20rpx;">
				<text>我的信息</text>
			</view>
			<u-cell-group>
				<u-cell name="userName" :value="userInfo.userName" :isLink="true"
					@click="editMessage('userName',userInfo.userName,'用户名')">
					<view slot="title" class="u-slot-title">
						<text class="iconfont" style="margin-right: 7rpx;">&#xe605;</text>
						<text class="u-cell-text">用户名</text>
					</view>
				</u-cell>
				<u-cell name="nickName" :value="userInfo.nickName" :isLink="true"
					@click="editMessage('nickName',userInfo.nickName,'昵称')">
					<view slot="title" class="u-slot-title">
						<text class="iconfont" style="margin-right: 7rpx;">&#xe605;</text>
						<text class="u-cell-text">昵称</text>
					</view>
				</u-cell>
				<u-cell name="avatar" :isLink="true" @click="editMessage('avatar',userInfo.avatar,'头像')">
					<view slot="title" class="u-slot-title">
						<text class="iconfont" style="margin-right: 7rpx;">&#xe60d;</text>
						<text class="u-cell-text">头像</text>
					</view>
				</u-cell>
				<u-cell name="schoolName" :value="userInfo.schoolName" :isLink="true"
					@click="editMessage('schoolId',userInfo.schoolName,'大学',userInfo.schoolId)">
					<view slot="title" class="u-slot-title">
						<text class="iconfont" style="margin-right: 7rpx;">&#xe916;</text>
						<text class="u-cell-text">大学</text>
					</view>
				</u-cell>
				<u-cell name="campusName" :value="userInfo.campusName" :isLink="true"
					@click="editMessage('campusId',userInfo.campusName,'校区',userInfo.campusId,userInfo.schoolId)">
					<view slot="title" class="u-slot-title">
						<text class="iconfont" style="margin-right: 7rpx;">&#xe628;</text>
						<text class="u-cell-text">校区</text>
					</view>
				</u-cell>
				<u-cell name="sex" :value="sexName" :isLink="true" @click="editMessage('sex',userInfo.sex,'性别')">
					<view slot="title" class="u-slot-title">
						<text class="iconfont" style="margin-right: 7rpx;">&#xe614;</text>
						<text class="u-cell-text">性别</text>
					</view>
				</u-cell>
				<u-cell name="email" :value="userInfo.email" :isLink="true"
					@click="editMessage('email',userInfo.email,'邮箱')">
					<view slot="title" class="u-slot-title">
						<text class="iconfont" style="margin-right: 7rpx;">&#xe672;</text>
						<text class="u-cell-text">邮箱</text>
					</view>
				</u-cell>
				<u-cell name="contactInformation" :isLink="true"
					@click="editMessage('contactInformation',userInfo.contactInformation,'联系方式')">
					<view slot="title" class="u-slot-title">
						<text class="iconfont" style="margin-right: 7rpx;">&#xe637;</text>
						<text class="u-cell-text">联系方式</text>
					</view>
				</u-cell>
				<u-cell name="selfIntroduction" :isLink="true"
					@click="editMessage('selfIntroduction',userInfo.selfIntroduction,'自我介绍')">
					<view slot="title" class="u-slot-title">
						<text class="iconfont" style="margin-right: 7rpx;">&#xe654;</text>
						<text class="u-cell-text">自我介绍</text>
					</view>
				</u-cell>
				<u-cell name="password" :isLink="true" @click="editMessage('password','-1','修改密码')">
					<view slot="title" class="u-slot-title">
						<text class="iconfont" style="margin-right: 7rpx;">&#xe603;</text>
						<text class="u-cell-text">修改密码</text>
					</view>
				</u-cell>
				<u-cell :isLink="true" @click="logout()">
					<view slot="title" class="u-slot-title">
						<text class="iconfont" style="margin-right: 7rpx;">&#xe659;</text>
						<text class="u-cell-text">退出账号</text>
					</view>
				</u-cell>
			</u-cell-group>
		</view>

	</view>
</template>

<script>
	import {
		logout
	} from "@/api/login";
	import {
		getUserProfileVo
	} from "@/api/user";

	export default {

		data() {
			return {
				userInfo: {
					avatar: '',
					nickName: "你好呀",
					userName: "admin",
					schoolName: "XX大学",
					campusName: "XX学院",
					sex: 0,
					selfIntroduction: "自我介绍,打撒活动啊速宏达搜好滴傻大搜到阿斯顿撒旦好骚",
					contactInformation: "联系方式",
					email: "32136712361@qq.com"
				},
				sexName: '其他',
			}
		},
		created() {
			this.getUserProfile();
		},
		methods: {
			editMessage(editKey, currentValue, editName, valueId = 0, schoolId = 0) {
				uni.navigateTo({
					url: "/pages/my/prodileEdit?editKey=" + editKey + "&currentValue=" + currentValue +
						"&editName=" + editName + "&valueId=" + valueId + "&schoolId=" + schoolId
				})
			},
			/**
			 * 登出账号
			 */
			logout() {
				// console.log("退出账号:")
				logout().then(res => {
					// console.log("退出账号:" + JSON.stringify(res));
					// 清除所有缓存
					uni.clearStorageSync();
					// 跳转到登录页
					uni.redirectTo({
						url: "/pages/login/login"
					})
				})
			},
			/**
			 * 获取用户信息
			 */
			getUserProfile() {
				getUserProfileVo().then(res => {
					// console.log("getUserProfile:" + JSON.stringify(res));
					this.userInfo = res.data;
					this.sexName = this.getSexName(this.userInfo.sex);
					// console.log("this.userInfo.sex:" + this.userInfo.sex + ",this.sexName:" + this.sexName);
					// console.log("this.userInfo:" + JSON.stringify(this.userInfo));
				})
			},
			getSexName(type) {
				if (type == 0) {
					return "男";
				} else if (type == 1) {
					return "女";
				} else if (type == 2) {
					return "其他";
				}
			}
		}
	}
</script>

<style lang="scss">
	.container {
		background: #F4F5F7;
		min-height: 100vh;

		.userDisplay {
			display: flex;
			padding: 20rpx;
			background: #2B92FF;

			.avatar {
				display: flex;
				justify-content: center;
				align-items: center;
				margin-right: 30rpx;
				background: #ffffff;
				border-radius: 50%;
				padding: 3px;
			}

			.nameView {
				display: flex;
				justify-content: center;
				align-items: center;

				.selfIntroductionText {
					overflow: hidden;
					text-overflow: ellipsis;
					display: -webkit-box;
					/* 显示1行 */
					-webkit-line-clamp: 1;
					-webkit-box-orient: vertical;
				}
			}
		}

		.userMessage {
			margin: 30rpx 30rpx;
			background: #FFFFFF;
			border-radius: 20rpx;
		}
	}
</style>

退出账号

退出账号需要做三件事,分别是:

  1. 调用后端接口,让其清除Redis中的token
  2. 小程序清除客户端的token缓存
  3. 重新跳转到登录页面
/**
* 登出账号
 */
logout() {
	logout().then(res => {
		// 清除所有缓存
		uni.clearStorageSync();
		// 跳转到登录页
		uni.redirectTo({
			url: "/pages/login/login"
		})
	})
},

让自我介绍只显示一行,结尾多余的字使用…代替

.selfIntroductionText {
	overflow: hidden;
	text-overflow: ellipsis;
	display: -webkit-box;
	/* 显示1行 */
	-webkit-line-clamp: 1;
	-webkit-box-orient: vertical;
}

在这里插入图片描述

跳转到信息修改页面

editMessage(editKey, currentValue, editName, valueId = 0, schoolId = 0) {
	uni.navigateTo({
		url: "/pages/my/prodileEdit?editKey=" + editKey + "&currentValue=" + currentValue +
			"&editName=" + editName + "&valueId=" + valueId + "&schoolId=" + schoolId
	})
},

所有信息的修改都在prodileEdit页面完成,跳转的时候需要携带一些参数,prodileEdit页面根据路由携带的参数来判断是修改什么信息,进而执行不同的代码

valueId = 0指的是,如果valueId没有接收到传值,就赋予默认值0

信息修改界面实现

api

user.js

import httpRequest from '@/utils/request'

// 修改用户个人信息
export function updateUserProfile(data) {
	return httpRequest.request({
		url: '/system/user/profile',
		method: 'put',
		data: data
	})
}

// 用户密码重置
export function updateUserPwd(oldPassword, newPassword) {
	const data = {
		oldPassword,
		newPassword
	}
	return httpRequest.request({
		url: '/system/user/profile/updatePwd',
		method: 'put',
		data: data
	})
}

school.js

import httpRequest from '@/utils/request'

// 查询学校列表
export function listSchool(query) {
	return httpRequest.request({
		url: '/market/school/list',
		method: 'post',
		data: query
	})
}

campus.js

import httpRequest from '@/utils/request'

// 查询校区列表
export function listCampus(query) {
	return httpRequest.request({
		url: '/market/campus/list',
		method: 'post',
		data: query
	})
}

logout方法在上面有了,这里就不重复写了,两个页面都调用了账号退出的逻辑,按理说应该单独写一个工具js来封装一个方法的,这样不同页面直接调用即可,可以减少代码的冗余,但是我看只有两个页面调用,而且代码量也不多,于是就偷懒了

页面

<template>
	<view class="container">
		<u-toast ref="uToast"></u-toast>

		<!-- 设置头像 -->
		<view v-if="editUser.editKey==='avatar'">
			<imageUpload v-model="picList"></imageUpload>
		</view>

		<!-- 设置学校 -->
		<view v-else-if="editUser.editKey==='schoolId'">
			<view style="align-items: center;background:#2B92FF ;padding: 20rpx;border-radius: 10rpx;">
				<view
					style="border: 2rpx solid white ;border-radius: 10rpx;width:100%;display: flex;align-items: center;background:#ffffff ;">
					<u-search placeholder="请输入搜索内容" v-model="schoolId" @custom="seachSchool"></u-search>
				</view>
				<view style="margin: 10px;"></view>
				<view @click="this.selectSchoolShow = true"
					style="border: 2rpx solid white ;border-radius: 10rpx;width:100%;display: flex;align-items: center;background:#ffffff ;">
					<text style="margin: 5px;width: 55px;">
						学校
					</text>
					<view
						style="padding: 0px 5px; background:#F2F2F2;border-radius: 3px;width: 100%;margin-right: 5px;">
						{{editUser.currentValue}}
					</view>
				</view>
			</view>

			<u-picker :show="selectSchoolShow" :columns="schoolOptions" keyName="name" @cancel="closeSchoolSelect"
				@confirm="confirmSchoolSelect">
			</u-picker>
		</view>

		<!-- 设置校区 -->
		<view v-else-if="editUser.editKey==='campusId'">
			<view style="align-items: center;background:#2B92FF ;padding: 20rpx;border-radius: 10rpx;">
				<view @click="this.selectCampusShow = true"
					style="border: 2rpx solid white ;border-radius: 10rpx;width:100%;display: flex;align-items: center;background:#ffffff ;">
					<text style="margin: 5px;width: 55px;">
						校区
					</text>
					<view
						style="padding: 0px 5px; background:#F2F2F2;border-radius: 3px;width: 100%;margin-right: 5px;">
						{{editUser.currentValue}}
					</view>
				</view>
			</view>

			<u-picker :show="selectCampusShow" :columns="campusOptions" keyName="name" @cancel="closeCampusSelect"
				@confirm="confirmCampusSelect">
			</u-picker>
		</view>

		<!-- 设置性别 -->
		<view v-else-if="editUser.editKey==='sex'">
			<u-radio-group v-model="sexName" placement="column">
				<u-radio :customStyle="{marginBottom: '8px'}" v-for="(item, index) in sexList" :key="index"
					:label="item.name" :name="item.name" @change="sexChange">
				</u-radio>
			</u-radio-group>
		</view>

		<!-- 修改密码 -->
		<view v-else-if="editUser.editKey==='password'">
			<u--form :model="editPasswordForm" ref="editPasswordForm">
				<u-form-item label="输入原密码" :prop="editPasswordForm.oldPassword" borderBottom="true" labelWidth="80">
					<u-input v-model="editPasswordForm.oldPassword" password />
				</u-form-item>
				<u-form-item label="输入新密码" :prop="editPasswordForm.newPassword1" borderBottom="true" labelWidth="80">
					<u-input v-model="editPasswordForm.newPassword1" password />
				</u-form-item>
				<u-form-item label="再次输入新密码" :prop="editPasswordForm.newPassword2" borderBottom="true" labelWidth="80">
					<u-input v-model="editPasswordForm.newPassword2" password />
				</u-form-item>
			</u--form>
			<view style="margin: 10px;"></view>
			<u-button type="primary" @click="resetPassword" style="width: 90%;">提交</u-button>
		</view>

		<!-- 设置其他信息 -->
		<view v-else>
			<u--form :model="editUser" ref="uForm">
				<u-form-item :label="editUser.editName" :prop="editUser.editKey" borderBottom="true" labelWidth="80">
					<u--textarea v-if="editUser.editKey=='contactInformation'||editUser.editKey=='selfIntroduction'"
						v-model="editUser.currentValue" placeholder="请输入内容" autoHeight count
						maxlength='250'></u--textarea>
					<u-input v-else v-model="editUser.currentValue" />
				</u-form-item>
			</u--form>
		</view>

		<view style="margin: 10px;" v-if="editUser.editKey!='password'"></view>
		<u-button type="primary" @click="updateUserProfile" style="width: 90%;"
			v-if="editUser.editKey!='password'">提交</u-button>

		</u-picker>
	</view>
</template>

<script>
	import {
		updateUserProfile,
		updateUserPwd
	} from "@/api/user";
	import {
		listSchool
	} from "@/api/schoolMessage/school.js";
	import {
		listCampus
	} from "@/api/schoolMessage/campus.js";
	import {
		logout
	} from "@/api/login";
	import imageUpload from "@/components/ImageUpload/ImageUpload.vue";

	export default {
		components: {
			imageUpload
		},
		data() {
			return {
				editUser: {},
				/// 学校选择
				selectSchoolShow: false,
				schoolOptions: [],
				// 搜索学校名称
				schoolId: '',
				schoolQueryParams: {
					name: ''
				},
				/// 校区选择
				campusId: '',
				campusOptions: [],
				selectCampusShow: false,
				/// 性别选择
				sexList: [{
						name: '男',
						disabled: false
					},
					{
						name: '女',
						disabled: false
					},
					{
						name: '其他',
						disabled: false
					}
				],
				sexName: "其他",
				// 图片集合
				picList: [],
				/// 修改密码
				editPasswordForm: {
					oldPassword: '',
					newPassword1: '',
					newPassword2: ''
				}

			}
		},
		created() {

		},
		// 获取路由的参数
		onLoad(e) {
			// console.log("e:" + JSON.stringify(e));
			if (e) {
				this.editUser = {
					editKey: e.editKey,
					currentValue: e.currentValue,
					editName: e.editName,
					valueId: e.valueId,
					schoolId: e.schoolId
				};
				if (e.editKey === 'schoolId') {
					this.getSchoolList();
				} else if (e.editKey === 'campusId') {
					this.getCampusList();
				} else if (e.editKey === 'sex') {
					this.sexName = this.getSexName(e.currentValue);
				} else if (e.editKey === 'avatar') {
					this.picList.push(e.currentValue);
					// console.log("this.picList:" + JSON.stringify(this.picList));
				}
			}
		},
		methods: {
			updateUserProfile() {
				let updateUser = {};
				if (this.editUser.editKey === 'schoolId' || this.editUser.editKey === 'campusId') {
					updateUser = {
						[this.editUser.editKey]: this.editUser.valueId
					};
				} else if (this.editUser.editKey === 'avatar') {
					updateUser = {
						[this.editUser.editKey]: this.picList[0]
					};
				} else {
					updateUser = {
						[this.editUser.editKey]: this.editUser.currentValue
					};
				}
				// console.log("updateUser:" + JSON.stringify(updateUser));
				updateUserProfile(updateUser).then(res => {
					// 修改成功,返回之前的页面
					uni.reLaunch({
						url: "/pages/my/my"
					})
					this.$refs.uToast.show({
						type: 'success',
						message: "修改成功"
					})
				}).catch(res => {
					// console.log("响应出错");
					// console.log("res:" + JSON.stringify(res));
					this.$refs.uToast.show({
						type: 'error',
						message: res.msg
					})
				})
			},
			/**
			 * 修改密码
			 */
			resetPassword() {
				let isSame = this.editPasswordForm.newPassword1 === this.editPasswordForm.newPassword2;
				if (isSame == false) {
					this.$refs.uToast.show({
						type: 'error',
						message: '两次输入的新密码不同,请重新输入'
					})
				} else if (this.editPasswordForm.newPassword1.length < 6) {
					this.$refs.uToast.show({
						type: 'error',
						message: '新密码长度小于6个字符,请重新输入'
					})
				} else {
					updateUserPwd(this.editPasswordForm.oldPassword, this.editPasswordForm.newPassword1).then(res => {
						this.$refs.uToast.show({
							type: 'success',
							message: '密码修改成功,即将退出账号,请重新登录'
						})
						setTimeout(() => {
							this.logout();
						}, 2000)
					}).catch(res => {
						this.$refs.uToast.show({
							type: 'error',
							message: res.msg
						})
					})
				}
			},
			getSchoolList() {
				listSchool(this.schoolQueryParams).then(res => {
					this.schoolOptions = [];
					this.schoolOptions.push(res.rows);
					// console.log("this.schoolOptions:" + JSON.stringify(this.schoolOptions));
				})
			},
			/**
			 * 搜索学校
			 */
			seachSchool() {
				this.schoolQueryParams.name = this.schoolId;
				// console.log("this.schoolQueryParams:"+JSON.stringify(this.schoolQueryParams))
				this.getSchoolList();
				this.selectSchoolShow = true;
			},
			/**
			 * 关闭学校选择
			 */
			closeSchoolSelect() {
				// console.log("closeSchoolSelect")
				this.selectSchoolShow = false;
			},
			/**
			 * 确定选择学校
			 */
			confirmSchoolSelect(e) {
				this.editUser.valueId = e.value[0].id;
				this.editUser.currentValue = e.value[0].name;
				// console.log("this.editUser.schoolId:" + this.editUser.schoolId);
				this.selectSchoolShow = false;
			},
			getCampusList() {
				let CampusQueryParams = {
					schoolId: this.editUser.schoolId
				}
				listCampus().then(res => {
					this.campusOptions = [];
					this.campusOptions.push(res.rows);
					// console.log("this.schoolOptions:" + JSON.stringify(this.schoolOptions));
				})
			},
			/**
			 * 关闭校区选择
			 */
			closeCampusSelect() {
				// console.log("closeSchoolSelect")
				this.selectCampusShow = false;
			},
			/**
			 * 确定选择校区
			 */
			confirmCampusSelect(e) {
				this.editUser.valueId = e.value[0].id;
				this.editUser.currentValue = e.value[0].name;
				// console.log("this.editUser.schoolId:" + this.editUser.schoolId);
				this.selectCampusShow = false;
			},
			/**
			 * 修改性别
			 */
			sexChange(e) {
				// console.log("sexChange:" + JSON.stringify(e));
				if (e == "男") {
					this.editUser.currentValue = 0;
				} else if (e == "女") {
					this.editUser.currentValue = 1;
				} else if (e == "其他") {
					this.editUser.currentValue = 2;
				}
			},
			getSexName(type) {
				if (type == 0) {
					return "男";
				} else if (type == 1) {
					return "女";
				} else if (type == 2) {
					return "其他";
				}
			},
			/**
			 * 登出账号
			 */
			logout() {
				console.log("退出账号:")
				logout().then(res => {
					console.log("退出账号:" + JSON.stringify(res));
					// 清除所有缓存
					uni.clearStorageSync();
					// 跳转到首页
					uni.redirectTo({
						url: "/pages/login/login"
					})
				})
			},

		}
	}
</script>

<style lang="scss">
	.container {
		padding: 20px;
	}
</style>

动态给对象设置属性名和值

updateUser = {
	[this.editUser.editKey]: this.editUser.valueId
};

修改密码

/**
* 修改密码
 */
resetPassword() {
	let isSame = this.editPasswordForm.newPassword1 === this.editPasswordForm.newPassword2;
	if (isSame == false) {
		this.$refs.uToast.show({
			type: 'error',
			message: '两次输入的新密码不同,请重新输入'
		})
	} else if (this.editPasswordForm.newPassword1.length < 6) {
		this.$refs.uToast.show({
			type: 'error',
			message: '新密码长度小于6个字符,请重新输入'
		})
	} else {
		updateUserPwd(this.editPasswordForm.oldPassword, this.editPasswordForm.newPassword1).then(res => {
			this.$refs.uToast.show({
				type: 'success',
				message: '密码修改成功,即将退出账号,请重新登录'
			})
			setTimeout(() => {
				this.logout();
			}, 2000)
		}).catch(res => {
			this.$refs.uToast.show({
				type: 'error',
				message: res.msg
			})
		})
	}
},

在修改密码之前,前端需要做一些数据校验,来减轻后台的工作压力,如提前将不合法的密码拦截,不让其提交。我这里只是做了最简单的校验,还可以使用正则表达式做一些复杂的密码校验,如密码必须包含英文、数字、符号

图片上传组件

<template>
	<u-upload :fileList="fileList1" @afterRead="afterRead" @delete="deletePic" name="1" multiple :maxCount="maxCount"
		:previewFullImage="true"></u-upload>
</template>

<script>
	import ossApi from "@/api/thirdParty/oss.js";
	import uuidApi from "@/utils/uuid.js"
	export default {
		name: "ImageUpload",
		props: {
			value: [String, Object, Array],
			// 图片最大上传数量
			maxCount: {
				type: Number,
				default: 1
			}
		},
		data() {
			return {
				fileList1: [],
				uploadUrl: "http://smart-scheduling-system-13184.oss-cn-beijing.aliyuncs.com",
				// 图片数量
				pictureNum: 0,
			};
		},
		created() {
			for (var i = 0; i < this.value.length; i++) {
				this.fileList1.push({
					url: this.value[i]
				});
			}

			// console.log("this.fileList1:" + JSON.stringify(this.fileList1))
		},
		methods: {
			// 删除图片
			deletePic(event) {
				this[`fileList${event.name}`].splice(event.index, 1);
				this.pictureNum--;
			},
			// 新增图片
			async afterRead(event) {
				// 当设置 multiple 为 true 时, file 为数组格式,否则为对象格式
				let lists = [].concat(event.file)
				let fileListLen = this[`fileList${event.name}`].length
				lists.map((item) => {
					this[`fileList${event.name}`].push({
						...item,
						status: 'uploading',
						message: '上传中'
					})
				})
				for (let i = 0; i < lists.length; i++) {
					const result = await this.uploadFilePromise(lists[i].url)
					let item = this[`fileList${event.name}`][fileListLen]
					this[`fileList${event.name}`].splice(fileListLen, 1, Object.assign(item, {
						status: 'success',
						message: '',
						url: result
					}))
					fileListLen++
				}
			},
			// 上传图片
			uploadFilePromise(url) {
				return new Promise((resolve, reject) => {
					let dataObj = {
						policy: '',
						signature: '',
						key: '',
						OSSAccessKeyId: '',
						dir: '',
						host: ''
					};
					ossApi.getPolicy()
						.then((response) => {
							// console.log('policy response:' + JSON.stringify(response))
							// debugger;
							dataObj.policy = response.data.policy
							dataObj.signature = response.data.signature
							dataObj.OSSAccessKeyId = response.data.accessId
							dataObj.key = response.data.dir + uuidApi.getUUID() + '_${filename}'
							dataObj.dir = response.data.dir
							dataObj.host = response.data.host
							// console.log('获取policy成功')
							let a = uni.uploadFile({
								url: this.uploadUrl,
								filePath: url,
								name: 'file',
								formData: dataObj,
								success: (res) => {
									// console.log('图片上传成功,url:' + JSON.stringify(url));
									// console.log('图片上传成功,this.fileList1:' + JSON.stringify(this
									// 	.fileList1));
									// 拼接出可以直接访问的oss图片 "http://tmp/":windows电脑的前缀 "wxfile://":安卓微信的前缀
									let picUrl = dataObj.host +
										'/' +
										dataObj.key.replace('${filename}', url.indexOf(
											"http://tmp/") != -1 ? url.replace(
											"http://tmp/", '') : url.replace(
											"wxfile://", ''));
									// 设置之后,才可以预览图片
									this.fileList1[this.fileList1.length - (this.fileList1.length -
										this.pictureNum)].url = picUrl;
									this.pictureNum++;
									let urlList = [];
									for (var i = 0; i < this.fileList1.length; i++) {
										urlList.push(this.fileList1[i].url);
									}
									this.$emit("input", urlList);
									// console.log("urlList:" + JSON.stringify(urlList))
									setTimeout(() => {
										resolve(res)
									}, 1000)
								}
							});
							resolve(true)
						})
						.catch((err) => {
							// console.log('获取policy失败')
							reject(false)
						})

				})
			},
		}
	}
</script>

<style>

</style>

OSS后端代码和讲解可以参考OSS对象存储后端实现+Vue实现图片上传【基于若依管理系统开发】

通过定义在props中定义value属性,并结合this.$emit("input", 值);方法,可以将值同步给组件v-model所绑定的变量

<imageUpload v-model="picList"></imageUpload>

注意:imageUpload 接收的属性需要是一个图片url数组

部分后端代码

后端基于若依后端管理系统开发,很多接口在系统中已经内置,或者可以直接通过系统的生成器生成出来,这里就不再贴上来,只贴部分基于系统已有接口修改而来的接口,避免读者迷惑

Controller

/**
 * 修改用户
 */
@Log(title = "个人信息", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult updateProfile(@RequestBody SysUser user) {
    LoginUser loginUser = getLoginUser();
    SysUser sysUser = loginUser.getUser();
    if (StringUtils.isNotEmpty(user.getUserName()) && !userService.checkUserNameUnique(user)) {
        return error("修改用户 '" + sysUser.getUserName() + "' 失败,用户名已存在");
    }
    if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) {
        return error("修改用户 '" + sysUser.getUserName() + "' 失败,手机号码已存在");
    }
    if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) {
        return error("修改用户 '" + sysUser.getUserName() + "' 失败,邮箱账号已存在");
    }
    user.setUserId(sysUser.getUserId());
    user.setPassword(null);
//        user.setAvatar(null);
    user.setDeptId(null);
    if (userService.updateUserProfile(user) > 0) {
        // 更新缓存用户信息
        sysUser.setUserName(user.getUserName());
        sysUser.setNickName(user.getNickName());
        sysUser.setPhonenumber(user.getPhonenumber());
        sysUser.setEmail(user.getEmail());
        sysUser.setSex(user.getSex());
        tokenService.setLoginUser(loginUser);
        return success();
    }
    return error("修改个人信息异常,请联系管理员");
}
 /**
  * 重置密码
  */
 @Log(title = "个人信息", businessType = BusinessType.UPDATE)
 @PutMapping("/updatePwd")
 public AjaxResult updatePwd(@RequestBody Map<String, String> map) {
     LoginUser loginUser = getLoginUser();
     String userName = loginUser.getUsername();
     String password = loginUser.getPassword();
     String oldPassword = map.get("oldPassword");
     String newPassword = map.get("newPassword");
     if (!SecurityUtils.matchesPassword(oldPassword, password)) {
         return error("修改密码失败,旧密码错误");
     }
     if (SecurityUtils.matchesPassword(newPassword, password)) {
         return error("新密码不能与旧密码相同");
     }
     if (userService.resetUserPwd(userName, SecurityUtils.encryptPassword(newPassword)) > 0) {
         // 更新缓存用户密码
         loginUser.getUser().setPassword(SecurityUtils.encryptPassword(newPassword));
         tokenService.setLoginUser(loginUser);
         return success();
     }
     return error("修改密码异常,请联系管理员");
 }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/43325.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Windows11的VTK安装:VS201x+Qt5/Qt6 +VTK7.1/VTK9.2.6

需要提前安装好VS2017和VS2019和Qt VS开发控件以及Qt VS-addin。 注意Qt6.2.4只能跟VTK9.2.6联合编译&#xff08;目前VTK9和Qt6的相互支持版本&#xff09;。 首先下载VTK&#xff0c;需要下载源码和data&#xff1a; Download | VTKhttps://vtk.org/download/ 然后这两个文…

1 请使用js、css、html技术实现以下页面,表格内容根据查询条件动态变化。

1.1 创建css文件&#xff0c;用于编辑style 注意&#xff1a; 1.背景颜色用ppt的取色器来获取&#xff1a; 先点击ppt的形状轮廓&#xff0c;然后点击取色器&#xff0c;吸颜色&#xff0c;然后再点击形状轮廓的其他轮廓颜色&#xff0c;即可获取到对应颜色。 2.表格间的灰色线…

什么是搜索引擎?2023 年搜索引擎如何运作?

目录 什么是搜索引擎&#xff1f;搜索引擎的原理什么是搜索引擎爬取&#xff1f;什么是搜索引擎索引&#xff1f;什么是搜索引擎检索?什么是搜索引擎排序&#xff1f; 搜索引擎的目的是什么&#xff1f;搜索引擎如何赚钱&#xff1f;搜索引擎如何建立索引?网页抓取文本处理建…

【数字图像处理与应用】模板匹配

【数字图像处理与应用】模板匹配 题目模板匹配原理Matlab代码实现算法介绍显示图像的匹配结果 (最匹配的一个)MATLAB实现运行结果图像的相关值结果&#xff1a;在原图像上绘制检测到的目标位置&#xff1a;显示检测到的目标坐标&#xff1a; 显示图像的匹配结果 (最匹配的三个&…

聊聊spring-cloud的负载均衡

聊聊spring-cloud的负载均衡 1. 选择合适的负载均衡算法2. 合理设置超时时间3. 缓存服务实例列表4. 使用断路器5. 使用缓存Spring Cloud负载均衡组件对比RibbonLoadBalancerWebClient对比 总结 在微服务架构中&#xff0c;负载均衡是非常重要的一个环节&#xff0c;可以有效地提…

python与深度学习(六):CNN和手写数字识别二

目录 1. 说明2. 手写数字识别的CNN模型测试2.1 导入相关库2.2 加载数据和模型2.3 设置保存图片的路径2.4 加载图片2.5 图片预处理2.6 对图片进行预测2.7 显示图片 3. 完整代码和显示结果4. 多张图片进行测试的完整代码以及结果 1. 说明 本篇文章是对上篇文章训练的模型进行测试…

极速跳板机登陆服务器

目录 一&#xff1a;简单登陆跳板器二&#xff1a;一键申请相关的服务器权限三&#xff1a;简化登陆 一&#xff1a;简单登陆跳板器 登陆公司提供的网址&#xff0c; 下载自己的专属RSA密钥。在密钥文件处&#xff0c; 执行登陆指令&#xff1a; ssh -p 36000 -i id_rsa 用户跳…

LAXCUS分布式操作系统:人工智能最后一公里

随着人工智能技术的飞速发展&#xff0c;越来越多的应用场景开始涌现。然而&#xff0c;在实际应用中&#xff0c;人工智能技术仍然面临着许多挑战&#xff0c;其中最大的挑战之一就是如何实现人工智能的“最后一公里”。这一问题主要体现在以下几个方面&#xff1a; 计算资源…

程序员进阶之路:程序环境和预处理

目录 前言 程序的翻译环境和执行环境 翻译环境 运行环境 预处理&#xff08;预编译&#xff09; 预定义符号 #define #define 定义标识符 #define 定义宏 #define 替换规则 #和## #的作用 ##的作用 带副作用的宏参数 宏和函数对比 命名约定 #undef 命令行定义 条件…

Task :app:javaPreCompileDebug FAILED

一,报错内容 在打包react native项目的时候,报错如下信息,我的项目的react-native版本比较低,是0.62… > Task :app:javaPreCompileDebug FAILED Execution failed for task :app:javaPreCompileDebug. > Could not resolve all files for configuration :app:debugCom…

Windows下YUICompress实现js、css混淆压缩

首先&#xff0c;我们针对Linux下的部分命令进行Windows系统的对应实现 ls————cmd /c dir/b rm————cmd /c del mv————cmd /c move pwd————cmd /c chdir 注&#xff1a;cmd /c是执行完命令后关闭命令行窗口、cmd /k是执行完命令后不关闭命令行窗口、cmd /c sta…

关于计算机的各种编码

ASCII编码 ASCII (American Standard Code for Information Interchange)&#xff1a;美国信息交换标准代码是基于的一套电脑编码系统&#xff0c;主要用于显示现代英语和其他语言。它是最通用的标准&#xff0c;并等同于国际标准 ISO/IEC 646。ASCII第一次以规范标准的类型发表…

如何在 SwiftUI 中使用 Touch ID 和 Face ID?

1. 需要通过指纹&#xff0c;面容认证后才能打开 App 2. 添加配置 需要向 Info.plist 文件中添加一个配置&#xff0c;向用户说明为什么要访问 添加 Privacy - Face ID Usage Description 并为其赋予值 $(PRODUCT_NAME) need Touch Id or Face ID permission for app lock 3. …

sql中group by 的使用

1、概述 Group By 从字面意义上理解就是根据By指定的规则对数据进行分组&#xff0c;所谓的分组就是将一个数据集划分为若干个小区域&#xff0c;然后针对若干个小区域进行数据处理 2、原始表 3、简单的Group By 示例1 select 类别&#xff0c;数量 as 数量之和 from A gro…

​MySQL高阶语句(三)

目录 1、内连接 2、左连接 3、右连接&#xff1a; 二、存储过程⭐⭐⭐ 4. 调用存储过程 5.查看存储过程 5.1 查看存储过程 5.2查看指定存储过程信息 三. 存储过程的参数 3.1存储过程的参数 3.2修改存储过程 四.删除存储过程 MySQL 的连接查询&#xff0c;通常都是将来…

(css)原生html实现遮罩层弹窗

(css)原生html实现遮罩层弹窗 效果&#xff1a; html <div class"overlay"><div class"content"><!-- 需要遮罩的内容 --> <el-table :data"tableData" size"mini" class"table-class" border stripe…

解决阿里云服务器不能访问端口

服务器已经下载了redis&#xff0c;kafka&#xff0c;但就是访问不了端口号&#xff0c; 开通云服务器以后&#xff0c;请一定在安全组设置规则&#xff0c;放行端口 防火墙要关闭

网络安全基础知识解析:了解常见的网络攻击类型、术语及其防范方法

目录 1、网络安全常识和术语 1.1资产 1.2网络安全 1.3漏洞 1.4 0day 1.5 1day 1.6后门 1.7exploit 1.8攻击 1.9安全策略 1.10安全机制 1.11社会工程学 2、为什么会出现网络安全问题&#xff1f; 2.1网络的脆弱性 2.4.1缓冲区溢出攻击原理&#xff1a; 2.4.2缓冲…

【简单认识MySQL函数和高级语句】

文章目录 一.常用查询1.按关键字排序&#xff08;ORDER BY 语句&#xff09;1、语法格式2、 ASC和DESC的排序概念3、举例1、按分数排序&#xff0c;默认不指定是升序排列2、分数按降序排列3、order by 还可以结合where进行条件过滤&#xff0c;筛选地址是南京的学生按分数降序排…

数据可视化——绘制带有时间线的柱状图

文章目录 前言如何绘制柱状图添加时间线根据提供的数据绘制动态柱状图读取并删除无用数据将数据转换为字典创建柱状图并添加到时间线中配置选项并生成带有数据的折线图 前言 我们已经学习了使用 pyecharts 包中的模块和相应的方法绘制了折线图和地图&#xff0c;那么今天我将为…