退料、维修功能修改

This commit is contained in:
hayu 2025-06-12 10:03:26 +08:00
parent 756aacbeb2
commit 7ea3ed0d14
1 changed files with 690 additions and 0 deletions

View File

@ -0,0 +1,690 @@
<template>
<!-- 数量出库 -->
<view class="page-container">
<view class="table-list-item">
<uni-row :gutter="24">
<uni-col :span="6">物资名称</uni-col>
<uni-col :span="18"
><view class="cont">{{ queryParams.typeName }}</view>
</uni-col>
</uni-row>
<uni-row :gutter="24">
<uni-col :span="6">物资类型</uni-col>
<uni-col :span="18"
><view class="cont">{{ queryParams.type }}</view>
</uni-col>
</uni-row>
<uni-row :gutter="24">
<uni-col :span="6">设备编码</uni-col>
<uni-col :span="18"
><view class="cont">{{ selectedCodesDisplay }}</view>
</uni-col>
</uni-row>
</view>
<uni-row
:gutter="24"
class="search-form"
style="background: #fff; padding: 10px; margin: 5px; border-radius: 5px"
>
<uni-col :span="6">
<view class="btnBox complete" @click="saveCode"> 维修完成 </view>
</uni-col>
</uni-row>
<scroll-view scroll-y style="padding-bottom: 20rpx">
<!-- -->
<view class="table-list-item">
<!-- 维修人员 -->
<h2 style="padding: 4rpx 0; font-weight: bold">维修信息</h2>
<uni-forms ref="baseForm" label-align="right">
<uni-forms-item label="维修人员">
<uni-data-select
:localdata="repairPersonData"
v-model="repairPerson"
placeholder="请选择维修人员"
/>
</uni-forms-item>
<uni-forms-item label="备注">
<uni-easyinput placeholder="请填写备注" maxlength="50" v-model="remark" />
</uni-forms-item>
<uni-forms-item label="附件">
<div class="upload" @click="uploadImg" v-if="imgBeseUrl == ''">+</div>
<div class="upload" @click="uploadImg" v-else>
<image
:src="imgBeseUrl"
style="width: 160rpx; height: 160rpx"
mode=""
></image>
</div>
</uni-forms-item>
</uni-forms>
</view>
<!-- 内部维修 -->
<view class="table-list-item" v-if="repairType == 1">
<h2 style="padding: 4rpx 0; font-weight: bold">内部维修</h2>
<uni-forms ref="baseForm" label-align="right">
<!-- <uni-forms-item label="维修数量">
<uni-easyinput placeholder="请填写维修数量" v-model="formLeft.repairNum"/>
</uni-forms-item> -->
<div v-for="(item, index) in partItems" :key="index">
<uni-forms-item label="配件类型">
<treeSelect
style="width: 100%; height: 90rpx"
ref="treeSelectRef"
:options="partTreeData"
@change="partTreeChange"
:index="index"
@clear="clearPart"
:defaultProps="defaultProps"
></treeSelect>
</uni-forms-item>
<uni-forms-item label="配件数量">
<uni-easyinput
placeholder="配件数量"
v-model="item.partNum"
type="number"
:clearable="false"
@input="partCheckNum(item)"
/>
</uni-forms-item>
<uni-forms-item label="是否收费">
<div style="width: 100%; display: flex">
<uni-data-select
:localdata="isChargeList"
v-model="item.partType"
placeholder="请选择是否收费"
:clear="false"
/>
<div class="operation-btns">
<span class="add" @click="addPart">+</span>
<span class="remove" @click="delPart(index)">-</span>
</div>
</div>
</uni-forms-item>
</div>
</uni-forms>
</view>
</scroll-view>
</view>
</template>
<script setup>
import { computed, ref, reactive } from 'vue'
import {
partTypeTreeList,
getSupplierList,
getRepairerListApi,
saveRepairRow,
getScrapReasonList,
} from '@/services/repair/repair.js'
import { baseURL } from '@/utils/http'
import treeSelect from '../tree-select/tselect.vue'
import { onLoad } from '@dcloudio/uni-app'
const queryParams = ref({})
const rowIndex = ref(-1)
//
const selectedCodesDisplay = computed(() => {
if (queryParams.value.selectedCodes && queryParams.value.selectedCodes.length > 0) {
//
const cleanCodes = queryParams.value.selectedCodes.map(code => {
//
if (typeof code === 'string') {
return code.replace(/^["']|["']$/g, '')
}
return String(code)
})
return cleanCodes.join(', ')
}
return ''
})
// onLoad((options) => {
// console.log(options)
// queryParams.value = JSON.parse(options.queryParams)
// rowIndex.value = options.rowIndex
// console.log(queryParams.value)
// getScrapReasonListData()
// })
onLoad((options) => {
queryParams.value = JSON.parse(decodeURIComponent(options.batchParams))
if (queryParams.value.selectedCodes) {
queryParams.value.selectedCodes = queryParams.value.selectedCodes.map(code => {
//
if (typeof code === 'string') {
return code.replace(/^["']|["']$/g, '')
}
return String(code)
})
}
console.log('批量维修参数:', queryParams.value)
console.log('选中的设备:', queryParams.value.selectedDevices)
console.log('选中的编码:', queryParams.value.selectedCodes)
})
const repairType = ref(1)
const changeTab = async (e) => {
repairType.value = e
}
const isChargeList = ref([
{ value: 1, text: '是' },
{ value: 0, text: '否' },
])
const { userInfo } = JSON.parse(uni.getStorageSync('member'))
// console.log('🚀 ~ userInfo:', userInfo)
//
const repairPersonData = ref([])
const repairPerson = ref('')
const getRepairerListData = async () => {
const res = await getRepairerListApi({})
console.log(res)
repairPersonData.value = res.data.map((item) => {
let obj = {
value: item.userId,
text: item.repairer,
}
return obj
})
// userInfo.userId repairPersonData.value ,
if (
repairPersonData.value &&
repairPersonData.value.findIndex((v) => v.value === userInfo.userId) > -1
) {
repairPerson.value = userInfo.userId
} else {
repairPerson.value = repairPersonData.value[0].value
}
}
getRepairerListData()
const remark = ref('') //
const imgBeseUrl = ref('') //
const bmFileInfos = ref([]) //
//
const uploadImg = () => {
uni.chooseImage({
count: 1, //
sizeType: ['original', 'compressed'], //original compressed
sourceType: ['album', 'camera'], //album camera 使
success: (res) => {
console.log(res)
let imgFiles = res.tempFilePaths //
imgBeseUrl.value = imgFiles[0]
// console.log('', baseURL+"/file/upload")
uni.uploadFile({
// url: baseURL+"/file/upload",//app
url: '/file/upload', //h5
filePath: imgFiles[0],
name: 'file',
success: (res) => {
res = JSON.parse(res.data)
console.log('上传成功', res)
if (res.code && res.code == 200) {
let obj = {
name: res.data.name,
url: res.data.url,
}
bmFileInfos.value = [obj]
console.log('上传成功', bmFileInfos.value)
uni.showToast({ title: '上传成功', icon: 'none' })
} else {
bmFileInfos.value = []
uni.showToast({ title: '上传失败', icon: 'none' })
}
},
fail: (err) => {
console.error('上传失败', err)
},
})
},
})
}
//
const partTreeData = ref([])
const defaultProps = ref({
id: 'id',
children: 'children',
label: 'label',
})
const getPartTreeData = async () => {
const res = await partTypeTreeList({})
partTreeData.value = res.data
}
getPartTreeData()
const treeSelectRef = ref([])
const clearPart = (index) => {
partItems.value[index].partId = ''
}
const partTreeChange = (val, index) => {
const isHas = partItems.value.findIndex((v) => v.partId === val.id)
if (isHas > -1) {
//
console.log(isHas)
uni.showToast({ title: '已存在该配件类型', icon: 'none' })
treeSelectRef.value[index].clearInput()
partItems.value[index].partId = ''
partItems.value[index].storageNum = ''
partItems.value[index].partNum = 0
} else {
partItems.value[index].partId = val.id
partItems.value[index].storageNum = val.storageNum
partItems.value[index].partNum = 0
}
}
//
const partItems = ref([{ partNum: '', partType: 0, partId: '', storageNum: '' }])
const addPart = () => {
partItems.value.push({ partNum: '', partType: 0, partId: '', storageNum: '' })
}
const delPart = (index) => {
if (partItems.value.length > 1) {
partItems.value.splice(index, 1)
}
}
const partIds = ref([])
const formLeft = ref({
// repairNum:0
})
const partItemsMiddle = ref([
{ partName: '', supplierId: '', partNum: 0, partPrice: 0, partType: 0 },
])
const addMidPart = () => {
partItemsMiddle.value.push({
partName: '',
supplierId: '',
partNum: 0,
partPrice: 0,
partType: 0,
})
}
const delMidPart = (index) => {
if (partItemsMiddle.value.length > 1) {
partItemsMiddle.value.splice(index, 1)
}
}
const formMiddle = ref({
// supplierId:undefined,
// repairNum:0
})
//
const formRight = ref({
// scrapNum:0,
scrapType: 0,
scrapId: null, // id
scrapReason: '', //
fileList: [],
})
const rowData = ref({})
// change
const partCheckNum = (item) => {
// console.log(item)
// console.log(item.partNum)
setTimeout(() => {
item.partNum = Number(String(item.partNum).replace(/[^\d.]/g, ''))
if (item.storageNum) {
// console.log(item.partNum)
// console.log(item.storageNum)
if (Number(item.partNum) >= Number(item.storageNum)) {
item.partNum = Number(item.storageNum)
}
}
}, 500)
}
// change
const costCheckNum = (item) => {
// console.log(item)
// console.log(item.partPrice)
setTimeout(() => {
item.partPrice = Number(String(item.partPrice).replace(/[^\d.]/g, ''))
}, 500)
}
//
const saveCode = () => {
if (repairType.value == 1) {
let index1 = partItems.value.findIndex((v) => v.partId == '')
let index2 = partItems.value.findIndex((v) => v.partNum == 0)
if (repairPerson.value == '') {
uni.showToast({ title: '请先选择维修人员!', icon: 'none' })
} else if (index1 > -1) {
uni.showToast({ title: '请先选择配件类型!', icon: 'none' })
} else if (index2 > -1) {
uni.showToast({ title: '请填写配件数量!', icon: 'none' })
} else {
saveCodeApi()
}
}
}
//
const saveCodeApi = async () => {
//
rowData.value = queryParams.value
//
for (let i = 0; i < rowData.value.repairDeviceList.length; i++) {
//
rowData.value.repairDeviceList[i].repairList = [
{
repairer: repairPerson.value,
remark: remark.value,
fileList: bmFileInfos.value,
},
]
//
if (!rowData.value.repairDeviceList[i].codeInRepairPartList) {
rowData.value.repairDeviceList[i].codeInRepairPartList = [];
}
//
for (let j = 0; j < partItems.value.length; j++) {
rowData.value.repairDeviceList[i].codeInRepairPartList.push({
partType: partItems.value[j].partType,
partId: partItems.value[j].partId,
partNum: partItems.value[j].partNum,
storageNum: partItems.value[j].storageNum,
})
}
// 1
rowData.value.repairDeviceList[i].repairType = 1;
}
console.log(rowData.value.repairDeviceList)
saveRepairRow(rowData.value.repairDeviceList).then(async (response) => {
if (response.code == 200) {
uni.showToast({ title: '保存成功', icon: 'none' })
uni.navigateBack({
delta: 2, //
})
}
})
}
</script>
<style lang="scss" scoped>
.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;
}
//
.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;
}
}
.page-container {
display: flex;
height: 100vh;
padding: 24rpx;
flex-direction: column;
background-color: #f7f8fa;
//
.table-list-item {
background-color: #fff;
border-radius: 20rpx;
padding: 24rpx;
margin-bottom: 24rpx;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.06);
//
h2 {
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;
}
}
//
.uni-row {
padding: 16rpx 0;
font-size: 28rpx;
border-bottom: 2rpx solid #f5f5f5;
&:last-child {
border-bottom: none;
}
.uni-col-6 {
color: #8c8c8c;
}
.cont {
color: #262626;
}
}
//
:deep(.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;
}
.uni-easyinput__content {
background-color: #f7f8fa;
border: 2rpx solid #e8e8e8;
border-radius: 12rpx;
height: 88rpx;
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-data-select {
.uni-select {
border: 2rpx solid #e8e8e8;
border-radius: 12rpx;
height: 88rpx;
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);
}
}
}
}
}
//
.search-form {
margin-bottom: 24rpx;
background: #fff !important;
border-radius: 20rpx !important;
padding: 24rpx !important;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.06);
.btnBox {
height: 88rpx;
line-height: 88rpx;
text-align: center;
color: #fff;
font-size: 28rpx;
font-weight: 600;
border-radius: 12rpx;
transition: all 0.3s ease;
box-shadow: 0 6rpx 20rpx rgba(55, 132, 251, 0.2);
&:active {
transform: scale(0.98);
opacity: 0.9;
}
//
&.internal {
background: linear-gradient(135deg, #2ecc71 0%, #27ae60 100%);
box-shadow: 0 6rpx 20rpx rgba(46, 204, 113, 0.2);
}
//
&.return {
background: linear-gradient(135deg, #f39c12 0%, #e67e22 100%);
box-shadow: 0 6rpx 20rpx rgba(243, 156, 18, 0.2);
}
//
&.scrap {
background: linear-gradient(135deg, #e74c3c 0%, #c0392b 100%);
box-shadow: 0 6rpx 20rpx rgba(231, 76, 60, 0.2);
}
//
&.complete {
background: linear-gradient(135deg, #3498db 0%, #2980b9 100%);
box-shadow: 0 6rpx 20rpx rgba(52, 152, 219, 0.2);
}
}
}
//
.operation-btns {
display: flex;
align-items: center;
gap: 16rpx;
margin-left: 24rpx;
span {
width: 48rpx;
height: 48rpx;
display: flex;
align-items: center;
justify-content: center;
border-radius: 8rpx;
font-size: 32rpx;
transition: all 0.3s ease;
&:active {
transform: scale(0.95);
opacity: 0.8;
}
//
&.add {
color: #2ecc71;
background-color: rgba(46, 204, 113, 0.1);
}
//
&.remove {
color: #e74c3c;
background-color: rgba(231, 76, 60, 0.1);
}
}
}
}
//
.loading-text {
text-align: center;
font-size: 28rpx;
color: #666;
padding: 20rpx 0;
}
.outbound-btn {
width: 70%;
margin: 25rpx auto;
height: 65rpx;
line-height: 65rpx;
text-align: center;
background-color: #19be6b;
border-radius: 12rpx;
color: #fff;
}
</style>