diff --git a/components.d.ts b/components.d.ts index 795ad47..e405dac 100644 --- a/components.d.ts +++ b/components.d.ts @@ -45,6 +45,7 @@ declare module 'vue' { ASkeleton: typeof import('ant-design-vue/es')['Skeleton'] ASpace: typeof import('ant-design-vue/es')['Space'] ASpin: typeof import('ant-design-vue/es')['Spin'] + ASwitch: typeof import('ant-design-vue/es')['Switch'] ATabPane: typeof import('ant-design-vue/es')['TabPane'] ATabs: typeof import('ant-design-vue/es')['Tabs'] ATag: typeof import('ant-design-vue/es')['Tag'] @@ -64,7 +65,10 @@ declare module 'vue' { Carousel: typeof import('./src/components/MyUI/Carousel/Carousel.vue')['default'] Cascader: typeof import('./src/components/MyUI/Cascader/Cascader.vue')['default'] Checkbox: typeof import('./src/components/MyUI/Checkbox/Checkbox.vue')['default'] + CheckCard: typeof import('./src/components/MyUI/CheckCard/CheckCard.vue')['default'] + CheckOutlined: typeof import('@ant-design/icons-vue')['CheckOutlined'] CloseCircleOutlined: typeof import('@ant-design/icons-vue')['CloseCircleOutlined'] + CloseOutlined: typeof import('@ant-design/icons-vue')['CloseOutlined'] Clouds: typeof import('./src/components/Clouds/Clouds.vue')['default'] Col: typeof import('./src/components/MyUI/Grid/Col.vue')['default'] Collapse: typeof import('./src/components/MyUI/Collapse/Collapse.vue')['default'] @@ -74,9 +78,11 @@ declare module 'vue' { CompareImage: typeof import('./src/views/Upscale/CompareImage.vue')['default'] Countdown: typeof import('./src/components/MyUI/Countdown/Countdown.vue')['default'] DatePicker: typeof import('./src/components/MyUI/DatePicker/DatePicker.vue')['default'] + DeleteOutlined: typeof import('@ant-design/icons-vue')['DeleteOutlined'] Descriptions: typeof import('./src/components/MyUI/Descriptions/Descriptions.vue')['default'] Dialog: typeof import('./src/components/MyUI/Dialog/Dialog.vue')['default'] Divider: typeof import('./src/components/MyUI/Divider/Divider.vue')['default'] + DownloadOutlined: typeof import('@ant-design/icons-vue')['DownloadOutlined'] Drawer: typeof import('./src/components/MyUI/Drawer/Drawer.vue')['default'] DynamicTitle: typeof import('./src/components/DynamicTitle/DynamicTitle.vue')['default'] Ellipsis: typeof import('./src/components/MyUI/Ellipsis/Ellipsis.vue')['default'] @@ -90,9 +96,11 @@ declare module 'vue' { GradientText: typeof import('./src/components/MyUI/GradientText/GradientText.vue')['default'] Image: typeof import('./src/components/MyUI/Image/Image.vue')['default'] ImageShare: typeof import('./src/views/ImageShare/ImageShare.vue')['default'] + ImageWaterfall: typeof import('./src/components/MyUI/Waterfall/ImageWaterfall.vue')['default'] Input: typeof import('./src/components/MyUI/Input/Input.vue')['default'] InputSearch: typeof import('./src/components/MyUI/InputSearch/InputSearch.vue')['default'] LandingPage: typeof import('./src/views/Landing/LandingPage.vue')['default'] + LazyImage: typeof import('./src/components/MyUI/LazyImage/LazyImage.vue')['default'] List: typeof import('./src/components/MyUI/List/List.vue')['default'] LoadingBar: typeof import('./src/components/MyUI/LoadingBar/LoadingBar.vue')['default'] LoadingGraphic: typeof import('./src/components/LoadingGraphic/LoadingGraphic.vue')['default'] @@ -113,6 +121,7 @@ declare module 'vue' { Phoalbum: typeof import('./src/views/Album/Phoalbum/Phoalbum.vue')['default'] PhoneUpload: typeof import('./src/views/PhoneUpload/PhoneUpload.vue')['default'] PlusOutlined: typeof import('@ant-design/icons-vue')['PlusOutlined'] + PlusSquareOutlined: typeof import('@ant-design/icons-vue')['PlusSquareOutlined'] Popconfirm: typeof import('./src/components/MyUI/Popconfirm/Popconfirm.vue')['default'] Popover: typeof import('./src/components/MyUI/Popover/Popover.vue')['default'] Progress: typeof import('./src/components/MyUI/Progress/Progress.vue')['default'] @@ -135,6 +144,7 @@ declare module 'vue' { Segmented: typeof import('./src/components/MyUI/Segmented/Segmented.vue')['default'] Select: typeof import('./src/components/MyUI/Select/Select.vue')['default'] SendOutlined: typeof import('@ant-design/icons-vue')['SendOutlined'] + ShareAltOutlined: typeof import('@ant-design/icons-vue')['ShareAltOutlined'] Skeleton: typeof import('./src/components/MyUI/Skeleton/Skeleton.vue')['default'] Slider: typeof import('./src/components/MyUI/Slider/Slider.vue')['default'] Space: typeof import('./src/components/MyUI/Space/Space.vue')['default'] @@ -162,6 +172,6 @@ declare module 'vue' { Video: typeof import('./src/components/MyUI/Video/Video.vue')['default'] VueCompareImage: typeof import('./src/components/VueCompareImage/VueCompareImage.vue')['default'] WarningOutlined: typeof import('@ant-design/icons-vue')['WarningOutlined'] - Waterfall: typeof import('./src/components/MyUI/Waterfall/Waterfall.vue')['default'] + Waterfall: typeof import('./src/components/MyUI/Waterfall/ImageWaterfall.vue')['default'] } } diff --git a/eslint.config.js b/eslint.config.js index c11ea93..e2568ae 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -5,6 +5,7 @@ import pluginVue from "eslint-plugin-vue"; import {fileURLToPath} from "node:url"; import {dirname, resolve} from "path"; import {readFileSync} from "node:fs"; +import vueI18n from '@intlify/eslint-plugin-vue-i18n'; // 动态读取 .eslintrc-auto-import.json 文件内容 const autoImportConfig = JSON.parse( readFileSync( @@ -14,6 +15,7 @@ const autoImportConfig = JSON.parse( ); export default [ + ...vueI18n.configs['flat/recommended'], {files: ["**/*.{js,mjs,cjs,ts,vue}"]}, {languageOptions: {globals: {...globals.browser, ...globals.node, ...autoImportConfig.globals}}}, pluginJs.configs.recommended, @@ -37,6 +39,26 @@ export default [ "ignoreRestSiblings": true } ], + '@intlify/vue-i18n/no-dynamic-keys': 'error', + '@intlify/vue-i18n/no-unused-keys': [ + 'error', + { + extensions: ['.ts', '.vue'] + } + ], + "@intlify/vue-i18n/no-duplicate-keys-in-locale": [ + "error", + { + "ignoreI18nBlock": false + } + ], + "@intlify/vue-i18n/no-raw-text": 'off', + }, + settings: { + 'vue-i18n': { + localeDir: '/src/locales/language/*.{ts}', + messageSyntaxVersion: '^9.0.0' + } } } ]; diff --git a/package.json b/package.json index aa621a3..1c17045 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "dependencies": { "@alova/adapter-axios": "^2.0.12", "@ant-design/icons-vue": "^7.0.1", + "@intlify/eslint-plugin-vue-i18n": "^3.2.0", "@tensorflow/tfjs": "^4.22.0", "@tensorflow/tfjs-backend-webgl": "^4.22.0", "@tensorflow/tfjs-backend-webgpu": "^4.22.0", @@ -53,8 +54,9 @@ "vite-plugin-node-polyfills": "^0.22.0", "vue": "^3.5.13", "vue-dompurify-html": "^5.2.0", - "vue-i18n": "^10.0.5", + "vue-i18n": "^11.0.1", "vue-router": "^4.5.0", + "vue-waterfall-plugin-next": "^2.6.4", "ws": "^8.18.0" }, "devDependencies": { @@ -63,12 +65,12 @@ "eslint-plugin-vue": "^9.32.0", "globals": "^15.14.0", "sass": "^1.83.0", - "typescript": "^5.6.3", - "typescript-eslint": "^8.18.1", + "typescript": "^5.7.2", + "typescript-eslint": "^8.18.2", "unplugin-vue-components": "^0.28.0", - "vite": "^6.0.5", + "vite": "^6.0.6", "vite-plugin-bundle-obfuscator": "1.4.0", "vite-plugin-chunk-split": "^0.5.0", - "vue-tsc": "2.1.10" + "vue-tsc": "2.2.0" } } diff --git a/src/App.vue b/src/App.vue index 1f09fb8..9c16d65 100644 --- a/src/App.vue +++ b/src/App.vue @@ -3,9 +3,9 @@ :locale="lang.lang === 'en' ? enUS : zhCN" :theme="app.themeConfig" > - + - + diff --git a/src/assets/gif/loading.gif b/src/assets/gif/loading.gif new file mode 100644 index 0000000..cac4313 Binary files /dev/null and b/src/assets/gif/loading.gif differ diff --git a/src/assets/svgs/cancle.svg b/src/assets/svgs/cancle.svg new file mode 100644 index 0000000..64478be --- /dev/null +++ b/src/assets/svgs/cancle.svg @@ -0,0 +1 @@ + diff --git a/src/assets/svgs/complete.svg b/src/assets/svgs/complete.svg new file mode 100644 index 0000000..09665b8 --- /dev/null +++ b/src/assets/svgs/complete.svg @@ -0,0 +1 @@ + diff --git a/src/assets/svgs/grey-complete.svg b/src/assets/svgs/grey-complete.svg new file mode 100644 index 0000000..8a3214c --- /dev/null +++ b/src/assets/svgs/grey-complete.svg @@ -0,0 +1 @@ + diff --git a/src/assets/svgs/no-image.svg b/src/assets/svgs/no-image.svg new file mode 100644 index 0000000..5adbf45 --- /dev/null +++ b/src/assets/svgs/no-image.svg @@ -0,0 +1 @@ + diff --git a/src/assets/svgs/upload-1.svg b/src/assets/svgs/upload-1.svg new file mode 100644 index 0000000..c68c3ec --- /dev/null +++ b/src/assets/svgs/upload-1.svg @@ -0,0 +1 @@ + diff --git a/src/components/MyUI/CheckCard/CheckCard.vue b/src/components/MyUI/CheckCard/CheckCard.vue new file mode 100644 index 0000000..eab2230 --- /dev/null +++ b/src/components/MyUI/CheckCard/CheckCard.vue @@ -0,0 +1,187 @@ + + + + + diff --git a/src/components/MyUI/Checkbox/Checkbox.vue b/src/components/MyUI/Checkbox/Checkbox.vue index 70e8d9d..2ffa4ad 100644 --- a/src/components/MyUI/Checkbox/Checkbox.vue +++ b/src/components/MyUI/Checkbox/Checkbox.vue @@ -156,7 +156,7 @@ function onChecked() { &:not(.checkbox-disabled):hover { .checkbox-box { - border-color: @themeColor; + border-color: #40a9ff; } } @@ -195,8 +195,8 @@ function onChecked() { } .checkbox-checked { - background-color: @themeColor; - border-color: @themeColor; + background-color: #40a9ff; + border-color: #40a9ff; &::after { opacity: 1; @@ -211,7 +211,7 @@ function onChecked() { left: 50%; width: 8px; height: 8px; - background-color: @themeColor; + background-color: #40a9ff; border: 0; transform: translate(-50%, -50%) scale(1); opacity: 1; diff --git a/src/components/MyUI/Input/Input.vue b/src/components/MyUI/Input/Input.vue index be5c8c4..571692b 100644 --- a/src/components/MyUI/Input/Input.vue +++ b/src/components/MyUI/Input/Input.vue @@ -70,7 +70,7 @@ const showAfter = computed(() => { return slotsExist.addonAfter || props.addonAfter; }); const lazyInput = computed(() => { - return 'lazy' in props.valueModifiers; + return 'lazy.ts' in props.valueModifiers; }); function onInput(e: InputEvent) { diff --git a/src/components/MyUI/InputSearch/InputSearch.vue b/src/components/MyUI/InputSearch/InputSearch.vue index a823d71..086a5fe 100644 --- a/src/components/MyUI/InputSearch/InputSearch.vue +++ b/src/components/MyUI/InputSearch/InputSearch.vue @@ -70,7 +70,7 @@ const showBefore = computed(() => { return slotsExist.addonBefore || props.addonBefore; }); const lazyInput = computed(() => { - return 'lazy' in props.valueModifiers; + return 'lazy.ts' in props.valueModifiers; }); function onInput(e: InputEvent) { diff --git a/src/components/MyUI/Textarea/Textarea.vue b/src/components/MyUI/Textarea/Textarea.vue index c679258..d6adec2 100644 --- a/src/components/MyUI/Textarea/Textarea.vue +++ b/src/components/MyUI/Textarea/Textarea.vue @@ -67,7 +67,7 @@ const showCountNum = computed(() => { return props.value.length; }); const lazyTextarea = computed(() => { - return 'lazy' in props.valueModifiers; + return 'lazy.ts' in props.valueModifiers; }); watch( () => props.value, diff --git a/src/components/MyUI/Waterfall/Waterfall.vue b/src/components/MyUI/Waterfall/ImageWaterfall.vue similarity index 100% rename from src/components/MyUI/Waterfall/Waterfall.vue rename to src/components/MyUI/Waterfall/ImageWaterfall.vue diff --git a/src/directives/index.ts b/src/directives/index.ts index e1a518f..9a0b30d 100644 --- a/src/directives/index.ts +++ b/src/directives/index.ts @@ -9,5 +9,5 @@ import lazyLoad from "@/directives/v-lazy-load.ts"; */ export const registerDirectives = (app: any) => { app.directive('click-outside', clickOutside); - app.directive('lazy-load', lazyLoad); + app.directive('lazy.ts-load', lazyLoad); }; diff --git a/src/layout/default/Sidebar/Sidebar.vue b/src/layout/default/Sidebar/Sidebar.vue index 7f51a08..d18f833 100644 --- a/src/layout/default/Sidebar/Sidebar.vue +++ b/src/layout/default/Sidebar/Sidebar.vue @@ -11,13 +11,13 @@ @select="handleClick" > - + {{ t('album.allAlbums') }} - + @@ -25,25 +25,25 @@ - + {{ t('album.albums') }} - + {{ t('album.peopleAlbums') }} - + {{ t('album.locationAlbums') }} - + @@ -51,19 +51,19 @@ - + {{ t('album.share') }} - + {{ t('album.recyclingBin') }} - + @@ -101,8 +101,6 @@ const {t} = useI18n(); const router = useRouter(); const route = useRoute(); - - /** * handle click event of menu item * @param key @@ -111,6 +109,32 @@ function handleClick({key}) { router.push(`/main/${key}`); } +const menuCSSStyle: any = reactive({ + display: 'flex', + alignItems: 'center', +}); + + +watch( + () => route.path, + () => { + scrollToSelectedMenuItem(); + } +); + +// scroll to selected menu item +function scrollToSelectedMenuItem() { + nextTick(() => { + const selected = document.querySelector(`.ant-menu-item-selected`); + if (selected) { + selected.scrollIntoView({behavior: 'smooth', block: 'center'}); + } + }); +} + +onMounted(() => { + scrollToSelectedMenuItem(); +}); diff --git a/src/views/Photograph/AllPhoto/index.scss b/src/views/Photograph/AllPhoto/index.scss deleted file mode 100644 index e69de29..0000000 diff --git a/src/views/Photograph/RecentUpload/RecentUpload.vue b/src/views/Photograph/RecentUpload/RecentUpload.vue index 3362c50..5cddb52 100644 --- a/src/views/Photograph/RecentUpload/RecentUpload.vue +++ b/src/views/Photograph/RecentUpload/RecentUpload.vue @@ -1,7 +1,35 @@