Files
SmartParks_uniapp/pages/sys/workbench/inspection/inspectionOpt.vue
liyuanchao c7ff9a5234
Some checks failed
Uniapp 自动化打包 CI/CD / 打包 Uniapp 项目 (push) Has been cancelled
1.
2025-09-05 16:54:53 +08:00

573 lines
13 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="inspection-opt-container">
<view class="inspection-opt-lable"> 巡检人
<view class="inspection-opt-round" />
<text class="text">{{info.planInspectionPerson}}</text>
</view>
<view class="inspection-opt-lable"> 巡检位置
<text class="required">*</text>
</view>
<view class="inspection-opt-row">
<text class="text2">{{info.inspectionLocation}}</text>
<text v-if="!isSign" class="text3" @click="taskSignIn"> 签到</text>
</view>
<view class="inspection-opt-lable"> 巡检结果
<text class="required">*</text>
<view :class="info.inspectionResults == 1?'inspection-opt-round4':'inspection-opt-round2'"
@click="toggleInspectionResult(1)" />
<text class="text" @click="toggleInspectionResult(1)">正常</text>
<view :class="info.inspectionResults != 1?'inspection-opt-round3':'inspection-opt-round2'"
@click="toggleInspectionResult(0)" />
<text class="text" @click="toggleInspectionResult(0)"> 异常</text>
</view>
<view class="inspection-opt-lable"> 巡检描述
<text class="required">*</text>
</view>
<textarea type="text" v-model="info.remark" placeholder="请输入" class="input" />
<!-- 上传照片 -->
<view class="page">
<!-- 如果没有图片显示上传按钮 -->
<view class="custom-upload-btn" @click="chooseImage" v-if="!selectedImage">
<image class="image" src="/static/ic_camera.png"></image>
<text class="text">上传图片</text>
</view>
<!-- 已选图片预览 -->
<view class="preview-item" v-else>
<image class="preview-img" :src="selectedImage" mode="aspectFill" @click="previewImage"></image>
<view class="delete-btn" @click.stop="deletePic"></view>
</view>
</view>
<view v-if="info.inspectionResults != 1" class="inspection-opt-lable">报事报修</view>
<view v-if="info.inspectionResults != 1" class="repair-type" @click="chooseType">
<text class="text-type">{{ selectedType.orderTypeName }}</text>
<image class="right-arrow" src="/static/ic_right_arrow_g.png" />
</view>
<!-- 提交按钮 -->
<button class="inspection-opt-submit-btn"
@click="beforeSubmit">{{ info.inspectionResults == 1 ? '提交' : '生成工单提交' }}</button>
<!-- 弹窗 -->
<view class="custom-dialog" v-if="showDialog">
<image class="dialog-bg" src="/static/ic_dialog_01.png"></image>
<view class="dialog-content">
<text class="dialog-title">是否确定</text>
<text class="dialog-desc">转送确定生成工单编号</text>
<view class="dialog-btns">
<view class="btn-cancel" @click="closeDialog">下次再说</view>
<view class="btn-confirm" @click="confirmDialog">确认生成</view>
</view>
</view>
</view>
</view>
</template>
<script>
// 导入MediaSelector和MediaType
import MediaSelector, {
MediaType
} from '@/utils/mediaSelector';
import {
uploadFiles
} from '@/common/upload.js';
import toast from '../../../../uview-ui/libs/function/toast';
export default {
data() {
return {
info: {
inspectionResults: 1 // 默认选中"正常"
},
repairTypes: [],
selectedType: {},
selectedImage: '',
isSign: false,
showDialog: false // 控制弹窗显示
}
},
onLoad(options) {
if (options.item) {
try {
// 首先尝试解析原始字符串(可能未编码)
const item = JSON.parse(options.item);
this.info = item;
} catch (e) {
// 如果直接解析失败,再尝试解码后解析
try {
const item = JSON.parse(decodeURIComponent(options.item));
this.info = item;
} catch (e2) {
this.info = options.item;
}
}
this.isSign = this.info.actualSignState == 1
}
this.loadFilterData()
},
methods: {
async loadFilterData() {
let resType = await this.$u.api.getOrdersType();
if (resType.code === 200) {
this.repairTypes = [...this.repairTypes, ...resType.rows];
this.selectedType = this.repairTypes[0]
}
},
chooseImage() {
uni.chooseImage({
count: 1,
success: (res) => {
this.selectedImage = res.tempFilePaths[0]
}
})
},
// 预览图片
previewImage() {
uni.previewImage({
current: this.selectedImage,
urls: [this.selectedImage]
})
},
// 删除图片
deletePic(event) {
this.selectedImage = ''
},
// 切换巡检结果状态
toggleInspectionResult(result) {
// 使用$set确保响应式更新
this.$set(this.info, 'inspectionResults', result);
},
// 添加chooseType方法实现
chooseType() {
uni.showActionSheet({
itemList: this.repairTypes.map(item => item.orderTypeName),
success: (res) => {
this.selectedType = this.repairTypes[res.tapIndex];
},
fail: (err) => {
console.log('用户取消选择或出错', err);
}
});
},
beforeSubmit() {
// if(!this.isSign){
// uni.showToast({
// title: '请先签到',
// icon: 'none'
// });
// return
// }
if (this.info.inspectionResults == 1) {
// 直接提交
this.submit();
} else {
// 弹窗显示,生成工单提交
this.showDialog = true;
}
},
closeDialog() {
this.showDialog = false;
},
confirmDialog() {
this.showDialog = false;
// 生成工单提交
this.orderSubmig();
},
async taskSignIn() {
uni.scanCode({
success: async (scanRes) => {
// 使用扫码结果调用接口
let params = {
taskId: this.info.id,
qrCode: scanRes.result // 将扫码结果作为参数传递
};
if (scanRes.result == this.info.pointId) {
uni.showLoading({
title: '加载中...'
});
this.info.signType = 3
let res = await this.$u.api.taskSignIn(this.info);
// 隐藏loading
uni.hideLoading();
if (res.code == 200) {
this.isSign = true
uni.showToast({
title: '签到成功',
icon: 'none'
});
} else {
uni.showToast({
title: res.msg || '签到失败',
icon: 'none'
});
}
} else {
uni.showToast({
title: '当前签到巡检点不是目标点',
icon: 'none'
});
}
},
fail: (error) => {
// 扫码失败处理
// uni.showToast({
// title: '扫码失败,请重试',
// icon: 'none'
// });
}
});
},
async orderSubmig(){
this.info.orderTypeId = this.selectedType.id
uni.showLoading({
title: '工单提交中...'
});
let res = await this.$u.api.taskOrderSubmit(this.info);
uni.hideLoading();
if (res.code == 200) {
this.submit()
} else {
uni.showToast({
title: res.msg || '工单提交失败',
icon: 'none'
});
this.info.orderTypeId = ''
}
},
async submit() {
// 显示loading
uni.showLoading({
title: '提交中...'
});
if (!this.selectedImage) {
this.realSubmit()
return
}
const images = [];
images.push(this.selectedImage?.path?.replace('file://', '') || this.selectedImage);
if (images.length === 0) {
this.realSubmit();
return;
}
const result = await uploadFiles({
files: images,
url: this.vuex_config.baseUrl + '/resource/oss/upload',
name: 'file',
vm: this // 关键:用于注入 token 等
});
const allSuccess = result.every(item => item.code == 200);
if (!allSuccess) {
uni.showToast({
title: '上传失败',
icon: 'none'
});
// 隐藏loading
uni.hideLoading();
return;
}
// 遍历result获取data.url加上,分割
const urls = result.map(item => item.data?.url || '').filter(url => url !== '');
this.info.inspectionImage = urls.join(',');
this.realSubmit()
},
async realSubmit() {
let res = await this.$u.api.taskSubmit(this.info);
if (res.code == '200') {
// 关闭页面前发送事件通知前页面刷新
uni.$emit('refreshData', '');
// 返回上一页
uni.navigateBack();
}
// 隐藏loading
uni.hideLoading();
},
}
}
</script>
<style scoped>
.inspection-opt-container {
height: 100vh;
background: #fff;
display: flex;
flex-direction: column;
}
.inspection-opt-lable {
font-size: 32rpx;
color: #000000;
font-weight: 600;
display: flex;
flex-direction: row;
align-items: center;
margin-left: 40rpx;
margin-top: 45rpx;
}
.inspection-opt-row {
display: flex;
flex-direction: row;
align-items: center;
margin-left: 40rpx;
margin-right: 40rpx;
margin-top: 34rpx;
}
.required {
color: #DC9100;
margin-left: 10rpx;
}
.text {
color: #000000;
font-size: 24rpx;
margin-left: 10rpx;
font-weight: 400;
}
.text2 {
height: 73rpx;
flex: 1;
background: #F7F7F7;
border-radius: 10rpx;
display: flex;
align-items: center;
padding-left: 20rpx;
padding-right: 20rpx;
}
.text3 {
width: 88rpx;
height: 73rpx;
background: #296AEF;
border-radius: 10rpx;
color: #F7F7F7;
text-align: center;
margin-left: 18rpx;
line-height: 73rpx;
display: flex;
align-items: center;
justify-content: center;
}
.input {
height: 200rpx;
width: auto;
margin-left: 40rpx;
margin-right: 40rpx;
margin-top: 40rpx;
background: #F7F7F7;
border-radius: 10rpx;
font-size: 24rpx;
color: #000000;
padding: 15rpx;
}
.image {
width: 55rpx;
height: 42rpx;
}
.inspection-opt-round {
width: 34rpx;
height: 34rpx;
border-radius: 17rpx;
background: #3370FF;
margin-left: 35rpx;
}
.inspection-opt-round2 {
width: 34rpx;
height: 34rpx;
border-radius: 17rpx;
background: #fff;
margin-left: 24rpx;
border: 1rpx solid #3370FF;
}
.inspection-opt-round3 {
width: 34rpx;
height: 34rpx;
border-radius: 17rpx;
background: #F27A0F;
margin-left: 24rpx;
}
.inspection-opt-round4 {
width: 34rpx;
height: 34rpx;
border-radius: 17rpx;
background: #3370FF;
margin-left: 24rpx;
}
.custom-upload-btn {
width: auto;
margin-left: 40rpx;
margin-right: 40rpx;
margin-top: 24rpx;
height: 244rpx;
background: #f6f6f6;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
border-radius: 16rpx;
}
.preview-item {
position: relative;
width: auto;
/* 宽度自动 */
margin-left: 40rpx;
margin-right: 40rpx;
height: 244rpx;
margin-top: 24rpx;
/* 固定高度 */
display: flex;
justify-content: center;
/* 水平居中 */
align-items: center;
/* 垂直居中 */
overflow: hidden;
/* 裁剪超出部分 */
border-radius: 10rpx;
/* 可选:圆角 */
}
.delete-btn {
position: absolute;
top: 0;
right: 0;
width: 40rpx;
height: 40rpx;
line-height: 40rpx;
text-align: center;
border-radius: 50%;
background: rgba(0, 0, 0, 0.6);
color: #fff;
font-size: 24rpx;
}
/* 隐藏自带按钮 */
::v-deep .u-upload__wrap__add {
display: none !important;
}
.inspection-opt-submit-btn {
width: 60vw;
height: 73rpx;
background: linear-gradient(90deg, #005DE9 0%, #4B9BFF 100%);
color: #fff;
font-size: 32rpx;
border: none;
border-radius: 40rpx;
margin: 100rpx auto 0 auto;
display: block;
font-weight: bold;
box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.18);
}
/* 弹窗遮罩 */
.custom-dialog {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background: rgba(0, 0, 0, 0.3);
display: flex;
justify-content: center;
align-items: center;
z-index: 999;
}
/* 弹窗背景图 */
.dialog-bg {
position: absolute;
width: 656rpx;
height: 560rpx;
border-radius: 16rpx;
}
/* 弹窗内容覆盖在图片上 */
.dialog-content {
position: relative;
width: 80vw;
margin-top: 220rpx;
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
z-index: 10;
}
.dialog-title {
font-size: 42rpx;
font-weight: bold;
color: #000;
margin-bottom: 40rpx;
}
.dialog-desc {
font-size: 26rpx;
color: #666;
margin-bottom: 100rpx;
}
.dialog-btns {
display: flex;
width: 100%;
justify-content: space-around;
}
.btn-cancel,
.btn-confirm {
font-size: 36rpx;
}
.btn-cancel {
color: #333;
}
.btn-confirm {
color: #FF6B00;
}
.repair-type {
height: 98rpx;
background: #F7F8FA;
border-radius: 10rpx;
padding: 0 20rpx;
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 20rpx;
box-sizing: border-box;
margin-left: 40rpx;
margin-right: 40rpx;
margin-top: 20rpx;
}
.text-type {
font-size: 24rpx;
color: #808080;
}
.right-arrow {
width: 11rpx;
height: 21rpx;
}
</style>