java后端

jcbranch
fanluyan 1 year ago
parent 1adb9fda30
commit 77b0afd0ee

28
.gitignore vendored

@ -1,11 +1,23 @@
# ---> Vue
# gitignore template for Vue.js projects
#
# Recommended template: Node.gitignore
.DS_Store
node_modules
/dist
# TODO: where does this rule come from?
docs/_book
# TODO: where does this rule come from?
test/
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

@ -1,3 +1,27 @@
# ops-fronted-java
# ops-fronted
java后端的运维
运维
## Project setup
```
npm install
```
### Compiles and hot-reloads for development
```
npm run serve
```
### Compiles and minifies for production
```
npm run build
```
### Lints and fixes files
```
npm run lint
```

@ -0,0 +1,6 @@
// module.exports = {
// presets: ["@vue/cli-plugin-babel/preset"],
// };
module.exports = {
plugins: ["@babel/plugin-transform-optional-chaining"],
};

@ -0,0 +1,19 @@
{
"compilerOptions": {
"target": "es5",
"module": "esnext",
"baseUrl": "./",
"moduleResolution": "node",
"paths": {
"@/*": [
"src/*"
]
},
"lib": [
"esnext",
"dom",
"dom.iterable",
"scripthost"
]
}
}

9310
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -0,0 +1,61 @@
{
"name": "operation",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"axios": "^1.6.2",
"core-js": "^3.8.3",
"echarts": "^5.4.3",
"element-ui": "^2.15.14",
"file-saver": "^2.0.5",
"moment": "^2.29.4",
"postcss-px2rem": "^0.3.0",
"px2rem-loader": "^0.1.9",
"three": "^0.158.0",
"umy-ui": "^1.1.6",
"vue": "^2.6.14",
"vue-router": "^3.5.1",
"vuex": "^3.6.2",
"xlsx": "^0.17.5"
},
"devDependencies": {
"@babel/core": "^7.12.16",
"@babel/eslint-parser": "^7.12.16",
"@babel/plugin-transform-optional-chaining": "^7.24.1",
"@vue/cli-plugin-babel": "~5.0.0",
"@vue/cli-plugin-eslint": "~5.0.0",
"@vue/cli-plugin-router": "~5.0.0",
"@vue/cli-plugin-vuex": "~5.0.0",
"@vue/cli-service": "~5.0.0",
"eslint": "^7.32.0",
"eslint-plugin-vue": "^8.0.3",
"less": "^4.0.0",
"less-loader": "^7.0.1",
"postcss-loader": "^4.3.0",
"vue-template-compiler": "^2.6.14"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"parserOptions": {
"parser": "@babel/eslint-parser"
},
"rules": {}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<link rel="icon" href="<%= BASE_URL %>favicon.ico" />
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
<strong
>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work
properly without JavaScript enabled. Please enable it to
continue.</strong
>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

@ -0,0 +1,112 @@
<template>
<div id="app">
<router-view></router-view>
</div>
</template>
<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">
* {
margin: 0;
padding: 0;
}
html,
body {
width: 100%;
height: 100%;
overflow: hidden;
color: #fff;
}
a {
text-decoration: none;
color: #fff;
}
#app {
width: 100%;
height: 100%;
}
body {
font-family: "PingFang SC", "Helvetica Neue", Helvetica, "microsoft yahei",
arial, STHeiTi, sans-serif;
}
// /* */
// ::-webkit-scrollbar {
// width: 8px;
// height: 8px;
// }
// /* */
// ::-webkit-scrollbar-thumb {
// background-color: #ccc;
// /* */
// border-radius: 32px;
// }
// /* */
// ::-webkit-scrollbar-track {
// background-color: #f0f0f0;
// border-radius: 32px;
// }
.el-dialog__headerbtn {
top: 18px;
.el-dialog__close {
font-size: 26px;
&:hover {
background: #e2e2e2;
}
}
}
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

@ -0,0 +1,60 @@
<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"> -->
<keep-alive :include="caches">
<router-view v-if="isRenderTab"></router-view>
</keep-alive>
<!-- </transition> -->
</div>
</div>
</div>
</template>
<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() {},
};
</script>
<style lang="less">
.wrapper {
min-width: 1366px;
color: #333;
.content-box {
position: absolute;
left: 0px;
right: 0;
top: 92px;
bottom: 0;
//padding-bottom: 30px;
-webkit-transition: left 0.3s ease-in-out;
transition: left 0.3s ease-in-out;
// background: @background-color-base;
.content {
width: 100%;
height: 100%;
//padding: 10px;
overflow-y: auto;
box-sizing: border-box;
}
}
}
</style>

@ -0,0 +1,251 @@
<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-icon-refresh {
margin: 0px 8px 0px 4px;
}
.el-tabs--border-card > .el-tabs__header .el-tabs__item.is-active {
color: #fff;
background-color: #169e8c;
}
.el-tabs--border-card
> .el-tabs__header
.el-tabs__item:not(.is-disabled):hover {
color: #fff;
background-color: #169e8c;
}
.el-tabs__item .el-icon-close {
transition: none;
}
.el-tabs__item {
height: 30px;
line-height: 30px;
font-size: 12px;
padding: 0 10px !important;
}
.el-tabs__content {
display: none;
}
}
</style>

@ -0,0 +1,94 @@
<template>
<div class="sidebarBox">
<ul class="menuBoxUl">
<li class="menuItem" v-for="(item, index) in routeItem" :key="index">
<router-link :to="item.path"> {{ item.name }} </router-link>
</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
routeItem: [
{
path: "/home",
name: "首页",
},
{
path: "/report",
name: "状态报表",
},
{
path: "/log",
name: "日志列表",
},
{
path: "/upgradation",
name: "上传Apk",
},
{
path: "/upgradationOta",
name: "上传Ota",
},
{
path: "/activity",
name: "活动列表",
},
// {
// path: "/userlist",
// name: "",
// },
],
};
},
watch: {},
methods: {},
created() {},
};
</script>
<style lang="less">
.sidebarBox {
// width: 55%;
// margin: 0 auto;
display: flex;
align-items: center;
.menuBoxUl {
flex: 1;
display: flex;
align-items: center;
justify-content: space-around;
.menuItem {
list-style: none;
display: flex;
height: 40px;
justify-content: center;
align-items: center;
cursor: pointer;
font-size: 14px;
margin-right: 32px;
a {
color: #fff;
//background: #e8f5f4;
height: 40px;
line-height: 40px;
padding: 0 12px;
background-size: 100% 100%;
background-repeat: no-repeat;
overflow: hidden;
border-radius: 8px;
&:hover {
background: #128071;
}
}
.router-link-active {
background: #128071;
}
}
}
}
</style>

@ -0,0 +1,153 @@
<template>
<div class="header">
<div class="leftLogo">
<!-- <img src="../assets/stateGridCorporation.png" /> -->
<img src="../assets/logo.png" />
<p>运维管理系统</p>
</div>
<div class="menuBox">
<vSidebar></vSidebar>
</div>
<div class="userInfo">
<div class="header-user-con">
<!-- 用户头像 -->
<div class="user-avator">
<!-- <img src="../assets/user.jpeg" /> -->
<!-- 显示当前时间 -->
<span>{{ $moment(currentTime).format("YYYY-MM-DD HH:mm:ss") }}</span>
</div>
<!-- 用户名下拉菜单 -->
<el-dropdown class="user-name" trigger="click" @command="handleCommand">
<span class="el-dropdown-link">
<!-- {{ userName }} -->
系统
<i class="el-icon-caret-bottom"></i>
</span>
<el-dropdown-menu slot="dropdown">
<!-- <el-dropdown-item command="changePwd"> 修改密码</el-dropdown-item> -->
<el-dropdown-item command="loginout">退出登录</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
</div>
</div>
</template>
<script>
import vSidebar from "./Sidebar.vue";
// import passwordDialog from "../components/passwordDialog.vue";
export default {
components: {
vSidebar,
// passwordDialog,
},
data() {
return {
currentTime: null,
userName: localStorage.getItem("userName"),
role: localStorage.getItem("role"),
};
},
methods: {
//
handleCommand(command) {
switch (command) {
case "noticeShow": //
console.log(command);
break;
case "changePwd": //
this.$refs.passwordref.display();
break;
case "loginout": //退
this.$message({
duration: 1500,
showClose: true,
message: "退出成功",
type: "success",
});
this.$store.commit("REMOVE_INFO");
this.$router.push("/login");
break;
}
},
},
created() {},
mounted() {
this.currentTime = new Date();
setInterval(() => {
this.currentTime = new Date();
}, 1000);
},
};
</script>
<style lang="less">
.header {
width: 100%;
height: 52px;
box-sizing: border-box;
background: #169e8c;
-webkit-backdrop-filter: blur(0.41667vw);
backdrop-filter: blur(0.41667vw);
line-height: 52px;
padding: 0px 16px;
display: flex;
.leftLogo {
display: flex;
align-items: center;
justify-content: center;
img {
margin-right: 16px;
}
p {
font-size: 16px;
color: #fff;
height: 40px;
line-height: 40px;
overflow: hidden;
}
}
.menuBox {
flex: 1;
display: flex;
justify-content: space-between;
margin: 0px 32px;
}
.userInfo {
.header-user-con {
display: flex;
height: 52px;
align-items: center;
.user-avator {
margin-left: 16px;
height: 40px;
line-height: 40px;
overflow: hidden;
// img {
// display: block;
// width: 40px;
// height: 40px;
// border-radius: 50%;
// }
span {
color: #fff;
font-size: 14px;
margin-right: 8px;
}
}
.user-name {
margin-left: 8px;
height: 40px;
line-height: 40px;
overflow: hidden;
.el-dropdown-link {
color: #fff;
cursor: pointer;
}
}
.el-select {
width: 90px;
}
}
}
}
</style>

@ -0,0 +1,53 @@
import Vue from "vue";
import App from "./App.vue";
import router from "./router";
import store from "./store";
import ElementUI from "element-ui";
import "umy-ui/lib/theme-chalk/index.css"; // 引入样式
// import "element-ui/lib/theme-chalk/index.css";
import "../src/assets/css/theme/index.css"; //cac主题
Vue.use(ElementUI, {
size: "small",
});
//引入Echarts;
import * as echarts from "echarts";
Vue.prototype.$echarts = echarts;
//字体自适应
import "./utils/rem";
//引入日期// 注册全局 moment
import moment from "moment";
Vue.prototype.$moment = moment;
//挂载弹出信息
import { message } from "@/utils/resetMessage";
Vue.prototype.$message = message;
Vue.config.productionTip = false;
//虚拟列表
import { UTable, UTableColumn } from "umy-ui";
Vue.component(UTable.name, UTable);
Vue.component(UTableColumn.name, UTableColumn);
//使用钩子函数对路由进行权限跳转
router.beforeEach((to, from, next) => {
document.title = `${to.meta.title} | 运维管理系统`;
const token = localStorage.getItem("token");
if (!token && to.path !== "/login") {
next({
path: "/login",
});
} else {
next();
}
});
new Vue({
router,
store,
render: (h) => h(App),
}).$mount("#app");

@ -0,0 +1,90 @@
import Vue from "vue";
import VueRouter from "vue-router";
Vue.use(VueRouter);
const routes = [
{
path: "/login",
component: () => import("../views/login/index.vue"),
meta: { title: "登录" },
},
{
path: "/",
redirect: "/home",
component: () => import("../components/Home.vue"),
children: [
{
path: "/home",
component: () => import("../views/homePage/index.vue"),
name: "home",
meta: {
title: "首页",
keepAlive: true,
},
},
{
path: "/report",
component: () => import("../views/report/index.vue"),
name: "report",
meta: {
title: "状态报表",
//keepAlive: true,
},
},
{
path: "/log",
component: () => import("../views/logList/index.vue"),
name: "log",
meta: {
title: "日志列表",
keepAlive: true,
},
},
{
path: "/upgradation",
component: () => import("../views/upgradation/index.vue"),
name: "upgradation",
meta: {
title: "上传Apk",
keepAlive: true,
},
},
{
path: "/upgradationOta",
component: () => import("../views/upgradationOta/index.vue"),
name: "upgradationOta",
meta: {
title: "上传Ota",
keepAlive: true,
},
},
{
path: "/activity",
component: () => import("../views/activityList/index.vue"),
name: "activity",
meta: {
title: "活动列表",
keepAlive: true,
},
},
{
path: "/userlist",
component: () => import("../views/userList/index.vue"),
name: "userList",
meta: {
title: "用户列表",
keepAlive: true,
},
},
],
},
];
const router = new VueRouter({
mode: "hash",
base: process.env.BASE_URL,
routes,
});
export default router;

@ -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);
});
},
},
};

@ -0,0 +1,20 @@
import Vue from "vue";
import Vuex from "vuex";
import cacheModule from "./cache";
Vue.use(Vuex);
export default new Vuex.Store({
state: {
//用户登录token 存储
isRenderTab: true,
},
getters: {},
mutations: {
setIsRenderTab(state, data) {
state.isRenderTab = data;
},
},
actions: {},
modules: { cache: cacheModule },
});

@ -0,0 +1,172 @@
import request from "../request";
//获取登录
export function loginJoggle(data) {
return request({
url: "api/login.php",
method: "post",
data,
});
}
//获取line
export function getqueryLineApi(data) {
return request({
url: "api/queryLine.php",
method: "get",
params: data,
headers: {
"Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
},
});
}
export function getqueryTermsApi(data) {
return request({
url: "api/queryTerms.php",
method: "get",
params: data,
headers: {
"Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
},
});
}
//获取规约
export function getqueryProtocolApi(data) {
return request({
url: "api/queryProtocol.php",
method: "get",
params: data,
headers: {
"Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
},
});
}
//运维,快心跳
export function getdoActionApi(data) {
return request({
url: "api/doAction.php",
method: "get",
params: data,
headers: {
"Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
},
});
}
//上传日志列表
export function getqueryUploadsApi(data) {
return request({
url: "api/queryUploads.php",
method: "get",
params: data,
headers: {
"Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
},
});
}
//删除日志列表
export function updUploadApi(data) {
return request({
url: "api/updUpload.php",
method: "get",
params: data,
headers: {
"Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
},
});
}
//获取信息装置的信息
export function getqueryRawApi(data) {
return request({
url: "api/queryRawData.php",
method: "get",
params: data,
headers: {
"Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
},
});
}
//带下发状态
export function getqueryCmdsApi(data) {
return request({
url: "api/queryCmds.php",
method: "get",
params: data,
headers: {
"Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
},
});
}
//上传apk
export function postuploadFileApi(data) {
return request({
url: "api/uploadFile.php",
method: "post",
params: data,
headers: {
"Content-Type": "multipart/form-data", // set the content type to multipart/form-data
},
});
}
//获取上传列表
export function getqueryUpgradesApi(data) {
return request({
url: "api/queryUpgrades.php",
method: "get",
params: data,
headers: {
"Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
},
});
}
//删除列表
export function getupdUpgradeApi(data) {
return request({
url: "api/updUpgrade.php",
method: "get",
params: data,
headers: {
"Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
},
});
}
//新建活动和删除活动
export function updActivityApi(data) {
return request({
url: "api/updActivity.php",
method: "post",
data,
headers: {
"Content-Type": "multipart/form-data", // set the content type to multipart/form-data
},
});
}
//获取活动列表和详细列表
export function getqueryActivityApi(data) {
return request({
url: "api/queryActivity.php",
method: "get",
params: data,
headers: {
"Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
},
});
}
export function updComment(data) {
return request({
url: "api/updComment.php",
method: "get",
params: data,
headers: {
"Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
},
});
}

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

@ -0,0 +1,58 @@
import FileSaver from "file-saver";
import XLSX from "xlsx";
const htmlToExcel = {
getExcel(dom, title = "表格") {
// 设置当前日期
const time = new Date();
const year = time.getFullYear();
const month = time.getMonth() + 1;
const day = time.getDate();
const name = year + "-" + month + "-" + day;
var xlsxParam = { raw: true }; //转换成excel时使用原始的格式
const wb = XLSX.utils.table_to_book(document.querySelector(dom), xlsxParam);
/* 获取二进制字符串作为输出 */
const wbout = XLSX.write(wb, {
bookType: "xlsx",
bookSST: true,
type: "array",
});
try {
FileSaver.saveAs(
new Blob([wbout], { type: "application/octet-stream" }),
name + title + ".xlsx"
);
} catch (e) {
if (typeof console !== "undefined") console.log(e, wbout);
}
return wbout;
},
};
export default htmlToExcel;
// import FileSaver from "file-saver";
// import XLSX from "xlsx";
// const htmlToExcel = {
// getExcel(dom, title = "表格") {
// var excelTitle = title;
// var wb = XLSX.utils.table_to_book(document.querySelector(dom));
// /* 获取二进制字符串作为输出 */
// var wbout = XLSX.write(wb, {
// bookType: "xlsx",
// bookSST: true,
// type: "array",
// });
// try {
// FileSaver.saveAs(
// new Blob([wbout], { type: "application/octet-stream" }),
// excelTitle + ".xlsx"
// );
// } catch (e) {
// if (typeof console !== "undefined") console.log(e, wbout);
// }
// return wbout;
// },
// };
// export default htmlToExcel;

@ -0,0 +1,17 @@
// rem等比适配配置文件
// 基准大小
const baseSize = 16;
// 设置 rem 函数
function setRem() {
// 当前页面宽度相对于 1920宽的缩放比例可根据自己需要修改。
// const scale = document.documentElement.clientWidth / 1920;
// // 设置页面根节点字体大小“Math.min(scale, 2)” 指最高放大比例为2可根据实际业务需求调整
// document.documentElement.style.fontSize =
// baseSize * Math.min(scale, 2) + "px";
}
// 初始化
setRem();
// 改变窗口大小时重新设置 rem
window.onresize = function () {
setRem();
};

@ -0,0 +1,79 @@
import axios from "axios";
import { MessageBox, Message } from "element-ui";
import router from "../router/index";
const service = axios.create({
// process.env.NODE_ENV === 'development' 来判断是否开发环境
// easy-mock服务挂了暂时不使用了
// baseURL: '',
// timeout: 5000
baseURL: "/web", //把原来的项目地址改成api解决跨域问题
timeout: 30000,
});
// 添加请求拦截器一下内容是axios的拦截器可以不用写
service.interceptors.request.use(
function (config) {
// 在发送请求之前做些什么
return config;
},
function (error) {
// 对请求错误做些什么
return Promise.reject(error);
}
);
// 添加响应拦截器
service.interceptors.response.use(
function (response) {
// 对响应数据做点什么
return response.data;
},
function (error) {
// 对响应错误做点什么
return Promise.reject(error);
}
);
export default service;
// service.interceptors.request.use((config) => {
// if (localStorage.getItem("token")) {
// config.headers.sessionId = localStorage.getItem("token");
// }
// return config;
// });
// service.interceptors.response.use(
// (response) => {
// const res = response.data;
// if (res.code !== 200) {
// if (res.code === 401) {
// Message({ message: res.msg, type: "error", duration: 1500 });
// router.push("/login");
// }
// if (res.code === 400) {
// Message({ message: res.msg, type: "error", duration: 1500 });
// }
// if (res.code === 500) {
// Message({
// showClose: true,
// message: 服务器错误(500),
// type: "error",
// duration: 1500,
// });
// }
// return Promise.reject(new Error(res.msg || "Error"));
// } else {
// return res;
// }
// },
// (error) => {
// Message({
// message: error.message,
// showClose: true,
// type: "error",
// duration: 1500,
// });
// return Promise.reject(error);
// }
// );

@ -0,0 +1,28 @@
//resetMessage.js
/**重置message防止重复点击重复弹出message消息提示 */
import { Message } from "element-ui";
let messageInstance = null;
const resetMessage = (options) => {
if (messageInstance) {
messageInstance.close();
}
Message.closeAll(); //手动关闭所有消息提示实例
messageInstance = Message(options);
// console.log(Message(options));
};
["error", "success", "info", "warning"].forEach((type) => {
resetMessage[type] = (options) => {
if (typeof options === "string") {
options = {
message: options,
};
}
options.type = type;
return resetMessage(options);
};
});
export const message = resetMessage;

@ -0,0 +1,435 @@
<template>
<div class="activityBox">
<div class="uploadForm">
<div class="noteBox">
<h3 class="lableBox">活动名称</h3>
<el-input
class="noteClass"
v-model="activityForm.title"
placeholder="输入活动名称"
@focus="inputfocus"
></el-input>
<p class="redErr" v-if="titleFlag">*</p>
</div>
<div class="upgradeBox">
<h3 class="lableBox">装置列表</h3>
<el-input
type="textarea"
:rows="22"
placeholder="请输入装置列表"
v-model="activityForm.cmdidArr"
@focus="textfocus"
>
</el-input>
<p class="redErr" v-if="cmdidFlag">*</p>
</div>
<el-button
class="uploadBtn"
size="small"
type="primary"
@click="submitUpload"
>上传活动列表</el-button
>
</div>
<div class="activityList">
<el-table
:data="activityData"
style="width: 100%"
border
stripe
height="calc(100% - 0px)"
v-loading="activityloading"
>
<el-table-column type="index" width="50" label="序号">
</el-table-column>
<el-table-column
prop="createTime"
label="创建时间"
width="180"
></el-table-column>
<el-table-column prop="title" label="活动名称"> </el-table-column>
<el-table-column prop="termCount" label="装置数量">
<template slot-scope="scope">
{{ scope.row.termCount }}
</template>
</el-table-column>
<!-- <el-table-column prop="path" label="文件路径"> </el-table-column> -->
<el-table-column label="操作" width="300" class-name="editClass">
<template slot-scope="scope">
<el-link
type="primary"
@click="handleEditClick(scope.row)"
size="small"
icon="el-icon-document"
>修改</el-link
>
<el-link
type="primary"
@click="handleLookClick(scope.row)"
size="small"
icon="el-icon-document"
>详情</el-link
>
<el-link
type="danger"
@click="handleDeleteClick(scope.row)"
size="small"
icon="el-icon-delete"
>删除</el-link
>
</template>
</el-table-column>
</el-table>
</div>
<el-dialog
class="termsDialog"
:title="activityName"
:visible.sync="termsShow"
:close-on-click-modal="false"
width="50%"
>
<el-button class="exportBtn" type="primary" @click="handleExport"
>导出活动列表</el-button
>
<el-table
ref="activityTable"
id="activityTable"
:data="termsData"
style="width: 100%"
:header-cell-style="{ 'text-align': 'center' }"
:cell-style="{ 'text-align': 'center' }"
border
stripe
height="600px"
v-loading="activityloading"
@header-click="handleHeaderClick"
>
<el-table-column type="index" width="50" label="序号">
</el-table-column>
<el-table-column prop="line_name" label="线路名称"> </el-table-column>
<el-table-column prop="tower_name" label="杆塔名称"> </el-table-column>
<el-table-column prop="cmdid" label="装置编号">
<template slot="header" slot-scope="scope">
装置编号<el-tag
type="success"
style="cursor: pointer; margin-left: 8px"
>复制列</el-tag
>
</template>
</el-table-column>
<el-table-column prop="protocol" label="规约">
<template slot-scope="scope">
{{ protocolMap[scope.row.protocol] }}
</template>
</el-table-column>
</el-table>
<div slot="footer" class="dialog-footer">
<el-button @click="termsShow = false">关闭</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { updActivityApi, getqueryActivityApi } from "@/utils/api/index";
import htmlToExcel from "@/utils/htmlToExcel";
import { saveAs } from "file-saver";
import XLSX from "xlsx";
export default {
name: "activity",
components: {},
data() {
return {
activityloading: true,
activityData: [], //
activityForm: {
title: "",
cmdidArr: "",
},
titleFlag: false, //title
cmdidFlag: false, //cmdid
termsShow: false,
termsData: [],
termsLoading: true,
activityName: "",
activityNameTitle: "",
protocolMap: {
65280: "国网I1",
65296: "陕西",
65281: "安徽",
65282: "江苏",
65283: "湖南",
65284: "浙江",
65285: "河南全景",
65286: "河南郑州",
65290: "河南统一视频v2020",
},
ActibityId: "", //
};
},
computed: {},
mounted() {
this.getactivityList();
},
methods: {
async handleHeaderClick(column) {
console.log(column);
//
const dataField = column.property;
//
const columnData = this.termsData.map((row) => row[dataField]);
console.log(`当前列数据字段:${dataField}`);
console.log(`当前列数据值:${columnData}`);
this.copyToClipboard(columnData.join("\n"));
console.log(columnData);
// this.activityForm.cmdidArr = columnData.join("\n");
// this.activityForm.title = this.activityNameTitle;
//this.termsShow = false;
},
copyToClipboard(text) {
const textArea = document.createElement("textarea");
textArea.value = text;
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
try {
const successful = document.execCommand("copy");
const msg = successful ? "成功复制到剪贴板" : "复制失败";
console.log(msg);
this.$message({
duration: 1500,
showClose: true,
message: msg,
type: "success",
});
} catch (err) {
console.error("复制失败:", err);
} finally {
document.body.removeChild(textArea);
}
},
//
handleExport() {
htmlToExcel.getExcel("#activityTable", "设备活动列表");
},
//
getactivityList() {
this.activityloading = true;
this.activityData = [];
getqueryActivityApi({
act: "list",
})
.then((res) => {
console.log(res);
this.activityData = res.data;
this.activityloading = false;
})
.catch((err) => {});
},
//
handleEditClick(row) {
console.log(row);
getqueryActivityApi({
act: "detail",
id: row.id,
})
.then((res) => {
console.log(res);
this.ActibityId = res.data.activity.id;
this.activityForm.title = res.data.activity.title;
console.log(this.activityForm.title);
const columnData = res.data.terms.map((item) => item.cmdid);
console.log(columnData);
this.activityForm.cmdidArr = columnData.join("\n");
})
.catch((err) => {});
},
//
handleLookClick(row) {
this.termsShow = true;
this.termsLoading = true;
this.termsData = [];
getqueryActivityApi({
act: "detail",
id: row.id,
})
.then((res) => {
console.log(res);
this.termsLoading = false;
this.activityNameTitle = res.data.activity.title;
this.activityName =
res.data.activity.title + "(" + res.data.terms.length + ")";
this.termsData = res.data.terms;
})
.catch((err) => {});
},
//
handleDeleteClick(row) {
console.log(row);
updActivityApi({
act: "del",
id: row.id,
})
.then((res) => {
console.log(res);
this.$confirm("此操作将永久删除该文件, 是否继续?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
})
.then(() => {
this.$message({
duration: 1500,
showClose: true,
message: "文件删除成功",
type: "success",
});
this.getactivityList();
})
.catch(() => {});
})
.catch((err) => {});
},
//title
inputfocus() {
this.titleFlag = false;
},
//text
textfocus() {
this.cmdidFlag = false;
},
//
submitUpload() {
if (this.activityForm.title == "") {
this.titleFlag = true;
return;
}
if (this.activityForm.cmdidArr == "") {
this.cmdidFlag = true;
return;
}
let actParams = {};
if (this.ActibityId !== "") {
console.log(this.ActibityId);
actParams = {
id: this.ActibityId,
title: this.activityForm.title,
cmdids: this.activityForm.cmdidArr,
act: "edt",
};
} else {
actParams = {
title: this.activityForm.title,
cmdids: this.activityForm.cmdidArr,
act: "new",
};
}
console.log(this.activityForm.title);
console.log(this.activityForm.cmdidArr);
//console.log(arrList);
updActivityApi(actParams)
.then((res) => {
console.log(res);
this.getactivityList();
this.activityForm.title = "";
this.activityForm.cmdidArr = "";
this.ActibityId = "";
})
.catch((err) => {});
},
},
};
</script>
<style lang="less">
.activityBox {
height: calc(100% - 24px);
width: calc(100% - 24px);
padding: 12px;
display: flex;
.uploadForm {
min-width: 300px;
margin-right: 20px;
.noteBox {
margin-bottom: 16px;
position: relative;
.noteClass {
width: 100%;
}
.lableBox {
font-size: 14px;
font-weight: normal;
width: 78px;
line-height: 32px;
}
.redErr {
position: absolute;
font-size: 12px;
color: red;
}
}
.upgradeBox {
position: relative;
.lableBox {
font-size: 14px;
font-weight: normal;
width: 78px;
line-height: 32px;
}
.redErr {
position: absolute;
font-size: 12px;
color: red;
}
}
.uploadBtn {
margin-top: 16px;
margin-left: auto;
display: flex;
}
}
.activityList {
height: calc(100% - 0px);
flex: 1;
min-width: 0;
.el-table {
.el-table__cell {
text-align: center;
}
}
}
.editClass {
.el-link.el-link--primary {
margin-right: 14px;
}
}
.termsDialog {
.el-dialog {
margin-top: 0 !important;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
.exportBtn {
position: absolute;
z-index: 1;
top: 16px;
right: 66px;
}
.el-dialog__body {
padding: 12px;
}
}
}
.el-dialog__headerbtn {
top: 18px;
.el-dialog__close {
font-size: 26px;
&:hover {
background: #e2e2e2;
}
}
}
</style>

@ -0,0 +1,309 @@
<template>
<el-dialog
class="cmdMsgDialog"
title="历史信息"
:visible.sync="isShow"
:close-on-click-modal="false"
>
<div class="cmdBoxMain">
<el-table
:data="gridData"
style="width: 100%"
border
stripe
height="calc(100% - 40px)"
v-loading="girdloading"
>
<el-table-column type="index" width="50" label="序号">
</el-table-column>
<el-table-column prop="createTime" label="时间"></el-table-column>
<el-table-column label="id">
<template slot-scope="scope">
{{ scope.row.raw_report.id }}
</template>
</el-table-column>
<el-table-column label="i1服务器">
<template slot-scope="scope">
<span v-if="scope.row.raw_report.hasOwnProperty('XyDev')">{{
scope.row.raw_report.cma
}}</span>
<span v-else>{{ scope.row.raw_report.msgs.cma }}</span>
</template>
</el-table-column>
<el-table-column label="心跳间隔" width="70">
<template slot-scope="scope">
<span v-if="scope.row.raw_report.hasOwnProperty('XyDev')">{{
scope.row.raw_report.heartbeatDuration
}}</span>
<span v-else>{{
scope.row.raw_report.msgs.heartbeatDuration
}}</span>
</template>
</el-table-column>
<el-table-column label="电池">
<template slot-scope="scope">
<span v-if="scope.row.raw_report.hasOwnProperty('XyDev')">{{
scope.row.raw_report.battary
}}</span>
<span v-else> {{ scope.row.raw_report.msgs.battery }}</span>
</template>
</el-table-column>
<el-table-column label="电池温度" width="70">
<template slot-scope="scope">
<span v-if="scope.row.raw_report.hasOwnProperty('XyDev')">{{
scope.row.raw_report.batteryTmp
}}</span>
<span v-else>{{ scope.row.raw_report.msgs.batteryTmp }}</span>
</template>
</el-table-column>
<el-table-column label="主板温度" width="70">
<template slot-scope="scope">
<span v-if="scope.row.raw_report.hasOwnProperty('XyDev')">{{
scope.row.raw_report.mainBoardTmp
}}</span>
<span v-else> {{ scope.row.raw_report.msgs.mainBoardTmp }}</span>
</template>
</el-table-column>
<el-table-column label="系统重启" width="70">
<template slot-scope="scope">
<span v-if="scope.row.raw_report.hasOwnProperty('XyDev')">{{
scope.row.raw_report.rebootTimes
}}</span>
<span v-else>{{ scope.row.raw_report.msgs.rebootTimes }}</span>
</template>
</el-table-column>
<el-table-column label="i1重启" width="70">
<template slot-scope="scope">
<span v-if="scope.row.raw_report.hasOwnProperty('XyDev')">{{
scope.row.raw_report.i1RebootTimes
}}</span>
<span v-else>{{ scope.row.raw_report.msgs.i1RebootTimes }}</span>
</template>
</el-table-column>
<el-table-column label="收" width="70">
<template slot-scope="scope">
<span v-if="scope.row.raw_report.hasOwnProperty('XyDev')">{{
scope.row.raw_report.recv
}}</span>
<span v-else> {{ scope.row.raw_report.msgs.recv }}</span>
</template>
</el-table-column>
<el-table-column label="传图" width="70">
<template slot-scope="scope">
<span v-if="scope.row.raw_report.hasOwnProperty('XyDev')">{{
scope.row.raw_report.pic
}}</span>
<span v-else> {{ scope.row.raw_report.pic }}</span>
</template>
</el-table-column>
<el-table-column label="拍" width="60">
<template slot-scope="scope">
<span v-if="scope.row.raw_report.hasOwnProperty('XyDev')">{{
scope.row.raw_report.photoTimes
}}</span>
<span v-else> {{ scope.row.raw_report.msgs.photoTimes }}</span>
</template>
</el-table-column>
<el-table-column label="成/败/传" width="70">
<template slot-scope="scope">
<span v-if="scope.row.raw_report.hasOwnProperty('XyDev')">
{{ scope.row.raw_report.success }}/{{
scope.row.raw_report.failure
}}/{{ scope.row.raw_report.uploads }}</span
>
<span v-else>
{{ scope.row.raw_report.msgs.success }}/{{
scope.row.raw_report.msgs.failure
}}/{{ scope.row.raw_report.msgs.uploads }}</span
>
</template>
</el-table-column>
<el-table-column label="心跳累计" width="80">
<template slot-scope="scope">
<span v-if="scope.row.raw_report.hasOwnProperty('XyDev')">{{
scope.row.raw_report.numberOfHb
}}</span>
<span v-else> {{ scope.row.raw_report.msgs.numberOfHb }}</span>
</template>
</el-table-column>
<el-table-column label="网络异常" width="80">
<template slot-scope="scope">
<span v-if="scope.row.raw_report.hasOwnProperty('XyDev')">{{
scope.row.raw_report.networkError
}}</span>
<span v-else>{{ scope.row.raw_report.msgs.networkError }}</span>
</template>
</el-table-column>
<el-table-column label="信号1" width="60">
<template slot-scope="scope">
<span v-if="scope.row.raw_report.hasOwnProperty('XyDev')">{{
scope.row.raw_report.signature1
}}</span>
<span v-else>{{ scope.row.raw_report.msgs.signature1 }}</span>
</template>
</el-table-column>
<el-table-column label="信号2" width="60">
<template slot-scope="scope">
<span v-if="scope.row.raw_report.hasOwnProperty('XyDev')">{{
scope.row.raw_report.signature2
}}</span>
<span v-else> {{ scope.row.raw_report.msgs.signature2 }}</span>
</template>
</el-table-column>
<!-- <el-table-column label="其他">
<template slot-scope="scope">
{{ scope.row.raw_report.msgs.id }}
</template>
</el-table-column> -->
<el-table-column prop="content" label="其他" class-name="msgClass">
<template slot-scope="scope">
<el-tooltip
:open-delay="600"
popper-class="msgTootip"
placement="top"
effect="light"
>
<div slot="content">
<p v-html="cutout(scope.row)"></p>
</div>
<p>
{{ scope.row.content }}
</p>
</el-tooltip>
</template>
</el-table-column>
</el-table>
<div class="pageNation">
<el-pagination
@current-change="handleCurrentChange"
@size-change="handleSizeChange"
:current-page="page"
:page-size="pageSize"
layout="sizes, prev, pager, next, jumper,total"
:total="total"
>
</el-pagination>
</div>
</div>
</el-dialog>
</template>
<script>
import { getqueryRawApi } from "@/utils/api/index";
export default {
props: {},
data() {
return {
gridData: [],
girdloading: true,
isShow: false,
page: 1, //
pageSize: 20, //
total: 0, //
termid: "",
};
},
methods: {
//tootip
cutout(cellValue) {
var aString = cellValue.content
.replace(/\,/g, "</br>")
.replace(/{|}/g, "")
.replace(/"|"/g, "")
.replace(/msg:/g, "");
return aString;
},
getQueryList() {
this.girdloading = true;
getqueryRawApi({
termId: this.termid,
p: this.page,
ps: this.pageSize,
})
.then((res) => {
console.log(res);
this.gridData = res.data;
this.total = Number(res.page.totalRecords);
this.girdloading = false;
})
.catch((err) => {});
},
display(val) {
this.isShow = true;
this.termid = val.id;
this.getQueryList();
},
hide() {
this.isShow = false;
},
handleCurrentChange(val) {
this.page = val;
this.getQueryList();
},
//
handleSizeChange(val) {
this.pageSize = val;
this.getQueryList();
},
},
};
</script>
<style lang="less">
.cmdMsgDialog {
display: flex;
align-items: center;
justify-items: center;
justify-content: center;
.el-dialog {
width: 95%;
height: 83%;
margin-top: 0px !important;
.el-dialog__body {
padding: 12px;
width: calc(100% - 24px);
height: calc(100% - 78px);
.cmdBoxMain {
width: 100%;
height: 100%;
.el-table {
.el-table__cell {
text-align: center;
}
.msgClass {
.cell {
p {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
cursor: default;
}
}
}
}
}
.pageNation {
margin-top: 10px;
display: flex;
justify-content: flex-end;
}
}
}
}
.msgTootip {
color: #333;
overflow: auto;
height: 90%;
p {
font-size: 14px;
line-height: 22px;
}
}
</style>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -0,0 +1,773 @@
<template>
<div class="homeBox">
<div class="filterBox">
<el-form
v-show="showDiv"
:inline="true"
:model="formdata"
class="demo-form-inline"
>
<div class="topSearch">
<el-form-item label="线路" class="xlbox">
<el-select
v-model="formdata.lineId"
@change="getSearchgt"
filterable
>
<el-option
v-for="item in xlOptions"
:key="item.id"
:label="item.name"
:value="item.id"
>
{{ item.vname + item.name }}
</el-option>
</el-select>
</el-form-item>
<el-form-item label="杆塔" class="gtbox">
<el-select v-model="formdata.towerId" filterable>
<el-option
v-for="item in gtOptions"
:key="item.id"
:label="item.name"
:value="item.id"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="是否在线" class="isonLineClass">
<el-select v-model="formdata.isonline">
<el-option
v-for="item in onlineOptions"
:key="item.id"
:label="item.name"
:value="item.id"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="是否运维" class="ismntClass">
<el-select v-model="formdata.ismntend">
<el-option
v-for="item in mntendOptions"
:key="item.id"
:label="item.name"
:value="item.id"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="规约" class="gybox">
<el-select v-model="formdata.protocolId" filterable>
<el-option
v-for="item in protocolOptions"
:key="item.id"
:label="item.name"
:value="item.id"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="活动" class="activitybox">
<el-select
v-model="formdata.activityId"
filterable
@change="changeActive"
>
<el-option
v-for="item in activityOptions"
:key="item.id"
:label="item.name"
:value="item.id"
></el-option>
</el-select>
</el-form-item>
</div>
<div class="bottomSearch">
<el-form-item label="出厂ID" class="oidbox">
<el-input
v-model="formdata.oidInput"
placeholder="请输入出厂ID"
clearable
></el-input>
<el-tooltip
class="item"
effect="dark"
content="反选"
placement="top"
>
<el-checkbox
v-model="formdata.oidCheck"
:checked="formdata.oidCheck == 1 ? true : false"
true-label="1"
false-label="0"
></el-checkbox>
</el-tooltip>
</el-form-item>
<el-form-item label="装置编号" class="cmdibox">
<el-input
v-model="formdata.cmdidInput"
placeholder="请输入装置编号"
clearable
></el-input>
<el-tooltip
class="item"
effect="dark"
content="反选"
placement="top"
>
<el-checkbox
v-model="formdata.cmdidCheck"
:checked="formdata.cmdidCheck == 1 ? true : false"
true-label="1"
false-label="0"
></el-checkbox>
</el-tooltip>
</el-form-item>
<el-form-item label="CMA服务器" class="cmabox">
<el-input
v-model="formdata.cmaInput"
placeholder="请输入CMA服务器"
clearable
></el-input>
<el-tooltip
class="item"
effect="dark"
content="反选"
placement="top"
>
<el-checkbox
v-model="formdata.cmaCheck"
:checked="formdata.cmaCheck == 1 ? true : false"
true-label="1"
false-label="0"
></el-checkbox>
</el-tooltip>
</el-form-item>
<el-form-item label="版本" class="versionbox">
<el-input
v-model="formdata.versionInput"
placeholder="请输入版本"
clearable
></el-input>
<el-tooltip
class="item"
effect="dark"
content="反选"
placement="top"
>
<el-checkbox
v-model="formdata.versionCheck"
:checked="formdata.versionCheck == 1 ? true : false"
true-label="1"
false-label="0"
></el-checkbox>
</el-tooltip>
</el-form-item>
<el-form-item class="btngrop">
<el-button type="primary" @click="onSubmit"></el-button>
<el-button type="primary" @click="onReset"></el-button>
</el-form-item>
</div>
</el-form>
<el-tooltip
class="item"
effect="dark"
:content="showDiv ? '收起' : '展开'"
placement="top"
>
<el-button
type="primary"
:class="showDiv ? 'toggleClass' : 'toggleClass2'"
:icon="showDiv ? 'el-icon-d-arrow-right' : 'el-icon-d-arrow-left'"
circle
@click="toggleDiv"
></el-button>
</el-tooltip>
</div>
<div
class="tableBox"
:style="{ height: showDiv ? 'calc(100% - 82px)' : 'calc(100% - 2px)' }"
>
<tableMain
ref="tableRef"
:tableData="dataListNew"
:onlineNum="onlineNum"
:offlineNum="offlineNum"
:noPicNum="noPicNum"
:freeNum="freeNum"
:tableLoaidng="tableLoaidng"
></tableMain>
</div>
</div>
</template>
<script>
import {
getqueryLineApi,
getqueryTermsApi,
getqueryProtocolApi,
getqueryActivityApi,
getqueryCmdsApi,
} from "@/utils/api/index";
import tableMain from "./components/tableMain";
export default {
name: "home",
components: {
tableMain,
},
data() {
return {
showDiv: true, // div
nowTime: new Date().getTime() / 1000,
xlOptions: [{ id: 0, name: "全部" }], //线
gtOptions: [{ id: 0, name: "全部" }], //
onlineOptions: [
{ id: -1, name: "全部" },
{ id: 1, name: "在线" },
{ id: 0, name: "离线" },
],
formdata: {
lineId: 0,
towerId: 0,
isonline: -1,
protocolId: 0,
activityId: 0,
ismntend: 1,
oidInput: "",
oidCheck: 0,
cmdidInput: "",
cmdidCheck: 0,
cmaInput: "",
cmaCheck: 0,
versionInput: "",
versionCheck: 0,
},
protocolOptions: [{ id: 0, name: "全部" }], //
activityOptions: [{ id: 0, name: "全部" }], //
mntendOptions: [
{ id: 0, name: "全部" },
{ id: 1, name: "运维" },
{ id: 2, name: "未运维" },
], //
dataList: [],
dataListNew: [],
tableLoaidng: true,
onlineNum: 0, //线
offlineNum: 0, //线
noPicNum: 0, //
freeNum: 0,
intervalId: null, // ID
activityIdLoc: "",
runCommand: [], //
};
},
created() {
var that = this;
document.onkeydown = function (e) {
var key = window.event.keyCode;
if (key === 13) {
that.onSubmit(); //
}
};
this.activityIdLoc =
JSON.parse(localStorage.getItem("activeId")) !== null
? JSON.parse(localStorage.getItem("activeId"))
: -1;
//this.fetchData(); //
//setInterval(this.fetchData, 60000); // 10
this.formdata =
JSON.parse(localStorage.getItem("searchParams")) !== null
? JSON.parse(localStorage.getItem("searchParams"))
: {
lineId: 0,
towerId: 0,
isonline: -1,
protocolId: 0,
activityId: 0,
ismntend: 1,
oidInput: "",
oidCheck: 0,
cmdidInput: "",
cmdidCheck: 0,
cmaInput: "",
cmaCheck: 0,
versionInput: "",
versionCheck: 0,
};
},
mounted() {
this.getActivityList();
this.getLineList();
this.getprotocolList();
},
watch: {},
methods: {
//linelist 线
getLineList() {
getqueryLineApi()
.then((res) => {
console.log(res);
this.xlOptions = [{ id: 0, name: "全部", vname: "" }];
this.xlOptions = this.xlOptions.concat(res.data);
this.formdata.lineId = this.xlOptions[0].id;
})
.catch((err) => {});
},
//线
getSearchgt() {
getqueryLineApi({ lineId: this.formdata.lineId })
.then((res) => {
this.gtOptions = [{ id: 0, name: "全部" }];
this.gtOptions = this.gtOptions.concat(res.data);
this.formdata.towerId = this.gtOptions[0].id;
})
.catch((err) => {});
},
//linelist 线
getprotocolList() {
getqueryProtocolApi()
.then((res) => {
console.log(res);
this.protocolOptions = [{ id: 0, name: "全部" }];
this.protocolOptions = this.protocolOptions.concat(res.data);
this.formdata.protocolId = this.protocolOptions[0].id;
})
.catch((err) => {});
},
//
getActivityList() {
getqueryActivityApi({
act: "list",
})
.then((res) => {
console.log(res);
console.log("222222222222222");
this.activityOptions = [{ id: 0, name: "全部" }];
let activeArr = res.data.map((item) => ({
id: item.id,
name: item.title,
}));
this.activityOptions = this.activityOptions.concat(activeArr);
//this.formdata.activityId = this.activityOptions[0].id;
this.formdata.activityId =
JSON.parse(localStorage.getItem("activeId")) !== null
? JSON.parse(localStorage.getItem("activeId"))
: this.activityOptions[0].id;
this.onSubmit();
})
.catch((err) => {});
},
changeActive(val) {
console.log(val);
localStorage.setItem("activeId", JSON.stringify(val));
},
onSubmit() {
this.tableLoaidng = true;
this.dataList = [];
console.log("我是查询", this.formdata);
localStorage.setItem("searchParams", JSON.stringify(this.formdata));
let params = {
lineId: this.formdata.lineId,
towerId: this.formdata.towerId,
isonLine: this.formdata.isonline,
};
var nonmntnedObj = {
name: "mntned",
value: this.formdata.ismntend,
invertVal: "",
};
var protocolObj = {
name: "protocol",
value: this.formdata.protocolId,
invertVal: 0,
};
var activityObj = {
name: "activity",
value: this.formdata.activityId,
invertVal: 0,
};
var oidObj = {
name: "oid",
value: this.formdata.oidInput.trim(),
invertVal: this.formdata.oidCheck,
};
var cmdidObj = {
name: "cmdid",
value: this.formdata.cmdidInput.trim(),
invertVal: this.formdata.cmdidCheck,
};
var cmaObj = {
name: "cma",
value: this.formdata.cmaInput.trim(),
invertVal: this.formdata.cmaCheck,
};
var versionObj = {
name: "version",
value: this.formdata.versionInput.trim(),
invertVal: this.formdata.versionCheck,
};
let arrayOfObjects = [nonmntnedObj, protocolObj, activityObj];
if (oidObj.value !== "") {
arrayOfObjects.push(oidObj);
}
if (cmaObj.value !== "") {
arrayOfObjects.push(cmaObj);
}
if (cmdidObj.value !== "") {
arrayOfObjects.push(cmdidObj);
}
if (versionObj.value !== "") {
arrayOfObjects.push(versionObj);
}
console.log(arrayOfObjects);
for (var k = 0; k < arrayOfObjects.length; k++) {
params["fc"] = arrayOfObjects.length;
params["fn" + (k + 1)] = arrayOfObjects[k].name;
params["fv" + (k + 1)] = arrayOfObjects[k].value;
params["frev" + (k + 1)] = arrayOfObjects[k].invertVal;
}
console.log(params);
//
if (this.intervalId) {
clearInterval(this.intervalId);
this.intervalId = null;
}
const interval = 60000; // 60000
this.intervalId = setInterval(() => {
//
this.fetchData();
}, interval);
getqueryTermsApi(params)
.then((res) => {
res.data = res.data.map((item) => {
if (!item.raw_report.pic) {
item.raw_report.pic = 0;
}
return item;
});
if (this.formdata.isonline == "-1") {
//
this.dataList = res.data;
// console.log(this.dataList)
} else if (this.formdata.isonline == "1") {
//线
this.dataList = res.data.filter(
(item) => this.nowTime - item.last_heartbeat_ts <= 720
);
} else if (this.formdata.isonline == "0") {
//线
this.dataList = res.data.filter(
(item) => this.nowTime - item.last_heartbeat_ts > 720
);
}
this.onlineNum = this.dataList.filter(
(item) => this.nowTime - item.last_heartbeat_ts <= 720
).length;
this.offlineNum = this.dataList.length - this.onlineNum;
this.noPicNum = this.dataList.filter(
(item) =>
item.raw_report.pic == undefined ||
item.raw_report.pic == 0 ||
item.raw_report.pic == -1
).length;
this.freeNum = this.dataList.filter(
(item) => parseInt(item.raw_report.msgs.freeROM) < 50
).length;
console.log("我是磁盘", this.freeNum);
this.getCmdList();
this.tableLoaidng = false;
})
.catch((err) => {});
},
fetchData() {
let params = {
lineId: this.formdata.lineId,
towerId: this.formdata.towerId,
isonLine: this.formdata.isonline,
};
var nonmntnedObj = {
name: "mntned",
value: this.formdata.ismntend,
invertVal: "",
};
var protocolObj = {
name: "protocol",
value: this.formdata.protocolId,
invertVal: 0,
};
var activityObj = {
name: "activity",
value: this.formdata.activityId,
invertVal: 0,
};
var oidObj = {
name: "oid",
value: this.formdata.oidInput,
invertVal: this.formdata.oidCheck,
};
var cmdidObj = {
name: "cmdid",
value: this.formdata.cmdidInput,
invertVal: this.formdata.cmdidCheck,
};
var cmaObj = {
name: "cma",
value: this.formdata.cmaInput,
invertVal: this.formdata.cmaCheck,
};
var versionObj = {
name: "version",
value: this.formdata.versionInput,
invertVal: this.formdata.versionCheck,
};
let arrayOfObjects = [nonmntnedObj, protocolObj, activityObj];
if (oidObj.value !== "") {
arrayOfObjects.push(oidObj);
}
if (cmaObj.value !== "") {
arrayOfObjects.push(cmaObj);
}
if (cmdidObj.value !== "") {
arrayOfObjects.push(cmdidObj);
}
if (versionObj.value !== "") {
arrayOfObjects.push(versionObj);
}
console.log(arrayOfObjects);
for (var k = 0; k < arrayOfObjects.length; k++) {
params["fc"] = arrayOfObjects.length;
params["fn" + (k + 1)] = arrayOfObjects[k].name;
params["fv" + (k + 1)] = arrayOfObjects[k].value;
params["frev" + (k + 1)] = arrayOfObjects[k].invertVal;
}
console.log(params);
getqueryTermsApi(params)
.then((res) => {
console.log(res);
res.data = res.data.map((item) => {
if (!item.raw_report.pic) {
item.raw_report.pic = 0;
}
return item;
});
if (this.formdata.isonline == "-1") {
//
this.dataList = res.data;
} else if (this.formdata.isonline == "1") {
//线
this.dataList = res.data.filter(
(item) => this.nowTime - item.last_heartbeat_ts <= 720
);
} else if (this.formdata.isonline == "0") {
//线
this.dataList = res.data.filter(
(item) => this.nowTime - item.last_heartbeat_ts > 720
);
}
this.onlineNum = this.dataList.filter(
(item) => this.nowTime - item.last_heartbeat_ts <= 720
).length;
this.offlineNum = this.dataList.length - this.onlineNum;
this.noPicNum = this.dataList.filter(
(item) =>
item.raw_report.pic == undefined ||
item.raw_report.pic == 0 ||
item.raw_report.pic == -1
).length;
this.freeNum = this.dataList.filter(
(item) => parseInt(item.raw_report.msgs.freeROM) < 50
).length;
console.log("我是磁盘", this.freeNum);
this.getCmdList();
})
.catch((err) => {});
},
//
getCmdList() {
getqueryCmdsApi({ p: 1, ps: 10000 })
.then((res) => {
console.log(res);
console.log("我是命令列表");
console.log(this.dataList);
this.runCommand = res.data;
// let array1 = [{ id: 0, name: "sss" },{ id: 1, name: "111" }];
// let array2 = [{ termid: 0, time: "aaaa" },{ termid: 1, time: "s1111ss" }];
// array1id
let ids = this.dataList.map((item) => item.id);
// array2termIdarray1id
let filteredArray2 = this.runCommand.filter((item) =>
ids.includes(item.termId)
);
// array1list
this.dataList.forEach((item) => {
let match = filteredArray2.find((i) => i.termId === item.id);
if (match) {
item.list = item.list || []; // list
item.list.push(match);
}
});
this.dataListNew = this.dataList;
console.log(this.dataList);
})
.catch((err) => {});
},
//
onReset() {
this.formdata = {
lineId: 0,
towerId: 0,
isonline: -1,
protocolId: 0,
activityId:
JSON.parse(localStorage.getItem("activeId")) !== null
? JSON.parse(localStorage.getItem("activeId"))
: 0,
ismntend: 1,
oidInput: "",
oidCheck: 0,
cmdidInput: "",
cmdidCheck: 0,
cmaInput: "",
cmaCheck: 0,
versionInput: "",
versionCheck: 0,
};
this.onSubmit();
},
//
toggleDiv() {
this.showDiv = !this.showDiv; // showDiv
this.$refs.tableRef.calculateHeight(this.showDiv);
},
},
};
</script>
<style lang="less">
.homeBox {
height: calc(100% - 16px);
width: calc(100% - 24px);
padding: 12px 12px 4px 12px;
.filterBox {
position: relative;
font-size: 12px;
.el-form-item__label {
font-size: 12px;
}
.el-input__inner {
font-size: 12px;
padding: 0px 24px 0px 4px !important;
}
.el-form {
display: flex;
// align-items: center;
// flex-wrap: wrap;
flex-direction: column;
.el-form-item {
margin-bottom: 8px;
}
.topSearch {
display: flex;
}
.bottomSearch {
display: flex;
align-items: center;
.el-form-item--small .el-form-item__label {
white-space: nowrap;
}
.btngrop {
.el-form-item__content {
display: flex;
flex-wrap: nowrap;
}
}
}
.ismntClass {
.el-select {
width: 100px;
}
}
.isonLineClass {
.el-select {
width: 80px;
}
}
.gybox {
.el-select {
width: 160px;
}
}
.oidbox,
.cmdibox,
.cmabox,
.versionbox {
display: flex;
align-items: center;
background: #e9e9e9;
padding: 0px 12px;
border-radius: 3px;
.el-form-item__content {
display: flex;
align-items: center;
.el-input {
margin-right: 8px;
width: 162px;
}
}
}
.el-form-item__label,
.el-checkbox {
color: #333;
}
}
.toggleClass {
position: absolute;
right: 2px;
top: 82px;
.el-icon-d-arrow-left {
transform: rotate(-90deg);
}
.el-icon-d-arrow-right {
transform: rotate(-90deg);
}
}
.toggleClass2 {
position: absolute;
right: 2px;
top: 0px;
.el-icon-d-arrow-left {
transform: rotate(-90deg);
}
.el-icon-d-arrow-right {
transform: rotate(-90deg);
}
}
}
.tableBox {
//height: calc(100% - 102px);
}
}
.el-pagination {
color: #606262;
font-weight: normal;
.el-pager li.active {
font-weight: 800;
}
}
.el-dialog__headerbtn {
top: 18px;
.el-dialog__close {
font-size: 26px;
&:hover {
background: #e2e2e2;
}
}
}
</style>

@ -0,0 +1,158 @@
<template>
<div class="logMainClass">
<h3>日志列表</h3>
<div class="boxLogTable">
<el-table
v-loading="logLoading"
:data="tableData"
border
stripe
style="width: 100%"
height="100%"
>
<el-table-column type="index" width="50" label="序号">
</el-table-column>
<!-- <el-table-column prop="id" label="Id" width="80"> </el-table-column> -->
<el-table-column prop="line_name" label="线路"> </el-table-column>
<el-table-column prop="cmdid" label="装置编号"> </el-table-column>
<el-table-column label="规约" width="100">
<template slot-scope="scope">
{{ protocolMap[scope.row.protocol] }}
</template>
</el-table-column>
<el-table-column prop="file_name" label="文件名">
<template slot-scope="scope">
<a :href="'/dl/?id=' + scope.row.id" class="buttonText">{{
scope.row.file_name
}}</a>
</template>
</el-table-column>
<el-table-column label="文件大小">
<template slot-scope="scope">
{{ scope.row.file_size | changeType }}
</template>
</el-table-column>
<el-table-column prop="create_time" label="上传时间"> </el-table-column>
<el-table-column label="操作" class-name="editClass">
<template slot-scope="scope">
<el-link
type="danger"
@click="handleDeleteClick(scope.row)"
size="small"
icon="el-icon-delete"
>删除</el-link
>
</template>
</el-table-column>
</el-table>
</div>
</div>
</template>
<script>
import { getqueryUploadsApi, updUploadApi } from "@/utils/api/index";
export default {
name: "log",
components: {},
data() {
return {
tableData: [],
logLoading: false,
protocolMap: {
65280: "国网I1",
65296: "陕西",
65281: "安徽",
65282: "江苏",
65283: "湖南",
65284: "浙江",
65285: "河南全景",
65286: "河南郑州",
65290: "河南统一视频v2020",
},
};
},
filters: {
changeType(val) {
if (val == "0") return "0B";
var k = 1024;
var sizes = ["B", "KB", "MB", "GB", "TB"];
let i = Math.floor(Math.log(val) / Math.log(k)); //kB?MB
return (val / Math.pow(k, i)).toPrecision(3) + "" + sizes[i];
},
},
computed: {},
created() {},
mounted() {
this.getLogList();
},
methods: {
getLogList() {
this.logLoading = true;
getqueryUploadsApi()
.then((res) => {
this.tableData = res.data;
this.logLoading = false;
})
.catch((err) => {});
},
handleDeleteClick(row) {
this.$confirm("此操作将永久删除该文件, 是否继续?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
})
.then(() => {
updUploadApi({
act: "del",
id: row.id,
})
.then((res) => {
console.log(res);
this.$message({
duration: 1500,
showClose: true,
message: "文件删除成功",
type: "success",
});
this.getLogList();
})
.catch(() => {});
})
.catch(() => {});
},
},
};
</script>
<style lang="less">
.logMainClass {
height: calc(100% - 24px);
width: calc(100% - 24px);
padding: 12px;
h3 {
margin-bottom: 12px;
font-size: 16px;
line-height: 24px;
}
.boxLogTable {
height: calc(100% - 36px);
background: #fcc;
.el-table__cell {
text-align: center;
}
.el-table thead {
th.el-table__cell {
background: #fafafa;
}
}
.buttonText {
cursor: pointer;
color: #606266;
&:hover {
color: #337ab7;
text-decoration: underline;
}
}
}
}
</style>

@ -0,0 +1,212 @@
<template>
<div class="login">
<div class="loginContain">
<div class="loginMain slideInDown">
<div class="ms-login">
<h3>用户登录</h3>
<el-form
:model="userInfo"
:rules="rules"
ref="loginForm"
label-width="0px"
class="ms-content"
size="medium"
>
<el-form-item prop="userName">
<el-input v-model="userInfo.userName" placeholder="用户名">
<span slot="prepend" class="el-icon-user"></span>
</el-input>
</el-form-item>
<el-form-item prop="password">
<el-input
type="password"
placeholder="密码"
show-password
v-model="userInfo.password"
@keyup.enter.native="submitForm()"
>
<span slot="prepend" class="el-icon-lock"></span>
</el-input>
</el-form-item>
<div class="login-btn">
<el-button type="primary" @click="submitForm()"></el-button>
</div>
</el-form>
</div>
</div>
</div>
</div>
</template>
<script>
import { loginJoggle } from "@/utils/api/index";
export default {
components: {},
data: function () {
return {
userInfo: {
userName: "",
password: "",
},
rules: {
userName: [
{ required: true, message: "请输入用户名", trigger: "blur" },
],
password: [
{ required: true, message: "请输入密码", trigger: "blur" },
// { min: 6, max: 8, message: "6-8", trigger: "blur" },
],
},
token: "",
};
},
computed: {},
methods: {
submitForm() {
this.$refs.loginForm.validate((valid) => {
if (valid) {
console.log(this.userInfo);
// if (
// (this.userInfo.userName == "admin" &&
// this.userInfo.password == "shxy123456") ||
// (this.userInfo.userName == "cacuser" &&
// this.userInfo.password == "cac123456")
// ) {
// localStorage.setItem("token", "13747c96ff9f434cb09ecf78e4b9a8bc");
// this.$message({
// duration: 1500,
// showClose: true,
// message: "",
// type: "success",
// });
// this.$router.push("/");
// return;
// } else {
// this.$message({
// duration: 1500,
// showClose: true,
// message: "",
// type: "warning",
// });
// return;
// }
//
loginJoggle(this.userInfo)
.then((res) => {
if (res.res == 1) {
// this.$store.commit("SET_TOKEN", res.data.sessionId); //tokenvuex
// this.$store.commit("SET_USERINFO", res.data); //vuex
localStorage.setItem(
"token",
"13747c96ff9f434cb09ecf78e4b9a8bc"
);
console.log(res.data);
this.$router.push("/");
this.$message({
duration: 1500,
showClose: true,
message: "登录成功",
type: "success",
});
} else {
this.$message.error(res.msg);
}
})
.catch((err) => {});
} else {
this.$message.error("请输入账号和密码");
console.log("error submit!!");
return false;
}
});
},
getLogin() {},
},
created() {},
mounted() {},
};
</script>
<style lang="less">
.login {
//background: url(../../assets/loginbg.jpg) top #060c41 no-repeat;
background: linear-gradient(#141e30, #243b55);
width: 100%;
height: 100%;
background-size: inherit;
position: fixed;
display: flex;
justify-content: center;
align-items: center;
flex-wrap: nowrap;
flex-direction: column;
.loginContain {
display: flex;
justify-content: flex-end;
align-items: center;
flex-wrap: nowrap;
flex-direction: column;
margin: auto;
position: relative;
z-index: 1;
.loginMain {
width: 400px;
height: auto;
// background-color: #0c1622;
margin: 100px auto;
border-radius: 10px;
box-shadow: 0 15px 25px 0 rgba(0, 0, 0, 0.6);
padding: 40px;
box-sizing: border-box;
animation: slideInDown 0.5s;
.ms-login {
h3 {
text-align: center;
color: aliceblue;
margin-bottom: 30px;
font-family: "Courier New", Courier, monospace;
}
.ms-content {
.el-input-group__append,
.el-input-group__prepend,
.el-input__inner {
border: 0.0625rem /* 1/16 */ solid #1479ad;
background: rgba(255, 255, 255, 0.1);
border-radius: 0.25rem 0 0 0.25rem /* 4/16 */ /* 4/16 */;
color: #fff;
}
.el-input__inner {
border: 0.0625rem /* 1/16 */ solid #1479ad;
background: rgba(255, 255, 255, 0.1);
border-radius: 0rem 00.25rem 0.25rem 0rem /* 4/16 */ /* 4/16 */;
color: #fff;
}
.el-form-item {
margin-bottom: 30px;
}
.login-btn {
text-align: center;
button {
width: 100%;
height: 36px;
margin-bottom: 10px;
}
}
}
}
}
.slideInDown {
animation-name: slideInDown;
}
}
@keyframes slideInDown {
0% {
transform: translateY(-100%);
visibility: visible;
}
100% {
transform: translateY(0);
}
}
}
</style>

@ -0,0 +1,657 @@
<template>
<div class="reportBox">
<div class="commandBox">
<div class="commandRunLeft commandClass">
<div class="headTitle">
<span class="title">待下发终端</span>
<el-select
v-model="operateL"
placeholder="筛选运操维作"
@change="selectLeftChanged"
>
<el-option
v-for="item in operateOptions"
:key="item.id"
:label="item.name"
:value="item.id"
></el-option>
</el-select>
<el-input
class="cmdidClass"
v-model="leftcmdVal"
placeholder="请输入设备ID查询"
@blur="leftInputChange"
></el-input>
<span class="mlspan">命令:{{ leftCommand.length }}</span>
<span class="time"
>更新时间{{
$moment(updateTime).format("YYYY-MM-DD HH:mm:ss")
}}</span
>
<el-button
v-if="leftCommand.length > 0"
class="deletebtn"
type="danger"
icon="el-icon-delete"
@click="deleteml"
></el-button>
</div>
<div
class="commandList"
v-loading="leftComLoading"
v-if="leftCommand.length != 0"
>
<p
class="comLi"
v-for="(item, index) in leftCommand"
:key="index"
@dblclick="handleShowCommand(item)"
>
<span class="indexClass">{{ index + 1 }}</span>
<span class="comMsg"
><b>时间{{ item.createTime }}</b>
<b>设备ID{{ item.cmdid }}</b>
<b v-if="item.cmd.fileName">apk{{ item.cmd.fileName }}</b>
<b v-if="item.cmdDesc == ''">{{ cmdCn[item.cmdName] }}</b
><b v-else>{{ item.cmdDesc }}</b>
<b v-if="item.estimatedPublishTime * 1000 - newupdatatime > 0"
>命令预计拿走时间
{{
$moment(item.estimatedPublishTime * 1000).format(
"MM-DD HH:mm:ss"
)
}}
{{ remainingTime(item) }}
</b>
</span>
</p>
</div>
<div class="commandList" v-else>
<p>暂无下发命令</p>
</div>
</div>
<div class="commandRunRight commandClass">
<div class="headTitle">
<span class="title">已下发终端</span>
<el-select
v-model="operateR"
placeholder="筛选运操维作"
@change="selectRightChanged"
>
<el-option
v-for="item in operateOptions"
:key="item.id"
:label="item.name"
:value="item.id"
></el-option>
</el-select>
<el-input
class="cmdidClass"
v-model="rightcmdVal"
placeholder="请输入设备ID查询"
@blur="rightInputChange"
></el-input>
<span class="mlspan">命令:{{ rightCommand.length }}</span>
<span class="time"
>更新时间{{
$moment(updateTime).format("YYYY-MM-DD HH:mm:ss")
}}</span
>
<el-button
v-if="rightCommand.length > 0"
class="deletebtn"
type="danger"
icon="el-icon-delete"
@click="deletehis"
></el-button>
</div>
<div class="commandList" v-if="rightCommand.length != 0">
<p class="comLi" v-for="(item, index) in rightCommand" :key="index">
<el-tooltip
class="item"
effect="dark"
:open-delay="600"
:content="item.status == '1' ? '已下发' : '已取消'"
placement="top"
>
<span
class="indexClass"
:class="item.status == '1' ? 'normalClass' : 'cancelClass'"
>{{ index + 1 }}</span
>
</el-tooltip>
<span class="comMsg"
><b>下发时间{{ item.publishTime }}</b>
<b>设备ID{{ item.cmdid }}</b>
<b>命令{{ cmdCn[item.cmdName] }}</b>
<b v-if="item.cmd.fileName">apk{{ item.cmd.fileName }}</b>
<b v-else>cmd{{ item.cmd }}</b>
</span>
</p>
</div>
<div class="commandList" v-else>
<p>暂无已下发命令</p>
</div>
</div>
</div>
<el-dialog
class="MsgDialog"
title="命令信息"
:visible.sync="commandShow"
:close-on-click-modal="false"
width="680px"
>
<div class="cmdMain">
<!-- {{ deveceMsg }} -->
<p>设备ID:{{ deveceMsg.cmdid }}</p>
<p>操作时间{{ deveceMsg.createTime }}</p>
<p>待执行操作{{ deveceMsg.cmdName }}</p>
<p>cmd{{ deveceMsg.cmd }}</p>
</div>
<div slot="footer" class="dialog-footer">
<el-button @click="handleCancel(deveceMsg.id)"></el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { getdoActionApi, getqueryCmdsApi } from "@/utils/api/index";
export default {
name: "report",
components: {},
data() {
return {
leftComLoading: false, //loading
runCommand: [],
endCommand: [],
leftCommand: [],
rightCommand: [],
commandShow: false,
deveceMsg: "",
cmdCn: {
yw_cmd_android_reboot: "重启设备",
yw_cmd_mcu_reboot: "MCU单片机重启",
i1_cmd_set_i1_server_ip_port: "设置I1服务器",
i1_cmd_set_xy_yw_ip_port: "设置运维服务器",
i1_cmd_set_i1_heart_beat_time: "设置心跳周期",
yw_cmd_upload_i1_zip_log: "上传日志",
upgrade: "升级",
updOta: "Ota升级",
yw_cmd_start_frpc: "开启frpc",
yw_cmd_stop_frpc: "停止frpc",
i1_cmd_stop_aging_test: "停止老化测试",
},
cmdtimer: null,
endtimer: null,
updateTime: null,
newupdatatime: null,
//
operateOptions: [
{ id: 0, name: "全部" },
{ id: 1, name: "重启设备" },
{ id: 2, name: "MCU单片机重启" },
{ id: 3, name: "设置I1服务器" },
// { id: 4, name: "" },
{ id: 5, name: "设置心跳周期" },
{ id: 6, name: "上传日志" },
{ id: 7, name: "升级" },
{ id: 11, name: "OTA升级" },
{ id: 8, name: "开启frpc" },
{ id: 9, name: "停止frpc" },
{ id: 10, name: "停止老化测试" },
],
operateL: 0,
operateR: 0,
leftcmdVal: "",
rightcmdVal: "",
intervalId: null, // setIntervalID
};
},
computed: {},
created() {
this.cmdtimer = setInterval(this.getCmdList, 60000); // 60
this.endtimer = setInterval(this.getEndList, 60000); // 60
},
mounted() {
this.getCmdList();
this.getEndList();
this.startCountdown(); //
},
methods: {
startCountdown() {
this.newupdatatime = new Date().getTime(); //
//
if (this.intervalId) {
clearInterval(this.intervalId);
}
// remainingTime
this.intervalId = setInterval(() => {
this.newupdatatime = new Date().getTime(); //
this.leftCommand.forEach((item) => {
this.remainingTime(item); //
});
}, 1000); //
},
remainingTime(item) {
if (!this.newupdatatime) {
//
return "计算中...";
}
const estimatedPublishTime = item.estimatedPublishTime * 1000;
const difference = estimatedPublishTime - this.newupdatatime;
const minutes = Math.floor(difference / 60000);
const seconds = Math.floor((difference % 60000) / 1000);
if (minutes == 0 && seconds == 0) {
this.getCmdList();
this.getEndList();
return `命令已下发`;
} else {
return ` 预估剩余:${minutes} 分钟 ${seconds}`;
}
},
getCmdList() {
//this.leftComLoading = true;
getqueryCmdsApi({ p: 1, ps: 10000 })
.then((res) => {
console.log(res);
this.runCommand = res.data;
this.leftComLoading = false;
this.selectLeftChanged(this.operateL);
this.updateTime = new Date();
})
.catch((err) => {});
},
handleShowCommand(val) {
console.log(val);
this.commandShow = true;
console.log(this.commandShow);
this.deveceMsg = val;
},
//
handleCancel(val) {
getdoActionApi({
act: "cancel",
id: val,
})
.then((res) => {
console.log(res);
this.$confirm("确定取消该命令?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
})
.then(() => {
this.$message({
duration: 1500,
showClose: true,
message: "命令已取消",
type: "success",
});
this.commandShow = false;
this.getCmdList();
this.getEndList();
})
.catch(() => {
this.commandShow = false;
});
})
.catch((err) => {});
},
//
getEndList() {
getqueryCmdsApi({ qt: "his", p: 1, ps: 10000 })
.then((res) => {
console.log(res);
//this.endCommand = res.data;
this.endCommand = res.data.filter((item) => item.status == "1");
this.selectRightChanged(this.operateR);
// this.leftComLoading = false;
this.updateTime = new Date();
})
.catch((err) => {});
},
//
selectLeftChanged(val) {
console.log(val);
switch (val) {
case 0:
this.leftCommand = this.runCommand;
return;
case 1:
this.leftCommand = this.runCommand.filter(
(item) => item.cmdName == "yw_cmd_android_reboot"
);
return;
case 2:
this.leftCommand = this.runCommand.filter(
(item) => item.cmdName == "yw_cmd_mcu_reboot"
);
return;
case 3:
this.leftCommand = this.runCommand.filter(
(item) => item.cmdName == "i1_cmd_set_i1_server_ip_port"
);
return;
case 4:
this.leftCommand = this.runCommand.filter(
(item) => item.cmdName == "i1_cmd_set_xy_yw_ip_port"
);
return;
case 5:
this.leftCommand = this.runCommand.filter(
(item) => item.cmdName == "i1_cmd_set_i1_heart_beat_time"
);
return;
case 6:
this.leftCommand = this.runCommand.filter(
(item) => item.cmdName == "yw_cmd_upload_i1_zip_log"
);
return;
case 7:
this.leftCommand = this.runCommand.filter(
(item) => item.cmdName == "upgrade"
);
return;
case 8:
this.leftCommand = this.runCommand.filter(
(item) => item.cmdName == "yw_cmd_start_frpc"
);
return;
case 9:
this.leftCommand = this.runCommand.filter(
(item) => item.cmdName == "yw_cmd_stop_frpc"
);
return;
case 10:
this.leftCommand = this.runCommand.filter(
(item) => item.cmdName == "i1_cmd_stop_aging_test"
);
return;
case 11:
this.leftCommand = this.runCommand.filter(
(item) => item.cmdName == "updOta"
);
return;
}
},
leftInputChange() {
console.log(this.leftcmdVal);
this.leftCommand = this.runCommand.filter((item) =>
item.cmdid.includes(this.leftcmdVal)
);
},
//
selectRightChanged(val) {
console.log(val);
switch (val) {
case 0:
this.rightCommand = this.endCommand;
console.log(this.rightCommand);
return;
case 1:
this.rightCommand = this.endCommand.filter(
(item) => item.cmdName == "yw_cmd_android_reboot"
);
console.log(this.rightCommand);
return;
case 2:
this.rightCommand = this.endCommand.filter(
(item) => item.cmdName == "yw_cmd_mcu_reboot"
);
return;
case 3:
this.rightCommand = this.endCommand.filter(
(item) => item.cmdName == "i1_cmd_set_i1_server_ip_port"
);
return;
case 4:
this.rightCommand = this.endCommand.filter(
(item) => item.cmdName == "i1_cmd_set_xy_yw_ip_port"
);
return;
case 5:
this.rightCommand = this.endCommand.filter(
(item) => item.cmdName == "i1_cmd_set_i1_heart_beat_time"
);
return;
case 6:
this.rightCommand = this.endCommand.filter(
(item) => item.cmdName == "yw_cmd_upload_i1_zip_log"
);
return;
case 7:
this.rightCommand = this.endCommand.filter(
(item) => item.cmdName == "upgrade"
);
return;
case 8:
this.rightCommand = this.endCommand.filter(
(item) => item.cmdName == "yw_cmd_start_frpc"
);
return;
case 9:
this.rightCommand = this.endCommand.filter(
(item) => item.cmdName == "yw_cmd_stop_frpc"
);
return;
case 10:
this.rightCommand = this.endCommand.filter(
(item) => item.cmdName == "i1_cmd_stop_aging_test"
);
return;
case 11:
this.leftCommand = this.runCommand.filter(
(item) => item.cmdName == "updOta"
);
return;
}
},
rightInputChange() {
console.log(this.rightcmdVal);
this.rightCommand = this.endCommand.filter((item) =>
item.cmdid.includes(this.rightcmdVal)
);
},
deleteml() {
getdoActionApi({
act: "clear",
})
.then((res) => {
console.log(res);
this.$confirm("确定清除所有命令?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
})
.then(() => {
this.$message({
duration: 1500,
showClose: true,
message: "命令已清除",
type: "success",
});
this.commandShow = false;
this.getCmdList();
this.getEndList();
})
.catch(() => {
this.commandShow = false;
});
})
.catch((err) => {});
},
deletehis() {
getdoActionApi({
act: "clearHis",
})
.then((res) => {
console.log(res);
this.$confirm("确定清除所有命令?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
})
.then(() => {
this.$message({
duration: 1500,
showClose: true,
message: "命令已清除",
type: "success",
});
this.getCmdList();
this.getEndList();
})
.catch(() => {});
})
.catch((err) => {});
},
},
beforeDestroy() {
//
clearInterval(this.cmdtimer);
clearInterval(this.endtimer);
this.cmdtimer = null;
this.endtimer = null;
if (this.intervalId) {
clearInterval(this.intervalId);
}
},
};
</script>
<style lang="less">
.reportBox {
height: calc(100% - 24px);
width: calc(100% - 24px);
padding: 12px;
.commandBox {
display: flex;
height: 100%;
.commandClass {
width: 50%;
padding: 12px;
height: calc(100% - 24px);
border: 1px solid #dcdfe6;
margin-right: 12px;
border-radius: 4px;
.headTitle {
height: 40px;
line-height: 40px;
display: flex;
align-items: center;
.title {
font-size: 16px;
font-weight: normal;
}
.el-select {
margin: 0px 12px;
width: 150px;
}
.cmdidClass {
width: 180px;
}
.mlspan {
font-size: 14px;
margin-left: 8px;
}
.time {
font-size: 12px;
margin-left: 8px;
}
.deletebtn {
margin-left: auto;
padding: 4px;
}
}
.commandList {
width: 100%;
height: calc(100% - 32px);
//background: #fcc;
overflow: auto;
p {
background: #fdf6ec;
margin-bottom: 8px;
line-height: 24px;
color: #333;
font-size: 14px;
padding: 6px;
cursor: pointer;
display: flex;
align-items: center;
&:hover {
background: #faecd8;
}
.indexClass {
padding: 4px;
font-size: 14px;
color: #000;
background: #d3d3d3;
min-width: 18px;
text-align: center;
margin-right: 8px;
}
.normalClass {
background: #d3d3d3;
}
.cancelClass {
background: #fde2e2;
}
.comMsg {
display: flex;
flex-wrap: wrap;
b {
font-weight: normal;
margin-right: 12px;
}
}
}
}
}
.commandRunLeft {
}
.commandRunRight {
.commandList {
p {
cursor: default;
background: #e1f3d8;
&:hover {
background: #e1f3d8;
}
}
}
}
}
.MsgDialog {
.cmdMain {
p {
font-size: 16px;
line-height: 32px;
}
}
.dialog-footer {
display: flex;
align-items: center;
justify-content: center;
}
}
}
.el-dialog__headerbtn {
top: 18px;
.el-dialog__close {
font-size: 26px;
&:hover {
background: #e2e2e2;
}
}
}
</style>

@ -0,0 +1,414 @@
<template>
<div class="upgradationBox">
<div class="uploadForm">
<div class="upgradeBox">
<h3 class="lableBox">文件上传</h3>
<el-upload
class="upload-demo"
ref="upload"
action="/web/api/uploadFile.php"
:limit="1"
:file-list="fileList"
:data="reportData"
:on-progress="handleProgress"
:auto-upload="false"
:on-success="handleAvatarSuccess"
@before-upload="beforeAvatarUpload"
>
<el-button slot="trigger" size="small" type="primary"
>选取文件</el-button
>
</el-upload>
</div>
<div class="noteBox">
<h3 class="lableBox">文件备注</h3>
<el-input
class="noteClass"
v-model="reportData.title"
placeholder="输入备注"
></el-input>
<el-button
class="uploadBtn"
size="small"
type="primary"
@click="submitUpload"
>上传到服务器</el-button
>
</div>
</div>
<div class="uploadPressMask" v-if="progressLoading">
<div class="centerClass">
<el-progress type="circle" :percentage="progress"></el-progress>
</div>
</div>
<div class="uploadList">
<el-table
:data="fileData"
style="width: 100%"
border
stripe
height="calc(100% - 0px)"
v-loading="fileloading"
>
<el-table-column type="index" width="50" label="序号">
</el-table-column>
<el-table-column
prop="createTime"
label="创建时间"
width="180"
></el-table-column>
<el-table-column prop="fileName" label="文件名称">
<template slot-scope="scope">
<span
@dblclick="handleDblClick(scope.row.path)"
style="cursor: pointer"
>
{{ scope.row.fileName }}</span
>
</template>
</el-table-column>
<el-table-column prop="path" label="文件路径">
<template slot-scope="scope">
<span
@dblclick="handleDblClick(scope.row.path)"
style="cursor: pointer"
>
{{ scope.row.path }}</span
>
</template>
</el-table-column>
<el-table-column prop="fileSize" label="文件大小">
<template slot-scope="scope">
{{ scope.row.fileSize | changeType }}
</template>
</el-table-column>
<el-table-column prop="title" label="备注"> </el-table-column>
<!-- <el-table-column prop="path" label="文件路径"> </el-table-column> -->
<el-table-column label="操作" width="300" class-name="editClass">
<template slot-scope="scope">
<el-link
type="primary"
@click="handleEditClick(scope.row)"
size="small"
icon="el-icon-edit"
>修改</el-link
>
<el-link
type="danger"
@click="handleDeleteClick(scope.row)"
size="small"
icon="el-icon-delete"
>删除</el-link
>
</template>
</el-table-column>
</el-table>
</div>
<el-dialog
class="titleDialog"
title="修改备注"
:visible.sync="titleShow"
:close-on-click-modal="false"
width="480px"
>
<el-form
:model="ruleForm"
:rules="rules"
ref="ruleForm"
label-width="100px"
class="demo-ruleForm"
>
<el-form-item label="文件备注" prop="notesNewVal">
<el-input v-model="ruleForm.notesNewVal"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="confirmClick"></el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import {
postuploadFileApi,
getqueryUpgradesApi,
getupdUpgradeApi,
} from "@/utils/api/index";
export default {
name: "upgradation",
components: {},
data() {
return {
//apk notesVal
fileList: [],
reportData: {
title: "",
upgradeType:0,
},
fileData: [], //
fileloading: false,
editShow: false,
titleShow: false,
ruleForm: {
notesNewVal: "",
},
rules: {
notesNewVal: [
{ required: true, message: "请输入备注信息", trigger: "blur" },
],
},
rowData: "", //
progress: 0,
progressLoading: false,
};
},
filters: {
changeType(val) {
if (val == "0") return "0B";
var k = 1024;
var sizes = ["B", "KB", "MB", "GB", "TB"];
let i = Math.floor(Math.log(val) / Math.log(k)); //kB?MB
return (val / Math.pow(k, i)).toPrecision(3) + "" + sizes[i];
},
},
computed: {},
mounted() {
this.getUpgradeList();
},
methods: {
//
handleDblClick(val) {
// alert(val);
var input = document.createElement("input"); // input
input.value = val; //
document.body.appendChild(input); //
input.select(); //
document.execCommand("Copy"); //
document.body.removeChild(input); //
//this.$message.success("");
this.$message({
duration: 1500,
showClose: true,
message: "复制成功!" + val,
type: "success",
});
},
//
handleProgress(event, file, fileList) {
this.progressLoading = true;
//
if (event.percent == 100) {
this.progress = 98;
} else {
this.progress = Math.round(event.percent);
}
//
console.log(this.progress); // 使使
},
//
beforeAvatarUpload(file) {
console.log(this.reportData.title);
console.log(this.reportData.title);
console.log(file);
},
//apk
submitUpload() {
//console.log();
this.$refs.upload.submit();
},
handleAvatarSuccess(res, file) {
this.progressLoading = false;
console.log(res);
this.$message({
duration: 1500,
showClose: true,
message: "文件上传成功",
type: "success",
});
this.reportData.title = "";
this.$refs.upload.clearFiles();
this.getUpgradeList();
},
getUpgradeList() {
this.fileloading = true;
getqueryUpgradesApi()
.then((res) => {
console.log(res);
this.fileData = res.data.filter(item => item.type === "0");
this.fileloading = false;
})
.catch((err) => {});
},
handleDeleteClick(row) {
getupdUpgradeApi({
act: "del",
id: row.id,
})
.then((res) => {
console.log(res);
this.$confirm("此操作将永久删除该文件, 是否继续?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
})
.then(() => {
this.$message({
duration: 1500,
showClose: true,
message: "文件删除成功",
type: "success",
});
this.getUpgradeList();
})
.catch(() => {});
})
.catch((err) => {});
},
handleEditClick(row) {
console.log(row);
this.titleShow = true;
this.ruleForm.notesNewVal = row.title;
this.rowData = row;
},
confirmClick() {
this.$refs.ruleForm.validate((valid) => {
if (valid) {
console.log(this.ruleForm.notesNewVal);
getupdUpgradeApi({
act: "edt",
id: this.rowData.id,
title: this.ruleForm.notesNewVal,
})
.then((res) => {
console.log(res);
this.$message({
duration: 1500,
showClose: true,
message: "修改备注成功",
type: "success",
});
this.titleShow = false;
this.getUpgradeList();
})
.catch((err) => {});
} else {
console.log("error submit!!");
return false;
}
});
},
},
};
</script>
<style lang="less">
.upgradationBox {
height: calc(100% - 24px);
width: calc(100% - 24px);
padding: 12px;
.upgradeBox {
height: 32px;
line-height: 32px;
display: flex;
margin-bottom: 16px;
// align-items: center;
// flex-direction: column;
.lableBox {
font-size: 14px;
font-weight: normal;
width: 78px;
}
.upload-demo {
position: relative;
display: flex;
flex-direction: row-reverse;
margin-right: 32px;
.el-upload-list {
width: 320px;
height: 32px;
line-height: 32px;
border: 1px solid #ddd;
margin-right: 12px;
border-radius: 4px;
.el-upload-list__item {
transition: none;
font-size: 14px;
color: #606266;
position: relative;
box-sizing: border-box;
border-radius: 4px;
width: 100%;
height: 32px;
line-height: 32px;
margin-top: 0px !important;
.el-icon-close {
top: 10px;
}
}
}
}
}
.noteBox {
height: 32px;
line-height: 32px;
display: flex;
margin-bottom: 16px;
.noteClass {
width: 322px;
}
.lableBox {
font-size: 14px;
font-weight: normal;
width: 78px;
}
}
.uploadBtn {
margin-left: 12px;
}
.uploadList {
margin-top: 20px;
height: calc(100% - 100px);
.el-table {
.el-table__cell {
text-align: center;
}
}
}
.editClass {
.el-link.el-link--primary {
margin-right: 14px;
}
}
.uploadPressMask {
position: fixed;
width: 100%;
height: 100%;
background-color: hsla(0, 0%, 100%, 0.9);
margin: 0;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 3;
.centerClass {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
}
}
}
.el-dialog__headerbtn {
top: 18px;
.el-dialog__close {
font-size: 26px;
&:hover {
background: #e2e2e2;
}
}
}
</style>

@ -0,0 +1,413 @@
<template>
<div class="upgradationOta">
<div class="uploadForm">
<div class="upgradeBox">
<h3 class="lableBox">文件上传</h3>
<el-upload
class="upload-demo"
ref="upload"
action="/web/api/uploadFile.php"
:limit="1"
:file-list="fileList"
:data="reportData"
:on-progress="handleProgress"
:auto-upload="false"
:on-success="handleAvatarSuccess"
@before-upload="beforeAvatarUpload"
>
<el-button slot="trigger" size="small" type="primary"
>选取文件</el-button
>
</el-upload>
</div>
<div class="noteBox">
<h3 class="lableBox">文件备注</h3>
<el-input
class="noteClass"
v-model="reportData.title"
placeholder="输入备注"
></el-input>
<el-button
class="uploadBtn"
size="small"
type="primary"
@click="submitUpload"
>上传到服务器</el-button
>
</div>
</div>
<div class="uploadPressMask" v-if="progressLoading">
<div class="centerClass">
<el-progress type="circle" :percentage="progress"></el-progress>
</div>
</div>
<div class="uploadList">
<el-table
:data="fileData"
style="width: 100%"
border
stripe
height="calc(100% - 0px)"
v-loading="fileloading"
>
<el-table-column type="index" width="50" label="序号">
</el-table-column>
<el-table-column
prop="createTime"
label="创建时间"
width="180"
></el-table-column>
<el-table-column prop="fileName" label="文件名称">
<template slot-scope="scope">
<span
@dblclick="handleDblClick(scope.row.path)"
style="cursor: pointer"
>
{{ scope.row.fileName }}</span
>
</template>
</el-table-column>
<el-table-column prop="path" label="文件路径">
<template slot-scope="scope">
<span
@dblclick="handleDblClick(scope.row.path)"
style="cursor: pointer"
>
{{ scope.row.path }}</span
>
</template>
</el-table-column>
<el-table-column prop="fileSize" label="文件大小">
<template slot-scope="scope">
{{ scope.row.fileSize | changeType }}
</template>
</el-table-column>
<el-table-column prop="title" label="备注"> </el-table-column>
<!-- <el-table-column prop="path" label="文件路径"> </el-table-column> -->
<el-table-column label="操作" width="300" class-name="editClass">
<template slot-scope="scope">
<el-link
type="primary"
@click="handleEditClick(scope.row)"
size="small"
icon="el-icon-edit"
>修改</el-link
>
<el-link
type="danger"
@click="handleDeleteClick(scope.row)"
size="small"
icon="el-icon-delete"
>删除</el-link
>
</template>
</el-table-column>
</el-table>
</div>
<el-dialog
class="titleDialog"
title="修改备注"
:visible.sync="titleShow"
:close-on-click-modal="false"
width="480px"
>
<el-form
:model="ruleForm"
:rules="rules"
ref="ruleForm"
label-width="100px"
class="demo-ruleForm"
>
<el-form-item label="文件备注" prop="notesNewVal">
<el-input v-model="ruleForm.notesNewVal"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="confirmClick"></el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import {
postuploadFileApi,
getqueryUpgradesApi,
getupdUpgradeApi,
} from "@/utils/api/index";
export default {
name: "upgradationOta",
components: {},
data() {
return {
//apk notesVal
fileList: [],
reportData: {
title: "",
upgradeType:1,
},
fileData: [], //
fileloading: false,
editShow: false,
titleShow: false,
ruleForm: {
notesNewVal: "",
},
rules: {
notesNewVal: [
{ required: true, message: "请输入备注信息", trigger: "blur" },
],
},
rowData: "", //
progress: 0,
progressLoading: false,
};
},
filters: {
changeType(val) {
if (val == "0") return "0B";
var k = 1024;
var sizes = ["B", "KB", "MB", "GB", "TB"];
let i = Math.floor(Math.log(val) / Math.log(k)); //kB?MB
return (val / Math.pow(k, i)).toPrecision(3) + "" + sizes[i];
},
},
computed: {},
mounted() {
this.getUpgradeList();
},
methods: {
//
handleDblClick(val) {
// alert(val);
var input = document.createElement("input"); // input
input.value = val; //
document.body.appendChild(input); //
input.select(); //
document.execCommand("Copy"); //
document.body.removeChild(input); //
//this.$message.success("");
this.$message({
duration: 1500,
showClose: true,
message: "复制成功!" + val,
type: "success",
});
},
//
handleProgress(event, file, fileList) {
this.progressLoading = true;
//
if (event.percent == 100) {
this.progress = 98;
} else {
this.progress = Math.round(event.percent);
}
//
console.log(this.progress); // 使使
},
//
beforeAvatarUpload(file) {
console.log(this.reportData.title);
console.log(file);
},
//apk
submitUpload() {
//console.log();
this.$refs.upload.submit();
},
handleAvatarSuccess(res, file) {
this.progressLoading = false;
console.log(res);
this.$message({
duration: 1500,
showClose: true,
message: "文件上传成功",
type: "success",
});
this.reportData.title = "";
this.$refs.upload.clearFiles();
this.getUpgradeList();
},
getUpgradeList() {
this.fileloading = true;
getqueryUpgradesApi()
.then((res) => {
console.log(res);
this.fileData = res.data.filter(item => item.type === "1");
this.fileloading = false;
})
.catch((err) => {});
},
handleDeleteClick(row) {
getupdUpgradeApi({
act: "del",
id: row.id,
})
.then((res) => {
console.log(res);
this.$confirm("此操作将永久删除该文件, 是否继续?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
})
.then(() => {
this.$message({
duration: 1500,
showClose: true,
message: "文件删除成功",
type: "success",
});
this.getUpgradeList();
})
.catch(() => {});
})
.catch((err) => {});
},
handleEditClick(row) {
console.log(row);
this.titleShow = true;
this.ruleForm.notesNewVal = row.title;
this.rowData = row;
},
confirmClick() {
this.$refs.ruleForm.validate((valid) => {
if (valid) {
console.log(this.ruleForm.notesNewVal);
getupdUpgradeApi({
act: "edt",
id: this.rowData.id,
title: this.ruleForm.notesNewVal,
})
.then((res) => {
console.log(res);
this.$message({
duration: 1500,
showClose: true,
message: "修改备注成功",
type: "success",
});
this.titleShow = false;
this.getUpgradeList();
})
.catch((err) => {});
} else {
console.log("error submit!!");
return false;
}
});
},
},
};
</script>
<style lang="less">
.upgradationOta {
height: calc(100% - 24px);
width: calc(100% - 24px);
padding: 12px;
.upgradeBox {
height: 32px;
line-height: 32px;
display: flex;
margin-bottom: 16px;
// align-items: center;
// flex-direction: column;
.lableBox {
font-size: 14px;
font-weight: normal;
width: 78px;
}
.upload-demo {
position: relative;
display: flex;
flex-direction: row-reverse;
margin-right: 32px;
.el-upload-list {
width: 320px;
height: 32px;
line-height: 32px;
border: 1px solid #ddd;
margin-right: 12px;
border-radius: 4px;
.el-upload-list__item {
transition: none;
font-size: 14px;
color: #606266;
position: relative;
box-sizing: border-box;
border-radius: 4px;
width: 100%;
height: 32px;
line-height: 32px;
margin-top: 0px !important;
.el-icon-close {
top: 10px;
}
}
}
}
}
.noteBox {
height: 32px;
line-height: 32px;
display: flex;
margin-bottom: 16px;
.noteClass {
width: 322px;
}
.lableBox {
font-size: 14px;
font-weight: normal;
width: 78px;
}
}
.uploadBtn {
margin-left: 12px;
}
.uploadList {
margin-top: 20px;
height: calc(100% - 100px);
.el-table {
.el-table__cell {
text-align: center;
}
}
}
.editClass {
.el-link.el-link--primary {
margin-right: 14px;
}
}
.uploadPressMask {
position: fixed;
width: 100%;
height: 100%;
background-color: hsla(0, 0%, 100%, 0.9);
margin: 0;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 3;
.centerClass {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
}
}
}
.el-dialog__headerbtn {
top: 18px;
.el-dialog__close {
font-size: 26px;
&:hover {
background: #e2e2e2;
}
}
}
</style>

@ -0,0 +1,122 @@
<template>
<el-dialog
class="addUserDialog"
:title="title"
:visible.sync="isShow"
:close-on-click-modal="false"
width="470px"
@close="handleclose"
>
<el-form
label-position="left"
ref="formInfo"
label-width="100px"
:rules="rules"
:model="formdata"
>
<el-form-item label="用户名:" prop="userName">
<el-input
placeholder="请输入用户名"
v-model="formdata.userName"
autocomplete="off"
></el-input>
</el-form-item>
<el-form-item label="密码:" prop="password">
<el-input
placeholder="请输入密码"
v-model="formdata.password"
show-password
></el-input>
</el-form-item>
<el-form-item label="备注:" prop="notesNewVal">
<el-input
placeholder="请输入备注"
v-model="formdata.notesNewVal"
autocomplete="off"
></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="isShow = false"> </el-button>
<el-button type="primary" @click="submitForm()"> </el-button>
</div>
</el-dialog>
</template>
<script>
import { addUserApi, updateUserApi } from "@/utils/api/index";
export default {
props: {
title: String,
},
data() {
return {
roleUser: "",
isShow: false,
roleoptions: [
{
value: 1,
label: "管理员",
},
{
value: 2,
label: "用户",
},
],
formdata: {},
rules: {
userName: [
{ required: true, message: "请输入用户名", trigger: "blur" },
],
password: [
{ required: true, message: "请输入密码", trigger: "blur" },
// { min: 6, max: 8, message: "6-8", trigger: "blur" },
],
},
};
},
methods: {
//
getdataform(val) {
console.log(val);
},
//
submitForm() {
this.$refs.formInfo.validate((valid) => {
if (valid) {
if (this.title == "新增") {
} else {
}
} else {
console.log("error submit!!");
return false;
}
});
},
display() {
this.isShow = true;
this.roleUser = localStorage.getItem("role");
},
hide() {
this.isShow = false;
},
handleclose() {
//this.$parent.deviceList();
},
},
mounted() {},
};
</script>
<style lang="less">
.addUserDialog {
.el-form-item {
.el-input,
.el-select,
.el-input-number {
width: 100%;
}
}
}
</style>

@ -0,0 +1,131 @@
<template>
<el-dialog
class="setPermissionDialog"
title="权限管理"
:visible.sync="isShow"
:close-on-click-modal="false"
width="470px"
@close="handleclose"
>
<div class="setContain">
<p class="labeltitle">用户名{{ userinfo.name }}</p>
<el-checkbox v-model="ywchecked"
>是否可进行运维操作(<span v-if="ywchecked"></span
><span v-else></span>)</el-checkbox
>
<el-divider></el-divider>
<p class="labeltitle">活动列表权限分配</p>
<div class="activityBox">
<el-checkbox
:indeterminate="isIndeterminate"
v-model="checkAll"
@change="handleCheckAllChange"
>全选</el-checkbox
>
<el-checkbox-group
v-model="checkedCities"
@change="handleCheckedCitiesChange"
>
<el-checkbox
v-for="(item, index) in activityData"
:label="item.title"
:key="item.id"
>{{ item.title }}</el-checkbox
>
</el-checkbox-group>
</div>
</div>
<div slot="footer" class="dialog-footer">
<el-button @click="isShow = false"> </el-button>
<el-button type="primary" @click="submitForm()"> </el-button>
</div>
</el-dialog>
</template>
<script>
// import { addUserApi, updateUserApi } from "@/utils/api/index";
import { getqueryActivityApi } from "@/utils/api/index";
export default {
props: {},
data() {
return {
roleUser: "",
userinfo: "",
ywchecked: true,
isShow: false,
checkAll: false,
checkedCities: [],
isIndeterminate: false,
activityData: [],
};
},
methods: {
handleCheckAllChange(val) {
this.checkedCities = val ? activityData : [];
this.isIndeterminate = false;
},
handleCheckedCitiesChange(value) {
let checkedCount = value.length;
this.checkAll = checkedCount === this.activityData.length;
this.isIndeterminate =
checkedCount > 0 && checkedCount < this.activityData.length;
},
//
getactivityList() {
getqueryActivityApi({
act: "list",
})
.then((res) => {
console.log(res);
this.activityData = res.data;
})
.catch((err) => {});
},
//
submitForm() {
this.isShow = false;
},
display(val) {
this.isShow = true;
this.userinfo = val;
console.log(val);
this.getactivityList();
},
hide() {
this.isShow = false;
},
handleclose() {},
},
mounted() {},
};
</script>
<style lang="less">
.setPermissionDialog {
.el-dialog__body {
padding: 12px 20px;
}
.setContain {
.el-checkbox {
line-height: 32px;
}
.labeltitle {
line-height: 32px;
font-size: 14px;
margin-bottom: 8px;
}
.el-divider--horizontal {
margin: 12px 0px;
}
.activityBox {
max-height: 200px;
overflow: auto;
.el-checkbox-group {
display: flex;
flex-direction: column;
}
}
}
}
</style>

@ -0,0 +1,143 @@
<template>
<div class="userbox">
<el-button
class="addBtn"
type="primary"
icon="el-icon-plus"
@click="handleAdddevice()"
>新建用户</el-button
>
<div class="usercontain">
<el-table
v-loading="logLoading"
:data="userData"
border
stripe
style="width: 100%"
height="100%"
>
<el-table-column type="index" width="50" label="序号">
</el-table-column>
<el-table-column prop="name" label="用户名"> </el-table-column>
<el-table-column prop="mark" label="备注"> </el-table-column>
<el-table-column prop="updateTime" label="创建时间"> </el-table-column>
<el-table-column label="操作" class-name="editClass">
<template slot-scope="scope">
<el-link
type="primary"
@click="handleSetClick(scope.row)"
size="small"
icon="el-icon-setting"
>设置权限</el-link
>
<el-link
type="primary"
@click="handleEditClick(scope.row)"
size="small"
icon="el-icon-document"
>修改</el-link
>
<el-link
type="danger"
@click="handleDeleteClick(scope.row)"
size="small"
icon="el-icon-delete"
>删除</el-link
>
</template>
</el-table-column>
</el-table>
</div>
<addEditDialog :title="title" ref="adduserref"></addEditDialog>
<setPermission ref="setpermissionRef"></setPermission>
</div>
</template>
<script>
// import { getqueryUploadsApi } from "@/utils/api/index";
import addEditDialog from "./components/addEditDialog.vue";
import setPermission from "./components/setPermission.vue";
export default {
name: "userlist",
components: {
addEditDialog,
setPermission,
},
data() {
return {
title: "", //
page: 1, //
pageSize: 20, //
total: 0, //
logLoading: false,
userData: [
{ name: "用户1", mark: "xxxxx", updateTime: "2023-12-25 10:20:30" },
{ name: "用户2", mark: "xxxxx", updateTime: "2023-12-25 10:20:30" },
{ name: "用户3", mark: "xxxxx", updateTime: "2023-12-25 10:20:30" },
],
};
},
computed: {},
created() {},
mounted() {},
methods: {
//
handleAdddevice() {
this.title = "修改";
this.$refs.adduserref.display();
this.$refs.adduserref.getdataform(data);
},
//
handleSetClick(data) {
this.$refs.setpermissionRef.display(data);
},
//
handleEditClick() {
this.title = "修改";
this.$refs.adduserref.display();
this.$refs.adduserref.getdataform(data);
},
//
handleDeleteClick() {
this.$confirm("确定要删除该用户?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
})
.then(() => {})
.catch(() => {});
},
},
};
</script>
<style lang="less">
.userbox {
height: calc(100% - 24px);
width: calc(100% - 24px);
padding: 12px;
.addBtn {
display: flex;
margin-left: auto;
margin-bottom: 12px;
}
.usercontain {
height: calc(100% - 44px);
background: #fcc;
.el-table__cell {
text-align: center;
}
.el-table thead {
th.el-table__cell {
background: #fafafa;
}
}
.editClass {
.el-link.el-link--primary {
margin-right: 14px;
}
}
}
}
</style>

@ -0,0 +1,31 @@
const { defineConfig } = require("@vue/cli-service");
module.exports = defineConfig({
//打包清除console
// chainWebpack(config) {
// config.optimization.minimizer("terser").tap((args) => {
// args[0].terserOptions.compress.drop_console = true;
// return args;
// });
// },
productionSourceMap: false, // 生产环境是否要生成 sourceMap
publicPath: process.env.PUBLIC_PATH ? process.env.PUBLIC_PATH : "./", // 部署应用包时的基本 URL
// assetsPublicPath: process.env.NODE_ENV === "production" ? "" : "/",
outputDir: "dist", // 打包时输出的文件目录
assetsDir: "static", // 放置静态文件夹目录
transpileDependencies: true,
lintOnSave: false,
devServer: {
port: 1234, // 端口号的配置
proxy: {
"/api": {
//表示拦截以/api开头的请求路径
target: "http://61.169.135.146:40101/", //
changOrigin: true, //是否开启跨域
pathRewrite: {
"^/api": "/api", //重写api把api变成空字符因为我们真正请求的路径是没有api的
},
},
},
},
});
Loading…
Cancel
Save