소스 검색

Merge branch 'develop6.0-tmd' of http://52.130.252.100:10000/TEAMMODEL/TEAMModelOS into develop6.0-tmd

zhouj1203@hotmail.com 3 년 전
부모
커밋
eb4be197c3
47개의 변경된 파일1743개의 추가작업 그리고 425개의 파일을 삭제
  1. 1 0
      .gitignore
  2. 1 0
      TEAMModelBI/ClientApp/package.json
  3. 1 1
      TEAMModelBI/ClientApp/public/index.html
  4. 22 0
      TEAMModelBI/ClientApp/src/api/index.js
  5. 8 0
      TEAMModelBI/ClientApp/src/router/index.js
  6. 1 1
      TEAMModelBI/ClientApp/src/until/http.js
  7. 1 1
      TEAMModelBI/ClientApp/src/view/areaServe/statistics.vue
  8. 71 35
      TEAMModelBI/ClientApp/src/view/common/aside.vue
  9. 2 2
      TEAMModelBI/ClientApp/src/view/common/header.vue
  10. 6 6
      TEAMModelBI/ClientApp/src/view/schoolServe/index.vue
  11. 180 0
      TEAMModelBI/ClientApp/src/view/systemConfig/correlation.vue
  12. 56 0
      TEAMModelBI/ClientApp/src/view/systemConfig/index.vue
  13. 155 0
      TEAMModelBI/ClientApp/src/view/systemConfig/operate.vue
  14. 370 0
      TEAMModelBI/ClientApp/src/view/systemConfig/setAdmin.vue
  15. 249 0
      TEAMModelBI/ClientApp/src/view/systemConfig/website.vue
  16. 174 120
      TEAMModelBI/ClientApp/src/view/teachermanage/manage.vue
  17. 7 6
      TEAMModelBI/ClientApp/src/view/teachermanage/reuse.vue
  18. 4 0
      TEAMModelBI/ClientApp/src/view/teachermanage/traitmanage.vue
  19. 71 36
      TEAMModelBI/Controllers/DingDingStruc/TableDingDingInfoController.cs
  20. 53 22
      TEAMModelBI/Controllers/LoginController.cs
  21. 13 0
      TEAMModelBI/Models/MonthStartEnd.cs
  22. 33 0
      TEAMModelBI/Tool/CosmosBank/SchoolWay.cs
  23. 1 1
      TEAMModelOS.FunctionV4/ServiceBus/ActiveTaskTopic.cs
  24. 3 3
      TEAMModelOS.FunctionV4/TEAMModelOS.FunctionV4.csproj
  25. 1 1
      TEAMModelOS.SDK/Models/Cosmos/BI/DingDingUserInfo.cs
  26. 4 0
      TEAMModelOS.SDK/Models/Cosmos/Normal/AreaSetting.cs
  27. 6 6
      TEAMModelOS.SDK/Models/Service/GroupListService.cs
  28. 5 5
      TEAMModelOS/ClientApp/src/locale/lang/en-US/auth.js
  29. 3 3
      TEAMModelOS/ClientApp/src/locale/lang/en-US/cusMgt.js
  30. 2 2
      TEAMModelOS/ClientApp/src/locale/lang/en-US/home.js
  31. 56 56
      TEAMModelOS/ClientApp/src/locale/lang/en-US/learnActivity.js
  32. 7 7
      TEAMModelOS/ClientApp/src/locale/lang/en-US/schoolBaseInfo.js
  33. 1 1
      TEAMModelOS/ClientApp/src/locale/lang/en-US/stuAccount.js
  34. 12 12
      TEAMModelOS/ClientApp/src/locale/lang/en-US/studentWeb.js
  35. 24 24
      TEAMModelOS/ClientApp/src/locale/lang/en-US/task.js
  36. 32 33
      TEAMModelOS/ClientApp/src/locale/lang/en-US/teachermgmt.js
  37. 1 1
      TEAMModelOS/ClientApp/src/locale/lang/en-US/unit.js
  38. 2 2
      TEAMModelOS/ClientApp/src/locale/lang/zh-TW/learnActivity.js
  39. 2 2
      TEAMModelOS/ClientApp/src/locale/lang/zh-TW/schoolBaseInfo.js
  40. 6 6
      TEAMModelOS/ClientApp/src/locale/lang/zh-TW/studentWeb.js
  41. 8 9
      TEAMModelOS/ClientApp/src/locale/lang/zh-TW/teachermgmt.js
  42. 3 3
      TEAMModelOS/ClientApp/src/locale/lang/zh-TW/user.js
  43. 23 5
      TEAMModelOS/ClientApp/src/view/areaSetting/AreaSetting.vue
  44. 16 8
      TEAMModelOS/ClientApp/src/view/assessment/Assessment.vue
  45. 1 1
      TEAMModelOS/Controllers/Both/GroupListController.cs
  46. 42 1
      TEAMModelOS/Controllers/Teacher/FavoriteController.cs
  47. 3 3
      TEAMModelOS/TEAMModelOS.csproj

+ 1 - 0
.gitignore

@@ -265,3 +265,4 @@ _Pvt_Extensions
 TEAMModelOS.FunctionV4/Properties/ServiceDependencies/TEAMModel-Test - Zip Deploy/
 
 TEAMModelOS.FunctionV4/Properties/ServiceDependencies/teammodelfunction-rc - Zip Deploy/
+/TEAMModelOS.FunctionV4/Properties/serviceDependencies.teammodelfunction-rc - Zip Deploy.json

+ 1 - 0
TEAMModelBI/ClientApp/package.json

@@ -10,6 +10,7 @@
     "dependencies": {
         "@azure/storage-blob": "^12.8.0",
         "@element-plus/icons": "0.0.11",
+        "@element-plus/icons-vue": "^1.1.4",
         "@lywzx/vue.access.control": "^1.0.10",
         "axios": "^0.20.0-0",
         "bootstrap": "^4.5.3",

+ 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_98kq2w80bo.js"></script>
+<script src="https://at.alicdn.com/t/font_2934132_d4kwuzrkqwk.js"></script>
 
 <body>
     <noscript>

+ 22 - 0
TEAMModelBI/ClientApp/src/api/index.js

@@ -220,5 +220,27 @@ export default {
     //获取空间使用率和明细
     getEmploySizes(data) {
         return post('/bloblog/get-area', data)
+    },
+
+    //系统配置
+    //站点配置
+    getSystemConfig(data) {
+        return post('/syscfg/get-config', data)
+    },
+    //修改系统配置信息
+    updateSystemconfig(data) {
+        return post('/syscfg/set-config', data)
+    },
+    //搜素人员
+    searchPersonnel(data) {
+        return post('/biservers/get-coreinfo', data)
+    },
+    //移除管理员
+    removeAdmin(data) {
+        return post('/tabledd/set-backend', data)
+    },
+    //添加系统管理员
+    addAdmin(data) {
+        return post('/tabledd/set-tmdadmin', data)
     }
 }

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

@@ -27,6 +27,14 @@ const routes = [{
                 isShow: true,
                 component: () => require.ensure([], (require) => require(`@/view/index/dashboard.vue`))
             },
+            {
+                name: "system",
+                path: "system",
+                permission: "batcharea-read|batcharea-upd|batchschool-read|batchschool-upd",
+                menuName: "",
+                isShow: true,
+                component: () => require.ensure([], (require) => require(`@/view/systemConfig/index.vue`))
+            },
             {
                 name: "peopleManagement",
                 path: "teach",

+ 1 - 1
TEAMModelBI/ClientApp/src/until/http.js

@@ -12,7 +12,7 @@ axios.interceptors.request.use(
             config.url.indexOf('batcharea') != -1 ||
             config.url.indexOf('batchschool') != -1 ||
             config.url.indexOf('schoolcheck') != -1 ||
-            config.url.indexOf('tabledd') != -1 || config.url.indexOf('schoolroom') != -1) {
+            config.url.indexOf('tabledd') != -1 || config.url.indexOf('schoolroom') != -1 || config.url.indexOf('syscfg') != -1 || config.url.indexOf('biservers') != -1) {
             config.headers = {
                 'Content-Type': 'application/json',
                 'x-auth-authtoken': JSON.parse(localStorage.id_token)

+ 1 - 1
TEAMModelBI/ClientApp/src/view/areaServe/statistics.vue

@@ -184,7 +184,7 @@ export default {
         let showPattern = ref('all')
         let aspectsData = ref([
             { id: 1, title: '区内学校', num: 0, icon: '#icon-renshixuexiao', classname: 'school' },
-            { id: 2, title: '区内老师', num: 0, icon: '#icon-laoshi', classname: 'teach' },
+            { id: 2, title: '区内老师', num: 0, icon: '#icon-schoollaoshi', classname: 'teach' },
             { id: 3, title: '本周数据', num: 0, icon: '#icon-benzhou', classname: 'months' },
             { id: 4, title: '产出总数据', num: 0, icon: '#icon-ziyuan1', classname: 'datas' },
             { id: 5, title: '空间总容量', num: 0, icon: '#icon-kongjian', classname: 'size' },

+ 71 - 35
TEAMModelBI/ClientApp/src/view/common/aside.vue

@@ -100,7 +100,7 @@ export default {
                 sort: 0,
             },
             {
-                name: '系统设置',
+                name: '系统管理',
                 icon: '#icon-xitongshezhi1',
                 router: '',
                 role: ['admin'],
@@ -108,6 +108,13 @@ export default {
                 permission: '',
                 sort: 1,
                 child: [
+                    {
+                        name: '系统配置',
+                        router: '/home/system',
+                        icon: '#icon-peizhi-xitongpeizhi',
+                        permission: ['orgusers-read', 'orgusers-upd'],
+                        isShow: true,
+                    },
                     {
                         name: proxy.$t(`menu.personnel`),
                         router: '/home/teach',
@@ -115,61 +122,90 @@ export default {
                         permission: ['orgusers-read', 'orgusers-upd'],
                         isShow: true,
                     },
+                    {
+                        name: '操作日志',
+                        router: '/home/log',
+                        icon: '#icon-rizhi1',
+                        permission: [],
+                        isShow: true,
+                    },
                 ],
             },
             {
-                name: '区域服务',
+                name: '区校管理',
                 router: '/home/areamanage',
                 role: ['special'],
-                icon: '#icon-quyuguanli',
+                icon: '#icon-zisunchaquyufenbu',
                 permission: ['batcharea-read', 'batcharea-upd'],
                 isShow: true,
-                child: [],
-                sort: 2,
-            },
-            {
-                name: '学校服务',
-                router: '/home/schoolmanage',
-                role: ['special'],
-                icon: '#icon-pingtai_xuexiaoguanli',
-                permission: ['batchschool-read', 'batchschool-upd'],
-                isShow: true,
                 child: [
                     {
-                        name: '学校统计',
+                        name: '学区管理',
                         router: '/home/schoolmanage',
-                        icon: '#icon-zhexiantu',
+                        icon: '#icon-quyuguanli',
                         permission: ['orgusers-read', 'orgusers-upd'],
                         isShow: true,
                     },
                     {
-                        name: '基础设置',
-                        router: '/home/schoolset',
-                        icon: '#icon-navicon-jcsz',
+                        name: '学校管理',
+                        router: '/home/schoolmanage',
+                        icon: '#icon-pingtai_xuexiaoguanli',
                         permission: ['orgusers-read', 'orgusers-upd'],
                         isShow: true,
                     },
                     {
-                        name: '授权管理',
-                        router: '/home/impower',
-                        icon: '#icon-shouquanguanli',
+                        name: '微能力管理',
+                        router: '/home/schoolmanage',
+                        icon: '#icon-peizhiguanli',
                         permission: ['orgusers-read', 'orgusers-upd'],
                         isShow: true,
                     },
                 ],
-                sort: 3,
-            },
-            {
-                name: proxy.$t(`menu.ability`),
-                router: '/home/traitmanage',
-                role: ['admin', 'assist'],
-                icon: '#icon-peizhiguanli',
-                permission: ['abilitystandard-read', 'abilitystandard-upd'],
-                isShow: true,
-                child: [],
-                sort: 4,
+                sort: 2,
             },
             // {
+            //     name: '学校服务',
+            //     router: '/home/schoolmanage',
+            //     role: ['special'],
+            //     icon: '#icon-pingtai_xuexiaoguanli',
+            //     permission: ['batchschool-read', 'batchschool-upd'],
+            //     isShow: true,
+            //     child: [
+            //         {
+            //             name: '学校统计',
+            //             router: '/home/schoolmanage',
+            //             icon: '#icon-zhexiantu',
+            //             permission: ['orgusers-read', 'orgusers-upd'],
+            //             isShow: true,
+            //         },
+            //         {
+            //             name: '基础设置',
+            //             router: '/home/schoolset',
+            //             icon: '#icon-navicon-jcsz',
+            //             permission: ['orgusers-read', 'orgusers-upd'],
+            //             isShow: true,
+            //         },
+            //         {
+            //             name: '授权管理',
+            //             router: '/home/impower',
+            //             icon: '#icon-shouquanguanli',
+            //             permission: ['orgusers-read', 'orgusers-upd'],
+            //             isShow: true,
+            //         },
+            //     ],
+            //     sort: 3,
+            // },
+            // {
+            //     name: proxy.$t(`menu.ability`),
+            //     router: '/home/traitmanage',
+            //     role: ['admin', 'assist'],
+            //     icon: '#icon-peizhiguanli',
+            //     permission: ['abilitystandard-read', 'abilitystandard-upd'],
+            //     isShow: true,
+            //     child: [],
+            //     sort: 4,
+            // },
+            // {
             //     name: proxy.$t(`menu.ability`),
             //     router: '/home/traitmanage',
             //     role: ['admin', 'assist'],
@@ -180,7 +216,7 @@ export default {
             //     sort: 5,
             // },
             {
-                name: '应用管理',
+                name: '区校掌握',
                 icon: '#icon-jichuguanli',
                 router: '',
                 role: ['admin', 'assist'],
@@ -189,14 +225,14 @@ export default {
                 sort: 5,
                 child: [
                     {
-                        name: '区域管理',
+                        name: '学区情况',
                         router: '',
                         icon: '#icon-xiangmufanwei',
                         permission: [],
                         isShow: true,
                     },
                     {
-                        name: '学校管理',
+                        name: '学校情况',
                         router: '',
                         icon: '#icon-xuexiao2',
                         permission: [],

+ 2 - 2
TEAMModelBI/ClientApp/src/view/common/header.vue

@@ -1,6 +1,6 @@
 <template>
     <el-header style="text-align: right; font-size: 12px">
-        <div class="logsbox" :title="$t(`header.log`)" @click="pushlog" v-show="isAdmin">
+        <div class="logsbox" :title="$t(`header.log`)" @click="pushlog">
             <!-- <div class="iconimg">
                 <svg class="log-icon" aria-hidden="true">
                     <use xlink:href="#icon-caozuorizhi-copy"></use>
@@ -9,7 +9,7 @@
             <div class="icontext">
                 <sapn style="color:#fff">操作日志</sapn>
             </div> -->
-            <el-button plain icon="el-icon-s-order" size="mini">{{$t(`header.log`)}}</el-button>
+            <!-- <el-button plain icon="el-icon-s-order" size="mini">{{$t(`header.log`)}}</el-button> -->
             <!-- <el-button size="small">
                 <svg class="log-icon" aria-hidden="true">
                     <use xlink:href="#icon-caozuorizhi-copy"></use>

+ 6 - 6
TEAMModelBI/ClientApp/src/view/schoolServe/index.vue

@@ -382,7 +382,7 @@ export default {
                                 },
                                 itemStyle: {
                                     normal: {
-                                        color: '#173164',
+                                        color: '#6a89cc',
                                     },
                                 },
                             },
@@ -489,7 +489,7 @@ export default {
                                 },
                                 itemStyle: {
                                     normal: {
-                                        color: '#173164',
+                                        color: '#6a89cc',
                                     },
                                 },
                             },
@@ -596,7 +596,7 @@ export default {
                                 },
                                 itemStyle: {
                                     normal: {
-                                        color: '#173164',
+                                        color: '#6a89cc',
                                     },
                                 },
                             },
@@ -703,7 +703,7 @@ export default {
                                 },
                                 itemStyle: {
                                     normal: {
-                                        color: '#173164',
+                                        color: '#6a89cc',
                                     },
                                 },
                             },
@@ -715,7 +715,7 @@ export default {
                 backgroundColor: '#fff',
                 grid: {
                     top: '22%',
-                    bottom: '22%',
+                    bottom: '25%',
                     left: '4%',
                     right: '3%',
                 },
@@ -1061,7 +1061,7 @@ export default {
 }
 .bottombox {
     width: 98%;
-    height: 20vh;
+    height: 25vh;
     margin: 1%;
     background: #fff;
     position: relative;

+ 180 - 0
TEAMModelBI/ClientApp/src/view/systemConfig/correlation.vue

@@ -0,0 +1,180 @@
+<template>
+    <div class="correlationbox">
+        <div class="nowuser">
+            <p class="correlationbox-title">当前操作用户:</p>
+            <div class="userlist">
+                <PersonalPhoto style="cursor: pointer;" name="陈明洋" width="40px" height="40px" fontSize="12px" class="pigpicture"></PersonalPhoto>
+                <p class="userlist-name">陈明洋</p>
+            </div>
+        </div>
+        <p class="correlationbox-title">目前用户所关联学校:</p>
+        <div class="possessbox" v-if="tableDatas.length >=1">
+            <el-table :data="tableDatas" style="width: 100%" height="20vh" size="small">
+                <el-table-column fixed prop="date" label="名称" />
+                <el-table-column prop="date" label="学校简码" />
+                <el-table-column prop="name" label="版本" />
+                <el-table-column prop="name" label="目前顾问" />
+                <el-table-column fixed="right" label="操作" width='80'>
+                    <template #default="scope">
+                        <el-button type="text" size="small" @click="removeSchool(scope.$index,tableData)">取消关联</el-button>
+                    </template>
+                </el-table-column>
+            </el-table>
+        </div>
+        <div class="nodata" v-else-if="tableDatas.length ==0">
+            <div>暂无关联学校</div>
+        </div>
+        <div class="school-list">
+            <p class="correlationbox-title">学校列表:</p>
+            <div class="listbox">
+                <el-table :data="tableData" style="width: 100%" height="40vh" size="small">
+                    <el-table-column fixed prop="date" label="名称" />
+                    <el-table-column prop="date" label="学校简码" />
+                    <el-table-column prop="name" label="版本" />
+                    <el-table-column prop="name" label="目前顾问" />
+                    <el-table-column fixed="right" label="操作" width='80'>
+                        <template #default="scope">
+                            <el-button type="text" size="small" @click="correlation(scope.$index,tableData)">关联学校</el-button>
+                        </template>
+                    </el-table-column>
+                </el-table>
+            </div>
+        </div>
+    </div>
+</template>
+<script>
+import { ref, getCurrentInstance } from 'vue'
+import { ElMessage, ElLoading, ElMessageBox } from 'element-plus'
+export default {
+    setup() {
+        let { proxy } = getCurrentInstance()
+        const tableDatas = ref([])
+        const tableData = [
+            {
+                date: '2016-05-03',
+                name: 'Tom',
+                address: 'No. 189, Grove St, Los Angeles',
+            },
+            {
+                date: '2016-05-02',
+                name: 'Tom',
+                address: 'No. 189, Grove St, Los Angeles',
+            },
+            {
+                date: '2016-05-04',
+                name: 'Tom',
+                address: 'No. 189, Grove St, Los Angeles',
+            },
+            {
+                date: '2016-05-01',
+                name: 'Tom',
+                address: 'No. 189, Grove St, Los Angeles',
+            },
+            {
+                date: '2016-05-01',
+                name: 'Tom',
+                address: 'No. 189, Grove St, Los Angeles',
+            },
+            {
+                date: '2016-05-01',
+                name: 'Tom',
+                address: 'No. 189, Grove St, Los Angeles',
+            },
+            {
+                date: '2016-05-01',
+                name: 'Tom',
+                address: 'No. 189, Grove St, Los Angeles',
+            },
+            {
+                date: '2016-05-01',
+                name: 'Tom',
+                address: 'No. 189, Grove St, Los Angeles',
+            },
+            {
+                date: '2016-05-01',
+                name: 'Tom',
+                address: 'No. 189, Grove St, Los Angeles',
+            },
+            {
+                date: '2016-05-01',
+                name: 'Tom',
+                address: 'No. 189, Grove St, Los Angeles',
+            },
+            {
+                date: '2016-05-01',
+                name: 'Tom',
+                address: 'No. 189, Grove St, Los Angeles',
+            },
+        ]
+        function correlation(value, data) {
+            ElMessageBox.confirm(`请问您确定将 用户123 设为 成都锦江区外国语小学 顾问,进行数据关联吗 ?`, '关联学校', {
+                confirmButtonText: proxy.$t(`commonMsg.confirm`),
+                cancelButtonText: proxy.$t(`commonMsg.closes`),
+                type: 'success',
+                center: true,
+            }).then(() => {
+                tableDatas.value.push({
+                    date: '2016-05-01',
+                    name: 'Tom',
+                    address: 'No. 189, Grove St, Los Angeles',
+                })
+                ElMessage.success('操作成功')
+            })
+        }
+        function removeSchool(value, data) {
+            console.log(value, data)
+            ElMessageBox.confirm(`请问您确定将 用户123 与 成都锦江区外国语小学 取消关联吗 ?`, '取消关联', {
+                confirmButtonText: proxy.$t(`commonMsg.confirm`),
+                cancelButtonText: proxy.$t(`commonMsg.closes`),
+                type: 'error',
+                center: true,
+            }).then(() => {
+                tableDatas.value.splice(value, 1)
+                console.log(tableDatas)
+                ElMessage.success('操作成功')
+            })
+        }
+        return { tableData, tableDatas, correlation, removeSchool }
+    },
+}
+</script>
+<style scoped>
+.correlationbox {
+    width: 100%;
+}
+.correlationbox-title {
+    font-size: 14px;
+    color: #b2bec3;
+    text-align: left;
+}
+.possessbox {
+    width: 100%;
+    overflow: hidden;
+    height: 20vh;
+    /* border: 1px solid #ccc; */
+}
+.school-list {
+    width: 100%;
+    margin-top: 7%;
+}
+.nodata {
+    width: 100%;
+    height: 20vh;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+}
+.nodata {
+    font-size: 18px;
+    color: #bdc3c7;
+    font-weight: 700;
+}
+.userlist {
+    width: 20%;
+    text-align: center;
+}
+.userlist-name {
+    font-size: 14px;
+    color: #7f8c8d;
+}
+</style>

+ 56 - 0
TEAMModelBI/ClientApp/src/view/systemConfig/index.vue

@@ -0,0 +1,56 @@
+<template>
+    <div class="systembox">
+        <div class="systembox-tabs">
+            <el-tabs v-model="activeName" class="demo-tabs">
+                <el-tab-pane label="站点配置" name="websites">
+                    <Website></Website>
+                </el-tab-pane>
+                <el-tab-pane label="系统管理者" name="admin">
+                    <SetAdmin></SetAdmin>
+                </el-tab-pane>
+            </el-tabs>
+        </div>
+    </div>
+</template>
+<script>
+import { ref } from 'vue'
+import Website from './website.vue'
+import SetAdmin from './setAdmin.vue'
+export default {
+    components: {
+        Website,
+        SetAdmin,
+    },
+    setup() {
+        let activeName = ref('websites')
+        return { activeName }
+    },
+}
+</script>
+<style scoped>
+.systembox {
+    width: 100%;
+    line-height: 20px;
+}
+.systembox-tabs {
+    width: 100%;
+}
+/* .demo-tabs > .el-tabs__content {
+    padding: 32px;
+    color: #6b778c;
+    font-size: 32px;
+    font-weight: 600;
+} */
+</style>
+<style>
+.systembox .el-tabs__header {
+    margin: 0px;
+    /* padding-left: 15px; */
+    box-shadow: 0 2px 5px #e9e9e9;
+    margin-bottom: 5px;
+    background: #fff;
+}
+.systembox .el-tabs__nav-wrap {
+    padding-left: 15px;
+}
+</style>

+ 155 - 0
TEAMModelBI/ClientApp/src/view/systemConfig/operate.vue

@@ -0,0 +1,155 @@
+<template>
+    <div class="operatebox">
+        <div class="nowuser">
+            <p class="identitybox-title">当前操作用户:</p>
+            <div class="userlist">
+                <PersonalPhoto style="cursor: pointer;" name="陈明洋" width="40px" height="40px" fontSize="12px" class="pigpicture"></PersonalPhoto>
+                <p class="userlist-name">陈明洋</p>
+            </div>
+        </div>
+        <div class="identitybox">
+            <p class="identitybox-title">当前身份:</p>
+            <div class="identitybox-select">
+                <el-select v-model="value" size="small" placeholder="当前身份">
+                    <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
+                </el-select>
+            </div>
+        </div>
+        <div class="authoritybox">
+            <p class="identitybox-title">权限列表:</p>
+            <div class="authority-block" v-for="(item,index) in authorityList" :key="index">
+                <p class="authority-block-title">{{item.name}}</p>
+                <div class="authority-block-item" v-for="(items,indexs) in item.children" :key="indexs">
+                    <div class="authority-block-item-name">{{items.name}}</div>
+                    <div class="authority-block-item-state">
+                        <el-switch v-model="items.state" />
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</template>
+<script>
+import { ref } from 'vue'
+export default {
+    setup() {
+        const value = ref('')
+        const options = [
+            {
+                value: 'channelcrew',
+                label: '渠道人员',
+            },
+            {
+                value: 'sellcrew',
+                label: '销售',
+            },
+            {
+                value: 'counselor',
+                label: '顾问',
+            },
+            // {
+            //     value: 'research',
+            //     label: '研发部门人员',
+            // },
+            {
+                value: 'leader',
+                label: '领导',
+            },
+            {
+                value: 'admin',
+                label: '系统管理员',
+            },
+        ]
+        const authorityList = [
+            // { id: 1, name: '系统配置', children: [{ id: 1 - 1, name: '操作系统配置', key: '123456', state: false }] },
+            // {
+            //     id: 2,
+            //     name: '人员管理',
+            //     children: [
+            //         { id: 2 - 1, name: '查看人员名单信息', key: '123456', state: false },
+            //         { id: 2 - 2, name: '编辑人员名单信息', key: '123456', state: true },
+            //     ],
+            // },
+            {
+                id: 3,
+                name: '学区情况',
+                children: [
+                    { id: 3 - 1, name: '查看学区数据信息', key: '123456', state: false },
+                    { id: 3 - 2, name: '修改学区相关信息', key: '123456', state: false },
+                ],
+            },
+            {
+                id: 4,
+                name: '学校情况',
+                children: [
+                    { id: 4 - 1, name: '查看学校数据信息', key: '123456', state: false },
+                    { id: 4 - 2, name: '修改学校相关信息', key: '123456', state: false },
+                ],
+            },
+        ]
+        return { value, options, authorityList }
+    },
+}
+</script>
+<style scoped>
+.operatebox {
+    width: 100%;
+    line-height: 20px;
+    text-align: left;
+}
+.identitybox {
+    padding: 1% 0% 4% 0%;
+    border-bottom: 1px solid #b2bec3;
+}
+.identitybox-title {
+    font-size: 14px;
+    color: #7f8fa6;
+}
+.identitybox-select {
+    width: 100%;
+}
+.authoritybox {
+    width: 100%;
+    padding: 1% 0%;
+}
+.authority-block {
+    width: 100%;
+    padding: 1%;
+    line-height: 30px;
+}
+.authority-block-title {
+    font-size: 14px;
+    color: #b2bec3;
+}
+.authority-block-item-name {
+    width: 67%;
+    display: inline-block;
+    vertical-align: top;
+    font-size: 16px;
+    padding-left: 3%;
+    color: #636e72;
+}
+.authority-block-item-state {
+    width: 25%;
+    display: inline-block;
+    vertical-align: top;
+    text-align: right;
+    padding-right: 5%;
+}
+.authority-block-item {
+    padding: 1% 0%;
+}
+.userlist {
+    width: 20%;
+    text-align: center;
+}
+.userlist-name {
+    font-size: 14px;
+    color: #7f8c8d;
+}
+</style>
+<style>
+.identitybox-select .el-select--small {
+    width: 50%;
+}
+</style>

+ 370 - 0
TEAMModelBI/ClientApp/src/view/systemConfig/setAdmin.vue

@@ -0,0 +1,370 @@
+<template>
+    <div class="setadmin">
+        <div class="admin-List">
+            <p class="admin-List-title">平台系统管理员列表</p>
+            <div class="list-item" v-for="(item,index) in adminData" :key="index">
+                <div class="list-item-photo">
+                    <div class="headerPhoto">
+                        <el-image style="width: 55px; height: 55px;border-radius:50%" :src="item.avatar" fit="fill" v-if="item.avatar !=='' "></el-image>
+                        <PersonalPhoto style="cursor: pointer;" :name="item.name" width="55px" height="55px" v-else></PersonalPhoto>
+                    </div>
+                </div>
+                <div class="list-item-left">
+                    <p class="list-item-left-name">{{item.name}}</p>
+                    <p class="list-item-left-content"><span class="list-item-left-title">醍摩豆账号:</span><span>{{item.tmdId}}</span></p>
+                    <p class="list-item-left-content"><span class="list-item-left-title">手机号:</span><span>{{item.mobile}}</span></p>
+                    <p class="list-item-left-content"><span class="list-item-left-title">加入时间:</span><span>2022-03-16</span></p>
+                </div>
+                <div class="list-item-right">
+                    <div class="deletebtn" @click="removeadmin(item)">
+                        <svg class="undock" aria-hidden="true">
+                            <use xlink:href="#icon-yichuhaoyou"></use>
+                        </svg>
+                    </div>
+                </div>
+            </div>
+        </div>
+        <div class="setadmin-add">
+            <p class="admin-List-title">添加管理者</p>
+            <div class="admin-searchbox">
+                <div class="admin-text">
+                    <div class="admin-text-box" v-if="searchState ===false">
+                        <div class="hint"><span>请输入用户</span><span class="emphasize">手机号、醍摩豆账号</span><span>等相关信息进行搜索</span></div>
+                        <div class="search-box">
+                            <!-- <input class="search-txt" type="text" id="serachname" :value="filterText" placeholder="搜索相关人名" @oninput="personnelSearch()" @compositionend="personnelSearch()"> -->
+                            <el-input v-model="adminfilter" placeholder="Please input" class="search-txt" />
+                            <svg class="serachbox-empty" aria-hidden="true" v-if="adminfilter !==''" @click="adminfilter=''">
+                                <use xlink:href="#icon-qingkong"></use>
+                            </svg>
+                            <svg class="serachbox-iconinfo" aria-hidden="true" v-else>
+                                <use xlink:href="#icon-sousuotianchong"></use>
+                            </svg>
+                        </div>
+                        <div class="submitbtn">
+                            <el-button type="primary" size="small" @click=serachPersonnel(adminfilter) class="anewbox-btn blue">搜索人员</el-button>
+                        </div>
+                    </div>
+                    <div class="admin-text-box" v-else-if="searchState ===true">
+                        <div class="serarch-result">
+                            <el-image style="width: 140px; height: 140px;border-radius:50%" :src="searchData.picture" fit="fill" v-if="searchData.picture"></el-image>
+                            <PersonalPhoto style="cursor: pointer;" :name="searchData.name" width="140px" height="140px" fontSize="18px" class="pigpicture" v-else></PersonalPhoto>
+                            <div class="result-text">
+                                <p class="result-text-name">{{searchData.name}}</p>
+                                <p class="result-text-phone">{{searchData.id}}</p>
+                                <p class="result-text-phone">{{searchData.mobile}}</p>
+                            </div>
+                            <div class="anewbox">
+                                <el-button type="primary" size="small" @click="addAdmin()" class="anewbox-btn">加入到系统管理员</el-button>
+                                <el-button type="primary" size="small" class="anewbox-btn" @click="searchState=false,searchData='',adminfilter=''">重新检索人员</el-button>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</template>
+<script>
+import { ref, getCurrentInstance } from 'vue'
+import { Search } from '@element-plus/icons-vue'
+import { ElMessage, ElLoading, ElMessageBox } from 'element-plus'
+export default {
+    components: {
+        Search,
+    },
+    setup() {
+        let adminfilter = ref('')
+        let adminData = ref([])
+        let { proxy } = getCurrentInstance()
+        let searchData = ref()
+        let searchState = ref(false)
+        function getAdmin() {
+            let data = { busy: 'admin' }
+            proxy.$api
+                .getEveryinfo(data)
+                .then((res) => {
+                    console.log(res, 'ADMIN')
+                    res.state === 200 ? (adminData.value = res.ddUserInfos) : ''
+                })
+                .catch((err) => {
+                    ElMessage.error('系统管理员获取API异常')
+                })
+        }
+        function serachPersonnel(value) {
+            let data = [value]
+            proxy.$api
+                .searchPersonnel(data)
+                .then((res) => {
+                    res.state === 200 && res.infos.length !== 0 ? ((searchData.value = res.infos[0]), (searchState.value = true)) : ''
+                })
+                .catch((err) => {
+                    ElMessage.error('人员搜索异常')
+                })
+        }
+        function removeadmin(value) {
+            console.log(value)
+            ElMessageBox.confirm(`请问您确定从系统管理员列表中移除 ${value.name}(${value.mobile}) 吗?`, '移除管理员', {
+                confirmButtonText: proxy.$t(`commonMsg.confirm`),
+                cancelButtonText: proxy.$t(`commonMsg.closes`),
+                type: 'error',
+                center: true,
+            }).then(() => {
+                let data = { partitionKey: value.partitionKey, rowKey: value.rowKey, isAdmin: false }
+                proxy.$api
+                    .removeAdmin(data)
+                    .then((res) => {
+                        res.state === 200 ? (ElMessage.success('操作成功'), getAdmin()) : ''
+                    })
+                    .catch((error) => {
+                        ElMessage.error('删除失败')
+                    })
+            })
+        }
+        function addAdmin() {
+            let data = searchData.value
+                ? { tmdId: searchData.value.id, tmdName: searchData.value.name, mobile: searchData.value.mobile, picture: searchData.value.picture, mail: searchData.value.mail }
+                : ''
+            proxy.$api
+                .addAdmin(data)
+                .then((res) => {
+                    console.log(res, '添加管理员返回')
+                    res.state === 200 ? (ElMessage.success('操作成功'), getAdmin()) : ''
+                })
+                .catch((error) => {
+                    ElMessage.error('添加管理员失败')
+                })
+        }
+        getAdmin()
+        return { adminfilter, adminData, getAdmin, serachPersonnel, searchData, searchState, removeadmin, addAdmin }
+    },
+}
+</script>
+<style scoped>
+.setadmin {
+    width: 100%;
+    display: flex;
+    line-height: 20px;
+}
+.admin-List {
+    width: 30%;
+    text-align: left;
+    height: 100vh;
+    border-right: 1px solid #ccc;
+}
+.setadmin-add {
+    width: 70%;
+}
+.admin-List-title {
+    font-size: 14px;
+    color: #636e72;
+    line-height: 40px;
+    padding-left: 1%;
+    text-align: left;
+}
+.list-item {
+    padding: 5px 20px 5px 15px;
+    display: flex;
+}
+.list-item-left {
+    width: 65%;
+    height: 100px;
+}
+.list-item-right {
+    width: 15%;
+    height: 100px;
+    line-height: 70px;
+    text-align: center;
+    display: flex;
+    align-items: center;
+}
+.list-item-left-name {
+    font-size: 20px;
+    margin-bottom: 10px;
+    font-weight: 600;
+}
+.list-item-left-content {
+    font-size: 14px;
+    margin: 5px 0px;
+}
+.deletebtn {
+    width: 40px;
+    height: 40px;
+    background-color: #8395a7;
+    position: relative;
+    border-radius: 50%;
+    opacity: 0;
+    cursor: pointer;
+}
+.undock {
+    position: absolute;
+    width: 20px;
+    height: 20px;
+    top: 25%;
+    left: 28%;
+}
+.list-item-left-title {
+    color: #95a5a6;
+}
+.list-item:hover {
+    background-color: #c8d6e5;
+}
+.list-item:hover .deletebtn {
+    opacity: 1;
+}
+.admin-searchbox {
+    position: relative;
+    padding-left: 20px;
+    height: calc(100% - 155px);
+}
+.admin-text {
+    height: 100%;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+}
+.admin-text-box {
+    width: 450px;
+    text-align: center;
+}
+.admin-serach {
+    margin-top: 5%;
+}
+.serachicon {
+    position: absolute;
+    width: 20px;
+    height: 20px;
+    top: 0%;
+}
+.search-box {
+    /* position: absolute;
+    top: 9%;
+    left: 15%; */
+    /* transform: translate(0%, -50%); */
+    background: #bdc3c7;
+    height: 40px;
+    border-radius: 40px;
+    padding: 10px;
+    display: inline-block;
+    vertical-align: top;
+    /* justify-content: center; */
+    margin-top: 12px;
+    margin-left: 1%;
+}
+.search-btn {
+    float: right;
+    width: 40px;
+    height: 40px;
+    border-radius: 50%;
+    background: #2f3640;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    transition: 0.4s;
+}
+.search-txt {
+    border: none;
+    background: none;
+    outline: none;
+    float: left;
+    padding: 0;
+    color: white;
+    font-size: 16px;
+    transition: 0.4s;
+    line-height: 20px;
+    width: 400px;
+}
+.serachbox-empty {
+    width: 20px;
+    height: 20px;
+    vertical-align: 1.3em;
+    fill: currentColor;
+    overflow: hidden;
+    color: #95a5a6;
+    margin-right: 5px;
+    cursor: pointer;
+    float: right;
+    display: inline-block;
+}
+.serachbox-iconinfo {
+    width: 20px;
+    height: 20px;
+    vertical-align: 1.2em;
+    fill: currentColor;
+    overflow: hidden;
+    float: right;
+}
+.hint {
+    font-size: 14px;
+}
+.emphasize {
+    font-size: 16px;
+    color: #74b9ff;
+}
+.submitbtn {
+    margin-top: 10%;
+}
+.list-item-photo {
+    width: 20%;
+    text-align: center;
+    line-height: 100px;
+    display: flex;
+    align-items: center;
+}
+.pigpicture {
+    margin-bottom: 5%;
+}
+.result-text-name {
+    font-size: 16px;
+    color: #333;
+    font-weight: 600;
+    margin-bottom: 5px;
+}
+.result-text-phone {
+    font-size: 14px;
+    color: #7f8c8d;
+    margin: 5px;
+}
+.anewbox {
+    margin-top: 2%;
+    margin-bottom: 2%;
+}
+.anewbox-btn {
+    width: 180px;
+    display: block;
+    margin: 0 auto;
+    margin-bottom: 10px;
+    background-color: #12cbc4;
+    color: #fefefe;
+    border: none;
+    font-weight: 900;
+}
+.blue {
+    width: 200px;
+    background-color: #00a8ff;
+}
+</style>
+<style>
+.search-box .el-input__inner {
+    opacity: 1;
+    width: 100%;
+    /* padding: 0px; */
+    height: 30px;
+    line-height: 30px;
+    border: 0px;
+    background-color: #bdc3c7;
+    vertical-align: top;
+    border-radius: 8px;
+    padding-bottom: 10px;
+}
+.submitbtn .el-button--small {
+    padding: 9px 62px;
+    font-size: 14px;
+}
+.headerPhoto .el-image {
+    display: block;
+}
+</style>
+
+
+
+

+ 249 - 0
TEAMModelBI/ClientApp/src/view/systemConfig/website.vue

@@ -0,0 +1,249 @@
+<template>
+    <div class="websiteList">
+        <div class="basics">
+            <p class="commonbox-title">基础设置</p>
+            <el-form :model="basicsData" label-width="140px" size="small">
+                <el-form-item label="站点:" class="basics-name">
+                    <el-input v-model="basicsData.website" @input="changeData('basics','site')" />
+                </el-form-item>
+                <el-form-item label="工程模式/部门ID:" class="basics-ip">
+                    <el-input v-model="basicsData.platform" @input="changeData('basics','proDeptId')" />
+                </el-form-item>
+                <!-- <el-form-item label="语系:" class="basics-lang">
+                    <el-select v-model="basicsData.language" placeholder="选择语系" @change="basicsData.state=true">
+                        <el-option label="简体" value="familiar" />
+                        <el-option label="繁体" value="complex" />
+                    </el-select>
+                </el-form-item> -->
+            </el-form>
+            <div class="basics-redact-btn" v-show="basicsData.state" @click="updateData('basics')">
+                <el-button type="primary" size="small">确认调整</el-button>
+            </div>
+        </div>
+        <div class="privatebox">
+            <p class="commonbox-title">密钥相关</p>
+            <div class="dingding">
+                <p class="interiorTag">钉钉密钥</p>
+                <el-form :model="dingDingData" label-width="120px" size="small">
+                    <el-form-item label="Agentld:" class="dingding-Id">
+                        <el-input v-model="dingDingData.Agentld" @input="changeData('dingDing','appId')" />
+                    </el-form-item>
+                    <el-form-item label="appKey:" class="dingding-Key">
+                        <el-input v-model="dingDingData.appKey" @input="changeData('dingDing','appKey')" />
+                    </el-form-item>
+                    <el-form-item label="appSecret:" class="dingding-appSecret">
+                        <el-input v-model="dingDingData.appSecret" type="textarea" :rows="4" @input="changeData('dingDing','appSecret')" />
+                    </el-form-item>
+                </el-form>
+                <div class="redact-btn" v-show="dingDingData.state" @click="updateData('dingDing')">
+                    <el-button type="primary" size="small">更新配置</el-button>
+                </div>
+            </div>
+            <div class="databasebox">
+                <p class="interiorTag">数据库</p>
+                <div class="database-list">
+                    <el-form :model="databaseData" label-width="120px" size="small">
+                        <p class="database-title">Blob</p>
+                        <el-form-item label="ConnectionString">
+                            <el-input v-model="databaseData.Storage" type="textarea" @input="changeData('database','storage')" />
+                        </el-form-item>
+                        <p class="database-title">CosmosDB</p>
+                        <el-form-item label="ConnectionString:">
+                            <el-input v-model="databaseData.Cosmos" type="textarea" @input="changeData('database','cosmosDb')" />
+                        </el-form-item>
+                        <p class="database-title">Redis</p>
+                        <el-form-item label="ConnectionString:">
+                            <el-input v-model="databaseData.Redis" type="textarea" @input="changeData('database','redis')" />
+                        </el-form-item>
+                        <p class="database-title">服务地址</p>
+                        <el-form-item label="ConnectionString:">
+                            <el-input v-model="databaseData.ServiceBus" type="textarea" @input="changeData('database','serviceBus')" />
+                        </el-form-item>
+                    </el-form>
+                    <div class="redact-btn" v-show="databaseData.state" @click="updateData('database')">
+                        <el-button type="primary" size="small">更新配置</el-button>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</template>
+<script>
+import { ref, reactive, getCurrentInstance } from 'vue'
+import { ElMessage, ElLoading } from 'element-plus'
+export default {
+    setup() {
+        let { proxy } = getCurrentInstance()
+        let adminfilter = ref('')
+        //基础信息
+        let basicsData = ref({
+            website: '',
+            platform: '',
+            state: false,
+        })
+        //钉钉密钥
+        let dingDingData = ref({
+            Agentld: '',
+            appKey: '',
+            appSecret: '',
+            state: false,
+        })
+        //数据库
+        let databaseData = ref({
+            Storage: '',
+            Cosmos: '',
+            Redis: '',
+            ServiceBus: '',
+            state: false,
+        })
+        function getData() {
+            proxy.$api
+                .getSystemConfig({})
+                .then((res) => {
+                    console.log(res, '配置返回')
+                    res.state === 200
+                        ? ((basicsData.value.website = res.siteScope),
+                          (basicsData.value.platform = res.proDeptId),
+                          (dingDingData.value.Agentld = res.ddAgentld),
+                          (dingDingData.value.appKey = res.ddAppKey),
+                          (dingDingData.value.appSecret = res.ddAppSecret),
+                          (databaseData.value.Storage = res.storage),
+                          (databaseData.value.Cosmos = res.cosmos),
+                          (databaseData.value.Redis = res.redis),
+                          (databaseData.value.ServiceBus = res.serviceBus))
+                        : ''
+                })
+                .catch((res) => {
+                    ElMessage.error('获取系统配置API异常')
+                })
+        }
+        function changeData(statename, value) {
+            statename === 'basics' ? (basicsData.value.state = true) : statename === 'dingDing' ? (dingDingData.value.state = true) : statename === 'database' ? (databaseData.value.state = true) : ''
+        }
+        function updateData(name) {
+            let data =
+                name === 'basics'
+                    ? { busy: 'website', site: basicsData.value.website, proDeptId: basicsData.value.platform }
+                    : name === 'dingDing'
+                    ? { busy: 'dd', appId: dingDingData.value.Agentld, appKey: dingDingData.value.appKey, appSecret: dingDingData.value.appSecret }
+                    : name === 'database'
+                    ? { busy: 'dbs', storage: databaseData.value.Storage, cosmosDb: databaseData.value.Cosmos, redis: databaseData.value.Redis, serviceBus: databaseData.value.ServiceBus }
+                    : ''
+
+            proxy.$api
+                .updateSystemconfig(data)
+                .then((res) => {
+                    console.log(res)
+                    ElMessage.success('操作成功!')
+                })
+                .catch((err) => {
+                    ElMessage.error('修改配置失败')
+                })
+        }
+        getData()
+        return {
+            basicsData,
+            dingDingData,
+            databaseData,
+            changeData,
+            updateData,
+        }
+    },
+}
+</script>
+<style scoped>
+.websiteList {
+    width: 100%;
+    margin-top: 1%;
+}
+.basics {
+    width: 80%;
+    padding: 1%;
+    position: relative;
+}
+.basics-name {
+    width: 40%;
+}
+.basics-ip {
+    width: 40%;
+}
+.basics-name {
+    margin-top: 2%;
+}
+.privatebox {
+    width: 100%;
+    padding: 1%;
+    position: relative;
+    display: flex;
+    justify-content: space-between;
+}
+.dingding {
+    width: 43%;
+    padding: 1.5%;
+    border: 1px solid #ccc;
+    position: relative;
+    margin-top: 1%;
+    border-radius: 5px;
+}
+.interiorTag {
+    position: absolute;
+    left: 0;
+    top: 0;
+    font-size: 14px;
+    background: rgba(45, 183, 245, 0.6);
+    color: #fff;
+    padding: 1px 20px 2px 5px;
+    border-bottom-right-radius: 30px;
+}
+.dingding-Id,
+.dingding-Key {
+    width: 70%;
+}
+.dingding-appSecret {
+    width: 90%;
+}
+.databasebox {
+    width: 55%;
+    padding: 2% 2% 2% 2%;
+    border: 1px solid #ccc;
+    position: relative;
+    margin-top: 1%;
+    border-radius: 5px;
+}
+
+.database-title {
+    text-align: left;
+    font-size: 14px;
+    color: #636e72;
+    font-weight: 700;
+}
+.commonbox-title {
+    border-left: 6px solid rgb(45, 140, 240);
+    padding-left: 15px;
+    font-size: 18px;
+    line-height: 16px;
+    color: #414749;
+    margin-bottom: 0;
+    position: absolute;
+    top: 1%;
+    font-size: 16px;
+}
+.redact-btn {
+    position: absolute;
+    bottom: 1%;
+    right: 1%;
+}
+.basics-redact-btn {
+    position: absolute;
+    bottom: 45%;
+    left: 50%;
+}
+</style>
+<style>
+.systembox .el-form-item__content {
+    text-align: left;
+}
+.basics .el-select--small {
+    width: 34.2%;
+}
+</style>

+ 174 - 120
TEAMModelBI/ClientApp/src/view/teachermanage/manage.vue

@@ -16,21 +16,27 @@
         <div class="search-box">
             <!-- <input class="search-txt" type="text" id="serachname" :value="filterText" placeholder="搜索相关人名" @oninput="personnelSearch()" @compositionend="personnelSearch()"> -->
             <el-input v-model="filterText" placeholder="Please input" class="search-txt" />
+            <svg class="serachbox-empty" aria-hidden="true" @click="filterText=''">
+                <use xlink:href="#icon-qingkong"></use>
+            </svg>
             <svg class="serachbox-icon" aria-hidden="true">
                 <use xlink:href="#icon-sousuotianchong"></use>
             </svg>
         </div>
     </div>
     <div class="refreshbtn">
-        <el-button @click="refresh">
-            <svg class="refreshbtn-icon" aria-hidden="true">
-                <use xlink:href="#icon-yunduanshuaxin-copy"></use>
-            </svg>
-            {{$t(`personnelManagement.synchronization.title`)}}
-        </el-button>
+        <div class="totalnum">总人数:<span>{{tableData.length}}</span></div>
+        <div class="refresh-btn">
+            <el-button @click="refresh()">
+                <svg class="refreshbtn-icon" aria-hidden="true">
+                    <use xlink:href="#icon-yunduanshuaxin-copy"></use>
+                </svg>
+                {{$t(`personnelManagement.synchronization.title`)}}
+            </el-button>
+        </div>
     </div>
     <div class="manage-table">
-        <el-table :data="tableData.value" style="width: 100%" height="80vh" v-loading="loading" element-loading-text="数据加载中..." class="customer-table" :empty-text='$t(`personnelManagement.personnelTable.nodatas`)'>
+        <el-table :data="tableData" style="width: 100%" height="85vh" v-loading="loading" element-loading-text="数据加载中..." class="customer-table" :empty-text='$t(`personnelManagement.personnelTable.nodatas`)'>
             <el-table-column prop="id" :label="$t(`personnelManagement.personnelTable.serialnum`)" sortable align="center" />
             <el-table-column :label="$t(`personnelManagement.personnelTable.headportrait`)" align="center">
                 <template #default="scope">
@@ -74,18 +80,31 @@
             <el-table-column prop="tmdId" :label="$t(`personnelManagement.personnelTable.tmdids`)" align="center">
             </el-table-column>
             <el-table-column prop="title" :label="$t(`personnelManagement.personnelTable.position`)" sortable align="center" />
-            <el-table-column :label="$t(`personnelManagement.personnelTable.operate`)" align="center" v-if="PowerShow">
+            <el-table-column :label="$t(`personnelManagement.personnelTable.operate`)" align="center">
                 <template #default="scope">
                     <el-button type="primary" size="small" @click="handleClick(scope.$index,tableData)">
                         <svg class="qxmages" aria-hidden="true">
                             <use xlink:href="#icon-quanxianguanli-"></use>
                         </svg>
-                        {{$t(`personnelManagement.personnelTable.operatecontent`)}}
+                        <!-- {{$t(`personnelManagement.personnelTable.operatecontent`)}} -->
+                        编辑
                     </el-button>
                 </template>
             </el-table-column>
         </el-table>
     </div>
+    <div class="personnel-drawer">
+        <el-drawer v-model="drawer" title="用户相关信息配置" :direction="direction" :modal="false">
+            <el-tabs v-model="activeName" class="demo-tabs">
+                <el-tab-pane label="权限/身份" name="first">
+                    <Operates></Operates>
+                </el-tab-pane>
+                <el-tab-pane label="关联学校" name="second">
+                    <Correlation></Correlation>
+                </el-tab-pane>
+            </el-tabs>
+        </el-drawer>
+    </div>
     <div class="manatips">
         <el-dialog v-model="managebox" :title="$t(`personnelManagement.authority.title`)" width="40%">
             <div class="manageboxs">
@@ -117,14 +136,20 @@ import { getCurrentInstance, reactive, ref, watch } from 'vue'
 import { useStore } from 'vuex'
 import { ElMessage, ElLoading } from 'element-plus'
 import jwt_decode from 'jwt-decode'
+import Operates from '@/view/systemConfig/operate.vue'
+import Correlation from '@/view/systemConfig/correlation.vue'
 export default {
+    components: {
+        Operates,
+        Correlation,
+    },
     setup() {
         let { proxy } = getCurrentInstance()
         const store = useStore()
-        let PowerShow = proxy.$access.inspectPower('orgusers-upd')
+        // let PowerShow = proxy.$access.inspectPower('orgusers-upd')
         let staffData = ref([])
         let loading = ref(true)
-        let tableData = reactive([])
+        let tableData = ref([])
         var numid = ref(1)
         let department = ref([])
         let options = ref([
@@ -186,6 +211,9 @@ export default {
         let original = ref([])
         let filterText = ref('')
         let timer = ref('')
+        let drawer = ref(false)
+        let direction = ref('rtl')
+        const activeName = ref('first')
         //处理名单
         getEvery()
         function process(val) {}
@@ -225,64 +253,63 @@ export default {
         }
         // 处理各个部门
         function handleClick(index, data) {
-            console.log(index, data, 'click')
-            let userData = data.value[index]
-            nowUser.value = data.value[index]
-            let manaPermission = JSON.parse(localStorage.getItem('management'))
-            // let userBind = userData.tmdId ? true : true
-            operateUser.value = userData
-            console.log(userData)
-            typeof userData.permissions !== 'object' ? userData.permissions.split(',') : ''
-            console.log(userData, '查看数据')
-            let arrData = []
-            for (let i in manaPermission) {
-                let name = manaPermission[i].rowKey
-                let result = userData.permissions.includes(name)
-                result
-                    ? arrData.push({
-                          name: manaPermission[i].discription,
-                          rowKey: manaPermission[i].rowKey,
-                          state: true,
-                      })
-                    : arrData.push({
-                          name: manaPermission[i].discription,
-                          rowKey: manaPermission[i].rowKey,
-                          state: false,
-                      })
-            }
-            // let showData = []
-            // arrData.forEach((item) => {
-            //     item.rowKey.includes('read') ? '' : showData.push(item)
-            // })
-            //处理是否管理员
-            userData.handleRoles.includes('admin') ? (userisAdmin.value.state = true) : (userisAdmin.value.state = false)
-            let ardata = [
-                // { id: 1, name: '能力点标准管理(读)', children: [] },
-                // { id: 2, name: '批量创区(读)', children: [] },
-                // { id: 3, name: '批量创校(读)', children: [] },
-                // { id: 4, name: '钉钉组织架构人员管理(读)', children: [] },
-            ]
-            let textname = ['能力点', '区域', '学校', '钉钉架构']
-            let num = 0
-            //处理类似于层级的权限呈现
-            for (let i in arrData) {
-                let oddEven = i % 2 == 0 ? 'odd' : 'even'
-                if (oddEven === 'odd') {
-                    arrData[i].children = []
-                    arrData[i].text = textname[num]
-                    ardata.push(arrData[i])
-                    num += 1
-                } else if (oddEven === 'even') {
-                    for (let y in ardata) {
-                        ardata[ardata.length - 1].children.push(arrData[i])
-                        break
-                    }
-                }
-            }
-            console.log(ardata, '循环的结果')
-            manageList.value = ardata
-            console.log(manageList, '结果')
-            managebox.value = true
+            // console.log(index, data, 'click')
+            drawer.value = true
+
+            // let userData = data.value[index]
+            // nowUser.value = data.value[index]
+            // let manaPermission = JSON.parse(localStorage.getItem('management'))
+            // // let userBind = userData.tmdId ? true : true
+            // operateUser.value = userData
+            // console.log(userData)
+            // typeof userData.permissions !== 'object' ? userData.permissions.split(',') : ''
+            // console.log(userData, '查看数据')
+            // let arrData = []
+            // for (let i in manaPermission) {
+            //     let name = manaPermission[i].rowKey
+            //     let result = userData.permissions.includes(name)
+            //     result
+            //         ? arrData.push({
+            //               name: manaPermission[i].discription,
+            //               rowKey: manaPermission[i].rowKey,
+            //               state: true,
+            //           })
+            //         : arrData.push({
+            //               name: manaPermission[i].discription,
+            //               rowKey: manaPermission[i].rowKey,
+            //               state: false,
+            //           })
+            // }
+
+            // //处理是否管理员
+            // userData.handleRoles.includes('admin') ? (userisAdmin.value.state = true) : (userisAdmin.value.state = false)
+            // let ardata = [
+            //     // { id: 1, name: '能力点标准管理(读)', children: [] },
+            //     // { id: 2, name: '批量创区(读)', children: [] },
+            //     // { id: 3, name: '批量创校(读)', children: [] },
+            //     // { id: 4, name: '钉钉组织架构人员管理(读)', children: [] },
+            // ]
+            // let textname = ['能力点', '区域', '学校', '钉钉架构']
+            // let num = 0
+            // //处理类似于层级的权限呈现
+            // for (let i in arrData) {
+            //     let oddEven = i % 2 == 0 ? 'odd' : 'even'
+            //     if (oddEven === 'odd') {
+            //         arrData[i].children = []
+            //         arrData[i].text = textname[num]
+            //         ardata.push(arrData[i])
+            //         num += 1
+            //     } else if (oddEven === 'even') {
+            //         for (let y in ardata) {
+            //             ardata[ardata.length - 1].children.push(arrData[i])
+            //             break
+            //         }
+            //     }
+            // }
+            // console.log(ardata, '循环的结果')
+            // manageList.value = ardata
+            // console.log(manageList, '结果')
+            // managebox.value = true
         }
         //删除所用
         function dataindexOf(val) {
@@ -299,45 +326,6 @@ export default {
                 operateUser.value.permissions.splice(index, 1)
             }
         }
-        //处理调整个人权限
-        function changeManage(rowkey, state) {
-            console.log(rowkey, state)
-            console.log(operateUser, manageList, '当前操作的人')
-            console.log(PowerShow)
-            if (!PowerShow) {
-                ElMessage.error(proxy.$t(`commonMsg.notoperate`))
-                return
-            }
-            let manaName = []
-            manageList.value.forEach((item) => {
-                item.state === true ? manaName.push(item.rowKey) : ''
-            })
-            let users = JSON.parse(localStorage.getItem('userData'))
-            console.log(manaName)
-            // if (operateUser.value.tmdId) {
-            let data = {
-                partitionKey: operateUser.value.partitionKey,
-                rowKey: operateUser.value.rowKey,
-                permissions: manaName,
-                tmdId: users.tmdId,
-                tmdName: users.tmdName,
-            }
-            proxy.$api
-                .updateManege(data)
-                .then((res) => {
-                    res.state === 200 ? (ElMessage.success(proxy.$t(`commonMsg.operateSuccess`)), (operateUser.value.permissions = manaName), synchronous(users, operateUser, manaName)) : ''
-                    // state ? (operateUser.value.handlePermissions = operateUser.value.handlePermissions.concat(manaName)) : dataremove(rowkey)
-                })
-                .catch((res) => {
-                    ElMessage.error(proxy.$t(`commonMsg.operateError`))
-                })
-            // } else {
-            //     manageList.value.forEach((element) => {
-            //         element.state = false
-            //     })
-            //     ElMessage(proxy.$t(`commonMsg.nonactivated`))
-            // }
-        }
         //任命系统管理员
         function changeAdmin(state) {
             let nowState = state
@@ -372,22 +360,31 @@ export default {
         //人员名单刷新
         function refresh() {
             let user = JSON.parse(localStorage.getItem('userData'))
+            if (user.tmdId === '' || user.tmdName === '') {
+                ElMessage.error('用户数据异常,操作失败')
+                return
+            }
             const loading = ElLoading.service({
                 lock: true,
                 text: '更新可能需要一些时间,请等待~',
                 background: 'rgba(0, 0, 0, 0.7)',
             })
             let data = { tmdId: user.tmdId, tmdName: user.tmdName }
-            proxy.$api.getStaffList(data).then((res) => {
-                res.state === 200 ? ElMessage.success('人员名单已更新') : ElMessage.error('人员名单更新失败,请稍后重试')
-                loading.close()
-            })
+            proxy.$api
+                .getStaffList(data)
+                .then((res) => {
+                    res.state === 200 ? ElMessage.success('人员名单已更新') : res.state === 401 ? ElMessage.error('非系统管理员无法操作') : ElMessage.error('人员名单更新失败,请稍后重试')
+                    loading.close()
+                })
+                .catch((err) => {
+                    ElMessage.error('操作失败,非系统管理人员无法操作!')
+                    loading.close()
+                })
         }
         //人员搜索
         function personnelSearch() {
             let arr = tableData.value
             let newArr = arr.filter((item) => {
-                console.log(item)
                 // return (item.name && item.name.includes(filterText.value)) || (item.mobile && item.mobile.includes(filterText.value)) || (item.mobile && item.mobile.tmdId.includes(filterText.value))
                 return item.name.includes(filterText.value)
             })
@@ -421,12 +418,10 @@ export default {
             changeDepartment,
             managebox,
             manageList,
-            changeManage,
             operateUser,
             dataindexOf,
             dataremove,
             synchronous,
-            PowerShow,
             refresh,
             isAdmin,
             userisAdmin,
@@ -434,6 +429,9 @@ export default {
             nowUser,
             personnelSearch,
             filterText,
+            drawer,
+            direction,
+            activeName,
         }
     },
 }
@@ -448,7 +446,9 @@ export default {
     margin-right: 5px;
 }
 .manage-table {
+    width: 100%;
     padding: 0% 1%;
+    transition: all 0.6s ease-out;
 }
 .select-box {
     width: 68%;
@@ -534,14 +534,25 @@ export default {
     /* justify-content: center; */
     margin-top: 12px;
     margin-left: 1%;
+    /* width: 250px; */
+    transition: 0.4s;
+}
+.search-box:hover {
+    /* width: 250px; */
 }
 .search-box:hover > .search-txt {
-    width: 200px;
+    width: 180px;
     padding: 0 6px;
 }
 .search-box:hover > .search-btn {
     background: white;
 }
+.search-box:hover > .serachbox-icon {
+    opacity: 0;
+}
+.search-box:hover > .serachbox-empty {
+    display: inline-block;
+}
 .search-btn {
     float: right;
     width: 40px;
@@ -566,11 +577,25 @@ export default {
     width: 0px;
 }
 .serachbox-icon {
-    width: 1.4em;
-    height: 1.4em;
+    width: 20px;
+    height: 20px;
     vertical-align: 1.2em;
     fill: currentColor;
     overflow: hidden;
+    float: right;
+    opacity: 1;
+}
+.serachbox-empty {
+    width: 20px;
+    height: 20px;
+    vertical-align: 1.3em;
+    fill: currentColor;
+    overflow: hidden;
+    color: #95a5a6;
+    margin-right: 5px;
+    cursor: pointer;
+    float: right;
+    display: none;
 }
 
 .contentbox {
@@ -630,6 +655,22 @@ export default {
 .pass {
     color: #1afa29;
 }
+.identity {
+    width: 20%;
+    display: none;
+}
+.personnel-drawer {
+    line-height: 20px;
+}
+.totalnum {
+    font-size: 14px;
+    color: #95afc0;
+    display: inline-block;
+    margin-right: 15px;
+}
+.refresh-btn {
+    display: inline-block;
+}
 </style>
 <style>
 .manatips .el-dialog__header,
@@ -650,7 +691,7 @@ export default {
     line-height: 65px !important;
 }
 .search-box .el-input__inner {
-    opacity: 0.1;
+    /* opacity: 0.1; */
     width: 0px;
     /* padding: 0px; */
     height: 0px;
@@ -661,7 +702,7 @@ export default {
     border-radius: 8px;
 }
 .search-box:hover .el-input__inner {
-    opacity: 1;
+    /* opacity: 1; */
     width: 100%;
     height: 30px;
     padding-bottom: 10px;
@@ -678,4 +719,17 @@ export default {
     top: 2px;
     right: 4px;
 }
+.personnel-drawer .el-drawer.rtl {
+    top: 6%;
+}
+.personnel-drawer .el-drawer__header {
+    line-height: 20px;
+    text-align: left;
+    margin-bottom: 5px;
+    padding: 5px;
+    font-size: 14px;
+}
+.personnel-drawer .el-drawer__body {
+    padding: 0px 10px;
+}
 </style>

+ 7 - 6
TEAMModelBI/ClientApp/src/view/teachermanage/reuse.vue

@@ -5,12 +5,10 @@
                 <div class="cardbox" v-for="(item,index) in abilityProject">
                     <el-card class="box-card">
                         <div class="card-number">{{index+1}}</div>
-                        <template #header>
-                            <div class="card-header">
-                                <span>{{item.standardName}}</span>
-                                <el-button class="button" type="text">编辑</el-button>
-                            </div>
-                        </template>
+                        <div class="card-header">
+                            <span>{{item.standardName}}</span>
+                            <el-button class="button" type="text">编辑</el-button>
+                        </div>
                         <div class="information-box">
                             <p class="source">来源于:<span class="source-title">{{item.name}}</span></p>
                             <p class="source">地区:<span class="source-title">{{item.provName}}{{item.cityName}}</span></p>
@@ -164,4 +162,7 @@ export default {
     min-height: 800px;
     text-align: left;
 }
+.cardbox .card-header {
+    border-bottom: 0px !important;
+}
 </style>

+ 4 - 0
TEAMModelBI/ClientApp/src/view/teachermanage/traitmanage.vue

@@ -864,6 +864,8 @@ export default {
     display: flex;
     justify-content: space-between;
     align-items: center;
+    border-bottom: 0px;
+    /* background: #bdc3c7; */
 }
 .text {
     font-size: 14px;
@@ -1246,6 +1248,8 @@ export default {
     overflow: hidden;
     text-overflow: ellipsis;
     white-space: nowrap;
+    font-size: 16px;
+    font-weight: 600;
 }
 .cutbtn {
     position: absolute;

+ 71 - 36
TEAMModelBI/Controllers/DingDingStruc/TableDingDingInfoController.cs

@@ -23,6 +23,8 @@ using Azure.Cosmos;
 using Microsoft.Azure.Cosmos.Table;
 using TEAMModelBI.Filter;
 using TEAMModelBI.Tool.Extension;
+using TEAMModelBI.Models;
+using TEAMModelBI.Tool.CosmosBank;
 
 namespace TEAMModelBI.Controllers.DingDingStruc
 {
@@ -170,15 +172,17 @@ namespace TEAMModelBI.Controllers.DingDingStruc
                 var users = await table.FindListByDict<DingDingUserInfo>(new Dictionary<string, object> { { "PartitionKey", $"{divide}" } });
 
                 List<DingDingUserInfo> noExisits = new();
-
                 if (users.Count > 0)
                 {
+                    //var temps = users.Union(tempddUserInfos).Except(users.Intersect(tempddUserInfos));
                     List<DingDingUserInfo> existsUserInfo = users.Where(u => !tempddUserInfos.Exists(e => u.userId.Equals(e.userId) && u.PartitionKey.Equals(e.PartitionKey))).ToList();
-                    //existsUserInfo.AddRange(tempddUserInfos.Where(e => !users.Exists(u => e.userId.Equals(u.userId) && e.PartitionKey.Equals(u.PartitionKey))).ToList());
+                    existsUserInfo.AddRange(tempddUserInfos.Where(e => !users.Exists(u => e.userId.Equals(u.userId) && e.PartitionKey.Equals(u.PartitionKey))).ToList());
 
                     ////List<DingDingUserInfo> existsUserInfo = users.Where((x, i) => users.FindIndex(z => z.userId.Equals(x.userId) && x.PartitionKey.Equals(divide)) == i).Select(x => x).ToList();
-
-                    noExisits = await table.DeleteAll(users);
+                    if (existsUserInfo.Count > 0)
+                    {
+                        noExisits = await table.DeleteAll(existsUserInfo);
+                    }
                 }
 
                 List<DingDingUserInfo> UserInfo = await table.SaveOrUpdateAll(tempddUserInfos);  //保存和修改至Table
@@ -202,14 +206,13 @@ namespace TEAMModelBI.Controllers.DingDingStruc
             try
             {
                 jsonElement.TryGetProperty("busy", out JsonElement busy);
+                var cosmosCliet = _azureCosmos.GetCosmosClient();
                 var table = _azureStorage.GetCloudTableClient().GetTableReference("BIDDUserInfo");
                 //string divide = _configuration["CustomParam:SiteScope"];
                 string divide = _option.Location;
-
-                Dictionary<string, object> dic = new Dictionary<string, object> { { "PartitionKey", $"{divide}" } };
-                List<DingDingUserInfo> ddUserInfoList = await table.FindListByDict<DingDingUserInfo>(dic);
-
                 List<DDUserInfo> ddUserInfos = new();
+                Dictionary<string, object> dic = new() { { "PartitionKey", $"{divide}" } };
+                List<DingDingUserInfo> ddUserInfoList = await table.FindListByDict<DingDingUserInfo>(dic);
 
                 switch ($"{busy}")
                 {
@@ -244,7 +247,13 @@ namespace TEAMModelBI.Controllers.DingDingStruc
                                     permissions = item.permissions,
                                     handleRoles = !string.IsNullOrEmpty($"{item.roles}") ? new List<string>(item.roles.Split(",")) : new List<string>(),
                                     handlePermissions = !string.IsNullOrEmpty($"{item.permissions}") ? new List<string>(item.permissions.Split(",")) : new List<string>(),
+                                 
                                 };
+                                if (!string.IsNullOrEmpty(item.schoolIds)) 
+                                {
+                                    List<string> tempSchoolIds = new(item.schoolIds.Split("|"));
+                                    ddUserInfo.handleSchools = await SchoolWay.GetSchoolInfos(cosmosCliet, tempSchoolIds);
+                                }
                                 ddUserInfos.Add(ddUserInfo);
                             }
                         }
@@ -280,6 +289,12 @@ namespace TEAMModelBI.Controllers.DingDingStruc
                                 handleRoles = !string.IsNullOrEmpty($"{item.roles}") ? new List<string>(item.roles.Split(",")) : new List<string>(),
                                 handlePermissions = !string.IsNullOrEmpty($"{item.permissions}") ? new List<string>(item.permissions.Split(",")) : new List<string>(),
                             };
+
+                            if (!string.IsNullOrEmpty(item.schoolIds))
+                            {
+                                List<string> tempSchoolIds = new(item.schoolIds.Split("|"));
+                                ddUserInfo.handleSchools = await SchoolWay.GetSchoolInfos(cosmosCliet, tempSchoolIds);
+                            }
                             ddUserInfos.Add(ddUserInfo);
                         }
 
@@ -490,7 +505,6 @@ namespace TEAMModelBI.Controllers.DingDingStruc
             }
         }
 
-
         /// <summary>
         /// 依据部门ID获取部门列表
         /// </summary>
@@ -502,6 +516,7 @@ namespace TEAMModelBI.Controllers.DingDingStruc
         {
             try
             {
+                var cosmosCliet = _azureCosmos.GetCosmosClient();
                 if (!jsonElement.TryGetProperty("deptId", out JsonElement deptId)) return BadRequest();
                 //string divide = _configuration["CustomParam:SiteScope"];
                 string divide = _option.Location;
@@ -615,6 +630,12 @@ namespace TEAMModelBI.Controllers.DingDingStruc
                         handleRoles = !string.IsNullOrEmpty($"{item.roles}") ? new List<string>(item.roles.Split(",")) : new List<string>(),
                         handlePermissions = !string.IsNullOrEmpty($"{item.permissions}") ? new List<string>(item.permissions.Split(",")) : new List<string>(),
                     };
+
+                    if (!string.IsNullOrEmpty(item.schoolIds))
+                    {
+                        List<string> tempSchoolIds = new List<string>(item.schoolIds.Split("|"));
+                        tempUserInfo.handleSchools = await SchoolWay.GetSchoolInfos(cosmosCliet, tempSchoolIds);
+                    }
                     ddUserInfos.Add(tempUserInfo);
                 }
 
@@ -816,7 +837,7 @@ namespace TEAMModelBI.Controllers.DingDingStruc
                 if (!jsonElement.TryGetProperty("mobile", out JsonElement mobile)) return BadRequest();
                 jsonElement.TryGetProperty("picture ", out JsonElement picture);
                 jsonElement.TryGetProperty("mail ", out JsonElement mail);
-
+                var cosmosCliet = _azureCosmos.GetCosmosClient();
                 var (_tmdId, _tmdName, pic, did, dname, dpic) = HttpJwtAnalysis.JwtXAuthBI(HttpContext.GetXAuth("AuthToken"), _option);
 
                 List<DDUserInfo> ddUserInfos = new();
@@ -895,6 +916,12 @@ namespace TEAMModelBI.Controllers.DingDingStruc
                             handleRoles = !string.IsNullOrEmpty($"{respUser.roles}") ? new List<string>(respUser.roles.Split(",")) : new List<string>(),
                             handlePermissions = !string.IsNullOrEmpty($"{respUser.permissions}") ? new List<string>(respUser.permissions.Split(",")) : new List<string>()
                         };
+
+                        if (!string.IsNullOrEmpty(respUser.schoolIds))
+                        {
+                            List<string> tempSchoolIds = new List<string>(respUser.schoolIds.Split("|"));
+                            dDUserInfo.handleSchools = await SchoolWay.GetSchoolInfos(cosmosCliet, tempSchoolIds);
+                        }
                         ddUserInfos.Add(dDUserInfo);
                     }
                 }
@@ -975,7 +1002,6 @@ namespace TEAMModelBI.Controllers.DingDingStruc
             return Ok(new { state = 200, userInfos });
         }
 
-
         /// <summary>
         /// 获取钉钉用户信息
         /// 并查询本地Table数据表中是否存在
@@ -1017,30 +1043,34 @@ namespace TEAMModelBI.Controllers.DingDingStruc
                         {
                             foreach (var user in users)
                             {
-                                DingDingUserInfo ddUserInfo = new();
-                                ddUserInfo.PartitionKey = user.PartitionKey;
-                                ddUserInfo.RowKey = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds().ToString();
-                                ddUserInfo.userId = itemUser.Userid;
-                                ddUserInfo.unionId = itemUser.Unionid;
-                                ddUserInfo.name = itemUser.Name;
-                                ddUserInfo.email = itemUser.Email;
-                                ddUserInfo.title = itemUser.Title;
-                                ddUserInfo.stateCode = itemUser.StateCode;
-                                ddUserInfo.mobile = itemUser.Mobile;
-                                ddUserInfo.jobNumber = itemUser.JobNumber;
-                                ddUserInfo.pid = parentId;
-                                ddUserInfo.deptId = deptId;
-                                ddUserInfo.deptName = name;
-                                ddUserInfo.depts = string.Join(",", itemUser.DeptIdList.ToArray());
-                                ddUserInfo.avatar = itemUser.Avatar;
-                                ddUserInfo.isAdmin = itemUser.Admin;
-                                ddUserInfo.tmdId = user.tmdId;
-                                ddUserInfo.tmdName = user.tmdName;
-                                ddUserInfo.tmdMobile = user.tmdMobile;
-                                ddUserInfo.mail = user.mail;
-                                ddUserInfo.picture = user.picture;
-                                ddUserInfo.roles = user.roles;
-                                ddUserInfo.permissions = user.permissions;
+                                DingDingUserInfo ddUserInfo = new()
+                                {
+                                    PartitionKey = user.PartitionKey,
+                                    RowKey = user.RowKey,
+                                    userId = itemUser.Userid,
+                                    unionId = itemUser.Unionid,
+                                    name = itemUser.Name,
+                                    email = itemUser.Email,
+                                    title = itemUser.Title,
+                                    stateCode = itemUser.StateCode,
+                                    mobile = itemUser.Mobile,
+                                    jobNumber = itemUser.JobNumber,
+                                    pid = parentId,
+                                    deptId = deptId,
+                                    deptName = name,
+                                    depts = string.Join(",", itemUser.DeptIdList.ToArray()),
+                                    avatar = itemUser.Avatar,
+                                    isAdmin = itemUser.Admin,
+                                    tmdId = user.tmdId,
+                                    tmdName = user.tmdName,
+                                    tmdMobile = user.tmdMobile,
+                                    mail = user.mail,
+                                    picture = user.picture,
+                                    roles = user.roles,
+                                    joinTime = user.joinTime,
+                                    permissions = user.permissions,
+                                    schoolIds = user.schoolIds
+                                };
 
                                 ddUserInfos.Add(ddUserInfo);
                             }
@@ -1055,6 +1085,7 @@ namespace TEAMModelBI.Controllers.DingDingStruc
                                 name = itemUser.Name,
                                 email = itemUser.Email,
                                 title = itemUser.Title,
+                                stateCode = itemUser.StateCode,
                                 mobile = itemUser.Mobile,
                                 jobNumber = itemUser.JobNumber,
                                 pid = parentId,
@@ -1070,7 +1101,9 @@ namespace TEAMModelBI.Controllers.DingDingStruc
                                 mail = "",
                                 picture = "",
                                 roles = "assist",
-                                permissions = "abilitystandard-read,batcharea-read,batchschool-read,orgusers-read"
+                                joinTime = 0,
+                                permissions = "abilitystandard-read,batcharea-read,batchschool-read,orgusers-read",
+                                schoolIds = ""
                             };
 
                             ddUserInfos.Add(ddUserInfo);
@@ -1108,6 +1141,8 @@ namespace TEAMModelBI.Controllers.DingDingStruc
             public string permissions { get; set; }
             public List<string> handleRoles { get; set; }
             public List<string> handlePermissions { get; set; }
+            public List<AdvSchool> handleSchools { get; set; }
         }
+
     }
 }

+ 53 - 22
TEAMModelBI/Controllers/LoginController.cs

@@ -33,6 +33,7 @@ using TEAMModelBI.Filter;
 using TEAMModelBI.Models.Extension;
 using TEAMModelOS.SDK;
 using Microsoft.AspNetCore.Hosting;
+using TEAMModelBI.Tool;
 //using static DingTalk.Api.Response.OapiV2UserGetResponse;
 
 namespace TEAMModelBI.Controllers
@@ -52,18 +53,18 @@ namespace TEAMModelBI.Controllers
         private readonly DingDing _dingDing;
         private readonly Option _option;
         //隐式登录
-        private readonly CoreAPIHttpService _aoreAPIHttpService;
+        private readonly CoreAPIHttpService _coreAPIHttpService;
         private readonly IHttpClientFactory _http;
         private readonly IWebHostEnvironment _environment; //读取文件
 
-        public LoginController(IConfiguration configuration, AzureCosmosFactory azureCosmos, AzureStorageFactory azureStorage, DingDing dingDing, IOptionsSnapshot<Option> option, CoreAPIHttpService aoreAPIHttpService, IHttpClientFactory http, IWebHostEnvironment environment)
+        public LoginController(IConfiguration configuration, AzureCosmosFactory azureCosmos, AzureStorageFactory azureStorage, DingDing dingDing, IOptionsSnapshot<Option> option, CoreAPIHttpService coreAPIHttpService, IHttpClientFactory http, IWebHostEnvironment environment)
         {
             _configuration = configuration;
             _azureCosmos = azureCosmos;
             _azureStorage = azureStorage;
             _dingDing = dingDing;
             _option = option?.Value;
-            _aoreAPIHttpService = aoreAPIHttpService;
+            _coreAPIHttpService = coreAPIHttpService;
             _http = http;
             _environment = environment;
         }
@@ -84,6 +85,7 @@ namespace TEAMModelBI.Controllers
                 string proDeptId = _configuration["CustomParam:proDeptId"]; 
                 //string divide = _configuration["CustomParam:SiteScope"];
                 string divide = _option.Location;
+                var cosmosClient = _azureCosmos.GetCosmosClient();
 
                 if (string.IsNullOrWhiteSpace(appKey) || string.IsNullOrWhiteSpace(appSecret))
                 {
@@ -152,32 +154,55 @@ namespace TEAMModelBI.Controllers
                     {
                         if (string.IsNullOrEmpty(item.tmdId))
                         {
-                            HttpClient httpClient = _http.CreateClient();
-                            string url = _configuration.GetValue<string>("HaBookAuth:CoreId:userinfo");
-
                             List<string> mobiles = new() { $"{ item.mobile}" };
-                            HttpResponseMessage responseMessage = await httpClient.PostAsJsonAsync(url, mobiles);
-                            if (responseMessage.StatusCode == HttpStatusCode.OK)
+                            var content = new StringContent(mobiles.ToJsonString(), Encoding.UTF8, "application/json");
+                            string json = await _coreAPIHttpService.GetUserInfos(content);
+                            if (!string.IsNullOrEmpty(json))
                             {
-                                string temp = responseMessage.Content.ReadAsStringAsync().Result;
-                                List<JsonElement> json_id = temp.ToObject<List<JsonElement>>();
-                                if (json_id.Count > 0)
+                                List<JsonElement> json_id = json.ToObject<List<JsonElement>>();
+                                foreach (var tmd in json_id)
                                 {
-                                    foreach (var tmd in json_id)
-                                    {
-                                        item.tmdId = tmd.GetProperty("id").ToString();
-                                        item.tmdName = tmd.GetProperty("name").ToString();
-                                        item.tmdMobile = tmd.GetProperty("mobile").ToString();
-                                        item.picture = tmd.GetProperty("picture").ToString();
-                                        item.mail = tmd.GetProperty("mail").ToString();
-                                    }
+                                    item.tmdId = tmd.GetProperty("id").ToString();
+                                    item.tmdName = tmd.GetProperty("name").ToString();
+                                    item.tmdMobile = tmd.GetProperty("mobile").ToString();
+                                    item.picture = tmd.GetProperty("picture").ToString();
+                                    item.mail = tmd.GetProperty("mail").ToString();
                                 }
-                                else return Ok(new { state = 404, msg = "依据钉钉手机号未找到醍摩豆账号!" });
                             }
+                            else return Ok(new { state = 404, msg = "依据钉钉手机号未找到醍摩豆账号!" });
+
+                            //HttpClient httpClient = _http.CreateClient();
+                            //string url = _configuration.GetValue<string>("HaBookAuth:CoreId:userinfo");
+                            //List<string> mobiles = new() { $"{ item.mobile}" };
+                            //HttpResponseMessage responseMessage = await httpClient.PostAsJsonAsync(url, mobiles);
+                            //if (responseMessage.StatusCode == HttpStatusCode.OK)
+                            //{
+                            //    string temp = responseMessage.Content.ReadAsStringAsync().Result;
+                            //    List<JsonElement> json_id = temp.ToObject<List<JsonElement>>();
+                            //    if (json_id.Count > 0)
+                            //    {
+                            //        foreach (var tmd in json_id)
+                            //        {
+                            //            item.tmdId = tmd.GetProperty("id").ToString();
+                            //            item.tmdName = tmd.GetProperty("name").ToString();
+                            //            item.tmdMobile = tmd.GetProperty("mobile").ToString();
+                            //            item.picture = tmd.GetProperty("picture").ToString();
+                            //            item.mail = tmd.GetProperty("mail").ToString();
+                            //        }
+                            //    }
+                            //    else return Ok(new { state = 404, msg = "依据钉钉手机号未找到醍摩豆账号!" });
+                            //}
 
                             strMsg.Append($"{item.tmdName}【{item.tmdId}】醍摩豆账号和{item.name}【{item.userId}】钉钉账户绑定成功");
+                            saveInfo.Add(item);
+                        }
+
+                        List<string> schoolIds = await CommonFind.FindSchoolIds(cosmosClient, item.tmdId);
+                        if (schoolIds.Count > 0)
+                        {
+                            item.schoolIds = string.Join("|", schoolIds);
+                            await table.SaveOrUpdate<DingDingUserInfo>(item);
                         }
-                        saveInfo.Add(item);
 
                         roles = !string.IsNullOrEmpty($"{item.roles}") ? new List<string>(item.roles.Split(",")) : new List<string>();
                         permissions = !string.IsNullOrEmpty($"{item.permissions}") ? new List<string>(item.permissions.Split(",")) : new List<string>();
@@ -194,7 +219,7 @@ namespace TEAMModelBI.Controllers
                     {
                         ddusers = await table.UpdateAll<DingDingUserInfo>(saveInfo);
                         //保存操作记录
-                        await _azureStorage.SaveBILog("tabledd-update", strMsg?.ToString(), _dingDing, httpContext: HttpContext);
+                        await _azureStorage.SaveBILog("tabledd-update", strMsg?.ToString(), _dingDing, httpContext: HttpContext,twebsite:"BI");
                     }
                 }
                 else
@@ -246,6 +271,12 @@ namespace TEAMModelBI.Controllers
                     }
                     else return Ok(new { state = 404, msg = "钉钉手机号为空" });
 
+                    List<string> schoolIds = await CommonFind.FindSchoolIds(cosmosClient, ddUserInfo.tmdId);
+                    if (schoolIds.Count > 0)
+                    {
+                        ddUserInfo.schoolIds = string.Join("|", schoolIds);
+                    }
+
                     ddUserInfo = await table.Save<DingDingUserInfo>(ddUserInfo);
 
                     //保存操作记录

+ 13 - 0
TEAMModelBI/Models/MonthStartEnd.cs

@@ -32,5 +32,18 @@
         public int scale { get; set; }
     }
 
+    /// <summary>
+    /// 学校简易信息
+    /// </summary>
+    public record AdvSchool
+    {
+        public string id { get; set; }
+
+        public string name { get; set; }
+
+        public string picture { get; set; }
+
+
+    }
 
 }

+ 33 - 0
TEAMModelBI/Tool/CosmosBank/SchoolWay.cs

@@ -0,0 +1,33 @@
+using Azure.Cosmos;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using TEAMModelBI.Models;
+
+namespace TEAMModelBI.Tool.CosmosBank
+{
+    public class SchoolWay
+    {
+        /// <summary>
+        /// 依据钉钉人员信息中的学校列表
+        /// </summary>
+        /// <param name="cosmosClient"></param>
+        /// <param name="schoolIds"></param>
+        /// <returns></returns>
+        public async static Task<List<AdvSchool>> GetSchoolInfos(CosmosClient cosmosClient, List<string> schoolIds) 
+        {
+            List<AdvSchool> advSchools = new();
+            foreach (var item in schoolIds)
+            {
+                await foreach (var info in cosmosClient.GetContainer("TEAMModelOS", "School").GetItemQueryIterator<AdvSchool>(queryText: $"select c.id,c.name,c.picture from c where c.id='{item}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("Base") }))
+                {
+                    advSchools.Add(info);
+                }
+            }
+
+
+
+            return advSchools;
+        }
+
+    }
+}

+ 1 - 1
TEAMModelOS.FunctionV4/ServiceBus/ActiveTaskTopic.cs

@@ -1098,7 +1098,7 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
                                     await _azureStorage.GetBlobServiceClient().DeleteBlobs(_dingDing, blobname, paths);
                                     //end 处理历史数据
                                     #endregion
-                                    await client.GetContainer(Constant.TEAMModelOS, tbname).DeleteItemAsync<LessonRecord>(lessonId, new PartitionKey(code));
+                                    //await client.GetContainer(Constant.TEAMModelOS, tbname).DeleteItemAsync<LessonRecord>(lessonId, new PartitionKey(code));
                                     await _azureStorage.GetBlobServiceClient().DeleteBlobs(_dingDing, blobname, new List<string> { $"records/{_lessonId}" });
                                     await client.GetContainer(Constant.TEAMModelOS, tbname).DeleteItemStreamAsync(lessonRecord.id,new PartitionKey ($"Bloblog-{blobname}"));
                                     var messageBlob = new ServiceBusMessage(new { id = Guid.NewGuid().ToString(), progress = "update", root = "records", name = $"{blobname}" }.ToJsonString()); ;

+ 3 - 3
TEAMModelOS.FunctionV4/TEAMModelOS.FunctionV4.csproj

@@ -5,9 +5,9 @@
 		<OutputType>Exe</OutputType>
 		<_FunctionsSkipCleanOutput>true</_FunctionsSkipCleanOutput>
 		<SignAssembly>true</SignAssembly>
-		<AssemblyVersion>5.2204.18.1</AssemblyVersion>
-		<FileVersion>5.2204.18.1</FileVersion>
-		<Version>5.2204.18</Version>
+		<AssemblyVersion>5.2204.20.1</AssemblyVersion>
+		<FileVersion>5.2204.20.1</FileVersion>
+		<Version>5.2204.20</Version>
 		<PackageId>TEAMModelOS.FunctionV4</PackageId>
 		<Authors>teammodel</Authors>
 		<Company>醍摩豆(成都)信息技术有限公司</Company>

+ 1 - 1
TEAMModelOS.SDK/Models/Cosmos/BI/DingDingUserInfo.cs

@@ -122,6 +122,6 @@ namespace TEAMModelOS.SDK.Models.Cosmos.BI
         /// <summary>
         /// 学校列表
         /// </summary>
-        public string schools { get; set; }
+        public string schoolIds { get; set; }
     }
 }

+ 4 - 0
TEAMModelOS.SDK/Models/Cosmos/Normal/AreaSetting.cs

@@ -35,6 +35,10 @@ namespace TEAMModelOS.SDK.Models
         /// </summary>
         public int lessonMinutes { get; set; } = 45;
         /// <summary>
+        /// 限制分钟数
+        /// </summary>
+        public int limitMinutes { get; set; } = -1;
+        /// <summary>
         /// 文档类型
         /// </summary>
         public List<string> doc { get; set; } = new List<string>();

+ 6 - 6
TEAMModelOS.SDK/Models/Service/GroupListService.cs

@@ -608,7 +608,7 @@ namespace TEAMModelOS.SDK
                         name = item.name, 
                         picture = item.picture,
                         type = 1,
-                        nickname=item.name,
+                       // nickname=item.name,
                     };
                     members.Add(member);
 
@@ -746,7 +746,7 @@ namespace TEAMModelOS.SDK
                                 id = y.id,
                                 code = school,
                                 name = y.name,
-                                nickname = y.name,
+                                //nickname = y.name,
                                 type = 2,
                                 picture = y.picture,
                                 no = y.no,
@@ -1055,14 +1055,14 @@ namespace TEAMModelOS.SDK
                 {
                     var user = tmdsData.Find(y => y.id.Equals(x.id));
                     x.name = user?.name;
-                    x.nickname = string.IsNullOrWhiteSpace(x.nickname) ? user?.name : x.nickname;
+                   // x.nickname = string.IsNullOrWhiteSpace(x.nickname) ? user?.name : x.nickname;
                     x.picture = user?.picture;
                 });
                 students.ForEach(x =>
                 {
                     var student = studentsData.Find(y => y.id.Equals(x.id) && y.schoolId.Equals(x.code));
                     x.name = student?.name;
-                    x.nickname = string.IsNullOrWhiteSpace(x.nickname) ? student?.name:x.nickname;
+                   // x.nickname = string.IsNullOrWhiteSpace(x.nickname) ? student?.name:x.nickname;
                     x.picture = student?.picture;
                     x.classId = student?.classId;
                 });
@@ -1083,14 +1083,14 @@ namespace TEAMModelOS.SDK
                     {
                         var tmd = tmdids.Find(t => t.id.Equals(y.id));
                         y.name = tmd?.name;
-                        y.nickname = string.IsNullOrWhiteSpace(y.nickname) ? tmd?.nickname : y.nickname;
+                        //y.nickname = string.IsNullOrWhiteSpace(y.nickname) ? tmd?.nickname : y.nickname;
                         y.picture = tmd?.picture;
                     }
                     if (y.type == 2)
                     {
                         var student = students.Find(t => t.id.Equals(y.id) && t.code.Equals(y.code));
                         y.name = student?.name;
-                        y.nickname =  string.IsNullOrWhiteSpace(y.nickname) ? student?.nickname : y.nickname; 
+                      //  y.nickname =  string.IsNullOrWhiteSpace(y.nickname) ? student?.nickname : y.nickname; 
                         y.picture = student?.picture;
                         y.classId = student?.classId;
                     }

+ 5 - 5
TEAMModelOS/ClientApp/src/locale/lang/en-US/auth.js

@@ -14,10 +14,10 @@ export default {
     teachSpace: 'Allocated to teachers',
     homework: 'Homework',
     train: 'Seminar',
-    records:'課堂記錄',
+    records:'Lesson Record',
     over: 'Remaining',
-    syllabus:'課綱',
-    itemAndPaper:'試題試卷',
+    syllabus:'Syllabus',
+    itemAndPaper:'Question & Exam File',
     appData:'Application Data',
     content:'Content Module',
     used:'Used:',
@@ -74,6 +74,6 @@ export default {
     unauthText1: 'The school has not yet obtained the',
     unauthText2: 'authorization and cannot view the current content.',
     toAuth: 'Go to Authorize',
-    periodInfo1:'學校學段數量',
-    periodInfo2:'學校學院數量',
+    periodInfo1: 'No. of school systems school purchased',
+    periodInfo2: 'No. of colleges school purchased',
 }

+ 3 - 3
TEAMModelOS/ClientApp/src/locale/lang/en-US/cusMgt.js

@@ -111,8 +111,8 @@ export default {
     qrCodeText: 'Invitation Code:',
     inviteUrl: 'Copy Invitation Link',
     copyUrl: 'Copy Link',
-    joinMessage1: "允許加入課程",
-    joinMessage2: "禁止加入課程",
+    joinMessage1: "Allowed to join the course",
+    joinMessage2: "Prohibited to join the course",
     inviteInfo1: 'Invite to join the IES Teacher Personal Course on the TEAM Model Cloud',
     inviteInfo2: 'Course Name:',
     inviteInfo3: 'Course List:',
@@ -368,7 +368,7 @@ export default {
         errorContent: 'Course list access failed, please scan the code to join again!',
         joinOk: 'Join successfully',
         joinErr: 'Failed to join',
-        joinLock: "課程名單未開放加入",
+        joinLock: "The course list is not open to join",
         getListErr: 'Failed to get list information',
         hasJoin: 'you have joined successfully! ',
         getErr: 'Failed to read user information',

+ 2 - 2
TEAMModelOS/ClientApp/src/locale/lang/en-US/home.js

@@ -1,7 +1,7 @@
 export default{
     previewStudy:'Previews before class',
     classData:'Lesson Data',
-    recentRecord:'Recent Lesson Record',
+    recentRecord:'Recent 7-day lesson record',
     acCount:'Activities Overview',
     goingList:'List Of Ongoing Activities',
     scNotice:'School Announcement',
@@ -84,5 +84,5 @@ export default{
     count6: 'Exam File No.',
     count7: 'Question No.',
     count8: 'Resource No.',    
-    spaceInfo:'空間使用情況'
+    spaceInfo:'Space Usage'
 }

+ 56 - 56
TEAMModelOS/ClientApp/src/locale/lang/en-US/learnActivity.js

@@ -9,8 +9,8 @@ export default {
     notSupportType: 'Uploading files of this format is not supported!',
     mgtScEv: {
         listLabel: 'Assessment List',
-        listLabel1: '學校評測',
-        listLabel2: '個人評測',
+        listLabel1: 'School Assessment',
+        listLabel2: 'Personal Assessment',
         period: 'School System:',
         create: 'Create',
         delete: 'Delete',
@@ -27,7 +27,7 @@ export default {
         nodata: 'No assessment yet',
         tab1: 'Assessment Data',
         tab2: 'Assessment Files',
-        tab3: '作答詳情',
+        tab3: 'Answering Details',
         autoTips1: 'This function is only used to show the scenario and quickly simulate student response data. Student responses are randomly generated for reference only!',
         autoTips2: 'This function is only used to show the scenario and quickly simulate teacher grading data. Teacher grading are randomly generated for reference only!',
         autoScore: 'One Click Grading',
@@ -81,7 +81,7 @@ export default {
         copyTitle: 'Copy Assessment',
         copyContent: 'Are you sure to copy the assessment?',
         copyContent1: 'Smarter Classroom Assessment cannot be copied.',
-        paperExam:'紙本測驗',
+        paperExam:'SelfPace Test (Instant Paper)',
         loadAll:'已加載所有數據',
         crossSchool:'跨校評測,在當前學校無法查看發布對象'
     },
@@ -232,7 +232,7 @@ export default {
         status2: 'Go to grading',
         status3: 'View Score',
         status4: 'Absent',
-        status5: '補考',
+        status5: 'Make-up Test',
         column1: 'Name',
         column2: 'Total Score',
         column3: 'Status',
@@ -312,13 +312,13 @@ export default {
         complyCount: 'Passer Number',
         simpleErr: 'Failed to search statistical data',
         dataErr: 'The assessment statistical data error!',
-        quCorrectRate:'試題答對率',
-        cc:'及格人數',
-        rac:'比率 (人數):',
-        noKn:'試卷沒有知識點數據',
-        dataErr:'評測數據異常',
-        goingNoData:'評測進行中,無法查看統計數據',
-        paperErr: '試卷數據異常'
+        quCorrectRate: 'Question Correct Rate',
+        cc: 'Passer Number',
+        rac: 'Ratio (No. of people):',
+        noKn: 'No key concept data in the exam file',
+        dataErr: 'Assessment data has anomalies',
+        goingNoData: 'Assessment is in progress, statistics cannot be viewed',
+        paperErr: 'Exam file data has anomalies'
     },
 
     mark: {
@@ -334,7 +334,7 @@ export default {
         remove: 'Remove',
         addTea: 'Add Marking Teacher',
         quDistrub: '題目分配',
-        quIndex: '題號',
+        quIndex: 'Question No.',
         markNum: '閱卷人數',
         markTea: 'Marking Teacher',
         stage: '進行階段',
@@ -348,8 +348,8 @@ export default {
         markProg: 'Marking Progress',
         data: 'Data Statistics',
         dataView: 'Data Overview',
-        scanOk: '掃描成功',
-        scanErr: '掃描失敗',
+        scanOk: 'Scanned successfully',
+        scanErr: 'Failed to scan',
         arbPaper: '仲裁試卷',
         subData: 'Overview Of Each Subject',
         assigned: 'Assigned',
@@ -359,9 +359,9 @@ export default {
         schedule: 'Adjust',
         subject: 'Subject',
         stuNum: 'Examinee Number',
-        scanProg: '掃描進度',
+        scanProg: 'Scanning Progress',
         assignStatus: '閱卷分配',
-        errDeclare: 'Abnormality Report',
+        errDeclare: 'Report Abnormality',
         errTeacher: 'Abnormality Handler',
         arbTeacher: 'Arbitration Teacher',
         arbDeclare: 'Arbitration Paper',
@@ -384,7 +384,7 @@ export default {
         no: 'No',
         allQu: 'All Question',
         noSet: 'Not set yet',
-        quNoSet: '題號設置',
+        quNoSet: 'Question No. Setting',
         startErr: 'Please set the start time',
         endErr: 'Please set the end time',
         typeErr: 'Please set the assigning method',
@@ -421,21 +421,21 @@ export default {
         reapQu: 'There are questions that are repeatedly assigned',
         objectiveLabel: '(Objective)',
         alreadyLabel: '(Already)',
-        exTag: '異常',
-        scoreTips: '溫馨提示:客觀題已由系統自動評分,下面只顯示了需要人工評分的主觀題題號。',
-        feedback: '反饋:',
-        exStatus: '狀態:未處理',
-        continueMark: '繼續閱卷',
-        exTitle: '異常原因',
-        exReason1: '答案不清晰,看不清楚',
-        exReason2: '答案圖片不完整',
-        exReason3: '其他原因',
-        exHolder: '異常原因...',
-        exceptionOk: '上報成功',
-        exceptionErr: '上報失敗',
-        noExTips: '請選擇異常原因',
-        markSaveOk: '批註保存成功',
-        hasNoMarkQu: '還有未閱題目',
+        exTag: 'Abnormal',
+        scoreTips: 'Note: The objective questions have been automatically marked by the system. Only the subjective questions that need to be marked manually are shown below.',
+        feedback: 'Feedback:',
+        exStatus: 'Status: Unprocessed',
+        continueMark: 'Continue',
+        exTitle: 'Abnormal Reason',
+        exReason1: 'The answer is not clear and cannot be seen clearly',
+        exReason2: 'The answer picture is incomplete',
+        exReason3: 'Other reasons',
+        exHolder: 'Abnormal Reason...',
+        exceptionOk: 'Reported successfully',
+        exceptionErr: 'Failed to report',
+        noExTips: 'Please select abnormal reason',
+        markSaveOk: 'Annotation save successfully',
+        hasNoMarkQu: 'There are still unmark questions',
         markSetLabel: 'Marking Settings',
         markTime: 'Time:',
         allocationType: 'Method:',
@@ -443,20 +443,20 @@ export default {
         examSubject: 'Subject:',
         delTask: 'Delete Marking Task',
         delTaskTips: 'When you delete a marking task, all the marking tasks of assigned teachers and marking data of the currently assessment will be deleted. Are you sure you want to delete it?',
-        distribution: '題目配分:',
-        loadAll: '已加載所有數據',
+        distribution: 'Allocated Points:',
+        loadAll: 'All data has been loaded',
 
         //ByqU.vue & ByStu.vue
-        quit: '退出閱卷',
-        examName: '考試名稱:',
-        reviewType: '閱卷方式:',
-        byQu: '按題閱卷',
-        byStu: '按人閱卷',
-        stuId: '學生Id',
-        score: '分數:',
-        curQu: '當前題號:',
-        quProg: '題目進度',
-        exception: '異常申報',
+        quit: 'Exit',
+        examName: 'Name:',
+        reviewType: 'Method:',
+        byQu: 'Mark By Question',
+        byStu: 'Mark By People',
+        stuId: 'Student ID',
+        score: 'Point:',
+        curQu: 'Question No.:',
+        quProg: 'Progress',
+        exception: 'Report Abnormality',
         move: 'Move',
         text: 'Text',
         brush: 'Pen',
@@ -466,12 +466,12 @@ export default {
         seal: 'Stamp',
         clear: 'Clear Annotation',
         eraser: 'Eraser',
-        marked: '已閱',
-        unmark: '未閱',
-        fullScore: '滿分',
-        zeroScore: '零分',
-        halfRight: '半對',
-        submit: '提交分數/批註',
+        marked: 'Marked',
+        unmark: 'Unmark',
+        fullScore: 'Full Score',
+        zeroScore: '0 Point',
+        halfRight: 'Half Score',
+        submit: 'Submit',
         setting1: '打分自動切換學生',
         setting2: '完成批閱自動彈出切換',
         setting3: '打分自動切換題目',
@@ -482,13 +482,13 @@ export default {
         noSocreErr: '請先打分',
         completeQu: '當前題目已閱完,請切換題目',
         completeStu: '當前完成當前學生評分,如果繼續評分,請切換學生',
-        noAnswer: '未作答',
-        stuInfoErr: '學生資訊異常',
-        ummarkQu: '未閱題目',
+        noAnswer: 'Not Answered',
+        stuInfoErr: 'Student Information Error',
+        ummarkQu: 'Unmark Questions',
         unmarkContent: '題目尚未評分,是否跳轉到對應題目繼續評分? ',
-        finished: '已閱完',
+        finished: 'Finished Marking',
         noUnMarkStu: '已無未閱學生,請挑選進行中的學生繼續閱卷。 ',
-        completeTask: '您已完成閱卷任務',
+        completeTask: 'You have completed the marking task',
         // ProgPie.vue
         marking: 'In progress'
     }

+ 7 - 7
TEAMModelOS/ClientApp/src/locale/lang/en-US/schoolBaseInfo.js

@@ -116,11 +116,11 @@ export default {
   setStartTitps:'Set as enrollment semester',
   periodCountTips:'The number of school systems is allocated based on school purchases, and schools can only edit school system names, not add or delete school system.',
   cgCountTips:'The number of colleges is allocated based on school purchases, and schools can only edit college names',  
-  addSubjectType:'添加方式',
-  addSubjectType1:'新建學科',
-  addSubjectType2:'選擇已有學科',
-  addSubjectType3:'已有學科',
-  addSubjectType4:'請選擇需要添加的學科',
+  addSubjectType:'Method',
+  addSubjectType1:'New Subject',
+  addSubjectType2:'Select an existing subject',
+  addSubjectType3:'Existing subject',
+  addSubjectType4:'Please select the subject to be added',
 
   // ClassroomSetting.vue
   classroomList: 'Classroom List',
@@ -227,9 +227,9 @@ export default {
   cusTabel: 'Class Schedule',
   setCusTable: 'Set Class Schedule',
   fullRoomInfo:'Please complete the classroom information first!',
-  noSetLabel:'Number setting',
+  noSetLabel:'No. Setting',
   exportQrCode:'Generate List QR Code',
-  exportList:'Generate List',
+  exportList:'Export List',
   setTypes:'Setting items:',
   noLabel:'Seat Number',
   irsLabel:'IRS Number',

+ 1 - 1
TEAMModelOS/ClientApp/src/locale/lang/en-US/stuAccount.js

@@ -131,7 +131,7 @@ export default {
 	// Authorization.vue
 	authTitle: 'Service Authorization Management',
 	authTitle1: 'AClass One Learning Companion Service Authorization',
-	authDiscraption: 'Grant access to the Learning Companion App to students with TEAM Model IDs that are authorized to use the service.',
+	authDiscraption: 'The AClass ONE Learning Companion is licensed to the student account that holds the service license.',
 	authCount: 'Total authorization number of school',
 	alreadyUse: 'Number of authorizations used today',
 	mayUse: 'Number of authorizations available',

+ 12 - 12
TEAMModelOS/ClientApp/src/locale/lang/en-US/studentWeb.js

@@ -192,14 +192,14 @@ export default {
         warning: "Join the course repeatedly!",
         error: "Failed to join the course",
         api: "API Error",
-        noAgree: "課程名單未開放加入",
+        noAgree: "The course is not open to join",
     },
     coursesCardTitle: 'My Course List',
     newAddCourse: 'The latest addition',
     addTime: "Join time",
     missionListCardTitle: 'Activity Task List',
-    missionListCardTitle1: 'Task List',
-    missionListCardTitle2: 'Activity List',
+    missionListCardTitle1: 'Assessment & Homework',
+    missionListCardTitle2: 'Poll & Survey',
     choiceTime: "Filter Time",
     missionListCardPlace: "Default display activities within 30 days",
     missionListCardLoading: 'Loading',
@@ -546,7 +546,7 @@ export default {
             fileView: 'Preview File',
             noReview: 'This file does not support preview, please download and view! ',
             pdfErr: 'Failed to load PDF',
-            noTestAns: '暫無',
+            noTestAns: 'No Answer',
             noMark: 'Not annotated yet',
             noAnalyse: 'No explanation yet',
             noKnowledge: 'No key concept yet',
@@ -638,7 +638,7 @@ export default {
         delOk: "Delete",
         delCancel: "Cancel",
         examError: "There is an issue with the exam file, it cannot be opened properly",
-        dataError: "初始化評測數據异常",
+        dataError: "Abnormalities in obtaining assessment data",
         source: {
             evMode1: 'Online Assessment',
             evMode2: 'Smarter Classroom Assessment',
@@ -699,13 +699,13 @@ export default {
         noanswer: "Not answered",
         dataCount: {
             attendTypeList: [
-                "未點名",
-                "已出席",
-                "缺席",
-                "請假",
-                "病假",
-                "事假",
-                "病假",
+                "Uncalled",
+                "Present",
+                "Absent",
+                "Leave",
+                "Sick",
+                "Personal",
+                "Official",
             ],
             attendTrue: "Present",
             attendFalse: "Absent",

+ 24 - 24
TEAMModelOS/ClientApp/src/locale/lang/en-US/task.js

@@ -35,33 +35,33 @@ export default {
     noMarkTask1:'暫無結束的任務',
     dataCount:'Data Statistics',
     errCount:'Abnormality Statistics',
-    hasHandle:'已處理',
-    handling:'處理中',
-    col1:'學號',
-    col2:'題號',
-    col3:'異常原因',
-    col4:'反饋建議',
-    col5:'狀態',
-    noStuSel:'暫無可選學生',
-    pendingTips:'閱卷任務尚未開始',
-    finishTips:'閱卷任務已結束',
+    hasHandle: 'Processed',
+    handling: 'Unprocessed',
+    col1: 'Student ID',
+    col2: 'Question No.',
+    col3: 'Abnormal Reason',
+    col4: 'Feedback',
+    col5: 'Status',
+    noStuSel: 'No students to choose from yet.',
+    pendingTips: 'Marking task have not yet begun',
+    finishTips: 'Marking task is over',
     myProgress:'My Progress',
     totalProgress:'Overall Progress',
     unhandle:'Unprocessed',
     hasHandle:'Processed',
-    quLable:'題目:',
-    stuId:'學生ID:',
-    reason:'原因:',
-    errStatus1: '已處理',
-    errStatus2: '處理',
-    hanldeErrTitle:'異常處理',
-    stuAnswer:'學生答案:',
-    viewOriginal:'查看原卷',
-    errDesc:'異常描述:',
-    suggestBack:'反饋建議:',
-    suggestHolder:'請輸入反饋建議',
-    handleOk:'處理成功',
-    suggestTips:'請輸入反饋建議',
+    quLable: 'Question No.:',
+    stuId: 'Student ID:',
+    reason: 'Reason:',
+    errStatus1: 'Processed',
+    errStatus2: 'View',
+    hanldeErrTitle: 'Abnormality Handling',
+    stuAnswer: 'Student Answer:',
+    viewOriginal: 'View Exam File',
+    errDesc: 'Abnormal Description:',
+    suggestBack: 'Feedback:',
+    suggestHolder: 'Please enter feedback suggestions',
+    handleOk: 'Handle successfully',
+    suggestTips: 'Please enter feedback suggestions',
     deviation:'誤差控制值',
     deviationContent:'誤差控制值:雙評差值的最大允許值稱為誤差控制值。誤差控制值大於題目滿分的1/6系統自動設置為仲裁卷。 ',
     noArb:'暫無仲裁卷處理',
@@ -72,7 +72,7 @@ export default {
     markScore1:'閱卷分數1: ',
     markScore2:'閱卷分數2: ',
     score:'分',
-    viewMark:'查看批註',
+    viewMark:'View Annotation',
     arbScore:'仲裁分數:',
     arbOk:'Score saved successfully',
     arbAllQu:'Arbitration questions has been processed.',

+ 32 - 33
TEAMModelOS/ClientApp/src/locale/lang/en-US/teachermgmt.js

@@ -265,38 +265,37 @@ export default {
     qrcodeErr: 'Failed to generate QR code',
     confirm: 'Confirm',
     cancel: 'Cancel',
-    filter: '篩選',
-    reset: '重置',
-    teacherStatus1: '未加入',
-    teacherStatus2: '邀請中',
-    teacherStatus3: '已加入',
-    importTips1: '導入教師範本:',
-    importTips2: '欄位說明:',
-    importTips3: '1. name: 教師姓名,必填;',
-    importTips4: '2. phone: 教師手機號,選填;',
-    importTips5: '3. email: 教師郵箱,選填;',
-    importTips6: '4. tmdid: 教師醍摩豆ID,選填;',
-    importTips7: '5. note: 教師備註信息,選填;',
-    importTips8: '溫馨提示:如果導入教師醍摩豆ID,或者導入的手機或郵箱已註冊醍摩豆ID,系統會自動邀請老師加入學校。',
-    importTips9: '點擊或者拖拽文件導入',
-    impText:'無效數據(沒有名字):',
-    impText1: '有效導入數據:',
-    impText2: '僅導入姓名:',
-    impText3: '系統將自動邀請:',
-    impText4: '重新導入',
-    impText5: '確認導入',
-    impText6: '導入成功',
-    impText7: '繼續導入',
-    impText8: '查看教師名單',
-    impTd1: '姓名',
-    impTd2: '手機',
-    impTd3: '郵箱',
-    impTd4: '醍摩豆ID',
-    impTd5: '備註',
-    joinTips1: '溫馨提示:學校存在僅導入名字的老師,如果對應當前老師賬號,可以進行綁定修改教師加入學校的狀態。如果當前老師賬號不為學校導入對應的老師可以不用進行綁定。',
-    joinTips2: '綁定學校尚未加入的老師:',
-    hasLeader: '當前老師已經是組長了',
-    export: '導出名單',
-    teacherList: '教師名單',
+    filter: 'Filter',
+    reset: 'Reset',
+    teacherStatus1: 'Not joined',
+    teacherStatus2: 'Inviting',
+    teacherStatus3: 'Joined',
+    importTips1: 'Import Teacher/Sample:',
+    importTips2: 'Field Description:',
+    importTips3: "1. name: Teacher's name, required",
+    importTips4: "2. phone: Teacher's cellphone number, optional",
+    importTips5: "3. email: Teacher's email, optional",
+    importTips6: "4. tmdid: Teacher's user ID, optional",
+    importTips7: '5. note: Note about the teacher, optional',
+    importTips8: "Tip: If the imported teacher's user ID, cell phone, or email has already registered a TEAM Model account, the system will automatically invite the teacher to join the school.",
+    importTips9: 'Select or drag files to this area to import',
+    impText1: 'No. of imported:',
+    impText2: 'No. of only name is imported:',
+    impText3: 'No. of auto-invite by system:',
+    impText4: 'Re-import',
+    impText5: 'Confirm Import',
+    impText6: 'Imported successfully',
+    impText7: 'Continue Import',
+    impText8: 'View Teacher List',
+    impTd1: 'Name',
+    impTd2: 'Cellphone',
+    impTd3: 'Email',
+    impTd4: 'User ID',
+    impTd5: 'Note',
+    joinTips1: 'Note: If a teacher is imported into the school by name only, the teacher can be bound/modified to join the school after comparing with the current teacher account in the school.',
+    joinTips2: 'Binding teachers who have not yet joined school:',
+    hasLeader: 'This teacher is already a section chief',
+    export: 'Export List',
+    teacherList: 'Teacher List',
     noIpmtData:'暫無可導入數據'
 }

+ 1 - 1
TEAMModelOS/ClientApp/src/locale/lang/en-US/unit.js

@@ -12,7 +12,7 @@ export default {
 	text11: 'point(s)',
 	text12: 'total ',
 	text13: 'No. Of People',
-	text14:'',
+	text14:'',
 	gradeYear: '',
 	minute: 'min(s)',
 	hour: 'hour(s)',

+ 2 - 2
TEAMModelOS/ClientApp/src/locale/lang/zh-TW/learnActivity.js

@@ -316,8 +316,8 @@ export default {
         cc:'及格人數',
         rac:'比率 (人數):',
         noKn:'試卷沒有知識點數據',
-        dataErr:'評數據異常',
-        goingNoData:'評進行中,無法查看統計數據',
+        dataErr:'評數據異常',
+        goingNoData:'評進行中,無法查看統計數據',
         paperErr: '試卷數據異常'
     },
 

+ 2 - 2
TEAMModelOS/ClientApp/src/locale/lang/zh-TW/schoolBaseInfo.js

@@ -116,11 +116,11 @@ export default {
   setStartTitps:'設置為入學期',
   periodCountTips:'學段數量根據學校購買進行分配,學校只能進行編輯學段名稱,不能新增和刪除學段。',
   cgCountTips:'學院數量根據學校購買進行分配,學校只能進行編輯學院名稱,不能新增和刪除學院。',
-  addSubjectType:'添加方式',
+  addSubjectType:'新增方式',
   addSubjectType1:'新建學科',
   addSubjectType2:'選擇已有學科',
   addSubjectType3:'已有學科',
-  addSubjectType4:'請選擇需要添加的學科',
+  addSubjectType4:'請選擇需要新增的學科',
 
   // ClassroomSetting.vue
   classroomList: '教室清單',

+ 6 - 6
TEAMModelOS/ClientApp/src/locale/lang/zh-TW/studentWeb.js

@@ -141,7 +141,7 @@ export default {
         updBadge: '上傳頭像',
         message: {
             mobile: "請輸入手機號碼",
-            mail: "請輸入箱",
+            mail: "請輸入電子信箱",
             ok: "修改成功",
             pw: "密碼輸入錯誤,請重新輸入",
             nameWarning:'姓名不能為空',
@@ -152,13 +152,13 @@ export default {
             mobileErr:'請輸入手機號碼',
             codeWarning:'請輸入驗證碼',
             areaErr:'請選擇區號',
-            emailErr:'請輸入電子箱',
+            emailErr:'請輸入電子箱',
             msgOk:'驗證碼發送成功',
             noMobile:'手機號碼不存在',
             hasReg:'此手機號已注冊',
             msgErr:'簡訊發送失敗',
             emailOk:'郵件發送成功',
-            emailHasReg:'此箱已被注冊',
+            emailHasReg:'此箱已被注冊',
             emailErr:'郵件發送失敗',
             checkTips:'請檢查資訊是否正確',
             updOk:'更新成功',
@@ -198,7 +198,7 @@ export default {
     newAddCourse: '最新加入課程',
     addTime: "加入時間",
     missionListCardTitle: '活動任務清單',
-    missionListCardTitle1: '評測工作任務',
+    missionListCardTitle1: '評量作業任務',
     missionListCardTitle2: '投票問卷活動',
     choiceTime: "篩選時間",
     missionListCardPlace: "預設顯示近30天的活動",
@@ -638,7 +638,7 @@ export default {
         delOk: "刪除",
         delCancel: "取消",
         examError: "試卷存在問題,無法正常打開",
-        dataError: "初始化評測數據异常",
+        dataError: "初始化評量數據異常",
         source: {
             evMode1: '線上自主評量',
             evMode2: '智慧教室評量',
@@ -705,7 +705,7 @@ export default {
                 "請假",
                 "病假",
                 "事假",
-                "假",
+                "假",
             ],
             attendTrue: "已出席",
             attendFalse: "未出席",

+ 8 - 9
TEAMModelOS/ClientApp/src/locale/lang/zh-TW/teachermgmt.js

@@ -273,13 +273,12 @@ export default {
     importTips2:'欄位說明:',
     importTips3:'1. name: 教師姓名,必填;',
     importTips4:'2. phone: 教師手機號,選填;',
-    importTips5:'3. email: 教師箱,選填;',
-    importTips6:'4. tmdid: 教師醍摩豆ID,選填;',
-    importTips7:'5. note: 教師備註信息,選填;',
-    importTips8:'溫馨提示:如果導入教師醍摩豆ID,或者導入的手機或郵箱已註冊醍摩豆ID,系統會自動邀請老師加入學校。',
+    importTips5:'3. email: 教師電子信箱,選填;',
+    importTips6:'4. tmdid: 教師用戶編號,選填;',
+    importTips7:'5. note: 教師備註內容,選填;',
+    importTips8:'溫馨提示:如果導入的教師用戶編號,或者導入的手機或信箱已註冊醍摩豆帳號,系統會自動邀請老師加入學校。',
     importTips9:'點擊或者拖拽文件導入',
-    impText:'無效數據(沒有名字):',
-    impText1:'有效導入數據:',
+    impText1:'導入總人數:',
     impText2:'僅導入姓名:',
     impText3:'系統將自動邀請:',
     impText4:'重新導入',
@@ -289,10 +288,10 @@ export default {
     impText8:'查看教師名單',
     impTd1:'姓名',
     impTd2:'手機',
-    impTd3:'箱',
-    impTd4:'醍摩豆ID',
+    impTd3:'電子信箱',
+    impTd4:'用戶編號',
     impTd5:'備註',
-    joinTips1:'溫馨提示:學校存在僅導入名字的老師,如果對應當前老師賬號,可以進行綁定修改教師加入學校的狀態。如果當前老師賬號不為學校導入對應的老師可以不用進行綁定。',
+    joinTips1:'溫馨提示:學校存在僅導入名字的老師,如果對應當前老師帳號,可以進行綁定修改教師加入學校的狀態。如果當前老師帳號不為學校導入對應的老師可以不用進行綁定。',
     joinTips2:'綁定學校尚未加入的老師:',
     hasLeader:'當前老師已經是組長了',
     export:'導出名單',

+ 3 - 3
TEAMModelOS/ClientApp/src/locale/lang/zh-TW/user.js

@@ -6,7 +6,7 @@ export default{
     setting:'設置',
     psw:'密碼:',
     mobile:'手機號碼',
-    email:'電子箱',
+    email:'電子箱',
     pswErr1:'兩次密碼輸入不一樣',
     oldErr:'請輸入原始密碼',
     pswErr2:'請輸入新密碼',
@@ -14,13 +14,13 @@ export default{
     mobileErr:'請輸入手機號碼',
     codeWarning:'請輸入驗證碼',
     areaErr:'請選擇區號',
-    emailErr:'請輸入電子箱',
+    emailErr:'請輸入電子箱',
     msgOk:'驗證碼發送成功',
     noMobile:'手機號碼不存在',
     hasReg:'此手機號已註冊',
     msgErr:'簡訊發送失敗',
     emailOk:'郵件發送成功',
-    emailHasReg:'此箱已被註冊',
+    emailHasReg:'此箱已被註冊',
     emailErr:'郵件發送失敗',
     checkTips:'請檢查資訊是否正確',
     updOk:'更新成功',

+ 23 - 5
TEAMModelOS/ClientApp/src/view/areaSetting/AreaSetting.vue

@@ -14,11 +14,6 @@
 					</span>
 				</p>
 				<div class="content">
-					<div class="setting-item">
-						<p>单个学时</p>
-						<InputNumber :max="2000" :min="0" v-model="areaSetting.lessonMinutes"></InputNumber>
-						<span> 分钟</span>
-					</div>
 					<div class="setting-item">
 						<p>总体合格需要</p>
 						<InputNumber :max="2000" :min="0" v-model="areaSetting.allTime"></InputNumber>
@@ -28,6 +23,9 @@
 						<p>线上研修合格需要</p>
 						<InputNumber :max="2000" :min="0" v-model="areaSetting.onlineTime"></InputNumber>
 						<span> 学时</span>
+						<p>,每个学时</p>
+						<InputNumber :max="2000" :min="0" :step="0.1" v-model="areaSetting.lessonMinutes"></InputNumber>
+						<span> 分钟</span>
 					</div>
 					<div class="setting-item">
 						<p>线下研修合格需要</p>
@@ -44,6 +42,15 @@
 						<InputNumber :max="2000" :min="0" v-model="areaSetting.classTime"></InputNumber>
 						<span> 学时</span>
 					</div>
+					<div class="setting-item">
+						<p style="margin-right: 10px;">更多自定义设置</p>
+						<i-switch v-model="openCustom"></i-switch>
+					</div>
+					<div class="setting-item" v-if="openCustom">
+						<p>每个能力点需学习最少</p>
+						<InputNumber :max="2000" :min="1" v-model="areaSetting.limitMinutes"></InputNumber>
+						<span> 分钟</span>
+					</div>
 				</div>
 			</div>
 			<div class="setting-block">
@@ -132,6 +139,7 @@
 	export default {
 		data() {
 			return {
+				openCustom:false,
 				newDimensionName: '',
 				addDimensionModal: false,
 				btnLoading: false,
@@ -168,6 +176,13 @@
 				}).then(res => {
 					if (res.setting) {
 						this.areaSetting = res.setting
+						if(res.setting.limitMinutes === -1){
+							this.areaSetting.limitMinutes = 1
+							this.openCustom = false
+						}else{
+							this.openCustom = true
+						}
+						
 					} else {
 						// this.$Message.warning('未查询到设置信息!')
 					}
@@ -177,6 +192,9 @@
 			saveAreaSetting() {
 				this.btnLoading = true
 				this.areaSetting.id = sessionStorage.getItem('areaId')
+				if(!this.openCustom){
+					this.areaSetting.limitMinutes = -1
+				}
 				this.$api.ability.saveAreaSetting(this.areaSetting).then(res => {
 					this.$Message.success('保存成功!')
 					this.btnLoading = false

+ 16 - 8
TEAMModelOS/ClientApp/src/view/assessment/Assessment.vue

@@ -147,9 +147,9 @@
 							<div class="abilities-item" v-for="(item,index) in row.abilities" :key="index">
 								<span class="overflow-text" :title="item.name">{{ item.no }}{{ item.name }}</span>
 								<span style="margin-left: 5px;"><span
-										:class="item.videoTime >= item.limitTime * settingHours.lessonMinutes ? 'color-suc' : 'color-fail'"
-										style="font-weight: bold;font-size: 16px;">{{ Math.min(item.videoTime,item.limitTime * settingHours.lessonMinutes) }}</span>
-									/ {{ item.limitTime * settingHours.lessonMinutes }} 分钟</span>
+										:class="item.videoTime >= getLimitMinutes(item) ? 'color-suc' : 'color-fail'"
+										style="font-weight: bold;font-size: 16px;">{{ Math.min(item.videoTime,getLimitMinutes(item)) }}</span>
+									/ {{ getLimitMinutes(item) }} 分钟</span>
 							</div>
 						</div>
 					</template>
@@ -641,18 +641,21 @@
 		methods: {
 			/* 导出表格数据 */
 			onExportTable(){
-				let header = ['姓名','总学时','线上研修学时','认证材料学时','校本研修学时','课堂实录学时','认证材料需提交数','认证材料未提交数','作业未提交数','课堂实录是否提交']
-				let keys = ['name','totalTime','online','ability','offline','video','abilityCount','noAbilityCount','noHwCount','isSubmitVideo']
+				let header = ['姓名','总学时','线上研修学时','未修满能力点','认证材料学时','校本研修学时','课堂实录学时','认证材料需提交数','认证材料未提交数','未提交认证材料能力点','作业未提交数','课堂实录是否提交']
+				let keys = ['name','totalTime','online','unFinishArr','ability','offline','video','abilityCount','noAbilityCount','noAbilityNoArr','noHwCount','isSubmitVideo']
+				console.log(this.assessmentList)
 				let datas = this.assessmentList.map(i => {
 					return {
 						name:i.userInfo.name,
 						totalTime:i.totalTime,
-						online:i.hoursArr[0],
-						ability:i.hoursArr[1],
-						offline:i.hoursArr[2],
+						online:i.hoursArr[1],
+						unFinishArr:i.abilities.filter(j => j.videoTime < this.getLimitMinutes(j)).map(k => k.no).join(','),
+						ability:i.hoursArr[2],
+						offline:i.hoursArr[0],
 						video:i.hoursArr[3],
 						abilityCount:i.abilities.length,
 						noAbilityCount:i.abilities.filter(i => i.zpscore === -1).length,
+						noAbilityNoArr:i.abilities.filter(j => j.zpscore === -1).map(k => k.no).join(','),
 						noHwCount:i.trains.filter(item => item.haswork && !item.url).length,
 						isSubmitVideo:i.video ? '已提交':'未提交'
 					}
@@ -1193,6 +1196,11 @@
 			}
 		},
 		computed: {
+			getLimitMinutes(){
+				return item => {
+					return this.settingHours.limitMinutes === -1 ? (item.limitTime * this.settingHours.lessonMinutes) : this.settingHours.limitMinutes
+				}
+			},
 			/* 判断当前区是否对接省平台 */
 			hasAreaAccess(){
 				return sessionStorage.getItem('areaAccess') && Number(sessionStorage.getItem('areaAccess')) === 1

+ 1 - 1
TEAMModelOS/Controllers/Both/GroupListController.cs

@@ -745,7 +745,7 @@ namespace TEAMModelOS.Controllers
                                 students.Add(item);
                             }     
                             ///行政班(学生搜寻classId动态返回)class
-                            List<RMember> smembers = students.Where(x => x.classId.Equals(clazz.id)).Select(y => new RMember { nickname = y.name, id = y.id, code = $"{_code}", name = y.name, type = 2, picture = y.picture, no = y.no,classId=y.classId, groupId = y.groupId, groupName = y.groupName }).ToList();
+                            List<RMember> smembers = students.Where(x => x.classId.Equals(clazz.id)).Select(y => new RMember {  id = y.id, code = $"{_code}", name = y.name, type = 2, picture = y.picture, no = y.no,classId=y.classId, groupId = y.groupId, groupName = y.groupName }).ToList();
                             groupList = new RGroupList
                             {
                                 id=clazz.id,

+ 42 - 1
TEAMModelOS/Controllers/Teacher/FavoriteController.cs

@@ -15,6 +15,7 @@ using TEAMModelOS.SDK.Extension;
 using TEAMModelOS.SDK.Models.Cosmos;
 using TEAMModelOS.SDK.Models.Cosmos.Common;
 using TEAMModelOS.SDK;
+using TEAMModelOS.SDK.Models;
 
 namespace TEAMModelOS.Controllers
 {
@@ -60,6 +61,24 @@ namespace TEAMModelOS.Controllers
                 request.pk = "Favorite";
                 request.code = request.code.StartsWith("Favorite-") ? request.code : request.pk + "-" + request.code;
                 request.ttl = -1;
+                if (request.type.Equals("LessonRecord")) {
+                    string tableName = "";
+                    if (request.scope.Equals("private"))
+                    {
+                        tableName = Constant.Teacher;
+                    }
+                    else   
+                    {
+                        tableName = Constant.School;
+                    }
+                    try {
+                        LessonRecord lessonRecord = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, tableName).ReadItemAsync<LessonRecord>(request.id, new PartitionKey(request.fromCode));
+                        lessonRecord.favorite = 1;
+                        await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, tableName).ReplaceItemAsync<LessonRecord>(lessonRecord, request.id, new PartitionKey(request.fromCode));
+                    } catch (CosmosException ) { 
+                        
+                    }
+                }
                 long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
                 request.createTime = now;
                 request = await client.GetContainer(Constant.TEAMModelOS, "Teacher").UpsertItemAsync(request, new PartitionKey($"{request.code}"));
@@ -116,7 +135,29 @@ namespace TEAMModelOS.Controllers
                 var client = _azureCosmos.GetCosmosClient();
                 if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
                 if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
-                var room = await client.GetContainer(Constant.TEAMModelOS, "Teacher").DeleteItemAsync<Favorite>(id.GetString(), new PartitionKey($"Favorite-{code}"));
+                Favorite favorite = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<Favorite>(id.GetString(), new PartitionKey($"Favorite-{code}"));
+                if (favorite.type.Equals("LessonRecord"))
+                {
+                    string tableName = "";
+                    if (favorite.scope.Equals("private"))
+                    {
+                        tableName = Constant.Teacher;
+                    }
+                    else
+                    {
+                        tableName = Constant.School;
+                    }
+                    try
+                    {
+                        LessonRecord lessonRecord = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, tableName).ReadItemAsync<LessonRecord>(favorite.id, new PartitionKey(favorite.fromCode));
+                        lessonRecord.favorite = 0;
+                        await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, tableName).ReplaceItemAsync<LessonRecord>(lessonRecord, favorite.id, new PartitionKey(favorite.fromCode));
+                    }
+                    catch (CosmosException)
+                    {
+                    }
+                }
+                favorite = await client.GetContainer(Constant.TEAMModelOS, "Teacher").DeleteItemAsync<Favorite>(id.GetString(), new PartitionKey($"Favorite-{code}"));
                 return Ok(new { status=200});
             }
             catch (Exception ex)

+ 3 - 3
TEAMModelOS/TEAMModelOS.csproj

@@ -32,9 +32,9 @@
     <SpaRoot>ClientApp\</SpaRoot>
     <DefaultItemExcludes>$(DefaultItemExcludes);$(SpaRoot)node_modules\**</DefaultItemExcludes>
     <UserSecretsId>078b5d89-7d90-4f6a-88fc-7d96025990a8</UserSecretsId>
-    <Version>5.2204.18</Version>
-    <AssemblyVersion>5.2204.18.1</AssemblyVersion>
-    <FileVersion>5.2204.18.1</FileVersion>
+    <Version>5.2204.20</Version>
+    <AssemblyVersion>5.2204.20.1</AssemblyVersion>
+    <FileVersion>5.2204.20.1</FileVersion>
     <Description>TEAMModelOS(IES5)</Description>
     <PackageReleaseNotes>6.0版本说明</PackageReleaseNotes>
     <PackageId>TEAMModelOS</PackageId>