|
@@ -1,9 +1,302 @@
|
|
|
<template>
|
|
|
- <div>
|
|
|
- 111
|
|
|
- </div>
|
|
|
+ <hc-card>
|
|
|
+ <div class="relative h-full flex">
|
|
|
+ <div class="mr-4 h-full w-[260px]">
|
|
|
+ <hc-card-item>
|
|
|
+ <div class="hc-flex-center">
|
|
|
+ <div class="user-avatar">
|
|
|
+ <img class="avatar" :src="userInfo.avatar || avatarPng" alt="">
|
|
|
+ <div class="avatar-upload" @click="setModalShowClick">
|
|
|
+ <HcIcon fill name="camera" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="user-name">{{ userInfo.real_name || '游客' }}</div>
|
|
|
+ <div class="user-menu-box">
|
|
|
+ <hc-menu-simple :datas="menuOptions" :keys="menuKey" @change="handleMenuChange" />
|
|
|
+ </div>
|
|
|
+ </hc-card-item>
|
|
|
+ </div>
|
|
|
+ <div class="h-full flex-1">
|
|
|
+ <hc-card-item v-if="menuKey === 'basic'" title="基础信息">
|
|
|
+ <el-form :model="formUserModel" label-position="top" size="large">
|
|
|
+ <el-row :gutter="20">
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="用户名称">
|
|
|
+ <el-input v-model="formUserModel.real_name" disabled />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="登录账号">
|
|
|
+ <el-input v-model="formUserModel.account" disabled />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="身份证号">
|
|
|
+ <el-input v-model="formUserModel.idNumber" disabled />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="绑定手机">
|
|
|
+ <el-input v-model="formUserModel.phone" disabled />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="所属角色">
|
|
|
+ <el-input v-model="formUserModel.roleName" disabled />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="所属部门">
|
|
|
+ <el-input v-model="formUserModel.deptId" disabled />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ </el-form>
|
|
|
+ </hc-card-item>
|
|
|
+ <hc-card-item v-if="menuKey === 'password'" title="密码设置">
|
|
|
+ <el-form
|
|
|
+ ref="formUserPassRef"
|
|
|
+ :model="formUserPassModel"
|
|
|
+ :rules="formUserPassRules"
|
|
|
+ label-position="top" size="large"
|
|
|
+ style="max-width: 400px; margin: auto;"
|
|
|
+ >
|
|
|
+ <el-form-item label="原始密码" prop="oldPassword">
|
|
|
+ <el-input
|
|
|
+ v-model="formUserPassModel.oldPassword" placeholder="请输入原始密码"
|
|
|
+ show-password type="password"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="新的密码" prop="newPassword">
|
|
|
+ <el-input
|
|
|
+ v-model="formUserPassModel.newPassword" placeholder="请输入新的密码"
|
|
|
+ show-password type="password"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="确认新密码" prop="newPassword1">
|
|
|
+ <el-input
|
|
|
+ v-model="formUserPassModel.newPassword1" placeholder="请输入确认新密码"
|
|
|
+ show-password type="password"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ <template #action>
|
|
|
+ <div class="hc-flex-center">
|
|
|
+ <el-button :loading="saveUserLoading" hc-btn type="primary" @click="saveUserInfoClick">
|
|
|
+ <HcIcon name="save" />
|
|
|
+ <span>提交保存</span>
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </hc-card-item>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <!-- 文件上传 -->
|
|
|
+ <hc-upload-file ref="HcUploadFileRef" :options="uploadFileOptions" @success="uploadFileSuccess" />
|
|
|
+ </hc-card>
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
+import { onMounted, ref } from 'vue'
|
|
|
+import { useAppStore } from '~src/store'
|
|
|
+import userApi from '~api/userInfo/index'
|
|
|
+import avatarPng from '~src/assets/images/avatar.png'
|
|
|
+import { getHeader } from 'hc-vue3-ui'
|
|
|
+import { formValidate } from 'js-fast-way'
|
|
|
+const useState = useAppStore()
|
|
|
+import md5 from 'js-md5'
|
|
|
|
|
|
+
|
|
|
+const userInfo = ref(useState.getUserInfo)
|
|
|
+
|
|
|
+onMounted(() => {
|
|
|
+ uploadFileOptions.value = {
|
|
|
+ headers: getHeader(),
|
|
|
+ url: '/api/blade-resource/oss/endpoint/put-file',
|
|
|
+ accept: 'image/png,image/jpg,image/jpeg',
|
|
|
+ accept_tip: '只能上传图片(png、jpg、jpeg)文件',
|
|
|
+ multiple: false,
|
|
|
+ }
|
|
|
+ queryCurrentUserData()
|
|
|
+})
|
|
|
+
|
|
|
+//文件上传
|
|
|
+const HcUploadFileRef = ref(null)
|
|
|
+const uploadFileOptions = ref({})
|
|
|
+const setModalShowClick = () => {
|
|
|
+ HcUploadFileRef.value?.selectFile()
|
|
|
+}
|
|
|
+//文件上传完成
|
|
|
+const uploadFileSuccess = async ({ resData }) => {
|
|
|
+ const link = resData?.link ?? ''
|
|
|
+ const user_id = userInfo.value?.user_id ?? ''
|
|
|
+ if (link) {
|
|
|
+ const { error, code } = await userApi.updateUserInfo({
|
|
|
+ avatar: link,
|
|
|
+ id: user_id,
|
|
|
+ })
|
|
|
+ if (!error && code === 200) {
|
|
|
+ userInfo.value.avatar = link
|
|
|
+ window?.$message?.success('更换头像成功')
|
|
|
+ useState.setUserInfo(userInfo.value)
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ window?.$message?.warning('上传头像异常,请稍后再试')
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+//左侧菜单
|
|
|
+const menuKey = ref('basic')
|
|
|
+const menuOptions = ref([
|
|
|
+ { key: 'basic', label: '基础信息', icon: 'user-3' },
|
|
|
+ { key: 'password', label: '密码设置', icon: 'lock-unlock' },
|
|
|
+])
|
|
|
+const handleMenuChange = ({ key }) => {
|
|
|
+ if (key === 'basic' && menuKey.value !== key) {
|
|
|
+ queryCurrentUserData()
|
|
|
+ }
|
|
|
+ menuKey.value = key
|
|
|
+}
|
|
|
+
|
|
|
+//获取用户信息
|
|
|
+const formUserModel = ref({})
|
|
|
+const queryCurrentUserData = async () => {
|
|
|
+ const { error, code, data } = await userApi.queryCurrentUserData()
|
|
|
+ if (!error && code === 200) {
|
|
|
+ formUserModel.value = userInfo.value
|
|
|
+ formUserModel.value.deptId = data?.deptId || ''
|
|
|
+ formUserModel.value.idNumber = data?.idNumber || ''
|
|
|
+ formUserModel.value.roleName = data?.roleName || ''
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+//密码设置表单
|
|
|
+const formUserPassRef = ref(null)
|
|
|
+const formUserPassModel = ref({
|
|
|
+ oldPassword: '',
|
|
|
+ newPassword: '',
|
|
|
+ newPassword1: '',
|
|
|
+})
|
|
|
+const formUserPassRules = {
|
|
|
+ oldPassword: {
|
|
|
+ required: true,
|
|
|
+ trigger: 'blur',
|
|
|
+ message: '请输入原始密码',
|
|
|
+ },
|
|
|
+ newPassword: {
|
|
|
+ required: true,
|
|
|
+ validator(rule, value, callback) {
|
|
|
+ const pass = formUserPassModel.value.newPassword1
|
|
|
+ if (!value) {
|
|
|
+ callback(new Error('请输入新的密码'))
|
|
|
+ } else if (pass && value !== pass) {
|
|
|
+ callback(new Error('新的密码和确认新密码不一致'))
|
|
|
+ }
|
|
|
+ callback()
|
|
|
+ },
|
|
|
+ trigger: 'blur',
|
|
|
+ },
|
|
|
+ newPassword1: {
|
|
|
+ required: true,
|
|
|
+ validator(rule, value, callback) {
|
|
|
+ const pass = formUserPassModel.value.newPassword
|
|
|
+ if (!value) {
|
|
|
+ callback(new Error('请输入确认新密码'))
|
|
|
+ } else if (pass && value !== pass) {
|
|
|
+ callback(new Error('新的密码和确认新密码不一致'))
|
|
|
+ }
|
|
|
+ callback()
|
|
|
+ },
|
|
|
+ trigger: 'blur',
|
|
|
+ },
|
|
|
+}
|
|
|
+
|
|
|
+//保存数据
|
|
|
+const saveUserLoading = ref(false)
|
|
|
+const saveUserInfoClick = async () => {
|
|
|
+ const res = await formValidate(formUserPassRef.value)
|
|
|
+ if (res) {
|
|
|
+ const form = formUserPassModel.value
|
|
|
+ saveUserLoading.value = true
|
|
|
+ const { error, code } = await userApi.updatePassword({
|
|
|
+ oldPassword: md5(form?.oldPassword),
|
|
|
+ newPassword: md5(form?.newPassword),
|
|
|
+ newPassword1: md5(form?.newPassword1),
|
|
|
+ plaintextPassword: form?.newPassword,
|
|
|
+ })
|
|
|
+ if (!error && code === 200) {
|
|
|
+ saveUserLoading.value = false
|
|
|
+ window?.$message?.success('密码修改成功')
|
|
|
+ formUserPassModel.value = {
|
|
|
+ oldPassword: '',
|
|
|
+ newPassword: '',
|
|
|
+ newPassword1: '',
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ saveUserLoading.value = false
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
</script>
|
|
|
+
|
|
|
+<style scoped lang="scss">
|
|
|
+.user-avatar {
|
|
|
+ position: relative;
|
|
|
+ height: 100px;
|
|
|
+ width: 100px;
|
|
|
+ border: 2px solid #fff;
|
|
|
+ border-radius: 50%;
|
|
|
+ background: #d8d8d8;
|
|
|
+ margin-top: 16px;
|
|
|
+ margin-bottom: 12px;
|
|
|
+ box-shadow: 7px 7px 8px #365ca726, -7px -7px 8px #fff, 4px 4px 8px #365ca726, -4px -4px 8px #fff;
|
|
|
+ img {
|
|
|
+ border-radius: 50%;
|
|
|
+ display: block;
|
|
|
+ height: 100%;
|
|
|
+ -o-object-fit: cover;
|
|
|
+ object-fit: cover;
|
|
|
+ width: 100%;
|
|
|
+ }
|
|
|
+ .avatar-upload {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ position: absolute;
|
|
|
+ width: 24px;
|
|
|
+ height: 24px;
|
|
|
+ right: 0;
|
|
|
+ bottom: 0;
|
|
|
+ cursor: pointer;
|
|
|
+ color: #838791;
|
|
|
+ background: #f1f5f8;
|
|
|
+ border-radius: 50%;
|
|
|
+ transition: color .2s;
|
|
|
+ box-shadow: 4px 4px 8px #365ca726;
|
|
|
+ &:hover {
|
|
|
+ color: var(--el-color-primary);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+.user-name {
|
|
|
+ position: relative;
|
|
|
+ color: #1a1a1a;
|
|
|
+ font-size: 16px;
|
|
|
+ font-weight: 700;
|
|
|
+ text-align: center;
|
|
|
+}
|
|
|
+</style>
|
|
|
+
|
|
|
+<style lang="scss">
|
|
|
+.user-menu-box {
|
|
|
+ position: relative;
|
|
|
+ margin-top: 20px;
|
|
|
+ .hc-menu-simple-box {
|
|
|
+ margin: -10px;
|
|
|
+ .item-box + .item-box {
|
|
|
+ margin-top: 16px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|