fix: iot
This commit is contained in:
@@ -345,7 +345,7 @@ onMounted(async () => {
|
|||||||
<Button
|
<Button
|
||||||
type="primary"
|
type="primary"
|
||||||
@click="handleCreate"
|
@click="handleCreate"
|
||||||
v-hasPermi="['iot:device:create']"
|
v-access:code="['iot:device:create']"
|
||||||
>
|
>
|
||||||
<IconifyIcon icon="ant-design:plus-outlined" class="mr-1" />
|
<IconifyIcon icon="ant-design:plus-outlined" class="mr-1" />
|
||||||
新增
|
新增
|
||||||
@@ -353,19 +353,19 @@ onMounted(async () => {
|
|||||||
<Button
|
<Button
|
||||||
type="primary"
|
type="primary"
|
||||||
@click="handleExport"
|
@click="handleExport"
|
||||||
v-hasPermi="['iot:device:export']"
|
v-access:code="['iot:device:export']"
|
||||||
>
|
>
|
||||||
<IconifyIcon icon="ant-design:download-outlined" class="mr-1" />
|
<IconifyIcon icon="ant-design:download-outlined" class="mr-1" />
|
||||||
导出
|
导出
|
||||||
</Button>
|
</Button>
|
||||||
<Button @click="handleImport" v-hasPermi="['iot:device:import']">
|
<Button @click="handleImport" v-access:code="['iot:device:import']">
|
||||||
<IconifyIcon icon="ant-design:upload-outlined" class="mr-1" />
|
<IconifyIcon icon="ant-design:upload-outlined" class="mr-1" />
|
||||||
导入
|
导入
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
v-show="viewMode === 'list'"
|
v-show="viewMode === 'list'"
|
||||||
@click="handleAddToGroup"
|
@click="handleAddToGroup"
|
||||||
v-hasPermi="['iot:device:update']"
|
v-access:code="['iot:device:update']"
|
||||||
>
|
>
|
||||||
<IconifyIcon icon="ant-design:folder-add-outlined" class="mr-1" />
|
<IconifyIcon icon="ant-design:folder-add-outlined" class="mr-1" />
|
||||||
添加到分组
|
添加到分组
|
||||||
@@ -374,7 +374,7 @@ onMounted(async () => {
|
|||||||
v-show="viewMode === 'list'"
|
v-show="viewMode === 'list'"
|
||||||
danger
|
danger
|
||||||
@click="handleDeleteBatch"
|
@click="handleDeleteBatch"
|
||||||
v-hasPermi="['iot:device:delete']"
|
v-access:code="['iot:device:delete']"
|
||||||
>
|
>
|
||||||
<IconifyIcon icon="ant-design:delete-outlined" class="mr-1" />
|
<IconifyIcon icon="ant-design:delete-outlined" class="mr-1" />
|
||||||
批量删除
|
批量删除
|
||||||
|
|||||||
@@ -53,13 +53,13 @@ const queryParams = ref({
|
|||||||
});
|
});
|
||||||
|
|
||||||
// 获取产品名称
|
// 获取产品名称
|
||||||
const getProductName = (productId: number) => {
|
function getProductName(productId: number) {
|
||||||
const product = props.products.find((p: any) => p.id === productId);
|
const product = props.products.find((p: any) => p.id === productId);
|
||||||
return product?.name || '-';
|
return product?.name || '-';
|
||||||
};
|
}
|
||||||
|
|
||||||
// 获取设备列表
|
// 获取设备列表
|
||||||
const getList = async () => {
|
async function getList() {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
try {
|
try {
|
||||||
const data = await getDevicePage({
|
const data = await getDevicePage({
|
||||||
@@ -71,26 +71,26 @@ const getList = async () => {
|
|||||||
} finally {
|
} finally {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
// 处理页码变化
|
// 处理页码变化
|
||||||
const handlePageChange = (page: number, pageSize: number) => {
|
function handlePageChange(page: number, pageSize: number) {
|
||||||
queryParams.value.pageNo = page;
|
queryParams.value.pageNo = page;
|
||||||
queryParams.value.pageSize = pageSize;
|
queryParams.value.pageSize = pageSize;
|
||||||
getList();
|
getList();
|
||||||
};
|
}
|
||||||
|
|
||||||
// 获取设备类型颜色
|
// 获取设备类型颜色
|
||||||
const getDeviceTypeColor = (deviceType: number) => {
|
function getDeviceTypeColor(deviceType: number) {
|
||||||
const colors: Record<number, string> = {
|
const colors: Record<number, string> = {
|
||||||
0: 'blue',
|
0: 'blue',
|
||||||
1: 'cyan',
|
1: 'cyan',
|
||||||
};
|
};
|
||||||
return colors[deviceType] || 'default';
|
return colors[deviceType] || 'default';
|
||||||
};
|
}
|
||||||
|
|
||||||
// 获取设备状态信息
|
// 获取设备状态信息
|
||||||
const getStatusInfo = (state: number) => {
|
function getStatusInfo(state: number) {
|
||||||
if (state === DeviceStateEnum.ONLINE) {
|
if (state === DeviceStateEnum.ONLINE) {
|
||||||
return {
|
return {
|
||||||
text: '在线',
|
text: '在线',
|
||||||
@@ -105,7 +105,7 @@ const getStatusInfo = (state: number) => {
|
|||||||
bgColor: '#fff1f0',
|
bgColor: '#fff1f0',
|
||||||
borderColor: '#ffccc7',
|
borderColor: '#ffccc7',
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getList();
|
getList();
|
||||||
@@ -171,7 +171,7 @@ defineExpose({
|
|||||||
<a
|
<a
|
||||||
class="value link"
|
class="value link"
|
||||||
@click="
|
@click="
|
||||||
(e: MouseEvent) => {
|
(e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
emit('productDetail', item.productId);
|
emit('productDetail', item.productId);
|
||||||
}
|
}
|
||||||
@@ -209,7 +209,7 @@ defineExpose({
|
|||||||
size="small"
|
size="small"
|
||||||
class="action-btn btn-edit"
|
class="action-btn btn-edit"
|
||||||
@click="
|
@click="
|
||||||
(e: MouseEvent) => {
|
(e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
emit('edit', item);
|
emit('edit', item);
|
||||||
}
|
}
|
||||||
@@ -289,23 +289,23 @@ defineExpose({
|
|||||||
.device-card-view {
|
.device-card-view {
|
||||||
.device-card {
|
.device-card {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
border-radius: 8px;
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
box-shadow:
|
|
||||||
0 1px 2px 0 rgba(0, 0, 0, 0.03),
|
|
||||||
0 1px 6px -1px rgba(0, 0, 0, 0.02),
|
|
||||||
0 2px 4px 0 rgba(0, 0, 0, 0.02);
|
|
||||||
transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
|
|
||||||
border: 1px solid #f0f0f0;
|
|
||||||
background: #fff;
|
background: #fff;
|
||||||
|
border: 1px solid #f0f0f0;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow:
|
||||||
|
0 1px 2px 0 rgb(0 0 0 / 3%),
|
||||||
|
0 1px 6px -1px rgb(0 0 0 / 2%),
|
||||||
|
0 2px 4px 0 rgb(0 0 0 / 2%);
|
||||||
|
transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
box-shadow:
|
|
||||||
0 1px 2px -2px rgba(0, 0, 0, 0.16),
|
|
||||||
0 3px 6px 0 rgba(0, 0, 0, 0.12),
|
|
||||||
0 5px 12px 4px rgba(0, 0, 0, 0.09);
|
|
||||||
transform: translateY(-4px);
|
|
||||||
border-color: #e6e6e6;
|
border-color: #e6e6e6;
|
||||||
|
box-shadow:
|
||||||
|
0 1px 2px -2px rgb(0 0 0 / 16%),
|
||||||
|
0 3px 6px 0 rgb(0 0 0 / 12%),
|
||||||
|
0 5px 12px 4px rgb(0 0 0 / 9%);
|
||||||
|
transform: translateY(-4px);
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.ant-card-body) {
|
:deep(.ant-card-body) {
|
||||||
@@ -313,10 +313,10 @@ defineExpose({
|
|||||||
}
|
}
|
||||||
|
|
||||||
.card-content {
|
.card-content {
|
||||||
padding: 16px;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
padding: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 头部区域
|
// 头部区域
|
||||||
@@ -327,48 +327,48 @@ defineExpose({
|
|||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
|
|
||||||
.device-icon {
|
.device-icon {
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
border-radius: 6px;
|
|
||||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
color: #fff;
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
box-shadow: 0 2px 8px rgba(102, 126, 234, 0.25);
|
color: #fff;
|
||||||
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
|
border-radius: 6px;
|
||||||
|
box-shadow: 0 2px 8px rgb(102 126 234 / 25%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-badge {
|
.status-badge {
|
||||||
|
display: flex;
|
||||||
|
gap: 4px;
|
||||||
|
align-items: center;
|
||||||
padding: 2px 10px;
|
padding: 2px 10px;
|
||||||
border-radius: 12px;
|
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 4px;
|
|
||||||
border: 1px solid;
|
|
||||||
line-height: 18px;
|
line-height: 18px;
|
||||||
|
border: 1px solid;
|
||||||
|
border-radius: 12px;
|
||||||
|
|
||||||
.status-dot {
|
.status-dot {
|
||||||
width: 6px;
|
width: 6px;
|
||||||
height: 6px;
|
height: 6px;
|
||||||
|
background: currentcolor;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
background: currentColor;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 设备名称
|
// 设备名称
|
||||||
.device-name {
|
.device-name {
|
||||||
font-size: 16px;
|
|
||||||
font-weight: 600;
|
|
||||||
color: #262626;
|
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
white-space: nowrap;
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
line-height: 24px;
|
line-height: 24px;
|
||||||
|
color: #262626;
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 信息区域
|
// 信息区域
|
||||||
@@ -378,30 +378,30 @@ defineExpose({
|
|||||||
|
|
||||||
.info-item {
|
.info-item {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
gap: 8px;
|
|
||||||
|
|
||||||
&:last-child {
|
&:last-child {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.label {
|
.label {
|
||||||
|
flex-shrink: 0;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
color: #8c8c8c;
|
color: #8c8c8c;
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.value {
|
.value {
|
||||||
font-size: 13px;
|
|
||||||
color: #262626;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
text-align: right;
|
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
font-size: 13px;
|
||||||
|
color: #262626;
|
||||||
|
text-align: right;
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
&.link {
|
&.link {
|
||||||
color: #1890ff;
|
color: #1890ff;
|
||||||
@@ -415,11 +415,10 @@ defineExpose({
|
|||||||
|
|
||||||
&.code {
|
&.code {
|
||||||
font-family:
|
font-family:
|
||||||
'SF Mono', 'Monaco', 'Inconsolata', 'Fira Code', 'Consolas',
|
'SF Mono', Monaco, Inconsolata, 'Fira Code', Consolas, monospace;
|
||||||
monospace;
|
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: #595959;
|
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
|
color: #595959;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -427,28 +426,28 @@ defineExpose({
|
|||||||
|
|
||||||
// 操作按钮栏
|
// 操作按钮栏
|
||||||
.action-bar {
|
.action-bar {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
padding-top: 12px;
|
padding-top: 12px;
|
||||||
border-top: 1px solid #f5f5f5;
|
border-top: 1px solid #f5f5f5;
|
||||||
position: relative;
|
|
||||||
z-index: 1;
|
|
||||||
|
|
||||||
.action-btn {
|
.action-btn {
|
||||||
flex: 1;
|
|
||||||
height: 32px;
|
|
||||||
padding: 4px 8px;
|
|
||||||
border-radius: 6px;
|
|
||||||
font-size: 13px;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
gap: 4px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
gap: 4px;
|
height: 32px;
|
||||||
transition: all 0.2s;
|
padding: 4px 8px;
|
||||||
|
font-size: 13px;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
border: 1px solid;
|
|
||||||
cursor: pointer;
|
|
||||||
pointer-events: auto;
|
pointer-events: auto;
|
||||||
|
cursor: pointer;
|
||||||
|
border: 1px solid;
|
||||||
|
border-radius: 6px;
|
||||||
|
transition: all 0.2s;
|
||||||
|
|
||||||
:deep(.anticon) {
|
:deep(.anticon) {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ function goToProductDetail(productId: number | undefined) {
|
|||||||
<!-- 右上:按钮 -->
|
<!-- 右上:按钮 -->
|
||||||
<Button
|
<Button
|
||||||
v-if="product.status === 0"
|
v-if="product.status === 0"
|
||||||
v-hasPermi="['iot:device:update']"
|
v-access:code="['iot:device:update']"
|
||||||
@click="openForm('update', device.id)"
|
@click="openForm('update', device.id)"
|
||||||
>
|
>
|
||||||
编辑
|
编辑
|
||||||
|
|||||||
@@ -32,9 +32,9 @@ const IconComponent = computed(() => iconMap[props.icon] || iconMap.menu);
|
|||||||
<div class="flex h-full flex-col">
|
<div class="flex h-full flex-col">
|
||||||
<div class="mb-4 flex items-start justify-between">
|
<div class="mb-4 flex items-start justify-between">
|
||||||
<div class="flex flex-1 flex-col">
|
<div class="flex flex-1 flex-col">
|
||||||
<span class="mb-2 text-sm font-medium text-gray-500">{{
|
<span class="mb-2 text-sm font-medium text-gray-500">
|
||||||
title
|
{{ title }}
|
||||||
}}</span>
|
</span>
|
||||||
<span class="text-3xl font-bold text-gray-800">
|
<span class="text-3xl font-bold text-gray-800">
|
||||||
<span v-if="value === -1">--</span>
|
<span v-if="value === -1">--</span>
|
||||||
<CountTo v-else :end-val="value" :duration="1000" />
|
<CountTo v-else :end-val="value" :duration="1000" />
|
||||||
@@ -49,9 +49,9 @@ const IconComponent = computed(() => iconMap[props.icon] || iconMap.menu);
|
|||||||
<div class="flex items-center justify-between text-sm">
|
<div class="flex items-center justify-between text-sm">
|
||||||
<span class="text-gray-400">今日新增</span>
|
<span class="text-gray-400">今日新增</span>
|
||||||
<span v-if="todayCount === -1" class="text-gray-400">--</span>
|
<span v-if="todayCount === -1" class="text-gray-400">--</span>
|
||||||
<span v-else class="font-medium text-green-500"
|
<span v-else class="font-medium text-green-500">
|
||||||
>+{{ todayCount }}</span
|
+{{ todayCount }}
|
||||||
>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -61,18 +61,18 @@ const IconComponent = computed(() => iconMap[props.icon] || iconMap.menu);
|
|||||||
<style scoped>
|
<style scoped>
|
||||||
.stat-card {
|
.stat-card {
|
||||||
height: 160px;
|
height: 160px;
|
||||||
transition: all 0.3s ease;
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stat-card:hover {
|
.stat-card:hover {
|
||||||
|
box-shadow: 0 6px 20px rgb(0 0 0 / 8%);
|
||||||
transform: translateY(-4px);
|
transform: translateY(-4px);
|
||||||
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.08);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.stat-card :deep(.ant-card-body) {
|
.stat-card :deep(.ant-card-body) {
|
||||||
height: 100%;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ const hasData = computed(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
/** 初始化图表 */
|
/** 初始化图表 */
|
||||||
const initChart = () => {
|
function initChart() {
|
||||||
if (!hasData.value) return;
|
if (!hasData.value) return;
|
||||||
|
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
@@ -94,7 +94,7 @@ const initChart = () => {
|
|||||||
],
|
],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
|
||||||
/** 监听数据变化 */
|
/** 监听数据变化 */
|
||||||
watch(
|
watch(
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ const getGaugeOption = (value: number, color: string, title: string): any => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/** 初始化图表 */
|
/** 初始化图表 */
|
||||||
const initCharts = () => {
|
function initCharts() {
|
||||||
if (!hasData.value) return;
|
if (!hasData.value) return;
|
||||||
|
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
@@ -101,7 +101,7 @@ const initCharts = () => {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
|
||||||
/** 监听数据变化 */
|
/** 监听数据变化 */
|
||||||
watch(
|
watch(
|
||||||
|
|||||||
@@ -1,10 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { Dayjs } from 'dayjs';
|
import type { Dayjs } from 'dayjs';
|
||||||
|
|
||||||
import type {
|
import type { IotStatisticsApi } from '#/api/iot/statistics';
|
||||||
IotStatisticsDeviceMessageReqVO,
|
|
||||||
IotStatisticsDeviceMessageSummaryByDateRespVO,
|
|
||||||
} from '#/api/iot/statistics';
|
|
||||||
|
|
||||||
import { computed, nextTick, onMounted, reactive, ref } from 'vue';
|
import { computed, nextTick, onMounted, reactive, ref } from 'vue';
|
||||||
|
|
||||||
@@ -13,7 +10,7 @@ import { EchartsUI, useEcharts } from '@vben/plugins/echarts';
|
|||||||
import { Button, Card, DatePicker, Empty, Space } from 'ant-design-vue';
|
import { Button, Card, DatePicker, Empty, Space } from 'ant-design-vue';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
|
|
||||||
import { StatisticsApi } from '#/api/iot/statistics';
|
import { getDeviceMessageSummaryByDate } from '#/api/iot/statistics';
|
||||||
|
|
||||||
defineOptions({ name: 'MessageTrendCard' });
|
defineOptions({ name: 'MessageTrendCard' });
|
||||||
|
|
||||||
@@ -23,11 +20,11 @@ const messageChartRef = ref();
|
|||||||
const { renderEcharts } = useEcharts(messageChartRef);
|
const { renderEcharts } = useEcharts(messageChartRef);
|
||||||
|
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const messageData = ref<IotStatisticsDeviceMessageSummaryByDateRespVO[]>([]);
|
const messageData = ref<IotStatisticsApi.DeviceMessageSummaryByDate[]>([]);
|
||||||
const activeTimeRange = ref('7d'); // 当前选中的时间范围
|
const activeTimeRange = ref('7d'); // 当前选中的时间范围
|
||||||
const dateRange = ref<[Dayjs, Dayjs] | undefined>(undefined);
|
const dateRange = ref<[Dayjs, Dayjs] | undefined>(undefined);
|
||||||
|
|
||||||
const queryParams = reactive<IotStatisticsDeviceMessageReqVO>({
|
const queryParams = reactive<IotStatisticsApi.DeviceMessageReq>({
|
||||||
interval: 1, // 按天
|
interval: 1, // 按天
|
||||||
times: [],
|
times: [],
|
||||||
});
|
});
|
||||||
@@ -38,7 +35,7 @@ const hasData = computed(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// 设置时间范围
|
// 设置时间范围
|
||||||
const setTimeRange = (range: string) => {
|
function setTimeRange(range: string) {
|
||||||
activeTimeRange.value = range;
|
activeTimeRange.value = range;
|
||||||
dateRange.value = undefined; // 清空自定义时间选择
|
dateRange.value = undefined; // 清空自定义时间选择
|
||||||
|
|
||||||
@@ -73,10 +70,10 @@ const setTimeRange = (range: string) => {
|
|||||||
];
|
];
|
||||||
|
|
||||||
fetchMessageData();
|
fetchMessageData();
|
||||||
};
|
}
|
||||||
|
|
||||||
// 处理自定义日期选择
|
// 处理自定义日期选择
|
||||||
const handleDateChange = () => {
|
function handleDateChange() {
|
||||||
if (dateRange.value && dateRange.value.length === 2) {
|
if (dateRange.value && dateRange.value.length === 2) {
|
||||||
activeTimeRange.value = ''; // 清空快捷选择
|
activeTimeRange.value = ''; // 清空快捷选择
|
||||||
queryParams.interval = 1; // 按天
|
queryParams.interval = 1; // 按天
|
||||||
@@ -86,16 +83,15 @@ const handleDateChange = () => {
|
|||||||
];
|
];
|
||||||
fetchMessageData();
|
fetchMessageData();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
// 获取消息统计数据
|
// 获取消息统计数据
|
||||||
const fetchMessageData = async () => {
|
async function fetchMessageData() {
|
||||||
if (!queryParams.times || queryParams.times.length !== 2) return;
|
if (!queryParams.times || queryParams.times.length !== 2) return;
|
||||||
|
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
try {
|
try {
|
||||||
messageData.value =
|
messageData.value = await getDeviceMessageSummaryByDate(queryParams);
|
||||||
await StatisticsApi.getDeviceMessageSummaryByDate(queryParams);
|
|
||||||
await nextTick();
|
await nextTick();
|
||||||
initChart();
|
initChart();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -104,10 +100,10 @@ const fetchMessageData = async () => {
|
|||||||
} finally {
|
} finally {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
// 初始化图表
|
// 初始化图表
|
||||||
const initChart = () => {
|
function initChart() {
|
||||||
if (!hasData.value) return;
|
if (!hasData.value) return;
|
||||||
|
|
||||||
const times = messageData.value.map((item) => item.time);
|
const times = messageData.value.map((item) => item.time);
|
||||||
@@ -181,7 +177,7 @@ const initChart = () => {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
|
||||||
// 组件挂载时查询数据
|
// 组件挂载时查询数据
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
|||||||
Reference in New Issue
Block a user