调整业务模块

This commit is contained in:
2026-09-07 10:05:32 +08:00
parent 6a6d10dc79
commit 0d070d4b34
16 changed files with 264 additions and 157 deletions
+2
View File
@@ -4,6 +4,8 @@ const baseUrl = '/blade-transport/formal-settlement';
export const getList = (current, size, params) =>
request({ url: `${baseUrl}/list`, method: 'get', params: { current, size, ...params } });
export const exportList = params =>
request({ url: `${baseUrl}/export`, method: 'get', params, responseType: 'blob' });
export const getDetail = id => request({ url: `${baseUrl}/detail`, method: 'get', params: { id } });
export const getCandidates = (current, size, params) =>
request({
@@ -4,6 +4,8 @@ const baseUrl = '/blade-transport/transport-reconciliation';
export const getList = (current, size, params) =>
request({ url: `${baseUrl}/list`, method: 'get', params: { current, size, ...params } });
export const exportList = params =>
request({ url: `${baseUrl}/export`, method: 'get', params, responseType: 'blob' });
export const getDetail = id => request({ url: `${baseUrl}/detail`, method: 'get', params: { id } });
export const getFormalOptions = (current, size, params) =>
request({
@@ -335,7 +335,12 @@ export default {
const data = (file.response && file.response.data) || file.data || file;
const url = data.link || data.url || data.domain || file.url || '';
const originalName =
data.originalName || file.originalName || data.name || file.name || this.getFileName(url) || '附件';
data.originalName ||
file.originalName ||
file.name ||
data.name ||
this.getFileName(url) ||
'附件';
const extension = this.getExtension({ name: originalName, url });
return {
...data,
+12
View File
@@ -152,6 +152,18 @@ export default [
},
],
},
{
path: '/business/waybill-import',
component: Layout,
children: [
{
path: '',
name: '导入运单',
meta: { keepAlive: false, activeMenu: '/business/waybill-import' },
component: () => import('@/views/business/waybill-import.vue'),
},
],
},
{
path: '/business/loading-manage/form',
component: Layout,
@@ -3268,12 +3268,6 @@
</template>
</el-dialog>
<waybill-import-dialog
v-if="config.enableWaybillImport"
v-model="waybillImportBox"
@closed="refreshChange"
/>
<flow-design
v-if="website.design.designMode"
is-dialog
@@ -5271,7 +5265,6 @@ import { h, resolveComponent } from 'vue';
import { mapGetters } from 'vuex';
import NProgress from 'nprogress';
import 'nprogress/nprogress.css';
import WaybillImportDialog from './waybill-import-dialog.vue';
import BillingPlanEditor from './billing-plan-editor.vue';
const AMAP_KEY = '653b7cf105ad7fb8ec9b2f5198ade315';
@@ -5511,7 +5504,6 @@ const taskCarrierTypes = ['承运商', '自运', '网货平台'];
export default {
components: {
WaybillImportDialog,
BillingPlanEditor,
PageAvueForm,
Rank,
@@ -5611,7 +5603,6 @@ export default {
currentPage: 1,
total: 0,
},
waybillImportBox: false,
transportPlanImportBox: false,
transportPlanImportLoading: false,
transportPlanImportFiles: [],
@@ -11554,7 +11545,7 @@ export default {
},
handleImport() {
if (this.config.enableWaybillImport) {
this.waybillImportBox = true;
this.$router.push({ path: '/business/waybill-import' });
return;
}
if (this.config.enableTransportPlanImport) {
@@ -114,7 +114,7 @@
<el-form :model="route" label-position="right" label-width="auto" class="dispatch-form carrier-form">
<el-row :gutter="16">
<template v-if="isRoad(route)">
<el-col :span="6"><el-form-item label="承运商" :required="route.carrierType === '承运商'"><el-select :model-value="route.carrierType === '承运商' ? route.carrierContractId : route.carrierName" filterable clearable placeholder="请选择" :loading="carrierLoading" @change="value => handleCarrierContractChange(route, value)"><el-option v-for="item in carrierOptions" :key="carrierOptionValue(item)" :label="carrierOptionLabel(item)" :value="route.carrierType === '承运商' ? carrierOptionValue(item) : item.carrierName" /></el-select></el-form-item></el-col>
<el-col :span="6"><el-form-item label="承运商" :required="route.carrierType !== '自运'"><el-select :model-value="route.carrierType !== '自运' ? route.carrierContractId : route.carrierName" filterable clearable placeholder="请选择" :loading="carrierLoading" @change="value => handleCarrierContractChange(route, value)"><el-option v-for="item in carrierOptions" :key="carrierOptionValue(item)" :label="carrierOptionLabel(item)" :value="route.carrierType !== '自运' ? carrierOptionValue(item) : item.carrierName" /></el-select></el-form-item></el-col>
<el-col :span="6"><el-form-item label="司机" :required="route.carrierType !== '承运商'"><el-autocomplete :ref="element => setDriverInput(route.segmentNo, element)" v-model="route.driverName" :debounce="300" :fetch-suggestions="fetchDriverSuggestions" clearable placeholder="请输入司机" :loading="driverLoading" @select="item => handleDriverSuggestionSelect(route, item)" /></el-form-item></el-col>
<el-col :span="6"><el-form-item :label="route.carrierType === '承运商' ? '手机号' : '司机手机号'" :required="route.carrierType !== '承运商'"><el-input v-model="route.driverPhone" placeholder="请输入" /></el-form-item></el-col>
<el-col :span="6"><el-form-item label="车牌号" required><el-input v-model="route.vehicleNo" placeholder="请输入" /></el-form-item></el-col>
@@ -123,7 +123,7 @@
<el-col v-if="route.carrierType !== '承运商'" :span="6"><el-form-item label="押运人手机号"><el-input v-model="route.escortPhone" placeholder="请输入" /></el-form-item></el-col>
</template>
<template v-else>
<el-col :span="6"><el-form-item label="承运商" :required="route.carrierType === '承运商'"><el-select :model-value="route.carrierType === '承运商' ? route.carrierContractId : route.carrierName" filterable clearable placeholder="请选择" :loading="carrierLoading" @change="value => handleCarrierContractChange(route, value)"><el-option v-for="item in carrierOptions" :key="carrierOptionValue(item)" :label="carrierOptionLabel(item)" :value="route.carrierType === '承运商' ? carrierOptionValue(item) : item.carrierName" /></el-select></el-form-item></el-col>
<el-col :span="6"><el-form-item label="承运商" :required="route.carrierType !== '自运'"><el-select :model-value="route.carrierType !== '自运' ? route.carrierContractId : route.carrierName" filterable clearable placeholder="请选择" :loading="carrierLoading" @change="value => handleCarrierContractChange(route, value)"><el-option v-for="item in carrierOptions" :key="carrierOptionValue(item)" :label="carrierOptionLabel(item)" :value="route.carrierType !== '自运' ? carrierOptionValue(item) : item.carrierName" /></el-select></el-form-item></el-col>
<el-col :span="6"><el-form-item label="船/航/班列号" required><el-input v-model="route.vehicleNo" placeholder="请输入" /></el-form-item></el-col>
<el-col :span="6"><el-form-item label="船长"><el-input v-model="route.captainName" placeholder="请输入" /></el-form-item></el-col>
<el-col :span="6"><el-form-item label="联系电话"><el-input v-model="route.driverPhone" placeholder="请输入" /></el-form-item></el-col>
@@ -689,16 +689,17 @@ export default {
},
handleCarrierTypeChange(route, value) {
route.carrierType = value;
route.carrierName = '';
route.carrierId = '';
route.carrierContractId = '';
if (value === '承运商') {
route.trailerVehicleNo = '';
route.escortName = '';
route.escortPhone = '';
}
if (value !== '承运商') {
route.carrierContractId = '';
if (value === '网货平台') route.carrierName = '';
this.loadCarrierOptions().then(() => {
if (value === '自运') this.applySelfOperatedCarrierDefaults(route);
}
});
},
handleCarrierContractChange(route, contractId) {
const contract = this.carrierOptions.find(
@@ -707,7 +708,8 @@ export default {
value => String(value || '') === String(contractId || '')
)
);
route.carrierContractId = route.carrierType === '承运商' ? contract?.contractId || '' : '';
route.carrierContractId = route.carrierType !== '自运' ? contract?.contractId || '' : '';
route.carrierId = route.carrierType !== '自运' ? contract?.carrierId || '' : '';
route.carrierName = contract?.carrierName || '';
},
carrierOptionValue(item = {}) {
@@ -733,7 +735,26 @@ export default {
async loadCarrierOptions() {
this.carrierLoading = true;
try {
this.carrierOptions = unwrapRecords(await api.getCarriers(this.id));
this.carrierOptions = unwrapRecords(await api.getCarriers(this.id))
.map(item => ({
...item,
contractId: item.contractId || item.carrierContractId || item.id || '',
carrierName:
item.partyB ||
item.partyBName ||
item.contractPartyB ||
item.customerContractPartyB ||
item.carrierName ||
'',
carrierId:
item.partyBId ||
item.partyBUserId ||
item.contractPartyBId ||
item.customerContractPartyBId ||
item.carrierId ||
'',
}))
.filter(item => item.carrierName);
} finally {
this.carrierLoading = false;
}
@@ -7296,16 +7296,13 @@ export default {
},
handleDispatchCarrierTypeChange(value) {
const nextValue = value || '';
this.dispatchItemForm.carrierName = '';
this.dispatchItemForm.carrierId = '';
this.dispatchItemForm.carrierContractId = '';
if (nextValue === '承运商') {
this.dispatchItemForm.trailerVehicleNo = '';
this.dispatchItemForm.escortName = '';
this.dispatchItemForm.escortPhone = '';
} else {
this.dispatchItemForm.carrierContractId = '';
if (nextValue === '网货平台') {
this.dispatchItemForm.carrierId = '';
this.dispatchItemForm.carrierName = '';
}
}
this.dispatchItemForm.carrierType = nextValue;
this.loadDispatchCarrierOptions(this.dispatchRow);
@@ -7379,8 +7376,11 @@ export default {
});
return Promise.all([detailPromise, contractPromise])
.then(([, carrierContracts]) => {
if (carrierTypeAtRequest === '承运商') {
this.dispatchCarrierOptions = carrierContracts || [];
if (carrierTypeAtRequest !== '自运') {
this.dispatchCarrierOptions = (carrierContracts || []).map(item => ({
...item,
value: item.carrierContractId || item.id,
}));
const current = this.dispatchCarrierOptions.find(
item =>
String(item.carrierContractId) === String(this.dispatchItemForm.carrierContractId)
@@ -7408,19 +7408,37 @@ export default {
},
getWaybillCarrierContractOptions(contracts = []) {
const counts = contracts.reduce((result, item) => {
const name = String(item.partyB || '').trim();
const name = String(
item.partyB ||
item.partyBName ||
item.contractPartyB ||
item.customerContractPartyB ||
''
).trim();
if (name) result[name] = (result[name] || 0) + 1;
return result;
}, {});
return contracts
.map(contract => {
const carrierName = String(contract.partyB || '').trim();
const carrierName = String(
contract.partyB ||
contract.partyBName ||
contract.contractPartyB ||
contract.customerContractPartyB ||
''
).trim();
if (!carrierName || !contract.id) return null;
const identifier = contract.contractName || contract.contractNo || contract.id;
return {
id: contract.id,
value: contract.id,
carrierContractId: contract.id,
carrierId:
contract.partyBId ||
contract.partyBUserId ||
contract.contractPartyBId ||
contract.customerContractPartyBId ||
'',
carrierName,
fullName: carrierName,
label: counts[carrierName] > 1 ? `${carrierName}${identifier}` : carrierName,
@@ -7464,9 +7482,9 @@ export default {
const optionValue = this.dispatchIsCarrierMode ? item.carrierContractId : item.value;
return String(optionValue || '') === String(value || '');
});
if (this.dispatchIsCarrierMode) {
if (this.dispatchItemForm.carrierType !== '自运') {
this.dispatchItemForm.carrierContractId = carrier?.carrierContractId || '';
this.dispatchItemForm.carrierId = '';
this.dispatchItemForm.carrierId = carrier?.carrierId || '';
this.dispatchItemForm.carrierName = carrier?.carrierName || '';
return;
}
@@ -1,10 +1,12 @@
<template>
<el-dialog
<component
:is="standalone ? 'div' : 'el-dialog'"
v-model="visible"
title="导入运单"
width="90%"
append-to-body
destroy-on-close
:class="{ 'waybill-import-page': standalone }"
@closed="handleClosed"
>
<div class="waybill-import-toolbar">
@@ -96,7 +98,7 @@
@current-change="loadBatches"
@size-change="loadBatches"
/>
</el-dialog>
</component>
<el-dialog v-model="detailVisible" title="导入运单详情" width="90%" append-to-body>
<el-form :inline="true" :model="detailQuery"
@@ -423,7 +425,7 @@
</template>
<script setup>
import { computed, reactive, ref } from 'vue';
import { computed, onMounted, reactive, ref, watch } from 'vue';
import { ElMessage, ElMessageBox } from 'element-plus';
import { getList as getCargoTypeList } from '@/api/base/cargo-type';
import { getList as getCommonCargoList } from '@/api/business/common-cargo';
@@ -434,7 +436,7 @@ import { getDictionary } from '@/api/system/dictbiz';
import * as api from '@/api/business/waybill-manage';
import { downloadXls } from '@/utils/util';
const props = defineProps({ modelValue: Boolean });
const props = defineProps({ modelValue: Boolean, standalone: Boolean });
const emit = defineEmits(['update:modelValue', 'closed']);
const visible = computed({
get: () => props.modelValue,
@@ -753,6 +755,15 @@ const loadBatches = async () => {
batches.value = res.data?.data?.records || [];
page.total = res.data?.data?.total || 0;
};
onMounted(() => {
if (props.standalone) loadBatches();
});
watch(
() => props.modelValue,
value => {
if (value) loadBatches();
}
);
const resetQuery = () => {
Object.assign(query, { batchNo: '', carrierId: '', createUser: '', createTimeRange: [] });
page.current = 1;
@@ -1083,6 +1094,12 @@ const confirmImport = async () => {
}
}
.waybill-import-page {
min-height: calc(100vh - 120px);
padding: 12px 24px 24px;
background: #fff;
}
.waybill-import-create {
&__form-panel,
&__detail-panel {
@@ -634,13 +634,7 @@
item.fullName ||
item.name
"
:value="
item.value ||
item.customerName ||
item.carrierName ||
item.fullName ||
item.name
"
:value="taskCarrierOptionValue(item)"
/>
</el-select>
</el-form-item>
@@ -1188,13 +1182,7 @@
item.fullName ||
item.name
"
:value="
item.value ||
item.customerName ||
item.carrierName ||
item.fullName ||
item.name
"
:value="taskCarrierOptionValue(item)"
/>
</el-select>
</el-form-item>
@@ -2212,12 +2200,6 @@
</template>
</el-dialog>
<waybill-import-dialog
v-if="config.enableWaybillImport"
v-model="waybillImportBox"
@closed="refreshChange"
/>
<flow-design
v-if="website.design.designMode"
is-dialog
@@ -2827,7 +2809,6 @@ import { h, resolveComponent } from 'vue';
import { mapGetters } from 'vuex';
import NProgress from 'nprogress';
import 'nprogress/nprogress.css';
import WaybillImportDialog from './waybill-import-dialog.vue';
const AMAP_KEY = '653b7cf105ad7fb8ec9b2f5198ade315';
const AMAP_SECURITY_CODE = '5aab65c632e48ebae0d0e28f5b28e21a';
@@ -2973,7 +2954,6 @@ const getPlainAvueForm = avueForm => {
export default {
components: {
WaybillImportDialog,
PageAvueForm,
InfoFilled,
Rank,
@@ -3073,7 +3053,6 @@ export default {
currentPage: 1,
total: 0,
},
waybillImportBox: false,
draftSaveLoading: false,
crudDialogType: '',
defaultDialogButtons: null,
@@ -3363,10 +3342,9 @@ export default {
},
taskCarrierValue: {
get() {
if (this.form.carrierType === '承运商') {
return this.form.carrierContractId || '';
}
return this.form.carrierName || '';
return this.form.carrierType === '自运'
? this.form.carrierName || ''
: this.form.carrierContractId || this.form.carrierName || '';
},
set(value) {
this.handleTaskCarrierChange(value);
@@ -5387,34 +5365,34 @@ export default {
},
handleTaskCarrierTypeChange(value) {
const nextValue = value || '承运商';
this.form.carrierName = '';
this.form.carrierId = '';
this.form.carrierContractId = '';
if (nextValue === '承运商') {
this.form.trailerVehicleNo = '';
this.form.escortName = '';
this.form.escortPhone = '';
} else if (!this.isTaskCarrierRequired(nextValue)) {
this.form.carrierName = '';
this.form.carrierId = '';
}
if (nextValue !== '承运商') {
this.form.carrierContractId = '';
}
this.form.carrierType = nextValue;
if (nextValue === '自运') {
const contract = this.contractOptions.find(
item => String(item.id) === String(this.form.contractId)
);
this.fillSelfOperatedCarrierFromContract(contract);
}
this.taskCarrierRequestId += 1;
this.taskCarrierOptions = [];
this.taskCarrierLoading = false;
if (nextValue === '自运' && this.form.projectId) {
this.resetWaybillCarrierContractState();
//
// 使
if (this.form.projectId) {
this.loadTaskCarrierOptions();
}
},
fillSelfOperatedCarrierFromContract(contract = {}) {
if (this.form.carrierType !== '自运') return;
const carrierName = String(contract.partyB || contract.partyBName || '').trim();
const carrierName = String(
contract.partyB ||
contract.partyBName ||
contract.contractPartyB ||
contract.customerContractPartyB ||
''
).trim();
if (!carrierName) return;
const exists = this.taskCarrierOptions.some(
item => String(item.value || item.carrierName || '') === carrierName
@@ -5433,6 +5411,19 @@ export default {
isTaskCarrierRequired(carrierType) {
return ['承运商', '网货平台'].includes(String(carrierType || '').trim());
},
taskCarrierOptionValue(item = {}) {
if (this.form.carrierType !== '自运') {
return item.carrierContractId || item.value || item.id || '';
}
return (
item.carrierName ||
item.customerName ||
item.fullName ||
item.name ||
item.value ||
''
);
},
getProjectCarrierOptions(project = {}) {
const rows = this.parseJsonArray(project.carrierJson);
const names = String(project.carrierNames || '')
@@ -5462,18 +5453,42 @@ export default {
},
getWaybillCarrierContractOptions(contracts = []) {
const carrierNameCounts = contracts.reduce((counts, contract) => {
const carrierName = String(contract.partyA || contract.partyAName || '').trim();
const carrierName = String(
contract.partyB ||
contract.partyBName ||
contract.contractPartyB ||
contract.customerContractPartyB ||
contract.secondParty ||
contract.secondPartyName ||
''
).trim();
if (carrierName) counts[carrierName] = (counts[carrierName] || 0) + 1;
return counts;
}, {});
return contracts
.map(contract => {
const carrierName = String(contract.partyA || contract.partyAName || '').trim();
const carrierName = String(
contract.partyB ||
contract.partyBName ||
contract.contractPartyB ||
contract.customerContractPartyB ||
contract.secondParty ||
contract.secondPartyName ||
''
).trim();
if (!carrierName || !contract.id) return null;
const contractIdentifier = contract.contractName || contract.contractNo || contract.id;
return {
id: contract.id,
carrierId: contract.partyAId || contract.partyAUserId || contract.customerId || '',
carrierId:
contract.partyBId ||
contract.partyBUserId ||
contract.contractPartyBId ||
contract.customerContractPartyBId ||
contract.secondPartyId ||
contract.secondPartyUserId ||
contract.carrierId ||
'',
value: contract.id,
label:
carrierNameCounts[carrierName] > 1
@@ -5534,7 +5549,7 @@ export default {
...project,
id: projectId,
});
if (carrierTypeAtRequest === '承运商') {
if (carrierTypeAtRequest !== '自运') {
if (!projectId) {
this.taskCarrierOptions = [];
return Promise.resolve([]);
@@ -5545,12 +5560,6 @@ export default {
if (requestId !== this.taskCarrierRequestId) return this.taskCarrierOptions;
if (options === null) return this.taskCarrierOptions;
this.taskCarrierOptions = options || [];
if (!this.taskCarrierOptions.length && this.form.carrierType === '自运') {
const customerContract = this.contractOptions.find(
item => String(item.id) === String(this.form.contractId)
);
this.fillSelfOperatedCarrierFromContract(customerContract);
}
return this.taskCarrierOptions;
})
.catch(() => this.taskCarrierOptions)
@@ -5599,14 +5608,19 @@ export default {
},
handleTaskCarrierChange(value) {
const carrier = this.taskCarrierOptions.find(item =>
[item.value, item.customerName, item.carrierName, item.fullName, item.name].some(
name => String(name || '') === String(value || '')
)
[
this.taskCarrierOptionValue(item),
item.value,
item.customerName,
item.carrierName,
item.fullName,
item.name,
].some(name => String(name || '') === String(value || ''))
);
if (this.form.carrierType === '承运商') {
if (this.form.carrierType !== '自运') {
this.form.carrierContractId = carrier?.carrierContractId || '';
this.form.carrierId = carrier?.carrierId || '';
this.form.carrierName = carrier?.carrierName || value || '';
this.form.carrierName = carrier?.carrierName || '';
return;
}
this.form.carrierId = carrier?.carrierContractId ? '' : carrier?.id || '';
@@ -7537,7 +7551,7 @@ export default {
},
handleImport() {
if (this.config.enableWaybillImport) {
this.waybillImportBox = true;
this.$router.push({ path: '/business/waybill-import' });
return;
}
const column = this.findColumn(this.excelOptionConfig.column, 'excelFile');
+26 -5
View File
@@ -2464,6 +2464,9 @@ export default {
});
},
handleCarrierTypeChange() {
this.dialogForm.carrierContractId = '';
this.dialogForm.carrierName = '';
this.dialogForm.carrierId = '';
if (this.dialogForm.carrierType === '承运商') {
this.dialogForm.trailerVehicleNo = '';
this.dialogForm.escortName = '';
@@ -2471,7 +2474,6 @@ export default {
}
if (this.dialogForm.carrierType === '网货平台') {
this.dialogForm.carrierContractId = '';
this.dialogForm.carrierName = '';
}
this.loadTaskCarrierOptions();
},
@@ -2626,19 +2628,38 @@ export default {
const response = await loadingApi.getCarrierContracts(projectIds);
if (requestId !== this.taskCarrierRequestId) return [];
const contracts = response.data?.data || response.data || [];
if (this.dialogForm.carrierType === '承运商') {
this.taskCarrierOptions = contracts;
if (this.dialogForm.carrierType !== '自运') {
this.taskCarrierOptions = contracts
.map(item => ({
...item,
carrierName:
item.partyB ||
item.partyBName ||
item.contractPartyB ||
item.customerContractPartyB ||
item.carrierName ||
'',
carrierId:
item.partyBId ||
item.partyBUserId ||
item.contractPartyBId ||
item.customerContractPartyBId ||
item.carrierId ||
'',
}))
.filter(item => item.carrierName);
const current =
contracts.find(item => String(item.id) === String(this.dialogForm.carrierContractId)) ||
contracts.find(item => item.carrierName === this.dialogForm.carrierName);
this.taskCarrierOptions.find(item => item.carrierName === this.dialogForm.carrierName);
if (current) {
this.dialogForm.carrierContractId = current.id;
this.dialogForm.carrierName = current.carrierName;
this.dialogForm.carrierId = current.carrierId || '';
} else {
this.dialogForm.carrierContractId = '';
this.dialogForm.carrierName = '';
}
return contracts;
return this.taskCarrierOptions;
}
if (this.dialogForm.carrierType === '自运' && contracts.length) {
this.taskCarrierOptions = contracts;
+1 -3
View File
@@ -2003,9 +2003,7 @@ export default {
getCustomerArchiveList(1, 100, {
customerType: type,
status: 1,
...(this.dialogType !== 'add' && type === '客户'
? { approvalStatus: 'approved' }
: {}),
approvalStatus: 'approved',
})
.then(res => {
const records = (res.data.data && res.data.data.records) || [];
+38
View File
@@ -0,0 +1,38 @@
<template>
<basic-container class="waybill-import-page-container">
<div class="waybill-import-page-title">导入运单</div>
<waybill-import-dialog standalone />
</basic-container>
</template>
<script setup>
import WaybillImportDialog from './components/waybill-import-dialog.vue';
</script>
<style scoped lang="scss">
.waybill-import-page-container {
:deep(.basic-container__card > .el-card__body) {
padding: 0;
}
}
.waybill-import-page-title {
position: relative;
padding: 16px 24px 12px 36px;
border-bottom: 1px solid #eff1f7;
color: #303133;
font-size: 18px;
font-weight: 600;
&::before {
position: absolute;
top: 16px;
left: 24px;
width: 4px;
height: 22px;
border-radius: 2px;
background: #409eff;
content: '';
}
}
</style>
+10 -6
View File
@@ -1403,6 +1403,14 @@ export default {
attachmentFileName(file) {
return String(file?.originalName || file?.name || file?.fileName || '').trim();
},
normalizedAttachmentFileName(file) {
let fileName = this.attachmentFileName(file) || this.attachmentFileUrl(file);
fileName = String(fileName || '').split(/[?#]/)[0];
try {
fileName = decodeURIComponent(fileName);
} catch {}
return fileName.toLocaleLowerCase();
},
attachmentFileUrl(file) {
return (
file?.url ||
@@ -1469,7 +1477,7 @@ export default {
this.$message.error('附件预览失败');
},
attachmentMatchesMaterial(file, material) {
const fileName = this.attachmentFileName(file).toLocaleLowerCase();
const fileName = this.normalizedAttachmentFileName(file);
return (
Boolean(this.attachmentFileUrl(file)) &&
(file.attachmentType === MATERIAL_TYPE_MAP[material.key] ||
@@ -1477,11 +1485,7 @@ export default {
);
},
resolveAttachmentTypeByFileName(file) {
let fileName = this.attachmentFileName(file) || this.attachmentFileUrl(file);
fileName = String(fileName || '').split(/[?#]/)[0].toLocaleLowerCase();
try {
fileName = decodeURIComponent(fileName);
} catch {}
const fileName = this.normalizedAttachmentFileName(file);
const material = [...Object.values(ATTACHMENT_MATERIALS)]
.sort(
(a, b) =>
+5 -26
View File
@@ -169,8 +169,8 @@
<script>
import { ArrowDown, ArrowUp } from '@element-plus/icons-vue';
import { mapGetters } from 'vuex';
import * as XLSX from 'xlsx';
import { createSettlementTransfer } from '@/utils/settlement-transfer';
import { downloadFile } from '@/utils/util';
import * as api from '@/api/settlement/formalSettlement';
import * as paymentApi from '@/api/payment/paymentApplication';
import {
@@ -503,31 +503,10 @@ export default {
win.document.close();
},
async handleExport() {
const response = await api.getList(1, 100000, this.buildQueryParams());
const data = this.unwrapData(response);
const rows = (data.records || []).map(item => ({
结算单号: item.formalSettlementNo,
预结算单号: item.preSettlementNos,
来源: item.sourceType,
付款方: item.payerName,
收款方: item.payeeName,
项目名称: item.projectName,
所属组织: item.deptName,
合同编号: item.contractNo,
合同名称: item.contractName,
原币结算金额: item.settlementAmount,
本位币结算金额: item.localSettlementAmount,
结算汇率: item.exchangeRate,
发票状态: this.invoiceName(item.invoiceStatus, item.settlementType),
收付款状态: this.paymentName(item.paymentStatus),
审核状态: item.approvalStatusName,
金蝶单据号: item.kingdeeBillNo,
创建人: item.createUserName,
创建时间: item.createTime,
}));
const workbook = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(workbook, XLSX.utils.json_to_sheet(rows), '正式结算单');
XLSX.writeFile(workbook, `正式结算单${this.$dayjs().format('YYYY-MM-DD HH-mm-ss')}.xlsx`);
const params = this.buildQueryParams();
if (this.selection.length) params.ids = this.selection.map(item => item.id).join(',');
const { data } = await api.exportList(params);
downloadFile(data, `正式结算单${this.$dayjs().format('YYYY-MM-DD HH-mm-ss')}.xlsx`);
},
buildQueryParams() {
// 所属组织级联返回 id 路径,转成组织名称传给后端(用副本,避免污染搜索框回显)
+3 -1
View File
@@ -622,7 +622,9 @@ export default {
)}</div></div><h2>结算合计</h2><table><thead><tr><th>序号</th><th>费用类型</th><th>费用项</th><th>原金额</th><th>调整金额</th><th>结算金额</th></tr></thead><tbody>${summaryRows}</tbody></table><div class="actions"><button onclick="window.print()">打印 / 另存为 PDF</button></div></body></html>`;
},
async handleExport() {
const { data } = await exportList(this.buildQuery());
const params = this.buildQuery();
if (this.selection.length) params.ids = this.selection.map(item => item.id).join(',');
const { data } = await exportList(params);
downloadFile(data, `预结算单${this.$dayjs().format('YYYY-MM-DD HH-mm-ss')}.xlsx`);
},
openFlow(row) {
@@ -93,7 +93,7 @@
<script>
import { ArrowDown, ArrowUp, Refresh } from '@element-plus/icons-vue';
import { mapGetters } from 'vuex';
import * as XLSX from 'xlsx';
import { downloadFile } from '@/utils/util';
import * as api from '@/api/settlement/transportReconciliation';
import { transportReconciliationSearchFields } from '@/option/settlement/transportReconciliationSearch';
import { transportReconciliationTableColumns } from '@/option/settlement/transportReconciliationTable';
@@ -217,30 +217,13 @@ export default {
this.loadTable();
},
async handleExport() {
const response = await api.getList(1, 100000, {
...this.query,
const params = {
...this.normalizeOrganizationSearch({ ...this.query }, 'deptName'),
settlementType: this.settlementType,
});
const data = response?.data?.data || response?.data || response || {};
const exportRows = (data.records || []).map(item => ({
对账单号: item.reconciliationNo,
付款方: item.payerName,
收款方: item.payeeName,
项目名称: item.projectName,
所属组织: item.deptName,
合同编号: item.contractNo,
合同名称: item.contractName,
结算金额: Number(item.settlementAmount || 0).toFixed(2),
对账模式: item.reconciliationModeName,
账单总数: item.externalBillCount,
匹配数: item.matchedCount,
对账状态: item.reconciliationStatusName,
创建人: item.createUserName,
创建时间: item.createTime,
}));
const workbook = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(workbook, XLSX.utils.json_to_sheet(exportRows), '运输对账');
XLSX.writeFile(workbook, `运输对账${this.$dayjs().format('YYYY-MM-DD HH-mm-ss')}.xlsx`);
};
if (this.selection.length) params.ids = this.selection.map(item => item.id).join(',');
const { data } = await api.exportList(params);
downloadFile(data, `运输对账${this.$dayjs().format('YYYY-MM-DD HH-mm-ss')}.xlsx`);
},
isEditable(row) {
return row.reconciliationStatus === 'unfinished';