feat(web): update Vue components and composables
- PersonalWorkbench.vue: update personal workbench component - useAppShell.js: update app shell composable - useChat.js: update chat composable with new features - AppShellRouteView.vue: update route view - ChatView.vue: update chat view with enhanced UI - TravelReimbursementCreateView.vue: update travel reimbursement form - ChatView.js: update chat view script logic - TravelReimbursementCreateView.js: update travel form script logic
This commit is contained in:
@@ -14,13 +14,25 @@ export function useAppShell() {
|
||||
|
||||
const travelCreateMode = ref(false)
|
||||
const smartEntryOpen = ref(false)
|
||||
const smartEntryContext = ref({ prompt: '', source: 'requests', request: null })
|
||||
const smartEntryContext = ref({ prompt: '', source: 'requests', request: null, files: [] })
|
||||
const smartEntrySessionId = ref(0)
|
||||
|
||||
const { activeView, currentView, setView } = useNavigation()
|
||||
const { requests, search, filters, ranges, activeRange, filteredRequests, approveRequest, rejectRequest } =
|
||||
useRequests()
|
||||
const { messages, draft, uploadedFiles, messageList, activeCase, prompts, sendMessage, handleUpload, openChat, openNewChat } =
|
||||
const {
|
||||
messages,
|
||||
draft,
|
||||
uploadedFiles,
|
||||
messageList,
|
||||
activeCase,
|
||||
prompts,
|
||||
sending,
|
||||
sendMessage,
|
||||
handleUpload,
|
||||
openChat,
|
||||
openNewChat
|
||||
} =
|
||||
useChat(activeView)
|
||||
const { toast } = useToast()
|
||||
|
||||
@@ -81,7 +93,7 @@ export function useAppShell() {
|
||||
function openTravelCreate() {
|
||||
smartEntryOpen.value = true
|
||||
travelCreateMode.value = false
|
||||
smartEntryContext.value = { prompt: '', source: 'topbar', request: null }
|
||||
smartEntryContext.value = { prompt: '', source: 'topbar', request: null, files: [] }
|
||||
smartEntrySessionId.value += 1
|
||||
}
|
||||
|
||||
@@ -92,7 +104,8 @@ export function useAppShell() {
|
||||
smartEntryContext.value = {
|
||||
prompt: payload.prompt ?? '',
|
||||
source: payload.source ?? 'workbench',
|
||||
request: payload.request ?? selectedTravelRequest.value
|
||||
request: payload.request ?? selectedTravelRequest.value,
|
||||
files: Array.isArray(payload.files) ? payload.files : []
|
||||
}
|
||||
smartEntrySessionId.value += 1
|
||||
}
|
||||
@@ -145,6 +158,7 @@ export function useAppShell() {
|
||||
search,
|
||||
selectedTravelRequest,
|
||||
sendMessage,
|
||||
sending,
|
||||
setView,
|
||||
smartEntryContext,
|
||||
smartEntryOpen,
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import { nextTick, ref } from 'vue'
|
||||
|
||||
import { useSystemState } from './useSystemState.js'
|
||||
import { runOrchestrator } from '../services/orchestrator.js'
|
||||
|
||||
const initialMessages = [
|
||||
{
|
||||
id: 1,
|
||||
@@ -21,11 +24,13 @@ const initialMessages = [
|
||||
export const prompts = ['生成审批意见', '列出补件清单', '解释风险原因', '生成运营简报']
|
||||
|
||||
export function useChat(activeView) {
|
||||
const { currentUser } = useSystemState()
|
||||
const messages = ref([...initialMessages])
|
||||
const draft = ref('')
|
||||
const uploadedFiles = ref([])
|
||||
const messageList = ref(null)
|
||||
const activeCase = ref(null)
|
||||
const sending = ref(false)
|
||||
|
||||
function agentReply(text) {
|
||||
const c = activeCase.value
|
||||
@@ -56,15 +61,113 @@ export function useChat(activeView) {
|
||||
nextTick(() => messageList.value?.scrollTo({ top: messageList.value.scrollHeight, behavior: 'smooth' }))
|
||||
}
|
||||
|
||||
function sendMessage() {
|
||||
function replaceMessage(id, nextMessage) {
|
||||
const index = messages.value.findIndex((item) => item.id === id)
|
||||
if (index === -1) {
|
||||
messages.value.push(nextMessage)
|
||||
return
|
||||
}
|
||||
messages.value.splice(index, 1, nextMessage)
|
||||
}
|
||||
|
||||
function buildOrchestratorMeta(payload) {
|
||||
const items = []
|
||||
|
||||
if (payload?.selected_agent) {
|
||||
items.push(`Agent: ${payload.selected_agent}`)
|
||||
}
|
||||
|
||||
if (payload?.permission_level) {
|
||||
items.push(`权限: ${payload.permission_level}`)
|
||||
}
|
||||
|
||||
if (payload?.trace_summary?.tool_count) {
|
||||
items.push(`工具: ${payload.trace_summary.tool_count}`)
|
||||
}
|
||||
|
||||
if (payload?.trace_summary?.degraded) {
|
||||
items.push('已降级')
|
||||
}
|
||||
|
||||
if (payload?.requires_confirmation) {
|
||||
items.push('待确认')
|
||||
}
|
||||
|
||||
if (payload?.run_id) {
|
||||
items.push(`Run: ${payload.run_id}`)
|
||||
}
|
||||
|
||||
return items
|
||||
}
|
||||
|
||||
function buildAssistantMessage(payload, fallbackText) {
|
||||
const result = payload?.result || {}
|
||||
|
||||
return {
|
||||
text: result.answer || result.message || fallbackText,
|
||||
meta: buildOrchestratorMeta(payload),
|
||||
citations: Array.isArray(result.citations) ? result.citations : [],
|
||||
suggestedActions: Array.isArray(result.suggested_actions) ? result.suggested_actions : [],
|
||||
draftPayload: result.draft_payload || null,
|
||||
riskFlags: Array.isArray(result.risk_flags) ? result.risk_flags : []
|
||||
}
|
||||
}
|
||||
|
||||
async function sendMessage() {
|
||||
const text = draft.value.trim()
|
||||
if (!text) return false
|
||||
messages.value.push({ id: Date.now(), role: 'user', text })
|
||||
if (!text || sending.value) return false
|
||||
|
||||
const userMessageId = Date.now()
|
||||
const pendingMessageId = userMessageId + 1
|
||||
messages.value.push({ id: userMessageId, role: 'user', text })
|
||||
draft.value = ''
|
||||
setTimeout(() => {
|
||||
messages.value.push({ id: Date.now() + 1, role: 'agent', text: agentReply(text) })
|
||||
sending.value = true
|
||||
messages.value.push({
|
||||
id: pendingMessageId,
|
||||
role: 'agent',
|
||||
text: 'Orchestrator 正在处理中...',
|
||||
meta: ['运行中']
|
||||
})
|
||||
scrollToBottom()
|
||||
|
||||
const user = currentUser.value || {}
|
||||
|
||||
try {
|
||||
const payload = await runOrchestrator({
|
||||
source: 'user_message',
|
||||
user_id: user.username || user.name || 'anonymous',
|
||||
message: text,
|
||||
context_json: {
|
||||
role_codes: Array.isArray(user.roleCodes) ? user.roleCodes : [],
|
||||
is_admin: Boolean(user.isAdmin),
|
||||
name: user.name || '',
|
||||
role: user.role || '',
|
||||
active_case_id: activeCase.value?.id || ''
|
||||
}
|
||||
})
|
||||
|
||||
const assistantMessage = buildAssistantMessage(payload, 'Orchestrator 已完成处理。')
|
||||
replaceMessage(pendingMessageId, {
|
||||
id: pendingMessageId,
|
||||
role: 'agent',
|
||||
...assistantMessage
|
||||
})
|
||||
} catch (error) {
|
||||
replaceMessage(pendingMessageId, {
|
||||
id: pendingMessageId,
|
||||
role: 'agent',
|
||||
text: `后端暂时不可用,已切换为本地占位回复:${agentReply(text)}`,
|
||||
meta: [error?.message || '后端调用失败'],
|
||||
citations: [],
|
||||
suggestedActions: [],
|
||||
draftPayload: null,
|
||||
riskFlags: []
|
||||
})
|
||||
} finally {
|
||||
sending.value = false
|
||||
scrollToBottom()
|
||||
}, 260)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -96,7 +199,7 @@ export function useChat(activeView) {
|
||||
}
|
||||
|
||||
return {
|
||||
messages, draft, uploadedFiles, messageList, activeCase, prompts,
|
||||
messages, draft, uploadedFiles, messageList, activeCase, prompts, sending,
|
||||
sendMessage, handleUpload, openChat, openNewChat, scrollToBottom
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user