Main.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  1. <template>
  2. <Panel v-show="player.showWidgets" :isOpen="isOpen">
  3. <div @click="toggleOpen" class="menu color">
  4. <div class="logo">
  5. <img :src="require('@/assets/images/icon/logo.png')" alt="" />
  6. <p>cdf澳門上葡京店</p>
  7. </div>
  8. <div class="vline"></div>
  9. <ul>
  10. <li v-if="tours.length > 0">
  11. <ui-icon type="preview" @click.stop="playTour"></ui-icon>
  12. <div>導覽</div>
  13. </li>
  14. <li @click.stop="onClickMenu(item)" v-for="(item, i) in menulist" :key="i">
  15. <ui-icon :type="item.icon"></ui-icon>
  16. <div>{{ item.name }}</div>
  17. </li>
  18. <li v-if="showdaogou">
  19. <ui-icon
  20. type="guided_shopping"
  21. @click.stop="
  22. onClickMenu({
  23. icon: 'guided_shopping',
  24. id: 'guided_shopping',
  25. name: '導購',
  26. })
  27. "
  28. ></ui-icon>
  29. <div>導購</div>
  30. </li>
  31. <li>
  32. <ui-icon
  33. type="shopping"
  34. @click.stop="
  35. onClickMenu({
  36. icon: 'shopping',
  37. id: 'shopping',
  38. name: '購物',
  39. })
  40. "
  41. ></ui-icon>
  42. <div>購物</div>
  43. </li>
  44. </ul>
  45. </div>
  46. <div class="toolbar color">
  47. <div class="navigation">
  48. <div class="h3">專櫃導航</div>
  49. <div class="swiper-container" id="sw-navigation">
  50. <ul class="swiper-wrapper">
  51. <li
  52. class="swiper-slide"
  53. :class="{ liactive: item.sceneUrl === currentM && item.inPosition.indexOf(currentPose) > -1 }"
  54. @click.stop="onClickShop(item)"
  55. v-for="(item, i) in brandlist"
  56. :key="i"
  57. >
  58. <div v-if="item.shopLogo" class="img" :style="{ 'background-image': `url(${item.shopLogo})` }"></div>
  59. <div class="name" v-if="item.shopName">
  60. <span :class="{ active: item.shopName.length > 6 }">
  61. {{ item.shopName }}
  62. </span>
  63. </div>
  64. </li>
  65. </ul>
  66. </div>
  67. </div>
  68. <div class="category">
  69. <div class="swiper-container" id="sw-category">
  70. <ul class="swiper-wrapper">
  71. <li
  72. class="swiper-slide"
  73. :class="{ categoryactive: '' == currentCategory.id }"
  74. @click.stop="
  75. onClickCategory({
  76. id: '',
  77. categoryName: '全部',
  78. })
  79. "
  80. >
  81. <div>全部</div>
  82. </li>
  83. <li
  84. @click.stop="onClickCategory(item)"
  85. :class="{ categoryactive: item.id == currentCategory.id }"
  86. class="swiper-slide"
  87. v-for="(item, i) in categorylist"
  88. :key="i"
  89. >
  90. <div>{{ item.categoryName }}</div>
  91. </li>
  92. </ul>
  93. </div>
  94. </div>
  95. </div>
  96. </Panel>
  97. </template>
  98. <script setup>
  99. import { useStore } from "vuex";
  100. import { onMounted, watch, computed, ref, nextTick } from "vue";
  101. import Panel from "@/views/Panel.vue";
  102. import { useApp, getApp } from "@/app";
  103. import * as apis from "@/apis/index.js";
  104. import browser from "@/utils/browser";
  105. const store = useStore();
  106. const isOpen = ref(false);
  107. const toggleOpen = () => {
  108. isOpen.value = !isOpen.value;
  109. };
  110. const currentCategory = ref({
  111. id: "",
  112. categoryName: "全部",
  113. });
  114. const currentM = computed(() => browser.getURLParam("m"));
  115. const currentPose = computed(() => browser.getURLParam("pose"));
  116. const showdaogou = computed(() => store.getters["rtc/showdaogou"]);
  117. const isPlay = computed(() => {
  118. let status = store.getters["tour/isPlay"];
  119. let map = document.querySelector(".kankan-app div[xui_min_map]");
  120. if (map) {
  121. if (status) {
  122. map.classList.add("disabled");
  123. } else {
  124. map.classList.remove("disabled");
  125. }
  126. }
  127. return status;
  128. });
  129. const partId = computed(() => store.getters["tour/partId"]);
  130. const playTour = async () => {
  131. let player = await getApp().TourManager.player;
  132. if (isPlay.value) {
  133. store.commit("tour/setData", { isPlay: true });
  134. player.pause();
  135. } else {
  136. store.commit("tour/setData", { isPlay: true });
  137. player.play(partId.value);
  138. }
  139. };
  140. const metadata = computed(() => store.getters["scene/metadata"]);
  141. const player = computed(() => store.getters["player"]);
  142. const tours = computed(() => store.getters["tour/tours"]);
  143. const menulist = computed(() => {
  144. let fff = [
  145. {
  146. icon: "help",
  147. id: "help",
  148. name: "幫助",
  149. },
  150. {
  151. icon: "customer_service",
  152. id: "kefu",
  153. name: "客服",
  154. },
  155. ];
  156. if (!browser.isMobile()) {
  157. fff.shift();
  158. }
  159. return fff;
  160. });
  161. const categorylist = ref([]);
  162. const brandlist = ref([]);
  163. const brandScroll = () => {
  164. nextTick(() => {
  165. let t = setTimeout(() => {
  166. clearTimeout(t);
  167. new Swiper("#sw-navigation", {
  168. freeMode: true,
  169. slidesPerView: "auto",
  170. centeredSlides: false,
  171. spaceBetween: 10,
  172. grid: {
  173. rows: 2,
  174. },
  175. on: {
  176. touchMove(swiper, e) {
  177. e.stopPropagation();
  178. e.preventDefault();
  179. },
  180. },
  181. });
  182. new Swiper("#sw-category", {
  183. freeMode: true,
  184. slidesPerView: "auto",
  185. spaceBetween: 10,
  186. on: {
  187. touchMove(swiper, e) {
  188. e.stopPropagation();
  189. e.preventDefault();
  190. },
  191. },
  192. });
  193. }, 100);
  194. });
  195. };
  196. const onClickMenu = (item) => {
  197. if (item.id == "kefu") {
  198. let mglink =
  199. "https://webpage.qidian.qq.com/2/chat/h5/index.html?linkType=1&env=ol&kfuin=3009110132&fid=3655&key=9b4334768c39150ead3f23e11e5dc2e4&cate=7&source=0&isLBS=0&isCustomEntry=0&type=10&ftype=1&_type=wpa&qidian=true&_pid=kvrmvu.74cg11.l43qvbcu&translateSwitch=0&isSsc=0&roleValue=4&roleData=922223821";
  200. window.open(mglink, "_blank");
  201. } else if (item.id == "shopping") {
  202. browser.openLink(
  203. "/subPackage/pages/shoppingcart/shoppingcart",
  204. "https://m.cdfmembers.com/shop/600667208/shoppingcart",
  205. "/subPackage/pages/shoppingcart/shoppingcart"
  206. );
  207. } else if (item.id == "help") {
  208. store.commit("showUserGuide", true);
  209. } else if (item.id == "guided_shopping") {
  210. store.commit("showShoppingguide", true);
  211. }
  212. };
  213. const getCategorylist = async () => {
  214. let res = await apis.get_category_list({});
  215. categorylist.value = res.data;
  216. brandScroll();
  217. };
  218. const onClickCategory = (item) => {
  219. currentCategory.value.id = item.id;
  220. currentCategory.value.categoryName = item.categoryName;
  221. };
  222. const onClickShop = (item) => {
  223. let url = window.location.href;
  224. if (!browser.hasURLParam("pose")) {
  225. url += `&${item.inPosition}`;
  226. } else {
  227. url = browser.replaceQueryString(url, "pose", item.inPosition.replace("pose=", ""));
  228. }
  229. url = browser.replaceQueryString(url, "m", item.sceneUrl);
  230. window.location.href = url;
  231. };
  232. watch(
  233. () => currentCategory,
  234. (val, old) => {
  235. getShoplist();
  236. },
  237. {
  238. deep: true,
  239. }
  240. );
  241. const getShoplist = async () => {
  242. let res = await apis.get_shop_list({
  243. categoryId: currentCategory.value.id,
  244. });
  245. brandlist.value = res.data;
  246. brandScroll();
  247. };
  248. onMounted(() => {
  249. useApp().then((app) => {
  250. getCategorylist();
  251. getShoplist();
  252. });
  253. });
  254. </script>
  255. <style lang="scss" scoped>
  256. .menu {
  257. width: 100%;
  258. border-radius: 6px;
  259. border: 1px solid rgba(255, 255, 255, 0.2);
  260. background: rgba(0, 0, 0, 0.2);
  261. display: flex;
  262. justify-content: space-between;
  263. box-sizing: border-box;
  264. position: relative;
  265. align-items: center;
  266. height: 48px;
  267. padding: 0 12px;
  268. text-align: center;
  269. .logo {
  270. width: 90px;
  271. transform: translateY(-24%);
  272. > img {
  273. width: 100%;
  274. border-radius: 4px;
  275. }
  276. > p {
  277. margin: 2px 0;
  278. font-size: 10px;
  279. }
  280. }
  281. .vline {
  282. width: 1px;
  283. height: 14px;
  284. background: #fff;
  285. }
  286. > ul {
  287. display: flex;
  288. align-items: center;
  289. font-size: 0;
  290. justify-content: flex-end;
  291. > li {
  292. margin-left: 0.5rem;
  293. &:first-of-type {
  294. margin-left: 0;
  295. }
  296. > div {
  297. margin-top: 4px;
  298. font-size: 10px;
  299. }
  300. }
  301. }
  302. }
  303. .toolbar {
  304. width: 100%;
  305. border-radius: 6px;
  306. border: 1px solid rgba(255, 255, 255, 0.2);
  307. margin-top: 8px;
  308. margin-bottom: 30px;
  309. background: rgba(0, 0, 0, 0.2);
  310. .navigation {
  311. padding: 8px 0;
  312. .h3 {
  313. font-size: 14px;
  314. padding: 0 14px;
  315. }
  316. .swiper-container {
  317. width: 100%;
  318. height: 130px;
  319. overflow: hidden;
  320. margin-top: 8px;
  321. padding-right: 2px;
  322. padding-left: 14px;
  323. position: relative;
  324. &::after {
  325. position: absolute;
  326. right: 0;
  327. bottom: 0;
  328. content: "";
  329. display: inline-block;
  330. height: 100%;
  331. z-index: 99;
  332. width: 17px;
  333. background: linear-gradient(90deg, rgba(0, 0, 0, 0) 0%, #000000 100%);
  334. opacity: 0.4;
  335. pointer-events: none;
  336. }
  337. > ul {
  338. margin: 0 !important;
  339. > li {
  340. width: 60px;
  341. height: 60px;
  342. border-radius: 4px;
  343. position: relative;
  344. font-size: 0;
  345. overflow: hidden;
  346. border: 1px transparent solid;
  347. box-sizing: border-box;
  348. &.liactive {
  349. color: var(--editor-main-color);
  350. border: 1px var(--editor-main-color) solid;
  351. }
  352. .img {
  353. width: 100%;
  354. height: 100%;
  355. background-size: contain;
  356. }
  357. .name {
  358. width: 100%;
  359. position: absolute;
  360. bottom: -1px;
  361. font-size: 12px;
  362. left: 0;
  363. background: rgba(0, 0, 0, 0.5);
  364. // text-overflow: ellipsis;
  365. // white-space: nowrap;
  366. // overflow: hidden;
  367. text-align: center;
  368. padding: 2px 4px;
  369. box-sizing: border-box;
  370. word-break: break-all;
  371. > span {
  372. display: inline-block;
  373. white-space: nowrap;
  374. }
  375. .active {
  376. animation: 5s wordsLoop linear infinite normal;
  377. }
  378. }
  379. }
  380. }
  381. }
  382. }
  383. .category {
  384. padding: 8px 14px;
  385. border-top: 1px solid rgba(255, 255, 255, 0.2);
  386. .swiper-container {
  387. width: 100%;
  388. overflow: hidden;
  389. > ul {
  390. > li {
  391. width: auto;
  392. color: rgba(255, 255, 255, 0.5);
  393. > div {
  394. width: 100%;
  395. font-size: 14px;
  396. padding: 2px 4px;
  397. }
  398. }
  399. .categoryactive {
  400. color: #fff;
  401. }
  402. }
  403. }
  404. }
  405. }
  406. @keyframes wordsLoop {
  407. 0% {
  408. transform: translateX(100%);
  409. -webkit-transform: translateX(100%);
  410. }
  411. 100% {
  412. transform: translateX(-100%);
  413. -webkit-transform: translateX(-100%);
  414. }
  415. }
  416. </style>