feat: 优化差旅报销预审流程与个人工作台 UI 体系

- 完善 user_agent_application 申请差旅报销预审槽位与消息组装
- 增强预算助理报告与风险建议卡片交互
- 重构登录页视觉样式与移动端响应式适配
- 优化个人工作台、文档中心、政策中心、员工管理等页面布局
- 拆分 travelRequestDetailPreReviewModel 为 advice/submit 模型
- 补充报销草稿、风险复核、Item Sync 与模板执行器测试覆盖
This commit is contained in:
caoxiaozhu
2026-06-02 14:01:51 +08:00
parent 92444e7eae
commit ca691f3ee0
107 changed files with 5663 additions and 1542 deletions

View File

@@ -16,7 +16,7 @@ export const APPLICATION_PREVIEW_FIELD_DEFINITIONS = [
{ key: 'department', label: '部门', editable: false, required: false },
{ key: 'position', label: '岗位', editable: false, required: false },
{ key: 'managerName', label: '直属领导', editable: false, required: false },
{ key: 'time', label: '发生时间' },
{ key: 'time', label: '申请时间' },
{ key: 'location', label: '地点' },
{ key: 'reason', label: '事由' },
{ key: 'days', label: '天数' },
@@ -33,6 +33,20 @@ export const APPLICATION_TRANSPORT_MODE_OPTIONS = ['火车', '飞机', '轮船']
const APPLICATION_POLICY_PENDING_TEXT = '填写地点和天数后自动测算'
const APPLICATION_TRANSPORT_REIMBURSEMENT_TEXT = '选择火车、飞机或轮船后自动生成交通参考票价,报销阶段按真实票据复核'
export function resolveApplicationTimeLabel(applicationType = '') {
const label = String(applicationType || '').trim()
if (/差旅|出差/.test(label)) return '行程时间'
if (/招待|宴请|餐饮/.test(label)) return '招待时间'
return '申请时间'
}
function resolveApplicationFieldLabel(item, fields = {}) {
if (item.key === 'time') {
return resolveApplicationTimeLabel(fields.applicationType)
}
return item.label
}
function compactText(value) {
return String(value || '').replace(/\s+/g, '')
}
@@ -374,7 +388,7 @@ function buildMissingFields(fields) {
return APPLICATION_PREVIEW_FIELD_DEFINITIONS
.filter((item) => item.key !== 'applicationType' && item.required !== false)
.filter((item) => !isApplicationPreviewValueProvided(fields?.[item.key]))
.map((item) => item.label)
.map((item) => resolveApplicationFieldLabel(item, fields))
}
export function buildApplicationPolicyEstimateRequest(preview = {}, currentUser = {}) {
@@ -551,6 +565,38 @@ export function normalizeApplicationPreview(preview = {}) {
}
}
export function applyApplicationBusinessTimeContext(preview = {}, businessTimeContext = null) {
if (!businessTimeContext || typeof businessTimeContext !== 'object') {
return normalizeApplicationPreview(preview)
}
const startDate = String(businessTimeContext.start_date || '').trim()
const endDate = String(businessTimeContext.end_date || startDate).trim()
const displayValue = String(
businessTimeContext.business_time ||
businessTimeContext.time_range ||
businessTimeContext.display_value ||
''
).trim()
const time = startDate && endDate
? (startDate === endDate ? startDate : `${startDate}${endDate}`)
: displayValue
if (!time) {
return normalizeApplicationPreview(preview)
}
const normalized = normalizeApplicationPreview(preview)
const fields = normalized.fields || {}
return normalizeApplicationPreview({
...normalized,
fields: {
...fields,
time,
days: resolveDaysFromDateRange(time) || fields.days
}
})
}
export function buildModelRefinedApplicationPreview(localPreview = {}, ontology = {}, rawText = '', currentUser = {}) {
const currentFields = localPreview?.fields || {}
const ontologyFields = buildApplicationFieldsFromOntology(ontology || {}, rawText, currentUser)
@@ -598,6 +644,7 @@ export function buildApplicationPreviewRows(preview = {}) {
const value = String(rawValue || '').trim() || '待补充'
return {
...item,
label: resolveApplicationFieldLabel(item, fields),
value,
editable: item.editable !== false,
highlight: Boolean(item.highlight),