diff --git a/build/vite/plugin/styleImport.ts b/build/vite/plugin/styleImport.ts index 7eb334f..5a49ac5 100644 --- a/build/vite/plugin/styleImport.ts +++ b/build/vite/plugin/styleImport.ts @@ -8,7 +8,6 @@ */ import styleImport from 'vite-plugin-style-import'; -import {createStyleImportPlugin} from 'vite-plugin-style-import'; export function configStyleImportPlugin() { const styleImportPlugin = styleImport({ libs: [ diff --git a/src/components/Cropper/src/CropperAvatar.vue b/src/components/Cropper/src/CropperAvatar.vue index 5b58cae..c0bf5b2 100644 --- a/src/components/Cropper/src/CropperAvatar.vue +++ b/src/components/Cropper/src/CropperAvatar.vue @@ -91,9 +91,9 @@ } ); - function handleUploadSuccess({ source }) { + function handleUploadSuccess({ source, data }) { sourceValue.value = source; - emit('change', source); + emit('change', {source, data}); createMessage.success(t('component.cropper.uploadSuccess')); } diff --git a/src/layouts/default/header/components/user-dropdown/index.vue b/src/layouts/default/header/components/user-dropdown/index.vue index 8ba2cff..a9f79b7 100644 --- a/src/layouts/default/header/components/user-dropdown/index.vue +++ b/src/layouts/default/header/components/user-dropdown/index.vue @@ -43,10 +43,9 @@ import { propTypes } from '/@/utils/propTypes'; import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent'; import { useRouter } from 'vue-router'; - import { isUrl } from '/@/utils/is'; + import { isUrl, isBase64image } from '/@/utils/is'; import { useGlobSetting } from '/@/hooks/setting'; type MenuEvent = 'logout' | 'doc' | 'lock' | 'userInfo'; - import defaultAvatar from '/@/assets/images/defaultAvatar.svg'; import type { User } from '/@/api/platform/core/entity/user'; export default defineComponent({ @@ -81,14 +80,15 @@ } const getAvatarUrl = computed((): string => { - if (!unref(getUserInfo).avatar) return defaultAvatar; - return isUrl(unref(getUserInfo).avatar) ? unref(getUserInfo).avatar : apiUrl + unref(getUserInfo).avatar; + return (isUrl(unref(getUserInfo).avatar) || isBase64image(unref(getUserInfo).avatar)) + ? unref(getUserInfo).avatar + : apiUrl + unref(getUserInfo).avatar; }); function handleMenuClick(e: { key: MenuEvent }) { switch (e.key) { case 'userInfo': - push('/system/userInfo'); + push('/system/accountSetting'); break; case 'logout': handleLoginOut(); diff --git a/src/locales/lang/en/layout.ts b/src/locales/lang/en/layout.ts index 42c7173..d8889d0 100644 --- a/src/locales/lang/en/layout.ts +++ b/src/locales/lang/en/layout.ts @@ -3,7 +3,7 @@ export default { header: { // 用户下拉 dropdownItemLoginOut: 'Login Out', - dropdownItemUserInfo: 'User Info', + dropdownItemUserInfo: 'User Settings', tooltipErrorLog: 'Error log', tooltipLock: 'Lock screen', diff --git a/src/locales/lang/zh-CN/layout.ts b/src/locales/lang/zh-CN/layout.ts index 7b39487..c05e312 100644 --- a/src/locales/lang/zh-CN/layout.ts +++ b/src/locales/lang/zh-CN/layout.ts @@ -3,7 +3,7 @@ export default { header: { // 用户下拉 dropdownItemLoginOut: '退出系统', - dropdownItemUserInfo: '个人中心', + dropdownItemUserInfo: '个人设置', // 提示信息 tooltipErrorLog: '错误日志', diff --git a/src/store/modules/user.ts b/src/store/modules/user.ts index 61b4b3b..0231b98 100644 --- a/src/store/modules/user.ts +++ b/src/store/modules/user.ts @@ -17,6 +17,8 @@ import { useMessage } from '/@/hooks/web/useMessage'; import { router } from '/@/router'; import { usePermissionStore } from '/@/store/modules/permission'; import { RouteRecordRaw } from 'vue-router'; +import defaultAvatar from '/@/assets/images/defaultAvatar.svg'; +import { urlToBase64 } from '/@/utils/file/base64Conver'; interface UserState { userInfo: Nullable; @@ -133,6 +135,7 @@ export const useUserStore = defineStore({ /** 获取用户信息 */ async getUserInfoAction(): Promise { const userInfo = await getUserInfo().catch(()=> this.resetState()); + userInfo.avatar || (userInfo.avatar = await urlToBase64(defaultAvatar)); userInfo.tenantIds = String(userInfo.tenantId).split(','); // 存储用户扩展信息,便于鉴权 this.setUserInfo(userInfo); diff --git a/src/utils/is.ts b/src/utils/is.ts index 9e54908..ca4fa9e 100644 --- a/src/utils/is.ts +++ b/src/utils/is.ts @@ -104,3 +104,8 @@ export function isUrl(path: string): boolean { /(((^https?:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)$/; return reg.test(path); } + +export function isBase64image(base64: string): boolean { + const reg = /data:image\/([^;]+).*/; + return reg.test(base64); +} diff --git a/src/views/system/user/account/center/Application.vue b/src/views/system/user/account/center/Application.vue new file mode 100644 index 0000000..636e57c --- /dev/null +++ b/src/views/system/user/account/center/Application.vue @@ -0,0 +1,92 @@ + + + diff --git a/src/views/system/user/account/center/Article.vue b/src/views/system/user/account/center/Article.vue new file mode 100644 index 0000000..bb71cc9 --- /dev/null +++ b/src/views/system/user/account/center/Article.vue @@ -0,0 +1,97 @@ + + + diff --git a/src/views/system/user/account/center/Project.vue b/src/views/system/user/account/center/Project.vue new file mode 100644 index 0000000..296cbc7 --- /dev/null +++ b/src/views/system/user/account/center/Project.vue @@ -0,0 +1,71 @@ + + + diff --git a/src/views/system/user/account/center/data.tsx b/src/views/system/user/account/center/data.tsx new file mode 100644 index 0000000..51a4d2b --- /dev/null +++ b/src/views/system/user/account/center/data.tsx @@ -0,0 +1,132 @@ +export interface ListItem { + title: string; + icon: string; + color?: string; +} + +export interface TabItem { + key: string; + name: string; + component: string; +} + +export const tags: string[] = [ + '很有想法的', + '专注设计', + '川妹子', + '大长腿', + '海纳百川', + '前端开发', + 'vue3', +]; + +export const teams: ListItem[] = [ + { + icon: 'ri:alipay-fill', + title: '科学搬砖组', + color: '#ff4000', + }, + { + icon: 'emojione-monotone:letter-a', + title: '中二少年团', + color: '#7c51b8', + }, + { + icon: 'ri:alipay-fill', + title: '高逼格设计', + color: '#00adf7', + }, + { + icon: 'jam:codepen-circle', + title: '程序员日常', + color: '#00adf7', + }, + { + icon: 'fa:behance-square', + title: '科学搬砖组', + color: '#7c51b8', + }, + { + icon: 'jam:codepen-circle', + title: '程序员日常', + color: '#ff4000', + }, +]; + +export const details: ListItem[] = [ + { + icon: 'ic:outline-contacts', + title: '交互专家', + }, + { + icon: 'grommet-icons:cluster', + title: '某某某事业群', + }, + { + icon: 'bx:bx-home-circle', + title: '福建省厦门市', + }, +]; + +export const achieveList: TabItem[] = [ + { + key: '1', + name: '文章', + component: 'Article', + }, + { + key: '2', + name: '应用', + component: 'Application', + }, + { + key: '3', + name: '项目', + component: 'Project', + }, +]; + +export const actions: any[] = [ + { icon: 'clarity:star-line', text: '156', color: '#018ffb' }, + { icon: 'bx:bxs-like', text: '156', color: '#459ae8' }, + { icon: 'bx:bxs-message-dots', text: '2', color: '#42d27d' }, +]; + +export const articleList = (() => { + const result: any[] = []; + for (let i = 0; i < 4; i++) { + result.push({ + title: 'Vben Admin', + description: ['Vben', '设计语言', 'Typescript'], + content: '基于Vue Next, TypeScript, Ant Design实现的一套完整的企业级后台管理系统。', + time: '2020-11-14 11:20', + }); + } + return result; +})(); + +export const applicationList = (() => { + const result: any[] = []; + for (let i = 0; i < 8; i++) { + result.push({ + title: 'Vben Admin', + icon: 'emojione-monotone:letter-a', + color: '#1890ff', + active: '100', + new: '1,799', + download: 'bx:bx-download', + }); + } + return result; +})(); + +export const projectList = (() => { + const result: any[] = []; + for (let i = 0; i < 8; i++) { + result.push({ + title: 'Vben Admin', + content: '基于Vue Next, TypeScript, Ant Design实现的一套完整的企业级后台管理系统。', + }); + } + return result; +})(); diff --git a/src/views/system/user/account/center/index.vue b/src/views/system/user/account/center/index.vue new file mode 100644 index 0000000..ae82aeb --- /dev/null +++ b/src/views/system/user/account/center/index.vue @@ -0,0 +1,155 @@ + + + + diff --git a/src/views/system/user/account/setting/EntCertification.vue b/src/views/system/user/account/setting/EntCertification.vue new file mode 100644 index 0000000..12af9d9 --- /dev/null +++ b/src/views/system/user/account/setting/EntCertification.vue @@ -0,0 +1,34 @@ + + + diff --git a/src/views/system/user/account/setting/UserInfo.vue b/src/views/system/user/account/setting/UserInfo.vue new file mode 100644 index 0000000..46bbc32 --- /dev/null +++ b/src/views/system/user/account/setting/UserInfo.vue @@ -0,0 +1,152 @@ + + + + diff --git a/src/views/system/user/account/setting/data.ts b/src/views/system/user/account/setting/data.ts new file mode 100644 index 0000000..3dec086 --- /dev/null +++ b/src/views/system/user/account/setting/data.ts @@ -0,0 +1,93 @@ +import { FormSchema } from '/@/components/Form/index'; + +export const settingList = [ + { + key: '1', + name: '个人信息', + component: 'UserInfo', + prefixIcon: 'fa:user' + }, + { + key: '2', + name: '企业认证', + component: 'EntCertification', + prefixIcon: 'fa6-solid:city' + } +]; + +export const userFormSchema: FormSchema[] = [ + { + field: 'id', + label: 'ID', + component: 'Input', + show: false + }, + { + field: 'nickName', + label: '用户昵称', + component: 'Input', + required: true + }, + { + field: 'deptName', + label: '归属机构', + component: 'Input', + required: true, + componentProps: { + disabled: true + } + }, + { + field: 'phone', + label: '手机号', + component: 'Input', + rules: [ + { + required: true, + message: '请输入手机号!', + }, + { + pattern: new RegExp('^1[3|4|5|6|7|8|9][0-9]\\d{8}$'), + message: '请输入正确的手机号码!', + validateTrigger: 'blur' + } + ] + }, + { + field: 'email', + label: '邮箱', + component: 'Input', + rules: [ + { + required: true, + message: '请输入邮箱!', + }, + { + type: 'email', + message: '请输入正确的邮箱地址!', + validateTrigger: ['blur', 'change'] + } + ] + }, + { + field: 'sex', + label: '性别', + component: 'RadioGroup', + defaultValue: '0', + required: true, + componentProps: { + options: [ + { label: '男', value: '0' }, + { label: '女', value: '1' } + ] + } + }, + { + label: '备注', + field: 'remarks', + component: 'InputTextArea', + componentProps: { + rows: 6 + } + } +]; diff --git a/src/views/system/user/account/setting/index.vue b/src/views/system/user/account/setting/index.vue new file mode 100644 index 0000000..d3b2bc4 --- /dev/null +++ b/src/views/system/user/account/setting/index.vue @@ -0,0 +1,88 @@ + + + +