feat: 数字员工财务报告体系与定时提醒及看板快照调度
- 新增数字员工财务报告生成、邮件投递与渲染调度器 - 引入员工画像扫描调度与定时提醒任务 - 完善财务看板快照、排行口径与部门人员占比计算 - 优化数字员工工作看板仪表盘与技能目录 - 增强前端总览页图表、工作台摘要与顶部导航栏交互 - 新增差旅申请规划推动提醒与报销创建会话状态管理 - 补充财务报告、看板调度、数字员工工作记录测试覆盖
This commit is contained in:
@@ -49,6 +49,13 @@ import {
|
||||
buildLocalApplicationPreviewMessage,
|
||||
normalizeApplicationPreview
|
||||
} from '../../utils/expenseApplicationPreview.js'
|
||||
import {
|
||||
TRAVEL_PLANNING_ACTION_GENERATE,
|
||||
TRAVEL_PLANNING_ACTION_SKIP,
|
||||
buildTravelPlanningNudgeMessage,
|
||||
buildTravelPlanningRecommendation,
|
||||
buildTravelPlanningSuggestedActions
|
||||
} from '../../utils/travelApplicationPlanning.js'
|
||||
import {
|
||||
calculateTravelReimbursement,
|
||||
createExpenseClaimItem,
|
||||
@@ -524,6 +531,14 @@ export default {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
initialPromptAutoSubmit: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
initialApplicationPreview: {
|
||||
type: Object,
|
||||
default: null
|
||||
},
|
||||
initialFiles: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
@@ -629,7 +644,9 @@ export default {
|
||||
handleApplicationPreviewEditorKeydown
|
||||
} = useApplicationPreviewEditor({
|
||||
persistSessionState,
|
||||
toast
|
||||
toast,
|
||||
calculateTravelReimbursement,
|
||||
currentUser
|
||||
})
|
||||
|
||||
function applyLinkedApplicationPreviewDateSelection(selection) {
|
||||
@@ -1372,6 +1389,14 @@ export default {
|
||||
currentInsight.value =
|
||||
currentInsight.value
|
||||
|| buildWelcomeInsight(props.entrySource, linkedRequest.value, activeSessionType.value, currentUser.value)
|
||||
if (props.initialApplicationPreview && typeof props.initialApplicationPreview === 'object') {
|
||||
const applicationPreview = normalizeApplicationPreview(props.initialApplicationPreview)
|
||||
messages.value.push(createMessage('assistant', buildLocalApplicationPreviewMessage(applicationPreview), [], {
|
||||
meta: ['修改申请'],
|
||||
applicationPreview
|
||||
}))
|
||||
persistSessionState()
|
||||
}
|
||||
if (props.initialPrompt?.trim() || props.initialFiles.length) {
|
||||
const initialMerge = mergeFilesWithLimit([], Array.from(props.initialFiles), MAX_ATTACHMENTS)
|
||||
composerDraft.value = props.initialPrompt.trim()
|
||||
@@ -1380,7 +1405,12 @@ export default {
|
||||
if (initialMerge.overflowCount > 0) {
|
||||
toast(`一次最多上传 ${MAX_ATTACHMENTS} 份附件,已保留前 ${MAX_ATTACHMENTS} 份。`)
|
||||
}
|
||||
submitComposer()
|
||||
nextTick(() => {
|
||||
adjustComposerTextareaHeight()
|
||||
})
|
||||
if (props.initialPromptAutoSubmit !== false) {
|
||||
submitComposer()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -1576,6 +1606,32 @@ export default {
|
||||
if (await handleGuidedSuggestedAction(message, action)) return
|
||||
if (await handleSceneSelectionApplicationGate(message, action)) return
|
||||
|
||||
if (actionType === TRAVEL_PLANNING_ACTION_GENERATE) {
|
||||
if (!lockSuggestedActionMessage(message, action)) return
|
||||
const sourcePreview = action?.payload?.applicationPreview || action?.payload?.preview || null
|
||||
const sourceDraftPayload = action?.payload?.draftPayload || action?.payload?.draft_payload || null
|
||||
const recommendation = buildTravelPlanningRecommendation(sourcePreview, sourceDraftPayload)
|
||||
if (recommendation) {
|
||||
messages.value.push(createMessage('user', '生成行程规划'))
|
||||
messages.value.push(createMessage('assistant', recommendation, [], {
|
||||
meta: ['行程规划建议']
|
||||
}))
|
||||
nextTick(scrollToBottom)
|
||||
persistSessionState()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if (actionType === TRAVEL_PLANNING_ACTION_SKIP) {
|
||||
if (!lockSuggestedActionMessage(message, action)) return
|
||||
messages.value.push(createMessage('assistant', '好的,本次先保留申请结果。后续需要规划交通或酒店时,可以继续在这里告诉我。', [], {
|
||||
meta: ['暂不规划']
|
||||
}))
|
||||
nextTick(scrollToBottom)
|
||||
persistSessionState()
|
||||
return
|
||||
}
|
||||
|
||||
if (actionType === ASSISTANT_SCOPE_ACTION_SWITCH) {
|
||||
const actionPayload = action?.payload && typeof action.payload === 'object' ? action.payload : {}
|
||||
const targetSessionType = String(actionPayload.session_type || '').trim()
|
||||
@@ -2033,6 +2089,17 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
function resolveApplicationEditClaimId() {
|
||||
if (activeSessionType.value !== SESSION_TYPE_APPLICATION) {
|
||||
return ''
|
||||
}
|
||||
const request = linkedRequest.value || {}
|
||||
if (!request.applicationEditMode) {
|
||||
return ''
|
||||
}
|
||||
return String(request.claimId || request.claim_id || '').trim()
|
||||
}
|
||||
|
||||
async function confirmApplicationSubmit() {
|
||||
const message = applicationSubmitConfirmDialog.value.message
|
||||
if (!message || submitting.value || reviewActionBusy.value) {
|
||||
@@ -2044,6 +2111,7 @@ export default {
|
||||
const applicationSubmitText = applicationPreview
|
||||
? buildApplicationPreviewSubmitText(applicationPreview)
|
||||
: '确认提交'
|
||||
const applicationEditClaimId = resolveApplicationEditClaimId()
|
||||
applicationSubmitConfirmDialog.value = {
|
||||
open: false,
|
||||
message: null
|
||||
@@ -2059,7 +2127,16 @@ export default {
|
||||
feedbackOperationType: 'submit_application',
|
||||
extraContext: {
|
||||
application_preview: applicationPreview,
|
||||
user_input_text: applicationSubmitText
|
||||
user_input_text: applicationSubmitText,
|
||||
...(applicationEditClaimId
|
||||
? {
|
||||
application_edit_claim_id: applicationEditClaimId,
|
||||
application_edit_claim_no: String(linkedRequest.value?.claimNo || linkedRequest.value?.id || '').trim(),
|
||||
application_edit_mode: true,
|
||||
draft_claim_id: applicationEditClaimId,
|
||||
selected_claim_id: applicationEditClaimId
|
||||
}
|
||||
: {})
|
||||
}
|
||||
})
|
||||
const draftPayload = payload?.result?.draft_payload || {}
|
||||
@@ -2074,6 +2151,23 @@ export default {
|
||||
documentType: 'application'
|
||||
})
|
||||
}
|
||||
const planningText = buildTravelPlanningNudgeMessage(applicationPreview, draftPayload)
|
||||
const planningActions = buildTravelPlanningSuggestedActions(applicationPreview, draftPayload).map((action) => ({
|
||||
...action,
|
||||
payload: {
|
||||
...(action.payload || {}),
|
||||
applicationPreview,
|
||||
draftPayload
|
||||
}
|
||||
}))
|
||||
if (planningText && planningActions.length) {
|
||||
messages.value.push(createMessage('assistant', planningText, [], {
|
||||
meta: ['行程规划推荐'],
|
||||
suggestedActions: planningActions
|
||||
}))
|
||||
persistSessionState()
|
||||
nextTick(scrollToBottom)
|
||||
}
|
||||
} finally {
|
||||
reviewActionBusy.value = false
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user