fix
This commit is contained in:
@@ -12,8 +12,12 @@ export const config = {
|
|||||||
exportName: '发货模板',
|
exportName: '发货模板',
|
||||||
enableAllDept: false,
|
enableAllDept: false,
|
||||||
enableProjectSelect: true,
|
enableProjectSelect: true,
|
||||||
|
excludeVoidedProjects: true,
|
||||||
enableAttachmentTable: true,
|
enableAttachmentTable: true,
|
||||||
enableTransportPlanForm: true,
|
enableTransportPlanForm: true,
|
||||||
|
enableShippingTemplateFreight: true,
|
||||||
|
editableRoadAddress: true,
|
||||||
|
fixedTransportAddressType: true,
|
||||||
enableTemplateCodePreview: true,
|
enableTemplateCodePreview: true,
|
||||||
attachmentTitle: '附件',
|
attachmentTitle: '附件',
|
||||||
defaultForm: {
|
defaultForm: {
|
||||||
@@ -178,6 +182,7 @@ export const option = {
|
|||||||
labelWidth: '0px',
|
labelWidth: '0px',
|
||||||
className: 'business-crud-page__full-form-item',
|
className: 'business-crud-page__full-form-item',
|
||||||
},
|
},
|
||||||
|
{ label: '运费信息', prop: 'freightJson', hide: true, display: false },
|
||||||
{
|
{
|
||||||
label: '',
|
label: '',
|
||||||
prop: 'attachmentTitle',
|
prop: 'attachmentTitle',
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ const formatGoodsInfo = row => {
|
|||||||
const text = Object.entries(groups)
|
const text = Object.entries(groups)
|
||||||
.map(([unit, group]) => {
|
.map(([unit, group]) => {
|
||||||
const quantity = `${formatGoodsQuantity(group.quantity)}${unit}`;
|
const quantity = `${formatGoodsQuantity(group.quantity)}${unit}`;
|
||||||
return `${group.typeName}等${group.count}中货物 | ${quantity}`;
|
return `${group.typeName}等${group.count}种货物 | ${quantity}`;
|
||||||
})
|
})
|
||||||
.join('; ');
|
.join('; ');
|
||||||
|
|
||||||
|
|||||||
@@ -104,6 +104,40 @@
|
|||||||
</el-tag>
|
</el-tag>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<template #goodsInfo="{ row }">
|
||||||
|
<el-tooltip
|
||||||
|
v-if="isTransportPlanPage"
|
||||||
|
:content="formatTransportPlanGoodsInfo(row)"
|
||||||
|
placement="top"
|
||||||
|
:disabled="formatTransportPlanGoodsInfo(row).length <= 10"
|
||||||
|
>
|
||||||
|
<span>{{ truncateTransportPlanText(formatTransportPlanGoodsInfo(row), 10) }}</span>
|
||||||
|
</el-tooltip>
|
||||||
|
<span v-else>{{ row.goodsInfo || '-' }}</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #departureAddress="{ row }">
|
||||||
|
<el-tooltip
|
||||||
|
v-if="isTransportPlanPage"
|
||||||
|
:content="row.departureAddress || '-'"
|
||||||
|
placement="top"
|
||||||
|
>
|
||||||
|
<span>{{ formatTransportPlanDistrictAddress(row.departureAddress) }}</span>
|
||||||
|
</el-tooltip>
|
||||||
|
<span v-else>{{ row.departureAddress || '-' }}</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #arrivalAddress="{ row }">
|
||||||
|
<el-tooltip
|
||||||
|
v-if="isTransportPlanPage"
|
||||||
|
:content="row.arrivalAddress || '-'"
|
||||||
|
placement="top"
|
||||||
|
>
|
||||||
|
<span>{{ formatTransportPlanDistrictAddress(row.arrivalAddress) }}</span>
|
||||||
|
</el-tooltip>
|
||||||
|
<span v-else>{{ row.arrivalAddress || '-' }}</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
<template #basicInfoTitle-form>
|
<template #basicInfoTitle-form>
|
||||||
<div class="dialog-section-title">基本信息</div>
|
<div class="dialog-section-title">基本信息</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -245,25 +279,36 @@
|
|||||||
v-model="form.departureName"
|
v-model="form.departureName"
|
||||||
readonly
|
readonly
|
||||||
:placeholder="transportStationNamePlaceholder"
|
:placeholder="transportStationNamePlaceholder"
|
||||||
:suffix-icon="transportStationMode ? Search : undefined"
|
|
||||||
:disabled="transportAddressSelectDisabled"
|
:disabled="transportAddressSelectDisabled"
|
||||||
@click="openTransportPrimaryAddressPicker('departure')"
|
@click="openTransportPrimaryAddressPicker('departure')"
|
||||||
/>
|
>
|
||||||
|
<template v-if="transportStationMode" #suffix>
|
||||||
|
<el-icon class="business-crud-page__map-suffix" @click.stop="openTransportSecondaryAddressPicker('departure')">
|
||||||
|
<Search />
|
||||||
|
</el-icon>
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
<el-input
|
<el-input
|
||||||
v-model="form.departureAddress"
|
v-model="form.departureAddress"
|
||||||
readonly
|
:readonly="transportStationMode || !config.editableRoadAddress"
|
||||||
:placeholder="transportAddressDetailPlaceholder"
|
:placeholder="transportAddressDetailPlaceholder"
|
||||||
:suffix-icon="transportStationMode ? undefined : Location"
|
:suffix-icon="transportStationMode || config.editableRoadAddress ? undefined : Location"
|
||||||
:disabled="transportAddressSelectDisabled"
|
:disabled="transportAddressSelectDisabled"
|
||||||
@click="openTransportSecondaryAddressPicker('departure')"
|
@click="handleTransportSecondaryAddressInputClick('departure')"
|
||||||
/>
|
>
|
||||||
|
<template v-if="!transportStationMode && config.editableRoadAddress" #suffix>
|
||||||
|
<el-icon class="business-crud-page__map-suffix" @click.stop="openTransportMapDialog('departure')">
|
||||||
|
<Location />
|
||||||
|
</el-icon>
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
<el-tooltip content="选择常用地址" placement="top">
|
<el-tooltip content="选择常用地址" placement="top">
|
||||||
<el-button
|
<el-button
|
||||||
type="primary"
|
type="primary"
|
||||||
:icon="List"
|
:icon="List"
|
||||||
link
|
link
|
||||||
:disabled="transportAddressSelectDisabled"
|
:disabled="transportAddressSelectDisabled"
|
||||||
@click="openTransportAddressDialog('departure')"
|
@click="openTransportAddressPicker('departure')"
|
||||||
/>
|
/>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
<span class="business-crud-page__route-label">联系人</span>
|
<span class="business-crud-page__route-label">联系人</span>
|
||||||
@@ -283,25 +328,36 @@
|
|||||||
v-model="form.arrivalName"
|
v-model="form.arrivalName"
|
||||||
readonly
|
readonly
|
||||||
:placeholder="transportStationNamePlaceholder"
|
:placeholder="transportStationNamePlaceholder"
|
||||||
:suffix-icon="transportStationMode ? Search : undefined"
|
|
||||||
:disabled="transportAddressSelectDisabled"
|
:disabled="transportAddressSelectDisabled"
|
||||||
@click="openTransportPrimaryAddressPicker('arrival')"
|
@click="openTransportPrimaryAddressPicker('arrival')"
|
||||||
/>
|
>
|
||||||
|
<template v-if="transportStationMode" #suffix>
|
||||||
|
<el-icon class="business-crud-page__map-suffix" @click.stop="openTransportSecondaryAddressPicker('arrival')">
|
||||||
|
<Search />
|
||||||
|
</el-icon>
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
<el-input
|
<el-input
|
||||||
v-model="form.arrivalAddress"
|
v-model="form.arrivalAddress"
|
||||||
readonly
|
:readonly="transportStationMode || !config.editableRoadAddress"
|
||||||
:placeholder="transportAddressDetailPlaceholder"
|
:placeholder="transportAddressDetailPlaceholder"
|
||||||
:suffix-icon="transportStationMode ? undefined : Location"
|
:suffix-icon="transportStationMode || config.editableRoadAddress ? undefined : Location"
|
||||||
:disabled="transportAddressSelectDisabled"
|
:disabled="transportAddressSelectDisabled"
|
||||||
@click="openTransportSecondaryAddressPicker('arrival')"
|
@click="handleTransportSecondaryAddressInputClick('arrival')"
|
||||||
/>
|
>
|
||||||
|
<template v-if="!transportStationMode && config.editableRoadAddress" #suffix>
|
||||||
|
<el-icon class="business-crud-page__map-suffix" @click.stop="openTransportMapDialog('arrival')">
|
||||||
|
<Location />
|
||||||
|
</el-icon>
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
<el-tooltip content="选择常用地址" placement="top">
|
<el-tooltip content="选择常用地址" placement="top">
|
||||||
<el-button
|
<el-button
|
||||||
type="primary"
|
type="primary"
|
||||||
:icon="List"
|
:icon="List"
|
||||||
link
|
link
|
||||||
:disabled="transportAddressSelectDisabled"
|
:disabled="transportAddressSelectDisabled"
|
||||||
@click="openTransportAddressDialog('arrival')"
|
@click="openTransportAddressPicker('arrival')"
|
||||||
/>
|
/>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
<span class="business-crud-page__route-label">联系人</span>
|
<span class="business-crud-page__route-label">联系人</span>
|
||||||
@@ -1235,9 +1291,150 @@
|
|||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
<div class="business-crud-page__cargo-total">
|
<div v-if="!shippingTemplateFreightVisible" class="business-crud-page__cargo-total">
|
||||||
运输数量合计:{{ transportCargoQuantityTotal }}
|
运输数量合计:{{ transportCargoQuantityTotal }}
|
||||||
</div>
|
</div>
|
||||||
|
<section v-if="shippingTemplateFreightVisible" class="business-crud-page__freight-section">
|
||||||
|
<div class="dialog-section-title">
|
||||||
|
运费信息{{ transportMode === 'road' ? '(公路)' : '' }}
|
||||||
|
</div>
|
||||||
|
<template v-if="transportMode === 'road'">
|
||||||
|
<el-form
|
||||||
|
:model="shippingTemplateFreight"
|
||||||
|
label-position="right"
|
||||||
|
label-width="auto"
|
||||||
|
class="business-crud-page__freight-form business-crud-page__freight-form--road"
|
||||||
|
>
|
||||||
|
<template v-for="(row, index) in shippingTemplateFreight.freightItems" :key="index">
|
||||||
|
<el-form-item :label="`单价${index + 1}`">
|
||||||
|
<el-input
|
||||||
|
v-model="row.unitPrice"
|
||||||
|
placeholder="请输入"
|
||||||
|
:disabled="dialogReadonly"
|
||||||
|
@input="value => handleShippingTemplateFreightNumberInput(row, 'unitPrice', value)"
|
||||||
|
>
|
||||||
|
<template #append>
|
||||||
|
<el-select
|
||||||
|
v-model="row.priceUnit"
|
||||||
|
class="business-crud-page__append-select"
|
||||||
|
placeholder="单位"
|
||||||
|
:disabled="dialogReadonly"
|
||||||
|
@visible-change="visible => visible && loadTaskFeeUnitOptions()"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in taskFeeUnitOptions"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="`数量合计${index + 1}`">
|
||||||
|
<el-input :model-value="shippingTemplateRoadFreightQuantity(index)" disabled>
|
||||||
|
<template #append>
|
||||||
|
<el-select
|
||||||
|
:model-value="transportCargoRows[index]?.quantityUnit"
|
||||||
|
class="business-crud-page__append-select"
|
||||||
|
placeholder="单位"
|
||||||
|
disabled
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
:label="transportCargoRows[index]?.quantityUnit || '单位'"
|
||||||
|
:value="transportCargoRows[index]?.quantityUnit || ''"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="`运费${index + 1}`">
|
||||||
|
<el-input :model-value="shippingTemplateRoadFreightAmount(row, index)" disabled>
|
||||||
|
<template #suffix>{{ shippingTemplateCurrencyLabel }}</template>
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</template>
|
||||||
|
<el-form-item label="运费合计">
|
||||||
|
<el-input :model-value="shippingTemplateRoadFreightTotal" disabled>
|
||||||
|
<template #suffix>{{ shippingTemplateCurrencyLabel }}</template>
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="其他运费合计">
|
||||||
|
<el-input
|
||||||
|
v-model="shippingTemplateFreight.otherFreightAmount"
|
||||||
|
placeholder="请输入"
|
||||||
|
:disabled="dialogReadonly"
|
||||||
|
@input="value => handleShippingTemplateFreightNumberInput(shippingTemplateFreight, 'otherFreightAmount', value)"
|
||||||
|
>
|
||||||
|
<template #suffix>{{ shippingTemplateCurrencyLabel }}</template>
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="币种">
|
||||||
|
<el-select
|
||||||
|
v-model="shippingTemplateFreight.currency"
|
||||||
|
placeholder="请选择"
|
||||||
|
clearable
|
||||||
|
:disabled="dialogReadonly"
|
||||||
|
@visible-change="visible => visible && loadShippingTemplateCurrencyOptions()"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in shippingTemplateCurrencyOptions"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</template>
|
||||||
|
<el-form
|
||||||
|
v-else
|
||||||
|
:model="shippingTemplateFreight"
|
||||||
|
label-position="right"
|
||||||
|
label-width="auto"
|
||||||
|
class="business-crud-page__freight-form business-crud-page__freight-form--non-road"
|
||||||
|
>
|
||||||
|
<el-form-item label="运费">
|
||||||
|
<el-input
|
||||||
|
v-model="shippingTemplateFreight.freightAmount"
|
||||||
|
placeholder="请输入"
|
||||||
|
:disabled="dialogReadonly"
|
||||||
|
@input="value => handleShippingTemplateFreightNumberInput(shippingTemplateFreight, 'freightAmount', value)"
|
||||||
|
>
|
||||||
|
<template #suffix>{{ shippingTemplateCurrencyLabel }}</template>
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="数量">
|
||||||
|
<el-input :model-value="transportCargoQuantityTotal" disabled />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="其他运费合计">
|
||||||
|
<el-input
|
||||||
|
v-model="shippingTemplateFreight.otherFreightAmount"
|
||||||
|
placeholder="请输入"
|
||||||
|
:disabled="dialogReadonly"
|
||||||
|
@input="value => handleShippingTemplateFreightNumberInput(shippingTemplateFreight, 'otherFreightAmount', value)"
|
||||||
|
>
|
||||||
|
<template #suffix>{{ shippingTemplateCurrencyLabel }}</template>
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="币种">
|
||||||
|
<el-select
|
||||||
|
v-model="shippingTemplateFreight.currency"
|
||||||
|
placeholder="请选择"
|
||||||
|
clearable
|
||||||
|
:disabled="dialogReadonly"
|
||||||
|
@visible-change="visible => visible && loadShippingTemplateCurrencyOptions()"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in shippingTemplateCurrencyOptions"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -1653,6 +1850,21 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #menu-form-before>
|
<template #menu-form-before>
|
||||||
|
<div
|
||||||
|
v-if="config.enableShippingTemplateFreight && !dialogReadonly"
|
||||||
|
class="business-crud-page__shipping-template-footer-summary"
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
运费合计:<strong>¥{{ formatShippingTemplateFooterFreightTotal }}</strong>
|
||||||
|
</span>
|
||||||
|
<el-link
|
||||||
|
type="primary"
|
||||||
|
:disabled="!form.projectId"
|
||||||
|
@click="openShippingTemplateProcessConfig"
|
||||||
|
>
|
||||||
|
查看过程配置
|
||||||
|
</el-link>
|
||||||
|
</div>
|
||||||
<el-button
|
<el-button
|
||||||
v-if="config.enableDraftSave && !dialogReadonly"
|
v-if="config.enableDraftSave && !dialogReadonly"
|
||||||
type="primary"
|
type="primary"
|
||||||
@@ -3323,6 +3535,7 @@
|
|||||||
clearable
|
clearable
|
||||||
filterable
|
filterable
|
||||||
placeholder="请选择"
|
placeholder="请选择"
|
||||||
|
:disabled="!!getTransportFixedAddressType()"
|
||||||
>
|
>
|
||||||
<el-option
|
<el-option
|
||||||
v-for="item in addressTypeOptions"
|
v-for="item in addressTypeOptions"
|
||||||
@@ -3405,7 +3618,7 @@
|
|||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
<el-dialog
|
<el-dialog
|
||||||
title="选择站点"
|
:title="`选择${transportStationTypeLabel || '站点'}`"
|
||||||
append-to-body
|
append-to-body
|
||||||
v-model="transportStationBox"
|
v-model="transportStationBox"
|
||||||
width="1180px"
|
width="1180px"
|
||||||
@@ -3634,8 +3847,8 @@
|
|||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
<el-dialog title="导入货物" append-to-body v-model="cargoImportBox" width="560px">
|
<el-dialog title="导入货物" append-to-body v-model="cargoImportBox" width="560px">
|
||||||
|
<div class="business-crud-page__cargo-import">
|
||||||
<el-upload
|
<el-upload
|
||||||
drag
|
|
||||||
action="#"
|
action="#"
|
||||||
accept=".xls,.xlsx"
|
accept=".xls,.xlsx"
|
||||||
:auto-upload="false"
|
:auto-upload="false"
|
||||||
@@ -3643,19 +3856,50 @@
|
|||||||
:disabled="cargoImportLoading"
|
:disabled="cargoImportLoading"
|
||||||
:on-change="handleCargoImportFileChange"
|
:on-change="handleCargoImportFileChange"
|
||||||
>
|
>
|
||||||
<i class="el-icon-upload"></i>
|
<el-button type="primary" :loading="cargoImportLoading">上传</el-button>
|
||||||
<div class="el-upload__text">将 Excel 文件拖到此处,或点击上传</div>
|
|
||||||
<template #tip>
|
<template #tip>
|
||||||
<div class="el-upload__tip">
|
<div class="el-upload__tip">支持.xlsx、.xls的文件格式,单个文件大小限制50M</div>
|
||||||
按货物信息表头读取:货物名称、货物类型、数量、数量单位、包装、品牌、规格、型号、物料编码、设备编码、备注
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
</el-upload>
|
</el-upload>
|
||||||
|
<el-button type="primary" @click="handleCargoImportTemplate">点击下载模板</el-button>
|
||||||
|
</div>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<el-button @click="cargoImportBox = false">关闭</el-button>
|
<el-button @click="cargoImportBox = false">关闭</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
|
<el-dialog
|
||||||
|
v-model="shippingTemplateProcessConfigBox"
|
||||||
|
title="过程配置"
|
||||||
|
append-to-body
|
||||||
|
width="980px"
|
||||||
|
class="business-crud-page__process-config-dialog"
|
||||||
|
>
|
||||||
|
<div v-loading="shippingTemplateProcessConfigLoading">
|
||||||
|
<el-table :data="shippingTemplateProcessConfigRows" border empty-text="当前项目暂无过程配置">
|
||||||
|
<el-table-column prop="configCode" label="配置编号" min-width="160" />
|
||||||
|
<el-table-column prop="configName" label="配置名称" min-width="180" />
|
||||||
|
<el-table-column prop="projectNames" label="项目" min-width="220" />
|
||||||
|
<el-table-column label="过程节点" min-width="260">
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{ formatShippingTemplateProcessNodes(row.includedNodes) }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="defaultFinishDays" label="默认完成时限(天)" width="160" />
|
||||||
|
<el-table-column label="状态" width="100" align="center">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-tag :type="Number(row.status) === 1 ? 'success' : 'info'">
|
||||||
|
{{ Number(row.status) === 1 ? '启用' : '停用' }}
|
||||||
|
</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
|
<template #footer>
|
||||||
|
<el-button type="primary" @click="shippingTemplateProcessConfigBox = false">关闭</el-button>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
<el-dialog :title="`${config.title}导入`" append-to-body v-model="excelBox" width="555px">
|
<el-dialog :title="`${config.title}导入`" append-to-body v-model="excelBox" width="555px">
|
||||||
<avue-form :option="excelOptionConfig" v-model="excelForm">
|
<avue-form :option="excelOptionConfig" v-model="excelForm">
|
||||||
<template #excelTemplate>
|
<template #excelTemplate>
|
||||||
@@ -3669,7 +3913,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { exportBlob } from '@/api/common';
|
import { exportBlob, importBlob } from '@/api/common';
|
||||||
import { getList as getCommonAddressList } from '@/api/base/common-address';
|
import { getList as getCommonAddressList } from '@/api/base/common-address';
|
||||||
import { getList as getAirportMasterList } from '@/api/base/airport-master';
|
import { getList as getAirportMasterList } from '@/api/base/airport-master';
|
||||||
import { getList as getCargoTypeList } from '@/api/base/cargo-type';
|
import { getList as getCargoTypeList } from '@/api/base/cargo-type';
|
||||||
@@ -3682,9 +3926,11 @@ import { getList as getContractList } from '@/api/business/contract-manage';
|
|||||||
import { getList as getProjectList } from '@/api/business/project-apply';
|
import { getList as getProjectList } from '@/api/business/project-apply';
|
||||||
import { getList as getCommonRouteList } from '@/api/business/common-route';
|
import { getList as getCommonRouteList } from '@/api/business/common-route';
|
||||||
import { getList as getTransportPlanList } from '@/api/business/transport-plan';
|
import { getList as getTransportPlanList } from '@/api/business/transport-plan';
|
||||||
|
import { getList as getProcessConfigList } from '@/api/business/process-config';
|
||||||
import { getList as getCarrierCustomerList } from '@/api/vehicle/customer-archive';
|
import { getList as getCarrierCustomerList } from '@/api/vehicle/customer-archive';
|
||||||
import { getList as getDriverList } from '@/api/transportCapacity/driver';
|
import { getList as getDriverList } from '@/api/transportCapacity/driver';
|
||||||
import { getDictionary } from '@/api/system/dictbiz';
|
import { getDictionary } from '@/api/system/dictbiz';
|
||||||
|
import { getDictionary as getSystemDictionary } from '@/api/system/dict';
|
||||||
import { getDeptTree } from '@/api/system/dept';
|
import { getDeptTree } from '@/api/system/dept';
|
||||||
import { addressTypeOptions } from '@/option/base/common-address';
|
import { addressTypeOptions } from '@/option/base/common-address';
|
||||||
import { packageOptions } from '@/option/business/common';
|
import { packageOptions } from '@/option/business/common';
|
||||||
@@ -3804,6 +4050,18 @@ const defaultTransportCargo = () => ({
|
|||||||
remark: '',
|
remark: '',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const defaultShippingTemplateFreight = () => ({
|
||||||
|
currency: '',
|
||||||
|
otherFreightAmount: '',
|
||||||
|
freightAmount: '',
|
||||||
|
freightItems: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
const defaultShippingTemplateFreightItem = () => ({
|
||||||
|
unitPrice: '',
|
||||||
|
priceUnit: '',
|
||||||
|
});
|
||||||
|
|
||||||
const defaultDispatchRow = () => ({
|
const defaultDispatchRow = () => ({
|
||||||
taskEntryMode: 'simple',
|
taskEntryMode: 'simple',
|
||||||
transportType: '',
|
transportType: '',
|
||||||
@@ -3953,6 +4211,12 @@ export default {
|
|||||||
attachmentRows: [],
|
attachmentRows: [],
|
||||||
contractFileRows: [],
|
contractFileRows: [],
|
||||||
transportCargoRows: [],
|
transportCargoRows: [],
|
||||||
|
shippingTemplateFreight: defaultShippingTemplateFreight(),
|
||||||
|
shippingTemplateCurrencyOptions: [],
|
||||||
|
shippingTemplateCurrencyLoading: false,
|
||||||
|
shippingTemplateProcessConfigBox: false,
|
||||||
|
shippingTemplateProcessConfigLoading: false,
|
||||||
|
shippingTemplateProcessConfigRows: [],
|
||||||
transportRouteBox: false,
|
transportRouteBox: false,
|
||||||
transportRouteLoading: false,
|
transportRouteLoading: false,
|
||||||
transportRouteQuery: {},
|
transportRouteQuery: {},
|
||||||
@@ -4128,6 +4392,10 @@ export default {
|
|||||||
this.loadTaskFeeUnitOptions();
|
this.loadTaskFeeUnitOptions();
|
||||||
this.ensureBillingCargoTypeOptions();
|
this.ensureBillingCargoTypeOptions();
|
||||||
}
|
}
|
||||||
|
if (this.config.enableShippingTemplateFreight) {
|
||||||
|
this.loadShippingTemplateCurrencyOptions();
|
||||||
|
this.loadTaskFeeUnitOptions();
|
||||||
|
}
|
||||||
this.consumeTemplateCreatePayload();
|
this.consumeTemplateCreatePayload();
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@@ -4140,6 +4408,9 @@ export default {
|
|||||||
detailSections() {
|
detailSections() {
|
||||||
return this.config.detailSections || [];
|
return this.config.detailSections || [];
|
||||||
},
|
},
|
||||||
|
isTransportPlanPage() {
|
||||||
|
return this.config.permission === 'transport_plan';
|
||||||
|
},
|
||||||
transportPlanImportDuplicateCount() {
|
transportPlanImportDuplicateCount() {
|
||||||
return this.transportPlanImportRows.filter(row => row._duplicate).length;
|
return this.transportPlanImportRows.filter(row => row._duplicate).length;
|
||||||
},
|
},
|
||||||
@@ -4445,6 +4716,37 @@ export default {
|
|||||||
}, 0);
|
}, 0);
|
||||||
return Number.isInteger(total) ? String(total) : total.toFixed(2);
|
return Number.isInteger(total) ? String(total) : total.toFixed(2);
|
||||||
},
|
},
|
||||||
|
shippingTemplateFreightVisible() {
|
||||||
|
return (
|
||||||
|
this.config.enableShippingTemplateFreight === true && this.form.templateType === '运单'
|
||||||
|
);
|
||||||
|
},
|
||||||
|
shippingTemplateCurrencyLabel() {
|
||||||
|
const currency = this.shippingTemplateFreight.currency;
|
||||||
|
if (!currency) return '';
|
||||||
|
const option = this.shippingTemplateCurrencyOptions.find(item => item.value === currency);
|
||||||
|
return option?.label || currency;
|
||||||
|
},
|
||||||
|
shippingTemplateRoadFreightTotal() {
|
||||||
|
const total = this.shippingTemplateFreight.freightItems.reduce(
|
||||||
|
(sum, item, index) => sum + Number(this.shippingTemplateRoadFreightAmount(item, index) || 0),
|
||||||
|
0
|
||||||
|
);
|
||||||
|
return this.formatShippingTemplateFreightNumber(total);
|
||||||
|
},
|
||||||
|
shippingTemplateFooterFreightTotal() {
|
||||||
|
const freightAmount =
|
||||||
|
this.transportMode === 'road'
|
||||||
|
? Number(this.shippingTemplateRoadFreightTotal || 0)
|
||||||
|
: Number(this.shippingTemplateFreight.freightAmount || 0);
|
||||||
|
return freightAmount + Number(this.shippingTemplateFreight.otherFreightAmount || 0);
|
||||||
|
},
|
||||||
|
formatShippingTemplateFooterFreightTotal() {
|
||||||
|
return this.shippingTemplateFooterFreightTotal.toLocaleString('zh-CN', {
|
||||||
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2,
|
||||||
|
});
|
||||||
|
},
|
||||||
transportAddressSelectDisabled() {
|
transportAddressSelectDisabled() {
|
||||||
return this.dialogReadonly || this.isBillingFieldEmpty(this.form.transportType);
|
return this.dialogReadonly || this.isBillingFieldEmpty(this.form.transportType);
|
||||||
},
|
},
|
||||||
@@ -4480,6 +4782,7 @@ export default {
|
|||||||
if (!this.shippingInfoFormEnabled || this.suppressTransportTypeClear) return;
|
if (!this.shippingInfoFormEnabled || this.suppressTransportTypeClear) return;
|
||||||
if (String(value ?? '') === String(oldValue ?? '')) return;
|
if (String(value ?? '') === String(oldValue ?? '')) return;
|
||||||
this.handleTransportTypeChange(value);
|
this.handleTransportTypeChange(value);
|
||||||
|
this.syncShippingTemplateFreightItems();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@@ -4490,6 +4793,31 @@ export default {
|
|||||||
};
|
};
|
||||||
return applyTableMenuWidth(nextOption, menuButtonCount);
|
return applyTableMenuWidth(nextOption, menuButtonCount);
|
||||||
},
|
},
|
||||||
|
formatTransportPlanGoodsInfo(row = {}) {
|
||||||
|
if (row.goodsInfo) return String(row.goodsInfo);
|
||||||
|
const goodsRows = this.parseJsonArray(row.goodsJson);
|
||||||
|
return goodsRows
|
||||||
|
.map(item => item.cargoType || item.goodsType || item.cargoName || item.goodsName || '')
|
||||||
|
.filter(Boolean)
|
||||||
|
.join('/');
|
||||||
|
},
|
||||||
|
truncateTransportPlanText(value, length = 10) {
|
||||||
|
const text = String(value || '');
|
||||||
|
return text.length > length ? `${text.slice(0, length)}...` : text || '-';
|
||||||
|
},
|
||||||
|
formatTransportPlanDistrictAddress(value) {
|
||||||
|
const text = String(value || '').trim();
|
||||||
|
if (!text) return '-';
|
||||||
|
const cityIndex = text.indexOf('市');
|
||||||
|
const districtStart = cityIndex > -1 ? cityIndex + 1 : 0;
|
||||||
|
const districtMatch = text
|
||||||
|
.slice(districtStart)
|
||||||
|
.match(/(?:自治县|自治旗|林区|矿区|新区|开发区|区|县|旗)/);
|
||||||
|
if (districtMatch) {
|
||||||
|
return text.slice(0, districtStart + districtMatch.index + districtMatch[0].length);
|
||||||
|
}
|
||||||
|
return cityIndex > -1 ? text.slice(0, cityIndex + 1) : text;
|
||||||
|
},
|
||||||
hasPermission(code) {
|
hasPermission(code) {
|
||||||
return this.isAdmin || this.validData(this.permission && this.permission[code], false);
|
return this.isAdmin || this.validData(this.permission && this.permission[code], false);
|
||||||
},
|
},
|
||||||
@@ -4901,6 +5229,10 @@ export default {
|
|||||||
if (this.config.enableTransportPlanForm) {
|
if (this.config.enableTransportPlanForm) {
|
||||||
if (!this.validateTransportPlanForm(submitRow)) return false;
|
if (!this.validateTransportPlanForm(submitRow)) return false;
|
||||||
submitRow.goodsJson = JSON.stringify(this.transportCargoRows);
|
submitRow.goodsJson = JSON.stringify(this.transportCargoRows);
|
||||||
|
if (this.config.enableShippingTemplateFreight) {
|
||||||
|
if (!this.validateShippingTemplateFreight()) return false;
|
||||||
|
submitRow.freightJson = this.serializeShippingTemplateFreight();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (this.taskInfoFormEnabled) {
|
if (this.taskInfoFormEnabled) {
|
||||||
if (!this.validateTaskInfoForm(submitRow)) return false;
|
if (!this.validateTaskInfoForm(submitRow)) return false;
|
||||||
@@ -4980,6 +5312,142 @@ export default {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
loadShippingTemplateCurrencyOptions() {
|
||||||
|
if (this.shippingTemplateCurrencyOptions.length || this.shippingTemplateCurrencyLoading) {
|
||||||
|
return Promise.resolve(this.shippingTemplateCurrencyOptions);
|
||||||
|
}
|
||||||
|
this.shippingTemplateCurrencyLoading = true;
|
||||||
|
return getSystemDictionary({ code: 'currency_type' })
|
||||||
|
.then(res => {
|
||||||
|
this.shippingTemplateCurrencyOptions = this.normalizeDictOptions(res.data?.data || []);
|
||||||
|
const cny = this.shippingTemplateCurrencyOptions.find(item =>
|
||||||
|
['CNY', '人民币', 'RMB'].includes(String(item.value).toUpperCase())
|
||||||
|
);
|
||||||
|
if (!this.shippingTemplateFreight.currency) {
|
||||||
|
this.shippingTemplateFreight.currency = (cny || this.shippingTemplateCurrencyOptions[0])?.value || '';
|
||||||
|
}
|
||||||
|
return this.shippingTemplateCurrencyOptions;
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.shippingTemplateCurrencyLoading = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
initShippingTemplateFreight() {
|
||||||
|
if (!this.config.enableShippingTemplateFreight) return;
|
||||||
|
const freight = this.parseJsonObject(this.form.freightJson);
|
||||||
|
this.shippingTemplateFreight = {
|
||||||
|
...defaultShippingTemplateFreight(),
|
||||||
|
...freight,
|
||||||
|
freightItems: (freight.freightItems || []).map(item => ({
|
||||||
|
...defaultShippingTemplateFreightItem(),
|
||||||
|
...item,
|
||||||
|
})),
|
||||||
|
};
|
||||||
|
this.syncShippingTemplateFreightItems();
|
||||||
|
this.loadShippingTemplateCurrencyOptions();
|
||||||
|
},
|
||||||
|
syncShippingTemplateFreightItems() {
|
||||||
|
if (!this.config.enableShippingTemplateFreight || this.transportMode !== 'road') return;
|
||||||
|
const rows = this.shippingTemplateFreight.freightItems || [];
|
||||||
|
this.shippingTemplateFreight.freightItems = this.transportCargoRows.map((_, index) => ({
|
||||||
|
...defaultShippingTemplateFreightItem(),
|
||||||
|
...(rows[index] || {}),
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
handleShippingTemplateFreightNumberInput(row, prop, value) {
|
||||||
|
const text = String(value || '').replace(/[^\d.]/g, '');
|
||||||
|
const parts = text.split('.');
|
||||||
|
row[prop] =
|
||||||
|
parts.length > 1 ? `${parts[0]}.${parts.slice(1).join('').slice(0, 2)}` : parts[0];
|
||||||
|
},
|
||||||
|
shippingTemplateRoadFreightQuantity(index) {
|
||||||
|
return this.formatShippingTemplateFreightNumber(this.transportCargoRows[index]?.quantity || 0);
|
||||||
|
},
|
||||||
|
shippingTemplateRoadFreightAmount(item, index) {
|
||||||
|
const amount = Number(item?.unitPrice || 0) * Number(this.transportCargoRows[index]?.quantity || 0);
|
||||||
|
return this.formatShippingTemplateFreightNumber(amount);
|
||||||
|
},
|
||||||
|
formatShippingTemplateFreightNumber(value) {
|
||||||
|
const number = Number(value || 0);
|
||||||
|
if (!Number.isFinite(number)) return '';
|
||||||
|
return Number(number.toFixed(2)).toString();
|
||||||
|
},
|
||||||
|
serializeShippingTemplateFreight() {
|
||||||
|
if (this.form.templateType !== '运单') return '';
|
||||||
|
const freight = {
|
||||||
|
currency: this.shippingTemplateFreight.currency || '',
|
||||||
|
otherFreightAmount: this.shippingTemplateFreight.otherFreightAmount || '',
|
||||||
|
};
|
||||||
|
if (this.transportMode === 'road') {
|
||||||
|
freight.totalFreightAmount = this.shippingTemplateRoadFreightTotal;
|
||||||
|
freight.freightItems = this.shippingTemplateFreight.freightItems.map((item, index) => ({
|
||||||
|
cargoIndex: index,
|
||||||
|
unitPrice: item.unitPrice || '',
|
||||||
|
priceUnit: item.priceUnit || '',
|
||||||
|
quantity: this.shippingTemplateRoadFreightQuantity(index),
|
||||||
|
freightAmount: this.shippingTemplateRoadFreightAmount(item, index),
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
freight.quantity = this.transportCargoQuantityTotal;
|
||||||
|
freight.freightAmount = this.shippingTemplateFreight.freightAmount || '';
|
||||||
|
}
|
||||||
|
return JSON.stringify(freight);
|
||||||
|
},
|
||||||
|
validateShippingTemplateFreight() {
|
||||||
|
if (!this.shippingTemplateFreightVisible) return true;
|
||||||
|
if (!this.shippingTemplateFreight.currency) {
|
||||||
|
this.$message.warning('请选择币种');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (this.transportMode === 'road') {
|
||||||
|
const invalid = this.shippingTemplateFreight.freightItems.findIndex(
|
||||||
|
item => Number(item.unitPrice || 0) < 0
|
||||||
|
);
|
||||||
|
if (invalid > -1) {
|
||||||
|
this.$message.warning(`第${invalid + 1}条货物单价不能小于0`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const missingPriceUnit = this.shippingTemplateFreight.freightItems.findIndex(
|
||||||
|
item => !item.priceUnit
|
||||||
|
);
|
||||||
|
if (missingPriceUnit > -1) {
|
||||||
|
this.$message.warning(`请选择第${missingPriceUnit + 1}条货物的计价单位`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (Number(this.shippingTemplateFreight.freightAmount || 0) < 0) {
|
||||||
|
this.$message.warning('运费不能小于0');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (Number(this.shippingTemplateFreight.otherFreightAmount || 0) < 0) {
|
||||||
|
this.$message.warning('其他运费合计不能小于0');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
openShippingTemplateProcessConfig() {
|
||||||
|
if (!this.form.projectId || this.shippingTemplateProcessConfigLoading) return;
|
||||||
|
this.shippingTemplateProcessConfigBox = true;
|
||||||
|
this.shippingTemplateProcessConfigLoading = true;
|
||||||
|
getProcessConfigList(1, 100, { projectIds: this.form.projectId })
|
||||||
|
.then(res => {
|
||||||
|
this.shippingTemplateProcessConfigRows = extractRecords(res).filter(row => {
|
||||||
|
const projectIds = String(row.projectIds || '')
|
||||||
|
.split(',')
|
||||||
|
.map(item => item.trim());
|
||||||
|
return projectIds.includes(String(this.form.projectId));
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.shippingTemplateProcessConfigLoading = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
formatShippingTemplateProcessNodes(nodes) {
|
||||||
|
if (Array.isArray(nodes)) return nodes.join('、');
|
||||||
|
return String(nodes || '')
|
||||||
|
.split(',')
|
||||||
|
.filter(Boolean)
|
||||||
|
.join('、');
|
||||||
|
},
|
||||||
stopSubmitLoading(loading) {
|
stopSubmitLoading(loading) {
|
||||||
if (typeof loading === 'function') {
|
if (typeof loading === 'function') {
|
||||||
loading();
|
loading();
|
||||||
@@ -5235,6 +5703,7 @@ export default {
|
|||||||
this.clearShippingPlan();
|
this.clearShippingPlan();
|
||||||
}
|
}
|
||||||
this.transportCargoRows = [];
|
this.transportCargoRows = [];
|
||||||
|
this.shippingTemplateFreight = defaultShippingTemplateFreight();
|
||||||
this.billingPlanRows = [];
|
this.billingPlanRows = [];
|
||||||
this.settlementRuleForm = defaultSettlementRule();
|
this.settlementRuleForm = defaultSettlementRule();
|
||||||
this.reconciliationForm = defaultReconciliation();
|
this.reconciliationForm = defaultReconciliation();
|
||||||
@@ -5343,7 +5812,9 @@ export default {
|
|||||||
this.projectLoading = true;
|
this.projectLoading = true;
|
||||||
getProjectList(1, 9999, this.config.projectQueryParams || {})
|
getProjectList(1, 9999, this.config.projectQueryParams || {})
|
||||||
.then(res => {
|
.then(res => {
|
||||||
this.projectOptions = extractRecords(res);
|
this.projectOptions = extractRecords(res).filter(
|
||||||
|
item => !this.config.excludeVoidedProjects || item.approvalStatus !== 'voided'
|
||||||
|
);
|
||||||
this.syncCurrentProjectOption();
|
this.syncCurrentProjectOption();
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
@@ -5352,6 +5823,7 @@ export default {
|
|||||||
},
|
},
|
||||||
syncCurrentProjectOption() {
|
syncCurrentProjectOption() {
|
||||||
if (!this.form.projectId || !this.form.projectName) return;
|
if (!this.form.projectId || !this.form.projectName) return;
|
||||||
|
if (this.config.excludeVoidedProjects) return;
|
||||||
const exists = this.projectOptions.some(
|
const exists = this.projectOptions.some(
|
||||||
item => String(item.id) === String(this.form.projectId)
|
item => String(item.id) === String(this.form.projectId)
|
||||||
);
|
);
|
||||||
@@ -6001,6 +6473,7 @@ export default {
|
|||||||
this.transportCargoRows = this.parseJsonArray(this.form.goodsJson).map(row =>
|
this.transportCargoRows = this.parseJsonArray(this.form.goodsJson).map(row =>
|
||||||
this.normalizeTransportCargoRow(row)
|
this.normalizeTransportCargoRow(row)
|
||||||
);
|
);
|
||||||
|
this.initShippingTemplateFreight();
|
||||||
this.syncTransportCargoJson();
|
this.syncTransportCargoJson();
|
||||||
this.syncCurrentContractOption();
|
this.syncCurrentContractOption();
|
||||||
this.restoreTransportCargoTypePaths();
|
this.restoreTransportCargoTypePaths();
|
||||||
@@ -6054,9 +6527,13 @@ export default {
|
|||||||
} else {
|
} else {
|
||||||
this.transportCargoRows.push(nextRow);
|
this.transportCargoRows.push(nextRow);
|
||||||
}
|
}
|
||||||
|
this.syncShippingTemplateFreightItems();
|
||||||
this.syncTransportCargoJson();
|
this.syncTransportCargoJson();
|
||||||
},
|
},
|
||||||
removeTransportCargoRow(index) {
|
removeTransportCargoRow(index) {
|
||||||
|
if (this.config.enableShippingTemplateFreight && this.transportMode === 'road') {
|
||||||
|
this.shippingTemplateFreight.freightItems.splice(index, 1);
|
||||||
|
}
|
||||||
this.transportCargoRows.splice(index, 1);
|
this.transportCargoRows.splice(index, 1);
|
||||||
if (
|
if (
|
||||||
!this.transportCargoRows.length &&
|
!this.transportCargoRows.length &&
|
||||||
@@ -6064,6 +6541,7 @@ export default {
|
|||||||
) {
|
) {
|
||||||
this.transportCargoRows.push(this.normalizeTransportCargoRow());
|
this.transportCargoRows.push(this.normalizeTransportCargoRow());
|
||||||
}
|
}
|
||||||
|
this.syncShippingTemplateFreightItems();
|
||||||
this.syncTransportCargoJson();
|
this.syncTransportCargoJson();
|
||||||
},
|
},
|
||||||
handleTransportCargoQuantityInput(row, value) {
|
handleTransportCargoQuantityInput(row, value) {
|
||||||
@@ -6071,6 +6549,7 @@ export default {
|
|||||||
const parts = text.split('.');
|
const parts = text.split('.');
|
||||||
row.quantity =
|
row.quantity =
|
||||||
parts.length > 1 ? `${parts[0]}.${parts.slice(1).join('').slice(0, 3)}` : parts[0];
|
parts.length > 1 ? `${parts[0]}.${parts.slice(1).join('').slice(0, 3)}` : parts[0];
|
||||||
|
this.syncShippingTemplateFreightItems();
|
||||||
this.syncTransportCargoJson();
|
this.syncTransportCargoJson();
|
||||||
},
|
},
|
||||||
handleTransportCargoTypeChange(row, value) {
|
handleTransportCargoTypeChange(row, value) {
|
||||||
@@ -6207,6 +6686,11 @@ export default {
|
|||||||
}
|
}
|
||||||
this.openTransportMapDialog(target);
|
this.openTransportMapDialog(target);
|
||||||
},
|
},
|
||||||
|
handleTransportSecondaryAddressInputClick(target) {
|
||||||
|
if (this.transportStationMode || !this.config.editableRoadAddress) {
|
||||||
|
this.openTransportSecondaryAddressPicker(target);
|
||||||
|
}
|
||||||
|
},
|
||||||
ensureTransportTypeBeforeAddress() {
|
ensureTransportTypeBeforeAddress() {
|
||||||
if (!this.shippingInfoFormEnabled || !this.isBillingFieldEmpty(this.form.transportType)) {
|
if (!this.shippingInfoFormEnabled || !this.isBillingFieldEmpty(this.form.transportType)) {
|
||||||
return true;
|
return true;
|
||||||
@@ -6381,10 +6865,31 @@ export default {
|
|||||||
if (!this.ensureTransportTypeBeforeAddress()) return;
|
if (!this.ensureTransportTypeBeforeAddress()) return;
|
||||||
this.transportAddressTarget = target;
|
this.transportAddressTarget = target;
|
||||||
this.transportAddressSelected = null;
|
this.transportAddressSelected = null;
|
||||||
this.transportAddressQuery = {};
|
this.resetTransportAddressQuery();
|
||||||
this.transportAddressPage.currentPage = 1;
|
this.transportAddressPage.currentPage = 1;
|
||||||
this.transportAddressBox = true;
|
this.transportAddressBox = true;
|
||||||
},
|
},
|
||||||
|
openTransportAddressPicker(target) {
|
||||||
|
if (this.transportStationMode) {
|
||||||
|
this.openTransportStationDialog(target);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.openTransportAddressDialog(target);
|
||||||
|
},
|
||||||
|
resetTransportAddressQuery() {
|
||||||
|
const addressType = this.getTransportFixedAddressType();
|
||||||
|
this.transportAddressQuery = addressType ? { addressType } : {};
|
||||||
|
},
|
||||||
|
getTransportFixedAddressType() {
|
||||||
|
if (!this.config.fixedTransportAddressType) return '';
|
||||||
|
const typeMap = {
|
||||||
|
road: '常规地址',
|
||||||
|
rail: '铁路车站',
|
||||||
|
water: '港口/码头',
|
||||||
|
air: '空港机场',
|
||||||
|
};
|
||||||
|
return typeMap[this.transportMode] || '';
|
||||||
|
},
|
||||||
loadTransportAddressList() {
|
loadTransportAddressList() {
|
||||||
this.transportAddressLoading = true;
|
this.transportAddressLoading = true;
|
||||||
getCommonAddressList(
|
getCommonAddressList(
|
||||||
@@ -6409,7 +6914,7 @@ export default {
|
|||||||
this.loadTransportAddressList();
|
this.loadTransportAddressList();
|
||||||
},
|
},
|
||||||
handleTransportAddressReset() {
|
handleTransportAddressReset() {
|
||||||
this.transportAddressQuery = {};
|
this.resetTransportAddressQuery();
|
||||||
this.transportAddressPage.currentPage = 1;
|
this.transportAddressPage.currentPage = 1;
|
||||||
this.loadTransportAddressList();
|
this.loadTransportAddressList();
|
||||||
},
|
},
|
||||||
@@ -6812,44 +7317,26 @@ export default {
|
|||||||
async handleCargoImportFileChange(file) {
|
async handleCargoImportFileChange(file) {
|
||||||
const rawFile = file.raw;
|
const rawFile = file.raw;
|
||||||
if (!rawFile) return;
|
if (!rawFile) return;
|
||||||
|
if (!/\.(xls|xlsx)$/i.test(rawFile.name || '')) {
|
||||||
|
this.$message.warning('请上传 .xlsx、.xls 格式文件');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (rawFile.size > 50 * 1024 * 1024) {
|
||||||
|
this.$message.warning('单个文件大小不能超过50M');
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.cargoImportLoading = true;
|
this.cargoImportLoading = true;
|
||||||
try {
|
try {
|
||||||
const ExcelJSModule = await import('exceljs');
|
const res = await importBlob('/blade-transport/shipping-template/import-goods', rawFile);
|
||||||
const ExcelJS = ExcelJSModule.default || ExcelJSModule;
|
const contentType = res.headers['content-type'] || res.data.type || '';
|
||||||
const workbook = new ExcelJS.Workbook();
|
if (contentType.includes('application/vnd.ms-excel')) {
|
||||||
await workbook.xlsx.load(await rawFile.arrayBuffer());
|
downloadXls(res.data, `发货模板货物导入失败明细${this.$dayjs().format('YYYY-MM-DD HH:mm:ss')}.xlsx`);
|
||||||
const worksheet = workbook.worksheets[0];
|
this.$message.warning('部分数据导入失败,已下载失败明细');
|
||||||
const headerRow = worksheet.getRow(1);
|
return;
|
||||||
const headerMap = {};
|
|
||||||
headerRow.eachCell((cell, colNumber) => {
|
|
||||||
headerMap[String(cell.value || '').trim()] = colNumber;
|
|
||||||
});
|
|
||||||
const fieldMap = {
|
|
||||||
货物名称: 'cargoName',
|
|
||||||
货物类型: 'cargoType',
|
|
||||||
数量: 'quantity',
|
|
||||||
数量单位: 'quantityUnit',
|
|
||||||
包装: 'packageType',
|
|
||||||
品牌: 'brand',
|
|
||||||
规格: 'specification',
|
|
||||||
型号: 'model',
|
|
||||||
物料编码: 'materialCode',
|
|
||||||
设备编码: 'deviceCode',
|
|
||||||
备注: 'remark',
|
|
||||||
};
|
|
||||||
const rows = [];
|
|
||||||
worksheet.eachRow((row, rowNumber) => {
|
|
||||||
if (rowNumber === 1) return;
|
|
||||||
const nextRow = defaultTransportCargo();
|
|
||||||
Object.entries(fieldMap).forEach(([label, prop]) => {
|
|
||||||
const columnIndex = headerMap[label];
|
|
||||||
if (!columnIndex) return;
|
|
||||||
nextRow[prop] = String(row.getCell(columnIndex).value || '').trim();
|
|
||||||
});
|
|
||||||
if (Object.values(nextRow).some(value => String(value || '').trim())) {
|
|
||||||
rows.push(nextRow);
|
|
||||||
}
|
}
|
||||||
});
|
const result = JSON.parse(await res.data.text());
|
||||||
|
if (result.code !== 200) throw new Error(result.msg || '货物导入失败');
|
||||||
|
const rows = result.data || [];
|
||||||
if (!rows.length) {
|
if (!rows.length) {
|
||||||
this.$message.warning('未读取到货物数据');
|
this.$message.warning('未读取到货物数据');
|
||||||
return;
|
return;
|
||||||
@@ -6864,6 +7351,11 @@ export default {
|
|||||||
this.cargoImportLoading = false;
|
this.cargoImportLoading = false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
handleCargoImportTemplate() {
|
||||||
|
exportBlob('/blade-transport/shipping-template/export-goods-template').then(res => {
|
||||||
|
downloadXls(res.data, '发货模板货物导入模板.xlsx');
|
||||||
|
});
|
||||||
|
},
|
||||||
loadOrganizationOptions() {
|
loadOrganizationOptions() {
|
||||||
if (!this.config.enableOrganizationSelect || this.organizationLoading) return;
|
if (!this.config.enableOrganizationSelect || this.organizationLoading) return;
|
||||||
this.organizationLoading = true;
|
this.organizationLoading = true;
|
||||||
@@ -9043,6 +9535,15 @@ export default {
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__map-suffix {
|
||||||
|
cursor: pointer;
|
||||||
|
color: #909399;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #409eff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&__cargo-wrap {
|
&__cargo-wrap {
|
||||||
display: block;
|
display: block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -9050,6 +9551,20 @@ export default {
|
|||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__cargo-import {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 56px;
|
||||||
|
padding: 12px 0 8px;
|
||||||
|
|
||||||
|
:deep(.el-upload__tip) {
|
||||||
|
margin: 16px 0 0;
|
||||||
|
color: #606266;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&__cargo-table {
|
&__cargo-table {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
min-width: 1870px;
|
min-width: 1870px;
|
||||||
@@ -9118,6 +9633,87 @@ export default {
|
|||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__freight-section {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__freight-table {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
:deep(.el-table__header th) {
|
||||||
|
background: #f5f7fa;
|
||||||
|
color: #303133;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-table__cell) {
|
||||||
|
border-color: #eff1f7;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-input),
|
||||||
|
:deep(.el-select) {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__freight-summary {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
margin-top: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__freight-form {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(3, minmax(220px, 1fr));
|
||||||
|
gap: 16px 24px;
|
||||||
|
width: min(100%, 920px);
|
||||||
|
|
||||||
|
:deep(.el-form-item) {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-input),
|
||||||
|
:deep(.el-select) {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--non-road {
|
||||||
|
width: 100%;
|
||||||
|
grid-template-columns: repeat(4, minmax(220px, 1fr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__shipping-template-footer-summary {
|
||||||
|
position: absolute;
|
||||||
|
left: 16px;
|
||||||
|
bottom: 10px;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 24px;
|
||||||
|
height: 28px;
|
||||||
|
color: #303133;
|
||||||
|
font-size: 13px;
|
||||||
|
|
||||||
|
strong {
|
||||||
|
margin-left: 4px;
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-link) {
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__process-config-dialog {
|
||||||
|
:deep(.el-table__cell) {
|
||||||
|
border-color: #eff1f7;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-table__row:nth-child(even) td) {
|
||||||
|
background: #fafafa;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&__dialog-search {
|
&__dialog-search {
|
||||||
padding: 12px 12px 4px;
|
padding: 12px 12px 4px;
|
||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
@@ -9162,6 +9758,16 @@ export default {
|
|||||||
:deep(.el-select) {
|
:deep(.el-select) {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&--road {
|
||||||
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||||
|
column-gap: 56px;
|
||||||
|
row-gap: 16px;
|
||||||
|
|
||||||
|
:deep(.business-crud-page__append-select) {
|
||||||
|
width: 128px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__dialog-pagination {
|
&__dialog-pagination {
|
||||||
|
|||||||
@@ -1015,7 +1015,7 @@
|
|||||||
v-for="item in scoreQuantificationOptions"
|
v-for="item in scoreQuantificationOptions"
|
||||||
:key="item.id"
|
:key="item.id"
|
||||||
:label="item.name"
|
:label="item.name"
|
||||||
:value="item.id"
|
:value="String(item.id)"
|
||||||
/>
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@@ -1960,14 +1960,14 @@ export default {
|
|||||||
},
|
},
|
||||||
initScoreQuantificationOptions() {
|
initScoreQuantificationOptions() {
|
||||||
this.scoreQuantificationLoading = true;
|
this.scoreQuantificationLoading = true;
|
||||||
getCreditScoreQuantificationList(1, 9999, { status: 1 })
|
return getCreditScoreQuantificationList(1, 9999, { status: 1 })
|
||||||
.then(res => {
|
.then(res => {
|
||||||
const data = res.data.data || {};
|
const data = res.data.data || {};
|
||||||
const records = Array.isArray(data) ? data : data.records || [];
|
const records = Array.isArray(data) ? data : data.records || [];
|
||||||
this.scoreQuantificationOptions = records
|
this.scoreQuantificationOptions = records
|
||||||
.filter(item => Number(item.status) === 1)
|
.filter(item => Number(item.status) === 1)
|
||||||
.map(item => ({
|
.map(item => ({
|
||||||
id: item.id,
|
id: String(item.id),
|
||||||
name: item.name || item.configName || item.title || item.id,
|
name: item.name || item.configName || item.title || item.id,
|
||||||
}));
|
}));
|
||||||
})
|
})
|
||||||
@@ -1975,6 +1975,21 @@ export default {
|
|||||||
this.scoreQuantificationLoading = false;
|
this.scoreQuantificationLoading = false;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
ensureScoreQuantificationOption(quantificationId) {
|
||||||
|
if (!quantificationId) return Promise.resolve();
|
||||||
|
const id = String(quantificationId);
|
||||||
|
if (this.scoreQuantificationOptions.some(item => String(item.id) === id)) {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
return getCreditScoreQuantificationDetail(quantificationId).then(res => {
|
||||||
|
const item = res.data.data || {};
|
||||||
|
if (!item.id) return;
|
||||||
|
this.scoreQuantificationOptions.push({
|
||||||
|
id: String(item.id),
|
||||||
|
name: item.name || item.configName || item.title || String(item.id),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
loadDictOptions(code, target, fallback = [], callback) {
|
loadDictOptions(code, target, fallback = [], callback) {
|
||||||
getDictionary({ code }).then(res => {
|
getDictionary({ code }).then(res => {
|
||||||
const options = (res.data.data || []).map(item => ({
|
const options = (res.data.data || []).map(item => ({
|
||||||
@@ -2021,6 +2036,7 @@ export default {
|
|||||||
const deptNames = deptIds
|
const deptNames = deptIds
|
||||||
.map(id => this.deptOptions.find(item => String(item.value) === String(id))?.rawLabel)
|
.map(id => this.deptOptions.find(item => String(item.value) === String(id))?.rawLabel)
|
||||||
.filter(Boolean);
|
.filter(Boolean);
|
||||||
|
this.archiveForm.deptId = deptIds;
|
||||||
this.archiveForm.deptIds = deptIds.join(',');
|
this.archiveForm.deptIds = deptIds.join(',');
|
||||||
this.archiveForm.deptName = deptNames.join(',');
|
this.archiveForm.deptName = deptNames.join(',');
|
||||||
this.$refs.archiveForm?.validateField('deptName');
|
this.$refs.archiveForm?.validateField('deptName');
|
||||||
@@ -2691,6 +2707,7 @@ export default {
|
|||||||
attachments: [],
|
attachments: [],
|
||||||
details: [],
|
details: [],
|
||||||
...score,
|
...score,
|
||||||
|
quantificationId: score.quantificationId ? String(score.quantificationId) : '',
|
||||||
tempApplyCreditLimit: this.normalizeOptionalAmount(score.tempApplyCreditLimit),
|
tempApplyCreditLimit: this.normalizeOptionalAmount(score.tempApplyCreditLimit),
|
||||||
attachments: score.attachments || this.parseAttachments(score.proofAttachments),
|
attachments: score.attachments || this.parseAttachments(score.proofAttachments),
|
||||||
details: score.details || [],
|
details: score.details || [],
|
||||||
@@ -2807,7 +2824,7 @@ export default {
|
|||||||
.map(id => this.deptOptions.find(item => String(item.value) === String(id))?.rawLabel)
|
.map(id => this.deptOptions.find(item => String(item.value) === String(id))?.rawLabel)
|
||||||
.filter(Boolean);
|
.filter(Boolean);
|
||||||
archive.deptIds = deptIds.join(',');
|
archive.deptIds = deptIds.join(',');
|
||||||
archive.deptId = deptIds.length ? deptIds[0] : '';
|
archive.deptId = deptIds.length ? Number(deptIds[0]) : null;
|
||||||
archive.deptName = deptNames.length ? deptNames.join(',') : archive.deptName;
|
archive.deptName = deptNames.length ? deptNames.join(',') : archive.deptName;
|
||||||
archive.registeredAddress = this.formatArchiveAddress(archive);
|
archive.registeredAddress = this.formatArchiveAddress(archive);
|
||||||
delete archive.registeredRegionPath;
|
delete archive.registeredRegionPath;
|
||||||
@@ -2884,9 +2901,10 @@ export default {
|
|||||||
this.scoreAttachmentFiles = JSON.parse(JSON.stringify(this.currentScore.attachments || []));
|
this.scoreAttachmentFiles = JSON.parse(JSON.stringify(this.currentScore.attachments || []));
|
||||||
this.expandedScoreCategoryKeys = [];
|
this.expandedScoreCategoryKeys = [];
|
||||||
this.scoreBox = true;
|
this.scoreBox = true;
|
||||||
if (!this.scoreQuantificationOptions.length) {
|
const loadOptions = this.scoreQuantificationOptions.length
|
||||||
this.initScoreQuantificationOptions();
|
? Promise.resolve()
|
||||||
}
|
: this.initScoreQuantificationOptions();
|
||||||
|
loadOptions.then(() => this.ensureScoreQuantificationOption(this.currentScore.quantificationId));
|
||||||
},
|
},
|
||||||
resetScoreDialog() {
|
resetScoreDialog() {
|
||||||
this.scoreRecordIndex = -1;
|
this.scoreRecordIndex = -1;
|
||||||
|
|||||||
Reference in New Issue
Block a user