提交 9fb3bb44 authored 作者: BaoChunXian's avatar BaoChunXian

feat: 井道巡检异常时带出之前填写的情况摘要

上级 8c0d9459
<template>
<view v-if="isOpen" class="synchronous-dialog">
<view class="synchronous-content">
<!-- 巡检事项 -->
<view class="form-item">
<text class="form-label"
><text class="required">*</text>巡检事项:</text
>
<text>{{ inspectionItem }}</text>
</view>
<!-- 情况摘要(多选输入框) -->
<view class="form-item">
<text class="form-label"
><text class="required">*</text>情况摘要:</text
>
<textarea
v-model="summary"
placeholder="请输入情况摘要"
auto-height
class="input-box"
></textarea>
</view>
<!-- 固定词 -->
<view class="form-item last">
<text class="form-label"></text>
<view class="fixed-words">
<text
v-for="(word, index) in fixedWords"
:key="index"
class="word"
@click="selectWord(word)"
>
{{ word }}
</text>
</view>
</view>
<view class="row-item bottom-row">
<view class="button btn" @click="handleClose">取消</view>
<view class="button" @click="handleConfirm">确认</view>
</view>
</view>
</view>
</template>
<script>
export default {
props: {
// 父组件传递的巡检事项
inspectionItem: {
type: String,
default: "",
},
// 父组件传递的固定词
fixedWords: {
type: Array,
default: () => ["已检查", "正常", "异常", "需处理"],
},
},
data() {
return {
summary: "", // 情况摘要
isOpen: false,
};
},
methods: {
// 打开弹窗
open() {
this.isOpen = true;
},
// 关闭弹窗
close() {
this.isOpen = false;
},
// 选择固定词
selectWord(word) {
this.summary += word + " "; // 将选中的词添加到输入框
},
// 确认
handleConfirm() {
this.$emit("confirm", this.summary); // 将情况摘要回传给父组件
this.handleClose();
},
// 关闭弹窗
handleClose() {
this.summary = ""; // 清空输入框
this.close();
},
},
};
</script>
<style scoped lang="less">
.synchronous-dialog {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
z-index: 99999;
.synchronous-content {
padding: 3% 20px 32px 24px;
width: 400px;
height: 300px;
box-sizing: border-box;
background-image: linear-gradient(
-6deg,
#f9ffe7 0%,
#ffffff 12%,
#fcfeff 73%,
#ccf1ff 100%
);
border: 0.4px solid rgba(224, 224, 224, 1);
border-radius: 12px;
position: relative;
.row-item {
display: flex;
align-items: center;
justify-content: center;
}
.title {
font-family: PingFangSC-Medium;
font-size: 18px;
color: #000000;
text-align: center;
line-height: 26px;
font-weight: 500;
}
.count-num {
margin: 5% 0 5% 0;
align-items: flex-end;
.num {
display: inline-block;
font-family: AlibabaPuHuiTi_2_65_Medium;
font-size: 50px;
color: #3774f6;
line-height: 44px;
font-weight: 500;
}
}
.operating-instructions {
margin-bottom: 8%;
.title {
font-size: 13px;
color: #4a4a4a;
line-height: 24px;
font-weight: 600;
text-align: left;
}
.instructions-item {
font-size: 12px;
color: #7c7c7c;
line-height: 22px;
font-weight: 400;
}
}
// 打包按钮
.bottom-row {
position: absolute;
bottom: 24px;
left: 50%;
transform: translateX(-50%);
.button {
display: flex;
align-items: center;
justify-content: center;
background-image: linear-gradient(180deg, #3773f6 0%, #2c57f6 99%);
box-shadow: 0px 10px 24px 0px rgba(51, 104, 246, 0.24);
border-radius: 27px;
width: 128px;
height: 32px;
margin: 10px;
color: #fff;
&.btn {
background: #ffffff;
color: #000000;
}
}
}
// 关闭按钮
.close-button {
position: absolute;
bottom: -40px;
left: 50%;
transform: translateX(-50%);
.iconfont {
color: #fff;
font-size: 24px;
}
}
}
}
.form-item {
width: 100%;
display: flex;
align-items: center;
padding: 9.6px 0;
line-height: 28.8px;
border-bottom: 0.8px solid #f2f3f5;
&.last {
border: 0;
}
.fixed-words {
.word {
font-size: 11.2px;
margin-right: 4px;
padding: 4px 6px;
border: 1px solid #c7c7c7;
border-radius: 4px;
}
}
.form-label {
font-size: 11.2px;
font-weight: bold;
margin-right: 25.6px;
width: 64px;
text-align: right;
.required {
color: red;
margin-right: 3.2px;
}
}
.switch-container {
display: flex;
gap: 9.6px;
.status-btn {
flex: 1;
padding: 5.6px 19.2px;
font-size: 12.8px;
color: #000000;
background: #f2f2f2;
text-align: center;
font-weight: 400;
line-height: 17.6px;
border-radius: 14.4px;
&.active {
color: #ffffff;
background: #3774f6;
border: 0.32px solid rgba(224, 224, 224, 1);
}
}
}
.input-box {
flex: 1;
border-radius: 3.2px;
font-size: 12.8px;
line-height: 19.2px;
}
.photo-limit {
font-size: 12.8px;
color: #959595;
line-height: 19.2px;
font-weight: 400;
}
.photo-container {
display: flex;
flex-wrap: wrap;
margin-bottom: 6.4px;
.photo-item {
position: relative;
margin-right: 6.4px;
margin-bottom: 6.4px;
.photo {
width: 57.6px;
height: 57.6px;
border-radius: 3.2px;
margin-left: 9.6px;
}
.delete-photo {
position: absolute;
top: -6.4px;
right: -6.4px;
background-color: #ff4d4f;
color: #fff;
width: 12.8px;
height: 12.8px;
border-radius: 50%;
text-align: center;
line-height: 12.8px;
font-size: 9.6px;
}
}
}
.photo-btn {
background: #ffffff;
border: 0.272px solid rgba(221, 221, 221, 1);
border-radius: 1.64px;
width: 57.6px;
height: 57.6px;
font-size: 57.6px;
color: #cccccc;
text-align: center;
line-height: 51.2px;
}
}
</style>
<template>
<view v-if="isOpen" class="synchronous-dialog">
<view class="synchronous-content">
<!-- 巡检事项 -->
<view class="form-item">
<text class="form-label"
><text class="required">*</text>巡检事项:</text
>
<text>{{ inspectionItem }}</text>
</view>
<!-- 情况摘要(多选输入框) -->
<view class="form-item">
<text class="form-label"
><text class="required">*</text>情况摘要:</text
>
<textarea
v-model="summary"
placeholder="请输入情况摘要"
auto-height
class="input-box"
></textarea>
</view>
<!-- 固定词 -->
<view class="form-item last">
<text class="form-label"></text>
<view class="fixed-words">
<text
v-for="(word, index) in fixedWords"
:key="index"
class="word"
@click="selectWord(word)"
>
{{ word }}
</text>
</view>
</view>
<view class="row-item bottom-row">
<view class="button btn" @click="handleClose">取消</view>
<view class="button" @click="handleConfirm">确认</view>
</view>
</view>
</view>
</template>
<script>
export default {
props: {
// 父组件传递的巡检事项
inspectionItem: {
type: String,
default: "",
},
// 父组件传递的固定词
fixedWords: {
type: Array,
default: () => ["已检查", "正常", "异常", "需处理"],
},
},
data() {
return {
summary: "", // 情况摘要
isOpen: false,
};
},
methods: {
// 打开弹窗
open(item) {
this.summary = item.conclusion;
this.isOpen = true;
},
// 关闭弹窗
close() {
this.isOpen = false;
},
// 选择固定词
selectWord(word) {
this.summary += word + " "; // 将选中的词添加到输入框
},
// 确认
handleConfirm() {
this.$emit("confirm", this.summary); // 将情况摘要回传给父组件
this.handleClose();
},
// 关闭弹窗
handleClose() {
this.summary = ""; // 清空输入框
this.close();
},
},
};
</script>
<style scoped lang="less">
.synchronous-dialog {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
z-index: 99999;
.synchronous-content {
padding: 3% 20px 32px 24px;
width: 400px;
height: 300px;
box-sizing: border-box;
background-image: linear-gradient(
-6deg,
#f9ffe7 0%,
#ffffff 12%,
#fcfeff 73%,
#ccf1ff 100%
);
border: 0.4px solid rgba(224, 224, 224, 1);
border-radius: 12px;
position: relative;
.row-item {
display: flex;
align-items: center;
justify-content: center;
}
.title {
font-family: PingFangSC-Medium;
font-size: 18px;
color: #000000;
text-align: center;
line-height: 26px;
font-weight: 500;
}
.count-num {
margin: 5% 0 5% 0;
align-items: flex-end;
.num {
display: inline-block;
font-family: AlibabaPuHuiTi_2_65_Medium;
font-size: 50px;
color: #3774f6;
line-height: 44px;
font-weight: 500;
}
}
.operating-instructions {
margin-bottom: 8%;
.title {
font-size: 13px;
color: #4a4a4a;
line-height: 24px;
font-weight: 600;
text-align: left;
}
.instructions-item {
font-size: 12px;
color: #7c7c7c;
line-height: 22px;
font-weight: 400;
}
}
// 打包按钮
.bottom-row {
position: absolute;
bottom: 24px;
left: 50%;
transform: translateX(-50%);
.button {
display: flex;
align-items: center;
justify-content: center;
background-image: linear-gradient(180deg, #3773f6 0%, #2c57f6 99%);
box-shadow: 0px 10px 24px 0px rgba(51, 104, 246, 0.24);
border-radius: 27px;
width: 128px;
height: 32px;
margin: 10px;
color: #fff;
&.btn {
background: #ffffff;
color: #000000;
}
}
}
// 关闭按钮
.close-button {
position: absolute;
bottom: -40px;
left: 50%;
transform: translateX(-50%);
.iconfont {
color: #fff;
font-size: 24px;
}
}
}
}
.form-item {
width: 100%;
display: flex;
align-items: center;
padding: 9.6px 0;
line-height: 28.8px;
border-bottom: 0.8px solid #f2f3f5;
&.last {
border: 0;
}
.fixed-words {
.word {
font-size: 11.2px;
margin-right: 4px;
padding: 4px 6px;
border: 1px solid #c7c7c7;
border-radius: 4px;
}
}
.form-label {
font-size: 11.2px;
font-weight: bold;
margin-right: 25.6px;
width: 64px;
text-align: right;
.required {
color: red;
margin-right: 3.2px;
}
}
.switch-container {
display: flex;
gap: 9.6px;
.status-btn {
flex: 1;
padding: 5.6px 19.2px;
font-size: 12.8px;
color: #000000;
background: #f2f2f2;
text-align: center;
font-weight: 400;
line-height: 17.6px;
border-radius: 14.4px;
&.active {
color: #ffffff;
background: #3774f6;
border: 0.32px solid rgba(224, 224, 224, 1);
}
}
}
.input-box {
flex: 1;
border-radius: 3.2px;
font-size: 12.8px;
line-height: 19.2px;
}
.photo-limit {
font-size: 12.8px;
color: #959595;
line-height: 19.2px;
font-weight: 400;
}
.photo-container {
display: flex;
flex-wrap: wrap;
margin-bottom: 6.4px;
.photo-item {
position: relative;
margin-right: 6.4px;
margin-bottom: 6.4px;
.photo {
width: 57.6px;
height: 57.6px;
border-radius: 3.2px;
margin-left: 9.6px;
}
.delete-photo {
position: absolute;
top: -6.4px;
right: -6.4px;
background-color: #ff4d4f;
color: #fff;
width: 12.8px;
height: 12.8px;
border-radius: 50%;
text-align: center;
line-height: 12.8px;
font-size: 9.6px;
}
}
}
.photo-btn {
background: #ffffff;
border: 0.272px solid rgba(221, 221, 221, 1);
border-radius: 1.64px;
width: 57.6px;
height: 57.6px;
font-size: 57.6px;
color: #cccccc;
text-align: center;
line-height: 51.2px;
}
}
</style>
<template>
<!-- 井道巡检操作 -->
<view class="container">
<uni-nav-bar
:fixed="true"
background-color="rgba(214, 240, 255, 0.0)"
status-bar
rightWidth="300"
>
<block slot="left">
<view class="" @click="back">
<text class="iconfont icon-fanhui"></text>
</view>
</block>
</uni-nav-bar>
<view class="profile-section">
<view class="profile-box">
<view class="profile-left">
<view class="avatar">
<image
src="@/static/img/add-img/defaultAvatar.png"
mode="aspectFit"
></image>
</view>
<view class="info">
<view class="username">井道巡检</view>
<view class="number"
>位置:<text class="value">{{ location }}</text></view
>
</view>
</view>
<view class="action-btn complete-btn" @click="submit(1)">
完成巡检
</view>
</view>
</view>
<!-- 模块3:Tab 操作区域 -->
<view class="module">
<view class="tab-buttons">
<view
v-for="(tab, index) in tabs"
:key="index"
:class="['tab-item', { active: activeTab === index }]"
@click="switchTab(index)"
>
<text v-if="tab.status == 0" class="iconfont icon-weixunjian"></text>
<text v-if="tab.status == 1" class="iconfont icon-wancheng"></text>
<text v-if="tab.status == 2" class="iconfont icon-shibai1"></text>
<text class="tab-text">{{ tab.label }}</text>
<view v-if="activeTab === index" class="underline"></view>
</view>
</view>
<view class="tip">
<text class="iconfont icon-tixing"></text>{{ tabs[activeTab].text }}
</view>
<view class="tab-content">
<!-- 操作区域 -->
<view class="form-item"
><text class="form-label">巡检项</text>
<view class="label">
<text>{{ tabs[activeTab].label }}</text>
</view>
</view>
<view class="form-item">
<text class="form-label"
><text class="required">*</text>巡检结论</text
>
<view class="switch-container">
<view
:class="['status-btn', { active: inspectionResult === 0 }]"
@click="setInspectionResult(0)"
>
正常
</view>
<view
:class="['status-btn', { active: inspectionResult === 1 }]"
@click="setInspectionResult(1)"
>
异常
</view>
</view>
</view>
<template v-if="inspectionResult === 1">
<view class="form-item">
<text class="form-label"
><text class="required">*</text>情况摘要</text
>
<text
v-if="list[activeTab].conclusion"
class="conclusion have"
@click="showPopup(index)"
>{{ list[activeTab].conclusion }}</text
>
<text v-else class="conclusion" @click="showPopup(index)"
>请输入情况摘要</text
>
</view>
<view class="form-item">
<text class="form-label"
><text class="required">*</text>现场照片</text
>
<CommonUpload v-model="list[activeTab].photos" :max-count="5"> </CommonUpload>
<!-- <view class="photo-box">
<view class="photo-container">
<view
v-for="(photo, index) in list[activeTab] &&
list[activeTab].photos"
:key="index"
class="photo-item"
>
<image :src="photo" class="photo"></image>
<text class="delete-photo" @click="deletePhoto(index)"
>×</text
>
</view>
<view @click="takePhoto" class="photo-btn"> + </view>
</view>
<view class="photo-limit"
>请对检查项进行拍照留存(限5张)。发现“异常、告警”时,需拍照留存。</view
>
</view> -->
</view></template
>
</view>
</view>
<!-- 模块4:提交模块 -->
<!-- <view class="module submit-module">
<button class="action-btn" @click="saveDraft">暂存</button>
<button class="action-btn complete-btn" @click="complete">
完成
</button>
</view> -->
<view class="submit-module">
<view class="action-btn" @click="submit(0)">暂存</view>
<view
v-if="activeTab !== 2"
class="action-btn complete-btn"
@click="nextTab"
>
下一项
</view> </view
><custom-popup
ref="customPopup"
:inspectionItem="tabs[activeTab].label"
:fixedWords="['已检查', '正常', '异常', '需处理', '已处理']"
@confirm="handlePopupConfirm"
></custom-popup>
</view>
</template>
<script>
import {
pad_2_1_inspection_items,
pad_2_1_inspection_position,
pad_2_1_floor,
} from "@/utils/dict.js"; //巡检位置,A座到F座 楼层2楼4楼到26楼
import {
addLog,
getLogContent,
LOG_TYPE_ENUM,
writeDarf,
writeInspectionData,
} from "@/utils/IoReadingAndWriting.js";
import CommonUpload from "@/components/CommonUpload/index.vue";
import { getInspectionDetails, getDarft } from "@/request/index.js";
import moment from "moment";
import customPopup from "./model/customPopup.vue";
import _ from "lodash";
import inspectApi from "@/api/inspect";
import { sqlToData, dataToSql } from "./shared";
export default {
components: {
customPopup,
CommonUpload
},
data() {
return {
location: "",
value: "",
dictValue: "",
inspectionCode: "",
isSubmitEnabled: false, // 提交按钮是否可点击
uid: "",
randomDescription: "这是一段随机说明文字。", // 随机说明文字
tabs: [
{
label: "门禁",
status: "0",
text: "检查门禁是否可以正常开启/关闭",
},
{
label: "卫生",
status: "0",
text: "检查卫生状况是否保持清洁",
},
{
label: "设备告警",
status: "0",
text: "检查设备是否存在告警,有无设备离线或故障",
},
],
activeTab: 0, // 当前选中的 Tab
inspectionResult: "", // Switch 值(0: 正常, 1: 异常)
conclusion: "", // 情况摘要
photos: [], // 现场照片
historyData: null, // 历史数据
firstSubmitTime: null, // 首次提交时间
detailsInfo: {}, // 详情
baseInfo: {}, // 基础信息
list: [], //巡检信息
backValue: "", //路由来源
all_data: [],
};
},
computed: {
userInfo() {
return this.$store.state.now_user || {};
},
// isOperationPermissions() {
// // 是否有操作权限
// const {
// uid,
// createByName
// } = this.detailsInfo;
// return !uid || (uid && createByName == this.userInfo.user);
// },
},
onLoad(options) {
this.coverlist();
this.isDisable = options.isDisable == 1 ? true : false;
this.uid = options.uid;
this.location = options.location;
this.value = options.value;
this.dictValue = options.dictValue;
this.inspectionCode = options.inspectionCode;
this.backValue = options.backValue || "";
this.all_data = this.$store.state.all_data || [];
console.log("options", options);
if (options.uid) {
this.getDetails(options.uid);
} else {
this.init();
}
},
watch: {},
mounted() {},
methods: {
// 初始化
init() {
return new Promise((resolve, reject) => {
// 判断是否有回显数据
// 基础数据
this.baseInfo = {
inspectionType: "2",
inspectionCode: this.inspectionCode,
recordName: `${moment().format("yyyyMMDD")}-井道巡检`,
inspectionTime: moment().format("yyyy-MM-DD HH:mm"),
inspectionBy: this.$store.state.now_user.user,
inspectionById: this.$store.state.now_user.userId,
createByName: this.$store.state.now_user.user,
isException: "", // 是否有异常,大于0存在异常
inspectionNumber: 0, //巡检数量
floor: this.floor, // 楼层
isSubmit: "", // 0 是草稿态; 1 是正式提交
isSign: false, // 是否签字
signImg: "", // 签字图片地址
conclusion: "", //摘要
creatTime: `${new Date().getTime()}`,
items: [],
};
console.log(2222, this.baseInfo, this.list, this.detailsInfo);
resolve();
});
},
// 回显数据
getDetails(uid) {
uni.showLoading();
inspectApi
.info(uid)
.then((res) => {
const detailsInfo = sqlToData(res);
console.log("getDetails", res);
let list =
detailsInfo.originData[this.value - 1].position[this.dictValue - 1]
.details;
this.detailsInfo = detailsInfo;
// 未巡检需要处理默认数据结构
if (list && list.length) {
this.list = list;
}
this.inspectionResult = list[0].inspectionResult;
list.forEach((item, index) => {
this.tabs[index].status = item.inspectionResult === 0 ? "1" : "2";
});
console.log("let list", list);
console.log("获取list", this.list);
this.isDisable = this.isDisable || detailsInfo.synchronization == 1; // 是否禁用 1:已同步数据 0: 未同步数据
uni.hideLoading();
})
.catch((error) => {
uni.showToast({
title: error.msg,
icon: "none",
duration: 1000,
});
uni.hideLoading();
});
},
// 数据结构重组
coverlist() {
// 获取井道巡检的三个检查项固定数据再进行处理
const data = pad_2_1_inspection_items.rows.map((item) => {
return {
// ...item,
dictLabel: item.dictLabel,
dictValue: item.dictValue,
conclusion: "", // 情况摘要
// roomType,
inspectionResult: "", // 异常结论
itemCode: item.dictValue, // 检查项 如:门禁
measuredData: this.floor, // 逗号分隔字符串
photos: [], // 照片
};
});
this.list = data;
},
// 更新当前 Tab 数据
updateCurrentTabData() {
const currentTabData = this.list[this.activeTab];
this.inspectionResult = currentTabData.inspectionResult;
this.conclusion = currentTabData.conclusion;
this.photos = currentTabData.photos;
},
// 拍照
takePhoto() {
uni.chooseImage({
count: 1,
sourceType: ["camera"], // 可以从相机拍摄
success: async (res) => {
if (this.photos.length < 5) {
const base64 = await this.convertFileToBase64(res.tempFilePaths[0]);
this.photos.push(base64);
this.list[this.activeTab].photos = this.photos;
} else {
uni.showToast({
title: "最多只能上传5张照片",
icon: "none",
});
}
},
});
},
// 转化为base64
convertFileToBase64(filePath) {
return new Promise((resolve, reject) => {
plus.io.resolveLocalFileSystemURL(
filePath,
function (entry) {
entry.file(
function (file) {
const reader = new plus.io.FileReader();
reader.onloadend = function (evt) {
const base64 = evt.target.result; // 获取 Base64 数据
resolve(base64); // 返回 Base64 数据
};
reader.readAsDataURL(file); // 读取文件并转换为 Base64
},
function (error) {
reject("获取文件对象失败:" + error.message);
}
);
},
function (error) {
reject("解析文件路径失败:" + error.message);
}
);
});
},
// 删除照片
deletePhoto(index) {
this.photos.splice(index, 1);
this.list[this.activeTab].photos = this.photos;
},
// 处理提交数据
getParams(isSubmit) {
if (this.uid) {
console.log("74", this.value, this.dictValue, this.detailsInfo);
let posItem =
this.detailsInfo.originData[this.value - 1].position[
this.dictValue - 1
];
console.log("74", this.value, this.dictValue, posItem);
posItem.details = this.list;
posItem.isSubmit = isSubmit;
// 提交才会有巡检状态,暂存没有
if (!this.checkInspectionResult(this.list)) {
posItem.status = 2; //1表示已经巡检过有异常
posItem.statusLable = "巡检异常";
} else {
posItem.status = 1; //1表示已经巡检过没有异常
posItem.statusLable = "已巡检";
}
console.log("this.detailsInfo.originData", this.detailsInfo.originData);
let { statusNotZero, statusEqualsTwo } = this.countStatus(
this.detailsInfo.originData
);
console.log(
"this.detailsInfo.statusNotZero , statusEqualsTwo ",
statusNotZero,
statusEqualsTwo
);
this.detailsInfo.inspectionNumber = statusNotZero; //巡检总数
this.detailsInfo.isException = statusEqualsTwo; //异常数量
this.detailsInfo.isSubmit = isSubmit; //是否提交
console.log("this.detailsInfo", this.detailsInfo);
this.detailsInfo.submitTime = moment().format("yyyy-MM-DD"); // 记录提交时间
this.detailsInfo.submitMonth = moment().format("yyyy-MM"); // 记录提交月份
// this.detailsInfo.synchronization = 2; //编辑中
return this.detailsInfo;
} else {
let baseInfo = this.baseInfo;
let dataObj = pad_2_1_inspection_position.rows.map((item, index) => {
return {
name: item.dictLabel,
value: item.dictValue,
isVaild: false, // 校验通过
// type: 1, // 枚举值
position: pad_2_1_floor.rows,
refName: `TabContentItem_${index}`,
descript: "检查内容包括门禁、卫生、设备告警。",
};
});
let tabList = JSON.parse(JSON.stringify(dataObj));
let posItem = tabList[this.value - 1].position[this.dictValue - 1];
posItem.details = this.list;
posItem.isSubmit = isSubmit; //当前项是否提交
if (!this.checkInspectionResult(this.list)) {
posItem.status = 2; //1表示已经巡检过有异常
posItem.statusLable = "巡检异常";
} else {
posItem.status = 1; //1表示已经巡检过没有异常
posItem.statusLable = "已巡检";
}
// 根据获取到的每个井道的isSubmit来判断是否有暂存状态,只有有一个井道是暂存,那就是编辑中、暂存状态
let typeSubmit = this.typeSubmit(tabList);
const data = {
...baseInfo,
isSubmit: isSubmit, //0暂存(编辑中) 1提交(待同步,已同步)
inspectionNumber: 1,
isException: posItem.status == 2 ? 1 : 0,
items: [],
synchronization: 0, // 是否同步过
submitTime: moment().format("yyyy-MM-DD"), // 记录提交时间
submitMonth: moment().format("yyyy-MM"), // 记录提交月份
originData: tabList, //所有大楼和楼层的数据
};
console.log("getParams,data", data);
return data;
}
},
countStatus(data) {
let statusNotZero = 0;
let statusEqualsTwo = 0;
console.log("data", data);
// 遍历数据(假设 data 是数组)
data.forEach((item) => {
console.log(4515, item);
// 检查是否有 originData
item.position.forEach((floor) => {
// 检查是否有 position
// 获取 status(可能是数字或字符串)
const status = floor.status;
// 转换为数字进行比较
const statusNum = parseInt(status, 10);
if (!isNaN(statusNum)) {
if (statusNum !== 0) {
statusNotZero++;
}
if (statusNum === 2) {
statusEqualsTwo++;
}
}
});
});
return {
statusNotZero,
statusEqualsTwo,
};
},
typeSubmit(originData) {
return originData.reduce((acc, curr) => {
return (
acc +
curr.position.reduce((innerAcc, innerCurr) => {
return innerCurr.status === 0 ? innerAcc + 1 : innerAcc;
}, 0)
);
}, 0);
},
// 检查是否存在异常
checkInspectionResult(arr) {
return !arr.some((obj) => obj.inspectionResult === 1);
},
// 提交
async submit(isSubmit = 1) {
// 校验是否通过
if (isSubmit && !this.isAllTabValid().valid) {
uni.showToast({
title: "请填写完整必填项",
icon: "none",
});
return false;
}
const params = this.getParams(isSubmit); //数据获取
// const all_data = this.$store.state.all_data; //获取全部数据
let logContent = "";
console.log("this.uid", this.uid);
console.log("all_data", this.all_data);
// 写数据到indexedDB
// 处理数据
const send = dataToSql(params);
let api;
if (this.uid) {
send.id = this.uid
api = inspectApi.update
} else {
api = inspectApi.save
}
try {
let saveRes = await api(send)
if (this.uid) {
const index = this.all_data.findIndex(
(element) => element.uid == this.uid
);
params.uid = this.uid;
this.all_data[index] = params;
logContent = getLogContent(
LOG_TYPE_ENUM.edit,
`${params.recordName}(${params.inspectionCode})`,
"巡检模块"
);
} else {
params.uid = new Date().getTime(); // 唯一标识 pad 端使用
this.all_data.push(params);
logContent = getLogContent(
LOG_TYPE_ENUM.add,
`${params.recordName}(${params.inspectionCode})`,
"巡检模块"
);
}
// 更新巡检list
const userInfo = this.userInfo;
console.log("all_data存储", this.all_data);
this.$store.commit("SET_ALL_DATA", this.all_data);
const inspectList = this.all_data.filter(
(item) => item.createByName == userInfo.user
);
console.log("inspectList", inspectList);
writeInspectionData(inspectList, userInfo.user);
// 更新日志
const log_list = this.$store.state.log_list;
logContent.inspectionType = params.inspectionType;
log_list.push(logContent);
this.$store.commit("SET_LOG_LIST", log_list);
addLog(log_list).then((res) => {
console.log("日志文件写入成功");
});
// 清空基础缓存信息
// this.$store.commit("SET_TEMP_DATA", {}); // 缓存[巡检信息]
uni.showToast({
title: isSubmit ? "提交成功1" : "保存草稿成功",
icon: "success",
});
uni.navigateTo({
url: `/pages/shaftInspection/shaftInspectionList?uid=${ this.uid ? this.uid : saveRes.lastInsertId}&backValue=${this.backValue}`,
});
} catch (err) {
console.log('err',err)
}
},
// 检查所有Tab 的必填项是否填写完整
isAllTabValid() {
// 遍历所有巡检项
for (let i = 0; i < this.list.length; i++) {
const item = this.list[i];
// 1. 检查是否填写了巡检结论
if (
item.inspectionResult === null ||
item.inspectionResult === undefined
) {
return {
valid: false,
message: `请填写【${this.tabs[i].label}】的巡检结论`,
tabIndex: i,
};
}
// 如果巡检结论为正常,则不对摘要和现场照片做必填校验
if(item.inspectionResult === 0) {
continue
}
// 2. 检查是否填写了情况摘要
if (!item.conclusion || item.conclusion.trim() === "") {
return {
valid: false,
message: `请填写【${this.tabs[i].label}】的情况摘要`,
tabIndex: i,
};
}
// 3. 如果是异常情况,检查是否上传了照片
if (
item.inspectionResult === 1 &&
(!item.photos || item.photos.length === 0)
) {
return {
valid: false,
message: `【${this.tabs[i].label}】为异常情况,必须上传现场照片`,
tabIndex: i,
};
}
}
// 所有检查都通过
return {
valid: true,
message: "",
};
},
// 检查当前 Tab 的必填项是否填写完整
// 下一项
nextTab() {
// if (!this.isCurrentTabValid()) {
// uni.showToast({
// title: "请填写完整必填项",
// icon: "none",
// });
// return false;
// }
this.tabs[this.activeTab].status =
this.list[this.activeTab].inspectionResult === 0 ? "1" : "2"; // 更新当前 Tab 的数据
if (this.activeTab === 2) {
this.isSubmitEnabled = true;
} else {
this.switchTab(this.activeTab + 1);
}
},
// 切换 Tab
switchTab(index) {
this.activeTab = index;
this.updateCurrentTabData();
},
// 显示弹窗
showPopup(index) {
this.currentIndex = index;
this.$refs.customPopup.open();
},
// 处理弹窗确认
handlePopupConfirm(summary) {
this.list[this.activeTab].conclusion = summary; // 回显到文字显示区域
},
// 设置巡检结论
setInspectionResult(value) {
console.log("value", value);
this.inspectionResult = value;
this.list[this.activeTab].inspectionResult = value; // 更新当前 Tab 的数据
this.tabs[this.activeTab].status = value === 0 ? "1" : "2"; // 更新当前 Tab 的数据
},
// 返回
back() {
uni.navigateTo({
url: `/pages/shaftInspection/shaftInspectionList?uid=${this.uid}&backValue=${this.backValue}`,
});
},
// 关闭弹窗
closePopup() {
this.switchTab((this.activeTab + 1) % this.tabs.length);
},
},
};
</script>
<style scoped lang="less">
.uni-nav-bar-text {
height: 28.8px;
width: 28.8px;
background: #ffffff;
border: 0.32px solid rgba(224, 224, 224, 1);
border-radius: 14.4px;
color: #333;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
}
.container {
padding: 19.2px;
height: calc(100vh - 148px);
}
.profile-section {
width: 100%;
margin-bottom: 10.24px;
.profile-box {
background-color: #fff;
border-radius: 7.68px;
padding: 10.24px 20.48px;
display: flex;
justify-content: space-between;
align-items: center;
position: relative;
.profile-left {
display: flex;
align-items: center;
.avatar {
position: relative;
width: 32.4px;
height: 32.4px;
border-radius: 50%;
overflow: hidden;
margin-right: 7.2px;
image {
width: 100%;
height: 100%;
}
.change-password {
position: absolute;
bottom: 0;
left: 0;
right: 0;
background-color: rgba(0, 0, 0, 0.5);
text-align: center;
height: 14.08px;
font-family: PingFangSC-Regular;
font-size: 7.68px;
color: #ffffff;
line-height: 12.8px;
font-weight: 400;
}
}
.info {
.username {
font-size: 12.8px;
color: #000000;
line-height: 17.92px;
font-weight: 500;
margin-bottom: 5.76px;
}
.number {
font-size: 10.24px;
color: #4a4a4a;
line-height: 17.92px;
font-weight: 400;
.value {
color: #000000;
}
}
}
}
.action-btn {
width: 145.6px;
height: 38.4px;
line-height: 38.4px;
background: #ffffff;
border: 0.8px solid rgba(224, 224, 224, 1);
box-shadow: 0px 8px 19.2px 0px rgba(185, 185, 185, 0.24);
border-radius: 21.6px 19.2px 19.2px 21.6px;
font-size: 16px;
color: #000000;
text-align: center;
font-weight: 400;
position: absolute;
right: 20px;
top: 15px;
&.complete-btn {
background-image: linear-gradient(180deg, #3773f6 0%, #2c57f6 99%);
color: #ffffff;
}
}
}
}
.module {
background: #ffffff;
height: 100%;
border-radius: 9.6px;
padding: 12.8px 20px;
}
.title-bar {
display: flex;
align-items: center;
margin-bottom: 8px;
.blue-line {
width: 3.2px;
height: 12.8px;
background-color: #007aff;
margin-right: 6.4px;
}
.title {
font-size: 12.8px;
font-weight: bold;
}
.location {
margin-left: 6.4px;
color: #666;
}
.submit-btn {
position: absolute;
right: 19.2px;
width: 20%;
background-color: #ccc;
color: #fff;
border-radius: 3.2px;
padding: 3.2px 6.4px;
font-size: 9.6px;
&.active {
background-color: #007aff;
}
}
}
.description {
font-size: 11.2px;
color: #666;
}
.tab-buttons {
display: flex;
justify-content: flex-start;
align-items: center;
margin-bottom: 8px;
gap: 16px;
}
.tip {
width: 100%;
height: 27.2px;
background: rgba(55, 116, 246, 0.05);
border: 0.8px solid rgba(55, 116, 246, 0.3);
border-radius: 8px;
font-size: 11.2px;
color: #4a4a4a;
letter-spacing: 0;
line-height: 27.2px;
font-weight: 400;
padding: 0 9.6px;
.icon-tixing {
color: #3774f6;
font-size: 11.2px;
margin-right: 6.4px;
}
}
.tab-item {
display: flex;
align-items: flex-start;
position: relative;
padding: 6.4px 0;
cursor: pointer;
white-space: nowrap;
.iconfont {
font-size: 12px;
margin-right: 4px;
&.icon-weixunjian {
color: #959595;
}
&.icon-shibai1 {
color: #ff4a34;
}
&.icon-wancheng {
color: #3774f6;
}
}
.tab-icon {
width: 8.4px;
height: 8.4px;
margin-bottom: 3.2px;
margin-right: 2.4px;
}
.tab-text {
font-size: 11.2px;
color: #333;
}
&.active {
.tab-text {
color: #3774f6;
}
.underline {
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 100%;
height: 1.6px;
background-color: #3774f6;
}
}
}
.form-item {
display: flex;
align-items: center;
padding: 9.6px 0;
line-height: 28.8px;
border-bottom: 0.8px solid #f2f3f5;
.form-label {
font-size: 11.2px;
margin-right: 25.6px;
width: 58.4px;
text-align: right;
color: #7c7c7c;
.required {
color: red;
margin-right: 3.2px;
}
}
.conclusion {
color: #c7c7c7;
font-size: 11.2px;
&.have {
color: #000;
}
}
.label {
font-size: 11.2px;
}
.switch-container {
display: flex;
gap: 9.6px;
.status-btn {
flex: 1;
padding: 5.6px 19.2px;
font-size: 12.8px;
color: #000000;
background: #f2f2f2;
text-align: center;
font-weight: 400;
line-height: 17.6px;
border-radius: 14.4px;
&.active {
color: #ffffff;
background: #3774f6;
border: 0.32px solid rgba(224, 224, 224, 1);
}
}
}
.input-box {
flex: 1;
border-radius: 3.2px;
font-size: 12.8px;
line-height: 19.2px;
}
.photo-limit {
font-size: 12.8px;
color: #959595;
line-height: 19.2px;
font-weight: 400;
}
.photo-container {
display: flex;
flex-wrap: wrap;
margin-bottom: 6.4px;
.photo-item {
position: relative;
margin-right: 6.4px;
margin-bottom: 6.4px;
.photo {
width: 57.6px;
height: 57.6px;
border-radius: 3.2px;
margin-left: 9.6px;
}
.delete-photo {
position: absolute;
top: -6.4px;
right: -6.4px;
background-color: #ff4d4f;
color: #fff;
width: 12.8px;
height: 12.8px;
border-radius: 50%;
text-align: center;
line-height: 12.8px;
font-size: 9.6px;
}
}
}
.photo-btn {
background: #ffffff;
border: 0.272px solid rgba(221, 221, 221, 1);
border-radius: 1.64px;
width: 57.6px;
height: 57.6px;
font-size: 57.6px;
color: #cccccc;
text-align: center;
line-height: 51.2px;
}
}
.submit-module {
display: flex;
justify-content: center;
position: fixed;
gap: 16px;
left: 50%;
transform: translateX(-50%);
bottom: 25.6px;
.action-btn {
width: 145.6px;
height: 38.4px;
line-height: 38.4px;
background: #ffffff;
border: 0.8px solid rgba(224, 224, 224, 1);
box-shadow: 0px 8px 19.2px 0px rgba(185, 185, 185, 0.24);
border-radius: 21.6px 19.2px 19.2px 21.6px;
font-size: 16px;
color: #000000;
text-align: center;
font-weight: 400;
&.complete-btn {
background-image: linear-gradient(180deg, #3773f6 0%, #2c57f6 99%);
color: #ffffff;
}
}
}
.popup-content {
background-color: white;
padding: 32px;
border-radius: 8px;
text-align: center;
position: relative;
width: 240px;
.close-icon {
position: absolute;
top: 8px;
right: 8px;
font-size: 16px;
cursor: pointer;
}
.icon-success {
font-size: 32px;
color: green;
margin-bottom: 16px;
}
.success-text {
font-size: 14.4px;
margin-bottom: 16px;
}
.next-button {
background-color: blue;
color: white;
padding: 8px 16px;
border-radius: 4px;
cursor: pointer;
font-size: 12.8px;
&:hover {
opacity: 0.9;
}
}
}
</style>
<template>
<!-- 井道巡检操作 -->
<view class="container">
<uni-nav-bar
:fixed="true"
background-color="rgba(214, 240, 255, 0.0)"
status-bar
rightWidth="300"
>
<block slot="left">
<view class="" @click="back">
<text class="iconfont icon-fanhui"></text>
</view>
</block>
</uni-nav-bar>
<view class="profile-section">
<view class="profile-box">
<view class="profile-left">
<view class="avatar">
<image
src="@/static/img/add-img/defaultAvatar.png"
mode="aspectFit"
></image>
</view>
<view class="info">
<view class="username">井道巡检</view>
<view class="number"
>位置:<text class="value">{{ location }}</text></view
>
</view>
</view>
<view class="action-btn complete-btn" @click="submit(1)">
完成巡检
</view>
</view>
</view>
<!-- 模块3:Tab 操作区域 -->
<view class="module">
<view class="tab-buttons">
<view
v-for="(tab, index) in tabs"
:key="index"
:class="['tab-item', { active: activeTab === index }]"
@click="switchTab(index)"
>
<text v-if="tab.status == 0" class="iconfont icon-weixunjian"></text>
<text v-if="tab.status == 1" class="iconfont icon-wancheng"></text>
<text v-if="tab.status == 2" class="iconfont icon-shibai1"></text>
<text class="tab-text">{{ tab.label }}</text>
<view v-if="activeTab === index" class="underline"></view>
</view>
</view>
<view class="tip">
<text class="iconfont icon-tixing"></text>{{ tabs[activeTab].text }}
</view>
<view class="tab-content">
<!-- 操作区域 -->
<view class="form-item"
><text class="form-label">巡检项</text>
<view class="label">
<text>{{ tabs[activeTab].label }}</text>
</view>
</view>
<view class="form-item">
<text class="form-label"
><text class="required">*</text>巡检结论</text
>
<view class="switch-container">
<view
:class="['status-btn', { active: inspectionResult === 0 }]"
@click="setInspectionResult(0)"
>
正常
</view>
<view
:class="['status-btn', { active: inspectionResult === 1 }]"
@click="setInspectionResult(1)"
>
异常
</view>
</view>
</view>
<template v-if="inspectionResult === 1">
<view class="form-item">
<text class="form-label"
><text class="required">*</text>情况摘要</text
>
<text
v-if="list[activeTab].conclusion"
class="conclusion have"
@click="showPopup(list[activeTab])"
>{{ list[activeTab].conclusion }}</text
>
<text v-else class="conclusion" @click="showPopup(list[activeTab])"
>请输入情况摘要</text
>
</view>
<view class="form-item">
<text class="form-label"
><text class="required">*</text>现场照片</text
>
<CommonUpload v-model="list[activeTab].photos" :max-count="5">
</CommonUpload>
<!-- <view class="photo-box">
<view class="photo-container">
<view
v-for="(photo, index) in list[activeTab] &&
list[activeTab].photos"
:key="index"
class="photo-item"
>
<image :src="photo" class="photo"></image>
<text class="delete-photo" @click="deletePhoto(index)"
>×</text
>
</view>
<view @click="takePhoto" class="photo-btn"> + </view>
</view>
<view class="photo-limit"
>请对检查项进行拍照留存(限5张)。发现“异常、告警”时,需拍照留存。</view
>
</view> -->
</view></template
>
</view>
</view>
<!-- 模块4:提交模块 -->
<!-- <view class="module submit-module">
<button class="action-btn" @click="saveDraft">暂存</button>
<button class="action-btn complete-btn" @click="complete">
完成
</button>
</view> -->
<view class="submit-module">
<view class="action-btn" @click="submit(0)">暂存</view>
<view
v-if="activeTab !== 2"
class="action-btn complete-btn"
@click="nextTab"
>
下一项
</view> </view
><custom-popup
ref="customPopup"
:inspectionItem="tabs[activeTab].label"
:fixedWords="['已检查', '正常', '异常', '需处理', '已处理']"
@confirm="handlePopupConfirm"
></custom-popup>
</view>
</template>
<script>
import {
pad_2_1_inspection_items,
pad_2_1_inspection_position,
pad_2_1_floor,
} from "@/utils/dict.js"; //巡检位置,A座到F座 楼层2楼4楼到26楼
import {
addLog,
getLogContent,
LOG_TYPE_ENUM,
writeDarf,
writeInspectionData,
} from "@/utils/IoReadingAndWriting.js";
import CommonUpload from "@/components/CommonUpload/index.vue";
import { getInspectionDetails, getDarft } from "@/request/index.js";
import moment from "moment";
import customPopup from "./model/customPopup.vue";
import _ from "lodash";
import inspectApi from "@/api/inspect";
import { sqlToData, dataToSql } from "./shared";
export default {
components: {
customPopup,
CommonUpload,
},
data() {
return {
location: "",
value: "",
dictValue: "",
inspectionCode: "",
isSubmitEnabled: false, // 提交按钮是否可点击
uid: "",
randomDescription: "这是一段随机说明文字。", // 随机说明文字
tabs: [
{
label: "门禁",
status: "0",
text: "检查门禁是否可以正常开启/关闭",
},
{
label: "卫生",
status: "0",
text: "检查卫生状况是否保持清洁",
},
{
label: "设备告警",
status: "0",
text: "检查设备是否存在告警,有无设备离线或故障",
},
],
activeTab: 0, // 当前选中的 Tab
inspectionResult: "", // Switch 值(0: 正常, 1: 异常)
conclusion: "", // 情况摘要
photos: [], // 现场照片
historyData: null, // 历史数据
firstSubmitTime: null, // 首次提交时间
detailsInfo: {}, // 详情
baseInfo: {}, // 基础信息
list: [], //巡检信息
backValue: "", //路由来源
all_data: [],
};
},
computed: {
userInfo() {
return this.$store.state.now_user || {};
},
// isOperationPermissions() {
// // 是否有操作权限
// const {
// uid,
// createByName
// } = this.detailsInfo;
// return !uid || (uid && createByName == this.userInfo.user);
// },
},
onLoad(options) {
this.coverlist();
this.isDisable = options.isDisable == 1 ? true : false;
this.uid = options.uid;
this.location = options.location;
this.value = options.value;
this.dictValue = options.dictValue;
this.inspectionCode = options.inspectionCode;
this.backValue = options.backValue || "";
this.all_data = this.$store.state.all_data || [];
console.log("options", options);
if (options.uid) {
this.getDetails(options.uid);
} else {
this.init();
}
},
watch: {},
mounted() {},
methods: {
// 初始化
init() {
return new Promise((resolve, reject) => {
// 判断是否有回显数据
// 基础数据
this.baseInfo = {
inspectionType: "2",
inspectionCode: this.inspectionCode,
recordName: `${moment().format("yyyyMMDD")}-井道巡检`,
inspectionTime: moment().format("yyyy-MM-DD HH:mm"),
inspectionBy: this.$store.state.now_user.user,
inspectionById: this.$store.state.now_user.userId,
createByName: this.$store.state.now_user.user,
isException: "", // 是否有异常,大于0存在异常
inspectionNumber: 0, //巡检数量
floor: this.floor, // 楼层
isSubmit: "", // 0 是草稿态; 1 是正式提交
isSign: false, // 是否签字
signImg: "", // 签字图片地址
conclusion: "", //摘要
creatTime: `${new Date().getTime()}`,
items: [],
};
console.log(2222, this.baseInfo, this.list, this.detailsInfo);
resolve();
});
},
// 回显数据
getDetails(uid) {
uni.showLoading();
inspectApi
.info(uid)
.then((res) => {
const detailsInfo = sqlToData(res);
console.log("getDetails", res);
let list =
detailsInfo.originData[this.value - 1].position[this.dictValue - 1]
.details;
this.detailsInfo = detailsInfo;
// 未巡检需要处理默认数据结构
if (list && list.length) {
this.list = list;
}
this.inspectionResult = list[0].inspectionResult;
list.forEach((item, index) => {
this.tabs[index].status = item.inspectionResult === 0 ? "1" : "2";
});
console.log("let list", list);
console.log("获取list", this.list);
this.isDisable = this.isDisable || detailsInfo.synchronization == 1; // 是否禁用 1:已同步数据 0: 未同步数据
uni.hideLoading();
})
.catch((error) => {
uni.showToast({
title: error.msg,
icon: "none",
duration: 1000,
});
uni.hideLoading();
});
},
// 数据结构重组
coverlist() {
// 获取井道巡检的三个检查项固定数据再进行处理
const data = pad_2_1_inspection_items.rows.map((item) => {
return {
// ...item,
dictLabel: item.dictLabel,
dictValue: item.dictValue,
conclusion: "", // 情况摘要
// roomType,
inspectionResult: "", // 异常结论
itemCode: item.dictValue, // 检查项 如:门禁
measuredData: this.floor, // 逗号分隔字符串
photos: [], // 照片
};
});
this.list = data;
},
// 更新当前 Tab 数据
updateCurrentTabData() {
const currentTabData = this.list[this.activeTab];
this.inspectionResult = currentTabData.inspectionResult;
this.conclusion = currentTabData.conclusion;
this.photos = currentTabData.photos;
},
// 拍照
takePhoto() {
uni.chooseImage({
count: 1,
sourceType: ["camera"], // 可以从相机拍摄
success: async (res) => {
if (this.photos.length < 5) {
const base64 = await this.convertFileToBase64(res.tempFilePaths[0]);
this.photos.push(base64);
this.list[this.activeTab].photos = this.photos;
} else {
uni.showToast({
title: "最多只能上传5张照片",
icon: "none",
});
}
},
});
},
// 转化为base64
convertFileToBase64(filePath) {
return new Promise((resolve, reject) => {
plus.io.resolveLocalFileSystemURL(
filePath,
function (entry) {
entry.file(
function (file) {
const reader = new plus.io.FileReader();
reader.onloadend = function (evt) {
const base64 = evt.target.result; // 获取 Base64 数据
resolve(base64); // 返回 Base64 数据
};
reader.readAsDataURL(file); // 读取文件并转换为 Base64
},
function (error) {
reject("获取文件对象失败:" + error.message);
}
);
},
function (error) {
reject("解析文件路径失败:" + error.message);
}
);
});
},
// 删除照片
deletePhoto(index) {
this.photos.splice(index, 1);
this.list[this.activeTab].photos = this.photos;
},
// 处理提交数据
getParams(isSubmit) {
if (this.uid) {
console.log("74", this.value, this.dictValue, this.detailsInfo);
let posItem =
this.detailsInfo.originData[this.value - 1].position[
this.dictValue - 1
];
console.log("74", this.value, this.dictValue, posItem);
posItem.details = this.list;
posItem.isSubmit = isSubmit;
// 提交才会有巡检状态,暂存没有
if (!this.checkInspectionResult(this.list)) {
posItem.status = 2; //1表示已经巡检过有异常
posItem.statusLable = "巡检异常";
} else {
posItem.status = 1; //1表示已经巡检过没有异常
posItem.statusLable = "已巡检";
}
console.log("this.detailsInfo.originData", this.detailsInfo.originData);
let { statusNotZero, statusEqualsTwo } = this.countStatus(
this.detailsInfo.originData
);
console.log(
"this.detailsInfo.statusNotZero , statusEqualsTwo ",
statusNotZero,
statusEqualsTwo
);
this.detailsInfo.inspectionNumber = statusNotZero; //巡检总数
this.detailsInfo.isException = statusEqualsTwo; //异常数量
this.detailsInfo.isSubmit = isSubmit; //是否提交
console.log("this.detailsInfo", this.detailsInfo);
this.detailsInfo.submitTime = moment().format("yyyy-MM-DD"); // 记录提交时间
this.detailsInfo.submitMonth = moment().format("yyyy-MM"); // 记录提交月份
// this.detailsInfo.synchronization = 2; //编辑中
return this.detailsInfo;
} else {
let baseInfo = this.baseInfo;
let dataObj = pad_2_1_inspection_position.rows.map((item, index) => {
return {
name: item.dictLabel,
value: item.dictValue,
isVaild: false, // 校验通过
// type: 1, // 枚举值
position: pad_2_1_floor.rows,
refName: `TabContentItem_${index}`,
descript: "检查内容包括门禁、卫生、设备告警。",
};
});
let tabList = JSON.parse(JSON.stringify(dataObj));
let posItem = tabList[this.value - 1].position[this.dictValue - 1];
posItem.details = this.list;
posItem.isSubmit = isSubmit; //当前项是否提交
if (!this.checkInspectionResult(this.list)) {
posItem.status = 2; //1表示已经巡检过有异常
posItem.statusLable = "巡检异常";
} else {
posItem.status = 1; //1表示已经巡检过没有异常
posItem.statusLable = "已巡检";
}
// 根据获取到的每个井道的isSubmit来判断是否有暂存状态,只有有一个井道是暂存,那就是编辑中、暂存状态
let typeSubmit = this.typeSubmit(tabList);
const data = {
...baseInfo,
isSubmit: isSubmit, //0暂存(编辑中) 1提交(待同步,已同步)
inspectionNumber: 1,
isException: posItem.status == 2 ? 1 : 0,
items: [],
synchronization: 0, // 是否同步过
submitTime: moment().format("yyyy-MM-DD"), // 记录提交时间
submitMonth: moment().format("yyyy-MM"), // 记录提交月份
originData: tabList, //所有大楼和楼层的数据
};
console.log("getParams,data", data);
return data;
}
},
countStatus(data) {
let statusNotZero = 0;
let statusEqualsTwo = 0;
console.log("data", data);
// 遍历数据(假设 data 是数组)
data.forEach((item) => {
console.log(4515, item);
// 检查是否有 originData
item.position.forEach((floor) => {
// 检查是否有 position
// 获取 status(可能是数字或字符串)
const status = floor.status;
// 转换为数字进行比较
const statusNum = parseInt(status, 10);
if (!isNaN(statusNum)) {
if (statusNum !== 0) {
statusNotZero++;
}
if (statusNum === 2) {
statusEqualsTwo++;
}
}
});
});
return {
statusNotZero,
statusEqualsTwo,
};
},
typeSubmit(originData) {
return originData.reduce((acc, curr) => {
return (
acc +
curr.position.reduce((innerAcc, innerCurr) => {
return innerCurr.status === 0 ? innerAcc + 1 : innerAcc;
}, 0)
);
}, 0);
},
// 检查是否存在异常
checkInspectionResult(arr) {
return !arr.some((obj) => obj.inspectionResult === 1);
},
// 提交
async submit(isSubmit = 1) {
// 校验是否通过
if (isSubmit && !this.isAllTabValid().valid) {
uni.showToast({
title: "请填写完整必填项",
icon: "none",
});
return false;
}
const params = this.getParams(isSubmit); //数据获取
// const all_data = this.$store.state.all_data; //获取全部数据
let logContent = "";
console.log("this.uid", this.uid);
console.log("all_data", this.all_data);
// 写数据到indexedDB
// 处理数据
const send = dataToSql(params);
let api;
if (this.uid) {
send.id = this.uid;
api = inspectApi.update;
} else {
api = inspectApi.save;
}
try {
let saveRes = await api(send);
if (this.uid) {
const index = this.all_data.findIndex(
(element) => element.uid == this.uid
);
params.uid = this.uid;
this.all_data[index] = params;
logContent = getLogContent(
LOG_TYPE_ENUM.edit,
`${params.recordName}(${params.inspectionCode})`,
"巡检模块"
);
} else {
params.uid = new Date().getTime(); // 唯一标识 pad 端使用
this.all_data.push(params);
logContent = getLogContent(
LOG_TYPE_ENUM.add,
`${params.recordName}(${params.inspectionCode})`,
"巡检模块"
);
}
// 更新巡检list
const userInfo = this.userInfo;
console.log("all_data存储", this.all_data);
this.$store.commit("SET_ALL_DATA", this.all_data);
const inspectList = this.all_data.filter(
(item) => item.createByName == userInfo.user
);
console.log("inspectList", inspectList);
writeInspectionData(inspectList, userInfo.user);
// 更新日志
const log_list = this.$store.state.log_list;
logContent.inspectionType = params.inspectionType;
log_list.push(logContent);
this.$store.commit("SET_LOG_LIST", log_list);
addLog(log_list).then((res) => {
console.log("日志文件写入成功");
});
// 清空基础缓存信息
// this.$store.commit("SET_TEMP_DATA", {}); // 缓存[巡检信息]
uni.showToast({
title: isSubmit ? "提交成功1" : "保存草稿成功",
icon: "success",
});
uni.navigateTo({
url: `/pages/shaftInspection/shaftInspectionList?uid=${
this.uid ? this.uid : saveRes.lastInsertId
}&backValue=${this.backValue}`,
});
} catch (err) {
console.log("err", err);
}
},
// 检查所有Tab 的必填项是否填写完整
isAllTabValid() {
// 遍历所有巡检项
for (let i = 0; i < this.list.length; i++) {
const item = this.list[i];
// 1. 检查是否填写了巡检结论
if (
item.inspectionResult === null ||
item.inspectionResult === undefined
) {
return {
valid: false,
message: `请填写【${this.tabs[i].label}】的巡检结论`,
tabIndex: i,
};
}
// 如果巡检结论为正常,则不对摘要和现场照片做必填校验
if (item.inspectionResult === 0) {
continue;
}
// 2. 检查是否填写了情况摘要
if (!item.conclusion || item.conclusion.trim() === "") {
return {
valid: false,
message: `请填写【${this.tabs[i].label}】的情况摘要`,
tabIndex: i,
};
}
// 3. 如果是异常情况,检查是否上传了照片
if (
item.inspectionResult === 1 &&
(!item.photos || item.photos.length === 0)
) {
return {
valid: false,
message: `【${this.tabs[i].label}】为异常情况,必须上传现场照片`,
tabIndex: i,
};
}
}
// 所有检查都通过
return {
valid: true,
message: "",
};
},
// 检查当前 Tab 的必填项是否填写完整
// 下一项
nextTab() {
// if (!this.isCurrentTabValid()) {
// uni.showToast({
// title: "请填写完整必填项",
// icon: "none",
// });
// return false;
// }
this.tabs[this.activeTab].status =
this.list[this.activeTab].inspectionResult === 0 ? "1" : "2"; // 更新当前 Tab 的数据
if (this.activeTab === 2) {
this.isSubmitEnabled = true;
} else {
this.switchTab(this.activeTab + 1);
}
},
// 切换 Tab
switchTab(index) {
this.activeTab = index;
this.updateCurrentTabData();
},
// 显示弹窗
showPopup(item) {
console.log(item);
this.$refs.customPopup.open(item);
},
// 处理弹窗确认
handlePopupConfirm(summary) {
this.list[this.activeTab].conclusion = summary; // 回显到文字显示区域
},
// 设置巡检结论
setInspectionResult(value) {
console.log("value", value);
this.inspectionResult = value;
this.list[this.activeTab].inspectionResult = value; // 更新当前 Tab 的数据
this.tabs[this.activeTab].status = value === 0 ? "1" : "2"; // 更新当前 Tab 的数据
},
// 返回
back() {
uni.navigateTo({
url: `/pages/shaftInspection/shaftInspectionList?uid=${this.uid}&backValue=${this.backValue}`,
});
},
// 关闭弹窗
closePopup() {
this.switchTab((this.activeTab + 1) % this.tabs.length);
},
},
};
</script>
<style scoped lang="less">
.uni-nav-bar-text {
height: 28.8px;
width: 28.8px;
background: #ffffff;
border: 0.32px solid rgba(224, 224, 224, 1);
border-radius: 14.4px;
color: #333;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
}
.container {
padding: 19.2px;
height: calc(100vh - 148px);
}
.profile-section {
width: 100%;
margin-bottom: 10.24px;
.profile-box {
background-color: #fff;
border-radius: 7.68px;
padding: 10.24px 20.48px;
display: flex;
justify-content: space-between;
align-items: center;
position: relative;
.profile-left {
display: flex;
align-items: center;
.avatar {
position: relative;
width: 32.4px;
height: 32.4px;
border-radius: 50%;
overflow: hidden;
margin-right: 7.2px;
image {
width: 100%;
height: 100%;
}
.change-password {
position: absolute;
bottom: 0;
left: 0;
right: 0;
background-color: rgba(0, 0, 0, 0.5);
text-align: center;
height: 14.08px;
font-family: PingFangSC-Regular;
font-size: 7.68px;
color: #ffffff;
line-height: 12.8px;
font-weight: 400;
}
}
.info {
.username {
font-size: 12.8px;
color: #000000;
line-height: 17.92px;
font-weight: 500;
margin-bottom: 5.76px;
}
.number {
font-size: 10.24px;
color: #4a4a4a;
line-height: 17.92px;
font-weight: 400;
.value {
color: #000000;
}
}
}
}
.action-btn {
width: 145.6px;
height: 38.4px;
line-height: 38.4px;
background: #ffffff;
border: 0.8px solid rgba(224, 224, 224, 1);
box-shadow: 0px 8px 19.2px 0px rgba(185, 185, 185, 0.24);
border-radius: 21.6px 19.2px 19.2px 21.6px;
font-size: 16px;
color: #000000;
text-align: center;
font-weight: 400;
position: absolute;
right: 20px;
top: 15px;
&.complete-btn {
background-image: linear-gradient(180deg, #3773f6 0%, #2c57f6 99%);
color: #ffffff;
}
}
}
}
.module {
background: #ffffff;
height: 100%;
border-radius: 9.6px;
padding: 12.8px 20px;
}
.title-bar {
display: flex;
align-items: center;
margin-bottom: 8px;
.blue-line {
width: 3.2px;
height: 12.8px;
background-color: #007aff;
margin-right: 6.4px;
}
.title {
font-size: 12.8px;
font-weight: bold;
}
.location {
margin-left: 6.4px;
color: #666;
}
.submit-btn {
position: absolute;
right: 19.2px;
width: 20%;
background-color: #ccc;
color: #fff;
border-radius: 3.2px;
padding: 3.2px 6.4px;
font-size: 9.6px;
&.active {
background-color: #007aff;
}
}
}
.description {
font-size: 11.2px;
color: #666;
}
.tab-buttons {
display: flex;
justify-content: flex-start;
align-items: center;
margin-bottom: 8px;
gap: 16px;
}
.tip {
width: 100%;
height: 27.2px;
background: rgba(55, 116, 246, 0.05);
border: 0.8px solid rgba(55, 116, 246, 0.3);
border-radius: 8px;
font-size: 11.2px;
color: #4a4a4a;
letter-spacing: 0;
line-height: 27.2px;
font-weight: 400;
padding: 0 9.6px;
.icon-tixing {
color: #3774f6;
font-size: 11.2px;
margin-right: 6.4px;
}
}
.tab-item {
display: flex;
align-items: flex-start;
position: relative;
padding: 6.4px 0;
cursor: pointer;
white-space: nowrap;
.iconfont {
font-size: 12px;
margin-right: 4px;
&.icon-weixunjian {
color: #959595;
}
&.icon-shibai1 {
color: #ff4a34;
}
&.icon-wancheng {
color: #3774f6;
}
}
.tab-icon {
width: 8.4px;
height: 8.4px;
margin-bottom: 3.2px;
margin-right: 2.4px;
}
.tab-text {
font-size: 11.2px;
color: #333;
}
&.active {
.tab-text {
color: #3774f6;
}
.underline {
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 100%;
height: 1.6px;
background-color: #3774f6;
}
}
}
.form-item {
display: flex;
align-items: center;
padding: 9.6px 0;
line-height: 28.8px;
border-bottom: 0.8px solid #f2f3f5;
.form-label {
font-size: 11.2px;
margin-right: 25.6px;
width: 58.4px;
text-align: right;
color: #7c7c7c;
.required {
color: red;
margin-right: 3.2px;
}
}
.conclusion {
color: #c7c7c7;
font-size: 11.2px;
&.have {
color: #000;
}
}
.label {
font-size: 11.2px;
}
.switch-container {
display: flex;
gap: 9.6px;
.status-btn {
flex: 1;
padding: 5.6px 19.2px;
font-size: 12.8px;
color: #000000;
background: #f2f2f2;
text-align: center;
font-weight: 400;
line-height: 17.6px;
border-radius: 14.4px;
&.active {
color: #ffffff;
background: #3774f6;
border: 0.32px solid rgba(224, 224, 224, 1);
}
}
}
.input-box {
flex: 1;
border-radius: 3.2px;
font-size: 12.8px;
line-height: 19.2px;
}
.photo-limit {
font-size: 12.8px;
color: #959595;
line-height: 19.2px;
font-weight: 400;
}
.photo-container {
display: flex;
flex-wrap: wrap;
margin-bottom: 6.4px;
.photo-item {
position: relative;
margin-right: 6.4px;
margin-bottom: 6.4px;
.photo {
width: 57.6px;
height: 57.6px;
border-radius: 3.2px;
margin-left: 9.6px;
}
.delete-photo {
position: absolute;
top: -6.4px;
right: -6.4px;
background-color: #ff4d4f;
color: #fff;
width: 12.8px;
height: 12.8px;
border-radius: 50%;
text-align: center;
line-height: 12.8px;
font-size: 9.6px;
}
}
}
.photo-btn {
background: #ffffff;
border: 0.272px solid rgba(221, 221, 221, 1);
border-radius: 1.64px;
width: 57.6px;
height: 57.6px;
font-size: 57.6px;
color: #cccccc;
text-align: center;
line-height: 51.2px;
}
}
.submit-module {
display: flex;
justify-content: center;
position: fixed;
gap: 16px;
left: 50%;
transform: translateX(-50%);
bottom: 25.6px;
.action-btn {
width: 145.6px;
height: 38.4px;
line-height: 38.4px;
background: #ffffff;
border: 0.8px solid rgba(224, 224, 224, 1);
box-shadow: 0px 8px 19.2px 0px rgba(185, 185, 185, 0.24);
border-radius: 21.6px 19.2px 19.2px 21.6px;
font-size: 16px;
color: #000000;
text-align: center;
font-weight: 400;
&.complete-btn {
background-image: linear-gradient(180deg, #3773f6 0%, #2c57f6 99%);
color: #ffffff;
}
}
}
.popup-content {
background-color: white;
padding: 32px;
border-radius: 8px;
text-align: center;
position: relative;
width: 240px;
.close-icon {
position: absolute;
top: 8px;
right: 8px;
font-size: 16px;
cursor: pointer;
}
.icon-success {
font-size: 32px;
color: green;
margin-bottom: 16px;
}
.success-text {
font-size: 14.4px;
margin-bottom: 16px;
}
.next-button {
background-color: blue;
color: white;
padding: 8px 16px;
border-radius: 4px;
cursor: pointer;
font-size: 12.8px;
&:hover {
opacity: 0.9;
}
}
}
</style>
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论