Files
property-manager-side/wuye-manager-uniapp/pageSubPack/inspection/inspection_upload.vue
2026-05-28 11:52:50 +08:00

385 lines
10 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>
<view class="page_padding">
<view class="inspection_upload_box flex flex-col">
<view class="inspection_info_box">
<view class="inspection_title flex flex-between">
<view class="title flex">
<text class="line"></text>
<text>{{ info.villageName }} - {{ info.taskName }}</text>
</view>
<view class="status" v-if="!isComputed">
<text>未巡检</text>
</view>
</view>
<view class="inspection_item_info_box">
<view class="inspection_item">
<text>巡检项目:</text>
<text>{{ info.planName }}</text>
</view>
<view class="inspection_item">
<text>巡检时间:</text>
<text>07:00:00 - 09:00:00</text>
</view>
<view class="inspection_item">
<text>巡检小区:</text>
<text>{{ info.villageName }}</text>
</view>
<view class="" v-for="(item, index) in baseFormData" :key="index">
<view class="inspection_item">
<text>巡检路线:</text>
<text>{{ item.routeName }}</text>
</view>
<view class="inspection_item">
<text>巡检点:</text>
<text v-for="(ite, ind) in item.points" :key="ind">{{ ite.ponitName }};</text>
</view>
</view>
</view>
</view>
<view class="inspection_info_upload_box" v-if="baseFormData.length > 0">
<view class="inspection_routes" v-for="(item, index) in baseFormData" :key="index">
<view class="header">
<text>{{ item.routeName }} - 巡检结果</text>
</view>
<view class="info_body" v-for="(ite, ind) in item.points" :key="ind">
<view class="info_title" style="margin-bottom: 20rpx"> {{ ite.ponitName }} </view>
<uni-forms :modelValue="ite" :rules="rules" label-position="left" label-width="150">
<uni-forms-item label="巡检状态" required>
<uni-data-checkbox
:disabled="ite.complated"
v-model="ite.status"
:localdata="statuslist"
/>
</uni-forms-item>
<uni-forms-item label="巡检描述" v-if="!ite.complated">
<uni-easyinput
type="textarea"
:disabled="ite.complated"
:input-border="true"
v-model="ite.desition"
placeholder="请输入"
></uni-easyinput>
</uni-forms-item>
<view class="items_picker_box flex" style="align-items: baseline" v-else>
<view class="label"> 巡检描述 </view>
<view class="desitionbox flex-1">
<text class="desition">{{ ite.desition }}</text>
</view>
</view>
<view class="items_picker_box">
<view class="label">
<text v-if="info.inspectSetting === 1" class="is-required">*</text>
<text>巡检照片</text>
</view>
<view class="filePickerbox" v-if="!ite.complated">
<filePicker
v-model="ite.files"
:sourceType="['camera']"
file-field-name="file"
:extra-data="uploadParams"
uploadUrl="/resource/oss/upload"
@fail="onUploadFail"
></filePicker>
</view>
<view class="filePickerbox showimagegrid" v-else>
<image
class="img"
mode="scaleToFill"
v-for="(ite, ind) in ite.files"
lazy-load
:key="ind"
:src="ite"
@tap="previewImages(ite.files, index)"
></image>
</view>
</view>
</uni-forms>
<view class="submitbox" @tap="handleSubmit(ite)" v-if="!ite.complated">
<text>提交</text>
</view>
<view class="line" v-if="ind + 1 === baseFormData.length"> </view>
</view>
</view>
</view>
</view>
</view>
</template>
<script setup>
import { computed, ref } from 'vue'
import filePicker from '@/components/filePicker/filePicker.vue'
import { getInspectionMain } from '@/api/insepction.js'
import { onLoad } from '@dcloudio/uni-app'
import { putInsepctionPoint } from '@/api/insepction.js'
const statuslist = [
{
text: '正常',
value: 0
},
{
text: '异常',
value: 1
}
]
const taskid = ref('')
const baseFormData = ref([])
const info = ref({
planName: '',
remindTime: '',
routes: [],
taskId: '',
taskName: '',
taskTime: '',
villageName: ''
})
const rules = {
status: {
rules: [
{
required: true,
errorMessage: '巡检状态不能为空'
}
]
},
files: {
rules: [
{
required: true,
errorMessage: '巡检照片不能为空'
}
]
}
}
function init() {
if (!taskid.value) return
getInspectionMain(taskid.value)
.then(res => {
info.value = res.data
if (!res.data.routes) return
let result = res.data.routes
.map(item => {
if (!item.points || item.points.length <= 0) return false
const points = item.points.map(ite => {
return {
pointId: ite.pointId,
ponitName: ite.pointName,
status: ite.status ?? 0,
desition: ite.remark,
complated: ite.status !== null,
files: ite.imgUrl ? ite.imgUrl.split(',') : []
}
})
return {
routeName: item.routeName,
routeId: item.routeId,
description: item.description,
points: points
}
})
.filter(item => item !== false)
baseFormData.value = result
})
.catch(err => {
uni.showToast({
icon: 'error',
title: '网络异常'
})
})
}
onLoad(options => {
taskid.value = options.id
// taskid.value = '2044684785371725826'
init()
})
// ----------------------------------------------
const uploadParams = ref({})
function onUploadFail(e) {
console.log('上传失败', e)
}
/** 提交巡检点 检查情况 */
function handleSubmit(item) {
if (info.value.inspectSetting === 1) {
if (item.files.length <= 0) {
uni.showToast({
icon: 'error',
mask: true,
title: '必须拍照'
})
return
}
}
let obj = {
pointId: item.pointId,
imgUrl: item.files.length > 0 ? item.files.join(',') : '',
remark: item.desition,
status: item.status,
taskId: taskid.value
}
putInsepctionPoint(obj)
.then(res => {
item.complated = true
})
.catch(err => {
uni.showToast({
icon: 'error',
title: '网络错误'
})
})
}
const isComputed = computed(() => {
// 遍历每一项
return baseFormData.value.every(item => {
// 每一项里的所有 points 都必须是已完成
return item.points.every(point => point.complated)
})
})
/**
* 预览图片
* @param {Array} images - 所有图片的URL数组
* @param {Number} currentIndex - 当前点击的图片索引
*/
function previewImages(images, currentIndex) {
uni.previewImage({
urls: [
'https://picsum.photos/80',
'https://picsum.photos/80',
'https://picsum.photos/80',
'https://picsum.photos/80'
],
current: currentIndex
})
}
</script>
<style scoped lang="scss">
.is-required {
color: #dd524d;
font-weight: bold;
}
.inspection_upload_box {
background: #f9f9f9;
padding: 20rpx 40rpx;
position: relative;
flex: 1;
overflow: hidden;
box-sizing: border-box;
.inspection_info_box {
background-color: #ffffff;
padding: 20rpx 40rpx;
margin-bottom: 20rpx;
border-radius: 16rpx;
.inspection_title {
margin-bottom: 20rpx;
.title {
font-size: 32rpx;
color: #333333;
line-height: 40rpx;
height: 40rpx;
.line {
display: block;
width: 6rpx;
height: 28rpx;
background: #4d5dfa;
margin-right: 10rpx;
margin-top: 6rpx;
}
}
.status {
font-weight: 400;
font-size: 28rpx;
color: #4d5dfa;
line-height: 36rpx;
}
}
.inspection_item_info_box {
width: 100%;
.inspection_item {
margin-bottom: 20rpx;
font-weight: 400;
font-size: 28rpx;
color: #333333;
line-height: 36rpx;
}
}
}
.inspection_info_upload_box {
border-radius: 16rpx;
background-color: #fff;
padding: 30rpx 40rpx;
flex: 1;
box-sizing: border-box;
overflow: hidden;
overflow-y: auto;
.header {
font-weight: 500;
font-size: 32rpx;
color: #222222;
line-height: 40rpx;
margin-bottom: 20rpx;
}
.info_body {
margin-bottom: 40rpx;
.desitionbox {
.desition {
font-size: small;
color: #ccc;
line-height: 1;
letter-spacing: 1px;
}
}
}
.info_title {
font-weight: 550;
}
.line {
width: 100%;
margin-top: 40rpx;
margin-bottom: 40rpx;
border: 1rpx dashed #ccc;
}
.items_picker_box {
.label {
text-align: left;
font-size: 14px;
color: #606266;
height: 36px;
padding: 0 12px 0 0;
vertical-align: middle;
box-sizing: border-box;
}
.showimagegrid {
display: grid;
grid-template-columns: repeat(3, 1fr);
& > .img:not(:last-child) {
margin-right: 20rpx;
}
width: 100%;
.img {
width: 160rpx;
height: 160rpx;
}
}
}
}
.submitbox {
height: 80rpx;
background: #4d5dfa;
border-radius: 8rpx 8rpx 8rpx 8rpx;
text-align: center;
font-weight: 400;
font-size: 28rpx;
color: #ffffff;
line-height: 80rpx;
margin-top: 40rpx;
}
}
</style>