package bo import ( "encoding/json" "encoding/xml" "errors" "fmt" "scd_check_tools/arrayex" "scd_check_tools/logger" "scd_check_tools/models/enum" "scd_check_tools/tools" "strconv" "strings" "sync" "github.com/astaxie/beego/orm" ) //系统内置模型 type T_data_model_defualt struct { Id int `orm:"pk"` ModelName string // '模型名称' , AreaType int // '所属间隔类型ID' , VolId int // '所属电压等级ID' , LineLinkStyle int // '接线方式' , IedTypes string // '包含的装置类型' , RelationJson string // '关系定义内容' , IsSys int //是否内置模型。1 系统内置模型 2 任务检测模型 FromModelId int //非系统内置模型时的参照模型ID。is_sys为2时有效 Cr int // '创建人' , Ct string `orm:"-"` // '创建时间' , Ur int // '更新人' , Ut string `orm:"-"` // '更新时间' } type ModelNodeStruct struct { XMLName xml.Name `xml:"flow"` Nodes []*INodeStruct `xml:"nodes"` Edges []*IEdges `xml:"edges"` } type INodeStruct struct { Id string `xml:"id"` Type string `xml:"type"` X string `xml:"x"` Y string `xml:"y"` Text *IText `xml:"text"` Properties *Iproperties `xml:"properties"` } type IText struct { X string `xml:"x"` Y string `xml:"y"` Value string `xml:"value"` } type Iproperties struct { IedType string `xml:"ied_type"` } type IEdges struct { Id string `xml:"id"` Type string `xml:"type"` SourceNodeId string `xml:"sourceNodeId"` TargetNodeId string `xml:"targetNodeId"` Properties *ILineProperties `xml:"properties"` } type ILineProperties struct { Issv string `xml:"issv"` // SV|GOOSE } //内置检测模型管理对象 type SysCheckModelMgr struct { Model T_data_model_defualt DeviceBaseModel } var sysCheckModelDesc = "内置检测模型" var SysModelList = sync.Map{} func init() { orm.RegisterModel(new(T_data_model_defualt)) } //判断名称是否已存在 func (c *SysCheckModelMgr) ExistName(name string) (has bool, id int) { db := orm.NewOrm() rows := []orm.Params{} _, err := db.Raw("select id from t_data_model_defualt where model_name=?", name).Values(&rows) if err != nil { logger.Logger.Error(err) return true, 0 } if len(rows) > 0 { id, _ = strconv.Atoi(tools.IsEmpty(rows[0]["id"])) return true, id } return false, 0 } //保存检测模型信息 func (c *SysCheckModelMgr) Save() (err error) { dblog := new(SystemLog) dblog.SetUserInfo(c.GetUserInfo()) dblog.Audittype = enum.AuditType_check_model dblog.Logtype = enum.LogType_Insert dblog.Eventtype = enum.OptEventType_Bus dblog.Eventlevel = enum.OptEventLevel_Hight db := orm.NewOrm() if c.Model.Id == 0 { h, _ := c.ExistName(c.Model.ModelName) if h { return errors.New("模型名称已存在") } if c.Model.IsSys == 0 { c.Model.IsSys = 1 } c.Model.Cr, _ = strconv.Atoi(c.GetUserId()) //处理组合装置 if c.Model.RelationJson != "" { modelJson := map[string]interface{}{} err = json.Unmarshal([]byte(c.Model.RelationJson), &modelJson) if err != nil { logger.Logger.Error(err) dblog.Description = fmt.Sprintf("保存%s信息失败:%s,操作数据:%+v", sysCheckModelDesc, err.Error(), c.Model) dblog.Fail2() return err } if modelJson["nodes"] != nil { nodes := modelJson["nodes"].([]interface{}) iedtypes := []string{} for _, ritem := range nodes { ritem2 := ritem.(map[string]interface{}) nodetype := tools.IsEmpty(ritem2["type"]) if nodetype == "my-group" { properties := ritem2["properties"].(map[string]interface{}) iedtypes = append(iedtypes, tools.IsEmpty(properties["ied_type"])) continue } properties := ritem2["properties"].(map[string]interface{}) tmp := tools.IsEmpty(properties["ied_type"]) if arrayex.IndexOf(iedtypes, tmp) > 0 { //装置类型重复了 return errors.New("装置类型" + tmp + "不能重复引用") } iedtypes = append(iedtypes, tmp) } c.Model.IedTypes = strings.Join(iedtypes, ",") } } newid, err2 := db.Insert(&c.Model) if err2 == nil { c.Model.Id = int(newid) //添加接线方式与模型关系 lm := new(LinkStyleModelMgr) lm.Model.LinkstyleId = c.Model.LineLinkStyle lm.Model.ModelId = int(newid) lm.SetUserInfo(c.GetUserInfo()) lm.Save() } if err2 != nil { err = err2 } } else { tmpObj, err := c.One() if err != nil { return err } if c.Model.ModelName != "" { h, oldid := c.ExistName(c.Model.ModelName) if h && c.Model.Id != oldid { return errors.New("模型名称已存在") } } else { c.Model.ModelName = tmpObj.ModelName } if c.Model.AreaType == 0 { c.Model.AreaType = tmpObj.AreaType } if c.Model.IedTypes == "" { c.Model.IedTypes = tmpObj.IedTypes } if c.Model.IsSys == 0 { c.Model.IsSys = tmpObj.IsSys } if c.Model.LineLinkStyle == 0 { c.Model.LineLinkStyle = tmpObj.LineLinkStyle } else if c.Model.LineLinkStyle != tmpObj.LineLinkStyle { //更新接线方式与模型关系 lm := new(LinkStyleModelMgr) lm.Model.LinkstyleId = tmpObj.LineLinkStyle lm.Model.ModelId = c.Model.Id lm.SetUserInfo(c.GetUserInfo()) lm.Delete() //清除原来的关系 lm.Model.LinkstyleId = c.Model.LineLinkStyle lm.Save() } if c.Model.VolId == 0 { c.Model.VolId = tmpObj.VolId } if c.Model.IsSys == 0 { c.Model.IsSys = tmpObj.IsSys } if c.Model.FromModelId == 0 { c.Model.FromModelId = tmpObj.FromModelId } if c.Model.RelationJson != "" { // 解析出模型需要的装置类型 modelJson := map[string]interface{}{} err = json.Unmarshal([]byte(c.Model.RelationJson), &modelJson) /* 5d787390-ebbb-4e97-93d2-87f6a63f7c44 rect 417 202 PM 417 202 母线保护 */ /*nodes := new(ModelNodeStruct) err = xml.Unmarshal([]byte(``+c.Model.RelationJson+``), &nodes) */ if err != nil { logger.Logger.Error(err) dblog.Description = fmt.Sprintf("保存%s信息失败:%s,操作数据:%+v", sysCheckModelDesc, err.Error(), c.Model) dblog.Fail2() return err } if modelJson["nodes"] != nil { nodes := modelJson["nodes"].([]interface{}) iedtypes := []string{} //groupIedTypes := map[string]int{} for _, ritem := range nodes { ritem2 := ritem.(map[string]interface{}) nodetype := tools.IsEmpty(ritem2["type"]) if nodetype == "my-group" { //装置分组 properties := ritem2["properties"].(map[string]interface{}) tmp := tools.IsEmpty(properties["ied_type"]) iedtypes = append(iedtypes, tmp) continue } properties := ritem2["properties"].(map[string]interface{}) tmp := tools.IsEmpty(properties["ied_type"]) if arrayex.IndexOf(iedtypes, tmp) > 0 { //装置类型重复了 return errors.New("装置类型" + tmp + "不能重复引用") } iedtypes = append(iedtypes, tmp) } c.Model.IedTypes = strings.Join(iedtypes, ",") } m2 := new(SysCheckModelIedRelationMgr) m2.SetUserInfo(c.GetUserInfo()) m2.Model.ModelId = c.Model.Id err = m2.Save(modelJson) //先执行这 } else { c.Model.RelationJson = tmpObj.RelationJson } if err == nil { c.Model.Cr = tmpObj.Cr c.Model.Ur, _ = strconv.Atoi(c.GetUserId()) _, err = db.Update(&c.Model) if err != nil { //对比装置类型是否有变动.如果有减少则,需要同步删除减少装置类型的相关数据 oldTypes := strings.Split(tmpObj.IedTypes, ",") newTypes := "," + c.Model.IedTypes + "," for _, item := range oldTypes { if strings.Index(newTypes, ","+item+",") == -1 { //当前装置类型item被删除:删除该装置类型原来的功能定义等 m1 := new(SysCheckModelIedFuncMgr) m1.Model = T_data_model_func_def{ModelId: c.Model.Id, IedType: item} m1.Delete() } } } } } if err != nil { logger.Logger.Error(err) dblog.Description = fmt.Sprintf("保存%s信息失败:%s,操作数据:%+v", sysCheckModelDesc, err.Error(), c.Model) dblog.Fail2() } else { dblog.Description = fmt.Sprintf("保存%s信息成功,操作数据:%+v", sysCheckModelDesc, c.Model) dblog.Success2() //保存装置分组 bgm := new(SysCheckModelIedtypeGroupMgr) bgm.Model = T_data_model_iedtype_group{ModelId: c.Model.Id} bgm.Save(c.Model.RelationJson) } return err } func (c *SysCheckModelMgr) One() (T_data_model_defualt, error) { if c.Model.Id == 0 { return c.Model, errors.New("未指定id") } o := orm.NewOrm() tmpMod := T_data_model_defualt{Id: c.Model.Id} err := o.Read(&tmpMod) if err != nil { logger.Logger.Error(err) } return tmpMod, err } //更新指定模型中的指定装置类型编码 func (c *SysCheckModelMgr) UpdateIedType(oldiedtype, newiedtype string) error { c.Model, _ = c.One() dblog := new(SystemLog) dblog.SetUserInfo(c.GetUserInfo()) dblog.Audittype = enum.AuditType_check_model dblog.Logtype = enum.LogType_Delete dblog.Eventtype = enum.OptEventType_Bus dblog.Eventlevel = enum.OptEventLevel_Hight //判断修改的是否是分组的自定义装置类型 groupMapping := new(SysCheckModelIedtypeGroupMgr) groupMapping.Model = T_data_model_iedtype_group{ModelId: c.Model.Id} rowset := groupMapping.List() for _, g := range rowset { if g == oldiedtype { db := orm.NewOrm() db.Raw("update t_data_model_relation_def set from_ied_code=? where model_id=? and from_ied_code=?", newiedtype, c.Model.Id, oldiedtype).Exec() db.Raw("update t_data_model_relation_def set to_ied_code=? where model_id=? and to_ied_code=?", newiedtype, c.Model.Id, oldiedtype).Exec() db.Raw("update t_data_model_iedtype_group set ied_type=? where model_id=? and ied_type=?", newiedtype, c.Model.Id, oldiedtype).Exec() db.Raw("update t_data_model_iedtype_group set children_type=? where model_id=? and children_type=?", newiedtype, c.Model.Id, oldiedtype).Exec() dblog.Description = fmt.Sprintf("设置%s%s装置类型编码(%s->%s)成功", sysCheckModelDesc, c.Model.ModelName, oldiedtype, newiedtype) dblog.Success2() return nil } } mapping := new(SysCheckModelIedtypeMappingMgr) mapping.Model = T_data_model_iedtype_mapping{ModelId: c.Model.Id} mapping.Model.IedType = oldiedtype mapping.Model.MappingIedType = newiedtype err := mapping.Save() if err != nil { dblog.Description = fmt.Sprintf("设置%s%s装置类型编码(%s->%s)失败:%s", sysCheckModelDesc, c.Model.ModelName, oldiedtype, newiedtype, err.Error()) dblog.Fail2() } else { dblog.Description = fmt.Sprintf("设置%s%s装置类型编码(%s->%s)成功", sysCheckModelDesc, c.Model.ModelName, oldiedtype, newiedtype) dblog.Success2() } return err } //获取指定装置类型的自定义类型编码 func (c *SysCheckModelMgr) GetIedtypeMapping(iedtype string) string { mapping := new(SysCheckModelIedtypeMappingMgr) mapping.Model = T_data_model_iedtype_mapping{ModelId: c.Model.Id} mapping.Model.IedType = iedtype re := mapping.List() if len(re) == 0 { return "" } return re[iedtype] } //根据model中指定的id删除 func (c *SysCheckModelMgr) Delete() (err error) { dblog := new(SystemLog) dblog.SetUserInfo(c.GetUserInfo()) dblog.Audittype = enum.AuditType_check_model dblog.Logtype = enum.LogType_Delete dblog.Eventtype = enum.OptEventType_Bus dblog.Eventlevel = enum.OptEventLevel_Hight db := orm.NewOrm() if c.Model.Id > 0 { db.Read(&c.Model) _, err = db.Delete(&c.Model) } if err != nil { logger.Logger.Error(err) dblog.Description = fmt.Sprintf("删除%s%s失败:%s", sysCheckModelDesc, c.Model.ModelName, err.Error()) dblog.Fail2() } else { SysModelList.Delete(c.Model.Id) lsm := new(LinkStyleModelMgr) lsm.SetUserInfo(c.GetUserInfo()) lsm.Model.ModelId = c.Model.Id lsm.Delete() m2 := new(SysCheckModelIedRelationMgr) m2.SetUserInfo(c.GetUserInfo()) m2.Model.ModelId = c.Model.Id m2.Delete() m3 := new(SysCheckModelIedFuncMgr) m3.Model = T_data_model_func_def{ModelId: c.Model.Id} m3.Delete() bgm := new(SysCheckModelIedtypeGroupMgr) bgm.Model = T_data_model_iedtype_group{ModelId: c.Model.Id} bgm.Delete() obj1 := new(SysCheckModelIedtypeMappingMgr) obj1.Model = T_data_model_iedtype_mapping{ModelId: c.Model.Id} obj1.Delete() dblog.Description = fmt.Sprintf("删除%s%s成功", sysCheckModelDesc, c.Model.ModelName) dblog.Success2() } return err } //复制模型 func (c *SysCheckModelMgr) Copy(modelid int) (error, int) { dblog := new(SystemLog) dblog.SetUserInfo(c.GetUserInfo()) dblog.Audittype = enum.AuditType_check_model dblog.Logtype = enum.LogType_Query dblog.Eventtype = enum.OptEventType_Bus dblog.Eventlevel = enum.OptEventLevel_Low o := orm.NewOrm() tmpM := T_data_model_defualt{Id: modelid} err := o.Read(&tmpM) if err != nil { logger.Logger.Error(err) return err, 0 } if c.Model.ModelName != "" { tmpM.ModelName = c.Model.ModelName + tmpM.ModelName } else { tmpM.ModelName = "[检测模型]" + tmpM.ModelName } sql := "insert into t_data_model_defualt(model_name,area_type,vol_id,line_link_style,ied_types,relation_json,is_sys,from_model_id)values(?,?,?,?,?,?,?,?)" r, err := o.Raw(sql, []interface{}{tmpM.ModelName, tmpM.AreaType, tmpM.VolId, tmpM.LineLinkStyle, tmpM.IedTypes, tmpM.RelationJson, 2, modelid}).Exec() if err != nil { logger.Logger.Error(err) dblog.Description = fmt.Sprintf("复制%s%s失败:%s", sysCheckModelDesc, c.Model.ModelName, err.Error()) dblog.Fail2() return err, 0 } else { m2 := new(SysCheckModelIedRelationMgr) m2.SetUserInfo(c.GetUserInfo()) m2.Model = T_data_model_relation_def{ModelId: modelid} newid, _ := r.LastInsertId() err, _ = m2.Copy(int(newid)) if err != nil { c.Model.Id = int(newid) c.Delete() dblog.Description = fmt.Sprintf("复制%s%s失败:%s", sysCheckModelDesc, c.Model.ModelName, err.Error()) dblog.Fail2() return err, 0 } //复制装置类型分组数据 bgm := new(SysCheckModelIedtypeGroupMgr) bgm.Model = T_data_model_iedtype_group{ModelId: modelid} bgm.Copy(int(newid)) //复制装置类型自定义信息 obj1 := new(SysCheckModelIedtypeMappingMgr) obj1.Model = T_data_model_iedtype_mapping{ModelId: c.Model.Id} obj1.Copy(int(newid)) //复制功能及端子信息 m3 := new(SysCheckModelIedFuncMgr) m3.SetUserInfo(c.GetUserInfo()) err = m3.Copy(tmpM.Id, int(newid)) if err != nil { c.Model.Id = int(newid) c.Delete() m2.Model.ModelId = int(newid) m2.Delete() dblog.Description = fmt.Sprintf("复制%s%s失败:%s", sysCheckModelDesc, c.Model.ModelName, err.Error()) dblog.Fail2() return err, 0 } dblog.Description = fmt.Sprintf("复制%s%s成功", sysCheckModelDesc, c.Model.ModelName) dblog.Success2() return nil, int(newid) } } //获取指定电压等级下的所有模型 func (c *SysCheckModelMgr) GetModelsByVolid(is_sys ...int) ([]orm.Params, error) { o := orm.NewOrm() s := 1 if len(is_sys) > 0 { s = is_sys[0] } sqlParamters := []interface{}{s} sql := "select t.id, t.model_name,t.area_type,c.code area_type_code,c.name area_type_name ,t.ied_types,t.is_sys ,c1.`code` vol_code,c1.`name` vol_name from t_data_model_defualt t INNER JOIN global_const_code c on c.id=t.area_type and c.parentcode='area_type' INNER JOIN global_const_code c1 on t.vol_id=c1.id and c1.parentcode='voltage_level' where t.is_sys=? " rowset := []orm.Params{} _, err := o.Raw(sql, sqlParamters).Values(&rowset) if err != nil { logger.Logger.Error(err) } return rowset, err } //根据model中的指定过滤属性条件查询列表 func (c *SysCheckModelMgr) List(pageno, pagesize int) ([]orm.Params, int, error) { dblog := new(SystemLog) dblog.SetUserInfo(c.GetUserInfo()) dblog.Audittype = enum.AuditType_check_model dblog.Logtype = enum.LogType_Query dblog.Eventtype = enum.OptEventType_Bus dblog.Eventlevel = enum.OptEventLevel_Low o := orm.NewOrm() sqlParamters := []interface{}{} sql := "select t.*,t1.name area_type_name,s1.name line_link_style_name,v1.name voltage_level_name from t_data_model_defualt t left join global_const_code t1 on t.area_type=t1.id and t1.parentcode='area_type' left join global_const_code v1 on t.vol_id=v1.id and v1.parentcode='voltage_level' left join t_data_link_style s1 on t.line_link_style=s1.id where 1=1 " if c.Model.Id > 0 { sql += " and t.id=?" sqlParamters = append(sqlParamters, c.Model.Id) } if c.Model.VolId > 0 { sql += " and t.vol_id=?" sqlParamters = append(sqlParamters, c.Model.VolId) } if c.Model.LineLinkStyle > 0 { sql += " and t.line_link_style=?" sqlParamters = append(sqlParamters, c.Model.LineLinkStyle) } if c.Model.AreaType > 0 { sql += " and t.area_type=?" sqlParamters = append(sqlParamters, c.Model.AreaType) } if c.Model.ModelName != "" { sql += " and t.model_name like ?" sqlParamters = append(sqlParamters, "%"+c.Model.ModelName+"%") } if c.Model.IsSys > 0 { sql += " and t.is_sys = ?" sqlParamters = append(sqlParamters, c.Model.IsSys) } limit := fmt.Sprintf(" order by t.ct desc limit %d,%d", (pageno-1)*pagesize, pagesize) r := []orm.Params{} _, err := o.Raw(sql+limit, sqlParamters).Values(&r) dblog.Description = fmt.Sprintf("SQL:%s 参数:%+v", sql+limit, sqlParamters) if err != nil { logger.Logger.Error(err, dblog.Description) dblog.Fail2() return nil, 0, err } dblog.Success2() total := []orm.Params{} _, err = o.Raw(strings.Replace(sql, "t.*,t1.name area_type_name,s1.name line_link_style_name,v1.name voltage_level_name", "count(1) cnt", 1), sqlParamters).Values(&total) if err != nil { logger.Logger.Error(err) return nil, 0, err } totalCnt := 0 if len(total) > 0 { totalCnt, _ = strconv.Atoi(tools.IsEmpty(total[0]["cnt"])) } return r, totalCnt, err }