调整 iam
This commit is contained in:
@@ -1,8 +1,51 @@
|
||||
<template>
|
||||
<div v-loading="loading" class="master-detail">
|
||||
<section v-if="master" class="detail-overview">
|
||||
<div class="detail-heading"><div><h2>多联总单详情 <span>|</span> {{ master.masterNo }}</h2><el-tag :type="statusType(master.businessStatus)" class="status-text">{{ statusName(master.businessStatus) }}</el-tag><el-tag v-if="transportFlowLabel" type="info" class="transport-flow-tag">{{ transportFlowLabel }}</el-tag></div><el-button @click="$emit('back')">取消</el-button></div>
|
||||
<dl class="detail-meta"><div><dt>客户</dt><dd>{{ master.customerName || '-' }}</dd></div><div><dt>合同编号</dt><dd>{{ master.contractNo || '-' }}</dd></div><div><dt>项目</dt><dd>{{ master.projectName || '-' }}</dd></div><div class="detail-meta__attachments"><dt>附件</dt><dd><template v-if="attachments.length"><el-link v-for="file in attachments" :key="file.url || file.link || file.name || file.originalName" type="primary" @click="previewAttachment(file)">{{ attachmentName(file) }}</el-link></template><span v-else>-</span></dd></div></dl>
|
||||
<div class="detail-heading"><div><h2>多联总单详情 <span>|</span> {{ master.masterNo }}</h2><el-tag :type="statusType(master.businessStatus)" class="status-text">{{ statusName(master.businessStatus) }}</el-tag><el-tag v-if="transportFlowLabel" type="info" class="transport-flow-tag">{{ transportFlowLabel }}</el-tag></div></div>
|
||||
<dl class="detail-meta">
|
||||
<div>
|
||||
<dt>客户</dt>
|
||||
<dd>
|
||||
<el-link v-if="master.customerName" type="primary" @click="openCustomer">{{
|
||||
master.customerName
|
||||
}}</el-link>
|
||||
<span v-else>-</span>
|
||||
</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>合同编号</dt>
|
||||
<dd>
|
||||
<el-link v-if="master.contractNo && master.contractId" type="primary" @click="openContract">{{
|
||||
master.contractNo
|
||||
}}</el-link>
|
||||
<span v-else>{{ master.contractNo || '-' }}</span>
|
||||
</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>项目</dt>
|
||||
<dd>
|
||||
<el-link v-if="master.projectName && master.projectId" type="primary" @click="openProject">{{
|
||||
master.projectName
|
||||
}}</el-link>
|
||||
<span v-else>{{ master.projectName || '-' }}</span>
|
||||
</dd>
|
||||
</div>
|
||||
<div class="detail-meta__attachments">
|
||||
<dt>附件</dt>
|
||||
<dd>
|
||||
<template v-if="attachments.length">
|
||||
<el-link
|
||||
v-for="file in attachments"
|
||||
:key="file.url || file.link || file.name || file.originalName"
|
||||
type="primary"
|
||||
@click="previewAttachment(file)"
|
||||
>{{ attachmentName(file) }}</el-link
|
||||
>
|
||||
</template>
|
||||
<span v-else>-</span>
|
||||
</dd>
|
||||
</div>
|
||||
</dl>
|
||||
<div class="route-map"><template v-for="(route, index) in segments" :key="route.segmentNo"><div class="route-map__node"><span :class="['route-badge', index ? 'middle' : 'start']">{{ index ? '经' : '起' }}</span><strong>{{ segmentLocationName(route, 'departure') }}</strong><small>{{ route.departureAddress || '-' }}</small><small class="route-map__progress">{{ index ? `已到达 ${quantity(segments[index - 1].arrivedQuantity)}/${quantity(master.totalQuantity)} ${plannedUnit(segments[index - 1])}` : `已调度 ${quantity(route.dispatchedQuantity)}/${quantity(master.totalQuantity)} ${plannedUnit(route)}` }}</small><small v-if="index" class="route-map__progress">已调度 {{ quantity(route.dispatchedQuantity) }}/{{ quantity(master.totalQuantity) }} {{ plannedUnit(route) }}</small></div><div class="route-map__line"></div><div v-if="index === segments.length - 1" class="route-map__node"><span class="route-badge end">终</span><strong>{{ segmentLocationName(route, 'arrival') }}</strong><small>{{ route.arrivalAddress || '-' }}</small><small class="route-map__progress">已到达 {{ quantity(route.arrivedQuantity) }}/{{ quantity(master.totalQuantity) }} {{ plannedUnit(route) }}</small></div></template></div>
|
||||
</section>
|
||||
|
||||
@@ -42,6 +85,8 @@
|
||||
|
||||
<script>
|
||||
import * as api from '@/api/business/master-order';
|
||||
import { getDetail as getProjectDetail } from '@/api/business/project-apply';
|
||||
import { getList as getCustomerArchiveList } from '@/api/vehicle/customer-archive';
|
||||
import { CaretBottom, CaretTop } from '@element-plus/icons-vue';
|
||||
import { ElImageViewer } from 'element-plus';
|
||||
import { OpenFileViewer } from '@open-file-viewer/vue';
|
||||
@@ -51,10 +96,26 @@ import pdfWorkerSrc from 'pdfjs-dist/build/pdf.worker.mjs?url';
|
||||
|
||||
const viewerPlugins = [imagePlugin(), pdfPlugin({ workerSrc: pdfWorkerSrc, useFetchData: true }), officePlugin({ pdf: { workerSrc: pdfWorkerSrc, useFetchData: true } }), textPlugin(), fallbackPlugin()];
|
||||
|
||||
const parseJsonArray = value => {
|
||||
if (Array.isArray(value)) return value;
|
||||
if (!value) return [];
|
||||
try {
|
||||
const parsed = JSON.parse(value);
|
||||
if (Array.isArray(parsed)) return parsed;
|
||||
return parsed && typeof parsed === 'object' ? [parsed] : [];
|
||||
} catch (error) {
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
const customerRowLabel = (row = {}) =>
|
||||
row.customer || row.fullName || row.shortName || row.customerName || row.customerCode || '';
|
||||
|
||||
const customerRowId = (row = {}) => row.id || row.customerId || '';
|
||||
|
||||
export default {
|
||||
components: { ElImageViewer, OpenFileViewer },
|
||||
props: { id: [String, Number] },
|
||||
emits: ['back'],
|
||||
data() { return { loading: false, master: null, expandedSegments: {}, CaretBottom, CaretTop, imagePreviewVisible: false, imagePreviewUrls: [], imagePreviewIndex: 0, documentPreviewVisible: false, previewFile: {}, viewerPlugins, viewerToolbar: { download: true, fullscreen: true, print: true, rotate: true, zoom: true } }; },
|
||||
computed: {
|
||||
segments() {
|
||||
@@ -148,6 +209,68 @@ export default {
|
||||
this.$router.push({ path: '/business/waybill-manage/detail', query: { id: row.id } });
|
||||
},
|
||||
openPlan(row) { this.$router.push({ path: '/business/transport-plan', query: { detailId: row.id } }); },
|
||||
openContract() {
|
||||
if (!this.master?.contractId) {
|
||||
this.$message.warning('合同信息缺失,无法打开');
|
||||
return;
|
||||
}
|
||||
this.$router.push({
|
||||
path: '/business/contract-manage/detail',
|
||||
query: { id: this.master.contractId, name: '合同详情' },
|
||||
});
|
||||
},
|
||||
openProject() {
|
||||
if (!this.master?.projectId) {
|
||||
this.$message.warning('项目信息缺失,无法打开');
|
||||
return;
|
||||
}
|
||||
this.$router.push({
|
||||
path: '/business/project-apply/form',
|
||||
query: { mode: 'view', id: this.master.projectId, name: '查看项目管理' },
|
||||
});
|
||||
},
|
||||
async resolveCustomerId() {
|
||||
if (this.master?.customerId) return this.master.customerId;
|
||||
const name = String(this.master?.customerName || '').trim();
|
||||
if (!name) return '';
|
||||
if (this.master?.projectId) {
|
||||
try {
|
||||
const res = await getProjectDetail(this.master.projectId);
|
||||
const rows = parseJsonArray(res.data?.data?.customerJson);
|
||||
const matched =
|
||||
rows.find(row => customerRowLabel(row) === name) ||
|
||||
rows.find(row => {
|
||||
const label = customerRowLabel(row);
|
||||
return label && (name.includes(label) || label.includes(name));
|
||||
});
|
||||
const id = customerRowId(matched);
|
||||
if (id) return id;
|
||||
} catch (error) {
|
||||
// 项目客户解析失败时回退到客商档案检索
|
||||
}
|
||||
}
|
||||
try {
|
||||
const res = await getCustomerArchiveList(1, 20, { fullName: name });
|
||||
const records = res.data?.data?.records || [];
|
||||
const exact =
|
||||
records.find(item => item.fullName === name || item.shortName === name) || records[0];
|
||||
return exact?.id || '';
|
||||
} catch (error) {
|
||||
return '';
|
||||
}
|
||||
},
|
||||
async openCustomer() {
|
||||
if (!this.master?.customerName) return;
|
||||
const customerId = await this.resolveCustomerId();
|
||||
if (!customerId) {
|
||||
this.$message.warning('未找到对应客商档案,无法打开');
|
||||
return;
|
||||
}
|
||||
this.$router.push({
|
||||
path: '/vehicle/customer-archive/form',
|
||||
query: { id: String(customerId), name: '查看客商档案', view: '1' },
|
||||
});
|
||||
},
|
||||
waybillStatusName(value) { return ({ pending: '待执行', waiting: '待执行', running: '进行中', processing: '进行中', completed: '已完成', cancelled: '已取消' })[value] || value || '-'; },
|
||||
waybillStatusType(value) { return ({ pending: 'info', waiting: 'info', running: 'warning', processing: 'warning', completed: 'success', cancelled: 'danger' })[value] || 'info'; },
|
||||
statusName(value) { return ({ waiting_dispatch: '待调度', dispatching: '调度中', completed: '调度完成', closed: '调度关闭' })[value] || value || '-'; },
|
||||
@@ -161,7 +284,7 @@ export default {
|
||||
.detail-overview, .execution-detail-card { margin-bottom: 8px; border: 1px solid #eff1f7; background: #fff; }
|
||||
.detail-heading { display: flex; align-items: center; justify-content: space-between; padding: 18px 24px; h2 { display: inline-block; margin: 0 16px 0 0; font-size: 20px; } h2 span { margin: 0 8px; color: #909399; font-weight: 400; } }
|
||||
.transport-flow-tag { margin-left: 8px; }
|
||||
.detail-meta { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 18px 24px; margin: 0; padding: 0 24px 20px; dt { margin-bottom: 6px; color: #909399; font-size: 13px; } dd { display: flex; flex-wrap: wrap; gap: 8px 16px; margin: 0; color: #409eff; font-size: 14px; word-break: break-all; } }
|
||||
.detail-meta { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 18px 24px; margin: 0; padding: 0 24px 20px; dt { margin-bottom: 6px; color: #909399; font-size: 13px; } dd { display: flex; flex-wrap: wrap; gap: 8px 16px; margin: 0; color: #303133; font-size: 14px; word-break: break-all; } :deep(.el-link) { font-size: 14px; } }
|
||||
.route-map { display: flex; align-items: flex-start; padding: 16px 24px 20px; border-top: 1px solid #eff1f7; overflow-x: auto; }
|
||||
.route-map__node { display: grid; flex: 0 0 150px; justify-items: center; gap: 6px; text-align: center; strong { font-size: 16px; white-space: nowrap; } small { color: #606266; white-space: nowrap; } }
|
||||
.route-map__progress { color: #303133 !important; }
|
||||
|
||||
Reference in New Issue
Block a user