From 31359d82106e855d50e260bd14f878775ea0bf18 Mon Sep 17 00:00:00 2001
From: liyong <18434998025@163.com>
Date: 星期四, 21 五月 2026 18:00:42 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/dev_NEW_pro' into dev_NEW_pro
---
src/components/AIChatSidebar/assistants/financeAssistant.js | 26 ++++++
src/components/AIChatSidebar/assistants/index.js | 8 +
src/components/AIChatSidebar/index.vue | 182 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 211 insertions(+), 5 deletions(-)
diff --git a/src/components/AIChatSidebar/assistants/financeAssistant.js b/src/components/AIChatSidebar/assistants/financeAssistant.js
new file mode 100644
index 0000000..cbb650a
--- /dev/null
+++ b/src/components/AIChatSidebar/assistants/financeAssistant.js
@@ -0,0 +1,26 @@
+import { Money } from '@element-plus/icons-vue'
+
+export const financeAssistant = {
+ key: 'finance',
+ label: '璐㈠姟鍔╃悊',
+ title: '璐㈠姟鏅鸿兘鍔╃悊',
+ tooltip: '璐㈠姟鏅鸿兘鍔╃悊',
+ icon: Money,
+ apiBase: '/financial-ai',
+ storageKey: 'financial_ai_chat_uuid',
+ placeholder: '璇疯緭鍏ヨ储鍔¢棶棰�... (Enter 鍙戦��, Shift+Enter 鎹㈣)',
+ welcomeMessage: '浣犲ソ',
+ description: '鎴戝彲浠ュ崗鍔╀綘瀹屾垚鎴愭湰鏍哥畻銆佸埄娑﹀垎鏋愩�佸簱瀛樿祫閲戝垎鏋愩�佺幇閲戞祦棰勬祴銆佸紓甯搁璀﹀拰缁忚惀鍛ㄦ姤瑙h銆�',
+ allowFileUpload: false,
+ emptySessionText: '鏆傛棤璐㈠姟浼氳瘽',
+ quickPrompts: [
+ '鏌ョ湅鏈湀缁忚惀椹鹃┒鑸�',
+ '鏌ヨ杩�30澶╀簭鎹熻鍗�',
+ '鍒嗘瀽杩�30澶╁簱瀛樿祫閲戝崰鐢�',
+ '棰勬祴鏈潵3涓湀鐜伴噾娴�',
+ '鐢熸垚鏈懆缁忚惀鍛ㄦ姤',
+ '涓轰粈涔堝埄娑︿笅闄�',
+ '鍝釜瀹㈡埛鏈�璧氶挶',
+ '鍝釜宸ュ簭鎴愭湰鏈�楂�'
+ ]
+}
diff --git a/src/components/AIChatSidebar/assistants/index.js b/src/components/AIChatSidebar/assistants/index.js
index d7081b4..6e2a35d 100644
--- a/src/components/AIChatSidebar/assistants/index.js
+++ b/src/components/AIChatSidebar/assistants/index.js
@@ -2,14 +2,16 @@
import { purchaseAssistant } from './purchaseAssistant'
import { productionAssistant } from './productionAssistant'
import { salesAssistant } from './salesAssistant'
+import { financeAssistant } from './financeAssistant'
-export { generalAssistant, purchaseAssistant, productionAssistant, salesAssistant }
+export { generalAssistant, purchaseAssistant, productionAssistant, salesAssistant, financeAssistant }
export const assistantRegistry = {
general: generalAssistant,
sales: salesAssistant,
purchase: purchaseAssistant,
- production: productionAssistant
+ production: productionAssistant,
+ finance: financeAssistant
}
-export const builtInAssistants = [generalAssistant, salesAssistant, purchaseAssistant, productionAssistant]
+export const builtInAssistants = [generalAssistant, salesAssistant, purchaseAssistant, productionAssistant, financeAssistant]
diff --git a/src/components/AIChatSidebar/index.vue b/src/components/AIChatSidebar/index.vue
index c9db563..3006ce7 100644
--- a/src/components/AIChatSidebar/index.vue
+++ b/src/components/AIChatSidebar/index.vue
@@ -523,6 +523,64 @@
</div>
</div>
+ <div v-if="message.financeData" class="sales-structured-card">
+ <div class="sales-structured-card__title">{{ getFinancialTypeLabel(message.type) }}</div>
+
+ <div v-if="message.financeData.summaryEntries?.length" class="sales-summary-grid">
+ <div
+ v-for="(entry, entryIndex) in message.financeData.summaryEntries"
+ :key="`finance-summary-${entry.key}-${entryIndex}`"
+ class="sales-summary-item"
+ >
+ <span class="sales-summary-label">{{ entry.label }}</span>
+ <strong class="sales-summary-value">{{ entry.value }}</strong>
+ </div>
+ </div>
+
+ <div v-if="message.financeData.headline" class="finance-headline">
+ {{ message.financeData.headline }}
+ </div>
+
+ <div v-if="message.financeData.conclusions?.length" class="finance-text-section">
+ <div class="sales-section-title">鏍稿績缁撹</div>
+ <ul>
+ <li v-for="(item, idx) in message.financeData.conclusions" :key="`finance-conclusion-${idx}`">
+ {{ item }}
+ </li>
+ </ul>
+ </div>
+
+ <div v-if="message.financeData.riskSuggestions?.length" class="finance-text-section">
+ <div class="sales-section-title">椋庨櫓寤鸿</div>
+ <ul>
+ <li v-for="(item, idx) in message.financeData.riskSuggestions" :key="`finance-risk-${idx}`">
+ {{ item }}
+ </li>
+ </ul>
+ </div>
+
+ <div
+ v-for="section in message.financeData.sections"
+ :key="`finance-section-${section.key}`"
+ class="table-wrapper manufacturing-table-wrapper"
+ >
+ <div class="sales-section-title">{{ section.title }}</div>
+ <el-table :data="section.items" border stripe size="small" style="width: 100%">
+ <el-table-column
+ v-for="col in section.columns"
+ :key="`finance-${section.key}-${col}`"
+ :label="getStructuredFieldLabel(col)"
+ min-width="120"
+ show-overflow-tooltip
+ >
+ <template #default="{ row }">
+ {{ formatStructuredValue(row[col]) }}
+ </template>
+ </el-table-column>
+ </el-table>
+ </div>
+ </div>
+
<div v-if="message.purchaseIntentData?.quickPrompts?.length" class="purchase-intent-quick-prompt-wrap">
<div class="purchase-intent-quick-prompt-title">璇曡瘯浠ヤ笅鎻愰棶</div>
<div class="quick-prompt-list purchase-intent-quick-prompt-list">
@@ -960,6 +1018,26 @@
purchase_material_rank: '閲囪喘鐗╂枡閲戦鎺掕',
purchase_pending_payment_list: '寰呬粯娆鹃噰璐崟'
}
+const financialStructuredTypeSet = new Set([
+ 'financial_cost_accounting',
+ 'financial_order_profit_analysis',
+ 'financial_inventory_capital_analysis',
+ 'financial_cashflow_forecast',
+ 'financial_business_anomaly_warning',
+ 'financial_business_cockpit',
+ 'financial_operation_report',
+ 'financial_rag_knowledge'
+])
+const financialTypeLabelMap = {
+ financial_cost_accounting: '鎴愭湰鏍哥畻',
+ financial_order_profit_analysis: '璁㈠崟鍒╂鼎鍒嗘瀽',
+ financial_inventory_capital_analysis: '搴撳瓨璧勯噾鍒嗘瀽',
+ financial_cashflow_forecast: '鐜伴噾娴侀娴�',
+ financial_business_anomaly_warning: '缁忚惀寮傚父棰勮',
+ financial_business_cockpit: '缁忚惀椹鹃┒鑸�',
+ financial_operation_report: '缁忚惀鎶ュ憡',
+ financial_rag_knowledge: '璐㈠姟鐭ヨ瘑妫�绱�'
+}
const manufacturingStructuredTypeSet = new Set([
'manufacturing_site_snapshot',
'manufacturing_plan_list',
@@ -1042,6 +1120,32 @@
collectionStrategy: '鍥炴绛栫暐',
quotationStrategy: '鎶ヤ环绛栫暐',
nextAction: '涓嬩竴姝ュ姩浣�',
+ salesContractNo: '閿�鍞悎鍚屽彿',
+ revenue: '鏀跺叆',
+ materialCost: '鏉愭枡鎴愭湰',
+ laborCost: '浜哄伐鎴愭湰',
+ depreciationCost: '鎶樻棫鎴愭湰',
+ scrapCost: '鎶ュ簾鎴愭湰',
+ totalCost: '鎬绘垚鏈�',
+ profit: '鍒╂鼎',
+ profitRate: '鍒╂鼎鐜�',
+ reasons: '鍘熷洜',
+ suggestion: '寤鸿',
+ productName: '浜у搧鍚嶇О',
+ model: '鍨嬪彿',
+ quantity: '鏁伴噺',
+ inventoryValue: '搴撳瓨璧勯噾',
+ stagnantDays: '鍛嗘粸澶╂暟',
+ overstock: '鏄惁瓒呭偍',
+ month: '鏈堜唤',
+ income: '鏀跺叆',
+ expense: '鏀嚭',
+ netFlow: '鍑�鐜伴噾娴�',
+ message: '棰勮淇℃伅',
+ headline: '鎶ュ憡鏍囬',
+ conclusions: '鏍稿績缁撹',
+ riskSuggestions: '椋庨櫓寤鸿',
+ orderProfitTop: '鍒╂鼎Top',
contractAmountTotal: '鍚堝悓鎬婚',
receivedAmountTotal: '宸插洖娆鹃噾棰�',
pendingAmountTotal: '寰呭洖娆炬�婚',
@@ -1492,6 +1596,50 @@
const getPurchaseTypeLabel = (type = '') => purchaseTypeLabelMap[String(type || '')] || '閲囪喘鏌ヨ缁撴灉'
+const financialDataSectionConfig = [
+ { key: 'orders', title: '璁㈠崟鏄庣粏' },
+ { key: 'items', title: '鏄庣粏鍒楄〃' },
+ { key: 'actualMonthly', title: '鍘嗗彶鐜伴噾娴�' },
+ { key: 'forecastMonthly', title: '棰勬祴鐜伴噾娴�' },
+ { key: 'receivableRiskTop', title: '搴旀敹椋庨櫓Top' },
+ { key: 'payablePressureTop', title: '搴斾粯鍘嬪姏Top' },
+ { key: 'orderProfitTop', title: '鍒╂鼎Top' }
+]
+
+const buildFinancialStructuredSections = (rawData = {}) => {
+ const sections = []
+ financialDataSectionConfig.forEach((section) => {
+ const items = normalizeSalesListItems(rawData?.[section.key])
+ if (!items.length) return
+ sections.push({
+ key: section.key,
+ title: section.title,
+ items,
+ columns: inferSalesColumns(items)
+ })
+ })
+ return sections
+}
+
+const buildFinancialStructuredData = (parsedData) => {
+ const type = String(parsedData?.type || '')
+ if (!financialStructuredTypeSet.has(type) || parsedData?.success !== true) return null
+
+ const rawData = isPlainObject(parsedData?.data) ? parsedData.data : {}
+ const headline = String(rawData?.headline || '').trim()
+
+ return {
+ type,
+ summaryEntries: normalizeManufacturingSummaryEntries(parsedData?.summary),
+ headline,
+ conclusions: toStructuredStringArray(rawData?.conclusions),
+ riskSuggestions: toStructuredStringArray(rawData?.riskSuggestions),
+ sections: buildFinancialStructuredSections(rawData)
+ }
+}
+
+const getFinancialTypeLabel = (type = '') => financialTypeLabelMap[String(type || '')] || '璐㈠姟鏌ヨ缁撴灉'
+
const isSalesFocusType = (type = '') => salesFocusTypeSet.has(String(type || ''))
const getSalesLevelTagType = (level = '') => {
@@ -1913,6 +2061,7 @@
salesData: null,
purchaseData: null,
purchaseIntentData: null,
+ financeData: null,
localUploadFiles: isUser ? mapHistoryFilePathsToSnapshots(msg.filePaths, uuid.value, idx) : []
}
@@ -2161,6 +2310,7 @@
messageObj.salesData = null
messageObj.purchaseData = null
messageObj.purchaseIntentData = null
+ messageObj.financeData = null
if (isPurchaseIntentNotRecognized) {
messageObj.purchaseIntentData = normalizePurchaseIntentNotRecognizedData(parsedData)
@@ -2188,12 +2338,18 @@
messageObj.purchaseData = purchaseData
}
+ const financeData = buildFinancialStructuredData(parsedData)
+ if (financeData) {
+ messageObj.financeData = financeData
+ }
+
if (parsedData.action === 'confirm_required' && parsedData.businessType) {
messageObj.type = 'purchase_analysis_confirm'
messageObj.purchaseAnalysisData = parsedData
messageObj.manufacturingData = null
messageObj.salesData = null
messageObj.purchaseData = null
+ messageObj.financeData = null
if (!Array.isArray(messageObj.payloadTreeData) || !messageObj.payloadTreeData.length) {
initializePurchasePayloadTree(messageObj, parsedData.payload || {})
}
@@ -2251,6 +2407,7 @@
if (parsedData.type === 'manufacturing_analysis') return '宸蹭负鎮ㄧ敓鎴愬埗閫犲垎鏋愮粨鏋溿��'
return '宸茶繑鍥炲埗閫犳煡璇㈢粨鏋溿��'
}
+ if (financialStructuredTypeSet.has(parsedData.type)) return '宸茶繑鍥炶储鍔″垎鏋愮粨鏋溿��'
if (String(parsedData.type || '').startsWith('purchase_')) return '宸茶繑鍥為噰璐煡璇㈢粨鏋溿��'
if (parsedData.charts && Object.keys(parsedData.charts).length > 0) return '宸蹭负鎮ㄧ敓鎴愬垎鏋愬浘琛ㄣ��'
return '姝e湪涓烘偍灞曠ず鍒嗘瀽缁撴灉...'
@@ -3384,7 +3541,8 @@
manufacturingData: null,
salesData: null,
purchaseData: null,
- purchaseIntentData: null
+ purchaseIntentData: null,
+ financeData: null
})
outputState.value[botMsgIndex] = {
@@ -3512,7 +3670,8 @@
manufacturingData: null,
salesData: null,
purchaseData: null,
- purchaseIntentData: null
+ purchaseIntentData: null,
+ financeData: null
}
messages.value.push(botMsg)
@@ -4957,6 +5116,25 @@
color: $deep-blue;
}
+.finance-headline {
+ margin-top: 4px;
+ font-size: 13px;
+ line-height: 1.7;
+ color: #344054;
+}
+
+.finance-text-section {
+ margin-top: 10px;
+
+ ul {
+ margin: 6px 0 0;
+ padding-left: 18px;
+ font-size: 13px;
+ line-height: 1.7;
+ color: #344054;
+ }
+}
+
.purchase-intent-quick-prompt-wrap {
margin-top: 12px;
}
--
Gitblit v1.9.3