From e0cf2f99f9b27ea29f077694a2789ce9de832f9b Mon Sep 17 00:00:00 2001 From: lxj <15683799673@163.com> Date: Thu, 7 Aug 2025 09:48:58 +0800 Subject: [PATCH 01/28] =?UTF-8?q?=E9=97=A8=E7=A6=81=E5=8F=AF=E8=A7=86?= =?UTF-8?q?=E5=8C=96=E9=A1=B5=E9=9D=A2=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/api/sis/accessControl/index.ts | 31 +++++++----- .../src/views/sis/acAdmin/dp-tree.vue | 13 +++-- apps/web-antd/src/views/sis/acAdmin/index.vue | 50 +++++++++---------- 3 files changed, 51 insertions(+), 43 deletions(-) diff --git a/apps/web-antd/src/api/sis/accessControl/index.ts b/apps/web-antd/src/api/sis/accessControl/index.ts index e6798260..b209b5ef 100644 --- a/apps/web-antd/src/api/sis/accessControl/index.ts +++ b/apps/web-antd/src/api/sis/accessControl/index.ts @@ -2,12 +2,12 @@ import type { AccessControlForm, AccessControlQuery, AccessControlVO, -} from './model' +} from './model'; -import type { ID, IDS, PageResult, TreeNode } from '#/api/common' +import type { ID, IDS, PageResult, TreeNode } from '#/api/common'; -import { commonExport } from '#/api/helper' -import { requestClient } from '#/api/request' +import { commonExport } from '#/api/helper'; +import { requestClient } from '#/api/request'; /** * 查询门禁管理列表 @@ -18,7 +18,7 @@ export function accessControlList(params?: AccessControlQuery) { return requestClient.get>( '/sis/accessControl/list', { params }, - ) + ); } /** @@ -27,7 +27,7 @@ export function accessControlList(params?: AccessControlQuery) { * @returns 门禁管理列表 */ export function accessControlExport(params?: AccessControlQuery) { - return commonExport('/sis/accessControl/export', params ?? {}) + return commonExport('/sis/accessControl/export', params ?? {}); } /** @@ -36,7 +36,7 @@ export function accessControlExport(params?: AccessControlQuery) { * @returns 门禁管理详情 */ export function accessControlInfo(id: ID) { - return requestClient.get(`/sis/accessControl/${id}`) + return requestClient.get(`/sis/accessControl/${id}`); } /** @@ -45,7 +45,7 @@ export function accessControlInfo(id: ID) { * @returns void */ export function accessControlAdd(data: AccessControlForm) { - return requestClient.postWithMsg('/sis/accessControl', data) + return requestClient.postWithMsg('/sis/accessControl', data); } /** @@ -54,7 +54,7 @@ export function accessControlAdd(data: AccessControlForm) { * @returns void */ export function accessControlUpdate(data: AccessControlForm) { - return requestClient.putWithMsg('/sis/accessControl', data) + return requestClient.putWithMsg('/sis/accessControl', data); } /** @@ -63,7 +63,7 @@ export function accessControlUpdate(data: AccessControlForm) { * @returns void */ export function accessControlRemove(id: ID | IDS) { - return requestClient.deleteWithMsg(`/sis/accessControl/${id}`) + return requestClient.deleteWithMsg(`/sis/accessControl/${id}`); } /** @@ -71,7 +71,7 @@ export function accessControlRemove(id: ID | IDS) { * @returns void */ export function queryTree() { - return requestClient.get[]>(`/sis/accessControl/tree`) + return requestClient.get[]>(`/sis/accessControl/tree`); } /** @@ -79,5 +79,12 @@ export function queryTree() { * @returns void */ export function accessControlSync() { - return requestClient.get(`/sis/accessControl/sync`) + return requestClient.get(`/sis/accessControl/sync`); +} + +export function remoteOpenDoor(params: any) { + return requestClient.post( + `/sis/accessControl/e8/remoteOpenDoor`, + params, + ); } diff --git a/apps/web-antd/src/views/sis/acAdmin/dp-tree.vue b/apps/web-antd/src/views/sis/acAdmin/dp-tree.vue index 06d54792..790828d6 100644 --- a/apps/web-antd/src/views/sis/acAdmin/dp-tree.vue +++ b/apps/web-antd/src/views/sis/acAdmin/dp-tree.vue @@ -2,7 +2,7 @@ import { onMounted, ref, toRaw } from 'vue'; import { SyncOutlined } from '@ant-design/icons-vue'; import { InputSearch, message, Skeleton, Tree } from 'ant-design-vue'; -import { queryTree } from '#/api/sis/accessControl'; +import { queryTree, remoteOpenDoor } from '#/api/sis/accessControl'; import type { TreeNode } from '#/api/common'; defineOptions({ inheritAttrs: false }); @@ -57,13 +57,14 @@ function open() { const acArr = checkNodeData(); if (acArr) { console.log(acArr); + remoteOpenDoor({ acIds: acArr, type: 0 }); } } function close() { const acArr = checkNodeData(); if (acArr) { - console.log(acArr); + remoteOpenDoor({ acIds: acArr, type: 1 }); } } @@ -71,6 +72,7 @@ function alwaysOpen() { const acArr = checkNodeData(); if (acArr) { console.log(acArr); + remoteOpenDoor({ acIds: acArr, type: 2 }); } } @@ -78,6 +80,7 @@ function reSet() { const acArr = checkNodeData(); if (acArr) { console.log(acArr); + remoteOpenDoor({ acIds: acArr, type: 4 }); } } @@ -92,7 +95,7 @@ function checkNodeData() { arr.forEach((item) => { const node: any = checkData[item]; if (node.level == 5) { - acArr.push(node); + acArr.push(node.id); } }); if (!acArr || acArr.length === 0) { @@ -116,8 +119,8 @@ function onTreeCheck(_keys: any, nodes: any) { delete checkData[id]; } }); - const nodes = toRaw(checkedNodes); - emit('checked', nodes); + const data = toRaw(checkedNodes); + emit('checked', checked, data); } onMounted(loadChannelTree); diff --git a/apps/web-antd/src/views/sis/acAdmin/index.vue b/apps/web-antd/src/views/sis/acAdmin/index.vue index 47fcb088..2274bee2 100644 --- a/apps/web-antd/src/views/sis/acAdmin/index.vue +++ b/apps/web-antd/src/views/sis/acAdmin/index.vue @@ -1,7 +1,7 @@ diff --git a/apps/web-antd/src/views/property/inspectionManagement/inspectionPoint/point-detail.vue b/apps/web-antd/src/views/property/inspectionManagement/inspectionPoint/point-detail.vue new file mode 100644 index 00000000..7b9fe199 --- /dev/null +++ b/apps/web-antd/src/views/property/inspectionManagement/inspectionPoint/point-detail.vue @@ -0,0 +1,64 @@ + + + From 1d1afb0162457c1cc01f1f1dcc8112e6fb59e52c Mon Sep 17 00:00:00 2001 From: fyy <2717885210@qq.com> Date: Tue, 12 Aug 2025 13:51:35 +0800 Subject: [PATCH 14/28] =?UTF-8?q?=E8=A7=86=E9=A2=91=E9=A2=84=E8=AD=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/web-antd/src/layouts/basic.vue | 55 ++-- .../workforceManagement/arrangement-modal.vue | 52 +++- .../workforceManagement/data.ts | 34 ++- .../workforceManagement/dept-tree.vue | 122 ++++++++ .../workforceManagement/scheduleView.vue | 3 +- .../workforceManagement/type.d.ts | 109 +++---- .../workforceManagement/unit-person-modal.vue | 204 ++++--------- .../videoWarning/videoAlertList/index.vue | 1 - .../videoWarning/videoWarningHasDone/data.ts | 265 +++++++++++++++++ .../videoWarningHasDone/index.vue | 279 ++++++++++++++++++ .../level-setting-modal.vue | 45 +++ .../videoWarningHasDone/warning-detail.vue | 147 +++++++++ .../videoWarningHasDone/warning-modal.vue | 122 ++++++++ .../videoWarningProcessing/data.ts | 103 +++++-- .../videoWarningProcessing/index.vue | 152 +++++----- .../videoWarningProcessing/warning-detail.vue | 79 ++++- .../videoWarningProcessing/warning-modal.vue | 13 + .../videoWarning/videoWarningToDone/data.ts | 265 +++++++++++++++++ .../videoWarning/videoWarningToDone/index.vue | 276 +++++++++++++++++ .../level-setting-modal.vue | 45 +++ .../videoWarningToDone/warning-detail.vue | 147 +++++++++ .../videoWarningToDone/warning-modal.vue | 121 ++++++++ 22 files changed, 2260 insertions(+), 379 deletions(-) create mode 100644 apps/web-antd/src/views/property/attendanceManagement/workforceManagement/dept-tree.vue create mode 100644 apps/web-antd/src/views/videoSystem/videoWarning/videoWarningHasDone/data.ts create mode 100644 apps/web-antd/src/views/videoSystem/videoWarning/videoWarningHasDone/index.vue create mode 100644 apps/web-antd/src/views/videoSystem/videoWarning/videoWarningHasDone/level-setting-modal.vue create mode 100644 apps/web-antd/src/views/videoSystem/videoWarning/videoWarningHasDone/warning-detail.vue create mode 100644 apps/web-antd/src/views/videoSystem/videoWarning/videoWarningHasDone/warning-modal.vue create mode 100644 apps/web-antd/src/views/videoSystem/videoWarning/videoWarningToDone/data.ts create mode 100644 apps/web-antd/src/views/videoSystem/videoWarning/videoWarningToDone/index.vue create mode 100644 apps/web-antd/src/views/videoSystem/videoWarning/videoWarningToDone/level-setting-modal.vue create mode 100644 apps/web-antd/src/views/videoSystem/videoWarning/videoWarningToDone/warning-detail.vue create mode 100644 apps/web-antd/src/views/videoSystem/videoWarning/videoWarningToDone/warning-modal.vue diff --git a/apps/web-antd/src/layouts/basic.vue b/apps/web-antd/src/layouts/basic.vue index 4d5fee5d..fffb92c6 100644 --- a/apps/web-antd/src/layouts/basic.vue +++ b/apps/web-antd/src/layouts/basic.vue @@ -11,7 +11,6 @@ import { GiteeIcon, GitHubOutlined, UserOutlined, - } from '@vben/icons'; import { BasicLayout, @@ -58,34 +57,34 @@ const menus = computed(() => { icon: UserOutlined, text: $t('ui.widgets.profile'), }, + // { + // handler: () => { + // openWindow('https://gitee.com/dapppp/ruoyi-plus-vben5', { + // target: '_blank', + // }); + // }, + // icon: () => h(GiteeIcon, { class: 'text-red-800' }), + // text: 'Gitee项目地址', + // }, + // { + // handler: () => { + // openWindow(VBEN_GITHUB_URL, { + // target: '_blank', + // }); + // }, + // icon: GitHubOutlined, + // text: 'Vben官方地址', + // }, + // { + // handler: () => { + // openWindow(`${VBEN_GITHUB_URL}/issues`, { + // target: '_blank', + // }); + // }, + // icon: CircleHelp, + // text: $t('ui.widgets.qa'), + // }, { - handler: () => { - openWindow('https://gitee.com/dapppp/ruoyi-plus-vben5', { - target: '_blank', - }); - }, - icon: () => h(GiteeIcon, { class: 'text-red-800' }), - text: 'Gitee项目地址', - }, - { - handler: () => { - openWindow(VBEN_GITHUB_URL, { - target: '_blank', - }); - }, - icon: GitHubOutlined, - text: 'Vben官方地址', - }, - { - handler: () => { - openWindow(`${VBEN_GITHUB_URL}/issues`, { - target: '_blank', - }); - }, - icon: CircleHelp, - text: $t('ui.widgets.qa'), - }, - { handler: () => { router.push('/navigation'); }, diff --git a/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/arrangement-modal.vue b/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/arrangement-modal.vue index 1a941699..85d4c4ec 100644 --- a/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/arrangement-modal.vue +++ b/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/arrangement-modal.vue @@ -1,5 +1,5 @@ + + diff --git a/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/scheduleView.vue b/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/scheduleView.vue index c2d101a0..6a22a6aa 100644 --- a/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/scheduleView.vue +++ b/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/scheduleView.vue @@ -114,6 +114,7 @@ async function handleDelete(row: Required) { border: '1px solid #d9d9d9', borderRadius: '4px', }" + class="calendar" > ) { diff --git a/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/type.d.ts b/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/type.d.ts index f3685f2a..9f4afa2d 100644 --- a/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/type.d.ts +++ b/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/type.d.ts @@ -1,67 +1,52 @@ //列表数据,用于展示人员列表 export interface PersonVO { - /** - * 主键id - */ - id: string | number; - - /** - * 用户id - */ - userId: string | number; - - /** - * 用户名称 - */ + userId: string; + tenantId: string; + deptId: number; userName: string; - - /** - * 联系电话 - */ - phone: string; - - /** - * 性别 - */ - gender: number; - - /** - * 人脸图片 - */ - img: string; - - /** - * 所属单位id - */ - unitId: string | number; - - /** - * 所属单位名称 - */ - unitName: string; - - /** - * 入驻位置 - */ - locathon: string; - - /** - * 入驻时间 - */ - time: string; - - /** - * 车牌号码 - */ - carNumber: string; - - /** - * 状态 - */ - state: number | string; - - /** - * 备注 - */ + nickName: string; + userType: string; + email: string; + phonenumber: string; + sex: string; + avatar?: string; + status: string; + loginIp: string; + loginDate: string; remark: string; + createTime: string; + dept: Dept; + roles: Role[]; + roleIds?: string[]; + postIds?: number[]; + roleId: string; + deptName: string; +} +export interface Dept { + deptId: number; + parentId: number; + parentName?: string; + ancestors: string; + deptName: string; + orderNum: number; + leader: string; + phone?: string; + email?: string; + status: string; + createTime?: string; +} + +export interface Role { + roleId: string; + roleName: string; + roleKey: string; + roleSort: number; + dataScope: string; + menuCheckStrictly?: boolean; + deptCheckStrictly?: boolean; + status: string; + remark: string; + createTime?: string; + flag: boolean; + superAdmin: boolean; } diff --git a/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/unit-person-modal.vue b/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/unit-person-modal.vue index d2b9a3b4..425ef105 100644 --- a/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/unit-person-modal.vue +++ b/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/unit-person-modal.vue @@ -1,35 +1,22 @@ diff --git a/apps/web-antd/src/views/videoSystem/videoWarning/videoAlertList/index.vue b/apps/web-antd/src/views/videoSystem/videoWarning/videoAlertList/index.vue index 52143fee..d56d9376 100644 --- a/apps/web-antd/src/views/videoSystem/videoWarning/videoAlertList/index.vue +++ b/apps/web-antd/src/views/videoSystem/videoWarning/videoAlertList/index.vue @@ -38,7 +38,6 @@ class="cursor-pointer overflow-hidden rounded-lg border border-gray-200 transition-shadow hover:shadow-md" @click="handleViewDetail(item)" > -
+import { Page, useVbenModal, type VbenFormProps } from '@vben/common-ui'; +import { getVxePopupContainer } from '@vben/utils'; + +import { Modal, Popconfirm, Space, Tag } from 'ant-design-vue'; +import { ref, watch } from 'vue'; + +import { + useVbenVxeGrid, + vxeCheckboxChecked, + type VxeGridProps, +} from '#/adapter/vxe-table'; + +import { commonDownloadExcel } from '#/utils/file/download'; +import { renderDict } from '#/utils/render'; + +import { columns, querySchema } from './data'; +import warningModal from './warning-modal.vue'; +import warningDetail from './warning-detail.vue'; +import LevelSettingModal from './level-setting-modal.vue'; +import imgPng from '../../../../assets/algorithmManagement/image.png'; + +// 假数据 +const mockData = ref([ + { + id: 1, + alarmId: 'JWD-3434234', + alarmTime: '2025.07.21 12:20', + level: '特大', + alarmType: '越界侦测', + description: '温度高于80度发生火宅', + location: '1栋3号电梯旁', + processingStatus: '已完成', + processingDetails: '', + processingTime: '', + }, + { + id: 2, + alarmId: 'JWD-3434235', + alarmTime: '2025.07.21 11:15', + level: '重要', + alarmType: '异常行为', + description: '人员异常聚集', + location: '2栋大厅', + processingStatus: '已完成', + processingDetails: '已派人员前往处理', + processingTime: '2025.07.21 11:30', + imgUrl: imgPng, + }, + { + id: 3, + alarmId: 'JWD-3434236', + alarmTime: '2025.07.21 10:45', + level: '一般', + alarmType: '设备故障', + description: '摄像头离线', + location: '3栋走廊', + processingStatus: '已完成', + processingDetails: '已修复设备', + processingTime: '2025.07.21 11:00', + imgUrl: imgPng, + }, + { + id: 4, + alarmId: 'JWD-3434236', + alarmTime: '2025.07.21 10:45', + level: '一般', + alarmType: '设备故障', + description: '摄像头离线', + location: '3栋走廊', + processingStatus: '已完成', + processingDetails: '已修复设备', + processingTime: '2025.07.21 11:00', + imgUrl: imgPng, + }, +]); + +const formOptions: VbenFormProps = { + commonConfig: { + labelWidth: 100, + componentProps: { + allowClear: true, + }, + }, + schema: querySchema(), + wrapperClass: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3', +}; + +const gridOptions: VxeGridProps = { + columns, + height: 'auto', + data: mockData.value, + pagerConfig: { + currentPage: 1, + pageSize: 10, + total: mockData.value.length, + }, + rowConfig: { + keyField: 'id', + }, + id: 'video-warning-processing-index', +}; + +const [BasicTable, tableApi] = useVbenVxeGrid({ + formOptions, + gridOptions, +}); + +// 监听数据变化,强制重新渲染表格 +const tableKey = ref(0); +watch( + mockData, + () => { + tableKey.value++; + }, + { deep: true }, +); + +const [WarningModal, modalApi] = useVbenModal({ + connectedComponent: warningModal, +}); + +const [WarningDetail, detailApi] = useVbenModal({ + connectedComponent: warningDetail, +}); + +const [LevelSettingModalComp, levelModalApi] = useVbenModal({ + connectedComponent: LevelSettingModal, +}); + +// 级别设置 +function handleLevelSetting(row: any) { + levelModalApi.setData({ id: row.id, level: row.level, data: mockData.value }); + levelModalApi.open(); +} + +// 查看详情 +async function handleView(row: any) { + detailApi.setData({ id: row.id, data: mockData.value }); + detailApi.open(); +} + +// 编辑 +async function handleEdit(row: any) { + modalApi.setData({ id: row.id, data: mockData.value }); + modalApi.open(); +} + +// // 分配处理 +// function handleAssign(row: any) { +// Modal.confirm({ +// title: '分配处理', +// content: `确定要分配预警 ${row.alarmId} 给处理人员吗?`, +// onOk() { +// // 模拟分配处理 +// const index = mockData.value.findIndex((item: any) => item.id === row.id); +// if (index !== -1) { +// mockData.value[index].processingStatus = '处理中'; +// mockData.value[index].processingDetails = '已分配给处理人员'; +// mockData.value[index].processingTime = new Date().toLocaleString(); +// tableApi.query(); +// } +// }, +// }); +// } + +// 删除 +async function handleDelete(row: any) { + const index = mockData.value.findIndex((item: any) => item.id === row.id); + if (index !== -1) { + mockData.value.splice(index, 1); + await tableApi.query(); + } +} + +// 批量删除 +function handleMultiDelete() { + const rows = tableApi.grid.getCheckboxRecords(); + const ids = rows.map((row: any) => row.id); + Modal.confirm({ + title: '提示', + okType: 'danger', + content: `确认删除选中的${ids.length}条记录吗?`, + onOk: async () => { + ids.forEach((id) => { + const index = mockData.value.findIndex((item: any) => item.id === id); + if (index !== -1) { + mockData.value.splice(index, 1); + } + }); + await tableApi.query(); + }, + }); +} + + + diff --git a/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningHasDone/level-setting-modal.vue b/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningHasDone/level-setting-modal.vue new file mode 100644 index 00000000..1568374a --- /dev/null +++ b/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningHasDone/level-setting-modal.vue @@ -0,0 +1,45 @@ + + + diff --git a/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningHasDone/warning-detail.vue b/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningHasDone/warning-detail.vue new file mode 100644 index 00000000..9479a43b --- /dev/null +++ b/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningHasDone/warning-detail.vue @@ -0,0 +1,147 @@ + + + diff --git a/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningHasDone/warning-modal.vue b/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningHasDone/warning-modal.vue new file mode 100644 index 00000000..125a333e --- /dev/null +++ b/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningHasDone/warning-modal.vue @@ -0,0 +1,122 @@ + + + + + diff --git a/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningProcessing/data.ts b/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningProcessing/data.ts index 7639cf63..a6cae811 100644 --- a/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningProcessing/data.ts +++ b/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningProcessing/data.ts @@ -48,6 +48,11 @@ export const columns: VxeGridProps['columns'] = [ field: 'alarmTime', width: 150, }, + { + title: '设备名称', + field: 'deviceName', + width: 150, + }, { title: '级别', field: 'level', @@ -116,6 +121,11 @@ export const columns: VxeGridProps['columns'] = [ field: 'processingDetails', width: 150, }, + { + title: '预期处理时间', + field: 'expectedProcessingTime', + width: 150, + }, { title: '处理时间', field: 'processingTime', @@ -145,6 +155,7 @@ export const modalSchema: FormSchemaGetter = () => [ fieldName: 'alarmId', component: 'Input', rules: 'required', + disabled: true, }, { label: '预警时间', @@ -156,6 +167,63 @@ export const modalSchema: FormSchemaGetter = () => [ showTime: true, }, rules: 'required', + disabled: true, + }, + { + label: '预警类型', + fieldName: 'alarmType', + component: 'Input', + rules: 'required', + disabled: true, + }, + { + label: '描述', + fieldName: 'description', + component: 'Input', + formItemClass: 'col-span-2', + disabled: true, + }, + { + label: '所在位置', + fieldName: 'location', + component: 'Input', + rules: 'required', + disabled: true, + }, + { + label: '设备名称', + fieldName: 'deviceName', + component: 'Input', + rules: 'required', + disabled: true, + }, + { + label: '处理情况', + fieldName: 'processingDetails', + component: 'Input', + componentProps: { + rows: 3, + }, + formItemClass: 'col-span-2', + disabled: true, + }, + { + label: '处理时间', + fieldName: 'processingTime', + component: 'DatePicker', + componentProps: { + format: 'YYYY.MM.DD HH:mm', + valueFormat: 'YYYY.MM.DD HH:mm', + showTime: true, + }, + disabled: true, + }, + { + label: '处理图片', + fieldName: 'imgUrl', + component: 'Input', + rules: 'required', + disabled: true, }, { label: '级别', @@ -170,27 +238,6 @@ export const modalSchema: FormSchemaGetter = () => [ }, rules: 'selectRequired', }, - { - label: '预警类型', - fieldName: 'alarmType', - component: 'Input', - rules: 'required', - }, - { - label: '描述', - fieldName: 'description', - component: 'InputTextArea', - componentProps: { - rows: 3, - }, - formItemClass: 'col-span-2', - }, - { - label: '所在位置', - fieldName: 'location', - component: 'Input', - rules: 'required', - }, { label: '处理状态', fieldName: 'processingStatus', @@ -205,22 +252,14 @@ export const modalSchema: FormSchemaGetter = () => [ rules: 'selectRequired', }, { - label: '处理情况', - fieldName: 'processingDetails', - component: 'InputTextArea', - componentProps: { - rows: 3, - }, - formItemClass: 'col-span-2', - }, - { - label: '处理时间', - fieldName: 'processingTime', + label: '预期处理时间', + fieldName: 'expectedProcessingTime', component: 'DatePicker', componentProps: { format: 'YYYY.MM.DD HH:mm', valueFormat: 'YYYY.MM.DD HH:mm', showTime: true, }, + rules: 'required', }, ]; diff --git a/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningProcessing/index.vue b/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningProcessing/index.vue index b7ca1380..7ff8410d 100644 --- a/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningProcessing/index.vue +++ b/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningProcessing/index.vue @@ -1,73 +1,3 @@ - - - + diff --git a/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningToDone/data.ts b/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningToDone/data.ts new file mode 100644 index 00000000..a6cae811 --- /dev/null +++ b/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningToDone/data.ts @@ -0,0 +1,265 @@ +import type { FormSchemaGetter } from '#/adapter/form'; +import type { VxeGridProps } from '#/adapter/vxe-table'; +import { getDictOptions } from '#/utils/dict'; +import { renderDict } from '#/utils/render'; +import { h } from 'vue'; + +export const querySchema: FormSchemaGetter = () => [ + { + component: 'Input', + fieldName: 'alarmType', + label: '视频预警类型', + }, + { + component: 'Select', + componentProps: { + options: [ + { label: '特大', value: '特大' }, + { label: '重要', value: '重要' }, + { label: '一般', value: '一般' }, + ], + }, + fieldName: 'level', + label: '级别', + }, + { + component: 'Select', + componentProps: { + options: [ + { label: '待分配', value: '待分配' }, + { label: '处理中', value: '处理中' }, + { label: '已完成', value: '已完成' }, + ], + }, + fieldName: 'processingStatus', + label: '处理状态', + }, +]; + +export const columns: VxeGridProps['columns'] = [ + { type: 'checkbox', width: 60 }, + { + title: '预警编号', + field: 'alarmId', + width: 150, + }, + { + title: '预警时间', + field: 'alarmTime', + width: 150, + }, + { + title: '设备名称', + field: 'deviceName', + width: 150, + }, + { + title: '级别', + field: 'level', + width: 100, + slots: { + default: ({ row }: any) => { + const levelColors: Record = { + 特大: 'red', + 重要: 'orange', + 一般: 'blue', + }; + return h( + 'span', + { + style: { + color: levelColors[row.level] || '#666', + fontWeight: 'bold', + }, + }, + row.level, + ); + }, + }, + }, + { + title: '预警类型', + field: 'alarmType', + width: 120, + }, + { + title: '描述', + field: 'description', + minWidth: 200, + }, + { + title: '所在位置', + field: 'location', + width: 150, + }, + { + title: '处理状态', + field: 'processingStatus', + width: 100, + slots: { + default: ({ row }: any) => { + const statusColors: Record = { + 待分配: 'red', + 处理中: 'orange', + 已完成: 'green', + }; + return h( + 'span', + { + style: { + color: statusColors[row.processingStatus] || '#666', + fontWeight: 'bold', + }, + }, + row.processingStatus, + ); + }, + }, + }, + { + title: '处理情况', + field: 'processingDetails', + width: 150, + }, + { + title: '预期处理时间', + field: 'expectedProcessingTime', + width: 150, + }, + { + title: '处理时间', + field: 'processingTime', + width: 150, + }, + { + field: 'action', + fixed: 'right', + slots: { default: 'action' }, + title: '操作', + width: 380, + }, +]; + +export const modalSchema: FormSchemaGetter = () => [ + { + label: '主键', + fieldName: 'id', + component: 'Input', + dependencies: { + show: () => false, + triggerFields: [''], + }, + }, + { + label: '预警编号', + fieldName: 'alarmId', + component: 'Input', + rules: 'required', + disabled: true, + }, + { + label: '预警时间', + fieldName: 'alarmTime', + component: 'DatePicker', + componentProps: { + format: 'YYYY.MM.DD HH:mm', + valueFormat: 'YYYY.MM.DD HH:mm', + showTime: true, + }, + rules: 'required', + disabled: true, + }, + { + label: '预警类型', + fieldName: 'alarmType', + component: 'Input', + rules: 'required', + disabled: true, + }, + { + label: '描述', + fieldName: 'description', + component: 'Input', + formItemClass: 'col-span-2', + disabled: true, + }, + { + label: '所在位置', + fieldName: 'location', + component: 'Input', + rules: 'required', + disabled: true, + }, + { + label: '设备名称', + fieldName: 'deviceName', + component: 'Input', + rules: 'required', + disabled: true, + }, + { + label: '处理情况', + fieldName: 'processingDetails', + component: 'Input', + componentProps: { + rows: 3, + }, + formItemClass: 'col-span-2', + disabled: true, + }, + { + label: '处理时间', + fieldName: 'processingTime', + component: 'DatePicker', + componentProps: { + format: 'YYYY.MM.DD HH:mm', + valueFormat: 'YYYY.MM.DD HH:mm', + showTime: true, + }, + disabled: true, + }, + { + label: '处理图片', + fieldName: 'imgUrl', + component: 'Input', + rules: 'required', + disabled: true, + }, + { + label: '级别', + fieldName: 'level', + component: 'Select', + componentProps: { + options: [ + { label: '特大', value: '特大' }, + { label: '重要', value: '重要' }, + { label: '一般', value: '一般' }, + ], + }, + rules: 'selectRequired', + }, + { + label: '处理状态', + fieldName: 'processingStatus', + component: 'Select', + componentProps: { + options: [ + { label: '待分配', value: '待分配' }, + { label: '处理中', value: '处理中' }, + { label: '已完成', value: '已完成' }, + ], + }, + rules: 'selectRequired', + }, + { + label: '预期处理时间', + fieldName: 'expectedProcessingTime', + component: 'DatePicker', + componentProps: { + format: 'YYYY.MM.DD HH:mm', + valueFormat: 'YYYY.MM.DD HH:mm', + showTime: true, + }, + rules: 'required', + }, +]; diff --git a/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningToDone/index.vue b/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningToDone/index.vue new file mode 100644 index 00000000..cb074052 --- /dev/null +++ b/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningToDone/index.vue @@ -0,0 +1,276 @@ + + + diff --git a/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningToDone/level-setting-modal.vue b/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningToDone/level-setting-modal.vue new file mode 100644 index 00000000..1568374a --- /dev/null +++ b/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningToDone/level-setting-modal.vue @@ -0,0 +1,45 @@ + + + diff --git a/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningToDone/warning-detail.vue b/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningToDone/warning-detail.vue new file mode 100644 index 00000000..9479a43b --- /dev/null +++ b/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningToDone/warning-detail.vue @@ -0,0 +1,147 @@ + + + diff --git a/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningToDone/warning-modal.vue b/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningToDone/warning-modal.vue new file mode 100644 index 00000000..78c338ea --- /dev/null +++ b/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningToDone/warning-modal.vue @@ -0,0 +1,121 @@ + + + + From 938bb0a52a984b109608e0a0d15e52bb112671e5 Mon Sep 17 00:00:00 2001 From: FLL <2162874245@qq.com> Date: Tue, 12 Aug 2025 13:59:23 +0800 Subject: [PATCH 15/28] =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../property/customerService/commonProblem/index.vue | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 apps/web-antd/src/views/property/customerService/commonProblem/index.vue diff --git a/apps/web-antd/src/views/property/customerService/commonProblem/index.vue b/apps/web-antd/src/views/property/customerService/commonProblem/index.vue new file mode 100644 index 00000000..8300c0b3 --- /dev/null +++ b/apps/web-antd/src/views/property/customerService/commonProblem/index.vue @@ -0,0 +1,11 @@ + + + + + From 8cf6df683d82103a04dab9644efda632e812e91e Mon Sep 17 00:00:00 2001 From: lxj <15683799673@163.com> Date: Tue, 12 Aug 2025 15:47:15 +0800 Subject: [PATCH 16/28] =?UTF-8?q?=E9=A1=B5=E9=9D=A2=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/web-antd/src/api/sis/stream/index.ts | 11 ++ .../src/views/screen/monitor/map/Map.vue | 149 +++++++++++++++--- .../src/views/screen/monitor/map/map.scss | 5 + apps/web-antd/src/views/sis/acAdmin/index.vue | 2 +- apps/web-antd/src/views/sis/video/index.vue | 17 +- 5 files changed, 158 insertions(+), 26 deletions(-) diff --git a/apps/web-antd/src/api/sis/stream/index.ts b/apps/web-antd/src/api/sis/stream/index.ts index c233a1f5..87e18d94 100644 --- a/apps/web-antd/src/api/sis/stream/index.ts +++ b/apps/web-antd/src/api/sis/stream/index.ts @@ -19,3 +19,14 @@ export function addFFmpegStreamProxy(params?: any) { params, ); } + +export function addMediaStreamProxy(params?: any) { + return requestClient.post('sis/stream/proxy', params); +} + +export function addFFmpegMediaStreamProxy(params?: any) { + return requestClient.post( + 'sis/stream/ffmpeg/proxy', + params, + ); +} diff --git a/apps/web-antd/src/views/screen/monitor/map/Map.vue b/apps/web-antd/src/views/screen/monitor/map/Map.vue index a6c3478d..f56abc0f 100644 --- a/apps/web-antd/src/views/screen/monitor/map/Map.vue +++ b/apps/web-antd/src/views/screen/monitor/map/Map.vue @@ -8,13 +8,42 @@ import './map.scss'; import { icons, MapDefaultData } from './constants.js'; import { onMounted } from 'vue'; import { deviceManageList } from '#/api/sis/deviceManage/index.js'; +import { deviceChannelList } from '#/api/sis/deviceChannel/index.js'; +import mpegts from 'mpegts.js'; +import { message } from 'ant-design-vue'; +import { + addFFmpegMediaStreamProxy, + addMediaStreamProxy, +} from '#/api/sis/stream/index.js'; +import { checkHEVCSupport } from '#/utils/video.js'; // 地图全局对象 let map = null; - +let currentPlayer; +let videoElement; +let isSupportH265 = false; onMounted(() => { + // 检测浏览器是否支持h265 + isSupportH265 = checkHEVCSupport(); mapFn.intiMap(); // 加载设备信息 + loadCameraData(); + // 增加视频追帧操作 + setInterval(catchUp, 10000); +}); + +function catchUp() { + if (currentPlayer) { + const end = currentPlayer.buffered.end(player.buffered.length - 1); + const diff = end - videoElement.currentTime; + if (diff > 2) { + // 如果延迟超过2秒 + videoElement.currentTime = end - 0.5; // 跳转到接近直播点 + } + } +} + +function loadCameraData() { deviceManageList({ deviceType: 1 }).then(({ rows = [], total = 0 }) => { if (total > 0) { // 渲染设备点位信息 @@ -29,39 +58,111 @@ onMounted(() => { mapFn.renderOverLayersData(items, function (marker, data) { // 渲染设备点击事件 marker.addEventListener('click', () => { - console.log(data); // 查询当前设备的通道信息 - - //渲染设备播放列表 - const html = [ - '
', - `
${data.deviceName}
`, - `
X
`, - `
`, - `
`, - '', - `
`, - `
`, - `
`, - ]; - const infoWindow = new BMap.InfoWindow(html.join(''), { - width: 530, - height: 350, - enableCloseOnClick: false, - }); - map.openInfoWindow(infoWindow, marker.point); + const params = { + deviceIp: data.deviceIp, + pageNum: 1, + pageSize: 10, + }; + deviceChannelList({ deviceIp: data.deviceIp }).then( + ({ total, rows }) => { + console.log(data); + const deviceData = { ...data }; + if (total > 0) { + //渲染设备播放列表 + const deviceName = deviceData.deviceName; + const html = [ + '
', + `
${deviceName}
`, + `
X
`, + `
`, + `
`, + '', + `
`, + `
`, + `
`, + ]; + const infoWindow = new BMap.InfoWindow(html.join(''), { + width: 530, + height: 350, + enableCloseOnClick: false, + }); + map.openInfoWindow(infoWindow, marker.point); + const data = rows[0]; + const params = {}; + if (data.nvrIp) { + params.deviceIp = data.nvrIp; + params.channelNo = data.nvrChannelNo; + } else { + params.deviceIp = data.deviceIp; + params.channelNo = data.channelNo; + } + doPlayer(params); + } + }, + ); }); }); } }); -}); -// 当前页面播放的对象 -let currentPlayer = undefined; +} +/** + * 开始播放视频流 + * @param nodeData 播放的节点数据 + */ +function doPlayer(nodeData) { + if (mpegts.isSupported()) { + streamProxy(nodeData, (res) => { + const url = res.flv; + // 将url 绑定到 nodeData + nodeData.url = url; + closeVideo(currentPlayer); + const videoConfig = { + type: 'flv', + url: url, + isLive: true, + hasAudio: false, + hasVideo: true, + enableWorker: true, // 启用分离的线程进行转码 + enableStashBuffer: false, // 关闭IO隐藏缓冲区 + stashInitialSize: 256, // 减少首帧显示等待时长 + }; + const playerConfig = { + enableErrorRecover: true, // 启用错误恢复 + autoCleanupMaxBackwardDuration: 30, + autoCleanupMinBackwardDuration: 10, + }; + const player = mpegts.createPlayer(videoConfig, playerConfig); + const videoElement = document.getElementById('video-player'); + if (videoElement) { + player.attachMediaElement(videoElement); + player.load(); + player.play(); + } else { + console.log('视频播放元素获取异常'); + } + }); + } else { + message.error('浏览器不支持播放'); + } +} + +function streamProxy(params, cb) { + if (isSupportH265) { + addMediaStreamProxy(params).then((res) => cb(res)); + } else { + // addMediaStreamProxy(params).then((res) => cb(res)); + addFFmpegMediaStreamProxy(params).then((res) => cb(res)); + } +} + +// 当前页面播放的对象 window.pageEvent = { closeInfoWindow() { map.closeInfoWindow(); closeVideo(currentPlayer); + currentPlayer = null; }, }; diff --git a/apps/web-antd/src/views/screen/monitor/map/map.scss b/apps/web-antd/src/views/screen/monitor/map/map.scss index 828858fa..1174a593 100644 --- a/apps/web-antd/src/views/screen/monitor/map/map.scss +++ b/apps/web-antd/src/views/screen/monitor/map/map.scss @@ -75,6 +75,11 @@ height: 111%; } + video { + width: 100%; + height: 100%; + } + .content-right { margin-left: 15px; padding-top: 10px; diff --git a/apps/web-antd/src/views/sis/acAdmin/index.vue b/apps/web-antd/src/views/sis/acAdmin/index.vue index dd871237..8d6febaf 100644 --- a/apps/web-antd/src/views/sis/acAdmin/index.vue +++ b/apps/web-antd/src/views/sis/acAdmin/index.vue @@ -178,7 +178,7 @@ function doPlayer(nodeData: any, index: number = 0) { console.log('index=', index); if (mpegts.isSupported()) { streamProxy(nodeData, (res: AddStreamProxyResult) => { - const url = res.wsFlv; + const url = res.flv; // 将url 绑定到 nodeData nodeData.url = url; closePlayer(index); diff --git a/apps/web-antd/src/views/sis/video/index.vue b/apps/web-antd/src/views/sis/video/index.vue index da6348c1..bda3df59 100644 --- a/apps/web-antd/src/views/sis/video/index.vue +++ b/apps/web-antd/src/views/sis/video/index.vue @@ -305,7 +305,7 @@ function doPlayer(nodeData: any, index: number = 0) { console.log('index=', index); if (mpegts.isSupported()) { streamProxy(nodeData, (res: AddStreamProxyResult) => { - const url = res.wsFlv; + const url = res.flv; // 将url 绑定到 nodeData nodeData.url = url; closePlayer(index); @@ -371,10 +371,25 @@ function closePlayer(index: number) { } } +function catchUp() { + playerList.forEach((playerData) => { + if (playerData) { + const { player, el } = playerData; + const end = player.buffered.end(player.buffered.length - 1); + const diff = end - el.currentTime; + if (diff > 2) { + // 如果延迟超过2秒 + el.currentTime = end - 0.5; // 跳转到接近直播点 + } + } + }); +} + let isSupportH265 = false; onMounted(() => { // 检测浏览器是否支持h265 isSupportH265 = checkHEVCSupport(); + setInterval(catchUp, 10000); }); onUnmounted(() => { From 13f79986f8920374f1b75275c715ea3f1c0bce28 Mon Sep 17 00:00:00 2001 From: fyy <2717885210@qq.com> Date: Tue, 12 Aug 2025 17:30:57 +0800 Subject: [PATCH 17/28] =?UTF-8?q?=E6=9F=A5=E8=AF=A2=E6=8E=92=E7=8F=AD?= =?UTF-8?q?=E8=AF=A6=E8=AF=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../workforceManagement/arrangement-modal.vue | 2 +- .../workforceManagement/data.ts | 3 ++- .../workforceManagement/unit-person-modal.vue | 1 - .../workforceManagement/workforce-detail.vue | 26 ++++++++++++------- 4 files changed, 19 insertions(+), 13 deletions(-) diff --git a/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/arrangement-modal.vue b/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/arrangement-modal.vue index 85d4c4ec..13251334 100644 --- a/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/arrangement-modal.vue +++ b/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/arrangement-modal.vue @@ -207,8 +207,8 @@ const [BasicModal, modalApi] = useVbenModal({ if (!isOpen) { return null; } - await getGroupList(); modalApi.modalLoading(true); + await getGroupList(); // await markInitialized(); modalApi.modalLoading(false); }, diff --git a/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/data.ts b/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/data.ts index 27466c77..42f47b65 100644 --- a/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/data.ts +++ b/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/data.ts @@ -120,12 +120,13 @@ export const columns: VxeGridProps['columns'] = [ minWidth: 200, slots: { default: ({ row }) => { + if(!row.attendanceShift) return '/'; if (row.attendanceShift.startTime && row.attendanceShift.endTime) { if ( row.attendanceShift.restEndTime && row.attendanceShift.restStartTime ) { - return `${row.attendanceShift.startTime}~${row.attendanceShift.endTime} ${row.shift.restStartTime}~${row.shift.restEndTime}`; + return `${row.attendanceShift.startTime}~${row.attendanceShift.endTime} ${row.attendanceShift.restStartTime}~${row.attendanceShift.restEndTime}`; } else { return `${row.attendanceShift.startTime}~${row.attendanceShift.endTime}`; } diff --git a/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/unit-person-modal.vue b/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/unit-person-modal.vue index 425ef105..d8d7ae92 100644 --- a/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/unit-person-modal.vue +++ b/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/unit-person-modal.vue @@ -192,7 +192,6 @@ async function handleConfirm() { }); } } - console.log(tableData); resetInitialized(); emit('reload', tableData); tableData = []; diff --git a/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/workforce-detail.vue b/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/workforce-detail.vue index 900d0d29..496b3bc4 100644 --- a/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/workforce-detail.vue +++ b/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/workforce-detail.vue @@ -1,5 +1,5 @@ + + + diff --git a/apps/web-antd/src/views/property/attendanceManagement/attendanceArea/data.ts b/apps/web-antd/src/views/property/attendanceManagement/attendanceArea/data.ts new file mode 100644 index 00000000..35a9ec6f --- /dev/null +++ b/apps/web-antd/src/views/property/attendanceManagement/attendanceArea/data.ts @@ -0,0 +1,68 @@ +import type { FormSchemaGetter } from '#/adapter/form'; +import type { VxeGridProps } from '#/adapter/vxe-table'; + + +export const querySchema: FormSchemaGetter = () => [ + { + component: 'Input', + fieldName: 'area', + label: '区域', + } +]; + +// 需要使用i18n注意这里要改成getter形式 否则切换语言不会刷新 +// export const columns: () => VxeGridProps['columns'] = () => [ +export const columns: VxeGridProps['columns'] = [ + { type: 'checkbox', width: 60 }, + { + title: '区域', + field: 'area', + width: 'auto', + }, + { + title: '摄像机id', + field: 'deviceManageId', + minWidth: 300, + }, + + { + title: '备注', + field: 'reamark', + }, + { + field: 'action', + fixed: 'right', + slots: { default: 'action' }, + title: '操作', + width: 180, + }, +]; + +export const modalSchema: FormSchemaGetter = () => [ + { + label: '主键id', + fieldName: 'id', + component: 'Input', + dependencies: { + show: () => false, + triggerFields: [''], + }, + }, + { + label: '区域', + fieldName: 'area', + component: 'Input', + }, + { + label: '摄像机id', + fieldName: 'deviceManageId', + component: 'Select', + componentProps: { + }, + }, + { + label: '备注', + fieldName: 'reamark', + component: 'Input', + }, +]; diff --git a/apps/web-antd/src/views/property/attendanceManagement/attendanceArea/index.vue b/apps/web-antd/src/views/property/attendanceManagement/attendanceArea/index.vue new file mode 100644 index 00000000..52cc246e --- /dev/null +++ b/apps/web-antd/src/views/property/attendanceManagement/attendanceArea/index.vue @@ -0,0 +1,182 @@ + + + diff --git a/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/calendarView.vue b/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/calendarView.vue index 87f5d535..a91c95b9 100644 --- a/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/calendarView.vue +++ b/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/calendarView.vue @@ -180,8 +180,8 @@ const getListData2 = ( if (found) { return found.list; } - } + } // 如果没有找到数据,返回空数组 return []; }; diff --git a/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/data.ts b/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/data.ts index 42f47b65..ddf61fb8 100644 --- a/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/data.ts +++ b/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/data.ts @@ -82,13 +82,13 @@ export const columns: VxeGridProps['columns'] = [ }, { title: '人员', - field: 'employeeName', + field: 'sysUser.userName', width: 120, // width: 'auto', }, { title: '单位', - field: 'deptName', + field: 'sysUser.deptName', width: 'auto', }, // { diff --git a/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/scheduleView.vue b/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/scheduleView.vue index 6a22a6aa..dd0262d7 100644 --- a/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/scheduleView.vue +++ b/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/scheduleView.vue @@ -83,12 +83,12 @@ function handleAdd() { } async function handleEdit(row: Required) { - modalApi.setData({ id: row.id }); + modalApi.setData({ id: row.scheduleId }); modalApi.open(); } async function handleDelete(row: Required) { - await arrangementRemove(row.id); + await arrangementRemove(row.scheduleId); await tableApi.query(); } @@ -129,12 +129,6 @@ async function handleDelete(row: Required) { From 2cdbc64250818f3515d9416fc08395dffa59211d Mon Sep 17 00:00:00 2001 From: dev_ljl <2590379346@qq.com> Date: Thu, 14 Aug 2025 14:58:42 +0800 Subject: [PATCH 20/28] =?UTF-8?q?feat:=E8=B0=83=E6=9F=A5=E9=97=AE=E5=8D=B7?= =?UTF-8?q?=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../customerService/questionnaire/data.ts | 158 +++++++ .../customerService/questionnaire/index.vue | 231 ++++++++++ .../questionnaire/questionnaire-detail.vue | 96 ++++ .../questionnaire/questionnaire-modal.vue | 421 ++++++++++++++++++ 4 files changed, 906 insertions(+) create mode 100644 apps/web-antd/src/views/property/customerService/questionnaire/data.ts create mode 100644 apps/web-antd/src/views/property/customerService/questionnaire/index.vue create mode 100644 apps/web-antd/src/views/property/customerService/questionnaire/questionnaire-detail.vue create mode 100644 apps/web-antd/src/views/property/customerService/questionnaire/questionnaire-modal.vue diff --git a/apps/web-antd/src/views/property/customerService/questionnaire/data.ts b/apps/web-antd/src/views/property/customerService/questionnaire/data.ts new file mode 100644 index 00000000..933e55ec --- /dev/null +++ b/apps/web-antd/src/views/property/customerService/questionnaire/data.ts @@ -0,0 +1,158 @@ +import type { FormSchemaGetter } from '#/adapter/form'; +import type { VxeGridProps } from '#/adapter/vxe-table'; +import { getDictOptions } from '#/utils/dict'; +import { renderDict } from '#/utils/render'; +import {h} from "vue"; +import {Rate} from "ant-design-vue"; + +export const querySchema: FormSchemaGetter = () => [ + { + component: 'Select', + componentProps: { + options: getDictOptions('type_contingency_plan'), + }, + fieldName: 'contingenPlanType', + label: '预案类型', + }, + { + component: 'ApiSelect', + fieldName: 'dutyPersion', + label: '责任人', + }, + { + component: 'Select', + componentProps: { + options: getDictOptions('pro_exercise_status'), + }, + fieldName: 'status', + label: '演练状态', + }, +]; + +export const columns: VxeGridProps['columns'] = [ + { type: 'checkbox', width: 60 }, + { + title: '序号', + field: 'id', + slots: { + default: ({rowIndex}) => { + return (rowIndex + 1).toString(); + } + } + }, + { + title: '预案名称', + field: 'contingenPlanName', + }, + { + title: '预案类型', + field: 'contingenPlanType', + slots: { + default: ({ row }) => { + return renderDict(row.contingenPlanType, 'type_contingency_plan'); + }, + }, + }, + { + title: '风险等级', + field: 'grade', + slots: { + default: ({ row }) => { + return h(Rate, { + value: row.grade || 0, + disabled: true, + }); + }, + }, + minWidth: '150' + }, + { + title: '发起人', + field: 'initiatName', + }, + { + title: '演练状态', + field: 'status', + slots: { + default: ({ row }) => { + return renderDict(row.status, 'pro_exercise_status'); + }, + }, + }, + { + title: '责任人', + field: 'dutyPersionName', + }, + { + title: '完成时间', + field: 'compleTimes', + }, + { + field: 'action', + fixed: 'right', + slots: { default: 'action' }, + title: '操作', + width: 240, + }, +]; + +export const modalSchema: FormSchemaGetter = () => [ + { + label: '主键', + fieldName: 'id', + component: 'Input', + dependencies: { + show: () => false, + triggerFields: [''], + }, + }, + { + label: '预案名称', + fieldName: 'contingenPlanName', + component: 'Input', + rules: 'required', + }, + { + label: '预案类型', + fieldName: 'contingenPlanType', + component: 'Select', + componentProps: { + options: getDictOptions('type_contingency_plan'), + }, + rules: 'selectRequired', + }, + { + label: '发起人', + fieldName: 'initiat', + component: 'ApiSelect', + rules: 'selectRequired', + }, + { + label: '责任人', + fieldName: 'dutyPersion', + component: 'ApiSelect', + rules: 'selectRequired', + }, + { + label: '预案内容', + fieldName: 'contingenPlanContent', + component: 'RichTextarea', + componentProps: { + // disabled: false, // 是否只读 + // height: 400 // 高度 默认400 + }, + formItemClass: 'col-span-2' + }, + { + label: '风险等级', + fieldName: 'grade', + component: 'Rate', + componentProps: { + allowHalf: false, + count: 5, + tooltips: ['1星', '2星', '3星', '4星', '5星'], + defaultValue: 0 + }, + rules: 'required', + }, +]; diff --git a/apps/web-antd/src/views/property/customerService/questionnaire/index.vue b/apps/web-antd/src/views/property/customerService/questionnaire/index.vue new file mode 100644 index 00000000..149a5bd4 --- /dev/null +++ b/apps/web-antd/src/views/property/customerService/questionnaire/index.vue @@ -0,0 +1,231 @@ + + + diff --git a/apps/web-antd/src/views/property/customerService/questionnaire/questionnaire-detail.vue b/apps/web-antd/src/views/property/customerService/questionnaire/questionnaire-detail.vue new file mode 100644 index 00000000..bf8fb9a2 --- /dev/null +++ b/apps/web-antd/src/views/property/customerService/questionnaire/questionnaire-detail.vue @@ -0,0 +1,96 @@ + + + diff --git a/apps/web-antd/src/views/property/customerService/questionnaire/questionnaire-modal.vue b/apps/web-antd/src/views/property/customerService/questionnaire/questionnaire-modal.vue new file mode 100644 index 00000000..f49a0444 --- /dev/null +++ b/apps/web-antd/src/views/property/customerService/questionnaire/questionnaire-modal.vue @@ -0,0 +1,421 @@ + + + + + From f24ec168bf376b5df9f3aff25df217c5f5f9af33 Mon Sep 17 00:00:00 2001 From: dev_ljl <2590379346@qq.com> Date: Thu, 14 Aug 2025 15:12:40 +0800 Subject: [PATCH 21/28] =?UTF-8?q?feat:=E8=B0=83=E6=9F=A5=E9=97=AE=E5=8D=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../property/questionnaire/question/index.ts | 61 ++++++++++ .../questionnaire/question/model.d.ts | 114 ++++++++++++++++++ .../questionnaire/questionItem/index.ts | 61 ++++++++++ .../questionnaire/questionItem/model.d.ts | 79 ++++++++++++ .../questionnaire/questionnaire/index.ts | 61 ++++++++++ .../questionnaire/questionnaire/model.d.ts | 114 ++++++++++++++++++ 6 files changed, 490 insertions(+) create mode 100644 apps/web-antd/src/api/property/questionnaire/question/index.ts create mode 100644 apps/web-antd/src/api/property/questionnaire/question/model.d.ts create mode 100644 apps/web-antd/src/api/property/questionnaire/questionItem/index.ts create mode 100644 apps/web-antd/src/api/property/questionnaire/questionItem/model.d.ts create mode 100644 apps/web-antd/src/api/property/questionnaire/questionnaire/index.ts create mode 100644 apps/web-antd/src/api/property/questionnaire/questionnaire/model.d.ts diff --git a/apps/web-antd/src/api/property/questionnaire/question/index.ts b/apps/web-antd/src/api/property/questionnaire/question/index.ts new file mode 100644 index 00000000..12365003 --- /dev/null +++ b/apps/web-antd/src/api/property/questionnaire/question/index.ts @@ -0,0 +1,61 @@ +import type { QuestionVO, QuestionForm, QuestionQuery } from './model'; + +import type { ID, IDS } from '#/api/common'; +import type { PageResult } from '#/api/common'; + +import { commonExport } from '#/api/helper'; +import { requestClient } from '#/api/request'; + +/** +* 查询调查问卷问题列表 +* @param params +* @returns 调查问卷问题列表 +*/ +export function questionList(params?: QuestionQuery) { + return requestClient.get>('/property/question/list', { params }); +} + +/** + * 导出调查问卷问题列表 + * @param params + * @returns 调查问卷问题列表 + */ +export function questionExport(params?: QuestionQuery) { + return commonExport('/property/question/export', params ?? {}); +} + +/** + * 查询调查问卷问题详情 + * @param id id + * @returns 调查问卷问题详情 + */ +export function questionInfo(id: ID) { + return requestClient.get(`/property/question/${id}`); +} + +/** + * 新增调查问卷问题 + * @param data + * @returns void + */ +export function questionAdd(data: QuestionForm) { + return requestClient.postWithMsg('/property/question', data); +} + +/** + * 更新调查问卷问题 + * @param data + * @returns void + */ +export function questionUpdate(data: QuestionForm) { + return requestClient.putWithMsg('/property/question', data); +} + +/** + * 删除调查问卷问题 + * @param id id + * @returns void + */ +export function questionRemove(id: ID | IDS) { + return requestClient.deleteWithMsg(`/property/question/${id}`); +} diff --git a/apps/web-antd/src/api/property/questionnaire/question/model.d.ts b/apps/web-antd/src/api/property/questionnaire/question/model.d.ts new file mode 100644 index 00000000..c5367713 --- /dev/null +++ b/apps/web-antd/src/api/property/questionnaire/question/model.d.ts @@ -0,0 +1,114 @@ +import type { PageQuery, BaseEntity } from '#/api/common'; + +export interface QuestionVO { + /** + * id + */ + id: string | number; + + /** + * 调查问卷id + */ + questionnaireId: string | number; + + /** + * 标题 + */ + head: string; + + /** + * 问题类型(1单行文本2多行文本3单选题4多选题5评分题6日期选择) + */ + type: string; + + /** + * 是否必填(1不必填2必填) + */ + isRequired: string; + + /** + * 描述 + */ + depict: string; + + /** + * 排序 + */ + sort: number; + +} + +export interface QuestionForm extends BaseEntity { + /** + * id + */ + id?: string | number; + + /** + * 调查问卷id + */ + questionnaireId?: string | number; + + /** + * 标题 + */ + head?: string; + + /** + * 问题类型(1单行文本2多行文本3单选题4多选题5评分题6日期选择) + */ + type?: string; + + /** + * 是否必填(1不必填2必填) + */ + isRequired?: string; + + /** + * 描述 + */ + depict?: string; + + /** + * 排序 + */ + sort?: number; + +} + +export interface QuestionQuery extends PageQuery { + /** + * 调查问卷id + */ + questionnaireId?: string | number; + + /** + * 标题 + */ + head?: string; + + /** + * 问题类型(1单行文本2多行文本3单选题4多选题5评分题6日期选择) + */ + type?: string; + + /** + * 是否必填(1不必填2必填) + */ + isRequired?: string; + + /** + * 描述 + */ + depict?: string; + + /** + * 排序 + */ + sort?: number; + + /** + * 日期范围参数 + */ + params?: any; +} diff --git a/apps/web-antd/src/api/property/questionnaire/questionItem/index.ts b/apps/web-antd/src/api/property/questionnaire/questionItem/index.ts new file mode 100644 index 00000000..c66defca --- /dev/null +++ b/apps/web-antd/src/api/property/questionnaire/questionItem/index.ts @@ -0,0 +1,61 @@ +import type { QuestionItemVO, QuestionItemForm, QuestionItemQuery } from './model'; + +import type { ID, IDS } from '#/api/common'; +import type { PageResult } from '#/api/common'; + +import { commonExport } from '#/api/helper'; +import { requestClient } from '#/api/request'; + +/** +* 查询调查问卷问题选项列表 +* @param params +* @returns 调查问卷问题选项列表 +*/ +export function questionItemList(params?: QuestionItemQuery) { + return requestClient.get>('/property/questionItem/list', { params }); +} + +/** + * 导出调查问卷问题选项列表 + * @param params + * @returns 调查问卷问题选项列表 + */ +export function questionItemExport(params?: QuestionItemQuery) { + return commonExport('/property/questionItem/export', params ?? {}); +} + +/** + * 查询调查问卷问题选项详情 + * @param id id + * @returns 调查问卷问题选项详情 + */ +export function questionItemInfo(id: ID) { + return requestClient.get(`/property/questionItem/${id}`); +} + +/** + * 新增调查问卷问题选项 + * @param data + * @returns void + */ +export function questionItemAdd(data: QuestionItemForm) { + return requestClient.postWithMsg('/property/questionItem', data); +} + +/** + * 更新调查问卷问题选项 + * @param data + * @returns void + */ +export function questionItemUpdate(data: QuestionItemForm) { + return requestClient.putWithMsg('/property/questionItem', data); +} + +/** + * 删除调查问卷问题选项 + * @param id id + * @returns void + */ +export function questionItemRemove(id: ID | IDS) { + return requestClient.deleteWithMsg(`/property/questionItem/${id}`); +} diff --git a/apps/web-antd/src/api/property/questionnaire/questionItem/model.d.ts b/apps/web-antd/src/api/property/questionnaire/questionItem/model.d.ts new file mode 100644 index 00000000..3dea08ba --- /dev/null +++ b/apps/web-antd/src/api/property/questionnaire/questionItem/model.d.ts @@ -0,0 +1,79 @@ +import type { PageQuery, BaseEntity } from '#/api/common'; + +export interface QuestionItemVO { + /** + * id + */ + id: string | number; + + /** + * 问题id + */ + questionId: string | number; + + /** + * 选项内容 + */ + itemContent: string; + + /** + * 排序 + */ + sort: number; + + /** + * 备注 + */ + remark: string; + +} + +export interface QuestionItemForm extends BaseEntity { + /** + * id + */ + id?: string | number; + + /** + * 问题id + */ + questionId?: string | number; + + /** + * 选项内容 + */ + itemContent?: string; + + /** + * 排序 + */ + sort?: number; + + /** + * 备注 + */ + remark?: string; + +} + +export interface QuestionItemQuery extends PageQuery { + /** + * 问题id + */ + questionId?: string | number; + + /** + * 选项内容 + */ + itemContent?: string; + + /** + * 排序 + */ + sort?: number; + + /** + * 日期范围参数 + */ + params?: any; +} diff --git a/apps/web-antd/src/api/property/questionnaire/questionnaire/index.ts b/apps/web-antd/src/api/property/questionnaire/questionnaire/index.ts new file mode 100644 index 00000000..06321b2c --- /dev/null +++ b/apps/web-antd/src/api/property/questionnaire/questionnaire/index.ts @@ -0,0 +1,61 @@ +import type { QuestionnaireVO, QuestionnaireForm, QuestionnaireQuery } from './model'; + +import type { ID, IDS } from '#/api/common'; +import type { PageResult } from '#/api/common'; + +import { commonExport } from '#/api/helper'; +import { requestClient } from '#/api/request'; + +/** +* 查询调查问卷列表 +* @param params +* @returns 调查问卷列表 +*/ +export function questionnaireList(params?: QuestionnaireQuery) { + return requestClient.get>('/property/questionnaire/list', { params }); +} + +/** + * 导出调查问卷列表 + * @param params + * @returns 调查问卷列表 + */ +export function questionnaireExport(params?: QuestionnaireQuery) { + return commonExport('/property/questionnaire/export', params ?? {}); +} + +/** + * 查询调查问卷详情 + * @param id id + * @returns 调查问卷详情 + */ +export function questionnaireInfo(id: ID) { + return requestClient.get(`/property/questionnaire/${id}`); +} + +/** + * 新增调查问卷 + * @param data + * @returns void + */ +export function questionnaireAdd(data: QuestionnaireForm) { + return requestClient.postWithMsg('/property/questionnaire', data); +} + +/** + * 更新调查问卷 + * @param data + * @returns void + */ +export function questionnaireUpdate(data: QuestionnaireForm) { + return requestClient.putWithMsg('/property/questionnaire', data); +} + +/** + * 删除调查问卷 + * @param id id + * @returns void + */ +export function questionnaireRemove(id: ID | IDS) { + return requestClient.deleteWithMsg(`/property/questionnaire/${id}`); +} diff --git a/apps/web-antd/src/api/property/questionnaire/questionnaire/model.d.ts b/apps/web-antd/src/api/property/questionnaire/questionnaire/model.d.ts new file mode 100644 index 00000000..d28fca41 --- /dev/null +++ b/apps/web-antd/src/api/property/questionnaire/questionnaire/model.d.ts @@ -0,0 +1,114 @@ +import type { PageQuery, BaseEntity } from '#/api/common'; + +export interface QuestionnaireVO { + /** + * id + */ + id: string | number; + + /** + * 标题 + */ + head: string; + + /** + * 描述 + */ + depict: string; + + /** + * 是否匿名收集 + */ + isAnonyCollec: string; + + /** + * 是否多次提交 + */ + isCommit: string; + + /** + * 截止日期 + */ + deadline: string; + + /** + * 状态(1草稿2已发布3未发布) + */ + status: string; + +} + +export interface QuestionnaireForm extends BaseEntity { + /** + * id + */ + id?: string | number; + + /** + * 标题 + */ + head?: string; + + /** + * 描述 + */ + depict?: string; + + /** + * 是否匿名收集 + */ + isAnonyCollec?: string; + + /** + * 是否多次提交 + */ + isCommit?: string; + + /** + * 截止日期 + */ + deadline?: string; + + /** + * 状态(1草稿2已发布3未发布) + */ + status?: string; + +} + +export interface QuestionnaireQuery extends PageQuery { + /** + * 标题 + */ + head?: string; + + /** + * 描述 + */ + depict?: string; + + /** + * 是否匿名收集 + */ + isAnonyCollec?: string; + + /** + * 是否多次提交 + */ + isCommit?: string; + + /** + * 截止日期 + */ + deadline?: string; + + /** + * 状态(1草稿2已发布3未发布) + */ + status?: string; + + /** + * 日期范围参数 + */ + params?: any; +} From fcd4051e906646e612a2ce833e1fc20cafa892ab Mon Sep 17 00:00:00 2001 From: FLL <2162874245@qq.com> Date: Thu, 14 Aug 2025 15:14:32 +0800 Subject: [PATCH 22/28] =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../visitorManagement/visitorInvitation/data.ts | 14 ++++++++++++-- .../visitorInvitation/visitorInvitation-detail.vue | 6 ++++-- .../visitorTodo/visitorTodo-detail.vue | 6 ++++-- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/apps/web-antd/src/views/property/visitorManagement/visitorInvitation/data.ts b/apps/web-antd/src/views/property/visitorManagement/visitorInvitation/data.ts index ccbcfa04..b4eaa93b 100644 --- a/apps/web-antd/src/views/property/visitorManagement/visitorInvitation/data.ts +++ b/apps/web-antd/src/views/property/visitorManagement/visitorInvitation/data.ts @@ -1,5 +1,7 @@ import type { FormSchemaGetter } from '#/adapter/form'; import type { VxeGridProps } from '#/adapter/vxe-table'; +import {getDictOptions} from "#/utils/dict"; +import {renderDict} from "#/utils/render"; export const querySchema: FormSchemaGetter = () => [ { @@ -64,6 +66,11 @@ export const columns: VxeGridProps['columns'] = [ { title: '事由', field: 'visitingReason', + slots: { + default: ({ row }) => { + return renderDict(row.visitingReason, 'reason_for_visit'); + }, + }, }, { title: '拜访时间', @@ -156,8 +163,11 @@ export const modalSchema: FormSchemaGetter = () => [ { label: '事由', fieldName: 'visitingReason', - component: 'Input', - rules: 'required', + component: 'Select', + componentProps: { + options: getDictOptions('reason_for_visit'), + }, + rules: 'selectRequired', }, { label: '拜访时间', diff --git a/apps/web-antd/src/views/property/visitorManagement/visitorInvitation/visitorInvitation-detail.vue b/apps/web-antd/src/views/property/visitorManagement/visitorInvitation/visitorInvitation-detail.vue index 53bb98d1..1cfb8c9c 100644 --- a/apps/web-antd/src/views/property/visitorManagement/visitorInvitation/visitorInvitation-detail.vue +++ b/apps/web-antd/src/views/property/visitorManagement/visitorInvitation/visitorInvitation-detail.vue @@ -53,8 +53,10 @@ async function handleOpenChange(open: boolean) { {{ visitorInvitationDetail.interviewedUnit }} - - {{ visitorInvitationDetail.visitingReason }} + + {{ visitorInvitationDetail.visitingBeginTime+' - '+visitorInvitationDetail.visitingBeginTime }} diff --git a/apps/web-antd/src/views/property/visitorManagement/visitorTodo/visitorTodo-detail.vue b/apps/web-antd/src/views/property/visitorManagement/visitorTodo/visitorTodo-detail.vue index 16c92028..4a250854 100644 --- a/apps/web-antd/src/views/property/visitorManagement/visitorTodo/visitorTodo-detail.vue +++ b/apps/web-antd/src/views/property/visitorManagement/visitorTodo/visitorTodo-detail.vue @@ -59,8 +59,10 @@ async function handleOpenChange(open: boolean) { {{ visitorTodoDetail.interviewedUnit }} - - {{ visitorTodoDetail.visitingReason }} + + {{ visitorTodoDetail.visitingBeginTime+' - '+visitorTodoDetail.visitingBeginTime }} From 78ff0f0c3d0a1d96488d1298fd7e00025b5f5c83 Mon Sep 17 00:00:00 2001 From: fyy <2717885210@qq.com> Date: Thu, 14 Aug 2025 17:19:58 +0800 Subject: [PATCH 23/28] =?UTF-8?q?feat:=20=E9=97=AE=E5=8D=B7=E5=88=86?= =?UTF-8?q?=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/api/sis/deviceManage/model.d.ts | 4 +- .../attendanceArea/data.ts | 21 +- .../workforceManagement/data.ts | 6 +- .../workforce-day-detail.vue | 2 +- .../workforceManagement/workforce-detail.vue | 10 +- .../questionnaireAnalysis/data.ts | 0 .../questionnaireAnalysis/index.vue | 275 ++++++++++++++++++ .../questionnaire-table-modal.vue | 4 + 8 files changed, 306 insertions(+), 16 deletions(-) create mode 100644 apps/web-antd/src/views/property/customerService/questionnaireAnalysis/data.ts create mode 100644 apps/web-antd/src/views/property/customerService/questionnaireAnalysis/index.vue create mode 100644 apps/web-antd/src/views/property/customerService/questionnaireAnalysis/questionnaire-table-modal.vue diff --git a/apps/web-antd/src/api/sis/deviceManage/model.d.ts b/apps/web-antd/src/api/sis/deviceManage/model.d.ts index c961d7f0..3e27e50f 100644 --- a/apps/web-antd/src/api/sis/deviceManage/model.d.ts +++ b/apps/web-antd/src/api/sis/deviceManage/model.d.ts @@ -178,9 +178,9 @@ export interface DeviceManageQuery extends PageQuery { */ deviceMac?: string; - lon: number; + lon?: number; - lat: number; + lat?: number; /** * 设备在线状态 0:离线 1:在线 2:未知 diff --git a/apps/web-antd/src/views/property/attendanceManagement/attendanceArea/data.ts b/apps/web-antd/src/views/property/attendanceManagement/attendanceArea/data.ts index 35a9ec6f..9f0abf52 100644 --- a/apps/web-antd/src/views/property/attendanceManagement/attendanceArea/data.ts +++ b/apps/web-antd/src/views/property/attendanceManagement/attendanceArea/data.ts @@ -1,13 +1,12 @@ import type { FormSchemaGetter } from '#/adapter/form'; import type { VxeGridProps } from '#/adapter/vxe-table'; - - +import { deviceManageList } from '#/api/sis/deviceManage'; export const querySchema: FormSchemaGetter = () => [ { component: 'Input', fieldName: 'area', label: '区域', - } + }, ]; // 需要使用i18n注意这里要改成getter形式 否则切换语言不会刷新 @@ -54,10 +53,22 @@ export const modalSchema: FormSchemaGetter = () => [ component: 'Input', }, { - label: '摄像机id', + label: '摄像机', fieldName: 'deviceManageId', - component: 'Select', + component: 'ApiSelect', componentProps: { + api: async () => { + const res = await deviceManageList({ + pageNum: 1, + pageSize: 10000, + deviceType: 1, + }); + return res; + }, + resultField: 'rows', + labelField: 'deviceName', + valueField: 'id', + mode: 'multiple', }, }, { diff --git a/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/data.ts b/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/data.ts index ddf61fb8..331d649a 100644 --- a/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/data.ts +++ b/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/data.ts @@ -82,13 +82,13 @@ export const columns: VxeGridProps['columns'] = [ }, { title: '人员', - field: 'sysUser.userName', + field: 'remoteUserVo.userName', width: 120, // width: 'auto', }, { title: '单位', - field: 'sysUser.deptName', + field: 'deptName', width: 'auto', }, // { @@ -120,7 +120,7 @@ export const columns: VxeGridProps['columns'] = [ minWidth: 200, slots: { default: ({ row }) => { - if(!row.attendanceShift) return '/'; + if (!row.attendanceShift) return '/'; if (row.attendanceShift.startTime && row.attendanceShift.endTime) { if ( row.attendanceShift.restEndTime && diff --git a/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/workforce-day-detail.vue b/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/workforce-day-detail.vue index 23fb8b50..696610df 100644 --- a/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/workforce-day-detail.vue +++ b/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/workforce-day-detail.vue @@ -87,7 +87,7 @@ async function handleClosed() { :key="item.id" class="wrap-cell" > - {{ item.sysUser.userName }} + {{ item.remoteUserVo.userName }} diff --git a/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/workforce-detail.vue b/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/workforce-detail.vue index 0fd19db4..b5e64776 100644 --- a/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/workforce-detail.vue +++ b/apps/web-antd/src/views/property/attendanceManagement/workforceManagement/workforce-detail.vue @@ -1,5 +1,5 @@ + diff --git a/apps/web-antd/src/views/property/customerService/questionnaireAnalysis/questionnaire-table-modal.vue b/apps/web-antd/src/views/property/customerService/questionnaireAnalysis/questionnaire-table-modal.vue new file mode 100644 index 00000000..9d13f383 --- /dev/null +++ b/apps/web-antd/src/views/property/customerService/questionnaireAnalysis/questionnaire-table-modal.vue @@ -0,0 +1,4 @@ + + From 81de99b01513d6f20a00adf3e8757a20a1f955f7 Mon Sep 17 00:00:00 2001 From: lxj <15683799673@163.com> Date: Fri, 15 Aug 2025 14:08:35 +0800 Subject: [PATCH 24/28] =?UTF-8?q?=E4=BA=8B=E4=BB=B6=E5=91=8A=E8=AD=A6?= =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/web-antd/src/views/sis/video/index.vue | 3 +- .../videoWarningProcessing/data.ts | 82 +++--------- .../videoWarningProcessing/index.vue | 119 ++++++------------ .../base/shared/src/constants/dict-enum.ts | 7 ++ 4 files changed, 64 insertions(+), 147 deletions(-) diff --git a/apps/web-antd/src/views/sis/video/index.vue b/apps/web-antd/src/views/sis/video/index.vue index bda3df59..7390fef4 100644 --- a/apps/web-antd/src/views/sis/video/index.vue +++ b/apps/web-antd/src/views/sis/video/index.vue @@ -291,7 +291,8 @@ function streamProxy(nodeData: any, cb: Function) { if (isSupportH265) { addStreamProxy(params).then((res) => cb(res)); } else { - addFFmpegStreamProxy(params).then((res) => cb(res)); + // addFFmpegStreamProxy(params).then((res) => cb(res)); + addStreamProxy(params).then((res) => cb(res)); } } } diff --git a/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningProcessing/data.ts b/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningProcessing/data.ts index a6cae811..989bc049 100644 --- a/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningProcessing/data.ts +++ b/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningProcessing/data.ts @@ -1,8 +1,9 @@ import type { FormSchemaGetter } from '#/adapter/form'; import type { VxeGridProps } from '#/adapter/vxe-table'; -import { getDictOptions } from '#/utils/dict'; -import { renderDict } from '#/utils/render'; import { h } from 'vue'; +import { getPopupContainer } from '@vben/utils'; +import { getDictOptions } from '#/utils/dict'; +import { DictEnum } from '@vben/constants'; export const querySchema: FormSchemaGetter = () => [ { @@ -13,11 +14,8 @@ export const querySchema: FormSchemaGetter = () => [ { component: 'Select', componentProps: { - options: [ - { label: '特大', value: '特大' }, - { label: '重要', value: '重要' }, - { label: '一般', value: '一般' }, - ], + getPopupContainer, + options: getDictOptions(DictEnum.alarm_level), }, fieldName: 'level', label: '级别', @@ -25,13 +23,10 @@ export const querySchema: FormSchemaGetter = () => [ { component: 'Select', componentProps: { - options: [ - { label: '待分配', value: '待分配' }, - { label: '处理中', value: '处理中' }, - { label: '已完成', value: '已完成' }, - ], + getPopupContainer, + options: getDictOptions(DictEnum.alarm_state), }, - fieldName: 'processingStatus', + fieldName: 'state', label: '处理状态', }, ]; @@ -40,29 +35,25 @@ export const columns: VxeGridProps['columns'] = [ { type: 'checkbox', width: 60 }, { title: '预警编号', - field: 'alarmId', - width: 150, + field: 'id', }, { title: '预警时间', - field: 'alarmTime', - width: 150, + field: 'reportTime', }, { title: '设备名称', field: 'deviceName', - width: 150, }, { title: '级别', field: 'level', - width: 100, slots: { default: ({ row }: any) => { const levelColors: Record = { - 特大: 'red', - 重要: 'orange', - 一般: 'blue', + 1: 'red', + 2: 'orange', + 3: 'blue', }; return h( 'span', @@ -72,64 +63,31 @@ export const columns: VxeGridProps['columns'] = [ fontWeight: 'bold', }, }, - row.level, + row.levelName, ); }, }, }, { title: '预警类型', - field: 'alarmType', - width: 120, - }, - { - title: '描述', - field: 'description', - minWidth: 200, - }, - { - title: '所在位置', - field: 'location', - width: 150, - }, - { - title: '处理状态', - field: 'processingStatus', - width: 100, + field: 'alarmTypeName', slots: { default: ({ row }: any) => { - const statusColors: Record = { - 待分配: 'red', - 处理中: 'orange', - 已完成: 'green', - }; - return h( - 'span', - { - style: { - color: statusColors[row.processingStatus] || '#666', - fontWeight: 'bold', - }, - }, - row.processingStatus, - ); + return h('span', row.bigTypeName + '-' + row.smallTypeName); }, }, }, { - title: '处理情况', - field: 'processingDetails', - width: 150, + title: '处理状态', + field: 'stateName', }, { title: '预期处理时间', - field: 'expectedProcessingTime', - width: 150, + field: 'processSt', }, { title: '处理时间', - field: 'processingTime', - width: 150, + field: 'processEt', }, { field: 'action', diff --git a/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningProcessing/index.vue b/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningProcessing/index.vue index 7ff8410d..d15a9ad5 100644 --- a/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningProcessing/index.vue +++ b/apps/web-antd/src/views/videoSystem/videoWarning/videoWarningProcessing/index.vue @@ -2,69 +2,21 @@ import { Page, useVbenModal, type VbenFormProps } from '@vben/common-ui'; import { getVxePopupContainer } from '@vben/utils'; -import { Modal, Popconfirm, Space, Tag } from 'ant-design-vue'; -import { ref, watch } from 'vue'; - +import { Modal, Popconfirm, Space } from 'ant-design-vue'; import { useVbenVxeGrid, vxeCheckboxChecked, type VxeGridProps, } from '#/adapter/vxe-table'; -import { commonDownloadExcel } from '#/utils/file/download'; -import { renderDict } from '#/utils/render'; - import { columns, querySchema } from './data'; import warningModal from './warning-modal.vue'; import warningDetail from './warning-detail.vue'; import LevelSettingModal from './level-setting-modal.vue'; -import imgPng from '../../../../assets/algorithmManagement/image.png'; - -// 假数据 -const mockData = ref([ - { - id: 1, - alarmId: 'JWD-3434234', - alarmTime: '2025.07.21 12:20', - level: '特大', - alarmType: '越界侦测', - description: '温度高于80度发生火宅', - location: '1栋3号电梯旁', - processingStatus: '待分配', - processingDetails: '', - processingTime: '', - deviceName: '监控设备', - }, - { - id: 2, - alarmId: 'JWD-3434235', - alarmTime: '2025.07.21 11:15', - level: '重要', - alarmType: '异常行为', - description: '人员异常聚集', - location: '2栋大厅', - processingStatus: '处理中', - processingDetails: '已派人员前往处理', - processingTime: '2025.07.21 11:30', - expectedProcessingTime: '2025.07.21 11:30', - deviceName: '门禁设备', - }, - { - id: 3, - alarmId: 'JWD-3434236', - alarmTime: '2025.07.21 10:45', - level: '一般', - alarmType: '设备故障', - description: '摄像头离线', - location: '3栋走廊', - processingStatus: '已完成', - processingDetails: '已修复设备', - processingTime: '2025.07.21 11:00', - imgUrl: imgPng, - deviceName: '消防设备', - }, -]); +import { alarmEventsList, alarmEventsRemove } from '#/api/sis/alarmEvents'; +import type { AlarmEventsForm } from '#/api/sis/alarmEvents/model'; +/* 搜索栏配置 */ const formOptions: VbenFormProps = { commonConfig: { labelWidth: 100, @@ -76,14 +28,31 @@ const formOptions: VbenFormProps = { wrapperClass: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3', }; +/* table栏配置 */ const gridOptions: VxeGridProps = { + checkboxConfig: { + // 高亮 + highlight: true, + // 翻页时保留选中状态 + reserve: true, + // 点击行选中 + // trigger: 'row', + }, + // 需要使用i18n注意这里要改成getter形式 否则切换语言不会刷新 + // columns: columns(), columns, height: 'auto', - data: mockData.value, - pagerConfig: { - currentPage: 1, - pageSize: 10, - total: mockData.value.length, + pagerConfig: {}, + proxyConfig: { + ajax: { + query: async ({ page }, formValues = {}) => { + return await alarmEventsList({ + pageNum: page.currentPage, + pageSize: page.pageSize, + ...formValues, + }); + }, + }, }, rowConfig: { keyField: 'id', @@ -97,14 +66,6 @@ const [BasicTable, tableApi] = useVbenVxeGrid({ }); // 监听数据变化,强制重新渲染表格 -const tableKey = ref(0); -watch( - mockData, - () => { - tableKey.value++; - }, - { deep: true }, -); const [WarningModal, modalApi] = useVbenModal({ connectedComponent: warningModal, @@ -120,19 +81,19 @@ const [LevelSettingModalComp, levelModalApi] = useVbenModal({ // 级别设置 function handleLevelSetting(row: any) { - levelModalApi.setData({ id: row.id, level: row.level, data: mockData.value }); + levelModalApi.setData({ id: row.id, level: row.level, data: row }); levelModalApi.open(); } // 查看详情 async function handleView(row: any) { - detailApi.setData({ id: row.id, data: mockData.value }); + detailApi.setData({ id: row.id, data: row }); detailApi.open(); } // 编辑 async function handleEdit(row: any) { - modalApi.setData({ id: row.id, data: mockData.value }); + modalApi.setData({ id: row.id, data: row }); modalApi.open(); } @@ -143,7 +104,7 @@ function handleAssign(row: any) { content: `确定要分配预警 ${row.alarmId} 给处理人员吗?`, onOk() { // 模拟分配处理 - const index = mockData.value.findIndex((item: any) => item.id === row.id); + const index = row.id; if (index !== -1) { // mockData.value[index].processingStatus = '处理中'; // mockData.value[index].processingDetails = '已分配给处理人员'; @@ -156,9 +117,8 @@ function handleAssign(row: any) { // 删除 async function handleDelete(row: any) { - const index = mockData.value.findIndex((item: any) => item.id === row.id); + const index = row.id; if (index !== -1) { - mockData.value.splice(index, 1); await tableApi.query(); } } @@ -166,18 +126,13 @@ async function handleDelete(row: any) { // 批量删除 function handleMultiDelete() { const rows = tableApi.grid.getCheckboxRecords(); - const ids = rows.map((row: any) => row.id); + const ids = rows.map((row: Required) => row.id); Modal.confirm({ title: '提示', okType: 'danger', content: `确认删除选中的${ids.length}条记录吗?`, onOk: async () => { - ids.forEach((id) => { - const index = mockData.value.findIndex((item: any) => item.id === id); - if (index !== -1) { - mockData.value.splice(index, 1); - } - }); + await alarmEventsRemove(ids); await tableApi.query(); }, }); @@ -185,11 +140,7 @@ function handleMultiDelete() {