🚸 optimize
This commit is contained in:
@@ -8,11 +8,9 @@ export const generateClientId = () => {
|
|||||||
{
|
{
|
||||||
meta: {
|
meta: {
|
||||||
ignoreToken: true,
|
ignoreToken: true,
|
||||||
|
signature: true
|
||||||
},
|
},
|
||||||
cacheFor: {
|
cacheFor: null,
|
||||||
mode: "restore",
|
|
||||||
expire: 1000 * 60 * 60 * 24
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@@ -58,7 +58,7 @@ export const commentListApi = (params: any) => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
cacheFor: {
|
cacheFor: {
|
||||||
expire: 60 * 60 * 24 * 7,
|
expire: 60 * 60 * 24,
|
||||||
mode: "restore",
|
mode: "restore",
|
||||||
}, // 7天缓存
|
}, // 7天缓存
|
||||||
hitSource: "comment-submit",
|
hitSource: "comment-submit",
|
||||||
@@ -81,7 +81,7 @@ export const replyListApi = (params: any) => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
cacheFor: {
|
cacheFor: {
|
||||||
expire: 60 * 60 * 24 * 7,
|
expire: 60 * 60 * 24,
|
||||||
mode: "restore",
|
mode: "restore",
|
||||||
}, // 7天缓存
|
}, // 7天缓存
|
||||||
hitSource: ["reply-submit", "reply-reply-submit"],
|
hitSource: ["reply-submit", "reply-reply-submit"],
|
||||||
|
@@ -11,7 +11,7 @@ export const getGiteeUrl = () => {
|
|||||||
},
|
},
|
||||||
cacheFor: {
|
cacheFor: {
|
||||||
mode: "restore",
|
mode: "restore",
|
||||||
expire: 1000 * 60 * 60 * 24 * 7
|
expire: 1000 * 60 * 60 * 24
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@@ -14,7 +14,7 @@ export const getGithubUrl = (state: string) => {
|
|||||||
},
|
},
|
||||||
cacheFor: {
|
cacheFor: {
|
||||||
mode: "restore",
|
mode: "restore",
|
||||||
expire: 1000 * 60 * 60 * 24 * 7
|
expire: 1000 * 60 * 60 * 24
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@@ -11,7 +11,7 @@ export const getQQUrl = (state: string) => {
|
|||||||
},
|
},
|
||||||
cacheFor: {
|
cacheFor: {
|
||||||
mode: "restore",
|
mode: "restore",
|
||||||
expire: 1000 * 60 * 60 * 24 * 7
|
expire: 1000 * 60 * 60 * 24
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@@ -10,7 +10,7 @@ export const generateQrCode = (clientId: string) => {
|
|||||||
params: {
|
params: {
|
||||||
client_id: clientId
|
client_id: clientId
|
||||||
},
|
},
|
||||||
cacheFor: 1000 * 60 * 60 * 24 * 7,
|
cacheFor: null,
|
||||||
meta: {
|
meta: {
|
||||||
ignoreToken: true,
|
ignoreToken: true,
|
||||||
},
|
},
|
||||||
|
@@ -8,7 +8,7 @@ export const refreshToken = () => {
|
|||||||
return service.Post('/api/auth/token/refresh', {}, {
|
return service.Post('/api/auth/token/refresh', {}, {
|
||||||
meta: {
|
meta: {
|
||||||
authRole: 'refreshToken',
|
authRole: 'refreshToken',
|
||||||
ignoreToken: false,
|
ignoreToken: true,
|
||||||
signature: true
|
signature: true
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -93,11 +93,14 @@ export const resetPasswordApi = (param: ResetPassword) => {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取用户设备信息
|
* 获取用户设备信息
|
||||||
|
* @param access_token
|
||||||
*/
|
*/
|
||||||
export const getUserDevice = () => {
|
export const getUserDevice = (access_token: string) => {
|
||||||
return service.Get('/api/user/device',
|
return service.Post('/api/user/device',
|
||||||
|
{
|
||||||
|
access_token: access_token,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
params: {},
|
|
||||||
meta: {
|
meta: {
|
||||||
ignoreToken: true,
|
ignoreToken: true,
|
||||||
signature: true
|
signature: true
|
||||||
|
@@ -12,6 +12,73 @@ import Module from "@/workers/imghelper.ts";
|
|||||||
export const useUpscaleStore = defineStore(
|
export const useUpscaleStore = defineStore(
|
||||||
'upscale',
|
'upscale',
|
||||||
() => {
|
() => {
|
||||||
|
|
||||||
|
// 模型参数
|
||||||
|
const TypeData = ref<string[]>(['realesrgan', 'realcugan']);
|
||||||
|
|
||||||
|
const model_type = ref<string>(TypeData.value[0]);
|
||||||
|
|
||||||
|
const ModelConfig = reactive({
|
||||||
|
realesrgan: {
|
||||||
|
model: ["anime_fast", "anime_plus", "general_fast", "general_plus"],
|
||||||
|
factor: [4],
|
||||||
|
tile_size: [32, 48, 64, 96, 128, 192, 256],
|
||||||
|
},
|
||||||
|
realcugan: {
|
||||||
|
factor: [2, 4],
|
||||||
|
denoise: {
|
||||||
|
2: [
|
||||||
|
"conservative",
|
||||||
|
"no-denoise",
|
||||||
|
"denoise1x",
|
||||||
|
"denoise2x",
|
||||||
|
"denoise3x",
|
||||||
|
],
|
||||||
|
3: ["conservative", "denoise3x"],
|
||||||
|
4: ["conservative", "no-denoise", "denoise3x"],
|
||||||
|
},
|
||||||
|
tile_size: [32, 48, 64, 96, 128, 192, 256, 384, 512],
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const factor = ref<number>(4);
|
||||||
|
const model = ref(ModelConfig[model_type.value].model[0]);
|
||||||
|
const modes = computed(() => {
|
||||||
|
if (model_type.value === "realesrgan") {
|
||||||
|
return ModelConfig[model_type.value].model;
|
||||||
|
} else {
|
||||||
|
return ModelConfig[model_type.value].denoise[factor.value];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(model_type, val => {
|
||||||
|
if (model_type.value === "realesrgan") {
|
||||||
|
model.value = ModelConfig[val].model[0];
|
||||||
|
} else {
|
||||||
|
model.value = ModelConfig[val].denoise[factor.value][0];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Scale
|
||||||
|
const scales = computed(() => {
|
||||||
|
return ModelConfig[model_type.value].factor;
|
||||||
|
});
|
||||||
|
|
||||||
|
//tile size
|
||||||
|
const tile_size = ref<number>(128);
|
||||||
|
const tileSize = computed(() => {
|
||||||
|
return ModelConfig[model_type.value].tile_size;
|
||||||
|
});
|
||||||
|
|
||||||
|
// overlap
|
||||||
|
const overlapList = ref<number[]>([0, 4, 8, 12, 16, 20]);
|
||||||
|
const min_lap = ref<number>(overlapList.value[3]);
|
||||||
|
|
||||||
|
// run on
|
||||||
|
const backendList = ref<string[]>(['webgl', 'webgpu']);
|
||||||
|
const backend = ref<string>(backendList.value[0]);
|
||||||
|
|
||||||
|
// ***************图片处理***************
|
||||||
const image: HTMLImageElement = document.createElement('img');
|
const image: HTMLImageElement = document.createElement('img');
|
||||||
const imageData = ref<string>();
|
const imageData = ref<string>();
|
||||||
const fileData = ref<string>();
|
const fileData = ref<string>();
|
||||||
@@ -33,7 +100,7 @@ export const useUpscaleStore = defineStore(
|
|||||||
const isProcessing = ref<boolean>(false);
|
const isProcessing = ref<boolean>(false);
|
||||||
const msg = ref<string>("");
|
const msg = ref<string>("");
|
||||||
const progressBar = ref<number>(0);
|
const progressBar = ref<number>(0);
|
||||||
|
const status = ref<string>('loading');
|
||||||
/**
|
/**
|
||||||
* 图片上传前的校验
|
* 图片上传前的校验
|
||||||
* @param file
|
* @param file
|
||||||
@@ -111,6 +178,19 @@ export const useUpscaleStore = defineStore(
|
|||||||
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
TypeData,
|
||||||
|
model_type,
|
||||||
|
ModelConfig,
|
||||||
|
model,
|
||||||
|
modes,
|
||||||
|
factor,
|
||||||
|
tile_size,
|
||||||
|
tileSize,
|
||||||
|
scales,
|
||||||
|
overlapList,
|
||||||
|
min_lap,
|
||||||
|
backend,
|
||||||
|
backendList,
|
||||||
uploading,
|
uploading,
|
||||||
imageData,
|
imageData,
|
||||||
input,
|
input,
|
||||||
@@ -122,6 +202,7 @@ export const useUpscaleStore = defineStore(
|
|||||||
isProcessing,
|
isProcessing,
|
||||||
msg,
|
msg,
|
||||||
progressBar,
|
progressBar,
|
||||||
|
status,
|
||||||
loadImg,
|
loadImg,
|
||||||
beforeUpload,
|
beforeUpload,
|
||||||
customUploadRequest,
|
customUploadRequest,
|
||||||
|
@@ -5,7 +5,7 @@ import {getGithubUrl} from "@/api/oauth/github.ts";
|
|||||||
import {getQQUrl} from "@/api/oauth/qq.ts";
|
import {getQQUrl} from "@/api/oauth/qq.ts";
|
||||||
import {getGiteeUrl} from "@/api/oauth/gitee.ts";
|
import {getGiteeUrl} from "@/api/oauth/gitee.ts";
|
||||||
import {getUserDevice} from "@/api/user";
|
import {getUserDevice} from "@/api/user";
|
||||||
import message from "@/components/MyUI/Message/Message.vue";
|
import {message} from "ant-design-vue";
|
||||||
import {useI18n} from "vue-i18n";
|
import {useI18n} from "vue-i18n";
|
||||||
|
|
||||||
export const useAuthStore = defineStore(
|
export const useAuthStore = defineStore(
|
||||||
@@ -70,17 +70,18 @@ export const useAuthStore = defineStore(
|
|||||||
* 处理消息
|
* 处理消息
|
||||||
* @param e
|
* @param e
|
||||||
*/
|
*/
|
||||||
const messageHandler = async (e: any) => {
|
const messageHandler = async (e: MessageEvent) => {
|
||||||
if (typeof e.data === 'string') {
|
if (typeof e.data === 'string') {
|
||||||
const res: any = JSON.parse(e.data);
|
const res: any = JSON.parse(e.data);
|
||||||
if (res && res.code === 200) {
|
if (res && res.code === 200) {
|
||||||
user.uid = res.data.uid;
|
const {data} = res;
|
||||||
user.access_token = res.data.access_token;
|
user.uid = data.uid;
|
||||||
user.username = res.data.username;
|
user.access_token = data.access_token;
|
||||||
user.avatar = res.data.avatar;
|
user.username = data.username;
|
||||||
user.nickname = res.data.nickname;
|
user.avatar = data.avatar;
|
||||||
user.status = res.data.status;
|
user.nickname = data.nickname;
|
||||||
await getUserDevice();
|
user.status = data.status;
|
||||||
|
await getUserDevice(data.access_token);
|
||||||
message.success(t('login.loginSuccess'));
|
message.success(t('login.loginSuccess'));
|
||||||
window.removeEventListener("message", messageHandler);
|
window.removeEventListener("message", messageHandler);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
@@ -20,7 +20,13 @@ export const useWebSocketStore = defineStore('websocket', () => {
|
|||||||
}) {
|
}) {
|
||||||
state.wsService = new WebSocketService(options);
|
state.wsService = new WebSocketService(options);
|
||||||
state.wsService?.open();
|
state.wsService?.open();
|
||||||
|
|
||||||
|
state.wsService?.on('open', () => {
|
||||||
readyState.value = WebSocket.OPEN;
|
readyState.value = WebSocket.OPEN;
|
||||||
|
});
|
||||||
|
state.wsService?.on('close', () => {
|
||||||
|
readyState.value = WebSocket.CLOSED;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendMessage(data: any) {
|
function sendMessage(data: any) {
|
||||||
|
@@ -41,7 +41,7 @@ export const service = createAlova({
|
|||||||
requestAdapter: axiosRequestAdapter(),
|
requestAdapter: axiosRequestAdapter(),
|
||||||
l2Cache: localforageStorageAdapter,
|
l2Cache: localforageStorageAdapter,
|
||||||
cacheLogger: import.meta.env.VITE_NODE_ENV === 'development',
|
cacheLogger: import.meta.env.VITE_NODE_ENV === 'development',
|
||||||
cacheFor: {},
|
cacheFor: null,
|
||||||
// 设置全局的请求拦截器
|
// 设置全局的请求拦截器
|
||||||
beforeRequest: onAuthRequired(async (method: any) => {
|
beforeRequest: onAuthRequired(async (method: any) => {
|
||||||
if (!method.meta?.ignoreToken) {
|
if (!method.meta?.ignoreToken) {
|
||||||
|
@@ -6,7 +6,7 @@ export function handleErrorCode(code: number): void {
|
|||||||
message
|
message
|
||||||
.open({
|
.open({
|
||||||
content: i18n.global.t("error.400"),
|
content: i18n.global.t("error.400"),
|
||||||
duration: 5,
|
duration: 3,
|
||||||
type: "error",
|
type: "error",
|
||||||
})
|
})
|
||||||
.then();
|
.then();
|
||||||
@@ -15,7 +15,7 @@ export function handleErrorCode(code: number): void {
|
|||||||
message
|
message
|
||||||
.open({
|
.open({
|
||||||
content: i18n.global.t("error.401"),
|
content: i18n.global.t("error.401"),
|
||||||
duration: 5,
|
duration: 3,
|
||||||
type: "error",
|
type: "error",
|
||||||
})
|
})
|
||||||
.then();
|
.then();
|
||||||
@@ -24,7 +24,7 @@ export function handleErrorCode(code: number): void {
|
|||||||
message
|
message
|
||||||
.open({
|
.open({
|
||||||
content: i18n.global.t("error.403"),
|
content: i18n.global.t("error.403"),
|
||||||
duration: 5,
|
duration: 3,
|
||||||
type: "error",
|
type: "error",
|
||||||
})
|
})
|
||||||
.then();
|
.then();
|
||||||
@@ -33,7 +33,7 @@ export function handleErrorCode(code: number): void {
|
|||||||
message
|
message
|
||||||
.open({
|
.open({
|
||||||
content: i18n.global.t("error.404"),
|
content: i18n.global.t("error.404"),
|
||||||
duration: 5,
|
duration: 3,
|
||||||
type: "error",
|
type: "error",
|
||||||
})
|
})
|
||||||
.then();
|
.then();
|
||||||
@@ -42,7 +42,7 @@ export function handleErrorCode(code: number): void {
|
|||||||
message
|
message
|
||||||
.open({
|
.open({
|
||||||
content: i18n.global.t("error.408"),
|
content: i18n.global.t("error.408"),
|
||||||
duration: 5,
|
duration: 3,
|
||||||
type: "error",
|
type: "error",
|
||||||
})
|
})
|
||||||
.then();
|
.then();
|
||||||
@@ -51,7 +51,7 @@ export function handleErrorCode(code: number): void {
|
|||||||
message
|
message
|
||||||
.open({
|
.open({
|
||||||
content: i18n.global.t("error.500"),
|
content: i18n.global.t("error.500"),
|
||||||
duration: 5,
|
duration: 3,
|
||||||
type: "error",
|
type: "error",
|
||||||
})
|
})
|
||||||
.then();
|
.then();
|
||||||
@@ -60,7 +60,7 @@ export function handleErrorCode(code: number): void {
|
|||||||
message
|
message
|
||||||
.open({
|
.open({
|
||||||
content: i18n.global.t("error.501"),
|
content: i18n.global.t("error.501"),
|
||||||
duration: 5,
|
duration: 3,
|
||||||
type: "error",
|
type: "error",
|
||||||
})
|
})
|
||||||
.then();
|
.then();
|
||||||
@@ -69,7 +69,7 @@ export function handleErrorCode(code: number): void {
|
|||||||
message
|
message
|
||||||
.open({
|
.open({
|
||||||
content: i18n.global.t("error.502"),
|
content: i18n.global.t("error.502"),
|
||||||
duration: 5,
|
duration: 3,
|
||||||
type: "error",
|
type: "error",
|
||||||
})
|
})
|
||||||
.then();
|
.then();
|
||||||
@@ -78,7 +78,7 @@ export function handleErrorCode(code: number): void {
|
|||||||
message
|
message
|
||||||
.open({
|
.open({
|
||||||
content: i18n.global.t("error.503"),
|
content: i18n.global.t("error.503"),
|
||||||
duration: 5,
|
duration: 3,
|
||||||
type: "error",
|
type: "error",
|
||||||
})
|
})
|
||||||
.then();
|
.then();
|
||||||
@@ -87,7 +87,7 @@ export function handleErrorCode(code: number): void {
|
|||||||
message
|
message
|
||||||
.open({
|
.open({
|
||||||
content: i18n.global.t("error.504"),
|
content: i18n.global.t("error.504"),
|
||||||
duration: 5,
|
duration: 3,
|
||||||
type: "error",
|
type: "error",
|
||||||
})
|
})
|
||||||
.then();
|
.then();
|
||||||
@@ -96,7 +96,7 @@ export function handleErrorCode(code: number): void {
|
|||||||
message
|
message
|
||||||
.open({
|
.open({
|
||||||
content: i18n.global.t("error.505"),
|
content: i18n.global.t("error.505"),
|
||||||
duration: 5,
|
duration: 3,
|
||||||
type: "error",
|
type: "error",
|
||||||
})
|
})
|
||||||
.then();
|
.then();
|
||||||
@@ -105,7 +105,7 @@ export function handleErrorCode(code: number): void {
|
|||||||
message
|
message
|
||||||
.open({
|
.open({
|
||||||
content: i18n.global.t("error.other") + `(${code})`,
|
content: i18n.global.t("error.other") + `(${code})`,
|
||||||
duration: 5,
|
duration: 3,
|
||||||
type: "error",
|
type: "error",
|
||||||
})
|
})
|
||||||
.then();
|
.then();
|
||||||
|
29
src/utils/imageUtils/getImageSizeWithUnit.ts
Normal file
29
src/utils/imageUtils/getImageSizeWithUnit.ts
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
async function getImageSizeWithUnit(url: string): Promise<string> {
|
||||||
|
let sizeInBytes: number;
|
||||||
|
|
||||||
|
// 处理 base64 格式的图片 URL
|
||||||
|
if (url.startsWith('data:')) {
|
||||||
|
sizeInBytes = atob(url.split(',')[1]).length * 0.75;
|
||||||
|
}
|
||||||
|
// 处理 blob 格式的图片 URL
|
||||||
|
else if (url.startsWith('blob:')) {
|
||||||
|
const response = await fetch(url);
|
||||||
|
const blob = await response.blob();
|
||||||
|
sizeInBytes = blob.size;
|
||||||
|
} else {
|
||||||
|
throw new Error('Unsupported URL format');
|
||||||
|
}
|
||||||
|
|
||||||
|
let unit = 'Bytes';
|
||||||
|
if (sizeInBytes >= 1024 * 1024) {
|
||||||
|
sizeInBytes /= (1024 * 1024);
|
||||||
|
unit = 'MB';
|
||||||
|
} else if (sizeInBytes >= 1024) {
|
||||||
|
sizeInBytes /= 1024;
|
||||||
|
unit = 'KB';
|
||||||
|
}
|
||||||
|
|
||||||
|
return `${parseFloat(sizeInBytes.toFixed(2))} ${unit}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default getImageSizeWithUnit;
|
@@ -53,7 +53,7 @@ export class WebSocketService {
|
|||||||
};
|
};
|
||||||
|
|
||||||
private handleMessage = (event: MessageEvent): void => {
|
private handleMessage = (event: MessageEvent): void => {
|
||||||
const data = JSON.parse(event.data);
|
const {data} = event;
|
||||||
if (this.callbacks.message) {
|
if (this.callbacks.message) {
|
||||||
this.callbacks.message.forEach((cb) => (cb as MessageCallback)(data));
|
this.callbacks.message.forEach((cb) => (cb as MessageCallback)(data));
|
||||||
}
|
}
|
||||||
@@ -71,9 +71,6 @@ export class WebSocketService {
|
|||||||
console.log('WebSocket连接已关闭');
|
console.log('WebSocket连接已关闭');
|
||||||
if (this.callbacks.close) {
|
if (this.callbacks.close) {
|
||||||
this.callbacks.close.forEach((cb) => (cb as EventCallback)());
|
this.callbacks.close.forEach((cb) => (cb as EventCallback)());
|
||||||
if (!this.options.reconnectTimeout) {
|
|
||||||
this.reconnect();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -84,8 +81,4 @@ export class WebSocketService {
|
|||||||
console.warn('尝试发送消息时WebSocket未连接');
|
console.warn('尝试发送消息时WebSocket未连接');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public getReadyState(): number {
|
|
||||||
return this.ws ? this.ws.readyState : WebSocket.CLOSED;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -47,7 +47,6 @@ import BoxDog from "@/components/BoxDog/BoxDog.vue";
|
|||||||
import QRLoginFooter from "@/views/QRLogin/QRLoginFooter.vue";
|
import QRLoginFooter from "@/views/QRLogin/QRLoginFooter.vue";
|
||||||
import {useRouter} from 'vue-router';
|
import {useRouter} from 'vue-router';
|
||||||
import {generateQrCode} from "@/api/oauth/wechat.ts";
|
import {generateQrCode} from "@/api/oauth/wechat.ts";
|
||||||
import {onBeforeUnmount, onMounted, ref} from "vue";
|
|
||||||
import logo from "@/assets/svgs/logo-album.svg";
|
import logo from "@/assets/svgs/logo-album.svg";
|
||||||
|
|
||||||
import useStore from "@/store";
|
import useStore from "@/store";
|
||||||
@@ -71,7 +70,6 @@ const userStore = useStore().user;
|
|||||||
async function getQrCode() {
|
async function getQrCode() {
|
||||||
const res: any = await generateQrCode(userStore.clientId);
|
const res: any = await generateQrCode(userStore.clientId);
|
||||||
if (res && res.code === 200) {
|
if (res && res.code === 200) {
|
||||||
status.value = 'active';
|
|
||||||
qrcode.value = res.data;
|
qrcode.value = res.data;
|
||||||
await handleListenMessage();
|
await handleListenMessage();
|
||||||
} else {
|
} else {
|
||||||
@@ -82,6 +80,7 @@ async function getQrCode() {
|
|||||||
|
|
||||||
const wsOptions = {
|
const wsOptions = {
|
||||||
url: import.meta.env.VITE_QR_SOCKET_URL + "?client_id=" + userStore.clientId,
|
url: import.meta.env.VITE_QR_SOCKET_URL + "?client_id=" + userStore.clientId,
|
||||||
|
reconnectTimeout: 10000,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -93,14 +92,15 @@ async function handleListenMessage() {
|
|||||||
// 注册消息接收处理函数
|
// 注册消息接收处理函数
|
||||||
websocket.on('message', async (res: any) => {
|
websocket.on('message', async (res: any) => {
|
||||||
if (res && res.code === 200) {
|
if (res && res.code === 200) {
|
||||||
userStore.user.uid = res.data.uid;
|
|
||||||
userStore.user.access_token = res.data.access_token;
|
|
||||||
userStore.user.username = res.data.username;
|
|
||||||
userStore.user.avatar = res.data.avatar;
|
|
||||||
userStore.user.nickname = res.data.nickname;
|
|
||||||
userStore.user.status = res.data.status;
|
|
||||||
status.value = 'scanned';
|
status.value = 'scanned';
|
||||||
await getUserDevice();
|
const {data} = res;
|
||||||
|
userStore.user.uid = data.uid;
|
||||||
|
userStore.user.access_token = data.access_token;
|
||||||
|
userStore.user.username = data.username;
|
||||||
|
userStore.user.avatar = data.avatar;
|
||||||
|
userStore.user.nickname = data.nickname;
|
||||||
|
userStore.user.status = data.status;
|
||||||
|
await getUserDevice(data.access_token);
|
||||||
message.success(t('login.loginSuccess'));
|
message.success(t('login.loginSuccess'));
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
router.push('/main/photo/all');
|
router.push('/main/photo/all');
|
||||||
@@ -117,6 +117,17 @@ onMounted(async () => {
|
|||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
websocket.close(false);
|
websocket.close(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => websocket.readyState,
|
||||||
|
(newStatus) => {
|
||||||
|
if (newStatus === WebSocket.OPEN) {
|
||||||
|
status.value = 'active';
|
||||||
|
} else {
|
||||||
|
status.value = 'expired';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
<style src="./index.scss" lang="scss" scoped>
|
<style src="./index.scss" lang="scss" scoped>
|
||||||
|
|
||||||
|
@@ -1,7 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
ref="canvasContainer"
|
ref="canvasContainer"
|
||||||
class="canvas-container bg drag-over dark"
|
class="canvas-container bg"
|
||||||
|
:class="{
|
||||||
|
'drag-over':false,
|
||||||
|
'dark':false
|
||||||
|
}"
|
||||||
@mousedown="startDragging"
|
@mousedown="startDragging"
|
||||||
@mouseup="stopDragging"
|
@mouseup="stopDragging"
|
||||||
@mouseleave="stopDragging"
|
@mouseleave="stopDragging"
|
||||||
@@ -51,6 +55,8 @@
|
|||||||
:value="generateQrCodeUrl()"
|
:value="generateQrCodeUrl()"
|
||||||
:icon="phone"
|
:icon="phone"
|
||||||
:iconSize="iconSize"
|
:iconSize="iconSize"
|
||||||
|
:status="store.status"
|
||||||
|
|
||||||
/>
|
/>
|
||||||
<span class="canvas-qr-text">手机扫码上传</span>
|
<span class="canvas-qr-text">手机扫码上传</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -87,6 +93,11 @@
|
|||||||
</ATooltip>
|
</ATooltip>
|
||||||
</AFlex>
|
</AFlex>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- 图片信息 -->
|
||||||
|
<div class="image-info">
|
||||||
|
<ATag color="cyan" :bordered="false" v-if="store.imageData">修复前: {{ originalImageSize }}</ATag>
|
||||||
|
<ATag color="purple" :bordered="false" v-if="store.processedImg">修复后: {{ processedImageSize }}</ATag>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
@@ -96,6 +107,7 @@ import download from '@/assets/svgs/download.svg';
|
|||||||
import share from '@/assets/svgs/share.svg';
|
import share from '@/assets/svgs/share.svg';
|
||||||
import save from '@/assets/svgs/save.svg';
|
import save from '@/assets/svgs/save.svg';
|
||||||
import deleted from '@/assets/svgs/deleted.svg';
|
import deleted from '@/assets/svgs/deleted.svg';
|
||||||
|
import getImageSizeWithUnit from "@/utils/imageUtils/getImageSizeWithUnit.ts";
|
||||||
|
|
||||||
const canvasContainer = ref<HTMLDivElement | null>(null);
|
const canvasContainer = ref<HTMLDivElement | null>(null);
|
||||||
const dragging = ref<boolean>(false);
|
const dragging = ref<boolean>(false);
|
||||||
@@ -124,6 +136,11 @@ const processedImg = ref<HTMLImageElement>(new Image());
|
|||||||
|
|
||||||
const qrcodeSize = ref<number>(250);
|
const qrcodeSize = ref<number>(250);
|
||||||
const iconSize = ref<number>(30);
|
const iconSize = ref<number>(30);
|
||||||
|
|
||||||
|
const originalImageSize = ref<string>('');
|
||||||
|
const processedImageSize = ref<string>('');
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新二维码大小
|
* 更新二维码大小
|
||||||
*/
|
*/
|
||||||
@@ -140,8 +157,6 @@ function generateQrCodeUrl(): string {
|
|||||||
return import.meta.env.VITE_APP_WEB_URL + "/upscale/app?user_id=" + user.user.uid + "&token=" + user.user.access_token;
|
return import.meta.env.VITE_APP_WEB_URL + "/upscale/app?user_id=" + user.user.uid + "&token=" + user.user.access_token;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(generateQrCodeUrl());
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 下载图片
|
* 下载图片
|
||||||
*/
|
*/
|
||||||
@@ -149,8 +164,22 @@ function downloadImage() {
|
|||||||
if (!store.processedImg) return;
|
if (!store.processedImg) return;
|
||||||
const a = document.createElement("a");
|
const a = document.createElement("a");
|
||||||
a.href = store.processedImg;
|
a.href = store.processedImg;
|
||||||
if (store.hasAlpha) a.download = "output.png";
|
if (store.hasAlpha) a.download = store.model_type +
|
||||||
else a.download = "output.jpg";
|
"_" + store.model +
|
||||||
|
"_" + store.factor +
|
||||||
|
"_" + store.tile_size +
|
||||||
|
"_" + store.min_lap +
|
||||||
|
"_" + store.backend +
|
||||||
|
"_" +
|
||||||
|
"output.png";
|
||||||
|
else a.download = store.model_type +
|
||||||
|
"_" + store.model +
|
||||||
|
"_" + store.factor +
|
||||||
|
"_" + store.tile_size +
|
||||||
|
"_" + store.min_lap +
|
||||||
|
"_" + store.backend +
|
||||||
|
"_" +
|
||||||
|
"output.jpg";
|
||||||
document.body.appendChild(a);
|
document.body.appendChild(a);
|
||||||
a.click();
|
a.click();
|
||||||
document.body.removeChild(a);
|
document.body.removeChild(a);
|
||||||
@@ -529,8 +558,9 @@ watch(
|
|||||||
(newValue) => {
|
(newValue) => {
|
||||||
if (newValue) {
|
if (newValue) {
|
||||||
img.value.src = newValue;
|
img.value.src = newValue;
|
||||||
img.value.onload = () => {
|
img.value.onload = async () => {
|
||||||
initCanvasSize();
|
initCanvasSize();
|
||||||
|
originalImageSize.value = await getImageSizeWithUnit(newValue);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -540,8 +570,9 @@ watch(
|
|||||||
(newValue) => {
|
(newValue) => {
|
||||||
if (newValue) {
|
if (newValue) {
|
||||||
processedImg.value.src = newValue;
|
processedImg.value.src = newValue;
|
||||||
processedImg.value.onload = () => {
|
processedImg.value.onload = async () => {
|
||||||
initCanvasSize();
|
initCanvasSize();
|
||||||
|
processedImageSize.value = await getImageSizeWithUnit(newValue);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -567,6 +598,8 @@ onBeforeUnmount(() => {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
|
border-radius: 10px;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bg {
|
.bg {
|
||||||
@@ -640,6 +673,7 @@ canvas {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
|
border-radius: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.canvas-qr {
|
.canvas-qr {
|
||||||
@@ -708,7 +742,7 @@ canvas {
|
|||||||
.canvas-progressbar-text {
|
.canvas-progressbar-text {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: white;
|
color: #000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
.floating-menu {
|
.floating-menu {
|
||||||
@@ -747,4 +781,22 @@ canvas {
|
|||||||
.menu-icon:hover {
|
.menu-icon:hover {
|
||||||
transform: scale(1.1);
|
transform: scale(1.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.image-info {
|
||||||
|
position: absolute;
|
||||||
|
opacity: 0.8;
|
||||||
|
border-radius: 10px;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
padding: 10px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 10px;
|
||||||
|
align-items: flex-start;
|
||||||
|
transition: all 0.5s ease;
|
||||||
|
user-select: none;
|
||||||
|
z-index: 3;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@@ -4,15 +4,15 @@
|
|||||||
<div class="upscale-params-item-content">
|
<div class="upscale-params-item-content">
|
||||||
<span class="upscale-params-title">类型:</span>
|
<span class="upscale-params-title">类型:</span>
|
||||||
<ASelect style="width: 100%" size="large"
|
<ASelect style="width: 100%" size="large"
|
||||||
v-model:value="model_type"
|
v-model:value="upscale.model_type"
|
||||||
:options="TypeData.map(item => ({label: item, value: item}))">
|
:options="upscale.TypeData.map(item => ({label: item, value: item}))">
|
||||||
</ASelect>
|
</ASelect>
|
||||||
</div>
|
</div>
|
||||||
<div class="upscale-params-item-content">
|
<div class="upscale-params-item-content">
|
||||||
<span class="upscale-params-title">模型:</span>
|
<span class="upscale-params-title">模型:</span>
|
||||||
<ASelect style="width: 100%" size="large"
|
<ASelect style="width: 100%" size="large"
|
||||||
v-model:value="model"
|
v-model:value="upscale.model"
|
||||||
:options="modes.map((item: any) => ({label: item, value: item}))">
|
:options="upscale.modes.map((item: any) => ({label: item, value: item}))">
|
||||||
</ASelect>
|
</ASelect>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -20,16 +20,16 @@
|
|||||||
<div class="upscale-params-item-content">
|
<div class="upscale-params-item-content">
|
||||||
<span class="upscale-params-title">比列:</span>
|
<span class="upscale-params-title">比列:</span>
|
||||||
<ASelect style="width: 100%" size="large"
|
<ASelect style="width: 100%" size="large"
|
||||||
v-model:value="factor"
|
v-model:value="upscale.factor"
|
||||||
:options="scales.map((item: any) => ({label: item, value: item}))">
|
:options="upscale.scales.map((item: any) => ({label: item, value: item}))">
|
||||||
|
|
||||||
</ASelect>
|
</ASelect>
|
||||||
</div>
|
</div>
|
||||||
<div class="upscale-params-item-content">
|
<div class="upscale-params-item-content">
|
||||||
<span class="upscale-params-title">分块大小:</span>
|
<span class="upscale-params-title">分块大小:</span>
|
||||||
<ASelect style="width: 100%" size="large"
|
<ASelect style="width: 100%" size="large"
|
||||||
v-model:value="tile_size"
|
v-model:value="upscale.tile_size"
|
||||||
:options="tileSize.map((item: any) => ({label: item, value: item}))">
|
:options="upscale.tileSize.map((item: any) => ({label: item, value: item}))">
|
||||||
|
|
||||||
</ASelect>
|
</ASelect>
|
||||||
</div>
|
</div>
|
||||||
@@ -38,15 +38,15 @@
|
|||||||
<div class="upscale-params-item-content">
|
<div class="upscale-params-item-content">
|
||||||
<span class="upscale-params-title">重复:</span>
|
<span class="upscale-params-title">重复:</span>
|
||||||
<ASelect style="width: 100%" size="large"
|
<ASelect style="width: 100%" size="large"
|
||||||
v-model:value="min_lap"
|
v-model:value="upscale.min_lap"
|
||||||
:options="overlapList.map((item: any) => ({label: item, value: item}))">
|
:options="upscale.overlapList.map((item: any) => ({label: item, value: item}))">
|
||||||
</ASelect>
|
</ASelect>
|
||||||
</div>
|
</div>
|
||||||
<div class="upscale-params-item-content">
|
<div class="upscale-params-item-content">
|
||||||
<span class="upscale-params-title">运行环境:</span>
|
<span class="upscale-params-title">运行环境:</span>
|
||||||
<ASelect style="width: 100%" size="large"
|
<ASelect style="width: 100%" size="large"
|
||||||
v-model:value="backend"
|
v-model:value="upscale.backend"
|
||||||
:options="backendList.map((item: any) => ({label: item, value: item}))">
|
:options="upscale.backendList.map((item: any) => ({label: item, value: item}))">
|
||||||
</ASelect>
|
</ASelect>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -69,70 +69,6 @@ import useStore from "@/store";
|
|||||||
import run from '@/assets/svgs/run.svg';
|
import run from '@/assets/svgs/run.svg';
|
||||||
|
|
||||||
const upscale = useStore().upscale;
|
const upscale = useStore().upscale;
|
||||||
// ***************参数设置***************
|
|
||||||
const TypeData = ['realesrgan', 'realcugan'];
|
|
||||||
|
|
||||||
const model_type = ref<string>(TypeData[0]);
|
|
||||||
|
|
||||||
const ModelConfig = reactive({
|
|
||||||
realesrgan: {
|
|
||||||
model: ["anime_fast", "anime_plus", "general_fast", "general_plus"],
|
|
||||||
factor: [4],
|
|
||||||
tile_size: [32, 48, 64, 96, 128, 192, 256],
|
|
||||||
},
|
|
||||||
realcugan: {
|
|
||||||
factor: [2, 4],
|
|
||||||
denoise: {
|
|
||||||
2: [
|
|
||||||
"conservative",
|
|
||||||
"no-denoise",
|
|
||||||
"denoise1x",
|
|
||||||
"denoise2x",
|
|
||||||
"denoise3x",
|
|
||||||
],
|
|
||||||
3: ["conservative", "denoise3x"],
|
|
||||||
4: ["conservative", "no-denoise", "denoise3x"],
|
|
||||||
},
|
|
||||||
tile_size: [32, 48, 64, 96, 128, 192, 256, 384, 512],
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const factor = ref<number>(4);
|
|
||||||
const model = ref(ModelConfig[model_type.value].model[0]);
|
|
||||||
const modes = computed(() => {
|
|
||||||
if (model_type.value === "realesrgan") {
|
|
||||||
return ModelConfig[model_type.value].model;
|
|
||||||
} else {
|
|
||||||
return ModelConfig[model_type.value].denoise[factor.value];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
watch(model_type, val => {
|
|
||||||
if (model_type.value === "realesrgan") {
|
|
||||||
model.value = ModelConfig[val].model[0];
|
|
||||||
} else {
|
|
||||||
model.value = ModelConfig[val].denoise[factor.value][0];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
// Scale
|
|
||||||
const scales = computed(() => {
|
|
||||||
return ModelConfig[model_type.value].factor;
|
|
||||||
});
|
|
||||||
|
|
||||||
//tile size
|
|
||||||
const tile_size = ref<number>(128);
|
|
||||||
const tileSize = computed(() => {
|
|
||||||
return ModelConfig[model_type.value].tile_size;
|
|
||||||
});
|
|
||||||
|
|
||||||
// overlap
|
|
||||||
const overlapList = [0, 4, 8, 12, 16, 20];
|
|
||||||
const min_lap = ref<number>(overlapList[3]);
|
|
||||||
|
|
||||||
// run on
|
|
||||||
const backendList = ['webgl', 'webgpu'];
|
|
||||||
const backend = ref<string>(backendList[0]);
|
|
||||||
|
|
||||||
// ********************处理图片*******************
|
// ********************处理图片*******************
|
||||||
const outputData = ref<any>();
|
const outputData = ref<any>();
|
||||||
@@ -166,8 +102,8 @@ async function startTask() {
|
|||||||
if (!upscale.hasAlpha || (upscale.hasAlpha && upscale.inputAlpha)) {
|
if (!upscale.hasAlpha || (upscale.hasAlpha && upscale.inputAlpha)) {
|
||||||
if (upscale.input) {
|
if (upscale.input) {
|
||||||
outputData.value = new Img(
|
outputData.value = new Img(
|
||||||
factor.value * upscale.input.width,
|
upscale.factor * upscale.input.width,
|
||||||
factor.value * upscale.input.height,
|
upscale.factor * upscale.input.height,
|
||||||
new Uint8Array(output)
|
new Uint8Array(output)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -177,14 +113,14 @@ async function startTask() {
|
|||||||
worker.postMessage(
|
worker.postMessage(
|
||||||
{
|
{
|
||||||
input: upscale.inputAlpha.data.buffer,
|
input: upscale.inputAlpha.data.buffer,
|
||||||
factor: factor.value,
|
factor: upscale.factor,
|
||||||
tile_size: tile_size.value,
|
tile_size: upscale.tile_size,
|
||||||
min_lap: min_lap.value,
|
min_lap: upscale.min_lap,
|
||||||
model_type: model_type.value,
|
model_type: upscale.model_type,
|
||||||
width: upscale.inputAlpha.width,
|
width: upscale.inputAlpha.width,
|
||||||
height: upscale.inputAlpha.height,
|
height: upscale.inputAlpha.height,
|
||||||
model: model.value,
|
model: upscale.model,
|
||||||
backend: backend.value,
|
backend: upscale.backend,
|
||||||
hasAlpha: true,
|
hasAlpha: true,
|
||||||
},
|
},
|
||||||
[upscale.inputAlpha.data.buffer]
|
[upscale.inputAlpha.data.buffer]
|
||||||
@@ -247,14 +183,14 @@ async function startTask() {
|
|||||||
worker.postMessage(
|
worker.postMessage(
|
||||||
{
|
{
|
||||||
input: upscale.input.data.buffer,
|
input: upscale.input.data.buffer,
|
||||||
factor: factor.value,
|
factor: upscale.factor,
|
||||||
tile_size: tile_size.value,
|
tile_size: upscale.tile_size,
|
||||||
min_lap: min_lap.value,
|
min_lap: upscale.min_lap,
|
||||||
model_type: model_type.value,
|
model_type: upscale.model_type,
|
||||||
width: upscale.input.width,
|
width: upscale.input.width,
|
||||||
height: upscale.input.height,
|
height: upscale.input.height,
|
||||||
model: model.value,
|
model: upscale.model,
|
||||||
backend: backend.value,
|
backend: upscale.backend,
|
||||||
hasAlpha: false,
|
hasAlpha: false,
|
||||||
},
|
},
|
||||||
[upscale.input.data.buffer]
|
[upscale.input.data.buffer]
|
||||||
|
@@ -13,7 +13,7 @@
|
|||||||
</ACard>
|
</ACard>
|
||||||
</div>
|
</div>
|
||||||
<div class="upscale-content-right">
|
<div class="upscale-content-right">
|
||||||
<CompareImage style="border-radius: 10px"/>
|
<CompareImage/>
|
||||||
</div>
|
</div>
|
||||||
</AFlex>
|
</AFlex>
|
||||||
</div>
|
</div>
|
||||||
@@ -35,7 +35,7 @@ const wsOptions = {
|
|||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
websocket.initialize(wsOptions);
|
websocket.initialize(wsOptions);
|
||||||
websocket.on("message", async (res: any) => {
|
websocket.on("message", async (res: any) => {
|
||||||
if (res && res && res.code === 200) {
|
if (res && res.code === 200) {
|
||||||
const {data} = res;
|
const {data} = res;
|
||||||
img.src = data;
|
img.src = data;
|
||||||
await upscale.loadImg(img);
|
await upscale.loadImg(img);
|
||||||
@@ -43,7 +43,16 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
watch(
|
||||||
|
() => websocket.readyState,
|
||||||
|
(newStatus) => {
|
||||||
|
if (newStatus === WebSocket.OPEN) {
|
||||||
|
upscale.status = 'active';
|
||||||
|
} else {
|
||||||
|
upscale.status = 'loading';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
websocket.close(false);
|
websocket.close(false);
|
||||||
});
|
});
|
||||||
@@ -87,7 +96,7 @@ onUnmounted(() => {
|
|||||||
.upscale-content-right {
|
.upscale-content-right {
|
||||||
width: 70%;
|
width: 70%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
border-radius: 10px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -236,10 +236,6 @@ self.onmessage = async function (e: MessageEvent): Promise<void> {
|
|||||||
output.cropToOriginalSize(width_ori * factor, height_ori * factor);
|
output.cropToOriginalSize(width_ori * factor, height_ori * factor);
|
||||||
}
|
}
|
||||||
await new Promise((resolve) => setTimeout(resolve, 10));
|
await new Promise((resolve) => setTimeout(resolve, 10));
|
||||||
self.postMessage({
|
|
||||||
progress: 100,
|
|
||||||
info: `Processing image...`,
|
|
||||||
});
|
|
||||||
self.postMessage(
|
self.postMessage(
|
||||||
{
|
{
|
||||||
progress: 100,
|
progress: 100,
|
||||||
|
Reference in New Issue
Block a user