feat: refactor monolithic App.vue into modular Vue component architecture
- Extract 711-line App.vue into 15+ focused files across 5 directories
- Add data layer (icons, metrics, policies, auditTrail, requests)
- Add composables (useNavigation, useRequests, useChat, useToast)
- Add layout components (SidebarRail, TopBar, FilterBar)
- Add shared components (PanelHead, InfoRow, ToastNotification)
- Add business component (RequestTable) and 5 view components
- Extract global CSS to assets/styles/global.css
- Add start.sh with WSL/Windows cross-platform support
- Add .gitignore for node_modules, dist, and IDE dirs
2026-04-28 17:20:52 +08:00
|
|
|
|
import { nextTick, ref } from 'vue'
|
2026-04-30 17:11:05 +08:00
|
|
|
|
|
2026-05-12 01:27:49 +00:00
|
|
|
|
import { useSystemState } from './useSystemState.js'
|
|
|
|
|
|
import { runOrchestrator } from '../services/orchestrator.js'
|
2026-05-30 15:46:51 +08:00
|
|
|
|
import { filterVisibleMessageMeta } from '../utils/assistantMessageMeta.js'
|
2026-05-12 01:27:49 +00:00
|
|
|
|
|
2026-04-30 17:11:05 +08:00
|
|
|
|
const initialMessages = [
|
|
|
|
|
|
{
|
|
|
|
|
|
id: 1,
|
|
|
|
|
|
role: 'agent',
|
|
|
|
|
|
text: '我已读取当前报销、发票、行程和制度命中情况。当前建议:优先处理即将超时与高风险单据。'
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
id: 2,
|
|
|
|
|
|
role: 'user',
|
|
|
|
|
|
text: '请列出今天最需要关注的风险。'
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
id: 3,
|
|
|
|
|
|
role: 'agent',
|
|
|
|
|
|
text: '主要风险包括:3 笔单据将在 30 分钟内超时,市场部存在 2 笔高风险差旅报销,另有 1 笔报销缺少酒店入住清单。'
|
|
|
|
|
|
}
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
export const prompts = ['生成审批意见', '列出补件清单', '解释风险原因', '生成运营简报']
|
feat: refactor monolithic App.vue into modular Vue component architecture
- Extract 711-line App.vue into 15+ focused files across 5 directories
- Add data layer (icons, metrics, policies, auditTrail, requests)
- Add composables (useNavigation, useRequests, useChat, useToast)
- Add layout components (SidebarRail, TopBar, FilterBar)
- Add shared components (PanelHead, InfoRow, ToastNotification)
- Add business component (RequestTable) and 5 view components
- Extract global CSS to assets/styles/global.css
- Add start.sh with WSL/Windows cross-platform support
- Add .gitignore for node_modules, dist, and IDE dirs
2026-04-28 17:20:52 +08:00
|
|
|
|
|
|
|
|
|
|
export function useChat(activeView) {
|
2026-05-12 01:27:49 +00:00
|
|
|
|
const { currentUser } = useSystemState()
|
feat: refactor monolithic App.vue into modular Vue component architecture
- Extract 711-line App.vue into 15+ focused files across 5 directories
- Add data layer (icons, metrics, policies, auditTrail, requests)
- Add composables (useNavigation, useRequests, useChat, useToast)
- Add layout components (SidebarRail, TopBar, FilterBar)
- Add shared components (PanelHead, InfoRow, ToastNotification)
- Add business component (RequestTable) and 5 view components
- Extract global CSS to assets/styles/global.css
- Add start.sh with WSL/Windows cross-platform support
- Add .gitignore for node_modules, dist, and IDE dirs
2026-04-28 17:20:52 +08:00
|
|
|
|
const messages = ref([...initialMessages])
|
|
|
|
|
|
const draft = ref('')
|
|
|
|
|
|
const uploadedFiles = ref([])
|
|
|
|
|
|
const messageList = ref(null)
|
|
|
|
|
|
const activeCase = ref(null)
|
2026-05-12 01:27:49 +00:00
|
|
|
|
const sending = ref(false)
|
feat: refactor monolithic App.vue into modular Vue component architecture
- Extract 711-line App.vue into 15+ focused files across 5 directories
- Add data layer (icons, metrics, policies, auditTrail, requests)
- Add composables (useNavigation, useRequests, useChat, useToast)
- Add layout components (SidebarRail, TopBar, FilterBar)
- Add shared components (PanelHead, InfoRow, ToastNotification)
- Add business component (RequestTable) and 5 view components
- Extract global CSS to assets/styles/global.css
- Add start.sh with WSL/Windows cross-platform support
- Add .gitignore for node_modules, dist, and IDE dirs
2026-04-28 17:20:52 +08:00
|
|
|
|
|
|
|
|
|
|
function agentReply(text) {
|
|
|
|
|
|
const c = activeCase.value
|
2026-04-30 17:11:05 +08:00
|
|
|
|
if (text.includes('超时') || text.includes('SLA')) {
|
|
|
|
|
|
return '当前最紧急的是 3 笔即将超时单据,建议先按剩余处理时长排序,并把缺附件单据转给申请人补齐。'
|
|
|
|
|
|
}
|
|
|
|
|
|
if (text.includes('高风险') || text.includes('风险')) {
|
|
|
|
|
|
return '高风险主要集中在市场部差旅报销,风险点包括住宿超标、重复发票疑似命中、行程说明缺失。建议人工复核后再通过。'
|
|
|
|
|
|
}
|
|
|
|
|
|
if (text.includes('部门')) {
|
|
|
|
|
|
return '从待处理金额看,销售部与研发中心占比最高;从异常占比看,市场部更需要优先关注。'
|
|
|
|
|
|
}
|
|
|
|
|
|
if (text.includes('简报')) {
|
|
|
|
|
|
return '运营简报:今日待审批 12 单,高风险 4 单,平均审批 5.6h,SLA 达成率 96%。建议优先处理差旅报销和即将超时单据。'
|
|
|
|
|
|
}
|
|
|
|
|
|
if (text.includes('补件') || text.includes('附件')) {
|
|
|
|
|
|
return '建议补件清单:酒店入住水单、完整行程单、发票原件或验真结果、直属经理确认记录。'
|
|
|
|
|
|
}
|
|
|
|
|
|
if (text.includes('审批意见')) {
|
|
|
|
|
|
return c
|
|
|
|
|
|
? `${c.id} 建议审批意见:费用归属与预算中心基本匹配,请补充必要说明后通过。`
|
|
|
|
|
|
: '建议审批意见:当前单据存在待确认项,请先完成风险核查和附件补齐后再审批。'
|
|
|
|
|
|
}
|
2026-06-24 10:42:50 +08:00
|
|
|
|
return '收到。我可以继续帮您拆解异常原因、比较部门趋势、生成审批意见,或整理一份今日报销运营简报。'
|
feat: refactor monolithic App.vue into modular Vue component architecture
- Extract 711-line App.vue into 15+ focused files across 5 directories
- Add data layer (icons, metrics, policies, auditTrail, requests)
- Add composables (useNavigation, useRequests, useChat, useToast)
- Add layout components (SidebarRail, TopBar, FilterBar)
- Add shared components (PanelHead, InfoRow, ToastNotification)
- Add business component (RequestTable) and 5 view components
- Extract global CSS to assets/styles/global.css
- Add start.sh with WSL/Windows cross-platform support
- Add .gitignore for node_modules, dist, and IDE dirs
2026-04-28 17:20:52 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function scrollToBottom() {
|
|
|
|
|
|
nextTick(() => messageList.value?.scrollTo({ top: messageList.value.scrollHeight, behavior: 'smooth' }))
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-12 01:27:49 +00:00
|
|
|
|
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?.trace_summary?.degraded) {
|
|
|
|
|
|
items.push('已降级')
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (payload?.requires_confirmation) {
|
|
|
|
|
|
items.push('待确认')
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-30 15:46:51 +08:00
|
|
|
|
return filterVisibleMessageMeta(items)
|
2026-05-12 01:27:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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() {
|
feat: refactor monolithic App.vue into modular Vue component architecture
- Extract 711-line App.vue into 15+ focused files across 5 directories
- Add data layer (icons, metrics, policies, auditTrail, requests)
- Add composables (useNavigation, useRequests, useChat, useToast)
- Add layout components (SidebarRail, TopBar, FilterBar)
- Add shared components (PanelHead, InfoRow, ToastNotification)
- Add business component (RequestTable) and 5 view components
- Extract global CSS to assets/styles/global.css
- Add start.sh with WSL/Windows cross-platform support
- Add .gitignore for node_modules, dist, and IDE dirs
2026-04-28 17:20:52 +08:00
|
|
|
|
const text = draft.value.trim()
|
2026-05-12 01:27:49 +00:00
|
|
|
|
if (!text || sending.value) return false
|
|
|
|
|
|
|
|
|
|
|
|
const userMessageId = Date.now()
|
|
|
|
|
|
const pendingMessageId = userMessageId + 1
|
|
|
|
|
|
messages.value.push({ id: userMessageId, role: 'user', text })
|
feat: refactor monolithic App.vue into modular Vue component architecture
- Extract 711-line App.vue into 15+ focused files across 5 directories
- Add data layer (icons, metrics, policies, auditTrail, requests)
- Add composables (useNavigation, useRequests, useChat, useToast)
- Add layout components (SidebarRail, TopBar, FilterBar)
- Add shared components (PanelHead, InfoRow, ToastNotification)
- Add business component (RequestTable) and 5 view components
- Extract global CSS to assets/styles/global.css
- Add start.sh with WSL/Windows cross-platform support
- Add .gitignore for node_modules, dist, and IDE dirs
2026-04-28 17:20:52 +08:00
|
|
|
|
draft.value = ''
|
2026-05-12 01:27:49 +00:00
|
|
|
|
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 || '',
|
2026-06-01 17:07:14 +08:00
|
|
|
|
department: user.department || user.departmentName || '',
|
|
|
|
|
|
department_name: user.departmentName || user.department || '',
|
2026-05-16 06:14:08 +00:00
|
|
|
|
position: user.position || '',
|
|
|
|
|
|
grade: user.grade || '',
|
2026-06-01 17:07:14 +08:00
|
|
|
|
employee_no: user.employeeNo || '',
|
|
|
|
|
|
manager_name: user.managerName || user.manager_name || '',
|
2026-05-12 01:27:49 +00:00
|
|
|
|
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
|
feat: refactor monolithic App.vue into modular Vue component architecture
- Extract 711-line App.vue into 15+ focused files across 5 directories
- Add data layer (icons, metrics, policies, auditTrail, requests)
- Add composables (useNavigation, useRequests, useChat, useToast)
- Add layout components (SidebarRail, TopBar, FilterBar)
- Add shared components (PanelHead, InfoRow, ToastNotification)
- Add business component (RequestTable) and 5 view components
- Extract global CSS to assets/styles/global.css
- Add start.sh with WSL/Windows cross-platform support
- Add .gitignore for node_modules, dist, and IDE dirs
2026-04-28 17:20:52 +08:00
|
|
|
|
scrollToBottom()
|
2026-05-12 01:27:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
feat: refactor monolithic App.vue into modular Vue component architecture
- Extract 711-line App.vue into 15+ focused files across 5 directories
- Add data layer (icons, metrics, policies, auditTrail, requests)
- Add composables (useNavigation, useRequests, useChat, useToast)
- Add layout components (SidebarRail, TopBar, FilterBar)
- Add shared components (PanelHead, InfoRow, ToastNotification)
- Add business component (RequestTable) and 5 view components
- Extract global CSS to assets/styles/global.css
- Add start.sh with WSL/Windows cross-platform support
- Add .gitignore for node_modules, dist, and IDE dirs
2026-04-28 17:20:52 +08:00
|
|
|
|
return true
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function handleUpload(event) {
|
|
|
|
|
|
uploadedFiles.value = Array.from(event.target.files ?? []).map((file) => ({
|
|
|
|
|
|
name: file.name,
|
|
|
|
|
|
size: file.size
|
|
|
|
|
|
}))
|
|
|
|
|
|
if (uploadedFiles.value.length) {
|
|
|
|
|
|
const names = uploadedFiles.value.map((file) => file.name).join('、')
|
|
|
|
|
|
messages.value.push({
|
|
|
|
|
|
id: Date.now(),
|
|
|
|
|
|
role: 'agent',
|
2026-04-30 17:11:05 +08:00
|
|
|
|
text: `已接收 ${uploadedFiles.value.length} 个附件:${names}。我会优先核对发票验真、费用标准、预算归属和必要审批材料。`
|
feat: refactor monolithic App.vue into modular Vue component architecture
- Extract 711-line App.vue into 15+ focused files across 5 directories
- Add data layer (icons, metrics, policies, auditTrail, requests)
- Add composables (useNavigation, useRequests, useChat, useToast)
- Add layout components (SidebarRail, TopBar, FilterBar)
- Add shared components (PanelHead, InfoRow, ToastNotification)
- Add business component (RequestTable) and 5 view components
- Extract global CSS to assets/styles/global.css
- Add start.sh with WSL/Windows cross-platform support
- Add .gitignore for node_modules, dist, and IDE dirs
2026-04-28 17:20:52 +08:00
|
|
|
|
})
|
|
|
|
|
|
scrollToBottom()
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function openChat(request) {
|
|
|
|
|
|
activeCase.value = request
|
|
|
|
|
|
activeView.value = 'chat'
|
|
|
|
|
|
nextTick(() => messageList.value?.scrollTo({ top: messageList.value.scrollHeight }))
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-29 23:35:56 +08:00
|
|
|
|
function openNewChat() {
|
|
|
|
|
|
activeCase.value = null
|
|
|
|
|
|
activeView.value = 'chat'
|
|
|
|
|
|
}
|
|
|
|
|
|
|
feat: refactor monolithic App.vue into modular Vue component architecture
- Extract 711-line App.vue into 15+ focused files across 5 directories
- Add data layer (icons, metrics, policies, auditTrail, requests)
- Add composables (useNavigation, useRequests, useChat, useToast)
- Add layout components (SidebarRail, TopBar, FilterBar)
- Add shared components (PanelHead, InfoRow, ToastNotification)
- Add business component (RequestTable) and 5 view components
- Extract global CSS to assets/styles/global.css
- Add start.sh with WSL/Windows cross-platform support
- Add .gitignore for node_modules, dist, and IDE dirs
2026-04-28 17:20:52 +08:00
|
|
|
|
return {
|
2026-05-12 01:27:49 +00:00
|
|
|
|
messages, draft, uploadedFiles, messageList, activeCase, prompts, sending,
|
2026-04-29 23:35:56 +08:00
|
|
|
|
sendMessage, handleUpload, openChat, openNewChat, scrollToBottom
|
feat: refactor monolithic App.vue into modular Vue component architecture
- Extract 711-line App.vue into 15+ focused files across 5 directories
- Add data layer (icons, metrics, policies, auditTrail, requests)
- Add composables (useNavigation, useRequests, useChat, useToast)
- Add layout components (SidebarRail, TopBar, FilterBar)
- Add shared components (PanelHead, InfoRow, ToastNotification)
- Add business component (RequestTable) and 5 view components
- Extract global CSS to assets/styles/global.css
- Add start.sh with WSL/Windows cross-platform support
- Add .gitignore for node_modules, dist, and IDE dirs
2026-04-28 17:20:52 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|