Browse Source

Merge branch 'develop' into PL/develop-BI

Li 2 years ago
parent
commit
dbd0c796fd

+ 8 - 8
TEAMModelBI/ClientApp/src/view/common/aside.vue

@@ -168,14 +168,14 @@ export default {
           //   isShow: true,
           //   sort: 10,
           // },
-          // {
-          //   name: '第三方管理',
-          //   router: '/home/thirdparty',
-          //   icon: '#icon-collaboration-system',
-          //   permission: [],
-          //   isShow: true,
-          //   sort: 11,
-          // },
+          {
+            name: '第三方管理',
+            router: '/home/thirdparty',
+            icon: '#icon-collaboration-system',
+            permission: [],
+            isShow: true,
+            sort: 11,
+          },
         ],
       },
       // {

+ 94 - 1
TEAMModelOS/ClientApp/public/lang/en-US.js

@@ -7190,5 +7190,98 @@ const LANG_EN_US = {
         ae42: 'Exam file unavailable',
         ae43: 'Art assessment Exam file can only contain objective questions (single-answer, multiple-answers, true-false), please re-select the file or go to the Exam library to modify. ',
         ae44: 'The Exam file data is abnormal',
-    }
+    },
+    areaStatistics: {
+        tag: {
+            basics: 'Basic data',
+            classData: 'Classroom data',
+            classActive: 'Classroom active status',
+            training: 'Training progress',
+            size: 'Space usage',
+            list: 'School List'
+        },
+        header: {
+            areaTilte: 'Schools in the district',
+            areaTeach: 'Teachers in the district',
+            areaStudent: 'Students in the district',
+            areaData: 'Total ouput data',
+            areaSize: 'Total space',
+            weekAdd: 'Weekly increment',
+            monthAdd: 'Monthly increment',
+        },
+        basics: {
+            weekClass: 'Lesson records this week',
+            semesterClass: 'Lesson records this semester',
+            weekActivity: 'Activities this week',
+            semesterActivity: 'Activities this semester',
+            accumulatedClass: 'Accumulated lessons',
+            accumulatedExample: 'Accumulated lesson records',
+            accumulatedResource: 'Accumulated resources',
+            accumulatedActivity: 'Accumulated activities',
+            evaluating: 'Assesment',
+            vote: 'Polling',
+            questionnaire: 'Questionnaire',
+            work: 'Homework activity',
+            basicsV: 'Basic edition',
+            standardV: 'Standard edition',
+            marjorV: 'Pro edition',
+        },
+        class: {
+            total: 'Total data this year',
+            lastWeek: 'Last week',
+            nowMonth: 'This month',
+            vitality: 'Active status',
+        },
+        research: {
+            accomplish: 'Completed',
+            underneath: 'In progress',
+            unfinished: 'Unfinished',
+            classroom: 'Lesson record',
+            online: 'Online training',
+            attestation: 'Certification material',
+            researchTraining: 'School-based training',
+        },
+        size: {
+            use: 'Space usage',
+            documents: 'Docuemnt',
+            image: 'Image',
+            other: 'Other',
+            video: 'Video',
+            thumbnail: 'Thumbnail',
+            material: 'Material',
+            audio: 'Audio',
+            hiteachs: 'HiTeach upload data',
+            moralEducation: 'Moral education collections'
+        },
+        list: {
+            badge: 'School badge',
+            name: 'Name',
+            code: 'School code',
+        }
+    },
+    schoolStatistics: {
+        header: {
+            teachNum: 'Number of teachers',
+            studentNum: 'Number of students',
+            roomNum: 'Numbers of Smart Classroom',
+            class: 'Number of lesson records',
+        },
+        year: {
+            class: 'Total lesson records this year',
+            activity: 'Total activities this year',
+            interaction: 'Total interactions this year',
+        },
+        class: {
+            lessonTitle: 'Lesson record',
+            activityTitle: 'Activity',
+            interactionTitle: 'Interaction',
+            totalTitle: 'Total data',
+            todayData: 'Today data',
+            contrastYesterday: 'Compare with yesterday',
+            contrastLastmonth: 'Compare with last month',
+            contrastLastyear: 'Compare with last year',
+        },
+        gradeTitle: 'Grades distribution',
+        subjectTitle: 'Subjects distribution',
+    },
 }

+ 96 - 1
TEAMModelOS/ClientApp/public/lang/zh-CN.js

@@ -7181,5 +7181,100 @@ const LANG_ZH_CN = {
         ae42: '试卷不可用',
         ae43: '艺术评测试卷只能包含客观题(单选、多选、判断),请重新挑选试卷或前往试卷库修改当前试卷。',
         ae44: '试卷数据异常',
-    }
+    },
+    //区级数据统计
+    areaStatistics: {
+        tag: {
+            basics: '基础数据',
+            classData: '课例数据',
+            classActive: '课例活跃度',
+            training: '研修进度',
+            size: '空间使用情况',
+            list: '学校列表'
+        },
+        header: {
+            areaTilte: '区内学校',
+            areaTeach: '区内老师',
+            areaStudent: '区内学生',
+            areaData: '产出总数据',
+            areaSize: '空间总容量',
+            weekAdd: '周新增',
+            monthAdd: '月新增',
+        },
+        basics: {
+            weekClass: '本周课例数',
+            semesterClass: '学期课例数',
+            weekActivity: '本周活动数',
+            semesterActivity: '学期活动数',
+            accumulatedClass: '累计开课',
+            accumulatedExample: '累计课例',
+            accumulatedResource: '累计资源',
+            accumulatedActivity: '累计活动',
+            evaluating: '评量测验',
+            vote: '投票活动',
+            questionnaire: '问卷调查',
+            work: '作业活动',
+            basicsV: '基础版',
+            standardV: '标准版',
+            marjorV: '专业版',
+        },
+        class: {
+            total: '今年总数据',
+            lastWeek: '上周',
+            nowMonth: '本月',
+            vitality: '活跃度',
+        },
+        research: {
+            accomplish: '已完成',
+            underway: '进行中',
+            unfinished: '未完成',
+            classroom: '课堂实录',
+            online: '线上研修',
+            attestation: '认证材料',
+            researchTraining: '校本研修',
+        },
+        size: {
+            use: '空间使用率',
+            documents: '文档',
+            image: '图片',
+            other: '其他',
+            video: '视频',
+            thumbnail: '缩略图',
+            material: '教材',
+            audio: '音频',
+            hiteachs: 'HiTeach上传数据',
+            moralEducation:'德育风采'
+        },
+        list: {
+            badge: '校徽',
+            name: '名称',
+            code:'简码',
+        }
+    },
+    //学校数据统计
+    schoolStatistics: {
+        header: {
+            teachNum: '教师数',
+            studentNum: '学生数',
+            roomNum: '智慧教室',
+            class:'课例数',
+        },
+        year: {
+            class: '今年课例总计',
+            activity: '今年活动总计',
+            interaction:'今年互动总计',
+        },
+        class: {
+            lessonTitle: '课例',
+            activityTitle: '活动',
+            interactionTitle: '互动',
+            totalTitle: '总数据',
+            todayData: '今日数据',
+            contrastYesterday: '昨日对比',
+            contrastLastmonth: '上月对比',
+            contrastLastyear:'去年对比',
+        },
+        gradeTitle: '年级占比',
+        subjectTitle: '科目占比',
+    },
 }

+ 94 - 1
TEAMModelOS/ClientApp/public/lang/zh-TW.js

@@ -7181,5 +7181,98 @@ const LANG_ZH_TW = {
         ae42: '試卷不可用',
         ae43: '藝術評量試卷只能包含客觀類題型(單選、複選、是非),請重新挑選試卷或前往試卷庫修改當前試卷。 ',
         ae44: '試卷資料異常',
-    }
+    },
+    areaStatistics: {
+        tag: {
+            basics: '基礎數據',
+            classData: '課堂數據',
+            classActive: '課堂活躍度',
+            training: '研修進度',
+            size: '空間使用情況',
+            list: '學校列表'
+        },
+        header: {
+            areaTilte: '區內學校',
+            areaTeach: '區內老師',
+            areaStudent: '區內學生',
+            areaData: '產出總數據',
+            areaSize: '空間總容量',
+            weekAdd: '週新增',
+            monthAdd: '月新增',
+        },
+        basics: {
+            weekClass: '本週課堂數',
+            semesterClass: '學期課堂數',
+            weekActivity: '本週活動數',
+            semesterActivity: '學期活動數',
+            accumulatedClass: '累計開課',
+            accumulatedExample: '累計課堂',
+            accumulatedResource: '累計資源',
+            accumulatedActivity: '累計活動',
+            evaluating: '評量測驗',
+            vote: '投票活動',
+            questionnaire: '問卷調查',
+            work: '作業活動',
+            basicsV: '基礎版',
+            standardV: '標準版',
+            marjorV: '專業版',
+        },
+        class: {
+            total: '今年總數據',
+            lastWeek: '上週',
+            nowMonth: '本月',
+            vitality: '活躍度',
+        },
+        research: {
+            accomplish: '已完成',
+            underway: '進行中',
+            unfinished: '未完成',
+            classroom: '課堂實錄',
+            online: '線上研修',
+            attestation: '認證材料',
+            researchTraining: '校本研修',
+        },
+        size: {
+            use: '空間使用率',
+            documents: '檔案',
+            image: '圖片',
+            other: '其他',
+            video: '影片',
+            thumbnail: '縮圖',
+            material: '教材',
+            audio: '音訊',
+            hiteachs: 'HiTeach上傳數據',
+            moralEducation: '德育風采'
+        },
+        list: {
+            badge: '校徽',
+            name: '名稱',
+            code: '簡碼',
+        }
+    },
+    schoolStatistics: {
+        header: {
+            teachNum: '教師數',
+            studentNum: '學生數',
+            roomNum: '智慧教室',
+            class: '課堂數',
+        },
+        year: {
+            class: '今年課堂總計',
+            activity: '今年活動總計',
+            interaction: '今年互動總計',
+        },
+        class: {
+            lessonTitle: '課堂',
+            activityTitle: '活動',
+            interactionTitle: '互動',
+            totalTitle: '總數據',
+            todayData: '今日數據',
+            contrastYesterday: '昨日對比',
+            contrastLastmonth: '上月對比',
+            contrastLastyear: '去年對比',
+        },
+        gradeTitle: '年級佔比',
+        subjectTitle: '科目佔比',
+    },
 }

+ 7 - 7
TEAMModelOS/ClientApp/src/view/areaMgmt/AreaEcharts/gradePie.vue

@@ -107,13 +107,13 @@ class InitChart {
     this.state.chart && this.destory()
     this.state.chart = echarts.init(this.myEcharts)
     this.state.chart.setOption({
-      title: {
-        text: '年级占比',
-        textStyle: {
-          fontSize: '12',
-          color: '#b2bec3',
-        },
-      },
+      //title: {
+      //  text: '年级占比',
+      //  textStyle: {
+      //    fontSize: '12',
+      //    color: '#b2bec3',
+      //  },
+      //},
       color: color,
       tooltip: {
         show: true,

+ 74 - 76
TEAMModelOS/ClientApp/src/view/areaMgmt/AreaIndex.vue

@@ -17,15 +17,15 @@
                             <p class="right-top-title">{{item.title}}</p>
                         </div>
                         <div class="right-top-bottombox-comparison" v-if="item.classname ==='school' || item.classname ==='teach' || item.classname ==='datas' || item.classname ==='student'">
-                            <p>周新增:<span class="week-comparison">{{item.addweek}}</span></p>
-                            <p>月新增:<span class="months-comparison">{{item.addmonth}}</span></p>
+                            <p>{{$t('areaStatistics.header.weekAdd')}}:<span class="week-comparison">{{item.addweek}}</span></p>
+                            <p>{{$t('areaStatistics.header.monthAdd')}}:<span class="months-comparison">{{item.addmonth}}</span></p>
                         </div>
                     </div>
                 </div>
             </div>
             <div class="leftbox">
                 <div class="tagbox">
-                    <p class="tags basics"><span>基础数据</span></p>
+                    <p class="tags basics"><span>{{$t('areaStatistics.tag.basics')}}</span></p>
                 </div>
                 <div :class="[items.type==='month' ? 'alonebox' :'totalalonebox']" v-for="(items,indexs) in activityData.oneself" :key="indexs">
                     <p :class="[items.type ==='month' ? 'alonebox-title':'total-alonebox-title']">{{items.title}}</p>
@@ -34,7 +34,7 @@
             </div>
             <div class="rightbox">
                 <div class="tagbox">
-                    <p class="tags basics"><span>基础数据</span></p>
+                    <p class="tags basics"><span>{{$t('areaStatistics.tag.basics')}}</span></p>
                 </div>
                 <!--<div class="rightbox-pie">
                <CommonPie :proportionData="areaData.alonePie"></CommonPie>
@@ -51,19 +51,19 @@
         <div class="center-resource">
             <div class="center-resource-left">
                 <div class="tagbox ">
-                    <p class="tags source"><span>课例数据</span></p>
+                    <p class="tags source"><span>{{$t('areaStatistics.tag.classData')}}</span></p>
                 </div>
                 <div class="center-resource-left-leftEcharts">
-                    <div class="echarts-title">今年总数据:</div>
+                    <div class="echarts-title">{{$t('areaStatistics.class.total')}}:</div>
                     <ConventionPie :pieData="areaData.class"></ConventionPie>
                 </div>
                 <div class="center-resource-left-rightbox">
                     <div class="week-echart">
-                        <div class="echarts-title-pie">上周:</div>
+                        <div class="echarts-title-pie">{{$t('areaStatistics.class.lastWeek')}}:</div>
                         <ConventionPie :pieData="areaData.lastweek"></ConventionPie>
                     </div>
                     <div class="month-echart">
-                        <div class="echarts-title-pie">本月:</div>
+                        <div class="echarts-title-pie">{{$t('areaStatistics.class.nowMonth')}}:</div>
                         <ConventionPie :pieData="areaData.monthsContrast"></ConventionPie>
                     </div>
                 </div>
@@ -71,7 +71,7 @@
             </div>
             <div class="center-resource-right">
                 <div class="tagbox">
-                    <p class="tags dynamic"><span>课例活跃度</span></p>
+                    <p class="tags dynamic"><span>{{$t('areaStatistics.tag.classActive')}}</span></p>
                 </div>
                 <CommonLine :lineData="areaData.dynamic"></CommonLine>
             </div>
@@ -79,13 +79,13 @@
         <div class="bottom-resource">
             <div class="bottom-leftbox">
                 <div class="tagbox">
-                    <p class="tags types"><span>研修进度</span></p>
+                    <p class="tags types"><span>{{$t('areaStatistics.tag.training')}}</span></p>
                 </div>
                 <DoublePie :doublePieData="areaData.schedule"></DoublePie>
             </div>
             <div class="bottom-rightbox">
                 <div class="tagbox">
-                    <p class="tags interspace"><span>空间使用情况</span></p>
+                    <p class="tags interspace"><span>{{$t('areaStatistics.tag.size')}}</span></p>
                 </div>
                 <div class="bottom-rightbox-left">
                     <Liquidfill :liquidfillData="areaData.size"></Liquidfill>
@@ -97,7 +97,7 @@
         </div>
         <div class="school-Listinfo">
             <div class="tagbox">
-                <p class="tags schoolLists"><span>学校列表</span></p>
+                <p class="tags schoolLists"><span>{{$t('areaStatistics.tag.list')}}</span></p>
             </div>
             <div class="listbox">
                 <Table :columns="columns" :data="data">
@@ -129,11 +129,11 @@
            states:'develop',
            showPattern:'all',
            aspectsData:[
-               { id: 1, title: '区内学校', num: 0, icon: 'iconfont icon-24gl-school', classname: 'months', addweek: 0, addmonth: 0, },
-               { id: 2, title: '区内老师', num: 0, icon: 'iconfont icon-laoshi', classname: 'teach', addweek: 0, addmonth: 0, },
-               { id: 3, title: '区内学生', num: 0, icon: 'iconfont icon-w_xuesheng-', classname: 'school', addweek: 0, addmonth: 0, },
-               { id: 4, title: '产出总数据', num: 0, icon: 'iconfont icon-shujutongji', classname: 'datas', addweek: 0, addmonth: 0, },
-               { id: 5, title: '空间总容量', num: 0, icon: 'iconfont icon-kongjian', classname: 'size' },
+               { id: 1, title: this.$t('areaStatistics.header.areaTilte'), num: 0, icon: 'iconfont icon-24gl-school', classname: 'months', addweek: 0, addmonth: 0, },
+               { id: 2, title: this.$t('areaStatistics.header.areaTeach'), num: 0, icon: 'iconfont icon-laoshi', classname: 'teach', addweek: 0, addmonth: 0, },
+               { id: 3, title: this.$t('areaStatistics.header.areaStudent'), num: 0, icon: 'iconfont icon-w_xuesheng-', classname: 'school', addweek: 0, addmonth: 0, },
+               { id: 4, title: this.$t('areaStatistics.header.areaData'), num: 0, icon: 'iconfont icon-shujutongji', classname: 'datas', addweek: 0, addmonth: 0, },
+               { id: 5, title: this.$t('areaStatistics.header.areaSize'), num: 0, icon: 'iconfont icon-kongjian', classname: 'size' },
             ],
             aspectsLoading:{
                 counselorData: true,
@@ -146,25 +146,25 @@
                 schoolList: true,
             },
             activityData:{
-                total: [
-                    { id: 1, title: '本周课例数', num: 0, type: 'month' },
-                    { id: 2, title: '学期课例数', num: 0, type: 'month' },
-                    { id: 3, title: '本周活动数', num: 0, type: 'month' },
-                    { id: 4, title: '学期活动数', num: 0, type: 'month' },
-                    { id: 5, title: '智慧教室', num: 0, type: 'total' },
-                    { id: 6, title: '累计课例', num: 0, type: 'total' },
-                    { id: 7, title: '累计资源', num: 0, type: 'total' },
-                    { id: 8, title: '累计活动', num: 0, type: 'total' },
-                ],
+                //total: [
+                //    { id: 1, title: '本周课例数', num: 0, type: 'month' },
+                //    { id: 2, title: '学期课例数', num: 0, type: 'month' },
+                //    { id: 3, title: '本周活动数', num: 0, type: 'month' },
+                //    { id: 4, title: '学期活动数', num: 0, type: 'month' },
+                //    { id: 5, title: '智慧教室', num: 0, type: 'total' },
+                //    { id: 6, title: '累计课例', num: 0, type: 'total' },
+                //    { id: 7, title: '累计资源', num: 0, type: 'total' },
+                //    { id: 8, title: '累计活动', num: 0, type: 'total' },
+                //],
                 oneself: [
-                    { id: 1, title: '本周课例数', num: 0, type: 'month' },
-                    { id: 2, title: '学期课例数', num: 0, type: 'month' },
-                    { id: 3, title: '本周活动数', num: 0, type: 'month' },
-                    { id: 4, title: '学期活动数', num: 0, type: 'month' },
-                    { id: 5, title: '累计开课', num: 0, type: 'total' },
-                    { id: 6, title: '累计课例', num: 0, type: 'total' },
-                    { id: 7, title: '累计资源', num: 0, type: 'total' },
-                    { id: 8, title: '累计活动', num: 0, type: 'total' },
+                    { id: 1, title: this.$t('areaStatistics.basics.weekClass'), num: 0, type: 'month' },
+                    { id: 2, title: this.$t('areaStatistics.basics.semesterClass'), num: 0, type: 'month' },
+                    { id: 3, title: this.$t('areaStatistics.basics.weekActivity'), num: 0, type: 'month' },
+                    { id: 4, title: this.$t('areaStatistics.basics.semesterActivity'), num: 0, type: 'month' },
+                    { id: 5, title: this.$t('areaStatistics.basics.accumulatedClass'), num: 0, type: 'total' },
+                    { id: 6, title: this.$t('areaStatistics.basics.accumulatedExample'), num: 0, type: 'total' },
+                    { id: 7, title: this.$t('areaStatistics.basics.accumulatedResource'), num: 0, type: 'total' },
+                    { id: 8, title: this.$t('areaStatistics.basics.accumulatedActivity'), num: 0, type: 'total' },
                 ],
             },
             unit:{
@@ -205,11 +205,9 @@
         searchAreasv:'',
         searchOriginal: [],
         columns:[
-            {
-                title: '校徽', slot: 'badge', align: 'center',
-            },
-            { title: '名称', key: 'name', align: 'center'},
-            { title: '简码', key: 'id', align: 'center'},
+            { title: this.$t('areaStatistics.list.badge'), slot: 'badge', align: 'center',},
+            { title: this.$t('areaStatistics.list.name'), key: 'name', align: 'center'},
+            { title: this.$t('areaStatistics.list.code'), key: 'id', align: 'center'},
            /* { title: '空间', solt: 'size', align: 'center' },*/
            /* { title: '操作', solt: 'operate', align: 'center' },*/
             {
@@ -335,10 +333,10 @@
                                     },
                                 },
                                 data: [
-                                    { value: 0, name: '评量测验' },
-                                    { value: 0, name: '投票活动' },
-                                    { value: 0, name: '问卷调查' },
-                                    { value: 0, name: '作业活动' },
+                                    { value: 0, name: this.$t('areaStatistics.basics.evaluating') },
+                                    { value: 0, name: this.$t('areaStatistics.basics.vote') },
+                                    { value: 0, name: this.$t('areaStatistics.basics.questionnaire') },
+                                    { value: 0, name: this.$t('areaStatistics.basics.work') },
                                 ],
                             },
                         ],
@@ -373,9 +371,9 @@
                                     },
                                 },
                                 data: [
-                                    { value: 0, name: '基础版' },
-                                    { value: 0, name: '标准版' },
-                                    { value: 0, name: '专业版' },
+                                    { value: 0, name: this.$t('areaStatistics.basics.basicsV') },
+                                    { value: 0, name: this.$t('areaStatistics.basics.standardV') },
+                                    { value: 0, name: this.$t('areaStatistics.basics.marjorV') },
                                 ],
                             },
                         ],
@@ -572,7 +570,7 @@
                             end: 35
                         }],
                         series: [{
-                            name: "活跃度",
+                            name: this.$t('areaStatistics.class.vitality'),
                             type: "line",
                             symbolSize: 10,
                             symbol: 'circle',
@@ -603,9 +601,9 @@
                     schedule: {
                         color: ['#3fb1e3', '#6be6c1', '#626c91', '#a0a7e6', '#c4ebad', '#96dee8'],
                         data: [
-                            { value: 0, name: '已完成' },
-                            { value: 0, name: '进行中' },
-                            { value: 0, name: '未完成' },
+                            //{ value: 0, name: '已完成' },
+                            //{ value: 0, name: '进行中' },
+                            //{ value: 0, name: '未完成' },
                         ],
                         tooltip: {
                             trigger: 'item',
@@ -622,10 +620,10 @@
                                 fontSize: 12,
                             },
                             data: [
-                                { value: 0, name: '线上研修' },
-                                { value: 0, name: '校本研修' },
-                                { value: 0, name: '认证材料' },
-                                { value: 0, name: '课堂实录' },
+                                //{ value: 0, name: '线上研修' },
+                                //{ value: 0, name: '校本研修' },
+                                //{ value: 0, name: '认证材料' },
+                                //{ value: 0, name: '课堂实录' },
                             ],
                         },
                         series: [
@@ -657,10 +655,10 @@
                                 type: 'pie',
                                 radius: ['65%', '90%'],
                                 data: [
-                                    { value: 0, name: '线上研修' },
-                                    { value: 0, name: '校本研修' },
-                                    { value: 0, name: '认证材料' },
-                                    { value: 0, name: '课堂实录' },
+                                    //{ value: 0, name: '线上研修' },
+                                    //{ value: 0, name: '校本研修' },
+                                    //{ value: 0, name: '认证材料' },
+                                    //{ value: 0, name: '课堂实录' },
                                 ],
                             },
                         ],
@@ -788,15 +786,15 @@
                         /*this.areaData.dynamic.series[1].data = res.weekLess*/
                         //处理研修进度
                         let outer = [
-                            { value: 0, name: '线上研修' },
-                            { value: 0, name: '校本研修' },
-                            { value: 0, name: '认证材料' },
-                            { value: 0, name: '课堂实录' },
+                            { value: 0, name: this.$t('areaStatistics.research.online') },  //线上研修
+                            { value: 0, name: this.$t('areaStatistics.research.researchTraining') },  //校本研修
+                            { value: 0, name: this.$t('areaStatistics.research.attestation') },  //认证材料
+                            { value: 0, name: this.$t('areaStatistics.research.classroom') },  //课堂实录
                         ]
                         let within = [
-                            { value: 0, name: '已完成' },
-                            { value: 0, name: '进行中' },
-                            { value: 0, name: '未完成' },
+                            { value: 0, name: this.$t('areaStatistics.research.accomplish') },   //已完成
+                            { value: 0, name: this.$t('areaStatistics.research.underway') },   //进行中
+                            { value: 0, name: this.$t('areaStatistics.research.unfinished') },   //未完成
                         ]
                         outer[0].value = res.areaScStats.srStats.online
                         outer[1].value = res.areaScStats.srStats.offline
@@ -847,7 +845,7 @@
                 console.log(this.sizeNums, '空间使用率')
                 let pies = {
                     title: {
-                        text: '{a|' + this.sizeNums + '}{c|%}' + '\n' + '空间使用率',
+                        text: '{a|' + this.sizeNums + '}{c|%}' + '\n' + this.$t('areaStatistics.size.use'),
                         x: 'center',
                         y: 'center',
                         textStyle: {
@@ -931,15 +929,15 @@
                 this.areaData.size=pies
                 //处理空间占比
                 let namedata = [
-                    { name: '文档', title: 'doc', value: 0 },
-                    { name: '图片', title: 'image', value: 0 },
-                    { name: '其他', title: 'other', value: 0 },
-                    { name: '视频', title: 'video', value: 0 },
-                    { name: '缩略图', title: 'thum', value: 0 },
-                    { name: '教材', title: 'res', value: 0 },
-                    { name: '音频', title: 'audio', value: 0 },
-                    { name: 'HiTeach上传的数据', title: 'records', value: 0 },
-                    { name: '德育风采', title: 'elegant', value: 0 },
+                    { name: this.$t('areaStatistics.size.documents'), title: 'doc', value: 0 },
+                    { name: this.$t('areaStatistics.size.image'), title: 'image', value: 0 },
+                    { name: this.$t('areaStatistics.size.other'), title: 'other', value: 0 },
+                    { name: this.$t('areaStatistics.size.video'), title: 'video', value: 0 },
+                    { name: this.$t('areaStatistics.size.thumbnail'), title: 'thum', value: 0 },
+                    { name: this.$t('areaStatistics.size.material'), title: 'res', value: 0 },
+                    { name: this.$t('areaStatistics.size.audio'), title: 'audio', value: 0 },
+                    { name: this.$t('areaStatistics.size.hiteachs'), title: 'records', value: 0 },
+                    { name: this.$t('areaStatistics.size.moralEducation'), title: 'elegant', value: 0 },
                 ]
                 for (let i in namedata) {
                     let names = namedata[i].name

+ 47 - 32
TEAMModelOS/ClientApp/src/view/areaMgmt/AreaSchool.vue

@@ -9,19 +9,19 @@
                 </div>
                 <div class="school-analyse-headersbox-basics">
                     <div class="items-basics">
-                        <p class="items-basics-title">教师数:</p>
+                        <p class="items-basics-title">{{$t('schoolStatistics.header.teachNum')}}:</p>
                         <p class="items-basics-num">{{anSchool.teachNum}}</p>
                     </div>
                     <div class="items-basics">
-                        <p class="items-basics-title">学生数:</p>
+                        <p class="items-basics-title">{{$t('schoolStatistics.header.studentNum')}}:</p>
                         <p class="items-basics-num">{{anSchool.studentNum}}</p>
                     </div>
                     <div class="items-basics">
-                        <p class="items-basics-title">智慧教室:</p>
+                        <p class="items-basics-title">{{$t('schoolStatistics.header.roomNum')}}:</p>
                         <p class="items-basics-num">{{anSchool.classNum}}</p>
                     </div>
                     <div class="items-basics">
-                        <p class="items-basics-title">课例数:</p>
+                        <p class="items-basics-title">{{$t('schoolStatistics.header.class')}}:</p>
                         <p class="items-basics-num">{{anSchool.classInfoNum}}</p>
                     </div>
                 </div>
@@ -34,17 +34,17 @@
         </div>
         <div class="school-analyse-top">
             <div class="school-analyse-top-left">
-                <div class="echarts-titles"><span>今年课例总计:{{anSchool.class}}</span></div>
+                <div class="echarts-titles"><span>{{$t('schoolStatistics.year.class')}}:{{anSchool.class}}</span></div>
                 <div class="notdatas" v-if="detailsEchart.bar1.series[0].data.length ===0 || (detailsEchart.bar1.series[0].data.length <=1 && detailsEchart.bar1.series[0].data[0]===0)">暂无数据</div>
                 <Bar :barData="detailsEchart.bar1" v-else></Bar>
             </div>
             <div class="school-analyse-top-center">
-                <div class="echarts-titles activitys"><span>今年活动总计:{{anSchool.activity}}</span></div>
+                <div class="echarts-titles activitys"><span>{{$t('schoolStatistics.year.activity')}}:{{anSchool.activity}}</span></div>
                 <div class="notdatas" v-if="detailsEchart.bar2.series[0].data.length ===0 || (detailsEchart.bar2.series[0].data.length <=1 && detailsEchart.bar2.series[0].data[0]===0)">暂无数据</div>
                 <Bar :barData="detailsEchart.bar2" v-else></Bar>
             </div>
             <div class="school-analyse-top-right">
-                <div class="echarts-titles interact"><span>今年互动总计:{{anSchool.interact}}</span></div>
+                <div class="echarts-titles interact"><span>{{$t('schoolStatistics.year.interaction')}}:{{anSchool.interact}}</span></div>
                 <div class="notdatas" v-if="detailsEchart.bar3.series[0].data.length ===0 || (detailsEchart.bar3.series[0].data.length <=1 && detailsEchart.bar3.series[0].data[0]===0)">暂无数据</div>
                 <Bar :barData="detailsEchart.bar3" v-else></Bar>
             </div>
@@ -91,9 +91,11 @@
         </div>
         <div class="school-analyse-bottom">
             <div class="school-analyse-bottom-left">
+                <div class="gradetitle">{{$t('schoolStatistics.gradeTitle')}}</div>
                 <Gradepie :mapData="detailsGrade"></Gradepie>
             </div>
             <div class="school-analyse-bottom-right">
+                <div class="gradetitle">{{$t('schoolStatistics.subjectTitle')}}</div>
                 <ConventionPie :pieData="detailsEchart.subject"></ConventionPie>
             </div>
         </div>
@@ -406,14 +408,13 @@
                     subject: {
                         // color: ['#ef5777', '#0fbcf9', '#0be881', '#575fcf', '#ffd32a', '#55E6C1', '#3742fa', '#B33771', '#F8EFBA'],
                         color: ['#3fb1e3', '#6be6c1', '#626c91', '#a0a7e6', '#c4ebad', '#96dee8'],
-                        title: {
-                            text: '科目占比',
-                            textStyle: {
-                                fontSize: '12',
-                                color: '#b2bec3',
-                            },
-                        },
-
+                        //title: {
+                        //    text: this.$t('schoolStatistics.subjectTitle'),
+                        //    textStyle: {
+                        //        fontSize: '12',
+                        //        color: '#b2bec3',
+                        //    },
+                        //},
                         legend: {
                             right: '10%',
                             orient: 'vertical',
@@ -426,7 +427,7 @@
                         },
                         series: [
                             {
-                                name: '科目占比',
+                                name: this.$t('schoolStatistics.subjectTitle'),
                                 type: 'pie',
                                 radius: '80%',
                                 center: ['45%', '50%'],
@@ -451,62 +452,62 @@
                 detailsbasics:[
                     {
                         id: 1,
-                        title: '课例',
+                        title: this.$t('schoolStatistics.class.lessonTitle'),
                         num: 0,
                         icon: 'iconfont icon-kechengguanli',
-                        subheading: '昨日对比',
+                        subheading: this.$t('schoolStatistics.class.contrastYesterday'),
                         subheadingNum: '0%',
                         subheadingState: '',
-                        subhead: '上月对比',
+                        subhead: this.$t('schoolStatistics.class.contrastLastmonth'),
                         subheadNum: '0%',
                         subheadState: '',
                         classname: 'purples',
-                        today: '今日数据',
+                        today: this.$t('schoolStatistics.class.todayData'),
                         todayNum: 0,
                     },
                     {
                         id: 2,
-                        title: '活动',
+                        title: this.$t('schoolStatistics.class.activityTitle'),
                         num: 0,
                         icon: 'iconfont icon-huodongzhihang',
-                        subheading: '昨日对比',
+                        subheading: this.$t('schoolStatistics.class.contrastYesterday'),
                         subheadingNum: '0%',
                         subheadingState: '',
-                        subhead: '上月对比',
+                        subhead: this.$t('schoolStatistics.class.contrastLastmonth'),
                         subheadNum: '0%',
                         subheadState: '',
                         classname: 'oranges',
-                        today: '今日数据',
+                        today: this.$t('schoolStatistics.class.todayData'),
                         todayNum: 0,
                     },
                     {
                         id: 3,
-                        title: '互动',
+                        title: this.$t('schoolStatistics.class.interactionTitle'),
                         num: 0,
                         icon: 'iconfont icon-hudong1',
-                        subheading: '昨日对比',
+                        subheading: this.$t('schoolStatistics.class.contrastYesterday'),
                         subheadingNum: '0%',
                         subheadingState: '',
-                        subhead: '上月对比',
+                        subhead: this.$t('schoolStatistics.class.contrastLastmonth'),
                         subheadNum: '0%',
                         subheadState: '',
                         classname: 'blues',
-                        today: '今日数据',
+                        today: this.$t('schoolStatistics.class.todayData'),
                         todayNum: 0,
                     },
                     {
                         id: 3,
-                        title: '总数据',
+                        title: this.$t('schoolStatistics.class.totalTitle'),
                         num: 0,
                         icon: 'iconfont icon-shuju',
-                        subheading: '上月对比',
+                        subheading: this.$t('schoolStatistics.class.contrastLastmonth'),
                         subheadingNum: '0%',
                         subheadingState: '',
-                        subhead: '去年对比',
+                        subhead: this.$t('schoolStatistics.class.contrastLastyear'),
                         subheadNum: '0%',
                         subheadState: '',
                         classname: 'total',
-                        today: '今日数据',
+                        today: this.$t('schoolStatistics.class.todayData'),
                         todayNum: 0,
                     },
                 ],
@@ -736,6 +737,12 @@
                                     }
                                 }
                             }
+                            //Xdata.title = {
+                            //    text: this.$t('schoolStatistics.gradeTitle'),
+                            //    textStyle: {
+                            //        fontSize: '12',
+                            //        color: '#b2bec3',
+                            //    },}
                             this.detailsGrade = Xdata
                             console.log(Xdata, '处理的结果')
                         } else {
@@ -949,6 +956,7 @@
         width: 48%;
         height: 28vh;
         background-color: #fff;
+        position:relative;
     }
 
     .school-list {
@@ -1313,4 +1321,11 @@
         font-weight: bold;
         color: #bdc3c7;
     }
+    .gradetitle {
+        position: absolute;
+        left: 0.5%;
+        top: 0.5%;
+        font-size: 14px;
+        color: #bdc3c7;
+    }
 </style>

+ 334 - 6
TEAMModelOS/Controllers/Analysis/ClassAnalysisController.cs

@@ -8,10 +8,16 @@ using Microsoft.AspNetCore.Http;
 using Microsoft.AspNetCore.Mvc;
 using Microsoft.Extensions.Configuration;
 using Microsoft.Extensions.Options;
+using Newtonsoft.Json;
 using OpenXmlPowerTools;
+using StackExchange.Redis;
 using System;
 using System.Collections.Generic;
+using System.Configuration;
+using System.Dynamic;
 using System.Linq;
+using System.Net.Http.Headers;
+using System.Net.Http;
 using System.Text;
 using System.Text.Json;
 using System.Threading.Tasks;
@@ -23,6 +29,8 @@ using TEAMModelOS.SDK.Extension;
 using TEAMModelOS.SDK.Helper.Common.DateTimeHelper;
 using TEAMModelOS.SDK.Models;
 using TEAMModelOS.SDK.Models.Cosmos.Common;
+using System.Net;
+using System.Net.Http.Json;
 
 namespace TEAMModelOS.Controllers.Analysis
 {
@@ -39,8 +47,11 @@ namespace TEAMModelOS.Controllers.Analysis
         private readonly Option _option;
         private readonly AzureStorageFactory _azureStorage;
         private readonly CoreAPIHttpService _coreAPIHttpService;
+        private readonly AzureRedisFactory _azureRedis;
+        private readonly IConfiguration _configuration;
+        private readonly IHttpClientFactory _httpClient;
         public ClassAnalysisController(CoreAPIHttpService coreAPIHttpService, AzureCosmosFactory azureCosmos, AzureServiceBusFactory serviceBus, SnowflakeId snowflakeId, DingDing dingDing,
-            IOptionsSnapshot<Option> option, AzureStorageFactory azureStorage)
+            IOptionsSnapshot<Option> option, AzureStorageFactory azureStorage, AzureRedisFactory azureRedis, IConfiguration configuration, IHttpClientFactory httpClient)
         {
             _azureCosmos = azureCosmos;
             _serviceBus = serviceBus;
@@ -49,6 +60,9 @@ namespace TEAMModelOS.Controllers.Analysis
             _option = option?.Value;
             _azureStorage = azureStorage;
             _coreAPIHttpService = coreAPIHttpService;
+            _azureRedis = azureRedis;
+            _configuration = configuration;
+            _httpClient = httpClient;
         }
         /// <param name="request"></param>
         /// <returns></returns>
@@ -83,6 +97,116 @@ namespace TEAMModelOS.Controllers.Analysis
                     records.Add(item);
 
                 }
+                double teacherCount = 0;
+                await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIterator(queryText: $"SELECT count(1) as teachers FROM c", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Teacher-{code}") }))
+                {
+                    using var json = await JsonDocument.ParseAsync(item.ContentStream);
+                    if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
+                    {
+                        foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
+                        {
+                            if (obj.TryGetProperty("teachers", out JsonElement teachers))
+                            {
+                                teacherCount = teachers.GetDouble();
+                            }
+                        }
+                    }
+
+                }
+                double studentCount = 0;
+                await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Student").GetItemQueryStreamIterator(queryText: $"SELECT count(1) as stus FROM c where c.periodId = '{pId}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Base-{code}") }))
+                {
+                    using var json = await JsonDocument.ParseAsync(item.ContentStream);
+                    if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
+                    {
+                        foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
+                        {
+                            if (obj.TryGetProperty("stus", out JsonElement stus))
+                            {
+                                studentCount = stus.GetDouble();
+                            }
+                        }
+                    }
+
+                }
+                double itemCount = 0;
+                await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIterator(queryText: $"SELECT count(1) as items FROM c where c.periodId = '{pId}' and c.pid = null and c.scope = 'school' ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Item-{code}") }))
+                {
+                    using var json = await JsonDocument.ParseAsync(item.ContentStream);
+                    if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
+                    {
+                        foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
+                        {
+                            if (obj.TryGetProperty("items", out JsonElement items))
+                            {
+                                itemCount = items.GetDouble();
+                            }
+                        }
+                    }
+                }
+
+                double paperCount = 0;
+                await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIterator(queryText: $"SELECT count(1) as papers FROM c where c.periodId = '{pId}' and c.scope = 'school' ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Paper-{code}") }))
+                {
+                    using var json = await JsonDocument.ParseAsync(item.ContentStream);
+                    if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
+                    {
+                        foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
+                        {
+                            if (obj.TryGetProperty("papers", out JsonElement papers))
+                            {
+                                paperCount = papers.GetDouble();
+                            }
+                        }
+                    }
+                }
+                double voteCount = 0;
+                await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryStreamIterator(queryText: $"SELECT count(1) as votes FROM c where c.periodId = '{pId}' and c.scope = 'school' ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Vote-{code}") }))
+                {
+                    using var json = await JsonDocument.ParseAsync(item.ContentStream);
+                    if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
+                    {
+                        foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
+                        {
+                            if (obj.TryGetProperty("votes", out JsonElement votes))
+                            {
+                                voteCount = votes.GetDouble();
+                            }
+                        }
+                    }
+                }
+                double surveyCount = 0;
+                await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryStreamIterator(queryText: $"SELECT count(1) as surveys FROM c where c.periodId = '{pId}' and c.scope = 'school' ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Survey-{code}") }))
+                {
+                    using var json = await JsonDocument.ParseAsync(item.ContentStream);
+                    if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
+                    {
+                        foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
+                        {
+                            if (obj.TryGetProperty("surveys", out JsonElement surveys))
+                            {
+                                surveyCount = surveys.GetDouble();
+                            }
+                        }
+                    }
+                }
+                double homeworkCount = 0;
+                await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryStreamIterator(queryText: $"SELECT count(1) as works FROM c where c.periodId = '{pId}' and c.scope = 'school' ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Homework-{code}") }))
+                {
+                    using var json = await JsonDocument.ParseAsync(item.ContentStream);
+                    if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
+                    {
+                        foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
+                        {
+                            if (obj.TryGetProperty("works", out JsonElement works))
+                            {
+                                homeworkCount = works.GetDouble();
+                            }
+                        }
+                    }
+                }
+                double resourcesCount = itemCount + paperCount;
+                double classRooms = await GetTeacCount(code.GetString());
                 if (records.Count > 0)
                 {
                     var response = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync(code.GetString(), new PartitionKey($"Base"));
@@ -128,12 +252,19 @@ namespace TEAMModelOS.Controllers.Analysis
                     double workCount = records.Select(c => c.collateCount).Sum();
                     double examQuizCount = records.Select(c => c.examQuizCount).Sum();
                     double interactCount = records.Select(c => c.clientInteractionCount).Sum();
+                    
                     //学校基本信息
                     School scInfo = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>($"{code}", partitionKey: new PartitionKey("Base"));
                     var perMore = scInfo.period.Where(c => c.id.Equals(pId.GetString())).FirstOrDefault().grades;
-
-                    var realrecords = records.Where(c => c.startTime >= stime.GetInt64() && c.startTime <= etime.GetInt64() && c.grade.Any()).ToList();                       
-                    List<(string name, int? cICount, int? pCount, int? cTCount, int? eCount,int? diffCount)> tcount = new();
+                    var subjects = scInfo.period.Where(c => c.id.Equals(pId.GetString())).FirstOrDefault().subjects;
+                    var realrecords = records.Where(c => c.startTime >= stime.GetInt64() && c.startTime <= etime.GetInt64() && c.grade.Any()).ToList();
+                    double attendCount = realrecords.Select(c => c.attendCount).Sum();
+                    double duration  = realrecords.Select(c => c.duration).Sum();
+                    double clientInteractionCount = realrecords.Select(c => c.clientInteractionCount).Sum();
+                    double collateCount = realrecords.Select(c => c.collateCount).Sum();
+                    var numbers = realrecords.GroupBy(x => (x.interactionCount, x.attendCount,x.id)).Select(y => new { product = y.Key.interactionCount * y.Key.attendCount }).Select(c => c.product).Sum();
+                    List <(string name, int? cICount, int? pCount, int? cTCount, int? eCount,int? diffCount)> tcount = new();
+                    List<(string name, int? cICount, int? pCount, int? cTCount, int? eCount, int? diffCount)> subjectCount = new();
                     List<(string name, int? count)> gdCount = new();
                     int gCount = 0;
                     perMore.ForEach(x =>
@@ -149,6 +280,18 @@ namespace TEAMModelOS.Controllers.Analysis
                         gCount++;
                     });
 
+                    subjects.ForEach(x =>
+                    {
+                        var cICount = realrecords.Where(c =>!string.IsNullOrEmpty(c.subjectId) && c.subjectId.Contains(x.id)).Select(z => z.learningCategory?.interaction).Sum();
+                        var pCount = realrecords.Where(c => !string.IsNullOrEmpty(c.subjectId) && c.subjectId.Contains(x.id)).Select(z => z.learningCategory?.cooperation).Sum();
+                        var tCount = realrecords.Where(c => !string.IsNullOrEmpty(c.subjectId) && c.subjectId.Contains(x.id)).Select(z => z.learningCategory?.task).Sum();
+                        var eCount = realrecords.Where(c => !string.IsNullOrEmpty(c.subjectId) && c.subjectId.Contains(x.id)).Select(z => z.learningCategory?.exam).Sum();
+                        var diffCount = realrecords.Where(c => !string.IsNullOrEmpty(c.subjectId) && c.subjectId.Contains(x.id)).Select(z => z.learningCategory?.diffential).Sum();
+                        //var gradeCount = grades.Where(c => perMore[int.Parse(c.name)].Equals(x, StringComparison.OrdinalIgnoreCase)).FirstOrDefault().count;
+                        subjectCount.Add((x.name, cICount, pCount, tCount, eCount, diffCount));
+                        //gdCount.Add((x, gradeCount));
+                    });
+
                     var teachingCount = tcount.Select(x => new
                     {
                         x.name,
@@ -158,12 +301,24 @@ namespace TEAMModelOS.Controllers.Analysis
                         exam = x.eCount == null ? 0 : x.eCount,
                         diffential = x.diffCount == null ? 0 : x.eCount
                     });
+                    var subject = subjectCount.Select(x => new
+                    {
+                        x.name,
+                        interaction = x.cICount == null ? 0 : x.cICount,
+                        cooperation = x.pCount == null ? 0 : x.pCount,
+                        task = x.cTCount == null ? 0 : x.cTCount,
+                        exam = x.eCount == null ? 0 : x.eCount,
+                        diffential = x.diffCount == null ? 0 : x.eCount
+                    });
                     var classify_grade = gdCount.Select(x => new
                     {
                         x.name,
                         value = x.count
                     });
-                    return Ok(new { total, trend, classify_group, classify_grade, classify_type, classify_sub, teachCount, taskCount, workCount, examQuizCount, interactCount, exams, teachingCount });
+                    return Ok(new { total, trend, classify_group, classify_grade, classify_type, classify_sub, teachCount, taskCount, workCount, examQuizCount, interactCount, exams, teachingCount, 
+                        subject, attendCount, duration,teacherCount,studentCount , resourcesCount ,classRooms,voteCount,surveyCount,homeworkCount,
+                        clientInteractionCount,collateCount,numbers
+                    });
                 }
                 else
                 {
@@ -177,6 +332,179 @@ namespace TEAMModelOS.Controllers.Analysis
             }
 
         }
+
+        private async Task<double> GetTeacCount(string code)
+        {
+            try
+            {
+                var db = _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School");
+                var r8 = _azureRedis.GetRedisClient(8);
+
+                List<SchoolProductSerial> serial = new(); //承接DB資料用:序號
+                List<deviceForCoreService> uuidList = new(); //要向CoreService詢問deviceID及硬體資訊的UUID列表
+                long UTCNow = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
+
+                //軟體
+                List<string> serialPermitList = SchoolController.getSerialPermitProdcodeList();
+                string serialPermitJsonStr = JsonConvert.SerializeObject(serialPermitList);
+                string serialQueryText = $"SELECT * FROM c WHERE c.dataType = 'serial' AND ARRAY_CONTAINS({serialPermitJsonStr}, c.prodCode)";
+                await foreach (var itemsr in db.GetItemQueryStreamIterator(queryText: serialQueryText, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Product-{code}") }))
+                {
+                    using var json = await JsonDocument.ParseAsync(itemsr.ContentStream);
+                    if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
+                    {
+                        deviceForCoreService uuidForCore;
+                        foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
+                        {
+                            serial.Add(obj.ToObject<SchoolProductSerial>());
+                            if (obj.TryGetProperty("deviceBound", out JsonElement deviceBoundJobj) && !string.IsNullOrWhiteSpace(deviceBoundJobj.ToString()))
+                            {
+                                foreach (var deviceBoundTmpRow in deviceBoundJobj.EnumerateArray())
+                                {
+                                    uuidForCore = new deviceForCoreService
+                                    {
+                                        sn = (!string.IsNullOrWhiteSpace(Convert.ToString(obj.GetProperty("serial")))) ? Convert.ToString(obj.GetProperty("serial")) : null,
+                                        uuid1 = (!string.IsNullOrWhiteSpace(Convert.ToString(deviceBoundTmpRow.GetProperty("uuid")))) ? Convert.ToString(deviceBoundTmpRow.GetProperty("uuid")) : null,
+                                        uuid2 = (!string.IsNullOrWhiteSpace(Convert.ToString(deviceBoundTmpRow.GetProperty("uuid2")))) ? Convert.ToString(deviceBoundTmpRow.GetProperty("uuid2")) : null,
+                                        device_id = (!string.IsNullOrWhiteSpace(Convert.ToString(deviceBoundTmpRow.GetProperty("deviceId")))) ? Convert.ToString(deviceBoundTmpRow.GetProperty("deviceId")) : null,
+                                        class_id = (!string.IsNullOrWhiteSpace(Convert.ToString(deviceBoundTmpRow.GetProperty("classId")))) ? Convert.ToString(deviceBoundTmpRow.GetProperty("classId")) : null
+                                    };
+                                    uuidList.Add(uuidForCore);
+                                }
+                            }
+                        }
+                    }
+                }
+                ////取得DeviceInfo From Core 並更新序號資料
+                List<deviceFromCoreService> coreUuidList = (List<deviceFromCoreService>)GetDeviceFromCoreAsync(uuidList).GetAwaiter().GetResult();
+                List<deviceBoundExt> deviceBoundArray;
+                List<deviceBoundExt> counts = new();
+                List<deviceFromCoreService> coreUuid;
+                deviceForCoreService deviceBoundRow;
+                deviceBoundExt deviceBoundExt;
+                List<SchoolProductSerial> updSchoolProductSerialList = new List<SchoolProductSerial>(); //更新學校產品序號用
+                foreach (SchoolProductSerial serialRow in serial)
+                {
+                    deviceBoundArray = new List<deviceBoundExt>();
+                    coreUuid = coreUuidList
+                           .Where((deviceFromCoreService x) => x.sn == serialRow.serial)
+                           .ToList();
+                    foreach (deviceFromCoreService deviceRow in coreUuid)
+                    {
+                        if (!string.IsNullOrWhiteSpace(deviceRow.uuid1) || !string.IsNullOrWhiteSpace(deviceRow.uuid2) || !string.IsNullOrWhiteSpace(deviceRow.device_id)) //uuid1、uuid2、device_id 任一欄有值
+                        {
+                            //前端顯示用
+                            deviceBoundRow = uuidList.Where(u => u.sn == deviceRow.sn && u.uuid1 == deviceRow.uuid1 && u.uuid2 == deviceRow.uuid2).FirstOrDefault();
+                            deviceBoundExt = new deviceBoundExt
+                            {
+                                uuid = deviceBoundRow.uuid1,
+                                uuid2 = deviceBoundRow.uuid2,
+                                classId = deviceBoundRow.class_id,
+                                deviceId = deviceRow.device_id,
+                                os = deviceRow.os,
+                                ip = deviceRow.local_ip,
+                                cpu = deviceRow.cpu,
+                                pcname = deviceRow.pc_name,
+                                osver = deviceRow.os_ver
+                            };
+                            deviceBoundArray.Add(deviceBoundExt);
+                        }
+                    }
+                    if (deviceBoundArray.Count.Equals(0)) //無法取得CS的硬體資訊,則用序號的硬體資訊帶入
+                    {
+                        if (serialRow.deviceBound != null)
+                        {
+                            foreach (deviceBound serialRowDeviceBound in serialRow.deviceBound)
+                            {
+                                if (!string.IsNullOrEmpty(serialRowDeviceBound.uuid) || !string.IsNullOrEmpty(serialRowDeviceBound.uuid2))
+                                {
+                                    deviceBoundExt = new deviceBoundExt
+                                    {
+                                        uuid = serialRowDeviceBound.uuid,
+                                        uuid2 = serialRowDeviceBound.uuid2,
+                                        classId = serialRowDeviceBound.classId,
+                                        deviceId = serialRowDeviceBound.deviceId
+                                    };
+                                    deviceBoundArray.Add(deviceBoundExt);
+                                }
+                            }
+                        }
+                    }
+                    //序號更新
+                    //updSchoolProductSerialList.Add(serialRow);
+                    counts.AddRange(deviceBoundArray);
+                    //await db.ReplaceItemAsync<SchoolProductSerial>(serialRow, serialRow.id, new PartitionKey($"Product-{school_code}"));
+                }
+                //取得CC授權使用狀態
+                var hashs = await r8.HashGetAllAsync($"CC:License:{code}");
+                var ccuser = hashs.Select(x => JsonDocument.Parse(x.Value.ToString())).ToList();
+
+                //更新學校產品序號
+                //_ = UpdupdSchoolProductSerialListAsync(updSchoolProductSerialList, school_code.GetString());
+                double Teachs = counts.Count + ccuser.Count;
+                return Teachs;
+            }
+            catch (Exception ex)
+            {
+                return 0;
+            }
+        }
+
+        private async Task<List<deviceFromCoreService>> GetDeviceFromCoreAsync(List<deviceForCoreService> uuidList)
+        {
+            List<deviceFromCoreService> result = new List<deviceFromCoreService>();
+            try
+            {
+                string url = _configuration.GetValue<string>("HaBookAuth:CoreService:deviceinfo");
+                string AccessToken = await getCoreAccessToken();
+                var client = _httpClient.CreateClient();
+                client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", AccessToken);
+                string uuidListJson = JsonConvert.SerializeObject(uuidList);
+                var content = new StringContent(uuidListJson, Encoding.UTF8, "application/json");
+                HttpResponseMessage responseMessage = await client.PostAsync(url, content);
+                if (responseMessage.StatusCode == HttpStatusCode.OK)
+                {
+                    string responseBody = responseMessage.Content.ReadAsStringAsync().Result;
+                    result = System.Text.Json.JsonSerializer.Deserialize<List<deviceFromCoreService>>(responseBody.ToString());
+                }
+                return result;
+            }
+            catch (Exception ex)
+            {
+                return result;
+            }
+        }
+
+        private async Task<string> getCoreAccessToken()
+        {
+            string AccessToken = "";
+            try
+            {
+                string Url = _configuration.GetValue<string>("HaBookAuth:CoreAPI") + "/oauth2/token";
+                string GrantType = "device";
+                string ClientID = _configuration.GetValue<string>("HaBookAuth:CoreService:clientID");
+                string Secret = _configuration.GetValue<string>("HaBookAuth:CoreService:clientSecret");
+                var content = new { grant_type = GrantType, client_id = ClientID, client_secret = Secret };
+                var response = await _httpClient.CreateClient().PostAsJsonAsync($"{Url}", content);
+                if (response.IsSuccessStatusCode)
+                {
+                    string responseBody = response.Content.ReadAsStringAsync().Result;
+                    using (JsonDocument document = JsonDocument.Parse(responseBody.ToString()))
+                    {
+                        if (document.RootElement.TryGetProperty("access_token", out JsonElement AccessTokenObj))
+                        {
+                            AccessToken = AccessTokenObj.ToString();
+                        }
+                    }
+                }
+                return AccessToken;
+            }
+            catch (Exception ex)
+            {
+                return AccessToken;
+            }
+        }
+
         /// <param name="request"></param>
         /// <returns></returns>
         [ProducesDefaultResponseType]
@@ -884,6 +1212,6 @@ namespace TEAMModelOS.Controllers.Analysis
                 await _dingDing.SendBotMsg($"OS,{_option.Location},area/get-students()\n{e.Message}\n{e.StackTrace}", GroupNames.醍摩豆服務運維群組);
                 return new List<string>();
             }
-        }
+        }       
     }
 }