From 3471eeaf92a2ea32aa06ddfb231ee6c6d8b60bad Mon Sep 17 00:00:00 2001
From: feiyu02 <risaku@163.com>
Date: 星期一, 01 十二月 2025 08:41:12 +0800
Subject: [PATCH] 新增监管任务界面巡查人员统计信息
---
src/views/fysp/evaluation/components/precheck/components/CompCheckSource.vue | 2
src/views/fysp/config/DeviceMatch.vue | 4
src/components/bg-task/FYBgTaskItem.vue | 4
src/views/fysp/check/components/CompProRecent.vue | 8
src/utils/time-util.js | 54 ++++++++
src/views/fysp/evaluation/components/precheck/CompPreCheck.vue | 4
src/api/index.js | 4
src/components/map/BaseMap.vue | 4
src/components/list-item/ItemSubTask.vue | 2
src/views/fysp/task/components/CompSubTaskList.vue | 9 +
src/views/fysp/evaluation/components/precheck/components/CompCheckConfirm.vue | 2
src/views/fysp/task/TaskManage.vue | 12 +
src/views/fysp/task/components/CompMonitorPlan.vue | 201 +++++++++++++++++++++++++++-----
13 files changed, 253 insertions(+), 57 deletions(-)
diff --git a/src/api/index.js b/src/api/index.js
index e512156..73cda5e 100644
--- a/src/api/index.js
+++ b/src/api/index.js
@@ -13,8 +13,8 @@
let ip2_file = 'https://fyami.com.cn/';
if (debug) {
- ip1 = 'http://192.168.0.103:9001/';
- // ip1 = 'http://localhost:9001/';
+ // ip1 = 'http://192.168.0.103:9001/';
+ ip1 = 'http://localhost:9001/';
// ip1_file = 'http://192.168.0.138:8080/';
// ip2 = 'http://192.168.0.138:8080/';
// ip2_file = 'https://fyami.com.cn/';
diff --git a/src/components/bg-task/FYBgTaskItem.vue b/src/components/bg-task/FYBgTaskItem.vue
index df9b060..be619e6 100644
--- a/src/components/bg-task/FYBgTaskItem.vue
+++ b/src/components/bg-task/FYBgTaskItem.vue
@@ -31,10 +31,10 @@
</el-col>
<el-col :span="12">
<el-text type="default" size="default" tag="div"
- >寮�濮嬶細{{ $fm.formatYMDH(model.startTime) }}</el-text
+ >寮�濮嬶細{{ $fm.formatYMDHMS(model.startTime) }}</el-text
>
<el-text type="default" size="default" tag="div"
- >缁撴潫锛歿{ $fm.formatYMDH(model.endTime) }}</el-text
+ >缁撴潫锛歿{ $fm.formatYMDHMS(model.endTime) }}</el-text
>
</el-col>
</el-row>
diff --git a/src/components/list-item/ItemSubTask.vue b/src/components/list-item/ItemSubTask.vue
index b53fd56..93c3e8f 100644
--- a/src/components/list-item/ItemSubTask.vue
+++ b/src/components/list-item/ItemSubTask.vue
@@ -31,7 +31,7 @@
<el-icon class="m-r-4" size="16"><AlarmClock /></el-icon>
<span>鏃堕棿锛�</span>
</div>
- {{ $fm.formatYMD(item.planstarttime) }}
+ {{ $fm.formatYMDHM(item.executionstarttime) }}鑷硔{ $fm.formatYMDHM(item.executionendtime) }}
</div>
<div class="text-info">
<div class="text-label">
diff --git a/src/components/map/BaseMap.vue b/src/components/map/BaseMap.vue
index d4aa7fb..8201a2d 100644
--- a/src/components/map/BaseMap.vue
+++ b/src/components/map/BaseMap.vue
@@ -7,7 +7,9 @@
import { createMap, map } from '@/utils/map/index';
onMounted(() => {
// 楂樺痉鍦板浘鍒濆鍖�
- createMap('container');
+ setTimeout(() => {
+ createMap('container');
+ }, 1000);
});
onUnmounted(() => {
map?.destroy();
diff --git a/src/utils/time-util.js b/src/utils/time-util.js
index e126941..cac41e8 100644
--- a/src/utils/time-util.js
+++ b/src/utils/time-util.js
@@ -29,7 +29,15 @@
}
},
- formatYMDH(date) {
+ formatYMDHM(date) {
+ if (date) {
+ return this.format(date, 'YYYY-MM-DD HH:mm');
+ } else {
+ return '----/--/-- --:--';
+ }
+ },
+
+ formatYMDHMS(date) {
if (date) {
return this.format(date, 'YYYY-MM-DD HH:mm:ss');
} else {
@@ -51,5 +59,47 @@
format +
(date < 10 ? '0' + date : date)
);
+ },
+
+ /**
+ * 灏嗙鏁拌浆鎹负涓枃鎻忚堪鏍煎紡
+ * @param {number} seconds - 绉掓暟
+ * @returns {string} 涓枃鏃堕棿鎻忚堪
+ */
+ formatSecondsToChinese(seconds) {
+ if (!seconds || seconds < 0 || isNaN(seconds)) {
+ return '--';
+ }
+
+ // 瀹氫箟鏃堕棿鍗曚綅鍜屽搴旂殑绉掓暟
+ const units = [
+ { unit: '澶�', value: 24 * 60 * 60 },
+ { unit: '灏忔椂', value: 60 * 60 },
+ { unit: '鍒�', value: 60 },
+ { unit: '绉�', value: 1 }
+ ];
+
+ let remainingSeconds = Math.floor(seconds);
+ let result = '';
+
+ // 閬嶅巻鏃堕棿鍗曚綅锛岃绠楁瘡涓崟浣嶇殑鏁伴噺
+ for (const { unit, value } of units) {
+ if (remainingSeconds >= value) {
+ const count = Math.floor(remainingSeconds / value);
+ result += `${count}${unit}`;
+ remainingSeconds %= value;
+
+ // // 濡傛灉鍓╀綑绉掓暟涓�0锛屼笖宸茬粡鏈夌粨鏋滐紝灏卞彲浠ョ粨鏉熶簡
+ // if (remainingSeconds === 0 && result) {
+ // break;
+ // }
+ // 濡傛灉宸茬粡鏈夌粨鏋滐紝灏卞彲浠ョ粨鏉熶簡
+ if (result) {
+ break;
+ }
+ }
+ }
+
+ return result;
}
-};
+};
\ No newline at end of file
diff --git a/src/views/fysp/check/components/CompProRecent.vue b/src/views/fysp/check/components/CompProRecent.vue
index 6305479..ca076d6 100644
--- a/src/views/fysp/check/components/CompProRecent.vue
+++ b/src/views/fysp/check/components/CompProRecent.vue
@@ -145,11 +145,11 @@
return {
startTime:
this.activeName === '杩戜笁涓湀'
- ? this.$fm.formatYMDH(threeMonthsAgo)
+ ? this.$fm.formatYMDHMS(threeMonthsAgo)
: this.activeName === '杩戝崐骞�'
- ? this.$fm.formatYMDH(sixMonthsAgo)
- : this.$fm.formatYMDH(oneYearAgo),
- endTime: this.$fm.formatYMDH(today),
+ ? this.$fm.formatYMDHMS(sixMonthsAgo)
+ : this.$fm.formatYMDHMS(oneYearAgo),
+ endTime: this.$fm.formatYMDHMS(today),
sceneId: this.deepCopyPro.sguid
};
},
diff --git a/src/views/fysp/config/DeviceMatch.vue b/src/views/fysp/config/DeviceMatch.vue
index 31ce579..001799d 100644
--- a/src/views/fysp/config/DeviceMatch.vue
+++ b/src/views/fysp/config/DeviceMatch.vue
@@ -133,7 +133,7 @@
districtname: formSearch.locations.dName,
towncode: formSearch.locations.tCode,
townname: formSearch.locations.tName,
- starttime: $fm.formatYMDH(formSearch.time),
+ starttime: $fm.formatYMDHMS(formSearch.time),
scensetypeid: formSearch.scenetype.value,
online: true,
// 姝ゅ鏁版嵁鏉ユ簮鍥哄畾涓洪缇界洃绠$郴缁�
@@ -157,7 +157,7 @@
function timeFormat(row) {
const time = row.createTime;
if (time) {
- return $fm.formatYMDH(time);
+ return $fm.formatYMDHMS(time);
} else {
return '';
}
diff --git a/src/views/fysp/evaluation/components/precheck/CompPreCheck.vue b/src/views/fysp/evaluation/components/precheck/CompPreCheck.vue
index a2b6e09..3dba2b8 100644
--- a/src/views/fysp/evaluation/components/precheck/CompPreCheck.vue
+++ b/src/views/fysp/evaluation/components/precheck/CompPreCheck.vue
@@ -71,8 +71,8 @@
districtname: v._locations.dName,
towncode: v._locations.tCode,
townname: v._locations.tName,
- starttime: this.$fm.formatYMDH(v.time),
- endtime: this.$fm.formatYMDH(v.time),
+ starttime: this.$fm.formatYMDHMS(v.time),
+ endtime: this.$fm.formatYMDHMS(v.time),
scensetypeid: v._scenetype.value,
online: true,
sourceType: v.sourceType
diff --git a/src/views/fysp/evaluation/components/precheck/components/CompCheckConfirm.vue b/src/views/fysp/evaluation/components/precheck/components/CompCheckConfirm.vue
index 1fc99ae..7c6deb2 100644
--- a/src/views/fysp/evaluation/components/precheck/components/CompCheckConfirm.vue
+++ b/src/views/fysp/evaluation/components/precheck/components/CompCheckConfirm.vue
@@ -90,7 +90,7 @@
districtname: v._locations.dName,
towncode: v._locations.tCode,
townname: v._locations.tName,
- starttime: this.$fm.formatYMDH(v.time),
+ starttime: this.$fm.formatYMDHMS(v.time),
scensetypeid: v._scenetype.value,
online: true,
sourceType: v.sourceType
diff --git a/src/views/fysp/evaluation/components/precheck/components/CompCheckSource.vue b/src/views/fysp/evaluation/components/precheck/components/CompCheckSource.vue
index 82f7e2a..2103658 100644
--- a/src/views/fysp/evaluation/components/precheck/components/CompCheckSource.vue
+++ b/src/views/fysp/evaluation/components/precheck/components/CompCheckSource.vue
@@ -309,7 +309,7 @@
// districtname: v._locations.dName,
// towncode: v._locations.tCode,
// townname: v._locations.tName,
- // starttime: this.$fm.formatYMDH(v.time),
+ // starttime: this.$fm.formatYMDHMS(v.time),
// scensetypeid: v._scenetype.value,
// online: true,
// sourceType: v.sourceType
diff --git a/src/views/fysp/task/TaskManage.vue b/src/views/fysp/task/TaskManage.vue
index 161af96..31a2926 100644
--- a/src/views/fysp/task/TaskManage.vue
+++ b/src/views/fysp/task/TaskManage.vue
@@ -37,10 +37,11 @@
>璁″垝璋冩暣</el-button
> -->
<el-tabs model-value="first">
- <el-tab-pane label="鐩戠璁″垝" name="first">
+ <el-tab-pane label="宸℃煡璁″垝" name="first">
<el-row>
<el-col :span="curSubTaskList ? 16 : 24">
<CompMonitorPlan
+ :loading="daytaskLoading"
ref="planRef"
:task="curTask.data"
:day-task-list="curDayTaskList"
@@ -51,6 +52,7 @@
<CompSubTaskList
create
v-model="curSubTaskList"
+ :date="curDay"
:loading="subTaskLoading"
:create-loading="daytaskCreateLoading"
height="56vh"
@@ -60,7 +62,7 @@
</el-col>
</el-row>
</el-tab-pane>
- <el-tab-pane label="鐩戠鍦板浘" name="second">
+ <el-tab-pane label="鍦烘櫙鍦板浘" name="second">
<CompTaskMap :plans="curMonitorObjList"></CompTaskMap>
</el-tab-pane>
</el-tabs>
@@ -283,12 +285,16 @@
fetchDayTasks() {
// 鑾峰彇鏃ヤ换鍔$粺璁′俊鎭�
this.dayTaskLoading = true;
+ this.mainLoading = true;
return taskApi
.fetchDayTasks(this.curTask.data.tguid)
.then((res) => {
this.curDayTaskList = res;
})
- .finally(() => (this.dayTaskLoading = false));
+ .finally(() => {
+ this.dayTaskLoading = false;
+ this.mainLoading = false;
+ });
},
editTask() {
this.$router.push({
diff --git a/src/views/fysp/task/components/CompMonitorPlan.vue b/src/views/fysp/task/components/CompMonitorPlan.vue
index 954a280..a9c6bf8 100644
--- a/src/views/fysp/task/components/CompMonitorPlan.vue
+++ b/src/views/fysp/task/components/CompMonitorPlan.vue
@@ -5,39 +5,141 @@
@update:model-value="onDateChange"
>
<template #header="{ date }">
- <span>{{ title }}</span>
- <el-space>
- <el-tag>鎬昏锛歿{ taskStatistic.total }}</el-tag>
- <el-tag>瀹屾垚锛歿{ taskStatistic.complete }}</el-tag>
- <el-tag>鏁存敼锛歿{ taskStatistic.changed }}</el-tag>
- </el-space>
- <!-- <span>{{ date }}</span> -->
+ <div>
+ <el-row justify="space-between">
+ <el-space>
+ <el-tag type="default"
+ >宸℃煡閲忥細{{
+ `${taskStatistic.complete}/${taskStatistic.total}`
+ }}</el-tag
+ >
+ <el-tag type="default"
+ >缁煎悎鏁存敼鐜囷細{{
+ formatPercent(
+ taskStatistic.changedProblemNum /
+ taskStatistic.totalProblemNum
+ )
+ }}</el-tag
+ >
+ <el-tag type="default">鏁存敼锛歿{ taskStatistic.changed }}</el-tag>
+ </el-space>
+ <el-space>
+ <el-text>鑱氱劍鐢ㄦ埛锛�</el-text>
+ <el-select
+ v-model="selectedUsers"
+ multiple
+ clearable
+ style="width: 150px"
+ >
+ <el-option
+ v-for="user in taskStatistic.progressPerUser"
+ :key="user.userId"
+ :label="user.userName"
+ :value="user.userName"
+ />
+ </el-select>
+ </el-space>
+ </el-row>
+ <el-row class="m-t-4">
+ <el-space wrap>
+ <el-tag
+ type="default"
+ v-for="user in taskStatistic.progressPerUser"
+ :key="user.userId"
+ >
+ {{
+ `${user.userName}锛氬贰鏌ラ噺 ${
+ user.completeTaskNum
+ }锛屽強鏃舵暣鏀圭巼 ${formatPercent(
+ user.changedProblemNumOnTime / user.totalProblemNum
+ )}锛屽钩鍧囪�楁椂 ${
+ user.avgInspectionTime ? user.avgInspectionTime : '--'
+ }`
+ }}
+ </el-tag>
+ </el-space>
+ </el-row>
+ </div>
</template>
<template #date-cell="{ data }">
<div :class="calendarDayClz(data.day)">
<div style="background-color: #f8f4f4">{{ getDay(data.day) }}</div>
<template v-if="computeDayTask(data.day)">
- <!-- <el-divider></el-divider> -->
- <el-row justify="space-between" class="m-t-16">
+ <el-row
+ v-if="computeDayTask(data.day).totalTaskNum > 0"
+ justify="space-between"
+ >
<el-space direction="vertical">
- <el-text size="small">鎬昏</el-text>
- <el-text>{{ computeDayTask(data.day).totalTaskNum }}</el-text>
+ <el-text size="small" tag="b">宸℃煡閲�</el-text>
+ <el-text size="small"
+ >{{ computeDayTask(data.day).completeTaskNum }} /
+ {{ computeDayTask(data.day).totalTaskNum }}</el-text
+ >
</el-space>
<el-space direction="vertical">
- <el-text size="small">瀹屾垚</el-text>
- <el-text>{{ computeDayTask(data.day).completeTaskNum }}</el-text>
+ <el-text size="small" tag="b">缁煎悎鏁存敼鐜�</el-text>
+ <el-text size="small">{{
+ formatPercent(
+ computeDayTask(data.day).changedProblemNum /
+ computeDayTask(data.day).totalProblemNum
+ )
+ }}</el-text>
</el-space>
- <el-space direction="vertical">
- <el-text size="small">鏁存敼</el-text>
- <el-text>{{ computeDayTask(data.day).changedTaskNum }}</el-text>
- </el-space>
- <!-- <el-statistic title="鎬昏" :value="computeDayTask(data.day).totalTaskNum" />
- <el-statistic title="瀹屾垚" :value="computeDayTask(data.day).completeTaskNum" />
- <el-statistic title="鏁存敼" :value="computeDayTask(data.day).changedTaskNum" /> -->
</el-row>
- <!-- <div>浠诲姟鎬昏锛歿{ computeDayTask(data.day).totalTaskNum }}</div>
- <div>浠诲姟瀹屾垚锛歿{ computeDayTask(data.day).completeTaskNum }}</div>
- <div>浠诲姟鏁存敼锛歿{ computeDayTask(data.day).changedTaskNum }}</div> -->
+ <div style="border-top: 1px solid #0000002f" class="m-t-4"></div>
+ <div
+ v-for="item in computeDayTask(data.day).progressPerUser"
+ :key="item.userId"
+ class="m-t-4"
+ >
+ <el-row justify="space-between">
+ <el-text
+ size="small"
+ :type="
+ selectedUsers.includes(item.userName) ? 'primary' : 'info'
+ "
+ :tag="selectedUsers.includes(item.userName) ? 'b' : 'span'"
+ >{{ item.userName }}</el-text
+ >
+ </el-row>
+ <el-row justify="space-between">
+ <!-- <el-space> -->
+ <el-text
+ size="small"
+ style="text-align: center; flex: 1"
+ :type="
+ selectedUsers.includes(item.userName) ? 'primary' : 'info'
+ "
+ :tag="selectedUsers.includes(item.userName) ? 'b' : 'span'"
+ >{{ item.completeTaskNum }}</el-text
+ >
+ <el-text
+ size="small"
+ style="text-align: center; flex: 1"
+ :type="
+ selectedUsers.includes(item.userName) ? 'primary' : 'info'
+ "
+ :tag="selectedUsers.includes(item.userName) ? 'b' : 'span'"
+ >{{
+ formatPercent(
+ item.changedProblemNumOnTime / item.totalProblemNum
+ )
+ }}</el-text
+ >
+ <el-text
+ size="small"
+ style="text-align: center; flex: 1"
+ :type="
+ selectedUsers.includes(item.userName) ? 'primary' : 'info'
+ "
+ :tag="selectedUsers.includes(item.userName) ? 'b' : 'span'"
+ >{{
+ timeUtil.formatSecondsToChinese(item.avgInspectionTime)
+ }}</el-text
+ >
+ <!-- </el-space> -->
+ </el-row>
+ </div>
</template>
</div>
</template>
@@ -47,6 +149,7 @@
import { ref, computed, onMounted, watch } from 'vue';
import taskApi from '@/api/fysp/taskApi';
import dayjs from 'dayjs';
+import timeUtil from '@/utils/time-util';
const props = defineProps({
task: {
@@ -60,16 +163,9 @@
});
const emit = defineEmits(['dateChange']);
// 閫変腑鏃ユ湡
+const selectedUsers = ref([]);
+// const dateValue = ref(new Date());
const dateValue = ref();
-// 鏃ュ巻鏍囬
-const title = computed(() => {
- if (props.task) {
- // return `${props.task.name}璁″垝`;
- return `宸℃煡璁″垝`;
- } else {
- return '';
- }
-});
// 鏃ュ巻鑼冨洿
const startDay = computed(() => dayjs(props.task.starttime));
const endDay = computed(() => dayjs(props.task.endtime));
@@ -77,7 +173,6 @@
startDay.value.toDate(),
endDay.value.toDate()
]);
-// const dateRange = computed(() => [new Date(2024, 4, 27), new Date(2024, 5, 30)]);
// 鏃ユ湡鏄惁鍦ㄤ换鍔¤寖鍥村唴
function isDayEnable(day) {
@@ -154,14 +249,52 @@
// 鎬讳换鍔$粺璁�
const taskStatistic = computed(() => {
- const res = { total: 0, complete: 0, changed: 0 };
+ const res = {
+ total: 0,
+ complete: 0,
+ changed: 0,
+ changedProblemNum: 0,
+ totalProblemNum: 0
+ };
+ const userMap = new Map();
props.dayTaskList.forEach((e) => {
res.total += e.totalTaskNum;
res.complete += e.completeTaskNum;
res.changed += e.changedTaskNum;
+ res.changedProblemNum += e.changedProblemNum;
+ res.totalProblemNum += e.totalProblemNum;
+ e.progressPerUser.forEach((user) => {
+ if (!userMap.has(user.userId)) {
+ userMap.set(user.userId, {
+ userName: user.userName,
+ completeTaskNum: 0,
+ changedProblemNumOnTime: 0,
+ totalProblemNum: 0,
+ totalInspectionTime: 0,
+ dayTaskNum: 0
+ });
+ }
+ const userItem = userMap.get(user.userId);
+ userItem.completeTaskNum += user.completeTaskNum;
+ userItem.changedProblemNumOnTime += user.changedProblemNumOnTime;
+ userItem.totalProblemNum += user.totalProblemNum;
+ userItem.totalInspectionTime += user.avgInspectionTime;
+ userItem.dayTaskNum++;
+ });
});
+ res.progressPerUser = Array.from(userMap.values()).map((user) => ({
+ ...user,
+ completeTaskNum: Math.round(user.completeTaskNum * 100) / 100,
+ avgInspectionTime: timeUtil.formatSecondsToChinese(
+ user.totalInspectionTime / user.dayTaskNum
+ )
+ }));
return res;
});
+
+const formatPercent = (num) => {
+ return isNaN(num) ? '0%' : parseInt(num * 100) + '%';
+};
/********************** 鍒濆鍖� *********************************/
// watch(
diff --git a/src/views/fysp/task/components/CompSubTaskList.vue b/src/views/fysp/task/components/CompSubTaskList.vue
index 818339f..51dd342 100644
--- a/src/views/fysp/task/components/CompSubTaskList.vue
+++ b/src/views/fysp/task/components/CompSubTaskList.vue
@@ -1,6 +1,6 @@
<template>
<el-row justify="space-between">
- <el-text>鍗曟棩璁″垝</el-text>
+ <el-text>{{dateStr}}璁″垝</el-text>
<div v-show="create && data && data.length > 0">
<el-button
icon="IconPrinter"
@@ -63,6 +63,7 @@
</div>
</el-scrollbar>
</div>
+ <!-- 缂栬緫宸℃煡瀛愪换鍔� -->
<el-dialog
v-model="dialogVisible"
width="600"
@@ -78,6 +79,7 @@
@cancel="dialogVisible = false"
></CompSubTaskEdit>
</el-dialog>
+ <!-- 宸℃煡鍗曚笅杞� -->
<SceneInspectFile
v-model="downloadDialog"
:value="downloadSceneList"
@@ -85,13 +87,14 @@
</template>
<script setup>
import { ref, computed, watch, onMounted, onUnmounted } from 'vue';
-import { ElMessageBox, ElNotification, ElMessage } from 'element-plus';
+import { ElMessageBox, ElNotification, ElMessage, dayjs } from 'element-plus';
import CompSubTaskEdit from './CompSubTaskEdit.vue';
import SceneInspectFile from '@/views/fysp/scene/SceneInspectFile.vue';
import subtaskApi from '@/api/fysp/subtaskApi';
const props = defineProps({
modelValue: Array,
+ date: Date,
height: {
type: String,
default: '70vh'
@@ -110,6 +113,8 @@
const emit = defineEmits(['submit', 'add', 'remove', 'update:modelValue']);
+const dateStr = computed(()=> dayjs(props.date).format('MM鏈圖D鏃�'))
+
function remove(item) {
if (item.status == '鏈墽琛�') {
ElMessageBox.confirm('鏄惁绉婚櫎鐩戠浠诲姟', `绉婚櫎纭`, {
--
Gitblit v1.9.3