Files
cattleTransportation/pc-cattle-transportation/src/views/userManage/driverDialog.vue
2025-11-21 17:22:20 +08:00

228 lines
7.8 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<el-dialog v-model="data.dialogVisible" :title="data.title" :before-close="handleClose" style="width: 650px; padding-bottom: 20px">
<el-form ref="formDataRef" :model="ruleForm" :rules="rules" label-width="auto">
<el-form-item label="司机姓名" prop="username">
<el-input v-model="ruleForm.username" placeholder="请输入司机姓名" clearable></el-input>
</el-form-item>
<el-form-item label="司机手机号" prop="mobile">
<el-input v-model="ruleForm.mobile" placeholder="请输入司机手机号" clearable></el-input>
</el-form-item>
<el-form-item label="驾驶证照片" prop="driver_license">
<el-upload
:limit="2"
list-type="picture-card"
action="/api/common/upload"
:on-success="(response, file, fileList) => handleAvatarSuccess(response, file, fileList, 'driver_license')"
:on-preview="handlePreview"
:on-remove="(file, fileList) => handleRemove(file, fileList, 'driver_license')"
:before-upload="beforeAvatarUpload"
:file-list="ruleForm.driver_license"
:headers="importHeaders"
:on-exceed="() => handleExceed(2)"
>
<el-icon><Plus /></el-icon>
</el-upload>
</el-form-item>
<el-form-item label="身份证照片" prop="id_card">
<el-upload
:limit="2"
list-type="picture-card"
action="/api/common/upload"
:on-success="(response, file, fileList) => handleAvatarSuccess(response, file, fileList, 'id_card')"
:on-preview="handlePreview"
:on-remove="(file, fileList) => handleRemove(file, fileList, 'id_card')"
:before-upload="beforeAvatarUpload"
:file-list="ruleForm.id_card"
:headers="importHeaders"
:on-exceed="() => handleExceed(2)"
>
<el-icon><Plus /></el-icon>
</el-upload>
</el-form-item>
</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 v-model="data.dialogVisibleImg">
<img w-full :src="data.dialogImageUrl" alt="Preview Image" />
</el-dialog>
</el-dialog>
</template>
<script setup>
import { ref, reactive, onMounted, nextTick } from 'vue';
import { ElMessage } from 'element-plus';
import { Plus } from '@element-plus/icons-vue';
import { driverAdd, driverEdit } from '@/api/userManage.js';
import { useUserStore } from '../../store/user';
const userStore = useUserStore();
const importHeaders = reactive({ Authorization: userStore.$state.token });
const emits = defineEmits();
const formDataRef = ref();
const data = reactive({
dialogVisible: false,
title: '',
saveLoading: false,
dialogVisibleImg: false,
dialogImageUrl: '',
isEdit: false,
});
const ruleForm = reactive({
id: null,
username: '',
mobile: '',
driver_license: [], // 驾驶证照片
id_card: [], // 身份证照片
});
const rules = reactive({
username: [{ required: true, message: '请输入司机姓名', trigger: 'blur' }],
mobile: [
{
required: true,
validator(rule, value, callback) {
if (!value) {
callback(new Error('请输入司机手机号'));
} else if (!/^1[3-9]\d{9}$/.test(value)) {
callback(new Error('请输入正确的手机号'));
} else {
callback();
}
},
trigger: 'blur',
},
],
driver_license: [{ required: true, message: '请上传驾驶证照片', trigger: 'change' }],
id_card: [{ required: true, message: '请上传身份证照片', trigger: 'change' }],
});
const handleAvatarSuccess = (res, file, fileList, type) => {
if (ruleForm.hasOwnProperty(type)) {
let imageUrl = null;
if (res && res.data && res.data.src) {
imageUrl = res.data.src;
} else if (res && res.data && typeof res.data === 'string') {
imageUrl = res.data;
} else if (res && res.url) {
imageUrl = res.url;
} else if (res && typeof res === 'string') {
imageUrl = res;
}
if (imageUrl) {
// 直接更新 fileList
file.url = imageUrl;
ruleForm[type] = fileList;
} else {
console.error('无法解析图片URL:', res);
ElMessage.error('上传失败无法获取图片URL');
}
}
};
const handleRemove = (file, fileList, type) => {
if (ruleForm.hasOwnProperty(type)) {
ruleForm[type] = fileList;
}
};
const beforeAvatarUpload = (file) => {
const isImage = file.type.startsWith('image/');
const isLt10M = file.size / 1024 / 1024 < 10;
if (!isImage) {
ElMessage.error('上传文件只能是图片格式!');
}
if (!isLt10M) {
ElMessage.error('上传图片大小不能超过 10MB!');
}
return isImage && isLt10M;
};
const handleExceed = (number) => {
ElMessage.warning(`最多只能上传${number}张图片!`);
};
const handlePreview = (file) => {
data.dialogImageUrl = file.url;
data.dialogVisibleImg = true;
};
const handleClose = () => {
formDataRef.value?.resetFields();
ruleForm.id = null;
ruleForm.username = '';
ruleForm.mobile = '';
ruleForm.driver_license = [];
ruleForm.id_card = [];
data.dialogVisible = false;
data.isEdit = false;
};
const onClickSave = () => {
formDataRef.value.validate((valid) => {
if (valid) {
data.saveLoading = true;
const params = {
id: ruleForm.id,
username: ruleForm.username,
mobile: ruleForm.mobile,
driverLicense: ruleForm.driver_license.length > 0 ? ruleForm.driver_license.map((item) => item.url).join(',') : '',
idCard: ruleForm.id_card.length > 0 ? ruleForm.id_card.map((item) => item.url).join(',') : '',
};
const apiCall = data.isEdit ? driverEdit(params) : driverAdd(params);
apiCall.then((res) => {
data.saveLoading = false;
if (res.code === 200) {
ElMessage.success(data.isEdit ? '编辑成功' : '新增成功');
handleClose();
emits('success');
} else {
ElMessage.error(res.msg || '操作失败');
}
}).catch((error) => {
data.saveLoading = false;
console.error('保存失败:', error);
ElMessage.error('保存失败,请稍后重试');
});
}
});
};
const onShowDialog = (row = null) => {
data.dialogVisible = true;
data.isEdit = !!row;
data.title = row ? '编辑司机' : '新增司机';
if (row) {
ruleForm.id = row.id;
ruleForm.username = row.username || '';
ruleForm.mobile = row.mobile || '';
ruleForm.driver_license = row.driver_license ? row.driver_license.split(',').map(url => ({ url: url.trim() })) : [];
ruleForm.id_card = row.id_card ? row.id_card.split(',').map(url => ({ url: url.trim() })) : [];
}
};
defineExpose({ onShowDialog });
</script>
<style scoped>
.dialog-footer {
display: flex;
justify-content: flex-end;
}
</style>