<template>
|
<view class="list_box">
|
<CardTitle title="出库" :hideAction="false">
|
<template #action>
|
<wd-button type="icon" icon="scan" color="#0D867F" @click="openScan"></wd-button>
|
</template>
|
</CardTitle>
|
<view class="list_content">
|
<view v-if="outboundList.length === 0" class="empty_tip">
|
<view class="empty_text">暂无出库数据</view>
|
</view>
|
<view v-for="(item, index) in outboundList" :key="index" class="outbound_item">
|
<view class="outbound_item_left">
|
<view class="outbound_item_content">
|
<view class="outbound_item_row">
|
<text class="outbound_item_label">合同号:</text>
|
<text class="outbound_item_value">{{ item.contractNo || "-" }}</text>
|
</view>
|
<view class="outbound_item_row">
|
<text class="outbound_item_label">生产批次号:</text>
|
<text class="outbound_item_value">{{ item.batchNo || "-" }}</text>
|
</view>
|
<view class="outbound_item_row">
|
<text class="outbound_item_label">规格型号:</text>
|
<text class="outbound_item_value">{{ item.model || "-" }}</text>
|
</view>
|
<view class="outbound_item_row">
|
<text class="outbound_item_label">重量:</text>
|
<text class="outbound_item_value">{{ item.weight || "-" }} kg</text>
|
</view>
|
<view class="outbound_item_row">
|
<text class="outbound_item_label">厂家:</text>
|
<text class="outbound_item_value">{{ item.clienteleName || "-" }}</text>
|
</view>
|
<view class="outbound_item_row">
|
<text class="outbound_item_label">段长:</text>
|
<text class="outbound_item_value">{{ item.actuallyLength || "-" }} M</text>
|
</view>
|
<view class="outbound_item_row">
|
<text class="outbound_item_label">生产日期:</text>
|
<text class="outbound_item_value">{{ item.productionDate || "-" }}</text>
|
</view>
|
</view>
|
</view>
|
<view class="outbound_item_action">
|
<wd-button
|
type="icon"
|
icon="delete"
|
size="small"
|
custom-class="delete-btn"
|
@click.stop="removeOutboundItem(index)"
|
></wd-button>
|
</view>
|
</view>
|
</view>
|
<view v-if="outboundList.length > 0" class="outbound_footer">
|
<wd-button block @click="handleOutbound">
|
<text class="text-[#fff]">出库</text>
|
</wd-button>
|
</view>
|
<Scan ref="scanRef" emitName="scanOutbound" />
|
<wd-toast />
|
</view>
|
</template>
|
|
<script setup lang="ts">
|
import CardTitle from "@/components/card-title/index.vue";
|
import Scan from "@/components/scan/index.vue";
|
import { useToast } from "wot-design-uni";
|
import { dayjs } from "wot-design-uni";
|
import OutboundApi from "@/api/product/outbound";
|
|
const scanRef = ref();
|
const toast = useToast();
|
const outboundList = ref<any[]>([]);
|
const projectId = ref<string | number>("");
|
|
// 格式化时间
|
const formatTime = (date: Date) => {
|
return dayjs(date).format("YYYY-MM-DD HH:mm:ss");
|
};
|
|
// 扫码回调
|
const getScanCode = async (code: any) => {
|
try {
|
// 如果 code 是对象且有 code 字段,使用 code.code;否则直接使用 code
|
let scanCode = code.code || code;
|
|
// 如果 scanCode 是对象,尝试获取其 code 字段
|
if (typeof scanCode === "object" && scanCode.code) {
|
scanCode = scanCode.code;
|
}
|
|
// 如果 scanCode 是字符串,直接使用;如果是对象,转为字符串
|
if (typeof scanCode !== "string") {
|
scanCode = JSON.stringify(scanCode);
|
}
|
|
if (!scanCode) {
|
toast.error("扫码内容为空");
|
return;
|
}
|
|
// 解析扫码数据,现在二维码只包含id
|
let scanData;
|
try {
|
scanData = JSON.parse(scanCode);
|
} catch (e) {
|
toast.error("二维码格式错误");
|
return;
|
}
|
|
const outPutId = scanData.id;
|
|
if (!outPutId) {
|
toast.error("二维码格式错误,缺少id信息");
|
return;
|
}
|
|
// 检查是否已存在(根据id判断)
|
const exists = outboundList.value.some((item) => {
|
const itemId = item.id;
|
return itemId && itemId === outPutId && itemId !== "-";
|
});
|
|
if (exists) {
|
toast.error("该条码已存在,请勿重复扫码");
|
return;
|
}
|
|
// 调用接口获取绞线详细信息
|
const { data: tagData } = await OutboundApi.getTagByIdJx({
|
outPutId: outPutId,
|
});
|
|
// 提取数据字段(根据接口返回的数据结构)
|
const parsedData = {
|
id: tagData?.id || outPutId,
|
contractNo: tagData?.contractno || tagData?.contractNo || "-",
|
batchNo: tagData?.systemno || tagData?.systemNo || tagData?.batchNo || "-",
|
model: tagData?.model || "-",
|
weight: tagData?.actuallyweight || tagData?.actuallyWeight || tagData?.weight || "-",
|
clienteleName: tagData?.clientelename || tagData?.clienteleName || "-",
|
actuallyLength: tagData?.actuallylength || tagData?.actuallyLength || "-",
|
productionDate: tagData?.producttime || tagData?.productionDate || "-",
|
projectId: tagData?.projectid || tagData?.projectId || projectId.value || "",
|
// 保留原始数据
|
rawData: tagData,
|
scanCode: scanCode,
|
};
|
|
// 如果接口返回的数据中有 projectId,保存它
|
if (parsedData.projectId && !projectId.value) {
|
projectId.value = parsedData.projectId;
|
}
|
|
// 添加到列表
|
const newItem = {
|
...parsedData,
|
scanTime: formatTime(new Date()),
|
};
|
|
outboundList.value.push(newItem);
|
toast.success("扫码成功");
|
} catch (error: any) {
|
console.error("扫码处理失败:", error);
|
toast.error(error.msg || "二维码异常,请更换二维码!");
|
}
|
};
|
|
// 触发扫码
|
const openScan = () => {
|
scanRef.value.triggerScan();
|
};
|
|
// 删除项
|
const removeOutboundItem = (index: number) => {
|
const item = outboundList.value[index];
|
const itemName = item.contractNo || item.batchNo || `第${index + 1}项`;
|
|
uni.showModal({
|
title: "确认删除",
|
content: `确定要删除"${itemName}"吗?`,
|
confirmText: "删除",
|
cancelText: "取消",
|
confirmColor: "#ff4444",
|
success: (res) => {
|
if (res.confirm) {
|
outboundList.value.splice(index, 1);
|
toast.success("删除成功");
|
}
|
},
|
});
|
};
|
|
// 处理出库
|
const handleOutbound = async () => {
|
if (outboundList.value.length === 0) {
|
toast.error("暂无出库数据");
|
return;
|
}
|
|
// 构建请求数据
|
const requestData = outboundList.value.map((item) => ({
|
outPutId: item.id,
|
projectId: item.projectId,
|
}));
|
|
try {
|
uni.showLoading({
|
title: "出库中...",
|
mask: true,
|
});
|
console.log("requestData", requestData);
|
const { code, msg } = await OutboundApi.finishedOutbound(requestData);
|
|
uni.hideLoading();
|
|
if (code === 200) {
|
toast.success("出库成功");
|
// 清空列表
|
outboundList.value = [];
|
} else {
|
toast.error(msg || "出库失败");
|
}
|
} catch (error: any) {
|
uni.hideLoading();
|
console.error("出库失败:", error);
|
}
|
};
|
|
// 确保先移除再添加监听
|
const setupScanListener = () => {
|
uni.$off("scanOutbound", getScanCode); // 先移除旧的
|
uni.$on("scanOutbound", getScanCode); // 再添加新的
|
};
|
|
onMounted(() => {
|
setupScanListener();
|
});
|
|
onUnmounted(() => {
|
uni.$off("scanOutbound", getScanCode);
|
});
|
</script>
|
|
<style lang="scss" scoped>
|
.list_box {
|
height: calc(100vh - 100px);
|
background: #f3f9f8;
|
display: flex;
|
flex-direction: column;
|
}
|
|
.list_content {
|
flex: 1;
|
overflow-y: auto;
|
padding-bottom: 120rpx;
|
}
|
|
.empty_tip {
|
display: flex;
|
flex-direction: column;
|
align-items: center;
|
justify-content: center;
|
padding: 100rpx 0;
|
color: #999;
|
|
.empty_text {
|
font-size: 32rpx;
|
margin-bottom: 20rpx;
|
}
|
}
|
|
.outbound_item {
|
display: flex;
|
align-items: center;
|
justify-content: space-between;
|
padding: 30rpx;
|
margin: 20rpx;
|
background: #fff;
|
border-radius: 16rpx;
|
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
|
|
.outbound_item_left {
|
display: flex;
|
align-items: center;
|
flex: 1;
|
}
|
|
.outbound_item_content {
|
flex: 1;
|
}
|
|
.outbound_item_row {
|
display: flex;
|
align-items: center;
|
margin-bottom: 12rpx;
|
font-size: 28rpx;
|
|
&:last-child {
|
margin-bottom: 0;
|
}
|
}
|
|
.outbound_item_label {
|
color: #666;
|
min-width: 140rpx;
|
flex-shrink: 0;
|
}
|
|
.outbound_item_value {
|
color: #333;
|
flex: 1;
|
word-break: break-all;
|
}
|
|
.outbound_item_action {
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
margin-left: 20rpx;
|
flex-shrink: 0;
|
}
|
}
|
|
:deep(.delete-btn) {
|
.wd-button__content {
|
color: #ff4444 !important;
|
}
|
|
&:active {
|
opacity: 0.7;
|
}
|
}
|
|
:deep(.wd-button__content) {
|
color: #0d867f;
|
}
|
|
.outbound_footer {
|
position: fixed;
|
bottom: 0;
|
left: 0;
|
right: 0;
|
padding: 20rpx 30rpx;
|
padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
|
z-index: 100;
|
}
|
</style>
|