feat: 实训教学模块
This commit is contained in:
@@ -1,42 +1,461 @@
|
||||
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"
|
||||
)
|
||||
|
||||
// IPtNeConfigDataService 服务层接口
|
||||
type IPtNeConfigDataService interface {
|
||||
// SelectPage 根据条件分页查询字典类型
|
||||
SelectPage(query map[string]any) map[string]any
|
||||
|
||||
// SelectList 根据实体查询
|
||||
SelectList(param model.PtNeConfigData) []model.PtNeConfigData
|
||||
|
||||
// SelectByIds 通过ID查询
|
||||
SelectById(paramId string) model.PtNeConfigData
|
||||
|
||||
// Insert 新增信息
|
||||
Insert(param model.PtNeConfigData) string
|
||||
|
||||
// Update 修改信息
|
||||
Update(param model.PtNeConfigData) int64
|
||||
|
||||
// DeleteByIds 批量删除信息
|
||||
DeleteByIds(paramIds []string) (int64, error)
|
||||
|
||||
// SaveAsDefault 系统网元配置保存为系统示例
|
||||
SaveAsDefault(neType, neId string)
|
||||
|
||||
// ResetAsDefault 重置配置示例
|
||||
// stubType:2个人为班级示例 1班级为系统示例
|
||||
ResetAsDefault(operaUserName, stubType, neType, deptId string)
|
||||
|
||||
// SelectByStubType 通过存根类型查询
|
||||
SelectByStubType(param model.PtNeConfigData) model.PtNeConfigData
|
||||
|
||||
// ApplyToNe 参数应用到网元
|
||||
ApplyToNe(paramUser, neType string) error
|
||||
|
||||
// ExportToExcel 导出网元的全部配置项数据
|
||||
ExportToExcel(operaUserName, fileName string) (string, error)
|
||||
// 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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user