Files
be.ems/src/modules/practical_training/service/pt_ne_config_data.go
2024-11-23 10:44:22 +08:00

462 lines
13 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package service
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"reflect"
"be.ems/src/framework/constants/uploadsubpath"
"be.ems/src/framework/utils/file"
"be.ems/src/framework/utils/parse"
neFetchlink "be.ems/src/modules/network_element/fetch_link"
neModel "be.ems/src/modules/network_element/model"
neService "be.ems/src/modules/network_element/service"
"be.ems/src/modules/practical_training/model"
"be.ems/src/modules/practical_training/repository"
"github.com/xuri/excelize/v2"
)
// NewPtNeConfigDataService 实例化服务层
var NewPtNeConfigDataService = &PtNeConfigDataService{
ptNeConfigDataLogRepository: repository.NewPtNeConfigDataLogRepository,
ptNeConfigDataRepository: repository.NewPtNeConfigDataRepository,
neConfigService: neService.NewNeConfig,
neInfoService: neService.NewNeInfo,
}
// PtNeConfigDataService 服务层处理
type PtNeConfigDataService struct {
// 实训教学_网元参数配置数据变更日志
ptNeConfigDataLogRepository *repository.PtNeConfigDataLogRepository
// 实训教学_网元参数配置表
ptNeConfigDataRepository *repository.PtNeConfigDataRepository
// 网元参数配置可用属性值服务
neConfigService *neService.NeConfig
// 网元信息服务
neInfoService *neService.NeInfo
}
// SelectNeHostPage 分页查询列表数据
func (r *PtNeConfigDataService) SelectPage(query map[string]any) (int64, []model.PtNeConfigData) {
return r.ptNeConfigDataRepository.SelectPage(query)
}
// SelectConfigList 查询列表
func (r *PtNeConfigDataService) SelectList(param model.PtNeConfigData) []model.PtNeConfigData {
return r.ptNeConfigDataRepository.SelectList(param)
}
// SelectByIds 通过ID查询
func (r *PtNeConfigDataService) SelectById(paramId string) model.PtNeConfigData {
if paramId == "" {
return model.PtNeConfigData{}
}
neHosts := r.ptNeConfigDataRepository.SelectByIds([]string{paramId})
if len(neHosts) > 0 {
return neHosts[0]
}
return model.PtNeConfigData{}
}
// Insert 新增信息
func (r *PtNeConfigDataService) Insert(param model.PtNeConfigData) int64 {
return r.ptNeConfigDataRepository.Insert(param)
}
// Update 修改信息
func (r *PtNeConfigDataService) Update(param model.PtNeConfigData) int64 {
return r.ptNeConfigDataRepository.Update(param)
}
// DeleteByIds 批量删除信息
func (r *PtNeConfigDataService) DeleteByIds(paramIds []string) (int64, error) {
// 检查是否存在
ids := r.ptNeConfigDataRepository.SelectByIds(paramIds)
if len(ids) <= 0 {
return 0, fmt.Errorf("ptNeConfigData.noData")
}
if len(ids) == len(paramIds) {
rows := r.ptNeConfigDataRepository.DeleteByIds(paramIds)
return rows, nil
}
// 删除信息失败!
return 0, fmt.Errorf("delete fail")
}
// SaveAsDefault 系统网元配置保存为系统示例
func (r *PtNeConfigDataService) SaveAsDefault(neType, neId string) {
// 查询网元获取IP获取网元状态
neInfo := r.neInfoService.SelectNeInfoByNeTypeAndNeID(neType, neId)
if neInfo.NeId != neId || neInfo.IP == "" {
return
}
stubType := "0"
operaUserName := "admin"
deptId := "100"
confs := r.neConfigService.SelectList(neModel.NeConfig{NeType: neInfo.NeType})
for _, v := range confs {
// 查询是否存在记录
hasItems := r.SelectList(model.PtNeConfigData{
NeType: v.NeType,
StubType: stubType,
ParamName: v.ParamName,
ParamType: v.ParamType,
})
// 网元直连 获取网元配置信息
resData, err := neFetchlink.NeConfigInfo(neInfo, v.ParamName)
if err != nil {
continue
}
// 将json数据转字符串存储 data:[{},{}]
data, ok := resData["data"]
if !ok {
continue
}
paramDataByte, err := json.Marshal(data)
if err != nil {
continue
}
// 插入
if len(hasItems) == 0 {
r.Insert(model.PtNeConfigData{
CreateBy: operaUserName,
StubType: stubType,
NeType: v.NeType,
ParamName: v.ParamName,
ParamDisplay: v.ParamDisplay,
ParamType: v.ParamType,
ParamJson: string(paramDataByte),
DeptId: deptId,
})
}
// 更新
if len(hasItems) == 1 {
item := hasItems[0]
item.UpdateBy = operaUserName
item.ParamDisplay = v.ParamDisplay
item.ParamJson = string(paramDataByte)
item.DeptId = deptId
r.Update(item)
}
}
}
// ResetAsDefault 重置配置示例
// stubType2个人为班级示例 1班级为系统示例
func (r *PtNeConfigDataService) ResetAsDefault(operaUserName, stubType, neType, deptId string) {
rootStubType := "1"
if stubType == "1" {
rootStubType = "0"
}
if stubType == "2" {
rootStubType = "1"
}
ptConfs := r.SelectList(model.PtNeConfigData{StubType: rootStubType, NeType: neType})
for _, v := range ptConfs {
// 查询是否存在记录
hasItems := r.SelectList(model.PtNeConfigData{
CreateBy: operaUserName,
NeType: v.NeType,
StubType: stubType,
ParamName: v.ParamName,
ParamType: v.ParamType,
})
// 插入
if len(hasItems) == 0 {
r.Insert(model.PtNeConfigData{
CreateBy: operaUserName,
StubType: stubType,
NeType: v.NeType,
ParamName: v.ParamName,
ParamDisplay: v.ParamDisplay,
ParamType: v.ParamType,
ParamJson: v.ParamJson,
DeptId: deptId,
})
// 保留变更日志
changeLog := model.PtNeConfigDataLog{
CreateBy: operaUserName,
StubType: stubType,
NeType: v.NeType,
ParamName: v.ParamName,
ParamDisplay: v.ParamDisplay,
ParamType: v.ParamType,
OperaType: 0,
ParamJsonOld: "[]",
ParamJsonNew: v.ParamJson,
}
r.ptNeConfigDataLogRepository.Insert(changeLog)
}
// 更新
if len(hasItems) == 1 {
item := hasItems[0]
item.UpdateBy = operaUserName
item.ParamDisplay = v.ParamDisplay
item.ParamJson = v.ParamJson
item.DeptId = deptId
r.Update(item)
// 保留变更日志
changeLog := model.PtNeConfigDataLog{
CreateBy: operaUserName,
StubType: hasItems[0].StubType,
NeType: v.NeType,
ParamName: v.ParamName,
ParamDisplay: v.ParamDisplay,
ParamType: v.ParamType,
OperaType: 0,
ParamJsonOld: hasItems[0].ParamJson,
ParamJsonNew: v.ParamJson,
}
r.ptNeConfigDataLogRepository.Insert(changeLog)
}
}
}
// SelectByStubType 通过存根类型查询
func (r *PtNeConfigDataService) SelectByStubType(param model.PtNeConfigData) model.PtNeConfigData {
list := r.SelectList(param)
if len(list) == 0 && param.StubType != "1" {
param.CreateBy = ""
param.StubType = "1"
list = r.SelectList(param)
}
if len(list) == 0 && param.StubType != "0" {
param.CreateBy = ""
param.StubType = "0"
param.DeptId = "100"
list = r.SelectList(param)
}
var paraData model.PtNeConfigData
if len(list) > 0 {
paraData = list[0]
if err := json.Unmarshal([]byte(paraData.ParamJson), &paraData.ParamData); err != nil {
paraData.ParamData = []map[string]any{}
}
}
return paraData
}
// ApplyToNe 参数应用到网元
func (r *PtNeConfigDataService) ApplyToNe(paramUser, neType string) error {
ptConfs := r.SelectList(model.PtNeConfigData{CreateBy: paramUser, NeType: neType})
if len(ptConfs) == 0 {
return fmt.Errorf("NeConfigData Not Found")
}
// 找网元只有一套就固定neId:001
neInfo := r.neInfoService.SelectNeInfoByNeTypeAndNeID(neType, "001")
if neInfo.NeType != neType || neInfo.ID == "" {
return fmt.Errorf("NeInfo Not Found")
}
// 遍历去设置参数
for _, ptConf := range ptConfs {
if err := json.Unmarshal([]byte(ptConf.ParamJson), &ptConf.ParamData); err != nil {
ptConf.ParamData = []map[string]any{}
}
// 将json数据转字符串存储 [{},{}]
if len(ptConf.ParamData) == 0 {
continue
}
// 单层逐个更新
if ptConf.ParamType == "list" {
for k, v := range ptConf.ParamData[0] {
neFetchlink.NeConfigUpdate(neInfo, ptConf.ParamName, "", map[string]any{k: v})
}
}
// 多层逐个更新
if ptConf.ParamType == "array" {
// 删除原先配置
resData, err := neFetchlink.NeConfigInfo(neInfo, ptConf.ParamName)
if err != nil {
continue
}
if data, ok := resData["data"]; ok {
for i := 0; i < len(data.([]any)); i++ { // 倒序遍历
originIndex := i
newIndex := len(data.([]any)) - originIndex - 1
element := data.([]any)[newIndex]
loc := parse.Number(element.(map[string]any)["index"])
neFetchlink.NeConfigDelete(neInfo, ptConf.ParamName, fmt.Sprint(loc))
}
}
// 遍历新增
for _, v := range ptConf.ParamData {
loc := parse.Number(v["index"])
neFetchlink.NeConfigInstall(neInfo, ptConf.ParamName, fmt.Sprint(loc), v)
// 检查是否有array子层
for vk, vv := range v {
if reflect.TypeOf(vv).Kind() == reflect.Slice {
for i, item := range vv.([]any) {
data := item.(map[string]any)
data["index"] = i
neFetchlink.NeConfigInstall(neInfo, ptConf.ParamName, fmt.Sprintf("%v/%s/%v", loc, vk, i), data)
}
}
}
}
}
}
return nil
}
// ExportToExcel 导出网元的全部配置项数据
func (r *PtNeConfigDataService) ExportToExcel(operaUserName, fileName string) (string, error) {
confs := r.neConfigService.SelectNeConfigByNeType("*")
datas := r.ptNeConfigDataRepository.SelectList(model.PtNeConfigData{CreateBy: operaUserName})
return r.writeSheet(confs, datas, fileName)
}
// writeSheet 写入表格
func (r *PtNeConfigDataService) writeSheet(sheetData []neModel.NeConfig, cellData []model.PtNeConfigData, fileName string) (string, error) {
f := excelize.NewFile()
defer f.Close()
// 设置颜色填充
styleType, _ := f.NewStyle(&excelize.Style{Fill: excelize.Fill{
Type: "pattern",
Pattern: 1,
Color: []string{"F0F806"}, // RRGGBB 格式的
}})
styleRow, _ := f.NewStyle(&excelize.Style{Fill: excelize.Fill{
Type: "pattern",
Pattern: 1,
Color: []string{"D0CECE"}, // RRGGBB 格式的
}})
styleMore, _ := f.NewStyle(&excelize.Style{Font: &excelize.Font{
Color: "4472C4",
VertAlign: "center",
}})
// 网元工作簿行计数
sheetNameRows := make(map[string]int)
for _, sd := range sheetData {
_ = json.Unmarshal([]byte(sd.ParamJson), &sd.ParamData)
// 取到对应数据
var data model.PtNeConfigData
for _, cell := range cellData {
if cell.NeType == sd.NeType && cell.ParamName == sd.ParamName {
data = cell
break
}
}
if err := json.Unmarshal([]byte(data.ParamJson), &data.ParamData); err != nil || len(data.ParamData) == 0 {
continue
}
sheetName := sd.NeType
// 创建一个工作表
f.NewSheet(sheetName)
// 设置工作表上宽度为 20
// f.SetColWidth(sheetName, "B", "C", 20)
sheetRows := 1
if v, ok := sheetNameRows[sheetName]; ok && v != 0 {
sheetRows = v
}
// 合并标题单元格
f.MergeCell(sheetName, fmt.Sprintf("A%d", sheetRows), fmt.Sprintf("C%d", sheetRows))
f.SetCellStyle(sheetName, fmt.Sprintf("A%d", sheetRows), fmt.Sprintf("C%d", sheetRows), styleType)
// 标题
f.SetCellValue(sheetName, fmt.Sprintf("A%d", sheetRows), sd.ParamDisplay)
sheetRows += 1
// fmt.Println(sheetName, " ========= ", sd.ParamDisplay, " ==== ", sd.ParamType, len(data.ParamData))
itemData := []*[]any{}
if sd.ParamType == "list" {
itemData = append(itemData, &[]any{"Key", "Value"})
for _, v := range sd.ParamData {
name := v["name"].(string)
value := v["value"]
// 取到对应数据
for _, dv := range data.ParamData {
value = dv[name]
}
itemData = append(itemData, &[]any{v["display"], value})
}
}
if sd.ParamType == "array" {
rowTitle := []any{} // 行头
rowData := make([][]any, len(data.ParamData)) // 行数据
for _, v := range sd.ParamData {
rowTitle = append(rowTitle, v["display"])
name := v["name"].(string)
// 取到对应数据
for i, dv := range data.ParamData {
rowData[i] = append(rowData[i], dv[name])
}
}
itemData = append(itemData, &rowTitle)
for _, v := range rowData {
item := v
itemData = append(itemData, &item)
}
}
for i, row := range itemData {
// 行头样式
if i == 0 {
f.SetCellStyle(sheetName, fmt.Sprintf("A%d", sheetRows), fmt.Sprintf("A%d", sheetRows), styleRow)
}
f.SetSheetRow(sheetName, fmt.Sprintf("A%d", sheetRows), row)
// 存在array子层时转字符串
for i, s := range *row {
if reflect.ValueOf(s).Kind() == reflect.Slice {
if cell, err := excelize.CoordinatesToCellName(i+1, sheetRows); err == nil {
b, _ := json.Marshal(s)
f.SetCellDefault(sheetName, cell, "#")
f.SetCellStyle(sheetName, cell, cell, styleMore)
f.AddComment(sheetName, excelize.Comment{
Cell: cell,
Author: "OMC",
Text: string(b),
})
}
}
}
sheetRows += 1
}
// 记下次写入的行数
sheetRows += 2
sheetNameRows[sheetName] = sheetRows
}
// 默认工作表
f.SetCellValue("Sheet1", "A1", cellData[0].CreateBy)
f.MergeCell("Sheet1", "A1", "B1")
f.SetCellStyle("Sheet1", "A1", "B1", styleType)
f.SetCellValue("Sheet1", "A2", "5GC")
f.SetCellStyle("Sheet1", "A2", "A2", styleRow)
sheetNameData := []any{}
for k := range sheetNameRows {
sheetNameData = append(sheetNameData, k)
}
f.SetSheetRow("Sheet1", "A3", &sheetNameData)
// 上传资源路径
filePath := file.ParseUploadFileDir(uploadsubpath.EXPORT)
saveFilePath := filepath.ToSlash(filepath.Join(filePath, fileName))
// 创建文件目录
if err := os.MkdirAll(filepath.Dir(saveFilePath), 0775); err != nil {
return "", fmt.Errorf("failed to create save file %v", err)
}
// 根据指定路径保存文件
if err := f.SaveAs(saveFilePath); err != nil {
return "", fmt.Errorf("failed to save worksheet %v", err)
}
return saveFilePath, nil
}