P0-3/P0-4/P0-5: 快捷申请全量卡片端点+RecommendCard崩溃修复+WS全字段透传(部署v16)

This commit is contained in:
Simon
2026-07-18 00:05:59 +08:00
parent 18a639919c
commit 54481525f4
4 changed files with 103 additions and 10 deletions
+35
View File
@@ -403,6 +403,41 @@ export async function getApprovalLinks(): Promise<ApprovalLink[]> {
return (data?.items || data || []) as ApprovalLink[]
}
// =============================================================================
// v4.0 P0-3: 全量审批卡片 API(快捷申请按钮用)
// =============================================================================
/** 审批卡片选项 */
export interface ApprovalCardOption {
name: string
icon: string
desc: string
url: string
}
/** 标准化审批卡片数据(后端 ApprovalMatcher 直出,前端纯渲染) */
export interface ApprovalCardData {
card_type: 'single' | 'multiple'
title: string
description?: string
options: ApprovalCardOption[]
}
/**
* 获取全量审批卡片(快捷申请按钮用)
* 注意:approval 路由挂在根路径(非 /api 前缀),需用绝对路径
* @returns 标准化 card_data
*/
export async function getAllCategoriesCard(): Promise<ApprovalCardData> {
// approval 路由在 /approval(根路径),不走 apiClient 的 /api baseURL
const token = localStorage.getItem('employee_token') || ''
const resp = await fetch('/approval/all-categories-card', {
headers: { Authorization: `Bearer ${token}` },
})
if (!resp.ok) throw new Error(`HTTP ${resp.status}`)
return resp.json()
}
// =============================================================================
// 审批意图检测 API(Dify 意图置信度 — 替代纯关键词匹配)
// =============================================================================
@@ -144,7 +144,8 @@ const sourceLabel = computed(() => {
// 判断操作项是否可点击
function isItemClickable(item: RecommendItem): boolean {
return !!(item.url || item.action || item.type === 'info' || item.copyable)
// v3.2 修复:删除接口中不存在的 item.action 死引用
return !!(item.url || item.type === 'info' || item.copyable)
}
// 获取操作项图标
@@ -174,8 +175,12 @@ function handleItemClick(item: RecommendItem) {
break
case 'approval':
// 打开审批表单
invokeApproval(item.approval_type || '')
// v3.2 修复:invokeApproval 未定义(ReferenceError),改为与 download 一致的 url 打开
if (item.url) {
window.open(item.url, '_blank')
} else {
showToast('链接缺失')
}
break
case 'info':
+36 -7
View File
@@ -400,6 +400,13 @@ export const useConversationStore = defineStore('conversation', () => {
sender_name?: string
content: string
msg_type?: string
// v3.2 P0-5: 全字段透传(后端 messages.py:278 已下发,修复坐席图片/文件不渲染)
media_url?: string
file_name?: string
file_size?: number
extra_data?: Record<string, any>
reply_to_id?: string
created_at?: string
}): void {
// WS-06 消息去重:检查 message_id 是否已处理过
if (processedMessageIds.value.has(data.message_id)) {
@@ -421,7 +428,13 @@ export const useConversationStore = defineStore('conversation', () => {
// ★ 防御性类型保护:确保 content 始终是 String
content: typeof data.content === 'string' ? data.content : (data.content ? JSON.stringify(data.content) : ''),
sender_name: data.sender_name || '',
created_at: new Date().toISOString(),
// v3.2 P0-5: 全字段透传(created_at 用服务端值,不用 new Date()
media_url: data.media_url,
file_name: data.file_name,
file_size: data.file_size,
extra_data: data.extra_data,
reply_to_id: data.reply_to_id,
created_at: data.created_at || new Date().toISOString(),
})
// 更新最后消息ID
@@ -891,14 +904,29 @@ export const useConversationStore = defineStore('conversation', () => {
approvalCardTriggerText.value = ''
}
// v4.0 P0-3: 缓存全量审批卡片(首次点击拉取,后续复用)
let _allCategoriesCardCache: any = null
/**
* 显示审批卡片(快捷按钮触发)
* 新流程中审批卡片作为消息流内联卡片,此函数直接在消息列表中插入一条审批卡片消息。
* v4.0 P0-3: 改为 async 拉取后端 /approval/all-categories-card
* 修复旧版构造 {approval_type:'',confidence:0} 导致的空白气泡(F1
*
* @param _triggerText 触发文本(可选,新流程中不再使用关键词匹配)
*/
function showApprovalCard(_triggerText: string = ''): void {
// 插入一条审批卡片消息到消息列表(approval_type 为空时组件展示全部选项)
async function showApprovalCard(_triggerText: string = ''): Promise<void> {
// 首次拉取并缓存
if (!_allCategoriesCardCache) {
try {
const { getAllCategoriesCard } = await import('@/api/conversation')
_allCategoriesCardCache = await getAllCategoriesCard()
} catch (e) {
console.error('[Store] 拉取全量审批卡片失败:', e)
return
}
}
// 插入审批卡片消息(action.card_data 为后端标准化数据,前端纯渲染)
const approvalCardMessage: Message = {
message_id: `approval_card_${Date.now()}`,
conversation_id: currentConversation.value?.conversation_id || '',
@@ -908,12 +936,13 @@ export const useConversationStore = defineStore('conversation', () => {
sender_name: '',
created_at: new Date().toISOString(),
extra_data: {
approval_type: '',
confidence: 0,
action: {
card_data: _allCategoriesCardCache,
},
},
}
messages.value.push(approvalCardMessage)
console.log('[Store] 手动插入审批卡片消息(快捷按钮触发)')
console.log('[Store] 手动插入审批卡片消息(快捷按钮触发v4.0 全量卡片')
}
/**