2025年04月07日18:35:52
5
components.d.ts
vendored
@ -7,10 +7,8 @@ export {}
|
|||||||
|
|
||||||
declare module '@vue/runtime-core' {
|
declare module '@vue/runtime-core' {
|
||||||
export interface GlobalComponents {
|
export interface GlobalComponents {
|
||||||
2: typeof import('./src/components/alarm copy 2.vue')['default']
|
|
||||||
Alarm: typeof import('./src/components/alarm.vue')['default']
|
Alarm: typeof import('./src/components/alarm.vue')['default']
|
||||||
BatchImp: typeof import('./src/components/batch-imp.vue')['default']
|
BatchImp: typeof import('./src/components/batch-imp.vue')['default']
|
||||||
copy: typeof import('./src/components/alarm copy.vue')['default']
|
|
||||||
Countup: typeof import('./src/components/countup.vue')['default']
|
Countup: typeof import('./src/components/countup.vue')['default']
|
||||||
DeviceInfo: typeof import('./src/components/deviceInfo.vue')['default']
|
DeviceInfo: typeof import('./src/components/deviceInfo.vue')['default']
|
||||||
ElAvatar: typeof import('element-plus/es')['ElAvatar']
|
ElAvatar: typeof import('element-plus/es')['ElAvatar']
|
||||||
@ -45,13 +43,12 @@ declare module '@vue/runtime-core' {
|
|||||||
ElTable: typeof import('element-plus/es')['ElTable']
|
ElTable: typeof import('element-plus/es')['ElTable']
|
||||||
ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
|
ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
|
||||||
ElTag: typeof import('element-plus/es')['ElTag']
|
ElTag: typeof import('element-plus/es')['ElTag']
|
||||||
ElTooltip: typeof import('element-plus/es')['ElTooltip']
|
|
||||||
ElUpload: typeof import('element-plus/es')['ElUpload']
|
ElUpload: typeof import('element-plus/es')['ElUpload']
|
||||||
Header: typeof import('./src/components/header.vue')['default']
|
Header: typeof import('./src/components/header.vue')['default']
|
||||||
RouterLink: typeof import('vue-router')['RouterLink']
|
RouterLink: typeof import('vue-router')['RouterLink']
|
||||||
RouterView: typeof import('vue-router')['RouterView']
|
RouterView: typeof import('vue-router')['RouterView']
|
||||||
Sidebar: typeof import('./src/components/sidebar.vue')['default']
|
Sidebar: typeof import('./src/components/sidebar.vue')['default']
|
||||||
StudentInfo: typeof import('./src/components/studentInfo.vue')['default']
|
SvgIcon: typeof import('./src/components/SvgIcon.vue')['default']
|
||||||
TableCustom: typeof import('./src/components/table-custom.vue')['default']
|
TableCustom: typeof import('./src/components/table-custom.vue')['default']
|
||||||
TableDetail: typeof import('./src/components/table-detail.vue')['default']
|
TableDetail: typeof import('./src/components/table-detail.vue')['default']
|
||||||
TableEdit: typeof import('./src/components/table-edit.vue')['default']
|
TableEdit: typeof import('./src/components/table-edit.vue')['default']
|
||||||
|
@ -7,11 +7,12 @@
|
|||||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||||
<title>智能手铐管理系统</title>
|
<title>智能手铐管理系统</title>
|
||||||
<link rel="stylesheet" href="//at.alicdn.com/t/c/font_830376_92o68tc95je.css">
|
<link rel="stylesheet" href="//at.alicdn.com/t/c/font_830376_92o68tc95je.css">
|
||||||
|
<link rel="icon" href="/public/favicon.ico">
|
||||||
<script>window._AMapSecurityConfig = {
|
<script>window._AMapSecurityConfig = {
|
||||||
securityJsCode: '83572bd6398cb4594c611f93f89b506a'
|
securityJsCode: '83572bd6398cb4594c611f93f89b506a'
|
||||||
}</script>
|
}</script>
|
||||||
<script
|
<script
|
||||||
src="https://webapi.amap.com/maps?v=1.4.15&key=e1e6dde852b57c61bacdcf1af21a3d9a&plugin=AMap.MouseTool&plugin=AMap.PolygonEditor&plugin=AMap.CircleEditor&plugin=AMap.MoveAnimation&plugin=AMap.PlaceSearch&plugin=AMap.AutoComplete&plugin=AMap.MoveAnimation"></script>
|
src="https://webapi.amap.com/maps?v=1.4.15&key=e1e6dde852b57c61bacdcf1af21a3d9a&plugin=AMap.MouseTool&plugin=AMap.PolygonEditor&plugin=AMap.PolyEditor&plugin=AMap.CircleEditor&plugin=AMap.MoveAnimation&plugin=AMap.PlaceSearch&plugin=AMap.AutoComplete&plugin=AMap.MoveAnimation"></script>
|
||||||
<script src=https://a.amap.com/jsapi_demos/static/demo-center/js/demoutils.js></script>
|
<script src=https://a.amap.com/jsapi_demos/static/demo-center/js/demoutils.js></script>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "vue-manage-system",
|
"name": "yak_handcuffs",
|
||||||
"version": "5.5.0",
|
"version": "5.5.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
BIN
public/favicon.ico
Normal file
After Width: | Height: | Size: 5.8 KiB |
BIN
public/logo.jpg
Normal file
After Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 121 KiB |
Before Width: | Height: | Size: 425 KiB |
59
src/api/index.d.ts
vendored
@ -9,6 +9,11 @@ export interface IpagingRes<T> {
|
|||||||
pages: number
|
pages: number
|
||||||
records: T[]
|
records: T[]
|
||||||
}
|
}
|
||||||
|
export interface TRoleList {
|
||||||
|
id: number
|
||||||
|
name: string
|
||||||
|
createTime: string
|
||||||
|
}
|
||||||
|
|
||||||
export namespace TLogin {
|
export namespace TLogin {
|
||||||
export interface Ireq {
|
export interface Ireq {
|
||||||
@ -150,3 +155,57 @@ export namespace TDevice {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export namespace TOrg {
|
||||||
|
export interface IAdd {
|
||||||
|
name: string;
|
||||||
|
rails: string;
|
||||||
|
parentId: string;
|
||||||
|
}
|
||||||
|
export interface IListReq extends Ipaging {
|
||||||
|
name?: number;
|
||||||
|
}
|
||||||
|
export interface Idel {
|
||||||
|
id: number;
|
||||||
|
}
|
||||||
|
export interface IOrgRecordRes {
|
||||||
|
id: number
|
||||||
|
name: string
|
||||||
|
parentId: number
|
||||||
|
status: number
|
||||||
|
updateUser: string
|
||||||
|
updateTime: string
|
||||||
|
creatUser: string
|
||||||
|
createTime: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TStatisticsDevice {
|
||||||
|
addCount: number
|
||||||
|
deviceTotal: number
|
||||||
|
onlineCount: number
|
||||||
|
warnCount: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface statisticsContentReq {
|
||||||
|
type: string
|
||||||
|
startDate: string
|
||||||
|
endDate: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface statisticsContentRes {
|
||||||
|
sosCount: number
|
||||||
|
railCount: number
|
||||||
|
destroyCount: number
|
||||||
|
batteryCount: number
|
||||||
|
heartRateCount: number
|
||||||
|
bloodOxygenCount: number
|
||||||
|
tempCount: number
|
||||||
|
times: any[],
|
||||||
|
sosArr: any[],
|
||||||
|
railArr: any[],
|
||||||
|
destroyArr: any[],
|
||||||
|
healthArr: any[],
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
import request from '../utils/request';
|
import request from '../utils/request';
|
||||||
import { TLogin, TAccount, IpagingRes, TDevice } from "./index.d";
|
import { TLogin, TAccount, IpagingRes, TDevice, TOrg, TRoleList, TStatisticsDevice, statisticsContentReq, statisticsContentRes } from "./index.d";
|
||||||
|
|
||||||
export const fetchLogin = (p: TLogin.Ireq): Promise<TLogin.IRes> => {
|
export const fetchLogin = (p: TLogin.Ireq): Promise<TLogin.IRes> => {
|
||||||
return request({
|
return request({
|
||||||
@ -9,6 +9,15 @@ export const fetchLogin = (p: TLogin.Ireq): Promise<TLogin.IRes> => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 批量导入账号样例
|
||||||
|
export const exportDemoAccount = (): Promise<any> => {
|
||||||
|
return request({
|
||||||
|
url: '/v1/web/upload/exportDemo/account',
|
||||||
|
method: 'get',
|
||||||
|
responseType: 'blob'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
export const fetchData = () => {
|
export const fetchData = () => {
|
||||||
return request({
|
return request({
|
||||||
@ -139,3 +148,62 @@ export const warningRecord = (p: TDevice.IRecordReq): Promise<IpagingRes<TDevice
|
|||||||
params: p
|
params: p
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 新增机构
|
||||||
|
export const orgAdd = (p: TOrg.IAdd): Promise<null> => {
|
||||||
|
return request({
|
||||||
|
url: '/v1/web/org/add',
|
||||||
|
method: 'post',
|
||||||
|
data: p
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// 修改机构
|
||||||
|
export const orgModify = (p: TOrg.IAdd): Promise<null> => {
|
||||||
|
return request({
|
||||||
|
url: '/v1/web/org/modify',
|
||||||
|
method: 'post',
|
||||||
|
data: p
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// 机构列表
|
||||||
|
export const orgList = (p?: TOrg.IListReq): Promise<IpagingRes<TOrg.IOrgRecordRes>> => {
|
||||||
|
return request({
|
||||||
|
url: '/v1/web/org/list',
|
||||||
|
method: 'get',
|
||||||
|
params: p
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 删除机构
|
||||||
|
export const orgDelete = (p?: TOrg.Idel): Promise<null> => {
|
||||||
|
return request({
|
||||||
|
url: '/v1/web/org/delete',
|
||||||
|
method: 'post',
|
||||||
|
data: p
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取角色列表
|
||||||
|
export const roleList = (): Promise<TRoleList[]> => {
|
||||||
|
return request({
|
||||||
|
url: '/v1/web/account/role/list',
|
||||||
|
method: 'get',
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 设备在线统计
|
||||||
|
export const statisticsDevice = (): Promise<TStatisticsDevice> => {
|
||||||
|
return request({
|
||||||
|
url: '/v1/web/statistics/device',
|
||||||
|
method: 'get',
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 内容数据
|
||||||
|
export const statisticsContent = (p: statisticsContentReq): Promise<statisticsContentRes> => {
|
||||||
|
return request({
|
||||||
|
url: '/v1/web/statistics/content',
|
||||||
|
method: 'post',
|
||||||
|
data: p
|
||||||
|
});
|
||||||
|
};
|
||||||
|
BIN
src/assets/img/m1.png
Normal file
After Width: | Height: | Size: 983 B |
BIN
src/assets/img/m1_a.png
Normal file
After Width: | Height: | Size: 802 B |
BIN
src/assets/img/m2.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
src/assets/img/m2_a.png
Normal file
After Width: | Height: | Size: 983 B |
BIN
src/assets/img/m3.png
Normal file
After Width: | Height: | Size: 717 B |
BIN
src/assets/img/m3_a.png
Normal file
After Width: | Height: | Size: 580 B |
BIN
src/assets/img/m4.png
Normal file
After Width: | Height: | Size: 1011 B |
BIN
src/assets/img/m4_a.png
Normal file
After Width: | Height: | Size: 729 B |
@ -1,18 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-dialog title="批量创建" v-model="dialogVisible" width="500px" destroy-on-close :close-on-click-modal="false">
|
<el-dialog title="批量创建" v-model="dialogVisible" width="500px" destroy-on-close :close-on-click-modal="false">
|
||||||
<el-upload
|
<el-upload :headers="HEADERS" :on-success="handleSuccess" :on-error="handleError" :before-upload="beforeUpload" class="upload-demo" drag :action="ACTION">
|
||||||
:on-success="handleSuccess"
|
|
||||||
:before-upload="beforeUpload"
|
|
||||||
class="upload-demo"
|
|
||||||
drag
|
|
||||||
action="https://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15"
|
|
||||||
>
|
|
||||||
<el-icon class="el-icon--upload"><upload-filled /></el-icon>
|
<el-icon class="el-icon--upload"><upload-filled /></el-icon>
|
||||||
<div class="el-upload__text"><em>点击</em>或将文件拖拽到这里上传</div>
|
<div class="el-upload__text"><em>点击</em>或将文件拖拽到这里上传</div>
|
||||||
<template #tip>
|
<template #tip>
|
||||||
<div class="tip-text">
|
<div class="tip-text">
|
||||||
<div class="el-upload__tip">只能上传excel文件,且不超过500KB</div>
|
<div class="el-upload__tip">只能上传excel文件,且不超过500KB</div>
|
||||||
<div class="down el-upload__tip">下载导入模板</div>
|
<div class="down el-upload__tip" @click="dowdDemo">下载导入模板</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-upload>
|
</el-upload>
|
||||||
@ -28,11 +22,35 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
import { ElMessage } from "element-plus";
|
import { ElMessage } from "element-plus";
|
||||||
|
import { useCommonStore } from "@/store/common";
|
||||||
|
import { exportDemoAccount } from "@/api/index";
|
||||||
|
interface Tdata {
|
||||||
|
code: number;
|
||||||
|
data: {
|
||||||
|
errMsg: string;
|
||||||
|
errorCount: number;
|
||||||
|
};
|
||||||
|
msg: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const comm = useCommonStore();
|
||||||
|
const ACTION = import.meta.env.VITE_APP_URL + "/v1/web/upload/account";
|
||||||
|
const HEADERS = {
|
||||||
|
"Access-Token": comm.user.token,
|
||||||
|
};
|
||||||
const dialogVisible = ref(false);
|
const dialogVisible = ref(false);
|
||||||
defineExpose({ dialogVisible });
|
defineExpose({ dialogVisible });
|
||||||
const handleSuccess = (rawFile: any) => {
|
const emit = defineEmits(["success"]);
|
||||||
console.log(rawFile);
|
|
||||||
|
const handleSuccess = ({ code, data, msg }: Tdata) => {
|
||||||
|
if (code != 200) return ElMessage.error(msg);
|
||||||
|
if (data.errorCount > 0) return ElMessage.error({ message: data.errMsg, dangerouslyUseHTMLString: true });
|
||||||
|
ElMessage.success("用户导入成功");
|
||||||
|
emit("success");
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleError = ({ msg }: { msg: string }) => {
|
||||||
|
ElMessage.error(msg);
|
||||||
};
|
};
|
||||||
const beforeUpload = (rawFile: any) => {
|
const beforeUpload = (rawFile: any) => {
|
||||||
if (rawFile.size / 1024 > 500) {
|
if (rawFile.size / 1024 > 500) {
|
||||||
@ -43,10 +61,25 @@ const beforeUpload = (rawFile: any) => {
|
|||||||
ElMessage.error("只能上传excel文件");
|
ElMessage.error("只能上传excel文件");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
dialogVisible.value = false;
|
||||||
|
};
|
||||||
|
const dowdDemo = async () => {
|
||||||
|
try {
|
||||||
|
const response = await exportDemoAccount();
|
||||||
|
const blob = new Blob([response], { type: "application/vnd.ms-excel" });
|
||||||
|
const link = document.createElement("a");
|
||||||
|
link.href = window.URL.createObjectURL(blob);
|
||||||
|
link.download = "批量创建用户模板.xlsx";
|
||||||
|
link.click();
|
||||||
|
window.URL.revokeObjectURL(link.href);
|
||||||
|
ElMessage.success("模板下载成功");
|
||||||
|
} catch (error) {
|
||||||
|
ElMessage.error("模板下载失败");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped lang="less">
|
||||||
.tip-text {
|
.tip-text {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -56,7 +89,9 @@ const beforeUpload = (rawFile: any) => {
|
|||||||
.down {
|
.down {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
|
|
||||||
color: #409eff;
|
color: #409eff;
|
||||||
}
|
}
|
||||||
|
/deep/ .el-upload-list {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -20,9 +20,7 @@
|
|||||||
<template v-if="item.children">
|
<template v-if="item.children">
|
||||||
<el-sub-menu :index="item.name" :key="index">
|
<el-sub-menu :index="item.name" :key="index">
|
||||||
<template #title>
|
<template #title>
|
||||||
<el-icon>
|
<div class="icon" :style="getBackgroundStyle(item.meta.icon, item.meta.activeIcon)"></div>
|
||||||
<component :is="item.meta.icon"></component>
|
|
||||||
</el-icon>
|
|
||||||
<span>{{ item.meta.tabs[0] }}</span>
|
<span>{{ item.meta.tabs[0] }}</span>
|
||||||
</template>
|
</template>
|
||||||
<template v-for="(subItem, subIde) in item.children">
|
<template v-for="(subItem, subIde) in item.children">
|
||||||
@ -41,9 +39,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<el-menu-item :index="item.name" :key="index" @click="menuClick(item)">
|
<el-menu-item :index="item.name" :key="index" @click="menuClick(item)">
|
||||||
<el-icon>
|
<div class="icon" :style="getBackgroundStyle(item.meta.icon, item.meta.activeIcon)"></div>
|
||||||
<component :is="item.meta.icon"></component>
|
|
||||||
</el-icon>
|
|
||||||
<template #title>{{ item.meta.tabs[0] }}</template>
|
<template #title>{{ item.meta.tabs[0] }}</template>
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
</template>
|
</template>
|
||||||
@ -65,9 +61,17 @@ const onRoutes = computed(() => {
|
|||||||
if (String(route.name).indexOf("/") != -1) {
|
if (String(route.name).indexOf("/") != -1) {
|
||||||
return String(route.name).split("/")[0];
|
return String(route.name).split("/")[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
return route.name;
|
return route.name;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const getBackgroundStyle = (icon: string, activeIcon: string) => {
|
||||||
|
return {
|
||||||
|
"--icon": `url(${icon})`,
|
||||||
|
"--activeIcon": `url(${activeIcon})`,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
const menuClick = (item: RouteRecordRaw) => {
|
const menuClick = (item: RouteRecordRaw) => {
|
||||||
router.push(item.path);
|
router.push(item.path);
|
||||||
};
|
};
|
||||||
@ -160,6 +164,11 @@ const collapseChage = () => {
|
|||||||
color: #061451;
|
color: #061451;
|
||||||
background: #061451;
|
background: #061451;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
|
.icon {
|
||||||
|
background-image: var(--activeIcon) !important;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: 20px 20px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.el-menu-item {
|
.el-menu-item {
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
@ -167,9 +176,19 @@ const collapseChage = () => {
|
|||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
.icon {
|
||||||
|
background-image: var(--icon);
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: 20px 20px;
|
||||||
|
}
|
||||||
&:hover {
|
&:hover {
|
||||||
background: #061451;
|
background: #061451;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
|
.icon {
|
||||||
|
background-image: var(--activeIcon) !important;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: 20px 20px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.el-sub-menu {
|
.el-sub-menu {
|
||||||
@ -184,6 +203,11 @@ const collapseChage = () => {
|
|||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
background: #061451;
|
background: #061451;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
|
.icon {
|
||||||
|
background-image: var(--activeIcon) !important;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: 20px 20px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,6 +215,11 @@ const collapseChage = () => {
|
|||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
width: 228px;
|
width: 228px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
|
.icon {
|
||||||
|
background-image: var(--icon);
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: 20px 20px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.el-menu {
|
.el-menu {
|
||||||
.el-menu-item {
|
.el-menu-item {
|
||||||
@ -219,6 +248,11 @@ const collapseChage = () => {
|
|||||||
|
|
||||||
.sidebar-el-menu {
|
.sidebar-el-menu {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
.icon {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
// border: none;
|
// border: none;
|
||||||
// min-height: 100%;
|
// min-height: 100%;
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,6 @@ import { usePermissStore } from './store/permiss';
|
|||||||
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
|
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
|
||||||
import 'element-plus/dist/index.css';
|
import 'element-plus/dist/index.css';
|
||||||
import './assets/css/icon.css';
|
import './assets/css/icon.css';
|
||||||
import { ElNotification } from 'element-plus'
|
|
||||||
|
|
||||||
const app = createApp(App);
|
const app = createApp(App);
|
||||||
const pinia = createPinia();
|
const pinia = createPinia();
|
||||||
|
@ -5,6 +5,14 @@ import { useTabsStore } from "@/store/tabs";
|
|||||||
import Layout from '@/layout/index.vue';
|
import Layout from '@/layout/index.vue';
|
||||||
import NProgress from 'nprogress';
|
import NProgress from 'nprogress';
|
||||||
import 'nprogress/nprogress.css';
|
import 'nprogress/nprogress.css';
|
||||||
|
import m1 from "@/assets/img/m1.png";
|
||||||
|
import m2 from "@/assets/img/m2.png";
|
||||||
|
import m3 from "@/assets/img/m3.png";
|
||||||
|
import m4 from "@/assets/img/m4.png";
|
||||||
|
import m1_a from "@/assets/img/m1_a.png";
|
||||||
|
import m2_a from "@/assets/img/m2_a.png";
|
||||||
|
import m3_a from "@/assets/img/m3_a.png";
|
||||||
|
import m4_a from "@/assets/img/m4_a.png";
|
||||||
|
|
||||||
export const routes: RouteRecordRaw[] = [
|
export const routes: RouteRecordRaw[] = [
|
||||||
{
|
{
|
||||||
@ -16,37 +24,37 @@ export const routes: RouteRecordRaw[] = [
|
|||||||
path: '/statisticalCenter',
|
path: '/statisticalCenter',
|
||||||
name: 'statisticalCenter',
|
name: 'statisticalCenter',
|
||||||
component: () => import('@/views/statisticalCenter/index.vue'),
|
component: () => import('@/views/statisticalCenter/index.vue'),
|
||||||
meta: { tabs: ['统计中心'], icon: 'el-icon-set-up' }
|
meta: { tabs: ['统计中心'], icon: m1, activeIcon: m1_a }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/monitoringCenter',
|
path: '/monitoringCenter',
|
||||||
name: 'monitoringCenter',
|
name: 'monitoringCenter',
|
||||||
component: () => import('@/views/monitoringCenter/index.vue'),
|
component: () => import('@/views/monitoringCenter/index.vue'),
|
||||||
meta: { tabs: ['监控中心'], icon: 'el-icon-set-up' }
|
meta: { tabs: ['监控中心'], icon: m2, activeIcon: m2_a }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/alarmCenter',
|
path: '/alarmCenter',
|
||||||
name: 'alarmCenter',
|
name: 'alarmCenter',
|
||||||
component: () => import('@/views/alarmCenter/index.vue'),
|
component: () => import('@/views/alarmCenter/index.vue'),
|
||||||
meta: { tabs: ['告警中心'], icon: 'el-icon-set-up' },
|
meta: { tabs: ['告警中心'], icon: m3, activeIcon: m3_a },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/incidentDispose',
|
path: '/incidentDispose',
|
||||||
name: 'alarmCenter/incidentDispose',
|
name: 'alarmCenter/incidentDispose',
|
||||||
component: () => import('@/views/incidentDispose/index.vue'),
|
component: () => import('@/views/incidentDispose/index.vue'),
|
||||||
meta: { tabs: ['告警中心', '处理事件'], icon: 'el-icon-set-up', hideMenu: true, }
|
meta: { tabs: ['告警中心', '处理事件'], hideMenu: true, }
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
path: '/synthesizeManage',
|
path: '/synthesizeManage',
|
||||||
name: 'synthesizeManage',
|
name: 'synthesizeManage',
|
||||||
meta: { tabs: ['综合管理中心'], icon: 'el-icon-school' },
|
meta: { tabs: ['综合管理中心'], icon: m4, activeIcon: m4_a, },
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: '/synthesizeManage/deviceManage',
|
path: '/synthesizeManage/deviceManage',
|
||||||
name: 'deviceManage',
|
name: 'deviceManage',
|
||||||
component: () => import('@/views/synthesizeManage/deviceManage/index.vue'),
|
component: () => import('@/views/synthesizeManage/deviceManage/index.vue'),
|
||||||
meta: { tabs: ['综合管理中心', '设备管理'], icon: 'el-icon-set-up' }
|
meta: { tabs: ['综合管理中心', '设备管理'], }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/synthesizeManage/deviceInfo',
|
path: '/synthesizeManage/deviceInfo',
|
||||||
@ -70,13 +78,13 @@ export const routes: RouteRecordRaw[] = [
|
|||||||
path: '/synthesizeManage/userManage',
|
path: '/synthesizeManage/userManage',
|
||||||
name: 'userManage',
|
name: 'userManage',
|
||||||
component: () => import('@/views/synthesizeManage/userManage/index.vue'),
|
component: () => import('@/views/synthesizeManage/userManage/index.vue'),
|
||||||
meta: { tabs: ['综合管理中心', '人员管理'], icon: 'el-icon-set-up' }
|
meta: { tabs: ['综合管理中心', '人员管理'] }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/synthesizeManage/areaManage',
|
path: '/synthesizeManage/areaManage',
|
||||||
name: 'areaManage',
|
name: 'areaManage',
|
||||||
component: () => import('@/views/synthesizeManage/areaManage/index.vue'),
|
component: () => import('@/views/synthesizeManage/areaManage/index.vue'),
|
||||||
meta: { tabs: ['综合管理中心', '辖区管理'], icon: 'el-icon-set-up' }
|
meta: { tabs: ['综合管理中心', '辖区管理'] }
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -8,6 +8,36 @@ export class MapCustom {
|
|||||||
...data,
|
...data,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
// 多边形回显
|
||||||
|
polyEditor(list, fn) {
|
||||||
|
this.map.clearMap();
|
||||||
|
let pathList = [];
|
||||||
|
list.forEach((item, index) => {
|
||||||
|
let lngLat = new AMap.LngLat(item.lng, item.lat);
|
||||||
|
pathList.push(lngLat);
|
||||||
|
});
|
||||||
|
const circle = new AMap.Polygon({
|
||||||
|
map: this.map,
|
||||||
|
path: pathList, // 圆心位置
|
||||||
|
strokeWeight: 2,
|
||||||
|
strokeStyle: "solid",
|
||||||
|
fillColor: "#00aeff57",
|
||||||
|
strokeColor: "#00AEFF", //描边颜色
|
||||||
|
fillOpacity: 0.3, //填充透明度
|
||||||
|
});
|
||||||
|
let PolygonEditor = new AMap.PolyEditor(this.map, circle);
|
||||||
|
PolygonEditor.open();
|
||||||
|
PolygonEditor.on("adjust", (event) => {
|
||||||
|
const pathList = event.target.getPath();
|
||||||
|
let list = [];
|
||||||
|
pathList.forEach((e, i) => {
|
||||||
|
list.push({ lat: e.lat, lng: e.lng });
|
||||||
|
});
|
||||||
|
fn && fn(list);
|
||||||
|
// this.ruleForm.points = list;
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
draw() {
|
draw() {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
this.drawResolve = resolve;
|
this.drawResolve = resolve;
|
||||||
|
@ -22,23 +22,22 @@ service.interceptors.request.use(
|
|||||||
|
|
||||||
service.interceptors.response.use(
|
service.interceptors.response.use(
|
||||||
(response: AxiosResponse) => {
|
(response: AxiosResponse) => {
|
||||||
const { data } = response;
|
const { data, headers } = response;
|
||||||
if (data.code !== 200) {
|
if (headers['content-type'] == 'application/json') {
|
||||||
ElMessage.error(data.msg)
|
if (data.code !== 200) {
|
||||||
|
ElMessage.error(data.msg)
|
||||||
if (data.code === 1003) {
|
|
||||||
// const comm = useCommonStore();
|
|
||||||
// comm.clearStore()
|
|
||||||
// router.replace('/login');
|
|
||||||
|
|
||||||
|
if (data.code === 1003) {
|
||||||
|
const comm = useCommonStore();
|
||||||
|
comm.clearStore()
|
||||||
|
router.replace('/login');
|
||||||
|
}
|
||||||
|
return Promise.reject(data);
|
||||||
|
} else {
|
||||||
|
return data.data;
|
||||||
}
|
}
|
||||||
return Promise.reject(data);
|
|
||||||
}
|
|
||||||
if (response.status === 200) {
|
|
||||||
return data.data;
|
|
||||||
} else {
|
|
||||||
Promise.reject(data);
|
|
||||||
}
|
}
|
||||||
|
return data;
|
||||||
},
|
},
|
||||||
(error: AxiosError) => {
|
(error: AxiosError) => {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
|
@ -3,21 +3,23 @@
|
|||||||
<div class="card-head">
|
<div class="card-head">
|
||||||
<div class="title">内容数据</div>
|
<div class="title">内容数据</div>
|
||||||
<div class="condition">
|
<div class="condition">
|
||||||
<el-button-group>
|
<el-radio-group v-model="radioType">
|
||||||
<el-button type="primary">心率</el-button>
|
<el-radio-button label="时" value="hour" />
|
||||||
<el-button>血氧</el-button>
|
<el-radio-button label="天" value="day" />
|
||||||
<el-button>体表温度</el-button>
|
<el-radio-button label="周" value="week" />
|
||||||
</el-button-group>
|
</el-radio-group>
|
||||||
<div class="condition-time">
|
<div class="condition-time">
|
||||||
|
<el-date-picker v-if="radioType == 'week'" v-model="value" type="week" value-format="YYYY-MM-DD" placeholder="请选择周" @change="handleWeekChange" />
|
||||||
<el-date-picker
|
<el-date-picker
|
||||||
|
v-else
|
||||||
style="width: 350px"
|
style="width: 350px"
|
||||||
v-model="value1"
|
v-model="value1"
|
||||||
type="datetimerange"
|
type="datetimerange"
|
||||||
start-placeholder="Start date"
|
|
||||||
end-placeholder="End date"
|
|
||||||
format="YYYY-MM-DD HH:mm:ss"
|
format="YYYY-MM-DD HH:mm:ss"
|
||||||
date-format="YYYY/MM/DD ddd"
|
value-format="YYYY-MM-DD HH:mm:ss"
|
||||||
time-format="A hh:mm:ss"
|
start-placeholder="开始时间"
|
||||||
|
end-placeholder="结束时间"
|
||||||
|
@change="handleDateChange"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -27,7 +29,23 @@
|
|||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
|
const value = ref("");
|
||||||
const value1 = ref("");
|
const value1 = ref("");
|
||||||
|
const radioType = ref("hour");
|
||||||
|
const { api } = defineProps({
|
||||||
|
api: {
|
||||||
|
type: Function,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleWeekChange = (val, res) => {
|
||||||
|
console.log(val, "handleWeekChange");
|
||||||
|
api({ type: radioType.value, startDate: `${val} 00:00:00`, endDate: `${val} 00:00:00` });
|
||||||
|
};
|
||||||
|
const handleDateChange = (val) => {
|
||||||
|
api({ type: radioType.value, startDate: val[0], endDate: val[1] });
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
<style scoped lang="less">
|
<style scoped lang="less">
|
||||||
.card {
|
.card {
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="container scrollbar">
|
<div class="container scrollbar">
|
||||||
<MonitoringTop />
|
<MonitoringTop :list="funcList" />
|
||||||
<el-row :gutter="20">
|
<el-row :gutter="20">
|
||||||
<el-col class="elcol" :span="16" :xs="24" :sm="24" :md="24" :lg="16" :xl="16">
|
<el-col class="elcol" :span="16" :xs="24" :sm="24" :md="24" :lg="16" :xl="16">
|
||||||
<DeviceHistory>
|
<DeviceHistory :api="getStatisticsContent">
|
||||||
<template #chart>
|
<template #chart>
|
||||||
<div ref="chartRef" style="flex: 1"></div>
|
<div ref="chartRef" style="flex: 1"></div>
|
||||||
</template>
|
</template>
|
||||||
@ -38,10 +38,15 @@ import OnLineStatistics from "./onLineStatistics.vue";
|
|||||||
import EmergencyList from "./emergencyList.vue";
|
import EmergencyList from "./emergencyList.vue";
|
||||||
import * as echarts from "echarts";
|
import * as echarts from "echarts";
|
||||||
import { MapCustom } from "@/utils/mapCustom";
|
import { MapCustom } from "@/utils/mapCustom";
|
||||||
import { fetchData } from "@/api/index";
|
import { fetchData, statisticsDevice, statisticsContent } from "@/api/index";
|
||||||
import { TableItem } from "@/types/table";
|
import { TableItem } from "@/types/table";
|
||||||
import { onMounted, ref, reactive, onDeactivated } from "vue";
|
import { onMounted, ref, reactive, onDeactivated } from "vue";
|
||||||
import { debounce } from "@/utils";
|
import { debounce } from "@/utils";
|
||||||
|
import { TStatisticsDevice } from "@/api/index.d";
|
||||||
|
import handcuffs from "@/assets/img/handcuffs.png";
|
||||||
|
import onLine from "@/assets/img/onLine.png";
|
||||||
|
import report from "@/assets/img/report.png";
|
||||||
|
import newly from "@/assets/img/newly.png";
|
||||||
|
|
||||||
const chartRef = ref(null);
|
const chartRef = ref(null);
|
||||||
const chartRef1 = ref(null);
|
const chartRef1 = ref(null);
|
||||||
@ -51,6 +56,13 @@ let myChart = null;
|
|||||||
let myChart1 = null;
|
let myChart1 = null;
|
||||||
let myChart2 = null;
|
let myChart2 = null;
|
||||||
|
|
||||||
|
let funcList = ref([
|
||||||
|
{ title: "手铐总数", en: "SHOUKAOZONGSHU", icon: handcuffs, num: 0, color: "##71DDF9" },
|
||||||
|
{ title: "在线数量", en: "ZAIXIANSHULIANG", icon: onLine, num: 0, color: "##71DDF9" },
|
||||||
|
{ title: "告警数量", en: "GAOJINGSHULIANG", icon: report, num: 0, color: "#8B51FD" },
|
||||||
|
{ title: "较昨日新增", en: "JIAOZUORIXINZENG", icon: newly, num: 0, color: "#FF6905" },
|
||||||
|
]);
|
||||||
|
|
||||||
const option = {
|
const option = {
|
||||||
xAxis: {
|
xAxis: {
|
||||||
type: "category",
|
type: "category",
|
||||||
@ -100,7 +112,17 @@ const getData = async () => {
|
|||||||
const res = await fetchData();
|
const res = await fetchData();
|
||||||
tableData.value = res.data.list;
|
tableData.value = res.data.list;
|
||||||
};
|
};
|
||||||
getData();
|
const getStatisticsDevice = () => {
|
||||||
|
statisticsDevice().then((res) => {
|
||||||
|
funcList.value[0].num = res.deviceTotal;
|
||||||
|
funcList.value[1].num = res.onlineCount;
|
||||||
|
funcList.value[2].num = res.warnCount;
|
||||||
|
funcList.value[3].num = res.addCount;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const getStatisticsContent = (res) => {
|
||||||
|
statisticsContent(res).then((res) => {});
|
||||||
|
};
|
||||||
|
|
||||||
const changePage = (val: number) => {
|
const changePage = (val: number) => {
|
||||||
page.index = val;
|
page.index = val;
|
||||||
@ -114,6 +136,9 @@ const handleResize = debounce(() => {
|
|||||||
}, 200);
|
}, 200);
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
getData();
|
||||||
|
getStatisticsDevice();
|
||||||
|
|
||||||
new MapCustom({ dom: "mapcontainer" });
|
new MapCustom({ dom: "mapcontainer" });
|
||||||
|
|
||||||
if (chartRef.value) {
|
if (chartRef.value) {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-row :gutter="20" class="monitoring-top">
|
<el-row :gutter="20" class="monitoring-top">
|
||||||
<el-col :span="24" :xs="24" :sm="12" :md="12" :lg="6" :xl="6" v-for="item in funcList">
|
<el-col :span="24" :xs="24" :sm="12" :md="12" :lg="6" :xl="6" v-for="item in list">
|
||||||
<div class="item">
|
<div class="item">
|
||||||
<div class="item-left">
|
<div class="item-left">
|
||||||
<div class="item-left-head">
|
<div class="item-left-head">
|
||||||
@ -20,16 +20,13 @@
|
|||||||
</el-row>
|
</el-row>
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
import handcuffs from "@/assets/img/handcuffs.png";
|
const { list } = defineProps({
|
||||||
import onLine from "@/assets/img/onLine.png";
|
// 表格相关
|
||||||
import report from "@/assets/img/report.png";
|
list: {
|
||||||
import newly from "@/assets/img/newly.png";
|
type: Array,
|
||||||
let funcList = [
|
default: () => [],
|
||||||
{ title: "手铐总数", en: "SHOUKAOZONGSHU", icon: handcuffs, num: 1326, color: "##71DDF9" },
|
},
|
||||||
{ title: "在线数量", en: "SHOUKAOZONGSHU", icon: onLine, num: 326, color: "##71DDF9" },
|
});
|
||||||
{ title: "告警数量", en: "SHOUKAOZONGSHU", icon: report, num: 99, color: "#8B51FD" },
|
|
||||||
{ title: "较昨日新增", en: "SHOUKAOZONGSHU", icon: newly, num: 86, color: "#FF6905" },
|
|
||||||
];
|
|
||||||
</script>
|
</script>
|
||||||
<style scoped lang="less">
|
<style scoped lang="less">
|
||||||
.monitoring-top {
|
.monitoring-top {
|
||||||
|
@ -21,8 +21,8 @@
|
|||||||
version="1.1"
|
version="1.1"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
p-id="5520"
|
p-id="5520"
|
||||||
width="18"
|
width="25"
|
||||||
height="18"
|
height="25"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
d="M229.12 475.52l687.296 183.872-1.408 1.472-1.024 12.864c-2.56 34.048-6.4 62.976-17.92 139.52l-6.528 43.648c-3.84 26.048-6.528 46.976-8.768 66.304-4.224 36.544-23.488 65.28-54.656 81.6-15.424 8.128-32 12.672-45.824 13.44l-4.032 0.192-90.432-24.32a18.88 18.88 0 0 1-12.16-26.688l35.392-71.552-20.352 26.24a515.328 515.328 0 0 1-47.36 50.56 19.008 19.008 0 0 1-18.112 4.672l-75.456-20.16a18.88 18.88 0 0 1-12.16-26.624l35.456-71.552-20.352 26.24a510.336 510.336 0 0 1-47.36 50.56 18.944 18.944 0 0 1-18.112 4.672l-88.448-23.68a18.944 18.944 0 0 1-12.096-26.56l35.392-71.552-20.352 26.24a515.84 515.84 0 0 1-47.36 50.56 18.944 18.944 0 0 1-18.112 4.672l-62.528-16.704a18.944 18.944 0 0 1-12.096-26.688l35.392-71.488-20.352 26.24c-8.32 10.688-20.48 24-36.48 39.936a44.736 44.736 0 0 1-43.136 11.52l-78.08-20.864-23.104-8.704c-29.632-25.536-44.608-61.44-39.36-95.552 5.76-37.12 32.32-67.648 82.112-88.704 34.368-14.656 67.584-74.176 89.664-157.44l3.84-14.464-1.024-1.792z m-42.88-76.16a60.224 60.224 0 0 1 5.056-6.4l123.776-135.424c9.92-10.752 24.832-19.392 41.856-23.936 16.64-4.416 33.984-4.672 48.64-0.768l123.584 33.024 4.096-2.368 55.36-205.824c8.704-32.448 43.968-51.456 78.72-42.24l83.2 22.272c34.752 9.28 55.808 43.392 47.104 75.84l-55.36 205.824 2.368 4.096 118.528 31.68c14.592 3.84 29.568 12.8 41.728 24.96 12.416 12.352 21.12 27.2 24.192 41.472l39.36 179.072a58.688 58.688 0 0 1 1.28 9.856c-0.704 6.592-5.312 10.304-13.696 11.2L194.944 418.048c-10.432-2.944-13.376-9.216-8.768-18.752z"
|
d="M229.12 475.52l687.296 183.872-1.408 1.472-1.024 12.864c-2.56 34.048-6.4 62.976-17.92 139.52l-6.528 43.648c-3.84 26.048-6.528 46.976-8.768 66.304-4.224 36.544-23.488 65.28-54.656 81.6-15.424 8.128-32 12.672-45.824 13.44l-4.032 0.192-90.432-24.32a18.88 18.88 0 0 1-12.16-26.688l35.392-71.552-20.352 26.24a515.328 515.328 0 0 1-47.36 50.56 19.008 19.008 0 0 1-18.112 4.672l-75.456-20.16a18.88 18.88 0 0 1-12.16-26.624l35.456-71.552-20.352 26.24a510.336 510.336 0 0 1-47.36 50.56 18.944 18.944 0 0 1-18.112 4.672l-88.448-23.68a18.944 18.944 0 0 1-12.096-26.56l35.392-71.552-20.352 26.24a515.84 515.84 0 0 1-47.36 50.56 18.944 18.944 0 0 1-18.112 4.672l-62.528-16.704a18.944 18.944 0 0 1-12.096-26.688l35.392-71.488-20.352 26.24c-8.32 10.688-20.48 24-36.48 39.936a44.736 44.736 0 0 1-43.136 11.52l-78.08-20.864-23.104-8.704c-29.632-25.536-44.608-61.44-39.36-95.552 5.76-37.12 32.32-67.648 82.112-88.704 34.368-14.656 67.584-74.176 89.664-157.44l3.84-14.464-1.024-1.792z m-42.88-76.16a60.224 60.224 0 0 1 5.056-6.4l123.776-135.424c9.92-10.752 24.832-19.392 41.856-23.936 16.64-4.416 33.984-4.672 48.64-0.768l123.584 33.024 4.096-2.368 55.36-205.824c8.704-32.448 43.968-51.456 78.72-42.24l83.2 22.272c34.752 9.28 55.808 43.392 47.104 75.84l-55.36 205.824 2.368 4.096 118.528 31.68c14.592 3.84 29.568 12.8 41.728 24.96 12.416 12.352 21.12 27.2 24.192 41.472l39.36 179.072a58.688 58.688 0 0 1 1.28 9.856c-0.704 6.592-5.312 10.304-13.696 11.2L194.944 418.048c-10.432-2.944-13.376-9.216-8.768-18.752z"
|
||||||
@ -39,7 +39,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<template #reference>
|
<template #reference>
|
||||||
<div @click="draw">
|
<div @click="draw">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 34.295 30">
|
<svg xmlns="http://www.w3.org/2000/svg" width="25" height="25" viewBox="0 0 34.295 30">
|
||||||
<g id="组_608" data-name="组 608" transform="translate(-1304 -128.546)">
|
<g id="组_608" data-name="组 608" transform="translate(-1304 -128.546)">
|
||||||
<path
|
<path
|
||||||
id="路径_489"
|
id="路径_489"
|
||||||
@ -76,7 +76,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<div class="dialog-footer">
|
<div class="dialog-footer">
|
||||||
<el-button @click="handleBtn()">取消</el-button>
|
<el-button @click="closeDialog">取消</el-button>
|
||||||
<el-button type="primary" @click="handleBtn(ruleFormRef)">确定</el-button>
|
<el-button type="primary" @click="handleBtn(ruleFormRef)">确定</el-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -86,19 +86,37 @@
|
|||||||
import { ref, reactive, onMounted, nextTick } from "vue";
|
import { ref, reactive, onMounted, nextTick } from "vue";
|
||||||
import { MapCustom } from "@/utils/mapCustom";
|
import { MapCustom } from "@/utils/mapCustom";
|
||||||
import type { FormRules, FormInstance } from "element-plus";
|
import type { FormRules, FormInstance } from "element-plus";
|
||||||
|
import { useCommonStore } from "@/store/common";
|
||||||
|
|
||||||
|
const comm = useCommonStore();
|
||||||
|
const { update, rowData } = defineProps({
|
||||||
|
update: {
|
||||||
|
type: Function,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
rowData: {
|
||||||
|
type: Object,
|
||||||
|
dfault: () => ({}),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const visible = ref(true);
|
const visible = ref(true);
|
||||||
const ruleFormRef = ref<FormInstance>();
|
const ruleFormRef = ref<FormInstance>();
|
||||||
const ruleForm = reactive({
|
const ruleForm = reactive(
|
||||||
name: "",
|
rowData.id
|
||||||
location: "",
|
? { ...rowData }
|
||||||
});
|
: {
|
||||||
|
name: "",
|
||||||
|
rails: "",
|
||||||
|
parentId: comm.user.orgId,
|
||||||
|
}
|
||||||
|
);
|
||||||
let mapInfo: any = null;
|
let mapInfo: any = null;
|
||||||
|
|
||||||
const emit = defineEmits(["closeDialog"]);
|
const emit = defineEmits(["closeDialog", "handleBtn"]);
|
||||||
|
|
||||||
const validatePass = (_: any, _1: any, callback: any) => {
|
const validatePass = (_: any, _1: any, callback: any) => {
|
||||||
if (ruleForm.location == "") {
|
if (ruleForm.rails == "") {
|
||||||
callback(new Error("请绘制围栏"));
|
callback(new Error("请绘制围栏"));
|
||||||
} else {
|
} else {
|
||||||
callback();
|
callback();
|
||||||
@ -107,7 +125,7 @@ const validatePass = (_: any, _1: any, callback: any) => {
|
|||||||
|
|
||||||
const rules = reactive<FormRules<typeof ruleForm>>({
|
const rules = reactive<FormRules<typeof ruleForm>>({
|
||||||
name: [{ required: true, message: "请输入辖区名称" }],
|
name: [{ required: true, message: "请输入辖区名称" }],
|
||||||
location: [
|
rails: [
|
||||||
{ required: true, message: "请绘制围栏" },
|
{ required: true, message: "请绘制围栏" },
|
||||||
{ validator: validatePass, trigger: "blur" },
|
{ validator: validatePass, trigger: "blur" },
|
||||||
],
|
],
|
||||||
@ -116,17 +134,21 @@ const rules = reactive<FormRules<typeof ruleForm>>({
|
|||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
mapInfo = new MapCustom({ dom: "mapcontainer" });
|
mapInfo = new MapCustom({ dom: "mapcontainer" });
|
||||||
|
console.log(ruleForm, "ruleForm");
|
||||||
|
|
||||||
|
mapInfo.polyEditor(ruleForm.rails, (res) => {
|
||||||
|
ruleForm.rails = res;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const clearMap = () => {
|
const clearMap = () => {
|
||||||
mapInfo.clearMap();
|
mapInfo.clearMap();
|
||||||
ruleForm.location = "";
|
ruleForm.rails = "";
|
||||||
};
|
};
|
||||||
const draw = () => {
|
const draw = () => {
|
||||||
mapInfo.draw().then((res) => {
|
mapInfo.draw().then((res) => {
|
||||||
console.log(res, 1111);
|
ruleForm.rails = res;
|
||||||
ruleForm.location = JSON.stringify(res);
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
const closeDialog = () => {
|
const closeDialog = () => {
|
||||||
@ -136,12 +158,10 @@ const handleBtn = (formEl?: FormInstance | undefined) => {
|
|||||||
if (formEl) {
|
if (formEl) {
|
||||||
formEl.validate((valid) => {
|
formEl.validate((valid) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
console.log("submit!");
|
update(ruleForm);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
}
|
}
|
||||||
emit("closeDialog");
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -2,28 +2,24 @@
|
|||||||
<div class="container">
|
<div class="container">
|
||||||
<TableSearch :query="query" :options="searchOpt" :search="handleSearch" />
|
<TableSearch :query="query" :options="searchOpt" :search="handleSearch" />
|
||||||
<div class="table-container">
|
<div class="table-container">
|
||||||
<TableCustom :columns="columns" :tableData="tableData" :total="page.total" :refresh="getData" :currentPage="page.index" :changePage="changePage">
|
<TableCustom :columns="columns" :tableData="tableData" :total="paging.total" :refresh="getData" :currentPage="paging.page" :changePage="changePage">
|
||||||
<template #toolbarBtn>
|
<template #toolbarBtn>
|
||||||
<el-button type="primary" @click="handleAdd">新增</el-button>
|
<el-button type="primary" @click="handleAdd">新增</el-button>
|
||||||
<el-button>导出</el-button>
|
<!-- <el-button>导出</el-button> -->
|
||||||
<el-button type="danger">删除</el-button>
|
<!-- <el-button type="danger">删除</el-button> -->
|
||||||
</template>
|
</template>
|
||||||
<template #money="{ rows }"> ¥{{ rows.money }} </template>
|
<template #status="{ rows }">
|
||||||
<template #thumb="{ rows }">
|
<el-tag :type="rows.status ? 'success' : 'danger'">
|
||||||
<el-image class="table-td-thumb" :src="rows.thumb" :z-index="10" :preview-src-list="[rows.thumb]" preview-teleported> </el-image>
|
{{ StatusEnum[rows.status] }}
|
||||||
</template>
|
|
||||||
<template #state="{ rows }">
|
|
||||||
<el-tag :type="rows.state ? 'success' : 'danger'">
|
|
||||||
{{ rows.state ? "正常" : "异常" }}
|
|
||||||
</el-tag>
|
</el-tag>
|
||||||
</template>
|
</template>
|
||||||
<template #operator="{ rows }">
|
<template #operator="{ rows }">
|
||||||
<el-button link type="primary" size="small" @click="handleEdit(rows)"> 修改 </el-button>
|
<el-button link type="primary" size="small" @click="handleEdit(rows)"> 修改 </el-button>
|
||||||
<el-button link type="danger" size="small" @click="handelDel(rows)"> 删除 </el-button>
|
<el-button link type="danger" size="small" @click="handelDel(rows.id)"> 删除 </el-button>
|
||||||
</template>
|
</template>
|
||||||
</TableCustom>
|
</TableCustom>
|
||||||
</div>
|
</div>
|
||||||
<AddFence ref="addRef" v-if="visible" @closeDialog="visible = false" />
|
<AddFence ref="addRef" :rowData="rowData" v-if="visible" @closeDialog="visible = false" :update="updateData" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -31,14 +27,19 @@
|
|||||||
import { ref, reactive } from "vue";
|
import { ref, reactive } from "vue";
|
||||||
import { ElMessage, ElMessageBox } from "element-plus";
|
import { ElMessage, ElMessageBox } from "element-plus";
|
||||||
import { CirclePlusFilled } from "@element-plus/icons-vue";
|
import { CirclePlusFilled } from "@element-plus/icons-vue";
|
||||||
import { fetchData } from "@/api/index";
|
import { fetchData, orgAdd, orgModify, orgList, orgDelete } from "@/api/index";
|
||||||
import TableCustom from "@/components/table-custom.vue";
|
import TableCustom from "@/components/table-custom.vue";
|
||||||
import TableSearch from "@/components/table-search.vue";
|
import TableSearch from "@/components/table-search.vue";
|
||||||
import AddFence from "./addFence.vue";
|
import AddFence from "./addFence.vue";
|
||||||
import { TableItem } from "@/types/table";
|
import { TableItem } from "@/types/table";
|
||||||
import { FormOptionList } from "@/types/form-option";
|
import { FormOptionList } from "@/types/form-option";
|
||||||
import Alarm from "@/components/alarm.vue";
|
import Alarm from "@/components/alarm.vue";
|
||||||
|
import { TOrg } from "@/api/index.d";
|
||||||
|
// 0-禁用 1-启用
|
||||||
|
enum StatusEnum {
|
||||||
|
"禁用" = 0,
|
||||||
|
"启用",
|
||||||
|
}
|
||||||
// 查询相关
|
// 查询相关
|
||||||
const query = reactive({
|
const query = reactive({
|
||||||
name: "",
|
name: "",
|
||||||
@ -59,31 +60,33 @@ const searchOpt = ref<FormOptionList[]>([
|
|||||||
|
|
||||||
// 表格相关
|
// 表格相关
|
||||||
let columns = ref([
|
let columns = ref([
|
||||||
{ type: "selection" },
|
// { type: "selection" },
|
||||||
{ type: "index", label: "序号", width: 55, align: "center" },
|
{ type: "index", label: "序号", width: 55, align: "center" },
|
||||||
{ prop: "name", label: "辖区编号" },
|
{ prop: "id", label: "辖区编号" },
|
||||||
{ prop: "money", label: "辖区名称" },
|
{ prop: "name", label: "辖区名称" },
|
||||||
{ prop: "thumb", label: "创建角色" },
|
{ prop: "creatUser", label: "创建角色" },
|
||||||
{ prop: "time", label: "创建时间" },
|
{ prop: "createTime", label: "创建时间" },
|
||||||
{ prop: "state", label: "账户状态" },
|
// { prop: "status", label: "状态" },
|
||||||
{ prop: "operator", label: "操作", width: 200 },
|
{ prop: "operator", label: "操作", width: 200 },
|
||||||
]);
|
]);
|
||||||
const page = reactive({
|
const paging = reactive({
|
||||||
index: 1,
|
page: 1,
|
||||||
size: 10,
|
size: 10,
|
||||||
total: 200,
|
total: 0,
|
||||||
});
|
});
|
||||||
const tableData = ref<TableItem[]>([]);
|
const tableData = ref<TOrg.IOrgRecordRes[]>([]);
|
||||||
|
|
||||||
const getData = async () => {
|
const getData = async () => {
|
||||||
const res = await fetchData();
|
const res = await orgList(paging);
|
||||||
tableData.value = res.data.list;
|
tableData.value = res.records;
|
||||||
|
paging.total = res.total;
|
||||||
};
|
};
|
||||||
getData();
|
getData();
|
||||||
const handleSearch = () => {
|
const handleSearch = () => {
|
||||||
changePage(1);
|
changePage(1);
|
||||||
};
|
};
|
||||||
const changePage = (val: number) => {
|
const changePage = (val: number) => {
|
||||||
page.index = val;
|
paging.page = val;
|
||||||
getData();
|
getData();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -97,12 +100,15 @@ const handleEdit = (row: TableItem) => {
|
|||||||
visible.value = true;
|
visible.value = true;
|
||||||
};
|
};
|
||||||
// 删除
|
// 删除
|
||||||
const handelDel = (row: TableItem) => {
|
const handelDel = (id: number) => {
|
||||||
ElMessageBox.confirm("确定要删除吗?", "提示", {
|
ElMessageBox.confirm("确定要删除吗?", "提示", {
|
||||||
type: "warning",
|
type: "warning",
|
||||||
})
|
})
|
||||||
.then(async () => {
|
.then(async () => {
|
||||||
// ElMessage.success("删除成功");
|
orgDelete({ id }).then(() => {
|
||||||
|
ElMessage.success("删除成功");
|
||||||
|
getData();
|
||||||
|
});
|
||||||
})
|
})
|
||||||
.catch(() => {});
|
.catch(() => {});
|
||||||
};
|
};
|
||||||
@ -110,6 +116,18 @@ const handelDel = (row: TableItem) => {
|
|||||||
const handleAdd = () => {
|
const handleAdd = () => {
|
||||||
visible.value = true;
|
visible.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const updateData = (res) => {
|
||||||
|
let api, msg;
|
||||||
|
|
||||||
|
api = res.id ? orgModify : orgAdd;
|
||||||
|
msg = res.id ? "修改成功" : "新增成功";
|
||||||
|
api(res).then((res) => {
|
||||||
|
ElMessage.success(msg);
|
||||||
|
visible.value = false;
|
||||||
|
getData();
|
||||||
|
});
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
@ -57,6 +57,7 @@ import DeviceControl from "./deviceControl.vue";
|
|||||||
import { TableItem } from "@/types/table";
|
import { TableItem } from "@/types/table";
|
||||||
import { FormOption, FormOptionList } from "@/types/form-option";
|
import { FormOption, FormOptionList } from "@/types/form-option";
|
||||||
import { useRouter } from "vue-router";
|
import { useRouter } from "vue-router";
|
||||||
|
|
||||||
enum stateEnum {
|
enum stateEnum {
|
||||||
"离线" = 0,
|
"离线" = 0,
|
||||||
"在线",
|
"在线",
|
||||||
|
@ -43,14 +43,14 @@
|
|||||||
<el-dialog title="编辑类型" v-model="typeVisible" width="800px" destroy-on-close :close-on-click-modal="false" @close="closeDialog">
|
<el-dialog title="编辑类型" v-model="typeVisible" width="800px" destroy-on-close :close-on-click-modal="false" @close="closeDialog">
|
||||||
<UserType />
|
<UserType />
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
<BatchImp ref="batchImpRef" />
|
<BatchImp ref="batchImpRef" @success="handleSearch" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts" name="basetable">
|
<script setup lang="ts" name="basetable">
|
||||||
import { ref, reactive } from "vue";
|
import { ref, reactive } from "vue";
|
||||||
import { ElMessage, ElMessageBox } from "element-plus";
|
import { ElMessage, ElMessageBox } from "element-plus";
|
||||||
import { accountAdd, accountModify, accountList, accountDeletet, passwordReset } from "@/api/index";
|
import { accountAdd, accountModify, accountList, accountDeletet, passwordReset, roleList } from "@/api/index";
|
||||||
import TableCustom from "@/components/table-custom.vue";
|
import TableCustom from "@/components/table-custom.vue";
|
||||||
import TableSearch from "@/components/table-search.vue";
|
import TableSearch from "@/components/table-search.vue";
|
||||||
import TableEdit from "@/components/table-edit.vue";
|
import TableEdit from "@/components/table-edit.vue";
|
||||||
@ -59,7 +59,7 @@ import { useCommonStore } from "@/store/common";
|
|||||||
import UserType from "./userType.vue";
|
import UserType from "./userType.vue";
|
||||||
import { TableItem } from "@/types/table";
|
import { TableItem } from "@/types/table";
|
||||||
import { FormOption, FormOptionList } from "@/types/form-option";
|
import { FormOption, FormOptionList } from "@/types/form-option";
|
||||||
import { TAccount } from "@/api/index.d";
|
import { TAccount, TRoleList } from "@/api/index.d";
|
||||||
// import { Hide, View } from "@element-plus/icons-vue";
|
// import { Hide, View } from "@element-plus/icons-vue";
|
||||||
|
|
||||||
enum roleEnum {
|
enum roleEnum {
|
||||||
@ -75,6 +75,7 @@ const typeVisible = ref(false);
|
|||||||
const isEdit = ref(false);
|
const isEdit = ref(false);
|
||||||
const dialogTitle = ref("");
|
const dialogTitle = ref("");
|
||||||
const rowData = ref<TAccount.IListRes | undefined>();
|
const rowData = ref<TAccount.IListRes | undefined>();
|
||||||
|
|
||||||
// 查询相关
|
// 查询相关
|
||||||
const query = reactive({
|
const query = reactive({
|
||||||
name: "",
|
name: "",
|
||||||
@ -86,6 +87,7 @@ const paging = reactive({
|
|||||||
total: 0,
|
total: 0,
|
||||||
});
|
});
|
||||||
const tableData = ref<TAccount.IListRes[]>([]);
|
const tableData = ref<TAccount.IListRes[]>([]);
|
||||||
|
const roleListData = ref<TRoleList[]>([]);
|
||||||
|
|
||||||
const searchOpt = ref<FormOptionList[]>([
|
const searchOpt = ref<FormOptionList[]>([
|
||||||
{ type: "input", label: "用户名:", prop: "name" },
|
{ type: "input", label: "用户名:", prop: "name" },
|
||||||
@ -178,7 +180,14 @@ const changePage = (val: number) => {
|
|||||||
paging.page = val;
|
paging.page = val;
|
||||||
getData();
|
getData();
|
||||||
};
|
};
|
||||||
|
const roleListFn = () => {
|
||||||
|
roleList().then((res) => {
|
||||||
|
let opts = res.map((item) => {
|
||||||
|
return { label: item.name, value: item.id };
|
||||||
|
});
|
||||||
|
addOpt.list[3].opts = opts;
|
||||||
|
});
|
||||||
|
};
|
||||||
const getData = async () => {
|
const getData = async () => {
|
||||||
const res = await accountList(paging);
|
const res = await accountList(paging);
|
||||||
tableData.value = res.records.map((item) => {
|
tableData.value = res.records.map((item) => {
|
||||||
@ -187,6 +196,7 @@ const getData = async () => {
|
|||||||
});
|
});
|
||||||
paging.total = res.total;
|
paging.total = res.total;
|
||||||
};
|
};
|
||||||
|
roleListFn();
|
||||||
getData();
|
getData();
|
||||||
|
|
||||||
// 删除相关
|
// 删除相关
|
||||||
|
@ -53,6 +53,7 @@
|
|||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
<el-table-column prop="date" label="操作" width="200" align="center">
|
<el-table-column prop="date" label="操作" width="200" align="center">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button link type="primary" size="small">锁定</el-button>
|
<el-button link type="primary" size="small">锁定</el-button>
|
||||||
|