feat: 新增风险图谱算法与系统仪表盘及操作反馈体系
后端新增风险图谱算法模块、风险观察与反馈服务、规则 DSL 校验器和可解释性引擎,完善系统仪表盘和财务仪表盘统计, 优化 agent 运行和编排执行链路,清理旧开发文档,前端新增 系统趋势、负载热力图等多种仪表盘图表组件,完善操作反馈 对话框和工作台日期选择器,优化报销创建和审批详情交互, 补充单元测试覆盖。
This commit is contained in:
@@ -6,20 +6,48 @@ import {
|
||||
buildLocalApplicationPreviewMessage,
|
||||
normalizeApplicationPreview
|
||||
} from '../../utils/expenseApplicationPreview.js'
|
||||
import {
|
||||
buildWorkbenchDateLabel,
|
||||
canApplyWorkbenchDateSelection,
|
||||
getTodayDateValue
|
||||
} from '../../utils/workbenchComposerDate.js'
|
||||
|
||||
export function useApplicationPreviewEditor({ persistSessionState, toast } = {}) {
|
||||
const applicationPreviewEditor = ref({
|
||||
function parseEditorDateValue(value) {
|
||||
const text = String(value || '').trim()
|
||||
const matches = [...text.matchAll(/20\d{2}-\d{1,2}-\d{1,2}/g)].map((item) => item[0])
|
||||
const startDate = matches[0] || getTodayDateValue()
|
||||
const endDate = matches[1] || startDate
|
||||
return {
|
||||
dateMode: matches.length > 1 && startDate !== endDate ? 'range' : 'single',
|
||||
singleDate: startDate,
|
||||
rangeStartDate: startDate,
|
||||
rangeEndDate: endDate
|
||||
}
|
||||
}
|
||||
|
||||
function buildEmptyEditor() {
|
||||
return {
|
||||
messageId: '',
|
||||
fieldKey: '',
|
||||
draftValue: ''
|
||||
})
|
||||
draftValue: '',
|
||||
dateMode: 'single',
|
||||
singleDate: getTodayDateValue(),
|
||||
rangeStartDate: getTodayDateValue(),
|
||||
rangeEndDate: getTodayDateValue()
|
||||
}
|
||||
}
|
||||
|
||||
export function useApplicationPreviewEditor({ persistSessionState, toast } = {}) {
|
||||
const applicationPreviewEditor = ref(buildEmptyEditor())
|
||||
|
||||
function resolveApplicationPreviewRows(message) {
|
||||
return buildApplicationPreviewRows(message?.applicationPreview || {})
|
||||
}
|
||||
|
||||
function resolveApplicationPreviewEditorControl(fieldKey) {
|
||||
return fieldKey === 'transportMode' ? 'select' : 'text'
|
||||
if (fieldKey === 'transportMode') return 'select'
|
||||
if (fieldKey === 'time') return 'date'
|
||||
return 'text'
|
||||
}
|
||||
|
||||
function resolveApplicationPreviewEditorOptions(fieldKey) {
|
||||
@@ -39,21 +67,47 @@ export function useApplicationPreviewEditor({ persistSessionState, toast } = {})
|
||||
.find((row) => row.key === fieldKey)
|
||||
if (targetRow && targetRow.editable === false) return
|
||||
const normalizedValue = String(value || '').trim() === '待补充' ? '' : String(value || '')
|
||||
const dateState = fieldKey === 'time' ? parseEditorDateValue(normalizedValue) : {}
|
||||
applicationPreviewEditor.value = {
|
||||
messageId: String(message.id || ''),
|
||||
fieldKey,
|
||||
draftValue: fieldKey === 'transportMode' && !APPLICATION_TRANSPORT_MODE_OPTIONS.includes(normalizedValue)
|
||||
? ''
|
||||
: normalizedValue
|
||||
: normalizedValue,
|
||||
...dateState
|
||||
}
|
||||
}
|
||||
|
||||
function cancelApplicationPreviewEditor() {
|
||||
applicationPreviewEditor.value = {
|
||||
messageId: '',
|
||||
fieldKey: '',
|
||||
draftValue: ''
|
||||
}
|
||||
applicationPreviewEditor.value = buildEmptyEditor()
|
||||
}
|
||||
|
||||
function isApplicationPreviewDateEditorOpen(message) {
|
||||
return isApplicationPreviewEditing(message, 'time')
|
||||
}
|
||||
|
||||
function setApplicationPreviewDateMode(mode) {
|
||||
applicationPreviewEditor.value.dateMode = mode === 'range' ? 'range' : 'single'
|
||||
}
|
||||
|
||||
function canApplyApplicationPreviewDateSelection() {
|
||||
const editor = applicationPreviewEditor.value
|
||||
return canApplyWorkbenchDateSelection({
|
||||
mode: editor.dateMode,
|
||||
singleDate: editor.singleDate,
|
||||
rangeStartDate: editor.rangeStartDate,
|
||||
rangeEndDate: editor.rangeEndDate
|
||||
})
|
||||
}
|
||||
|
||||
function buildApplicationPreviewDateDraftValue() {
|
||||
const editor = applicationPreviewEditor.value
|
||||
return buildWorkbenchDateLabel({
|
||||
mode: editor.dateMode,
|
||||
singleDate: editor.singleDate,
|
||||
rangeStartDate: editor.rangeStartDate,
|
||||
rangeEndDate: editor.rangeEndDate
|
||||
})
|
||||
}
|
||||
|
||||
function commitApplicationPreviewEditor(message) {
|
||||
@@ -63,7 +117,13 @@ export function useApplicationPreviewEditor({ persistSessionState, toast } = {})
|
||||
return false
|
||||
}
|
||||
|
||||
const nextValue = String(editor.draftValue || '').trim()
|
||||
const nextValue = editor.fieldKey === 'time'
|
||||
? buildApplicationPreviewDateDraftValue()
|
||||
: String(editor.draftValue || '').trim()
|
||||
if (editor.fieldKey === 'time' && !nextValue) {
|
||||
toast?.('请先选择有效日期。')
|
||||
return false
|
||||
}
|
||||
const nextPreview = normalizeApplicationPreview({
|
||||
...message.applicationPreview,
|
||||
fields: {
|
||||
@@ -79,6 +139,14 @@ export function useApplicationPreviewEditor({ persistSessionState, toast } = {})
|
||||
return true
|
||||
}
|
||||
|
||||
function commitApplicationPreviewDateEditor(message) {
|
||||
if (!canApplyApplicationPreviewDateSelection()) {
|
||||
toast?.('请确认结束日期不早于开始日期。')
|
||||
return false
|
||||
}
|
||||
return commitApplicationPreviewEditor(message)
|
||||
}
|
||||
|
||||
function handleApplicationPreviewEditorKeydown(event, message) {
|
||||
if (event.key === 'Enter') {
|
||||
event.preventDefault()
|
||||
@@ -97,9 +165,13 @@ export function useApplicationPreviewEditor({ persistSessionState, toast } = {})
|
||||
resolveApplicationPreviewEditorControl,
|
||||
resolveApplicationPreviewEditorOptions,
|
||||
isApplicationPreviewEditing,
|
||||
isApplicationPreviewDateEditorOpen,
|
||||
openApplicationPreviewEditor,
|
||||
commitApplicationPreviewEditor,
|
||||
commitApplicationPreviewDateEditor,
|
||||
cancelApplicationPreviewEditor,
|
||||
setApplicationPreviewDateMode,
|
||||
canApplyApplicationPreviewDateSelection,
|
||||
handleApplicationPreviewEditorKeydown
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user