Files
klp-mono/apps/hand-factory/pages/easycode/easycode.vue
2025-11-11 09:40:40 +08:00

685 lines
19 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>
<view class="container">
<!-- 标题区域 -->
<view class="page-title">操作类型选择</view>
<!-- 操作类型按钮区域 -->
<view class="btn-grid">
<button v-for='item in types' :key="item.dictValue" @click="handleScan(item.dictValue)" class="type-btn">
{{ item.dictLabel }}
</button>
<button class="type-btn" style="background-color: orange;" @click="handleTranfer">移库</button>
<button class="type-btn" style="background-color: greenyellow;" @click="handleShip">发货</button>
</view>
<uni-popup ref="tranferPopup" type="bottom">
<view style="background-color: white;">
<view class="info-card" v-if="form.coilId">
<view class="card-title">
<text class="title-dot"></text>
<text class="title-text">原钢卷信息</text>
<view class="more-btn" @click.stop="showBomDialog"
v-if="coilDetail.bomItemList && coilDetail.bomItemList.length > 0">
<text class="icon-more"></text>
<text class="more-text">参数</text>
</view>
</view>
<view class="info-grid">
<view class="info-item">
<text class="item-label">入场钢卷号</text>
<text class="item-value">{{ coilDetail.enterCoilNo || '-' }}</text>
</view>
<view class="info-item">
<text class="item-label">当前钢卷号</text>
<text class="item-value">{{ coilDetail.currentCoilNo || '-' }}</text>
</view>
<view class="info-item">
<text class="item-label">当前库区</text>
<text class="item-value">{{ coilDetail.actualWarehouseName }}</text>
</view>
</view>
</view>
<view class="form-card" v-if="form.coilId">
<view class="form-item form-item-optional">
<text class="form-label-optional">真实库区</text>
<klp-warehouse-picker v-model="form.actualWarehouseId" :disabled="coilDetail.dataType === 0"
placeholder="请选择目标库区" ware-type="actual" />
</view>
<view class="action-buttons">
<button class="btn btn-secondary" @click="handleReScan">重新扫码</button>
<button v-if="coilDetail.dataType === 1" class="btn btn-primary" @click="handleConfirm" :disabled="loading">
{{ loading ? '提交中...' : '保存' }}
</button>
</view>
</view>
</view>
</uni-popup>
<!-- 退出登录按钮固定在底部 -->
<view class="logout-container">
<button @click='handleLogout' class="logout-btn">
退出登录
</button>
</view>
</view>
</template>
<script>
import {
getDicts
} from '@/api/system/dict/data.js'
import {
getGenerateRecord
} from '@/api/wms/code.js'
import {
getMaterialCoil,
updateMaterialCoilSimple
} from '@/api/wms/coil.js'
import {
addPendingAction
} from '@/api/wms/pendingAction.js'
export default {
data() {
return {
types: [],
loading: false,
coilDetail: {},
form: {}
}
},
methods: {
handleLogout() {
this.$modal.confirm('确定注销并退出系统吗?').then(() => {
this.$store.dispatch('LogOut').then(() => {}).finally(() => {
this.$tab.reLaunch('/pages/login')
})
})
},
// 扫码并创建待操作
handleScan(actionType) {
uni.scanCode({
success: async (res) => {
console.log('=== 开始扫码流程 ===');
console.log('扫码结果:', res.result);
console.log('操作类型:', actionType);
uni.showLoading({
title: '处理中...'
});
try {
const qrcodeId = res.result;
// 1. 通过二维码ID获取二维码详情
console.log('1. 获取二维码详情ID:', qrcodeId);
const qrcodeRes = await getGenerateRecord(qrcodeId);
console.log('二维码响应:', qrcodeRes);
if (qrcodeRes.code !== 200) {
throw new Error('未找到二维码记录');
}
// 2. 解析二维码的content获取coil_id
const qrcodeRecord = qrcodeRes.data;
console.log('2. 二维码记录:', qrcodeRecord);
// 检查二维码状态0=失效1=有效)
if (qrcodeRecord.status === 0) {
uni.hideLoading();
uni.showModal({
title: '提示',
content: '该二维码已失效,无法创建待操作任务',
showCancel: false
});
return;
}
const content = JSON.parse(qrcodeRecord.content);
console.log('解析后的内容:', content);
// 优先使用current_coil_id当前有效的钢卷ID如果没有则使用coil_id兼容旧数据
let coilId = content.current_coil_id && content.current_coil_id !== 'null' ? content
.current_coil_id : null;
if (!coilId) {
coilId = content.coil_id && content.coil_id !== 'null' ? content.coil_id : null;
}
console.log('提取钢卷ID - current_coil_id:', content.current_coil_id, 'coil_id:', content.coil_id,
'最终使用:', coilId);
if (!coilId) {
throw new Error('二维码中未包含有效的钢卷ID');
}
// 3. 直接通过钢卷ID获取钢卷详情
console.log('3. 获取钢卷详情钢卷ID:', coilId);
const coilRes = await getMaterialCoil(coilId);
console.log('钢卷详情响应:', coilRes);
if (coilRes.code !== 200) {
throw new Error(coilRes.msg || '查询钢卷信息失败');
}
if (!coilRes.data) {
throw new Error('未找到钢卷信息');
}
const coilData = coilRes.data;
console.log('4. 钢卷数据:', coilData);
// 4. 创建待操作记录
const pendingData = {
coilId: coilData.coilId,
currentCoilNo: coilData.currentCoilNo,
actionType: parseInt(actionType),
actionStatus: 0, // 待处理
sourceType: 'scan', // 扫码来源
scanTime: new Date().toISOString(),
scanDevice: this.getDeviceInfo(),
warehouseId: coilData.warehouseId,
priority: 0, // 默认普通优先级
remark: `移动端扫码创建 - ${this.getActionTypeName(actionType)}`
};
console.log('5. 创建待操作记录,数据:', pendingData);
const addRes = await addPendingAction(pendingData);
console.log('创建待操作响应:', addRes);
if (addRes.code !== 200) {
throw new Error(addRes.msg || '创建待操作失败');
}
uni.hideLoading();
console.log('=== 扫码流程完成 ===');
uni.navigateTo({
url: '/pages/scansuccess/scansuccess'
})
// uni.showToast({
// title: '创建成功',
// icon: 'success',
// duration: 2000
// });
// // 延迟后返回或跳转
// setTimeout(() => {
// // 可以跳转到待操作列表或返回上一页
// uni.navigateBack();
// }, 2000);
} catch (err) {
console.error('=== 扫码处理失败 ===');
console.error('错误信息:', err);
console.error('错误堆栈:', err.stack);
uni.hideLoading();
uni.showToast({
title: err.message || '处理失败',
icon: 'none',
duration: 3000
});
}
},
fail: (err) => {
console.error('扫码失败:', err);
uni.showToast({
title: '扫码失败,请重试',
icon: 'none'
});
}
});
},
handleShip() {
uni.scanCode({
success: async (res) => {
console.log('=== 开始扫码流程 ===');
console.log('扫码结果:', res.result);
// console.log('操作类型:', actionType);
uni.showLoading({
title: '处理中...'
});
try {
const qrcodeId = res.result;
// 1. 通过二维码ID获取二维码详情
console.log('1. 获取二维码详情ID:', qrcodeId);
const qrcodeRes = await getGenerateRecord(qrcodeId);
console.log('二维码响应:', qrcodeRes);
if (qrcodeRes.code !== 200) {
throw new Error('未找到二维码记录');
}
// 2. 解析二维码的content获取coil_id
const qrcodeRecord = qrcodeRes.data;
console.log('2. 二维码记录:', qrcodeRecord);
// 检查二维码状态0=失效1=有效)
if (qrcodeRecord.status === 0) {
uni.hideLoading();
uni.showModal({
title: '提示',
content: '该二维码已失效,无法创建待操作任务',
showCancel: false
});
return;
}
const content = JSON.parse(qrcodeRecord.content);
console.log('解析后的内容:', content);
// 优先使用current_coil_id当前有效的钢卷ID如果没有则使用coil_id兼容旧数据
let coilId = content.current_coil_id && content.current_coil_id !== 'null' ? content
.current_coil_id : null;
if (!coilId) {
coilId = content.coil_id && content.coil_id !== 'null' ? content.coil_id : null;
}
console.log('提取钢卷ID - current_coil_id:', content.current_coil_id, 'coil_id:', content.coil_id,
'最终使用:', coilId);
if (!coilId) {
throw new Error('二维码中未包含有效的钢卷ID');
}
// 3. 直接通过钢卷ID获取钢卷详情
console.log('3. 获取钢卷详情钢卷ID:', coilId);
const coilRes = await getMaterialCoil(coilId);
console.log('钢卷详情响应:', coilRes);
if (coilRes.code !== 200) {
throw new Error(coilRes.msg || '查询钢卷信息失败');
}
if (!coilRes.data) {
throw new Error('未找到钢卷信息');
}
const coilData = coilRes.data;
if (coilRes.data.status == 1) {
uni.showToast({
title: '钢卷已经发货,无需再次发货'
})
return;
}
uni.showModal({
cancelText: '取消',
confirmText: '确认',
title: '确定要将钢卷号为:' + coilRes.data.currentCoilNo + '发货吗?',
showCancel: true,
success: async () => {
try {
// 1. 更新钢卷状态为已发货
await updateMaterialCoilSimple({
...coilRes.data,
status: 1,
});
// 2. 插入一条已完成的待操作记录
await addPendingAction({
coilId: coilRes.data.coilId,
currentCoilNo: coilRes.data.currentCoilNo,
actionType: 4, // 4=发货
actionStatus: 2, // 2=已完成
scanTime: new Date(),
scanDevice: this.getDeviceInfo(),
priority: 0, // 0=普通
sourceType: 'scan',
warehouseId: coilRes.data.warehouseId,
processTime: new Date(),
completeTime: new Date()
});
uni.showToast({
title: '发货成功',
icon: 'none'
});
} catch (error) {
console.error('发货失败:', error);
uni.showToast({
title: error.message || '发货失败',
icon: 'none'
});
}
},
fail() {
uni.showToast({
title: '已取消发货',
icon: 'none'
})
}
});
uni.hideLoading();
} catch (err) {
console.error('=== 扫码处理失败 ===');
console.error('错误信息:', err);
console.error('错误堆栈:', err.stack);
uni.hideLoading();
uni.showToast({
title: err.message || '处理失败',
icon: 'none',
duration: 3000
});
}
},
fail: (err) => {
console.error('扫码失败:', err);
uni.showToast({
title: '扫码失败,请重试',
icon: 'none'
});
}
});
},
handleTranfer() {
uni.scanCode({
success: async (res) => {
console.log('=== 开始扫码流程 ===');
console.log('扫码结果:', res.result);
// console.log('操作类型:', actionType);
uni.showLoading({
title: '处理中...'
});
try {
const qrcodeId = res.result;
// 1. 通过二维码ID获取二维码详情
console.log('1. 获取二维码详情ID:', qrcodeId);
const qrcodeRes = await getGenerateRecord(qrcodeId);
console.log('二维码响应:', qrcodeRes);
if (qrcodeRes.code !== 200) {
throw new Error('未找到二维码记录');
}
// 2. 解析二维码的content获取coil_id
const qrcodeRecord = qrcodeRes.data;
console.log('2. 二维码记录:', qrcodeRecord);
// 检查二维码状态0=失效1=有效)
if (qrcodeRecord.status === 0) {
uni.hideLoading();
uni.showModal({
title: '提示',
content: '该二维码已失效,无法创建待操作任务',
showCancel: false
});
return;
}
const content = JSON.parse(qrcodeRecord.content);
console.log('解析后的内容:', content);
// 优先使用current_coil_id当前有效的钢卷ID如果没有则使用coil_id兼容旧数据
let coilId = content.current_coil_id && content.current_coil_id !== 'null' ? content
.current_coil_id : null;
if (!coilId) {
coilId = content.coil_id && content.coil_id !== 'null' ? content.coil_id : null;
}
console.log('提取钢卷ID - current_coil_id:', content.current_coil_id, 'coil_id:', content.coil_id,
'最终使用:', coilId);
if (!coilId) {
throw new Error('二维码中未包含有效的钢卷ID');
}
// 3. 直接通过钢卷ID获取钢卷详情
console.log('3. 获取钢卷详情钢卷ID:', coilId);
const coilRes = await getMaterialCoil(coilId);
console.log('钢卷详情响应:', coilRes);
if (coilRes.code !== 200) {
throw new Error(coilRes.msg || '查询钢卷信息失败');
}
if (!coilRes.data) {
throw new Error('未找到钢卷信息');
}
this.coilDetail = coilRes.data;
this.form = coilRes.data;
this.$refs.tranferPopup.open();
uni.hideLoading()
} catch (err) {
console.error('=== 扫码处理失败 ===');
console.error('错误信息:', err);
console.error('错误堆栈:', err.stack);
uni.hideLoading();
uni.showToast({
title: err.message || '处理失败',
icon: 'none',
duration: 3000
});
}
},
fail: (err) => {
console.error('扫码失败:', err);
uni.showToast({
title: '扫码失败,请重试',
icon: 'none'
});
}
});
},
async handleConfirm() {
try {
// 1. 更新钢卷信息(移库)
await updateMaterialCoilSimple(this.form);
// 2. 插入一条已完成的待操作记录
await addPendingAction({
coilId: this.form.coilId,
currentCoilNo: this.form.currentCoilNo,
actionType: 5, // 5=移库
actionStatus: 2, // 2=已完成
scanTime: new Date(),
scanDevice: this.getDeviceInfo(),
priority: 0, // 0=普通
sourceType: 'scan',
warehouseId: this.form.warehouseId,
processTime: new Date(),
completeTime: new Date()
});
uni.showToast({
title: '移库成功',
icon: 'none'
});
this.$refs.tranferPopup.close();
} catch (error) {
console.error('移库失败:', error);
uni.showToast({
title: error.message || '移库失败',
icon: 'none'
});
}
},
// 获取设备信息
getDeviceInfo() {
try {
const systemInfo = uni.getSystemInfoSync();
return `${systemInfo.platform} ${systemInfo.model}`;
} catch (e) {
return 'Unknown Device';
}
},
// 获取操作类型名称
getActionTypeName(actionType) {
const type = this.types.find(t => t.dictValue === String(actionType));
return type ? type.dictLabel : '未知操作';
}
},
mounted() {
getDicts('action_type').then(res => {
this.types = res.data
})
}
}
</script>
<style scoped>
.container {
padding: 20rpx;
min-height: 100vh;
background-color: #f5f7fa;
display: flex;
flex-direction: column;
align-items: center;
}
/* 页面标题 */
.page-title {
font-size: 32rpx;
font-weight: bold;
color: #333;
padding: 20rpx 0;
margin-bottom: 30rpx;
text-align: center;
}
/* 按钮网格布局 */
.btn-grid {
display: grid;
grid-template-columns: 200rpx 200rpx 200rpx;
/* 固定按钮宽度 */
grid-template-rows: repeat(4, 1fr);
gap: 40rpx;
/* 按钮间距 */
margin-bottom: 60rpx;
}
/* 操作类型按钮样式 - 修改后 */
.type-btn {
width: 200rpx;
height: 150rpx;
white-space: normal; /* 允许文字换行 */
line-height: 1.4; /* 适配换行的行高 */
padding: 10rpx 0; /* 上下内边距优化 */
font-size: 30rpx; /* 字体缩小 */
color: #333;
background-color: #fff;
border-radius: 12rpx;
border: none;
box-shadow: 0 4rpx 10rpx rgba(0, 0, 0, 0.05);
transition: all 0.2s ease;
text-align: center;
display: flex;
align-items: center;
justify-content: center;
}
.type-btn:active {
background-color: #f0f0f0;
box-shadow: 0 2rpx 5rpx rgba(0, 0, 0, 0.1);
transform: scale(0.98);
}
/* 退出登录按钮容器 */
.logout-container {
width: 100%;
position: fixed;
bottom: 30rpx;
left: 0;
padding: 0 20rpx;
box-sizing: border-box;
}
/* 退出登录按钮样式 */
.logout-btn {
width: 100%;
height: 90rpx;
line-height: 90rpx;
/* 文字竖直居中 */
font-size: 30rpx;
color: #fff;
background-color: #ff4d4f;
border-radius: 16rpx;
border: none;
box-shadow: 0 4rpx 10rpx rgba(255, 77, 79, 0.2);
transition: all 0.2s ease;
}
.logout-btn:active {
background-color: #f5222d;
transform: scale(0.98);
}
/* 卡片样式 */
.info-card,
.material-card,
.form-card {
background: #fff;
border-radius: 16rpx;
padding: 30rpx;
margin-bottom: 20rpx;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.04);
}
/* 表单项 */
.form-item {
margin-bottom: 30rpx;
&:last-of-type {
margin-bottom: 0;
}
.form-label {
display: block;
font-size: 28rpx;
color: #333;
margin-bottom: 15rpx;
font-weight: 500;
&::before {
content: '*';
color: #ff4d4f;
margin-right: 6rpx;
}
}
.form-label-optional {
display: block;
font-size: 28rpx;
color: #333;
margin-bottom: 15rpx;
font-weight: 500;
}
.form-input {
width: 100%;
height: 88rpx;
padding: 0 24rpx;
background: #f8f9fa;
border: 2rpx solid #e8e8e8;
border-radius: 12rpx;
font-size: 28rpx;
color: #333;
box-sizing: border-box;
transition: all 0.3s;
&:focus {
background: #fff;
border-color: #007aff;
}
&.form-input-disabled {
background: #f5f5f5;
color: #999;
cursor: not-allowed;
}
}
}
</style>