Quellcode durchsuchen

Add 添加设备维护页面

YueYunyun vor 2 Jahren
Ursprung
Commit
b833d82018

+ 66 - 65
SERVER/IotAdmin/app/iot/apis/group.go

@@ -1,13 +1,14 @@
 package apis
 
 import (
-    "fmt"
+	"fmt"
 
-	"github.com/gin-gonic/gin"
 	"IotAdmin/core/sdk/api"
 	"IotAdmin/core/sdk/pkg/jwt-auth/user"
 	_ "IotAdmin/core/sdk/pkg/response"
 
+	"github.com/gin-gonic/gin"
+
 	"IotAdmin/app/iot/models"
 	"IotAdmin/app/iot/service"
 	"IotAdmin/app/iot/service/dto"
@@ -32,27 +33,27 @@ type IotGroupApi struct {
 // @Router /api/iot-group [get]
 // @Security Bearer
 func (e IotGroupApi) GetPage(c *gin.Context) {
-    req := dto.IotGroupGetPageReq{}
-    s := service.IotGroupService{}
-    err := e.MakeContext(c).
-        MakeOrm().
-        Bind(&req).
-        MakeService(&s.Service).
-        Errors
-   	if err != nil {
-   		e.Logger.Error(err)
-   		e.Error(500, err, err.Error())
-   		return
-   	}
-
-	p :=  permission.GetPermissionFromContext(c)
+	req := dto.IotGroupGetPageReq{}
+	s := service.IotGroupService{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	p := permission.GetPermissionFromContext(c)
 	list := make([]models.IotGroup, 0)
 	var count int64
 
-	err = s.GetPage(&req, p, &list, &count)
+	err = s.GetPage(&req, p, &list)
 	if err != nil {
 		e.Error(500, err, fmt.Sprintf("获取分组失败,\r\n失败信息 %s", err.Error()))
-        return
+		return
 	}
 
 	e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功")
@@ -69,7 +70,7 @@ func (e IotGroupApi) GetPage(c *gin.Context) {
 func (e IotGroupApi) Get(c *gin.Context) {
 	req := dto.IotGroupGetReq{}
 	s := service.IotGroupService{}
-    err := e.MakeContext(c).
+	err := e.MakeContext(c).
 		MakeOrm().
 		Bind(&req).
 		MakeService(&s.Service).
@@ -81,14 +82,14 @@ func (e IotGroupApi) Get(c *gin.Context) {
 	}
 	var object models.IotGroup
 
-	p :=  permission.GetPermissionFromContext(c)
+	p := permission.GetPermissionFromContext(c)
 	err = s.Get(&req, p, &object)
 	if err != nil {
 		e.Error(500, err, fmt.Sprintf("获取分组失败,\r\n失败信息 %s", err.Error()))
-        return
+		return
 	}
 
-	e.OK( object, "查询成功")
+	e.OK(object, "查询成功")
 }
 
 // Insert 添加分组
@@ -102,25 +103,25 @@ func (e IotGroupApi) Get(c *gin.Context) {
 // @Router /api/iot-group [post]
 // @Security Bearer
 func (e IotGroupApi) Insert(c *gin.Context) {
-    req := dto.IotGroupInsertReq{}
-    s := service.IotGroupService{}
-    err := e.MakeContext(c).
-        MakeOrm().
-        Bind(&req).
-        MakeService(&s.Service).
-        Errors
-    if err != nil {
-        e.Logger.Error(err)
-        e.Error(500, err, err.Error())
-        return
-    }
+	req := dto.IotGroupInsertReq{}
+	s := service.IotGroupService{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
 	// 设置创建人
 	req.SetCreateBy(user.GetUserId(c))
 
 	err = s.Insert(&req)
 	if err != nil {
 		e.Error(500, err, fmt.Sprintf("添加分组失败,\r\n失败信息 %s", err.Error()))
-        return
+		return
 	}
 
 	e.OK(req.GetId(), "添加成功")
@@ -138,27 +139,27 @@ func (e IotGroupApi) Insert(c *gin.Context) {
 // @Router /api/iot-group/{id} [put]
 // @Security Bearer
 func (e IotGroupApi) Update(c *gin.Context) {
-    req := dto.IotGroupUpdateReq{}
-    s := service.IotGroupService{}
-    err := e.MakeContext(c).
-        MakeOrm().
-        Bind(&req).
-        MakeService(&s.Service).
-        Errors
-    if err != nil {
-        e.Logger.Error(err)
-        e.Error(500, err, err.Error())
-        return
-    }
+	req := dto.IotGroupUpdateReq{}
+	s := service.IotGroupService{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
 	req.SetUpdateBy(user.GetUserId(c))
-	p :=  permission.GetPermissionFromContext(c)
+	p := permission.GetPermissionFromContext(c)
 
 	err = s.Update(&req, p)
 	if err != nil {
 		e.Error(500, err, fmt.Sprintf("修改分组失败,\r\n失败信息 %s", err.Error()))
-        return
+		return
 	}
-	e.OK( req.GetId(), "修改成功")
+	e.OK(req.GetId(), "修改成功")
 }
 
 // Delete 删除分组
@@ -170,26 +171,26 @@ func (e IotGroupApi) Update(c *gin.Context) {
 // @Router /api/iot-group [delete]
 // @Security Bearer
 func (e IotGroupApi) Delete(c *gin.Context) {
-    s := service.IotGroupService{}
-    req := dto.IotGroupDeleteReq{}
-    err := e.MakeContext(c).
-        MakeOrm().
-        Bind(&req).
-        MakeService(&s.Service).
-        Errors
-    if err != nil {
-        e.Logger.Error(err)
-        e.Error(500, err, err.Error())
-        return
-    }
+	s := service.IotGroupService{}
+	req := dto.IotGroupDeleteReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
 
 	// req.SetUpdateBy(user.GetUserId(c))
-	p :=  permission.GetPermissionFromContext(c)
+	p := permission.GetPermissionFromContext(c)
 
 	err = s.Remove(&req, p)
 	if err != nil {
 		e.Error(500, err, fmt.Sprintf("删除分组失败,\r\n失败信息 %s", err.Error()))
-        return
+		return
 	}
-	e.OK( req.GetId(), "删除成功")
+	e.OK(req.GetId(), "删除成功")
 }

+ 1 - 1
SERVER/IotAdmin/app/iot/models/device.go

@@ -30,7 +30,7 @@ type IotDevice struct {
 	OnlineStatus int                       `json:"onlineStatus" gorm:"type:tinyint(1);comment:在线状态"`
 	TimeOnline   time.Time                 `json:"timeOnline" gorm:"type:datetime;comment:上线时间"`
 	TimeOffline  time.Time                 `json:"timeOffline" gorm:"type:datetime;comment:离线时间"`
-	Group        *IotGroup                 `json:"group"`
+	GroupName    string                    `json:"groupName" `
 	ReportConfig *[]iotStruct.ReportConfig `json:"reportConfigs" gorm:"-"`
 	models.ControlBy
 	models.ModelTime

+ 10 - 11
SERVER/IotAdmin/app/iot/models/group.go

@@ -1,24 +1,23 @@
 package models
 
 import (
-
 	"IotAdmin/common/models"
-
 )
 
 // IotGroup 分组实体
 type IotGroup struct {
-    models.Model
-    ParentId string `json:"parentId" gorm:"type:bigint(20);comment:父ID"` 
-    Path string `json:"path" gorm:"type:varchar(255);comment:分组路径"` 
-    Name string `json:"name" gorm:"type:varchar(255);comment:分组名称"` 
-    Description string `json:"description" gorm:"type:varchar(255);comment:分组描述"` 
-    models.ControlBy
-    models.ModelTime
+	models.Model
+	ParentId    int        `json:"parentId" gorm:"type:bigint(20);comment:父ID"`
+	Path        string     `json:"path" gorm:"type:varchar(255);comment:分组路径"`
+	Name        string     `json:"name" gorm:"type:varchar(255);comment:分组名称"`
+	Description string     `json:"description" gorm:"type:varchar(255);comment:分组描述"`
+	Children    []IotGroup `json:"children,omitempty" gorm:"-"`
+	models.ControlBy
+	models.ModelTime
 }
 
 func (*IotGroup) TableName() string {
-    return "iot_group"
+	return "iot_group"
 }
 
 func (e *IotGroup) Generate() models.ActiveRecord {
@@ -28,4 +27,4 @@ func (e *IotGroup) Generate() models.ActiveRecord {
 
 func (e *IotGroup) GetId() interface{} {
 	return e.Id
-}
+}

+ 2 - 2
SERVER/IotAdmin/app/iot/service/device.go

@@ -32,9 +32,9 @@ func (e *IotDeviceService) GetPage(c *dto.IotDeviceGetPageReq, p *permission.Dat
 		permission.Permission(data.TableName(), p),
 	)
 	if c.Type == constant.IotDeviceTypeGateway {
-		db = db.Preload("Group").Select("id,name,type,group_id,sn,cycle,online_status,time_online,time_offline,created_at")
+		db = db.Joins("left join iot_group as g on g.id=iot_device.group_id").Select("iot_device.id,g.name as group_name,iot_device.name,type,group_id,sn,cycle,online_status,time_online,time_offline,iot_device.created_at")
 	} else {
-		db = db.Select("id,name,type,sn,protocol,address,bm_yz,other_config,created_at")
+		db = db.Select("id,name,type,sn,protocol,mode,address,bm_yz,other_config,created_at")
 	}
 	err = db.Find(list).Limit(-1).Offset(-1).Count(count).Error
 	if err != nil {

+ 1 - 0
SERVER/IotAdmin/app/iot/service/dto/device.go

@@ -12,6 +12,7 @@ import (
 
 type IotDeviceGetPageReq struct {
 	dto.Pagination `search:"-"`
+	Type           int    `form:"type" search:"type:exact;column:type;table:iot_device" comment:"设备类型"`
 	BeginTime      string `form:"beginTime" search:"type:gte;column:created_at;table:iot_device" comment:"创建时间"`
 	EndTime        string `form:"endTime" search:"type:lte;column:created_at;table:iot_device" comment:"创建时间"`
 	IotDeviceOrder

+ 3 - 3
SERVER/IotAdmin/app/iot/service/dto/group.go

@@ -26,7 +26,7 @@ func (m *IotGroupGetPageReq) GetNeedSearch() interface{} {
 // IotGroupInsertReq 添加分组请求参数
 type IotGroupInsertReq struct {
 	Id          int    `json:"-" comment:"Id"` // Id
-	ParentId    string `json:"parentId" comment:"父ID"`
+	ParentId    int    `json:"parentId" comment:"父ID"`
 	Name        string `json:"name" comment:"分组名称"`
 	Description string `json:"description" comment:"分组描述"`
 	comModels.ControlBy
@@ -49,7 +49,7 @@ func (s *IotGroupInsertReq) GetId() interface{} {
 // IotGroupUpdateReq 修改分组请求参数
 type IotGroupUpdateReq struct {
 	Id          int    `uri:"id" comment:"Id"` // Id
-	ParentId    string `json:"parentId" comment:"父ID"`
+	ParentId    int    `json:"parentId" comment:"父ID"`
 	Name        string `json:"name" comment:"分组名称"`
 	Description string `json:"description" comment:"分组描述"`
 	comModels.ControlBy
@@ -90,7 +90,7 @@ func (s *IotGroupDeleteReq) GetId() interface{} {
 // IotGroupResp 获取分组响应参数
 type IotGroupResp struct {
 	Id          int       `uri:"id" comment:"Id"` // Id
-	ParentId    string    `json:"parentId" comment:"父ID"`
+	ParentId    int       `json:"parentId" comment:"父ID"`
 	Name        string    `json:"name" comment:"分组名称"`
 	Description string    `json:"description" comment:"分组描述"`
 	CreateBy    int       `json:"createBy" comment:"创建者"`

+ 113 - 41
SERVER/IotAdmin/app/iot/service/group.go

@@ -1,9 +1,12 @@
 package service
 
 import (
+	"IotAdmin/core/sdk/pkg"
 	"errors"
+	"strings"
+
+	"IotAdmin/core/sdk/service"
 
-    "IotAdmin/core/sdk/service"
 	"gorm.io/gorm"
 
 	"IotAdmin/app/iot/models"
@@ -18,32 +21,57 @@ type IotGroupService struct {
 }
 
 // GetPage 获取分组列表
-func (e *IotGroupService) GetPage(c *dto.IotGroupGetPageReq, p * permission.DataPermission, list *[]models.IotGroup, count *int64) error {
+func (e *IotGroupService) GetPage(c *dto.IotGroupGetPageReq, p *permission.DataPermission, list *[]models.IotGroup) error {
 	var err error
 	var data models.IotGroup
+	var groups = make([]models.IotGroup, 0)
 
-	err = e.Orm.Model(&data).
-		Scopes(
-			cDto.MakeCondition(c.GetNeedSearch()),
-			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
-			 permission.Permission(data.TableName(), p),
-		).
-		Find(list).Limit(-1).Offset(-1).
-		Count(count).Error
+	err = e.Orm.Model(&data).Scopes(
+		cDto.MakeCondition(c.GetNeedSearch()),
+		permission.Permission(data.TableName(), p),
+	).Find(&groups).Error
 	if err != nil {
 		e.Log.Errorf("IotGroupService GetPage error:%s \r\n", err)
 		return err
 	}
+	for _, v := range groups {
+		if v.ParentId != 0 {
+			continue
+		}
+		g := groupCall(&groups, v)
+		*list = append(*list, g)
+	}
 	return nil
 }
+func groupCall(groupList *[]models.IotGroup, group models.IotGroup) models.IotGroup {
+	list := *groupList
+	groups := make([]models.IotGroup, 0)
+	for _, v := range list {
+		if v.ParentId != group.Id {
+			continue
+		}
+		g := &models.IotGroup{
+			ParentId:    v.ParentId,
+			Name:        v.Name,
+			Path:        v.Path,
+			Description: v.Description,
+			Children:    make([]models.IotGroup, 0),
+		}
+		g.Id = v.Id
+		gc := groupCall(groupList, *g)
+		groups = append(groups, gc)
+	}
+	group.Children = groups
+	return group
+}
 
 // Get 获取分组对象
-func (e *IotGroupService) Get(d *dto.IotGroupGetReq, p * permission.DataPermission, model *models.IotGroup) error {
+func (e *IotGroupService) Get(d *dto.IotGroupGetReq, p *permission.DataPermission, model *models.IotGroup) error {
 	var data models.IotGroup
 
 	err := e.Orm.Model(&data).
 		Scopes(
-			 permission.Permission(data.TableName(), p),
+			permission.Permission(data.TableName(), p),
 		).
 		First(model, d.GetId()).Error
 	if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
@@ -60,51 +88,95 @@ func (e *IotGroupService) Get(d *dto.IotGroupGetReq, p * permission.DataPermissi
 
 // Insert 添加分组对象
 func (e *IotGroupService) Insert(c *dto.IotGroupInsertReq) error {
-    var err error
-    var data models.IotGroup
-    c.Generate(&data)
+	var err error
+	var data models.IotGroup
+	c.Generate(&data)
+	tx := e.Orm.Debug().Begin()
+	defer func() {
+		if err != nil {
+			tx.Rollback()
+		} else {
+			tx.Commit()
+		}
+	}()
 	err = e.Orm.Create(&data).Error
 	if err != nil {
 		e.Log.Errorf("IotGroupService Insert error:%s \r\n", err)
 		return err
 	}
-	return nil
+	err = inIitPaths(e.Orm, &data)
+	return err
 }
 
-// Update 修改分组对象
-func (e *IotGroupService) Update(c *dto.IotGroupUpdateReq, p * permission.DataPermission) error {
-    var err error
-    var data = models.IotGroup{}
-    e.Orm.Scopes(
-             permission.Permission(data.TableName(), p),
-        ).First(&data, c.GetId())
-    c.Generate(&data)
+func inIitPaths(tx *gorm.DB, group *models.IotGroup) error {
+	var err error
+	var data models.IotGroup
+	parentGroup := &models.IotGroup{}
+	if group.ParentId != 0 {
+		err = tx.Model(&data).First(parentGroup, group.ParentId).Error
+		if err != nil {
+			return err
+		}
+		if parentGroup.Path == "" {
+			err = errors.New("父级paths异常,请尝试对当前节点父级分组进行更新操作!")
+			return err
+		}
+		group.Path = parentGroup.Path + "/" + pkg.IntToString(group.Id)
+	} else {
+		group.Path = "/0/" + pkg.IntToString(group.Id)
+	}
+	err = tx.Model(&data).Where("id = ?", group.Id).Update("path", group.Path).Error
+	return err
+}
 
-    db := e.Orm.Save(&data)
-    if err = db.Error; err != nil {
-        e.Log.Errorf("IotGroupService Save error:%s \r\n", err)
-        return err
-    }
-    if db.RowsAffected == 0 {
-        return errors.New("无权更新该数据")
-    }
-    return nil
+// Update 修改分组对象
+func (e *IotGroupService) Update(c *dto.IotGroupUpdateReq, p *permission.DataPermission) error {
+	var err error
+	var data = models.IotGroup{}
+	e.Orm.Scopes(
+		permission.Permission(data.TableName(), p),
+	).First(&data, c.GetId())
+	c.Generate(&data)
+	tx := e.Orm.Debug().Begin()
+	defer func() {
+		if err != nil {
+			tx.Rollback()
+		} else {
+			tx.Commit()
+		}
+	}()
+	db := e.Orm.Save(&data)
+	if err = db.Error; err != nil {
+		e.Log.Errorf("IotGroupService Save error:%s \r\n", err)
+		return err
+	}
+	oldPath := data.Path
+	if db.RowsAffected == 0 {
+		return errors.New("无权更新该数据")
+	}
+	var groupList []models.IotGroup
+	tx.Where("path like ?", oldPath+"%").Find(&groupList)
+	for _, v := range groupList {
+		v.Path = strings.Replace(v.Path, oldPath, data.Path, 1)
+		tx.Model(&v).Update("path", v.Path)
+	}
+	return nil
 }
 
 // Remove 删除分组
-func (e *IotGroupService) Remove(d *dto.IotGroupDeleteReq, p * permission.DataPermission) error {
+func (e *IotGroupService) Remove(d *dto.IotGroupDeleteReq, p *permission.DataPermission) error {
 	var data models.IotGroup
 
 	db := e.Orm.Model(&data).
 		Scopes(
-			 permission.Permission(data.TableName(), p),
+			permission.Permission(data.TableName(), p),
 		).Delete(&data, d.GetId())
 	if err := db.Error; err != nil {
-        e.Log.Errorf("Service RemoveIotGroup error:%s \r\n", err)
-        return err
-    }
-    if db.RowsAffected == 0 {
-        return errors.New("无权删除该数据")
-    }
+		e.Log.Errorf("Service RemoveIotGroup error:%s \r\n", err)
+		return err
+	}
+	if db.RowsAffected == 0 {
+		return errors.New("无权删除该数据")
+	}
 	return nil
 }

+ 2 - 2
SERVER/IotAdmin/app/system/apis/sys_org.go

@@ -201,9 +201,9 @@ func (e SysOrgApi) Get2Tree(c *gin.Context) {
 		e.Error(500, err, err.Error())
 		return
 	}
-	//p := permission.GetPermissionFromContext(c)
+	p := permission.GetPermissionFromContext(c)
 	list := make([]dto.OrgLabel, 0)
-	list, err = s.SetOrgTree(&req)
+	list, err = s.SetOrgTree(&req, p)
 	if err != nil {
 		e.Error(500, err, "查询失败")
 		return

+ 7 - 5
SERVER/IotAdmin/app/system/service/sys_org.go

@@ -164,10 +164,12 @@ func (e *SysOrgService) getList(c *dto.SysOrgGetPageReq, list *[]models.SysOrg,
 }
 
 // SetOrgTree 设置组织数据
-func (e *SysOrgService) SetOrgTree(c *dto.SysOrgGetReq) (m []dto.OrgLabel, err error) {
+func (e *SysOrgService) SetOrgTree(c *dto.SysOrgGetReq, p *permission.DataPermission) (m []dto.OrgLabel, err error) {
 	var list []models.SysOrg
 	var data models.SysOrg
-	err = e.Orm.Model(&data).Where("org_id = ? or parent_id = ? ", c.GetId(), c.GetId()).Find(&list).Error
+	err = e.Orm.Model(&data).Scopes(
+		permission.Permission(data.TableName(), p),
+	).Where("status = ?", 2).Where("org_id = ? or parent_id = ? ", c.GetId(), c.GetId()).Find(&list).Error
 	if err != nil {
 		e.Log.Errorf("db error:%s", err)
 		return
@@ -175,9 +177,9 @@ func (e *SysOrgService) SetOrgTree(c *dto.SysOrgGetReq) (m []dto.OrgLabel, err e
 
 	m = make([]dto.OrgLabel, 0)
 	for i := 0; i < len(list); i++ {
-		//if list[i].ParentId != 0 {
-		//	continue
-		//}
+		if list[i].ParentId != 0 {
+			continue
+		}
 		e := dto.OrgLabel{}
 		e.Id = list[i].OrgId
 		e.Label = list[i].OrgName

+ 10 - 8
SERVER/IotAdmin/config/sql/db.sql

@@ -311,11 +311,7 @@ INSERT INTO sys_api VALUES  (221,'','生成菜单及接口','/api/sys/gen-menu-a
 INSERT INTO sys_config VALUES (1, '初始密码', 'sys_user_initPassword', '123456', 'Y', '0', '用户管理-账号初始密码:123456', 1, 1, '2024-03-14 00:00:00.000', '2024-03-14 00:00:00.000', NULL);
 INSERT INTO sys_config VALUES (2, '系统名称', 'sys_app_name', 'go-admin管理系统', 'Y', '1', '', 1, 0, '2024-03-14 00:00:00.000', '2024-03-14 00:00:00.000', NULL);
 
-INSERT INTO sys_org VALUES (1, 0, '/0/1/', '中科轼峰', 0, 'aituo', '13782218188', 'atuo@aituo.com', '2', 1, 1, '2024-03-14 00:00:00.000', '2024-03-14 00:00:00.000', NULL);
-INSERT INTO sys_org VALUES (2, 1, '/0/1/2/', '研发部', 1, 'aituo', '13782218188', 'atuo@aituo.com', '2', 1, 1, '2024-03-14 00:00:00.000', '2024-03-14 00:00:00.000', NULL);
-INSERT INTO sys_org VALUES (3, 1, '/0/1/3/', '运维部', 2, 'aituo', '13782218188', 'atuo@aituo.com', '2', 1, 1, '2024-03-14 00:00:00.000', '2024-03-14 00:00:00.000', NULL);
-INSERT INTO sys_org VALUES (4, 1, '/0/1/4/', '客服部', 3, 'aituo', '13782218188', 'atuo@aituo.com', '2', 1, 1, '2024-03-14 00:00:00.000', '2024-03-14 00:00:00.000', NULL);
-INSERT INTO sys_org VALUES (5, 1, '/0/1/5/', '人力资源', 4, 'aituo', '13782218188', 'atuo@aituo.com', '1', 1, 1, '2024-03-14 00:00:00.000', '2024-03-14 00:00:00.000', NULL);
+
 
 INSERT INTO sys_dict_type VALUES (1, '系统开关', 'sys_normal_disable', '2', '系统开关列表', 1, 1, '2024-03-14 00:00:00.000', '2024-03-14 00:00:00.000', NULL);
 INSERT INTO sys_dict_data VALUES (1, 0, '正常', '2', 'sys_normal_disable', '', 'primary', '', '2', '', '系统正常', 1, 1, '2024-03-14 00:00:00.000', '2024-03-14 00:00:00.000', NULL);
@@ -387,9 +383,15 @@ INSERT INTO sys_job VALUES (1, '接口测试', 'SYSTEM', 1, '0/5 * * * * ', 'htt
 INSERT INTO sys_job VALUES (2, '函数测试', 'SYSTEM', 2, '0/5 * * * * ', 'ExamplesOne', '参数', 1, 1, 1, 0, 1, 1, '2024-03-14 00:00:00.000', '2024-03-14 00:00:00.000', NULL);
 
 
-INSERT INTO sys_post VALUES (1, '首席执行官', 'CEO', 0, '2','首席执行官', 1, 1, '2024-03-14 00:00:00.000', '2024-03-14 00:00:00.000', NULL);
-INSERT INTO sys_post VALUES (2, '首席技术执行官', 'CTO', 2, '2','首席技术执行官', 1, 1,'2024-03-14 00:00:00.000', '2024-03-14 00:00:00.000', NULL);
-INSERT INTO sys_post VALUES (3, '首席运营官', 'COO', 3, '2','测试工程师', 1, 1,'2024-03-14 00:00:00.000', '2024-03-14 00:00:00.000', NULL);
+INSERT INTO sys_post VALUES (1, '默认岗位', 'CEO', 0, '2','默认岗位', 1, 1, '2024-03-14 00:00:00.000', '2024-03-14 00:00:00.000', NULL);
+# INSERT INTO sys_post VALUES (2, '首席技术执行官', 'CTO', 2, '2','首席技术执行官', 1, 1,'2024-03-14 00:00:00.000', '2024-03-14 00:00:00.000', NULL);
+# INSERT INTO sys_post VALUES (3, '首席运营官', 'COO', 3, '2','测试工程师', 1, 1,'2024-03-14 00:00:00.000', '2024-03-14 00:00:00.000', NULL);
+
+INSERT INTO sys_org VALUES (1, 0, '/0/1/', '物联网设备管理平台', 0, 'aituo', '13782218188', 'atuo@aituo.com', '2', 1, 1, '2024-03-14 00:00:00.000', '2024-03-14 00:00:00.000', NULL);
+INSERT INTO sys_org VALUES (2, 1, '/0/1/2/', '中科轼峰设备管理平台', 1, 'aituo', '13782218188', 'atuo@aituo.com', '2', 1, 1, '2024-03-14 00:00:00.000', '2024-03-14 00:00:00.000', NULL);
+INSERT INTO sys_org VALUES (3, 1, '/0/1/3/', '测试平台', 2, 'aituo', '13782218188', 'atuo@aituo.com', '2', 1, 1, '2024-03-14 00:00:00.000', '2024-03-14 00:00:00.000', NULL);
+INSERT INTO sys_org VALUES (4, 1, '/0/1/4/', '测试平台2', 3, 'aituo', '13782218188', 'atuo@aituo.com', '2', 1, 1, '2024-03-14 00:00:00.000', '2024-03-14 00:00:00.000', NULL);
+INSERT INTO sys_org VALUES (5, 1, '/0/1/5/', '测试平台3', 4, 'aituo', '13782218188', 'atuo@aituo.com', '1', 1, 1, '2024-03-14 00:00:00.000', '2024-03-14 00:00:00.000', NULL);
 
 INSERT INTO sys_role VALUES (1, '超级管理员', '2', 'admin', 1, 'static', '超级管理员,不可删除修改', true, '1', 1, 1, '2024-03-14 00:00:00.000', '2024-03-14 00:00:00.000', NULL);
 INSERT INTO sys_role VALUES (2, '默认角色', '2', 'default', 2, 'static', '默认角色,不可删除修改', true, '4', 1, 1, '2024-03-14 00:00:00.000', '2024-03-14 00:00:00.000', NULL);

+ 341 - 0
UI/IOTADMIN.VUE/src/views/iot/device/_gateway.vue

@@ -0,0 +1,341 @@
+<script setup lang="ts" name="Device">
+import apis from "@a"
+import message from "@@/utils/message"
+import dayjs from "dayjs"
+const emits = defineEmits<{ (e: "change", v: number): void }>()
+const groupIdOptions = ref<any[]>([])
+const protocolOptions = computed(() => {
+	return [
+		{ label: "请选择", value: "" },
+		{ label: "", value: "" }
+	]
+})
+const onlineStatusOptions = computed(() => {
+	return [
+		{ label: "在线", value: 1, class: "success" },
+		{ label: "离线", value: 2, class: "danger" }
+	]
+})
+
+const tableRef = ref()
+const modalRef = ref()
+const opts = reactive<any>({
+	columns: [
+		{ field: "id", name: "ID", width: 100, visible: false, isSort: false, tooltip: true },
+		{ field: "groupName", name: "设备分组", width: "auto", isSort: true, visible: true },
+		{ field: "sn", name: "设备编码", width: "auto", isSort: true, visible: true },
+		{ field: "name", name: "设备名称", width: "auto", isSort: true, visible: true },
+		{ field: "type", name: "设备类型", width: 80, isSort: false, visible: true },
+		{ field: "cycle", name: "上报周期(分钟)", width: 120, isSort: false, visible: true },
+		{ field: "onlineStatus", name: "在线状态", width: 100, isSort: true, visible: true },
+		{ field: "timeOnline", name: "上线时间", width: 155, isSort: true, visible: true },
+		{ field: "timeOffline", name: "离线时间", width: 155, isSort: true, visible: true },
+		{ field: "createdAt", name: "创建时间", width: 155, isSort: true, visible: true },
+		{ field: "actions", name: `操作`, width: 150 }
+	],
+	queryParams: {
+		groupId: undefined,
+		sn: undefined,
+		name: undefined,
+		type: 1
+	},
+	searchFormItems: [
+		{
+			field: "groupId",
+			label: "分组ID",
+			class: "w-100",
+			component: "VS",
+			data: () => groupIdOptions.value,
+			props: {
+				type: "select",
+				clearable: true,
+				placeholder: "请选择分组ID",
+				props: {
+					label: "name",
+					value: "id"
+				}
+			}
+		},
+		{
+			field: "sn",
+			label: "设备编码",
+			class: "w-100",
+			component: "I",
+			listeners: {
+				keyup: (e: any) => {
+					if (e.code == "Enter") {
+						handleQuery()
+					}
+				}
+			}
+		},
+		{
+			field: "name",
+			label: "设备名称",
+			class: "w-100",
+			component: "I",
+			listeners: {
+				keyup: (e: any) => {
+					if (e.code == "Enter") {
+						handleQuery()
+					}
+				}
+			}
+		}
+	] as any,
+	permission: "iot:device",
+	handleFuns: {},
+	customBtns: [],
+	tableListFun: apis.iot.deviceApi.listDevice,
+	getEntityFun: apis.iot.deviceApi.getDevice,
+	deleteEntityFun: apis.iot.deviceApi.delDevice,
+	formItems: [
+		{
+			field: "parentId",
+			label: "父分组",
+			class: "w-100",
+			component: "I",
+			type: "number",
+			required: false
+		},
+		{
+			field: "groupId",
+			label: "设备分组",
+			class: "w-100",
+			required: true,
+			component: "VS",
+			data: () => groupIdOptions.value,
+			props: {
+				type: "select",
+				valueIsNumber: true,
+				clearable: true,
+				placeholder: "请选择分组",
+				props: {
+					label: "name",
+					value: "id"
+				}
+			}
+		},
+		{
+			field: "sn",
+			label: "设备编码",
+			class: "w-100",
+			component: "I",
+			required: true
+		},
+		{
+			field: "name",
+			label: "设备名称",
+			class: "w-100",
+			component: "I",
+			required: true
+		},
+		{
+			field: "type",
+			label: "设备类型",
+			class: "w-100",
+			required: true,
+			component: "Dict",
+			props: {
+				type: "radio",
+				valueIsNumber: true,
+				clearable: true,
+				placeholder: "请选择设备类型",
+				dictType: "iot_device_type"
+			}
+		},
+		{
+			field: "mode",
+			label: "设备模式",
+			class: "w-100",
+			required: false,
+			component: "Dict",
+			props: {
+				type: "radio",
+				valueIsNumber: true,
+				clearable: true,
+				placeholder: "请选择设备模式",
+				dictType: "iot_device_mode"
+			}
+		},
+		{
+			field: "cycle",
+			label: "上报周期",
+			class: "w-100",
+			component: "I",
+			type: "number",
+			required: true
+		},
+		{
+			field: "description",
+			label: "设备描述",
+			class: "w-100",
+			component: "I",
+			required: false
+		},
+		{
+			field: "protocol",
+			label: "表计协议",
+			class: "w-100",
+			required: false,
+			component: "VS",
+			placeholder: "请选择表计协议",
+			data: () => protocolOptions.value,
+			props: {
+				type: "select",
+				clearable: true
+			}
+		},
+		{
+			field: "address",
+			label: "表计地址",
+			class: "w-100",
+			component: "I",
+			type: "number",
+			required: true
+		}
+	] as any,
+	resetForm: () => {
+		form.value = emptyFormData.value
+	},
+	emptyFormData: {
+		id: undefined,
+		parentId: undefined,
+		groupId: undefined,
+		sn: undefined,
+		name: undefined,
+		type: undefined,
+		mode: undefined,
+		cycle: undefined,
+		description: undefined,
+		protocol: undefined,
+		address: undefined
+	}
+})
+const { queryParams, emptyFormData } = toRefs(opts)
+const form = ref<any>(emptyFormData.value)
+
+/** 修改按钮操作 */
+function handleUpdate(row: any) {
+	tableRef.value.defaultHandleFuns.handleUpdate("", row)
+}
+/** 删除按钮操作 */
+function handleDelete(rows: any[]) {
+	tableRef.value.defaultHandleFuns.handleDelete("", rows)
+}
+/** 提交按钮 */
+function submitForm() {
+	if (form.value.id != undefined) {
+		apis.iot.deviceApi.updateDevice(form.value).then(() => {
+			message.msgSuccess("修改成功")
+			handleQuery()
+		})
+	} else {
+		apis.iot.deviceApi.addDevice(form.value).then(() => {
+			message.msgSuccess("新增成功")
+			handleQuery()
+		})
+	}
+}
+/** 查询按钮 */
+function handleQuery() {
+	addDateRange(queryParams.value, queryParams.value.dateRange)
+	tableRef.value?.search()
+}
+/** 查询重置按钮 */
+function resetQuery() {
+	queryParams.value.dateRange = []
+	addDateRange(queryParams.value, queryParams.value.dateRange)
+}
+
+function init() {
+	apis.iot.groupApi.listGroup({ pageSize: 10000, pageIndex: 1 }).then((res) => {
+		groupIdOptions.value = res.data.rows
+	})
+}
+function onRowClick(row: any) {
+	emits("change", row.id)
+}
+onMounted(init)
+</script>
+
+<template>
+	<div class="w-100 h-100">
+		<VbDataTable
+			ref="tableRef"
+			style="height: 100%"
+			:handle-perm="opts.permission"
+			:handle-funs="opts.handleFuns"
+			:search-form-items="opts.searchFormItems"
+			:columns="opts.columns"
+			:custom-btns="opts.customBtns"
+			:remote-fun="opts.tableListFun"
+			:get-entity-fun="opts.getEntityFun"
+			:delete-entity-fun="opts.deleteEntityFun"
+			:page-size="10"
+			:page-size-array="[10, 25, 50]"
+			sortField="createdAt"
+			sort-order="desc"
+			:modal="modalRef"
+			:reset-form-fun="opts.resetForm"
+			v-model:form-data="form"
+			:query-params="queryParams"
+			:check-multiple="true"
+			:has-checkbox="true"
+			:row-click="onRowClick"
+			:reset-search-form-fun="resetQuery"
+			:custom-search-fun="handleQuery">
+			<template #type="{ row }">
+				<DictTag valueIsNumber :value="row.type" type="iot_device_type"></DictTag>
+			</template>
+			<template #mode="{ row }">
+				<DictTag valueIsNumber :value="row.mode" type="iot_device_mode"></DictTag>
+			</template>
+			<template #onlineStatus="{ row }">
+				<VbTag valueIsNumber :value="row.onlineStatus" :data="onlineStatusOptions"></VbTag>
+			</template>
+			<template #timeOnline="{ row }">
+				<span>{{ row.timeOnline ? "" : dayjs(row.timeOnline).format("YYYY-MM-DD HH:mm:ss") }}</span>
+			</template>
+			<template #timeOffline="{ row }">
+				<span>
+					{{ row.timeOffline ? "" : dayjs(row.timeOffline).format("YYYY-MM-DD HH:mm:ss") }}
+				</span>
+			</template>
+			<template #createdAt="{ row }">
+				<span>{{ dayjs(row.createdAt).format("YYYY-MM-DD HH:mm:ss") }}</span>
+			</template>
+			<template #actions="{ row }">
+				<vb-tooltip content="修改" placement="top">
+					<el-button
+						link
+						type="primary"
+						@click="handleUpdate(row)"
+						v-hasPermission="'iot:device:edit'">
+						<template #icon>
+							<VbIcon icon-name="notepad-edit" icon-type="duotone" class="fs-3"></VbIcon>
+						</template>
+					</el-button>
+				</vb-tooltip>
+				<vb-tooltip content="删除" placement="top">
+					<el-button
+						link
+						type="primary"
+						@click="handleDelete([row])"
+						v-hasPermission="'iot:device:remove'">
+						<template #icon>
+							<VbIcon icon-name="trash-square" icon-type="duotone" class="fs-3"></VbIcon>
+						</template>
+					</el-button>
+				</vb-tooltip>
+			</template>
+		</VbDataTable>
+		<VbModal
+			v-model:modal="modalRef"
+			:title="opts.modalTitle"
+			:form-items="opts.formItems as any"
+			:form-data="form"
+			@confirm="submitForm"
+			append-to-body></VbModal>
+	</div>
+</template>

+ 348 - 0
UI/IOTADMIN.VUE/src/views/iot/device/_meter.vue

@@ -0,0 +1,348 @@
+<script setup lang="ts" name="Device">
+import apis from "@a"
+import message from "@@/utils/message"
+import dayjs from "dayjs"
+
+const props = withDefaults(defineProps<{ id: number }>(), { id: 0 })
+
+const groupIdOptions = ref<any[]>([])
+const protocolOptions = computed(() => {
+	return [
+		{ label: "请选择", value: "" },
+		{ label: "", value: "" }
+	]
+})
+
+const tableRef = ref()
+const modalRef = ref()
+const opts = reactive<any>({
+	columns: [
+		{ field: "id", name: "ID", width: 100, visible: false, isSort: false, tooltip: true },
+		{ field: "sn", name: "设备编码", width: "auto", isSort: true, visible: true },
+		{ field: "name", name: "设备名称", width: "auto", isSort: true, visible: true },
+		{ field: "type", name: "设备类型", width: 100, isSort: true, visible: true },
+		{ field: "mode", name: "设备模式", width: 180, isSort: false, visible: true },
+		{ field: "createdAt", name: "创建时间", width: 185, isSort: true, visible: true },
+		{ field: "actions", name: `操作`, width: 150 }
+	],
+	queryParams: {
+		sn: undefined,
+		name: undefined,
+		type: 2,
+		dateRange: []
+	},
+	searchFormItems: [
+		{
+			field: "sn",
+			label: "设备编码",
+			class: "w-100",
+			component: "I",
+			listeners: {
+				keyup: (e: any) => {
+					if (e.code == "Enter") {
+						handleQuery()
+					}
+				}
+			}
+		},
+		{
+			field: "name",
+			label: "设备名称",
+			class: "w-100",
+			component: "I",
+			listeners: {
+				keyup: (e: any) => {
+					if (e.code == "Enter") {
+						handleQuery()
+					}
+				}
+			}
+		},
+		{
+			field: "type",
+			label: "设备类型",
+			class: "w-100",
+			component: "Dict",
+			props: {
+				type: "radio",
+				placeholder: "请选择设备类型",
+				dictType: "iot_device_type",
+				valueIsNumber: true
+			}
+		},
+		{
+			field: "dateRange",
+			label: "创建时间",
+			class: "w-100",
+			component: "D",
+			placeholder: "请选择创建时间",
+			props: {
+				type: "daterange",
+				valueFormat: "YYYY-MM-DD",
+				rangeSeparator: "-",
+				startPlaceholder: "开始日期",
+				endPlaceholder: "结束日期"
+			},
+			listeners: {
+				change: (v: any) => {
+					queryParams.value.dateRange = v
+				}
+			}
+		}
+	] as any,
+	permission: "iot:device",
+	handleFuns: {},
+	customBtns: [],
+	tableListFun: apis.iot.deviceApi.listDevice,
+	getEntityFun: apis.iot.deviceApi.getDevice,
+	deleteEntityFun: apis.iot.deviceApi.delDevice,
+	formItems: [
+		{
+			field: "parentId",
+			label: "父分组",
+			class: "w-100",
+			component: "I",
+			type: "number",
+			required: false
+		},
+		{
+			field: "groupId",
+			label: "设备分组",
+			class: "w-100",
+			required: true,
+			component: "VS",
+			data: () => groupIdOptions.value,
+			props: {
+				type: "select",
+				valueIsNumber: true,
+				clearable: true,
+				placeholder: "请选择分组",
+				props: {
+					label: "name",
+					value: "id"
+				}
+			}
+		},
+		{
+			field: "sn",
+			label: "设备编码",
+			class: "w-100",
+			component: "I",
+			required: true
+		},
+		{
+			field: "name",
+			label: "设备名称",
+			class: "w-100",
+			component: "I",
+			required: true
+		},
+		{
+			field: "type",
+			label: "设备类型",
+			class: "w-100",
+			required: true,
+			component: "Dict",
+			props: {
+				type: "radio",
+				valueIsNumber: true,
+				clearable: true,
+				placeholder: "请选择设备类型",
+				dictType: "iot_device_type"
+			}
+		},
+		{
+			field: "mode",
+			label: "设备模式",
+			class: "w-100",
+			required: false,
+			component: "Dict",
+			props: {
+				type: "radio",
+				valueIsNumber: true,
+				clearable: true,
+				placeholder: "请选择设备模式",
+				dictType: "iot_device_mode"
+			}
+		},
+		{
+			field: "cycle",
+			label: "上报周期",
+			class: "w-100",
+			component: "I",
+			type: "number",
+			required: true
+		},
+		{
+			field: "description",
+			label: "设备描述",
+			class: "w-100",
+			component: "I",
+			required: false
+		},
+		{
+			field: "protocol",
+			label: "表计协议",
+			class: "w-100",
+			required: false,
+			component: "VS",
+			placeholder: "请选择表计协议",
+			data: () => protocolOptions.value,
+			props: {
+				type: "select",
+				clearable: true
+			}
+		},
+		{
+			field: "address",
+			label: "表计地址",
+			class: "w-100",
+			component: "I",
+			type: "number",
+			required: true
+		}
+	] as any,
+	resetForm: () => {
+		form.value = emptyFormData.value
+	},
+	emptyFormData: {
+		id: undefined,
+		parentId: undefined,
+		groupId: undefined,
+		sn: undefined,
+		name: undefined,
+		type: undefined,
+		mode: undefined,
+		cycle: undefined,
+		description: undefined,
+		protocol: undefined,
+		address: undefined
+	}
+})
+const { queryParams, emptyFormData } = toRefs(opts)
+const form = ref<any>(emptyFormData.value)
+
+/** 修改按钮操作 */
+function handleUpdate(row: any) {
+	tableRef.value.defaultHandleFuns.handleUpdate("", row)
+}
+/** 删除按钮操作 */
+function handleDelete(rows: any[]) {
+	tableRef.value.defaultHandleFuns.handleDelete("", rows)
+}
+/** 提交按钮 */
+function submitForm() {
+	if (form.value.id != undefined) {
+		apis.iot.deviceApi.updateDevice(form.value).then(() => {
+			message.msgSuccess("修改成功")
+			handleQuery()
+		})
+	} else {
+		apis.iot.deviceApi.addDevice(form.value).then(() => {
+			message.msgSuccess("新增成功")
+			handleQuery()
+		})
+	}
+}
+/** 查询按钮 */
+function handleQuery() {
+	addDateRange(queryParams.value, queryParams.value.dateRange)
+	tableRef.value?.search()
+}
+/** 查询重置按钮 */
+function resetQuery() {
+	queryParams.value.dateRange = []
+	addDateRange(queryParams.value, queryParams.value.dateRange)
+}
+
+function init() {
+	apis.iot.groupApi.listGroup({ pageSize: 10000, pageIndex: 1 }).then((res) => {
+		groupIdOptions.value = res.data.rows
+	})
+}
+
+onMounted(init)
+watch(
+	() => props.id,
+	(val: any) => {
+		queryParams.value.parentId = val
+		handleQuery()
+	}
+)
+</script>
+
+<template>
+	<div class="w-100 h-100">
+		<VbDataTable
+			ref="tableRef"
+			style="height: 100%"
+			:init-search="false"
+			:show-right-toolbar="false"
+			:show-search-bar="false"
+			:show-toolbar="false"
+			:page-size="5"
+			:page-size-array="[5, 10, 25]"
+			:handle-perm="opts.permission"
+			:handle-funs="opts.handleFuns"
+			:search-form-items="opts.searchFormItems"
+			:columns="opts.columns"
+			:custom-btns="opts.customBtns"
+			:remote-fun="opts.tableListFun"
+			:get-entity-fun="opts.getEntityFun"
+			:delete-entity-fun="opts.deleteEntityFun"
+			sortField="createdAt"
+			sort-order="desc"
+			:modal="modalRef"
+			:reset-form-fun="opts.resetForm"
+			v-model:form-data="form"
+			:query-params="queryParams"
+			:check-multiple="true"
+			:has-checkbox="true"
+			:reset-search-form-fun="resetQuery"
+			:custom-search-fun="handleQuery">
+			<template #groupId="{ row }">
+				{{ row.group?.Name }}
+			</template>
+			<template #type="{ row }">
+				<DictTag valueIsNumber :value="row.type" type="iot_device_type"></DictTag>
+			</template>
+			<template #mode="{ row }">
+				<DictTag valueIsNumber :value="row.mode" type="iot_device_mode"></DictTag>
+			</template>
+			<template #createdAt="{ row }">
+				<span>{{ dayjs(row.createdAt).format("YYYY-MM-DD HH:mm:ss") }}</span>
+			</template>
+			<template #actions="{ row }">
+				<vb-tooltip content="修改" placement="top">
+					<el-button
+						link
+						type="primary"
+						@click="handleUpdate(row)"
+						v-hasPermission="'iot:device:edit'">
+						<template #icon>
+							<VbIcon icon-name="notepad-edit" icon-type="duotone" class="fs-3"></VbIcon>
+						</template>
+					</el-button>
+				</vb-tooltip>
+				<vb-tooltip content="删除" placement="top">
+					<el-button
+						link
+						type="primary"
+						@click="handleDelete([row])"
+						v-hasPermission="'iot:device:remove'">
+						<template #icon>
+							<VbIcon icon-name="trash-square" icon-type="duotone" class="fs-3"></VbIcon>
+						</template>
+					</el-button>
+				</vb-tooltip>
+			</template>
+		</VbDataTable>
+		<VbModal
+			v-model:modal="modalRef"
+			:title="opts.modalTitle"
+			:form-items="opts.formItems as any"
+			:form-data="form"
+			@confirm="submitForm"
+			append-to-body></VbModal>
+	</div>
+</template>

+ 14 - 345
UI/IOTADMIN.VUE/src/views/iot/device/index.vue

@@ -1,353 +1,22 @@
-
 <script setup lang="ts" name="Device">
-import apis from "@a"
-import message from "@@/utils/message"
-import dayjs from "dayjs"
-
-
-const groupIdOptions = ref<any[]>([])
-const protocolOptions = computed(() => {
-    return [
-        { label: "请选择", value: "" },
-        { label: "", value: "" }
-    ]
-})
-
-const tableRef = ref()
-const modalRef = ref()
-const opts = reactive<any>({
-    columns: [
-        { field: "id", name: "ID", width: 100, visible: false, isSort: false, tooltip: true},
-        { field: "groupId", name: "分组ID", width: "auto", isSort: true, visible: true},
-        { field: "sn", name: "设备编码", width: "auto", isSort: true, visible: true},
-        { field: "name", name: "设备名称", width: "auto", isSort: true, visible: true},
-        { field: "type", name: "设备类型 1:网关 2:表计", width: 100, isSort: true, visible: true},
-        { field: "mode", name: "设备模式 1:下发指令查询 2:表计主动上报", width: 100, isSort: false, visible: true},
-        { field: "cycle", name: "上报周期", width: "auto", isSort: false, visible: true},
-        { field: "createdAt", name: "创建时间", width: 185, isSort: true, visible: true},
-        { field: "actions", name: `操作`, width: 150 }
-    ],
-    queryParams: {
-        groupId: undefined,
-        sn: undefined,
-        name: undefined,
-        type: undefined,
-        dateRange:[]
-    },
-    searchFormItems: [
-        {
-            field: "groupId",
-            label: "分组ID",
-            class: "w-100",
-            component: "VS",
-            data: () => groupIdOptions.value,
-            props: {
-                type: "select",
-                clearable: true,
-                placeholder: "请选择分组ID",
-                props:{
-                    label:'name',
-                    value:'id',
-                }
-            }
-        },
-        {
-            field: "sn",
-            label: "设备编码",
-            class: "w-100",
-            component: "I",
-            listeners:{
-                keyup: (e: any) => {
-                    if (e.code == "Enter") {
-                        handleQuery()
-                    }
-                }
-            }
-        },
-        {
-            field: "name",
-            label: "设备名称",
-            class: "w-100",
-            component: "I",
-            listeners:{
-                keyup: (e: any) => {
-                    if (e.code == "Enter") {
-                        handleQuery()
-                    }
-                }
-            }
-        },
-        {
-            field: "type",
-            label: "设备类型 1:网关 2:表计",
-            class: "w-100",
-            component: "Dict",
-            props: {
-                type: "radio",
-                placeholder: "请选择设备类型 1:网关 2:表计",
-                dictType: "iot_device_type",
-                valueIsNumber: true,
-            }
-        },
-        {
-            field: "dateRange",
-            label: "创建时间",
-            class: "w-100",
-            component: "D",
-            placeholder: "请选择创建时间",
-            props: {
-                type: "daterange",
-                valueFormat: "YYYY-MM-DD",
-                rangeSeparator: "-",
-                startPlaceholder: "开始日期",
-                endPlaceholder: "结束日期"
-            },
-            listeners: {
-                change: (v: any) => {
-                    queryParams.value.dateRange = v
-                }
-            },
-        },
-    ] as any,
-    permission: "iot:device",
-    handleFuns: {},
-    customBtns: [],
-    tableListFun: apis.iot.deviceApi.listDevice,
-    getEntityFun: apis.iot.deviceApi.getDevice,
-    deleteEntityFun: apis.iot.deviceApi.delDevice,
-    formItems:[
-    {
-        field: "parentId",
-        label: "父ID",
-        class: "w-100",
-        component: "I",
-        type: "number",
-        required: false
-    },
-    {
-        field: "groupId",
-        label: "分组ID",
-        class: "w-100",
-        required: true,
-        component: "VS",
-        data: () => groupIdOptions.value,
-        props: {
-            type: "select",
-            valueIsNumber: true,
-            clearable: true,
-            placeholder: "请选择分组ID",
-            props:{
-                label:'name',
-                value:'id',
-            }
-        }
-    },
-    {
-        field: "sn",
-        label: "设备编码",
-        class: "w-100",
-        component: "I",
-        required: true
-    },
-    {
-        field: "name",
-        label: "设备名称",
-        class: "w-100",
-        component: "I",
-        required: true
-    },
-    {
-        field: "type",
-        label: "设备类型 1:网关 2:表计",
-        class: "w-100",
-        required: true,
-        component: "Dict",
-        props: {
-            type: "radio",
-            valueIsNumber: true,
-            clearable: true,
-            placeholder: "请选择设备类型 1:网关 2:表计",
-            dictType: "iot_device_type"
-        }
-    },
-    {
-        field: "mode",
-        label: "设备模式 1:下发指令查询 2:表计主动上报",
-        class: "w-100",
-        required: false,
-        component: "Dict",
-        props: {
-            type: "radio",
-            valueIsNumber: true,
-            clearable: true,
-            placeholder: "请选择设备模式 1:下发指令查询 2:表计主动上报",
-            dictType: "iot_device_mode"
-        }
-    },
-    {
-        field: "cycle",
-        label: "上报周期",
-        class: "w-100",
-        component: "I",
-        type: "number",
-        required: true
-    },
-    {
-        field: "description",
-        label: "设备描述",
-        class: "w-100",
-        component: "I",
-        required: false
-    },
-    {
-        field: "protocol",
-        label: "表计协议",
-        class: "w-100",
-        required: false,
-        component: "VS",
-        placeholder: "请选择表计协议",
-        data: () => protocolOptions.value,
-        props: {
-            type: "select",
-            clearable: true,
-        },
-    },
-    {
-        field: "address",
-        label: "表计地址",
-        class: "w-100",
-        component: "I",
-        type: "number",
-        required: true
-    },
-
-] as any,
-    resetForm: () => {
-        form.value = emptyFormData.value
-    },
-    emptyFormData: {
-        id: undefined,
-        parentId: undefined,
-        groupId: undefined,
-        sn: undefined,
-        name: undefined,
-        type: undefined,
-        mode: undefined,
-        cycle: undefined,
-        description: undefined,
-        protocol: undefined,
-        address: undefined,
-    }
-})
-const { queryParams, emptyFormData } = toRefs(opts)
-const form = ref<any>(emptyFormData.value)
-
-/** 修改按钮操作 */
-function handleUpdate(row: any) {
-    tableRef.value.defaultHandleFuns.handleUpdate("", row)
-}
-/** 删除按钮操作 */
-function handleDelete(rows: any[]) {
-    tableRef.value.defaultHandleFuns.handleDelete("", rows)
-}
-/** 提交按钮 */
-function submitForm() {
-    if (form.value.id != undefined) {
-        apis.iot.deviceApi.updateDevice(form.value).then(() => {
-            message.msgSuccess("修改成功")
-            handleQuery()
-        })
-    } else {
-        apis.iot.deviceApi.addDevice(form.value).then(() => {
-            message.msgSuccess("新增成功")
-            handleQuery()
-        })
-    }
-}
-/** 查询按钮 */
-function handleQuery() {
-    addDateRange(queryParams.value, queryParams.value.dateRange)
-    tableRef.value?.search()
-}
-/** 查询重置按钮 */
-function resetQuery() {
-    queryParams.value.dateRange = []
-    addDateRange(queryParams.value, queryParams.value.dateRange)
-}
-
-function init(){
-    apis.iot.groupApi.listGroup({pageSize:10000,pageIndex:1}).then((res)=>{
-        groupIdOptions.value = res.data.rows
-    })
+import Gateway from "./_gateway"
+import Meter from "./_meter"
+const id = ref(0)
+function onChange(data: number) {
+	id.value = data
 }
+function init() {}
 
 onMounted(init)
-
 </script>
 
 <template>
-    <div class="app-container">
-        <VbDataTable
-            ref="tableRef"
-            :handle-perm="opts.permission"
-            :handle-funs="opts.handleFuns"
-            :search-form-items="opts.searchFormItems"
-            :columns="opts.columns"
-            :custom-btns="opts.customBtns"
-            :remote-fun="opts.tableListFun"
-            :get-entity-fun="opts.getEntityFun"
-            :delete-entity-fun="opts.deleteEntityFun"
-            sortField="createdAt"
-            sort-order="desc"
-            :modal="modalRef"
-            :reset-form-fun="opts.resetForm"
-            v-model:form-data="form"
-            :query-params="queryParams"
-            :check-multiple="true"
-            :has-checkbox="true"
-            :reset-search-form-fun="resetQuery"
-            :custom-search-fun="handleQuery">
-            <template #groupId="{ row }">
-                <vb-tag :value="row.groupId" :data="groupIdOptions"></vb-tag>
-            </template><template #type="{ row }">
-                <DictTag valueIsNumber :value="row.type" type="iot_device_type"></DictTag>
-            </template><template #mode="{ row }">
-                <DictTag valueIsNumber :value="row.mode" type="iot_device_mode"></DictTag>
-            </template>
-            <template #createdAt="{ row }">
-                <span>{{ dayjs(row.createdAt).format("YYYY-MM-DD HH:mm:ss") }}</span>
-            </template>
-            <template #actions="{ row }">
-                <vb-tooltip content="修改" placement="top">
-                    <el-button
-                            link
-                            type="primary"
-                            @click="handleUpdate(row)"
-                            v-hasPermission="'iot:device:edit'">
-                        <template #icon>
-                            <VbIcon icon-name="notepad-edit" icon-type="duotone" class="fs-3"></VbIcon>
-                        </template>
-                    </el-button>
-                </vb-tooltip>
-                <vb-tooltip content="删除" placement="top">
-                    <el-button
-                            link
-                            type="primary"
-                            @click="handleDelete([row])"
-                            v-hasPermission="'iot:device:remove'">
-                        <template #icon>
-                            <VbIcon icon-name="trash-square" icon-type="duotone" class="fs-3"></VbIcon>
-                        </template>
-                    </el-button>
-                </vb-tooltip>
-            </template>
-        </VbDataTable>
-        <VbModal
-            v-model:modal="modalRef"
-            :title="opts.modalTitle"
-            :form-items="opts.formItems as any"
-            :form-data="form"
-            @confirm="submitForm"
-            append-to-body></VbModal>
-    </div>
+	<div class="app-container d-flex flex-column" style="height: calc(100vh - 140px)">
+		<div class="w-100" style="height: 65%">
+			<Gateway @change="onChange" />
+		</div>
+		<div class="w-100" style="height: 35%">
+			<Meter :id="id"></Meter>
+		</div>
+	</div>
 </template>

+ 51 - 8
UI/IOTADMIN.VUE/src/views/iot/group/index.vue

@@ -5,12 +5,19 @@ import dayjs from "dayjs"
 
 const tableRef = ref()
 const modalRef = ref()
+const groupOptions = ref<any[]>([])
 const opts = reactive<any>({
 	columns: [
 		{ field: "id", name: "ID", width: 100, visible: false, isSort: false, tooltip: true },
-		{ field: "parentId", name: "父ID", width: "auto", isSort: false, visible: true },
-		{ field: "name", name: "分组名称", width: "auto", isSort: true, visible: true },
-		{ field: "description", name: "分组描述", width: "auto", isSort: false, visible: true },
+		{ field: "name", name: "分组名称", width: 300, isSort: true, visible: true },
+		{
+			field: "description",
+			name: "分组描述",
+			width: "auto",
+			isSort: false,
+			visible: true,
+			tooltip: true
+		},
 		{ field: "createdAt", name: "创建时间", width: 185, isSort: true, visible: true },
 		{ field: "actions", name: `操作`, width: 150 }
 	],
@@ -68,6 +75,16 @@ const opts = reactive<any>({
 	] as any,
 	permission: "iot:group",
 	handleFuns: {},
+	handleBtns: [
+		{
+			key: "handleUpdate",
+			show: false
+		},
+		{
+			key: "handleDelete",
+			show: false
+		}
+	],
 	customBtns: [],
 	tableListFun: apis.iot.groupApi.listGroup,
 	getEntityFun: apis.iot.groupApi.getGroup,
@@ -77,7 +94,16 @@ const opts = reactive<any>({
 			field: "parentId",
 			label: "父ID",
 			class: "w-100",
-			component: "I",
+			component: "VST",
+			data: () => groupOptions.value,
+			props: {
+				placeholder: "请选择父分组",
+				props: {
+					label: "name",
+					value: "id",
+					children: "children"
+				}
+			},
 			required: true
 		},
 		{
@@ -92,11 +118,12 @@ const opts = reactive<any>({
 			label: "分组描述",
 			class: "w-100",
 			component: "I",
-			required: true
+			type: "textarea"
 		}
 	] as any,
 	resetForm: () => {
 		form.value = emptyFormData.value
+		getGroupTreeSelect()
 	},
 	emptyFormData: {
 		id: undefined,
@@ -140,7 +167,14 @@ function resetQuery() {
 	queryParams.value.dateRange = []
 	addDateRange(queryParams.value, queryParams.value.dateRange)
 }
-
+function getGroupTreeSelect() {
+	groupOptions.value = []
+	apis.iot.groupApi.listGroup({}).then((res) => {
+		const group: any = { id: 0, name: "主节点", children: [] }
+		group.children = res.data.rows //handleTree(res.data, "orgId")
+		groupOptions.value.push(group)
+	})
+}
 function init() {}
 
 onMounted(init)
@@ -150,8 +184,19 @@ onMounted(init)
 	<div class="app-container">
 		<VbDataTable
 			ref="tableRef"
+			:is-tree="true"
+			keyField="id"
+			iconField="name"
+			parentField="parentId"
+			childrenField="children"
+			:no-page="true"
+			:expand-depth="1"
+			:interval-left="10"
+			:check-multiple="false"
+			:has-checkbox="false"
 			:handle-perm="opts.permission"
 			:handle-funs="opts.handleFuns"
+			:handle-btns="opts.handleBtns"
 			:search-form-items="opts.searchFormItems"
 			:columns="opts.columns"
 			:custom-btns="opts.customBtns"
@@ -164,8 +209,6 @@ onMounted(init)
 			:reset-form-fun="opts.resetForm"
 			v-model:form-data="form"
 			:query-params="queryParams"
-			:check-multiple="true"
-			:has-checkbox="true"
 			:reset-search-form-fun="resetQuery"
 			:custom-search-fun="handleQuery">
 			<template #createdAt="{ row }">

+ 1 - 1
UI/IOTADMIN.VUE/src/views/system/org/index.vue

@@ -197,7 +197,7 @@ function getTableData(q: any) {
 			parentField="parentId"
 			childrenField="children"
 			:no-page="true"
-			:expand-orgh="1"
+			:expand-depth="1"
 			:interval-left="10"
 			:check-multiple="false"
 			:has-checkbox="false"

+ 6 - 5
UI/IOTADMIN.VUE/src/views/system/user/index.vue

@@ -255,6 +255,7 @@ const modalOpts = reactive({
 		}
 	] as any,
 	emptyFormData: {
+		id: undefined,
 		userId: undefined,
 		orgId: undefined,
 		userName: undefined,
@@ -265,23 +266,23 @@ const modalOpts = reactive({
 		sex: "0",
 		status: "2",
 		remark: undefined,
-		postId: undefined,
-		roleId: undefined
+		postId: 1,
+		roleId: 2
 	}
 })
 const { title: modalTitle, emptyFormData, formItems } = toRefs(modalOpts)
 const form = ref(emptyFormData)
 function reset() {
-	form.value = emptyFormData.value
+	form.value = Object.assign({}, emptyFormData.value)
 }
 const initPassword = ref(undefined)
 function handleCreate() {
 	modalTitle.value = "新增用户"
 	reset()
+	initPassword.value = undefined
 	apis.system.userApi.getUser("0").then(({ data }) => {
 		setOptions(data)
-		form.value.password = initPassword.value
-		form.value.postId = undefined
+		console.log("USER", form.value)
 		modalRef.value.show()
 	})
 }