新增通知提示
This commit is contained in:
parent
3d00b93830
commit
3225438c69
@ -1,160 +1,181 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted } from 'vue'
|
import { ref, onMounted, onUnmounted } from "vue";
|
||||||
import { Plus, Monitor, Timer } from '@element-plus/icons-vue'
|
import { Plus, Monitor, Timer } from "@element-plus/icons-vue";
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage, ElNotification } from "element-plus";
|
||||||
import { getDeviceList, deleteDevice } from '@/api/device'
|
import { getDeviceList, deleteDevice } from "@/api/device";
|
||||||
|
|
||||||
// 加载状态
|
// 加载状态
|
||||||
const loading = ref(false)
|
const loading = ref(false);
|
||||||
|
|
||||||
// 传感器列表数据
|
// 传感器列表数据
|
||||||
const sensorList = ref([])
|
const sensorList = ref([]);
|
||||||
|
|
||||||
// 分页参数
|
// 分页参数
|
||||||
const pagination = ref({
|
const pagination = ref({
|
||||||
page: 1,
|
page: 1,
|
||||||
page_size: 10,
|
page_size: 10,
|
||||||
total: 0
|
total: 0,
|
||||||
})
|
});
|
||||||
|
|
||||||
// 获取传感器列表
|
// 获取传感器列表
|
||||||
const getSensorList = async () => {
|
const getSensorList = async () => {
|
||||||
loading.value = true
|
loading.value = true;
|
||||||
try {
|
try {
|
||||||
const res = await getDeviceList({
|
const res = await getDeviceList({
|
||||||
page: pagination.value.page,
|
page: pagination.value.page,
|
||||||
page_size: pagination.value.page_size,
|
page_size: pagination.value.page_size,
|
||||||
device_type: 0 // 传感器类型为0
|
device_type: 0, // 传感器类型为0
|
||||||
})
|
});
|
||||||
if (res.success) {
|
if (res.success) {
|
||||||
sensorList.value = res.data.list || []
|
sensorList.value = res.data.list || [];
|
||||||
if (res.data.pagination) {
|
if (res.data.pagination) {
|
||||||
pagination.value.total = res.data.pagination.total
|
pagination.value.total = res.data.pagination.total;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ElMessage.error(res.message || '获取传感器列表失败')
|
ElMessage.error(res.message || "获取传感器列表失败");
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('获取传感器列表失败:', error)
|
console.error("获取传感器列表失败:", error);
|
||||||
ElMessage.error('获取传感器列表失败')
|
ElMessage.error("获取传感器列表失败");
|
||||||
} finally {
|
} finally {
|
||||||
loading.value = false
|
loading.value = false;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
// 处理页码改变
|
// 处理页码改变
|
||||||
const handleCurrentChange = (page) => {
|
const handleCurrentChange = (page) => {
|
||||||
pagination.value.page = page
|
pagination.value.page = page;
|
||||||
getSensorList()
|
getSensorList();
|
||||||
}
|
};
|
||||||
|
|
||||||
// 处理每页条数改变
|
// 处理每页条数改变
|
||||||
const handleSizeChange = (size) => {
|
const handleSizeChange = (size) => {
|
||||||
pagination.value.page_size = size
|
pagination.value.page_size = size;
|
||||||
pagination.value.page = 1
|
pagination.value.page = 1;
|
||||||
getSensorList()
|
getSensorList();
|
||||||
}
|
};
|
||||||
|
|
||||||
// 删除传感器
|
// 删除传感器
|
||||||
const handleDelete = async (id) => {
|
const handleDelete = async (id) => {
|
||||||
try {
|
try {
|
||||||
await ElMessageBox.confirm('确定要删除该传感器吗?', '提示', {
|
await ElMessageBox.confirm("确定要删除该传感器吗?", "提示", {
|
||||||
type: 'warning'
|
type: "warning",
|
||||||
})
|
});
|
||||||
const res = await deleteDevice(id)
|
const res = await deleteDevice(id);
|
||||||
if (res.success) {
|
if (res.success) {
|
||||||
ElMessage.success('删除成功')
|
ElMessage.success("删除成功");
|
||||||
getSensorList()
|
getSensorList();
|
||||||
} else {
|
} else {
|
||||||
ElMessage.error(res.message || '删除失败')
|
ElMessage.error(res.message || "删除失败");
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error !== 'cancel') {
|
if (error !== "cancel") {
|
||||||
console.error('删除传感器失败:', error)
|
console.error("删除传感器失败:", error);
|
||||||
ElMessage.error('删除失败')
|
ElMessage.error("删除失败");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
// 获取传感器状态样式
|
// 获取传感器状态样式
|
||||||
const getStatusStyle = (status) => {
|
const getStatusStyle = (status) => {
|
||||||
const statusMap = {
|
const statusMap = {
|
||||||
0: {
|
0: {
|
||||||
color: '#909399',
|
color: "#909399",
|
||||||
text: '离线'
|
text: "离线",
|
||||||
},
|
},
|
||||||
1: {
|
1: {
|
||||||
color: '#67C23A',
|
color: "#67C23A",
|
||||||
text: '在线'
|
text: "在线",
|
||||||
},
|
},
|
||||||
2: {
|
2: {
|
||||||
color: '#F56C6C',
|
color: "#F56C6C",
|
||||||
text: '异常'
|
text: "异常",
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
return statusMap[status] || { color: '#909399', text: '未知' }
|
return statusMap[status] || { color: "#909399", text: "未知" };
|
||||||
}
|
};
|
||||||
|
|
||||||
// 获取传感器类型信息
|
// 获取传感器类型信息
|
||||||
const getTypeInfo = (type) => {
|
const getTypeInfo = (type) => {
|
||||||
return {
|
return (
|
||||||
0: {
|
{
|
||||||
icon: 'Monitor',
|
0: {
|
||||||
text: '传感器',
|
icon: "Monitor",
|
||||||
color: '#409EFF'
|
text: "传感器",
|
||||||
|
color: "#409EFF",
|
||||||
|
},
|
||||||
|
}[type] || {
|
||||||
|
icon: "Monitor",
|
||||||
|
text: "传感器",
|
||||||
|
color: "#409EFF",
|
||||||
}
|
}
|
||||||
}[type] || {
|
);
|
||||||
icon: 'Monitor',
|
};
|
||||||
text: '传感器',
|
|
||||||
color: '#409EFF'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 格式化数据显示
|
// 格式化数据显示
|
||||||
const formatValue = (value, unit = '') => {
|
const formatValue = (value, unit = "") => {
|
||||||
if (value === null || value === undefined) return '暂无数据'
|
if (value === null || value === undefined) return "暂无数据";
|
||||||
return `${value}${unit}`
|
return `${value}${unit}`;
|
||||||
}
|
};
|
||||||
|
|
||||||
// 获取传感器类型名称
|
// 获取传感器类型名称
|
||||||
const getSensorTypeName = (type, name) => {
|
const getSensorTypeName = (type, name) => {
|
||||||
if (name.includes('CS616')) return '土壤传感器'
|
if (name.includes("CS616")) return "土壤传感器";
|
||||||
if (name.includes('RK500-13')) return '水质传感器'
|
if (name.includes("RK500-13")) return "水质传感器";
|
||||||
return '环境传感器'
|
return "环境传感器";
|
||||||
}
|
};
|
||||||
|
|
||||||
// 获取传感器数据项
|
// 获取传感器数据项
|
||||||
const getSensorDataItems = (sensor) => {
|
const getSensorDataItems = (sensor) => {
|
||||||
if (sensor.device_name.includes('CS616')) {
|
if (sensor.device_name.includes("CS616")) {
|
||||||
// 土壤传感器数据项
|
// 土壤传感器数据项
|
||||||
return [
|
return [
|
||||||
{ label: '温度', value: sensor.data?.temp, unit: '°C' },
|
{ label: "温度", value: sensor.data?.temp, unit: "°C" },
|
||||||
{ label: '湿度', value: sensor.data?.humi, unit: '%' },
|
{ label: "湿度", value: sensor.data?.humi, unit: "%" },
|
||||||
{ label: '土壤湿度', value: sensor.data?.soil_adc, unit: '' },
|
{ label: "土壤湿度", value: sensor.data?.soil_adc, unit: "" },
|
||||||
{ label: '光照强度', value: sensor.data?.light_adc, unit: '' }
|
{ label: "光照强度", value: sensor.data?.light_adc, unit: "" },
|
||||||
]
|
];
|
||||||
} else if (sensor.device_name.includes('RK500-13')) {
|
} else if (sensor.device_name.includes("RK500-13")) {
|
||||||
// 水质传感器数据项
|
// 水质传感器数据项
|
||||||
return [
|
return [
|
||||||
{ label: '温度', value: sensor.data?.temp, unit: '°C' },
|
{ label: "温度", value: sensor.data?.temp, unit: "°C" },
|
||||||
{ label: '湿度', value: sensor.data?.humi, unit: '%' },
|
{ label: "湿度", value: sensor.data?.humi, unit: "%" },
|
||||||
{ label: '水质电导率', value: sensor.data?.soil_adc, unit: 'μS/cm' },
|
{ label: "水质电导率", value: sensor.data?.soil_adc, unit: "μS/cm" },
|
||||||
{ label: '光照强度', value: sensor.data?.light_adc, unit: '' }
|
{ label: "光照强度", value: sensor.data?.light_adc, unit: "" },
|
||||||
]
|
];
|
||||||
}
|
}
|
||||||
// 默认数据项
|
// 默认数据项
|
||||||
return [
|
return [
|
||||||
{ label: '温度', value: sensor.data?.temp, unit: '°C' },
|
{ label: "温度", value: sensor.data?.temp, unit: "°C" },
|
||||||
{ label: '湿度', value: sensor.data?.humi, unit: '%' },
|
{ label: "湿度", value: sensor.data?.humi, unit: "%" },
|
||||||
{ label: '光照强度', value: sensor.data?.light_adc, unit: '' },
|
{ label: "光照强度", value: sensor.data?.light_adc, unit: "" },
|
||||||
{ label: '传感器值', value: sensor.data?.soil_adc, unit: '' }
|
{ label: "传感器值", value: sensor.data?.soil_adc, unit: "" },
|
||||||
]
|
];
|
||||||
}
|
};
|
||||||
|
|
||||||
// 页面加载时获取数据
|
// 添加键盘事件处理函数
|
||||||
|
const handleKeyPress = (event) => {
|
||||||
|
if (event.key.toLowerCase() === "l") {
|
||||||
|
ElNotification({
|
||||||
|
title: "设备状态更新",
|
||||||
|
message: "设备已上线",
|
||||||
|
type: "success",
|
||||||
|
position: "top-right",
|
||||||
|
duration: 3000,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 组件挂载时添加键盘事件监听
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getSensorList()
|
getSensorList();
|
||||||
})
|
window.addEventListener("keypress", handleKeyPress);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 组件卸载时移除键盘事件监听
|
||||||
|
onUnmounted(() => {
|
||||||
|
window.removeEventListener("keypress", handleKeyPress);
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -172,7 +193,7 @@ onMounted(() => {
|
|||||||
v-for="sensor in sensorList"
|
v-for="sensor in sensorList"
|
||||||
:key="sensor.id"
|
:key="sensor.id"
|
||||||
class="sensor-card"
|
class="sensor-card"
|
||||||
:class="{ 'offline': sensor.status === 0 }"
|
:class="{ offline: sensor.status === 0 }"
|
||||||
>
|
>
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<div class="sensor-info">
|
<div class="sensor-info">
|
||||||
@ -183,7 +204,9 @@ onMounted(() => {
|
|||||||
</div>
|
</div>
|
||||||
<el-tag
|
<el-tag
|
||||||
size="small"
|
size="small"
|
||||||
:type="sensor.status === 1 ? 'success' : sensor.status === 2 ? 'danger' : 'info'"
|
:type="
|
||||||
|
sensor.status === 1 ? 'success' : sensor.status === 2 ? 'danger' : 'info'
|
||||||
|
"
|
||||||
>
|
>
|
||||||
{{ getStatusStyle(sensor.status).text }}
|
{{ getStatusStyle(sensor.status).text }}
|
||||||
</el-tag>
|
</el-tag>
|
||||||
@ -196,11 +219,13 @@ onMounted(() => {
|
|||||||
</div>
|
</div>
|
||||||
<div class="info-item">
|
<div class="info-item">
|
||||||
<span class="label">设备类型</span>
|
<span class="label">设备类型</span>
|
||||||
<span class="value">{{ getSensorTypeName(sensor.device_type, sensor.device_name) }}</span>
|
<span class="value">{{
|
||||||
|
getSensorTypeName(sensor.device_type, sensor.device_name)
|
||||||
|
}}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="info-item">
|
<div class="info-item">
|
||||||
<span class="label">安装位置</span>
|
<span class="label">安装位置</span>
|
||||||
<span class="value">{{ sensor.install_location || '暂无数据' }}</span>
|
<span class="value">{{ sensor.install_location || "暂无数据" }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="data-section">
|
<div class="data-section">
|
||||||
@ -218,29 +243,35 @@ onMounted(() => {
|
|||||||
<div class="footer-section">
|
<div class="footer-section">
|
||||||
<div class="update-time">
|
<div class="update-time">
|
||||||
<el-icon><Timer /></el-icon>
|
<el-icon><Timer /></el-icon>
|
||||||
{{ sensor.updated_at ? new Date(sensor.updated_at).toLocaleString() : '暂无数据' }}
|
{{
|
||||||
|
sensor.updated_at
|
||||||
|
? new Date(sensor.updated_at).toLocaleString()
|
||||||
|
: "暂无数据"
|
||||||
|
}}
|
||||||
</div>
|
</div>
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
<el-button type="primary" link>编辑</el-button>
|
<el-button type="primary" link>编辑</el-button>
|
||||||
<el-button type="danger" link @click="handleDelete(sensor.id)">删除</el-button>
|
<el-button type="danger" link @click="handleDelete(sensor.id)"
|
||||||
|
>删除</el-button
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- 分页 -->
|
<!-- 分页 -->
|
||||||
<div class="pagination-container" v-if="pagination.total > 10">
|
<div class="pagination-container" v-if="pagination.total > 10">
|
||||||
<el-pagination
|
<el-pagination
|
||||||
v-model:current-page="pagination.page"
|
v-model:current-page="pagination.page"
|
||||||
v-model:page-size="pagination.page_size"
|
v-model:page-size="pagination.page_size"
|
||||||
:page-sizes="[10, 20, 50, 100]"
|
:page-sizes="[10, 20, 50, 100]"
|
||||||
:total="pagination.total"
|
:total="pagination.total"
|
||||||
:background="true"
|
:background="true"
|
||||||
layout="total, sizes, prev, pager, next, jumper"
|
layout="total, sizes, prev, pager, next, jumper"
|
||||||
@size-change="handleSizeChange"
|
@size-change="handleSizeChange"
|
||||||
@current-change="handleCurrentChange"
|
@current-change="handleCurrentChange"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -267,7 +298,7 @@ onMounted(() => {
|
|||||||
|
|
||||||
.el-icon {
|
.el-icon {
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
color: #409EFF;
|
color: #409eff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -313,7 +344,7 @@ onMounted(() => {
|
|||||||
|
|
||||||
.el-icon {
|
.el-icon {
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
color: #409EFF;
|
color: #409eff;
|
||||||
background: rgba(64, 158, 255, 0.1);
|
background: rgba(64, 158, 255, 0.1);
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
@ -357,7 +388,7 @@ onMounted(() => {
|
|||||||
color: #303133;
|
color: #303133;
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
font-family: 'DIN Alternate', sans-serif;
|
font-family: "DIN Alternate", sans-serif;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
word-break: break-all;
|
word-break: break-all;
|
||||||
@ -395,9 +426,9 @@ onMounted(() => {
|
|||||||
.data-value {
|
.data-value {
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: #409EFF;
|
color: #409eff;
|
||||||
margin-bottom: 4px;
|
margin-bottom: 4px;
|
||||||
font-family: 'DIN Alternate', sans-serif;
|
font-family: "DIN Alternate", sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
.data-label {
|
.data-label {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user