2025年04月10日19:00:16

This commit is contained in:
luojiayi 2025-04-10 19:00:17 +08:00
parent 054d5fb5ca
commit 3346134b9a
14 changed files with 367 additions and 194 deletions

1
components.d.ts vendored
View File

@ -49,6 +49,7 @@ declare module '@vue/runtime-core' {
ElTag: typeof import('element-plus/es')['ElTag']
ElUpload: typeof import('element-plus/es')['ElUpload']
Header: typeof import('./src/components/header.vue')['default']
InfoWindow: typeof import('./src/components/InfoWindow.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
Sidebar: typeof import('./src/components/sidebar.vue')['default']

67
src/api/index.d.ts vendored
View File

@ -9,12 +9,19 @@ export interface IpagingRes<T> {
pages: number
records: T[]
}
export interface TRoleList {
id: number
name: string
createTime: string
}
interface TRoleMenu {
id?: number
type?: number
name?: string
createTime?: string
}
export interface TRoleList {
id?: number
name: string
createTime?: string
roleMenu: TRoleMenu[]
}
export interface TStatisticsDevice {
@ -72,6 +79,14 @@ export interface TDeviceConfigModify {
}
export namespace TRoleModify {
export interface Ireq {
id: number
name: string
roleMenu: TRoleMenu[]
}
}
export namespace TDeviceConfig {
interface Treq {
@ -160,6 +175,7 @@ export namespace TDevice {
accountId: number
orgId: number
status: number
useStatus: number
deviceSwitch: number
mode: number
monitorMode: number
@ -345,4 +361,45 @@ export namespace THealthLatestData {
tempArr: any[]
}
}
export namespace TLocateRecord {
interface TReq {
deviceId: number | string
startDate: string
endDate: string
}
interface TRes {
id: number
deviceId: string
lat: number
lng: number
locationType: number
adCode: string
place: string
address: string
locationTime: string
createTime: string
}
}
export namespace TSetUseStatus {
interface TReq {
status: number
deviceId: number
}
}
export namespace TRoleMenuList {
interface TMenus {
id: number
type: number
name: string
createTime: string
}
interface TRes {
name: string
type: number
menus: TMenus[]
}
}

View File

@ -1,5 +1,5 @@
import request from '../utils/request';
import { TLogin, TAccount, IpagingRes, TDevice, TOrg, TRoleList, TStatisticsDevice, statisticsContentReq, statisticsContentRes, TStatisticsCount, TWarnRecord, TWarningDetail, TWarningConfirm, TDeviceConfigModify, TDeviceConfig, THealthLatestData } from "./index.d";
import { TLogin, TAccount, IpagingRes, TDevice, TOrg, TRoleList, TStatisticsDevice, statisticsContentReq, statisticsContentRes, TStatisticsCount, TWarnRecord, TWarningDetail, TWarningConfirm, TDeviceConfigModify, TDeviceConfig, THealthLatestData, TLocateRecord, TSetUseStatus, TRoleMenuList, TRoleModify } from "./index.d";
export const fetchLogin = (p: TLogin.Ireq): Promise<TLogin.IRes> => {
return request({
@ -191,6 +191,15 @@ export const roleList = (): Promise<TRoleList[]> => {
});
};
// 修改角色信息
export const roleModify = (p: TRoleModify.Ireq): Promise<null> => {
return request({
url: '/v1/web/role/modify',
method: 'post',
data: p
});
};
// 设备在线统计
export const statisticsDevice = (): Promise<TStatisticsDevice> => {
return request({
@ -278,4 +287,39 @@ export const healthLatestData = (p: THealthLatestData.TReq): Promise<THealthLate
});
};
// 设备定位记录
export const locateRecord = (p: TLocateRecord.TReq): Promise<TLocateRecord.TRes[]> => {
return request({
url: '/v1/web/device/locate/record',
method: 'get',
params: p
});
};
// 设置使用状态
export const setUseStatus = (p: TSetUseStatus.TReq): Promise<null> => {
return request({
url: '/v1/web/device/set/useStatus',
method: 'post',
data: p
});
};
// 设置禁用状态
export const setStatus = (p: TSetUseStatus.TReq): Promise<null> => {
return request({
url: '/v1/web/device/set/status',
method: 'post',
data: p
});
};
// 获取菜单列表
export const roleMenuList = (): Promise<TRoleMenuList.TRes[]> => {
return request({
url: '/v1/web/role/menu/list',
method: 'get',
});
};

View File

@ -2,26 +2,28 @@
<div class="infoBox">
<div class="infoBox-head">
<div class="item">
<div class="span">姓名</div>
<div class="span">{{ value.username }}</div>
<div class="span">手铐</div>
<div class="span">{{ value.id }}</div>
</div>
<div class="item">
<i class="el-icon-close" style="font-size: 24px; cursor: pointer" @click="$emit('close')" />
<div class="item" style="cursor: pointer" @click="emit('close')">
<svg t="1744273365398" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8493" width="24" height="24">
<path
d="M576 512l277.333333 277.333333-64 64-277.333333-277.333333L234.666667 853.333333 170.666667 789.333333l277.333333-277.333333L170.666667 234.666667 234.666667 170.666667l277.333333 277.333333L789.333333 170.666667 853.333333 234.666667 576 512z"
fill="#444444"
p-id="8494"
></path>
</svg>
<!-- <i class="el-icon-close" style="font-size: 24px; cursor: pointer" @click="emit('close')" /> -->
</div>
</div>
<div class="infoBox-content">
2
<div class="item">
<div class="item-left">IMEI号</div>
<div class="item-right">{{ value.deviceId }}</div>
</div>
<div class="item">
<div class="item-left">定位方式</div>
<div class="item-right">{{ locateEnum[value.locateType == -1 ? 3 : value.locateType] }}</div>
</div>
<div class="item">
<div class="item-left">定位时间</div>
<div class="item-right">{{ value.locateTime }}</div>
<div class="item-right">{{ value.locationTime }}</div>
</div>
<div class="item">
<div class="item-left">位置</div>
@ -40,6 +42,8 @@ defineProps({
},
});
const emit = defineEmits(["close"]);
enum locateEnum {
"WIFI" = 0,
"LBS",
@ -48,7 +52,7 @@ enum locateEnum {
}
</script>
<style lang="scss" scoped>
<style lang="less" scoped>
.infoBox {
width: 400px;
background: #fff;

View File

@ -6,7 +6,7 @@
<div class="app-main" :class="{ 'content-collapse': sidebar.collapse }">
<router-view v-slot="{ Component }">
<transition name="move" mode="out-in">
<keep-alive>
<keep-alive :include="[]">
<component :is="Component"></component>
</keep-alive>
</transition>
@ -19,9 +19,24 @@
import { useSidebarStore } from "@/store/sidebar";
import vHeader from "@/components/header.vue";
import vSidebar from "@/components/sidebar.vue";
import { routes } from "@/router/index";
const sidebar = useSidebarStore();
console.log(sidebar);
const getInclude = (routeList: any) => {
if (!routeList) return [];
let list = [];
routeList.forEach((item) => {
if (item.meta && item.meta.keepAlive) {
list.push(item.name);
}
if (item.children && item.children.length) {
list = [...list, ...getInclude(item.children)];
}
});
return list;
};
// const include = getInclude(routes[0].children);
</script>
<style scoped lang="less">

View File

@ -22,7 +22,7 @@ export const mix = (color1: string, color2: string, weight: number = 0.5): strin
* @param {*} fmStr YYYY-MM-DD HH:mm:ss
* @returns
*/
export function format(time: Date | string, fmStr: string = "YYYY-MM-DD HH:mm:ss") {
export function format(time: Date | string | number, fmStr: string = "YYYY-MM-DD HH:mm:ss") {
if (!time) return "";
return dayjs(typeof time == 'string' ? new Date(time) : time).format(fmStr);
}

View File

@ -115,12 +115,36 @@ export class MapCustom {
icon,
position,
map: this.map,
offset: new AMap.Pixel(-25, -50),
offset: new AMap.Pixel(-20, -40),
})
}
lngLat(lng, lat) {
return new AMap.LngLat(lng, lat);
}
infoWindow(option = {
anchor: 'bottom-center',
isCustom: true, //使用自定义窗体
content: document.querySelector('.infoBox'),
offset: new AMap.Pixel(-2, -40),
}) {
return new AMap.InfoWindow(option)
}
//绘制轨迹线条
polyline(list) {
this.clearMap()
let Polyline = new AMap.Polyline({
map: this.map,
path: list.map((item) => [item.lng, item.lat]),
showDir: true,
strokeColor: '#0088F6', //线颜色
strokeWeight: 4 //线宽
})
this.map.setFitView(Polyline);
}
setCenter(position) {
this.map.setCenter(position)
}
clearMap() {
this.map.clearMap();

View File

@ -12,7 +12,7 @@
<div v-infinite-scroll="load" :infinite-scroll-immediate="false" class="device-list noScrollbar infinite-list" style="overflow: auto">
<el-popover :width="350" class="box-item" placement="bottom" v-for="item in list" :key="item.id">
<template #reference>
<div class="item">
<div class="item" :class="{ active: deviceId === item.deviceId }" @click="emit('click', item)">
<div class="item-img">
<img src="@/assets/img/handcuffs.png" alt="" srcset="" />
</div>
@ -74,8 +74,8 @@ enum modeEnum {
"审讯模式",
"户外押送",
}
const { list, paging, api } = defineProps({
const emit = defineEmits(["click"]);
const { list, paging, api, deviceId } = defineProps({
list: {
type: Array<TDevice.IListRes>,
default: () => [],
@ -88,6 +88,10 @@ const { list, paging, api } = defineProps({
type: Object,
default: () => {},
},
deviceId: {
type: Number || String,
default: () => "",
},
});
const handelMode = () => {
@ -145,6 +149,9 @@ const load = () => {
box-sizing: border-box;
border-bottom: 1px solid #dedede;
cursor: pointer;
&.active {
background: #f5f5f5;
}
&:hover {
background: #f5f5f5;
}

View File

@ -1,10 +1,12 @@
<template>
<div class="container">
<el-row class="el-row" :gutter="20">
<el-col :span="6" class="el-row-left"><DeviceInfo :paging="devicePaging" :api="getdeviceList" :list="deviceData" /></el-col>
<el-col :span="6" class="el-row-left"
><DeviceInfo :deviceId="deviceInfo?.deviceId" :paging="devicePaging" :api="getdeviceList" :list="deviceData" @click="handelClickDevice"
/></el-col>
<el-col :span="18" class="el-row-right scrollbar">
<MonitoringTop :funcList="funcList" />
<div v-if="deviceInfo?.status != 2">
<div v-if="deviceInfo?.status == 2">
<div class="monitoringMap" id="mapcontainer"></div>
<el-row :gutter="20" style="margin-top: 20px">
<el-col :span="12">
@ -44,16 +46,18 @@ import DeviceHistory from "./deviceHistory.vue";
import DeviceRecord from "./deviceRecord.vue";
import { MapCustom } from "@/utils/mapCustom";
import * as echarts from "echarts";
import { deviceList, healthLatestData, warningRecord } from "@/api/index";
import { deviceList, healthLatestData, warningRecord, locateRecord } from "@/api/index";
import { TDevice, THealthLatestData } from "@/api/index.d";
import { onMounted, onDeactivated, ref, reactive } from "vue";
import { debounce, format } from "@/utils";
import heart from "@/assets/img/heart.png";
import temperature from "@/assets/img/temperature.png";
import blood from "@/assets/img/blood.png";
import location from "@/assets/img/location.png";
const chartRef = ref(null);
let myChart = null;
let newMap = null;
let funcList = ref([
{ title: "当前心率", en: "DANGQIANXINLV", icon: heart, unit: "次/分", num: 0, color: "#FF0303" },
{ title: "当前血氧", en: "DANGQIANXUEYANG", icon: blood, unit: "%", num: 0, color: "#8B51FD" },
@ -86,13 +90,6 @@ const options = {
},
};
const paging = reactive({
page: 1,
size: 10,
total: 0,
status: undefined,
warnType: undefined,
});
const devicePaging = reactive({
page: 1,
size: 10,
@ -101,7 +98,6 @@ const devicePaging = reactive({
const HealthData = ref<THealthLatestData.TRes>();
const deviceInfo = ref<TDevice.IListRes>();
const tableData = ref<TDevice.IWarningRecordRes[]>([]);
const deviceData = ref<TDevice.IListRes[]>([]);
const getdeviceList = async () => {
@ -110,29 +106,20 @@ const getdeviceList = async () => {
if (res.records.length > 0) {
deviceInfo.value = res.records[1];
getHealthLatestData();
// getData();
getLocateRecord();
}
};
const getData = async () => {
const res = await warningRecord({ ...paging, deviceId: deviceInfo.value.deviceId });
tableData.value = res.records;
paging.total = res.total;
};
const getHealthLatestData = () => {
healthLatestData({ deviceId: deviceInfo.value.deviceId }).then((res) => {
HealthData.value = res;
funcList.value[0].num = res.hr;
funcList.value[1].num = res.bo;
funcList.value[2].num = res.temp;
getOptionsData(HealthData.value.hrArr, "心率", "#FF0303");
});
};
const changePage = (val: number) => {
paging.page = val;
getData();
};
const handelRadio = (val: number) => {
if (val == 1) {
getOptionsData(HealthData.value.hrArr, "心率", "#FF0303");
@ -145,22 +132,49 @@ const handelRadio = (val: number) => {
const getOptionsData = (list: { time: string; value: number }[], name: string, color: string) => {
options.xAxis.data = [];
options.series.data = [];
list.forEach((item) => {
options.xAxis.data.push(format(item.time, "HH:mm:ss"));
options.series.data.push(item.value);
});
options.series.name = name;
options.series.itemStyle.color = color;
if (list && list.length) {
list.forEach((item) => {
options.xAxis.data.push(format(item.time, "HH:mm:ss"));
options.series.data.push(item.value);
});
options.series.name = name;
options.series.itemStyle.color = color;
}
myChart.setOption(options);
};
const getLocateRecord = () => {
let d = new Date();
locateRecord({
deviceId: deviceInfo.value.deviceId,
startDate: `${format(d, "YYYY-MM-DD")} 00:00:00`,
endDate: `${format(d, "YYYY-MM-DD")} 23:59:59`,
}).then((res) => {
if (res && res.length) {
let list = res;
newMap.clearMap();
newMap.setCenter([list[0].lng, list[0].lat]);
newMap.polyline(list);
let icon = newMap.newIcon(location);
list.forEach((item) => {
let marker = newMap.marker({ icon, position: [item.lng, item.lat] });
marker.setMap(newMap.map);
});
}
});
};
const handleResize = debounce(() => {
myChart.resize();
}, 200);
const handelClickDevice = (val: TDevice.IListRes) => {
deviceInfo.value = val;
getHealthLatestData();
getLocateRecord();
};
onMounted(() => {
getdeviceList();
new MapCustom({ dom: "mapcontainer" });
newMap = new MapCustom({ dom: "mapcontainer" });
if (chartRef.value) {
myChart = echarts.init(chartRef.value);
window.addEventListener("resize", handleResize);

View File

@ -39,14 +39,7 @@
<template #header>
<div class="card-header">当前设备告警记录</div>
</template>
<TableCustom
:hasToolbar="false"
:columns="columns"
:tableData="warningTableData"
:total="paging1.total"
:currentPage="paging1.page"
:changePage="changeWarningPage"
>
<TableCustom :hasToolbar="false" :columns="columns" :tableData="warningTableData" :paging="paging1" :changePage="changeWarningPage">
<template #operator="{ rows }">
<el-button link type="primary" size="small" @click="toIncidentDispose(rows.id)" v-if="rows.status == 0"> 处理事件 </el-button>
<div v-else></div>

View File

@ -2,7 +2,7 @@
<div class="container">
<TableSearch :query="query" :options="searchOpt" :search="handleSearch" />
<div class="table-container">
<TableCustom :columns="columns" :tableData="tableData" :paging="paging" :refresh="getData" :changePage="changePage">
<TableCustom :columns="columns" :tableData="tableData" :paging="paging" :changePage="changePage">
<template #toolbarBtn>
<!-- <el-button type="primary" @click="handleAdd">新增</el-button> -->
<el-button @click="handleEdit">手铐关联</el-button>
@ -13,11 +13,14 @@
<template #status="{ rows }">
<el-tag :type="statusColor[rows.status]">{{ statusEnum[rows.status] }}</el-tag>
</template>
<template #mode="{ rows }">
<el-tag :type="modeColor[rows.mode]">{{ modeEnum[rows.mode] }}</el-tag>
<template #useStatus="{ rows }">
<el-switch v-model="rows.useStatus" :active-value="1" :inactive-value="0" @click="handelSwitch(rows, 1)" />
</template>
<template #deviceSwitch="{ rows }">
<el-switch v-model="rows.deviceSwitch" />
<el-switch v-model="rows.deviceSwitch" :active-value="1" :inactive-value="0" @click="handelSwitch(rows, 2)" />
</template>
<template #mode="{ rows }">
<el-tag :type="modeColor[rows.mode]">{{ modeEnum[rows.mode] }}</el-tag>
</template>
<template #battery="{ rows }"> {{ rows.battery }}% </template>
<template #operator="{ rows }">
@ -44,7 +47,7 @@
<script setup lang="ts" name="basetable">
import { ref, reactive, onMounted } from "vue";
import { ElMessage } from "element-plus";
import { deviceList, setMode, deviceGetLocation, deviceControl } from "@/api/index";
import { deviceList, setMode, deviceGetLocation, deviceControl, setUseStatus, setStatus } from "@/api/index";
import { TDevice } from "@/api/index.d";
import TableCustom from "@/components/table-custom.vue";
import TableSearch from "@/components/table-search.vue";
@ -107,7 +110,8 @@ let columns = ref([
{ prop: "deviceVersion", label: "版本号" },
{ prop: "status", label: "设备状态" },
{ prop: "mode", label: "当前模式" },
{ prop: "deviceSwitch", label: "开关" },
{ prop: "useStatus", label: "使用状态" },
{ prop: "deviceSwitch", label: "启用开关" },
{ prop: "orgName", label: "关联辖区编号" },
{ prop: "createTime", label: "最新通信时间" },
{ prop: "createTime", label: "创建时间" },
@ -159,7 +163,16 @@ const handelRow = (row?: TDevice.IListRes) => {
controlForm.mode = row.mode;
visible1.value = true;
};
const handelSwitch = (val: TDevice.IListRes, type: number) => {
let api = type == 1 ? setUseStatus : setStatus;
api({
deviceId: val.deviceId,
status: type == 1 ? val.useStatus : val.deviceSwitch,
}).then(() => {
getData();
ElMessage.success("操作成功");
});
};
const handelControl = (type: number) => {
switch (type) {
case 4:
@ -216,7 +229,7 @@ const toPage = (path: string, row: TDevice.IListRes) => {
if (path == "deviceInfo") {
p = { ...row };
} else if (path == "mapLocation") {
p = { id: row.id };
p = { deviceId: row.deviceId };
} else if (path == "setting") {
p = { deviceId: row.deviceId };
}

View File

@ -17,23 +17,11 @@
range-separator="-"
start-placeholder="开始时间"
end-placeholder="结束时间"
v-model="time"
@change="timeChange"
/>
<el-date-picker v-else type="week" value-format="YYYY-MM-DD/ww" placeholder="请选择周" @change="weekChange" />
<el-date-picker v-model="week" v-else type="week" value-format="YYYY-MM-DD" placeholder="请选择周" @change="weekChange" />
</div>
<el-select
v-model="value"
multiple
filterable
remote
reserve-keyword
placeholder="请输入设备IMEI"
:remote-method="remoteMethod"
:loading="loading"
style="width: 240px"
>
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
<!-- <span>位置样式</span>
<el-radio-group v-model="styleType">
<el-radio-button :value="1"></el-radio-button>
@ -66,49 +54,76 @@
<el-col :span="24" class="container-right">
</el-col>
</el-row> -->
<div :style="{ display: 'none' }">
<InfoWindow class="infoBox" :value="deviceInfo" @close="InfoWin.close()" />
</div>
</div>
</template>
<script setup lang="ts">
import handcuffs from "@/assets/img/handcuffs.png";
import { onMounted } from "vue";
import { onMounted, reactive } from "vue";
import { MapCustom } from "@/utils/mapCustom";
import { ref } from "vue";
interface ListItem {
value: string;
label: string;
}
let tabs = [
{ label: "全部", value: "0" },
{ label: "未处理", value: "1" },
{ label: "已处理", value: "2" },
];
import { locateRecord } from "@/api";
import { format } from "@/utils";
import { TLocateRecord } from "@/api/index.d";
import { useRoute } from "vue-router";
import location from "@/assets/img/location.png";
import InfoWindow from "@/components/InfoWindow.vue";
const { query } = useRoute();
let d = new Date();
let newMap = null;
let time = ref([new Date(`${format(d, "YYYY-MM-DD")} 00:00:00`), new Date(`${format(d, "YYYY-MM-DD")} 23:59:59`)]);
let week = ref(d);
let deviceInfo = ref({});
let sectionType = ref(1);
let styleType = ref(1);
let InfoWin = null;
const list = ref<ListItem[]>([]);
const options = ref<ListItem[]>([]);
const value = ref<string[]>([]);
const loading = ref(false);
const params = reactive<TLocateRecord.TReq>({
deviceId: query.deviceId as string,
// startDate: `${format(d, "YYYY-MM-DD")} 00:00:00`,
// endDate: `${format(d, "YYYY-MM-DD")} 23:59:59`,
startDate: "2021-04-14 00:00:00",
endDate: "2025-05-14 23:59:59",
});
//
const weekChange = (value: any) => {};
const remoteMethod = (query: string) => {
if (query) {
loading.value = true;
setTimeout(() => {
loading.value = false;
options.value = list.value.filter((item) => {
return item.label.toLowerCase().includes(query.toLowerCase());
const weekChange = (val: any) => {
let endTime = new Date(val).getTime() + 6 * 24 * 60 * 60 * 1000;
params.startDate = `${val} 00:00:00`;
params.endDate = `${format(endTime, "YYYY-MM-DD")} 23:59:59`;
getLocateRecord();
};
const timeChange = (val: any) => {
params.startDate = `${format(val[0], "YYYY-MM-DD")} 00:00:00`;
params.endDate = `${format(val[1], "YYYY-MM-DD")} 23:59:59`;
getLocateRecord();
};
const getLocateRecord = () => {
locateRecord(params).then((res) => {
if (res && res.length) {
let list = res;
newMap.clearMap();
newMap.setCenter([list[0].lng, list[0].lat]);
newMap.polyline(list);
let icon = newMap.newIcon(location);
list.forEach((item) => {
let marker = newMap.marker({ icon, position: [item.lng, item.lat] });
marker.setMap(newMap.map);
marker.on("click", () => {
deviceInfo.value = item;
InfoWin = newMap.infoWindow();
InfoWin.open(newMap.map, marker.getPosition());
});
});
}, 200);
} else {
options.value = [];
}
}
});
};
onMounted(() => {
new MapCustom({ dom: "mapcontainer" });
newMap = new MapCustom({ dom: "mapcontainer" });
getLocateRecord();
});
</script>

View File

@ -41,16 +41,16 @@
<TableEdit :form-data="rowData" :options="options" :edit="isEdit" :update="updateData" @close="closeDialog" />
</el-dialog>
<el-dialog title="编辑类型" v-model="typeVisible" width="800px" destroy-on-close :close-on-click-modal="false" @close="closeDialog">
<UserType />
<UserType :typeHeadList="typeHeadList" :roleListData="roleListData" @complete="saveType" @addType="addType" />
</el-dialog>
<BatchImp ref="batchImpRef" @success="handleSearch" />
</div>
</template>
<script setup lang="ts" name="basetable">
import { ref, reactive } from "vue";
import { ref, reactive, onMounted } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import { accountAdd, accountModify, accountList, accountDeletet, passwordReset, roleList } from "@/api/index";
import { accountAdd, accountModify, accountList, accountDeletet, passwordReset, roleList, roleMenuList, roleModify } from "@/api/index";
import TableCustom from "@/components/table-custom.vue";
import TableSearch from "@/components/table-search.vue";
import TableEdit from "@/components/table-edit.vue";
@ -59,7 +59,7 @@ import { useCommonStore } from "@/store/common";
import UserType from "./userType.vue";
import { TableItem } from "@/types/table";
import { FormOption, FormOptionList } from "@/types/form-option";
import { TAccount, TRoleList } from "@/api/index.d";
import { TAccount, TRoleList, TRoleMenuList } from "@/api/index.d";
// import { Hide, View } from "@element-plus/icons-vue";
enum roleEnum {
@ -75,7 +75,8 @@ const typeVisible = ref(false);
const isEdit = ref(false);
const dialogTitle = ref("");
const rowData = ref<TAccount.IListRes | undefined>();
//
let typeHeadList = ref<TRoleMenuList.TRes[]>([]);
//
const query = reactive({
name: "",
@ -182,6 +183,7 @@ const changePage = (val: number) => {
};
const roleListFn = () => {
roleList().then((res) => {
roleListData.value = res;
let opts = res?.map((item) => {
return { label: item.name, value: item.id };
});
@ -196,8 +198,6 @@ const getData = async () => {
});
paging.total = res.total;
};
roleListFn();
getData();
//
const handelDel = (row: TableItem) => {
@ -229,7 +229,16 @@ const updateData = (res) => {
getData();
});
};
const saveType = (row: TRoleList) => {
roleModify(row).then(() => {
ElMessage.success("保存成功");
roleListFn();
typeVisible.value = false;
});
};
const addType = () => {
roleListData.value.push({ name: "", roleMenu: [] });
};
const closeDialog = () => {
visible.value = false;
isEdit.value = false;
@ -254,6 +263,16 @@ const handelRow = (name: string, row?: TAccount.IListRes) => {
}
visible.value = true;
};
const getRoleMenuList = () => {
roleMenuList().then((res) => {
typeHeadList.value = res;
});
};
onMounted(() => {
roleListFn();
getData();
getRoleMenuList();
});
</script>
<style scoped>

View File

@ -1,51 +1,21 @@
<template>
<div>
<el-table :data="tableData" style="width: 100%">
<el-table :data="roleListData" style="width: 100%">
<el-table-column prop="name" label="" width="150" align="center">
<template #default="{ row }">
<el-checkbox value="Value 1" size="large" v-if="row.flag" />
<el-input v-model="row.name" v-else />
<el-input v-model="row.name" />
</template>
</el-table-column>
<el-table-column prop="date" label="web管理权限" width="150" align="center">
<template #default="{ row }">
<el-checkbox size="large" v-model="row.check" disabled>
<template #default>
<div class="box box1" v-if="!row.check">
<el-icon><CloseBold style="color: red" /></el-icon>
</div>
<div class="box box2" v-else>
<el-icon><Select style="color: #fff" /></el-icon>
</div>
</template>
</el-checkbox>
</template>
</el-table-column>
<el-table-column label="APP权限" align="center">
<el-table-column prop="name" label="手铐管理权限" align="center">
<el-table-column :label="item.name" align="center" v-for="(item, index) in typeHeadList" :key="index">
<el-table-column prop="name" :label="ite.name" align="center" v-for="(ite, ide) in item.menus" :key="`${index}_${ide}`">
<template #default="{ row }">
<el-checkbox value="Value 1" size="large" disabled>
<el-checkbox value="Value 1" size="large">
<template #default>
<div class="box box1" v-if="!row.check">
<div class="box box1" v-if="!isCheck(ite, row)" @click="clickItem(ite, row)">
<el-icon><CloseBold style="color: red" /></el-icon>
</div>
<div class="box box2" v-else>
<el-icon><Select style="color: #fff" /></el-icon>
</div>
</template>
</el-checkbox>
</template>
</el-table-column>
<el-table-column prop="name" label="告警管理权限" align="center">
<template #default="{ row }">
<el-checkbox value="Value 1" size="large" disabled>
<template #default>
<div class="box box1" v-if="!row.check">
<el-icon><CloseBold style="color: red" /></el-icon>
</div>
<div class="box box2" v-else>
<div class="box box2" v-else @click="clickItem(ite, row)">
<el-icon><Select style="color: #fff" /></el-icon>
</div>
</template>
@ -55,50 +25,47 @@
</el-table-column>
<el-table-column prop="date" label="操作" width="200" align="center">
<template #default="scope">
<el-button link type="primary" size="small">锁定</el-button>
<el-button link type="primary" size="small">修改</el-button>
<template #default="{ row }">
<el-button link type="primary" size="small" @click="emit('complete', row)">保存</el-button>
</template>
</el-table-column>
</el-table>
<el-button class="mt-4" style="width: 100%" @click="addType"> 添加类型 </el-button>
<el-button class="mt-4" style="width: 100%" @click="emit('addType')"> 添加类型 </el-button>
</div>
</template>
<script setup lang="ts">
import { ref } from "vue";
import { TRoleList, TRoleMenuList } from "@/api/index.d";
import { PropType, ref } from "vue";
const tableData = ref([
{
name: "管理员",
flag: false,
check: false,
const { roleListData, typeHeadList } = defineProps({
typeHeadList: {
type: Array as PropType<TRoleMenuList.TRes[]>,
default: () => [],
},
{
name: "警察",
flag: false,
check: false,
roleListData: {
type: Array as PropType<TRoleList[]>,
default: () => [],
},
{
name: "辅警",
flag: false,
check: false,
},
{
name: "协警",
flag: false,
check: true,
},
]);
});
const addType = () => {
tableData.value = [
...tableData.value,
{
name: "",
flag: false,
check: false,
},
];
const emit = defineEmits(["complete", "addType"]);
const isCheck = (ite, row) => {
let flag = false;
row.roleMenu.forEach((item) => {
if (ite.id == item.id) {
flag = true;
}
});
return flag;
};
const clickItem = (val, e) => {
let flag = e.roleMenu.some((item) => val.id == item.id);
if (!flag) {
e.roleMenu.push(val);
} else {
e.roleMenu = e.roleMenu.filter((item) => item.id != val.id);
}
};
</script>