OCR出库

This commit is contained in:
bb_pan 2025-08-12 18:10:17 +08:00
parent c3d88653aa
commit 206cf573ba
6 changed files with 1566 additions and 532 deletions

View File

@ -536,9 +536,9 @@ const handleQrCode = async (qrCode) => {
//
const ocrClick = () => {
console.log('编码识别--')
console.log('编码识别--', queryParams.value)
uni.navigateTo({
url: `/pages/materialsStation/toolsLease/ocrScan/ocrOutScan?queryParams=${JSON.stringify(
url: `/pages/materialsStation/toolsLease/ocrScan/ocrOutScan?params=${JSON.stringify(
queryParams.value,
)}`,
})

View File

@ -57,7 +57,7 @@
<ElectronicSeal :maCode="codeData?.maCode" :maId="codeData?.maId" />
</div>
<button type="primary" style="margin-top: 20px;" @click="addCode">添加编码</button>
<button type="primary" style="margin-top: 20px" @click="addCode">添加编码</button>
</view>
<!-- 相机预览页面 -->
@ -105,7 +105,7 @@
<script>
import { decryptWithSM4 } from '@/utils/sm'
import { getDeviceListAPI } from '@/services/picking/outbound'
import { getDeviceListAPI, getDeviceListAPINew } from '@/services/picking/outbound'
import ElectronicSeal from '@/components/ElectronicSeal/index.vue'
export default {
@ -143,6 +143,10 @@ export default {
//
this.getDeviceInfo()
},
onLoad(options) {
this.queryParams = options.params ? JSON.parse(options.params) : {}
console.log('🚀 ~ onLoad ~ this.queryParams:', this.queryParams)
},
onHide() {
this.cleanup()
},
@ -152,6 +156,13 @@ export default {
methods: {
//
addCode() {
if (this.codeData.typeId != this.queryParams.typeId) {
uni.showToast({
title: `当前添加的 (${this.codeData.maName}) 类型不匹配, 请重新添加`,
icon: 'none',
})
return
}
if (!this.codeData.maCode) {
uni.showToast({
title: '请先扫码添加',
@ -508,7 +519,10 @@ export default {
console.log('图片处理完成开始OCR识别...')
uni.request({
url: '/material/app/ocr/getOcrCode',
url:
this.queryParams?.jiJuType == 2
? '/material/app/ocr/getOcrCode'
: '/material/app/ocr/getOcrCodeTwo',
method: 'POST',
data: {
image: cleanBase64,
@ -644,7 +658,10 @@ export default {
console.log('相册图片处理完成开始OCR识别...')
uni.request({
url: '/material/app/ocr/getOcrCode',
url:
this.queryParams?.jiJuType == 2
? '/material/app/ocr/getOcrCode'
: '/material/app/ocr/getOcrCodeTwo',
method: 'POST',
data: {
image: processedBase64,
@ -710,7 +727,7 @@ export default {
},
//
getCode() {
async getCode() {
if (!this.queryCodeParams.maCode.trim()) {
uni.showToast({
title: '请输入设备编码',
@ -719,35 +736,37 @@ export default {
return
}
try {
getDeviceListAPI({ maCode: this.queryCodeParams.maCode })
.then((response) => {
console.log('xxxxxxxxxxx', response)
if (response.code === 200 && response.data && response.data.length > 0) {
this.optionList = response.data.map((option) => ({
value: option.maId,
text: option.maCode,
}))
if (response.data.length === 1) {
this.codeData = response.data[0]
}
} else {
uni.showToast({
title: '未查询到该编号信息',
icon: 'none',
duration: 2000,
})
}
})
.catch((error) => {
console.error('获取设备信息失败', error)
uni.hideLoading()
uni.showLoading({
title: '加载中...',
mask: true,
})
let res = null
if (this.queryParams?.jiJuType == 2) {
res = await getDeviceListAPINew(this.queryCodeParams.maCode)
} else {
res = await getDeviceListAPI(this.queryCodeParams.maCode)
}
console.log('🚀 ~ getCode ~ res:', res)
if (res.code === 200 && res.data && res.data.length > 0) {
this.optionList = response.data.map((option) => ({
value: option.maId,
text: option.maCode,
}))
if (response.data.length === 1) {
this.codeData = response.data[0]
}
} else {
uni.showToast({
title: '未查询到该编号信息',
icon: 'none',
duration: 2000,
})
}
} catch (error) {
console.error('查询失败:', error)
uni.showToast({
title: '查询失败,请重试',
icon: 'none',
})
} finally {
uni.hideLoading()
}
},
@ -755,9 +774,14 @@ export default {
async changeTag() {
if (!this.queryCodeParams.maId) return
try {
const response = await getDeviceListAPI({ maId: this.queryCodeParams.maId })
if (response.data && response.data.length !== 0) {
this.codeData = response.data[0]
let res = null
if (this.queryParams?.jiJuType == 2) {
res = await getDeviceListAPINew({ maId: this.queryCodeParams.maId })
} else {
res = await getDeviceListAPI({ maId: this.queryCodeParams.maId })
}
if (res.data && res.data.length !== 0) {
this.codeData = res.data[0]
}
} catch (error) {
console.error('获取编号信息失败', error)

View File

@ -36,7 +36,7 @@
<uni-row :gutter="24" style="display: flex; align-items: center">
<uni-col :span="6">出库方式</uni-col>
<uni-col :span="6">
<view class="coding-btn" @tap="onCodeIdentify">编码识别</view>
<view class="coding-btn" @tap="onCodeIdentify">OCR识别</view>
</uni-col>
<uni-col :span="6">
<view class="coding-btn" @tap="scanStart">二维码出库</view>
@ -205,11 +205,20 @@ const toggleForm = () => {
onLoad((options) => {
queryParams.value = JSON.parse(options.queryParams)
console.log('🚀 ~ queryParams.value:', queryParams.value)
getCodeDetailData(queryParams.value.id, queryParams.value.publishTask, queryParams.value.typeId) //
})
onShow(() => {
uni.$once('paramsReceived', (data) => {
console.log('🚀 ~ onShow ~ data:', data)
// data.maId checkedIds
if (!checkedIds.value.some(item => item.maId === data.maId)) {
checkedIds.value.push(data)
getCodeDeviceListData()
}
})
console.log(queryParams.value)
getCodeDetailData(queryParams.value.id, queryParams.value.publishTask, queryParams.value.typeId) //
// getCodeDetailData(queryParams.value.id, queryParams.value.publishTask, queryParams.value.typeId) //
})
const isWithinOneMonth = (dateStr) => {
@ -234,6 +243,7 @@ const getCodeDetailData = async (id, publishTask, typeId) => {
console.log('xxxxxxxxxxxxxx', formData.value, maxNum.value)
maxNum.value = formData.value.preNum - formData.value.alNum
queryParams.value.jiJuType = res.data.jiJuType
queryCodeParams.value.typeId = queryParams.value.typeId
queryCodeParams.value.pageNum = 1
codeDeviceList.value = []
@ -245,10 +255,11 @@ const getCodeDeviceListData = async () => {
const ids = checkedIds.value.map((item) => item.maId)
const checkedIdSet = new Set(ids)
const res = await getCodeDeviceListAPI(queryCodeParams.value)
console.log('🚀 ~ getCodeDeviceListData ~ res:', res)
const newRows = res.rows || []
const map = new Map()
//
//
codeDeviceList.value.forEach((item) => {
map.set(item.maId, item)
})
@ -261,8 +272,12 @@ const getCodeDeviceListData = async () => {
})
})
//
codeDeviceList.value = Array.from(map.values())
//
const allItems = Array.from(map.values())
codeDeviceList.value = [
...allItems.filter(item => item.checked), //
...allItems.filter(item => !item.checked) //
]
total.value = res.total || 0
}
@ -361,11 +376,12 @@ const onHandleOutbound = async () => {
title: '出库成功!',
icon: 'none',
})
getCodeDetailData(
queryParams.value.id,
queryParams.value.publishTask,
queryParams.value.typeId,
) //
// getCodeDetailData(
// queryParams.value.id,
// queryParams.value.publishTask,
// queryParams.value.typeId,
// ) //
uni.navigateBack()
}
} catch (error) {
console.log('🚀 ~ onHandleOutbound ~ error:', error)
@ -519,7 +535,7 @@ const onCodeIdentify = () => {
})
} else {
uni.navigateTo({
url: `/pages/picking/outbound/codeOutScan?queryParams=${JSON.stringify(
url: `/pages/picking/outbound/codeOutScan?params=${JSON.stringify(
queryParams.value,
)}`,
})

View File

@ -0,0 +1,516 @@
<template>
<view class="page-container">
<!-- <view>
<live-pusher v-once id="livePusher" ref="livePusher" class="livePusher" mode="FHD" beauty="0" whiteness="0"
device-position="back" :auto-focus="false" :muted="true" :enable-camera="true" :enable-mic="true"
:zoom="true" :style="[{height: cameraHeight+'rpx' ,width:'750rpx'}]">
</live-pusher>
</view> -->
<view class="table-list-item">
<view class="scan-btn" @click="handleInstruct()">
<text style="color: #fff">开始识别</text>
</view>
</view>
<!-- <view> 参数{{ testParams }} </view>
<view> 返回{{ resData }} </view> -->
<view class="table-list-item">
<uni-row :gutter="24" style="display: flex; align-items: center">
<uni-col :span="5">
<text> 设备编码 </text>
</uni-col>
<uni-col :span="10">
<view>
<uni-easyinput v-model="queryCodeParams.maCode" placeholder="请输入内容" />
</view>
</uni-col>
<uni-col :span="6">
<view
class="coding-btn"
style="
padding: 10rpx 0;
color: #fe9a09;
background-color: #fff7eb;
border: 1px solid #fe9a09;
"
@click="getCode()"
>
<text style="color: #fe9a09; text-align: center">编码检索</text>
</view>
</uni-col>
</uni-row>
</view>
<view class="table-list-item">
<scroll-view class="scroll-view" scroll-y="true" style="height: 500rpx">
<uni-forms :model="codeData" label-width="100" :border="true">
<uni-forms-item label="物资名称:" name="materialType">
<text style="height: 100%; display: flex; align-items: center">{{
codeData.materialType
}}</text>
</uni-forms-item>
<uni-forms-item label="物资类型:" name="materialName">
<text style="height: 100%; display: flex; align-items: center">{{
codeData.materialName
}}</text>
</uni-forms-item>
<uni-forms-item label="规格型号:" name="materialModel">
<text style="height: 100%; display: flex; align-items: center">{{
codeData.materialModel
}}</text>
</uni-forms-item>
<uni-forms-item label="设备编码:" name="maCode">
<text style="height: 100%; display: flex; align-items: center">{{
codeData.maCode
}}</text>
</uni-forms-item>
<uni-forms-item label="设备状态:" name="statusName">
<text style="height: 100%; display: flex; align-items: center">{{
codeData.statusName
}}</text>
</uni-forms-item>
<!-- <uni-forms-item label="设备数量:">
<text class="form-view">1</text>
</uni-forms-item> -->
</uni-forms>
</scroll-view>
</view>
<view class="outbound-btn" @tap="onHandleOutbound">
<text style="color: #fff">出库</text>
</view>
</view>
</template>
<script>
export default {
data() {
return {
livePusher: null,
ready: true,
cameraHeight: '', //
coverImage: null,
queryParams: {},
queryCodeParams: {
maCode: '',
},
codeData: {},
testParams: '',
resData: '',
}
},
onLoad(options) {
this.queryParams = JSON.parse(options.queryParams)
this.queryCodeParams.typeId = this.queryParams.typeId
},
onReady() {
// this.cameraHeight = uni.getSystemInfoSync().screenHeight * 0.22
// console.log(this.cameraHeight)
// this.init()
},
methods: {
//
// init() {
// this.livePusher = uni.createLivePusherContext('livePusher', this);
// console.log(this.livePusher)
// setTimeout(() => {
// this.startPreview()
// }, 1000)
// },
// //
// startPreview() {
// this.livePusher.startPreview({
// success: () => {
// console.log('');
// switch (plus.os.name) {
// case 'Android':
// break;
// case 'iOS':
// this.livePusher.switchCamera()
// break
// }
// },
// fail: (err) => {
// console.log(err)
// }
// });
// },
//
handleInstruct() {
//
uni.showActionSheet({
itemList: ['拍照', '从相册选择'],
success: (res) => {
if (res.tapIndex === 0) {
this.getCamera()
} else if (res.tapIndex === 1) {
//
this.getPhoto()
// uni.chooseImage({
// count: 1,
// sourceType: ['album'],
// success: async (res) => {
// // ... ...
// const tempFilePath = res.tempFilePaths[0]
// console.log(':', tempFilePath)
// //
// let base64 = await this.imgToBase64(tempFilePath) //
// let params = {
// image: base64,
// jiju_type: '12231',
// auth_lic:
// 'xIWDlaDVdijcBB4mjhGCPYk5Kvk8tHZJbUn+vW+ih15+MYx98e/PXyBmKL5gFcWMPznLgDA15QuSAnZQSLddwdy9HkZgtuQDEEZZ351Eyb1eiDUccUnyoSGIrNimbx5TooBNNPYqU4qJeFrPJXAqjBHzRrxoBxuR2CEGKQPgHC4=',
// }
// uni.request({
// url: '/material/app/ocr/getOcrCode',
// method: 'post',
// data: params,
// header: {
// 'Content-Type': 'application/json', // POST JSON
// },
// success: (res) => {
// console.log('88888888', res)
// if (res.code == 200) {
// uni.showToast({
// title: '',
// icon: 'none',
// })
// } else {
// uni.showToast({ title: '', icon: 'none' }) //
// }
// },
// fail: (err) => {
// uni.showToast({
// title: '' + err.errMsg,
// icon: 'none',
// })
// },
// })
// },
// fail: (err) => {
// console.error(':', err)
// uni.showToast({
// title: '',
// icon: 'none',
// })
// },
// })
}
},
fail: (err) => {
console.error('操作菜单选择失败:', err)
},
})
},
imgToBase64(filePath) {
return new Promise((resolve, reject) => {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest()
xhr.open('GET', filePath, true)
xhr.responseType = 'blob'
xhr.onload = () => {
if (xhr.status === 200) {
const reader = new FileReader()
reader.onloadend = (evt) => {
// data:URL
const base64WithoutPrefix = evt.target.result.split(',')[1]
resolve(base64WithoutPrefix)
}
reader.onerror = reject
reader.readAsDataURL(xhr.response)
} else {
reject(new Error(`请求图片失败,状态码: ${xhr.status}`))
}
}
xhr.onerror = reject
xhr.send()
})
})
},
getCamera() {
console.log(1)
navigator.camera.getPicture(this.onCameraSuccess, this.onCameraError, {
quality: 50,
destinationType: window.Camera.DestinationType.DATA_URL,
sourceType: window.Camera.PictureSourceType.CAMERA,
})
},
getPhoto() {
console.log(2)
navigator.camera.getPicture(this.onCameraSuccess, this.onCameraError, {
quality: 50,
destinationType: window.Camera.DestinationType.DATA_URL,
sourceType: window.Camera.PictureSourceType.SAVEDPHOTOALBUM,
})
},
onCameraError(message) {
console.log(message)
},
onCameraSuccess(file) {
// const file1 = "data:image/jpeg;base64," + file;
const file1 = file
let params = {
image: file1,
jiju_type: '',
auth_lic:
'xIWDlaDVdijcBB4mjhGCPYk5Kvk8tHZJbUn+vW+ih15+MYx98e/PXyBmKL5gFcWMPznLgDA15QuSAnZQSLddwdy9HkZgtuQDEEZZ351Eyb1eiDUccUnyoSGIrNimbx5TooBNNPYqU4qJeFrPJXAqjBHzRrxoBxuR2CEGKQPgHC4=',
}
this.testParams = params
// this.$http
// .post("/dzqm/uploadSignature", {
// base64Str: file1,
// })
// .then((res) => {
// console.log(res);
// if (res.code == 200) {
// // this.src = file
// this.$set(this.obj, "src", file1);
// this.$toast("");
// this.PictureVisible = false;
// }
// });
uni.request({
url: '/material/app/ocr/getOcrCode',
method: 'post',
data: params,
header: {
'Content-Type': 'application/json', // POST JSON
},
success: (res) => {
// const resData = JSON.stringify(res, null, 2)
// this.resData = res
const { data: resData } = res
if (resData.data.data.result) {
this.queryCodeParams.maCode = resData.data.data.result
this.getCode()
} else {
uni.showToast({
title: '识别失败!' + resData.data.msg,
icon: 'none',
})
}
// uni.showModal({
// title: '',
// content: resData.data,
// showCancel: false, //
// })
// if (resData.data.data.data.result) {
// this.queryCodeParams.maCode = resData.data.data.data.result
// this.getCode()
// } else {
// uni.showToast({
// title: '' + resData.data.data.msg,
// icon: 'none',
// })
// }
// uni.showModal({
// title: '',
// content: resData,
// showCancel: false, //
// })
// if (res.code == 200) {
// uni.showToast({
// title: '',
// icon: 'none',
// })
// } else {
// uni.showToast({ title: '', icon: 'none' }) //
// }
},
fail: (err) => {
uni.showToast({
title: '请求失败:' + err.errMsg,
icon: 'none',
})
},
})
},
//
async getCode() {
let param = {
maCode: this.queryCodeParams.maCode,
typeId: this.queryCodeParams.typeId,
maStatus: 1,
}
uni.request({
url: '/material/ma_machine/list',
method: 'get',
data: param,
success: (res) => {
res = res.data
console.log(res)
if (res.rows && res.rows.length > 0) {
this.codeData = res.rows[0]
} else {
uni.showToast({
title: '未检索到有效的设备编码!',
icon: 'none',
})
}
},
fail: (err) => {
console.log(err)
},
})
// const res = await getCodeDeviceListAPI(param)
// console.log(res)
// this.codeData=res.rows[0];
},
//
async onHandleOutbound() {
let paramsList = []
paramsList.push({
maCode: this.codeData.maCode,
maId: this.codeData.maId,
manageType: 0,
outNum: 1,
typeId: this.codeData.typeId,
parentId: this.queryParams.parentId,
})
console.log('333333333', paramsList)
uni.request({
url: '/material/lease_apply_info/leaseOut',
method: 'post',
data: { leaseOutDetailsList: paramsList },
success: (res) => {
res = res.data
console.log(res)
if (res.code === 200) {
uni.showToast({
title: '出库成功!',
icon: 'none',
})
this.queryCodeParams.maCode = ''
this.codeData = {}
}
},
fail: (err) => {
console.log(err)
},
})
},
},
}
</script>
<style>
.page-container {
display: flex;
height: auto;
flex-direction: column;
background-color: #f7f8fa;
padding: 24rpx;
}
.table-list-item {
margin-top: 10rpx;
background: #fff;
padding: 20rpx;
border-radius: 20rpx;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.06);
margin-bottom: 20rpx;
}
.scan-btn {
/* width: 100%; */
height: 88rpx;
background: #4b8eff;
display: flex;
justify-content: center;
align-items: center;
border-radius: 12rpx;
font-size: 32rpx;
font-weight: 600;
box-shadow: 0 6rpx 20rpx rgba(55, 132, 251, 0.2);
/* transition: all 0.3s ease; */
margin: 0;
padding: 0;
}
.coding-btn {
/* padding: 12rpx 0; */
background: #fff;
color: #ff9800;
border: 2rpx solid rgba(255, 152, 0, 0.5);
background: linear-gradient(to bottom, rgba(255, 152, 0, 0.05), rgba(255, 152, 0, 0.1));
border-radius: 12rpx;
text-align: center;
font-size: 28rpx;
font-weight: 600;
letter-spacing: 1rpx;
/* transition: all 0.3s ease; */
/* &:active {
background: rgba(255, 152, 0, 0.15);
border-color: rgba(255, 152, 0, 0.6);
transform: translateY(1rpx);
} */
}
.outbound-btn {
position: fixed;
bottom: 40rpx;
left: 10%;
/* transform: translateX(-50%); */
/* width: 90%; */
height: 88rpx;
width: 620rpx;
margin: 0 10px;
/* background: linear-gradient(135deg, #4b8eff 0%, #3784fb 100%); */
background: #4b8eff;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
border-radius: 12rpx;
font-size: 32rpx;
font-weight: 600;
box-shadow: 0 6rpx 20rpx rgba(55, 132, 251, 0.2);
/* transition: all 0.3s ease; */
/* &:active {
transform: translateX(-50%) scale(0.98);
opacity: 0.9;
} */
}
.camera-background {
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.3);
}
.cover-image {
position: fixed;
top: 0;
left: 0;
z-index: 99;
}
.camera-options {
flex-direction: row;
align-items: center;
}
.camera-item {
flex: 1;
flex-direction: row;
justify-content: center;
align-items: center;
height: 100%;
}
.camera-item .camera-item-image {
width: 80rpx;
height: 80rpx;
}
.camera-options-center .camera-item-image {
width: 120rpx;
height: 120rpx;
}
</style>

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
<template>
<view class="page-container">
<!-- 表单信息区域 -->
<scroll-view scroll-y style="height: 100vh;">
<!-- <scroll-view scroll-y style="height: 100vh;"> -->
<view class="form-section" v-if="queryParams.manageType==1">
<view class="form-content">
<uni-forms :model="formData" label-width="100" :border="true">
@ -21,7 +21,8 @@
</view>
</view>
<scroll-view scroll-y @scrolltolower="onScrollTolower" v-if="queryParams.manageType==0" style="padding-bottom: 90rpx">
<view class="table-list-item" v-for="item in codeDeviceList" :key="item.maId">
<view class="table-list-item" v-for="(item, index) in codeDeviceList" :key="item.maId">
<span style="color: #409EFF">{{ index + 1 }}.</span>
<uni-row :gutter="24">
<uni-col :span="6">物资类型</uni-col>
<uni-col :span="14">
@ -73,7 +74,7 @@
{{ finish ? '没有更多数据了~' : '正在加载...' }}
</view>
</scroll-view>
</scroll-view>
<!-- </scroll-view> -->
<!-- <view class="outbound-btn" @tap="leaseOutBack" v-if="isBack"> 退回 </view> -->
</view>
</template>
@ -124,13 +125,15 @@ const getCodeDeviceListData = async () => {
const res = await getDetailsByIdApi(queryCodeParams.value)
console.log("xxxxxxxxxxxxxx",res)
if(queryParams.value.manageType==0){
codeDeviceList.value.push(...res.data.rows)
if (isBack.value&&codeDeviceList.value.length > 0) {
codeDeviceList.value = codeDeviceList.value.map((e) => {
return { ...e, checked: false }
})
}
// codeDeviceList.value.push(...res.data.rows)
// if (isBack.value&&codeDeviceList.value.length > 0) {
// codeDeviceList.value = codeDeviceList.value.map((e) => {
// return { ...e, checked: false }
// })
// }
codeDeviceList.value = res.data.rows || []
total.value = res.data.total;
console.log('🚀 ~ getCodeDeviceListData ~ total.value:', total.value)
}else if(queryParams.value.manageType==1){
if(res.data.rows&&res.data.rows.length>0){
formData.value=res.data.rows[0]
@ -157,7 +160,7 @@ const onCodeSearch = () => {
//
const onScrollTolower = debounce(() => {
// console.log('--')
console.log('滚动触底--')
if (total.value > codeDeviceList.value.length) {
queryCodeParams.value.pageSize += 5
getCodeDeviceListData()
@ -229,7 +232,7 @@ const leaseOutBack = async (item) => {
<style lang="scss" scoped>
.page-container {
display: flex;
height: 100%;
height: 100vh;
flex-direction: column;
background-color: #f7f8fa;
padding: 24rpx;