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() (model T_data_model_defualt, 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 c.Model, 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 c.Model, 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{})
tmp := tools.IsEmpty(properties["ied_type"])
if arrayex.IndexOf(iedtypes, tmp) > -1 {
//装置类型重复了
return c.Model, errors.New("装置类型" + tmp + "不能重复引用")
}
iedtypes = append(iedtypes, tmp)
continue
}
properties := ritem2["properties"].(map[string]interface{})
tmp := tools.IsEmpty(properties["ied_type"])
if arrayex.IndexOf(iedtypes, tmp) > -1 {
//装置类型重复了
return c.Model, 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 c.Model, err
}
if c.Model.ModelName != "" {
h, oldid := c.ExistName(c.Model.ModelName)
if h && c.Model.Id != oldid {
return c.Model, 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 c.Model, 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"])
if arrayex.IndexOf(iedtypes, tmp) > -1 {
//装置类型重复了
return c.Model, errors.New("装置类型" + tmp + "不能重复引用")
}
iedtypes = append(iedtypes, tmp)
continue
}
properties := ritem2["properties"].(map[string]interface{})
tmp := tools.IsEmpty(properties["ied_type"])
if arrayex.IndexOf(iedtypes, tmp) > -1 {
//装置类型重复了
return c.Model, 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 c.Model, 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 != "" {
if c.Model.IsSys == 2 {
tmpM.ModelName = c.Model.ModelName + tmpM.ModelName
} else {
tmpM.ModelName = c.Model.ModelName
}
} else {
tmpM.ModelName = "[检测模型]" + tmpM.ModelName
}
if c.Model.VolId > 0 {
tmpM.VolId = c.Model.VolId
}
if c.Model.LineLinkStyle > 0 {
tmpM.LineLinkStyle = c.Model.LineLinkStyle
}
if c.Model.IsSys > 0 {
tmpM.IsSys = c.Model.IsSys
} else {
tmpM.IsSys = 2
}
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, tmpM.IsSys, 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: modelid}
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
}