浏览代码

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

CrazyIter_Bin 3 年之前
父节点
当前提交
cd9a865cd9
共有 28 个文件被更改,包括 2109 次插入318 次删除
  1. 1 1
      TEAMModelBI/ClientApp/public/index.html
  2. 18 3
      TEAMModelBI/ClientApp/src/api/index.js
  3. 二进制
      TEAMModelBI/ClientApp/src/assets/img/increase.png
  4. 二进制
      TEAMModelBI/ClientApp/src/assets/img/international.png
  5. 二进制
      TEAMModelBI/ClientApp/src/assets/img/mainland.png
  6. 34 10
      TEAMModelBI/ClientApp/src/router/index.js
  7. 28 53
      TEAMModelBI/ClientApp/src/view/common/aside.vue
  8. 205 91
      TEAMModelBI/ClientApp/src/view/systemConfig/correlation.vue
  9. 420 8
      TEAMModelBI/ClientApp/src/view/systemConfig/index.vue
  10. 119 16
      TEAMModelBI/ClientApp/src/view/systemConfig/operate.vue
  11. 22 6
      TEAMModelBI/ClientApp/src/view/systemConfig/setAdmin.vue
  12. 198 78
      TEAMModelBI/ClientApp/src/view/systemConfig/website.vue
  13. 48 11
      TEAMModelBI/ClientApp/src/view/teachermanage/manage.vue
  14. 3 3
      TEAMModelBI/Controllers/Census/ActivitySticsController.cs
  15. 7 1
      TEAMModelBI/Controllers/DingDingStruc/SystemConfigController.cs
  16. 4 1
      TEAMModelBI/Models/SysConfig.cs
  17. 1 1
      TEAMModelOS/ClientApp/src/locale/lang/en-US/cusMgt.js
  18. 1 1
      TEAMModelOS/ClientApp/src/locale/lang/zh-CN/cusMgt.js
  19. 1 1
      TEAMModelOS/ClientApp/src/locale/lang/zh-TW/cusMgt.js
  20. 5 5
      TEAMModelOS/ClientApp/src/static/Global.js
  21. 4 3
      TEAMModelOS/ClientApp/src/view/classrecord/ClassRecord.less
  22. 4 0
      TEAMModelOS/ClientApp/src/view/classrecord/ClassRecord.vue
  23. 260 23
      TEAMModelOS/ClientApp/src/view/classrecord/eventchart/Exam.vue
  24. 116 0
      TEAMModelOS/ClientApp/src/view/classrecord/eventchart/ExamGrade.vue
  25. 208 0
      TEAMModelOS/ClientApp/src/view/classrecord/eventchart/ExamQu.vue
  26. 400 0
      TEAMModelOS/ClientApp/src/view/classrecord/eventchart/ExamTable.vue
  27. 0 1
      TEAMModelOS/ClientApp/src/view/learnactivity/ExamMgt.vue
  28. 2 1
      TEAMModelOS/ClientApp/src/view/learnactivity/tabs/DataView.vue

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

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

+ 18 - 3
TEAMModelBI/ClientApp/src/api/index.js

@@ -49,6 +49,13 @@ export default {
     setisAdmin(data) {
     setisAdmin(data) {
         return post('/tabledd/set-backend', data)
         return post('/tabledd/set-backend', data)
     },
     },
+    //为用户设置关联学校或删除
+    setAistschool(data) {
+        return post('/schoolcheck/set-aistschool', data)
+    },
+
+
+
     //获取区域内的微能力点
     //获取区域内的微能力点
     getCapacity(data) {
     getCapacity(data) {
         return post('/batcharea/get-areas', data)
         return post('/batcharea/get-areas', data)
@@ -225,11 +232,11 @@ export default {
     //系统配置
     //系统配置
     //站点配置
     //站点配置
     getSystemConfig(data) {
     getSystemConfig(data) {
-        return post('/syscfg/get-config', data)
+        return post('/syscfg/get-allconfig', data)
     },
     },
-    //修改系统配置信息
+    //修改系统配置信息or添加新站点
     updateSystemconfig(data) {
     updateSystemconfig(data) {
-        return post('/syscfg/set-config', data)
+        return post('/syscfg/set-singleconfig', data)
     },
     },
     //搜素人员
     //搜素人员
     searchPersonnel(data) {
     searchPersonnel(data) {
@@ -239,8 +246,16 @@ export default {
     removeAdmin(data) {
     removeAdmin(data) {
         return post('/tabledd/set-backend', data)
         return post('/tabledd/set-backend', data)
     },
     },
+    //切换站点
+    cutSitesInfo(data) {
+        return post('/syscfg/cut-site', data)
+    },
     //添加系统管理员
     //添加系统管理员
     addAdmin(data) {
     addAdmin(data) {
         return post('/tabledd/set-tmdadmin', data)
         return post('/tabledd/set-tmdadmin', data)
+    },
+    //变更BI权限和身份
+    setRolesandPower(data) {
+        return post('/tabledd/set-rolesper', data)
     }
     }
 }
 }

二进制
TEAMModelBI/ClientApp/src/assets/img/increase.png


二进制
TEAMModelBI/ClientApp/src/assets/img/international.png


二进制
TEAMModelBI/ClientApp/src/assets/img/mainland.png


+ 34 - 10
TEAMModelBI/ClientApp/src/router/index.js

@@ -8,6 +8,7 @@ const routes = [{
     {
     {
         path: "/login",
         path: "/login",
         name: "login",
         name: "login",
+        roles: "all",
         component: () => require.ensure([], (require) => require(`@/view/login.vue`))
         component: () => require.ensure([], (require) => require(`@/view/login.vue`))
     },
     },
     // {
     // {
@@ -23,79 +24,88 @@ const routes = [{
                 name: "index",
                 name: "index",
                 path: "index",
                 path: "index",
                 permission: "teacher-read|teacher-upd",
                 permission: "teacher-read|teacher-upd",
-                menuName: "teachermgmt",
+                roles: ['all'],
                 isShow: true,
                 isShow: true,
                 component: () => require.ensure([], (require) => require(`@/view/index/dashboard.vue`))
                 component: () => require.ensure([], (require) => require(`@/view/index/dashboard.vue`))
             },
             },
+            //系统配置
             {
             {
                 name: "system",
                 name: "system",
                 path: "system",
                 path: "system",
                 permission: "batcharea-read|batcharea-upd|batchschool-read|batchschool-upd",
                 permission: "batcharea-read|batcharea-upd|batchschool-read|batchschool-upd",
-                menuName: "",
+                roles: ['admin'],
                 isShow: true,
                 isShow: true,
                 component: () => require.ensure([], (require) => require(`@/view/systemConfig/index.vue`))
                 component: () => require.ensure([], (require) => require(`@/view/systemConfig/index.vue`))
             },
             },
+            //人员管理
             {
             {
                 name: "peopleManagement",
                 name: "peopleManagement",
                 path: "teach",
                 path: "teach",
                 permission: "teacher-read|teacher-upd",
                 permission: "teacher-read|teacher-upd",
-                menuName: "teachermgmt",
+                roles: ['admin'],
                 isShow: true,
                 isShow: true,
                 component: () => require.ensure([], (require) => require(`@/view/teachermanage/manage.vue`))
                 component: () => require.ensure([], (require) => require(`@/view/teachermanage/manage.vue`))
             },
             },
+            //区校管理(学区管理)--研发部
             {
             {
                 name: "areaManagement",
                 name: "areaManagement",
                 path: "areamanage",
                 path: "areamanage",
                 permission: "teacher-read|teacher-upd",
                 permission: "teacher-read|teacher-upd",
-                menuName: "teachermgmt",
+                roles: ['special'],
                 isShow: true,
                 isShow: true,
                 component: () => require.ensure([], (require) => require(`@/view/areaServe/index.vue`))
                 component: () => require.ensure([], (require) => require(`@/view/areaServe/index.vue`))
             },
             },
+            //区校管理(学校管理)--研发部
             {
             {
                 name: "schoolManagement",
                 name: "schoolManagement",
                 path: "schoolmanage",
                 path: "schoolmanage",
                 permission: "teacher-read|teacher-upd",
                 permission: "teacher-read|teacher-upd",
-                menuName: "teachermgmt",
+                roles: ['special'],
                 isShow: true,
                 isShow: true,
                 component: () => require.ensure([], (require) => require(`@/view/schoolServe/index.vue`))
                 component: () => require.ensure([], (require) => require(`@/view/schoolServe/index.vue`))
             },
             },
+            //所有学校列表,待定。
             {
             {
                 name: "schoolset",
                 name: "schoolset",
                 path: "schoolset",
                 path: "schoolset",
                 permission: "teacher-read|teacher-upd",
                 permission: "teacher-read|teacher-upd",
-                menuName: "teachermgmt",
+                roles: ['all'],
                 isShow: true,
                 isShow: true,
                 component: () => require.ensure([], (require) => require(`@/view/schoolServe/school.vue`))
                 component: () => require.ensure([], (require) => require(`@/view/schoolServe/school.vue`))
             },
             },
+            //服务智慧教室统计,待定。
             {
             {
                 name: "impower",
                 name: "impower",
                 path: "impower",
                 path: "impower",
                 permission: "teacher-read|teacher-upd",
                 permission: "teacher-read|teacher-upd",
-                menuName: "teachermgmt",
+                roles: ['all'],
                 isShow: true,
                 isShow: true,
                 component: () => require.ensure([], (require) => require(`@/view/schoolServe/accredit.vue`))
                 component: () => require.ensure([], (require) => require(`@/view/schoolServe/accredit.vue`))
             },
             },
+            //区校管理(微能力点管理)--研发部
             {
             {
                 name: "abilityManagement",
                 name: "abilityManagement",
                 path: "traitmanage",
                 path: "traitmanage",
                 permission: "teacher-read|teacher-upd",
                 permission: "teacher-read|teacher-upd",
-                menuName: "teachermgmt",
+                roles: ['special'],
                 isShow: true,
                 isShow: true,
                 component: () => require.ensure([], (require) => require(`@/view/teachermanage/traitmanage.vue`))
                 component: () => require.ensure([], (require) => require(`@/view/teachermanage/traitmanage.vue`))
             },
             },
+            //创建学区学校 ---研发部
             {
             {
                 name: "created",
                 name: "created",
                 path: "created",
                 path: "created",
                 permission: "batcharea-read|batcharea-upd|batchschool-read|batchschool-upd",
                 permission: "batcharea-read|batcharea-upd|batchschool-read|batchschool-upd",
-                menuName: "",
+                roles: ['special'],
                 isShow: true,
                 isShow: true,
                 component: () => require.ensure([], (require) => require(`@/view/created/created.vue`))
                 component: () => require.ensure([], (require) => require(`@/view/created/created.vue`))
             },
             },
+            //日志
             {
             {
                 name: "log",
                 name: "log",
                 path: "log",
                 path: "log",
                 permission: "batcharea-read|batcharea-upd|batchschool-read|batchschool-upd",
                 permission: "batcharea-read|batcharea-upd|batchschool-read|batchschool-upd",
-                menuName: "",
+                roles: ['admin'],
                 isShow: true,
                 isShow: true,
                 component: () => require.ensure([], (require) => require(`@/view/index/operateLog.vue`))
                 component: () => require.ensure([], (require) => require(`@/view/index/operateLog.vue`))
             },
             },
@@ -119,6 +129,20 @@ router.beforeEach((to, from, next) => {
     if (!recordUser || !token) return next('/login')
     if (!recordUser || !token) return next('/login')
     let time = Date.parse(new Date()) / 1000
     let time = Date.parse(new Date()) / 1000
     if (time > token.exp) return next('/login')
     if (time > token.exp) return next('/login')
+        // let homes = routes[2]
+        // let state = function() {
+        //     for (let i in token.roles) {
+        //         let name = token.roles[i]
+        //         for (let y in homes.children) {
+        //             if (homes.children[y].roles.includes(name)) {
+        //                 return true
+        //             } else {
+        //                 return false
+        //             }
+        //         }
+        //     }
+        // }
+        // if (to.path && state) { next() } else { next('/404') }
     next()
     next()
 })
 })
 console.log("-------路由-------", router);
 console.log("-------路由-------", router);

+ 28 - 53
TEAMModelBI/ClientApp/src/view/common/aside.vue

@@ -4,50 +4,22 @@
             <img src="@/assets/img/logox.png">
             <img src="@/assets/img/logox.png">
         </div>
         </div>
         <el-aside :width="menuWidth">
         <el-aside :width="menuWidth">
-            <!-- <el-radio-group v-model="isCollapse" style="margin-bottom: 20px">
-                <el-radio-button :label="false" @click="menuWidth=200+'px';isCollapse=false" v-show="isCollapse ==true"><i class="el-icon-s-unfold"></i></el-radio-button>
-                <el-radio-button :label="true" @click="menuWidth=64+'px';isCollapse=true" v-show="isCollapse ==false"><i class="el-icon-s-fold"></i></el-radio-button>
-            </el-radio-group> -->
-            <!-- <el-menu :default-active="indexMenu" class="el-menu-vertical-demo" :collapse="isCollapse" @select="handleSelect" v-for="(item,index) in menuList" :key="index" :collapse-transition="locksetting" background-color="#1d1e23" text-color="#fff">
-                <el-sub-menu :index="index" v-if="item.child.length">
-                    <template #title>
-                        <svg class="icon" aria-hidden="true">
-                            <use :xlink:href="item.icon"></use>
-                        </svg>
-                        <span>{{item.name}}</span>
-                    </template>
-                    <el-menu-item :index="index+'-'+indexs" v-for="(items,indexs) in item.child" :key="indexs">
-                        <div @click="routerskip(items.router)">
-                            <svg class="icon" aria-hidden="true">
-                                <use :xlink:href="items.icon"></use>
-                            </svg>
-                            {{items.name}}
-                        </div>
-                    </el-menu-item>
-                </el-sub-menu>
-                <el-menu-item :index="index" v-else>
-                    <svg class="icon" aria-hidden="true">
-                        <use :xlink:href="item.icon"></use>
-                    </svg>
-                    <span @click="routerskip(item.router)">{{item.name}}</span>
-                </el-menu-item>
-            </el-menu> -->
-            <el-menu :default-active="indexMenu" :default-openeds="opens" class="el-menu-vertical-demo" :collapse="isCollapse" @select="handleSelect" :collapse-transition="locksetting" background-color="#1d1e23" text-color="#fff" unique-opened="true">
-                <div v-for="(item,index) in menuList" :key="index" class="menu-title">
-                    <el-menu-item :index="index" v-if="!item.child.length">
+            <el-menu :default-active="currentRoutePath" :default-openeds="opens" class="el-menu-vertical-demo" :collapse="isCollapse" @select="handleSelect" :collapse-transition="locksetting" background-color="#1d1e23" text-color="#fff" unique-opened="true">
+                <div v-for="item in menuList" :key="item.sort" class="menu-title">
+                    <el-menu-item v-if="!item.child.length" :index="item.router">
                         <svg class="icon" aria-hidden="true">
                         <svg class="icon" aria-hidden="true">
                             <use :xlink:href="item.icon"></use>
                             <use :xlink:href="item.icon"></use>
                         </svg>
                         </svg>
                         <span @click="routerskip(item.router)">{{item.name}}</span>
                         <span @click="routerskip(item.router)">{{item.name}}</span>
                     </el-menu-item>
                     </el-menu-item>
-                    <el-sub-menu :index="index" v-else>
+                    <el-sub-menu :index="item.sort" v-else>
                         <template #title>
                         <template #title>
                             <svg class="icon" aria-hidden="true">
                             <svg class="icon" aria-hidden="true">
                                 <use :xlink:href="item.icon"></use>
                                 <use :xlink:href="item.icon"></use>
                             </svg>
                             </svg>
                             {{item.name}}
                             {{item.name}}
                         </template>
                         </template>
-                        <el-menu-item :index="index+'-'+indexs" v-for="(items,indexs) in item.child" :key="indexs">
+                        <el-menu-item v-for="items in item.child" :key="items.sort" :index="items.router">
                             <div @click="routerskip(items.router)" class="subordinate">
                             <div @click="routerskip(items.router)" class="subordinate">
                                 <svg class="icon" aria-hidden="true">
                                 <svg class="icon" aria-hidden="true">
                                     <use :xlink:href="items.icon"></use>
                                     <use :xlink:href="items.icon"></use>
@@ -70,7 +42,7 @@
 //基础菜单
 //基础菜单
 
 
 import { Location, Document, Menu as IconMenu, Setting } from '@element-plus/icons'
 import { Location, Document, Menu as IconMenu, Setting } from '@element-plus/icons'
-import { getCurrentInstance, ref, watch, onMounted, reactive } from 'vue'
+import { getCurrentInstance, ref, watch, onMounted, reactive, toRefs } from 'vue'
 import { useStore } from 'vuex'
 import { useStore } from 'vuex'
 import { useRouter } from 'vue-router'
 import { useRouter } from 'vue-router'
 import router from '@/router/index.js'
 import router from '@/router/index.js'
@@ -114,6 +86,7 @@ export default {
                         icon: '#icon-peizhi-xitongpeizhi',
                         icon: '#icon-peizhi-xitongpeizhi',
                         permission: ['orgusers-read', 'orgusers-upd'],
                         permission: ['orgusers-read', 'orgusers-upd'],
                         isShow: true,
                         isShow: true,
+                        sort: 2,
                     },
                     },
                     {
                     {
                         name: proxy.$t(`menu.personnel`),
                         name: proxy.$t(`menu.personnel`),
@@ -121,6 +94,7 @@ export default {
                         icon: '#icon-chengyuanguanli',
                         icon: '#icon-chengyuanguanli',
                         permission: ['orgusers-read', 'orgusers-upd'],
                         permission: ['orgusers-read', 'orgusers-upd'],
                         isShow: true,
                         isShow: true,
+                        sort: 3,
                     },
                     },
                     {
                     {
                         name: '操作日志',
                         name: '操作日志',
@@ -128,6 +102,7 @@ export default {
                         icon: '#icon-rizhi1',
                         icon: '#icon-rizhi1',
                         permission: [],
                         permission: [],
                         isShow: true,
                         isShow: true,
+                        sort: 4,
                     },
                     },
                 ],
                 ],
             },
             },
@@ -138,6 +113,7 @@ export default {
                 icon: '#icon-zisunchaquyufenbu',
                 icon: '#icon-zisunchaquyufenbu',
                 permission: ['batcharea-read', 'batcharea-upd'],
                 permission: ['batcharea-read', 'batcharea-upd'],
                 isShow: true,
                 isShow: true,
+                sort: 5,
                 child: [
                 child: [
                     {
                     {
                         name: '学区管理',
                         name: '学区管理',
@@ -145,6 +121,7 @@ export default {
                         icon: '#icon-quyuguanli',
                         icon: '#icon-quyuguanli',
                         permission: ['orgusers-read', 'orgusers-upd'],
                         permission: ['orgusers-read', 'orgusers-upd'],
                         isShow: true,
                         isShow: true,
+                        sort: 6,
                     },
                     },
                     {
                     {
                         name: '学校管理',
                         name: '学校管理',
@@ -152,6 +129,7 @@ export default {
                         icon: '#icon-pingtai_xuexiaoguanli',
                         icon: '#icon-pingtai_xuexiaoguanli',
                         permission: ['orgusers-read', 'orgusers-upd'],
                         permission: ['orgusers-read', 'orgusers-upd'],
                         isShow: true,
                         isShow: true,
+                        sort: 7,
                     },
                     },
                     {
                     {
                         name: '微能力管理',
                         name: '微能力管理',
@@ -159,9 +137,9 @@ export default {
                         icon: '#icon-peizhiguanli',
                         icon: '#icon-peizhiguanli',
                         permission: ['orgusers-read', 'orgusers-upd'],
                         permission: ['orgusers-read', 'orgusers-upd'],
                         isShow: true,
                         isShow: true,
+                        sort: 8,
                     },
                     },
                 ],
                 ],
-                sort: 2,
             },
             },
             // {
             // {
             //     name: '学校服务',
             //     name: '学校服务',
@@ -222,7 +200,7 @@ export default {
                 role: ['admin', 'assist'],
                 role: ['admin', 'assist'],
                 isShow: true,
                 isShow: true,
                 permission: '',
                 permission: '',
-                sort: 5,
+                sort: 9,
                 child: [
                 child: [
                     {
                     {
                         name: '学区情况',
                         name: '学区情况',
@@ -230,6 +208,7 @@ export default {
                         icon: '#icon-xiangmufanwei',
                         icon: '#icon-xiangmufanwei',
                         permission: [],
                         permission: [],
                         isShow: true,
                         isShow: true,
+                        sort: 10,
                     },
                     },
                     {
                     {
                         name: '学校情况',
                         name: '学校情况',
@@ -237,6 +216,7 @@ export default {
                         icon: '#icon-xuexiao2',
                         icon: '#icon-xuexiao2',
                         permission: [],
                         permission: [],
                         isShow: true,
                         isShow: true,
+                        sort: 11,
                     },
                     },
                 ],
                 ],
             },
             },
@@ -246,8 +226,7 @@ export default {
         const shenfen = ref('admin')
         const shenfen = ref('admin')
         //路由
         //路由
         const routers = useRouter()
         const routers = useRouter()
-        let indexMenu = ref(0)
-        let indexsinfo = ref()
+        let indexMenu = reactive({ currentRoutePath: routers.currentRoute.value.path })
         let lockState = ref(true)
         let lockState = ref(true)
         let locktitle = ref(proxy.$t(`menu.lock`))
         let locktitle = ref(proxy.$t(`menu.lock`))
         let lockicon = ref('#icon-weisuoding-copy')
         let lockicon = ref('#icon-weisuoding-copy')
@@ -284,15 +263,19 @@ export default {
             //         }
             //         }
             //     }
             //     }
             // }
             // }
+
+            //身份
             let userRoles = user.roles
             let userRoles = user.roles
             console.log(userRoles)
             console.log(userRoles)
             for (let n in userRoles) {
             for (let n in userRoles) {
                 let name = userRoles[n]
                 let name = userRoles[n]
+                console.log(name)
                 for (let i in schoolMenus) {
                 for (let i in schoolMenus) {
-                    console.log(schoolMenus[i].role.includes(userRoles), schoolMenus[i].role)
-                    schoolMenus[i].role.includes('all') ? menuList.value.push(schoolMenus[i]) : ''
+                    schoolMenus[i].role.indexOf('all') != -1 ? menuList.value.push(schoolMenus[i]) : ''
                     schoolMenus[i].role.includes(name) ? menuList.value.push(schoolMenus[i]) : ''
                     schoolMenus[i].role.includes(name) ? menuList.value.push(schoolMenus[i]) : ''
-                    user.azp ? menuList.value.push(schoolMenus[i]) : ''
+                    user.azp && schoolMenus[i].router == '/home/areamanage' ? menuList.value.push(schoolMenus[i]) : ''
+                    console.log(schoolMenus[i].role.includes(name), schoolMenus[i].role, schoolMenus[i])
+                    schoolMenus[i].router
                 }
                 }
             }
             }
             var result = []
             var result = []
@@ -311,17 +294,9 @@ export default {
                 return 0
                 return 0
             })
             })
             console.log(menuList.value, result, '菜单')
             console.log(menuList.value, result, '菜单')
-            var timer = null
-            // btn.onmouseover = btn.onmouseover = function () {
-            //     isCollapse.value = false
-            //     menuWidth.value = 200 + 'px'
-            //     console.log('11111111111')
-            // }
-            // btn.onmouseout = btn.onmouseout = function () {
-            //     isCollapse.value = !isCollapse.value
-            //     menuWidth.value = 64 + 'px'
-            //     console.log('22222')
-            // }
+            //router内容
+            let nowUrl = routers.currentRoute.value.path
+            console.log(nowUrl, '现在url')
         })
         })
         watch(
         watch(
             store.state,
             store.state,
@@ -400,7 +375,7 @@ export default {
             lockMenu,
             lockMenu,
             lockicon,
             lockicon,
             locksetting,
             locksetting,
-            indexMenu,
+            ...toRefs(indexMenu),
             routers,
             routers,
             activeIndex,
             activeIndex,
             opens,
             opens,

+ 205 - 91
TEAMModelBI/ClientApp/src/view/systemConfig/correlation.vue

@@ -3,38 +3,58 @@
         <div class="nowuser">
         <div class="nowuser">
             <p class="correlationbox-title">当前操作用户:</p>
             <p class="correlationbox-title">当前操作用户:</p>
             <div class="userlist">
             <div class="userlist">
-                <PersonalPhoto style="cursor: pointer;" name="陈明洋" width="40px" height="40px" fontSize="12px" class="pigpicture"></PersonalPhoto>
-                <p class="userlist-name">陈明洋</p>
+                <div class="photobox">
+                    <PersonalPhoto style="cursor: pointer;" :name="nowUsers.name" width="40px" height="40px" fontSize="12px" class="pigpicture" v-if="!nowUsers.picture"></PersonalPhoto>
+                    <el-image style="width: 40px; height: 40px;border-radius:50%" :src="nowUsers.picture" fit="fill" v-else></el-image>
+                </div>
+                <div class="userlist-name">{{nowUsers.name}}({{nowUsers.mobile}})</div>
             </div>
             </div>
         </div>
         </div>
         <p class="correlationbox-title">目前用户所关联学校:</p>
         <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="目前顾问" />
+        <div class="possessbox" v-if="nowUsers.handleSchools.length >0">
+            <el-table :data="nowUsers.handleSchools" style="width: 100%" height="20vh" size="small">
+                <el-table-column :label="$t(`personnelManagement.personnelTable.headportrait`)" align="center">
+                    <template #default="scope">
+                        <el-image style="width: 40px; height: 40px;" :src="scope.row.picture" fit="fill"></el-image>
+                    </template>
+                </el-table-column>
+                <el-table-column fixed prop="name" label="名称" />
+                <el-table-column prop="id" label="学校简码" />
+                <!-- <el-table-column prop="name" label="版本" />
+                <el-table-column prop="name" label="目前顾问" /> -->
                 <el-table-column fixed="right" label="操作" width='80'>
                 <el-table-column fixed="right" label="操作" width='80'>
                     <template #default="scope">
                     <template #default="scope">
-                        <el-button type="text" size="small" @click="removeSchool(scope.$index,tableData)">取消关联</el-button>
+                        <el-button type="text" size="small" @click="removeSchool(scope.row,scope.$index)">取消关联</el-button>
                     </template>
                     </template>
                 </el-table-column>
                 </el-table-column>
             </el-table>
             </el-table>
         </div>
         </div>
-        <div class="nodata" v-else-if="tableDatas.length ==0">
+        <div class="nodata" v-else-if="nowUsers.handleSchools.length ===0">
             <div>暂无关联学校</div>
             <div>暂无关联学校</div>
         </div>
         </div>
         <div class="school-list">
         <div class="school-list">
-            <p class="correlationbox-title">学校列表:</p>
+            <div class="school-list-header">
+                <div class="correlationbox-titles">学校列表:</div>
+                <div class="correlationbox-btn">
+                    <el-button type="primary" size="small" v-if="multipleSchool.length >0" @click="multipleCorrelation">关联选中学校</el-button>
+                    <el-button type="primary" size="small" v-else-if="multipleSchool.length ===0" disabled>关联选中学校</el-button>
+                </div>
+            </div>
             <div class="listbox">
             <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 :data="tableData" style="width: 100%" height="40vh" size="small" @selection-change="checkSchool">
+                    <el-table-column type="selection" />
+                    <el-table-column :label="$t(`personnelManagement.personnelTable.headportrait`)" align="center">
+                        <template #default="scope">
+                            <el-image style="width: 40px; height: 40px;" :src="scope.row.picture" fit="fill"></el-image>
+                        </template>
+                    </el-table-column>
+                    <el-table-column fixed prop="name" label="名称" />
+                    <el-table-column prop="id" label="学校简码" />
+                    <!-- <el-table-column prop="name" label="版本" /> -->
+                    <el-table-column prop="assisName" label="目前顾问" />
                     <el-table-column fixed="right" label="操作" width='80'>
                     <el-table-column fixed="right" label="操作" width='80'>
                         <template #default="scope">
                         <template #default="scope">
-                            <el-button type="text" size="small" @click="correlation(scope.$index,tableData)">关联学校</el-button>
+                            <el-button type="text" size="small" @click="correlation(scope.row,tableData)">关联学校</el-button>
                         </template>
                         </template>
                     </el-table-column>
                     </el-table-column>
                 </el-table>
                 </el-table>
@@ -43,98 +63,154 @@
     </div>
     </div>
 </template>
 </template>
 <script>
 <script>
-import { ref, getCurrentInstance } from 'vue'
+import { ref, getCurrentInstance, watch } from 'vue'
 import { ElMessage, ElLoading, ElMessageBox } from 'element-plus'
 import { ElMessage, ElLoading, ElMessageBox } from 'element-plus'
 export default {
 export default {
-    setup() {
+    props: {
+        userdata: {
+            type: Object,
+            default: () => {},
+        },
+    },
+    setup(props) {
         let { proxy } = getCurrentInstance()
         let { proxy } = getCurrentInstance()
         const tableDatas = ref([])
         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',
-            },
-        ]
+        let tableData = ref([])
+        let nowUsers = ref()
+        let multipleSchool = ref([])
+        function getSchoolList() {
+            proxy.$api
+                .getSchooldata({})
+                .then((res) => {
+                    console.log(res, '学校的返回列表')
+                    // res.state === 200 ? (tableData.value = res.schoolAssists) : ''
+                    if (res.state === 200) {
+                        for (let i in res.schoolAssists) {
+                            if (res.schoolAssists[i].assists) {
+                                res.schoolAssists[i].assisName = ''
+                                let datas = res.schoolAssists[i].assists
+                                for (let y in datas) {
+                                    res.schoolAssists[i].assisName = res.schoolAssists[i].assisName + datas[y].tmdName + ','
+                                }
+                            }
+                        }
+                        tableData.value = res.schoolAssists
+                        processingSchool()
+                    }
+                })
+                .catch((err) => {
+                    ElMessage.error('获取学校列表失败')
+                })
+        }
         function correlation(value, data) {
         function correlation(value, data) {
-            ElMessageBox.confirm(`请问您确定将 用户123 设为 成都锦江区外国语小学 顾问,进行数据关联吗 ?`, '关联学校', {
+            console.log(value, data)
+            ElMessageBox.confirm(`请问您确定将 ${nowUsers.value.name} 设为 ${value.name} 顾问,进行数据关联吗 ?`, '关联学校', {
                 confirmButtonText: proxy.$t(`commonMsg.confirm`),
                 confirmButtonText: proxy.$t(`commonMsg.confirm`),
                 cancelButtonText: proxy.$t(`commonMsg.closes`),
                 cancelButtonText: proxy.$t(`commonMsg.closes`),
                 type: 'success',
                 type: 'success',
                 center: true,
                 center: true,
             }).then(() => {
             }).then(() => {
-                tableDatas.value.push({
-                    date: '2016-05-01',
-                    name: 'Tom',
-                    address: 'No. 189, Grove St, Los Angeles',
-                })
-                ElMessage.success('操作成功')
+                let schoolArr = [value.id]
+                let data = { partitionKey: nowUsers.value.partitionKey, userId: nowUsers.value.userId, tmdId: nowUsers.value.tmdId, schoolIds: schoolArr, busy: 'add' }
+                proxy.$api
+                    .setAistschool(data)
+                    .then((res) => {
+                        console.log(res, '成功的返回')
+                        res.state === 200
+                            ? (nowUsers.value.handleSchools.push(value), getSchoolList(), processingSchool(), ElMessage.success('操作成功'))
+                            : res.state === 201
+                            ? (ElMessage.success('已关联,请勿重复操作'), getSchoolList())
+                            : ''
+                    })
+                    .catch((error) => {
+                        ElMessage.error('关联失败,API异常')
+                    })
             })
             })
         }
         }
-        function removeSchool(value, data) {
-            console.log(value, data)
-            ElMessageBox.confirm(`请问您确定将 用户123 与 成都锦江区外国语小学 取消关联吗 ?`, '取消关联', {
+        function removeSchool(value, index) {
+            console.log(value, index)
+            ElMessageBox.confirm(`请问您确定将 ${nowUsers.value.name} 与 ${value.name} 取消关联吗 ?`, '取消关联', {
                 confirmButtonText: proxy.$t(`commonMsg.confirm`),
                 confirmButtonText: proxy.$t(`commonMsg.confirm`),
                 cancelButtonText: proxy.$t(`commonMsg.closes`),
                 cancelButtonText: proxy.$t(`commonMsg.closes`),
                 type: 'error',
                 type: 'error',
                 center: true,
                 center: true,
             }).then(() => {
             }).then(() => {
-                tableDatas.value.splice(value, 1)
-                console.log(tableDatas)
-                ElMessage.success('操作成功')
+                let schoolArr = [value.id]
+                let data = { partitionKey: nowUsers.value.partitionKey, userId: nowUsers.value.userId, tmdId: nowUsers.value.tmdId, schoolIds: schoolArr, busy: 'del' }
+                proxy.$api
+                    .setAistschool(data)
+                    .then((res) => {
+                        res.state === 200 ? (nowUsers.value.handleSchools.splice(index, 1), getSchoolList(), processingSchool(), ElMessage.success('操作成功')) : ''
+                    })
+                    .catch((error) => {
+                        ElMessage.error('取消关联失败,API异常')
+                    })
             })
             })
         }
         }
-        return { tableData, tableDatas, correlation, removeSchool }
+        function checkSchool(value, row) {
+            multipleSchool.value = value
+            console.log(multipleSchool.value, '111')
+        }
+        function multipleCorrelation() {
+            let schoolData = multipleSchool.value
+            let schoolName = ''
+            if (schoolData.length < 5) {
+                schoolData.forEach((item) => {
+                    schoolName = schoolName + ',' + item.name
+                })
+            } else {
+                for (let i = 0; i < 5; i++) {
+                    schoolName = schoolName + ',' + schoolData[i].name
+                }
+                schoolName = schoolName + '等...'
+            }
+            ElMessageBox.confirm(`请问您确定将 ${nowUsers.value.name} 设为 ${schoolName} 学校的顾问,进行数据关联吗 ?`, '关联学校', {
+                confirmButtonText: proxy.$t(`commonMsg.confirm`),
+                cancelButtonText: proxy.$t(`commonMsg.closes`),
+                type: 'success',
+                center: true,
+            }).then(() => {
+                let schoolArr = []
+                for (let i in schoolData) {
+                    schoolArr.push(schoolData[i].id)
+                }
+                let data = { partitionKey: nowUsers.value.partitionKey, userId: nowUsers.value.userId, tmdId: nowUsers.value.tmdId, schoolIds: schoolArr, busy: 'add' }
+                proxy.$api
+                    .setAistschool(data)
+                    .then((res) => {
+                        console.log(res, '成功的返回')
+                        res.state === 200
+                            ? ((nowUsers.value.handleSchools = nowUsers.value.handleSchools.concat(schoolData)), getSchoolList(), processingSchool(), ElMessage.success('操作成功'))
+                            : res.state === 201
+                            ? (ElMessage.success('已关联,请勿重复操作'), getSchoolList())
+                            : ''
+                    })
+                    .catch((error) => {
+                        ElMessage.error('关联失败,API异常')
+                    })
+            })
+        }
+        function processingSchool() {
+            let allSchool = tableData.value
+            let handleSchools = nowUsers.value.handleSchools
+            for (let i in handleSchools) {
+                let schoolInfo = handleSchools[i].id
+                for (let s in allSchool) {
+                    allSchool[s].id === schoolInfo ? allSchool.splice(s, 1) : ''
+                }
+            }
+            tableData.value = allSchool
+        }
+        watch(
+            props,
+            (newuser) => {
+                newuser ? (nowUsers.value = newuser.userdata) : ''
+                console.log(nowUsers.value, '触发监听')
+            },
+            { immediate: true, deep: true }
+        )
+        getSchoolList()
+        return { tableData, tableDatas, correlation, removeSchool, nowUsers, getSchoolList, checkSchool, multipleSchool, multipleCorrelation, processingSchool }
     },
     },
 }
 }
 </script>
 </script>
@@ -170,11 +246,49 @@ export default {
     font-weight: 700;
     font-weight: 700;
 }
 }
 .userlist {
 .userlist {
-    width: 20%;
+    width: 100%;
     text-align: center;
     text-align: center;
+    display: flex;
+    justify-content: center;
+    align-items: center;
 }
 }
 .userlist-name {
 .userlist-name {
     font-size: 14px;
     font-size: 14px;
     color: #7f8c8d;
     color: #7f8c8d;
 }
 }
+.photobox {
+    display: inline-block;
+    width: 20%;
+    vertical-align: top;
+}
+.userlist-name {
+    text-align: left;
+    display: inline-block;
+    width: 45%;
+    vertical-align: top;
+    line-height: 40px;
+    margin-left: 0%;
+    font-size: 18px;
+}
+.school-list-header {
+    width: 100%;
+    display: flex;
+    justify-content: space-between;
+}
+.correlationbox-titles {
+    width: 50%;
+    font-size: 14px;
+    color: #b2bec3;
+    text-align: left;
+}
+.correlationbox-btn {
+    width: 50%;
+    text-align: right;
+}
+</style>
+<style>
+.school-list-header .el-button--small {
+    min-height: 25px;
+    padding: 7px 10px;
+}
 </style>
 </style>

+ 420 - 8
TEAMModelBI/ClientApp/src/view/systemConfig/index.vue

@@ -3,7 +3,27 @@
         <div class="systembox-tabs">
         <div class="systembox-tabs">
             <el-tabs v-model="activeName" class="demo-tabs">
             <el-tabs v-model="activeName" class="demo-tabs">
                 <el-tab-pane label="站点配置" name="websites">
                 <el-tab-pane label="站点配置" name="websites">
-                    <Website></Website>
+                    <div v-if="modelShow=='choice'">
+                        <p class="titles">选择站点:</p>
+                        <div class="choicebox">
+                            <div class="choicebox-frame">
+                                <div class="particularsbox" v-for="item in siteLists" @click="changeSite(item)">
+                                    <div class="particularsbox-img">
+                                        <el-image style="width: 200px; height: 300px" :src="item.img" fit="fill" />
+                                    </div>
+                                    <div class="particularsbox-name"><span>{{item.nickName}}</span></div>
+                                    <div class="now-pitch" v-if="nowcurrentSysConfig.site === item.site"><span>当前站点</span></div>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                    <Website v-else-if="modelShow=='details'" :siteValue="siteValue" @changemodels="backisinfo" @state="backState"></Website>
+                    <div class="addSitebtn" @click="dialogVisible=true" v-if="modelShow=='choice'">
+                        <el-button type="success" size="small">新增站点</el-button>
+                    </div>
+                    <div class="cutSitebtn" @click="cutsiteSHow=true" v-if="modelShow=='choice'">
+                        <el-button type="primary" size="small">切换站点</el-button>
+                    </div>
                 </el-tab-pane>
                 </el-tab-pane>
                 <el-tab-pane label="系统管理者" name="admin">
                 <el-tab-pane label="系统管理者" name="admin">
                     <SetAdmin></SetAdmin>
                     <SetAdmin></SetAdmin>
@@ -11,9 +31,111 @@
             </el-tabs>
             </el-tabs>
         </div>
         </div>
     </div>
     </div>
+    <div class="created-site">
+        <el-dialog v-model="dialogVisible" title="创建站点" width="50%" :close="emptyData()">
+            <div class="created-site-form">
+                <el-form :model="form" label-width="120px">
+                    <el-form-item label="站点名称">
+                        <el-input v-model="form.site" />
+                    </el-form-item>
+                    <el-form-item label="站点别名">
+                        <el-input v-model="form.nickname" />
+                    </el-form-item>
+                    <el-form-item label="工程模式/部门ID">
+                        <el-input v-model="form.proDeptId" />
+                    </el-form-item>
+                    <!-- <el-form-item label="站点地址">
+                        <el-input v-model="form.name" />
+                    </el-form-item> -->
+                    <el-form-item label="连接内容:">
+                        <div class="database-add">
+                            <el-form :model="form.clientKey" label-width="140px" size="small">
+                                <el-form-item label="clientID">
+                                    <el-input v-model="form.clientKey.clientID" type="textarea" />
+                                </el-form-item>
+                                <el-form-item label="clientSecret:">
+                                    <el-input v-model="form.clientKey.clientSecret" type="textarea" />
+                                </el-form-item>
+                            </el-form>
+                        </div>
+                    </el-form-item>
+                    <el-form-item label="钉钉密钥:">
+                        <div class="database-add">
+                            <el-form :model="form.dDAuth" label-width="140px" size="small">
+                                <el-form-item label="Agentld:" class="dingding-Id">
+                                    <el-input v-model="form.dDAuth.agentId" />
+                                </el-form-item>
+                                <el-form-item label="appKey:" class="dingding-Key">
+                                    <el-input v-model="form.dDAuth.appKey" />
+                                </el-form-item>
+                                <el-form-item label="appSecret:" class="dingding-appSecret">
+                                    <el-input v-model="form.dDAuth.appSecret" type="textarea" :rows="4" />
+                                </el-form-item>
+                            </el-form>
+                        </div>
+                    </el-form-item>
+                    <el-form-item label="数据库:">
+                        <div class="database-add">
+                            <el-form :model="form.azureClient" label-width="140px" size="small">
+                                <p class="database-title">Blob</p>
+                                <el-form-item label="ConnectionString">
+                                    <el-input v-model="form.azureClient.storage" type="textarea" />
+                                </el-form-item>
+                                <p class="database-title">CosmosDB</p>
+                                <el-form-item label="ConnectionString:">
+                                    <el-input v-model="form.azureClient.cosmos" type="textarea" />
+                                </el-form-item>
+                                <p class="database-title">Redis</p>
+                                <el-form-item label="ConnectionString:">
+                                    <el-input v-model="form.azureClient.redis" type="textarea" />
+                                </el-form-item>
+                                <p class="database-title">服务地址</p>
+                                <el-form-item label="ConnectionString:">
+                                    <el-input v-model="form.azureClient.servicBus" type="textarea" />
+                                </el-form-item>
+                            </el-form>
+                        </div>
+                    </el-form-item>
+                    <!-- <el-form-item>
+                        <el-button>新增配置信息</el-button>
+                    </el-form-item> -->
+                </el-form>
+            </div>
+            <template #footer>
+                <span class="dialog-footer">
+                    <el-button @click="dialogVisible = false">取消</el-button>
+                    <el-button type="primary" @click="addSite()">确认</el-button>
+                </span>
+            </template>
+        </el-dialog>
+    </div>
+    <div class="cut-site">
+        <el-dialog v-model="cutsiteSHow" title="切换站点" width="60%">
+            <div class="nowtitle"><span>当前站点:</span>{{nowcurrentSysConfig.site}}<span class="site-nickname">别名:</span>{{nowcurrentSysConfig.nickName}}</div>
+            <div class="choicebox">
+                <div class="cut-choicebox-frame">
+                    <div class="particularsbox" v-for="(item,index) in siteLists" @click="cutsites(item,index)">
+                        <div class="particularsbox-img">
+                            <el-image style="width: 100px; height: 150px" :src="item.img" fit="fill" />
+                        </div>
+                        <div class="cut-particularsbox-name"><span>{{item.nickName}}</span></div>
+                        <div class="pitchs" v-if="nowcurrentSysConfig.site === item.site"><span>当前站点</span></div>
+                        <div class="pitch-site" v-if="pitchNum===index && nowcurrentSysConfig.site !== item.site"><span>选中站点</span></div>
+                    </div>
+                </div>
+            </div>
+            <template #footer>
+                <span class="dialog-footer">
+                    <el-button @click="cutsiteSHow = false">取消</el-button>
+                    <el-button type="primary" @click="confirmCut">确认</el-button>
+                </span>
+            </template>
+        </el-dialog>
+    </div>
 </template>
 </template>
 <script>
 <script>
-import { ref } from 'vue'
+import { ref, reactive, getCurrentInstance } from 'vue'
+import { ElMessage, ElLoading } from 'element-plus'
 import Website from './website.vue'
 import Website from './website.vue'
 import SetAdmin from './setAdmin.vue'
 import SetAdmin from './setAdmin.vue'
 export default {
 export default {
@@ -22,8 +144,149 @@ export default {
         SetAdmin,
         SetAdmin,
     },
     },
     setup() {
     setup() {
+        let { proxy } = getCurrentInstance()
         let activeName = ref('websites')
         let activeName = ref('websites')
-        return { activeName }
+        let modelShow = ref('choice')
+        let siteLists = ref([
+            { id: 1, title: '大陆站(测试)', img: require('@/assets/img/mainland.png'), key: 'mainland' },
+            { id: 2, title: '国际站(测试)', img: require('@/assets/img/international.png'), key: 'international' },
+            { id: 3, title: '大陆站', img: require('@/assets/img/mainland.png'), key: 'mainland' },
+            { id: 4, title: '国际站', img: require('@/assets/img/international.png'), key: 'international' },
+            // { id: 3, title: '新增站点', img: require('@/assets/img/increase.png'), key: 'add' },
+        ])
+        let imgArr = ref([
+            { id: 1, img: require('@/assets/img/mainland.png') },
+            { id: 2, img: require('@/assets/img/international.png') },
+            { id: 3, img: require('@/assets/img/mainland.png') },
+            { id: 4, img: require('@/assets/img/international.png') },
+            { id: 5, img: require('@/assets/img/mainland.png') },
+            { id: 6, img: require('@/assets/img/international.png') },
+        ])
+        let siteValue = ref('')
+        let dialogVisible = ref(false)
+        let cutsiteSHow = ref(false)
+        let pitchNum = ref(-1)
+        let nowcurrentSysConfig = ref({
+            site: '',
+        })
+        let nowpitchSite = ref()
+        let form = ref({
+            site: '',
+            nickname: '',
+            proDeptId: '',
+            clientKey: {
+                clientID: '',
+                clientSecret: '',
+            },
+            dDAuth: {
+                agentId: '',
+                appKey: '',
+                appSecret: '',
+            },
+            azureClient: {
+                storage: '',
+                cosmosDB: '',
+                redis: '',
+                servicBus: '',
+            },
+        })
+        function getData() {
+            proxy.$api
+                .getSystemConfig({})
+                .then((res) => {
+                    console.log(res, '配置返回')
+                    if (res.state === 200) {
+                        for (let i in res.allConfigs) {
+                            res.allConfigs[i].img = imgArr.value[i].img
+                        }
+                        nowcurrentSysConfig.value = res.currentSysConfig
+                        siteLists.value = res.allConfigs
+                    }
+                })
+                .catch((res) => {
+                    ElMessage.error('获取系统配置API异常')
+                })
+        }
+        function changeSite(value) {
+            siteValue.value = value
+            modelShow.value = 'details'
+        }
+        function backisinfo(value) {
+            console.log(value, '进入方法1111')
+            modelShow.value = value
+        }
+        function backState(value) {
+            // siteLists.value = value
+            getData()
+        }
+        function addSite() {
+            let addForm = form.value
+            proxy.$api
+                .updateSystemconfig(addForm)
+                .then((res) => {
+                    console.log(res, '返回')
+                    if (res.state === 200) {
+                        for (let i in res.allConfigs) {
+                            res.allConfigs[i].img = imgArr.value[i].img
+                        }
+                        siteLists.value = res.allConfigs
+                        ElMessage.success('创建成功')
+                    }
+                })
+                .catch((err) => {
+                    ElMessage.error('创建新站点API异常')
+                })
+        }
+        //添加数据 关闭,清空数据
+        function emptyData() {
+            form.value.site = ''
+            form.value.nickname = ''
+            form.value.proDeptId = ''
+            form.value.clientKey.client = ''
+            form.value.clientKey.clientSecret = ''
+            form.value.dDAuth.agentId = ''
+            form.value.dDAuth.appKey = ''
+            form.value.dDAuth.appSecret = ''
+            form.value.azureClient.storage = ''
+            form.value.azureClient.cosmosDB = ''
+            form.value.azureClient.redis = ''
+            form.value.azureClient.serviceBus = ''
+        }
+        function cutsites(value, index) {
+            pitchNum.value = index
+            nowpitchSite.value = value
+        }
+        function confirmCut() {
+            let data = { site: nowpitchSite.value.site }
+            proxy.$api
+                .cutSitesInfo(data)
+                .then((res) => {
+                    res.state === 200 ? ((nowcurrentSysConfig.value = res.sysConfig), ElMessage.success('站点切换成功')) : ''
+                })
+                .catch((error) => {
+                    ElMessage.error('API异常,站点切换失败')
+                })
+        }
+        getData()
+        return {
+            activeName,
+            modelShow,
+            siteLists,
+            changeSite,
+            siteValue,
+            backisinfo,
+            dialogVisible,
+            form,
+            getData,
+            emptyData,
+            addSite,
+            backState,
+            cutsiteSHow,
+            nowcurrentSysConfig,
+            cutsites,
+            pitchNum,
+            confirmCut,
+        }
     },
     },
 }
 }
 </script>
 </script>
@@ -31,16 +294,146 @@ export default {
 .systembox {
 .systembox {
     width: 100%;
     width: 100%;
     line-height: 20px;
     line-height: 20px;
+    position: relative;
 }
 }
 .systembox-tabs {
 .systembox-tabs {
     width: 100%;
     width: 100%;
 }
 }
-/* .demo-tabs > .el-tabs__content {
-    padding: 32px;
-    color: #6b778c;
-    font-size: 32px;
+.choicebox {
+    width: 100%;
+    height: 100%;
+    padding: 1%;
+    text-align: left;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    overflow-x: auto;
+}
+.choicebox-frame {
+    width: 70%;
+    height: 70vh;
+    border: 1px solid #ccc;
+    display: flex;
+    justify-content: space-around;
+    align-items: center;
+}
+.cut-choicebox-frame {
+    width: 100%;
+    height: 55vh;
+    border: 1px solid #ccc;
+    display: flex;
+    justify-content: space-around;
+    align-items: center;
+}
+.particularsbox {
+    width: 20%;
+    height: 70%;
+    text-align: center;
+    border: 1px solid #ccc;
+    border-radius: 10px;
+    transform: all 0.8s ease-in-out;
+    cursor: pointer;
+    position: relative;
+    overflow: hidden;
+}
+.particularsbox-img {
+    width: 100%;
+    height: 70%;
+    display: block;
+}
+.particularsbox-img {
+    margin-top: 20%;
+}
+.particularsbox-name {
+    font-size: 16px;
     font-weight: 600;
     font-weight: 600;
-} */
+    margin-top: 10%;
+}
+.cut-particularsbox-name {
+    font-size: 16px;
+    font-weight: 600;
+    line-height: 20px;
+}
+.particularsbox:hover {
+    transform: translateY(-15px);
+    box-shadow: 0px 5px 8px #ccc;
+    background: #fff;
+}
+.titles {
+    font-size: 18px;
+    font-weight: 600;
+    margin-top: 1.5%;
+}
+.created-site {
+    width: 100%;
+    /* height: 50vh; */
+    line-height: 20px;
+    overflow: hidden;
+}
+.created-site-form {
+    width: 95%;
+    text-align: left;
+}
+.database-add {
+    width: 100%;
+    padding: 1%;
+    border: 1px solid #ccc;
+    border-radius: 5px;
+}
+.addSitebtn {
+    position: absolute;
+    top: 3%;
+    right: 1%;
+}
+.cutSitebtn {
+    position: absolute;
+    top: 3%;
+    left: 1%;
+}
+.cut-site {
+    width: 100%;
+}
+.pitch-site {
+    height: 20px;
+    line-height: 18px;
+    width: 100%;
+    background-color: #2ed573;
+    font-size: 12px;
+    position: absolute;
+    top: 4%;
+    color: #fff;
+}
+.pitchs {
+    height: 20px;
+    line-height: 18px;
+    width: 100%;
+    background-color: #0984e3;
+    font-size: 12px;
+    position: absolute;
+    top: 4%;
+    color: #fff;
+}
+.nowtitle {
+    font-size: 14px;
+    text-align: left;
+    line-height: 18px;
+    padding-left: 1%;
+}
+.site-nickname {
+    margin-left: 5%;
+}
+.now-pitch {
+    height: 24px;
+    line-height: 24px;
+    width: 100px;
+    background-color: #0984e3;
+    font-size: 12px;
+    position: absolute;
+    top: 3%;
+    right: -10%;
+    color: #fff;
+    transform: rotate(45deg);
+}
 </style>
 </style>
 <style>
 <style>
 .systembox .el-tabs__header {
 .systembox .el-tabs__header {
@@ -53,4 +446,23 @@ export default {
 .systembox .el-tabs__nav-wrap {
 .systembox .el-tabs__nav-wrap {
     padding-left: 15px;
     padding-left: 15px;
 }
 }
+.backbtn .el-button--small {
+    height: 30px;
+    padding: 5px 15px;
+}
+.created-site .el-dialog__header,
+.cut-site .el-dialog__header {
+    line-height: 20px;
+}
+.created-site .el-dialog,
+.cut-site .el-dialog {
+    height: 80vh;
+    overflow: auto;
+}
+.cut-site .el-dialog__footer {
+    line-height: 20px;
+}
+.cut-site .el-dialog {
+    background-color: #e9eef3;
+}
 </style>
 </style>

+ 119 - 16
TEAMModelBI/ClientApp/src/view/systemConfig/operate.vue

@@ -3,14 +3,17 @@
         <div class="nowuser">
         <div class="nowuser">
             <p class="identitybox-title">当前操作用户:</p>
             <p class="identitybox-title">当前操作用户:</p>
             <div class="userlist">
             <div class="userlist">
-                <PersonalPhoto style="cursor: pointer;" name="陈明洋" width="40px" height="40px" fontSize="12px" class="pigpicture"></PersonalPhoto>
-                <p class="userlist-name">陈明洋</p>
+                <div class="photobox">
+                    <PersonalPhoto style="cursor: pointer;" :name="nowUsers.name" width="40px" height="40px" fontSize="12px" class="pigpicture" v-if="!nowUsers.picture"></PersonalPhoto>
+                    <el-image style="width: 40px; height: 40px;border-radius:50%" :src="nowUsers.picture" fit="fill" v-else></el-image>
+                </div>
+                <div class="userlist-name">{{nowUsers.name}}({{nowUsers.mobile}})</div>
             </div>
             </div>
         </div>
         </div>
         <div class="identitybox">
         <div class="identitybox">
             <p class="identitybox-title">当前身份:</p>
             <p class="identitybox-title">当前身份:</p>
             <div class="identitybox-select">
             <div class="identitybox-select">
-                <el-select v-model="value" size="small" placeholder="当前身份">
+                <el-select v-model="identityValue" size="small" placeholder="当前身份" multiple @change="changeIdentity">
                     <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
                     <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
                 </el-select>
                 </el-select>
             </div>
             </div>
@@ -22,7 +25,7 @@
                 <div class="authority-block-item" v-for="(items,indexs) in item.children" :key="indexs">
                 <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-name">{{items.name}}</div>
                     <div class="authority-block-item-state">
                     <div class="authority-block-item-state">
-                        <el-switch v-model="items.state" />
+                        <el-switch v-model="items.state" @change="changeAuthority" />
                     </div>
                     </div>
                 </div>
                 </div>
             </div>
             </div>
@@ -30,10 +33,20 @@
     </div>
     </div>
 </template>
 </template>
 <script>
 <script>
-import { ref } from 'vue'
+import { ref, watch, getCurrentInstance } from 'vue'
+import { ElMessage, ElLoading, ElMessageBox } from 'element-plus'
 export default {
 export default {
-    setup() {
-        const value = ref('')
+    emits: ['changeShow'],
+    props: {
+        userdata: {
+            type: Object,
+            default: () => {},
+        },
+    },
+    setup(props, context) {
+        console.log(props)
+        let { proxy } = getCurrentInstance()
+        const identityValue = ref([])
         const options = [
         const options = [
             {
             {
                 value: 'channelcrew',
                 value: 'channelcrew',
@@ -44,7 +57,7 @@ export default {
                 label: '销售',
                 label: '销售',
             },
             },
             {
             {
-                value: 'counselor',
+                value: 'assist',
                 label: '顾问',
                 label: '顾问',
             },
             },
             // {
             // {
@@ -60,7 +73,8 @@ export default {
                 label: '系统管理员',
                 label: '系统管理员',
             },
             },
         ]
         ]
-        const authorityList = [
+
+        let authorityList = ref([
             // { id: 1, name: '系统配置', children: [{ id: 1 - 1, name: '操作系统配置', key: '123456', state: false }] },
             // { id: 1, name: '系统配置', children: [{ id: 1 - 1, name: '操作系统配置', key: '123456', state: false }] },
             // {
             // {
             //     id: 2,
             //     id: 2,
@@ -74,20 +88,92 @@ export default {
                 id: 3,
                 id: 3,
                 name: '学区情况',
                 name: '学区情况',
                 children: [
                 children: [
-                    { id: 3 - 1, name: '查看学区数据信息', key: '123456', state: false },
-                    { id: 3 - 2, name: '修改学区相关信息', key: '123456', state: false },
+                    { id: 3 - 1, name: '查看学区数据信息', key: 'areadata-read', state: false },
+                    { id: 3 - 2, name: '修改学区相关信息', key: 'areadata-upd', state: false },
                 ],
                 ],
             },
             },
             {
             {
                 id: 4,
                 id: 4,
                 name: '学校情况',
                 name: '学校情况',
                 children: [
                 children: [
-                    { id: 4 - 1, name: '查看学校数据信息', key: '123456', state: false },
-                    { id: 4 - 2, name: '修改学校相关信息', key: '123456', state: false },
+                    { id: 4 - 1, name: '查看学校数据信息', key: 'schooldata-read', state: false },
+                    { id: 4 - 2, name: '修改学校相关信息', key: 'schooldata-upd', state: false },
                 ],
                 ],
             },
             },
-        ]
-        return { value, options, authorityList }
+        ])
+        let nowUsers = ref()
+        let nowAuthority = ref([])
+        let nowIdentity = ref([])
+        function init() {
+            let userInfo = nowUsers.value.handlePermissions
+            console.log(userInfo)
+            for (let i in userInfo) {
+                let authorityName = userInfo[i]
+                for (let y in authorityList.value) {
+                    let listData = authorityList.value[y].children
+                    for (let e in listData) {
+                        listData[e].key === authorityName ? (listData[e].state = true) : ''
+                    }
+                }
+            }
+        }
+        function initialize() {
+            for (let y in authorityList.value) {
+                let listData = authorityList.value[y].children
+                listData.map((x) => (x.state = false))
+            }
+            for (let i in nowUsers.value.handleRoles) {
+                let role = nowUsers.value.handleRoles[i]
+                for (let u in options) {
+                    options[u].value === role ? identityValue.value.push(options[u].value) : ''
+                }
+            }
+            identityValue.value = [...new Set(identityValue.value)]
+            nowAuthority.value = []
+            nowIdentity.value = []
+        }
+        function changeIdentity(value) {
+            console.log(value)
+            nowIdentity.value = value
+            console.log(identityValue.value)
+            context.emit('changeShow', true)
+        }
+        function changeAuthority(value) {
+            console.log(value)
+            for (let i in authorityList.value) {
+                let data = authorityList.value[i].children
+                for (let u in data) {
+                    data[u].state === true ? nowAuthority.value.push(data[u].key) : ''
+                }
+            }
+            context.emit('changeShow', true)
+            nowAuthority.value = [...new Set(nowAuthority.value)]
+        }
+        function notarizeChange() {
+            changeAuthority()
+            console.log('触发子组件的修改方法')
+            let rolesinfo = identityValue.value
+            let permissionsinfo = nowAuthority.value
+            let data = { partitionKey: nowUsers.value.partitionKey, user: nowUsers.value.userId, tmdId: nowUsers.value.tmdId, permissions: permissionsinfo, roles: rolesinfo }
+            proxy.$api
+                .setRolesandPower(data)
+                .then((res) => {
+                    console.log(res, '变更返回')
+                    res.state === 200 ? (ElMessage.success('保存成功'), context.emit('changeShow', false)) : ElMessage.error('变更保存失败')
+                })
+                .catch((err) => {
+                    ElMessage.error('变更API保存失败')
+                })
+        }
+        watch(
+            props,
+            (newuser) => {
+                newuser ? (nowUsers.value = newuser.userdata) : ''
+                initialize(), init()
+            },
+            { immediate: true, deep: true }
+        )
+        return { identityValue, options, authorityList, nowUsers, init, changeIdentity, changeAuthority, notarizeChange }
     },
     },
 }
 }
 </script>
 </script>
@@ -140,13 +226,30 @@ export default {
     padding: 1% 0%;
     padding: 1% 0%;
 }
 }
 .userlist {
 .userlist {
-    width: 20%;
+    width: 100%;
     text-align: center;
     text-align: center;
+    display: flex;
+    justify-content: center;
+    align-items: center;
 }
 }
 .userlist-name {
 .userlist-name {
     font-size: 14px;
     font-size: 14px;
     color: #7f8c8d;
     color: #7f8c8d;
 }
 }
+.photobox {
+    display: inline-block;
+    width: 20%;
+    vertical-align: top;
+}
+.userlist-name {
+    text-align: left;
+    display: inline-block;
+    width: 45%;
+    vertical-align: top;
+    line-height: 40px;
+    margin-left: 0%;
+    font-size: 18px;
+}
 </style>
 </style>
 <style>
 <style>
 .identitybox-select .el-select--small {
 .identitybox-select .el-select--small {

+ 22 - 6
TEAMModelBI/ClientApp/src/view/systemConfig/setAdmin.vue

@@ -40,6 +40,9 @@
                                 <use xlink:href="#icon-sousuotianchong"></use>
                                 <use xlink:href="#icon-sousuotianchong"></use>
                             </svg>
                             </svg>
                         </div>
                         </div>
+                        <div class="serachbox-notdata" v-if="searchNodata">
+                            <p>未搜索到相关用户信息,请检验后重新输入搜索</p>
+                        </div>
                         <div class="submitbtn">
                         <div class="submitbtn">
                             <el-button type="primary" size="small" @click=serachPersonnel(adminfilter) class="anewbox-btn blue">搜索人员</el-button>
                             <el-button type="primary" size="small" @click=serachPersonnel(adminfilter) class="anewbox-btn blue">搜索人员</el-button>
                         </div>
                         </div>
@@ -78,6 +81,7 @@ export default {
         let { proxy } = getCurrentInstance()
         let { proxy } = getCurrentInstance()
         let searchData = ref()
         let searchData = ref()
         let searchState = ref(false)
         let searchState = ref(false)
+        let searchNodata = ref(false)
         function getAdmin() {
         function getAdmin() {
             let data = { busy: 'admin' }
             let data = { busy: 'admin' }
             proxy.$api
             proxy.$api
@@ -95,7 +99,11 @@ export default {
             proxy.$api
             proxy.$api
                 .searchPersonnel(data)
                 .searchPersonnel(data)
                 .then((res) => {
                 .then((res) => {
-                    res.state === 200 && res.infos.length !== 0 ? ((searchData.value = res.infos[0]), (searchState.value = true)) : ''
+                    res.state === 200 && res.infos.length !== 0
+                        ? ((searchData.value = res.infos[0]), (searchState.value = true), (searchNodata.value = false))
+                        : res.state === 200 && res.infos.length === 0
+                        ? (searchNodata.value = true)
+                        : ''
                 })
                 })
                 .catch((err) => {
                 .catch((err) => {
                     ElMessage.error('人员搜索异常')
                     ElMessage.error('人员搜索异常')
@@ -135,7 +143,7 @@ export default {
                 })
                 })
         }
         }
         getAdmin()
         getAdmin()
-        return { adminfilter, adminData, getAdmin, serachPersonnel, searchData, searchState, removeadmin, addAdmin }
+        return { adminfilter, adminData, getAdmin, serachPersonnel, searchData, searchState, removeadmin, addAdmin, searchNodata }
     },
     },
 }
 }
 </script>
 </script>
@@ -158,7 +166,7 @@ export default {
     font-size: 14px;
     font-size: 14px;
     color: #636e72;
     color: #636e72;
     line-height: 40px;
     line-height: 40px;
-    padding-left: 1%;
+    padding-left: 2%;
     text-align: left;
     text-align: left;
 }
 }
 .list-item {
 .list-item {
@@ -301,7 +309,7 @@ export default {
     color: #74b9ff;
     color: #74b9ff;
 }
 }
 .submitbtn {
 .submitbtn {
-    margin-top: 10%;
+    margin-top: 5%;
 }
 }
 .list-item-photo {
 .list-item-photo {
     width: 20%;
     width: 20%;
@@ -342,19 +350,27 @@ export default {
     width: 200px;
     width: 200px;
     background-color: #00a8ff;
     background-color: #00a8ff;
 }
 }
+.serachbox-notdata p {
+    width: 100%;
+    font-size: 14px;
+    color: red;
+    margin-bottom: 5px;
+    margin-top: 10px;
+}
 </style>
 </style>
 <style>
 <style>
-.search-box .el-input__inner {
+.admin-text-box .search-box .el-input__inner {
     opacity: 1;
     opacity: 1;
     width: 100%;
     width: 100%;
     /* padding: 0px; */
     /* padding: 0px; */
-    height: 30px;
+    height: 30px !important;
     line-height: 30px;
     line-height: 30px;
     border: 0px;
     border: 0px;
     background-color: #bdc3c7;
     background-color: #bdc3c7;
     vertical-align: top;
     vertical-align: top;
     border-radius: 8px;
     border-radius: 8px;
     padding-bottom: 10px;
     padding-bottom: 10px;
+    color: #333 !important;
 }
 }
 .submitbtn .el-button--small {
 .submitbtn .el-button--small {
     padding: 9px 62px;
     padding: 9px 62px;

+ 198 - 78
TEAMModelBI/ClientApp/src/view/systemConfig/website.vue

@@ -1,23 +1,53 @@
 <template>
 <template>
     <div class="websiteList">
     <div class="websiteList">
+        <div class="site" v-if="sitevname==='mainland'">
+            <span>当前设置:
+                <svg class="site-icon" aria-hidden="true">
+                    <use xlink:href="#icon-guoneiyou"></use>
+                </svg>
+            </span>
+            <span class="site-title">大陆站</span>
+        </div>
+        <div class="site" v-else-if="sitevname ==='international'">
+            <span>当前设置:
+                <svg class="site-icon" aria-hidden="true">
+                    <use xlink:href="#icon-yk_guoji"></use>
+                </svg>
+            </span>
+            <span class="site-title">国际站</span>
+        </div>
         <div class="basics">
         <div class="basics">
             <p class="commonbox-title">基础设置</p>
             <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 class="commonbox-form">
+                <p class="interiorTag">站点配置</p>
+                <el-form :model="basicsData" label-width="140px" size="small" :inline="true">
+                    <el-form-item label="站点:" class="basics-name">
+                        <el-input v-model="basicsData.website" @input="changeData('basics','site')" />
+                    </el-form-item>
+                    <el-form-item label="站点别名:" class="basics-name">
+                        <el-input v-model="basicsData.nickname" @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>
+                <!-- <div class="basics-redact-btn" v-show="basicsData.state" @click="updateData('basics')">
+                    <el-button type="primary" size="small">确认调整</el-button>
+                </div> -->
+            </div>
+        </div>
+        <div class="basics-client">
+            <p class="commonbox-title">连接相关</p>
+            <div class="commonbox-form">
+                <p class="interiorTag">连接配置</p>
+                <el-form :model="clientData" label-width="140px" size="small" :inline="true">
+                    <el-form-item label="clientID:" class="basics-name">
+                        <el-input v-model="clientData.clientID" @input="changeData('basics','site')" />
+                    </el-form-item>
+                    <el-form-item label="clientSecret:" class="basics-ip">
+                        <el-input v-model="clientData.clientSecret" @input="changeData('basics','proDeptId')" />
+                    </el-form-item>
+                </el-form>
             </div>
             </div>
         </div>
         </div>
         <div class="privatebox">
         <div class="privatebox">
@@ -26,7 +56,7 @@
                 <p class="interiorTag">钉钉密钥</p>
                 <p class="interiorTag">钉钉密钥</p>
                 <el-form :model="dingDingData" label-width="120px" size="small">
                 <el-form :model="dingDingData" label-width="120px" size="small">
                     <el-form-item label="Agentld:" class="dingding-Id">
                     <el-form-item label="Agentld:" class="dingding-Id">
-                        <el-input v-model="dingDingData.Agentld" @input="changeData('dingDing','appId')" />
+                        <el-input v-model="dingDingData.agentId" @input="changeData('dingDing','appId')" />
                     </el-form-item>
                     </el-form-item>
                     <el-form-item label="appKey:" class="dingding-Key">
                     <el-form-item label="appKey:" class="dingding-Key">
                         <el-input v-model="dingDingData.appKey" @input="changeData('dingDing','appKey')" />
                         <el-input v-model="dingDingData.appKey" @input="changeData('dingDing','appKey')" />
@@ -35,9 +65,9 @@
                         <el-input v-model="dingDingData.appSecret" type="textarea" :rows="4" @input="changeData('dingDing','appSecret')" />
                         <el-input v-model="dingDingData.appSecret" type="textarea" :rows="4" @input="changeData('dingDing','appSecret')" />
                     </el-form-item>
                     </el-form-item>
                 </el-form>
                 </el-form>
-                <div class="redact-btn" v-show="dingDingData.state" @click="updateData('dingDing')">
+                <!-- <div class="redact-btn" v-show="dingDingData.state" @click="updateData('dingDing')">
                     <el-button type="primary" size="small">更新配置</el-button>
                     <el-button type="primary" size="small">更新配置</el-button>
-                </div>
+                </div> -->
             </div>
             </div>
             <div class="databasebox">
             <div class="databasebox">
                 <p class="interiorTag">数据库</p>
                 <p class="interiorTag">数据库</p>
@@ -45,108 +75,133 @@
                     <el-form :model="databaseData" label-width="120px" size="small">
                     <el-form :model="databaseData" label-width="120px" size="small">
                         <p class="database-title">Blob</p>
                         <p class="database-title">Blob</p>
                         <el-form-item label="ConnectionString">
                         <el-form-item label="ConnectionString">
-                            <el-input v-model="databaseData.Storage" type="textarea" @input="changeData('database','storage')" />
+                            <el-input v-model="databaseData.storage" type="textarea" @input="changeData('database','storage')" />
                         </el-form-item>
                         </el-form-item>
                         <p class="database-title">CosmosDB</p>
                         <p class="database-title">CosmosDB</p>
                         <el-form-item label="ConnectionString:">
                         <el-form-item label="ConnectionString:">
-                            <el-input v-model="databaseData.Cosmos" type="textarea" @input="changeData('database','cosmosDb')" />
+                            <el-input v-model="databaseData.cosmos" type="textarea" @input="changeData('database','cosmosDb')" />
                         </el-form-item>
                         </el-form-item>
                         <p class="database-title">Redis</p>
                         <p class="database-title">Redis</p>
                         <el-form-item label="ConnectionString:">
                         <el-form-item label="ConnectionString:">
-                            <el-input v-model="databaseData.Redis" type="textarea" @input="changeData('database','redis')" />
+                            <el-input v-model="databaseData.redis" type="textarea" @input="changeData('database','redis')" />
                         </el-form-item>
                         </el-form-item>
                         <p class="database-title">服务地址</p>
                         <p class="database-title">服务地址</p>
                         <el-form-item label="ConnectionString:">
                         <el-form-item label="ConnectionString:">
-                            <el-input v-model="databaseData.ServiceBus" type="textarea" @input="changeData('database','serviceBus')" />
+                            <el-input v-model="databaseData.servicBus" type="textarea" @input="changeData('database','serviceBus')" />
                         </el-form-item>
                         </el-form-item>
                     </el-form>
                     </el-form>
-                    <div class="redact-btn" v-show="databaseData.state" @click="updateData('database')">
+                    <!-- <div class="redact-btn" v-show="databaseData.state" @click="updateData('database')">
                         <el-button type="primary" size="small">更新配置</el-button>
                         <el-button type="primary" size="small">更新配置</el-button>
-                    </div>
+                    </div> -->
                 </div>
                 </div>
             </div>
             </div>
         </div>
         </div>
+        <div class="backbtnbox">
+            <div class="redact-btn">
+                <el-button type="primary" size="small" v-if="submitShow" @click="updateData">保存配置</el-button>
+                <el-button type="primary" size="small" v-else disabled>保存配置</el-button>
+            </div>
+            <div class="backbtn" @click="backbtnInfo">
+                <svg class="site-icon" aria-hidden="true">
+                    <use xlink:href="#icon-fanhui2"></use>
+                </svg>
+                <span>返回</span>
+            </div>
+        </div>
     </div>
     </div>
 </template>
 </template>
 <script>
 <script>
-import { ref, reactive, getCurrentInstance } from 'vue'
+import { ref, reactive, getCurrentInstance, watch } from 'vue'
 import { ElMessage, ElLoading } from 'element-plus'
 import { ElMessage, ElLoading } from 'element-plus'
 export default {
 export default {
-    setup() {
+    props: {
+        siteValue: {
+            type: String,
+            default: '',
+        },
+    },
+    setup(props, context) {
         let { proxy } = getCurrentInstance()
         let { proxy } = getCurrentInstance()
         let adminfilter = ref('')
         let adminfilter = ref('')
         //基础信息
         //基础信息
         let basicsData = ref({
         let basicsData = ref({
             website: '',
             website: '',
+            nickname: '',
             platform: '',
             platform: '',
-            state: false,
         })
         })
         //钉钉密钥
         //钉钉密钥
         let dingDingData = ref({
         let dingDingData = ref({
-            Agentld: '',
+            agentId: '',
             appKey: '',
             appKey: '',
             appSecret: '',
             appSecret: '',
-            state: false,
         })
         })
         //数据库
         //数据库
         let databaseData = ref({
         let databaseData = ref({
-            Storage: '',
-            Cosmos: '',
-            Redis: '',
-            ServiceBus: '',
-            state: false,
+            storage: '',
+            cosmos: '',
+            redis: '',
+            servicBus: '',
         })
         })
-        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异常')
-                })
-        }
+        //连接相关
+        let clientData = ref({
+            clientID: '',
+            clientSecret: '',
+        })
+        let sitevname = ref('')
+        let submitShow = ref(false)
         function changeData(statename, value) {
         function changeData(statename, value) {
-            statename === 'basics' ? (basicsData.value.state = true) : statename === 'dingDing' ? (dingDingData.value.state = true) : statename === 'database' ? (databaseData.value.state = true) : ''
+            statename === 'basics' ? (submitShow.value = true) : statename === 'dingDing' ? (submitShow.value = true) : statename === 'database' ? (submitShow.value = 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 }
-                    : ''
-
+        function updateData() {
+            let data = {
+                site: basicsData.value.website,
+                nickname: basicsData.value.nickname,
+                proDeptId: basicsData.value.platform,
+                clientKey: clientData.value,
+                dDAuth: dingDingData.value,
+                azureClient: databaseData.value,
+            }
             proxy.$api
             proxy.$api
                 .updateSystemconfig(data)
                 .updateSystemconfig(data)
                 .then((res) => {
                 .then((res) => {
-                    console.log(res)
-                    ElMessage.success('操作成功!')
+                    console.log(res, '保存返回')
+                    res.state === 200 ? ElMessage.success('保存成功') : ElMessage.error('保存失败')
+                    context.emit('state', res.allConfigs)
                 })
                 })
                 .catch((err) => {
                 .catch((err) => {
-                    ElMessage.error('修改配置失败')
+                    ElMessage.error('配置更新API异常,保存失败')
                 })
                 })
         }
         }
-        getData()
+        function backbtnInfo() {
+            context.emit('changemodels', 'choice')
+        }
+        watch(
+            props,
+            (newValue) => {
+                console.log(newValue)
+                // newValue ? (sitevname.value = newValue.siteValue) : ''
+                if (newValue) {
+                    basicsData.value.website = newValue.siteValue.site
+                    basicsData.value.nickname = newValue.siteValue.nickName
+                    basicsData.value.platform = newValue.siteValue.proDeptId
+                    dingDingData.value = newValue.siteValue.dDAuth
+                    databaseData.value = newValue.siteValue.azureClient
+                    clientData.value = newValue.siteValue.clientKey
+                }
+                console.log(sitevname.value, '触发监听')
+            },
+            { immediate: true, deep: true }
+        )
         return {
         return {
             basicsData,
             basicsData,
             dingDingData,
             dingDingData,
             databaseData,
             databaseData,
             changeData,
             changeData,
             updateData,
             updateData,
+            sitevname,
+            backbtnInfo,
+            clientData,
+            submitShow,
         }
         }
     },
     },
 }
 }
@@ -155,17 +210,28 @@ export default {
 .websiteList {
 .websiteList {
     width: 100%;
     width: 100%;
     margin-top: 1%;
     margin-top: 1%;
+    position: relative;
 }
 }
 .basics {
 .basics {
-    width: 80%;
+    width: 100%;
+    padding: 1%;
+    position: relative;
+    margin-top: 2%;
+    text-align: left;
+}
+.basics-client {
+    width: 100%;
     padding: 1%;
     padding: 1%;
     position: relative;
     position: relative;
+    margin-top: 1%;
+    text-align: left;
 }
 }
 .basics-name {
 .basics-name {
-    width: 40%;
+    width: 25%;
+    margin-right: 10%;
 }
 }
 .basics-ip {
 .basics-ip {
-    width: 40%;
+    width: 30%;
 }
 }
 .basics-name {
 .basics-name {
     margin-top: 2%;
     margin-top: 2%;
@@ -177,6 +243,13 @@ export default {
     display: flex;
     display: flex;
     justify-content: space-between;
     justify-content: space-between;
 }
 }
+.commonbox-form {
+    text-align: left;
+    border: 1px solid #ccc;
+    margin-top: 1%;
+    border-radius: 5px;
+    position: relative;
+}
 .dingding {
 .dingding {
     width: 43%;
     width: 43%;
     padding: 1.5%;
     padding: 1.5%;
@@ -229,14 +302,61 @@ export default {
     font-size: 16px;
     font-size: 16px;
 }
 }
 .redact-btn {
 .redact-btn {
-    position: absolute;
+    /* position: absolute;
     bottom: 1%;
     bottom: 1%;
-    right: 1%;
+    right: 1%; */
+    width: 40%;
+    margin-right: 10%;
 }
 }
 .basics-redact-btn {
 .basics-redact-btn {
     position: absolute;
     position: absolute;
-    bottom: 45%;
-    left: 50%;
+    bottom: 0%;
+    right: 0%;
+}
+.site {
+    position: absolute;
+    top: 0%;
+    right: 2%;
+    font-size: 14px;
+    color: #95a5a6;
+}
+.site-icon {
+    width: 1.5em;
+    height: 1.5em;
+    vertical-align: -0.4em;
+    fill: currentColor;
+    overflow: hidden;
+    margin-right: 5px;
+    color: #333;
+}
+.site-title {
+    font-size: 14px;
+    color: #2c3e50;
+}
+.backbtnbox {
+    position: absolute;
+    top: -35px;
+    right: 1%;
+    display: flex;
+    width: 200px;
+    justify-content: space-between;
+}
+.backbtn {
+    width: 80px;
+    line-height: 20px;
+    font-size: 14px;
+    border: 1px solid #ccc;
+    padding: 5px 10px;
+    border-radius: 5px;
+    color: #54a0ff;
+    background: #c8d6e5;
+    font-weight: 600;
+    cursor: pointer;
+}
+.connect {
+    width: 100%;
+    padding: 1%;
+    position: relative;
 }
 }
 </style>
 </style>
 <style>
 <style>

+ 48 - 11
TEAMModelBI/ClientApp/src/view/teachermanage/manage.vue

@@ -16,7 +16,7 @@
         <div class="search-box">
         <div class="search-box">
             <!-- <input class="search-txt" type="text" id="serachname" :value="filterText" placeholder="搜索相关人名" @oninput="personnelSearch()" @compositionend="personnelSearch()"> -->
             <!-- <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" />
             <el-input v-model="filterText" placeholder="Please input" class="search-txt" />
-            <svg class="serachbox-empty" aria-hidden="true" @click="filterText=''">
+            <svg class="serachbox-empty" aria-hidden="true" @click="filterText='',valueinfo='all'">
                 <use xlink:href="#icon-qingkong"></use>
                 <use xlink:href="#icon-qingkong"></use>
             </svg>
             </svg>
             <svg class="serachbox-icon" aria-hidden="true">
             <svg class="serachbox-icon" aria-hidden="true">
@@ -47,7 +47,6 @@
                         </svg> -->
                         </svg> -->
                         <PersonalPhoto style="cursor: pointer;" :name="scope.row.name"></PersonalPhoto>
                         <PersonalPhoto style="cursor: pointer;" :name="scope.row.name"></PersonalPhoto>
                     </div>
                     </div>
-
                 </template>
                 </template>
             </el-table-column>
             </el-table-column>
             <el-table-column prop="name" :label="$t(`personnelManagement.personnelTable.name`)" sortable align="center" />
             <el-table-column prop="name" :label="$t(`personnelManagement.personnelTable.name`)" sortable align="center" />
@@ -94,15 +93,19 @@
         </el-table>
         </el-table>
     </div>
     </div>
     <div class="personnel-drawer">
     <div class="personnel-drawer">
-        <el-drawer v-model="drawer" title="用户相关信息配置" :direction="direction" :modal="false">
+        <el-drawer v-model="drawer" title="用户相关信息配置" :direction="direction" :modal="false" :before-close="closeDrawer()">
             <el-tabs v-model="activeName" class="demo-tabs">
             <el-tabs v-model="activeName" class="demo-tabs">
                 <el-tab-pane label="权限/身份" name="first">
                 <el-tab-pane label="权限/身份" name="first">
-                    <Operates></Operates>
+                    <Operates ref="roaming" :userdata="nowUser" @changeShow="changeState"></Operates>
                 </el-tab-pane>
                 </el-tab-pane>
                 <el-tab-pane label="关联学校" name="second">
                 <el-tab-pane label="关联学校" name="second">
-                    <Correlation></Correlation>
+                    <Correlation :userdata="nowUser"></Correlation>
                 </el-tab-pane>
                 </el-tab-pane>
             </el-tabs>
             </el-tabs>
+            <div class="changeBtn" v-show="activeName === 'first'">
+                <el-button type="primary" size="small" v-if="drawerChange" @click="changeSubmit">保存变更</el-button>
+                <el-button type="info" size="small" disabled v-else>保存变更</el-button>
+            </div>
         </el-drawer>
         </el-drawer>
     </div>
     </div>
     <div class="manatips">
     <div class="manatips">
@@ -213,7 +216,9 @@ export default {
         let timer = ref('')
         let timer = ref('')
         let drawer = ref(false)
         let drawer = ref(false)
         let direction = ref('rtl')
         let direction = ref('rtl')
-        const activeName = ref('first')
+        let activeName = ref('first')
+        let drawerChange = ref(false)
+        let roaming = ref()
         //处理名单
         //处理名单
         getEvery()
         getEvery()
         function process(val) {}
         function process(val) {}
@@ -253,9 +258,10 @@ export default {
         }
         }
         // 处理各个部门
         // 处理各个部门
         function handleClick(index, data) {
         function handleClick(index, data) {
-            // console.log(index, data, 'click')
+            console.log(index, data, 'click')
+            nowUser.value = data[index]
+            console.log(nowUser.value)
             drawer.value = true
             drawer.value = true
-
             // let userData = data.value[index]
             // let userData = data.value[index]
             // nowUser.value = data.value[index]
             // nowUser.value = data.value[index]
             // let manaPermission = JSON.parse(localStorage.getItem('management'))
             // let manaPermission = JSON.parse(localStorage.getItem('management'))
@@ -373,7 +379,11 @@ export default {
             proxy.$api
             proxy.$api
                 .getStaffList(data)
                 .getStaffList(data)
                 .then((res) => {
                 .then((res) => {
-                    res.state === 200 ? ElMessage.success('人员名单已更新') : res.state === 401 ? ElMessage.error('非系统管理员无法操作') : ElMessage.error('人员名单更新失败,请稍后重试')
+                    res.state === 200
+                        ? (getEvery(), ElMessage.success('人员名单已更新'))
+                        : res.state === 401
+                        ? ElMessage.error('非系统管理员无法操作')
+                        : ElMessage.error('人员名单更新失败,请稍后重试')
                     loading.close()
                     loading.close()
                 })
                 })
                 .catch((err) => {
                 .catch((err) => {
@@ -396,6 +406,16 @@ export default {
             }
             }
             timer.value = setTimeout(fn, wait)
             timer.value = setTimeout(fn, wait)
         }
         }
+        function closeDrawer() {
+            activeName.value = 'first'
+        }
+        function changeState(value) {
+            drawerChange.value = value
+        }
+        function changeSubmit() {
+            console.log(roaming.value)
+            roaming.value.notarizeChange()
+        }
         watch(filterText, (newdata) => {
         watch(filterText, (newdata) => {
             if (newdata.trim().length !== 0) {
             if (newdata.trim().length !== 0) {
                 debounce(personnelSearch, 500)
                 debounce(personnelSearch, 500)
@@ -432,6 +452,11 @@ export default {
             drawer,
             drawer,
             direction,
             direction,
             activeName,
             activeName,
+            closeDrawer,
+            drawerChange,
+            changeState,
+            changeSubmit,
+            roaming,
         }
         }
     },
     },
 }
 }
@@ -661,6 +686,7 @@ export default {
 }
 }
 .personnel-drawer {
 .personnel-drawer {
     line-height: 20px;
     line-height: 20px;
+    position: relative;
 }
 }
 .totalnum {
 .totalnum {
     font-size: 14px;
     font-size: 14px;
@@ -671,6 +697,11 @@ export default {
 .refresh-btn {
 .refresh-btn {
     display: inline-block;
     display: inline-block;
 }
 }
+.changeBtn {
+    position: absolute;
+    top: 8%;
+    right: 2%;
+}
 </style>
 </style>
 <style>
 <style>
 .manatips .el-dialog__header,
 .manatips .el-dialog__header,
@@ -691,7 +722,7 @@ export default {
     line-height: 65px !important;
     line-height: 65px !important;
 }
 }
 .search-box .el-input__inner {
 .search-box .el-input__inner {
-    /* opacity: 0.1; */
+    opacity: 0.1;
     width: 0px;
     width: 0px;
     /* padding: 0px; */
     /* padding: 0px; */
     height: 0px;
     height: 0px;
@@ -700,13 +731,15 @@ export default {
     background-color: #bdc3c7;
     background-color: #bdc3c7;
     vertical-align: top;
     vertical-align: top;
     border-radius: 8px;
     border-radius: 8px;
+    color: #333;
 }
 }
 .search-box:hover .el-input__inner {
 .search-box:hover .el-input__inner {
-    /* opacity: 1; */
+    opacity: 1;
     width: 100%;
     width: 100%;
     height: 30px;
     height: 30px;
     padding-bottom: 10px;
     padding-bottom: 10px;
     line-height: 30px;
     line-height: 30px;
+    color: #333;
 }
 }
 .manatips .el-dialog__header {
 .manatips .el-dialog__header {
     line-height: 20px;
     line-height: 20px;
@@ -732,4 +765,8 @@ export default {
 .personnel-drawer .el-drawer__body {
 .personnel-drawer .el-drawer__body {
     padding: 0px 10px;
     padding: 0px 10px;
 }
 }
+.changeBtn .el-button--small {
+    min-height: 20px;
+    padding: 5px 8px;
+}
 </style>
 </style>

+ 3 - 3
TEAMModelBI/Controllers/Census/ActivitySticsController.cs

@@ -506,9 +506,9 @@ namespace TEAMModelBI.Controllers.Census
             long resourceCount = 0; //累计资源
             long resourceCount = 0; //累计资源
             long totalTime = 0; //总学时
             long totalTime = 0; //总学时
 
 
-            scCount = await CommonFind.FindTotals(cosmosClient, $"select count(c.id) as totals form c ", "School", "Base");
-            tecCount = await CommonFind.FindTotals(cosmosClient, $"select count(c.id) as totals form c ", "Teacher", "Base");
-            stuCount = await CommonFind.FindTotals(cosmosClient, $"select count(c.id) as totals form c ", "Student", "Base");
+            scCount = await CommonFind.FindTotals(cosmosClient, $"SELECT count(c.id) as totals FROM c ", "School", "Base");
+            tecCount = await CommonFind.FindTotals(cosmosClient, $"SELECT count(c.id) as totals FROM c ", "Teacher", "Base");
+            stuCount = await CommonFind.FindTotals(cosmosClient, $"SELECT count(c.id) as totals FROM c ", "Student", "Base");
 
 
             foreach (var area in areaInfos) 
             foreach (var area in areaInfos) 
             {
             {

+ 7 - 1
TEAMModelBI/Controllers/DingDingStruc/SystemConfigController.cs

@@ -270,7 +270,13 @@ namespace TEAMModelBI.Controllers.DingDingStruc
             string input = stringBuilder.ToString();
             string input = stringBuilder.ToString();
             List<SysConfig> allConfigs = input.ToObject<List<SysConfig>>();
             List<SysConfig> allConfigs = input.ToObject<List<SysConfig>>();
             var currentSite = _option.Location;
             var currentSite = _option.Location;
-            SysConfig currentSysConfig = allConfigs.Where(x => x.site.Equals(currentSite)).FirstOrDefault();
+            SysConfig currentSysConfig = new();
+            try
+            {
+                currentSysConfig = allConfigs.Where(x => x.site.Equals(currentSite)).FirstOrDefault();
+            }
+            catch{}
+
             if (currentSysConfig != null)
             if (currentSysConfig != null)
             {
             {
                 return Ok(new { state = 200, allConfigs, currentSysConfig });
                 return Ok(new { state = 200, allConfigs, currentSysConfig });

+ 4 - 1
TEAMModelBI/Models/SysConfig.cs

@@ -1,4 +1,6 @@
-namespace TEAMModelBI.Models
+using System.ComponentModel.DataAnnotations;
+
+namespace TEAMModelBI.Models
 {
 {
     /// <summary>
     /// <summary>
     /// 配置文件
     /// 配置文件
@@ -9,6 +11,7 @@
         /// <summary>
         /// <summary>
         /// 站点
         /// 站点
         /// </summary>
         /// </summary>
+        [Required(ErrorMessage = "{0} 必须填写")]
         public string site { get; set; }
         public string site { get; set; }
         /// <summary>
         /// <summary>
         /// 站点昵称
         /// 站点昵称

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

@@ -419,7 +419,7 @@ export default {
         interactionCount: 'Student Interaction No.',
         interactionCount: 'Student Interaction No.',
         intUnit: 'time/person',
         intUnit: 'time/person',
         optionCount: 'Option Distribution',
         optionCount: 'Option Distribution',
-        tPushLabel: 'The teacher pushed a picture:',
+        tPushLabel: '推送:',
         noAns: 'Not Answered',
         noAns: 'Not Answered',
     }
     }
 }
 }

+ 1 - 1
TEAMModelOS/ClientApp/src/locale/lang/zh-CN/cusMgt.js

@@ -419,7 +419,7 @@ export default {
         interactionCount:'学生互动总数',
         interactionCount:'学生互动总数',
         intUnit:'次/人',
         intUnit:'次/人',
         optionCount:'选项分布',
         optionCount:'选项分布',
-        tPushLabel:'教师推送了一张图:',
+        tPushLabel:'推送:',
         noAns:'未答',
         noAns:'未答',
     }
     }
 }
 }

+ 1 - 1
TEAMModelOS/ClientApp/src/locale/lang/zh-TW/cusMgt.js

@@ -419,7 +419,7 @@ export default {
         interactionCount: '學生互動總數',
         interactionCount: '學生互動總數',
         intUnit: '次/人',
         intUnit: '次/人',
         optionCount: '選項分佈',
         optionCount: '選項分佈',
-        tPushLabel: '教師推送了一張圖:',
+        tPushLabel: '推送:',
         noAns:'未答',
         noAns:'未答',
     }
     }
 }
 }

+ 5 - 5
TEAMModelOS/ClientApp/src/static/Global.js

@@ -363,11 +363,11 @@ const HI_TEACH_EVENT = ()=>{
 			type:'fn',
 			type:'fn',
 			relation:'irs'
 			relation:'irs'
 		},
 		},
-		// SPQStrt:{
-		// 	text:'测验模式',
-		// 	type:'fn',
-		// 	relation:'exam'
-		// },
+		SPQStrt:{
+			text:'测验模式',
+			type:'fn',
+			relation:'exam'
+		},
 		PickupResult:{
 		PickupResult:{
 			text:'挑人',
 			text:'挑人',
 			type:'fn',
 			type:'fn',

+ 4 - 3
TEAMModelOS/ClientApp/src/view/classrecord/ClassRecord.less

@@ -250,19 +250,20 @@
 .page-item {
 .page-item {
     display: flex;
     display: flex;
     position: relative;
     position: relative;
-    border-bottom: 10px solid #f0f0f0;
     background: white;
     background: white;
     padding: 10px 70px 10px 20px;
     padding: 10px 70px 10px 20px;
     .record-data-wrap {
     .record-data-wrap {
         width: 100%;
         width: 100%;
-        padding-left: 15px;
+        // padding-left: 15px;
+        padding-top: 5px;
+        border-bottom: 1px dashed #e0e0e0;
     }
     }
 }
 }
 .page-info-wrap{
 .page-info-wrap{
     margin-right: 10px;
     margin-right: 10px;
     max-width: 160px;
     max-width: 160px;
     padding-right: 15px;
     padding-right: 15px;
-    border-right: 1px dashed #e0e0e0;
+    // border-right: 1px dashed #e0e0e0;
 }
 }
 
 
 .page-tag {
 .page-tag {

+ 4 - 0
TEAMModelOS/ClientApp/src/view/classrecord/ClassRecord.vue

@@ -491,6 +491,10 @@ export default {
     },
     },
     created() {
     created() {
         this.hiTeachEvent = this.$GLOBAL.HI_TEACH_EVENT()
         this.hiTeachEvent = this.$GLOBAL.HI_TEACH_EVENT()
+        //正式站先暂时不放出课中评测
+        if (this.$store.state.config.srvAdrType == 'product') {
+            this.$delete(this.hiTeachEvent,'SPQStrt')
+        }
         this.events = Object.keys(this.hiTeachEvent)
         this.events = Object.keys(this.hiTeachEvent)
         this.fnEvents = this.events.filter(key => this.hiTeachEvent[key].type === 'fn')
         this.fnEvents = this.events.filter(key => this.hiTeachEvent[key].type === 'fn')
         console.log(this.events, this.fnEvents)
         console.log(this.events, this.fnEvents)

+ 260 - 23
TEAMModelOS/ClientApp/src/view/classrecord/eventchart/Exam.vue

@@ -1,17 +1,25 @@
 <template>
 <template>
     <div class="exam-wrap">
     <div class="exam-wrap">
         <TeacherClient></TeacherClient>
         <TeacherClient></TeacherClient>
-        <div class="exam-info" @click="getExamInfo">
+        <div class="exam-info" v-if="!examDetaiInfo" @click="getExamInfo">
             <Icon type="md-podium" style="margin-right:5px" />
             <Icon type="md-podium" style="margin-right:5px" />
             查看评测数据
             查看评测数据
         </div>
         </div>
+        <div v-else class="exam-chart-wrap">
+            <ExamGrade :pieData="scoreSegment" style="margin-right:50px"></ExamGrade>
+            <ExamQu :quData="correctData[0] ? correctData[0].data : []" style="margin-right:50px"></ExamQu>
+            <ExamTable :examInfo="examDetaiInfo" :recordInfo="recordInfo"></ExamTable>
+        </div>
     </div>
     </div>
 </template>
 </template>
 <script>
 <script>
 import TeacherClient from './TeacherClient.vue'
 import TeacherClient from './TeacherClient.vue'
+import ExamGrade from './ExamGrade.vue'
+import ExamQu from './ExamQu.vue'
+import ExamTable from './ExamTable.vue'
 export default {
 export default {
     components: {
     components: {
-        TeacherClient
+        TeacherClient, ExamGrade, ExamQu, ExamTable
     },
     },
     props: {
     props: {
         examInfo: {
         examInfo: {
@@ -29,32 +37,258 @@ export default {
     },
     },
     data() {
     data() {
         return {
         return {
-
+            simpleData: {},
+            examDetaiInfo: undefined,
+            paperQuInfo: [],
+            correctData:[]
         }
         }
     },
     },
     methods: {
     methods: {
-        getExamInfo() {
-            console.log(this.examInfo)
-            console.log(this.recordInfo)
-            this.$router.push({
-                path: '/home/evDetail',
-                query: {
-                    examId: this.examInfo.ExamId,
-                    code: `Exam-${this.$store.state.userInfo.TEAMModelId}`
+        //获取评测简要数据分析
+        findSimpleAna() {
+            this.simpleData = {}
+            let requestData = {
+                id: this.examInfo.ExamId,
+                code: this.$store.state.userInfo.TEAMModelId//课中评测统一记录的是教师id,不用根据课堂记录scope处理
+            }
+            this.$api.learnActivity.simpleAna(requestData).then(
+                res => {
+                    if (!res.error) {
+                        if (res.averageMap.length && res.averageMap.length) {
+                            this.dataErr = false
+                            this.calculating = false
+                            for (let i in res.averageMap) {
+                                for (let j in res.averageMap[i].ClassAverage) {
+                                    res.averageMap[i].ClassAverage[j] = parseFloat(res.averageMap[i].ClassAverage[j].toFixed(2))
+                                }
+                                let subject = this.examDetaiInfo.subjects.find(item => {
+                                    return item.id == res.averageMap[i].subjectId
+                                })
+                                if (subject) {
+                                    res.averageMap[i].subjectId = subject.name
+                                } else {
+                                    res.averageMap[i].subjectId = '-'
+                                }
+                            }
+                            res.averageTotal.forEach(item => {
+                                let subjectInfo = this.examDetaiInfo.papers.find(subItem => {
+                                    return subItem.subjectId == item.subjectId
+                                })
+                                if (subjectInfo) {
+                                    item.subjectName = subjectInfo.subjectName
+                                    item.paperScore = subjectInfo.score
+                                } else {
+                                    item.subjectName = this.examDetaiInfo.subjects && this.examDetaiInfo.subjects.length ? this.examDetaiInfo.subjects[0].name : ''
+                                    item.paperScore = this.examDetaiInfo.papers && this.examDetaiInfo.papers[0] ? this.examDetaiInfo.papers[0].score : ''
+                                }
+                            })
+                            this.simpleData = res
+                            this.getCorrectData(res)
+                        } else {
+                            this.calculating = true
+                            this.$Message.warning(this.$t('learnActivity.simple.inCalc'))
+                        }
+
+                    } else {
+                        this.dataErr = true
+                        this.$Message.error(this.$t('learnActivity.simple.simpleErr'))
+                    }
+                },
+                err => {
+                    this.dataErr = true
                 }
                 }
+            ).finally(() => {
+                this.isLoading = false
             })
             })
-            // let requestData = {
-            //     id: this.examInfo.ExamId,
-            //     code: `Exam-${this.$store.state.userInfo.TEAMModelId}`
-            // }
-            // this.$api.learnActivity.FindExamInfo(requestData).then(
-            //     res => {
+        },
+        //获取各科题目正确率数据
+        getCorrectData(data) {
+            let d = []
+            if (data.averageTotal) {
+                data.averageTotal.forEach(item => {
+                    let quInfo = this.paperQuInfo.find(pq => pq.subjectId == item.subjectId)
+                    let quNoList = quInfo ? quInfo.quNo : []
+                    let total = item.total.length //总人数
+                    let cData = item.wrongNum.map((w, i) => {
+                        let correct = total - w
+                        return {
+                            correct: correct, //正确人数
+                            wrong: w,//错误人数
+                            rate: total ? parseInt(correct * 100 / total) : 0,//正确率
+                            quLabel: quNoList[i] ? quNoList[i].label : i
+                        }
+                    })
+                    d.push({
+                        subjectId: item.subjectId,
+                        subjectName: item.subjectName,
+                        data: cData
+                    })
+                })
+                this.correctData = d
+            } else {
+                this.correctData = []
+            }
+        },
+        getExamInfo() {
+            let requestData = {
+                id: this.examInfo.ExamId,
+                code: `Exam-${this.$store.state.userInfo.TEAMModelId}` //课中评测统一记录的是教师id,不用根据课堂记录scope处理
+            }
+            this.$api.learnActivity.FindExamInfo(requestData).then(
+                async res => {
+                    if (!res.error && res.examInfo[0]) {
+                        let resData = res.examInfo[0]
+                        resData.score = 0
+                        for (let index in resData.papers) {
+                            let blob = resData.papers[index].blob
+                            let sheetNo = resData.papers[index].sheetNo
+                            let totlaSocre = resData.papers[index].point.reduce((prev, next, index, array) => {
+                                return prev + next
+                            })
+                            resData.examPaperErr = false
+                            resData.papers[index].examScope = resData.scope
+                            resData.papers[index].examCode = resData.code
+                            resData.papers[index].examId = resData.id
+                            resData.papers[index].owner = resData.owner
+                            resData.papers[index].sheetNo = sheetNo
+                            try {
+                                resData.papers[index] = await this.$evTools.getFullPaper(resData.papers[index])
+                            } catch (e) {
+                                resData.papers[index].item = []
+                                resData.examPaperErr = true
+                                this.$Message.error(this.$t('learnActivity.simple.paperErr'))
+                            }
+                            resData.papers[index].examScope = resData.scope
+                            resData.papers[index].examCode = resData.code
+                            resData.papers[index].examId = resData.id
+                            resData.papers[index].owner = resData.owner
+                            resData.papers[index].sheetNo = sheetNo
+                            resData.papers[index].totlaSocre = totlaSocre
+                            if (!resData.papers[index].subjectId) {
+                                resData.papers[index].subjectId = blob.substring(blob.lastIndexOf('/') + 1)
+                                resData.papers[index].subjectName = resData.subjects[index].name
+                            }
+                            resData.papers[index].blob = blob
+                            resData.score += resData.papers[index].score
 
 
-            //     },
-            //     err => {
+                            // //补充评测状态信息
+                            // let statusInfo = this.getEvStatusInfo(resData.progress, resData.sStatus)
+                            // resData.progText = statusInfo.progText
+                            // resData.progColor = statusInfo.progColor
+                            // resData.scoreText = statusInfo.scoreText
+                            // resData.scoreColor = statusInfo.scoreColor
+                            // resData.curSchool = !(resData.scope === 'school' && resData.school != this.$store.state.userInfo.schoolCode)
+                            //设置各科题号信息
+                            this.setPaperQuInfo(resData.papers)
+                        }
+                        this.examDetaiInfo = resData
+                        if (this.examDetaiInfo.progress === 'finish') {
+                            this.findSimpleAna()
+                        }
+                    } else {
+                        this.$Message.error(this.$t('learnActivity.mgtScEv.exInfoErr'))
+                    }
+                },
+                err => {
 
 
-            //     }
-            // )
+                }
+            )
+        },
+        // 设置各科题号信息
+        setPaperQuInfo(papers) {
+            this.paperQuInfo = []
+            if (!papers) return
+            let objectiveQu = ['single', 'multiple', 'judge']
+            papers.forEach(paper => {
+                let data = []
+                let realIndex = 0
+                paper.item?.forEach((item, index) => {
+                    if (item.children.length) {
+                        item.children.forEach((childItem, childIndex) => {
+                            let i = realIndex++
+                            data.push({
+                                label: (index + 1) + '-' + (childIndex + 1),
+                                value: i,
+                                disabled: objectiveQu.includes(childItem.type),
+                                quIndex: index,
+                                childIndex: childIndex
+                            })
+                        })
+                    } else {
+                        let i = realIndex++
+                        data.push({
+                            label: (index + 1) + '',
+                            value: i,
+                            disabled: objectiveQu.includes(item.type),
+                            quIndex: index,
+                            childIndex: -1
+                        })
+                    }
+                })
+                this.paperQuInfo.push({
+                    subjectId: paper.subjectId,
+                    subjectName: paper.subjectName,
+                    quNo: data
+                })
+            })
+        },
+    },
+    computed: {
+        examScore() {
+            if (this.examDetaiInfo && this.examDetaiInfo.score) {
+                return this.examDetaiInfo.score
+            } else {
+                return 0
+            }
+        },
+        //所有学生总分统计(多科)
+        stuTotalScores() {
+            if (this.simpleData && this.simpleData.averageTotal) {
+                let total = []
+                this.simpleData.averageTotal.forEach((subItem, i) => {
+                    // 累积各科分数
+                    subItem.total.forEach((sItem, j) => {
+                        if (!total[j]) total[j] = 0
+                        total[j] += sItem
+                    })
+                })
+                return total
+            } else {
+                return []
+            }
+        },
+        //总分成绩分布
+        scoreSegment() {
+            if (this.stuTotalScores.length) {
+                let segment = []
+                let unit = this.examScore / 10
+                let startScore = 0
+                for (let i = 0; i < 10; i++) {
+                    let endScore = Math.ceil(unit * (i + 1))
+                    let s = this.stuTotalScores.filter(item => {
+                        return item >= startScore && item <= endScore
+                    })
+                    segment.push({
+                        name: `${startScore}-${endScore}`,
+                        value: s.length
+                    })
+                    startScore = endScore + 1
+                }
+                return segment
+            } else {
+                return []
+            }
+        },
+    },
+    watch:{
+        examInfo:{
+            deep:true,
+            immediate:true,
+            handler(n,o){
+                if(n && n.ExamId){
+                    this.getExamInfo()
+                }
+            }
         }
         }
     }
     }
 }
 }
@@ -65,13 +299,16 @@ export default {
 }
 }
 .exam-info {
 .exam-info {
     width: fit-content;
     width: fit-content;
-    padding: 10px 20px;
+    padding: 5px 20px;
     background: #5cadff;
     background: #5cadff;
     color: white;
     color: white;
     border: 2px solid #2b85e4;
     border: 2px solid #2b85e4;
     border-radius: 6px;
     border-radius: 6px;
-    font-size: 18px;
+    font-size: 14px;
     user-select: none;
     user-select: none;
     cursor: pointer;
     cursor: pointer;
 }
 }
+.exam-chart-wrap{
+    display: flex;
+}
 </style>
 </style>

+ 116 - 0
TEAMModelOS/ClientApp/src/view/classrecord/eventchart/ExamGrade.vue

@@ -0,0 +1,116 @@
+<template>
+    <div class="ev-score-matrix" :id="'ev-score-matrix'+id"></div>
+</template>
+<script>
+import elementResizeDetectorMaker from "element-resize-detector"
+export default {
+    props: {
+        isTotal: {
+            type: Boolean,
+            default: false
+        },
+        pieData: {
+            type: Array,
+            default: () => {
+                return []
+            }
+        }
+    },
+    data() {
+        return {
+            id: '',
+            progressPie: undefined,
+            option: {}
+        }
+    },
+    mounted() {
+        this.progressPie = this.$echarts.init(document.getElementById('ev-score-matrix' + this.id), 'macarons')
+        this.progressPie.setOption(this.option)
+        let erd11 = elementResizeDetectorMaker()
+        erd11.listenTo(document.getElementById("ev-score-matrix" + this.id), () => {
+            this.$nextTick(() => {
+                //监听到事件后执行的业务逻辑
+                this.progressPie.resize()
+            })
+        })
+    },
+    created() {
+        this.id = this.$jsFn.getBtwRandom(0, 100000000)
+    },
+    watch: {
+        pieData: {
+            handler(n, o) {
+                this.$nextTick(() => {
+                    console.log('成绩分布数据:', n)
+                    this.option = {
+                        tooltip: {
+                            trigger: 'item',
+                            formatter: '{b} : {c}' + this.$t('unit.text7')
+                        },
+                        grid: {
+                            left: 20,
+                            right: 20,
+                            top: 25,
+                            bottom: 20
+                        },
+                        title: {
+                            "text": `${this.isTotal ? this.$t('learnActivity.simple.total') : ''}${this.$t('learnActivity.simple.scoreMat')}`,
+                            "left": "center",
+                            "top": 0,
+                            "textStyle": {
+                                // "color": "#303030",
+                                fontSize: 12
+                            }
+                        },
+                        xAxis: {
+                            show: true,
+                            type: 'category',
+                            data: [],
+                            axisLine: {
+                                lineStyle: {
+                                    color: "#AAA"
+                                }
+                            },
+                            axisLabel: {
+                                rotate: 10
+                            }
+                        },
+                        yAxis: {
+                            type: 'value'
+                        },
+                        series: [
+                            {
+                                data: [],
+                                type: 'bar',
+                                barMaxWidth: 20,
+                            }
+                        ]
+                    }
+                    if (!this.progressPie) {
+                        this.progressPie = this.$echarts.init(document.getElementById('ev-score-matrix' + this.id), 'macarons')
+                    }
+                    // this.option.series[0].data = this.pieData.filter(item => {
+                    //     return item.value > 0
+                    // })
+                    let d = this.pieData.filter(item => {
+                        return item.value > 0
+                    })
+                    this.option.series[0].data = d.map(item => item.value)
+                    this.option.xAxis.data = d.map(item => `${item.name}${this.$t('unit.text11')}`)
+                    this.progressPie.setOption(this.option, true)
+                })
+            },
+            deep: true,
+            immediate: true
+        }
+    }
+}
+</script>
+<style scoped lang="less">
+.ev-score-matrix {
+    width: 260px;
+    height: 150px;
+}
+</style>
+<style>
+</style>

+ 208 - 0
TEAMModelOS/ClientApp/src/view/classrecord/eventchart/ExamQu.vue

@@ -0,0 +1,208 @@
+<template>
+    <div class="qu-score-count" :id="'qu-score-count'+id"></div>
+</template>
+<script>
+import elementResizeDetectorMaker from "element-resize-detector"
+export default {
+    props: {
+        quData: {
+            type: Array,
+            default: () => {
+                return []
+            }
+        }
+    },
+    data() {
+        let _this = this
+        return {
+            isShowRate: true,
+            id: '',
+            progressPie: undefined,
+            stuCount: 0,
+            option: {}
+        }
+    },
+    created() {
+        this.id = this.$jsFn.getBtwRandom(0, 100000000)
+    },
+    mounted() {
+        this.progressPie = this.$echarts.init(document.getElementById('qu-score-count' + this.id), 'macarons')
+        this.progressPie.setOption(this.option)
+        let erd11 = elementResizeDetectorMaker()
+        erd11.listenTo(document.getElementById("qu-score-count" + this.id), () => {
+            this.$nextTick(() => {
+                //监听到事件后执行的业务逻辑
+                this.progressPie.resize()
+            })
+        })
+    },
+    watch: {
+        quData: {
+            handler(n, o) {
+                let _this = this
+                this.$nextTick(() => {
+                    if (this.quData.length) _this.stuCount = this.quData[0].correct + this.quData[0].wrong
+                    this.option = {
+                        tooltip: {
+                            trigger: 'item',
+                            formatter: '{b} : {c}' + this.$t('unit.text7')
+                        },
+                        grid: {
+                            left: 30,
+                            right: 20,
+                            top: 25,
+                            bottom: 50
+                        },
+                        title: {
+                            "text": this.$t('learnActivity.simple.quCorrectRate'),
+                            "left": "center",
+                            "top": 0,
+                            "textStyle": {
+                                fontSize: 12
+                            }
+                        },
+                        tooltip: {
+                            formatter: (params) => {
+                                return `${_this.$t('learnActivity.simple.rac')} ${params.data.toFixed(0)}%(${_this.quData[params.dataIndex].correct}${_this.$t('unit.text7')})`
+                            }
+                        },
+                        xAxis: {
+                            show: true,
+                            // name:'题号',
+                            nameLocation: 'end',
+                            type: 'category',
+                            data: [],
+                            axisLine: {
+                                lineStyle: {
+                                    color: "#AAA"
+                                }
+                            },
+                            axisLabel: {
+                                rotate: 0
+                            }
+                        },
+                        yAxis: {
+                            // name:'正确率',
+                            type: 'value'
+                        },
+                        series: [
+                            {
+                                data: [],
+                                type: 'bar',
+                                barMinWidth: 20,
+                                barMaxWidth: 20,
+                                label: {
+                                    show: true,
+                                    position: 'top',
+                                    formatter: (params) => {
+                                        //统计人数的算法
+                                        // if (_this.stuCount > 0) {
+                                        //     return `${(params.data * 100 / _this.stuCount).toFixed(1)}%`
+                                        // } else {
+                                        //     return params.data
+                                        // }
+                                        // 统计正确率的算法
+                                        return _this.isShowRate ? `${params.data.toFixed(0)}%` : ''
+                                    },
+                                },
+                                itemStyle: {
+                                    normal: {
+                                        color: function (params) {
+                                            const colorList = ['#ed4014', '#ff9900', '#19be6b']
+                                            //统计人数的算法
+                                            // if (_this.stuCount >= 0) {
+                                            //     let rate = params.data * 100 / _this.stuCount
+                                            //     console.log(params, rate)
+                                            //     if (rate >= 70) {
+                                            //         return colorList[2]
+                                            //     } else if (rate > 50) {
+                                            //         return colorList[1]
+                                            //     } else {
+                                            //         return colorList[0]
+                                            //     }
+                                            // } else {
+                                            //     return colorList[2]
+                                            // }
+                                            // 统计正确率的算法
+                                            if (params.data >= 70) {
+                                                return colorList[2]
+                                            } else if (params.data > 50) {
+                                                return colorList[1]
+                                            } else {
+                                                return colorList[0]
+                                            }
+
+                                        }
+                                    }
+                                }
+                            }
+                        ]
+                    }
+                    if (!this.progressPie) {
+                        this.progressPie = this.$echarts.init(document.getElementById('qu-score-count' + this.id), 'macarons')
+                    }
+                    this.option.series[0].data = this.quData.map(item => item.correct * 100 / this.stuCount) //计算正确率
+                    this.option.xAxis.data = this.quData.map(item => item.quLabel)
+                    // if (this.quData.length) this.option.yAxis.max = this.quData[0].correct + this.quData[0].wrong
+                    if (this.quData.length) this.option.yAxis.max = 100 //计算比例不算人数
+                    if (this.quData.length > 8) {
+                        this.option.dataZoom = [
+                            {
+                                show: true,
+                                height: 8,
+                                xAxisIndex: [
+                                    0
+                                ],
+                                bottom: 10,
+                                endValue: 30,
+                                startValue: 0,
+                                handleIcon: 'M512 497.821538m-418.264615 0a418.264615 418.264615 0 1 0 836.52923 0 418.264615 418.264615 0 1 0-836.52923 0Z',
+                                handleSize: '100%',
+                                handleStyle: {
+                                    color: '#d3dee5'
+
+                                },
+                                textStyle: {
+                                    color: '#fff'
+                                },
+                                borderRadius: '5px',
+                                maxValue: 30,
+                            },
+                            {
+                                type: 'inside',
+                                show: true,
+                                height: 15,
+                                endValue: 30,
+                                startValue: 0,
+                                maxValue: 30,
+                            }
+                        ]
+                    } else {
+                        this.option.dataZoom = []
+                    }
+                    this.progressPie.setOption(this.option, true)
+                    this.progressPie.on('datazoom', (params) => {
+                        let start = params.batch[0]?.start
+                        let end = params.batch[0]?.end
+                        if (end - start > 30) {
+                            this.isShowRate = false
+                        } else {
+                            this.isShowRate = true
+                        }
+                    })
+                })
+            },
+            deep: true,
+            immediate: true
+        }
+    }
+}
+</script>
+<style scoped lang="less">
+.qu-score-count {
+    width: 260px;
+    height: 180px;
+}
+</style>
+<style>
+</style>

+ 400 - 0
TEAMModelOS/ClientApp/src/view/classrecord/eventchart/ExamTable.vue

@@ -0,0 +1,400 @@
+<template>
+    <div class="exam-table-wrap">
+        <!-- 班级人数 -->
+        <div class="data-count-item">
+            <p class="data-value">
+                {{overviewInfo.total}}
+            </p>
+            <p class="data-text">
+                {{$t('learnActivity.simple.classStuCount')}}
+            </p>
+        </div>
+        <!-- 已作答 -->
+        <div class="data-count-item">
+            <p class="data-value">
+                {{overviewInfo.answered}}
+            </p>
+            <p class="data-text">
+                {{$t('learnActivity.simple.answered')}}
+            </p>
+        </div>
+        <!-- 未作答/缺考 -->
+        <div class="data-count-item">
+            <p class="data-value" style="color:#ed4014">
+                {{overviewInfo.noAnswer}}
+            </p>
+            <p class="data-text">
+                {{ examInfo.progress == 'going' ? $t('learnActivity.simple.unanswer') : $t('learnActivity.simple.missExam')}}
+            </p>
+        </div>
+        <!-- 已评分 -->
+        <div class="data-count-item">
+            <p class="data-value">
+                {{overviewInfo.scored}}
+            </p>
+            <p class="data-text">
+                {{$t('learnActivity.simple.scored')}}
+            </p>
+        </div>
+        <!-- 未评分 -->
+        <div class="data-count-item">
+            <p class="data-value" style="color:#ed4014">
+                {{overviewInfo.noScore}}
+            </p>
+            <p class="data-text">
+                {{$t('learnActivity.simple.unscore')}}
+            </p>
+        </div>
+        <!-- 查看更多 -->
+        <div class="data-count-item view-more" @click="toEvDetail">
+            <p class="data-value" style="color:#2d8cf0">
+                <Icon type="ios-more" />
+            </p>
+            <p class="data-text" style="color:#2d8cf0">
+                查看更多
+            </p>
+        </div>
+        <Modal v-model="viewTableStatus" className="ed-name-modal" footer-hide :width="1000">
+            <div slot="header" class="modal-header">
+                详细作答数据
+            </div>
+            <div class="edit-name-content" style="padding-bottom:50px">
+                <Table ref="score-table" class="score-box" border :columns="tableColumn" :data="tableData" :no-data-text="$t('learnActivity.score.classNoStu')">
+                    <template slot-scope="{ row,index }" :slot="'qu'+qIndex" v-for="(item,qIndex) in quCount">
+                        <div :key="'qu'+qIndex" @click="getStuScore(row,qIndex)" style="cursor:pointer;">
+                            <span v-if="row.data[qIndex] == -1 && row.status == 1">- -</span>
+                            <Icon size="20" type="ios-create-outline" color="#2db7f5" v-else-if="row.data[qIndex] == -1 && row.status !== 1" />
+                            <span style="color:#2db7f5;" v-else>{{row.data[qIndex]}}</span>
+                        </div>
+                    </template>
+                    <template slot-scope="{ row }" slot="total">
+                        <span style="color:#2db7f5;">{{ row.total }}</span>
+                    </template>
+                    <template slot-scope="{ row }" slot="name">
+                        <span style="color:#2db7f5;cursor: pointer;" :title="row.id">{{ row.name}}</span>
+                    </template>
+                    <!-- 1: 未作答 2:未评分 3:已评分 4:缺考 5:补考中 -->
+                    <template slot-scope="{ row,index }" slot="status">
+                        <span class="stu-status-tag" :style="{'background':row.statusColor}">
+                            {{row.statusText}}
+                        </span>
+                    </template>
+                    <Loading slot="loading" :top="-50"></Loading>
+                </Table>
+                <div class="page-wrap">
+                    <Page show-total size="small" :current="currentPage" :total="studentScore.length" :page-size="pageSize" :page-size-opts="pageSizeOpts" @on-change="pageChange" @on-page-size-change="pageSizeChange" show-sizer />
+                </div>
+            </div>
+        </Modal>
+    </div>
+</template>
+<script>
+export default {
+    props: {
+        examInfo: {
+            type: Object,
+            default: () => {
+                return {}
+            }
+        },
+        recordInfo: {
+            type: Object,
+            default: () => {
+                return {}
+            }
+        },
+    },
+    data() {
+        return {
+            currentPage: 1,
+            pageSize: 10,
+            pageSizeOpts: [5, 10, 20, 30, 40],
+            viewTableStatus: false,
+            dataLoading: true,
+            overviewInfo: {
+                total: 0,
+                answered: 0,
+                noAnswer: 0,
+                scored: 0,
+                noScore: 0
+            },
+            scoreList: [
+                {
+                    title: this.$t('learnActivity.score.column1'),
+                    slot: "name",
+                    fixed: "left",
+                    align: "center",
+                    width: 150,
+                },
+                {
+                    title: this.$t('learnActivity.score.column2'),
+                    slot: "total",
+                    align: "center",
+                    sortable: true,
+                    fixed: "right",
+                    width: 100
+                },
+                // {
+                //     title: this.$t('learnActivity.score.column3'),
+                //     slot: "status",
+                //     align: "center",
+                //     fixed: "right",
+                //     width: 130,
+                // }
+            ],
+            tableColumn: [],
+            studentScore: [],
+            originData: [],
+            students: [],
+            tableData: [],
+            quCount: 0
+        }
+    },
+    methods: {
+        toEvDetail() {
+            this.$router.push({
+                path: '/home/evDetail',
+                query: {
+                    examId: this.examInfo.id,
+                    code: `Exam-${this.$store.state.userInfo.TEAMModelId}`
+                }
+            })  
+        },
+        getStatusInfo(answer, score, status) {
+            //评测设置学生可以补考
+            if (status == 2 || status == 3) {
+                return {
+                    status: 3,
+                    statusText: this.$t('learnActivity.score.status5'),
+                    statusColor: '#2db7f5'
+                }
+            }
+
+            //评测结束,学生缺考
+            if (status == 1 && this.examInfo.progress == 'finish') {
+                return {
+                    status: 1,
+                    statusText: this.$t('learnActivity.score.status4'),
+                    statusColor: '#ed4014'
+                }
+            }
+
+            //评测进行中,未作答
+            if (status == 1 && this.examInfo.progress == 'going') {
+                return {
+                    status: 0,
+                    statusText: this.$t('learnActivity.score.status1'),
+                    statusColor: '#808695'
+                }
+            }
+            // status:0
+            //已作答,未评分
+            if (score.includes(-1)) {
+                return {
+                    status: 2,
+                    statusText: this.$t('learnActivity.score.status2'),
+                    statusColor: '#ff9900'
+                }
+            }
+            //已作答已评分
+            return {
+                status: 4,
+                statusText: this.$t('learnActivity.score.status3'),
+                statusColor: '#19be6b'
+            }
+        },
+        //分数求和
+        getcount(arr) {
+            return arr.reduce((total, item) => {
+                if (item !== -1) {
+                    return total + item;
+                } else {
+                    return total;
+                }
+            }, 0);
+        },
+        //初始化表单数据
+        setTableData(studentData, studentAns) {
+            console.log(arguments)
+            this.studentScore = []
+            this.tableColumn = [...this.scoreList]
+            this.quCount = studentAns.studentScores[0] ? studentAns.studentScores[0].length : 0
+            for (let i = 0; i < this.quCount; i++) {
+                let data = {
+                    title: "Q" + (i + 1),
+                    slot: "qu" + i,
+                    align: "center",
+                    minWidth: 70
+                }
+                this.tableColumn.push(data);
+            }
+            let ans = []
+            for (let i = 0; i < studentAns.studentIds.length; i++) {
+                for (let k = 0; k < studentData.length; k++) {
+                    let score = {}
+                    if (studentAns.studentIds[i] == studentData[k].id) {
+                        score.name = studentData[k].name
+                        score.type = studentData[k].type
+                        score.id = studentAns.studentIds[i]
+                        score.data = studentAns.studentScores[i]
+                        score.total = this.getcount(score.data)
+                        score.ansBlob = studentAns.studentAnswers[i]
+                        score.mark = studentAns.mark[i]
+                        let { status, statusText, statusColor } = this.getStatusInfo(studentAns.studentAnswers[i], studentAns.studentScores[i], studentAns.status[i])
+                        score.status = status
+                        score.statusText = statusText
+                        score.statusColor = statusColor
+                        this.studentScore.push(score)
+                    }
+                }
+            }
+            this.originData = this._.cloneDeep(this.studentScore)
+            this.students = this._.cloneDeep(this.studentScore)
+            this.pageChange(1)
+            if (ans.length) {
+                for (let k = 0; k < this.paperInfo.papers.item.length; k++) {
+                    this.$set(
+                        this.paperInfo.papers.item[k],
+                        "answerData",
+                        ans[k]
+                    );
+                    this.$set(
+                        this.paperInfo.papers.item[k],
+                        "stuScore",
+                        score[k]
+                    );
+                }
+            }
+        },
+        // 页面size变化
+        pageSizeChange(val) {
+            this.pageSize = val
+            this.pageChange(1)
+        },
+        // 分页页面变化
+        pageChange(page) {
+            let start = this.pageSize * (page - 1)
+            let end = this.pageSize * page
+            this.currentPage = page
+            this.tableData = this.studentScore.slice(start, end)
+        },
+        //获取学生作答详情数据
+        getStudentAnswer() {
+            this.dataLoading = true
+            let requestData = {
+                id: this.examInfo.id,
+                code: this.recordInfo.scope == 'school' ? this.$store.state.userInfo.schoolCode : this.$store.state.userInfo.TEAMModelId,
+                subjectId: this.recordInfo.subjectId,
+                classId: this.recordInfo.groupIds[0],
+            };
+            this.$api.learnActivity.FindAllStudent(requestData).then(
+                (res) => {
+                    if (res.examClassResults && res.examClassResults.length) {
+                        this.setTableData(res.ufos, res.examClassResults[0])
+                        this.calcOverView(res.examClassResults[0])
+                        this.dataLoading = false
+                        this.tableLoading = false
+                    }
+                    //如果首次没有获取到有效数据(数据暂未生成),则尝试重复活动5次
+                    else {
+                        this.$Message.error({
+                            content: this.$t('learnActivity.score.dataError'),
+                            duration: 3
+                        })
+                        this.dataLoading = false
+                        this.tableLoading = false
+                    }
+                },
+                (err) => {
+                    this.$t('learnActivity.score.dataError')
+                    this.dataLoading = false
+                    this.tableLoading = false
+                }
+            )
+        },
+        //计算总览数据
+        calcOverView(data) {
+            //评测进行中计算未作答
+            console.log(data)
+            this.overviewInfo.noAnswer = 0
+            if (this.examInfo.progress == 'going') {
+                data.studentAnswers.forEach(item => {
+                    if (item.length == 0) {
+                        this.overviewInfo.noAnswer++
+                    }
+                })
+            }
+            //评测结束计算缺考
+            else {
+                this.overviewInfo.noAnswer = data.status?.filter(item => item == 1).length || 0
+            }
+
+            this.overviewInfo.answered = data.studentAnswers.length - this.overviewInfo.noAnswer
+            // 计算已评分未评分
+            this.overviewInfo.noScore = 0
+            data.studentScores.forEach(item => {
+                let flag = item.find(item => {
+                    return item == -1
+                })
+                if (flag) {
+                    this.overviewInfo.noScore++
+                }
+            })
+            this.overviewInfo.scored = data.studentScores.length - this.overviewInfo.noScore
+            // 班级总人数
+            this.overviewInfo.total = data.studentIds.length
+        },
+    },
+    watch: {
+        examInfo: {
+            deep: true,
+            immediate: true,
+            handler(n, o) {
+                console.log('评测数据', n)
+                if (n && n.id) {
+                    this.getStudentAnswer()
+                }
+            }
+        }
+    }
+}
+</script>
+<style lang="less" scoped>
+.exam-table-wrap {
+    margin-top: 5px;
+    padding: 10px;
+    width: 300px;
+    height: 150px;
+    box-shadow: 0px 2px 5px #e9e9e9;
+    display: flex;
+    flex-wrap: wrap;
+    align-items: center;
+}
+.data-count-item {
+    text-align: center;
+    width: 33.3%;
+}
+.view-more {
+    cursor: pointer;
+    &:hover {
+        color: #2b85e4;
+    }
+}
+.stu-status-tag {
+    cursor: pointer;
+    font-size: 12px;
+    padding: 3px 8px;
+    font-weight: 800;
+    border-radius: 4px;
+    color: white;
+}
+.page-wrap {
+    float: right;
+    margin-top: 15px;
+}
+</style>
+<style lang="less">
+.exam-table-wrap .ivu-page-options-sizer {
+    margin-right: 0px;
+}
+</style>

+ 0 - 1
TEAMModelOS/ClientApp/src/view/learnactivity/ExamMgt.vue

@@ -554,7 +554,6 @@ export default {
             this.$api.learnActivity.FindExamInfo(requestData).then(
             this.$api.learnActivity.FindExamInfo(requestData).then(
                 async res => {
                 async res => {
                     this.dataErr = false
                     this.dataErr = false
-
                     if (!res.error) {
                     if (!res.error) {
                         let resData = res.examInfo[0]
                         let resData = res.examInfo[0]
                         resData.score = 0
                         resData.score = 0

+ 2 - 1
TEAMModelOS/ClientApp/src/view/learnactivity/tabs/DataView.vue

@@ -190,11 +190,12 @@ export default {
                 return '--'
                 return '--'
             }
             }
         },
         },
-        //学生总分
+        //所有学生总分统计(多科)
         stuTotalScores() {
         stuTotalScores() {
             if (this.simpleData && this.simpleData.averageTotal) {
             if (this.simpleData && this.simpleData.averageTotal) {
                 let total = []
                 let total = []
                 this.simpleData.averageTotal.forEach((subItem, i) => {
                 this.simpleData.averageTotal.forEach((subItem, i) => {
+                    // 累积各科分数
                     subItem.total.forEach((sItem, j) => {
                     subItem.total.forEach((sItem, j) => {
                         if (!total[j]) total[j] = 0
                         if (!total[j]) total[j] = 0
                         total[j] += sItem
                         total[j] += sItem