| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515 |
- package jobs
- import (
- "fmt"
- "fwh-toolbox-server/domain"
- "fwh-toolbox-server/repositories"
- "fwh-toolbox-server/utils/minio"
- "sort"
- "strings"
- "github.com/xuri/excelize/v2"
- "go.uber.org/zap"
- )
- type AutoUpdateConfigUpdateOrder struct {
- Order []string // 升级顺序
- Remark string // 用于特殊流程的备注,标准流程留空即可
- }
- // key = aPowerVersion组合, value = 升级流程
- type AutoUpdateConfigAPowerCombMap = map[string]AutoUpdateConfigUpdateOrder
- type AutoUpdateConfigEmsVersion struct {
- Config AutoUpdateConfigAPowerCombMap
- Remark string
- }
- // key = EmsVersion, value = aPowerVersionListData
- type AutoUpdateConfigEmsVersionMap = map[string]AutoUpdateConfigEmsVersion
- // key = aGateName, value = EmsVersionListData
- type AutoUpdateConfigAGateMap = map[string]AutoUpdateConfigEmsVersionMap
- // 组合函数
- func combinations(arr []string, k int) [][]string {
- var result [][]string
- path := make([]string, 0, k)
- var dfs func(start int)
- dfs = func(start int) {
- if len(path) == k {
- tmp := make([]string, k)
- copy(tmp, path)
- result = append(result, tmp)
- return
- }
- for i := start; i < len(arr); i++ {
- path = append(path, arr[i])
- dfs(i + 1)
- path = path[:len(path)-1]
- }
- }
- dfs(0)
- return result
- }
- // 所有组合函数
- func allCombinations(arr []string) [][]string {
- var result [][]string
- for k := 1; k <= len(arr); k++ {
- result = append(result, combinations(arr, k)...)
- }
- return result
- }
- // 生成自动升级配置文件,并保存到Minio
- func CreateAutoUpdateConfigFile(filePath, bucket, key string) (err error) {
- err = nil
- // 提取配置相关数据
- configOption, err := repositories.GetAutoUpdateConfigOption()
- if err != nil {
- zap.L().Error("GetAutoUpdateConfigOption failed.")
- return
- }
- packages := make(map[string]domain.AutoUpdatePackages)
- // system
- for _, fileName := range configOption.Packages.System {
- p, subErr := repositories.GetAutoUpdatePackages(fileName)
- if subErr != nil {
- err = subErr
- zap.L().Error("GetAutoUpdatePackages failed.", zap.String("err", subErr.Error()), zap.String("fileName", fileName))
- return
- }
- packages[fileName] = *p
- }
- // aGate
- for _, fileName := range configOption.Packages.AGate {
- p, subErr := repositories.GetAutoUpdatePackages(fileName)
- if subErr != nil {
- err = subErr
- zap.L().Error("GetAutoUpdatePackages failed.", zap.String("err", subErr.Error()), zap.String("fileName", fileName))
- return
- }
- packages[fileName] = *p
- }
- // subDevice
- for _, fileName := range configOption.Packages.SubDevice {
- p, subErr := repositories.GetAutoUpdatePackages(fileName)
- if subErr != nil {
- err = subErr
- zap.L().Error("GetAutoUpdatePackages failed.", zap.String("err", subErr.Error()), zap.String("fileName", fileName))
- return
- }
- packages[fileName] = *p
- }
- // others
- for _, fileName := range configOption.Packages.Others {
- p, subErr := repositories.GetAutoUpdatePackages(fileName)
- if subErr != nil {
- err = subErr
- zap.L().Error("GetAutoUpdatePackages failed.", zap.String("err", subErr.Error()), zap.String("fileName", fileName))
- return
- }
- packages[fileName] = *p
- }
- configs := make(map[string]domain.AutoUpdateConfig, len(configOption.AGateVersions))
- for _, aGateName := range configOption.AGateVersions {
- c, subErr := repositories.GetAutoUpdateConfig(aGateName)
- if subErr != nil {
- err = subErr
- zap.L().Error("GetAutoUpdateConfig failed.", zap.String("err", subErr.Error()), zap.String("aGateName", aGateName))
- return
- }
- configs[aGateName] = *c
- }
- // 将配置数据转换成升级流程map
- mapConfig := make(AutoUpdateConfigAGateMap, len(configs))
- for aGateName, cfg := range configs {
- emsVersionList := make(AutoUpdateConfigEmsVersionMap)
- for _, emsVer := range cfg.Config.DefaultType.EmsVersions {
- aPowerVersionList := make(AutoUpdateConfigAPowerCombMap)
- aPowerCombinations := allCombinations(cfg.Config.DefaultType.APowerVersions)
- if len(aPowerCombinations) == 0 {
- aPowerVersionList["null"] = AutoUpdateConfigUpdateOrder{
- Order: cfg.Config.DefaultType.UpdateOrder,
- Remark: "", // 标准流程留空
- }
- break
- }
- for _, comb := range aPowerCombinations {
- aPowerVersionList[strings.Join(comb, ",")] = AutoUpdateConfigUpdateOrder{
- Order: cfg.Config.DefaultType.UpdateOrder,
- Remark: "", // 标准流程留空
- }
- }
- emsVersionList[emsVer.Version] = AutoUpdateConfigEmsVersion{
- Config: aPowerVersionList,
- Remark: emsVer.Remark,
- }
- }
- for _, specialConfig := range cfg.Config.SpecialType {
- for _, emsVer := range specialConfig.EmsVersions {
- aPowerVersionList := make(AutoUpdateConfigAPowerCombMap)
- aPowerCombinations := allCombinations(specialConfig.APowerVersions)
- for _, comb := range aPowerCombinations {
- if specialConfig.UseDefaultUpdate {
- aPowerVersionList[strings.Join(comb, ",")] = AutoUpdateConfigUpdateOrder{
- Order: append(cfg.Config.DefaultType.UpdateOrder, specialConfig.SpecialUpdateOrder...),
- Remark: emsVer.Remark,
- }
- } else {
- aPowerVersionList[strings.Join(comb, ",")] = AutoUpdateConfigUpdateOrder{
- Order: specialConfig.SpecialUpdateOrder,
- Remark: emsVer.Remark,
- }
- }
- }
- if _, ok := emsVersionList[emsVer.Version]; ok {
- // EMS 版本已存在
- for comb, updateOrder := range aPowerVersionList {
- emsVersionList[emsVer.Version].Config[comb] = updateOrder
- }
- } else {
- // EMS 版本不存在
- emsVersionList[emsVer.Version] = AutoUpdateConfigEmsVersion{
- Config: aPowerVersionList,
- Remark: emsVer.Remark,
- }
- }
- }
- }
- mapConfig[aGateName] = emsVersionList
- }
- // 生成xlsx文件
- f := excelize.NewFile()
- defer func() {
- closeErr := f.Close()
- if closeErr != nil {
- zap.L().Error("Excel 文件close失败", zap.String("err", err.Error()))
- if err == nil {
- err = closeErr
- }
- }
- }()
- // 提取 key list 排序
- configAGateNameList := make([]string, 0, len(mapConfig))
- for key := range mapConfig {
- configAGateNameList = append(configAGateNameList, key)
- }
- sort.Strings(configAGateNameList)
- // f.DeleteSheet("Sheet1")
- f.SetSheetName("Sheet1", "说明")
- for _, aGateName := range configAGateNameList {
- sheetName := aGateName
- // 写标题行
- f.NewSheet(sheetName)
- f.SetCellValue(sheetName, "A1", "#")
- f.SetCellValue(sheetName, "B1", "升级类型")
- f.SetCellValue(sheetName, "C1", "aGate硬件")
- f.SetCellValue(sheetName, "D1", "EMS版本")
- f.SetCellValue(sheetName, "E1", "aPower硬件")
- f.SetCellValue(sheetName, "F1", "INV版本")
- f.SetCellValue(sheetName, "G1", "配置Type")
- f.SetCellValue(sheetName, "H1", "完整升级的步骤")
- f.SetCellValue(sheetName, "I1", "备注")
- var titleStyle int
- titleStyle, err = styleBoldBlueCenter(f)
- if err != nil {
- return
- }
- f.SetCellStyle(sheetName, "A1", "I1", titleStyle)
- // 调整列宽
- f.SetColWidth(sheetName, "A", "A", 3.93)
- f.SetColWidth(sheetName, "B", "B", 17.89)
- f.SetColWidth(sheetName, "C", "C", 13.99)
- f.SetColWidth(sheetName, "D", "D", 18.94)
- f.SetColWidth(sheetName, "E", "E", 15.19)
- f.SetColWidth(sheetName, "F", "F", 24.36)
- f.SetColWidth(sheetName, "G", "G", 15.47)
- f.SetColWidth(sheetName, "H", "H", 68.43)
- f.SetColWidth(sheetName, "I", "I", 47.86)
- // 数据从第二行开始
- row := 2
- configIndex := 1
- // 写入数据
- aGateConfig := mapConfig[aGateName]
- // 提取EMS版本表,并排序
- configEmsVersionList := make([]string, 0, len(aGateConfig))
- for key := range aGateConfig {
- configEmsVersionList = append(configEmsVersionList, key)
- }
- sort.Strings(configEmsVersionList)
- for emsVerIndex, emsVer := range configEmsVersionList {
- var rowStyleCenter int
- var rowStyleLeftWrap int
- if emsVerIndex%2 == 1 {
- rowStyleCenter, err = styleLightPinkCenter(f)
- if err != nil {
- return
- }
- rowStyleLeftWrap, err = styleLightPinkLeft(f)
- if err != nil {
- return
- }
- } else {
- rowStyleCenter, err = styleLightGreenCenter(f)
- if err != nil {
- return
- }
- rowStyleLeftWrap, err = styleLightGreenLeft(f)
- if err != nil {
- return
- }
- }
- emsVersionConfig := aGateConfig[emsVer]
- // 提取aPower版本表,并排序
- configAPowerCombList := make([]string, 0, len(emsVersionConfig.Config))
- for key := range emsVersionConfig.Config {
- configAPowerCombList = append(configAPowerCombList, key)
- }
- sort.Strings(configAPowerCombList)
- for _, aPowerComb := range configAPowerCombList {
- updateOrder := emsVersionConfig.Config[aPowerComb]
- // 生成升级步骤
- updateOrderList := make([]string, 0, len(updateOrder.Order))
- invVersion := ""
- for i, order := range updateOrder.Order {
- updateOrderList = append(updateOrderList, fmt.Sprintf("%d、%s: %s", i+1, packages[order].Title, order))
- invVersion = strings.Join(packages[order].InvVersion, "\n")
- }
- updateOrderStr := strings.Join(updateOrderList, "\n")
- // 获取INV版本
- // 获取备注
- remark := emsVersionConfig.Remark
- if updateOrder.Remark != "" {
- remark = updateOrder.Remark
- }
- f.SetCellValue(sheetName, fmt.Sprintf("A%d", row), fmt.Sprintf("%d", configIndex))
- f.SetCellValue(sheetName, fmt.Sprintf("B%d", row), "commissions升级")
- f.SetCellValue(sheetName, fmt.Sprintf("C%d", row), aGateName)
- f.SetCellValue(sheetName, fmt.Sprintf("D%d", row), emsVer)
- f.SetCellValue(sheetName, fmt.Sprintf("E%d", row), aPowerComb)
- f.SetCellValue(sheetName, fmt.Sprintf("F%d", row), invVersion)
- f.SetCellValue(sheetName, fmt.Sprintf("G%d", row), "not_eq_type")
- f.SetCellValue(sheetName, fmt.Sprintf("H%d", row), updateOrderStr)
- f.SetCellValue(sheetName, fmt.Sprintf("I%d", row), remark)
- f.SetCellStyle(sheetName, fmt.Sprintf("A%d", row), fmt.Sprintf("G%d", row), rowStyleCenter)
- f.SetCellStyle(sheetName, fmt.Sprintf("H%d", row), fmt.Sprintf("I%d", row), rowStyleLeftWrap)
- row++
- if emsVerIndex == len(configEmsVersionList)-1 {
- // 最后一个版本
- f.SetCellValue(sheetName, fmt.Sprintf("A%d", row), fmt.Sprintf("%d", configIndex))
- f.SetCellValue(sheetName, fmt.Sprintf("B%d", row), "commissions升级")
- f.SetCellValue(sheetName, fmt.Sprintf("C%d", row), aGateName)
- f.SetCellValue(sheetName, fmt.Sprintf("D%d", row), emsVer)
- f.SetCellValue(sheetName, fmt.Sprintf("E%d", row), aPowerComb)
- f.SetCellValue(sheetName, fmt.Sprintf("F%d", row), invVersion)
- f.SetCellValue(sheetName, fmt.Sprintf("G%d", row), "eq_type")
- f.SetCellValue(sheetName, fmt.Sprintf("H%d", row), "/")
- f.SetCellValue(sheetName, fmt.Sprintf("I%d", row), remark)
- } else {
- f.SetCellValue(sheetName, fmt.Sprintf("A%d", row), fmt.Sprintf("%d", configIndex))
- f.SetCellValue(sheetName, fmt.Sprintf("B%d", row), "commissions升级")
- f.SetCellValue(sheetName, fmt.Sprintf("C%d", row), aGateName)
- f.SetCellValue(sheetName, fmt.Sprintf("D%d", row), emsVer)
- f.SetCellValue(sheetName, fmt.Sprintf("E%d", row), aPowerComb)
- f.SetCellValue(sheetName, fmt.Sprintf("F%d", row), invVersion)
- f.SetCellValue(sheetName, fmt.Sprintf("G%d", row), "eq_type")
- f.SetCellValue(sheetName, fmt.Sprintf("H%d", row), updateOrderStr)
- f.SetCellValue(sheetName, fmt.Sprintf("I%d", row), remark)
- }
- f.SetCellStyle(sheetName, fmt.Sprintf("A%d", row), fmt.Sprintf("G%d", row), rowStyleCenter)
- f.SetCellStyle(sheetName, fmt.Sprintf("H%d", row), fmt.Sprintf("I%d", row), rowStyleLeftWrap)
- row++
- }
- }
- }
- // 保存到文件
- err = f.SaveAs(filePath)
- if err != nil {
- zap.L().Error("Excel文件save失败", zap.String("path", filePath), zap.String("err", err.Error()))
- return
- }
- // 上传到文件服务器
- if err = minio.UploadFileToBucket(bucket, filePath, key); err != nil {
- zap.L().Error("上传Excel文件失败", zap.String("path", filePath), zap.String("bucket", bucket), zap.String("key", key), zap.String("err", err.Error()))
- return
- }
- return
- }
- // 字体加粗,背景蓝色,文字居中
- func styleBoldBlueCenter(f *excelize.File) (int, error) {
- style, err := f.NewStyle(&excelize.Style{
- Font: &excelize.Font{
- Bold: true,
- },
- Fill: excelize.Fill{
- Type: "pattern",
- Color: []string{"#3399FF"}, // 蓝色
- Pattern: 1,
- },
- Alignment: &excelize.Alignment{
- Horizontal: "center",
- Vertical: "center",
- },
- // 黑色实线边框
- Border: []excelize.Border{
- {Type: "left", Color: "000000", Style: 1},
- {Type: "top", Color: "000000", Style: 1},
- {Type: "right", Color: "000000", Style: 1},
- {Type: "bottom", Color: "000000", Style: 1},
- },
- })
- if err != nil {
- zap.L().Error("StyleBoldBlueCenter error", zap.String("err", err.Error()))
- return 0, err
- }
- return style, nil
- }
- // 背景浅粉色、文字居中、自动换行
- func styleLightPinkCenter(f *excelize.File) (int, error) {
- style, err := f.NewStyle(&excelize.Style{
- Fill: excelize.Fill{
- Type: "pattern",
- Color: []string{"#FFDDEE"}, // 浅粉色
- Pattern: 1,
- },
- Alignment: &excelize.Alignment{
- Horizontal: "center",
- Vertical: "center",
- WrapText: true,
- },
- // 黑色实线边框
- Border: []excelize.Border{
- {Type: "left", Color: "000000", Style: 1},
- {Type: "top", Color: "000000", Style: 1},
- {Type: "right", Color: "000000", Style: 1},
- {Type: "bottom", Color: "000000", Style: 1},
- },
- })
- if err != nil {
- zap.L().Error("StyleLightPinkCenter error", zap.String("err", err.Error()))
- return 0, err
- }
- return style, nil
- }
- // 背景浅粉色、文字左对齐、自动换行
- func styleLightPinkLeft(f *excelize.File) (int, error) {
- style, err := f.NewStyle(&excelize.Style{
- Fill: excelize.Fill{
- Type: "pattern",
- Color: []string{"#FFDDEE"},
- Pattern: 1,
- },
- Alignment: &excelize.Alignment{
- Horizontal: "left",
- Vertical: "center",
- WrapText: true,
- },
- // 黑色实线边框
- Border: []excelize.Border{
- {Type: "left", Color: "000000", Style: 1},
- {Type: "top", Color: "000000", Style: 1},
- {Type: "right", Color: "000000", Style: 1},
- {Type: "bottom", Color: "000000", Style: 1},
- },
- })
- if err != nil {
- zap.L().Error("StyleLightPinkLeftWrap error", zap.String("err", err.Error()))
- return 0, err
- }
- return style, nil
- }
- // 背景浅绿色、文字居中、自动换行
- func styleLightGreenCenter(f *excelize.File) (int, error) {
- style, err := f.NewStyle(&excelize.Style{
- Fill: excelize.Fill{
- Type: "pattern",
- Color: []string{"#CCFFCC"}, // 浅绿色
- Pattern: 1,
- },
- Alignment: &excelize.Alignment{
- Horizontal: "center",
- Vertical: "center",
- WrapText: true,
- },
- // 黑色实线边框
- Border: []excelize.Border{
- {Type: "left", Color: "000000", Style: 1},
- {Type: "top", Color: "000000", Style: 1},
- {Type: "right", Color: "000000", Style: 1},
- {Type: "bottom", Color: "000000", Style: 1},
- },
- })
- if err != nil {
- zap.L().Error("StyleLightGreenCenter error", zap.String("err", err.Error()))
- return 0, err
- }
- return style, nil
- }
- // 背景浅绿色、文字左对齐、自动换行
- func styleLightGreenLeft(f *excelize.File) (int, error) {
- style, err := f.NewStyle(&excelize.Style{
- Fill: excelize.Fill{
- Type: "pattern",
- Color: []string{"#CCFFCC"},
- Pattern: 1,
- },
- Alignment: &excelize.Alignment{
- Horizontal: "left",
- Vertical: "center",
- WrapText: true,
- },
- // 黑色实线边框
- Border: []excelize.Border{
- {Type: "left", Color: "000000", Style: 1},
- {Type: "top", Color: "000000", Style: 1},
- {Type: "right", Color: "000000", Style: 1},
- {Type: "bottom", Color: "000000", Style: 1},
- },
- })
- if err != nil {
- zap.L().Error("StyleLightGreenLeftWrap error", zap.String("err", err.Error()))
- return 0, err
- }
- return style, nil
- }
|