2025年04月28日17:18:08

This commit is contained in:
luojiayi 2025-04-28 17:18:11 +08:00
parent 9b61be74c7
commit 5d600041cf
17 changed files with 310 additions and 204 deletions

View File

@ -1,5 +1,11 @@
# VITE_APP_URL = 'http://192.168.3.116:8001/' # VITE_APP_URL = 'http://192.168.3.116:8001/'
# VITE_APP_URL_WEBSOCKET = 'http://192.168.3.116:8000/api/websocket' # VITE_APP_URL_WEBSOCKET = 'http://192.168.3.116:8000/api/websocket'
VITE_APP_URL = 'http://api.handcuff.youaikang.cn' VITE_APP_URL = 'http://47.112.185.26:8001/'
VITE_APP_URL_WEBSOCKET = 'ws://device.handcuff.youaikang.cn:8000/api/websocket' VITE_APP_URL_WEBSOCKET = 'ws://47.112.185.26:8000/api/websocket'
# VITE_APP_URL = 'http://api.handcuff.zhuhaiguangdun.cn'
# VITE_APP_URL_WEBSOCKET = 'ws://device.handcuff.zhuhaiguangdun.cn:8000/api/websocket'
# VITE_APP_URL = 'http://api.handcuff.youaikang.cn'
# VITE_APP_URL_WEBSOCKET = 'http://device.handcuff.youaikang.cn:8000/api/websocket'

View File

@ -1,5 +1,5 @@
VITE_APP_URL = 'http://api.handcuff.youaikang.cn' VITE_APP_URL = 'http://47.112.185.26:8001/'
VITE_APP_URL_WEBSOCKET = 'http://device.handcuff.youaikang.cn:8000/api/websocket' VITE_APP_URL_WEBSOCKET = 'ws://47.112.185.26:8000/api/websocket'
# VITE_APP_URL = 'http://api.handcuff.zhuhaiguangdun.cn'
# VITE_APP_URL_WEBSOCKET = 'ws://device.handcuff.zhuhaiguangdun.cn:8000/api/websocket'

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

@ -2,8 +2,7 @@
<div class="infoBox"> <div class="infoBox">
<div class="infoBox-head"> <div class="infoBox-head">
<div class="item"> <div class="item">
<div class="span">手铐</div> {{ value.deviceId }}
<div class="span">{{ value.id }}</div>
</div> </div>
<div class="item" style="cursor: pointer" @click="emit('close')"> <div class="item" style="cursor: pointer" @click="emit('close')">
<svg t="1744273365398" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8493" width="24" height="24"> <svg t="1744273365398" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8493" width="24" height="24">
@ -17,10 +16,6 @@
</div> </div>
</div> </div>
<div class="infoBox-content"> <div class="infoBox-content">
<div class="item">
<div class="item-left">IMEI号</div>
<div class="item-right">{{ value.deviceId }}</div>
</div>
<div class="item"> <div class="item">
<div class="item-left">定位时间</div> <div class="item-left">定位时间</div>
<div class="item-right">{{ value.locationTime }}</div> <div class="item-right">{{ value.locationTime }}</div>
@ -86,12 +81,8 @@ enum locateEnum {
font-size: 16px; font-size: 16px;
color: #333; color: #333;
font-weight: 400; font-weight: 400;
.span {
flex-shrink: 0; flex-shrink: 0;
font-weight: 700; font-weight: 700;
}
.battery { .battery {
width: 34px; width: 34px;
height: 16px; height: 16px;

View File

@ -38,7 +38,6 @@ const handleBeforeUnload = (event: any) => {
}; };
const onMessage = (res) => { const onMessage = (res) => {
console.log(res, "WebSocket接收服务器消息");
if (res.cmd == "warning") { if (res.cmd == "warning") {
alarmRef.value.visible = true; alarmRef.value.visible = true;
alarmRef.value.warningList.unshift({ ...res, createTime: format(new Date(), "HH:mm:ss") }); alarmRef.value.warningList.unshift({ ...res, createTime: format(new Date(), "HH:mm:ss") });
@ -51,20 +50,21 @@ const onMessage = (res) => {
}; };
onMounted(() => { onMounted(() => {
// const isReload = localStorage.getItem("isReload"); const isReload = localStorage.getItem("isReload");
// if (isReload !== "true") { if (isReload !== "true") {
// ElMessageBox.alert("", "", { ElMessageBox.alert("由于浏览器安全策略,用户必须点击屏幕才能播放告警声音", "提示", {
// confirmButtonText: "OK", confirmButtonText: "OK",
// callback: () => { callback: () => {
// localStorage.setItem("isReload", "true"); localStorage.setItem("isReload", "true");
// }, },
// }); });
// } }
if (ws.socket == null) { if (ws.socket == null) {
ws.connect(); ws.connect();
} }
ws.onMessage(onMessage); ws.onMessage(onMessage);
window.addEventListener("beforeunload", handleBeforeUnload); window.addEventListener("beforeunload", handleBeforeUnload);
}); });

View File

@ -103,20 +103,30 @@ export class MapCustom {
}) })
} }
newIcon(url) { newIcon(option) {
return new AMap.Icon({ let data = {
size: new AMap.Size(36, 42), size: new AMap.Size(36, 42),
image: url, // Icon的图像 image: '', // Icon的图像
imageSize: new AMap.Size(36, 42) imageSize: new AMap.Size(36, 42)
}) }
if (typeof option == 'string') {
data.image = option
} else {
data = {
image: option.image, // Icon的图像
size: new AMap.Size(option.size[0], option.size[1]),
imageSize: new AMap.Size(option.size[0], option.size[1]),
}
}
return new AMap.Icon({ ...data })
} }
// 创建marker // 创建marker
marker({ icon, position }) { marker({ icon, position, offset }) {
return new AMap.Marker({ return new AMap.Marker({
icon, icon,
position, position,
map: this.map, map: this.map,
offset: new AMap.Pixel(-20, -40), offset: new AMap.Pixel(-13, -26),
}) })
} }
lngLat(lng, lat) { lngLat(lng, lat) {

View File

@ -41,9 +41,10 @@ export default class WebSocketService {
} }
webScoketLogin() { webScoketLogin() {
const comm = useCommonStore();
this.sendMessage({ this.sendMessage({
username: "admin", username: comm.user.username,
password: "111111", token: comm.user.token,
type: 'web', type: 'web',
cmd: "webLogin", cmd: "webLogin",
}) })
@ -106,6 +107,8 @@ export default class WebSocketService {
onMessage = (callback) => { onMessage = (callback) => {
this.socket.onmessage = (event) => { this.socket.onmessage = (event) => {
const data = JSON.parse(event.data); const data = JSON.parse(event.data);
console.log(data, 'onMessage');
if (data.cmd == "webLogin" && !data.code == 200) return this.webScoketLogin() if (data.cmd == "webLogin" && !data.code == 200) return this.webScoketLogin()
callback && callback(data); callback && callback(data);
if (event.data.includes('heartbeat')) { if (event.data.includes('heartbeat')) {

View File

@ -13,7 +13,6 @@
<el-col :span="7"> <el-col :span="7">
<div class="right-content"> <div class="right-content">
<div class="info scrollbar"> <div class="info scrollbar">
<div class="info-text">设备序号{{ curData.id }}</div>
<div class="info-text">IMEI号{{ curData.deviceId }}</div> <div class="info-text">IMEI号{{ curData.deviceId }}</div>
<div class="info-text">告警时间{{ curData.createTime }}</div> <div class="info-text">告警时间{{ curData.createTime }}</div>
<div class="info-text"> <div class="info-text">
@ -77,6 +76,9 @@
</div> </div>
</el-col> </el-col>
</el-row> </el-row>
<div :style="{ display: 'none' }">
<InfoWindow class="infoBox" :value="locationInfo" @close="InfoWin.close()" />
</div>
</div> </div>
</template> </template>
@ -117,6 +119,8 @@ const disabled = ref(false);
const ruleFormRef = ref<FormInstance>(); const ruleFormRef = ref<FormInstance>();
let map = null; let map = null;
let myChart = null; let myChart = null;
let InfoWin = null;
let locationInfo = ref({});
const options = { const options = {
tooltip: { tooltip: {
@ -138,7 +142,7 @@ const options = {
grid: { grid: {
left: "0%", left: "0%",
right: "4%", right: "4%",
bottom: "3%", bottom: "6%",
containLabel: true, containLabel: true,
}, },
xAxis: { xAxis: {
@ -150,6 +154,28 @@ const options = {
yAxis: { yAxis: {
type: "value", type: "value",
}, },
dataZoom: [
{
type: "slider", //sliderinside
start: 90, // 10%
end: 100, // 60%
show: true,
xAxisIndex: [0],
handleSize: 0, // 2
height: 12, //
bottom: -2, //
borderColor: "#eee",
fillerColor: "#E7E7E7",
backgroundColor: "#eee", //
showDataShadow: false, // auto
showDetail: false, // true
realtime: true, //
filterMode: "filter",
handleStyle: {
borderRadius: "20",
},
},
],
series: [ series: [
{ {
itemStyle: { itemStyle: {
@ -235,14 +261,13 @@ watch(
const getData = async () => { const getData = async () => {
try { try {
const res = await warningDetail({ id: query.id as string }); const res = await warningDetail({ id: query.id as string });
locationInfo.value = res;
curData.value = res; curData.value = res;
ruleForm.name = res.rname; ruleForm.name = res.rname;
ruleForm.username = res.rname; ruleForm.username = res.rname;
ruleForm.content = res.rcontent; ruleForm.content = res.rcontent;
ruleForm.images = JSON.parse(res.rimg); ruleForm.images = JSON.parse(res.rimg);
let icon = map.newIcon(location);
let marker = map.marker({ icon, position: [116.406315, 39.908775] });
marker.setMap(map.map);
if (res.healthData && res.healthData.length) { if (res.healthData && res.healthData.length) {
res.healthData.forEach((item) => { res.healthData.forEach((item) => {
options.times.push(item.time); options.times.push(item.time);
@ -253,6 +278,16 @@ const getData = async () => {
}); });
myChart.setOption(options); myChart.setOption(options);
} }
map.clearMap();
map.setCenter([res.lng, res.lat]);
let icon = map.newIcon(location);
let marker = map.marker({ icon, position: [res.lng, res.lat] });
marker.setMap(map.map);
marker.on("click", () => {
InfoWin = map.infoWindow();
InfoWin.open(map.map, marker.getPosition());
});
} catch (error) {} } catch (error) {}
}; };
const submitForm = async (formEl: FormInstance | undefined) => { const submitForm = async (formEl: FormInstance | undefined) => {

View File

@ -14,10 +14,7 @@
<el-form-item> <el-form-item>
<el-button type="primary" :disabled="disabled" @click="submitForm(ruleFormRef)" class="btn" size="large"> </el-button> <el-button type="primary" :disabled="disabled" @click="submitForm(ruleFormRef)" class="btn" size="large"> </el-button>
</el-form-item> </el-form-item>
<div class="hint"> <div class="hint">如遇到账号问题请联系管理员</div>
如遇到账号问题请联系管理员<br />
管理员联系方式13812345678 邮箱123456@qq.com
</div>
</el-form> </el-form>
</div> </div>
</div> </div>

View File

@ -8,30 +8,118 @@
<el-radio-button label="体表温度" value="3" /> <el-radio-button label="体表温度" value="3" />
</el-radio-group> </el-radio-group>
</div> </div>
<div class="card-chart"> <div ref="chartRef" class="card-chart"></div>
<slot name="chart"></slot>
</div>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref } from "vue"; import { debounce, format } from "@/utils";
import { onMounted, onUnmounted, ref } from "vue";
import * as echarts from "echarts";
const radio = ref("1"); const radio = ref("1");
const chartRef = ref(null);
let myChart: any = null;
const emit = defineEmits(["change"]); const emit = defineEmits(["change"]);
defineExpose({ radio }); const options = {
tooltip: {
trigger: "axis",
formatter: function (params) {
let unit = { 心率: "次/分", 血氧: "%", 体表温度: "℃" };
var res = format(options.times[params[0].dataIndex]) + "<br/>";
res += params
.map(function (param, index) {
return param.marker + param.seriesName + "" + param.value + unit[param.seriesName] + "<br/>";
})
.join("");
return res;
},
},
times: [],
xAxis: {
type: "category",
data: [],
},
yAxis: {
type: "value",
},
grid: {
left: "5%",
right: "4%",
bottom: "20%",
},
dataZoom: [
{
type: "slider", //sliderinside
start: 90, // 10%
end: 100, // 60%
show: true,
xAxisIndex: [0],
handleSize: 0, // 2
height: 12, //
bottom: -2, //
borderColor: "#eee",
fillerColor: "#E7E7E7",
backgroundColor: "#eee", //
showDataShadow: false, // auto
showDetail: false, // true
realtime: true, //
filterMode: "filter",
handleStyle: {
borderRadius: "20",
},
},
],
series: {
name: "",
data: [],
type: "line",
showSymbol: false,
itemStyle: {
color: "#ff4567", // 线
},
smooth: true,
},
};
const getOptionsData = (list: { time: string; value: number }[], name: string, color: string) => {
options.xAxis.data = [];
options.series.data = [];
if (list && list.length) {
list.forEach((item) => {
options.times.push(item.time);
options.xAxis.data.push(format(item.time, "HH:mm:ss"));
options.series.data.push(item.value);
});
options.series.name = name;
options.series.itemStyle.color = color;
}
myChart.setOption(options);
};
const handleResize = debounce(() => {
myChart.resize();
}, 200);
defineExpose({ radio, getOptionsData });
onMounted(() => {
myChart = echarts.init(chartRef.value);
window.addEventListener("resize", handleResize);
});
onUnmounted(() => {
window.removeEventListener("resize", handleResize);
});
const change = (e) => { const change = (e) => {
emit("change", e); emit("change", e);
}; };
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
.card { .card {
// height: 100%; min-height: 385px;
flex-shrink: 0;
background: #ffffff; background: #ffffff;
padding: 16px 10px; padding: 16px 10px;
box-sizing: border-box; box-sizing: border-box;
flex: 1;
margin-right: 20px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;

View File

@ -10,7 +10,9 @@ import { format } from "@/utils";
import { MapCustom } from "@/utils/mapCustom"; import { MapCustom } from "@/utils/mapCustom";
import { onMounted, ref, watch } from "vue"; import { onMounted, ref, watch } from "vue";
import InfoWindow from "@/components/InfoWindow.vue"; import InfoWindow from "@/components/InfoWindow.vue";
import location from "@/assets/img/location.png"; import ViaMarker from "@/assets/img/via-marker.png";
import endMarker from "@/assets/img/end-marker.png";
import startMarker from "@/assets/img/start-marker.png";
let InfoWin = null; let InfoWin = null;
let newMap = null; let newMap = null;
@ -44,9 +46,28 @@ const getLocateRecord = () => {
newMap.clearMap(); newMap.clearMap();
newMap.setCenter([list[0].lng, list[0].lat]); newMap.setCenter([list[0].lng, list[0].lat]);
newMap.polyline(list); newMap.polyline(list);
let icon = newMap.newIcon(location); let startIcon = newMap.newIcon({
list.forEach((item) => { image: startMarker,
let marker = newMap.marker({ icon, position: [item.lng, item.lat] }); size: [20, 29],
});
let endIcon = newMap.newIcon({
image: endMarker,
size: [20, 29],
});
let ViaIcon = newMap.newIcon({
image: ViaMarker,
size: [20, 29],
});
list.forEach((item, index) => {
let marker: any = "";
if (index == 0) {
marker = newMap.marker({ icon: startIcon, position: [item.lng, item.lat] });
} else if (index == list.length - 1) {
marker = newMap.marker({ icon: endIcon, position: [item.lng, item.lat] });
} else {
marker = newMap.marker({ icon: ViaIcon, position: [item.lng, item.lat] });
}
marker.setMap(newMap.map); marker.setMap(newMap.map);
marker.on("click", () => { marker.on("click", () => {
locationInfo.value = item; locationInfo.value = item;

View File

@ -48,7 +48,7 @@ enum warnTypeEnum {
const warnTypeList = ["SOS告警", "围栏告警", "破坏告警", "低电告警", "心率告警", "血氧告警", "体温告警"]; const warnTypeList = ["SOS告警", "围栏告警", "破坏告警", "低电告警", "心率告警", "血氧告警", "体温告警"];
const paging = reactive({ const paging = reactive({
page: 1, page: 1,
size: 4, size: 5,
total: 0, total: 0,
deviceId: undefined, deviceId: undefined,
status: undefined, status: undefined,
@ -98,10 +98,12 @@ watch(
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
.card { .card {
background: #ffffff; min-height: 345px;
height: 100%;
padding: 16px 10px; padding: 16px 10px;
box-sizing: border-box; box-sizing: border-box;
flex-shrink: 0;
background: #ffffff;
.card-head { .card-head {
color: #061451; color: #061451;
font-size: 18px; font-size: 18px;

View File

@ -1,38 +1,32 @@
<template> <template>
<div class="container"> <div class="container">
<el-row class="el-row" :gutter="20"> <div class="el-row-left">
<el-col :span="6" class="el-row-left" <DeviceInfo :deviceInfo="deviceInfo" :paging="devicePaging" :list="deviceData" :handelMode="handelMode" :load="handelLoad" @click="handelClickDevice" />
><DeviceInfo :deviceInfo="deviceInfo" :paging="devicePaging" :list="deviceData" :handelMode="handelMode" :load="handelLoad" @click="handelClickDevice" </div>
/></el-col> <div class="el-row-right scrollbar">
<el-col :span="18" class="el-row-right scrollbar">
<MonitoringTop :funcList="funcList" /> <MonitoringTop :funcList="funcList" />
<div class="el-row-right-content" v-if="deviceInfo?.mode == 0 || deviceInfo?.mode == 2"> <div class="el-row-right-content" v-if="deviceInfo?.mode == 0 || deviceInfo?.mode == 2">
<DeviceLocationMap :device-id="deviceInfo.deviceId" /> <DeviceLocationMap :device-id="deviceInfo.deviceId" />
<div class="box"> <el-row class="box" :gutter="20">
<DeviceHistory @change="handelRadio" ref="devHisRef"> <el-col :span="12" :xs="24" :sm="24" :md="24" :lg="24" :xl="12" style="margin-bottom: 20px">
<template #chart> <DeviceHistory @change="handelRadio" ref="devHisRef" />
<div ref="chartRef" style="width: 100%; height: 100%"></div> </el-col>
</template> <el-col :span="12" :xs="24" :sm="24" :md="24" :lg="24" :xl="12">
</DeviceHistory>
<DeviceRecord :deviceInfo="deviceInfo" /> <DeviceRecord :deviceInfo="deviceInfo" />
</div> </el-col>
</el-row>
</div> </div>
<div class="el-row-right-content" v-else> <div class="el-row-right-content" v-else>
<el-row :gutter="20" style="margin-top: 20px"> <el-row :gutter="20">
<el-col :span="24"> <el-col :span="24" style="margin-bottom: 20px">
<DeviceHistory @change="handelRadio" ref="devHisRef"> <DeviceHistory @change="handelRadio" ref="devHisRef" />
<template #chart>
<div ref="chartRef1" style="width: 100%; height: 350px"></div>
</template>
</DeviceHistory>
</el-col> </el-col>
<el-col :span="24" style="margin-top: 20px"> <el-col :span="24">
<DeviceRecord :deviceInfo="deviceInfo" /> <DeviceRecord :deviceInfo="deviceInfo" />
</el-col> </el-col>
</el-row> </el-row>
</div> </div>
</el-col> </div>
</el-row>
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
@ -40,21 +34,17 @@ import DeviceInfo from "./deviceInfo.vue";
import MonitoringTop from "./monitoringTop.vue"; import MonitoringTop from "./monitoringTop.vue";
import DeviceHistory from "./deviceHistory.vue"; import DeviceHistory from "./deviceHistory.vue";
import DeviceRecord from "./deviceRecord.vue"; import DeviceRecord from "./deviceRecord.vue";
import * as echarts from "echarts"; import DeviceLocationMap from "./deviceLocationMap.vue";
import { deviceList, healthLatestData } from "@/api/index"; import { deviceList, healthLatestData } from "@/api/index";
import { TDevice, THealthLatestData } from "@/api/index.d"; import { TDevice, THealthLatestData } from "@/api/index.d";
import { onMounted, ref, reactive, onUnmounted, watch, nextTick } from "vue"; import { onMounted, ref, reactive, onUnmounted } from "vue";
import { debounce, format } from "@/utils"; import { format } from "@/utils";
import heart from "@/assets/img/heart.png"; import heart from "@/assets/img/heart.png";
import temperature from "@/assets/img/temperature.png"; import temperature from "@/assets/img/temperature.png";
import blood from "@/assets/img/blood.png"; import blood from "@/assets/img/blood.png";
import DeviceLocationMap from "./deviceLocationMap.vue";
const chartRef = ref(null);
const chartRef1 = ref(null);
const devHisRef = ref(null); const devHisRef = ref(null);
const loadFlag = ref(false); const loadFlag = ref(false);
let myChart = null;
let Interval = null; let Interval = null;
let funcList = ref([ let funcList = ref([
{ title: "当前心率", en: "DANGQIANXINLV", icon: heart, unit: "次/分", num: 0, color: "#FF0303" }, { title: "当前心率", en: "DANGQIANXINLV", icon: heart, unit: "次/分", num: 0, color: "#FF0303" },
@ -126,28 +116,6 @@ const HealthData = ref<THealthLatestData.TRes>();
const deviceInfo = ref<TDevice.IListRes>(); const deviceInfo = ref<TDevice.IListRes>();
const deviceData = ref<TDevice.IListRes[]>([]); const deviceData = ref<TDevice.IListRes[]>([]);
watch(
() => deviceInfo,
(newVal) => {
if (newVal.value) {
if (newVal.value?.mode == 0 || newVal.value?.mode == 2) {
nextTick(() => {
myChart = echarts.init(chartRef.value);
});
options.grid.left = "10%";
options.grid.bottom = "30%";
} else {
options.grid.left = "5%";
options.grid.bottom = "20%";
nextTick(() => {
myChart = echarts.init(chartRef1.value);
});
}
}
},
{ deep: true }
);
const getdeviceList = async () => { const getdeviceList = async () => {
const res = await deviceList(devicePaging); const res = await deviceList(devicePaging);
deviceData.value = [...deviceData.value, ...res.records]; deviceData.value = [...deviceData.value, ...res.records];
@ -167,35 +135,19 @@ const getHealthLatestData = () => {
funcList.value[0].num = res.hr; funcList.value[0].num = res.hr;
funcList.value[1].num = res.bo; funcList.value[1].num = res.bo;
funcList.value[2].num = res.temp; funcList.value[2].num = res.temp;
handelRadio(devHisRef.value.radio); handelRadio(devHisRef.value.radio);
}); });
}; };
const handelRadio = (val: number) => { const handelRadio = (val: number) => {
console.log("刷新");
if (val == 1) { if (val == 1) {
getOptionsData(HealthData.value.hrArr, "心率", "#FF0303"); devHisRef.value?.getOptionsData(HealthData.value.hrArr, "心率", "#FF0303");
} else if (val == 2) { } else if (val == 2) {
getOptionsData(HealthData.value.boArr, "血氧", "#983AFC"); devHisRef.value?.getOptionsData(HealthData.value.boArr, "血氧", "#983AFC");
} else if (val == 3) { } else if (val == 3) {
getOptionsData(HealthData.value.tempArr, "体表温度", "#FFA91F"); devHisRef.value?.getOptionsData(HealthData.value.tempArr, "体表温度", "#FFA91F");
} }
}; };
const getOptionsData = (list: { time: string; value: number }[], name: string, color: string) => {
options.xAxis.data = [];
options.series.data = [];
if (list && list.length) {
list.forEach((item) => {
options.times.push(item.time);
options.xAxis.data.push(format(item.time, "HH:mm:ss"));
options.series.data.push(item.value);
});
options.series.name = name;
options.series.itemStyle.color = color;
}
myChart.setOption(options);
};
const IntervalFn = () => { const IntervalFn = () => {
Interval = setInterval(() => { Interval = setInterval(() => {
@ -218,47 +170,42 @@ const handelClickDevice = (val: TDevice.IListRes) => {
deviceInfo.value = val; deviceInfo.value = val;
getHealthLatestData(); getHealthLatestData();
}; };
const handleResize = debounce(() => {
myChart.resize();
}, 200);
onMounted(() => { onMounted(() => {
getdeviceList(); getdeviceList();
myChart = echarts.init(chartRef.value ? chartRef.value : chartRef1.value);
window.addEventListener("resize", handleResize);
}); });
onUnmounted(() => { onUnmounted(() => {
clearInterval(Interval); clearInterval(Interval);
window.removeEventListener("resize", handleResize);
}); });
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
.container { .container {
overflow: hidden; overflow: hidden;
display: flex; display: flex;
.el-row { flex-direction: row;
flex: 1;
overflow: hidden;
display: flex;
.el-row-left { .el-row-left {
height: 100%; width: 335px;
// height: 100%;
display: flex; display: flex;
overflow: hidden; overflow: hidden;
flex-shrink: 0;
} }
.el-row-right { .el-row-right {
height: 100%; width: 100%;
overflow: auto; overflow: auto;
margin-left: 20px;
.el-row-right-content { .el-row-right-content {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden; overflow: hidden;
// height: 100%;
.box { .box {
height: 388px; height: 100%;
flex-shrink: 0; flex-shrink: 0;
overflow: hidden;
margin-top: 20px; margin-top: 20px;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
.el-col {
height: 100%;
} }
} }
} }

View File

@ -10,6 +10,9 @@
<template #location="{ rows }"> <template #location="{ rows }">
<el-button type="success" link :icon="View" v-if="rows.warnType == 0 || rows.warnType == 1" @click="toIncidentDispose(rows.id)"> 查看 </el-button> <el-button type="success" link :icon="View" v-if="rows.warnType == 0 || rows.warnType == 1" @click="toIncidentDispose(rows.id)"> 查看 </el-button>
</template> </template>
<template #warnType="{ rows }">
{{ warnTypeEnum[rows.warnType] }}
</template>
<template #status="{ rows }"> <template #status="{ rows }">
<el-tag :type="rows.status == 1 ? 'success' : 'danger'"> <el-tag :type="rows.status == 1 ? 'success' : 'danger'">
{{ statusEnum[rows.status] }} {{ statusEnum[rows.status] }}
@ -38,6 +41,15 @@ enum statusEnum {
"待处理", "待处理",
"已处理", "已处理",
} }
enum warnTypeEnum {
"SOS告警",
"围栏告警",
"破坏告警",
"低电告警",
"心率告警",
"血氧告警",
"体温告警",
}
const search = ref(""); const search = ref("");
const { tableData, page, getData, changePage } = defineProps({ const { tableData, page, getData, changePage } = defineProps({
@ -66,6 +78,7 @@ const { tableData, page, getData, changePage } = defineProps({
let columns = [ let columns = [
{ type: "index", label: "序号", width: 55, align: "center" }, { type: "index", label: "序号", width: 55, align: "center" },
{ prop: "deviceId", label: "IMEI号" }, { prop: "deviceId", label: "IMEI号" },
{ prop: "warnType", label: "事件类型" },
{ prop: "createTime", label: "时间" }, { prop: "createTime", label: "时间" },
{ prop: "location", label: "地理位置" }, { prop: "location", label: "地理位置" },
{ prop: "status", label: "处理状态" }, { prop: "status", label: "处理状态" },

View File

@ -228,43 +228,36 @@ const getOrgAllList = () => {
}); });
}; };
const handelControl = (type: number) => { const handelControl = (type: number) => {
switch (type) { let api: Function;
case 4: let params: any = {};
deviceGetLocation({ if (type == 4) {
deviceId: rowData.value.deviceId, api = deviceGetLocation;
}).then(() => { params = { deviceId: rowData.value.deviceId };
ElMessage.success("操作成功"); } else if (type == 5) {
}); api = setMode;
break; params = {
case 5:
setMode({
deviceId: rowData.value.deviceId, deviceId: rowData.value.deviceId,
mode: controlForm.mode, mode: controlForm.mode,
}).then(() => { };
getData(); } else if (type == 6) {
ElMessage.success("操作成功"); api = deviceOta;
}); params = rowData.value.deviceId;
break; } else {
case 6:
deviceOta(rowData.value.deviceId).then(() => {
getData();
ElMessage.success("操作成功");
});
break;
default:
let cmdEnum = { let cmdEnum = {
1: "poweroff", 1: "poweroff",
2: "restart", 2: "restart",
3: "factory", 3: "factory",
}; };
deviceControl({ api = deviceControl;
params = {
deviceId: rowData.value.deviceId, deviceId: rowData.value.deviceId,
cmd: cmdEnum[type], cmd: cmdEnum[type],
}).then(() => { };
}
api(params).then(() => {
getData();
ElMessage.success("操作成功"); ElMessage.success("操作成功");
}); });
break;
}
visible1.value = false; visible1.value = false;
}; };