mirror of
https://github.com/xiaoyiweb/YiAi.git
synced 2025-11-14 21:23:44 +08:00
2.5版本 增加dall-e 优化mj 对接mj-plus
This commit is contained in:
@@ -5,11 +5,11 @@ const path = require('path')
|
||||
function configureAppMenu(mainWindow) {
|
||||
|
||||
let tray = new Tray(path.join(__dirname, '../icons/16x16.png'));
|
||||
// tray.setToolTip('Nine Ai');
|
||||
// tray.setToolTip('YiAi Ai');
|
||||
|
||||
const template = [
|
||||
{
|
||||
label: 'NineAi',
|
||||
label: 'YiAi',
|
||||
submenu: [
|
||||
{
|
||||
label: '退出应用',
|
||||
|
||||
@@ -26,7 +26,7 @@ function createMainWindow() {
|
||||
|
||||
if (app.isPackaged) {
|
||||
// mainWindow.loadFile(filePath)
|
||||
mainWindow.loadURL('https://ai.jiangly.com')
|
||||
// mainWindow.loadURL('https://ai.jiangly.com')
|
||||
}
|
||||
else {
|
||||
mainWindow.loadURL('http://127.0.0.1:1002')
|
||||
|
||||
@@ -190,6 +190,11 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(
|
||||
"%c本项目作者----小易,联系QQ:805239273",
|
||||
"background-color:rgb(30,30,30);border-radius:4px;font-size:12px;padding:4px;color:rgb(220,208,129);"
|
||||
)
|
||||
</script>
|
||||
</body>
|
||||
|
||||
|
||||
@@ -1,106 +1,106 @@
|
||||
{
|
||||
"name": "chatgpt-cooper",
|
||||
"version": "2.3.0",
|
||||
"private": true,
|
||||
"description": "ChatGPT Cooper",
|
||||
"author": "Snine <J_longyan@163.com>",
|
||||
"keywords": [
|
||||
"chatgpt-cooper",
|
||||
"chatgpt",
|
||||
"chatbot",
|
||||
"vue",
|
||||
"nestjs"
|
||||
],
|
||||
"main": "electron/main.js",
|
||||
"scripts": {
|
||||
"start:h": "pnpm run -C service dev",
|
||||
"start:f": "vite",
|
||||
"all": "npm-run-all --parallel start:h start:f",
|
||||
"dev": "vite",
|
||||
"build-check": "run-p type-check build-only",
|
||||
"preview": "vite preview",
|
||||
"build": "vite build --mode=production",
|
||||
"type-check": "vue-tsc --noEmit",
|
||||
"lint": "eslint .",
|
||||
"lint:fix": "eslint . --fix",
|
||||
"bootstrap": "pnpm install && pnpm run common:prepare",
|
||||
"start": "pnpm dev && electron .",
|
||||
"ele": "electron .",
|
||||
"common:cleanup": "rimraf node_modules && rimraf pnpm-lock.yaml",
|
||||
"pack:mac": "NPM_CONFIG_ELECTRON_MIRROR=http://npm.taobao.org/mirrors/electron/ electron-builder build --mac",
|
||||
"pack:win": "NPM_CONFIG_ELECTRON_MIRROR=http://npm.taobao.org/mirrors/electron/ electron-builder build --win --ia32"
|
||||
},
|
||||
"dependencies": {
|
||||
"@electron/remote": "^2.1.0",
|
||||
"@icon-park/vue-next": "^1.4.2",
|
||||
"@traptitech/markdown-it-katex": "^3.6.0",
|
||||
"@types/dom-to-image": "^2.6.4",
|
||||
"@types/file-saver": "^2.0.5",
|
||||
"@vicons/ionicons5": "^0.12.0",
|
||||
"@vueuse/core": "^9.13.0",
|
||||
"@vueuse/electron": "^10.2.1",
|
||||
"@vueuse/integrations": "^10.2.0",
|
||||
"@vueuse/motion": "^2.0.0",
|
||||
"add": "^2.0.6",
|
||||
"clientjs": "^0.2.1",
|
||||
"date-fns": "^2.30.0",
|
||||
"dom-to-image": "^2.6.0",
|
||||
"file-saver": "^2.0.5",
|
||||
"highlight.js": "^11.7.0",
|
||||
"html-to-image": "^1.11.11",
|
||||
"html2canvas": "^1.4.1",
|
||||
"katex": "^0.16.4",
|
||||
"markdown-it": "^13.0.1",
|
||||
"marked": "^4.3.0",
|
||||
"markmap-common": "0.14.2",
|
||||
"markmap-lib": "0.14.4",
|
||||
"markmap-view": "0.14.4",
|
||||
"naive-ui": "^2.34.3",
|
||||
"pinia": "^2.0.33",
|
||||
"qrcode": "^1.5.3",
|
||||
"v-viewer": "3.0.11",
|
||||
"vue": "^3.2.47",
|
||||
"vue-clipboard3": "^2.0.0",
|
||||
"vue-i18n": "^9.2.2",
|
||||
"vue-router": "^4.1.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@antfu/eslint-config": "^0.35.3",
|
||||
"@commitlint/cli": "^17.4.4",
|
||||
"@commitlint/config-conventional": "^17.4.4",
|
||||
"@iconify/vue": "^4.1.0",
|
||||
"@types/crypto-js": "^4.1.1",
|
||||
"@types/katex": "^0.16.0",
|
||||
"@types/markdown-it": "^12.2.3",
|
||||
"@types/markdown-it-link-attributes": "^3.0.1",
|
||||
"@types/node": "^18.14.6",
|
||||
"@vitejs/plugin-vue": "^4.0.0",
|
||||
"autoprefixer": "^10.4.13",
|
||||
"axios": "^1.3.4",
|
||||
"crypto-js": "^4.1.1",
|
||||
"electron": "^25.3.1",
|
||||
"electron-builder": "^24.4.0",
|
||||
"eslint": "^8.35.0",
|
||||
"husky": "^8.0.3",
|
||||
"less": "^4.1.3",
|
||||
"lint-staged": "^13.1.2",
|
||||
"markdown-it-link-attributes": "^4.0.1",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"postcss": "^8.4.21",
|
||||
"rimraf": "^4.2.0",
|
||||
"tailwindcss": "^3.2.7",
|
||||
"typescript": "~4.9.5",
|
||||
"vite": "^4.2.0",
|
||||
"vite-plugin-pwa": "^0.14.4",
|
||||
"vue-tsc": "^1.2.0"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{ts,tsx,vue}": [
|
||||
"pnpm lint:fix"
|
||||
]
|
||||
},
|
||||
"build": {
|
||||
"productName": "NineAi",
|
||||
"name": "chatgpt-cooper",
|
||||
"version": "2.5.0",
|
||||
"private": true,
|
||||
"description": "ChatGPT Cooper",
|
||||
"author": "Yi <a8052@qq.com>",
|
||||
"keywords": [
|
||||
"chatgpt-cooper",
|
||||
"chatgpt",
|
||||
"chatbot",
|
||||
"vue",
|
||||
"nestjs"
|
||||
],
|
||||
"main": "electron/main.js",
|
||||
"scripts": {
|
||||
"start:h": "pnpm run -C service dev",
|
||||
"start:f": "vite",
|
||||
"all": "npm-run-all --parallel start:h start:f",
|
||||
"dev": "vite",
|
||||
"build-check": "run-p type-check build-only",
|
||||
"preview": "vite preview",
|
||||
"build": "vite build --mode=production",
|
||||
"type-check": "vue-tsc --noEmit",
|
||||
"lint": "eslint .",
|
||||
"lint:fix": "eslint . --fix",
|
||||
"bootstrap": "pnpm install && pnpm run common:prepare",
|
||||
"start": "pnpm dev && electron .",
|
||||
"ele": "electron .",
|
||||
"common:cleanup": "rimraf node_modules && rimraf pnpm-lock.yaml",
|
||||
"pack:mac": "NPM_CONFIG_ELECTRON_MIRROR=http://npm.taobao.org/mirrors/electron/ electron-builder build --mac",
|
||||
"pack:win": "NPM_CONFIG_ELECTRON_MIRROR=http://npm.taobao.org/mirrors/electron/ electron-builder build --win --ia32"
|
||||
},
|
||||
"dependencies": {
|
||||
"@electron/remote": "^2.1.0",
|
||||
"@icon-park/vue-next": "^1.4.2",
|
||||
"@traptitech/markdown-it-katex": "^3.6.0",
|
||||
"@types/dom-to-image": "^2.6.4",
|
||||
"@types/file-saver": "^2.0.5",
|
||||
"@vicons/ionicons5": "^0.12.0",
|
||||
"@vueuse/core": "^9.13.0",
|
||||
"@vueuse/electron": "^10.2.1",
|
||||
"@vueuse/integrations": "^10.2.0",
|
||||
"@vueuse/motion": "^2.0.0",
|
||||
"add": "^2.0.6",
|
||||
"clientjs": "^0.2.1",
|
||||
"date-fns": "^2.30.0",
|
||||
"dom-to-image": "^2.6.0",
|
||||
"file-saver": "^2.0.5",
|
||||
"highlight.js": "^11.7.0",
|
||||
"html-to-image": "^1.11.11",
|
||||
"html2canvas": "^1.4.1",
|
||||
"katex": "^0.16.4",
|
||||
"markdown-it": "^13.0.1",
|
||||
"marked": "^4.3.0",
|
||||
"markmap-common": "0.14.2",
|
||||
"markmap-lib": "0.14.4",
|
||||
"markmap-view": "0.14.4",
|
||||
"naive-ui": "^2.37.3",
|
||||
"pinia": "^2.0.33",
|
||||
"qrcode": "^1.5.3",
|
||||
"v-viewer": "3.0.11",
|
||||
"vue": "^3.2.47",
|
||||
"vue-clipboard3": "^2.0.0",
|
||||
"vue-i18n": "^9.2.2",
|
||||
"vue-router": "^4.1.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@antfu/eslint-config": "^0.35.3",
|
||||
"@commitlint/cli": "^17.4.4",
|
||||
"@commitlint/config-conventional": "^17.4.4",
|
||||
"@iconify/vue": "^4.1.0",
|
||||
"@types/crypto-js": "^4.1.1",
|
||||
"@types/katex": "^0.16.0",
|
||||
"@types/markdown-it": "^12.2.3",
|
||||
"@types/markdown-it-link-attributes": "^3.0.1",
|
||||
"@types/node": "^18.14.6",
|
||||
"@vitejs/plugin-vue": "^4.0.0",
|
||||
"autoprefixer": "^10.4.13",
|
||||
"axios": "^1.3.4",
|
||||
"crypto-js": "^4.1.1",
|
||||
"electron": "^25.3.1",
|
||||
"electron-builder": "^24.4.0",
|
||||
"eslint": "^8.35.0",
|
||||
"husky": "^8.0.3",
|
||||
"less": "^4.1.3",
|
||||
"lint-staged": "^13.1.2",
|
||||
"markdown-it-link-attributes": "^4.0.1",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"postcss": "^8.4.21",
|
||||
"rimraf": "^4.2.0",
|
||||
"tailwindcss": "^3.2.7",
|
||||
"typescript": "~4.9.5",
|
||||
"vite": "^4.2.0",
|
||||
"vite-plugin-pwa": "^0.14.4",
|
||||
"vue-tsc": "^1.2.0"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{ts,tsx,vue}": [
|
||||
"pnpm lint:fix"
|
||||
]
|
||||
},
|
||||
"build": {
|
||||
"productName": "Yiai",
|
||||
"appId": "ai.jiangly.com",
|
||||
"icon": "icons/icon.icns",
|
||||
"directories": {
|
||||
|
||||
@@ -1,165 +1,223 @@
|
||||
import type { AxiosProgressEvent, GenericAbortSignal } from 'axios'
|
||||
import { get, post } from '@/utils/request'
|
||||
import { useSettingStore } from '@/store'
|
||||
import type { AxiosProgressEvent, GenericAbortSignal } from "axios";
|
||||
import { get, post } from "@/utils/request";
|
||||
import { useSettingStore } from "@/store";
|
||||
|
||||
/* 流失对话聊天 */
|
||||
export function fetchChatAPIProcess<T = any>(
|
||||
params: {
|
||||
prompt: string
|
||||
appId?: number
|
||||
options?: { conversationId?: string; parentMessageId?: string; temperature: number }
|
||||
imageUrl?:string
|
||||
model?:string
|
||||
signal?: GenericAbortSignal
|
||||
onDownloadProgress?: (progressEvent: AxiosProgressEvent) => void },
|
||||
) {
|
||||
return post<T>({
|
||||
url: '/chatgpt/chat-process',
|
||||
data: { prompt: params.prompt, appId: params?.appId, options: params.options,imageUrl: params.imageUrl,model: params.model},
|
||||
signal: params.signal,
|
||||
onDownloadProgress: params.onDownloadProgress,
|
||||
})
|
||||
export function fetchChatAPIProcess<T = any>(params: {
|
||||
prompt: string;
|
||||
appId?: number;
|
||||
options?: {
|
||||
conversationId?: string;
|
||||
parentMessageId?: string;
|
||||
temperature: number;
|
||||
};
|
||||
imageUrl?: string;
|
||||
model?: string;
|
||||
signal?: GenericAbortSignal;
|
||||
onDownloadProgress?: (progressEvent: AxiosProgressEvent) => void;
|
||||
}) {
|
||||
return post<T>({
|
||||
url: "/chatgpt/chat-process",
|
||||
data: {
|
||||
prompt: params.prompt,
|
||||
appId: params?.appId,
|
||||
options: params.options,
|
||||
imageUrl: params.imageUrl,
|
||||
model: params.model,
|
||||
},
|
||||
signal: params.signal,
|
||||
onDownloadProgress: params.onDownloadProgress,
|
||||
});
|
||||
}
|
||||
|
||||
/* 获取个人信息 */
|
||||
export function fetchGetInfo<T>() {
|
||||
return get<T>({ url: '/auth/getInfo' })
|
||||
return get<T>({ url: "/auth/getInfo" });
|
||||
}
|
||||
|
||||
/* 注册 */
|
||||
export function fetchRegisterAPI<T>(data: { username: string;password: string;email: string }): Promise<T> {
|
||||
return post<T>({ url: '/auth/register', data }) as Promise<T>
|
||||
export function fetchRegisterAPI<T>(data: {
|
||||
username: string;
|
||||
password: string;
|
||||
email: string;
|
||||
}): Promise<T> {
|
||||
return post<T>({ url: "/auth/register", data }) as Promise<T>;
|
||||
}
|
||||
|
||||
/* 注册 */
|
||||
export function fetchRegisterByPhoneAPI<T>(data: { username: string;password: string; phone: string; phoneCode: string }): Promise<T> {
|
||||
return post<T>({ url: '/auth/registerByPhone', data }) as Promise<T>
|
||||
export function fetchRegisterByPhoneAPI<T>(data: {
|
||||
username: string;
|
||||
password: string;
|
||||
phone: string;
|
||||
phoneCode: string;
|
||||
}): Promise<T> {
|
||||
return post<T>({ url: "/auth/registerByPhone", data }) as Promise<T>;
|
||||
}
|
||||
|
||||
/* 登录 */
|
||||
export function fetchLoginAPI<T>(data: { username: string; password: string }): Promise<T> {
|
||||
return post<T>({ url: '/auth/login', data }) as Promise<T>
|
||||
export function fetchLoginAPI<T>(data: {
|
||||
username: string;
|
||||
password: string;
|
||||
}): Promise<T> {
|
||||
return post<T>({ url: "/auth/login", data }) as Promise<T>;
|
||||
}
|
||||
|
||||
/* 手机号登录 */
|
||||
export function fetchLoginByPhoneAPI<T>(data: { phone: string; password: string }): Promise<T> {
|
||||
return post<T>({ url: '/auth/loginByPhone', data }) as Promise<T>
|
||||
export function fetchLoginByPhoneAPI<T>(data: {
|
||||
phone: string;
|
||||
password: string;
|
||||
}): Promise<T> {
|
||||
return post<T>({ url: "/auth/loginByPhone", data }) as Promise<T>;
|
||||
}
|
||||
|
||||
/* 修改个人信息 */
|
||||
export function fetchUpdateInfoAPI<T>(data: { username?: string; avatar?: string }): Promise<T> {
|
||||
return post<T>({ url: '/user/update', data }) as Promise<T>
|
||||
export function fetchUpdateInfoAPI<T>(data: {
|
||||
username?: string;
|
||||
avatar?: string;
|
||||
}): Promise<T> {
|
||||
return post<T>({ url: "/user/update", data }) as Promise<T>;
|
||||
}
|
||||
|
||||
/* 获取个人绘画记录 */
|
||||
export function fetchGetChatLogDraw<T>(data: { model: string }): Promise<T> {
|
||||
return get<T>({ url: '/chatLog/draw', data }) as Promise<T>
|
||||
return get<T>({ url: "/chatLog/draw", data }) as Promise<T>;
|
||||
}
|
||||
|
||||
/* 获取所有绘画记录 */
|
||||
export function fetchGetAllChatLogDraw<T>(data: { size: number; rec: number; model: string }): Promise<T> {
|
||||
return get<T>({ url: '/chatLog/drawAll', data }) as Promise<T>
|
||||
export function fetchGetAllChatLogDraw<T>(data: {
|
||||
size: number;
|
||||
rec: number;
|
||||
model: string;
|
||||
}): Promise<T> {
|
||||
return get<T>({ url: "/chatLog/drawAll", data }) as Promise<T>;
|
||||
}
|
||||
|
||||
/* chatgpt的dall-e2绘画 */
|
||||
export function fetchChatDraw<T>(data: { prompt: string;n: number;size: string }): Promise<T> {
|
||||
return post<T>({ url: '/chatgpt/chat-draw', data }) as Promise<T>
|
||||
export function fetchChatDraw<T>(data: {
|
||||
prompt: string;
|
||||
n: number;
|
||||
size: string;
|
||||
}): Promise<T> {
|
||||
return post<T>({ url: "/chatgpt/chat-draw", data }) as Promise<T>;
|
||||
}
|
||||
|
||||
/* 修改密码 */
|
||||
export function fetchUpdatePasswordAPI<T>(data: { oldPassword?: string;password?: string }): Promise<T> {
|
||||
return post<T>({ url: '/auth/updatePassword', data }) as Promise<T>
|
||||
export function fetchUpdatePasswordAPI<T>(data: {
|
||||
oldPassword?: string;
|
||||
password?: string;
|
||||
}): Promise<T> {
|
||||
return post<T>({ url: "/auth/updatePassword", data }) as Promise<T>;
|
||||
}
|
||||
|
||||
/* 同步对话 */
|
||||
export function fetchGetchatSyncApi<T = any>(
|
||||
params: {
|
||||
prompt: string
|
||||
options?: { conversationId?: string; parentMessageId?: string; temperature: number }
|
||||
signal?: GenericAbortSignal
|
||||
onDownloadProgress?: (progressEvent: AxiosProgressEvent) => void },
|
||||
) {
|
||||
return post<T>({
|
||||
url: '/chatgpt/chat-sync',
|
||||
data: { prompt: params.prompt, options: params.options },
|
||||
signal: params.signal,
|
||||
onDownloadProgress: params.onDownloadProgress,
|
||||
})
|
||||
export function fetchGetchatSyncApi<T = any>(params: {
|
||||
prompt: string;
|
||||
options?: {
|
||||
conversationId?: string;
|
||||
parentMessageId?: string;
|
||||
temperature: number;
|
||||
};
|
||||
signal?: GenericAbortSignal;
|
||||
onDownloadProgress?: (progressEvent: AxiosProgressEvent) => void;
|
||||
}) {
|
||||
return post<T>({
|
||||
url: "/chatgpt/chat-sync",
|
||||
data: { prompt: params.prompt, options: params.options },
|
||||
signal: params.signal,
|
||||
onDownloadProgress: params.onDownloadProgress,
|
||||
});
|
||||
}
|
||||
|
||||
/* 获取mind绘画联想词 */
|
||||
export function fetchGetchatMindApi<T = any>(
|
||||
params: {
|
||||
prompt: string
|
||||
options?: { conversationId?: string; parentMessageId?: string; temperature: number }
|
||||
signal?: GenericAbortSignal
|
||||
onDownloadProgress?: (progressEvent: AxiosProgressEvent) => void },
|
||||
) {
|
||||
return post<T>({
|
||||
url: '/chatgpt/chat-mind',
|
||||
data: { prompt: params.prompt, options: params.options },
|
||||
signal: params.signal,
|
||||
onDownloadProgress: params.onDownloadProgress,
|
||||
})
|
||||
export function fetchGetchatMindApi<T = any>(params: {
|
||||
prompt: string;
|
||||
options?: {
|
||||
conversationId?: string;
|
||||
parentMessageId?: string;
|
||||
temperature: number;
|
||||
};
|
||||
signal?: GenericAbortSignal;
|
||||
onDownloadProgress?: (progressEvent: AxiosProgressEvent) => void;
|
||||
}) {
|
||||
return post<T>({
|
||||
url: "/chatgpt/chat-mind",
|
||||
data: { prompt: params.prompt, options: params.options },
|
||||
signal: params.signal,
|
||||
onDownloadProgress: params.onDownloadProgress,
|
||||
});
|
||||
}
|
||||
|
||||
/* 获取MJ绘画联想词 */
|
||||
export function fetchGetMjPromptAssociateApi<T>(data: { prompt: string }): Promise<T> {
|
||||
return post<T>({ url: '/chatgpt/mj-associate', data }) as Promise<T>
|
||||
export function fetchGetMjPromptAssociateApi<T>(data: {
|
||||
prompt: string;
|
||||
}): Promise<T> {
|
||||
return post<T>({ url: "/chatgpt/mj-associate", data }) as Promise<T>;
|
||||
}
|
||||
|
||||
/* 获取MJ绘画联想词 */
|
||||
export function fetchGetMjPromptFanyiApi<T>(data: { prompt: string }): Promise<T> {
|
||||
return post<T>({ url: '/chatgpt/mj-fy', data }) as Promise<T>
|
||||
export function fetchGetMjPromptFanyiApi<T>(data: {
|
||||
prompt: string;
|
||||
}): Promise<T> {
|
||||
return post<T>({ url: "/chatgpt/mj-fy", data }) as Promise<T>;
|
||||
}
|
||||
|
||||
/* 获取我得绘制列表 */
|
||||
export function fetchMidjourneyDrawList<T>(data: { page?: number; size?: number }): Promise<T> {
|
||||
return get<T>({ url: '/midjourney/drawList', data }) as Promise<T>
|
||||
export function fetchMidjourneyDrawList<T>(data: {
|
||||
page?: number;
|
||||
size?: number;
|
||||
}): Promise<T> {
|
||||
return get<T>({ url: "/midjourney/drawList", data }) as Promise<T>;
|
||||
}
|
||||
|
||||
/* 获取Mj提示词 */
|
||||
export function fetchMidjourneyPromptList<T>(): Promise<T> {
|
||||
return get<T>({ url: '/midjourney/queryPrompts' }) as Promise<T>
|
||||
return get<T>({ url: "/midjourney/queryPrompts" }) as Promise<T>;
|
||||
}
|
||||
|
||||
/* 获取Mj完整提示词 */
|
||||
export function fetchMidjourneyFullPrompt<T>(data: any): Promise<T> {
|
||||
return get<T>({ url: '/midjourney/getFullPrompt', data }) as Promise<T>
|
||||
return get<T>({ url: "/midjourney/getFullPrompt", data }) as Promise<T>;
|
||||
}
|
||||
|
||||
/* 删除MJ绘画记录 */
|
||||
export function fetchDownloadImg<T>(data: { id: number }): Promise<T> {
|
||||
return post<T>({ url: '/midjourney/delete', data }) as Promise<T>
|
||||
return post<T>({ url: "/midjourney/delete", data }) as Promise<T>;
|
||||
}
|
||||
|
||||
/* 获取我得绘制列表 */
|
||||
export function fetchMidjourneyGetList<T>(data: { page?: number; size?: number; rec: number }): Promise<T> {
|
||||
return get<T>({ url: '/midjourney/getList', data }) as Promise<T>
|
||||
export function fetchMidjourneyGetList<T>(data: {
|
||||
page?: number;
|
||||
size?: number;
|
||||
rec: number;
|
||||
}): Promise<T> {
|
||||
return get<T>({ url: "/midjourney/getList", data }) as Promise<T>;
|
||||
}
|
||||
|
||||
/* 推荐图片 */
|
||||
export function fetchRecDraw<T>(data: { id: number }): Promise<T> {
|
||||
return post<T>({ url: '/midjourney/rec', data }) as Promise<T>
|
||||
return post<T>({ url: "/midjourney/rec", data }) as Promise<T>;
|
||||
}
|
||||
|
||||
/* 获取图片验证码 */
|
||||
export function fetchCaptchaImg<T>(data: { color: string }): Promise<T> {
|
||||
return post<T>({ url: '/auth/captcha', data }) as Promise<T>
|
||||
return post<T>({ url: "/auth/captcha", data }) as Promise<T>;
|
||||
}
|
||||
|
||||
/* 发送手机验证码 */
|
||||
export function fetchSendSms<T>(data: { phone: string; captchaId: string; captchaCode: string }): Promise<T> {
|
||||
return post<T>({ url: '/auth/sendPhoneCode', data }) as Promise<T>
|
||||
export function fetchSendSms<T>(data: {
|
||||
phone: string;
|
||||
captchaId: string;
|
||||
captchaCode: string;
|
||||
}): Promise<T> {
|
||||
return post<T>({ url: "/auth/sendPhoneCode", data }) as Promise<T>;
|
||||
}
|
||||
|
||||
/* 获取九宫格设置 */
|
||||
export function fetchGetChatBoxList<T>() {
|
||||
return get<T>({ url: '/chatgpt/queryChatBoxFrontend' })
|
||||
return get<T>({ url: "/chatgpt/queryChatBoxFrontend" });
|
||||
}
|
||||
|
||||
|
||||
/* 获取快问设置 */
|
||||
export function fetchGetChatPreList<T>() {
|
||||
return get<T>({ url: '/chatgpt/queryChatPreList' })
|
||||
return get<T>({ url: "/chatgpt/queryChatPreList" });
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ export function fetchTranslateAPI<T>(data: { text: string }): Promise<T> {
|
||||
}
|
||||
|
||||
/* 提交一个绘画任务 */
|
||||
export function fetchDrawTaskAPI<T>(data: { prompt?: string; imgUrl?: string; extraParam?: string; drawId?: number; action?: number; orderId?: number }): Promise<T> {
|
||||
export function fetchDrawTaskAPI<T>(data: { prompt?: string; imgUrl?: string; extraParam?: string; drawId?: number; action?: string; orderId?: number }): Promise<T> {
|
||||
return post<T>({
|
||||
url: '/queue/addMjDrawQueue',
|
||||
data,
|
||||
@@ -45,8 +45,8 @@ export function fetchProxyImgAPI<T>(data: { url: string }): Promise<T> {
|
||||
return get<T>({
|
||||
url: '/midjourney/proxy',
|
||||
data,
|
||||
headers: {
|
||||
responseType: 'arraybuffer'
|
||||
}
|
||||
headers: {
|
||||
responseType: 'arraybuffer'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
BIN
chat/src/assets/voice.gif
Normal file
BIN
chat/src/assets/voice.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
@@ -6,20 +6,23 @@ const props = withDefaults(defineProps<Props>(), {
|
||||
gap: 10,
|
||||
progress: 0,
|
||||
tips: '',
|
||||
words: ['L', 'O', 'A', 'D', 'I', 'N', 'G']
|
||||
// words: ['L', 'O', 'A', 'D', 'I', 'N', 'G']
|
||||
words: ['AI', '绘', '画', '中'],
|
||||
})
|
||||
|
||||
const appStore = useAppStore()
|
||||
|
||||
const theme = computed(() => appStore.theme)
|
||||
const loadingTextColor = computed(() => theme.value === 'dark' ? '#fff' : '#000')
|
||||
const loadingTextColor = computed(() =>
|
||||
theme.value === 'dark' ? '#fff' : '#000'
|
||||
)
|
||||
|
||||
interface Props {
|
||||
gap?: number
|
||||
progress?: number
|
||||
tips?: string
|
||||
bgColor?: string
|
||||
words?: any
|
||||
words?: any
|
||||
}
|
||||
// const words = ref<string[]>(['L', 'O', 'A', 'D', 'I', 'N', 'G'])
|
||||
</script>
|
||||
@@ -27,7 +30,13 @@ interface Props {
|
||||
<template>
|
||||
<div class="loading" :style="{ background: props.bgColor }">
|
||||
<div class="loading-text">
|
||||
<span v-for="item in props.words" :key="item" :style="{ margin: `0 ${props.gap}px`, color: loadingTextColor }" class="loading-text-words">{{ item }}</span>
|
||||
<span
|
||||
v-for="item in props.words"
|
||||
:key="item"
|
||||
:style="{ margin: `0 ${props.gap}px`, color: loadingTextColor }"
|
||||
class="loading-text-words"
|
||||
>{{ item }}</span
|
||||
>
|
||||
</div>
|
||||
<div v-if="!tips && props.progress" class="progress">
|
||||
绘制进度: {{ props.progress }}%
|
||||
@@ -46,14 +55,14 @@ interface Props {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 100;
|
||||
user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.progress{
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
.progress {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
.loading-text {
|
||||
@@ -72,42 +81,42 @@ interface Props {
|
||||
display: inline-block;
|
||||
margin: 0 5px;
|
||||
color: #fff;
|
||||
font-family: "Quattrocento Sans", sans-serif;
|
||||
font-family: 'Quattrocento Sans', sans-serif;
|
||||
}
|
||||
.loading-text span:nth-child(1) {
|
||||
filter: blur(0px);
|
||||
-webkit-animation: blur-text 1.5s 0s infinite linear alternate;
|
||||
animation: blur-text 1.5s 0s infinite linear alternate;
|
||||
animation: blur-text 1.5s 0s infinite linear alternate;
|
||||
}
|
||||
.loading-text span:nth-child(2) {
|
||||
filter: blur(0px);
|
||||
-webkit-animation: blur-text 1.5s 0.2s infinite linear alternate;
|
||||
animation: blur-text 1.5s 0.2s infinite linear alternate;
|
||||
animation: blur-text 1.5s 0.2s infinite linear alternate;
|
||||
}
|
||||
.loading-text span:nth-child(3) {
|
||||
filter: blur(0px);
|
||||
-webkit-animation: blur-text 1.5s 0.4s infinite linear alternate;
|
||||
animation: blur-text 1.5s 0.4s infinite linear alternate;
|
||||
animation: blur-text 1.5s 0.4s infinite linear alternate;
|
||||
}
|
||||
.loading-text span:nth-child(4) {
|
||||
filter: blur(0px);
|
||||
-webkit-animation: blur-text 1.5s 0.6s infinite linear alternate;
|
||||
animation: blur-text 1.5s 0.6s infinite linear alternate;
|
||||
animation: blur-text 1.5s 0.6s infinite linear alternate;
|
||||
}
|
||||
.loading-text span:nth-child(5) {
|
||||
filter: blur(0px);
|
||||
-webkit-animation: blur-text 1.5s 0.8s infinite linear alternate;
|
||||
animation: blur-text 1.5s 0.8s infinite linear alternate;
|
||||
animation: blur-text 1.5s 0.8s infinite linear alternate;
|
||||
}
|
||||
.loading-text span:nth-child(6) {
|
||||
filter: blur(0px);
|
||||
-webkit-animation: blur-text 1.5s 1s infinite linear alternate;
|
||||
animation: blur-text 1.5s 1s infinite linear alternate;
|
||||
animation: blur-text 1.5s 1s infinite linear alternate;
|
||||
}
|
||||
.loading-text span:nth-child(7) {
|
||||
filter: blur(0px);
|
||||
-webkit-animation: blur-text 1.5s 1.2s infinite linear alternate;
|
||||
animation: blur-text 1.5s 1.2s infinite linear alternate;
|
||||
animation: blur-text 1.5s 1.2s infinite linear alternate;
|
||||
}
|
||||
|
||||
@-webkit-keyframes blur-text {
|
||||
|
||||
377
chat/src/components/common/GridManager2/index.vue
Normal file
377
chat/src/components/common/GridManager2/index.vue
Normal file
@@ -0,0 +1,377 @@
|
||||
<script lang="ts" setup>
|
||||
import {
|
||||
onMounted,
|
||||
ref,
|
||||
computed,
|
||||
onUnmounted,
|
||||
getCurrentInstance,
|
||||
watch,
|
||||
nextTick,
|
||||
} from 'vue';
|
||||
import { throttle } from '@/utils/functions/throttle';
|
||||
import { SvgIcon } from '@/components/common';
|
||||
import { copyText } from '@/utils/format';
|
||||
import { useMessage, NPopover } from 'naive-ui';
|
||||
import { useAuthStore } from '@/store';
|
||||
import { useRouter } from 'vue-router';
|
||||
const authStore = useAuthStore();
|
||||
interface Props {
|
||||
dataList: FileItem[];
|
||||
scaleWidth?: number;
|
||||
isDrawLike?: boolean;
|
||||
usePropmpt?: boolean;
|
||||
copyPropmpt?: boolean;
|
||||
gap?: number;
|
||||
}
|
||||
|
||||
interface FileItem {
|
||||
id: number;
|
||||
drawUrl: string;
|
||||
fullPrompt?: string;
|
||||
drawRatio: string;
|
||||
}
|
||||
|
||||
interface Emit {
|
||||
(ev: 'loadMore'): void;
|
||||
(ev: 'usePropmptDraw', prompt: string): void;
|
||||
}
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
gap: 5,
|
||||
});
|
||||
const emit = defineEmits<Emit>();
|
||||
const $viewerApi =
|
||||
getCurrentInstance()?.appContext.config.globalProperties.$viewerApi;
|
||||
const ms = useMessage();
|
||||
const boxRefs = ref<any>({});
|
||||
const otherInfoContainerHeight = ref(0);
|
||||
const realWidth = ref(160);
|
||||
const realColumn = ref(0);
|
||||
const loadComplete = ref<number[]>([]);
|
||||
const wapperRef = ref<HTMLDivElement | null>(null);
|
||||
const wapperHeigth = ref(0);
|
||||
const isLogin = computed(() => authStore.isLogin);
|
||||
const width = computed(() => {
|
||||
return props.scaleWidth
|
||||
? Number(props.scaleWidth) * 2 + props.gap + 150
|
||||
: 150;
|
||||
});
|
||||
|
||||
const router = useRouter();
|
||||
/* 拿到图片高度 对定位top和right 新的一轮去插入最小值的那一列 贪心算法即可 */
|
||||
function compilerContainer() {
|
||||
calcHeight();
|
||||
compilerColumn();
|
||||
const columns = realColumn.value;
|
||||
const itemWidth = realWidth.value;
|
||||
const cacheHeight = <any>[];
|
||||
props.dataList.forEach((item, index) => {
|
||||
const drawRatio = item.drawRatio; // 假设 drawRatio 是 "1632x2912"
|
||||
const dimensions = drawRatio.split('x'); // 使用 'x' 分割字符串
|
||||
const width = parseInt(dimensions[0], 10); // 宽度,转换为数字
|
||||
const height = parseInt(dimensions[1], 10); // 高度,转换为数字
|
||||
const bi = itemWidth / width;
|
||||
const boxheight = height * bi + props.gap + otherInfoContainerHeight.value;
|
||||
const currentBox = boxRefs.value[item.id];
|
||||
if (cacheHeight.length < columns) {
|
||||
currentBox.style.top = '0px';
|
||||
currentBox.style.left = `${(itemWidth + props.gap) * index}px`;
|
||||
cacheHeight.push(boxheight);
|
||||
} else {
|
||||
const minHeight = Math.min.apply(null, cacheHeight);
|
||||
const minIndex = cacheHeight.findIndex((t: number) => t === minHeight);
|
||||
currentBox.style.top = `${minHeight + 0}px`;
|
||||
currentBox.style.left = `${minIndex * (realWidth.value + props.gap)}px`;
|
||||
cacheHeight[minIndex] += boxheight;
|
||||
}
|
||||
});
|
||||
wapperHeigth.value = Math.max(...cacheHeight) + 100;
|
||||
}
|
||||
|
||||
function setItemRefs(el: HTMLDivElement, item: FileItem) {
|
||||
if (el && item) {
|
||||
boxRefs.value[item.id] = el;
|
||||
}
|
||||
}
|
||||
|
||||
/* 通过额外展示的信息计算有没有除了图片意外额外的高度 eg: 图片100px 额外显示其他信息30px cacheHeight的高度在图片的基础上需要+30 */
|
||||
function calcHeight() {
|
||||
const { showName = 0, showOther = 0 } = {};
|
||||
otherInfoContainerHeight.value =
|
||||
[showName, showOther].filter((t) => t).length * 15;
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.scaleWidth,
|
||||
(val) => {
|
||||
handleResizeThrottled();
|
||||
}
|
||||
);
|
||||
|
||||
watch(
|
||||
() => props.dataList,
|
||||
(val) => {
|
||||
if (!val) return;
|
||||
nextTick(() => {
|
||||
handleResizeThrottled();
|
||||
});
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
/* 计算放多少列比较合理,并计算最终单个图片的宽 */
|
||||
function compilerColumn() {
|
||||
if (!wapperRef.value) return;
|
||||
const containerWidth = wapperRef.value.clientWidth;
|
||||
|
||||
/* 计算按目前宽度最多可以是几列 */
|
||||
realColumn.value = Math.floor(containerWidth / width.value);
|
||||
const surplus = containerWidth - realColumn.value * width.value; // 剩下的多余空间
|
||||
/* 计算如果给了左右间距那么作业间距需要占多少宽度 */
|
||||
const positionWith = (realColumn.value - 1) * props.gap; // 设置的right 需要padding的值
|
||||
/* 总宽度减去right的宽度,如果是负数考虑要不要cloumn-1 那么图片真实宽度就会比传入的宽度大 */
|
||||
if (surplus - positionWith < 0) {
|
||||
realColumn.value -= 1;
|
||||
}
|
||||
/* 图片宽度*列 + right的间距 不管大于小于总宽 多的或者少的那部分都平分给列容器 保证总宽是100% */
|
||||
realWidth.value = Math.floor(
|
||||
(containerWidth - positionWith) / realColumn.value
|
||||
);
|
||||
}
|
||||
|
||||
function imgLoadSuccess(e: any, item: FileItem) {
|
||||
loadComplete.value.push(item.id);
|
||||
}
|
||||
|
||||
function imgLoadError(e: any, item: FileItem) {
|
||||
console.error('Image failed to load:', item);
|
||||
loadComplete.value.push(item.id);
|
||||
}
|
||||
|
||||
function handleCopy(item: any) {
|
||||
if (!isLogin.value) {
|
||||
return authStore.setLoginDialog(true);
|
||||
}
|
||||
const { prompt } = item;
|
||||
copyText({ text: prompt });
|
||||
ms.success('复制prompt成功');
|
||||
}
|
||||
|
||||
function drawLike(item: any) {
|
||||
router.push(`/midjourney?mjId=${item.id}`);
|
||||
}
|
||||
|
||||
function usePropmptDraw(item: FileItem) {
|
||||
const { fullPrompt } = item;
|
||||
emit('usePropmptDraw', fullPrompt);
|
||||
}
|
||||
|
||||
function handlePreview(item: any) {
|
||||
const { drawUrl } = item;
|
||||
$viewerApi({ options: {}, images: [drawUrl] });
|
||||
}
|
||||
|
||||
const realHeight = computed(() => (item) => {
|
||||
const ratio = item.drawRatio.split('x');
|
||||
const originalWidth = Number(ratio[0]);
|
||||
const originalHeight = Number(ratio[1]);
|
||||
return originalHeight / (originalWidth / realWidth.value);
|
||||
});
|
||||
|
||||
const handleResizeThrottled = throttle(function (this: any) {
|
||||
compilerContainer();
|
||||
}, 200);
|
||||
|
||||
onMounted(async () => {
|
||||
window.addEventListener('resize', handleResizeThrottled);
|
||||
const container: any = document.getElementById('footer');
|
||||
const observer = new IntersectionObserver((entries, observer) => {
|
||||
entries.forEach((entry) => {
|
||||
if (entry.isIntersecting) {
|
||||
emit('loadMore');
|
||||
}
|
||||
});
|
||||
});
|
||||
observer.observe(container);
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener('resize', handleResizeThrottled);
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="min-h-full overflow-hidden flex flex-col">
|
||||
<div class="flex-1 min-h-full p-4 relative">
|
||||
<div
|
||||
id="wapper"
|
||||
ref="wapperRef"
|
||||
class="wapper"
|
||||
:style="{ height: `${wapperHeigth}px` }"
|
||||
>
|
||||
<div
|
||||
v-for="(item, index) in dataList"
|
||||
:id="item.id.toString()"
|
||||
:key="index"
|
||||
:ref="(el) => setItemRefs(el, item)"
|
||||
class="wapper-item"
|
||||
:style="{ width: `${realWidth}px` }"
|
||||
>
|
||||
<transition name="img" :css="true">
|
||||
<img
|
||||
:id="item.id.toString()"
|
||||
class="item-file rounded-sm"
|
||||
:style="{
|
||||
width: `${realWidth}px`,
|
||||
height: `${realHeight(item)}px`,
|
||||
}"
|
||||
:src="item.drawUrl"
|
||||
loading="lazy"
|
||||
@load="imgLoadSuccess($event, item)"
|
||||
@error="imgLoadError($event, item)"
|
||||
@click="handlePreview(item)"
|
||||
/>
|
||||
</transition>
|
||||
<div class="menu p-2 text-[#cbd5e1]">
|
||||
<div class="prompt">
|
||||
{{ item.fullPrompt }}
|
||||
</div>
|
||||
<div class="flex justify-end items-end space-x-2">
|
||||
<n-popover trigger="hover" v-if="isDrawLike">
|
||||
<template #trigger>
|
||||
<button
|
||||
class="flex h-5 w-8 items-center justify-center rounded border transition hover:bg-[#666161] dark:border-neutral-700 dark:hover:bg-[#33373c]"
|
||||
@click.stop="drawLike(item)"
|
||||
>
|
||||
<span class="text-sm dark:text-slate-400">
|
||||
<SvgIcon
|
||||
icon="fluent:draw-image-24-regular"
|
||||
class="text-sm"
|
||||
/>
|
||||
</span>
|
||||
</button>
|
||||
</template>
|
||||
<span>画同款</span>
|
||||
</n-popover>
|
||||
|
||||
<n-popover trigger="hover" v-if="usePropmpt">
|
||||
<template #trigger>
|
||||
<button
|
||||
class="flex h-5 w-8 items-center justify-center rounded border transition hover:bg-[#666161] dark:border-neutral-700 dark:hover:bg-[#33373c]"
|
||||
@click.stop="usePropmptDraw(item)"
|
||||
>
|
||||
<span class="text-sm dark:text-slate-400">
|
||||
<SvgIcon
|
||||
icon="fluent:draw-image-24-regular"
|
||||
class="text-sm"
|
||||
/>
|
||||
</span>
|
||||
</button>
|
||||
</template>
|
||||
<span>使用当前画同款</span>
|
||||
</n-popover>
|
||||
|
||||
<n-popover trigger="hover" v-if="copyPropmpt">
|
||||
<template #trigger>
|
||||
<button
|
||||
class="flex h-5 w-8 items-center justify-center rounded border transition hover:bg-[#666161] dark:border-neutral-700 dark:hover:bg-[#33373c]"
|
||||
@click.stop="handleCopy(item)"
|
||||
>
|
||||
<span class="text-sm dark:text-slate-400">
|
||||
<SvgIcon icon="tabler:copy" class="text-sm" />
|
||||
</span>
|
||||
</button>
|
||||
</template>
|
||||
<span>复制提示词</span>
|
||||
</n-popover>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="item-loading"
|
||||
v-if="!loadComplete.includes(item.id)"
|
||||
:style="{
|
||||
width: `${realWidth}px`,
|
||||
height: `${realHeight(item)}px`,
|
||||
}"
|
||||
></div>
|
||||
</div>
|
||||
<div id="footer" class="w-full absolute bottom-[350px]" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="less">
|
||||
.wapper {
|
||||
width: 100%;
|
||||
position: relative;
|
||||
height: 100%;
|
||||
padding-bottom: 20px;
|
||||
|
||||
&-item {
|
||||
z-index: 10;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
transition: all 0.5s;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
.menu {
|
||||
transition: transform 0.3s ease-in-out;
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
|
||||
img {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
}
|
||||
|
||||
.menu {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 94%;
|
||||
left: 3%;
|
||||
max-height: 70%;
|
||||
height: 100px;
|
||||
transform: translateY(100%);
|
||||
background-color: #090b15;
|
||||
opacity: 0.8;
|
||||
transition: all 0.1s cubic-bezier(0.68, -0.55, 0.265, 1.55);
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
|
||||
.prompt {
|
||||
height: 50px;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
img {
|
||||
user-select: none;
|
||||
cursor: pointer;
|
||||
transition: all 0.6s cubic-bezier(0.19, 1, 0.22, 1);
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.item-loading {
|
||||
background: url(@/assets/img-bg.png) no-repeat center center;
|
||||
filter: blur(20px);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.img-enter-active,
|
||||
.img-leave-active {
|
||||
transition: transform 0.3s;
|
||||
}
|
||||
|
||||
.img-enter,
|
||||
.img-leave-to {
|
||||
transform: scale(0.6);
|
||||
opacity: 0;
|
||||
}
|
||||
</style>
|
||||
@@ -317,7 +317,7 @@ onUnmounted(() => {
|
||||
}
|
||||
|
||||
.item-loading {
|
||||
background: url(../../assets/img-bg.png) no-repeat center center;
|
||||
background: url(@/assets/img-bg.png) no-repeat center center;
|
||||
filter: blur(20px);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
@@ -10,7 +10,8 @@ export function defaultState(): Chat.ChatState {
|
||||
groupList: [],
|
||||
chatList: [],
|
||||
groupKeyWord: '',
|
||||
baseConfig: null
|
||||
baseConfig: null,
|
||||
chatPreList: [],
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ export function defaultSetting(): UserState {
|
||||
return {
|
||||
userInfo: {
|
||||
avatar: 'https://public-1300678944.cos.ap-shanghai.myqcloud.com/blog/1681310872890image.png',
|
||||
name: 'Nine Ai',
|
||||
name: 'Yi Ai',
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,13 +4,6 @@ body,
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
// @font-face {
|
||||
// font-family: "nineai";
|
||||
// src: url("//at.alicdn.com/wf/webfont/KDHmc7Mx03dG/NkbQEk5ZpA2z.woff2") format("woff2"),
|
||||
// url("//at.alicdn.com/wf/webfont/KDHmc7Mx03dG/MG5Fkb82nDmI.woff") format("woff");
|
||||
// font-display: swap;
|
||||
// }
|
||||
|
||||
*{
|
||||
font-family: consolas, Menlo, "PingFang SC", "Microsoft YaHei", sans-serif;
|
||||
}
|
||||
|
||||
@@ -13,6 +13,9 @@ import {
|
||||
useDialog,
|
||||
useMessage,
|
||||
NAlert,
|
||||
NSpace,
|
||||
NPopselect,
|
||||
NText,
|
||||
} from 'naive-ui'
|
||||
import type { MessageRenderMessage } from 'naive-ui'
|
||||
|
||||
@@ -40,7 +43,7 @@ import {
|
||||
useGlobalStoreWithOut,
|
||||
} from '@/store'
|
||||
import { fetchQueryOneCatAPI } from '@/api/appStore'
|
||||
import { fetchChatAPIProcess } from '@/api'
|
||||
import { fetchChatAPIProcess, fetchVideoAPIProcess } from '@/api'
|
||||
import { t } from '@/locales'
|
||||
import { router } from '@/router'
|
||||
const uploadUrl = ref(`${import.meta.env.VITE_GLOB_API_URL}/upload/file`)
|
||||
@@ -84,6 +87,38 @@ const themeOptions: {
|
||||
icon: 'noto-v1:last-quarter-moon-face',
|
||||
},
|
||||
]
|
||||
|
||||
const videoOptions: {
|
||||
label: string
|
||||
value: string
|
||||
}[] = [
|
||||
{
|
||||
value: 'alloy',
|
||||
label: 'alloy',
|
||||
},
|
||||
{
|
||||
value: 'echo',
|
||||
label: 'echo',
|
||||
},
|
||||
{
|
||||
value: 'fable',
|
||||
label: 'fable',
|
||||
},
|
||||
{
|
||||
value: 'nova',
|
||||
label: 'nova',
|
||||
},
|
||||
{
|
||||
value: 'onyx',
|
||||
label: 'onyx',
|
||||
},
|
||||
{
|
||||
value: 'shimmer',
|
||||
label: 'shimmer',
|
||||
},
|
||||
]
|
||||
|
||||
let currentVideo = ref('alloy')
|
||||
const theme = computed(() => appStore.theme)
|
||||
|
||||
const globaelConfig = computed(() => authStore.globalConfig)
|
||||
@@ -198,6 +233,48 @@ function handleSignIn() {
|
||||
useGlobalStore.updateSignInDialog(true)
|
||||
}
|
||||
|
||||
const audioRef = ref(null)
|
||||
const audioState = ref('Play')
|
||||
function hendleVideo(item) {
|
||||
var data = JSON.stringify({
|
||||
model: 'tts-1',
|
||||
input: item.text,
|
||||
voice: 'alloy',
|
||||
})
|
||||
axios({
|
||||
method: 'post',
|
||||
url: 'https://api.oneapi.dwyu.cn/v1/audio/speech',
|
||||
headers: {
|
||||
Authorization:
|
||||
'Bearer sk-z726fTNvD1jzSBZ42e8dF919840b48A5820e4e5d9d4e70A4',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
data: data,
|
||||
})
|
||||
.then(function (response) {
|
||||
console.log('--response.data', response.data)
|
||||
const audio = audioRef.value
|
||||
const blob = new Blob([response.data], { type: 'audio/mpeg' })
|
||||
if (!audio) return
|
||||
audio.src = URL.createObjectURL(blob)
|
||||
console.log(audio)
|
||||
audio.load()
|
||||
audio.play()
|
||||
|
||||
// if (audio.paused) {
|
||||
// audio.play()
|
||||
// audioState.value = 'Stop'
|
||||
// } else {
|
||||
// audio.pause()
|
||||
// audio.currentTime = 0
|
||||
// audioState.value = 'Play'
|
||||
// }
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.error('There was an error fetching the audio data', error)
|
||||
})
|
||||
}
|
||||
|
||||
// 解析文件 gpt-4-all逆向
|
||||
let curFile: File | null
|
||||
|
||||
@@ -279,7 +356,6 @@ async function uploadFile() {
|
||||
} finally {
|
||||
dataBase64.value = null
|
||||
curFile = null
|
||||
showProgressModal.value = false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -426,6 +502,7 @@ async function onConversation(msg?: string) {
|
||||
usage: data?.detail?.usage,
|
||||
error: false,
|
||||
loading: true,
|
||||
imageUrl: data?.imageUrl,
|
||||
conversationOptions: {
|
||||
conversationId: data?.conversationId,
|
||||
parentMessageId: data?.id,
|
||||
@@ -594,6 +671,7 @@ async function onConversation(msg?: string) {
|
||||
return
|
||||
}
|
||||
updateGroupChat(dataSources.value.length - 1, {
|
||||
imageUrl: data.imageUrl,
|
||||
dateTime: new Date().toLocaleString(),
|
||||
text: errorMessage,
|
||||
inversion: false,
|
||||
@@ -607,6 +685,8 @@ async function onConversation(msg?: string) {
|
||||
loading.value = false
|
||||
isStreamIn.value = false
|
||||
imageUrl = null
|
||||
typingStatusEnd.value = true
|
||||
scrollToBottom()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -818,6 +898,7 @@ onUnmounted(() => {
|
||||
:imageUrl="item.imageUrl"
|
||||
@regenerate="handleSubmit(index)"
|
||||
@delete="handleDelete(item)"
|
||||
@video="hendleVideo(item)"
|
||||
/>
|
||||
<div class="sticky bottom-1 left-0 flex justify-center">
|
||||
<NButton v-if="loading" @click="handleStop">
|
||||
@@ -844,6 +925,7 @@ onUnmounted(() => {
|
||||
@click="toggleUsingContext"
|
||||
>
|
||||
<span
|
||||
class=""
|
||||
:class="{
|
||||
'text-[#3076fd]': usingContext,
|
||||
'text-[#ffffff]': !usingContext,
|
||||
@@ -971,7 +1053,6 @@ onUnmounted(() => {
|
||||
</NTooltip>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="m-auto max-w-screen-4xl"
|
||||
:class="[isMobile ? 'px-2 py-1' : 'px-4 py-2']"
|
||||
@@ -1097,35 +1178,6 @@ onUnmounted(() => {
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-between items-center">
|
||||
<!-- <div
|
||||
class="flex items-center text-neutral-400 cursor-pointer hover:text-[#3076fd]"
|
||||
>
|
||||
<span class="ml-2 mr-2 text-xs" @click="toggleUsingNetwork"
|
||||
>{{ usingNetwork ? '关闭' : '开启' }}联网访问</span
|
||||
>
|
||||
<NTooltip trigger="hover" :disabled="isMobile">
|
||||
<template #trigger>
|
||||
<SvgIcon
|
||||
icon="zondicons:network"
|
||||
class="cursor-pointer mb-0.5"
|
||||
:class="[
|
||||
{
|
||||
'text-[#3076fd]': usingNetwork,
|
||||
'': !usingNetwork,
|
||||
},
|
||||
]"
|
||||
@click="toggleUsingNetwork"
|
||||
/>
|
||||
</template>
|
||||
{{ usingNetwork ? '关闭联网模式' : '开启联网模式' }}
|
||||
</NTooltip>
|
||||
<div
|
||||
class="mx-4 h-full text-neutral-300 dark:text-neutral-600"
|
||||
>
|
||||
|
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<NButton
|
||||
type="primary"
|
||||
size="small"
|
||||
@@ -1181,6 +1233,10 @@ onUnmounted(() => {
|
||||
/>
|
||||
</NCard>
|
||||
</NModal>
|
||||
|
||||
<!-- <audio ref="audioRef" controls>
|
||||
<source type="audio/mpeg" />
|
||||
</audio> -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -61,11 +61,9 @@ const themeOptions: {
|
||||
]
|
||||
|
||||
const modelName = computed(() => {
|
||||
if (!chatStore.activeConfig)
|
||||
return
|
||||
if (!chatStore.activeConfig) return
|
||||
const { modelTypeInfo, modelInfo } = chatStore.activeConfig
|
||||
if (!modelTypeInfo || !modelInfo)
|
||||
return
|
||||
if (!modelTypeInfo || !modelInfo) return
|
||||
return `${modelTypeInfo?.label} / ${modelInfo.modelName}`
|
||||
})
|
||||
|
||||
@@ -85,8 +83,7 @@ function handleUpdateCollapsed() {
|
||||
|
||||
function onScrollToTop() {
|
||||
const scrollRef = document.querySelector('#scrollRef')
|
||||
if (scrollRef)
|
||||
nextTick(() => (scrollRef.scrollTop = 0))
|
||||
if (scrollRef) nextTick(() => (scrollRef.scrollTop = 0))
|
||||
}
|
||||
|
||||
function handleExport() {
|
||||
@@ -180,7 +177,7 @@ function handleSignIn() {
|
||||
</div>
|
||||
</div>
|
||||
</NPopover> -->
|
||||
|
||||
|
||||
<NTooltip v-if="isMobile" trigger="hover" :disabled="isMobile">
|
||||
<template #trigger>
|
||||
<button
|
||||
@@ -199,7 +196,7 @@ function handleSignIn() {
|
||||
<button
|
||||
class="flex h-8 w-8 items-center justify-center rounded border transition hover:bg-[#eef0f3] dark:border-neutral-700 dark:hover:bg-[#33373c]"
|
||||
@click="handleExport"
|
||||
v-show="!isMobile"
|
||||
v-show="!isMobile"
|
||||
>
|
||||
<span class="text-base text-slate-500 dark:text-slate-400">
|
||||
<SvgIcon
|
||||
@@ -216,7 +213,9 @@ function handleSignIn() {
|
||||
class="flex h-8 w-8 items-center justify-center rounded border transition hover:bg-[#eef0f3] dark:border-neutral-700 dark:hover:bg-[#33373c]"
|
||||
@click="handleClear"
|
||||
>
|
||||
<span class="text-base text-slate-500 dark:text-slate-400"><SvgIcon icon="material-symbols:delete-outline"/></span>
|
||||
<span class="text-base text-slate-500 dark:text-slate-400"
|
||||
><SvgIcon icon="material-symbols:delete-outline"
|
||||
/></span>
|
||||
</button>
|
||||
</template>
|
||||
删除本页内容
|
||||
@@ -227,7 +226,9 @@ function handleSignIn() {
|
||||
class="flex h-8 w-8 items-center justify-center rounded border transition hover:bg-[#eef0f3] dark:border-neutral-700 dark:hover:bg-[#33373c]"
|
||||
@click="handleScrollBtm"
|
||||
>
|
||||
<span class="text-base text-slate-500 dark:text-slate-400"><SvgIcon icon="material-symbols:keyboard-arrow-down" /></span>
|
||||
<span class="text-base text-slate-500 dark:text-slate-400"
|
||||
><SvgIcon icon="material-symbols:keyboard-arrow-down"
|
||||
/></span>
|
||||
</button>
|
||||
</template>
|
||||
滚动到底部
|
||||
|
||||
@@ -4,11 +4,13 @@ import MarkdownIt from 'markdown-it'
|
||||
import mdKatex from '@traptitech/markdown-it-katex'
|
||||
import mila from 'markdown-it-link-attributes'
|
||||
import hljs from 'highlight.js'
|
||||
import { NButton, NIcon } from 'naive-ui'
|
||||
import { NButton, NIcon, NImage } from 'naive-ui'
|
||||
import { Copy, Delete } from '@icon-park/vue-next'
|
||||
import { useAppStore } from '@/store'
|
||||
import { useBasicLayout } from '@/hooks/useBasicLayout'
|
||||
import { t } from '@/locales'
|
||||
import { SvgIcon } from '@/components/common'
|
||||
|
||||
interface Props {
|
||||
inversion?: boolean
|
||||
error?: boolean
|
||||
@@ -22,6 +24,7 @@ interface Emit {
|
||||
(ev: 'regenerate'): void
|
||||
(ev: 'delete'): void
|
||||
(ev: 'copy'): void
|
||||
(ev: 'video'): void
|
||||
}
|
||||
|
||||
const props = defineProps<Props>()
|
||||
@@ -106,6 +109,10 @@ function handleRegenerate() {
|
||||
emit('regenerate')
|
||||
}
|
||||
|
||||
function hendleVideo() {
|
||||
emit('video')
|
||||
}
|
||||
|
||||
function handleCopy() {
|
||||
emit('copy')
|
||||
}
|
||||
@@ -118,106 +125,137 @@ defineExpose({ textRef })
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div :class="wrapClass" class="w-full" style="width: auto">
|
||||
<div ref="textRef" class="leading-relaxed break-words">
|
||||
<div v-if="!inversion" class="flex flex-col items-start">
|
||||
<div class="w-full">
|
||||
<div
|
||||
v-if="!asRawText"
|
||||
class="w-full markdown-body"
|
||||
:class="[{ 'markdown-body-generate': loading }]"
|
||||
v-html="text"
|
||||
/>
|
||||
<div v-else class="w-full whitespace-pre-wrap" v-text="text" />
|
||||
<span
|
||||
<div class="flex flex-col group max-w-full" style="width: auto">
|
||||
<div :class="wrapClass" class="w-full" style="width: auto">
|
||||
<div ref="textRef" class="leading-relaxed break-words">
|
||||
<div v-if="!inversion" class="flex flex-col items-start">
|
||||
<div class="w-full">
|
||||
<div
|
||||
v-if="!asRawText"
|
||||
class="w-full markdown-body"
|
||||
:class="[{ 'markdown-body-generate': loading }]"
|
||||
v-html="text"
|
||||
/>
|
||||
<div v-else class="w-full whitespace-pre-wrap" v-text="text" />
|
||||
<!-- <span
|
||||
v-if="loading"
|
||||
class="dark:text-white w-[4px] h-[20px] block animate-blink"
|
||||
style="display: none"
|
||||
class="dark:text-white w-[4px] h-[10px] block animate-blink"
|
||||
/> -->
|
||||
<NImage
|
||||
v-if="imageUrl && isImageUrl"
|
||||
:src="imageUrl"
|
||||
:preview-src="imageUrl"
|
||||
alt="图片"
|
||||
class="h-md rounded-md m-1"
|
||||
:style="{ 'max-width': isMobile ? '100%' : '20vw' }"
|
||||
style="margin-top: 0.5rem"
|
||||
/>
|
||||
</div>
|
||||
<!-- 小易改动:注册掉底部的内容 -->
|
||||
</div>
|
||||
<div v-else>
|
||||
<div class="whitespace-pre-wrap" v-text="text" />
|
||||
<NImage
|
||||
:src="imageUrl"
|
||||
:preview-src="imageUrl"
|
||||
alt="图片"
|
||||
class="h-md rounded-md m-1"
|
||||
:style="{ 'max-width': isMobile ? '100%' : '20vw' }"
|
||||
style="margin-top: 0.5rem"
|
||||
v-if="imageUrl && isImageUrl"
|
||||
/>
|
||||
</div>
|
||||
<!-- 小易改动:注册掉底部的内容 -->
|
||||
<!-- <div style="margin-top: 0.5rem"> -->
|
||||
<!-- <NButton class="ml-2" text type="primary" @click="handleCopy">
|
||||
<template #icon>
|
||||
<NIcon :size="10" :component="Copy" />
|
||||
</template>
|
||||
<span class="text-xs">复制</span>
|
||||
</NButton>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="flex opacity-0 transition-opacity duration-300 group-hover:opacity-100 text-gray-700"
|
||||
>
|
||||
<div v-if="!inversion">
|
||||
<div class="mt-1 flex">
|
||||
<button
|
||||
class="flex ml-0 items-center text-gray-400 hover:text-gray-700 dark:text-gray-600 dark:hover:text-gray-400 mx-1"
|
||||
text
|
||||
type="primary"
|
||||
@click="handleCopy"
|
||||
>
|
||||
<SvgIcon class="flex h-3 w-3 mx-1" icon="tabler:copy" />
|
||||
<span class="flex text-xs">复制</span>
|
||||
</button>
|
||||
|
||||
<span style="margin-left: 0.5rem" />
|
||||
<NButton
|
||||
class="ml-2"
|
||||
<button
|
||||
class="flex ml-0 items-center text-gray-400 hover:text-gray-700 dark:text-gray-600 dark:hover:text-gray-400 mx-1"
|
||||
text
|
||||
type="primary"
|
||||
@click="handleRegenerate"
|
||||
>
|
||||
<SvgIcon class="flex h-3 w-3 mx-1" icon="clarity:refresh-line" />
|
||||
<span class="flex text-xs">重新生成</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
class="flex ml-0 items-center text-gray-400 hover:text-gray-700 dark:text-gray-600 dark:hover:text-gray-400 mx-1"
|
||||
text
|
||||
type="primary"
|
||||
@click="handleDelete"
|
||||
>
|
||||
<SvgIcon
|
||||
class="flex h-3 w-3 mx-1"
|
||||
icon="fluent:delete-48-regular"
|
||||
/>
|
||||
<span class="flex text-xs">删除</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
class="flex ml-0 items-center text-gray-400 hover:text-gray-700 dark:text-gray-600 dark:hover:text-gray-400 mx-1"
|
||||
text
|
||||
type="primary"
|
||||
@click="asRawText = !asRawText"
|
||||
>
|
||||
<template #icon>
|
||||
<SvgIcon
|
||||
class="text-xs"
|
||||
:icon="asRawText ? 'ic:outline-code-off' : 'ic:outline-code'"
|
||||
/>
|
||||
</template>
|
||||
<span class="text-xs">{{
|
||||
<SvgIcon
|
||||
class="flex h-3 w-3 mx-1"
|
||||
:icon="asRawText ? 'ic:outline-code-off' : 'ic:outline-code'"
|
||||
/>
|
||||
<span class="flex text-xs">{{
|
||||
asRawText ? t('chat.preview') : t('chat.showRawText')
|
||||
}}</span>
|
||||
</NButton> -->
|
||||
<!-- 删除BUG -->
|
||||
<!-- <span style="margin-left: 0.5rem" />
|
||||
<NButton text type="primary" @click="handleDelete">
|
||||
<template #icon>
|
||||
<NIcon :size="10" :component="Delete" />
|
||||
</template>
|
||||
<span class="text-xs">删除</span>
|
||||
</NButton> -->
|
||||
</button>
|
||||
|
||||
<!-- <span style="margin-left: 0.5rem" />
|
||||
<NButton text type="primary" @click="handleRegenerate">
|
||||
<template #icon>
|
||||
<NIcon :size="10" :component="Refresh" />
|
||||
</template>
|
||||
<span class="text-xs">重新回答</span>
|
||||
</NButton> -->
|
||||
<!-- </div> -->
|
||||
<!-- <button
|
||||
class="flex ml-0 items-center text-gray-400 hover:text-gray-700 dark:text-gray-600 dark:hover:text-gray-400 mx-1"
|
||||
text
|
||||
type="primary"
|
||||
@click="hendleVideo"
|
||||
>
|
||||
<img src="@/assets/voice.gif" class="flex h-3 w-3 mx-1" />
|
||||
<SvgIcon class="flex h-3 w-3 mx-1" icon="ep:video-play" />
|
||||
<span class="flex text-xs">播放</span>
|
||||
</button> -->
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div class="whitespace-pre-wrap" v-text="text" />
|
||||
<a v-if="imageUrl && isImageUrl" :href="imageUrl" target="_blank">
|
||||
<img
|
||||
:src="imageUrl"
|
||||
alt="图片"
|
||||
class="h-auto rounded-md mb-1"
|
||||
:class="{ 'max-w-full': isMobile, 'max-w-sm': !isMobile }"
|
||||
style="margin-top: 0.5rem"
|
||||
/>
|
||||
</a>
|
||||
<a
|
||||
:href="imageUrl"
|
||||
target="_blank"
|
||||
:class="{ 'file-2': isMobile, 'file-1': !isMobile }"
|
||||
>
|
||||
<img
|
||||
src="@/assets/file.jpeg"
|
||||
alt="文件"
|
||||
class="h-auto rounded-md mb-1"
|
||||
:class="{ 'file-2': isMobile, 'file-1': !isMobile }"
|
||||
v-if="imageUrl && !isImageUrl"
|
||||
/>
|
||||
</a>
|
||||
<div v-if="false" style="margin-left: 0.5rem">
|
||||
<NButton class="ml-2" text color="#FFF" @click="handleCopy">
|
||||
<template #icon>
|
||||
<NIcon :size="10" :component="Copy" />
|
||||
</template>
|
||||
|
||||
<span class="text-xs">复制</span>
|
||||
</NButton>
|
||||
<span class="ml-3" />
|
||||
<NButton text color="#FFF" @click="handleDelete">
|
||||
<template #icon>
|
||||
<NIcon :size="10" :component="Delete" />
|
||||
</template>
|
||||
<span class="text-xs">删除</span>
|
||||
</NButton>
|
||||
<div v-else>
|
||||
<div class="mt-1 flex">
|
||||
<button
|
||||
class="flex ml-0 items-center text-gray-400 hover:text-gray-700 dark:text-gray-600 dark:hover:text-gray-400 mx-1"
|
||||
text
|
||||
type="primary"
|
||||
@click="handleCopy"
|
||||
>
|
||||
<SvgIcon class="flex h-3 w-3 mx-1" icon="tabler:copy" />
|
||||
<span class="flex text-xs">复制</span>
|
||||
</button>
|
||||
<button
|
||||
class="flex ml-0 items-center text-gray-400 hover:text-gray-700 dark:text-gray-600 dark:hover:text-gray-400 mx-1"
|
||||
text
|
||||
type="primary"
|
||||
@click="handleDelete"
|
||||
>
|
||||
<SvgIcon
|
||||
class="flex h-3 w-3 mx-1"
|
||||
icon="fluent:delete-48-regular"
|
||||
/>
|
||||
<span class="flex text-xs">删除</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -21,6 +21,7 @@ interface Props {
|
||||
interface Emit {
|
||||
(ev: 'regenerate'): void
|
||||
(ev: 'delete'): void
|
||||
(ev: 'video'): void
|
||||
}
|
||||
|
||||
const props = defineProps<Props>()
|
||||
@@ -81,6 +82,10 @@ function handleDetele() {
|
||||
emit('delete')
|
||||
}
|
||||
|
||||
function hendleVideo() {
|
||||
emit('video')
|
||||
}
|
||||
|
||||
function handleCopy() {
|
||||
copyText({ text: props.text ?? '' })
|
||||
props.text && ms.success('复制成功!')
|
||||
@@ -128,9 +133,10 @@ function handleRegenerate() {
|
||||
@regenerate="handleRegenerate"
|
||||
@copy="handleCopy"
|
||||
@delete="handleDetele"
|
||||
@video="hendleVideo"
|
||||
:imageUrl="imageUrl"
|
||||
/>
|
||||
<div class="flex flex-col">
|
||||
<!-- <div class="flex flex-col">
|
||||
<button
|
||||
v-if="!inversion"
|
||||
class="flex mb-2 transition text-neutral-300 hover:text-neutral-800 dark:hover:text-neutral-300"
|
||||
@@ -150,7 +156,7 @@ function handleRegenerate() {
|
||||
<SvgIcon icon="ri:more-2-fill" />
|
||||
</button>
|
||||
</NDropdown>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -6,7 +6,7 @@ import { fetchChatDraw, fetchGetAllChatLogDraw, fetchGetChatLogDraw } from '@/ap
|
||||
import { useBasicLayout } from '@/hooks/useBasicLayout'
|
||||
import { TitleBar } from '@/components/base'
|
||||
import { useAppStore, useAuthStore } from '@/store'
|
||||
import GridManager from '@/components/common/GridManager/index.vue'
|
||||
import OldGridManager from '@/components/common/OldGridManager/index.vue'
|
||||
|
||||
import Loading from '@/components/base/Loading.vue'
|
||||
const theme = computed(() => appStore.theme)
|
||||
@@ -73,14 +73,14 @@ function updateEx() {
|
||||
}
|
||||
|
||||
async function queryMyDrawList() {
|
||||
const res: ResData = await fetchGetChatLogDraw({ model: 'DALL-E2' })
|
||||
const res: ResData = await fetchGetChatLogDraw({ model: 'dall-e-3' })
|
||||
if (!res.success)
|
||||
return
|
||||
mineDrawList.value = formatFileInfo(res.data)
|
||||
}
|
||||
|
||||
async function queryAllDrawList() {
|
||||
const res: ResData = await fetchGetAllChatLogDraw({ size: 999, rec: 1, model: 'DALL-E2' })
|
||||
const res: ResData = await fetchGetAllChatLogDraw({ size: 999, rec: 1, model: 'dall-e-3' })
|
||||
if (!res.success)
|
||||
return ms.error(res.message)
|
||||
allDrawList.value = formatFileInfo(res.data.rows)
|
||||
@@ -184,13 +184,13 @@ onMounted(() => {
|
||||
参数设置
|
||||
</h4>
|
||||
<div class="flex items-center mt-5">
|
||||
<span class="mr-2 inline-block w-16 flex-shrink-0">图片尺寸:</span>
|
||||
<span class="mr-2 inline-block w-20 flex-shrink-0">图片尺寸:</span>
|
||||
<div>
|
||||
<span v-for="item in imageSizeList" :key="item.value" class="rounded ml-2 select-none cursor-pointer inline-block mb-2" :class="[item.value === form.size ? ['text-primary', 'bg-[#0d6efd1c]'] : ['bg-[#bfc4d033]'], isMobile ? 'px-1.5 py-0.5' : 'px-3 py-1']" @click="form.size = item.value">{{ item.label }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center mt-5">
|
||||
<span class="mr-2 inline-block w-16 flex-shrink-0">图片质量:</span>
|
||||
<span class="mr-2 inline-block w-20 flex-shrink-0">图片质量:</span>
|
||||
<div>
|
||||
<span v-for="item in qualityList" :key="item.value" class=" py-0.5 px-2.5 rounded ml-2 select-none cursor-pointer inline-block mb-2" :class="item.value === form.quality ? ['text-primary', 'bg-[#0d6efd1c]'] : ['bg-[#bfc4d033]']" @click="form.quality = item.value">{{ item.label }}</span>
|
||||
</div>
|
||||
@@ -232,13 +232,13 @@ onMounted(() => {
|
||||
<NTabs type="line" animated class="mt-5" @update:value="updateTabs">
|
||||
<NTabPane name="all" tab="公共生成">
|
||||
<div v-if="allDrawList.length" class="min-h-screen">
|
||||
<GridManager @loadMore="loadMore" usePropmpt :gap="8" preOrigin @usePropmptDraw="usePropmptDraw" :dataList="allDrawList" :scaleWidth="50" />
|
||||
<OldGridManager @loadMore="loadMore" usePropmpt :gap="8" preOrigin @usePropmptDraw="usePropmptDraw" :dataList="allDrawList" :scaleWidth="50" />
|
||||
</div>
|
||||
<NEmpty v-else size="huge" class="mt-20" description="暂无数据哟~" />
|
||||
</NTabPane>
|
||||
<NTabPane name="mine" tab="我的生成">
|
||||
<div v-if="mineDrawList.length" class="min-h-screen">
|
||||
<GridManager @loadMore="loadMore" usePropmpt :gap="8" preOrigin @usePropmptDraw="usePropmptDraw" :dataList="mineDrawList" :scaleWidth="50" />
|
||||
<OldGridManager @loadMore="loadMore" usePropmpt :gap="8" preOrigin @usePropmptDraw="usePropmptDraw" :dataList="mineDrawList" :scaleWidth="50" />
|
||||
</div>
|
||||
<NEmpty v-else size="huge" class="mt-20" description="暂无数据哟~" />
|
||||
</NTabPane>
|
||||
|
||||
@@ -7,8 +7,8 @@ import { NButton } from 'naive-ui'
|
||||
|
||||
const proxyImgBase = ref('')
|
||||
|
||||
const mode1Url = 'https://chevereto.jiangly.com/images/2023/11/21/61888bd4ede4.png'
|
||||
const mode2Url = 'https://chevereto.jiangly.com/images/2023/11/19/shoes.jpg'
|
||||
const mode1Url = ''
|
||||
const mode2Url = ''
|
||||
|
||||
|
||||
const canvasRef = ref<any>(null)
|
||||
|
||||
@@ -1,153 +1,163 @@
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref, computed } from 'vue'
|
||||
import { fetchMidjourneyGetList } from '@/api'
|
||||
import type { ResData } from '@/api/types'
|
||||
import { NSlider, NInput, NIcon } from 'naive-ui'
|
||||
import GridManager from '@/components/common/GridManager/index.vue'
|
||||
import { FlashOutline } from '@vicons/ionicons5'
|
||||
import { onMounted, ref, computed } from 'vue';
|
||||
import { fetchMidjourneyGetList } from '@/api';
|
||||
import type { ResData } from '@/api/types';
|
||||
import { NSlider, NInput, NIcon } from 'naive-ui';
|
||||
import GridManager2 from '@/components/common/GridManager2/index.vue';
|
||||
import { FlashOutline } from '@vicons/ionicons5';
|
||||
|
||||
const imageList = ref<any>([])
|
||||
const wapperRef = ref<HTMLDivElement | null>(null)
|
||||
const scaleWidth = ref(50)
|
||||
const keyword = ref('')
|
||||
const page = ref(1)
|
||||
const size = ref(20)
|
||||
const loading = ref(false)
|
||||
const isMore = ref(true)
|
||||
const imageList = ref<any>([]);
|
||||
const wapperRef = ref<HTMLDivElement | null>(null);
|
||||
const scaleWidth = ref(50);
|
||||
const keyword = ref('');
|
||||
const page = ref(1);
|
||||
const size = ref(20);
|
||||
const loading = ref(false);
|
||||
const isMore = ref(true);
|
||||
|
||||
const dataList = computed(() => {
|
||||
if (!keyword.value) {
|
||||
return imageList.value;
|
||||
} else {
|
||||
return imageList.value.filter((item: any) => {
|
||||
const { prompt } = item;
|
||||
return prompt.includes(keyword.value);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const dataList = computed(() => {
|
||||
if(!keyword.value){
|
||||
return imageList.value
|
||||
}else{
|
||||
return imageList.value.filter((item: any) => {
|
||||
const { prompt } = item
|
||||
return prompt.includes(keyword.value)
|
||||
})
|
||||
}
|
||||
})
|
||||
async function queryDrawImg() {
|
||||
loading.value = true;
|
||||
const res: ResData = await fetchMidjourneyGetList({
|
||||
page: page.value,
|
||||
size: size.value,
|
||||
rec: 1,
|
||||
});
|
||||
loading.value = false;
|
||||
isMore.value = size.value === res.data.rows.length;
|
||||
imageList.value = [...imageList.value, ...res.data.rows];
|
||||
}
|
||||
|
||||
async function queryDrawImg() {
|
||||
loading.value = true
|
||||
const res: ResData = await fetchMidjourneyGetList({ page: page.value ,size: size.value, rec: 1 })
|
||||
loading.value = false
|
||||
isMore.value = size.value === res.data.rows.length
|
||||
imageList.value = [...imageList.value, ...res.data.rows]
|
||||
}
|
||||
onMounted(async () => {
|
||||
await queryDrawImg();
|
||||
});
|
||||
|
||||
onMounted(async () => {
|
||||
await queryDrawImg()
|
||||
})
|
||||
function loadMore() {
|
||||
page.value = page.value + 1;
|
||||
queryDrawImg();
|
||||
}
|
||||
</script>
|
||||
|
||||
function loadMore(){
|
||||
page.value = page.value + 1
|
||||
queryDrawImg()
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<div
|
||||
class="bg-[#fff] h-[100vh] overflow-hidden p-4 pr-0 dark:bg-[#18181c] flex flex-col"
|
||||
>
|
||||
<div class="p-4 flex pr-6 justify-between items-center">
|
||||
<div class="font-bold text-xl">AI绘画广场</div>
|
||||
<div class="w-[200px] sm:w-[300px] flex justify-between">
|
||||
<span class="hidden sm:block">尺寸调整</span>
|
||||
<div class="flex-1 ml-5">
|
||||
<n-slider v-model:value="scaleWidth" :step="10" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="px-4 mb-1 pr-5">
|
||||
<n-input v-model:value="keyword" placeholder="prompt关键词搜索">
|
||||
<template #prefix>
|
||||
<n-icon :component="FlashOutline" />
|
||||
</template>
|
||||
</n-input>
|
||||
</div>
|
||||
<div
|
||||
class="market overflow-y-scroll flex-1 min-h-screen p-4 dark:bg-[#18181c] relative"
|
||||
>
|
||||
<div id="wapper" ref="wapperRef" class="wapper">
|
||||
<GridManager2
|
||||
@loadMore="loadMore"
|
||||
copyPropmpt
|
||||
isDrawLike
|
||||
:dataList="dataList"
|
||||
:scaleWidth="scaleWidth"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template>
|
||||
<div class="bg-[#fff] h-[100vh] overflow-hidden p-4 pr-0 dark:bg-[#18181c] flex flex-col">
|
||||
<div class="p-4 flex pr-6 justify-between items-center">
|
||||
<div class="font-bold text-xl">AI绘画广场</div>
|
||||
<div class="w-[200px] sm:w-[300px] flex justify-between">
|
||||
<span class="hidden sm:block" >尺寸调整</span>
|
||||
<div class="flex-1 ml-5">
|
||||
<n-slider v-model:value="scaleWidth" :step="10" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="px-4 mb-1 pr-5">
|
||||
<n-input v-model:value="keyword" placeholder="prompt关键词搜索">
|
||||
<template #prefix>
|
||||
<n-icon :component="FlashOutline" />
|
||||
</template>
|
||||
</n-input>
|
||||
</div>
|
||||
<div class="market overflow-y-scroll flex-1 min-h-screen p-4 dark:bg-[#18181c] relative ">
|
||||
<div id="wapper" ref="wapperRef" class="wapper">
|
||||
<GridManager @loadMore="loadMore" copyPropmpt isDrawLike :dataList="dataList" :scaleWidth="scaleWidth" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<style lang="less">
|
||||
.market {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
</template>
|
||||
.wapper {
|
||||
width: 100%;
|
||||
position: relative;
|
||||
height: 100%;
|
||||
padding-bottom: 20px;
|
||||
|
||||
<style lang="less">
|
||||
.market{
|
||||
padding: 15px;
|
||||
}
|
||||
&-item {
|
||||
z-index: 10;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
transition: all 0.5s;
|
||||
cursor: pointer;
|
||||
|
||||
.wapper{
|
||||
width: 100%;
|
||||
position: relative;
|
||||
height: 100%;
|
||||
padding-bottom: 20px;
|
||||
&:hover {
|
||||
.menu {
|
||||
transition: transform 0.3s ease-in-out;
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
img {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
}
|
||||
|
||||
.menu {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 94%;
|
||||
left: 3%;
|
||||
max-height: 70%;
|
||||
height: 100px;
|
||||
transform: translateY(100%);
|
||||
background-color: #090b15;
|
||||
opacity: 0.8;
|
||||
transition: all 0.1s cubic-bezier(0.68, -0.55, 0.265, 1.55);
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
|
||||
&-item{
|
||||
z-index: 10;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
transition: all 0.5s;
|
||||
cursor: pointer;
|
||||
.prompt {
|
||||
height: 50px;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover{
|
||||
.menu{
|
||||
transition: transform 0.3s ease-in-out;
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
img{
|
||||
transform: scale(1.1);
|
||||
}
|
||||
}
|
||||
img {
|
||||
user-select: none;
|
||||
cursor: pointer;
|
||||
transition: all 0.6s cubic-bezier(0.19, 1, 0.22, 1);
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.menu{
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 94%;
|
||||
left: 3%;
|
||||
max-height: 70%;
|
||||
height: 100px;
|
||||
transform: translateY(100%);
|
||||
background-color: #090b15;
|
||||
opacity: 0.8;
|
||||
transition: all .1s cubic-bezier(0.68, -0.55, 0.265, 1.55);
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
.item-loading {
|
||||
background: url(../../assets/img-bg.png) no-repeat center center;
|
||||
filter: blur(20px);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.prompt{
|
||||
height: 50px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
img{
|
||||
user-select: none;
|
||||
cursor: pointer;
|
||||
transition: all .6s cubic-bezier(0.19, 1, 0.22, 1);
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.item-loading{
|
||||
background: url(../../assets/img-bg.png) no-repeat center center;
|
||||
filter: blur(20px);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.img-enter-active, .img-leave-active {
|
||||
transition: transform .3s;
|
||||
}
|
||||
.img-enter, .img-leave-to{
|
||||
transform: scale(.6);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
.img-enter-active,
|
||||
.img-leave-active {
|
||||
transition: transform 0.3s;
|
||||
}
|
||||
.img-enter,
|
||||
.img-leave-to {
|
||||
transform: scale(0.6);
|
||||
opacity: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,67 +1,71 @@
|
||||
<script lang='ts' setup>
|
||||
import { NButton, NImage, NInput, NInputNumber, NSelect, NSpace, NSwitch, NTag, NTooltip, useDialog, useMessage, NScrollbar } from 'naive-ui'
|
||||
import { onMounted, reactive, ref, toRefs, watch, computed } from 'vue'
|
||||
import axios from 'axios'
|
||||
import { fetchDownloadImg } from '@/api'
|
||||
import type { ResData } from '@/api/types'
|
||||
import failImg from '@/assets/fail.png'
|
||||
import drawSvg from '@/assets/icons/draw.svg'
|
||||
import zoomSvg from '@/assets/icons/zoom.svg'
|
||||
import { useAppStore, useAuthStore } from '@/store'
|
||||
import { fetchDrawTaskAPI, fetchTranslateAPI } from '@/api/mjDraw'
|
||||
import { SvgIcon } from '@/components/common'
|
||||
import Loading from '@/components/base/Loading.vue'
|
||||
<script lang="ts" setup>
|
||||
import {
|
||||
NButton,
|
||||
NImage,
|
||||
NInput,
|
||||
NInputNumber,
|
||||
NSelect,
|
||||
NSpace,
|
||||
NSwitch,
|
||||
NTag,
|
||||
NTooltip,
|
||||
useDialog,
|
||||
useMessage,
|
||||
NScrollbar,
|
||||
} from 'naive-ui';
|
||||
import { onMounted, reactive, ref, toRefs, watch, computed } from 'vue';
|
||||
import axios from 'axios';
|
||||
import { fetchDownloadImg } from '@/api';
|
||||
import type { ResData } from '@/api/types';
|
||||
import failImg from '@/assets/fail.png';
|
||||
import drawSvg from '@/assets/icons/draw.svg';
|
||||
import zoomSvg from '@/assets/icons/zoom.svg';
|
||||
import { useAppStore, useAuthStore } from '@/store';
|
||||
import { fetchDrawTaskAPI, fetchTranslateAPI } from '@/api/mjDraw';
|
||||
import { SvgIcon } from '@/components/common';
|
||||
import Loading from '@/components/base/Loading.vue';
|
||||
|
||||
interface Emits {
|
||||
(e: 'usePrompt', val: any): void
|
||||
(e: 'queryData'): void
|
||||
(e: 'usePrompt', val: any): void;
|
||||
(e: 'queryData'): void;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
drawItemInfo: any
|
||||
drawItemInfo: any;
|
||||
}
|
||||
|
||||
const emit = defineEmits<Emits>()
|
||||
const appStore = useAppStore()
|
||||
const authStore = useAuthStore()
|
||||
const theme = computed(() => appStore.theme)
|
||||
const loadingTextColor = computed(() => theme.value === 'dark' ? '#fff' : '#000')
|
||||
const props = defineProps<Props>()
|
||||
const dialog = useDialog()
|
||||
const ms = useMessage()
|
||||
const downloadUrl = `${import.meta.env.VITE_GLOB_API_URL}/midjourney/download`
|
||||
const refreshLoading = ref(false)
|
||||
const emit = defineEmits<Emits>();
|
||||
const appStore = useAppStore();
|
||||
const authStore = useAuthStore();
|
||||
const theme = computed(() => appStore.theme);
|
||||
const loadingTextColor = computed(() =>
|
||||
theme.value === 'dark' ? '#fff' : '#000'
|
||||
);
|
||||
const props = defineProps<Props>();
|
||||
const dialog = useDialog();
|
||||
const ms = useMessage();
|
||||
const downloadUrl = `${import.meta.env.VITE_GLOB_API_URL}/midjourney/download`;
|
||||
const refreshLoading = ref(false);
|
||||
|
||||
const statusType: any = computed(() => {
|
||||
const { status } = props.drawItemInfo
|
||||
if (status === 1)
|
||||
return ''
|
||||
if (status === 2)
|
||||
return 'info'
|
||||
if (status === 3)
|
||||
return 'primary'
|
||||
if (status === 4)
|
||||
return 'error'
|
||||
if (status === 5)
|
||||
return 'error'
|
||||
})
|
||||
const { status } = props.drawItemInfo;
|
||||
if (status === 1) return '';
|
||||
if (status === 2) return 'info';
|
||||
if (status === 3) return 'primary';
|
||||
if (status === 4) return 'error';
|
||||
if (status === 5) return 'error';
|
||||
});
|
||||
const statusMsg = computed(() => {
|
||||
const { status } = props.drawItemInfo
|
||||
if (status === 1)
|
||||
return '等待中'
|
||||
if (status === 2)
|
||||
return '绘制中'
|
||||
if (status === 3)
|
||||
return '成功'
|
||||
if (status === 4)
|
||||
return '失败'
|
||||
if (status === 5)
|
||||
return '超时'
|
||||
})
|
||||
const { status } = props.drawItemInfo;
|
||||
if (status === 1) return '等待中';
|
||||
if (status === 2) return '绘制中';
|
||||
if (status === 3) return '成功';
|
||||
if (status === 4) return '失败';
|
||||
if (status === 5) return '超时';
|
||||
});
|
||||
|
||||
|
||||
function usePrompt(){
|
||||
emit('usePrompt')
|
||||
function usePrompt() {
|
||||
emit('usePrompt');
|
||||
}
|
||||
|
||||
/* 下载图片 */
|
||||
@@ -72,21 +76,27 @@ async function handleDownloadImg(item: any) {
|
||||
positiveText: '下载',
|
||||
negativeText: '取消',
|
||||
onPositiveClick: async () => {
|
||||
d.loading = true
|
||||
return new Promise(async (resolve) => {
|
||||
const { fileInfo } = item
|
||||
const { filename, cosUrl } = fileInfo
|
||||
const response = await axios.post(downloadUrl, { url: cosUrl }, { responseType: 'blob' })
|
||||
const blob = new Blob([response.data], { type: response.headers['content-type'] })
|
||||
const urlObject = window.URL.createObjectURL(blob)
|
||||
const link = document.createElement('a')
|
||||
link.href = urlObject
|
||||
link.download = filename
|
||||
link.click()
|
||||
resolve(true)
|
||||
})
|
||||
}
|
||||
})
|
||||
d.loading = true;
|
||||
return new Promise(async (resolve) => {
|
||||
const { fileInfo } = item;
|
||||
const { filename, cosUrl } = fileInfo;
|
||||
const response = await axios.post(
|
||||
downloadUrl,
|
||||
{ url: cosUrl },
|
||||
{ responseType: 'blob' }
|
||||
);
|
||||
const blob = new Blob([response.data], {
|
||||
type: response.headers['content-type'],
|
||||
});
|
||||
const urlObject = window.URL.createObjectURL(blob);
|
||||
const link = document.createElement('a');
|
||||
link.href = urlObject;
|
||||
link.download = filename;
|
||||
link.click();
|
||||
resolve(true);
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/* 删除图片 */
|
||||
@@ -97,375 +107,425 @@ async function handleDeleteDraw(item: any) {
|
||||
positiveText: '删除',
|
||||
negativeText: '取消',
|
||||
onPositiveClick: async () => {
|
||||
const { id } = item
|
||||
const res: ResData = await fetchDownloadImg({ id })
|
||||
if (!res.success)
|
||||
return ms.error(res.message)
|
||||
ms.success('删除绘制记录成功!')
|
||||
emit('queryData')
|
||||
const { id } = item;
|
||||
const res: ResData = await fetchDownloadImg({ id });
|
||||
if (!res.success) return ms.error(res.message);
|
||||
ms.success('删除绘制记录成功!');
|
||||
emit('queryData');
|
||||
},
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
/* 提交放大绘制任务 */
|
||||
async function handleUpscale(item: any, orderId: number) {
|
||||
const { id } = item
|
||||
await fetchDrawTaskAPI({ drawId: id, action: 2, orderId })
|
||||
ms.success('提交放大绘制任务成功、请等待绘制结束!')
|
||||
if(authStore.token){
|
||||
await refreshUserInfo()
|
||||
}
|
||||
emit('queryData')
|
||||
const { drawId } = item;
|
||||
await fetchDrawTaskAPI({ drawId: drawId, action: 'UPSCALE', orderId });
|
||||
ms.success('提交放大绘制任务成功、请等待绘制结束!');
|
||||
if (authStore.token) {
|
||||
await refreshUserInfo();
|
||||
}
|
||||
emit('queryData');
|
||||
}
|
||||
|
||||
/* 提交重新生成任务 */
|
||||
async function handleReGenerate(item: any, orderId: number) {
|
||||
const { id } = item
|
||||
await fetchDrawTaskAPI({ drawId: id, action: 5, orderId })
|
||||
ms.success('提交重新生成绘制任务成功、请等待绘制结束!')
|
||||
if(authStore.token){
|
||||
await refreshUserInfo()
|
||||
}
|
||||
emit('queryData')
|
||||
const { drawId } = item;
|
||||
await fetchDrawTaskAPI({ drawId: drawId, action: 'REGENERATE', orderId });
|
||||
ms.success('提交重新生成绘制任务成功、请等待绘制结束!');
|
||||
if (authStore.token) {
|
||||
await refreshUserInfo();
|
||||
}
|
||||
emit('queryData');
|
||||
}
|
||||
|
||||
/* 提交变体任务 */
|
||||
async function handleVariation(item: any, orderId: number) {
|
||||
const { id } = item
|
||||
await fetchDrawTaskAPI({ drawId: id, action: 3, orderId })
|
||||
ms.success('提交图片变换绘制任务成功、请等待绘制结束!')
|
||||
if(authStore.token){
|
||||
await refreshUserInfo()
|
||||
}
|
||||
emit('queryData')
|
||||
const { drawId } = item;
|
||||
await fetchDrawTaskAPI({ drawId: drawId, action: 'VARIATION', orderId });
|
||||
ms.success('提交图片变换绘制任务成功、请等待绘制结束!');
|
||||
if (authStore.token) {
|
||||
await refreshUserInfo();
|
||||
}
|
||||
emit('queryData');
|
||||
}
|
||||
|
||||
|
||||
async function refreshUserInfo() {
|
||||
refreshLoading.value = true
|
||||
refreshLoading.value = true;
|
||||
try {
|
||||
await authStore.getUserInfo()
|
||||
refreshLoading.value = false
|
||||
}
|
||||
catch (error) {
|
||||
refreshLoading.value = false
|
||||
await authStore.getUserInfo();
|
||||
refreshLoading.value = false;
|
||||
} catch (error) {
|
||||
refreshLoading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
const calcTips = computed(() => {
|
||||
const { progress, status } = props.drawItemInfo
|
||||
if (status === 1)
|
||||
return '正在排队中...'
|
||||
if (status === 2 && !progress)
|
||||
return '正在绘制中...'
|
||||
if (status === 2 && progress === 100)
|
||||
return '正在存储图片中...'
|
||||
})
|
||||
const { progress, status } = props.drawItemInfo;
|
||||
if (status === 1) return '正在排队中...';
|
||||
if (status === 2 && !progress) return '正在绘制中...';
|
||||
if (status === 2 && progress === 100) return '正在存储图片中...';
|
||||
});
|
||||
|
||||
/* 提交对单张图片调整任务 */
|
||||
async function handleVary(item: any, orderId: number) {
|
||||
const { id } = item
|
||||
await fetchDrawTaskAPI({ drawId: id, action: 7, orderId })
|
||||
ms.success('提交图片调整绘制任务成功、请等待绘制结束!')
|
||||
if(authStore.token){
|
||||
await refreshUserInfo()
|
||||
}
|
||||
emit('queryData')
|
||||
const { drawId } = item;
|
||||
await fetchDrawTaskAPI({ drawId: drawId, action: 'VARIATION', orderId });
|
||||
ms.success('提交图片调整绘制任务成功、请等待绘制结束!');
|
||||
if (authStore.token) {
|
||||
await refreshUserInfo();
|
||||
}
|
||||
emit('queryData');
|
||||
}
|
||||
|
||||
/* 提交对单张图片缩放任务 */
|
||||
async function handleZoom(item: any, orderId: number) {
|
||||
const { id } = item
|
||||
await fetchDrawTaskAPI({ drawId: id, action: 6, orderId })
|
||||
ms.success('提交图片调整绘制任务成功、请等待绘制结束!')
|
||||
if(authStore.token){
|
||||
await refreshUserInfo()
|
||||
}
|
||||
emit('queryData')
|
||||
const { drawId } = item;
|
||||
await fetchDrawTaskAPI({ drawId: drawId, action: 'UPSCALE', orderId });
|
||||
ms.success('提交图片调整绘制任务成功、请等待绘制结束!');
|
||||
if (authStore.token) {
|
||||
await refreshUserInfo();
|
||||
}
|
||||
emit('queryData');
|
||||
}
|
||||
|
||||
function handleRegion(file){}
|
||||
|
||||
function handleRegion(file) {}
|
||||
</script>
|
||||
|
||||
|
||||
<template>
|
||||
<div class="relative overflow-hidden rounded-md border p-4 transition-all hover:shadow dark:border-neutral-700">
|
||||
<div class="flex items-center justify-between">
|
||||
<span>
|
||||
<NTag size="small" :type="statusType">
|
||||
{{ statusMsg }}
|
||||
</NTag>
|
||||
</span>
|
||||
<div
|
||||
class="relative overflow-hidden rounded-md border p-4 transition-all hover:shadow dark:border-neutral-700"
|
||||
>
|
||||
<div class="flex items-center justify-between">
|
||||
<span>
|
||||
<NTag size="small" :type="statusType">
|
||||
{{ statusMsg }}
|
||||
</NTag>
|
||||
</span>
|
||||
|
||||
<NSpace>
|
||||
<NTooltip v-if="drawItemInfo.isGroup" placement="top" trigger="hover">
|
||||
<template #trigger>
|
||||
<NButton size="tiny" ghost @click="usePrompt">
|
||||
<template #icon>
|
||||
<SvgIcon icon="ri:brush-line" class="text-base" />
|
||||
</template>
|
||||
使用
|
||||
</NButton>
|
||||
</template>
|
||||
<div style="width: 240px">
|
||||
<p>{{ drawItemInfo.fullPrompt }}</p>
|
||||
</div>
|
||||
</NTooltip>
|
||||
<NSpace>
|
||||
<NTooltip
|
||||
v-if="drawItemInfo.action === 'IMAGINE'"
|
||||
placement="top"
|
||||
trigger="hover"
|
||||
>
|
||||
<template #trigger>
|
||||
<NButton size="tiny" ghost @click="usePrompt">
|
||||
<template #icon>
|
||||
<SvgIcon icon="ri:brush-line" class="text-base" />
|
||||
</template>
|
||||
使用
|
||||
</NButton>
|
||||
</template>
|
||||
<div style="width: 240px">
|
||||
<p>{{ drawItemInfo.fullPrompt }}</p>
|
||||
</div>
|
||||
</NTooltip>
|
||||
|
||||
<NButton size="tiny" ghost @click="handleDownloadImg(drawItemInfo)">
|
||||
<template #icon>
|
||||
<SvgIcon icon="mingcute:file-download-line" class="text-base" />
|
||||
</template>
|
||||
下载
|
||||
</NButton>
|
||||
<NButton size="tiny" ghost @click="handleDeleteDraw(drawItemInfo)">
|
||||
<template #icon>
|
||||
<SvgIcon icon="ri:delete-bin-line" class="text-base" />
|
||||
</template>
|
||||
删除
|
||||
</NButton>
|
||||
</NSpace>
|
||||
</div>
|
||||
<!-- content -->
|
||||
<div class="my-4 h-[280px]">
|
||||
<div v-if="drawItemInfo.status === 3" class="flex h-full w-full items-center justify-center overflow-hidden rounded-md">
|
||||
<NImage
|
||||
style="object-fit: contain;"
|
||||
:src="drawItemInfo.fileInfo.thumbImg"
|
||||
:preview-src="drawItemInfo.fileInfo.cosUrl"
|
||||
object-fit="contain"
|
||||
/>
|
||||
</div>
|
||||
<div v-if="[4, 5, 6].includes(drawItemInfo.status)" class="flex flex-col h-full w-full items-center justify-center overflow-hidden rounded-md">
|
||||
<img class="w-[75px]" :src="failImg">
|
||||
<span class="mt-3 text-base">绘制失败</span>
|
||||
<span class="mt-1">已退还余额至您的账户!</span>
|
||||
</div>
|
||||
<div v-if="[1, 2].includes(drawItemInfo.status)" class="my-4 h-[280px] relative">
|
||||
<Loading :text-color="loadingTextColor" :progress="drawItemInfo.progress" :tips="calcTips" />
|
||||
</div>
|
||||
</div>
|
||||
<!-- footer -->
|
||||
<div class="-mx-4 -mb-4 bg-[#fafafc] px-4 py-2 dark:bg-[#262629]">
|
||||
<div v-if="drawItemInfo.isGroup" class="w-full">
|
||||
<div class="mb-2 flex items-center justify-between">
|
||||
<span>放大:</span>
|
||||
<span class="text-base text-neutral-400">
|
||||
<NTooltip placement="top" trigger="hover">
|
||||
<template #trigger>
|
||||
<SvgIcon icon="ri:error-warning-line" class="text-base" />
|
||||
</template>
|
||||
<div style="width: 240px">
|
||||
<p>参数释义:放大某张图片如 U1 放大第一张图片,以此类推</p>
|
||||
</div>
|
||||
</NTooltip>
|
||||
</span>
|
||||
<div class="flex-1">
|
||||
<div class="flex items-center justify-around">
|
||||
<NButton size="tiny" @click="handleUpscale(drawItemInfo, 1)">
|
||||
U1
|
||||
</NButton>
|
||||
<NButton size="tiny" @click="handleUpscale(drawItemInfo, 2)">
|
||||
U2
|
||||
</NButton>
|
||||
<NButton size="tiny" @click="handleUpscale(drawItemInfo, 3)">
|
||||
U3
|
||||
</NButton>
|
||||
<NButton size="tiny" @click="handleUpscale(drawItemInfo, 4)">
|
||||
U4
|
||||
</NButton>
|
||||
<NTooltip placement="top" trigger="hover">
|
||||
<template #trigger>
|
||||
<NButton size="tiny" @click="handleReGenerate(drawItemInfo, 5)">
|
||||
<SvgIcon icon="solar:refresh-outline" class="text-base" />
|
||||
</NButton>
|
||||
</template>
|
||||
<p>重新生成一次</p>
|
||||
</NTooltip>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<NButton size="tiny" ghost @click="handleDownloadImg(drawItemInfo)">
|
||||
<template #icon>
|
||||
<SvgIcon icon="mingcute:file-download-line" class="text-base" />
|
||||
</template>
|
||||
下载
|
||||
</NButton>
|
||||
<NButton size="tiny" ghost @click="handleDeleteDraw(drawItemInfo)">
|
||||
<template #icon>
|
||||
<SvgIcon icon="ri:delete-bin-line" class="text-base" />
|
||||
</template>
|
||||
删除
|
||||
</NButton>
|
||||
</NSpace>
|
||||
</div>
|
||||
<!-- content -->
|
||||
<div class="my-4 h-[280px]">
|
||||
<div
|
||||
v-if="drawItemInfo.status === 3"
|
||||
class="flex h-full w-full items-center justify-center overflow-hidden rounded-md"
|
||||
>
|
||||
<NImage
|
||||
style="object-fit: contain"
|
||||
:src="drawItemInfo.drawUrl"
|
||||
:preview-src="drawItemInfo.drawUrl"
|
||||
object-fit="contain"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
v-if="[4, 5, 6].includes(drawItemInfo.status)"
|
||||
class="flex flex-col h-full w-full items-center justify-center overflow-hidden rounded-md"
|
||||
>
|
||||
<img class="w-[75px]" :src="failImg" />
|
||||
<span class="mt-3 text-base">绘制失败</span>
|
||||
<span class="mt-1">已退还余额至您的账户!</span>
|
||||
</div>
|
||||
<div
|
||||
v-if="[1, 2].includes(drawItemInfo.status)"
|
||||
class="my-4 h-[280px] relative"
|
||||
>
|
||||
<Loading
|
||||
:text-color="loadingTextColor"
|
||||
:progress="drawItemInfo.progress"
|
||||
:tips="calcTips"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<!-- footer -->
|
||||
<div class="-mx-4 -mb-4 bg-[#fafafc] px-4 py-2 dark:bg-[#262629]">
|
||||
<div
|
||||
v-if="
|
||||
(drawItemInfo.action === 'IMAGINE' ||
|
||||
drawItemInfo.action === 'VARIATION' ||
|
||||
drawItemInfo.action === 'ZOOM' ||
|
||||
drawItemInfo.action === 'OUTPAINT' ||
|
||||
drawItemInfo.action === 'REROLL') &&
|
||||
drawItemInfo.status === 3
|
||||
"
|
||||
class="w-full"
|
||||
>
|
||||
<div class="mb-2 flex items-center justify-between">
|
||||
<span>放大:</span>
|
||||
<span class="text-base text-neutral-400">
|
||||
<NTooltip placement="top" trigger="hover">
|
||||
<template #trigger>
|
||||
<SvgIcon icon="ri:error-warning-line" class="text-base" />
|
||||
</template>
|
||||
<div style="width: 240px">
|
||||
<p>参数释义:放大某张图片如 U1 放大第一张图片,以此类推</p>
|
||||
</div>
|
||||
</NTooltip>
|
||||
</span>
|
||||
<div class="flex-1">
|
||||
<div class="flex items-center justify-around">
|
||||
<NButton size="tiny" @click="handleUpscale(drawItemInfo, 1)">
|
||||
U1
|
||||
</NButton>
|
||||
<NButton size="tiny" @click="handleUpscale(drawItemInfo, 2)">
|
||||
U2
|
||||
</NButton>
|
||||
<NButton size="tiny" @click="handleUpscale(drawItemInfo, 3)">
|
||||
U3
|
||||
</NButton>
|
||||
<NButton size="tiny" @click="handleUpscale(drawItemInfo, 4)">
|
||||
U4
|
||||
</NButton>
|
||||
<NTooltip placement="top" trigger="hover">
|
||||
<template #trigger>
|
||||
<NButton
|
||||
size="tiny"
|
||||
@click="handleReGenerate(drawItemInfo, 5)"
|
||||
>
|
||||
<SvgIcon icon="solar:refresh-outline" class="text-base" />
|
||||
</NButton>
|
||||
</template>
|
||||
<p>重新生成一次</p>
|
||||
</NTooltip>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 套图 新生成 变体图 重新生成 三种类型 -->
|
||||
<div v-if="drawItemInfo.isGroup" class="w-full">
|
||||
<div class="mb-2 flex items-center justify-between">
|
||||
<span>变换:</span>
|
||||
<span class="text-base text-neutral-400">
|
||||
<NTooltip placement="top" trigger="hover">
|
||||
<template #trigger>
|
||||
<SvgIcon icon="ri:error-warning-line" class="text-base" />
|
||||
</template>
|
||||
<div style="width: 240px">
|
||||
<p>参数释义:以某张图片为基准重新生成
|
||||
如 V1 则变换第一张图片,以此类推</p>
|
||||
</div>
|
||||
</NTooltip>
|
||||
</span>
|
||||
<div class="flex-1">
|
||||
<div class="flex items-center justify-around">
|
||||
<NButton size="tiny" @click="handleVariation(drawItemInfo, 1)">
|
||||
V1
|
||||
</NButton>
|
||||
<NButton size="tiny" @click="handleVariation(drawItemInfo, 2)">
|
||||
V2
|
||||
</NButton>
|
||||
<NButton size="tiny" @click="handleVariation(drawItemInfo, 3)">
|
||||
V3
|
||||
</NButton>
|
||||
<NButton size="tiny" @click="handleVariation(drawItemInfo, 4)">
|
||||
V4
|
||||
</NButton>
|
||||
<NButton size="tiny" style="opacity:0">
|
||||
V5
|
||||
</NButton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 套图 新生成 变体图 重新生成 三种类型 -->
|
||||
<div
|
||||
v-if="
|
||||
(drawItemInfo.action === 'IMAGINE' ||
|
||||
drawItemInfo.action === 'VARIATION' ||
|
||||
drawItemInfo.action === 'ZOOM' ||
|
||||
drawItemInfo.action === 'OUTPAINT' ||
|
||||
drawItemInfo.action === 'REROLL') &&
|
||||
drawItemInfo.status === 3
|
||||
"
|
||||
class="w-full"
|
||||
>
|
||||
<div class="mb-2 flex items-center justify-between">
|
||||
<span>变换:</span>
|
||||
<span class="text-base text-neutral-400">
|
||||
<NTooltip placement="top" trigger="hover">
|
||||
<template #trigger>
|
||||
<SvgIcon icon="ri:error-warning-line" class="text-base" />
|
||||
</template>
|
||||
<div style="width: 240px">
|
||||
<p>
|
||||
参数释义:以某张图片为基准重新生成 如 V1
|
||||
则变换第一张图片,以此类推
|
||||
</p>
|
||||
</div>
|
||||
</NTooltip>
|
||||
</span>
|
||||
<div class="flex-1">
|
||||
<div class="flex items-center justify-around">
|
||||
<NButton size="tiny" @click="handleVariation(drawItemInfo, 1)">
|
||||
V1
|
||||
</NButton>
|
||||
<NButton size="tiny" @click="handleVariation(drawItemInfo, 2)">
|
||||
V2
|
||||
</NButton>
|
||||
<NButton size="tiny" @click="handleVariation(drawItemInfo, 3)">
|
||||
V3
|
||||
</NButton>
|
||||
<NButton size="tiny" @click="handleVariation(drawItemInfo, 4)">
|
||||
V4
|
||||
</NButton>
|
||||
<NButton size="tiny" style="opacity: 0"> V5 </NButton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 对老图片增强 单张图或生成中的图 -->
|
||||
<div v-if="!drawItemInfo.isGroup && drawItemInfo.orderId" class="w-full mb-2 flex items-center justify-between">
|
||||
<!-- 图片放大或变体 并且图片还未生成成功的时候没有message_id -->
|
||||
<div v-if="drawItemInfo.orderId !== 5 && !drawItemInfo.extend">
|
||||
<span v-if="drawItemInfo.action === 2">
|
||||
操作:{{ `选中套图第${drawItemInfo.orderId || 'x'}张图片进行放大` }}
|
||||
</span>
|
||||
<span v-if="drawItemInfo.action === 3">
|
||||
操作:{{ `选中套图第${drawItemInfo.orderId || 'x'}张图片进行变换` }}
|
||||
</span>
|
||||
</div>
|
||||
<!-- 已经生成成功的单张图 可以zoom和vary -->
|
||||
<div v-if="drawItemInfo.orderId !== 5 && drawItemInfo.extend" class="flex w-full">
|
||||
<div class="mb-2 flex flex-1 items-center justify-between">
|
||||
<span>调整:</span>
|
||||
<span class="text-base text-neutral-400">
|
||||
<NTooltip placement="top" trigger="hover">
|
||||
<template #trigger>
|
||||
<SvgIcon icon="ri:error-warning-line" class="text-base" />
|
||||
</template>
|
||||
<div style="width: 275px">
|
||||
<p>参数释义:Vary 以当前图片为基础调整图片</p>
|
||||
</div>
|
||||
</NTooltip>
|
||||
</span>
|
||||
<div class="flex-1">
|
||||
<div class="flex items-center pl-2">
|
||||
<NSpace>
|
||||
<NTooltip placement="top" trigger="hover">
|
||||
<template #trigger>
|
||||
<NButton size="tiny" @click="handleVary(drawItemInfo, 1)">
|
||||
<template #icon>
|
||||
<img :src="drawSvg" class="w-4" alt="">
|
||||
</template>
|
||||
V(Strong)
|
||||
</NButton>
|
||||
</template>
|
||||
<p>以当前图片为基础大幅增强</p>
|
||||
</NTooltip>
|
||||
<!-- 对老图片增强 单张图或生成中的图 -->
|
||||
<div
|
||||
v-if="drawItemInfo.progress !== 100 && drawItemInfo.status !== 3"
|
||||
class="w-full mb-2 flex items-center justify-between"
|
||||
>
|
||||
<!-- 图片放大或变体 并且图片还未生成成功的时候没有message_id -->
|
||||
<div v-if="drawItemInfo.orderId !== 5">
|
||||
<span v-if="drawItemInfo.action === 'UPSCALE'">
|
||||
操作:{{ `选中套图第${drawItemInfo.orderId || 'x'}张图片进行放大` }}
|
||||
</span>
|
||||
<span v-if="drawItemInfo.action === 'VARIATION'">
|
||||
操作:{{ `选中套图第${drawItemInfo.orderId || 'x'}张图片进行变换` }}
|
||||
</span>
|
||||
</div>
|
||||
<!-- 已经生成成功的单张图 可以zoom和vary -->
|
||||
|
||||
<NTooltip placement="top" trigger="hover">
|
||||
<template #trigger>
|
||||
<NButton size="tiny" @click="handleVary(drawItemInfo, 2)">
|
||||
<template #icon>
|
||||
<img :src="drawSvg" class="w-4" alt="">
|
||||
</template>
|
||||
V(Subtle)
|
||||
</NButton>
|
||||
</template>
|
||||
<p>以当前图片为基础细微调整</p>
|
||||
</NTooltip>
|
||||
</NSpace>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 重新绘制套图【只在生成中显示 生成完毕即会进入group套图】 -->
|
||||
<span v-if="drawItemInfo.orderId === 5">
|
||||
操作:正在对图片重新生成一次
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- 重新绘制套图【只在生成中显示 生成完毕即会进入group套图】 -->
|
||||
<span v-if="drawItemInfo.orderId === 5">
|
||||
操作:正在对图片重新生成一次
|
||||
</span>
|
||||
</div>
|
||||
<!-- 新图绘制中 -->
|
||||
<div
|
||||
v-if="
|
||||
drawItemInfo.action === 'IMAGINE' &&
|
||||
!drawItemInfo.orderId &&
|
||||
drawItemInfo.status === 'UPSCALE'
|
||||
"
|
||||
class="w-full mb-2 flex items-center justify-between"
|
||||
>
|
||||
操作:正在火速绘制中...
|
||||
</div>
|
||||
|
||||
<!-- 新图绘制中 -->
|
||||
<div v-if="!drawItemInfo.isGroup && !drawItemInfo.orderId && drawItemInfo.status === 2" class="w-full mb-2 flex items-center justify-between">
|
||||
操作:正在火速绘制中...
|
||||
</div>
|
||||
<!-- 绘制失败了 -->
|
||||
<div
|
||||
v-if="!drawItemInfo.orderId && [4, 5, 6].includes(drawItemInfo.status)"
|
||||
class="w-full mb-2 flex items-center justify-between"
|
||||
>
|
||||
执行: 换个提示词重新试试吧!
|
||||
</div>
|
||||
<!-- 加载失败 -->
|
||||
<div
|
||||
v-if="!drawItemInfo.action && !drawItemInfo.extend"
|
||||
class="w-full mb-2 flex items-center justify-between"
|
||||
>
|
||||
上级: {{ drawItemInfo.message_id || '正在加载中...' }}
|
||||
</div>
|
||||
|
||||
<!-- 绘制失败了 -->
|
||||
<div v-if="!drawItemInfo.isGroup && !drawItemInfo.orderId && [4, 5, 6].includes(drawItemInfo.status) " class="w-full mb-2 flex items-center justify-between">
|
||||
执行: 换个提示词重新试试吧!
|
||||
</div>
|
||||
<!-- 加载失败 -->
|
||||
<div v-if="!drawItemInfo.isGroup && !drawItemInfo.extend" class="w-full mb-2 flex items-center justify-between">
|
||||
上级: {{ drawItemInfo.message_id || '正在加载中...' }}
|
||||
</div>
|
||||
<!-- 2 -->
|
||||
<div
|
||||
v-if="
|
||||
(drawItemInfo.action === 'UPSCALE' ||
|
||||
drawItemInfo.action === 'ACTION') &&
|
||||
drawItemInfo.status === 3
|
||||
"
|
||||
>
|
||||
<div class="mb-2 flex flex-1 items-center justify-between">
|
||||
<span>缩放:</span>
|
||||
<span class="text-base text-neutral-400">
|
||||
<NTooltip placement="top" trigger="hover">
|
||||
<template #trigger>
|
||||
<SvgIcon icon="ri:error-warning-line" class="text-base" />
|
||||
</template>
|
||||
<div style="width: 270px">
|
||||
<p>参数释义:Zoom 对当前图片进行无限缩放</p>
|
||||
</div>
|
||||
</NTooltip>
|
||||
</span>
|
||||
<div class="flex-1">
|
||||
<div class="flex items-center pl-2">
|
||||
<NSpace>
|
||||
<NTooltip placement="top" trigger="hover">
|
||||
<template #trigger>
|
||||
<NButton size="tiny" @click="handleZoom(drawItemInfo, 1)">
|
||||
<template #icon>
|
||||
<img :src="zoomSvg" class="w-4" alt="" />
|
||||
</template>
|
||||
U(Subtle)
|
||||
</NButton>
|
||||
</template>
|
||||
<p>放大</p>
|
||||
</NTooltip>
|
||||
|
||||
<!-- -->
|
||||
<div v-if="!drawItemInfo.isGroup && drawItemInfo.orderId !== 5 && drawItemInfo.extend">
|
||||
<div class="mb-2 flex flex-1 items-center justify-between">
|
||||
<span>缩放:</span>
|
||||
<span class="text-base text-neutral-400">
|
||||
<NTooltip placement="top" trigger="hover">
|
||||
<template #trigger>
|
||||
<SvgIcon icon="ri:error-warning-line" class="text-base" />
|
||||
</template>
|
||||
<div style="width: 270px">
|
||||
<p>参数释义:Zoom 对当前图片进行无限缩放</p>
|
||||
</div>
|
||||
</NTooltip>
|
||||
</span>
|
||||
<div class="flex-1">
|
||||
<div class="flex items-center pl-2">
|
||||
<NSpace>
|
||||
<NTooltip placement="top" trigger="hover">
|
||||
<template #trigger>
|
||||
<NButton size="tiny" @click="handleZoom(drawItemInfo, 1)">
|
||||
<template #icon>
|
||||
<img :src="zoomSvg" class="w-4" alt="">
|
||||
</template>
|
||||
Zoom 2
|
||||
</NButton>
|
||||
</template>
|
||||
<p>缩放2倍</p>
|
||||
</NTooltip>
|
||||
<NTooltip placement="top" trigger="hover">
|
||||
<template #trigger>
|
||||
<NButton size="tiny" @click="handleZoom(drawItemInfo, 2)">
|
||||
<template #icon>
|
||||
<img :src="zoomSvg" class="w-4" alt="" />
|
||||
</template>
|
||||
U(Creative)
|
||||
</NButton>
|
||||
</template>
|
||||
<p>放大</p>
|
||||
</NTooltip>
|
||||
</NSpace>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="
|
||||
(drawItemInfo.action === 'UPSCALE' ||
|
||||
drawItemInfo.action === 'ACTION') &&
|
||||
drawItemInfo.status === 3
|
||||
"
|
||||
class="flex w-full"
|
||||
>
|
||||
<div class="mb-2 flex flex-1 items-center justify-between">
|
||||
<span>调整:</span>
|
||||
<span class="text-base text-neutral-400">
|
||||
<NTooltip placement="top" trigger="hover">
|
||||
<template #trigger>
|
||||
<SvgIcon icon="ri:error-warning-line" class="text-base" />
|
||||
</template>
|
||||
<div style="width: 275px">
|
||||
<p>参数释义:Vary 以当前图片为基础调整图片</p>
|
||||
</div>
|
||||
</NTooltip>
|
||||
</span>
|
||||
<div class="flex-1">
|
||||
<div class="flex items-center pl-2">
|
||||
<NSpace>
|
||||
<NTooltip placement="top" trigger="hover">
|
||||
<template #trigger>
|
||||
<NButton size="tiny" @click="handleVary(drawItemInfo, 1)">
|
||||
<template #icon>
|
||||
<img :src="drawSvg" class="w-4" alt="" />
|
||||
</template>
|
||||
V(Strong)
|
||||
</NButton>
|
||||
</template>
|
||||
<p>以当前图片为基础大幅增强</p>
|
||||
</NTooltip>
|
||||
|
||||
<NTooltip placement="top" trigger="hover">
|
||||
<template #trigger>
|
||||
<NButton size="tiny" @click="handleZoom(drawItemInfo, 2)">
|
||||
<template #icon>
|
||||
<img :src="zoomSvg" class="w-4" alt="">
|
||||
</template>
|
||||
Zoom 1.5
|
||||
</NButton>
|
||||
</template>
|
||||
<p>缩放1.5倍</p>
|
||||
</NTooltip>
|
||||
<NTooltip placement="top" trigger="hover">
|
||||
<template #trigger>
|
||||
<NButton size="tiny" @click="handleVary(drawItemInfo, 2)">
|
||||
<template #icon>
|
||||
<img :src="drawSvg" class="w-4" alt="" />
|
||||
</template>
|
||||
V(Subtle)
|
||||
</NButton>
|
||||
</template>
|
||||
<p>以当前图片为基础细微调整</p>
|
||||
</NTooltip>
|
||||
</NSpace>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- <NTooltip placement="top" trigger="hover">
|
||||
<template #trigger>
|
||||
<NButton size="tiny" @click="handleRegion(drawItemInfo)">
|
||||
<template #icon>
|
||||
<img :src="zoomSvg" class="w-4" alt="">
|
||||
</template>
|
||||
Region
|
||||
</NButton>
|
||||
</template>
|
||||
<p>缩放2倍</p>
|
||||
</NTooltip> -->
|
||||
</NSpace>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-full flex">
|
||||
<span class="text-[#64748b]">时间:{{ drawItemInfo.createdAt }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="w-full flex">
|
||||
<span class="text-[#64748b]">时间:{{ drawItemInfo.createdAt }}</span>
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
|
||||
</style>
|
||||
<style lang="scss" scoped></style>
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -59,7 +59,7 @@ const demoData = `
|
||||
`
|
||||
|
||||
const prompt = ref('')
|
||||
const initValue = `# NineAi
|
||||
const initValue = `# YiAi
|
||||
## 基础功能
|
||||
- 支持AI聊天
|
||||
- 支持GPT4
|
||||
|
||||
@@ -10,8 +10,8 @@ function setupPlugins(env: ImportMetaEnv): PluginOption[] {
|
||||
env.VITE_GLOB_APP_PWA === 'true' && VitePWA({
|
||||
injectRegister: 'auto',
|
||||
manifest: {
|
||||
name: 'Nine AI',
|
||||
short_name: 'Nine AI',
|
||||
name: 'YI AI',
|
||||
short_name: 'YI AI',
|
||||
icons: [
|
||||
{ src: 'pwa-192x192.png', sizes: '192x192', type: 'image/png' },
|
||||
{ src: 'pwa-512x512.png', sizes: '512x512', type: 'image/png' },
|
||||
|
||||
Reference in New Issue
Block a user