sidebarL.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540
  1. <template>
  2. <div class="left">
  3. <!-- <div > -->
  4. <div class="logo2">
  5. <img :src="fromL.basics.logo ? fromL.basics.logo : require('../assets/img/moren.png')" alt="">
  6. </div>
  7. <!-- <div class="ulT"> -->
  8. <!-- 默认首页 -->
  9. <div class="ulTOne" @click.stop="goto(0)">
  10. <div class="menu_left">
  11. <div class="iconW">
  12. <img class="logo" :src="activeL === 0 ? require('../assets/img/sy.svg') : require('../assets/img/sy1.svg')" alt="">
  13. </div>
  14. <span class="barT" :style="{color : activeL === 0 ? '#0051D7' :''}">首页</span>
  15. </div>
  16. </div>
  17. <!-- 权限 -->
  18. <div v-for="(item,index) in appSignL(fromL.admin.sidebar.list)"
  19. :key="index+1">
  20. <!-- 渲染菜单类型 -->
  21. <div class="ulTOne TwoBar" v-if="item.menuName">
  22. <!-- 二级导航 -->
  23. <transition name="slide">
  24. <div class="ulTCopy2">
  25. <div class="ulTCopyTit">
  26. <span>{{ item.menuName }}</span>
  27. </div>
  28. <div class="ulTCopyHei">
  29. <div class="ulTCopyTxt"
  30. v-for="(i,ind) in appSignL(item.children)"
  31. @click="levTwo(i,ind,index)" :key="ind+'a'">
  32. <div class="ulTCopyTxt"
  33. :style="{background : (activeLTwo === index+1 +'+' + ind)? '#0663FE' : '',color: (activeLTwo === index+1 +'+' + ind)? '#fff' :''}"
  34. v-for="(p,pin) in AppCon(i.url)" :key="pin+'p'">
  35. <div class="ulTCopyConT">{{ p.name }}</div>
  36. </div>
  37. </div>
  38. </div>
  39. </div>
  40. </transition>
  41. <div class="menu_left">
  42. <div class="iconW">
  43. <img :src="activeL === (index +1) ? item.menuActiveIcon : item.menuIcon" class="logo" alt="">
  44. </div>
  45. <span class="barT">{{ item.menuName }}</span>
  46. </div>
  47. </div>
  48. <!-- 渲染平台工具类型 -->
  49. <div @click.stop="goto(index,item)"
  50. v-else>
  51. <div class="ulTOne TwoBar"
  52. @mouseenter="mouGet(item.toolId)"
  53. v-for="(p,pin) in AppCon(item.url)" :key="pin+'p'">
  54. <!-- 二级导航 -->
  55. <transition name="slide">
  56. <div class="ulTCopy2" v-if="item.toolId == 'appStore'">
  57. <div class="ulTCopyTit">
  58. <span>CocoFlow</span>
  59. </div>
  60. <div class="ulTCopyHei" >
  61. <span v-if="cocoFlowList[0].length" style="color: #00000066;">最近使用</span>
  62. <div class="ulTCopyTxt"
  63. v-for="(i,ind) in cocoFlowList[0]"
  64. @click="openNewWindow(i.url)" :key="ind+'ab'">
  65. <div class="ulTCopyConT">{{ i.name }}</div>
  66. </div>
  67. <span v-if="cocoFlowList[1].length" style="color: #00000066;">我的收藏</span>
  68. <div class="ulTCopyTxt"
  69. v-for="(i,ind) in cocoFlowList[1]" @click="openNewWindow(i.url)" :key="ind+'a'">
  70. <div class="ulTCopyConT">{{ i.name }}</div>
  71. </div>
  72. </div>
  73. </div>
  74. </transition>
  75. <div class="menu_left" >
  76. <div class="iconW">
  77. <img class="logo"
  78. :src="activeL === (index +1) ? p.activeIcon : p.defaultIcon"
  79. alt="">
  80. </div>
  81. <span class="barT" :style="{color : activeL === (index +1) ? '#0051D7' :''}">
  82. {{ p.name }}
  83. </span>
  84. </div>
  85. </div>
  86. </div>
  87. </div>
  88. </div>
  89. </template>
  90. <script>
  91. import { mapGetters, mapActions } from 'vuex';
  92. import store from '../store'
  93. import { API_CONFIG } from "@/common/apiConfig";
  94. export default {
  95. props:['urlAddress'],
  96. computed: {
  97. ...mapGetters(['userinfo','fromL','appSign']),
  98. // 如果hk,com没有图标,默认使用cn的
  99. AppCon(){
  100. return function(c) {
  101. let k = JSON.parse(JSON.stringify(c))
  102. let data = k.filter(e=>{
  103. return e.region == this.userinfo.schoolArea || e.region == this.userinfo.orgArea
  104. })
  105. let data2 = k.filter(e=>{
  106. return e.region == 'cn'
  107. })
  108. // 如果hk,com没有图标,默认使用cn的
  109. if (!data[0].icon){
  110. data[0].icon = data2[0].icon
  111. data[0].activeIcon = data2[0].activeIcon
  112. }
  113. return data
  114. };
  115. },
  116. // 筛选是否为管理员可见,是否被删除
  117. appSignL(){
  118. return function(val){
  119. // console.log('appSignL',val);
  120. let data = []
  121. if (this.userinfo.type == 1 && this.userinfo.role == 1) {
  122. val.forEach( e =>{
  123. if (e.menuName || e.status == 0) {
  124. data.push(e)
  125. }
  126. })
  127. } else {
  128. val.forEach( e =>{
  129. if (e.menuName || (e.isAdmin == '0' && e.status == 0)) {
  130. data.push(e)
  131. }
  132. })
  133. }
  134. return data
  135. }
  136. }
  137. },
  138. data() {
  139. return {
  140. // 一级选中第几个
  141. activeL:0,
  142. visible:true,
  143. // 二级选中第几个
  144. activeLTwo: null,
  145. cocoFlowList:[],
  146. }
  147. },
  148. methods: {
  149. ...mapActions({
  150. logout: 'user/logout'
  151. }),
  152. mouGet(val){
  153. if(val != 'appStore') return
  154. console.log('666')
  155. this.getData()
  156. },
  157. // 点击一级导航
  158. async goto(index,val = null){
  159. // console.log('goto',val);
  160. // val = null 就是点击了首页
  161. if (val) {
  162. this.activeL = index + 1
  163. }else{
  164. // 点击首页清空内容,并把标识去除
  165. await store.commit('user/SET_AppSIGN', '')
  166. this.$emit('update:urlAddress','')
  167. this.$emit('getPer')
  168. // 清空选中状态
  169. this.activeLTwo = ''
  170. this.activeL = index
  171. return
  172. }
  173. this.activeLTwo = ''
  174. // 点击相同应用不刷新
  175. if (this.appSign == val.toolId) return
  176. // 更新标识
  177. await store.commit('user/SET_AppSIGN', val.toolId)
  178. let url = ''
  179. // 查出对应账号的应用区域地址
  180. val.url.forEach(e => {
  181. // if (e.region == this.userinfo.schoolArea || e.region == this.userinfo.orgArea) {
  182. if (e.region == "beta") {
  183. url = e.url
  184. }
  185. });
  186. let _userinfo = this.userinfo, //登录用户信息
  187. { userid: _userid, organizeid: _oid, type: _type, org: _org, role: _role, classid: _classId } = _userinfo; // 解构赋值获取用户信息
  188. const _TscreenType = 1, _SscreenType = 3; // 常量定义
  189. let queryString = ''
  190. if(val.argumentList && val.argumentList.length){
  191. const paramsMap = {
  192. userid: _userid,
  193. org: _org,
  194. oid: _oid,
  195. tType: _type,
  196. role: _role,
  197. classId: _classId,
  198. TscreenType: _TscreenType,
  199. SscreenType: _SscreenType
  200. };
  201. const canshu = val.argumentList
  202. .filter(param => paramsMap[param] !== undefined)
  203. .map(param => `${param}=${paramsMap[param]}`);
  204. queryString = canshu.length ? (url.includes('?') ? '&' : '?') + canshu.join('&') : ''; // 生成查询字符串
  205. }
  206. let _url = url + queryString
  207. let kpl = ` <iframe
  208. v-if="appSign && urlAddress"
  209. allow= "camera *; microphone *;display-capture;midi;encrypted-media;"
  210. frameborder="no"
  211. border="0"
  212. style="border:0;width:100%;height:100%;"
  213. src="${_url}"
  214. ref="pageCon"
  215. >
  216. </iframe>`
  217. let pl = {json:kpl ,stateL :true,toolId :val.toolId}
  218. // 添加打开应用
  219. this.$emit('AddAppJson',pl)
  220. },
  221. // 获取cocoFlow收藏与历史使用记录
  222. getData(){
  223. let params = [
  224. {
  225. functionName: API_CONFIG.ajax_appStoreSave.functionName,
  226. uid: this.userinfo.userid,
  227. },
  228. ];
  229. this.$ajax
  230. .post(API_CONFIG.baseUrl, params)
  231. .then((res) => {
  232. this.cocoFlowList.push(res.data[0])
  233. this.cocoFlowList.push(res.data[1])
  234. })
  235. .catch((err) => {
  236. console.log(err);
  237. this.$message.error("获取常见应用失败");
  238. });
  239. },
  240. // 点击二级导航
  241. async levTwo(val,index,aInd){
  242. this.activeL = ''
  243. this.activeL = aInd +1
  244. this.activeLTwo = `${aInd + 1}+${index}`
  245. // 点击相同应用不刷新
  246. if (this.appSign == val.toolId) return
  247. // 更新标识
  248. await store.commit('user/SET_AppSIGN', val.toolId)
  249. let url = ''
  250. val.url.forEach(e => {
  251. // if (e.region == this.userinfo.schoolArea || e.region == this.userinfo.orgArea) {
  252. if (e.region == "beta") {
  253. url = e.url
  254. }
  255. });
  256. let _userinfo = this.userinfo, //登录用户信息
  257. { userid: _userid, organizeid: _oid, type: _type, org: _org, role: _role, classid: _classId } = _userinfo; // 解构赋值获取用户信息
  258. const _TscreenType = 1, _SscreenType = 3; // 常量定义
  259. let queryString = ''
  260. if(val.argumentList && val.argumentList.length){
  261. const paramsMap = {
  262. userid: _userid,
  263. org: _org,
  264. oid: _oid,
  265. tType: _type,
  266. role: _role,
  267. classId: _classId,
  268. TscreenType: _TscreenType,
  269. SscreenType: _SscreenType
  270. };
  271. const canshu = val.argumentList
  272. .filter(param => paramsMap[param] !== undefined)
  273. .map(param => `${param}=${paramsMap[param]}`);
  274. queryString = canshu.length ? (url.includes('?') ? '&' : '?') + canshu.join('&') : ''; // 生成查询字符串
  275. }
  276. let _url = url + queryString
  277. let kpl = ` <iframe
  278. v-if="appSign && urlAddress"
  279. allow= "camera *; microphone *;display-capture;midi;encrypted-media;"
  280. frameborder="no"
  281. border="0"
  282. style="border:0;width:100%;height:100%;"
  283. src="${_url}"
  284. ref="pageCon"
  285. >
  286. </iframe>`
  287. let pl = {json:kpl ,stateL :true,toolId :val.toolId}
  288. this.$emit('AddAppJson',pl)
  289. },
  290. openNewWindow(val) {
  291. console.log(val);
  292. // // 基本用法:打开指定 URL
  293. window.open(val, "_blank");
  294. },
  295. },
  296. }
  297. </script>
  298. <style scoped>
  299. .ulTCopy{
  300. overflow: auto;
  301. height: 100%;
  302. }
  303. .ulTCopy2 {
  304. height: 90%;
  305. width: 154px;
  306. overflow: hidden;
  307. background-color: rgb(255 255 255 / 98%);
  308. border-radius: 12px;
  309. position: fixed;
  310. left: -75px;
  311. top: 70px;
  312. z-index: -100;
  313. transition: transform .5s ease;
  314. }
  315. .TwoBar:hover .ulTCopy2{
  316. display: block !important;
  317. transform: translateX(164px) !important; /* 初始位置在视图之外 */
  318. z-index: -100;
  319. box-shadow: 0px 6px 30px 5px #0000000D;
  320. }
  321. .logo{
  322. margin: auto;
  323. width: 21px;
  324. max-height: 24px;
  325. }
  326. .iconW{
  327. width: 30px;
  328. height: 30px;
  329. display: flex;
  330. align-content: center;
  331. justify-content: center;
  332. padding: 1px;
  333. box-sizing: border-box;
  334. }
  335. .logo2 {
  336. padding: 8px;
  337. box-sizing: border-box;
  338. height: 48px;
  339. width: 100%;
  340. background-color: #fff;
  341. text-align: center;
  342. }
  343. .logo2 img{
  344. width: 30px;
  345. height: 30px;
  346. }
  347. .userInfo{
  348. width: 80px;
  349. color: #374151;
  350. font-size: 12px;
  351. display: flex;
  352. flex-direction: column;
  353. align-items: center;
  354. padding: 8px;
  355. box-sizing: border-box;
  356. background-color: #fff;
  357. padding-bottom: 20px;
  358. }
  359. .left {
  360. font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji" !important;
  361. width: 80px;
  362. height: 100%;
  363. padding:23px 6px;
  364. box-sizing: border-box;
  365. background-color: #ffffff;
  366. display: flex;
  367. flex-direction: column;
  368. align-items: center;
  369. gap: 24px;
  370. overflow: auto;
  371. border-right: 1px #D5D5D5 solid;
  372. }
  373. .ulTOne{
  374. width: 100%;
  375. border-radius: 10px;
  376. display: flex;
  377. height: 48px;
  378. width: 48px;
  379. flex-wrap:nowrap;
  380. align-content: center;
  381. justify-content: center;
  382. position: relative;
  383. }
  384. .barT{
  385. font-size:10px;
  386. overflow: hidden;
  387. white-space: nowrap;
  388. text-overflow: ellipsis;
  389. }
  390. .menu_left {
  391. width: 32px;
  392. height: 42px;
  393. font-size: 10px;
  394. color: #64748b;
  395. box-sizing: border-box;
  396. cursor: pointer;
  397. margin: auto;
  398. display: flex;
  399. flex-direction: column;
  400. align-items: center;
  401. gap: 2px;
  402. }
  403. .slide-enter-active, .slide-leave-active {
  404. transition: transform 0.5s ease;
  405. z-index: -1000 !important;
  406. }
  407. .slide-enter{
  408. z-index: -1000 !important;
  409. transform: translateX(0); /* 进入时移动到正常位置 */
  410. }
  411. .slide-leave-to /* .slide-leave-active in <2.1.8 */ {
  412. z-index: -1000 !important;
  413. transform: translateX(0); /* 进入时移动到正常位置 */
  414. }
  415. .ulTCopyTit{
  416. font-family: PingFang SC;
  417. font-weight: 600;
  418. font-size: 12px;
  419. letter-spacing: 0px;
  420. color: #000;
  421. height: 40px;
  422. padding: 12px 16px;
  423. box-sizing: border-box;
  424. border-bottom: .5px #e5e7eb solid;
  425. background: #fff !important;
  426. }
  427. .ulTCopyHei{
  428. display: flex;flex-direction: column;
  429. gap: 10px;
  430. overflow: auto;
  431. padding: 10px;
  432. overflow-x: hidden;
  433. height: calc(100% - 72px);
  434. }
  435. .ulTCopyTxt{
  436. box-sizing: border-box;display: flex;
  437. align-items: center;
  438. color: #374151;
  439. width: 100%;
  440. border-radius: 10px;
  441. font-size: 16px;
  442. margin: 0;
  443. }
  444. .ulTCopyTxtBlock{
  445. width: 100%;
  446. }
  447. .ulTCopyConT {
  448. width: 100%;
  449. font-size: 12px;
  450. cursor: pointer;
  451. border-radius: 8px;
  452. padding: 8px;
  453. box-sizing: border-box;
  454. white-space: nowrap;
  455. overflow: hidden;
  456. text-overflow: ellipsis;
  457. }
  458. .ulTCopyConT:hover{
  459. background: #e7e7e7;
  460. color: #000;
  461. }
  462. .ulTCopyTxtCon{
  463. display: flex;align-items: center;width: 100%;
  464. }
  465. /* .ulTCopyTxt:hover{
  466. background-color: #f3f4f6 !important;
  467. } */
  468. .cha:hover{
  469. color: #000 !important;
  470. }
  471. .ovlH{
  472. overflow: hidden;
  473. white-space: nowrap;
  474. text-overflow: ellipsis;
  475. }
  476. </style>