From d54810ab0246a489d4ec36e436a47ee349735034 Mon Sep 17 00:00:00 2001 From: chansee97 Date: Tue, 26 Aug 2025 22:53:09 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AF=B9=E6=8E=A5=E5=90=8E=E7=AB=AF?= =?UTF-8?q?=E7=99=BB=E5=BD=95=E5=92=8C=E8=8F=9C=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build/plugins.ts | 2 + locales/en_US.json | 1 - locales/zh_CN.json | 1 - package.json | 17 +- src/AppMain.vue | 15 +- src/components/common/IconSelect.vue | 95 +++++- src/hooks/usePermission.ts | 8 +- src/layouts/components/header/UserCenter.vue | 2 +- src/router/routes.static.ts | 78 ++--- src/service/api/{system.ts => demo.ts} | 13 +- src/service/api/list.ts | 5 - src/service/api/login.ts | 53 +++- src/service/api/system/dict.ts | 119 +++++++ src/service/api/system/menu.ts | 49 +++ src/service/api/system/role.ts | 50 +++ src/service/api/system/user.ts | 51 +++ src/service/http/alova.ts | 30 +- src/service/http/config.ts | 3 - src/service/http/handle.ts | 75 +---- src/service/http/type.d.ts | 24 ++ src/service/index.ts | 7 +- src/store/auth.ts | 49 +-- src/store/dict.ts | 18 +- src/store/router/helper.ts | 15 +- src/store/router/index.ts | 10 +- src/typings/api/login.d.ts | 17 - src/typings/entities/dict.d.ts | 63 +++- src/typings/entities/menu.d.ts | 78 +++++ src/typings/entities/message.d.ts | 2 +- src/typings/entities/role.d.ts | 33 +- src/typings/entities/user.d.ts | 43 ++- src/typings/global.d.ts | 22 +- src/typings/route.d.ts | 2 +- src/typings/service.d.ts | 49 --- src/utils/array.ts | 37 --- src/utils/i18n.ts | 3 +- src/utils/index.ts | 1 - .../build-in/login/components/Login/index.vue | 115 +++++-- src/views/build-in/user-center/index.vue | 136 ++++---- src/views/demo/dict/index.vue | 16 +- .../demo/fetch/components/RefreshToken.vue | 4 +- .../demo/permission/permission/index.vue | 2 +- src/views/setting/account/columns.tsx | 110 +++++++ .../setting/account/components/TableModal.vue | 122 +++++--- src/views/setting/account/index.vue | 143 +++------ src/views/setting/dictionary/columns.tsx | 144 +++++++++ .../dictionary/components/DictModal.vue | 70 ++++- src/views/setting/dictionary/index.vue | 171 ++++------ src/views/setting/menu/columns.tsx | 109 +++++++ .../setting/menu/components/DirectoryForm.vue | 43 +++ .../setting/menu/components/MenuModal.vue | 171 ++++++++++ .../setting/menu/components/PageForm.vue | 82 +++++ .../menu/components/PermissionForm.vue | 22 ++ .../setting/menu/components/TableModal.vue | 296 ------------------ src/views/setting/menu/index.vue | 233 +++++--------- 55 files changed, 1952 insertions(+), 1177 deletions(-) rename src/service/api/{system.ts => demo.ts} (54%) delete mode 100644 src/service/api/list.ts create mode 100644 src/service/api/system/dict.ts create mode 100644 src/service/api/system/menu.ts create mode 100644 src/service/api/system/role.ts create mode 100644 src/service/api/system/user.ts create mode 100644 src/service/http/type.d.ts delete mode 100644 src/typings/api/login.d.ts create mode 100644 src/typings/entities/menu.d.ts delete mode 100644 src/typings/service.d.ts delete mode 100644 src/utils/array.ts create mode 100644 src/views/setting/account/columns.tsx create mode 100644 src/views/setting/dictionary/columns.tsx create mode 100644 src/views/setting/menu/columns.tsx create mode 100644 src/views/setting/menu/components/DirectoryForm.vue create mode 100644 src/views/setting/menu/components/MenuModal.vue create mode 100644 src/views/setting/menu/components/PageForm.vue create mode 100644 src/views/setting/menu/components/PermissionForm.vue delete mode 100644 src/views/setting/menu/components/TableModal.vue diff --git a/build/plugins.ts b/build/plugins.ts index c82ea60..59f7e11 100644 --- a/build/plugins.ts +++ b/build/plugins.ts @@ -7,6 +7,7 @@ import { FileSystemIconLoader } from 'unplugin-icons/loaders' import IconsResolver from 'unplugin-icons/resolver' import Icons from 'unplugin-icons/vite' import { NaiveUiResolver } from 'unplugin-vue-components/resolvers' +import { ProNaiveUIResolver } from 'pro-naive-ui-resolver' import Components from 'unplugin-vue-components/vite' import viteCompression from 'vite-plugin-compression' import VueDevTools from 'vite-plugin-vue-devtools' @@ -65,6 +66,7 @@ export function createVitePlugins(env: ImportMetaEnv) { ], }), NaiveUiResolver(), + ProNaiveUIResolver(), ], }), diff --git a/locales/en_US.json b/locales/en_US.json index 4866218..e0d3393 100644 --- a/locales/en_US.json +++ b/locales/en_US.json @@ -70,7 +70,6 @@ "signInTitle": "Login", "accountRuleTip": "Please enter account", "passwordRuleTip": "Please enter password", - "or": "Or", "rememberMe": "Remember me", "forgotPassword": "Forget the password?", "signIn": "Sign in", diff --git a/locales/zh_CN.json b/locales/zh_CN.json index cceb930..547bc86 100644 --- a/locales/zh_CN.json +++ b/locales/zh_CN.json @@ -101,7 +101,6 @@ "passwordPlaceholder": "输入密码", "accountRuleTip": "请输入账户", "passwordRuleTip": "请输入密码", - "or": "其他", "signIn": "登录", "rememberMe": "记住我", "forgotPassword": "忘记密码?", diff --git a/package.json b/package.json index 6a9e5c7..70dd662 100644 --- a/package.json +++ b/package.json @@ -37,28 +37,28 @@ "UnoCSS" ], "scripts": { - "dev": "vite --mode dev --port 9980", + "dev": "vite --mode dev", "dev:prod": "vite --mode production", "build": "vite build", - "build:dev": "vite build --mode dev", - "preview": "vite preview --port 9981", + "preview": "vite preview", "lint": "eslint . && vue-tsc --noEmit", "lint:fix": "eslint . --fix", "lint:check": "npx @eslint/config-inspector", "sizecheck": "npx vite-bundle-visualizer" }, "dependencies": { - "@vueuse/core": "^13.6.0", + "@vueuse/core": "^13.7.0", "alova": "^3.3.4", + "array-to-tree": "^3.3.2", "colord": "^2.9.3", - "echarts": "^5.6.0", + "echarts": "^6.0.0", "md-editor-v3": "^5.6.1", "pinia": "^3.0.3", - "pinia-plugin-persistedstate": "^4.4.1", - "pro-naive-ui": "^2.4.3", + "pinia-plugin-persistedstate": "^4.5.0", + "pro-naive-ui": "^3.0.3", "quill": "^2.0.3", "radash": "^12.1.1", - "vue": "^3.5.18", + "vue": "^3.5.20", "vue-draggable-plus": "^0.6.0", "vue-i18n": "^11.1.11", "vue-router": "^4.5.1" @@ -73,6 +73,7 @@ "eslint": "^9.29.0", "lint-staged": "^16.1.2", "naive-ui": "^2.42.0", + "pro-naive-ui-resolver": "^1.0.2", "sass": "^1.89.2", "simple-git-hooks": "^2.13.1", "typescript": "^5.8.3", diff --git a/src/AppMain.vue b/src/AppMain.vue index d37c9d8..34ec3c0 100644 --- a/src/AppMain.vue +++ b/src/AppMain.vue @@ -38,11 +38,20 @@ const appStore = useAppStore() const naiveLocale = computed(() => { return naiveI18nOptions[appStore.lang] ? naiveI18nOptions[appStore.lang] : naiveI18nOptions.enUS }) + +const propOverrides = { + ProModalForm: { + labelWidth: 120, + labelPlacement: 'left', + preset: 'card', + }, +} diff --git a/src/components/common/IconSelect.vue b/src/components/common/IconSelect.vue index 2736a70..e95dd73 100644 --- a/src/components/common/IconSelect.vue +++ b/src/components/common/IconSelect.vue @@ -20,9 +20,96 @@ const value = defineModel('value', { type: String }) // 包含的图标库系列名,更多:https://icon-sets.iconify.design/ const nameList = ['icon-park-outline', 'carbon', 'ant-design'] +interface CacheItem { + data: IconList +} + // 获取单个图标库数据 async function fetchIconList(name: string): Promise { - return await fetch(`https://api.iconify.design/collection?prefix=${name}`).then(res => res.json()) + const cacheKey = `icon_list_${name}` + + try { + // 先从sessionStorage读取缓存 + const cachedData = sessionStorage.getItem(cacheKey) + if (cachedData) { + const cache: CacheItem = JSON.parse(cachedData) + + // 如果缓存数据存在,直接返回 + if (cache.data) { + return cache.data + } + } + } + catch (error) { + console.warn(`读取图标库缓存失败: ${name}`, error) + } + + try { + // 缓存不存在,从API获取数据 + const data = await fetch(`https://api.iconify.design/collection?prefix=${name}`) + .then(res => res.json()) + + // 将数据缓存到sessionStorage + try { + const cacheItem: CacheItem = { + data, + } + sessionStorage.setItem(cacheKey, JSON.stringify(cacheItem)) + } + catch (cacheError) { + console.warn(`缓存图标库数据失败: ${name}`, cacheError) + } + + return data + } + catch (error) { + console.error(`获取图标库数据失败: ${name}`, error) + + // 如果API请求失败,尝试使用缓存数据作为降级方案 + try { + const cachedData = sessionStorage.getItem(cacheKey) + if (cachedData) { + const cache: CacheItem = JSON.parse(cachedData) + if (cache.data) { + return cache.data + } + } + } + catch (fallbackError) { + console.warn(`读取降级缓存失败: ${name}`, fallbackError) + } + + // 如果所有方法都失败,返回空的图标库数据 + return { + prefix: name, + icons: [], + title: name, + total: 0, + categories: {}, + uncategorized: [], + } + } +} + +// 清除指定图标库的缓存 +function clearIconCache(name?: string) { + try { + if (name) { + // 清除指定图标库的缓存 + const cacheKey = `icon_list_${name}` + sessionStorage.removeItem(cacheKey) + } + else { + // 清除所有图标库缓存 + nameList.forEach((iconName) => { + const cacheKey = `icon_list_${iconName}` + sessionStorage.removeItem(cacheKey) + }) + } + } + catch (error) { + console.warn('清除图标库缓存失败:', error) + } } // 获取所有图标库数据 @@ -62,6 +149,12 @@ onMounted(async () => { iconList.value = await fetchIconAllList(nameList) }) +// 在开发环境下暴露清除缓存函数到全局,方便调试 +if (import.meta.env.DEV) { + // @ts-expect-error 开发环境下扩展window对象 + window.clearIconCache = clearIconCache +} + // 当前tab const currentTab = shallowRef(0) // 当前tag diff --git a/src/hooks/usePermission.ts b/src/hooks/usePermission.ts index 27fcab3..59c751a 100644 --- a/src/hooks/usePermission.ts +++ b/src/hooks/usePermission.ts @@ -13,18 +13,18 @@ export function usePermission() { if (!authStore.userInfo) return false - const { role } = authStore.userInfo + const { roles } = authStore.userInfo // 角色为super可直接通过 - let has = role.includes('super') + let has = roles.includes('super') if (!has) { if (isArray(permission)) // 角色为数组, 判断是否有交集 - has = permission.some(i => role.includes(i)) + has = permission.some(i => roles.includes(i)) if (isString(permission)) // 角色为字符串, 判断是否包含 - has = role.includes(permission) + has = roles.includes(permission) } return has } diff --git a/src/layouts/components/header/UserCenter.vue b/src/layouts/components/header/UserCenter.vue index 88837f5..daba447 100644 --- a/src/layouts/components/header/UserCenter.vue +++ b/src/layouts/components/header/UserCenter.vue @@ -83,7 +83,7 @@ function handleSelect(key: string | number) {