调整业务模块

This commit is contained in:
2026-09-04 05:23:34 +08:00
parent c63c7c3e33
commit e789f1647a
10 changed files with 2082 additions and 591 deletions
@@ -152,10 +152,7 @@
@click="handleTransportSecondaryAddressInputClick('departure')"
>
<template #suffix>
<el-icon
v-if="!transportStationMode"
@click.stop="openTransportMapDialog('departure')"
>
<el-icon @click.stop="openTransportMapDialog('departure')">
<Location />
</el-icon>
</template>
@@ -198,7 +195,7 @@
@click="handleTransportSecondaryAddressInputClick('arrival')"
>
<template #suffix>
<el-icon v-if="!transportStationMode" @click.stop="openTransportMapDialog('arrival')">
<el-icon @click.stop="openTransportMapDialog('arrival')">
<Location />
</el-icon>
</template>
@@ -559,9 +556,15 @@
label-width="auto"
class="shipping-template-page__detail-form shipping-template-page__detail-grid"
>
<el-form-item label="模板编号"><span>{{ detailRow.templateCode || '-' }}</span></el-form-item>
<el-form-item label="模板名称"><span>{{ detailRow.templateName || '-' }}</span></el-form-item>
<el-form-item label="模板类型"><span>{{ detailRow.templateType || '-' }}</span></el-form-item>
<el-form-item label="模板编号"
><span>{{ detailRow.templateCode || '-' }}</span></el-form-item
>
<el-form-item label="模板名称"
><span>{{ detailRow.templateName || '-' }}</span></el-form-item
>
<el-form-item label="模板类型"
><span>{{ detailRow.templateType || '-' }}</span></el-form-item
>
<el-form-item label="备注" class="shipping-template-page__detail-form-wide">
<span>{{ detailRow.remark || '-' }}</span>
</el-form-item>
@@ -575,10 +578,16 @@
label-width="auto"
class="shipping-template-page__detail-form shipping-template-page__detail-grid"
>
<el-form-item label="项目"><span>{{ detailRow.projectName || '-' }}</span></el-form-item>
<el-form-item label="客户合同"><span>{{ detailRow.contractName || '-' }}</span></el-form-item>
<el-form-item label="项目"
><span>{{ detailRow.projectName || '-' }}</span></el-form-item
>
<el-form-item label="客户合同"
><span>{{ detailRow.contractName || '-' }}</span></el-form-item
>
<el-form-item label="运输方式">
<span>{{ getTransportTypeLabel(detailRow.transportType) || detailRow.transportType || '-' }}</span>
<span>{{
getTransportTypeLabel(detailRow.transportType) || detailRow.transportType || '-'
}}</span>
</el-form-item>
<el-form-item label="备注" class="shipping-template-page__detail-form-wide">
<span>{{ detailRow.basicRemark || '-' }}</span>
@@ -588,7 +597,11 @@
<section class="shipping-template-page__detail-section">
<div class="dialog-section-title">收发货信息</div>
<el-form label-position="right" label-width="auto" class="shipping-template-page__detail-form">
<el-form
label-position="right"
label-width="auto"
class="shipping-template-page__detail-form"
>
<el-form-item label="发货地址">
<div class="shipping-template-page__detail-route-values">
<span>{{ detailRow.departureName || '-' }}</span>
@@ -617,11 +630,21 @@
<el-table-column prop="cargoName" label="货物名称" min-width="220" align="center" />
<el-table-column prop="packageType" label="包装" min-width="120" align="center" />
<el-table-column prop="quantity" label="数量" min-width="120" align="center" />
<el-table-column prop="quantityUnit" label="数量单位" min-width="120" align="center" />
<el-table-column
prop="quantityUnit"
label="数量单位"
min-width="120"
align="center"
/>
<el-table-column prop="brand" label="品牌" min-width="120" align="center" />
<el-table-column prop="specification" label="规格" min-width="120" align="center" />
<el-table-column prop="model" label="型号" min-width="120" align="center" />
<el-table-column prop="materialCode" label="物料编码" min-width="140" align="center" />
<el-table-column
prop="materialCode"
label="物料编码"
min-width="140"
align="center"
/>
<el-table-column prop="deviceCode" label="设备编码" min-width="140" align="center" />
<el-table-column prop="remark" label="备注" min-width="160" align="center" />
</el-table>
@@ -638,11 +661,16 @@
label-width="auto"
:class="[
'shipping-template-page__freight-form',
`shipping-template-page__freight-form--${detailTransportMode === 'road' ? 'road' : 'non-road'}`,
`shipping-template-page__freight-form--${
detailTransportMode === 'road' ? 'road' : 'non-road'
}`,
]"
>
<template v-if="detailTransportMode === 'road'">
<template v-for="(item, index) in detailFreightItems" :key="item.quantityUnit || index">
<template
v-for="(item, index) in detailFreightItems"
:key="item.quantityUnit || index"
>
<el-form-item label="单价">
<el-input :model-value="item.unitPrice || '-'" disabled>
<template #append>{{ item.priceUnit || '-' }}</template>
@@ -690,7 +718,9 @@
<el-table-column type="index" label="序号" width="70" />
<el-table-column label="文件名" min-width="220">
<template #default="{ row }">
<el-link type="primary" @click="previewAttachment(row)">{{ attachmentName(row) }}</el-link>
<el-link type="primary" @click="previewAttachment(row)">{{
attachmentName(row)
}}</el-link>
</template>
</el-table-column>
<el-table-column label="附件描述" min-width="220">
@@ -901,7 +931,8 @@
><el-button @click="transportMapBox = false">取消</el-button
><el-button
type="primary"
:disabled="!transportMapSelected.longitude"
:loading="transportMapLoading"
:disabled="!transportMapSelected.detailAddress || !transportMapSelected.regionName"
@click="confirmTransportMapPick"
>确定</el-button
></template
@@ -1410,10 +1441,7 @@ export default {
return this.parseJsonArray(this.detailRow.goodsJson);
},
detailCargoQuantityTotal() {
const total = this.detailGoodsRows.reduce(
(sum, row) => sum + (Number(row.quantity) || 0),
0
);
const total = this.detailGoodsRows.reduce((sum, row) => sum + (Number(row.quantity) || 0), 0);
return total ? String(Number(total.toFixed(3))) : '系统自动计算';
},
detailAttachmentRows() {
@@ -1433,9 +1461,7 @@ export default {
return this.resolveTransportMode(this.detailRow.transportType);
},
detailFreightItems() {
return Array.isArray(this.detailFreight.freightItems)
? this.detailFreight.freightItems
: [];
return Array.isArray(this.detailFreight.freightItems) ? this.detailFreight.freightItems : [];
},
detailFreightTotal() {
const storedTotal = Number(this.detailFreight.totalFreightAmount);
@@ -1970,6 +1996,7 @@ export default {
this.contractLoading = true;
getContractList(1, 9999, {
projectId: this.form.projectId,
projectName: this.form.projectName,
...(this.config.contractQueryParams || {}),
})
.then(res => {
@@ -2239,6 +2266,9 @@ export default {
this.form[`${prefix}Latitude`] = address.latitude || '';
this.form[`${prefix}Contact`] = address.contactName || this.form[`${prefix}Contact`] || '';
this.form[`${prefix}Phone`] = address.contactPhone || this.form[`${prefix}Phone`] || '';
this.$nextTick(() => {
this.$refs.crud?.clearValidate?.([`${prefix}Address`]);
});
},
openTransportStationDialog(target) {
if (!this.form.transportType) return this.$message.warning('请先选择运输方式');
@@ -2299,8 +2329,19 @@ export default {
},
openTransportMapDialog(target) {
if (this.dialogReadonly || !this.form.transportType) return;
this.transportMapTarget = target;
this.transportMapKeyword = this.form[`${target}Address`] || '';
const prefix = target === 'departure' ? 'departure' : 'arrival';
this.transportMapTarget = prefix;
this.transportMapKeyword = this.form[`${prefix}Address`] || this.form[`${prefix}Name`] || '';
this.transportMapSelected = this.buildTransportMapSelection({
longitude: this.form[`${prefix}Longitude`],
latitude: this.form[`${prefix}Latitude`],
detailAddress: this.form[`${prefix}Address`],
regionName: this.form[`${prefix}Name`],
addressCode: this.form[`${prefix}AddressCode`],
});
this.transportMapStatus = this.transportMapSelected.longitude
? '已加载当前选点,可重新选点'
: '可搜索地址或点击地图选点';
this.transportMapBox = true;
},
loadAmap() {
@@ -2310,8 +2351,9 @@ export default {
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;
script.onerror = () => reject(new Error('高德地图组件加载失败'));
document.body.appendChild(script);
});
return amapLoader;
@@ -2321,56 +2363,185 @@ export default {
.then(() => {
this.$nextTick(() => {
if (!this.transportMapInstance) {
const center = this.transportMapSelected.longitude
? this.toLngLat(
this.transportMapSelected.longitude,
this.transportMapSelected.latitude
)
: [116.40769, 39.89945];
this.transportMapInstance = new window.AMap.Map(this.$refs.transportMap, {
center: [116.40769, 39.89945],
zoom: 11,
center,
zoom: this.transportMapSelected.longitude ? 14 : 11,
});
this.transportMapInstance.on('click', event => this.pickMapPoint(event.lnglat));
} else this.transportMapInstance.resize();
} else {
this.transportMapInstance.resize();
}
if (this.transportMapSelected.longitude) {
this.renderTransportMapMarker(
this.toLngLat(
this.transportMapSelected.longitude,
this.transportMapSelected.latitude
)
);
} else {
this.transportMapMarker?.setMap(null);
this.transportMapMarker = null;
}
});
})
.catch(() => {
this.$message.error('高德地图组件加载失败');
this.$message.error('高德地图组件加载失败,请稍后重试或重新打开弹窗');
this.transportMapBox = false;
});
},
searchTransportMapKeyword() {
if (!this.transportMapKeyword) return this.$message.warning('请输入地址关键词');
this.loadAmap().then(() => {
this.transportMapLoading = true;
window.AMap.plugin('AMap.Geocoder', () => {
this.transportMapGeocoder = this.transportMapGeocoder || new window.AMap.Geocoder();
this.transportMapGeocoder.getLocation(this.transportMapKeyword, (status, result) => {
this.transportMapLoading = false;
const location = status === 'complete' && result.geocodes?.[0]?.location;
if (location) this.pickMapPoint(location, this.transportMapKeyword);
else this.$message.warning('地图搜索无匹配地址');
});
const keyword = String(this.transportMapKeyword || '').trim();
if (!keyword) return this.$message.warning('请输入地址关键词');
this.transportMapLoading = true;
this.loadAmap()
.then(() => this.ensureTransportMapGeocoder())
.then(() => this.runTransportMapGeocode('location', keyword))
.then(result => {
const point = this.resolveTransportMapPoint(result);
if (!point) throw new Error('未找到匹配地址');
return this.pickMapPoint(point, keyword);
})
.catch(() => {
this.transportMapStatus = '地图搜索失败';
this.$message.warning('地图搜索无匹配地址');
})
.finally(() => {
this.transportMapLoading = false;
});
});
},
pickMapPoint(point, keyword = '') {
const longitude = point.getLng ? point.getLng() : point.lng;
const latitude = point.getLat ? point.getLat() : point.lat;
if (longitude === undefined || latitude === undefined) return;
this.transportMapSelected = {
longitude: Number(longitude).toFixed(6),
latitude: Number(latitude).toFixed(6),
detailAddress: keyword || this.transportMapKeyword,
};
this.transportMapStatus = '已选点,可确认回填';
if (this.transportMapInstance) {
this.transportMapMarker?.setMap(null);
this.transportMapMarker = new window.AMap.Marker({ position: [longitude, latitude] });
this.transportMapMarker.setMap(this.transportMapInstance);
this.transportMapInstance.setCenter([longitude, latitude]);
const longitude = this.getTransportMapPointLng(point);
const latitude = this.getTransportMapPointLat(point);
if (!Number.isFinite(Number(longitude)) || !Number.isFinite(Number(latitude))) {
this.$message.warning('选点坐标无效');
return Promise.resolve();
}
const lnglat = this.toLngLat(longitude, latitude);
this.renderTransportMapMarker(lnglat);
this.transportMapSelected = this.buildTransportMapSelection({ longitude, latitude });
this.transportMapStatus = '正在反查地址...';
this.transportMapLoading = true;
return this.ensureTransportMapGeocoder()
.then(() => this.runTransportMapGeocode('address', lnglat))
.then(result => {
const address = this.resolveTransportMapAddress(result);
this.transportMapSelected = {
...this.transportMapSelected,
detailAddress: address.detailAddress || keyword,
regionName: address.regionName,
addressCode: address.addressCode,
};
this.transportMapKeyword =
this.transportMapSelected.detailAddress || this.transportMapKeyword;
this.transportMapStatus = this.transportMapSelected.detailAddress || '已选点,可确认回填';
})
.catch(() => {
this.transportMapSelected = {};
this.transportMapStatus = '反查地址失败';
this.$message.error('反查地址失败,请重新选点');
})
.finally(() => {
this.transportMapLoading = false;
});
},
renderTransportMapMarker(point) {
if (!this.transportMapInstance || !window.AMap) return;
this.transportMapMarker?.setMap(null);
this.transportMapMarker = new window.AMap.Marker({ position: point });
this.transportMapMarker.setMap(this.transportMapInstance);
this.transportMapInstance.setCenter(point);
},
confirmTransportMapPick() {
if (!this.transportMapSelected.detailAddress || !this.transportMapSelected.regionName) {
this.$message.warning('请等待地址解析完成后再确认');
return;
}
const prefix = this.transportMapTarget;
this.applyAddress(prefix, this.transportMapSelected);
this.transportMapBox = false;
},
buildTransportMapSelection({ longitude, latitude, detailAddress, regionName, addressCode }) {
return {
longitude: this.formatTransportMapCoordinate(longitude),
latitude: this.formatTransportMapCoordinate(latitude),
detailAddress: detailAddress || '',
regionName: regionName || '',
addressCode: addressCode || '',
};
},
formatTransportMapCoordinate(value) {
if (value === undefined || value === null || value === '') return '';
const numberValue = Number(value);
return Number.isFinite(numberValue) ? numberValue.toFixed(6) : '';
},
toLngLat(longitude, latitude) {
return new window.AMap.LngLat(Number(longitude), Number(latitude));
},
getTransportMapPointLng(point) {
if (!point) return undefined;
return typeof point.getLng === 'function' ? point.getLng() : point.lng ?? point.lon;
},
getTransportMapPointLat(point) {
if (!point) return undefined;
return typeof point.getLat === 'function' ? point.getLat() : point.lat;
},
ensureTransportMapGeocoder() {
if (this.transportMapGeocoder) return Promise.resolve(this.transportMapGeocoder);
return new Promise((resolve, reject) => {
if (!window.AMap?.plugin) {
reject(new Error('高德地图组件未就绪'));
return;
}
window.AMap.plugin(['AMap.Geocoder'], () => {
try {
this.transportMapGeocoder = new window.AMap.Geocoder();
resolve(this.transportMapGeocoder);
} catch (error) {
reject(error);
}
});
});
},
runTransportMapGeocode(action, input) {
return new Promise((resolve, reject) => {
const timer = window.setTimeout(() => reject(new Error('高德地图请求超时')), 10000);
const done = (status, result) => {
window.clearTimeout(timer);
if (status === 'complete' && result) {
resolve(result);
return;
}
reject(new Error('高德地图请求失败'));
};
try {
if (action === 'location') this.transportMapGeocoder.getLocation(input, done);
else this.transportMapGeocoder.getAddress(input, done);
} catch (error) {
window.clearTimeout(timer);
reject(error);
}
});
},
resolveTransportMapPoint(result) {
const geocode = Array.isArray(result?.geocodes) ? result.geocodes[0] : null;
return geocode?.location || result?.location || result?.lnglat || null;
},
resolveTransportMapAddress(result = {}) {
const regeocode = result.regeocode || {};
const component = regeocode.addressComponent || {};
const city = Array.isArray(component.city) ? '' : component.city;
return {
detailAddress: regeocode.formattedAddress || '',
regionName: [component.province, city, component.district].filter(Boolean).join(''),
addressCode: component.adcode || '',
};
},
ensureCargoTypeOptions() {
if (this.cargoTypeRequest) return this.cargoTypeRequest;
if (this.cargoTypeOptions.length) return Promise.resolve(this.cargoTypeOptions);
@@ -2538,9 +2709,7 @@ export default {
quantityUnits() {
return [
...new Set(
this.transportCargoRows
.map(row => String(row.quantityUnit || '').trim())
.filter(Boolean)
this.transportCargoRows.map(row => String(row.quantityUnit || '').trim()).filter(Boolean)
),
];
},
@@ -2990,10 +3159,7 @@ export default {
}
.shipping-template-page__detail-route-values {
display: grid;
grid-template-columns: minmax(160px, 1fr) minmax(220px, 2fr) minmax(140px, 1fr) minmax(
160px,
1fr
);
grid-template-columns: minmax(160px, 1fr) minmax(220px, 2fr) minmax(140px, 1fr) minmax(160px, 1fr);
gap: 8px;
width: 100%;
}