feat: 本体字段治理与风险规则模板执行器重构
- 新增本体字段注册表与字段治理审计脚本 - 重构风险规则模板执行器、DSL 验证与清单分类器 - 完善票据夹服务与差旅请求详情页交互 - 优化趋势图表与总览页数据展示 - 增强报销平台风险分级与模拟公司筛选 - 补充本体字段、风险规则生成与票据夹服务测试覆盖
This commit is contained in:
@@ -126,9 +126,9 @@
|
||||
</p>
|
||||
</div>
|
||||
<div v-if="!isApplicationDocument" class="detail-card-actions">
|
||||
<button v-if="canOpenAiEntry" class="smart-entry-btn" type="button" @click="openAiEntry">
|
||||
<button v-if="canOpenAiEntry" class="smart-entry-btn" type="button" :disabled="actionBusy" @click="triggerSmartEntryUpload">
|
||||
<i class="mdi mdi-robot-outline"></i>
|
||||
<span>智能录入</span>
|
||||
<span>{{ uploadingExpenseId ? '识别中' : '智能录入' }}</span>
|
||||
</button>
|
||||
<button
|
||||
v-if="isEditableRequest"
|
||||
@@ -190,6 +190,10 @@
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!isApplicationDocument" class="detail-expense-table">
|
||||
<div v-if="smartEntryRecognitionBusy" class="expense-recognition-banner">
|
||||
<i class="mdi mdi-loading mdi-spin"></i>
|
||||
<span>{{ smartEntryRecognitionText }}</span>
|
||||
</div>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -199,6 +203,7 @@
|
||||
<th class="col-desc">说明</th>
|
||||
<th class="col-amount">金额</th>
|
||||
<th class="col-attachment">附件材料</th>
|
||||
<th class="col-risk-note">异常说明</th>
|
||||
<th v-if="isEditableRequest" class="col-action">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -209,13 +214,17 @@
|
||||
<strong>{{ item.filledAt }}</strong>
|
||||
<span>条款填写时间</span>
|
||||
</td>
|
||||
<td :class="['expense-time col-time', { 'has-major-risk': isMajorExpenseRisk(item) }]">
|
||||
<i
|
||||
v-if="isMajorExpenseRisk(item)"
|
||||
class="mdi mdi-alert expense-risk-indicator"
|
||||
<td :class="['expense-time col-time', { 'has-major-risk': hasExpenseRiskIndicator(item) }]">
|
||||
<button
|
||||
v-if="hasExpenseRiskIndicator(item)"
|
||||
class="expense-risk-indicator"
|
||||
type="button"
|
||||
:title="resolveExpenseRiskIndicatorTitle(item)"
|
||||
:aria-label="resolveExpenseRiskIndicatorTitle(item)"
|
||||
></i>
|
||||
@click="focusExpenseRisk(item)"
|
||||
>
|
||||
<i class="mdi mdi-alert"></i>
|
||||
</button>
|
||||
<template v-if="editingExpenseId === item.id">
|
||||
<div class="cell-editor">
|
||||
<input v-model="expenseEditor.itemDate" class="editor-input" type="date" />
|
||||
@@ -281,6 +290,10 @@
|
||||
<td class="expense-attachment col-attachment">
|
||||
<template v-if="editingExpenseId === item.id">
|
||||
<div class="cell-editor editor-stack">
|
||||
<div v-if="uploadingExpenseId === item.id" class="system-attachment-note pending">
|
||||
<i class="mdi mdi-loading mdi-spin"></i>
|
||||
<span>识别中</span>
|
||||
</div>
|
||||
<div class="attachment-action-group">
|
||||
<button
|
||||
v-if="isEditableRequest && !item.invoiceId && !item.isSystemGenerated"
|
||||
@@ -318,7 +331,11 @@
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div v-if="item.isSystemGenerated" class="system-attachment-note">
|
||||
<div v-if="uploadingExpenseId === item.id" class="system-attachment-note pending">
|
||||
<i class="mdi mdi-loading mdi-spin"></i>
|
||||
<span>识别中</span>
|
||||
</div>
|
||||
<div v-else-if="item.isSystemGenerated" class="system-attachment-note">
|
||||
<i class="mdi mdi-calculator-variant-outline"></i>
|
||||
<span>无需附件</span>
|
||||
</div>
|
||||
@@ -358,6 +375,24 @@
|
||||
</div>
|
||||
</template>
|
||||
</td>
|
||||
<td class="expense-risk-note col-risk-note">
|
||||
<template v-if="editingExpenseId === item.id">
|
||||
<div class="cell-editor">
|
||||
<textarea
|
||||
v-model="expenseEditor.itemNote"
|
||||
class="editor-textarea"
|
||||
rows="3"
|
||||
placeholder="如票据存在异常或风险,请补充原因"
|
||||
></textarea>
|
||||
<span>用于说明改签、绕行、超标、票据异常等情况</span>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<strong v-if="item.itemNote">{{ item.itemNote }}</strong>
|
||||
<span v-else-if="hasExpenseRiskOrAbnormal(item)" class="risk-note-missing">待补充异常说明</span>
|
||||
<span v-else>无异常说明</span>
|
||||
</template>
|
||||
</td>
|
||||
<td v-if="isEditableRequest" class="expense-action-cell col-action">
|
||||
<div v-if="item.isSystemGenerated" class="system-row-lock">
|
||||
<i class="mdi mdi-lock-outline"></i>
|
||||
@@ -438,7 +473,9 @@
|
||||
<article
|
||||
v-for="card in section.items"
|
||||
:key="card.id"
|
||||
:class="['risk-advice-card', card.tone]"
|
||||
:id="resolveRiskCardDomId(card)"
|
||||
:data-risk-card-id="card.id"
|
||||
:class="['risk-advice-card', card.tone, { 'is-highlighted': isHighlightedRiskCard(card) }]"
|
||||
>
|
||||
<div class="risk-advice-card-main">
|
||||
<div class="risk-advice-card-head">
|
||||
@@ -545,6 +582,58 @@
|
||||
accept="image/*,.pdf"
|
||||
@change="handleExpenseFileChange"
|
||||
/>
|
||||
<input
|
||||
ref="smartEntryUploadInput"
|
||||
class="expense-upload-input"
|
||||
type="file"
|
||||
accept="image/*,.pdf"
|
||||
multiple
|
||||
@change="handleSmartEntryFileChange"
|
||||
/>
|
||||
<ConfirmDialog
|
||||
:open="smartEntryUploadDialogOpen"
|
||||
badge="智能录入"
|
||||
title="上传报销附件"
|
||||
description="请选择需要识别并归集到当前草稿的票据附件,确认前可以清除或重新选择。"
|
||||
cancel-text="取消"
|
||||
confirm-text="确认识别"
|
||||
busy-text="识别中"
|
||||
confirm-icon="mdi mdi-file-search-outline"
|
||||
:busy="smartEntryUploadBusy"
|
||||
@close="closeSmartEntryUploadDialog"
|
||||
@confirm="confirmSmartEntryUpload"
|
||||
>
|
||||
<div class="smart-entry-upload-panel">
|
||||
<button
|
||||
class="smart-entry-upload-picker"
|
||||
type="button"
|
||||
:disabled="smartEntryUploadBusy"
|
||||
@click="chooseSmartEntryFile"
|
||||
>
|
||||
<i class="mdi mdi-tray-arrow-up"></i>
|
||||
<span>{{ smartEntrySelectedFileCount ? '重新选择附件' : '选择附件' }}</span>
|
||||
</button>
|
||||
<div class="smart-entry-upload-file">
|
||||
<i :class="smartEntrySelectedFileCount ? 'mdi mdi-file-check-outline' : 'mdi mdi-file-outline'"></i>
|
||||
<div>
|
||||
<strong>{{ smartEntrySelectedFileSummary || '尚未选择附件' }}</strong>
|
||||
<span>支持 JPG、PNG、PDF;确认后系统会逐张识别并归集到草稿明细。</span>
|
||||
<ul v-if="smartEntrySelectedFileNames.length" class="smart-entry-upload-list">
|
||||
<li v-for="fileName in smartEntrySelectedFileNames" :key="fileName">{{ fileName }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
<button
|
||||
v-if="smartEntrySelectedFileCount"
|
||||
class="smart-entry-upload-clear"
|
||||
type="button"
|
||||
:disabled="smartEntryUploadBusy"
|
||||
@click="clearSmartEntryFile"
|
||||
>
|
||||
清除
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</ConfirmDialog>
|
||||
<Transition name="shared-confirm">
|
||||
<div
|
||||
v-if="attachmentPreviewOpen"
|
||||
|
||||
Reference in New Issue
Block a user