Browse Source

图表修改

develop
fuguobin 1 year ago
parent
commit
2f7c0dae65
  1. 4
      .env.production
  2. 2
      src/api/device/types.ts
  3. 11
      src/store/modules/user.ts
  4. 2
      src/types/auto-imports.d.ts
  5. 202
      src/views/details/index - 副本 (2).vue
  6. 187
      src/views/details/index - 副本.vue
  7. 226
      src/views/details/index.vue
  8. 574
      src/views/monitoring/components/header.vue
  9. 4
      src/views/monitoring/screen/components/main.vue
  10. 4
      vite.config.ts

4
.env.production

@ -5,6 +5,6 @@ VITE_APP_PORT = 8089
#VITE_APP_WS_API = 'ws://board.heatiot.cn:8001/prod-api' ## websocket地址
#VITE_APP_BASE_API = 'http://board.heatiot.cn:8001/prod-api/' ## 线上接口
#VITE_APP_WS_API = 'ws://${window.location.host}/ws' ## websocket地址 ws://10.10.10.56:9000/websocket/
VITE_APP_BASE_API = '/prod-api/' ## 正式环境
# VITE_APP_BASE_API = '/biprod-api/' ## 测试环境
# VITE_APP_BASE_API = '/prod-api/' ## 正式环境
VITE_APP_BASE_API = '/biprod-api/' ## 测试环境

2
src/api/device/types.ts

@ -74,10 +74,12 @@ export interface parameterVo {
version: null;
}
export interface seriesVo {
index: number;
name: string;
type: string;
smooth: boolean;
symbol: string;
paramUnit: string;
unit: string;
data: Array<string | number>;
}

11
src/store/modules/user.ts

@ -13,6 +13,7 @@ import { useSessionStorage } from '@vueuse/core';
export const useUserStore = defineStore('user', () => {
// state
const token = useSessionStorage('userToken', '');
const userInfo = useSessionStorage('userInfo', {});
const nickname = ref('');
const avatar = ref('');
const roles = ref<Array<string>>([]); // 用户角色编码集合 → 判断路由权限
@ -27,7 +28,7 @@ export const useUserStore = defineStore('user', () => {
function login(loginData: LoginData) {
return new Promise<void>((resolve, reject) => {
loginApi(loginData)
.then((response:any) => {
.then((response: any) => {
const userToken = response.token;
token.value = 'Bearer ' + userToken; // Bearer eyJhbGciOiJIUzI1NiJ9.xxx.xxx
resolve();
@ -42,19 +43,20 @@ export const useUserStore = defineStore('user', () => {
function getInfo() {
return new Promise<UserInfo>((resolve, reject) => {
getUserInfo()
.then((data:any) => {
.then((data: any) => {
if (!data) {
return reject('Verification failed, please Login again.');
}
if (!data.roles || data.roles.length <= 0) {
reject('getUserInfo: roles must be a non-null array!');
}
const user=data.user
const user = data.user;
nickname.value = user.nickName;
avatar.value = user.avatar;
roles.value = data.roles;
perms.value = data.permissions;
useSessionStorage('userInfo', user);
userInfo.value = user;
// useSessionStorage('userInfo', user);
resolve(data);
})
.catch(error => {
@ -81,6 +83,7 @@ export const useUserStore = defineStore('user', () => {
// 重置
function resetToken() {
token.value = '';
userInfo.value = {};
nickname.value = '';
avatar.value = '';
roles.value = [];

2
src/types/auto-imports.d.ts

@ -2,7 +2,6 @@
export {}
declare global {
const EffectScope: typeof import('vue')['EffectScope']
const ElForm: typeof import('element-plus/es')['ElForm']
const ElMessage: typeof import('element-plus/es')['ElMessage']
const ElMessageBox: typeof import('element-plus/es')['ElMessageBox']
const ElNotification: typeof import('element-plus/es')['ElNotification']
@ -273,7 +272,6 @@ import { UnwrapRef } from 'vue'
declare module 'vue' {
interface ComponentCustomProperties {
readonly EffectScope: UnwrapRef<typeof import('vue')['EffectScope']>
readonly ElForm: UnwrapRef<typeof import('element-plus/es')['ElForm']>
readonly ElMessage: UnwrapRef<typeof import('element-plus/es')['ElMessage']>
readonly ElMessageBox: UnwrapRef<typeof import('element-plus/es')['ElMessageBox']>
readonly ElNotification: UnwrapRef<typeof import('element-plus/es')['ElNotification']>

202
src/views/details/index - 副本 (2).vue

@ -1,202 +0,0 @@
<template>
<div class="details">
<el-card class="search" shadow="always">
<el-form ref="searchRef" :inline="true" :model="searchForm" label-width="100px" class="demo-ruleForm">
<el-form-item label="时间" prop="time">
<el-date-picker
v-model="searchForm.time"
type="datetimerange"
start-placeholder="开始时间"
end-placeholder="结束时间"
:default-time="defaultTime1"
/>
</el-form-item>
<el-form-item label="颗粒度" prop="particle">
<el-select v-model="searchForm.particle" placeholder="请选择">
<el-option v-for="item in particleData" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item label="设备" prop="device">
<el-select v-model="searchForm.device" placeholder="请选择">
<el-option v-for="item in optionss" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item label="参数" prop="parameter">
<el-select v-model="searchForm.parameter" placeholder="请选择">
<el-option v-for="item in optionss" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm(searchRef)">确认</el-button>
<el-button @click="resetForm(searchRef)">重置</el-button>
</el-form-item>
</el-form>
</el-card>
<el-card class="echart" shadow="always">
<div class="comparisonInfo">
<div ref="stackedRef" class="stackedLine" />
</div>
</el-card>
</div>
</template>
<script lang="ts" setup>
import * as echarts from 'echarts';
import { Ref } from 'vue';
const stackedRef: Ref<HTMLElement | any> = ref(null);
import type { FormInstance } from 'element-plus';
const searchRef = ref<FormInstance>();
const defaultTime1 = new Date(2000, 1, 1, 12, 0, 0); // '12:00:00'
const searchForm = reactive({
time: '',
particle: '',
device: '',
parameter: ''
});
const submitForm = (formEl: FormInstance | undefined) => {
if (!formEl) return;
formEl.validate(valid => {
if (valid) {
console.log('submit!');
} else {
console.log('error submit!');
return false;
}
});
};
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return;
formEl.resetFields();
};
const particleData = [
{ label: '分钟', value: 1 },
{ label: '小时', value: 2 }
];
const optionss = [
{
value: 'Option1',
label: 'Option1'
},
{
value: 'Option2',
label: 'Option2'
}
];
const colors = ['#EE6666', '#91CC75', '#5470C6'];
const options = {
color: colors,
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross'
}
},
grid: {
right: '20%'
},
toolbox: {
feature: {
dataView: { show: true, readOnly: false },
restore: { show: true },
saveAsImage: { show: true }
}
},
legend: {
data: ['回温', '供压', '回压']
},
xAxis: [
{
type: 'category',
axisTick: {
alignWithLabel: true
},
// prettier-ignore
data: ['2021', '2022', '2023', '2024', '2025', '2026', '2027', '2028', '2029', '2030', '2031', '2032']
}
],
yAxis: [
{
type: 'value',
name: '回温',
position: 'right',
alignTicks: true,
axisLine: {
show: true,
lineStyle: {
color: colors[0]
}
},
axisLabel: {
formatter: '{value} ml'
}
},
{
type: 'value',
name: '供压',
position: 'right',
alignTicks: true,
offset: 80,
axisLine: {
show: true,
lineStyle: {
color: colors[1]
}
},
axisLabel: {
formatter: '{value} ml'
}
},
{
type: 'value',
name: '回压',
position: 'left',
alignTicks: true,
axisLine: {
show: true,
lineStyle: {
color: colors[2]
}
},
axisLabel: {
formatter: '{value} °C'
}
}
],
series: [
{
name: '回温',
type: 'line',
data: [2.0, 4.9, 7.0, 23.2, 25.6, 76.7, 135.6, 162.2, 32.6, 20.0, 6.4, 3.3]
},
{
name: '供压',
type: 'line',
yAxisIndex: 2,
data: [5.0, 2.2, 3.3, 4.5, 6.3, 10.2, 20.3, 23.4, 23.0, 16.5, 12.0, 6.2]
},
{
name: '回压',
type: 'line',
yAxisIndex: 1,
data: [2.6, 5.9, 9.0, 26.4, 28.7, 70.7, 175.6, 182.2, 48.7, 18.8, 6.0, 2.3]
}
]
};
onMounted(() => {
//
const chart = echarts.init(stackedRef.value);
chart.setOption(options);
//
window.addEventListener('resize', () => {
chart.resize();
});
});
</script>
<style lang="scss" scoped>
@import './index.scss';
</style>

187
src/views/details/index - 副本.vue

@ -1,187 +0,0 @@
<template>
<div class="details">
<el-card class="search" shadow="always">
<el-form ref="searchRef" :inline="true" :model="searchForm" label-width="100px" class="demo-ruleForm">
<el-form-item label="时间" prop="time">
<el-date-picker
v-model="searchForm.time"
type="datetimerange"
start-placeholder="开始时间"
end-placeholder="结束时间"
:default-time="defaultTime1"
/>
</el-form-item>
<!-- <el-form-item label="颗粒度" prop="particle">
<el-select v-model="searchForm.particle" placeholder="请选择">
<el-option v-for="item in optionss" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item> -->
<el-form-item label="设备" prop="device">
<el-select v-model="searchForm.device" placeholder="请选择">
<el-option v-for="item in optionss" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item label="参数" prop="parameter">
<el-select v-model="searchForm.parameter" placeholder="请选择">
<el-option v-for="item in optionss" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm(searchRef)">确认</el-button>
<el-button @click="resetForm(searchRef)">重置</el-button>
</el-form-item>
</el-form>
</el-card>
<el-card class="echart" shadow="always">
<div class="comparisonInfo">
<div ref="stackedRef" class="stackedLine" />
</div>
</el-card>
</div>
</template>
<script lang="ts" setup>
import * as echarts from 'echarts';
import { Ref } from 'vue';
const stackedRef: Ref<HTMLElement | any> = ref(null);
import type { FormInstance } from 'element-plus';
const searchRef = ref<FormInstance>();
const defaultTime1 = new Date(2000, 1, 1, 12, 0, 0); // '12:00:00'
const searchForm = reactive({
time: '',
particle: '',
device: '',
parameter: ''
});
const submitForm = (formEl: FormInstance | undefined) => {
if (!formEl) return;
formEl.validate(valid => {
if (valid) {
console.log('submit!');
} else {
console.log('error submit!');
return false;
}
});
};
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return;
formEl.resetFields();
};
const optionss = [
{
value: 'Option1',
label: 'Option1'
},
{
value: 'Option2',
label: 'Option2'
},
{
value: 'Option3',
label: 'Option3'
},
{
value: 'Option4',
label: 'Option4'
},
{
value: 'Option5',
label: 'Option5'
}
];
const options = {
title: {
text: 'Temperature Change in the Coming Week'
},
tooltip: {
trigger: 'axis'
},
legend: {},
toolbox: {
show: true,
feature: {
dataZoom: {
yAxisIndex: 'none'
},
dataView: { readOnly: false },
magicType: { type: ['line', 'bar'] },
restore: {},
saveAsImage: {}
}
},
xAxis: {
type: 'category',
boundaryGap: false,
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
yAxis: {
type: 'value',
axisLabel: {
formatter: '{value} °C'
}
},
series: [
{
name: 'Highest',
type: 'line',
data: [10, 11, 13, 11, 12, 12, 9],
markPoint: {
data: [
{ type: 'max', name: 'Max' },
{ type: 'min', name: 'Min' }
]
},
markLine: {
data: [{ type: 'average', name: 'Avg' }]
}
},
{
name: 'Lowest',
type: 'line',
data: [1, -2, 2, 5, 3, 2, 0],
markPoint: {
data: [{ name: '周最低', value: -2, xAxis: 1, yAxis: -1.5 }]
},
markLine: {
data: [
{ type: 'average', name: 'Avg' },
[
{
symbol: 'none',
x: '90%',
yAxis: 'max'
},
{
symbol: 'circle',
label: {
position: 'start',
formatter: 'Max'
},
type: 'max',
name: '最高点'
}
]
]
}
}
]
};
onMounted(() => {
//
const chart = echarts.init(stackedRef.value);
chart.setOption(options);
//
window.addEventListener('resize', () => {
chart.resize();
});
});
</script>
<style lang="scss" scoped>
@import './index.scss';
</style>

226
src/views/details/index.vue

@ -793,30 +793,30 @@ const options2 = {
color: colors[1]
}
}
},
{
type: 'value',
name: '累计热量(JG)',
position: 'right',
alignTicks: true,
offset: 100,
scale: true, //
minInterval: 1, //
nameTextStyle: {
fontSize: 12,
padding: [0, 0, 0, 0] //name
},
axisTick: {
//
show: false
},
axisLine: {
show: true,
lineStyle: {
color: colors[2]
}
}
}
// {
// type: 'value',
// name: '(JG)',
// position: 'right',
// alignTicks: true,
// offset: 100,
// scale: true, //
// minInterval: 1, //
// nameTextStyle: {
// fontSize: 12,
// padding: [0, 0, 0, 0] //name
// },
// axisTick: {
// //
// show: false
// },
// axisLine: {
// show: true,
// lineStyle: {
// color: colors[2]
// }
// }
// }
],
// yAxis: {
// type: 'value',
@ -982,9 +982,9 @@ const options2 = {
type: 'line',
smooth: true,
symbol: 'none',
yAxisIndex: 2,
yAxisIndex: 1,
data: [
['2023-10-01 08:00:00', Math.round(Math.random() * 500)],
['2023-10-01 08:00:00', Math.round(Math.random() * 600)],
['2023-10-01 09:00:00', Math.round(Math.random() * 500)],
['2023-10-01 10:00:00', Math.round(Math.random() * 500)],
['2023-10-01 11:00:00', Math.round(Math.random() * 500)],
@ -1097,76 +1097,114 @@ function init(data: any) {
options.series = [];
if (data.mainInfos.length === 0) {
options.title.text = '暂无数据';
} else {
options.title.text = data.additionalInfo.name;
options.title.x = 'top';
options.title.y = 'left';
if (multipleLimit.value === 0 && parameterLimit.value === 1) {
console.log('单设备多参数');
data.mainInfos.map((item: seriesVo, index: number) => {
const offsetData = index === 0 ? 0 : index === 1 ? 0 : (index - 1) * 100;
console.log('offsetData--', offsetData);
options.legend.data.push(item.name);
options.yAxis.push({
type: 'value',
name: `${item.name}(${item.paramUnit})`,
position: `${index === 0 ? 'left' : 'right'}`,
alignTicks: true,
offset: offsetData,
scale: true, //
// minInterval: 1, //
nameTextStyle: {
fontSize: 12,
padding: [0, 0, 0, 0] //name
},
axisTick: {
//
show: false
},
axisLine: {
show: true,
lineStyle: {
color: colors[index]
}
}
});
options.series.push({
name: item.name,
type: 'line',
smooth: true,
symbol: 'none',
yAxisIndex: index,
data: item.data
});
});
} else {
console.log('多设备单参数');
options.yAxis.push({
type: 'value',
scale: true, //
minInterval: 1, //
name: `${data.additionalInfo.name}(${data.additionalInfo.unit})`,
nameTextStyle: {
fontSize: 12,
padding: [0, 0, 0, 0] //name
},
axisTick: {
//
show: false
}
});
data.mainInfos.map((item: seriesVo) => {
options.legend.data.push(item.name);
options.series.push({
name: item.name,
type: 'line',
smooth: true,
symbol: 'none',
data: item.data
});
});
}
return;
}
options.title.text = data.additionalInfo.name;
options.title.x = 'top';
options.title.y = 'left';
data.units.map((item: seriesVo, index: number) => {
const offsetData = index === 0 ? 0 : index === 1 ? 0 : (index - 1) * 100;
console.log('offsetData--', offsetData);
options.yAxis.push({
type: 'value',
name: `${item.name}(${item.unit})`,
position: `${index === 0 ? 'left' : 'right'}`,
alignTicks: true,
offset: offsetData,
scale: true, //
// minInterval: 1, //
nameTextStyle: {
fontSize: 12,
padding: [0, 0, 0, 0] //name
},
axisTick: {
//
show: false
},
axisLine: {
show: true,
lineStyle: {
color: colors[index]
}
}
});
});
data.mainInfos.map((item: seriesVo, index: number) => {
options.legend.data.push(item.name);
options.series.push({
name: item.name,
type: 'line',
smooth: true,
symbol: 'none',
yAxisIndex: item.index,
data: item.data
});
});
// if (multipleLimit.value === 0 && parameterLimit.value === 1) {
// console.log('');
// data.mainInfos.map((item: seriesVo, index: number) => {
// const offsetData = index === 0 ? 0 : index === 1 ? 0 : (index - 1) * 100;
// console.log('offsetData--', offsetData);
// options.legend.data.push(item.name);
// options.yAxis.push({
// type: 'value',
// name: `${item.name}(${item.paramUnit})`,
// position: `${index === 0 ? 'left' : 'right'}`,
// alignTicks: true,
// offset: offsetData,
// scale: true, //
// // minInterval: 1, //
// nameTextStyle: {
// fontSize: 12,
// padding: [0, 0, 0, 0] //name
// },
// axisTick: {
// //
// show: false
// },
// axisLine: {
// show: true,
// lineStyle: {
// color: colors[index]
// }
// }
// });
// options.series.push({
// name: item.name,
// type: 'line',
// smooth: true,
// symbol: 'none',
// yAxisIndex: index,
// data: item.data
// });
// });
// } else {
// console.log('');
// options.yAxis.push({
// type: 'value',
// scale: true, //
// minInterval: 1, //
// name: `${data.additionalInfo.name}(${data.additionalInfo.unit})`,
// nameTextStyle: {
// fontSize: 12,
// padding: [0, 0, 0, 0] //name
// },
// axisTick: {
// //
// show: false
// }
// });
// data.mainInfos.map((item: seriesVo) => {
// options.legend.data.push(item.name);
// options.series.push({
// name: item.name,
// type: 'line',
// smooth: true,
// symbol: 'none',
// data: item.data
// });
// });
// }
const chart = echarts.init(stackedRef.value);
chart.clear();
chart.resize();

574
src/views/monitoring/components/header.vue

@ -1,200 +1,222 @@
<template>
<div class="title">
<h3>{{ titleData }}</h3>
<div class="title">
<h3>{{ titleData }}</h3>
</div>
<div class="weather">
<div class="time">{{ currentTime }} {{ lunarDay.ncWeek }}</div>
<div class="line"></div>
<div class="forecast">
<span>{{ weatherData.city }}{{ weatherData.weather }} {{ weatherData.temperature }}</span>
<svg-icon class="weatherSvg" :icon-class="weatherData.weatherImg" />
<!-- <img src="../../../assets/images/weather/duoyun.png" /> -->
</div>
<div class="weather">
<div class="time">
{{ currentTime }} {{ lunarDay.ncWeek }}
</div>
<div class="seeting">
<n-tooltip trigger="hover">
<template #trigger>
<n-button class="tooltips" circle quaternary @click="lineClick">
<template #icon>
<n-icon>
<ChartLine />
</n-icon>
</template>
</n-button>
</template>
图表
</n-tooltip>
<n-tooltip trigger="hover" v-if="settingShow">
<template #trigger>
<n-button class="tooltips" circle quaternary @click="showClick">
<template #icon>
<n-icon>
<Settings />
</n-icon>
</template>
</n-button>
</template>
显示项
</n-tooltip>
<n-tooltip trigger="hover">
<template #trigger>
<n-button class="tooltips" circle quaternary @click="returnBack">
<template #icon>
<n-icon>
<Power />
</n-icon>
</template>
</n-button>
</template>
返回上一页
</n-tooltip>
<n-tooltip trigger="hover" v-if="warningShow">
<template #trigger>
<n-badge class="warningbadge" :value="waringData.length" :max="15">
<n-button class="tooltips" circle quaternary @click="waringClick">
<template #icon>
<n-icon>
<Bell />
</n-icon>
</template>
</n-button>
</n-badge>
</template>
报警
</n-tooltip>
</div>
<n-drawer class="waringDrawer" v-model:show="waringDrawer" :default-width="420" resizable placement="right">
<n-drawer-content closable>
<template #header>
<div class="title">
<span>消息</span>
<span class="button" @click="waringMore">更多</span>
</div>
<div class="line"></div>
<div class="forecast">
<span>{{ weatherData.city }}{{ weatherData.weather }} {{ weatherData.temperature }}</span>
<svg-icon class="weatherSvg" :icon-class="weatherData.weatherImg" />
<!-- <img src="../../../assets/images/weather/duoyun.png" /> -->
</template>
<div class="waringList">
<div class="item" v-for="(item, index) in waringData" :key="index">
<div class="name">
<span>{{ item.deviceName }}</span>
<span class="time">{{ item.alertTime }}</span>
</div>
<div class="info">
<span>{{ item.paramName }}</span>
<n-button type="info" size="small" @click="waringConfirm(item)">确认</n-button>
</div>
</div>
</div>
<div class="seeting">
<n-tooltip trigger="hover" v-if="settingShow">
<template #trigger>
<n-button class="tooltips" circle quaternary @click="showClick">
<template #icon>
<n-icon>
<Settings />
</n-icon>
</template>
</n-button>
</template>
显示项
</n-tooltip>
<n-tooltip trigger="hover">
<template #trigger>
<n-button class="tooltips" circle quaternary @click="returnBack">
<template #icon>
<n-icon>
<Power />
</n-icon>
</template>
</n-button>
</template>
返回上一页
</n-tooltip>
<n-tooltip trigger="hover" v-if="warningShow">
<template #trigger>
<n-badge class="warningbadge" :value="waringData.length" :max="15">
<n-button class="tooltips" circle quaternary @click="waringClick">
<template #icon>
<n-icon>
<Bell />
</n-icon>
</template>
</n-button>
</n-badge>
</template>
报警
</n-tooltip>
</div>
<n-drawer class="waringDrawer" v-model:show="waringDrawer" :default-width="420" resizable placement="right">
<n-drawer-content closable>
<template #header>
<div class="title">
<span>消息</span>
<span class="button" @click="waringMore">更多</span>
</div>
</template>
<div class="waringList">
<div class="item" v-for="(item, index) in waringData" :key="index">
<div class="name">
<span>{{ item.deviceName }}</span>
<span class="time">{{ item.alertTime }}</span>
</div>
<div class="info">
<span>{{ item.paramName }}</span>
<n-button type="info" size="small" @click="waringConfirm(item)">确认</n-button>
</div>
</div>
</div>
</n-drawer-content>
</n-drawer>
<n-modal class="waringModal" v-model:show="waringModal">
<n-card :bordered="false" size="huge" role="dialog" aria-modal="true">
<el-table class="waringTable" :data="waringList" header-row-class-name="headerRowClass"
header-cell-class-name="headerCellClass" row-class-name="rowClass" cell-class-name="cellClass" height="350"
stripe>
<el-table-column prop="deviceName" label="设备名称" align="center" />
<el-table-column prop="paramName" label="变量名称" align="center" />
<el-table-column prop="alertName" label="告警级别" align="center">
<template #default="scope">
<span class="level">{{ scope.row.alertName }}</span>
</template>
</el-table-column>
<el-table-column prop="totalCounts" label="告警累计" align="center" />
<el-table-column label="报警时间" align="center">
<el-table-column prop="alertFirstTime" label="首次告警时间" align="center" />
<el-table-column prop="alertLastTime" label="末次告警时间" align="center" />
</el-table-column>
<el-table-column fixed="right" label="操作" align="center">
<template #default="scope">
<el-button class="confirm" type="info" size="small" @click="waringConfirm(scope.row)">确认</el-button>
</template>
</el-table-column>
</el-table>
<div class="warClose" @click="warClose">
<CloseCircleOutline />
</div>
</n-card>
</n-modal>
</div>
</n-drawer-content>
</n-drawer>
<n-modal class="waringModal" v-model:show="waringModal">
<n-card :bordered="false" size="huge" role="dialog" aria-modal="true">
<el-table
class="waringTable"
:data="waringList"
header-row-class-name="headerRowClass"
header-cell-class-name="headerCellClass"
row-class-name="rowClass"
cell-class-name="cellClass"
height="350"
stripe
>
<el-table-column prop="deviceName" label="设备名称" align="center" />
<el-table-column prop="paramName" label="变量名称" align="center" />
<el-table-column prop="alertName" label="告警级别" align="center">
<template #default="scope">
<span class="level">{{ scope.row.alertName }}</span>
</template>
</el-table-column>
<el-table-column prop="totalCounts" label="告警累计" align="center" />
<el-table-column label="报警时间" align="center">
<el-table-column prop="alertFirstTime" label="首次告警时间" align="center" />
<el-table-column prop="alertLastTime" label="末次告警时间" align="center" />
</el-table-column>
<el-table-column fixed="right" label="操作" align="center">
<template #default="scope">
<el-button class="confirm" type="info" size="small" @click="waringConfirm(scope.row)">确认</el-button>
</template>
</el-table-column>
</el-table>
<div class="warClose" @click="warClose">
<CloseCircleOutline />
</div>
</n-card>
</n-modal>
</template>
<script lang="ts" setup>
import { useRoute, useRouter } from "vue-router";
import { useRoute, useRouter } from 'vue-router';
import { getWeather } from '@/api/user/index';
import { getWarList, process } from '@/api/waring/index';
import { waringVo } from '@/api/waring/types';
import { Filter, Maximize, Settings, Power, Bell } from '@vicons/tabler';
import { Filter, Maximize, Settings, Power, Bell, ChartLine } from '@vicons/tabler';
import { CloseCircleOutline } from '@vicons/ionicons5';
import { useDateFormat, useNow } from '@vueuse/core';
import { uniqueArrayObject } from '@/utils/index';
import mitt from '@/plugins/bus';
import calendar from '@/utils/lunar';
const route = useRoute()
const router = useRouter()
const route = useRoute();
const router = useRouter();
const currentTime = useDateFormat(useNow(), 'YYYY-MM-DD HH:mm:ss');
const emit = defineEmits(['showModalClick', 'returnClick']);
const timer = ref()
const isCurrentRoute = ref(true)
const waringDrawer = ref(false)
const waringModal = ref(false)
const waringData = ref<waringVo[]>([])
const waringList = ref<waringVo[]>([])
const routerType = ref('')
const timer = ref();
const isCurrentRoute = ref(true);
const waringDrawer = ref(false);
const waringModal = ref(false);
const waringData = ref<waringVo[]>([]);
const waringList = ref<waringVo[]>([]);
const routerType = ref('');
const weatherData = ref(
{ city: "", weather: "", temperature: "", weatherImg: "" }
);
const weatherData = ref({ city: '', weather: '', temperature: '', weatherImg: '' });
const lunarDay: any = calendar.solarToLunar(
useNow().value.getUTCFullYear(),
useNow().value.getUTCMonth() + 1,
useNow().value.getUTCDate()
useNow().value.getUTCFullYear(),
useNow().value.getUTCMonth() + 1,
useNow().value.getUTCDate()
);
const props = defineProps({
titleData: {
type: String,
default: '数据大屏',
},
settingShow: {
type: Boolean,
default: false
},
warningShow: {
type: Boolean,
default: false
}
titleData: {
type: String,
default: '数据大屏'
},
settingShow: {
type: Boolean,
default: false
},
warningShow: {
type: Boolean,
default: false
}
});
onMounted(() => {
routerType.value = route.query?.id === undefined ? "0" : "1"
getWeatherData()
routerType.value = route.query?.id === undefined ? '0' : '1';
getWeatherData();
});
mitt.on('waringMessage', (res: any) => {
//
console.log("waringMessage--", res.data);
waringData.value = res.data
// waringData.value.push(res.data)
// console.log("waringData--", waringData.value);
// waringData.value = uniqueArrayObject(waringData.value, "id")
// console.log("waringData--", waringData.value);
//
console.log('waringMessage--', res.data);
waringData.value = res.data;
// waringData.value.push(res.data)
// console.log("waringData--", waringData.value);
// waringData.value = uniqueArrayObject(waringData.value, "id")
// console.log("waringData--", waringData.value);
});
function showClick() {
///
emit('showModalClick', true);
// showModal.value = true;
///
emit('showModalClick', true);
// showModal.value = true;
}
function returnBack() {
//
// emit('returnClick', '');
if (routerType.value === '1' && route.path != "/screen") {
router.push({
path: "/screen",
query: { id: sessionStorage.getItem('id') }
})
} else {
router.replace("/dashboard")
}
//
// emit('returnClick', '');
if (routerType.value === '1' && route.path != '/screen') {
router.push({
path: '/screen',
query: { id: sessionStorage.getItem('id') }
});
} else {
router.replace('/dashboard');
}
}
function waringClick() {
//
// if (waringData.value.length === 0) {
// ElNotification({
// message: '',
// type: 'info',
// })
// } else {
waringDrawer.value = true
// }
//
// if (waringData.value.length === 0) {
// ElNotification({
// message: '',
// type: 'info',
// })
// } else {
waringDrawer.value = true;
// }
}
function lineClick() {
//
router.push({
path: '/details'
});
}
// function getWeatherData() {
@ -207,150 +229,152 @@ function waringClick() {
// }
function getWeatherData() {
//
getWeather().then((res: any) => {
if (res.code === 200) {
if (isCurrentRoute) {
timer.value = setTimeout(async () => {
await (timer.value && clearTimeout(timer.value));
await getWeatherData();
}, 600000)
}
weatherData.value = res.data;
} else {
clearTimeout(timer.value);
}
});
//
getWeather().then((res: any) => {
if (res.code === 200) {
if (isCurrentRoute) {
timer.value = setTimeout(async () => {
await (timer.value && clearTimeout(timer.value));
await getWeatherData();
}, 600000);
}
weatherData.value = res.data;
} else {
clearTimeout(timer.value);
}
});
}
function waringMore() {
//
waringDrawer.value = false
waringModal.value = true
getwaringList()
//
waringDrawer.value = false;
waringModal.value = true;
getwaringList();
}
function getwaringList() {
const params = 0;
getWarList(params).then((res: any) => {
if (res.code === 200) {
waringList.value = res.rows;
}
});
const params = 0;
getWarList(params).then((res: any) => {
if (res.code === 200) {
waringList.value = res.rows;
}
});
}
function waringConfirm(item: any) {
//
ElMessageBox.confirm('是否确认操作?', '提示', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
}).then(() => {
const params = item.id;
process(params).then((res: any) => {
if (res.code === 200) {
waringList.value = res.data;
// waringDrawer.value = false
// waringModal.value = false
getwaringList()
ElMessage({
message: res.msg,
type: 'success',
})
}
});
}).catch(() => { })
//
ElMessageBox.confirm('是否确认操作?', '提示', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => {
const params = item.id;
process(params).then((res: any) => {
if (res.code === 200) {
waringList.value = res.data;
// waringDrawer.value = false
// waringModal.value = false
getwaringList();
ElMessage({
message: res.msg,
type: 'success'
});
}
});
})
.catch(() => {});
}
function warClose() {
//
waringModal.value = false
//
waringModal.value = false;
}
</script>
<style lang="scss" scoped>
.header {
display: flex;
justify-content: space-between;
align-items: center;
// height: 5.7rem;
display: flex;
justify-content: space-between;
align-items: center;
// height: 5.7rem;
.title {
width: 80%;
background: url(@/assets/images/title-bg.png);
background-size: 100%;
text-align: center;
padding-bottom: 38px;
margin: 0 auto;
.title {
width: 80%;
background: url(@/assets/images/title-bg.png);
background-size: 100%;
text-align: center;
padding-bottom: 38px;
margin: 0 auto;
h3 {
height: 57px;
font-size: 3.8rem;
font-family: 'YouSheBiaoTiHei';
font-weight: 400;
letter-spacing: 4px;
background: linear-gradient(180deg, #FEFDFF 0%, #95DAFF 97%);
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
margin: 0;
}
h3 {
height: 57px;
font-size: 3.8rem;
font-family: 'YouSheBiaoTiHei';
font-weight: 400;
letter-spacing: 4px;
background: linear-gradient(180deg, #fefdff 0%, #95daff 97%);
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
margin: 0;
}
}
}
.weather {
display: flex;
align-items: center;
position: absolute;
top: 2.5rem;
left: 7rem;
color: #b2d4ff;
font-size: 1.8rem;
line-height: 2.2rem;
font-family: 'AlibabaPuHuiTiRegular';
.line {
width: 2px;
height: 2rem;
background: linear-gradient(to top, #000e38, #1ea8dd, #000e38);
margin: 0 1rem;
}
.forecast {
display: flex;
align-items: center;
position: absolute;
top: 2.5rem;
left: 7rem;
color: #B2D4FF;
font-size: 1.8rem;
line-height: 2.2rem;
font-family: 'AlibabaPuHuiTiRegular';
.line {
width: 2px;
height: 2rem;
background: linear-gradient(to top, #000E38, #1EA8DD, #000E38);
margin: 0 1rem;
.weatherSvg {
width: 1.5em !important;
height: 1.5em !important;
margin-left: 10px;
}
.forecast {
display: flex;
align-items: center;
.weatherSvg {
width: 1.5em !important;
height: 1.5em !important;
margin-left: 10px;
}
// img {
// width: 25px;
// margin-left: 10px;
// }
}
// img {
// width: 25px;
// margin-left: 10px;
// }
}
}
.seeting {
position: absolute;
top: 2.5rem;
right: 7rem;
position: absolute;
top: 2.5rem;
right: 7rem;
.warningbadge {
margin-top: -10px;
}
.warningbadge {
margin-top: -10px;
}
.tooltips {
width: 36px;
height: 36px;
background: linear-gradient(180deg, #003269 1%, rgba(3, 79, 163, 0.2314) 56%, #003269 100%);
border-radius: 0px 0px 0px 0px;
opacity: 1;
.tooltips {
width: 36px;
height: 36px;
background: linear-gradient(180deg, #003269 1%, rgba(3, 79, 163, 0.2314) 56%, #003269 100%);
border-radius: 0px 0px 0px 0px;
opacity: 1;
:deep(span) {
color: #5beff9;
}
margin-left: 10px;
:deep(span) {
color: #5beff9;
}
margin-left: 10px;
}
}
</style>
</style>

4
src/views/monitoring/screen/components/main.vue

@ -161,8 +161,8 @@ const userInfo = JSON.parse(userStorageInfo === null ? '' : userStorageInfo);
// const baseApi = "http://board.heatiot.cn:8001/prod-api"//websocket
//const baseApi = import.meta.env.VITE_APP_BASE_API
//const apiUrl = baseApi.replace(/https?:/, '');
// const wsUrl = `ws://${window.location.host}/ws/websocket/${userInfo.userName}`; //websocket
const wsUrl = `ws://10.10.10.56:9010/websocket/${userInfo.userName}`; //websocket
const wsUrl = `ws://${window.location.host}/ws/websocket/${userInfo.userName}`; //websocket
// const wsUrl = `ws://172.1.2.158:9010/websocket/${userInfo.userName}`; //websocket
const emit = defineEmits(['tableHeaderData']);
// const listData = ref([

4
vite.config.ts

@ -46,8 +46,8 @@ export default defineConfig(({ mode }: ConfigEnv): UserConfig => {
proxy: {
[env.VITE_APP_BASE_API]: {
// target: 'http://172.1.2.196:9010/', //本地接口地址
target: 'http://172.1.2.139:9010/', //本地接口地址
// target: 'http://10.10.10.56:9010/', //线上测试接口地址
// target: 'http://172.1.2.158:9010/', //本地接口地址
target: 'http://10.10.10.56:9010/', //线上测试接口地址
changeOrigin: true,
rewrite: path => path.replace(new RegExp('^' + env.VITE_APP_BASE_API), '')
}

Loading…
Cancel
Save