diff --git a/apps/admin/package.json b/apps/admin/package.json index e778b6a..b0549f2 100644 --- a/apps/admin/package.json +++ b/apps/admin/package.json @@ -56,7 +56,7 @@ "@vueuse/core": "^9.13.0", "@vueuse/shared": "^9.13.0", "@zxcvbn-ts/core": "^2.2.1", - "ant-design-vue": "^3.2.20", + "ant-design-vue": "^4.0.6", "axios": "^1.6.0", "codemirror": "^5.65.15", "cropperjs": "^1.6.1", @@ -71,6 +71,7 @@ "nprogress": "^0.2.0", "path-to-regexp": "^6.2.1", "pinia": "2.0.33", + "pinia-plugin-persistedstate": "^3.2.0", "print-js": "^1.6.0", "qrcode": "^1.5.3", "qs": "^6.11.2", @@ -124,4 +125,4 @@ "node": ">=16.15.1", "pnpm": ">=8.1.0" } -} +} \ No newline at end of file diff --git a/apps/admin/src/App.vue b/apps/admin/src/App.vue index a4d2e80..303d31a 100644 --- a/apps/admin/src/App.vue +++ b/apps/admin/src/App.vue @@ -1,5 +1,5 @@ diff --git a/apps/admin/src/components/Button/src/BasicButton.vue b/apps/admin/src/components/Button/src/BasicButton.vue index 19e6dbb..b8cfcaa 100644 --- a/apps/admin/src/components/Button/src/BasicButton.vue +++ b/apps/admin/src/components/Button/src/BasicButton.vue @@ -1,5 +1,8 @@ diff --git a/apps/admin/src/components/Upload/src/FileList.vue b/apps/admin/src/components/Upload/src/FileList.vue index ddb087e..c3b6534 100644 --- a/apps/admin/src/components/Upload/src/FileList.vue +++ b/apps/admin/src/components/Upload/src/FileList.vue @@ -21,49 +21,52 @@ const { columns, actionColumn, dataSource } = props; const columnList = [...columns, actionColumn]; return ( - - - {columnList.map((item) => { - const { width = 0, dataIndex } = item; - const style: CSSProperties = { - width: `${width}px`, - minWidth: `${width}px`, - }; - return ; - })} - - - + // x scrollbar +
+
+ {columnList.map((item) => { - const { title = '', align = 'center', dataIndex } = item; + const { width = 0, dataIndex } = item; + const style: CSSProperties = { + width: `${width}px`, + minWidth: `${width}px`, + }; + return ; + })} + + + + {columnList.map((item) => { + const { title = '', align = 'center', dataIndex } = item; + return ( + + ); + })} + + + + {dataSource.map((record = {}, index) => { return ( - + + {columnList.map((item) => { + const { dataIndex = '', customRender, align = 'center' } = item; + const render = customRender && isFunction(customRender); + return ( + + ); + })} + ); })} - - - - {dataSource.map((record = {}, index) => { - return ( - - {columnList.map((item) => { - const { dataIndex = '', customRender, align = 'center' } = item; - const render = customRender && isFunction(customRender); - return ( - - ); - })} - - ); - })} - -
+ {title} +
- {title} -
+ {render + ? customRender?.({ text: record[dataIndex], record }) + : record[dataIndex]} +
- {render - ? customRender?.({ text: record[dataIndex], record }) - : record[dataIndex]} -
+ + + ); }; }, diff --git a/apps/admin/src/components/Upload/src/UploadModal.vue b/apps/admin/src/components/Upload/src/UploadModal.vue index 268e560..528b034 100644 --- a/apps/admin/src/components/Upload/src/UploadModal.vue +++ b/apps/admin/src/components/Upload/src/UploadModal.vue @@ -46,7 +46,6 @@ import { defineComponent, reactive, ref, toRefs, unref, computed, PropType } from 'vue'; import { Upload, Alert } from 'ant-design-vue'; import { BasicModal, useModalInner } from '/@/components/Modal'; - // import { BasicTable, useTable } from '/@/components/Table'; // hooks import { useUploadType } from './useUpload'; import { useMessage } from '/@/hooks/web/useMessage'; @@ -165,14 +164,6 @@ emit('delete', record); } - // 预览 - // function handlePreview(record: FileItem) { - // const { thumbUrl = '' } = record; - // createImgPreview({ - // imageList: [thumbUrl], - // }); - // } - async function uploadApiByItem(item: FileItem) { const { api } = props; if (!api || !isFunction(api)) { @@ -276,15 +267,14 @@ } return { - columns: createTableColumns() as any[], - actionColumn: createActionColumn(handleRemove) as any, + columns: createTableColumns(), + actionColumn: createActionColumn(handleRemove), register, closeModal, getHelpText, getStringAccept, getOkButtonProps, beforeUpload, - // registerTable, fileListRef, state, isUploadingRef, diff --git a/apps/admin/src/components/Upload/src/UploadPreviewModal.vue b/apps/admin/src/components/Upload/src/UploadPreviewModal.vue index bc4091b..b66c777 100644 --- a/apps/admin/src/components/Upload/src/UploadPreviewModal.vue +++ b/apps/admin/src/components/Upload/src/UploadPreviewModal.vue @@ -12,7 +12,6 @@ + diff --git a/apps/admin/src/layouts/default/header/components/FullScreen.vue b/apps/admin/src/layouts/default/header/components/FullScreen.vue index 1304e8c..2e124b5 100644 --- a/apps/admin/src/layouts/default/header/components/FullScreen.vue +++ b/apps/admin/src/layouts/default/header/components/FullScreen.vue @@ -13,6 +13,7 @@ import { useFullscreen } from '@vueuse/core'; import { FullscreenExitOutlined, FullscreenOutlined } from '@ant-design/icons-vue'; + export default defineComponent({ name: 'FullScreen', components: { FullscreenExitOutlined, FullscreenOutlined, Tooltip }, diff --git a/apps/admin/src/layouts/default/header/components/lock/LockModal.vue b/apps/admin/src/layouts/default/header/components/lock/LockModal.vue index 4e098eb..3a17ec6 100644 --- a/apps/admin/src/layouts/default/header/components/lock/LockModal.vue +++ b/apps/admin/src/layouts/default/header/components/lock/LockModal.vue @@ -34,6 +34,7 @@ import { useUserStore } from '/@/store/modules/user'; import { useLockStore } from '/@/store/modules/lock'; import headerImg from '/@/assets/images/header.jpg'; + export default defineComponent({ name: 'LockModal', components: { BasicModal, BasicForm }, @@ -47,7 +48,7 @@ const getRealName = computed(() => userStore.getUserInfo?.realName); const [register, { closeModal }] = useModalInner(); - const [registerForm, { validateFields, resetFields }] = useForm({ + const [registerForm, { validate, resetFields }] = useForm({ showActionButtonGroup: false, schemas: [ { @@ -62,17 +63,20 @@ ], }); - async function handleLock() { - const values = (await validateFields()) as any; - const password: string | undefined = values.password; + const handleLock = async () => { + const { password = '' } = await validate<{ + password: string; + }>(); + closeModal(); lockStore.setLockInfo({ isLock: true, pwd: password, }); + await resetFields(); - } + }; const avatar = computed(() => { const { avatar } = userStore.getUserInfo; diff --git a/apps/admin/src/layouts/default/header/components/notify/NoticeList.vue b/apps/admin/src/layouts/default/header/components/notify/NoticeList.vue index a309266..47e1e24 100644 --- a/apps/admin/src/layouts/default/header/components/notify/NoticeList.vue +++ b/apps/admin/src/layouts/default/header/components/notify/NoticeList.vue @@ -59,13 +59,23 @@ import { useDesign } from '/@/hooks/web/useDesign'; import { List, Avatar, Tag, Typography } from 'ant-design-vue'; import { isNumber } from '/@/utils/is'; + + // types + import type { StyleValue } from '/@/utils/types'; + import type { FunctionalComponent } from 'vue'; + import type { ParagraphProps } from 'ant-design-vue/es/typography/Paragraph'; + export default defineComponent({ components: { [Avatar.name]: Avatar, [List.name]: List, [List.Item.name]: List.Item, AListItemMeta: List.Item.Meta, - ATypographyParagraph: Typography.Paragraph, + ATypographyParagraph: Typography.Paragraph as FunctionalComponent< + ParagraphProps & { + style?: StyleValue; + } + >, [Tag.name]: Tag, }, props: { @@ -112,11 +122,15 @@ const isTitleClickable = computed(() => !!props.onTitleClick); const getPagination = computed(() => { const { list, pageSize } = props; - if (pageSize > 0 && list && list.length > pageSize) { + + // compatible line 104 + // if typeof pageSize is boolean, Number(true) && 5 = 5, Number(false) && 5 = 0 + const size = isNumber(pageSize) ? pageSize : Number(pageSize) && 5; + + if (size > 0 && list && list.length > size) { return { total: list.length, - pageSize, - //size: 'small', + pageSize: size, current: unref(current), onChange(page) { current.value = page; diff --git a/apps/admin/src/layouts/default/header/components/notify/index.vue b/apps/admin/src/layouts/default/header/components/notify/index.vue index da66aff..e6883bb 100644 --- a/apps/admin/src/layouts/default/header/components/notify/index.vue +++ b/apps/admin/src/layouts/default/header/components/notify/index.vue @@ -66,7 +66,7 @@ @prefix-cls: ~'@{namespace}-header-notify'; .@{prefix-cls} { - padding-top: 2px; + padding-bottom: 1px; &__overlay { max-width: 360px; @@ -77,6 +77,8 @@ } .ant-badge { + display: flex; + align-items: center; font-size: 18px; .ant-badge-multiple-words { diff --git a/apps/admin/src/layouts/default/header/components/user-dropdown/index.vue b/apps/admin/src/layouts/default/header/components/user-dropdown/index.vue index 8c46130..7bd9af5 100644 --- a/apps/admin/src/layouts/default/header/components/user-dropdown/index.vue +++ b/apps/admin/src/layouts/default/header/components/user-dropdown/index.vue @@ -3,7 +3,7 @@ - + {{ getUserInfo.realName }} @@ -18,6 +18,12 @@ v-if="getShowDoc" /> + + diff --git a/apps/admin/src/layouts/default/tabs/index.less b/apps/admin/src/layouts/default/tabs/index.less index e6cdeb3..dbe58ee 100644 --- a/apps/admin/src/layouts/default/tabs/index.less +++ b/apps/admin/src/layouts/default/tabs/index.less @@ -1,13 +1,5 @@ @prefix-cls: ~'@{namespace}-multiple-tabs'; -html[data-theme='dark'] { - .@{prefix-cls} { - .ant-tabs-tab { - border-bottom: 1px solid @border-color-base; - } - } -} - html[data-theme='light'] { .@{prefix-cls} { .ant-tabs-tab:not(.ant-tabs-tab-active) { @@ -19,9 +11,9 @@ html[data-theme='light'] { .@{prefix-cls} { z-index: 10; height: @multiple-height + 2; - line-height: @multiple-height + 2; - background-color: @component-background; border-bottom: 1px solid @border-color-base; + background-color: @component-background; + line-height: @multiple-height + 2; .ant-tabs-small { height: @multiple-height; @@ -29,11 +21,11 @@ html[data-theme='light'] { .ant-tabs.ant-tabs-card { .ant-tabs-nav { - padding-top: 2px; height: @multiple-height; margin: 0; - background-color: @component-background; + padding-top: 2px; border: 0; + background-color: @component-background; box-shadow: none; .ant-tabs-nav-container { @@ -44,10 +36,10 @@ html[data-theme='light'] { .ant-tabs-tab { height: calc(@multiple-height - 2px); padding-right: 12px; - line-height: calc(@multiple-height - 2px); - color: @text-color-base; - background-color: @component-background; transition: none; + background-color: @component-background; + color: @text-color-base; + line-height: calc(@multiple-height - 2px); &:hover { .ant-tabs-tab-remove { @@ -58,12 +50,12 @@ html[data-theme='light'] { .ant-tabs-tab-remove { width: 8px; height: 28px; - font-size: 12px; - color: inherit; - opacity: 0; - transition: none; - margin-left: 2px; margin-right: -4px; + margin-left: 2px; + transition: none; + opacity: 0; + color: inherit; + font-size: 12px; &:hover { svg { @@ -92,9 +84,9 @@ html[data-theme='light'] { .ant-tabs-tab-active { position: relative; padding-left: 18px; - background: @primary-color; - border: 0; transition: none; + border: 0; + background: @primary-color; span { color: @white !important; @@ -147,11 +139,11 @@ html[data-theme='light'] { display: inline-block; width: 36px; height: @multiple-height; - line-height: @multiple-height; + border-left: 1px solid @border-color-base; color: @text-color-secondary; + line-height: @multiple-height; text-align: center; cursor: pointer; - border-left: 1px solid @border-color-base; &:hover { color: @text-color-base; @@ -172,8 +164,8 @@ html[data-theme='light'] { display: inline-block; width: 100%; height: @multiple-height - 2; - padding-left: 0; margin-left: -10px; + padding-left: 0; font-size: 12px; cursor: pointer; user-select: none; diff --git a/apps/admin/src/layouts/default/tabs/index.vue b/apps/admin/src/layouts/default/tabs/index.vue index 3b487bb..a5195cd 100644 --- a/apps/admin/src/layouts/default/tabs/index.vue +++ b/apps/admin/src/layouts/default/tabs/index.vue @@ -8,7 +8,7 @@ :tabBarGutter="3" :activeKey="activeKeyRef" @change="handleChange" - @edit="handleEdit" + @edit="(e) => handleEdit(`${e}`)" > - diff --git a/apps/admin/src/layouts/default/trigger/SiderTrigger.vue b/apps/admin/src/layouts/default/trigger/SiderTrigger.vue index 0eb38b5..ab0d057 100644 --- a/apps/admin/src/layouts/default/trigger/SiderTrigger.vue +++ b/apps/admin/src/layouts/default/trigger/SiderTrigger.vue @@ -4,18 +4,9 @@ - diff --git a/apps/admin/src/layouts/default/trigger/index.vue b/apps/admin/src/layouts/default/trigger/index.vue index 61f43b3..5a070e1 100644 --- a/apps/admin/src/layouts/default/trigger/index.vue +++ b/apps/admin/src/layouts/default/trigger/index.vue @@ -2,21 +2,14 @@ - + diff --git a/apps/admin/src/locales/lang/en.ts b/apps/admin/src/locales/lang/en.ts index f2bf247..a25bf56 100644 --- a/apps/admin/src/locales/lang/en.ts +++ b/apps/admin/src/locales/lang/en.ts @@ -1,10 +1,10 @@ import { genMessage } from '../helper'; import antdLocale from 'ant-design-vue/es/locale/en_US'; -const modules = import.meta.globEager('./en/**/*.ts'); +const modules = import.meta.glob('./en/**/*.json', { eager: true }); export default { message: { - ...genMessage(modules, 'en'), + ...genMessage(modules as Recordable, 'en'), antdLocale, }, dateLocale: null, diff --git a/apps/admin/src/locales/lang/en/common.json b/apps/admin/src/locales/lang/en/common.json new file mode 100644 index 0000000..8c5de53 --- /dev/null +++ b/apps/admin/src/locales/lang/en/common.json @@ -0,0 +1,17 @@ +{ + "okText": "OK", + "closeText": "Close", + "cancelText": "Cancel", + "loadingText": "Loading...", + "saveText": "Save", + "delText": "Delete", + "resetText": "Reset", + "searchText": "Search", + "queryText": "Search", + "inputText": "Please enter ", + "chooseText": "Please choose ", + "redo": "Refresh", + "back": "Back", + "light": "Light", + "dark": "Dark" +} \ No newline at end of file diff --git a/apps/admin/src/locales/lang/en/common.ts b/apps/admin/src/locales/lang/en/common.ts deleted file mode 100644 index f7cdce0..0000000 --- a/apps/admin/src/locales/lang/en/common.ts +++ /dev/null @@ -1,20 +0,0 @@ -export default { - okText: 'OK', - closeText: 'Close', - cancelText: 'Cancel', - loadingText: 'Loading...', - saveText: 'Save', - delText: 'Delete', - resetText: 'Reset', - searchText: 'Search', - queryText: 'Search', - - inputText: 'Please enter', - chooseText: 'Please choose', - - redo: 'Refresh', - back: 'Back', - - light: 'Light', - dark: 'Dark', -}; diff --git a/apps/admin/src/locales/lang/en/component.json b/apps/admin/src/locales/lang/en/component.json new file mode 100644 index 0000000..9d4951c --- /dev/null +++ b/apps/admin/src/locales/lang/en/component.json @@ -0,0 +1,125 @@ +{ + "app": { + "searchNotData": "No search results yet", + "toSearch": "to search", + "toNavigate": "to navigate" + }, + "countdown": { + "normalText": "Get SMS code", + "sendText": "Reacquire in {0}s" + }, + "cropper": { + "selectImage": "Select Image", + "uploadSuccess": "Uploaded success!", + "imageTooBig": "Image too big", + "modalTitle": "Avatar upload", + "okText": "Confirm and upload", + "btn_reset": "Reset", + "btn_rotate_left": "Counterclockwise rotation", + "btn_rotate_right": "Clockwise rotation", + "btn_scale_x": "Flip horizontal", + "btn_scale_y": "Flip vertical", + "btn_zoom_in": "Zoom in", + "btn_zoom_out": "Zoom out", + "preview": "Preivew" + }, + "drawer": { + "loadingText": "Loading...", + "cancelText": "Close", + "okText": "Confirm" + }, + "excel": { + "exportModalTitle": "Export data", + "fileType": "File type", + "fileName": "File name" + }, + "form": { + "putAway": "Put away", + "unfold": "Unfold", + "maxTip": "The number of characters should be less than {0}", + "apiSelectNotFound": "Wait for data loading to complete..." + }, + "icon": { + "placeholder": "Click the select icon", + "search": "Search icon", + "copy": "Copy icon successfully!" + }, + "menu": { + "search": "Menu search" + }, + "modal": { + "cancelText": "Close", + "okText": "Confirm", + "close": "Close", + "maximize": "Maximize", + "restore": "Restore" + }, + "table": { + "settingDens": "Density", + "settingDensDefault": "Default", + "settingDensMiddle": "Middle", + "settingDensSmall": "Compact", + "settingColumn": "Column settings", + "settingColumnShow": "Column display", + "settingIndexColumnShow": "Index Column", + "settingSelectColumnShow": "Selection Column", + "settingFixedLeft": "Fixed Left", + "settingFixedRight": "Fixed Right", + "settingFullScreen": "Full Screen", + "index": "Index", + "total": "total of {total}" + }, + "time": { + "before": " ago", + "after": " after", + "just": "just now", + "seconds": " seconds", + "minutes": " minutes", + "hours": " hours", + "days": " days" + }, + "tree": { + "selectAll": "Select All", + "unSelectAll": "Cancel Select", + "expandAll": "Expand All", + "unExpandAll": "Collapse all", + "checkStrictly": "Hierarchical association", + "checkUnStrictly": "Hierarchical independence" + }, + "upload": { + "save": "Save", + "upload": "Upload", + "imgUpload": "ImageUpload", + "uploaded": "Uploaded", + "operating": "Operating", + "del": "Delete", + "download": "download", + "saveWarn": "Please wait for the file to upload and save!", + "saveError": "There is no file successfully uploaded and cannot be saved!", + "preview": "Preview", + "choose": "Select the file", + "accept": "Support {0} format", + "acceptUpload": "Only upload files in {0} format", + "maxSize": "A single file does not exceed {0}MB ", + "maxSizeMultiple": "Only upload files up to {0}MB!", + "maxNumber": "Only upload up to {0} files", + "legend": "Legend", + "fileName": "File name", + "fileSize": "File size", + "fileStatue": "File status", + "pending": "Pendig", + "startUpload": "Start upload", + "uploadSuccess": "Upload successfully", + "uploadError": "Upload failed", + "uploading": "Uploading", + "uploadWait": "Please wait for the file upload to finish", + "reUploadFailed": "Re-upload failed files" + }, + "verify": { + "error": "verification failed!", + "time": "The verification is successful and it takes {time} seconds!", + "redoTip": "Click the picture to refresh", + "dragText": "Hold down the slider and drag", + "successText": "Verified" + } +} \ No newline at end of file diff --git a/apps/admin/src/locales/lang/en/component.ts b/apps/admin/src/locales/lang/en/component.ts deleted file mode 100644 index b93dbd5..0000000 --- a/apps/admin/src/locales/lang/en/component.ts +++ /dev/null @@ -1,129 +0,0 @@ -export default { - app: { - searchNotData: 'No search results yet', - toSearch: 'to search', - toNavigate: 'to navigate', - }, - countdown: { - normalText: 'Get SMS code', - sendText: 'Reacquire in {0}s', - }, - cropper: { - selectImage: 'Select Image', - uploadSuccess: 'Uploaded success!', - modalTitle: 'Avatar upload', - okText: 'Confirm and upload', - btn_reset: 'Reset', - btn_rotate_left: 'Counterclockwise rotation', - btn_rotate_right: 'Clockwise rotation', - btn_scale_x: 'Flip horizontal', - btn_scale_y: 'Flip vertical', - btn_zoom_in: 'Zoom in', - btn_zoom_out: 'Zoom out', - preview: 'Preivew', - }, - drawer: { - loadingText: 'Loading...', - cancelText: 'Close', - okText: 'Confirm', - }, - excel: { - exportModalTitle: 'Export data', - fileType: 'File type', - fileName: 'File name', - }, - form: { - putAway: 'Put away', - unfold: 'Unfold', - maxTip: 'The number of characters should be less than {0}', - apiSelectNotFound: 'Wait for data loading to complete...', - }, - icon: { - placeholder: 'Click the select icon', - search: 'Search icon', - copy: 'Copy icon successfully!', - }, - menu: { - search: 'Menu search', - }, - modal: { - cancelText: 'Close', - okText: 'Confirm', - close: 'Close', - maximize: 'Maximize', - restore: 'Restore', - }, - table: { - settingDens: 'Density', - settingDensDefault: 'Default', - settingDensMiddle: 'Middle', - settingDensSmall: 'Compact', - settingColumn: 'Column settings', - settingColumnShow: 'Column display', - settingIndexColumnShow: 'Index Column', - settingSelectColumnShow: 'Selection Column', - settingFixedLeft: 'Fixed Left', - settingFixedRight: 'Fixed Right', - settingFullScreen: 'Full Screen', - index: 'Index', - total: 'total of {total}', - }, - time: { - before: ' ago', - after: ' after', - just: 'just now', - seconds: ' seconds', - minutes: ' minutes', - hours: ' hours', - days: ' days', - }, - tree: { - selectAll: 'Select All', - unSelectAll: 'Cancel Select', - expandAll: 'Expand All', - unExpandAll: 'Collapse all', - - checkStrictly: 'Hierarchical association', - checkUnStrictly: 'Hierarchical independence', - }, - upload: { - save: 'Save', - upload: 'Upload', - imgUpload: 'ImageUpload', - uploaded: 'Uploaded', - - operating: 'Operating', - del: 'Delete', - download: 'download', - saveWarn: 'Please wait for the file to upload and save!', - saveError: 'There is no file successfully uploaded and cannot be saved!', - - preview: 'Preview', - choose: 'Select the file', - - accept: 'Support {0} format', - acceptUpload: 'Only upload files in {0} format', - maxSize: 'A single file does not exceed {0}MB ', - maxSizeMultiple: 'Only upload files up to {0}MB!', - maxNumber: 'Only upload up to {0} files', - - legend: 'Legend', - fileName: 'File name', - fileSize: 'File size', - fileStatue: 'File status', - - startUpload: 'Start upload', - uploadSuccess: 'Upload successfully', - uploadError: 'Upload failed', - uploading: 'Uploading', - uploadWait: 'Please wait for the file upload to finish', - reUploadFailed: 'Re-upload failed files', - }, - verify: { - error: 'verification failed!', - time: 'The verification is successful and it takes {time} seconds!', - redoTip: 'Click the picture to refresh', - dragText: 'Hold down the slider and drag', - successText: 'Verified', - }, -}; diff --git a/apps/admin/src/locales/lang/en/layout.json b/apps/admin/src/locales/lang/en/layout.json new file mode 100644 index 0000000..1a12285 --- /dev/null +++ b/apps/admin/src/locales/lang/en/layout.json @@ -0,0 +1,95 @@ +{ + "footer": { + "onlinePreview": "Preview", + "onlineDocument": "Document" + }, + "header": { + "dropdownChangeApi": "Change Api", + "dropdownItemDoc": "Document", + "dropdownItemLoginOut": "Log Out", + "tooltipErrorLog": "Error log", + "tooltipLock": "Lock screen", + "tooltipNotify": "Notification", + "tooltipEntryFull": "Full Screen", + "tooltipExitFull": "Exit Full Screen", + "lockScreenPassword": "Lock screen password", + "lockScreen": "Lock screen", + "lockScreenBtn": "Locking", + "home": "Home" + }, + "multipleTab": { + "reload": "Refresh current", + "close": "Close current", + "closeLeft": "Close Left", + "closeRight": "Close Right", + "closeOther": "Close Other", + "closeAll": "Close All" + }, + "setting": { + "contentModeFull": "Full", + "contentModeFixed": "Fixed width", + "topMenuAlignLeft": "Left", + "topMenuAlignRight": "Center", + "topMenuAlignCenter": "Right", + "menuTriggerNone": "Not Show", + "menuTriggerBottom": "Bottom", + "menuTriggerTop": "Top", + "menuTypeSidebar": "Left menu mode", + "menuTypeMixSidebar": "Left menu mixed mode", + "menuTypeMix": "Top Menu Mix mode", + "menuTypeTopMenu": "Top menu mode", + "on": "On", + "off": "Off", + "minute": "Minute", + "operatingTitle": "Successful!", + "operatingContent": "The copy is successful, please go to src/settings/projectSetting.ts to modify the configuration!", + "resetSuccess": "Successfully reset!", + "copyBtn": "Copy", + "clearBtn": "Clear cache and to the login page", + "drawerTitle": "Configuration", + "darkMode": "Dark mode", + "navMode": "Navigation mode", + "interfaceFunction": "Interface function", + "interfaceDisplay": "Interface display", + "animation": "Animation", + "splitMenu": "Split menu", + "closeMixSidebarOnChange": "Switch page to close menu", + "sysTheme": "System theme", + "headerTheme": "Header theme", + "sidebarTheme": "Menu theme", + "menuDrag": "Drag Sidebar", + "menuSearch": "Menu search", + "menuAccordion": "Sidebar accordion", + "menuCollapse": "Collapse menu", + "collapseMenuDisplayName": "Collapse menu display name", + "topMenuLayout": "Top menu layout", + "menuCollapseButton": "Menu collapse button", + "contentMode": "Content area width", + "expandedMenuWidth": "Expanded menu width", + "breadcrumb": "Breadcrumbs", + "breadcrumbIcon": "Breadcrumbs Icon", + "tabs": "Tabs", + "tabDetail": "Tab Detail", + "tabsQuickBtn": "Tabs quick button", + "tabsRedoBtn": "Tabs redo button", + "tabsFoldBtn": "Tabs flod button", + "sidebar": "Sidebar", + "header": "Header", + "footer": "Footer", + "fullContent": "Full content", + "grayMode": "Gray mode", + "colorWeak": "Color Weak Mode", + "progress": "Progress", + "switchLoading": "Switch Loading", + "switchAnimation": "Switch animation", + "animationType": "Animation type", + "autoScreenLock": "Auto screen lock", + "notAutoScreenLock": "Not auto lock", + "fixedHeader": "Fixed header", + "fixedSideBar": "Fixed Sidebar", + "mixSidebarTrigger": "Mixed menu Trigger", + "triggerHover": "Hover", + "triggerClick": "Click", + "mixSidebarFixed": "Fixed expanded menu" + } +} \ No newline at end of file diff --git a/apps/admin/src/locales/lang/en/layout.ts b/apps/admin/src/locales/lang/en/layout.ts deleted file mode 100644 index f3c627f..0000000 --- a/apps/admin/src/locales/lang/en/layout.ts +++ /dev/null @@ -1,115 +0,0 @@ -export default { - footer: { onlinePreview: 'Preview', onlineDocument: 'Document' }, - header: { - // user dropdown - dropdownItemDoc: 'Document', - dropdownItemLoginOut: 'Log Out', - - tooltipErrorLog: 'Error log', - tooltipLock: 'Lock screen', - tooltipNotify: 'Notification', - - tooltipEntryFull: 'Full Screen', - tooltipExitFull: 'Exit Full Screen', - - // lock - lockScreenPassword: 'Lock screen password', - lockScreen: 'Lock screen', - lockScreenBtn: 'Locking', - - home: 'Home', - }, - multipleTab: { - reload: 'Refresh current', - close: 'Close current', - closeLeft: 'Close Left', - closeRight: 'Close Right', - closeOther: 'Close Other', - closeAll: 'Close All', - }, - setting: { - // content mode - contentModeFull: 'Full', - contentModeFixed: 'Fixed width', - // topMenu align - topMenuAlignLeft: 'Left', - topMenuAlignRight: 'Center', - topMenuAlignCenter: 'Right', - // menu trigger - menuTriggerNone: 'Not Show', - menuTriggerBottom: 'Bottom', - menuTriggerTop: 'Top', - // menu type - menuTypeSidebar: 'Left menu mode', - menuTypeMixSidebar: 'Left menu mixed mode', - menuTypeMix: 'Top Menu Mix mode', - menuTypeTopMenu: 'Top menu mode', - - on: 'On', - off: 'Off', - minute: 'Minute', - - operatingTitle: 'Successful!', - operatingContent: - 'The copy is successful, please go to src/settings/projectSetting.ts to modify the configuration!', - resetSuccess: 'Successfully reset!', - - copyBtn: 'Copy', - clearBtn: 'Clear cache and to the login page', - - drawerTitle: 'Configuration', - - darkMode: 'Dark mode', - navMode: 'Navigation mode', - interfaceFunction: 'Interface function', - interfaceDisplay: 'Interface display', - animation: 'Animation', - splitMenu: 'Split menu', - closeMixSidebarOnChange: 'Switch page to close menu', - - sysTheme: 'System theme', - headerTheme: 'Header theme', - sidebarTheme: 'Menu theme', - - menuDrag: 'Drag Sidebar', - menuSearch: 'Menu search', - menuAccordion: 'Sidebar accordion', - menuCollapse: 'Collapse menu', - collapseMenuDisplayName: 'Collapse menu display name', - topMenuLayout: 'Top menu layout', - menuCollapseButton: 'Menu collapse button', - contentMode: 'Content area width', - expandedMenuWidth: 'Expanded menu width', - - breadcrumb: 'Breadcrumbs', - breadcrumbIcon: 'Breadcrumbs Icon', - tabs: 'Tabs', - tabDetail: 'Tab Detail', - tabsQuickBtn: 'Tabs quick button', - tabsRedoBtn: 'Tabs redo button', - tabsFoldBtn: 'Tabs flod button', - sidebar: 'Sidebar', - header: 'Header', - footer: 'Footer', - fullContent: 'Full content', - grayMode: 'Gray mode', - colorWeak: 'Color Weak Mode', - - progress: 'Progress', - switchLoading: 'Switch Loading', - switchAnimation: 'Switch animation', - animationType: 'Animation type', - - autoScreenLock: 'Auto screen lock', - notAutoScreenLock: 'Not auto lock', - - fixedHeader: 'Fixed header', - fixedSideBar: 'Fixed Sidebar', - - mixSidebarTrigger: 'Mixed menu Trigger', - triggerHover: 'Hover', - triggerClick: 'Click', - - mixSidebarFixed: 'Fixed expanded menu', - }, -}; diff --git a/apps/admin/src/locales/lang/en/routes/basic.json b/apps/admin/src/locales/lang/en/routes/basic.json new file mode 100644 index 0000000..e6e35df --- /dev/null +++ b/apps/admin/src/locales/lang/en/routes/basic.json @@ -0,0 +1,4 @@ +{ + "login": "Login", + "errorLogList": "Error Log" +} \ No newline at end of file diff --git a/apps/admin/src/locales/lang/en/routes/basic.ts b/apps/admin/src/locales/lang/en/routes/basic.ts deleted file mode 100644 index b6faa00..0000000 --- a/apps/admin/src/locales/lang/en/routes/basic.ts +++ /dev/null @@ -1,4 +0,0 @@ -export default { - login: 'Login', - errorLogList: 'Error Log', -}; diff --git a/apps/admin/src/locales/lang/en/routes/dashboard.json b/apps/admin/src/locales/lang/en/routes/dashboard.json new file mode 100644 index 0000000..ad3980c --- /dev/null +++ b/apps/admin/src/locales/lang/en/routes/dashboard.json @@ -0,0 +1,6 @@ +{ + "dashboard": "Dashboard", + "about": "About", + "workbench": "Workbench", + "analysis": "Analysis" +} diff --git a/apps/admin/src/locales/lang/en/routes/dashboard.ts b/apps/admin/src/locales/lang/en/routes/dashboard.ts deleted file mode 100644 index 6d047b5..0000000 --- a/apps/admin/src/locales/lang/en/routes/dashboard.ts +++ /dev/null @@ -1,6 +0,0 @@ -export default { - dashboard: 'Dashboard', - about: 'About', - workbench: 'Workbench', - analysis: 'Analysis', -}; diff --git a/apps/admin/src/locales/lang/en/routes/demo.json b/apps/admin/src/locales/lang/en/routes/demo.json new file mode 100644 index 0000000..0d0f93d --- /dev/null +++ b/apps/admin/src/locales/lang/en/routes/demo.json @@ -0,0 +1,178 @@ +{ + "charts": { + "baiduMap": "Baidu map", + "aMap": "A map", + "googleMap": "Google map", + "charts": "Chart", + "map": "Map", + "line": "Line", + "pie": "Pie" + }, + "comp": { + "comp": "Component", + "basic": "Basic", + "transition": "Animation", + "countTo": "Count To", + "scroll": "Scroll", + "scrollBasic": "Basic", + "scrollAction": "Scroll Function", + "virtualScroll": "Virtual Scroll", + "tree": "Tree", + "treeBasic": "Basic", + "editTree": "Searchable/toolbar", + "actionTree": "Function operation", + "modal": "Modal", + "drawer": "Drawer", + "desc": "Desc", + "verify": "Verify", + "verifyDrag": "Drag ", + "verifyRotate": "Picture Restore", + "qrcode": "QR code", + "strength": "Password strength", + "upload": "Upload", + "loading": "Loading", + "time": "Relative Time", + "cropperImage": "Cropper Image", + "cardList": "Card List" + }, + "editor": { + "editor": "Editor", + "jsonEditor": "Json editor", + "markdown": "Markdown editor", + "tinymce": "Rich text", + "tinymceBasic": "Basic", + "tinymceForm": "embedded form" + }, + "excel": { + "excel": "Excel", + "customExport": "Select export format", + "jsonExport": "JSON data export", + "arrayExport": "Array data export", + "importExcel": "Import" + }, + "feat": { + "feat": "Page Function", + "icon": "Icon", + "tabs": "Tabs", + "tabDetail": "Tab Detail", + "sessionTimeout": "Session Timeout", + "print": "Print", + "contextMenu": "Context Menu", + "download": "Download", + "clickOutSide": "ClickOutSide", + "imgPreview": "Picture Preview", + "copy": "Clipboard", + "ellipsis": "EllipsisText", + "msg": "Message prompt", + "watermark": "Watermark", + "ripple": "Ripple", + "fullScreen": "Full Screen", + "errorLog": "Error Log", + "tab": "Tab with parameters", + "tab1": "Tab with parameter 1", + "tab2": "Tab with parameter 2", + "menu": "Menu with parameters", + "menu1": "Menu with parameters 1", + "menu2": "Menu with parameters 2", + "ws": "Websocket test", + "breadcrumb": "Breadcrumbs", + "breadcrumbFlat": "Flat Mode", + "breadcrumbFlatDetail": "Flat mode details", + "requestDemo": "Retry request demo", + "breadcrumbChildren": "Level mode", + "breadcrumbChildrenDetail": "Level mode detail" + }, + "flow": { + "name": "Graphics editor", + "flowChart": "FlowChart" + }, + "form": { + "form": "Form", + "basic": "Basic", + "useForm": "useForm", + "refForm": "RefForm", + "advancedForm": "Shrinkable", + "ruleForm": "Form validation", + "dynamicForm": "Dynamic", + "customerForm": "Custom", + "appendForm": "Append", + "tabsForm": "TabsForm" + }, + "iframe": { + "frame": "External", + "antv": "antVue doc (embedded)", + "doc": "Project doc (embedded)", + "docExternal": "Project doc (external)" + }, + "level": { + "level": "MultiMenu" + }, + "page": { + "page": "Page", + "form": "Form", + "formBasic": "Basic Form", + "formStep": "Step Form", + "formHigh": "Advanced Form", + "desc": "Details", + "descBasic": "Basic Details", + "descHigh": "Advanced Details", + "result": "Result", + "resultSuccess": "Success", + "resultFail": "Failed", + "account": "Personal", + "accountCenter": "Personal Center", + "accountSetting": "Personal Settings", + "exception": "Exception", + "netWorkError": "Network Error", + "notData": "No data", + "list": "List page", + "listCard": "Card list", + "basic": "Basic list", + "listBasic": "Basic list", + "listSearch": "Search list" + }, + "permission": { + "permission": "Permission", + "front": "front-end", + "frontPage": "Page", + "frontBtn": "Button", + "frontTestA": "Test page A", + "frontTestB": "Test page B", + "back": "background", + "backPage": "Page", + "backBtn": "Button" + }, + "setup": { + "page": "Intro page" + }, + "system": { + "moduleName": "System management", + "account": "Account management", + "account_detail": "Account detail", + "password": "Change password", + "dept": "Department management", + "menu": "Menu management", + "role": "Role management" + }, + "table": { + "table": "Table", + "basic": "Basic", + "treeTable": "Tree", + "fetchTable": "Remote loading", + "fixedColumn": "Fixed column", + "customerCell": "Custom column", + "formTable": "Open search", + "useTable": "UseTable", + "refTable": "RefTable", + "multipleHeader": "MultiLevel header", + "mergeHeader": "Merge cells", + "expandTable": "Expandable table", + "fixedHeight": "Fixed height", + "footerTable": "Footer", + "editCellTable": "Editable cell", + "editRowTable": "Editable row", + "authColumn": "Auth column", + "resizeParentHeightTable": "resizeParentHeightTable", + "vxeTable": "VxeTable" + } +} \ No newline at end of file diff --git a/apps/admin/src/locales/lang/en/routes/demo.ts b/apps/admin/src/locales/lang/en/routes/demo.ts deleted file mode 100644 index 1cc82d0..0000000 --- a/apps/admin/src/locales/lang/en/routes/demo.ts +++ /dev/null @@ -1,199 +0,0 @@ -export default { - charts: { - baiduMap: 'Baidu map', - aMap: 'A map', - googleMap: 'Google map', - charts: 'Chart', - map: 'Map', - line: 'Line', - pie: 'Pie', - }, - comp: { - comp: 'Component', - basic: 'Basic', - transition: 'Animation', - countTo: 'Count To', - - scroll: 'Scroll', - scrollBasic: 'Basic', - scrollAction: 'Scroll Function', - virtualScroll: 'Virtual Scroll', - - tree: 'Tree', - - treeBasic: 'Basic', - editTree: 'Searchable/toolbar', - actionTree: 'Function operation', - - modal: 'Modal', - drawer: 'Drawer', - desc: 'Desc', - - verify: 'Verify', - verifyDrag: 'Drag ', - verifyRotate: 'Picture Restore', - - qrcode: 'QR code', - strength: 'Password strength', - upload: 'Upload', - - loading: 'Loading', - - time: 'Relative Time', - cropperImage: 'Cropper Image', - cardList: 'Card List', - }, - editor: { - editor: 'Editor', - jsonEditor: 'Json editor', - markdown: 'Markdown editor', - - tinymce: 'Rich text', - tinymceBasic: 'Basic', - tinymceForm: 'embedded form', - }, - excel: { - excel: 'Excel', - customExport: 'Select export format', - jsonExport: 'JSON data export', - arrayExport: 'Array data export', - importExcel: 'Import', - }, - feat: { - feat: 'Page Function', - icon: 'Icon', - tabs: 'Tabs', - tabDetail: 'Tab Detail', - sessionTimeout: 'Session Timeout', - print: 'Print', - contextMenu: 'Context Menu', - download: 'Download', - clickOutSide: 'ClickOutSide', - imgPreview: 'Picture Preview', - copy: 'Clipboard', - msg: 'Message prompt', - watermark: 'Watermark', - ripple: 'Ripple', - fullScreen: 'Full Screen', - errorLog: 'Error Log', - tab: 'Tab with parameters', - tab1: 'Tab with parameter 1', - tab2: 'Tab with parameter 2', - menu: 'Menu with parameters', - menu1: 'Menu with parameters 1', - menu2: 'Menu with parameters 2', - - ws: 'Websocket test', - - breadcrumb: 'Breadcrumbs', - breadcrumbFlat: 'Flat Mode', - breadcrumbFlatDetail: 'Flat mode details', - requestDemo: 'Retry request demo', - - breadcrumbChildren: 'Level mode', - breadcrumbChildrenDetail: 'Level mode detail', - }, - flow: { - name: 'Graphics editor', - flowChart: 'FlowChart', - }, - form: { - form: 'Form', - basic: 'Basic', - useForm: 'useForm', - refForm: 'RefForm', - advancedForm: 'Shrinkable', - ruleForm: 'Form validation', - dynamicForm: 'Dynamic', - customerForm: 'Custom', - appendForm: 'Append', - tabsForm: 'TabsForm', - }, - iframe: { - frame: 'External', - antv: 'antVue doc (embedded)', - doc: 'Project doc (embedded)', - docExternal: 'Project doc (external)', - }, - level: { level: 'MultiMenu' }, - page: { - page: 'Page', - - form: 'Form', - formBasic: 'Basic Form', - formStep: 'Step Form', - formHigh: 'Advanced Form', - - desc: 'Details', - descBasic: 'Basic Details', - descHigh: 'Advanced Details', - - result: 'Result', - resultSuccess: 'Success', - resultFail: 'Failed', - - account: 'Personal', - accountCenter: 'Personal Center', - accountSetting: 'Personal Settings', - - exception: 'Exception', - netWorkError: 'Network Error', - notData: 'No data', - - list: 'List page', - listCard: 'Card list', - basic: 'Basic list', - listBasic: 'Basic list', - listSearch: 'Search list', - }, - permission: { - permission: 'Permission', - - front: 'front-end', - frontPage: 'Page', - frontBtn: 'Button', - frontTestA: 'Test page A', - frontTestB: 'Test page B', - - back: 'background', - backPage: 'Page', - backBtn: 'Button', - }, - setup: { - page: 'Intro page', - }, - system: { - moduleName: 'System management', - - account: 'Account management', - account_detail: 'Account detail', - password: 'Change password', - - dept: 'Department management', - - menu: 'Menu management', - role: 'Role management', - }, - table: { - table: 'Table', - - basic: 'Basic', - treeTable: 'Tree', - fetchTable: 'Remote loading', - fixedColumn: 'Fixed column', - customerCell: 'Custom column', - formTable: 'Open search', - useTable: 'UseTable', - refTable: 'RefTable', - multipleHeader: 'MultiLevel header', - mergeHeader: 'Merge cells', - expandTable: 'Expandable table', - fixedHeight: 'Fixed height', - footerTable: 'Footer', - editCellTable: 'Editable cell', - editRowTable: 'Editable row', - authColumn: 'Auth column', - resizeParentHeightTable: 'resizeParentHeightTable', - vxeTable: 'VxeTable', - }, -}; diff --git a/apps/admin/src/locales/lang/en/sys.json b/apps/admin/src/locales/lang/en/sys.json new file mode 100644 index 0000000..1f67b11 --- /dev/null +++ b/apps/admin/src/locales/lang/en/sys.json @@ -0,0 +1,92 @@ +{ + "api": { + "operationSuccess": "Operation Success", + "operationFailed": "Operation failed", + "errorTip": "Error Tip", + "successTip": "Success Tip", + "errorMessage": "The operation failed, the system is abnormal!", + "timeoutMessage": "Login timed out, please log in again!", + "apiTimeoutMessage": "The interface request timed out, please refresh the page and try again!", + "apiRequestFailed": "The interface request failed, please try again later!", + "networkException": "network anomaly", + "networkExceptionMsg": "Please check if your network connection is normal! The network is abnormal", + "errMsg401": "The user does not have permission (token, user name, password error)!", + "errMsg403": "The user is authorized, but access is forbidden!", + "errMsg404": "Network request error, the resource was not found!", + "errMsg405": "Network request error, request method not allowed!", + "errMsg408": "Network request timed out!", + "errMsg500": "Server error, please contact the administrator!", + "errMsg501": "The network is not implemented!", + "errMsg502": "Network Error!", + "errMsg503": "The service is unavailable, the server is temporarily overloaded or maintained!", + "errMsg504": "Network timeout!", + "errMsg505": "The http version does not support the request!" + }, + "app": { + "logoutTip": "Reminder", + "logoutMessage": "Confirm to exit the system?", + "menuLoading": "Menu loading..." + }, + "errorLog": { + "tableTitle": "Error log list", + "tableColumnType": "Type", + "tableColumnDate": "Time", + "tableColumnFile": "File", + "tableColumnMsg": "Error message", + "tableColumnStackMsg": "Stack info", + "tableActionDesc": "Details", + "modalTitle": "Error details", + "fireVueError": "Fire vue error", + "fireResourceError": "Fire resource error", + "fireAjaxError": "Fire ajax error", + "enableMessage": "Only effective when useErrorHandle=true in `/src/settings/projectSetting.ts`." + }, + "exception": { + "backLogin": "Back Login", + "backHome": "Back Home", + "subTitle403": "Sorry, you don't have access to this page.", + "subTitle404": "Sorry, the page you visited does not exist.", + "subTitle500": "Sorry, the server is reporting an error.", + "noDataTitle": "No data on the current page.", + "networkErrorTitle": "Network Error", + "networkErrorSubTitle": "Sorry,Your network connection has been disconnected, please check your network!" + }, + "lock": { + "unlock": "Click to unlock", + "alert": "Lock screen password error", + "backToLogin": "Back to login", + "entry": "Enter the system", + "placeholder": "Please enter the lock screen password or user password" + }, + "login": { + "backSignIn": "Back sign in", + "mobileSignInFormTitle": "Mobile sign in", + "qrSignInFormTitle": "Qr code sign in", + "signInFormTitle": "Sign in", + "signUpFormTitle": "Sign up", + "forgetFormTitle": "Reset password", + "signInTitle": "Backstage management system", + "signInDesc": "Enter your personal details and get started!", + "policy": "I agree to the xxx Privacy Policy", + "scanSign": "scanning the code to complete the login", + "loginButton": "Sign in", + "registerButton": "Sign up", + "rememberMe": "Remember me", + "forgetPassword": "Forget Password?", + "otherSignIn": "Sign in with", + "loginSuccessTitle": "Login successful", + "loginSuccessDesc": "Welcome back", + "accountPlaceholder": "Please input username", + "passwordPlaceholder": "Please input password", + "smsPlaceholder": "Please input sms code", + "mobilePlaceholder": "Please input mobile", + "policyPlaceholder": "Register after checking", + "diffPwd": "The two passwords are inconsistent", + "userName": "Username", + "password": "Password", + "confirmPassword": "Confirm Password", + "email": "Email", + "smsCode": "SMS code", + "mobile": "Mobile" + } +} \ No newline at end of file diff --git a/apps/admin/src/locales/lang/en/sys.ts b/apps/admin/src/locales/lang/en/sys.ts deleted file mode 100644 index c88d25d..0000000 --- a/apps/admin/src/locales/lang/en/sys.ts +++ /dev/null @@ -1,106 +0,0 @@ -export default { - api: { - operationSuccess: 'Operation Success', - operationFailed: 'Operation failed', - errorTip: 'Error Tip', - successTip: 'Success Tip', - errorMessage: 'The operation failed, the system is abnormal!', - timeoutMessage: 'Login timed out, please log in again!', - apiTimeoutMessage: 'The interface request timed out, please refresh the page and try again!', - apiRequestFailed: 'The interface request failed, please try again later!', - networkException: 'network anomaly', - networkExceptionMsg: - 'Please check if your network connection is normal! The network is abnormal', - - errMsg401: 'The user does not have permission (token, user name, password error)!', - errMsg403: 'The user is authorized, but access is forbidden!', - errMsg404: 'Network request error, the resource was not found!', - errMsg405: 'Network request error, request method not allowed!', - errMsg408: 'Network request timed out!', - errMsg500: 'Server error, please contact the administrator!', - errMsg501: 'The network is not implemented!', - errMsg502: 'Network Error!', - errMsg503: 'The service is unavailable, the server is temporarily overloaded or maintained!', - errMsg504: 'Network timeout!', - errMsg505: 'The http version does not support the request!', - }, - app: { - logoutTip: 'Reminder', - logoutMessage: 'Confirm to exit the system?', - menuLoading: 'Menu loading...', - }, - errorLog: { - tableTitle: 'Error log list', - tableColumnType: 'Type', - tableColumnDate: 'Time', - tableColumnFile: 'File', - tableColumnMsg: 'Error message', - tableColumnStackMsg: 'Stack info', - - tableActionDesc: 'Details', - - modalTitle: 'Error details', - - fireVueError: 'Fire vue error', - fireResourceError: 'Fire resource error', - fireAjaxError: 'Fire ajax error', - - enableMessage: 'Only effective when useErrorHandle=true in `/src/settings/projectSetting.ts`.', - }, - exception: { - backLogin: 'Back Login', - backHome: 'Back Home', - subTitle403: "Sorry, you don't have access to this page.", - subTitle404: 'Sorry, the page you visited does not exist.', - subTitle500: 'Sorry, the server is reporting an error.', - noDataTitle: 'No data on the current page.', - networkErrorTitle: 'Network Error', - networkErrorSubTitle: - 'Sorry,Your network connection has been disconnected, please check your network!', - }, - lock: { - unlock: 'Click to unlock', - alert: 'Lock screen password error', - backToLogin: 'Back to login', - entry: 'Enter the system', - placeholder: 'Please enter the lock screen password or user password', - }, - login: { - backSignIn: 'Back sign in', - mobileSignInFormTitle: 'Mobile sign in', - qrSignInFormTitle: 'Qr code sign in', - signInFormTitle: 'Sign in', - signUpFormTitle: 'Sign up', - forgetFormTitle: 'Reset password', - - signInTitle: 'Backstage management system', - signInDesc: 'Enter your personal details and get started!', - policy: 'I agree to the xxx Privacy Policy', - scanSign: `scanning the code to complete the login`, - - loginButton: 'Sign in', - registerButton: 'Sign up', - rememberMe: 'Remember me', - forgetPassword: 'Forget Password?', - otherSignIn: 'Sign in with', - - // notify - loginSuccessTitle: 'Login successful', - loginSuccessDesc: 'Welcome back', - - // placeholder - accountPlaceholder: 'Please input username', - passwordPlaceholder: 'Please input password', - smsPlaceholder: 'Please input sms code', - mobilePlaceholder: 'Please input mobile', - policyPlaceholder: 'Register after checking', - diffPwd: 'The two passwords are inconsistent', - - userName: 'Username', - password: 'Password', - confirmPassword: 'Confirm Password', - email: 'Email', - smsCode: 'SMS code', - mobile: 'Mobile', - }, -}; diff --git a/apps/admin/src/locales/lang/zh-CN/antdLocale/DatePicker.json b/apps/admin/src/locales/lang/zh-CN/antdLocale/DatePicker.json new file mode 100644 index 0000000..b088fb5 --- /dev/null +++ b/apps/admin/src/locales/lang/zh-CN/antdLocale/DatePicker.json @@ -0,0 +1,19 @@ +{ + "lang": { + "shortWeekDays": ["一", "二", "三", "四", "五", "六", "日"], + "shortMonths": [ + "1月", + "2月", + "3月", + "4月", + "5月", + "6月", + "7月", + "8月", + "9月", + "10月", + "11月", + "12月" + ] + } +} diff --git a/apps/admin/src/locales/lang/zh-CN/antdLocale/DatePicker.ts b/apps/admin/src/locales/lang/zh-CN/antdLocale/DatePicker.ts deleted file mode 100644 index 452dff0..0000000 --- a/apps/admin/src/locales/lang/zh-CN/antdLocale/DatePicker.ts +++ /dev/null @@ -1,19 +0,0 @@ -export default { - lang: { - shortWeekDays: ['一', '二', '三', '四', '五', '六', '日'], - shortMonths: [ - '1月', - '2月', - '3月', - '4月', - '5月', - '6月', - '7月', - '8月', - '9月', - '10月', - '11月', - '12月', - ], - }, -}; diff --git a/apps/admin/src/locales/lang/zh-CN/common.json b/apps/admin/src/locales/lang/zh-CN/common.json new file mode 100644 index 0000000..19647c8 --- /dev/null +++ b/apps/admin/src/locales/lang/zh-CN/common.json @@ -0,0 +1,20 @@ +{ + "okText": "确认", + "closeText": "关闭", + "cancelText": "取消", + "loadingText": "加载中...", + "saveText": "保存", + "delText": "删除", + "resetText": "重置", + "searchText": "搜索", + "queryText": "查询", + + "inputText": "请输入", + "chooseText": "请选择", + + "redo": "刷新", + "back": "返回", + + "light": "亮色主题", + "dark": "黑暗主题" +} diff --git a/apps/admin/src/locales/lang/zh-CN/common.ts b/apps/admin/src/locales/lang/zh-CN/common.ts deleted file mode 100644 index 478c625..0000000 --- a/apps/admin/src/locales/lang/zh-CN/common.ts +++ /dev/null @@ -1,20 +0,0 @@ -export default { - okText: '确认', - closeText: '关闭', - cancelText: '取消', - loadingText: '加载中...', - saveText: '保存', - delText: '删除', - resetText: '重置', - searchText: '搜索', - queryText: '查询', - - inputText: '请输入', - chooseText: '请选择', - - redo: '刷新', - back: '返回', - - light: '亮色主题', - dark: '黑暗主题', -}; diff --git a/apps/admin/src/locales/lang/zh-CN/component.json b/apps/admin/src/locales/lang/zh-CN/component.json new file mode 100644 index 0000000..5d8a658 --- /dev/null +++ b/apps/admin/src/locales/lang/zh-CN/component.json @@ -0,0 +1,125 @@ +{ + "app": { + "searchNotData": "暂无搜索结果", + "toSearch": "确认", + "toNavigate": "切换" + }, + "countdown": { + "normalText": "获取验证码", + "sendText": "{0}秒后重新获取" + }, + "cropper": { + "selectImage": "选择图片", + "uploadSuccess": "上传成功", + "imageTooBig": "图片超限", + "modalTitle": "头像上传", + "okText": "确认并上传", + "btn_reset": "重置", + "btn_rotate_left": "逆时针旋转", + "btn_rotate_right": "顺时针旋转", + "btn_scale_x": "水平翻转", + "btn_scale_y": "垂直翻转", + "btn_zoom_in": "放大", + "btn_zoom_out": "缩小", + "preview": "预览" + }, + "drawer": { + "loadingText": "加载中...", + "cancelText": "关闭", + "okText": "确认" + }, + "excel": { + "exportModalTitle": "导出数据", + "fileType": "文件类型", + "fileName": "文件名" + }, + "form": { + "putAway": "收起", + "unfold": "展开", + "maxTip": "字符数应小于{0}位", + "apiSelectNotFound": "请等待数据加载完成..." + }, + "icon": { + "placeholder": "点击选择图标", + "search": "搜索图标", + "copy": "复制图标成功!" + }, + "menu": { + "search": "菜单搜索" + }, + "modal": { + "cancelText": "关闭", + "okText": "确认", + "close": "关闭", + "maximize": "最大化", + "restore": "还原" + }, + "table": { + "settingDens": "密度", + "settingDensDefault": "默认", + "settingDensMiddle": "中等", + "settingDensSmall": "紧凑", + "settingColumn": "列设置", + "settingColumnShow": "列展示", + "settingIndexColumnShow": "序号列", + "settingSelectColumnShow": "勾选列", + "settingFixedLeft": "固定到左侧", + "settingFixedRight": "固定到右侧", + "settingFullScreen": "全屏", + "index": "序号", + "total": "共 {total} 条数据" + }, + "time": { + "before": "前", + "after": "后", + "just": "刚刚", + "seconds": "秒", + "minutes": "分钟", + "hours": "小时", + "days": "天" + }, + "tree": { + "selectAll": "选择全部", + "unSelectAll": "取消选择", + "expandAll": "展开全部", + "unExpandAll": "折叠全部", + "checkStrictly": "层级关联", + "checkUnStrictly": "层级独立" + }, + "upload": { + "save": "保存", + "upload": "上传", + "imgUpload": "图片上传", + "uploaded": "已上传", + "operating": "操作", + "del": "删除", + "download": "下载", + "saveWarn": "请等待文件上传后,保存!", + "saveError": "没有上传成功的文件,无法保存!", + "preview": "预览", + "choose": "选择文件", + "accept": "支持{0}格式", + "acceptUpload": "只能上传{0}格式文件", + "maxSize": "单个文件不超过{0}MB", + "maxSizeMultiple": "只能上传不超过{0}MB的文件!", + "maxNumber": "最多只能上传{0}个文件", + "legend": "略缩图", + "fileName": "文件名", + "fileSize": "文件大小", + "fileStatue": "状态", + "pending": "待上传", + "startUpload": "开始上传", + "uploadSuccess": "上传成功", + "uploadError": "上传失败", + "uploading": "上传中", + "uploadWait": "请等待文件上传结束后操作", + "reUploadFailed": "重新上传失败文件" + }, + "verify": { + "error": "验证失败!", + "time": "验证校验成功,耗时{time}秒!", + "redoTip": "点击图片可刷新", + "dragText": "请按住滑块拖动", + "successText": "验证通过" + } +} \ No newline at end of file diff --git a/apps/admin/src/locales/lang/zh-CN/component.ts b/apps/admin/src/locales/lang/zh-CN/component.ts deleted file mode 100644 index d9b54eb..0000000 --- a/apps/admin/src/locales/lang/zh-CN/component.ts +++ /dev/null @@ -1,134 +0,0 @@ -export default { - app: { - searchNotData: '暂无搜索结果', - toSearch: '确认', - toNavigate: '切换', - }, - countdown: { - normalText: '获取验证码', - sendText: '{0}秒后重新获取', - }, - cropper: { - selectImage: '选择图片', - uploadSuccess: '上传成功', - modalTitle: '头像上传', - okText: '确认并上传', - btn_reset: '重置', - btn_rotate_left: '逆时针旋转', - btn_rotate_right: '顺时针旋转', - btn_scale_x: '水平翻转', - btn_scale_y: '垂直翻转', - btn_zoom_in: '放大', - btn_zoom_out: '缩小', - preview: '预览', - }, - drawer: { - loadingText: '加载中...', - cancelText: '关闭', - okText: '确认', - }, - excel: { - exportModalTitle: '导出数据', - fileType: '文件类型', - fileName: '文件名', - }, - form: { - putAway: '收起', - unfold: '展开', - - maxTip: '字符数应小于{0}位', - - apiSelectNotFound: '请等待数据加载完成...', - }, - icon: { - placeholder: '点击选择图标', - search: '搜索图标', - copy: '复制图标成功!', - }, - menu: { - search: '菜单搜索', - }, - modal: { - cancelText: '关闭', - okText: '确认', - close: '关闭', - maximize: '最大化', - restore: '还原', - }, - table: { - settingDens: '密度', - settingDensDefault: '默认', - settingDensMiddle: '中等', - settingDensSmall: '紧凑', - settingColumn: '列设置', - settingColumnShow: '列展示', - settingIndexColumnShow: '序号列', - settingSelectColumnShow: '勾选列', - settingFixedLeft: '固定到左侧', - settingFixedRight: '固定到右侧', - settingFullScreen: '全屏', - - index: '序号', - - total: '共 {total} 条数据', - }, - time: { - before: '前', - after: '后', - just: '刚刚', - seconds: '秒', - minutes: '分钟', - hours: '小时', - days: '天', - }, - tree: { - selectAll: '选择全部', - unSelectAll: '取消选择', - expandAll: '展开全部', - unExpandAll: '折叠全部', - checkStrictly: '层级关联', - checkUnStrictly: '层级独立', - }, - upload: { - save: '保存', - upload: '上传', - imgUpload: '图片上传', - uploaded: '已上传', - - operating: '操作', - del: '删除', - download: '下载', - saveWarn: '请等待文件上传后,保存!', - saveError: '没有上传成功的文件,无法保存!', - - preview: '预览', - choose: '选择文件', - - accept: '支持{0}格式', - acceptUpload: '只能上传{0}格式文件', - maxSize: '单个文件不超过{0}MB', - maxSizeMultiple: '只能上传不超过{0}MB的文件!', - maxNumber: '最多只能上传{0}个文件', - - legend: '略缩图', - fileName: '文件名', - fileSize: '文件大小', - fileStatue: '状态', - - startUpload: '开始上传', - uploadSuccess: '上传成功', - uploadError: '上传失败', - uploading: '上传中', - uploadWait: '请等待文件上传结束后操作', - reUploadFailed: '重新上传失败文件', - }, - verify: { - error: '验证失败!', - time: '验证校验成功,耗时{time}秒!', - - redoTip: '点击图片可刷新', - - dragText: '请按住滑块拖动', - successText: '验证通过', - }, -}; diff --git a/apps/admin/src/locales/lang/zh-CN/layout.json b/apps/admin/src/locales/lang/zh-CN/layout.json new file mode 100644 index 0000000..d6a894e --- /dev/null +++ b/apps/admin/src/locales/lang/zh-CN/layout.json @@ -0,0 +1,95 @@ +{ + "footer": { + "onlinePreview": "在线预览", + "onlineDocument": "在线文档" + }, + "header": { + "dropdownChangeApi": "切换API", + "dropdownItemDoc": "文档", + "dropdownItemLoginOut": "退出系统", + "tooltipErrorLog": "错误日志", + "tooltipLock": "锁定屏幕", + "tooltipNotify": "消息通知", + "tooltipEntryFull": "全屏", + "tooltipExitFull": "退出全屏", + "lockScreenPassword": "锁屏密码", + "lockScreen": "锁定屏幕", + "lockScreenBtn": "锁定", + "home": "首页" + }, + "multipleTab": { + "reload": "重新加载", + "close": "关闭标签页", + "closeLeft": "关闭左侧标签页", + "closeRight": "关闭右侧标签页", + "closeOther": "关闭其它标签页", + "closeAll": "关闭全部标签页" + }, + "setting": { + "contentModeFull": "流式", + "contentModeFixed": "定宽", + "topMenuAlignLeft": "居左", + "topMenuAlignRight": "居中", + "topMenuAlignCenter": "居右", + "menuTriggerNone": "不显示", + "menuTriggerBottom": "底部", + "menuTriggerTop": "顶部", + "menuTypeSidebar": "左侧菜单模式", + "menuTypeMixSidebar": "左侧菜单混合模式", + "menuTypeMix": "顶部菜单混合模式", + "menuTypeTopMenu": "顶部菜单模式", + "on": "开", + "off": "关", + "minute": "分钟", + "operatingTitle": "操作成功", + "operatingContent": "复制成功,请到 src/settings/projectSetting.ts 中修改配置!", + "resetSuccess": "重置成功!", + "copyBtn": "拷贝", + "clearBtn": "清空缓存并返回登录页", + "drawerTitle": "项目配置", + "darkMode": "主题", + "navMode": "导航栏模式", + "interfaceFunction": "界面功能", + "interfaceDisplay": "界面显示", + "animation": "动画", + "splitMenu": "分割菜单", + "closeMixSidebarOnChange": "切换页面关闭菜单", + "sysTheme": "系统主题", + "headerTheme": "顶栏主题", + "sidebarTheme": "菜单主题", + "menuDrag": "侧边菜单拖拽", + "menuSearch": "菜单搜索", + "menuAccordion": "侧边菜单手风琴模式", + "menuCollapse": "折叠菜单", + "collapseMenuDisplayName": "折叠菜单显示名称", + "topMenuLayout": "顶部菜单布局", + "menuCollapseButton": "菜单折叠按钮", + "contentMode": "内容区域宽度", + "expandedMenuWidth": "菜单展开宽度", + "breadcrumb": "面包屑", + "breadcrumbIcon": "面包屑图标", + "tabs": "标签页", + "tabDetail": "标签详情页", + "tabsQuickBtn": "标签页快捷按钮", + "tabsRedoBtn": "标签页刷新按钮", + "tabsFoldBtn": "标签页折叠按钮", + "sidebar": "左侧菜单", + "header": "顶栏", + "footer": "页脚", + "fullContent": "全屏内容", + "grayMode": "灰色模式", + "colorWeak": "色弱模式", + "progress": "顶部进度条", + "switchLoading": "切换loading", + "switchAnimation": "切换动画", + "animationType": "动画类型", + "autoScreenLock": "自动锁屏", + "notAutoScreenLock": "不自动锁屏", + "fixedHeader": "固定header", + "fixedSideBar": "固定Sidebar", + "mixSidebarTrigger": "混合菜单触发方式", + "triggerHover": "悬停", + "triggerClick": "点击", + "mixSidebarFixed": "固定展开菜单" + } +} \ No newline at end of file diff --git a/apps/admin/src/locales/lang/zh-CN/layout.ts b/apps/admin/src/locales/lang/zh-CN/layout.ts deleted file mode 100644 index ed1f853..0000000 --- a/apps/admin/src/locales/lang/zh-CN/layout.ts +++ /dev/null @@ -1,115 +0,0 @@ -export default { - footer: { onlinePreview: '在线预览', onlineDocument: '在线文档' }, - header: { - // user dropdown - dropdownItemDoc: '文档', - dropdownItemLoginOut: '退出系统', - - // tooltip - tooltipErrorLog: '错误日志', - tooltipLock: '锁定屏幕', - tooltipNotify: '消息通知', - - tooltipEntryFull: '全屏', - tooltipExitFull: '退出全屏', - - // lock - lockScreenPassword: '锁屏密码', - lockScreen: '锁定屏幕', - lockScreenBtn: '锁定', - - home: '首页', - }, - multipleTab: { - reload: '重新加载', - close: '关闭标签页', - closeLeft: '关闭左侧标签页', - closeRight: '关闭右侧标签页', - closeOther: '关闭其它标签页', - closeAll: '关闭全部标签页', - }, - setting: { - // content mode - contentModeFull: '流式', - contentModeFixed: '定宽', - // topMenu align - topMenuAlignLeft: '居左', - topMenuAlignRight: '居中', - topMenuAlignCenter: '居右', - // menu trigger - menuTriggerNone: '不显示', - menuTriggerBottom: '底部', - menuTriggerTop: '顶部', - // menu type - menuTypeSidebar: '左侧菜单模式', - menuTypeMixSidebar: '左侧菜单混合模式', - menuTypeMix: '顶部菜单混合模式', - menuTypeTopMenu: '顶部菜单模式', - - on: '开', - off: '关', - minute: '分钟', - - operatingTitle: '操作成功', - operatingContent: '复制成功,请到 src/settings/projectSetting.ts 中修改配置!', - resetSuccess: '重置成功!', - - copyBtn: '拷贝', - clearBtn: '清空缓存并返回登录页', - - drawerTitle: '项目配置', - - darkMode: '主题', - navMode: '导航栏模式', - interfaceFunction: '界面功能', - interfaceDisplay: '界面显示', - animation: '动画', - splitMenu: '分割菜单', - closeMixSidebarOnChange: '切换页面关闭菜单', - - sysTheme: '系统主题', - headerTheme: '顶栏主题', - sidebarTheme: '菜单主题', - - menuDrag: '侧边菜单拖拽', - menuSearch: '菜单搜索', - menuAccordion: '侧边菜单手风琴模式', - menuCollapse: '折叠菜单', - collapseMenuDisplayName: '折叠菜单显示名称', - topMenuLayout: '顶部菜单布局', - menuCollapseButton: '菜单折叠按钮', - contentMode: '内容区域宽度', - expandedMenuWidth: '菜单展开宽度', - - breadcrumb: '面包屑', - breadcrumbIcon: '面包屑图标', - tabs: '标签页', - tabDetail: '标签详情页', - tabsQuickBtn: '标签页快捷按钮', - tabsRedoBtn: '标签页刷新按钮', - tabsFoldBtn: '标签页折叠按钮', - sidebar: '左侧菜单', - header: '顶栏', - footer: '页脚', - fullContent: '全屏内容', - grayMode: '灰色模式', - colorWeak: '色弱模式', - - progress: '顶部进度条', - switchLoading: '切换loading', - switchAnimation: '切换动画', - animationType: '动画类型', - - autoScreenLock: '自动锁屏', - notAutoScreenLock: '不自动锁屏', - - fixedHeader: '固定header', - fixedSideBar: '固定Sidebar', - - mixSidebarTrigger: '混合菜单触发方式', - triggerHover: '悬停', - triggerClick: '点击', - - mixSidebarFixed: '固定展开菜单', - }, -}; diff --git a/apps/admin/src/locales/lang/zh-CN/routes/basic.json b/apps/admin/src/locales/lang/zh-CN/routes/basic.json new file mode 100644 index 0000000..830ff12 --- /dev/null +++ b/apps/admin/src/locales/lang/zh-CN/routes/basic.json @@ -0,0 +1,4 @@ +{ + "login": "登录", + "errorLogList": "错误日志列表" +} diff --git a/apps/admin/src/locales/lang/zh-CN/routes/basic.ts b/apps/admin/src/locales/lang/zh-CN/routes/basic.ts deleted file mode 100644 index 3d03e8e..0000000 --- a/apps/admin/src/locales/lang/zh-CN/routes/basic.ts +++ /dev/null @@ -1,4 +0,0 @@ -export default { - login: '登录', - errorLogList: '错误日志列表', -}; diff --git a/apps/admin/src/locales/lang/zh-CN/routes/dashboard.json b/apps/admin/src/locales/lang/zh-CN/routes/dashboard.json new file mode 100644 index 0000000..f5fba47 --- /dev/null +++ b/apps/admin/src/locales/lang/zh-CN/routes/dashboard.json @@ -0,0 +1,6 @@ +{ + "dashboard": "Dashboard", + "about": "关于", + "workbench": "工作台", + "analysis": "分析页" +} diff --git a/apps/admin/src/locales/lang/zh-CN/routes/dashboard.ts b/apps/admin/src/locales/lang/zh-CN/routes/dashboard.ts deleted file mode 100644 index 04b1b19..0000000 --- a/apps/admin/src/locales/lang/zh-CN/routes/dashboard.ts +++ /dev/null @@ -1,6 +0,0 @@ -export default { - dashboard: 'Dashboard', - about: '关于', - workbench: '工作台', - analysis: '分析页', -}; diff --git a/apps/admin/src/locales/lang/zh-CN/routes/demo.json b/apps/admin/src/locales/lang/zh-CN/routes/demo.json new file mode 100644 index 0000000..c73630f --- /dev/null +++ b/apps/admin/src/locales/lang/zh-CN/routes/demo.json @@ -0,0 +1,177 @@ +{ + "charts": { + "baiduMap": "百度地图", + "aMap": "高德地图", + "googleMap": "谷歌地图", + "charts": "图表", + "map": "地图", + "line": "折线图", + "pie": "饼图" + }, + "comp": { + "comp": "组件", + "basic": "基础组件", + "transition": "动画组件", + "countTo": "数字动画", + "scroll": "滚动组件", + "scrollBasic": "基础滚动", + "scrollAction": "滚动函数", + "virtualScroll": "虚拟滚动", + "tree": "Tree", + "treeBasic": "基础树", + "editTree": "可搜索/工具栏", + "actionTree": "函数操作示例", + "modal": "弹窗扩展", + "drawer": "抽屉扩展", + "desc": "详情组件", + "verify": "验证组件", + "verifyDrag": "拖拽校验", + "verifyRotate": "图片还原", + "qrcode": "二维码组件", + "strength": "密码强度组件", + "upload": "上传组件", + "loading": "Loading", + "time": "相对时间", + "cropperImage": "图片裁剪", + "cardList": "卡片列表" + }, + "editor": { + "editor": "编辑器", + "jsonEditor": "Json编辑器", + "markdown": "markdown编辑器", + "tinymce": "富文本", + "tinymceBasic": "基础使用", + "tinymceForm": "嵌入form" + }, + "excel": { + "excel": "Excel", + "customExport": "选择导出格式", + "jsonExport": "JSON数据导出", + "arrayExport": "Array数据导出", + "importExcel": "导入" + }, + "feat": { + "feat": "功能", + "icon": "图标", + "sessionTimeout": "登录过期", + "tabs": "标签页操作", + "tabDetail": "标签详情页", + "print": "打印", + "contextMenu": "右键菜单", + "download": "文件下载", + "clickOutSide": "ClickOutSide组件", + "imgPreview": "图片预览", + "copy": "剪切板", + "ellipsis": "文本省略", + "msg": "消息提示", + "watermark": "水印", + "ripple": "水波纹", + "fullScreen": "全屏", + "errorLog": "错误日志", + "tab": "Tab带参", + "tab1": "Tab带参1", + "tab2": "Tab带参2", + "menu": "Menu带参", + "menu1": "Menu带参1", + "menu2": "Menu带参2", + "ws": "websocket测试", + "breadcrumb": "面包屑导航", + "breadcrumbFlat": "平级模式", + "requestDemo": "测试请求重试", + "breadcrumbFlatDetail": "平级详情", + "breadcrumbChildren": "层级模式", + "breadcrumbChildrenDetail": "层级详情" + }, + "flow": { + "name": "图形编辑器", + "flowChart": "流程图" + }, + "form": { + "form": "Form", + "basic": "基础表单", + "useForm": "useForm", + "refForm": "RefForm", + "advancedForm": "可收缩表单", + "ruleForm": "表单验证", + "dynamicForm": "动态表单", + "customerForm": "自定义组件", + "appendForm": "表单增删示例", + "tabsForm": "标签页+多级field" + }, + "iframe": { + "frame": "外部页面", + "antv": "antVue文档(内嵌)", + "doc": "项目文档(内嵌)", + "docExternal": "项目文档(外链)" + }, + "level": { + "level": "多级菜单" + }, + "page": { + "page": "页面", + "form": "表单页", + "formBasic": "基础表单", + "formStep": "分步表单", + "formHigh": "高级表单", + "desc": "详情页", + "descBasic": "基础详情页", + "descHigh": "高级详情页", + "result": "结果页", + "resultSuccess": "成功页", + "resultFail": "失败页", + "account": "个人页", + "accountCenter": "个人中心", + "accountSetting": "个人设置", + "exception": "异常页", + "netWorkError": "网络错误", + "notData": "无数据", + "list": "列表页", + "listCard": "卡片列表", + "listBasic": "标准列表", + "listSearch": "搜索列表" + }, + "permission": { + "permission": "权限管理", + "front": "基于前端权限", + "frontPage": "页面权限", + "frontBtn": "按钮权限", + "frontTestA": "权限测试页A", + "frontTestB": "权限测试页B", + "back": "基于后台权限", + "backPage": "页面权限", + "backBtn": "按钮权限" + }, + "setup": { + "page": "引导页" + }, + "system": { + "moduleName": "系统管理", + "account": "账号管理", + "account_detail": "账号详情", + "password": "修改密码", + "dept": "部门管理", + "menu": "菜单管理", + "role": "角色管理" + }, + "table": { + "table": "Table", + "basic": "基础表格", + "treeTable": "树形表格", + "fetchTable": "远程加载示例", + "fixedColumn": "固定列", + "customerCell": "自定义列", + "formTable": "开启搜索区域", + "useTable": "UseTable", + "refTable": "RefTable", + "multipleHeader": "多级表头", + "mergeHeader": "合并单元格", + "expandTable": "可展开表格", + "fixedHeight": "定高/头部自定义", + "footerTable": "表尾行合计", + "editCellTable": "可编辑单元格", + "editRowTable": "可编辑行", + "authColumn": "权限列", + "resizeParentHeightTable": "继承父元素高度", + "vxeTable": "VxeTable" + } +} \ No newline at end of file diff --git a/apps/admin/src/locales/lang/zh-CN/routes/demo.ts b/apps/admin/src/locales/lang/zh-CN/routes/demo.ts deleted file mode 100644 index 54f6482..0000000 --- a/apps/admin/src/locales/lang/zh-CN/routes/demo.ts +++ /dev/null @@ -1,190 +0,0 @@ -export default { - charts: { - baiduMap: '百度地图', - aMap: '高德地图', - googleMap: '谷歌地图', - charts: '图表', - map: '地图', - line: '折线图', - pie: '饼图', - }, - comp: { - comp: '组件', - basic: '基础组件', - transition: '动画组件', - countTo: '数字动画', - - scroll: '滚动组件', - scrollBasic: '基础滚动', - scrollAction: '滚动函数', - virtualScroll: '虚拟滚动', - - tree: 'Tree', - treeBasic: '基础树', - editTree: '可搜索/工具栏', - actionTree: '函数操作示例', - - modal: '弹窗扩展', - drawer: '抽屉扩展', - desc: '详情组件', - - verify: '验证组件', - verifyDrag: '拖拽校验', - verifyRotate: '图片还原', - - qrcode: '二维码组件', - strength: '密码强度组件', - upload: '上传组件', - - loading: 'Loading', - - time: '相对时间', - cropperImage: '图片裁剪', - cardList: '卡片列表', - }, - editor: { - editor: '编辑器', - jsonEditor: 'Json编辑器', - markdown: 'markdown编辑器', - - tinymce: '富文本', - tinymceBasic: '基础使用', - tinymceForm: '嵌入form', - }, - excel: { - excel: 'Excel', - customExport: '选择导出格式', - jsonExport: 'JSON数据导出', - arrayExport: 'Array数据导出', - importExcel: '导入', - }, - feat: { - feat: '功能', - icon: '图标', - sessionTimeout: '登录过期', - tabs: '标签页操作', - tabDetail: '标签详情页', - print: '打印', - contextMenu: '右键菜单', - download: '文件下载', - clickOutSide: 'ClickOutSide组件', - imgPreview: '图片预览', - copy: '剪切板', - msg: '消息提示', - watermark: '水印', - ripple: '水波纹', - fullScreen: '全屏', - errorLog: '错误日志', - tab: 'Tab带参', - tab1: 'Tab带参1', - tab2: 'Tab带参2', - menu: 'Menu带参', - menu1: 'Menu带参1', - menu2: 'Menu带参2', - ws: 'websocket测试', - breadcrumb: '面包屑导航', - breadcrumbFlat: '平级模式', - requestDemo: '测试请求重试', - breadcrumbFlatDetail: '平级详情', - breadcrumbChildren: '层级模式', - breadcrumbChildrenDetail: '层级详情', - }, - flow: { - name: '图形编辑器', - flowChart: '流程图', - }, - form: { - form: 'Form', - basic: '基础表单', - useForm: 'useForm', - refForm: 'RefForm', - advancedForm: '可收缩表单', - ruleForm: '表单验证', - dynamicForm: '动态表单', - customerForm: '自定义组件', - appendForm: '表单增删示例', - tabsForm: '标签页+多级field', - }, - iframe: { - frame: '外部页面', - antv: 'antVue文档(内嵌)', - doc: '项目文档(内嵌)', - docExternal: '项目文档(外链)', - }, - level: { level: '多级菜单' }, - page: { - page: '页面', - - form: '表单页', - formBasic: '基础表单', - formStep: '分步表单', - formHigh: '高级表单', - - desc: '详情页', - descBasic: '基础详情页', - descHigh: '高级详情页', - - result: '结果页', - resultSuccess: '成功页', - resultFail: '失败页', - - account: '个人页', - accountCenter: '个人中心', - accountSetting: '个人设置', - - exception: '异常页', - netWorkError: '网络错误', - notData: '无数据', - - list: '列表页', - listCard: '卡片列表', - listBasic: '标准列表', - listSearch: '搜索列表', - }, - permission: { - permission: '权限管理', - - front: '基于前端权限', - frontPage: '页面权限', - frontBtn: '按钮权限', - frontTestA: '权限测试页A', - frontTestB: '权限测试页B', - - back: '基于后台权限', - backPage: '页面权限', - backBtn: '按钮权限', - }, - setup: { - page: '引导页', - }, - system: { - moduleName: '系统管理', - account: '账号管理', - account_detail: '账号详情', - password: '修改密码', - dept: '部门管理', - menu: '菜单管理', - role: '角色管理', - }, - table: { - table: 'Table', - basic: '基础表格', - treeTable: '树形表格', - fetchTable: '远程加载示例', - fixedColumn: '固定列', - customerCell: '自定义列', - formTable: '开启搜索区域', - useTable: 'UseTable', - refTable: 'RefTable', - multipleHeader: '多级表头', - mergeHeader: '合并单元格', - expandTable: '可展开表格', - fixedHeight: '定高/头部自定义', - footerTable: '表尾行合计', - editCellTable: '可编辑单元格', - editRowTable: '可编辑行', - authColumn: '权限列', - resizeParentHeightTable: '继承父元素高度', - vxeTable: 'VxeTable', - }, -}; diff --git a/apps/admin/src/locales/lang/zh-CN/sys.json b/apps/admin/src/locales/lang/zh-CN/sys.json new file mode 100644 index 0000000..73517d7 --- /dev/null +++ b/apps/admin/src/locales/lang/zh-CN/sys.json @@ -0,0 +1,92 @@ +{ + "api": { + "operationSuccess": "操作成功", + "operationFailed": "操作失败", + "errorTip": "错误提示", + "successTip": "成功提示", + "errorMessage": "操作失败,系统异常!", + "timeoutMessage": "登录超时,请重新登录!", + "apiTimeoutMessage": "接口请求超时,请刷新页面重试!", + "apiRequestFailed": "请求出错,请稍候重试", + "networkException": "网络异常", + "networkExceptionMsg": "网络异常,请检查您的网络连接是否正常!", + "errMsg401": "用户没有权限(令牌、用户名、密码错误)!", + "errMsg403": "用户得到授权,但是访问是被禁止的。!", + "errMsg404": "网络请求错误,未找到该资源!", + "errMsg405": "网络请求错误,请求方法未允许!", + "errMsg408": "网络请求超时!", + "errMsg500": "服务器错误,请联系管理员!", + "errMsg501": "网络未实现!", + "errMsg502": "网络错误!", + "errMsg503": "服务不可用,服务器暂时过载或维护!", + "errMsg504": "网络超时!", + "errMsg505": "http版本不支持该请求!" + }, + "app": { + "logoutTip": "温馨提醒", + "logoutMessage": "是否确认退出系统?", + "menuLoading": "菜单加载中..." + }, + "errorLog": { + "tableTitle": "错误日志列表", + "tableColumnType": "类型", + "tableColumnDate": "时间", + "tableColumnFile": "文件", + "tableColumnMsg": "错误信息", + "tableColumnStackMsg": "stack信息", + "tableActionDesc": "详情", + "modalTitle": "错误详情", + "fireVueError": "点击触发vue错误", + "fireResourceError": "点击触发资源加载错误", + "fireAjaxError": "点击触发ajax错误", + "enableMessage": "只在`/src/settings/projectSetting.ts` 内的useErrorHandle=true时生效." + }, + "exception": { + "backLogin": "返回登录", + "backHome": "返回首页", + "subTitle403": "抱歉,您无权访问此页面。", + "subTitle404": "抱歉,您访问的页面不存在。", + "subTitle500": "抱歉,服务器报告错误。", + "noDataTitle": "当前页无数据", + "networkErrorTitle": "网络错误", + "networkErrorSubTitle": "抱歉,您的网络连接已断开,请检查您的网络!" + }, + "lock": { + "unlock": "点击解锁", + "alert": "锁屏密码错误", + "backToLogin": "返回登录", + "entry": "进入系统", + "placeholder": "请输入锁屏密码或者用户密码" + }, + "login": { + "backSignIn": "返回", + "signInFormTitle": "登录", + "mobileSignInFormTitle": "手机登录", + "qrSignInFormTitle": "二维码登录", + "signUpFormTitle": "注册", + "forgetFormTitle": "重置密码", + "signInTitle": "开箱即用的中后台管理系统", + "signInDesc": "输入您的个人详细信息开始使用!", + "policy": "我同意xxx隐私政策", + "scanSign": "扫码后点击\"确认\",即可完成登录", + "loginButton": "登录", + "registerButton": "注册", + "rememberMe": "记住我", + "forgetPassword": "忘记密码?", + "otherSignIn": "其他登录方式", + "loginSuccessTitle": "登录成功", + "loginSuccessDesc": "欢迎回来", + "accountPlaceholder": "请输入账号", + "passwordPlaceholder": "请输入密码", + "smsPlaceholder": "请输入验证码", + "mobilePlaceholder": "请输入手机号码", + "policyPlaceholder": "勾选后才能注册", + "diffPwd": "两次输入密码不一致", + "userName": "账号", + "password": "密码", + "confirmPassword": "确认密码", + "email": "邮箱", + "smsCode": "短信验证码", + "mobile": "手机号码" + } +} \ No newline at end of file diff --git a/apps/admin/src/locales/lang/zh-CN/sys.ts b/apps/admin/src/locales/lang/zh-CN/sys.ts deleted file mode 100644 index 44ef9f4..0000000 --- a/apps/admin/src/locales/lang/zh-CN/sys.ts +++ /dev/null @@ -1,100 +0,0 @@ -export default { - api: { - operationSuccess: '操作成功', - operationFailed: '操作失败', - errorTip: '错误提示', - successTip: '成功提示', - errorMessage: '操作失败,系统异常!', - timeoutMessage: '登录超时,请重新登录!', - apiTimeoutMessage: '接口请求超时,请刷新页面重试!', - apiRequestFailed: '请求出错,请稍候重试', - networkException: '网络异常', - networkExceptionMsg: '网络异常,请检查您的网络连接是否正常!', - - errMsg401: '用户没有权限(令牌、用户名、密码错误)!', - errMsg403: '用户得到授权,但是访问是被禁止的。!', - errMsg404: '网络请求错误,未找到该资源!', - errMsg405: '网络请求错误,请求方法未允许!', - errMsg408: '网络请求超时!', - errMsg500: '服务器错误,请联系管理员!', - errMsg501: '网络未实现!', - errMsg502: '网络错误!', - errMsg503: '服务不可用,服务器暂时过载或维护!', - errMsg504: '网络超时!', - errMsg505: 'http版本不支持该请求!', - }, - app: { logoutTip: '温馨提醒', logoutMessage: '是否确认退出系统?', menuLoading: '菜单加载中...' }, - errorLog: { - tableTitle: '错误日志列表', - tableColumnType: '类型', - tableColumnDate: '时间', - tableColumnFile: '文件', - tableColumnMsg: '错误信息', - tableColumnStackMsg: 'stack信息', - - tableActionDesc: '详情', - - modalTitle: '错误详情', - - fireVueError: '点击触发vue错误', - fireResourceError: '点击触发资源加载错误', - fireAjaxError: '点击触发ajax错误', - - enableMessage: '只在`/src/settings/projectSetting.ts` 内的useErrorHandle=true时生效.', - }, - exception: { - backLogin: '返回登录', - backHome: '返回首页', - subTitle403: '抱歉,您无权访问此页面。', - subTitle404: '抱歉,您访问的页面不存在。', - subTitle500: '抱歉,服务器报告错误。', - noDataTitle: '当前页无数据', - networkErrorTitle: '网络错误', - networkErrorSubTitle: '抱歉,您的网络连接已断开,请检查您的网络!', - }, - lock: { - unlock: '点击解锁', - alert: '锁屏密码错误', - backToLogin: '返回登录', - entry: '进入系统', - placeholder: '请输入锁屏密码或者用户密码', - }, - login: { - backSignIn: '返回', - signInFormTitle: '登录', - mobileSignInFormTitle: '手机登录', - qrSignInFormTitle: '二维码登录', - signUpFormTitle: '注册', - forgetFormTitle: '重置密码', - - signInTitle: '开箱即用的中后台管理系统', - signInDesc: '输入您的个人详细信息开始使用!', - policy: '我同意xxx隐私政策', - scanSign: `扫码后点击"确认",即可完成登录`, - - loginButton: '登录', - registerButton: '注册', - rememberMe: '记住我', - forgetPassword: '忘记密码?', - otherSignIn: '其他登录方式', - - // notify - loginSuccessTitle: '登录成功', - loginSuccessDesc: '欢迎回来', - - // placeholder - accountPlaceholder: '请输入账号', - passwordPlaceholder: '请输入密码', - smsPlaceholder: '请输入验证码', - mobilePlaceholder: '请输入手机号码', - policyPlaceholder: '勾选后才能注册', - diffPwd: '两次输入密码不一致', - - userName: '账号', - password: '密码', - confirmPassword: '确认密码', - email: '邮箱', - smsCode: '短信验证码', - mobile: '手机号码', - }, -}; diff --git a/apps/admin/src/locales/lang/zh_CN.ts b/apps/admin/src/locales/lang/zh_CN.ts index d715c58..9d2b01b 100644 --- a/apps/admin/src/locales/lang/zh_CN.ts +++ b/apps/admin/src/locales/lang/zh_CN.ts @@ -1,10 +1,10 @@ import { genMessage } from '../helper'; import antdLocale from 'ant-design-vue/es/locale/zh_CN'; -const modules = import.meta.globEager('./zh-CN/**/*.ts'); +const modules = import.meta.glob('./zh-CN/**/*.json', { eager: true }); export default { message: { - ...genMessage(modules, 'zh-CN'), + ...genMessage(modules as Recordable, 'zh-CN'), antdLocale, }, }; diff --git a/apps/admin/src/locales/setupI18n.ts b/apps/admin/src/locales/setupI18n.ts index 405fb0c..c98ef92 100644 --- a/apps/admin/src/locales/setupI18n.ts +++ b/apps/admin/src/locales/setupI18n.ts @@ -1,5 +1,5 @@ import type { App } from 'vue'; -import type { I18n, I18nOptions } from 'vue-i18n'; +import type { I18nOptions } from 'vue-i18n'; import { createI18n } from 'vue-i18n'; import { setHtmlPageLang, setLoadLocalePool } from './helper'; @@ -39,6 +39,6 @@ async function createI18nOptions(): Promise { // setup i18n instance with glob export async function setupI18n(app: App) { const options = await createI18nOptions(); - i18n = createI18n(options) as I18n; + i18n = createI18n(options); app.use(i18n); } diff --git a/apps/admin/src/logics/error-handle/index.ts b/apps/admin/src/logics/error-handle/index.ts index e04c009..a18c644 100644 --- a/apps/admin/src/logics/error-handle/index.ts +++ b/apps/admin/src/logics/error-handle/index.ts @@ -62,16 +62,15 @@ function formatComponentName(vm: any) { /** * Configure Vue error handling function */ - -function vueErrorHandler(err: Error, vm: any, info: string) { +function vueErrorHandler(err: unknown, vm: any, info: string) { const errorLogStore = useErrorLogStoreWithOut(); const { name, path } = formatComponentName(vm); errorLogStore.addErrorLogInfo({ type: ErrorTypeEnum.VUE, name, file: path, - message: err.message, - stack: processStackMsg(err), + message: (err as Error).message, + stack: processStackMsg(err as Error), detail: info, url: window.location.href, }); diff --git a/apps/admin/src/logics/mitt/routeChange.ts b/apps/admin/src/logics/mitt/routeChange.ts index a985fe2..ccd777d 100644 --- a/apps/admin/src/logics/mitt/routeChange.ts +++ b/apps/admin/src/logics/mitt/routeChange.ts @@ -6,10 +6,12 @@ import { mitt } from '/@/utils/mitt'; import type { RouteLocationNormalized } from 'vue-router'; import { getRawRoute } from '/@/utils'; -const emitter = mitt(); - const key = Symbol(); +const emitter = mitt<{ + [key]: RouteLocationNormalized; +}>(); + let lastChangeTab: RouteLocationNormalized; export function setRouteChange(lastChangeRoute: RouteLocationNormalized) { diff --git a/apps/admin/src/main.ts b/apps/admin/src/main.ts index 60c3c05..1c4c808 100644 --- a/apps/admin/src/main.ts +++ b/apps/admin/src/main.ts @@ -1,7 +1,7 @@ import 'uno.css'; import '@/design/index.less'; import '@/components/VxeTable/src/css/index.scss'; -import 'ant-design-vue/dist/antd.less'; +import 'ant-design-vue/dist/reset.css'; // Register icon sprite import 'virtual:svg-icons-register'; diff --git a/apps/admin/src/router/guard/permissionGuard.ts b/apps/admin/src/router/guard/permissionGuard.ts index 5b1acde..fd2b5ab 100644 --- a/apps/admin/src/router/guard/permissionGuard.ts +++ b/apps/admin/src/router/guard/permissionGuard.ts @@ -95,7 +95,6 @@ export function createPermissionGuard(router: Router) { next(); return; } - const routes = await permissionStore.buildRoutesAction(); routes.forEach((route) => { diff --git a/apps/admin/src/router/menus/index.ts b/apps/admin/src/router/menus/index.ts index 014d757..c9124b7 100644 --- a/apps/admin/src/router/menus/index.ts +++ b/apps/admin/src/router/menus/index.ts @@ -10,12 +10,12 @@ import { router } from '/@/router'; import { PermissionModeEnum } from '/@/enums/appEnum'; import { pathToRegexp } from 'path-to-regexp'; -const modules = import.meta.globEager('./modules/**/*.ts'); +const modules = import.meta.glob('./modules/**/*.ts', { eager: true }); const menuModules: MenuModule[] = []; Object.keys(modules).forEach((key) => { - const mod = modules[key].default || {}; + const mod = (modules as Recordable)[key].default || {}; const modList = Array.isArray(mod) ? [...mod] : [mod]; menuModules.push(...modList); }); diff --git a/apps/admin/src/router/routes/basic.ts b/apps/admin/src/router/routes/basic.ts index 58db494..573ce2b 100644 --- a/apps/admin/src/router/routes/basic.ts +++ b/apps/admin/src/router/routes/basic.ts @@ -42,7 +42,7 @@ export const REDIRECT_ROUTE: AppRouteRecordRaw = { }, children: [ { - path: '/redirect/:path(.*)', + path: '/redirect/:path(.*)/:_redirect_type(.*)/:_origin_params(.*)?', name: REDIRECT_NAME, component: () => import('/@/views/sys/redirect/index.vue'), meta: { diff --git a/apps/admin/src/router/routes/index.ts b/apps/admin/src/router/routes/index.ts index 5262342..79115b7 100644 --- a/apps/admin/src/router/routes/index.ts +++ b/apps/admin/src/router/routes/index.ts @@ -6,13 +6,13 @@ import { mainOutRoutes } from './mainOut'; import { PageEnum } from '/@/enums/pageEnum'; import { t } from '/@/hooks/web/useI18n'; -// import.meta.globEager() 直接引入所有的模块 Vite 独有的功能 -const modules = import.meta.globEager('./modules/**/*.ts'); +// import.meta.glob() 直接引入所有的模块 Vite 独有的功能 +const modules = import.meta.glob('./modules/**/*.ts', { eager: true }); const routeModuleList: AppRouteModule[] = []; // 加入到路由集合中 Object.keys(modules).forEach((key) => { - const mod = modules[key].default || {}; + const mod = (modules as Recordable)[key].default || {}; const modList = Array.isArray(mod) ? [...mod] : [mod]; routeModuleList.push(...modList); }); diff --git a/apps/admin/src/router/routes/modules/demo/charts.ts b/apps/admin/src/router/routes/modules/demo/charts.ts deleted file mode 100644 index c36b5ee..0000000 --- a/apps/admin/src/router/routes/modules/demo/charts.ts +++ /dev/null @@ -1,80 +0,0 @@ -import type { AppRouteModule } from '/@/router/types'; - -import { getParentLayout, LAYOUT } from '/@/router/constant'; -import { t } from '/@/hooks/web/useI18n'; - -const charts: AppRouteModule = { - path: '/charts', - name: 'Charts', - component: LAYOUT, - redirect: '/charts/echarts/map', - meta: { - orderNo: 500, - icon: 'ion:bar-chart-outline', - title: t('routes.demo.charts.charts'), - }, - children: [ - { - path: 'baiduMap', - name: 'BaiduMap', - meta: { - title: t('routes.demo.charts.baiduMap'), - }, - component: () => import('/@/views/demo/charts/map/Baidu.vue'), - }, - { - path: 'aMap', - name: 'AMap', - meta: { - title: t('routes.demo.charts.aMap'), - }, - component: () => import('/@/views/demo/charts/map/Gaode.vue'), - }, - { - path: 'googleMap', - name: 'GoogleMap', - meta: { - title: t('routes.demo.charts.googleMap'), - }, - component: () => import('/@/views/demo/charts/map/Google.vue'), - }, - - { - path: 'echarts', - name: 'Echarts', - component: getParentLayout('Echarts'), - meta: { - title: 'Echarts', - }, - redirect: '/charts/echarts/map', - children: [ - { - path: 'map', - name: 'Map', - component: () => import('/@/views/demo/charts/Map.vue'), - meta: { - title: t('routes.demo.charts.map'), - }, - }, - { - path: 'line', - name: 'Line', - component: () => import('/@/views/demo/charts/Line.vue'), - meta: { - title: t('routes.demo.charts.line'), - }, - }, - { - path: 'pie', - name: 'Pie', - component: () => import('/@/views/demo/charts/Pie.vue'), - meta: { - title: t('routes.demo.charts.pie'), - }, - }, - ], - }, - ], -}; - -export default charts; diff --git a/apps/admin/src/router/routes/modules/demo/comp.ts b/apps/admin/src/router/routes/modules/demo/comp.ts deleted file mode 100644 index 28091ba..0000000 --- a/apps/admin/src/router/routes/modules/demo/comp.ts +++ /dev/null @@ -1,545 +0,0 @@ -import type { AppRouteModule } from '/@/router/types'; - -import { getParentLayout, LAYOUT } from '/@/router/constant'; -import { t } from '/@/hooks/web/useI18n'; - -const comp: AppRouteModule = { - path: '/comp', - name: 'Comp', - component: LAYOUT, - redirect: '/comp/basic', - meta: { - orderNo: 30, - icon: 'ion:layers-outline', - title: t('routes.demo.comp.comp'), - }, - - children: [ - { - path: 'basic', - name: 'BasicDemo', - component: () => import('/@/views/demo/comp/button/index.vue'), - meta: { - title: t('routes.demo.comp.basic'), - }, - }, - - { - path: 'form', - name: 'FormDemo', - redirect: '/comp/form/basic', - component: getParentLayout('FormDemo'), - meta: { - // icon: 'mdi:form-select', - title: t('routes.demo.form.form'), - }, - children: [ - { - path: 'basic', - name: 'FormBasicDemo', - component: () => import('/@/views/demo/form/index.vue'), - meta: { - title: t('routes.demo.form.basic'), - }, - }, - { - path: 'useForm', - name: 'UseFormDemo', - component: () => import('/@/views/demo/form/UseForm.vue'), - meta: { - title: t('routes.demo.form.useForm'), - }, - }, - { - path: 'refForm', - name: 'RefFormDemo', - component: () => import('/@/views/demo/form/RefForm.vue'), - meta: { - title: t('routes.demo.form.refForm'), - }, - }, - { - path: 'advancedForm', - name: 'AdvancedFormDemo', - component: () => import('/@/views/demo/form/AdvancedForm.vue'), - meta: { - title: t('routes.demo.form.advancedForm'), - }, - }, - { - path: 'ruleForm', - name: 'RuleFormDemo', - component: () => import('/@/views/demo/form/RuleForm.vue'), - meta: { - title: t('routes.demo.form.ruleForm'), - }, - }, - { - path: 'dynamicForm', - name: 'DynamicFormDemo', - component: () => import('/@/views/demo/form/DynamicForm.vue'), - meta: { - title: t('routes.demo.form.dynamicForm'), - }, - }, - { - path: 'customerForm', - name: 'CustomerFormDemo', - component: () => import('/@/views/demo/form/CustomerForm.vue'), - meta: { - title: t('routes.demo.form.customerForm'), - }, - }, - { - path: 'appendForm', - name: 'appendFormDemo', - component: () => import('/@/views/demo/form/AppendForm.vue'), - meta: { - title: t('routes.demo.form.appendForm'), - }, - }, - { - path: 'tabsForm', - name: 'tabsFormDemo', - component: () => import('/@/views/demo/form/TabsForm.vue'), - meta: { - title: t('routes.demo.form.tabsForm'), - }, - }, - ], - }, - { - path: 'table', - name: 'TableDemo', - redirect: '/comp/table/basic', - component: getParentLayout('TableDemo'), - meta: { - // icon: 'carbon:table-split', - title: t('routes.demo.table.table'), - }, - - children: [ - { - path: 'basic', - name: 'TableBasicDemo', - component: () => import('/@/views/demo/table/Basic.vue'), - meta: { - title: t('routes.demo.table.basic'), - }, - }, - { - path: 'treeTable', - name: 'TreeTableDemo', - component: () => import('/@/views/demo/table/TreeTable.vue'), - meta: { - title: t('routes.demo.table.treeTable'), - }, - }, - { - path: 'fetchTable', - name: 'FetchTableDemo', - component: () => import('/@/views/demo/table/FetchTable.vue'), - meta: { - title: t('routes.demo.table.fetchTable'), - }, - }, - { - path: 'fixedColumn', - name: 'FixedColumnDemo', - component: () => import('/@/views/demo/table/FixedColumn.vue'), - meta: { - title: t('routes.demo.table.fixedColumn'), - }, - }, - { - path: 'customerCell', - name: 'CustomerCellDemo', - component: () => import('/@/views/demo/table/CustomerCell.vue'), - meta: { - title: t('routes.demo.table.customerCell'), - }, - }, - { - path: 'formTable', - name: 'FormTableDemo', - component: () => import('/@/views/demo/table/FormTable.vue'), - meta: { - title: t('routes.demo.table.formTable'), - }, - }, - { - path: 'useTable', - name: 'UseTableDemo', - component: () => import('/@/views/demo/table/UseTable.vue'), - meta: { - title: t('routes.demo.table.useTable'), - }, - }, - { - path: 'refTable', - name: 'RefTableDemo', - component: () => import('/@/views/demo/table/RefTable.vue'), - meta: { - title: t('routes.demo.table.refTable'), - }, - }, - { - path: 'multipleHeader', - name: 'MultipleHeaderDemo', - component: () => import('/@/views/demo/table/MultipleHeader.vue'), - meta: { - title: t('routes.demo.table.multipleHeader'), - }, - }, - { - path: 'mergeHeader', - name: 'MergeHeaderDemo', - component: () => import('/@/views/demo/table/MergeHeader.vue'), - meta: { - title: t('routes.demo.table.mergeHeader'), - }, - }, - { - path: 'expandTable', - name: 'ExpandTableDemo', - component: () => import('/@/views/demo/table/ExpandTable.vue'), - meta: { - title: t('routes.demo.table.expandTable'), - }, - }, - { - path: 'fixedHeight', - name: 'FixedHeightDemo', - component: () => import('/@/views/demo/table/FixedHeight.vue'), - meta: { - title: t('routes.demo.table.fixedHeight'), - }, - }, - { - path: 'footerTable', - name: 'FooterTableDemo', - component: () => import('/@/views/demo/table/FooterTable.vue'), - meta: { - title: t('routes.demo.table.footerTable'), - }, - }, - { - path: 'editCellTable', - name: 'EditCellTableDemo', - component: () => import('/@/views/demo/table/EditCellTable.vue'), - meta: { - title: t('routes.demo.table.editCellTable'), - }, - }, - { - path: 'editRowTable', - name: 'EditRowTableDemo', - component: () => import('/@/views/demo/table/EditRowTable.vue'), - meta: { - title: t('routes.demo.table.editRowTable'), - }, - }, - { - path: 'authColumn', - name: 'AuthColumnDemo', - component: () => import('/@/views/demo/table/AuthColumn.vue'), - meta: { - title: t('routes.demo.table.authColumn'), - }, - }, - { - path: 'resizeParentHeightTable', - name: 'ResizeParentHeightTable', - component: () => import('/@/views/demo/table/ResizeParentHeightTable.vue'), - meta: { - title: t('routes.demo.table.resizeParentHeightTable'), - }, - }, - { - path: 'vxeTable', - name: 'VxeTableDemo', - component: () => import('/@/views/demo/table/VxeTable.vue'), - meta: { - title: t('routes.demo.table.vxeTable'), - }, - }, - ], - }, - { - path: 'transition', - name: 'transitionDemo', - component: () => import('/@/views/demo/comp/transition/index.vue'), - meta: { - title: t('routes.demo.comp.transition'), - }, - }, - { - path: 'cropper', - name: 'CropperDemo', - component: () => import('/@/views/demo/comp/cropper/index.vue'), - meta: { - title: t('routes.demo.comp.cropperImage'), - }, - }, - - { - path: 'timestamp', - name: 'TimeDemo', - component: () => import('/@/views/demo/comp/time/index.vue'), - meta: { - title: t('routes.demo.comp.time'), - }, - }, - { - path: 'countTo', - name: 'CountTo', - component: () => import('/@/views/demo/comp/count-to/index.vue'), - meta: { - title: t('routes.demo.comp.countTo'), - }, - }, - { - path: 'tree', - name: 'TreeDemo', - redirect: '/comp/tree/basic', - component: getParentLayout('TreeDemo'), - meta: { - // icon: 'clarity:tree-view-line', - title: t('routes.demo.comp.tree'), - }, - children: [ - { - path: 'basic', - name: 'BasicTreeDemo', - component: () => import('/@/views/demo/tree/index.vue'), - meta: { - title: t('routes.demo.comp.treeBasic'), - }, - }, - { - path: 'editTree', - name: 'EditTreeDemo', - component: () => import('/@/views/demo/tree/EditTree.vue'), - meta: { - title: t('routes.demo.comp.editTree'), - }, - }, - { - path: 'actionTree', - name: 'ActionTreeDemo', - component: () => import('/@/views/demo/tree/ActionTree.vue'), - meta: { - title: t('routes.demo.comp.actionTree'), - }, - }, - ], - }, - { - path: 'editor', - name: 'EditorDemo', - redirect: '/comp/editor/markdown', - component: getParentLayout('EditorDemo'), - meta: { - // icon: 'carbon:table-split', - title: t('routes.demo.editor.editor'), - }, - children: [ - { - path: 'json', - component: () => import('/@/views/demo/editor/json/index.vue'), - name: 'JsonEditorDemo', - meta: { - title: t('routes.demo.editor.jsonEditor'), - }, - }, - { - path: 'markdown', - component: getParentLayout('MarkdownDemo'), - name: 'MarkdownDemo', - meta: { - title: t('routes.demo.editor.markdown'), - }, - redirect: '/comp/editor/markdown/index', - children: [ - { - path: 'index', - name: 'MarkDownBasicDemo', - component: () => import('/@/views/demo/editor/markdown/index.vue'), - meta: { - title: t('routes.demo.editor.tinymceBasic'), - }, - }, - { - path: 'editor', - name: 'MarkDownFormDemo', - component: () => import('/@/views/demo/editor/markdown/Editor.vue'), - meta: { - title: t('routes.demo.editor.tinymceForm'), - }, - }, - ], - }, - - { - path: 'tinymce', - component: getParentLayout('TinymceDemo'), - name: 'TinymceDemo', - meta: { - title: t('routes.demo.editor.tinymce'), - }, - redirect: '/comp/editor/tinymce/index', - children: [ - { - path: 'index', - name: 'TinymceBasicDemo', - component: () => import('/@/views/demo/editor/tinymce/index.vue'), - meta: { - title: t('routes.demo.editor.tinymceBasic'), - }, - }, - { - path: 'editor', - name: 'TinymceFormDemo', - component: () => import('/@/views/demo/editor/tinymce/Editor.vue'), - meta: { - title: t('routes.demo.editor.tinymceForm'), - }, - }, - ], - }, - ], - }, - { - path: 'scroll', - name: 'ScrollDemo', - redirect: '/comp/scroll/basic', - component: getParentLayout('ScrollDemo'), - meta: { - title: t('routes.demo.comp.scroll'), - }, - children: [ - { - path: 'basic', - name: 'BasicScrollDemo', - component: () => import('/@/views/demo/comp/scroll/index.vue'), - meta: { - title: t('routes.demo.comp.scrollBasic'), - }, - }, - { - path: 'action', - name: 'ActionScrollDemo', - component: () => import('/@/views/demo/comp/scroll/Action.vue'), - meta: { - title: t('routes.demo.comp.scrollAction'), - }, - }, - { - path: 'virtualScroll', - name: 'VirtualScrollDemo', - component: () => import('/@/views/demo/comp/scroll/VirtualScroll.vue'), - meta: { - title: t('routes.demo.comp.virtualScroll'), - }, - }, - ], - }, - - { - path: 'modal', - name: 'ModalDemo', - component: () => import('/@/views/demo/comp/modal/index.vue'), - meta: { - title: t('routes.demo.comp.modal'), - }, - }, - { - path: 'drawer', - name: 'DrawerDemo', - component: () => import('/@/views/demo/comp/drawer/index.vue'), - meta: { - title: t('routes.demo.comp.drawer'), - }, - }, - { - path: 'desc', - name: 'DescDemo', - component: () => import('/@/views/demo/comp/desc/index.vue'), - meta: { - title: t('routes.demo.comp.desc'), - }, - }, - - { - path: 'verify', - name: 'VerifyDemo', - component: getParentLayout('VerifyDemo'), - redirect: '/comp/verify/drag', - meta: { - title: t('routes.demo.comp.verify'), - }, - children: [ - { - path: 'drag', - name: 'VerifyDragDemo', - component: () => import('/@/views/demo/comp/verify/index.vue'), - meta: { - title: t('routes.demo.comp.verifyDrag'), - }, - }, - { - path: 'rotate', - name: 'VerifyRotateDemo', - component: () => import('/@/views/demo/comp/verify/Rotate.vue'), - meta: { - title: t('routes.demo.comp.verifyRotate'), - }, - }, - ], - }, - // - - { - path: 'qrcode', - name: 'QrCodeDemo', - component: () => import('/@/views/demo/comp/qrcode/index.vue'), - meta: { - title: t('routes.demo.comp.qrcode'), - }, - }, - { - path: 'strength-meter', - name: 'StrengthMeterDemo', - component: () => import('/@/views/demo/comp/strength-meter/index.vue'), - meta: { - title: t('routes.demo.comp.strength'), - }, - }, - { - path: 'upload', - name: 'UploadDemo', - component: () => import('/@/views/demo/comp/upload/index.vue'), - meta: { - title: t('routes.demo.comp.upload'), - }, - }, - { - path: 'loading', - name: 'LoadingDemo', - component: () => import('/@/views/demo/comp/loading/index.vue'), - meta: { - title: t('routes.demo.comp.loading'), - }, - }, - { - path: 'cardList', - name: 'CardListDemo', - component: () => import('/@/views/demo/comp/card-list/index.vue'), - meta: { - title: t('routes.demo.comp.cardList'), - }, - }, - ], -}; - -export default comp; diff --git a/apps/admin/src/router/routes/modules/demo/feat.ts b/apps/admin/src/router/routes/modules/demo/feat.ts deleted file mode 100644 index 7c7121d..0000000 --- a/apps/admin/src/router/routes/modules/demo/feat.ts +++ /dev/null @@ -1,315 +0,0 @@ -import type { AppRouteModule } from '/@/router/types'; - -import { getParentLayout, LAYOUT } from '/@/router/constant'; -import { t } from '/@/hooks/web/useI18n'; - -const feat: AppRouteModule = { - path: '/feat', - name: 'FeatDemo', - component: LAYOUT, - redirect: '/feat/icon', - meta: { - orderNo: 19, - icon: 'ion:git-compare-outline', - title: t('routes.demo.feat.feat'), - }, - - children: [ - { - path: 'icon', - name: 'IconDemo', - component: () => import('/@/views/demo/feat/icon/index.vue'), - meta: { - title: t('routes.demo.feat.icon'), - }, - }, - { - path: 'ws', - name: 'WebSocket', - component: () => import('/@/views/demo/feat/ws/index.vue'), - meta: { - title: t('routes.demo.feat.ws'), - }, - }, - { - path: 'session-timeout', - name: 'SessionTimeout', - component: () => import('/@/views/demo/feat/session-timeout/index.vue'), - meta: { - title: t('routes.demo.feat.sessionTimeout'), - }, - }, - { - path: 'print', - name: 'Print', - component: () => import('/@/views/demo/feat/print/index.vue'), - meta: { - title: t('routes.demo.feat.print'), - }, - }, - { - path: 'tabs', - name: 'TabsDemo', - component: () => import('/@/views/demo/feat/tabs/index.vue'), - meta: { - title: t('routes.demo.feat.tabs'), - hideChildrenInMenu: true, - }, - children: [ - { - path: 'detail/:id', - name: 'TabDetail', - component: () => import('/@/views/demo/feat/tabs/TabDetail.vue'), - meta: { - currentActiveMenu: '/feat/tabs', - title: t('routes.demo.feat.tabDetail'), - hideMenu: true, - dynamicLevel: 3, - realPath: '/feat/tabs/detail', - }, - }, - ], - }, - { - path: 'breadcrumb', - name: 'BreadcrumbDemo', - redirect: '/feat/breadcrumb/flat', - component: getParentLayout('BreadcrumbDemo'), - meta: { - title: t('routes.demo.feat.breadcrumb'), - }, - - children: [ - { - path: 'flat', - name: 'BreadcrumbFlatDemo', - component: () => import('/@/views/demo/feat/breadcrumb/FlatList.vue'), - meta: { - title: t('routes.demo.feat.breadcrumbFlat'), - }, - }, - { - path: 'flatDetail', - name: 'BreadcrumbFlatDetailDemo', - component: () => import('/@/views/demo/feat/breadcrumb/FlatListDetail.vue'), - meta: { - title: t('routes.demo.feat.breadcrumbFlatDetail'), - hideMenu: true, - hideTab: true, - currentActiveMenu: '/feat/breadcrumb/flat', - }, - }, - { - path: 'children', - name: 'BreadcrumbChildrenDemo', - component: () => import('/@/views/demo/feat/breadcrumb/ChildrenList.vue'), - meta: { - title: t('routes.demo.feat.breadcrumbChildren'), - }, - children: [ - { - path: 'childrenDetail', - name: 'BreadcrumbChildrenDetailDemo', - component: () => import('/@/views/demo/feat/breadcrumb/ChildrenListDetail.vue'), - meta: { - currentActiveMenu: '/feat/breadcrumb/children', - title: t('routes.demo.feat.breadcrumbChildrenDetail'), - //hideTab: true, - // hideMenu: true, - }, - }, - ], - }, - ], - }, - - { - path: 'context-menu', - name: 'ContextMenuDemo', - component: () => import('/@/views/demo/feat/context-menu/index.vue'), - meta: { - title: t('routes.demo.feat.contextMenu'), - }, - }, - { - path: 'download', - name: 'DownLoadDemo', - component: () => import('/@/views/demo/feat/download/index.vue'), - meta: { - title: t('routes.demo.feat.download'), - }, - }, - { - path: 'click-out-side', - name: 'ClickOutSideDemo', - component: () => import('/@/views/demo/feat/click-out-side/index.vue'), - meta: { - title: t('routes.demo.feat.clickOutSide'), - }, - }, - { - path: 'img-preview', - name: 'ImgPreview', - component: () => import('/@/views/demo/feat/img-preview/index.vue'), - meta: { - title: t('routes.demo.feat.imgPreview'), - }, - }, - { - path: 'copy', - name: 'CopyDemo', - component: () => import('/@/views/demo/feat/copy/index.vue'), - meta: { - title: t('routes.demo.feat.copy'), - }, - }, - { - path: 'msg', - name: 'MsgDemo', - component: () => import('/@/views/demo/feat/msg/index.vue'), - meta: { - title: t('routes.demo.feat.msg'), - }, - }, - { - path: 'watermark', - name: 'WatermarkDemo', - component: () => import('/@/views/demo/feat/watermark/index.vue'), - meta: { - title: t('routes.demo.feat.watermark'), - }, - }, - { - path: 'ripple', - name: 'RippleDemo', - component: () => import('/@/views/demo/feat/ripple/index.vue'), - meta: { - title: t('routes.demo.feat.ripple'), - }, - }, - { - path: 'full-screen', - name: 'FullScreenDemo', - component: () => import('/@/views/demo/feat/full-screen/index.vue'), - meta: { - title: t('routes.demo.feat.fullScreen'), - }, - }, - { - path: '/error-log', - name: 'ErrorLog', - component: () => import('/@/views/sys/error-log/index.vue'), - meta: { - title: t('routes.demo.feat.errorLog'), - }, - }, - { - path: 'excel', - name: 'Excel', - redirect: '/feat/excel/customExport', - component: getParentLayout('Excel'), - meta: { - // icon: 'mdi:microsoft-excel', - title: t('routes.demo.excel.excel'), - }, - - children: [ - { - path: 'customExport', - name: 'CustomExport', - component: () => import('/@/views/demo/excel/CustomExport.vue'), - meta: { - title: t('routes.demo.excel.customExport'), - }, - }, - { - path: 'jsonExport', - name: 'JsonExport', - component: () => import('/@/views/demo/excel/JsonExport.vue'), - meta: { - title: t('routes.demo.excel.jsonExport'), - }, - }, - { - path: 'arrayExport', - name: 'ArrayExport', - component: () => import('/@/views/demo/excel/ArrayExport.vue'), - meta: { - title: t('routes.demo.excel.arrayExport'), - }, - }, - { - path: 'importExcel', - name: 'ImportExcel', - component: () => import('/@/views/demo/excel/ImportExcel.vue'), - meta: { - title: t('routes.demo.excel.importExcel'), - }, - }, - ], - }, - { - path: 'testTab/:id', - name: 'TestTab', - component: () => import('/@/views/demo/feat/tab-params/index.vue'), - meta: { - title: t('routes.demo.feat.tab'), - carryParam: true, - hidePathForChildren: true, - }, - children: [ - { - path: 'testTab/id1', - name: 'TestTab1', - component: () => import('/@/views/demo/feat/tab-params/index.vue'), - meta: { - title: t('routes.demo.feat.tab1'), - carryParam: true, - ignoreRoute: true, - }, - }, - { - path: 'testTab/id2', - name: 'TestTab2', - component: () => import('/@/views/demo/feat/tab-params/index.vue'), - meta: { - title: t('routes.demo.feat.tab2'), - carryParam: true, - ignoreRoute: true, - }, - }, - ], - }, - { - path: 'testParam/:id', - name: 'TestParam', - component: getParentLayout('TestParam'), - meta: { - title: t('routes.demo.feat.menu'), - ignoreKeepAlive: true, - }, - children: [ - { - path: 'sub1', - name: 'TestParam_1', - component: () => import('/@/views/demo/feat/menu-params/index.vue'), - meta: { - title: t('routes.demo.feat.menu1'), - ignoreKeepAlive: true, - }, - }, - { - path: 'sub2', - name: 'TestParam_2', - component: () => import('/@/views/demo/feat/menu-params/index.vue'), - meta: { - title: t('routes.demo.feat.menu2'), - ignoreKeepAlive: true, - }, - }, - ], - }, - ], -}; - -export default feat; diff --git a/apps/admin/src/router/routes/modules/demo/flow.ts b/apps/admin/src/router/routes/modules/demo/flow.ts deleted file mode 100644 index 4654c9b..0000000 --- a/apps/admin/src/router/routes/modules/demo/flow.ts +++ /dev/null @@ -1,28 +0,0 @@ -import type { AppRouteModule } from '/@/router/types'; - -import { LAYOUT } from '/@/router/constant'; -import { t } from '/@/hooks/web/useI18n'; - -const charts: AppRouteModule = { - path: '/flow', - name: 'FlowDemo', - component: LAYOUT, - redirect: '/flow/flowChart', - meta: { - orderNo: 5000, - icon: 'tabler:chart-dots', - title: t('routes.demo.flow.name'), - }, - children: [ - { - path: 'flowChart', - name: 'flowChartDemo', - component: () => import('/@/views/demo/comp/flow-chart/index.vue'), - meta: { - title: t('routes.demo.flow.flowChart'), - }, - }, - ], -}; - -export default charts; diff --git a/apps/admin/src/router/routes/modules/demo/iframe.ts b/apps/admin/src/router/routes/modules/demo/iframe.ts deleted file mode 100644 index 9a3eaa8..0000000 --- a/apps/admin/src/router/routes/modules/demo/iframe.ts +++ /dev/null @@ -1,49 +0,0 @@ -import type { AppRouteModule } from '/@/router/types'; - -import { LAYOUT } from '/@/router/constant'; -import { t } from '/@/hooks/web/useI18n'; - -const IFrame = () => import('/@/views/sys/iframe/FrameBlank.vue'); - -const iframe: AppRouteModule = { - path: '/frame', - name: 'Frame', - component: LAYOUT, - redirect: '/frame/doc', - meta: { - orderNo: 1000, - icon: 'ion:tv-outline', - title: t('routes.demo.iframe.frame'), - }, - - children: [ - { - path: 'doc', - name: 'Doc', - component: IFrame, - meta: { - frameSrc: 'https://doc.vvbin.cn/', - title: t('routes.demo.iframe.doc'), - }, - }, - { - path: 'antv', - name: 'Antv', - component: IFrame, - meta: { - frameSrc: 'https://www.antdv.com/docs/vue/introduce-cn/', - title: t('routes.demo.iframe.antv'), - }, - }, - { - path: 'https://doc.vvbin.cn/', - name: 'DocExternal', - component: IFrame, - meta: { - title: t('routes.demo.iframe.docExternal'), - }, - }, - ], -}; - -export default iframe; diff --git a/apps/admin/src/router/routes/modules/demo/level.ts b/apps/admin/src/router/routes/modules/demo/level.ts deleted file mode 100644 index 3cee375..0000000 --- a/apps/admin/src/router/routes/modules/demo/level.ts +++ /dev/null @@ -1,68 +0,0 @@ -import type { AppRouteModule } from '/@/router/types'; - -import { getParentLayout, LAYOUT } from '/@/router/constant'; -import { t } from '/@/hooks/web/useI18n'; - -const permission: AppRouteModule = { - path: '/level', - name: 'Level', - component: LAYOUT, - redirect: '/level/menu1/menu1-1/menu1-1-1', - meta: { - orderNo: 2000, - icon: 'ion:menu-outline', - title: t('routes.demo.level.level'), - }, - - children: [ - { - path: 'menu1', - name: 'Menu1Demo', - component: getParentLayout('Menu1Demo'), - meta: { - title: 'Menu1', - }, - redirect: '/level/menu1/menu1-1/menu1-1-1', - children: [ - { - path: 'menu1-1', - name: 'Menu11Demo', - component: getParentLayout('Menu11Demo'), - meta: { - title: 'Menu1-1', - }, - redirect: '/level/menu1/menu1-1/menu1-1-1', - children: [ - { - path: 'menu1-1-1', - name: 'Menu111Demo', - component: () => import('/@/views/demo/level/Menu111.vue'), - meta: { - title: 'Menu111', - }, - }, - ], - }, - { - path: 'menu1-2', - name: 'Menu12Demo', - component: () => import('/@/views/demo/level/Menu12.vue'), - meta: { - title: 'Menu1-2', - }, - }, - ], - }, - { - path: 'menu2', - name: 'Menu2Demo', - component: () => import('/@/views/demo/level/Menu2.vue'), - meta: { - title: 'Menu2', - // ignoreKeepAlive: true, - }, - }, - ], -}; - -export default permission; diff --git a/apps/admin/src/router/routes/modules/demo/page.ts b/apps/admin/src/router/routes/modules/demo/page.ts deleted file mode 100644 index 17ab276..0000000 --- a/apps/admin/src/router/routes/modules/demo/page.ts +++ /dev/null @@ -1,255 +0,0 @@ -import type { AppRouteModule } from '/@/router/types'; - -import { getParentLayout, LAYOUT } from '/@/router/constant'; -import { ExceptionEnum } from '/@/enums/exceptionEnum'; -import { t } from '/@/hooks/web/useI18n'; - -const ExceptionPage = () => import('/@/views/sys/exception/Exception.vue'); - -const page: AppRouteModule = { - path: '/page-demo', - name: 'PageDemo', - component: LAYOUT, - redirect: '/page-demo/form/basic', - meta: { - orderNo: 20, - icon: 'ion:aperture-outline', - title: t('routes.demo.page.page'), - }, - children: [ - // =============================form start============================= - { - path: 'form', - name: 'FormPage', - redirect: '/page-demo/form/basic', - component: getParentLayout('FormPage'), - meta: { - title: t('routes.demo.page.form'), - }, - children: [ - { - path: 'basic', - name: 'FormBasicPage', - component: () => import('/@/views/demo/page/form/basic/index.vue'), - meta: { - title: t('routes.demo.page.formBasic'), - }, - }, - { - path: 'step', - name: 'FormStepPage', - component: () => import('/@/views/demo/page/form/step/index.vue'), - meta: { - title: t('routes.demo.page.formStep'), - }, - }, - { - path: 'high', - name: 'FormHightPage', - component: () => import('/@/views/demo/page/form/high/index.vue'), - meta: { - title: t('routes.demo.page.formHigh'), - }, - }, - ], - }, - // =============================form end============================= - // =============================desc start============================= - { - path: 'desc', - name: 'DescPage', - component: getParentLayout('DescPage'), - redirect: '/page-demo/desc/basic', - meta: { - title: t('routes.demo.page.desc'), - }, - children: [ - { - path: 'basic', - name: 'DescBasicPage', - component: () => import('/@/views/demo/page/desc/basic/index.vue'), - meta: { - title: t('routes.demo.page.descBasic'), - }, - }, - { - path: 'high', - name: 'DescHighPage', - component: () => import('/@/views/demo/page/desc/high/index.vue'), - meta: { - title: t('routes.demo.page.descHigh'), - }, - }, - ], - }, - // =============================desc end============================= - - // =============================result start============================= - { - path: 'result', - name: 'ResultPage', - redirect: '/page-demo/result/success', - component: getParentLayout('ResultPage'), - - meta: { - title: t('routes.demo.page.result'), - }, - children: [ - { - path: 'success', - name: 'ResultSuccessPage', - component: () => import('/@/views/demo/page/result/success/index.vue'), - meta: { - title: t('routes.demo.page.resultSuccess'), - }, - }, - { - path: 'fail', - name: 'ResultFailPage', - component: () => import('/@/views/demo/page/result/fail/index.vue'), - meta: { - title: t('routes.demo.page.resultFail'), - }, - }, - ], - }, - // =============================result end============================= - - // =============================account start============================= - { - path: 'account', - name: 'AccountPage', - component: getParentLayout('AccountPage'), - redirect: '/page-demo/account/setting', - meta: { - title: t('routes.demo.page.account'), - }, - children: [ - { - path: 'center', - name: 'AccountCenterPage', - component: () => import('/@/views/demo/page/account/center/index.vue'), - meta: { - title: t('routes.demo.page.accountCenter'), - }, - }, - { - path: 'setting', - name: 'AccountSettingPage', - component: () => import('/@/views/demo/page/account/setting/index.vue'), - meta: { - title: t('routes.demo.page.accountSetting'), - }, - }, - ], - }, - // =============================account end============================= - // =============================exception start============================= - { - path: 'exception', - name: 'ExceptionPage', - component: getParentLayout('ExceptionPage'), - redirect: '/page-demo/exception/404', - meta: { - title: t('routes.demo.page.exception'), - }, - children: [ - { - path: '403', - name: 'PageNotAccess', - component: ExceptionPage, - props: { - status: ExceptionEnum.PAGE_NOT_ACCESS, - }, - meta: { - title: '403', - }, - }, - { - path: '404', - name: 'PageNotFound', - component: ExceptionPage, - props: { - status: ExceptionEnum.PAGE_NOT_FOUND, - }, - meta: { - title: '404', - }, - }, - { - path: '500', - name: 'ServiceError', - component: ExceptionPage, - props: { - status: ExceptionEnum.ERROR, - }, - meta: { - title: '500', - }, - }, - { - path: 'net-work-error', - name: 'NetWorkError', - component: ExceptionPage, - props: { - status: ExceptionEnum.NET_WORK_ERROR, - }, - meta: { - title: t('routes.demo.page.netWorkError'), - }, - }, - { - path: 'not-data', - name: 'NotData', - component: ExceptionPage, - props: { - status: ExceptionEnum.PAGE_NOT_DATA, - }, - meta: { - title: t('routes.demo.page.notData'), - }, - }, - ], - }, - // =============================exception end============================= - // =============================list start============================= - { - path: 'list', - name: 'ListPage', - component: getParentLayout('ListPage'), - redirect: '/page-demo/list/card', - meta: { - title: t('routes.demo.page.list'), - }, - children: [ - { - path: 'basic', - name: 'ListBasicPage', - component: () => import('/@/views/demo/page/list/basic/index.vue'), - meta: { - title: t('routes.demo.page.listBasic'), - }, - }, - { - path: 'card', - name: 'ListCardPage', - component: () => import('/@/views/demo/page/list/card/index.vue'), - meta: { - title: t('routes.demo.page.listCard'), - }, - }, - { - path: 'search', - name: 'ListSearchPage', - component: () => import('/@/views/demo/page/list/search/index.vue'), - meta: { - title: t('routes.demo.page.listSearch'), - }, - }, - ], - }, - // =============================list end============================= - ], -}; - -export default page; diff --git a/apps/admin/src/router/routes/modules/demo/permission.ts b/apps/admin/src/router/routes/modules/demo/permission.ts deleted file mode 100644 index e876362..0000000 --- a/apps/admin/src/router/routes/modules/demo/permission.ts +++ /dev/null @@ -1,92 +0,0 @@ -import type { AppRouteModule } from '/@/router/types'; - -import { getParentLayout, LAYOUT } from '/@/router/constant'; -import { RoleEnum } from '/@/enums/roleEnum'; -import { t } from '/@/hooks/web/useI18n'; - -const permission: AppRouteModule = { - path: '/permission', - name: 'Permission', - component: LAYOUT, - redirect: '/permission/front/page', - meta: { - orderNo: 15, - icon: 'ion:key-outline', - title: t('routes.demo.permission.permission'), - }, - - children: [ - { - path: 'front', - name: 'PermissionFrontDemo', - component: getParentLayout('PermissionFrontDemo'), - meta: { - title: t('routes.demo.permission.front'), - }, - children: [ - { - path: 'page', - name: 'FrontPageAuth', - component: () => import('/@/views/demo/permission/front/index.vue'), - meta: { - title: t('routes.demo.permission.frontPage'), - }, - }, - { - path: 'btn', - name: 'FrontBtnAuth', - component: () => import('/@/views/demo/permission/front/Btn.vue'), - meta: { - title: t('routes.demo.permission.frontBtn'), - }, - }, - { - path: 'auth-pageA', - name: 'FrontAuthPageA', - component: () => import('/@/views/demo/permission/front/AuthPageA.vue'), - meta: { - title: t('routes.demo.permission.frontTestA'), - roles: [RoleEnum.SUPER], - }, - }, - { - path: 'auth-pageB', - name: 'FrontAuthPageB', - component: () => import('/@/views/demo/permission/front/AuthPageB.vue'), - meta: { - title: t('routes.demo.permission.frontTestB'), - roles: [RoleEnum.TEST], - }, - }, - ], - }, - { - path: 'back', - name: 'PermissionBackDemo', - component: getParentLayout('PermissionBackDemo'), - meta: { - title: t('routes.demo.permission.back'), - }, - children: [ - { - path: 'page', - name: 'BackAuthPage', - component: () => import('/@/views/demo/permission/back/index.vue'), - meta: { - title: t('routes.demo.permission.backPage'), - }, - }, - { - path: 'btn', - name: 'BackAuthBtn', - component: () => import('/@/views/demo/permission/back/Btn.vue'), - meta: { - title: t('routes.demo.permission.backBtn'), - }, - }, - ], - }, - ], -}; - -export default permission; diff --git a/apps/admin/src/router/routes/modules/demo/setup.ts b/apps/admin/src/router/routes/modules/demo/setup.ts deleted file mode 100644 index cec2e29..0000000 --- a/apps/admin/src/router/routes/modules/demo/setup.ts +++ /dev/null @@ -1,31 +0,0 @@ -import type { AppRouteModule } from '/@/router/types'; - -import { LAYOUT } from '/@/router/constant'; -import { t } from '/@/hooks/web/useI18n'; - -const setup: AppRouteModule = { - path: '/setup', - name: 'SetupDemo', - component: LAYOUT, - redirect: '/setup/index', - meta: { - orderNo: 90000, - hideChildrenInMenu: true, - icon: 'whh:paintroll', - title: t('routes.demo.setup.page'), - }, - children: [ - { - path: 'index', - name: 'SetupDemoPage', - component: () => import('/@/views/demo/setup/index.vue'), - meta: { - title: t('routes.demo.setup.page'), - icon: 'whh:paintroll', - hideMenu: true, - }, - }, - ], -}; - -export default setup; diff --git a/apps/admin/src/router/routes/modules/demo/system.ts b/apps/admin/src/router/routes/modules/demo/system.ts deleted file mode 100644 index 66e19da..0000000 --- a/apps/admin/src/router/routes/modules/demo/system.ts +++ /dev/null @@ -1,78 +0,0 @@ -import type { AppRouteModule } from '/@/router/types'; - -import { LAYOUT } from '/@/router/constant'; -import { t } from '/@/hooks/web/useI18n'; - -const system: AppRouteModule = { - path: '/system', - name: 'System', - component: LAYOUT, - redirect: '/system/account', - meta: { - orderNo: 2000, - icon: 'ion:settings-outline', - title: t('routes.demo.system.moduleName'), - }, - children: [ - { - path: 'account', - name: 'AccountManagement', - meta: { - title: t('routes.demo.system.account'), - ignoreKeepAlive: false, - }, - component: () => import('/@/views/demo/system/account/index.vue'), - }, - { - path: 'account_detail/:id', - name: 'AccountDetail', - meta: { - hideMenu: true, - title: t('routes.demo.system.account_detail'), - ignoreKeepAlive: true, - showMenu: false, - currentActiveMenu: '/system/account', - }, - component: () => import('/@/views/demo/system/account/AccountDetail.vue'), - }, - { - path: 'role', - name: 'RoleManagement', - meta: { - title: t('routes.demo.system.role'), - ignoreKeepAlive: true, - }, - component: () => import('/@/views/demo/system/role/index.vue'), - }, - - { - path: 'menu', - name: 'MenuManagement', - meta: { - title: t('routes.demo.system.menu'), - ignoreKeepAlive: true, - }, - component: () => import('/@/views/demo/system/menu/index.vue'), - }, - { - path: 'dept', - name: 'DeptManagement', - meta: { - title: t('routes.demo.system.dept'), - ignoreKeepAlive: true, - }, - component: () => import('/@/views/demo/system/dept/index.vue'), - }, - { - path: 'changePassword', - name: 'ChangePassword', - meta: { - title: t('routes.demo.system.password'), - ignoreKeepAlive: true, - }, - component: () => import('/@/views/demo/system/password/index.vue'), - }, - ], -}; - -export default system; diff --git a/apps/admin/src/router/types.ts b/apps/admin/src/router/types.ts index 082d208..65febaf 100644 --- a/apps/admin/src/router/types.ts +++ b/apps/admin/src/router/types.ts @@ -29,6 +29,8 @@ export interface Menu { icon?: string; + img?: string; + path: string; // path contains param, auto assignment. diff --git a/apps/admin/src/settings/projectSetting.ts b/apps/admin/src/settings/projectSetting.ts index 860c669..242fba6 100644 --- a/apps/admin/src/settings/projectSetting.ts +++ b/apps/admin/src/settings/projectSetting.ts @@ -74,6 +74,7 @@ const setting: ProjectConfig = { showNotice: true, // Whether to display the menu search showSearch: true, + showApi: false, }, // Menu configuration diff --git a/apps/admin/src/store/index.ts b/apps/admin/src/store/index.ts index efaf6c9..9ceca5a 100644 --- a/apps/admin/src/store/index.ts +++ b/apps/admin/src/store/index.ts @@ -1,7 +1,9 @@ import type { App } from 'vue'; import { createPinia } from 'pinia'; +import { registerPiniaPersistPlugin } from '@/store/plugin/persist'; const store = createPinia(); +registerPiniaPersistPlugin(store); export function setupStore(app: App) { app.use(store); diff --git a/apps/admin/src/store/modules/app.ts b/apps/admin/src/store/modules/app.ts index 39563b6..7dfc6ed 100644 --- a/apps/admin/src/store/modules/app.ts +++ b/apps/admin/src/store/modules/app.ts @@ -5,13 +5,13 @@ import type { TransitionSetting, MultiTabsSetting, } from '/#/config'; -import type { BeforeMiniState } from '/#/store'; +import type { BeforeMiniState, ApiAddress } from '/#/store'; import { defineStore } from 'pinia'; import { store } from '/@/store'; import { ThemeEnum } from '/@/enums/appEnum'; -import { APP_DARK_MODE_KEY_, PROJ_CFG_KEY } from '/@/enums/cacheEnum'; +import { APP_DARK_MODE_KEY, PROJ_CFG_KEY, API_ADDRESS } from '/@/enums/cacheEnum'; import { Persistent } from '/@/utils/cache/persistent'; import { darkMode } from '/@/settings/designSetting'; import { resetRouter } from '/@/router'; @@ -40,7 +40,7 @@ export const useAppStore = defineStore({ return state.pageLoading; }, getDarkMode(state): 'light' | 'dark' | string { - return state.darkMode || localStorage.getItem(APP_DARK_MODE_KEY_) || darkMode; + return state.darkMode || localStorage.getItem(APP_DARK_MODE_KEY) || darkMode; }, getBeforeMiniInfo(state): BeforeMiniState { @@ -63,6 +63,9 @@ export const useAppStore = defineStore({ getMultiTabsSetting(): MultiTabsSetting { return this.getProjectConfig.multiTabsSetting; }, + getApiAddress() { + return JSON.parse(localStorage.getItem(API_ADDRESS) || '{}'); + }, }, actions: { setPageLoading(loading: boolean): void { @@ -71,7 +74,7 @@ export const useAppStore = defineStore({ setDarkMode(mode: ThemeEnum): void { this.darkMode = mode; - localStorage.setItem(APP_DARK_MODE_KEY_, mode); + localStorage.setItem(APP_DARK_MODE_KEY, mode); }, setBeforeMiniInfo(state: BeforeMiniState): void { @@ -79,7 +82,11 @@ export const useAppStore = defineStore({ }, setProjectConfig(config: DeepPartial): void { - this.projectConfig = deepMerge(this.projectConfig || {}, config); + this.projectConfig = deepMerge(this.projectConfig || {}, config) as ProjectConfig; + Persistent.setLocal(PROJ_CFG_KEY, this.projectConfig); + }, + setMenuSetting(setting: Partial): void { + this.projectConfig!.menuSetting = deepMerge(this.projectConfig!.menuSetting, setting); Persistent.setLocal(PROJ_CFG_KEY, this.projectConfig); }, @@ -99,6 +106,9 @@ export const useAppStore = defineStore({ clearTimeout(timeId); } }, + setApiAddress(config: ApiAddress): void { + localStorage.setItem(API_ADDRESS, JSON.stringify(config)); + }, }, }); diff --git a/apps/admin/src/store/modules/multipleTab.ts b/apps/admin/src/store/modules/multipleTab.ts index f742c2f..e67c423 100644 --- a/apps/admin/src/store/modules/multipleTab.ts +++ b/apps/admin/src/store/modules/multipleTab.ts @@ -23,7 +23,7 @@ export interface MultipleTabState { function handleGotoPage(router: Router) { const go = useGo(router); - go(unref(router.currentRoute).path, true); + go(unref(router.currentRoute).fullPath, true); } const getToTarget = (tabItem: RouteLocationNormalized) => { @@ -308,7 +308,7 @@ export const useMultipleTabStore = defineStore({ for (const path of closePathList) { if (path !== route.fullPath) { - const closeItem = this.tabList.find((item) => item.path === path); + const closeItem = this.tabList.find((item) => item.fullPath === path); if (!closeItem) { continue; } @@ -320,6 +320,7 @@ export const useMultipleTabStore = defineStore({ } this.bulkCloseTabs(pathList); this.updateCacheTab(); + Persistent.setLocal(MULTIPLE_TABS_KEY, this.tabList, true); handleGotoPage(router); }, diff --git a/apps/admin/src/store/modules/user.ts b/apps/admin/src/store/modules/user.ts index afd976d..cd8e7f5 100644 --- a/apps/admin/src/store/modules/user.ts +++ b/apps/admin/src/store/modules/user.ts @@ -15,7 +15,6 @@ import { RouteRecordRaw } from 'vue-router'; import { PAGE_NOT_FOUND_ROUTE } from '/@/router/routes/basic'; import { isArray } from '/@/utils/is'; import { h } from 'vue'; -import { useWsStore } from './ws'; interface UserState { userInfo: Nullable; @@ -110,6 +109,7 @@ export const useUserStore = defineStore({ this.setSessionTimeout(false); } else { const permissionStore = usePermissionStore(); + if (!permissionStore.isDynamicAddedRoute) { const routes = await permissionStore.buildRoutesAction(); routes.forEach((route) => { @@ -134,11 +134,6 @@ export const useUserStore = defineStore({ this.setRoleList([]); } this.setUserInfo(userInfo); - if (import.meta.env.PROD) { - const wsStore = useWsStore(); - !wsStore.client && wsStore.initSocket(); - } - return userInfo; }, /** @@ -152,8 +147,6 @@ export const useUserStore = defineStore({ console.log('注销Token失败'); } } - const wsStore = useWsStore(); - wsStore.closeSocket(); this.setToken(undefined); this.setSessionTimeout(false); this.setUserInfo(null); diff --git a/apps/admin/src/store/modules/ws.ts b/apps/admin/src/store/modules/ws.ts deleted file mode 100644 index 96b8364..0000000 --- a/apps/admin/src/store/modules/ws.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { defineStore } from 'pinia'; -import { Modal } from 'ant-design-vue'; -import type { SocketIOWrapperType, SocketStatusType } from '/@/core/socket/socket-io'; -import { router } from '/@/router'; -import { store } from '/@/store'; -import { EVENT_KICK, EVENT_UPDATE_MENU } from '/@/core/socket/event-type'; -import { SocketIOWrapper, SocketStatus } from '/@/core/socket/socket-io'; -import { useUserStore } from '/@/store/modules/user'; -import { useTabs } from '/@/hooks/web/useTabs'; - -interface WsState { - client: SocketIOWrapperType | null; - status: SocketStatusType; -} - -export const useWsStore = defineStore({ - id: 'ws', - state: (): WsState => ({ - // socket wrapper 实例 - client: null, - // socket 连接状态 - status: SocketStatus.CLOSE, - }), - actions: { - setClient(client: SocketIOWrapperType | null) { - this.client = client as any; - }, - setStatus(status: SocketStatusType) { - if (this.status === status) { - return; - } - this.status = status; - }, - // 初始化Socket - initSocket() { - // check is init - if (this.client?.isConnected?.()) { - return; - } - const ws = new SocketIOWrapper(); - ws.subscribe(EVENT_KICK, async (data) => { - const userStore = useUserStore(); - // reset token - userStore.resetState(); - Modal.warning({ - title: '警告', - content: `您已被管理员${data.operater}踢下线!`, - centered: true, - okText: '重新登录', - onOk() { - // 刷新页面 - window.location.reload(); - }, - }); - }); - ws.subscribe(EVENT_UPDATE_MENU, async () => { - const userStore = useUserStore(); - const { close } = useTabs(); - console.log('EVENT_UPDATE_MENU', EVENT_UPDATE_MENU); - - await userStore.afterLoginAction(); - const currentRoute = router.currentRoute.value!; - const hasRoute = router.hasRoute(currentRoute.name!); - if (Object.is(hasRoute, false)) { - Modal.warning({ - title: '提示', - content: `您的权限已被管理员修改,暂无当前页面预览权限!`, - centered: true, - okText: '关闭当前页', - onOk() { - close(currentRoute); - }, - }); - } - }); - this.setClient(ws); - }, - - // 关闭Socket连接 - closeSocket() { - this.client?.close?.(); - this.setClient(null); - }, - }, -}); - -// 在组件setup函数外使用 -export function useWsStoreWithOut() { - return useWsStore(store); -} diff --git a/apps/admin/src/store/plugin/persist.ts b/apps/admin/src/store/plugin/persist.ts new file mode 100644 index 0000000..4fa176e --- /dev/null +++ b/apps/admin/src/store/plugin/persist.ts @@ -0,0 +1,38 @@ +/** + * Pinia Persist Plugin + * Pinia 持久化插件 + * @link https://prazdevs.github.io/pinia-plugin-persistedstate/zh/guide/ + * + */ +import type { Pinia } from 'pinia'; +import { createPersistedState } from 'pinia-plugin-persistedstate'; +import type { PersistedStateFactoryOptions } from 'pinia-plugin-persistedstate'; +import { getCommonStoragePrefix } from '@/utils/env'; + +export const PERSIST_KEY_PREFIX = getCommonStoragePrefix(); + +// TODO customSerializer + +/** + * Register Pinia Persist Plugin + * 注册 Pinia 持久化插件 + * + * @param pinia Pinia instance Pinia 实例 + */ +export function registerPiniaPersistPlugin(pinia: Pinia) { + pinia.use(createPersistedState(createPersistedStateOptions(PERSIST_KEY_PREFIX))); +} + +/** + * Create Persisted State Options + * 创建持久化状态选项 + * + * @param keyPrefix prefix for storage key 储存键前缀 + * @returns persisted state factory options + */ +export function createPersistedStateOptions(keyPrefix: string): PersistedStateFactoryOptions { + return { + storage: localStorage, + key: (id) => `${keyPrefix}__${id}`, + }; +} diff --git a/apps/admin/src/utils/__test__/index.test.ts b/apps/admin/src/utils/__test__/index.test.ts new file mode 100644 index 0000000..bc6995e --- /dev/null +++ b/apps/admin/src/utils/__test__/index.test.ts @@ -0,0 +1,145 @@ +// 暂时未安装依赖,无法测试 +// @ts-ignore +import { describe, expect, test } from 'vitest'; +import { deepMerge } from '@/utils'; + +describe('deepMerge function', () => { + test('should correctly merge basic data types', () => { + const source = { a: 1, b: 2, c: null }; + const target = { + a: 2, + b: undefined, + c: 3, + }; + const expected = { + a: 2, + b: 2, + c: 3, + }; + expect(deepMerge(source, target)).toStrictEqual(expected); + }); + + test('should return the same date if only 1 is passed', () => { + const foo = new Date(); + const merged = deepMerge(foo, null); + const merged2 = deepMerge(undefined, foo); + expect(merged).toStrictEqual(foo); + expect(merged2).toStrictEqual(foo); + expect(merged).toStrictEqual(merged2); + }); + + test('should merge two objects recursively', () => { + const source = { + a: { b: { c: 1 }, d: [1, 2] }, + e: [1, 2], + foo: { bar: 3 }, + array: [ + { + does: 'work', + too: [1, 2, 3], + }, + ], + r: { a: 1 }, + }; + const target = { + a: { b: { d: [3] } }, + e: [3], + foo: { baz: 4 }, + qu: 5, + array: [ + { + does: 'work', + too: [4, 5, 6], + }, + { + really: 'yes', + }, + ], + r: { a: 2 }, + }; + const expected = { + a: { b: { c: 1, d: [3] }, d: [1, 2] }, + e: [3], + foo: { + bar: 3, + baz: 4, + }, + array: [ + { + does: 'work', + too: [4, 5, 6], + }, + { + really: 'yes', + }, + ], + qu: 5, + r: { a: 2 }, + }; + expect(deepMerge(source, target)).toStrictEqual(expected); + }); + + test('should replace arrays by default', () => { + const source = { + a: { b: { d: [1, 2] } }, + e: [1, 2], + }; + const target = { + a: { b: { d: [3] } }, + e: [3], + }; + const expected = { + a: { b: { d: [3] } }, + e: [3], + }; + expect(deepMerge(source, target)).toStrictEqual(expected); + }); + + test("should union arrays using mergeArrays = 'union'", () => { + const source = { + a: { b: { d: [1, 2] } }, + e: [1, 2], + }; + const target = { + a: { b: { d: [2, 3] } }, + e: [1, 3], + }; + const expected = { + a: { b: { d: [1, 2, 3] } }, + e: [1, 2, 3], + }; + expect(deepMerge(source, target, 'union')).toStrictEqual(expected); + }); + + test("should intersect arrays using mergeArrays = 'intersection'", () => { + const source = { + a: { b: { d: [1, 2] } }, + e: [1, 2], + }; + const target = { + a: { b: { d: [2, 3] } }, + e: [3], + }; + const expected = { + a: { b: { d: [2] } }, + e: [], + }; + expect(deepMerge(source, target, 'intersection')).toStrictEqual(expected); + }); + + test("should concatenate arrays using mergeArrays = 'concat'", () => { + const source = { + a: { b: { d: [1, 2] } }, + e: [1, 2], + }; + const target = { + a: { b: { d: [2, 3] } }, + e: [3], + }; + const expected = { + a: { b: { d: [1, 2, 2, 3] } }, + e: [1, 2, 3], + }; + expect(deepMerge(source, target, 'concat')).toStrictEqual(expected); + }); +}); diff --git a/apps/admin/src/utils/bem.ts b/apps/admin/src/utils/bem.ts index 7dcadbc..53fb054 100644 --- a/apps/admin/src/utils/bem.ts +++ b/apps/admin/src/utils/bem.ts @@ -14,8 +14,9 @@ function genBem(name: string, mods?: Mods): string { return ` ${name}--${mods}`; } + // ArrayConstructor.isArray(arg: any): arg is any[] if (Array.isArray(mods)) { - return mods.reduce((ret, item) => ret + genBem(name, item), ''); + return (mods as Mod[]).reduce((ret, item) => ret + genBem(name, item), ''); } return Object.keys(mods).reduce((ret, key) => ret + (mods[key] ? genBem(name, key) : ''), ''); diff --git a/apps/admin/src/utils/cache/storageCache.ts b/apps/admin/src/utils/cache/storageCache.ts index 84ba2aa..6e1d4e5 100644 --- a/apps/admin/src/utils/cache/storageCache.ts +++ b/apps/admin/src/utils/cache/storageCache.ts @@ -1,6 +1,6 @@ import { cacheCipher } from '/@/settings/encryptionSetting'; -import type { EncryptionParams } from '/@/utils/cipher'; -import { AesEncryption } from '/@/utils/cipher'; +import type { EncryptionParams } from '/@/utils/cipherOld'; +import { AesEncryption } from '/@/utils/cipherOld'; import { isNullOrUnDef } from '/@/utils/is'; export interface CreateStorageParams extends EncryptionParams { diff --git a/apps/admin/src/utils/cipher.ts b/apps/admin/src/utils/cipher.ts index 7a02cfc..cbc2242 100644 --- a/apps/admin/src/utils/cipher.ts +++ b/apps/admin/src/utils/cipher.ts @@ -1,54 +1,159 @@ -import { encrypt, decrypt } from 'crypto-js/aes'; +import { decrypt as aesDecrypt, encrypt as aesEncrypt } from 'crypto-js/aes'; import UTF8, { parse } from 'crypto-js/enc-utf8'; import pkcs7 from 'crypto-js/pad-pkcs7'; -import ECB from 'crypto-js/mode-ecb'; -import md5 from 'crypto-js/md5'; +import CTR from 'crypto-js/mode-ctr'; import Base64 from 'crypto-js/enc-base64'; +import MD5 from 'crypto-js/md5'; +import SHA256 from 'crypto-js/sha256'; +import SHA512 from 'crypto-js/sha512'; + +// Define an interface for encryption +// 定义一个加密器的接口 +export interface Encryption { + encrypt(plainText: string): string; + decrypt(cipherText: string): string; +} +// Define an interface for Hashing +// 定义一个哈希算法的接口 +export interface Hashing { + hash(data: string): string; +} export interface EncryptionParams { key: string; iv: string; } -export class AesEncryption { - private key; - private iv; +class AesEncryption implements Encryption { + private readonly key; + private readonly iv; - constructor(opt: Partial = {}) { - const { key, iv } = opt; - if (key) { - this.key = parse(key); - } - if (iv) { - this.iv = parse(iv); - } + constructor({ key, iv }: EncryptionParams) { + this.key = parse(key); + this.iv = parse(iv); } get getOptions() { return { - mode: ECB, + mode: CTR, padding: pkcs7, iv: this.iv, }; } - encryptByAES(cipherText: string) { - return encrypt(cipherText, this.key, this.getOptions).toString(); + encrypt(plainText: string) { + return aesEncrypt(plainText, this.key, this.getOptions).toString(); } - decryptByAES(cipherText: string) { - return decrypt(cipherText, this.key, this.getOptions).toString(UTF8); + decrypt(cipherText: string) { + return aesDecrypt(cipherText, this.key, this.getOptions).toString(UTF8); } } -export function encryptByBase64(cipherText: string) { - return UTF8.parse(cipherText).toString(Base64); +// Define a singleton class for Base64 encryption +class Base64Encryption implements Encryption { + private static instance: Base64Encryption; + + private constructor() {} + + // Get the singleton instance + // 获取单例实例 + public static getInstance(): Base64Encryption { + if (!Base64Encryption.instance) { + Base64Encryption.instance = new Base64Encryption(); + } + return Base64Encryption.instance; + } + + encrypt(plainText: string) { + return UTF8.parse(plainText).toString(Base64); + } + + decrypt(cipherText: string) { + return Base64.parse(cipherText).toString(UTF8); + } } -export function decodeByBase64(cipherText: string) { - return Base64.parse(cipherText).toString(UTF8); +// Define a singleton class for MD5 Hashing +class MD5Hashing implements Hashing { + private static instance: MD5Hashing; + + private constructor() {} + + // Get the singleton instance + // 获取单例实例 + public static getInstance(): MD5Hashing { + if (!MD5Hashing.instance) { + MD5Hashing.instance = new MD5Hashing(); + } + return MD5Hashing.instance; + } + + hash(plainText: string) { + return MD5(plainText).toString(); + } } -export function encryptByMd5(password: string) { - return md5(password).toString(); +// Define a singleton class for SHA256 Hashing +class SHA256Hashing implements Hashing { + private static instance: SHA256Hashing; + + private constructor() {} + + // Get the singleton instance + // 获取单例实例 + public static getInstance(): SHA256Hashing { + if (!SHA256Hashing.instance) { + SHA256Hashing.instance = new SHA256Hashing(); + } + return SHA256Hashing.instance; + } + + hash(plainText: string) { + return SHA256(plainText).toString(); + } +} + +// Define a singleton class for SHA512 Hashing +class SHA512Hashing implements Hashing { + private static instance: SHA512Hashing; + + private constructor() {} + + // Get the singleton instance + // 获取单例实例 + public static getInstance(): SHA256Hashing { + if (!SHA512Hashing.instance) { + SHA512Hashing.instance = new SHA512Hashing(); + } + return SHA512Hashing.instance; + } + + hash(plainText: string) { + return SHA512(plainText).toString(); + } +} + +export class EncryptionFactory { + public static createAesEncryption(params: EncryptionParams): Encryption { + return new AesEncryption(params); + } + + public static createBase64Encryption(): Encryption { + return Base64Encryption.getInstance(); + } +} + +export class HashingFactory { + public static createMD5Hashing(): Hashing { + return MD5Hashing.getInstance(); + } + + public static createSHA256Hashing(): Hashing { + return SHA256Hashing.getInstance(); + } + + public static createSHA512Hashing(): Hashing { + return SHA512Hashing.getInstance(); + } } diff --git a/apps/admin/src/utils/cipherOld.ts b/apps/admin/src/utils/cipherOld.ts new file mode 100644 index 0000000..7a02cfc --- /dev/null +++ b/apps/admin/src/utils/cipherOld.ts @@ -0,0 +1,54 @@ +import { encrypt, decrypt } from 'crypto-js/aes'; +import UTF8, { parse } from 'crypto-js/enc-utf8'; +import pkcs7 from 'crypto-js/pad-pkcs7'; +import ECB from 'crypto-js/mode-ecb'; +import md5 from 'crypto-js/md5'; +import Base64 from 'crypto-js/enc-base64'; + +export interface EncryptionParams { + key: string; + iv: string; +} + +export class AesEncryption { + private key; + private iv; + + constructor(opt: Partial = {}) { + const { key, iv } = opt; + if (key) { + this.key = parse(key); + } + if (iv) { + this.iv = parse(iv); + } + } + + get getOptions() { + return { + mode: ECB, + padding: pkcs7, + iv: this.iv, + }; + } + + encryptByAES(cipherText: string) { + return encrypt(cipherText, this.key, this.getOptions).toString(); + } + + decryptByAES(cipherText: string) { + return decrypt(cipherText, this.key, this.getOptions).toString(UTF8); + } +} + +export function encryptByBase64(cipherText: string) { + return UTF8.parse(cipherText).toString(Base64); +} + +export function decodeByBase64(cipherText: string) { + return Base64.parse(cipherText).toString(UTF8); +} + +export function encryptByMd5(password: string) { + return md5(password).toString(); +} diff --git a/apps/admin/src/utils/copyTextToClipboard.ts b/apps/admin/src/utils/copyTextToClipboard.ts new file mode 100644 index 0000000..74fc795 --- /dev/null +++ b/apps/admin/src/utils/copyTextToClipboard.ts @@ -0,0 +1,12 @@ +import { message } from 'ant-design-vue'; + +export function copyText(text: string, prompt: string | null = '已成功复制到剪切板!') { + navigator.clipboard.writeText(text).then( + function () { + prompt && message.success(prompt); + }, + function (error: Error) { + message.error('复制失败!' + error.message); + }, + ); +} diff --git a/apps/admin/src/utils/domUtils.ts b/apps/admin/src/utils/domUtils.ts index 7efe9cb..bc80613 100644 --- a/apps/admin/src/utils/domUtils.ts +++ b/apps/admin/src/utils/domUtils.ts @@ -158,7 +158,7 @@ export function off( export function once(el: HTMLElement, event: string, fn: EventListener): void { const listener = function (this: any, ...args: unknown[]) { if (fn) { - fn.apply(this, args); + fn.apply(this, args as [evt: Event]); } off(el, event, listener); }; diff --git a/apps/admin/src/utils/env.ts b/apps/admin/src/utils/env.ts index 3a51ad1..19f455a 100644 --- a/apps/admin/src/utils/env.ts +++ b/apps/admin/src/utils/env.ts @@ -1,11 +1,6 @@ import type { GlobEnvConfig } from '/#/config'; import pkg from '../../package.json'; - -const getVariableName = (title: string) => { - return `__PRODUCTION__${title.replace(/\s/g, '_') || '__APP'}__CONF__` - .toUpperCase() - .replace(/\s/g, ''); -}; +import { API_ADDRESS } from '/@/enums/cacheEnum'; export function getCommonStoragePrefix() { const { VITE_GLOB_APP_TITLE } = getAppEnvConfig(); @@ -17,17 +12,30 @@ export function getStorageShortName() { return `${getCommonStoragePrefix()}${`__${pkg.version}`}__`.toUpperCase(); } +const getVariableName = (title: string) => { + function strToHex(str: string) { + const result: string[] = []; + for (let i = 0; i < str.length; ++i) { + const hex = str.charCodeAt(i).toString(16); + result.push(('000' + hex).slice(-4)); + } + return result.join('').toUpperCase(); + } + return `__PRODUCTION__${strToHex(title) || '__APP'}__CONF__`.toUpperCase().replace(/\s/g, ''); +}; + export function getAppEnvConfig() { const ENV_NAME = getVariableName(import.meta.env.VITE_GLOB_APP_TITLE); - - const ENV = (import.meta.env.DEV + const ENV = import.meta.env.DEV ? // Get the global configuration (the configuration will be extracted independently when packaging) (import.meta.env as unknown as GlobEnvConfig) - : window[ENV_NAME as any]) as unknown as GlobEnvConfig; - - const { VITE_GLOB_APP_TITLE, VITE_GLOB_API_URL, VITE_GLOB_API_URL_PREFIX, VITE_GLOB_UPLOAD_URL } = - ENV; - + : (window[ENV_NAME] as unknown as GlobEnvConfig); + const { VITE_GLOB_APP_TITLE, VITE_GLOB_API_URL_PREFIX, VITE_GLOB_UPLOAD_URL } = ENV; + let { VITE_GLOB_API_URL } = ENV; + if (localStorage.getItem(API_ADDRESS)) { + const address = JSON.parse(localStorage.getItem(API_ADDRESS) || '{}'); + if (address?.key) VITE_GLOB_API_URL = address?.val; + } return { VITE_GLOB_APP_TITLE, VITE_GLOB_API_URL, diff --git a/apps/admin/src/utils/factory/createAsyncComponent.tsx b/apps/admin/src/utils/factory/createAsyncComponent.tsx index fc5e2a6..712e56c 100644 --- a/apps/admin/src/utils/factory/createAsyncComponent.tsx +++ b/apps/admin/src/utils/factory/createAsyncComponent.tsx @@ -1,4 +1,7 @@ import { + AsyncComponentLoader, + Component, + ComponentPublicInstance, defineAsyncComponent, // FunctionalComponent, CSSProperties } from 'vue'; @@ -27,7 +30,11 @@ interface Options { retry?: boolean; } -export function createAsyncComponent(loader: Fn, options: Options = {}) { +export function createAsyncComponent< + T extends Component = { + new (): ComponentPublicInstance; + }, +>(loader: AsyncComponentLoader, options: Options = {}) { const { size = 'small', delay = 100, timeout = 30000, loading = false, retry = true } = options; return defineAsyncComponent({ loader, diff --git a/apps/admin/src/utils/helper/tsxHelper.tsx b/apps/admin/src/utils/helper/tsxHelper.tsx index a75327a..3de2365 100644 --- a/apps/admin/src/utils/helper/tsxHelper.tsx +++ b/apps/admin/src/utils/helper/tsxHelper.tsx @@ -1,10 +1,11 @@ import { Slots } from 'vue'; import { isFunction } from '/@/utils/is'; +import { RenderOpts } from '/@/components/Form'; /** * @description: Get slot to prevent empty error */ -export function getSlot(slots: Slots, slot = 'default', data?: any) { +export function getSlot(slots: Slots, slot = 'default', data?: any, opts?: RenderOpts) { if (!slots || !Reflect.has(slots, slot)) { return null; } @@ -14,7 +15,8 @@ export function getSlot(slots: Slots, slot = 'default', data?: any) { } const slotFn = slots[slot]; if (!slotFn) return null; - return slotFn(data); + const params = { ...data, ...opts }; + return slotFn(params); } /** diff --git a/apps/admin/src/utils/http/axios/Axios.ts b/apps/admin/src/utils/http/axios/Axios.ts index 31808eb..b215be9 100644 --- a/apps/admin/src/utils/http/axios/Axios.ts +++ b/apps/admin/src/utils/http/axios/Axios.ts @@ -89,7 +89,8 @@ export class VAxios { // Request interceptor configuration processing this.axiosInstance.interceptors.request.use((config: InternalAxiosRequestConfig) => { // If cancel repeat request is turned on, then cancel repeat request is prohibited - const { requestOptions } = this.options; + const requestOptions = + (config as unknown as any).requestOptions ?? this.options.requestOptions; const ignoreCancelToken = requestOptions?.ignoreCancelToken ?? true; !ignoreCancelToken && axiosCanceler.addPending(config); @@ -192,10 +193,6 @@ export class VAxios { return this.request({ ...config, method: 'PUT' }, options); } - patch(config: AxiosRequestConfig, options?: RequestOptions): Promise { - return this.request({ ...config, method: 'PATCH' }, options); - } - delete(config: AxiosRequestConfig, options?: RequestOptions): Promise { return this.request({ ...config, method: 'DELETE' }, options); } @@ -207,6 +204,10 @@ export class VAxios { conf.cancelToken = config.cancelToken; } + if (config.signal) { + conf.signal = config.signal; + } + const transform = this.getTransform(); const { requestOptions } = this.options; diff --git a/apps/admin/src/utils/http/axios/axiosTransform.ts b/apps/admin/src/utils/http/axios/axiosTransform.ts index b0cc0af..a997438 100644 --- a/apps/admin/src/utils/http/axios/axiosTransform.ts +++ b/apps/admin/src/utils/http/axios/axiosTransform.ts @@ -5,7 +5,7 @@ import type { AxiosInstance, AxiosRequestConfig, AxiosResponse, - InternalAxiosRequestConfig + InternalAxiosRequestConfig, } from 'axios'; import type { RequestOptions, Result } from '/#/axios'; diff --git a/apps/admin/src/utils/http/axios/checkStatus.ts b/apps/admin/src/utils/http/axios/checkStatus.ts index dee552b..3e47517 100644 --- a/apps/admin/src/utils/http/axios/checkStatus.ts +++ b/apps/admin/src/utils/http/axios/checkStatus.ts @@ -19,6 +19,7 @@ export function checkStatus( const { t } = useI18n(); const userStore = useUserStoreWithOut(); let errMessage = ''; + switch (status) { case 400: case 422: diff --git a/apps/admin/src/utils/http/axios/index.ts b/apps/admin/src/utils/http/axios/index.ts index 8bb8695..abc8189 100644 --- a/apps/admin/src/utils/http/axios/index.ts +++ b/apps/admin/src/utils/http/axios/index.ts @@ -1,7 +1,7 @@ // axios配置 可自行根据项目进行更改,只需更改该文件即可,其他文件可以不动 // The axios configuration can be changed according to the project, just change the file, other files can be left unchanged -import type { AxiosResponse } from 'axios'; +import type { AxiosInstance, AxiosResponse } from 'axios'; import { clone } from 'lodash-es'; import type { RequestOptions, Result } from '/#/axios'; import type { AxiosTransform, CreateAxiosOptions } from './axiosTransform'; @@ -77,7 +77,6 @@ const transform: AxiosTransform = { case ResultEnum.TIMEOUT: timeoutMsg = t('sys.api.timeoutMessage'); const userStore = useUserStoreWithOut(); - userStore.setToken(undefined); userStore.logout(true); break; default: @@ -175,7 +174,7 @@ const transform: AxiosTransform = { /** * @description: 响应错误处理 */ - responseInterceptorsCatch: (axiosInstance: AxiosResponse, error: any) => { + responseInterceptorsCatch: (axiosInstance: AxiosInstance, error: any) => { const { t } = useI18n(); const errorLogStore = useErrorLogStoreWithOut(); errorLogStore.addAjaxErrorInfo(error); diff --git a/apps/admin/src/utils/index.ts b/apps/admin/src/utils/index.ts index 945ed08..c557300 100644 --- a/apps/admin/src/utils/index.ts +++ b/apps/admin/src/utils/index.ts @@ -1,9 +1,9 @@ import type { RouteLocationNormalized, RouteRecordNormalized } from 'vue-router'; import type { App, Component } from 'vue'; +import { intersectionWith, isEqual, mergeWith, unionWith } from 'lodash-es'; import { unref } from 'vue'; import { isArray, isObject } from '/@/utils/is'; -import { cloneDeep, isEqual, mergeWith, unionWith } from 'lodash-es'; export const noop = () => {}; @@ -34,24 +34,49 @@ export function setObjToUrlParams(baseUrl: string, obj: any): string { } /** - - 递归合并两个对象。 - Recursively merge two objects. - @param target 目标对象,合并后结果存放于此。The target object to merge into. - @param source 要合并的源对象。The source object to merge from. - @returns 合并后的对象。The merged object. + * Recursively merge two objects. + * 递归合并两个对象。 + * + * @param source The source object to merge from. 要合并的源对象。 + * @param target The target object to merge into. 目标对象,合并后结果存放于此。 + * @param mergeArrays How to merge arrays. Default is "replace". + * 如何合并数组。默认为replace。 + * - "union": Union the arrays. 对数组执行并集操作。 + * - "intersection": Intersect the arrays. 对数组执行交集操作。 + * - "concat": Concatenate the arrays. 连接数组。 + * - "replace": Replace the source array with the target array. 用目标数组替换源数组。 + * @returns The merged object. 合并后的对象。 */ export function deepMerge( - target: T, - source: U, + source: T, + target: U, + mergeArrays: 'union' | 'intersection' | 'concat' | 'replace' = 'replace', ): T & U { - return mergeWith(cloneDeep(target), source, (objValue, srcValue) => { - if (isObject(objValue) && isObject(srcValue)) { - return mergeWith(cloneDeep(objValue), srcValue, (prevValue, nextValue) => { - // 如果是数组,合并数组(去重) If it is an array, merge the array (remove duplicates) - return isArray(prevValue) ? unionWith(prevValue, nextValue, isEqual) : undefined; - }); + if (!target) { + return source as T & U; + } + if (!source) { + return target as T & U; + } + return mergeWith({}, source, target, (sourceValue, targetValue) => { + if (isArray(targetValue) && isArray(sourceValue)) { + switch (mergeArrays) { + case 'union': + return unionWith(sourceValue, targetValue, isEqual); + case 'intersection': + return intersectionWith(sourceValue, targetValue, isEqual); + case 'concat': + return sourceValue.concat(targetValue); + case 'replace': + return targetValue; + default: + throw new Error(`Unknown merge array strategy: ${mergeArrays as string}`); + } + } + if (isObject(targetValue) && isObject(sourceValue)) { + return deepMerge(sourceValue, targetValue, mergeArrays); } + return undefined; }); } diff --git a/apps/admin/src/utils/is.ts b/apps/admin/src/utils/is.ts index 3a5c4a6..b9cf4b0 100644 --- a/apps/admin/src/utils/is.ts +++ b/apps/admin/src/utils/is.ts @@ -1,3 +1,4 @@ +import { isNil } from 'lodash-es'; const toString = Object.prototype.toString; export function is(val: unknown, type: string) { @@ -16,7 +17,15 @@ export function isObject(val: any): val is Record { return val !== null && is(val, 'Object'); } +export function isNotEmpty(val: any): boolean { + return !isNil(val) && !isEmpty(val); +} + export function isEmpty(val: T): val is T { + if (isNil(val)) { + return true; + } + if (isArray(val) || isString(val)) { return val.length === 0; } @@ -36,6 +45,8 @@ export function isDate(val: unknown): val is Date { return is(val, 'Date'); } + + export function isNull(val: unknown): val is null { return val === null; } diff --git a/apps/admin/src/utils/propTypes.ts b/apps/admin/src/utils/propTypes.ts index 16cf9cd..b4f0623 100644 --- a/apps/admin/src/utils/propTypes.ts +++ b/apps/admin/src/utils/propTypes.ts @@ -20,13 +20,13 @@ const newPropTypes = createTypes({ // 从 vue-types v5.0 开始,extend()方法已经废弃,当前已改为官方推荐的ES6+方法 https://dwightjack.github.io/vue-types/advanced/extending-vue-types.html#the-extend-method class propTypes extends newPropTypes { // a native-like validator that supports the `.validable` method - static get style() { + static override get style() { return toValidableType('style', { type: [String, Object], }); } - static get VNodeChild() { + static override get VNodeChild() { return toValidableType('VNodeChild', { type: undefined, }); diff --git a/apps/admin/src/utils/props.ts b/apps/admin/src/utils/props.ts index 00b364d..8984cfa 100644 --- a/apps/admin/src/utils/props.ts +++ b/apps/admin/src/utils/props.ts @@ -129,7 +129,7 @@ export function buildProp< return { type: - typeof type === 'object' && Object.getOwnPropertySymbols(type).includes(wrapperKey) + typeof type === 'object' && Object.getOwnPropertySymbols(type).includes(wrapperKey) && type ? type[wrapperKey] : type, required: !!required, @@ -175,9 +175,10 @@ export const buildProps = < : never; }; -export const definePropType = (val: any) => ({ [wrapperKey]: val } as PropWrapper); +export const definePropType = (val: any) => ({ [wrapperKey]: val }) as PropWrapper; + +export const keyOf = (arr: T) => Object.keys(arr) as Array; -export const keyOf = (arr: T) => Object.keys(arr) as Array; export const mutable = >(val: T) => val as Mutable; diff --git a/apps/admin/src/utils/types.ts b/apps/admin/src/utils/types.ts index 4453ec4..a853855 100644 --- a/apps/admin/src/utils/types.ts +++ b/apps/admin/src/utils/types.ts @@ -40,3 +40,26 @@ export type ComponentSize = 'large' | 'medium' | 'small' | 'mini'; export type StyleValue = string | CSSProperties | Array; export type Mutable = { -readonly [P in keyof T]: T[P] }; + +type Merge = { + [K in keyof O | keyof T]: K extends keyof T ? T[K] : K extends keyof O ? O[K] : never; +}; + +/** + * T = [ + * { name: string; age: number; }, + * { sex: 'male' | 'female'; age: string } + * ] + * => + * MergeAll = { + * name: string; + * sex: 'male' | 'female'; + * age: string + * } + */ +export type MergeAll = T extends [ + infer F extends object, + ...infer Rest extends object[], +] + ? MergeAll> + : R; diff --git a/apps/admin/types/axios.d.ts b/apps/admin/types/axios.d.ts index 4f6d95c..0ff2f58 100644 --- a/apps/admin/types/axios.d.ts +++ b/apps/admin/types/axios.d.ts @@ -39,7 +39,7 @@ export interface Result { code: number; type: 'success' | 'error' | 'warning'; message: string; - data: T; + result: T; } // multipart/form-data: upload file diff --git a/apps/admin/types/config.d.ts b/apps/admin/types/config.d.ts index 18ef03a..959c55e 100644 --- a/apps/admin/types/config.d.ts +++ b/apps/admin/types/config.d.ts @@ -57,6 +57,7 @@ export interface HeaderSetting { // Show message center button showNotice: boolean; showSearch: boolean; + showApi: boolean; } export interface LocaleSetting { diff --git a/apps/admin/types/global.d.ts b/apps/admin/types/global.d.ts index 07c689c..301c19a 100644 --- a/apps/admin/types/global.d.ts +++ b/apps/admin/types/global.d.ts @@ -22,6 +22,13 @@ declare global { // __APP__: App; // } + // fix FullScreen type error + interface Document { + mozFullScreenElement?: Element; + msFullscreenElement?: Element; + webkitFullscreenElement?: Element; + } + // vue declare type PropType = VuePropType; declare type VueNode = VNodeChild | JSX.Element; diff --git a/apps/admin/types/index.d.ts b/apps/admin/types/index.d.ts index b279c0a..7f67f33 100644 --- a/apps/admin/types/index.d.ts +++ b/apps/admin/types/index.d.ts @@ -14,7 +14,7 @@ declare type LabelValueOptions = { [key: string]: string | number | boolean; }[]; -declare type EmitType = (event: string, ...args: any[]) => void; +declare type EmitType = ReturnType; declare type TargetContext = '_self' | '_blank'; diff --git a/apps/admin/types/store.d.ts b/apps/admin/types/store.d.ts index 36a6025..3c1b910 100644 --- a/apps/admin/types/store.d.ts +++ b/apps/admin/types/store.d.ts @@ -10,6 +10,11 @@ export interface LockInfo { isLock?: boolean; } +export interface ApiAddress { + key: string; + val: string; +} + // Error-log information export interface ErrorLogInfo { // Type of error diff --git a/apps/admin/types/vue-router.d.ts b/apps/admin/types/vue-router.d.ts index 3c9bb9e..310d611 100644 --- a/apps/admin/types/vue-router.d.ts +++ b/apps/admin/types/vue-router.d.ts @@ -21,6 +21,8 @@ declare module 'vue-router' { affix?: boolean; // icon on tab icon?: string; + // img on tab + img?: string; frameSrc?: string; // current page transition transitionName?: string; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e7d4565..cff5265 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -63,8 +63,8 @@ importers: specifier: ^2.2.1 version: 2.2.1 ant-design-vue: - specifier: ^3.2.20 - version: 3.2.20(vue@3.3.7) + specifier: ^4.0.6 + version: 4.0.6(vue@3.3.7) axios: specifier: ^1.6.0 version: 1.6.0 @@ -107,6 +107,9 @@ importers: pinia: specifier: 2.0.33 version: 2.0.33(typescript@5.2.2)(vue@3.3.7) + pinia-plugin-persistedstate: + specifier: ^3.2.0 + version: 3.2.0(pinia@2.0.33) print-js: specifier: ^1.6.0 version: 1.6.0 @@ -822,6 +825,16 @@ packages: '@ant-design/icons-svg': 4.2.1 vue: 3.3.7(typescript@5.2.2) + /@ant-design/icons-vue@7.0.1(vue@3.3.7): + resolution: {integrity: sha512-eCqY2unfZK6Fe02AwFlDHLfoyEFreP6rBwAZMIJ1LugmfMiVgwWDYlp1YsRugaPtICYOabV1iWxXdP12u9U43Q==} + peerDependencies: + vue: '>=3.0.3' + dependencies: + '@ant-design/colors': 6.0.0 + '@ant-design/icons-svg': 4.2.1 + vue: 3.3.7(typescript@5.2.2) + dev: false + /@antfu/install-pkg@0.1.1: resolution: {integrity: sha512-LyB/8+bSfa0DFGC06zpCEfs89/XoWZwws5ygEa5D+Xsm3OfI+aXQ86VgVG7Acyef+rSZ5HE7J8rrxzrQeM3PjQ==} dependencies: @@ -2677,6 +2690,14 @@ packages: resolution: {integrity: sha512-/Z3l6pXthq0JvMYdUFyX9j0MaCltlIn6mfh9jLyQwg5aPKxkyNa0PTHtU1AlFXLNk55ZuAeJRcpvq+tmLfKmaQ==} engines: {node: '>=10'} + /@emotion/hash@0.9.1: + resolution: {integrity: sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==} + dev: false + + /@emotion/unitless@0.8.1: + resolution: {integrity: sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==} + dev: false + /@esbuild/android-arm64@0.17.19: resolution: {integrity: sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==} engines: {node: '>=12'} @@ -6618,19 +6639,22 @@ packages: warning: 4.0.3 dev: true - /ant-design-vue@3.2.20(vue@3.3.7): - resolution: {integrity: sha512-YWpMfGaGoRastIXEYfCoJiaRiDHk4chqtYhlKQM5GqPt6NfvrM1Vg2e60yHtjxlZjed91wCMm0rAmyUr7Hwzdg==} + /ant-design-vue@4.0.6(vue@3.3.7): + resolution: {integrity: sha512-6kh3b8Ito9SAbOKTW0wyfcCnd859uhQQlttjo8RjMj6YjLK52yNO2TdgYRwed06scUm5RwEnQ2JKMxYYoeG1MA==} engines: {node: '>=12.22.0'} peerDependencies: vue: '>=3.2.0' dependencies: '@ant-design/colors': 6.0.0 - '@ant-design/icons-vue': 6.1.0(vue@3.3.7) + '@ant-design/icons-vue': 7.0.1(vue@3.3.7) '@babel/runtime': 7.22.6 '@ctrl/tinycolor': 3.6.0 + '@emotion/hash': 0.9.1 + '@emotion/unitless': 0.8.1 '@simonwep/pickr': 1.8.2 array-tree-filter: 2.1.0 async-validator: 4.2.5 + csstype: 3.1.2 dayjs: 1.11.10 dom-align: 1.12.4 dom-scroll-into-view: 2.0.1 @@ -6639,6 +6663,8 @@ packages: resize-observer-polyfill: 1.5.1 scroll-into-view-if-needed: 2.2.31 shallow-equal: 1.2.1 + stylis: 4.3.0 + throttle-debounce: 5.0.0 vue: 3.3.7(typescript@5.2.2) vue-types: 3.0.2(vue@3.3.7) warning: 4.0.3 @@ -15600,6 +15626,14 @@ packages: requiresBuild: true optional: true + /pinia-plugin-persistedstate@3.2.0(pinia@2.0.33): + resolution: {integrity: sha512-tZbNGf2vjAQcIm7alK40sE51Qu/m9oWr+rEgNm/2AWr1huFxj72CjvpQcIQzMknDBJEkQznCLAGtJTIcLKrKdw==} + peerDependencies: + pinia: ^2.0.0 + dependencies: + pinia: 2.0.33(typescript@5.2.2)(vue@3.3.7) + dev: false + /pinia@2.0.33(typescript@5.2.2)(vue@3.3.7): resolution: {integrity: sha512-HOj1yVV2itw6rNIrR2f7+MirGNxhORjrULL8GWgRwXsGSvEqIQ+SE0MYt6cwtpegzCda3i+rVTZM+AM7CG+kRg==} peerDependencies: @@ -17785,6 +17819,10 @@ packages: - supports-color dev: true + /stylis@4.3.0: + resolution: {integrity: sha512-E87pIogpwUsUwXw7dNyU4QDjdgVMy52m+XEOPEKUn161cCzWjjhPSQhByfd1CcNvrOLnXQ6OnnZDwnJrz/Z4YQ==} + dev: false + /superagent-proxy@3.0.0(superagent@8.0.9): resolution: {integrity: sha512-wAlRInOeDFyd9pyonrkJspdRAxdLrcsZ6aSnS+8+nu4x1aXbz6FWSTT9M6Ibze+eG60szlL7JA8wEIV7bPWuyQ==} engines: {node: '>=6'} @@ -18062,6 +18100,11 @@ packages: resolution: {integrity: sha512-WKexMoJj3vEuK0yFEapj8y64V0A6xcuPuK9Gt1d0R+dzCSJc0lHqQytAbSB4cDAK0dWh4T0E2ETkoLE2WZ41OQ==} dev: false + /throttle-debounce@5.0.0: + resolution: {integrity: sha512-2iQTSgkkc1Zyk0MeVrt/3BvuOXYPl/R8Z0U2xxo9rjwNciaHDG3R+Lm6dh4EeUci49DanvBnuqI6jshoQQRGEg==} + engines: {node: '>=12.22'} + dev: false + /through2@2.0.5: resolution: {integrity: sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==} dependencies: