<template>
|
<div class="app-container">
|
<div class="search_form">
|
<el-form :model="searchForm" :inline="true">
|
<el-form-item label="销售订单号:">
|
<el-input v-model="searchForm.salesContractNo" placeholder="请输入" clearable prefix-icon="Search" style="width: 200px"
|
@change="handleQuery" />
|
</el-form-item>
|
<el-form-item label="车牌号:">
|
<el-input v-model="searchForm.shippingCarNumber" placeholder="请输入" clearable prefix-icon="Search" style="width: 200px"
|
@change="handleQuery" />
|
</el-form-item>
|
<el-form-item label="快递单号:">
|
<el-input v-model="searchForm.expressNumber" placeholder="请输入" clearable prefix-icon="Search" style="width: 200px"
|
@change="handleQuery" />
|
</el-form-item>
|
<el-form-item>
|
<el-button type="primary" @click="handleQuery"> 搜索 </el-button>
|
</el-form-item>
|
</el-form>
|
</div>
|
<div class="table_list">
|
<div class="actions">
|
<div></div>
|
<div>
|
<el-button @click="handleOut">导出</el-button>
|
<el-button type="danger" plain @click="handleDelete">删除</el-button>
|
</div>
|
</div>
|
<el-table :data="tableData" border v-loading="tableLoading" @selection-change="handleSelectionChange"
|
:row-key="(row) => row.id" style="width: 100%" height="calc(100vh - 21.5em)">
|
<el-table-column align="center" type="selection" width="55" />
|
<el-table-column align="center" label="序号" type="index" width="60" />
|
<el-table-column label="销售订单" prop="salesContractNo" show-overflow-tooltip />
|
<el-table-column label="客户名称" prop="customerName" show-overflow-tooltip />
|
<el-table-column label="发货时间" prop="shippingDate" show-overflow-tooltip />
|
<el-table-column label="发货车牌号" prop="shippingCarNumber" show-overflow-tooltip />
|
<el-table-column label="快递公司" prop="expressCompany" show-overflow-tooltip />
|
<el-table-column label="快递单号" prop="expressNumber" show-overflow-tooltip />
|
<el-table-column fixed="right" label="操作" width="150" align="center">
|
<template #default="scope">
|
<el-button link type="primary" size="small" @click="openForm('edit', scope.row)">编辑</el-button>
|
<el-button link type="danger" size="small" @click="handleDeleteSingle(scope.row)">删除</el-button>
|
</template>
|
</el-table-column>
|
</el-table>
|
<pagination v-show="total > 0" :total="total" layout="total, sizes, prev, pager, next, jumper"
|
:page="page.current" :limit="page.size" @pagination="paginationChange" />
|
</div>
|
<el-dialog v-model="dialogFormVisible" :title="operationType === 'add' ? '新增发货台账' : '编辑发货台账'" width="40%"
|
@close="closeDia">
|
<el-form :model="form" label-width="120px" label-position="top" :rules="rules" ref="formRef">
|
<el-row :gutter="30">
|
<el-col :span="24">
|
<el-form-item label="发货类型:" prop="type">
|
<el-select
|
v-model="form.type"
|
placeholder="请选择发货类型"
|
style="width: 100%"
|
@change="handleShippingTypeChange"
|
>
|
<el-option label="货车" value="货车" />
|
<el-option label="快递" value="快递" />
|
</el-select>
|
</el-form-item>
|
</el-col>
|
</el-row>
|
<el-row :gutter="30">
|
<el-col :span="24">
|
<el-form-item label="发货日期:" prop="shippingDate">
|
<el-date-picker
|
style="width: 100%"
|
v-model="form.shippingDate"
|
value-format="YYYY-MM-DD"
|
format="YYYY-MM-DD"
|
type="date"
|
placeholder="请选择发货日期"
|
clearable
|
/>
|
</el-form-item>
|
</el-col>
|
</el-row>
|
<el-row :gutter="30">
|
<el-col :span="24" v-if="form.type === '货车'">
|
<el-form-item label="发货车牌号:" prop="shippingCarNumber">
|
<el-input
|
v-model="form.shippingCarNumber"
|
placeholder="请输入发货车牌号"
|
clearable
|
/>
|
</el-form-item>
|
</el-col>
|
<el-col :span="24" v-else>
|
<el-form-item label="快递公司:" prop="expressCompany">
|
<el-input
|
v-model="form.expressCompany"
|
placeholder="请输入快递公司"
|
clearable
|
/>
|
</el-form-item>
|
</el-col>
|
</el-row>
|
<el-row :gutter="30" v-if="form.type === '快递'">
|
<el-col :span="24">
|
<el-form-item label="快递单号:" prop="expressNumber">
|
<el-input
|
v-model="form.expressNumber"
|
placeholder="请输入快递单号"
|
clearable
|
/>
|
</el-form-item>
|
</el-col>
|
</el-row>
|
<el-row :gutter="30">
|
<el-col :span="24">
|
<el-form-item label="发货图片:">
|
<el-upload
|
v-model:file-list="deliveryFileList"
|
:action="upload.url"
|
multiple
|
ref="deliveryFileUpload"
|
auto-upload
|
:headers="upload.headers"
|
:data="{ type: 9 }"
|
:before-upload="handleDeliveryBeforeUpload"
|
:on-error="handleDeliveryUploadError"
|
:on-success="handleDeliveryUploadSuccess"
|
:on-remove="handleDeliveryRemove"
|
list-type="picture-card"
|
:limit="9"
|
accept="image/png,image/jpeg,image/jpg"
|
>
|
<el-icon class="avatar-uploader-icon"><Plus /></el-icon>
|
<template #tip>
|
<div class="el-upload__tip">
|
支持 jpg、jpeg、png 格式,最多上传 9 张,单张大小不超过 10MB
|
</div>
|
</template>
|
</el-upload>
|
</el-form-item>
|
</el-col>
|
</el-row>
|
</el-form>
|
<template #footer>
|
<div class="dialog-footer">
|
<el-button type="primary" @click="submitForm">确认</el-button>
|
<el-button @click="closeDia">取消</el-button>
|
</div>
|
</template>
|
</el-dialog>
|
</div>
|
</template>
|
|
<script setup>
|
import pagination from "@/components/PIMTable/Pagination.vue";
|
import { onMounted, ref, reactive, toRefs, getCurrentInstance } from "vue";
|
import { ElMessageBox } from "element-plus";
|
import { Plus } from "@element-plus/icons-vue";
|
import { getToken } from "@/utils/auth";
|
import { getCurrentDate } from "@/utils/index.js";
|
import {
|
deliveryLedgerListPage,
|
addOrUpdateDeliveryLedger,
|
delDeliveryLedger,
|
} from "@/api/salesManagement/deliveryLedger.js";
|
import { delLedgerFile } from "@/api/salesManagement/salesLedger.js";
|
|
|
const { proxy } = getCurrentInstance();
|
const tableData = ref([]);
|
const selectedRows = ref([]);
|
const tableLoading = ref(false);
|
const salesOrderOptions = ref([]);
|
const page = reactive({
|
current: 1,
|
size: 100,
|
});
|
const total = ref(0);
|
const deliveryFileList = ref([]);
|
const javaApi = proxy.javaApi;
|
|
// 上传配置
|
const upload = reactive({
|
// 上传的地址
|
url: import.meta.env.VITE_APP_BASE_API + "/file/upload",
|
// 设置上传的请求头部
|
headers: { Authorization: "Bearer " + getToken() },
|
});
|
|
// 用户信息表单弹框数据
|
const operationType = ref("");
|
const dialogFormVisible = ref(false);
|
const data = reactive({
|
searchForm: {
|
salesContractNo: "", // 销售订单号
|
shippingCarNumber: "", // 车牌号
|
expressNumber: "", // 快递单号
|
},
|
form: {
|
id: null,
|
salesContractNo: "",
|
customerName: "",
|
type: "货车", // 货车, 快递
|
shippingDate: "",
|
shippingCarNumber: "",
|
expressCompany: "",
|
expressNumber: "", // 快递单号
|
},
|
rules: {
|
salesContractNo: [{ required: true, message: "请选择销售订单", trigger: "change" }],
|
customerName: [{ required: true, message: "请输入客户名称", trigger: "blur" }],
|
type: [
|
{ required: true, message: "请选择发货类型", trigger: "change" }
|
],
|
shippingDate: [{ required: true, message: "请选择发货时间", trigger: "change" }],
|
shippingCarNumber: [
|
{ validator: (_, value, callback) => validateShippingCarNumber(value, callback), trigger: "blur" }
|
],
|
expressCompany: [
|
{ validator: (_, value, callback) => validateExpressCompany(value, callback), trigger: "blur" }
|
],
|
},
|
});
|
const { form, rules } = toRefs(data);
|
const { searchForm } = toRefs(data);
|
|
|
|
// 查询列表
|
const handleQuery = () => {
|
page.current = 1;
|
getList();
|
};
|
|
const paginationChange = (obj) => {
|
page.current = obj.page;
|
page.size = obj.limit;
|
getList();
|
};
|
|
const getList = () => {
|
tableLoading.value = true;
|
deliveryLedgerListPage({ ...searchForm.value, ...page })
|
.then((res) => {
|
tableLoading.value = false;
|
tableData.value = res.data.records || [];
|
total.value = res.data.total || 0;
|
})
|
.catch(() => {
|
tableLoading.value = false;
|
});
|
};
|
|
// 销售订单变化时自动填充客户名称
|
const handleSalesOrderChange = (value) => {
|
const selectedOrder = salesOrderOptions.value.find(item => item.salesContractNo === value);
|
if (selectedOrder) {
|
form.value.customerName = selectedOrder.customerName;
|
}
|
};
|
|
// 表格选择数据
|
const handleSelectionChange = (selection) => {
|
selectedRows.value = selection;
|
};
|
|
// 打开弹框
|
const openForm = async (type, row) => {
|
operationType.value = type;
|
const baseUrl = import.meta.env.VITE_APP_BASE_API;
|
|
if (type === 'edit' && row) {
|
form.value = {
|
id: row.id ?? null,
|
salesContractNo: row.salesContractNo ?? "",
|
customerName: row.customerName ?? "",
|
type: row.type || "货车",
|
shippingDate: row.shippingDate || getCurrentDate(),
|
shippingCarNumber: row.shippingCarNumber ?? "",
|
expressCompany: row.expressCompany ?? "",
|
expressNumber: row.expressNumber ?? "",
|
};
|
// 如果有图片,将 commonFileList 转换为文件列表格式
|
if (row.commonFileList && Array.isArray(row.commonFileList) && row.commonFileList.length > 0) {
|
deliveryFileList.value = row.commonFileList.map((file, index) => {
|
// 处理 URL:将 Windows 路径转换为可访问的 URL
|
let fileUrl = file.url || '';
|
console.log('原始 URL:', fileUrl);
|
|
// 如果 URL 是 Windows 路径格式(包含反斜杠),需要转换
|
if (fileUrl && fileUrl.indexOf('\\') > -1) {
|
// 查找 uploads 关键字的位置,从那里开始提取相对路径
|
const uploadsIndex = fileUrl.toLowerCase().indexOf('uploads');
|
if (uploadsIndex > -1) {
|
// 从 uploads 开始提取路径,并将反斜杠替换为正斜杠
|
const relativePath = fileUrl.substring(uploadsIndex).replace(/\\/g, '/');
|
fileUrl = '/' + relativePath;
|
console.log('转换后的相对路径:', fileUrl);
|
} else {
|
// 如果没有找到 uploads,提取最后一个目录和文件名
|
const parts = fileUrl.split('\\');
|
const fileName = parts[parts.length - 1];
|
fileUrl = '/uploads/' + fileName;
|
console.log('未找到 uploads,使用文件名:', fileUrl);
|
}
|
}
|
|
// 确保所有非 http 开头的 URL 都拼接 baseUrl
|
if (fileUrl && !fileUrl.startsWith('http')) {
|
// 确保路径以 / 开头
|
if (!fileUrl.startsWith('/')) {
|
fileUrl = '/' + fileUrl;
|
}
|
// 拼接 baseUrl
|
fileUrl = javaApi + fileUrl;
|
console.log('最终拼接的 URL:', fileUrl);
|
}
|
|
return {
|
uid: file.id || Date.now() + index,
|
name: file.name || `image_${index + 1}.jpg`,
|
url: fileUrl,
|
status: 'success',
|
response: {
|
code: 200,
|
data: {
|
tempId: file.id,
|
url: fileUrl
|
}
|
},
|
tempId: file.id // 保存文件ID,用于提交时使用
|
};
|
});
|
} else {
|
deliveryFileList.value = [];
|
}
|
} else {
|
form.value = {
|
id: null,
|
salesContractNo: "",
|
customerName: "",
|
type: "货车",
|
shippingDate: getCurrentDate(),
|
shippingCarNumber: "",
|
expressCompany: "",
|
expressNumber: "",
|
};
|
deliveryFileList.value = [];
|
}
|
|
dialogFormVisible.value = true;
|
};
|
|
// 提交表单
|
const submitForm = () => {
|
proxy.$refs["formRef"].validate((valid) => {
|
if (valid) {
|
let tempFileIds = [];
|
if (deliveryFileList.value !== null && deliveryFileList.value.length > 0) {
|
tempFileIds = deliveryFileList.value.map((item) => item.tempId);
|
}
|
const payload = {
|
id: form.value.id,
|
type: form.value.type,
|
shippingDate: form.value.shippingDate,
|
shippingCarNumber: form.value.type === "货车" ? form.value.shippingCarNumber : "",
|
expressCompany: form.value.type === "快递" ? form.value.expressCompany : "",
|
expressNumber: form.value.type === "快递" ? form.value.expressNumber : "",
|
tempFileIds: tempFileIds,
|
};
|
addOrUpdateDeliveryLedger(payload).then((res) => {
|
proxy.$modal.msgSuccess("操作成功");
|
closeDia();
|
getList();
|
});
|
}
|
});
|
};
|
|
// 关闭弹框
|
const closeDia = () => {
|
proxy.resetForm("formRef");
|
deliveryFileList.value = []; // 清空文件列表
|
dialogFormVisible.value = false;
|
};
|
|
// 导出
|
const handleOut = () => {
|
ElMessageBox.confirm("选中的内容将被导出,是否确认导出?", "导出", {
|
confirmButtonText: "确认",
|
cancelButtonText: "取消",
|
type: "warning",
|
})
|
.then(() => {
|
proxy.download("/shippingInfo/export", {}, "发货台账.xlsx");
|
})
|
.catch(() => {
|
proxy.$modal.msg("已取消");
|
});
|
};
|
|
// 批量删除
|
const handleDelete = () => {
|
let ids = [];
|
if (selectedRows.value.length > 0) {
|
ids = selectedRows.value.map((item) => item.id);
|
} else {
|
proxy.$modal.msgWarning("请选择数据");
|
return;
|
}
|
ElMessageBox.confirm("选中的内容将被删除,是否确认删除?", "删除", {
|
confirmButtonText: "确认",
|
cancelButtonText: "取消",
|
type: "warning",
|
})
|
.then(() => {
|
delDeliveryLedger(ids).then((res) => {
|
proxy.$modal.msgSuccess("删除成功");
|
getList();
|
});
|
})
|
.catch(() => {
|
proxy.$modal.msg("已取消");
|
});
|
};
|
|
// 单个删除
|
const handleDeleteSingle = (row) => {
|
ElMessageBox.confirm("此操作将删除该记录,是否确认?", "删除", {
|
confirmButtonText: "确认",
|
cancelButtonText: "取消",
|
type: "warning",
|
})
|
.then(() => {
|
delDeliveryLedger([row.id]).then((res) => {
|
proxy.$modal.msgSuccess("删除成功");
|
getList();
|
});
|
})
|
.catch(() => {
|
proxy.$modal.msg("已取消");
|
});
|
};
|
|
// 发货类型校验:货车时要求车牌,快递时要求快递公司
|
const validateShippingCarNumber = (value, callback) => {
|
if (form.value.type === "货车") {
|
if (!value) return callback(new Error("请输入发货车牌号"));
|
}
|
callback();
|
};
|
const validateExpressCompany = (value, callback) => {
|
if (form.value.type === "快递") {
|
if (!value) return callback(new Error("请输入快递公司"));
|
}
|
callback();
|
};
|
|
// 发货图片上传前校检
|
function handleDeliveryBeforeUpload(file) {
|
// 校检文件类型
|
const isImage = file.type === 'image/png' || file.type === 'image/jpeg' || file.type === 'image/jpg';
|
if (!isImage) {
|
proxy.$modal.msgError("只能上传 jpg、jpeg、png 格式的图片!");
|
return false;
|
}
|
// 校检文件大小
|
const isLt10M = file.size / 1024 / 1024 < 10;
|
if (!isLt10M) {
|
proxy.$modal.msgError("上传图片大小不能超过 10MB!");
|
return false;
|
}
|
proxy.$modal.loading("正在上传图片,请稍候...");
|
return true;
|
}
|
// 发货图片上传失败
|
function handleDeliveryUploadError(err) {
|
proxy.$modal.msgError("上传图片失败");
|
proxy.$modal.closeLoading();
|
}
|
// 发货图片上传成功回调
|
function handleDeliveryUploadSuccess(res, file, uploadFiles) {
|
proxy.$modal.closeLoading();
|
if (res.code === 200) {
|
file.tempId = res.data.tempId;
|
proxy.$modal.msgSuccess("上传成功");
|
} else {
|
proxy.$modal.msgError(res.msg);
|
proxy.$refs.deliveryFileUpload.handleRemove(file);
|
}
|
}
|
// 移除发货图片
|
function handleDeliveryRemove(file) {
|
console.log('file--', file)
|
// 如果是编辑模式且文件有 id,需要调用接口删除
|
if (operationType.value === "edit") {
|
let ids = [];
|
ids.push(file.uid);
|
delLedgerFile(ids).then((res) => {
|
proxy.$modal.msgSuccess("删除成功");
|
// 从文件列表中移除
|
const index = deliveryFileList.value.findIndex(item => item.uid === file.uid);
|
if (index > -1) {
|
deliveryFileList.value.splice(index, 1);
|
}
|
}).catch(() => {
|
proxy.$modal.msgError("删除失败");
|
});
|
} else {
|
// 新增模式或没有 id 的文件,直接从列表中移除
|
const index = deliveryFileList.value.findIndex(item => item.uid === file.uid);
|
if (index > -1) {
|
deliveryFileList.value.splice(index, 1);
|
}
|
}
|
}
|
|
// 发货类型切换时清空对应字段
|
const handleShippingTypeChange = (val) => {
|
if (val === "货车") {
|
form.value.expressCompany = "";
|
form.value.expressNumber = "";
|
} else {
|
form.value.shippingCarNumber = "";
|
}
|
};
|
|
onMounted(() => {
|
getList();
|
});
|
</script>
|
|
<style scoped lang="scss">
|
.table_list {
|
margin-top: unset;
|
}
|
|
.actions {
|
display: flex;
|
justify-content: space-between;
|
margin-bottom: 10px;
|
}
|
|
// 隐藏图片上传组件的预览按钮(放大镜)
|
:deep(.el-upload-list--picture-card .el-upload-list__item-actions) {
|
.el-upload-list__item-preview {
|
display: none;
|
}
|
}
|
</style>
|