提交 ca6366a6 authored 作者: BaoChunXian's avatar BaoChunXian

feayt: 井道巡检

上级 7a83284c
......@@ -178,4 +178,22 @@ export default {
}
console.log("更新完成...");
},
async updateSignImg(data) {
console.log("开始更新巡检签名图片", data);
let sqllitedb = await SqlliteDbUtil.initSqlliteDB();
try {
if (!data.id) {
throw new Error("更新操作需要提供 id");
}
let sql = `UPDATE ${table.inspectionRecordName} SET
signImg = '${data.signImg}'
WHERE id = ${data.id}`;
await sqllitedb.executeSQL(sql);
} catch (e) {
console.log(e.message);
} finally {
await sqllitedb.closeDB();
}
console.log("更新完成...");
},
};
<template>
<view class="inspect-item" @click="toPage">
<view class="content" :class="details.synchronization == 1 ? 'synchronization' : ''">
<view class="content" :class="details.synFlag == 1 ? 'synchronization' : ''">
<view class="name">{{
details.isSubmit == 0 ? "编辑中" :details.synchronization == 0 ? "待同步" : "已同步"
details.isSubmit == 0 ? "编辑中" :details.synFlag == 0 ? "待同步" : "已同步"
}}</view>
<view class="info">
<view class="info-row">
......@@ -64,7 +64,7 @@
}`;
uni.navigateTo({
url: `${url}&uid=${this.details.uid}`,
url: `${url}&uid=${this.details.id}`,
});
},
},
......
......@@ -54,8 +54,8 @@ export default {
props: {
// 父组件传递的详情
detailsItem: {
type: Object,
default: () => {},
type: Array,
default: () => ([]),
},
},
data() {
......
<template>
<view class="synchronous-dialog">
<view class="synchronous-content">
<view class="row-item">
<text class="title">待同步数据</text>
</view>
<view class="row-item count-num">
<text class="num">{{ 1 }}</text>
<text></text>
</view>
<view class="operating-instructions">
<view class="title">操作说明:</view>
<view class="instructions-item">
1、在PAD端,完成巡检记录后。
</view>
<view class="instructions-item">
2、将PAD直联PC机,在PAD端点击“数据同步“,同时也在PC端确认“接收同步数据”。
</view>
<view class="instructions-item">
3、PC端同步数据完成后,列表自动刷新展示同步数据;且PAD端已同步数据不支持再次修改。
</view>
</view>
<view class="row-item bottom-row">
<button class="button" :loading="loading" @click="clickHandle">
数据同步
</button>
</view>
<!-- 关闭按钮 -->
<div class="close-button">
<text class="iconfont icon-shibai1" @click="close"></text>
</div>
</view>
</view>
</template>
<script>
import {
SYNCHRONIZE_DATA_PAD,
checkAndCreateDirectory,
createFileWithPlusIO,
setSm2,
USER_FILE_NAME,
getUserList,
} from "@/utils/systemCofig";
import {
writeInspectionData,
copyDirectory,
deleteAllFilesInDirectory,
addLog,
getLogContent,
LOG_TYPE_ENUM,
} from "@/utils/IoReadingAndWriting.js";
import moment from "moment";
import { getAllInspections } from "@/request/index.js";
import { Base64 } from "js-base64";
export default {
props: {
list: {
type: Array,
default: () => {
return [];
},
},
},
components: {},
data() {
return {
loading: false,
notSynchronizationList: [], // 未同步数据
allList: [], // 所有数据
};
},
watch: {
list(newVal) {
console.log("newVal",newVal);
this.init()
},
},
// async mounted() {
// const temp = [];
// this.list.forEach((item) => {
// temp.push(...(item.list || []));
// });
// console.log("this.list", this.list);
// console.log("temp", temp);
// this.notSynchronizationList = temp.filter(
// (item) => item.synchronization == 0 && item.isSign === true
// );
// getAllInspections().then((res) => {
// this.allList = res;
// });
// },
methods: {
init() {
const temp = [];
this.list.forEach((item) => {
temp.push(...(item.list || []));
});
console.log("this.list", this.list);
console.log("temp", temp);
this.notSynchronizationList = temp.filter(
(item) => item.synchronization == 0 && item.isSign === true
);
getAllInspections().then((res) => {
this.allList = res;
});
},
close() {
this.$emit("close");
},
/**
* 1.生成两个文件. 机房文件 和 井道文件
* 2. 更新巡检数据状态 synchronization 置为 1
* 3. 写入数据
* 读取上一次打包的文件, 复制到 [ history ] 文件夹中
*/
clickHandle() {
if (this.loading) return;
const directoryPath = `${SYNCHRONIZE_DATA_PAD}/发送数据`;
const targetDirectoryPath = `${SYNCHRONIZE_DATA_PAD}/history`;
checkAndCreateDirectory(directoryPath).then(() => {
copyDirectory(directoryPath, targetDirectoryPath)
.then(() => {
return deleteAllFilesInDirectory(directoryPath);
})
.then(() => {
this.coverData();
})
.catch((error) => {
uni.showToast({
title: error,
icon: "none",
duration: 1000,
});
});
});
},
// 处理数据
coverData() {
const userName = this.$store.state.now_user.user;
const notSynchronizationList = this.notSynchronizationList;
const allList = this.allList;
console.log("窗口allList", allList);
console.log(
"窗口this.notSynchronizationList",
this.notSynchronizationList
);
let timeStr = moment().format("yyyy_MM_DD_hh_mm_ss");
const JFXJ_DATA = notSynchronizationList
.filter((item) => item.inspectionType == 1)
.map((item) => {
return item;
}); // 机房数据类型是 1
const JDXJ_DATA = notSynchronizationList
.filter((item) => item.inspectionType == 2)
.map((item) => {
return item;
}); // 井道数据类型是 2
console.log(5151, JFXJ_DATA, JDXJ_DATA);
this.loading = true;
const tmepList = [];
if (JFXJ_DATA.length) {
let JFXJ_DATA_FILE_NAME = `${userName}_JFXJ_${timeStr}.txt`;
tmepList.push(this.packedData(JFXJ_DATA, JFXJ_DATA_FILE_NAME));
}
JDXJ_DATA.forEach((item, index) => {
let JDXJ_DATA_FILE_NAME = `${userName}_JDXJ_${timeStr}_${index}.txt`;
tmepList.push(this.packedData(item, JDXJ_DATA_FILE_NAME));
});
console.log("同步窗口");
console.log("同步窗口", tmepList);
Promise.all(tmepList)
.then(() => {
// 更新巡检数据状态
const synchronizationUids = notSynchronizationList.map((item) => {
item.synchronization = 1;
return item.uid;
});
const userData = {};
allList.forEach((item) => {
if (synchronizationUids.includes(item.uid)) {
item.synchronization = 1;
}
if (userData[item.createByName]) {
userData[item.createByName].push(item);
} else {
userData[item.createByName] = [item];
}
});
this.$store.commit("SET_ALL_DATA", allList);
const keys = Object.keys(userData);
const promiseArr = keys.map((key) => {
const val = userData[key];
return writeInspectionData(val, key);
});
Promise.all(promiseArr)
.then(() => {
setTimeout(() => {
uni.showToast({
title: "打包成功",
icon: "none",
duration: 2000,
});
this.close();
this.loading = false;
// 生成日志
const logContent = getLogContent(
LOG_TYPE_ENUM.sys,
"",
"同步模块"
);
const log_list = this.$store.state.log_list;
log_list.push(logContent);
this.$store.commit("SET_LOG_LIST", log_list);
addLog(log_list).then((res) => {});
// 更新同步时间
this.updateSysTime();
}, 2 * 1000);
})
.catch((error) => {
this.loading = false;
uni.showToast({
title: error,
icon: "none",
duration: 2000,
});
});
})
.catch(() => {
setTimeout(() => {
uni.showToast({
title: "打包失败",
icon: "none",
duration: 2000,
});
this.loading = false;
}, 2 * 1000);
});
},
// 打包文件
packedData(content, fileName) {
const fileContent = setSm2(content);
return createFileWithPlusIO(
`${SYNCHRONIZE_DATA_PAD}/发送数据`,
fileName,
fileContent
);
},
// 更新最近一次同步时间
updateSysTime() {
getUserList().then((personList) => {
const now_user = this.$store.state.now_user;
const key = personList.findIndex(
(item) => item.userId == now_user.userId
);
// 更新用户同步时间
const userInfo = personList[key];
const LastSynchronizationTime = moment().format("yyyy-MM-DD HH:mm");
personList[key].LastSynchronizationTime = LastSynchronizationTime;
userInfo.LastSynchronizationTime = LastSynchronizationTime;
this.$store.commit("SET_USER", userInfo);
uni.setStorageSync("last_time", userInfo.LastSynchronizationTime || "");
// 更新用户数据
const fileContent = JSON.stringify(
Base64.encode(JSON.stringify(personList))
);
uni.setStorage({
key: "user_data",
data: JSON.stringify(personList),
fail: (error) => {
console.log("APP.vue 存储数据失败", error);
},
});
createFileWithPlusIO(SYNCHRONIZE_DATA_PAD, USER_FILE_NAME, fileContent)
.then(() => {
console.log("---用户数据更新成功");
})
.catch((error) => {
console.log("---用户数据更新失败", error);
});
});
},
},
};
</script>
<style scoped lang="less">
.synchronous-dialog {
position: fixed;
z-index: 999;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
.synchronous-content {
padding: 3% 20px 32px 24px;
width: 400px;
height: 60%;
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: 160px;
height: 40px;
color: #fff;
}
}
// 关闭按钮
.close-button {
position: absolute;
bottom: -40px;
left: 50%;
transform: translateX(-50%);
.iconfont {
font-size: 24px;
}
}
}
}
</style>
......@@ -40,6 +40,17 @@
<button v-if="!isSign" class="record-button" @click="toSign">
巡检人签字
</button>
<view v-else class="action-container">
<image
class="sign-img"
:src="detailsInfo.signImg"
mode="aspectFit">
</image>
<button class="record-button small" @click="toSign">
重签
</button>
<view class="inspection-button" @click="openDialog(true)">数据同步</view>
</view>
</view>
</view>
</view>
......@@ -127,10 +138,10 @@
<!-- 左侧模块 -->
<view class="left-side">
<view
v-for="(tab, index) in tabsDetail.slice(0, 6)"
v-for="(tab, index) in tabsDetail.slice(0, 7)"
:key="index"
:class="['tab-item', { active: activeTab === index }]"
@click="getActiveTabDetails(index)"
@click="getActiveTabDetails(index, tab)"
>
{{ tab }}
</view>
......@@ -155,7 +166,7 @@
status1: position.status == 1,
status2: position.status == 2,
}"
@click="getDetailsItem(item.value, position.dictValue)"
@click="getDetailsItem(item.value, position.dictCode)"
>
<view class="card-content">
<view class="status-line">
......@@ -189,6 +200,11 @@
</view>
</view>
<signDialog ref="signDialog" @confirm="handlePopupConfirm"></signDialog>
<!-- <Dialog
v-show="showSyncDialog"
:list="list"
@close="openDialog(false)"
></Dialog> -->
</view>
</template>
......@@ -202,17 +218,21 @@ import {
LOG_TYPE_ENUM,
} from "@/utils/IoReadingAndWriting.js";
import { getInspectionDetails } from "@/request/index.js";
import inspectApi from "@/api/inspect";
import signDialog from "@/components/signDialog.vue";
import detail from "./model/detail.vue";
import Dialog from './model/dialog.vue'
import { sqlToData, dataToSql } from "./shared";
export default {
components: {
signDialog,
detail,
Dialog
},
data() {
return {
tabs: ["所有井道"], // 选项卡内容
tabsDetail: [],
tabsDetail: ["所有井道"],
activeTab: 0, // 默认选中的选项卡
inspectionNumber: 0, // 已巡检的井道数量
cards: [
......@@ -243,6 +263,8 @@ export default {
all_data: [], //所有数据
detailsItem: {}, //单个井道详情
isShow: false,
showSyncDialog: false,
list: []
};
},
computed: {
......@@ -287,7 +309,7 @@ export default {
};
});
this.cardsInfo = this.tabList;
this.inspectionCode = `JFXJ${moment().format("yyyyMMDDHHmmss")}${
this.inspectionCode = `JDXJ${moment().format("yyyyMMDDHHmmss")}${
Math.floor(Math.random() * 900) + 100
}`;
console.log("this.tabList", this.tabList);
......@@ -308,8 +330,9 @@ export default {
});
},
// 获取井道详情
getDetailsItem(value, dictValue) {
let item = this.detailsInfo.originData[value - 1].position[dictValue - 1];
getDetailsItem(value, dictCode) {
let item = this.detailsInfo.originData.find(building => building.value === value)?.position.find(pos => pos.dictCode === dictCode)
if (item.status < 1) {
uni.showToast({
title: "该井道暂无数据",
......@@ -329,25 +352,45 @@ export default {
this.cardsInfo = [this.tabList[index - 1]];
}
},
getActiveTabDetails(index) {
getActiveTabDetails(index, tab) {
this.activeTab = index;
this.cardsInfo = [this.tabList[index]];
// this.cardsInfo = [selected];
// this.cardsInfo = [this.tabList[index]];
if (this.activeTab == 0) {
this.cardsInfo = this.tabList;
} else {
let selected = this.tabList.find( t => t.name === tab)
this.cardsInfo = [selected];
}
this.isShow = false;
},
// 回显数据
getDetails(uid) {
uni.showLoading();
getInspectionDetails(uid)
inspectApi
.info(uid)
.then((res) => {
const detailsInfo = res;
console.log(res)
const detailsInfo = sqlToData(res);
console.log("detailsInfo", detailsInfo);
this.detailsInfo = detailsInfo;
this.inspectionNumber = detailsInfo.inspectionNumber;
if(detailsInfo.synchronization === 1) {
// 已同步数据的查看详情时,只展示'已巡检'的井道信息,过滤未巡检的井道
let defaultList = detailsInfo.originData
this.cardsInfo = this.tabList = defaultList.filter(building => {
building.position = building.position.filter(pos => pos.status === 1)
return building.position.length
})
} else {
this.cardsInfo = this.tabList = detailsInfo.originData;
}
this.inspectionCode = detailsInfo.inspectionCode;
this.cardsInfo = this.tabList = detailsInfo.originData;
// this.cardsInfo = this.tabList = detailsInfo.originData;
this.isSubmit = this.detailsInfo.isSubmit;
this.isSign = this.detailsInfo.isSign;
this.isSign = !!this.detailsInfo.signImg;
this.cardsInfo.forEach((item) => {
this.tabs.push(item.name);
this.tabsDetail.push(item.name);
......@@ -419,10 +462,18 @@ export default {
addLog(log_list).then((res) => {
console.log("日志文件写入成功");
});
if(type === 'sign') {
console.log(123456)
inspectApi.updateSignImg({
id: params.id,
signImg: params.signImg
})
}
uni.showToast({
title: type == "sign" ? "签字成功" : "同步成功",
icon: "success",
});
this.getActiveTabDetails(0);
},
lookTable() {
......@@ -447,6 +498,19 @@ export default {
});
}
},
openDialog(val) {
if(val) {
this.list = [
{
time: this.detailsInfo.submitMonth,
list: [this.detailsInfo]
}
]
} else {
this.list = []
}
this.showSyncDialog = val
}
},
};
</script>
......@@ -580,6 +644,32 @@ export default {
line-height: 28.8px;
font-weight: 400;
}
.action-container {
display: flex;
.record-button.small {
width: 75px;
margin-right: 10px;
}
.inspection-button {
display: flex;
align-items: center;
justify-content: center;
width: 115.2px;
height: 28.8px;
color: #fff;
background-image: linear-gradient(180deg, #3773f6 0%, #2c57f6 99%);
box-shadow: 0px 8px 19.2px 0px rgba(51, 104, 246, 0.24);
border-radius: 14.4px;
}
.sign-img {
width: 80px;
height: 28.8px;
margin-right: 10px;
border: 1px solid #ccc;
// border-right: none;
border-radius: 3px;
}
}
}
}
}
......
......@@ -142,6 +142,7 @@
><custom-popup
ref="customPopup"
:inspectionItem="tabs[activeTab].label"
:fixedWords="['已检查', '正常', '异常', '需处理', '已处理']"
@confirm="handlePopupConfirm"
></custom-popup>
</view>
......@@ -165,6 +166,8 @@ 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: {
......@@ -273,9 +276,10 @@ export default {
// 回显数据
getDetails(uid) {
uni.showLoading();
getInspectionDetails(uid)
inspectApi
.info(uid)
.then((res) => {
const detailsInfo = res;
const detailsInfo = sqlToData(res);
console.log("getDetails", res);
let list =
detailsInfo.originData[this.value - 1].position[this.dictValue - 1]
......@@ -505,7 +509,7 @@ export default {
return !arr.some((obj) => obj.inspectionResult === 1);
},
// 提交
submit(isSubmit = 1) {
async submit(isSubmit = 1) {
// 校验是否通过
if (isSubmit && !this.isAllTabValid().valid) {
uni.showToast({
......@@ -519,56 +523,72 @@ export default {
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) {
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})`,
"巡检模块"
);
send.id = this.uid
api = inspectApi.update
} else {
params.uid = new Date().getTime(); // 唯一标识 pad 端使用
this.all_data.push(params);
logContent = getLogContent(
LOG_TYPE_ENUM.add,
`${params.recordName}(${params.inspectionCode})`,
"巡检模块"
);
api = inspectApi.save
}
// 更新巡检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);
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
);
// 更新日志
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("日志文件写入成功");
});
console.log("inspectList", inspectList);
writeInspectionData(inspectList, userInfo.user);
// 清空基础缓存信息
// this.$store.commit("SET_TEMP_DATA", {}); // 缓存[巡检信息]
uni.showToast({
title: isSubmit ? "提交成功" : "保存草稿成功",
icon: "success",
});
uni.navigateTo({
url: `/pages/shaftInspection/shaftInspectionList?uid=${params.uid}&backValue=${this.backValue}`,
});
// 更新日志
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() {
......@@ -587,7 +607,10 @@ export default {
tabIndex: i,
};
}
// 如果巡检结论为正常,则不对摘要和现场照片做必填校验
if(item.inspectionResult === 0) {
continue
}
// 2. 检查是否填写了情况摘要
if (!item.conclusion || item.conclusion.trim() === "") {
return {
......
import moment from "moment";
import store from "@/store";
// 将现有机房巡检数据转换为SQL数据所需要格式
export function dataToSql(data) {
let synFlag = 0;
if (data.isSubmit == 0) {
synFlag = 0;
} else {
synFlag = data.synchronization;
}
const send = {
inspectionType: data.inspectionType,
inspectionCode: data.inspectionCode,
recordName: `${moment().format("yyyyMMDD")}-井道巡检`,
inspectionTime: moment().format("yyyy-MM-DD HH:mm"),
isException: data.isException, // 是否异常:0 否 1 是 2 巡检中
userId: store.state.now_user.userId,
userName: store.state.now_user.user,
synFlag: synFlag, // 0.未同步,1.已同步,2.编辑
signImg: data.signImg || "",
createBy: store.state.now_user.userId,
createTime: data.id ? data.createTime : `${new Date().getTime()}`,
updateTime: `${new Date().getTime()}`,
updateBy: store.state.now_user.userId,
inspectionData: data.originData,
};
console.log("dataToSql", send);
return send;
}
export function sqlToData(sqlData) {
try {
let isSubmit;
let synchronization;
if (sqlData.synFlag === 0) {
isSubmit = 0;
synchronization = 0;
} else {
isSubmit = 1;
synchronization = sqlData.synFlag;
}
const originData = JSON.parse(sqlData.inspectionData || "{}");
console.log(originData)
const inspectedItems = originData.reduce((acc,cur) => {
acc.push(...cur.position)
return acc
}, []).filter((item) => item.status == 1 || item.status == 2)
console.log(inspectedItems)
// 获取已经巡检过的数量
const inspectionNumber = inspectedItems.length;
const ret = {
id: sqlData.id,
inspectionType: sqlData.inspectionType,
inspectionCode: sqlData.inspectionCode,
isException: sqlData.isException,
signImg: sqlData.signImg,
createTime: sqlData.createTime,
isSubmit: isSubmit,
synchronization: synchronization,
originData,
inspectionNumber
};
console.log(ret)
return ret;
} catch (err) {
console.log(err)
}
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论