添加物联设备同步查询与分配功能

This commit is contained in:
yangjun 2025-07-25 10:21:33 +08:00
parent bbf7e9872e
commit 9fed0b9442
9 changed files with 444 additions and 8 deletions

View File

@ -89,7 +89,6 @@
opt.getContainer = `.${prefixVar}-layout-content` as any; opt.getContainer = `.${prefixVar}-layout-content` as any;
} }
} }
console.log('getProps:opt',opt);
return opt as DrawerProps; return opt as DrawerProps;
}); });

View File

@ -107,7 +107,6 @@
//update-begin-author:taoyan date:2022-6-1 for: VUEN-1144 online //update-begin-author:taoyan date:2022-6-1 for: VUEN-1144 online
function storePathTitle(path) { function storePathTitle(path) {
console.log('storePathTitle', path);
let title = ''; let title = '';
if (instance!.attrs) { if (instance!.attrs) {
let item: any = instance!.attrs.item; let item: any = instance!.attrs.item;

View File

@ -131,5 +131,5 @@ export function registerGlobComp(app: App) {
.use(Cascader) .use(Cascader)
.use(Rate) .use(Rate)
.use(Progress); .use(Progress);
console.log("---初始化--- 全局注册Antd、仪表盘、流程设计器、online、流程等组件--------------") // console.log("---初始化--- 全局注册Antd、仪表盘、流程设计器、online、流程等组件--------------")
} }

View File

@ -28,10 +28,10 @@ export function connectWebSocket(url: string) {
protocols: [token], protocols: [token],
// update-begin--author:liaozhiyang---date:20240726---for[issues/6662] 演示系统socket总断换一个写法 // update-begin--author:liaozhiyang---date:20240726---for[issues/6662] 演示系统socket总断换一个写法
onConnected: function (ws) { onConnected: function (ws) {
console.log('[WebSocket] 连接成功', ws); // console.log('[WebSocket] 连接成功', ws);
}, },
onDisconnected: function (ws, event) { onDisconnected: function (ws, event) {
console.log('[WebSocket] 连接断开:', ws, event); // console.log('[WebSocket] 连接断开:', ws, event);
}, },
onError: function (ws, event) { onError: function (ws, event) {
console.log('[WebSocket] 连接发生错误: ', ws, event); console.log('[WebSocket] 连接发生错误: ', ws, event);
@ -78,11 +78,11 @@ export function connectWebSocket(url: string) {
} }
function onOpen() { function onOpen() {
console.log('[WebSocket] 连接成功'); // console.log('[WebSocket] 连接成功');
} }
function onClose(e) { function onClose(e) {
console.log('[WebSocket] 连接断开:', e); // console.log('[WebSocket] 连接断开:', e);
} }
function onError(e) { function onError(e) {

View File

@ -212,7 +212,7 @@ export const usePermissionStore = defineStore({
// 后台菜单构建 // 后台菜单构建
case PermissionModeEnum.BACK: case PermissionModeEnum.BACK:
const { createMessage, createWarningModal } = useMessage(); const { createMessage, createWarningModal } = useMessage();
console.log(" --- 构建后台路由菜单 --- ") // console.log(" --- 构建后台路由菜单 --- ")
// 菜单加载提示 // 菜单加载提示
// createMessage.loading({ // createMessage.loading({
// content: t('sys.app.menuLoading'), // content: t('sys.app.menuLoading'),

View File

@ -0,0 +1,75 @@
import {BasicColumn} from '/@/components/Table';
import {FormSchema} from '/@/components/Table';
import { rules} from '/@/utils/helper/validator';
import { render } from '/@/utils/common/renderUtils';
import { getWeekMonthQuarterYear } from '/@/utils';
//列表数据
export const baseSxtColumns: BasicColumn[] = [
{
title: '设备序号',
align: "center",
dataIndex: 'deviceIndex',
width: 120,
},
{
title: '设备名称',
align: "center",
dataIndex: 'deviceName'
},
{
title: '设备状态',
align: "center",
dataIndex: 'deviceStatus_dictText',
width: 120,
},
{
title: '设备型号',
align: "center",
dataIndex: 'deviceModel',
width: 220,
},
{
title: 'NUID',
align: "center",
dataIndex: 'nuId',
width: 120,
},
{
title: '操作',
align: "center",
dataIndex: 'action',
width: 120,
},
];
export const checkSxtColumns: BasicColumn[] = [
{
title: '设备序号',
align: "center",
dataIndex: 'deviceIndex',
width: 120,
},
{
title: '设备名称',
align: "center",
dataIndex: 'deviceName'
},
{
title: '设备状态',
align: "center",
dataIndex: 'deviceStatus_dictText',
width: 120,
},
{
title: '设备型号',
align: "center",
dataIndex: 'deviceModel',
width: 220,
},
{
title: '操作',
align: "center",
dataIndex: 'action',
width: 120,
},
];

View File

@ -0,0 +1,179 @@
<template>
<div class="p-2">
<div v-if="activeKey==='1'">
<!--查询区域-->
<div class="jeecg-basic-table-form-container">
<a-form ref="formRef" @keyup.enter.native="searchQuery" :model="queryParam" :label-col="labelCol" :wrapper-col="wrapperCol">
<a-row :gutter="24">
<a-col :lg="6">
<a-form-item name="syncType">
<template #label><span title="机构名称">机构名称</span></template>
<j-dict-select-tag type='list' v-model:value="queryParam.id" dictCode="sys_depart,depart_name,id"
placeholder="请选机构名称" allow-clear />
</a-form-item>
</a-col>
<a-col :xl="6" :lg="7" :md="8" :sm="24">
<span style="float: left; overflow: hidden" class="table-page-search-submitButtons">
<a-button type="primary" preIcon="ant-design:search-outlined" @click="searchQuery">查询</a-button>
<a-button type="primary" preIcon="ant-design:reload-outlined" @click="searchReset" style="margin-left: 8px">重置</a-button>
</span>
</a-col>
</a-row>
</a-form>
</div>
<a-row>
<a-col v-for="(item,index) in orgList" style="padding: 5px" :key="index" :xs="24" :sm="24" :md="12" :lg="12" :xl="8" :xxl="6">
<a-card :title="item.departName"
:class="['card-3d', { 'card-selected': isSelected===item }]"
@mouseenter="item.key"
@mouseleave="item.key"
@click="isSelected = item">
<p>机构编码{{item.orgCode}}</p>
<p>创建时间{{item.createTime}}</p>
<p style="text-align: right"><a-button @click="handleCheckOrg(item)">选择</a-button></p>
</a-card>
</a-col>
</a-row>
</div>
<div v-else-if="activeKey==='2'">
<a-row style="padding:10px;">
<a-col :span="12"><span style="font-size: 18px;">{{orgInfo.departName}} - 物联设备配置</span></a-col>
<a-col :span="12" style="text-align: right"><a-button @click="activeKey = '1'">返回上一页</a-button></a-col>
<a-col v-for="(item,index) in baseList" style="padding: 5px" :key="index" :xs="24" :sm="24" :md="12" :lg="12" :xl="8" :xxl="6">
<a-card :title="`NUID`+item.nuId"
:class="['card-3d', { 'card-selected': isSelected===item }]"
@mouseenter="item.key"
@mouseleave="item.key"
@click="isSelected = item">
<p>单元名称{{item.nuName}}</p>
<p>创建时间{{item.createTime}}</p>
<p>单元类型{{item.areaFlagText}}</p>
<div style="text-align: center;">
<a-badge :count="item.sxtNum">
<a-button type="dashed" size="small" @click="handleSxt(item)" style="margin-left: 10px;">摄像头</a-button>
</a-badge>
<a-badge :count="item.dbNum">
<a-button type="dashed" size="small" @click="handleDb(item)" style="margin-left: 10px;">电表</a-button>
</a-badge>
<a-badge :count="item.sbNum" >
<a-button type="dashed" size="small" @click="handleSb(item)" style="margin-left: 10px;">水表</a-button>
</a-badge>
<a-badge :count="item.wsdjNum" >
<a-button type="dashed" size="small" @click="handleWsd(item)" style="margin-left: 10px;">温湿度</a-button>
</a-badge>
</div>
</a-card>
</a-col>
</a-row>
</div>
<SxtModal ref="sxtModal" @success="handleSuccess"></SxtModal>
</div>
</template>
<script lang="ts" name="ElectricitySyncLog-ElectricitySyncLog" setup>
import { ref, reactive,onMounted } from 'vue';
import { defHttp } from '/@/utils/http/axios';
import JDictSelectTag from '/@/components/Form/src/jeecg/components/JDictSelectTag.vue';
import SxtModal from '/@/views/iot/baseIot/compoents/SxtModal.vue';
const formRef = ref();
const sxtModal = ref();
const queryParam = reactive<any>({});
const activeKey= ref('1');
const orgInfo= ref<any>({});
const orgList= ref<any>([]);
const baseList= ref<any>([]);
const isHover = ref(false);
const isSelected = ref(false);
const labelCol = reactive({
xs:24, sm:4, xl:6, xxl:4
});
const wrapperCol = reactive({
xs: 24, sm: 20,
});
//
function searchQuery() {
defHttp.get({ url: '/sys/sysDepart/listAll', params: queryParam }).then((res) => {
orgList.value = res;
});
}
//
function searchReset() {
queryParam.id = '';
searchQuery();
}
//
function handleSuccess(){
searchQuery();
}
//
function handleCheckOrg(item){
activeKey.value = "2";
orgInfo.value = item;
getBaseList(item);
}
//
function getBaseList(item){
defHttp.get({ url: '/admin/nuBaseInfo/nuBaseInfo/getBaseWlsbList', params: {orgCode:item.orgCode} }).then((res) => {
baseList.value = res;
});
}
//
function handleSxt(item){
console.log("🚀 ~ handleSxt ~ item:", item)
sxtModal.value.init(item);
}
//
function handleDb(item){
console.log("🚀 ~ handleDb ~ item:", item)
}
//
function handleSb(item){
console.log("🚀 ~ handleSb ~ item:", item)
}
//湿
function handleWsd(item){
console.log("🚀 ~ handleWsd ~ item:", item)
}
//
onMounted(() => {
activeKey.value = "1";
searchQuery();
});
</script>
<style lang="less" scoped>
/* 基础卡片样式 */
.card-3d {
border-radius: 8px;
border: 1px solid #f0f0f0; /* 边框增强立体感 */
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
transition: all 0.3s ease;
background: white;
position: relative;
}
/* 鼠标悬停:阴影加深 + 轻微上浮 */
.card-3d:hover {
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.15);
transform: translate(-2px,-2px);
}
/* 选中状态:蓝色边框 + 更明显的阴影 */
.card-3d.card-selected {
box-shadow: 0 8px 24px rgba(24, 144, 255, 0.3);
border: 1px solid #1890ff;
}
/* 选中 + 悬停:阴影更强 */
.card-3d.card-selected.card-hover {
box-shadow: 0 10px 28px rgba(24, 144, 255, 0.4);
transform: translate(-3px,-3px);
}
</style>

View File

@ -0,0 +1,118 @@
<template>
<div class="p-2">
<div style="margin-bottom: 30px;">
<SectionDivider :title="'基础信息'" />
<span class="jcxxClass">NUID{{baseIotInfo.nuId}}</span>
<span class="jcxxClass">护理单元名称{{baseIotInfo.nuName}}</span>
<span class="jcxxClass">护理单元类型{{baseIotInfo.areaFlagText}}</span>
</div>
<SectionDivider :title="'摄像头列表'" />
<a-table :columns="baseSxtColumns" :data-source="dataList.records" :pagination="pageParams" @change="handleTableChange" >
<template #bodyCell="{ column, record }">
<template v-if="column.dataIndex === 'action'">
<span>
<a @click="handleSelect(record)">选择</a>
</span>
</template>
</template>
</a-table>
<SectionDivider :title="'已选择列表'" />
<a-table :columns="checkSxtColumns" :data-source="checkDataList.records" :pagination="false">
<template #bodyCell="{ column, record }">
<template v-if="column.dataIndex === 'action'">
<span>
<a @click="handleUnSelect(record)">移除</a>
</span>
</template>
</template>
</a-table>
</div>
</template>
<script lang="ts" setup>
import { ref, reactive, defineExpose, nextTick, defineProps, computed, onMounted } from 'vue';
import { defHttp } from '/@/utils/http/axios';
import { useMessage } from '/@/hooks/web/useMessage';
import { baseSxtColumns,checkSxtColumns } from '../BaseIot.data';
import { Pagination } from 'ant-design-vue';
const formRef = ref();
const queryParam = reactive<any>({});
const emit = defineEmits(['register', 'ok']);
const { createMessage } = useMessage();
const labelCol = ref<any>({ xs: { span: 24 }, sm: { span: 5 } });
const wrapperCol = ref<any>({ xs: { span: 24 }, sm: { span: 16 } });
const confirmLoading = ref<boolean>(false);
const dataList= ref<any>([]);
const checkDataList= ref<any>([]);
const baseIotInfo= ref<any>({});
const pageParams = ref({ pageNo: 1, pageSize: 10, total: 0, showTotal: (total) => `${total} 条数据` })
/**
* 初始化
*/
function init(record) {
baseIotInfo.value = record;
queryParam.pageNo = 1;
getDataList();
getCheckDataList();
}
/**
* 分页触发方法
*/
function handleTableChange(record){
queryParam.pageNo = record.current;
getDataList();
}
/**
* 获取数据列表
*/
function getDataList() {
queryParam.pageSize = pageParams.value.pageSize;
defHttp.get({ url: '/iot/tplink/cameraInfo/list',params:queryParam }).then((res) => {
dataList.value = res;
pageParams.value.total = res.total;
});
}
/**
* 获取已选的数据列表
*/
function getCheckDataList(){
const params = {nuId:baseIotInfo.value.nuId}
defHttp.get({ url: '/iot/tplink/cameraInfo/list',params }).then((res) => {
checkDataList.value = res;
});
}
function handleSelect(record){
if(checkDataList.value.records.some(item => item.id === record.id)){
createMessage.error('已选择该设备')
}else{
checkDataList.value.records.push(record)
}
}
function handleUnSelect(record){
checkDataList.value.records = checkDataList.value.records.filter(item => item.id !== record.id)
}
/**
* 提交数据
*/
function submitForm() {
}
defineExpose({
init,
submitForm,
});
</script>
<style lang="less" scoped>
.antd-modal-form {
padding: 14px;
}
.jcxxClass{
margin-left: 35px;
}
</style>

View File

@ -0,0 +1,66 @@
<template>
<j-modal :title="title" :width="width" :visible="visible" @ok="handleOk" :okButtonProps="{ class: { 'jee-hidden': disableSubmit } }" @cancel="handleCancel" cancelText="关闭">
<SxtForm ref="registerForm" @ok="submitCallback"></SxtForm>
</j-modal>
</template>
<script lang="ts" setup>
import { ref, nextTick, defineExpose } from 'vue';
import SxtForm from './SxtForm.vue'
import JModal from '/@/components/Modal/src/JModal/JModal.vue';
const title = ref<string>('');
const width = ref<string>('80%');
const visible = ref<boolean>(false);
const disableSubmit = ref<boolean>(false);
const registerForm = ref();
const emit = defineEmits(['register', 'success']);
/**
* 编辑
* @param record
*/
function init(record) {
title.value = '摄像头';
visible.value = true;
nextTick(() => {
registerForm.value.init(record);
});
}
/**
* 确定按钮点击事件
*/
function handleOk() {
registerForm.value.submitForm();
}
/**
* form保存回调事件
*/
function submitCallback() {
handleCancel();
emit('success');
}
/**
* 取消按钮回调事件
*/
function handleCancel() {
visible.value = false;
}
defineExpose({
init,
disableSubmit,
});
</script>
<style lang="less">
/**隐藏样式-modal确定按钮 */
.jee-hidden {
display: none !important;
}
</style>
<style lang="less" scoped></style>