1、完善配载
2、调整客商 3、调整临时额度 4、新增表头拖拽排序
This commit is contained in:
@@ -89,3 +89,10 @@ export const batchComplete = ids =>
|
||||
ids,
|
||||
},
|
||||
});
|
||||
|
||||
export const changeRoute = row =>
|
||||
request({
|
||||
url: `${baseUrl}/change-route`,
|
||||
method: 'post',
|
||||
data: row,
|
||||
});
|
||||
|
||||
@@ -23,7 +23,7 @@ export default {
|
||||
//配置首页不可关闭
|
||||
setting: {
|
||||
sidebar: 'vertical',
|
||||
tag: false,
|
||||
tag: true,
|
||||
debug: false,
|
||||
collapse: true,
|
||||
search: false,
|
||||
|
||||
@@ -15,6 +15,7 @@ import crudCommon from '@/mixins/crud.js';
|
||||
import { getScreen, findColumn } from './utils/util';
|
||||
import { setupPaginationEnhancer } from './utils/pagination';
|
||||
import { setupDialogFormLabelAlign } from './utils/dialog-form-label';
|
||||
import { setupTableColumnDrag } from './utils/table-column-drag';
|
||||
import './permission';
|
||||
import error from './error';
|
||||
import App from './App.vue';
|
||||
@@ -107,6 +108,7 @@ app.use(VueClipboard, {
|
||||
autoSetContainer: true,
|
||||
appendToBody: true, // 这可以帮助解决一些更复杂的使用场景下的问题
|
||||
});
|
||||
setupTableColumnDrag(app);
|
||||
app.mount('#app');
|
||||
setupPaginationEnhancer();
|
||||
setupDialogFormLabelAlign();
|
||||
|
||||
@@ -32,6 +32,7 @@ export const config = {
|
||||
temporaryCreditLimitSelectable: true,
|
||||
},
|
||||
enableAttachmentTable: true,
|
||||
detailAttachmentUploadTimeWidth: 220,
|
||||
enableDraftSave: true,
|
||||
saveAsDraft: true,
|
||||
defaultForm: {
|
||||
@@ -271,6 +272,8 @@ export const option = {
|
||||
},
|
||||
...auditColumns.map(column => ({ ...column, hide: true })),
|
||||
]),
|
||||
dialogWidth: 1280,
|
||||
dialogWidth: 1400,
|
||||
menuFixed: 'right',
|
||||
menuWidth: 320,
|
||||
index: false,
|
||||
};
|
||||
|
||||
@@ -574,12 +574,10 @@
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
// 全站统一:表格操作列文字链接统一为主色(蓝色)
|
||||
// 覆盖 Avue #menu 槽位与手写表格操作列中 el-link 的 warning / success / danger 等类型,
|
||||
// 同时统一 hover / active / disabled 态,保证全站操作列风格一致。
|
||||
// 全站统一:表格普通操作链接使用主色(蓝色),删除等危险操作保持危险色(红色)。
|
||||
// 选择器同时覆盖 Avue 行菜单(.avue-crud__menu)与任意含 el-link 的表格体单元格(手写操作列)。
|
||||
.avue-crud__menu .el-link,
|
||||
.el-table .el-table__body .cell:has(.el-link) .el-link {
|
||||
.avue-crud__menu .el-link:not(.el-link--danger),
|
||||
.el-table .el-table__body .cell:has(.el-link) .el-link:not(.el-link--danger) {
|
||||
// 覆盖 Element Plus el-link 默认的 font-weight: var(--el-font-weight-primary)(500 中等粗),
|
||||
// 操作列文字统一为常规字重,避免「查看/编辑/删除」等链接显得加粗。
|
||||
font-weight: normal;
|
||||
@@ -589,6 +587,14 @@
|
||||
--el-link-disabled-text-color: var(--el-color-primary-light-5);
|
||||
}
|
||||
|
||||
.avue-crud__menu .el-link.el-link--danger,
|
||||
.el-table .el-table__body .cell:has(.el-link) .el-link.el-link--danger {
|
||||
--el-link-text-color: var(--el-color-danger);
|
||||
--el-link-hover-text-color: var(--el-color-danger-light-3);
|
||||
--el-link-active-text-color: var(--el-color-danger-dark-2);
|
||||
--el-link-disabled-text-color: var(--el-color-danger-light-5);
|
||||
}
|
||||
|
||||
// 全站统一:去除操作列 el-link 默认 margin,避免与 8px gap 叠加导致文字间距过宽
|
||||
.avue-crud .avue-crud__menu .el-link,
|
||||
.el-table .el-table__body .cell:not(.avue-crud__menu):has(> .el-link) .el-link {
|
||||
@@ -652,3 +658,13 @@
|
||||
gap: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
// 全局表格列拖拽:仅对可移动的普通列显示拖拽反馈。
|
||||
.el-table th.tms-table-column-draggable {
|
||||
cursor: grab;
|
||||
|
||||
&.is-column-dragging {
|
||||
cursor: grabbing;
|
||||
opacity: 0.55;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,7 +86,8 @@ const collectLabelGroups = form => {
|
||||
};
|
||||
|
||||
const alignFormLabelsByColumn = form => {
|
||||
const groups = collectLabelGroups(form);
|
||||
if (form.classList.contains('dialog-form-label-fixed')) return;
|
||||
const groups = collectLabelGroups(form);
|
||||
|
||||
groups.forEach(group => {
|
||||
group.labels.forEach(label => {
|
||||
|
||||
@@ -0,0 +1,176 @@
|
||||
const STORAGE_PREFIX = 'tms:table-column-order:';
|
||||
|
||||
const getStore = instance =>
|
||||
instance?.store ||
|
||||
instance?.exposed?.store ||
|
||||
instance?.proxy?.store ||
|
||||
instance?.$?.exposed?.store ||
|
||||
instance?.$?.ctx?.store ||
|
||||
instance?.$?.store;
|
||||
|
||||
const getColumnKey = column =>
|
||||
String(column.property || column.columnKey || column.label || column.id || '');
|
||||
|
||||
const getTableKey = (instance, columns) => {
|
||||
const routePath = instance.$route?.path || instance.proxy?.$route?.path || window.location.pathname;
|
||||
const signature = columns
|
||||
.map(getColumnKey)
|
||||
.filter(Boolean)
|
||||
.sort()
|
||||
.join('|');
|
||||
return `${STORAGE_PREFIX}${routePath}:${signature}`;
|
||||
};
|
||||
|
||||
const canDragColumn = column =>
|
||||
column && !column.fixed && !['selection', 'index', 'expand'].includes(column.type);
|
||||
|
||||
const getColumnFromHeader = (header, columns) =>
|
||||
columns.find(column => header.classList.contains(column.id));
|
||||
|
||||
const updateColumnOrder = (instance, columns) => {
|
||||
const store = getStore(instance);
|
||||
if (!store?.states?._columns || columns.length !== store.states._columns.value.length) return;
|
||||
columns.forEach((column, index) => {
|
||||
column.no = index;
|
||||
});
|
||||
store.states._columns.value = [...columns];
|
||||
store.updateColumns?.();
|
||||
store.scheduleLayout?.(true, true);
|
||||
};
|
||||
|
||||
const restoreColumnOrder = instance => {
|
||||
const store = getStore(instance);
|
||||
const columns = store?.states?._columns?.value;
|
||||
if (!Array.isArray(columns) || columns.length < 2) return;
|
||||
const saved = JSON.parse(localStorage.getItem(getTableKey(instance, columns)) || '[]');
|
||||
if (!Array.isArray(saved) || !saved.length) return;
|
||||
const orderMap = new Map(saved.map((key, index) => [key, index]));
|
||||
const ordered = [...columns].sort((a, b) => {
|
||||
const aOrder = orderMap.get(getColumnKey(a));
|
||||
const bOrder = orderMap.get(getColumnKey(b));
|
||||
if (aOrder === undefined && bOrder === undefined) return a.no - b.no;
|
||||
if (aOrder === undefined) return 1;
|
||||
if (bOrder === undefined) return -1;
|
||||
return aOrder - bOrder;
|
||||
});
|
||||
updateColumnOrder(instance, ordered);
|
||||
};
|
||||
|
||||
const bindHeaderDrag = instance => {
|
||||
const store = getStore(instance);
|
||||
const columns = store?.states?._columns?.value;
|
||||
const headerRow = instance.$el?.querySelector('.el-table__header-wrapper thead tr');
|
||||
if (!headerRow || headerRow.__tmsColumnDragBound || !Array.isArray(columns)) return;
|
||||
headerRow.__tmsColumnDragBound = true;
|
||||
let draggingColumn = null;
|
||||
|
||||
[...headerRow.children].forEach(header => {
|
||||
const column = getColumnFromHeader(header, columns);
|
||||
if (!canDragColumn(column)) return;
|
||||
header.draggable = true;
|
||||
header.classList.add('tms-table-column-draggable');
|
||||
});
|
||||
|
||||
headerRow.addEventListener('dragstart', event => {
|
||||
const header = event.target.closest('th');
|
||||
const currentColumns = store.states._columns.value;
|
||||
const column = header && getColumnFromHeader(header, currentColumns);
|
||||
if (!canDragColumn(column)) {
|
||||
event.preventDefault();
|
||||
return;
|
||||
}
|
||||
draggingColumn = column;
|
||||
event.dataTransfer.effectAllowed = 'move';
|
||||
header.classList.add('is-column-dragging');
|
||||
});
|
||||
headerRow.addEventListener('dragover', event => {
|
||||
const header = event.target.closest('th');
|
||||
const column = header && getColumnFromHeader(header, store.states._columns.value);
|
||||
if (draggingColumn && canDragColumn(column)) event.preventDefault();
|
||||
});
|
||||
headerRow.addEventListener('drop', event => {
|
||||
const header = event.target.closest('th');
|
||||
const targetColumn = header && getColumnFromHeader(header, store.states._columns.value);
|
||||
if (!draggingColumn || !canDragColumn(targetColumn) || draggingColumn === targetColumn) return;
|
||||
event.preventDefault();
|
||||
const ordered = [...store.states._columns.value];
|
||||
const from = ordered.indexOf(draggingColumn);
|
||||
if (from < 0) return;
|
||||
const movingRight = from < ordered.indexOf(targetColumn);
|
||||
ordered.splice(from, 1);
|
||||
const targetIndex = ordered.indexOf(targetColumn);
|
||||
ordered.splice(targetIndex + (movingRight ? 1 : 0), 0, draggingColumn);
|
||||
updateColumnOrder(instance, ordered);
|
||||
localStorage.setItem(getTableKey(instance, ordered), JSON.stringify(ordered.map(getColumnKey)));
|
||||
});
|
||||
headerRow.addEventListener('dragend', () => {
|
||||
instance.$el.querySelectorAll('.is-column-dragging').forEach(item => item.classList.remove('is-column-dragging'));
|
||||
draggingColumn = null;
|
||||
});
|
||||
};
|
||||
|
||||
export const setupTableColumnDrag = app => {
|
||||
let dragging = null;
|
||||
const restoredTables = new WeakSet();
|
||||
const getTableInstance = element => {
|
||||
let instance = element.closest('.el-table')?.__vueParentComponent;
|
||||
while (instance && instance.type?.name !== 'ElTable') {
|
||||
instance = instance.parent;
|
||||
}
|
||||
return instance;
|
||||
};
|
||||
const enableHeaderDrag = () => {
|
||||
document.querySelectorAll('.el-table__header-wrapper th').forEach(header => {
|
||||
if (header.closest('.el-table__fixed, .el-table__fixed-right')) return;
|
||||
const instance = getTableInstance(header);
|
||||
if (instance && !restoredTables.has(instance)) {
|
||||
restoreColumnOrder(instance);
|
||||
restoredTables.add(instance);
|
||||
}
|
||||
const column = getColumnFromHeader(header, getStore(instance)?.states?._columns?.value || []);
|
||||
if (!canDragColumn(column)) return;
|
||||
header.draggable = true;
|
||||
header.classList.add('tms-table-column-draggable');
|
||||
});
|
||||
};
|
||||
const tableObserver = new MutationObserver(enableHeaderDrag);
|
||||
tableObserver.observe(document.documentElement, { childList: true, subtree: true });
|
||||
setTimeout(enableHeaderDrag, 0);
|
||||
|
||||
document.addEventListener('dragstart', event => {
|
||||
const header = event.target.closest?.('.el-table__header-wrapper th.tms-table-column-draggable');
|
||||
const instance = header && getTableInstance(header);
|
||||
const store = getStore(instance);
|
||||
const column = header && getColumnFromHeader(header, store?.states?._columns?.value || []);
|
||||
if (!header || !canDragColumn(column)) return;
|
||||
dragging = { instance, column, header };
|
||||
event.dataTransfer.effectAllowed = 'move';
|
||||
header.classList.add('is-column-dragging');
|
||||
});
|
||||
document.addEventListener('dragover', event => {
|
||||
const header = event.target.closest?.('.el-table__header-wrapper th.tms-table-column-draggable');
|
||||
const instance = header && getTableInstance(header);
|
||||
if (dragging && instance === dragging.instance) event.preventDefault();
|
||||
});
|
||||
document.addEventListener('drop', event => {
|
||||
const header = event.target.closest?.('.el-table__header-wrapper th.tms-table-column-draggable');
|
||||
const instance = header && getTableInstance(header);
|
||||
const store = getStore(instance);
|
||||
const target = header && getColumnFromHeader(header, store?.states?._columns?.value || []);
|
||||
if (!dragging || instance !== dragging.instance || !canDragColumn(target) || target === dragging.column) return;
|
||||
event.preventDefault();
|
||||
const ordered = [...store.states._columns.value];
|
||||
const from = ordered.indexOf(dragging.column);
|
||||
if (from < 0) return;
|
||||
const movingRight = from < ordered.indexOf(target);
|
||||
ordered.splice(from, 1);
|
||||
const targetIndex = ordered.indexOf(target);
|
||||
ordered.splice(targetIndex + (movingRight ? 1 : 0), 0, dragging.column);
|
||||
updateColumnOrder(instance, ordered);
|
||||
localStorage.setItem(getTableKey(instance, ordered), JSON.stringify(ordered.map(getColumnKey)));
|
||||
});
|
||||
document.addEventListener('dragend', () => {
|
||||
document.querySelectorAll('.is-column-dragging').forEach(item => item.classList.remove('is-column-dragging'));
|
||||
dragging = null;
|
||||
});
|
||||
};
|
||||
@@ -2179,7 +2179,12 @@
|
||||
<template #default="{ row }">{{ formatFileSize(row.size) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="uploadUserName" label="上传人" width="140" />
|
||||
<el-table-column prop="uploadTime" label="上传时间" width="180" sortable/>
|
||||
<el-table-column
|
||||
prop="uploadTime"
|
||||
label="上传时间"
|
||||
:width="config.detailAttachmentUploadTimeWidth || 180"
|
||||
sortable
|
||||
/>
|
||||
</el-table>
|
||||
</section-card>
|
||||
</div>
|
||||
|
||||
@@ -138,9 +138,9 @@
|
||||
>
|
||||
<el-option
|
||||
v-for="item in carrierOptions"
|
||||
:key="item.id || item.customerName || item.carrierName"
|
||||
:label="item.customerName || item.carrierName || item.name"
|
||||
:value="item.customerName || item.carrierName || item.name"
|
||||
:key="item.id || item.fullName || item.customerName || item.carrierName"
|
||||
:label="item.fullName || item.customerName || item.carrierName || item.name"
|
||||
:value="item.fullName || item.customerName || item.carrierName || item.name"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
@@ -214,7 +214,7 @@
|
||||
<div class="loading-manage-page__search-actions">
|
||||
<el-button type="primary" @click="handleSearch">查询</el-button>
|
||||
<el-button @click="handleResetSearch">重置</el-button>
|
||||
<el-link type="primary" @click="searchExpanded = !searchExpanded">{{ searchExpanded ? '收起筛选' : '展开筛选' }}</el-link>
|
||||
<el-link type="primary" @click="searchExpanded = !searchExpanded">{{ searchExpanded ? '收起' : '展开' }}</el-link>
|
||||
</div>
|
||||
</div>
|
||||
</el-form>
|
||||
@@ -350,7 +350,29 @@
|
||||
@closed="resetLoadingDialog"
|
||||
>
|
||||
<div v-loading="dialogLoading" class="loading-manage-dialog__body">
|
||||
<div v-if="dialogReadonly" class="loading-detail">
|
||||
<section-card title="配载单详情">
|
||||
<div class="loading-detail__summary">
|
||||
<div class="loading-detail__heading">配载单详情</div>
|
||||
<div>{{ dialogForm.loadingNo || '-' }}</div>
|
||||
<div><el-tag :type="detailStatusType">{{ statusText(dialogForm) }}</el-tag></div>
|
||||
<div><el-tag type="warning">{{ dialogForm.transportType || '-' }}</el-tag></div>
|
||||
</div>
|
||||
<div class="loading-detail__task-row">
|
||||
<div class="loading-detail__field"><span class="loading-detail__label">任务信息</span><span class="loading-detail__value">{{ taskSummary }}</span></div>
|
||||
<div class="loading-detail__field"><span class="loading-detail__label">附件</span><span class="loading-detail__value"><el-link v-for="file in detailAttachments" :key="file.url || file.name" type="primary" @click="previewAttachment(file)">{{ file.name }}</el-link><span v-if="!detailAttachments.length">-</span></span></div>
|
||||
</div>
|
||||
</section-card>
|
||||
<section-card>
|
||||
<template #title><span class="loading-detail__route-title">运输路线<el-link type="primary" @click="openRouteChangeDialog">变更运输路线</el-link></span></template>
|
||||
<div v-if="routeNodes.length" class="loading-detail__steps"><div v-for="(node, index) in routeNodes" :key="node.key || index" class="loading-detail__step"><div class="loading-detail__step-line"><span :class="['loading-detail__step-dot', index === 0 ? 'start' : index === routeNodes.length - 1 ? 'end' : 'middle']">{{ index === 0 ? '起' : index === routeNodes.length - 1 ? '终' : '经' }}</span></div><div class="loading-detail__step-address">{{ node.address }}</div><div class="loading-detail__step-tags"><el-tag v-for="tag in node.tags || []" :key="tag" size="small">{{ tag }}</el-tag></div></div></div><el-empty v-else description="暂无路线" :image-size="60" />
|
||||
</section-card>
|
||||
<section-card title="货物信息"><el-table :data="cargoRows" border height="220"><el-table-column type="index" label="序号" width="70"/><el-table-column prop="projectName" label="项目名称" min-width="140"/><el-table-column prop="cargoName" label="货物名称" min-width="140"/><el-table-column prop="cargoType" label="货物类型" min-width="120"/><el-table-column prop="packageType" label="包装" min-width="100"/><el-table-column prop="weight" label="重量(吨)" min-width="110"/><el-table-column prop="volume" label="体积(方)" min-width="110"/><el-table-column prop="quantity" label="数量" min-width="90"/><el-table-column prop="materialCode" label="物料编码" min-width="120"/><el-table-column prop="equipmentCode" label="设备编码" min-width="120"/><el-table-column prop="brand" label="品牌" min-width="120"/><el-table-column prop="specificationModel" label="规格型号" min-width="140"/><el-table-column prop="remark" label="备注" min-width="160"/><el-table-column prop="unitPrice" label="货物单价(元)" min-width="140"/><el-table-column prop="planDate" label="计划日期" min-width="130"/></el-table></section-card>
|
||||
<section-card title="关联运单信息"><el-table :data="selectedWaybillRows" border><el-table-column type="index" label="序号" width="70"/><el-table-column prop="waybillNo" label="运单号" min-width="150"><template #default="{ row }"><el-link type="primary">{{ row.waybillNo || '-' }}</el-link></template></el-table-column><el-table-column label="配载单号" min-width="150"><template #default>{{ dialogForm.loadingNo || '-' }}</template></el-table-column><el-table-column prop="projectName" label="项目名称" min-width="150"/><el-table-column prop="customerName" label="客户" min-width="140"/><el-table-column prop="departureAddress" label="发货地址" min-width="220" show-overflow-tooltip/><el-table-column prop="arrivalAddress" label="到货地址" min-width="220" show-overflow-tooltip/></el-table></section-card>
|
||||
<div class="loading-detail__bottom-grid"><section-card title="运输节点"><el-timeline v-if="processNodes.length"><el-timeline-item v-for="(item, index) in processNodes" :key="item.id || index" :timestamp="item.time || ''">{{ item.name || item.nodeName || item.label }}</el-timeline-item></el-timeline><el-empty v-else description="暂无运输节点" :image-size="50"/></section-card><section-card title="物流轨迹"><template #extra><div class="loading-detail__track-actions"><el-button plain @click="handleTrackAction('playback')">轨迹回放</el-button><el-button plain @click="handleTrackAction('locate')">实时定位</el-button></div></template><div ref="detailAmap" class="loading-detail__map"></div></section-card></div>
|
||||
</div>
|
||||
<el-form
|
||||
v-else
|
||||
ref="loadingFormRef"
|
||||
:model="dialogForm"
|
||||
:disabled="dialogReadonly"
|
||||
@@ -358,102 +380,9 @@
|
||||
label-width="auto"
|
||||
class="loading-manage-dialog__form"
|
||||
>
|
||||
<section-card title="配载基本信息">
|
||||
<div class="loading-manage-dialog__grid">
|
||||
<el-form-item label="配载单号">
|
||||
<el-input v-model="dialogForm.loadingNo" disabled placeholder="系统自动生成" />
|
||||
</el-form-item>
|
||||
<el-form-item label="运输类型" required>
|
||||
<el-select
|
||||
v-model="dialogForm.transportType"
|
||||
filterable
|
||||
clearable
|
||||
placeholder="请选择"
|
||||
@visible-change="visible => visible && loadTransportTypeOptions()"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in transportTypeOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="项目名称">
|
||||
<el-input v-model="dialogForm.projectName" readonly placeholder="从待配载运单带出" />
|
||||
</el-form-item>
|
||||
<el-form-item label="客户名称">
|
||||
<el-input v-model="dialogForm.customerName" readonly placeholder="从待配载运单带出" />
|
||||
</el-form-item>
|
||||
<el-form-item label="原始单号">
|
||||
<el-input v-model="dialogForm.originalNo" readonly placeholder="从待配载运单带出" />
|
||||
</el-form-item>
|
||||
<el-form-item label="运单批次号">
|
||||
<el-input v-model="dialogForm.batchNo" clearable placeholder="请输入" />
|
||||
</el-form-item>
|
||||
<el-form-item label="数据来源">
|
||||
<el-select v-model="dialogForm.dataSource" clearable placeholder="请选择">
|
||||
<el-option
|
||||
v-for="item in dataSourceOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="计划名称">
|
||||
<el-select
|
||||
v-model="dialogForm.planName"
|
||||
clearable
|
||||
filterable
|
||||
remote
|
||||
reserve-keyword
|
||||
:remote-method="loadPlanOptions"
|
||||
:loading="planLoading"
|
||||
placeholder="请输入"
|
||||
@visible-change="visible => visible && loadPlanOptions(dialogForm.planName)"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in planOptions"
|
||||
:key="item.id || item.planName"
|
||||
:label="item.planName"
|
||||
:value="item.planName"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="开始日期">
|
||||
<el-date-picker
|
||||
v-model="dialogForm.startDate"
|
||||
type="date"
|
||||
format="YYYY-MM-DD"
|
||||
value-format="YYYY-MM-DD"
|
||||
placeholder="请选择"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="结束日期">
|
||||
<el-date-picker
|
||||
v-model="dialogForm.endDate"
|
||||
type="date"
|
||||
format="YYYY-MM-DD"
|
||||
value-format="YYYY-MM-DD"
|
||||
placeholder="请选择"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="配载子单号" class="loading-manage-dialog__span-2">
|
||||
<el-input
|
||||
v-model="dialogForm.loadingSubNos"
|
||||
readonly
|
||||
type="textarea"
|
||||
:rows="2"
|
||||
placeholder="添加待配载运单后自动生成"
|
||||
/>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</section-card>
|
||||
|
||||
<section-card title="筛选待配载运单">
|
||||
<template #extra>
|
||||
<el-link v-if="!dialogReadonly" type="primary" @click="loadCandidateWaybills">筛选</el-link>
|
||||
<el-link v-if="!dialogReadonly" type="primary" @click="openCandidateSearch">筛选</el-link>
|
||||
</template>
|
||||
<div class="loading-manage-dialog__candidate-search" v-if="candidateSearchVisible">
|
||||
<el-row :gutter="16">
|
||||
@@ -584,9 +513,9 @@
|
||||
>
|
||||
<el-option
|
||||
v-for="item in carrierOptions"
|
||||
:key="item.id || item.customerName || item.carrierName"
|
||||
:label="item.customerName || item.carrierName || item.name"
|
||||
:value="item.customerName || item.carrierName || item.name"
|
||||
:key="item.id || item.fullName || item.customerName || item.carrierName"
|
||||
:label="item.fullName || item.customerName || item.carrierName || item.name"
|
||||
:value="item.fullName || item.customerName || item.carrierName || item.name"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
@@ -641,15 +570,12 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
<div class="loading-manage-dialog__selected-summary">
|
||||
<span>已选择 {{ selectedWaybillRows.length }} 条运单</span>
|
||||
</div>
|
||||
<el-table
|
||||
ref="candidateTableRef"
|
||||
v-loading="candidateLoading"
|
||||
:data="candidateRows"
|
||||
border
|
||||
height="260"
|
||||
height="287"
|
||||
row-key="id"
|
||||
@selection-change="candidateSelectionChange"
|
||||
>
|
||||
@@ -723,7 +649,13 @@
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
</el-table>
|
||||
<div class="loading-manage-dialog__pagination">
|
||||
<div class="loading-manage-dialog__table-toolbar">
|
||||
<el-button
|
||||
type="primary"
|
||||
:disabled="!candidateSelection.length || candidateAdding"
|
||||
:loading="candidateAdding"
|
||||
@click="addSelectedWaybills"
|
||||
>添加配载</el-button>
|
||||
<el-pagination
|
||||
v-model:current-page="candidatePage.currentPage"
|
||||
v-model:page-size="candidatePage.pageSize"
|
||||
@@ -736,64 +668,66 @@
|
||||
</div>
|
||||
</section-card>
|
||||
|
||||
<section-card title="待配载列表">
|
||||
<el-table
|
||||
:data="selectedWaybillRows"
|
||||
border
|
||||
class="loading-manage-dialog__selected-table"
|
||||
>
|
||||
<el-table-column type="index" label="序号" width="70" align="center" />
|
||||
<el-table-column prop="waybillNo" label="运单号" min-width="150">
|
||||
<template #default="{ row }">
|
||||
<el-link type="primary">{{ row.waybillNo }}</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="projectName" label="项目名称" min-width="160" />
|
||||
<el-table-column
|
||||
prop="departureAddress"
|
||||
label="发货地"
|
||||
min-width="220"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="arrivalAddress"
|
||||
label="到货地"
|
||||
min-width="220"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column label="操作" width="110" fixed="right">
|
||||
<template #default="{ $index }">
|
||||
<el-link
|
||||
v-if="!dialogReadonly"
|
||||
type="primary"
|
||||
@click="removeSelectedWaybill($index)"
|
||||
>移除</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</section-card>
|
||||
<div class="loading-manage-dialog__waybill-route-layout">
|
||||
<section-card title="待配载列表">
|
||||
<el-table
|
||||
:data="selectedWaybillRows"
|
||||
border
|
||||
class="loading-manage-dialog__selected-table"
|
||||
>
|
||||
<el-table-column type="index" label="序号" width="70" align="center" />
|
||||
<el-table-column prop="waybillNo" label="运单号" min-width="150">
|
||||
<template #default="{ row }">
|
||||
<el-link type="primary">{{ row.waybillNo }}</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="projectName" label="项目名称" min-width="160" />
|
||||
<el-table-column
|
||||
prop="departureAddress"
|
||||
label="发货地"
|
||||
min-width="220"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="arrivalAddress"
|
||||
label="到货地"
|
||||
min-width="220"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column label="操作" width="110" fixed="right">
|
||||
<template #default="{ $index }">
|
||||
<el-link
|
||||
v-if="!dialogReadonly"
|
||||
type="danger"
|
||||
@click="removeSelectedWaybill($index)"
|
||||
>删除</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</section-card>
|
||||
|
||||
<section-card title="路线信息">
|
||||
<div class="loading-manage-dialog__route-list" v-if="routeNodes.length">
|
||||
<div
|
||||
v-for="(node, index) in routeNodes"
|
||||
:key="node.key"
|
||||
class="loading-manage-dialog__route-item"
|
||||
draggable="true"
|
||||
@dragstart="handleRouteDragStart(index)"
|
||||
@dragover.prevent
|
||||
@drop="handleRouteDrop(index)"
|
||||
>
|
||||
<el-icon class="loading-manage-dialog__route-handle"><Rank /></el-icon>
|
||||
<span class="loading-manage-dialog__route-type">{{ routeTypeText(index) }}</span>
|
||||
<span class="loading-manage-dialog__route-address">{{ node.address }}</span>
|
||||
<span class="loading-manage-dialog__route-tags">
|
||||
<el-tag v-for="tag in node.tags" :key="tag" size="small">{{ tag }}</el-tag>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<el-empty v-else description="添加待配载运单后自动生成路线" :image-size="72" />
|
||||
</section-card>
|
||||
<section-card title="线路编辑">
|
||||
<div class="loading-manage-dialog__route-list" v-if="routeNodes.length">
|
||||
<div
|
||||
v-for="(node, index) in routeNodes"
|
||||
:key="node.key"
|
||||
class="loading-manage-dialog__route-item"
|
||||
draggable="true"
|
||||
@dragstart="handleRouteDragStart(index)"
|
||||
@dragover.prevent
|
||||
@drop="handleRouteDrop(index)"
|
||||
>
|
||||
<el-icon class="loading-manage-dialog__route-handle"><Rank /></el-icon>
|
||||
<span class="loading-manage-dialog__route-type">{{ routeTypeText(index) }}</span>
|
||||
<span class="loading-manage-dialog__route-address">{{ node.address }}</span>
|
||||
<span class="loading-manage-dialog__route-tags">
|
||||
<el-tag v-for="tag in node.tags" :key="tag" size="small">{{ tag }}</el-tag>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<el-empty v-else description="添加待配载运单后自动生成路线" :image-size="72" />
|
||||
</section-card>
|
||||
</div>
|
||||
|
||||
<section-card title="货物信息">
|
||||
<el-table :data="cargoRows" border class="loading-manage-dialog__cargo-table">
|
||||
@@ -805,11 +739,13 @@
|
||||
<el-table-column prop="weight" label="重量(吨)" min-width="120" />
|
||||
<el-table-column prop="volume" label="体积(方)" min-width="120" />
|
||||
<el-table-column prop="quantity" label="数量" min-width="100" />
|
||||
<el-table-column prop="planDate" label="计划日期" min-width="130" sortable/>
|
||||
<el-table-column prop="unitPrice" label="货物单价(元)" min-width="150" />
|
||||
<el-table-column prop="materialCode" label="物料编码" min-width="130" />
|
||||
<el-table-column prop="equipmentCode" label="设备编码" min-width="130" />
|
||||
<el-table-column prop="brand" label="品牌" min-width="120" />
|
||||
<el-table-column prop="specificationModel" label="规格型号" min-width="140" />
|
||||
<el-table-column prop="remark" label="备注" min-width="180" show-overflow-tooltip />
|
||||
<el-table-column prop="unitPrice" label="货物单价(元)" min-width="150" />
|
||||
<el-table-column prop="planDate" label="计划日期" min-width="130" sortable />
|
||||
</el-table>
|
||||
</section-card>
|
||||
|
||||
@@ -837,9 +773,9 @@
|
||||
>
|
||||
<el-option
|
||||
v-for="item in carrierOptions"
|
||||
:key="item.id || item.customerName || item.carrierName"
|
||||
:label="item.customerName || item.carrierName || item.name"
|
||||
:value="item.customerName || item.carrierName || item.name"
|
||||
:key="item.id || item.fullName || item.customerName || item.carrierName"
|
||||
:label="item.fullName || item.customerName || item.carrierName || item.name"
|
||||
:value="item.fullName || item.customerName || item.carrierName || item.name"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
@@ -939,6 +875,30 @@
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<el-dialog v-model="routeChangeVisible" title="变更运输路线" append-to-body destroy-on-close width="78%" class="loading-route-change-dialog">
|
||||
<el-tabs v-model="routeChangeTab">
|
||||
<el-tab-pane label="变更路线" name="change">
|
||||
<section-card title="关联子运单地址">
|
||||
<el-table :data="routeChangeRows" border>
|
||||
<el-table-column type="index" label="序号" width="70" />
|
||||
<el-table-column prop="waybillNo" label="运单号" min-width="150"><template #default="{ row }"><el-link type="primary">{{ row.waybillNo || '-' }}</el-link></template></el-table-column>
|
||||
<el-table-column prop="projectName" label="项目名称" min-width="160" />
|
||||
<el-table-column label="发货地" min-width="310"><template #default="{ row }"><div class="loading-route-change-dialog__original">原:{{ row.originalDepartureAddress || '-' }}</div><el-input v-model="row.departureAddress" placeholder="请选择或输入地址" @input="updateRouteChangeNodes"><template #suffix><el-icon class="loading-route-change-dialog__location" @click="openCommonAddressDialog(row, 'departure')"><Location /></el-icon></template></el-input></template></el-table-column>
|
||||
<el-table-column label="到货地" min-width="310"><template #default="{ row }"><div class="loading-route-change-dialog__original">原:{{ row.originalArrivalAddress || '-' }}</div><el-input v-model="row.arrivalAddress" placeholder="请选择或输入地址" @input="updateRouteChangeNodes"><template #suffix><el-icon class="loading-route-change-dialog__location" @click="openCommonAddressDialog(row, 'arrival')"><Location /></el-icon></template></el-input></template></el-table-column>
|
||||
</el-table>
|
||||
</section-card>
|
||||
<section-card title="路线编辑"><template #extra><span class="loading-route-change-dialog__hint">拖拽调整顺序</span></template><div v-if="routeChangeNodes.length" class="loading-route-change-dialog__route-list"><div v-for="(node, index) in routeChangeNodes" :key="node.key || index" class="loading-route-change-dialog__route-item" draggable="true" @dragstart="handleRouteChangeDragStart(index)" @dragover.prevent @drop="handleRouteChangeDrop(index)"><span class="loading-route-change-dialog__route-type">{{ routeChangeTypeText(index) }}</span><span>{{ node.address }}</span><span class="loading-route-change-dialog__tags"><el-tag v-for="tag in node.tags || []" :key="tag" size="small">{{ tag }}</el-tag></span><el-icon><Rank /></el-icon></div></div><el-empty v-else description="暂无路线" :image-size="60" /></section-card>
|
||||
<el-form label-width="auto"><el-form-item label="变更备注"><el-input v-model="routeChangeRemark" type="textarea" :rows="1" maxlength="200" show-word-limit placeholder="请输入" /></el-form-item></el-form>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="变更记录" name="records"><el-table :data="routeChangeRecords" border><el-table-column prop="changeTime" label="变更时间" min-width="170"/><el-table-column prop="changeUser" label="变更人" min-width="120"/><el-table-column prop="content" label="变更内容" min-width="360"><template #default="{ row }"><div class="loading-route-change-dialog__record-content">{{ row.content || '-' }}</div></template></el-table-column><el-table-column prop="remark" label="备注" min-width="200" show-overflow-tooltip/></el-table><el-empty v-if="!routeChangeRecords.length" description="暂无变更记录" :image-size="60"/></el-tab-pane>
|
||||
</el-tabs>
|
||||
<template #footer><el-button @click="routeChangeVisible = false">关闭</el-button><el-button v-if="routeChangeTab === 'change'" type="primary" @click="confirmRouteChange">确认变更</el-button></template>
|
||||
</el-dialog>
|
||||
<el-dialog v-model="commonAddressVisible" title="选择常用地址" append-to-body width="900px" class="loading-common-address-dialog">
|
||||
<div class="loading-common-address-dialog__toolbar"><el-input v-model="commonAddressQuery.addressName" clearable placeholder="请输入地址名称" @keyup.enter="loadCommonAddresses"/><el-button type="primary" @click="loadCommonAddresses">查询</el-button></div>
|
||||
<el-table v-loading="commonAddressLoading" :data="commonAddressRows" border @row-dblclick="selectCommonAddress"><el-table-column prop="addressName" label="地址名称" min-width="180"/><el-table-column prop="regionName" label="区域" min-width="180"/><el-table-column prop="detailAddress" label="详细地址" min-width="260"/><el-table-column label="操作" width="90"><template #default="{ row }"><el-link type="primary" @click="selectCommonAddress(row)">选择</el-link></template></el-table-column></el-table>
|
||||
<template #footer><el-pagination v-model:current-page="commonAddressPage.currentPage" v-model:page-size="commonAddressPage.pageSize" layout="total, prev, pager, next" :total="commonAddressPage.total" @current-change="loadCommonAddresses"/><el-button @click="commonAddressVisible = false">关闭</el-button></template>
|
||||
</el-dialog>
|
||||
</basic-container>
|
||||
</template>
|
||||
|
||||
@@ -956,6 +916,8 @@ import {
|
||||
import { getParentOptions as getCargoTypeOptions } from '@/api/base/cargo-type';
|
||||
import { getList as getCustomerList } from '@/api/vehicle/customer-archive';
|
||||
import { getList as getDriverList } from '@/api/transportCapacity/driver';
|
||||
import { getList as getProcessConfigList } from '@/api/business/process-config';
|
||||
import { getList as getCommonAddressList } from '@/api/base/common-address';
|
||||
import {
|
||||
carrierTypeOptions,
|
||||
loadingManageConfig,
|
||||
@@ -963,11 +925,14 @@ import {
|
||||
loadingStatusOptions,
|
||||
} from '@/option/business/loading-manage';
|
||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
import { Rank, Refresh, Setting } from '@element-plus/icons-vue';
|
||||
import { Location, Rank, Refresh, Setting } from '@element-plus/icons-vue';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
const defaultTransportType = '公路整车';
|
||||
const defaultCandidateTransportType = '公路运输';
|
||||
const defaultTransportType = '';
|
||||
const defaultCandidateTransportType = '';
|
||||
const AMAP_KEY = '653b7cf105ad7fb8ec9b2f5198ade315';
|
||||
const AMAP_SECURITY_CODE = '5aab65c632e48ebae0d0e28f5b28e21a';
|
||||
let detailAmapLoader;
|
||||
|
||||
const createSearchForm = () => ({
|
||||
loadingNo: '',
|
||||
@@ -1091,6 +1056,7 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
Rank,
|
||||
Location,
|
||||
Refresh,
|
||||
Setting,
|
||||
loading: false,
|
||||
@@ -1102,7 +1068,7 @@ export default {
|
||||
total: 0,
|
||||
pageSizes: [10, 20, 50, 100],
|
||||
},
|
||||
searchExpanded: true,
|
||||
searchExpanded: false,
|
||||
searchForm: createSearchForm(),
|
||||
selectionRows: [],
|
||||
dialogVisible: false,
|
||||
@@ -1110,9 +1076,10 @@ export default {
|
||||
dialogLoading: false,
|
||||
dialogSaving: '',
|
||||
dialogForm: createDialogForm(),
|
||||
candidateSearchVisible: true,
|
||||
candidateSearchVisible: false,
|
||||
candidateQuery: createCandidateSearchForm(),
|
||||
candidateLoading: false,
|
||||
candidateAdding: false,
|
||||
candidateRows: [],
|
||||
candidateSelection: [],
|
||||
candidatePage: {
|
||||
@@ -1142,6 +1109,21 @@ export default {
|
||||
statusOptions: loadingStatusOptions,
|
||||
dataSourceOptions: loadingManageConfig.dataSourceOptions,
|
||||
config: loadingManageConfig,
|
||||
processNodes: [],
|
||||
routeChangeVisible: false,
|
||||
routeChangeTab: 'change',
|
||||
routeChangeRows: [],
|
||||
routeChangeNodes: [],
|
||||
routeChangeRemark: '',
|
||||
routeChangeRecords: [],
|
||||
routeChangeDragIndex: -1,
|
||||
commonAddressVisible: false,
|
||||
commonAddressLoading: false,
|
||||
commonAddressRows: [],
|
||||
commonAddressQuery: { addressName: '' },
|
||||
commonAddressPage: { currentPage: 1, pageSize: 10, total: 0 },
|
||||
commonAddressTarget: null,
|
||||
detailAmap: null,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@@ -1158,6 +1140,20 @@ export default {
|
||||
};
|
||||
return titleMap[this.dialogMode] || '配载管理';
|
||||
},
|
||||
detailStatusType() {
|
||||
const typeMap = { pending: 'success', running: 'success', completed: 'info', cancelled: 'info', draft: 'warning' };
|
||||
return typeMap[this.dialogForm.businessStatus] || 'info';
|
||||
},
|
||||
taskSummary() {
|
||||
return [this.dialogForm.carrierName, this.dialogForm.driverName, this.dialogForm.vehicleNo]
|
||||
.filter(Boolean)
|
||||
.join(' / ') || '-';
|
||||
},
|
||||
detailAttachments() {
|
||||
return parseJsonArray(this.dialogForm.attachmentsJson || this.dialogForm.attachmentJson).map(item =>
|
||||
typeof item === 'string' ? { name: item.split('/').pop(), url: item } : { name: item.name || item.fileName || '附件', url: item.url || item.link || item.fileUrl }
|
||||
);
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.loadTransportTypeOptions();
|
||||
@@ -1294,6 +1290,9 @@ export default {
|
||||
this.dialogForm.loadingSubNos
|
||||
);
|
||||
this.restoreRouteAndCargo();
|
||||
this.restoreRouteChangeRecords();
|
||||
await this.loadProcessNodes();
|
||||
this.$nextTick(() => this.initDetailAmap());
|
||||
await this.loadCandidateWaybills();
|
||||
} else {
|
||||
this.dialogForm = createDialogForm();
|
||||
@@ -1310,6 +1309,8 @@ export default {
|
||||
this.dialogLoading = false;
|
||||
},
|
||||
resetDialogData() {
|
||||
this.detailAmap?.destroy?.();
|
||||
this.detailAmap = null;
|
||||
this.dialogForm = createDialogForm();
|
||||
this.candidateQuery = createCandidateSearchForm();
|
||||
this.candidateRows = [];
|
||||
@@ -1319,7 +1320,8 @@ export default {
|
||||
this.cargoRows = [];
|
||||
this.candidatePage.currentPage = 1;
|
||||
this.candidatePage.total = 0;
|
||||
this.candidateSearchVisible = true;
|
||||
this.candidateSearchVisible = false;
|
||||
this.processNodes = [];
|
||||
},
|
||||
clearLoadingDialog() {
|
||||
this.resetDialogData();
|
||||
@@ -1333,6 +1335,164 @@ export default {
|
||||
: this.buildRouteNodes(this.selectedWaybillRows);
|
||||
this.cargoRows = cargoRows.length ? cargoRows : this.buildCargoRows(this.selectedWaybillRows);
|
||||
},
|
||||
restoreRouteChangeRecords() {
|
||||
try {
|
||||
const taskInfo = JSON.parse(this.dialogForm.taskInfoJson || '{}');
|
||||
this.routeChangeRecords = Array.isArray(taskInfo.routeChangeRecords)
|
||||
? [...taskInfo.routeChangeRecords].sort((a, b) => String(b.changeTime).localeCompare(String(a.changeTime)))
|
||||
: [];
|
||||
} catch (error) {
|
||||
this.routeChangeRecords = [];
|
||||
}
|
||||
},
|
||||
async loadProcessNodes() {
|
||||
const waybillProcess = parseJsonArray(this.selectedWaybillRows[0]?.processJson);
|
||||
if (waybillProcess.length) {
|
||||
this.processNodes = waybillProcess;
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const rows = unwrapRecords(await getProcessConfigList(1, 20, { projectId: this.dialogForm.projectId, status: 1 }));
|
||||
const config = rows.find(item => item.nodeConfigJson) || {};
|
||||
this.processNodes = parseJsonArray(config.nodeConfigJson);
|
||||
} catch (error) {
|
||||
this.processNodes = [];
|
||||
}
|
||||
},
|
||||
previewAttachment(file) {
|
||||
if (!file.url) {
|
||||
ElMessage.info('暂无可预览的附件地址');
|
||||
return;
|
||||
}
|
||||
window.open(file.url, '_blank', 'noopener,noreferrer');
|
||||
},
|
||||
loadDetailAmap() {
|
||||
if (window.AMap?.Map) return Promise.resolve();
|
||||
if (!detailAmapLoader) {
|
||||
detailAmapLoader = new Promise((resolve, reject) => {
|
||||
window._AMapSecurityConfig = { securityJsCode: AMAP_SECURITY_CODE };
|
||||
const script = document.createElement('script');
|
||||
script.src = `https://webapi.amap.com/maps?v=2.0&key=${AMAP_KEY}`;
|
||||
script.async = true;
|
||||
script.onload = resolve;
|
||||
script.onerror = () => reject(new Error('高德地图组件加载失败'));
|
||||
document.body.appendChild(script);
|
||||
});
|
||||
}
|
||||
return detailAmapLoader;
|
||||
},
|
||||
initDetailAmap() {
|
||||
if (!this.$refs.detailAmap) return;
|
||||
this.loadDetailAmap()
|
||||
.then(() => {
|
||||
if (!this.detailAmap) {
|
||||
this.detailAmap = new window.AMap.Map(this.$refs.detailAmap, {
|
||||
center: [116.40769, 39.89945],
|
||||
zoom: 11,
|
||||
});
|
||||
window.AMap.plugin(['AMap.ToolBar'], () => this.detailAmap?.addControl(new window.AMap.ToolBar()));
|
||||
} else {
|
||||
this.detailAmap.resize?.();
|
||||
}
|
||||
})
|
||||
.catch(() => ElMessage.warning('高德地图加载失败'));
|
||||
},
|
||||
handleTrackAction(action) {
|
||||
ElMessage.info(action === 'playback' ? '暂无可回放的物流轨迹' : '暂无车辆实时定位数据');
|
||||
},
|
||||
openRouteChangeDialog() {
|
||||
this.routeChangeTab = 'change';
|
||||
this.routeChangeRemark = '';
|
||||
this.routeChangeRows = this.selectedWaybillRows.map(row => ({
|
||||
...row,
|
||||
originalDepartureAddress: row.departureAddress || row.departureName || '',
|
||||
originalArrivalAddress: row.arrivalAddress || row.arrivalName || '',
|
||||
departureAddress: row.departureAddress || row.departureName || '',
|
||||
arrivalAddress: row.arrivalAddress || row.arrivalName || '',
|
||||
}));
|
||||
this.routeChangeNodes = this.buildRouteNodes(this.routeChangeRows);
|
||||
this.routeChangeVisible = true;
|
||||
},
|
||||
routeChangeTypeText(index) {
|
||||
if (index === 0) return '起';
|
||||
if (index === this.routeChangeNodes.length - 1) return '终';
|
||||
return '经';
|
||||
},
|
||||
handleRouteChangeDragStart(index) {
|
||||
this.routeChangeDragIndex = index;
|
||||
},
|
||||
handleRouteChangeDrop(index) {
|
||||
if (this.routeChangeDragIndex < 0 || this.routeChangeDragIndex === index) return;
|
||||
const nodes = [...this.routeChangeNodes];
|
||||
const [node] = nodes.splice(this.routeChangeDragIndex, 1);
|
||||
nodes.splice(index, 0, node);
|
||||
this.routeChangeNodes = nodes;
|
||||
this.routeChangeDragIndex = -1;
|
||||
},
|
||||
updateRouteChangeNodes() {
|
||||
this.routeChangeNodes = this.buildRouteNodes(this.routeChangeRows);
|
||||
},
|
||||
openCommonAddressDialog(row, field) {
|
||||
this.commonAddressTarget = { row, field };
|
||||
this.commonAddressQuery = { addressName: '' };
|
||||
this.commonAddressPage.currentPage = 1;
|
||||
this.commonAddressVisible = true;
|
||||
this.loadCommonAddresses();
|
||||
},
|
||||
async loadCommonAddresses() {
|
||||
this.commonAddressLoading = true;
|
||||
try {
|
||||
const page = unwrapPage(await getCommonAddressList(this.commonAddressPage.currentPage, this.commonAddressPage.pageSize, { ...this.commonAddressQuery, allDept: 0 }));
|
||||
this.commonAddressRows = page.records;
|
||||
this.commonAddressPage.total = page.total;
|
||||
} finally {
|
||||
this.commonAddressLoading = false;
|
||||
}
|
||||
},
|
||||
selectCommonAddress(address) {
|
||||
const target = this.commonAddressTarget;
|
||||
if (!target) return;
|
||||
target.row[`${target.field}Address`] = [address.regionName, address.detailAddress || address.addressName].filter(Boolean).join('') || address.addressName || '';
|
||||
this.updateRouteChangeNodes();
|
||||
this.commonAddressVisible = false;
|
||||
},
|
||||
async confirmRouteChange() {
|
||||
const changeRows = this.routeChangeRows.filter(row => row.departureAddress !== row.originalDepartureAddress || row.arrivalAddress !== row.originalArrivalAddress);
|
||||
if (!changeRows.length && !this.routeChangeRemark) {
|
||||
ElMessage.warning('请修改地址或填写变更备注');
|
||||
return;
|
||||
}
|
||||
const content = changeRows.map(row => `${row.waybillNo || '运单'}:发货地 ${row.originalDepartureAddress} → ${row.departureAddress};到货地 ${row.originalArrivalAddress} → ${row.arrivalAddress}`).join(';') || '调整运输路线顺序';
|
||||
this.routeChangeRecords.unshift({ changeTime: dayjs().format('YYYY-MM-DD HH:mm:ss'), changeUser: '当前用户', content, remark: this.routeChangeRemark });
|
||||
let taskInfo = {};
|
||||
try {
|
||||
taskInfo = JSON.parse(this.dialogForm.taskInfoJson || '{}');
|
||||
} catch (error) {
|
||||
taskInfo = {};
|
||||
}
|
||||
this.dialogForm.taskInfoJson = JSON.stringify({
|
||||
...(typeof taskInfo === 'object' && !Array.isArray(taskInfo) ? taskInfo : {}),
|
||||
routeChangeRecords: this.routeChangeRecords,
|
||||
});
|
||||
this.selectedWaybillRows = this.routeChangeRows.map(({ originalDepartureAddress, originalArrivalAddress, ...row }) => row);
|
||||
this.routeNodes = this.routeChangeNodes;
|
||||
this.syncRouteAddressFields();
|
||||
try {
|
||||
await loadingApi.changeRoute({
|
||||
id: this.dialogForm.id,
|
||||
routeJson: JSON.stringify(this.routeNodes),
|
||||
departureAddress: this.dialogForm.departureAddress,
|
||||
transitAddress: this.dialogForm.transitAddress,
|
||||
arrivalAddress: this.dialogForm.arrivalAddress,
|
||||
taskInfoJson: this.dialogForm.taskInfoJson,
|
||||
});
|
||||
this.routeChangeVisible = false;
|
||||
ElMessage.success('路线变更已保存');
|
||||
} catch (error) {
|
||||
this.restoreRouteChangeRecords();
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
async restoreWaybillRows(idsJson, loadingSubNos) {
|
||||
const ids = parseJsonArray(idsJson).filter(Boolean);
|
||||
if (ids.length) {
|
||||
@@ -1369,6 +1529,10 @@ export default {
|
||||
this.candidateLoading = false;
|
||||
}
|
||||
},
|
||||
openCandidateSearch() {
|
||||
this.candidateSearchVisible = true;
|
||||
this.loadCandidateWaybills();
|
||||
},
|
||||
handleCandidateSearch() {
|
||||
this.candidatePage.currentPage = 1;
|
||||
this.loadCandidateWaybills();
|
||||
@@ -1390,20 +1554,38 @@ export default {
|
||||
candidateSelectionChange(rows) {
|
||||
this.candidateSelection = rows || [];
|
||||
},
|
||||
addSelectedWaybills() {
|
||||
const exists = new Set(this.selectedWaybillRows.map(row => String(row.id || row.waybillNo)));
|
||||
const nextRows = [...this.selectedWaybillRows];
|
||||
this.candidateSelection.forEach(row => {
|
||||
const key = String(row.id || row.waybillNo);
|
||||
if (!exists.has(key)) {
|
||||
nextRows.push(row);
|
||||
exists.add(key);
|
||||
}
|
||||
});
|
||||
this.selectedWaybillRows = nextRows;
|
||||
this.rebuildSummaryFromWaybills();
|
||||
this.$refs.candidateTableRef?.clearSelection?.();
|
||||
this.candidateSelection = [];
|
||||
async addSelectedWaybills() {
|
||||
this.candidateAdding = true;
|
||||
try {
|
||||
const selectedRows = await Promise.all(
|
||||
this.candidateSelection.map(async row => {
|
||||
if (!row.id) return row;
|
||||
try {
|
||||
const res = await getWaybillDetail(row.id);
|
||||
return { ...row, ...(res.data?.data || res.data || {}) };
|
||||
} catch (error) {
|
||||
return row;
|
||||
}
|
||||
})
|
||||
);
|
||||
const exists = new Set(
|
||||
this.selectedWaybillRows.map(row => String(row.id || row.waybillNo))
|
||||
);
|
||||
const nextRows = [...this.selectedWaybillRows];
|
||||
selectedRows.forEach(row => {
|
||||
const key = String(row.id || row.waybillNo);
|
||||
if (!exists.has(key)) {
|
||||
nextRows.push(row);
|
||||
exists.add(key);
|
||||
}
|
||||
});
|
||||
this.selectedWaybillRows = nextRows;
|
||||
this.rebuildSummaryFromWaybills();
|
||||
this.$refs.candidateTableRef?.clearSelection?.();
|
||||
this.candidateSelection = [];
|
||||
} finally {
|
||||
this.candidateAdding = false;
|
||||
}
|
||||
},
|
||||
removeSelectedWaybill(index) {
|
||||
this.selectedWaybillRows.splice(index, 1);
|
||||
@@ -1444,17 +1626,18 @@ export default {
|
||||
},
|
||||
buildRouteNodes(rows) {
|
||||
const nodeMap = new Map();
|
||||
const appendNode = (address, tag) => {
|
||||
if (!address) return;
|
||||
if (!nodeMap.has(address)) nodeMap.set(address, { address, tags: [] });
|
||||
nodeMap.get(address).tags.push(tag);
|
||||
};
|
||||
rows.forEach((row, rowIndex) => {
|
||||
const departure = row.departureAddress || row.departureName;
|
||||
appendNode(departure, `装${rowIndex + 1}`);
|
||||
});
|
||||
rows.forEach((row, rowIndex) => {
|
||||
const arrival = row.arrivalAddress || row.arrivalName;
|
||||
if (departure) {
|
||||
if (!nodeMap.has(departure)) nodeMap.set(departure, { address: departure, tags: [] });
|
||||
nodeMap.get(departure).tags.push(`装${rowIndex + 1}`);
|
||||
}
|
||||
if (arrival) {
|
||||
if (!nodeMap.has(arrival)) nodeMap.set(arrival, { address: arrival, tags: [] });
|
||||
nodeMap.get(arrival).tags.push(`卸${rowIndex + 1}`);
|
||||
}
|
||||
appendNode(arrival, `卸${rowIndex + 1}`);
|
||||
});
|
||||
return [...nodeMap.values()].map((node, index) => ({
|
||||
...node,
|
||||
@@ -1489,7 +1672,7 @@ export default {
|
||||
},
|
||||
buildCargoRows(rows) {
|
||||
return rows.flatMap(row => {
|
||||
const goodsRows = parseJsonArray(row.goodsJson);
|
||||
const goodsRows = parseJsonArray(row.goodsList || row.goodsRows || row.goodsJson);
|
||||
if (goodsRows.length) {
|
||||
return goodsRows.map(item => this.normalizeCargoRow(row, item));
|
||||
}
|
||||
@@ -1509,6 +1692,9 @@ export default {
|
||||
unitPrice: item.unitPrice || waybill.unitPrice || '',
|
||||
materialCode: item.materialCode || '',
|
||||
equipmentCode: item.equipmentCode || '',
|
||||
brand: item.brand || item.brandName || waybill.brand || '',
|
||||
specificationModel:
|
||||
item.specificationModel || item.specModel || item.specification || waybill.specificationModel || '',
|
||||
remark: item.remark || '',
|
||||
};
|
||||
},
|
||||
@@ -1694,9 +1880,6 @@ export default {
|
||||
label: item.dictValue || item.label || item.name,
|
||||
value: item.dictKey || item.value || item.dictValue || item.name,
|
||||
}));
|
||||
if (!this.transportTypeOptions.length) {
|
||||
this.transportTypeOptions = [{ label: defaultTransportType, value: defaultTransportType }];
|
||||
}
|
||||
},
|
||||
async loadProjectOptions(keyword = '') {
|
||||
this.projectLoading = true;
|
||||
@@ -1710,7 +1893,7 @@ export default {
|
||||
this.customerLoading = true;
|
||||
try {
|
||||
this.customerOptions = unwrapRecords(
|
||||
await getCustomerList(1, 20, { customerName: keyword })
|
||||
await getCustomerList(1, 20, { customerName: keyword, customerType: '承运商' })
|
||||
);
|
||||
} finally {
|
||||
this.customerLoading = false;
|
||||
@@ -1892,10 +2075,17 @@ export default {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.loading-manage-dialog__waybill-route-layout {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 2fr) minmax(320px, 1fr);
|
||||
gap: 16px;
|
||||
align-items: start;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.loading-manage-dialog__candidate-actions,
|
||||
.loading-manage-dialog__collapsed-search,
|
||||
.loading-manage-dialog__table-toolbar,
|
||||
.loading-manage-dialog__pagination,
|
||||
.loading-manage-dialog__footer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -1908,16 +2098,18 @@ export default {
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
.loading-manage-dialog__pagination {
|
||||
padding: 10px 0 4px;
|
||||
}
|
||||
|
||||
.loading-manage-dialog__route-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
@media (max-width: 1200px) {
|
||||
.loading-manage-dialog__waybill-route-layout {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
.loading-manage-dialog__route-item {
|
||||
display: grid;
|
||||
grid-template-columns: 28px 36px minmax(0, 1fr) auto;
|
||||
@@ -1998,4 +2190,33 @@ export default {
|
||||
--el-table-border-color: #eff1f7;
|
||||
}
|
||||
}
|
||||
|
||||
.loading-detail {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
color: #303133;
|
||||
.loading-detail__summary { display: flex; align-items: center; flex-wrap: wrap; gap: 24px; padding: 4px 0 16px; }
|
||||
.loading-detail__heading { font-size: 20px; font-weight: 600; margin-right: 8px; }
|
||||
.loading-detail__route-title { display: inline-flex; align-items: center; gap: 16px; }
|
||||
.loading-detail__label { color: #909399; margin-right: 10px; }
|
||||
.loading-detail__task-row { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; padding-bottom: 4px; }
|
||||
.loading-detail__field { display: flex; flex-direction: column; align-items: flex-start; gap: 8px; }
|
||||
.loading-detail__field .loading-detail__label { margin-right: 0; }
|
||||
.loading-detail__value { display: flex; flex-wrap: wrap; gap: 8px; text-align: left; }
|
||||
.loading-detail__steps { display: flex; align-items: flex-start; overflow-x: auto; padding: 8px 4px 16px; }
|
||||
.loading-detail__step { position: relative; min-width: 190px; flex: 1; text-align: center; }
|
||||
.loading-detail__step:not(:last-child)::after { position: absolute; z-index: 0; top: 16px; left: calc(50% + 25px); width: calc(100% - 50px); height: 2px; content: ''; background: #606266; }
|
||||
.loading-detail__step-line { display: flex; align-items: center; justify-content: center; }
|
||||
.loading-detail__step-dot { position: relative; z-index: 1; display: inline-flex; width: 34px; height: 34px; align-items: center; justify-content: center; color: #fff; border-radius: 4px; font-weight: 600; }
|
||||
.loading-detail__step-dot.start { background: #409eff; }.loading-detail__step-dot.middle { background: #67c23a; }.loading-detail__step-dot.end { background: #e6a23c; }
|
||||
.loading-detail__step-address { margin-top: 8px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
||||
.loading-detail__step-tags { display: flex; justify-content: center; gap: 4px; margin-top: 6px; }
|
||||
.loading-detail__bottom-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
|
||||
.loading-detail__track-actions { display: flex; gap: 8px; }
|
||||
.loading-detail__map { width: 100%; min-height: 260px; border: 1px solid #eff1f7; }
|
||||
}
|
||||
.loading-route-change-dialog { .loading-route-change-dialog__original { color: #a8abb2; line-height: 20px; margin-bottom: 4px; }.loading-route-change-dialog__location { cursor: pointer; color: #909399; }.loading-route-change-dialog__hint { color: #909399; }.loading-route-change-dialog__route-list { display: flex; flex-direction: column; gap: 8px; }.loading-route-change-dialog__route-item { display: grid; grid-template-columns: 34px minmax(0, 1fr) auto 24px; align-items: center; gap: 12px; padding: 10px 12px; background: #f5f6f7; cursor: move; }.loading-route-change-dialog__route-type { width: 30px; height: 30px; border-radius: 50%; background: #dcdfe6; text-align: center; line-height: 30px; }.loading-route-change-dialog__tags { display: flex; gap: 4px; }.loading-route-change-dialog__record-content { white-space: normal; overflow-wrap: anywhere; line-height: 22px; } }
|
||||
.loading-common-address-dialog__toolbar { display: flex; gap: 8px; margin-bottom: 12px; }.loading-common-address-dialog__toolbar .el-input { flex: 1; }
|
||||
@media (max-width: 900px) { .loading-detail__task-row, .loading-detail__bottom-grid { grid-template-columns: 1fr; } }
|
||||
</style>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<business-crud-page :api="api" :config="config" :crud-option="option" :menu-width="270" />
|
||||
<business-crud-page :api="api" :config="config" :crud-option="option" :menu-width="320" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
@@ -147,9 +147,9 @@
|
||||
:model="archiveForm"
|
||||
:rules="formRules"
|
||||
label-position="right"
|
||||
label-width="auto"
|
||||
label-width="calc(6em + 24px)"
|
||||
:disabled="readonly"
|
||||
class="archive-form"
|
||||
class="archive-form dialog-form-label-fixed"
|
||||
>
|
||||
<section-card title="工商信息">
|
||||
<el-row :gutter="18">
|
||||
@@ -614,7 +614,7 @@
|
||||
</el-table-column>
|
||||
<el-table-column label="文件名称" min-width="180">
|
||||
<template #default="{ row }">
|
||||
<span>{{ row.originalName || row.name || '-' }}</span>
|
||||
<el-link type="primary" :disabled="!row.url" @click="previewQualificationFile(row)">{{ row.originalName || row.name || '-' }}</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="附件描述" min-width="220">
|
||||
@@ -664,6 +664,11 @@
|
||||
</div>
|
||||
</section-card>
|
||||
|
||||
<el-dialog v-model="qualificationDocumentPreviewVisible" :title="qualificationPreviewFile.name || '附件预览'" append-to-body destroy-on-close width="90%" top="4vh">
|
||||
<open-file-viewer v-if="qualificationDocumentPreviewVisible && qualificationPreviewFile.url" :file="qualificationPreviewFile.url" :file-name="qualificationPreviewFile.name" :mime-type="qualificationPreviewFile.mimeType" width="100%" height="72vh" fit="contain" theme="auto" locale="zh-CN" :toolbar="qualificationViewerToolbar" :plugins="qualificationViewerPlugins" @unsupported="handleQualificationPreviewUnsupported" @error="handleQualificationPreviewError" />
|
||||
</el-dialog>
|
||||
<el-image-viewer v-if="qualificationImagePreviewVisible" :url-list="qualificationImagePreviewUrls" :initial-index="qualificationImagePreviewIndex" @close="qualificationImagePreviewVisible = false" />
|
||||
|
||||
<section-card title="变更记录">
|
||||
<el-table :data="changeRecordPage.records" border>
|
||||
<el-table-column
|
||||
@@ -1230,6 +1235,11 @@ import { getToken } from '@/utils/auth';
|
||||
import { getUploadHeaders } from '@/utils/upload';
|
||||
import { normalizeSearchRangeParams } from '@/utils/search-range';
|
||||
import { ArrowRight } from '@element-plus/icons-vue';
|
||||
import { ElImageViewer } from 'element-plus';
|
||||
import { OpenFileViewer } from '@open-file-viewer/vue';
|
||||
import { fallbackPlugin, imagePlugin, officePlugin, pdfPlugin, textPlugin } from '@open-file-viewer/core';
|
||||
import '@open-file-viewer/core/style.css';
|
||||
import pdfWorkerSrc from 'pdfjs-dist/build/pdf.worker.mjs?url';
|
||||
import { mapGetters } from 'vuex';
|
||||
import NProgress from 'nprogress';
|
||||
import 'nprogress/nprogress.css';
|
||||
@@ -1241,10 +1251,19 @@ const createTimeRangeMap = {
|
||||
const AMAP_KEY = '653b7cf105ad7fb8ec9b2f5198ade315';
|
||||
const AMAP_SECURITY_CODE = '5aab65c632e48ebae0d0e28f5b28e21a';
|
||||
let amapLoader;
|
||||
const qualificationViewerPlugins = [
|
||||
imagePlugin(),
|
||||
pdfPlugin({ workerSrc: pdfWorkerSrc, useFetchData: true }),
|
||||
officePlugin({ pdf: { workerSrc: pdfWorkerSrc, useFetchData: true } }),
|
||||
textPlugin(),
|
||||
fallbackPlugin(),
|
||||
];
|
||||
|
||||
export default {
|
||||
components: {
|
||||
ArrowRight,
|
||||
ElImageViewer,
|
||||
OpenFileViewer,
|
||||
},
|
||||
data() {
|
||||
const nonNegativeLabelMap = {
|
||||
@@ -1363,6 +1382,19 @@ export default {
|
||||
qualificationFiles: [],
|
||||
qualificationUploadFiles: [],
|
||||
selectedQualificationFiles: [],
|
||||
qualificationImagePreviewVisible: false,
|
||||
qualificationImagePreviewUrls: [],
|
||||
qualificationImagePreviewIndex: 0,
|
||||
qualificationDocumentPreviewVisible: false,
|
||||
qualificationPreviewFile: {},
|
||||
qualificationViewerPlugins,
|
||||
qualificationViewerToolbar: {
|
||||
download: true,
|
||||
fullscreen: true,
|
||||
print: true,
|
||||
rotate: true,
|
||||
zoom: true,
|
||||
},
|
||||
deptTree: [],
|
||||
deptOptions: [],
|
||||
regionOptions: [],
|
||||
@@ -2748,10 +2780,53 @@ export default {
|
||||
files: [file],
|
||||
});
|
||||
},
|
||||
getQualificationFileUrl(file = {}) {
|
||||
return file.url || file.link || file.domain || '';
|
||||
},
|
||||
getQualificationFileExtension(file = {}) {
|
||||
const name = String(file.originalName || file.name || this.getQualificationFileUrl(file) || '')
|
||||
.split('?')[0];
|
||||
const index = name.lastIndexOf('.');
|
||||
return index > -1 ? name.slice(index + 1).toLowerCase() : '';
|
||||
},
|
||||
isQualificationImage(file) {
|
||||
return ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'].includes(
|
||||
this.getQualificationFileExtension(file)
|
||||
);
|
||||
},
|
||||
previewQualificationFile(file) {
|
||||
const url = this.getQualificationFileUrl(file);
|
||||
if (!url) {
|
||||
this.$message.warning('附件地址为空,无法预览');
|
||||
return;
|
||||
}
|
||||
if (this.isQualificationImage(file)) {
|
||||
this.qualificationImagePreviewUrls = this.qualificationFiles
|
||||
.filter(item => this.isQualificationImage(item) && this.getQualificationFileUrl(item))
|
||||
.map(item => this.getQualificationFileUrl(item));
|
||||
this.qualificationImagePreviewIndex = Math.max(
|
||||
this.qualificationImagePreviewUrls.indexOf(url),
|
||||
0
|
||||
);
|
||||
this.qualificationImagePreviewVisible = true;
|
||||
return;
|
||||
}
|
||||
this.qualificationPreviewFile = {
|
||||
name: file.originalName || file.name || '附件',
|
||||
url,
|
||||
mimeType: file.mimeType || file.contentType || '',
|
||||
};
|
||||
this.qualificationDocumentPreviewVisible = true;
|
||||
},
|
||||
handleQualificationPreviewUnsupported() {
|
||||
this.$message.warning('当前文件暂不支持在线预览');
|
||||
},
|
||||
handleQualificationPreviewError() {
|
||||
this.$message.error('附件预览失败');
|
||||
},
|
||||
resolveQualificationType(fileName) {
|
||||
const name = String(fileName || '').toLocaleLowerCase();
|
||||
return (
|
||||
[...this.qualificationTypeOptions]
|
||||
const matchedType = [...this.qualificationTypeOptions]
|
||||
.filter(item => item?.label || item?.value)
|
||||
.sort(
|
||||
(a, b) =>
|
||||
@@ -2760,8 +2835,14 @@ export default {
|
||||
.find(item => {
|
||||
const typeText = String(item.label || item.value || '').toLocaleLowerCase();
|
||||
return typeText && name.includes(typeText);
|
||||
})?.value || ''
|
||||
});
|
||||
if (matchedType?.value) return matchedType.value;
|
||||
const otherType = this.qualificationTypeOptions.find(item =>
|
||||
String(item.label || item.value || '').includes('其他')
|
||||
);
|
||||
if (otherType?.value) return otherType.value;
|
||||
this.qualificationTypeOptions.push({ label: '其他附件', value: '其他附件' });
|
||||
return '其他附件';
|
||||
},
|
||||
downloadAttachments() {
|
||||
const source = this.selectedQualificationFiles.length
|
||||
@@ -3617,12 +3698,26 @@ export default {
|
||||
}
|
||||
|
||||
.archive-form {
|
||||
:deep(.el-input-number),
|
||||
:deep(.el-select),
|
||||
:deep(.el-cascader),
|
||||
:deep(.el-date-editor) {
|
||||
width: 100%;
|
||||
:deep(.el-form-item__label) {
|
||||
flex: 0 0 calc(6em + 24px) !important;
|
||||
width: calc(6em + 24px) !important;
|
||||
height: auto;
|
||||
min-height: 32px;
|
||||
white-space: normal !important;
|
||||
word-break: break-all;
|
||||
overflow-wrap: anywhere;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
:deep(.el-form-item__content > .el-input),
|
||||
:deep(.el-form-item__content > .el-select),
|
||||
:deep(.el-form-item__content > .el-cascader),
|
||||
:deep(.el-form-item__content > .el-input-number),
|
||||
:deep(.el-form-item__content > .el-date-editor) {
|
||||
width: 220px;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
business-term-field,
|
||||
@@ -3635,7 +3730,8 @@ business-term-field,
|
||||
|
||||
.business-term-field {
|
||||
:deep(.el-date-editor) {
|
||||
flex: 1;
|
||||
flex: 0 0 220px;
|
||||
width: 220px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
@@ -3646,14 +3742,15 @@ business-term-field,
|
||||
}
|
||||
|
||||
.archive-form__address {
|
||||
.el-input,
|
||||
:deep(.el-input),
|
||||
:deep(.el-cascader) {
|
||||
flex: 1;
|
||||
flex: 0 0 220px;
|
||||
width: 220px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
:deep(.el-cascader) {
|
||||
flex: 0 0 36%;
|
||||
flex-basis: 220px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user