Files
tms-erp-web/src/views/transportCapacity/components/cert-audit-detail/main.vue
T

293 lines
8.3 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<el-dialog
v-model="visible"
:title="dialogTitle"
width="92%"
top="4vh"
append-to-body
class="cert-audit-detail-dialog"
@closed="handleClosed"
>
<div v-loading="loading" class="cert-audit-detail">
<el-alert
v-if="loadFailed"
type="error"
:closable="false"
show-icon
title="认证记录详情加载失败,请刷新后重试"
class="cert-audit-detail__notice"
/>
<section-card title="提交信息">
<el-descriptions :column="3" border size="small">
<el-descriptions-item label="认证对象">
{{ detail.bizKey || '-' }}
</el-descriptions-item>
<el-descriptions-item label="审核状态">
<el-tag :type="statusTag.type" size="small">
{{ detail.statusText || statusTag.label }}
</el-tag>
</el-descriptions-item>
<el-descriptions-item label="该对象当前是否已认证">
<el-tag :type="detail.certified ? 'success' : 'info'" size="small">
{{ detail.certified ? '已认证' : '未认证' }}
</el-tag>
</el-descriptions-item>
<el-descriptions-item label="提交人">
{{ detail.submitUserName || '-' }}
</el-descriptions-item>
<el-descriptions-item label="提交时间">
{{ formatCertDateTime(detail.submitTime) }}
</el-descriptions-item>
<el-descriptions-item label="认证类型">
{{ bizTypeLabel }}
</el-descriptions-item>
<el-descriptions-item label="审核人">
{{ detail.auditUserName || '-' }}
</el-descriptions-item>
<el-descriptions-item :label="auditTimeLabel">
{{ detail.auditTime ? formatCertDateTime(detail.auditTime) : '-' }}
</el-descriptions-item>
</el-descriptions>
</section-card>
<section-card v-if="!loading && !loadFailed" title="待审内容 vs 当前生效值">
<cert-audit-diff
:key="diffKey"
:biz-type="bizType"
:pending-json="detail.pendingSnapshotJson"
:effective-json="detail.effectiveSnapshotJson"
/>
</section-card>
<section-card title="审核意见">
<el-form label-position="right" label-width="90px" class="cert-audit-detail__form">
<el-form-item label="驳回原因">
<el-input
v-model="rejectReason"
type="textarea"
:rows="3"
maxlength="200"
show-word-limit
:disabled="!auditable"
placeholder="驳回时必填,不超过 200 字;通过时无需填写"
/>
</el-form-item>
</el-form>
</section-card>
</div>
<template #footer>
<el-button @click="visible = false">取消</el-button>
<el-button
type="danger"
:disabled="!auditable || loadFailed"
:loading="rejectLoading"
@click="handleReject"
>
驳回
</el-button>
<el-button
type="primary"
:disabled="!auditable || loadFailed"
:loading="approveLoading"
@click="handleApprove"
>
通过
</el-button>
</template>
</el-dialog>
</template>
<script>
import { getAuditDetail, auditCertification } from '@/api/transportCapacity/certification-audit';
import { CERT_RECORD_STATUS, certStatusTag, formatCertDateTime } from '@/utils/cert-audit';
import CertAuditDiff from '../cert-audit-diff/main.vue';
export default {
name: 'CertAuditDetail',
components: {
CertAuditDiff,
},
props: {
modelValue: {
type: Boolean,
default: false,
},
// 认证记录主键
recordId: {
type: [String, Number],
default: '',
},
// 认证对象类型:driver / vehicle
bizType: {
type: String,
default: 'driver',
},
},
emits: ['update:modelValue', 'success'],
data() {
return {
loading: false,
loadFailed: false,
detail: {},
rejectReason: '',
approveLoading: false,
rejectLoading: false,
};
},
computed: {
visible: {
get() {
return this.modelValue;
},
set(value) {
this.$emit('update:modelValue', value);
},
},
bizTypeLabel() {
return this.bizType === 'vehicle' ? '车辆认证' : '司机认证';
},
dialogTitle() {
const bizKey = this.detail.bizKey ? `:${this.detail.bizKey}` : '';
return `${this.bizTypeLabel}审核${bizKey}`;
},
statusTag() {
return certStatusTag(this.detail.status);
},
// 审核时间一栏按审核结论换标签:还在「审核中」的记录没有结论,不能写成通过或驳回时间
auditTimeLabel() {
const status = String(this.detail.status);
if (status === String(CERT_RECORD_STATUS.APPROVED)) return '审核通过时间';
if (status === String(CERT_RECORD_STATUS.REJECTED)) return '审核驳回时间';
return '审核时间';
},
// 只有「审核中」的记录可审;已通过/已驳回/已作废都是终态
auditable() {
return String(this.detail.status) === String(CERT_RECORD_STATUS.PENDING);
},
diffKey() {
return `${this.detail.id || this.recordId || ''}-${this.detail.submitTime || ''}`;
},
},
watch: {
modelValue(value) {
if (value) {
this.resetState();
this.loadDetail();
}
},
},
methods: {
formatCertDateTime,
resetState() {
this.detail = {};
this.rejectReason = '';
this.loadFailed = false;
this.approveLoading = false;
this.rejectLoading = false;
},
loadDetail() {
if (!this.recordId) {
this.loadFailed = true;
return;
}
this.loading = true;
getAuditDetail(this.recordId)
.then(res => {
this.detail = res.data.data || {};
this.loadFailed = false;
})
.catch(() => {
this.detail = {};
this.loadFailed = true;
})
.finally(() => {
this.loading = false;
});
},
handleClosed() {
this.resetState();
},
// 通过:只提交是否通过,不带驳回原因
handleApprove() {
const bizKey = this.detail.bizKey || '该认证对象';
this.$confirm(`通过后本次提交将立即成为「${bizKey}」的当前生效值,是否确认通过?`, {
confirmButtonText: '确认通过',
cancelButtonText: '取消',
type: 'warning',
})
.then(() => {
this.approveLoading = true;
return auditCertification(this.detail.id, true);
})
.then(() => {
this.$message.success('认证已通过');
this.visible = false;
this.$emit('success');
})
.catch(() => {})
.finally(() => {
this.approveLoading = false;
});
},
// 驳回:原因必填且不超过 200 字,前端先拦一道
handleReject() {
const rejectReason = String(this.rejectReason || '').trim();
if (!rejectReason) {
this.$message.warning('请输入驳回原因');
return;
}
if (rejectReason.length > 200) {
this.$message.warning('驳回原因不能超过 200 字');
return;
}
const bizKey = this.detail.bizKey || '该认证对象';
this.$confirm(
`驳回后本次提交的内容不会生效,「${bizKey}」的当前生效值保持不变,是否确认驳回?`,
{
confirmButtonText: '确认驳回',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(() => {
this.rejectLoading = true;
return auditCertification(this.detail.id, false, rejectReason);
})
.then(() => {
this.$message.success('认证已驳回');
this.visible = false;
this.$emit('success');
})
.catch(() => {})
.finally(() => {
this.rejectLoading = false;
});
},
},
};
</script>
<style lang="scss" scoped>
.cert-audit-detail {
&__notice {
margin-bottom: 8px;
}
:deep(.section-card) {
margin-bottom: 8px;
}
:deep(.el-descriptions__label) {
width: 150px;
}
&__form {
:deep(.el-form-item) {
margin-bottom: 0;
}
}
}
</style>