2025年04月11日18:46:50
This commit is contained in:
parent
3346134b9a
commit
f82d3934ba
@ -1 +1,2 @@
|
||||
VITE_APP_URL = 'http://192.168.3.116:8001'
|
||||
VITE_APP_URL_WEBSOCKET = 'http://192.168.3.116:8000/api/websocket'
|
||||
|
@ -1,3 +1,4 @@
|
||||
VITE_APP_URL = 'http://192.168.3.116:8001/'
|
||||
VITE_APP_URL_WEBSOCKET = 'http://192.168.3.116:8000/api/websocket'
|
||||
|
||||
|
||||
|
2
auto-imports.d.ts
vendored
2
auto-imports.d.ts
vendored
@ -1,5 +1,5 @@
|
||||
// Generated by 'unplugin-auto-import'
|
||||
export {}
|
||||
declare global {
|
||||
|
||||
const ElMessage: typeof import('element-plus/es')['ElMessage']
|
||||
}
|
||||
|
10
src/api/index.d.ts
vendored
10
src/api/index.d.ts
vendored
@ -20,7 +20,7 @@ export interface TRoleList {
|
||||
id?: number
|
||||
name: string
|
||||
createTime?: string
|
||||
roleMenu: TRoleMenu[]
|
||||
roleMenu?: TRoleMenu[]
|
||||
}
|
||||
|
||||
|
||||
@ -81,9 +81,10 @@ export interface TDeviceConfigModify {
|
||||
|
||||
export namespace TRoleModify {
|
||||
export interface Ireq {
|
||||
id: number
|
||||
id?: number
|
||||
name: string
|
||||
roleMenu: TRoleMenu[]
|
||||
menus?: TRoleMenu[]
|
||||
}
|
||||
}
|
||||
|
||||
@ -257,9 +258,6 @@ export namespace TDevice {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
export namespace TOrg {
|
||||
export interface IAdd {
|
||||
name: string;
|
||||
@ -267,7 +265,7 @@ export namespace TOrg {
|
||||
parentId: string;
|
||||
}
|
||||
export interface IListReq extends Ipaging {
|
||||
name?: number;
|
||||
name?: string;
|
||||
}
|
||||
export interface Idel {
|
||||
id: number;
|
||||
|
@ -3,7 +3,7 @@ import { TLogin, TAccount, IpagingRes, TDevice, TOrg, TRoleList, TStatisticsDevi
|
||||
|
||||
export const fetchLogin = (p: TLogin.Ireq): Promise<TLogin.IRes> => {
|
||||
return request({
|
||||
url: '/v1/web/login',
|
||||
url: '/v1/api/login',
|
||||
method: 'post',
|
||||
data: p
|
||||
});
|
||||
@ -12,7 +12,7 @@ export const fetchLogin = (p: TLogin.Ireq): Promise<TLogin.IRes> => {
|
||||
// 批量导入账号样例
|
||||
export const exportDemoAccount = (): Promise<any> => {
|
||||
return request({
|
||||
url: '/v1/web/upload/exportDemo/account',
|
||||
url: '/v1/api/upload/exportDemo/account',
|
||||
method: 'get',
|
||||
responseType: 'blob'
|
||||
});
|
||||
@ -47,7 +47,7 @@ export const fetchRoleData = () => {
|
||||
// 添加用户
|
||||
export const accountAdd = (p: TAccount.IAdd): Promise<null> => {
|
||||
return request({
|
||||
url: '/v1/web/account/add',
|
||||
url: '/v1/api/account/add',
|
||||
method: 'post',
|
||||
data: p
|
||||
});
|
||||
@ -55,7 +55,7 @@ export const accountAdd = (p: TAccount.IAdd): Promise<null> => {
|
||||
// 删除用户
|
||||
export const accountDeletet = (p: TAccount.Idel): Promise<null> => {
|
||||
return request({
|
||||
url: '/v1/web/account/delete',
|
||||
url: '/v1/api/account/delete',
|
||||
method: 'post',
|
||||
data: p
|
||||
});
|
||||
@ -63,7 +63,7 @@ export const accountDeletet = (p: TAccount.Idel): Promise<null> => {
|
||||
// 修改用户
|
||||
export const accountModify = (p: TAccount.IAdd): Promise<null> => {
|
||||
return request({
|
||||
url: '/v1/web/account/modify',
|
||||
url: '/v1/api/account/modify',
|
||||
method: 'post',
|
||||
data: p
|
||||
});
|
||||
@ -71,7 +71,7 @@ export const accountModify = (p: TAccount.IAdd): Promise<null> => {
|
||||
// 获取用户列表
|
||||
export const accountList = (p: TAccount.IListReq): Promise<IpagingRes<TAccount.IListRes>> => {
|
||||
return request({
|
||||
url: '/v1/web/account/list',
|
||||
url: '/v1/api/account/list',
|
||||
method: 'get',
|
||||
params: p
|
||||
});
|
||||
@ -79,7 +79,7 @@ export const accountList = (p: TAccount.IListReq): Promise<IpagingRes<TAccount.I
|
||||
// 重置密码
|
||||
export const passwordReset = (p: TAccount.IResetPwd): Promise<null> => {
|
||||
return request({
|
||||
url: '/v1/web/account/password/reset',
|
||||
url: '/v1/api/account/password/reset',
|
||||
method: 'post',
|
||||
data: p
|
||||
});
|
||||
@ -89,7 +89,7 @@ export const passwordReset = (p: TAccount.IResetPwd): Promise<null> => {
|
||||
// 获取设备列表
|
||||
export const deviceList = (p: TDevice.IListReq): Promise<IpagingRes<TDevice.IListRes>> => {
|
||||
return request({
|
||||
url: '/v1/web/device/list',
|
||||
url: '/v1/api/device/list',
|
||||
method: 'get',
|
||||
params: p
|
||||
});
|
||||
@ -98,7 +98,7 @@ export const deviceList = (p: TDevice.IListReq): Promise<IpagingRes<TDevice.ILis
|
||||
// 设置监测模式
|
||||
export const setMonitor = (p: TDevice.ISetMonitor): Promise<null> => {
|
||||
return request({
|
||||
url: '/v1/web/device/set/monitor',
|
||||
url: '/v1/api/device/set/monitor',
|
||||
method: 'post',
|
||||
data: p
|
||||
});
|
||||
@ -107,7 +107,7 @@ export const setMonitor = (p: TDevice.ISetMonitor): Promise<null> => {
|
||||
// 设置模式
|
||||
export const setMode = (p: TDevice.ISetMonitor): Promise<null> => {
|
||||
return request({
|
||||
url: '/v1/web/device/set/mode',
|
||||
url: '/v1/api/device/set/mode',
|
||||
method: 'post',
|
||||
data: p
|
||||
});
|
||||
@ -116,7 +116,7 @@ export const setMode = (p: TDevice.ISetMonitor): Promise<null> => {
|
||||
// 获取定位
|
||||
export const deviceGetLocation = (p: TDevice.ISetMonitor): Promise<null> => {
|
||||
return request({
|
||||
url: '/v1/web/device/getLocate',
|
||||
url: '/v1/api/device/getLocate',
|
||||
method: 'post',
|
||||
data: p
|
||||
});
|
||||
@ -125,7 +125,7 @@ export const deviceGetLocation = (p: TDevice.ISetMonitor): Promise<null> => {
|
||||
// 设备控制
|
||||
export const deviceControl = (p: TDevice.ISetMonitor): Promise<null> => {
|
||||
return request({
|
||||
url: '/v1/web/device/control',
|
||||
url: '/v1/api/device/control',
|
||||
method: 'post',
|
||||
data: p
|
||||
});
|
||||
@ -134,7 +134,7 @@ export const deviceControl = (p: TDevice.ISetMonitor): Promise<null> => {
|
||||
// 设备使用记录
|
||||
export const deviceUseRecord = (p: TDevice.IRecordReq): Promise<IpagingRes<TDevice.IUseRecordRes>> => {
|
||||
return request({
|
||||
url: '/v1/web/device/use/record',
|
||||
url: '/v1/api/device/use/record',
|
||||
method: 'get',
|
||||
params: p
|
||||
});
|
||||
@ -143,7 +143,7 @@ export const deviceUseRecord = (p: TDevice.IRecordReq): Promise<IpagingRes<TDevi
|
||||
// 预警记录
|
||||
export const warningRecord = (p: TDevice.IRecordReq): Promise<IpagingRes<TDevice.IWarningRecordRes>> => {
|
||||
return request({
|
||||
url: '/v1/web/warning/record',
|
||||
url: '/v1/api/warning/record',
|
||||
method: 'get',
|
||||
params: p
|
||||
});
|
||||
@ -152,7 +152,7 @@ export const warningRecord = (p: TDevice.IRecordReq): Promise<IpagingRes<TDevice
|
||||
// 新增机构
|
||||
export const orgAdd = (p: TOrg.IAdd): Promise<null> => {
|
||||
return request({
|
||||
url: '/v1/web/org/add',
|
||||
url: '/v1/api/org/add',
|
||||
method: 'post',
|
||||
data: p
|
||||
});
|
||||
@ -160,7 +160,7 @@ export const orgAdd = (p: TOrg.IAdd): Promise<null> => {
|
||||
// 修改机构
|
||||
export const orgModify = (p: TOrg.IAdd): Promise<null> => {
|
||||
return request({
|
||||
url: '/v1/web/org/modify',
|
||||
url: '/v1/api/org/modify',
|
||||
method: 'post',
|
||||
data: p
|
||||
});
|
||||
@ -168,7 +168,7 @@ export const orgModify = (p: TOrg.IAdd): Promise<null> => {
|
||||
// 机构列表
|
||||
export const orgList = (p?: TOrg.IListReq): Promise<IpagingRes<TOrg.IOrgRecordRes>> => {
|
||||
return request({
|
||||
url: '/v1/web/org/list',
|
||||
url: '/v1/api/org/page',
|
||||
method: 'get',
|
||||
params: p
|
||||
});
|
||||
@ -177,7 +177,7 @@ export const orgList = (p?: TOrg.IListReq): Promise<IpagingRes<TOrg.IOrgRecordRe
|
||||
// 删除机构
|
||||
export const orgDelete = (p?: TOrg.Idel): Promise<null> => {
|
||||
return request({
|
||||
url: '/v1/web/org/delete',
|
||||
url: '/v1/api/org/delete',
|
||||
method: 'post',
|
||||
data: p
|
||||
});
|
||||
@ -186,7 +186,7 @@ export const orgDelete = (p?: TOrg.Idel): Promise<null> => {
|
||||
// 获取角色列表
|
||||
export const roleList = (): Promise<TRoleList[]> => {
|
||||
return request({
|
||||
url: '/v1/web/role/list',
|
||||
url: '/v1/api/role/list',
|
||||
method: 'get',
|
||||
});
|
||||
};
|
||||
@ -194,7 +194,16 @@ export const roleList = (): Promise<TRoleList[]> => {
|
||||
// 修改角色信息
|
||||
export const roleModify = (p: TRoleModify.Ireq): Promise<null> => {
|
||||
return request({
|
||||
url: '/v1/web/role/modify',
|
||||
url: '/v1/api/role/modify',
|
||||
method: 'post',
|
||||
data: p
|
||||
});
|
||||
};
|
||||
|
||||
// 添加角色信息
|
||||
export const roleAdd = (p: TRoleModify.Ireq): Promise<null> => {
|
||||
return request({
|
||||
url: '/v1/api/role/add',
|
||||
method: 'post',
|
||||
data: p
|
||||
});
|
||||
@ -203,7 +212,7 @@ export const roleModify = (p: TRoleModify.Ireq): Promise<null> => {
|
||||
// 设备在线统计
|
||||
export const statisticsDevice = (): Promise<TStatisticsDevice> => {
|
||||
return request({
|
||||
url: '/v1/web/statistics/device',
|
||||
url: '/v1/api/statistics/device',
|
||||
method: 'get',
|
||||
});
|
||||
};
|
||||
@ -211,7 +220,7 @@ export const statisticsDevice = (): Promise<TStatisticsDevice> => {
|
||||
// 内容数据
|
||||
export const statisticsContent = (p: statisticsContentReq): Promise<statisticsContentRes> => {
|
||||
return request({
|
||||
url: '/v1/web/statistics/content',
|
||||
url: '/v1/api/statistics/content',
|
||||
method: 'post',
|
||||
data: p
|
||||
});
|
||||
@ -220,7 +229,7 @@ export const statisticsContent = (p: statisticsContentReq): Promise<statisticsCo
|
||||
// 获取统计数据
|
||||
export const statisticsCount = (): Promise<TStatisticsCount> => {
|
||||
return request({
|
||||
url: '/v1/web/statistics/count',
|
||||
url: '/v1/api/statistics/count',
|
||||
method: 'get',
|
||||
});
|
||||
};
|
||||
@ -228,7 +237,7 @@ export const statisticsCount = (): Promise<TStatisticsCount> => {
|
||||
// 告警统计
|
||||
export const statisticsWarningapi = (): Promise<statisticsContentRes> => {
|
||||
return request({
|
||||
url: '/v1/web/statistics/warning',
|
||||
url: '/v1/api/statistics/warning',
|
||||
method: 'get',
|
||||
});
|
||||
};
|
||||
@ -236,7 +245,7 @@ export const statisticsWarningapi = (): Promise<statisticsContentRes> => {
|
||||
// 预警记录
|
||||
export const warnRecord = (p: TWarnRecord.IListReq): Promise<IpagingRes<TWarnRecord.IListRes>> => {
|
||||
return request({
|
||||
url: '/v1/web/warning/record',
|
||||
url: '/v1/api/warning/record',
|
||||
method: 'get',
|
||||
params: p
|
||||
});
|
||||
@ -245,7 +254,7 @@ export const warnRecord = (p: TWarnRecord.IListReq): Promise<IpagingRes<TWarnRec
|
||||
// 预警记录
|
||||
export const warningDetail = (p: TWarningDetail.TParams): Promise<TWarningDetail.TRes> => {
|
||||
return request({
|
||||
url: '/v1/web/warning/detail',
|
||||
url: '/v1/api/warning/detail',
|
||||
method: 'get',
|
||||
params: p
|
||||
});
|
||||
@ -254,7 +263,7 @@ export const warningDetail = (p: TWarningDetail.TParams): Promise<TWarningDetail
|
||||
// 预警记录
|
||||
export const warningConfirm = (p: TWarningConfirm): Promise<null> => {
|
||||
return request({
|
||||
url: '/v1/web/warning/confirm',
|
||||
url: '/v1/api/warning/confirm',
|
||||
method: 'post',
|
||||
data: p
|
||||
});
|
||||
@ -263,7 +272,7 @@ export const warningConfirm = (p: TWarningConfirm): Promise<null> => {
|
||||
// 获取专项配置
|
||||
export const deviceConfig = (p: TDeviceConfig.Treq): Promise<TDeviceConfig.Tres> => {
|
||||
return request({
|
||||
url: '/v1/web/device/deviceConfig',
|
||||
url: '/v1/api/device/deviceConfig',
|
||||
method: 'get',
|
||||
params: p
|
||||
});
|
||||
@ -272,7 +281,7 @@ export const deviceConfig = (p: TDeviceConfig.Treq): Promise<TDeviceConfig.Tres>
|
||||
// 修改专项配置
|
||||
export const deviceConfigModify = (p: TDeviceConfigModify): Promise<null> => {
|
||||
return request({
|
||||
url: '/v1/web/device/deviceConfig/modify',
|
||||
url: '/v1/api/device/deviceConfig/modify',
|
||||
method: 'post',
|
||||
data: p
|
||||
});
|
||||
@ -281,7 +290,7 @@ export const deviceConfigModify = (p: TDeviceConfigModify): Promise<null> => {
|
||||
// 获取最新健康数据
|
||||
export const healthLatestData = (p: THealthLatestData.TReq): Promise<THealthLatestData.TRes> => {
|
||||
return request({
|
||||
url: '/v1/web/health/latestData',
|
||||
url: '/v1/api/health/latestData',
|
||||
method: 'get',
|
||||
params: p
|
||||
});
|
||||
@ -290,7 +299,7 @@ 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',
|
||||
url: '/v1/api/device/locate/record',
|
||||
method: 'get',
|
||||
params: p
|
||||
});
|
||||
@ -299,7 +308,7 @@ export const locateRecord = (p: TLocateRecord.TReq): Promise<TLocateRecord.TRes[
|
||||
// 设置使用状态
|
||||
export const setUseStatus = (p: TSetUseStatus.TReq): Promise<null> => {
|
||||
return request({
|
||||
url: '/v1/web/device/set/useStatus',
|
||||
url: '/v1/api/device/set/useStatus',
|
||||
method: 'post',
|
||||
data: p
|
||||
});
|
||||
@ -308,7 +317,7 @@ export const setUseStatus = (p: TSetUseStatus.TReq): Promise<null> => {
|
||||
// 设置禁用状态
|
||||
export const setStatus = (p: TSetUseStatus.TReq): Promise<null> => {
|
||||
return request({
|
||||
url: '/v1/web/device/set/status',
|
||||
url: '/v1/api/device/set/status',
|
||||
method: 'post',
|
||||
data: p
|
||||
});
|
||||
@ -317,7 +326,7 @@ export const setStatus = (p: TSetUseStatus.TReq): Promise<null> => {
|
||||
// 获取菜单列表
|
||||
export const roleMenuList = (): Promise<TRoleMenuList.TRes[]> => {
|
||||
return request({
|
||||
url: '/v1/web/role/menu/list',
|
||||
url: '/v1/api/role/menu/list',
|
||||
method: 'get',
|
||||
});
|
||||
};
|
||||
|
BIN
src/assets/audio/warning1.mp3
Normal file
BIN
src/assets/audio/warning1.mp3
Normal file
Binary file not shown.
@ -18,9 +18,9 @@
|
||||
<div class="button-glow"></div>
|
||||
</button>
|
||||
|
||||
<!-- <audio ref="audioPlayer" autoplay loop>
|
||||
<source src="../assets/audio/alarm.mp3" type="video/mp3" />
|
||||
</audio> -->
|
||||
<audio ref="audioPlayer" hidden>
|
||||
<source src="../assets/audio/alarm.mp3" type="audio/mpeg" />
|
||||
</audio>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
@ -43,14 +43,16 @@ defineProps({
|
||||
},
|
||||
});
|
||||
|
||||
defineEmits(["close", "confirm"]);
|
||||
const emit = defineEmits(["close", "confirm"]);
|
||||
|
||||
const handleAudioEnd = () => {
|
||||
if (audioPlayer.value) {
|
||||
audioPlayer.value.play().catch((error) => {
|
||||
console.error("自动播放被阻止:", error);
|
||||
});
|
||||
}
|
||||
emit("close");
|
||||
|
||||
// if (audioPlayer.value) {
|
||||
// audioPlayer.value.play().catch((error) => {
|
||||
// console.error("自动播放被阻止:", error);
|
||||
// });
|
||||
// }
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
|
@ -34,7 +34,7 @@ interface Tdata {
|
||||
}
|
||||
|
||||
const comm = useCommonStore();
|
||||
const ACTION = import.meta.env.VITE_APP_URL + "/v1/web/upload/account";
|
||||
const ACTION = import.meta.env.VITE_APP_URL + "/v1/api/upload/account";
|
||||
const HEADERS = {
|
||||
"Access-Token": comm.user.token,
|
||||
};
|
||||
|
@ -24,6 +24,7 @@
|
||||
style="width: 220px"
|
||||
v-else-if="item.type === 'daterange'"
|
||||
v-model="query[item.prop]"
|
||||
value-format="YYYY-MM-DD"
|
||||
type="daterange"
|
||||
range-separator="-"
|
||||
start-placeholder="开始日期"
|
||||
|
@ -1,17 +1,20 @@
|
||||
<template>
|
||||
<el-upload
|
||||
:style="`--width: ${size}px; --height: ${size}px`"
|
||||
:style="`--width: ${props.size}px; --height: ${props.size}px`"
|
||||
class="upload"
|
||||
:class="{ hide: disabled }"
|
||||
accept="image/*"
|
||||
list-type="picture-card"
|
||||
v-model:file-list="fileList"
|
||||
:action="ACTION"
|
||||
:headers="HEADERS"
|
||||
name="files"
|
||||
:on-preview="handlePictureCardPreview"
|
||||
:on-remove="handleRemove"
|
||||
:on-success="handleSuccess"
|
||||
:limit="9"
|
||||
:before-upload="beforeUpload"
|
||||
:disabled="disabled"
|
||||
>
|
||||
<el-icon><Plus /></el-icon>
|
||||
</el-upload>
|
||||
@ -22,9 +25,9 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from "vue";
|
||||
import { ref, watch } from "vue";
|
||||
import { Plus } from "@element-plus/icons-vue";
|
||||
import { ElMessage, UploadProps } from "element-plus";
|
||||
import { ElMessage, UploadFiles, UploadProps } from "element-plus";
|
||||
import { useCommonStore } from "@/store/common";
|
||||
|
||||
interface Tdata {
|
||||
@ -35,12 +38,12 @@ interface Tdata {
|
||||
msg: string;
|
||||
}
|
||||
const comm = useCommonStore();
|
||||
const ACTION = import.meta.env.VITE_APP_URL + "/v1/web/upload/warning/img";
|
||||
const ACTION = import.meta.env.VITE_APP_URL + "/v1/api/upload/warning/img";
|
||||
const HEADERS = {
|
||||
"Access-Token": comm.user.token,
|
||||
};
|
||||
|
||||
const { size, modelValue } = defineProps({
|
||||
const props = defineProps({
|
||||
size: {
|
||||
type: Number,
|
||||
default: 100,
|
||||
@ -49,6 +52,14 @@ const { size, modelValue } = defineProps({
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: () => false,
|
||||
},
|
||||
limit: {
|
||||
type: Number,
|
||||
default: () => 9,
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(["update:modelValue"]);
|
||||
@ -58,6 +69,22 @@ const fileList = ref<any[]>([]);
|
||||
const dialogImageUrl = ref("");
|
||||
const dialogVisible = ref(false);
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(newVal) => {
|
||||
if (newVal && newVal.length) {
|
||||
fileList.value = newVal.map((item) => {
|
||||
return {
|
||||
name: item,
|
||||
response: { code: 200, msg: "成功", data: [item] },
|
||||
status: "success",
|
||||
url: item,
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
const beforeUpload = (rawFile: any) => {
|
||||
const isLtSize = rawFile.size / 1024 / 1024 < 5;
|
||||
if (!isLtSize) {
|
||||
@ -67,13 +94,13 @@ const beforeUpload = (rawFile: any) => {
|
||||
return true;
|
||||
};
|
||||
|
||||
const handleSuccess = ({ code, data, msg }: Tdata) => {
|
||||
if (code != 200) return ElMessage.error(msg);
|
||||
let list = fileList.value.map((item) => item?.response?.data?.imeUrl);
|
||||
const handleSuccess: UploadProps["onSuccess"] = (_: any, _1: any, uploadFiles: any) => {
|
||||
let list = uploadFiles.map((item) => item?.response?.data[0]);
|
||||
emit("update:modelValue", list);
|
||||
};
|
||||
const handleRemove: UploadProps["onRemove"] = () => {
|
||||
let list = fileList.value.map((item) => item?.response?.data?.imeUrl);
|
||||
|
||||
const handleRemove = (_: any, uploadFiles: any) => {
|
||||
let list = uploadFiles.map((item) => item.response.data[0]);
|
||||
emit("update:modelValue", list);
|
||||
};
|
||||
|
||||
@ -84,17 +111,18 @@ const handlePictureCardPreview: UploadProps["onPreview"] = (uploadFile) => {
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.upload {
|
||||
/deep/ .el-upload {
|
||||
.upload :deep(.el-upload) {
|
||||
width: var(--width);
|
||||
height: var(--height);
|
||||
}
|
||||
/deep/ .el-upload-list__item {
|
||||
}
|
||||
.upload :deep(.el-upload-list__item) {
|
||||
width: var(--width);
|
||||
height: var(--height);
|
||||
}
|
||||
/deep/ .el-icon--close-tip {
|
||||
}
|
||||
.upload :deep(.el-icon--close-tip) {
|
||||
display: none;
|
||||
}
|
||||
.hide :deep(.el-upload--picture-card) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
19
src/layout/index copy 2.vue
Normal file
19
src/layout/index copy 2.vue
Normal file
@ -0,0 +1,19 @@
|
||||
<template>
|
||||
<div class="app-wrapper">
|
||||
<audio ref="audioRef" autoplay loop hidden>
|
||||
<source src="../assets/audio/alarm.mp3" type="video/mp3" />
|
||||
</audio>
|
||||
<el-button @click="playAudio">Default</el-button>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref } from "vue";
|
||||
const audioSrc = ref(new URL("@/assets/audio/alarm.mp3", import.meta.url).href);
|
||||
const audioRef = ref(null);
|
||||
|
||||
const playAudio = (context) => {
|
||||
audioRef.value.play().catch((err) => {
|
||||
// console.log(err, "暂停失败");
|
||||
});
|
||||
};
|
||||
</script>
|
120
src/layout/index copy.vue
Normal file
120
src/layout/index copy.vue
Normal file
@ -0,0 +1,120 @@
|
||||
<template>
|
||||
<div class="app-wrapper">
|
||||
<v-sidebar />
|
||||
<v-header />
|
||||
<div class="main-container">
|
||||
<div class="app-main" :class="{ 'content-collapse': sidebar.collapse }">
|
||||
<router-view v-slot="{ Component }">
|
||||
<transition name="move" mode="out-in">
|
||||
<keep-alive :include="[]">
|
||||
<component :is="Component"></component>
|
||||
</keep-alive>
|
||||
</transition>
|
||||
</router-view>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <audio ref="audioPlayer" src="../assets/audio/alarm.mp3" hidden /> -->
|
||||
<audio ref="audioPlayer" autoplay loop hidden>
|
||||
<source src="../assets/audio/alarm.mp3" type="audio/mpeg" />
|
||||
</audio>
|
||||
<!-- <Alarm ref="alarmRef" v-if="visible" @close="close" /> -->
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { useSidebarStore } from "@/store/sidebar";
|
||||
import vHeader from "@/components/header.vue";
|
||||
import vSidebar from "@/components/sidebar.vue";
|
||||
import Alarm from "@/components/alarm.vue";
|
||||
import { ref } from "vue";
|
||||
|
||||
// import useWebSocket from "@/utils/webSocket";
|
||||
// const { onMessage } = useWebSocket();
|
||||
// onMessage((res) => {
|
||||
// console.log(res, "WebSocket 接收服务器消息");
|
||||
// if (res.cmd == "warning") {
|
||||
// console.log("预警弹窗");
|
||||
// }
|
||||
// });
|
||||
|
||||
const sidebar = useSidebarStore();
|
||||
const alarmRef = ref(null);
|
||||
const audioPlayer = ref(null);
|
||||
const visible = ref(true);
|
||||
|
||||
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 close = async () => {
|
||||
try {
|
||||
audioPlayer.value.play();
|
||||
console.log(1111);
|
||||
} catch (error) {
|
||||
console.log(error, 2222);
|
||||
}
|
||||
};
|
||||
|
||||
// setTimeout(() => {
|
||||
// audioRef.value.play().catch((error) => {
|
||||
// console.error("自动播放被阻止:", error);
|
||||
// });
|
||||
// }, 5000);
|
||||
const playAudio = () => {
|
||||
if (audioPlayer.value) {
|
||||
audioPlayer.value.play().catch((error) => {
|
||||
console.error("自动播放被阻止:", error);
|
||||
});
|
||||
}
|
||||
};
|
||||
// const include = getInclude(routes[0].children);
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
// @media screen and (max-width: 800px) {
|
||||
// .main-container {
|
||||
// margin-left: 0 !important;
|
||||
// }
|
||||
// .sidebar-container {
|
||||
// width: 0 !important;
|
||||
// }
|
||||
// .app-wrapper-header {
|
||||
// width: 100% !important;
|
||||
// }
|
||||
// }
|
||||
.app-wrapper {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
background: #f0f2f5;
|
||||
overflow: hidden;
|
||||
.main-container {
|
||||
height: 100vh;
|
||||
margin-left: 210px;
|
||||
min-height: 100%;
|
||||
position: relative;
|
||||
transition: 0.3s;
|
||||
background-color: #f2f4fa;
|
||||
}
|
||||
.app-main {
|
||||
// height: 100vh;
|
||||
height: calc(100vh - 90px);
|
||||
position: relative;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
// padding-top: 70px;
|
||||
margin-top: 70px;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -13,15 +13,30 @@
|
||||
</router-view>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- <Alarm ref="alarmRef" v-if="visible" @close="close" /> -->
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { useSidebarStore } from "@/store/sidebar";
|
||||
import vHeader from "@/components/header.vue";
|
||||
import vSidebar from "@/components/sidebar.vue";
|
||||
import { routes } from "@/router/index";
|
||||
import Alarm from "@/components/alarm.vue";
|
||||
import { ref } from "vue";
|
||||
|
||||
// import useWebSocket from "@/utils/webSocket";
|
||||
// const { onMessage } = useWebSocket();
|
||||
// onMessage((res) => {
|
||||
// console.log(res, "WebSocket 接收服务器消息");
|
||||
// if (res.cmd == "warning") {
|
||||
// console.log("预警弹窗");
|
||||
// }
|
||||
// });
|
||||
|
||||
const sidebar = useSidebarStore();
|
||||
const alarmRef = ref(null);
|
||||
const audioPlayer = ref(null);
|
||||
const visible = ref(true);
|
||||
|
||||
const getInclude = (routeList: any) => {
|
||||
if (!routeList) return [];
|
||||
@ -36,6 +51,27 @@ const getInclude = (routeList: any) => {
|
||||
});
|
||||
return list;
|
||||
};
|
||||
const close = async () => {
|
||||
try {
|
||||
audioPlayer.value.play();
|
||||
console.log(1111);
|
||||
} catch (error) {
|
||||
console.log(error, 2222);
|
||||
}
|
||||
};
|
||||
|
||||
setTimeout(() => {
|
||||
audioPlayer.value.play().catch((error) => {
|
||||
console.error("自动播放被阻止:", error);
|
||||
});
|
||||
}, 5000);
|
||||
const playAudio = () => {
|
||||
if (audioPlayer.value) {
|
||||
audioPlayer.value.play().catch((error) => {
|
||||
console.error("自动播放被阻止:", error);
|
||||
});
|
||||
}
|
||||
};
|
||||
// const include = getInclude(routes[0].children);
|
||||
</script>
|
||||
|
||||
|
@ -1,11 +1,13 @@
|
||||
import { defineStore } from 'pinia';
|
||||
import { TLogin } from "@/api/index.d";
|
||||
import { TLogin, TRoleList } from "@/api/index.d";
|
||||
import { roleList } from '@/api';
|
||||
|
||||
export const useCommonStore = defineStore('common', {
|
||||
state: () => {
|
||||
return {
|
||||
time: new Date(),
|
||||
user: <TLogin.IRes>{}
|
||||
user: <TLogin.IRes>{},
|
||||
roleList: <TRoleList[]>[]
|
||||
};
|
||||
},
|
||||
getters: {},
|
||||
@ -13,6 +15,11 @@ export const useCommonStore = defineStore('common', {
|
||||
setTime() {
|
||||
this.time = new Date();
|
||||
},
|
||||
getRoleList() {
|
||||
roleList().then(res => {
|
||||
this.roleList = res
|
||||
})
|
||||
},
|
||||
setUser(data: TLogin.IRes) {
|
||||
this.user = data
|
||||
},
|
||||
|
158
src/utils/webSocket.js
Normal file
158
src/utils/webSocket.js
Normal file
@ -0,0 +1,158 @@
|
||||
import { ref, onMounted, onUnmounted } from 'vue';
|
||||
|
||||
class WebSocketService {
|
||||
constructor() {
|
||||
this.url = import.meta.env.VITE_APP_URL_WEBSOCKET;
|
||||
this.socket = null;
|
||||
this.isAlive = false; // 用于判断心跳是否正常
|
||||
this.reconnectAttempts = 0; // 重连尝试次数
|
||||
this.MAX_RECONNECT_ATTEMPTS = 5; // 最大重连次数
|
||||
this.HEARTBEAT_INTERVAL = 5000; // 心跳间隔时间 (30秒)
|
||||
// this.HEARTBEAT_INTERVAL = 30000; // 心跳间隔时间 (30秒)
|
||||
this.heartbeatTimer = null;
|
||||
this.reconnectTimer = null;
|
||||
|
||||
this.connect();
|
||||
}
|
||||
|
||||
connect() {
|
||||
this.socket = new WebSocket(this.url);
|
||||
|
||||
this.socket.onopen = () => {
|
||||
console.log('WebSocket已连接');
|
||||
this.webScoketLogin();
|
||||
this.reconnectAttempts = 0; // 成功连接后重置重试次数
|
||||
this.startHeartbeat(); // 开始心跳检测
|
||||
};
|
||||
|
||||
this.socket.onmessage = (event) => {
|
||||
// 处理接收到的消息
|
||||
console.log('Message received:', event.data);
|
||||
};
|
||||
|
||||
this.socket.onclose = () => {
|
||||
console.log('WebSocket连接已关闭');
|
||||
this.stopHeartbeat();
|
||||
this.attemptReconnect();
|
||||
};
|
||||
|
||||
this.socket.onerror = (error) => {
|
||||
console.log('WebSocket连接错误', error);
|
||||
};
|
||||
}
|
||||
|
||||
webScoketLogin() {
|
||||
this.sendMessage({
|
||||
username: "admin",
|
||||
password: "111111",
|
||||
type: 0,
|
||||
cmd: "webLogin",
|
||||
})
|
||||
}
|
||||
|
||||
startHeartbeat() {
|
||||
if (!this.heartbeatTimer) {
|
||||
this.heartbeatTimer = setInterval(() => {
|
||||
if (this.socket.readyState === WebSocket.OPEN) {
|
||||
this.isAlive = false;
|
||||
this.sendPing();
|
||||
}
|
||||
}, this.HEARTBEAT_INTERVAL);
|
||||
}
|
||||
}
|
||||
|
||||
stopHeartbeat() {
|
||||
if (this.heartbeatTimer) {
|
||||
clearInterval(this.heartbeatTimer);
|
||||
this.heartbeatTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
sendPing() {
|
||||
console.log('发送心跳', JSON.stringify({ cmd: 'heartbeat' }));
|
||||
|
||||
this.socket.send(JSON.stringify({ cmd: 'heartbeat' }));
|
||||
setTimeout(() => {
|
||||
if (!this.isAlive) {
|
||||
console.warn('WebSocket heartbeat failed, attempting to reconnect...');
|
||||
this.socket.close();
|
||||
}
|
||||
}, this.HEARTBEAT_INTERVAL / 2); // 如果没有pong响应,则关闭并重连
|
||||
}
|
||||
|
||||
receivePong() {
|
||||
this.isAlive = true;
|
||||
}
|
||||
|
||||
attemptReconnect() {
|
||||
if (this.reconnectAttempts < this.MAX_RECONNECT_ATTEMPTS) {
|
||||
this.reconnectAttempts++;
|
||||
console.log(`Attempting to reconnect (${this.reconnectAttempts})...`);
|
||||
this.reconnectTimer = setTimeout(() => {
|
||||
this.connect();
|
||||
}, 1000 * this.reconnectAttempts); // 指数退避算法
|
||||
} else {
|
||||
console.error('Max reconnect attempts reached');
|
||||
}
|
||||
}
|
||||
|
||||
sendMessage(message) {
|
||||
if (this.socket && this.socket.readyState === WebSocket.OPEN) {
|
||||
this.socket.send(JSON.stringify(message));
|
||||
}
|
||||
}
|
||||
|
||||
close() {
|
||||
this.stopHeartbeat();
|
||||
if (this.reconnectTimer) {
|
||||
clearTimeout(this.reconnectTimer);
|
||||
this.reconnectTimer = null;
|
||||
}
|
||||
if (this.socket) {
|
||||
this.socket.close();
|
||||
this.socket = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default function useWebSocket() {
|
||||
const ws = new WebSocketService();
|
||||
|
||||
const message = ref(null);
|
||||
const isConnected = ref(false);
|
||||
|
||||
const onMessage = (callback) => {
|
||||
ws.socket.onmessage = (event) => {
|
||||
const data = JSON.parse(event.data);
|
||||
if (data.cmd == "webLogin" && !data.code == 200) return ws.webScoketLogin()
|
||||
|
||||
callback(data);
|
||||
if (event.data.includes('heartbeat')) {
|
||||
ws.receivePong();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const onClose = () => {
|
||||
ws.socket.onclose()
|
||||
};
|
||||
|
||||
const onOpen = (callback) => {
|
||||
ws.socket.onopen = () => {
|
||||
isConnected.value = true;
|
||||
callback();
|
||||
};
|
||||
};
|
||||
|
||||
// onMounted(() => {
|
||||
// onOpen(() => console.log('Connected'));
|
||||
// onClose(() => console.log('Disconnected'));
|
||||
// onMessage((data) => console.log('Received:', data));
|
||||
// });
|
||||
|
||||
// onUnmounted(() => {
|
||||
// ws.close();
|
||||
// });
|
||||
|
||||
return { isConnected, message, sendMessage: ws.sendMessage.bind(ws), onMessage, onClose };
|
||||
}
|
@ -44,23 +44,33 @@ enum warnTypeEnum {
|
||||
}
|
||||
const router = useRouter();
|
||||
// 查询相关
|
||||
const query = reactive({
|
||||
name: "",
|
||||
});
|
||||
const query = reactive<any>({});
|
||||
const searchOpt = ref<FormOptionList[]>([
|
||||
{ type: "select", label: "来源手铐:", prop: "name1", opts: [{ label: "866503071660886", value: "866503071660886" }] },
|
||||
{ type: "select", label: "事件类型:", prop: "name2", opts: [{ label: "866503071660886", value: "866503071660886" }] },
|
||||
{ type: "select", label: "事件级别:", prop: "name3", opts: [{ label: "866503071660886", value: "866503071660886" }] },
|
||||
{ type: "input", label: "手铐IMEI号:", prop: "deviceId" },
|
||||
{
|
||||
type: "select",
|
||||
label: "告警类型:",
|
||||
prop: "warnType",
|
||||
opts: [
|
||||
{ label: "SOS告警", value: 0 },
|
||||
{ label: "围栏告警", value: 1 },
|
||||
{ label: "破坏告警", value: 2 },
|
||||
{ label: "低电告警", value: 3 },
|
||||
{ label: "心率告警", value: 4 },
|
||||
{ label: "血氧告警", value: 5 },
|
||||
{ label: "体温告警", value: 6 },
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "select",
|
||||
label: "处理状态:",
|
||||
prop: "status",
|
||||
opts: [
|
||||
{ label: "未处理", value: "0" },
|
||||
{ label: "已处理", value: "1" },
|
||||
{ label: "待处理", value: 0 },
|
||||
{ label: "已处理", value: 1 },
|
||||
],
|
||||
},
|
||||
{ type: "daterange", label: "创建时间:", prop: "name5" },
|
||||
{ type: "daterange", label: "创建时间:", prop: "time" },
|
||||
]);
|
||||
const handleSearch = () => {
|
||||
changePage(1);
|
||||
@ -86,7 +96,10 @@ const tableData = ref<TWarnRecord.IListRes[]>([]);
|
||||
|
||||
const getData = async () => {
|
||||
try {
|
||||
const res = await warnRecord(paging);
|
||||
console.log(query, "queryqueryquery");
|
||||
let p = { ...paging, ...query, startDate: query.time?.[0], endDate: query.time?.[1] };
|
||||
delete p.time;
|
||||
const res = await warnRecord(p);
|
||||
tableData.value = res.records;
|
||||
paging.total = res.total;
|
||||
} catch (error) {}
|
||||
@ -97,10 +110,10 @@ const changePage = (val: number) => {
|
||||
paging.page = val;
|
||||
getData();
|
||||
};
|
||||
const toIncidentDispose = (deviceId: string) => {
|
||||
const toIncidentDispose = (id: string) => {
|
||||
router.push({
|
||||
path: "/incidentDispose",
|
||||
query: { deviceId },
|
||||
query: { id },
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
@ -47,26 +47,26 @@
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="处理人:" prop="name">
|
||||
<el-input v-model="ruleForm.name" clearable :disabled="curData.status == 1" />
|
||||
<el-input v-model="ruleForm.name" clearable :disabled="disabled" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="警号:" prop="username">
|
||||
<el-input v-model="ruleForm.username" clearable :disabled="curData.status == 1" />
|
||||
<el-input v-model="ruleForm.username" clearable :disabled="disabled" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item label="处理记录:" prop="content">
|
||||
<el-input v-model="ruleForm.content" clearable :autosize="{ minRows: 2, maxRows: 4 }" type="textarea" :disabled="curData.status == 1" />
|
||||
<el-input v-model="ruleForm.content" clearable :autosize="{ minRows: 2, maxRows: 4 }" type="textarea" :disabled="disabled" />
|
||||
</el-form-item>
|
||||
<el-form-item label="处理图片:" prop="images">
|
||||
<Upload v-model="ruleForm.images" :disabled="curData.status == 1" />
|
||||
<Upload v-model="ruleForm.images" :disabled="disabled" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="right-foot">
|
||||
<el-button type="primary" @click="submitForm(ruleFormRef)">保存</el-button>
|
||||
<div class="right-foot" v-if="!disabled">
|
||||
<el-button type="primary" @click="submitForm(ruleFormRef)" :disabled="disabled">保存</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
@ -77,7 +77,7 @@
|
||||
<script setup lang="ts" name="incidentDispose">
|
||||
import location from "@/assets/img/location.png";
|
||||
import { MapCustom } from "@/utils/mapCustom";
|
||||
import { onMounted, ref, reactive } from "vue";
|
||||
import { onMounted, ref, reactive, watch } from "vue";
|
||||
import Upload from "@/components/upload-img.vue";
|
||||
import * as echarts from "echarts";
|
||||
import { warningDetail, warningConfirm } from "@/api/index";
|
||||
@ -106,6 +106,7 @@ enum warnTypeEnum {
|
||||
}
|
||||
const { query } = useRoute();
|
||||
const chartRef = ref(null);
|
||||
const disabled = ref(false);
|
||||
const ruleFormRef = ref<FormInstance>();
|
||||
let map = null;
|
||||
|
||||
@ -135,7 +136,7 @@ const ringOptions = {
|
||||
],
|
||||
};
|
||||
const ruleForm = reactive<TWarningConfirm>({
|
||||
id: query.deviceId as string,
|
||||
id: query.id as string,
|
||||
name: "",
|
||||
username: "",
|
||||
content: "",
|
||||
@ -174,17 +175,23 @@ const rules = reactive<FormRules<TWarningConfirm>>({
|
||||
content: [{ required: true, message: "请输入处理记录", trigger: "blur" }],
|
||||
images: [{ required: true, message: "请上传图片", trigger: "blur" }],
|
||||
});
|
||||
watch(
|
||||
() => curData.value,
|
||||
(newVal) => {
|
||||
if (newVal && newVal.status == 1) {
|
||||
disabled.value = true;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
const getData = async () => {
|
||||
try {
|
||||
const res = await warningDetail({ id: query.deviceId as string });
|
||||
const res = await warningDetail({ id: query.id as string });
|
||||
curData.value = res;
|
||||
ruleForm.name = res.rname;
|
||||
ruleForm.username = res.rname;
|
||||
ruleForm.content = res.rcontent;
|
||||
ruleForm.images = JSON.parse(res.rimg);
|
||||
|
||||
console.log(ruleForm, "ruleFormruleFormruleFormruleForm");
|
||||
|
||||
let icon = map.newIcon(location);
|
||||
let marker = map.marker({ icon, position: [116.406315, 39.908775] });
|
||||
marker.setMap(map.map);
|
||||
@ -245,6 +252,7 @@ onMounted(() => {
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
.info {
|
||||
background: #ffffff;
|
||||
height: 100%;
|
||||
|
@ -56,6 +56,7 @@ const submitForm = async (formEl: FormInstance | undefined) => {
|
||||
if (valid) {
|
||||
fetchLogin(ruleForm).then((res) => {
|
||||
comm.setUser(res);
|
||||
comm.getRoleList();
|
||||
ElMessage({
|
||||
message: "登录成功",
|
||||
type: "success",
|
||||
|
@ -8,7 +8,7 @@
|
||||
</div>
|
||||
<TableCustom :columns="columns" :tableData="tableData" :paging="page" :changePage="changePage">
|
||||
<template #location="{ rows }">
|
||||
<el-button type="success" link :icon="View" v-if="rows.warnType == 0 || rows.warnType == 1" @click="toIncidentDispose(rows.deviceId)"> 查看 </el-button>
|
||||
<el-button type="success" link :icon="View" v-if="rows.warnType == 0 || rows.warnType == 1" @click="toIncidentDispose(rows.id)"> 查看 </el-button>
|
||||
</template>
|
||||
<template #status="{ rows }">
|
||||
<el-tag :type="rows.status == 1 ? 'success' : 'danger'">
|
||||
@ -75,10 +75,10 @@ const handleInput = debounce((e) => {
|
||||
getData();
|
||||
}, 500);
|
||||
|
||||
const toIncidentDispose = (deviceId: string) => {
|
||||
const toIncidentDispose = (id: string) => {
|
||||
router.push({
|
||||
path: "/incidentDispose",
|
||||
query: { deviceId },
|
||||
query: { id },
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
@ -27,7 +27,6 @@ const { list } = defineProps({
|
||||
default: () => [],
|
||||
},
|
||||
});
|
||||
console.log(list, "list1111");
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
.monitoring-top {
|
||||
|
@ -24,7 +24,7 @@
|
||||
</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 { CirclePlusFilled } from "@element-plus/icons-vue";
|
||||
import { fetchData, orgAdd, orgModify, orgList, orgDelete } from "@/api/index";
|
||||
@ -45,17 +45,8 @@ const query = reactive({
|
||||
name: "",
|
||||
});
|
||||
const searchOpt = ref<FormOptionList[]>([
|
||||
{ type: "input", label: "辖区名称:", prop: "name1" },
|
||||
{ type: "daterange", label: "创建时间:", prop: "name2" },
|
||||
{
|
||||
type: "select",
|
||||
label: "状态:",
|
||||
prop: "name3",
|
||||
opts: [
|
||||
{ label: "启用", value: "1" },
|
||||
{ label: "禁用", value: "0" },
|
||||
],
|
||||
},
|
||||
{ type: "input", label: "辖区名称:", prop: "name" },
|
||||
// { type: "daterange", label: "创建时间:", prop: "name2" },
|
||||
]);
|
||||
|
||||
// 表格相关
|
||||
@ -77,11 +68,11 @@ const paging = reactive({
|
||||
const tableData = ref<TOrg.IOrgRecordRes[]>([]);
|
||||
|
||||
const getData = async () => {
|
||||
const res = await orgList(paging);
|
||||
const res = await orgList({ ...paging, ...query });
|
||||
tableData.value = res.records;
|
||||
paging.total = res.total;
|
||||
};
|
||||
getData();
|
||||
|
||||
const handleSearch = () => {
|
||||
changePage(1);
|
||||
};
|
||||
@ -128,6 +119,9 @@ const updateData = (res) => {
|
||||
getData();
|
||||
});
|
||||
};
|
||||
onMounted(() => {
|
||||
getData();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
|
@ -143,10 +143,10 @@ const changeWarningPage = (val: number) => {
|
||||
paging1.page = val;
|
||||
getWarningData();
|
||||
};
|
||||
const toIncidentDispose = (deviceId: string) => {
|
||||
const toIncidentDispose = (id: string) => {
|
||||
router.push({
|
||||
path: "/incidentDispose",
|
||||
query: { deviceId },
|
||||
query: { id },
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
@ -88,12 +88,39 @@ const editOp = [
|
||||
];
|
||||
|
||||
// 查询相关
|
||||
const query = reactive({
|
||||
name: "",
|
||||
});
|
||||
const query = reactive({});
|
||||
const searchOpt = ref<FormOptionList[]>([
|
||||
{ type: "input", label: "手铐SN:", prop: "name" },
|
||||
{ type: "input", label: "警察账号:", prop: "name1" },
|
||||
{ type: "input", label: "手铐SN:", prop: "deviceId" },
|
||||
{ type: "input", label: "警察名称:", prop: "name" },
|
||||
{
|
||||
type: "select",
|
||||
label: "当前模式:",
|
||||
prop: "mode",
|
||||
opts: [
|
||||
{ label: "常规", value: "0" },
|
||||
{ label: "审讯", value: "1" },
|
||||
{ label: "户外押送", value: "2" },
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "select",
|
||||
label: "设备状态:",
|
||||
prop: "status",
|
||||
opts: [
|
||||
{ label: "离线", value: "0" },
|
||||
{ label: "在线", value: "1" },
|
||||
{ label: "充电中", value: "2" },
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "select",
|
||||
label: "使用状态:",
|
||||
prop: "useStatus",
|
||||
opts: [
|
||||
{ label: "未使用", value: "0" },
|
||||
{ label: "使用中", value: "1" },
|
||||
],
|
||||
},
|
||||
]);
|
||||
const handleSearch = () => {
|
||||
changePage(1);
|
||||
@ -103,19 +130,18 @@ const handleSearch = () => {
|
||||
let columns = ref([
|
||||
{ type: "selection" },
|
||||
{ type: "index", label: "序号", width: 55, align: "center" },
|
||||
{ prop: "deviceId", label: "手铐IMEI" },
|
||||
{ prop: "name", label: "绑定警察名称" },
|
||||
{ prop: "username", label: "绑定警察账户" },
|
||||
{ prop: "battery", label: "电量" },
|
||||
{ prop: "deviceVersion", label: "版本号" },
|
||||
{ prop: "status", label: "设备状态" },
|
||||
{ prop: "mode", label: "当前模式" },
|
||||
{ prop: "useStatus", label: "使用状态" },
|
||||
{ prop: "deviceSwitch", label: "启用开关" },
|
||||
{ prop: "orgName", label: "关联辖区编号" },
|
||||
{ prop: "createTime", label: "最新通信时间" },
|
||||
{ prop: "createTime", label: "创建时间" },
|
||||
|
||||
{ prop: "deviceId", label: "手铐IMEI", width: 120 },
|
||||
{ prop: "adminName", label: "绑定警察名称", width: 180 },
|
||||
{ prop: "adminUsername", label: "绑定警察账户", width: 120 },
|
||||
{ prop: "battery", label: "电量", width: 100 },
|
||||
{ prop: "deviceVersion", label: "版本号", width: 100 },
|
||||
{ prop: "status", label: "设备状态", width: 100 },
|
||||
{ prop: "mode", label: "当前模式", width: 100 },
|
||||
{ prop: "useStatus", label: "使用状态", width: 100 },
|
||||
{ prop: "deviceSwitch", label: "启用开关", width: 100 },
|
||||
{ prop: "orgName", label: "关联辖区编号", width: 120 },
|
||||
{ prop: "createTime", label: "最新通信时间", width: 180 },
|
||||
{ prop: "createTime", label: "创建时间", width: 180 },
|
||||
{ prop: "operator", label: "操作", width: 400 },
|
||||
]);
|
||||
const paging = reactive({
|
||||
@ -130,7 +156,7 @@ const controlForm = reactive({
|
||||
|
||||
const tableData = ref<TDevice.IListRes[]>([]);
|
||||
const getData = async () => {
|
||||
const res = await deviceList(paging);
|
||||
const res = await deviceList({ ...paging, ...query });
|
||||
tableData.value = res.records;
|
||||
paging.total = res.total;
|
||||
};
|
||||
|
@ -11,14 +11,14 @@
|
||||
<!-- <el-button type="danger">删除</el-button> -->
|
||||
</template>
|
||||
|
||||
<template #state="{ rows }">
|
||||
<el-switch v-model="rows.state" :active-value="1" :inactive-value="0" />
|
||||
<template #status="{ rows }">
|
||||
<el-switch v-model="rows.status" :active-value="1" :inactive-value="0" />
|
||||
</template>
|
||||
|
||||
<template #roleId="{ rows }">
|
||||
{{ roleEnum[rows.roleId] }}
|
||||
</template>
|
||||
|
||||
<!--
|
||||
<template #password="{ rows }">
|
||||
<div v-if="rows.flag" @click="rows.flag = false">
|
||||
{{ rows.password }}
|
||||
@ -28,7 +28,7 @@
|
||||
******
|
||||
<el-icon style="cursor: pointer"><Hide /></el-icon>
|
||||
</div>
|
||||
</template>
|
||||
</template> -->
|
||||
|
||||
<template #operator="{ rows }">
|
||||
<el-button link type="primary" size="small" @click="handelRow('pwd', rows)"> 重置密码 </el-button>
|
||||
@ -50,7 +50,7 @@
|
||||
<script setup lang="ts" name="basetable">
|
||||
import { ref, reactive, onMounted } from "vue";
|
||||
import { ElMessage, ElMessageBox } from "element-plus";
|
||||
import { accountAdd, accountModify, accountList, accountDeletet, passwordReset, roleList, roleMenuList, roleModify } from "@/api/index";
|
||||
import { accountAdd, accountModify, accountList, accountDeletet, passwordReset, roleList, roleMenuList, roleModify, roleAdd } 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,17 +59,18 @@ 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, TRoleMenuList } from "@/api/index.d";
|
||||
import { TAccount, TRoleList, TRoleMenuList, TRoleModify } from "@/api/index.d";
|
||||
// import { Hide, View } from "@element-plus/icons-vue";
|
||||
|
||||
enum roleEnum {
|
||||
管理员 = -1,
|
||||
警察 = 1,
|
||||
辅警 = 2,
|
||||
协警 = 3,
|
||||
"管理员" = -1,
|
||||
"警察" = 1,
|
||||
"辅警" = 2,
|
||||
"协警" = 3,
|
||||
}
|
||||
|
||||
const comm = useCommonStore();
|
||||
|
||||
const visible = ref(false);
|
||||
const typeVisible = ref(false);
|
||||
const isEdit = ref(false);
|
||||
@ -92,25 +93,25 @@ const roleListData = ref<TRoleList[]>([]);
|
||||
|
||||
const searchOpt = ref<FormOptionList[]>([
|
||||
{ type: "input", label: "用户名:", prop: "name" },
|
||||
{ type: "input", label: "警员号:", prop: "username" },
|
||||
{
|
||||
type: "select",
|
||||
label: "用户类型:",
|
||||
prop: "name1",
|
||||
opts: [
|
||||
{ label: "管理员", value: "1" },
|
||||
{ label: "警察", value: "2" },
|
||||
{ label: "辅警", value: "3" },
|
||||
{ label: "协警", value: "4" },
|
||||
],
|
||||
prop: "roleId",
|
||||
opts: comm.roleList.map((item) => {
|
||||
return {
|
||||
label: item.name,
|
||||
value: item.id,
|
||||
};
|
||||
}),
|
||||
},
|
||||
{ type: "daterange", label: "创建时间:", prop: "name2" },
|
||||
{
|
||||
type: "select",
|
||||
label: "状态:",
|
||||
prop: "name3",
|
||||
prop: "status",
|
||||
opts: [
|
||||
{ label: "启用", value: "1" },
|
||||
{ label: "禁用", value: "0" },
|
||||
{ label: "启用", value: "1" },
|
||||
],
|
||||
},
|
||||
]);
|
||||
@ -122,10 +123,10 @@ let columns = ref([
|
||||
{ prop: "name", label: "用户名称" },
|
||||
{ prop: "username", label: "警员号" },
|
||||
{ prop: "phone", label: "手机号" },
|
||||
{ prop: "password", label: "密码", width: 120 },
|
||||
// { prop: "password", label: "密码", width: 120 },
|
||||
{ prop: "roleId", label: "类型" },
|
||||
{ prop: "createTime", label: "创建时间" },
|
||||
{ prop: "state", label: "状态" },
|
||||
{ prop: "status", label: "状态" },
|
||||
{ prop: "operator", label: "操作", width: 250 },
|
||||
]);
|
||||
|
||||
@ -191,7 +192,7 @@ const roleListFn = () => {
|
||||
});
|
||||
};
|
||||
const getData = async () => {
|
||||
const res = await accountList(paging);
|
||||
const res = await accountList({ ...paging, ...query });
|
||||
tableData.value = res.records?.map((item) => {
|
||||
item.flag = false;
|
||||
return item;
|
||||
@ -229,11 +230,13 @@ const updateData = (res) => {
|
||||
getData();
|
||||
});
|
||||
};
|
||||
const saveType = (row: TRoleList) => {
|
||||
roleModify(row).then(() => {
|
||||
const saveType = (row: TRoleModify.Ireq) => {
|
||||
const api = row.id ? roleModify : roleAdd;
|
||||
api(row).then(() => {
|
||||
ElMessage.success("保存成功");
|
||||
roleListFn();
|
||||
typeVisible.value = false;
|
||||
comm.getRoleList();
|
||||
// roleListFn();
|
||||
// typeVisible.value = false;
|
||||
});
|
||||
};
|
||||
const addType = () => {
|
||||
|
@ -26,7 +26,7 @@
|
||||
|
||||
<el-table-column prop="date" label="操作" width="200" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-button link type="primary" size="small" @click="emit('complete', row)">保存</el-button>
|
||||
<el-button link type="primary" size="small" @click="handleComplete(row)">保存</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@ -49,6 +49,11 @@ const { roleListData, typeHeadList } = defineProps({
|
||||
});
|
||||
|
||||
const emit = defineEmits(["complete", "addType"]);
|
||||
const handleComplete = (row: TRoleList) => {
|
||||
let p = { ...row, menus: row.roleMenu };
|
||||
delete p.roleMenu;
|
||||
emit("complete", p);
|
||||
};
|
||||
|
||||
const isCheck = (ite, row) => {
|
||||
let flag = false;
|
||||
|
31
sta.html
Normal file
31
sta.html
Normal file
@ -0,0 +1,31 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>背景音乐示例</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<h1>欢迎来到我的网站</h1>
|
||||
<!-- 插入背景音乐 -->
|
||||
<audio id="bgm" loop controls>
|
||||
<source src="./src/assets/audio/alarm.mp3" type="audio/mpeg">
|
||||
您的浏览器不支持 audio 标签。
|
||||
</audio>
|
||||
|
||||
<!-- 点击页面播放音乐js -->
|
||||
<script>
|
||||
document.addEventListener('click', function () {
|
||||
var audioElement = document.getElementById('bgm');
|
||||
if (audioElement.paused) { // 检查音频是否已播放
|
||||
audioElement.volume = 0.5; // 设置音量
|
||||
audioElement.play(); // 播放音频
|
||||
}
|
||||
}, { once: true }); // 确保事件处理器只执行一次
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
17
yarn.lock
17
yarn.lock
@ -1067,6 +1067,11 @@ hasown@^2.0.0:
|
||||
dependencies:
|
||||
function-bind "^1.1.2"
|
||||
|
||||
howler@^2.2.4:
|
||||
version "2.2.4"
|
||||
resolved "https://registry.yarnpkg.com/howler/-/howler-2.2.4.tgz#bd3df4a4f68a0118a51e4bd84a2bfc2e93e6e5a1"
|
||||
integrity sha512-iARIBPgcQrwtEr+tALF+rapJ8qSc+Set2GJQl7xT1MQzWaVkFebdJhR3alVlSiUf5U7nAANKuj3aWpwerocD5w==
|
||||
|
||||
html-void-elements@^2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/html-void-elements/-/html-void-elements-2.0.1.tgz#29459b8b05c200b6c5ee98743c41b979d577549f"
|
||||
@ -1511,13 +1516,6 @@ pify@^4.0.1:
|
||||
resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231"
|
||||
integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==
|
||||
|
||||
pinia-plugin-persist@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/pinia-plugin-persist/-/pinia-plugin-persist-1.0.0.tgz#fc696f225527f30bd5955109fafadd43c725e888"
|
||||
integrity sha512-M4hBBd8fz/GgNmUPaaUsC29y1M09lqbXrMAHcusVoU8xlQi1TqgkWnnhvMikZwr7Le/hVyMx8KUcumGGrR6GVw==
|
||||
dependencies:
|
||||
vue-demi "^0.12.1"
|
||||
|
||||
pinia-plugin-persistedstate@^4.2.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/pinia-plugin-persistedstate/-/pinia-plugin-persistedstate-4.2.0.tgz#31973291b768bd84ce24e55083e7171b2f451ad1"
|
||||
@ -1966,11 +1964,6 @@ vue-demi@*, vue-demi@>=0.14.5:
|
||||
resolved "https://registry.yarnpkg.com/vue-demi/-/vue-demi-0.14.7.tgz#8317536b3ef74c5b09f268f7782e70194567d8f2"
|
||||
integrity sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==
|
||||
|
||||
vue-demi@^0.12.1:
|
||||
version "0.12.5"
|
||||
resolved "https://registry.yarnpkg.com/vue-demi/-/vue-demi-0.12.5.tgz#8eeed566a7d86eb090209a11723f887d28aeb2d1"
|
||||
integrity sha512-BREuTgTYlUr0zw0EZn3hnhC3I6gPWv+Kwh4MCih6QcAeaTlaIX0DwOVN0wHej7hSvDPecz4jygy/idsgKfW58Q==
|
||||
|
||||
vue-demi@^0.13.11:
|
||||
version "0.13.11"
|
||||
resolved "https://registry.yarnpkg.com/vue-demi/-/vue-demi-0.13.11.tgz#7d90369bdae8974d87b1973564ad390182410d99"
|
||||
|
Loading…
x
Reference in New Issue
Block a user