index.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486
  1. <script setup lang="ts">
  2. import ModelList, { baseURL } from "@/assets/data/Model/index";
  3. import { ModelType } from "@/types/Model/index";
  4. import getNumNoRepeat from "@/utils/tool";
  5. import restaurantList, { hotelList } from "@/assets/data/recommend/index";
  6. import Swiper from "swiper";
  7. import "swiper/swiper-bundle.css";
  8. import { nextTick } from "vue";
  9. const currentScene = ref({} as ModelType);
  10. const route = useRoute();
  11. const router = useRouter();
  12. const isShow = ref(false);
  13. const goVr = (code: string) => {
  14. console.log(code);
  15. router.push({
  16. path: "/bldgMap/detail/scene",
  17. query: {
  18. code: code,
  19. },
  20. });
  21. };
  22. // 美食的两个随机推荐
  23. const recommendFoods = ref([]);
  24. // 酒店的两个随机推荐
  25. const recommendHotels = ref([]);
  26. const lastY = ref(0);
  27. const bottomHeight = ref("50%");
  28. // 手指滑动
  29. const touchMove = (event: any) => {
  30. // 左右切换为 X 即可
  31. let currentY = event.changedTouches[0].pageY;
  32. let ty = currentY - lastY.value;
  33. if (ty < -20) {
  34. bottomHeight.value = 97 + "%";
  35. return;
  36. } else if (ty > 20) {
  37. bottomHeight.value = 50 + "%";
  38. return;
  39. }
  40. };
  41. // 开始滑动
  42. const handletouchstart = (event: any) => {
  43. lastY.value = event.changedTouches[0].pageY;
  44. };
  45. // 当前轮播下标
  46. const swiperActiveIndex = ref(0);
  47. const itRecommend = () => {
  48. // 产生推荐的随机数
  49. let recommendFoodIndexs = getNumNoRepeat(
  50. currentScene.value.recommend.food.length - 1,
  51. 2
  52. );
  53. const recommendHotelIndexs = getNumNoRepeat(
  54. currentScene.value.recommend.hotel.length - 1,
  55. 2
  56. );
  57. console.log(typeof recommendFoodIndexs);
  58. if (recommendFoodIndexs && recommendHotelIndexs) {
  59. // 获取推荐信息——美食
  60. recommendFoodIndexs.forEach((index: number) => {
  61. const res = restaurantList.find((item: any) => {
  62. return item.id == currentScene.value.recommend.food[index];
  63. });
  64. recommendFoods.value.push(res);
  65. });
  66. // 获取推荐信息——酒店
  67. recommendHotelIndexs.forEach((index: number) => {
  68. const res = hotelList.find((item: any) => {
  69. return item.id == currentScene.value.recommend.hotel[index];
  70. });
  71. recommendHotels.value.push(res);
  72. });
  73. }
  74. console.log(recommendFoods.value, recommendHotels.value);
  75. };
  76. onMounted(async () => {
  77. await nextTick(() => {
  78. currentScene.value = ModelList.find((item: ModelType) => {
  79. return item.code === route.query.code;
  80. });
  81. itRecommend();
  82. });
  83. var swiper = new Swiper(".mySwiper", {
  84. pagination: {
  85. el: ".swiper-pagination",
  86. },
  87. on: {
  88. slideChange: function (swiper: any) {
  89. nextTick(() => {
  90. const index = swiper.activeIndex;
  91. swiperActiveIndex.value = index;
  92. });
  93. },
  94. },
  95. });
  96. });
  97. </script>
  98. <template>
  99. <div class="detail">
  100. <div class="top">
  101. <!-- <img
  102. src="/public/image/swiperImage/天主堂/DJI_0312.JPG"
  103. alt=""
  104. /> -->
  105. <div class="swiper mySwiper">
  106. <div class="swiper-wrapper">
  107. <div
  108. class="swiper-slide"
  109. v-for="(item, index) in currentScene.swiperImage"
  110. :key="index"
  111. >
  112. <img :src="item" alt="" />
  113. </div>
  114. </div>
  115. <div class="swiper-pagination" slot="pagination"></div>
  116. </div>
  117. <div
  118. class="viewBig"
  119. @click="
  120. () => {
  121. isShow = true;
  122. }
  123. "
  124. >
  125. <div>查看</div>
  126. <div>大图</div>
  127. </div>
  128. </div>
  129. <div
  130. class="bottom"
  131. :style="{
  132. height: bottomHeight,
  133. overflow: bottomHeight === '97%' ? 'auto' : '',
  134. }"
  135. >
  136. <div
  137. class="bottom-top"
  138. @touchmove="touchMove"
  139. @touchstart="handletouchstart"
  140. >
  141. <div class="bottom-line"></div>
  142. </div>
  143. <div
  144. class="bottom-name"
  145. @touchmove="touchMove"
  146. @touchstart="handletouchstart"
  147. >
  148. <!-- 拼音 -->
  149. <div class="bottom-name-pinyin">{{ currentScene.pinyin }}</div>
  150. <!-- 汉字 -->
  151. <div class="bottom-name-name">
  152. {{ currentScene.name }}
  153. <div
  154. class="bg"
  155. v-if="Object.keys(currentScene).length > 0"
  156. :style="{ width: currentScene.name.length * 1.5 + 'rem' }"
  157. ></div>
  158. </div>
  159. </div>
  160. <div class="bottom-other">
  161. <div class="adress">{{ "地址:" + currentScene.adress }}</div>
  162. <div class="rank">{{ "级别:" + currentScene.rank }}</div>
  163. <div class="openTime">{{ "开放时间:" + currentScene.openTime }}</div>
  164. <div class="ticketInfo">{{ "门票:" + currentScene.ticketInfo }}</div>
  165. </div>
  166. <div class="bottom-disc">
  167. {{ "简介:" + currentScene.disc }}
  168. </div>
  169. <div class="bottom-recommend">
  170. <div class="bottom-recommend-top">周边推荐</div>
  171. <div class="bottom-recommend-content">
  172. <!-- 食物 -->
  173. <div class="content-item">
  174. <div
  175. class="item"
  176. v-for="(item, index) in recommendFoods"
  177. :key="item.id"
  178. >
  179. <img
  180. :src="baseURL + '/image/service/food/' + item.coverName"
  181. alt=""
  182. />
  183. <div>{{ item.name }}</div>
  184. </div>
  185. </div>
  186. <!-- 酒店 -->
  187. <div class="content-item">
  188. <!-- <div class="item">
  189. <img src="@/assets/img/map/recommend/1/hotel/2(1).jpg" alt="" />
  190. <div>MS美宿艺术品酒店</div>
  191. </div>
  192. <div class="item">
  193. <img src="@/assets/img/map/recommend/1/hotel/3(1).jpg" alt="" />
  194. <div>芜湖奇士商务酒店</div>
  195. </div> -->
  196. <div
  197. class="item"
  198. v-for="(item, index) in recommendHotels"
  199. :key="item.id"
  200. >
  201. <img
  202. :src="baseURL + '/image/service/hotel/' + item.coverImg"
  203. alt=""
  204. />
  205. <div>{{ item.name }}</div>
  206. </div>
  207. </div>
  208. </div>
  209. </div>
  210. </div>
  211. <img
  212. v-if="currentScene.sceneId != ''"
  213. class="go-vr"
  214. src="@/assets/img/map/goVr.png"
  215. alt=""
  216. @click="goVr(currentScene.sceneId)"
  217. />
  218. <div class="big-img-box" v-if="isShow">
  219. <div class="img-box">
  220. <img
  221. class="content-img"
  222. :src="currentScene.swiperImage[swiperActiveIndex]"
  223. alt=""
  224. />
  225. <img
  226. class="close-icon"
  227. src="@/assets/img/map/close.png"
  228. alt=""
  229. @click="
  230. () => {
  231. isShow = false;
  232. }
  233. "
  234. />
  235. </div>
  236. </div>
  237. </div>
  238. </template>
  239. <style lang="less" scoped>
  240. .detail {
  241. max-width: 100%;
  242. max-height: 100%;
  243. overflow: hidden;
  244. .top {
  245. width: 100%;
  246. height: 50vh;
  247. .swiper {
  248. width: 100%;
  249. height: 100%;
  250. }
  251. .swiper-slide {
  252. text-align: center;
  253. font-size: 18px;
  254. background: #fff;
  255. /* Center slide text vertically */
  256. display: -webkit-box;
  257. display: -ms-flexbox;
  258. display: -webkit-flex;
  259. display: flex;
  260. -webkit-box-pack: center;
  261. -ms-flex-pack: center;
  262. -webkit-justify-content: center;
  263. justify-content: center;
  264. -webkit-box-align: center;
  265. -ms-flex-align: center;
  266. -webkit-align-items: center;
  267. align-items: center;
  268. }
  269. .swiper-slide img {
  270. display: block;
  271. width: 100%;
  272. height: 100%;
  273. object-fit: cover;
  274. }
  275. img {
  276. width: 100%;
  277. height: 50vh;
  278. object-fit: cover;
  279. }
  280. .viewBig {
  281. position: absolute;
  282. border-radius: 50%;
  283. width: 18vw;
  284. height: 18vw;
  285. border: 1px solid white;
  286. background: #515151;
  287. font-size: 1.1rem;
  288. display: flex;
  289. flex-direction: column;
  290. justify-content: center;
  291. align-items: center;
  292. line-height: 110%;
  293. letter-spacing: 2px;
  294. color: white;
  295. top: 33vh;
  296. right: 5vw;
  297. z-index: 2;
  298. }
  299. }
  300. .bottom {
  301. width: 100%;
  302. background: var(--color-bg);
  303. position: absolute;
  304. bottom: 0;
  305. border-radius: 20px;
  306. padding: 15px 20px 12vh 20px;
  307. box-sizing: border-box;
  308. overflow: hidden;
  309. z-index: 2;
  310. // overflow: auto;
  311. transition-property: height;
  312. transition-duration: 0.2s;
  313. transition-timing-function: ease-in;
  314. transition-delay: 0.2s;
  315. .bottom-top {
  316. width: 100%;
  317. height: 10px;
  318. background: rgba(0, 128, 0, 0);
  319. display: flex;
  320. justify-content: center;
  321. .bottom-line {
  322. width: 25%;
  323. height: 5px;
  324. background: #867858;
  325. border-radius: 50px;
  326. margin: auto;
  327. }
  328. }
  329. &-name {
  330. overflow: auto;
  331. width: auto;
  332. margin-top: 10px;
  333. margin-bottom: 5px;
  334. &-pinyin {
  335. font-size: 0.6rem;
  336. width: inherit;
  337. }
  338. &-name {
  339. width: inherit;
  340. font-size: 1.3rem;
  341. /* letter-spacing: 0.1rem; */
  342. margin-left: 2px;
  343. position: relative;
  344. font-weight: bold;
  345. position: relative;
  346. z-index: 2;
  347. }
  348. .bg {
  349. height: 2vh;
  350. position: absolute;
  351. bottom: 0;
  352. background: #ede0c3;
  353. z-index: -1;
  354. }
  355. }
  356. &-other {
  357. font-size: 0.85rem;
  358. font-weight: bold;
  359. color: #665e4a;
  360. div {
  361. margin-top: 10px;
  362. letter-spacing: 2px;
  363. }
  364. div:before {
  365. content: "●";
  366. margin-right: 5px;
  367. color: #666;
  368. }
  369. }
  370. &-disc {
  371. font-size: 0.8rem;
  372. color: #918a6f;
  373. line-height: 1.2rem;
  374. letter-spacing: 2px;
  375. font-weight: bold;
  376. margin-top: 15px;
  377. }
  378. .ellipsis {
  379. width: 100%;
  380. word-break: break-all;
  381. text-overflow: ellipsis;
  382. overflow: hidden;
  383. display: -webkit-box;
  384. -webkit-box-orient: vertical;
  385. -webkit-line-clamp: 4;
  386. letter-spacing: 2px;
  387. }
  388. .bottom-recommend {
  389. &-top {
  390. width: 100%;
  391. font-size: 1.4rem;
  392. color: #665e4a;
  393. font-weight: bold;
  394. margin-top: 20px;
  395. }
  396. &-content {
  397. width: 100%;
  398. margin-top: 10px;
  399. .content-item {
  400. width: 100%;
  401. display: flex;
  402. justify-content: space-around;
  403. .item {
  404. width: 43%;
  405. height: 20vh;
  406. img {
  407. width: 100%;
  408. height: 80%;
  409. object-fit: cover;
  410. }
  411. div {
  412. width: 100%;
  413. font-size: 0.8rem;
  414. color: #665e4a;
  415. font-weight: bold;
  416. margin-top: -6px;
  417. text-overflow: ellipsis;
  418. overflow: hidden;
  419. white-space: nowrap;
  420. margin-top: 0px;
  421. }
  422. }
  423. }
  424. }
  425. }
  426. }
  427. .go-vr {
  428. width: 60%;
  429. height: 50px;
  430. margin: auto;
  431. position: absolute;
  432. left: 50%;
  433. bottom: 20px;
  434. transform: translateX(-50%);
  435. z-index: 3;
  436. }
  437. .big-img-box {
  438. position: absolute;
  439. z-index: 3;
  440. width: 100%;
  441. height: 100%;
  442. top: 0;
  443. left: 0;
  444. background: #666666db;
  445. .img-box {
  446. position: absolute;
  447. width: 80%;
  448. left: 50%;
  449. top: 50%;
  450. transform: translate(-50%, -50%);
  451. display: flex;
  452. flex-direction: column;
  453. align-items: center;
  454. .content-img {
  455. width: 100%;
  456. }
  457. .close-icon {
  458. width: 10%;
  459. margin: auto;
  460. margin-top: 10px;
  461. }
  462. }
  463. }
  464. }
  465. </style>