瀏覽代碼

Merge branch 'master' of https://git.cocorobo.cn/CocoRoboLabs/pbl_admin_table

lsc 3 周之前
父節點
當前提交
b147c36d52
共有 62 個文件被更改,包括 2907 次插入851 次删除
  1. 0 0
      dist/css/app.23a5f805.css
  2. 0 0
      dist/css/app.4ad68d96.css
  3. 二進制
      dist/img/BaseData4.618ae906.png
  4. 二進制
      dist/img/BaseData7.dfb753cf.png
  5. 二進制
      dist/img/BaseData8.0dec5fca.png
  6. 二進制
      dist/img/BaseData9.431cdeaa.png
  7. 0 10
      dist/img/Cop2.01296be9.svg
  8. 0 3
      dist/img/chart10.7bed16ca.svg
  9. 0 3
      dist/img/chart11.c7b53590.svg
  10. 0 3
      dist/img/chart12.92fd7abf.svg
  11. 0 3
      dist/img/chart13.ed8100fe.svg
  12. 0 3
      dist/img/chart14.7f658a90.svg
  13. 0 3
      dist/img/chart2.9ffe1b0d.svg
  14. 0 3
      dist/img/chart3.0608331f.svg
  15. 0 3
      dist/img/chart5.c469e8b3.svg
  16. 0 3
      dist/img/chart6.2293cf5f.svg
  17. 0 3
      dist/img/chart7.415cdedc.svg
  18. 0 3
      dist/img/chart8.7e0ad4f4.svg
  19. 0 4
      dist/img/chart9.3810d220.svg
  20. 0 0
      dist/img/cocoflow2.b8cc401e.svg
  21. 0 1
      dist/img/dui.a18f4330.svg
  22. 0 3
      dist/img/tese.e3ec7a0a.svg
  23. 0 11
      dist/img/uuu4.2648aa63.svg
  24. 0 4
      dist/img/uuu5.d74a6d37.svg
  25. 0 0
      dist/img/wechat.0277f1a9.svg
  26. 1 1
      dist/index.html
  27. 0 0
      dist/js/app.2bc0de7e.js
  28. 0 0
      dist/js/app.2bc0de7e.js.map
  29. 0 0
      dist/js/app.e7e1ea1d.js
  30. 0 0
      dist/js/app.e7e1ea1d.js.map
  31. 0 0
      dist/js/chunk-vendors.203900df.js
  32. 0 0
      dist/js/chunk-vendors.203900df.js.map
  33. 0 0
      dist/js/chunk-vendors.7cdade31.js.map
  34. 二進制
      src/assets/img/BaseData1.png
  35. 二進制
      src/assets/img/BaseData2.png
  36. 二進制
      src/assets/img/BaseData3.png
  37. 二進制
      src/assets/img/BaseData4.png
  38. 二進制
      src/assets/img/BaseData5.png
  39. 二進制
      src/assets/img/BaseData6.png
  40. 二進制
      src/assets/img/BaseData7.png
  41. 二進制
      src/assets/img/BaseData8.png
  42. 二進制
      src/assets/img/BaseData9.png
  43. 4 0
      src/common/aws-sdk-2.235.1.min.js
  44. 1 0
      src/components/schoolArea.vue
  45. 76 66
      src/components/sidebarL.vue
  46. 257 213
      src/components/topPage.vue
  47. 98 0
      src/mixins/mixin.js
  48. 74 4
      src/store/modules/user.js
  49. 434 319
      src/views/HomeView.vue
  50. 4 4
      src/views/homepageL.vue
  51. 86 0
      src/views/kanBan/components/AIApplications.vue
  52. 85 71
      src/views/kanBan/components/AdataKanban.vue
  53. 3 0
      src/views/kanBan/components/AquickEntrance.vue
  54. 850 96
      src/views/kanBan/components/AschoolFeature.vue
  55. 188 0
      src/views/kanBan/components/BasicData.vue
  56. 282 0
      src/views/kanBan/components/RegularTeaching.vue
  57. 66 0
      src/views/kanBan/components/TeacherManagement.vue
  58. 212 0
      src/views/kanBan/components/addCampusDialog.vue
  59. 82 0
      src/views/kanBan/components/countPercentage.vue
  60. 83 0
      src/views/kanBan/components/ranking.vue
  61. 17 11
      src/views/kanBan/index.vue
  62. 4 0
      src/views/login/loginPage.vue

File diff suppressed because it is too large
+ 0 - 0
dist/css/app.23a5f805.css


File diff suppressed because it is too large
+ 0 - 0
dist/css/app.4ad68d96.css


二進制
dist/img/BaseData4.618ae906.png


二進制
dist/img/BaseData7.dfb753cf.png


二進制
dist/img/BaseData8.0dec5fca.png


二進制
dist/img/BaseData9.431cdeaa.png


+ 0 - 10
dist/img/Cop2.01296be9.svg

@@ -1,10 +0,0 @@
-<svg width="297" height="297" viewBox="0 0 297 297" fill="none" xmlns="http://www.w3.org/2000/svg">
-<circle cx="229.5" cy="165.5" r="31.5" fill="#2B4ABD"/>
-<rect y="197" width="297" height="100" rx="20" fill="#0663FE"/>
-<rect x="8" y="183.554" width="292.634" height="14" transform="rotate(-15.1474 8 183.554)" fill="black"/>
-<path d="M41.2557 22.8818L170.118 100.995L38.0388 173.536L41.2557 22.8818Z" fill="#0663FE"/>
-<path d="M97.1698 262.013H112.987V264.98H97.1698V262.013ZM97.1698 267.973H113.039V270.863H97.1698V267.973ZM97.1182 274.063H113.142V276.979H97.1182V274.063ZM95.3893 262.013H98.4341V271.302C98.4341 272.317 98.3911 273.426 98.3051 274.631C98.2191 275.835 98.0471 277.048 97.789 278.269C97.5482 279.473 97.1784 280.626 96.6795 281.727C96.1978 282.828 95.5613 283.808 94.77 284.668C94.6152 284.462 94.383 284.23 94.0733 283.971C93.7637 283.713 93.4455 283.464 93.1186 283.223C92.809 282.982 92.5423 282.793 92.3187 282.656C93.024 281.881 93.5831 281.03 93.9959 280.101C94.4088 279.155 94.7098 278.183 94.8991 277.185C95.1055 276.17 95.2345 275.164 95.2861 274.166C95.3549 273.151 95.3893 272.188 95.3893 271.276V262.013ZM111.904 262.013H115V280.875C115 281.701 114.897 282.337 114.69 282.785C114.484 283.249 114.114 283.602 113.581 283.842C113.065 284.083 112.402 284.238 111.594 284.307C110.785 284.376 109.788 284.402 108.601 284.384C108.549 283.971 108.42 283.473 108.214 282.888C108.007 282.303 107.801 281.813 107.594 281.417C108.093 281.434 108.592 281.451 109.091 281.469C109.59 281.469 110.029 281.469 110.407 281.469C110.803 281.469 111.086 281.469 111.258 281.469C111.499 281.469 111.663 281.426 111.749 281.34C111.852 281.254 111.904 281.09 111.904 280.849V262.013ZM103.337 263.2H106.459V284.204H103.337V263.2Z" fill="white"/>
-<path d="M67.7795 263.303H87.9063V266.219H67.7795V263.303ZM66.1281 263.303H69.2762V270.244C69.2762 271.293 69.2417 272.446 69.1729 273.702C69.1213 274.957 69.0095 276.248 68.8375 277.572C68.6655 278.88 68.416 280.161 68.0892 281.417C67.7623 282.655 67.3237 283.774 66.7732 284.771C66.6012 284.582 66.3432 284.367 65.9991 284.126C65.6551 283.903 65.3024 283.679 64.9412 283.455C64.5971 283.249 64.2961 283.094 64.038 282.991C64.5197 282.079 64.8982 281.081 65.1734 279.998C65.4658 278.914 65.6809 277.804 65.8185 276.669C65.9561 275.517 66.0421 274.398 66.0765 273.315C66.1109 272.214 66.1281 271.19 66.1281 270.244V263.303ZM75.0561 260.722L78.1784 260C78.488 260.619 78.7804 261.299 79.0557 262.038C79.3481 262.761 79.5718 263.389 79.7266 263.922L76.5011 264.799C76.3635 264.249 76.1571 263.587 75.8819 262.813C75.6066 262.038 75.3314 261.342 75.0561 260.722ZM69.9987 269.599L72.708 268.541C73.0865 269.47 73.4649 270.468 73.8434 271.534C74.239 272.584 74.5917 273.607 74.9013 274.605C75.2282 275.603 75.4776 276.506 75.6496 277.314L72.7338 278.527C72.579 277.718 72.3554 276.798 72.0629 275.766C71.7705 274.734 71.435 273.684 71.0566 272.618C70.6953 271.534 70.3427 270.528 69.9987 269.599ZM75.1335 267.973L77.9461 267.251C78.2558 268.197 78.5568 269.195 78.8493 270.244C79.1417 271.293 79.4083 272.325 79.6492 273.34C79.89 274.338 80.0792 275.241 80.2168 276.05L77.2236 276.875C77.1204 276.067 76.9484 275.155 76.7076 274.14C76.4839 273.125 76.2345 272.085 75.9593 271.018C75.684 269.934 75.4088 268.919 75.1335 267.973ZM83.8551 267.148L87.158 268.257C86.6591 269.926 86.057 271.629 85.3517 273.366C84.6636 275.086 83.8895 276.772 83.0294 278.424C82.1693 280.058 81.2318 281.58 80.2168 282.991C80.0104 282.698 79.7008 282.363 79.2879 281.985C78.8923 281.606 78.531 281.305 78.2042 281.081C79.0987 279.774 79.9072 278.338 80.6297 276.772C81.3694 275.19 82.0059 273.573 82.5392 271.921C83.0896 270.253 83.5283 268.661 83.8551 267.148ZM68.8891 280.591H88.1901V283.507H68.8891V280.591Z" fill="white"/>
-<path d="M51.8352 263.451V282.217H46.7404V263.451H51.8352Z" fill="white"/>
-<path d="M28.4979 282.217H23L29.1943 263.451H36.1583L42.3526 282.217H36.8547L32.7496 268.619H32.603L28.4979 282.217ZM27.4716 274.813H37.8077V278.625H27.4716V274.813Z" fill="white"/>
-</svg>

File diff suppressed because it is too large
+ 0 - 3
dist/img/chart10.7bed16ca.svg


File diff suppressed because it is too large
+ 0 - 3
dist/img/chart11.c7b53590.svg


File diff suppressed because it is too large
+ 0 - 3
dist/img/chart12.92fd7abf.svg


File diff suppressed because it is too large
+ 0 - 3
dist/img/chart13.ed8100fe.svg


File diff suppressed because it is too large
+ 0 - 3
dist/img/chart14.7f658a90.svg


File diff suppressed because it is too large
+ 0 - 3
dist/img/chart2.9ffe1b0d.svg


File diff suppressed because it is too large
+ 0 - 3
dist/img/chart3.0608331f.svg


File diff suppressed because it is too large
+ 0 - 3
dist/img/chart5.c469e8b3.svg


File diff suppressed because it is too large
+ 0 - 3
dist/img/chart6.2293cf5f.svg


File diff suppressed because it is too large
+ 0 - 3
dist/img/chart7.415cdedc.svg


File diff suppressed because it is too large
+ 0 - 3
dist/img/chart8.7e0ad4f4.svg


File diff suppressed because it is too large
+ 0 - 4
dist/img/chart9.3810d220.svg


File diff suppressed because it is too large
+ 0 - 0
dist/img/cocoflow2.b8cc401e.svg


+ 0 - 1
dist/img/dui.a18f4330.svg

@@ -1 +0,0 @@
-<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1744968741523" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6522" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M416.832 798.08C400.64 798.08 384.512 791.872 372.16 779.52L119.424 525.76C94.784 500.992 94.784 460.8 119.424 436.032 144.128 411.264 184.128 411.264 208.768 436.032L416.832 644.928 814.4 245.76C839.04 220.928 879.04 220.928 903.744 245.76 928.384 270.528 928.384 310.656 903.744 335.424L461.504 779.52C449.152 791.872 432.96 798.08 416.832 798.08Z" fill="#0663FE" p-id="6523"></path></svg>

+ 0 - 3
dist/img/tese.e3ec7a0a.svg

@@ -1,3 +0,0 @@
-<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
-<path d="M10 5L12 3M8 16L16 8M12 21L14 19M16.5 19C17.163 19 17.7989 18.7366 18.2678 18.2678C18.7366 17.7989 19 17.163 19 16.5C19 15.837 18.7366 15.2011 18.2678 14.7322C17.7989 14.2634 17.163 14 16.5 14C15.837 14 15.2011 14.2634 14.7322 14.7322C14.2634 15.2011 14 15.837 14 16.5C14 17.163 14.2634 17.7989 14.7322 18.2678C15.2011 18.7366 15.837 19 16.5 19ZM7.5 10C8.16304 10 8.79893 9.73661 9.26777 9.26777C9.73661 8.79893 10 8.16304 10 7.5C10 6.83696 9.73661 6.20107 9.26777 5.73223C8.79893 5.26339 8.16304 5 7.5 5C6.83696 5 6.20107 5.26339 5.73223 5.73223C5.26339 6.20107 5 6.83696 5 7.5C5 8.16304 5.26339 8.79893 5.73223 9.26777C6.20107 9.73661 6.83696 10 7.5 10ZM5.5 21C6.16304 21 6.79893 20.7366 7.26777 20.2678C7.73661 19.7989 8 19.163 8 18.5C8 17.837 7.73661 17.2011 7.26777 16.7322C6.79893 16.2634 6.16304 16 5.5 16C4.83696 16 4.20107 16.2634 3.73223 16.7322C3.26339 17.2011 3 17.837 3 18.5C3 19.163 3.26339 19.7989 3.73223 20.2678C4.20107 20.7366 4.83696 21 5.5 21ZM18.5 8C19.163 8 19.7989 7.73661 20.2678 7.26777C20.7366 6.79893 21 6.16304 21 5.5C21 4.83696 20.7366 4.20107 20.2678 3.73223C19.7989 3.26339 19.163 3 18.5 3C17.837 3 17.2011 3.26339 16.7322 3.73223C16.2634 4.20107 16 4.83696 16 5.5C16 6.16304 16.2634 6.79893 16.7322 7.26777C17.2011 7.73661 17.837 8 18.5 8Z" stroke="#0663FE" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
-</svg>

File diff suppressed because it is too large
+ 0 - 11
dist/img/uuu4.2648aa63.svg


File diff suppressed because it is too large
+ 0 - 4
dist/img/uuu5.d74a6d37.svg


+ 0 - 0
dist/img/wechat.d3d8349b.svg → dist/img/wechat.0277f1a9.svg


+ 1 - 1
dist/index.html

@@ -36,7 +36,7 @@
         width: 100%;
         background: #e6eaf0;
         font-family: '黑体';
-      }</style><script defer="defer" src="/js/chunk-vendors.7cdade31.js"></script><script defer="defer" src="/js/app.e7e1ea1d.js"></script><link href="/css/chunk-vendors.7cfe4581.css" rel="stylesheet"><link href="/css/app.23a5f805.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but pblAdminTable doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div></body></html><script>function stopSafari() {
+      }</style><script defer="defer" src="/js/chunk-vendors.203900df.js"></script><script defer="defer" src="/js/app.2bc0de7e.js"></script><link href="/css/chunk-vendors.7cfe4581.css" rel="stylesheet"><link href="/css/app.4ad68d96.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but pblAdminTable doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div></body></html><script>function stopSafari() {
     //阻止safari浏览器双击放大功能
     let lastTouchEnd = 0  //更新手指弹起的时间
     document.documentElement.addEventListener("touchstart", function (event) {

File diff suppressed because it is too large
+ 0 - 0
dist/js/app.2bc0de7e.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/app.2bc0de7e.js.map


File diff suppressed because it is too large
+ 0 - 0
dist/js/app.e7e1ea1d.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/app.e7e1ea1d.js.map


File diff suppressed because it is too large
+ 0 - 0
dist/js/chunk-vendors.203900df.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/chunk-vendors.203900df.js.map


File diff suppressed because it is too large
+ 0 - 0
dist/js/chunk-vendors.7cdade31.js.map


二進制
src/assets/img/BaseData1.png


二進制
src/assets/img/BaseData2.png


二進制
src/assets/img/BaseData3.png


二進制
src/assets/img/BaseData4.png


二進制
src/assets/img/BaseData5.png


二進制
src/assets/img/BaseData6.png


二進制
src/assets/img/BaseData7.png


二進制
src/assets/img/BaseData8.png


二進制
src/assets/img/BaseData9.png


File diff suppressed because it is too large
+ 4 - 0
src/common/aws-sdk-2.235.1.min.js


+ 1 - 0
src/components/schoolArea.vue

@@ -73,6 +73,7 @@ export default {
     display: flex;
     width: 230px;
     height: 54px;
+    font-size: 18px;
     align-items: center;
     padding: 16px;
     box-sizing: border-box;

+ 76 - 66
src/components/sidebarL.vue

@@ -58,7 +58,7 @@
                                     </span>
                                 </div>
                                 <!-- 二级导航 -->
-                                <div class="ulTCopy" v-if="item.toolId == 'appStore' && cocoFlowList[0] && cocoFlowList[1] && cocoFlowList[0].length && cocoFlowList[1].length">
+                                <div class="ulTCopy" v-if="item.toolId.includes('appStore') && ((cocoFlowList[0] && cocoFlowList[0].length) || (cocoFlowList[1] &&  cocoFlowList[1].length))">
                                     <div class="ulTCopyTit">
                                         <span>CocoFlow</span>
                                     </div>
@@ -66,13 +66,13 @@
                                         <span v-if="cocoFlowList[0] && cocoFlowList[0].length" style="color: #00000066;">最近使用</span>
                                         <div class="ulTCopyTxt"  
                                         v-for="(i,ind) in cocoFlowList[0]" 
-                                        @click.stop="openNewWindow(i.url)" :key="ind+'ab'">
+                                        @click.stop="openNewWindow(i)" :key="ind+'ab'">
                                                 <div class="ulTCopyConT">{{ i.name }}</div>
                                         </div>
                                         <span v-if="cocoFlowList[0] && cocoFlowList[1].length" style="color: #00000066;">我的收藏</span>
 
                                         <div class="ulTCopyTxt"
-                                        v-for="(i,ind) in cocoFlowList[1]" @click.stop="openNewWindow(i.url)" :key="ind+'a'">
+                                        v-for="(i,ind) in cocoFlowList[1]" @click.stop="openNewWindow(i)" :key="ind+'a'">
                                                 <div class="ulTCopyConT">{{ i.name }}</div>
                                         </div>
                                     </div>
@@ -87,12 +87,12 @@
 
 <script>
 import { mapGetters, mapActions } from 'vuex';
-
 import store from '../store'
 import { API_CONFIG } from "@/common/apiConfig";
+import { myMixin } from "@/mixins/mixin.js"
 
     export default {
-        props:['urlAddress'],
+        mixins: [ myMixin ],
         computed: {
             ...mapGetters(['userinfo','userinfo2','fromL','appSign']),
             // 如果hk,com没有图标,默认使用cn的
@@ -159,7 +159,8 @@ import { API_CONFIG } from "@/common/apiConfig";
             async gotoKanban(){
                 // 重新获取基础数据
                 await store.dispatch('user/getschPerInfo')
-                await store.commit('user/SET_USERINFO2', {})
+                // 清除数据让数据看板中的埋点正常(不能这样写,那点返回校区的话就完蛋了)
+                // await store.commit('user/SET_USERINFO2', {})
                 let num = this.userinfo.type == 1 && this.userinfo.role == 1 && this.userinfo.rrole == 1 ? 1 : 2
                 this.$router.push({
                     path: '/KanBan',
@@ -169,52 +170,53 @@ import { API_CONFIG } from "@/common/apiConfig";
                 });
             },
             mouGet(val){
-                if(val != 'appStore') return
-                console.log('666')
+                
+                if(!val.includes('appStore')) return
+                // console.log('val',val);
                 this.getData()
             },
             // 点击一级导航
             async goto(index,val = null){
                 // console.log('goto',val);
-              
+
+               // 清空二级菜单选中状态
+                this.activeLTwo = ''
                 // val = null 就是点击了首页
                 if (val) {
                     this.activeL = index + 1               
                 }else{
                     // 点击首页清空内容,并把标识去除
                     await store.commit('user/SET_AppSIGN', '')
-                    this.$emit('update:urlAddress','')
 
                     this.$emit('getPer')
-                    // 清空选中状态
-                    this.activeLTwo = ''
                     this.activeL = index
                     return
                 }
            
-                    this.activeLTwo = ''
 
 
-                    // 点击相同应用不刷新  
-                    if (this.appSign == val.toolId) return
+                // 点击相同应用不刷新  
+                if (this.appSign == val.toolId) return
 
-                    // 更新标识
-                    await store.commit('user/SET_AppSIGN', val.toolId)
+                // 更新标识
+                await store.commit('user/SET_AppSIGN', val.toolId)
 
-                    let url = ''
-                    // 查出对应账号的应用区域地址
-                    val.url.forEach(e => {
-                         // if (e.region == this.roleUser.schoolArea || e.region == this.roleUser.orgArea) {
-                        if (e.region == this.$region) {
-                            url = e.url
-                        }
-                    });
-                    let _userinfo = this.roleUser, //登录用户信息
-                    { userid: _userid, organizeid: _oid, type: _type, org: _org, role: _role, classid: _classId } = _userinfo; // 解构赋值获取用户信息
-                    const _TscreenType = 1, _SscreenType = 3; // 常量定义
-                    let queryString = ''
-                    if(val.argumentList && val.argumentList.length){
-                        const paramsMap = {
+                let url = ''
+
+                // 查出对应账号的应用区域地址
+                val.url.forEach(e => {
+                        // if (e.region == this.roleUser.schoolArea || e.region == this.roleUser.orgArea) {
+                    if (e.region == this.$region) {
+                        url = e.url
+                    }
+                });
+                
+                let _userinfo = this.roleUser, //登录用户信息
+                { userid: _userid, organizeid: _oid, type: _type, org: _org, role: _role, classid: _classId } = _userinfo; // 解构赋值获取用户信息
+                const _TscreenType = 1, _SscreenType = 3; // 常量定义
+                let queryString = ''
+                if(val.argumentList && val.argumentList.length){
+                    const paramsMap = {
                         userid: _userid,
                         org: _org,
                         oid: _oid,
@@ -223,37 +225,40 @@ import { API_CONFIG } from "@/common/apiConfig";
                         classId: _classId,
                         TscreenType: _TscreenType,
                         SscreenType: _SscreenType
-                        };
+                    };
 
-                        const canshu = val.argumentList
-                    .filter(param => paramsMap[param] !== undefined || param === 'type')
-                    .map(param => param === 'type' ? `tType=${paramsMap['tType']}` : `${param}=${paramsMap[param]}`);
+                    const canshu = val.argumentList
+                .filter(param => paramsMap[param] !== undefined || param === 'type')
+                .map(param => param === 'type' ? `tType=${paramsMap['tType']}` : `${param}=${paramsMap[param]}`);
 
-                        queryString = canshu.length ? (url.includes('?') ? '&' : '?') + canshu.join('&') : ''; // 生成查询字符串
-                    }
+                    queryString = canshu.length ? (url.includes('?') ? '&' : '?') + canshu.join('&') : ''; // 生成查询字符串
+                }
 
-                    let _url = url + queryString
-                    console.log('_url',_url);
+                let _url = url + queryString
+                console.log('_url',_url);
                     
 
-                    let kpl = ` <iframe 
-                                    allow= "camera *; microphone *;display-capture;midi;encrypted-media;"
-                                    frameborder="no" 
-                                    border="0" 
-                                    style="border:0;width:100%;height:100%;" 
-                                    src="${_url}" 
-                                    ref="pageCon"
-                                    >
-                                </iframe>`
+                    // let kpl = ` <iframe 
+                    //                 allow= "camera *; microphone *;display-capture;midi;encrypted-media;"
+                    //                 frameborder="no" 
+                    //                 border="0" 
+                    //                 style="border:0;width:100%;height:100%;" 
+                    //                 src="${_url}" 
+                    //                 ref="${val.toolId}"
+                    //                 >
+                    //             </iframe>`
+
+                let pl = {json:_url ,stateL :true,toolId :val.toolId}
+
+                // 添加打开应用
+                this.$emit('AddAppJson',pl)
 
-                    let pl = {json:kpl ,stateL :true,toolId :val.toolId}
+                this.addOp3('1', "", { type:this.prefixL + val.toolId + "_open" }, "success")
 
-                    // 添加打开应用
-                    this.$emit('AddAppJson',pl)
             },
             
             // 获取cocoFlow收藏与历史使用记录
-            getData(){
+            getData(){                
                 let params = [
                     {
                         functionName: API_CONFIG.ajax_appStoreSave.functionName,
@@ -273,7 +278,7 @@ import { API_CONFIG } from "@/common/apiConfig";
             },
             // 点击二级导航
             async levTwo(val,index,aInd){     
-                console.log('val,index,aInd',val,index,aInd);
+                // console.log('val,index,aInd',val,index,aInd);
                 
                 
                 this.activeL = ''
@@ -320,25 +325,30 @@ import { API_CONFIG } from "@/common/apiConfig";
                 let _url = url + queryString
                 console.log('_url',_url);
                 
-                let kpl = ` <iframe 
-                                allow= "camera *; microphone *;display-capture;midi;encrypted-media;"
-                                frameborder="no" 
-                                border="0" 
-                                style="border:0;width:100%;height:100%;" 
-                                src="${_url}" 
-                                ref="pageCon"
-                                >
-                            </iframe>`
-
-                let pl = {json:kpl ,stateL :true,toolId :val.toolId}
+                // let kpl = ` <iframe 
+                //                 allow= "camera *; microphone *;display-capture;midi;encrypted-media;"
+                //                 frameborder="no" 
+                //                 border="0" 
+                //                 style="border:0;width:100%;height:100%;" 
+                //                 src="${_url}" 
+                //                 ref="pageCon"
+                //                 >
+                //             </iframe>`
+
+                let pl = {json:_url ,stateL :true,toolId :val.toolId}
+
+                this.addOp3('1', "", { type:this.prefixL + val.toolId + "_open" }, "success")
 
                 this.$emit('AddAppJson',pl)
             },
+            // 打开ai应用
             openNewWindow(val) {
                 console.log(val);
                 
                 // // 基本用法:打开指定 URL
-                window.open(val, "_blank");
+                window.open(val.url, "_blank");
+                this.addOp3('1', "", {id :val.id,name:val.name ,type:this.prefixL + "appstoreOpen" }, "success")
+
             },
         },
        
@@ -503,7 +513,7 @@ import { API_CONFIG } from "@/common/apiConfig";
    
 }
 .ulTCopyConT:hover{
-    background: #e7e7e7;
+    background: #f6f1f1;
     color: #000;
 }
 .ulTCopyTxtCon{

+ 257 - 213
src/components/topPage.vue

@@ -64,27 +64,42 @@
         <!-- 常见应用  -->
         <div class="footCon">
             <div class="footConLeft">
-                <img src="../assets/img/Cop2.svg" alt="">
-                <!-- <div class="CocoTit">
-                    COCO FLOW
-                </div> -->
+                <img v-if="fromL.basics.cocoFlow" :src="fromL.basics.cocoFlow" alt="">
+
+                <div v-else style="min-width: 150px;display: flex;flex-direction: column;justify-content: flex-end;">
+                    <img class="CutImg" src="../assets/img/dong.png" alt="">
+                    <div class="CocoTit">
+                        COCO FLOW
+                    </div>
+                </div>
+                
             </div>
 
             <div style="display: flex;gap: 16px;flex: 1;">
                 <div class="footList">
                     <div class="footListCon" v-for="(item,index) in admincocoFlow" @click="openNewWindow(item)" :key="index+'2p'">
                         <div class="footListConimg">
-                            <img v-if="!fromL.admin.cocoFlow.length" 
-                            style="margin-bottom: 12px;height: 40px;width: 40px;object-fit: contain;" 
+                            <img v-if="fromL.admin.cocoFlow.length == 0" 
+                            class="footListConimgPic"
                             :src="appImgList[index]" alt="">
 
+                            <img v-else-if="fromL.admin.cocoFlow[index].setIcon" 
+                            class="footListConimgPic"
+                            :src="fromL.admin.cocoFlow[index].setIcon" alt="">
+
                             <img
                             style="margin-bottom: 12px;height: 40px;width: 40px;object-fit: contain;"  
                             v-else :src="JSON.parse(item.json).icon" alt="">
                         </div>
                            
                             
-                        <div class="TabListName">{{ item.name }}</div>
+                        <div class="TabListName">
+                            <el-tooltip class="item" effect="light" :content="item.name" placement="bottom">
+                                <span>
+                                    {{ item.name }}
+                                </span>
+                            </el-tooltip>
+                        </div>
                         <div class="TabListBri">
                             <el-tooltip class="item" effect="light" :content="item.detail" placement="bottom">
                                 <span>
@@ -98,13 +113,24 @@
                     </div>
                 </div>
 
-                <div class="footList2">
+                <div v-if="CocoFlowList.length" class="footList2">
                     <div class="footListCon6" v-for="(item,index) in CocoFlowList" @click="openNewWindow(item)" :key="index+'4p'">
                         <div class="footListConimg">
                             <!-- <img style="margin-bottom: 12px;height: 24px;width: 22px;" :src="JSON.parse(item.json).icon" alt=""> -->
-                            <img style="margin-bottom: 12px;height: 40px;width: 40px;object-fit: contain;" :src="require('../assets/img/cocoflow2.svg')" alt="">
+                            <img v-if="fromL.admin.cocoFlow2[index] && fromL.admin.cocoFlow2[index].setIcon" 
+                                class="footListConimgPic"
+                                :src="fromL.admin.cocoFlow2[index].setIcon" alt="">
+                            <img v-else class="footListConimgPic" :src="JSON.parse(item.json).icon" alt="">
+                            
+                            <!-- <img v-else class="footListConimgPic" :src="require('../assets/img/cocoflow2.svg')" alt=""> -->
+                        </div>
+                        <div class="TabListName">
+                            <el-tooltip class="item" effect="light" :content="item.name" placement="bottom">
+                                <span>
+                                    {{ item.name }}
+                                </span>
+                            </el-tooltip>
                         </div>
-                        <div class="TabListName">{{ item.name }}</div>
                         <div class="TabListBri">
                             <el-tooltip class="item" effect="light" :content="item.detail" placement="bottom">
                                 <span>
@@ -149,7 +175,7 @@
         </div>
 
         <!-- 常见应用弹框 -->
-        <el-dialog
+        <!-- <el-dialog
         title="应用列表"
         :visible.sync="dialogVisible"
         class="moreDia"
@@ -181,7 +207,7 @@
                 <el-button @click="handleClose">取消</el-button>
                 <el-button @click="addUsuallyApp" style="background-color: #0663FE;" type="primary">确认</el-button>
             </div>
-        </el-dialog>
+        </el-dialog> -->
     </div>
 </template>
 
@@ -189,8 +215,11 @@
 import { mapGetters } from 'vuex';
 import store from '../store'
 import { API_CONFIG } from "@/common/apiConfig";
+import { myMixin } from "@/mixins/mixin.js"
 
     export default {
+        mixins: [ myMixin ],
+
         computed: {
             ...mapGetters(['userinfo','userinfo2','fromL']),
             // banner循环图
@@ -253,16 +282,15 @@ import { API_CONFIG } from "@/common/apiConfig";
                 // 平台工具 
                 tabList:[],
                 appImgList:[
-                    require('../assets/img/img4.svg'),
-                    require('../assets/img/img1.svg'),
-                    require('../assets/img/img3.svg'),
-                    require('../assets/img/img5.svg'),
+                    require('../assets/img/img7.svg'),
                     require('../assets/img/img8.svg'),
                     require('../assets/img/img2.svg'),
-                    require('../assets/img/img7.svg'),
                     require('../assets/img/img6.svg'),
+                    require('../assets/img/img5.svg'),
+                    require('../assets/img/img1.svg'),
+                    require('../assets/img/img4.svg'),
+                    require('../assets/img/img3.svg'),
                 ],
-
                 hovList:[],
             }
         },
@@ -273,174 +301,48 @@ import { API_CONFIG } from "@/common/apiConfig";
             },
             // 首页平台应用浮动效果
             setHovered(index, value) {
-                // console.log(index, value);
-                
-
                 this.tabList[index].hovered = value;
-                // console.log('this.tabList',this.tabList[index].hovered);
-                
             },
-            // 删除应用
-            delApp(val){
-                this.$confirm('确定删除吗', '提示', {
-                    confirmButtonText: '确定',
-                    cancelButtonText: '取消',
-                    type: 'warning'
-                }).then(async () => {
-                    let params = [
-                            {
-                                functionName: API_CONFIG.ajax_del_usuallyApp.functionName,
-                                aid: val, 
-                            },
-                        ];
-                        
-                    this.$ajax
-                        .post(API_CONFIG.baseUrl, params)
-                        .then(() => {
-                            this.$message.success('删除成功')
-                            this.getData()
-                        })
-                        .catch((err) => {
-                            console.log(err);
-                            this.$message.error("删除失败");
-                        });
-                   
-                }).catch(() => {
-                    // 取消操作
-                });
-
-                
-                
-            },
-            handleClose(){
-                this.usuallyList= []
-                this.tab= []
-                this.dialogVisible = false
-            },
-            // 弹框选择添加应用
-            addApp(val){
-                // let data = this.CocoFlowList.filter(e=>{
-                //     return e.id == val 
-                // })
-                // if (data.length != 0) return this.$message.info('常用列表已添加')
-                let kpl = [...this.tab,...this.CocoFlowList]
-                // console.log(kpl);
-                
+            // 获取cocoFlow2应用
+            getData(){
 
-                const index = this.tab.indexOf(val);
-                if (index !== -1) {
-                    this.tab.splice(index, 1); // 删除第一个匹配项
-                } else {
-                    if (kpl.length > 3) return this.$message.info('只能添加四个常用应用哦')
-                    this.tab.push(val);    // 添加元素到末尾
+                // if (this.fromL.admin.cocoFlow2 && this.fromL.admin.cocoFlow2.length > 0) {
+                //     this.CocoFlowList = this.fromL.admin.cocoFlow2
+                // }
+                let cocoFlowCopy = []
+                if (this.fromL.admin.cocoFlow2 && this.fromL.admin.cocoFlow2.length) {
+                    cocoFlowCopy = this.fromL.admin.cocoFlow2.map(item => item.id);
+                }else{
+                    return
                 }
-            },
-            // 打开常见应用弹框
-            openUsuallyApp(){
-                this.dialogVisible = true
-                this.loading = true
-                let params = [
-                    {
-                        functionName: API_CONFIG.ajax_usuallyApp.functionName,
-                        uid: this.roleUser.userid, 
-                        cn: this.roleUser.schoolArea ? this.roleUser.schoolArea : this.roleUser.orgArea, //学校id
-                    },
-                ];
-                
-                this.$ajax
-                    .post(API_CONFIG.baseUrl, params)
-                    .then((res) => {
-                        this.usuallyList = res.data[0]
-                        this.loading = false
+                    // let appList=[
+                    //     "4aed8607-19e1-11f0-a66a-005056924926",
+                    //     "337f9d06-1eb6-11f0-a66a-005056924926",
+                    //     "52b4aae8-088d-11f0-b508-005056924926",
+                    //     "5c95f692-1460-11f0-bad1-005056924926"
+                    // ]
 
-                    })
-                    .catch((err) => {
-                        console.log(err);
-                        this.loading = false
-                        this.$message.error("获取工具数据失败");
-                    });
-            },
-            // 添加常用确定按钮
-            async addUsuallyApp(){
-                const uploadYn = async files => {
-                    for (let index = 0; index < files.length; index++) {
-                        await this.XAdd(files[index]);
-                        console.log(index);
-                    }
-                }
-                await uploadYn(this.tab);
-                console.log('完成了');
-                this.getData()
-                this.handleClose()
-            },
-            // 循环添加用户选择常见应用
-            XAdd(val){
-                return new Promise((resolve) => {
                     let params = [
                         {
-                            functionName: API_CONFIG.ajax_add_usuallyApp.functionName,
-                            oid:this.roleUser.organizeid,
-                            aid: val,
-                            uid: this.roleUser.userid,
+                            functionName: API_CONFIG.ajax_AdminApp.functionName,
+                            con: cocoFlowCopy.join(','), 
                         },
                     ];
-                    
-                    this.$ajax
-                        .post(API_CONFIG.baseUrl, params)
-                        .then(() => {
-                            resolve(1)
-                        })
-                        .catch((err) => {
-                            console.log(err);
-                        });
-                    })
-            },
-
-            // 获取已添加cocoFlow应用
-            getData(){
-                // let params = [
-                //     {
-                //         functionName: API_CONFIG.ajax_addedUsuallyApp.functionName,
-                //         uid: this.roleUser.userid, 
-                //     },
-                // ];
-                
-                // this.$ajax
-                //     .post(API_CONFIG.baseUrl, params)
-                //     .then((res) => {
-                //         this.CocoFlowList = res.data[0]
-                //     })
-                //     .catch((err) => {
-                //         console.log(err);
-                //         this.$message.error("获取工具数据失败");
-                //     });
-
-
-                    let appList=[
-                    "4aed8607-19e1-11f0-a66a-005056924926",
-                    "337f9d06-1eb6-11f0-a66a-005056924926",
-                    "52b4aae8-088d-11f0-b508-005056924926",
-                    "5c95f692-1460-11f0-bad1-005056924926"
-
-                        ]
-
-                let params = [
-                    {
-                        functionName: API_CONFIG.ajax_AdminApp.functionName,
-                        con: appList.join(','), 
-                    },
-                ];
                 
                 this.$ajax
                     .post(API_CONFIG.baseUrl, params)
                     .then((res) => {
-                        this.CocoFlowList = res.data[0]
+                        let _data = res.data[0];
+
+                        this.CocoFlowList = cocoFlowCopy.map(id => _data.find(item => item.id === id));
+
                     })
                     .catch((err) => {
                         console.log(err);
                         this.$message.error("获取工具数据失败");
                     });
             },
+            // 筛选可用平台工具,判断是否管理员可见,去除已删除工具
             siftCoco(){
                 let data = []
                 let val = JSON.parse(JSON.stringify(this.fromL.admin.index.list))
@@ -462,40 +364,57 @@ import { API_CONFIG } from "@/common/apiConfig";
                 }
 
                 this.tabList = data
-                console.log('this.tabList',this.tabList);
+                // console.log('this.tabList',this.tabList);
 
             },
+            // 获取cocoFlow应用
             getAdmincocoFlow(){
                 // 筛选可用平台工具,判断是否管理员可见,去除已删除工具
                 this.siftCoco()
-                // console.log('getAdmincocoFlow',this.fromL);
-                
-                let appList=["2d05a12a-f0e7-11ef-b508-005056924926",
-                            "38ee6402-0539-11f0-b508-005056924926",
-                            "1c83613c-ffb7-11ef-b508-005056924926",
-                            "0d3d87bd-00b6-11f0-b508-005056924926",
-                            "ee61f383-0311-11f0-b508-005056924926",
-                            "701615ab-ffe8-11ef-b508-005056924926",
-                            "d1edef14-ef6f-11ef-b508-005056924926",
-                            "a8781a86-00d8-11f0-b508-005056924926",
-                        ]
-
-                let params = [
-                    {
-                        functionName: API_CONFIG.ajax_AdminApp.functionName,
-                        con: this.fromL.admin.cocoFlow.length == 0 ? appList.join(',') : this.fromL.admin.cocoFlow.join(','), 
-                    },
-                ];
-                
-                this.$ajax
-                    .post(API_CONFIG.baseUrl, params)
-                    .then((res) => {
-                        this.admincocoFlow = res.data[0]
-                    })
-                    .catch((err) => {
-                        console.log(err);
-                        this.$message.error("获取工具数据失败");
-                    });
+                let appList= []
+
+                if (this.fromL.admin.cocoFlow.length > 0) {
+                    appList = this.fromL.admin.cocoFlow.map(item => item.id);
+
+                    // this.admincocoFlow = JSON.parse(JSON.stringify(this.fromL.admin.cocoFlow))
+                } else {
+                    appList= [
+                        "d1edef14-ef6f-11ef-b508-005056924926",
+                        "701615ab-ffe8-11ef-b508-005056924926",
+                        "a8781a86-00d8-11f0-b508-005056924926",
+                        "ee61f383-0311-11f0-b508-005056924926",
+                        "38ee6402-0539-11f0-b508-005056924926",
+                        "1c83613c-ffb7-11ef-b508-005056924926",
+                        "0d3d87bd-00b6-11f0-b508-005056924926",
+                        "2d05a12a-f0e7-11ef-b508-005056924926",
+                    ]
+                }
+                 let params = [
+                        {
+                            functionName: API_CONFIG.ajax_AdminApp.functionName,
+                            con: appList.join(',') 
+                        },
+                    ];
+                    
+                    this.$ajax
+                        .post(API_CONFIG.baseUrl, params)
+                        .then((res) => {
+                            console.log('res',res);
+                            
+                            let _data = res.data[0]
+                            
+                            let appli = appList.map(id => _data.find(item => item.id === id));
+                            console.log('appli',appli);
+                            
+
+                            this.admincocoFlow = appli.filter(Boolean);
+
+
+                        })
+                        .catch((err) => {
+                            console.log(err);
+                            this.$message.error("获取工具数据失败");
+                        });
             },
 
             // 打开平台应用
@@ -542,21 +461,23 @@ import { API_CONFIG } from "@/common/apiConfig";
                 console.log('_url',_url);
 
 
-                  let kpl = ` <iframe 
-                                allow= "camera *; microphone *;display-capture;midi;encrypted-media;"
-                                frameborder="no" 
-                                border="0" 
-                                style="border:0;width:100%;height:100%;" 
-                                src="${_url}" 
-                                ref="pageCon"
-                                >
-                            </iframe>`
+                //   let kpl = ` <iframe 
+                //                 allow= "camera *; microphone *;display-capture;midi;encrypted-media;"
+                //                 frameborder="no" 
+                //                 border="0" 
+                //                 style="border:0;width:100%;height:100%;" 
+                //                 src="${_url}" 
+                //                 ref="pageCon"
+                //                 >
+                //             </iframe>`
 
-                let pl = {json:kpl ,stateL :true,toolId :val.toolId}
+                let pl = {json:_url ,stateL :true,toolId :val.toolId}
 
                 // this.$emit('AddAppJson',pl)
                 
                 this.$emit('cutUrl',pl)
+
+                this.addOp3('1', "", { type:this.prefixL + val.toolId + "_open" }, "success")
         
                 // document.querySelector('#pageCon').innerHTML = '';
                 
@@ -567,10 +488,125 @@ import { API_CONFIG } from "@/common/apiConfig";
             // 打开CocoFlow应用
             openNewWindow(val) {
                 console.log(val);
-                
+                this.addOp3('1', "", {id :val.id,name:val.name ,type:this.prefixL + "appstoreOpen" }, "success")
+
                 // // 基本用法:打开指定 URL
                 window.open(val.url, "_blank");
             },
+            //#region 
+             // handleClose(){
+            //     this.usuallyList= []
+            //     this.tab= []
+            //     this.dialogVisible = false
+            // },
+             // 弹框选择添加应用
+            // addApp(val){
+            //     // let data = this.CocoFlowList.filter(e=>{
+            //     //     return e.id == val 
+            //     // })
+            //     // if (data.length != 0) return this.$message.info('常用列表已添加')
+            //     let kpl = [...this.tab,...this.CocoFlowList]
+            //     // console.log(kpl);
+                
+
+            //     const index = this.tab.indexOf(val);
+            //     if (index !== -1) {
+            //         this.tab.splice(index, 1); // 删除第一个匹配项
+            //     } else {
+            //         if (kpl.length > 3) return this.$message.info('只能添加四个常用应用哦')
+            //         this.tab.push(val);    // 添加元素到末尾
+            //     }
+            // },
+             // // 添加常用确定按钮
+            // async addUsuallyApp(){
+            //     const uploadYn = async files => {
+            //         for (let index = 0; index < files.length; index++) {
+            //             await this.XAdd(files[index]);
+            //             console.log(index);
+            //         }
+            //     }
+            //     await uploadYn(this.tab);
+            //     console.log('完成了');
+            //     this.getData()
+            //     this.handleClose()
+            // },
+            // // 循环添加用户选择常见应用
+            // XAdd(val){
+            //     return new Promise((resolve) => {
+            //         let params = [
+            //             {
+            //                 functionName: API_CONFIG.ajax_add_usuallyApp.functionName,
+            //                 oid:this.roleUser.organizeid,
+            //                 aid: val,
+            //                 uid: this.roleUser.userid,
+            //             },
+            //         ];
+                    
+            //         this.$ajax
+            //             .post(API_CONFIG.baseUrl, params)
+            //             .then(() => {
+            //                 resolve(1)
+            //             })
+            //             .catch((err) => {
+            //                 console.log(err);
+            //             });
+            //         })
+            // },
+             // // 删除应用
+            // delApp(val){
+            //     this.$confirm('确定删除吗', '提示', {
+            //         confirmButtonText: '确定',
+            //         cancelButtonText: '取消',
+            //         type: 'warning'
+            //     }).then(async () => {
+            //         let params = [
+            //                 {
+            //                     functionName: API_CONFIG.ajax_del_usuallyApp.functionName,
+            //                     aid: val, 
+            //                 },
+            //             ];
+                        
+            //         this.$ajax
+            //             .post(API_CONFIG.baseUrl, params)
+            //             .then(() => {
+            //                 this.$message.success('删除成功')
+            //                 this.getData()
+            //             })
+            //             .catch((err) => {
+            //                 console.log(err);
+            //                 this.$message.error("删除失败");
+            //             });
+                   
+            //     }).catch(() => {
+            //         // 取消操作
+            //     });
+            // },
+            // 打开常见应用弹框
+            // openUsuallyApp(){
+            //     this.dialogVisible = true
+            //     this.loading = true
+            //     let params = [
+            //         {
+            //             functionName: API_CONFIG.ajax_usuallyApp.functionName,
+            //             uid: this.roleUser.userid, 
+            //             cn: this.roleUser.schoolArea ? this.roleUser.schoolArea : this.roleUser.orgArea, //学校id
+            //         },
+            //     ];
+                
+            //     this.$ajax
+            //         .post(API_CONFIG.baseUrl, params)
+            //         .then((res) => {
+            //             this.usuallyList = res.data[0]
+            //             this.loading = false
+
+            //         })
+            //         .catch((err) => {
+            //             console.log(err);
+            //             this.loading = false
+            //             this.$message.error("获取工具数据失败");
+            //         });
+            // },
+            //#endregion
         },
     }
 </script>
@@ -665,20 +701,20 @@ import { API_CONFIG } from "@/common/apiConfig";
 }
 .TabListName{
     color: #1f2937;
-    font-size: 16px;
+    font-size: 18px;
     font-weight: 600;
-    margin: auto 0 5px;
+    margin: 0 0 5px;
     margin-bottom: 4px;
-    -webkit-line-clamp: 2;
+    -webkit-line-clamp: 1;
     display: -webkit-box;
     -webkit-box-orient: vertical;
     overflow: hidden;
     text-overflow: ellipsis;
 }
 .TabListBri{
-    color: #4b5563;
-    font-size: 12px;
-    -webkit-line-clamp: 1;
+    color: rgba(0,0,0,.6);
+    font-size: 14px;
+    -webkit-line-clamp: 2;
     display: -webkit-box;
     -webkit-box-orient: vertical;
     overflow: hidden;
@@ -715,12 +751,17 @@ import { API_CONFIG } from "@/common/apiConfig";
     box-sizing: border-box;
     display: flex;
     padding-right: 40px;
+    object-fit: contain;
 }
 .footConLeft img{
     min-width: 150px;
     border-radius: 15px;
     /* object-view-box: inset(0% 12px 30px 30px); */
 }
+.CutImg{
+    width: 100% !important;
+    object-view-box: inset(0% 12px 30px 30px);
+}
 .CocoTit{
     width: 100%;
     min-width: 150px;
@@ -786,6 +827,9 @@ import { API_CONFIG } from "@/common/apiConfig";
     padding-top: 8px;
     box-sizing: border-box;
 }
+.footListConimgPic{
+    margin-bottom: 12px;height: 40px;width: 40px;object-fit: contain;
+}
 .cha{
     display: none;position: absolute;top: 10px;right: 10px;
 }

+ 98 - 0
src/mixins/mixin.js

@@ -0,0 +1,98 @@
+import { mapGetters } from 'vuex';
+
+export const myMixin = {
+  computed: {
+    ...mapGetters(['userinfo']),
+    roleUser(){
+      return Object.keys(this.userinfo).length != 0 ? this.userinfo : this.userJson
+    }
+  },
+  data() {
+    return {
+        userJson: {},
+        prefixL: window.location.href.includes("/liyuan") ? "liyuan_" : "admin_"
+    };
+  },
+  methods: {
+    detectBrowser() {
+      const ua = navigator.userAgent;
+
+      // 按优先级顺序检测
+      if (ua.includes("Edg/") || ua.includes("Edge/")) {
+        return "Microsoft Edge";
+      } else if (ua.includes("Firefox")) {
+        return "Mozilla Firefox";
+      } else if (ua.includes("Trident") || ua.includes("MSIE")) {
+        return "Internet Explorer";
+      } else if (ua.includes("360EE")) {
+        return "360 Browser (极速模式)";
+      } else if (ua.includes("360SE")) {
+        return "360 Browser (安全模式)";
+      } else if (ua.includes("SLBrowser")) {
+        return "QQ Browser";
+      } else if (ua.includes("UCBrowser")) {
+        return "UC Browser";
+      } else if (ua.includes("Opera") || ua.includes("OPR/")) {
+        return "Opera";
+      } else if (ua.includes("Chrome") && !ua.includes("Edg/")) {
+        return "Google Chrome";
+      } else if (ua.includes("Safari/") && !ua.includes("Chrome")) {
+        return "Safari";
+      } else {
+        return "Other Browser";
+      }
+    },
+    async addOp3(userTime, loadTime, object, status,account) {
+      if (!this.roleUser.userid) return
+
+      try {
+        if(!this.roleUser || !this.roleUser.accountNumber){
+            let res = await this.$ajax.get('https://pbl.cocorobo.cn/api/pbl/selectUser', {
+              userid: account
+            });
+
+            this.userJson = res.data[0][0]
+            console.log('this.userJson',this.userJson);
+        }
+      } catch (e) {
+        console.log(e);
+        return this.addOp3(userTime, loadTime, object, status);
+      }  
+
+      let _time = new Date()
+        .toLocaleString("zh-CN", { hour12: false, timeZone: "Asia/Shanghai" })
+        .replace(/\//g, "-");
+      let browser = this.detectBrowser();
+
+      let params = {
+        userid: this.roleUser.userid,
+        username: this.roleUser.username,
+        accountNumber: this.roleUser.accountNumber,
+        org: this.roleUser.orgName,
+        school: this.roleUser.schoolName,
+        role: this.roleUser.type =='1'?'老师':'学生',
+        browser: browser,
+        userTime: userTime == "1" ? _time : userTime, // 使用时间 1次的就1 其次传秒
+        loadTime: loadTime, //load的时间没有就“”
+        object: JSON.stringify(object), //执行信息传json
+        status: status //成功返回success。失败返回error的信息
+      };
+      console.log('...',params);
+      
+
+      this.$ajax
+        .post('https://pbl.cocorobo.cn/api/mongo/' + "updateUserData2", [params])
+        .then(res => {
+          if (res.data.status == 1) {
+            console.log("保存成功");
+          } else {
+            console.log("保存失败");
+          }
+        })
+        .catch(e => {
+          console.log("保存失败");
+          console.log(e);
+        });
+    }
+  }
+};

+ 74 - 4
src/store/modules/user.js

@@ -159,14 +159,14 @@ const actions = {
           functionName: API_CONFIG.ajax_schoolPermission.functionName, // 调用存储过程的名称
           org: state.userinfo.org, //组织id
           oid: state.userinfo.organizeid, //学校id
-        }]
-      ;
+        }];
+
       console.log('params',params);
       // 获取学校权限与组织权限,优先使用学校权限,其次使用组织权限
       // 第一步
       let res = await axios.post(API_CONFIG.baseUrl, params)
       let perData= JSON.parse(res.data[0][0].json)
-
+      
       // 第二步
       let params2 = [
 				{
@@ -184,7 +184,78 @@ const actions = {
         i.argumentList = JSON.parse(i.argumentList);
       });
 
+      let params3 = [
+				{
+					functionName: "select_schUsuallyApp",
+					userid: "",
+					stand: "cn",
+				},
+			];
+			let res3 = await axios.post(API_CONFIG.baseUrl, params3)
+      
+
+			let _list = res3.data[0]
+
+			_list.forEach((i) => {
+				i.json = JSON.parse(i.json);
+			});
+
+			let appList = _list;
+
       // 第三步
+      perData.desktop.list.forEach((i, index) => {
+				let _index = toolList.findIndex((i2) => i == i2.id);
+				if (_index != -1) {
+					perData.desktop.list[index] = toolList[_index];
+				} else {
+					console.log("无工具", i);
+				}
+			});
+      
+      
+      // if (perData.admin.cocoFlow) {
+			// 	perData.admin.cocoFlow.forEach((i, index) => {
+			// 		let _index = appList.findIndex((i2) => i.id == i2.id);
+			// 		if (_index != -1) {
+			// 			let _setData = appList[_index];
+			// 			_setData.setIcon = i.setIcon;
+			// 			perData.admin.cocoFlow[index] = _setData;
+			// 		} else {
+			// 			console.log("无应用", i);
+			// 		}
+			// 	});
+			// }
+
+      // if (perData.admin.cocoFlow2) {
+      //   perData.admin.cocoFlow2.forEach((i, index) => {
+      //     let _index = appList.findIndex((i2) => i.id == i2.id);
+      //     if (_index != -1) {
+      //     let _setData = appList[_index];
+      //     _setData.setIcon = i.setIcon;
+      //     perData.admin.cocoFlow2[index] = _setData;
+      //   } else {
+      //     console.log("无应用", i);
+      //   }
+      //   });
+      // }
+
+
+      if (perData.admin.CampusF && perData.admin.CampusF.appList) {
+				perData.admin.CampusF.appList.forEach((i, index) => {
+					let _index = appList.findIndex((i2) => i.id == i2.id);
+          
+					if (_index != -1) {
+						let _setData = appList[_index];
+						_setData.setIcon = i.setIcon;
+						perData.admin.CampusF.appList[index] = _setData;
+					} else {
+						console.log("无应用", i);
+					}
+				});
+        perData.admin.CampusF.appList = perData.admin.CampusF.appList.filter(Boolean);
+			}
+
+
 			perData.admin.index.list.forEach((i, index) => {
 				let _index = toolList.findIndex((i2) => i == i2.id);
 				if (_index != -1) {
@@ -194,7 +265,6 @@ const actions = {
 					console.log("无工具", i);
 				}
 			});
-
 			perData.admin.sidebar.list.forEach((i, index) => {
 				if (i.children) {
 					i.children.forEach((i2, index2) => {

+ 434 - 319
src/views/HomeView.vue

@@ -1,212 +1,268 @@
 <template>
-  <div class="body">
-   
-    <div class="container">
-      <div class="leftBar" style="height: 100%;">
-        <sidebarL @getPer="getPer" @AddAppJson="AddAppJson" :urlAddress.sync="urlAddress"  ref="sidebarLRef"></sidebarL>
-      </div>
-      <div class="table-container">
-
-        <div class="top">
-          <div class="topCon">
-            <div class="title">
-              <span v-if="roleUser.orgName">{{roleUser.orgName}}</span >
-              <span style="color: #0663FE;font-weight: 600;">{{ roleUser.schoolName }}</span>
-                
-            </div>
-            <div class="person">
-              <div class="person_name">
-                <img
-                 @click="openData()"
-                style="width: 40px;height: 40px;object-fit: cover;border-radius: 50%; cursor: pointer;" 
-                :src="roleUser.headportrait ? roleUser.headportrait : require('../assets/img/toux2.png')" alt="">
-                <div class="personInfo">
-                  <div class="personInfoTit">
-                    {{  roleUser.username }}
-                  </div>
-                  <div class="personInfoBri">
-                    {{ userSuffix() }}
-                  </div>
-                </div>
-              </div>
-              <el-button type="text" @click="handleLogout" style="margin-left: 20px">退出</el-button>
-            </div>
-          </div>
-        </div>
-        <!-- <router-view></router-view> -->
-         <!-- 首页 -->
-         <homepageL @AddAppJson="AddAppJson" :urlAddress.sync="urlAddress" v-show="!appSign" ref="homepageLRef"></homepageL>
-
-         <!-- 循环数组展示iframe  -->
-          <div
-              v-for="(item,index) in AppJSon" :key="index">
-            <div style="height: calc(100vh - 60px);" v-show="item.stateL">
-              <div style="height: 100%;"  v-html="item.json"></div>
-            </div>
-          </div>
-        
-         <div v-if="loading" style="position: absolute;left: 0;top: 0;width: 100%;height: 100%;background-color: #fff;
-              display: flex;justify-content: center;align-items: center;">
-          <div style="display: flex;flex-direction: column;align-items: center;">
-            <img style="height: 75px;transform: scale(2);" src="../assets/img/cocoloading.gif" alt="">
-            <div style="color: #0354D7;">拼命加载中...</div>
-          </div>  
-
-         </div>
-      </div>
-    </div>
-  </div>
+	<div class="body">
+		<div class="container">
+			<div class="leftBar" style="height: 100%">
+				<sidebarL
+					@getPer="getPer"
+					@AddAppJson="AddAppJson"
+					ref="sidebarLRef"
+				></sidebarL>
+			</div>
+			<div class="table-container">
+				<div class="top">
+					<div class="topCon">
+						<div class="title">
+							<span v-if="roleUser.orgName">{{ roleUser.orgName }}</span>
+							<span style="color: #0663fe; font-weight: 600">{{
+								roleUser.schoolName
+							}}</span>
+						</div>
+						<div class="person">
+							<div class="person_name">
+								<img
+									@click="openData()"
+									style="
+										width: 40px;
+										height: 40px;
+										object-fit: cover;
+										border-radius: 50%;
+										cursor: pointer;
+									"
+									:src="
+										roleUser.headportrait
+											? roleUser.headportrait
+											: require('../assets/img/toux2.png')
+									"
+									alt=""
+								/>
+								<div class="personInfo">
+									<div class="personInfoTit">
+										{{ roleUser.username }}
+									</div>
+									<div class="personInfoBri">
+										{{ userSuffix() }}
+									</div>
+								</div>
+							</div>
+							<el-button
+								type="text"
+								@click="handleLogout"
+								style="margin-left: 20px"
+								>退出</el-button
+							>
+						</div>
+					</div>
+				</div>
+
+				<!-- 首页 -->
+				<homepageL
+					@AddAppJson="AddAppJson"
+					v-show="!appSign"
+					ref="homepageLRef"
+				></homepageL>
+
+				<!-- 循环数组展示iframe  -->
+				<div v-for="(item, index) in AppJSon" :key="index">
+					<!-- {{ item }} -->
+					<div style="height: calc(100vh - 60px)" v-show="item.stateL">
+						<iframe
+							allow="camera *; microphone *;display-capture;midi;encrypted-media;fullscreen *;"
+							frameborder="no"
+							style="border: 0; width: 100%; height: calc(100vh - 60px)"
+							:src="item.json"
+							:ref="item.toolId"
+						>
+						</iframe>
+					</div>
+				</div>
+
+				<div
+					v-if="loading"
+					style="
+						position: absolute;
+						left: 0;
+						top: 0;
+						width: 100%;
+						height: 100%;
+						background-color: #fff;
+						display: flex;
+						justify-content: center;
+						align-items: center;
+					"
+				>
+					<div
+						style="display: flex; flex-direction: column; align-items: center"
+					>
+						<img
+							style="height: 75px; transform: scale(2)"
+							src="../assets/img/cocoloading.gif"
+							alt=""
+						/>
+						<div style="color: #0354d7">拼命加载中...</div>
+					</div>
+				</div>
+			</div>
+		</div>
+	</div>
 </template>
 
 <script>
-import { mapGetters, mapActions } from 'vuex';
-import { loginOut } from '@/api/user';
-import sidebarL from '../components/sidebarL.vue';
+import { mapGetters, mapActions } from "vuex";
+import { loginOut } from "@/api/user";
+import sidebarL from "../components/sidebarL.vue";
 import { API_CONFIG } from "@/common/apiConfig";
-import store from '../store'
-import homepageL from './homepageL.vue';
-
+import store from "../store";
+import homepageL from "./homepageL.vue";
 
 export default {
-  name: "HomeView",
-  components:{
-    sidebarL,
-    homepageL
-  },
-  data() {
-    return {
-      perData:[],
-      toolList:[],
-      form:{},
-      urlAddress:'',
-      AppJSon:[],
-      loading:false
-    }
-  },
-  computed: {
-    ...mapGetters(['userinfo','appSign','userinfo2']),
-    userSuffix(){
-      let yym = ''
-      return function() {
-        
-        // this.userinfo.role == 1 && this.userinfo.rrole == 1 && this.userinfo.type == 1 && 
-        yym = Object.keys(this.userinfo2).length != 0 ? this.userinfo2 : this.userinfo
-       
-        let val = yym.accountNumber
-
-        let userName = JSON.parse(JSON.stringify(val))
-
-        const regEmail = new RegExp("^[A-Za-z0-9_-]+@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+$");
-        
-        // // 判断用户输入账户带不带后缀
-        if (!regEmail.test(userName)) {
-          console.log('111');
-        } else {
-          const parts = userName.split('@');
-          userName = parts[0];
-        }
-
-        return userName
-      }
-    },
-    roleUser(){
-      // this.userinfo.role == 1 && this.userinfo.rrole == 1 && this.userinfo.type == 1&&
-        return  Object.keys(this.userinfo2).length != 0 ? this.userinfo2 : this.userinfo
-    }
-  },
-  methods: {
-    ...mapActions({
-      logout: 'user/logout'
-    }),
-    openData(){
-        window.topU.U.MD.D.I.openApplication('my')
-    },
-    // 打开平台应用工具
-    AddAppJson(val){
-      console.log('val',val);
-
-      // 判断有没有打开过这个应用
-      let data = this.AppJSon.filter(e=>{
-        return val.toolId == e.toolId
-      })
-      // console.log('data',data);
-
-      if (data.length == 0) {   //为0则添加进列表,并将其他的展示状态改为false
-        this.loading = true
-
-        // 打开平台工具加载两秒
-        setTimeout(() => {
-          this.loading = false
-        }, 2000);
-        this.AppJSon.forEach(e=>{
-          this.$set(e, 'stateL', false); // 使用 Vue.set 确保响应式
-        })
-        this.AppJSon.push(val)
-      }else{
-        this.AppJSon.forEach(e=>{
-          if (val.toolId == e.toolId) {  //已经打开过了,将点击的工具展示状态改为false
-            this.$set(e, 'stateL', true); // 使用 Vue.set 确保响应式
-          }else{
-            this.$set(e, 'stateL', false); // 确保响应式更新
-          }
-        })
-      }
-    },
-
-    
-    async handleLogout() {
-      this.$confirm('确定退出吗', '提示', {
-        confirmButtonText: '确定',
-        cancelButtonText: '取消',
-        type: 'warning'
-      }).then(async () => {
-        loginOut()
-          .then(async () => {
-            this.$message({
-              message: '退出成功',
-              type: 'success'
-            });
-            await this.logout();
-            this.$router.push('/login');
-          })
-          .catch(err => {
-            console.error(err);
-          });
-      }).catch(() => {
-        // 取消操作
-      });
-    },
-   
-    // 获取学校权限与组织权限,优先使用学校权限,其次使用组织权限
-    getPer() {
-      // 查询首页应用
-      this.$refs.homepageLRef.getData()
-      //查询cocofrow最近使用与收藏
-      this.$refs.sidebarLRef.getData()
-
-      let params = [
-        {
-          functionName: API_CONFIG.ajax_schoolPermission.functionName, // 调用存储过程的名称
-          org: this.roleUser.org, //组织id
-          oid: this.roleUser.organizeid, //学校id
-        },
-      ];
-      
-      // 发起请求
-      this.$ajax
-        .post(API_CONFIG.baseUrl, params)
-        .then((res) => {
-          let data = res.data[0]
-          // console.log('data', data)
-          this.perData= JSON.parse(data[0].json)
-          this.getToolData()
-        })
-        .catch((err) => {
-          console.error("请求失败,错误信息:", err);
-        });
-    },
-    getToolData() {
+	name: "HomeView",
+	components: {
+		sidebarL,
+		homepageL,
+	},
+	data() {
+		return {
+			AppJSon: [],
+			loading: false,
+		};
+	},
+	computed: {
+		...mapGetters(["userinfo", "appSign", "userinfo2"]),
+		userSuffix() {
+			let yym = "";
+			return function () {
+				// this.userinfo.role == 1 && this.userinfo.rrole == 1 && this.userinfo.type == 1 &&
+				yym =
+					Object.keys(this.userinfo2).length != 0
+						? this.userinfo2
+						: this.userinfo;
+
+				let val = yym.accountNumber;
+
+				let userName = JSON.parse(JSON.stringify(val));
+
+				const regEmail = new RegExp(
+					"^[A-Za-z0-9_-]+@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+$"
+				);
+
+				// // 判断用户输入账户带不带后缀
+				if (!regEmail.test(userName)) {
+					console.log("111");
+				} else {
+					const parts = userName.split("@");
+					userName = parts[0];
+				}
+
+				return userName;
+			};
+		},
+		roleUser() {
+			// this.userinfo.role == 1 && this.userinfo.rrole == 1 && this.userinfo.type == 1&&
+			return Object.keys(this.userinfo2).length != 0
+				? this.userinfo2
+				: this.userinfo;
+		},
+	},
+	methods: {
+		...mapActions({
+			logout: "user/logout",
+		}),
+		// 打开个人信息
+		openData() {
+			window.topU.U.MD.D.I.openApplication("my");
+		},
+		// 打开平台应用工具
+		AddAppJson(val) {
+			// console.log('val',val);
+
+			// 判断有没有打开过这个应用
+			let data = this.AppJSon.filter((e) => {
+				return val.toolId == e.toolId;
+			});
+
+			if (data.length == 0) {
+				//为0则添加进列表,并将其他的展示状态改为false
+				this.loading = true;
+
+				// 打开平台工具加载两秒
+				setTimeout(() => {
+					this.loading = false;
+				}, 2000);
+
+				this.AppJSon.forEach((e) => {
+					this.$set(e, "stateL", false); // 使用 Vue.set 确保响应式
+				});
+
+				this.AppJSon.push(val);
+			} else {
+				this.AppJSon.forEach((e) => {
+					if (val.toolId == e.toolId) {
+						//已经打开过了,将点击的工具展示状态改为false
+						this.$set(e, "stateL", true); // 使用 Vue.set 确保响应式
+					} else {
+						this.$set(e, "stateL", false); // 确保响应式更新
+					}
+				});
+
+				setTimeout(() => {
+
+					console.log('this.$refs.appRef.contentWindow.document.body;', this.$refs[val.toolId][0].contentWindow.document.body);
+
+					if (!this.$refs[val.toolId][0].contentWindow.document.body) {
+						this.$refs[val.toolId][0].contentWindow.location.reload();
+					}
+				}, 2000);
+			}
+		},
+
+		async handleLogout() {
+			this.$confirm("确定退出吗", "提示", {
+				confirmButtonText: "确定",
+				cancelButtonText: "取消",
+				type: "warning",
+			})
+				.then(async () => {
+					loginOut()
+						.then(async () => {
+							this.$message({
+								message: "退出成功",
+								type: "success",
+							});
+							await this.logout();
+							this.$router.push("/login");
+						})
+						.catch((err) => {
+							console.error(err);
+						});
+				})
+				.catch(() => {
+					// 取消操作
+				});
+		},
+
+		// 获取学校权限与组织权限,优先使用学校权限,其次使用组织权限
+		async getPer() {
+			// 查询首页应用
+			this.$refs.homepageLRef.getData();
+			//查询cocofrow最近使用与收藏
+			this.$refs.sidebarLRef.getData();
+
 			let params = [
+				{
+					functionName: API_CONFIG.ajax_schoolPermission.functionName, // 调用存储过程的名称
+					org: this.roleUser.org, //组织id
+					oid: this.roleUser.organizeid, //学校id
+				},
+			];
+			// 获取学校权限与组织权限,优先使用学校权限,其次使用组织权限
+			// 第一步
+			let res = await this.$ajax.post(API_CONFIG.baseUrl, params);
+			let perData = JSON.parse(res.data[0][0].json);
+
+			// console.log('perData',JSON.parse(JSON.stringify(perData)));
+
+			// 第二步
+			let params2 = [
 				{
 					functionName: "select_desktopToolByPage",
 					status: "",
@@ -214,169 +270,228 @@ export default {
 					lim: 9999999,
 				},
 			];
-			this.$ajax
-				.post(API_CONFIG.baseUrl, params)
-				.then((res) => {
-					let _data = res.data;
-					let _list = _data[0];
-					_list.forEach((i) => {
-						i.url = JSON.parse(i.url);
-						i.json = JSON.parse(i.json);
-						i.argumentList = JSON.parse(i.argumentList);
-					});
-					this.toolList = _list;
-          // console.log('_list',_list);
-          
-					this.setDataListToo(_list);
-				})
-				.catch((err) => {
-					console.log(err);
-					this.$message.error("获取工具数据失败");
-				});
-		},
-    async setDataListToo(toolList = []) {
-      // console.log('toolList',toolList);
-      
-			let _form = JSON.parse(JSON.stringify(this.perData));
-			// _form.desktop.list.forEach((i, index) => {
-			// 	let _index = toolList.findIndex((i2) => i == i2.id);
-			// 	if (_index != -1) {
-			// 		_form.desktop.list[index] = toolList[_index];
-			// 	} else {
-			// 		console.log("无工具", i);
-			// 	}
+
+			let res2 = await this.$ajax.post(API_CONFIG.baseUrl, params2);
+			let toolList = res2.data[0];
+			toolList.forEach((i) => {
+				i.url = JSON.parse(i.url);
+				i.json = JSON.parse(i.json);
+				i.argumentList = JSON.parse(i.argumentList);
+			});
+
+			// let params3 = [
+			// 	{
+			// 		functionName: "select_schUsuallyApp",
+			// 		userid: "",
+			// 		stand: "cn",
+			// 	},
+			// ];
+
+			// let res3 = await this.$ajax.post(API_CONFIG.baseUrl, params3);
+
+			// let _list = res3.data[0];
+
+			// _list.forEach((i) => {
+			// 	i.json = JSON.parse(i.json);
 			// });
 
-			_form.admin.index.list.forEach((i, index) => {
+			// let appList = _list;
+
+			// 第三步
+			perData.desktop.list.forEach((i, index) => {
 				let _index = toolList.findIndex((i2) => i == i2.id);
 				if (_index != -1) {
-					_form.admin.index.list[index] = toolList[_index];
-          _form.admin.index.list[index].hovered = false
+					perData.desktop.list[index] = toolList[_index];
 				} else {
 					console.log("无工具", i);
 				}
 			});
+			// console.log(
+			// 	"perData.admin.cocoFlow",
+			// 	JSON.parse(JSON.stringify(perData.admin))
+			// );
+
+			// if (perData.admin.cocoFlow) {
+			// 	perData.admin.cocoFlow.forEach((i, index) => {
+			// 		let _index = appList.findIndex((i2) => i.id == i2.id);
+			// 		if (_index != -1) {
+			// 			let _setData = appList[_index];
+			// 			_setData.setIcon = i.setIcon;
+			// 			perData.admin.cocoFlow[index] = _setData;
+			// 		} else {
+			// 			console.log("无应用", i);
+			// 		}
+			// 	});
+			// }
+			// if (perData.admin.cocoFlow2) {
+			// 	perData.admin.cocoFlow2.forEach((i, index) => {
+			// 		let _index = appList.findIndex((i2) => i.id == i2.id);
+			// 		if (_index != -1) {
+			// 			let _setData = appList[_index];
+			// 			_setData.setIcon = i.setIcon;
+			// 			perData.admin.cocoFlow2[index] = _setData;
+			// 		} else {
+			// 			console.log("无应用", i);
+			// 		}
+			// 	});
+			// }
+			// if (perData.admin.CampusF && perData.admin.CampusF.appList) {
+			// 	perData.admin.CampusF.appList.forEach((i, index) => {
+			// 		let _index = appList.findIndex((i2) => i.id == i2.id);
 
-			_form.admin.sidebar.list.forEach((i, index) => {
+			// 		if (_index != -1) {
+			// 			let _setData = appList[_index];
+			// 			_setData.setIcon = i.setIcon;
+			// 			perData.admin.CampusF.appList[index] = _setData;
+			// 		} else {
+			// 			console.log("无应用", i);
+			// 		}
+			// 	});
+			// }
+
+			perData.admin.index.list.forEach((i, index) => {
+				let _index = toolList.findIndex((i2) => i == i2.id);
+				if (_index != -1) {
+					perData.admin.index.list[index] = toolList[_index];
+					perData.admin.index.list[index].hovered = false;
+				} else {
+					console.log("无工具", i);
+				}
+			});
+
+			perData.admin.sidebar.list.forEach((i, index) => {
 				if (i.children) {
 					i.children.forEach((i2, index2) => {
-						let _toolList = JSON.parse(JSON.stringify(toolList))
+						let _toolList = JSON.parse(JSON.stringify(toolList));
 						let _index = _toolList.findIndex((i3) => i2 == i3.id);
-						
+
 						if (_index != -1) {
-							_form.admin.sidebar.list[index].children[index2] = _toolList[_index];
-							_form.admin.sidebar.list[index].children[index2].typeId = _form.admin.sidebar.list[index].typeId + "," +_toolList[_index].id;
+							perData.admin.sidebar.list[index].children[index2] =
+								_toolList[_index];
+							perData.admin.sidebar.list[index].children[index2].typeId =
+								perData.admin.sidebar.list[index].typeId +
+								"," +
+								_toolList[_index].id;
 						} else {
 							console.log("无工具", i);
 						}
 					});
 				} else {
-					let _toolList = JSON.parse(JSON.stringify(toolList))
+					let _toolList = JSON.parse(JSON.stringify(toolList));
 					let _index = _toolList.findIndex((i2) => i == i2.id);
 					if (_index != -1) {
-						_form.admin.sidebar.list[index] = _toolList[_index];
-						_form.admin.sidebar.list[index].typeId =
-							_form.admin.sidebar.list[index].id;
+						perData.admin.sidebar.list[index] = _toolList[_index];
+						perData.admin.sidebar.list[index].typeId =
+							perData.admin.sidebar.list[index].id;
 					} else {
 						console.log("无工具", i);
-					} 
+					}
 				}
 			});
 
-      // console.log('_form',_form);
-      await store.commit('user/SET_FROM', _form)
-      // 获取后台管理设置常见应用
-      this.$refs.homepageLRef.getadmincocoFlow()
-      
-			this.$forceUpdate();
+			await store.commit("user/SET_FROM", perData);
+			// 获取后台管理设置常见应用
+			this.$refs.homepageLRef.getadmincocoFlow();
 		},
-  },
-  mounted() {
-    console.log('重新获取数据');
-    
-      this.getPer()
-  },
+	},
+	mounted() {
+		console.log("重新获取数据");
+		this.getPer();
+	},
 };
 </script>
 
 <style scoped>
-.top{
-  width: 100%;
-  padding: 0 90px;
-  display: flex;
-  height: 60px;
-  box-sizing: border-box;
+.top {
+	width: 100%;
+	padding: 0 90px;
+	display: flex;
+	height: 60px;
+	box-sizing: border-box;
 }
-.topCon{
-  display: flex;
-  width: 100%;
-  justify-content: space-between;
-  align-items: center;
+
+.topCon {
+	display: flex;
+	width: 100%;
+	justify-content: space-between;
+	align-items: center;
 }
+
 .body {
-  width: 100%;
-  height: 100%;
-  overflow: hidden;
-  font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
+	width: 100%;
+	height: 100%;
+	overflow: hidden;
+	font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji",
+		"Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
 }
-.title{
-  font-family: PingFang SC;
-  font-weight: 400;
-  font-size: 14px;
-  line-height: 100%;
-  letter-spacing: 0%;
-  color: #969BA3;
-  display: flex;
-  gap: 11px;
+
+.title {
+	font-family: PingFang SC;
+	font-weight: 400;
+	font-size: 14px;
+	line-height: 100%;
+	letter-spacing: 0%;
+	color: #969ba3;
+	display: flex;
+	gap: 11px;
 }
-.person{
-  display: flex;
-  align-items: center;
+
+.person {
+	display: flex;
+	align-items: center;
 }
-.person_name{
-  display: flex;
-  gap: 9px;
+
+.person_name {
+	display: flex;
+	gap: 9px;
 }
-.personInfo{
-  display: flex;
-  flex-direction: column;
-  justify-content: space-between;
-  padding: 1px 0 2px;
-  box-sizing: border-box;
+
+.personInfo {
+	display: flex;
+	flex-direction: column;
+	justify-content: space-between;
+	padding: 5px 0 2px;
+	box-sizing: border-box;
 }
-.personInfoTit{
-  font-family: PingFang SC;
-  font-weight: 500;
-  font-size: 16px;
-  line-height: 100%;
-  color: #000000;
+
+.personInfoTit {
+	font-family: PingFang SC;
+	font-weight: 500;
+	font-size: 14px;
+	line-height: 100%;
+	color: #000000;
 }
-.personInfoBri{
-  font-family: PingFang SC;
-  font-weight: 300;
-  font-size: 10px;
-  line-height: 100%;
-  color: #969BA3;
+
+.personInfoBri {
+	font-family: PingFang SC;
+	font-weight: 300;
+	font-size: 10px;
+	line-height: 100%;
+	color: #969ba3;
 }
+
 .container {
-  display: flex;
-  width: 100%;
-  height: 100vh;
+	display: flex;
+	width: 100%;
+	height: 100vh;
 }
-.container >>> .el-loading-mask{
-  z-index: 0;
+
+.container >>> .el-loading-mask {
+	z-index: 0;
 }
+
 .table-container {
-  /* display: flex;
+	/* display: flex;
   flex: 1;
   justify-content: center; */
-  width: 100%;
-  background-color: #F9FAFB;
-  position: relative;
+	width: 100%;
+	background-color: #f9fafb;
+	position: relative;
 }
-.leftBar{
-  /* box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px 6px rgb(0 0 0 / 0.1); */
-  /* overflow: visible;  */
-  z-index: 999;
+
+.leftBar {
+	/* box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px 6px rgb(0 0 0 / 0.1); */
+	/* overflow: visible;  */
+	z-index: 999;
 }
-</style>
+</style>

+ 4 - 4
src/views/homepageL.vue

@@ -14,7 +14,6 @@ import { mapGetters } from 'vuex';
 import { API_CONFIG } from "@/common/apiConfig";
 
     export default {
-        props:['urlAddress'],
         computed: {
             ...mapGetters(['userinfo','userinfo2']),
             roleUser(){
@@ -35,14 +34,15 @@ import { API_CONFIG } from "@/common/apiConfig";
         methods: {
             // 获取后台管理设置常见应用
             getadmincocoFlow(){
+                // 获取已添加cocoFlow应用
+                this.$refs.topPageRef.getData()
+
                 this.$refs.topPageRef.getAdmincocoFlow()
             },
 
             // 查询首页应用
             getData(){
-                // 获取已添加cocoFlow应用
-                this.$refs.topPageRef.getData()
-
+                
                 let params = [
                     {
                         functionName: API_CONFIG.ajax_allApp.functionName, // 调用存储过程的名称

+ 86 - 0
src/views/kanBan/components/AIApplications.vue

@@ -0,0 +1,86 @@
+<template>
+    <div class="aiApp">
+        <div class="aiTopArea">
+            <ranking />
+            <countPercentage />
+            <countPercentage />
+        </div>
+        <div class="aiMidArea">
+            <ranking :title="'创作者排名TOP5'" />
+            <div class="DataDiv">
+                <div class="DataTitle">活跃度环比增长率</div>
+                <div class="imgArea">
+                    <img src="../../../assets/img/BaseData2.png">
+                </div>
+            </div>
+        </div>
+
+        <div class="rankingArea">
+            <ranking />
+            <ranking />
+            <ranking />
+        </div>
+    </div>
+</template>
+<script>
+import ranking from './ranking.vue';
+import countPercentage from './countPercentage.vue';
+export default {
+    name: 'AIApplications',
+    components: {
+        ranking,
+        countPercentage
+    }
+}
+</script>
+<style scoped>
+.aiApp {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 41px;
+}
+
+.aiTopArea {
+    display: grid;
+    gap: 20px;
+    grid-template-columns: 326px auto auto;
+    width: 100%;
+}
+.aiMidArea {
+    display: grid;
+    grid-template-columns: 326px auto;
+    width: 100%;
+    gap: 20px;
+}
+.DataDiv {
+    background-color: #fff;
+    border-radius: 20px;
+    padding: 20px;
+    box-shadow: 0px 4px 29px rgba(0, 0, 0, 0.1);
+}
+
+.DataDiv img {
+    width: 100%;
+    height: 100%;
+}
+
+.DataTitle {
+    font-weight: bold;
+    font-size: 17px;
+}
+
+.imgArea {
+    padding: 41px;
+}
+
+.rankingArea {
+    display: grid;
+    gap: 26px;
+    background-color: #ededed;
+    padding: 20px;
+    border-radius: 20px;
+    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); 
+    width: 100%;
+}
+
+</style>

+ 85 - 71
src/views/kanBan/components/AdataKanban.vue

@@ -1,13 +1,14 @@
 <template>
     <div class="datakanban">
         <div class="barList">
-            <div @click="cutPage(index)" :class="[pageEnd == index ? 'Selected' : '' ]" v-for="(i,index) in barList" :key="index">
+            <div @click="cutPage(index)" :class="[pageEnd == index ? 'Selected' : '']" v-for="(i, index) in barList"
+                :key="index">
                 {{ i.name }}
             </div>
         </div>
 
         <div class="dataExponent">
-            <div class="dataExponentCon" v-for="(i,index) in dataExponentList[pageEnd]" :key="index + 'p'">
+            <div class="dataExponentCon" v-for="(i, index) in dataExponentList[pageEnd]" :key="index + 'p'">
                 <div class="dataExponentConTit">
                     {{ i.name }}
                 </div>
@@ -18,52 +19,46 @@
         </div>
 
         <div v-if="pageEnd == 0">
-            <img style="width: 100%;" src="../../../assets/img/uuu4.svg" alt="">
-            <!-- <div style="display: flex;flex-direction: column;">
-                <div style="display: flex;justify-content: flex-end;">
-                    <img src="../../../assets/img/cs1.svg" alt="">
-                </div>
-                <div style="display: flex;justify-content: space-between;">
-                        <img style="width: 200px;" src="../../../assets/img/uuu4.svg" alt="">
-                        <img style="width: 200px;" src="../../../assets/img/uuu5.svg" alt="">
-                </div>
-                <div style="display: flex;justify-content: space-between;">
-                    <div> <img src="../../../assets/img/cs3.svg" alt=""></div>
-                    <div> <img src="../../../assets/img/cs4.svg" alt=""></div>
-                </div>
-            </div> -->
+            <BasicData/>
+            <!-- <img style="width: 100%;" src="../../../assets/img/uuu4.svg" alt=""> -->
+
 
         </div>
         <div style="display: flex;flex-direction: column;justify-content: center;" v-if="pageEnd == 1">
-            <div style="display: flex;width: 100%;">
+            <AIApplications/>
+            
+            <!-- <div style="display: flex;width: 100%;">
                 <img style="transform: scale(1.05);" src="../../../assets/img/chart2.svg" alt="">
                 <div>
                     <img src="../../../assets/img/chart3.svg" alt="">
                     <img src="../../../assets/img/chart5.svg" alt="">
                 </div>
             </div>
-            <img style="width: 100%;"  src="../../../assets/img/uuu5.svg" alt="">
+            <img style="width: 100%;" src="../../../assets/img/uuu5.svg" alt=""> -->
         </div>
         <div v-if="pageEnd == 2">
-            <div style="display: flex;width: 100%;">
+           <RegularTeaching/>
+
+            <!-- <div style="display: flex;width: 100%;">
                 <img style="transform: scale(1.05);" src="../../../assets/img/chart6.svg" alt="">
                 <div>
                     <img src="../../../assets/img/chart10.svg" alt="">
                     <img src="../../../assets/img/chart8.svg" alt="">
                 </div>
             </div>
-            <img style="width: 100%;"  src="../../../assets/img/chart7.svg" alt="">
-            <img style="width: 100%;"  src="../../../assets/img/chart9.svg" alt="">
+            <img style="width: 100%;" src="../../../assets/img/chart7.svg" alt="">
+            <img style="width: 100%;" src="../../../assets/img/chart9.svg" alt=""> -->
         </div>
         <div v-if="pageEnd == 3">
-            <img style="width: 100%;"  src="../../../assets/img/chart11.svg" alt="">
+           <TeacherManagement/>
+            <!-- <img style="width: 100%;" src="../../../assets/img/chart11.svg" alt="">
             <div style="display: flex;width: 100%;">
                 <div>
                     <img style="object-view-box: inset(4% 16% 3% 0%);" src="../../../assets/img/chart12.svg" alt="">
                     <img style="object-view-box: inset(3% 0% 6% 0%);" src="../../../assets/img/chart13.svg" alt="">
                 </div>
                 <img style="object-view-box: inset(5% 4% 4% 4%);" src="../../../assets/img/chart14.svg" alt="">
-            </div>
+            </div> -->
         </div>
 
 
@@ -71,73 +66,88 @@
 </template>
 
 <script>
-    export default {
-        data(){
-            return{
-                barList:[
-                    {name:'基础数据',ind: 1},
-                    {name:'AI应用',ind: 2},
-                    {name:'常规教学',ind: 3},
-                    {name:'教师管理',ind: 4},
-                ],
-                dataExponentList:[
-                    [
-                        {name:'教师总量',num:1254},
-                        {name:'教师总量',num:3721},
-                        {name:'月登录总数',num:4579},
-                        {name:'月登录环比',num:'+15%'},
-                    ],[
-                        {name:'AI应用数量',num:1254},
-                        {name:'今日用户数量',num:3721},
-                        {name:'知识库数量',num:4579},
-                        {name:'文件数量',num:'+15%'},
-                    ],[
-                        {name:'课程总量',num:1254},
-                        {name:'本月新增课程',num:3721},
-                        {name:'新增课程环比',num:4579},
-                        {name:'AI应用嵌入数量',num:'272'},
-                    ],[
-                        {name:'表单总量',num:1254},
-                        {name:'表单回收率',num:3721},
-                        {name:'表单平均处理时长',num:4579},
-                        {name:'智能问答次数',num:'272'},
-                    ],
+import BasicData from './BasicData.vue';
+import AIApplications from './AIApplications.vue';
+import RegularTeaching from './RegularTeaching.vue';
+import TeacherManagement from './TeacherManagement.vue';
+export default {
+    name: 'AdataKanban',
+    components: {
+        BasicData,
+        AIApplications,
+        RegularTeaching,
+        TeacherManagement,
+    },
+    data() {
+        return {
+            barList: [
+                { name: '基础数据', ind: 1 },
+                { name: 'AI应用', ind: 2 },
+                { name: '常规教学', ind: 3 },
+                { name: '教师管理', ind: 4 },
+            ],
+            dataExponentList: [
+                [
+                    { name: '教师总量', num: 1254 },
+                    { name: '教师总量', num: 3721 },
+                    { name: '月登录总数', num: 4579 },
+                    { name: '月登录环比', num: '+15%' },
+                ], [
+                    { name: 'AI应用数量', num: 1254 },
+                    { name: '今日用户数量', num: 3721 },
+                    { name: '知识库数量', num: 4579 },
+                    { name: '文件数量', num: '+15%' },
+                ], [
+                    { name: '课程总量', num: 1254 },
+                    { name: '本月新增课程', num: 3721 },
+                    { name: '新增课程环比', num: 4579 },
+                    { name: 'AI应用嵌入数量', num: '272' },
+                ], [
+                    { name: '表单总量', num: 1254 },
+                    { name: '表单回收率', num: 3721 },
+                    { name: '表单平均处理时长', num: 4579 },
+                    { name: '智能问答次数', num: '272' },
                 ],
-                pageEnd: 0,
-            }
-        },
-        methods:{
-            cutPage(val){
-                this.pageEnd = val
-            }
+            ],
+            pageEnd: 0
+        }
+    },
+    methods: {
+        cutPage(val) {
+            this.pageEnd = val
         }
     }
+}
 </script>
 
 <style scoped>
-.datakanban{
+.datakanban {
     width: 100%;
 }
-.barList{
+
+.barList {
     display: flex;
     gap: 42px;
     font-family: PingFang SC;
     font-weight: 500;
-    font-size: 14px;
+    font-size: 16px;
     line-height: 22px;
     color: #969BA3;
     margin-bottom: 15px;
 }
-.barList > div{
+
+.barList>div {
     cursor: pointer;
     height: 23px;
     line-height: 23px;
 }
-.Selected{
+
+.Selected {
     color: #0663FE;
     border-bottom: 2px solid #0663FE;
 }
-.dataExponent{
+
+.dataExponent {
     width: 100%;
     height: 120px;
     display: grid;
@@ -148,7 +158,8 @@
     align-items: center;
     /* grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); */
 }
-.dataExponentCon{
+
+.dataExponentCon {
     display: flex;
     flex-direction: column;
     justify-content: center;
@@ -156,16 +167,19 @@
     height: 50%;
     border-right: 1px solid #D9D9D9;
 }
-.dataExponentCon:nth-child(4){
+
+.dataExponentCon:nth-child(4) {
     border: none;
 }
-.dataExponentConTit{
+
+.dataExponentConTit {
     font-family: PingFang SC;
     font-size: 14px;
     line-height: 100%;
     color: #969BA3;
 }
-.dataExponentConNum{
+
+.dataExponentConNum {
     height: 45px;
     font-family: PingFang SC;
     font-weight: 600;

+ 3 - 0
src/views/kanBan/components/AquickEntrance.vue

@@ -82,6 +82,9 @@ import { addrrole } from "@/api/user";
                     // console.log('res.data[0]',res.data[0]);
                     if (res.data[0].length) {
                         await store.commit('user/SET_USERINFO2', res.data[0][0])
+
+                        await store.commit('user/SET_AppSIGN', '')
+
                         this.loading = false
 
                         this.$router.push('/');

+ 850 - 96
src/views/kanBan/components/AschoolFeature.vue

@@ -1,124 +1,740 @@
 <template>
-    <div style="display: flex;flex-direction: column;gap: 20px;height: 100%;">
-       <div class="top">
+    <div style="display: flex; flex-direction: column; gap: 20px; height: 100%">
+        <div class="top">
             <div class="topTit">
                 <div>
                     <div>集团简介</div>
-                    <div style="height: 4px;background-color: #0663FE;width: 2rem;margin-top: 6px;"></div>
+                    <div style="
+							height: 4px;
+							background-color: #0663fe;
+							width: 2rem;
+							margin-top: 6px;
+						"></div>
                 </div>
                 <div>
+                    <img v-if="userinfo.role == 1 && userinfo.type == 1" class="topTitEdit" @click="editregion(0)"
+                        src="../../../assets/img/bianji.svg" alt="" />
                 </div>
             </div>
             <div class="Topbri">
-                深圳市荔园教育集团是一所现代化、智能化的示范性办学团体,致力于为学生提供优质的教育资源和创新的学习环境。我们采用先进的教学理念和方法,培养学生的综合素质和创新能力。
+                {{ fromL.admin.CampusF ? fromL.admin.CampusF.GroupBri : "暂无简介" }}
             </div>
-       </div>
-       <div class="feature">
+        </div>
+
+        <div class="feature">
             <div class="topTit">
                 <div>
                     <div>办学特色</div>
-                    <div style="height: 4px;background-color: #0663FE;width: 2rem;margin-top: 6px;"></div>
+                    <div style="
+							height: 4px;
+							background-color: #0663fe;
+							width: 2rem;
+							margin-top: 6px;
+						"></div>
                 </div>
                 <div>
-                    <img src="../../../assets/img/bianji.svg" alt="">
+                    <img v-if="userinfo.role == 1 && userinfo.type == 1" class="topTitEdit" @click="editregion(1)"
+                        src="../../../assets/img/bianji.svg" alt="" />
                 </div>
             </div>
 
-            <div style="display: flex;justify-content: space-between;">
-                <div class="featureCon" v-for="(i,index) in featureList" :key="index">
-                    <img style="width: 24px;" src="../../../assets/img/tese.svg" alt="">
-                    <div class="featureConTit">{{i.name}}</div>
-                    <div class="Topbri">{{i.bir}}</div>
+            <div class="featureAll">
+                <template v-if="featureList.length">
+                    <div class="featureCon" v-for="(i, index) in featureList" :key="index">
+                        <img style="width: 34px; height: 34px; object-fit: contain" :src="i.icon" alt="" />
+                        <div class="featureConTit">{{ i.name }}</div>
+
+                        <el-tooltip class="item" effect="dark" :content="i.bri" placement="bottom">
+                            <div class="Topbri2">{{ i.bri }}</div>
+                        </el-tooltip>
+                    </div>
+
+                </template>
+                <div v-else>
+                    暂无数据
                 </div>
             </div>
-       </div>
+        </div>
 
-       <div class="feature">
+        <div class="feature">
             <div class="topTit">
                 <div>
                     <div>师资力量</div>
-                    <div style="height: 4px;background-color: #0663FE;width: 2rem;margin-top: 6px;"></div>
+                    <div style="
+							height: 4px;
+							background-color: #0663fe;
+							width: 2rem;
+							margin-top: 6px;
+						"></div>
                 </div>
                 <div>
-                    <img src="../../../assets/img/bianji.svg" alt="">
+                    <img v-if="userinfo.role == 1 && userinfo.type == 1" class="topTitEdit" @click="editregion(2)"
+                        src="../../../assets/img/bianji.svg" alt="" />
                 </div>
             </div>
             <div class="Topbri">
-                深圳市荔园教育集团是一所现代化、智能化的示范性办学团体,致力于为学生提供优质的教育资源和创新的学习环境。我们采用先进的教学理念和方法,培养学生的综合素质和创新能力。
+                <el-tooltip class="item" effect="dark" :content="fromL.admin.CampusF ? fromL.admin.CampusF.teacherN.teaBri : '暂无数据'
+                    " placement="bottom">
+                    <span>
+                        {{ fromL.admin.CampusF ? fromL.admin.CampusF.teacherN.teaBri : "暂无简介" }}
+                    </span>
+                </el-tooltip>
             </div>
 
-            <div style="display: flex;justify-content: space-between;">
-                <div class="featureCon2" v-for="(i,index) in teaData" :key="index">
-                    <div class="featureConTit2">{{i.name}}</div>
-                    <div class="Topbri">{{i.bir}}</div>
+            <div class="featureAll" v-if="teaData.length">
+                <div class="featureCon2" v-for="(i, index) in teaData" :key="index">
+                    <div class="featureConTit2">{{ i.bri }}</div>
+                    <div class="Topbri">{{ i.name }}</div>
                 </div>
             </div>
-       </div>
+            <div v-else>
+                暂无数据
+            </div>
+        </div>
 
-       <div class="feature">
+        <div class="feature">
             <div class="topTit">
                 <div>
                     <div>特色应用</div>
-                    <div style="height: 4px;background-color: #0663FE;width: 2rem;margin-top: 6px;"></div>
+                    <div style="
+							height: 4px;
+							background-color: #0663fe;
+							width: 2rem;
+							margin-top: 6px;
+						"></div>
                 </div>
                 <div>
-                    <img src="../../../assets/img/bianji.svg" alt="">
+                    <img v-if="userinfo.role == 1 && userinfo.type == 1" class="topTitEdit" @click="editregion(4)"
+                        src="../../../assets/img/bianji.svg" alt="" />
                 </div>
             </div>
 
-            <div class="AppStoreList">
-                <div class="AppStore" v-for="i in 2" :key="i">
-                    <img style="width: 24px;" src="../../../assets/img/bianji.svg" alt="">
-                    <div class="AppStoreCon">
-                        <img style="width: 18px;margin-bottom: 10px;" src="../../../assets/img/tese.svg" alt="">
-                        <div class="AppStoreConTit">PBL课程设计</div>
-                        <div class="AppStoreConBri">项目式学习课程规划</div>
-                    </div>
-                    <div class="AppStoreBri">
-                        基于人工智能技术,为每位学生提供个性化的学习路径和教学内容。系统能够实时分析学习数据,调整教学策略,确保学习效果最大化。包含智能题目推荐、错题分析、知识图谱等功能。
+            <div class="AppStoreList" :class="{ 'AppStoreList2': CampusF.appList && CampusF.appList.length === 0 }">
+                <template v-if="CampusF.appList && CampusF.appList.length">
+                    <div class="AppStore" v-for="(i, index) in CampusF.appList" :key="index" @click="openNewWindow(i)">
+                        <!-- <img style="width: 24px;" src="../../../assets/img/bianji.svg" alt=""> -->
+                        <div class="AppStoreCon">
+                            <img style="
+									width: 32px;
+									height: 32px;
+									margin-bottom: 10px;
+									object-fit: contain;
+								" :src="i.setIcon ? i.setIcon : i.json.icon" alt="" />
+                            <div class="AppStoreConTit">{{ i.name }}</div>
+                            <el-tooltip class="item" effect="dark" :content="i.detail" placement="bottom">
+                                <div class="AppStoreConBri">{{ i.detail }}</div>
+                            </el-tooltip>
+                        </div>
                     </div>
+                </template>
+                <div v-else>
+                    暂无数据
                 </div>
-
-                <div  class="AppStore">
-                    <div style="height: 24px;"></div>
+                <div class="AppStore" v-if="userinfo.role == 1 && userinfo.type == 1" @click="editregion(3)"
+                    :style="{ maxWidth:CampusF.appList && CampusF.appList.length === 0 ? '301px' : 'auto' }">
+                    <!-- <div style="height: 24px;"></div> -->
                     <div class="AppAdd">
-                        <img src="../../../assets/img/add.svg" alt="">
+                        <img src="../../../assets/img/add.svg" alt="" />
                     </div>
-                    <div>
-                       
+                </div>
+            </div>
+        </div>
+
+        <!-- 修改校区特色弹框 -->
+        <el-dialog :title=editTitle :visible.sync="editVisible" close-on-click-modal class="Fedialog"
+            :before-close="handleClose">
+            <el-input v-if="isBtn === 0" type="textarea" :rows="4" placeholder="请输入内容" v-model="CampusF.GroupBri">
+            </el-input>
+
+            <el-table :data="CampusF.feature" v-if="isBtn === 1" stripe border style="width: 100%">
+                <el-table-column label="icon" min-width="200" show-overflow-tooltip>
+                    <template slot-scope="scope">
+                        <img style="height: 30px; width: 30px; object-fit: cover" :src="scope.row.icon" alt="" />
+                    </template>
+                </el-table-column>
+
+                <el-table-column label="标题" min-width="200" show-overflow-tooltip>
+                    <template slot-scope="scope">{{
+                        scope.row.name ? scope.row.name : "-"
+                    }}</template>
+                </el-table-column>
+
+                <el-table-column label="简介" min-width="200" show-overflow-tooltip>
+                    <template slot-scope="scope">{{
+                        scope.row.bri ? scope.row.bri : "-"
+                    }}</template>
+                </el-table-column>
+
+                <el-table-column label="修改" min-width="200" show-overflow-tooltip>
+                    <template slot-scope="scope">
+                        <button @click="editRunS(scope.$index, scope.row, 0)" style="
+								color: #308fff;
+								background: none;
+								border: none;
+								cursor: pointer;
+								margin-left: 25px;
+							">
+                            修改
+                        </button>
+                        <button v-if="CampusF.feature.length > 1" @click="delFe(scope.$index, 0)" style="
+								color: red;
+								background: none;
+								border: none;
+								cursor: pointer;
+								margin-left: 25px;
+							">
+                            删除
+                        </button>
+                        <button v-if="scope.$index == CampusF.feature.length - 1" @click="addCon(0)" style="
+								color: #308fff;
+								background: none;
+								border: none;
+								cursor: pointer;
+								margin-left: 25px;
+							">
+                            添加
+                        </button>
+                    </template>
+                </el-table-column>
+            </el-table>
+
+            <div class="ea_appList" v-if="isBtn === 2">
+                <el-input style="margin-bottom: 10px" type="textarea" :rows="2" resize="none" placeholder="请输入描述"
+                    v-model="CampusF.teacherN.teaBri">
+                </el-input>
+                <el-table :data="CampusF.teacherN.list" stripe border style="width: 100%">
+                    <el-table-column label="标题" min-width="200" show-overflow-tooltip>
+                        <template slot-scope="scope">
+                            {{ scope.row.name ? scope.row.name : "-" }}
+                        </template>
+                    </el-table-column>
+
+                    <el-table-column label="简介" min-width="200" show-overflow-tooltip>
+                        <template slot-scope="scope">{{
+                            scope.row.bri ? scope.row.bri : "-"
+                        }}</template>
+                    </el-table-column>
+
+                    <el-table-column label="修改" min-width="200" show-overflow-tooltip>
+                        <template slot-scope="scope">
+                            <button @click="editRunS(scope.$index, scope.row, 1)" style="
+									color: #308fff;
+									background: none;
+									border: none;
+									cursor: pointer;
+									margin-left: 25px;
+								">
+                                修改
+                            </button>
+
+                            <button v-if="CampusF.teacherN.list.length > 1" @click="delFe(scope.$index, 1)" style="
+									color: red;
+									background: none;
+									border: none;
+									cursor: pointer;
+									margin-left: 25px;
+								">
+                                删除
+                            </button>
+
+                            <button v-if="scope.$index == CampusF.teacherN.list.length - 1" @click="addCon(1)" style="
+									color: #308fff;
+									background: none;
+									border: none;
+									cursor: pointer;
+									margin-left: 25px;
+								">
+                                添加
+                            </button>
+                        </template>
+                    </el-table-column>
+                </el-table>
+            </div>
+
+            <div class="ea_appList" v-if="isBtn === 3" v-loading="appLoading">
+                <div style="
+						display: grid;
+						grid-template-columns: repeat(3, minmax(0, 1fr));
+						gap: 20px;
+					">
+                    <div class="appItem" v-for="item in allApp(appList)" :key="item.id"
+                        :class="{ appActive: isSel(item) }" @click="toggleSelection(item)">
+                        <div class="ai_left">
+                            <el-image style="width: 100%; height: 100%; cursor: pointer"
+                                :src="item.setIcon ? item.setIcon : item.json.icon" fit="cover"></el-image>
+                        </div>
+                        <div class="ai_right">
+                            <div>{{ item.name }}</div>
+                            <div class="ai_r_btn"></div>
+                            <span>{{ item.detail }}</span>
+                        </div>
                     </div>
                 </div>
             </div>
-            
-       </div>
+
+            <div class="ea_appList" v-if="isBtn === 4">
+                <el-table :data="CampusF.appList" v-if="isBtn === 4" stripe border style="width: 100%">
+                    <el-table-column label="icon" min-width="200" show-overflow-tooltip>
+                        <template slot-scope="scope">
+                            <img style="height: 30px; width: 30px; object-fit: cover" :src="scope.row.setIcon ? scope.row.setIcon : scope.row.json.icon
+                                " alt="" />
+                        </template>
+                    </el-table-column>
+
+                    <el-table-column label="名称" min-width="200" show-overflow-tooltip>
+                        <template slot-scope="scope">
+                            {{ scope.row.name }}
+                        </template>
+                    </el-table-column>
+                    <el-table-column label="简介" min-width="200" show-overflow-tooltip>
+                        <template slot-scope="scope">
+                            {{ scope.row.detail }}
+                        </template>
+                    </el-table-column>
+                    <el-table-column label="操作" min-width="200" show-overflow-tooltip>
+                        <template slot-scope="scope">
+                            <button @click="editRunS(scope.$index, scope.row, 2)" style="
+									color: #308fff;
+									background: none;
+									border: none;
+									cursor: pointer;
+									margin-left: 25px;
+								">
+                                修改
+                            </button>
+                            <button v-if="fromL.admin.CampusF.appList.length > 1" @click="delFe(scope.$index, 2)" style="
+									color: red;
+									background: none;
+									border: none;
+									cursor: pointer;
+									margin-left: 25px;
+								">
+                                删除
+                            </button>
+
+                            <!-- 上移按钮 -->
+                            <button v-if="scope.$index != 0" @click="moveUp(scope.$index)" style="
+									color: #308fff;
+									background: none;
+									border: none;
+									cursor: pointer;
+									margin-left: 10px;
+								">
+                                上移
+                            </button>
+
+                            <!-- 下移按钮 -->
+                            <button v-if="scope.$index != CampusF.appList.length - 1" @click="moveDown(scope.$index)"
+                                style="
+									color: #308fff;
+									background: none;
+									border: none;
+									cursor: pointer;
+									margin-left: 10px;
+								">
+                                下移
+                            </button>
+                        </template>
+                    </el-table-column>
+                </el-table>
+            </div>
+
+            <span slot="footer" class="dialog-footer">
+                <el-button @click="handleClose">取 消</el-button>
+                <!-- 添加特色应用按钮 -->
+                <el-button v-if="isBtn === 3" type="primary" @click="getNewApp">确定</el-button>
+                <el-button v-else type="primary" @click="setJson">确 定</el-button>
+            </span>
+        </el-dialog>
+
+        <addCampusDialog ref="addCampusDialogRef" @success="addCampusSuccess" />
     </div>
 </template>
 
 <script>
-    export default {
-        data(){
-            return{
-                featureList:[
-                    {name:'智能教育',bir:'引入AI技术,打造智能化学习环境,提供个性化教学服务。'},
-                    {name:'小班教学',bir:'采用小班制教学模式,确保每个学生都能得到充分关注。'},
-                    {name:'国际视野',bir:'开展国际交流项目,培养学生国际化视野和跨文化交际能力'},
-                    {name:'艺术教育',bir:'引入AI技术,打造智能化学习环境,提供个性化教学服务。'},
-                ],
-                teaData:[
-                    {name:'120+',bir:'专职教师'},
-                    {name:'90%',bir:'硕士及以上'},
-                    {name:'30+',bir:'市级奖项'},
-                    {name:'15+',bir:'特级教师'},
-                ]
+import { mapGetters } from "vuex";
+import { API_CONFIG } from "../../../common/apiConfig.js";
+import addCampusDialog from "./addCampusDialog";
+import { myMixin } from "@/mixins/mixin.js";
+
+import axios from "@/common/axios.config"; // 引入 axios 配置实例
+import store from "../../../store";
+
+export default {
+    mixins: [myMixin],
+
+    components: {
+        addCampusDialog,
+    },
+    data() {
+        return {
+            featureApp: [],
+            // 判断弹框是添加还是编辑
+            editTtype: 0,
+            // 添加与编辑弹框显示
+            editVisible: false,
+
+            loading: false,
+            appLoading: false,
+
+            // 判断点击的哪个部分的编辑按钮
+            isBtn: -1,
+
+            // 所有应用列表
+            appList: [],
+
+            // 页面校区特色数据
+            CampusF: [],
+
+            // 储存选择特色应用
+            selectedItem: [],
+
+            // 修改校区特色信息
+            CampusData: "",
+            CampusType: 0,
+            // 0 办学特色 1 师资力量
+            CampusNum: 0,
+        };
+    },
+    computed: {
+        ...mapGetters(["fromL", "userinfo"]),
+        featureList() {
+            if (this.fromL.admin.CampusF) {
+                return this.fromL.admin.CampusF.feature; // 从 Vuex 的 fromL 中获取 featureList
+            } else {
+                return [];
+            }
+        },
+        teaData() {
+            if (this.fromL.admin.CampusF) {
+                return this.fromL.admin.CampusF.teacherN.list; // 从 Vuex 的 fromL 中获取 teaData
+            } else {
+                return [];
+            }
+        },
+        allApp() {
+            return function (val) {
+                const difference = val.filter(
+                    (item1) =>
+                        !this.CampusF.appList.some((item2) => item1.id === item2.id)
+                );
+                return difference;
+            };
+        },
+        isSel() {
+            return function (val) {
+                let res5 = this.selectedItem.some(function (item) {
+                    return item.id == val.id;
+                });
+                return res5;
+            };
+        },
+        editTitle() {
+            if (this.isBtn == 0) return "编辑集团简介";
+            else if (this.isBtn == 1) return "编辑办学特色";
+            else if (this.isBtn == 2) return "编辑师资力量";
+            else if (this.isBtn == 3) return "添加特色应用";
+            else if (this.isBtn == 4) return "编辑特色应用";
+            else return ""; // 默认值
+        },
+    },
+    methods: {
+        // 点击区块编辑
+        async editregion(type) {
+            if (type == 3) this.getAppData();
+            this.isBtn = type;
+            this.editVisible = true;
+            this.appLoading = true;
+        },
+        handleClose() {
+            this.editVisible = false;
+            this.isBtn = -1;
+            this.appList = [];
+
+            // 修改校区特色信息
+            this.CampusData = "";
+            this.CampusType = 0;
+            // 0 办学特色 1 师资力量
+            this.CampusNum = 0;
+
+            if (this.fromL.admin.CampusF) {
+                this.CampusF = JSON.parse(JSON.stringify(this.fromL.admin.CampusF));
+            }
+        },
+        // 上移
+        moveUp(index) {
+            if (index > 0) {
+                const list = this.CampusF.appList;
+                const temp = list[index];
+                this.$set(list, index, list[index - 1]);
+                this.$set(list, index - 1, temp);
+            }
+        },
+
+        // 下移
+        moveDown(index) {
+            const list = this.CampusF.appList;
+            if (index < list.length - 1) {
+                const temp = list[index];
+                this.$set(list, index, list[index + 1]);
+                this.$set(list, index + 1, temp);
+            }
+        },
+        //  0 办学特色 1 师资力量
+        addCon(type) {
+            this.CampusType = type;
+
+            // this.CampusF.feature.push({bri:'',icon:'',name:''})
+            if (type == 0) {
+                this.CampusNum = this.CampusF.feature.length;
+                this.$refs.addCampusDialogRef.open({ bri: "", icon: "", name: "" },
+                    type,
+                    "添加办学特色"
+                );
+            } else {
+                this.CampusNum = this.CampusF.teacherN.list.length;
+                this.$refs.addCampusDialogRef.open({ bri: "", name: "" },
+                    1,
+                    "添加师资力量"
+                );
+            }
+        },
+        // // 添加师资力量
+        // add2() {
+        // 	this.CampusType = 1;
+        // 	this.$refs.addCampusDialogRef.open({ bri: "", name: "" }, 1);
+
+        // 	// this.CampusF.teacherN.list.push()
+        // },
+        // 修改办学特色
+        editRunS(index, val, type) {
+            this.CampusData = val;
+            this.CampusType = type;
+            this.CampusNum = index;
+            this.$refs.addCampusDialogRef.open(val, type);
+        },
+        //修改 0 办学特色 1 师资力量 2 特色应用
+        addCampusSuccess(val) {
+            console.log("val", val);
+            console.log("CampusType", this.CampusType);
+
+            if (this.CampusType == 0) {
+                this.CampusF.feature.splice(this.CampusNum, 1, val.item);
+            } else if (this.CampusType == 1) {
+                this.CampusF.teacherN.list.splice(this.CampusNum, 1, val.item);
+            } else {
+                this.CampusF.appList.splice(this.CampusNum, 1, val.item);
+            }
+        },
+        // 删除办学特色
+        delFe(index, type) {
+            this.$confirm('确定要删除吗?', '提示', {
+                confirmButtonText: '确定',
+                cancelButtonText: '取消',
+                type: 'warning',
+            })
+                .then(() => {
+                    // 用户点击“确定”后执行删除操作
+                    if (type == 0) {
+                        this.CampusF.feature.splice(index, 1);
+                    } else if (type == 1) {
+                        this.CampusF.teacherN.list.splice(index, 1);
+                    } else {
+                        this.CampusF.appList.splice(index, 1);
+                    }
+                    this.$message.success('删除成功!');
+                })
+                .catch(() => {
+                    // 用户点击“取消”后执行的操作
+                    this.$message.error('已取消删除');
+                });
+        },
+        moveApp() { },
+        getAppData() {
+            return new Promise((resolve) => {
+                let params = [
+                    {
+                        functionName: "select_schUsuallyApp",
+                        userid: "",
+                        stand: "cn",
+                    },
+                ];
+                this.loading = true;
+                this.$ajax
+                    .post(API_CONFIG.baseUrl, params)
+                    .then((res) => {
+                        let _data = res.data;
+                        let _list = _data[0];
+                        _list.forEach((i) => {
+                            i.json = JSON.parse(i.json);
+                        });
+                        this.appList = _list;
+                        this.appLoading = false;
+                        // console.log('_list', _list);
+
+                        // this.loading = false;
+                        resolve(_list);
+                    })
+                    .catch((err) => {
+                        console.log(err);
+                        // this.loading = false;
+                        this.$message.error("获取应用数据失败");
+                        // this.close();
+                    });
+            });
+        },
+        toggleSelection(item) {
+            const index = this.selectedItem.findIndex((user) => user.id === item.id);
+
+            if (index == -1) {
+                this.selectedItem.push(item);
+            } else {
+                this.selectedItem.splice(index, 1);
             }
+        },
+
+        // 添加选中的应用
+        getNewApp() {
+            if (this.selectedItem.length == 0) {
+                this.$message.warning("请先选择一个应用!");
+                return;
+            }
+
+            this.CampusF.appList = [...this.CampusF.appList, ...this.selectedItem];
+
+            this.selectedItem = []; // 清空选中状态
+            this.editVisible = false;
+            this.setJson();
+        },
+        openNewWindow(val) {
+            console.log(val);
+            this.addOp3('1', "", { id: val.id, name: val.name, type: this.prefixL + "appstoreOpen" }, "success")
+
+            // // 基本用法:打开指定 URL
+            window.open(val.url, "_blank");
+        },
+        // 提交
+        setJson() {
+            this.loading = true;
+
+            let _form = JSON.parse(JSON.stringify(this.fromL));
+
+            _form.desktop.list = _form.desktop.list.map((i) => i.id);
+
+            _form.admin.index.list = _form.admin.index.list.map((i) => i.id);
+
+            _form.admin.sidebar.list.forEach((i, index) => {
+                if (i.children) {
+                    _form.admin.sidebar.list[index].children = i.children.map(
+                        (i) => i.id
+                    );
+                } else {
+                    _form.admin.sidebar.list[index] = i.id;
+                }
+            });
+
+            _form.admin.cocoFlow = _form.admin.cocoFlow
+                ? _form.admin.cocoFlow.map((i) => { return { id: i.id, setIcon: i.setIcon } }) : [];
+
+            _form.admin.cocoFlow2 = _form.admin.cocoFlow2
+                ? _form.admin.cocoFlow2.map((i) => { return { id: i.id, setIcon: i.setIcon } }) : [];
+
+            _form.admin.CampusF = JSON.parse(JSON.stringify(this.CampusF));
+
+            _form.admin.CampusF.appList = _form.admin.CampusF.appList.length
+                ? _form.admin.CampusF.appList.map((i) => { return { id: i.id, setIcon: i.setIcon } }) : [];
+
+            console.log("_form", _form);
+            let params = [
+                {
+                    functionName: "update_orgOroid_json_byId",
+                    id: this.userinfo.organizeid,
+                    ujson: JSON.stringify(_form),
+                    type: "school",
+                },
+            ];
+            axios
+                .post(API_CONFIG.baseUrl, params)
+                .then(async (res) => {
+                    let _data = res.data;
+                    if (_data == 1) {
+                        this.$message.success("修改权限成功");
+                        // this.$emit("getData");
+
+                        await store.dispatch("user/getschPerInfo");
+
+                        // await addOp({
+                        // 	uid: this.userid,
+                        // 	cid: this.data.id,
+                        // 	type: "user_op",
+                        // 	content: `修改了${this.data.name}的权限设置`,
+                        // });
+                        this.handleClose();
+
+                        this.addOp3(
+                            "1",
+                            "",
+                            {
+                                uid: this.userinfo.userid,
+                                cid: this.userinfo.organizeid,
+                                type: "user_op",
+                                content: `修改了${this.userinfo.schoolName}的权限设置`,
+                            },
+                            "success"
+                        );
+                    } else {
+                        this.$message.error("修改权限失败");
+                    }
+                    this.loading = false;
+                })
+                .catch((err) => {
+                    console.log(err);
+                    this.loading = false;
+                    this.$message.error("修改权限失败");
+
+                    this.addOp3(
+                        "1",
+                        "",
+                        {
+                            uid: this.userid,
+                            cid: this.data.id,
+                            type: "user_op",
+                            content: `修改了${this.data.name}的权限设置`,
+                        },
+                        err
+                    );
+                });
+        },
+    },
+    mounted() {
+        if (this.fromL.admin.CampusF) {
+            this.CampusF = JSON.parse(JSON.stringify(this.fromL.admin.CampusF));
+        } else {
+            this.CampusF = {
+                GroupBri: "暂无简介",
+                feature: [
+                    {
+                        bri: "暂无简介",
+                        icon: "https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/tese1745913146000.svg",
+                        name: "默认标题",
+                    },
+                ],
+                teacherN: {
+                    teaBri: "暂无简介",
+                    list: [{ bri: "默认标题", name: "暂无数据" }],
+                },
+                appList: [],
+            };
         }
-    }
+        console.log("CampusF", this.CampusF.appList);
+    },
+};
 </script>
 
 <style scoped>
-.top{
+.top {
     height: 159px;
-    padding: 36px  27px;
+    padding: 36px 27px;
     box-sizing: border-box;
     display: flex;
     flex-direction: column;
@@ -126,38 +742,58 @@
     border-radius: 12px;
     justify-content: space-between;
 }
-.topTit{
+
+.topTit {
     font-family: PingFang SC;
     font-weight: 600;
-    font-size: 20px;
+    font-size: 18px;
     line-height: 22px;
-    color: #0663FE;
+    color: #0663fe;
     display: flex;
     height: 36px;
     justify-content: space-between;
 }
-.Topbri{
+
+.topTit .topTitEdit {
+    cursor: pointer;
+}
+
+.Topbri {
     font-family: PingFang SC;
     font-weight: 400;
-    font-size: 12px;
+    font-size: 14px;
     line-height: 22px;
     color: #000;
 }
-.feature{
+
+.Topbri2 {
+    font-family: PingFang SC;
+    font-weight: 400;
+    font-size: 14px;
+    color: #000;
+    display: -webkit-box;
+    -webkit-line-clamp: 2;
+    -webkit-box-orient: vertical;
+    overflow: hidden;
+    text-overflow: ellipsis;
+}
+
+.feature {
     width: 100%;
     padding: 36px 27px;
     border-radius: 12px;
     box-sizing: border-box;
-    background: #EEEEEE;
+    background: #eeeeee;
     display: flex;
     flex-direction: column;
     gap: 20px;
     justify-content: space-between;
 }
-.featureCon{
-    background: #FFFFFF;
-    width: 24%;
-    height: 206px;
+
+.featureCon {
+    background: #ffffff;
+    width: 100%;
+    height: 211px;
     display: flex;
     flex-direction: column;
     justify-content: center;
@@ -167,9 +803,16 @@
     box-sizing: border-box;
     gap: 18px;
 }
-.featureCon2{
-    background: #FFFFFF;
-    width: 24%;
+
+.featureAll {
+    grid-template-columns: repeat(4, 1fr);
+    display: grid;
+    gap: 20px;
+}
+
+.featureCon2 {
+    background: #ffffff;
+    width: 100%;
     height: 94px;
     display: flex;
     flex-direction: column;
@@ -180,63 +823,174 @@
     box-sizing: border-box;
     gap: 10px;
 }
-.featureConTit{
+
+.featureConTit {
     font-family: PingFang SC;
     font-weight: 600;
-    font-size: 20px;
+    font-size: 18px;
     line-height: 22px;
     color: #000;
 }
-.featureConTit2{
+
+.featureConTit2 {
     font-family: PingFang SC;
     font-weight: 600;
     font-size: 20px;
     line-height: 22px;
-    color: #0663FE;
+    color: #0663fe;
 }
-.AppStoreList{
-    display: flex;
+
+.AppStoreList {
+    display: grid;
+    grid-template-columns: repeat(auto-fit, minmax(20%, 1fr));
     gap: 20px;
 }
-.AppStore{
-    width: 33%;
+
+.AppStoreList2 {
+    display: flex;
+    flex-direction: column;
+}
+
+.AppStore {
     display: flex;
     flex-direction: column;
     gap: 10px;
+    min-height: 171px;
+    min-width: 100px;
+    cursor: pointer;
 }
-.AppStoreCon{
-    height: 122px;
+
+.AppStoreCon {
     border-radius: 10px;
     padding: 17px 17px;
+    height: 100%;
     box-sizing: border-box;
     background: #fff;
 }
-.AppAdd{
-    height: 122px;
+
+.AppAdd {
+    height: 171px;
     border-radius: 10px;
     padding: 17px 17px;
     box-sizing: border-box;
     border: 1px dashed #000000;
-    background: #E5E5E5;
+    background: #e5e5e5;
     display: flex;
     justify-content: center;
     align-items: center;
 }
-.AppStoreConTit{
+
+.AppStoreConTit {
     font-family: PingFang SC;
     font-weight: 500;
     font-size: 16px;
     margin-bottom: 5px;
+    display: -webkit-box;
+    -webkit-line-clamp: 2;
+    -webkit-box-orient: vertical;
+    overflow: hidden;
+    text-overflow: ellipsis;
 }
-.AppStoreConBri{
+
+.AppStoreConBri {
     font-family: PingFang SC;
     font-weight: 300;
-    font-size: 12px;
-    color: #969BA3;
+    font-size: 14px;
+    color: #969ba3;
+    display: -webkit-box;
+    -webkit-line-clamp: 2;
+    -webkit-box-orient: vertical;
+    overflow: hidden;
+    text-overflow: ellipsis;
 }
-.AppStoreBri{
+
+.AppStoreBri {
     font-family: PingFang SC;
     font-size: 10px;
-    color: #969BA3;
+    color: #969ba3;
+}
+
+.appItem {
+    height: 100px;
+    background-color: white;
+    box-sizing: border-box;
+    border: solid 1px #f3f4f6;
+    padding: 10px;
+    border-radius: 8px;
+    cursor: pointer;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    transition: 0.3s;
+}
+
+.appActive {
+    border-color: #409eff;
+    box-shadow: 0px 6px 30px 5px #00000015;
+}
+
+.appItem:hover {
+    box-shadow: 0px 6px 30px 5px #00000015;
+}
+
+.ai_left {
+    width: 80px;
+    height: 80px;
+    box-sizing: border-box;
+    padding: 10px;
+    margin-right: 10px;
+}
+
+.ai_right {
+    width: calc(100% - 80px - 10px);
+    position: relative;
+}
+
+.ai_right>div {
+    max-width: calc(100% - 50px);
+    font-weight: bold;
+    overflow: hidden;
+    white-space: nowrap;
+    text-overflow: ellipsis;
+    font-size: 16px;
+    color: #000;
+    margin-bottom: 10px;
+}
+
+.ai_right>span {
+    font-size: 14px;
+    color: #00000099;
+    display: -webkit-box;
+    -webkit-box-orient: vertical;
+    -webkit-line-clamp: 2;
+    overflow: hidden;
+    text-overflow: ellipsis;
+}
+
+.Fedialog>>>.el-dialog {
+    width: 60% !important;
+    min-width: 1000px;
+    overflow: hidden;
+    margin-top: 10vh !important;
+}
+
+.Fedialog>>>.el-dialog__header {
+    padding: 15px 20px;
+    background: #454545;
+}
+
+.Fedialog>>>.el-dialog__body {
+    max-height: 70vh;
+    /* 内容区域最大高度为视口高度的 70% */
+    overflow-y: auto;
+    /* 当内容超出时显示滚动条 */
+    padding: 20px;
+    /* 添加内边距 */
+    box-sizing: border-box;
+    /* 确保 padding 不影响宽度计算 */
+}
+
+.Fedialog>>>.el-dialog__title {
+    color: #fff;
 }
-</style>
+</style>

+ 188 - 0
src/views/kanBan/components/BasicData.vue

@@ -0,0 +1,188 @@
+<template>
+    <div class="chartArea">
+        <div class="selectDateArea">
+            <div class="selectDate">
+                <div class='dateDiv' v-for="(i, index) in DateList" :key="index"
+                    :class="{ 'active': selectedDate === index }" @click="selectDate(index)">{{ i.date }}</div>
+            </div>
+        </div>
+        <div class="BaseData">
+            <div class="BaseDataArea1">
+                <div class="DataDiv">
+                    <div class="DataTitle">教师活跃度</div>
+                    <div class="imgArea">
+                        <img src="../../../assets/img/BaseData1.png" alt="">
+                    </div>
+
+                </div>
+
+                <div class="DataDiv">
+                    <div class="DataTitle">活跃度环比增长率</div>
+                    <div class="imgArea">
+                        <img src="../../../assets/img/BaseData2.png" alt="">
+                    </div>
+                </div>
+            </div>
+            <div class="BaseDataArea2">
+                <div class="DataDiv">
+                    <div class="DataTitle">应用使用分类</div>
+                    <div class="useCount">
+                        <div class="useItem">
+                            <div class="useColor" style="background-color: #3681fc;"></div>
+                            <div>高频</div>
+                            <div>45%</div>
+                            <div>(40-80人)</div>
+                        </div>
+                        <div class="useItem">
+                            <div class="useColor" style="background-color:#1f94ff;"></div>
+                            <div>中高频</div>
+                            <div>30%</div>
+                            <div>(0-25人)</div>
+                        </div>
+                        <div class="useItem">
+                            <div class="useColor" style="background-color:#8979ff;"></div>
+                            <div>中频</div>
+                            <div>45%</div>
+                            <div>(0-25人)</div>
+                        </div>
+                        <div class="useItem">
+                            <div class="useColor" style="background-color:#f4cf3b;"></div>
+                            <div>低频</div>
+                            <div>45%</div>
+                            <div>(0-25人)</div>
+                        </div>
+
+                    </div>
+                    <div class="imgArea" style="padding: 41px 82px;">
+                        <img src="../../../assets/img/BaseData3.png" alt="">
+                    </div>
+                </div>
+                <div class="DataDiv">
+                    <div class="DataTitle">使用时长</div>
+                    <div class="imgArea">
+                        <img src="../../../assets/img/BaseData4.png" alt="">
+                    </div>
+                </div>
+            </div>
+        </div>
+
+    </div>
+</template>
+<script>
+export default {
+    name: 'BasicData',
+    data() {
+        return {
+            DateList: [
+                { date: '年' },
+                { date: '月' },
+                { date: '日' },
+            ],
+            selectedDate: 0
+        }
+    },
+    methods: {
+        selectDate(index) {
+            this.selectedDate = index;
+        }
+    }
+}
+</script>
+<style scoped>
+.chartArea {
+    background-color: #eaeaea;
+    border-radius: 20px;
+}
+
+
+.selectDateArea {
+    display: flex;
+    justify-content: flex-end;
+    padding: 30px 35px;
+}
+
+.selectDate {
+    display: flex;
+    justify-content: center;
+    height: 30px;
+    background-color: #fff;
+    border-radius: 20px;
+    gap: 17px;
+    box-shadow: 0px 4px 29px rgba(0, 0, 0, 0.1);
+}
+
+.dateDiv {
+    width: 63px;
+    line-height: 30px;
+    text-align: center;
+    border-radius: 15px;
+    cursor: pointer;
+    font-weight: bold;
+    font-size: 17px;
+}
+
+.dateDiv.active {
+    background-color: black;
+    color: #fff;
+}
+
+.BaseData {
+    display: flex;
+    flex-wrap: wrap;
+    padding-bottom: 30px;
+    margin: 10px 38px;
+    gap: 29px;
+}
+.BaseDataArea1{
+    display: grid;
+    gap: 20px;
+    /* grid-template-columns: repeat(2, 1fr); */
+    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); 
+    width: 100%;
+}
+.BaseDataArea2{
+    display: grid;
+    gap: 20px;
+    grid-template-columns: 470px auto;
+    width: 100%;
+}
+.DataDiv {
+    background-color: #fff;
+    border-radius: 20px;
+    padding: 20px;
+    box-shadow: 0px 4px 29px rgba(0, 0, 0, 0.1);
+}
+
+.DataDiv img {
+    width: 100%;
+    height: 100%;
+}
+
+.DataTitle {
+    font-weight: bold;
+    font-size: 17px;
+}
+
+.imgArea {
+    padding: 41px;
+}
+
+.useCount {
+    display: grid;
+    justify-content: end;
+    gap: 5px;
+}
+
+.useItem {
+    display: flex;
+    align-items: center;
+    gap: 8px;
+    font-size: 12px;
+}
+
+.useColor {
+    width: 11px;
+    border-radius: 10px;
+    height: 11px;
+}
+</style>

+ 282 - 0
src/views/kanBan/components/RegularTeaching.vue

@@ -0,0 +1,282 @@
+<template>
+    <div class="tradTea">
+        <div class="tradTeaArea1">
+            <ranking />
+            <div class="DataDiv">
+                <div class="DataTitle">课程分布</div>
+                <div class="imgArea">
+                    <img src="../../../assets/img/BaseData5.png" alt="">
+                </div>
+            </div>
+        </div>
+        <div class="tradTeaArea2">
+            <ranking />
+            <countPercentage :title="'AI辅助设计分析'" />
+            <div class="DataDiv">
+                <div class="DataTitle"> 使用分析</div>
+                <div class="aiUseCount">
+                    <div class="aiUseArea">
+                        <div class="aiUseItem">
+                            <div class="useColor" style="background-color: #3681fc;"></div>
+                            <div>高频</div>
+                            <div>45%</div>
+                            <div>(40-80人)</div>
+                        </div>
+                        <div class="aiUseItem">
+                            <div class="useColor" style="background-color:#1f94ff;"></div>
+                            <div>中高频</div>
+                            <div>30%</div>
+                            <div>(0-25人)</div>
+                        </div>
+                    </div>
+                    <div class="aiUseArea">
+                        <div class="aiUseItem">
+                            <div class="useColor" style="background-color:#8979ff;"></div>
+                            <div>中频</div>
+                            <div>45%</div>
+                            <div>(0-25人)</div>
+                        </div>
+                        <div class="aiUseItem">
+                            <div class="useColor" style="background-color:#f4cf3b;"></div>
+                            <div>低频</div>
+                            <div>45%</div>
+                            <div>(0-25人)</div>
+                        </div>
+                    </div>
+
+
+                </div>
+                <div class="imgArea">
+                    <img src="../../../assets/img/BaseData6.png" alt="">
+                </div>
+            </div>
+        </div>
+        <div class="DataDiv" style="width: 100%;">
+            <div class="DataTitle">AI与教学融合度</div>
+
+            <div class="imgArea" style="display: flex;align-items: center;">
+                <img src="../../../assets/img/BaseData7.png">
+                <img src="../../../assets/img/BaseData8.png">
+            </div>
+        </div>
+        <div class="classArea">
+            <div class="DataDiv">
+                <div class="DataTitle">课堂模块占分析</div>
+                <div class="classDiv">
+                    <div class="imgArea" style="padding: 41px 68px;">
+                        <img src="../../../assets/img/BaseData3.png">
+                    </div>
+                    <div class="useCount">
+                        <div class="useItem">
+                            <div class="useColor" style="background-color: #3681fc;"></div>
+                            <div>高频</div>
+                            <div>45%</div>
+                            <div>(40-80人)</div>
+                        </div>
+                        <div class="useItem">
+                            <div class="useColor" style="background-color:#1f94ff;"></div>
+                            <div>中高频</div>
+                            <div>30%</div>
+                            <div>(0-25人)</div>
+                        </div>
+                        <div class="useItem">
+                            <div class="useColor" style="background-color:#8979ff;"></div>
+                            <div>中频</div>
+                            <div>45%</div>
+                            <div>(0-25人)</div>
+                        </div>
+                        <div class="useItem">
+                            <div class="useColor" style="background-color:#f4cf3b;"></div>
+                            <div>低频</div>
+                            <div>45%</div>
+                            <div>(0-25人)</div>
+                        </div>
+
+                    </div>
+                </div>
+
+            </div>
+            <div class="DataDiv">
+                <div class="DataTitle">课堂观察综合结果</div>
+                <div class="classView">
+                    <div class="imgArea">
+                        <img src="../../../assets/img/BaseData9.png">
+                    </div>
+                    <div class="useCountArea">
+                        <div class="useCount">
+                            <div class="useItem">
+                                <div class="useColor" style="background-color: #3681fc;"></div>
+                                <div>高频</div>
+                                <div>45%</div>
+                                <div>(40-80人)</div>
+                            </div>
+                            <div class="useItem">
+                                <div class="useColor" style="background-color:#1f94ff;"></div>
+                                <div>中高频</div>
+                                <div>30%</div>
+                                <div>(0-25人)</div>
+                            </div>
+                            <div class="useItem">
+                                <div class="useColor" style="background-color:#8979ff;"></div>
+                                <div>中频</div>
+                                <div>45%</div>
+                                <div>(0-25人)</div>
+                            </div>
+                            <div class="useItem">
+                                <div class="useColor" style="background-color:#f4cf3b;"></div>
+                                <div>低频</div>
+                                <div>45%</div>
+                                <div>(0-25人)</div>
+                            </div>
+
+                        </div>
+                        <div class="allRating">
+                            <div class="ratingText1">总体评价</div>
+                            <div class="ratingText2">综合得分:7.7</div>
+                            <div class="ratingText2">状态:良好</div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+
+    </div>
+</template>
+<script>
+import ranking from './ranking.vue'
+import countPercentage from './countPercentage.vue'
+export default {
+    name: 'RegularTeaching',
+    components: {
+        ranking,
+        countPercentage
+    },
+}
+</script>
+<style scoped>
+.tradTea {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 41px;
+}
+
+.tradTeaArea1 {
+    display: grid;
+    grid-template-columns: 326px auto;
+    width: 100%;
+    gap: 20px;
+}
+.tradTeaArea2 {
+    display: grid;
+    grid-template-columns: 326px auto auto;
+    width: 100%;
+    gap: 20px;
+}
+.DataDiv {
+    background-color: #fff;
+    border-radius: 20px;
+    padding: 20px;
+    box-shadow: 0px 4px 29px rgba(0, 0, 0, 0.1);
+}
+
+.DataDiv img {
+    width: 100%;
+    height: 100%;
+}
+
+.DataTitle {
+    font-weight: bold;
+    font-size: 17px;
+}
+
+.imgArea {
+    padding: 41px;
+}
+
+.aiUseCount {
+    display: flex;
+    gap: 28px;
+}
+
+.aiUseArea {
+    margin-top: 10px;
+}
+
+.aiUseItem {
+    display: flex;
+    align-items: center;
+    gap: 8px;
+    font-size: 12px;
+    margin-top: 5px;
+}
+
+.useColor {
+    width: 11px;
+    border-radius: 10px;
+    height: 11px;
+}
+
+.classDiv {
+    display: flex;
+    align-items: center;
+}
+
+.useCountArea {
+    display: flex;
+    flex-direction: column;
+    justify-content: space-between;
+    margin: 26px;
+}
+
+.useCount {
+    display: grid;
+    justify-content: end;
+    gap: 5px;
+}
+
+.useItem {
+    display: flex;
+    align-items: center;
+    gap: 8px;
+    font-size: 12px;
+}
+
+.useColor {
+    width: 11px;
+    border-radius: 10px;
+    height: 11px;
+}
+
+.allRating {
+    background-color: #fff;
+    border-radius: 20px;
+    padding: 20px;
+    box-shadow: 0px 4px 29px rgba(0, 0, 0, 0.1);
+    display: flex;
+    flex-direction: column;
+    gap: 10px;
+}
+
+.ratingText1 {
+    color: #0663fe;
+}
+
+.ratingText2 {
+    font-size: 14px;
+    color: #969ba3;
+}
+
+.classArea {
+    display: grid;
+    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); 
+    width: 100%;
+    gap: 26px;
+    background-color: #ededed;
+    padding: 30px;
+    border-radius: 20px;
+}
+
+.classView {
+    display: flex;
+}
+</style>

+ 66 - 0
src/views/kanBan/components/TeacherManagement.vue

@@ -0,0 +1,66 @@
+<template>
+    <div class="teaManage">
+        <div class="DataDiv" style="width: 100%;">
+            <div class="DataTitle">AI与教学融合度</div>
+
+            <div class="imgArea" style="display: flex;align-items: center;">
+                <img src="../../../assets/img/BaseData7.png">
+                <img src="../../../assets/img/BaseData8.png">
+            </div>
+        </div>
+        <div class="teaManageArea">
+            <countPercentage :title="'流程自定义分类'" />
+            <ranking :title="'流程自定义分析'" />
+
+            <div class="DataDiv">
+                <div class="DataTitle">智能问答词云</div>
+            </div>
+        </div>
+
+    </div>
+</template>
+<script>
+import ranking from './ranking.vue'
+import countPercentage from './countPercentage.vue'
+export default {
+    name: 'TeacherManagement',
+    components: {
+        ranking,
+        countPercentage
+    },
+}
+</script>
+<style scoped>
+.teaManage {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 41px;
+}
+
+.DataDiv {
+    background-color: #fff;
+    border-radius: 20px;
+    padding: 20px;
+    box-shadow: 0px 4px 29px rgba(0, 0, 0, 0.1);
+}
+
+.DataTitle {
+    font-weight: bold;
+    font-size: 17px;
+}
+
+.imgArea {
+    padding: 41px;
+}
+
+.DataDiv img {
+    width: 100%;
+    height: 100%;
+}
+.teaManageArea {
+    display: grid;
+    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); 
+    width: 100%;
+    gap: 20px;
+}
+</style>

+ 212 - 0
src/views/kanBan/components/addCampusDialog.vue

@@ -0,0 +1,212 @@
+<template>
+	<div>
+		<el-dialog :title="dialogTitle" class="table" :visible.sync="show" :close-on-click-modal="false" width="800px"
+			top="8vh">
+			<div v-loading="loading">
+				<el-image style="
+						width: 50px;
+						height: 50px;
+						cursor: pointer;
+						display: flex;
+						align-items: center;
+						justify-content: center;
+					" :src="form.icon" fit="cover" v-if="this.type === 2" @click="addUrlIcon()">
+					<div slot="error" class="image-slot" @click="addUrlIcon()">
+						<i class="el-icon-picture-outline"></i>
+					</div>
+				</el-image>
+
+				<el-image style="
+						width: 50px;
+						height: 50px;
+						cursor: pointer;
+						display: flex;
+						align-items: center;
+						justify-content: center;
+					" :src="form.icon" fit="cover" v-if="this.type === 0" @click="addUrlIcon()">
+					<div slot="error" class="image-slot" @click="addUrlIcon()">
+						<i class="el-icon-picture-outline"></i>
+					</div>
+				</el-image>
+
+				<div v-if="this.type != 2">
+					<div class="Tit">标题</div>
+					<div>
+						<el-input v-model="form.name" placeholder="请输入内容"></el-input>
+					</div>
+				</div>
+
+				<div v-if="this.type != 2">
+					<div class="Tit">描述</div>
+					<div>
+						<el-input type="textarea" :rows="3" resize="none" placeholder="请输入描述" v-model="form.bri">
+						</el-input>
+					</div>
+				</div>
+			</div>
+			<!-- 按钮区域 -->
+			<div slot="footer" class="el-dialog__footer">
+				<el-button @click="close()">取 消</el-button>
+				<el-button type="primary" @click="submit()">确认</el-button>
+			</div>
+		</el-dialog>
+	</div>
+</template>
+
+<script>
+import "@/common/aws-sdk-2.235.1.min.js";
+export default {
+	data() {
+		return {
+			show: false,
+			loading: false,
+			form: {
+				name: "",
+				icon: "",
+				bri: "",
+			},
+			form2:{},
+			type: null,
+			title: "",
+		};
+	},
+	computed: {
+		dialogTitle() {
+			return this.title || (this.type === 0
+            ? "修改办学特色"
+            : this.type === 1
+            ? "修改师资力量"
+            : this.type === 2
+            ? "修改特色应用"
+            : "");
+		},
+	},
+	methods: {
+		open(data, type, title = "") {
+			this.type = type;
+			this.title = title;
+
+			// 根据 type 处理图片字段
+			if (type === 2) {
+				this.form2 = JSON.parse(JSON.stringify(data));
+
+				// 如果是特色应用,图片在 form.json.icon
+				this.form.icon = data.setIcon ?  data.setIcon : data.json.icon; // 确保 json 存在,避免报错
+			}else{
+				this.form = JSON.parse(JSON.stringify(data));
+			}
+			this.show = true;
+		},
+		close() {
+			this.show = false;
+			this.init();
+		},
+		init() {
+			this.form = {
+				name: "",
+				icon: "",
+				bri: "",
+			};
+			this.title = "";
+		},
+		submit() {
+			if (this.type == 0) {
+				if (!this.form.name || !this.form.icon || !this.form.bri)
+					return this.$message.error("请完善表单");
+			} else if (this.type == 1) {
+				if (!this.form.name || !this.form.bri)
+					return this.$message.error("请完善表单");
+			} else if (this.type == 2) {
+				if (!this.form.icon) {
+					return this.$message.error("请完善表单");
+				}
+				let data = JSON.parse(JSON.stringify(this.form.icon))
+				this.form2.setIcon = data 
+				this.form = this.form2
+			}
+			this.$emit("success", { item: this.form });
+			this.close()
+		},
+		async addUrlIcon() {
+			let _url = await this.uploadFile("image/*");
+			console.log("addUrlIcon", _url);
+
+			if (_url) {
+				this.form.icon = _url;	
+			} else {
+				return console.log("无图片");
+			}
+		},
+		uploadFile(accept = "*") {
+			return new Promise((resolve) => {
+				const input = document.createElement("input");
+				input.type = "file";
+				input.accept = accept;
+				input.onchange = (event) => {
+					const file = event.target.files[0];
+					if (file) {
+						let credentials = {
+							accessKeyId: "AKIATLPEDU37QV5CHLMH",
+							secretAccessKey: "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",
+						}; //秘钥形式的登录上传
+						window.AWS.config.update(credentials);
+						window.AWS.config.region = "cn-northwest-1"; //设置区域
+						let bucket = new window.AWS.S3({ params: { Bucket: "ccrb" } }); //选择桶
+						// let _name = file.name;
+						// let size = file.size;
+						let params = {
+							Key:
+								file.name.split(".")[0] +
+								new Date().getTime() +
+								"." +
+								file.name.split(".")[file.name.split(".").length - 1],
+							ContentType: file.type,
+							Body: file,
+							"Access-Control-Allow-Credentials": "*",
+							ACL: "public-read",
+						}; //key可以设置为桶的相抵路径,Body为文件, ACL最好要设置
+						let options = {
+							partSize: 2048 * 1024 * 1024,
+							queueSize: 2,
+							leavePartsOnError: true,
+						};
+
+						bucket
+							.upload(params, options)
+							.on("httpUploadProgress", (evt) => {
+								console.log(evt);
+							})
+							.send((err, data) => {
+								if (err) {
+									this.$message.error("上传失败");
+									return resolve("");
+								} else {
+									return resolve(data.Location);
+								}
+							});
+					} else {
+						resolve("");
+					}
+				};
+				input.click();
+			});
+		},
+	},
+};
+</script>
+
+<style scoped>
+.table>>>.el-dialog__header {
+	padding: 15px 20px;
+	background: #454545;
+}
+
+.table>>>.el-dialog__title {
+	color: #fff;
+}
+
+.Tit {
+	padding: 15px 0;
+	font-size: 14px;
+}
+</style>

+ 82 - 0
src/views/kanBan/components/countPercentage.vue

@@ -0,0 +1,82 @@
+<template>
+    <div class="DataDiv">
+        <div class="DataTitle">{{ title }}</div>
+        <div class="aiUseCount">
+            <div class="aiUseArea" v-for="(area, areaIndex) in useData" :key="areaIndex">
+                <div class="aiUseItem" v-for="(item, itemIndex) in area" :key="itemIndex">
+                    <div class="useColor" :style="{ backgroundColor: item.color }"></div>
+                    <div>{{ item.label }}</div>
+                    <div>{{ item.percentage }}</div>
+                    <div>{{ item.range }}</div>
+                </div>
+            </div>
+        </div>
+        <div class="imgArea">
+            <img src="../../../assets/img/BaseData3.png" alt="">
+        </div>
+    </div>
+</template>
+<script>
+export default {
+  name: "countPercentage",
+  props: {
+    title: {
+      type: String,
+      default: "应用使用分类", // 默认标题
+    },
+    useData: {
+      type: Array,
+      default: () => [
+        [
+          { color: "#3681fc", label: "高频", percentage: "45%", range: "(40-80人)" },
+          { color: "#1f94ff", label: "中高频", percentage: "30%", range: "(0-25人)" },
+        ],
+        [
+          { color: "#8979ff", label: "中频", percentage: "45%", range: "(0-25人)" },
+          { color: "#f4cf3b", label: "低频", percentage: "45%", range: "(0-25人)" },
+        ],
+      ],
+    },
+  },
+};
+</script>
+<style scoped>
+.DataDiv {
+    background-color: #fff;
+    border-radius: 20px;
+    padding: 20px;
+    box-shadow: 0px 4px 29px rgba(0, 0, 0, 0.1);
+}
+.DataDiv img {
+    width: 100%;
+    height: 100%;
+}
+.DataTitle {
+    font-weight: bold;
+    font-size: 17px;
+}
+.aiUseCount {
+    display: flex;
+    gap: 28px;
+}
+
+.aiUseArea {
+    margin-top: 10px;
+}
+
+.aiUseItem {
+    display: flex;
+    align-items: center;
+    gap: 8px;
+    font-size: 12px;
+    margin-top: 5px;
+}
+.useColor {
+    width: 11px;
+    border-radius: 10px;
+    height: 11px;
+}
+.imgArea {
+    padding: 65px 92px;
+}
+</style>

+ 83 - 0
src/views/kanBan/components/ranking.vue

@@ -0,0 +1,83 @@
+<template>
+    <div class="rankingDiv">
+        <div class="rankTitle">{{ title }}</div>
+        <div class="rankItem" v-for="(i, index) in useData" :key="index">
+            <div class="item_left">
+                <div class="rankNumber" :style="{
+                    backgroundColor: i.backgroundColor,
+                    border: i.hasBorder ? '1px solid gray' : 'none',
+                }">{{ i.rank }}</div>
+                <div class="rankText">{{ i.name }}</div>
+            </div>
+            <div class="rankCount">{{ i.count }}</div>
+        </div>
+
+    </div>
+</template>
+<script>
+export default {
+    name: "rankingDiv",
+    props: {
+        title: {
+            type: String,
+            default: "热门应用排名TOP5", // 默认标题
+        },
+        useData: {
+            type: Array,
+            default: () => [
+                { rank: 1, name: "应用1", count: "2213次", backgroundColor: "#f0b343" },
+                { rank: 2, name: "应用2", count: "2213次", backgroundColor: "#d9d9d9" },
+                { rank: 3, name: "应用3", count: "2213次", backgroundColor: "#ae938c" },
+                { rank: 4, name: "应用4", count: "2213次", backgroundColor: "#fff", hasBorder: true },
+                { rank: 5, name: "应用5", count: "2213次", backgroundColor: "#fff", hasBorder: true },
+            ],
+        },
+    },
+}
+</script>
+<style scoped>
+.rankingDiv {
+    background-color: #fff;
+    box-shadow: 0px 4px 29px rgba(0, 0, 0, 0.1);
+    padding: 20px;
+    border-radius: 20px;
+    display: flex;
+    flex-direction: column;
+}
+
+.rankTitle {
+    font-weight: bold;
+    font-size: 17px;
+}
+
+.rankItem {
+    display: flex;
+    justify-content: space-between;
+    border-bottom: 1px solid #e5e1e1;
+    padding-bottom: 7px;
+    margin: 25px 10px;
+}
+
+.item_left {
+    display: flex;
+}
+
+.rankNumber {
+    border-radius: 10px;
+    width: 17px;
+    height: 17px;
+    text-align: center;
+    font-size: 13px;
+    margin-right: 5px;
+}
+
+.rankText {
+    font-size: 13px;
+    font-weight: bold;
+}
+
+.rankCount {
+    font-size: 13px;
+    color: #2878fe;
+}
+</style>

+ 17 - 11
src/views/kanBan/index.vue

@@ -5,9 +5,10 @@
             <div class="title">
               <span v-if="userinfo.orgName">{{userinfo.orgName}}</span >
               <span style="color: #0663FE;font-weight: 600;">{{ userinfo.schoolName }}</span>
+              <span style="color: #0663FE;cursor: pointer;font-weight: 600;" v-if="isIndex2 == 2" @click="gotoli">返回校区</span>
+
             </div>
             <div class="person">
-                <el-button v-if="isIndex2 == 2" type="text" @click="gotoli" style="margin-right: 20px">返回校区</el-button>
               <div class="person_name">
                 <img
                  @click="openData()"
@@ -28,7 +29,7 @@
         </div>
         <div class="midBlo">
             <div class="buttonArea">
-                <div style="width: 500px;display: flex;gap: 100px;">
+                <div :style="{width: '500px',display: 'flex',justifyContent : userinfo.role == 1 && userinfo.rrole == 1 && userinfo.type ==1? 'space-between' : 'center'}">
                     <div class="btnDiv"  :class="{ active: isActive === 1 }" >
                         <div v-if="userinfo.role == 1 && userinfo.rrole == 1 && userinfo.type ==1" @click="setActive(1)">
                             数据看板
@@ -71,6 +72,7 @@ import AquickEntrance from './components/AquickEntrance';
 import AschoolFeature from './components/AschoolFeature';
 import { mapGetters, mapActions } from 'vuex';
 import { loginOut } from '@/api/user';
+import store from '../../store'
 
 export default {
     name:'kanBan',
@@ -82,6 +84,7 @@ export default {
     },
     computed: {
     ...mapGetters(['userinfo','userinfo2','fromL','appSign']),
+    // 去除账号后缀
     userSuffix(){
       return function(val) {
         let userName = JSON.parse(JSON.stringify(val))
@@ -109,9 +112,12 @@ export default {
             logout: 'user/logout'
         }),
         // 返回首页
-        gotoli(){
+        async gotoli(){
+            await store.commit('user/SET_AppSIGN', '')
+
             this.$router.push('/homepageL');
         },
+        // 退出登录
         async handleLogout() {
             this.$confirm('确定退出吗', '提示', {
                 confirmButtonText: '确定',
@@ -134,8 +140,9 @@ export default {
                 // 取消操作
             });
         },
+        // 导航栏切换
         setActive(Index) {
-            this.isActive = Index; // 设置激活的按钮
+            this.isActive = Index; 
         }
     },
     mounted() {
@@ -180,6 +187,7 @@ export default {
   color: #969BA3;
   display: flex;
   gap: 11px;
+  display: flex;
 }
 .person{
   display: flex;
@@ -193,13 +201,13 @@ export default {
   display: flex;
   flex-direction: column;
   justify-content: space-between;
-  padding: 1px 0 2px;
+  padding: 5px 0 2px;
   box-sizing: border-box;
 }
 .personInfoTit{
   font-family: PingFang SC;
   font-weight: 500;
-  font-size: 16px;
+  font-size: 14px;
   line-height: 100%;
   color: #000000;
 }
@@ -266,16 +274,14 @@ export default {
 
 .btnDiv {
     height: 48px;
-    width: 64px;
+    width: 72px;
     text-align: center;
     line-height: 48px;
-    margin-left: 15px;
+    font-size: 18px;
+    /* margin-left: 15px; */
     cursor: pointer;
 }
 
-/* .btnDiv:hover {
-    background-color: #d6d6e0;
-} */
 
 .btnDiv.active {
     font-weight: 600;

+ 4 - 0
src/views/login/loginPage.vue

@@ -135,8 +135,10 @@ import { API_CONFIG } from "@/common/apiConfig";
 import "@/common/wxLogin";
 import { getUser } from "@/api/user";
 import { loginOut } from "@/api/user";
+import { myMixin } from "@/mixins/mixin.js"
 
 export default {
+	mixins: [ myMixin ],
 	name: "loginPage",
 	data() {
 		return {
@@ -286,6 +288,7 @@ export default {
 							window.localStorage["identity"] = JSON.stringify(_data.identity);
 							this.$message.success("登录成功");
 							await this.login();
+							this.addOp3('1', "", { type:this.prefixL + "login" }, "success",_data.userid)
 							if (
 								userjson.data[0][0].type == 1 &&
 								userjson.data[0][0].role == 1 &&
@@ -559,6 +562,7 @@ export default {
 						window.localStorage["identity"] = JSON.stringify(_data.identity);
 						this.$message.success("登录成功");
 						await this.login();
+						this.addOp3('1', "", { type:this.prefixL + "login" }, "success",_data.userid)
 						if (
 							userjson.data[0][0].type == 1 &&
 							userjson.data[0][0].role == 1 &&

Some files were not shown because too many files changed in this diff