瀏覽代碼

Merge branch 'develop' of http://52.130.252.100:10000/TEAMMODEL/TEAMModelOS into develop

OnePsycho 1 年之前
父節點
當前提交
df52ef35bf

+ 1 - 1
TEAMModelOS.FunctionV4/CosmosDB/TriggerExam.cs

@@ -1574,7 +1574,7 @@ namespace TEAMModelOS.FunctionV4
                 if () { 
                 
                 }*/
-                if (errorItems.Count == 0)
+                if (errorItems.Count == 0 && info.qamode != 2)
                 {
                     // 新增逻辑 收集错题内容
                     BlobDownloadResult index_json;

+ 2 - 2
TEAMModelOS.SDK/Models/Cosmos/School/Elegant.cs

@@ -49,12 +49,12 @@ namespace TEAMModelOS.SDK.Models
      
         public List<Attachment> attachments { get; set; } = new List<Attachment>();
         public string target { get; set; }
-      
+
         /// <summary>
         /// 业务类型。elegant 德育, art 艺术,弃用
         /// </summary>
         // public List<string> bizCode { get; set; }
-        public List<string> bizType { get; set; }
+        public List<string> bizType { get; set; } = new List<string>();
         /// <summary>
         /// image  video
         /// </summary>

+ 70 - 0
TEAMModelOS.TEST/Program.cs

@@ -17,6 +17,76 @@ namespace TEAMModelOS.TEST
             //var jsonAuth = System.IO.File.ReadAllText("C:\\Users\\CrazyIter\\Downloads\\492266088181141504\\ActivityInfo.json", Encoding.UTF8);
             //var jsonData = jsonAuth.ToObject<LessonRecordActivityInfo>();
             string path = "C:\\Users\\CrazyIter\\Downloads\\消费清单(2022-2023)\\bill";
+            List<List<string>> inputArray = new List<List<string>>
+            {  
+                new List<string> { "2", "11" },
+                new List<string> { "1", "22" },
+                new List<string> { "1", "11", "111" },
+                new List<string> { "2", "22", "222" },
+                new List<string> { "1", "11" },
+                new List<string> { "1", "11" },
+                new List<string> { "1" },
+                new List<string> { "2", "22", "222" },
+                new List<string> { "2", "22" }  ,
+            };
+
+            // 转换为层级结构
+            List<ClassifiedItem> result = ClassifyHierarchy(inputArray);
+
+            // 输出结果
+            foreach (var item in result)
+            {
+                Console.WriteLine($"id: {item.Id}, count: {item.Count}, pid: {item.Pid}");
+            }
+        }
+        static List<ClassifiedItem> ClassifyHierarchy(List<List<string>> inputArray)
+        {
+            Dictionary<string, int> hierarchyCount = new Dictionary<string, int>();
+            List<ClassifiedItem> result = new List<ClassifiedItem>();
+
+            foreach (var list in inputArray)
+            {
+                for (int i = 0; i < list.Count; i++)
+                {
+                    string currentId = list[i];
+                    string parentId = (i > 0) ? list[i - 1] : null;
+
+                    string hierarchyKey = $"{currentId}|{parentId}";
+
+                    if (hierarchyCount.ContainsKey(hierarchyKey))
+                    {
+                        hierarchyCount[hierarchyKey]++;
+                    }
+                    else
+                    {
+                        hierarchyCount[hierarchyKey] = 1;
+                    }
+                    var item = result.Find(item => item.Id == currentId && item.Pid == parentId);
+                    if (item== null  )
+                    {
+                        result.Add(new ClassifiedItem
+                        {
+                            Id = currentId,
+                            Pid = parentId,
+                            Count = 0
+                        });
+                    }
+                }
+            }
+
+            foreach (var item in result)
+            {
+                string hierarchyKey = $"{item.Id}|{item.Pid}";
+                item.Count = hierarchyCount.ContainsKey(hierarchyKey) ? hierarchyCount[hierarchyKey] : 0;
+            }
+
+            return result;
+        }
+        class ClassifiedItem
+        {
+            public string Id { get; set; }
+            public int Count { get; set; }
+            public string Pid { get; set; }
         }
     }
 

+ 6 - 0
TEAMModelOS/ClientApp/public/lang/en-US.js

@@ -7647,6 +7647,7 @@ const LANG_EN_US = {
             title: 'Device Statistics',
             deviceTotal: 'Total Devices',
             deviceOnline: 'Used Devices',
+            numAndproportion: 'Quantity and Proportion',
         },
         lessons: {
             title: 'Lesson and Application History Chart',
@@ -7662,6 +7663,11 @@ const LANG_EN_US = {
             task: 'Task',
             differentiation: 'Differentiated',
             examination: 'Assessment',
+        },
+        basicsChat: {
+            title: 'Basic data',
+            roomnum: 'Classrooms',
+            teachnum: 'Teachers',
         }
     },
     areaIot: {

+ 6 - 0
TEAMModelOS/ClientApp/public/lang/zh-TW.js

@@ -7648,6 +7648,7 @@ const LANG_ZH_TW = {
             title: '裝置統計',
             deviceTotal: '總裝置數',
             deviceOnline: '上線數',
+            numAndproportion: '數量與佔比',
         },
         lessons: {
             title: '課堂與應用歷程統計',
@@ -7663,6 +7664,11 @@ const LANG_ZH_TW = {
             task: '任務型態',
             differentiation: '差異化型態',
             examination: '測驗型態',
+        },
+        basicsChat: {
+            title: '基礎資料',
+            roomnum: '教室數',
+            teachnum: '教師數',
         }
     },
     areaIot: {

+ 15 - 9
TEAMModelOS/ClientApp/src/view/iot/echarts/barandLine/specialBarline.vue

@@ -135,7 +135,7 @@
               textStyle: {
                 color: '#90979c',
               },
-              data: ['教室数','教师数','学生参与人数','课堂总数','课堂总时数','学生参与总时数']
+              data: [this.$t('schoolIot.basicsChat.roomnum'),this.$t('schoolIot.basicsChat.teachnum'),this.$t('schoolIot.basics.studentnums'),this.$t('schoolIot.basics.classroomTotal'),this.$t('schoolIot.basics.classroomTime'),this.$t('schoolIot.basics.studentTime')]
             },
             calculable: true,
             xAxis: [{
@@ -232,7 +232,8 @@
             }],
             series: [
             {
-                name:'教室数',
+                //教室数
+                name:this.$t('schoolIot.basicsChat.roomnum'),
                 type:'bar',
                 barWidth: 10,
                 symbol: 'circle',
@@ -253,7 +254,8 @@
                 data:this.trendData.rooms
             },
             {
-                name:'教师数',
+                //教师数
+                name:this.$t('schoolIot.basicsChat.teachnum'),
                 type:'bar',
                 barWidth: 10,
                 symbol: 'circle',
@@ -275,7 +277,8 @@
                 data:this.transferJson.rooms
             },
             {
-                name:'学生参与人数',
+                //学生参与人次
+                name:this.$t('schoolIot.basics.studentnums'),
                 type:'bar',
                 // stack: '参与人数',
                 barWidth: 10,
@@ -297,7 +300,8 @@
                 data:this.transferJson.students
             },
             {
-                name:'课堂总数',
+                //课堂总数
+                name:this.$t('schoolIot.basics.classroomTotal'),
                 type:'bar',
                 // stack: '参与人数',
                 barWidth: 10,
@@ -318,8 +322,9 @@
                 },
                 data:this.transferJson.class
             },
-            { //作品数量
-            name: '课堂总时数',
+            { 
+            //课堂总时数
+            name:this.$t('schoolIot.basics.classroomTime'),
             type: 'line',
             yAxisIndex: 1,
             // smooth: true, //是否平滑曲线显示
@@ -366,8 +371,9 @@
             },
             data:this.transferJson.classtimes
             },
-            { //作品数量
-            name: '学生参与总时数',
+            { 
+            //学生参与总时数
+            name:this.$t('schoolIot.basics.studentTime'),
             type: 'line',
             yAxisIndex: 1,
             // smooth: true, //是否平滑曲线显示

+ 2 - 2
TEAMModelOS/ClientApp/src/view/iot/schooliot.vue

@@ -94,7 +94,7 @@
                     </dv-border-box-11>
                 </div>
                 <div class="restsbox-right">
-                    <dv-border-box-11 title="数量与占比">
+                    <dv-border-box-11 :title="$t('schoolIot.device.numAndproportion')">
                         <div class="total-solution">
                             <Bar title="学期" :cdata="bars"></Bar>
                         </div>
@@ -121,7 +121,7 @@
                     <dv-border-box-12>
                         <div class="innerbox">
                             <p class="boxtitles">
-                                <span>基础数据</span>
+                                <span>{{$t('schoolIot.basicsChat.title')}}</span>
                                 <dv-decoration-3 style="width:200px;height:20px;"/>
                             </p>
                             <div class="barbox">

+ 20 - 16
TEAMModelOS/Controllers/Common/ActivityController.cs

@@ -1393,26 +1393,30 @@ namespace TEAMModelOS.Controllers
                     
                      }
             }
-            if (tmdid == null  && !string.IsNullOrWhiteSpace($"{_token}"))
+            
+            if (tmdid == null   )
             {
-                var jwt = new JwtSecurityToken(_token.GetString());
-                if (JwtAuthExtension.ValidateAuthTokenRefresh(_token.GetString(), _option.JwtSecretKey))
+                if (!string.IsNullOrWhiteSpace($"{_token}"))
                 {
-                    tmdid = jwt.Payload.Sub;
-
-                    if (HttpContext.Request.Headers.TryGetValue("lang", out var _lang))
+                    var jwt = new JwtSecurityToken(_token.GetString());
+                    if (JwtAuthExtension.ValidateAuthTokenRefresh(_token.GetString(), _option.JwtSecretKey))
                     {
-                        head_lang = $"{_lang}";
+                        tmdid = jwt.Payload.Sub;
+
+                        if (HttpContext.Request.Headers.TryGetValue("lang", out var _lang))
+                        {
+                            head_lang = $"{_lang}";
+                        }
+                        jwt.Payload.TryGetValue("name", out name);
+                        jwt.Payload.TryGetValue("picture", out picture);
+                        jwt.Payload.TryGetValue("lang", out object _jwtlang);
+                        head_lang = !string.IsNullOrWhiteSpace($"{_jwtlang}") ? $"{_jwtlang}" : head_lang;
                     }
-                    jwt.Payload.TryGetValue("name", out name);
-                    jwt.Payload.TryGetValue("picture", out picture);
-                    jwt.Payload.TryGetValue("lang", out object _jwtlang);
-                    head_lang = !string.IsNullOrWhiteSpace($"{_jwtlang}") ? $"{_jwtlang}" : head_lang;
+                    else { return Ok(new { code = 2, msg = "Token验证失败" }); }
                 }
-                else { return Ok(new { code = 2, msg = "Token验证失败" }); }
-
+                else { return Ok(new { code = 3, msg = "凭证验证失败" }); }
             }
-            else { return Ok(new { code = 3, msg = "凭证验证失败" }); }
+           
             teacherInfo = await TeacherService.TeacherInfoLite(_azureCosmos,  $"{name}", $"{picture}", tmdid, _azureStorage, _option, _azureRedis, ip, _httpTrigger, head_lang);
             string sql = $"select value c from c where c.route='{_route}'";
             var result = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Normal).GetList<ActivityWebsite>(sql, "ActivityWebsite");
@@ -1448,8 +1452,8 @@ namespace TEAMModelOS.Controllers
                 { JwtRegisteredClaimNames.Exp,DateTimeOffset.UtcNow.AddHours(2).ToUnixTimeSeconds()},  // 到期的時間,必須為數字
                 { "name",name}, // 用戶的顯示名稱
                 { "picture",picture}, // 用戶頭像
-                { "roles", roles}, // 登入者的角色,角色類型 (Admin、Teacher、Student) 
-                { JwtRegisteredClaimNames.Website,website.route},
+                { "roles", roles.ToArray()}, // 登入者的角色,角色類型 (Admin、Teacher、Student) 
+                { JwtRegisteredClaimNames.Website,website?.route},
             };
             var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_option.JwtSecretKey));
             var signingCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256Signature);

+ 99 - 3
TEAMModelOS/Controllers/Common/ExamController.cs

@@ -39,6 +39,15 @@ using DocumentFormat.OpenXml.Drawing.Charts;
 using ClouDASLibx;
 using HTEXLib.Helpers.ShapeHelpers;
 using TEAMModelOS.SDK.Helper.Common.DateTimeHelper;
+using Microsoft.Extensions.Hosting;
+using System.Configuration;
+using DocumentFormat.OpenXml.Presentation;
+using static SKIT.FlurlHttpClient.Wechat.TenpayV3.Models.CreateApplyForSubjectApplymentRequest.Types;
+using TEAMModelOS.Controllers.Core;
+using Azure.Storage.Blobs.Models;
+using Top.Api;
+using Newtonsoft.Json.Linq;
+using System.IO;
 
 namespace TEAMModelOS.Controllers
 {
@@ -272,7 +281,8 @@ namespace TEAMModelOS.Controllers
                             {
                                 simple.blob = $"/exam/{request.id}/paper/{simple.subjectId}/{simple.id}";
                             }
-                            else {
+                            else
+                            {
                                 simple.blob = $"/exam/{request.id}/paper/{request.subjects[n].id}";
                                 n++;
                             }
@@ -3696,8 +3706,8 @@ namespace TEAMModelOS.Controllers
                         break;
                     }
                 }
-                //var items = ids.GroupBy(x => x).Select(z => z.Key).ToList().Count;
-                return Ok(new { errorItems, token, ids.Count });
+                errorItems = errorItems.Where((x, i) => errorItems.FindIndex(z => z.id == x.id) == i).ToList();
+                return Ok(new { errorItems, token,ids.Count });
             }
             catch (Exception ex)
             {
@@ -4197,7 +4207,88 @@ namespace TEAMModelOS.Controllers
             return Task.FromResult(wn);
         }
 
+        //获取题目信息
+        [ProducesDefaultResponseType]
+        //[AuthToken(Roles = "teacher,admin,student")]
+        [HttpPost("get-item")]
+        //[Authorize(Roles = "IES")]
+        public async Task<IActionResult> getItemInfo(JsonElement request)
+        {
+            if (!request.TryGetProperty("errorItems", out JsonElement items)) return BadRequest();
+            List<errorItemInfo> errors = items.ToObject<List<errorItemInfo>>();
+            var client = _azureCosmos.GetCosmosClient();
+            List<string> ids = errors.Select(c => c.activityId).ToList();
+            var queryClass = $"select value(c) from c where c.id in ({string.Join(",", ids.Select(o => $"'{o}'"))}) and c.pk = 'Exam'";
+            List<ExamInfo> exams = new();
+            await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryIterator<ExamInfo>(queryText: queryClass))
+            {
+                exams.Add(item);
+            }
+            List<JsonElement> elements = new();
+            if (exams.Count > 0)
+            {
+                foreach (errorItemInfo itemInfo in errors) {
+                    ExamInfo info = exams.Where(c => c.id.Equals(itemInfo.activityId)).FirstOrDefault();
+                    List<ExamSubject> subjects = info.subjects;
+                    int index = 0;
+                    foreach (ExamSubject subject in subjects)
+                    {
+                        if (subject.id.Equals(itemInfo.unitId))
+                        {
+                            continue;
+                        }
+                        else
+                        {
+                            index++;
+                        }
+                    }
+                    List<PaperSimple> simples = info.papers;
+                    string blob = simples[index].blob;
+                    try {
+                        BlobDownloadResult index_item_json;
+                        if (info.scope.Equals("school"))
+                        {
+                            index_item_json = await _azureStorage.GetBlobContainerClient($"{info.school}").GetBlobClient($"{blob}/{itemInfo.qId}.json").DownloadContentAsync();
+                        }
+                        else
+                        {
+                            index_item_json = await _azureStorage.GetBlobContainerClient($"{info.creatorId}").GetBlobClient($"{blob}/{itemInfo.qId}.json").DownloadContentAsync();
+                        }
+                        JsonElement itemJson = JsonDocument.Parse(new MemoryStream(Encoding.UTF8.GetBytes(index_item_json.Content.ToString()))).RootElement;
+                        elements.Add(itemJson);
+                        if (itemJson.TryGetProperty("pid", out JsonElement pid))
+                        {
+                            if (!string.IsNullOrEmpty(pid.ToString()))
+                            {
+                                BlobDownloadResult index_pid_item_json;
+                                if (info.scope.Equals("school"))
+                                {
+                                    index_pid_item_json = await _azureStorage.GetBlobContainerClient($"{info.school}").GetBlobClient($"{blob}/{pid}.json").DownloadContentAsync();
+                                }
+                                else
+                                {
+                                    index_pid_item_json = await _azureStorage.GetBlobContainerClient($"{info.creatorId}").GetBlobClient($"{blob}/{pid}.json").DownloadContentAsync();
+                                }
+                                JsonElement pidJson = JsonDocument.Parse(new MemoryStream(Encoding.UTF8.GetBytes(index_pid_item_json.Content.ToString()))).RootElement;
+                                elements.Add(pidJson);
+                            }
+                        }
+                    } catch (Exception e) {
+                        return BadRequest(new { msg = "blob 文件读取异常" });
+                    }
+                                    
+                }
+            }
+            else
+            {
+                return BadRequest(new { msg = "暂无数据" });
+            }
+            return Ok(elements);
+        }
+
     }
+
+
     public class stus
     {
         public string id { get; set; }
@@ -4214,4 +4305,9 @@ namespace TEAMModelOS.Controllers
         public string subjectId { get; set; }
         public int number { get; set; }
     }
+    public class errorItemInfo { 
+        public string activityId { get; set; }
+        public string qId { get; set; }
+        public string unitId { get; set; }
+    }
 }

+ 170 - 1
TEAMModelOS/Controllers/School/ElegantController.cs

@@ -5,6 +5,8 @@ using System.Dynamic;
 using System.IO;
 using System.Linq;
 using System.Net;
+using System.Net.Http;
+using System.Net.Http.Json;
 using System.Text;
 using System.Text.Json;
 using System.Threading.Tasks;
@@ -16,6 +18,7 @@ using Microsoft.AspNetCore.Authorization;
 using Microsoft.AspNetCore.Cryptography.KeyDerivation;
 using Microsoft.AspNetCore.Mvc;
 using Microsoft.Extensions.Options;
+using Newtonsoft.Json;
 using TEAMModelOS.Filter;
 using TEAMModelOS.Models;
 using TEAMModelOS.SDK.DI;
@@ -23,6 +26,8 @@ using TEAMModelOS.SDK.Extension;
 using TEAMModelOS.SDK.Models;
 using TEAMModelOS.SDK.Models.Cosmos;
 using TEAMModelOS.SDK.Models.Cosmos.Common;
+using TEAMModelOS.SDK.Models.Dtos;
+using TEAMModelOS.SDK.Models.Service;
 namespace TEAMModelOS.Controllers
 {
     [Route("school/elegant")]
@@ -34,17 +39,181 @@ namespace TEAMModelOS.Controllers
         private readonly AzureStorageFactory _azureStorage;
         private readonly DingDing _dingDing;
         private readonly Option _option;
+        private IHttpClientFactory _httpClientFactory;
         public ElegantController(
            AzureCosmosFactory azureCosmos,
            AzureStorageFactory azureStorage,
            DingDing dingDing,
-           IOptionsSnapshot<Option> option
+           IOptionsSnapshot<Option> option,IHttpClientFactory httpClientFactory
            )
         {
             _azureCosmos = azureCosmos;
             _azureStorage = azureStorage;
             _dingDing = dingDing;
             _option = option?.Value;
+            _httpClientFactory = httpClientFactory;
+        }
+
+        /// <summary>
+        /// 新增 或 修改
+        /// </summary>
+        /// <param name="request"></param>
+        /// <returns></returns>
+        [ProducesDefaultResponseType]
+        [HttpPost("statistics")]
+#if !DEBUG
+        [Authorize(Roles = "IES")]
+        [AuthToken(Roles = "teacher,admin,area")]
+#endif
+        public async Task<IActionResult> Statistics(JsonElement  json)
+        {
+            if (!json.TryGetProperty("scope", out JsonElement _scope))
+            {
+                return BadRequest();
+            }
+            if (!json.TryGetProperty("code", out JsonElement _code))
+            {
+                return BadRequest();
+            }
+            List<Elegant> elegants = new List<Elegant>();
+            if ($"{_scope}".Equals("area"))
+            {
+                string sql = $"select value c.id  from c where c.areaId ='{_code}'";
+                var result = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).GetList<string>(sql, "Base");
+                if (result.list.IsNotEmpty())
+                {
+                    string sqlE = $"select value c from c where c.school in ({string.Join(",", result.list.Select(z => $"'{z}'"))})";
+                    var resultE = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).GetList<Elegant>(sqlE);
+                    if (resultE.list.IsNotEmpty())
+                    {
+                        elegants.AddRange(resultE.list);
+                    }
+                }
+            }
+            else if ($"{_scope}".Equals("school"))
+            {
+                string sqlE = $"select value c from c ";
+                var resultE = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).GetList<Elegant>(sqlE,$"Elegant-{_code}");
+                if (resultE.list.IsNotEmpty())
+                {
+                    elegants.AddRange(resultE.list);
+                }
+            }
+            List<ClassifiedItem> items = ClassifyHierarchy(elegants);
+            string rs = string.Empty;
+            List<dynamic> comments = new List<dynamic>();
+            foreach (var es in elegants) {
+                comments.Add(new { comment = $"{es.title} {es.content}" });
+            }
+            if (comments.IsNotEmpty()) {
+                rs= comments.ToJsonString();
+            }
+            foreach (var item in items)
+            {
+                var es = elegants.FindAll(z => item.sid.Contains(z.id));
+                if (es.IsNotEmpty()) {
+                    var video = es.SelectMany(z => z.attachments).Where(a =>!string.IsNullOrWhiteSpace(a.type) &&  a.type.Equals("video"));
+                    if (video.Any()) { 
+                        item.videoCount = video.Count();
+                    }
+                    var image = es.SelectMany(z => z.attachments).Where(a => !string.IsNullOrWhiteSpace(a.type) &&a.type.Equals("image"));
+                    if (image.Any())
+                    {
+                        item.imageCount = image.Count();
+                    }
+                    var doc = es.SelectMany(z => z.attachments).Where(a => !string.IsNullOrWhiteSpace(a.type) && a.type.Equals("doc"));
+                    if (doc.Any())
+                    {
+                        item.docCount = doc.Count();
+                    }
+                    var other = es.SelectMany(z => z.attachments).Where(a => string.IsNullOrWhiteSpace(a.type) ||  (!a.type.Equals("doc") && !a.type.Equals("video") && !a.type.Equals("image")  && !a.type.Equals("doc")));
+                    if (other.Any())
+                    {
+                        item.otherCount = other.Count();
+                    }
+                }
+            }
+            List<CommentKeyCount> keyCounts = new List<CommentKeyCount>();
+            if (!string.IsNullOrWhiteSpace(rs)) {
+               var httpClient=  _httpClientFactory.CreateClient();
+                if (!httpClient.DefaultRequestHeaders.Contains("x-functions-key")) {
+                    httpClient.DefaultRequestHeaders.Add("x-functions-key", "2BcXFR_hvzG1pZjqIkaM7Dx74Hcu6m0PwwOacFpDpq44AzFuHJBRXA==");
+                }
+                string paramJson = JsonConvert.SerializeObject(new { rs = $"{rs}", fmt = "0" });
+                var content = new StringContent(paramJson, Encoding.UTF8, "application/json");
+                HttpResponseMessage httpResponse=  await httpClient.PostAsync("https://malearn.teammodel.cn/api/txtwc", content);
+                if (httpResponse.IsSuccessStatusCode) {
+                    string str = await httpResponse.Content.ReadAsStringAsync();
+                    if (str.Contains("freq"))
+                    { keyCounts= str.ToObject<List<CommentKeyCount>>(); }
+                }
+            }
+            return Ok(new { keyCounts,items= items.Select(z=>new {z.id ,z.pid,z.count,z.videoCount,z.docCount,z.imageCount,z.otherCount })});
+        }
+
+        private  List<ClassifiedItem> ClassifyHierarchy(List<Elegant> inputArray)
+        {
+            Dictionary<string, int> hierarchyCount = new Dictionary<string, int>();
+            List<ClassifiedItem> result = new List<ClassifiedItem>();
+
+            foreach (var list in inputArray)
+            {
+                if (list.bizType.IsEmpty()) {
+                    list.bizType.Add("德育风采");
+                }
+                for (int i = 0; i < list.bizType.Count; i++)
+                {
+                    string currentId = list.bizType[i];
+                    string parentId = (i > 0) ? list.bizType[i - 1] : null;
+                    string hierarchyKey = $"{currentId}|{parentId}";
+                    if (hierarchyCount.ContainsKey(hierarchyKey))
+                    {
+                        hierarchyCount[hierarchyKey]++;
+                    }
+                    else
+                    {
+                        hierarchyCount[hierarchyKey] = 1;
+                    }
+                    var item =  result.Find(item => item.id == currentId && item.pid == parentId);
+                    if (item== null)
+                    {
+                        result.Add(new ClassifiedItem
+                        {
+                            id = currentId,
+                            pid = parentId,
+                            count = 0,
+                            sid= new List<string> {list.id }
+                        });
+                    }
+                    else {
+                        item.sid.Add(list.id);
+                    }
+                }
+            }
+            foreach (var item in result)
+            {
+                string hierarchyKey = $"{item.id}|{item.pid}";
+                item.count = hierarchyCount.ContainsKey(hierarchyKey) ? hierarchyCount[hierarchyKey] : 0;
+            }
+            return result;
+        }
+        class CommentKeyCount
+        { 
+            public int id { get; set; }
+            public string word { get; set; }
+            public int freq { get; set; }
+
+        }
+        class ClassifiedItem
+        {
+            public List<string> sid { get; set; } = new List<string>();
+            public string id { get; set; }
+            public int count { get; set; }
+            public string pid { get; set; }
+            public int videoCount { get; set; }
+            public int imageCount { get; set; }
+            public int docCount { get; set; }
+            public int otherCount { get; set; }
         }
         /// <summary>
         /// 新增 或 修改