refactor: migrate from Vue CLI to Vite, update WebSocket handling, and clean up configuration

- Replaced vue.config.js with vite.config.js for Vite setup.
- Updated WebSocket implementation in webSocket.js for improved readability and performance.
- Removed unnecessary comments and cleaned up code formatting.
- Configured Vite plugins for auto-imports, SVG icons, and component resolution.
- Set up proxy configurations for API endpoints in Vite.
This commit is contained in:
bighuixiang
2025-06-18 14:31:35 +08:00
parent 9191678708
commit 3a52cc1e53
19 changed files with 20706 additions and 26139 deletions

4
.env
View File

@@ -1,4 +1,4 @@
# NODE_ENV = 'production'
NODE_ENV = 'development'
# VUE_APP_BASE_URL = 'http://18.167.251.121:10086'
VUE_APP_BASE_URL = 'https://www.api.aida.com.hk'
# VITE_APP_BASE_URL = 'http://18.167.251.121:10086'
VITE_APP_BASE_URL = 'https://www.api.aida.com.hk'

View File

@@ -1,11 +1,11 @@
NODE_ENV = 'development'
# VUE_APP_BASE_URL = 'https://develop.api.aida.com.hk'
# VUE_APP_BASE_URL = 'https://api.aida.com.hk'
# VITE_APP_BASE_URL = 'https://develop.api.aida.com.hk'
# VITE_APP_BASE_URL = 'https://api.aida.com.hk'
# VUE_APP_BASE_URL = 'http://18.167.251.121:10086'
VUE_APP_BASE_URL = 'https://develop.api.aida.com.hk'
# VUE_APP_BASE_URL = 'https://www.api.aida.com.hk'
# VITE_APP_BASE_URL = 'http://18.167.251.121:10086'
VITE_APP_BASE_URL = 'https://develop.api.aida.com.hk'
# VITE_APP_BASE_URL = 'https://www.api.aida.com.hk'
# 徐佩
# VUE_APP_BASE_URL = 'http://192.168.31.118:5567'
# VITE_APP_BASE_URL = 'http://192.168.31.118:5567'
# 海波
# VUE_APP_BASE_URL = 'http://192.168.31.34:5567'
# VITE_APP_BASE_URL = 'http://192.168.31.34:5567'

View File

@@ -1,7 +1,7 @@
NODE_ENV = 'production'
# VUE_APP_BASE_URL = 'https://aida.com.hk/test'
# VUE_APP_BASE_URL = 'http://18.167.251.121:10088'
# VUE_APP_BASE_URL = 'https://api.aida.com.hk'
VUE_APP_BASE_URL = 'https://develop.api.aida.com.hk'
# VITE_APP_BASE_URL = 'https://aida.com.hk/test'
# VITE_APP_BASE_URL = 'http://18.167.251.121:10088'
# VITE_APP_BASE_URL = 'https://api.aida.com.hk'
VITE_APP_BASE_URL = 'https://develop.api.aida.com.hk'

View File

@@ -1,4 +1,4 @@
NODE_ENV = 'production'
# VUE_APP_BASE_URL = 'http://18.167.251.121:10086'
# VUE_APP_BASE_URL = 'https://polyu.api.aida.com.hk'
VUE_APP_BASE_URL = 'https://www.api.aida.com.hk'
# VITE_APP_BASE_URL = 'http://18.167.251.121:10086'
# VITE_APP_BASE_URL = 'https://polyu.api.aida.com.hk'
VITE_APP_BASE_URL = 'https://www.api.aida.com.hk'

View File

@@ -1,7 +1,7 @@
NODE_ENV = 'development'
VUE_APP_BASE_URL = 'https://test.api.aida.com.hk'
# VUE_APP_BASE_URL = 'https://api.aida.com.hk'
VITE_APP_BASE_URL = 'https://test.api.aida.com.hk'
# VITE_APP_BASE_URL = 'https://api.aida.com.hk'
# VUE_APP_BASE_URL = 'http://18.167.251.121:10086'
# VUE_APP_BASE_URL = 'http://192.168.1.9:5567'
# VUE_APP_BASE_URL = 'http://192.168.1.6:7766'
# VITE_APP_BASE_URL = 'http://18.167.251.121:10086'
# VITE_APP_BASE_URL = 'http://192.168.1.9:5567'
# VITE_APP_BASE_URL = 'http://192.168.1.6:7766'

View File

@@ -1,7 +1,7 @@
NODE_ENV = 'production'
# VUE_APP_BASE_URL = 'https://aida.com.hk/test'
# VUE_APP_BASE_URL = 'http://18.167.251.121:10088'
# VUE_APP_BASE_URL = 'https://api.aida.com.hk'
# VUE_APP_BASE_URL = 'https://test.api.aida.com.hk'
VUE_APP_BASE_URL = 'https://develop.api.aida.com.hk'
# VITE_APP_BASE_URL = 'https://aida.com.hk/test'
# VITE_APP_BASE_URL = 'http://18.167.251.121:10088'
# VITE_APP_BASE_URL = 'https://api.aida.com.hk'
# VITE_APP_BASE_URL = 'https://test.api.aida.com.hk'
VITE_APP_BASE_URL = 'https://develop.api.aida.com.hk'

14
components.d.ts vendored Normal file
View File

@@ -0,0 +1,14 @@
/* eslint-disable */
// @ts-nocheck
// Generated by unplugin-vue-components
// Read more: https://github.com/vuejs/core/pull/3399
// biome-ignore lint: disable
export {}
/* prettier-ignore */
declare module 'vue' {
export interface GlobalComponents {
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
}
}

22674
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -3,13 +3,15 @@
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"serve:test": "vue-cli-service serve --mode test",
"build:test": "vue-cli-service build --mode test_build",
"serve:dev": "vue-cli-service serve --mode dev",
"build:dev": "vue-cli-service build --mode dev_build",
"lint": "vue-cli-service lint"
"dev": "vite",
"serve": "vite",
"build": "vite build",
"preview": "vite preview",
"serve:test": "vite --mode test",
"build:test": "vite build --mode test_build",
"serve:dev": "vite --mode dev",
"build:dev": "vite build --mode dev_build",
"lint": "eslint src --ext .js,.ts,.vue --fix"
},
"dependencies": {
"@ans1998/vue3-color": "^3.0.7",
@@ -20,8 +22,8 @@
"core-js": "^3.8.3",
"driver.js": "^1.3.1",
"echarts": "^5.5.1",
"fabric-with-all": "^5.3.1",
"element-plus": "^2.4.2",
"fabric-with-all": "^5.3.1",
"file-saver": "^2.0.5",
"fingerprintjs2": "^2.1.4",
"gsap": "^3.12.5",
@@ -45,6 +47,7 @@
"@types/three": "^0.174.0",
"@typescript-eslint/eslint-plugin": "^5.4.0",
"@typescript-eslint/parser": "^5.4.0",
"@vitejs/plugin-vue": "^5.2.4",
"@vue/cli-plugin-babel": "~5.0.0",
"@vue/cli-plugin-eslint": "~5.0.0",
"@vue/cli-plugin-router": "~5.0.0",
@@ -59,7 +62,11 @@
"less-loader": "^11.0.0",
"style-resources-loader": "^1.5.0",
"typescript": "~4.5.5",
"unplugin-auto-import": "^19.3.0",
"unplugin-element-plus": "^0.8.0",
"unplugin-vue-components": "^28.7.0",
"vite": "^6.3.5",
"vite-plugin-svg-icons": "^2.0.1",
"vue-cli-plugin-style-resources-loader": "^0.1.5",
"vue-lazyload": "^3.0.0-rc.2"
},

View File

@@ -1,11 +1,12 @@
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"> -->
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<link rel="icon" href="/favicon.ico">
<title>AiDA</title>
<!-- <link href="https://fonts.font.im/css?family=Roboto:400,500,700,700i" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700;900&display=swap" rel="stylesheet"> -->
@@ -14,14 +15,17 @@
<link rel="stylesheet" href="/css/roboto.css">
<link rel="stylesheet" href="/css/sloganFamily.css">
</head>
<body>
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/color-thief/2.3.0/color-thief.umd.js"></script> -->
<script src="/js/color-thief.js"></script>
<script src="/js/aligning_guidelines.js"></script>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
<strong>We're sorry but AiDA doesn't work properly without JavaScript enabled. Please enable it to
continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
<script type="module" src="/src/main.ts"></script>
</body>
</html>

89
src/auto-imports.d.ts vendored Normal file
View File

@@ -0,0 +1,89 @@
/* eslint-disable */
/* prettier-ignore */
// @ts-nocheck
// noinspection JSUnusedGlobalSymbols
// Generated by unplugin-auto-import
// biome-ignore lint: disable
export {}
declare global {
const EffectScope: typeof import('vue')['EffectScope']
const cloneDeep: typeof import('lodash-es')['cloneDeep']
const cloneDeepWith: typeof import('lodash-es')['cloneDeepWith']
const computed: typeof import('vue')['computed']
const createApp: typeof import('vue')['createApp']
const customRef: typeof import('vue')['customRef']
const debounce: typeof import('lodash-es')['debounce']
const defineAsyncComponent: typeof import('vue')['defineAsyncComponent']
const defineComponent: typeof import('vue')['defineComponent']
const effectScope: typeof import('vue')['effectScope']
const getCurrentInstance: typeof import('vue')['getCurrentInstance']
const getCurrentScope: typeof import('vue')['getCurrentScope']
const h: typeof import('vue')['h']
const inject: typeof import('vue')['inject']
const isArray: typeof import('lodash-es')['isArray']
const isBoolean: typeof import('lodash-es')['isBoolean']
const isDate: typeof import('lodash-es')['isDate']
const isFunction: typeof import('lodash-es')['isFunction']
const isNaN: typeof import('lodash-es')['isNaN']
const isNull: typeof import('lodash-es')['isNull']
const isNumber: typeof import('lodash-es')['isNumber']
const isObject: typeof import('lodash-es')['isObject']
const isProxy: typeof import('vue')['isProxy']
const isReactive: typeof import('vue')['isReactive']
const isReadonly: typeof import('vue')['isReadonly']
const isRef: typeof import('vue')['isRef']
const isString: typeof import('lodash-es')['isString']
const isUndefined: typeof import('lodash-es')['isUndefined']
const markRaw: typeof import('vue')['markRaw']
const nextTick: typeof import('vue')['nextTick']
const onActivated: typeof import('vue')['onActivated']
const onBeforeMount: typeof import('vue')['onBeforeMount']
const onBeforeRouteLeave: typeof import('vue-router')['onBeforeRouteLeave']
const onBeforeRouteUpdate: typeof import('vue-router')['onBeforeRouteUpdate']
const onBeforeUnmount: typeof import('vue')['onBeforeUnmount']
const onBeforeUpdate: typeof import('vue')['onBeforeUpdate']
const onDeactivated: typeof import('vue')['onDeactivated']
const onErrorCaptured: typeof import('vue')['onErrorCaptured']
const onMounted: typeof import('vue')['onMounted']
const onRenderTracked: typeof import('vue')['onRenderTracked']
const onRenderTriggered: typeof import('vue')['onRenderTriggered']
const onScopeDispose: typeof import('vue')['onScopeDispose']
const onServerPrefetch: typeof import('vue')['onServerPrefetch']
const onUnmounted: typeof import('vue')['onUnmounted']
const onUpdated: typeof import('vue')['onUpdated']
const onWatcherCleanup: typeof import('vue')['onWatcherCleanup']
const provide: typeof import('vue')['provide']
const reactive: typeof import('vue')['reactive']
const readonly: typeof import('vue')['readonly']
const ref: typeof import('vue')['ref']
const resolveComponent: typeof import('vue')['resolveComponent']
const shallowReactive: typeof import('vue')['shallowReactive']
const shallowReadonly: typeof import('vue')['shallowReadonly']
const shallowRef: typeof import('vue')['shallowRef']
const toRaw: typeof import('vue')['toRaw']
const toRef: typeof import('vue')['toRef']
const toRefs: typeof import('vue')['toRefs']
const toValue: typeof import('vue')['toValue']
const triggerRef: typeof import('vue')['triggerRef']
const unref: typeof import('vue')['unref']
const useAttrs: typeof import('vue')['useAttrs']
const useCssModule: typeof import('vue')['useCssModule']
const useCssVars: typeof import('vue')['useCssVars']
const useId: typeof import('vue')['useId']
const useLink: typeof import('vue-router')['useLink']
const useModel: typeof import('vue')['useModel']
const useRoute: typeof import('vue-router')['useRoute']
const useRouter: typeof import('vue-router')['useRouter']
const useSlots: typeof import('vue')['useSlots']
const useTemplateRef: typeof import('vue')['useTemplateRef']
const watch: typeof import('vue')['watch']
const watchEffect: typeof import('vue')['watchEffect']
const watchPostEffect: typeof import('vue')['watchPostEffect']
const watchSyncEffect: typeof import('vue')['watchSyncEffect']
}
// for type re-export
declare global {
// @ts-ignore
export type { Component, Slot, Slots, ComponentPublicInstance, ComputedRef, DirectiveBinding, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, MaybeRef, MaybeRefOrGetter, VNode, WritableComputedRef } from 'vue'
import('vue')
}

View File

@@ -306,7 +306,7 @@ export class BatchInitializeRedGreenModeCommand extends Command {
*/
async _setupBackgroundLayer(backgroundLayer, clothingImage) {
let backgroundObject = backgroundLayer.fabricObject;
const { object } = findObjectById(this.canvas, backgroundObject.id);
let { object } = findObjectById(this.canvas, backgroundObject.id);
if (!object) {
// 创建白色背景矩形

View File

@@ -1,311 +1,488 @@
<template>
<div class="chat" :class="{ active: !openChat }" @click.stop="">
<div class="top" :class="{active:!isChattingRecords}" @click="()=>{isChattingRecords=!isChattingRecords}">
<div
class="top"
:class="{ active: !isChattingRecords }"
@click="
() => {
isChattingRecords = !isChattingRecords;
}
"
>
<i class="fi fi-br-angle-small-down"></i>
</div>
<div v-show="!openChat" class="left" @click="()=>{openChat = !openChat;isChattingRecords=true}">
<div
v-show="!openChat"
class="left"
@click="
() => {
openChat = !openChat;
isChattingRecords = true;
}
"
>
<i class="fi fi-br-angle-small-down"></i>
</div>
<div class="chatBox">
<div class="chattingRecords" v-show="chatList.length > 0 && isChattingRecords">
<div
class="chattingRecords"
v-show="chatList.length > 0 && isChattingRecords"
>
<div class="itemBox" ref="chatBox">
<div class="item" v-for="item in chatList" :class="{user:item.role == 'user'}">
<div
class="item"
v-for="item in chatList"
:class="{ user: item.role == 'user' }"
>
<div class="textBox">
<div class="icon">
<img src="@/assets/images/icon/favicon.png" alt="">
<img src="@/assets/images/icon/favicon.png" alt="" />
</div>
<div class="text" v-show="item.content.think || item.content.message || item.content.img || item.content.color">
<div
class="text"
v-show="
item.content.think ||
item.content.message ||
item.content.img ||
item.content.color
"
>
<span class="content">
<div class="showThink" :class="{active:item.content?.isThink}" v-show="item.content.think" @click="()=>item.content?.isThink?(item.content.isThink = false):(item.content.isThink = true)">
<div
class="showThink"
:class="{ active: item.content?.isThink }"
v-show="item.content.think"
@click="
() =>
item.content?.isThink
? (item.content.isThink = false)
: (item.content.isThink = true)
"
>
<div>已深度思考</div>
<i class="fi fi-br-angle-small-down"></i>
</div>
<div class="think" v-show="item.content?.isThink">{{item.content.think}}</div>
<div class="think" v-show="item.content?.isThink">
{{ item.content.think }}
</div>
<div class="txt">{{ item.content.message }}</div>
</span>
<div class="fileBox">
<div v-if="item?.fileList?.length > 0" class="item" v-for="fileItem in item.fileList">
<div
v-if="item?.fileList?.length > 0"
class="item"
v-for="fileItem in item.fileList"
>
<div>{{ fileItem.name }}</div>
</div>
</div>
<div class="imgBox">
<img v-if="item.content?.img?.length > 0" v-for="imgItem in item.content?.img" :src="imgItem.minioUrl" alt="">
<img
v-if="item.content?.img?.length > 0"
v-for="imgItem in item.content?.img"
:src="imgItem.minioUrl"
alt=""
/>
</div>
<div class="colorBox">
<div v-if="item.content?.color?.length > 0" class="item" v-for="colorItem in item.content?.color">
<div class="color" :style="{'background-color':`rgba(${colorItem.rgb.replace(/\s+/g, ',')})`}"></div>
<div class="text">{{ colorItem.rgb.replace(/\s+/g, ',') }}</div>
<div
v-if="item.content?.color?.length > 0"
class="item"
v-for="colorItem in item.content?.color"
>
<div
class="color"
:style="{
'background-color': `rgba(${colorItem.rgb.replace(
/\s+/g,
','
)})`,
}"
></div>
<div class="text">
{{ colorItem.rgb.replace(/\s+/g, ",") }}
</div>
</div>
</div>
<i class="fi fi-br-loading" v-if="!item.content.think && !item.content.message && !item.content.img && !item.content.color"></i>
</div>
<i
class="fi fi-br-loading"
v-if="
!item.content.think &&
!item.content.message &&
!item.content.img &&
!item.content.color
"
></i>
</div>
</div>
</div>
</div>
<div class="content" @click="openChattingRecords">
<textarea ref="textarea" @input="inputText($event)" @keydown.enter.prevent="sendChat" placeholder="Write your message"></textarea>
<textarea
ref="textarea"
@input="inputText($event)"
@keydown.enter.prevent="sendChat"
placeholder="Write your message"
></textarea>
<div class="btn">
<div class="uploadBox">
<div class="filList">
<div class="item" v-for="item,index in filList">
<div class="item" v-for="(item, index) in filList">
<div>{{ item.name }}</div>
<span class="icon iconfont icon-shanchu" @click="deleteFile(item,index)"></span>
<span
class="icon iconfont icon-shanchu"
@click="deleteFile(item, index)"
></span>
</div>
</div>
<i class="fi fi-rs-paperclip-vertical">
<input type="file" @change="handleFileUpload($event)">
<input type="file" @change="handleFileUpload($event)" />
</i>
<div class="enableThinking" :class="{active:enableThinking}" @click="()=>enableThinking = !enableThinking">Deep Thinking</div>
<div
class="enableThinking"
:class="{ active: enableThinking }"
@click="() => (enableThinking = !enableThinking)"
>
Deep Thinking
</div>
</div>
<div class="sendBox">
<div class="maxNum">{{ chatContent?.length }}/10000</div>
<div class="send" :class="{active:chatContent?.length>0}" @click="sendChat">
<div
class="send"
:class="{ active: chatContent?.length > 0 }"
@click="sendChat"
>
<i class="fi fi-ss-paper-plane-top"></i>
</div>
</div>
</div>
</div>
</div>
<div v-show="openChat" class="right" @click="()=>{openChat = !openChat;isChattingRecords=false}">
<div
v-show="openChat"
class="right"
@click="
() => {
openChat = !openChat;
isChattingRecords = false;
}
"
>
<i class="fi fi-br-angle-small-down"></i>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent,computed,ref,inject,nextTick,createVNode,toRefs, reactive, watch} from 'vue'
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import {
defineComponent,
computed,
ref,
inject,
nextTick,
createVNode,
toRefs,
reactive,
watch,
} from "vue";
import { ExclamationCircleOutlined } from "@ant-design/icons-vue";
import { Https } from "@/tool/https";
import { useStore } from "vuex";
import { Modal,message,Upload,CascaderProps } from 'ant-design-vue';
import { useI18n } from 'vue-i18n'
import { Modal, message, Upload, CascaderProps } from "ant-design-vue";
import { useI18n } from "vue-i18n";
import { setCookie, getCookie, WriteCookie } from "@/tool/cookie";
import { useRouter,useRoute } from 'vue-router'
import { useRouter, useRoute } from "vue-router";
export default defineComponent({
components:{
},
props:{
},
emits:['chatChange'],
components: {},
props: {},
emits: ["chatChange"],
setup(props, { emit }) {
const store = useStore();
const route = useRoute()
const route = useRoute();
const data = reactive({
chatContent:'',
chatContent: "",
openChat: true,
chatList:[
] as any,
chatList: [] as any,
isChattingRecords: false,
selectObject: computed(() => store.state.Workspace.probjects) as any, //选择的项目
filList: [] as any,
setIsShowMark:inject('setIsShowMark') as any,
setIsShowMark: inject("setIsShowMark") as any,
isFinish: true,
enableThinking: false, //深度思考
})
});
const dataDom = reactive({
textarea: null as any,
chatBox: null as any,
})
watch(()=>data.selectObject.id,(newValue,oldValue)=>{
if(newValue && (data.selectObject.httpType == 'SERIES_DESIGN' || data.selectObject.httpType == 'SINGLE_DESIGN')){
data.chatList = []
if(route.query?.create)return
});
watch(
() => data.selectObject.id,
(newValue, oldValue) => {
if (
newValue &&
(data.selectObject.httpType == "SERIES_DESIGN" ||
data.selectObject.httpType == "SINGLE_DESIGN")
) {
data.chatList = [];
if (route.query?.create) return;
nextTick(() => {
getChatHistory(newValue)
})
getChatHistory(newValue);
});
}
})
}
);
const inputText = (e: any) => {
if (e.target.value.length <= 1000) {
data.chatContent = e.target.value
data.chatContent = e.target.value;
} else {
e.target.value = data.chatContent
e.target.value = data.chatContent;
}
e.target.style.height = `${e.target.scrollHeight}px`;
}
};
const sendChat = () => {
if(!data.isFinish)return
if(!data.chatContent)return
let fileList
if (!data.isFinish) return;
if (!data.chatContent) return;
let fileList;
if (data.filList) {
fileList = JSON.parse(JSON.stringify(data.filList))
fileList = JSON.parse(JSON.stringify(data.filList));
} else {
fileList = []
fileList = [];
}
let fileUrl = (fileList.filter((item:any)=>item.type == 'file').length > 0) ? fileList.filter((item:any)=>item.type == 'file')[0].minioPath : ''
let imageUrlList = (fileList.filter((item:any)=>item.type == 'image').length > 0)? fileList.filter((item:any)=>item.type == 'image').map((item:any)=>item.minioPath).join(',') : ''
data.chatList.push({content:{message:data.chatContent,think:''},role:'user',fileList:fileList})
data.chatList.push({content:{message:'',think:''},role:'system'})
const eventSource = new EventSource(`${process.env.VUE_APP_BASE_URL}${Https.httpUrls.llmStream}?token=${getCookie('token')}&prompt=${data.chatContent}&projectId=${data.selectObject.id}&fileUrl=${fileUrl}&imageUrlList=${imageUrlList}&enableThinking=${data.enableThinking}`);
data.chatContent = ''
dataDom.textarea.value = ''
data.filList = []
let fileUrl =
fileList.filter((item: any) => item.type == "file").length > 0
? fileList.filter((item: any) => item.type == "file")[0].minioPath
: "";
let imageUrlList =
fileList.filter((item: any) => item.type == "image").length > 0
? fileList
.filter((item: any) => item.type == "image")
.map((item: any) => item.minioPath)
.join(",")
: "";
data.chatList.push({
content: { message: data.chatContent, think: "" },
role: "user",
fileList: fileList,
});
data.chatList.push({
content: { message: "", think: "" },
role: "system",
});
const eventSource = new EventSource(
`${import.meta.env.VITE_APP_BASE_URL}${
Https.httpUrls.llmStream
}?token=${getCookie("token")}&prompt=${data.chatContent}&projectId=${
data.selectObject.id
}&fileUrl=${fileUrl}&imageUrlList=${imageUrlList}&enableThinking=${
data.enableThinking
}`
);
data.chatContent = "";
dataDom.textarea.value = "";
data.filList = [];
eventSource.onmessage = function (event) {
data.isFinish = false
console.log('收到数据:', JSON.parse(event.data));
data.isFinish = false;
console.log("收到数据:", JSON.parse(event.data));
// if(event.data.status == 'DESIGN_SIGNAL'){
// emit('chatChange',{type:'design'})
// }else if(event.data.status == 'RUNNING'){
// data.chatList[data.chatList.length-1].content.message+=JSON.parse(event.data).content
// }
const container = dataDom.chatBox;
if(container?.scrollHeight)container.scrollTop = container.scrollHeight;
if (container?.scrollHeight)
container.scrollTop = container.scrollHeight;
const eventData = JSON.parse(event.data)
if(eventData.type == 'text'){
data.chatList[data.chatList.length-1].content.message+=eventData.content
}else if(eventData.type == 'think'){
data.chatList[data.chatList.length-1].content.think+=eventData.content
const eventData = JSON.parse(event.data);
if (eventData.type == "text") {
data.chatList[data.chatList.length - 1].content.message +=
eventData.content;
} else if (eventData.type == "think") {
data.chatList[data.chatList.length - 1].content.think +=
eventData.content;
} else if (eventData.type == "tools_response") {
let nameList = ['moodboard','printboard','sketchboard','generate_color_code']
let nameList = [
"moodboard",
"printboard",
"sketchboard",
"generate_color_code",
];
let nameData = {
moodboard:'moodBoard',
printboard:'printBoard',
sketchboard:'sketchBoard',
} as any
let getData = ''
moodboard: "moodBoard",
printboard: "printBoard",
sketchboard: "sketchBoard",
} as any;
let getData = "";
if (nameList.indexOf(eventData.tools_name) > -1) {
if(data.chatList[data.chatList.length - 1].content.message)data.chatList.push({content:{message:''},role:'system'})
if(eventData.tools_name == 'generate_color_code'){
data.chatList[data.chatList.length-1].content.color = JSON.parse(JSON.parse(event.data).content).receiveCollectionElementList
getData = 'colorBoard'
if (data.chatList[data.chatList.length - 1].content.message)
data.chatList.push({ content: { message: "" }, role: "system" });
if (eventData.tools_name == "generate_color_code") {
data.chatList[data.chatList.length - 1].content.color =
JSON.parse(
JSON.parse(event.data).content
).receiveCollectionElementList;
getData = "colorBoard";
} else {
data.chatList[data.chatList.length-1].content.img = JSON.parse(JSON.parse(event.data).content).receiveCollectionElementList
getData = nameData[eventData.tools_name]
data.chatList[data.chatList.length - 1].content.img = JSON.parse(
JSON.parse(event.data).content
).receiveCollectionElementList;
getData = nameData[eventData.tools_name];
}
data.chatList.push({content:{message:''},role:'system'})
}else if(eventData.tools_name == 'design_control_signal'){
emit('chatChange',{type:eventData.tools_name,design:true})
data.chatList.push({ content: { message: "" }, role: "system" });
} else if (eventData.tools_name == "design_control_signal") {
emit("chatChange", { type: eventData.tools_name, design: true });
}
emit('chatChange',{type:eventData.type,module:getData})
emit("chatChange", { type: eventData.type, module: getData });
}
//emit('chatChange',{type:JSON.parse(event.data).status})
};
eventSource.onerror = function (error) {
if (eventSource.readyState === EventSource.CLOSED) {
data.chatList[data.chatList.length-1].content.message='服务器繁忙,请稍后再试。'
data.chatList[data.chatList.length - 1].content.message =
"服务器繁忙,请稍后再试。";
} else {
eventSource.close()
data.isFinish = true
eventSource.close();
data.isFinish = true;
}
};
}
};
const getChatHistory = (objectId: number) => {
if(!data.isFinish)return
if (!data.isFinish) return;
let value = {
projectId: objectId,
page: 1,
pageSize: 100,
}
};
Https.axiosPost(Https.httpUrls.getChatHistory, value).then((rv) => {
if (rv) {
rv.content.forEach((item: any, index: number) => {
if(rv.content[rv.content.length - index -1].role == 'system'){
let text = rv.content[rv.content.length - index -1].content
if (rv.content[rv.content.length - index - 1].role == "system") {
let text = rv.content[rv.content.length - index - 1].content;
if (rv.content[rv.content.length - index - 1].isImage == 2) {
rv.content[rv.content.length - index - 1].content = {
img : JSON.parse(rv.content[rv.content.length - index -1].content)
}
}else if(rv.content[rv.content.length - index -1].isImage==1){
img: JSON.parse(
rv.content[rv.content.length - index - 1].content
),
};
} else if (
rv.content[rv.content.length - index - 1].isImage == 1
) {
rv.content[rv.content.length - index - 1].content = {
color : JSON.parse(rv.content[rv.content.length - index -1].content)
}
color: JSON.parse(
rv.content[rv.content.length - index - 1].content
),
};
} else {
let think = ''
let message = ''
if(text.split('[TEXT]').length > 1 && text.split('[THINK]').length > 1){
think = text.split('[TEXT]')[0]
text.split('[TEXT]').forEach((text:any,index:number) => {
if(index == 0)return
message += ('[TEXT]'+text)
let think = "";
let message = "";
if (
text.split("[TEXT]").length > 1 &&
text.split("[THINK]").length > 1
) {
think = text.split("[TEXT]")[0];
text.split("[TEXT]").forEach((text: any, index: number) => {
if (index == 0) return;
message += "[TEXT]" + text;
});
} else {
message = text
message = text;
}
rv.content[rv.content.length - index - 1].content = {
message: message,
think: think,
}
};
}
} else {
let content = JSON.parse(rv.content[rv.content.length - index -1].content)
content.fileList = []
let content = JSON.parse(
rv.content[rv.content.length - index - 1].content
);
content.fileList = [];
if (content.file || content.image) {
let getName = (url: any) => {
let minio = url.splice('?')[0]
return minio.splice('/')[minio.splice('/').length-1]
}
let minio = url.splice("?")[0];
return minio.splice("/")[minio.splice("/").length - 1];
};
if (content.file) {
content.file.forEach((item: any) => {
content.fileList.push({name:getName(item),type:'file',url:item})
})
content.fileList.push({
name: getName(item),
type: "file",
url: item,
});
});
}
if (content.image) {
content.image.forEach((item: any) => {
content.fileList.push({name:getName(item),type:'image',url:item})
})
}
}
rv.content[rv.content.length - index -1].content = content
}
data.chatList.push(rv.content[rv.content.length - index -1])
content.fileList.push({
name: getName(item),
type: "image",
url: item,
});
});
}
})
}
rv.content[rv.content.length - index - 1].content = content;
}
data.chatList.push(rv.content[rv.content.length - index - 1]);
});
}
});
};
const openChattingRecords = () => {
data.isChattingRecords = true
data.isChattingRecords = true;
// let setRecords = ()=>{
// data.isChattingRecords = false
// document.removeEventListener('click',setRecords)
// }
// document.addEventListener('click',setRecords)
}
};
const handleFileUpload = (event: any) => {
if (event.target.files[0].size > 5 * 1024 * 1024) { // 5MB
message.info('The file size cannot exceed 5MB.');
return
if (event.target.files[0].size > 5 * 1024 * 1024) {
// 5MB
message.info("The file size cannot exceed 5MB.");
return;
}
let type = event.target.files[0].type.startsWith('image/')
let type = event.target.files[0].type.startsWith("image/");
if (type) {
if(data.filList.filter((item:any)=>item.type == 'image').length >= 5){
message.info('You can only upload five pictures.');
return
if (
data.filList.filter((item: any) => item.type == "image").length >= 5
) {
message.info("You can only upload five pictures.");
return;
}
} else {
if(data.filList.filter((item:any)=>item.type == 'file').length >= 1){
message.info('You can only upload one file.');
return
if (
data.filList.filter((item: any) => item.type == "file").length >= 1
) {
message.info("You can only upload one file.");
return;
}
}
data.setIsShowMark(true)
data.setIsShowMark(true);
const formData = new FormData();
formData.append('file', event.target.files[0]);
formData.append("file", event.target.files[0]);
let config: any = {
headers:{'Content-Type':'multipart/form-data','Accept':'*/*' },
headers: { "Content-Type": "multipart/form-data", Accept: "*/*" },
params: formData,
}
};
Https.axiosPost(Https.httpUrls.llmUploadFile, formData, config)
.then((rv: any) => {
let obj = {
name: event.target.files[0].name,
type:type?'image':'file',
type: type ? "image" : "file",
minioPath: rv[0],
url: rv[1],
}
data.filList.push(obj)
};
data.filList.push(obj);
// data.filList.unshift(rv)
data.setIsShowMark(false)
}
).catch(rv=>{
data.setIsShowMark(false)
data.setIsShowMark(false);
})
}
.catch((rv) => {
data.setIsShowMark(false);
});
};
const deleteFile = (item: any, index: number) => {
data.filList.splice(index,1)
}
data.filList.splice(index, 1);
};
return {
...toRefs(dataDom),
...toRefs(data),
@@ -314,13 +491,12 @@ export default defineComponent({
openChattingRecords,
handleFileUpload,
deleteFile,
}
};
},
provide() {
return {
}
return {};
},
})
});
</script>
<style lang="less" scoped>
.chat {
@@ -331,7 +507,7 @@ export default defineComponent({
bottom: 3.2rem;
top: auto;
width: 50%;
transition: all .3s;
transition: all 0.3s;
border-radius: 2.4rem;
display: flex;
border: 1px solid #e5e5e5;
@@ -363,7 +539,6 @@ export default defineComponent({
> .text {
> .content {
> .txt {
}
> .showThink {
display: none;
@@ -372,9 +547,9 @@ export default defineComponent({
> .fileBox {
> .item {
height: 3rem;
padding: .5rem 1rem;
padding: 0.5rem 1rem;
background: #efeff1;
border-radius: .5rem;
border-radius: 0.5rem;
margin-right: 1rem;
font-size: 1.4rem;
line-height: 2rem;
@@ -391,7 +566,6 @@ export default defineComponent({
> .icon {
display: none;
}
}
}
@@ -415,12 +589,11 @@ export default defineComponent({
// word-wrap: break-word;
> .content {
> .txt {
}
> .showThink {
cursor: pointer;
display: flex;
padding: .7rem 1.4rem;
padding: 0.7rem 1.4rem;
margin-bottom: 1.2rem;
background: rgb(237 237 237);
border-radius: 1rem;
@@ -433,7 +606,7 @@ export default defineComponent({
}
> i {
display: flex;
transition: all .3s;
transition: all 0.3s;
}
}
> .think {
@@ -454,14 +627,14 @@ export default defineComponent({
width: 10rem;
height: 10rem;
cursor: pointer;
margin: .5rem;
margin: 0.5rem;
}
}
> .colorBox {
display: flex;
flex-wrap: wrap;
> .item {
margin: .5rem;
margin: 0.5rem;
border-radius: 1rem;
overflow: hidden;
border: 1px solid;
@@ -496,7 +669,6 @@ export default defineComponent({
}
}
}
}
}
}
@@ -527,9 +699,9 @@ export default defineComponent({
display: flex;
> .item {
height: 3rem;
padding: .5rem 1rem;
padding: 0.5rem 1rem;
background: #efeff1;
border-radius: .5rem;
border-radius: 0.5rem;
margin-right: 1rem;
font-size: 1.4rem;
line-height: 2rem;
@@ -547,17 +719,16 @@ export default defineComponent({
}
> .enableThinking {
width: 10rem;
padding: .2rem .4rem;
padding: 0.2rem 0.4rem;
text-align: center;
font-size: 1.4rem;
border: 1px solid #000;
border-radius: .4rem;
border-radius: 0.4rem;
cursor: pointer;
margin-left: 1rem;
&.active {
background: #000;
color: #fff;
}
}
}
@@ -585,11 +756,11 @@ export default defineComponent({
> .maxNum {
font-size: 1.2rem;
margin-right: .8rem;
margin-right: 0.8rem;
font-weight: 400;
}
> .send {
opacity: .5;
opacity: 0.5;
cursor: no-drop;
&.active {
opacity: 1;
@@ -600,7 +771,9 @@ export default defineComponent({
}
}
}
> .right,> .left,>.top{
> .right,
> .left,
> .top {
display: flex;
align-items: center;
cursor: pointer;
@@ -609,7 +782,7 @@ export default defineComponent({
> i {
display: flex;
font-size: 2rem;
transition: all .3s;
transition: all 0.3s;
}
}
> .top {

View File

@@ -5,7 +5,14 @@
<div class="title">How can I help you today?</div>
<div class="selectFlow">
<div class="select">
<div class="item" @click="setFlow(item)" :class="{active:item.title == selectFlow.title}" v-for="item in flowList">{{ item.title }}</div>
<div
class="item"
@click="setFlow(item)"
:class="{ active: item.title == selectFlow.title }"
v-for="item in flowList"
>
{{ item.title }}
</div>
</div>
<div class="describe">
<p v-for="item in selectFlow.describe">{{ item }}</p>
@@ -13,24 +20,50 @@
</div>
<div class="chatOrSetting">
<div class="select">
<div class="item" @click="setChatOrSetting('chat')" :class="{active:chatOrSetting == 'chat'}">Chat</div>
<div class="item" @click="setChatOrSetting('setting')" :class="{active:chatOrSetting == 'setting'}">Setting</div>
<div
class="item"
@click="setChatOrSetting('chat')"
:class="{ active: chatOrSetting == 'chat' }"
>
Chat
</div>
<div
class="item"
@click="setChatOrSetting('setting')"
:class="{ active: chatOrSetting == 'setting' }"
>
Setting
</div>
</div>
</div>
<div class="chatBox" v-show="chatOrSetting == 'chat'">
<textarea ref="textarea" @input="inputText($event)" @keydown.enter.prevent="sendChat" placeholder="Write your message"></textarea>
<textarea
ref="textarea"
@input="inputText($event)"
@keydown.enter.prevent="sendChat"
placeholder="Write your message"
></textarea>
<div class="btn">
<div class="uploadBox">
<div class="filList">
<div class="item" v-for="item,index in filList">
<div class="item" v-for="(item, index) in filList">
<div>{{ item.name }}</div>
<span class="icon iconfont icon-shanchu" @click="deleteFile(item,index)"></span>
<span
class="icon iconfont icon-shanchu"
@click="deleteFile(item, index)"
></span>
</div>
</div>
<i class="fi fi-rs-paperclip-vertical">
<input type="file" @change="handleFileUpload($event)">
<input type="file" @change="handleFileUpload($event)" />
</i>
<div class="enableThinking" :class="{active:enableThinking}" @click="()=>enableThinking = !enableThinking">Deep Thinking</div>
<div
class="enableThinking"
:class="{ active: enableThinking }"
@click="() => (enableThinking = !enableThinking)"
>
Deep Thinking
</div>
</div>
<div class="sendBox">
<div class="maxNum">{{ chatContent.length }}/10000</div>
@@ -41,10 +74,19 @@
</div>
</div>
<div v-show="chatOrSetting != 'chat'" class="workspaceBox">
<workspace @setProject="setProject" :httpWorkflowType="selectFlow.value"></workspace>
<workspace
@setProject="setProject"
:httpWorkflowType="selectFlow.value"
></workspace>
</div>
<div class="hint" v-show="chatOrSetting == 'chat'">
<div class="item" v-for="item in hintList" @click="addChatContent(item)">{{ item }}</div>
<div
class="item"
v-for="item in hintList"
@click="addChatContent(item)"
>
{{ item }}
</div>
</div>
</div>
</div>
@@ -54,103 +96,129 @@
</div>
</template>
<script lang="ts">
import { defineComponent,computed,ref,provide,nextTick,createVNode,toRefs, reactive, onMounted} from 'vue'
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import {
defineComponent,
computed,
ref,
provide,
nextTick,
createVNode,
toRefs,
reactive,
onMounted,
} from "vue";
import { ExclamationCircleOutlined } from "@ant-design/icons-vue";
import { Https } from "@/tool/https";
import { useStore } from "vuex";
import { Modal,message,Upload,CascaderProps } from 'ant-design-vue';
import { useI18n } from 'vue-i18n'
import {getCookie,clonAllCookie} from '@/tool/cookie'
import router from '@/router';
import workspace from './workspace.vue'
import { Modal, message, Upload, CascaderProps } from "ant-design-vue";
import { useI18n } from "vue-i18n";
import { getCookie, clonAllCookie } from "@/tool/cookie";
import router from "@/router";
import workspace from "./workspace.vue";
export default defineComponent({
components: {
workspace,
},
props:{
},
emits:['newProject'],
props: {},
emits: ["newProject"],
setup(props, { emit }) {
const store = useStore();
const data = reactive({
flowList: [
{
title:'Series Design',
value:'SERIES_DESIGN',
title: "Series Design",
value: "SERIES_DESIGN",
describe: [
'Series Design focuses on the coordinated design of multi-category clothing, ideal for creating a unified fashion collection. You can use the Moodboard, Printboard, Colorboard, Sketchboard, and Mannequin sections in the Design Assests panel to organize your inspiration and design complementary clothing combinations. Finally, refine your designs in the Draft and Collection panels using tools like To Product Image, Relight, and Transfer Pose, then export to the Canvas to showcase your complete series design.',
]
"Series Design focuses on the coordinated design of multi-category clothing, ideal for creating a unified fashion collection. You can use the Moodboard, Printboard, Colorboard, Sketchboard, and Mannequin sections in the Design Assests panel to organize your inspiration and design complementary clothing combinations. Finally, refine your designs in the Draft and Collection panels using tools like To Product Image, Relight, and Transfer Pose, then export to the Canvas to showcase your complete series design.",
],
},
{
title:'Single Design',
value:'SINGLE_DESIGN',
title: "Single Design",
value: "SINGLE_DESIGN",
describe: [
'Single Design centers on the independent design of a single clothing category, such as a T-shirt, dress, or jacket, without considering coordination with other items. Use the Moodboard, Printboard, Colorboard, and Sketchboard in the Design Assests panel to gather inspiration and focus on crafting a unique piece. Once completed, optimize your design in the Draft and Collection panels with tools like To Product Image, Relight, and Transfer Pose, then export to the Canvas to display your individual creation.',
]
"Single Design centers on the independent design of a single clothing category, such as a T-shirt, dress, or jacket, without considering coordination with other items. Use the Moodboard, Printboard, Colorboard, and Sketchboard in the Design Assests panel to gather inspiration and focus on crafting a unique piece. Once completed, optimize your design in the Draft and Collection panels with tools like To Product Image, Relight, and Transfer Pose, then export to the Canvas to display your individual creation.",
],
},
],
selectFlow: {
title:'Series Design',
value:'SERIES_DESIGN',
title: "Series Design",
value: "SERIES_DESIGN",
describe: [
'Series Design focuses on the coordinated design of multi-category clothing, ideal for creating a unified fashion collection. You can use the Moodboard, Printboard, Colorboard, Sketchboard, and Mannequin sections in the Design Assests panel to organize your inspiration and design complementary clothing combinations. Finally, refine your designs in the Draft and Collection panels using tools like To Product Image, Relight, and Transfer Pose, then export to the Canvas to showcase your complete series design.',
]
"Series Design focuses on the coordinated design of multi-category clothing, ideal for creating a unified fashion collection. You can use the Moodboard, Printboard, Colorboard, Sketchboard, and Mannequin sections in the Design Assests panel to organize your inspiration and design complementary clothing combinations. Finally, refine your designs in the Draft and Collection panels using tools like To Product Image, Relight, and Transfer Pose, then export to the Canvas to showcase your complete series design.",
],
},
chatContent:'',
chatContent: "",
hintList: [
'设计一套田园风衣服',
'设计一套夏日风衣服',
'设计一套未来风格的衣服',
"设计一套田园风衣服",
"设计一套夏日风衣服",
"设计一套未来风格的衣服",
],
enableThinking: false, //深度思考
uploadFile: null as any,
loadingShow: false,
text:'',
text: "",
filList: [] as any,
textarea: null as any,
chatOrSetting:'chat',
})
const dataDom = reactive({
})
chatOrSetting: "chat",
});
const dataDom = reactive({});
const setFlow = (item: any) => {
data.selectFlow = item
}
data.selectFlow = item;
};
const inputText = (e: any) => {
if (e.target.value.length <= 1000) {
data.chatContent = e.target.value
data.chatContent = e.target.value;
} else {
e.target.value = data.chatContent
e.target.value = data.chatContent;
}
e.target.style.height = `${e.target.scrollHeight}px`;
}
};
const addChatContent = (item: any) => {
if((data.textarea.value?.length + item.length) > 10000)return
data.chatContent += item
data.textarea.value += item
}
if (data.textarea.value?.length + item.length > 10000) return;
data.chatContent += item;
data.textarea.value += item;
};
const sendChat = () => {
if(!data.chatContent)return
data.loadingShow = true
let fileList = JSON.parse(JSON.stringify(data.filList))
let fileUrl = (fileList.filter((item:any)=>item.type == 'file').length > 0) ? fileList.filter((item:any)=>item.type == 'file')[0].minioPath : ''
let imageUrlList = (fileList.filter((item:any)=>item.type == 'image').length > 0)? fileList.filter((item:any)=>item.type == 'image').map((item:any)=>item.minioPath).join(',') : ''
Https.axiosGet(Https.httpUrls.chatCreateProject, {params:{prompt:data.chatContent,process:data.selectFlow.value,fileUrl:fileUrl,imageUrlList}}).then((rv)=>{
if (!data.chatContent) return;
data.loadingShow = true;
let fileList = JSON.parse(JSON.stringify(data.filList));
let fileUrl =
fileList.filter((item: any) => item.type == "file").length > 0
? fileList.filter((item: any) => item.type == "file")[0].minioPath
: "";
let imageUrlList =
fileList.filter((item: any) => item.type == "image").length > 0
? fileList
.filter((item: any) => item.type == "image")
.map((item: any) => item.minioPath)
.join(",")
: "";
Https.axiosGet(Https.httpUrls.chatCreateProject, {
params: {
prompt: data.chatContent,
process: data.selectFlow.value,
fileUrl: fileUrl,
imageUrlList,
},
})
.then((rv) => {
if (rv) {
data.loadingShow = false
data.loadingShow = false;
let value = {
id: rv,
fileList: fileList,
chatContent: data.chatContent,
enableThinking: data.enableThinking,
};
emit("newProject", value);
}
emit('newProject',value)
}
}).catch(()=>{
data.loadingShow = false
})
.catch(() => {
data.loadingShow = false;
});
// let projectId = ''
// const eventSource = new EventSource(`${process.env.VUE_APP_BASE_URL}${Https.httpUrls.llmStream}?token=${getCookie('token')}&prompt=${data.chatContent}&projectId=&fileUrl=${fileUrl}&imageUrlList=${imageUrlList}&enableThinking=${data.enableThinking}&process=${data.selectFlow.value}`);
// const eventSource = new EventSource(`${import.meta.env.VITE_APP_BASE_URL}${Https.httpUrls.llmStream}?token=${getCookie('token')}&prompt=${data.chatContent}&projectId=&fileUrl=${fileUrl}&imageUrlList=${imageUrlList}&enableThinking=${data.enableThinking}&process=${data.selectFlow.value}`);
// eventSource.onmessage = function(event) {
// let eventData = JSON.parse(event.data)
// if(eventData.status == "[PROJECT_CREATE_SIGNAL]"){
@@ -168,58 +236,63 @@ export default defineComponent({
// }
// data.loadingShow = false
// };
}
};
const handleFileUpload = (event: any) => {
if (event.target.files[0].size > 5 * 1024 * 1024) { // 5MB
message.info('The file size cannot exceed 5MB.');
return
if (event.target.files[0].size > 5 * 1024 * 1024) {
// 5MB
message.info("The file size cannot exceed 5MB.");
return;
}
let type = event.target.files[0].type.startsWith('image/')
let type = event.target.files[0].type.startsWith("image/");
if (type) {
if(data.filList.filter((item:any)=>item.type == 'image').length >= 5){
message.info('You can only upload five pictures.');
return
if (
data.filList.filter((item: any) => item.type == "image").length >= 5
) {
message.info("You can only upload five pictures.");
return;
}
} else {
if(data.filList.filter((item:any)=>item.type == 'file').length >= 1){
message.info('You can only upload one file.');
return
if (
data.filList.filter((item: any) => item.type == "file").length >= 1
) {
message.info("You can only upload one file.");
return;
}
}
data.loadingShow = true
data.loadingShow = true;
const formData = new FormData();
formData.append('file', event.target.files[0]);
formData.append("file", event.target.files[0]);
let config: any = {
headers:{'Content-Type':'multipart/form-data','Accept':'*/*' },
headers: { "Content-Type": "multipart/form-data", Accept: "*/*" },
params: formData,
}
};
Https.axiosPost(Https.httpUrls.llmUploadFile, formData, config)
.then((rv: any) => {
let obj = {
name: event.target.files[0].name,
type:type?'image':'file',
type: type ? "image" : "file",
minioPath: rv[0],
url: rv[1],
}
data.filList.push(obj)
data.loadingShow = false
}
).catch(rv=>{
data.loadingShow = false
};
data.filList.push(obj);
data.loadingShow = false;
})
}
.catch((rv) => {
data.loadingShow = false;
});
};
const deleteFile = (item: any, index: number) => {
data.filList.splice(index,1)
}
data.filList.splice(index, 1);
};
const setChatOrSetting = (str: any) => {
data.chatOrSetting = str
}
data.chatOrSetting = str;
};
const setProject = (item: any) => {
router.push(`home?history=${item.id}`)
}
router.push(`home?history=${item.id}`);
};
onMounted(() => {
store.commit('createProbject')
})
store.commit("createProbject");
});
return {
...toRefs(dataDom),
...toRefs(data),
@@ -231,13 +304,12 @@ export default defineComponent({
deleteFile,
setChatOrSetting,
setProject,
}
};
},
provide() {
return {
}
return {};
},
})
});
</script>
<style lang="less" scoped>
.newProject {
@@ -283,14 +355,14 @@ export default defineComponent({
border: 1px solid #0000001a;
border-radius: 2.4rem;
display: flex;
padding: .2rem;
padding: 0.2rem;
border-radius: 2rem;
> div {
white-space: nowrap;
justify-content: space-between;
border-radius: 2.2rem;
font-size: 1.6rem;
padding: .6rem .8rem;
padding: 0.6rem 0.8rem;
min-width: 25%;
text-align: center;
font-weight: 600;
@@ -304,7 +376,7 @@ export default defineComponent({
}
> .describe {
margin-top: 1.6rem;
margin-left: .8rem;
margin-left: 0.8rem;
> p {
margin: 0;
color: #71717a;
@@ -321,14 +393,14 @@ export default defineComponent({
border: 1px solid #0000001a;
border-radius: 2.4rem;
display: flex;
padding: .2rem;
padding: 0.2rem;
border-radius: 2rem;
> div {
white-space: nowrap;
justify-content: space-between;
border-radius: 2.2rem;
font-size: 1.6rem;
padding: .6rem .8rem;
padding: 0.6rem 0.8rem;
min-width: 10rem;
text-align: center;
font-weight: 600;
@@ -342,7 +414,7 @@ export default defineComponent({
}
}
> .chatBox {
margin-top: .4rem;
margin-top: 0.4rem;
border-radius: 2.4rem;
position: relative;
background: #f5f5f5;
@@ -370,9 +442,9 @@ export default defineComponent({
display: flex;
> .item {
height: 3rem;
padding: .5rem 1rem;
padding: 0.5rem 1rem;
background: #efeff1;
border-radius: .5rem;
border-radius: 0.5rem;
margin-right: 1rem;
font-size: 1.4rem;
line-height: 2rem;
@@ -390,17 +462,16 @@ export default defineComponent({
}
> .enableThinking {
width: 10rem;
padding: .2rem .4rem;
padding: 0.2rem 0.4rem;
margin-left: 1rem;
text-align: center;
font-size: 1.4rem;
border: 1px solid #000;
border-radius: .4rem;
border-radius: 0.4rem;
cursor: pointer;
&.active {
background: #000;
color: #fff;
}
}
}
@@ -428,7 +499,7 @@ export default defineComponent({
> .maxNum {
font-size: 1.2rem;
margin-right: .8rem;
margin-right: 0.8rem;
font-weight: 400;
}
}

View File

@@ -1,19 +1,18 @@
import axios from 'axios'
import axios from "axios";
// import qs from 'qs'
// import message from '@/components/public/message/src'
import router from '@/router/index'
import {getCookie,clonAllCookie} from '@/tool/cookie'
import router from "@/router/index";
import { getCookie, clonAllCookie } from "@/tool/cookie";
// import cookie from '@/tools/cookie.js'
axios.defaults.timeout = 60000; //响应时间
// axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8'; //配置请求头
axios.defaults.headers.post["Content-Type"] = "application/json";
axios.defaults.headers.post['lang'] = 'en'; //配置语言请求头
axios.defaults.headers.post["lang"] = "en"; //配置语言请求头
axios.defaults.withCredentials = true; //跨域携带cookie
import { message } from 'ant-design-vue';
import store from '@/store';
import { message } from "ant-design-vue";
import store from "@/store";
// if(process.env.NODE_ENV == "development"){
// axios.defaults.baseURL = ""; //配置接口地址
// }else{
@@ -25,117 +24,141 @@ import store from '@/store';
// }else{
// httpIp = ''
// }
let httpIp = process.env.NODE_ENV == 'development' ? "" : "";
let httpIp = process.env.NODE_ENV == "development" ? "" : "";
// let httpIp = process.env.NODE_ENV == 'development' ? "https://192.168.1.8:10086" : "";
axios.defaults.baseURL = httpIp; //配置接口地址
// console.log(axios.defaults.baseURL);
axios.defaults.baseURL = process.env.VUE_APP_BASE_URL; //配置接口地址
axios.defaults.baseURL = import.meta.env.VITE_APP_BASE_URL; //配置接口地址
// 创建取消令牌
const CancelToken = axios.CancelToken;
const source = CancelToken.source();
// console.log(process.env.VUE_APP_BASE_URL);
const filterHttpsUrl = ['/api/portfolio/page','/api/portfolio/detail','/api/account/preLogin','/api/account/schoolLogin','/api/account/enterpriseLogin','/api/account/login']
// console.log(import.meta.env.VITE_APP_BASE_URL);
const filterHttpsUrl = [
"/api/portfolio/page",
"/api/portfolio/detail",
"/api/account/preLogin",
"/api/account/schoolLogin",
"/api/account/enterpriseLogin",
"/api/account/login",
];
//POST传参序列化(添加请求拦截器)
axios.interceptors.request.use((config) => {
axios.interceptors.request.use(
(config) => {
//在发送请求之前做某件事
// config.cancelToken = source.token
if(config.method === 'post' || config.method === 'put' || config.method === 'delete'){
if (
config.method === "post" ||
config.method === "put" ||
config.method === "delete"
) {
// config.data = qs.stringify(config.data);
// config.data = JSON.stringify(config.data);
}
// config.headers.Authorization = 'Bearer-eyJhbGciOiJIUzUxMiJ9.eyJqdGkiOiIyIiwic3ViIjoie1wiaWRcIjoyLFwidXNlcm5hbWVcIjpcImxpcnNcIn0iLCJpYXQiOjE2NjU3NDEwODcsImlzcyI6IkRXSiIsImF1dGhvcml0aWVzIjoiW10iLCJleHAiOjE2NzQzODEwODd9.ShM9R_NNFD7oo1OvxrEgg7PFeWinOuAKkuInUCMQupp66s64Hhv8tN0Wwr83nIN4rHPqtn95wmd4msWcvaFYJA';
if (filterHttpsUrl.indexOf(config.url) == -1) {
config.headers.Authorization = getCookie('token');
config.headers.Authorization = getCookie("token");
} else {
config.headers.Authorization = '';
config.headers.Authorization = "";
}
return config;
},(error) =>{
},
(error) => {
return Promise.reject(error);
});
let isLoginTime = false
const binaryToUrl = (binary,type = 'application/octet-stream',res)=>{
let blob = new Blob([binary], {'content-type':res.headers['content-type']});
let url = URL.createObjectURL(blob);
return url
}
);
let isLoginTime = false;
const binaryToUrl = (binary, type = "application/octet-stream", res) => {
let blob = new Blob([binary], {
"content-type": res.headers["content-type"],
});
let url = URL.createObjectURL(blob);
return url;
};
//返回状态判断(添加响应拦截器)
axios.interceptors.response.use((res) =>{
axios.interceptors.response.use(
(res) => {
// if(res.data.data == null){
// message.warning(res.data.errMsg)
// return Promise.reject(res.data);
// }else
if (res.config.env.binary) {
let url = binaryToUrl(res.data,res.config.env.binaryType,res)
return Promise.resolve({url,data:res.data})
let url = binaryToUrl(res.data, res.config.env.binaryType, res);
return Promise.resolve({ url, data: res.data });
}
if (res.data) {
if (res.data.errCode === 0) {
// message.error(res.data.errMsg)
return Promise.resolve(res.data.data);
} else if (res.data.errCode === 1) {
message.warning(res.data.errMsg)
message.warning(res.data.errMsg);
return Promise.reject(res.data);
} else if (res.data.errCode === 2) {
return Promise.reject(res.data);
} else if (res.data.errCode === -1) {
message.error(res.data.errMsg)
message.error(res.data.errMsg);
return Promise.reject(res.data);
}
} else {
if (res.data.errCode === 0) {
message.warning(res.data.errMsg)
message.warning(res.data.errMsg);
return Promise.reject(res.data);
} else if (res.data.errCode === 1) {
message.warning(res.data.errMsg)
message.warning(res.data.errMsg);
return Promise.reject(res.data);
} else if (res.data.errCode === 2) {
return Promise.reject(res.data);
} else if (res.data.errCode === -1) {
message.error(res.data.errMsg)
message.error(res.data.errMsg);
return Promise.reject(res.data);
}
}
}, function(error) {
if(error?.response?.status === 401 && router.currentRoute._value.name != 'setIdentification'){//如果是记录浏览器页面就不跳转login
},
function (error) {
if (
error?.response?.status === 401 &&
router.currentRoute._value.name != "setIdentification"
) {
//如果是记录浏览器页面就不跳转login
// return
clonAllCookie()
clonAllCookie();
if (!isLoginTime) {
isLoginTime = true
let isSystemUserRouteList = ['/Square']//如果是这两个页面就无需跳转未登录页
let sSystemUser = false
isLoginTime = true;
let isSystemUserRouteList = ["/Square"]; //如果是这两个页面就无需跳转未登录页
let sSystemUser = false;
for (let index = 0; index < isSystemUserRouteList.length; index++) {
if(router.currentRoute.value.path.indexOf(isSystemUserRouteList[index]) > -1){
sSystemUser = true
break
if (
router.currentRoute.value.path.indexOf(
isSystemUserRouteList[index]
) > -1
) {
sSystemUser = true;
break;
}
}
if (!sSystemUser) {
router.replace('/')
router.replace("/");
}
message.warning('Please login and try again~')
store.commit('createDetail')
store.commit('createProbject')
setTimeout(()=>[
isLoginTime = false
],2000)
message.warning("Please login and try again~");
store.commit("createDetail");
store.commit("createProbject");
setTimeout(() => [(isLoginTime = false)], 2000);
}
// source.cancel('取消后续接口调用');
return Promise.reject()
return Promise.reject();
}
let data_new = error?.response?.data
let data_new = error?.response?.data;
// message.error(data_new?.errMsg || 'Error: server exception')
return Promise.reject(data_new);
});
}
);
export const Https = {
httpUrls: {
interfaceUrl: '',
parseGoogleCredential:'/api/third/party/parseGoogleCredential',//谷歌登录注册
parseWeChatCode:'/api/third/party/parseWeChatCode',//微信登录
accountIsLogin:'/api/account/isLogin', //判断用户是否登录
interfaceUrl: "",
parseGoogleCredential: "/api/third/party/parseGoogleCredential", //谷歌登录注册
parseWeChatCode: "/api/third/party/parseWeChatCode", //微信登录
accountIsLogin: "/api/account/isLogin", //判断用户是否登录
accountLogin: `/api/account/login`, //账号密码登录接口
organizationNameSearch: `/api/account/organizationNameSearch`, //查询学校或者企业版名字
getUserLanguage: `/api/account/getUserLanguage`, //获取当前用户语言
@@ -161,30 +184,28 @@ export const Https = {
endpoint: `api/third/party/your-secured-endpoint`, //获取唯一标识是否存在
designWorksRegister: "/api/account/designWorksRegister", //注册
designWorksRegisterCode: "/api/account/designWorksRegisterCode", //注册
designWorksRegister:'/api/account/designWorksRegister', //注册
designWorksRegisterCode:'/api/account/designWorksRegisterCode', //注册
preLogin:'/api/account/preLogin',//预先登入
schoolLogin:'/api/account/schoolLogin',//学校管理员登录
enterpriseLogin:'/api/account/enterpriseLogin',//企业管理员登录
preLogin: "/api/account/preLogin", //预先登入
schoolLogin: "/api/account/schoolLogin", //学校管理员登录
enterpriseLogin: "/api/account/enterpriseLogin", //企业管理员登录
accountSendEmail: `/api/account/sendEmail`, //发送邮件
accountResetPwd:'/api/account/resetPwd', //忘记密码修改
accountLogout:'/api/account/logout',//登出
accountBindEmail:'/api/account/bindEmail', //绑定邮箱
bindGoogle:'/api/account/bindGoogle', //绑定谷歌
bindWeChat:'/api/account/bindWeChat', //绑定微信
accountResetPwd: "/api/account/resetPwd", //忘记密码修改
accountLogout: "/api/account/logout", //登出
accountBindEmail: "/api/account/bindEmail", //绑定邮箱
bindGoogle: "/api/account/bindGoogle", //绑定谷歌
bindWeChat: "/api/account/bindWeChat", //绑定微信
unbindGoogle: `/api/account/unbindGoogle`, //取消绑定谷歌
unbindWeChat:'/api/account/unbindWeChat', //取消绑定微信
elementGeneratePrint:'/api/element/generatePrint', //生成印花
elementSavePrint:'/api/element/savePrint',//保存印花
getRgbByTcx:'/api/element/getRgbByTcx', // 通过hsv值获取潘通信息
getRgbByHsv:'/api/element/getRgbByHsv', //通过hsv值获取潘通信息
unbindWeChat: "/api/account/unbindWeChat", //取消绑定微信
elementGeneratePrint: "/api/element/generatePrint", //生成印花
elementSavePrint: "/api/element/savePrint", //保存印花
getRgbByTcx: "/api/element/getRgbByTcx", // 通过hsv值获取潘通信息
getRgbByHsv: "/api/element/getRgbByHsv", //通过hsv值获取潘通信息
designCollection: `/api/design/designCollection`, //设计 Conllection
reDesignCollection: `/api/design/reDesignCollection`, //重新设计 Conllection
countDesignProcess:'/api/design/countDesignProcess', //统计design进度
getDesignResult:'/api/design/getDesignResult', //查询design结果
countDesignProcess: "/api/design/countDesignProcess", //统计design进度
getDesignResult: "/api/design/getDesignResult", //查询design结果
designSort: `/api/design/sort`, //design排序
collectionLikeUpdate: `/api/history/collectionLikeUpdate`, //赋值排序
@@ -218,8 +239,8 @@ export const Https = {
historyChoose: `/api/history/choose`, //History choose
getDesignDetail: `/api/design/detail/getDetail`, //查询design详情
designSingleWithGradient: `/api/design/detail/designSingleWithGradient`, //查询需要更新mask列表
getNextSysElement:'/api/design/detail/getNextSysElement',//切换系统的element
detailPrintDot:'/api/design/detail/printDot',//print打点预览
getNextSysElement: "/api/design/detail/getNextSysElement", //切换系统的element
detailPrintDot: "/api/design/detail/printDot", //print打点预览
designSingle: `/api/design/detail/designSingle`, //单个design
queryLibraryPage: `/api/library/queryLibraryPage`, //Library分页列表
libraryUpload: `/api/library/upload`, // Library文件上传
@@ -258,8 +279,6 @@ export const Https = {
poselikeOrDisike: `/api/generate/likeOrDislike`, //postTransform like
getAllPose: `/api/generate/getAllPose`, //获取动作
//拼贴
genSketchRecon: `/api/generate/genSketchRecon`,
saveReconCanvas: `/api/generate/saveReconCanvas`,
@@ -268,11 +287,11 @@ export const Https = {
poseTransform: `/api/generate/poseTransform`,
poseTransformResult: `/api/generate/poseTransformResult`,
batchUpdateLibraryName:'/api/library/batchUpdateLibraryName',//Library修改用户文件名
batchDeleteLibrary:'/api/library/batchDeleteLibrary',//删除library
queryLibraryTopAndBottomPage:'/api/library/queryLibraryTopAndBottomPage',//Library分页列表(查询top和bottom)
saveOrEditTemplatePoint:'/api/library/saveOrEditTemplatePoint',//保存或者编辑template打点
libraryModelsDot:'/api/library/modelsDot',//Models打点预览
batchUpdateLibraryName: "/api/library/batchUpdateLibraryName", //Library修改用户文件名
batchDeleteLibrary: "/api/library/batchDeleteLibrary", //删除library
queryLibraryTopAndBottomPage: "/api/library/queryLibraryTopAndBottomPage", //Library分页列表(查询top和bottom)
saveOrEditTemplatePoint: "/api/library/saveOrEditTemplatePoint", //保存或者编辑template打点
libraryModelsDot: "/api/library/modelsDot", //Models打点预览
chatStreamTest: `/api/python/chatStream`, //机器人助力
pictureLikeOrUnLike: `/api/python/pictureLikeOrUnLike`, //机器人生成图喜欢
getBloodBars: `/api/python/getBloodBars`, //机器人血条
@@ -286,15 +305,15 @@ export const Https = {
getStyleList: `/api/workspace/styleList`, //获取所有风格列表
workspaceList: `/api/workspace/list`,
sketchAndPrintGenerate:'/api/generate/sketchAndPrint',//sketchGenerate生成图片
sketchAndPrintGenerate: "/api/generate/sketchAndPrint", //sketchGenerate生成图片
generatePrepare:'/api/generate/prepare',//开始生成generate图片
generateStopWaiting:'/api/generate/stopWaiting',//取消生成
generateResult:'/api/generate/result',//获取生成结果
generateLike:'/api/generate/like',//喜欢ganerate图片
generateDislike:'/api/generate/dislike',//喜欢ganerate图片
imageToSketch:'/api/generate/imageToSketch',//成品图转为线稿
modifySketch:'/api/generate/modifySketch',//修改画布内容并且储存
generatePrepare: "/api/generate/prepare", //开始生成generate图片
generateStopWaiting: "/api/generate/stopWaiting", //取消生成
generateResult: "/api/generate/result", //获取生成结果
generateLike: "/api/generate/like", //喜欢ganerate图片
generateDislike: "/api/generate/dislike", //喜欢ganerate图片
imageToSketch: "/api/generate/imageToSketch", //成品图转为线稿
modifySketch: "/api/generate/modifySketch", //修改画布内容并且储存
elementUpload: `/api/element/upload`, //上传图片
imageSegmentation: `/api/element/imageSegmentation`, //分割衣服
@@ -324,7 +343,6 @@ export const Https = {
addOrganization: `/api/inquiry/addOrganization`, //添加企业版或者教育版
queryOrganization: `/api/inquiry/queryOrganization`, //查询企业版或者教育版
//云生成
designCloud: `/api/design/designCloud`, //创建云生成
cloudPage: `/api/design/cloudPage`, //创建云生成
@@ -369,7 +387,6 @@ export const Https = {
getTasksHistory: `/api/tasks/getAllTask`, //获取所有任务列表
prepareForSR: `/api/python/prepareForSR`, //超分
//作品广场
publish: `/api/portfolio/publish`, //发布作品到作品广场
getPorfolio: `/api/portfolio/page`, //查询作品广场
@@ -426,67 +443,73 @@ export const Https = {
getHistoryNotification: `/api/message/getHistoryNotification`, //获取历史消息
oneClickRead: `/api/message/oneClickRead`, //全部设为已读
personalHomepage: `/api/account/personalHomepage`, //获取个人主页信息
},
axiosGet(url, config) {
return new Promise((resolve, reject) => {
if(isLoginTime && url != '/api/portfolio/page') {
resolve('')
return
if (isLoginTime && url != "/api/portfolio/page") {
resolve("");
return;
}
axios.get(url,config).then(response => {
resolve(response)
}).catch((error) => {
reject(error)
axios
.get(url, config)
.then((response) => {
resolve(response);
})
.catch((error) => {
reject(error);
});
});
},
axiosPut(url, data) {
return new Promise((resolve, reject) => {
if(isLoginTime && url != '/api/portfolio/page') {
resolve('')
return
if (isLoginTime && url != "/api/portfolio/page") {
resolve("");
return;
}
axios.put(url, data).then(response => {
resolve(response)
}).catch((error) => {
reject(error)
axios
.put(url, data)
.then((response) => {
resolve(response);
})
.catch((error) => {
reject(error);
});
});
},
axiosPost(url, data, config) {
return new Promise((resolve, reject) => {
if(isLoginTime && url != '/api/portfolio/page') {
resolve('')
return
if (isLoginTime && url != "/api/portfolio/page") {
resolve("");
return;
}
axios.post(url, data,config).then(response => {
resolve(response)
}).catch((error) => {
reject(error)
axios
.post(url, data, config)
.then((response) => {
resolve(response);
})
.catch((error) => {
reject(error);
});
});
},
axiosDelete(url, newData) {
return new Promise((resolve, reject) => {
if(isLoginTime && url != '/api/portfolio/page') {
resolve('')
return
if (isLoginTime && url != "/api/portfolio/page") {
resolve("");
return;
}
axios.delete(url,{data:newData}).then(response => {
resolve(response)
}).catch((error) => {
reject(error)
axios
.delete(url, { data: newData })
.then((response) => {
resolve(response);
})
.catch((error) => {
reject(error);
});
});
},
}
};

View File

@@ -1,36 +1,37 @@
import Fingerprint2 from 'fingerprintjs2';//获取浏览器唯一标识
import Fingerprint2 from "fingerprintjs2"; //获取浏览器唯一标识
const isEmail = (email) => {
// let reg = /^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,})$/
let reg = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/
let result = reg.test(email)
return result
}
let reg = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
let result = reg.test(email);
return result;
};
const getUploadUrl = () => {
let url = process.env.VUE_APP_BASE_URL || ''
let url = import.meta.env.VITE_APP_BASE_URL || "";
// let url = "http://18.167.251.121:10086"
return url
}
return url;
};
const getMinioUrl = (url) => {
const { pathname } = new URL(url);
const result = pathname.slice(1);
return result
}
const rgbaToHex = (rgba)=> { // rgba转16进制
let hex = '#';
return result;
};
const rgbaToHex = (rgba) => {
// rgba转16进制
let hex = "#";
rgba.forEach((i, index) => {
if (index == 3) {
hex += Math.round(i * 255).toString(16)
hex += Math.round(i * 255).toString(16);
} else {
hex += Number(i).toString(16).padStart(2, '0');
hex += Number(i).toString(16).padStart(2, "0");
}
});
return hex;
}
};
function base64ToFile(urlData, name) {
let arr = urlData.split(',');
let arr = urlData.split(",");
let mime = arr[0].match(/:(.*?);/)[1];
let bstr = atob(arr[1]);
let n = bstr.length;
@@ -39,12 +40,13 @@ function base64ToFile(urlData,name) {
u8arr[n] = bstr.charCodeAt(n);
}
return new File([u8arr], name, {
type: mime
type: mime,
});
}
function dataURLtoBlob(dataurl) {//吧data url转为blob对象
var arr = dataurl.split(',');
function dataURLtoBlob(dataurl) {
//吧data url转为blob对象
var arr = dataurl.split(",");
var mime = arr[0].match(/:(.*?);/)[1];
var bstr = atob(arr[1]);
var n = bstr.length;
@@ -55,37 +57,43 @@ function dataURLtoBlob(dataurl) {//吧data url转为blob对象
return new Blob([u8arr], { type: mime });
}
function blobToFile(blob, fileName) {//给blob文件设置名字和日期
function blobToFile(blob, fileName) {
//给blob文件设置名字和日期
blob.lastModifiedDate = new Date();
blob.name = fileName;
return blob;
}
//下载图片
function downloadIamge(imgsrc, name) { // 下载图片地址和图片名
var image = new Image()
function downloadIamge(imgsrc, name) {
// 下载图片地址和图片名
var image = new Image();
// 解决跨域 Canvas 污染问题
image.setAttribute('crossOrigin', 'anonymous')
image.setAttribute("crossOrigin", "anonymous");
image.onload = function () {
var canvas = document.createElement('canvas')
canvas.width = image.width
canvas.height = image.height
var context = canvas.getContext('2d')
context.drawImage(image, 0, 0, image.width, image.height)
var url = canvas.toDataURL('image/png') // 得到图片的base64编码数据
var a = document.createElement('a') // 生成一个a元素
var event = new MouseEvent('click') // 创建一个单击事件
a.download = name || 'generate' // 设置图片名称
a.href = url // 将生成的URL设置为a.href属性
a.target = '_blank'
a.dispatchEvent(event) // 触发a的单击事件
image.remove()
}
image.src = imgsrc
var canvas = document.createElement("canvas");
canvas.width = image.width;
canvas.height = image.height;
var context = canvas.getContext("2d");
context.drawImage(image, 0, 0, image.width, image.height);
var url = canvas.toDataURL("image/png"); // 得到图片的base64编码数据
var a = document.createElement("a"); // 生成一个a元素
var event = new MouseEvent("click"); // 创建一个单击事件
a.download = name || "generate"; // 设置图片名称
a.href = url; // 将生成的URL设置为a.href属性
a.target = "_blank";
a.dispatchEvent(event); // 触发a的单击事件
image.remove();
};
image.src = imgsrc;
}
function dataURLtoFile(dataurl, filename) {//吧url转为文件对象指定文件名称
var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
function dataURLtoFile(dataurl, filename) {
//吧url转为文件对象指定文件名称
var arr = dataurl.split(","),
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
@@ -93,42 +101,44 @@ function dataURLtoFile(dataurl, filename) {//吧url转为文件对象指定
return blobToFile(blob, filename);
}
const base64toFile = (dataurl, filename = 'file') => {//转换base64
let arr = dataurl.split(',')
let mime = arr[0].match(/:(.*?);/)[1]
let suffix = mime.split('/')[1]
let bstr = atob(arr[1])
let n = bstr.length
let u8arr = new Uint8Array(n)
const base64toFile = (dataurl, filename = "file") => {
//转换base64
let arr = dataurl.split(",");
let mime = arr[0].match(/:(.*?);/)[1];
let suffix = mime.split("/")[1];
let bstr = atob(arr[1]);
let n = bstr.length;
let u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
u8arr[n] = bstr.charCodeAt(n);
}
return new File([u8arr], `${filename}.${suffix}`, {
type: mime
})
type: mime,
});
};
}
function rgbToHsv([R, G, B]) {//根据rgb获取hsv
R /= 255
G /= 255
B /= 255
const max = Math.max(R, G, B)
const min = Math.min(R, G, B)
const delta = max - min
var H, S, V
function rgbToHsv([R, G, B]) {
//根据rgb获取hsv
R /= 255;
G /= 255;
B /= 255;
const max = Math.max(R, G, B);
const min = Math.min(R, G, B);
const delta = max - min;
var H, S, V;
if (delta === 0) {
H = 0;
} else if (max === R) {
H = ((G - B) / delta) % 6;
} else if (max === G) {
H = (B - R) / delta + 2;
} else { // max === B
} else {
// max === B
H = (R - G) / delta + 4;
}
H = Math.round(H * 60); // 范围为 0-360
if (H < 0) {
H = 360 + H
H = 360 + H;
}
if (max === 0) {
S = 0;
@@ -137,10 +147,11 @@ function rgbToHsv([R, G, B]) {//根据rgb获取hsv
}
S = Math.round(S * 100); // 范围为 0-100
V = Math.round(max * 100); // 范围为 0-100
return [H, S, V]
return [H, S, V];
}
const formatTime = (timestamp, fmt) => {//吧时间戳转为YYYY-MM-DD hh:mm:ss格式
const formatTime = (timestamp, fmt) => {
//吧时间戳转为YYYY-MM-DD hh:mm:ss格式
// date = new Date(), fmt = 'MM/dd/yyyy';
let date = new Date();
date.setTime(timestamp * 1000);
@@ -150,38 +161,46 @@ const formatTime = (timestamp, fmt) => {//吧时间戳转为YYYY-MM-DD hh:mm:ss
}
// console.log(formatRule)
let o = {
'M+': date.getMonth() + 1, // 月份
'D+': date.getDate(), // 日
'h+': date.getHours(), // 小时
'm+': date.getMinutes(), // 分
's+': date.getSeconds(), // 秒
'q+': Math.floor((date.getMonth() + 3) / 3), // 季度
'S+': date.getMilliseconds(), // 毫秒
'a': date.getHours() > 12
? 'PM'
: 'AM' // 上午还是下午
"M+": date.getMonth() + 1, // 月份
"D+": date.getDate(), // 日
"h+": date.getHours(), // 小时
"m+": date.getMinutes(), // 分
"s+": date.getSeconds(), // 秒
"q+": Math.floor((date.getMonth() + 3) / 3), // 季度
"S+": date.getMilliseconds(), // 毫秒
a: date.getHours() > 12 ? "PM" : "AM", // 上午还是下午
};
if (/(Y+)/.test(fmt)) {
fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length));
fmt = fmt.replace(
RegExp.$1,
(date.getFullYear() + "").substr(4 - RegExp.$1.length)
);
}
if (/(a)/.test(fmt) && o['h+'] > 12) {
o['h+'] = o['h+'] - 12
if (/(a)/.test(fmt) && o["h+"] > 12) {
o["h+"] = o["h+"] - 12;
}
for (let k in o) {
if (new RegExp('(' + k + ')').test(fmt)) {
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1)
? (o[k])
: (('00' + o[k]).substr(('' + o[k]).length)));
if (new RegExp("(" + k + ")").test(fmt)) {
fmt = fmt.replace(
RegExp.$1,
RegExp.$1.length == 1 ? o[k] : ("00" + o[k]).substr(("" + o[k]).length)
);
}
}
return fmt;
}
};
const isMoible = () => {//判断是否是移动端
let is_mobile = navigator.userAgent.toLowerCase().match(/(ipad|ipod|iphone|android|coolpad|mmp|smartphone|midp|wap|xoom|symbian|j2me|blackberry|wince)/i) != null;
const isMoible = () => {
//判断是否是移动端
let is_mobile =
navigator.userAgent
.toLowerCase()
.match(
/(ipad|ipod|iphone|android|coolpad|mmp|smartphone|midp|wap|xoom|symbian|j2me|blackberry|wince)/i
) != null;
// alert(navigator.userAgent.toLowerCase())
var isiPad = (navigator.maxTouchPoints && navigator.maxTouchPoints > 1);
var isiPad = navigator.maxTouchPoints && navigator.maxTouchPoints > 1;
// if (is_mobile) {
// return true//判断是否在正则内
// } else if(window.matchMedia("(pointer:fine)").matches){
@@ -190,11 +209,11 @@ const isMoible = () => {//判断是否是移动端
// isiPad//判断触摸点
// }
if (is_mobile) {
return true//判断是否在正则内
return true; //判断是否在正则内
} else {
return isiPad//判断触摸点
}
return isiPad; //判断触摸点
}
};
let setPubDate = (date) => {
const timestamp = new Date(date);
@@ -225,16 +244,18 @@ let setPubDate = (date)=>{
} else {
return `1 minute ago`;
}
}
};
function getBrowserInfo() {//获取是什么浏览器
function getBrowserInfo() {
//获取是什么浏览器
var agent = navigator.userAgent.toLowerCase();
var userAgent = navigator.userAgent;
var regStr_ie = /msie [\d.]+;/gi;
var regStr_ff = /firefox\/[\d.]+/gi
var regStr_ff = /firefox\/[\d.]+/gi;
var regStr_chrome = /chrome\/[\d.]+/gi;
var regStr_saf = /safari\/[\d.]+/gi;
var isIE = userAgent.indexOf("compatible") > -1 && userAgent.indexOf("MSIE") > -1; //判断是否IE<11浏览器
var isIE =
userAgent.indexOf("compatible") > -1 && userAgent.indexOf("MSIE") > -1; //判断是否IE<11浏览器
var isEdge = userAgent.indexOf("Edge") > -1 && !isIE; //判断是否IE的Edge浏览器
//IE
if (agent.indexOf("msie") > 0) {
@@ -253,13 +274,11 @@ function getBrowserInfo() {//获取是什么浏览器
return agent.match(regStr_saf);
}
}
async function murmur(){//生成唯一标识 ,暂时没有使用
async function murmur() {
//生成唯一标识 ,暂时没有使用
return await new Promise((resolve, reject) => {
Fingerprint2.get(function (components) {
const values = components.map(function (
component,
index
) {
const values = components.map(function (component, index) {
if (index === 0) {
//把微信浏览器里UA的wifi或4G等网络替换成空,不然切换网络会ID不一样
return component.value.replace(/\bNetType\/\w+\b/, "");
@@ -268,9 +287,9 @@ async function murmur(){//生成唯一标识 ,暂时没有使用
});
// 生成最终id murmur
let murmur = Fingerprint2.x64hash128(values.join(""), 31);
resolve(murmur)
resolve(murmur);
});
});
})
}
/**
* @description: 计算canvas渐变起始坐标
@@ -324,7 +343,7 @@ function calculateGradientCoordinate(width,height,angle) {
const alpha = Math.round(
(Math.asin(width / Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2))) *
180) /
Math.PI,
Math.PI
);
// 当渐变轴分别于矩形的两条对角线重合情况下的四种结果
@@ -428,45 +447,49 @@ function calculateGradientCoordinate(width,height,angle) {
const setGradual = (colorObj, colorWidth, colorHeight) => {
return new Promise((resolve, reject) => {
let width = colorWidth || 320
let height = colorHeight || 700
let width = colorWidth || 320;
let height = colorHeight || 700;
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
canvas.width = width;
canvas.height = height;
let {x0, y0, x1, y1} = calculateGradientCoordinate(width,height,colorObj.angle)
let { x0, y0, x1, y1 } = calculateGradientCoordinate(
width,
height,
colorObj.angle
);
const gradient = ctx.createLinearGradient(x0, y0, x1, y1);
colorObj.gradientList.forEach(item => {
let left = item.left.split('%')[0]/100
let rgba = `rgba(${item.rgba.r},${item.rgba.g},${item.rgba.b},${item.rgba.a})`
colorObj.gradientList.forEach((item) => {
let left = item.left.split("%")[0] / 100;
let rgba = `rgba(${item.rgba.r},${item.rgba.g},${item.rgba.b},${item.rgba.a})`;
gradient.addColorStop(left, rgba); // 起始颜色
});
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, width, height);
// let dataURL = canvas.toDataURL('image/jpg');
resolve(canvas.toDataURL('image/jpg'))
})
}
resolve(canvas.toDataURL("image/jpg"));
});
};
function segmentImage(markerImage, fullImage, size) {
return new Promise((resolve, reject) => {
const markerCanvas = document.createElement('canvas');
const fullCanvas = document.createElement('canvas');
const nullCanvas = document.createElement('canvas');
const ctx1 = markerCanvas.getContext('2d');
const ctx2 = fullCanvas.getContext('2d');
const ctx3 = nullCanvas.getContext('2d');
markerCanvas.width=size.width
markerCanvas.height=size.height
fullCanvas.height=size.height
fullCanvas.width=size.width
nullCanvas.height=size.height
nullCanvas.width=size.width
let targetFrontUrl = ''
let targetBackUrl = ''
const markerCanvas = document.createElement("canvas");
const fullCanvas = document.createElement("canvas");
const nullCanvas = document.createElement("canvas");
const ctx1 = markerCanvas.getContext("2d");
const ctx2 = fullCanvas.getContext("2d");
const ctx3 = nullCanvas.getContext("2d");
markerCanvas.width = size.width;
markerCanvas.height = size.height;
fullCanvas.height = size.height;
fullCanvas.width = size.width;
nullCanvas.height = size.height;
nullCanvas.width = size.width;
let targetFrontUrl = "";
let targetBackUrl = "";
const marker = new Image();
const full = new Image();
marker.crossOrigin = 'anonymous';
full.crossOrigin = 'anonymous';
marker.crossOrigin = "anonymous";
full.crossOrigin = "anonymous";
marker.onload = () => {
ctx1.drawImage(marker, 0, 0, size.width, size.height);
full.onload = () => {
@@ -477,7 +500,6 @@ function segmentImage(markerImage,fullImage,size){
};
marker.src = markerImage;
function segmentImageItem() {
const markerData = ctx1.getImageData(0, 0, size.width, size.height);
const fullData = ctx2.getImageData(0, 0, size.width, size.height);
@@ -491,8 +513,7 @@ function segmentImage(markerImage,fullImage,size){
// (Math.abs(b - color.b) < threshold) || (Math.abs(0 - color.b) < threshold)
const isColorMatch = (r, g, b, color) =>
((color.r >= color.g) && r >= g) ||
((color.r < color.g) && r < g)
(color.r >= color.g && r >= g) || (color.r < color.g && r < g);
// (Math.abs(b - color.b) < threshold || Math.abs(0 - color.b) < threshold)
@@ -503,7 +524,7 @@ function segmentImage(markerImage,fullImage,size){
const g = markerData.data[i + 1];
const b = markerData.data[i + 2];
let a = markerData.data[i + 3];
a>1?a = 255:0
a > 1 ? (a = 255) : 0;
if (r >= g && a > 1) {
// 将完整图像中对应的像素复制到第一个输出图像
output1.data[i] = fullData.data[i];
@@ -548,23 +569,23 @@ function segmentImage(markerImage,fullImage,size){
}
}
const createImageURL = (imageData) => {
const canvas = document.createElement('canvas');
const canvas = document.createElement("canvas");
canvas.width = size.width;
canvas.height = size.height;
const ctx = canvas.getContext('2d');
const ctx = canvas.getContext("2d");
ctx.putImageData(imageData, 0, 0);
let data = canvas.toDataURL('image/png')
canvas.remove()
let data = canvas.toDataURL("image/png");
canvas.remove();
return data;
};
targetBackUrl =createImageURL(output2)
targetFrontUrl =createImageURL(output1)
resolve({targetFrontUrl, targetBackUrl})
markerCanvas.remove()
fullCanvas.remove()
nullCanvas.remove()
targetBackUrl = createImageURL(output2);
targetFrontUrl = createImageURL(output1);
resolve({ targetFrontUrl, targetBackUrl });
markerCanvas.remove();
fullCanvas.remove();
nullCanvas.remove();
}
})
});
}
export {
isEmail,
@@ -586,4 +607,4 @@ export {
setGradual,
calculateGradientCoordinate,
segmentImage,
}
};

View File

@@ -1,71 +1,77 @@
import { setCookie, getCookie, WriteCookie,clonAllCookie } from "@/tool/cookie";
import {
setCookie,
getCookie,
WriteCookie,
clonAllCookie,
} from "@/tool/cookie";
import MyEvent from "@/tool/myEvents";
class MyWs {
constructor() {
this.ws = null;
// this.ws = new WebSocket();
let http = process.env.VUE_APP_BASE_URL.replace(/^https?:\/\//, '')
this.messageUrl = http+'/notification'
this.wsUrl = ''
this.reconnectionTime = null
this.times = 0
this.sendPINGTime = null
let http = import.meta.env.VITE_APP_BASE_URL.replace(/^https?:\/\//, "");
this.messageUrl = http + "/notification";
this.wsUrl = "";
this.reconnectionTime = null;
this.times = 0;
this.sendPINGTime = null;
}
linkWs(url) {
if(!(JSON.parse(getCookie("userInfo"))))return
if (this.ws && this.ws.readyState == 1) return
if(!this.wsUrl)this.wsUrl = url +`/${JSON.parse(getCookie("userInfo")).userId}`
this.ws = new WebSocket(this.wsUrl)
if (!JSON.parse(getCookie("userInfo"))) return;
if (this.ws && this.ws.readyState == 1) return;
if (!this.wsUrl)
this.wsUrl = url + `/${JSON.parse(getCookie("userInfo")).userId}`;
this.ws = new WebSocket(this.wsUrl);
this.ws.onmessage = (e) => {
try {
let rv = JSON.parse(e.data)
if(rv == "PONG")return
this.times = 0
MyWs.receiveText(rv)
let rv = JSON.parse(e.data);
if (rv == "PONG") return;
this.times = 0;
MyWs.receiveText(rv);
} catch (error) {
console.error('websocket',error)
console.error("websocket", error);
}
}
clearInterval(this.sendPINGTime)
};
clearInterval(this.sendPINGTime);
this.sendPINGTime = setInterval(() => {
this.send({text:'PING'})
this.send({ text: "PING" });
// },1000)
},1000*60*2)
}, 1000 * 60 * 2);
this.ws.onclose = (e) => {
this.reconnection()
}
this.reconnection();
};
this.ws.onerror = (e) => {
this.reconnection()
}
this.reconnection();
};
}
reconnection() {
this.times++
clearTimeout(this.reconnectionTime)
if(this.times>=10)return
clearInterval(this.sendPINGTime)
this.times++;
clearTimeout(this.reconnectionTime);
if (this.times >= 10) return;
clearInterval(this.sendPINGTime);
this.reconnectionTime = setTimeout(() => {
this.linkWs(this.wsUrl)
},1000)
this.linkWs(this.wsUrl);
}, 1000);
}
static receiveText(data, call) {
MyEvent.emit('getMessage',data)
MyEvent.emit("getMessage", data);
}
sendMessage(data) {
if (this.ws && this.ws.readyState == 1) {
let obj = {
cmd: 1,
data: {
name: '123',
}
}
this.send(obj)
name: "123",
},
};
this.send(obj);
obj = {
cmd: 4,
data: {
msg: data,
}
}
this.send(obj)
},
};
this.send(obj);
// obj = {
// cmd: 6,
// data: {
@@ -77,18 +83,18 @@ class MyWs {
}
send(obj) {
if (this.ws.readyState == 1) {
this.ws.send(JSON.stringify(obj))
this.ws.send(JSON.stringify(obj));
} else {
clearTimeout(this.sendPINGTime)
this.reconnection()
clearTimeout(this.sendPINGTime);
this.reconnection();
}
}
close() {
if (this.ws && this.ws.readyState == 1) {
console.log("客户端 连接已关闭")
this.ws.close()
console.log("客户端 连接已关闭");
this.ws.close();
}
}
}
export default new MyWs()
export default new MyWs();

116
vite.config.js Normal file
View File

@@ -0,0 +1,116 @@
import { defineConfig, loadEnv } from "vite";
import vue from "@vitejs/plugin-vue";
import Components from "unplugin-vue-components/vite";
import { AntDesignVueResolver } from "unplugin-vue-components/resolvers";
import AutoImport from "unplugin-auto-import/vite";
import { createSvgIconsPlugin } from "vite-plugin-svg-icons";
import path from "path";
// https://vite.dev/config/
export default defineConfig(({ mode }) => {
// 加载环境变量
const env = loadEnv(mode, process.cwd(), "");
return {
resolve: {
alias: {
"@": path.resolve(__dirname, "src"),
},
},
plugins: [
vue(),
Components({
resolvers: [AntDesignVueResolver({ importStyle: false })],
}),
AutoImport({
imports: [
"vue",
"vue-router",
{
"lodash-es": [
"debounce",
"cloneDeep",
"cloneDeepWith",
"isBoolean",
"isString",
"isNumber",
"isArray",
"isDate",
"isFunction",
"isNaN",
"isNull",
"isObject",
"isUndefined",
],
},
],
dts: "src/auto-imports.d.ts",
}),
createSvgIconsPlugin({
// 指定需要缓存的图标文件夹
iconDirs: [path.resolve(process.cwd(), "src/assets/icons")],
// 指定symbolId格式
symbolId: "icon-[dir]-[name]",
}),
],
css: {
preprocessorOptions: {
less: {
modifyVars: {
"primary-color": "#ec6800",
},
javascriptEnabled: true,
// 全局导入less变量文件
additionalData: `@import "${path.resolve(
__dirname,
"src/assets/style/style.less"
)}";`,
},
},
},
server: {
host: "0.0.0.0", // 允许局域网内的IP访问
port: mode === "production" ? 8060 : 10086, // 根据环境设置端口
open: true, // 自动打开浏览器
strictPort: false, // 如果端口已被占用,则尝试下一个可用端口
proxy: {
"/api": {
target: "http://192.168.1.7:5567",
// target: 'https://develop.api.aida.com.hk',
changeOrigin: true,
},
"/xupei": {
target: "http://192.168.1.7:5567",
changeOrigin: true,
rewrite: (path) => path.replace(/^\/robot/, "/api"),
},
"/oldsis": {
target: "https://old.api.aida.com.hk",
changeOrigin: true,
rewrite: (path) => path.replace(/^\/oldsis/, "/api"),
},
},
},
build: {
sourcemap: false, // 对应vue.config.js中的productionSourceMap: false
outDir: "dist",
assetsDir: "assets",
// 分包策略
rollupOptions: {
output: {
manualChunks: {
vendor: ["vue", "vue-router", "vuex"],
antd: ["ant-design-vue"],
utils: ["axios", "lodash-es"],
},
},
},
},
// 定义全局常量替换
define: {
__VUE_OPTIONS_API__: true,
__VUE_PROD_DEVTOOLS__: false,
__VUE_PROD_HYDRATION_MISMATCH_DETAILS__: false,
},
};
});

View File

@@ -1,79 +0,0 @@
const {defineConfig} = require('@vue/cli-service')
const path = require('path');
const webpack = require('webpack')
module.exports = defineConfig({
transpileDependencies: ['vuetify'],
lintOnSave:false,//关闭语法检查
productionSourceMap: false,//打包不生成map文件减少文件大小
devServer: {
// hot: true, // 热更新
// port: '8060',
port: process.env.NODE_ENV === 'production'
? '8060'
: '10086',
proxy: {
// "/api": {
// // target: 'https://www.aida.com.hk', //后端接口地址
// target: process.env.VUE_APP_BASE_URL,
// changeOrigin: true, //是否允许跨越
// }
'/api':{
target:'http://192.168.1.7:5567',
// target:'https://develop.api.aida.com.hk',
changeOrigin:true,
},
'/xupei':{
target:'http://192.168.1.7:5567',
changeOrigin:true,
pathRewrite:{
'^/robot': 'api', // api替换成api
}
},
'/oldsis':{
target:'https://old.api.aida.com.hk',
changeOrigin:true,
pathRewrite:{
'^/oldsis': 'api', // api替换成api
}
}
},
// https:true,
},
pluginOptions: {
"style-resources-loader": {
preProcessor: "less",
patterns: [
// 存放less变量文件的路径
path.resolve(__dirname, "./src/assets/style/style.less")
]
}
},
css: {
loaderOptions: {
less: {
lessOptions: {
modifyVars: {
'primary-color': '#ec6800'
},
javascriptEnabled: true,
},
},
},
},
configureWebpack: {
plugins: [
require('unplugin-element-plus/webpack')({
// options
}),
],
},
})