From 30a08223fbdcb3fa7b7d1ab3a0ad93e4bc949aeb Mon Sep 17 00:00:00 2001
From: zhangwencui <1064582902@qq.com>
Date: 星期二, 28 四月 2026 17:52:35 +0800
Subject: [PATCH] Merge branch 'dev_NEW_pro' of http://114.132.189.42:9002/r/product-inventory-management into dev_NEW_pro
---
src/components/AIChatSidebar/index.vue | 153 +++++++++++++++++++++++++++++++++++++++++++++-----
1 files changed, 136 insertions(+), 17 deletions(-)
diff --git a/src/components/AIChatSidebar/index.vue b/src/components/AIChatSidebar/index.vue
index 1f1a580..bab4dea 100644
--- a/src/components/AIChatSidebar/index.vue
+++ b/src/components/AIChatSidebar/index.vue
@@ -2,9 +2,9 @@
<div class="ai-chat-sidebar-wrapper">
<!-- 鎮诞鍥炬爣 -->
<div class="ai-chat-trigger" @click="toggleSidebar" v-show="!visible">
- <el-tooltip content="AI 鍔╂墜" placement="left">
+ <el-tooltip :content="currentAssistant.tooltip" placement="left">
<div class="trigger-icon">
- <el-icon :size="30" color="#fff"><Cpu /></el-icon>
+ <el-icon :size="30" color="#fff"><component :is="currentAssistant.icon" /></el-icon>
</div>
</el-tooltip>
</div>
@@ -25,8 +25,19 @@
<template #header>
<div class="drawer-header">
<div class="header-left">
- <el-icon :size="20" class="header-icon"><Cpu /></el-icon>
- <span class="title">AI 鏅鸿兘鍔╂墜</span>
+ <el-icon :size="20" class="header-icon"><component :is="currentAssistant.icon" /></el-icon>
+ <span class="title">{{ currentAssistant.title }}</span>
+ </div>
+ <div v-if="showAssistantSwitch" class="assistant-switcher">
+ <el-radio-group v-model="selectedAssistantKey" size="small">
+ <el-radio-button
+ v-for="assistant in assistants"
+ :key="assistant.key"
+ :label="assistant.key"
+ >
+ {{ assistant.label }}
+ </el-radio-button>
+ </el-radio-group>
</div>
<div class="header-actions">
<el-tooltip content="浼氳瘽鍘嗗彶" placement="bottom">
@@ -82,7 +93,7 @@
<el-icon><Delete /></el-icon>
</el-button>
</div>
- <el-empty v-if="sessions.length === 0" description="鏆傛棤鍘嗗彶浼氳瘽" />
+ <el-empty v-if="sessions.length === 0" :description="currentAssistant.emptySessionText" />
</div>
</el-skeleton>
</div>
@@ -145,6 +156,7 @@
<el-icon><VideoPause /></el-icon>鍋滄鐢熸垚
</el-button>
<el-upload
+ v-if="currentAssistant.allowFileUpload"
class="file-upload-trigger"
action="#"
:auto-upload="false"
@@ -167,7 +179,7 @@
v-model="inputMessage"
type="textarea"
:rows="selectedFile ? 2 : 3"
- placeholder="璇疯緭鍏ユ偍鐨勯棶棰�... (Enter 鍙戦��, Shift+Enter 鎹㈣)"
+ :placeholder="currentAssistant.placeholder"
resize="none"
@keydown.enter.exact.prevent="sendMessage"
/>
@@ -191,8 +203,53 @@
import { ref, onMounted, onUnmounted, nextTick, watch, computed } from 'vue'
import request from '@/utils/request'
import * as echarts from 'echarts'
-import { Cpu, User, Plus, Loading, Timer, Delete, ChatDotSquare, VideoPause, Upload, Document, Close } from '@element-plus/icons-vue'
+import { Cpu, User, Plus, Timer, Delete, ChatDotSquare, VideoPause, Upload, Document, Close, ShoppingCart } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'
+
+const props = defineProps({
+ assistants: {
+ type: Array,
+ default: () => []
+ },
+ defaultAssistant: {
+ type: String,
+ default: ''
+ }
+})
+
+const builtInAssistants = [
+ {
+ key: 'general',
+ label: '寰呭姙鍔╃悊',
+ title: '寰呭姙鏅鸿兘鍔╃悊',
+ tooltip: '寰呭姙鍔╂墜',
+ icon: Cpu,
+ apiBase: '/xiaozhi',
+ storageKey: 'ai_chat_uuid',
+ placeholder: '璇疯緭鍏ユ偍鐨勯棶棰�... (Enter 鍙戦��, Shift+Enter 鎹㈣)',
+ welcomeMessage: '浣犲ソ',
+ allowFileUpload: true,
+ emptySessionText: '鏆傛棤鍘嗗彶浼氳瘽'
+ },
+ {
+ key: 'purchase',
+ label: '閲囪喘鍔╃悊',
+ title: '閲囪喘鏅鸿兘鍔╃悊',
+ tooltip: '閲囪喘鏅鸿兘鍔╃悊',
+ icon: ShoppingCart,
+ apiBase: '/purchase-ai',
+ storageKey: 'purchase_ai_chat_uuid',
+ placeholder: '璇疯緭鍏ラ噰璐棶棰�... (Enter 鍙戦��, Shift+Enter 鎹㈣)',
+ welcomeMessage: '浣犲ソ',
+ allowFileUpload: false,
+ emptySessionText: '鏆傛棤閲囪喘浼氳瘽'
+ }
+]
+
+const assistants = computed(() => props.assistants?.length ? props.assistants : builtInAssistants)
+const selectedAssistantKey = ref(props.defaultAssistant || assistants.value[0]?.key || 'general')
+const currentAssistant = computed(() => assistants.value.find(item => item.key === selectedAssistantKey.value) || assistants.value[0] || builtInAssistants[0])
+const showAssistantSwitch = computed(() => assistants.value.length > 1)
const visible = ref(false)
const windowWidth = ref(window.innerWidth)
@@ -227,7 +284,7 @@
const loadSessions = async () => {
loadingSessions.value = true
try {
- const res = await request.get('/xiaozhi/history/sessions')
+ const res = await request.get(`${currentAssistant.value.apiBase}/history/sessions`)
if (res.code === 200) {
sessions.value = res.data || []
}
@@ -241,11 +298,11 @@
const selectSession = async (session) => {
showHistory.value = false
uuid.value = session.memoryId
- localStorage.setItem('ai_chat_uuid', uuid.value)
+ localStorage.setItem(currentAssistant.value.storageKey, uuid.value)
// 鍔犺浇浼氳瘽娑堟伅
try {
- const res = await request.get(`/xiaozhi/history/messages/${uuid.value}`)
+ const res = await request.get(`${currentAssistant.value.apiBase}/history/messages/${uuid.value}`)
if (res.code === 200) {
disposeCharts()
messages.value = []
@@ -299,7 +356,7 @@
const handleDeleteSession = async (memoryId) => {
try {
- const res = await request.delete(`/xiaozhi/history/${memoryId}`)
+ const res = await request.delete(`${currentAssistant.value.apiBase}/history/${memoryId}`)
if (res.code === 200) {
loadSessions()
if (uuid.value === memoryId) {
@@ -335,6 +392,26 @@
window.removeEventListener('resize', handleWindowResize)
})
+watch(selectedAssistantKey, (nextKey, prevKey) => {
+ if (!prevKey || nextKey === prevKey) return
+
+ if (currentAbortController.value) {
+ currentAbortController.value.abort()
+ currentAbortController.value = null
+ }
+
+ isSending.value = false
+ disposeCharts()
+ messages.value = []
+ outputState.value = {}
+ sessions.value = []
+ showHistory.value = false
+ selectedFile.value = null
+ inputMessage.value = ''
+ initUUID()
+ hello()
+})
+
const handleWindowResize = () => {
windowWidth.value = window.innerWidth
}
@@ -351,23 +428,26 @@
}
const initUUID = () => {
- let storedUUID = localStorage.getItem('ai_chat_uuid')
+ let storedUUID = localStorage.getItem(currentAssistant.value.storageKey)
if (!storedUUID) {
storedUUID = Math.random().toString(36).substring(2, 10) + Date.now().toString(36).substring(4)
- localStorage.setItem('ai_chat_uuid', storedUUID)
+ localStorage.setItem(currentAssistant.value.storageKey, storedUUID)
}
uuid.value = storedUUID
}
const hello = () => {
- sendRequest('浣犲ソ')
+ sendRequest(currentAssistant.value.welcomeMessage || '浣犲ソ')
}
const newChat = () => {
disposeCharts()
messages.value = []
outputState.value = {}
- localStorage.removeItem('ai_chat_uuid')
+ sessions.value = []
+ showHistory.value = false
+ selectedFile.value = null
+ localStorage.removeItem(currentAssistant.value.storageKey)
initUUID()
hello()
}
@@ -527,7 +607,7 @@
formData.append('message', message.trim())
}
- request.post('/xiaozhi/analyze-file', formData, {
+ request.post(`${currentAssistant.value.apiBase}/analyze-file`, formData, {
headers: {
'Content-Type': 'multipart/form-data'
},
@@ -642,7 +722,7 @@
scrollToBottom()
- request.post('/xiaozhi/chat',
+ request.post(`${currentAssistant.value.apiBase}/chat`,
{ memoryId: uuid.value, message },
{
signal: currentAbortController.value.signal,
@@ -1297,6 +1377,45 @@
}
}
}
+
+ .assistant-switcher {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ flex: 1;
+ padding: 0 12px;
+ position: relative;
+ z-index: 1;
+
+ :deep(.el-radio-group) {
+ display: flex;
+ gap: 6px;
+ flex-wrap: wrap;
+ justify-content: center;
+ }
+
+ :deep(.el-radio-button__inner) {
+ border-radius: 999px;
+ border: 1px solid rgba(255, 255, 255, 0.18);
+ background: rgba(255, 255, 255, 0.12);
+ color: rgba(255, 255, 255, 0.86);
+ box-shadow: none;
+ padding: 7px 14px;
+ font-weight: 500;
+ }
+
+ :deep(.el-radio-button:first-child .el-radio-button__inner),
+ :deep(.el-radio-button:last-child .el-radio-button__inner) {
+ border-radius: 999px;
+ }
+
+ :deep(.el-radio-button__original-radio:checked + .el-radio-button__inner) {
+ background: #fff;
+ color: $primary-blue;
+ border-color: #fff;
+ box-shadow: 0 6px 14px rgba(0, 40, 120, 0.16);
+ }
+ }
}
@keyframes headerGlow {
--
Gitblit v1.9.3