|
@@ -5,8 +5,8 @@
|
|
<el-scrollbar class="message-list" ref="scrollbar">
|
|
<el-scrollbar class="message-list" ref="scrollbar">
|
|
<div class="messages">
|
|
<div class="messages">
|
|
<div v-for="(message, index) in messages" :key="index"
|
|
<div v-for="(message, index) in messages" :key="index"
|
|
- :class="['message-item', message.isSelf ? 'self' : 'other']">
|
|
|
|
- <el-avatar :size="32" :src="message.avatar" />
|
|
|
|
|
|
+ :class="['message-item', message.isSelf ? 'self' : 'other']">
|
|
|
|
+ <el-avatar :size="32" :src="message.avatar"/>
|
|
<div class="message-content">
|
|
<div class="message-content">
|
|
<div class="content" v-if="!message.isSelf" :class="{ 'loading-content': message.content === '' }">
|
|
<div class="content" v-if="!message.isSelf" :class="{ 'loading-content': message.content === '' }">
|
|
<span v-html="message.content"></span>
|
|
<span v-html="message.content"></span>
|
|
@@ -25,21 +25,25 @@
|
|
</div>
|
|
</div>
|
|
</el-scrollbar>
|
|
</el-scrollbar>
|
|
|
|
|
|
- <Tools @read-click="readClick" @upload-file="handleUpload" @handle-capture="handleCapture" />
|
|
|
|
|
|
+ <Tools @read-click="readClick"
|
|
|
|
+ @upload-file="handleUpload"
|
|
|
|
+ @handle-capture="handleCapture"
|
|
|
|
+ @his-records="hisRecords"
|
|
|
|
+ @add-new-dialogue="addNewDialogue"/>
|
|
|
|
|
|
<div>
|
|
<div>
|
|
<!-- 输入区域 -->
|
|
<!-- 输入区域 -->
|
|
<div class="input-area">
|
|
<div class="input-area">
|
|
<div v-show="isShowPage" style="border-bottom: 1px solid #F0F0F0;">
|
|
<div v-show="isShowPage" style="border-bottom: 1px solid #F0F0F0;">
|
|
<div class="card-content">
|
|
<div class="card-content">
|
|
- <img :src="pageInfo?.favIconUrl" style="width: 24px;" />
|
|
|
|
|
|
+ <img :src="pageInfo?.favIconUrl" style="width: 24px;"/>
|
|
<div class="title-wrapper">
|
|
<div class="title-wrapper">
|
|
<div class="title-scroller" :class="{ 'scroll': isHoveringTitle && titleScroll }">
|
|
<div class="title-scroller" :class="{ 'scroll': isHoveringTitle && titleScroll }">
|
|
{{ pageInfo?.title }}
|
|
{{ pageInfo?.title }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<el-icon size="16px" @click="isShowPage = false; taklToHtml = false">
|
|
<el-icon size="16px" @click="isShowPage = false; taklToHtml = false">
|
|
- <CircleClose />
|
|
|
|
|
|
+ <CircleClose/>
|
|
</el-icon>
|
|
</el-icon>
|
|
</div>
|
|
</div>
|
|
<div class="card-btn">
|
|
<div class="card-btn">
|
|
@@ -53,41 +57,50 @@
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
- <el-input ref="textareaRef" v-model="inputMessage" type="textarea" :rows="3" placeholder="输入消息..." @keyup.enter="() => {
|
|
|
|
- addMessage(inputMessage.trim(), true)
|
|
|
|
- inputMessage = ''
|
|
|
|
- }" />
|
|
|
|
|
|
+ <el-input ref="textareaRef" v-model="inputMessage" type="textarea" :rows="3" placeholder="输入消息..."
|
|
|
|
+ @keyup.enter="handleAsk"/>
|
|
<div class="chat_area_op">
|
|
<div class="chat_area_op">
|
|
<el-button type="primary" link @click="handleAsk" :disabled="!inputMessage.trim() || sendLoading">
|
|
<el-button type="primary" link @click="handleAsk" :disabled="!inputMessage.trim() || sendLoading">
|
|
<el-icon size="18" :color="inputMessage.trim() ? 'black' : 'gray'">
|
|
<el-icon size="18" :color="inputMessage.trim() ? 'black' : 'gray'">
|
|
- <Promotion />
|
|
|
|
|
|
+ <Promotion/>
|
|
</el-icon>
|
|
</el-icon>
|
|
</el-button>
|
|
</el-button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
</div>
|
|
</div>
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ <!-- 历史记录 -->
|
|
|
|
+ <historyComponent :msgUuid="msgUuid" ref="historyComponentRef" @currentData="(e)=>handleCurrentData(e)"/>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
<script setup>
|
|
-import { ref, onMounted, nextTick, inject, useTemplateRef } from 'vue'
|
|
|
|
-import { ElScrollbar, ElAvatar, ElInput, ElButton } from 'element-plus'
|
|
|
|
-import { buildExcelUnderstandingPrompt } from '@/utils/ai-service.js'
|
|
|
|
|
|
+import {ref, onMounted, nextTick, inject, useTemplateRef} from 'vue'
|
|
|
|
+import {ElScrollbar, ElAvatar, ElInput, ElButton} from 'element-plus'
|
|
|
|
+import moment from "moment";
|
|
|
|
+import {buildExcelUnderstandingPrompt} from '@/utils/ai-service.js'
|
|
import * as XLSX from "xlsx";
|
|
import * as XLSX from "xlsx";
|
|
-import { ElMessage } from 'element-plus';
|
|
|
|
-import { useMsg } from '@/entrypoints/sidepanel/hook/useMsg.ts';
|
|
|
|
|
|
+import {ElMessage} from 'element-plus';
|
|
|
|
+import {useMsg} from '@/entrypoints/sidepanel/hook/useMsg.ts';
|
|
import Tools from "@/entrypoints/sidepanel/component/tools.vue";
|
|
import Tools from "@/entrypoints/sidepanel/component/tools.vue";
|
|
-import { useSummary } from '@/entrypoints/sidepanel/hook/useSummary.ts'
|
|
|
|
-import { mockData } from "@/entrypoints/sidepanel/mock"
|
|
|
|
-import { useAutoResizeTextarea } from '@/entrypoints/sidepanel/hook/useAutoResizeTextarea.ts';
|
|
|
|
|
|
+import historyComponent from '@/entrypoints/sidepanel/component/historyComponent.vue';
|
|
|
|
+import {useSummary} from '@/entrypoints/sidepanel/hook/useSummary.ts'
|
|
|
|
+import {mockData, startMsg} from "@/entrypoints/sidepanel/mock"
|
|
|
|
+import {useAutoResizeTextarea} from '@/entrypoints/sidepanel/hook/useAutoResizeTextarea.ts';
|
|
|
|
+
|
|
|
|
|
|
// 滚动条引用
|
|
// 滚动条引用
|
|
const scrollbar = ref(null);
|
|
const scrollbar = ref(null);
|
|
const xlsxData = ref({});
|
|
const xlsxData = ref({});
|
|
const isShowPage = ref(false);
|
|
const isShowPage = ref(false);
|
|
const tareRef = useTemplateRef("textareaRef");
|
|
const tareRef = useTemplateRef("textareaRef");
|
|
|
|
+const drawerRef = useTemplateRef("historyComponentRef");
|
|
|
|
+// 获取父组件提供的 Hook 实例
|
|
|
|
+const {registerStore, useStore} = inject('indexedDBHook');
|
|
const {
|
|
const {
|
|
|
|
+ msgUuid,
|
|
messages,
|
|
messages,
|
|
inputMessage,
|
|
inputMessage,
|
|
indexTemp,
|
|
indexTemp,
|
|
@@ -101,7 +114,7 @@ const {
|
|
streamRes,
|
|
streamRes,
|
|
handleInput
|
|
handleInput
|
|
} = useMsg(scrollbar, xlsxData, fetchDataAndProcess);
|
|
} = useMsg(scrollbar, xlsxData, fetchDataAndProcess);
|
|
-const { handleCardButtonClick } = useSummary(addMessage, sendRequese);
|
|
|
|
|
|
+const {handleCardButtonClick} = useSummary(addMessage, sendRequese);
|
|
|
|
|
|
function handelIntelligentFillingClick() {
|
|
function handelIntelligentFillingClick() {
|
|
if (type.value !== '2') {
|
|
if (type.value !== '2') {
|
|
@@ -112,13 +125,41 @@ function handelIntelligentFillingClick() {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+function handleCurrentData(e) {
|
|
|
|
+ drawerRef.value.drawer = false;
|
|
|
|
+ if (!e) {
|
|
|
|
+ addNewDialogue();
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ // 添加indexDB Store配置
|
|
|
|
+ msgUuid.value = e;
|
|
|
|
+ useStore(e).getAll().then((res) => {
|
|
|
|
+ messages.value = res
|
|
|
|
+ nextTick(() => {
|
|
|
|
+ scrollbar.value?.setScrollTop(99999)
|
|
|
|
+ })
|
|
|
|
+ })
|
|
|
|
+}
|
|
|
|
+
|
|
async function readClick() {
|
|
async function readClick() {
|
|
isShowPage.value = true;
|
|
isShowPage.value = true;
|
|
taklToHtml.value = true;
|
|
taklToHtml.value = true;
|
|
await getPageInfo()
|
|
await getPageInfo()
|
|
}
|
|
}
|
|
|
|
|
|
-function handleAsk() {
|
|
|
|
|
|
+function addNewDialogue() {
|
|
|
|
+ messages.value = [];
|
|
|
|
+ msgUuid.value = 'D' + Date.now().toString();
|
|
|
|
+ registerStore({
|
|
|
|
+ name: msgUuid.value,
|
|
|
|
+ keyPath: 'id',
|
|
|
|
+ })
|
|
|
|
+ messages.value.push(startMsg);
|
|
|
|
+ useStore(msgUuid.value).add(startMsg);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+async function handleAsk() {
|
|
|
|
+ if (sendLoading.value) return;
|
|
addMessage(inputMessage.value.trim(), true);
|
|
addMessage(inputMessage.value.trim(), true);
|
|
inputMessage.value = '';
|
|
inputMessage.value = '';
|
|
}
|
|
}
|
|
@@ -131,6 +172,10 @@ function handleCapture() {
|
|
});
|
|
});
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+function hisRecords() {
|
|
|
|
+ drawerRef.value.drawer = true;
|
|
|
|
+}
|
|
|
|
+
|
|
// 计算标题是否需要滚动
|
|
// 计算标题是否需要滚动
|
|
const titleScroll = computed(() => {
|
|
const titleScroll = computed(() => {
|
|
return pageInfo.value?.title?.length > 20 // 当标题超过20个字符时触发滚动
|
|
return pageInfo.value?.title?.length > 20 // 当标题超过20个字符时触发滚动
|
|
@@ -190,9 +235,9 @@ const handleUpload = (file) => {
|
|
}
|
|
}
|
|
|
|
|
|
async function fetchDataAndProcess(input, obj) {
|
|
async function fetchDataAndProcess(input, obj) {
|
|
- console.log(input);
|
|
|
|
|
|
+ // console.log(input);
|
|
|
|
|
|
- const pageInfo = await getPageInfo();
|
|
|
|
|
|
+ // const pageInfo = await getPageInfo();
|
|
|
|
|
|
// 发起请求获取数据
|
|
// 发起请求获取数据
|
|
// const res = await hepl({
|
|
// const res = await hepl({
|
|
@@ -201,7 +246,7 @@ async function fetchDataAndProcess(input, obj) {
|
|
// })
|
|
// })
|
|
const res = await new Promise((resolve, reject) => {
|
|
const res = await new Promise((resolve, reject) => {
|
|
setTimeout(() => {
|
|
setTimeout(() => {
|
|
- resolve({ data: mockData[indexTemp.value] })
|
|
|
|
|
|
+ resolve({data: mockData[indexTemp.value]})
|
|
}, 1000)
|
|
}, 1000)
|
|
})
|
|
})
|
|
await handleClick(res.data, obj);
|
|
await handleClick(res.data, obj);
|
|
@@ -224,8 +269,8 @@ async function handleClick(res, msgObj) {
|
|
indexTemp.value++
|
|
indexTemp.value++
|
|
fetchDataAndProcess('', msgObj)
|
|
fetchDataAndProcess('', msgObj)
|
|
} else {
|
|
} else {
|
|
- ElMessage({ message: '操作执行完成', type: 'success', duration: 2 * 1000, grouping: true })
|
|
|
|
- index = 0
|
|
|
|
|
|
+ ElMessage({message: '操作执行完成', type: 'success', duration: 2 * 1000, grouping: true})
|
|
|
|
+ // index = 0
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return true
|
|
return true
|
|
@@ -233,7 +278,7 @@ async function handleClick(res, msgObj) {
|
|
}
|
|
}
|
|
if (res.action === 'show') {
|
|
if (res.action === 'show') {
|
|
msgObj.content = `请上传数据`
|
|
msgObj.content = `请上传数据`
|
|
- ElMessage({ message: '请上传数据', type: 'success', duration: 4 * 1000, grouping: true })
|
|
|
|
|
|
+ ElMessage({message: '请上传数据', type: 'success', duration: 4 * 1000, grouping: true})
|
|
}
|
|
}
|
|
// chrome.runtime.sendMessage({
|
|
// chrome.runtime.sendMessage({
|
|
// type: 'FROM_SIDE_PANEL_TO_ACTION',
|
|
// type: 'FROM_SIDE_PANEL_TO_ACTION',
|
|
@@ -260,7 +305,7 @@ async function handleClick(res, msgObj) {
|
|
const isHoveringTitle = ref(false)
|
|
const isHoveringTitle = ref(false)
|
|
|
|
|
|
// 组件挂载时滚动到底部
|
|
// 组件挂载时滚动到底部
|
|
-onMounted(async () => {
|
|
|
|
|
|
+onMounted(() => {
|
|
useAutoResizeTextarea(tareRef, inputMessage);
|
|
useAutoResizeTextarea(tareRef, inputMessage);
|
|
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
|
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
|
if (message.type === 'TO_SIDE_PANEL_PAGE_INFO') {
|
|
if (message.type === 'TO_SIDE_PANEL_PAGE_INFO') {
|
|
@@ -294,9 +339,17 @@ onMounted(async () => {
|
|
isHoveringTitle.value = false
|
|
isHoveringTitle.value = false
|
|
})
|
|
})
|
|
}
|
|
}
|
|
-
|
|
|
|
scrollbar.value?.setScrollTop(99999)
|
|
scrollbar.value?.setScrollTop(99999)
|
|
})
|
|
})
|
|
|
|
+
|
|
|
|
+ // 添加indexDB Store配置
|
|
|
|
+ msgUuid.value = 'D' + Date.now().toString();
|
|
|
|
+ registerStore({
|
|
|
|
+ name: msgUuid.value,
|
|
|
|
+ keyPath: 'id',
|
|
|
|
+ })
|
|
|
|
+ messages.value.push(startMsg);
|
|
|
|
+ useStore(msgUuid.value).add(startMsg);
|
|
})
|
|
})
|
|
</script>
|
|
</script>
|
|
|
|
|
|
@@ -526,8 +579,6 @@ onMounted(async () => {
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
-
|
|
|
|
-
|
|
|
|
.input-area {
|
|
.input-area {
|
|
padding: 8px 10px;
|
|
padding: 8px 10px;
|
|
color: black;
|
|
color: black;
|