462 lines
13 KiB
Go
462 lines
13 KiB
Go
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 重置配置示例
|
||
// stubType:2个人为班级示例 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), ¶Data.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
|
||
}
|