<!-- 审批详情:基础信息 + 填报内容 -->
|
<template>
|
<div class="approve-detail-panel">
|
<div class="detail-block">
|
<div class="detail-block-title">基本信息</div>
|
<el-descriptions :column="2" border>
|
<el-descriptions-item label="业务单号">{{
|
row.bizId || row.id || "—"
|
}}</el-descriptions-item>
|
<el-descriptions-item label="审批状态">
|
<el-tag
|
:type="approvalStatusTagType(row.approvalStatus)"
|
size="small"
|
effect="plain"
|
>
|
{{ approvalStatusLabel(row.approvalStatus) }}
|
</el-tag>
|
</el-descriptions-item>
|
<el-descriptions-item label="审批类型">
|
<span
|
class="approve-type-cell"
|
:style="approvalTypeStyle(row.approvalType)"
|
>
|
{{ approvalTypeLabel(row.approvalType) }}
|
</span>
|
</el-descriptions-item>
|
<el-descriptions-item label="申请人编号">{{
|
row.applicantNo || "—"
|
}}</el-descriptions-item>
|
<el-descriptions-item label="申请人名称">{{
|
row.applicantName || "—"
|
}}</el-descriptions-item>
|
<el-descriptions-item label="申请摘要">{{
|
row.summary || "—"
|
}}</el-descriptions-item>
|
<el-descriptions-item
|
v-if="row.rejectReason"
|
label="驳回原因"
|
:span="2"
|
>
|
<span class="reject-text">{{ row.rejectReason }}</span>
|
</el-descriptions-item>
|
<el-descriptions-item label="创建时间" :span="2">
|
{{ formatDisplayTime(row.createTime) }}
|
</el-descriptions-item>
|
</el-descriptions>
|
</div>
|
<div class="detail-block">
|
<div class="detail-block-title">填报内容</div>
|
<!-- 默认表单展示 -->
|
<FormPayloadFields
|
v-if="!isSpecialApprovalType"
|
:fields="formResolved.fields"
|
:form-payload="formResolved.formPayload"
|
readonly
|
/>
|
|
<!-- 发货审批详情 -->
|
<template v-else-if="row.businessType === 7">
|
<div v-if="detailData.shippingInfo" class="shipment-detail">
|
<el-divider content-position="left">发货详情</el-divider>
|
<el-descriptions :column="2" border>
|
<el-descriptions-item label="销售订单">{{
|
detailData.shippingInfo.salesContractNo || "--"
|
}}</el-descriptions-item>
|
<el-descriptions-item label="出库批号">{{
|
detailData.shippingInfo.outboundBatches || "--"
|
}}</el-descriptions-item>
|
<el-descriptions-item label="客户名称">{{
|
detailData.shippingInfo.customerName || "--"
|
}}</el-descriptions-item>
|
<el-descriptions-item label="发货类型">{{
|
detailData.shippingInfo.type || "--"
|
}}</el-descriptions-item>
|
<el-descriptions-item label="发货日期">{{
|
detailData.shippingInfo.shippingDateDate || "--"
|
}}</el-descriptions-item>
|
<el-descriptions-item label="审核状态">{{
|
detailData.shippingInfo.status || "--"
|
}}</el-descriptions-item>
|
<el-descriptions-item label="发货车牌号">{{
|
detailData.shippingInfo.shippingCarNumber || "--"
|
}}</el-descriptions-item>
|
<el-descriptions-item label="快递公司">{{
|
detailData.shippingInfo.expressCompany || "--"
|
}}</el-descriptions-item>
|
<el-descriptions-item label="快递单号" :span="2">{{
|
detailData.shippingInfo.expressNumber || "--"
|
}}</el-descriptions-item>
|
</el-descriptions>
|
<div
|
v-if="detailData.shippingProductDetailDtoList.length"
|
style="margin-top: 20px"
|
>
|
<h4>产品明细</h4>
|
<el-table
|
:data="detailData.shippingProductDetailDtoList"
|
border
|
size="small"
|
style="width: 100%"
|
>
|
<el-table-column
|
label="批号"
|
prop="batchNo"
|
min-width="160"
|
show-overflow-tooltip
|
/>
|
<el-table-column
|
label="产品名称"
|
prop="productName"
|
min-width="160"
|
show-overflow-tooltip
|
/>
|
<el-table-column
|
label="规格型号"
|
prop="specificationModel"
|
min-width="160"
|
show-overflow-tooltip
|
/>
|
<el-table-column
|
label="发货数量"
|
prop="deliveryQuantity"
|
min-width="120"
|
align="center"
|
/>
|
</el-table>
|
</div>
|
</div>
|
</template>
|
|
<!-- 采购审批详情 -->
|
<template v-else-if="row.businessType === 5">
|
<div v-if="detailData" class="procurement-detail">
|
<el-divider content-position="left">采购详情</el-divider>
|
<el-descriptions :column="2" border>
|
<el-descriptions-item label="采购合同号">{{
|
detailData.purchaseContractNumber || "--"
|
}}</el-descriptions-item>
|
<el-descriptions-item label="供应商名称">{{
|
detailData.supplierName || "--"
|
}}</el-descriptions-item>
|
<el-descriptions-item label="项目名称">{{
|
detailData.projectName || "--"
|
}}</el-descriptions-item>
|
<el-descriptions-item label="销售合同号">{{
|
detailData.salesContractNo || "--"
|
}}</el-descriptions-item>
|
<el-descriptions-item label="签订日期">{{
|
detailData.executionDate || "--"
|
}}</el-descriptions-item>
|
<el-descriptions-item label="录入日期">{{
|
detailData.entryDate || "--"
|
}}</el-descriptions-item>
|
<el-descriptions-item label="付款方式">{{
|
detailData.paymentMethod || "--"
|
}}</el-descriptions-item>
|
<el-descriptions-item label="合同金额" :span="2">
|
<span style="font-size: 18px; color: #e6a23c; font-weight: bold">
|
¥{{ Number(detailData.contractAmount ?? 0).toFixed(2) }}
|
</span>
|
</el-descriptions-item>
|
</el-descriptions>
|
<div v-if="detailData.productData.length" style="margin-top: 20px">
|
<h4>产品明细</h4>
|
<el-table :data="detailData.productData" border style="width: 100%">
|
<el-table-column prop="productCategory" label="产品名称" />
|
<el-table-column prop="specificationModel" label="规格型号" />
|
<el-table-column prop="unit" label="单位" />
|
<el-table-column prop="quantity" label="数量" />
|
<el-table-column prop="taxInclusiveUnitPrice" label="含税单价">
|
<template #default="scope"
|
>¥{{
|
Number(scope.row.taxInclusiveUnitPrice ?? 0).toFixed(2)
|
}}</template
|
>
|
</el-table-column>
|
<el-table-column prop="taxInclusiveTotalPrice" label="含税总价">
|
<template #default="scope"
|
>¥{{
|
Number(scope.row.taxInclusiveTotalPrice ?? 0).toFixed(2)
|
}}</template
|
>
|
</el-table-column>
|
</el-table>
|
</div>
|
</div>
|
</template>
|
|
<!-- 报价审批详情 -->
|
<template v-else-if="row.businessType === 6">
|
<div v-if="detailData" class="quotation-detail">
|
<el-divider content-position="left">报价详情</el-divider>
|
<el-descriptions :column="2" border>
|
<el-descriptions-item label="报价单号">{{
|
detailData.quotationNo || "--"
|
}}</el-descriptions-item>
|
<el-descriptions-item label="客户名称">{{
|
detailData.customer || "--"
|
}}</el-descriptions-item>
|
<el-descriptions-item label="业务员">{{
|
detailData.salesperson || "--"
|
}}</el-descriptions-item>
|
<el-descriptions-item label="报价日期">{{
|
detailData.quotationDate || "--"
|
}}</el-descriptions-item>
|
<el-descriptions-item label="有效期至">{{
|
detailData.validDate || "--"
|
}}</el-descriptions-item>
|
<el-descriptions-item label="付款方式">{{
|
detailData.paymentMethod || "--"
|
}}</el-descriptions-item>
|
<el-descriptions-item label="报价总额" :span="2">
|
<span style="font-size: 18px; color: #e6a23c; font-weight: bold">
|
¥{{ Number(detailData.totalAmount ?? 0).toFixed(2) }}
|
</span>
|
</el-descriptions-item>
|
</el-descriptions>
|
<div v-if="detailData.products?.length" style="margin-top: 20px">
|
<h4>产品明细</h4>
|
<el-table :data="detailData.products" border style="width: 100%">
|
<el-table-column prop="product" label="产品名称" />
|
<el-table-column prop="specification" label="规格型号" />
|
<el-table-column prop="unit" label="单位" />
|
<el-table-column prop="unitPrice" label="单价">
|
<template #default="scope"
|
>¥{{ Number(scope.row.unitPrice ?? 0).toFixed(2) }}</template
|
>
|
</el-table-column>
|
</el-table>
|
</div>
|
<div v-if="detailData.remark" style="margin-top: 20px">
|
<h4>备注</h4>
|
<p>{{ detailData.remark }}</p>
|
</div>
|
</div>
|
</template>
|
</div>
|
<div v-if="attachmentList.length" class="detail-block">
|
<div class="detail-block-title">附件列表</div>
|
<div class="attachment-list">
|
<div
|
v-for="file in attachmentList"
|
:key="file.id"
|
class="attachment-item"
|
>
|
<el-icon class="file-icon">
|
<Paperclip />
|
</el-icon>
|
<span class="file-name" :title="file.name || file.originalFilename">
|
{{ file.name || file.originalFilename }}
|
</span>
|
<div class="file-actions">
|
<el-link
|
v-if="file.previewURL || file.url"
|
type="primary"
|
:underline="false"
|
@click="openFile(file.previewURL || file.url)"
|
>预览</el-link
|
>
|
<el-divider
|
v-if="(file.previewURL || file.url) && file.downloadURL"
|
direction="vertical"
|
/>
|
<el-link
|
v-if="file.downloadURL"
|
type="primary"
|
:underline="false"
|
@click="openFile(file.downloadURL)"
|
>下载</el-link
|
>
|
</div>
|
</div>
|
</div>
|
</div>
|
</div>
|
</template>
|
|
<script setup>
|
import { computed } from "vue";
|
import { Paperclip } from "@element-plus/icons-vue";
|
import { formatDisplayTime } from "../../approve-template/approveTemplateConstants.js";
|
import {
|
approvalTypeLabel,
|
approvalTypeStyle,
|
approvalStatusLabel,
|
approvalStatusTagType,
|
resolveInstanceFormFields,
|
} from "../approveListConstants.js";
|
import FormPayloadFields from "./FormPayloadFields.vue";
|
|
const props = defineProps({
|
row: { type: Object, default: () => ({}) },
|
detailData: { type: Object, default: () => ({}) },
|
});
|
|
const formResolved = computed(() => resolveInstanceFormFields(props.row));
|
|
// 是否为特殊审批类型(采购、发货、报价)
|
const isSpecialApprovalType = computed(() => {
|
return [5, 7, 6].includes(props.row.businessType);
|
});
|
|
// 详情数据(直接使用传入的 detail-data 参数)
|
const detailData = computed(() => {
|
return props.detailData || {};
|
});
|
|
const attachmentList = computed(() => {
|
const list = props.row.storageBlobVOList || props.row.storageBlobDTOs || [];
|
return Array.isArray(list) ? list : [];
|
});
|
|
function openFile(url) {
|
if (!url) return;
|
window.open(url, "_blank");
|
}
|
</script>
|
|
<style scoped>
|
.approve-detail-panel {
|
display: flex;
|
flex-direction: column;
|
gap: 20px;
|
}
|
.detail-block-title {
|
font-size: 14px;
|
font-weight: 600;
|
color: var(--el-text-color-primary);
|
margin: 0 0 12px;
|
padding-left: 10px;
|
border-left: 3px solid var(--el-color-primary);
|
line-height: 1.4;
|
}
|
.approve-type-cell {
|
display: inline-block;
|
padding: 2px 10px;
|
border-radius: 4px;
|
font-size: 13px;
|
line-height: 1.5;
|
}
|
.reject-text {
|
color: var(--el-color-danger);
|
}
|
|
.attachment-list {
|
display: grid;
|
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
|
gap: 12px;
|
}
|
.attachment-item {
|
display: flex;
|
align-items: center;
|
padding: 10px 12px;
|
background-color: var(--el-fill-color-light);
|
border-radius: 6px;
|
border: 1px solid var(--el-border-color-lighter);
|
transition: all 0.3s;
|
}
|
.attachment-item:hover {
|
border-color: var(--el-color-primary-light-5);
|
background-color: var(--el-color-primary-light-9);
|
}
|
.file-icon {
|
font-size: 18px;
|
color: var(--el-text-color-secondary);
|
margin-right: 10px;
|
}
|
.file-name {
|
flex: 1;
|
font-size: 13px;
|
color: var(--el-text-color-primary);
|
white-space: nowrap;
|
overflow: hidden;
|
text-overflow: ellipsis;
|
margin-right: 12px;
|
}
|
.file-actions {
|
display: flex;
|
align-items: center;
|
flex-shrink: 0;
|
}
|
</style>
|