bonus-material-app/src/pages/materialsStation/toolsLease/codeOut.vue

824 lines
22 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 dark :fixed="true" shadow background-color="#4AA4EA" status-bar title="编码"
><template v-slot:left>
<view style="font-size: 18px; display: flex; align-items: center" @click="back">
<!-- 图标 -->
<uni-icons type="left" size="20" color="#fff"></uni-icons>
<!-- 文本 -->
<text>返回</text>
</view>
</template>
</uni-nav-bar>
<view class="page-container">
<!-- 表单信息区域 -->
<scroll-view scroll-y style="height: 100vh">
<view class="form-section">
<view class="section-header" @tap="toggleForm">
<text class="title">任务信息</text>
<text class="toggle-icon" :class="{ 'is-expanded': isExpanded }"></text>
</view>
<view class="form-content" :class="{ 'is-expanded': isExpanded }">
<uni-forms :model="formData" label-width="100" :border="true">
<uni-forms-item
label="物资类型:"
name="maTypeName"
class="flex"
v-if="!queryParams.isAddCode"
>
<span class="form-view">{{ queryParams.maTypeName }}</span>
</uni-forms-item>
<uni-forms-item
label="规格型号:"
name="typeName"
class="flex"
v-if="!queryParams.isAddCode"
>
<span class="form-view">{{ queryParams.typeName }}</span>
</uni-forms-item>
<uni-forms-item label="全选:" name="" class="flex">
<checkbox-group
><checkbox value="" :checked="allChecked" @click="handleCheckAll" />
<text>{{ isSelectNum }} / {{ codeDeviceList.length }} 条已选</text>
</checkbox-group>
</uni-forms-item>
<uni-forms-item label="" name="" v-if="codeDeviceList.length > 0">
<div
style="
display: flex;
align-items: center;
flex-wrap: wrap;
max-height: 249px;
overflow-y: auto;
"
>
<div
v-for="(item, index) in codeDeviceList"
style="margin: 0 5px"
v-show="item.checked"
>
<span
>{{ item.maCode }}
<uni-icons
type="close"
size="18"
color="red"
@click="handleItemChecked(item)"
></uni-icons
></span>
</div>
</div>
</uni-forms-item>
<!--
<uni-forms-item
label="待出库数量:"
name="outNum"
class="flex"
v-if="!queryParams.isAddCode"
>
<span class="form-view">{{ queryParams.outNum }}</span>
</uni-forms-item>
-->
</uni-forms>
</view>
</view>
<view class="table-list-item">
<uni-row :gutter="24" class="flex">
<uni-col :span="6">出库方式:</uni-col>
<uni-col :span="6">
<button class="item-btn" type="primary" @click="scanStart">二维码识别</button>
</uni-col>
<uni-col :span="6">
<button class="item-btn" type="primary" @click="handleRfid">RFID识别</button>
</uni-col>
<uni-col :span="6">
<button class="item-btn" type="primary" @click="ocrClick">OCR识别</button>
</uni-col>
</uni-row>
</view>
<ScanQrCode
ref="scanQrCodeRef"
@scanSuccess="handleScanSuccess"
@scanError="handleScanError"
/>
<div class="table-list-item">
<uni-row :gutter="24" style="display: flex; align-items: center">
<uni-col :span="6">
<view> 设备编码 </view>
</uni-col>
<uni-col :span="18">
<uni-data-select
v-model="queryCodeParams.maCode"
:localdata="codeRange"
@change="changeCode"
@click="handleMaCode"
:keepOpen="true"
></uni-data-select>
</uni-col>
</uni-row>
</div>
<scroll-view scroll-y style="padding-bottom: 30rpx; height: 70vh">
<view class="table-list-item" v-for="(item, index) in codeDeviceList" :key="item.maId">
<uni-row :gutter="24">
<uni-col :span="6">物资类型:</uni-col>
<uni-col :span="14">
<view class="cont">{{ item.materialName }}</view>
</uni-col>
<uni-col :span="4">
<!-- <div class="btn-del" @click="delMaterial(item, index)">移除</div> -->
<checkbox-group
><checkbox value="" :checked="item.checked" @click="handleItemChecked(item)"
/></checkbox-group>
</uni-col>
</uni-row>
<uni-row :gutter="24">
<uni-col :span="6">规格型号:</uni-col>
<uni-col :span="16">
<view class="cont">{{ item.typeName }}</view>
</uni-col>
</uni-row>
<uni-row :gutter="24">
<uni-col :span="6">设备编码:</uni-col>
<uni-col :span="16">
<view class="cont">{{ item.maCode }}</view>
</uni-col>
</uni-row>
<!-- <uni-row :gutter="24">
<uni-col :span="6">设备状态:</uni-col>
<uni-col :span="16">
<view class="cont">{{ item.maStatusName || item.maStatus }}</view>
</uni-col>
</uni-row> -->
<uni-row :gutter="24">
<uni-col :span="6">设备数量:</uni-col>
<uni-col :span="16">
<view class="cont">1</view>
</uni-col>
</uni-row>
</view>
<view class="loading-text">
{{ '没有更多数据了~' }}
</view>
<div v-if="codeDeviceList.length > 0">
<button type="primary" @click="onHandleOutbound">添加</button>
</div>
</scroll-view>
</scroll-view>
</view>
</template>
<script setup>
import { ref, computed } from 'vue'
import { onLoad, onShow } from '@dcloudio/uni-app'
import {
getCodeScanAPI,
getMachineByIdApi,
getCodeDeviceListAPI,
getMachine,
} from '@/services/materialsStation'
import ScanQrCode from '@/pages/devicesSearch/ScanQrCode.vue'
const isOpenQrCode = ref(false)
const openQrCodeRef = ref(null)
const scanQrCodeRef = ref(null)
const queryParams = ref({})
const queryParamsTemp = ref({
id: '',
typeId: '',
isAddCode: false,
})
const codeRange = ref([]) // 编码列表
const formData = ref({})
const codeDeviceList = ref([])
const total = ref(0)
// 编码设备列表查询参数
const queryCodeParams = ref({
pageNum: 1,
pageSize: 9999,
typeId: '',
// maStatus: 1,
maCode: '',
})
const qrCodeScan = ref('')
// 控制表单展开收起
const isExpanded = ref(true)
const allChecked = ref(false) // 全选复选框状态
const isSelectNum = computed(() => codeDeviceList.value.filter((e) => e.checked).length)
// 切换表单展开状态
const toggleForm = () => {
isExpanded.value = !isExpanded.value
}
const back = () => {
uni.navigateBack({
delta: 1,
})
}
// 页面加载完毕
onLoad((opt) => {
queryParamsTemp.value = opt.params ? JSON.parse(opt.params) : {}
// queryParamsTemp.value.id = queryParamsTemp.value.parentId
console.log('xxxxxxxx', queryParamsTemp.value)
queryCodeParams.value.typeId = queryParamsTemp.value.typeId
queryCodeParams.value.proId = queryParamsTemp.value.proId || queryParamsTemp.value.projectId
queryCodeParams.value.teamId = queryParamsTemp.value.teamId
queryParams.value = { ...queryParamsTemp.value }
if (queryParamsTemp.value.isBack) {
getCodeList() // 获取编码列表
} else {
getCodeDeviceListData()
}
codeDeviceList.value = queryParamsTemp.value.maCodeList || [] // 初始化编码设备列表
if (queryParamsTemp.value.maCodeList && queryParamsTemp.value.maCodeList.length > 0) {
allChecked.value = queryParamsTemp.value.maCodeList.every((e) => e.checked)
}
})
onShow((opt) => {
uni.$once('paramsReceived', (data) => {
console.log('🚀 ~ uni.$on ~ data:', data)
if (data) {
if (data.typeId != queryParamsTemp.value.typeId) {
uni.showToast({
title: `规格型号${data.typeName}不匹配, 请重新添加`,
icon: 'none',
duration: 1500,
})
return
}
const newItem = {
...data,
checked: true,
outType: 4,
}
// 去重
const exists = codeDeviceList.value.some((item) => item.maCode === newItem.maCode)
if (exists) {
uni.showToast({ title: '设备已添加', icon: 'none' })
} else {
codeDeviceList.value.unshift(newItem)
}
allChecked.value = codeDeviceList.value.every((e) => e.checked)
}
})
})
const getCodeList = async () => {
const params = {
teamId: queryParamsTemp.value.teamId,
proId: queryParamsTemp.value.projectId,
typeId: queryParamsTemp.value.typeId,
maCode: queryCodeParams.value.maCode,
}
try {
const res = await getMachineByIdApi(params)
console.log('🚀 ~ getCodeList ~ res:', res)
if (res.code === 200 && res.data && res.data.length > 0) {
codeRange.value = res.data.map((item) => {
return {
text: item.maCode,
value: item.maCode,
}
})
}
} catch (error) {
console.log('🚀 ~ getCodeList ~ error:', error)
}
}
// 获取编码列表
const getCodeDeviceListData = async () => {
console.log('🚀 ~ getCodeDeviceListData ~ queryCodeParams.value:', queryCodeParams.value)
try {
uni.showLoading({
title: '加载中...',
mask: true,
})
const res = await getCodeDeviceListAPI(queryCodeParams.value)
if (res.data && res.data.length > 0) {
codeRange.value = res.data.map((item) => {
return {
text: item.maCode,
value: item.maCode,
}
})
}
console.log('🚀 ~ getCodeDeviceListData ~ res:', res)
setTimeout(() => {
uni.hideLoading()
}, 300)
} catch (error) {
console.log('🚀 ~ getCodeDeviceListData ~ error:', error)
uni.hideLoading()
}
}
const handleMaCode = () => {
isExpanded.value = false
}
const changeCode = (value) => {
console.log('🚀 ~ changeCode ~ value:', value)
if (!value) return
queryCodeParams.value.maCode = value
getCodeInfoData()
}
const getCodeInfoData = async () => {
try {
uni.showLoading({
title: '加载中...',
mask: true,
})
let res = null
if (queryParamsTemp.value.isBack) {
res = await getMachineByIdApi(queryCodeParams.value)
} else {
res = await getCodeDeviceListAPI(queryCodeParams.value)
}
if (!res.data || !res.data.length) {
uni.hideLoading()
uni.showToast({
title: '暂无数据',
icon: 'none',
})
return
}
const newItem = {
...res.data[0],
checked: true,
outType: 0,
}
// 根据maCode去重
const exists = codeDeviceList.value.some((item) => item.maCode === newItem.maCode)
if (exists) {
uni.showToast({ title: '设备已添加', icon: 'none' })
} else {
codeDeviceList.value.unshift(newItem)
}
allChecked.value = codeDeviceList.value.every((e) => e.checked)
setTimeout(() => {
uni.hideLoading()
}, 300)
} catch (error) {
console.log('🚀 ~ getCodeDeviceListData ~ error:', error)
uni.hideLoading()
}
}
// 编码搜索按钮
const onCodeSearch = () => {
queryCodeParams.value.pageNum = 1
codeDeviceList.value = []
allChecked.value = false
// 退料
if (queryParams.value.isBack) {
getCodeList()
} else {
getCodeDeviceListData()
}
}
// 全选复选框事件
const handleCheckAll = async () => {
allChecked.value = !allChecked.value
codeDeviceList.value.forEach((item) => {
item.checked = allChecked.value
})
}
// 复选框单选事件
const handleItemChecked = (item) => {
item.checked = !item.checked
// 更新全选状态
allChecked.value = codeDeviceList.value.every((e) => e.checked)
}
// 出库按钮
const onHandleOutbound = async () => {
if (codeDeviceList.value.length == 0) {
uni.showToast({
title: '请添加设备',
icon: 'none',
})
return
}
// 至少勾选一条数据
const isSelectList = codeDeviceList.value.filter((e) => e.checked === true)
console.log('🚀 ~ onHandleOutbound ~ isSelectList:', isSelectList)
if (isSelectList.length === 0) {
uni.showToast({
title: '请至少勾选一条数据',
icon: 'none',
})
return
}
// 解构所需要的数据
const { typeId, parentId, publishTask } = queryParams.value
// 组装出库参数
const paramsList = []
isSelectList.forEach((e) => {
e.manageType = 0
})
// console.log('🚀 ~ 添加编码 ~ paramsList:', paramsList)
uni.$emit('maCodeList', isSelectList) // 更新编码设备列表
back()
}
// 扫码识别按钮
const scanStart = () => {
// handleQrCode('201811-00531')
if (scanQrCodeRef.value) {
scanQrCodeRef.value.scanQrCode()
}
// isOpenQrCode.value = true
// openQrCodeRef.value.openQrCode()
// console.log('🚀 ~ scanStart ~ openQrCodeRef.value:', openQrCodeRef.value)
}
// 处理RFID识别
const handleRfid = () => {
// 提示
uni.showToast({ title: '请在扫码终端操作', icon: 'none' })
}
// 处理扫描成功事件
const handleScanSuccess = (result) => {
qrCodeScan.value = result?.data?.split('?qrcode=')[1] || result?.data
if (qrCodeScan.value === '') {
uni.showToast({ title: '扫码识别失败', icon: 'none' })
} else {
handleQrCode(qrCodeScan.value)
}
}
// 处理扫描失败事件
const handleScanError = (error) => {
console.error('扫描出错:', error.message)
uni.showToast({ title: error.message, icon: 'none' })
}
// 处理二维码
const handleQrCode = async (qrCode) => {
const params = {
qrCode,
typeId: queryParams.value.typeId,
proId: queryParamsTemp.value.proId || queryParamsTemp.value.projectId,
teamId: queryParamsTemp.value.teamId,
}
try {
let res = null
if (queryParamsTemp.value.isBack) {
res = await getMachine(params)
console.log('🚀 ~ handleQrCode ~ res:', res)
const newItem = {
...res.data[0],
checked: true,
outType: 0,
}
// 根据maCode去重
const exists = codeDeviceList.value.some((item) => item.maCode === newItem.maCode)
if (exists) {
uni.showToast({ title: '设备已添加', icon: 'none' })
} else {
codeDeviceList.value.unshift(newItem)
}
allChecked.value = codeDeviceList.value.every((e) => e.checked)
return
} else {
res = await getCodeScanAPI(params)
}
console.log('🚀 ~ success: ~ res:', res)
if (res.code === 200) {
if (res.data && res.data.recordList.length > 0) {
codeDeviceList.value.unshift(...res.data.recordList)
// 去重
if (codeDeviceList.value.length > 0) {
const seen = new Set()
codeDeviceList.value = codeDeviceList.value.filter((item) => {
if (!item.maCode || seen.has(item.maCode)) {
uni.showToast({ title: '设备已添加', icon: 'none' })
return false
}
seen.add(item.maCode)
return true
})
codeDeviceList.value.forEach((item) => {
item.materialName = item.typeName
item.materialModel = item.typeModelName
item.outType = 2 // 出库方式 二维码
item.checked = true // 默认选中
})
allChecked.value = codeDeviceList.value.every((e) => e.checked)
}
} else {
uni.showToast({ title: res.data.msg, icon: 'none', duration: 1500 })
}
} else {
uni.showToast({ title: '扫码识别失败', icon: 'none' })
}
} catch (error) {
console.log('🚀 ~ success: ~ error:', error)
}
}
// 编码识别按钮
const ocrClick = () => {
console.log('编码识别--', queryParams.value)
uni.navigateTo({
url: `/pages/materialsStation/toolsLease/ocrScan/ocrOutScan?params=${JSON.stringify(
{ ...queryParams.value, proId: queryParamsTemp.value.proId },
)}`,
})
}
</script>
<style lang="scss" scoped>
.flex {
display: flex;
align-items: center;
}
.btn-del {
background: red;
color: #fff;
text-align: center;
border-radius: 5px;
line-height: 1.8;
}
.page-container {
display: flex;
height: 100%;
flex-direction: column;
background-color: #f7f8fa;
padding: 24rpx;
.table-list-item {
background: #fff;
padding: 32rpx 18rpx;
border-radius: 20rpx;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.06);
margin-bottom: 24rpx;
.item-btn {
padding-left: 3px;
padding-right: 3px;
@media (min-width: 768px) {
width: 100px;
font-size: 15px;
}
// 针对手机如宽度小于768px设置不同的 padding-top
@media (max-width: 767px) {
// width: 95px;
font-size: 13px;
}
}
// 表单样式
:deep(.uni-forms) {
.uni-forms-item {
margin-bottom: 24rpx;
padding: 0;
&:last-child {
margin-bottom: 0;
}
.uni-forms-item__label {
color: #8c8c8c;
font-size: 28rpx;
font-weight: 500;
padding: 0;
line-height: 1.8;
}
.uni-forms-item__content {
display: flex;
align-items: center;
min-height: unset;
}
}
}
// 编码按钮组
.coding-btn {
padding: 16rpx 0;
background: linear-gradient(135deg, #4b8eff 0%, #3784fb 100%);
border-radius: 12rpx;
text-align: center;
color: #fff;
font-size: 28rpx;
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;
}
// 编码检索按钮特殊样式
&.search-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));
box-shadow: none;
font-weight: 600;
letter-spacing: 1rpx;
&:active {
background: rgba(255, 152, 0, 0.15);
border-color: rgba(255, 152, 0, 0.6);
transform: translateY(1rpx);
}
}
}
// 编码列表样式
:deep(.uni-row) {
margin-bottom: 20rpx;
&:last-child {
margin-bottom: 0;
}
.uni-col-6 {
color: #8c8c8c;
font-size: 28rpx;
font-weight: 500;
}
.cont {
color: #262626;
font-size: 28rpx;
font-weight: 500;
line-height: 1.8;
}
}
// 输入框样式
:deep(.uni-easyinput__content) {
background-color: #f7f8fa;
border: 2rpx solid #e8e8e8;
border-radius: 12rpx;
height: 80rpx;
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;
color: #262626;
}
}
// 复选框样式
:deep(checkbox) {
.wx-checkbox-input {
width: 36rpx;
height: 36rpx;
border-radius: 8rpx;
border: 2rpx solid #e8e8e8;
background: transparent;
&.wx-checkbox-input-checked {
background: #3784fb;
border-color: #3784fb;
&::before {
font-size: 28rpx;
color: #fff;
}
}
&.wx-checkbox-input-disabled {
background: #f5f5f5;
border-color: #e8e8e8;
}
}
}
}
// 底部出库按钮
.outbound-btn {
// position: fixed;
// bottom: 40rpx;
// left: 50%;
// transform: translateX(-50%);
// width: 90%;
height: 88rpx;
background: linear-gradient(135deg, #4b8eff 0%, #3784fb 100%);
text-align: center;
line-height: 88rpx;
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;
}
}
}
// 加载提示文字
.loading-text {
text-align: center;
font-size: 26rpx;
color: #8c8c8c;
padding: 32rpx 0;
letter-spacing: 1rpx;
}
.form-section {
background: #fff;
border-radius: 20rpx;
margin-bottom: 24rpx;
overflow: hidden;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.06);
// 头部样式
.section-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 24rpx 32rpx;
background: #fff;
cursor: pointer;
transition: all 0.3s ease;
&:active {
background: #f7f8fa;
}
.title {
font-size: 32rpx;
font-weight: 600;
color: #262626;
}
.toggle-icon {
font-size: 40rpx;
color: #8c8c8c;
transform: rotate(90deg);
transition: transform 0.3s ease;
display: inline-block;
&.is-expanded {
transform: rotate(-90deg);
}
}
}
// 表单内容区域
.form-content {
max-height: 0;
overflow: hidden;
transition: max-height 0.3s ease-out;
&.is-expanded {
max-height: 1000rpx; // 根据实际内容调整
}
:deep(.uni-forms) {
padding: 0 32rpx 32rpx;
}
:deep(.uni-forms-item) {
margin-bottom: 24rpx;
&:last-child {
margin-bottom: 0;
}
.uni-forms-item__label {
color: #8c8c8c;
}
.form-view {
color: #262626;
font-size: 28rpx;
}
}
}
}
</style>