浏览代码

完善功能,增加项目管理

yangxiaokun 3 年之前
父节点
当前提交
e1a856b226

+ 2 - 2
public/index.html

@@ -4,9 +4,9 @@
 		<meta charset="utf-8">
 		<meta http-equiv="X-UA-Compatible" content="IE=edge">
 		<meta name="viewport" content="width=device-width,initial-scale=1.0">
-		<title>Tools</title>
+		<title>BMS</title>
 		<link rel="stylesheet" href="static/css/common.css">
-		<script type="text/javascript" src="https://webapi.amap.com/maps?v=1.4.15&key=ddbf8bc912a1c79be34e7d646f8fd726"></script>
+		<!-- <script type="text/javascript" src="https://webapi.amap.com/maps?v=1.4.15&key=ddbf8bc912a1c79be34e7d646f8fd726"></script> -->
 	</head>
 	<body>
 		<div id="app"></div>

+ 33 - 46
src/router/index.js

@@ -1,56 +1,43 @@
 import {
-    createRouter,
-    createWebHashHistory
+	createRouter,
+	createWebHashHistory
 } from 'vue-router'
 import Login from "../views/login/login";
 import Layout from "../views/layout/layout";
-import Users from "../views/system/users.vue";
-import Devices from "../views/devices/devices";
-import Map from "../views/map/map";
-import Set from "../views/devices/set";
-import MqttLogs from "../views/devices/logs.vue";
+import PrivApply from "../views/system/privApply";
+import Logs from "../views/monitor/logs";
+import Item from "../views/system/item";
 
 const routes = [{
-    path: "/",
-    name: "Layout",
-    component: Layout,
-    children: [
-        {
-            path: "/users",
-            name: "Users",
-            component: Users
-        },
-        {
-            path: "/devices",
-            name: "Devices",
-            component: Devices
-        },
-        {
-            path: "/map",
-            name: "Map",
-            component: Map
-        },
-        {
-            path: "/logs",
-            name: "MqttLogs",
-            component: MqttLogs
-        },
-        {
-            path: "/set/:id",
-            name: "Set",
-            component: Set
-        }
-    ]
-},
-    {
-        path: "/login",
-        name: "Login",
-        component: Login,
-    }
+		path: "/",
+		name: "Layout",
+		component: Layout,
+		children: [{
+				path: "/apply",
+				name: "PrivApply",
+				component: PrivApply
+			},
+			{
+				path: "/logs",
+				name: "Logs",
+				component: Logs
+			},
+			{
+				path: "/items",
+				name: "Item",
+				component: Item
+			}
+		]
+	},
+	{
+		path: "/login",
+		name: "Login",
+		component: Login,
+	}
 ];
 const router = createRouter({
-    history: createWebHashHistory(),
-    routes
+	history: createWebHashHistory(),
+	routes
 });
 
-export default router
+export default router

+ 27 - 35
src/static/js/axiosCfg.js

@@ -1,26 +1,19 @@
 //Http配置
 import Axios from 'axios'
 import {
-    ElMessage
+	ElMessage
 } from 'element-plus'
 import router from "../../router"
 import TokenManager from "./token"
-
-// Axios.defaults.timeout = 10000; // 超时时间
-Axios.defaults.headers['verify'] = 'omp'; // 验证
+Axios.defaults.headers['channel'] = 'bms';
 
 /**
  * 拦截http请求
  */
 Axios.interceptors.request.use(config => {
-    // 判断是否存在token,如果存在的话,则每个http header都加上token
-    try {
-        const obj = JSON.parse(TokenManager.getToken());
-        config.headers['token'] = obj.token;
-    } catch {
-        return config;
-    }
-    return config;
+	const tokenStr = TokenManager.getToken();
+	if (tokenStr != null) config.headers['token'] = JSON.parse(TokenManager.getToken()).token;
+	return config;
 });
 
 
@@ -28,27 +21,26 @@ Axios.interceptors.request.use(config => {
  * 拦截http响应
  */
 Axios.interceptors.response.use(res => {
-    switch (res.data.status) { //状态码
-        case 200:
-            return Promise.resolve(res.data);
-        case 300: //警告
-            ElMessage.error(res.data.msg);
-            break;
-        case 401: //权限不足
-            ElMessage.error("请先登录");
-            router.replace("/login");
-            break;
-        case 500: //服务器错误
-            ElMessage.error("服务器开小差了");
-            break;
-        default://无状态码
-            ElMessage.error("请求状态异常");
-            break;
-    }
-    return Promise.reject(res.data);
-}, error => {
-    ElMessage.error("请求异常");
-    return Promise.reject(error);
-});
-
+		switch (res.data.status) { //状态码
+			case 200:
+				return res.data;
+			case 300: //警告
+				ElMessage.error(res.data.msg);
+				break;
+			case 400: //无权限
+				router.replace("/login");
+				break;
+			case 500: //服务器错误
+				ElMessage.error("服务器开小差了");
+				break;
+			default: //无状态码
+				ElMessage.error("请求状态异常");
+				break;
+		}
+		throw "stop";
+	},
+	error => {
+		console.log(error);
+		throw "stop";
+	});
 export default Axios

+ 31 - 34
src/static/js/global.js

@@ -1,44 +1,41 @@
-const server = "http://localhost:8081/omp/api/pc/";
-// const server = "https://www.mang406.top/omp/api/pc/";
+const server = "http://localhost:8081/bms/api/operate/";
 
 const URL = {
 	//登录
 	login: server + "admin/login.do",
-	//验证token信息
-	verify: server + "admin/verify.do",
-	//获取用户列表
-	getUserList: server + "user/listPage.do",
-	//获取设备列表
-	getDeviceList: server + "device/listPage.do",
 
-	getLatestLocation: server + "location/getLatestLocation.do",
-
-	//查询mqtt日志
-	getMqttLogs: server + "logs/listPage.do",
-	//查询所有的指令
-	getAllInstruction: server + "logs/getInstruction.do",
-
-	//查询基本设置
-	getBaseSet: server + "set/baseSet.do",
-	//查询设备详情
-	getDeviceDetail: server + "device/getDetailByClientId.do",
-
-	//设置音量
-	setVolume: server + "set/volume.do",
-	//设置定位频率
-	setGpsRate: server + "set/gpsRate.do",
-	//自动接听
-	setAutoAnswer: server + "set/autoAnswer.do",
-	//持续定位
-	setContinue: server + "set/continue.do",
-	//发送消息
-	setNews: server + "set/news.do",
-	//紧急呼叫
-	setSos: server + "set/sos.do",
+	//权限申请
+	privilegeApply: {
+		//列表
+		listPage: server + "privilegeApply/listPage.do",
+		//提交审核
+		audit: server + "privilegeApply/audit.do",
+		//获取某用户没有权限的设备组
+		getNoPrivGroups: server + "privilegeApply/getNoPrivGroups.do",
+	},
+	//mqtt日志
+	logs: {
+		//列表
+		listPage: server + "logs/listPage.do",
+		//全部指令
+		instructions: server + "logs/getAllInstruction.do",
+	},
+	//项目管理
+	item: {
+		//列表
+		listPage: server + "item/listPage.do",
+		//增
+		save: server + "item/save.do",
+		//禁用
+		forbidden: server + "item/forbidden.do",
+		//启用
+		permit: server + "item/permit.do",
+		//更新
+		update: server + "item/update.do",
+	},
 
 	//webSocket 地址
-	// webSocket: "wss://www.mang406.top/webSocket/",
-	webSocket: "ws://localhost:8081/webSocket/",
+	webSocket: "wss://www.mang406.top/webSocket/",
 };
 
 export default {

+ 4 - 6
src/static/js/http.js

@@ -13,7 +13,6 @@ function openLoad() {
 	//打开加载框
 	loading = ElLoading.service({
 		text: "正在加载",
-		target: document.querySelector("#loading-area")
 	});
 }
 
@@ -53,15 +52,14 @@ let Http = {
 		openLoad();
 		//请求数据
 		return new Promise((resolve, reject) => {
-			Axios.get(url, {
-					params: data
-				})
+			Axios.get(url, {params: data})
 				.then(res => {
 					resolve(res);
 				})
-				.catch(res => {})
+				.catch(res => {
+					console.log(res)
+				})
 				.finally(() => {
-					//关闭加载框
 					closeLoad();
 				})
 		});

+ 3 - 17
src/static/js/token.js

@@ -3,35 +3,21 @@ const TokenManager = {
 	 * localStorage 存放token
 	 */
 	setToken: function(tokenAndName) {
-		window.localStorage.setItem("token", JSON.stringify(tokenAndName));
+		window.localStorage.setItem("BMS_TOKEN", JSON.stringify(tokenAndName));
 	},
 
 	/**
 	 * 获取Token
 	 */
 	getToken: function() {
-		return window.localStorage.getItem("token");
+		return window.localStorage.getItem("BMS_TOKEN");
 	},
 
 	/**
 	 * 注销登录
 	 */
 	removeToken: function() {
-		window.localStorage.removeItem("token");
-	},
-	
-	/**
-	 * 是否验证过token信息
-	 */
-	setVerify: function() {
-		window.sessionStorage.setItem("verify", "1");
-	},
-	
-	/**
-	 * 查看是否验证过token信息
-	 */
-	getVerify: function() {
-		return sessionStorage.getItem("verify");
+		window.localStorage.removeItem("BMS_TOKEN");
 	}
 };
 export default TokenManager;

+ 0 - 139
src/views/devices/devices.vue

@@ -1,139 +0,0 @@
-<template>
-    <div class="zy-template">
-        <div class="zy-module">
-            <el-form :model="query" label-width="60px">
-                <el-form-item label="设备码" class="zy-search-form-item">
-                    <el-input v-model="query.num" size="mini"></el-input>
-                </el-form-item>
-                <el-form-item label="状态" class="zy-search-form-item">
-                    <el-select v-model="query.status" size="mini" placeholder=" ">
-                        <el-option label="全部" value="-1"/>
-                        <el-option label="在线" value="1"/>
-                        <el-option label="离线" value="0"/>
-                    </el-select>
-                </el-form-item>
-                <el-button type="primary" size="mini" @click="submit">查询</el-button>
-            </el-form>
-        </div>
-
-        <div class="zy-module">
-            <el-table :data="page.records" stripe header-cell-class-name="zy-table-header-cell"
-                      cell-class-name='zy-table-cell'>
-                <el-table-column prop="deviceNum" label="设备码" width="180" fixed/>
-                <el-table-column prop="deviceId" label="MQTT-clientId" width="300" fixed/>
-                <el-table-column label="状态" width="100">
-                    <template #default="scope">
-                        <span :class="scope.row.status===1?'green':'red'">{{scope.row.status ===1?'在线':'离线'}}</span>
-                    </template>
-                </el-table-column>
-                <el-table-column prop="lastOnlineTime" label="最后一次在线时间" width="180"/>
-                <el-table-column prop="batteryNum" label="电量" width="100"/>
-                <el-table-column prop="signalNum" label="信号" width="100"/>
-                <el-table-column prop="lon" label="经度" width="150"/>
-                <el-table-column prop="lat" label="纬度" width="150"/>
-                <el-table-column prop="num" label="收星颗数" width="100"/>
-                <el-table-column label="定位模式" width="100">
-                    <template #default="scope">
-                        {{scope.row.mode ===1?'北斗定位':(scope.row.mode===2?"基站定位":'GPS定位')}}
-                    </template>
-                </el-table-column>
-                <el-table-column prop="uploadTime" label="定位时间" width="180"/>
-                <el-table-column prop="site" label="逆地理位置" width="400"/>
-                <el-table-column prop="createTime" label="创建时间" width="180"/>
-                <el-table-column label="操作" width="100" fixed="right">
-                    <template #default="scope">
-                        <el-button @click="handleSet(scope.row.deviceId)" type="text" size="small">调试</el-button>
-                    </template>
-                </el-table-column>
-            </el-table>
-
-            <el-pagination class="zy-table-pagination" background layout="prev, pager, next"
-                           :current-page="page.current"
-                           :total="page.total" :page-size="page.size" @current-change="pagination"/>
-        </div>
-
-    </div>
-</template>
-
-<script>
-    export default {
-        data() {
-            return {
-                query: {
-                    num: '',
-                    status: ''
-                },
-                page: {
-                    current: 1,
-                    size: 20,
-                },
-            };
-        },
-
-        mounted() {
-            this.getDeviceList();
-        },
-
-        methods: {
-            /**
-             * 提交查询条件
-             */
-            submit: function () {
-                const params = {
-                    num: this.query.num,
-                    status: this.query.status,
-                    current: 1,
-                    size: this.page.size,
-                };
-                this.getDeviceList(params);
-            },
-
-            /**
-             * 分页点击事件
-             */
-            pagination: function (current) {
-                const params = {
-                    num: this.query.num,
-                    status: this.query.status,
-                    current: current,
-                    size: this.page.size,
-                };
-                this.getDeviceList(params);
-            },
-
-            /**
-             * 获取设备列表
-             */
-            getDeviceList: function (params) {
-                const that = this;
-                this.$http.Post(this.$global.getDeviceList, params).then(res => {
-                    console.log(res.data);
-                    that.page = res.data;
-                })
-            },
-
-            /**
-             * 跳转至设置页面
-             */
-            handleSet: function (deviceId) {
-                this.$router.push({
-                    path: "/set/" + deviceId,
-                });
-            }
-        }
-    };
-</script>
-
-<style lang="scss" scoped>
-    .zy-template {
-        width: 100%;
-
-        &_table {
-            border-radius: 5px;
-            width: 100%;
-            background: white;
-            box-sizing: border-box;
-            padding: 20px;
-        }
-    }
-</style>

+ 0 - 135
src/views/devices/logs.vue

@@ -1,135 +0,0 @@
-<template>
-    <div class="zy-template">
-        <div class="zy-module">
-            <el-form ref="form" :model="query" label-width="60px">
-                <el-form-item label="设备ID:" class="zy-search-form-item">
-                    <el-input v-model="query.deviceId" size="mini" clearable></el-input>
-                </el-form-item>
-
-                <el-form-item label="类型:" class="zy-search-form-item">
-                    <el-select v-model="query.tag" size="mini" value="" clearable>
-                        <el-option value="1" label="发送(服务器)"/>
-                        <el-option value="0" label="接收(服务器)"/>
-                    </el-select>
-                </el-form-item>
-
-                <el-form-item label="指令:" class="zy-search-form-item">
-                    <el-select v-model="query.instruction" size="mini" value="" clearable>
-                        <el-option :value="item.id" :label="item.val" v-for="item in instructionList"/>
-                    </el-select>
-                </el-form-item>
-
-                <el-button type="primary" size="mini" @click="submit">查询</el-button>
-            </el-form>
-        </div>
-
-        <div class="zy-module">
-            <el-table :data="page.records" stripe header-cell-class-name="zy-table-header-cell"
-                      cell-class-name='zy-table-cell'>
-
-                <el-table-column prop="deviceId" label="设备ID" width="270" min-width="10%"/>
-                <el-table-column prop="tag" label="类型" width="60" min-width="10%">
-                    <template #default="scope">{{scope.row.tag===0?'接收':'发送'}}</template>
-                </el-table-column>
-                <el-table-column label="指令" width="60" min-width="10%">
-                    <template #default="scope">
-                        <el-tooltip effect="dark" :content="mapInstruction(scope.row.instruction)" placement="right">
-                            <div>{{scope.row.instruction}}</div>
-                        </el-tooltip>
-                    </template>
-                </el-table-column>
-                <el-table-column prop="content" label="内容" min-width="10%"/>
-                <el-table-column prop="createTime" label="时间" width="150"/>
-            </el-table>
-
-            <el-pagination class="zy-table-pagination" background layout="prev, pager, next"
-                           :current-page="page.current"
-                           :total="page.total" :page-size="page.size" @current-change="pagination"/>
-        </div>
-
-    </div>
-</template>
-
-<script>
-    export default {
-        data() {
-            return {
-                query: {
-                    deviceId: "",
-                    tag: null,
-                    instruction: null
-                },
-                page: {
-                    current: 1,
-                    size: 20,
-                },
-                instructionMap: {},//指令对应Map
-                instructionList: [],//指令对应集合
-            };
-        },
-        mounted() {
-            this.getListPage();
-            this.getAllInstruction();
-        },
-        methods: {
-            /**
-             * 提交查询条件
-             */
-            submit: function () {
-                const param = {
-                    current: 1,
-                    size: this.page.size,
-                    deviceId: this.query.deviceId,
-                    tag: this.query.tag,
-                    instruction: this.query.instruction,
-                };
-                this.getListPage(param);
-            },
-            /**
-             * 分页点击事件
-             */
-            pagination: function (current) {
-                const param = {
-                    current: current,
-                    size: this.page.size,
-                    deviceId: this.query.deviceId,
-                    tag: this.query.tag,
-                    instruction: this.query.instruction,
-                };
-                this.getListPage(param);
-            },
-
-            /**
-             * 获取日志列表
-             */
-            getListPage: function (params) {
-                this.$http.Post(this.$global.getMqttLogs, params).then(res => {
-                    console.log(res.data);
-                    this.page = res.data;
-                })
-            },
-            /**
-             * 获取日志列表
-             */
-            getAllInstruction: function () {
-                this.$http.Get(this.$global.getAllInstruction, {}).then(res => {
-                    this.instructionMap = res.data;
-                    let arr = [];
-                    for (let key  in  res.data) {
-                        arr.push({id: key, val: res.data[key]});
-                    }
-                    this.instructionList = arr;
-                })
-            },
-            /**
-             * 映射指令集
-             */
-            mapInstruction: function (key) {
-                return this.instructionMap[key]
-            }
-        }
-    };
-</script>
-
-<style lang="scss">
-</style>

+ 134 - 118
src/views/layout/layout.vue

@@ -1,139 +1,155 @@
 <template>
-    <el-container class="container">
-        <el-aside width="200px">
-            <div class="logo">
-                <img src="./static/logo.png" alt="logo">
-            </div>
-            <el-menu default-active="1" class="el-menu-vertical-demo" background-color="#141b2e" text-color="#E4ECFF">
-                <el-submenu index="1">
-                    <template #title><i class="el-icon-monitor"></i>设备管理</template>
-                    <router-link to="/map">
-                        <el-menu-item index="1-1">位置分布</el-menu-item>
-                    </router-link>
-                    <router-link to="/devices">
-                        <el-menu-item index="1-2">设备列表</el-menu-item>
-                    </router-link>
-                    <router-link to="/logs">
-                        <el-menu-item index="1-3">消息日志</el-menu-item>
-                    </router-link>
-                </el-submenu>
+	<el-container class="container">
+		<el-aside width="200px">
+			<div class="logo">
+				<img src="./static/logo.png" alt="logo">
+			</div>
+			<el-menu default-active="1" background-color="#141B2E" text-color="#E4ECFF">
+				<!-- 				<el-submenu index="1">
+					<template #title><i class="el-icon-monitor"></i>设备管理</template>
+					<router-link to="/map">
+						<el-menu-item index="1-1">位置分布</el-menu-item>
+					</router-link>
+					<router-link to="/devices">
+						<el-menu-item index="1-2">设备列表</el-menu-item>
+					</router-link>
+					<router-link to="/logs">
+						<el-menu-item index="1-3">消息日志</el-menu-item>
+					</router-link>
+				</el-submenu> -->
 
-                <el-submenu index="2">
-                    <template #title><i class="el-icon-setting"></i>系统设置</template>
-                    <router-link to="/users">
-                        <el-menu-item index="2-1">用户管理</el-menu-item>
-                    </router-link>
-                </el-submenu>
-            </el-menu>
-        </el-aside>
-        <el-container>
-            <el-header class='header' style="height: 50px;">
-                <div class="dropdown">
-                    <el-dropdown trigger="click">
+				<el-submenu index="2">
+					<template #title><i class="el-icon-monitor"></i>设备监控</template>
+					<router-link to="/logs">
+						<el-menu-item index="2-1">MQTT消息日志</el-menu-item>
+					</router-link>
+				</el-submenu>
+
+				<el-submenu index="3">
+					<template #title><i class="el-icon-setting"></i>系统设置</template>
+					<router-link to="/apply">
+						<el-menu-item index="3-1">用户管理</el-menu-item>
+					</router-link>
+					<router-link to="/item">
+						<el-menu-item index="3-2">项目管理</el-menu-item>
+					</router-link>
+					<router-link to="/apply">
+						<el-menu-item index="3-3">项目组管理</el-menu-item>
+					</router-link>
+					<router-link to="/apply">
+						<el-menu-item index="3-4">权限申请记录</el-menu-item>
+					</router-link>
+				</el-submenu>
+
+			</el-menu>
+		</el-aside>
+		<el-container>
+			<el-header class='header' style="height: 50px;">
+				<div class="dropdown">
+					<el-dropdown trigger="click">
 						<span class="el-dropdown-link">
 							{{nickname}}<i class="el-icon-arrow-down el-icon--right"></i>
 						</span>
-                        <template #dropdown>
-                            <el-dropdown-menu>
-                                <el-dropdown-item>退出登录</el-dropdown-item>
-                            </el-dropdown-menu>
-                        </template>
-                    </el-dropdown>
-                </div>
-            </el-header>
-            <el-main>
-                <!-- vue3.0配置 -->
-                <router-view v-slot="{Component}">
-                    <keep-alive>
-                        <component :is="Component"/>
-                    </keep-alive>
-                </router-view>
-            </el-main>
-        </el-container>
-    </el-container>
+						<template #dropdown>
+							<el-dropdown-menu>
+								<el-dropdown-item>退出登录</el-dropdown-item>
+							</el-dropdown-menu>
+						</template>
+					</el-dropdown>
+				</div>
+			</el-header>
+			<el-main>
+				<!-- vue3.0配置-->
+				<router-view v-slot="{Component}">
+					<keep-alive>
+						<component :is="Component" />
+					</keep-alive>
+				</router-view>
+			</el-main>
+		</el-container>
+	</el-container>
 </template>
 
 <script>
-    import TokenManager from '../../static/js/token.js'
-
-    export default {
-        data() {
-            return {
-                nickname: '管理员',
-            };
-        },
-        mounted: function () {
-            this.initToken();
-        },
-        methods: {
-            /**
-             * 查看token信息
-             */
-            initToken: function () {
-                try {
-                    const obj = JSON.parse(TokenManager.getToken());
-                    if (TokenManager.getVerify() != null) {
-                        this.nickname = obj.nickname;
-                        return;
-                    }
-                    this.$http.Get(this.$global.verify, {}).then(res => {
-                        TokenManager.setVerify();
-                        this.nickname = obj.nickname;
-                    })
-                } catch {
-                    this.$router.replace("/login");
-                }
-            }
-        }
-    };
+	import TokenManager from '../../static/js/token.js'
+	export default {
+		data() {
+			return {
+				nickname: '管理员',
+			};
+		},
+		mounted() {
+			//this.initToken();
+		},
+		methods: {
+			/**
+			 * 查看token信息
+			 */
+			initToken: function() {
+				try {
+					const obj = JSON.parse(TokenManager.getToken());
+					if (TokenManager.getVerify() != null) {
+						this.nickname = obj.nickname;
+						return;
+					}
+					this.$http.Get(this.$global.verify, {}).then(res => {
+						TokenManager.setVerify();
+						this.nickname = obj.nickname;
+					})
+				} catch {
+					this.$router.replace("/login");
+				}
+			}
+		}
+	};
 </script>
 
 <style scoped lang="scss">
-    .container {
-        height: 100%;
+	.container {
+		height: 100%;
 
-        & .logo {
-            box-sizing: border-box;
-            padding-top: 10px;
-            padding-left: 20px;
-            width: 100%;
-            height: 60px;
+		& .logo {
+			box-sizing: border-box;
+			padding-top: 10px;
+			padding-left: 20px;
+			width: 100%;
+			height: 60px;
 
-            & img {
-                width: 40px;
-                height: 40px;
-            }
+			& img {
+				width: 40px;
+				height: 40px;
+			}
 
-        }
+		}
 
-        & .header {
-            background: #f3f5f9;
+		& .header {
+			background: #f3f5f9;
 
-            & .dropdown {
-                float: right;
-                margin-right: 30px;
-                cursor: pointer;
-                line-height: 50px;
-            }
-        }
+			& .dropdown {
+				float: right;
+				margin-right: 30px;
+				cursor: pointer;
+				line-height: 50px;
+			}
+		}
 
-        & .el-main {
-            background: #f3f5f9;
-            height: 100%;
-            overflow-x: hidden;
-            overflow-y: scroll;
-            box-sizing: border-box;
-            padding: 0 15px 20px 20px;
+		& .el-main {
+			background: #f3f5f9;
+			height: 100%;
+			overflow-x: hidden;
+			overflow-y: scroll;
+			box-sizing: border-box;
+			padding: 0 15px 20px 20px;
 
-        }
+		}
 
-        & .el-aside {
-            height: 100%;
-            background: #141b2e;
+		& .el-aside {
+			height: 100%;
+			background: #141b2e;
 
-            & .el-menu {
-                border: none;
-            }
-        }
-    }
+			& .el-menu {
+				border: none;
+			}
+		}
+	}
 </style>

+ 0 - 1
src/views/login/login.vue

@@ -43,7 +43,6 @@
 				}
 			}
 		},
-		mounted: function() {},
 		methods: {
 			/**
 			 * 提交表单时间

+ 119 - 0
src/views/monitor/logs.vue

@@ -0,0 +1,119 @@
+<template>
+	<div class="zy-template">
+		<div class="zy-main-title">MQTT消息日志</div>
+		<div class="zy-module">
+			<el-form ref="form" :model="query" label-width="60px">
+				<el-form-item label="设备码:" class="zy-search-form-item">
+					<el-input v-model="query.openNum" size="mini" clearable></el-input>
+				</el-form-item>
+
+				<el-form-item label="类型:" class="zy-search-form-item">
+					<el-select v-model="query.type" size="mini" value="" placeholder=" " clearable>
+						<el-option value="0" label="服务器接收" />
+						<el-option value="1" label="服务器发送" />
+					</el-select>
+				</el-form-item>
+
+				<el-form-item label="指令:" class="zy-search-form-item">
+					<el-select v-model="query.m" size="mini" value="" placeholder=" " clearable>
+						<el-option :value="item.code" :label="item.remark" v-for="item in mList" />
+					</el-select>
+				</el-form-item>
+
+				<el-button type="primary" size="mini" @click="submit">查询</el-button>
+			</el-form>
+		</div>
+
+		<div class="zy-module">
+			<el-table :data="page.records" header-cell-class-name="zy-table-header-cell" cell-class-name='zy-table-cell'
+				stripe>
+				<el-table-column prop="openNum" label="设备ID" width="180" />
+				<el-table-column label="类型" width="80">
+					<template #default="scope">{{scope.row.type==0?'接收':'发送'}}</template>
+				</el-table-column>
+				<el-table-column label="类型" width="180">
+					<template #default="scope">{{scope.row.m}} ({{scope.row.remark}})</template>
+				</el-table-column>
+				<el-table-column prop="content" label="内容" min-width="10%" />
+				<el-table-column prop="createTime" label="时间" width="180" />
+			</el-table>
+
+			<el-pagination class="zy-table-pagination" background layout="prev, pager, next"
+				:current-page="page.current" :total="page.total" :page-size="page.size" @current-change="pagination" />
+		</div>
+
+	</div>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				query: {
+					openNum: "",
+					type: null,
+					m: null
+				},
+				mList: null, //指令列表
+				page: {
+					current: 1,
+					size: 20,
+				},
+			};
+		},
+		mounted() {
+			this.getAllInstruction();
+			this.getListPage();
+		},
+		methods: {
+			/**
+			 * 提交查询条件
+			 */
+			submit: function() {
+				const param = {
+					current: 1,
+					size: this.page.size,
+					openNum: this.query.openNum,
+					type: this.query.type,
+					m: this.query.m,
+				};
+				this.getListPage(param);
+			},
+			/**
+			 * 分页点击事件
+			 */
+			pagination: function(current) {
+				const param = {
+					current: current,
+					size: this.page.size,
+					openNum: this.query.openNum,
+					type: this.query.type,
+					m: this.query.m,
+				};
+				this.getListPage(param);
+			},
+
+			/**
+			 * 获取日志列表
+			 */
+			getListPage: function(params) {
+				this.$http.Post(this.$global.logs.listPage, params).then(res => {
+					this.page = res.data;
+					console.log(res.data)
+				})
+			},
+			/**
+			 * 获取全部的指令
+			 */
+			getAllInstruction() {
+				this.$http.Get(this.$global.logs.instructions, {}).then(res => {
+					this.mList = res.data;
+					console.log(res.data)
+				})
+			}
+		}
+	};
+</script>
+
+<style lang="scss">
+</style>

+ 200 - 0
src/views/system/item.vue

@@ -0,0 +1,200 @@
+<template>
+	<div class="zy-template">
+		<div class="zy-main-title">项目管理</div>
+		<div class="zy-module">
+			<el-form :model="query" label-width="80px">
+				<el-form-item label="关键字" class="zy-search-form-item">
+					<el-input v-model="query.name" size="mini" placeholder="项目名/项目编号" clearable></el-input>
+				</el-form-item>
+				<el-form-item label="状态" class="zy-search-form-item">
+					<el-select v-model="query.status" size="mini" clearable placeholder="不选默认全部">
+						<el-option label="禁用" value="0" />
+						<el-option label="启用" value="1" />
+					</el-select>
+				</el-form-item>
+				<el-button type="primary" size="mini" @click="submit">查询</el-button>
+			</el-form>
+		</div>
+
+		<div class="zy-module">
+			<el-button type="primary" size="small" style="margin-bottom: 20px;" @click="addDialog = true">增加</el-button>
+			<el-table :data="page.records" max-height="800" stripe size="small"
+				header-cell-class-name="zy-table-header-cell" cell-class-name='zy-table-cell'>
+				<el-table-column prop="name" label="项目名称" width="120" min-width="5%" />
+				<el-table-column label="项目备注" min-width="30%">
+					<template #default="scope">
+						<div style="height: 24px; overflow: hidden;">
+							{{scope.row.remark}}
+						</div>
+					</template>
+				</el-table-column>
+				<el-table-column label="状态" width="60">
+					<template #default="scope">
+						<el-tag type="danger" size="mini" v-if="scope.row.status==0">禁用</el-tag>
+						<el-tag type="success" size="mini" v-if="scope.row.status==1">启用</el-tag>
+					</template>
+				</el-table-column>
+				<el-table-column prop="createTime" label="创建时间" width="160" />
+				<el-table-column label="操作" width="100" min-width="10%">
+					<template #default="scope">
+						<el-button @click="handleDetail(scope.row)" type="text" size="small">修改</el-button>
+						<el-button @click="handlePass(scope.row.id)" type="text" size="small" style="color: #67c23a"
+							v-if="scope.row.status==0">启用</el-button>
+						<el-button @click="handleRefuse(scope.row.id)" type="text" size="small" style="color: #f56c6c;"
+							v-if="scope.row.status==1">禁用</el-button>
+					</template>
+				</el-table-column>
+			</el-table>
+			<el-pagination class="zy-table-pagination" background layout="prev, pager, next"
+				:current-page="page.current" :total="page.total" :page-size="page.size" @current-change="pagination" />
+		</div>
+
+		<el-dialog title="添加项目" v-model="addDialog" width="500px">
+			<el-form :model="addForm" label-width="100px">
+				<el-form-item label="项目名称:">
+					<el-input v-model="addForm.name" maxlength="30"></el-input>
+				</el-form-item>
+
+				<el-form-item label="备注:">
+					<el-input type="textarea" v-model="addForm.remark" maxlength="100"></el-input>
+				</el-form-item>
+			</el-form>
+			<template #footer>
+				<span class="dialog-footer">
+					<el-button @click="addDialog = false">取 消</el-button>
+					<el-button type="danger" @click="addSubmit">提 交</el-button>
+				</span>
+			</template>
+		</el-dialog>
+	</div>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				query: {
+					name: null,
+					status: null
+				},
+				page: {
+					current: 1,
+					size: 10,
+				},
+				addDialog: false, //增加表单
+				updateDialog: false, //更新表单
+				updateForm: null, //更新表单
+				addForm: null, //添加表单
+			};
+		},
+		mounted: function() {
+			this.getListPage(this.page);
+		},
+		methods: {
+			/**
+			 * 提交查询条件
+			 */
+			submit: function() {
+				const params = {
+					name: this.query.name,
+					status: this.query.status
+				};
+				this.getListPage(params);
+			},
+
+			/**
+			 * 分页点击事件
+			 */
+			pagination: function(current) {
+				const params = {
+					name: this.query.name,
+					status: this.query.status,
+					current: current,
+					size: this.page.size,
+				};
+				this.getListPage(params);
+			},
+
+			/**
+			 * 获取设备列表
+			 */
+			getListPage: function(params) {
+				this.$http.Get(this.$global.item.listPage, params).then(res => {
+					console.log(res.data);
+					this.page = res.data;
+				})
+			},
+
+			/**
+			 * 增加项目
+			 */
+			handleAdd: function(obj) {
+				this.addDialog = true;
+			},
+
+			/**
+			 * 更新项目
+			 */
+			handleUpdate: function(obj) {
+				this.updateDialog = true;
+			},
+
+			/**
+			 * 提交增加表单
+			 */
+			addSubmit: function() {
+				const param = {
+					name: this.query.name,
+					status: this.query.status
+				}
+				this.$http.Post(this.$global.item.save, param).then(res => {
+					this.$message.success("添加成功!");
+					this.refresh();
+				})
+			},
+
+			/**
+			 * 提交更新表单
+			 */
+			updateSubmit: function() {
+				const param = {
+					name: this.query.name,
+					status: this.query.status
+				}
+				this.$http.Post(this.$global.item.save, param).then(res => {
+					this.$message.success("添加成功!");
+					this.refresh();
+				})
+			},
+
+			/**
+			 * 禁用
+			 */
+			forbidden: function(id) {},
+
+			/**
+			 * 启用
+			 */
+			permit: function(id) {},
+
+
+			/**
+			 * 刷新列表
+			 */
+			refresh: function() {
+				this.addDialog = false;
+				const params = {
+					key: this.query.key,
+					status: this.query.status,
+					current: this.page.current,
+					size: this.page.size,
+				}
+				this.getListPage(params);
+			}
+		}
+	};
+</script>
+
+<style lang="scss" scoped>
+
+</style>

+ 262 - 0
src/views/system/privApply.vue

@@ -0,0 +1,262 @@
+<template>
+	<div class="zy-template">
+		<div class="zy-main-title">权限申请记录</div>
+		<div class="zy-module">
+			<el-form :model="query" label-width="80px">
+				<el-form-item label="关键字" class="zy-search-form-item">
+					<el-input v-model="query.key" size="mini" placeholder="手机号/申请信息" clearable></el-input>
+				</el-form-item>
+				<el-form-item label="审核状态" class="zy-search-form-item">
+					<el-select v-model="query.status" size="mini" clearable placeholder="不选默认全部">
+						<el-option label="拒绝" value="-1" />
+						<el-option label="待审核" value="0" />
+						<el-option label="通过" value="1" />
+					</el-select>
+				</el-form-item>
+				<el-button type="primary" size="mini" @click="submit">查询</el-button>
+			</el-form>
+		</div>
+
+		<div class="zy-module">
+			<el-table :data="page.records" max-height="800" stripe size="small"
+				header-cell-class-name="zy-table-header-cell" cell-class-name='zy-table-cell'>
+				<el-table-column prop="name" label="申请人" width="120" min-width="5%" />
+				<el-table-column prop="phone" label="手机号" width="150" min-width="5%" />
+				<el-table-column label="申请内容" min-width="30%">
+					<template #default="scope">
+						<div style="height: 24px; overflow: hidden;">
+							{{scope.row.remark}}
+						</div>
+					</template>
+				</el-table-column>
+				<el-table-column prop="createTime" label="申请时间" width="180" min-width="5%" />
+				<el-table-column label="审核状态" width="100" min-width="5%">
+					<template #default="scope">
+						<el-tag type="success" v-if="scope.row.status==1">通过</el-tag>
+						<el-tag type="warning" v-if="scope.row.status==0">待审核</el-tag>
+						<el-tag type="danger" v-if="scope.row.status==-1">拒绝</el-tag>
+					</template>
+				</el-table-column>
+				<el-table-column prop="auditTime" label="审核时间" width="180" min-width="5%" />
+				<el-table-column label="操作" width="150" min-width="10%">
+					<template #default="scope">
+						<el-button @click="handleDetail(scope.row)" type="text" size="small">详情</el-button>
+
+						<el-button @click="handlePass(scope.row.id)" type="text" size="small" style="color: #67c23a"
+							v-if="scope.row.status==0">通过</el-button>
+
+						<el-button @click="handleRefuse(scope.row.id)" type="text" size="small" style="color: #f56c6c;"
+							v-if="scope.row.status==0">拒绝</el-button>
+					</template>
+				</el-table-column>
+			</el-table>
+			<el-pagination class="zy-table-pagination" background layout="prev, pager, next"
+				:current-page="page.current" :total="page.total" :page-size="page.size" @current-change="pagination" />
+		</div>
+
+		<el-dialog title="申请信息" v-model="detailDialog" width="500px">
+			<el-descriptions :column="1" border size="small">
+				<el-descriptions-item label="申请人:">{{detailInfo.name}}</el-descriptions-item>
+				<el-descriptions-item label="手机号:">{{detailInfo.phone}}</el-descriptions-item>
+				<el-descriptions-item label="申请时间:">{{detailInfo.createTime}}</el-descriptions-item>
+				<el-descriptions-item label="申请内容:">{{detailInfo.remark}}</el-descriptions-item>
+				<el-descriptions-item label="审核时间:" v-if="detailInfo.status!=0">{{detailInfo.auditTime}}
+				</el-descriptions-item>
+				<el-descriptions-item label="拒绝原因:" v-if="detailInfo.status==-1">{{detailInfo.refuseReason}}
+				</el-descriptions-item>
+			</el-descriptions>
+		</el-dialog>
+
+		<el-dialog title="拒绝申请" v-model="refuseDialog" width="500px">
+			<el-form :model="refuseForm" label-width="100px">
+				<el-form-item label="原因:">
+					<el-input type="textarea" v-model="refuseForm.refuseReason"></el-input>
+				</el-form-item>
+			</el-form>
+			<template #footer>
+				<span class="dialog-footer">
+					<el-button @click="refuseDialog = false">取 消</el-button>
+					<el-button type="danger" @click="refuseSubmit">拒 绝</el-button>
+				</span>
+			</template>
+		</el-dialog>
+
+		<el-dialog title="通过申请" v-model="passDialog" width="500px">
+			<el-form label-width="100px">
+				<el-form-item label="配置组:">
+					<el-tree :data="privList" show-checkbox node-key="id" ref="tree" highlight-current
+						:props="defaultProps" accordion>
+					</el-tree>
+				</el-form-item>
+			</el-form>
+			<template #footer>
+				<span class="dialog-footer">
+					<el-button @click="passVisible = false">取 消</el-button>
+					<el-button type="success" @click="passSubmit">通 过</el-button>
+				</span>
+			</template>
+		</el-dialog>
+	</div>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				query: {
+					key: null,
+					status: null
+				},
+				page: {
+					current: 1,
+					size: 10,
+				},
+				detailDialog: false, //详情弹出框
+				refuseDialog: false, //拒绝申请弹出框
+				passDialog: false, //通过申请弹出框
+				detailInfo: null, //申请详情
+				selPassId: null, //选中的通过表单的ID
+				privList: null, //权限列表
+				defaultProps: {
+					children: 'children',
+					label: 'name'
+				},
+				refuseForm: { //拒绝申请表单
+					refuseReason: ''
+				},
+			};
+		},
+		mounted: function() {
+			this.getListPage(this.page);
+		},
+		methods: {
+			/**
+			 * 提交查询条件
+			 */
+			submit: function() {
+				const params = {
+					key: this.query.key,
+					status: this.query.status
+				};
+				this.getListPage(params);
+			},
+
+			/**
+			 * 分页点击事件
+			 */
+			pagination: function(current) {
+				const params = {
+					key: this.query.key,
+					status: this.query.status,
+					current: current,
+					size: this.page.size,
+				};
+				this.getListPage(params);
+			},
+			/**
+			 * 获取设备列表
+			 */
+			getListPage: function(params) {
+				this.$http.Get(this.$global.privilegeApply.listPage, params).then(res => {
+					console.log(res.data);
+					this.page = res.data;
+				})
+			},
+			/**
+			 * 申请详情
+			 */
+			handleDetail: function(obj) {
+				this.detailDialog = true;
+				this.detailInfo = obj;
+			},
+			/**
+			 * 拒绝申请
+			 */
+			handleRefuse: function(id) {
+				this.refuseDialog = true;
+				this.refuseForm.id = id;
+			},
+			/**
+			 * 提交拒绝申请表单
+			 */
+			refuseSubmit: function() {
+				const param = {
+					id: this.refuseForm.id,
+					refuseReason: this.refuseForm.refuseReason,
+					status: -1
+				}
+				this.$http.Post(this.$global.privilegeApply.audit, param).then(res => {
+					this.$message.success("提交成功!");
+					this.refresh();
+					this.refuseDialog = false;
+				})
+			},
+			/**
+			 * 通过申请
+			 */
+			handlePass: function(id) {
+				this.passDialog = true;
+				this.selPassId = id;
+				this.getPrivList();
+			},
+			/**
+			 * 提交通过申请表单
+			 */
+			passSubmit: function() {
+				const arr = this.$refs.tree.getCheckedKeys(true);
+				if (arr == null || arr.length <= 0) {
+					this.$message.error("至少配置一个组!");
+					return;
+				}
+				let groups = "";
+				arr.forEach(item => {
+					groups += (item + ",")
+				})
+				groups = groups.substr(0, groups.length - 1)
+				const params = {
+					id: this.selPassId,
+					groups: groups,
+					status: 1
+				}
+				console.log(params);
+				this.$http.Post(this.$global.privilegeApply.audit, params).then(res => {
+					this.$message.success("审核成功!");
+					this.refresh();
+					this.passDialog = false;
+				})
+			},
+
+			/**
+			 * 刷新列表
+			 */
+			refresh: function() {
+				const params = {
+					key: this.query.key,
+					status: this.query.status,
+					current: this.page.current,
+					size: this.page.size,
+				}
+				this.getListPage(params);
+			},
+			/**
+			 * 获取权限列表
+			 */
+			getPrivList: function() {
+				this.$http.Get(this.$global.privilegeApply.getNoPrivGroups, {}).then(res => {
+					const arr = [];
+					for (let key in res.data) {
+						arr.push({
+							name: key,
+							children: res.data[key]
+						})
+					}
+					this.privList = arr;
+				})
+			}
+		}
+	};
+</script>
+
+<style lang="scss" scoped>
+
+</style>