|
@@ -1,10 +1,12 @@
|
|
|
<script lang="ts" setup>
|
|
<script lang="ts" setup>
|
|
|
import { IotDeviceApi } from '@/api/pms/device'
|
|
import { IotDeviceApi } from '@/api/pms/device'
|
|
|
import { useUserStore } from '@/store/modules/user'
|
|
import { useUserStore } from '@/store/modules/user'
|
|
|
|
|
+import download from '@/utils/download'
|
|
|
import { rangeShortcuts } from '@/utils/formatTime'
|
|
import { rangeShortcuts } from '@/utils/formatTime'
|
|
|
import { useDebounceFn } from '@vueuse/core'
|
|
import { useDebounceFn } from '@vueuse/core'
|
|
|
import { dayjs, ElMessage } from 'element-plus'
|
|
import { dayjs, ElMessage } from 'element-plus'
|
|
|
import { computed, ref } from 'vue'
|
|
import { computed, ref } from 'vue'
|
|
|
|
|
+import { useI18n } from 'vue-i18n'
|
|
|
|
|
|
|
|
const { t } = useI18n()
|
|
const { t } = useI18n()
|
|
|
|
|
|
|
@@ -19,15 +21,15 @@ interface Query {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
const query = ref<Query>({
|
|
const query = ref<Query>({
|
|
|
- deviceCode: 'YF6660355',
|
|
|
|
|
- time: [
|
|
|
|
|
- dayjs().subtract(1, 'day').format('YYYY-MM-DD HH:mm:ss'),
|
|
|
|
|
- dayjs().format('YYYY-MM-DD HH:mm:ss')
|
|
|
|
|
- ]
|
|
|
|
|
|
|
+ deviceName: '',
|
|
|
|
|
+ deviceCode: '',
|
|
|
|
|
+ time: []
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
const pageSize = ref(100)
|
|
const pageSize = ref(100)
|
|
|
-const historyStack = ref<string[]>([]) // 存储历史开始时间
|
|
|
|
|
|
|
+const historyStack = ref<string[]>([])
|
|
|
|
|
+
|
|
|
|
|
+const hasSearched = ref(false)
|
|
|
|
|
|
|
|
// 数据列表类型
|
|
// 数据列表类型
|
|
|
interface ListItem {
|
|
interface ListItem {
|
|
@@ -41,15 +43,18 @@ interface ListItem {
|
|
|
const list = ref<ListItem[]>([])
|
|
const list = ref<ListItem[]>([])
|
|
|
const loading = ref(false)
|
|
const loading = ref(false)
|
|
|
|
|
|
|
|
-const isDeviceSelected = computed(() => !!query.value.deviceCode)
|
|
|
|
|
|
|
+const isConditionValid = computed(() => {
|
|
|
|
|
+ const hasTime = query.value.time && query.value.time.length === 2
|
|
|
|
|
+ const hasIdentity = !!query.value.deviceName || !!query.value.deviceCode
|
|
|
|
|
+ return hasTime && hasIdentity
|
|
|
|
|
+})
|
|
|
|
|
|
|
|
const canGoBack = computed(() => historyStack.value.length > 0)
|
|
const canGoBack = computed(() => historyStack.value.length > 0)
|
|
|
-
|
|
|
|
|
const canGoNext = computed(() => list.value.length >= pageSize.value)
|
|
const canGoNext = computed(() => list.value.length >= pageSize.value)
|
|
|
|
|
|
|
|
const loadList = useDebounceFn(async function () {
|
|
const loadList = useDebounceFn(async function () {
|
|
|
- if (!isDeviceSelected.value || !query.value.time?.length) {
|
|
|
|
|
- list.value = []
|
|
|
|
|
|
|
+ if (!isConditionValid.value) {
|
|
|
|
|
+ // list.value = []
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -76,36 +81,43 @@ const loadList = useDebounceFn(async function () {
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
function handleQuery() {
|
|
function handleQuery() {
|
|
|
- if (!query.value.deviceCode) {
|
|
|
|
|
- ElMessage.warning('请先输入设备编码')
|
|
|
|
|
|
|
+ if (!query.value.deviceName && !query.value.deviceCode) {
|
|
|
|
|
+ ElMessage.warning('请输入设备名称或设备编码')
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
if (!query.value.time || query.value.time.length !== 2) {
|
|
if (!query.value.time || query.value.time.length !== 2) {
|
|
|
ElMessage.warning('请选择时间范围')
|
|
ElMessage.warning('请选择时间范围')
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 重置历史栈
|
|
|
|
|
|
|
+ hasSearched.value = true
|
|
|
|
|
+
|
|
|
historyStack.value = []
|
|
historyStack.value = []
|
|
|
|
|
|
|
|
loadList()
|
|
loadList()
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+function handleReset() {
|
|
|
|
|
+ query.value = {
|
|
|
|
|
+ deviceCode: '',
|
|
|
|
|
+ deviceName: '',
|
|
|
|
|
+ time: []
|
|
|
|
|
+ }
|
|
|
|
|
+ list.value = []
|
|
|
|
|
+ historyStack.value = []
|
|
|
|
|
+ hasSearched.value = false
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
function handleNext() {
|
|
function handleNext() {
|
|
|
if (list.value.length === 0) return
|
|
if (list.value.length === 0) return
|
|
|
if (!query.value.time || query.value.time.length < 2) return
|
|
if (!query.value.time || query.value.time.length < 2) return
|
|
|
|
|
|
|
|
- // 1. 获取当前页最后一条数据的时间
|
|
|
|
|
const lastItem = list.value[list.value.length - 1]
|
|
const lastItem = list.value[list.value.length - 1]
|
|
|
|
|
|
|
|
if (lastItem && lastItem.ts) {
|
|
if (lastItem && lastItem.ts) {
|
|
|
- // 2. 将当前的【开始时间】存入栈中,以便返回
|
|
|
|
|
historyStack.value.push(query.value.time[1])
|
|
historyStack.value.push(query.value.time[1])
|
|
|
-
|
|
|
|
|
- // 3. 直接修改 query.time 的开始时间,保持结束时间不变
|
|
|
|
|
- // 注意:重新赋值数组以触发响应式更新
|
|
|
|
|
query.value.time = [query.value.time[0], dayjs(lastItem.ts).format('YYYY-MM-DD HH:mm:ss')]
|
|
query.value.time = [query.value.time[0], dayjs(lastItem.ts).format('YYYY-MM-DD HH:mm:ss')]
|
|
|
-
|
|
|
|
|
loadList()
|
|
loadList()
|
|
|
} else {
|
|
} else {
|
|
|
ElMessage.warning('无法获取最后一条数据的时间,无法跳转')
|
|
ElMessage.warning('无法获取最后一条数据的时间,无法跳转')
|
|
@@ -116,25 +128,32 @@ function handlePrev() {
|
|
|
if (historyStack.value.length === 0) return
|
|
if (historyStack.value.length === 0) return
|
|
|
if (!query.value.time || query.value.time.length < 2) return
|
|
if (!query.value.time || query.value.time.length < 2) return
|
|
|
|
|
|
|
|
- // 1. 弹出上一次的开始时间
|
|
|
|
|
const prevEndTime = historyStack.value.pop()
|
|
const prevEndTime = historyStack.value.pop()
|
|
|
|
|
|
|
|
if (prevEndTime) {
|
|
if (prevEndTime) {
|
|
|
- // 2. 恢复 query.time 的开始时间
|
|
|
|
|
query.value.time = [query.value.time[0], dayjs(prevEndTime).format('YYYY-MM-DD HH:mm:ss')]
|
|
query.value.time = [query.value.time[0], dayjs(prevEndTime).format('YYYY-MM-DD HH:mm:ss')]
|
|
|
-
|
|
|
|
|
loadList()
|
|
loadList()
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
function handleSizeChange() {
|
|
function handleSizeChange() {
|
|
|
- // 切换分页大小时,为了逻辑简单,直接重新查询第一页
|
|
|
|
|
- if (isDeviceSelected.value && query.value.time) {
|
|
|
|
|
- // 清空栈,因为分页切片改变了,之前的历史游标可能不再准确
|
|
|
|
|
|
|
+ if (isConditionValid.value) {
|
|
|
historyStack.value = []
|
|
historyStack.value = []
|
|
|
loadList()
|
|
loadList()
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+const exportLoading = ref(false)
|
|
|
|
|
+
|
|
|
|
|
+const handleExport = useDebounceFn(async function () {
|
|
|
|
|
+ exportLoading.value = true
|
|
|
|
|
+ try {
|
|
|
|
|
+ const data = await IotDeviceApi.exportMonitoringQuery(query.value)
|
|
|
|
|
+ download.excel(data, '运维监控查询.xls')
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ exportLoading.value = false
|
|
|
|
|
+ }
|
|
|
|
|
+}, 300)
|
|
|
</script>
|
|
</script>
|
|
|
|
|
|
|
|
<template>
|
|
<template>
|
|
@@ -184,6 +203,13 @@ function handleSizeChange() {
|
|
|
<el-button type="primary" @click="handleQuery()">
|
|
<el-button type="primary" @click="handleQuery()">
|
|
|
<Icon icon="ep:search" class="mr-5px" /> 搜索
|
|
<Icon icon="ep:search" class="mr-5px" /> 搜索
|
|
|
</el-button>
|
|
</el-button>
|
|
|
|
|
+ <el-button @click="handleReset()">
|
|
|
|
|
+ <Icon icon="ep:refresh" class="mr-1" /> 重置
|
|
|
|
|
+ </el-button>
|
|
|
|
|
+ <el-button :loading="exportLoading" plain type="success" @click="handleExport">
|
|
|
|
|
+ <Icon class="mr-5px" icon="ep:download" />
|
|
|
|
|
+ 导出
|
|
|
|
|
+ </el-button>
|
|
|
</el-form-item>
|
|
</el-form-item>
|
|
|
</div>
|
|
</div>
|
|
|
</el-form>
|
|
</el-form>
|
|
@@ -199,6 +225,14 @@ function handleSizeChange() {
|
|
|
:height="height"
|
|
:height="height"
|
|
|
:max-height="height"
|
|
:max-height="height"
|
|
|
>
|
|
>
|
|
|
|
|
+ <template #empty>
|
|
|
|
|
+ <el-empty
|
|
|
|
|
+ v-if="!hasSearched"
|
|
|
|
|
+ description="请至少输入【设备名称】或【设备编码】,并选择【时间范围】进行搜索"
|
|
|
|
|
+ />
|
|
|
|
|
+ <el-empty v-else description="暂无数据" />
|
|
|
|
|
+ </template>
|
|
|
|
|
+
|
|
|
<zm-table-column type="index" label="序号" :width="60" align="center" />
|
|
<zm-table-column type="index" label="序号" :width="60" align="center" />
|
|
|
<zm-table-column
|
|
<zm-table-column
|
|
|
prop="deviceName"
|
|
prop="deviceName"
|