From becdc20745d3648d2c1fd5c7c1f68c0c08113fe9 Mon Sep 17 00:00:00 2001 From: bunny <1319900154@qq.com> Date: Tue, 22 Oct 2024 15:55:48 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=F0=9F=9A=80=20=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E4=BF=A1=E6=81=AF=E6=9F=A5=E7=9C=8B=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E7=99=BB=E5=BD=95=E6=97=A5=E5=BF=97=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/v1/adminUser.ts | 5 + src/api/v1/files.ts | 4 +- src/plugins/i18n.ts | 80 +++++++++++- src/store/system/adminUser.ts | 18 ++- src/views/account-settings/index.vue | 36 +----- src/views/account-settings/profile.vue | 133 +++++++++++--------- src/views/account-settings/references.vue | 69 ---------- src/views/account-settings/security-log.vue | 43 ++++--- src/views/account-settings/utils/columns.ts | 90 +++++++++---- src/views/account-settings/utils/hooks.ts | 43 ++++++- 10 files changed, 298 insertions(+), 223 deletions(-) delete mode 100644 src/views/account-settings/references.vue diff --git a/src/api/v1/adminUser.ts b/src/api/v1/adminUser.ts index 3a6f96e..579d91d 100644 --- a/src/api/v1/adminUser.ts +++ b/src/api/v1/adminUser.ts @@ -69,6 +69,11 @@ export const fetchAddAdminUser = (data: any) => { return http.request>('post', 'user/addAdminUser', { data }); }; +/** 用户信息---更新本地用户信息 */ +export const fetchUpdateAdminUserByLocalUser = (data: any) => { + return http.request>('put', 'user/noManage/updateAdminUserByLocalUser', { data }); +}; + /** 用户信息---更新用户信息 */ export const fetchUpdateAdminUser = (data: any) => { return http.request>('put', 'user/updateAdminUser', { data }); diff --git a/src/api/v1/files.ts b/src/api/v1/files.ts index 2ca4fbc..e05c0a2 100644 --- a/src/api/v1/files.ts +++ b/src/api/v1/files.ts @@ -6,12 +6,12 @@ export const fetchGetFilesList = (data: any) => { return http.request>('get', `files/getFilesList/${data.currentPage}/${data.pageSize}`, { params: data }); }; -/** 系统文件管理---下载系统文件 */ +/** 系统文件管理---根据I下载系统文件d */ export const downloadFilesByFileId = (data: any) => { return http.request('get', `files/downloadFilesByFileId/${data.id}`, { responseType: 'blob' }); }; -/** 系统文件管理---下载系统文件 */ +/** 系统文件管理---批量下载系统文件 */ export const downloadFilesByFilepath = (data: any) => { return http.request('get', `files/downloadFilesByFilepath`, { params: data, responseType: 'blob' }); }; diff --git a/src/plugins/i18n.ts b/src/plugins/i18n.ts index d1a78f1..91ce8cd 100644 --- a/src/plugins/i18n.ts +++ b/src/plugins/i18n.ts @@ -9,14 +9,90 @@ const languageData = localStorage.getItem('i18nStore'); export const i18n = createI18n({ // 如果要支持 compositionAPI,此项必须设置为 false legacy: false, - // locale: 'zh', - fallbackLocale: 'en', + locale: 'zh', + fallbackLocale: 'zh', // ? 全局注册$t方法 globalInjection: true, // 本地内容存在时,首次加载如果本地存储没有多语言需要再刷新 messages: languageData ? JSON.parse(languageData).i18n : {}, }); +/*const siphonI18n = (function () { + // 仅初始化一次国际化配置 + let cache = Object.fromEntries( + Object.entries(import.meta.glob('../../locales/!*.y(a)?ml', { eager: true })).map(([key, value]: any) => { + const matched = key.match(/([A-Za-z0-9-_]+)\./i)[1]; + return [matched, value.default]; + }), + ); + return (prefix = 'zh-CN') => { + return cache[prefix]; + }; +})(); + +/!** 获取对象中所有嵌套对象的key键,并将它们用点号分割组成字符串 *!/ +function getObjectKeys(obj) { + const stack = []; + const keys: Set = new Set(); + + stack.push({ obj, key: '' }); + + while (stack.length > 0) { + const { obj, key } = stack.pop(); + + for (const k in obj) { + const newKey = key ? `${key}.${k}` : k; + + if (obj[k] && isObject(obj[k])) { + stack.push({ obj: obj[k], key: newKey }); + } else { + keys.add(key); + } + } + } + + return keys; +} + +/!** 将展开的key缓存 *!/ +const keysCache: Map> = new Map(); +const flatI18n = (prefix = 'zh') => { + let cache = keysCache.get(prefix); + if (!cache) { + cache = getObjectKeys(siphonI18n(prefix)); + keysCache.set(prefix, cache); + } + return cache; +}; + +/!** + * 国际化转换工具函数(自动读取根目录locales文件夹下文件进行国际化匹配) + * @param message message + * @returns 转化后的message + *!/ +export function transformI18n(message: any = '') { + if (!message) { + return ''; + } + + // 处理存储动态路由的title,格式 {zh:"",en:""} + if (typeof message === 'object') { + const locale: string | WritableComputedRef | any = i18n.global.locale; + return message[locale?.value]; + } + + const key = message.match(/(\S*)\./)?.input; + + if (key && flatI18n('zh-CN').has(key)) { + return i18n.global.t.call(i18n.global.locale, message); + } else if (!key && Object.hasOwn(siphonI18n('zh'), message)) { + // 兼容非嵌套形式的国际化写法 + return i18n.global.t.call(i18n.global.locale, message); + } else { + return message; + } +}*/ + export const $t: any = (i18n.global as any).t as any; export function useI18n(app: App) { diff --git a/src/store/system/adminUser.ts b/src/store/system/adminUser.ts index 17d035f..2c01866 100644 --- a/src/store/system/adminUser.ts +++ b/src/store/system/adminUser.ts @@ -2,7 +2,16 @@ import { defineStore } from 'pinia'; import { pageSizes } from '@/enums/baseConstant'; import { storeMessage } from '@/utils/message'; import { storePagination } from '@/store/useStorePagination'; -import { fetchAddAdminUser, fetchDeleteAdminUser, fetchGetAdminUserList, fetchQueryUser, fetchUpdateAdminUser, fetchUpdateUserPasswordByAdmin, fetchUpdateUserStatusByAdmin } from '@/api/v1/adminUser'; +import { + fetchAddAdminUser, + fetchDeleteAdminUser, + fetchGetAdminUserList, + fetchQueryUser, + fetchUpdateAdminUser, + fetchUpdateAdminUserByLocalUser, + fetchUpdateUserPasswordByAdmin, + fetchUpdateUserStatusByAdmin, +} from '@/api/v1/adminUser'; /** * 用户信息 Store @@ -60,6 +69,7 @@ export const useAdminUserStore = defineStore('adminUserStore', { return pagination(result); }, + /** 查询用户 */ async queryUser(data: any) { const result = await fetchQueryUser(data); if (result.code !== 200) return []; @@ -72,6 +82,12 @@ export const useAdminUserStore = defineStore('adminUserStore', { return storeMessage(result); }, + /** 修改本地用户信息 */ + async updateAdminUserByLocalUser(data: any) { + const result = await fetchUpdateAdminUserByLocalUser(data); + return storeMessage(result); + }, + /** 修改用户信息 */ async updateAdminUser(data: any) { const result = await fetchUpdateAdminUser(data); diff --git a/src/views/account-settings/index.vue b/src/views/account-settings/index.vue index f504c7d..04f9c33 100644 --- a/src/views/account-settings/index.vue +++ b/src/views/account-settings/index.vue @@ -2,53 +2,19 @@ import { useRouter } from 'vue-router'; import { onBeforeMount, ref } from 'vue'; import { Text } from '@/components/Text'; -import Profile from './profile.vue'; -import Preferences from './references.vue'; -import SecurityLog from './security-log.vue'; import { deviceDetection, useGlobal } from '@pureadmin/utils'; -import AccountManagement from './account-management.vue'; import { useDataThemeChange } from '@/layout/hooks/useDataThemeChange'; import LaySidebarTopCollapse from '@/layout/components/lay-sidebar/components/SidebarTopCollapse.vue'; import leftLine from '@iconify-icons/ri/arrow-left-s-line'; -import ProfileIcon from '@iconify-icons/ri/user-3-line'; -import PreferencesIcon from '@iconify-icons/ri/settings-3-line'; -import SecurityLogIcon from '@iconify-icons/ri/window-line'; -import AccountManagementIcon from '@iconify-icons/ri/profile-line'; import { $t } from '@/plugins/i18n'; import { userInfos } from '@/views/account-settings/utils/hooks'; +import { panes } from '@/views/account-settings/utils/columns'; const router = useRouter(); const isOpen = ref(!deviceDetection()); const { $storage } = useGlobal(); const witchPane = ref('profile'); -const panes = [ - { - key: 'profile', - label: '个人信息', - icon: ProfileIcon, - component: Profile, - }, - { - key: 'preferences', - label: '偏好设置', - icon: PreferencesIcon, - component: Preferences, - }, - { - key: 'securityLog', - label: '安全日志', - icon: SecurityLogIcon, - component: SecurityLog, - }, - { - key: 'accountManagement', - label: '账户管理', - icon: AccountManagementIcon, - component: AccountManagement, - }, -]; - onBeforeMount(() => { useDataThemeChange().dataThemeChange($storage.layout?.overallStyle); }); diff --git a/src/views/account-settings/profile.vue b/src/views/account-settings/profile.vue index 14b43cc..82ea45f 100644 --- a/src/views/account-settings/profile.vue +++ b/src/views/account-settings/profile.vue @@ -3,110 +3,121 @@ import { onMounted, ref } from 'vue'; import { message } from '@/utils/message'; import type { FormInstance } from 'element-plus'; import ReCropperPreview from '@/components/CropperPreview'; -import { createFormData, deviceDetection } from '@pureadmin/utils'; +import { deviceDetection } from '@pureadmin/utils'; import uploadLine from '@iconify-icons/ri/upload-line'; -import { useUserStore } from '@/store/system/user'; import { rules } from '@/views/account-settings/utils/columns'; -import { onSearch, userInfos } from '@/views/account-settings/utils/hooks'; +import { cropperBlob, handleSubmitImage, isShow, onSearchByUserinfo, uploadAvatarSrc, userInfos } from '@/views/account-settings/utils/hooks'; +import { $t } from '@/plugins/i18n'; +import { sexConstant } from '@/enums/baseConstant'; +import { useAdminUserStore } from '@/store/system/adminUser'; -const imgSrc = ref(''); -const cropperBlob = ref(); -const cropRef = ref(); -const uploadRef = ref(); -const isShow = ref(false); const userInfoFormRef = ref(); -const userStore = useUserStore(); +const uploadRef = ref(); +const cropRef = ref(); +// 剪裁完成后头像地址,base64内容 +const imgBase64Src = ref(''); -function queryEmail(queryString, callback) { - const emailList = [{ value: '@qq.com' }, { value: '@126.com' }, { value: '@163.com' }]; - let results = []; - let queryList = []; - emailList.map(item => queryList.push({ value: queryString.split('@')[0] + item.value })); - results = queryString ? queryList.filter(item => item.value.toLowerCase().indexOf(queryString.toLowerCase()) === 0) : queryList; - callback(results); -} - -const onChange = uploadFile => { - const reader = new FileReader(); - reader.onload = e => { - imgSrc.value = e.target.result as string; - isShow.value = true; - }; - reader.readAsDataURL(uploadFile.raw); -}; +const adminUserStore = useAdminUserStore(); +/** 关闭弹窗 */ const handleClose = () => { cropRef.value.hidePopover(); uploadRef.value.clearFiles(); isShow.value = false; }; +/** 剪裁头像 */ const onCropper = ({ blob }) => (cropperBlob.value = blob); -const handleSubmitImage = () => { - const formData = createFormData({ - files: new File([cropperBlob.value], 'avatar'), - }); - // formUpload(formData) - // .then(({ success, data }) => { - // if (success) { - // message('更新头像成功', { type: 'success' }); - // handleClose(); - // } else { - // message('更新头像失败'); - // } - // }) - // .catch(error => { - // message(`提交异常 ${error}`, { type: 'error' }); - // }); +/** 头像修改内容 */ +const onChange = (uploadFile: any) => { + const reader = new FileReader(); + reader.onload = e => { + imgBase64Src.value = e.target.result as string; + isShow.value = true; + console.log(imgBase64Src.value); + }; + reader.readAsDataURL(uploadFile.raw); }; -// 更新信息 +/** 提交表单 */ const onSubmit = async (formEl: FormInstance) => { - await formEl.validate((valid, fields) => { + await formEl.validate(async valid => { if (valid) { - console.log(userInfos); - message('更新信息成功', { type: 'success' }); + // 如果用户修改了头像,将上传的路径赋值进去 + const avatar = uploadAvatarSrc.value; + if (avatar) userInfos.avatar = avatar; + + await adminUserStore.updateAdminUserByLocalUser(userInfos); + await onSearchByUserinfo(); } else { - console.log('Error submit!', fields); + message($t('required_fields'), { type: 'warning' }); } }); }; onMounted(() => { - onSearch(); + onSearchByUserinfo(); });