Преглед на файлове

Merge branch 'develop' into PL/develop-BI

Li преди 3 години
родител
ревизия
1b473dfa30
променени са 42 файла, в които са добавени 6742 реда и са изтрити 1365 реда
  1. 1 1
      TEAMModelBI/ClientApp/public/index.html
  2. 158 73
      TEAMModelBI/ClientApp/src/components/echarts/test.vue
  3. 18 0
      TEAMModelBI/ClientApp/src/router/index.js
  4. 6 1
      TEAMModelBI/ClientApp/src/store/index.js
  5. 27 0
      TEAMModelBI/ClientApp/src/view/common/aside.vue
  6. 2 1
      TEAMModelBI/ClientApp/src/view/index/index.vue
  7. 935 0
      TEAMModelBI/ClientApp/src/view/participation/index.vue
  8. 1442 0
      TEAMModelBI/ClientApp/src/view/participation/setAbility.vue
  9. 2170 0
      TEAMModelBI/ClientApp/src/view/participation/setPhase.vue
  10. 75 5
      TEAMModelBI/ClientApp/src/view/schoolServe/analyseSchool.vue
  11. 18 10
      TEAMModelBI/ClientApp/src/view/schoolServe/school.vue
  12. 3 2
      TEAMModelBI/ClientApp/src/view/schoolServe/setschool.vue
  13. 1 1
      TEAMModelBI/Controllers/BISchool/BatchSchoolController.cs
  14. 1 1
      TEAMModelBI/Controllers/BISchool/SchoolController.cs
  15. 37 14
      TEAMModelOS.FunctionV4/ServiceBus/ActiveTaskTopic.cs
  16. 1 0
      TEAMModelOS.SDK/Context/Constant/Constant.cs
  17. 7 0
      TEAMModelOS.SDK/Models/Cosmos/Common/LessonRecord.cs
  18. 1 0
      TEAMModelOS.SDK/Models/Cosmos/School/Paper.cs
  19. 19 2
      TEAMModelOS.SDK/Models/Cosmos/School/SchoolSetting.cs
  20. 351 0
      TEAMModelOS.SDK/Models/Service/LessonService.cs
  21. 4 1
      TEAMModelOS.SDK/Models/Service/Third/Xkw/XkwOAuthModel.cs
  22. 10 2
      TEAMModelOS/ClientApp/public/index.html
  23. 4 8
      TEAMModelOS/ClientApp/public/lang/en-US.js
  24. 5 9
      TEAMModelOS/ClientApp/public/lang/zh-CN.js
  25. 11 15
      TEAMModelOS/ClientApp/public/lang/zh-TW.js
  26. 1 1
      TEAMModelOS/ClientApp/src/api/lessonRecord.js
  27. 6 20
      TEAMModelOS/ClientApp/src/locale/index.js
  28. 60 3
      TEAMModelOS/ClientApp/src/utils/public.js
  29. 3 0
      TEAMModelOS/ClientApp/src/view/evaluation/bank/TestPaperList.vue
  30. 2 2
      TEAMModelOS/ClientApp/src/view/evaluation/index/TestPaper.vue
  31. 153 116
      TEAMModelOS/ClientApp/src/view/research-center/BaseCleanCond.vue
  32. 814 802
      TEAMModelOS/ClientApp/src/view/research-center/ResearchMgt.vue
  33. 224 223
      TEAMModelOS/ClientApp/src/view/settings/Index.vue
  34. 2 1
      TEAMModelOS/ClientApp/src/view/student-analysis/total-analysis/EvaluationList/TotalIndex.vue
  35. 15 8
      TEAMModelOS/ClientApp/src/view/user/BandPhone.vue
  36. 3 3
      TEAMModelOS/Controllers/Both/PaperController.cs
  37. 2 0
      TEAMModelOS/Controllers/Both/SheetConfigController.cs
  38. 4 0
      TEAMModelOS/Controllers/School/SchoolSettingController.cs
  39. 66 7
      TEAMModelOS/Controllers/Student/StudentCommonController.cs
  40. 30 16
      TEAMModelOS/Controllers/Third/Sc/ScController.cs
  41. 18 2
      TEAMModelOS/Controllers/Third/Xkw/XkwOAuth2Controller.cs
  42. 32 15
      TEAMModelOS/Controllers/XTest/FixDataController.cs

+ 1 - 1
TEAMModelBI/ClientApp/public/index.html

@@ -11,7 +11,7 @@
     </title>
 </head>
 <script src="https://g.alicdn.com/dingding/dinglogin/0.0.5/ddLogin.js"></script>
-<script src="https://at.alicdn.com/t/font_2934132_mqzvxjqejqd.js"></script>
+<script src="https://at.alicdn.com/t/font_2934132_p2tqleauqsn.js"></script>
 
 <body>
     <noscript>

+ 158 - 73
TEAMModelBI/ClientApp/src/components/echarts/test.vue

@@ -6,7 +6,6 @@
 import { ref, onMounted, nextTick, watch, getCurrentInstance } from 'vue'
 import * as echarts from 'echarts'
 export default {
-    name: 'baseBar',
     props: {
         width: {
             type: String,
@@ -16,9 +15,9 @@ export default {
             type: String,
             default: '100%',
         },
-        mapData: {
-            type: Array,
-            default: () => [],
+        meterData: {
+            type: Object,
+            default: () => {},
         },
         title: {
             type: String,
@@ -26,18 +25,17 @@ export default {
         },
     },
     setup(props) {
-        console.log(props.mapData, '传进来的值')
         const myEcharts = ref(null)
         let { proxy } = getCurrentInstance()
         const chart = new InitChart(props, myEcharts)
         onMounted(() => {
-            chart.init(props.mapData, proxy)
+            chart.init(props.barData, proxy)
         })
         watch(
             props,
             (nweProps) => {
                 nextTick(() => {
-                    chart.init(props.mapData, proxy)
+                    nweProps ? chart.init(props.barData, proxy) : ''
                 })
             },
             { immediate: true, deep: true }
@@ -56,92 +54,179 @@ class InitChart {
         }
     }
     init(datas, proxy) {
+        var xdata = ['去年同月累计', '去年同月', '年初至本月累计', '本月']
+        var ydata = ['课例数量', '科技互动次数', '苏格拉底影片', '影片双绿灯数', '模组服务购买使用']
+        var vdata1 = [870, 799, 260, 130, 23]
+        var vdata2 = [260, 180, 21, 15, 5]
+        var vdata3 = [652, 378, 120, 167, 45]
+        var vdata4 = [267, 356, 59, 45, 10]
+        var fontColor = '#30eee9'
+        var piedata1 = [
+            {
+                name: '小学',
+                value: 25,
+            },
+            {
+                name: '初中',
+                value: 10,
+            },
+            {
+                name: '高中',
+                value: 5,
+            },
+            {
+                name: '大学',
+                value: 0,
+            },
+        ]
+        var piedata2 = [
+            {
+                name: '语文',
+                value: 580,
+            },
+            {
+                name: '数学',
+                value: 430,
+            },
+            {
+                name: '英语',
+                value: 495,
+            },
+            {
+                name: '政治',
+                value: 105,
+            },
+            {
+                name: '音乐',
+                value: 230,
+            },
+            {
+                name: '计算机',
+                value: 360,
+            },
+        ]
+        var piedata3 = [
+            {
+                name: '课例',
+                value: 580,
+            },
+            {
+                name: '资源',
+                value: 150,
+            },
+            {
+                name: '活动',
+                value: 320,
+            },
+        ]
         this.state.chart && this.destory()
         this.state.chart = echarts.init(this.myEcharts.value)
         this.state.chart.setOption({
-            title: {
-                text: '研修完成度',
+            backgroundColor: '#fff',
+            // title: {
+            //     text: '2020年1-4月港口吞吐量情况',
+            //     fontColor: '#FFF',
+            // },
+            color: ['#3fb1e3', '#6be6c1', '#626c91', '#a0a7e6', '#c4ebad', '#96dee8'],
+            legend: {
+                data: xdata,
                 textStyle: {
-                    color: '#595959',
-                    fontSize: 14,
+                    color: fontColor,
                 },
-                // subtext: '年度任务总数:18个',
-                // subtextStyle: {
-                //     fontSize: 14,
-                //     color: '#8C8C8C',
-                // },
-                itemGap: 20,
-                left: 'center',
-                top: '55%',
-            },
-            angleAxis: {
-                max: 100,
-                clockwise: true, // 逆时针
-                // 隐藏刻度线
-                show: false,
-            },
-            radiusAxis: {
-                type: 'category',
-                show: true,
+                top: '1%',
+            },
+            tooltip: {},
+            xAxis: {
+                type: 'value',
                 axisLabel: {
-                    show: false,
+                    color: fontColor,
                 },
-                axisLine: {
-                    show: false,
+                splitLine: {
+                    lineStyle: {
+                        type: 'dashed',
+                        color: fontColor,
+                    },
                 },
-                axisTick: {
-                    show: false,
+                axisLine: {
+                    show: true,
+                    lineStyle: {
+                        color: fontColor,
+                    },
                 },
             },
-            polar: {
-                center: ['50%', '50%'],
-                radius: '110%', //图形大小
+            yAxis: {
+                data: ydata,
+                axisLabel: {
+                    color: fontColor,
+                },
+                axisLine: {
+                    show: true,
+                    lineStyle: {
+                        color: fontColor,
+                    },
+                },
             },
+            grid: [
+                {
+                    bottom: '55%',
+                    top: '10%',
+                    left: '10%',
+                    right: '10%',
+                },
+            ],
             series: [
                 {
+                    name: '去年同月累计',
                     type: 'bar',
-                    data: [60],
-                    showBackground: true,
-                    coordinateSystem: 'polar',
-                    roundCap: true,
-                    barWidth: 8,
-                    itemStyle: {
-                        normal: {
-                            opacity: 1,
-                            color: '#1890FF',
-                        },
-                    },
-                    z: 10,
+                    data: vdata1,
                 },
                 {
+                    name: '去年同月',
                     type: 'bar',
-                    data: [100],
-                    showBackground: true,
-                    barGap: '-100%',
-                    coordinateSystem: 'polar',
-                    roundCap: true,
-                    barWidth: 8,
-                    itemStyle: {
-                        normal: {
-                            opacity: 1,
-                            color: '#E7E9EB',
-                        },
-                    },
+                    data: vdata2,
                 },
                 {
+                    name: '年初至本月累计',
+                    type: 'bar',
+                    data: vdata3,
+                },
+                {
+                    name: '本月',
+                    type: 'bar',
+                    data: vdata4,
+                },
+                {
+                    name: '学区学段占比',
                     type: 'pie',
-                    data: [1],
-                    radius: '90%',
-                    itemStyle: {
-                        color: 'transparent',
-                    },
-                    label: {
-                        show: true,
-                        position: 'center',
-                        formatter: 60 + '%',
-                        color: '#1890FF',
-                        fontSize: 22,
-                    },
+                    radius: '65%',
+                    //center: ['50%', '50%'],
+                    data: piedata1,
+                    bottom: '0%',
+                    top: '55%',
+                    left: '0%',
+                    right: '65%',
+                },
+                {
+                    name: '学区科目占比',
+                    type: 'pie',
+                    radius: '65%',
+                    //center: ['50%', '50%'],
+                    data: piedata2,
+                    bottom: '0%',
+                    top: '55%',
+                    left: '33%',
+                    right: '32%',
+                },
+                {
+                    name: '学区数据占比',
+                    type: 'pie',
+                    radius: '65%',
+                    //center: ['50%', '50%'],
+                    data: piedata3,
+                    bottom: '0%',
+                    top: '55%',
+                    left: '65%',
+                    right: '0%',
                 },
             ],
         })

+ 18 - 0
TEAMModelBI/ClientApp/src/router/index.js

@@ -136,6 +136,24 @@ const routes = [{
                 isShow: true,
                 component: () => require.ensure([], (require) => require(`@/view/schoolmanage/index.vue`))
             },
+            //我参与的 *学校管理(主要顾问使用)
+            {
+                name: "participation",
+                path: "participation",
+                permission: "batcharea-read|batcharea-upd|batchschool-read|batchschool-upd",
+                roles: ['admin', 'assist'],
+                isShow: true,
+                component: () => require.ensure([], (require) => require(`@/view/participation/index.vue`))
+            },
+            //我参与的 *学校管理(主要顾问使用)
+            {
+                name: "setability",
+                path: "setability",
+                permission: "batcharea-read|batcharea-upd|batchschool-read|batchschool-upd",
+                roles: ['admin', 'assist'],
+                isShow: true,
+                component: () => require.ensure([], (require) => require(`@/view/participation/setAbility.vue`))
+            },
         ]
     },
     {

+ 6 - 1
TEAMModelBI/ClientApp/src/store/index.js

@@ -14,7 +14,8 @@ export default createStore({
         },
         createModel: '',
         changbtnShow: false,
-        schoolPower: {}
+        schoolPower: {},
+        nowSchool: {},
     },
     mutations: {
         //修改组织架构
@@ -58,6 +59,10 @@ export default createStore({
         //当前选中学校的权限内容
         updateSchoolpower(state, value) {
             state.schoolPower = value
+        },
+        //当前选中学校 (用于 我参与的学校管理)
+        schoolDataInfo(state, value) {
+            state.nowSchool = value
         }
     },
     actions: {},

+ 27 - 0
TEAMModelBI/ClientApp/src/view/common/aside.vue

@@ -225,6 +225,33 @@ export default {
                     },
                 ],
             },
+            {
+                name: '我参与的',
+                icon: '#icon-canyu',
+                router: '',
+                role: ['admin', 'assist'],
+                isShow: true,
+                permission: '',
+                sort: 12,
+                child: [
+                    {
+                        name: '学校管理',
+                        router: '/home/participation',
+                        icon: '#icon-xuexiao3',
+                        permission: [],
+                        isShow: true,
+                        sort: 13,
+                    },
+                    {
+                        name: '微能力点管理',
+                        router: '/home/setability',
+                        icon: '#icon-tiaozheng1',
+                        permission: [],
+                        isShow: true,
+                        sort: 14,
+                    },
+                ],
+            },
         ]
         const isCollapse = ref(true)
         const store = useStore()

+ 2 - 1
TEAMModelBI/ClientApp/src/view/index/index.vue

@@ -11,7 +11,7 @@
                     </div>
                     <div class="right-top-text">
                         <p class="right-top-num">
-                            {{item.num}}
+                            {{item.num}}  
                         <div class="right-top-num-increase" v-if="(item.classname ==='datas' || item.classname ==='teach' || item.classname ==='student') && item.state ==='1'">
                             <span class="right-top-num-flag">+</span>
                             <span class="right-top-num-nums">7</span>
@@ -2120,6 +2120,7 @@ export default {
     overflow: hidden;
     margin-right: 5px;
     vertical-align: 20px;
+    cursor: pointer;
 }
 </style>
 <style>

+ 935 - 0
TEAMModelBI/ClientApp/src/view/participation/index.vue

@@ -0,0 +1,935 @@
+<template>
+    <!--学校列表-->
+    <div class="schoolbox" v-show="models==='default'">
+        <div class="select-List">
+            <div class="province-box">
+                <span>{{$t(`areaManages.selector.provinceName`)}}:</span>
+                <el-select v-model="provinceOptions.provinceValue" :placeholder="$t(`areaManages.selector.provinceDefault`)" @change="areaSelctChange(provinceOptions.provinceValue,'province')">
+                    <el-option v-for="item in provinceOptions.optionInfo" :key="item.code" :label="item.name" :value="item.name">
+                    </el-option>
+                </el-select>
+            </div>
+            <div class="city-box">
+                <span>{{$t(`areaManages.selector.cityName`)}}:</span>
+                <el-select v-model="cityOptions.cityValue" :placeholder="$t(`areaManages.selector.cityDefault`)" @change="areaSelctChange(cityOptions.cityValue,'city')">
+                    <el-option v-for="item in cityOptions.cityInfo" :key="item.code" :label="item.name" :value="item.name">
+                    </el-option>
+                </el-select>
+            </div>
+            <div class="dist-box">
+                <span>{{$t(`areaManages.selector.areaName`)}}:</span>
+                <el-select v-model="distOptions.distValue" filterable allow-create default-first-option :placeholder="$t(`areaManages.selector.areaDefault`)" @change="areaSelctChange(distOptions.distValue,'dist')">
+                    <el-option v-for="item in distOptions.distInfo" :key="item.code" :label="item.name" :value="item.name">
+                    </el-option>
+                </el-select>
+            </div>
+            <div class="close-box" v-show="provinceOptions.provinceValue || cityOptions.cityValue ||distOptions.distValue">
+                <svg class="closebtnIcon" aria-hidden="true" @click="closeSelectarea">
+                    <use xlink:href="#icon-quxiao"></use>
+                </svg>
+            </div>
+        </div>
+        <!-- <div class="boxselect" v-if="PowerShow">
+            <el-button size="small" @click="createdSchoolbtn">
+                <svg class="created-icon" aria-hidden="true">
+                    <use xlink:href="#icon-chuangjianx"></use>
+                </svg>
+                创建学校
+            </el-button>
+        </div> -->
+        <div class="school-list">
+            <el-table :data="tableData" style="width: 100%" height="75vh" v-loading="loading" element-loading-text="加载中...">
+                <el-table-column prop="index" :label="$t(`schoolManages.tables.serialnum`)" type="index" sortable align="center" />
+                <el-table-column :label="$t(`schoolManages.tables.badge`)" width="150" align="center">
+                    <template #default="scope">
+                        <el-image style="width: 70px; height: 70px" :src="scope.row.picture" fit="fill"></el-image>
+                    </template>
+                </el-table-column>
+                <el-table-column prop="name" :label="$t(`schoolManages.tables.name`)" sortable align="center" />
+                <!-- <el-table-column label="学段" width="150" align="center">
+                    <template #default="scope">
+                        <span>{{scope.row.period[0].name}}</span>
+                    </template>
+                </el-table-column> -->
+                <el-table-column :label="$t(`schoolManages.tables.scale`)" class="school-table-edition" align="center">
+                    <template #default="scope">
+                        <el-image style="width: 80px; height: 80px" :src="imgData.basics" fit="fill" v-if="scope.row.scale ===0"></el-image>
+                        <el-image style="width: 80px; height: 80px" :src="imgData.standard" fit="fill" v-else-if="scope.row.scale ===500 && scope.row.hard.length===0 && scope.row.serial.length ===0 && scope.row.service.length ===0"></el-image>
+                        <el-image style="width: 80px; height: 80px" :src="imgData.specialty" fit="fill" v-else-if="scope.row.scale ===500 && (scope.row.hard.length !=0 || scope.row.serial.length !=0 || scope.row.service.length !=0)"></el-image>
+                    </template>
+                </el-table-column>
+                <el-table-column prop="id" :label="$t(`schoolManages.tables.brevityCode`)" align="center" />
+                <el-table-column label="数据量" sortable :sort-method="schooldataSort" align="center">
+                    <template #default="scope">
+                        <div v-if="scope.row.lessonCount">
+                            <svg class="created-icon" aria-hidden="true">
+                                <use xlink:href="#icon-shuju"></use>
+                            </svg>
+                            {{scope.row.lessonCount}}
+                        </div>
+                        <div v-else>暂无</div>
+                    </template>
+                </el-table-column>
+                <el-table-column prop="location" label="位置" align="center" />
+                <!-- <el-table-column prop="city" :label="$t(`schoolManages.tables.city`)" align="center" />
+                <el-table-column prop="dist" :label="$t(`schoolManages.tables.area`)" align="center" /> -->
+                <el-table-column prop="size" :label="$t(`schoolManages.tables.spacesize`)" align="center" />
+                <el-table-column :label="$t(`schoolManages.tables.assis`)" align="center">
+                    <template #default="scope">
+                        <div v-if="scope.row.assisName">{{scope.row.assisName}}</div>
+                        <div v-else>暂无</div>
+                    </template>
+                </el-table-column>
+                <el-table-column label="模组情况" align="center" width="200">
+                    <template #default="scope">
+                        <div class="have-modules">
+                            <div v-for="item in scope.row.serviceData" :title="item.name" :key="item.id">
+                                <svg class="school-analyse" aria-hidden="true">
+                                    <use :xlink:href="item.icon"></use>
+                                </svg>
+                            </div>
+                        </div>
+                    </template>
+                </el-table-column>
+                <el-table-column label="数据统计" align="center">
+                    <template #default="scope">
+                        <div title="查看学校数据分析" @click="skipAnalyse(scope.row)">
+                            <svg class="school-analyse" aria-hidden="true">
+                                <use xlink:href="#icon-shujufenxi"></use>
+                            </svg>
+                        </div>
+                    </template>
+                </el-table-column>
+                <!-- <el-table-column prop="state" label="状态" width="110" align="center" /> -->
+                <el-table-column :label="$t(`schoolManages.tables.operate`)" align="center" v-if="PowerShow">
+                    <template #default="scope">
+                        <el-button type="primary" size="small" @click.prevent="deleteRow(scope.$index, scope.row)">{{$t(`schoolManages.tables.operatecontent`)}}</el-button>
+                        <!-- <el-button type="danger" size="small" @click="removeSchool(scope.row,scope.$index)">删除</el-button> -->
+                    </template>
+                </el-table-column>
+            </el-table>
+        </div>
+    </div>
+    <!--学校列表end-->
+    <!--编辑学校页面-->
+    <div class="schoolDeatils">
+        <div class="backbtn" v-if="models==='details' && PowerShow">
+            <el-button class="changebtn" v-if="store.state.changbtnShow && changebtns" @click="getSetschool()" size="small">
+                <svg class="changebtn-areaicon" aria-hidden="true">
+                    <use xlink:href="#icon-wenjian"></use>
+                </svg>
+                <span class="changebtn-title">{{$t(`schoolManages.gradSet.save`)}}</span>
+            </el-button>
+            <el-button type="primary" size="small" @click="schoolClose">
+                <svg class="back-icon" aria-hidden="true">
+                    <use xlink:href="#icon-fanhui"></use>
+                </svg>
+                返回
+            </el-button>
+        </div>
+        <el-tabs v-if="models==='details' && PowerShow" @tab-click="changeTabs">
+            <!--基础设置-->
+            <el-tab-pane :label="$t(`schoolManages.redactSet`)">
+                <div class="redactbox" v-show="models==='details' && PowerShow">
+                    <div class="school-formbox">
+                        <el-form ref="form" :model="nowPitchdata" label-width="120px">
+                            <el-form-item :label="$t(`schoolManages.basicSet.name`)+':'" class="school-form-name">
+                                <el-input v-model="nowPitchdata.name"></el-input>
+                            </el-form-item>
+                            <el-form-item :label="$t(`schoolManages.basicSet.badge`)+':'" class="school-form-badge">
+                                <el-upload class="upload-demo-redact" :headers="uploadHeader" action="/blob/upload-public" :before-upload="changeBadge" :on-success="success" :on-error="handleUpdErr">
+                                    <el-image style="width: 100%; height:125px" :src="nowPitchdata.picture" fit="contain"></el-image>
+                                    <div class="changebadge">
+                                        <el-button>{{$t(`schoolManages.basicSet.badgeChange`)}}</el-button>
+                                    </div>
+                                </el-upload>
+                            </el-form-item>
+                            <!-- <el-form-item label="学段:" class="school-form-grading">
+                                <el-checkbox v-model="nowPitchdata.period[0].value" label="小学"></el-checkbox>
+                                <el-checkbox v-model="nowPitchdata.period[1].value" label="初中"></el-checkbox>
+                                <el-checkbox v-model="nowPitchdata.period[2].value" label="高中"></el-checkbox>
+                                <el-checkbox v-model="nowPitchdata.period[3].value" label="职高"></el-checkbox>
+                                <el-checkbox v-model="nowPitchdata.period[4].value" label="大学"></el-checkbox>
+                            </el-form-item> -->
+                            <el-form-item :label="$t(`schoolManages.basicSet.type`)+':'" class="school-form-grading">
+                                <el-radio v-model="nowPitchdata.type" label="1" size="large">{{$t(`schoolManages.basicSet.ordinary`)}}</el-radio>
+                                <el-radio v-model="nowPitchdata.type" label="2" size="large">{{$t(`schoolManages.basicSet.higherEducation`)}}</el-radio>
+                            </el-form-item>
+                            <el-form-item :label="$t(`schoolManages.basicSet.nowAssistant`)+':'" class="school-form-admin">
+                                <el-select v-model="adminvalue" multiple @change="assistChange" :placeholder="$t(`schoolManages.basicSet.nowAssistanthint`)">
+                                    <el-option v-for="item in adminoptions" :key="item.name" :label="item.mobile+'——'+item.name" :value="item.tmdId ===null ? '':item.tmdId" :disabled="!item.tmdId">
+                                        <!-- <span style="float: left">{{ item.mobile }}-{{item.name}}</span>
+                            <i style="float: right;color: var(--el-text-color-secondary);font-size: 13px;" v-show="item.isexist === false">
+                                <svg class="school-admin-check" aria-hidden="true">
+                                    <use xlink:href="#icon-zhengque"></use>
+                                </svg>
+                            </i> -->
+                                    </el-option>
+                                </el-select>
+                            </el-form-item>
+                            <el-form-item :label="$t(`schoolManages.basicSet.brevityCode`)+':'" class="school-form-code">
+                                <el-input disabled :placeholder="nowPitchdata.id" v-if="nowPitchdata.id !==null" />
+                                <el-input disabled :placeholder="$t(`schoolManages.basicSet.notCode`)" v-else="nowPitchdata.id ==null" />
+                            </el-form-item>
+                            <el-form-item label="所属学区:" class="school-form-area">
+                                <el-select v-model="areaSelect.Selectvalue" :placeholder="$t(`schoolManages.basicSet.region`)">
+                                    <el-option v-for="item in areaSelect.data" :key="item.name" :label="item.name" :value="item.id">
+                                    </el-option>
+                                </el-select>
+                            </el-form-item>
+                            <el-form-item :label="$t(`schoolManages.basicSet.scale`)+':'" class="school-form-size">
+                                <el-input-number v-model="nowPitchdata.scale" :min="0" :step="100" />人
+                            </el-form-item>
+                            <!-- <el-form-item :label="$t(`schoolManages.basicSet.location`)+':'" class="school-form-site">
+                                <el-input disabled :placeholder="nowPitchdata.address" />
+                            </el-form-item> -->
+                            <el-form-item :label="$t(`schoolManages.basicSet.spacesize`)+':'" class="school-form-size">
+                                <el-input-number v-model="nowPitchdata.size" :min="1" :max="1000" />GB
+                            </el-form-item>
+                            <!-- <el-form-item label="学校状态:" class="school-form-state">
+                    <el-switch v-model="value2" active-color="#13ce66" inactive-color="#ff4949" />
+                </el-form-item> -->
+                            <el-form-item>
+                                <el-button type="primary" @click="updateSchoolinfo">{{$t(`schoolManages.basicSet.submit`)}}</el-button>
+                                <el-button @click="schoolClose">{{$t(`commonMsg.closes`)}}</el-button>
+                            </el-form-item>
+                        </el-form>
+                    </div>
+                </div>
+            </el-tab-pane>
+            <el-tab-pane :label="$t(`schoolManages.redactGrading`)">
+                <SetSchool :schoolData="studyPhase" ref="setSchoolData"></SetSchool>
+            </el-tab-pane>
+            <!-- <el-tab-pane :label="$t(`schoolManages.redactServe`)">
+                <Impower :schoolCode="studyPhase"></Impower>
+            </el-tab-pane>
+            <el-tab-pane :label="$t(`schoolManages.redactSerial`)">
+                <Classpower :schoolCode="studyPhase"></Classpower>
+            </el-tab-pane> -->
+        </el-tabs>
+    </div>
+    <!--编辑学校页面end-->
+</template>
+<script>
+import { reactive, ref, getCurrentInstance, toRef } from 'vue'
+import option from '@/static/region.json'
+import { useStore } from 'vuex'
+import { ElMessage, ElLoading, ElMessageBox } from 'element-plus'
+import { useRouter } from 'vue-router'
+import SetSchool from './setPhase.vue'
+const optionsData = option
+export default {
+    components: {
+        SetSchool,
+    },
+    setup() {
+        let { proxy } = getCurrentInstance()
+        let PowerShow = proxy.$access.inspectPower('batchschool-upd')
+        const store = useStore()
+        const routerInfo = useRouter()
+        //为了让表单呈现 暂时的数据,
+        let tableData = ref([])
+        const form = reactive({
+            name: '',
+            region: '',
+            date1: '',
+            date2: '',
+            delivery: false,
+            type: [],
+            resource: '',
+            desc: '',
+        })
+        let adminoptions = ref([])
+        let adminvalue = ref([])
+        const value2 = ref(true)
+        //为了让表单呈现 暂时的数据,
+        let loading = ref(true)
+        let uploadHeader = ref({})
+        let nowPitchdata = ref({
+            address: '',
+            areaId: '',
+            campuses: [],
+            city: '',
+            dist: '',
+            id: '',
+            name: '',
+            picture: '',
+            pk: '',
+            province: '',
+            region: '',
+            schoolCode: '',
+            size: 0,
+            standard: '',
+            admin: '',
+            type: 0,
+            scale: 0,
+        })
+        let originalData = ref([])
+        const options = option
+        const props = {
+            value: 'name',
+            label: 'name',
+            children: 'children',
+            checkStrictly: true,
+        }
+        let models = ref('default')
+        let imags = require('@/assets/img/tmd_logo.png')
+        //地区列表
+        let provinceOptions = ref({
+            optionInfo: [],
+            provinceValue: '',
+        })
+        let cityOptions = ref({
+            cityInfo: [],
+            cityValue: '',
+        })
+        let distOptions = ref({
+            distInfo: [],
+            distValue: '',
+        })
+        let areaSelect = ref({
+            Selectvalue: '',
+            data: [],
+        })
+        //学段管理(传输给子组件)
+        let studyPhase = ref()
+        //存储变更按钮显示show
+        let changebtns = ref(false)
+        let setSchoolData = ref(null)
+        let imgData = ref({
+            basics: require('@/assets/img/basicsEdition.svg'),
+            standard: require('@/assets/img/standardEdition.svg'),
+            specialty: require('@/assets/img/specialtyEdition.svg'),
+        })
+        //模组icon
+        let patternIcon = ref([
+            { id: 1, name: '学情分析', icon: '#icon-tongjifenxi', key: 'YMPCVCIM' },
+            { id: 2, name: '智慧学校管理服务', icon: '#icon-zhihuixiaoyuan', key: 'IPDYZYLC' },
+            { id: 3, name: 'A Class ONE 智慧学伴', icon: '#icon-jxuexiao2', key: '3CLYJ6NP' },
+            { id: 4, name: '数据存储服务空间', icon: '#icon-yuncunchu', key: 'IPALJ6NY' },
+            { id: 5, name: '卷卡合一阅卷系统', icon: '#icon-pingtai_kaoshi', key: 'VABAJ6NV' },
+            { id: 6, name: '教研中心模组', icon: '#icon-jiaoyan', key: 'VLY6J6N6' },
+        ])
+        provinceOptions.value.optionInfo = optionsData
+        console.log(store.state.point)
+        //所有学校列表
+        function getAllschool() {
+            proxy.$api.getSchooldata({}).then((res) => {
+                console.log(res, '获取学校列表assist')
+                //处理关联管家  拼内容
+                res.schoolAssists.splice(3)
+                for (let i in res.schoolAssists) {
+                    res.schoolAssists[i].serviceData = []
+                    if (res.schoolAssists[i].assists) {
+                        res.schoolAssists[i].assisName = ''
+                        res.schoolAssists[i].location = res.schoolAssists[i].province + res.schoolAssists[i].city + res.schoolAssists[i].dist
+                        let datas = res.schoolAssists[i].assists
+                        for (let y in datas) {
+                            res.schoolAssists[i].assisName = res.schoolAssists[i].assisName + datas[y].tmdName + ','
+                        }
+                    }
+                    if (res.schoolAssists[i].service.length > 0) {
+                        res.schoolAssists[i].service.forEach((x) => {
+                            for (let m in patternIcon.value) {
+                                patternIcon.value[m].key === x ? res.schoolAssists[i].serviceData.push(patternIcon.value[m]) : ''
+                            }
+                        })
+                    }
+                }
+                console.log(res)
+                res.state == 200 ? (tableData.value.push(...res.schoolAssists), (originalData.value = res.schoolAssists), (loading.value = false)) : ''
+            })
+        }
+        //点击学校列表,详情
+        function deleteRow(index, data) {
+            console.log(index, data, 'DATA')
+            //处理的基础设置
+            areaSelect.value.data = []
+            studyPhase.value = data.id
+            nowPitchdata.value = Object.assign(nowPitchdata.value, data)
+            nowPitchdata.value.address = data.address
+            nowPitchdata.value.name = data.name
+            nowPitchdata.value.type = data.type.toString()
+            nowPitchdata.value.scale = data.scale
+            nowPitchdata.value.standard = data.standard
+            nowPitchdata.value.areaId = data.areaId
+            data.assists.length
+                ? data.assists.forEach((element) => {
+                      adminvalue.value.push(element.tmdId)
+                  })
+                : ''
+            let token = JSON.parse(localStorage.getItem('id_token'))
+            uploadHeader.value['x-auth-authtoken'] = token
+            data.areaId !== null ? (areaSelect.value.Selectvalue = data.areaId) : ''
+            console.log(store.state.point, '目前现有的所有区')
+            store.state.point.length ? areaSelect.value.data.push(...store.state.point) : getoption()
+            models.value = 'details'
+            console.log(nowPitchdata.value, '查看当前学校的值')
+        }
+        //更换校徽
+        function changeBadge(file) {
+            console.log(file)
+            if (file.type == 'image/png' || file.type == 'image/jpeg') {
+                return true
+            } else {
+                ElMessage.error(proxy.$t(`commonMsg.uploadError`))
+                return false
+            }
+        }
+        //地区选择
+        function areaSelctChange(value, model) {
+            loading.value = true
+            console.log(value)
+            let data = option
+            if (model === 'province') {
+                //传输下一级的数据给select
+                let cityData = data.filter((item) => {
+                    return item.name === value
+                })
+                cityOptions.value.cityInfo = cityData[0].children
+                //遍历list
+                let schoolData = originalData.value.filter((items) => {
+                    return items.province === value
+                })
+                tableData.value = schoolData
+                console.log(schoolData, tableData.value)
+            } else if (model === 'city') {
+                let distData = cityOptions.value.cityInfo.filter((item) => {
+                    return item.name === value
+                })
+                distOptions.value.distInfo = distData[0].children
+                let provinceData = provinceOptions.value.provinceValue
+                let schoolData = originalData.value.filter((items) => {
+                    return items.city === value && items.province === provinceData
+                })
+                tableData.value = schoolData
+            } else if (model === 'dist') {
+                let provinceData = provinceOptions.value.provinceValue
+                let cityData = cityOptions.value.cityValue
+                let schoolData = originalData.value.filter((items) => {
+                    return items.city === cityData && items.province === provinceData && items.dist === value
+                })
+                tableData.value = schoolData
+            }
+            loading.value = false
+        }
+        //学校详情 close
+        function schoolClose() {
+            models.value = 'default'
+            const basics = {
+                areaId: '',
+                campuses: [],
+                city: '',
+                dist: '',
+                id: '',
+                name: '',
+                picture: '',
+                pk: '',
+                province: '',
+                region: '',
+                schoolCode: '',
+                size: 0,
+                standard: '',
+                admin: '',
+            }
+            nowPitchdata.value = Object.assign({}, basics)
+            adminvalue.value = []
+            areaSelect.value.Selectvalue = ''
+            store.commit('updateSchoolpower', {})
+            console.log(nowPitchdata, '取消后的')
+        }
+        //管家发生变化
+        function assistChange(val) {
+            console.log(val, adminvalue.value)
+        }
+        //获取所有的顾问API访问
+        function getAllassists() {
+            // let data = { deptId: '' }
+            // proxy.$api.getAllassist(data).then((res) => {
+            //     res.state === 200 ? adminoptions.value.push(...res.dDAndTmdInfos) : ''
+            // })
+            // let dataA = { deptId: '67690917' }
+            // proxy.$api.getAllassist(dataA).then((res) => {
+            //     console.log(res, '研发A')
+            //     res.state === 200 ? adminoptions.value.push(...res.dDAndTmdInfos) : ''
+            // })
+            proxy.$api.getEveryinfo({}).then((res) => {
+                console.log(res, '顾问返回')
+                res.state === 200 ? adminoptions.value.push(...res.ddUserInfos) : ''
+            })
+            console.log(adminoptions.value, '目前所有顾问')
+        }
+        function handleUpdErr() {
+            ElMessage.error('校徽修改失败')
+        }
+        //上传校徽成功后
+        function success(response, file, fileList) {
+            // this.schoolSetting.picture = response.url
+            console.log(response, file, fileList, '上传成功的返回')
+            nowPitchdata.value.picture = response.url
+            //校徽长传成功自动保存
+            // this.saveData()
+        }
+        // 确认修改学校信息
+        function updateSchoolinfo() {
+            let user = JSON.parse(localStorage.getItem('userData'))
+            //修改表单
+            let assistData = adminvalue.value
+            let periodData = []
+            for (let i in nowPitchdata.value.period) {
+                let num = Number(i) + 1
+                if (nowPitchdata.value.period[i].value === true) {
+                    periodData.push(nowPitchdata.value.period[i].name)
+                }
+            }
+            let updateForm = {
+                name: nowPitchdata.value.name,
+                schoolId: nowPitchdata.value.id,
+                picture: nowPitchdata.value.picture,
+                size: nowPitchdata.value.size,
+                assistId: assistData,
+                scale: nowPitchdata.value.scale,
+                type: parseInt(nowPitchdata.value.type),
+                standard: nowPitchdata.value.standard,
+                areaId: nowPitchdata.value.areaId,
+            }
+            console.log(updateForm, '学校信息')
+            proxy.$api.updateSchoolinfo(updateForm).then((res) => {
+                console.log(res, '修改学校的返回')
+                res.state === 200
+                    ? (ElMessage.success(proxy.$t(`commonMsg.schoolUpdateSuccess`), schoolJoinarea(), schoolClose()), updateSuccess())
+                    : ElMessage.error(proxy.$t(`commonMsg.schoolUpdateError`))
+            })
+        }
+        //学校加入区域或者修改
+        async function schoolJoinarea() {
+            let user = JSON.parse(localStorage.getItem('userData'))
+            if (areaSelect.value.Selectvalue === '' || areaSelect.value.Selectvalue === null) {
+                return
+            }
+            let standname = areaSelect.value.data.filter((item) => {
+                return item.id === areaSelect.value.Selectvalue
+            })
+            let dataInfo = {
+                tmdId: user.tmdId,
+                tmdName: user.tmdName,
+                standard: standname[0].standard,
+                areaId: areaSelect.value.Selectvalue,
+                schoolCode: [nowPitchdata.value.id],
+            }
+            await proxy.$api.areaAddSchool(dataInfo).then((res) => {
+                console.log(res, '学校加入区域API')
+            })
+        }
+        //创建学校btn 跳转
+        function createdSchoolbtn() {
+            routerInfo.push({ path: '/home/created', query: { model: 'schollC' } })
+        }
+        //获取所有区域,学校编辑内呈现
+        function getoption() {
+            proxy.$api.getCapacity({}).then((res) => {
+                areaSelect.value.data.push(...res.areas)
+                store.commit('getPoint', res.areas)
+            })
+        }
+        //修改成功后执行
+        function updateSuccess() {
+            loading.value = true
+            setTimeout(() => {
+                ;(models.value = 'default'), (tableData.value = []), getAllschool()
+            }, 2000)
+        }
+        //地区选择close btn
+        function closeSelectarea() {
+            provinceOptions.value.provinceValue = ''
+            provinceOptions.value.optionInfo = []
+            cityOptions.value.cityValue = ''
+            cityOptions.value.cityInfo = []
+            distOptions.value.distValue = ''
+            distOptions.value.distInfo = []
+            tableData.value = originalData.value
+            provinceOptions.value.optionInfo = optionsData
+        }
+        //关于储存变更按钮
+        function changeTabs(value) {
+            console.log(value.props.label)
+            value.props.label == '学段管理' || value.props.label == '學段管理' ? (changebtns.value = true) : (changebtns.value = false)
+        }
+        //获取子页面的数据
+        function getSetschool() {
+            console.log(setSchoolData.value.nowschoolData)
+            let newData = setSchoolData.value.nowschoolData
+            for (let i in newData.period) {
+                let datas = newData.period[i]
+                for (let u in datas.grades) {
+                    if (datas.grades[u] === '') {
+                        ElMessage.warning(proxy.$t(`schoolManages.gradSet.gradesHint`))
+                        return
+                    }
+                }
+                for (let e in datas.analysis.type) {
+                    if (datas.analysis.type[e].name === '') {
+                        ElMessage.warning(proxy.$t(`schoolManages.gradSet.typeHint`))
+                        return
+                    }
+                }
+            }
+            const loadinginfo = ElLoading.service({
+                lock: true,
+                text: '正在保存,请稍后...',
+                background: 'rgba(0, 0, 0, 0.7)',
+            })
+            proxy.$api
+                .updateSchoolphase(newData)
+                .then((res) => {
+                    res.state === 200 ? (ElMessage.success('保存成功'), (studyPhase.value = res.schoolInfo.id), (changebtns.value = false)) : ElMessage.error('保存失败')
+                    loadinginfo.close()
+                })
+                .catch((res) => {
+                    ElMessage.error(proxy.$t(`commonMsg.apiError`))
+                    loadinginfo.close()
+                })
+        }
+        function skipAnalyse(value) {
+            console.log(value, '学校信息')
+            routerInfo.push({ path: '/home/analyse', query: {} })
+            store.commit('schoolDataInfo', value)
+        }
+        function schooldataSort(a, b) {
+            tableData.value.sort(function (a, b) {
+                return b.lessonCount - a.lessonCount
+            })
+        }
+        function removeSchool(value, index) {
+            console.log(value)
+            ElMessageBox.confirm(`您确定要删除 ${value.name} 学校吗? 请慎重操作!`, '删除学校', {
+                confirmButtonText: proxy.$t(`commonMsg.confirm`),
+                cancelButtonText: proxy.$t(`commonMsg.closes`),
+                type: 'warning',
+                center: true,
+            }).then(() => {
+                let dataArr = tableData.value
+                dataArr.splice(index, 1)
+                ElMessage.success('删除成功')
+            })
+        }
+        getAllschool()
+        getAllassists()
+        return {
+            store,
+            tableData,
+            options,
+            props,
+            models,
+            form,
+            imags,
+            adminoptions,
+            adminvalue,
+            value2,
+            getAllschool,
+            deleteRow,
+            changeBadge,
+            nowPitchdata,
+            schoolClose,
+            originalData,
+            getAllassists,
+            assistChange,
+            loading,
+            uploadHeader,
+            success,
+            provinceOptions,
+            cityOptions,
+            distOptions,
+            areaSelctChange,
+            updateSchoolinfo,
+            createdSchoolbtn,
+            getoption,
+            areaSelect,
+            updateSuccess,
+            PowerShow,
+            closeSelectarea,
+            studyPhase,
+            changeTabs,
+            changebtns,
+            setSchoolData,
+            getSetschool,
+            imgData,
+            patternIcon,
+            skipAnalyse,
+            schooldataSort,
+            removeSchool,
+        }
+    },
+}
+</script>
+<style scoped>
+.schoolbox {
+    width: 100%;
+    margin: 0 auto;
+    line-height: 80px;
+}
+.select-List {
+    line-height: 60px;
+    text-align: left;
+    padding: 1% 2%;
+    width: 75%;
+    float: left;
+}
+.school-list {
+    width: 96%;
+    max-height: 74vh;
+    margin: 0 auto;
+    /* overflow-y: auto; */
+}
+/*编辑页面样式*/
+.redactbox {
+    width: 100%;
+    height: 87vh;
+    background-color: #fff;
+}
+.backbtn {
+    text-align: left;
+    position: absolute;
+    top: 0.5%;
+    right: 10px;
+    z-index: 999;
+    line-height: 40px;
+}
+.school-formbox {
+    width: 85%;
+    margin: 0 auto;
+    padding: 1%;
+}
+.upload-demo-redact {
+    width: 100%;
+    height: 125px;
+}
+.school-form-name {
+    width: 50%;
+}
+.school-form-area {
+    width: 35%;
+}
+.school-form-badge,
+.school-form-code {
+    width: 24%;
+}
+.school-form-grading {
+    width: 80%;
+}
+.changebadge {
+    width: 100%;
+    height: 125px;
+    position: absolute;
+    top: 0px;
+    left: 0px;
+    opacity: 0;
+}
+.school-form-site {
+    width: 35%;
+}
+.school-form-size {
+    width: 21%;
+    color: #bdc3c7;
+}
+.school-form-admin {
+    width: 35%;
+    text-align: left;
+}
+.school-form-state {
+    width: 15%;
+}
+.school-admin-check {
+    width: 2em;
+    height: 2em;
+    vertical-align: -0.5em;
+    fill: currentColor;
+    overflow: hidden;
+}
+.province-box,
+.city-box,
+.dist-box,
+.close-box {
+    display: inline-block;
+}
+.city-box,
+.dist-box {
+    margin-left: 1%;
+}
+/*btn*/
+.boxselect {
+    width: 20%;
+    display: inline-block;
+    margin-top: 0.5%;
+    text-align: right;
+}
+.created-areaicon {
+    width: 1.3em;
+    height: 1.3em;
+    /* vertical-align: -0.5em; */
+    fill: currentColor;
+    overflow: hidden;
+    margin-top: -135px;
+}
+.closebtnIcon {
+    width: 1.8em;
+    height: 1.8em;
+    vertical-align: -0.6em;
+    fill: currentColor;
+    overflow: hidden;
+    margin-left: 8px;
+}
+.closebtnIcon:hover {
+    cursor: pointer;
+}
+.schoolDeatils {
+    position: relative;
+    background: #e9eef3;
+}
+.changebtn {
+    display: inline-block;
+    /* float: right; */
+}
+.changebtn-title {
+    font-size: 12px;
+}
+.changebtn-areaicon {
+    width: 0.9em;
+    height: 0.9em;
+    vertical-align: -0.1em;
+    fill: currentColor;
+    margin-right: 3px;
+}
+.back-icon {
+    width: 0.9em;
+    height: 0.9em;
+    vertical-align: -0.1em;
+    fill: currentColor;
+    margin-right: 3px;
+}
+.created-icon {
+    width: 1.3em;
+    height: 1.3em;
+    vertical-align: -0.3em;
+    fill: currentColor;
+    overflow: hidden;
+    margin-right: 5px;
+}
+.school-analyse {
+    width: 1.8em;
+    height: 1.8em;
+    vertical-align: 0em;
+    fill: currentColor;
+    overflow: hidden;
+    cursor: pointer;
+}
+.have-modules {
+    display: flex;
+    justify-content: space-between;
+    overflow-x: auto;
+}
+</style>
+<style>
+.schoolbox .el-cascader {
+    width: 20%;
+}
+.school-form-badge .el-form-item__label {
+    line-height: 107px;
+}
+.school-form-badge .el-form-item__content {
+    border: 1px solid #ccc;
+    position: relative;
+}
+.changebadge .el-button {
+    width: 100%;
+    height: 100%;
+    font-size: 18px;
+    color: #fff;
+}
+.changebadge .el-button span {
+    border: 1px solid #ccc;
+    background-color: #409eff;
+    padding: 5px;
+    border-radius: 10px;
+}
+.changebadge:hover {
+    opacity: 0.8;
+}
+.school-form-code .el-input__inner {
+    text-align: center;
+}
+.school-form-admin .el-select {
+    width: 100%;
+}
+.school-form-badge .el-image__inner {
+    width: 100%;
+    height: 85%;
+    margin-top: 10%;
+}
+.school-form-grading .el-form-item__content {
+    text-align: left;
+}
+.el-select-dropdown__item {
+    padding: 0 12px 0 20px;
+}
+.school-formbox .el-form-item__content {
+    text-align: left;
+}
+.school-form-area .el-select {
+    width: 100%;
+}
+.school-list .el-table__header-wrapper {
+    line-height: 60px;
+}
+.schoolDeatils .el-tabs__header {
+    height: 45px;
+    line-height: 45px;
+    line-height: 0px;
+    padding-left: 15px;
+    box-shadow: 0 2px 5px #e9e9e9;
+    background-color: #fff;
+    margin: 0px 0px 1px;
+}
+.schoolDeatils .el-tabs__content {
+    padding: 0px;
+}
+.backbtn .changebtn {
+    padding: 8px 15px;
+}
+.upload-demo-redact .el-upload {
+    width: 100%;
+    height: 125px;
+}
+.school-form-grading .el-radio__input.is-checked .el-radio__inner::after {
+    content: '';
+    width: 10px;
+    height: 5px;
+    border: 2px solid white;
+    border-top: transparent;
+    border-right: transparent;
+    text-align: center;
+    display: inline-block;
+    position: absolute;
+    top: 2px;
+    left: 2px;
+    vertical-align: middle;
+    transform: rotate(-45deg);
+    border-radius: 0px;
+    background: none;
+}
+.schoolDeatils .el-tabs__nav-wrap::after {
+    width: 0%;
+}
+.el-upload-dragger {
+}
+@media screen and (max-width: 1920px) {
+    .school-formbox .school-form-badge {
+        width: 17.5%;
+    }
+}
+@media screen and (max-width: 1400px) {
+    .school-formbox .school-form-badge {
+        width: 24%;
+    }
+}
+</style>

Файловите разлики са ограничени, защото са твърде много
+ 1442 - 0
TEAMModelBI/ClientApp/src/view/participation/setAbility.vue


Файловите разлики са ограничени, защото са твърде много
+ 2170 - 0
TEAMModelBI/ClientApp/src/view/participation/setPhase.vue


+ 75 - 5
TEAMModelBI/ClientApp/src/view/schoolServe/analyseSchool.vue

@@ -1,7 +1,20 @@
 <template>
     <div class="school-servebox">
-        <div class="backs">
-            <el-button size="small" type="primary" @click="backindex">返回</el-button>
+        <div class="headerbox">
+            <div class="schoolname">
+                <div class="schoolname-img">
+                    <el-image style="width: 55px; height: 55px;border-radius:50%" :src="nowSchools.picture" fit="fill"></el-image>
+                </div>
+                <div class="schoolname-name">
+                    <div class="schoolname-name-title">{{nowSchools.name}}</div>
+                    <div class="schoolname-versions" v-if="nowSchools.scale ==0">基础版</div>
+                    <div class="schoolname-versions standard" v-else-if="nowSchools.scale ==500 && nowSchools.hard.length ===0 && nowSchools.serial.length ===0 && nowSchools.service.length ===0 ">标准版</div>
+                    <div class="schoolname-versions major" v-else-if="nowSchools.scale ===500 && (nowSchools.hard.length !=0 || nowSchools.serial.length !=0 || nowSchools.service.length !=0)">专业版</div>
+                </div>
+            </div>
+            <div class="backs">
+                <el-button size="small" type="primary" @click="backindex">返回</el-button>
+            </div>
         </div>
         <div class="topbox">
             <div class="topbox-list">
@@ -113,6 +126,7 @@ import CommonPie from '@/components/echarts/commonPie.vue'
 import CommonLine from '@/components/echarts/commonLine.vue'
 import Doublepie from '@/components/echarts/doublePie.vue'
 import { useRouter } from 'vue-router'
+import { useStore } from 'vuex'
 import * as echarts from 'echarts'
 export default {
     components: {
@@ -125,6 +139,8 @@ export default {
     },
     setup() {
         const router = useRouter()
+        const store = useStore()
+        let nowSchools = ref({})
         let headerData = ref([
             { id: 1, title: '教师数量', num: 0, icon: '#icon-schoollaoshi', classname: 'teach' },
             { id: 2, title: '班级数量', num: 0, icon: '#icon-banjiguanli1', classname: 'class' },
@@ -1002,15 +1018,18 @@ export default {
             },
         ]
         function backindex() {
-            router.push({ path: '/home/schoolmanage', query: {} })
+            router.push({ path: '/home/participation', query: {} })
         }
-        return { headerData, basicsData, totalechartsData, modulesData, tableData, backindex }
+        nowSchools.value = store.state.nowSchool
+        console.log(store.state.nowSchool)
+        return { headerData, basicsData, totalechartsData, modulesData, tableData, backindex, nowSchools }
     },
 }
 </script>
 <style scoped>
 .school-servebox {
     background: #e9eef3;
+    line-height: 20px;
 }
 .topbox {
     width: 100%;
@@ -1290,10 +1309,61 @@ export default {
     border-left: 6px solid #ff7979;
 }
 .backs {
+    width: 17%;
     line-height: 20px;
     text-align: right;
     margin-top: 0.5%;
-    margin-right: 1%;
+    margin-right: 0%;
+    display: inline-block;
+    vertical-align: top;
+}
+.headerbox {
+    width: 100%;
+    height: 8vh;
+    border-bottom: 1px solid #ccc;
+}
+.schoolname {
+    width: 80%;
+    font-size: 20px;
+    line-height: 24px;
+    display: inline-block;
+    vertical-align: top;
+    margin-top: 0.5%;
+    padding-left: 17%;
+}
+.schoolname div {
+    display: inline-block;
+    vertical-align: top;
+}
+.schoolname-name {
+    font-size: 24px;
+    font-weight: 600;
+    margin-left: 3%;
+    margin-top: 1.3%;
+    position: relative;
+}
+.schoolname-name-title {
+    /* width: 80%; */
+    display: inline-block;
+    vertical-align: top;
+}
+.schoolname-versions {
+    width: 55px;
+    font-size: 14px;
+    line-height: 20px;
+    border: 1px solid #48dbfb;
+    border-radius: 10px;
+    margin-left: 10px;
+    background-color: #48dbfb;
+    color: #fff;
+}
+.major {
+    background: linear-gradient(90deg, #734311, #ffc78c, #734311);
+    border: 1px solid #ffc78c;
+}
+.standard {
+    background: linear-gradient(90deg, #686de0, #5f27cd);
+    border: 1px solid #686de0;
 }
 </style>
 <style>

+ 18 - 10
TEAMModelBI/ClientApp/src/view/schoolServe/school.vue

@@ -54,8 +54,8 @@
                 <el-table-column :label="$t(`schoolManages.tables.scale`)" class="school-table-edition" align="center">
                     <template #default="scope">
                         <el-image style="width: 80px; height: 80px" :src="imgData.basics" fit="fill" v-if="scope.row.scale ===0"></el-image>
-                        <el-image style="width: 80px; height: 80px" :src="imgData.standard" fit="fill" v-else-if="scope.row.scale ===500 && scope.row.hard ===0 && scope.row.serial ===0 && scope.row.service ===0"></el-image>
-                        <el-image style="width: 80px; height: 80px" :src="imgData.specialty" fit="fill" v-else-if="scope.row.scale ===500 && (scope.row.hard !=0 || scope.row.serial !=0 || scope.row.service !=0)"></el-image>
+                        <el-image style="width: 80px; height: 80px" :src="imgData.standard" fit="fill" v-else-if="scope.row.scale ===500 && scope.row.hard.length ===0 && scope.row.serial.length ===0 && scope.row.service.length ===0"></el-image>
+                        <el-image style="width: 80px; height: 80px" :src="imgData.specialty" fit="fill" v-else-if="scope.row.scale ===500 && (scope.row.hard.length !=0 || scope.row.serial.length !=0 || scope.row.service.length !=0)"></el-image>
                     </template>
                 </el-table-column>
                 <el-table-column prop="id" :label="$t(`schoolManages.tables.brevityCode`)" align="center" />
@@ -83,7 +83,7 @@
                 <el-table-column label="模组情况" align="center" width="200">
                     <template #default="scope">
                         <div class="have-modules">
-                            <div v-for="item in patternIcon" :title="item.name" :key="item.id">
+                            <div v-for="item in scope.row.serviceData" :title="item.name" :key="item.id">
                                 <svg class="school-analyse" aria-hidden="true">
                                     <use :xlink:href="item.icon"></use>
                                 </svg>
@@ -307,12 +307,12 @@ export default {
         })
         //模组icon
         let patternIcon = ref([
-            { id: 1, name: '学情分析', icon: '#icon-tongjifenxi' },
-            { id: 2, name: '智慧学校管理服务', icon: '#icon-zhihuixiaoyuan' },
-            { id: 3, name: 'A Class ONE 智慧学伴', icon: '#icon-jxuexiao2' },
-            { id: 4, name: '数据存储服务空间', icon: '#icon-yuncunchu' },
-            { id: 5, name: '卷卡合一阅卷系统', icon: '#icon-pingtai_kaoshi' },
-            { id: 6, name: '教研中心模组', icon: '#icon-jiaoyan' },
+            { id: 1, name: '学情分析', icon: '#icon-tongjifenxi', key: 'YMPCVCIM' },
+            { id: 2, name: '智慧学校管理服务', icon: '#icon-zhihuixiaoyuan', key: 'IPDYZYLC' },
+            { id: 3, name: 'A Class ONE 智慧学伴', icon: '#icon-jxuexiao2', key: '3CLYJ6NP' },
+            { id: 4, name: '数据存储服务空间', icon: '#icon-yuncunchu', key: 'IPALJ6NY' },
+            { id: 5, name: '卷卡合一阅卷系统', icon: '#icon-pingtai_kaoshi', key: 'VABAJ6NV' },
+            { id: 6, name: '教研中心模组', icon: '#icon-jiaoyan', key: 'VLY6J6N6' },
         ])
         provinceOptions.value.optionInfo = optionsData
         console.log(store.state.point)
@@ -322,6 +322,7 @@ export default {
                 console.log(res, '获取学校列表')
                 //处理关联管家  拼内容
                 for (let i in res.schoolAssists) {
+                    res.schoolAssists[i].serviceData = []
                     if (res.schoolAssists[i].assists) {
                         res.schoolAssists[i].assisName = ''
                         res.schoolAssists[i].location = res.schoolAssists[i].province + res.schoolAssists[i].city + res.schoolAssists[i].dist
@@ -330,6 +331,13 @@ export default {
                             res.schoolAssists[i].assisName = res.schoolAssists[i].assisName + datas[y].tmdName + ','
                         }
                     }
+                    if (res.schoolAssists[i].service.length > 0) {
+                        res.schoolAssists[i].service.forEach((x) => {
+                            for (let m in patternIcon.value) {
+                                patternIcon.value[m].key === x ? res.schoolAssists[i].serviceData.push(patternIcon.value[m]) : ''
+                            }
+                        })
+                    }
                 }
                 console.log(res)
                 res.state == 200 ? (tableData.value.push(...res.schoolAssists), (originalData.value = res.schoolAssists), (loading.value = false)) : ''
@@ -740,7 +748,7 @@ export default {
     width: 35%;
 }
 .school-form-size {
-    width: 21%;
+    width: 35%;
     color: #bdc3c7;
 }
 .school-form-admin {

+ 3 - 2
TEAMModelBI/ClientApp/src/view/schoolServe/setschool.vue

@@ -998,9 +998,10 @@ export default {
                 return
             }
             for (let i in data) {
-                // data[i].id === value.id ? data.splice(i, 1) : ''
-                data[i].id === value.id && value.start === 0 ? (data.splice(i, 1), (data[0].start = 0)) : data.splice(i, 1)
+                data[i].id === value.id ? data.splice(i, 1) : ''
+                // data[i].id === value.id && value.start === 0 ? (data.splice(i, 1), (data[0].start = 0), console.log('进入删除111')) : data.splice(i, 1), console.log('进入删除2222')
             }
+            data[0].start = 0
             nowschoolData.value.period[pathNowphase.value].semesters = data
             console.log(nowschoolData.value.period[pathNowphase.value].semesters, '删除学期后的')
         }

+ 1 - 1
TEAMModelBI/Controllers/BISchool/BatchSchoolController.cs

@@ -543,7 +543,7 @@ namespace TEAMModelBI.Controllers.BISchool
         /// <param name="jsonElement"></param>
         /// <returns></returns>
         [ProducesDefaultResponseType]
-        [AuthToken(Roles = "assist")]
+        [AuthToken(Roles = "assist,admin")]
         [HttpPost("upd-schoolassist")]
         public async Task<IActionResult> UpdSchoolAssist(JsonElement jsonElement)
         {

+ 1 - 1
TEAMModelBI/Controllers/BISchool/SchoolController.cs

@@ -232,7 +232,7 @@ namespace TEAMModelBI.Controllers.BISchool
         /// <param name="school"></param>
         /// <returns></returns>
         [ProducesDefaultResponseType]
-        [AuthToken(Roles = "assist")]
+        [AuthToken(Roles = "assist,admin")]
         [HttpPost("upd-school")]
         public async Task<IActionResult> UpdSchool(School school)
         {

+ 37 - 14
TEAMModelOS.FunctionV4/ServiceBus/ActiveTaskTopic.cs

@@ -25,6 +25,7 @@ using TEAMModelOS.SDK.Services;
 using Azure.Storage.Blobs.Models;
 using System.IO;
 using Azure;
+using static TEAMModelOS.SDK.Models.Service.LessonService;
 
 namespace TEAMModelOS.FunctionV4.ServiceBus
 {
@@ -869,7 +870,7 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
             }
 
             var client = _azureCosmos.GetCosmosClient();
-
+           
             if ($"{scope}".Equals("school") && !string.IsNullOrEmpty($"{school}"))
             {
                 blobname = $"{school}";
@@ -907,6 +908,7 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
                 bool isReplace = true;
                 if (updates.IsNotEmpty())
                 {
+                    Teacher teacher = await client.GetContainer(Constant.TEAMModelOS, Constant.Teacher).ReadItemAsync<Teacher>(tmdid, new PartitionKey("Base"));
                     foreach (LessonUpdate update in updates)
                     {
                         switch (update.grant_type)
@@ -991,6 +993,8 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
                                         lessonRecord.totalInteractPoint = lessonBase.summary.totalInteractPoint;
                                     }
                                     // await _dingDing.SendBotMsg($"{_option.Location},课堂id:{_lessonId} 更新完成", GroupNames.醍摩豆服務運維群組);
+
+                                    LessonService.DoAutoDeleteSchoolLessonRecord(lessonRecord, scope, client, school, tmdid,   teacher, _notificationService, _serviceBus, _azureStorage, _configuration);
                                     long? size = await _azureStorage.GetBlobContainerClient(blobname).GetBlobsSize($"records/{_lessonId}");
                                     Bloblog bloblog = new Bloblog
                                     {
@@ -1097,7 +1101,7 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
                             case "create":
                                 oldlessonRecord = null;
                                 //处理课堂选用的课程信息
-                                Teacher teacher = await client.GetContainer(Constant.TEAMModelOS, Constant.Teacher).ReadItemAsync<Teacher>(tmdid, new PartitionKey("Base"));
+                              
                                 lessonRecord.show = teacher.lessonShow;
                                 if (!string.IsNullOrEmpty(lessonRecord.courseId))
                                 {
@@ -1244,18 +1248,35 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
                                             if (ids.Count >= limit)
                                             {
                                                 // 1-时间戳,7-时间戳
-                                                Dictionary<int, long> result = new Dictionary<int, long>();
+                                                Dictionary<int, ExpireTag> result = new Dictionary<int, ExpireTag>();
                                                 //暂定7天 
                                                 var now = DateTimeOffset.UtcNow;
                                                 //剩余3天的通知
                                                 //var day3= now.AddDays(Constant.private_lesson_expire - 3).ToUnixTimeMilliseconds();
                                                 //result.Add(3, day3);
                                                 //剩余1天的通知
-                                                var day1 = now.AddDays(Constant.private_lesson_expire - 6).ToUnixTimeMilliseconds();
-                                                result.Add(1, day1);
+                                                var day1 = now.AddDays(Constant.private_lesson_expire - (Constant.private_lesson_expire-1)).ToUnixTimeMilliseconds();
+                                                result.Add(1, new ExpireTag { expire = day1, tag = "notification" });
                                                 //到期通知
-                                                lessonRecord.expire = now.AddDays(Constant.private_lesson_expire).ToUnixTimeMilliseconds();
-                                                result.Add(Constant.private_lesson_expire, lessonRecord.expire);
+
+                                                //不到五点上传的课例,七天之后直接删除。
+                                                int addSecond = 0;
+                                                if (now.Hour > 5)
+                                                {
+                                                    // 到凌晨00点还差 (24 - now.Hour) *60 * 60 分钟,再加天数;
+                                                    addSecond = Constant.private_lesson_expire * 86400 + (24 - now.Hour) * 3600;
+                                                    //再加 00到05小时内的 随机秒数
+                                                    Random rand = new Random();
+                                                    addSecond += rand.Next(0 - 18000);
+                                                }
+                                                else
+                                                {
+                                                    addSecond = Constant.private_lesson_expire * 24 * 60 * 60;
+                                                }
+
+                                                lessonRecord.expire = now.AddSeconds(addSecond).ToUnixTimeMilliseconds();
+                                                //result.Add(Constant.private_lesson_expire, lessonRecord.expire);
+                                                result.Add(Constant.private_lesson_expire, new ExpireTag { expire = lessonRecord.expire, tag = "delete" });
                                                 string biz = "expire";
                                                 Notification notification = new Notification
                                                 {
@@ -1272,10 +1293,11 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
                                                         tmdname = teacher.name,
                                                         sid = lessonRecord.id,
                                                         sname = lessonRecord.name,
+                                                        scope=scope,
                                                         stime = lessonRecord.startTime,
                                                         expire = lessonRecord.expire,
                                                         status = 1,
-                                                        day = Constant.private_lesson_expire,
+                                                        //day = Constant.private_lesson_expire,
                                                         time = now
                                                     }.ToJsonString(),
                                                     expires = DateTimeOffset.UtcNow.AddDays(7).ToUnixTimeSeconds()
@@ -1307,10 +1329,11 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
                                                             tmdid = tmdid,
                                                             tmdname = teacher.name,
                                                             name = lessonRecord.name,
-                                                            startTime = lessonRecord.startTime
+                                                            startTime = lessonRecord.startTime,
+                                                            tag = item.Value.tag
                                                         }.ToJsonString());
                                                         message.ApplicationProperties.Add("name", "LessonRecordExpire");
-                                                        long start = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), message, DateTimeOffset.FromUnixTimeMilliseconds(item.Value));
+                                                        long start = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), message, DateTimeOffset.FromUnixTimeMilliseconds(item.Value.expire));
                                                         ChangeRecord changeRecord = new ChangeRecord
                                                         {
                                                             RowKey = lessonRecord.id,
@@ -1362,7 +1385,6 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
         [Function("LessonRecordExpire")]
         public async Task LessonRecordExpireFunc([ServiceBusTrigger("%Azure:ServiceBus:ActiveTask%", "lesson-record-expire", Connection = "Azure:ServiceBus:ConnectionString")] string msg)
         {
-
             try
             {
                 var jsonMsg = JsonDocument.Parse(msg).RootElement;
@@ -1376,9 +1398,10 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
                 jsonMsg.TryGetProperty("expire", out JsonElement expire);
                 jsonMsg.TryGetProperty("scope", out JsonElement scope);
                 jsonMsg.TryGetProperty("school", out JsonElement _school);
+                jsonMsg.TryGetProperty("tag", out JsonElement _tag);
                 var client = _azureCosmos.GetCosmosClient();
                 //处理到期删除
-                if ($"{progress}".Equals($"{Constant.private_lesson_expire}"))
+                if (_tag.ValueKind.Equals(JsonValueKind.String) && $"{_tag}".Equals("delete") )
                 {
                     string lessonId = $"{id}";
                     string tbname;
@@ -1433,7 +1456,7 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
                         stime = long.Parse($"{startTime}"),
                         expire = long.Parse($"{expire}"),
                         status = 1,
-                        day = Constant.private_lesson_expire,
+                        //day = Constant.private_lesson_expire,
                         time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()
                     }.ToJsonString(),
                     expires = DateTimeOffset.UtcNow.AddDays(7).ToUnixTimeSeconds()
@@ -1446,7 +1469,7 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
             }
             catch (Exception ex)
             {
-                await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-ServiceBus,Study()\n{ex.Message}\n{ex.StackTrace}\n{msg}", GroupNames.醍摩豆服務運維群組);
+                await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-ServiceBus,LessonRecordExpire()\n{ex.Message}\n{ex.StackTrace}\n{msg}", GroupNames.醍摩豆服務運維群組);
             }
 
         }

+ 1 - 0
TEAMModelOS.SDK/Context/Constant/Constant.cs

@@ -21,5 +21,6 @@ namespace TEAMModelOS.SDK.DI
         public static readonly string Student = "Student";
         public static readonly int private_lesson_limit =50;
         public static readonly int private_lesson_expire = 7;
+        public static readonly int school_lesson_expire = 7;
     }
 }

+ 7 - 0
TEAMModelOS.SDK/Models/Cosmos/Common/LessonRecord.cs

@@ -172,6 +172,9 @@ namespace TEAMModelOS.SDK.Models
         public double clientInteractionAverge { get; set; } = 0;
 
         public int examCount { get; set; }
+        /// <summary>
+        /// 总互动分
+        /// </summary>
         public double totalInteractPoint { get; set; } = 0;
         /// <summary>
         /// 过期时间,-1永不过期, 1577808000000 2020-01-01
@@ -189,6 +192,10 @@ namespace TEAMModelOS.SDK.Models
         /// 暂不 开放 teacher【开放给部分教师查看】醍摩豆id 
         /// </summary>
         public List<string> showTchs { get; set; } = new List<string>();
+        /// <summary>
+        /// 设置强制保留的 =1 ,不会被自动清理的。但是可以被手动清理。
+        /// </summary>
+        public int save { get; set; } = -1;
     }
     public class LessonTC
     {

+ 1 - 0
TEAMModelOS.SDK/Models/Cosmos/School/Paper.cs

@@ -62,6 +62,7 @@ namespace TEAMModelOS.SDK.Models
         public int multipleRule { get; set; }
         public string sheet { get; set; }
         public string sheetNo { get; set; }
+        public string mode { get; set; }
         //记录试卷大小
         public long? size { get; set; } = 0;
 

+ 19 - 2
TEAMModelOS.SDK/Models/Cosmos/School/SchoolSetting.cs

@@ -34,7 +34,24 @@ namespace TEAMModelOS.SDK.Models
         /// 课堂记录的标签
         /// </summary>
         public HashSet<string> lessonTag { get; set; } = new HashSet<string>();
+        public LessonSetting lessonSetting { get; set; }= new LessonSetting();
+    }
+    public class LessonSetting
+    {
+        /// <summary>
+        /// 是否开启自动清理  1 开启,0未开启
+        /// </summary>
+        public int openAutoClean { get; set; }
+        /// <summary>
+        /// 保留多少天
+        /// </summary>
+        public int expireDays { get; set; }
+        public List<LessonSettingCond> conds { get; set; }
+    }
+    public class LessonSettingCond
+    {
+        public string key { get; set; }
+        public double val { get; set; }
+        public string type { get; set; }
     }
-
-   
 }

+ 351 - 0
TEAMModelOS.SDK/Models/Service/LessonService.cs

@@ -1,4 +1,7 @@
 using Azure.Cosmos;
+using Azure.Messaging.ServiceBus;
+using HTEXLib.COMM.Helpers;
+using Microsoft.Extensions.Configuration;
 using System;
 using System.Collections.Generic;
 using System.Text;
@@ -13,6 +16,354 @@ namespace TEAMModelOS.SDK.Models.Service
 {
     public class LessonService
     {
+
+        public static async void DoAutoDeleteSchoolLessonRecord(LessonRecord lessonRecord,string  scope ,CosmosClient client,string school,string tmdid,
+            Teacher teacher, NotificationService _notificationService, AzureServiceBusFactory _serviceBus, AzureStorageFactory _azureStorage, IConfiguration _configuration) {
+            if (lessonRecord.scope.Equals("school"))
+            {
+                SchoolSetting setting = null;
+                Azure.Response schoolSetting = await client.GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemStreamAsync(school, new PartitionKey("SchoolSetting"));
+                School schoolBase = await client.GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemAsync<School>(school, new PartitionKey("Base"));
+                if (schoolSetting.Status == 200)
+                {
+                    setting = JsonDocument.Parse(schoolSetting.Content).RootElement.Deserialize<SchoolSetting>();
+                    if (setting.lessonSetting != null)
+                    {
+                        if (setting.lessonSetting.openAutoClean != 0 || setting.lessonSetting.openAutoClean != 1)
+                        {
+                            setting.lessonSetting.openAutoClean = 0;
+                            setting.lessonSetting.expireDays = Constant.school_lesson_expire;
+                        }
+                    }
+                    else
+                    {
+                        setting.lessonSetting = new LessonSetting() { openAutoClean = 0, expireDays = Constant.school_lesson_expire };
+                    }
+                }
+                else
+                {
+                    setting = new SchoolSetting() { lessonSetting = new LessonSetting { openAutoClean = 0, expireDays = Constant.school_lesson_expire } };
+                }
+                int school_lesson_expire =0;
+                bool save = true;
+                List<string> msg = new List<string>();
+                if (setting.lessonSetting.openAutoClean == 1)
+                {
+                    if (setting.lessonSetting.conds.IsEmpty())
+                    {
+                        save = false;
+                    }
+                    else {
+                        school_lesson_expire = setting.lessonSetting.expireDays;
+                        foreach (var item in setting.lessonSetting.conds)
+                        {
+                            switch (item.type)
+                            {
+                                case ">=":
+                                    switch (item.key)
+                                    {
+                                        case "attendRate":
+                                            if (!(lessonRecord.attendRate >= item.val))
+                                            {
+                                                save = false;
+                                                msg.Add($"{item.key}:{lessonRecord.attendRate}{item.type}{item.val}");
+                                            }
+                                            break;
+                                        case "groupCount":
+                                            if (!(lessonRecord.groupCount >= item.val))
+                                            {
+                                                save = false;
+                                                msg.Add($"{item.key}:{lessonRecord.groupCount}{item.type}{item.val}");
+                                            }
+                                            break;
+                                        case "totalPoint":
+                                            if (!(lessonRecord.totalPoint >= item.val))
+                                            {
+                                                save = false;
+                                                msg.Add($"{item.key}:{lessonRecord.totalPoint}{item.type}{item.val}");
+                                            }
+                                            break;
+                                        case "collateTaskCount":
+                                            if (!(lessonRecord.collateTaskCount >= item.val))
+                                            {
+                                                save = false;
+                                                msg.Add($"{item.key}:{lessonRecord.collateTaskCount}{item.type}{item.val}");
+                                            }
+                                            break;
+                                        case "collateCount":
+                                            if (!(lessonRecord.collateCount >= item.val))
+                                            {
+                                                save = false;
+                                                msg.Add($"{item.key}:{lessonRecord.collateCount}{item.type}{item.val}");
+                                            }
+                                            break;
+                                        case "pushCount":
+                                            if (!(lessonRecord.pushCount >= item.val))
+                                            {
+                                                save = false;
+                                                msg.Add($"{item.key}:{lessonRecord.pushCount}{item.type}{item.val}");
+                                            }
+                                            break;
+                                        case "totalInteractPoint":
+                                            if (!(lessonRecord.totalInteractPoint >= item.val))
+                                            {
+                                                save = false;
+                                                msg.Add($"{item.key}:{lessonRecord.totalInteractPoint}{item.type}{item.val}");
+                                            }
+                                            break;
+                                        case "interactionCount":
+                                            if (!(lessonRecord.interactionCount >= item.val))
+                                            {
+                                                save = false;
+                                                msg.Add($"{item.key}:{lessonRecord.interactionCount}{item.type}{item.val}");
+                                            }
+                                            break;
+                                        case "clientInteractionCount":
+                                            if (!(lessonRecord.clientInteractionCount >= item.val))
+                                            {
+                                                save = false;
+                                                msg.Add($"{item.key}:{lessonRecord.clientInteractionCount}{item.type}{item.val}");
+                                            }
+                                            break;
+                                        case "examQuizCount":
+                                            if (!(lessonRecord.examQuizCount >= item.val))
+                                            {
+                                                save = false;
+                                                msg.Add($"{item.key}:{lessonRecord.examQuizCount}{item.type}{item.val}");
+                                            }
+                                            break;
+                                        case "examPointRate":
+                                            if (!(lessonRecord.examPointRate >= item.val))
+                                            {
+                                                save = false;
+                                                msg.Add($"{item.key}:{lessonRecord.examPointRate}{item.type}{item.val}");
+                                            }
+                                            break;
+                                    }
+                                    break;
+                                case "<=":
+                                    switch (item.key)
+                                    {
+                                        case "attendRate":
+                                            if (!(lessonRecord.attendRate <= item.val))
+                                            {
+                                                save = false;
+                                                msg.Add($"{item.key}:{lessonRecord.attendRate}{item.type}{item.val}");
+                                            }
+                                            break;
+                                        case "groupCount":
+                                            if (!(lessonRecord.groupCount <= item.val))
+                                            {
+                                                save = false;
+                                                msg.Add($"{item.key}:{lessonRecord.groupCount}{item.type}{item.val}");
+                                            }
+                                            break;
+                                        case "totalPoint":
+                                            if (!(lessonRecord.totalPoint <= item.val))
+                                            {
+                                                save = false;
+                                                msg.Add($"{item.key}:{lessonRecord.totalPoint}{item.type}{item.val}");
+                                            }
+                                            break;
+                                        case "collateTaskCount":
+                                            if (!(lessonRecord.collateTaskCount <= item.val))
+                                            {
+                                                save = false;
+                                                msg.Add($"{item.key}:{lessonRecord.collateTaskCount}{item.type}{item.val}");
+                                            }
+                                            break;
+                                        case "collateCount":
+                                            if (!(lessonRecord.collateCount <= item.val))
+                                            {
+                                                save = false;
+                                                msg.Add($"{item.key}:{lessonRecord.collateCount}{item.type}{item.val}");
+                                            }
+                                            break;
+                                        case "pushCount":
+                                            if (!(lessonRecord.pushCount <= item.val))
+                                            {
+                                                save = false;
+                                                msg.Add($"{item.key}:{lessonRecord.pushCount}{item.type}{item.val}");
+                                            }
+                                            break;
+                                        case "totalInteractPoint":
+                                            if (!(lessonRecord.totalInteractPoint <= item.val))
+                                            {
+                                                save = false;
+                                                msg.Add($"{item.key}:{lessonRecord.totalInteractPoint}{item.type}{item.val}");
+                                            }
+                                            break;
+                                        case "interactionCount":
+                                            if (!(lessonRecord.interactionCount <= item.val))
+                                            {
+                                                save = false;
+                                                msg.Add($"{item.key}:{lessonRecord.interactionCount}{item.type}{item.val}");
+                                            }
+                                            break;
+                                        case "clientInteractionCount":
+                                            if (!(lessonRecord.clientInteractionCount <= item.val))
+                                            {
+                                                save = false;
+                                                msg.Add($"{item.key}:{lessonRecord.clientInteractionCount}{item.type}{item.val}");
+                                            }
+                                            break;
+                                        case "examQuizCount":
+                                            if (!(lessonRecord.examQuizCount <= item.val))
+                                            {
+                                                save = false;
+                                                msg.Add($"{item.key}:{lessonRecord.examQuizCount}{item.type}{item.val}");
+                                            }
+                                            break;
+                                        case "examPointRate":
+                                            if (!(lessonRecord.examPointRate <= item.val))
+                                            {
+                                                save = false;
+                                                msg.Add($"{item.key}:{lessonRecord.examPointRate}{item.type}{item.val}");
+                                            }
+                                            break;
+                                    }
+                                    break;
+                            }
+                        }
+                    }
+                   
+                }
+                else {
+                    save = false;
+                    school_lesson_expire = Constant.school_lesson_expire;
+
+
+                }
+
+                if (!save && school_lesson_expire > 0)
+                {
+                    // 1-时间戳,7-时间戳
+                    Dictionary<int, ExpireTag> result = new Dictionary<int, ExpireTag>();
+                    //暂定7天 
+                    var now = DateTimeOffset.UtcNow;
+                    //剩余3天的通知
+                    //var day3= now.AddDays(school_lesson_expire - 3).ToUnixTimeMilliseconds();
+                    //result.Add(3, day3);
+                    //剩余1天的通知
+                    var day1 = now.AddDays(school_lesson_expire - (school_lesson_expire - 1)).ToUnixTimeMilliseconds();
+                    result.Add(1, new ExpireTag { expire= day1 ,tag= "notification" });
+                    //到期通知
+                    //不到五点上传的课例,七天之后直接删除。
+                    int addSecond = 0;
+                    if (now.Hour > 5)
+                    {
+                        // 到凌晨00点还差 (24 - now.Hour) *60 * 60 分钟,再加天数;
+                        addSecond = school_lesson_expire * 86400 + (24 - now.Hour) * 3600;
+                        //再加 00到05小时内的 随机秒数
+                        Random rand = new Random();
+                        addSecond += rand.Next(0 - 18000);
+                    }
+                    else
+                    {
+                        addSecond = school_lesson_expire * 24 * 60 * 60;
+                    }
+                    lessonRecord.expire = now.AddSeconds(addSecond).ToUnixTimeMilliseconds();
+                    result.Add(school_lesson_expire, new ExpireTag { expire = lessonRecord.expire, tag = "delete" });
+                   // result.Add(school_lesson_expire, lessonRecord.expire);
+                    string biz = "expire";
+                    Notification notification = new Notification
+                    {
+                        hubName = "hita",
+                        type = "msg",
+                        from = $"ies5:{ Environment.GetEnvironmentVariable("Option:Location")}:private",
+                        to = new List<string> { tmdid },
+                        label = $"{biz}_lessonRecord",
+                        body = new
+                        {
+                            location = $"{Environment.GetEnvironmentVariable("Option:Location")}",
+                            biz = biz,
+                            tmdid = tmdid,
+                            tmdname = teacher.name,
+                            scope = scope,
+                            school = school,
+                            schoolName = schoolBase.name,
+                            sid = lessonRecord.id,
+                            sname = lessonRecord.name,
+                            stime = lessonRecord.startTime,
+                            expire = lessonRecord.expire,
+                            status = 1,
+                            //day = school_lesson_expire,
+                            time = now
+                        }.ToJsonString(),
+                        expires = DateTimeOffset.UtcNow.AddDays(7).ToUnixTimeSeconds()
+                    };
+                    var url = _configuration.GetValue<string>("HaBookAuth:CoreService:sendnotification");
+                    var clientID = _configuration.GetValue<string>("HaBookAuth:CoreService:clientID");
+                    var clientSecret = _configuration.GetValue<string>("HaBookAuth:CoreService:clientSecret");
+                    var location = $"{Environment.GetEnvironmentVariable("Option:Location")}";
+                    await _notificationService.SendNotification(clientID, clientSecret, location, url, notification); //站内发送消息
+
+                    var table = _azureStorage.GetCloudTableClient().GetTableReference("ChangeRecord");
+                    List<ChangeRecord> records = await table.FindListByDict<ChangeRecord>(new Dictionary<string, object>() { { "RowKey", lessonRecord.id } });
+                    if (records.Count <= 0)
+                    {
+                        foreach (var item in result)
+                        {
+                            string PartitionKey = string.Format("{0}{1}{2}", lessonRecord.code, "-", $"expire-{item.Key}");
+                            //课堂的id ,
+                            //课堂的通知时间类型progress, 默认就会发送一条,到期前一天发送一条,最后已到期发送一条。
+                            var message = new ServiceBusMessage(new
+                            {
+                                id = lessonRecord.id,
+                                progress = item.Key,
+                                code = lessonRecord.code,
+                                scope = lessonRecord.scope,
+                                school = lessonRecord.school,
+                                opt = "delete",
+                                expire = lessonRecord.expire,
+                                tmdid = tmdid,
+                                tmdname = teacher.name,
+                                name = lessonRecord.name,
+                                startTime = lessonRecord.startTime,
+                                tag = item.Value.tag
+                            }.ToJsonString());
+                            message.ApplicationProperties.Add("name", "LessonRecordExpire");
+                            long start = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), message, DateTimeOffset.FromUnixTimeMilliseconds(item.Value.expire));
+                            ChangeRecord changeRecord = new ChangeRecord
+                            {
+                                RowKey = lessonRecord.id,
+                                PartitionKey = PartitionKey,
+                                sequenceNumber = start,
+                                msgId = message.MessageId
+                            };
+                            await table.Save<ChangeRecord>(changeRecord);
+                        }
+                    }
+                }
+                else {
+
+                    if (lessonRecord.expire > 0)
+                    {
+                        var table = _azureStorage.GetCloudTableClient().GetTableReference("ChangeRecord");
+                        List<ChangeRecord> records = await table.FindListByDict<ChangeRecord>(new Dictionary<string, object>() { { "RowKey", lessonRecord.id } });
+                        foreach (var record in records)
+                        {
+                            try
+                            {
+                                await table.DeleteSingle<ChangeRecord>(record.PartitionKey, record.RowKey);
+                                await _serviceBus.GetServiceBusClient().CancelMessageAsync(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), record.sequenceNumber);
+                            }
+                            catch (Exception)
+                            {
+                                continue;
+                            }
+                        }
+                    }
+                    lessonRecord.expire = -1;
+                }
+            }
+        }
+
+
+        public record ExpireTag {
+            public long expire { get; set; }
+            public string tag { get; set; }
+        }
         /// <summary>
         /// 
         /// </summary>

+ 4 - 1
TEAMModelOS.SDK/Models/Service/Third/Xkw/XkwOAuthModel.cs

@@ -98,7 +98,10 @@ namespace TEAMModelOS.SDK.Models
         public string userId { get; set; }
         public string domain { get; set; }
     }
-
+    public record ServiceModule { 
+        public string module { get; set; }
+        public string url { get; set; }
+    }
     public record OAuthCode
     {
         public string code { get; set; }

+ 10 - 2
TEAMModelOS/ClientApp/public/index.html

@@ -1,16 +1,24 @@
 <!DOCTYPE html>
 <html lang="en">
+
 <head>
 	<meta charset="utf-8">
 	<meta http-equiv="X-UA-Compatible" content="IE=edge">
 	<meta name="viewport" content="width=device-width,initial-scale=1.0">
 	<link rel="icon" href="<%= BASE_URL %>favicon.ico">
 	<link id="theme" type="text/css" rel="stylesheet" href="<%= BASE_URL %>theme/dark-theme.css">
-	<script src="<%= BASE_URL %>lang/zh-CN.js"></script>
+	<!-- <script src="<%= BASE_URL %>lang/zh-CN.js"></script>
 	<script src="<%= BASE_URL %>lang/zh-TW.js"></script>
-	<script src="<%= BASE_URL %>lang/en-US.js"></script>
+	<script src="<%= BASE_URL %>lang/en-US.js"></script> -->
 	<title></title>
 	<script>
+		// 自动根据浏览器系统语言设置语言(优先判断本地设置的语言,如果有则使用本地设置的语言,如果没有则使用浏览器系统语言)
+		const curLang = localStorage.getItem('cloudSetting') ? JSON.parse(localStorage.getItem('cloudSetting')).curLang : null
+		const navLang = curLang || navigator.language.toLowerCase()
+		const localLang = (navLang === 'zh' || navLang === 'zh-tw' || navLang === 'zh-cn' || navLang === 'zh-hk') ? navLang : false
+		const lang = localLang || 'en-us'
+		const langJsUrl = 'https://' + window.location.host + '/lang/' + lang + '.js'
+		document.write('<script  src="' + langJsUrl + '"><\/script>')
 		MathJax = {
 			loader: {
 				load: ["input/tex", "output/svg"]

Файловите разлики са ограничени, защото са твърде много
+ 4 - 8
TEAMModelOS/ClientApp/public/lang/en-US.js


+ 5 - 9
TEAMModelOS/ClientApp/public/lang/zh-CN.js

@@ -317,7 +317,7 @@ const LANG_ZH_CN = {
         syllabus: '课纲',
         itemAndPaper: '试题试卷',
         appData: '其他应用数据',
-        content: '内容资源',
+        content: '内容',
         used: '已使用:',
         expired: '服务到期日:',
         prodCont: '服务内容:',
@@ -2479,7 +2479,7 @@ const LANG_ZH_CN = {
             rmvTitle: '移除老师',
             rmvContent: '是否确认移除',
             baseErr: '请完成阅卷基础设置',
-            teacherErr: '请完成阅卷和相关老师设置',
+            teacherErr: '阅卷和相关老师设置',
             saveOk: '保存成功!',
             saveErr: '保存失败!',
             deleteOk: '删除成功',
@@ -2497,14 +2497,13 @@ const LANG_ZH_CN = {
             orderIndex: '序号',
             quNo: '题号',
             teaCount: '教师人数',
-            markCount1: '阅卷量',
+            markCount: '阅卷量',
             delBlockTitle: '删除题块',
             delBlockCont: '确认删除当前题块设置吗?',
             selectQuTips: '请选择题目进行划块',
             selectTeaTips: '请设置当前题块的阅卷老师',
             lastQu: '题目尚未完全分配',
             reapQu: '题目划块设置存在重复题目',
-            setQuBlock: '请设置题目分块',
             objectiveLabel: '(客)',
             alreadyLabel: '(已)',
             exTag: '异常',
@@ -2567,7 +2566,7 @@ const LANG_ZH_CN = {
             saveErr: '保存失败',
             noSocreErr: '请先打分',
             completeQu: '当前题目已阅完,请切换题目',
-            completeStu: '完成当前学生评分,如果继续评分,请切换学生',
+            completeStu: '当前完成当前学生评分,如果继续评分,请切换学生',
             noAnswer: '未作答',
             stuInfoErr: '学生信息异常',
             ummarkQu: '未阅题目',
@@ -4508,9 +4507,6 @@ const LANG_ZH_CN = {
             wrongNum: "错误次数",
         },
         myAchievement: {
-            examAch: "评测成绩",
-            hwAch: "作业成绩",
-            cusAch: "老师给分",
             examMode: "评测模式",
             examIn: "发布来源",
             name: "名称",
@@ -5469,7 +5465,7 @@ const LANG_ZH_CN = {
         text3: '更多筛选',
         text4: '输入考试名称...',
         text5: '当前筛选条件',
-        text6: '符合条件数量',
+        text6: '当前数量',
         text7: '参与人数',
         text8: '考试日期',
         text9: '无',

Файловите разлики са ограничени, защото са твърде много
+ 11 - 15
TEAMModelOS/ClientApp/public/lang/zh-TW.js


+ 1 - 1
TEAMModelOS/ClientApp/src/api/lessonRecord.js

@@ -26,7 +26,7 @@ export default {
         return post('/common/lesson-record/delete-lesson-record', data)
     }, 
 	// 查询学校设置的课例类别
-	findLessonTags: function (data) {
+	findLessonSettings: function (data) {
         return post('/school/setting/find-id', data)
     }, 
 	// 设置学校的课例类别

+ 6 - 20
TEAMModelOS/ClientApp/src/locale/index.js

@@ -1,35 +1,21 @@
 import Vue from 'vue'
 import VueI18n from 'vue-i18n'
-// 引入iView多语言包
-import zhLocale from 'view-design/src/locale/lang/zh-CN'
-import enLocale from 'view-design/src/locale/lang/en-US'
-import twLocale from 'view-design/src/locale/lang/zh-TW'
-// 引入elementUI多语言包
-import enEl from 'element-ui/lib/locale/lang/en'
-import zhEl from 'element-ui/lib/locale/lang/zh-CN'
-import twEl from 'element-ui/lib/locale/lang/zh-TW'
+import tools from '@/utils/public.js'
 import ElementLocale from 'element-ui/lib/locale'
 ElementLocale.i18n((key, value) => i18n.t(key, value))
 Vue.use(VueI18n)
 // 自动根据浏览器系统语言设置语言(优先判断本地设置的语言,如果有则使用本地设置的语言,如果没有则使用浏览器系统语言)
-const curLang  = localStorage.getItem('cloudSetting') ? JSON.parse(localStorage.getItem('cloudSetting')).curLang : null
+const curLang = localStorage.getItem('cloudSetting') ? JSON.parse(localStorage.getItem('cloudSetting')).curLang : null
 const navLang = curLang || navigator.language.toLowerCase()
 const localLang = (navLang === 'zh' || navLang === 'zh-tw' || navLang === 'zh-cn' || navLang === 'zh-hk') ? navLang : false
 let lang = localLang || 'en-us'
 localStorage.setItem('local', lang)
 Vue.config.lang = lang
 Vue.locale = () => { }
-// 将本地语言包、elementUI语言包、iview语言包合并
-const messages = {
-    'zh-cn': Object.assign(LANG_ZH_CN, zhLocale, zhEl),
-    'zh': Object.assign(LANG_ZH_CN, zhLocale,zhEl),
-    'zh-tw': Object.assign(LANG_ZH_TW, twLocale,twEl),
-    'zh-hk': Object.assign(LANG_ZH_TW, twLocale, twEl),
-    'en-us': Object.assign(LANG_EN_US, enLocale, enEl)
-}
 const i18n = new VueI18n({
-  locale: lang,
-  messages
+  locale: lang
+})
+setTimeout(() => {
+  tools.seti18nLang(lang)
 })
-
 export default i18n

+ 60 - 3
TEAMModelOS/ClientApp/src/utils/public.js

@@ -8,12 +8,22 @@ import JsPDF from 'jspdf'
 import 'jspdf-autotable'
 import domtoimage from '@/utils/dom_to_image';
 import excel from '@/utils/excel.js'
+import i18n from '@/locale'
+// 引入iView多语言包
+import zhLocale from 'view-design/src/locale/lang/zh-CN'
+import enLocale from 'view-design/src/locale/lang/en-US'
+import twLocale from 'view-design/src/locale/lang/zh-TW'
+// 引入elementUI多语言包
+import enEl from 'element-ui/lib/locale/lang/en'
+import zhEl from 'element-ui/lib/locale/lang/zh-CN'
+import twEl from 'element-ui/lib/locale/lang/zh-TW'
 import {
 	app
 } from '@/boot-app.js'
 import {
-	Message
+	Message,Modal
 } from 'view-design'
+
 /**
  * 校验blob授权是否过期
  * */
@@ -178,6 +188,40 @@ export default {
 		'justify', // 对齐方式
 		'table', // 表格
 	],
+	/* 切换语系 */
+	changeLang(lang) {
+		// 如果已经加载过语言包 则直接设置 否则加载语言包
+		if (lang.toLowerCase() === 'zh-cn' && window.LANG_ZH_CN) {
+			this.seti18nLang(lang)
+		} else if (lang.toLowerCase() === 'zh-tw' && window.LANG_ZH_TW) {
+			this.seti18nLang(lang)
+		} else if (lang.toLowerCase() === 'en-us' && window.LANG_EN_US) {
+			this.seti18nLang(lang)
+		} else {
+			this.loadLangJs(lang)
+		}
+	},
+	/* 加载语言包 */
+	loadLangJs(lang) {
+		let script = document.createElement('script')
+		script.type = 'text/javascript'
+		script.src = 'https://' + window.location.host + '/lang/' + lang + '.js'
+		document.getElementsByTagName('head')[0].appendChild(script)
+		script.onload = () => {
+			this.seti18nLang(lang)
+		}
+	},
+	/* 设置到i18n语系 */
+	seti18nLang(lang) {
+		if (lang.toLowerCase() === 'zh-cn') {
+			i18n.setLocaleMessage(lang, Object.assign(LANG_ZH_CN, zhLocale, zhEl))
+		} else if (lang.toLowerCase() === 'zh-tw') {
+			i18n.setLocaleMessage(lang, Object.assign(LANG_ZH_TW, twLocale, twEl))
+		} else {
+			i18n.setLocaleMessage(lang, Object.assign(LANG_EN_US, enLocale, enEl))
+		}
+		document.title = app.$t('system.title')
+	},
 	/* 全屏 */
 	fullScreen(element) {
 		// var element = document.documentElement;
@@ -266,14 +310,27 @@ export default {
 						if (videoTrack && audioTrack) {
 							let videoFormat = videoTrack.Format.toLowerCase()
 							let audioFormat = audioTrack.Format.toLowerCase()
-							if((videoFormat === 'avc' && audioFormat === 'aac') || (['vp8','vp9'].includes(videoFormat) && audioFormat === 'vorbis')) {
+							if ((videoFormat === 'avc' && audioFormat === 'aac') || (['vp8', 'vp9'].includes(videoFormat) && audioFormat === 'vorbis')) {
 								r(videoTrack.Format_Profile || true)
+							} else {
+								r(false)
+							}
+						}
+						// 如果是只有视频轨没有音频轨(PPT直接转视频)
+						else if (videoTrack && !audioTrack) {
+							let videoFormat = videoTrack.Format.toLowerCase()
+							if(videoFormat === 'avc'){
+								Modal.info({
+									title: "温馨提示",
+									content: "视频文件未检测到音频轨,建议您调整后重新上传"
+								})
+								r(true)
 							}else{
 								r(false)
 							}
 						}
 						// 如果是音频文件则需要满足 mp3(MPEG Audio),ogg(Vorbis),wav(PCM) 任意一种编码格式
-						else if (!videoTrack && audioTrack && ['mpeg audio','vorbis','pcm'].includes(audioTrack.Format.toLowerCase())) {
+						else if (!videoTrack && audioTrack && ['mpeg audio', 'vorbis', 'pcm'].includes(audioTrack.Format.toLowerCase())) {
 							r(true)
 						} else {
 							r(false)

+ 3 - 0
TEAMModelOS/ClientApp/src/view/evaluation/bank/TestPaperList.vue

@@ -40,6 +40,7 @@
 						<span class="paper-item-tag" v-if="isSchool">{{ paper.subjectName }}</span>
 						<span style="margin-left: 8px;">{{ paper.name }}</span>
 						<span style="margin-left: 8px;" v-for="(tag,tagIndex) in paper.tags"><Tag color="geekblue" style="vertical-align: sub;">{{ tag }}</Tag></span>
+						<span style="margin-left: 8px;" v-if="paper.mode"><Tag color="green" style="vertical-align: sub;">{{ paper.mode }}</Tag></span>
 					</div>
 					<div class="paper-item-info">
 						<span class="info-item" v-if="isSchool">{{$t('evaluation.paperList.usePeriod')}}:<span
@@ -246,6 +247,7 @@
 					fullPaperJson.code = curPaper.code
 					fullPaperJson.sheet = curPaper.sheet
 					fullPaperJson.sheetNo = curPaper.sheetNo
+					fullPaperJson.mode = curPaper.mode
 					let paper = fullPaperJson
 					let schoolInfo = null
 					if (paper.scope === 'school') {
@@ -268,6 +270,7 @@
 						item: paper.item,
 						sheet: paper.sheet || null,
 						sheetNo: paper.sheetNo || null,
+						mode: paper.mode || null,
 						multipleRule: paper.multipleRule,
 						startTime: 0,
 						endTime: 0,

+ 2 - 2
TEAMModelOS/ClientApp/src/view/evaluation/index/TestPaper.vue

@@ -40,7 +40,7 @@
 								v-show="paperInfo.item.length">{{ isShowAnalysis ? this.$t('evaluation.paperList.paperDetails') : this.$t('evaluation.paperList.paperAnalysis')}}</Button>
 							<Button class="base-info-btn" type="info" v-show="paperInfo.item.length && paperInfo.id" @click="onChooseOrderTemp">{{ $t('evaluation.orderTemp') }}</Button>
 							<Button class="base-info-btn" type="info" @click="downloadSheet" :loading="downLoading"
-								v-show="paperInfo.item.length && paperInfo.id && paper.sheetNo">{{ $t('evaluation.paperList.goAnswerSheet') }}</Button>
+								v-show="paperInfo.item.length && paperInfo.id && paper.sheetNo">{{ $t('evaluation.paperList.goAnswerSheet') }}<span v-if="paperInfo.mode">-{{ paperInfo.mode }}</span></Button>
 							<Button class="base-info-btn" type="info" @click="goAnswerSheet"
 								v-show="paperInfo.item.length && paperInfo.id">{{ paper.sheetNo ?  $t('evaluation.paperList.reCreateSheet') : $t('evaluation.paperList.createSheet') }}</Button>
 						</div>
@@ -52,7 +52,7 @@
 							<Button class="base-info-btn" type="info" @click="isShowAnalysis = !isShowAnalysis"
 								v-show="!isHideAnalysis">{{ isShowAnalysis ? this.$t('evaluation.paperList.paperDetails') : this.$t('evaluation.paperList.paperAnalysis')}}</Button>
 							<Button class="base-info-btn" type="info" @click="downloadSheet" :loading="downLoading"
-								v-show="paperInfo.id && paper.sheetNo && !hideSheet && !isSharePreview">{{ $t('evaluation.paperList.goAnswerSheet') }}</Button>
+								v-show="paperInfo.id && paper.sheetNo && !hideSheet && !isSharePreview">{{ $t('evaluation.paperList.goAnswerSheet') }}<span v-if="paperInfo.mode">-{{ paperInfo.mode }}</span></Button>
 							<Button class="base-info-btn" type="info" @click="goAnswerSheet"
 								v-show="paperInfo.id && !hideSheet && !isSharePreview">{{ paper.sheetNo ?  $t('evaluation.paperList.reCreateSheet') : $t('evaluation.paperList.createSheet') }}</Button>
 							<Button class="base-info-btn" type="info" @click="exitPreview"

+ 153 - 116
TEAMModelOS/ClientApp/src/view/research-center/BaseCleanCond.vue

@@ -1,124 +1,161 @@
 <template>
-	<div class="base-clean-container">
-		<p style="font-weight: bold;color: #189df0;font-size: 14px;margin-bottom: 10px;"><Icon type="md-information-circle" /> 自动清除时间设置</p>
-		<div class="clean-item">
-			<span style="font-weight: bold;margin-right: 20px;">课堂记录保留期限</span>
-			<InputNumber :formatter="value => `${parseInt(Math.floor(value*100)/100)}`" :max="30" :min="1" :step="1" v-model="expireDays"></InputNumber>
-			<span style="margin-left: 10px;">天</span>
-		</div>
-		<p style="font-weight: bold;color: #F06431;font-size: 14px;margin-bottom: 10px;"><Icon type="md-information-circle" /> 符合以下条件的课堂记录,将会进行保留,不会被系统自动清除</p>
-		<div class="clean-item" v-for="(item,index) in condArr">
-			<span class="clean-item-name">{{ item.name }}</span>
-			<Select v-model="item.type" style="width:120px;margin: 0 20px;">
-				<Option value=">=">大于等于</Option>
-				<Option value="<=">小于等于</Option>
-			</Select>
-			<InputNumber :formatter="value => `${parseInt(Math.floor(value*100)/100)}`" :max="item.unit === 'rate' ? 100 : 10000" :min="0" :step="1" v-model="item.value"></InputNumber>
-			<span style="margin-left: 10px;">{{ item.unit === 'rate' ? '%' : item.unit === 'point' ? '分' : '个' }}</span>
-		</div>
-	</div>
+  <div class="base-clean-container">
+    <div style="display:flex;align-items:center">
+      <span style="font-weight: bold;font-size: 14px;">
+        自定义设置
+      </span>
+      <i-switch size="large" v-model="openAutoClean" style="margin-left:10px">
+        <span slot="open">开启</span>
+        <span slot="close">关闭</span>
+      </i-switch>
+      <Tooltip content="默认课堂记录仅保留7天(被收藏的课例除外),若开启自定义设置,则需要您设置保留期限以及保留条件" :max-width="300" theme="light" placement="right" style="margin-left: 10px">
+        <Icon type="md-information-circle" color="#888" size="16"/>
+      </Tooltip>
+    </div>
+    <div v-if="openAutoClean" style="margin-top:20px;">
+      <p style="font-weight: bold;color: #189df0;font-size: 14px;margin-bottom: 10px;">
+        <Icon type="md-information-circle" /> 课例保留时间设置
+      </p>
+      <div class="clean-item">
+        <span style="font-weight: bold;margin-right: 20px;">课堂记录保留期限</span>
+        <InputNumber :formatter="val => `${parseInt(Math.floor(val*100)/100)}`" :max="30" :min="1" :step="1" v-model="expireDays"></InputNumber>
+        <span style="margin-left: 10px;">天</span>
+      </div>
+      <p style="font-weight: bold;color: #F06431;font-size: 14px;margin-bottom: 10px;">
+        <Icon type="md-information-circle" /> 符合以下条件的课堂记录,将会进行保留,不会被系统自动清除
+      </p>
+      <div class="clean-item" v-for="(item,index) in condArr">
+        <span class="clean-item-name">{{ item.name }}</span>
+        <Select v-model="item.type" style="width:120px;margin: 0 20px;">
+          <Option value=">=">大于等于</Option>
+          <Option value="<=">小于等于</Option>
+        </Select>
+        <InputNumber :formatter="val => `${parseInt(Math.floor(val*100)/100)}`" :max="item.unit === 'rate' ? 100 : 10000" :min="0" :step="1" v-model="item.val"></InputNumber>
+        <span style="margin-left: 10px;">{{ item.unit === 'rate' ? '%' : item.unit === 'point' ? '分' : '个' }}</span>
+      </div>
+    </div>
+
+  </div>
 </template>
 
 <script>
-	export default {
-		data(){
-			return {
-				expireDays:7,
-				condArr:[
-					{
-						name:this.$t('lessonRecord.attendCount'),
-						key:'attendRate',
-						value:0, 
-						unit:'rate', 
-						type:'>='
-					},
-					{
-						name:this.$t('lessonRecord.groupCount'),
-						key:'groupCount',
-						value:0, 
-						unit:'count',
-						type:'>='
-					},
-					{
-						name:this.$t('lessonRecord.totalPoint'),
-						key:'totalPoint',
-						value:0, 
-						unit:'point',
-						type:'>='
-					},
-					{
-						name:this.$t('lessonRecord.collateTaskCount'),
-						key:'collateTaskCount',
-						value:0, 
-						unit:'count',
-						type:'>='
-					},
-					{
-						name:this.$t('lessonRecord.collateCount'),
-						key:'collateCount',
-						value:0, 
-						unit:'count',
-						type:'>='
-					},
-					{
-						name:this.$t('lessonRecord.pushCount'),
-						key:'pushCount',
-						value:0, 
-						unit:'count',
-						type:'>='
-					},
-					{
-						name:this.$t('lessonRecord.score'),
-						key:'score',
-						value:0, 
-						unit:'point',
-						type:'>='
-					},
-					{
-						name:this.$t('lessonRecord.interactionCount'),
-						key:'interactionCount',
-						value:0, 
-						unit:'count',
-						type:'>='
-					},
-					{
-						name:this.$t('lessonRecord.clientInteractionCount'),
-						key:'clientInteractionCount',
-						value:0, 
-						unit:'count',
-						type:'>='
-					},
-					{
-						name:this.$t('lessonRecord.examQuizCount'),
-						key:'examQuizCount',
-						value:0, 
-						unit:'count',
-						type:'>='
-					},
-					{
-						name:this.$t('lessonRecord.examPointRate'),
-						key:'examPointRate',
-						value:0, 
-						unit:'rate',
-						type:'>='
-					}
-				]
-			}
-		}
-	}
+export default {
+  data() {
+    return {
+      openAutoClean: false,
+      expireDays: 7,
+      condArr: [
+        {
+          name: this.$t('lessonRecord.attendCount'),
+          key: 'attendRate',
+          val: 0,
+          unit: 'rate',
+          type: '>='
+        },
+        {
+          name: this.$t('lessonRecord.groupCount'),
+          key: 'groupCount',
+          val: 0,
+          unit: 'count',
+          type: '>='
+        },
+        {
+          name: this.$t('lessonRecord.totalPoint'),
+          key: 'totalPoint',
+          val: 0,
+          unit: 'point',
+          type: '>='
+        },
+        {
+          name: this.$t('lessonRecord.collateTaskCount'),
+          key: 'collateTaskCount',
+          val: 0,
+          unit: 'count',
+          type: '>='
+        },
+        {
+          name: this.$t('lessonRecord.collateCount'),
+          key: 'collateCount',
+          val: 0,
+          unit: 'count',
+          type: '>='
+        },
+        {
+          name: this.$t('lessonRecord.pushCount'),
+          key: 'pushCount',
+          val: 0,
+          unit: 'count',
+          type: '>='
+        },
+        {
+          name: this.$t('lessonRecord.score'),
+          key: 'score',
+          val: 0,
+          unit: 'point',
+          type: '>='
+        },
+        {
+          name: this.$t('lessonRecord.interactionCount'),
+          key: 'interactionCount',
+          val: 0,
+          unit: 'count',
+          type: '>='
+        },
+        {
+          name: this.$t('lessonRecord.clientInteractionCount'),
+          key: 'clientInteractionCount',
+          val: 0,
+          unit: 'count',
+          type: '>='
+        },
+        {
+          name: this.$t('lessonRecord.examQuizCount'),
+          key: 'examQuizCount',
+          val: 0,
+          unit: 'count',
+          type: '>='
+        },
+        {
+          name: this.$t('lessonRecord.examPointRate'),
+          key: 'examPointRate',
+          val: 0,
+          unit: 'rate',
+          type: '>='
+        }
+      ]
+    }
+  },
+  created() {
+    this.$api.lessonRecord.findLessonSettings({
+      schoolId: this.$store.state.userInfo.schoolCode
+    }).then(res => {
+      if (!res.error) {
+        this.openAutoClean = res.setting.lessonSetting.openAutoClean === 1
+        this.expireDays = res.setting.lessonSetting.expireDays
+        this.condArr.map(item => {
+          let findItem = res.setting.lessonSetting.conds.find(i => i.key === item.key)
+          if (findItem) {
+            item.val = findItem.val
+            item.type = findItem.type
+          }
+        })
+      }
+    })
+  }
+}
 </script>
 
 <style lang="less">
-	.base-clean-container{
-		.clean-item{
-			margin: 15px 0;
-			display: flex;
-			align-items: center;
-			&-name{
-				display: inline-block;
-				font-weight: bold;
-				width: 80px;
-			}
-		}
-	}
+.base-clean-container {
+  .clean-item {
+    margin: 15px 0;
+    display: flex;
+    align-items: center;
+    &-name {
+      display: inline-block;
+      font-weight: bold;
+      width: 80px;
+    }
+  }
+}
 </style>

Файловите разлики са ограничени, защото са твърде много
+ 814 - 802
TEAMModelOS/ClientApp/src/view/research-center/ResearchMgt.vue


+ 224 - 223
TEAMModelOS/ClientApp/src/view/settings/Index.vue

@@ -1,26 +1,26 @@
 <template>
-    <div class="settings-container">
-        <div class="settings-header">
-            <span :class="['settings-header-item',activeTab === '1' ?  'active-item' : '']" @click="onTabChange('1')">{{ $t('settings.setting_title1')}}</span>
-            <span :class="['settings-header-item',activeTab === '0' ?  'active-item' : '']" @click="onTabChange('0')">{{ $t('settings.setting_title2')}}</span>
-            <!-- <span :class="['settings-header-item',activeTab === '2' ?  'active-item' : '']" @click="onTabChange('2')">{{ $t('settings.setting_title3')}}</span> -->
-        </div>
+  <div class="settings-container">
+    <div class="settings-header">
+      <span :class="['settings-header-item',activeTab === '1' ?  'active-item' : '']" @click="onTabChange('1')">{{ $t('settings.setting_title1')}}</span>
+      <span :class="['settings-header-item',activeTab === '0' ?  'active-item' : '']" @click="onTabChange('0')">{{ $t('settings.setting_title2')}}</span>
+      <!-- <span :class="['settings-header-item',activeTab === '2' ?  'active-item' : '']" @click="onTabChange('2')">{{ $t('settings.setting_title3')}}</span> -->
+    </div>
 
-        <div class="settings-body">
-            <div class="normal-settings animated fadeIn" v-if="activeTab === '0'">
-                <div class="normal-settings-item">
-                    <span class="item-title">{{ $t('settings.langSetting')}}</span>
-                    <span class="item-description">{{ $t('settings.langTips')}}</span>
-                    <span class="item-content light-iview-select">
-                        <Select v-model="cloudSetting.curLang" style="width:200px" @on-change="onSelectLang">
-                            <Option value="zh-cn">中文(简体)</Option>
-                            <Option value="zh-tw">中文(繁體)</Option>
-                            <Option value="en-us">English</Option>
-                        </Select>
-                        <Checkbox v-model="cloudSetting.isSystemLang" @on-change="onMenuStatusChange">{{ $t('settings.langCheck')}}</Checkbox>
-                    </span>
-                </div>
-                <!-- <div class="normal-settings-item">
+    <div class="settings-body">
+      <div class="normal-settings animated fadeIn" v-if="activeTab === '0'">
+        <div class="normal-settings-item">
+          <span class="item-title">{{ $t('settings.langSetting')}}</span>
+          <span class="item-description">{{ $t('settings.langTips')}}</span>
+          <span class="item-content light-iview-select">
+            <Select v-model="cloudSetting.curLang" style="width:200px" @on-change="onSelectLang">
+              <Option value="zh-cn">中文(简体)</Option>
+              <Option value="zh-tw">中文(繁體)</Option>
+              <Option value="en-us">English</Option>
+            </Select>
+            <Checkbox v-model="cloudSetting.isSystemLang" @on-change="onMenuStatusChange">{{ $t('settings.langCheck')}}</Checkbox>
+          </span>
+        </div>
+        <!-- <div class="normal-settings-item">
                     <span class="item-title">{{ $t('settings.themeSetting')}}</span>
                     <span class="item-description">{{ $t('settings.themeTips')}}</span>
                     <span class="item-content">
@@ -28,36 +28,36 @@
                         <span :class="['color-item',cloudSetting.curTheme === 'light' ?  'color-item-active' : '']" @click="onTips('light')"></span>
                     </span>
                 </div> -->
-                <div class="normal-settings-item">
-                    <span class="item-title">{{ $t('settings.menuSetting')}}</span>
-                    <span class="item-description">{{ $t('settings.menuTips')}}</span>
-                    <span class="item-content">
-                        <RadioGroup v-model="cloudSetting.menuStatus" @on-change="onMenuStatusChange">
-                            <Radio label="open">{{ $t('settings.menuOpen')}}</Radio>
-                            <Radio label="close">{{ $t('settings.menuClose')}}</Radio>
-                        </RadioGroup>
-                    </span>
-                </div>
-                <div class="normal-settings-item">
-                    <span class="item-title">{{ $t('settings.logoSetting')}}</span>
-                    <span class="item-description">{{ $t('settings.logoTips')}}</span>
-                    <span class="item-content">
-                        <RadioGroup v-model="cloudSetting.logoStatus" @on-change="onLogoStatusChange">
-                            <Radio label="open">{{ $t('settings.logoOpen')}}</Radio>
-                            <Radio label="close">{{ $t('settings.logoHide')}}</Radio>
-                        </RadioGroup>
-                    </span>
-                </div>
-                <div class="normal-settings-item">
-                    <!-- <Button @click="saveSetting">保存变更</Button> -->
-                </div>
-            </div>
-            <SchoolMgmt v-if="activeTab === '1'" class="animated fadeIn"></SchoolMgmt>
-            <!-- <OpenMgmt v-if="activeTab === '2'" class="animated fadeIn"></OpenMgmt> -->
-            <!-- 换成独立菜单了 -->
-            <!-- <OpenMgmt2 v-if="activeTab === '2'" class="animated fadeIn"></OpenMgmt2> -->
+        <div class="normal-settings-item">
+          <span class="item-title">{{ $t('settings.menuSetting')}}</span>
+          <span class="item-description">{{ $t('settings.menuTips')}}</span>
+          <span class="item-content">
+            <RadioGroup v-model="cloudSetting.menuStatus" @on-change="onMenuStatusChange">
+              <Radio label="open">{{ $t('settings.menuOpen')}}</Radio>
+              <Radio label="close">{{ $t('settings.menuClose')}}</Radio>
+            </RadioGroup>
+          </span>
+        </div>
+        <div class="normal-settings-item">
+          <span class="item-title">{{ $t('settings.logoSetting')}}</span>
+          <span class="item-description">{{ $t('settings.logoTips')}}</span>
+          <span class="item-content">
+            <RadioGroup v-model="cloudSetting.logoStatus" @on-change="onLogoStatusChange">
+              <Radio label="open">{{ $t('settings.logoOpen')}}</Radio>
+              <Radio label="close">{{ $t('settings.logoHide')}}</Radio>
+            </RadioGroup>
+          </span>
         </div>
+        <div class="normal-settings-item">
+          <!-- <Button @click="saveSetting">保存变更</Button> -->
+        </div>
+      </div>
+      <SchoolMgmt v-if="activeTab === '1'" class="animated fadeIn"></SchoolMgmt>
+      <!-- <OpenMgmt v-if="activeTab === '2'" class="animated fadeIn"></OpenMgmt> -->
+      <!-- 换成独立菜单了 -->
+      <!-- <OpenMgmt2 v-if="activeTab === '2'" class="animated fadeIn"></OpenMgmt2> -->
     </div>
+  </div>
 </template>
 
 <script>
@@ -66,121 +66,122 @@ import SchoolMgmt from './SchoolMgmt.vue'
 import OpenMgmt from './OpenMgmt.vue'
 // import OpenMgmt2 from './OpenMgmt2.vue';
 export default {
-    components: {
-        SchoolMgmt,
-        OpenMgmt,
-        // OpenMgmt2
-    },
-    data() {
-        return {
-            activeTab: '1',
-            activeTheme: '0',
-            menuStatus: 'open',
-            curLang: 'zh-cn',
-            isHomeworkLang: true,
-            cloudSetting: {
-                curLang: localStorage.getItem('local'),
-                curTheme: 'dark',
-                isSystemLang: true,
-                menuStatus: 'open',
-                logoStatus: 'open'
-            }
-        }
-    },
-    created() {
-        if (localStorage.getItem('cloudSetting')) {
-            this.cloudSetting = JSON.parse(localStorage.getItem('cloudSetting'))
-        }
-		
-    },
-    methods: {
-
-        onSelectLang(val) {
-            localStorage.setItem('cloudSetting', JSON.stringify(this.cloudSetting))
-            this.$store.commit("setLanguage", val);
-        },
+  components: {
+    SchoolMgmt,
+    OpenMgmt,
+    // OpenMgmt2
+  },
+  data() {
+    return {
+      activeTab: '1',
+      activeTheme: '0',
+      menuStatus: 'open',
+      curLang: 'zh-cn',
+      isHomeworkLang: true,
+      cloudSetting: {
+        curLang: localStorage.getItem('local'),
+        curTheme: 'dark',
+        isSystemLang: true,
+        menuStatus: 'open',
+        logoStatus: 'open'
+      }
+    }
+  },
+  created() {
+    if (localStorage.getItem('cloudSetting')) {
+      this.cloudSetting = JSON.parse(localStorage.getItem('cloudSetting'))
+    }
 
-        onMenuStatusChange(val) {
-            localStorage.setItem('cloudSetting', JSON.stringify(this.cloudSetting))
-        },
+  },
+  methods: {
 
-        onLogoStatusChange(val) {
-            localStorage.setItem('cloudSetting', JSON.stringify(this.cloudSetting))
-            this.$EventBus.$emit('onLogoStatusChange', val)
-        },
+    onSelectLang(val) {
+      localStorage.setItem('cloudSetting', JSON.stringify(this.cloudSetting))
+      this.$tools.changeLang(val)
+      this.$store.commit("setLanguage", val);
+    },
 
-        /* 一般设置与学校管理切换 */
-        onTabChange(index) {
-            this.activeTab = index
-        },
+    onMenuStatusChange(val) {
+      localStorage.setItem('cloudSetting', JSON.stringify(this.cloudSetting))
+    },
 
-        /* 主题切换 */
-        onThemeChange(index) {
-            this.cloudSetting.curTheme = index
-            //this.$less.modifyVars({  // 调用 `less.modifyVars` 方法来改变变量值'
-            //    '@border-color': '#000',
-            //    '@header-bg': 'white',
-            //})
-            //    .then(() => {
-            //        console.log('修改成功');
-            //    });
-            localStorage.setItem('cloudSetting', JSON.stringify(this.cloudSetting))
-            if (index == 'dark') {
-                let url = '/theme/dark-theme.css'
-                var link = document.getElementById('theme') ? document.getElementById('theme') : document.createElement('link');
-                if (document.getElementById('theme')) {
-                    link.href = url;
-                } else {
-                    var head = document.getElementsByTagName('head')[0];
-                    link.type = 'text/css';
-                    link.rel = 'stylesheet';
-                    link.id = 'theme';
-                    link.href = url;
-                    head.appendChild(link);
-                }
-            } else {
-                let url = '/theme/light-theme.css'
-                var link = document.getElementById('theme') ? document.getElementById('theme') : document.createElement('link');
-                if (document.getElementById('theme')) {
-                    link.href = url;
-                } else {
-                    var head = document.getElementsByTagName('head')[0];
-                    link.type = 'text/css';
-                    link.rel = 'stylesheet';
-                    link.id = 'theme';
-                    link.href = url;
-                    head.appendChild(link);
-                }
-            }
-        },
+    onLogoStatusChange(val) {
+      localStorage.setItem('cloudSetting', JSON.stringify(this.cloudSetting))
+      this.$EventBus.$emit('onLogoStatusChange', val)
+    },
 
-        onTips() {
-            this.$Message.warning('换肤功能即将上线')
-        },
+    /* 一般设置与学校管理切换 */
+    onTabChange(index) {
+      this.activeTab = index
+    },
 
-        /* 保存设置 */
-        saveSetting() {
-            this.$Modal.confirm({
-                title: '提示',
-                content: '设置保存成功,刷新后即可生效,是否前往?',
-                onOk: () => {
-                    localStorage.setItem('cloudSetting', JSON.stringify(this.cloudSetting))
-                    location.reload()
-                }
-            })
+    /* 主题切换 */
+    onThemeChange(index) {
+      this.cloudSetting.curTheme = index
+      //this.$less.modifyVars({  // 调用 `less.modifyVars` 方法来改变变量值'
+      //    '@border-color': '#000',
+      //    '@header-bg': 'white',
+      //})
+      //    .then(() => {
+      //        console.log('修改成功');
+      //    });
+      localStorage.setItem('cloudSetting', JSON.stringify(this.cloudSetting))
+      if (index == 'dark') {
+        let url = '/theme/dark-theme.css'
+        var link = document.getElementById('theme') ? document.getElementById('theme') : document.createElement('link');
+        if (document.getElementById('theme')) {
+          link.href = url;
+        } else {
+          var head = document.getElementsByTagName('head')[0];
+          link.type = 'text/css';
+          link.rel = 'stylesheet';
+          link.id = 'theme';
+          link.href = url;
+          head.appendChild(link);
         }
-    },
-    watch: {
-        $route: {
-            handler: function (val, oldVal) {
-                let routeData = this.$route.query
-                this.activeTab = routeData.tab || this.activeTab
-            },
-            // 深度观察监听
-            deep: true,
-            immediate: true
+      } else {
+        let url = '/theme/light-theme.css'
+        var link = document.getElementById('theme') ? document.getElementById('theme') : document.createElement('link');
+        if (document.getElementById('theme')) {
+          link.href = url;
+        } else {
+          var head = document.getElementsByTagName('head')[0];
+          link.type = 'text/css';
+          link.rel = 'stylesheet';
+          link.id = 'theme';
+          link.href = url;
+          head.appendChild(link);
         }
+      }
     },
+
+    onTips() {
+      this.$Message.warning('换肤功能即将上线')
+    },
+
+    /* 保存设置 */
+    saveSetting() {
+      this.$Modal.confirm({
+        title: '提示',
+        content: '设置保存成功,刷新后即可生效,是否前往?',
+        onOk: () => {
+          localStorage.setItem('cloudSetting', JSON.stringify(this.cloudSetting))
+          location.reload()
+        }
+      })
+    }
+  },
+  watch: {
+    $route: {
+      handler: function (val, oldVal) {
+        let routeData = this.$route.query
+        this.activeTab = routeData.tab || this.activeTab
+      },
+      // 深度观察监听
+      deep: true,
+      immediate: true
+    }
+  },
 }
 </script>
 
@@ -190,85 +191,85 @@ export default {
 
 <style lang="less">
 .settings-container {
-    .ivu-select-selection {
-        /* background: transparent;
+  .ivu-select-selection {
+    /* background: transparent;
         border-color: #363738;
         color: #a6a6a6; */
-    }
+  }
 
-    .ivu-checkbox-wrapper {
-        margin-left: 40px;
-        margin-top: 5px;
-        // color: #a6a6a6;
-    }
+  .ivu-checkbox-wrapper {
+    margin-left: 40px;
+    margin-top: 5px;
+    // color: #a6a6a6;
+  }
 
-    .ivu-checkbox {
-        margin-right: 5px;
-    }
+  .ivu-checkbox {
+    margin-right: 5px;
+  }
 
-    .ivu-radio-wrapper {
-        margin-right: 20px;
-        // color: #a5a5a5;
-    }
+  .ivu-radio-wrapper {
+    margin-right: 20px;
+    // color: #a5a5a5;
+  }
 
-    .ivu-radio-inner {
-        width: 18px;
-        height: 18px;
-        border-radius: 4px;
-        /* background-color: #0f0f0f;
+  .ivu-radio-inner {
+    width: 18px;
+    height: 18px;
+    border-radius: 4px;
+    /* background-color: #0f0f0f;
         border-color: #4d4d4d; */
-        border-width: 1px;
-        margin-right: 5px;
-        &::after {
-            content: "";
-            display: block;
-            width: 10px;
-            height: 16px;
-            border-right: #ffffff solid 3px;
-            border-bottom: #ffffff solid 3px;
-            transform: rotate(35deg);
-            position: absolute;
-            top: -4px;
-            left: 4px;
-            border-radius: 0;
-            background-color: transparent;
-            border-color: #0094ff;
-        }
+    border-width: 1px;
+    margin-right: 5px;
+    &::after {
+      content: "";
+      display: block;
+      width: 10px;
+      height: 16px;
+      border-right: #ffffff solid 3px;
+      border-bottom: #ffffff solid 3px;
+      transform: rotate(35deg);
+      position: absolute;
+      top: -4px;
+      left: 4px;
+      border-radius: 0;
+      background-color: transparent;
+      border-color: #0094ff;
     }
+  }
 
-    .ivu-checkbox-inner {
-        width: 18px;
-        height: 18px;
-        border-radius: 4px;
-        /* background-color: #0f0f0f;
+  .ivu-checkbox-inner {
+    width: 18px;
+    height: 18px;
+    border-radius: 4px;
+    /* background-color: #0f0f0f;
         border-color: #4d4d4d; */
-        border-width: 1px;
-        margin-right: 5px;
-    }
+    border-width: 1px;
+    margin-right: 5px;
+  }
 
-    .ivu-checkbox-checked .ivu-checkbox-inner {
-        width: 18px;
-        height: 18px;
-        border-radius: 4px;
-        background-color: #FFF;
-        /* border-color: #4d4d4d; */
-        border-width: 1px;
-        margin-right: 5px;
-        &::after {
-            content: "";
-            display: block;
-            width: 10px;
-            height: 16px;
-            border-right: #ffffff solid 3px;
-            border-bottom: #ffffff solid 3px;
-            transform: rotate(35deg);
-            position: absolute;
-            top: -4px;
-            left: 4px;
-            border-radius: 0;
-            background-color: transparent;
-            border-color: #0094ff;
-        }
+  .ivu-checkbox-checked .ivu-checkbox-inner {
+    width: 18px;
+    height: 18px;
+    border-radius: 4px;
+    background-color: #fff;
+    /* border-color: #4d4d4d; */
+    border-width: 1px;
+    margin-right: 5px;
+    &::after {
+      content: "";
+      display: block;
+      width: 10px;
+      height: 16px;
+      border-right: #ffffff solid 3px;
+      border-bottom: #ffffff solid 3px;
+      transform: rotate(35deg);
+      position: absolute;
+      top: -4px;
+      left: 4px;
+      border-radius: 0;
+      background-color: transparent;
+      border-color: #0094ff;
     }
+  }
 }
 </style>

+ 2 - 1
TEAMModelOS/ClientApp/src/view/student-analysis/total-analysis/EvaluationList/TotalIndex.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="index-container">
     <Loading v-show="isLoadingList"></Loading>
-    <Scroll :on-reach-bottom="handleReachBottom" height="880" :distance-to-edge="[0,0]">
+    <Scroll :on-reach-bottom="handleReachBottom" :height="scrollHeight" :distance-to-edge="[0,0]">
       <div class="section" id="analysisList">
         <!-- 评测列表数据部分 -->
         <div class="section exam-list-wrap">
@@ -155,6 +155,7 @@ export default {
   },
   data(vm) {
     return {
+      scrollHeight:document.documentElement.clientHeight * 0.95,
       filterResultCount: 0,
       typeCountArr: [],
       latestYear: null,

+ 15 - 8
TEAMModelOS/ClientApp/src/view/user/BandPhone.vue

@@ -189,20 +189,27 @@ export default {
                         this.$Message.error(this.$t('login.codeerr'))
                         return
                     }
+                    //20220509调整:已有账号和新建账号都只传手机,由后端通过手机获取token进行绑定
                     //已有账号直接绑定,通过bind进行隐式登录
-                    else if (res.error === 2) {
+                    else if (res.error === 2 || res.id_token) {
                         data = {
                             phone: this.accFormat
                         }
+                        this.bandingID(data)
+                    }else{
+                        this.$Message.error(this.$t('login.phoneerr'))
                     }
                     // 新账号会返回登录信息
-                    else if (res.id_token) {
-                        data = {
-                            id_token: res.id_token,
-                            loginData: res
-                        }
-                    }
-                    this.bandingID(data)
+                    // else if (res.id_token) {
+                    //     // data = {
+                    //     //     id_token: res.id_token,
+                    //     //     loginData: res
+                    //     // }
+                    //     data = {
+                    //         phone: this.accFormat
+                    //     }
+                    // }
+                    // this.bandingID(data)
                 },
                 err => {
                     this.$Message.error(this.$t('login.phoneerr'))

+ 3 - 3
TEAMModelOS/Controllers/Both/PaperController.cs

@@ -98,7 +98,7 @@ namespace TEAMModelOS.Controllers
             var id = jwt.Payload.Sub;
             var client = _azureCosmos.GetCosmosClient();
             List<object> papers = new List<object>();
-            var query = $"select c.id,c.subjectCode,c.code,c.periodCode,c.name,c.itemCount,c.level,c.pointItem,c.pointScore,c.score,c.gradeCode,c.createTime,c.sheet,c.sheetNo,c.tags from c where c.id = {id}";
+            var query = $"select c.id,c.subjectCode,c.code,c.periodCode,c.name,c.itemCount,c.level,c.pointItem,c.pointScore,c.score,c.gradeCode,c.createTime,c.sheet,c.sheetNo,c.tags ,c.mode from c where c.id = {id}";
             await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIterator(queryText: query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Paper-{school_code}") }))
             {
                 using var json = await JsonDocument.ParseAsync(item.ContentStream);
@@ -157,7 +157,7 @@ namespace TEAMModelOS.Controllers
             
             if (scope.ToString().Equals("school"))
             {
-                sql.Append("select  c.id,c.code,c.name,c.blob,c.periodId,c.gradeIds,c.subjectId,c.subjectName,c.score,c.useCount,c.scope,c.scoring,c.createTime,c.sheet ,c.sheetNo, c.tags from c");
+                sql.Append("select  c.id,c.code,c.name,c.blob,c.periodId,c.gradeIds,c.subjectId,c.subjectName,c.score,c.useCount,c.scope,c.scoring,c.createTime,c.sheet ,c.mode ,c.sheetNo, c.tags from c");
                 AzureCosmosQuery cosmosDbQuery = SQLHelper.GetSQL(dict, sql);
                 await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<Paper>(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Paper-{code}") }))
                 {
@@ -175,7 +175,7 @@ namespace TEAMModelOS.Controllers
             }
             if (scope.ToString().Equals("private"))
             {
-                sql.Append("select c.id,c.code,c.name,c.blob,c.subjectName,c.score,c.useCount,c.scope,c.scoring ,c.createTime ,c.sheet,c.sheetNo , c.tags from c");
+                sql.Append("select c.id,c.code,c.name,c.blob,c.subjectName,c.score,c.useCount,c.scope,c.scoring ,c.createTime ,c.sheet,c.sheetNo ,c.mode , c.tags from c");
                 AzureCosmosQuery cosmosDbQuery = SQLHelper.GetSQL(dict, sql);
                 await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIterator<Paper>(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Paper-{code}") }))
                 {

+ 2 - 0
TEAMModelOS/Controllers/Both/SheetConfigController.cs

@@ -198,8 +198,10 @@ namespace TEAMModelOS.Controllers.Common
                         if (string.IsNullOrEmpty(sheet.no)) {
                             sheet.no = await SheetService.genSheetNo(client, _dingDing, _option, sheet.code, tbname, sheet.from);
                             paper.sheetNo = sheet.no;
+                            paper.mode = sheet.mode;
                         }
                         paper.sheetNo = sheet.no;
+                        paper.mode = sheet.mode;
                         paper = await client.GetContainer(Constant.TEAMModelOS, tbname).ReplaceItemAsync<Paper>(paper, $"{_paperId}", new PartitionKey($"{code}"));
 
                     }

+ 4 - 0
TEAMModelOS/Controllers/School/SchoolSettingController.cs

@@ -139,6 +139,10 @@ namespace TEAMModelOS.Controllers
                     HashSet <string> lessonTag = _lessonTag.ToObject<HashSet<string>>();
                     setting.lessonTag = lessonTag;
                     break;
+                case bool when $"{_opt}".Equals("UpsertLessonSetting", StringComparison.OrdinalIgnoreCase) && (json.TryGetProperty("lessonSetting", out JsonElement _lessonSetting)):
+                    LessonSetting lessonSetting = _lessonSetting.ToObject<LessonSetting>();
+                    setting.lessonSetting = lessonSetting;
+                    break;
                 default: break;
             }
             await client.GetContainer(Constant.TEAMModelOS, "School").UpsertItemAsync<SchoolSetting>(setting, partitionKey: new Azure.Cosmos.PartitionKey("SchoolSetting"));

+ 66 - 7
TEAMModelOS/Controllers/Student/StudentCommonController.cs

@@ -62,8 +62,8 @@ namespace TEAMModelOS.Controllers
 
         [ProducesDefaultResponseType]
         [HttpPost("stu-score")]
-/*        [Authorize(Roles = "IES")]
-        [AuthToken(Roles = "teacher,student,admin")]*/
+        /*        [Authorize(Roles = "IES")]
+                [AuthToken(Roles = "teacher,student,admin")]*/
         public async Task<IActionResult> StuScore(JsonElement request)
         {
             var (id, name, pic, school) = HttpContext.GetAuthTokenInfo();
@@ -75,11 +75,56 @@ namespace TEAMModelOS.Controllers
             {
                 eIds.Add((data.id, data.scope, data.name, data.source, data.classIds, data.qamode, data.creatorId, data.ext, data.createTime, data.owner));
             }
-            if (eIds.Count() == 0) {
+            if (eIds.Count == 0)
+            {
                 return Ok(new { code = 404, msg = "暂无数据" });
             }
             var client = _azureCosmos.GetCosmosClient();
-            List<(string eId, string sub, string cId, string cname, List<string> sIds, List<double> sum)> classResults = await getExamClassResult(eIds, client);
+            List<(string eId, string sub, string cId, string cname, List<string> sIds, List<double> sum)> classResults = await getExamClassResult(eIds, client);           
+            List<(string id, double ps)> points = new();
+            await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryStreamIterator(
+                queryText: $"select A0.point,c.id from c join A0 in c.papers where c.id in ({string.Join(",", eIds.Select(o => $"'{o.id}'"))})"))
+            {
+                using var json = await JsonDocument.ParseAsync(item.ContentStream);
+                if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
+                {
+                    var accounts = json.RootElement.GetProperty("Documents").EnumerateArray();
+                    while (accounts.MoveNext())
+                    {
+                        JsonElement account = accounts.Current;
+                        List<double> ps = new();
+                        if (account.TryGetProperty("point", out JsonElement point))
+                        {
+                            ps = point.ToObject<List<double>>();
+                        }
+                        points.Add((account.GetProperty("id").GetString(), ps.Sum()));
+                    }
+                }
+            }
+
+            List<(string id, List<ExamSubject> sub)> subs = new();
+            await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryStreamIterator(
+                queryText: $"select c.subjects,c.id from c where c.id in ({string.Join(",", eIds.Select(o => $"'{o.id}'"))})"))
+            {
+                using var json = await JsonDocument.ParseAsync(item.ContentStream);
+                if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
+                {
+                    var accounts = json.RootElement.GetProperty("Documents").EnumerateArray();
+                    while (accounts.MoveNext())
+                    {
+                        JsonElement account = accounts.Current;
+                        List<ExamSubject> sj = new();
+                        if (account.TryGetProperty("subjects", out JsonElement sn))
+                        {
+                            sj = sn.ToObject<List<ExamSubject>>();
+                        }
+                        subs.Add((account.GetProperty("id").GetString(), sj));
+                    }
+                }
+            }
+            var pst = points.GroupBy(x => x.id).Select(p => new { key = p.Key, po = p.Select(o => o.ps) });
+            var sut = subs.GroupBy(x => x.id).Select(p => new { key = p.Key, po = p.Select(o => o.sub) });
+
             var exam = eIds.Select(e => new
             {
                 e.id,
@@ -91,10 +136,25 @@ namespace TEAMModelOS.Controllers
                 e.ext,
                 e.time,
                 e.owner,
+                point = pst.Where(s =>s.key == e.id).Select(c => c.po),
+                subject = subs.Where(s => s.id == e.id).FirstOrDefault().sub,
                 result = classResults.Where(c => c.eId == e.id).Select(s => new { s.sub, s.cId, s.cname, s.sum, s.sIds })
             });
-            var result = exam.Where(e => e.result.Any());
-            return Ok(new { result, continuationToken });
+            var result = exam.Where(e => e.result.Any()).Select(s => new { 
+                s.id,
+                s.name,
+                s.scope,
+                s.source,
+                s.createId,
+                s.qamode,
+                s.ext,
+                s.time,                   
+                s.owner,
+                point = s.point.FirstOrDefault(),
+                s.subject,
+                s.result
+            });
+            return Ok(new { result, continuationToken});
         }
 
         [ProducesDefaultResponseType]
@@ -291,7 +351,6 @@ namespace TEAMModelOS.Controllers
                     }
                 }
             }
-
             return classResults;
         }
         /// <summary>

+ 30 - 16
TEAMModelOS/Controllers/Third/Sc/ScController.cs

@@ -170,7 +170,7 @@ namespace TEAMModelOS.Controllers
 
             foreach (var teacher in teachers)
             {
-                var a = teacher.binds.SelectMany(y => y.data).ToList().Find(x => !string.IsNullOrEmpty(x));
+                var a = teacher.binds.SelectMany(y => y.data).ToList().Find(x => !string.IsNullOrWhiteSpace(x));
                 if (a != null)
                 {
                     await _azureStorage.UploadFileByContainer("teammodelos", a, $"yxpt/scpjx/scbind", $"{teacher.id}.json");
@@ -183,7 +183,7 @@ namespace TEAMModelOS.Controllers
                 {
                     foreach (var school in teacher.schools)
                     {
-                        if (!string.IsNullOrEmpty(school.schoolId))
+                        if (!string.IsNullOrWhiteSpace(school.schoolId))
                         {
 
                             if (school.status.Equals("join"))
@@ -276,7 +276,7 @@ namespace TEAMModelOS.Controllers
             {
                 Teacher teacher = null;
                 TmdidImplicit tmdidImplicit = null;
-                if (string.IsNullOrEmpty(sso.id_token) && !string.IsNullOrEmpty(sso.mobile))
+                if (!string.IsNullOrWhiteSpace(sso.mobile))
                 {
                     var coreUser = await _coreAPIHttpService.GetUserInfo(new Dictionary<string, string> { { "key", sso.mobile } }, _option.Location, _configuration);
                     if (coreUser != null)
@@ -286,13 +286,28 @@ namespace TEAMModelOS.Controllers
                                         { "client_id",clientID },
                                         { "account",coreUser.id },
                                         { "nonce",Guid.NewGuid().ToString()} }, _option.Location, _configuration);
-                        if (tmdidImplicit != null && !string.IsNullOrEmpty(tmdidImplicit.id_token))
+                        if (tmdidImplicit != null && !string.IsNullOrWhiteSpace(tmdidImplicit.id_token))
                         {
                             sso.id_token = tmdidImplicit.id_token;
                         }
+                        else
+                        {
+                            return Ok(new
+                            {
+                                location = _option.Location,
+                                status = 2,
+                            });
+                        }
+                    }
+                    else {
+                        return Ok(new
+                        {
+                            location = _option.Location,
+                            status = 2,
+                        });
                     }
                 }
-                if (string.IsNullOrEmpty(sso.id_token))
+                if (string.IsNullOrWhiteSpace(sso.id_token))
                 {
                     return Ok(new
                     {
@@ -398,7 +413,7 @@ namespace TEAMModelOS.Controllers
                         }
                     }
                 }
-                catch (CosmosException ex)
+                catch (CosmosException ex) when (ex.Status ==404)
                 {
                     teacher = new Teacher
                     {
@@ -416,7 +431,6 @@ namespace TEAMModelOS.Controllers
                     };
                     var container = _azureStorage.GetBlobContainerClient(id);
                     await container.CreateIfNotExistsAsync(PublicAccessType.None); //嘗試創建Teacher私有容器,如存在則不做任何事,保障容器一定存在
-
                     teacher = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Teacher").CreateItemAsync<Teacher>(teacher, new PartitionKey("Base"));
 
                     ScBindData bindData = scsso.data.ToObject<ScBindData>();
@@ -524,7 +538,7 @@ namespace TEAMModelOS.Controllers
                     setting = item;
                     break;
                 }
-                if (setting == null || (setting != null && string.IsNullOrEmpty(setting.accessConfig)))
+                if (setting == null || (setting != null && string.IsNullOrWhiteSpace(setting.accessConfig)))
                 {
                     return Redirect(rurl.Append($"?status=1").ToString());
                 }
@@ -544,7 +558,7 @@ namespace TEAMModelOS.Controllers
                         Account = $"{ scTeacher.Account}";
                     }
                 }
-                if (string.IsNullOrEmpty(SchoolID))
+                if (string.IsNullOrWhiteSpace(SchoolID))
                 {
                     (int status, string json) = await _httpTrigger.RequestHttpTrigger(dict, _option.Location, "GetSingleTeacherByProject");
                     if (status == 200)
@@ -620,7 +634,7 @@ namespace TEAMModelOS.Controllers
                         }, location, _configuration);
                     if (implicit_token != null)
                     {
-                        if (string.IsNullOrEmpty(implicit_token.id_token))
+                        if (string.IsNullOrWhiteSpace(implicit_token.id_token))
                         {
                             await _dingDing.SendBotMsg($"OS,隐式登录获得信息为空:{_option.Location}-\n{scsso.ToJsonString()} \npath:{path}\n{implicit_token.ToJsonString()}", GroupNames.醍摩豆服務運維群組);
                             return Redirect(rurl.Append($"?status=1").ToString());
@@ -664,12 +678,12 @@ namespace TEAMModelOS.Controllers
                     else
                     {
                         //绑定失效
-                        if (teacher.binds.IsNotEmpty())
-                        {
-                            teacher.binds.RemoveAll(x => x.userid.Equals(sso.tid));
-                            await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<Teacher>(teacher, teacher.id, new PartitionKey(teacher.code));
-                        }
-                        string enurl = $"status=4&param={HttpUtility.UrlEncode(sso.ToJsonString(), Encoding.UTF8)}&type={type}&bindurl=sc/bind";
+                        //if (teacher.binds.IsNotEmpty())
+                        //{
+                        //    teacher.binds.RemoveAll(x => x.userid.Equals(sso.tid));
+                        //    await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<Teacher>(teacher, teacher.id, new PartitionKey(teacher.code));
+                        //}
+                        //string enurl = $"status=4&param={HttpUtility.UrlEncode(sso.ToJsonString(), Encoding.UTF8)}&type={type}&bindurl=sc/bind";
                         // return Redirect(rurl.Append($"?{enurl}").ToString());
                         return Redirect(rurl.Append($"?status=1").ToString());
                     }

+ 18 - 2
TEAMModelOS/Controllers/Third/Xkw/XkwOAuth2Controller.cs

@@ -186,8 +186,8 @@ namespace TEAMModelOS.Controllers
                     Type = "xkw"
                 };
                 await table.SaveOrUpdate<OAuthUser>(authUser);
-                return Ok(new { status = 1, url=client.SERVICE_URL});
-                //return Redirect($"bind?status=1&accessToken={client.AccessToken}&openId={client.OpenId}&userId={client.UserId}&domain={domain}&msg={HttpUtility.UrlEncode("认证成功")}");
+                //return Ok(new { status = 1, url=client.SERVICE_URL});
+                return Redirect(client.SERVICE_URL);
             }
             else
             {
@@ -282,6 +282,22 @@ namespace TEAMModelOS.Controllers
                 string OAuth_Xkw_RedirectUrl = configs[0].RedirectUrl;
                 string OAuth_Xkw_OAuthHost = configs[0].OAuthHost;
                 string OAuth_Xkw_ServiceUrl = configs[0].ServiceUrl;
+                try {
+                    List<ServiceModule> services= configs[0].ServiceUrl.ToObject<List<ServiceModule>>();
+                    ServiceModule serviceModule= services.Find(x => x.module.Equals(module));
+                    if (serviceModule != null)
+                    {
+                        OAuth_Xkw_ServiceUrl = serviceModule.url;
+                    }
+                    else {
+                        OAuth_Xkw_ServiceUrl = "http://www.zxxk.com/";
+                    }
+                } catch (Exception ex) {
+                    if (!OAuth_Xkw_ServiceUrl.StartsWith("http://www.zxxk.com"))
+                    {
+                        OAuth_Xkw_ServiceUrl = "http://www.zxxk.com/";
+                    }
+                }
                 string OAuth_Xkw_Domain= configs[0].Domain;
                 string OAuth_Xkw_Param =$"tmdid={tmdid}&module={module}&state={Guid.NewGuid().ToString()}";
                 var client = new XkwOAuthClient(OAuth_Xkw_AppKey, OAuth_Xkw_AppSecret, OAuth_Xkw_RedirectUrl, OAuth_Xkw_OAuthHost, OAuth_Xkw_Domain, accessToken, openId, userId, OAuth_Xkw_Param);

+ 32 - 15
TEAMModelOS/Controllers/XTest/FixDataController.cs

@@ -2066,24 +2066,41 @@ namespace TEAMModelOS.Controllers
                await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReplaceItemAsync<School>(item, item.id, new PartitionKey(item.code));
             }
             return Ok(schoolsSet);
-        }    /// <summary>
-             /// 修复学校课例及blob计算
-             /// </summary>
-             /// <param name="jsonElement"></param>
-             /// <returns></returns>
-        [HttpPost("fix-teacher-private-lesson-record")]
+        }    
+
+        [HttpPost("fix-teacher-train-nickname")]
         public async Task<IActionResult> FixTeacherPrivateLessonRecord(JsonElement json)
         {
-            var client = _azureCosmos.GetCosmosClient();
-            string sql = " SELECT distinct value(c)  FROM c  where c.pk='LessonRecord'  ";
-            List<LessonRecord> lessonRecords = new List<LessonRecord>();
-            await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).GetItemQueryIterator<LessonRecord>(queryText: sql, requestOptions: new QueryRequestOptions {}))
-            {
-                item.code = "LessonRecord";
-                await  _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).UpsertItemAsync(item,new PartitionKey (item.code));
-                lessonRecords.Add(item);
+            var table = _azureStorage.GetCloudTableClient().GetTableReference("ScYxpt");
+            List<ScTeacher> scTeachers=  await table.FindListByDict<ScTeacher>(new Dictionary<string, object> { { "PartitionKey", "ScTeacher" } });
+            scTeachers=scTeachers.FindAll(x =>!string.IsNullOrWhiteSpace(x.tmdid) &&! string.IsNullOrWhiteSpace(x.schoolCode));
+            var groups= scTeachers.GroupBy(x => x.schoolCode).Select(x => new { key = x.Key, list = x.ToList() });
+            foreach (var item in groups) {
+                List<TeacherTrain> teacherTrains = new List<TeacherTrain>();
+                string sql = $" select value(c) from c where c.id in ({string.Join(",",item.list.Select(x=>$"'{x.tmdid}'"))})  ";
+                await foreach (var tr in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).GetItemQueryIterator<TeacherTrain>(queryText: sql,
+                    requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"TeacherTrain-{item.key}") }))
+                {
+                    teacherTrains.Add(tr);
+                }
+                List<Task<ItemResponse<TeacherTrain>>> update = new List<Task<ItemResponse<TeacherTrain>>>();
+                teacherTrains.ForEach(x => {
+                   var sc= scTeachers.Find(s => s.tmdid.Equals(x.id));
+                    if (sc != null ) {
+                        if (string.IsNullOrWhiteSpace(x.nickname))
+                        {
+                            x.nickname = sc.TeacherName;
+                            update.Add(_azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).ReplaceItemAsync(x, x.id, new PartitionKey(x.code)));
+                        }
+                        else if (!sc.TeacherName.Equals(x.nickname)) { 
+                            x.nickname = sc.TeacherName;
+                            update.Add(_azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).ReplaceItemAsync(x, x.id, new PartitionKey(x.code)));
+                        }
+                    }
+                });
+                await Task.WhenAll(update);
             }
-            return Ok(lessonRecords);
+            return Ok( );
         }
 
             /// <summary>