diff --git a/README.md b/README.md index fbd9826..edfe5f4 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,6 @@ [x] i18n注入 语言全局化实现 [x] 状态管理工具Pinia实现 [x] ElementPlus 组件引入 并且实现i18n -[] 引入unocss 样式 -[] 路由由后端控制实现动态路由 +[x] 路由由后端控制实现动态路由 diff --git a/components.d.ts b/components.d.ts index d3c2e95..ea7172c 100644 --- a/components.d.ts +++ b/components.d.ts @@ -27,6 +27,7 @@ declare module 'vue' { ElDescriptions: typeof import('element-plus/es')['ElDescriptions'] ElDescriptionsItem: typeof import('element-plus/es')['ElDescriptionsItem'] ElDialog: typeof import('element-plus/es')['ElDialog'] + ElDivider: typeof import('element-plus/es')['ElDivider'] ElDrawer: typeof import('element-plus/es')['ElDrawer'] ElDropdown: typeof import('element-plus/es')['ElDropdown'] ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem'] @@ -49,6 +50,8 @@ declare module 'vue' { ElRow: typeof import('element-plus/es')['ElRow'] ElScrollbar: typeof import('element-plus/es')['ElScrollbar'] ElSelect: typeof import('element-plus/es')['ElSelect'] + ElSkeleton: typeof import('element-plus/es')['ElSkeleton'] + ElSkeletonItem: typeof import('element-plus/es')['ElSkeletonItem'] ElSubMenu: typeof import('element-plus/es')['ElSubMenu'] ElTable: typeof import('element-plus/es')['ElTable'] ElTableColumn: typeof import('element-plus/es')['ElTableColumn'] @@ -59,8 +62,10 @@ declare module 'vue' { ElTimelineItem: typeof import('element-plus/es')['ElTimelineItem'] ElTooltip: typeof import('element-plus/es')['ElTooltip'] ElTree: typeof import('element-plus/es')['ElTree'] + EmojiPicker: typeof import('./src/components/comment/emojiPicker.vue')['default'] GlobaIcon: typeof import('./src/components/globaIcon/index.vue')['default'] GlobalIcon: typeof import('./src/components/GlobalIcon/index.vue')['default'] + NameAvatar: typeof import('./src/components/nameAvatar/index.vue')['default'] OverflowTabs: typeof import('./src/components/overflowTabs/index.vue')['default'] PageForm: typeof import('./src/components/pageForm/index.vue')['default'] ProTable: typeof import('./src/components/proTable/index.vue')['default'] @@ -69,6 +74,7 @@ declare module 'vue' { StageBreadcrumbs: typeof import('./src/components/stageBreadcrumbs/index.vue')['default'] StandardMenu: typeof import('./src/components/standardMenu/index.vue')['default'] StandMenu: typeof import('./src/components/standMenu/index.vue')['default'] + Xxx: typeof import('./src/components/comment/xxx.vue')['default'] } export interface GlobalDirectives { vLoading: typeof import('element-plus/es')['ElLoadingDirective'] diff --git a/package.json b/package.json index 8142e89..c948ce4 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "dayjs": "^1.11.19", "sass": "^1.97.1", "typescript": "~5.9.3", + "unicode-emoji-json": "^0.8.0", "unplugin-auto-import": "^20.3.0", "unplugin-vue-components": "^30.0.0", "vite": "^7.2.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c7b74f6..1d3e39e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -51,6 +51,9 @@ importers: typescript: specifier: ~5.9.3 version: 5.9.3 + unicode-emoji-json: + specifier: ^0.8.0 + version: 0.8.0 unplugin-auto-import: specifier: ^20.3.0 version: 20.3.0(@vueuse/core@10.11.1(vue@3.5.26(typescript@5.9.3))) @@ -317,42 +320,36 @@ packages: engines: {node: '>= 10.0.0'} cpu: [arm] os: [linux] - libc: [glibc] '@parcel/watcher-linux-arm-musl@2.5.1': resolution: {integrity: sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==} engines: {node: '>= 10.0.0'} cpu: [arm] os: [linux] - libc: [musl] '@parcel/watcher-linux-arm64-glibc@2.5.1': resolution: {integrity: sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [linux] - libc: [glibc] '@parcel/watcher-linux-arm64-musl@2.5.1': resolution: {integrity: sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [linux] - libc: [musl] '@parcel/watcher-linux-x64-glibc@2.5.1': resolution: {integrity: sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [linux] - libc: [glibc] '@parcel/watcher-linux-x64-musl@2.5.1': resolution: {integrity: sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [linux] - libc: [musl] '@parcel/watcher-win32-arm64@2.5.1': resolution: {integrity: sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==} @@ -413,67 +410,56 @@ packages: resolution: {integrity: sha512-EHMUcDwhtdRGlXZsGSIuXSYwD5kOT9NVnx9sqzYiwAc91wfYOE1g1djOEDseZJKKqtHAHGwnGPQu3kytmfaXLQ==} cpu: [arm] os: [linux] - libc: [glibc] '@rollup/rollup-linux-arm-musleabihf@4.54.0': resolution: {integrity: sha512-+pBrqEjaakN2ySv5RVrj/qLytYhPKEUwk+e3SFU5jTLHIcAtqh2rLrd/OkbNuHJpsBgxsD8ccJt5ga/SeG0JmA==} cpu: [arm] os: [linux] - libc: [musl] '@rollup/rollup-linux-arm64-gnu@4.54.0': resolution: {integrity: sha512-NSqc7rE9wuUaRBsBp5ckQ5CVz5aIRKCwsoa6WMF7G01sX3/qHUw/z4pv+D+ahL1EIKy6Enpcnz1RY8pf7bjwng==} cpu: [arm64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-arm64-musl@4.54.0': resolution: {integrity: sha512-gr5vDbg3Bakga5kbdpqx81m2n9IX8M6gIMlQQIXiLTNeQW6CucvuInJ91EuCJ/JYvc+rcLLsDFcfAD1K7fMofg==} cpu: [arm64] os: [linux] - libc: [musl] '@rollup/rollup-linux-loong64-gnu@4.54.0': resolution: {integrity: sha512-gsrtB1NA3ZYj2vq0Rzkylo9ylCtW/PhpLEivlgWe0bpgtX5+9j9EZa0wtZiCjgu6zmSeZWyI/e2YRX1URozpIw==} cpu: [loong64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-ppc64-gnu@4.54.0': resolution: {integrity: sha512-y3qNOfTBStmFNq+t4s7Tmc9hW2ENtPg8FeUD/VShI7rKxNW7O4fFeaYbMsd3tpFlIg1Q8IapFgy7Q9i2BqeBvA==} cpu: [ppc64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-riscv64-gnu@4.54.0': resolution: {integrity: sha512-89sepv7h2lIVPsFma8iwmccN7Yjjtgz0Rj/Ou6fEqg3HDhpCa+Et+YSufy27i6b0Wav69Qv4WBNl3Rs6pwhebQ==} cpu: [riscv64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-riscv64-musl@4.54.0': resolution: {integrity: sha512-ZcU77ieh0M2Q8Ur7D5X7KvK+UxbXeDHwiOt/CPSBTI1fBmeDMivW0dPkdqkT4rOgDjrDDBUed9x4EgraIKoR2A==} cpu: [riscv64] os: [linux] - libc: [musl] '@rollup/rollup-linux-s390x-gnu@4.54.0': resolution: {integrity: sha512-2AdWy5RdDF5+4YfG/YesGDDtbyJlC9LHmL6rZw6FurBJ5n4vFGupsOBGfwMRjBYH7qRQowT8D/U4LoSvVwOhSQ==} cpu: [s390x] os: [linux] - libc: [glibc] '@rollup/rollup-linux-x64-gnu@4.54.0': resolution: {integrity: sha512-WGt5J8Ij/rvyqpFexxk3ffKqqbLf9AqrTBbWDk7ApGUzaIs6V+s2s84kAxklFwmMF/vBNGrVdYgbblCOFFezMQ==} cpu: [x64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-x64-musl@4.54.0': resolution: {integrity: sha512-JzQmb38ATzHjxlPHuTH6tE7ojnMKM2kYNzt44LO/jJi8BpceEC8QuXYA908n8r3CNuG/B3BV8VR3Hi1rYtmPiw==} cpu: [x64] os: [linux] - libc: [musl] '@rollup/rollup-openharmony-arm64@4.54.0': resolution: {integrity: sha512-huT3fd0iC7jigGh7n3q/+lfPcXxBi+om/Rs3yiFxjvSxbSB6aohDFXbWvlspaqjeOh+hx7DDHS+5Es5qRkWkZg==} @@ -959,6 +945,9 @@ packages: undici-types@7.16.0: resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} + unicode-emoji-json@0.8.0: + resolution: {integrity: sha512-3wDXXvp6YGoKGhS2O2H7+V+bYduOBydN1lnI0uVfr1cIdY02uFFiEH1i3kE5CCE4l6UqbLKVmEFW9USxTAMD1g==} + unimport@5.6.0: resolution: {integrity: sha512-8rqAmtJV8o60x46kBAJKtHpJDJWkA2xcBqWKPI14MgUb05o1pnpnCnXSxedUXyeq7p8fR5g3pTo2BaswZ9lD9A==} engines: {node: '>=18.12.0'} @@ -1872,6 +1861,8 @@ snapshots: undici-types@7.16.0: {} + unicode-emoji-json@0.8.0: {} + unimport@5.6.0: dependencies: acorn: 8.15.0 diff --git a/src/api/stage/dict/index.ts b/src/api/stage/dict/index.ts index 702d96a..d8793f9 100644 --- a/src/api/stage/dict/index.ts +++ b/src/api/stage/dict/index.ts @@ -66,26 +66,26 @@ export const saveDictTypeValue = (id:string,data: addDataProps) => { // 删除字典类型值 export const deleteDictTypeValue = (typeId:string,id: string) => { - return request.delete(`/auth/v1/backend/dict/${typeId}/${id}`); + return request.delete(`/auth/v1/backend/dict/type/${typeId}/${id}`); }; // 更新字典类型值 export const updateDictTypeValue = (typeId:string,id: string,data: addDataProps) => { - return request.put(`/auth/v1/backend/dict/${typeId}/${id}`, data); + return request.put(`/auth/v1/backend/dict/type/${typeId}/${id}`, data); }; // 获取下级菜单数据 -export const getNextDictMenu = (id:string,parentId:string) => { - return request.get(`/auth/v1/backend/dict/type/${id}/data/${parentId}`); +export const getNextDictMenu = (id:string,parentId:string,params: paramsProps) => { + return request.get(`/auth/v1/backend/dict/type/${id}/data/${parentId}`,params); }; // 启用接口 -export const enableTypeDict = (id:string)=>{ +export const enableTypeDict = (typeId:string,id:string)=>{ return request.post(`/auth/v1/backend/dict/type/${typeId}/${id}/enable`); } // 禁用接口 -export const disableTypeDict = (id:string)=>{ +export const disableTypeDict = (typeId:string,id:string)=>{ return request.post(`/auth/v1/backend/dict/type/${typeId}/${id}/disable`) } \ No newline at end of file diff --git a/src/components/comment/index.vue b/src/components/comment/index.vue deleted file mode 100644 index 6f8cbe1..0000000 --- a/src/components/comment/index.vue +++ /dev/null @@ -1,329 +0,0 @@ - - - - - - - - - - - - - - {{ item.nickname }} - 作者 - - {{ item.content }} - - - - - - - - {{ reply.nickname }} - - 回复 - @{{ reply.replyTo }} - - : - {{ reply.content }} - - - - - - - - - - - - - - - - - - - - diff --git a/src/components/nameAvatar/index.vue b/src/components/nameAvatar/index.vue new file mode 100644 index 0000000..dbdc516 --- /dev/null +++ b/src/components/nameAvatar/index.vue @@ -0,0 +1,57 @@ + + + {{ displayText }} + + + + + + \ No newline at end of file diff --git a/src/components/proTable/index.vue b/src/components/proTable/index.vue index 2747d2e..ac362b3 100644 --- a/src/components/proTable/index.vue +++ b/src/components/proTable/index.vue @@ -1,12 +1,20 @@ - - + + - {{ scope.row[col.prop] || "-" }} + {{ + scope.row[col.prop] || "-" + }} @@ -22,7 +30,78 @@ - + + + + + + + {{ + typeof btn.label === "function" + ? btn.label(scope.row) + : btn.label + }} + + + + + + + + {{ col.dropdownText || "更多" }} + + + + + + + + + {{ + typeof btn.label === "function" + ? btn.label(scope.row) + : btn.label + }} + + + + + + + + + @@ -54,7 +133,7 @@ diff --git a/src/dict/dictManage.ts b/src/dict/dictManage.ts index 869fc8a..5caa140 100644 --- a/src/dict/dictManage.ts +++ b/src/dict/dictManage.ts @@ -10,7 +10,7 @@ const statusDict = { // 字典状态颜色 const statusDictColor = { 1:'#66E5BE', - 0:'#ff0000' + 0:'#90A1B9' } // 设置字典转换为目标格式 diff --git a/src/main.ts b/src/main.ts index f21d593..ef4f676 100644 --- a/src/main.ts +++ b/src/main.ts @@ -21,13 +21,16 @@ const app = createApp(App); // 导入全局的i18n文件 const loadLocalMessages = async () => { const messages: Record = {}; - const locales = import.meta.glob("./locales/*.ts", { eager: true }); + const locales = import.meta.glob(["./locales/*.ts","./modules/**/locales/*.ts"], { eager: true }); // 遍历所有匹配的文件 Object.keys(locales).forEach((path) => { - const lang = path.match(/\.\/locales\/(.+)\.ts$/)?.[1]; + const lang = path.match(/.*\/locales\/(.+)\.ts$/)?.[1]; if (lang && locales[path]) { - messages[lang] = locales[path].default; + if (!messages[lang]) { + messages[lang] = {}; + } + messages[lang] = { ...messages[lang], ...locales[path].default }; } }); diff --git a/src/modules/Comment/emojiPicker.vue b/src/modules/Comment/emojiPicker.vue new file mode 100644 index 0000000..0c6eda1 --- /dev/null +++ b/src/modules/Comment/emojiPicker.vue @@ -0,0 +1,84 @@ + + + + + 😊 + + + + + + {{ emoji }} + + + + + + + + + diff --git a/src/modules/Comment/index.vue b/src/modules/Comment/index.vue new file mode 100644 index 0000000..58f8f72 --- /dev/null +++ b/src/modules/Comment/index.vue @@ -0,0 +1,539 @@ + + + + + + + + + + + + + + + + onSelectEmoji(e, 'main')" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {{ item.nickname }} + {{ item.time }} + + + + + + + + 回复 + + + 删除 + + + + + + + + + + + {{ reply.nickname }} + 回复 + @{{ reply.replyTo }} + + {{ reply.time }} + + {{ reply.content }} + + + + 回复 + + + + 删除 + + + + + + + + + + + + + + onSelectEmoji(e, 'reply')" + /> + + + + + + + + + + + + + + + + + + + diff --git a/src/modules/Comment/locales/en.ts b/src/modules/Comment/locales/en.ts new file mode 100644 index 0000000..9f82ab0 --- /dev/null +++ b/src/modules/Comment/locales/en.ts @@ -0,0 +1,7 @@ +export default { + comment: { + placeholder: 'Enter your comment', + send:'Send', + reply:'Reply' + }, +} \ No newline at end of file diff --git a/src/modules/Comment/locales/zh.ts b/src/modules/Comment/locales/zh.ts new file mode 100644 index 0000000..8652191 --- /dev/null +++ b/src/modules/Comment/locales/zh.ts @@ -0,0 +1,7 @@ +export default { + comment: { + placeholder: '输入评论', + send:'发送', + reply:'回复' + }, +} \ No newline at end of file diff --git a/src/modules/Comment/useEmoji.ts b/src/modules/Comment/useEmoji.ts new file mode 100644 index 0000000..6014cc2 --- /dev/null +++ b/src/modules/Comment/useEmoji.ts @@ -0,0 +1,18 @@ +// useEmoji.ts +import emojiData from 'unicode-emoji-json' + +export function useEmoji() { + const getEmotionList = (): string[] => { + return Object.keys(emojiData).filter(key => { + const item = emojiData[key]; + return emojiData[key].group === 'Smileys & Emotion' && parseFloat(item.emoji_version) <= 12.0 + }) + } + + // 预先生成好数据,避免组件每次渲染都执行过滤逻辑 + const emotionList = getEmotionList() + + return { + emotionList + } +} \ No newline at end of file diff --git a/src/pages/Layout/rightMenuGroup.vue b/src/pages/Layout/rightMenuGroup.vue index 77ba64a..8cc0780 100644 --- a/src/pages/Layout/rightMenuGroup.vue +++ b/src/pages/Layout/rightMenuGroup.vue @@ -19,7 +19,7 @@ {{ userInfo.username }} SUPER ADMIN - + @@ -50,6 +50,7 @@ diff --git a/src/pages/stage/dict/dictFieldLevelManage.vue b/src/pages/stage/dict/dictFieldLevelManage.vue index 0f14172..e7df0b1 100644 --- a/src/pages/stage/dict/dictFieldLevelManage.vue +++ b/src/pages/stage/dict/dictFieldLevelManage.vue @@ -41,7 +41,7 @@ 停用 - + { await formEl.validate(async (valid, fields) => { if (valid) { loading.value = true; + console.log("获取外部的数据信息:",form,parentId) + // 如果是一级新增字段就是parentId为0 如果是添加二级字段就是parentId为父级的id try { const response = row.id ? await updateDictTypeValue(parentId,row.id,form) : await saveDictTypeValue(parentId,form); ElMessage.success(row.id ? '修改成功' : '新增成功'); diff --git a/src/pages/stage/dict/dictManage.vue b/src/pages/stage/dict/dictManage.vue index ca1da94..4715bbd 100644 --- a/src/pages/stage/dict/dictManage.vue +++ b/src/pages/stage/dict/dictManage.vue @@ -29,7 +29,7 @@ : - + diff --git a/src/pages/stage/dict/index.vue b/src/pages/stage/dict/index.vue index f41e8af..b59ed10 100644 --- a/src/pages/stage/dict/index.vue +++ b/src/pages/stage/dict/index.vue @@ -12,7 +12,11 @@ 条件筛选 - 重置 @@ -35,7 +39,12 @@ - 应用筛选 + 应用筛选 @@ -84,7 +93,7 @@ - + @@ -112,7 +121,12 @@ import CommonTable from "@/components/proTable/index.vue"; import dictFieldConfig from "./dictFieldConfig.vue"; import dictManage from "./dictManage.vue"; import dayjs from "dayjs"; -import { getDictValues, deleteDictValue,disableDict,enableDict } from "@/api/stage/dict"; +import { + getDictValues, + deleteDictValue, + disableDict, + enableDict, +} from "@/api/stage/dict"; import { DictManage } from "@/dict"; import { formatIndex } from "@/utils/utils"; import { ElMessage } from "element-plus"; @@ -164,33 +178,60 @@ const columns = [ }, }, { - prop:'updateByName', - label:'最后修改人', - align:'center' + prop: "updateByName", + label: "最后修改人", + align: "center", + }, + { + prop: "actions", + label: "操作", + align: "right", + width: "300", + actions: [ + { + label: "编辑", + type: "primary", + link:true, + permission: ["edit"], + onClick: (row) => handleEdit(row), + }, + { + label: "字段配置", + type: "primary", + link:true, + permission: ["config"], + onClick: (row) => handlefieldsConfig(row), + }, + { + label: "删除", + type: "danger", + link:true, + permission: ["delete"], + onClick: (row) => handleDelete(row), + } + ], }, - { prop: "actions", label: "操作", align: "right", width: "200" }, ]; // 返回的data数据信息 const dataValue = ref([]); - // popover关闭事件 -const onPopoverHide = () =>{ - filterForm.status = ''; -} +const onPopoverHide = () => { + filterForm.status = ""; +}; // 筛选重置 -const onReset = () =>{ - filterForm.status = ''; +const onReset = () => { + filterForm.status = ""; fetchTableData(); -} +}; // 获取当前的table数据信息 const getTableData = async (params) => { try { const response = await getDictValues({ ...params, keyword: searchVal.value, - ...filterForm + ...filterForm, }); return response; } catch (error) { @@ -201,26 +242,30 @@ const getTableData = async (params) => { const fetchTableData = () => { dictTableRef.value && dictTableRef.value.refresh(); }; +const clearSelectItem = () => { + Object.assign(selectItem,{id:null,name:'',key:'',status:1,remark:''}) +}; // 新增字典信息 const addDict = () => { dictVisible.value = true; + clearSelectItem(); }; // 编辑字典信息 const handleEdit = (item) => { - addDict(); + dictVisible.value = true; Object.assign(selectItem, item); }; // 启用-禁用事件 -const handleDictStatus = async (row)=>{ - try { - row.status === 1 ? await disableDict(row.id) : await enableDict(row.id); - ElMessage.success('操作成功'); - onConfirmSuccess(); - } catch (error) { - console.log('error',error); - } -} +const handleDictStatus = async (row) => { + try { + row.status === 1 ? await disableDict(row.id) : await enableDict(row.id); + ElMessage.success("操作成功"); + onConfirmSuccess(); + } catch (error) { + console.log("error", error); + } +}; // 刷新Table数据信息 const onConfirmSuccess = () => { @@ -228,7 +273,7 @@ const onConfirmSuccess = () => { }; // TODO:字段配置 const handlefieldsConfig = (ite) => { - fieldsConfigRef.value.open(ite); + fieldsConfigRef.value.open({ ...ite, parentId: ite.id }); }; // 删除字典类型数据 diff --git a/src/pages/stage/personnel/index.vue b/src/pages/stage/personnel/index.vue index 2fdf53c..8ac9516 100644 --- a/src/pages/stage/personnel/index.vue +++ b/src/pages/stage/personnel/index.vue @@ -4,7 +4,7 @@