preview.vue 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759
  1. <!--
  2. * @Description:
  3. * @Version: 1.668
  4. * @Autor: 地虎降天龙
  5. * @Date: 2023-11-18 22:17:49
  6. * @LastEditors: 地虎降天龙
  7. * @LastEditTime: 2026-05-12 09:06:12
  8. -->
  9. <template>
  10. <div class="absolute menuSelf">
  11. <div class="btn-just" @click="openTopMune"><MoreCircleOutlined /></div>
  12. </div>
  13. <FDrawer v-model:show="showTopMune" placement="top" title="" @ok="showTopMune = false">
  14. <f-menu mode="vertical" :collapsed="false" inverted @select="menuGoto">
  15. <template v-for="(item, index) in layoutConfigMenus" :key="index">
  16. <f-sub-menu v-if="item.children" :value="index">
  17. <template #label>{{ item.title }}</template>
  18. <template v-for="(oneo, pkey) in item.children">
  19. <f-menu-item :value="index * 10 + pkey">
  20. <template #label>{{ oneo.title }}</template>
  21. </f-menu-item>
  22. </template>
  23. </f-sub-menu>
  24. <f-menu-item v-else :value="index">
  25. <template #label>{{ item.title }}</template>
  26. </f-menu-item>
  27. </template>
  28. </f-menu>
  29. </FDrawer>
  30. <div class="flex h-full w-full">
  31. <div style="background-color: #0f1222">
  32. <FMenu
  33. mode="vertical"
  34. expandTrigger="click"
  35. :defaultExpandAll="detectDeviceType() === 'PC'"
  36. :collapsed="detectDeviceType() !== 'PC'"
  37. :inverted="true"
  38. @select="goto"
  39. >
  40. <f-sub-menu value="1">
  41. <template #icon>
  42. <AppstoreOutlined />
  43. </template>
  44. <template #label>
  45. <div class="flex absolute" style="left: 1px; flex-direction: column; top: 10px">
  46. <f-badge value="AllFree" class="tag-fbdge afree-tag" type="success" size="small" />
  47. </div>
  48. 基础功能组件 <FBadge :max="999" :value="getMenusCount().basic" class="count-fbdge big-cf" type="primary" size="small"
  49. /></template>
  50. <template v-for="(bP, pkey) in filteredData">
  51. <f-menu-item v-if="pkey === 'basic'" v-for="(onePlugin, okey) in bP.child" :value="onePlugin.name">
  52. <template #label>
  53. <div class="flex absolute badge-group">
  54. <template v-for="(lbItem, lbKey) in getleftMenuBadge(onePlugin.name)">
  55. <f-badge v-if="lbItem.show" :value="lbItem.text" class="tag-fbdge" type="primary" size="small" />
  56. </template>
  57. </div>
  58. <span class="left-m-text">{{ onePlugin.title }}</span>
  59. <FBadge :value="onePlugin.preview.length" class="count-fbdge" type="primary" size="small"
  60. /></template>
  61. </f-menu-item>
  62. </template>
  63. </f-sub-menu>
  64. <f-sub-menu value="2">
  65. <template #icon>
  66. <PictureOutlined />
  67. </template>
  68. <template #label>
  69. <div class="flex absolute" style="left: 1px; flex-direction: column; top: 10px">
  70. <f-badge value="AllFree" class="tag-fbdge afree-tag" type="success" size="small" />
  71. </div>
  72. 样例与组件 <FBadge :max="999" :value="getMenusCount().case" class="count-fbdge big-cf" type="primary" size="small"
  73. /></template>
  74. <template v-for="(onePlugin, pkey) in filteredData">
  75. <f-menu-item v-if="pkey !== 'basic' && isTvtstore(onePlugin) === 'caseCenter'" :value="pkey">
  76. <template #label>
  77. <div class="flex absolute badge-group">
  78. <template v-for="(lbItem, lbKey) in getleftMenuBadge(onePlugin.name)">
  79. <f-badge v-if="lbItem.show" :value="lbItem.text" class="tag-fbdge" type="primary" size="small" />
  80. </template>
  81. </div>
  82. <span class="left-m-text">{{ onePlugin.title }}</span>
  83. <FBadge :value="onePlugin.preview.length" class="count-fbdge" type="primary" size="small" />
  84. </template>
  85. </f-menu-item>
  86. </template>
  87. </f-sub-menu>
  88. <f-sub-menu value="3">
  89. <template #icon>
  90. <ClusterOutlined />
  91. </template>
  92. <template #label
  93. >插件应用管理 <FBadge :max="999" :value="getMenusCount().tvtstore" class="count-fbdge big-cf" type="primary" size="small"
  94. /></template>
  95. <f-menu-item value="tvtPluginUrl">
  96. <template #label>
  97. <div class="flex absolute badge-group">
  98. <f-badge value="tvtstore" class="tag-fbdge" type="danger" size="small" />
  99. </div>
  100. <span class="left-m-text">插件应用市场</span>
  101. </template>
  102. </f-menu-item>
  103. <template v-for="(onePlugin, pkey) in filteredData">
  104. <f-menu-item v-if="pkey !== 'basic' && isTvtstore(onePlugin) === 'Tvtstore'" :value="pkey">
  105. <template #label>
  106. <div class="flex absolute badge-group">
  107. <f-badge value="free" class="tag-fbdge afree-tag" type="success" size="small" v-if="onePlugin.tvtstore === 'FREE'" />
  108. </div>
  109. <div class="flex absolute" style="top: 3px; right: 30px">
  110. <f-badge :value="onePlugin.version" class="tag-fbdge" type="primary" size="small" />
  111. </div>
  112. <span class="left-m-text">{{ onePlugin.title }}</span>
  113. <FBadge :value="onePlugin.preview.length" class="count-fbdge" type="primary" size="small" />
  114. </template>
  115. </f-menu-item>
  116. </template>
  117. </f-sub-menu>
  118. <f-sub-menu value="4">
  119. <template #icon>
  120. <ProductOutlined />
  121. </template>
  122. <template #label
  123. >区域场景编辑器 <FBadge :max="999" :value="getMenusCount().zoneEditor" class="count-fbdge big-cf" type="primary" size="small"
  124. /></template>
  125. <f-menu-item value="zoneEditorUrl">
  126. <template #label>
  127. <div class="flex absolute badge-group">
  128. <f-badge value="zoneEditor" class="tag-fbdge" type="danger" size="small" />
  129. </div>
  130. <span class="left-m-text">编辑器介绍</span>
  131. </template>
  132. </f-menu-item>
  133. <template v-for="(onePlugin, pkey) in filteredData">
  134. <f-menu-item v-if="pkey !== 'basic' && isTvtstore(onePlugin) === 'zoneEditor'" :value="pkey">
  135. <template #label>
  136. <div class="flex absolute badge-group">
  137. <f-badge value="free" class="tag-fbdge afree-tag" type="success" size="small" v-if="onePlugin.tvtstore === 'FREE' || onePlugin.name === 'zone3Deditor'" />
  138. </div>
  139. <div class="flex absolute" style="top: 3px; right: 30px">
  140. <f-badge :value="onePlugin.version" class="tag-fbdge" type="primary" size="small" />
  141. </div>
  142. <span class="left-m-text">{{ onePlugin.title }}</span>
  143. <FBadge :value="onePlugin.preview.length" class="count-fbdge" type="primary" size="small" />
  144. </template>
  145. </f-menu-item>
  146. </template>
  147. </f-sub-menu>
  148. <f-sub-menu value="5">
  149. <template #icon>
  150. <ManagementOutlined />
  151. </template>
  152. <template #label
  153. >GIS地理空间编辑器 <FBadge :max="999" :value="getMenusCount().gisEditor" class="count-fbdge big-cf" type="primary" size="small"
  154. /></template>
  155. <f-menu-item value="gisPlaneEditorIntroUrl">
  156. <template #label>
  157. <div class="flex absolute badge-group">
  158. <f-badge value="GIS" class="tag-fbdge" type="danger" size="small" />
  159. </div>
  160. <span class="left-m-text">编辑器介绍</span>
  161. </template>
  162. </f-menu-item>
  163. <template v-for="(onePlugin, pkey) in filteredData">
  164. <f-menu-item v-if="pkey !== 'basic' && isTvtstore(onePlugin) === 'gisEditor'" :value="pkey">
  165. <template #label>
  166. <div class="flex absolute badge-group">
  167. <f-badge value="free" class="tag-fbdge afree-tag" type="success" size="small" v-if="onePlugin.tvtstore === 'FREE'" />
  168. </div>
  169. <div class="flex absolute" style="top: 3px; right: 30px">
  170. <f-badge :value="onePlugin.version" class="tag-fbdge" type="primary" size="small" />
  171. </div>
  172. <span class="left-m-text">{{ onePlugin.title }}</span>
  173. <FBadge :value="onePlugin.preview.length" class="count-fbdge" type="primary" size="small" />
  174. </template>
  175. </f-menu-item>
  176. </template>
  177. </f-sub-menu>
  178. <f-sub-menu value="animationEditorMenu">
  179. <template #icon>
  180. <PlayOutlined />
  181. </template>
  182. <template #label
  183. >动画编辑器 <FBadge :max="999" :value="getMenusCount().animationEditor" class="count-fbdge big-cf" type="primary" size="small"
  184. /></template>
  185. <f-menu-item value="animationEditorIntroUrl">
  186. <template #label>
  187. <div class="flex absolute badge-group">
  188. <f-badge value="动画" class="tag-fbdge" type="danger" size="small" />
  189. </div>
  190. <span class="left-m-text">编辑器介绍</span>
  191. </template>
  192. </f-menu-item>
  193. <template v-for="(onePlugin, pkey) in filteredData">
  194. <f-menu-item v-if="pkey !== 'basic' && isTvtstore(onePlugin) === 'animationEditor'" :value="pkey">
  195. <template #label>
  196. <div class="flex absolute badge-group">
  197. <f-badge value="free" class="tag-fbdge afree-tag" type="success" size="small" v-if="onePlugin.tvtstore === 'FREE'" />
  198. </div>
  199. <div class="flex absolute" style="top: 3px; right: 30px">
  200. <f-badge :value="onePlugin.version" class="tag-fbdge" type="primary" size="small" />
  201. </div>
  202. <span class="left-m-text">{{ onePlugin.title }}</span>
  203. <FBadge :value="onePlugin.preview.length" class="count-fbdge" type="primary" size="small" />
  204. </template>
  205. </f-menu-item>
  206. </template>
  207. </f-sub-menu>
  208. <f-sub-menu value="materialEditorMenu">
  209. <template #icon>
  210. <PictureOutlined />
  211. </template>
  212. <template #label
  213. >材质编辑器 <FBadge :max="999" :value="getMenusCount().materialEditor" class="count-fbdge big-cf" type="primary" size="small"
  214. /></template>
  215. <f-menu-item value="materialEditorIntroUrl">
  216. <template #label>
  217. <div class="flex absolute badge-group">
  218. <f-badge value="材质" class="tag-fbdge" type="danger" size="small" />
  219. </div>
  220. <span class="left-m-text">编辑器介绍</span>
  221. </template>
  222. </f-menu-item>
  223. <template v-for="(onePlugin, pkey) in filteredData">
  224. <f-menu-item v-if="pkey !== 'basic' && isTvtstore(onePlugin) === 'materialEditor'" :value="pkey">
  225. <template #label>
  226. <div class="flex absolute badge-group">
  227. <f-badge value="free" class="tag-fbdge afree-tag" type="success" size="small" v-if="onePlugin.tvtstore === 'FREE'" />
  228. </div>
  229. <div class="flex absolute" style="top: 3px; right: 30px">
  230. <f-badge :value="onePlugin.version" class="tag-fbdge" type="primary" size="small" />
  231. </div>
  232. <span class="left-m-text">{{ onePlugin.title }}</span>
  233. <FBadge :value="onePlugin.preview.length" class="count-fbdge" type="primary" size="small" />
  234. </template>
  235. </f-menu-item>
  236. </template>
  237. </f-sub-menu>
  238. <f-sub-menu value="6">
  239. <template #icon>
  240. <CodeOutlined />
  241. </template>
  242. <template #label
  243. >动态组件服务 <FBadge :max="999" :value="getMenusCount().loadDynamic" class="count-fbdge big-cf" type="primary" size="small"
  244. /></template>
  245. <template v-for="(onePlugin, pkey) in filteredData">
  246. <f-menu-item v-if="pkey !== 'basic' && isTvtstore(onePlugin) === 'loadDynamic'" :value="pkey">
  247. <template #label>
  248. <div class="flex absolute badge-group">
  249. <f-badge value="free" class="tag-fbdge afree-tag" type="success" size="small" v-if="onePlugin.tvtstore === 'FREE'" />
  250. </div>
  251. <div class="flex absolute" style="top: 3px; right: 30px">
  252. <f-badge :value="onePlugin.version" class="tag-fbdge" type="primary" size="small" />
  253. </div>
  254. <span class="left-m-text">{{ onePlugin.title }}</span>
  255. <FBadge :value="onePlugin.preview.length" class="count-fbdge" type="primary" size="small" />
  256. </template>
  257. </f-menu-item>
  258. </template>
  259. <f-menu-item value="loadDynamicEcoUrl">
  260. <template #label>
  261. <div class="flex absolute badge-group">
  262. <f-badge value="dcser" class="tag-fbdge" type="danger" size="small" />
  263. </div>
  264. <span class="left-m-text">动态组件服务生态</span>
  265. </template>
  266. </f-menu-item>
  267. </f-sub-menu>
  268. </FMenu>
  269. </div>
  270. <div
  271. id="right-page-list-id"
  272. class="overflow-scroll relative right-page-list"
  273. :class="{ 'mt-10': detectDeviceType() === 'PC' }"
  274. style="height: calc(100vh - 42px - 52px); width: 100%"
  275. >
  276. <filterComFixed v-show="detectDeviceType() === 'PC'" />
  277. <template v-for="(onePlugin, pkey) in filteredData" :key="pkey">
  278. <template v-if="pkey === 'basic'">
  279. <div style="background-color: #f1f1f2" v-for="(one, opkey) in onePlugin.child" :key="opkey" :ref="(el) => (tabListRef[one.name] = el)">
  280. <cardList :onePlugin="one" />
  281. </div>
  282. </template>
  283. </template>
  284. <template v-for="(onePlugin, pkey) in filteredData" :key="pkey">
  285. <div style="background-color: #f1f1f2" v-if="pkey !== 'basic' && isTvtstore(onePlugin) === 'caseCenter'" :ref="(el) => (tabListRef[pkey] = el)">
  286. <cardList :onePlugin="onePlugin" />
  287. </div>
  288. </template>
  289. <template v-for="(onePlugin, pkey) in filteredData" :key="pkey">
  290. <div style="background-color: #f1f1f2" v-if="pkey !== 'basic' && isTvtstore(onePlugin) === 'Tvtstore'" :ref="(el) => (tabListRef[pkey] = el)">
  291. <cardList :onePlugin="onePlugin" />
  292. </div>
  293. </template>
  294. <template v-for="(onePlugin, pkey) in filteredData" :key="pkey">
  295. <div style="background-color: #f1f1f2" v-if="pkey !== 'basic' && isTvtstore(onePlugin) === 'zoneEditor'" :ref="(el) => (tabListRef[pkey] = el)">
  296. <cardList :onePlugin="onePlugin" />
  297. </div>
  298. </template>
  299. <template v-for="(onePlugin, pkey) in filteredData" :key="pkey">
  300. <div style="background-color: #f1f1f2" v-if="pkey !== 'basic' && isTvtstore(onePlugin) === 'gisEditor'" :ref="(el) => (tabListRef[pkey] = el)">
  301. <cardList :onePlugin="onePlugin" />
  302. </div>
  303. </template>
  304. <template v-for="(onePlugin, pkey) in filteredData" :key="pkey">
  305. <div style="background-color: #f1f1f2" v-if="pkey !== 'basic' && isTvtstore(onePlugin) === 'animationEditor'" :ref="(el) => (tabListRef[pkey] = el)">
  306. <cardList :onePlugin="onePlugin" />
  307. </div>
  308. </template>
  309. <template v-for="(onePlugin, pkey) in filteredData" :key="pkey">
  310. <div style="background-color: #f1f1f2" v-if="pkey !== 'basic' && isTvtstore(onePlugin) === 'materialEditor'" :ref="(el) => (tabListRef[pkey] = el)">
  311. <cardList :onePlugin="onePlugin" />
  312. </div>
  313. </template>
  314. <template v-for="(onePlugin, pkey) in filteredData" :key="pkey">
  315. <div style="background-color: #f1f1f2" v-if="pkey !== 'basic' && isTvtstore(onePlugin) === 'loadDynamic'" :ref="(el) => (tabListRef[pkey] = el)">
  316. <cardList :onePlugin="onePlugin" />
  317. </div>
  318. </template>
  319. <UpCircleOutlined class="toTop" @click="scrollToTop" />
  320. </div>
  321. </div>
  322. </template>
  323. <script setup lang="ts">
  324. import { ref, provide, watch, onMounted, nextTick } from 'vue'
  325. import { defineRouteMeta, useRoute, useRouter } from '@fesjs/fes'
  326. import { FBadge, FDrawer, FMenu, FSubMenu, FMenuItem } from '@fesjs/fes-design'
  327. import {
  328. AppstoreOutlined,
  329. PictureOutlined,
  330. UpCircleOutlined,
  331. MoreCircleOutlined,
  332. ClusterOutlined,
  333. ProductOutlined,
  334. ManagementOutlined,
  335. PlayOutlined,
  336. CodeOutlined,
  337. } from '@fesjs/fes-design/icon'
  338. import { getPluginsConfig, getOnlinePluginConfig, detectDeviceType } from '../common/utils'
  339. import { useForPreviewStore } from '@/stores/forPreview'
  340. import cardList from '../components/forPreview/cardList.vue'
  341. import filterComFixed from '../components/forPreview/filterComFixed.vue'
  342. defineRouteMeta({
  343. name: 'preview',
  344. title: '开源框架展示',
  345. })
  346. const layoutConfigMenus = window.layoutConfig.menus
  347. const menuGoto = (value: any) => {
  348. console.log(value)
  349. if (value.value >= 10) {
  350. const i1 = Math.floor(value.value / 10)
  351. const i2 = value.value % 10
  352. window.location.assign(layoutConfigMenus[i1].children[i2].path)
  353. } else {
  354. window.location.assign(layoutConfigMenus[value.value].path)
  355. }
  356. }
  357. const tabListRef = ref([]) as any
  358. const pluginsConfig = ref(getPluginsConfig() as any)
  359. const router = useRouter()
  360. const scrollToPlugin = (name: string) => {
  361. tabListRef.value[name]?.scrollIntoView({ behavior: 'smooth', block: 'start' })
  362. }
  363. const goto = (value: any) => {
  364. if (value.value === 'tvtPluginUrl') {
  365. window.open('https://www.icegl.cn/tvtstore', '_blank')
  366. } else if (value.value === 'zoneEditorUrl') {
  367. window.open('https://www.icegl.cn/tvtstore/zone3Deditor', '_blank')
  368. } else if (value.value === 'gisPlaneEditorIntroUrl') {
  369. window.open('https://www.icegl.cn/tvtstore/gisPlaneEditor', '_blank')
  370. } else if (value.value === 'animationEditorIntroUrl') {
  371. window.open('https://www.icegl.cn/tvtstore/animationEditor.html', '_blank')
  372. } else if (value.value === 'materialEditorIntroUrl') {
  373. window.open('https://www.icegl.cn/tvtstore/materialEditor', '_blank')
  374. } else if (value.value === 'loadDynamicEcoUrl') {
  375. window.open('https://dcser.icegl.cn', '_blank')
  376. } else {
  377. scrollToPlugin(value.value)
  378. router.replace({ hash: `#${value.value}` })
  379. }
  380. }
  381. const route = useRoute()
  382. const scrollToHash = async () => {
  383. await nextTick()
  384. const hash = route.hash
  385. const tabdom = hash.startsWith('#') ? hash.slice(1) : hash
  386. if (tabdom) {
  387. scrollToPlugin(tabdom)
  388. }
  389. }
  390. const scrollToTop = () => {
  391. document.querySelector('.right-page-list')?.scrollTo({ top: 0, behavior: 'smooth' })
  392. }
  393. // const expandedKeys = ref(['1','2','3'])
  394. const filterFixedInputValue = ref('')
  395. provide('filterFixedInputValue', filterFixedInputValue)
  396. const filterObjects = (obj: any, searchString: string): any => {
  397. if (!searchString) {
  398. return filterMenuSetup(menuSetupFilter.value)
  399. }
  400. const result = {} as any
  401. for (const key in obj) {
  402. if (obj.hasOwnProperty(key)) {
  403. const item = obj[key]
  404. if (typeof item === 'object') {
  405. if (key === 'basic') {
  406. const bItem = Object.values(filterObjects(item.child, searchString))
  407. if (bItem.length) {
  408. result[key] = {}
  409. Object.assign(result[key], item, { child: bItem })
  410. }
  411. continue
  412. }
  413. const hasMatchInTitleOrName =
  414. (item.title && item.title.toLocaleLowerCase().includes(searchString)) || (item.name && item.name.toLocaleLowerCase().includes(searchString))
  415. if (hasMatchInTitleOrName) {
  416. result[key] = item
  417. continue
  418. } else {
  419. const filteredPreview = item.preview.filter((previewItem: any) => {
  420. return (
  421. (previewItem.name && previewItem.name.toLocaleLowerCase().includes(searchString)) ||
  422. (previewItem.title && previewItem.title.toLocaleLowerCase().includes(searchString))
  423. )
  424. })
  425. if (filteredPreview.length > 0) {
  426. result[key] = { ...item, preview: filteredPreview }
  427. }
  428. }
  429. }
  430. }
  431. }
  432. return result
  433. }
  434. const filteredData = ref(pluginsConfig.value) as any
  435. const { menuSetup } = useForPreviewStore()
  436. function filterMenuSetup(msFilter: any) {
  437. if (msFilter.length === 0) {
  438. return pluginsConfig.value
  439. }
  440. const result = {} as any
  441. msFilter.forEach((tag: any) => {
  442. if (menuSetup.value) {
  443. for (const key in menuSetup.value) {
  444. if (menuSetup.value.hasOwnProperty(key)) {
  445. for (const key2 in menuSetup.value[key]) {
  446. if (menuSetup.value[key].hasOwnProperty(key2)) {
  447. if (menuSetup.value[key][key2].taglist === tag) {
  448. if (pluginsConfig.value[key]?.preview) {
  449. const filteredPreview = pluginsConfig.value[key].preview.filter((item: any) => item.name === key2)
  450. if (filteredPreview) {
  451. if (result[key]) {
  452. result[key].preview = result[key].preview.concat(filteredPreview)
  453. } else {
  454. result[key] = { ...pluginsConfig.value[key], preview: filteredPreview }
  455. }
  456. }
  457. }
  458. }
  459. }
  460. }
  461. }
  462. }
  463. }
  464. })
  465. return result
  466. }
  467. const menuSetupFilter = ref([])
  468. provide('menuSetupFilter', menuSetupFilter)
  469. const refreshFilteredData = () => {
  470. filteredData.value = filterObjects(pluginsConfig.value, String(filterFixedInputValue.value || '').toLocaleLowerCase())
  471. }
  472. watch(filterFixedInputValue, refreshFilteredData)
  473. watch(menuSetupFilter, refreshFilteredData)
  474. watch(pluginsConfig, refreshFilteredData, {
  475. deep: true,
  476. })
  477. const shouldCheckReleaseMenu = process.env.NODE_ENV === 'development' || process.env.FES_APP_ONLINE_API
  478. const onlinePluginConfigReady =
  479. process.env.FES_APP_PLSNAME === undefined
  480. ? getOnlinePluginConfig(pluginsConfig, {
  481. checkReleaseMenu: shouldCheckReleaseMenu,
  482. })
  483. : Promise.resolve()
  484. onMounted(async () => {
  485. await scrollToHash()
  486. await onlinePluginConfigReady
  487. await scrollToHash()
  488. })
  489. const getleftMenuBadge = (name: string) => {
  490. const tagOne = {
  491. recommend: { show: false, text: '荐' },
  492. new: { show: false, text: '新' },
  493. hot: { show: false, text: '热' },
  494. editor: { show: false, text: '热' },
  495. } as any
  496. if (menuSetup.value && menuSetup.value[name]) {
  497. const tmpOne = menuSetup.value[name]
  498. for (const key in tmpOne) {
  499. tagOne[tmpOne[key].taglist].show = true
  500. if (tmpOne[key].taglist === 'editor') {
  501. // 编辑器标识 特殊处理
  502. tagOne[tmpOne[key].taglist].show = false
  503. }
  504. }
  505. }
  506. return tagOne
  507. }
  508. // 区分是否是案例中心的 还是 插件市场的
  509. const isTvtstore = (onePlugin: any) => {
  510. if (typeof onePlugin.tvtstore !== 'undefined') {
  511. if (onePlugin.name.startsWith('zone')) {
  512. return 'zoneEditor'
  513. } else if (onePlugin.name.startsWith('gis')) {
  514. return 'gisEditor'
  515. } else if (onePlugin.name.startsWith('animation')) {
  516. return 'animationEditor'
  517. } else if (onePlugin.name.startsWith('material')) {
  518. return 'materialEditor'
  519. } else if (onePlugin.name.startsWith('loadDynamic')) {
  520. return 'loadDynamic'
  521. }else {
  522. return 'Tvtstore'
  523. }
  524. } else {
  525. return 'caseCenter'
  526. }
  527. }
  528. const getMenusCount = () => {
  529. const reCount = {
  530. basic: 0,
  531. case: 0,
  532. tvtstore: 0,
  533. loadDynamic: 0,
  534. zoneEditor: 0,
  535. gisEditor: 0,
  536. animationEditor: 0,
  537. materialEditor: 0,
  538. }
  539. for (const key in filteredData.value) {
  540. if (filteredData.value.hasOwnProperty(key)) {
  541. if (key === 'basic') {
  542. for (const key2 in filteredData.value[key].child) {
  543. if (filteredData.value[key].child.hasOwnProperty(key2)) {
  544. reCount.basic += filteredData.value[key].child[key2].preview.length
  545. }
  546. }
  547. } else {
  548. if (isTvtstore(filteredData.value[key]) === 'Tvtstore') {
  549. reCount.tvtstore += filteredData.value[key].preview.length
  550. } else if (isTvtstore(filteredData.value[key]) === 'caseCenter') {
  551. reCount.case += filteredData.value[key].preview.length
  552. } else if (isTvtstore(filteredData.value[key]) === 'zoneEditor') {
  553. reCount.zoneEditor += filteredData.value[key].preview.length
  554. } else if (isTvtstore(filteredData.value[key]) === 'gisEditor') {
  555. reCount.gisEditor += filteredData.value[key].preview.length
  556. } else if (isTvtstore(filteredData.value[key]) === 'animationEditor') {
  557. reCount.animationEditor += filteredData.value[key].preview.length
  558. } else if (isTvtstore(filteredData.value[key]) === 'materialEditor') {
  559. reCount.materialEditor += filteredData.value[key].preview.length
  560. } else if (isTvtstore(filteredData.value[key]) === 'loadDynamic') {
  561. reCount.loadDynamic += filteredData.value[key].preview.length
  562. }
  563. }
  564. }
  565. }
  566. return reCount
  567. }
  568. const showTopMune = ref(false)
  569. const openTopMune = () => {
  570. showTopMune.value = true
  571. }
  572. </script>
  573. <style lang="less">
  574. @media (max-width: 900px) {
  575. #tvt-app > section > div > header > div.fes-menu.is-horizontal.is-inverted.layout-menu {
  576. display: none;
  577. }
  578. .fes-layout-container {
  579. z-index: 9999;
  580. position: absolute;
  581. overflow: visible !important;
  582. }
  583. .menuSelf {
  584. z-index: 99999;
  585. right: 0px;
  586. top: -40px;
  587. .btn-just {
  588. color: #fff;
  589. width: 1.5em;
  590. font-size: 1.5em;
  591. cursor: pointer;
  592. display: flex;
  593. }
  594. }
  595. body > div.fes-drawer.fes-drawer-top > {
  596. div.fes-drawer-mask {
  597. z-index: 9999 !important;
  598. }
  599. .fes-drawer-container {
  600. z-index: 9999 !important;
  601. .fes-drawer-wrapper {
  602. width: 100%;
  603. height: 520px;
  604. background: #ff000000;
  605. padding-top: 50px;
  606. .fes-drawer-close {
  607. margin-top: 7px;
  608. padding-right: 13px;
  609. color: white;
  610. }
  611. }
  612. .fes-drawer-body-container {
  613. background: #0f1222;
  614. }
  615. }
  616. }
  617. .fes-popper-wrapper {
  618. z-index: 9999 !important;
  619. overflow: scroll;
  620. scrollbar-width: thin;
  621. height: 100vh;
  622. }
  623. }
  624. .layout-logo {
  625. /* margin-right: 6.2em !important; */
  626. width: 12.5rem !important;
  627. max-width: 181px;
  628. padding: 0 !important;
  629. justify-content: center !important;
  630. margin: 0 !important;
  631. }
  632. .fes-menu.is-vertical.is-inverted .fes-menu-item,
  633. .fes-menu.is-horizontal.is-inverted .fes-menu-item {
  634. font-size: 0.93em;
  635. font-weight: 100;
  636. }
  637. .fes-menu.is-vertical.is-inverted {
  638. overflow: hidden;
  639. height: calc(100vh - 54px);
  640. overflow: scroll;
  641. }
  642. .fes-menu.is-vertical.is-inverted::-webkit-scrollbar {
  643. display: none;
  644. }
  645. .main-layout .layout-header {
  646. overflow: hidden;
  647. }
  648. .fes-checkbox-group {
  649. margin-bottom: 5px;
  650. margin-right: 20px;
  651. }
  652. .count-fbdge {
  653. span {
  654. border-radius: 3px !important;
  655. background-color: #0f1222 !important;
  656. border: white 1px solid;
  657. scale: 0.8;
  658. padding: 1px !important;
  659. margin-top: 2px;
  660. height: 15px;
  661. }
  662. }
  663. .tag-fbdge {
  664. span {
  665. border-radius: 2px !important;
  666. padding: 0px !important;
  667. }
  668. }
  669. &.afree-tag {
  670. span {
  671. border-radius: 2px !important;
  672. padding: 2px !important;
  673. }
  674. }
  675. .fes-menu.is-vertical .fes-menu-item-wrapper {
  676. height: 46px !important;
  677. }
  678. </style>
  679. <style lang="less" scoped>
  680. @media (min-width: 901px) {
  681. .right-page-list {
  682. scroll-padding-top: 50px;
  683. }
  684. }
  685. .toTop {
  686. position: fixed;
  687. right: 20px;
  688. bottom: 20px;
  689. font-size: 26px;
  690. font-weight: bold;
  691. color: #0f1222;
  692. cursor: pointer;
  693. }
  694. .count-fbdge {
  695. position: absolute;
  696. right: 13px;
  697. top: 13.8px;
  698. }
  699. &.big-cf {
  700. position: relative;
  701. left: -2px;
  702. right: auto;
  703. top: 0px;
  704. }
  705. .tag-fbdge {
  706. scale: 0.8;
  707. margin-bottom: -3px;
  708. margin-top: 1px;
  709. }
  710. .left-m-text {
  711. width: 95%;
  712. display: block;
  713. text-overflow: ellipsis;
  714. white-space: nowrap;
  715. overflow: hidden;
  716. }
  717. .badge-group {
  718. left: 1px;
  719. flex-direction: column;
  720. top: 2px;
  721. }
  722. @media (max-width: 900px) {
  723. .badge-group {
  724. left: -3px;
  725. top: -4px;
  726. }
  727. .tag-fbdge[data-v-470f55ee] {
  728. scale: 0.8;
  729. margin-bottom: -5px;
  730. margin-top: 0px;
  731. }
  732. }
  733. </style>