chat聊天功能
This commit is contained in:
531
src/component/home/chat/index.vue
Normal file
531
src/component/home/chat/index.vue
Normal file
@@ -0,0 +1,531 @@
|
||||
<template>
|
||||
<div class="chat" :class="{active:!openChat}" @click.stop="">
|
||||
<div v-show="!openChat" class="left" @click="()=>{openChat = !openChat;isChattingRecords=false}">
|
||||
<i class="fi fi-br-angle-small-down"></i>
|
||||
</div>
|
||||
<div class="chatBox">
|
||||
<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="textBox">
|
||||
<div class="icon">ICON</div>
|
||||
<div class="text" v-show="item.content.message || item.content.img || item.content.color">
|
||||
<span>{{item.content.message}}</span>
|
||||
<div class="fileBox">
|
||||
<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="">
|
||||
</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>
|
||||
</div>
|
||||
</div>
|
||||
<i class="fi fi-br-loading" v-if="!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>
|
||||
<div class="btn">
|
||||
<div class="uploadBox">
|
||||
<div class="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>
|
||||
</div>
|
||||
</div>
|
||||
<i class="fi fi-br-upload">
|
||||
<input type="file" @change="handleFileUpload($event)">
|
||||
</i>
|
||||
</div>
|
||||
<div class="sendBox">
|
||||
<div class="enableThinking" :class="{active:enableThinking}" @click="()=>enableThinking = !enableThinking">Deep Thinking</div>
|
||||
<div class="maxNum">{{ chatContent.length }}/10000</div>
|
||||
<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}">
|
||||
<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 { Https } from "@/tool/https";
|
||||
import { useStore } from "vuex";
|
||||
import { Modal,message,Upload,CascaderProps } from 'ant-design-vue';
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { setCookie, getCookie, WriteCookie } from "@/tool/cookie";
|
||||
export default defineComponent({
|
||||
components:{
|
||||
},
|
||||
props:{
|
||||
},
|
||||
emits:['chatChange'],
|
||||
setup(props,{emit}) {
|
||||
const store = useStore();
|
||||
const data = reactive({
|
||||
chatContent:'',
|
||||
openChat:true,
|
||||
chatList:[
|
||||
] as any,
|
||||
isChattingRecords:false,
|
||||
selectObject:computed(()=>store.state.Workspace.probjects) as any,//选择的项目
|
||||
filList:[] 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){
|
||||
getChatHistory(newValue)
|
||||
}
|
||||
})
|
||||
const inputText = (e:any)=>{
|
||||
if(e.target.value.length <= 1000){
|
||||
data.chatContent = e.target.value
|
||||
}else{
|
||||
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 = 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(',') : ''
|
||||
data.chatList.push({content:{message:data.chatContent},role:'user',fileList:fileList})
|
||||
data.chatList.push({content:{message:''},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 = []
|
||||
eventSource.onmessage = function(event) {
|
||||
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;
|
||||
container.scrollTop = container.scrollHeight;
|
||||
if(JSON.parse(event.data).status == "[RUNNING]"){
|
||||
data.chatList[data.chatList.length-1].content.message+=JSON.parse(event.data).content
|
||||
}else{
|
||||
if(JSON.parse(event.data).status == "[DESIGN_SIGNAL]"){
|
||||
|
||||
}else if(JSON.parse(event.data).status == "[COLOR_SIGNAL]"){
|
||||
data.chatList.push({content:{message:''},role:'system'})
|
||||
data.chatList[data.chatList.length-1].content.color = JSON.parse(JSON.parse(event.data).tools_data).receiveCollectionElementList
|
||||
data.chatList.push({content:{message:''},role:'system'})
|
||||
}else{
|
||||
data.chatList.push({content:{message:''},role:'system'})
|
||||
data.chatList[data.chatList.length-1].content.img = JSON.parse(JSON.parse(event.data).tools_data).receiveCollectionElementList
|
||||
data.chatList.push({content:{message:''},role:'system'})
|
||||
}
|
||||
console.log(data.chatList[data.chatList.length-1].content)
|
||||
emit('chatChange',{type:JSON.parse(event.data).status})
|
||||
}
|
||||
|
||||
};
|
||||
eventSource.onerror = function(error) {
|
||||
console.log(error,EventSource.CLOSED,eventSource.readyState)
|
||||
if (eventSource.readyState === EventSource.CLOSED) {
|
||||
data.chatList[data.chatList.length-1].content.message='服务器繁忙,请稍后再试。'
|
||||
|
||||
} else {
|
||||
eventSource.close()
|
||||
data.isFinish = true
|
||||
}
|
||||
};
|
||||
}
|
||||
const getChatHistory = (objectId:number)=>{
|
||||
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].isImage == 1){
|
||||
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==2){
|
||||
rv.content[rv.content.length - index -1].content={
|
||||
color : JSON.parse(rv.content[rv.content.length - index -1].content)
|
||||
}
|
||||
}else{
|
||||
rv.content[rv.content.length - index -1].content = {
|
||||
message:text
|
||||
}
|
||||
}
|
||||
}else{
|
||||
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]
|
||||
}
|
||||
if(content.file){
|
||||
content.file.forEach((item:any)=>{
|
||||
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])
|
||||
});
|
||||
}
|
||||
})
|
||||
}
|
||||
const openChattingRecords = ()=>{
|
||||
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
|
||||
}
|
||||
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
|
||||
}
|
||||
}else{
|
||||
if(data.filList.filter((item:any)=>item.type == 'file').length >= 1){
|
||||
message.info('You can only upload one file.');
|
||||
return
|
||||
}
|
||||
}
|
||||
data.setIsShowMark(true)
|
||||
const formData = new FormData();
|
||||
formData.append('file', event.target.files[0]);
|
||||
let config:any = {
|
||||
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',
|
||||
minioPath:rv[0],
|
||||
url:rv[1],
|
||||
}
|
||||
data.filList.push(obj)
|
||||
// data.filList.unshift(rv)
|
||||
data.setIsShowMark(false)
|
||||
}
|
||||
).catch(rv=>{
|
||||
data.setIsShowMark(false)
|
||||
})
|
||||
}
|
||||
const deleteFile = (item:any,index:number)=>{
|
||||
data.filList.splice(index,1)
|
||||
}
|
||||
return{
|
||||
...toRefs(dataDom),
|
||||
...toRefs(data),
|
||||
inputText,
|
||||
sendChat,
|
||||
openChattingRecords,
|
||||
handleFileUpload,
|
||||
deleteFile,
|
||||
}
|
||||
},
|
||||
provide() {
|
||||
return {
|
||||
}
|
||||
},
|
||||
})
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.chat{
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
z-index: 999;
|
||||
bottom: 3.2rem;
|
||||
top: auto;
|
||||
width: 50%;
|
||||
transition: all .3s;
|
||||
border-radius: 2.4rem;
|
||||
display: flex;
|
||||
border: 1px solid #e5e5e5;
|
||||
background: #fff;
|
||||
overflow: hidden;
|
||||
&.active{
|
||||
left: auto;
|
||||
right: 0;
|
||||
transform: translateX(calc(100% - 3rem));
|
||||
}
|
||||
> .chatBox{
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
> .chattingRecords{
|
||||
> .itemBox{
|
||||
width: 100%;
|
||||
padding: 1.6rem 2rem;
|
||||
max-height: 75vh;
|
||||
overflow-y: auto;
|
||||
> .item{
|
||||
display: flex;
|
||||
line-height: 1.75;
|
||||
// width: min-content;
|
||||
&.user{
|
||||
> .textBox{
|
||||
margin-left: auto;
|
||||
background: #f5f5f5;
|
||||
max-width: 60%;
|
||||
> .text{
|
||||
> .fileBox{
|
||||
> .item{
|
||||
height: 3rem;
|
||||
padding: .5rem 1rem;
|
||||
background: #efeff1;
|
||||
border-radius: .5rem;
|
||||
margin-right: 1rem;
|
||||
font-size: 1.4rem;
|
||||
line-height: 2rem;
|
||||
display: flex;
|
||||
> div{
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
max-width: 10rem;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
> .icon{
|
||||
display: none;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
> .textBox{
|
||||
display: flex;
|
||||
padding: 1.2rem 2rem;
|
||||
border-radius: 2.4rem;
|
||||
|
||||
> .text{
|
||||
// display: inline-block;
|
||||
// width: min-content;
|
||||
max-width: 100%;
|
||||
width: 100%;
|
||||
// width: min-content;
|
||||
// word-wrap: break-word;
|
||||
> .imgBox{
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
img{
|
||||
width: 10rem;
|
||||
height: 10rem;
|
||||
cursor: pointer;
|
||||
margin: .5rem;
|
||||
}
|
||||
}
|
||||
> .colorBox{
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
>.item{
|
||||
margin: .5rem;
|
||||
border-radius: 1rem;
|
||||
overflow: hidden;
|
||||
border: 1px solid;
|
||||
width: 10rem;
|
||||
> .color{
|
||||
width: 10rem;
|
||||
height: 7rem;
|
||||
}
|
||||
> .text{
|
||||
font-size: 1.4rem;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
> .icon{
|
||||
margin-right: 1.2rem;
|
||||
}
|
||||
|
||||
> i{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
animation: loading 1s linear infinite;
|
||||
@keyframes loading {
|
||||
from{
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to{
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
> .content{
|
||||
background: #f5f5f5;
|
||||
// border-radius: 2.4rem;
|
||||
> textarea{
|
||||
padding: 1.6rem 2rem 0;
|
||||
background: #f5f5f5;
|
||||
width: 100%;
|
||||
min-height: 7.2rem;
|
||||
// border-radius: 2.4rem;
|
||||
font-weight: 400;
|
||||
line-height: 2rem;
|
||||
font-size: 1.4rem;
|
||||
resize: none;
|
||||
border: none;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
> .btn{
|
||||
padding: 0 1.2rem 1.2rem;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
> .uploadBox{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
> .filList{
|
||||
display: flex;
|
||||
> .item{
|
||||
height: 3rem;
|
||||
padding: .5rem 1rem;
|
||||
background: #efeff1;
|
||||
border-radius: .5rem;
|
||||
margin-right: 1rem;
|
||||
font-size: 1.4rem;
|
||||
line-height: 2rem;
|
||||
display: flex;
|
||||
> div{
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
max-width: 10rem;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
> span{
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
i{
|
||||
font-size: 2rem;
|
||||
display: flex;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
> input{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
opacity: 0;
|
||||
cursor: pointer;
|
||||
&::-webkit-file-upload-button {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
> .sendBox{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
> .enableThinking{
|
||||
width: 10rem;
|
||||
padding: .2rem .4rem;
|
||||
text-align: center;
|
||||
font-size: 1.4rem;
|
||||
border: 1px solid #000;
|
||||
border-radius: .4rem;
|
||||
cursor: pointer;
|
||||
margin-right: 1rem;
|
||||
&.active{
|
||||
background: #000;
|
||||
color: #fff;
|
||||
|
||||
}
|
||||
}
|
||||
> .maxNum{
|
||||
font-size: 1.2rem;
|
||||
margin-right: .8rem;
|
||||
font-weight: 400;
|
||||
}
|
||||
> .send{
|
||||
opacity: .5;
|
||||
cursor: no-drop;
|
||||
&.active{
|
||||
opacity: 1;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
> .right,> .left{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
width: 3rem;
|
||||
justify-content: center;
|
||||
> i{
|
||||
display: flex;
|
||||
font-size: 2rem;
|
||||
transition: all .3s;
|
||||
}
|
||||
}
|
||||
> .right{
|
||||
border-left: 1px solid #e5e5e5;
|
||||
> i{
|
||||
transform: rotate(270deg);
|
||||
}
|
||||
}
|
||||
> .left{
|
||||
border-right: 1px solid #e5e5e5;
|
||||
> i{
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
0
src/component/home/design/childModel.vue
Normal file
0
src/component/home/design/childModel.vue
Normal file
1725
src/component/home/design/index.vue
Normal file
1725
src/component/home/design/index.vue
Normal file
File diff suppressed because it is too large
Load Diff
394
src/component/home/index.vue
Normal file
394
src/component/home/index.vue
Normal file
@@ -0,0 +1,394 @@
|
||||
<template>
|
||||
<div class="homeBox">
|
||||
<div class="mark_loading" v-show="isShowMark">
|
||||
<a-spin size="large" />
|
||||
</div>
|
||||
<div class="show">
|
||||
<router-view v-if="(openType && openType != 'history' && !routeQuery.id) || $route.path != '/home'" @setTask="setTask">
|
||||
</router-view>
|
||||
<div v-else-if="routeQuery.id || openType == 'history'" class="function">
|
||||
<design ref="design"></design>
|
||||
</div>
|
||||
<div v-else class="function">
|
||||
<newPorject ref="newPorject"></newPorject>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<chat ref="chat" @chatChange="chatChange" v-if="openType"></chat>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent,computed,ref,watch,nextTick,provide,toRefs, reactive} from 'vue'
|
||||
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
|
||||
import { Https } from "@/tool/https";
|
||||
import { useStore } from "vuex";
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useRouter,useRoute } from 'vue-router'
|
||||
import design from "./design/index.vue"
|
||||
import newPorject from "./newProject/index.vue"
|
||||
import chat from "./chat/index.vue"
|
||||
export default defineComponent({
|
||||
components:{
|
||||
design,newPorject,chat
|
||||
},
|
||||
props:{
|
||||
},
|
||||
emits:['setTask'],
|
||||
setup(props,{emit}) {
|
||||
const store = useStore();
|
||||
const route = useRoute()
|
||||
const data = reactive({
|
||||
openType:'',
|
||||
isShowMark:false,
|
||||
routeQuery:{} as any,
|
||||
selectObject:computed(()=>store.state.Workspace.probjects) as any,//选择的项目
|
||||
|
||||
})
|
||||
const setIsShowMark = (boolean:boolean)=>{
|
||||
data.isShowMark = boolean
|
||||
}
|
||||
provide('setIsShowMark',setIsShowMark)
|
||||
const dataDom = reactive({
|
||||
design:null as any,
|
||||
newPorject:null as any,
|
||||
})
|
||||
watch(() => route.query,
|
||||
(query, oldQuery) => {
|
||||
console.log(route)
|
||||
data.routeQuery = query
|
||||
const key = Object.keys(query)?.[0]
|
||||
if(key){
|
||||
data.openType = Object.keys(query)[0]
|
||||
}else{
|
||||
data.openType = ''
|
||||
}
|
||||
nextTick(()=>{
|
||||
if(query.id || query.history){
|
||||
data.isShowMark = true
|
||||
if(query.type == 'Works'){
|
||||
getWorks(query.id || query.history)
|
||||
}else{
|
||||
getHistory(query.id || query.history)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
},
|
||||
{ immediate: true } // 立即触发一次以处理初始参数
|
||||
);
|
||||
const createData = ()=>{
|
||||
store.commit("clearAllData");
|
||||
store.commit("clearAllCollection");
|
||||
store.commit("setAllBoardDataChoose",{});
|
||||
store.commit("clearShowSketchboard",{});
|
||||
store.commit("clearAllCollection");
|
||||
}
|
||||
const getWorks = (id:any)=>{
|
||||
let value:any = {
|
||||
"accountId": 0,
|
||||
"collectionId": 0,
|
||||
"coverId": 0,
|
||||
"createDate": "",
|
||||
id,
|
||||
"isDeleted": 0,
|
||||
"portfolioDes": "",
|
||||
"portfolioName": "",
|
||||
"portfolioType": "",
|
||||
"status": 0,
|
||||
"updateDate": "",
|
||||
"userLikeGroupId":''
|
||||
}
|
||||
Https.axiosPost(Https.httpUrls.setPorfolioChoose, value).then(
|
||||
(rv: any) => {
|
||||
setProjectData(rv)
|
||||
}
|
||||
).catch((res)=>{
|
||||
data.isShowMark = false
|
||||
});
|
||||
}
|
||||
const getHistory = (id:any)=>{
|
||||
let value = {
|
||||
id,
|
||||
}
|
||||
if(!id)return
|
||||
createData()
|
||||
Https.axiosPost(Https.httpUrls.selectHistoryProject,value).then((rv: any) => {
|
||||
setProjectData(rv)
|
||||
}).catch((res)=>{
|
||||
data.isShowMark = false
|
||||
})
|
||||
}
|
||||
const setTask = (item:any)=>{
|
||||
emit('setTask',item)
|
||||
}
|
||||
const setProjectData = (rv:any)=>{
|
||||
let storeData = {
|
||||
name:rv.name,
|
||||
id:rv.id,
|
||||
type:rv.type,
|
||||
httpType:rv.process,//项目类型
|
||||
ageGroup:rv.workspaceVO.ageGroup,
|
||||
style:rv.workspaceVO.style,
|
||||
styleId:rv.workspaceVO.styleId,
|
||||
styleName:rv.workspaceVO.styleName,
|
||||
sex:rv.workspaceVO.sex,
|
||||
systemDesignerPercentage:rv.workspaceVO.systemDesignerPercentage,
|
||||
position:{
|
||||
label:rv.workspaceVO.positionEnum.value,
|
||||
value:rv.workspaceVO.positionEnum.name
|
||||
},
|
||||
positionList:[],
|
||||
publishData:{
|
||||
id:rv.portfolioDTO.id?rv.portfolioDTO.id:'',
|
||||
portfolioDes:rv.portfolioDTO.portfolioDes?rv.portfolioDTO.portfolioDes:'',
|
||||
portfolioName:rv.portfolioDTO.portfolioName?rv.portfolioDTO.portfolioName:'',
|
||||
tagsDTO:rv.portfolioDTO.tagsDTO?rv.portfolioDTO.tagsDTO:[],
|
||||
},
|
||||
model:{}
|
||||
}
|
||||
let model:any = {}
|
||||
let position = []
|
||||
if(storeData.sex == "Female"){
|
||||
model = {
|
||||
id:rv.workspaceVO.mannequinFemaleId,
|
||||
type:rv.workspaceVO.mannequinFemaleType,
|
||||
url:rv.workspaceVO.femalePresignedUrl,
|
||||
}
|
||||
position = store.state.UserHabit.FemalePosition
|
||||
}else{
|
||||
model = {
|
||||
id:rv.workspaceVO.mannequinMaleId,
|
||||
type:rv.workspaceVO.mannequinMaleType,
|
||||
url:rv.workspaceVO.malePresignedUrl,
|
||||
}
|
||||
position = store.state.UserHabit.MalePosition
|
||||
}
|
||||
storeData.model = model
|
||||
data.selectObject.positionList = position
|
||||
storeData.positionList = position
|
||||
store.commit('setProbject',storeData)
|
||||
// let list:any = projectList
|
||||
// store.commit('setProjectList',list[type.value])
|
||||
// nextTick(()=>{
|
||||
// dataDom.workflow.isUpdataPorject = true
|
||||
// })
|
||||
|
||||
getCollection()
|
||||
}
|
||||
// const setitemData = (arr:any)=>{
|
||||
// return new Promise((resolve,reject)=>{
|
||||
// nextTick(()=>{
|
||||
// arr.forEach((rv:any)=>{
|
||||
// if(arr.indexOf(rv) > -1 || !dataDom[rv])return
|
||||
// dataDom[rv].openSetData()
|
||||
// })
|
||||
// resolve('')
|
||||
// })
|
||||
// })
|
||||
// }
|
||||
const getCollection = ()=>{
|
||||
let value:any = {
|
||||
"id":data.selectObject.id,
|
||||
"moduleList":["moodBoard", "printBoard", "colorBoard", "sketchBoard",'design','toProduct','relight','poseTransfer','mannequin']
|
||||
}
|
||||
Https.axiosPost(Https.httpUrls.getModuleContent,value).then(async (rv)=>{
|
||||
historyChooseData(rv)//设置历史数据
|
||||
let allBoardData = ['sketchBoard','moodBoard','printBoard','colorBoard']
|
||||
// let allBoardData = ['sketchBoard','moodBoard','printBoard','colorBoard','toProduct','relight','poseTransfer','mannequin']
|
||||
let canvasData = ['canvas']
|
||||
for (let index = 0; index < canvasData.length; index++) {
|
||||
const item = canvasData[index];
|
||||
await getCanvasData(item)
|
||||
}
|
||||
// await setitemData(allBoardData)
|
||||
//还有一个canvas
|
||||
if(rv.boundingBox)store.commit('setShowSketchboard',rv.boundingBox)
|
||||
allBoardData.forEach((item)=>{
|
||||
let value = {
|
||||
type:item,
|
||||
objectName:data.selectObject.type,
|
||||
}
|
||||
let arr = ['sketchBoard','moodBoard','printBoard','colorBoard']
|
||||
if(arr.indexOf(item) != -1){
|
||||
// store.dispatch('setAllBoardData',value)
|
||||
}else{
|
||||
store.dispatch('setModularData',value)
|
||||
}
|
||||
})
|
||||
data.isShowMark = false
|
||||
dataDom.design.openSetData()
|
||||
})
|
||||
}
|
||||
const getCanvasData = (str:any)=>{
|
||||
return new Promise((resolve, reject) => {
|
||||
let value = {
|
||||
module:str,
|
||||
projectId:data.selectObject.id,
|
||||
}
|
||||
Https.axiosPost(Https.httpUrls.exportSearch, value)
|
||||
.then((rv) => {
|
||||
store.commit("setCanvasData", {type:str,file:rv});
|
||||
resolve('')
|
||||
})
|
||||
.catch((rv) => {
|
||||
resolve(null)
|
||||
});
|
||||
})
|
||||
}
|
||||
const historyChooseData = (dataValue:any)=>{
|
||||
let collectionData = {
|
||||
disposeMoodboard: dataValue.moodBoard?.moodTemplateId?[{
|
||||
id:dataValue.moodBoard.moodTemplateId,
|
||||
imgUrl:dataValue.moodBoard.moodTemplateUrl,
|
||||
resData:{
|
||||
name:dataValue.moodBoard.moodTemplateName,
|
||||
}
|
||||
}]:[],
|
||||
moodboardPosition:dataValue.moodBoard?.moodboardPosition?JSON.parse(dataValue.moodBoard.moodboardPosition):{},
|
||||
moodboardFiles: dealViewChooseData(
|
||||
dataValue.moodBoard?.moodBoards,"Moodboard"
|
||||
),
|
||||
printboardFiles: dealViewChooseData(
|
||||
dataValue.printBoard,"Printboard"
|
||||
),
|
||||
generatePrintFiles: [],
|
||||
colorBoards: dealViewChooseColor(
|
||||
dataValue.colorBoard
|
||||
),
|
||||
sketchboardFiles: dealViewChooseData(
|
||||
dataValue.sketchBoard,"Sketchboard"
|
||||
),
|
||||
};
|
||||
if(dataValue.moodBoard?.moodTemplateId)store.commit("setMoodTemplateId", dataValue.moodBoard.moodTemplateId);
|
||||
store.commit("setAllBoardDataChoose", collectionData);
|
||||
store.commit("setShowSketchboard", dataValue.sketchBoards);
|
||||
let likeDesignCollectionList:any = []
|
||||
if(dataValue.design?.userLikeDetails){
|
||||
dataValue.design?.userLikeDetails.map(
|
||||
(v: any) => {
|
||||
let dataValue = {
|
||||
...v,
|
||||
groupDetailId: v.id,
|
||||
designItemUrl: v.designOutfitUrl,
|
||||
designItemId: v.designItemId,
|
||||
};
|
||||
return dataValue;
|
||||
}
|
||||
);
|
||||
}
|
||||
if(dataValue.design.userLikeDetails)store.commit("setLikeDesignCollectionList",dataValue.design.userLikeDetails);
|
||||
store.commit("setUserGroupId", dataValue.design.userGroupId);
|
||||
if(dataValue.toProduct){
|
||||
let value = {
|
||||
list: dataValue.toProduct,
|
||||
str:'add',
|
||||
index:-1,
|
||||
}
|
||||
store.commit("setToProductImage", value);
|
||||
}
|
||||
if(dataValue.relight){
|
||||
let value = {
|
||||
list: dataValue.relight,
|
||||
str:'add',
|
||||
index:-1,
|
||||
}
|
||||
store.commit("setRelightList", value);
|
||||
}
|
||||
if(dataValue.poseTransfer){
|
||||
let value = {
|
||||
list: dataValue.poseTransfer,
|
||||
str:'add',
|
||||
index:-1,
|
||||
}
|
||||
store.commit("setPoseTransfer", value);
|
||||
}
|
||||
}
|
||||
//统一处理选择组的渲染数据
|
||||
const dealViewChooseData = (dataValue: any,str:string)=> {
|
||||
if (!dataValue) {
|
||||
return [];
|
||||
}
|
||||
let filesList = dataValue.map((v: any) => {
|
||||
let newData: any = {
|
||||
imgUrl: v.url?v.url:v.designOutfitUrl,
|
||||
id: v.id,
|
||||
status: "done",
|
||||
resData: v,
|
||||
type_:{
|
||||
type1:'material',
|
||||
type2:v.level1Type
|
||||
}
|
||||
};
|
||||
if (v.level1Type === "Sketchboard") {
|
||||
newData.pin = v.isPin;
|
||||
newData.categoryValue = v.level2Type;
|
||||
newData.level2Type = v.level2Type;
|
||||
}
|
||||
if (v.level1Type === "Printboard") {
|
||||
newData.pin = v.isPin;
|
||||
newData.level2Type = v.level2Type;
|
||||
newData.categoryValue = v.level2Type;
|
||||
}
|
||||
return newData;
|
||||
});
|
||||
return filesList;
|
||||
}
|
||||
//统一处理选择组的渲染数据
|
||||
const dealViewChooseColor = (dataValue: any)=>{
|
||||
let colorList = dataValue.map((v: any) => {
|
||||
let rgbValue = v.rgbValue.split(" ");
|
||||
let newData: any = {
|
||||
id: v.id,
|
||||
name: v.name,
|
||||
tcx: v.tcx || "",
|
||||
rgbValue: {
|
||||
r: rgbValue[0],
|
||||
g: rgbValue[1],
|
||||
b: rgbValue[2],
|
||||
a: 1,
|
||||
},
|
||||
};
|
||||
if(v.gradient){
|
||||
newData.gradient = v.gradient;
|
||||
}else{
|
||||
delete newData.gradient;
|
||||
}
|
||||
return newData;
|
||||
});
|
||||
return colorList;
|
||||
}
|
||||
const chatChange = (value:any)=>{
|
||||
console.log(value)
|
||||
if(value.type == '[DESIGN_SIGNAL]' && dataDom.design){
|
||||
dataDom.design.designNewCollection()
|
||||
}else{
|
||||
getCollection()
|
||||
}
|
||||
}
|
||||
return{
|
||||
...toRefs(dataDom),
|
||||
...toRefs(data),
|
||||
setTask,
|
||||
chatChange,
|
||||
}
|
||||
},
|
||||
provide() {
|
||||
return {
|
||||
}
|
||||
},
|
||||
})
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.homeBox{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
> .show{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
> .function{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
415
src/component/home/newProject/index.vue
Normal file
415
src/component/home/newProject/index.vue
Normal file
@@ -0,0 +1,415 @@
|
||||
<template>
|
||||
<div class="newProject">
|
||||
<div class="contentBox">
|
||||
<div class="content">
|
||||
<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>
|
||||
<div class="describe">
|
||||
<p v-for="item in selectFlow.describe">{{ item }}</p>
|
||||
</div>
|
||||
</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>
|
||||
</div>
|
||||
<div class="chatBox" v-show="chatOrSetting == 'chat'">
|
||||
<textarea ref="textarea" @input="inputText($event)" placeholder="Write your message"></textarea>
|
||||
<div class="btn">
|
||||
<div class="uploadBox">
|
||||
<div class="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>
|
||||
</div>
|
||||
</div>
|
||||
<i class="fi fi-br-upload">
|
||||
<input type="file" @change="handleFileUpload($event)">
|
||||
</i>
|
||||
</div>
|
||||
<div class="sendBox">
|
||||
<div class="maxNum">{{ chatContent.length }}/10000</div>
|
||||
<div class="send" @click="sendChat">
|
||||
<i class="fi fi-ss-paper-plane-top"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-show="chatOrSetting != 'chat'">
|
||||
<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>
|
||||
{{ text }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="mark_loading" v-show="loadingShow">
|
||||
<a-spin size="large" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent,computed,ref,provide,nextTick,createVNode,toRefs, reactive} 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'
|
||||
export default defineComponent({
|
||||
components:{
|
||||
workspace,
|
||||
},
|
||||
props:{
|
||||
},
|
||||
emits:[],
|
||||
setup(props,{emit}) {
|
||||
const store = useStore();
|
||||
const data = reactive({
|
||||
flowList:[
|
||||
{
|
||||
title:'Series Design',
|
||||
value:'SERIES_DESIGN',
|
||||
describe:[
|
||||
'12312312',
|
||||
'12312312',
|
||||
]
|
||||
},
|
||||
{
|
||||
title:'Single Design',
|
||||
value:'SINGLE_DESIGN',
|
||||
describe:[
|
||||
'12312312',
|
||||
'12312312',
|
||||
]
|
||||
},
|
||||
],
|
||||
selectFlow:{
|
||||
title:'Series Design',
|
||||
value:'SERIES_DESIGN',
|
||||
describe:[
|
||||
'12312312',
|
||||
'12312312',
|
||||
]
|
||||
},
|
||||
chatContent:'',
|
||||
hintList:[
|
||||
'描述1',
|
||||
'描述3',
|
||||
'描述2',
|
||||
],
|
||||
uploadFile:null as any,
|
||||
loadingShow:false,
|
||||
text:'',
|
||||
filList:[] as any,
|
||||
textarea:null as any,
|
||||
chatOrSetting:'chat',
|
||||
})
|
||||
const dataDom = reactive({
|
||||
})
|
||||
const setFlow = (item:any)=>{
|
||||
data.selectFlow = item
|
||||
}
|
||||
|
||||
const inputText = (e:any)=>{
|
||||
if(e.target.value.length <= 1000){
|
||||
data.chatContent = e.target.value
|
||||
}else{
|
||||
e.target.value = data.chatContent
|
||||
}
|
||||
e.target.style.height = `${e.target.scrollHeight}px`;
|
||||
}
|
||||
const addChatContent = (item:any)=>{
|
||||
if((data.textarea.value += item.length) > 10000)return
|
||||
data.chatContent += item
|
||||
data.textarea.value += item
|
||||
}
|
||||
const sendChat = ()=>{
|
||||
if(!data.chatContent)return
|
||||
data.loadingShow = true
|
||||
Https.axiosGet(Https.httpUrls.chatCreateProject, {params:{prompt:data.chatContent,process:data.selectFlow.value}}).then((rv)=>{
|
||||
if(rv){
|
||||
data.loadingShow = false
|
||||
router.push(`home?history=${rv}`)
|
||||
}
|
||||
}).catch(()=>{
|
||||
data.loadingShow = false
|
||||
})
|
||||
|
||||
// const eventSource = new EventSource(`http://192.168.1.3:5567${Https.httpUrls.chatCreateProject}?prompt=${data.chatContent}&token=${getCookie('token')}`,{
|
||||
// });
|
||||
// eventSource.onmessage = function(event) {
|
||||
|
||||
// data.text+=event.data
|
||||
// console.log('收到数据:', event.data);
|
||||
// };
|
||||
// eventSource.onerror = function(error) {
|
||||
// console.log(EventSource.CLOSED,EventSource)
|
||||
// console.log(eventSource.readyState )
|
||||
// if (eventSource.readyState === EventSource.CLOSED) {
|
||||
// console.log('连接已正常关闭');
|
||||
// } else {
|
||||
// console.error('错误:', error);
|
||||
// // 处理错误重连逻辑
|
||||
// }
|
||||
// eventSource.close()
|
||||
// };
|
||||
}
|
||||
const handleFileUpload = (event:any)=>{
|
||||
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/')
|
||||
if(type){
|
||||
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
|
||||
}
|
||||
}
|
||||
data.loadingShow = true
|
||||
const formData = new FormData();
|
||||
formData.append('file', event.target.files[0]);
|
||||
let config:any = {
|
||||
headers:{'Content-Type':'multipart/form-data','Accept':'*/*' },
|
||||
params:formData,
|
||||
}
|
||||
Https.axiosPost(Https.httpUrls.llmUploadFile,formData,config)
|
||||
.then((rv: any) => {
|
||||
rv.name = event.target.files[0].name
|
||||
rv.type = type?'image':'file'
|
||||
data.filList.push(rv)
|
||||
data.loadingShow = false
|
||||
}
|
||||
).catch(rv=>{
|
||||
data.loadingShow = false
|
||||
})
|
||||
}
|
||||
const deleteFile = (item:any,index:number)=>{
|
||||
data.filList.splice(index,1)
|
||||
}
|
||||
const setChatOrSetting = (str:any)=>{
|
||||
data.chatOrSetting = str
|
||||
}
|
||||
const setProject = (item:any)=>{
|
||||
router.push(`home?history=${item.id}`)
|
||||
}
|
||||
return{
|
||||
...toRefs(dataDom),
|
||||
...toRefs(data),
|
||||
setFlow,
|
||||
inputText,
|
||||
addChatContent,
|
||||
sendChat,
|
||||
handleFileUpload,
|
||||
deleteFile,
|
||||
setChatOrSetting,
|
||||
setProject,
|
||||
}
|
||||
},
|
||||
provide() {
|
||||
return {
|
||||
}
|
||||
},
|
||||
})
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.newProject{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
> .contentBox{
|
||||
width: 100%;
|
||||
height: calc(100% - 7.8rem);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
> .content{
|
||||
// background: red;
|
||||
width: 88rem;
|
||||
// height: 100%;
|
||||
> .title{
|
||||
font-size: 2rem;
|
||||
font-weight: 600;
|
||||
text-align: center;
|
||||
}
|
||||
> .selectFlow{
|
||||
margin-top: 4.8rem;
|
||||
width: 100%;
|
||||
border-radius: 2.4rem;
|
||||
border: 1px solid #0000001a;
|
||||
padding: 1.2rem;
|
||||
> .select{
|
||||
border: 1px solid #0000001a;
|
||||
border-radius: 2.4rem;
|
||||
display: flex;
|
||||
padding: .2rem;
|
||||
border-radius: 2rem;
|
||||
> div{
|
||||
white-space: nowrap;
|
||||
justify-content: space-between;
|
||||
border-radius: 2.2rem;
|
||||
font-size: 1.6rem;
|
||||
padding: .6rem .8rem;
|
||||
min-width: 25%;
|
||||
text-align: center;
|
||||
font-weight: 600;
|
||||
color: #71717a;
|
||||
cursor: pointer;
|
||||
&.active{
|
||||
background: #efeff1;
|
||||
color: #3f3f46;
|
||||
}
|
||||
}
|
||||
}
|
||||
> .describe{
|
||||
margin-top: 1.6rem;
|
||||
margin-left: .8rem;
|
||||
> p{
|
||||
margin: 0;
|
||||
color: #71717a;
|
||||
font-weight: 400;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
> .chatOrSetting{
|
||||
margin-top: 2.4rem;
|
||||
width: min-content;
|
||||
margin-left: auto;
|
||||
> .select{
|
||||
border: 1px solid #0000001a;
|
||||
border-radius: 2.4rem;
|
||||
display: flex;
|
||||
padding: .2rem;
|
||||
border-radius: 2rem;
|
||||
> div{
|
||||
white-space: nowrap;
|
||||
justify-content: space-between;
|
||||
border-radius: 2.2rem;
|
||||
font-size: 1.6rem;
|
||||
padding: .6rem .8rem;
|
||||
min-width: 10rem;
|
||||
text-align: center;
|
||||
font-weight: 600;
|
||||
color: #71717a;
|
||||
cursor: pointer;
|
||||
&.active{
|
||||
background: #efeff1;
|
||||
color: #3f3f46;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
> .chatBox{
|
||||
margin-top: .4rem;
|
||||
border-radius: 2.4rem;
|
||||
position: relative;
|
||||
background: #f5f5f5;
|
||||
> textarea{
|
||||
padding: 1.6rem 2rem 0;
|
||||
background: #f5f5f5;
|
||||
width: 100%;
|
||||
min-height: 7.2rem;
|
||||
border-radius: 2.4rem;
|
||||
font-weight: 400;
|
||||
line-height: 2rem;
|
||||
font-size: 1.4rem;
|
||||
resize: none;
|
||||
border: none;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
> .btn{
|
||||
padding: 0 1.2rem 1.2rem;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
> .uploadBox{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
> .filList{
|
||||
display: flex;
|
||||
> .item{
|
||||
height: 3rem;
|
||||
padding: .5rem 1rem;
|
||||
background: #efeff1;
|
||||
border-radius: .5rem;
|
||||
margin-right: 1rem;
|
||||
font-size: 1.4rem;
|
||||
line-height: 2rem;
|
||||
display: flex;
|
||||
> div{
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
max-width: 10rem;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
> span{
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
i{
|
||||
font-size: 2rem;
|
||||
display: flex;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
> input{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
opacity: 0;
|
||||
cursor: pointer;
|
||||
&::-webkit-file-upload-button {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
> .sendBox{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
> .maxNum{
|
||||
font-size: 1.2rem;
|
||||
margin-right: .8rem;
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
> .hint{
|
||||
display: flex;
|
||||
margin-top: 2.4rem;
|
||||
> div{
|
||||
background: #efeff1;
|
||||
width: 25rem;
|
||||
height: 4.8rem;
|
||||
margin-right: 1.2rem;
|
||||
border-radius: 1.6rem;
|
||||
cursor: pointer;
|
||||
padding: 1.2rem;
|
||||
&:hover{
|
||||
background: #f5f5f5;
|
||||
}
|
||||
:first-child{
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
376
src/component/home/newProject/workspace.vue
Normal file
376
src/component/home/newProject/workspace.vue
Normal file
@@ -0,0 +1,376 @@
|
||||
<template>
|
||||
<div class="workspace">
|
||||
<div class="workspaceBox">
|
||||
<div class="projectName marginBottom" v-if="show.title">
|
||||
<div class="text">Project name: <span style="color: red;">*</span></div>
|
||||
<div class="input">
|
||||
<input type="text" v-model="selectObject.name">
|
||||
</div>
|
||||
</div>
|
||||
<div class="gender marginBottom" v-if="show.age">
|
||||
<div class="text">Role</div>
|
||||
<div class="radio">
|
||||
<label>
|
||||
<input type="radio" name="ageGroup" v-model="selectObject.ageGroup" value="Adult">
|
||||
<span>Adult</span>
|
||||
</label>
|
||||
<label>
|
||||
<input type="radio" name="ageGroup" v-model="selectObject.ageGroup" value="Child">
|
||||
<span>Child</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="gender marginBottom">
|
||||
<div class="text">Gender:</div>
|
||||
<div class="radio">
|
||||
<label>
|
||||
<input type="radio" name="gender" v-model="selectObject.sex" value="Female">
|
||||
<span>Female</span>
|
||||
</label>
|
||||
<label>
|
||||
<input type="radio" name="gender" v-model="selectObject.sex" value="Male">
|
||||
<span>Male</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="style marginBottom" v-if="show.style">
|
||||
<div class="text">Style:</div>
|
||||
<div class="text">{{ selectObject?.styleName?selectObject?.styleName:'All' }}</div>
|
||||
<div class="gallery_btn" style="line-height: 5rem;" @click="setStyle">{{ $t('Habit.Select') }}</div>
|
||||
</div>
|
||||
<div class="systemDesigner marginBottom" v-if="show.systemDesigner">
|
||||
<a-slider class="system_silder"
|
||||
v-model:value="selectObject.systemDesignerPercentage"
|
||||
:tip-formatter="formatter"
|
||||
:tooltipVisible="false"
|
||||
>
|
||||
</a-slider>
|
||||
<div class="text">
|
||||
<div class="left">
|
||||
{{ $t('Habit.System') }}<span>({{systemDesigner.designer}}%)</span>
|
||||
</div>
|
||||
<div class="right">
|
||||
|
||||
{{ $t('Habit.Designer') }}<span>({{systemDesigner.system}}%)</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="position marginBottom" style="display: flex; align-items: center;justify-content: space-between;" v-show="show.position">
|
||||
<div class="text">
|
||||
Category:
|
||||
</div>
|
||||
<generalMenu style="width:80%" :selectWidth="'100%'" :dataList="selectObject.positionList" @setprintModel="setprintModel" :item="selectObject.position"></generalMenu>
|
||||
</div>
|
||||
<div class="complete">
|
||||
<div class="gallery_btn" @click="complete">Complete</div>
|
||||
</div>
|
||||
</div>
|
||||
<habitSetStyle ref="habitSetStyle" @setWorkspaceStyle="setWorkspaceStyle" :mannequinStyle="mannequinStyle"></habitSetStyle>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent,computed,watch,nextTick,onBeforeUnmount,toRefs, reactive, onMounted, inject} from 'vue'
|
||||
// import setDesignItem from '@/component/Detail/setDesignItem2.vue'
|
||||
import { useStore } from "vuex";
|
||||
import { useI18n } from 'vue-i18n'
|
||||
// import workspace from './model/workspace.vue'
|
||||
import router from '@/router';
|
||||
import habitSetStyle from "@/component/Detail/habitSetStyle.vue";
|
||||
import generalMenu from "@/component/HomePage/generalMenu.vue";
|
||||
import { Https } from '@/tool/https';
|
||||
import { position } from 'html2canvas/dist/types/css/property-descriptors/position';
|
||||
import { id } from 'element-plus/es/locale';
|
||||
import { message } from 'ant-design-vue';
|
||||
import {projectList} from '@/tool/listData'
|
||||
export default defineComponent({
|
||||
components:{
|
||||
habitSetStyle,generalMenu
|
||||
},
|
||||
props:{
|
||||
workflowType:{
|
||||
type:String,
|
||||
default:''
|
||||
},
|
||||
httpWorkflowType:{
|
||||
type:String,
|
||||
default:''
|
||||
},
|
||||
workflowTitle:{
|
||||
type:String,
|
||||
default:''
|
||||
},
|
||||
firstTime:{
|
||||
type:Boolean,
|
||||
default:false
|
||||
}
|
||||
},
|
||||
emits:['setProject'],
|
||||
setup(props,{emit}) {
|
||||
const { t } = useI18n();
|
||||
const store = useStore();
|
||||
const data = reactive({
|
||||
selectObject_:computed(()=>store.state.Workspace.probjects),//选择的项目
|
||||
selectObject:{} as any,
|
||||
femalePosition:computed(()=>store.state.UserHabit.FemalePosition),//男性衣服位置
|
||||
malePosition:computed(()=>store.state.UserHabit.MalePosition),//女性衣服位置
|
||||
mannequinStyle:computed(()=>store.state.UserHabit.mannequinStyle),//
|
||||
show:{
|
||||
title:true,
|
||||
gender:true,
|
||||
style:true,
|
||||
age:true,
|
||||
systemDesigner:true,
|
||||
position:true,
|
||||
},
|
||||
systemDesigner:{
|
||||
system:0,
|
||||
designer:0,
|
||||
},
|
||||
setIsShowMark:inject('setIsShowMark') as any,
|
||||
})
|
||||
watch(()=>data.selectObject_,(newVal)=>{
|
||||
data.selectObject = JSON.parse(JSON.stringify(newVal))
|
||||
})
|
||||
const dataDom = reactive({
|
||||
habitSetStyle:null as any,
|
||||
})
|
||||
const setStyle = ()=>{
|
||||
dataDom.habitSetStyle.init(data.selectObject);
|
||||
}
|
||||
const setWorkspaceStyle = (value:any)=>{
|
||||
data.selectObject.styleName = value.name
|
||||
data.selectObject.style = value.value
|
||||
data.selectObject.styleId = value.id
|
||||
// store.commit('setProbject',data)
|
||||
}
|
||||
const setprintModel = (value:any)=>{
|
||||
data.selectObject.position = value
|
||||
}
|
||||
const formatter = (value: number)=>{
|
||||
data.systemDesigner.system = 100 - value
|
||||
data.systemDesigner.designer = value
|
||||
let num = Math.abs((value-50)*2)
|
||||
return `${num}%`;
|
||||
}
|
||||
const complete = ()=>{
|
||||
if(!data.selectObject.name){
|
||||
message.info(t('PrintboardUpload.jsContent7'))
|
||||
return
|
||||
}
|
||||
let value = {
|
||||
name:data.selectObject.name,
|
||||
process:props.httpWorkflowType,
|
||||
styleId:data.show.style?data.selectObject.styleId:null,
|
||||
id:data.selectObject.id,
|
||||
workspace:{
|
||||
sex:data.selectObject.sex,
|
||||
// sex:data.show.gender?data.selectObject.sex:null,
|
||||
systemDesignerPercentage:data.show.systemDesigner?data.selectObject.systemDesignerPercentage:null,
|
||||
position:data.show.position?data.selectObject.position.value:'Overall',
|
||||
ageGroup:data.show.style?data.selectObject.ageGroup:null,
|
||||
// position:data.selectObject,
|
||||
} as any,
|
||||
|
||||
}
|
||||
Https.axiosPost(Https.httpUrls.saveOrUpdate,value).then((rv)=>{
|
||||
if(rv){
|
||||
data.selectObject.id = rv.id
|
||||
let model:any = {}
|
||||
let position = []
|
||||
if(data.selectObject.sex == "Female"){
|
||||
// if(rv.workspaceVO.sex == "Female"){
|
||||
model = {
|
||||
id:rv.workspaceVO.mannequinFemaleId,
|
||||
type:rv.workspaceVO.mannequinFemaleType,
|
||||
url:rv.workspaceVO.femalePresignedUrl,
|
||||
}
|
||||
position = store.state.UserHabit.FemalePosition
|
||||
}else{
|
||||
model = {
|
||||
id:rv.workspaceVO.mannequinMaleId,
|
||||
type:rv.workspaceVO.mannequinMaleType,
|
||||
url:rv.workspaceVO.malePresignedUrl,
|
||||
}
|
||||
position = store.state.UserHabit.MalePosition
|
||||
}
|
||||
// model.url = rv.workspaceVO.malePresignedUrl
|
||||
data.selectObject.model = model
|
||||
data.selectObject.positionList = position
|
||||
// store.commit('setProbject',data.selectObject)
|
||||
emit('setProject',data.selectObject)
|
||||
}
|
||||
})
|
||||
}
|
||||
const openSetData = ()=>{
|
||||
|
||||
}
|
||||
onMounted(()=>{
|
||||
data.selectObject = JSON.parse(JSON.stringify(data.selectObject_))
|
||||
// data.show.gender = (props.workflowType == 'seriesDesign' || props.workflowType == 'singleProductDesign' || props.workflowType == 'printingDesign3D')
|
||||
// data.show.style = (props.workflowType == 'seriesDesign' || props.workflowType == 'singleProductDesign')
|
||||
// data.show.age = (props.workflowType == 'seriesDesign' || props.workflowType == 'singleProductDesign' || props.workflowType == 'sketchDesign')
|
||||
// data.show.systemDesigner = (props.workflowType == 'seriesDesign' || props.workflowType == 'singleProductDesign')
|
||||
// data.show.position = (props.workflowType == 'singleProductDesign')
|
||||
|
||||
if(!data.mannequinStyle){
|
||||
data.setIsShowMark(true)
|
||||
Https.axiosPost(Https.httpUrls.getStyleList, {}).then(
|
||||
(rv) => {
|
||||
data.setIsShowMark(false)
|
||||
rv.forEach((item:any) => {
|
||||
let name = item.value
|
||||
item.value = item.name
|
||||
item.name = name
|
||||
});
|
||||
data.selectObject.style = rv[0].value
|
||||
data.selectObject.styleName = rv[0].name
|
||||
data.selectObject.styleId = rv[0].id
|
||||
store.commit('setMannequinStyle',rv)
|
||||
}
|
||||
).catch(res=>{
|
||||
data.setIsShowMark(false)
|
||||
});
|
||||
}
|
||||
})
|
||||
watch(()=>data.selectObject.sex,(newVal)=>{
|
||||
if(newVal == 'Male'){
|
||||
data.selectObject.positionList = data.malePosition
|
||||
}else{
|
||||
data.selectObject.positionList = data.femalePosition
|
||||
}
|
||||
data.selectObject.position = data.selectObject.positionList[0]
|
||||
})
|
||||
return{
|
||||
projectList,
|
||||
...toRefs(dataDom),
|
||||
...toRefs(data),
|
||||
setStyle,
|
||||
setWorkspaceStyle,
|
||||
setprintModel,
|
||||
formatter,
|
||||
complete,
|
||||
openSetData,
|
||||
}
|
||||
},
|
||||
|
||||
provide() {
|
||||
return {
|
||||
}
|
||||
},
|
||||
|
||||
})
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.workspace{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-weight: 600;
|
||||
font-size: 1.8rem;
|
||||
border: 1px solid #0000001a;
|
||||
padding: 1.2rem;
|
||||
border-radius: 2.4rem;
|
||||
> .workspaceBox{
|
||||
width: 55rem;
|
||||
padding: 0 5rem;
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
// display: flex;
|
||||
// flex-wrap: wrap;
|
||||
// justify-content: space-between;
|
||||
// align-content: flex-start;
|
||||
> .marginBottom{
|
||||
margin-bottom: 3rem;
|
||||
// width: 44%;
|
||||
}
|
||||
> .title{
|
||||
font-size: 2.7rem;
|
||||
> span{
|
||||
color: #999999;
|
||||
font-size: 1.4rem;
|
||||
}
|
||||
}
|
||||
> .projectName{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
> .text{
|
||||
margin-right: 1rem;
|
||||
}
|
||||
> .input{
|
||||
// flex: 1;
|
||||
width: 80%;
|
||||
padding: 1rem 2rem;
|
||||
// padding: 2rem 2.7rem;
|
||||
font-size: 1.6rem;
|
||||
border-radius: 1.6rem;
|
||||
border: 2px solid #D0D0D0;
|
||||
display: flex;
|
||||
> input{
|
||||
flex: 1;
|
||||
border: none;
|
||||
}
|
||||
> i{
|
||||
display: flex;
|
||||
color: #999999;
|
||||
align-items: center;
|
||||
font-size: 2.4rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
> .gender{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
> .text{
|
||||
width: 8rem;
|
||||
}
|
||||
> .radio{
|
||||
display: flex;
|
||||
margin-left: 4.5rem;
|
||||
> label{
|
||||
display: flex;
|
||||
margin-right: 4rem;
|
||||
>input{
|
||||
margin-right: 1.5rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
> .style{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
> .systemDesigner{
|
||||
> .text{
|
||||
margin-right: 1rem;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
||||
> .position{
|
||||
> .text{
|
||||
margin-right: 1rem;
|
||||
}
|
||||
:deep(.generalMenu_printModel){
|
||||
position: relative;
|
||||
margin: 0;
|
||||
> div,> ul{
|
||||
width: 100%;
|
||||
border-radius: 1.6rem;
|
||||
border: 2px solid #D0D0D0;
|
||||
}
|
||||
}
|
||||
}
|
||||
> .complete{
|
||||
width: 100%;
|
||||
text-align: right;
|
||||
> div{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user