CrazyIter_Bin 2 سال پیش
والد
کامیت
ce3bb63ec8

+ 53 - 7
HTEXScreen/Controllers/ScreenController.cs

@@ -1,7 +1,11 @@
-using Microsoft.AspNetCore.Mvc;
+using HTEXScreen.Service;
+using Microsoft.AspNetCore.Mvc;
  
 using PuppeteerSharp;
 using System.Runtime.InteropServices;
+using System.Text;
+using System.Text.Json;
+using System.Text.RegularExpressions;
 using System.Web;
 
 namespace HTEXScreen.Controllers
@@ -10,11 +14,37 @@ namespace HTEXScreen.Controllers
     [Route("screen")]
     public class ScreenController : ControllerBase
     {
+        private readonly AzureStorageFactory _azureStorage;
         private readonly  HttpClient _httpClient;
-        public ScreenController(HttpClient httpClient) {
+        public ScreenController(HttpClient httpClient, AzureStorageFactory  azureStorage) {
             _httpClient = httpClient;
+            _azureStorage = azureStorage;
+        }
+        [HttpPost("testbase64")]
+        public async Task<IActionResult> TestBase64(JsonElement json ) {
+            JsonSerializerOptions option = new System.Text.Json.JsonSerializerOptions
+            {
+                Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping
+            };
+            string name = "dataid";
+            var reg = $"(?<=\\b{name}=)[^&]*";
+            Regex regex = new Regex(reg);
+            string decode= HttpUtility.UrlDecode("https://localhost:7298/swagger/index.html?dataid=%E5%BC%A0%E5%90%8C%E5%AD%A6&bs64=1234567&dataid=%E6%9D%8E%E5%90%8C%E5%AD%A6");
+            Match match= Regex.Match(decode, reg);
+            string a = "";
+            while (match.Success)
+            {
+                a =a+$"{match.Value}";
+                match = match.NextMatch();
+            }
+            string s = JsonSerializer.Serialize(json, option);
+            string das= HttpUtility.UrlEncode(s,Encoding.UTF8);
+            byte[] byts = Encoding.UTF8.GetBytes(s);
+            var rdata = Convert.ToBase64String(byts);
+            byte[] bs = Convert.FromBase64String(rdata);
+            string data = Encoding.UTF8.GetString(bs);
+            return Ok(new { a, rdata,das });
         }
-
         [HttpGet("download")]
         public async Task<IActionResult> Download([FromQuery] ScreenshotDto screenshot) {
             try {
@@ -157,7 +187,7 @@ namespace HTEXScreen.Controllers
                 int pagesize = 20;
                 if (screenshot.urls.Count <= pagesize)
                 {
-                      await PageToPdfStream(screenshot.urls,browser,viewPortOptions,pdfOptions);
+                      await PageToPdfStream(screenshot.urls,screenshot.fileNameKey,browser,viewPortOptions,pdfOptions);
                 }
                 else
                 {
@@ -166,7 +196,7 @@ namespace HTEXScreen.Controllers
                     for (int i = 0; i < pages; i++)
                     {
                         var lists = screenshot.urls.Skip((i) * pagesize).Take(pagesize).ToList();
-                        tasks.Add(PageToPdfStream(lists, browser, viewPortOptions, pdfOptions));
+                        tasks.Add(PageToPdfStream(lists, screenshot.fileNameKey, browser, viewPortOptions, pdfOptions));
                     }
                     await Task.WhenAll(tasks);
                 }
@@ -195,7 +225,7 @@ namespace HTEXScreen.Controllers
                 return BadRequest($"{ex.Message}\n{ex.StackTrace}");
             }
         }
-        private async Task PageToPdfStream(List<string> urls, Browser browser, ViewPortOptions viewPortOptions, PdfOptions pdfOptions)
+        private async Task PageToPdfStream(List<string> urls,string fileNameKey, Browser browser, ViewPortOptions viewPortOptions, PdfOptions pdfOptions)
         {
             List<Task<Page>> pages = new List<Task<Page>>();
             urls.ForEach(x => {
@@ -214,10 +244,25 @@ namespace HTEXScreen.Controllers
             var responses_tasks = await Task.WhenAll(responses);
             //List<Task<Stream>> streams = new List<Task<Stream>>();
             List<Task> tasks = new List<Task>();
+            List<Task<string>> uploads = new List<Task<string>>();
             foreach (var page_task in page_tasks) {
                 string url = page_task.Url;
+                string[] paths=  HttpUtility.UrlDecode(url).Split("/");
+                var reg = $"(?<=\\b{fileNameKey}=)[^&]*";
+                Regex regex = new Regex(reg);
+                string decode = HttpUtility.UrlDecode(url);
+                Match match = Regex.Match(decode, reg);
+                string id = "";
+                while (match.Success)
+                {
+                    id = id + $"{match.Value}";
+                    match = match.NextMatch();
+                }
+                //需要解析参数。paths[paths.Length-1]
                 Stream stream = await page_task.PdfStreamAsync(pdfOptions);
+                uploads.Add(_azureStorage.GetBlobContainerClient("teammodelos").UploadFileByContainer(stream, "artreport", $"{id}.pdf", true));
             }
+            await Task.WhenAll(uploads);
             //page_tasks.ToList().ForEach(x => {
             //    //string file = $"E://pdfs//{Guid.NewGuid()}.pdf";
             //     string a =  x.Url;
@@ -248,7 +293,7 @@ namespace HTEXScreen.Controllers
             var responses_tasks = await Task.WhenAll(responses);
             List<Task>  tasks = new List<Task>();
             page_tasks.ToList().ForEach(x => {
-                string file = $"E://pdfs//{Guid.NewGuid()}.pdf";
+                string file = $"{Guid.NewGuid()}.pdf";
                 tasks.Add(x.PdfAsync(file, pdfOptions));
             });
             await Task.WhenAll(tasks);
@@ -270,5 +315,6 @@ namespace HTEXScreen.Controllers
         public int height { get; set; } = 1080;
         public string? url { get; set; }
         public List<string> urls { get; set; } = new List<string>();
+        public string? fileNameKey { get; set; }
         public int delay { get; set; }
     }

+ 5 - 0
HTEXScreen/Program.cs

@@ -1,3 +1,6 @@
+using HTEXScreen.Service;
+using Microsoft.Extensions.Configuration;
+
 var builder = WebApplication.CreateBuilder(args);
 
 // Add services to the container.
@@ -7,6 +10,8 @@ builder.Services.AddControllers();
 builder.Services.AddEndpointsApiExplorer();
 builder.Services.AddSwaggerGen();
 builder.Services.AddHttpClient();
+string ConnectionString = builder.Configuration.GetValue<string>("Azure:Storage:ConnectionString");
+builder.Services.AddAzureStorage(ConnectionString);
 var app = builder.Build();
 
 // Configure the HTTP request pipeline.

+ 11 - 0
HTEXScreen/Service/AzureStorageBlobExtensions.cs

@@ -1,10 +1,21 @@
 using Azure.Storage.Blobs;
 using Azure.Storage.Blobs.Models;
+using Microsoft.Extensions.DependencyInjection.Extensions;
 
 namespace HTEXScreen.Service
 {
     public static class AzureStorageBlobExtensions
     {
+        public static IServiceCollection AddAzureStorage(this IServiceCollection services, string connectionString, string name = "Default")
+        {
+            if (services == null) throw new ArgumentNullException(nameof(services));
+            if (connectionString == null) throw new ArgumentNullException(nameof(connectionString));
+
+            services.TryAddSingleton<AzureStorageFactory>();
+            services.Configure<AzureStorageFactoryOptions>(name, o => { o.Name = name; o.StorageAccountConnectionString = connectionString; });
+
+            return services;
+        }
         /// <summary>
         /// 系统管理员 资源,题目关联,htex关联,学习活动学生上传文件关联,基本信息关联,教室平面图关联,评测冷数据关联
         /// "system": [ "res", "item", "htex", "task", "info", "room", "exam" ],

+ 447 - 0
HTEXScreen/api-count.html

@@ -0,0 +1,447 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <meta charset="utf-8" />
+    <title>Api Analysis</title>
+    <!-- 引入刚刚下载的 ECharts 文件 -->
+    <script src="https://cdn.bootcdn.net/ajax/libs/echarts/5.3.3/echarts.min.js"></script>
+    <style>
+        body {
+            background-color: #ededed;
+        }
+
+        div {
+            background-color: #fff;
+            border-radius: 10px;
+        }
+    </style>
+</head>
+
+<body>
+    <!-- 为 ECharts 准备一个定义了宽高的 DOM  -->
+    <div id="minChart" style="width: 100%;height:450px;margin-bottom: 20px;"></div>
+    <div id="regionChart" style="width: 100%;height:450px;margin-bottom: 20px;"></div>
+    <div style="display: flex;padding:20px 0">
+        <div id="apiChart" style="width: 50%;height:450px;"></div>
+        <div id="ipChart" style="width: 50%;height:450px;"></div>
+    </div>
+    <script type="text/javascript">
+        var params = getUrlParam()
+        var originUrl = params.get('url')
+        var hourStr = params.get('time') || ''
+        var total=0;
+        var originJson = null
+        getJson(originUrl)
+        // 截取参数
+        function getUrlParam() {
+            let that = this
+            let url = window.location.href
+            let p = url.split('?')[1]
+            let params = new URLSearchParams(p)
+            return params
+        }
+        // 获取JSON数据
+        function getJson(originUrl) {
+            var xhr = new XMLHttpRequest();
+            var formData = new FormData();
+            xhr.open('get', originUrl);
+            xhr.onload = function (e) {
+                originJson = JSON.parse(e.currentTarget.response)
+                console.log(originJson);
+                initApiCharts(originJson);
+                initIpCharts(originJson);
+                initMinCharts(originJson);
+                initRegionCharts(originJson);
+            };
+            xhr.send(formData);
+        }
+        // 初始化API统计
+        function initApiCharts(originJson) {
+            // 基于准备好的dom,初始化echarts实例
+            var apiChart = echarts.init(document.getElementById('apiChart'));
+            var apiOption = {
+                title: {
+                    text: 'Api访问量统计饼图',
+                    left: 'center',
+                    bottom: 15,
+                    textStyle: {
+                       // fontFamily: "'NotoSerif', '微软正黑体', 'Microsoft JhengHei UI', 'Microsoft JhengHei', Sans-serif",
+                        color: '#000',
+                        fontSize: '18'
+                    }
+                },
+                animation: false,
+                tooltip: {
+                    trigger: 'item'
+                },
+                legend: {
+                    top: '0%',
+                    left: 'center',
+                    orient: 'horizontal',
+                    type: 'scroll',
+                    pageIconColor: '#333',
+                    pageIconInactiveColor: '#333',
+                    left: 'center',
+                    align: 'auto',
+                },
+                series: [
+                    {
+                        name: 'Api访问量统计',
+                        type: 'pie',
+                        radius: ['40%', '70%'],
+                        itemStyle: {
+                            borderRadius: 10,
+                            borderColor: '#ddd',
+                            borderWidth: 2
+                        },
+                        label: {
+                            formatter: "{d}%",
+                        },
+                        labelLine: {
+                            length: 1,
+                            length2: 20,
+                        },
+                        emphasis: {
+                            label: {
+                                show: true,
+                                fontSize: '40',
+                                fontWeight: 'bold'
+                            }
+                        },
+                        data: originJson.apiCnt.map(i => {
+                            return {
+                                value: i.count,
+                                name: i.api
+                            }
+                        })
+                    }
+                ]
+            }
+            apiChart.setOption(apiOption);
+            window.addEventListener('resize', function () {
+                apiChart.resize()
+            })
+        }
+        // 初始化ip访问统计
+        function initIpCharts(originJson) {
+            // 基于准备好的dom,初始化echarts实例
+            var ipChart = echarts.init(document.getElementById('ipChart'));
+            var ipOption = {
+                title: {
+                    text: 'IP来源统计饼图',
+                    left: 'center',
+                    bottom: 15,
+                    textStyle: {
+                        //fontFamily: "'NotoSerif', '微软正黑体', 'Microsoft JhengHei UI', 'Microsoft JhengHei', Sans-serif",
+                        color: '#000',
+                        fontSize: '18'
+                    }
+                },
+                animation: false,
+                tooltip: {
+                    trigger: 'item'
+                },
+                legend: {
+                    top: '0%',
+                    left: 'center',
+                    orient: 'horizontal',
+                    type: 'scroll',
+                    pageIconColor: '#333',
+                    pageIconInactiveColor: '#333',
+                    left: 'center',
+                    align: 'auto',
+                },
+                series: [
+                    {
+                        name: 'IP来源统计',
+                        type: 'pie',
+                        radius: ['40%', '70%'],
+                        itemStyle: {
+                            borderRadius: 10,
+                            borderColor: '#fff',
+                            borderWidth: 2
+                        },
+                        label: {
+                            formatter: "{d}%",
+                        },
+                        labelLine: {
+                            length: 1,
+                            length2: 20,
+                        },
+                        emphasis: {
+                            label: {
+                                show: true,
+                                fontSize: '40',
+                                fontWeight: 'bold'
+                            }
+                        },
+                        data: originJson.ipCnt.map(i => {
+                            return {
+                                value: i.count,
+                                name: i.ip
+                            }
+                        })
+                    }
+                ]
+            }
+            ipChart.setOption(ipOption);
+            window.addEventListener('resize', function () {
+                ipChart.resize()
+            })
+        }
+        // 初始化分钟访问量折线图
+        function initMinCharts(originJson) {
+            // 基于准备好的dom,初始化echarts实例
+            var minChart = echarts.init(document.getElementById('minChart'));
+            var data_val = new Array(60).fill(0),
+                xAxis_val = new Array(60).fill(0).map((i, index) => index + '');
+            originJson.minCnts.forEach((item, index) => {
+                data_val[+item.minute] = item.cnt
+                total+=item.cnt
+            })
+            var minOption = {
+                title: {
+                    text: hourStr + ' 访问统计分析('+total+')',
+                    left: 'center',
+                    bottom: 5,
+                    textStyle: {
+                        //fontFamily: "'NotoSerif', '微软正黑体', 'Microsoft JhengHei UI', 'Microsoft JhengHei', Sans-serif",
+                        color: '#000',
+                        fontSize: '18'
+                    }
+                },
+                grid: {
+                    left: 80,
+                    right: 80,
+                    containLabel: true,
+                },
+                animation: false,
+                tooltip: {
+                    trigger: 'axis',
+                    axisPointer: {
+                        // 坐标轴指示器,坐标轴触发有效
+                        type: 'shadow', // 默认为直线,可选为:'line' | 'shadow'
+                        shadowStyle: {
+                            color: "rgba(255, 255, 255, 0.26)"
+                        },
+                    },
+
+                },
+                xAxis: {
+                    data: xAxis_val,
+                    boundaryGap: false,
+                    axisLine: {
+                        show: false,
+                    },
+                    axisTick: {
+                        show: false,
+                    },
+                    splitLine: {
+                        show: true,
+                        lineStyle: {
+                            color: '#ccc',
+                        },
+                    },
+                },
+                yAxis: {
+                    ayisLine: {
+                        show: false,
+                    },
+                    // x轴刻度线文字颜色
+                    axisLabel: {
+                        textStyle: {
+                            color: '#5c6076',
+                        },
+                    },
+                    // x轴线
+                    splitLine: {
+                        show: true,
+                        lineStyle: {
+                            color: '#fff',
+                        },
+                    },
+                    // Y轴
+                    axisLine: {
+                        lineStyle: {
+                            color: '#fff',
+                        },
+                    },
+                },
+                series: [
+                    {
+                        type: 'line',
+                        name: '访问量',
+                        smooth: true,
+                        symbolSize: 10,
+                        animation: false,
+                        lineWidth: 1,
+                        hoverAnimation: false,
+                        data: data_val,
+                        symbol: 'circle',
+                        itemStyle: {
+                            normal: {
+                                color: '#7083db',
+                            },
+                        },
+                        lineStyle: {
+                            normal: {
+                                width: 2,
+                                shadowBlur: 5,
+                                shadowColor: '#7083db',
+                                shadowOffsetY: 8
+                            }
+                        },
+                        label: {
+                            show: true,
+                            textStyle: {
+                                color: '#7083db',
+                                fontSize: 20,
+                            },
+                            position: 'top',
+                            formatter: function (p) {
+                                return p.value > 0 ? p.value : '';
+                            },
+                        },
+                        // 瀑布
+                        areaStyle: {
+                            normal: {
+                                color: '#7083db',
+                                opacity: 0.16,
+                            },
+                        },
+                    },
+                ],
+            };
+            minChart.setOption(minOption);
+            window.addEventListener('resize', function () {
+                minChart.resize()
+            })
+        }
+        //初始化地区访问量折线图
+        function initRegionCharts(originJson) {
+            // 基于准备好的dom,初始化echarts实例
+            var regionChart = echarts.init(document.getElementById('regionChart'));
+            var data_val = new Array(originJson.regionCnts.count).fill(0),
+                xAxis_val = new Array(originJson.regionCnts.count);
+            originJson.regionCnts.forEach((item, index) => {
+                data_val[index] = item.count
+                xAxis_val[index]=item.region
+               
+            })
+            var minOption = {
+                title: {
+                    text: hourStr + ' 地区访问统计分析('+total+')',
+                    left: 'center',
+                    bottom: 5,
+                    textStyle: {
+                        //fontFamily: "'NotoSerif', '微软正黑体', 'Microsoft JhengHei UI', 'Microsoft JhengHei', Sans-serif",
+                        color: '#000',
+                        fontSize: '18'
+                    }
+                },
+                grid: {
+                    left: 80,
+                    right: 80,
+                    containLabel: true,
+                },
+                animation: false,
+                tooltip: {
+                    trigger: 'axis',
+                    axisPointer: {
+                        // 坐标轴指示器,坐标轴触发有效
+                        type: 'shadow', // 默认为直线,可选为:'line' | 'shadow'
+                        shadowStyle: {
+                            color: "rgba(255, 255, 255, 0.26)"
+                        },
+                    },
+
+                },
+                xAxis: {
+                    data: xAxis_val,
+                    boundaryGap: false,
+                    axisLine: {
+                        show: false,
+                    },
+                    axisTick: {
+                        show: false,
+                    },
+                    splitLine: {
+                        show: true,
+                        lineStyle: {
+                            color: '#ccc',
+                        },
+                    },
+                },
+                yAxis: {
+                    ayisLine: {
+                        show: false,
+                    },
+                    // x轴刻度线文字颜色
+                    axisLabel: {
+                        textStyle: {
+                            color: '#5c6076',
+                        },
+                    },
+                    // x轴线
+                    splitLine: {
+                        show: true,
+                        lineStyle: {
+                            color: '#fff',
+                        },
+                    },
+                    // Y轴
+                    axisLine: {
+                        lineStyle: {
+                            color: '#fff',
+                        },
+                    },
+                },
+                series: [
+                    {
+                        type: 'bar',
+                        name: '访问量',
+                        smooth: true,
+                        symbolSize: 10,
+                        animation: false,
+                        lineWidth: 1,
+                        hoverAnimation: false,
+                        data: data_val,
+                        symbol: 'circle',
+                        itemStyle: {
+                            normal: {
+                                color: '#7083db',
+                            },
+                        },
+                        lineStyle: {
+                            normal: {
+                                width: 2,
+                                shadowBlur: 5,
+                                shadowColor: '#7083db',
+                                shadowOffsetY: 0
+                            }
+                        },
+                        label: {
+                            show: true,
+                            textStyle: {
+                                color: '#7083db',
+                                fontSize: 20,
+                            },
+                            position: 'top',
+                            formatter: function (p) {
+                                return p.value > 0 ? p.value : '';
+                            },
+                        },
+                    },
+                ],
+            };
+            regionChart.setOption(minOption);
+            window.addEventListener('resize', function () {
+                regionChart.resize()
+            })
+        }
+
+    </script>
+</body>
+
+</html>

+ 6 - 1
HTEXScreen/appsettings.json

@@ -5,5 +5,10 @@
       "Microsoft.AspNetCore": "Warning"
     }
   },
-  "AllowedHosts": "*"
+  "AllowedHosts": "*",
+  "Azure": {
+    "Storage": {
+      "ConnectionString": "DefaultEndpointsProtocol=https;AccountName=teammodeltest;AccountKey=O2W2vadCqexDxWO+px+QK7y1sHwsYj8f/WwKLdOdG5RwHgW/Dupz9dDUb4c1gi6ojzQaRpFUeAAmOu4N9E+37A==;EndpointSuffix=core.chinacloudapi.cn"
+    }
+  }
 }