diff --git a/attackevent/fw_data.go b/attackevent/fw_data.go index 847931c..b5313e5 100644 --- a/attackevent/fw_data.go +++ b/attackevent/fw_data.go @@ -232,7 +232,7 @@ func Fw_event(cookieStr, timeStr string) { if err := ss.Validate(); err != nil { log.Fatalf("验证文件时出错: %s", err) } - + log.Println("表格生成完成,保存文件:" + "防火墙安全事件" + time.Unix(tool.Timestamp("second"), 0).Format("20060102") + ".xlsx") if err := ss.SaveToFile("防火墙安全事件" + time.Unix(tool.Timestamp("second"), 0).Format("20060102") + ".xlsx"); err != nil { log.Fatalf("保存文件时出错: %s", err) } diff --git a/cache/image_0.png b/cache/image_0.png new file mode 100644 index 0000000..55ccd85 Binary files /dev/null and b/cache/image_0.png differ diff --git a/cache/image_1.png b/cache/image_1.png new file mode 100644 index 0000000..1a51e2d Binary files /dev/null and b/cache/image_1.png differ diff --git a/cache/image_2.png b/cache/image_2.png new file mode 100644 index 0000000..0527ce2 Binary files /dev/null and b/cache/image_2.png differ diff --git a/cache/image_3.png b/cache/image_3.png new file mode 100644 index 0000000..99a1761 Binary files /dev/null and b/cache/image_3.png differ diff --git a/cache/image_4.png b/cache/image_4.png new file mode 100644 index 0000000..d6d5630 Binary files /dev/null and b/cache/image_4.png differ diff --git a/cache/image_5.png b/cache/image_5.png new file mode 100644 index 0000000..7b2e144 Binary files /dev/null and b/cache/image_5.png differ diff --git a/cache/image_6.png b/cache/image_6.png new file mode 100644 index 0000000..04f04dc Binary files /dev/null and b/cache/image_6.png differ diff --git a/cache/image_7.png b/cache/image_7.png new file mode 100644 index 0000000..20ae9df Binary files /dev/null and b/cache/image_7.png differ diff --git a/cache/image_8.png b/cache/image_8.png new file mode 100644 index 0000000..5010a18 Binary files /dev/null and b/cache/image_8.png differ diff --git a/conf/test.yaml b/conf/test.yaml index 9cd40be..d990b3d 100644 --- a/conf/test.yaml +++ b/conf/test.yaml @@ -1,4 +1,4 @@ -cookie: vindex==43=12=0AB00=0R;supportLang=cn%2Cen;lang=cn;sessionid=2000012bb4019aa3ab12b847d96bbfe5f48d;loginid=7bea7ad577f67ab1f4d933aa3650d63e;2000012bb4019aa3ab12b847d96bbfe5f48d=true;abcd1234=true;login=false; +cookie: vindex==43=18=0AB00=0R;supportLang=cn%2Cen;lang=cn;sessionid=200001c7b0ac85156108afe97ee03544179f;loginid=32447a129283518387762bf5bb31a16e;200001c7b0ac85156108afe97ee03544179f=true;abcd1234=true;login=false; dtcloud_cookie: Hm_lvt_d980fb2543f406139975c7a72a5a0387=1740971050,1740974075,1741246647; ea6ee7ef65afa3fa0312817d0b12190e=787b65e4f93b05a0765ee0e7a6e2d24c; CECLOUD_OPS_SID=Tm1Sa01tUTRaakF0WW1FeE1DMDBNelUwTFdJMFl6QXROR1ppWWpWallqVXdNMlZsfGRYTmxjaTVvYkhjdVpIUmpiRzkxWkM1amIyMD0=; CECLOUD_OPS_CID=TmpObVpEbG1ORGd0WmpjNU1DMDBObUZtTFdKbVptWXRZVEJpWkRNd1pERTFOakk1fGRYTmxjaTVvYkhjdVpIUmpiRzkxWkM1amIyMD0= mysql: password: sLy1ZxZBEroGcoSv75P/xigUJ59/Yhsz1Z7896WzArcImdobrwg5+N6QEo4yT6CcpW22Y6bYy6a0ZWYAEzDaKZhOQG0odaUAv/SDP7JM7l7hH987XFJkUauaETu97Ev0kObsbS4laEiEg/+VG8fQrPuD2iRax1IWGXTKOtn+gHlyzSp016OhKOUUKKdW16OaC8AbVX9F3tVp10c2hsQNvLJl27MN5m3jXpoq9CTdcXsk15oHZVuIp3Kj9RWa8azpauiCPEKVE1KPvuJAhPYYakZBAdxGNU7Ye/YPZq68PJZHm6otEsaQxGJB1+DRNYh0oFWN9+aSYph6kAn0p5/c4g== diff --git a/donut_chart_with_labels.png b/donut_chart_with_labels.png index c0af9ae..5036f3a 100644 Binary files a/donut_chart_with_labels.png and b/donut_chart_with_labels.png differ diff --git a/hlw-3-14-20250314104058.doc b/hlw-3-14-20250314104058.doc new file mode 100644 index 0000000..1d8bc02 Binary files /dev/null and b/hlw-3-14-20250314104058.doc differ diff --git a/horizontal_bar_chart.png b/horizontal_bar_chart.png new file mode 100644 index 0000000..ccf06bf Binary files /dev/null and b/horizontal_bar_chart.png differ diff --git a/img/afc2000_1.png b/img/afc2000_1.png index 9d134ea..e9383f0 100644 Binary files a/img/afc2000_1.png and b/img/afc2000_1.png differ diff --git a/img/afc2000_2.png b/img/afc2000_2.png index 2e16653..3828e3c 100644 Binary files a/img/afc2000_2.png and b/img/afc2000_2.png differ diff --git a/img/capt.png b/img/capt.png index ed574e3..897b33b 100644 Binary files a/img/capt.png and b/img/capt.png differ diff --git a/img/hw_baolj.png b/img/hw_baolj.png index b7e5a11..e4e758c 100644 Binary files a/img/hw_baolj.png and b/img/hw_baolj.png differ diff --git a/img/hw_dtcloud_01.png b/img/hw_dtcloud_01.png index 630acf8..d915210 100644 Binary files a/img/hw_dtcloud_01.png and b/img/hw_dtcloud_01.png differ diff --git a/img/hw_dtcloud_02.png b/img/hw_dtcloud_02.png index 8884806..a962d77 100644 Binary files a/img/hw_dtcloud_02.png and b/img/hw_dtcloud_02.png differ diff --git a/img/hw_dtcloud_03.png b/img/hw_dtcloud_03.png index 63e143b..a3f0558 100644 Binary files a/img/hw_dtcloud_03.png and b/img/hw_dtcloud_03.png differ diff --git a/img/hw_dtcloud_04.png b/img/hw_dtcloud_04.png index 633e4dd..2fa853f 100644 Binary files a/img/hw_dtcloud_04.png and b/img/hw_dtcloud_04.png differ diff --git a/img/hw_dtcloud_05.png b/img/hw_dtcloud_05.png index 4685091..5bbc8dd 100644 Binary files a/img/hw_dtcloud_05.png and b/img/hw_dtcloud_05.png differ diff --git a/img/hw_dtcloud_06.png b/img/hw_dtcloud_06.png index 1cbc0bd..d88f0ce 100644 Binary files a/img/hw_dtcloud_06.png and b/img/hw_dtcloud_06.png differ diff --git a/img/hw_dtcloud_07.png b/img/hw_dtcloud_07.png index 2245089..3751c74 100644 Binary files a/img/hw_dtcloud_07.png and b/img/hw_dtcloud_07.png differ diff --git a/img/hw_dtcloud_man.png b/img/hw_dtcloud_man.png index c068dd0..4c9f7fb 100644 Binary files a/img/hw_dtcloud_man.png and b/img/hw_dtcloud_man.png differ diff --git a/img/hw_fw1.png b/img/hw_fw1.png index 8962ac8..90d513e 100644 Binary files a/img/hw_fw1.png and b/img/hw_fw1.png differ diff --git a/img/hw_tsgz.png b/img/hw_tsgz.png index 2c2a055..ffec800 100644 Binary files a/img/hw_tsgz.png and b/img/hw_tsgz.png differ diff --git a/img/zww_baolj.png b/img/zww_baolj.png index 8ea7a8f..97a0076 100644 Binary files a/img/zww_baolj.png and b/img/zww_baolj.png differ diff --git a/img/zww_dtcloud_01.png b/img/zww_dtcloud_01.png index 27c2705..b08afcd 100644 Binary files a/img/zww_dtcloud_01.png and b/img/zww_dtcloud_01.png differ diff --git a/img/zww_dtcloud_02.png b/img/zww_dtcloud_02.png index 908de7c..ced46c8 100644 Binary files a/img/zww_dtcloud_02.png and b/img/zww_dtcloud_02.png differ diff --git a/img/zww_dtcloud_03.png b/img/zww_dtcloud_03.png index 076eeca..645627a 100644 Binary files a/img/zww_dtcloud_03.png and b/img/zww_dtcloud_03.png differ diff --git a/img/zww_dtcloud_04.png b/img/zww_dtcloud_04.png index 1a2316b..7eb04ec 100644 Binary files a/img/zww_dtcloud_04.png and b/img/zww_dtcloud_04.png differ diff --git a/img/zww_dtcloud_05.png b/img/zww_dtcloud_05.png index 8598724..b3c8165 100644 Binary files a/img/zww_dtcloud_05.png and b/img/zww_dtcloud_05.png differ diff --git a/img/zww_dtcloud_06.png b/img/zww_dtcloud_06.png index 5f2e125..cafe353 100644 Binary files a/img/zww_dtcloud_06.png and b/img/zww_dtcloud_06.png differ diff --git a/img/zww_dtcloud_07.png b/img/zww_dtcloud_07.png index 5c1339b..fb2f04c 100644 Binary files a/img/zww_dtcloud_07.png and b/img/zww_dtcloud_07.png differ diff --git a/img/zww_dtcloud_man.png b/img/zww_dtcloud_man.png index 30af7a9..1f49253 100644 Binary files a/img/zww_dtcloud_man.png and b/img/zww_dtcloud_man.png differ diff --git a/img/zww_fw1.png b/img/zww_fw1.png index 87b52e2..4720548 100644 Binary files a/img/zww_fw1.png and b/img/zww_fw1.png differ diff --git a/img/zww_tsgz.png b/img/zww_tsgz.png index 12633ac..f225167 100644 Binary files a/img/zww_tsgz.png and b/img/zww_tsgz.png differ diff --git a/main.go b/main.go index 7f0d75b..cfcfeed 100644 --- a/main.go +++ b/main.go @@ -5,7 +5,6 @@ import ( "dt_automate/auth" _ "dt_automate/method" "dt_automate/tool" - "dt_automate/wps" _ "dt_automate/wps" "flag" "fmt" @@ -77,19 +76,19 @@ func main() { // method.HW_DTCLOUD() //截取运维中心的图片 // method.HW_BAOLJ() //截取堡垒机的图片 - //政务网区截图 + // // 政务网区截图 // method.ZWW_FW1() //截取防火墙的图片 // method.ZWW_TSGZ() //截取态势感知的图片 // method.ZWW_DTCLOUD() //截取运维中心的图片 // method.ZWWW_BAOLJ() //截取堡垒机的图片 // 互联网区运维巡检文档生成 - wps.HW_SYS_Word() //运维平台word文档生成 - //政务网区运维巡检文档生成 - wps.ZWW_SYS_Word() //运维平台word文档生成 - //安全巡检文档生成 + // wps.HW_SYS_Word() //运维平台word文档生成 + // //政务网区运维巡检文档生成 + // wps.ZWW_SYS_Word() //运维平台word文档生成 + // // 安全巡检文档生成 // wps.SAFET_Word() //安全巡检文档生成 //安全事件表格生成(需要先执行互联网区防火墙截图) - // attackevent.Fw_event(attackevent.HW_fw1_cookie(), "2025-03-12") //将防火墙安全事件存放到xlsx文件中 + // attackevent.Fw_event(attackevent.HW_fw1_cookie(), "2025-03-13") //将防火墙安全事件存放到xlsx文件中 //nessus的csv文件生成docx报告 // nessus.CSV_damo() //翻译模块调用腾讯xt翻译月500万字限制 @@ -101,7 +100,9 @@ func main() { // dtcloud.Memory() //获取单个ecs的memory使用情况 // dtcloud.Cpu() ///获取单个ecs的cpu使用情况 // dtcloud.TenantList() //获取租户列表(完成) - // damo.Damo() + //获取docx文档中所有的图片 + // wps.Weekly_get_img("") + // wps.DrawHorizontalBarChart() } } else { diff --git a/method/hw_fw1.go b/method/hw_fw1.go index 7580a3c..413f1ac 100644 --- a/method/hw_fw1.go +++ b/method/hw_fw1.go @@ -78,12 +78,12 @@ func HW_FW1() { document.body.appendChild(div); `, nil) page.Locator(`#leftmenu-body tr[data-recordid="M_ThreatLog"] div.x-grid-cell-inner.x-grid-cell-inner-treecolumn a.x-tree-node-text`).Click() - page.WaitForTimeout(3000) - page.Locator(`#button-1174-btnEl`).Click() page.WaitForTimeout(2000) + page.Locator(`#button-1174-btnEl`).Click() + page.WaitForTimeout(1000) page.Locator(`#combobox-1302-bodyEl #combobox-1302-inputEl`).Click() page.WaitForTimeout(1000) - page.Locator(`#boundlist-1330-listEl li[title="Untrust"]`).Click() + page.Locator(`#boundlist-1330-listEl li[title="yunwei"]`).Click() page.WaitForTimeout(500) page.Locator(`#combobox-1303-bodyEl #combobox-1303-inputEl`).Click() page.WaitForTimeout(500) diff --git a/temp/weekly_temp.xlsx b/temp/weekly_temp.xlsx deleted file mode 100644 index b185a9a..0000000 Binary files a/temp/weekly_temp.xlsx and /dev/null differ diff --git a/wps/system_word.go b/wps/system_word.go index 8e0d237..ca760f9 100644 --- a/wps/system_word.go +++ b/wps/system_word.go @@ -20,9 +20,9 @@ func HW_SYS_Word() { for _, p := range doc.Paragraphs() { paragraphs = append(paragraphs, p) } - // This sample document uses structured document tags, which are not common - // except for in document templates. Normally you can just iterate over the - // document's paragraphs. + //此示例文档使用了不常见的结构化文档标记 + //文档模板中的除外。通常情况下,您只需迭代 + //文档的段落。 for _, sdt := range doc.StructuredDocumentTags() { for _, p := range sdt.Paragraphs() { paragraphs = append(paragraphs, p) diff --git a/wps/weekly_word.go b/wps/weekly_word.go index 62f1404..84c14df 100644 --- a/wps/weekly_word.go +++ b/wps/weekly_word.go @@ -1,88 +1,7 @@ package wps -import ( - "fmt" - "math" +import "log" - "github.com/fogleman/gg" -) - -func Weekly_word() { - const ( - width, height = 900, 700 - centerX, centerY = width / 2, height / 2 - radius = 180 - ) - - // 初始化绘图上下文 - dc := gg.NewContext(width, height) - dc.SetRGB(1, 1, 1) // 设置背景为白色 - dc.Clear() - - // 数据示例:每个部分的角度、标签和颜色 - data := []struct { - angle float64 - label string - color string - }{ - {275, "1、敏感信息泄露:275", "#FF6384"}, // 红色 - {75, "2、代码执行:75", "#36A2EB"}, // 蓝色 - {68, "3、命令注入:68", "#FFCE56"}, // 黄色 - {47, "4、目录遍历:47", "#4bc0c0"}, // 绿色 - {28, "5、安全措施绕过:28", "#c12c1f"}, // 红色 - {12, "6、HTTP弱口令尝试:12", "#779649"}, // 绿色 - {10, "7、SQL注入:10", "#9BA0C9"}, // 绿色 - } - - // 加载支持中文的字体 - fontPath := "font/SIMFANG.TTF" // 确保字体文件在当前目录或指定路径下 - fontSize := 16.0 - if err := dc.LoadFontFace(fontPath, fontSize); err != nil { - panic(err) - } - - // 绘制图表标题 - dc.SetRGB(0, 0, 0) - dc.DrawString("安全事件类型分布Top10", float64(centerX-80), float64(centerY-250)) - dc.DrawString("安全事件类型分布Top10", float64(centerX-400), float64(centerY-300)) - - // 绘制圆环图表 - startAngle := 0.0 - for _, d := range data { - endAngle := startAngle + d.angle - drawDonutSegment(dc, centerX, centerY, radius, startAngle, endAngle, d.color) - startAngle = endAngle - } - - // 在右侧绘制数据标签 - labelX := float64(centerX + radius + 50) - labelY := float64(centerY - (len(data)*20)/2) - for _, d := range data { - // 绘制颜色一致的小圆点 - drawColorDot(dc, labelX, labelY, d.color) - // 绘制标签文本 - dc.DrawString(d.label, labelX+15, labelY) - labelY += 20 - } - - // 保存为图片 - dc.SavePNG("donut_chart_with_labels.png") - fmt.Println("圆环图表已保存为 donut_chart_with_labels.png") -} - -// 绘制圆环的部分 -func drawDonutSegment(dc *gg.Context, cx, cy, radius float64, startAngle, endAngle float64, color string) { - dc.SetHexColor(color) - dc.NewSubPath() - dc.DrawArc(cx, cy, radius, startAngle*math.Pi/180, endAngle*math.Pi/180) - dc.DrawArc(cx, cy, radius-50, endAngle*math.Pi/180, startAngle*math.Pi/180) - dc.ClosePath() - dc.Fill() -} - -// 绘制颜色一致的小圆点 -func drawColorDot(dc *gg.Context, x, y float64, color string) { - dc.SetHexColor(color) - dc.DrawCircle(x, y, 5) - dc.Fill() +func Weekly_word(str string) { + log.Println("周报") } diff --git a/wps/word_public.go b/wps/word_public.go index 1ac0448..5c4cd68 100644 --- a/wps/word_public.go +++ b/wps/word_public.go @@ -1,12 +1,20 @@ package wps import ( + "fmt" + "image" + "image/jpeg" + "image/png" "log" + "math" + "os" + "sort" "strings" "github.com/Esword618/unioffice/common" "github.com/Esword618/unioffice/document" "github.com/Esword618/unioffice/measurement" + "github.com/fogleman/gg" ) // 设置unidoc key @@ -59,3 +67,210 @@ func Replaceimg_1(r document.Run, doc *document.Document, path_img string) { anchored.SetSize(5.75*measurement.Inch, 3.2*measurement.Inch) log.Println("插入图片:", path_img) } + +// 获取文档中的图片 +func Weekly_get_img(file_img_path string) { + doc, err := document.Open(file_img_path) + if err != nil { + log.Panic("打开文件失败", err) + } + // 遍历文档中的所有关系,查找图片 + // 遍历文档中的所有图片 + // 遍历文档中的所有图片 + for idx, img := range doc.Images { + // 获取图片的二进制数据 + imgData := img.Path() + file, err := os.Open(imgData) + if err != nil { + log.Println("打开文件失败", err) + } + defer file.Close() + img, format, err := image.Decode(file) + if err != nil { + log.Println("解码图片失败", err) + } + // 生成图片文件名 + imgFileName := fmt.Sprintf("image_%d.%s", idx, format) + // 打开文件以写入图片数据 + outFile, err := os.Create("cache/" + imgFileName) + if err != nil { + log.Printf("无法创建文件 %s: %v", imgFileName, err) + continue + } + defer outFile.Close() + // 根据图片格式进行编码 + switch format { + case "jpeg": + err = jpeg.Encode(outFile, img, nil) + case "png": + err = png.Encode(outFile, img) + default: + log.Printf("不支持的图片格式 %s", format) + continue + } + if err != nil { + log.Printf("无法保存图片 %s: %v", imgFileName, err) + } else { + log.Printf("图片 %s 已保存", "cace/"+imgFileName) + } + log.Println(imgData) + } +} + +// 生成环形图表 +func Weekly_chart() { + const ( + width, height = 900, 700 + centerX, centerY = width / 2, height / 2 + radius = 180 + ) + + // 初始化绘图上下文 + dc := gg.NewContext(width, height) + dc.SetRGB(1, 1, 1) // 设置背景为白色 + dc.Clear() + + // 数据示例:每个部分的角度、标签和颜色 + data := []struct { + angle float64 + label string + color string + }{ + {275, "1、敏感信息泄露:275", "#FF6384"}, // 红色 + {75, "2、代码执行:75", "#36A2EB"}, // 蓝色 + {68, "3、命令注入:68", "#FFCE56"}, // 黄色 + {47, "4、目录遍历:47", "#4bc0c0"}, // 绿色 + {28, "5、安全措施绕过:28", "#c12c1f"}, // 红色 + {12, "6、HTTP弱口令尝试:12", "#779649"}, // 绿色 + {10, "7、SQL注入:10", "#9BA0C9"}, // 绿色 + } + + // 加载支持中文的字体 + fontPath := "font/SIMFANG.TTF" // 确保字体文件在当前目录或指定路径下 + fontSize := 16.0 + if err := dc.LoadFontFace(fontPath, fontSize); err != nil { + panic(err) + } + + // 绘制图表标题 + dc.SetRGB(0, 0, 0) + dc.DrawString("安全事件类型分布Top10", float64(centerX-80), float64(centerY-250)) + dc.DrawString("安全事件类型分布Top10", float64(centerX-400), float64(centerY-300)) + + // 绘制圆环图表 + startAngle := 0.0 + for _, d := range data { + endAngle := startAngle + d.angle + drawDonutSegment(dc, centerX, centerY, radius, startAngle, endAngle, d.color) + startAngle = endAngle + } + + // 在右侧绘制数据标签 + labelX := float64(centerX + radius + 50) + labelY := float64(centerY - (len(data)*20)/2) + for _, d := range data { + // 绘制颜色一致的小圆点 + drawColorDot(dc, labelX, labelY-5, d.color) + // 绘制标签文本 + dc.DrawString(d.label, labelX+15, labelY) + labelY += 20 + } + + // 保存为图片 + dc.SavePNG("donut_chart_with_labels.png") + fmt.Println("圆环图表已保存为 donut_chart_with_labels.png") +} + +// 绘制圆环的部分 +func drawDonutSegment(dc *gg.Context, cx, cy, radius float64, startAngle, endAngle float64, color string) { + dc.SetHexColor(color) + dc.NewSubPath() + dc.DrawArc(cx, cy, radius, startAngle*math.Pi/180, endAngle*math.Pi/180) + dc.DrawArc(cx, cy, radius-60, endAngle*math.Pi/180, startAngle*math.Pi/180) + dc.ClosePath() + dc.Fill() +} + +// 绘制颜色一致的小圆点 +func drawColorDot(dc *gg.Context, x, y float64, color string) { + dc.SetHexColor(color) + dc.DrawCircle(x, y, 5) + dc.Fill() +} + +// 绘制横向条形图 +func DrawHorizontalBarChart() { + const ( + width = 800 + height = 400 + barHeight = 20 + margin = 130 + ) + + // 初始化绘图上下文 + dc := gg.NewContext(width, height) + dc.SetRGB(1, 1, 1) // 设置背景为白色 + dc.Clear() + + // 加载支持中文的字体 + fontPath := "font/SIMFANG.TTF" // 确保字体文件在当前目录或指定路径下 + fontSize := 16.0 + if err := dc.LoadFontFace(fontPath, fontSize); err != nil { + panic(err) + } + + // 绘制图表标题 + dc.SetRGB(0, 0, 0) + dc.DrawStringAnchored("被外网攻击IP Top10", float64(width/2), 40, 0.5, 0) + + // 定义数据和标签 + data := []float64{100, 200, 150, 250, 300} + labels := []string{"11.2.144.18", "11.2.144.139", "11.2.144.156", "11.2.144.127", "11.2.144.129"} + // 创建一个索引数组 + indices := make([]int, len(data)) + for i := range indices { + indices[i] = i + } + + // 对索引数组进行排序,排序依据是 data 数组中的值从大到小 + sort.Slice(indices, func(i, j int) bool { + return data[indices[i]] > data[indices[j]] + }) + + // 根据排序后的索引重新排列 data 和 labels 数组 + sortedData := make([]float64, len(data)) + sortedLabels := make([]string, len(labels)) + for i, idx := range indices { + sortedData[i] = data[idx] + sortedLabels[i] = labels[idx] + } + // 计算最大数据值 + maxValue := 0.0 + for _, value := range data { + if value > maxValue { + maxValue = value + } + } + + // 绘制条形图 + for i, value := range sortedData { + y := float64(margin + i*(barHeight+15)) + barWidth := (value / maxValue) * float64(width-2*margin) + + // 绘制条形 + dc.SetRGB(0.2, 0.4, 0.8) + dc.DrawRectangle(float64(margin), y, barWidth, float64(barHeight)) + dc.Fill() + + // 绘制标签 + dc.SetRGB(0, 0, 0) + dc.DrawStringAnchored(sortedLabels[i], float64(margin-10), y+barHeight/2, 1, 0.5) + + // 绘制数值 + dc.DrawStringAnchored(fmt.Sprintf("%d", int(value)), float64(margin+barWidth+10), y+barHeight/2, 0, 0.5) + } + + // 保存为图片 + dc.SavePNG("horizontal_bar_chart.png") + fmt.Println("横向条形图已保存为 horizontal_bar_chart.png") +} diff --git a/zww-3-14-20250314104006.doc b/zww-3-14-20250314104006.doc new file mode 100644 index 0000000..fb00444 Binary files /dev/null and b/zww-3-14-20250314104006.doc differ