Browse Source

项目合并处理

IoT
fuguobin 6 months ago
parent
commit
576976285b
  1. 27
      package.json
  2. 3774
      pnpm-lock.yaml
  3. 7
      src/main.js
  4. 44
      src/plugins/vxe-table/index.js
  5. 5
      src/router/index.js
  6. 9
      src/store/modules/user.js
  7. 7
      src/types/components.d.ts
  8. 42
      src/views/index.vue
  9. 606
      src/views/monitoring/components/header.vue
  10. 305
      src/views/monitoring/components/menu.vue
  11. 166
      src/views/monitoring/data-monitor/components/infoPanel.vue
  12. 598
      src/views/monitoring/data-monitor/components/main.vue
  13. 320
      src/views/monitoring/data-monitor/components/showTree.vue
  14. 752
      src/views/monitoring/data-monitor/index.scss
  15. 224
      src/views/monitoring/data-monitor/index.vue
  16. 2
      src/views/monitoring/equipment/components/main.vue
  17. 16
      vite.config.js

27
package.json

@ -1,6 +1,6 @@
{
"name": "iot-management-system",
"version": "2.0.0",
"version": "1.0.0",
"description": "IoT管理系统",
"author": "联美",
"license": "MIT",
@ -20,6 +20,7 @@
"@vee-validate/rules": "4.5.8",
"@vueuse/core": "9.5.0",
"animate.css": "^4.1.1",
"ant-design-vue": "4.0.0-rc.6",
"axios": "0.27.2",
"bpmn-js": "^11.4.1",
"can-autoplay": "^3.0.2",
@ -36,6 +37,7 @@
"nprogress": "0.2.0",
"pinia": "2.0.22",
"splitpanes": "^3.1.5",
"swiper": "^10.2.0",
"vee-validate": "4.5.8",
"vkbeautify": "^0.99.3",
"vue": "3.2.45",
@ -45,14 +47,14 @@
"vue-router": "4.1.4",
"vue3-seamless-scroll": "^2.0.1",
"vuedraggable": "^2.24.3",
"vxe-table": "^4.5.14",
"vxe-table-plugin-antd": "^3.1.0",
"vxe-table-plugin-charts": "^3.1.0",
"vxe-table-plugin-element": "^3.1.0",
"vxe-table-plugin-menus": "^3.2.1",
"vxe-table-plugin-renderer": "^3.1.0",
"vxe-table-plugin-validator": "^3.0.0",
"xe-utils": "^3.5.14"
"vxe-table": "^4.5.21",
"vxe-table-plugin-antd": "^4.0.1",
"vxe-table-plugin-charts": "^4.0.1",
"vxe-table-plugin-element": "^4.0.1",
"vxe-table-plugin-menus": "^4.0.0",
"vxe-table-plugin-renderer": "^4.0.0",
"vxe-table-plugin-validator": "^4.0.0",
"xe-utils": "^3.5.22"
},
"devDependencies": {
"@types/crypto-js": "^4.2.1",
@ -61,16 +63,17 @@
"@vicons/antd": "^0.12.0",
"@vicons/ionicons5": "^0.12.0",
"@vicons/tabler": "^0.12.0",
"@vitejs/plugin-vue": "3.1.0",
"@vitejs/plugin-vue": "^4.2.3",
"@vue/compiler-sfc": "3.2.45",
"naive-ui": "^2.34.4",
"sass": "1.56.1",
"typescript": "^4.7.4",
"unplugin-auto-import": "^0.11.5",
"unplugin-vue-components": "^0.26.0",
"vite": "^3.2.3",
"vite": "^4.3.9",
"vite-plugin-compression": "0.5.1",
"vite-plugin-svg-icons": "2.0.1",
"vite-plugin-vue-setup-extend": "0.4.0"
"vite-plugin-vue-setup-extend": "0.4.0",
"vue-tsc": "^0.35.0"
}
}

3774
pnpm-lock.yaml

File diff suppressed because it is too large

7
src/main.js

@ -2,7 +2,6 @@ import { createApp } from "vue";
import Cookies from "js-cookie";
import ElementPlus from "element-plus";
// import naive from "naive-ui";
import locale from "element-plus/lib/locale/lang/zh-cn"; // 中文语言
import { useTable } from "./plugins/vxe-table";
@ -102,12 +101,6 @@ app.use(BaiduMap, {
directive(app);
// 使用element-plus 并且设置全局的大小
app.use(ElementPlus, {
locale: locale,
// 支持 large、default、small
size: Cookies.get("size") || "default",
});
// app.use(naive);
app.use(useTable);
app.mount("#app");

44
src/plugins/vxe-table/index.js

@ -1,37 +1,37 @@
import VXETable from 'vxe-table'
import 'vxe-table/lib/style.css'
import VXETable from "vxe-table";
import "vxe-table/lib/style.css";
// 自行按照,具体 echarts 看文档
import 'echarts/lib/chart/bar'
import 'echarts/lib/chart/pie'
import 'echarts/lib/chart/line'
import 'echarts/lib/component/grid'
import 'echarts/lib/component/tooltip'
import 'echarts/lib/component/legend'
import 'echarts/lib/component/legendScroll'
import "echarts/lib/chart/bar";
import "echarts/lib/chart/pie";
import "echarts/lib/chart/line";
import "echarts/lib/component/grid";
import "echarts/lib/component/tooltip";
import "echarts/lib/component/legend";
import "echarts/lib/component/legendScroll";
// 引入 vxe-table pro
import './pro/vxe-table-pro.es6.min'
import './pro/vxe-table-pro.min.css'
import "./pro/vxe-table-pro.es6.min";
import "./pro/vxe-table-pro.min.css";
// 引入快捷菜单插件(可选)
import VXETablePluginMenus from 'vxe-table-plugin-menus'
import VXETablePluginMenus from "vxe-table-plugin-menus";
// 引入图表插件(可选)
import VXETablePluginCharts from 'vxe-table-plugin-charts'
import 'vxe-table-plugin-charts/dist/style.css'
import VXETablePluginCharts from "vxe-table-plugin-charts";
import "vxe-table-plugin-charts/dist/style.css";
// 全局默认参数
VXETable.config({
authId: '1kedlpuyjow1v7ez', // Auth ID 在官网登录查看(必须,重要!!!)
version: 4, // 版本号,对于某些带数据缓存的功能有用到,上升版本号可以用于重置数据
zIndex: 999 // 全局 zIndex 起始值,如果项目的的 z-index 样式值过大时就需要跟随设置更大,避免被遮挡
})
authId: "1kedlpuyjow1v7ez", // Auth ID 在官网登录查看(必须,重要!!!)
version: 0, // 版本号,对于某些带数据缓存的功能有用到,上升版本号可以用于重置数据
zIndex: 999, // 全局 zIndex 起始值,如果项目的的 z-index 样式值过大时就需要跟随设置更大,避免被遮挡
});
// 安装快捷菜单插件(可选)
VXETable.use(VXETablePluginMenus)
VXETable.use(VXETablePluginMenus);
// 安装图表插件(可选)
VXETable.use(VXETablePluginCharts)
VXETable.use(VXETablePluginCharts);
export function useTable (app) {
app.use(VXETable)
export function useTable(app) {
app.use(VXETable);
}

5
src/router/index.js

@ -47,6 +47,11 @@ export const constantRoutes = [
component: () => import("@/views/register"),
hidden: true,
},
{
path: "/monitoring/data-monitor",
component: () => import("@/views/monitoring/data-monitor/index"),
hidden: true,
},
{
path: "/monitoring/equipment",
component: () => import("@/views/monitoring/equipment/index"),

9
src/store/modules/user.js

@ -1,13 +1,16 @@
import { login, logout, getInfo } from "@/api/login";
import { getToken, setToken, removeToken } from "@/utils/auth";
import defAva from "@/assets/images/avatar.png";
import cache from "@/plugins/cache";
const useUserStore = defineStore("user", {
state: () => ({
token: getToken(),
nickname: "",
name: "",
avatar: "",
roles: [],
perms: [],
permissions: [],
}),
actions: {
@ -35,7 +38,7 @@ const useUserStore = defineStore("user", {
getInfo()
.then((res) => {
const user = res.user;
const avatar =
const avatar = "";
user.avatar == "" || user.avatar == null
? defAva
: import.meta.env.VITE_APP_BASE_API + user.avatar;
@ -47,8 +50,11 @@ const useUserStore = defineStore("user", {
} else {
this.roles = ["ROLE_DEFAULT"];
}
this.nickname = user.nickName;
this.name = user.userName;
this.avatar = avatar;
this.perms = res.perms;
cache.session.setJSON("userInfo", user);
resolve(res);
})
.catch((error) => {
@ -63,6 +69,7 @@ const useUserStore = defineStore("user", {
.then(() => {
this.token = "";
this.roles = [];
this.perms = [];
this.permissions = [];
removeToken();
resolve();

7
src/types/components.d.ts

@ -21,6 +21,7 @@ declare module 'vue' {
ElButton: typeof import('element-plus/es')['ElButton']
ElCard: typeof import('element-plus/es')['ElCard']
ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
ElCol: typeof import('element-plus/es')['ElCol']
ElColorPicker: typeof import('element-plus/es')['ElColorPicker']
ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
ElDialog: typeof import('element-plus/es')['ElDialog']
@ -42,6 +43,8 @@ declare module 'vue' {
ElOption: typeof import('element-plus/es')['ElOption']
ElPagination: typeof import('element-plus/es')['ElPagination']
ElPopover: typeof import('element-plus/es')['ElPopover']
ElRadio: typeof import('element-plus/es')['ElRadio']
ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
ElRow: typeof import('element-plus/es')['ElRow']
ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
ElSelect: typeof import('element-plus/es')['ElSelect']
@ -56,6 +59,7 @@ declare module 'vue' {
ElTooltip: typeof import('element-plus/es')['ElTooltip']
ElTransfer: typeof import('element-plus/es')['ElTransfer']
ElTree: typeof import('element-plus/es')['ElTree']
ElTreeSelect: typeof import('element-plus/es')['ElTreeSelect']
ElUpload: typeof import('element-plus/es')['ElUpload']
ExecutionListener: typeof import('./../components/Process/panel/executionListener.vue')['default']
Expression: typeof import('./../components/flow/Expression/index.vue')['default']
@ -111,4 +115,7 @@ declare module 'vue' {
Week: typeof import('./../components/Crontab/week.vue')['default']
Year: typeof import('./../components/Crontab/year.vue')['default']
}
export interface ComponentCustomProperties {
vLoading: typeof import('element-plus/es')['ElLoadingDirective']
}
}

42
src/views/index.vue

@ -1,20 +1,24 @@
<template>
<div class="home">首页</div>
</template>
<!-- <template>
<div class="app-container home">
<video ref="videoPlayer" autoplay loop muted id="bgvid" class="home-page-video">
<source src="../assets/video/homepage.mp4" type="video/mp4">
<video
ref="videoPlayer"
autoplay
loop
muted
id="bgvid"
class="home-page-video"
>
<source src="../assets/video/homepage.mp4" type="video/mp4" />
</video>
<div class="middlewight">欢迎使用运营管理平台</div>
</div>
</template>
<script setup name="Index">
import { onMounted, watch, ref } from 'vue';
import { useRoute } from 'vue-router';
import { onMounted, watch, ref } from "vue";
import { useRoute } from "vue-router";
const { proxy } = getCurrentInstance();
const version = ref('3.8.5')
const version = ref("3.8.5");
const route = useRoute();
const videoElement = ref(null);
onMounted(() => {
@ -23,14 +27,17 @@ onMounted(() => {
videoElement.value.play();
}
});
watch(() => route.path, () => {
watch(
() => route.path,
() => {
if (videoElement.value) {
videoElement.value.play();
}
});
}
);
function goTarget(url) {
window.open(url, '__blank')
window.open(url, "__blank");
}
</script>
@ -96,7 +103,7 @@ function goTarget(url) {
}
}
.home-page-video{
.home-page-video {
position: fixed;
top: 50%;
left: 50%;
@ -106,18 +113,17 @@ function goTarget(url) {
height: auto;
transform: translateX(-50%) translateY(-50%);
z-index: -100;
}
.middlewight{
color:#eee;
}
.middlewight {
color: #eee;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size:88px;
font-size: 88px;
font-family: cursive;
width: 100%;
text-align: center;
}
}
</style> -->
</style>

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

@ -0,0 +1,606 @@
<template>
<div class="title">
<h3>{{ titleData }}</h3>
</div>
<div class="weather">
<div class="users">{{ timePeriod }} {{ userStore.nickname }}</div>
<div class="timeTips">
<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>
</div>
<div class="seeting">
<n-tooltip trigger="hover">
<template #trigger>
<n-button class="tooltips" circle dashed @click="returnBack">
<template #icon>
<n-icon>
<ReturnDownBack />
</n-icon>
</template>
</n-button>
</template>
返回上一页
</n-tooltip>
<n-tooltip trigger="hover">
<template #trigger>
<n-button class="tooltips" circle dashed @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 dashed @click="showClick">
<template #icon>
<n-icon>
<Settings />
</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 dashed @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">
<div class="title">
<svg-icon
icon-class="alarm"
v-if="audioType === true && item.alertSwitch === '1'"
/>
<span>{{ item.deviceName }}</span>
</div>
<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="alertFirstTimeS"
label="首次告警时间"
align="center"
/>
<el-table-column
prop="alertLastTimeS"
label="末次告警时间"
align="center"
/>
</el-table-column>
<el-table-column fixed="right" label="操作" align="center">
<template #default="scope">
<el-switch
v-model="scope.row.alertSwitchBoolean"
inline-prompt
active-text="开"
inactive-text="关"
@change="alarrmChange($event, scope.row)"
/>
<el-button
class="confirm"
type="info"
size="small"
@click="waringConfirm(scope.row)"
>确认</el-button
>
</template>
</el-table-column>
</el-table>
<el-pagination
class="waringPagination"
layout="prev, pager, next"
:current-page.sync="params.pageNum"
:page-size="params.pageSize"
:total="params.total"
hide-on-single-page
@current-change="handleCurrentChange"
/>
<div class="warClose" @click="warClose">
<CloseCircleOutline />
</div>
</n-card>
</n-modal>
<div class="alarm">
<audio
loop
autoplay
ref="alarsRef"
ebkit-playsinline="true"
playsinline="true"
controls="controls"
muted
hidden
>
<source :src="audisUrl" type="audio/mp3" />
</audio>
<audio
loop
autoplay
ref="alarmRef"
ebkit-playsinline="true"
playsinline="true"
:src="audioUrl"
muted
hidden
></audio>
</div>
</template>
<script setup>
import { useRoute, useRouter } from "vue-router";
import { getWeather } from "@/api/system/user";
import { getWarList, process, setAlarm } from "@/api/monitoring/table";
import useUserStore from "@/store/modules/user";
// import { waringVo } from '@/api/waring/types';
import {
Filter,
Maximize,
Settings,
Power,
Bell,
ChartLine,
} from "@vicons/tabler";
import { CloseCircleOutline, ReturnDownBack } from "@vicons/ionicons5";
import { useDateFormat, useNow } from "@vueuse/core";
// import { uniqueArrayObject } from '@/utils/index';
import canAutoPlay from "can-autoplay";
import mitt from "@/plugins/bus";
import calendar from "@/utils/lunar";
import audioUrl from "@/assets/media/alarm.mp3";
const audisUrl = ref("");
const userStore = useUserStore();
const hoursNow = useNow().value.getHours();
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 waringData = ref([]);
const waringList = ref([]);
const routerType = ref("");
const deptId = ref(0);
const params = reactive({
total: 10,
pageSize: 10,
pageNum: 1,
});
const alarmRef = ref();
const alarsRef = ref();
const audioType = ref(false);
const weatherData = ref({
city: "",
weather: "",
temperature: "",
weatherImg: "",
});
const lunarDay = calendar.solarToLunar(
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,
},
});
onMounted(() => {
deptId.value =
sessionStorage.getItem("deptId") === null
? 0
: Number(sessionStorage.getItem("deptId"));
routerType.value = route.query?.id === undefined ? "0" : "1";
getWeatherData();
document.body.addEventListener("mousedown", function () {
if (alarsRef.value != null) {
console.log("鼠标按下");
alarsRef.value.play();
alarsRef.value.muted = false;
}
});
});
const timePeriod = computed(() => {
if (hoursNow >= 3 && hoursNow < 8) {
return "早安!";
} else if (hoursNow >= 8 && hoursNow < 11) {
return "上午好!";
} else if (hoursNow >= 11 && hoursNow < 13) {
return "中午好!";
} else if (hoursNow >= 13 && hoursNow < 17) {
return "下午好!";
} else if (hoursNow >= 17 && hoursNow < 23) {
return "晚上好!";
} else if (hoursNow >= 23 && hoursNow < 3) {
return "晚安!";
}
});
mitt.on("waringMessage", (res) => {
//
console.log("waringMessage--", res.data);
waringData.value = res.data;
res.data.map((item) => {
// console.log(item.deviceName, item.alertSwitch);
if (item.alertSwitch === "1") {
// alarmRef.value.play();
// if (alarmRef.value) {
// //
// alarmRef.value.addEventListener('canplay', () => {
// audioType.value = true;
// alarmRef.value.play();
// // alarmRef.value.muted = false;
// });
// const playPromise = alarmRef.value.play();
// if (playPromise !== undefined) {
// playPromise.catch(error => {
// console.error(`Failed to play audio: ${error}`);
// });
// }
// }
canAutoPlay.audio().then(({ result }) => {
console.log("result--", result);
if (result === true) {
audioType.value = true;
alarmRef.value.play();
alarmRef.value.muted = false;
} else {
ElMessageBox.alert(
"检测到您的浏览器不支持媒体自动播放,是否同意播放提示音?",
"提示",
{
// if you want to disable its autofocus
// autofocus: false,
showClose: false,
confirmButtonText: "同意",
callback: (action) => {
audioType.value = true;
alarmRef.value.play();
alarmRef.value.muted = false;
},
}
);
}
});
return;
}
});
// 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;
}
function returnBack() {
//
// emit('returnClick', '');
if (routerType.value === "1" && route.path != "/monitoring/data-monitor") {
router.push({
path: "/monitoring/data-monitor",
query: { id: sessionStorage.getItem("id") },
});
} else {
router.go(-1);
}
}
function waringClick() {
//
// if (waringData.value.length === 0) {
// ElNotification({
// message: '',
// type: 'info',
// })
// } else {
waringDrawer.value = true;
// }
}
function lineClick() {
//
router.push({
path: "/monitoring/graph",
});
}
function handleCurrentChange(val) {
//
params.pageNum = val;
getwaringList();
}
function getWeatherData() {
//
getWeather().then((res) => {
if (res.code === 200) {
if (isCurrentRoute.value) {
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();
}
function getwaringList() {
//
const paramsr = {
beginTime: "",
endTime: "",
orgCode:
sessionStorage.getItem("deptId") === null
? 0
: Number(sessionStorage.getItem("deptId")),
params,
};
getWarList(paramsr).then((res) => {
if (res.code === 200) {
waringList.value = res.rows;
params.total = res.total;
// page.pageSize = res.size;
// page.pageSize = res.current;
}
});
}
function alarrmChange(val, row) {
//
const paramsr = {
id: row.id,
flag: val === true ? "1" : "0",
};
setAlarm(paramsr).then((res) => {
if (res.code === 200) {
if (val === false) {
audioType.value = false;
alarmRef.value.pause();
alarmRef.value.muted = true;
}
}
});
}
function waringConfirm(item) {
//
ElMessageBox.confirm("是否确认操作?", "提示", {
confirmButtonText: "确认",
cancelButtonText: "取消",
type: "warning",
})
.then(() => {
const params = item.id;
process(params).then((res) => {
if (res.code === 200) {
waringList.value = res.data;
audioType.value = false;
alarmRef.value.pause();
alarmRef.value.muted = true;
// waringDrawer.value = false
// waringModal.value = false
getwaringList();
ElMessage({
message: res.msg,
grouping: true, //
type: "success",
});
}
});
})
.catch(() => {});
}
function warClose() {
//
waringModal.value = false;
}
</script>
<style lang="scss" scoped>
.header {
display: flex;
justify-content: space-between;
align-items: center;
// height: 5.7rem;
.title {
width: 80%;
height: 70px;
line-height: 70px;
// background: url(@/assets/images/title-bg.png);
// background-size: 100%;
text-align: center;
// padding-bottom: 22px;
margin: 0 auto;
h3 {
font-size: 4.2rem;
font-family: "YouSheBiaoTiHei";
font-weight: 400;
letter-spacing: 4px;
background: linear-gradient(180deg, #fefdff 0%, #1677b3 100%);
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
margin: 0;
}
}
}
.weather {
position: absolute;
top: 10px;
left: 7rem;
font-size: 1.6rem;
font-family: "AlibabaPuHuiTiRegular";
.timeTips {
display: flex;
align-items: center;
// color: #b2d4ff;
}
.line {
width: 2px;
height: 2rem;
background: linear-gradient(to top, #000e38, #1ea8dd, #000e38);
margin: 0 1rem;
}
.forecast {
display: flex;
align-items: center;
.weatherSvg {
width: 1.5em !important;
height: 1.5em !important;
margin-left: 10px;
}
// img {
// width: 25px;
// margin-left: 10px;
// }
}
}
.seeting {
position: absolute;
top: 20px;
right: 7rem;
.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;
// :deep(span) {
// color: #5beff9;
// }
margin-left: 10px;
}
}
.waringModal {
.waringPagination {
justify-content: right;
margin-top: 5px;
:deep(button) {
color: #b1e3ff;
background: transparent;
}
:deep(.el-pager) {
.number,
.more {
color: #b1e3ff;
background: transparent;
}
.number.is-active {
color: #409eff;
}
}
}
}
</style>

305
src/views/monitoring/components/menu.vue

@ -0,0 +1,305 @@
<template>
<div class="menuCantent">
<n-menu
ref="menuInstRef"
class="menu"
:indent="0"
:options="menuOptions"
v-model:value="selectedKey"
key-field="deptId"
label-field="deptName"
:default-expand-all="false"
:watch-props="['defaultExpandedKeys']"
:render-label="renderMenuLabel"
@update:value="menuUpdateValue"
/>
</div>
</template>
<script lang="ts" setup>
import { useRoute } from "vue-router";
import type { MenuOption } from "naive-ui";
import { getMenu, getMenuData } from "@/api/monitoring/table";
import { getFirstNodeLastLevel } from "@/utils/index";
import useStorage from "@/utils/useStorage";
import mitt from "@/plugins/bus";
const router = useRoute();
const menuOptions = ref([]);
const selectedKey = ref();
const sessionStorageIns = useStorage("sessionStorage");
const routerType = ref("");
const id = ref(0);
const deptId = ref(0);
const menuDeptKey = ref(0);
const menuIdKey = ref(0);
const emit = defineEmits(["tableMenuData"]);
const props = defineProps({
menuType: {
type: String,
default: "1",
},
});
onMounted(() => {
routerType.value = router.query?.id === undefined ? "0" : "1";
id.value =
sessionStorage.getItem("id") === null
? 0
: Number(sessionStorage.getItem("id"));
deptId.value =
sessionStorage.getItem("deptId") === null
? 0
: Number(sessionStorage.getItem("deptId"));
if (props.menuType === "1") {
menuApi();
} else if (props.menuType === "2") {
comMenuApi();
}
});
function menuApi() {
//
getMenu().then((res: any) => {
if (res.code === 200) {
menuDeptKey.value =
routerType.value === "1"
? deptId.value
: routerType.value === "0" && deptId.value != 0
? deptId.value
: getFirstNodeLastLevel(res.data).deptId;
removeChildren(res.data);
menuOptions.value = res.data;
selectedKey.value = menuDeptKey.value;
sessionStorageIns.setUseStorage("deptId", menuDeptKey.value);
mitt.emit("menuKey", menuDeptKey.value);
emit("tableMenuData", res.data);
}
});
}
function comMenuApi() {
//
getMenuData().then((res: any) => {
if (res.code === 200) {
menuIdKey.value =
routerType.value === "1"
? id.value
: routerType.value === "0" && id.value != 0
? id.value
: getFirstNodeLastLevel(res.data).deptId;
const parentId =
routerType.value === "1"
? deptId.value
: getFirstNodeLastLevel(res.data).parentId;
removeChildren(res.data);
menuOptions.value = res.data;
selectedKey.value = menuIdKey.value;
sessionStorageIns.setUseStorage(
"deptId",
routerType.value === "1" ? deptId.value : parentId
);
mitt.emit("deviceMenuKey", menuIdKey.value);
emit("tableMenuData", res.data);
}
});
}
function removeChildren(menu: any) {
//children
if (!Array.isArray(menu)) {
return;
}
menu.forEach((item) => {
if (item.children && item.children.length === 0) {
delete item.children;
} else {
removeChildren(item.children);
}
});
}
// function renderMenuLabel(option: MenuOption) {
const renderMenuLabel = (option: MenuOption) => {
//
// return h(NEllipsis, null, option.deptName as string);
return h(NEllipsis, null, { default: () => option.deptName });
};
function menuUpdateValue(key: string, item: MenuOption) {
//
sessionStorageIns.setUseStorage(
props.menuType === "1" ? "deptId" : "id",
key
);
sessionStorageIns.setUseStorage("currentPage", 1);
if (props.menuType === "1") {
mitt.emit("currentPageEmit", 1);
}
if (props.menuType === "2") {
sessionStorageIns.setUseStorage("deptId", item.parentId);
}
mitt.emit(props.menuType === "1" ? "menuKey" : "deviceMenuKey", key);
console.log(key, item);
}
</script>
<style lang="scss" scoped>
:root {
--n-item-text-color-child-active-hover: #fff;
--n-item-text-color-active-hover: #fff;
--n-item-text-color-child-active: #fff;
}
.menuCantent {
height: -webkit-fill-available;
overflow: auto;
.menu {
text-align: center;
:deep(.n-submenu) {
--n-item-color-hover: auto;
.n-menu-item {
.n-menu-item-content {
padding: 0 !important;
.n-ellipsis {
font-family: "AlibabaPuHuiTiBold";
padding: 0 15px;
}
// .n-menu-item-content__arrow {
// color: #b1e3ff;
// }
}
.n-menu-item-content.n-menu-item-content--child-active {
// .n-menu-item-content-header {
// color: #b1e3ff;
// }
.n-menu-item-content__arrow {
color: var(--n-arrow-color);
}
}
// .n-menu-item-content--child-active {
// .n-menu-item-content-header:hover {
// color: #fff !important;
// }
// .n-menu-item-content__arrow:hover {
// color: #fff !important;
// }
// }
// .n-menu-item-content--child-active:hover{
// color: #fff !important;
// }
.n-menu-item-content-header {
font-size: 2.2rem;
color: var(--vxe-table-header-font-color);
}
}
.n-menu-item:hover {
color: #409eff;
}
.n-submenu-children {
.n-menu-item-content-header {
font-size: 1.6rem;
}
.n-menu-item-content--selected {
.n-menu-item-content-header {
color: #409eff;
.n-ellipsis {
position: relative;
span {
padding: 0 10px;
}
span::before {
content: none;
position: absolute;
left: 0;
top: 0.7rem;
width: 1.8rem;
height: 1.8rem;
// background: url(@/assets/images/taps.png) no-repeat;
// background-size: cover;
background-color: var(--menuActiveBg) !important;
}
}
}
}
.n-menu-item-content--selected::before {
background: -webkit-linear-gradient(left, #91d3fd 0%, #dedede 100%);
left: 0;
right: 0;
}
.n-menu-item-content--selected::after {
content: "";
position: absolute;
bottom: 0;
width: 100%;
height: 2px;
background: -webkit-linear-gradient(left, #409eff 0%, #dedede 100%);
}
}
.n-base-icon {
// color: #84e0f7;
right: 10px;
}
}
}
}
/*滚动条整体部分*/
.menuCantent::-webkit-scrollbar,
.tableGrid ::-webkit-scrollbar {
width: 8px;
height: 8px;
}
/*滚动条的轨道*/
.menuCantent::-webkit-scrollbar-track,
.tableGrid ::-webkit-scrollbar-track {
background-color: transparent;
-webkit-border-radius: 8px;
-moz-border-radius: 8px;
border-radius: 8px;
}
/*滚动条里面的小方块,能向上向下移动*/
.menuCantent::-webkit-scrollbar-thumb,
.tableGrid ::-webkit-scrollbar-thumb {
background-color: rgb(147, 147, 153, 0.5);
-webkit-border-radius: 8px;
-moz-border-radius: 8px;
border-radius: 8px;
}
.menuCantent::-webkit-scrollbar-thumb:hover,
.tableGrid ::-webkit-scrollbar-thumb:hover {
background-color: #a8a8a8;
}
.menuCantent::-webkit-scrollbar-thumb:active,
.tableGrid :-webkit-scrollbar-thumb:active {
background-color: #787878;
}
/*边角,即两个滚动条的交汇处*/
.menuCantent::-webkit-scrollbar-corner,
.tableGrid ::-webkit-scrollbar-corner {
background-color: transparent;
}
</style>

166
src/views/monitoring/data-monitor/components/infoPanel.vue

@ -0,0 +1,166 @@
<template>
<div class="infoPanel">
<swiper
class="swiper"
:loop="false"
:autoplay="{
delay: 500000,
pauseOnMouseEnter: true,
disableOnInteraction: false,
}"
:modules="modules"
:slides-per-view="4"
:space-between="15"
navigation
:pagination="{ clickable: true }"
>
<swiper-slide
class="item"
v-for="(item, index) in panelData"
:key="index"
>
<div class="content">
<div class="icon">
<img src="@/assets/images/panel_icon.png" />
</div>
<div class="numValue" v-if="item.type === 'A'">
<span>
<countTo :start="1" :end="item.value" :duration="3000"></countTo>
</span>
<i>{{ item.ext }}</i>
<p>{{ item.title }}</p>
</div>
<div class="numValueMore" v-if="item.type === 'B'">
<div
class="numItem"
v-for="(res, index) in item.extJsb.extData"
:key="index"
>
<span>{{ res.name }}</span>
<span
><countTo :start="1" :end="res.value" :duration="3000"></countTo
></span>
<span>{{ res.unit }}</span>
</div>
</div>
</div>
</swiper-slide>
</swiper>
</div>
</template>
<script lang="ts" setup>
import { Swiper, SwiperSlide } from "swiper/vue";
import { Navigation, Pagination, Autoplay } from "swiper/modules";
import { getTableFooter } from "@/api/monitoring/table";
import { PanelVo } from "@/api/monitoring/table/types";
import countTo from "@/utils/countTo";
import mitt from "@/plugins/bus";
import "swiper/css";
const modules = [Navigation, Pagination, Autoplay];
const panelData = ref<PanelVo[]>();
const deptId = ref(0);
// const panelData: PanelVo[] = [
// {
// title: '',
// value: 26449,
// ext: 'KJ',
// backImg: '/poll/hot',
// type: 'A',
// id: 2
// },
// {
// title: '',
// value: 9889,
// ext: 'm³',
// backImg: '/poll/onewater',
// type: 'A',
// id: 3
// },
// {
// title: '线',
// value: 40.425532,
// ext: '%',
// backImg: '/poll/dev',
// type: 'A',
// id: 1
// },
// {
// title: '',
// value: 27893,
// ext: '',
// backImg: '/poll/alert',
// type: 'A',
// id: 4
// },
// {
// title: '',
// value: 0,
// ext: [
// {
// name:'',
// value:'58996',
// ext:''
// },
// {
// name:'',
// value:'58996',
// ext:''
// },
// {
// name:'',
// value:'58996',
// ext:''
// },
// {
// name:'',
// value:'32369',
// ext:'t/h'
// },
// {
// name:'',
// value:'58996',
// ext:''
// },
// {
// name:'',
// value:'58996',
// ext:''
// },
// {
// name:'',
// value:'8956',
// ext:'T'
// }
// ],
// backImg: '/poll/alert',
// type: 'B',
// id: 5
// }
// ];
onMounted(() => {
deptId.value =
sessionStorage.getItem("deptId") === null
? 0
: Number(sessionStorage.getItem("deptId"));
getPanel();
});
mitt.on("menuKey", (res: any) => {
//
deptId.value = res;
getPanel();
});
function getPanel() {
//
const params = deptId.value;
getTableFooter(params).then((res: any) => {
if (res.code === 200) {
panelData.value = res.data;
}
});
}
</script>

598
src/views/monitoring/data-monitor/components/main.vue

@ -0,0 +1,598 @@
<template>
<div class="headerInfo" v-show="tapsShow">
<div class="header">
<div class="headerItem" v-for="(item, index) in headerData" :key="index">
<div class="name">{{ item.name }}</div>
<div class="value">{{ item.value }}</div>
</div>
</div>
</div>
<!-- <div
class="mainTable"
:style="{ height: tapsShow ? 'calc(100vh - 5.7rem - 222px)' : 'calc(100vh - 5.7rem - 60px)' }"
> -->
<div class="mainTable" :style="{ height: `${sidebarHeight}px` }">
<!-- <n-spin :show="loadingShow"> -->
<vxe-grid
ref="tableRef"
class="tableGrid"
align="center"
auto-resize
keep-source
:height="sidebarHeight - 4"
header-row-class-name="headerRowClass"
header-cell-class-name="headerCellClass"
row-class-name="tableRowClass"
cell-class-name="tableCellClass"
:sort-config="{ multiple: true, trigger: 'cell' }"
:stripe="!tableBorder"
:border="tableBorder"
:column-config="{ resizable: true, useKey: true }"
:row-config="{ useKey: true }"
:span-method="mergeRowMethod"
:columns="tableColumn"
:data="tableData"
:loading="loadingShow"
show-overflow
@cell-dblclick="cellDBLClickEvent"
>
<template #assetInfo_default="{ row }">
<div class="title">
<svg-icon
icon-class="warning_lights"
style="fill: currentColor; width: 15px; height: 15px; color: green"
v-if="row.assetInfo.assetStatus === '0'"
/>
<svg-icon
icon-class="warning_lights"
style="fill: currentColor; width: 15px; height: 15px; color: red"
v-if="row.assetInfo.assetStatus === '2'"
/>
<span class="name" @click.native="nameClick(row.assetInfo)">{{
row.gTitle
}}</span>
</div>
</template>
<template #pager>
<!--使用 pager 插槽-->
<vxe-pager
class="tablePage"
:layouts="[
'Sizes',
'PrevJump',
'PrevPage',
'Number',
'NextPage',
'NextJump',
'FullJump',
'Total',
]"
v-model:current-page="tablePage.currentPage"
v-model:page-size="tablePage.pageSize"
auto-hidden
:total="tablePage.total"
@page-change="handlePageChange"
>
</vxe-pager>
</template>
</vxe-grid>
<!-- <vxe-grid class="tableGrid" v-bind="gridOptions"> </vxe-grid> -->
<!-- </n-spin> -->
</div>
<vxe-modal :title="modalTitle" v-model="editModal">
<template #default>
<vxe-form
title-colon
ref="formRef"
title-align="right"
title-width="100"
:data="formData"
:loading="formLoading"
@submit="submitEvent"
@reset="resetEvent"
>
<vxe-form-item field="value" span="24" :item-render="{}" title-overflow>
<template #default="params">
<vxe-switch
v-model="params.data.value"
size="small"
open-label="启"
close-label="停"
v-if="params.data.valueType === 'bool'"
></vxe-switch>
<vxe-input
v-model="params.data.value"
placeholder="请输入数值"
type="number"
clearable
v-if="params.data.valueType != 'bool'"
></vxe-input>
<!-- <vxe-input
v-model="params.data.value"
placeholder="请输入数值"
clearable
v-if="params.data.valueType != 'bool'"
></vxe-input> -->
</template>
</vxe-form-item>
<vxe-form-item align="center" span="24">
<template #default>
<vxe-button
type="submit"
status="primary"
content="确认"
></vxe-button>
<vxe-button type="reset" content="重置"></vxe-button>
</template>
</vxe-form-item>
</vxe-form>
</template>
</vxe-modal>
</template>
<script lang="ts" setup>
import router from "@/router";
import {
VxeGridProps,
VxeGridInstance,
VxeTableEvents,
VxeColumnPropTypes,
VXETable,
VxeFormInstance,
VxeFormPropTypes,
VxeFormEvents,
VxeTablePropTypes,
VxePagerEvents,
} from "vxe-table";
import {
getTableHeader,
getStationInfo,
getTableData,
editConfig,
sendCtrl,
} from "@/api/monitoring/table";
import { TableVo } from "@/api/monitoring/table/types";
import useTableStore from "@/store/modules/table";
import mitt from "@/plugins/bus";
import socket from "@/utils/socket";
import useStorage from "@/utils/useStorage";
import useUserStore from "@/store/modules/user";
// import { useDateFormat } from '@vueuse/core';
const sessionStorageIns = useStorage("sessionStorage");
const userStore = useUserStore();
const requiredPerms = ["model:device:contrl"]; //
const controlPerm = userStore.perms?.some((perm) => {
return requiredPerms.includes(perm);
});
const tableStoreCounter = useTableStore();
// import type { MenuOption } from 'naive-ui'
// import { useMessage } from 'naive-ui'
// const message = useMessage()
// const mainHeight = ref('calc(100vh - 161px)');
const loadingShow = ref(false);
const editModal = ref(false);
const modalTitle = ref("");
const menuKey = ref(0);
const tableColumn = ref([]);
const tableData = ref<TableVo[]>([]);
const tableRef = ref<VxeGridInstance<TableVo>>();
const cellRow = ref({});
const cellColumn = ref();
const cellField = ref();
const tableBorder = ref(true);
const tablePage = reactive({
total: 0,
currentPage: 1,
pageSize: 10,
});
// const fields = ref(['deviceuuid']) //
// const waringArrow = ref([])
interface FormDataVO {
centeruuid: string;
paramcode: string;
url: string;
valueType: string;
value: string | boolean;
}
const formRef = ref<VxeFormInstance>();
const formLoading = ref(false);
const formData = ref<FormDataVO>({
centeruuid: "",
paramcode: "",
url: "",
valueType: "",
value: "",
});
// const formRules = ref<VxeFormPropTypes.Rules>({
// value: [
// { required: true, message: '' },
// { min: 1, max: 100, message: ' 1 100 ' },
// {
// validator({ itemValue }) {
// //
// const reg = /^-?\d+\.?\d{0,2}$/;
// if (!reg.test(itemValue)) {
// return new Error('');
// }
// }
// }
// ]
// });
const userStorageInfo = sessionStorage.getItem("userInfo");
const userInfo = JSON.parse(userStorageInfo === null ? "" : userStorageInfo);
//const apiUrl = import.meta.env.VITE_APP_WS_API
//const wsUrl = `${apiUrl}websocket/${userInfo.userName}`; //websocket
//const wsUrl = `${apiUrl}${userInfo.userName}`; //websocket
// const loginIp = userInfo.loginIp.split('.').join('');
// const baseApi = "http://172.1.2.106:9000"//websocket
// 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 emit = defineEmits(["tableHeaderData"]);
// const listData = ref([
// {
// name: 'area_default',
// value: 1,
// },
// ]);
defineProps({
tapsShow: {
type: Boolean,
default: true,
},
sidebarHeight: {
type: Number,
default: 0,
},
});
// watch(
// () => tableStoreCounter.tableDataStore,
// (newValue, oldValue) => {
// console.log('', newValue, oldValue);
// const $table = tableRef.value;
// $table.loadData(newValue);
// }
// );
// watchEffect(() => {
// const titleRef = props.tapsShow;
// console.log(tableStoreCounter.tableDataStore);
// tableData.value = tableStoreCounter.tableDataStore;
// $table.loadData(tableStoreCounter.tableDataStore);
// });
interface HeaderVo {
code: string;
name: string;
value: string;
}
const headerData = ref<HeaderVo[]>();
onMounted(() => {
// stationInfo();
// tableHeader();
// console.log(':', useDateFormat(new Date(), 'YYYY-MM-DD HH:mm:ss').value);
// console.log('aaaa', sessionStorage.getItem('currentPage'));
tablePage.currentPage =
sessionStorage.getItem("currentPage") === null
? 1
: Number(sessionStorage.getItem("currentPage"));
console.log(Number(sessionStorage.getItem("currentPage")));
tablePage.pageSize =
sessionStorage.getItem("pageSize") === null
? 10
: Number(sessionStorage.getItem("pageSize"));
// socket.initialize(wsUrl); //websocket http://
});
mitt.on("currentPageEmit", (res: any) => {
//
tablePage.currentPage = res;
});
mitt.on("menuKey", (res: any) => {
//
menuKey.value = res;
tableHeader();
tableDatas();
});
mitt.on("treeData", (res: any) => {
//header
tableColumn.value = [];
nextTick(() => {
tableColumn.value = res;
});
const params = res;
editConfig(params).then((res: any) => {
if (res.code === 200) {
mitt.emit("treeClose", true);
}
});
// tableColumn.value=res
// gridOptions.columns?.push(...res);
// console.log('', gridOptions.columns);
});
mitt.on("tableMessage", (res: any) => {
//
console.log("tableMessage--", res.data);
const $table = tableRef.value;
const tableArray = tableData.value;
if ($table) {
console.log("tableRef--", tableRef.value);
res.data.map((item: any) => {
const index = tableArray.findIndex(
(obj) =>
obj.assetInfo.id === item.assetInfo.id && obj.areaid === item.areaid
);
if (index !== -1) {
tableArray.splice(index, 1, item);
}
});
// console.log('tableData--', tableArray);
$table.loadData(tableArray);
// if (res.code === 'datareal') {
// const index = tableData.value.findIndex((obj) => obj.id === res.data.id);
// if (index !== -1) {
// tableData.value.splice(index, 1, res.data);
// }
// res.data.map((item: any) => {
// console.log(item)
// const index = tableData.value.findIndex((obj) => obj.id === item.id);
// if (index !== -1) {
// tableData.value.splice(index, 1, res.data);
// }
// })
// $table.loadData(mergedArray);
}
// } else if (res.code === 'alertDev') {
// waringArrow.value.push(res.data)
// waringArrow.value = uniqueArrayObject(waringArrow.value, "devUuid")
// }
// console.log("waringArrow:", waringArrow.value)
});
const handlePageChange: VxePagerEvents.PageChange = ({
currentPage,
pageSize,
}) => {
tablePage.currentPage = currentPage;
tablePage.pageSize = pageSize;
sessionStorageIns.setUseStorage("currentPage", currentPage);
sessionStorageIns.setUseStorage("pageSize", pageSize);
tableDatas();
};
function stationInfo() {
//
getStationInfo().then((res: any) => {
if (res.code === 200) {
headerData.value = res.data;
}
});
}
function tableHeader() {
//header
getTableHeader().then((res: any) => {
console.log(res);
//
const tableCessText = [
{
id: 0,
title: "ID",
field: "id",
type: "html",
formatter: formatRole,
visible: false,
},
];
console.log(tableCessText);
res.data.map((item: any) => {
if (item.formatter != undefined || item.children != undefined) {
item.formatter = eval(item.formatter);
if (item.children && item.children.length) {
item.children.map((res: any) => {
res.formatter = eval(res.formatter);
});
}
}
});
nextTick(() => {
tableColumn.value = res.data;
});
// tableColumn.value = res.data;
// const arr = [
// {
// id: 1,
// title: '',
// field: 'deviceuuid',
// colSort: 2,
// colType: '2',
// width: 150,
// show: true,
// disabled: true,
// fixed: 'left',
// type: 'html',
// formatter: "formatRole",
// },
// ];
// arr.map((item)=>{
// item.formatter=eval(item.formatter);
// })
// console.log(arr)
// tableColumn.value = arr;
// gridOptions.columns = res.data;
// console.log('', gridOptions.value.columns);
emit("tableHeaderData", res.data);
// mitt.emit('tableHeaderData', res.data);
// tableDatas();
});
}
function tableDatas() {
//
// const params = menuKey.value;
// console.log(':', useDateFormat(new Date(), 'YYYY-MM-DD HH:mm:ss').value);
const params = {
pageNum: tablePage.currentPage,
pageSize: tablePage.pageSize,
orgCode: menuKey.value,
};
loadingShow.value = true;
getTableData(params).then((res: any) => {
if (res.code === 200) {
// tableData.value=oldData
tableData.value = res.rows;
tableStoreCounter.tableDataAction(res.rows);
tablePage.total = res.total;
// gridOptions.data = res.data;
loadingShow.value = false;
// console.log(':', useDateFormat(new Date(), 'YYYY-MM-DD HH:mm:ss').value);
}
});
}
const cellDBLClickEvent: VxeTableEvents.CellDblclick<TableVo> = ({
row,
column,
}) => {
//
//edit ty zhousq 2023-10-12 formdata
// ctrlPro.centeruuid UUID cellField.ctrlPro.paramcode cellField.val
//ctrlPro
console.log("cellData--", row, column);
const cellField = row[column.field];
//const data = row.data;
cellRow.value = row;
cellColumn.value = column;
cellField.value = cellField;
debugger;
if (cellField.canBeControl === "1" && controlPerm) {
modalTitle.value = column.title;
///formData.value.url = data.url;
//formData.value.deviceName = cellField.deviceName;
formData.value = cellField.ctrlPro;
formData.value.value = cellField.val;
// formData.value.paramCode = cellField.ctrlPro.paramcode;
editModal.value = true;
}
console.log(row[column.field]);
};
const formatRole: VxeColumnPropTypes.Formatter<HeaderVo> = ({ cellValue }) => {
// console.log(':', useDateFormat(new Date(), 'YYYY-MM-DD HH:mm:ss').value);
//object
// console.log(cellValue);
// const iconFont=cellValue.changeProp===-1?'<i class="iconfont icon-decline" />':(cellValue.changeProp===1?'<i class="iconfont icon-rise" />':'<i/>')
// const cellData = `<span class="cellClass ${cellValue.alertProp===1?'warning':''}">${cellValue.val}</span>${iconFont}`;
// const cellData = `<span class="cellClass ${cellValue.alertProp === 1 ? 'warning' : cellValue.canBeControl === '1' ? 'cellEdit' : ''}">${cellValue.val}</span><i class="iconfont ${cellValue.changeProp === -1 ? 'icon-decline' : cellValue.changeProp === 1 ? 'icon-rise' : ''}" ></i>${cellValue.canBeControl === '1' ? '<i class="iconfont icon-edit-icon"></i>' : ''}`;
// const cellData = `
// <span class="cellClass ${cellValue.alertProp === 1 ? 'warning' : cellValue.canBeControl === '1' ? 'cellEdit' : ''}">
// ${cellValue.ctrlPro.valueType != 'bool' ? cellValue.val : cellValue.val === 'true' ? '' : ''}
// </span>
// <i class="iconfont ${
// cellValue.changeProp === -1 ? 'icon-decline' : cellValue.changeProp === 1 ? 'icon-rise' : ''
// }" ></i>
// ${cellValue.canBeControl === '1' && controlPerm ? '<i class="iconfont icon-edit-icon"></i>' : ''}`;
const cellData = `
<span class="cellClass ${
cellValue.alertProp === 1
? "warning"
: cellValue.canBeControl === "1"
? "cellEdit"
: ""
}">
${
cellValue.ctrlPro.valueType != "bool"
? cellValue.val
: cellValue.val === "true"
? "启"
: "停"
}
</span>
${
cellValue.canBeControl === "1" && controlPerm
? '<i class="iconfont icon-edit-icon"></i>'
: ""
}`;
// console.log(':', useDateFormat(new Date(), 'YYYY-MM-DD HH:mm:ss').value);
return cellData;
};
//
const mergeRowMethod: VxeTablePropTypes.SpanMethod<TableVo> = ({
row,
_rowIndex,
column,
visibleData,
}) => {
// console.log(':', useDateFormat(new Date(), 'YYYY-MM-DD HH:mm:ss').value);
const fields = ["gTitle"];
const cellValue = row[column.field];
if (cellValue && fields.includes(column.field)) {
const prevRow = visibleData[_rowIndex - 1];
let nextRow = visibleData[_rowIndex + 1];
if (prevRow && prevRow[column.field] === cellValue) {
return { rowspan: 0, colspan: 0 };
} else {
let countRowspan = 1;
while (nextRow && nextRow[column.field] === cellValue) {
nextRow = visibleData[++countRowspan + _rowIndex];
}
if (countRowspan > 1) {
return { rowspan: countRowspan, colspan: 1 };
}
}
}
// console.log(':', useDateFormat(new Date(), 'YYYY-MM-DD HH:mm:ss').value);
};
const submitEvent: VxeFormEvents.Submit = () => {
//websocket
formLoading.value = true;
const $table = tableRef.value;
const submitData = formData.value;
console.log(submitData);
//Add by zhousq 2023-10-12 post
sendCtrl(submitData).then((res: any) => {
if (res.code === 200) {
ElNotification({ message: res.data.msg });
}
});
//socket.onSend(submitData);
formLoading.value = false;
editModal.value = false;
if ($table) {
const row = cellRow.value;
const field = cellColumn.value.field;
row[field].val = formData.value.value;
$table.reloadRow(row, null, field);
}
// VXETable.modal.message({ content: '', status: 'success' });
};
function nameClick(row: any) {
//
console.log(row);
sessionStorageIns.setUseStorage("id", row.id);
router.push({ path: "/monitoring/equipment", query: { id: row.id } });
}
const resetEvent: VxeFormEvents.Reset = () => {
console.log({ content: "重置", status: "info" });
};
</script>
<style lang="scss" scoped>
@import "../index.scss";
</style>

320
src/views/monitoring/data-monitor/components/showTree.vue

@ -0,0 +1,320 @@
<template>
<div class="treeCard">
<el-tree
ref="tree"
class="showTree"
:data="treeData"
node-key="id"
show-checkbox
draggable
:props="defaultProps"
:default-checked-keys="defaultCheckedKeys"
:allow-drop="allowDrop"
@node-drop="nodeDrop"
@check-change="treeCheckChange"
>
<template #default="{ node, data }">
<span class="custom-tree-node">
<span>{{ data.field === "deviceStatus" ? "状态" : data.title }}</span>
</span>
<div class="weight" v-if="!data.children">
<span>宽度(px):</span>
<el-input
v-model="data.width"
size="small"
:disabled="data.disabled"
placeholder="请输入宽度"
/>
</div>
</template>
</el-tree>
<div class="treeBtn">
<el-button @click="cancelClick">取消</el-button>
<el-button type="primary" :loading="treeLoading" @click="confirmClick">{{
treeLoading ? "确认中" : "确认"
}}</el-button>
</div>
</div>
</template>
<script lang="ts" setup>
import { getCurrentInstance, ComponentInternalInstance } from "vue";
import mitt from "@/plugins/bus";
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const defaultCheckedKeys = ref([]); //
const checkList = ref<TreeVo[]>([]); //
interface TreeVo {
id?: number;
colSort: number;
colType: string;
field: string;
fixed?: string;
visible: boolean;
title: string;
width: number;
controlValue?: number;
children?: TreeVo[];
}
const treeLoading = ref(false);
const treeData = ref<TreeVo[]>();
const emit = defineEmits(["cancelClick", "confirmClick"]);
const props: any = defineProps({
headerData: {
type: Array,
default: [],
},
});
onMounted(() => {
treeData.value = props.headerData;
const checkData: any = [];
props.headerData.map((item: TreeVo) => {
if (item.visible) {
checkData.push(item.id);
checkList.value.push(item);
if (item.children && item.children.length) {
item.children.map((res: TreeVo) => {
checkData.push(res.id);
checkList.value.push(item);
});
}
}
});
defaultCheckedKeys.value = checkData;
});
// mitt.on('tableHeaderData', (res:any) => {
// //header
// treeData.value=res
// console.log(res)
// });
mitt.on("treeClose", (res: any) => {
//
emit("cancelClick", "");
treeLoading.value = false;
});
const defaultProps = {
children: "children",
label: "title",
};
// const treeData: TreeVo[] = [
// {
// title: '',
// id: '1',
// field: 'name',
// width: 150,
// show: true,
// disabled: true,
// slots: { default: 'name_default' },
// },
// {
// title: '',
// id: '2',
// field: 'area',
// width: 150,
// show: true,
// },
// {
// title: '',
// id: '3',
// show: true,
// children: [
// {
// title: '',
// id: '4',
// field: 'oneSupplyPressure',
// width: 150,
// show: true,
// slots: { default: 'oneSupplyPressure_default' },
// },
// {
// title: '',
// id: '5',
// field: 'oneBackPressure',
// width: 150,
// show: true,
// },
// {
// title: '',
// id: '6',
// field: 'oneSupplyTemperature',
// width: 150,
// show: true,
// },
// {
// title: '',
// id: '7',
// field: 'oneBackTemperature',
// width: 150,
// show: true,
// },
// ],
// },
// {
// title: '',
// id: '8',
// show: true,
// children: [
// {
// title: '',
// id: '9',
// field: 'twoSupplyPressure',
// width: 150,
// show: true,
// },
// {
// title: '',
// id: '10',
// field: 'twoBackPressure',
// width: 150,
// show: true,
// },
// {
// title: '',
// id: '11',
// field: 'twoSupplyTemperature',
// width: 150,
// show: true,
// },
// {
// title: '',
// id: '12',
// field: 'twoBackTemperature',
// width: 150,
// show: true,
// },
// {
// title: '',
// id: '13',
// field: 'averageTemperature',
// width: 150,
// show: true,
// },
// ],
// },
// {
// title: '',
// id: '14',
// field: 'totalFlow',
// width: 150,
// show: true,
// },
// {
// title: '',
// id: '15',
// field: 'trafficFlow',
// width: 150,
// show: true,
// },
// {
// title: '',
// id: '16',
// field: 'instantHeat',
// width: 150,
// show: true,
// },
// {
// title: '',
// id: '17',
// field: 'AaccumulatHeat',
// width: 150,
// show: true,
// },
// {
// title: '',
// id: '18',
// field: 'valve',
// width: 150,
// show: true,
// },
// {
// title: '',
// id: '19',
// field: 'waterLevel',
// width: 150,
// show: true,
// },
// {
// title: '',
// id: '20',
// field: 'cycleFrequency',
// width: 150,
// show: true,
// },
// {
// title: '',
// id: '21',
// field: 'waterFrequency',
// width: 150,
// show: true,
// editRender: {},
// slots: { edit: 'waterFrequency_edit' },
// },
// {
// title: '',
// id: '22',
// field: 'waterPolice',
// width: 150,
// show: true,
// },
// {
// title: '',
// id: '23',
// field: 'oneSupplementTwo',
// width: 150,
// show: true,
// },
// {
// title: '',
// id: '24',
// field: 'soundTurnedOn',
// width: 150,
// show: true,
// slots: { default: 'soundTurnedOn_default' },
// },
// ];
function allowDrop(draggingNode: any, dropNode: any, type: any) {
//
if (type !== "inner") {
let control = draggingNode.level === dropNode.level ? true : false;
return control;
}
}
const treeCheckChange = (
data: TreeVo,
checked: boolean,
indeterminate: boolean
) => {
//
console.log(data, checked, indeterminate);
data.visible = checked;
console.log(treeData.value);
};
const nodeDrop = () => {
//
nextTick(() => {
proxy?.$refs.tree.setCheckedKeys(defaultCheckedKeys.value);
});
};
function cancelClick() {
//
emit("cancelClick", "");
}
function confirmClick() {
//
treeLoading.value = true;
mitt.emit("treeData", treeData.value);
}
</script>
<style lang="scss" scoped>
@import "../index.scss";
</style>

752
src/views/monitoring/data-monitor/index.scss

@ -0,0 +1,752 @@
@import url('@/assets/fonts/font.css');
.screen {
position: relative;
width: 100%;
height: 100vh;
background-color: #dedede;
// background: url(@/assets/images/screen.png) no-repeat;
// background-color: var(--tableBg);
// background-size: 100% 100%;
// background-color: rgba(29,30,31,0.8);
// background-blend-mode: multiply;
padding: 0 25px;
overflow: hidden;
.menuShow {
width: 26px;
height: 26px;
position: absolute;
top: 118px;
left: 0;
color: #1169c0;
text-align: center;
// border: 1px solid #0d55b0;
// background-color: #02072e;
border-right: none;
cursor: pointer;
.iconfont {
display: inline-block;
}
.left {
transform: rotate(0deg);
-webkit-transform: rotate(0deg);
transition: transform 0.5s;
}
.right {
transform: rotate(180deg);
-webkit-transform: rotate(180deg);
transition: transform 0.5s;
}
}
.panelBtn {
position: absolute;
bottom: 0;
left: 0;
right: 0;
width: 70%;
height: 45px;
text-align: center;
color: #1169c0;
// background: url(@/assets/images/panelBtn_bg.png) no-repeat center;
// background-size: 100% 100%;
transition: width 0.28s;
margin: 0 auto;
cursor: pointer;
.iconfont {
display: inline-block;
font-size: 18px;
}
.up {
transform: rotate(0deg);
-webkit-transform: rotate(0deg);
transition: transform 0.5s;
}
.down {
transform: rotate(180deg);
-webkit-transform: rotate(180deg);
transition: transform 0.5s;
}
.copyright {
width: 100%;
// height: 25px;
// line-height: 25px;
text-align: center;
color: #acaeb1;
font-family: Arial;
font-size: 12px;
letter-spacing: 1px;
}
}
.panelBtn.left {
left: 14%;
}
// .header {
// display: flex;
// justify-content: space-between;
// align-items: center;
// // height: 5.7rem;
// .title {
// width: 1500px;
// background: url(@/assets/images/title-bg.png);
// background-size: 100%;
// text-align: center;
// padding-bottom: 38px;
// margin: 0 auto;
// h3 {
// 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.6rem;
// 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;
// img {
// width: 25px;
// margin-left: 10px;
// }
// }
// }
// .seeting {
// position: absolute;
// top: 2.5rem;
// right: 7rem;
// .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;
// }
// }
.layout {
display: flex;
// margin-top: 20px;
.sidebar {
width: 12%;
height: calc(100vh - 70px - 45px); //屏幕高度-头部header高度-底部高度
flex-shrink: 0;
border: 1px solid #b7babf;
padding: 10px 0;
// box-shadow: inset 0px 0px 10px 0px rgb(36, 90, 12);
margin-right: 1vw;
position: relative;
overflow: auto;
transition: width 0.28s;
// background-color: rgba(2, 8, 46, 0.8);
// .menu {
// text-align: center;
// :deep(.n-submenu) {
// --n-item-color-hover: auto;
// .n-menu-item {
// .n-menu-item-content {
// padding: 0 !important;
// .n-ellipsis {
// font-family: 'AlibabaPuHuiTiBold';
// padding: 0 15px;
// }
// }
// .n-menu-item-content-header {
// font-size: 2.4rem;
// color: #B1E3FF;
// }
// }
// .n-submenu-children {
// .n-menu-item-content-header {
// font-size: 1.8rem;
// }
// .n-menu-item-content--selected {
// .n-menu-item-content-header {
// color: #fff;
// .n-ellipsis {
// position: relative;
// span {
// padding: 0 10px;
// }
// span::before {
// content: '';
// position: absolute;
// left: 0;
// top: 0.7rem;
// width: 1.8rem;
// height: 1.8rem;
// background: url(../../../assets/images/taps.png) no-repeat;
// background-size: cover;
// }
// }
// }
// }
// .n-menu-item-content--selected::before {
// background: -webkit-linear-gradient(left, #1fc7ff29 0%, #1177e700 100%);
// left: 0;
// right: 0;
// }
// .n-menu-item-content--selected::after {
// content: '';
// position: absolute;
// bottom: 0;
// width: 100%;
// height: 2px;
// background: -webkit-linear-gradient(left, #1fc7ff29 0%, #1177e700 100%);
// }
// }
// .n-base-icon {
// color: #84e0f7;
// right: 10px;
// }
// }
// }
}
.sidebar.sidebarHide {
width: 0;
border: none;
margin-right: 0;
transition: width 0.28s;
}
.sidebar::after {
content: none;
position: absolute;
bottom: 0;
width: 100%;
height: 18rem;
background: url(@/assets/images/menu_bg.png) no-repeat;
background-size: 100% 100%;
}
.main {
position: relative;
width: 87%;
// background-color: rgba(2, 8, 46, 0.8);
.headerInfo {
border: 1px solid #0d55b0;
// box-shadow: inset 0px 0px 10px 0px rgb(36, 90, 124);
margin-bottom: 10px;
.header {
display: flex;
align-items: center;
flex-wrap: wrap;
.headerItem {
width: 11.1%;
color: #fff;
text-align: center;
.name {
font-size: 12px;
line-height: 36px;
padding: 0 3rem;
color: #ffffffb3;
background-color: #123f7580;
border-top: 1px solid #265a89;
border-bottom: 1px solid #265a89;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
.value {
font-size: 18px;
color: #5beff9;
line-height: 36px;
}
}
}
}
.mainTable {
// height: calc(100vh - 8rem - 202px);
// height: calc(100% - 162px);
border: 1px solid #b7babf;
background-color: #dedede;
transition: height 0.28s;
overflow: hidden;
.tableGrid {
// --vxe-table-header-background-color: none;
// --vxe-table-body-background-color: none;
// --vxe-table-footer-background-color: none;
// --vxe-table-border-color: rgba(12, 80, 166, 0.2);
// --vxe-table-border-color: none;
--vxe-font-color: #000;
// --vxe-table-header-font-color: #ffffffb3;
// border: 1px solid #b7babf;
// box-shadow: inset 0px 0px 10px 0px rgb(36, 90, 124);
:deep(.vxe-table) {
// height: calc(100vh - 5.7rem - 60px) !important;
.vxe-table--body-wrapper {
background-color: #dedede;
// height: calc(100vh - 5.7rem - 182px) !important;
}
.headerRowClass {
.headerCellClass {
font-size: 18px;
font-weight: 800;
color: #eee;
background-color: #1169c0;
// border: 1px solid var(--vxe-font-color) !important;
border-left: none !important;
.vxe-resizable.is--line:before {
content: none;
}
}
// .headerCellClass:nth-child(1){
// border-left: none !important;
// }
.headerCellClass.col--fixed {
// background-color: #020e38;
// box-shadow: inset 0px 0px 10px 0px #245a7c;
}
}
.tableRowClass {
font-size: 18px;
font-weight: 500;
.tableCellClass {
background-color: #dedede;
border-bottom: 1px solid #b7babf !important;
border-right: 1px solid #b7babf !important;
border-right-color: #b7babf !important;
.vxe-cell {
font-family: 'AlibabaPuHuiTiRegular';
// color: #b1e3ff;
.title {
display: flex;
align-items: center;
text-align: left;
.svg-icon {
flex-shrink: 0;
}
}
}
.vxe-cell--html {
display: flex;
justify-content: center;
align-items: center;
.warning {
font-size: 18px;
font-weight: bold;
color: red;
}
.cellEdit {
cursor: pointer;
}
.iconfont {
font-size: 18px;
}
.iconfont.icon-rise {
color: green;
}
.iconfont.icon-decline {
color: red;
}
.iconfont.icon-edit-icon {
font-size: 16px;
margin-left: 5px;
cursor: pointer;
}
}
}
}
.tableRowClass.row--stripe {
background-color: rgba(0, 95, 199, 0.15);
}
.tips {
display: inline-block;
width: 10px;
height: 10px;
margin: 0 auto;
border-radius: 10px;
margin-right: 5px;
}
.tips.green {
background-color: green;
}
.tips.red {
background-color: red;
}
.name {
margin-left: 5px;
cursor: pointer;
}
.cellName {
display: flex;
justify-content: center;
align-items: center;
color: #fef961;
}
.cellInput {
input {
color: #222;
text-align: center;
}
}
.vxe-table--fixed-left-wrapper.scrolling--middle {
background: -webkit-linear-gradient(top, #02072b 0%, #02082b 100%);
box-shadow: inset 0px 0px 10px rgb(36, 90, 124) !important;
}
}
}
.tablePage {
background-color: #dedede;
// --vxe-pager-background-color: none;
padding: 0 2rem;
// color: #b1e3ff;
// :deep(.vxe-select) {
// .vxe-input--inner {
// color: #b1e3ff;
// border: 1px solid #b1e3ff;
// background-color: transparent;
// }
// .vxe-select--panel {
// color: #b1e3ff;
// .vxe-select-option--wrapper {
// border: 1px solid #b1e3ff;
// background: -webkit-linear-gradient(top, #02072b 0%, #02082b 100%);
// .vxe-select-option:not(.is--disabled).is--hover {
// background: none;
// }
// }
// }
// }
// :deep(.vxe-pager--jump) {
// .vxe-pager--goto {
// color: #b1e3ff;
// border: 1px solid #b1e3ff;
// background-color: transparent;
// }
// }
}
// /*滚动条整体部分*/
// .tableGrid ::-webkit-scrollbar {
// width: 8px;
// height: 8px;
// }
// /*滚动条的轨道*/
// .tableGrid ::-webkit-scrollbar-track {
// background-color: transparent;
// -webkit-border-radius: 8px;
// -moz-border-radius: 8px;
// border-radius: 8px;
// }
// /*滚动条里面的小方块能向上向下移动*/
// .tableGrid ::-webkit-scrollbar-thumb {
// background-color: rgb(147, 147, 153, 0.5);
// -webkit-border-radius: 8px;
// -moz-border-radius: 8px;
// border-radius: 8px;
// }
// .tableGrid ::-webkit-scrollbar-thumb:hover {
// background-color: #a8a8a8;
// }
// .tableGrid ::-webkit-scrollbar-thumb:active {
// background-color: #787878;
// }
// /*边角即两个滚动条的交汇处*/
// .tableGrid ::-webkit-scrollbar-corner {
// background-color: transparent;
// }
}
.infoPanel {
height: 280px;
margin-top: 20px;
transition: transform 0.5s;
:deep(.swiper) {
--swiper-theme-color: #ff6600;
/* 设置Swiper风格 */
--swiper-navigation-color: #00ff33;
/* 单独设置按钮颜色 */
--swiper-navigation-size: 30px;
/* 设置按钮大小 */
.item {
height: 280px;
.content {
display: flex;
align-items: center;
height: -webkit-fill-available;
border: 2px solid #b7babf;
border-radius: 5px;
color: #000;
// padding: 15px;
// background-color: rgba(2, 8, 46, 0.5);
.icon {
width: 35%;
img {
width: 100%;
}
}
.numValue {
flex: 1;
text-align: center;
color: #000;
span {
font-size: 5rem;
}
i {
font-size: 3rem;
font-style: normal;
}
p {
font-size: 2rem;
margin: 0;
color: #1782ff;
}
}
.numValueMore {
flex: 1;
margin-left: 1.5rem;
span {
font-size: 1.4rem;
line-height: 30px;
color: #000;
margin-right: 3px;
}
span:nth-child(1) {
font-size: 1.6rem;
color: #1782ff;
}
span:nth-child(2) {
font-size: 1.8rem;
margin-right: 5px;
}
}
}
}
}
}
}
/*滚动条整体部分*/
.tableGrid ::-webkit-scrollbar {
width: 8px;
height: 8px;
}
/*滚动条的轨道*/
.tableGrid ::-webkit-scrollbar-track {
background-color: transparent;
-webkit-border-radius: 8px;
-moz-border-radius: 8px;
border-radius: 8px;
}
/*滚动条里面的小方块,能向上向下移动*/
.tableGrid ::-webkit-scrollbar-thumb {
background-color: rgb(147, 147, 153, 0.5);
-webkit-border-radius: 8px;
-moz-border-radius: 8px;
border-radius: 8px;
}
.tableGrid ::-webkit-scrollbar-thumb:hover {
background-color: #a8a8a8;
}
.tableGrid ::-webkit-scrollbar-thumb:active {
background-color: #787878;
}
/*边角,即两个滚动条的交汇处*/
.tableGrid ::-webkit-scrollbar-corner {
background-color: transparent;
}
}
}
// .cardClass {
.treeCard {
.showTree {
height: 50vh;
overflow: auto;
.weight {
display: flex;
align-items: center;
margin-left: auto;
span {
margin-right: 2px;
}
}
}
.treeBtn {
margin-top: 20px;
text-align: right;
.n-button {
margin-left: 10px;
}
}
/*滚动条整体部分*/
.showTree::-webkit-scrollbar {
width: 8px;
height: 8px;
}
/*滚动条的轨道*/
.showTree::-webkit-scrollbar-track {
background-color: transparent;
-webkit-border-radius: 8px;
-moz-border-radius: 8px;
border-radius: 8px;
}
/*滚动条里面的小方块,能向上向下移动*/
.showTree::-webkit-scrollbar-thumb {
background-color: rgb(147, 147, 153, 0.5);
-webkit-border-radius: 8px;
-moz-border-radius: 8px;
border-radius: 8px;
}
.showTree::-webkit-scrollbar-thumb:hover {
background-color: #a8a8a8;
}
.showTree:-webkit-scrollbar-thumb:active {
background-color: #787878;
}
/*边角,即两个滚动条的交汇处*/
.showTree::-webkit-scrollbar-corner {
background-color: transparent;
}
}
// }
.dark {
.screen {
background-color: rgba(29, 30, 31, 0.8);
background-blend-mode: multiply;
.layout {
.sidebar {
background-color: rgba(29, 30, 31, 0.8);
}
.main {
background-color: rgba(29, 30, 31, 0.8);
.mainTable {
.tableGrid {
:deep(.vxe-table) {
.vxe-table--fixed-left-wrapper.scrolling--middle {
background: -webkit-linear-gradient(top, rgba(21, 21, 25, 1) 0%, rgba(21, 21, 25, 1) 100%);
box-shadow: inset 0px 0px 10px rgb(36, 90, 124) !important;
}
}
}
}
}
.infoPanel {
:deep(.swiper) {
.item {
.content {
background-color: rgba(29, 30, 31, 0.8);
}
}
}
}
}
}
}

224
src/views/monitoring/data-monitor/index.vue

@ -1,8 +1,224 @@
<template>
<div>
<svg-icon class="logoIcon" icon-class="qing-rijian" />
<n-button type="primary"> Primary </n-button>
<div ref="screenRef" class="screen">
<section ref="titleRef" class="header">
<Header
:titleData="titleData"
:settingShow="true"
:warningShow="true"
@showModalClick="showModalClick"
@returnClick="returnClick"
/>
<!-- <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>天气多云</span>
<img src="../../../assets/images/weather/duoyun.png" />
</div>
</div>
<div class="seeting">
<n-tooltip trigger="hover">
<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>
</div> -->
</section>
<section class="layout">
<div
ref="sidebar"
class="sidebar animate__animated animate__fadeIn"
:class="menuShow ? '' : 'sidebarHide'"
>
<Menu menuType="1" @tableMenuData="tableMenuData" />
</div>
<div class="main" :style="`width: ${mainWidth}%`">
<Main
:tapsShow="tapsShow"
:sidebarHeight="sidebarHeight"
@tableHeaderData="tableHeaderData"
/>
<InfoPanel
class="animate__animated animate__fadeInUp"
v-if="panelShow"
/>
</div>
</section>
<section>
<!-- <n-modal v-model:show="showModal"> -->
<el-dialog v-model="showModal" title="显示项" width="600">
<!-- <n-card class="cardClass" style="width: 600px" title="显示项" :bordered="false" size="huge" role="dialog"
aria-modal="true"> -->
<ShowTree :headerData="headerData" @cancelClick="cancelClick" />
<!-- <template #header-extra>
*
</template> -->
<!-- <template #footer>
<n-button>取消</n-button>
<n-button type="info"> 确定 </n-button>
</template> -->
<!-- </n-card> -->
</el-dialog>
<!-- </n-modal> -->
</section>
<div class="menuShow" @click="menuIsShow">
<i
class="iconfont icon-angle-double"
:class="menuShow ? 'left' : 'right'"
></i>
</div>
<div
class="panelBtn"
:class="menuShow ? 'left' : 'right'"
@click="panelClick"
>
<i class="iconfont icon-up" :class="!panelShow ? 'up' : 'down'"></i>
<!-- <div class="copyright">
Copyright © {{ $t("copyright.year") }} {{ $t("copyright.abbr") }}
{{ $t("copyright.document") }}
</div> -->
<!-- <n-button type="info" size="tiny" ghost @click="panelClick">按钮</n-button> -->
</div>
</div>
</template>
<script lang="ts" setup>
import { useRoute, useRouter, onBeforeRouteLeave } from "vue-router";
// import { useDateFormat, useNow } from '@vueuse/core';
// import { Filter, Maximize, Settings, Power } from '@vicons/tabler';
import Header from "../components/header.vue";
import Menu from "../components/menu.vue";
import Main from "./components/main.vue";
import InfoPanel from "./components/infoPanel.vue";
import ShowTree from "./components/showTree.vue";
import useStorage from "@/utils/useStorage";
import socket from "@/utils/socket";
const sessionStorageIns = useStorage("sessionStorage");
const route = useRoute();
const router = useRouter();
// import calendar from '@/utils/lunar';
// const currentTime = useDateFormat(useNow(), 'YYYY-MM-DD HH:mm:ss');
// const lunarDay: any = calendar.solarToLunar(
// useNow().value.getUTCFullYear(),
// useNow().value.getUTCMonth() + 1,
// useNow().value.getUTCDate()
// );
// import screenfull from 'screenfull'
const tapsShow = ref(false);
const showModal = ref(false);
const screenRef = ref<HTMLElement>();
const titleRef = ref<HTMLElement>();
const sidebar = ref<HTMLElement>();
const sidebarHeight = ref();
const headerData = ref([]);
const mainWidth = ref(87);
const titleData = ref("");
const menuShow = ref(true);
const panelShow = ref(false);
const panelHeight = ref(0);
onMounted(() => {
// titleRef.value?.clientHeight; //
const offsetHeight = sidebar.value?.offsetHeight; //
sidebarHeight.value =
offsetHeight === undefined ? 0 : offsetHeight - panelHeight.value;
// menuShow.value=localStorage.getItem('menuShow')===undefined?true:JSON.parse(localStorage.getItem('menuShow'));
// console.log("sidebar:", sidebar.value?.offsetHeight)
});
window.addEventListener("resize", () => {
//
const offsetHeight = sidebar.value?.offsetHeight; //
sidebarHeight.value =
offsetHeight === undefined ? 0 : offsetHeight - panelHeight.value;
console.log("监听sidebar:", sidebar.value?.offsetHeight);
});
// onBeforeRouteLeave((to, from) => {
// //
// console.log('onBeforeRouteLeave--', to.path, from.path);
// if (to.path != from.path) {
// console.log('');
// socket.close(false);
// }
// });
function tableMenuData(data: any) {
//
titleData.value = data[0].deptName;
}
function tableHeaderData(data: any) {
//header
headerData.value = data;
}
function filterClick() {
///
tapsShow.value = !tapsShow.value;
}
function showModalClick(val: boolean) {
///
showModal.value = val;
}
function cancelClick() {
//
showModal.value = false;
}
function returnClick(val: string) {
//
router.replace("/dashboard");
}
function menuIsShow() {
//
menuShow.value = !menuShow.value;
mainWidth.value = menuShow.value ? 87 : 100;
sessionStorageIns.setUseStorage("menuShow", menuShow.value);
}
function panelClick() {
//
panelShow.value = !panelShow.value;
panelHeight.value = panelShow.value ? 300 : 0;
const offsetHeight = sidebar.value?.offsetHeight; //
sidebarHeight.value =
offsetHeight === undefined ? 0 : offsetHeight - panelHeight.value;
sessionStorageIns.setUseStorage("panelShow", panelShow.value);
}
<script setup></script>
// function screenClick(){
// if (screenfull.isEnabled) {
// //
// screenfull.toggle(screenRef.value)
// }
// }
</script>
<style lang="scss" scoped>
@import "./index.scss";
</style>

2
src/views/monitoring/equipment/components/main.vue

@ -318,7 +318,7 @@ import mitt from "@/plugins/bus";
// const active = ref(true)
const deviceMenuKey = ref();
const infoData = ref();
const zoneType = ref(); //1:,2:2,3:3:,4:
const zoneType = ref(); //1:,2:2,3:3,4:
const deviceImg = ref();
const timer = ref();
const isCurrentRoute = ref(true);

16
vite.config.js

@ -24,9 +24,6 @@ export default defineConfig(({ mode, command }) => {
// https://cn.vitejs.dev/config/#resolve-extensions
extensions: [".mjs", ".js", ".ts", ".jsx", ".tsx", ".json", ".vue"],
},
optimizeDeps: {
include: ["@/components/vform/designer.umd.js"], //此处路径必须跟main.js中import路径完全一致!
},
//本地运行配置,以及反向代理配置
server: {
host: "localhost",
@ -103,5 +100,18 @@ export default defineConfig(({ mode, command }) => {
//chunk 大小警告的限制
chunkSizeWarningLimit: 500,
},
optimizeDeps: {
include: [
"vue",
"vue-router",
"pinia",
"axios",
"element-plus",
"@vueuse/core",
"echarts",
"@/components/vform/designer.umd.js",
],
},
};
});

Loading…
Cancel
Save