list.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  1. <template>
  2. <div class="bar-list" :class=" store.listIsShow ? '' : 'bar-list-hidden'">
  3. <div
  4. class="swiper-container"
  5. id="swcatalogRoot"
  6. v-if="
  7. store.metadata.catalogRoot.length > 0 &&
  8. store.metadata.catalogs.length > 1
  9. "
  10. >
  11. <ul class="swiper-wrapper" v-if="store.metadata.catalogRoot.length > 1">
  12. <li
  13. class="swiper-slide"
  14. :class="{
  15. active: store.currentCatalogRoot.id == item.id,
  16. loopspan:
  17. item.name.length > spanlength &&
  18. store.currentCatalogRoot.id == item.id,
  19. }"
  20. @click="tabRoot(item)"
  21. v-for="(item, i) in store.metadata.catalogRoot"
  22. :key="i"
  23. >
  24. <div class="area-text" v-if="store.currentCatalogRoot.id == item.id">
  25. {{ item.name }}
  26. <div class="active-line"></div>
  27. </div>
  28. <div class="area-text" v-else>
  29. {{
  30. item.name.length > spanlength
  31. ? item.name.slice(0, spanlength)
  32. : item.name
  33. }}
  34. <!-- <div class="active-line"></div> -->
  35. </div>
  36. </li>
  37. </ul>
  38. <img
  39. src="../../assets/images/resource/scene/downIcon.png"
  40. @click="departure"
  41. />
  42. </div>
  43. <div
  44. class="bottom-con"
  45. :style="`width:${
  46. Math.max(scenesListW, secondaryW) > 1150
  47. ? '100%'
  48. : Math.max(scenesListW, secondaryW) + 120 + 'px'
  49. }`"
  50. >
  51. <div
  52. class="swiper-container"
  53. :style="`width:${scenesListW > 1150 ? '100%' : scenesListW + 'px'}`"
  54. id="swScenes"
  55. v-if="store.currentScenesList.length > 0"
  56. >
  57. <ul class="swiper-wrapper">
  58. <li
  59. @click="tabCurrentScene(item)"
  60. class="swiper-slide"
  61. :class="{
  62. active: store.currentScene.sceneCode == item.sceneCode,
  63. loopspan:
  64. item.sceneTitle.length > spanlength &&
  65. store.currentScene.id == item.id,
  66. }"
  67. :style="{ backgroundImage: `url(${item.icon})` }"
  68. v-for="(item, i) in store.currentScenesList"
  69. :key="i"
  70. >
  71. <div>
  72. <span v-if="store.currentScene.id == item.id"
  73. >{{ item.sceneTitle }}
  74. </span>
  75. <span v-else>{{
  76. item.sceneTitle.length > spanlength
  77. ? item.sceneTitle.slice(0, spanlength)
  78. : item.sceneTitle
  79. }}</span>
  80. </div>
  81. </li>
  82. </ul>
  83. </div>
  84. <div
  85. class="swiper-container"
  86. id="swSecondary"
  87. :style="`width:${secondaryW}px`"
  88. v-if="store.secondaryList.length > 1"
  89. >
  90. <ul class="swiper-wrapper">
  91. <li
  92. class="swiper-slide"
  93. @click="tabSecondary(item)"
  94. :class="{
  95. active: store.currentSecondary.id == item.id,
  96. loopspan:
  97. item.name.length > spanlength &&
  98. store.currentSecondary.id == item.id,
  99. }"
  100. v-for="(item, i) in store.secondaryList"
  101. :key="i"
  102. >
  103. <span v-if="store.currentSecondary.id == item.id">{{
  104. item.name
  105. }}</span>
  106. <span v-else>{{
  107. item.name.length > spanlength
  108. ? item.name.slice(0, spanlength)
  109. : item.name
  110. }}</span>
  111. </li>
  112. </ul>
  113. </div>
  114. </div>
  115. </div>
  116. </template>
  117. <script setup>
  118. import appStore from "@/store/index";
  119. import { ref, onMounted, computed, watch, nextTick } from "vue";
  120. import { useRoute } from "vue-router";
  121. const route = useRoute();
  122. const store = appStore();
  123. const spanlength = ref(5);
  124. const swidth = ref({
  125. swcatalogRoot: 130,
  126. swSecondary: 84,
  127. swScenes: 124,
  128. });
  129. const scenesListW = computed(
  130. () => store.currentScenesList.length * (swidth.value["swScenes"] + 10) - 10
  131. );
  132. const secondaryW = computed(
  133. () => store.secondaryList.length * (swidth.value["swSecondary"] + 10) - 10
  134. );
  135. const catalogRootW = computed(
  136. () =>
  137. store.metadata.catalogRoot.length * (swidth.value["swcatalogRoot"] + 10) -
  138. 10
  139. );
  140. const innerW = computed(() => 1150);
  141. const loadList = () => {
  142. nextTick(() => {
  143. let t = setTimeout(() => {
  144. clearTimeout(t);
  145. ["#swcatalogRoot", "#swSecondary", "#swScenes"].forEach((item) => {
  146. new Swiper(item, {
  147. slidesPerView: "auto",
  148. centeredSlides: true,
  149. spaceBetween: 10,
  150. centerInsufficientSlides: true,
  151. mousewheel: true,
  152. centeredSlidesBounds: true,
  153. freeMode: true,
  154. observer: true,
  155. observeParents: true,
  156. });
  157. });
  158. }, 100);
  159. });
  160. };
  161. const tabCurrentScene = (data) => {
  162. store.currentScene = data;
  163. route.params.id = data.sceneCode;
  164. };
  165. const tabSecondary = (data) => {
  166. store.setCurrentSecondary(data);
  167. };
  168. const tabRoot = (data) => {
  169. store.setCurrentCatalogRoot(data);
  170. setTimeout(() => {
  171. // 当前场景初始化为第一个
  172. store.setCurrentSceneFirst();
  173. }, 300);
  174. };
  175. // 向下离场
  176. const departure = () => {
  177. store.setListIsShow(false)
  178. };
  179. onMounted(() => {
  180. loadList();
  181. store.$subscribe((mutation, state) => {
  182. loadList();
  183. });
  184. });
  185. </script>
  186. <style lang="scss" scoped>
  187. $width: 100%;
  188. .bar-list-hidden {
  189. bottom: -200px !important;
  190. }
  191. .bar-list {
  192. position: absolute;
  193. bottom: 68px;
  194. left: 50%;
  195. transform: translateX(-50%);
  196. text-align: center;
  197. width: $width;
  198. overflow: hidden;
  199. transition: 0.3s all ease;
  200. z-index: 9999;
  201. // border-top: 2px solid #e1ceaa;
  202. // border-bottom: 2px solid #e1ceaa;
  203. background: linear-gradient(
  204. 89deg,
  205. rgba(141, 127, 100, 0) 0%,
  206. rgb(158 135 90 / 35%) 22%,
  207. rgba(141, 127, 100, 0.56) 80%,
  208. rgb(141 127 100 / 56%) 100%
  209. );
  210. backdrop-filter: blur(20px);
  211. padding: 10px;
  212. transition-property: bottom;
  213. transition-duration: 0.5s;
  214. pointer-events: all;
  215. box-shadow: inset 0px 2px 5px 0px rgba(255, 255, 255, 0.25);
  216. bottom: 0;
  217. .up-icon {
  218. position: absolute;
  219. top: -20px;
  220. z-index: 999;
  221. }
  222. .swiper-container {
  223. width: 100%;
  224. position: relative;
  225. // margin-top: 10px;
  226. > ul {
  227. > li {
  228. white-space: nowrap;
  229. > span,
  230. > div > span {
  231. cursor: pointer;
  232. display: inline-block;
  233. color: rgba(255, 255, 255);
  234. font-weight: bold;
  235. font-size: 14px;
  236. }
  237. &.loopspan {
  238. > span,
  239. > div > span {
  240. animation: 5s wordsLoop linear infinite normal;
  241. }
  242. }
  243. &.active {
  244. .area-text {
  245. color: rgba(255, 255, 255, 1) !important;
  246. font-weight: bold !important;
  247. }
  248. }
  249. .active-line {
  250. width: 80%;
  251. height: 4px;
  252. background-color: #e1ceaaad;
  253. position: absolute;
  254. bottom: 5px;
  255. left: 10px;
  256. }
  257. }
  258. }
  259. }
  260. .bottom-con {
  261. margin: 0px auto 0;
  262. padding: 10px;
  263. }
  264. #swcatalogRoot {
  265. .swiper-wrapper {
  266. transform: translate3d(0, 0px, 0px) !important;
  267. }
  268. > ul {
  269. > li {
  270. box-sizing: border-box;
  271. overflow: hidden;
  272. width: 90px;
  273. line-height: 30px;
  274. height: 30px;
  275. .area-text {
  276. width: 100%;
  277. word-break: keep-all;
  278. color: #ffffff;
  279. font-weight: 400;
  280. cursor: pointer;
  281. position: relative;
  282. font-size: 14px;
  283. }
  284. &.active {
  285. // border: 1px solid rgba(255, 255, 255, 1);
  286. }
  287. }
  288. }
  289. img {
  290. width: 35px;
  291. position: absolute;
  292. right: 20px;
  293. z-index: 999;
  294. top: -2px;
  295. cursor: pointer;
  296. }
  297. }
  298. #swSecondary {
  299. margin: 20px auto 10px;
  300. > ul {
  301. > li {
  302. width: 84px;
  303. box-sizing: border-box;
  304. overflow: hidden;
  305. padding-bottom: 6px;
  306. > span {
  307. width: 100%;
  308. word-break: keep-all;
  309. }
  310. &.active {
  311. position: relative;
  312. &::before {
  313. content: "";
  314. display: inline-block;
  315. position: absolute;
  316. bottom: 0;
  317. width: 20px;
  318. height: 2px;
  319. z-index: 9999;
  320. left: 50%;
  321. transform: translateX(-50%);
  322. background: var(--colors-primary-base);
  323. }
  324. }
  325. }
  326. }
  327. }
  328. #swScenes {
  329. > ul {
  330. > li {
  331. cursor: pointer;
  332. border-radius: 6px;
  333. border: 2px solid transparent;
  334. border-right: 0;
  335. background-size: cover;
  336. position: relative;
  337. overflow: hidden;
  338. width: 124px;
  339. height: 90px;
  340. border-radius: 1px;
  341. &::after {
  342. position: absolute;
  343. top: 0;
  344. left: 0;
  345. bottom: 0;
  346. width: 100%;
  347. height: 100%;
  348. display: inline-block;
  349. background: rgba(0, 0, 0, 0.5);
  350. content: "";
  351. pointer-events: none;
  352. }
  353. > div {
  354. position: absolute;
  355. top: 50%;
  356. transform: translate(-50%, -50%);
  357. left: 50%;
  358. height: 20px;
  359. width: 100%;
  360. overflow: hidden;
  361. z-index: 999;
  362. > span {
  363. width: 100%;
  364. line-height: 20px;
  365. word-break: keep-all;
  366. }
  367. }
  368. &.active {
  369. border: 2px solid #d9c7a4;
  370. &::after {
  371. position: absolute;
  372. top: 0;
  373. left: 0;
  374. bottom: 0;
  375. width: 100%;
  376. height: 100%;
  377. display: inline-block;
  378. background: linear-gradient(
  379. to top,
  380. rgb(0 0 0 / 59%),
  381. rgba(255, 0, 0, 0)
  382. );
  383. content: "";
  384. pointer-events: none;
  385. }
  386. > div {
  387. top: auto;
  388. bottom: 10px;
  389. transform: translate(0, 0);
  390. left: 0;
  391. > span {
  392. }
  393. }
  394. }
  395. }
  396. }
  397. }
  398. }
  399. .barshow {
  400. max-height: 190px;
  401. }
  402. @keyframes wordsLoop {
  403. 0% {
  404. transform: translateX(100%);
  405. -webkit-transform: translateX(100%);
  406. }
  407. 100% {
  408. transform: translateX(-100%);
  409. -webkit-transform: translateX(-100%);
  410. }
  411. }
  412. </style>