运维主站

master
fanluyan 2 years ago
parent d9b434f87d
commit 4b85bb8130

28
.gitignore vendored

@ -1,11 +1,23 @@
# ---> Vue .DS_Store
# gitignore template for Vue.js projects node_modules
# /dist
# Recommended template: Node.gitignore
# TODO: where does this rule come from?
docs/_book
# TODO: where does this rule come from? # local env files
test/ .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?

@ -0,0 +1,5 @@
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}

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

9168
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -0,0 +1,57 @@
{
"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",
"moment": "^2.29.4",
"postcss-px2rem": "^0.3.0",
"px2rem-loader": "^0.1.9",
"three": "^0.158.0",
"vue": "^2.6.14",
"vue-router": "^3.5.1",
"vuex": "^3.6.2"
},
"devDependencies": {
"@babel/core": "^7.12.16",
"@babel/eslint-parser": "^7.12.16",
"@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,17 @@
<!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,103 @@
<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;
}
</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: #337ab7;
}
}
.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: #337ab7;
}
.el-tabs--border-card
> .el-tabs__header
.el-tabs__item:not(.is-disabled):hover {
color: #fff;
background-color: #337ab7;
}
.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,74 @@
<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",
},
],
};
},
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: #6de1ff;
background-image: url(../assets/menu.png);
height: 40px;
line-height: 40px;
padding: 0 12px;
background-size: 100% 100%;
background-repeat: no-repeat;
overflow: hidden;
}
}
}
}
</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: rgba(24, 75, 112, 1);
-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: #66e6ff;
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,47 @@
import Vue from "vue";
import App from "./App.vue";
import router from "./router";
import store from "./store";
import ElementUI from "element-ui";
// 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;
//使用钩子函数对路由进行权限跳转
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,63 @@
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,
},
},
],
},
];
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,112 @@
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 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 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 getdelUpgradeApi(data) {
return request({
url: "api/delUpgrade.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,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,154 @@
<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="时间"
width="180"
></el-table-column>
<el-table-column prop="content" label="接收消息" class-name="msgClass">
<template slot-scope="scope">
<el-tooltip popper-class="msgTootip" placement="top" effect="light">
<!-- <div slot="content">
<p v-for="(value, key) in JSON.parse(scope.row.content)">
{{ key }}{{ value }}
</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
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: 1024px;
height: 632px;
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;
}
</style>

File diff suppressed because it is too large Load Diff

@ -0,0 +1,438 @@
<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>
</div>
<div class="bottomSearch">
<el-form-item label="出厂ID" class="oidbox">
<el-input
v-model="formdata.oidInput"
placeholder="请输入出厂ID"
clearable
></el-input>
</el-tooltip>
<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="toggleClass"
: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% - 102px)' : 'calc(100% - 2px)' }"
>
<tableMain :tableData="dataList" :onlineNum="onlineNum" :offlineNum="offlineNum" :noPicNum="noPicNum" v-loading="tableLoaidng"></tableMain>
</div>
</div>
</template>
<script>
import { getqueryLineApi, getqueryTermsApi } 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,
oidInput: "",
oidCheck: 0,
cmdidInput: "",
cmdidCheck: 0,
cmaInput: "",
cmaCheck: 0,
versionInput: "",
versionCheck: 0,
},
dataList: [],
tableLoaidng: false,
onlineNum: "", //线
offlineNum: "", //线
noPicNum:'',//
};
},
created() {
var that = this;
document.onkeydown = function (e) {
var key = window.event.keyCode;
if (key === 13) {
that.onSubmit(); //
}
};
//this.fetchData(); //
setInterval(this.fetchData, 60000); // 10
},
mounted() {
this.getLineList();
this.onSubmit();
},
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) => {});
},
onSubmit() {
this.tableLoaidng = true;
getqueryTermsApi({
lineId: this.formdata.lineId,
towerId: this.formdata.towerId,
isonLine: this.formdata.isonline,
fc: 4,
fn1: "oid",
fv1: this.formdata.oidInput,
frev1: this.formdata.oidCheck,
fn2: "cmdid",
fv2: this.formdata.cmdidInput,
frev2: this.formdata.cmdidCheck,
fn3: "cma",
fv3: this.formdata.cmaInput,
frev3: this.formdata.cmaCheck,
fn4: "version",
fv4: this.formdata.versionInput,
frev4: this.formdata.versionCheck,
})
.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.tableLoaidng = false;
})
.catch((err) => {});
},
fetchData() {
getqueryTermsApi({
lineId: this.formdata.lineId,
towerId: this.formdata.towerId,
isonLine: this.formdata.isonline,
fc: 4,
fn1: "oid",
fv1: this.formdata.oidInput,
frev1: this.formdata.oidCheck,
fn2: "cmdid",
fv2: this.formdata.cmdidInput,
frev2: this.formdata.cmdidCheck,
fn3: "cma",
fv3: this.formdata.cmaInput,
frev3: this.formdata.cmaCheck,
fn4: "version",
fv4: this.formdata.versionInput,
frev4: this.formdata.versionCheck,
})
.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
})
.catch((err) => {});
},
//
onReset() {
this.formdata = {
lineId: 0,
towerId: 0,
isonline: -1,
oidInput: "",
oidCheck: false,
cmdidInput: "",
cmdidCheck: false,
cmaInput: "",
cmaCheck: false,
versionInput: "",
versionCheck: false,
};
this.onSubmit();
},
//
toggleDiv() {
this.showDiv = !this.showDiv; // showDiv
},
},
};
</script>
<style lang="less">
.homeBox {
height: calc(100% - 24px);
width: calc(100% - 24px);
padding: 12px;
.filterBox {
position: relative;
.el-form {
display: flex;
// align-items: center;
// flex-wrap: wrap;
flex-direction: column;
.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;
}
}
}
.isonLineClass {
.el-select {
width: 80px;
}
}
.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;
}
}
}
.el-form-item__label,
.el-checkbox {
color: #333;
}
}
.toggleClass {
position: absolute;
right: 0px;
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 .el-dialog__close{
font-size:20px;
&:hover{
background:#e2e2e2;
}
}
</style>

@ -0,0 +1,105 @@
<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 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 prop="file_name" label="文件名">
<template slot-scope="scope">
<a
:href="'/dl/?id=' + scope.row.id"
target="_blank"
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>
</div>
</div>
</template>
<script>
import { getqueryUploadsApi } from "@/utils/api/index";
export default {
name: "log",
components: {},
data() {
return {
tableData: [],
logLoading: false,
};
},
filters: {
changeType(val) {
if (val == "0") return "0B";
var k = 1024;
var sizes = ["B", "KB", "MB", "GB", "TB"];
console.log("Math.log(val)", Math.log(val));
console.log("Math.log(k)", Math.log(k));
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) => {});
},
},
};
</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 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,206 @@
<template>
<div class="reportBox">
<div class="commandBox">
<div class="commandRunLeft commandClass">
<h3>待下发终端</h3>
<div class="commandList" v-loading="leftComLoading">
<p
class="comLi"
v-for="(item, index) in runCommand"
:key="index"
@click="handleShowCommand(item)"
>
<span class="indexClass">{{ index + 1 }}</span>
<span class="comMsg"
><b>时间{{ item.createTime }}</b>
<b>设备ID{{ item.cmdid }}</b>
<b>命令{{ item.cmdName }}</b></span
>
</p>
</div>
</div>
<div class="commandRunRight commandClass">
<h3>已下发终端</h3>
<div class="commandList">
<p class="comLi" v-for="(item, index) in endCommand" :key="index">
{{ item }}
</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>
</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: [
{
name: "我是已完成的列表",
id: 1,
},
{
name: "我是已完成的列表",
id: 2,
},
{
name: "我是已完成的列表",
id: 3,
},
{
name: "我是已完成的列表",
id: 4,
},
],
commandShow: false,
deveceMsg: "",
};
},
computed: {},
mounted() {
// setInterval(this.getCmdList(), 1000); // 10
this.getCmdList();
},
methods: {
getCmdList() {
this.leftComLoading = true;
getqueryCmdsApi({ p: 1, ps: 200 })
.then((res) => {
console.log(res);
this.runCommand = res.data;
this.leftComLoading = false;
})
.catch((err) => {});
},
handleShowCommand(val) {
console.log(val);
this.commandShow = true;
console.log(this.commandShow);
this.deveceMsg = val;
},
//
handleCancel(val) {
getdoActionApi({
action: "cancel",
id: val,
})
.then((res) => {
console.log(res);
this.commandShow = false;
this.getCmdList();
})
.catch((err) => {});
},
},
created() {},
};
</script>
<style lang="less">
.reportBox {
height: calc(100% - 24px);
width: calc(100% - 24px);
padding: 12px;
.commandBox {
display: flex;
height: 100%;
.commandClass {
width: 40%;
padding: 12px;
height: calc(100% - 24px);
border: 1px solid #dcdfe6;
margin-right: 12px;
border-radius: 4px;
h3 {
font-size: 16px;
font-weight: normal;
height: 32px;
line-height: 32px;
}
.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;
}
.comMsg {
display: flex;
flex-wrap: wrap;
b {
font-weight: normal;
margin-right: 12px;
}
}
}
}
}
.commandRunLeft {
}
.commandRunRight {
.commandList {
p {
background: rgb(225, 243, 216);
&:hover {
background: rgb(225, 243, 216);
}
}
}
}
}
.MsgDialog {
.cmdMain {
p {
font-size: 16px;
line-height: 32px;
}
}
.dialog-footer {
display: flex;
align-items: center;
justify-content: center;
}
}
}
</style>

@ -0,0 +1,237 @@
<template>
<div class="upgradationBox">
<div class="uploadForm">
<div class="noteBox">
<h3 class="lableBox">文件备注</h3>
<el-input
class="noteClass"
v-model="reportData.title"
placeholder="输入备注"
></el-input>
</div>
<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"
:auto-upload="false"
:on-success="handleAvatarSuccess"
@before-upload="beforeAvatarUpload"
>
<el-button slot="trigger" size="small" type="primary"
>选取文件</el-button
>
</el-upload>
</div>
<el-button
class="uploadBtn"
size="small"
type="primary"
@click="submitUpload"
>上传到服务器</el-button
>
</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="文件名称"> </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="100">
<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 {
postuploadFileApi,
getqueryUpgradesApi,
getdelUpgradeApi,
} from "@/utils/api/index";
export default {
name: "upgradation",
components: {},
data() {
return {
//apk notesVal
fileList: [],
reportData: {
title: "",
},
fileData: [], //
fileloading: false,
};
},
computed: {},
mounted() {
this.getUpgradeList();
},
methods: {
//
beforeAvatarUpload(file) {
console.log(this.reportData.title);
console.log(file);
},
//apk
submitUpload() {
//console.log();
this.$refs.upload.submit();
},
handleAvatarSuccess(res, file) {
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;
this.fileloading = false;
})
.catch((err) => {});
},
handleDeleteClick(row) {
getdelUpgradeApi({
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(() => {
this.$message({
type: "info",
showClose: true,
message: "已取消删除",
});
});
})
.catch((err) => {});
},
},
};
</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: 78px;
}
.uploadList {
margin-top: 20px;
height: calc(100% - 150px);
.el-table {
.el-table__cell {
text-align: center;
}
}
}
}
</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://180.166.218.222:40102/", //
changOrigin: true, //是否开启跨域
pathRewrite: {
"^/api": "/api", //重写api把api变成空字符因为我们真正请求的路径是没有api的
},
},
},
},
});
Loading…
Cancel
Save