bonus-material-app/src/pages/back/backCode.vue

927 lines
29 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>
<uni-nav-bar
status-bar
leftIcon="left"
title="退料编码"
backgroundColor="#dcf4ff"
:border="false"
fixed
@clickLeft="leftClick"
>
<!-- 使用右侧插槽自定义提交按钮 -->
<!-- <template #right>
<button
class="submit-btn"
@click="submitCode"
>
确定
</button>
</template> -->
</uni-nav-bar>
<view class="accept page-common">
<div class="card top-content" :class="{'is-expanded': isExpanded}">
<div class="card-header" @click="isExpanded = !isExpanded">
<div class="title">任务信息</div>
<uni-icons class="icon" type="down" size="19" :class="{'is-expanded': isExpanded}"></uni-icons>
</div>
<uni-forms :model="taskInfo" label-width="170rpx" :border="true">
<uni-forms-item label="退料单位:" name="unitName">
<span style="height: 100%; display: flex; align-items: center">{{
taskInfo.unitName
}}</span>
</uni-forms-item>
<uni-forms-item label="退料工程:" name="proName">
<span style="height: 100%; display: flex; align-items: center">{{
taskInfo.proName
}}</span>
</uni-forms-item>
<uni-forms-item label="退料单号:" name="code">
<span style="height: 100%; display: flex; align-items: center">{{
taskInfo.code
}}</span>
</uni-forms-item>
<uni-forms-item label="退料人员:" name="backPerson">
<span style="height: 100%; display: flex; align-items: center">{{
taskInfo.backPerson
}}</span>
</uni-forms-item>
<uni-forms-item label="联系电话:" name="phone">
<span style="height: 100%; display: flex; align-items: center">{{
taskInfo.phone
}}</span>
</uni-forms-item>
</uni-forms>
</div>
<div class="card" style="margin-top: 10px">
<uni-row :gutter="24" style="display: flex; align-items: center">
<uni-col :span="6">接收方式</uni-col>
<uni-col :span="6">
<view class="coding-btn" @click="onCodeIdentify">编码识别</view>
</uni-col>
<uni-col :span="6">
<view class="coding-btn" @click="scanStart">二维码识别</view>
</uni-col>
<uni-col :span="6">
<view class="coding-btn" @click="moveNum">转至数量</view>
</uni-col>
</uni-row>
</div>
<ScanQrCode
ref="scanQrCodeRef"
@scanSuccess="handleScanSuccess"
@scanError="handleScanError"
/>
<div class="card" style="margin-top: 10px">
<uni-row :gutter="24" style="display: flex; align-items: center; margin-bottom: 10px">
<uni-col :span="6">设备编码</uni-col>
<uni-col :span="12">
<!-- <uni-easyinput placeholder="请输入内容" maxlength="30" v-model="maCode" /> -->
<eselect
style="width: 100%; height: 90rpx"
v-model="maCode"
ref="treeSelect2"
:options="codeList"
@change="changeMaCode"
@clear="clearMaCode"
></eselect>
</uni-col>
<uni-col :span="6">
<view class="coding-btn search-btn" @click="getMaInfo">编码检索</view>
</uni-col>
</uni-row>
<uni-row :gutter="24" style="display: flex; align-items: center; margin-bottom: 10px">
<uni-col :span="6">物资类型:</uni-col>
<uni-col :span="16">
{{ typeName }}
</uni-col>
</uni-row>
<uni-row :gutter="24" style="display: flex; align-items: center; margin-bottom: 10px">
<uni-col :span="6">规格型号:</uni-col>
<uni-col :span="16">
{{ materialName }}
</uni-col>
</uni-row>
<uni-row :gutter="24" style="display: flex; align-items: center; margin-bottom: 10px">
<uni-col :span="6">设备状态:</uni-col>
<uni-col :span="16">
{{ maStatusName }}
</uni-col>
</uni-row>
<uni-row :gutter="24" style="display: flex; align-items: center; margin-bottom: 10px">
<uni-col :span="6">外观判定:</uni-col>
<uni-col :span="16">
<!-- <uni-easyinput placeholder="请输入内容" v-model="apDetection"/> -->
<radio-group @change="changeRadio">
<radio value="完好" checked style="margin-right: 5px">完好</radio>
<radio value="不合格">不合格</radio>
</radio-group>
</uni-col>
</uni-row>
<uni-row :gutter="24" style="display: flex; align-items: center; margin-bottom: 10px">
<uni-col :span="4">附件:</uni-col>
<uni-col :span="20">
<div class="upload-container">
<div class="upload" @click="uploadImg" v-if="imgList.length < 3">+</div>
<div class="image-preview" v-for="(img, index) in imgList" :key="index">
<image :src="img.url" mode="aspectFill"></image>
<view class="delete-btn" @click.stop="deleteImage(index)">×</view>
</div>
</div>
</uni-col>
</uni-row>
</div>
<div class="btn">
<button class="btn-cont" @click="submitCode">确认</button>
</div>
</view>
</template>
<script setup>
import { ref, reactive } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import { getMachine, insertApp, getSelectMachineByIdApi } from '../../services/back.js'
import ScanQrCode from '@/pages/devicesSearch/ScanQrCode.vue'
import { baseURL } from '@/utils/http'
import eselect from '@/components/tree-select/eselect.vue'
import { decryptWithSM4, encryptWithSM4, hashWithSM3AndSalt } from '@/utils/sm'
const taskInfo = ref({})
const maId = ref('') //编码
const maCode = ref('') //编码
const typeName = ref('') //物资类型
const materialName = ref('') //规格型号
const typeId = ref('') //类型id
const maStatusName = ref('') //状态
const apDetection = ref('完好') //外观判定
const imgBeseUrl = ref('') //图片展示
const imgList = ref([]) // 图片列表,用于回显
const bmFileInfos = ref([]) // 上传后的图片信息
const scanQrCodeRef = ref(null)
const codeList = ref([])
const isExpanded = ref(false)
const leftClick = () => {
// 返回
uni.navigateBack({
delta: 1, // 返回到已存在的页面
})
}
const changeRadio = (e) => {
console.log(e.detail.value)
apDetection.value = e.detail.value
}
// 获取编码下拉
const getMaCodeList = async () => {
let param = {
unitId: taskInfo.value.unitId,
proId: taskInfo.value.proId,
id: taskInfo.value.id,
}
try {
const res = await getSelectMachineByIdApi(param)
console.log('🚀 ~ getMaCodeList ~ res:', res)
if (!res.data || res.data.length === 0) return
codeList.value = res.data.map((item) => {
return {
id: item.maCode,
name: item.maCode,
parentId: 0,
}
})
} catch (error) {
console.log('🚀 ~ getMaCodeList ~ error:', error)
}
}
const changeMaCode = (e) => {
console.log('🚀 ~ changeMaCode ~ e:', e)
maCode.value = e.id
}
const clearMaCode = () => {
maCode.value = ''
typeName.value = ''
materialName.value = ''
maStatusName.value = ''
typeId.value = ''
maId.value = ''
maCode.value = ''
typeId.value = ''
apDetection.value = '完好'
bmFileInfos.value = []
imgBeseUrl.value = ''
imgList.value = []
}
//根据编码获取设备类型
const getMaInfo = () => {
console.log(maCode.value)
if (!maCode.value) {
uni.showToast({ title: '请选择设备编码!', icon: 'none' })
return
}
let param = {
maCode: maCode.value,
unitId: taskInfo.value.unitId,
proId: taskInfo.value.proId,
id: taskInfo.value.id,
}
getMachine(param)
.then((res) => {
console.log(res)
if (res.code == 200) {
if (res.data && res.data.length > 0) {
typeName.value = res.data[0].typeName
materialName.value = res.data[0].materialName
maStatusName.value = res.data[0].maStatusName
maId.value = res.data[0].maId
typeId.value = res.data[0].typeId
} else {
uni.showToast({ title: '该编码非该单位工程领用,不可退料!', icon: 'none' })
}
}
})
.catch((error) => {
console.log(error)
})
}
const qrCode = ref('') //图片展示
// 二维码扫码
const scanStart = async () => {
qrCode.value = ''
if (scanQrCodeRef.value) {
scanQrCodeRef.value.scanQrCode()
}
// var mpaasScanModule = uni.requireNativePlugin('Mpaas-Scan-Module')
// mpaasScanModule.mpaasScan(
// {
// // 扫码识别类型参数可多选qrCode、barCode不设置默认识别所有
// scanType: ['qrCode', 'barCode'],
// // 是否隐藏相册默认false不隐藏
// hideAlbum: false,
// //ios需要设置这个参数只支持中英文 zh-Hans、en默认中文
// language: 'en',
// //相册选择照片识别错误提示(ios)
// failedMsg: '未识别到二维码,请重试',
// //Android支持全屏需要设置此参数
// screenType: 'full',
// },
// (ret) => {
// console.log(ret)
// if (ret.resp_code == 10) {
// uni.showToast({ title: '用户取消', icon: 'none' })
// }
// if (ret.resp_code == 11) {
// uni.showToast({ title: '扫码失败', icon: 'none' })
// }
// if (ret.resp_code == 1000) {
// qrCode.value = ret.resp_result
// console.log(qrCode.value)
// let param = {
// qrCode: qrCode.value,
// unitId: taskInfo.value.unitId,
// proId: taskInfo.value.proId,
// }
// getMachine(param)
// .then((res) => {
// console.log(res)
// console.log(res.data[0])
// maCode.value = res.data[0].maCode
// typeName.value = res.data[0].typeName
// materialName.value = res.data[0].typeModelName
// maStatusName.value = res.data[0].maStatusName
// maId.value = res.data[0].maId
// typeId.value = res.data[0].typeId
// })
// .catch((error) => {
// console.log(error)
// })
// }
// },
// )
}
// 处理扫描成功事件
const handleScanSuccess = (result) => {
qrCode.value = result?.data?.split('?qrcode=')[1] || result?.data
if (qrCode.value === '') {
uni.showToast({ title: '扫码识别失败', icon: 'none' })
} else {
getMaInfoScan()
}
}
// 处理扫描失败事件
const handleScanError = (error) => {
console.error('扫描出错:', error.message)
uni.showToast({ title: error.message, icon: 'none' })
}
const moveNum = () => {
uni.navigateTo({ url: `/pages/back/backNum?taskInfo=${JSON.stringify(taskInfo.value)}` })
}
const getMaInfoScan = () => {
let param = {
qrCode: qrCode.value,
unitId: taskInfo.value.unitId,
proId: taskInfo.value.proId,
id: taskInfo.value.id,
}
uni.request({
url: '/material/back_apply_info/getMachine',
method: 'get',
data: param,
success: (res) => {
console.log(res)
if(!res.data.code){
res = JSON.parse(decryptWithSM4(res.data))
}else{
res = JSON.parse(res.data)
}
console.log("xxxxxxxxxxxxxxxx",res)
if (res.code == 200) {
console.log(res)
console.log(res.data[0])
maCode.value = res.data[0].maCode
typeName.value = res.data[0].typeName
materialName.value = res.data[0].typeModelName
maStatusName.value = res.data[0].maStatusName
maId.value = res.data[0].maId
typeId.value = res.data[0].typeId
}else{
uni.showModal({
title: '错误提示',
content: res.msg,
showCancel: false, // 不显示取消按钮
confirmText: '关闭',
success: (res) => {
// if (res.confirm) {
// console.log('用户点击关闭')
// }
}
})
}
},
})
// getMachine(param)
// .then((res) => {
// console.log(res)
// console.log(res.data[0])
// maCode.value = res.data[0].maCode
// typeName.value = res.data[0].typeName
// materialName.value = res.data[0].typeModelName
// maStatusName.value = res.data[0].maStatusName
// maId.value = res.data[0].maId
// typeId.value = res.data[0].typeId
// })
// .catch((error) => {
// uni.showModal({
// title: '错误提示',
// content: error.data.msg,
// showCancel: false, // 不显示取消按钮
// confirmText: '关闭',
// success: (res) => {
// // if (res.confirm) {
// // console.log('用户点击关闭')
// // }
// }
// })
// })
}
// // 扫码识别按钮
// const scanStart = () => {
// console.log('编码识别--')
// // 只允许通过相机扫码
// uni.scanCode({
// onlyFromCamera: true,
// scanType: ['qrCode', 'pdf417'],
// success: (res) => {
// console.log('扫码结果:' + res.result);
// maCode.value = res.result;
// },
// fail: (err) => {
// // uni.showToast({
// // title: '取消',
// // icon: 'none'
// // });
// }
// });
// }
// function getCamera() {
// console.log(1)
// navigator.camera.getPicture(this.onCameraSuccess, this.onCameraError, {
// quality: 50,
// destinationType: window.Camera.DestinationType.DATA_URL,
// sourceType: window.Camera.PictureSourceType.CAMERA,
// })
// }
// function getPhoto() {
// console.log(2)
// navigator.camera.getPicture(this.onCameraSuccess, this.onCameraError, {
// quality: 50,
// destinationType: window.Camera.DestinationType.DATA_URL,
// sourceType: window.Camera.PictureSourceType.SAVEDPHOTOALBUM,
// })
// }
// 编码识别按钮
const onCodeIdentify = () => {
console.log('编码识别--')
uni.navigateTo({
url: `/pages/back/backCodeScan?queryParams=${JSON.stringify(taskInfo.value)}`,
})
}
//提交
const submitCode = () => {
console.log(taskInfo.value)
if (maId.value == '') {
uni.showToast({ title: '请先添加退料设备编码!', icon: 'none' })
} else if (apDetection.value == '不合格' && bmFileInfos.value.length == 0) {
uni.showToast({ title: '请上传附件!', icon: 'none' })
} else {
// console.log(typeList.value)
let obj = {
maId: maId.value,
maCode: maCode.value,
typeId: typeId.value,
apDetection: apDetection.value,
goodNum: apDetection.value == '完好' ? 1 : 0,
badNum: apDetection.value == '不合格' ? 1 : 0,
bmFileInfos: bmFileInfos.value,
}
let param = {
backApplyInfo: taskInfo.value,
backApplyDetails: obj,
}
insertApp(param)
.then((res) => {
console.log(res)
if (res.code == 200) {
uni.showToast({ title: '添加成功!', icon: 'none' })
typeName.value = ''
materialName.value = ''
maStatusName.value = ''
typeId.value = ''
maId.value = ''
maCode.value = ''
typeId.value = ''
apDetection.value = '完好'
bmFileInfos.value = []
imgBeseUrl.value = ''
imgList.value = []
getMaCodeList()
// uni.navigateBack({
// delta: 1 // 返回到已存在的页面
// });
scanStart()
} else {
uni.showToast({ title: res.msg, icon: 'none' })
}
})
.catch((error) => {
console.log(error)
})
}
}
//上传
const uploadImg = () => {
const count = 3 - imgList.value.length
if (count <= 0) {
uni.showToast({ title: '最多上传3张图片', icon: 'none' })
return
}else{
uni.showActionSheet({
itemList: ['拍照', '从相册选择'],
success: (res) => {
if (res.tapIndex === 0) {
getCameraFj()
} else if (res.tapIndex === 1) {
// 从相册选择
getPhotoFj()
}
},
fail: (err) => {
console.error('操作菜单选择失败:', err)
},
})
}
}
// 附件拍照
const getCameraFj = () => {
navigator.camera.getPicture(onCameraSuccessFj, onCameraErrorFj, {
quality: 50,
destinationType: window.Camera.DestinationType.DATA_URL,
sourceType: window.Camera.PictureSourceType.CAMERA,
})
}
// 附件从相册选择
const getPhotoFj = () => {
navigator.camera.getPicture(onCameraSuccessFj, onCameraErrorFj, {
quality: 50,
destinationType: window.Camera.DestinationType.DATA_URL,
sourceType: window.Camera.PictureSourceType.SAVEDPHOTOALBUM,
})
}
const onCameraErrorFj = (message) => {
console.log(message)
}
const onCameraSuccessFj = (file) => {
uploadSignUrlFj(file)
}
const generateRandomString = (length) => {
let result = '';
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
const charactersLength = characters.length;
for (let i = 0; i < length; i++) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
}
return result;
}
const uploadSignUrlFj = (file) => {
const base64Data = file
uni.request({
url: '/file/uploadBase64',
method: 'POST',
data: {
base64File:base64Data,
fileName: `${generateRandomString(10)}_${Date.now()}.png`,
fileType: 'image/png'
},
success: (uploadRes) => {
if(!uploadRes.data.code){
uploadRes = JSON.parse(decryptWithSM4(uploadRes.data))
}else{
uploadRes = JSON.parse(uploadRes.data)
}
if (uploadRes.code && uploadRes.code == 200) {
imgList.value.push({
url: uploadRes.data.url, // Show local path first
serverUrl: uploadRes.data.url // Store server URL
})
bmFileInfos.value.push({
name: uploadRes.data.name,
url: uploadRes.data.url,
taskType: '10'
})
uni.showToast({ title: '上传成功', icon: 'none' })
} else {
uni.showToast({ title: '上传失败', icon: 'none' })
}
},
fail: (err) => {
console.error('上传失败', err)
uni.showToast({ title: '上传失败', icon: 'none' })
}
})
}
// 删除图片
const deleteImage = (index) => {
imgList.value.splice(index, 1)
bmFileInfos.value.splice(index, 1)
}
onLoad((options) => {
console.log(options)
taskInfo.value = JSON.parse(options.taskInfo)
console.log(taskInfo.value)
getMaCodeList()
})
</script>
<style lang="scss" scoped>
.submit-btn {
background-color: #007aff; /* 蓝色背景 */
color: white; /* 白色文字 */
border: none; /* 去掉边框 */
border-radius: 5px; /* 圆角 */
padding: 0 14px; /* 左右内边距 */
height: 30px; /* 高度 */
line-height: 30px; /* 垂直居中 */
font-size: 15px; /* 字体放大 */
margin-right: 2px; /* 与边缘间距 */
}
::v-deep .tree-item .head {
justify-content: center !important;
}
::v-deep .uni-easyinput__content {
padding: 0 !important;
}
/* 在style部分添加 */
.upload-container {
display: flex;
flex-wrap: wrap;
gap: 10px;
}
.upload {
width: 160rpx;
height: 160rpx;
background-color: #f7f8fa;
border: 2rpx dashed #d9d9d9;
border-radius: 12rpx;
display: flex;
justify-content: center;
align-items: center;
font-size: 48rpx;
color: #bfbfbf;
transition: all 0.3s ease;
}
.image-preview {
width: 160rpx;
height: 160rpx;
position: relative;
border-radius: 12rpx;
overflow: hidden;
}
.image-preview image {
width: 100%;
height: 100%;
}
.delete-btn {
position: absolute;
top: 0;
right: 0;
width: 40rpx;
height: 40rpx;
background-color: rgba(0, 0, 0, 0.5);
color: white;
display: flex;
justify-content: center;
align-items: center;
border-bottom-left-radius: 12rpx;
font-size: 32rpx;
line-height: 32rpx;
}
.uploading-mask {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.3);
display: flex;
justify-content: center;
align-items: center;
color: white;
font-size: 24rpx;
}
::v-deep .uni-radio-input {
width: 16px;
height: 16px;
}
.accept {
padding: 24rpx;
/* height: 95vh; */
word-break: break-all;
background-color: #f7f8fa;
display: flex;
flex-direction: column;
// 卡片样式
.card {
padding: 32rpx;
background-color: #fff;
border-radius: 20rpx;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.06);
margin-bottom: 24rpx;
// 卡片标题
/* > div:first-child {
font-size: 32rpx;
font-weight: 600;
color: #262626;
margin-bottom: 24rpx;
position: relative;
padding-left: 24rpx;
&::before {
content: '';
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 6rpx;
height: 28rpx;
background: #3784fb;
border-radius: 6rpx;
}
} */
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 24rpx;
.title {
font-size: 32rpx;
font-weight: 600;
color: #262626;
position: relative;
padding-left: 24rpx;
&::before {
content: '';
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 6rpx;
height: 28rpx;
background: #3784fb;
border-radius: 6rpx;
}
}
.icon {
transition: transform 0.5s ease; /* 添加动画过渡 */
transform: rotate(0deg);
&.is-expanded {
transform: rotate(180deg);
}
}
}
// 表单样式
:deep(.uni-forms) {
.uni-forms-item {
padding: 24rpx 0;
margin-bottom: 0;
border-bottom: 2rpx solid #f5f5f5;
&:last-child {
border-bottom: none;
}
.uni-forms-item__label {
color: #8c8c8c;
}
span {
color: #262626;
font-size: 28rpx;
}
}
}
// 扫码按钮样式
.coding-btn {
padding: 0 5px;
height: 60rpx;
line-height: 60rpx;
background: linear-gradient(135deg, #4b8eff 0%, #3784fb 100%);
border-radius: 12rpx;
text-align: center;
color: #fff;
font-size: 24rpx;
font-weight: 600;
box-shadow: 0 6rpx 20rpx rgba(55, 132, 251, 0.2);
transition: all 0.3s ease;
&:active {
transform: scale(0.98);
opacity: 0.9;
box-shadow: 0 2rpx 8rpx rgba(55, 132, 251, 0.2);
}
// 检索按钮样式
&.search-btn {
background: #fff7eb;
color: #fa8c16;
border: 2rpx solid #fa8c16;
box-shadow: none;
&:active {
background: #fff3e0;
}
}
}
// 信息展示行
:deep(.uni-row) {
/* margin-bottom: 24rpx; */
&:last-child {
margin-bottom: 0;
}
.uni-col-6 {
color: #8c8c8c;
font-size: 28rpx;
}
.uni-col-16 {
color: #262626;
font-size: 28rpx;
}
// 输入框样式
.uni-easyinput__content {
background-color: #f7f8fa;
border: 2rpx solid #e8e8e8;
border-radius: 12rpx;
height: 75rpx;
padding: 0 24rpx;
transition: all 0.3s ease;
&:focus-within {
border-color: #3784fb;
box-shadow: 0 0 0 2rpx rgba(55, 132, 251, 0.1);
}
.uni-easyinput__content-input {
font-size: 28rpx;
height: 75rpx;
line-height: 75rpx;
}
}
}
// 上传区域样式
.upload {
width: 160rpx;
height: 160rpx;
background-color: #f7f8fa;
border: 2rpx dashed #d9d9d9;
border-radius: 12rpx;
display: flex;
justify-content: center;
align-items: center;
font-size: 48rpx;
color: #bfbfbf;
transition: all 0.3s ease;
&:active {
background-color: #f0f0f0;
border-color: #3784fb;
}
image {
width: 100%;
height: 100%;
border-radius: 12rpx;
object-fit: cover;
}
}
}
// 底部按钮
.btn {
margin-top: auto;
padding: 32rpx;
background: #fff;
box-shadow: 0 -4rpx 16rpx rgba(0, 0, 0, 0.05);
.btn-cont {
width: 100%;
height: 88rpx;
line-height: 88rpx;
text-align: center;
background: linear-gradient(135deg, #4b8eff 0%, #3784fb 100%);
color: #fff;
border-radius: 44rpx;
font-size: 32rpx;
font-weight: 600;
box-shadow: 0 6rpx 20rpx rgba(55, 132, 251, 0.2);
transition: all 0.3s ease;
&:active {
transform: scale(0.98);
opacity: 0.9;
box-shadow: 0 2rpx 8rpx rgba(55, 132, 251, 0.2);
}
}
}
}
.top-content {
height: 30px;
overflow: hidden;
transition: max-height 0.5s ease-out;
&.is-expanded {
height: auto !important;
}
}
</style>