293 lines
8.3 KiB
Vue
293 lines
8.3 KiB
Vue
<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>
|