feat: 重构报销单AI预审流程并添加平台风险规则引擎
- 将AI验审改为AI预审,高风险不再拦截而是随单流转给审批人复核 - 新增平台风险规则评估引擎,支持事由过短、票据异常、重复发票等多种评估器 - 用户上下文增加部门信息(department_name),认证流程同步关联组织架构 - 规则scenario_json改为中文标签(差旅/费用科目),统一场景分类 - 新增orchestrator审核流程测试用例 - 前端更新审计视图、差旅报销等相关页面
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { computed, ref } from 'vue'
|
||||
import { computed, ref, watch } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
|
||||
import { useNavigation, navItems } from './useNavigation.js'
|
||||
@@ -127,6 +127,14 @@ export function useAppShell() {
|
||||
const logDetailMode = computed(() => route.name === 'app-log-detail')
|
||||
const detailAlerts = computed(() => (detailMode.value ? buildDetailAlerts(selectedRequest.value) : []))
|
||||
|
||||
const requestsListActive = computed(() => activeView.value === 'requests' && !detailMode.value)
|
||||
|
||||
watch(requestsListActive, (isActive, wasActive) => {
|
||||
if (isActive && !wasActive) {
|
||||
void reloadRequests()
|
||||
}
|
||||
})
|
||||
|
||||
const topBarView = computed(() => {
|
||||
if (detailMode.value) {
|
||||
return {
|
||||
@@ -243,7 +251,7 @@ export function useAppShell() {
|
||||
smartEntryOpen.value = false
|
||||
await reloadRequests()
|
||||
if (status === 'submitted') {
|
||||
toast(`${claimNo || '该'}单据已完成 AI验审${approvalStage ? `,当前节点:${approvalStage}` : ',并已提交审批'}。`)
|
||||
toast(`${claimNo || '该'}单据已完成 AI预审${approvalStage ? `,当前节点:${approvalStage}` : ',并已提交审批'}。`)
|
||||
} else {
|
||||
toast(`${claimNo || '该'}单据已保存到草稿,请到报销页面查看。`)
|
||||
}
|
||||
|
||||
@@ -16,9 +16,6 @@ const EXPENSE_TYPE_LABELS = {
|
||||
|
||||
const LOCATION_REQUIRED_EXPENSE_TYPES = new Set([
|
||||
'travel',
|
||||
'hotel',
|
||||
'transport',
|
||||
'meal',
|
||||
'meeting',
|
||||
'entertainment'
|
||||
])
|
||||
@@ -26,7 +23,7 @@ const LOCATION_REQUIRED_EXPENSE_TYPES = new Set([
|
||||
const REIMBURSEMENT_PROGRESS_LABELS = [
|
||||
'保存草稿',
|
||||
'待提交',
|
||||
'AI验审',
|
||||
'AI预审',
|
||||
'直属领导审批',
|
||||
'财务审批',
|
||||
'归档入账'
|
||||
@@ -135,10 +132,10 @@ function resolveWorkflowNode(claim, approvalMeta) {
|
||||
|
||||
if (rawNode) {
|
||||
if (rawNode === '审批流转') {
|
||||
return 'AI验审'
|
||||
return 'AI预审'
|
||||
}
|
||||
if (rawNode === '待补充') {
|
||||
return approvalMeta.key === 'draft' ? '待提交' : 'AI验审'
|
||||
return approvalMeta.key === 'draft' ? '待提交' : 'AI预审'
|
||||
}
|
||||
return rawNode
|
||||
}
|
||||
@@ -151,7 +148,7 @@ function resolveWorkflowNode(claim, approvalMeta) {
|
||||
return '归档入账'
|
||||
}
|
||||
|
||||
return 'AI验审'
|
||||
return 'AI预审'
|
||||
}
|
||||
|
||||
function stringifyRiskFlag(value) {
|
||||
@@ -220,7 +217,7 @@ function resolveProgressCurrentIndex(approvalMeta, workflowNode) {
|
||||
) {
|
||||
return 3
|
||||
}
|
||||
if (normalizedNode.includes('AI验审') || normalizedNode.includes('审批流转')) {
|
||||
if (normalizedNode.includes('AI预审') || normalizedNode.includes('AI验审') || normalizedNode.includes('审批流转')) {
|
||||
return 2
|
||||
}
|
||||
if (normalizedNode.includes('待提交')) {
|
||||
|
||||
@@ -90,6 +90,8 @@ function buildAnonymousUser() {
|
||||
username: '',
|
||||
name: '',
|
||||
role: '',
|
||||
department: '',
|
||||
departmentName: '',
|
||||
position: '',
|
||||
grade: '',
|
||||
roleCodes: [],
|
||||
@@ -107,6 +109,8 @@ function buildLegacyAdminUser(username = '') {
|
||||
username: normalized,
|
||||
name,
|
||||
role: DEFAULT_USER_ROLE,
|
||||
department: '',
|
||||
departmentName: '',
|
||||
position: DEFAULT_USER_ROLE,
|
||||
grade: '',
|
||||
roleCodes: ['manager'],
|
||||
@@ -135,6 +139,8 @@ function readStoredUser() {
|
||||
username,
|
||||
name,
|
||||
role: String(payload.role || DEFAULT_USER_ROLE),
|
||||
department: String(payload.department || payload.departmentName || ''),
|
||||
departmentName: String(payload.departmentName || payload.department || ''),
|
||||
position: String(payload.position || ''),
|
||||
grade: String(payload.grade || ''),
|
||||
roleCodes,
|
||||
|
||||
Reference in New Issue
Block a user