2025-05-20 16:47:27 +08:00
|
|
|
<template>
|
|
|
|
|
<div class="chat" :class="{active:!openChat}" @click.stop="">
|
2025-05-21 20:05:08 +08:00
|
|
|
<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}">
|
2025-05-20 16:47:27 +08:00
|
|
|
<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">
|
2025-06-03 14:57:18 +08:00
|
|
|
<div class="icon">
|
|
|
|
|
<img src="@/assets/images/icon/favicon.png" alt="">
|
|
|
|
|
</div>
|
2025-05-21 20:05:08 +08:00
|
|
|
<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>已深度思考</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="txt">{{item.content.message}}</div>
|
|
|
|
|
</span>
|
2025-05-20 16:47:27 +08:00
|
|
|
<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>
|
2025-05-21 20:05:08 +08:00
|
|
|
<i class="fi fi-br-loading" v-if="!item.content.think && !item.content.message && !item.content.img && !item.content.color"></i>
|
2025-05-20 16:47:27 +08:00
|
|
|
</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>
|
2025-05-21 20:05:08 +08:00
|
|
|
<i class="fi fi-rs-paperclip-vertical">
|
2025-05-20 16:47:27 +08:00
|
|
|
<input type="file" @change="handleFileUpload($event)">
|
|
|
|
|
</i>
|
2025-05-28 10:28:07 +08:00
|
|
|
<div class="enableThinking" :class="{active:enableThinking}" @click="()=>enableThinking = !enableThinking">Deep Thinking</div>
|
2025-05-20 16:47:27 +08:00
|
|
|
</div>
|
|
|
|
|
<div class="sendBox">
|
2025-05-22 14:26:47 +08:00
|
|
|
<div class="maxNum">{{ chatContent?.length }}/10000</div>
|
|
|
|
|
<div class="send" :class="{active:chatContent?.length>0}" @click="sendChat">
|
2025-05-20 16:47:27 +08:00
|
|
|
<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)=>{
|
2025-06-03 14:57:18 +08:00
|
|
|
if(newValue && (data.selectObject.httpType == 'SERIES_DESIGN' || data.selectObject.httpType == 'SINGLE_DESIGN')){
|
2025-05-20 16:47:27 +08:00
|
|
|
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
|
2025-05-22 14:26:47 +08:00
|
|
|
let fileList
|
|
|
|
|
if(data.filList){
|
|
|
|
|
fileList = JSON.parse(JSON.stringify(data.filList))
|
|
|
|
|
}else{
|
|
|
|
|
fileList = []
|
|
|
|
|
}
|
2025-05-20 16:47:27 +08:00
|
|
|
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(',') : ''
|
2025-05-21 20:05:08 +08:00
|
|
|
data.chatList.push({content:{message:data.chatContent,think:''},role:'user',fileList:fileList})
|
|
|
|
|
data.chatList.push({content:{message:'',think:''},role:'system'})
|
2025-05-20 16:47:27 +08:00
|
|
|
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
|
2025-06-09 10:25:54 +08:00
|
|
|
console.log('收到数据:', JSON.parse(event.data));
|
2025-05-20 16:47:27 +08:00
|
|
|
// 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;
|
|
|
|
|
|
2025-06-09 10:25:54 +08:00
|
|
|
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 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'
|
|
|
|
|
}else{
|
|
|
|
|
data.chatList[data.chatList.length-1].content.img = JSON.parse(JSON.parse(event.data).content).receiveCollectionElementList
|
|
|
|
|
getData = eventData.tools_name
|
|
|
|
|
}
|
2025-05-20 16:47:27 +08:00
|
|
|
data.chatList.push({content:{message:''},role:'system'})
|
2025-06-09 10:25:54 +08:00
|
|
|
}else{
|
|
|
|
|
|
2025-05-20 16:47:27 +08:00
|
|
|
}
|
2025-06-09 10:25:54 +08:00
|
|
|
emit('chatChange',{type:eventData.type,module:getData})
|
|
|
|
|
|
2025-05-20 16:47:27 +08:00
|
|
|
}
|
2025-06-09 10:25:54 +08:00
|
|
|
//emit('chatChange',{type:JSON.parse(event.data).status})
|
2025-05-20 16:47:27 +08:00
|
|
|
};
|
|
|
|
|
eventSource.onerror = function(error) {
|
|
|
|
|
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
|
2025-05-21 20:05:08 +08:00
|
|
|
if(rv.content[rv.content.length - index -1].isImage == 2){
|
2025-05-20 16:47:27 +08:00
|
|
|
rv.content[rv.content.length - index -1].content={
|
|
|
|
|
img : JSON.parse(rv.content[rv.content.length - index -1].content)
|
|
|
|
|
}
|
2025-05-21 20:05:08 +08:00
|
|
|
}else if(rv.content[rv.content.length - index -1].isImage==1){
|
2025-05-20 16:47:27 +08:00
|
|
|
rv.content[rv.content.length - index -1].content={
|
|
|
|
|
color : JSON.parse(rv.content[rv.content.length - index -1].content)
|
|
|
|
|
}
|
|
|
|
|
}else{
|
2025-05-21 20:05:08 +08:00
|
|
|
let think = ''
|
|
|
|
|
let message = ''
|
2025-05-22 11:18:11 +08:00
|
|
|
if(text.split('[TEXT]').length > 1 && text.split('[THINK]').length > 1){
|
2025-05-21 20:05:08 +08:00
|
|
|
think = text.split('[TEXT]')[0]
|
|
|
|
|
text.split('[TEXT]').forEach((text:any,index:number) => {
|
|
|
|
|
if(index == 0)return
|
|
|
|
|
message += ('[TEXT]'+text)
|
|
|
|
|
});
|
|
|
|
|
}else{
|
|
|
|
|
message = text
|
|
|
|
|
}
|
2025-05-20 16:47:27 +08:00
|
|
|
rv.content[rv.content.length - index -1].content = {
|
2025-05-21 20:05:08 +08:00
|
|
|
message:message,
|
|
|
|
|
think:think,
|
2025-05-20 16:47:27 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}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
|
2025-05-21 20:05:08 +08:00
|
|
|
// let setRecords = ()=>{
|
|
|
|
|
// data.isChattingRecords = false
|
|
|
|
|
// document.removeEventListener('click',setRecords)
|
|
|
|
|
// }
|
|
|
|
|
// document.addEventListener('click',setRecords)
|
2025-05-20 16:47:27 +08:00
|
|
|
}
|
|
|
|
|
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{
|
2025-05-21 20:05:08 +08:00
|
|
|
> .content{
|
|
|
|
|
> .txt{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
> .showThink{
|
|
|
|
|
display: none;
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-05-20 16:47:27 +08:00
|
|
|
> .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;
|
2025-06-09 10:25:54 +08:00
|
|
|
// -webkit-user-select: none;
|
2025-06-03 14:57:18 +08:00
|
|
|
> .icon{
|
|
|
|
|
> img{
|
|
|
|
|
width: 2.5rem;
|
|
|
|
|
height: 2.5rem;
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-05-20 16:47:27 +08:00
|
|
|
> .text{
|
|
|
|
|
// display: inline-block;
|
|
|
|
|
// width: min-content;
|
|
|
|
|
max-width: 100%;
|
|
|
|
|
width: 100%;
|
|
|
|
|
// width: min-content;
|
|
|
|
|
// word-wrap: break-word;
|
2025-05-21 20:05:08 +08:00
|
|
|
> .content{
|
|
|
|
|
> .txt{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
> .showThink{
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
display: flex;
|
|
|
|
|
padding: .7rem 1.4rem;
|
|
|
|
|
margin-bottom: 1.2rem;
|
|
|
|
|
background: rgb(237 237 237);
|
|
|
|
|
border-radius: 1rem;
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
|
|
|
|
&.active{
|
|
|
|
|
>i{
|
|
|
|
|
transform: rotate(180deg);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
> i{
|
|
|
|
|
display: flex;
|
|
|
|
|
transition: all .3s;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
> .think{
|
|
|
|
|
margin-bottom: 2rem;
|
|
|
|
|
padding-left: 2rem;
|
|
|
|
|
color: #8b8b8b;
|
|
|
|
|
white-space: pre-wrap;
|
|
|
|
|
border-left: 2px solid #e5e5e5;
|
|
|
|
|
-moz-user-select: none;
|
|
|
|
|
-ms-user-select: none;
|
|
|
|
|
user-select: none;
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-05-20 16:47:27 +08:00
|
|
|
> .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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-05-28 10:28:07 +08:00
|
|
|
> .enableThinking{
|
|
|
|
|
width: 10rem;
|
|
|
|
|
padding: .2rem .4rem;
|
|
|
|
|
text-align: center;
|
|
|
|
|
font-size: 1.4rem;
|
|
|
|
|
border: 1px solid #000;
|
|
|
|
|
border-radius: .4rem;
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
margin-left: 1rem;
|
|
|
|
|
&.active{
|
|
|
|
|
background: #000;
|
|
|
|
|
color: #fff;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-05-20 16:47:27 +08:00
|
|
|
}
|
|
|
|
|
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;
|
2025-05-28 10:28:07 +08:00
|
|
|
|
2025-05-20 16:47:27 +08:00
|
|
|
> .maxNum{
|
|
|
|
|
font-size: 1.2rem;
|
|
|
|
|
margin-right: .8rem;
|
|
|
|
|
font-weight: 400;
|
|
|
|
|
}
|
|
|
|
|
> .send{
|
|
|
|
|
opacity: .5;
|
|
|
|
|
cursor: no-drop;
|
|
|
|
|
&.active{
|
|
|
|
|
opacity: 1;
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-05-21 20:05:08 +08:00
|
|
|
> .right,> .left,>.top{
|
2025-05-20 16:47:27 +08:00
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
width: 3rem;
|
|
|
|
|
justify-content: center;
|
|
|
|
|
> i{
|
|
|
|
|
display: flex;
|
|
|
|
|
font-size: 2rem;
|
|
|
|
|
transition: all .3s;
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-05-21 20:05:08 +08:00
|
|
|
> .top{
|
|
|
|
|
width: 100%;
|
|
|
|
|
margin: 0 3rem;
|
|
|
|
|
height: 3rem;
|
|
|
|
|
&.active{
|
|
|
|
|
> i{
|
|
|
|
|
transform: rotate(180deg);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
> i{
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-05-20 16:47:27 +08:00
|
|
|
> .right{
|
|
|
|
|
border-left: 1px solid #e5e5e5;
|
|
|
|
|
> i{
|
|
|
|
|
transform: rotate(270deg);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
> .left{
|
|
|
|
|
border-right: 1px solid #e5e5e5;
|
|
|
|
|
> i{
|
|
|
|
|
transform: rotate(90deg);
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-05-21 20:05:08 +08:00
|
|
|
flex-wrap: wrap;
|
2025-05-20 16:47:27 +08:00
|
|
|
}
|
|
|
|
|
</style>
|