mirror of
https://gitee.com/hhyykk/ipms-sjy-ui.git
synced 2025-07-23 23:35:06 +08:00
初始化项目,自 v1.7.1 版本开始
This commit is contained in:
89
src/views/Profile/components/BasicInfo.vue
Normal file
89
src/views/Profile/components/BasicInfo.vue
Normal file
@ -0,0 +1,89 @@
|
||||
<template>
|
||||
<Form ref="formRef" :rules="rules" :schema="schema" :labelWidth="80">
|
||||
<template #sex="form">
|
||||
<el-radio-group v-model="form['sex']">
|
||||
<el-radio :label="1">{{ t('profile.user.man') }}</el-radio>
|
||||
<el-radio :label="2">{{ t('profile.user.woman') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</template>
|
||||
</Form>
|
||||
<XButton :title="t('common.save')" @click="submit()" />
|
||||
<XButton type="danger" :title="t('common.reset')" @click="init()" />
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import type { FormRules } from 'element-plus'
|
||||
import { ElMessage } from 'element-plus'
|
||||
|
||||
import { FormSchema } from '@/types/form'
|
||||
import type { FormExpose } from '@/components/Form'
|
||||
import {
|
||||
getUserProfileApi,
|
||||
updateUserProfileApi,
|
||||
UserProfileUpdateReqVO
|
||||
} from '@/api/system/user/profile'
|
||||
|
||||
const { t } = useI18n()
|
||||
// 表单校验
|
||||
const rules = reactive<FormRules>({
|
||||
nickname: [{ required: true, message: t('profile.rules.nickname'), trigger: 'blur' }],
|
||||
email: [
|
||||
{ required: true, message: t('profile.rules.mail'), trigger: 'blur' },
|
||||
{
|
||||
type: 'email',
|
||||
message: t('profile.rules.truemail'),
|
||||
trigger: ['blur', 'change']
|
||||
}
|
||||
],
|
||||
mobile: [
|
||||
{ required: true, message: t('profile.rules.phone'), trigger: 'blur' },
|
||||
{
|
||||
pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,
|
||||
message: t('profile.rules.truephone'),
|
||||
trigger: 'blur'
|
||||
}
|
||||
]
|
||||
})
|
||||
const schema = reactive<FormSchema[]>([
|
||||
{
|
||||
field: 'nickname',
|
||||
label: t('profile.user.nickname'),
|
||||
component: 'Input'
|
||||
},
|
||||
{
|
||||
field: 'mobile',
|
||||
label: t('profile.user.mobile'),
|
||||
component: 'Input'
|
||||
},
|
||||
{
|
||||
field: 'email',
|
||||
label: t('profile.user.email'),
|
||||
component: 'Input'
|
||||
},
|
||||
{
|
||||
field: 'sex',
|
||||
label: t('profile.user.sex'),
|
||||
component: 'InputNumber',
|
||||
value: 0
|
||||
}
|
||||
])
|
||||
const formRef = ref<FormExpose>() // 表单 Ref
|
||||
const submit = () => {
|
||||
const elForm = unref(formRef)?.getElFormRef()
|
||||
if (!elForm) return
|
||||
elForm.validate(async (valid) => {
|
||||
if (valid) {
|
||||
const data = unref(formRef)?.formModel as UserProfileUpdateReqVO
|
||||
await updateUserProfileApi(data)
|
||||
ElMessage.success(t('common.updateSuccess'))
|
||||
await init()
|
||||
}
|
||||
})
|
||||
}
|
||||
const init = async () => {
|
||||
const res = await getUserProfileApi()
|
||||
unref(formRef)?.setValues(res)
|
||||
}
|
||||
onMounted(async () => {
|
||||
await init()
|
||||
})
|
||||
</script>
|
88
src/views/Profile/components/ProfileUser.vue
Normal file
88
src/views/Profile/components/ProfileUser.vue
Normal file
@ -0,0 +1,88 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="text-center">
|
||||
<UserAvatar :img="userInfo?.avatar" />
|
||||
</div>
|
||||
<ul class="list-group list-group-striped">
|
||||
<li class="list-group-item">
|
||||
<Icon icon="ep:user" class="mr-5px" />{{ t('profile.user.username') }}
|
||||
<div class="pull-right">{{ userInfo?.username }}</div>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<Icon icon="ep:phone" class="mr-5px" />{{ t('profile.user.mobile') }}
|
||||
<div class="pull-right">{{ userInfo?.mobile }}</div>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<Icon icon="fontisto:email" class="mr-5px" />{{ t('profile.user.email') }}
|
||||
<div class="pull-right">{{ userInfo?.email }}</div>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<Icon icon="carbon:tree-view-alt" class="mr-5px" />{{ t('profile.user.dept') }}
|
||||
<div class="pull-right" v-if="userInfo?.dept">{{ userInfo?.dept.name }}</div>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<Icon icon="ep:suitcase" class="mr-5px" />{{ t('profile.user.posts') }}
|
||||
<div class="pull-right" v-if="userInfo?.posts">
|
||||
{{ userInfo?.posts.map((post) => post.name).join(',') }}
|
||||
</div>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<Icon icon="icon-park-outline:peoples" class="mr-5px" />{{ t('profile.user.roles') }}
|
||||
<div class="pull-right" v-if="userInfo?.roles">
|
||||
{{ userInfo?.roles.map((role) => role.name).join(',') }}
|
||||
</div>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<Icon icon="ep:calendar" class="mr-5px" />{{ t('profile.user.createTime') }}
|
||||
<div class="pull-right">{{ dayjs(userInfo?.createTime).format('YYYY-MM-DD') }}</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import dayjs from 'dayjs'
|
||||
import UserAvatar from './UserAvatar.vue'
|
||||
|
||||
import { getUserProfileApi, ProfileVO } from '@/api/system/user/profile'
|
||||
|
||||
const { t } = useI18n()
|
||||
const userInfo = ref<ProfileVO>()
|
||||
const getUserInfo = async () => {
|
||||
const users = await getUserProfileApi()
|
||||
userInfo.value = users
|
||||
}
|
||||
onMounted(async () => {
|
||||
await getUserInfo()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.text-center {
|
||||
text-align: center;
|
||||
position: relative;
|
||||
height: 120px;
|
||||
}
|
||||
.list-group-striped > .list-group-item {
|
||||
border-left: 0;
|
||||
border-right: 0;
|
||||
border-radius: 0;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
.list-group {
|
||||
padding-left: 0px;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.list-group-item {
|
||||
border-bottom: 1px solid #e7eaec;
|
||||
border-top: 1px solid #e7eaec;
|
||||
margin-bottom: -1px;
|
||||
padding: 11px 0px;
|
||||
font-size: 13px;
|
||||
}
|
||||
.pull-right {
|
||||
float: right !important;
|
||||
}
|
||||
</style>
|
68
src/views/Profile/components/ResetPwd.vue
Normal file
68
src/views/Profile/components/ResetPwd.vue
Normal file
@ -0,0 +1,68 @@
|
||||
<template>
|
||||
<el-form ref="formRef" :model="password" :rules="rules" label-width="80px">
|
||||
<el-form-item :label="t('profile.password.oldPassword')">
|
||||
<InputPassword v-model="password.oldPassword" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('profile.password.newPassword')">
|
||||
<InputPassword v-model="password.newPassword" strength />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('profile.password.confirmPassword')">
|
||||
<InputPassword v-model="password.confirmPassword" strength />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<XButton type="primary" @click="submit(formRef)" :title="t('common.save')" />
|
||||
<XButton type="danger" :title="t('common.reset')" @click="reset(formRef)" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import type { FormRules, FormInstance } from 'element-plus'
|
||||
|
||||
import { InputPassword } from '@/components/InputPassword'
|
||||
import { updateUserPwdApi } from '@/api/system/user/profile'
|
||||
|
||||
const { t } = useI18n()
|
||||
const message = useMessage()
|
||||
const formRef = ref<FormInstance>()
|
||||
const password = reactive({
|
||||
oldPassword: '',
|
||||
newPassword: '',
|
||||
confirmPassword: ''
|
||||
})
|
||||
|
||||
// 表单校验
|
||||
const equalToPassword = (value, callback) => {
|
||||
if (password.newPassword !== value) {
|
||||
callback(new Error(t('profile.password.diffPwd')))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
const rules = reactive<FormRules>({
|
||||
oldPassword: [
|
||||
{ required: true, message: t('profile.password.oldPwdMsg'), trigger: 'blur' },
|
||||
{ min: 3, max: 5, message: t('profile.password.pwdRules'), trigger: 'blur' }
|
||||
],
|
||||
newPassword: [
|
||||
{ required: true, message: t('profile.password.newPwdMsg'), trigger: 'blur' },
|
||||
{ min: 6, max: 20, message: t('profile.password.pwdRules'), trigger: 'blur' }
|
||||
],
|
||||
confirmPassword: [
|
||||
{ required: true, message: t('profile.password.cfPwdMsg'), trigger: 'blur' },
|
||||
{ required: true, validator: equalToPassword, trigger: 'blur' }
|
||||
]
|
||||
})
|
||||
const submit = (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return
|
||||
formEl.validate(async (valid) => {
|
||||
if (valid) {
|
||||
await updateUserPwdApi(password.oldPassword, password.newPassword)
|
||||
message.success(t('common.updateSuccess'))
|
||||
}
|
||||
})
|
||||
}
|
||||
const reset = (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return
|
||||
formEl.resetFields()
|
||||
}
|
||||
</script>
|
38
src/views/Profile/components/UserAvatar.vue
Normal file
38
src/views/Profile/components/UserAvatar.vue
Normal file
@ -0,0 +1,38 @@
|
||||
<template>
|
||||
<div class="change-avatar">
|
||||
<CropperAvatar
|
||||
ref="cropperRef"
|
||||
:value="avatar"
|
||||
:showBtn="false"
|
||||
@change="handelUpload"
|
||||
:btnProps="{ preIcon: 'ant-design:cloud-upload-outlined' }"
|
||||
width="120px"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { propTypes } from '@/utils/propTypes'
|
||||
import { uploadAvatarApi } from '@/api/system/user/profile'
|
||||
const props = defineProps({
|
||||
img: propTypes.string.def('')
|
||||
})
|
||||
const avatar = computed(() => {
|
||||
return props.img
|
||||
})
|
||||
|
||||
const cropperRef = ref()
|
||||
const handelUpload = async ({ data }) => {
|
||||
await uploadAvatarApi({ avatarFile: data })
|
||||
cropperRef.value.close()
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.change-avatar {
|
||||
img {
|
||||
display: block;
|
||||
margin-bottom: 15px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
</style>
|
67
src/views/Profile/components/UserSocial.vue
Normal file
67
src/views/Profile/components/UserSocial.vue
Normal file
@ -0,0 +1,67 @@
|
||||
<template>
|
||||
<el-table :data="socialUsers" :show-header="false">
|
||||
<el-table-column type="seq" title="序号" width="60" fixed="left" />
|
||||
<el-table-column label="社交平台" align="left" width="120">
|
||||
<template #default="{ row }">
|
||||
<img class="h-5 align-middle" :src="row.img" alt="" />
|
||||
<p class="mr-5">{{ row.title }}</p>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center">
|
||||
<template #default="{ row }">
|
||||
<template v-if="row.openid">
|
||||
已绑定
|
||||
<XTextButton type="primary" class="mr-5" @click="unbind(row)" title="(解绑)" />
|
||||
</template>
|
||||
<template v-else>
|
||||
未绑定
|
||||
<XTextButton type="primary" class="mr-5" @click="bind(row)" title="(绑定)" />
|
||||
</template>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { SystemUserSocialTypeEnum } from '@/utils/constants'
|
||||
import { getUserProfileApi, ProfileVO } from '@/api/system/user/profile'
|
||||
import { socialAuthRedirect, socialUnbind } from '@/api/system/user/socialUser'
|
||||
|
||||
const message = useMessage()
|
||||
const socialUsers = ref<any[]>([])
|
||||
const userInfo = ref<ProfileVO>()
|
||||
|
||||
const initSocial = async () => {
|
||||
const res = await getUserProfileApi()
|
||||
userInfo.value = res
|
||||
for (const i in SystemUserSocialTypeEnum) {
|
||||
const socialUser = { ...SystemUserSocialTypeEnum[i] }
|
||||
socialUsers.value.push(socialUser)
|
||||
if (userInfo.value?.socialUsers) {
|
||||
for (const j in userInfo.value.socialUsers) {
|
||||
if (socialUser.type === userInfo.value.socialUsers[j].type) {
|
||||
socialUser.openid = userInfo.value.socialUsers[j].openid
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
const bind = (row) => {
|
||||
const redirectUri = location.origin + '/user/profile?type=' + row.type
|
||||
// 进行跳转
|
||||
socialAuthRedirect(row.type, encodeURIComponent(redirectUri)).then((res) => {
|
||||
window.location.href = res.data
|
||||
})
|
||||
}
|
||||
const unbind = async (row) => {
|
||||
const res = await socialUnbind(row.type, row.openid)
|
||||
if (res) {
|
||||
row.openid = undefined
|
||||
}
|
||||
message.success('解绑成功')
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
await initSocial()
|
||||
})
|
||||
</script>
|
7
src/views/Profile/components/index.ts
Normal file
7
src/views/Profile/components/index.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import BasicInfo from './BasicInfo.vue'
|
||||
import ProfileUser from './ProfileUser.vue'
|
||||
import ResetPwd from './ResetPwd.vue'
|
||||
import UserAvatarVue from './UserAvatar.vue'
|
||||
import UserSocial from './UserSocial.vue'
|
||||
|
||||
export { BasicInfo, ProfileUser, ResetPwd, UserAvatarVue, UserSocial }
|
Reference in New Issue
Block a user