2025年05月09日18:28:30

This commit is contained in:
luojiayi 2025-05-09 18:28:33 +08:00
parent 5e52002178
commit bb0b996c8b
11 changed files with 150 additions and 73 deletions

1
components.d.ts vendored
View File

@ -13,6 +13,7 @@ declare module '@vue/runtime-core' {
ElAvatar: typeof import('element-plus/es')['ElAvatar']
ElButton: typeof import('element-plus/es')['ElButton']
ElCard: typeof import('element-plus/es')['ElCard']
ElCascader: typeof import('element-plus/es')['ElCascader']
ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
ElCol: typeof import('element-plus/es')['ElCol']
ElDatePicker: typeof import('element-plus/es')['ElDatePicker']

View File

@ -19,6 +19,16 @@
>
<el-option v-for="(opt, index) in item.opts" :label="opt.label" :value="opt.value" :key="index"></el-option>
</el-select>
<el-cascader
style="width: 168px"
v-model="cascaderValue"
v-else-if="item.type === 'cascader'"
:options="item.opts"
:props="item.props"
:show-all-levels="item.showAllLevels"
clearable
@change="(e) => cascaderChange(e, item.prop, item.showAllLevels)"
/>
<el-date-picker v-else-if="item.type === 'date'" type="date" v-model="query[item.prop]" :value-format="item.format"></el-date-picker>
<el-date-picker
style="width: 220px"
@ -60,11 +70,20 @@ const props = defineProps({
},
});
const cascaderValue = ref();
const searchRef = ref<FormInstance>();
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return;
formEl.resetFields();
props.search();
cascaderValue.value = undefined;
};
const cascaderChange = (e, name, showAllLevels = true) => {
if (e) {
props.query[name] = showAllLevels ? e : e[e.length - 1];
} else {
props.query[name] = undefined;
}
};
</script>

View File

@ -1,13 +1,14 @@
import { defineStore } from 'pinia';
import { TLogin, TRoleList } from "@/api/index.d";
import { roleList } from '@/api';
import { TLogin, TOrg, TRoleList } from "@/api/index.d";
import { roleList, orgAllList } from '@/api';
export const useCommonStore = defineStore('common', {
state: () => {
return {
time: new Date(),
user: <TLogin.IRes>{},
roleList: <TRoleList[]>[]
roleList: <TRoleList[]>[],
orgTree: <TOrg.IOrgRecordRes[]>[]
};
},
getters: {},
@ -20,6 +21,17 @@ export const useCommonStore = defineStore('common', {
this.roleList = res
})
},
getOrgAllList() {
orgAllList().then(res => {
this.orgTree = this.getTree(res)
})
},
getTree(list) {
list.forEach(item => {
item.children = list.filter(i => i.parentId === item.id)
});
return list.filter(item => item.parentId == null)
},
setUser(data: TLogin.IRes) {
this.user = data
},

View File

@ -18,6 +18,8 @@ export interface FormOptionList {
activeText?: string;
inactiveText?: string;
required?: boolean;
showAllLevels?: boolean;
defalut?: any;
validator?: Function;
props?: any;
}

View File

@ -57,6 +57,7 @@ const submitForm = async (formEl: FormInstance | undefined) => {
.then((res) => {
comm.setUser(res);
comm.getRoleList();
comm.getOrgAllList();
ElMessage({
message: "登录成功",
type: "success",

View File

@ -1,26 +1,25 @@
<template>
<div class="deviceStatistics card">
<div class="card-head">
<div class="title">当前设备历史数据</div>
<el-radio-group v-model="radio" @change="change">
<el-radio-button label="心率" value="1" />
<el-radio-button label="血氧" value="2" />
<el-radio-button label="体表温度" value="3" />
</el-radio-group>
</div>
<div class="card-head">当前设备历史数据</div>
<div ref="chartRef" class="card-chart"></div>
</div>
</template>
<script setup lang="ts">
import { debounce, format } from "@/utils";
import { onMounted, onUnmounted, ref } from "vue";
import { format } from "@/utils";
import { onMounted, ref, watch } from "vue";
import * as echarts from "echarts";
import { useResize } from "@/utils/hooks";
import { THealthLatestData } from "@/api/index.d";
const radio = ref("1");
const chartRef = ref(null);
let myChart: any = null;
const emit = defineEmits(["change"]);
const props = defineProps({
HealthData: {
type: Object as () => THealthLatestData.TRes,
default: () => ({}),
},
});
const options = {
tooltip: {
trigger: "axis",
@ -48,6 +47,7 @@ const options = {
type: "value",
},
grid: {
top: "5%",
left: "5%",
right: "4%",
bottom: "20%",
@ -74,44 +74,66 @@ const options = {
},
},
],
series: {
name: "",
data: [],
type: "line",
showSymbol: false,
itemStyle: {
color: "#ff4567", // 线
series: [
{
name: "心率",
data: [],
type: "line",
itemStyle: {
color: "#FF4241",
},
showSymbol: false,
},
smooth: true,
},
{
name: "血氧",
data: [],
type: "line",
itemStyle: {
color: "#12CCA2",
},
showSymbol: false,
},
{
name: "体表温度",
data: [],
type: "line",
itemStyle: {
color: "#FF7D00",
},
showSymbol: false,
},
],
};
const getOptionsData = (list: { time: string; value: number }[], name: string, color: string) => {
const getOptionsData = (res: THealthLatestData.TRes) => {
options.xAxis.data = [];
options.series.data = [];
if (list && list.length) {
list.forEach((item) => {
options.series[0].data = [];
options.series[1].data = [];
options.series[2].data = [];
if (res && res.hrArr) {
res.hrArr.forEach((item, i) => {
options.xAxis.data.push(item.time);
options.series.data.push(item.value);
options.series[0].data.push(item.value);
options.series[1].data.push(res.boArr[i].value);
options.series[2].data.push(res.tempArr[i].value);
});
options.series.name = name;
options.series.itemStyle.color = color;
}
myChart.setOption(options);
};
defineExpose({ radio, getOptionsData });
watch(
() => props.HealthData,
(newVal) => {
getOptionsData(newVal);
}
);
useResize(() => {
myChart.resize();
});
onMounted(() => {
myChart = echarts.init(chartRef.value);
});
const change = (e) => {
emit("change", e);
};
</script>
<style scoped lang="less">
.card {
@ -126,24 +148,15 @@ const change = (e) => {
.card-head {
color: #061451;
font-size: 18px;
display: flex;
align-items: center;
justify-content: space-between;
transform: translateX(-10px);
.title {
&::before {
display: inline-block;
margin-right: 10px;
content: "";
width: 2px;
height: 14px;
border-radius: 20px;
background: #061451;
}
}
.search {
display: flex;
align-items: center;
&::before {
display: inline-block;
margin-right: 10px;
content: "";
width: 2px;
height: 14px;
border-radius: 20px;
background: #061451;
}
}
.card-chart {

View File

@ -94,7 +94,8 @@ const statusColor = ["danger", "success", "warning"];
const modeColor = ["primary", "danger", "warning"];
enum statusEnum {
"离线" = 0,
"关机" = -1,
"离线",
"在线",
"充电中",
}

View File

@ -9,7 +9,7 @@
<DeviceLocationMap :device-id="deviceInfo.deviceId" />
<el-row class="box" :gutter="20">
<el-col :span="12" :xs="24" :sm="24" :md="24" :lg="24" :xl="12" style="margin-bottom: 20px">
<DeviceHistory @change="handleRadio" ref="devHisRef" />
<DeviceHistory :HealthData="HealthData" />
</el-col>
<el-col :span="12" :xs="24" :sm="24" :md="24" :lg="24" :xl="12">
<DeviceRecord :deviceInfo="deviceInfo" />
@ -19,7 +19,7 @@
<div class="el-row-right-content" v-else>
<el-row :gutter="20">
<el-col :span="24" style="margin-bottom: 20px">
<DeviceHistory @change="handleRadio" ref="devHisRef" />
<DeviceHistory :HealthData="HealthData" />
</el-col>
<el-col :span="24">
<DeviceRecord :deviceInfo="deviceInfo" />
@ -42,8 +42,6 @@ import heart from "@/assets/img/heart.png";
import temperature from "@/assets/img/temperature.png";
import blood from "@/assets/img/blood.png";
const devHisRef = ref(null);
let Interval = null;
let funcList = ref([
{ title: "当前心率", en: "DANGQIANXINLV", icon: heart, unit: "次/分", num: 0, color: "#FF0303" },
@ -60,18 +58,8 @@ const getHealthLatestData = () => {
funcList.value[0].num = res.hr;
funcList.value[1].num = res.bo;
funcList.value[2].num = res.temp;
handleRadio(devHisRef.value.radio);
});
};
const handleRadio = (val: number) => {
if (val == 1) {
devHisRef.value?.getOptionsData(HealthData.value.hrArr, "心率", "#FF0303");
} else if (val == 2) {
devHisRef.value?.getOptionsData(HealthData.value.boArr, "血氧", "#983AFC");
} else if (val == 3) {
devHisRef.value?.getOptionsData(HealthData.value.tempArr, "体表温度", "#FFA91F");
}
};
const IntervalFn = () => {
Interval = setInterval(() => {
@ -80,7 +68,6 @@ const IntervalFn = () => {
};
const handleClickDevice = (val: TDevice.IListRes) => {
devHisRef.value.radio = "1";
deviceInfo.value = val;
getHealthLatestData();
if (!Interval) {

View File

@ -35,6 +35,9 @@ import { TableItem } from "@/types/table";
import { FormOptionList } from "@/types/form-option";
import Alarm from "@/components/alarm.vue";
import { TOrg } from "@/api/index.d";
import { useCommonStore } from "@/store/common";
const comm = useCommonStore();
// 0- 1-
enum StatusEnum {
"禁用" = 0,
@ -98,6 +101,7 @@ const handleDel = (id: number) => {
.then(async () => {
orgDelete({ id }).then(() => {
ElMessage.success("删除成功");
comm.getOrgAllList();
getData();
});
})
@ -116,6 +120,7 @@ const updateData = (res) => {
api(res).then((res) => {
ElMessage.success(msg);
visible.value = false;
comm.getOrgAllList();
getData();
});
};

View File

@ -62,12 +62,14 @@ import TableSearch from "@/components/table-search.vue";
import TableEdit from "@/components/table-edit.vue";
import DeviceControl from "./deviceControl.vue";
import BindArea from "./bindArea.vue";
import { useCommonStore } from "@/store/common";
import { TableItem } from "@/types/table";
import { FormOption, FormOptionList } from "@/types/form-option";
import { useRouter } from "vue-router";
enum statusEnum {
"离线" = 0,
"关机" = -1,
"离线",
"在线",
"充电中",
}
@ -80,7 +82,7 @@ enum modeEnum {
const statusColor = ["danger", "success", "warning"];
const modeColor = ["primary", "danger", "warning"];
const comm = useCommonStore();
const router = useRouter();
// /
let TableEditOptions = ref<FormOption>({
@ -115,6 +117,7 @@ const searchOpt = ref<FormOptionList[]>([
label: "设备状态:",
prop: "status",
opts: [
{ label: "关机", value: -1 },
{ label: "离线", value: "0" },
{ label: "在线", value: "1" },
{ label: "充电中", value: "2" },
@ -129,6 +132,18 @@ const searchOpt = ref<FormOptionList[]>([
{ label: "使用中", value: "1" },
],
},
{
type: "cascader",
label: "辖区:",
prop: "orgId",
opts: comm.orgTree,
showAllLevels: false,
props: {
checkStrictly: true,
label: "name",
value: "id",
},
},
]);
const handleSearch = () => {
changePage(1);

View File

@ -16,7 +16,7 @@
</template>
<template #roleId="{ rows }">
{{ roleEnum[rows.roleId] }}
{{ getRoleName(rows.roleId) }}
</template>
<!--
<template #password="{ rows }">
@ -131,6 +131,18 @@ const searchOpt = ref<FormOptionList[]>([
{ label: "启用", value: "1" },
],
},
{
type: "cascader",
label: "辖区:",
prop: "orgId",
opts: comm.orgTree,
showAllLevels: false,
props: {
checkStrictly: true,
label: "name",
value: "id",
},
},
]);
//
@ -151,6 +163,15 @@ let columns = ref([
const handleImp = () => {
batchImpRef.value.dialogVisible = true;
};
const getRoleName = (id) => {
let name = "--";
comm.roleList.forEach((item) => {
if (item.id == id) {
name = item.name;
}
});
return name;
};
const handleSearch = () => {
paging.page = 1;
getData();