Files
cattleTransportation/pc-cattle-transportation/src/views/shipping/orderDialog.vue
2025-10-20 17:32:09 +08:00

672 lines
25 KiB
Vue

<template>
<el-dialog v-model="data.dialogVisible" title="创建装车订单" :before-close="handleClose" style="width: 1100px; padding-bottom: 20px">
<el-form ref="formDataRef" :model="ruleForm" :rules="rules" label-width="auto">
<el-row :gutter="40">
<el-col :span="12">
<el-form-item label="订单标题" prop="deliveryTitle">
<el-input v-model="ruleForm.deliveryTitle" placeholder="请输入订单标题" clearable></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="装车数量" prop="ratedQuantity">
<el-input v-model="ruleForm.ratedQuantity" placeholder="请输入装车数量" clearable> <template #append></template></el-input>
</el-form-item></el-col
>
</el-row>
<el-row :gutter="40">
<el-col :span="12">
<el-form-item label="选择供应商" prop="supplierName">
<el-select
v-model="ruleForm.supplierName"
clearable
filterable
remote
:remote-method="supplierRemoteMethod"
:loading="data.supplierLoading"
@change="supplierChange"
placeholder="请选择供应商"
style="width: 100%"
multiple
collapse-tags
collapse-tags-tooltip
:max-collapse-tags="2"
>
<el-option
v-for="item in data.supplierOptions"
:key="item.id"
:label="item.username + ' / ' + item.mobile + ' (' + item.tenantName + ')'"
:value="item.mobile"
>
</el-option>
<el-pagination
style="padding: 0px 20px"
@current-change="supplierHandleCurrentChange"
:page-size="10"
:current-page="data.supplierPageNum"
layout="total, prev, pager, next"
:total="data.supplierTotal"
>
</el-pagination>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="选择资金方" prop="financeName">
<el-select
v-model="ruleForm.financeName"
clearable
filterable
remote
:remote-method="financeRemoteMethod"
:loading="data.financeLoading"
@change="financeChange"
placeholder="请选择资金方"
style="width: 100%"
>
<el-option
v-for="item in data.financeOptions"
:key="item.id"
:label="item.username + ' / ' + item.mobile + ' (' + item.tenantName + ')'"
:value="item.mobile"
>
</el-option>
<el-pagination
style="padding: 0px 20px"
@current-change="financeHandleCurrentChange"
:page-size="10"
:current-page="data.financePageNum"
layout="total, prev, pager, next"
:total="data.financeTotal"
>
</el-pagination>
</el-select> </el-form-item
></el-col>
</el-row>
<el-row :gutter="40">
<el-col :span="12">
<el-form-item label="选择司机" prop="driverMobile">
<el-select
v-model="ruleForm.driverMobile"
clearable
filterable
remote
:remote-method="driverRemoteMethod"
:loading="data.driverLoading"
@change="driverChange"
placeholder="请选择司机"
style="width: 100%"
>
<el-option
v-for="item in data.driverOptions"
:key="item.id"
:label="item.username + ' / ' + item.mobile"
:value="item.mobile"
>
</el-option>
<el-pagination
style="padding: 0px 20px"
@current-change="driverHandleCurrentChange"
:page-size="10"
:current-page="data.driverPageNum"
layout="total, prev, pager, next"
:total="data.driverTotal"
>
</el-pagination>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="选择采购商" prop="purchaserMobile">
<el-select
v-model="ruleForm.purchaserMobile"
clearable
filterable
remote
:remote-method="purchaserRemoteMethod"
:loading="data.purchaserLoading"
@change="purchaserChange"
placeholder="请选择采购商"
style="width: 100%"
>
<el-option
v-for="item in data.purchaserOptions"
:key="item.id"
:label="item.username + ' / ' + item.mobile + ' (' + item.tenantName + ')'"
:value="item.mobile"
>
</el-option>
<el-pagination
style="padding: 0px 20px"
@current-change="purchaserHandleCurrentChange"
:page-size="10"
:current-page="data.purchaserPageNum"
layout="total, prev, pager, next"
:total="data.purchaserTotal"
>
</el-pagination>
</el-select> </el-form-item
></el-col>
</el-row>
<el-row :gutter="40">
<el-col :span="12">
<el-form-item label="采购单价" prop="buyerPrice">
<el-input v-model="ruleForm.buyerPrice" placeholder="请输入采购单价" clearable>
<template #append>/公斤</template>
</el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="销售单价" prop="salePrice">
<el-input v-model="ruleForm.salePrice" placeholder="请输入销售单价" clearable> <template #append>/公斤</template></el-input>
</el-form-item></el-col
>
</el-row>
<el-row :gutter="40">
<el-col :span="12">
<el-form-item label="约定单价" prop="firmPrice">
<el-input v-model="ruleForm.firmPrice" placeholder="请输入约定单价" clearable>
<template #append>/公斤</template>
</el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="40">
<el-col :span="12">
<el-form-item label="起始地" prop="startLocation">
<el-autocomplete
v-model="ruleForm.startLocation"
:fetch-suggestions="startSearchLocation"
placeholder="请输入起始地"
style="width: 100%"
:trigger-on-focus="false"
@select="startHandleSelects"
/>
<div class="maps" style="width: 100%">
<baidu-map
class="bm-view"
:center="data.startCenter"
:zoom="14"
style="height: 300px; width: 100%; border: 1px solid #ddd"
@ready="handler"
:scroll-wheel-zoom="true"
:extensions_road="true"
:extensions_town="true"
v-if="data.dialogVisible"
@click="startClickInfo"
:map-type="'BMAP_NORMAL_MAP'"
:enable-map-click="true"
>
<bm-marker :position="data.startCenter" :dragging="true"></bm-marker>
</baidu-map>
</div>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="目的地" prop="endLocation">
<el-autocomplete
v-model="ruleForm.endLocation"
:fetch-suggestions="endSearchLocation"
placeholder="请输入目的地"
style="width: 100%"
:trigger-on-focus="false"
@select="endHandleSelects"
/>
<div class="maps" style="width: 100%">
<baidu-map
class="bm-view"
:center="data.endCenter"
:zoom="14"
style="height: 300px; width: 100%; border: 1px solid #ddd"
@ready="handler"
:scroll-wheel-zoom="true"
:extensions_road="true"
:extensions_town="true"
v-if="data.dialogVisible"
@click="endClickInfo"
:map-type="'BMAP_NORMAL_MAP'"
:enable-map-click="true"
>
<bm-marker :position="data.endCenter" :dragging="true"></bm-marker>
</baidu-map>
</div>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button :loading="data.saveLoading" type="primary" @click="onClickSave">保存</el-button>
<el-button @click="handleClose">取消</el-button>
</span>
</template>
</el-dialog>
</template>
<script setup>
import { ref, reactive, onMounted } from 'vue';
import { orderAdd } from '@/api/shipping.js';
import { driverList, userList, memberListByType } from '@/api/userManage.js';
const emits = defineEmits();
const formDataRef = ref(null);
const maps = ref();
const BMap = reactive({});
const data = reactive({
dialogVisible: false,
saveLoading: false,
supplierOptions: [],
financeOptions: [],
driverOptions: [],
purchaserOptions: [],
startCenter: { lng: 0, lat: 0 },
endCenter: { lng: 0, lat: 0 },
driverLoading: false, // 司机loading
driverName: '',
driverPageNum: 1,
driverTotal: 0,
purchaserLoading: false, // 采购商loading
purchaserPageNum: 1,
purchaserTotal: 0,
purchaserName: '',
financeLoading: false, // 资金方loading
financePageNum: 1,
financeTotal: 0,
financeName: '',
supplierLoading: false, // 供应商loading
supplierPageNum: 1,
supplierTotal: 0,
supplierName: '',
});
const ruleForm = reactive({
deliveryTitle: '', // 订单标题
ratedQuantity: '', // 装车数量
supplier: [], // 供应商
fundId: '', // 资金方
driverId: '', // 司机
buyerId: '', // 采购商
buyerPrice: '', // 采购单价
salePrice: '', // 销售单价
firmPrice: '', // 约定单价
startLocation: '', // 起始地
startLat: '',
startLon: '',
endLocation: '', // 目的地
endLat: '',
endLon: '',
driverMobile: '',
purchaserMobile: '',
supplierMobile: '',
});
const rules = reactive({
deliveryTitle: [{ required: true, message: '请输入订单标题', trigger: 'blur' }],
// ratedQuantity: [{ required: true, message: '请输入装车数量', trigger: 'blur' }],
// supplierName: [{ required: true, message: '请选择供应商', trigger: 'change' }],
// financeName: [{ required: true, message: '请选择资金方', trigger: 'change' }],
// driverMobile: [{ required: true, message: '请选择司机', trigger: 'change' }],
// purchaserMobile: [{ required: true, message: '请选择采购商', trigger: 'change' }],
// buyerPrice: [{ required: true, message: '请输入采购单价', trigger: 'blur' }],
// salePrice: [{ required: true, message: '请输入销售单价', trigger: 'blur' }],
// startLocation: [{ required: true, message: '请输入起始地', trigger: 'blur' }],
// endLocation: [{ required: true, message: '请输入目的地', trigger: 'blur' }],
});
const handleClose = () => {
if (formDataRef.value) {
formDataRef.value.resetFields();
}
data.dialogVisible = false;
};
// ----------------
// 初始化
const handler = ({ BMap, map }) => {
BMap = BMap;
maps.value = map;
if (data.startCenter.lng == 0 && data.startCenter.lat == 0) {
const localcity = new BMap.LocalCity();
localcity.get((e) => {
data.startCenter.lng = e.center.lng;
data.startCenter.lat = e.center.lat;
data.endCenter.lng = e.center.lng;
data.endCenter.lat = e.center.lat;
});
} else {
// 如果有坐标点则,展示坐标点
}
};
const startSearchLocation = async (str, cb) => {
// 使用百度地图的地点搜索服务
const local = new window.BMap.LocalSearch(maps.value, {
onSearchComplete(res) {
const arr = [];
if (local.getStatus() == BMAP_STATUS_SUCCESS) {
for (let i = 0; i < res.getCurrentNumPois(); i++) {
const x = res.getPoi(i);
const item = { value: x.address + x.title, point: x.point };
arr.push(item);
}
cb(arr);
} else {
// ElMessage.error('未找到相关地点,请尝试其他关键字。');
}
},
});
local.search(str);
};
const endSearchLocation = async (str, cb) => {
// 使用百度地图的地点搜索服务
const local = new window.BMap.LocalSearch(maps.value, {
onSearchComplete(res) {
const arr = [];
if (local.getStatus() == BMAP_STATUS_SUCCESS) {
for (let i = 0; i < res.getCurrentNumPois(); i++) {
const x = res.getPoi(i);
const item = { value: x.address + x.title, point: x.point };
arr.push(item);
}
cb(arr);
} else {
// ElMessage.error('未找到相关地点,请尝试其他关键字。');
}
},
});
local.search(str);
};
const startHandleSelects = (item) => {
// 点击搜索的点位并地图跳转到该坐标
const { point } = item;
ruleForm.startLocation = item.value;
getStartClickInfo({ point });
};
const getStartClickInfo = ({ point }) => {
const geoc = new window.BMap.Geocoder(); // 创建地址解析器的实例
data.startCenter.lng = point.lng;
data.startCenter.lat = point.lat;
geoc.getLocation(point, function (result) {
if (result.surroundingPois.length > 0) {
const fcaArr = [result.addressComponents.province, result.addressComponents.city, result.addressComponents.district];
ruleForm.startLon = result.point.lng;
ruleForm.startLat = result.point.lat;
}
});
};
const startClickInfo = (e) => {
data.startCenter.lng = e.point.lng;
data.startCenter.lat = e.point.lat;
const geocoder = new window.BMap.Geocoder();
geocoder.getLocation(e.point, (res) => {
if (res) {
ruleForm.startLocation = res.address;
ruleForm.startLon = res.point.lng;
ruleForm.startLat = res.point.lat;
}
});
};
// 到达点
const endHandleSelects = (item) => {
// 点击搜索的点位并地图跳转到该坐标
const { point } = item;
ruleForm.endLocation = item.value;
getEndClickInfo({ point });
};
const getEndClickInfo = ({ point }) => {
const geoc = new window.BMap.Geocoder(); // 创建地址解析器的实例
data.endCenter.lng = point.lng;
data.endCenter.lat = point.lat;
geoc.getLocation(point, function (result) {
if (result.surroundingPois.length > 0) {
const fcaArr = [result.addressComponents.province, result.addressComponents.city, result.addressComponents.district];
ruleForm.endLon = result.point.lng;
ruleForm.endLat = result.point.lat;
}
});
};
const endClickInfo = (e) => {
data.endCenter.lng = e.point.lng;
data.endCenter.lat = e.point.lat;
const geocoder = new window.BMap.Geocoder();
geocoder.getLocation(e.point, (res) => {
if (res) {
ruleForm.endLocation = res.address;
ruleForm.endLon = res.point.lng;
ruleForm.endLat = res.point.lat;
}
});
};
// ----------------
// 供应商远程搜索
const supplierRemoteMethod = (e) => {
data.supplierName = e;
data.supplierPageNum = 1;
getSupplierList();
};
// 供应商 列表
const getSupplierList = () => {
data.supplierLoading = true;
const params = {
pageNum: data.supplierPageNum,
pageSize: 10,
type: 2, // 供应商类型
username: data.supplierName,
};
memberListByType(params)
.then((res) => {
data.supplierLoading = false;
data.supplierOptions = res.data.rows;
data.supplierTotal = res.data.total;
})
.catch(() => {
data.supplierLoading = false;
});
};
// 选择供应商分页
const supplierHandleCurrentChange = (val) => {
data.supplierPageNum = val;
getSupplierList();
};
// 选择供应商
const supplierChange = (e) => {
if (e) {
// ruleForm.supplier = data.supplierOptions.find((item) => item.mobile == e).id;
ruleForm.supplier = data.supplierOptions.filter((user) => e.includes(user.mobile)).map((user) => user.id);
} else {
ruleForm.supplier = [];
}
};
// 供应商远程搜索
const financeRemoteMethod = (e) => {
data.financeName = e;
data.financePageNum = 1;
getFinanceList();
};
// 资金方 列表
const getFinanceList = () => {
data.financeLoading = true;
const params = {
pageNum: data.financePageNum,
pageSize: 10,
type: 3, // 资金方类型
username: data.financeName,
};
memberListByType(params)
.then((res) => {
data.financeLoading = false;
data.financeOptions = res.data.rows;
data.financeTotal = res.data.total;
})
.catch(() => {
data.financeLoading = false;
});
};
// 选择资金方分页
const financeHandleCurrentChange = (val) => {
data.financePageNum = val;
getFinanceList();
};
// 选择资金方
const financeChange = (e) => {
if (e) {
ruleForm.fundId = data.financeOptions.find((item) => item.mobile == e).id;
} else {
ruleForm.fundId = '';
}
};
// 司机远程搜索
const driverRemoteMethod = (e) => {
data.driverName = e;
data.driverPageNum = 1;
getDriverList();
};
// 列表
const getDriverList = () => {
data.driverLoading = true;
const params = {
pageNum: data.driverPageNum,
pageSize: 10,
username: data.driverName,
};
driverList(params)
.then((res) => {
data.driverLoading = false;
data.driverOptions = res.data.rows;
data.driverTotal = res.data.total;
})
.catch(() => {
data.driverLoading = false;
});
};
// 选择司机分页
const driverHandleCurrentChange = (val) => {
data.driverPageNum = val;
getDriverList();
};
// 选择司机
const driverChange = (e) => {
if (e) {
ruleForm.driverId = data.driverOptions.find((item) => item.mobile == e).id;
} else {
ruleForm.driverId = '';
}
};
// 采购商远程搜索
const purchaserRemoteMethod = (e) => {
data.purchaserName = e;
data.purchaserPageNum = 1;
getPurchaserList();
};
// 采购商 列表
const getPurchaserList = () => {
data.purchaserLoading = true;
const params = {
pageNum: data.purchaserPageNum,
pageSize: 10,
type: 4, // 采购商类型
username: data.purchaserName,
};
memberListByType(params)
.then((res) => {
data.purchaserLoading = false;
data.purchaserOptions = res.data.rows;
data.purchaserTotal = res.data.total;
})
.catch(() => {
data.purchaserLoading = false;
});
};
// 采购商分页
const purchaserHandleCurrentChange = (val) => {
data.purchaserPageNum = val;
getPurchaserList();
};
// 选择采购商
const purchaserChange = (e) => {
if (e) {
ruleForm.buyerId = data.purchaserOptions.find((item) => item.mobile == e).id;
} else {
ruleForm.buyerId = '';
}
};
const onClickSave = () => {
if (formDataRef.value) {
formDataRef.value.validate((valid) => {
if (valid) {
const params = {
deliveryTitle: ruleForm.deliveryTitle,
ratedQuantity: ruleForm.ratedQuantity,
supplierId: ruleForm.supplier.join(','),
fundId: ruleForm.fundId,
driverId: ruleForm.driverId,
buyerId: ruleForm.buyerId,
buyerPrice: ruleForm.buyerPrice,
salePrice: ruleForm.salePrice,
firmPrice: ruleForm.firmPrice,
startLocation: ruleForm.startLocation,
startLat: ruleForm.startLat,
startLon: ruleForm.startLon,
endLocation: ruleForm.endLocation,
endLat: ruleForm.endLat,
endLon: ruleForm.endLon,
};
data.saveLoading = true;
orderAdd(params)
.then((res) => {
data.saveLoading = false;
if (res.code === 200) {
ElMessage({
message: res.msg,
type: 'success',
});
emits('success');
if (formDataRef.value) {
formDataRef.value.resetFields();
data.dialogVisible = false;
}
} else {
ElMessage.error(res.msg);
}
})
.catch((err) => {
data.saveLoading = false;
});
} else {
console.log('error submit!');
}
});
}
};
const onShowDialog = () => {
if (formDataRef.value) {
formDataRef.value.resetFields();
}
data.dialogVisible = true;
getDriverList();
getPurchaserList();
getFinanceList();
getSupplierList();
};
defineExpose({
onShowDialog,
});
</script>
<style lang="less" scoped>
::v-deep .anchorBL {
display: none;
visibility: hidden;
}
.bm-view {
border-radius: 4px;
overflow: hidden;
/* 优化WebGL渲染 */
transform: translateZ(0);
-webkit-transform: translateZ(0);
will-change: transform;
}
.maps {
border-radius: 4px;
overflow: hidden;
}
</style>