推送项目重构代码
This commit is contained in:
@@ -9,10 +9,6 @@
|
||||
</div>
|
||||
|
||||
<el-form ref="formRef" :model="form" :rules="rules" label-width="120px" size="small" class="metal-form">
|
||||
<el-alert v-if="ocrAvailable === false" type="error" :closable="false" show-icon style="margin-bottom:14px">
|
||||
<span slot="title">发票识别服务已停止,请联系信息化部门。在服务恢复前,您暂时无法上传发票附件。</span>
|
||||
</el-alert>
|
||||
|
||||
<div class="form-summary">
|
||||
<div class="summary-left">
|
||||
<div class="summary-title">发起日常报销</div>
|
||||
@@ -57,27 +53,27 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!-- 报销单据附件(OCR触发区) -->
|
||||
<!-- 报销单据附件(仅 PDF 电子发票) -->
|
||||
<el-form-item label="报销单据附件" prop="accessoryApplyIds">
|
||||
<file-upload v-model="form.accessoryApplyIds" :limit="200" :file-size="50"
|
||||
:file-type="['pdf', 'jpg', 'jpeg', 'png', 'doc', 'docx']" multiple
|
||||
:disabled="ocrAvailable === false"
|
||||
:file-type="['pdf']" multiple
|
||||
@delete="onFileDelete" />
|
||||
<div class="hint-text">
|
||||
{{ ocrAvailable === false ? '识别服务不可用,暂时无法上传' : '上传发票、收据、付款截图等(支持 PDF/图片,上传后自动识别明细)' }}
|
||||
仅支持 PDF 电子发票(含数电票/电子普通发票/电子专用发票),上传后自动解析金额与明细。<br/>
|
||||
扫描件 / 图片票 / 纸质票请先在开票平台下载 PDF 原件再上传。
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<!-- OCR 识别中提示 -->
|
||||
<!-- 发票解析中提示 -->
|
||||
<div v-if="anyOcrLoading" class="ocr-thinking">
|
||||
<i class="el-icon-loading"></i>
|
||||
<span>模型思考中,正在识别发票内容…</span>
|
||||
<span>正在解析发票 PDF…</span>
|
||||
</div>
|
||||
|
||||
<!-- 发票明细条目表 -->
|
||||
<div class="block-title">
|
||||
发票明细
|
||||
<span class="block-title-hint">(上传发票后自动识别;识别失败或无发票时可手动添加)</span>
|
||||
<span class="block-title-hint">(上传 PDF 后自动解析;解析失败或无发票时可手动添加)</span>
|
||||
<el-button size="mini" type="primary" plain icon="el-icon-plus" @click="addManualItem" style="margin-left:12px;vertical-align:middle">手动添加条目</el-button>
|
||||
</div>
|
||||
<div class="invoice-table" v-if="invoiceItems.length">
|
||||
@@ -108,7 +104,7 @@
|
||||
</el-tooltip>
|
||||
<el-upload v-else :action="uploadFileUrl" :headers="uploadHeaders" :show-file-list="false"
|
||||
:data="{ isPublic: 1 }" :on-success="(res) => onRowFileSuccess(res, idx)"
|
||||
accept=".pdf,.jpg,.jpeg,.png" class="row-upload">
|
||||
accept=".pdf" class="row-upload">
|
||||
<el-button size="mini" type="text" icon="el-icon-paperclip"></el-button>
|
||||
</el-upload>
|
||||
</div>
|
||||
@@ -243,15 +239,17 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { addReimburseReq, checkReimburseOcrHealth, listFlowNode, listFlowTemplate, ocrReimburseInvoice } from '@/api/hrm';
|
||||
import { addReimburseReq, listFlowNode, listFlowTemplate, ocrReimburseInvoice } from '@/api/hrm';
|
||||
import { getEmployeeByUserId } from '@/api/hrm/employee';
|
||||
import { ccFlowTask } from '@/api/hrm/flow';
|
||||
import FileUpload from '@/components/FileUpload';
|
||||
import { getToken } from '@/utils/auth';
|
||||
import UserMultiSelect from '@/components/UserSelect/multi.vue';
|
||||
import UserSelect from '@/components/UserSelect/single.vue';
|
||||
import approverNameMixin from '@/views/hrm/minix/approverNameMixin.js';
|
||||
|
||||
export default {
|
||||
mixins: [approverNameMixin],
|
||||
name: 'HrmReimburseRequest',
|
||||
components: { FileUpload, UserSelect, UserMultiSelect },
|
||||
data () {
|
||||
@@ -267,8 +265,6 @@ export default {
|
||||
assigneeUserId: null,
|
||||
assigneeUserName: '',
|
||||
reimburseTypeOptions: ['差旅费', '招待费', '办公费', '交通费', '通讯费', '其他'],
|
||||
// OCR服务状态:null=检测中,true=正常,false=不可用
|
||||
ocrAvailable: null,
|
||||
uploadFileUrl: process.env.VUE_APP_BASE_API + '/system/oss/upload',
|
||||
uploadHeaders: { Authorization: 'Bearer ' + getToken() },
|
||||
// 发票明细条目
|
||||
@@ -308,7 +304,7 @@ export default {
|
||||
created () {
|
||||
this.loadCurrentEmployee()
|
||||
this.loadTemplates()
|
||||
this.checkOcrHealth()
|
||||
this.loadUserNameMap()
|
||||
},
|
||||
computed: {
|
||||
currentApplicantText () {
|
||||
@@ -346,15 +342,6 @@ export default {
|
||||
onCcUsersSelected (users) { this.ccForm.selectedUsers = users || [] },
|
||||
removeCcUser (user) { this.ccForm.selectedUsers = this.ccForm.selectedUsers.filter(u => u.userId !== user.userId) },
|
||||
|
||||
async checkOcrHealth () {
|
||||
try {
|
||||
const res = await checkReimburseOcrHealth()
|
||||
this.ocrAvailable = res.code === 200 && res.data === true
|
||||
} catch (e) {
|
||||
this.ocrAvailable = false
|
||||
}
|
||||
},
|
||||
|
||||
async triggerOcr (ossId) {
|
||||
if (this.ocrDoneSet.has(ossId)) return
|
||||
this.ocrDoneSet.add(ossId)
|
||||
@@ -396,8 +383,12 @@ export default {
|
||||
this.invoiceItems.push({ ossId: ossId, itemName: '', reason: '', amount: 0, sortNo: this.invoiceItems.length })
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('[OCR] 识别失败', e)
|
||||
this.$message.warning('发票识别失败,请手动填写事由和金额')
|
||||
console.error('[Invoice] 解析失败', e)
|
||||
const msg = (e && e.msg) || (e && e.message) || ''
|
||||
this.$message.warning(
|
||||
'发票解析失败,请确认上传的是开票平台下载的正规 PDF 电子发票(数电票 / 电子普通发票 / 电子专用发票)。' +
|
||||
(msg ? ' 错误信息:' + msg : '')
|
||||
)
|
||||
this.invoiceItems.push({ ossId: ossId, itemName: '', reason: '', amount: 0, sortNo: this.invoiceItems.length })
|
||||
} finally {
|
||||
this.$set(this.ocrLoadingMap, ossId, false)
|
||||
@@ -469,19 +460,6 @@ export default {
|
||||
this.flowLoading = false
|
||||
}
|
||||
},
|
||||
nodePreviewText (n, idx) {
|
||||
const typeMap = { approve: '审批', cc: '抄送' }
|
||||
const ruleMap = { fixed_user: '指定人员', role: '指定角色', position: '指定岗位', leader: '直属上级' }
|
||||
const nodeType = typeMap[n.nodeType] || '节点'
|
||||
const rule = ruleMap[n.approverRule] || '规则'
|
||||
let detail = ''
|
||||
try {
|
||||
const arr = Array.isArray(n.approverValue) ? n.approverValue : JSON.parse(n.approverValue || '[]')
|
||||
if (arr.length) detail = `:${arr.join('、')}`
|
||||
} catch (e) { detail = n.approverValue ? `:${n.approverValue}` : '' }
|
||||
const text = `${nodeType}(${rule}${detail})`
|
||||
return idx === this.flowNodes.length - 1 ? `${text} → 结束` : text
|
||||
},
|
||||
normalizeOssIds (val) {
|
||||
if (!val) return ''
|
||||
if (typeof val === 'string') return val
|
||||
@@ -820,4 +798,6 @@ export default {
|
||||
.approve-row .k { font-size: 14px; color: #606266; }
|
||||
|
||||
.selected-users { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
|
||||
|
||||
@import "./_form-compact.scss";
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user