11wqe1 hace 2 meses
padre
commit
9ea44d6b6f

BIN
src/assets/img/toux.png


+ 10 - 0
src/common/apiConfig.js

@@ -55,6 +55,16 @@ export const API_CONFIG = {
   ajax_schoolPermission: {
     functionName: "select_schoolPermission",
   },
+
+  // 查询首页应用
+  ajax_allApp: {
+    functionName: "select_liYuanAllApp",
+  },
+
+  // 查询更多热门应用
+  ajax_morHotApp: {
+    functionName: "select_morHotApp",
+  },
   ////////////// 以下是账号审核的数据接口
 
   moveUser: {

+ 142 - 54
src/components/botPage.vue

@@ -4,43 +4,56 @@
             热门应用
         </div>
 
-        <div class="conBlock">
+        <div class="conBlock" v-for="(k,ind) in hotApp" :key="ind+'p'">
             <div style="display: flex;justify-content: space-between;margin-bottom: 16px;">
-                <div style="color: #1f2937;font-weight: 600;font-size: 18px;margin-bottom: 16px;">项目式学习</div>
-                <div style="color: #0354d7;font-size: 14px;cursor: pointer;">查看全部</div>
+                <div style="color: #1f2937;font-weight: 600;font-size: 18px;margin-bottom: 16px;">{{ tab[ind].name }}</div>
+                <div @click="lookMore(ind)" style="color: #0354d7;font-size: 14px;cursor: pointer;">查看全部</div>
             </div>
             <div style="display: grid;grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));gap: 16px;">
-                <div v-for="(item,index) in tab" class="tabCon" :key="index" style="min-width: 308px;">
-                        <div style="flex-wrap: wrap;display: flex;justify-content: space-between;border: 1px rgb(243 244 246 / var(--tw-border-opacity, 1)) solid;border-radius: 10px;padding: 16px;box-sizing: border-box;">
-                            <img style="width: 48px;border-radius: 50%;" src="../assets/img/root.png" alt="">
-                            <div style="flex: 1;margin-left: 12px;display: flex;flex-direction: column;justify-content: center;">
-                                <div style="color: #1f2937;font-size: 16px;height: 24px;line-height: 24px;">{{ item.name }}</div>
-                                <div style="color: #6b7280;font-size: 12px;height: 16px;line-height: 16px;">{{ item.bir }}</div>
+                <div v-for="(item,index) in k" class="tabCon" @click="openNewWindow(item)"  :key="index" style="min-width: 308px;">
+                        <div class="AppList">
+                            <img class="appImg" :src="JSON.parse(item.json).icon" alt="">
+                            <div class="con">
+                                <div class="tit">{{ item.name }}</div>
+                                <div class="bri">
+                                    <el-tooltip class="item" effect="light" :content="item.detail" placement="bottom">
+                                        <span>
+                                            {{ item.detail }}
+                                        </span>
+                                    </el-tooltip>
+                                </div>
                             </div>
                             <div class="hg">
                                 <img style="width: 20px;" v-if="index == 0" src="../assets/img/hg1.svg" alt="">
                                 <img style="width: 20px;" v-if="index == 1" src="../assets/img/hg2.svg" alt="">
                                 <img style="width: 20px;" v-if="index == 2" src="../assets/img/hg3.svg" alt="">
-
                             </div>
                     </div>
                 </div>
-                
             </div>
         </div>
-
-        <!-- <div class="conBlock">
-            <div style="display: flex;justify-content: space-between;margin-bottom: 16px;">
-                <div style="color: #1f2937;font-weight: 600;font-size: 18px;margin-bottom: 16px;">项目式学习</div>
-                <div style="color: #0354d7;font-size: 14px;cursor: pointer;">查看全部</div>
-            </div>
-            <div style="display: grid;grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));gap: 16px;">
-                <div v-for="(item,index) in tab" class="tabCon"  :key="index" style="min-width: 308px;">
-                        <div style="flex-wrap: wrap;display: flex;justify-content: space-between;border: 1px rgb(243 244 246 / var(--tw-border-opacity, 1)) solid;border-radius: 10px;padding: 16px;box-sizing: border-box;">
-                            <img style="width: 48px;border-radius: 50%;" src="../assets/img/root.png" alt="">
-                            <div style="flex: 1;margin-left: 12px;display: flex;flex-direction: column;justify-content: center;">
-                                <div style="color: #1f2937;font-size: 16px;height: 24px;line-height: 24px;">{{ item.name }}</div>
-                                <div style="color: #6b7280;font-size: 12px;height: 16px;line-height: 16px;">{{ item.bir }}</div>
+        <el-dialog
+        :title="diaTit"
+        
+        :visible.sync="dialogVisible"
+        class="moreDia"
+        :close-on-click-modal="false"
+        :modal="false"
+        width="60%"
+        :before-close="handleClose">
+            <div v-loading="loading" style="display: grid;grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));gap: 16px;">
+                <div v-for="(item,index) in moreList" class="tabCon" @click="openNewWindow(item)"  :key="index" style="min-width: 308px;">
+                        <div class="AppList">
+                            <img class="appImg" :src="JSON.parse(item.json).icon" alt="">
+                            <div class="con">
+                                <div class="tit">{{ item.name }}</div>
+                                <div class="bri">
+                                    <el-tooltip class="item" effect="light" :content="item.detail" placement="bottom">
+                                        <span>
+                                            {{ item.detail }}
+                                        </span>
+                                    </el-tooltip>
+                                </div>
                             </div>
                             <div class="hg">
                                 <img style="width: 20px;" v-if="index == 0" src="../assets/img/hg1.svg" alt="">
@@ -49,52 +62,90 @@
                             </div>
                     </div>
                 </div>
-                
             </div>
-        </div>
+        </el-dialog>
 
-        <div class="conBlock">
-            <div style="display: flex;justify-content: space-between;margin-bottom: 16px;">
-                <div style="color: #1f2937;font-weight: 600;font-size: 18px;margin-bottom: 16px;">项目式学习</div>
-                <div style="color: #0354d7;font-size: 14px;cursor: pointer;">查看全部</div>
-            </div>
-            <div style="display: grid;grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));gap: 16px;">
-                <div v-for="(item,index) in tab" class="tabCon"  :key="index" style="min-width: 308px;">
-                        <div style="flex-wrap: wrap;display: flex;justify-content: space-between;border: 1px rgb(243 244 246 / var(--tw-border-opacity, 1)) solid;border-radius: 10px;padding: 16px;box-sizing: border-box;">
-                            <img style="width: 48px;border-radius: 50%;" src="../assets/img/root.png" alt="">
-                            <div style="flex: 1;margin-left: 12px;display: flex;flex-direction: column;justify-content: center;">
-                                <div style="color: #1f2937;font-size: 16px;height: 24px;line-height: 24px;">{{ item.name }}</div>
-                                <div style="color: #6b7280;font-size: 12px;height: 16px;line-height: 16px;">{{ item.bir }}</div>
-                            </div>
-                            <div class="hg">
-                                <img style="width: 20px;" v-if="index == 0" src="../assets/img/hg1.svg" alt="">
-                                <img style="width: 20px;" v-if="index == 1" src="../assets/img/hg2.svg" alt="">
-                                <img style="width: 20px;" v-if="index == 2" src="../assets/img/hg3.svg" alt="">
-                            </div>
-                    </div>
-                </div>
-                
-            </div>
-        </div> -->
+    
     </div>
 </template>
 
 <script>
+import { API_CONFIG } from "@/common/apiConfig";
+import { mapGetters } from 'vuex';
+
     export default {
+        props:['hotApp'],
+        computed: {
+            ...mapGetters(['userinfo']),
+        },
         data() {
             return {
                 tab:[
-                    {name:'PBL课程设计',icon:'',bir:'项目式学习课程规划'},
-                    {name:'课堂活动设计',icon:'',bir:'互动教学活动规划'},
-                    {name:'教案编写',icon:'',bir:'教案智能生成'},
-
-                ]
+                    {name:'项目式学习',type:'63915be8-cefa-11ef-a2d1-005056b86db5'},
+                    {name:'教学工具',type:'38111096-cc11-11ef-a2d1-005056b86db5'},
+                    {name:'学习工具',type:'917a5a56-abd5-11ef-b887-005056b86db5'},
+                    {name:'效率工具',type:'9b257041-abd5-11ef-b887-005056b86db5'},
+                ],
+                // 控制弹框展开
+                dialogVisible:false,
+                // 查看更多标题
+                diaTit:'',
+                // 查看更多弹框list
+                moreList:[],
+                loading:false
             }
         },
+        methods: {
+            openNewWindow(val) {
+                console.log(val);
+                
+                // // 基本用法:打开指定 URL
+                window.open(val.url, "_blank");
+            },
+            handleClose(){
+                this.dialogVisible = false
+            },
+            lookMore(index){
+                this.dialogVisible = true
+
+                this.diaTit = this.tab[index].name
+                this.loading = true
+                let params = [
+                    {
+                        functionName: API_CONFIG.ajax_morHotApp.functionName,
+                        uid: this.userinfo.userid, 
+                        type: this.tab[index].type,
+                        cn: this.userinfo.schoolArea ? this.userinfo.schoolArea : this.userinfo.orgArea, //学校id
+                    },
+                ];
+                this.$ajax
+                    .post(API_CONFIG.baseUrl, params)
+                    .then((res) => {
+                        this.moreList = res.data[0]
+                        
+                       
+                        this.loading = false
+
+                    })
+                    .catch((err) => {
+                        console.log(err);
+                        this.loading = false
+                        this.$message.error("获取工具数据失败");
+                    });
+            }
+        },  
     }
 </script>
 
 <style scoped>
+.moreDia >>> .el-dialog{
+    border-radius: 10px;
+}
+.moreDia >>> .el-dialog__body{
+    height: 300px;
+    overflow: auto;
+    border-top: 1px #e7e7e7 solid;
+}
 .conBlock{
     background-color: #fff;
     padding: 24px;
@@ -105,6 +156,7 @@
 .tabCon{
     transition: all 0.3s ease; /* 统一过渡效果 */
     border-radius: 10px;
+    cursor: pointer;
 }
 .tabCon:hover{
     transform: translateY(-5px); /* 向上位移 */
@@ -114,4 +166,40 @@
     width: 23px !important;
     height: 20px;
 }
+.con{
+    flex: 1;
+    margin-left: 12px;
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+}
+.tit{
+    color: #1f2937;font-size: 16px;height: 24px;line-height: 24px;
+    -webkit-line-clamp: 1;
+    display: -webkit-box;
+    -webkit-box-orient: vertical;
+    overflow: hidden;
+    text-overflow: ellipsis;
+}
+.bri{
+    color: #6b7280;font-size: 12px;height: 16px;line-height: 16px;
+    overflow: hidden;
+    -webkit-line-clamp: 1;
+    display: -webkit-box;
+    -webkit-box-orient: vertical;
+    overflow: hidden;
+    text-overflow: ellipsis;
+}
+.appImg{
+    width: 48px;
+    height: 48px;
+    border-radius: 50%;
+    object-fit: cover;
+}
+.AppList{
+    flex-wrap: wrap;display: flex;
+    justify-content: space-between;
+    border: 1px rgb(243 244 246 / var(--tw-border-opacity, 1)) solid;
+    border-radius: 10px;padding: 16px;box-sizing: border-box;
+}
 </style>

+ 135 - 46
src/components/sidebarL.vue

@@ -5,6 +5,7 @@
             </div>
             <div class="ulT">
 
+                <!-- 默认首页 -->
                 <div @click.stop="goto(0)" :style="{background :activeL === 0 ?'#E6F0FF':'',zIndex : 10000 }">
                     <div class="menu_left">
                         <img  class="logo" :src="activeL === 0 ? require('../assets/img/sy1.svg') : require('../assets/img/sy.svg')" alt="">
@@ -12,46 +13,64 @@
                     </div>
                 </div>
 
-                <div v-for="(item,index) in fromL.admin.sidebar.list" @click.stop="goto(index,item)" :style="{background :activeL === (index +1) ?'#E6F0FF':'',zIndex : 10000 }" :key="index+1">
+                <!-- 权限 -->
+                <div v-for="(item,index) in appSignL(fromL.admin.sidebar.list)"
+                    @click.stop="goto(index,item)" 
+                    :style="{background :activeL === (index +1) ?'#E6F0FF':'',zIndex : 10000 }" 
+                    :key="index+1">
+
+                    <!-- 渲染菜单类型 -->
                     <div class="menu_left" v-if="item.menuName">
                         <img  class="logo" :src="activeL === (index +1) ? item.menuActiveIcon : item.menuIcon" alt="">
-                        <span  :style="{color : activeL === (index +1) ? '#0051D7' :''}">{{ item.menuName }}</span>
+                        <span :style="{color : activeL === (index +1) ? '#0051D7' :''}">{{ item.menuName }}</span>
                     </div>
                   
-                    <div class="menu_left" v-else>
-                        <div v-for="(p,pin) in item.url" :key="pin+'p'">
-                            <img class="logo3"  
-                            v-if="p.region == userinfo.schoolArea && p.icon" 
-                            :src="activeL === (index +1) ? p.icon : p.activeIcon" 
-                            alt="">
-                            <img class="logo3" v-else-if="p.region == 'cn'"  :src="p.icon" alt="">
+                    <!-- 渲染应用类型,               status判断是否被删除  isAdmin是否为管理员可见 -->
+                    <div v-else>
+                        <div>
+                            <div v-for="(p,pin) in AppCon(item.url)" :key="pin+'p'">
+                                <div class="menu_left" >
+                                    <div>
+                                        <img class="logo3"  
+                                        :src="activeL === (index +1) ? p.icon : p.activeIcon" 
+                                        alt="">
+                                    </div>
+                                    <span :style="{color : activeL === (index +1) ? '#0051D7' :''}">
+                                        {{ p.name }}
+                                    </span>
+                                </div>
+                                
+                            </div>
                         </div>
-                        <span  :style="{color : activeL === (index +1) ? '#0051D7' :''}">{{ item.description }}</span>
                     </div>
                 </div>
                
             </div>
             <div class="userInfo">
-                <img style="width: 40px;border-radius: 50%;margin-bottom: 4px;" :src="userinfo.headportrait ? userinfo.headportrait : require('../assets/img/root.png')" alt="">
+                <img style="width: 40px;height: 40px;object-fit: cover;border-radius: 50%;margin-bottom: 4px;" :src="userinfo.headportrait ? userinfo.headportrait : require('../assets/img/toux.png')" alt="">
                 <div style="margin-bottom: 8px;">{{ userinfo.username }}</div>
+                <span style="cursor: pointer;padding: 5px;background-color: #e7e7e7;box-sizing: border-box;border-radius: 5px;" @click="handleLogout">退出登录</span>
             </div>
-
+            
+            <!-- 二级导航 -->
             <div class="ulTCopy" v-if="isShow && barCopy.length != 0" >
                 <div class="ulTCopyTit">
                     <span>教学中心</span>
                     <span @click="closeCopy" class="cha" style="color: #6B7280;font-size: 23px;cursor: pointer;">⨯</span>
                 </div>
+
                 <div style="padding: 16px;box-sizing: border-box;">
-                    <div class="ulTCopyTxt" v-for="(i,ind) in barCopy" @click="levTwo(i)" :key="ind+'a'">
-                        <div v-for="(p,pin) in i.url" :key="pin+'p'">  
-                            <img style="width: 30px;object-fit: contain;margin-right: 5px;"  
-                            v-if="p.region == userinfo.schoolArea && p.icon" 
-                            :src="p.icon" 
-                            alt="">
-                            
-                            <img style="width: 30px;object-fit: contain;margin-right: 5px;" v-else-if="p.region == 'cn'"  :src="p.icon" alt="">
+                    <div class="ulTCopyTxt" v-for="(i,ind) in appSignL(barCopy)" @click="levTwo(i)" :key="ind+'a'">
+                        <div>
+                            <div style="display: flex;justify-content: space-between;align-items: center;" v-for="(p,pin) in AppCon(i.url)" :key="pin+'p'">
+                                <div>  
+                                    <img style="width: 30px;object-fit: contain;margin-right: 5px;"  
+                                    :src="p.icon" 
+                                    alt="">
+                                </div>
+                                <span>{{ p.name }}</span>
+                            </div>
                         </div>
-                        <span >{{ i.description }}</span>
                     </div>
                 </div>
             </div>
@@ -63,10 +82,53 @@
 <script>
 import { mapGetters, mapActions } from 'vuex';
 import { loginOut } from '@/api/user';
+import store from '../store'
 
     export default {
         computed: {
-            ...mapGetters(['userinfo','fromL']),
+            ...mapGetters(['userinfo','fromL','appSign']),
+            // 如果hk,com没有图标,默认使用cn的
+            AppCon(){
+                return function(c) {
+                    let k = JSON.parse(JSON.stringify(c))
+                    let data = k.filter(e=>{
+                        return e.region == this.userinfo.schoolArea || e.region == this.userinfo.orgArea
+                    })
+
+                    let data2 = k.filter(e=>{
+                        return e.region == 'cn'
+                    })
+                    
+                    // 如果hk,com没有图标,默认使用cn的
+                    if (!data[0].icon){
+                        data[0].icon = data2[0].icon
+                        data[0].activeIcon = data2[0].activeIcon
+                    }
+                    return data
+                };
+            },
+            // 筛选是否为管理员可见,是否被删除
+            appSignL(){
+                return function(val){
+                    console.log(val);
+                    
+                    let data = []
+                    if (this.userinfo.type == 1 && this.userinfo.role == 1) {
+                        val.forEach( e =>{
+                            if (e.menuName || e.status == 0) {
+                               data.push(e)
+                            }
+                        })
+                    } else {
+                        val.forEach( e =>{
+                            if (e.menuName || (e.isAdmin == '0' && e.status == 0)) {
+                               data.push(e)
+                            }
+                        })
+                    }
+                    return data
+                }
+            }
         },
         data() {
             return {
@@ -76,9 +138,7 @@ import { loginOut } from '@/api/user';
                 activeL:0,
                 // 二级分类
                 barCopy:[],
-                // 应用标识
-                appSign:'',
-                levAppSign:''
+             
             }
         },
         methods: {
@@ -112,13 +172,17 @@ import { loginOut } from '@/api/user';
                 this.isShow = false
             },
             // 点击一级导航
-            goto(index,val = null){
-                this.levAppSign = ''
+            async goto(index,val = null){
+                console.log('goto',val);
+                
+                // val = null 就是点击了首页
                 if (val) {
                     this.activeL = index + 1               
                 }else{
-                    this.appSign = ''
+                    // 点击首页清空内容,并把标识去除
+                    await store.commit('user/SET_AppSIGN', '')
                     document.querySelector('#pageCon').innerHTML = '';
+                    this.$emit('getPer')
 
                     this.isShow = false
                     this.activeL = index
@@ -126,24 +190,26 @@ import { loginOut } from '@/api/user';
                 }
 
 
-                // 有二级导航的显示二级导航,清除一级导航应用
-                if (this.fromL.admin.sidebar.list[index].children) {
-                    this.barCopy = JSON.parse(JSON.stringify(this.fromL.admin.sidebar.list[index].children))
+                // 有二级导航的显示二级导航.无二级则进行判断
+                if (val.children) {
+                    this.barCopy = JSON.parse(JSON.stringify(val.children))
                     this.isShow = true
 
-                    this.appSign = ''
-                    document.querySelector('#pageCon').innerHTML = '';
+                    // this.appSign = ''
+                    // document.querySelector('#pageCon').innerHTML = '';
                 }else{
                     this.isShow = false
 
                     // 点击相同应用不刷新  
                     if (this.appSign == val.toolId) return
-                    this.appSign = val.toolId
+
+                    // 更新标识
+                    await store.commit('user/SET_AppSIGN', val.toolId)
 
                     let url = ''
                     // 查出对应账号的应用区域地址
                     val.url.forEach(e => {
-                        if (e.region == this.userinfo.schoolArea) {
+                        if (e.region == this.userinfo.schoolArea || e.region == this.userinfo.orgArea) {
                             url = e.url
                         }
                     });
@@ -152,22 +218,44 @@ import { loginOut } from '@/api/user';
                     
                     document.querySelector('#pageCon').innerHTML = '';
                     
-                    // console.log(document.querySelector('#pageCon'));
-                    window.topU.U.MD.D.I.openApplicationWai(val.toolId, url, dom)
+                    if (val.toolId == 'dataBoardNew') {
+                        window.topU.U.MD.D.I.openApplicationWai(val.toolId, url, dom,['userid','oid','org','role'])
+                    }else if (val.toolId == 'classroomObservation') {
+                        window.topU.U.MD.D.I.openApplicationWai(val.toolId, url, dom,['userid','oid','org'])
+                    }else if (val.toolId == 'teacher') {
+                        window.topU.U.MD.D.I.openApplicationWai(val.toolId, url, dom,['userid','oid','org'])
+                    }else if (val.toolId == 'futureClass') {
+                        window.topU.U.MD.D.I.openApplicationWai(val.toolId, url, dom,['userid','oid','org','role'])
+                    }else if (val.toolId == 'student') {
+                        window.topU.U.MD.D.I.openApplicationWai(val.toolId, url, dom,['userid','oid','classId','org','role'])
+                    }else if (val.toolId == 'appStore') {
+                        window.topU.U.MD.D.I.openApplicationWai(val.toolId, url, dom,['userid','oid','org','role'])
+                    }else if (val.toolId == 'testTeacher') {
+                        window.topU.U.MD.D.I.openApplicationWai(val.toolId, url, dom,['userid','oid','org','role'])
+                    }else if (val.toolId == 'evaluate') {
+                        window.topU.U.MD.D.I.openApplicationWai(val.toolId, url, dom,['userid','oid','org'])
+                    }else if (val.toolId == 'project') {
+                        window.topU.U.MD.D.I.openApplicationWai(val.toolId, url, dom,['userid','oid','org','role'])
+                    }else if (val.toolId == 'study') {
+                        window.topU.U.MD.D.I.openApplicationWai(val.toolId, url, dom,['userid','oid','org','type','classId','TscreenType'])
+                    }else if (val.toolId == 'knowledge') {
+                        window.topU.U.MD.D.I.openApplicationWai(val.toolId, url, dom,['userid','oid','org'])
+                    }
                     // 应用标识,url,存储dom
                 }
             },
             // 点击二级导航
-            levTwo(val){
-                this.appSign = ''
-
+            async levTwo(val){
+              
                 // 点击相同应用不刷新
-                if (this.levAppSign == val.toolId) return
-                this.levAppSign = val.toolId
+                if (this.appSign == val.toolId) return
+
+               // 更新标识
+                await store.commit('user/SET_AppSIGN', val.toolId)
                 
                 let url = ''
                 val.url.forEach(e => {
-                    if (e.region == this.userinfo.schoolArea) {
+                    if (e.region == this.userinfo.schoolArea || e.region == this.userinfo.orgArea) {
                         url = e.url
                     }
                 });
@@ -210,6 +298,7 @@ import { loginOut } from '@/api/user';
   align-items: center;
   padding: 8px;
   box-sizing: border-box;
+  padding-bottom: 20px;
 }
 .left {
     font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji" !important;
@@ -222,7 +311,7 @@ import { loginOut } from '@/api/user';
     justify-content: space-between;
     position: relative;
     box-shadow: 5px 0 8px rgba(0, 0, 0, 0.1);
-    z-index: 9999;
+    z-index: 999;
 
 }
 .left .ulT { 
@@ -231,13 +320,13 @@ import { loginOut } from '@/api/user';
   padding: 8px;
   box-sizing: border-box;
   display: flex;
+  gap: 10px;
+  overflow: auto;
   flex-direction: column;
   background-color: #ffffff;
 }
 .left .ulT div{ 
-  margin-top: 10px;
   border-radius: 10px;
-  overflow: hidden;
 }
 .ulTCopy{
     position: absolute;

+ 131 - 32
src/components/topPage.vue

@@ -15,18 +15,24 @@
             <img style="width: 96px;height: 96px;" src="../assets/img/root.png" alt="">
         </div>
         <div class="TabList">
-            <div class="TabListCon" v-for="(item,index) in fromL.admin.index.list" :key="index">
-                <div v-for="(p,pin) in item.url" :key="pin+'p'">
-                    <img style="height: 25px;object-fit: contain;transform: scale(1.5);"  
-                    v-if="p.region == userinfo.schoolArea && p.icon" 
-                    :src="p.icon" 
-                    alt="">
-                    
-                    <img style="height: 25px;object-fit: contain;transform: scale(1.5);" v-else-if="p.region == 'cn'"  :src="p.icon" alt="">
-                </div>
+            <div class="TabListCon" @click="openApp(item)" v-for="(item,index) in appSignL(fromL.admin.index.list)" :key="index">
+                    <div v-for="(p,pin) in AppCon(item.url)" :key="pin+'p'">
+                        <img style="height: 25px;object-fit: contain;transform: scale(1.5);margin-bottom: 12px;"     
+                        :src="p.icon" 
+                        alt="">
+                        <div class="TabListName">
+                            {{ p.name }}
+                        </div>
+                    </div>
 
-                <div class="TabListName">{{ item.description }}</div>
-                <div class="TabListBri">暂无</div>
+                   
+                    <div class="TabListBri">
+                        <el-tooltip class="item" effect="light" :content="item.description" placement="bottom">
+                            <span>
+                                {{ item.description }}
+                            </span>
+                        </el-tooltip>
+                    </div>
             </div>
         </div>
         <div class="footCon">
@@ -37,10 +43,16 @@
             </div>
 
             <div class="footList">
-                <div class="footListCon" v-for="(item,index) in footData" :key="index">
-                    <div><img style="margin-bottom: 12px;height: 24px;width: 22px;" :src="item.icon" alt=""></div>
+                <div class="footListCon" v-for="(item,index) in CocoFlowList" @click="openNewWindow(item)" :key="index">
+                    <div><img style="margin-bottom: 12px;height: 24px;width: 22px;" :src="JSON.parse(item.json).icon" alt=""></div>
                     <div class="TabListName">{{ item.name }}</div>
-                    <div class="TabListBri">{{ item.bri }}</div>
+                    <div class="TabListBri">
+                        <el-tooltip class="item" effect="light" :content="item.detail" placement="bottom">
+                            <span>
+                                {{ item.detail }}
+                            </span>
+                        </el-tooltip>
+                    </div>
                 </div>
                 <!-- <div class="footListCon footListCon2">
                     <div style="margin-bottom: 8px;font-size: 40px;color: #0354D7;">+</div>
@@ -53,33 +65,108 @@
 
 <script>
 import { mapGetters } from 'vuex';
+import store from '../store'
 
     export default {
+        props:['CocoFlowList'],
         computed: {
             ...mapGetters(['userinfo','fromL']),
+              // 如果hk,com没有图标,默认使用cn的
+              AppCon(){
+                return function(c) {
+                    let k = JSON.parse(JSON.stringify(c))
+                    let data = k.filter(e=>{
+                        return e.region == this.userinfo.schoolArea || e.region == this.userinfo.orgArea
+                    })
+
+                    let data2 = k.filter(e=>{
+                        return e.region == 'cn'
+                    })
+                    
+                    // 如果hk,com没有图标,默认使用cn的
+                    if (!data[0].icon){
+                        data[0].icon = data2[0].icon
+                        data[0].activeIcon = data2[0].activeIcon
+                    }
+                    return data
+                };
+            },
+            // 筛选是否为管理员可见,是否被删除
+            appSignL(){
+                return function(val){
+                    
+                    let data = []
+                    if (this.userinfo.type == 1 && this.userinfo.role == 1) {
+                        val.forEach( e =>{
+                            if (e.menuName || e.status == 0) {
+                               data.push(e)
+                            }
+                        })
+                    } else {
+                        val.forEach( e =>{
+                            if (e.menuName || (e.isAdmin == '0' && e.status == 0)) {
+                               data.push(e)
+                            }
+                        })
+                    }
+                    return data
+                }
+            }
         },
         data() {
             return {
-                // tabData:[
-                //     {name:'综合看板',icon:require('@/assets/img/zhexian.svg'),bri:'平台数据可视化看板'},
-                //     {name:'智能表单',icon:require('@/assets/img/biaodanll.svg'),bri:'智能化表单管理'},
-                //     {name:'教师管理',icon:require('@/assets/img/kehu.svg'),bri:'教师账号与权限管理'},
-                //     {name:'课程中心',icon:require('@/assets/img/kecheng.svg'),bri:'在AI的辅助下进行授课与评价'},
-                //     {name:'课程管理',icon:require('@/assets/img/guanli.svg'),bri:'创建和管理课程'},
-                //     {name:'课堂观察',icon:require('@/assets/img/guancha.svg'),bri:'对课堂进行全方位、多维度的分析'},
-                // ],
-                footData:[
-                    {name:'项目式课程设计',icon:require('@/assets/img/zhexian.svg'),bri:'从创意开始,帮助你设计PBL的课程案例。'},
-                    {name:'STEM活动设计',icon:require('@/assets/img/zhexian.svg'),bri:'以“5EX”模型设计STEM课程'},
-                    {name:'跨学科课程设计',icon:require('@/assets/img/zhexian.svg'),bri:'以“C-POTE”模型设计跨学科课程'},
-                    {name:'创意智造',icon:require('@/assets/img/zhexian.svg'),bri:'以设计思维为核心,深度启发学生创意。'},
-                    {name:'资料搜集',icon:require('@/assets/img/zhexian.svg'),bri:'搜集适合教学使用的高质量媒体资源。'},
-                    {name:'文本改写',icon:require('@/assets/img/zhexian.svg'),bri:'按自定义标准改写文本。'},
-                    {name:'智能总结',icon:require('@/assets/img/zhexian.svg'),bri:'按自定义要求总结文本。'},
-                    {name:'班级管理助手',icon:require('@/assets/img/zhexian.svg'),bri:'诊断班级管理问题并给出建议'},
-                ],
+              
             }
         },
+        methods: {
+            async openApp(val){
+                // 点击相同应用不刷新
+                if (this.appSign == val.toolId) return
+                // 更新标识
+                await store.commit('user/SET_AppSIGN', val.toolId)
+                
+                let url = ''
+                val.url.forEach(e => {
+                    if (e.region == this.userinfo.schoolArea) {
+                        url = e.url
+                    }
+                });
+
+                let dom = document.querySelector('#pageCon')
+        
+                document.querySelector('#pageCon').innerHTML = '';
+                
+                if (val.toolId == 'dataBoardNew') {
+                    window.topU.U.MD.D.I.openApplicationWai(val.toolId, url, dom,['userid','oid','org','role'])
+                }else if (val.toolId == 'classroomObservation') {
+                    window.topU.U.MD.D.I.openApplicationWai(val.toolId, url, dom,['userid','oid','org'])
+                }else if (val.toolId == 'teacher') {
+                    window.topU.U.MD.D.I.openApplicationWai(val.toolId, url, dom,['userid','oid','org'])
+                }else if (val.toolId == 'futureClass') {
+                    window.topU.U.MD.D.I.openApplicationWai(val.toolId, url, dom,['userid','oid','org','role'])
+                }else if (val.toolId == 'student') {
+                    window.topU.U.MD.D.I.openApplicationWai(val.toolId, url, dom,['userid','oid','classId','org','role'])
+                }else if (val.toolId == 'appStore') {
+                    window.topU.U.MD.D.I.openApplicationWai(val.toolId, url, dom,['userid','oid','org','role'])
+                }else if (val.toolId == 'testTeacher') {
+                    window.topU.U.MD.D.I.openApplicationWai(val.toolId, url, dom,['userid','oid','org','role'])
+                }else if (val.toolId == 'evaluate') {
+                    window.topU.U.MD.D.I.openApplicationWai(val.toolId, url, dom,['userid','oid','org'])
+                }else if (val.toolId == 'project') {
+                    window.topU.U.MD.D.I.openApplicationWai(val.toolId, url, dom,['userid','oid','org','role'])
+                }else if (val.toolId == 'study') {
+                    window.topU.U.MD.D.I.openApplicationWai(val.toolId, url, dom,['userid','oid','org','type','classId','TscreenType'])
+                }else if (val.toolId == 'knowledge') {
+                    window.topU.U.MD.D.I.openApplicationWai(val.toolId, url, dom,['userid','oid','org'])
+                }
+            },
+            openNewWindow(val) {
+                console.log(val);
+                
+                // // 基本用法:打开指定 URL
+                window.open(val.url, "_blank");
+            },
+        },
     }
 </script>
 
@@ -112,6 +199,7 @@ import { mapGetters } from 'vuex';
     max-width: 187px;
     background-image: radial-gradient(#E6F0FF 1px, transparent 1px);
     background-size: 20px 20px;
+    cursor: pointer;
 }
 .footListCon:hover{
     transform: translateY(-5px); /* 向上位移 */
@@ -146,6 +234,7 @@ import { mapGetters } from 'vuex';
     transition: all 0.3s ease; /* 统一过渡效果 */
     background-image: radial-gradient(#E6F0FF 1px, transparent 1px);
     background-size: 20px 20px;
+    cursor: pointer;
 }
 .TabListCon:hover{
     transform: translateY(-5px); /* 向上位移 */
@@ -156,10 +245,20 @@ import { mapGetters } from 'vuex';
     font-size: 18px;
     font-weight: 600;
     margin-bottom: 4px;
+    -webkit-line-clamp: 2;
+    display: -webkit-box;
+    -webkit-box-orient: vertical;
+    overflow: hidden;
+    text-overflow: ellipsis;
 }
 .TabListBri{
     color: #4b5563;
     font-size: 12px;
+    -webkit-line-clamp: 2;
+    display: -webkit-box;
+    -webkit-box-orient: vertical;
+    overflow: hidden;
+    text-overflow: ellipsis;
 }
 .top{
     display: flex;

+ 1 - 0
src/store/getters.js

@@ -7,5 +7,6 @@ const getters = {
   userinfo: state => state.user.userinfo,
   fromL: state => state.user.fromL,
   token: state => state.user.token,
+  appSign: state => state.user.appSign,
 }
 export default getters

+ 7 - 0
src/store/modules/user.js

@@ -15,6 +15,7 @@ const getDefaultState = () => {
     avatar: "",
     is_init: false,
     userinfo: {},
+    // 应用权限
     fromL: {
       basics: {
         title: "",
@@ -34,6 +35,9 @@ const getDefaultState = () => {
         },
       },
     },
+    // 应用标识
+    appSign:''
+
   };
 };
 
@@ -54,6 +58,9 @@ const mutations = {
   SET_FROM: (state, from) => {
     state.fromL = from;
   },
+  SET_AppSIGN: (state, sign) => {
+    state.appSign = sign;
+  },
   SET_NAME: (state, name) => {
     state.name = name;
   },

+ 21 - 13
src/views/HomeView.vue

@@ -9,13 +9,13 @@
     </div> -->
     <div class="container">
       <div class="leftBar" style="height: 100%;">
-        <sidebarL ref="sidebarLRef"></sidebarL>
+        <sidebarL @getPer="getPer" @clearAppSign="clearAppSign" ref="sidebarLRef"></sidebarL>
       </div>
       <div class="table-container">
         <!-- <router-view></router-view> -->
-         <homepageL ></homepageL>
+         <homepageL v-show="!appSign" ref="homepageLRef"></homepageL>
 
-         <div id="pageCon"></div>
+         <div v-show="appSign" style="height: 100%;" id="pageCon"></div>
       </div>
     </div>
   </div>
@@ -44,12 +44,14 @@ export default {
     }
   },
   computed: {
-    ...mapGetters(['userinfo']),
+    ...mapGetters(['userinfo','appSign']),
   },
   methods: {
     ...mapActions({
       logout: 'user/logout'
     }),
+
+    
     async handleLogout() {
       this.$confirm('确定退出吗', '提示', {
         confirmButtonText: '确定',
@@ -72,8 +74,16 @@ export default {
         // 取消操作
       });
     },
+    // 清空组件标识,防止标识相同不刷新
+    clearAppSign(){
+      this.$refs.homepageLRef.$refs.topPageRef.TopAppSign = ''
+      // this.$refs.homepageLRef.$refs.botPageRef.TopAppSign = ''
+
+    },
     // 获取学校权限与组织权限,优先使用学校权限,其次使用组织权限
     getPer() {
+      this.$refs.homepageLRef.getData()
+
       let params = [
         {
           functionName: API_CONFIG.ajax_schoolPermission.functionName, // 调用存储过程的名称
@@ -87,7 +97,7 @@ export default {
         .post(API_CONFIG.baseUrl, params)
         .then((res) => {
           let data = res.data[0]
-          console.log('data', data)
+          // console.log('data', data)
           this.perData= JSON.parse(data[0].json)
           this.getToolData()
 
@@ -116,7 +126,7 @@ export default {
 						i.argumentList = JSON.parse(i.argumentList);
 					});
 					this.toolList = _list;
-          console.log('_list',_list);
+          // console.log('_list',_list);
           
 					this.setDataListToo(_list);
 				})
@@ -126,7 +136,7 @@ export default {
 				});
 		},
     async setDataListToo(toolList = []) {
-      console.log('toolList',toolList);
+      // console.log('toolList',toolList);
       
 			let _form = JSON.parse(JSON.stringify(this.perData));
 			// _form.desktop.list.forEach((i, index) => {
@@ -173,11 +183,8 @@ export default {
 				}
 			});
 
-      console.log('_form',_form);
+      // console.log('_form',_form);
       await store.commit('user/SET_FROM', _form)
-
-      console.log('999999999999999999999999',this.$refs.sidebarLRef.appSign);
-      
       
 			this.$forceUpdate();
 		},
@@ -203,9 +210,10 @@ export default {
   height: 100vh;
 }
 .table-container {
-  display: flex;
+  /* display: flex;
   flex: 1;
-  justify-content: center;
+  justify-content: center; */
+  width: 100%;
   background-color: #F9FAFB;
 }
 /* .leftBar{ */

+ 33 - 2
src/views/homepageL.vue

@@ -1,9 +1,9 @@
 <template>
     <div class="allPage">
         <div class="packageL">
-            <topPage></topPage>
+            <topPage :CocoFlowList="CocoFlowList" ref="topPageRef"></topPage>
             <div style="height: 30px;width: 100%;"></div>
-            <botPage></botPage>
+            <botPage :hotApp="hotApp" ref="botPageRef"></botPage>
         </div>
     </div>
 </template>
@@ -11,15 +11,46 @@
 <script>
 import topPage from '../components/topPage'
 import botPage from '../components/botPage'
+import { mapGetters } from 'vuex';
+import { API_CONFIG } from "@/common/apiConfig";
 
     export default {
+        computed: {
+            ...mapGetters(['userinfo']),
+        },
         components:{
             topPage,
             botPage
         },
         data() {
             return {
+                CocoFlowList:[],
+                hotApp:[]
+            }
+        },
+        methods: {
+            getData(){
+                let params = [
+                    {
+                    functionName: API_CONFIG.ajax_allApp.functionName, // 调用存储过程的名称
+                    uid: this.userinfo.userid, //组织id
+                    cn: this.userinfo.schoolArea ? this.userinfo.schoolArea : this.userinfo.orgArea, //学校id
+                    },
+                ];
                 
+                // 发起请求
+                this.$ajax
+                    .post(API_CONFIG.baseUrl, params)
+                    .then((res) => {
+                        console.log(res);
+                        let data = res.data
+                        this.CocoFlowList = data[0]
+                        this.hotApp = [data[1],data[2],data[3],data[4],]
+
+                    })
+                    .catch((err) => {
+                        console.error("请求失败,错误信息:", err);
+                    });
             }
         },
     }