添加tags缓存

wp1.0
fanluyan 2 years ago
parent 0806ead733
commit d2249ca1d0

@ -1,10 +1,63 @@
<template>
<div id="app">
<router-view />
<router-view></router-view>
</div>
</template>
<style lang="less">
#app {
}
</style>
<script>
import { mapActions } from "vuex";
export default {
name: "App",
methods: {
...mapActions("cache", ["addCache", "removeCache"]),
//
collectCaches() {
//
this.$route.matched.forEach((routeMatch) => {
const instance = routeMatch.components?.default;
const componentName = instance?.name;
console.log(componentName);
if (process.env.NODE_ENV === "development") {
this.checkRouteComponentName(componentName, instance?.__file);
}
// meta.keepAlive
if (routeMatch.meta.keepAlive) {
if (!componentName) {
console.warn(`${routeMatch.path} 路由的组件名称name为空`);
return;
}
this.addCache(componentName);
} else {
this.removeCache(componentName);
}
});
},
//
checkRouteComponentName(name, file) {
if (!this.cmpNames) this.cmpNames = {};
if (this.cmpNames[name]) {
if (this.cmpNames[name] !== file) {
console.warn(
`${file}${this.cmpNames[name]} 组件名称重复: ${name}`
);
}
} else {
this.cmpNames[name] = file;
}
},
},
watch: {
"$route.path": {
immediate: true,
handler() {
this.collectCaches();
},
},
},
};
</script>
<style lang="less"></style>

@ -1,11 +1,15 @@
<template>
<div class="wrapper">
<v-head></v-head>
<layout-tabs></layout-tabs>
<div class="content-box">
<div class="content">
<transition name="move" mode="out-in">
<router-view></router-view>
</transition>
<!-- <transition name="move" mode="out-in"> -->
<keep-alive :include="caches">
<router-view v-if="isRenderTab"></router-view>
</keep-alive>
<!-- </transition> -->
</div>
</div>
</div>
@ -13,13 +17,19 @@
<script>
import vHead from "./header.vue";
import LayoutTabs from "./LayoutTabs.vue";
import { mapState } from "vuex";
export default {
data() {
return {};
},
components: {
vHead,
LayoutTabs,
},
computed: {
...mapState("cache", ["caches"]),
...mapState(["isRenderTab"]),
},
created() {},
};
@ -31,7 +41,7 @@ export default {
position: absolute;
left: 0px;
right: 0;
top: 56px;
top: 92px;
bottom: 0;
//padding-bottom: 30px;
-webkit-transition: left 0.3s ease-in-out;

@ -0,0 +1,234 @@
<template>
<div class="layout-tabs">
<el-tabs
type="border-card"
v-model="curTabKey"
closable
@tab-click="clickTab"
@tab-remove="removeTab"
>
<el-tab-pane
v-for="item in tabs"
:label="item.title"
:name="item.tabKey"
:key="item.tabKey"
>
<template slot="label"
>{{ item.title }}
<i
v-if="curTabKey === item.tabKey"
class="el-icon-refresh"
@click="refreshTab(item)"
></i
></template>
</el-tab-pane>
</el-tabs>
<div class="close-tabs" @click="closeOtherTabs"></div>
</div>
</template>
<script>
import { mapMutations, mapActions } from "vuex";
import EventBus from "@/utils/event-bus";
export default {
name: "LayoutTabs",
props: {
// tab router-view
tabRouteViewDepth: {
type: Number,
default: 2,
},
// tabkeyroutekeytab
// matchRoute.path
getTabKey: {
type: Function,
default: function (routeMatch /* , route */) {
return routeMatch.path;
},
},
// tabmeta.title
tabTitleKey: {
type: String,
default: "title",
},
},
data() {
return {
tabs: [],
curTabKey: "",
};
},
methods: {
...mapActions("cache", ["addCache", "removeCache", "removeCacheEntry"]),
...mapMutations(["setIsRenderTab"]),
// tab
changeCurTab() {
//
const { path, query, params, hash, matched } = this.$route;
// tabmetacomponentName
const routeMatch = matched[this.tabRouteViewDepth - 1];
const meta = routeMatch.meta;
const componentName = routeMatch.components?.default?.name;
// tabtabKeykeytitle-tab-
const tabKey = this.getTabKey(routeMatch, this.$route);
const title = String(meta[this.tabTitleKey] || "");
const tab = this.tabs.find((tab) => tab.tabKey === tabKey);
if (!tabKey) {
// tabKeyname
console.warn(
`LayoutTabs组件${path} 路由没有匹配的tab标签页如有需要请配置tab标签页的key值`
);
return;
}
// route.path '/detail/:id'
// props.tabRouteViewDepth === matched.length tab
if (
tab &&
tab.path !== path &&
this.tabRouteViewDepth === matched.length
) {
this.removeCacheEntry(componentName || "");
tab.title = "";
}
const newTab = {
tabKey,
title: tab?.title || title,
path,
params,
query,
hash,
componentName,
};
tab ? Object.assign(tab, newTab) : this.tabs.push(newTab);
this.curTabKey = tabKey;
},
// tab
clickTab(pane) {
if (!pane.index) return;
const tab = this.tabs[Number(pane.index)];
if (tab.path !== this.$route.path) {
this.gotoTab(tab);
}
},
// tab
async removeTab(tabKey) {
//
if (this.tabs.length === 1) return;
const index = this.tabs.findIndex((tab) => tab.tabKey === tabKey);
if (index < -1) return;
const tab = this.tabs[index];
this.tabs.splice(index, 1);
// tabtab
if (tab.tabKey === this.curTabKey) {
const lastTab = this.tabs[this.tabs.length - 1];
lastTab && this.gotoTab(lastTab);
}
this.removeCache(tab.componentName || "");
},
// tab
async gotoTab(tab) {
await this.$router.push({
path: tab.path,
query: tab.query,
hash: tab.hash,
});
},
// tab
closeOtherTabs() {
this.tabs
.filter((tab) => tab.tabKey !== this.curTabKey)
.forEach((tab) => {
this.removeCache(tab.componentName || "");
});
this.tabs = this.tabs.filter((tab) => tab.tabKey === this.curTabKey);
},
// tab
async refreshTab(tab) {
this.setIsRenderTab(false);
await this.removeCacheEntry(tab.componentName);
this.setIsRenderTab(true);
},
// tab
async closeLayoutTab(tabKey = this.curTabKey) {
const index = this.tabs.findIndex((tab) => tab.tabKey === tabKey);
if (index > -1) {
this.removeCache(this.tabs[index].componentName);
this.tabs.splice(index, 1);
}
},
// tab
setCurTabTitle(title) {
const curTab = this.tabs.find((tab) => tab.tabKey === this.curTabKey);
if (curTab) {
curTab.title = title;
}
},
},
watch: {
"$route.path": {
handler() {
this.changeCurTab();
},
immediate: true,
},
},
created() {
// tab
EventBus.$on("LayoutTabs:closeTab", (tabKey) => {
this.closeLayoutTab(tabKey);
});
EventBus.$on("LayoutTabs:setTabTitle", (title) => {
this.setCurTabTitle(title);
});
},
};
</script>
<style lang="less">
.layout-tabs {
position: relative;
height: 32px;
line-height: 32px;
display: flex;
justify-content: space-between;
align-items: center;
background-color: #f5f7fa;
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.12), 0 0 6px 0 rgba(0, 0, 0, 0.04);
//background-color: #fcc;
.close-tabs {
padding-right: 12px;
cursor: pointer;
color: #999;
height: 32px;
line-height: 32px;
font-size: 12px;
&:hover {
color: #169e8c;
}
}
.el-tabs--border-card {
height: 30px;
flex: 1;
margin-right: 12px;
border: 1px solid #dcdfe6;
box-shadow: none;
}
.el-tabs__item {
height: 30px;
line-height: 30px;
font-size: 12px;
}
.el-tabs__content {
display: none;
}
}
</style>

@ -106,10 +106,10 @@ export default {
index: "/devicePhotoSchedule",
title: "拍照时间表设置",
},
{
index: "/deviceReport",
title: "装置报表",
},
// {
// index: "/deviceReport",
// title: "",
// },
{
index: "/waterMark",
title: "水印下发",

@ -8,135 +8,116 @@ const routes = [
{
path: "/stritl",
component: () => import("../components/Home.vue"),
meta: { title: "首页" },
children: [
{
path: "/stritl",
component: () =>
import(
/* webpackChunkName: "dashboard" */ "../views/homePage/index.vue"
),
path: "",
component: () => import("../views/homePage/index.vue"),
name: "home",
meta: {
title: "首页",
icon: "el-icon-s-home",
// keepAlive: true,
},
},
{
path: "/realTimeMonitor",
component: () =>
import(
/* webpackChunkName: "home" */ "../views/realTimeMonitor/index.vue"
),
component: () => import("../views/realTimeMonitor/index.vue"),
name: "realTimeMonitor",
meta: {
title: "实时监控",
permission: true,
icon: "el-icon-camera",
keepAlive: true,
},
},
{
path: "/pictureRotation",
component: () =>
import(
/* webpackChunkName: "home" */ "../views/pictureRotation/index.vue"
),
component: () => import("../views/pictureRotation/index.vue"),
name: "pictureRotation",
meta: {
title: "图片轮巡",
permission: true,
icon: "el-icon-camera",
keepAlive: true,
},
},
{
path: "/realTimeSearch",
component: () =>
import(
/* webpackChunkName: "home" */ "../views/realTimeSearch/index.vue"
),
component: () => import("../views/realTimeSearch/index.vue"),
name: "realTimeSearch",
meta: {
title: "历史图片",
permission: true,
icon: "el-icon-camera",
keepAlive: true,
},
},
{
path: "/photoAlarm",
component: () =>
import(
/* webpackChunkName: "home" */ "../views/alarmHandling/index.vue"
),
component: () => import("../views/alarmHandling/index.vue"),
name: "alarmHandling",
meta: {
title: "告警处理",
permission: true,
icon: "el-icon-camera",
keepAlive: true,
},
},
{
path: "/userManagement",
component: () =>
import(
/* webpackChunkName: "tabs" */ "../views/system/userManagement.vue"
),
meta: { title: "用户管理", icon: "el-icon-monitor" },
component: () => import("../views/system/userManagement.vue"),
name: "userManagement",
meta: { title: "用户管理", icon: "el-icon-monitor", keepAlive: true },
},
{
path: "/globalTools",
component: () =>
import(
/* webpackChunkName: "tabs" */ "../views/system/globalTools/index.vue"
),
meta: { title: "全局设置" },
component: () => import("../views/system/globalTools/index.vue"),
name: "globalTools",
meta: { title: "全局设置", keepAlive: true },
},
{
path: "/lineInformation",
component: () =>
import(
/* webpackChunkName: "tabs" */ "../views/lineInformation/index.vue"
),
meta: { title: "线路信息管理", icon: "" },
component: () => import("../views/lineInformation/index.vue"),
name: "lineInformation",
meta: { title: "线路信息管理", icon: "", keepAlive: true },
},
{
path: "/towerInformation",
component: () =>
import(
/* webpackChunkName: "tabs" */ "../views/towerInformation/index.vue"
),
meta: { title: "杆塔信息管理", icon: "" },
component: () => import("../views/towerInformation/index.vue"),
name: "towerInformation",
meta: { title: "杆塔信息管理", icon: "", keepAlive: true },
},
{
path: "/cameraChannel",
component: () =>
import(
/* webpackChunkName: "tabs" */ "../views/cameraChannel/index.vue"
),
meta: { title: "通道管理", icon: "" },
component: () => import("../views/cameraChannel/index.vue"),
name: "cameraChannel",
meta: { title: "通道管理", icon: "", keepAlive: true },
},
{
path: "/photographicDevice",
component: () =>
import(
/* webpackChunkName: "tabs" */ "../views/photographicDevice/index.vue"
),
meta: { title: "拍照装置管理", icon: "" },
component: () => import("../views/photographicDevice/index.vue"),
name: "photographicDevice",
meta: { title: "拍照装置管理", icon: "", keepAlive: true },
},
{
path: "/devicePhotoSchedule",
component: () =>
import(
/* webpackChunkName: "tabs" */ "../views/devicePhotoSchedule/index.vue"
),
meta: { title: "拍照时间表设置", icon: "" },
component: () => import("../views/devicePhotoSchedule/index.vue"),
name: "devicePhotoSchedule",
meta: { title: "拍照时间表设置", icon: "", keepAlive: true },
},
{
path: "/waterMark",
component: () =>
import(/* webpackChunkName: "tabs" */ "../views/waterMark/index.vue"),
meta: { title: "水印下发", icon: "" },
component: () => import("../views/waterMark/index.vue"),
name: "waterMark",
meta: { title: "水印下发", icon: "", keepAlive: true },
},
{
path: "/echarts",
component: () =>
import(/* webpackChunkName: "tabs" */ "../echartsDemo.vue"),
meta: { title: "echarts图表", icon: "" },
component: () => import("../echartsDemo.vue"),
name: "echartsDemo",
meta: { title: "echarts图表", icon: "", keepAlive: true },
},
],
},

@ -0,0 +1,57 @@
import Vue from "vue";
export default {
namespaced: true,
state: {
caches: [],
},
actions: {
// 添加缓存的路由组件
addCache({ state, dispatch }, componentName) {
if (Array.isArray(componentName)) {
componentName.forEach((item) => {
dispatch("addCache", item);
});
return;
}
const { caches } = state;
if (!componentName || caches.includes(componentName)) return;
caches.push(componentName);
console.log("缓存路由组件:", componentName);
},
// 移除缓存的路由组件
removeCache({ state, dispatch }, componentName) {
if (Array.isArray(componentName)) {
componentName.forEach((item) => {
dispatch("removeCache", item);
});
return;
}
const { caches } = state;
const index = caches.indexOf(componentName);
if (index > -1) {
console.log("清除缓存的路由组件:", componentName);
return caches.splice(index, 1)[0];
}
},
// 移除缓存的路由组件的实例
async removeCacheEntry({ dispatch }, componentName) {
const cacheRemoved = await dispatch("removeCache", componentName);
if (cacheRemoved) {
await Vue.nextTick();
dispatch("addCache", componentName);
}
},
// 清除缓存的路由组件的实例
clearEntry({ state, dispatch }) {
const { caches } = state;
caches.slice().forEach((key) => {
dispatch("removeCacheEntry", key);
});
},
},
};

@ -1,6 +1,6 @@
import Vue from "vue";
import Vuex from "vuex";
import cacheModule from "./cache";
Vue.use(Vuex);
export default new Vuex.Store({
@ -16,6 +16,7 @@ export default new Vuex.Store({
protocol: "",
cmdId: "",
channelIdList: [],
isRenderTab: true,
},
getters: {
token: (state) => state.token,
@ -73,7 +74,10 @@ export default new Vuex.Store({
REMOVE_INFO(state) {
localStorage.clear();
},
setIsRenderTab(state, data) {
state.isRenderTab = data;
},
},
actions: {},
modules: {},
modules: { cache: cacheModule },
});

@ -0,0 +1,4 @@
import Vue from 'vue'
const EventBus = new Vue()
export default EventBus

@ -364,6 +364,7 @@ import {
import morePicPreveiw from "../realTimeMonitor/components/morePicPreveiw";
import moment from "moment";
export default {
name: "alarmHandling",
components: {
morePicPreveiw,
},

@ -100,6 +100,7 @@ import addChannelDialog from "./components/addChannelDialog.vue";
import { getChannelListapi, deleteChannelapi } from "@/utils/api/index";
export default {
name: "cameraChannel",
components: {
addChannelDialog,
},

@ -96,6 +96,7 @@ import adddeviceDialog from "./components/adddeviceDialog.vue";
import bdSchedule from "./components/bdSchedule.vue";
export default {
name: "devicePhotoSchedule",
components: {
adddeviceDialog,
bdSchedule,

@ -126,7 +126,7 @@ import {
getOnlineTerminalListExcel,
} from "@/utils/api/index";
export default {
name: "",
name: "home",
data() {
return {
termDataNum: "", //
@ -477,11 +477,11 @@ export default {
</script>
<style lang="less">
.stritleEchartsPage {
height: calc(100% - 32px);
padding: 16px;
height: calc(100% - 24px);
padding: 12px;
display: flex;
flex-direction: column;
justify-content: space-around;
justify-content: space-between;
.echart-top {
display: flex;
height: 48%;

@ -127,6 +127,7 @@ import { getLineListJoggle, deleteLineJoggle } from "@/utils/api/index";
import addLineDialog from "./components/addLineDialog.vue";
import addTowerDialog from "./components/addTowerDialog.vue";
export default {
name: "lineInformation",
components: {
addLineDialog,
addTowerDialog,

@ -339,6 +339,7 @@ import gpsSite from "./components/gpsSite.vue";
import addLineDialog from "./components/addLineDialog.vue";
import towerDialog from "./components/towerDialog.vue";
export default {
name: "photographicDevice",
components: {
addPhotoDialog,
pictureTags,

@ -163,6 +163,7 @@ import { getPictureList, getTerminalPhotoListJoggle } from "@/utils/api/index";
import morePicPreveiw from "../realTimeMonitor/components/morePicPreveiw";
import defaultImage from "../../assets/img/nodatapic2.jpg";
export default {
name: "pictureRotation",
components: {
morePicPreveiw,
},

@ -40,6 +40,7 @@ import morePicPreveiw from "./components/morePicPreveiw";
import { mapGetters, mapState } from "vuex";
export default {
name: "realTimeMonitor",
data() {
return {
LineFlag: false, //线

@ -206,6 +206,7 @@
import { getSearchInfo, getRealtimePhoto } from "@/utils/api/index";
import defaultImage from "../../assets/img/nodatapic2.jpg";
export default {
name: "realTimeSearch",
data() {
return {
pickerOptions: {

@ -50,9 +50,6 @@
>
</el-card>
</div>
<div class="" v-for="item in infoMl">
{{ item }}
</div>
</div>
</template>
<script>
@ -65,6 +62,7 @@ import {
} from "@/utils/api/index";
export default {
name: "globalTools",
components: {},
data() {
return {
@ -73,47 +71,11 @@ export default {
probList: [],
tdOptions: [{ id: -1, name: "全部", alias: null }], //
channel: "",
infoMl: [],
tongdao: ["1", "2", "3", "4"],
cmdidArr: [
"12M10010107139801",
"12M10010107139802",
"12M10010107139803",
"12M10010107139804",
"12M10010107139805",
"12M10010107139806",
"12M10010107139807",
"12M10010107139808",
"12M10010107139809",
],
leftWater: [
"欣影-2023-10-08",
"欣影-2023-10-08",
"欣影-2023-10-08",
"欣影-2023-10-08",
"欣影-2023-10-08",
"欣影-2023-10-08",
"欣影-2023-10-08",
"欣影-2023-10-08",
"欣影-2023-10-08",
],
rightWater: [
"安庆- 输电运检一班-220kV文邓4C70线#052大号侧",
"安庆- 输电运检一班-220kV文邓4C70线#053大号侧",
"安庆- 输电运检一班-220kV文邓4C70线#053大号侧",
"安庆- 输电运检一班-220kV文邓4C70线#053大号侧",
"安庆- 输电运检一班-220kV文邓4C70线#053大号侧",
"安庆- 输电运检一班-220kV文邓4C70线#053大号侧",
"安庆- 输电运检一班-220kV文邓4C70线#053大号侧",
"安庆- 输电运检一班-220kV文邓4C70线#053大号侧",
"安庆- 输电运检一班-220kV文邓4C70线#053大号侧",
],
};
},
created() {
this.getalarmList();
this.getmark();
this.getWater();
},
methods: {
//
@ -195,37 +157,6 @@ export default {
console.log(err);
});
},
getWater() {
for (let j = 0; j < this.tongdao.length; j++) {
for (let i = 0; i < this.cmdidArr.length; i++) {
// console.log(this.cmdidArr[i]);
// console.log(this.leftWater[i]);
// console.log(this.rightWater[i]);
var a =
"/usr/local/bin/xympadmn --server=127.0.0.1 --port=6891 --act=osd --cmdid=" +
this.cmdidArr[i] +
" --flag=1 --channel=" +
this.tongdao[j] +
' --leftBottom="' +
this.leftWater[i] +
'" --rightBottom="' +
this.rightWater[i] +
'" --clientid=5 --reqid=TS; sleep 0.5';
this.infoMl.push(a);
console.log(
"/usr/local/bin/xympadmn --server=127.0.0.1 --port=6891 --act=osd --cmdid=" +
this.cmdidArr[i] +
" --flag=1 --channel=" +
this.tongdao[j] +
'" --leftBottom="' +
this.leftWater[i] +
'" --rightBottom="' +
this.rightWater[i] +
'" --clientid=5 --reqid=TS; sleep 0.5'
);
}
}
},
},
};
</script>

@ -81,6 +81,7 @@ import addUser from "./components/addUser.vue";
import { getUserList, delUserApi } from "@/utils/api/index";
export default {
name: "userManagement",
components: {
addUser,
},

@ -163,6 +163,7 @@ import { getTowerListApi, delTowerApi, getSearchInfo } from "@/utils/api/index";
import addDialog from "./components/addDialog.vue";
export default {
name: "towerInformation",
components: {
addDialog,
},

@ -63,7 +63,7 @@
</template>
<script>
export default {
components: {},
name: "waterMark",
data() {
return {
channelList: [

Loading…
Cancel
Save