现场维修

This commit is contained in:
bb_pan 2025-10-28 14:50:33 +08:00
parent 17cd908656
commit ec74c9bd2f
9 changed files with 1795 additions and 578 deletions

View File

@ -117,7 +117,7 @@ export default {
},
findNodeById(list, id) {
for (const item of list) {
if (item[this.defaultProps.id] === id) {
if (item[this.defaultProps.id] == id) {
return item
}
const children = item[this.defaultProps.children]

View File

@ -801,6 +801,12 @@
"navigationBarTitleText": "现场维修详情"
}
},
{
"path": "pages/repair/fieldMaintenance/detailList",
"style": {
"navigationBarTitleText": "现场维修详情"
}
},
{
"path": "pages/repair/fieldMaintenance/fieldCode",
"style": {

View File

@ -2,17 +2,22 @@
<view class="accept page-common">
<div class="card">
<uni-row :gutter="24">
<uni-col :span="6">
<uni-col :span="24">
<view class="coding-btn" @tap="codeScan">二维码识别</view>
</uni-col>
<uni-col :span="24" style="display: flex;">
<uni-easyinput v-model="maCode" maxlength="99" placeholder="请输入设备编码" />
<view class="coding-btn" @tap="maCodeScan" style="margin-left: 8px; width: 66px;">编码识别</view>
</uni-col>
</uni-row>
</div>
<div class="card">
<uni-forms :modelValue="formData" label-width="170rpx" :border="true">
<uni-forms :modelValue="formData" label-width="205rpx" :border="true">
<uni-forms-item label="单位名称:" name="unitId" required>
<eselect
style="width: 100%; height: 90rpx"
ref="treeSelect"
:value="unitId"
:options="unitList"
@change="getProject"
@clear="clearUnit"
@ -22,16 +27,17 @@
<eselect
style="width: 100%; height: 90rpx"
ref="treeSelect2"
:value="proId"
:options="proList"
@change="changePro"
@clear="clearPro"
></eselect>
</uni-forms-item>
<uni-forms-item label="现负责人:" name="fieldPerson" required>
<uni-forms-item label="现负责人:" name="fieldPerson" required>
<uni-easyinput v-model="fieldPerson" maxlength="10" placeholder="请输入现场负责人名称" />
</uni-forms-item>
<uni-forms-item label="联系电话:" name="phone" required>
<uni-easyinput v-model="phone" maxlength="11" placeholder="请输入联系电话" />
<uni-easyinput type="number" v-model="phone" maxlength="11" placeholder="请输入联系电话" @change="isPhone" />
</uni-forms-item>
</uni-forms>
</div>
@ -57,7 +63,7 @@ import {
insert,
getAgreementInfoById,
} from '@/services/fieldMaintenance/fieldMaintenance.js'
import { getMachineByQrCodeApi } from '../../../services/back.js'
import { getMachineByCodeApi, getMachine } from '@/services/back.js'
import eselect from '@/components/tree-select/eselect.vue'
import ScanQrCode from '@/pages/devicesSearch/ScanQrCode.vue'
@ -72,7 +78,47 @@ const proList = ref([])
const fieldPerson = ref('')
const phone = ref('')
const qrCode = ref('')
const maInfo = ref({}) //
const maCode = ref('')
//
const phoneReg = /^1[3-9]\d{9}$/
const isPhone = () => {
console.log('🚀 ~ isPhone ~ phoneReg.test(phone.value):', phone.value , phoneReg.test(phone.value))
if (!phoneReg.test(phone.value)) {
uni.showToast({
icon: 'none',
title: '请输入正确的手机号',
})
phone.value = ''
}
}
//
const maCodeScan = async() => {
if (!maCode.value) {
uni.showToast({
title: '请输入编码',
icon: 'none',
})
return
}
unitId.value = ''
proId.value = ''
try {
const res = await getMachineByCodeApi({ maCode: maCode.value })
console.log('🚀 ~ maCodeScan ~ res:', res)
if (res.data) {
unitId.value = res.data.unitId
proId.value = res.data.proId
if (unitId.value && proId.value) {
getAgreement()
}
} else {
uni.showToast({ title: '未查询到该编码数据', icon: 'none' })
}
} catch (error) {
console.log('🚀 ~ maCodeScan ~ error:', error)
}
}
//
const handleScanSuccess = (result) => {
qrCode.value = result?.data?.split('?qrcode=')[1] || result?.data
@ -93,13 +139,18 @@ const getMaInfoScan = async () => {
let param = {
qrCode: qrCode.value,
}
unitId.value = ''
proId.value = ''
//
const res = await getMachineByQrCodeApi(param)
const res = await getMachine(param)
console.log(res)
if (res.code == 200) {
if (res.data.length > 0) {
unitId.value = res.data[0].unitId
proId.value = res.data[0].proId
if (unitId.value && proId.value) {
getAgreement()
}
} else {
uni.showToast({ title: '扫码二维码未绑定设备编码!', icon: 'none' })
}
@ -108,8 +159,10 @@ const getMaInfoScan = async () => {
}
}
const codeScan = async () => {
qrCode.value = ''
// qrCode.value = '202304-00847'
// getMaInfoScan()
qrCode.value = ''
if (scanQrCodeRef.value) {
scanQrCodeRef.value.scanQrCode()
}
@ -282,6 +335,7 @@ onLoad((options) => {
font-weight: 600;
box-shadow: 0 6rpx 20rpx rgba(55, 132, 251, 0.2);
transition: all 0.3s ease;
margin-bottom: 20rpx;
&:active {
transform: scale(0.98);

View File

@ -32,7 +32,7 @@
</div>
<view class="line"></view>
<template v-for="field in fieldMap" :key="field.label">
<uni-row :gutter="24">
<uni-row :gutter="24" @click="handleDetails(table)">
<uni-col :span="field.labelSpan">{{ field.label }}</uni-col>
<uni-col :span="field.valueSpan">
<view class="cont">
@ -83,9 +83,23 @@
valueSpan: 18,
default: '未填写'
},
{
label: '',
key: 'maId',
labelSpan: 0,
valueSpan: 0,
default: 0
},
{
label: '',
key: 'taskId',
labelSpan: 0,
valueSpan: 0,
default: 0
},
{
label: '维修数量',
key: 'preNum',
key: 'repairNum',
labelSpan: 6,
valueSpan: 18,
default: 0
@ -167,7 +181,8 @@
//
deleteFieldApplyDetailsById({
parentId: item.parentId,
typeId: item.typeId
typeId: item.typeId,
taskId: item.taskId
}).then(res => {
console.log(res)
if (res.code == 200) {
@ -203,6 +218,12 @@
tableList.value = res.data.rows
})
}
const handleDetails = (item) => {
console.log('🚀 ~ handleDetails ~ item:', item)
uni.navigateTo({
url: `/pages/repair/fieldMaintenance/detailList?item=${JSON.stringify(item)}`
})
}
onShow(() => {
tableList.value = []

View File

@ -0,0 +1,421 @@
<template>
<view class="page-container">
<!-- 列表区域 -->
<scroll-view scroll-y class="scroll-container">
<view v-for="(table, index) in tableList" :key="index" class="table-list-item">
<div class="title">
<div class="title-left">
<span class="code">{{ table.typeName }} - {{ table.typeModelName }}</span>
</div>
</div>
<view class="line"></view>
<template v-for="field in fieldMap" :key="field.label">
<uni-row :gutter="24">
<uni-col :span="field.labelSpan">{{ field.label }}</uni-col>
<uni-col :span="field.valueSpan">
<view class="cont">
{{
field.formatter
? field.formatter(table[field.key])
: table[field.key] ?? field.default ?? '无'
}}
</view>
</uni-col>
</uni-row>
</template>
</view>
<view class="loading-text">{{ '没有更多数据了~' }}</view>
</scroll-view>
</view>
</template>
<script setup>
import { ref, computed } from 'vue'
import { getDetailsInfoApi } from '@/services/fieldMaintenance/fieldMaintenance.js'
import { onLoad, onShow } from '@dcloudio/uni-app'
const opts = ref({})
const tableList = ref([])
const fieldMap = [
{
label: '设备编码',
key: 'maCode',
labelSpan: 6,
valueSpan: 18,
default: '-',
},
{
label: '配件数量',
key: 'partNum',
labelSpan: 6,
valueSpan: 18,
default: 0,
},
{
label: '配件名称',
key: 'partName',
labelSpan: 6,
valueSpan: 18,
default: '-',
},
{
label: '维修内容',
key: 'repairContent',
labelSpan: 6,
valueSpan: 18,
default: '-',
},
]
onLoad((options) => {
opts.value = JSON.parse(options.item)
if (opts.value.manageType == 1) {
fieldMap.splice(0, 1)
}
})
const getTableList = async () => {
try {
const res = await getDetailsInfoApi({
taskId: opts.value.taskId,
typeId: opts.value.typeId,
maId: opts.value.maId,
})
console.log('🚀 ~ getTableList ~ res:', res)
tableList.value = res.data.partDetails
console.log('🚀 ~ getTableList ~ tableList.value:', tableList.value)
} catch (error) {}
}
onShow(() => {
tableList.value = []
getTableList()
})
</script>
<style lang="scss" scoped>
.title-left {
display: flex;
flex-direction: column;
.code {
font-size: 32rpx;
font-weight: 600;
color: #3784fb;
letter-spacing: 1rpx;
}
.sub-code {
font-size: 28rpx;
/* 比主code小一点 */
color: #8c8c8c;
/* 灰色更柔和 */
margin-top: 4rpx;
/* 与主code有一点间距 */
}
}
.status-tag {
display: flex;
align-items: center;
}
.page-container {
display: flex;
height: 100vh;
padding: 24rpx;
flex-direction: column;
background-color: #f7f8fa;
.complete-btn {
display: flex;
justify-content: center;
/* padding: 20rpx 24rpx;
background: #fff;
border-radius: 20rpx;
margin-bottom: 20rpx;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.05); */
.btn {
display: flex;
flex-direction: column;
align-items: center;
padding: 0 60rpx;
position: relative;
transition: all 0.3s ease;
span {
font-size: 32rpx;
color: #8c8c8c;
font-weight: 500;
&.active {
color: #3784fb;
font-weight: 600;
.second-active & {
color: #fa8c16;
}
}
}
.bt-line {
width: 32rpx;
height: 6rpx;
background: #3784fb;
margin-top: 12rpx;
border-radius: 6rpx;
transition: all 0.3s ease;
.second-active & {
background: #fa8c16;
}
}
}
}
.search-form {
display: flex;
align-items: center;
padding: 20rpx;
/* background: #fff;
border-radius: 20rpx;
margin-bottom: 20rpx;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.05); */
:deep(.uni-easyinput__content),
:deep(.uni-date-editor) {
background-color: #f7f8fa;
border: 2rpx solid #e8e8e8;
border-radius: 12rpx;
height: 75rpx;
transition: all 0.3s ease;
&:focus-within {
border-color: #3784fb;
box-shadow: 0 0 0 2rpx rgba(55, 132, 251, 0.1);
}
}
:deep(.uni-date) {
width: 100%;
.uni-date-x {
width: 100%;
}
.uni-date-editor--x {
width: 100%;
}
.uni-date-range--x {
width: 100%;
.uni-date-range--x-input {
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 24rpx;
.uni-date-range--x-text {
font-size: 28rpx;
color: #262626;
}
}
}
.uni-date-x--border {
width: 100%;
border: 2rpx solid #e8e8e8;
border-radius: 12rpx;
background-color: #f7f8fa;
height: 80rpx;
transition: all 0.3s ease;
&:focus-within {
border-color: #3784fb;
box-shadow: 0 0 0 2rpx rgba(55, 132, 251, 0.1);
}
}
}
:deep(.uni-date-editor) {
.uni-date-range {
display: flex;
align-items: center;
width: 100%;
.uni-date-range--text {
width: 50%;
text-align: center;
color: #333;
}
}
}
}
.search {
height: 60rpx;
background: linear-gradient(135deg, #4b8eff 0%, #3784fb 100%);
text-align: center;
line-height: 60rpx;
color: #fff;
border-radius: 12rpx;
font-size: 28rpx;
font-weight: 600;
box-shadow: 0 6rpx 20rpx rgba(55, 132, 251, 0.2);
transition: all 0.3s ease;
&:active {
transform: translateY(2rpx);
opacity: 0.9;
}
}
.add {
height: 60rpx;
background: linear-gradient(135deg, #00aa00 0%, #00aa7f 100%);
text-align: center;
line-height: 60rpx;
color: #fff;
border-radius: 12rpx;
font-size: 28rpx;
font-weight: 600;
box-shadow: 0 6rpx 20rpx rgba(55, 132, 251, 0.2);
transition: all 0.3s ease;
&:active {
transform: translateY(2rpx);
opacity: 0.9;
}
}
.scroll-container {
padding: 0 2rpx;
.table-list-item {
margin: 24rpx 0;
padding: 32rpx;
background-color: #fff;
min-height: 300rpx;
border-radius: 20rpx;
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.06);
transition: all 0.3s ease;
&:active {
transform: scale(0.985);
background-color: #fafbfc;
}
.title {
display: flex;
justify-content: space-between;
align-items: center;
// margin-bottom: 20rpx;
.title-left {
.code {
font-size: 32rpx;
font-weight: 300;
color: #3784fb;
letter-spacing: 1rpx;
}
}
span.status {
padding: 8rpx 28rpx;
border-radius: 8rpx;
font-size: 26rpx;
font-weight: 600;
&.completed {
background-color: rgba(82, 196, 26, 0.1);
color: #52c41a;
}
&.pending {
background-color: rgba(250, 140, 22, 0.1);
color: #fa8c16;
}
}
}
.line {
margin: 24rpx 0;
height: 2rpx;
background: linear-gradient(
90deg,
rgba(232, 232, 232, 0) 0%,
rgba(232, 232, 232, 1) 50%,
rgba(232, 232, 232, 0) 100%
);
}
:deep(.uni-row) {
/* margin-bottom: 20rpx; */
.uni-col-6 {
color: #8c8c8c;
font-size: 28rpx;
font-weight: 500;
}
}
.cont {
display: flex;
justify-content: flex-end;
line-height: 1.8;
color: #262626;
font-size: 28rpx;
font-weight: 500;
}
}
}
.loading-text {
text-align: center;
font-size: 26rpx;
color: #8c8c8c;
padding: 32rpx 0;
letter-spacing: 1rpx;
}
}
//
:deep(.uni-swipe_action) {
border-radius: 20rpx;
overflow: hidden;
.uni-swipe_content {
margin: 0 !important;
padding: 0;
background-color: #fff;
}
.uni-swipe_button-group {
height: 100%;
.uni-swipe_button {
writing-mode: vertical-rl;
padding: 0 24rpx;
font-size: 28rpx !important;
font-weight: 600;
//
&:nth-child(1) {
background: linear-gradient(to bottom, #3ad980, #34c759) !important;
}
//
&:nth-child(2) {
background: linear-gradient(to bottom, #3b95ff, #007aff) !important;
}
&:active {
opacity: 0.85;
}
}
}
}
</style>

File diff suppressed because it is too large Load Diff

View File

@ -4,24 +4,24 @@
<div class="card-container">
<div class="card-header" @click="toggleCollapse">
<span class="title">任务信息</span>
<span style="color: #007AFF">{{ collapsed ? '展开' : '收起' }}</span>
<span style="color: #007aff">{{ collapsed ? '展开' : '收起' }}</span>
</div>
<view v-show="!collapsed">
<uni-forms :model="item" label-width="170rpx" :border="true">
<uni-forms-item label="单位" name="unitName">
<uni-forms :model="item" label-width="190rpx" :border="true">
<uni-forms-item label="单位名称" name="unitName">
<span class="form-item">{{ item.unitName }}</span>
</uni-forms-item>
<uni-forms-item label="工程" name="proName">
<uni-forms-item label="工程名称" name="proName">
<span class="form-item">{{ item.proName }}</span>
</uni-forms-item>
<uni-forms-item label="单号:" name="code">
<span class="form-item">{{ item.code }}</span>
</uni-forms-item>
<uni-forms-item label="" name="fieldPerson">
<uni-forms-item label="现场负责人:" name="fieldPerson">
<span class="form-item">{{ item.fieldPerson }}</span>
</uni-forms-item>
<uni-forms-item label="电话:" name="phone">
<uni-forms-item label="联系电话:" name="phone">
<span class="form-item">{{ item.phone }}</span>
</uni-forms-item>
</uni-forms>
@ -34,35 +34,42 @@
<span class="title">维修物资</span>
</div>
<div class="select-area">
<uni-row :gutter="24" style="display: flex; align-items: center">
<uni-col :span="10">
<uni-row :gutter="24" style="display: flex; align-items: center; padding-top: 10px">
<uni-col :span="12">
<view>
<uni-data-select v-model="typeId" placeholder="请选择物资类型" :localdata="maTypeSelectList"
@change="getMaCode" filterable>
<uni-data-select
v-model="typeId"
placeholder="请选择物资类型"
:localdata="maTypeSelectList"
@change="getMaCode"
filterable
>
</uni-data-select>
</view>
</uni-col>
<uni-col :span="10">
<uni-col :span="12">
<view>
<uni-data-select v-model="typeCode" placeholder="请选择规格型号"
:localdata="maCodeSelectList"
@change="selectMaCode">
<uni-data-select
v-model="typeCode"
placeholder="请选择规格型号"
:localdata="maCodeSelectList"
@change="selectMaCode"
>
</uni-data-select>
</view>
</uni-col>
</uni-row>
</div>
<scroll-view scroll-y class="scroll-container" @scrolltolower="onScrollTolower">
<scroll-view scroll-y class="scroll-container">
<view v-for="(item, index) in typeList" :key="index" class="table-list-item">
<div class="title">
<div class="title-left">
<span class="code">{{ item.materialName }}</span>
</div>
<div class="status-tag">
<view @click.stop="deleteItem(item)" style="padding-right: 10rpx;">
<view @click.stop="deleteItem(item)" style="padding-right: 10rpx">
<uni-icons type="trash" size="24" color="#ff0000" />
</view>
</div>
</div>
<view class="line"></view>
@ -71,29 +78,106 @@
<uni-col :span="field.labelSpan">{{ field.label }}</uni-col>
<uni-col :span="field.valueSpan">
<view class="cont">
{{ field.formatter ? field.formatter(item[field.key]) : (item[field.key] ?? field.default ?? '无')
{{
field.formatter
? field.formatter(item[field.key])
: item[field.key] ?? field.default ?? '无'
}}
</view>
</uni-col>
</uni-row>
</template>
<uni-row :gutter="24" style="padding-top: 12px">
<uni-col :span="8">是否收费</uni-col>
<uni-col :span="8">维修数量</uni-col>
<uni-col :span="16">
<view class="cont">
<uni-data-select v-model="item.charge" placeholder="请选择规格型号" :localdata="charge"
@change="selectMaCode">
</uni-data-select>
<uni-easyinput
v-model="item.repairNum"
placeholder="请填写维修数量"
type="number"
:clearable="false"
@change="repairNumChange(item, index)"
/>
</view>
</uni-col>
</uni-row>
<div v-for="(childItem, childIndex) in item.partDetails" :key="childIndex">
<uni-row :gutter="24" style="padding-top: 12px">
<uni-col :span="8">配件名称</uni-col>
<uni-col :span="16">
<treeSelect
style="width: 100%; height: 90rpx"
:ref="
(el) => {
if (el) treeSelectRef[childIndex] = el
}
"
:options="partTreeData"
v-model="childItem.partId"
@change="(val) => partTreeChange(val, index, childIndex)"
@clear="clearPart(index, childIndex)"
:defaultProps="defaultProps"
></treeSelect>
</uni-col>
</uni-row>
<uni-row :gutter="24" style="padding-top: 12px">
<uni-col :span="8">配件数量</uni-col>
<uni-col :span="16">
<uni-easyinput
placeholder="配件数量"
v-model="childItem.partNum"
type="number"
:clearable="false"
/>
</uni-col>
</uni-row>
<uni-row :gutter="24" style="padding-top: 12px">
<uni-col :span="8">是否收费</uni-col>
<uni-col :span="16">
<div style="width: 100%; display: flex">
<uni-data-select
:localdata="charge"
v-model="childItem.partType"
placeholder="请选择是否收费"
/>
<div class="operation-btns">
<span class="add" @click="addPart(index)">+</span>
<span class="remove" @click="delPart(index, childIndex)"
>-</span
>
</div>
</div>
</uni-col>
</uni-row>
<uni-row :gutter="24" style="padding-top: 12px">
<uni-col :span="8">维修内容</uni-col>
<uni-col :span="16">
<view class="cont">
<uni-easyinput
v-model="childItem.repairContent"
placeholder="请填写维修内容"
:clearable="false"
/>
</view>
</uni-col>
</uni-row>
</div>
<uni-row :gutter="24" style="padding-top: 12px">
<uni-col :span="8">配件数量</uni-col>
<uni-col :span="8">附件</uni-col>
<uni-col :span="16">
<view class="cont">
<uni-easyinput type="number" v-model="item.preNum" @input="onChangeNumber(item)"
placeholder="输入数值" style="flex: 1;" />
</view>
<div class="upload" @click="uploadImg('part', index)" v-if="!item.partImgUrl">
+
</div>
<div class="upload" @click="uploadImg('part', index)" v-else>
<image
:src="item.partImgUrl"
style="width: 160rpx; height: 160rpx"
mode=""
></image>
</div>
<PreviewImg v-if="item.partImgUrl" :imgUrl="item.partImgUrl" />
</uni-col>
</uni-row>
</view>
@ -108,38 +192,38 @@
</template>
<script setup>
import {
ref,
reactive,
} from 'vue'
import {
onLoad,
} from '@dcloudio/uni-app'
import {
getUseType,
insertDetails,
} from '@/services/fieldMaintenance/fieldMaintenance.js'
import { ref, reactive } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import { getUseType, insertDetails } from '@/services/fieldMaintenance/fieldMaintenance'
import { partTypeTreeList } from '@/services/repair/repair'
import treeSelect from '@/pages/repair/tree-select/tselectTwo'
import PreviewImg from '@/components/PreviewImg/index.vue'
import { decryptWithSM4 } from '@/utils/sm'
const maCodeSelectList = ref([])
const charge = ref([{
value: 1,
text: '是',
}, {
value: 0,
text: '否',
}])
const charge = ref([
{
value: 1,
text: '是',
},
{
value: 0,
text: '否',
},
])
const maTypeSelectList = ref([])
const item = ref({})
const typeId = ref('') //
const typeCode = ref('') //
const collapsed = ref(true)
const typeList = ref([])
const fieldMap = [{
label: '规格型号',
key: 'typeName',
labelSpan: 8,
valueSpan: 16,
},
const fieldMap = [
{
label: '规格型号',
key: 'typeName',
labelSpan: 8,
valueSpan: 16,
},
{
label: '在用数',
key: 'num',
@ -147,110 +231,253 @@ const fieldMap = [{
valueSpan: 16,
},
]
const partImgUrl = ref('')
const fileInfoList = ref([])
const getMaType = () => {
let obj = {
'agreementId': item.value.agreementId,
agreementId: item.value.agreementId,
}
getUseType(obj).then(res => {
console.log(res)
maTypeSelectList.value = res.data.map(option => {
return {
value: option.typeId,
text: option.typeName,
}
getUseType(obj)
.then((res) => {
console.log(res)
maTypeSelectList.value = res.data.map((option) => {
return {
value: option.typeId,
text: option.typeName,
}
})
})
.catch((error) => {
console.log(error)
})
}).catch(error => {
console.log(error)
})
}
//
const getMaCode = () => {
let obj = {
'agreementId': item.value.agreementId,
'typeId': typeId.value,
agreementId: item.value.agreementId,
typeId: typeId.value,
}
getUseType(obj).then(res => {
console.log(res)
maCodeSelectList.value = res.data.map(option => {
let obj = {
...option,
bmFileInfos: [],
value: option.typeId,
text: option.typeName,
}
return obj
getUseType(obj)
.then((res) => {
console.log(res)
maCodeSelectList.value = res.data.map((option) => {
let obj = {
...option,
bmFileInfos: [],
value: option.typeId,
text: option.typeName,
}
return obj
})
})
.catch((error) => {
console.log(error)
})
}).catch(error => {
console.log(error)
})
}
const generateUniqueId = () => {
return Date.now().toString(36) + Math.random().toString(36).substr(2, 5)
}
const deleteItem = (item) => {
typeList.value = typeList.value.filter(i => i.itemId !== item.itemId)
typeList.value = typeList.value.filter((i) => i.itemId !== item.itemId)
}
const repairNumChange = (item, index) => {
//
if (item.unitValue == 1) {
item.repairNum = Number(String(e).replace(/[^\d.]/g, '')).toFixed(3)
} else {
item.repairNum = Number(String(e).replace(/[^\d]/g, ''))
}
if (Number(item.repairNum) > Number(item.num)) {
uni.showToast({
title: '维修数量不能大于在用数量',
icon: 'none',
})
item.repairNum = item.num
}
}
//
const selectMaCode = (e) => {
const matched = maCodeSelectList.value.find(item => item.typeId == e)
const matched = maCodeSelectList.value.find((item) => item.typeId == e)
if (matched) {
const exists = typeList.value.some((item) => item.typeId === matched.typeId)
if (exists) {
uni.showToast({
title: '请勿重复添加',
icon: 'none',
})
return
}
const itemCopy = JSON.parse(JSON.stringify(matched))
itemCopy.itemId = generateUniqueId()
itemCopy.preNum = 0
itemCopy.charge = 0
itemCopy.taskId = item.value.id
itemCopy.repairNum = 0
itemCopy.taskId = item.value.taskId
itemCopy.id = item.value.id
itemCopy.partDetails = [{ partNum: 0, partType: 1, partId: '', repairContent: '' }]
typeList.value.push(itemCopy)
}
console.log(typeList.value)
}
const toggleCollapse = () => (collapsed.value = !collapsed.value)
const onChangeNumber = (item) => {
console.log(item)
let maxNum = Number(item.num)
// outboundNum.value
setTimeout(() => {
if (item.unitValue == 1) {
item.preNum = Number(String(item.preNum).replace(/[^\d.]/g, ''))
} else {
item.preNum = Number(String(item.preNum).replace(/[^\d]/g, ''))
}
if (Number(item.preNum) <= 0) {
item.preNum = 0
}
if (Number(item.preNum) > maxNum) {
uni.showToast({
title: '已达到当前资最大在用数量!',
icon: 'none',
})
item.preNum = maxNum
}
}, 500)
const addPart = (index) => {
console.log('🚀 ~ addPart ~ index:', index)
typeList.value[index].partDetails.push({
partNum: 0,
partType: 1,
partId: '',
repairContent: '',
})
console.log('🚀 ~ addPart ~ typeList.value[index]:', typeList.value[index])
}
const delPart = (index, childIndex) => {
if (typeList.value[index].partDetails.length > 1) {
typeList.value[index].partDetails.splice(childIndex, 1)
}
}
//
const partTreeData = ref([])
const defaultProps = ref({
id: 'id',
children: 'children',
label: 'label',
})
const getPartTreeData = async () => {
const res = await partTypeTreeList({})
partTreeData.value = res.data
}
//
const clearPart = (index, childIndex) => {
typeList.value[index].partDetails[childIndex].partId = ''
}
const treeSelectRef = ref([])
//
const partTreeChange = (val, index, childIndex) => {
const isHas = typeList.value[index].partDetails.findIndex((v) => v.partId === val.id)
if (isHas > -1) {
//
uni.showToast({
title: '不可选择相同的配件',
icon: 'none',
})
} else {
typeList.value[index].partDetails[childIndex].partId = val.id
typeList.value[index].partDetails[childIndex].partPrice = val.buyPrice
typeList.value[index].partDetails[childIndex].partNum = 0
}
}
//
const uploadImg = (item, index) => {
uni.showActionSheet({
itemList: ['拍照', '从相册选择'],
success: (res) => {
if (res.tapIndex === 0) {
getCameraFj(item, index)
} else if (res.tapIndex === 1) {
//
getPhotoFj(item, index)
}
},
fail: (err) => {
console.error('操作菜单选择失败:', err)
},
})
}
//
const getCameraFj = (item, index) => {
navigator.camera.getPicture((file) => onCameraSuccessFj(file, item, index), onCameraErrorFj, {
quality: 50,
destinationType: window.Camera.DestinationType.DATA_URL,
sourceType: window.Camera.PictureSourceType.CAMERA,
})
}
//
const getPhotoFj = (item, index) => {
navigator.camera.getPicture((file) => onCameraSuccessFj(file, item, index), onCameraErrorFj, {
quality: 50,
destinationType: window.Camera.DestinationType.DATA_URL,
sourceType: window.Camera.PictureSourceType.SAVEDPHOTOALBUM,
})
}
const onCameraErrorFj = (message) => {
console.log(message)
}
const onCameraSuccessFj = (file, item, index) => {
uploadSignUrlFj(file, item, index)
}
const uploadSignUrlFj = (file, item, index) => {
const base64Data = file
uni.request({
url: '/file/uploadBase64',
method: 'POST',
data: {
base64File: base64Data,
fileName: `${generateRandomString(10)}_${Date.now()}.png`,
fileType: 'image/png',
},
success: (uploadRes) => {
console.log('xxxxxxxxxx', uploadRes)
if (!uploadRes.data.code) {
uploadRes = JSON.parse(decryptWithSM4(uploadRes.data))
} else {
uploadRes = JSON.parse(uploadRes.data)
}
if (uploadRes.code && uploadRes.code == 200) {
let obj = {
name: uploadRes.data.name,
url: uploadRes.data.url,
}
if (item == 'part') {
typeList.value[index].fileInfoList = [obj]
typeList.value[index].partImgUrl = uploadRes.data.url
}
uni.showToast({ title: '上传成功', icon: 'none' })
} else {
uni.showToast({ title: '上传失败', icon: 'none' })
}
},
fail: (err) => {
console.error('上传失败', err)
uni.showToast({ title: '上传失败', icon: 'none' })
},
})
}
const submitNum = () => {
console.log(item)
const jsonData = JSON.stringify(typeList.value)
console.log(jsonData)
insertDetails(JSON.parse(jsonData)).then(res => {
if (res.code == 200) {
uni.showToast({ title: '编辑成功', icon: 'none' })
uni.navigateBack({
delta: 1, //
})
} else {
uni.showToast({ title: res.msg, icon: 'none' })
}
}).catch(error => {
console.log(error)
})
insertDetails(JSON.parse(jsonData))
.then((res) => {
if (res.code == 200) {
uni.showToast({ title: '操作成功', icon: 'none' })
uni.navigateBack({
delta: 1, //
})
} else {
uni.showToast({ title: res.msg, icon: 'none' })
}
})
.catch((error) => {
console.log(error)
})
}
onLoad((options) => {
item.value = JSON.parse(options.item)
getMaType()
getPartTreeData()
})
</script>
@ -393,10 +620,12 @@ onLoad((options) => {
.line {
margin: 24rpx 0;
height: 2rpx;
background: linear-gradient(90deg,
background: linear-gradient(
90deg,
rgba(232, 232, 232, 0) 0%,
rgba(232, 232, 232, 1) 50%,
rgba(232, 232, 232, 0) 100%);
rgba(232, 232, 232, 0) 100%
);
}
:deep(.uni-row) {
@ -472,4 +701,157 @@ onLoad((options) => {
}
}
}
.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;
margin-left: 10px;
&::before {
content: '';
position: absolute;
left: -10px;
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: 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-data-select {
.uni-select {
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);
}
}
}
}
}
.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);
}
}
}
.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;
}
}
</style>

View File

@ -74,6 +74,8 @@
<view class="loading-text">{{ finish ? '没有更多数据了~' : '正在加载...' }}</view>
</scroll-view>
</view>
<PopupConfirm ref="popupConfirm" :content="popContent" />
</template>
<script setup>
@ -88,12 +90,15 @@
submitTask
} from '@/services/fieldMaintenance/fieldMaintenance.js'
import {
onLoad
onShow
} from '@dcloudio/uni-app'
import {
debounce
} from 'lodash-es'
import PopupConfirm from '@/components/PopupConfirm'
const popupConfirm = ref()
const popContent = ref('')
const total = ref(0)
const active = ref(1)
const tableList = ref([])
@ -149,7 +154,11 @@
},
]
const submitItem = item => {
const submitItem = async item => {
popContent.value = '是否确定提交?'
const { data: confirm } = await popupConfirm.value.openPopup()
if (!confirm) return
submitTask({
taskId: item.taskId
}).then(res => {
@ -171,15 +180,18 @@
}
const deleteItem = item => {
uni.showModal({
title: '提示',
content: '确定要删除该条记录吗?',
confirmText: '删除',
cancelText: '取消',
success: res => {
if (res.confirm) {
//
const deleteItem = async item => {
popContent.value = '是否确定删除?'
const { data: confirm } = await popupConfirm.value.openPopup()
if (!confirm) return
// uni.showModal({
// title: '',
// content: '',
// confirmText: '',
// cancelText: '',
// success: res => {
// if (res.confirm) {
// //
deleteFieldApplyInfoById({
id: item.id,
taskId: item.taskId
@ -199,10 +211,10 @@
}).catch(error => {
console.log(error)
})
}
//
}
})
// }
// //
// }
// })
}
@ -249,7 +261,7 @@
}
}
onLoad(() => {
onShow(() => {
tableList.value = []
total.value = 0
getTableList(true)

View File

@ -118,4 +118,13 @@ export const insertDetails =(data) =>{
url: '/material/field_apply_info/insertDetails',
data: data,
})
}
// 现场维修详情
export const getDetailsInfoApi = (data) => {
return http({
method: 'GET',
url: '/material/field_apply_info/getDetailsInfo',
data,
})
}