diff --git a/components.d.ts b/components.d.ts
index 1d0609b..6ec1a46 100644
--- a/components.d.ts
+++ b/components.d.ts
@@ -47,6 +47,8 @@ declare module 'vue' {
ARadio: typeof import('ant-design-vue/es')['Radio']
ARadioGroup: typeof import('ant-design-vue/es')['RadioGroup']
ARow: typeof import('ant-design-vue/es')['Row']
+ ASelect: typeof import('ant-design-vue/es')['Select']
+ ASelectOption: typeof import('ant-design-vue/es')['SelectOption']
ASkeleton: typeof import('ant-design-vue/es')['Skeleton']
ASpace: typeof import('ant-design-vue/es')['Space']
ASpin: typeof import('ant-design-vue/es')['Spin']
@@ -57,6 +59,7 @@ declare module 'vue' {
ATextarea: typeof import('ant-design-vue/es')['Textarea']
ATooltip: typeof import('ant-design-vue/es')['Tooltip']
AUpload: typeof import('ant-design-vue/es')['Upload']
+ AUploadDragger: typeof import('ant-design-vue/es')['UploadDragger']
Avatar: typeof import('./src/components/MyUI/Avatar/Avatar.vue')['default']
BackgroundAnimation: typeof import('./src/components/BackgroundAnimation/BackgroundAnimation.vue')['default']
BackTop: typeof import('./src/components/MyUI/BackTop/BackTop.vue')['default']
@@ -74,6 +77,7 @@ declare module 'vue' {
CloseCircleOutlined: typeof import('@ant-design/icons-vue')['CloseCircleOutlined']
Clouds: typeof import('./src/components/Clouds/Clouds.vue')['default']
CloudServerOutlined: typeof import('@ant-design/icons-vue')['CloudServerOutlined']
+ CloudUploadOutlined: typeof import('@ant-design/icons-vue')['CloudUploadOutlined']
Col: typeof import('./src/components/MyUI/Grid/Col.vue')['default']
Collapse: typeof import('./src/components/MyUI/Collapse/Collapse.vue')['default']
CommentInput: typeof import('./src/components/CommentReply/src/CommentInput/CommentInput.vue')['default']
@@ -81,6 +85,7 @@ declare module 'vue' {
CommentOutlined: typeof import('@ant-design/icons-vue')['CommentOutlined']
CommentReply: typeof import('./src/components/CommentReply/index.vue')['default']
CompareImage: typeof import('./src/components/ImageCompare/CompareImage.vue')['default']
+ CompareResult: typeof import('./src/views/Upscale/CompareResult.vue')['default']
Countdown: typeof import('./src/components/MyUI/Countdown/Countdown.vue')['default']
CustomerServiceOutlined: typeof import('@ant-design/icons-vue')['CustomerServiceOutlined']
DatePicker: typeof import('./src/components/MyUI/DatePicker/DatePicker.vue')['default']
@@ -104,6 +109,7 @@ declare module 'vue' {
ImageCompare: typeof import('./src/components/ImageCompare/ImageCompare.vue')['default']
ImageInPainting: typeof import('./src/views/Upscale/Upscale.vue')['default']
ImageShare: typeof import('./src/views/ImageShare/ImageShare.vue')['default']
+ InboxOutlined: typeof import('@ant-design/icons-vue')['InboxOutlined']
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']
@@ -140,6 +146,7 @@ declare module 'vue' {
ReplyInput: typeof import('./src/components/CommentReply/src/ReplyInput/ReplyInput.vue')['default']
ReplyList: typeof import('./src/components/CommentReply/src/ReplyList/ReplyList.vue')['default']
ReplyReply: typeof import('./src/components/CommentReply/src/ReplyReplyInput/ReplyReply.vue')['default']
+ RestOutlined: typeof import('@ant-design/icons-vue')['RestOutlined']
Result: typeof import('./src/components/MyUI/Result/Result.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
@@ -174,6 +181,7 @@ declare module 'vue' {
TreeChart: typeof import('./src/components/MyUI/TreeChart/TreeChart.vue')['default']
UngroupOutlined: typeof import('@ant-design/icons-vue')['UngroupOutlined']
Upload: typeof import('./src/components/MyUI/Upload/Upload.vue')['default']
+ UploadImage: typeof import('./src/views/Upscale/UploadImage.vue')['default']
Upscale: typeof import('./src/views/Upscale/Upscale.vue')['default']
UserInfoCard: typeof import('./src/components/CommentReply/src/UserInfoCard/UserInfoCard.vue')['default']
UserOutlined: typeof import('@ant-design/icons-vue')['UserOutlined']
diff --git a/package.json b/package.json
index 02f76ae..1d55dec 100644
--- a/package.json
+++ b/package.json
@@ -42,7 +42,7 @@
"nprogress": "^0.2.0",
"nsfwjs": "^4.2.1",
"pinia": "^2.3.0",
- "pinia-plugin-persistedstate": "^4.1.3",
+ "pinia-plugin-persistedstate-2": "^2.0.27",
"qrcode": "^1",
"seedrandom": "^3.0.5",
"swiper": "^11.1.15",
@@ -63,7 +63,7 @@
"globals": "^15.13.0",
"sass": "^1.82.0",
"typescript": "^5.7.2",
- "typescript-eslint": "^8.17.0",
+ "typescript-eslint": "^8.18.0",
"unplugin-vue-components": "^0.27.5",
"vite": "^6.0.3",
"vite-plugin-bundle-obfuscator": "1.3.2",
diff --git a/src/assets/svgs/download.svg b/src/assets/svgs/download.svg
new file mode 100644
index 0000000..c478d64
--- /dev/null
+++ b/src/assets/svgs/download.svg
@@ -0,0 +1 @@
+
diff --git a/src/assets/svgs/empty.svg b/src/assets/svgs/empty.svg
new file mode 100644
index 0000000..f8b7977
--- /dev/null
+++ b/src/assets/svgs/empty.svg
@@ -0,0 +1 @@
+
diff --git a/src/assets/svgs/file.svg b/src/assets/svgs/file.svg
index 3101494..d149e82 100644
--- a/src/assets/svgs/file.svg
+++ b/src/assets/svgs/file.svg
@@ -1 +1 @@
-
+
diff --git a/src/assets/svgs/package-download.svg b/src/assets/svgs/package-download.svg
new file mode 100644
index 0000000..72b9e17
--- /dev/null
+++ b/src/assets/svgs/package-download.svg
@@ -0,0 +1 @@
+
diff --git a/src/assets/svgs/qr-phone.svg b/src/assets/svgs/qr-phone.svg
new file mode 100644
index 0000000..35bd4a7
--- /dev/null
+++ b/src/assets/svgs/qr-phone.svg
@@ -0,0 +1 @@
+
diff --git a/src/assets/svgs/remove.svg b/src/assets/svgs/remove.svg
new file mode 100644
index 0000000..9563079
--- /dev/null
+++ b/src/assets/svgs/remove.svg
@@ -0,0 +1 @@
+
diff --git a/src/assets/svgs/run.svg b/src/assets/svgs/run.svg
new file mode 100644
index 0000000..85e0c57
--- /dev/null
+++ b/src/assets/svgs/run.svg
@@ -0,0 +1 @@
+
diff --git a/src/assets/svgs/save.svg b/src/assets/svgs/save.svg
new file mode 100644
index 0000000..67966fe
--- /dev/null
+++ b/src/assets/svgs/save.svg
@@ -0,0 +1 @@
+
diff --git a/src/main.ts b/src/main.ts
index f6220fe..cf1ca81 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -6,12 +6,13 @@ import router from "@/router/router.ts";
import "go-captcha-vue/dist/style.css";
import GoCaptcha from "go-captcha-vue";
import {createPinia, Pinia} from "pinia";
-import piniaPluginPersistedstate from "pinia-plugin-persistedstate";
+import {createPersistedStatePlugin} from 'pinia-plugin-persistedstate-2';
import VueDOMPurifyHTML from 'vue-dompurify-html';
import {registerDirectives} from "@/directives";
const pinia: Pinia = createPinia();
-pinia.use(piniaPluginPersistedstate);
+const installPersistedStatePlugin = createPersistedStatePlugin();
+pinia.use((context) => installPersistedStatePlugin(context));
const app = createApp(App);
registerDirectives(app);
app.use(pinia);
diff --git a/src/store/index.ts b/src/store/index.ts
index c19727a..4e1fdcd 100644
--- a/src/store/index.ts
+++ b/src/store/index.ts
@@ -3,6 +3,7 @@ import {useThemeStore} from "@/store/modules/themeStore.ts";
import {langStore} from "@/store/modules/langStore.ts";
import {useCommentStore} from "@/store/modules/commentStore.ts";
import {useWebSocketStore} from "@/store/modules/websocketStore.ts";
+import {useUpscaleStore} from "@/store/modules/upscaleStore.ts";
export default function useStore() {
return {
@@ -11,5 +12,6 @@ export default function useStore() {
lang: langStore(),
comment: useCommentStore(),
websocket: useWebSocketStore(),
+ upscale: useUpscaleStore(),
};
}
diff --git a/src/store/modules/commentStore.ts b/src/store/modules/commentStore.ts
index 9400574..ae3f751 100644
--- a/src/store/modules/commentStore.ts
+++ b/src/store/modules/commentStore.ts
@@ -8,6 +8,7 @@ import QQ_EMOJI from "@/constant/qq_emoji.ts";
import {initNSFWJs, predictNSFW} from "@/utils/nsfw/nsfw.ts";
import {NSFWJS} from "nsfwjs";
import i18n from "@/locales";
+import localForage from "localforage";
export const useCommentStore = defineStore(
'comment',
@@ -325,10 +326,16 @@ export const useCommentStore = defineStore(
},
{
// 开启数据持久化
- persist: {
+ // persist: {
+ // key: 'comment',
+ // storage: localStorage,
+ // pick: ["emojiList", "commentList", "replyVisibility", "commentMap"],
+ // }
+ persistedState: {
+ persist: true,
+ storage: localForage,
key: 'comment',
- storage: localStorage,
- pick: ["emojiList", "commentList", "replyVisibility", "commentMap"],
+ includePaths: ["emojiList", "commentList", "replyVisibility", "commentMap"]
}
}
);
diff --git a/src/store/modules/langStore.ts b/src/store/modules/langStore.ts
index ed231cd..014965d 100644
--- a/src/store/modules/langStore.ts
+++ b/src/store/modules/langStore.ts
@@ -1,6 +1,7 @@
import {defineStore} from 'pinia';
import {ref} from "vue";
+
export const langStore = defineStore(
'lang',
() => {
@@ -11,10 +12,11 @@ export const langStore = defineStore(
},
{
// 开启数据持久化
- persist: {
- key: 'lang',
+ persistedState: {
+ persist: true,
storage: localStorage,
- pick: ["lang"],
+ key: 'lang',
+ includePaths: ['lang']
}
}
);
diff --git a/src/store/modules/themeStore.ts b/src/store/modules/themeStore.ts
index cd86b2f..6a2606a 100644
--- a/src/store/modules/themeStore.ts
+++ b/src/store/modules/themeStore.ts
@@ -37,10 +37,11 @@ export const useThemeStore = defineStore(
return {themeName, themeConfig, darkMode, setThemeName, toggleDarkMode};
},
{
- persist: {
- key: 'theme',
+ persistedState: {
+ persist: true,
storage: localStorage,
- pick: ["themeName", "darkMode"],
+ key: 'theme',
+ includePaths: ['themeName', 'darkMode']
}
}
);
diff --git a/src/store/modules/upscaleStore.ts b/src/store/modules/upscaleStore.ts
new file mode 100644
index 0000000..e4c7875
--- /dev/null
+++ b/src/store/modules/upscaleStore.ts
@@ -0,0 +1,88 @@
+import {defineStore} from 'pinia';
+import {initNSFWJs, predictNSFW} from "@/utils/nsfw/nsfw.ts";
+import i18n from "@/locales";
+import message from "@/components/MyUI/Message/Message.vue";
+import {NSFWJS} from "nsfwjs";
+import localForage from "localforage";
+
+export const useUpscaleStore = defineStore(
+ 'upscale',
+ () => {
+ const imageList = ref([]);
+ const fileList = ref([]);
+ const uploading = ref(false);
+
+ /**
+ * 图片上传前的校验
+ * @param file
+ */
+ async function beforeUpload(file: any) {
+ if (fileList.value.length >= 5) {
+ return false;
+ }
+ uploading.value = true;
+ if (!window.FileReader) return false;
+ const reader = new FileReader();
+ reader.readAsDataURL(file); // 文件转换
+ reader.onloadend = async function () {
+ const img: HTMLImageElement = document.createElement('img');
+ img.src = reader.result as string;
+ img.onload = async () => {
+ // 图片 NSFW 检测
+ const nsfw: NSFWJS = await initNSFWJs();
+ const isNSFW: boolean = await predictNSFW(nsfw, img);
+ if (isNSFW) {
+ message.error(i18n.global.t('comment.illegalImage'));
+ fileList.value.pop();
+ return false;
+ }
+ fileList.value.push(img.src);
+ };
+
+ uploading.value = false;
+ return true;
+ };
+ }
+
+ /**
+ * 自定义上传图片请求
+ */
+ async function customUploadRequest() {
+ imageList.value = fileList.value;
+
+ }
+
+ /**
+ * 移除图片
+ * @param index
+ */
+ async function removeImage(index: number) {
+ fileList.value.splice(index, 1);
+ imageList.value.splice(index, 1);
+ }
+
+ return {
+ imageList,
+ fileList,
+ uploading,
+ beforeUpload,
+ customUploadRequest,
+ removeImage
+ };
+ }
+
+ ,
+ {
+ // 开启数据持久化
+ persistedState: {
+ persist: true,
+ storage:
+ localForage,
+ key:
+ 'upscale',
+ includePaths:
+ ['imageList', 'fileList']
+ }
+ }
+ )
+;
diff --git a/src/store/modules/userStore.ts b/src/store/modules/userStore.ts
index 2e3306e..3ff72ea 100644
--- a/src/store/modules/userStore.ts
+++ b/src/store/modules/userStore.ts
@@ -144,10 +144,16 @@ export const useAuthStore = defineStore(
},
{
// 开启数据持久化
- persist: {
- key: 'user',
+ // persist: {
+ // key: 'user',
+ // storage: localStorage,
+ // pick: ['user', "clientId", "githubRedirectUrl", "giteeRedirectUrl", "qqRedirectUrl"],
+ // }
+ persistedState: {
+ persist: true,
storage: localStorage,
- pick: ['user', "clientId", "githubRedirectUrl", "giteeRedirectUrl", "qqRedirectUrl"],
+ key: 'user',
+ includePaths: ['user', "clientId", "githubRedirectUrl", "giteeRedirectUrl", "qqRedirectUrl"]
}
}
);
diff --git a/src/store/modules/websocketStore.ts b/src/store/modules/websocketStore.ts
index c7b235a..a894b57 100644
--- a/src/store/modules/websocketStore.ts
+++ b/src/store/modules/websocketStore.ts
@@ -49,5 +49,7 @@ export const useWebSocketStore = defineStore('websocket', () => {
getReadyState
};
}, {
- persist: false,
+ persistedState: {
+ persist: false,
+ }
});
diff --git a/src/utils/nsfw/nsfw.ts b/src/utils/nsfw/nsfw.ts
index 974fc26..02060c9 100644
--- a/src/utils/nsfw/nsfw.ts
+++ b/src/utils/nsfw/nsfw.ts
@@ -9,7 +9,7 @@ let isInit: boolean = false;
const initNSFWJs = async (): Promise => {
tf.enableProdMode();
if (!isInit) {
- const initialLoad: nsfwjs.NSFWJS = await nsfwjs.load("/nsfw/model/mobilenet_v2_mid/", {
+ const initialLoad: nsfwjs.NSFWJS = await nsfwjs.load("/nsfw/mobilenet_v2_mid/", {
size: 224,
type: "graph"
});
diff --git a/src/views/Main/index.scss b/src/views/Main/index.scss
index e4a5b8a..c1ae92e 100644
--- a/src/views/Main/index.scss
+++ b/src/views/Main/index.scss
@@ -3,23 +3,20 @@
flex-direction: column;
background-color: #eaeef6;
color: var(--text-color);
- width: 100%;
- min-height: 100vh;
-
- .main-header {
-
- }
+ width: 100vw;
.main-content {
display: flex;
flex-direction: row;
+ width: 100%;
+ height: calc(100vh - 70px);
.main-content-container {
- width: calc(100% - 230px);
- height: calc(100% - 110px);
- padding: 20px;
- overflow: scroll;
-
+ width: calc(100vw - 230px);
+ height: calc(100vh - 100px);
+ max-height: calc(100vh - 100px);
+ padding: 15px;
+ overflow: auto;
}
}
diff --git a/src/views/Upscale/CompareResult.vue b/src/views/Upscale/CompareResult.vue
new file mode 100644
index 0000000..47698d9
--- /dev/null
+++ b/src/views/Upscale/CompareResult.vue
@@ -0,0 +1,184 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
保存下载
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 处理数量:
+ {{ 5 }}
+
+
+ 处理大小:
+ {{ upscale.imageList.length }} /mb
+
+
+
+
+
+ 消耗时间:
+ {{ upscale.imageList.length }} /s
+
+
+ 内存消耗:
+ {{ upscale.imageList.length }} /mb
+
+
+
+
+
+
+
+
diff --git a/src/views/Upscale/UploadImage.vue b/src/views/Upscale/UploadImage.vue
new file mode 100644
index 0000000..2e5f21b
--- /dev/null
+++ b/src/views/Upscale/UploadImage.vue
@@ -0,0 +1,211 @@
+
+
+
+
+
+
+
+
+
+
+
+ 点击或拖拽上传图片
+
+
最多一次处理5张图片
+
+
+
+
+
+
+
+
+ 图片列表
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/Upscale/Upscale.vue b/src/views/Upscale/Upscale.vue
index 8e222e3..b40b555 100644
--- a/src/views/Upscale/Upscale.vue
+++ b/src/views/Upscale/Upscale.vue
@@ -1,15 +1,122 @@