fast(项目-项目信息): 项目详情添加设备分组管理(项目管理员显示),解决设备列表选择组件的单个搜索按回车直接刷新整页和列表多次点击编辑会覆盖项bug

This commit is contained in:
fhysy 2024-12-18 16:01:18 +08:00
parent 2caadcd6c4
commit 3ea7f89b34
7 changed files with 685 additions and 19 deletions

View File

@ -17,7 +17,7 @@ export function getProject(projectId) {
});
}
// 查询项目详细
// 查询项目分组列表
export function getProjectGroupList(query) {
return request({
url: "/iot/group/list",
@ -26,6 +26,60 @@ export function getProjectGroupList(query) {
});
}
// 新增项目分组列表
export function addProjectGroupList(data) {
return request({
url: "/iot/group",
method: "post",
data: data
});
}
// 修改项目分组列表
export function editProjectGroupList(data) {
return request({
url: "/iot/group",
method: "put",
data: data
});
}
// 删除项目分组列表
export function delProjectGroupList(id) {
return request({
url: "/iot/group/" + id ,
method: "delete"
});
}
// 查询项目分组设备列表
export function getProjectGroupDeviceList(query) {
return request({
url: "/iot/group/groupDev",
method: "get",
params: query
});
}
// 分组绑定设备
export function bindProjectGroupDeviceList(data) {
return request({
url: "/iot/group/bind",
method: "post",
data: data
});
}
// 分组解绑设备
export function unbindProjectGroupDeviceList(data) {
return request({
url: "/iot/group/unbind",
method: "post",
data: data
});
}
// 导出项目
export function exportProject(query) {
return request({

View File

@ -4,17 +4,18 @@
<!--用户数据-->
<el-col v-if="queryOption.disable === false" :span="20" :xs="24">
<el-form
:model="params"
ref="queryForm"
:inline="queryOption.inline"
:label-width="queryOption.labelWidth ? queryOption.labelWidth : '100px'"
:model="params"
@submit.native.prevent
>
<el-form-item v-for="item in queryOption.queryChilds" :key="item.key" :label="item.label">
<el-input
v-if="!item.type || item.type === 'input'"
v-model="params[item.key]"
:placeholder="item.placeholder || ''"
:clearable="item.clearable"
:placeholder="item.placeholder || ''"
:size="item.size || 'small'"
:style="item.style || ''"
@keyup.enter.native="handleQuery"
@ -38,7 +39,7 @@
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-search" size="mini" type="primary" @click="handleQuery">搜索</el-button>
<!-- <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button> -->
</el-form-item>
</el-form>
@ -47,42 +48,42 @@
<el-table
v-loading="tableOption.loading"
:data="dataList"
class="select-table"
:height="tableOption.maxHeight"
:highlight-pageNum-row="true"
:row-key="tableOption.rowKey"
:tree-props="tableOption.treeProps"
class="select-table"
default-expand-all
highlight-current-row
:tree-props="tableOption.treeProps"
:row-key="tableOption.rowKey"
@row-click="row_clicks"
@row-dblclick="rowDblclick"
@selection-change="handleSelectionChange"
>
<el-table-column type="index" label="序号" align="center" :index="indexFormatter" width="80px"></el-table-column>
<el-table-column :index="indexFormatter" align="center" label="序号" type="index" width="80px"></el-table-column>
<el-table-column
v-if="tableOption.selection === true"
align="center"
type="selection"
width="50"
align="center"
/>
<el-table-column
v-for="(item, index) in tableOption.childs"
:key="index"
:type="item.type"
:width="item.width"
:align="item.align"
:label="item.label"
:prop="item.prop"
:type="item.type"
:width="item.width"
>
<template slot-scope="scope" v-if="item.tempType !== '' ">
<template v-if="item.tempType !== '' " slot-scope="scope">
<el-switch
v-if="item.tempType === 'switch'"
v-model="scope.row[item.prop]"
:active-value="item.option['active-value']"
:inactive-value="item.option['inactive-value']"
:disable="item.option.disable"
:inactive-value="item.option['inactive-value']"
></el-switch>
<span v-else-if="item.tempType === 'span'">{{scope.row[item.prop]}}</span>
@ -111,9 +112,9 @@
<pagination
v-show="queryOption.page.total > 0"
:total="queryOption.page.total"
:page.sync="queryOption.page.pageNum"
:limit.sync="queryOption.page.pageSize"
:page.sync="queryOption.page.pageNum"
:total="queryOption.page.total"
@pagination="handleQuery"
/>
</el-row>

View File

@ -0,0 +1,280 @@
<!--设备分组-->
<template>
<div class="app-container">
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
icon="el-icon-plus"
plain
size="mini"
type="primary"
@click="handleAdd"
>新增</el-button
>
</el-col>
<right-toolbar
:showSearch.sync="showSearch"
@queryTable="getList"
></right-toolbar>
</el-row>
<el-table
v-loading="loading"
:data="projectGroupList"
row-key="id"
>
<el-table-column
align="center"
label="序号"
type="index"
width="80px"
></el-table-column>
<el-table-column align="center" label="分组名" prop="groupName" >
<template slot-scope="scope">
<span style="color: #0d8afd;cursor: pointer" @click="clickType(scope.row)">{{ scope.row.groupName }}</span>
</template>
</el-table-column>
<el-table-column align="center" label="分组码" prop="groupCode" />
<el-table-column
align="center"
class-name="small-padding fixed-width"
label="操作"
width="200px"
>
<template slot-scope="scope">
<el-button
icon="el-icon-search"
size="mini"
type="text"
@click="handleDetails(scope.row)"
>分组设备</el-button>
<el-button icon="el-icon-edit" size="mini" type="text" @click="handleUpdate(scope.row)">修改</el-button>
<el-button
icon="el-icon-delete"
size="mini"
type="text"
@click="handleDelete(scope.row)"
>删除</el-button>
</template>
</el-table-column>
</el-table>
<el-dialog
:close-on-click-modal="false"
:title="modelTitle"
:visible.sync="modelShow"
append-to-body
class="select-table-dialog"
top="30vh"
width="600px"
>
<el-form ref="form" :model="form" :rules="rules" class="phone-box" label-width="120px">
<el-form-item label="分组名" prop="groupName">
<el-input v-model="form.groupName" placeholder="请输入分组名" />
</el-form-item>
<el-form-item label="分组码" prop="groupCode">
<span slot="label">
分组码
<el-tooltip class="item" content="分组码需要平台已有的" effect="dark"
placement="top">
<i class="el-icon-question"></i>
</el-tooltip>
</span>
<el-input v-model="form.groupCode" placeholder="请输入分组码" />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="() => {modelShow = false;}"> </el-button>
</div>
</el-dialog>
<el-dialog
:append-to-body="true"
:close-on-click-modal="false"
:title="groupDeviceTitle"
:visible.sync="selectTableShow"
class="eldialog-wrap"
top="10vh"
width="75%"
>
<device-group-device
v-if="selectTableShow"
:groupId="activeGroupId"
:infoData="infoData"
:projectId="infoData.projectId"
/>
<div slot="footer" class="dialog-footer">
<el-button size="mini" type="primary" @click="() =>{selectTableShow = false}"> </el-button>
<el-button size="mini" @click="() =>{selectTableShow = false}"> </el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import SelectTableWrap from "@/components/SelectTable/index";
import DeviceGroupDevice from "./DeviceGroupDevice"
import { addTagType, delTagType, listTagType, updateTagType } from "@/api/iot/tagType";
import { addProjectGroupList, delProjectGroupList, getProjectGroupList } from "@/api/tenant/project";
export default {
name: "DeviceGroup",
components: {
SelectTableWrap,
DeviceGroupDevice,
},
props: ["infoData"],
data() {
return {
modelTitle:'',
modelShow: false,
//
loading: true,
//
showSearch: true,
//
total: 0,
//
projectGroupList: [],
//
queryParams: {
},
//
form: {
id: null,
projectId:null,
groupName:null,
groupCode:null,
},
//
rules: {
groupName: [
{ required: true, message: "分组名不能为空", trigger: "blur" },
],
groupCode: [
{ required: true, message: "分组码不能为空", trigger: "blur" },
],
},
selectTableShow:false,
groupDeviceTitle: "",
//id
activeGroupId: "",
};
},
watch: {
infoData: {
handler(newVal) {
if (newVal) {
this.getList();
}
},
deep: true, //
immediate: false, //
},
},
created() {
this.getList();
},
methods: {
/** 查询项目用户关系列表 */
getList() {
this.loading = true;
getProjectGroupList({projectId:this.infoData.projectId}).then((response) => {
this.projectGroupList = response.rows;
this.total = response.total;
this.loading = false;
});
},
clickType(e){
this.$emit("changeTagType", e.labelType)
},
//
cancel() {
this.open = false;
this.reset();
},
//
reset() {
this.form = {
id: null,
projectId: this.infoData.projectId,
groupName:null,
groupCode:null,
};
this.resetForm("form");
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm");
this.handleQuery();
},
//
handleDetails(row) {
this.activeGroupId = row.id;
this.groupDeviceTitle = `[ ${row.groupName} ] 分组--设备管理`;
this.selectTableShow = true;
},
/** 新增按钮操作 */
handleAdd() {
this.reset();
this.modelTitle = '添加设备分组'
this.modelShow = true;
// this.handleDetails();
},
/** 修改按钮操作 */
handleUpdate(row) {
console.log("row",row)
this.reset();
this.form = JSON.parse(JSON.stringify(row));
this.modelTitle = "修改设备分组";
this.modelShow = true;
},
/** 提交按钮 */
submitForm() {
this.$refs["form"].validate(valid => {
if (valid) {
if (this.form.id != null) {
updateTagType({
id: this.form.id,
groupName:this.form.groupName,
}).then(response => {
this.msgSuccess("修改成功");
this.modelShow = false;
this.getList();
});
} else {
addProjectGroupList(this.form).then(response => {
this.msgSuccess("新增成功");
this.modelShow = false;
this.getList();
});
}
}
});
},
/** 删除按钮操作 */
handleDelete(row) {
const id = row.id;
this.$confirm('确认要删除分组(' + row.groupName + ')吗?', "警告", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
})
.then(function () {
return delProjectGroupList(id);
})
.then(() => {
this.getList();
this.msgSuccess("删除成功");
});
},
},
};
</script>

View File

@ -0,0 +1,324 @@
<template>
<div class="app-container">
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button v-if="infoData && infoData.projectRole !== 'personal'" icon="el-icon-plus" plain size="mini" type="primary" @click="handleAdd" >新增设备</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table
v-loading="loading"
:data="deviceList"
:default-sort="{prop: 'createTime', order: 'descending'}"
empty-text="分组下暂无设备"
@sort-change="sortChange"
>
<!-- <el-table-column :index="indexFormatter" align="center" label="序号" type="index" width="80px"></el-table-column>-->
<el-table-column type="index" />
<el-table-column align="left" label="设备key" prop="deviceKey" width="200px" />
<el-table-column align="left" label="设备名称" prop="deviceName" width="200px" />
<el-table-column align="left" label="设备类型" prop="deviceTypeName" width="120px" />
<el-table-column align="center" label="创建时间" prop="createTime" sortable="custom"/>
<el-table-column align="center" class-name="small-padding fixed-width" label="操作" width="150">
<template slot-scope="scope">
<el-button
v-if="scope.row.deviceType !== 'MINIATURE_BREAKER' && infoData && infoData.projectRole !== 'personal'"
v-hasPermi="['iot:label:edit']"
icon="el-icon-delete"
size="mini"
type="text"
@click="handleDelete(scope.row)"
>解绑设备</el-button>
</template>
</el-table-column>
</el-table>
<!-- <pagination-->
<!-- v-show="total>0"-->
<!-- :limit.sync="queryParams.pageSize"-->
<!-- :page.sync="queryParams.pageNum"-->
<!-- :total="total"-->
<!-- @pagination="getList"-->
<!-- />-->
<el-dialog
:close-on-click-modal="false"
:visible.sync="selectTableShow"
append-to-body
class="select-table-dialog"
title="选择设备"
top="10vh"
width="75%"
>
<select-table-wrap
v-if="selectTableShow"
:otherOption="tableSelectOption.otherOption"
:queryOption="tableSelectOption.queryOpt"
:tableList="tableSelectOption.tableList"
:tableOption="tableSelectOption.tableOpt"
@parentGetList="childGetList($event)"
@returnEvent="returnEvent($event)"
/>
<div slot="footer" class="dialog-footer">
<el-button size="mini" type="primary" @click="submitForm(false)"> </el-button>
<el-button size="mini" @click="() =>{selectTableShow = false}"> </el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import SelectTableWrap from "@/components/SelectTable/index";
import DialogTemplate from "@/components/DialogTemplate";
import {
bindProjectGroupDeviceList,
getProjectGroupDeviceList,
unbindProjectGroupDeviceList
} from "@/api/tenant/project";
export default {
name: "DeviceGroupDevice",
props: [ "projectId", "groupId", "infoData"],
components: {
SelectTableWrap,
DialogTemplate
},
data() {
return {
selectTableShow: false,
tableSelectOption: {},
selectResult: {},
//
loading: true,
//
showSearch: true,
//
total: 0,
//
deviceList: [],
//
queryParams: {
groupId: "",
// pageNum: 1,
// pageSize: 10,
orderByColumn: "createTime",
isAsc: "desc"
},
//
form: {},
//
rules: {},
};
},
created() {
this.getList();
},
methods: {
sortChange(column) {
const sort = {
isAsc: column.order === "descending" ? "desc" : "asc",
orderByColumn: column.prop
};
this.queryParams = Object.assign(this.queryParams, sort);
this.handleQuery();
},
indexFormatter(val) {
return (
val + 1 + (this.queryParams.pageNum - 1) * this.queryParams.pageSize
);
},
//
handleDetails() {
this.selectResult = {};
this.tableSelectOption = {
otherOption: {
tableType: "device"
},
queryOpt: {
disable: false,
labelWidth: "68px",
params: {
// deviceName: "",
// pageSize: 10,
// pageNum: 1,
groupId:this.groupId,
contains:false
},
page: {
pageSize: 10,
pageNum: 1,
total: 0
},
inline: true,
queryChilds: [
{
style: "",
placeholder: "请输入设备Key或者设备名称",
clearable: true,
label: "设备名称",
type: "input",
key: "deviceName",
size: "small",
value: ""
}
]
},
tableOpt: {
loading: false,
rowKey: "deviceId",
selection: false,
maxHeight: "45vh",
childs: [
// {
// style: "",
// label: "",
// type: "",
// prop: "modelName",
// align: "left",
// width: "",
// "show-overflow-tooltip": false,
// tempType: "span"
// },
{
style: "",
label: "设备Key",
type: "",
prop: "deviceKey",
align: "left",
width: "",
"show-overflow-tooltip": false,
tempType: "span"
},
{
style: "",
label: "设备名称",
type: "",
prop: "deviceName",
align: "left",
width: "",
"show-overflow-tooltip": false,
tempType: "span"
},
{
style: "",
label: "设备类型",
type: "",
prop: "deviceTypeName",
align: "left",
width: "",
"show-overflow-tooltip": false,
tempType: "span"
},
{
style: "",
label: "创建时间",
type: "time",
prop: "createTime",
align: "center",
width: "180",
"show-overflow-tooltip": false,
tempType: "span"
}
],
tableList: {
type: Array
}
},
tableList: []
};
this.selectTableShow = true;
},
childGetList(data) {
console.log("data.param",data)
getProjectGroupDeviceList(data.param).then(response => {
// this.tableSelectOption.tableList = response.data;
this.tableSelectOption.tableList = response.rows;
// this.tableSelectOption.queryOpt.page.total = Number(response.total);
});
},
returnEvent(data) {
console.log("data",data)
if (data.type === "dblclick") {
this.form.deviceKey = data.value.deviceKey;
this.submitForm(false);
} else if (data.type === "click") {
this.form.deviceKey = data.value.deviceKey;
}
},
/** 查询空间设备列表 */
getList() {
this.loading = true;
this.queryParams.groupId = this.groupId;
getProjectGroupDeviceList(this.queryParams).then(response => {
this.deviceList = response.rows;
this.total = response.total;
this.loading = false;
});
},
//
reset() {
this.form = {
groupId:this.groupId,
deviceKey: null
};
this.resetForm("form");
},
/** 搜索按钮操作 */
handleQuery() {
// this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm");
this.handleQuery();
},
/** 新增按钮操作 */
handleAdd() {
this.reset();
this.handleDetails();
},
/** 提交按钮 */
submitForm(flag=false) {
this.form.force = flag;
bindProjectGroupDeviceList(this.form).then(res => {
if (res.code == 200) {
this.msgSuccess("绑定成功");
this.selectTableShow = false;
this.getList();
}else{
this.msgError(`设备:${this.form.deviceKey}\n${res.msg}`)
}
}).catch(err=>{
if(err == 'Error: 设备已绑定分组'){
this.$confirm(`设备:${this.form.deviceKey}已被绑定设备组,是否强制移动到当前设备组`, "警告", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
.then(()=>{
this.submitForm(true)
})
}
});
},
/** 删除按钮操作 */
handleDelete(row) {
this.$confirm("确认要解绑设备(" + row.deviceName + ")吗?", "警告", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
.then(()=>{
return unbindProjectGroupDeviceList({ deviceKey: row.deviceKey,groupId:this.groupId});
})
.then(() => {
this.getList();
this.msgSuccess("解绑成功");
});
}
}
};
</script>

View File

@ -24,6 +24,10 @@
<el-tab-pane label="标签组" name="tagGroup">
<tag-group v-if="activeName === 'tagGroup'" :activeLabelType="activeLabelType" :infoData="projectInfo || {}"/>
</el-tab-pane>
<el-tab-pane v-if="projectInfo.projectRole== 'root'" label="设备分组" name="deviceGroup">
<device-group v-if="activeName === 'deviceGroup'" :activeLabelType="activeLabelType" :infoData="projectInfo || {}"/>
</el-tab-pane>
</el-tabs>
</div>
</template>
@ -34,6 +38,7 @@ import EObjectSpace from './EObjectSpace'
import EObjectTenant from './EObjectTenant'
import TagGroup from "@/views/iot/project/profileV2/TagGroup";
import TagType from "@/views/iot/project/profileV2/TagType";
import DeviceGroup from "@/views/iot/project/profileV2/DeviceGroup";
export default {
name: 'EObjectContainer',
components: {
@ -42,7 +47,8 @@ export default {
EObjectTenant,
ETenantUser,
TagGroup,
TagType
TagType,
DeviceGroup
},
props: {
projectInfo: {

View File

@ -402,11 +402,12 @@ export default {
},
/** 修改按钮操作 */
handleUpdate(row) {
let data = JSON.parse(JSON.stringify(row))
this.reset();
let labelName = this.statusFormat({labelType:row.labelType})
let labelName = this.statusFormat({labelType:data.labelType})
this.form = {
labelName,
...row
...data
};
this.modelType = 'edit';
this.open = true;

View File

@ -186,7 +186,7 @@ export default {
handleUpdate(row) {
console.log("row",row)
this.reset();
this.form = row;
this.form = JSON.parse(JSON.stringify(row));
this.modelTitle = "修改标签类型";
this.modelShow = true;
},