Ver Fonte

修复检测报告相关bug

liling há 1 ano atrás
pai
commit
5054fec1f7

+ 1 - 1
service/controllers/excelController.go

@@ -47,7 +47,7 @@ func init() {
 // 	@Success      200    {object} ResultOK 成功
 // 	@Failure 	 500 	{object} ResultError  失败
 //  @router expTableData [post]
-func (c *ApiController) ExpTableData() {
+func (c *ExcelController) ExpTableData() {
 	code := c.GetString("code", "") //业务数据类别,由系统定义
 	if code == "" {
 		c.Data["json"] = c.ResultError("导出的业务数据类别不能为空")

+ 21 - 3
service/controllers/fileDownController.go

@@ -10,6 +10,10 @@
  */
 package controllers
 
+import (
+	"path"
+)
+
 type FileDownController struct {
 	BaseController
 }
@@ -17,12 +21,26 @@ type FileDownController struct {
 func init() {
 }
 
-//公用文件下载方法
-//可通过该方法实现对目标文件进行下载权限、过虑、记录等操作
+// 	@Summary 公用文件下载方法
+//	@Description  公用文件下载方法.可通过该方法实现对目标文件进行下载权限、过虑、记录等操作
+// 	@Tags         文件/附件服务接口
+// 	@Accept       x-www-form-urlencoded
+// 	@Produce      json
+//	@Param 	path 	query   string  		true  "需要下载的文件路径"
+//	@Param 	save_name 	query   string  	false  "文件名称"
+// 	@Success      200    {object} ResultOK 成功
+// 	@Failure 	 500 	{object} ResultError  失败
+//  @router /file/download [get]
 func (this *FileDownController) Get() {
 	//图片,text,pdf文件全部在浏览器中显示了,并没有完全的实现下载的功能
 	//this.Redirect("/static/img/1.jpg", 302)
 
 	//第一个参数是文件的地址,第二个参数是下载显示的文件的名称
-	this.Ctx.Output.Download("static/img/1.jpg", "tu1.jpg")
+	//this.Ctx.Output.Download("static/img/1.jpg", "tu1.jpg")
+	realPath := this.GetString("path")
+	fn := this.GetString("save_name")
+	if fn == "" {
+		fn = path.Base(realPath)
+	}
+	this.Ctx.Output.Download(realPath, fn)
 }

+ 3 - 0
service/main.go

@@ -98,6 +98,9 @@ func main() {
 	} else if dbtype == "sqlite" {
 		db.ConnSqlite("conf/db.cnf")
 	}
+	//new(test.UnitTest).TestIntAddrParse("RPIT/GOINGGIO1.SPCSO1.stVal")
+	//new(test.UnitTest).TestDoiNameRex("(断路器)&(跳|合|闸){1,}&(位置)", "断路器跳位置")
+	//new(test.UnitTest).TestDoiNameRex("Ia1&A&保护", "保护A相电流Ia1(正)")
 	go mqtt.Start()
 	if runmode == "dev" {
 		//自动生成接口权限定义

+ 1 - 0
service/models/bo/check_sys_model.go

@@ -327,6 +327,7 @@ func (c *SysCheckModelMgr) UpdateIedType(oldiedtype, newiedtype string) error {
 			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

+ 17 - 5
service/models/bo/check_sysmodel_ied_fcda_relation.go

@@ -136,9 +136,21 @@ func (c *SysCheckModelFcdaRalationMgr) GetModelAllFcdaRef() (map[string][]orm.Pa
 		logger.Logger.Error(err)
 		return nil, err
 	}
+	//获取装置分组信息
+	bgm := new(SysCheckModelIedtypeGroupMgr)
+	bgm.Model = T_data_model_iedtype_group{ModelId: c.Model.ModelId}
+	groupList := bgm.List()
 	result := map[string][]orm.Params{}
 	for _, row := range rowset {
-		toiedcode := tools.IsEmpty(row["to_ied_code"])
+		tc := tools.IsEmpty(row["to_ied_code"])
+		fc := tools.IsEmpty(row["from_ied_code"])
+		if v, h := groupList[tc]; h {
+			tc = v
+		}
+		if v, h := groupList[fc]; h {
+			fc = v
+		}
+		key := fmt.Sprintf("%s,%s", tc, fc)
 		extref_name_exp := strings.ReplaceAll(tools.IsEmpty(row["to_fcda_match_exp"]), "/", "|")
 		if extref_name_exp == "" {
 			extref_name_exp = tools.IsEmpty(row["to_fcda_name"])
@@ -149,11 +161,11 @@ func (c *SysCheckModelFcdaRalationMgr) GetModelAllFcdaRef() (map[string][]orm.Pa
 			fcda_name_exp = tools.IsEmpty(row["from_fcda_name"])
 		}
 		row["from_fcda_match_exp"] = fcda_name_exp
-		if result[toiedcode] == nil {
-			result[toiedcode] = []orm.Params{}
+		if result[key] == nil {
+			result[key] = []orm.Params{}
 		}
-		result[toiedcode] = append(result[toiedcode], row)
+		result[key] = append(result[key], row)
 	}
-	logger.Logger.Debug(fmt.Sprintf("=====模型%d所有的端子关联关系=====\n%+v", c.Model.ModelId, result))
+	//logger.Logger.Debug(fmt.Sprintf("=====模型%d所有的端子关联关系=====\n%+v", c.Model.ModelId, result))
 	return result, err
 }

+ 1 - 0
service/models/bo/check_sysmodel_iedtype_group.go

@@ -56,6 +56,7 @@ func (c *SysCheckModelIedtypeGroupMgr) Save(jsonstr string) {
 	modelJson := map[string]interface{}{}
 	err := json.Unmarshal([]byte(jsonstr), &modelJson)
 	if err != nil {
+		logger.Logger.Error(err)
 		return
 	}
 	c.Delete()

+ 241 - 89
service/models/bo/checktools_area.go

@@ -3,7 +3,6 @@ package bo
 import (
 	"errors"
 	"fmt"
-	"regexp"
 	"scd_check_tools/logger"
 	"scd_check_tools/models/enum"
 	"scd_check_tools/models/node_attr"
@@ -483,11 +482,13 @@ func (c *CheckAreaMgr) CheckIedFcda() error {
 		volMap["low"] = volRows[len(volRows)-1]["vol"].(string) //低压电压等级
 	}
 	scdNodeRule := new(ScdNodeRule)
+	scdNodeRule.SetScdXmlObject(scdXmlObj)
 	scdNodeMgr := new(ScdNode)
 	//当前装置的所有信号接收端子列表
 	var getIedExtRefs = func(iedname string) map[string]*node_attr.NExtRef {
 		iedObj := scdNodeMgr.GetIed(scdXmlObj, tools.IsEmpty(c.ScdId), iedname)
 		if iedObj == nil {
+			logger.Logger.Debug(fmt.Sprintf("在scd:%d中未发现装置%s", c.ScdId, iedname))
 			return nil
 		}
 		fcdaObjList := map[string]*node_attr.NExtRef{}
@@ -589,50 +590,67 @@ func (c *CheckAreaMgr) CheckIedFcda() error {
 		}
 		return iedlst
 	}
-
 	//iedRelationMgr := new(SysCheckModelIedRelationMgr)
+	modelFcda := sync.Map{}
 	for _, row := range arealist {
 		//获取间隔标准装置及关系
 		modelid, _ := strconv.Atoi(tools.IsEmpty(row["model_id"]))
 		area_name := tools.IsEmpty(row["area_name"])
 		//area_type := tools.IsEmpty(row["area_type"]) //间隔模型类型
 		area_id := tools.IsEmpty(row["id"])
+		logger.Logger.Debug(fmt.Sprintf("开始检查模型%d的间隔%s", modelid, area_name))
+		//获取装置分组信息
+		bgm := new(SysCheckModelIedtypeGroupMgr)
+		bgm.Model = T_data_model_iedtype_group{ModelId: modelid}
+		groupList := bgm.List()
 		//获取该间隔模型配置的所有端子关系列表
 		tmpMgr := new(SysCheckModelFcdaRalationMgr)
 		tmpMgr.Model.ModelId = modelid
-		funclist, _ := tmpMgr.GetModelAllFcdaRef()
-		if funclist == nil {
-			continue
-		}
-		if len(funclist) == 0 {
-			logger.Logger.Error(errors.New(fmt.Sprintf("模型%d还未配置装置关系", modelid)))
-			continue
+		funclist := map[string][]orm.Params{}
+		key := fmt.Sprintf("%d-%d", modelid, area_id)
+		v, h := modelFcda.Load(key)
+		if h {
+			funclist = v.(map[string][]orm.Params)
+		} else {
+			funclist, _ = tmpMgr.GetModelAllFcdaRef()
+			if funclist == nil || len(funclist) == 0 {
+				logger.Logger.Error(errors.New(fmt.Sprintf("模型%d下的间隔%s还未配置装置端子关联关系", modelid, area_name)))
+				continue
+			}
+			modelFcda.Store(key, funclist)
 		}
 		//获取该间隔下该类型的装置
 		s1 := []orm.Params{}
 		_, err = db.Raw("select ied_name from t_data_check_area_ied where area_id=?", area_id).Values(&s1)
 		//循环处理关联关系
-		for ied_type2, fromrowlist := range funclist {
-			ied_type := c.getIedTypeCode(modelid, ied_type2)
-			//找出信号输出装置
-			outiedlist := map[string][]orm.Params{}
-			for _, r := range fromrowlist {
-				fromiedcode := c.getIedTypeCode(modelid, tools.IsEmpty(r["from_ied_code"]))
-				ied_type, vol := getIedTypeAndVolCode(fromiedcode)
-				outiedlist2 := filterAreaIeds(ied_type, vol, s1)
-				for _, iedrow := range outiedlist2 {
-					iedname := tools.IsEmpty(iedrow["ied_name"])
-					if outiedlist[iedname] == nil {
-						outiedlist[iedname] = []orm.Params{}
-					}
-					outiedlist[iedname] = append(outiedlist[iedname], r)
-				}
+		for to_ied_type2, refrow := range funclist {
+			ts := strings.Split(to_ied_type2, ",")
+			//从间隔中获取当前同类型的信号接收装置
+			ied_type := c.getIedTypeCode(modelid, ts[0])
+			if v, h := groupList[ied_type]; h {
+				ied_type = v
+			}
+			ied_type, vol := getIedTypeAndVolCode(ied_type)
+			iedlst := filterAreaIeds(ied_type, vol, s1)
+			logger.Logger.Debug(fmt.Sprintf("正在检查装置类型:%s的装置(%+v)端子关系", ied_type, iedlst))
+			//从间隔中获取当前信号输出装置
+			outiedlist := map[string]orm.Params{}
+			fromiedcode := c.getIedTypeCode(modelid, ts[1])
+			if v, h := groupList[fromiedcode]; h {
+				fromiedcode = v
+			}
+			from_ied_type, vol2 := getIedTypeAndVolCode(fromiedcode)
+			outiedlist2 := filterAreaIeds(from_ied_type, vol2, s1)
+			for _, iedrow := range outiedlist2 {
+				iedname := tools.IsEmpty(iedrow["ied_name"])
+				outiedlist[iedname] = iedrow
 			}
 			if len(outiedlist) == 0 {
+				logger.Logger.Debug(fmt.Sprintf("装置类型%s未发现输出任何装置", ied_type))
 				continue
 			}
-			ied_type, vol := getIedTypeAndVolCode(ied_type)
-			iedlst := filterAreaIeds(ied_type, vol, s1)
+			logger.Logger.Debug(fmt.Sprintf("当前装置类型:%s的装置(%+v)存在以下信号输出装置:%+v", ied_type, iedlst, outiedlist))
+			//logger.Logger.Debug(fmt.Sprintf("设计端子关联关系:%+v", refrow))
 			for _, ied := range iedlst {
 				iedname := tools.IsEmpty(ied["ied_name"])
 				iedObj := scdNodeMgr.GetIed(scdXmlObj, fmt.Sprintf("%d", c.ScdId), iedname)
@@ -641,9 +659,14 @@ func (c *CheckAreaMgr) CheckIedFcda() error {
 					iedObjDesc = iedObj.Desc
 				} else {
 					logger.Logger.Error(fmt.Sprintf("信号接收装置%s未找到!", iedname))
+					continue
 				}
 				extreflist := getIedExtRefs(iedname)
-				for outiedname, refrow := range outiedlist {
+				for outiedname, _ := range outiedlist {
+					if iedname == outiedname {
+						continue
+					}
+					logger.Logger.Debug(fmt.Sprintf("正在匹配装置%s与%s的端子关联关系", iedname, outiedname))
 					outIedObj := scdNodeMgr.GetIed(scdXmlObj, fmt.Sprintf("%d", c.ScdId), outiedname)
 					outIedObjDesc := ""
 					if outIedObj == nil {
@@ -667,57 +690,73 @@ func (c *CheckAreaMgr) CheckIedFcda() error {
 						fcda_name := tools.IsEmpty(r["from_fcda_name"])
 						extref_name_exp := tools.IsEmpty(r["to_fcda_match_exp"])
 						fcda_name_exp := tools.IsEmpty(r["from_fcda_match_exp"])
-						funcExist := false //设计的功能是否存在
+						funcExist := false //判断接收端设计的端子是否存在
 						extrefObj := new(node_attr.NExtRef)
+						fcda2Exist := false
+						fcdaObj := new(node_attr.NFCDA)
 						for desc, item := range extreflist {
-							rex, err := regexp.Compile(extref_name_exp)
-							if err != nil {
-								logger.Logger.Error(err, "无效的正则表达式:"+extref_name_exp)
-								return err
-							}
-							if rex.MatchString(desc) {
+							//logger.Logger.Debug(fmt.Sprintf("接收装置%s的设计端子%s匹配SCD ExtRef DO端子%s", iedname, extref_name_exp, desc))
+							if tools.RexGroupTestMatch(extref_name_exp, desc) {
 								funcExist = true
 								extrefObj = item
 								break
 							}
 						}
-						if !funcExist {
-							parse_result := fmt.Sprintf("间隔%s的装置%s缺失端子%s", area_name, iedname, extref_name)
-							re := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result,
-								"ied_name":      iedname,
-								"ied_desc":      iedObjDesc,
-								"out_ied_name":  outiedname,
-								"out_ied_desc":  outIedObjDesc,
-								"fcda_desc":     extref_name,
-								"fcda_addr":     "",
-								"out_fcda_desc": fcda_name,
-								"out_fcda_addr": "",
-								"error_type":    "3",
-							}
-							//检查未通过
-							scdNodeRule.AppendFcdaCheckResult(re)
-						} else {
-							//检查端子是否关联正确
-							fcda2Exist := false
-							fcdaObj := new(node_attr.NFCDA)
+						if funcExist {
+							//判断输出端端子是否存在
 							for desc, item := range outiedFcdaList {
-								rex, err := regexp.Compile(fcda_name_exp)
-								if err != nil {
-									logger.Logger.Error(err, "无效的正则表达式:"+fcda_name_exp)
-									return err
-								}
-								if rex.MatchString(desc) {
+								//logger.Logger.Debug(fmt.Sprintf("输出装置%s的设计端子%s匹配SCD FCDA DO端子%s", outiedname, fcda_name_exp, desc))
+								if tools.RexGroupTestMatch(fcda_name_exp, desc) {
 									fcda2Exist = true
 									fcdaObj = item
 									break
 								}
 							}
+						}
+						if !funcExist || !fcda2Exist {
+							if !funcExist {
+								parse_result := fmt.Sprintf("间隔%s的装置%s缺失端子%s", area_name, iedname, extref_name)
+								re := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result,
+									"ied_name":      iedname,
+									"ied_desc":      iedObjDesc,
+									"out_ied_name":  "",
+									"out_ied_desc":  "",
+									"fcda_desc":     extref_name,
+									"fcda_addr":     "",
+									"out_fcda_desc": "",
+									"out_fcda_addr": "",
+									"error_type":    "3",
+								}
+								//检查未通过
+								scdNodeRule.AppendFcdaCheckResult(re)
+							}
+							if !fcda2Exist {
+								parse_result := fmt.Sprintf("间隔%s的装置%s缺失端子%s", area_name, outiedname, fcda_name)
+								re := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result,
+									"ied_name":      "",
+									"ied_desc":      "",
+									"out_ied_name":  outiedname,
+									"out_ied_desc":  outIedObjDesc,
+									"fcda_desc":     "",
+									"fcda_addr":     "",
+									"out_fcda_desc": fcda_name,
+									"out_fcda_addr": "",
+									"error_type":    "3",
+								}
+								//检查未通过
+								scdNodeRule.AppendFcdaCheckResult(re)
+							}
+
+						} else {
+							//检查端子是否关联正确
 							if fcda2Exist && (extrefObj.LdInst != fcdaObj.LdInst ||
 								extrefObj.LnInst != fcdaObj.LnInst ||
 								extrefObj.LnClass != fcdaObj.LnClass ||
 								extrefObj.Prefix != fcdaObj.Prefix ||
 								extrefObj.DoName != fcdaObj.DoName) {
 								//不正确
+								logger.Logger.Debug(fmt.Sprintf("extref_name:%s extref_name_exp:%s extrefObj:%+v", extref_name, extref_name_exp, extrefObj))
+								logger.Logger.Debug(fmt.Sprintf("fcda_name:%s fcda_name_exp:%s fcdaObj:%+v", fcda_name, fcda_name_exp, fcdaObj))
 								iedObj := scdNodeMgr.GetIed(scdXmlObj, fmt.Sprintf("%d", c.ScdId), iedname)
 								outIedObj := scdNodeMgr.GetIed(scdXmlObj, fmt.Sprintf("%d", c.ScdId), outiedname)
 								parse_result := fmt.Sprintf("间隔%s的装置%s端子%s与装置%s端子%s关联错误", area_name, iedname, extref_name, outiedname, fcda_name)
@@ -751,19 +790,13 @@ func (c *CheckAreaMgr) CheckIedFcda() error {
 								hasYaoXinFunc = true
 							}
 							extref_name_exp := tools.IsEmpty(r1["to_fcda_match_exp"])
-							rex, err := regexp.Compile(extref_name_exp)
-							if err != nil {
-								logger.Logger.Error(err)
-								return err
-							}
-							if rex.MatchString(extrefdesc) {
+							if extrefdesc == extref_name_exp || tools.RexGroupTestMatch(extref_name_exp, extrefdesc) {
 								//端子存在
 								isHave = true
 								break
 							}
 						}
 						if !isHave {
-							parse_result := fmt.Sprintf("间隔%s的装置%s端子%s在设计中不存在", area_name, iedname, extref_name)
 							daname := ""
 							if r.DaName != "" {
 								daname = "." + r.DaName
@@ -776,6 +809,7 @@ func (c *CheckAreaMgr) CheckIedFcda() error {
 							if doi != nil {
 								fcda_name = doi.(*node_attr.NDOI).Desc
 							}
+							parse_result := fmt.Sprintf("间隔%s下装置(%s)的端子%s在设计中不存在", area_name, iedname, extref_name)
 							re := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result,
 								"ied_name":      iedname,
 								"ied_desc":      iedObj.Desc,
@@ -974,7 +1008,10 @@ func (c *CheckAreaMgr) pT(modelid int, iedtypes string, ieds map[string]orm.Para
 	scdParseMgr := new(ScdParse)
 	scdNodeMgr := new(ScdNode)
 	db := orm.NewOrm()
-
+	//获取装置分组信息
+	bgm := new(SysCheckModelIedtypeGroupMgr)
+	bgm.Model = T_data_model_iedtype_group{ModelId: modelid}
+	groupList := bgm.List()
 	scdXmlObj, _ := scdParseMgr.GetScdXmlObjectBySCDID(tools.IsEmpty(c.ScdId))
 	//获取当前站的各电压等级
 	volRows := []orm.Params{}
@@ -1032,6 +1069,10 @@ func (c *CheckAreaMgr) pT(modelid int, iedtypes string, ieds map[string]orm.Para
 		if tools.IsEmpty(row["ied_type"]) != ptCode[0:1] || tools.IsEmpty(row["p_type"]) != ptCode[1:] {
 			continue
 		}
+		if _, h := groupList[ptCode]; h {
+			//装置如果是分组成员装置,则不用检测
+			continue
+		}
 		//判断主变保护是否是按电压等级分开配置的模型
 		/*
 			if strings.Contains(iedtypes, "PT#H") || strings.Contains(iedtypes, "PT#M") || strings.Contains(iedtypes, "PT#L") {
@@ -1295,7 +1336,10 @@ func (c *CheckAreaMgr) pL(modelid int, vol, iedtypes string, ieds map[string]orm
 	scdParseMgr := new(ScdParse)
 	scdNodeMgr := new(ScdNode)
 	db := orm.NewOrm()
-
+	//获取装置分组信息
+	bgm := new(SysCheckModelIedtypeGroupMgr)
+	bgm.Model = T_data_model_iedtype_group{ModelId: modelid}
+	groupList := bgm.List()
 	scdXmlObj, _ := scdParseMgr.GetScdXmlObjectBySCDID(tools.IsEmpty(c.ScdId))
 	iedCode := c.getIedTypeCode(modelid, "PL")
 	for _, row := range ieds {
@@ -1305,6 +1349,10 @@ func (c *CheckAreaMgr) pL(modelid int, vol, iedtypes string, ieds map[string]orm
 		pmIedName := ""
 		mmIedName := ""
 		pl_iedname := tools.IsEmpty(row["ied_name"])
+		if _, h := groupList[pl_iedname]; h {
+			//装置如果是分组成员装置,则不用检测
+			continue
+		}
 		iednameParts := scdParseMgr.ParseIedName(pl_iedname)
 		areadesc := tools.IsEmpty(row["ied_desc"])
 		if areadesc == "" {
@@ -1335,7 +1383,15 @@ func (c *CheckAreaMgr) pL(modelid int, vol, iedtypes string, ieds map[string]orm
 		clCode := c.getIedTypeCode(modelid, "CL")
 		for _, ty := range strings.Split(iedtypes, ",") {
 			inAreaIedName := ""
+			if _, h := groupList[ty]; h {
+				//装置如果是分组成员装置,则不用检测
+				continue
+			}
 			tyCode := c.getIedTypeCode(modelid, ty)
+			if _, h := groupList[tyCode]; h {
+				//装置如果是分组成员装置,则不用检测
+				continue
+			}
 			if tyCode == pmCode {
 				//母线保护和母线合并单元装置编号跟随变压器
 				//查找变压器编号
@@ -1588,7 +1644,15 @@ func (c *CheckAreaMgr) cJ(modelid string, scdXmlObj *node_attr.SCL, scdNodeMgr *
 //线路间隔装置关系检查
 func (c *CheckAreaMgr) cL(modelid string, scdXmlObj *node_attr.SCL, scdNodeMgr *ScdNode, scdNodeRule *ScdNodeRule, area_name string, ied_refs []orm.Params, area_ieds []orm.Params, area_ruleid string) {
 	modelidInt, _ := strconv.Atoi(modelid)
+	//获取装置分组信息
+	bgm := new(SysCheckModelIedtypeGroupMgr)
+	bgm.Model = T_data_model_iedtype_group{ModelId: modelidInt}
+	groupList := bgm.List()
 	plIed := c.getIedTypeCode(modelidInt, "PL")
+	if v, h := groupList[plIed]; h {
+		//装置如果是分组成员装置
+		plIed = v
+	}
 	masterIed := new(node_attr.NIED)
 	findIedName := ""
 	for _, row2 := range area_ieds {
@@ -1601,6 +1665,7 @@ func (c *CheckAreaMgr) cL(modelid string, scdXmlObj *node_attr.SCL, scdNodeMgr *
 	if masterIed == nil {
 		return
 	}
+	logger.Logger.Debug(fmt.Sprintf("开始分析模型%d的线路间隔关系", modelidInt))
 	dealFromIed := map[string]int{}
 	for _, row := range ied_refs {
 		fromiedtype := c.getIedTypeCode(modelidInt, tools.IsEmpty(row["from_ied_code"]))
@@ -1617,7 +1682,17 @@ func (c *CheckAreaMgr) cL(modelid string, scdXmlObj *node_attr.SCL, scdNodeMgr *
 				} else {
 					if dealFromIed[findIedName] == 0 {
 						parse_result := fmt.Sprintf("间隔%s的装置%s缺失", area_name, findIedName)
-						r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result}
+						r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result,
+							"ied_name":      findIedName,
+							"ied_desc":      "",
+							"out_ied_name":  "",
+							"out_ied_desc":  "",
+							"fcda_desc":     "",
+							"fcda_addr":     "",
+							"out_fcda_desc": "",
+							"out_fcda_addr": "",
+							"error_type":    "9",
+						}
 						//检查未通过
 						scdNodeRule.AppendFcdaCheckResult(r)
 					}
@@ -1650,7 +1725,7 @@ func (c *CheckAreaMgr) cL(modelid string, scdXmlObj *node_attr.SCL, scdNodeMgr *
 					hasToIed = true
 					// 获取该ied的输出(ref_type为0)装置,并从中检测是否存在toiedtype类型的装置
 					inout, _ := scdNodeMgr.GetIedRelations(map[string]interface{}{"scd_id": c.ScdId, "ied_name": findIedName})
-					logger.Logger.Debug(fmt.Sprintf("ied:%s refs:%+v", findIedName, inout))
+					//logger.Logger.Debug(fmt.Sprintf("ied:%s refs:%+v", findIedName, inout))
 					if inout != nil {
 						outiedlist := inout[findIedName].(orm.Params)["list"].([]orm.Params)
 						for _, ieditem := range outiedlist {
@@ -1663,7 +1738,17 @@ func (c *CheckAreaMgr) cL(modelid string, scdXmlObj *node_attr.SCL, scdNodeMgr *
 					}
 					if !hasToIedRef {
 						parse_result := fmt.Sprintf("间隔%s的装置%s缺失与装置%s的%s信号关联", area_name, findIedName, toIedname, reftype)
-						r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result}
+						r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result,
+							"ied_name":      findIedName,
+							"ied_desc":      "",
+							"out_ied_name":  toIedname,
+							"out_ied_desc":  "",
+							"fcda_desc":     "",
+							"fcda_addr":     "",
+							"out_fcda_desc": "",
+							"out_fcda_addr": "",
+							"error_type":    "9",
+						}
 						//检查未通过
 						scdNodeRule.AppendFcdaCheckResult(r)
 					}
@@ -1671,7 +1756,17 @@ func (c *CheckAreaMgr) cL(modelid string, scdXmlObj *node_attr.SCL, scdNodeMgr *
 			}
 			if !hasToIed {
 				parse_result := fmt.Sprintf("间隔%s的装置%s缺失关联装置%s", area_name, findIedName, toIedname)
-				r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result}
+				r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result,
+					"ied_name":      findIedName,
+					"ied_desc":      "",
+					"out_ied_name":  toIedname,
+					"out_ied_desc":  "",
+					"fcda_desc":     "",
+					"fcda_addr":     "",
+					"out_fcda_desc": "",
+					"out_fcda_addr": "",
+					"error_type":    "9",
+				}
 				//检查未通过
 				scdNodeRule.AppendFcdaCheckResult(r)
 			}
@@ -1714,7 +1809,17 @@ func (c *CheckAreaMgr) cT(modelid string, scdXmlObj *node_attr.SCL, scdNodeMgr *
 				} else {
 					if dealFromIed[findIedName] == 0 {
 						parse_result := fmt.Sprintf("间隔%s的装置%s缺失", area_name, findIedName)
-						r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result}
+						r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result,
+							"ied_name":      findIedName,
+							"ied_desc":      "",
+							"out_ied_name":  "",
+							"out_ied_desc":  "",
+							"fcda_desc":     "",
+							"fcda_addr":     "",
+							"out_fcda_desc": "",
+							"out_fcda_addr": "",
+							"error_type":    "9",
+						}
 						//检查未通过
 						scdNodeRule.AppendFcdaCheckResult(r)
 					}
@@ -1731,7 +1836,17 @@ func (c *CheckAreaMgr) cT(modelid string, scdXmlObj *node_attr.SCL, scdNodeMgr *
 		if len(tmpToAreaIeds) == 0 {
 			logger.Logger.Debug(fmt.Sprintf("缺失类型关联装置 :%+v", row))
 			parse_result := fmt.Sprintf("间隔%s缺失类型为%s的%s信号装置", area_name, toiedtype, reftype)
-			r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result}
+			r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result,
+				"ied_name":      findIedName,
+				"ied_desc":      "",
+				"out_ied_name":  "",
+				"out_ied_desc":  "",
+				"fcda_desc":     "",
+				"fcda_addr":     "",
+				"out_fcda_desc": "",
+				"out_fcda_addr": "",
+				"error_type":    "9",
+			}
 			//检查未通过
 			scdNodeRule.AppendFcdaCheckResult(r)
 			continue
@@ -1762,7 +1877,7 @@ func (c *CheckAreaMgr) cT(modelid string, scdXmlObj *node_attr.SCL, scdNodeMgr *
 					hasToIed = true
 					// 获取该ied的输出(ref_type为0)装置,并从中检测是否存在toiedtype类型的装置
 					inout, _ := scdNodeMgr.GetIedRelations(map[string]interface{}{"scd_id": c.ScdId, "ied_name": findIedName})
-					logger.Logger.Debug(fmt.Sprintf("ied:%s refs:%+v", findIedName, inout))
+					//logger.Logger.Debug(fmt.Sprintf("ied:%s refs:%+v", findIedName, inout))
 					if inout != nil {
 						outiedlist := inout[findIedName].(orm.Params)["list"].([]orm.Params)
 						for _, ieditem := range outiedlist {
@@ -1775,7 +1890,17 @@ func (c *CheckAreaMgr) cT(modelid string, scdXmlObj *node_attr.SCL, scdNodeMgr *
 					}
 					if !hasToIedRef {
 						parse_result := fmt.Sprintf("间隔%s的装置%s缺失与装置%s的%s信号关联", area_name, findIedName, toIedname, reftype)
-						r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result}
+						r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result,
+							"ied_name":      findIedName,
+							"ied_desc":      "",
+							"out_ied_name":  toIedname,
+							"out_ied_desc":  "",
+							"fcda_desc":     "",
+							"fcda_addr":     "",
+							"out_fcda_desc": "",
+							"out_fcda_addr": "",
+							"error_type":    "9",
+						}
 						//检查未通过
 						scdNodeRule.AppendFcdaCheckResult(r)
 					}
@@ -1787,12 +1912,32 @@ func (c *CheckAreaMgr) cT(modelid string, scdXmlObj *node_attr.SCL, scdNodeMgr *
 			if toiedtype != ptIed {
 				if volLevel != "" && !hasSameVolIed {
 					parse_result := fmt.Sprintf("间隔%s的装置%s缺失同电压等级的关联类型%s装置", area_name, findIedName, toiedtype)
-					r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result}
+					r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result,
+						"ied_name":      findIedName,
+						"ied_desc":      "",
+						"out_ied_name":  "",
+						"out_ied_desc":  "",
+						"fcda_desc":     "",
+						"fcda_addr":     "",
+						"out_fcda_desc": "",
+						"out_fcda_addr": "",
+						"error_type":    "9",
+					}
 					//检查未通过
 					scdNodeRule.AppendFcdaCheckResult(r)
 				} else if !hasToIed {
 					parse_result := fmt.Sprintf("间隔%s的装置%s缺失关联装置%s", area_name, findIedName, toIedname)
-					r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result}
+					r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result,
+						"ied_name":      findIedName,
+						"ied_desc":      "",
+						"out_ied_name":  toIedname,
+						"out_ied_desc":  "",
+						"fcda_desc":     "",
+						"fcda_addr":     "",
+						"out_fcda_desc": "",
+						"out_fcda_addr": "",
+						"error_type":    "9",
+					}
 					//检查未通过
 					scdNodeRule.AppendFcdaCheckResult(r)
 				}
@@ -1808,7 +1953,7 @@ func (c *CheckAreaMgr) getPMName(iednameParts []string, ieds map[string]orm.Para
 	//如果只有一个PM装置,则直接返回该 装置
 	pmLst := []string{}
 	for n, _ := range ieds {
-		if strings.HasPrefix(n, "PM") {
+		if strings.HasPrefix(n, "PM"+iednameParts[3]+iednameParts[4]) {
 			pmLst = append(pmLst, n)
 		}
 	}
@@ -1816,12 +1961,9 @@ func (c *CheckAreaMgr) getPMName(iednameParts []string, ieds map[string]orm.Para
 		return pmLst[0]
 	}
 	//暴力匹配
-	no := []string{"A", "B", "C", "D", "1", "2", "3", "4"}
-	for _, i := range no {
-		tmpIedName := "PM" + iednameParts[3] + iednameParts[4] + iednameParts[5] + i + iednameParts[7]
-		iedObj := ieds[tmpIedName]
-		if iedObj != nil {
-			return tmpIedName
+	for _, n := range pmLst {
+		if strings.HasSuffix(n, iednameParts[7]) {
+			return n
 		}
 	}
 	return ""
@@ -1829,11 +1971,21 @@ func (c *CheckAreaMgr) getPMName(iednameParts []string, ieds map[string]orm.Para
 
 //根据参考ied name找出应该关联MM装置
 func (c *CheckAreaMgr) getMMName(iednameParts []string, ieds map[string]orm.Params, ab string) string {
-	tmpIedName := "MM" + iednameParts[3] + iednameParts[4] + iednameParts[5] + iednameParts[6] + ab
-	if ieds[tmpIedName] == nil {
-		tmpIedName = "MM" + iednameParts[3] + iednameParts[4] + iednameParts[5] + iednameParts[6] + iednameParts[7]
+	mmLst := []string{}
+	for n, _ := range ieds {
+		if strings.HasPrefix(n, "MM"+iednameParts[3]+iednameParts[4]) {
+			mmLst = append(mmLst, n)
+		}
+	}
+	if len(mmLst) == 1 {
+		return mmLst[0]
 	}
-	return tmpIedName
+	for _, n := range mmLst {
+		if strings.HasSuffix(n, ab) {
+			return n
+		}
+	}
+	return ""
 }
 
 //根据当前设备列表,分析出电压等级(高、中、低)的设备列表

+ 12 - 5
service/models/bo/scd_node_rule.go

@@ -113,6 +113,10 @@ func init() {
 
 var checktopic = "/jujutong/scd_check_tools/ruleparse"
 
+func (c *ScdNodeRule) SetScdXmlObject(obj *node_attr.SCL) {
+	c.scdXmlObject = obj
+}
+
 func (c *ScdNodeRule) TestCheckRule() {
 	c.scdXmlObject, _ = new(ScdParse).GetScdXmlObjectBySCDID(tools.IsEmpty(c.ScdID))
 	if c.scdXmlObject == nil {
@@ -2421,7 +2425,7 @@ func (c *ScdNodeRule) IedIntAddrExist(iedname, intAddr string) (obj interface{})
 				for _, ld := range ap.Server.LDevice {
 					if ld.Inst == ldinst {
 						if ld.LN0 != nil {
-							if strings.HasPrefix(lnstr, fmt.Sprintf("%s/%s%s%s", ld.Inst, ld.LN0.Prefix, ld.LN0.LnClass, ld.LN0.Inst)) {
+							if strings.HasPrefix(lnstr, fmt.Sprintf("%s%s%s", ld.LN0.Prefix, ld.LN0.LnClass, ld.LN0.Inst)) {
 								for _, item := range ld.LN0.DOI {
 									if item.Name == doname {
 										return item
@@ -2430,7 +2434,7 @@ func (c *ScdNodeRule) IedIntAddrExist(iedname, intAddr string) (obj interface{})
 							}
 						}
 						for _, item := range ld.LN {
-							if strings.HasPrefix(lnstr, fmt.Sprintf("%s/%s%s%s", ld.Inst, item.Prefix, item.LnClass, item.Inst)) {
+							if strings.HasPrefix(lnstr, fmt.Sprintf("%s%s%s", item.Prefix, item.LnClass, item.Inst)) {
 								for _, item := range item.DOI {
 									if item.Name == doname {
 										return item
@@ -2533,6 +2537,9 @@ func (c *ScdNodeRule) iedIntAddrDoiOrDaiExist(iedname, intAddr string) (obj inte
 
 //根据LNtype和doi名称返回其cdc属性值
 func (c *ScdNodeRule) getDoICdc(lntype, doiname, daname string) string {
+	if c.lnodeTypeMap == nil {
+		return ""
+	}
 	v, _ := c.lnodeTypeMap.Load(lntype)
 	if v == nil {
 		return ""
@@ -2646,7 +2653,7 @@ func (c *ScdNodeRule) writeNodeDB() {
 	for _, m := range c.CheckFailList {
 		check_type := tools.IsEmpty(m["check_type"]) // fcda检查结果写入t_scd_fcda_check_result
 		if check_type == "fcda" {
-			fcdaSqlValuesAry = append(fcdaSqlValuesAry, "("+tools.IsEmpty(m["scdid"])+",'"+tools.IsEmpty(m["ied_name"])+"','"+tools.IsEmpty(m["ied_desc"])+"','"+tools.IsEmpty(m["fcda_desc"])+"','"+tools.IsEmpty(m["fcda_addr"])+"','"+tools.IsEmpty(m["out_ied_name"])+"','"+tools.IsEmpty(m["out_ied_desc"])+"','"+tools.IsEmpty(m["out_fcda_desc"])+"','"+tools.IsEmpty(m["out_fcda_addr"])+"',"+tools.IsEmpty(m["ruleid"], "0")+",'"+tools.IsEmpty(m["parse_result"])+"',"+tools.IsEmpty(m["error_type"])+")")
+			fcdaSqlValuesAry = append(fcdaSqlValuesAry, "("+tools.IsEmpty(m["scdid"])+",'"+tools.IsEmpty(m["ied_name"])+"','"+tools.IsEmpty(m["ied_desc"])+"','"+tools.IsEmpty(m["fcda_desc"])+"','"+tools.IsEmpty(m["fcda_addr"])+"','"+tools.IsEmpty(m["out_ied_name"])+"','"+tools.IsEmpty(m["out_ied_desc"])+"','"+tools.IsEmpty(m["out_fcda_desc"])+"','"+tools.IsEmpty(m["out_fcda_addr"])+"',"+tools.IsEmpty(m["ruleid"], "0")+",'"+tools.IsEmpty(m["parse_result"])+"',"+tools.IsEmpty(m["error_type"], "0")+")")
 		} else {
 			nodeSqlValuesAry = append(nodeSqlValuesAry, "("+tools.IsEmpty(m["scdid"])+","+tools.IsEmpty(m["nodeid"], "0")+","+tools.IsEmpty(m["lineno"], "0")+",'"+tools.IsEmpty(m["rule_target"])+"',"+tools.IsEmpty(m["ruleid"], "0")+",'"+tools.IsEmpty(m["parse_result"])+"','"+tools.IsEmpty(m["ied_name"])+"','"+tools.IsEmpty(m["ied_desc"])+"')")
 		}
@@ -2661,7 +2668,7 @@ func (c *ScdNodeRule) writeNodeDB() {
 			nodeSqlValuesAry = []string{}
 		}
 		if len(fcdaSqlValuesAry) == 5000 {
-			sql := "insert into t_scd_fcda_check_result" + fcdaCols + "values" + strings.Join(nodeSqlValuesAry, ",")
+			sql := "insert into t_scd_fcda_check_result" + fcdaCols + "values" + strings.Join(fcdaSqlValuesAry, ",")
 			_, err := db.Raw(sql).Exec()
 			if err != nil {
 				log.Println(err)
@@ -2680,7 +2687,7 @@ func (c *ScdNodeRule) writeNodeDB() {
 		nodeSqlValuesAry = nil
 	}
 	if len(fcdaSqlValuesAry) > 0 {
-		sql := "insert into t_scd_fcda_check_result" + fcdaCols + "values" + strings.Join(nodeSqlValuesAry, ",")
+		sql := "insert into t_scd_fcda_check_result" + fcdaCols + "values" + strings.Join(fcdaSqlValuesAry, ",")
 		_, err := db.Raw(sql).Exec()
 		if err != nil {
 			log.Println(err)

+ 7 - 1
service/models/bo/task.go

@@ -127,6 +127,10 @@ func (c *TaskMgr) start(task T_data_task) error {
 	//清除原步骤及状态
 	db.Raw("delete from t_data_task_check_step where task_id=?", task.Id).Exec()
 	db.Raw("delete from t_scd_node_rule_parse where scd_id=?", task.ScdId).Exec()
+	db.Raw("delete from t_scd_fcda_check_result where scd_id=?", task.ScdId).Exec()
+	rept := new(TaskReportMgr)
+	rept.Model = T_data_task_report{TaskId: task.Id}
+	rept.Delete()
 	//生成新的步骤
 	db.Raw("insert into t_data_task_check_step(task_id,task_step_id,state) select ?,id,0 from global_const_code where parentcode='CHECK_STEP' order by id", task.Id).Exec()
 	var isStop = func(taskid int) bool {
@@ -336,6 +340,8 @@ func (c *TaskMgr) Delete() (err error) {
 		db.Raw("delete from t_data_task_check_step where task_id=?", c.Model.Id).Exec()
 		db.Raw("delete from t_data_check_area where scd_id=?", c.Model.ScdId).Exec()
 		db.Raw("delete from t_data_check_area_ied where scd_id=?", c.Model.ScdId).Exec()
+		db.Raw("delete from t_scd_node_rule_parse where scd_id=?", c.Model.ScdId).Exec()
+		db.Raw("delete from t_scd_fcda_check_result where scd_id=?", c.Model.ScdId).Exec()
 		scdmgr := new(ScdMgr)
 		scdmgr.SetUserInfo(u)
 		scdmgr.DeleteScd(strconv.FormatInt(c.Model.ScdId, 10), true)
@@ -363,7 +369,7 @@ func (c *TaskMgr) List(pageno, pagesize int) ([]orm.Params, int, error) {
 	dblog.Eventlevel = enum.OptEventLevel_Low
 	o := orm.NewOrm()
 	sqlParamters := []interface{}{}
-	sql := "select t.*,u.name username,s.scd_name,ts.area_name station_name,c1.id voltage_level,c1.name voltage_name from t_data_task t left join t_scd_scl s on t.scd_id=s.id left join t_data_user u on t.cr=u.id left join t_data_area ts on t.station_id=ts.ID left join global_const_code c1 on ts.AREA_LEVEL=c1.id and c1.parentcode='voltage_level' where 1=1 "
+	sql := "select t.*,u.name username,s.scd_name,ts.area_name station_name,c1.id voltage_level,c1.name voltage_name,ifnull(r1.doc,'') report_doc from t_data_task t left join t_scd_scl s on t.scd_id=s.id left join t_data_user u on t.cr=u.id left join t_data_area ts on t.station_id=ts.ID left join global_const_code c1 on ts.AREA_LEVEL=c1.id and c1.parentcode='voltage_level' left join t_data_task_report r1 on t.id=r1.task_id where 1=1 "
 
 	if c.Model.Id > 0 {
 		sql += " and t.id=?"

+ 15 - 3
service/models/bo/task_report.go

@@ -156,11 +156,23 @@ func (c *TaskReportMgr) Delete() (err error) {
 	dblog.Eventtype = enum.OptEventType_Bus
 	dblog.Eventlevel = enum.OptEventLevel_Hight
 	db := orm.NewOrm()
+	doc := ""
 	if c.Model.Id > 0 {
-		db.Read(&c.Model)
+		err = db.Read(&c.Model)
+		if err != nil {
+			return err
+		}
+		doc = c.Model.Doc
 		_, err = db.Delete(&c.Model)
 	}
 	if c.Model.TaskId > 0 {
+		lst := []orm.Params{}
+		db.Raw("select * from t_data_task_report where task_id=?", c.Model.TaskId).Values(&lst)
+		if len(lst) > 0 {
+			doc = tools.IsEmpty(lst[0]["doc"])
+		} else {
+			return nil
+		}
 		_, err = db.Raw("delete from t_data_task_report where task_id=?", c.Model.TaskId).Exec()
 	}
 
@@ -169,8 +181,8 @@ func (c *TaskReportMgr) Delete() (err error) {
 		dblog.Description = fmt.Sprintf("删除%s%d失败:%s", modelDesc3, c.Model.TaskId, err.Error())
 		dblog.Fail2()
 	} else {
-		if c.Model.Doc != "" {
-			//os.RemoveAll("./" + c.Model.Doc)
+		if doc != "" {
+			os.Remove("./" + doc)
 		}
 		dblog.Description = fmt.Sprintf("删除%s%d成功", modelDesc3, c.Model.TaskId)
 		dblog.Success2()

+ 45 - 9
service/routers/commentsRouter_____________ME_GoProject_src_scd_check_tools_controllers.go

@@ -430,15 +430,6 @@ func init() {
             Filters: nil,
             Params: nil})
 
-    beego.GlobalControllerRouter["scd_check_tools/controllers:ApiController"] = append(beego.GlobalControllerRouter["scd_check_tools/controllers:ApiController"],
-        beego.ControllerComments{
-            Method: "ExpTableData",
-            Router: "expTableData",
-            AllowHTTPMethods: []string{"post"},
-            MethodParams: param.Make(),
-            Filters: nil,
-            Params: nil})
-
     beego.GlobalControllerRouter["scd_check_tools/controllers:AttachmentController"] = append(beego.GlobalControllerRouter["scd_check_tools/controllers:AttachmentController"],
         beego.ControllerComments{
             Method: "AttachmentCfgDel",
@@ -621,6 +612,15 @@ func init() {
 
     beego.GlobalControllerRouter["scd_check_tools/controllers:BusAdminController"] = append(beego.GlobalControllerRouter["scd_check_tools/controllers:BusAdminController"],
         beego.ControllerComments{
+            Method: "DelFuncFcdaRef",
+            Router: "/admin/model/function/fcda-ref/del",
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["scd_check_tools/controllers:BusAdminController"] = append(beego.GlobalControllerRouter["scd_check_tools/controllers:BusAdminController"],
+        beego.ControllerComments{
             Method: "GetFuncFcdaRef",
             Router: "/admin/model/function/fcda-ref/list",
             AllowHTTPMethods: []string{"get"},
@@ -693,6 +693,15 @@ func init() {
 
     beego.GlobalControllerRouter["scd_check_tools/controllers:BusAdminController"] = append(beego.GlobalControllerRouter["scd_check_tools/controllers:BusAdminController"],
         beego.ControllerComments{
+            Method: "GetSysModelIedTypeMapping",
+            Router: "/admin/sysmodel/get/iedtype",
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["scd_check_tools/controllers:BusAdminController"] = append(beego.GlobalControllerRouter["scd_check_tools/controllers:BusAdminController"],
+        beego.ControllerComments{
             Method: "GetSysModelList",
             Router: "/admin/sysmodel/list",
             AllowHTTPMethods: []string{"get"},
@@ -720,6 +729,15 @@ func init() {
 
     beego.GlobalControllerRouter["scd_check_tools/controllers:BusAdminController"] = append(beego.GlobalControllerRouter["scd_check_tools/controllers:BusAdminController"],
         beego.ControllerComments{
+            Method: "UPdateSysModelIedType",
+            Router: "/admin/sysmodel/update/iedtype",
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["scd_check_tools/controllers:BusAdminController"] = append(beego.GlobalControllerRouter["scd_check_tools/controllers:BusAdminController"],
+        beego.ControllerComments{
             Method: "SaveCheckAreaIedByAreaID",
             Router: "/admin/update/check_area/ied",
             AllowHTTPMethods: []string{"post"},
@@ -729,6 +747,15 @@ func init() {
 
     beego.GlobalControllerRouter["scd_check_tools/controllers:ExcelController"] = append(beego.GlobalControllerRouter["scd_check_tools/controllers:ExcelController"],
         beego.ControllerComments{
+            Method: "ExpTableData",
+            Router: "expTableData",
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["scd_check_tools/controllers:ExcelController"] = append(beego.GlobalControllerRouter["scd_check_tools/controllers:ExcelController"],
+        beego.ControllerComments{
             Method: "UploadExcelFile",
             Router: "impData",
             AllowHTTPMethods: []string{"post"},
@@ -736,6 +763,15 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["scd_check_tools/controllers:FileDownController"] = append(beego.GlobalControllerRouter["scd_check_tools/controllers:FileDownController"],
+        beego.ControllerComments{
+            Method: "Get",
+            Router: "/file/download",
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["scd_check_tools/controllers:FlowController"] = append(beego.GlobalControllerRouter["scd_check_tools/controllers:FlowController"],
         beego.ControllerComments{
             Method: "DeleteFlowCnf_NodeUser",

+ 18 - 9
service/routers/commentsRouter_controllers.go

@@ -430,15 +430,6 @@ func init() {
             Filters: nil,
             Params: nil})
 
-    beego.GlobalControllerRouter["scd_check_tools/controllers:ApiController"] = append(beego.GlobalControllerRouter["scd_check_tools/controllers:ApiController"],
-        beego.ControllerComments{
-            Method: "ExpTableData",
-            Router: "expTableData",
-            AllowHTTPMethods: []string{"post"},
-            MethodParams: param.Make(),
-            Filters: nil,
-            Params: nil})
-
     beego.GlobalControllerRouter["scd_check_tools/controllers:AttachmentController"] = append(beego.GlobalControllerRouter["scd_check_tools/controllers:AttachmentController"],
         beego.ControllerComments{
             Method: "AttachmentCfgDel",
@@ -756,6 +747,15 @@ func init() {
 
     beego.GlobalControllerRouter["scd_check_tools/controllers:ExcelController"] = append(beego.GlobalControllerRouter["scd_check_tools/controllers:ExcelController"],
         beego.ControllerComments{
+            Method: "ExpTableData",
+            Router: "expTableData",
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["scd_check_tools/controllers:ExcelController"] = append(beego.GlobalControllerRouter["scd_check_tools/controllers:ExcelController"],
+        beego.ControllerComments{
             Method: "UploadExcelFile",
             Router: "impData",
             AllowHTTPMethods: []string{"post"},
@@ -763,6 +763,15 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["scd_check_tools/controllers:FileDownController"] = append(beego.GlobalControllerRouter["scd_check_tools/controllers:FileDownController"],
+        beego.ControllerComments{
+            Method: "Get",
+            Router: "/file/download",
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["scd_check_tools/controllers:FlowController"] = append(beego.GlobalControllerRouter["scd_check_tools/controllers:FlowController"],
         beego.ControllerComments{
             Method: "DeleteFlowCnf_NodeUser",

+ 1 - 0
service/routers/router.go

@@ -32,6 +32,7 @@ func init() {
 		beego.NSInclude(&controllers.TaskController{}),
 		beego.NSInclude(&controllers.BusAdminController{}),
 		beego.NSInclude(&controllers.ReportController{}),
+		beego.NSInclude(&controllers.FileDownController{}),
 	)
 	beego.AddNamespace(nsapi)
 

+ 36 - 1
service/static/swagger/swagger.json

@@ -2128,6 +2128,41 @@
                 }
             }
         },
+        "/file/download": {
+            "get": {
+                "tags": [
+                    "scd_check_tools/controllersFileDownController"
+                ],
+                "summary": "公用文件下载方法",
+                "description": "公用文件下载方法.可通过该方法实现对目标文件进行下载权限、过虑、记录等操作",
+                "parameters": [
+                    {
+                        "in": "query",
+                        "name": "path",
+                        "description": "需要下载的文件路径",
+                        "required": true,
+                        "type": "string"
+                    },
+                    {
+                        "in": "query",
+                        "name": "save_name",
+                        "description": "文件名称",
+                        "type": "string"
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "成功",
+                        "schema": {
+                            "$ref": "#/definitions/ResultOK"
+                        }
+                    },
+                    "500": {
+                        "description": "{object} ResultError  失败"
+                    }
+                }
+            }
+        },
         "/flow/cnf/deleteuser": {
             "post": {
                 "tags": [
@@ -6441,7 +6476,7 @@
         "expTableData": {
             "post": {
                 "tags": [
-                    "scd_check_tools/controllersApiController"
+                    "scd_check_tools/controllersExcelController"
                 ],
                 "summary": "Excel数据导出",
                 "description": "Excel数据导出。导出成功时将返回导出文件的下载地址。",

+ 24 - 1
service/static/swagger/swagger.yml

@@ -1447,6 +1447,29 @@ paths:
             $ref: '#/definitions/ResultError'
         "500":
           description: status  失败
+  /file/download:
+    get:
+      tags:
+      - scd_check_tools/controllersFileDownController
+      summary: 公用文件下载方法
+      description: 公用文件下载方法.可通过该方法实现对目标文件进行下载权限、过虑、记录等操作
+      parameters:
+      - in: query
+        name: path
+        description: 需要下载的文件路径
+        required: true
+        type: string
+      - in: query
+        name: save_name
+        description: 文件名称
+        type: string
+      responses:
+        "200":
+          description: 成功
+          schema:
+            $ref: '#/definitions/ResultOK'
+        "500":
+          description: '{object} ResultError  失败'
   /flow/cnf/deleteuser:
     post:
       tags:
@@ -4372,7 +4395,7 @@ paths:
   expTableData:
     post:
       tags:
-      - scd_check_tools/controllersApiController
+      - scd_check_tools/controllersExcelController
       summary: Excel数据导出
       description: Excel数据导出。导出成功时将返回导出文件的下载地址。
       parameters:

+ 36 - 1
service/swagger/swagger.json

@@ -2128,6 +2128,41 @@
                 }
             }
         },
+        "/file/download": {
+            "get": {
+                "tags": [
+                    "scd_check_tools/controllersFileDownController"
+                ],
+                "summary": "公用文件下载方法",
+                "description": "公用文件下载方法.可通过该方法实现对目标文件进行下载权限、过虑、记录等操作",
+                "parameters": [
+                    {
+                        "in": "query",
+                        "name": "path",
+                        "description": "需要下载的文件路径",
+                        "required": true,
+                        "type": "string"
+                    },
+                    {
+                        "in": "query",
+                        "name": "save_name",
+                        "description": "文件名称",
+                        "type": "string"
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "成功",
+                        "schema": {
+                            "$ref": "#/definitions/ResultOK"
+                        }
+                    },
+                    "500": {
+                        "description": "{object} ResultError  失败"
+                    }
+                }
+            }
+        },
         "/flow/cnf/deleteuser": {
             "post": {
                 "tags": [
@@ -6441,7 +6476,7 @@
         "expTableData": {
             "post": {
                 "tags": [
-                    "scd_check_tools/controllersApiController"
+                    "scd_check_tools/controllersExcelController"
                 ],
                 "summary": "Excel数据导出",
                 "description": "Excel数据导出。导出成功时将返回导出文件的下载地址。",

+ 24 - 1
service/swagger/swagger.yml

@@ -1447,6 +1447,29 @@ paths:
             $ref: '#/definitions/ResultError'
         "500":
           description: status  失败
+  /file/download:
+    get:
+      tags:
+      - scd_check_tools/controllersFileDownController
+      summary: 公用文件下载方法
+      description: 公用文件下载方法.可通过该方法实现对目标文件进行下载权限、过虑、记录等操作
+      parameters:
+      - in: query
+        name: path
+        description: 需要下载的文件路径
+        required: true
+        type: string
+      - in: query
+        name: save_name
+        description: 文件名称
+        type: string
+      responses:
+        "200":
+          description: 成功
+          schema:
+            $ref: '#/definitions/ResultOK'
+        "500":
+          description: '{object} ResultError  失败'
   /flow/cnf/deleteuser:
     post:
       tags:
@@ -4372,7 +4395,7 @@ paths:
   expTableData:
     post:
       tags:
-      - scd_check_tools/controllersApiController
+      - scd_check_tools/controllersExcelController
       summary: Excel数据导出
       description: Excel数据导出。导出成功时将返回导出文件的下载地址。
       parameters:

+ 69 - 0
service/test/test.go

@@ -2,7 +2,9 @@ package test
 
 import (
 	"encoding/json"
+	"errors"
 	"fmt"
+	"os"
 	"reflect"
 	"regexp"
 	"scd_check_tools/conf"
@@ -11,6 +13,7 @@ import (
 	"scd_check_tools/models/bo"
 	"scd_check_tools/tools"
 	"strings"
+	"sync"
 	"time"
 )
 
@@ -224,3 +227,69 @@ func (t *UnitTest) Test19() {
 	testResult, _ := tools.Post(url, postdataStr, UnitTestToken)
 	logger.Logger.Println(fmt.Sprintf("============测试结果报告生成:%+v", testResult))
 }
+
+func (t *UnitTest) TestDoiNameRex() {
+	return
+	defer func() {
+		os.Exit(0)
+	}()
+	regstr := ""
+	soruce := ""
+	regstrs := strings.Split(regstr, "&")
+	wg := sync.WaitGroup{}
+	wg.Add(len(regstrs))
+	wgResultFalse := map[string]bool{}
+	for _, item := range regstrs {
+		go func(item string) {
+			fcdarex, err2 := regexp.Compile(item)
+			if err2 != nil {
+				logger.Logger.Error(err2, item)
+				wgResultFalse["false"] = false
+			} else if !fcdarex.MatchString(soruce) {
+				wgResultFalse["false"] = false
+			}
+			wg.Done()
+		}(item)
+	}
+	wg.Wait()
+	matchSuccess := true
+	if _, h := wgResultFalse["false"]; h {
+		matchSuccess = false
+	}
+	fmt.Println(fmt.Sprintf("%+v", matchSuccess))
+}
+
+func (t *UnitTest) TestIntAddrParse() {
+	return
+	defer func() {
+		os.Exit(0)
+	}()
+	intAddr := ""
+	addrs := strings.Split(intAddr, ":")
+	if len(addrs) == 2 {
+		intAddr = addrs[1]
+	}
+	intAddrs := strings.Split(intAddr, "/")
+	if len(intAddrs) == 1 {
+		logger.Logger.Error(errors.New(fmt.Sprintf("无效的intAddr:%s", intAddr)))
+		return
+	}
+	ldinst := intAddrs[0]
+	lnstr := intAddrs[1]
+	v_tmpAry := strings.Split(lnstr, ".")
+	if len(v_tmpAry) < 2 {
+		logger.Logger.Error(errors.New(fmt.Sprintf("无效的intAddr:%s", intAddr)))
+		return
+	}
+	doda := v_tmpAry[1:]
+	doname := ""
+	daname := ""
+	if len(doda) == 1 {
+		//只有do
+		doname = doda[0]
+	} else {
+		doname = doda[0]
+		daname = strings.Join(doda[1:], ".") //还原da
+	}
+	fmt.Println(fmt.Sprintf("lnstr:%s,ldinst:%s,doname:%s,daname:%s", lnstr, ldinst, doname, daname))
+}

+ 42 - 0
service/tools/tool.go

@@ -25,6 +25,7 @@ import (
 	"scd_check_tools/logger"
 	"strconv"
 	"strings"
+	"sync"
 	"time"
 	"unicode"
 
@@ -102,6 +103,47 @@ func CheckErr(err error) {
 	}
 }
 
+//多表达式分组匹配
+//多个表达式组时使用&分隔,每个分组表达式可使用()括起来,更加易读,且内部内容必须符合正则表过式规则
+//表达式样例1:(断路器)&(跳|合|闸){1,}&(位置)
+//表达式样例2:Ia1&A&保护
+func RexGroupTestMatch(regstr, soruce string) bool {
+	if regstr == "" || soruce == "" {
+		return false
+	}
+	regstrs := strings.Split(regstr, "&")
+	if len(regstrs) > 1 {
+		//未分组时,直接匹配
+		fcdarex, err2 := regexp.Compile(regstr)
+		if err2 != nil {
+			logger.Logger.Error(err2, regstr)
+			return false
+		}
+		return fcdarex.MatchString(soruce)
+	}
+	wg := sync.WaitGroup{}
+	wg.Add(len(regstrs))
+	wgResultFalse := map[string]bool{}
+	for _, item := range regstrs {
+		go func(item string) {
+			fcdarex, err2 := regexp.Compile(item)
+			if err2 != nil {
+				logger.Logger.Error(err2, item)
+				wgResultFalse["false"] = false
+			} else if !fcdarex.MatchString(soruce) {
+				wgResultFalse["false"] = false
+			}
+			wg.Done()
+		}(item)
+	}
+	wg.Wait()
+	matchSuccess := true
+	if _, h := wgResultFalse["false"]; h {
+		matchSuccess = false
+	}
+	return matchSuccess
+}
+
 //生成全局唯一ID序列
 func GetSeqID() int64 {
 	if GlobalID == 0 {