添加新的需求

This commit is contained in:
xuqiuyun
2025-10-20 17:32:09 +08:00
parent 9979e00b47
commit 361d5ab1ae
247 changed files with 34249 additions and 1 deletions

View File

@@ -0,0 +1,356 @@
<template>
<el-dialog
v-model="dialogVisible"
title="新增运送清单"
width="800px"
:close-on-click-modal="false"
@close="handleClose"
>
<el-form
ref="formRef"
:model="formData"
:rules="rules"
label-width="120px"
>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="发货方" prop="shipper">
<el-input v-model="formData.shipper" placeholder="请输入发货方" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="采购方" prop="buyer">
<el-input v-model="formData.buyer" placeholder="请输入采购方" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="车牌号" prop="plateNumber">
<el-input v-model="formData.plateNumber" placeholder="如京A12345" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="司机姓名" prop="driverName">
<el-input v-model="formData.driverName" placeholder="请输入司机姓名" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="司机电话" prop="driverPhone">
<el-input v-model="formData.driverPhone" placeholder="请输入司机电话" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="主机设备" prop="serverId">
<el-select
v-model="formData.serverId"
placeholder="请选择主机设备"
clearable
filterable
style="width: 100%"
>
<el-option
v-for="item in serverList"
:key="item.id"
:label="item.deviceNo || item.deviceId"
:value="item.id"
/>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="耳标设备" prop="eartagIds">
<el-select
v-model="formData.eartagIds"
placeholder="请选择耳标设备"
multiple
clearable
filterable
style="width: 100%"
>
<el-option
v-for="item in eartagList"
:key="item.id"
:label="item.deviceNo || item.deviceId"
:value="item.id"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="项圈设备" prop="collarIds">
<el-select
v-model="formData.collarIds"
placeholder="请选择项圈设备"
multiple
clearable
filterable
style="width: 100%"
>
<el-option
v-for="item in collarList"
:key="item.id"
:label="item.deviceNo || item.deviceId"
:value="item.id"
/>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="预计出发时间" prop="estimatedDepartureTime">
<el-date-picker
v-model="formData.estimatedDepartureTime"
type="datetime"
placeholder="请选择预计出发时间"
style="width: 100%"
value-format="YYYY-MM-DD HH:mm:ss"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="预计到达时间" prop="estimatedArrivalTime">
<el-date-picker
v-model="formData.estimatedArrivalTime"
type="datetime"
placeholder="请选择预计到达时间"
style="width: 100%"
value-format="YYYY-MM-DD HH:mm:ss"
/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="起点地址" prop="startLocation">
<el-input v-model="formData.startLocation" placeholder="请输入起点地址" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="目的地地址" prop="endLocation">
<el-input v-model="formData.endLocation" placeholder="请输入目的地地址" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="牛只数量" prop="cattleCount">
<el-input-number
v-model="formData.cattleCount"
:min="1"
:max="9999"
placeholder="请输入牛只数量"
style="width: 100%"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="预估重量(kg)" prop="estimatedWeight">
<el-input-number
v-model="formData.estimatedWeight"
:min="0.01"
:precision="2"
placeholder="请输入预估重量"
style="width: 100%"
/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="检疫证号" prop="quarantineCertNo">
<el-input v-model="formData.quarantineCertNo" placeholder="请输入检疫证号(可选)" />
</el-form-item>
</el-col>
</el-row>
<el-form-item label="备注" prop="remark">
<el-input
v-model="formData.remark"
type="textarea"
:rows="3"
maxlength="500"
show-word-limit
placeholder="请输入备注信息(可选)"
/>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="handleClose">取消</el-button>
<el-button type="primary" :loading="submitLoading" @click="handleSubmit">
提交
</el-button>
</span>
</template>
</el-dialog>
</template>
<script setup>
import { ref, reactive } from 'vue';
import { ElMessage } from 'element-plus';
import { createDelivery, getAvailableServers, getAvailableEartags, getAvailableCollars } from '@/api/shipping.js';
const dialogVisible = ref(false);
const formRef = ref(null);
const submitLoading = ref(false);
const serverList = ref([]);
const eartagList = ref([]);
const collarList = ref([]);
const formData = reactive({
shipper: '',
buyer: '',
plateNumber: '',
driverName: '',
driverPhone: '',
serverId: null,
eartagIds: [],
collarIds: [],
estimatedDepartureTime: '',
estimatedArrivalTime: '',
startLocation: '',
endLocation: '',
cattleCount: 1,
estimatedWeight: null,
quarantineCertNo: '',
remark: '',
});
// 车牌号校验
const validatePlateNumber = (rule, value, callback) => {
const plateReg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z][A-Z0-9]{5}[A-Z0-9挂学警港澳]$/;
if (!value) {
callback(new Error('请输入车牌号'));
} else if (!plateReg.test(value)) {
callback(new Error('车牌号格式不正确'));
} else {
callback();
}
};
// 手机号校验
const validatePhone = (rule, value, callback) => {
const phoneReg = /^1[3-9]\d{9}$/;
if (!value) {
callback(new Error('请输入司机电话'));
} else if (!phoneReg.test(value)) {
callback(new Error('手机号格式不正确'));
} else {
callback();
}
};
// 时间校验
const validateArrivalTime = (rule, value, callback) => {
if (!value) {
callback(new Error('请选择预计到达时间'));
} else if (formData.estimatedDepartureTime && value <= formData.estimatedDepartureTime) {
callback(new Error('预计到达时间必须晚于出发时间'));
} else {
callback();
}
};
const rules = {
shipper: [{ required: true, message: '请输入发货方', trigger: 'blur' }],
buyer: [{ required: true, message: '请输入采购方', trigger: 'blur' }],
plateNumber: [{ required: true, validator: validatePlateNumber, trigger: 'blur' }],
driverName: [{ required: true, message: '请输入司机姓名', trigger: 'blur' }],
driverPhone: [{ required: true, validator: validatePhone, trigger: 'blur' }],
estimatedDepartureTime: [{ required: true, message: '请选择预计出发时间', trigger: 'change' }],
estimatedArrivalTime: [{ required: true, validator: validateArrivalTime, trigger: 'change' }],
startLocation: [{ required: true, message: '请输入起点地址', trigger: 'blur' }],
endLocation: [{ required: true, message: '请输入目的地地址', trigger: 'blur' }],
cattleCount: [{ required: true, message: '请输入牛只数量', trigger: 'blur' }],
estimatedWeight: [{ required: true, message: '请输入预估重量', trigger: 'blur' }],
};
// 打开弹窗
const open = () => {
dialogVisible.value = true;
loadDeviceOptions();
};
// 加载设备选项
const loadDeviceOptions = async () => {
try {
// 加载主机设备
const serverRes = await getAvailableServers({ pageNum: 1, pageSize: 9999 });
if (serverRes.code === 200) {
serverList.value = serverRes.data?.rows || serverRes.data || [];
}
// 加载耳标设备
const eartagRes = await getAvailableEartags({ pageNum: 1, pageSize: 9999 });
if (eartagRes.code === 200) {
eartagList.value = eartagRes.data?.rows || eartagRes.data || [];
}
// 加载项圈设备
const collarRes = await getAvailableCollars({ pageNum: 1, pageSize: 9999 });
if (collarRes.code === 200) {
collarList.value = collarRes.data?.rows || collarRes.data || [];
}
} catch (error) {
console.error('加载设备列表失败', error);
}
};
// 提交表单
const handleSubmit = () => {
formRef.value.validate(async (valid) => {
if (valid) {
submitLoading.value = true;
try {
const res = await createDelivery(formData);
if (res.code === 200) {
ElMessage.success('创建成功');
dialogVisible.value = false;
emit('success');
} else {
ElMessage.error(res.msg || '创建失败');
}
} catch (error) {
ElMessage.error('创建失败,请稍后重试');
} finally {
submitLoading.value = false;
}
}
});
};
// 关闭弹窗
const handleClose = () => {
formRef.value?.resetFields();
dialogVisible.value = false;
};
// 暴露方法给父组件
defineExpose({
open,
});
const emit = defineEmits(['success']);
</script>
<style scoped>
.dialog-footer {
display: flex;
justify-content: flex-end;
}
</style>