Skip to content

Commit

Permalink
feat: 新增个人中心页
Browse files Browse the repository at this point in the history
  • Loading branch information
kailong321200875 committed Feb 28, 2024
1 parent 5f8e795 commit 4146716
Show file tree
Hide file tree
Showing 10 changed files with 410 additions and 55 deletions.
5 changes: 0 additions & 5 deletions src/components/UserInfo/src/UserInfo.vue
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,6 @@ const toPage = (path: string) => {
{{ t('router.personalCenter') }}
</div>
</ElDropdownItem>
<ElDropdownItem>
<div @click="toPage('/personal/personal-setting')">
{{ t('router.personalSetting') }}
</div>
</ElDropdownItem>
<ElDropdownItem>
<div @click="toDocument">{{ t('common.document') }}</div>
</ElDropdownItem>
Expand Down
38 changes: 37 additions & 1 deletion src/hooks/web/useValidator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,46 @@ export const useValidator = () => {
}
}

const phone = (message?: string): FormItemRule => {
return {
validator: (_, val, callback) => {
if (!val) return callback()
if (!/^1[3456789]\d{9}$/.test(val)) {
callback(new Error(message || '请输入正确的手机号码'))
} else {
callback()
}
}
}
}

const email = (message?: string): FormItemRule => {
return {
validator: (_, val, callback) => {
if (!val) return callback()
if (!/^(\w-*\.*)+@(\w-?)+(\.\w{2,})+$/.test(val)) {
callback(new Error(message || '请输入正确的邮箱'))
} else {
callback()
}
}
}
}

const maxlength = (max: number): FormItemRule => {
return {
max,
message: '长度不能超过' + max + '个字符'
}
}

return {
required,
lengthRange,
notSpace,
notSpecialCharacters
notSpecialCharacters,
phone,
email,
maxlength
}
}
1 change: 0 additions & 1 deletion src/locales/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,6 @@ export default {
tableVideoPreview: 'Table video preview',
cardTable: 'Card table',
personalCenter: 'Personal center',
personalSetting: 'Personal setting',
personal: 'Personal'
},
permission: {
Expand Down
1 change: 0 additions & 1 deletion src/locales/zh-CN.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,6 @@ export default {
tableVideoPreview: '表格视频预览',
cardTable: '卡片表格',
personalCenter: '个人中心',
personalSetting: '个人设置',
personal: '个人'
},
permission: {
Expand Down
10 changes: 0 additions & 10 deletions src/router/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,16 +64,6 @@ export const constantRouterMap: AppRouteRecordRaw[] = [
hidden: true,
canTo: true
}
},
{
path: 'personal-setting',
component: () => import('@/views/Personal/PersonalSetting/PersonalSetting.vue'),
name: 'PersonalSetting',
meta: {
title: t('router.personalSetting'),
hidden: true,
canTo: true
}
}
]
},
Expand Down
167 changes: 137 additions & 30 deletions src/views/Personal/PersonalCenter/PersonalCenter.vue
Original file line number Diff line number Diff line change
@@ -1,41 +1,148 @@
<script lang="ts" setup>
import { ElCard, ElTag } from 'element-plus'
import avatar from '@/assets/imgs/avatar.jpg'
<script setup lang="ts">
import { ContentWrap } from '@/components/ContentWrap'
import { ref, unref } from 'vue'
import { ElDivider, ElImage, ElTag, ElTabPane, ElTabs, ElButton, ElMessage } from 'element-plus'
import defaultAvatar from '@/assets/imgs/avatar.jpg'
import UploadAvatar from './components/UploadAvatar.vue'
import { Dialog } from '@/components/Dialog'
import EditInfo from './components/EditInfo.vue'
import EditPassword from './components/EditPassword.vue'
const userInfo = ref()
const fetchDetailUserApi = async () => {
// 这里可以调用接口获取用户信息
const data = {
id: 1,
username: 'admin',
realName: 'admin',
phoneNumber: '18888888888',
email: '502431556@qq.com',
avatarUrl: '',
roleList: ['超级管理员']
}
userInfo.value = data
}
fetchDetailUserApi()
const activeName = ref('first')
const dialogVisible = ref(false)
const uploadAvatarRef = ref<ComponentRef<typeof UploadAvatar>>()
const avatarLoading = ref(false)
const saveAvatar = async () => {
try {
avatarLoading.value = true
const base64 = unref(uploadAvatarRef)?.getBase64()
console.log(base64)
// 这里可以调用修改头像接口
fetchDetailUserApi()
ElMessage.success('修改成功')
dialogVisible.value = false
} catch (error) {
console.log(error)
} finally {
avatarLoading.value = false
}
}
</script>

<template>
<div>
<ElCard
shadow="hover"
class="border-none! h-200px relative"
:body-style="{
padding: '0'
}"
>
<div class="card h-140px"> </div>
<img
:src="avatar"
alt="avatar"
class="w-128px h-128px border-rd-50% bottom-[40px] left-20px absolute"
/>
<div class="absolute left-168px bottom-70px">
<div class="font-size-24px font-600 mb-10px color-#fff">Archer</div>
<div class="color-#A3A6AD"> 种一棵树最好的时间是十年前,其次是现在。 </div>
<div class="flex w-100% h-100%">
<ContentWrap title="个人信息" class="w-400px">
<div class="flex justify-center items-center">
<div
class="avatar w-[150px] h-[150px] relative cursor-pointer"
@click="dialogVisible = true"
>
<ElImage
class="w-[150px] h-[150px] rounded-full"
:src="userInfo?.avatarUrl || defaultAvatar"
fit="fill"
/>
</div>
</div>
<ElDivider />
<div class="flex justify-between items-center">
<div>账号:</div>
<div>{{ userInfo?.username }}</div>
</div>
<div class="h-60px flex items-center justify-end pr-20px">
<ElTag class="mr-10px">前端开发</ElTag>
<ElTag class="mr-10px">专注设计</ElTag>
<ElTag class="mr-10px">很有想法</ElTag>
<ElTag>时间管理</ElTag>
<ElDivider />
<div class="flex justify-between items-center">
<div>昵称:</div>
<div>{{ userInfo?.realName }}</div>
</div>
</ElCard>
<ElDivider />
<div class="flex justify-between items-center">
<div>手机号码:</div>
<div>{{ userInfo?.phoneNumber ?? '-' }}</div>
</div>
<ElDivider />
<div class="flex justify-between items-center">
<div>用户邮箱:</div>
<div>{{ userInfo?.email ?? '-' }}</div>
</div>
<ElDivider />
<div class="flex justify-between items-center">
<div>所属角色:</div>
<div>
<template v-if="userInfo?.roleList?.length">
<ElTag v-for="item in userInfo?.roleList || []" :key="item" class="ml-2 mb-w"
>{{ item }}
</ElTag>
</template>
<template v-else>-</template>
</div>
</div>
<ElDivider />
</ContentWrap>
<ContentWrap title="基本资料" class="flex-[3] ml-20px">
<ElTabs v-model="activeName">
<ElTabPane label="基本信息" name="first">
<EditInfo :user-info="userInfo" />
</ElTabPane>
<ElTabPane label="修改密码" name="second">
<EditPassword />
</ElTabPane>
</ElTabs>
</ContentWrap>
</div>
<Dialog v-model="dialogVisible" title="修改头像" width="800px">
<UploadAvatar ref="uploadAvatarRef" :url="userInfo?.avatarUrl || defaultAvatar" />
<template #footer>
<ElButton type="primary" :loading="avatarLoading" @click="saveAvatar"> 保存 </ElButton>
<ElButton @click="dialogVisible = false">关闭</ElButton>
</template>
</Dialog>
</template>
<style lang="less" scoped>
.card {
background-image: url("~'@/assets/imgs/personal-center-bg.jpg'");
background-position: center;
background-size: cover;
.avatar {
position: relative;
&::after {
position: absolute;
top: 0;
left: 0;
display: flex;
width: 100%;
height: 100%;
font-size: 50px;
color: #fff;
background-color: rgb(0 0 0 / 40%);
border-radius: 50%;
content: '+';
opacity: 0;
justify-content: center;
align-items: center;
}
&:hover {
&::after {
opacity: 1;
}
}
}
</style>
96 changes: 96 additions & 0 deletions src/views/Personal/PersonalCenter/components/EditInfo.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<script lang="ts" setup>
import { FormSchema, Form } from '@/components/Form'
import { useForm } from '@/hooks/web/useForm'
import { useValidator } from '@/hooks/web/useValidator'
import { reactive, ref, watch } from 'vue'
import { ElDivider, ElMessage, ElMessageBox } from 'element-plus'
const props = defineProps({
userInfo: {
type: Object,
default: () => ({})
}
})
const { required, phone, maxlength, email } = useValidator()
const formSchema = reactive<FormSchema[]>([
{
field: 'realName',
label: '昵称',
component: 'Input',
colProps: {
span: 24
}
},
{
field: 'phoneNumber',
label: '手机号码',
component: 'Input',
colProps: {
span: 24
}
},
{
field: 'email',
label: '邮箱',
component: 'Input',
colProps: {
span: 24
}
}
])
const rules = reactive({
realName: [required(), maxlength(50)],
phoneNumber: [phone()],
email: [email()]
})
const { formRegister, formMethods } = useForm()
const { setValues, getElFormExpose } = formMethods
watch(
() => props.userInfo,
(value) => {
setValues(value)
},
{
immediate: true,
deep: true
}
)
const saveLoading = ref(false)
const save = async () => {
const elForm = await getElFormExpose()
const valid = await elForm?.validate().catch((err) => {
console.log(err)
})
if (valid) {
ElMessageBox.confirm('是否确认修改?', '提示', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning'
})
.then(async () => {
try {
saveLoading.value = true
// 这里可以调用修改用户信息接口
ElMessage.success('修改成功')
} catch (error) {
console.log(error)
} finally {
saveLoading.value = false
}
})
.catch(() => {})
}
}
</script>

<template>
<Form :rules="rules" @register="formRegister" :schema="formSchema" />
<ElDivider />
<BaseButton type="primary" @click="save">保存</BaseButton>
</template>
Loading

0 comments on commit 4146716

Please sign in to comment.