Files
delivery_manage_front/src/views/order/outWarehouse/index.vue

857 lines
26 KiB
Vue
Raw Normal View History

2026-02-04 08:47:21 +08:00
<template>
2026-03-19 15:20:48 +08:00
<div class="app-container">
<el-splitter>
<el-splitter-panel size="40%">
<el-form
:model="queryParams"
ref="queryRef"
v-show="showSearch"
label-width="90"
>
<el-row>
<el-col :span="10">
<el-form-item label="单据号" prop="billNoCk">
<el-input
v-model="queryParams.billNoCk"
placeholder="请输入单据号"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
</el-col>
<el-col :span="14">
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery"
>搜索</el-button
>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-col>
</el-row>
<el-row
:gutter="10"
class="mb8"
style="justify-content: flex-end; margin-right: 0"
>
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="plus"
@click="delieryReceipt()"
:disabled="multipleBill"
>生成配送单</el-button
>
</el-col>
<!-- <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar> -->
</el-row>
</el-form>
<el-table
v-loading="loading"
highlight-current-row
:data="billList"
ref="billTable"
@row-dblclick="billClick"
@select="handleBillSelectionChange"
@select-all="handleBillSelectionChange"
>
<el-table-column type="selection" width="55" align="center" />
<el-table-column
label="单据号"
align="center"
prop="billNo"
width="200"
/>
<el-table-column label="库存状态" align="center">
<template #default="scope">
<span>{{ isChukuFun(scope.row.isDelivery) }}</span>
</template>
</el-table-column>
<el-table-column label="理货员" align="center" prop="operatorName" />
<el-table-column
label="出库类型"
align="center"
prop="operationTypeName"
width="150"
/>
<el-table-column
label="出库时间"
align="center"
prop="operationTime"
width="170"
>
<template #default="scope">
<span>{{
parseTime(scope.row.operationTime, "{y}-{m}-{d} {h}:{i}:{s}")
}}</span>
</template>
</el-table-column>
</el-table>
<!-- 分页暂时注释掉 -->
<!-- <pagination
2026-02-04 08:47:21 +08:00
v-show="total>0"
:total="total"
v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/> -->
2026-03-19 15:20:48 +08:00
<!-- <el-pagination background layout="prev, pager, next" :total="total" v-model:page="queryParams.pageNum" @pagination="getList"/> -->
</el-splitter-panel>
<el-splitter-panel :min="200">
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="plus"
@click="delieryReceipt()"
:disabled="multiple"
>生成配送单</el-button
>
</el-col>
</el-row>
<el-table
v-loading="detailLoading"
show-overflow-tooltip
:data="stockList"
ref="detailTable"
@select="handleSelectionChange"
@select-all="handleSelectionChange"
>
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="库存状态" align="center">
<template #default="scope">
<span>{{ isChukuFun(scope.row.bizType) }}</span>
</template>
</el-table-column>
<el-table-column
label="项目号"
align="center"
prop="xmNo"
width="150"
/>
<el-table-column
label="项目描述"
align="center"
prop="xmMs"
width="250"
/>
<el-table-column
label="物料号"
align="center"
prop="wlNo"
width="100"
/>
<el-table-column
label="物料描述"
align="center"
prop="wlMs"
width="250"
/>
<el-table-column
label="供应商名称"
align="center"
prop="gysMc"
width="200"
/>
<el-table-column label="合同单价" align="center" prop="htDj" />
<el-table-column
label="订单编号"
align="center"
prop="sapNo"
width="150"
/>
<el-table-column label="计量单位" align="center" prop="dw" />
<el-table-column
label="实际出库数量"
align="center"
prop="realQty"
width="120"
/>
<el-table-column
label="库位码"
align="center"
prop="pcode"
width="120"
/>
<el-table-column label="托盘码" align="center" prop="trayCode" />
<el-table-column
label="身份码"
align="center"
prop="entityId"
width="200"
/>
<!-- <el-table-column label="出库类型" align="center" prop="operationTypeName" width="150"/> -->
<el-table-column
label="物资类型"
align="center"
prop="wlTypeName"
width="120"
/>
<el-table-column
label="所属仓库"
align="center"
prop="cangkuName"
width="150"
>
<template #default="scope">
<span
>{{ scope.row.parentWarehouseName }}-{{
scope.row.warehouseName
}}</span
>
</template>
</el-table-column>
<!-- <el-table-column label="操作时间" align="center" prop="operationTime" width="200">
2026-02-04 08:47:21 +08:00
<template #default="scope">
2026-02-04 15:31:45 +08:00
<span>{{ parseTime(scope.row.operationTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
2026-02-04 08:47:21 +08:00
</template>
2026-02-04 15:31:45 +08:00
</el-table-column> -->
2026-03-19 15:20:48 +08:00
<!-- <el-table-column label="库龄" align="center" prop="stockAge" /> -->
<el-table-column
label="备注"
align="center"
prop="remark"
width="200"
/>
</el-table>
</el-splitter-panel>
</el-splitter>
<el-dialog title="生成配送单" v-model="dialogPicDetailVisible">
<div class="container">
<div class="billBox">
<span>出库单号</span><span>{{ detailQueryParams.billNoCk }}</span>
</div>
<el-form
:model="delieryData"
ref="form"
:rules="rules"
label-width="100"
>
<el-divider content-position="left">配送信息</el-divider>
<el-row>
<el-col :span="12">
<el-form-item label="起点" prop="originName">
<el-input
v-model="delieryData.originName"
placeholder="请输入起点"
clearable
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="终点" prop="destName">
<el-input
v-model="delieryData.destName"
placeholder="请输入终点"
clearable
/>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="配送人" prop="shipperName">
<el-select
v-model="delieryData.shipperName"
placeholder="请选择配送人"
clearable
>
<el-option
v-for="dict in personList"
:key="dict.userId"
:label="dict.userName"
:value="dict.userName"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="配送人电话" prop="shipperPhone">
<el-input
v-model="delieryData.shipperPhone"
type="tel"
placeholder="请输入配送人电话"
clearable
/>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="收货人" prop="receiverName">
<el-input
v-model="delieryData.receiverName"
placeholder="请输入收货人"
clearable
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="收货人电话" prop="receiverPhone">
<el-input
v-model="delieryData.receiverPhone"
type="tel"
placeholder="请输入收货人电话"
clearable
/>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="接收单位" prop="receiverOrgName">
<el-input
v-model="delieryData.receiverOrgName"
placeholder="请输入接收单位"
clearable
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="配送日期" prop="deliveryDate">
<el-date-picker
v-model="delieryData.deliveryDate"
type="date"
format="YYYY-MM-DD"
value-format="YYYY-MM-DD"
style="width: 100%"
/>
</el-form-item>
</el-col>
</el-row>
<el-divider content-position="left">货物信息</el-divider>
<el-row>
<el-col :span="12">
<el-form-item label="重量" prop="deliveryTon">
<el-input v-model="delieryData.deliveryTon" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="体积" prop="goodsSize">
<el-input v-model="delieryData.goodsSize" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="公里数" prop="totalKm">
<el-input
v-model="delieryData.totalKm"
placeholder="请输入公里数"
clearable
/>
</el-form-item>
</el-col>
<el-col :span="4" :offset="1">
<el-button type="primary" @click="calculateFun(null)"
>计算</el-button
>
</el-col>
</el-row>
<el-divider content-position="left">计算信息</el-divider>
<el-row>
<el-col :span="12">
<el-form-item label="推荐车型" v-for="(item, index) in delieryData.vehicleTypeNameList" :key="index">
<el-select
v-model="item.vehicleTypeId"
placeholder="请选择推荐车型"
@change="changeCarType($event, index)"
>
<el-option
v-for="dict in carTypeList"
:key="dict.id"
:label="dict.name"
:value="dict.id"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="建议费用" prop="suggestFee">
<el-input
v-model="delieryData.suggestFee"
placeholder=""
clearable
disabled
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
2026-02-04 08:47:21 +08:00
<script setup name="outWarehouse">
2026-03-19 15:20:48 +08:00
import {
listBill,
listStock,
calculate,
addDelivery,
} from "@/api/outWarehouse/outWarehouse";
import { listType } from "@/api/document/type";
import { listUser } from "@/api/system/user"; //理货员
2026-02-04 08:47:21 +08:00
// let map = null;
// onMounted(() => {
// AMapLoader.load({
// key: "5617ac0ab71c7044bf96edb81b4efc9a", // 申请好的Web端开发者Key首次调用 load 时必填
// version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
// plugins: [], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
// })
// .then((AMap) => {
// map = new AMap.Map("container", {
// // 设置地图容器id
// viewMode: "3D", // 是否为3D地图模式
// zoom: 11, // 初始化地图级别
// center: [116.397428, 39.90923], // 初始化地图中心点位置
// });
// })
// .catch((e) => {
// console.log(e);
// });
// });
// onUnmounted(() => {
// map?.destroy();
// });
2026-03-19 15:20:48 +08:00
const { proxy } = getCurrentInstance();
const detailLoading = ref(false); //加载列表详情
const showSearch = ref(true);
const total = ref(0); //单据
const personList = ref([]); //理货员下拉数据
const carTypeList = ref([]); //推荐车型下拉数据
const dialogPicDetailVisible = ref(false);
const multiple = ref(true);
const data = reactive({
fileList: [],
form: {},
//配送单提交的数据
delieryData: {
deliveryTon: 0, //重量
goodsSize: 0, //体积
items: [],
vehicleTypeNameList: [{}], //推荐车型列表
},
queryParams: {},
detailQueryParams: {
pageNum: 1,
pageSize: 200,
id: null,
billNoCk: "",
},
rules: {
originName: [
{ required: true, message: "起点不能为空", trigger: "change" },
],
destName: [{ required: true, message: "终点不能为空", trigger: "change" }],
shipperName: [
{ required: true, message: "配送人不能为空", trigger: "change" },
],
shipperPhone: [
{
pattern: /^1[3456789]\d{9}$/,
message: "请输入有效的电话号码",
trigger: "blur",
},
],
receiverName: [
{ required: true, message: "收货人不能为空", trigger: "change" },
],
receiverPhone: [
{ required: true, message: "收货人电话不能为空", trigger: "change" },
{
pattern: /^1[3456789]\d{9}$/,
message: "请输入有效的电话号码",
trigger: "blur",
},
],
deliveryTon: [
{ required: true, message: "重量不能为空", trigger: "change" },
],
goodsSize: [{ required: true, message: "体积不能为空", trigger: "change" }],
totalKm: [{ required: true, message: "公里数不能为空", trigger: "change" }],
suggestFee: [
{ required: true, message: "建议费用不能为空", trigger: "change" },
],
deliveryDate: [
{ required: true, message: "配送日期不能为空", trigger: "change" },
],
},
switchRules: {
toCangku: [
{ required: true, message: "目标仓库不能为空", trigger: "change" },
],
toPcode: [
{ required: true, message: "目标存放位置不能为空", trigger: "change" },
],
},
});
const { queryParams, detailQueryParams, delieryData, rules } = toRefs(data);
//生成配送单弹框
function delieryReceipt() {
dialogPicDetailVisible.value = true;
//理货员下拉数据
listUser().then((response) => {
personList.value = response.rows;
});
//车型下拉数据
listType({ pageNum: 1, pageSize: 1000 }).then((response) => {
// carTypeList.value = response.rows;
});
}
2026-02-04 08:47:21 +08:00
2026-03-19 15:20:48 +08:00
//双击单据,查询明细
function billClick(row) {
stockList.value = row.recordList;
}
function isChukuFun(isChuku) {
// scope.row.isChuku==0?"已入库":(scope.row.isChuku==1?"已出库":"审批中")
return "已出库";
}
2026-02-04 08:47:21 +08:00
2026-03-19 15:20:48 +08:00
const stockList = ref([]); //明细列表
const billList = ref([]); //单据列表
const loading = ref(true);
/** 查询库存单据主列表 */
function getList() {
loading.value = true;
listBill(queryParams.value).then((response) => {
billList.value = response.data;
loading.value = false;
});
}
/** 搜索按钮操作 */
function handleQuery() {
queryParams.value.pageNum = 1;
multipleBill.value = true;
multiple.value = true
stockList.value = []
getList();
}
2026-02-04 08:47:21 +08:00
2026-03-19 15:20:48 +08:00
/** 重置按钮操作 */
function resetQuery() {
proxy.resetForm("queryRef");
handleQuery();
}
2026-02-04 08:47:21 +08:00
2026-03-19 15:20:48 +08:00
const multipleBill = ref(true);
const billTable = ref(null);
const detailTable = ref(null);
// 多选框选中数据
function handleBillSelectionChange(selectionArr) {
if (!multiple.value) {
proxy.$confirm('此操作将删除右侧勾选, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(() => {
detailTable.value.clearSelection();
delieryData.value.deliveryTon = 0;
delieryData.value.goodsSize = 0;
let selection = selectionArr
.flatMap((item) => item.recordList)
if (selection.length > 0) {
for (let i = 0; i < selection.length; i++) {
delieryData.value.deliveryTon +=
Number(selection[i].weightKg) * 1000 * selection[i].realQty;
delieryData.value.goodsSize +=
Number(selection[i].volumeM3) * 1000 * selection[i].realQty;
// selection[i].rkInfoId = selection[i].id
selection[i].rkRecordId = selection[i].id;
}
delieryData.value.items = selection;
// selection.forEach(element => {
// delieryData.value.deliveryTon += Number(element.deliveryTon)
// delieryData.value.goodsSize += Number(element.goodsSize)
// });
} else {
delieryData.value.deliveryTon = 0;
delieryData.value.goodsSize = 0;
delieryData.value.items = [];
}
delieryData.value.deliveryTon = delieryData.value.deliveryTon / 1000000;
delieryData.value.goodsSize = delieryData.value.goodsSize / 1000;
multipleBill.value = !selectionArr.length;
multiple.value = true
console.log(selectionArr);
proxy.$message({
type: 'success',
message: '删除成功!',
})
})
.catch(() => {
billTable.value.clearSelection();
proxy.$message({
type: 'info',
message: '已取消删除',
})
})
} else {
delieryData.value.deliveryTon = 0;
delieryData.value.goodsSize = 0;
let selection = selectionArr
.flatMap((item) => item.recordList)
if (selection.length > 0) {
for (let i = 0; i < selection.length; i++) {
delieryData.value.deliveryTon +=
Number(selection[i].weightKg) * 1000 * selection[i].realQty;
delieryData.value.goodsSize +=
Number(selection[i].volumeM3) * 1000 * selection[i].realQty;
// selection[i].rkInfoId = selection[i].id
selection[i].rkRecordId = selection[i].id;
}
delieryData.value.items = selection;
// selection.forEach(element => {
// delieryData.value.deliveryTon += Number(element.deliveryTon)
// delieryData.value.goodsSize += Number(element.goodsSize)
2026-02-04 08:47:21 +08:00
2026-03-19 15:20:48 +08:00
// });
} else {
delieryData.value.deliveryTon = 0;
delieryData.value.goodsSize = 0;
delieryData.value.items = [];
2026-02-04 08:47:21 +08:00
}
2026-03-19 15:20:48 +08:00
delieryData.value.deliveryTon = delieryData.value.deliveryTon / 1000000;
delieryData.value.goodsSize = delieryData.value.goodsSize / 1000;
multipleBill.value = !selectionArr.length;
multiple.value = true
console.log(selectionArr);
2026-02-04 08:47:21 +08:00
}
}
2026-03-19 15:20:48 +08:00
function handleSelectionChange(selection) {
console.log(selection);
if (!multipleBill.value) {
proxy.$confirm('此操作将删除左侧勾选, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(() => {
billTable.value.clearSelection();
delieryData.value.deliveryTon = 0;
delieryData.value.goodsSize = 0;
if (selection.length > 0) {
for (let i = 0; i < selection.length; i++) {
delieryData.value.deliveryTon +=
Number(selection[i].weightKg) * 1000 * selection[i].realQty;
delieryData.value.goodsSize +=
Number(selection[i].volumeM3) * 1000 * selection[i].realQty;
// selection[i].rkInfoId = selection[i].id
selection[i].rkRecordId = selection[i].id;
}
delieryData.value.items = selection;
// selection.forEach(element => {
// delieryData.value.deliveryTon += Number(element.deliveryTon)
// delieryData.value.goodsSize += Number(element.goodsSize)
// });
} else {
delieryData.value.deliveryTon = 0;
delieryData.value.goodsSize = 0;
delieryData.value.items = [];
}
delieryData.value.deliveryTon = delieryData.value.deliveryTon / 1000000;
delieryData.value.goodsSize = delieryData.value.goodsSize / 1000;
multiple.value = !selection.length;
multipleBill.value = true
console.log(selection);
proxy.$message({
type: 'success',
message: '删除成功!',
})
})
.catch(() => {
detailTable.value.clearSelection();
proxy.$message({
type: 'info',
message: '已取消删除',
})
})
} else {
delieryData.value.deliveryTon = 0;
delieryData.value.goodsSize = 0;
if (selection.length > 0) {
for (let i = 0; i < selection.length; i++) {
delieryData.value.deliveryTon +=
Number(selection[i].weightKg) * 1000 * selection[i].realQty;
delieryData.value.goodsSize +=
Number(selection[i].volumeM3) * 1000 * selection[i].realQty;
// selection[i].rkInfoId = selection[i].id
selection[i].rkRecordId = selection[i].id;
2026-02-04 08:47:21 +08:00
}
2026-03-19 15:20:48 +08:00
delieryData.value.items = selection;
// selection.forEach(element => {
// delieryData.value.deliveryTon += Number(element.deliveryTon)
// delieryData.value.goodsSize += Number(element.goodsSize)
// });
2026-02-04 08:47:21 +08:00
} else {
2026-03-19 15:20:48 +08:00
delieryData.value.deliveryTon = 0;
delieryData.value.goodsSize = 0;
delieryData.value.items = [];
2026-02-04 08:47:21 +08:00
}
2026-03-19 15:20:48 +08:00
delieryData.value.deliveryTon = delieryData.value.deliveryTon / 1000000;
delieryData.value.goodsSize = delieryData.value.goodsSize / 1000;
multiple.value = !selection.length;
multipleBill.value = true
console.log(selection);
}
}
//根据重量、体积、公里数计算车型、费用
function calculateFun(id) {
if (
!delieryData.value.deliveryTon ||
!delieryData.value.goodsSize ||
!delieryData.value.totalKm
) {
proxy.$modal.msgWarning("请输入公里数、重量、体积");
return;
}
let info = {
weightTon: 0,
volumeM3: 0,
distanceKm: 0,
};
let hasVehicle = delieryData.value.vehicleTypeNameList.every(item => item.vehicleTypeId)
if (hasVehicle) {
info.vehicleTypeId = delieryData.value.vehicleTypeNameList.map(item => item.vehicleTypeId).join(',')
}
info.weightTon = delieryData.value.deliveryTon;
info.volumeM3 = delieryData.value.goodsSize;
info.distanceKm = delieryData.value.totalKm;
calculate(info).then((response) => {
// 检查后端是否返回了错误信息
if (response.data.warningMessage) {
proxy.$modal.msgError(response.data.warningMessage);
return;
}
if (response.data.bestPlan.length > 0 && !id) {
delieryData.value.vehicleTypeNameList = response.data.bestPlan;
}
carTypeList.value = response.data.candidates;
delieryData.value.suggestFee = response.data.suggestFee;
delieryData.value.vehicleTypeName = response.data.vehicleTypeName;
console.log(delieryData.value)
});
2026-02-04 08:47:21 +08:00
}
//切换车型
2026-03-19 15:20:48 +08:00
function changeCarType(id, index) {
console.log(id, index)
if (
!delieryData.value.totalKm ||
!delieryData.value.deliveryTon ||
!delieryData.value.goodsSize
) {
proxy.$modal.msgWarning("请输入公里数、重量、体积");
return;
}
calculateFun(id);
2026-02-04 08:47:21 +08:00
}
// 取消按钮
function cancel() {
2026-03-19 15:20:48 +08:00
delieryData.value.originName = null;
delieryData.value.destName = null;
delieryData.value.shipperName = null;
delieryData.value.shipperPhone = null;
delieryData.value.receiverName = null;
delieryData.value.receiverPhone = null;
delieryData.value.receiverOrgName = null;
delieryData.value.deliveryDate = null;
delieryData.value.totalKm = null;
delieryData.value.vehicleTypeNameList = [{}];
delieryData.value.suggestFee = null;
proxy.$refs["form"].resetFields()
dialogPicDetailVisible.value = false;
2026-02-04 08:47:21 +08:00
}
2026-03-19 15:20:48 +08:00
// function reset() {
2026-02-04 08:47:21 +08:00
2026-03-19 15:20:48 +08:00
// }
2026-02-04 08:47:21 +08:00
2026-03-19 15:20:48 +08:00
function submitForm() {
let hasVehicle = delieryData.value.vehicleTypeNameList.every(item => item.vehicleTypeId)
if (!hasVehicle) {
proxy.$modal.msgWarning('请选择配送车型')
return
}
proxy.$refs["form"].validate((valid) => {
// console.log(delieryData.value)
// return
if (valid) {
let obj = JSON.parse(JSON.stringify(delieryData.value))
obj.vehicleTypeName = obj.vehicleTypeNameList.map(item => item.vehicleTypeName).join(',')
obj.vehicleTypeId = obj.vehicleTypeNameList.map(item => item.vehicleTypeId).join(',')
addDelivery(obj).then((response) => {
proxy.$modal.msgSuccess("操作成功");
dialogPicDetailVisible.value = false;
stockList.value = [];
getList();
});
}
});
}
2026-02-04 08:47:21 +08:00
2026-03-19 15:20:48 +08:00
//数据列表
getList();
</script>
2026-02-04 08:47:21 +08:00
<style scoped>
2026-03-19 15:20:48 +08:00
.el-table .warning-row {
--el-table-tr-bg-color: var(--el-color-warning-light-9);
}
.el-table .success-row {
--el-table-tr-bg-color: var(--el-color-success-light-9);
}
.titleBox {
text-align: center;
}
.topBox {
margin-bottom: 10px;
display: flex;
}
.bottomBox {
margin-top: 20px;
}
.oneLineBox {
display: flex;
}
.everyBox {
width: 30%;
}
.examine {
margin-top: 20px;
height: 100px;
background-color: #ededed;
padding: 20px 0 0 20px;
border-radius: 10px;
}
.billBox {
font-weight: bold;
}
</style>
2026-02-04 08:47:21 +08:00