list.vue 10 KB

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