index.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611
  1. <script setup lang="ts">
  2. import { ref, watch } from 'vue'
  3. import selectTime from '../components/choose-time.vue'
  4. import { timeFormat } from '../utils/index'
  5. import { StaticUrl } from '@/config'
  6. interface brand {
  7. id: number
  8. brandId: string
  9. brandName: string
  10. }
  11. const router = useRouter()
  12. definePage({
  13. name: 'film-choose-film',
  14. islogin: false,
  15. style: {
  16. navigationStyle: 'custom',
  17. navigationBarTitleText: '我的订单',
  18. backgroundColorBottom: '#fff',
  19. },
  20. })
  21. onLoad((options) => {
  22. console.log('onload', options)
  23. })
  24. const addressStore = useAddressStore()
  25. const { Location } = storeToRefs(addressStore)
  26. const query = ref({
  27. cityId: '103',
  28. showDates: timeFormat(new Date().getTime(), 'yyyy-MM-dd'),
  29. lat: Location.value.latitude,
  30. lng: Location.value.longitude,
  31. districtId: '',
  32. brandId: '',
  33. hall: '',
  34. movieId: '',
  35. })
  36. // const tab = ref(timeFormat(new Date().getTime(), 'yyyy-mm-dd'))
  37. const dayList = ref([])
  38. const active = ref<number | null>(null)
  39. const filmList = ref<Api.filmList[]>([])
  40. const cityList = ref<Api.filmCityList>([])
  41. const brandList = ref<brand[]>()
  42. const currentCity = ref(0)
  43. const show = ref(false)
  44. const info = ref<Api.filmMovieList>({})
  45. watch(() => show.value, (val) => {
  46. if (!val) {
  47. active.value = null
  48. }
  49. })
  50. function handleChoose(index: number) {
  51. show.value = true
  52. active.value = index
  53. }
  54. function close() {
  55. show.value = false
  56. }
  57. function choose(cityId: string, index?: number, districtId?: string) {
  58. if (active.value === 0) {
  59. query.value.cityId = cityId
  60. query.value.districtId = districtId || ''
  61. if (index) {
  62. currentCity.value = index
  63. }
  64. }
  65. else if (active.value === 1) {
  66. query.value.brandId = cityId
  67. }
  68. // else if (active.value === 2) {
  69. // }
  70. show.value = false
  71. getData()
  72. }
  73. function handleFilm(title: string = '保利万和学府影城', cinemaId: string) {
  74. console.log(title)
  75. router.push({
  76. name: 'film-select-time',
  77. params: {
  78. cinemaId,
  79. movieId: query.value.movieId,
  80. title,
  81. time: query.value.showDates,
  82. },
  83. })
  84. }
  85. async function getData() {
  86. uni.showLoading({ title: '加载中' })
  87. console.log('qingind', query.value)
  88. const res = await Apis.film.getFilmList({ data: query.value })
  89. uni.hideLoading()
  90. if (res.data) {
  91. filmList.value = res.data
  92. }
  93. }
  94. async function getDate(movieId: string) {
  95. const res = await Apis.film.getFilmDateList({ data: { movieId } })
  96. dayList.value = res.data
  97. }
  98. function changeTime() {
  99. getData()
  100. }
  101. async function getCityList() {
  102. const res = await Apis.film.getCityList({})
  103. cityList.value = res.data
  104. res.data.forEach((item: any, index: number) => {
  105. if (item.name.includes('贵阳')) {
  106. currentCity.value = index
  107. }
  108. })
  109. }
  110. getCityList()
  111. async function getFilmBrandList() {
  112. const res = await Apis.film.getFilmBrandList({})
  113. brandList.value = res.data
  114. }
  115. getFilmBrandList()
  116. onLoad((options) => {
  117. query.value.movieId = options?.movieId
  118. info.value = JSON.parse(options?.info)
  119. getDate(options?.movieId)
  120. getData()
  121. })
  122. </script>
  123. <template>
  124. <view class="choose-film">
  125. <wd-navbar
  126. title="" custom-style="background-color: transparent;" :bordered="false" :z-index="99"
  127. safe-area-inset-top left-arrow fixed @click-left="router.back()"
  128. />
  129. <view class="bg-box">
  130. <image class="img" :src="info.posterUrl" mode="scaleToFill" />
  131. </view>
  132. <view class="info-box">
  133. <view class="info">
  134. <image class="icon" :src="info.posterUrl" />
  135. <view class="box">
  136. <view class="name">
  137. {{ info.name }}
  138. </view>
  139. <view class="score-box">
  140. <view class="score">
  141. 评分 <view class="num">
  142. {{ info.score }}
  143. </view>
  144. </view>
  145. <view class="want-num">
  146. {{ info.wish }}人想看
  147. </view>
  148. </view>
  149. <view class="type-box">
  150. {{ info.category }}
  151. <view class="tag">
  152. {{ info.version }}
  153. </view>
  154. </view>
  155. <view class="publish-info">
  156. 时长: {{ info.duration }}分钟
  157. </view>
  158. <view class="publish-info">
  159. 上映:{{ info.releaseTime }}
  160. </view>
  161. <view class="publish-info">
  162. 导演:{{ info.director }}
  163. </view>
  164. <view class="publish-info">
  165. 演员:{{ info.star }}
  166. </view>
  167. </view>
  168. </view>
  169. </view>
  170. <view class="px-24rpx">
  171. <!-- 影院时间 -->
  172. <selectTime v-model="query.showDates" :data="dayList" @change="changeTime" />
  173. <view class="choose-list">
  174. <view class="choose-item" :class="[active == 0 ? 'active' : '']" @click="handleChoose(0)">
  175. <view class="choose-item-title">
  176. 全城
  177. </view>
  178. <image
  179. class="icon" :src="StaticUrl + (active == 0 ? '/film-choose-active.png' : '/film-choose.png')"
  180. mode="scaleToFill"
  181. />
  182. </view>
  183. <view class="choose-item" :class="[active == 1 ? 'active' : '']" @click="handleChoose(1)">
  184. <view class="choose-item-title">
  185. 品牌
  186. </view>
  187. <image
  188. class="icon" :src="StaticUrl + (active == 1 ? '/film-choose-active.png' : '/film-choose.png')"
  189. mode="scaleToFill"
  190. />
  191. </view>
  192. <view class="choose-item" :class="[active == 2 ? 'active' : '']" @click="handleChoose(2)">
  193. <view class="choose-item-title">
  194. 特色
  195. </view>
  196. <image
  197. class="icon" :src="StaticUrl + (active == 2 ? '/film-choose-active.png' : '/film-choose.png')"
  198. mode="scaleToFill"
  199. />
  200. </view>
  201. </view>
  202. </view>
  203. <view class="film-list">
  204. <view
  205. v-for="(item, index) in filmList" :key="index" class="film-item"
  206. @click="handleFilm(item.name, item.cinemaId)"
  207. >
  208. <view class="name-box">
  209. <view class="name w-450rpx overflow-hidden text-ellipsis whitespace-nowrap">
  210. {{ item.name }}
  211. </view>
  212. <view class="price-box">
  213. <view class="num">
  214. ¥{{ item.sellPrice }}
  215. </view>
  216. <div class="label">
  217. </div>
  218. </view>
  219. </view>
  220. <view class="address-box">
  221. <view class="address overflow-hidden text-ellipsis whitespace-nowrap">
  222. {{ item.address }}
  223. </view>
  224. <view class="distance">
  225. {{ item.distance }}km
  226. </view>
  227. </view>
  228. <div class="cantact">
  229. {{ item.phone || '暂无联系方式' }}
  230. </div>
  231. <div class="time-box">
  232. 近期场次:{{ item.showInfo }}
  233. </div>
  234. </view>
  235. </view>
  236. <wd-loadmore state="finished" :loading-props="{ color: '#9ED605', size: 20 }" />
  237. <!-- 弹窗 -->
  238. <wd-action-sheet v-if="show" v-model="show" @close="close">
  239. <view class="content">
  240. <!-- 影院时间 -->
  241. <selectTime v-model="query.showDates" :data="dayList" @change="changeTime" />
  242. <view class="choose-list">
  243. <view class="choose-item" :class="[active == 0 ? 'active' : '']" @click="handleChoose(0)">
  244. <view class="choose-item-title">
  245. 全城
  246. </view>
  247. <image
  248. class="icon" :src="StaticUrl + (active == 0 ? '/film-choose-active.png' : '/film-choose.png')"
  249. mode="scaleToFill"
  250. />
  251. </view>
  252. <view class="choose-item" :class="[active == 1 ? 'active' : '']" @click="handleChoose(1)">
  253. <view class="choose-item-title">
  254. 品牌
  255. </view>
  256. <image
  257. class="icon" :src="StaticUrl + (active == 1 ? '/film-choose-active.png' : '/film-choose.png')"
  258. mode="scaleToFill"
  259. />
  260. </view>
  261. <view class="choose-item" :class="[active == 2 ? 'active' : '']" @click="handleChoose(2)">
  262. <view class="choose-item-title">
  263. 特色
  264. </view>
  265. <image
  266. class="icon" :src="StaticUrl + (active == 2 ? '/film-choose-active.png' : '/film-choose.png')"
  267. mode="scaleToFill"
  268. />
  269. </view>
  270. </view>
  271. <view v-if="active == 0" class="choose-box">
  272. <view class="city-content">
  273. <view
  274. v-for="(item, index) in cityList" :key="index" class="name"
  275. :class="[query.cityId == item.cityId ? 'active' : '']" @click="choose(item.cityId, index as number)"
  276. >
  277. {{ item.name }}
  278. </view>
  279. </view>
  280. <view class="choose-content">
  281. <view class="choose-item" @click="choose(query.cityId)">
  282. <view class="name">
  283. 全城
  284. </view>
  285. <image
  286. v-if="query.districtId === ''" class="icon" :src="`${StaticUrl}/film-choose-icon.png`"
  287. mode="scaleToFill"
  288. />
  289. </view>
  290. <view
  291. v-for="(item, index) in cityList[currentCity].districts" :key="index" class="choose-item"
  292. @click="choose(item.cityId, currentCity, item.districtId)"
  293. >
  294. <view class="name" :class="[query.districtId == item.districtId ? 'active' : '']">
  295. {{ item.districtName }}
  296. </view>
  297. <image
  298. v-if="query.districtId == item.districtId" class="icon" :src="`${StaticUrl}/film-choose-icon.png`"
  299. mode="scaleToFill"
  300. />
  301. </view>
  302. </view>
  303. </view>
  304. <view v-if="active == 1" class="choose-box">
  305. <view class="choose-content">
  306. <view class="choose-item" @click="choose('')">
  307. <view class="name">
  308. 全部
  309. </view>
  310. <image
  311. v-if="query.brandId === ''" class="icon" :src="`${StaticUrl}/film-choose-icon.png`"
  312. mode="scaleToFill"
  313. />
  314. </view>
  315. <view v-for="(item, index) in brandList" :key="index" class="choose-item" @click="choose(item.brandId)">
  316. <view class="name" :class="[query.brandId == item.brandId ? 'active' : '']">
  317. {{ item.brandName }}
  318. </view>
  319. <image
  320. v-if="query.brandId == item.brandId" class="icon" :src="`${StaticUrl}/film-choose-icon.png`"
  321. mode="scaleToFill"
  322. />
  323. </view>
  324. </view>
  325. </view>
  326. </view>
  327. </wd-action-sheet>
  328. </view>
  329. </template>
  330. <style lang="scss" scoped>
  331. .choose-film{
  332. background: #fff;
  333. min-height: 100vh;
  334. .bg-box {
  335. width: 100%;
  336. height: 596rpx;
  337. position: relative;
  338. .img {
  339. width: 100%;
  340. height: 596rpx;
  341. vertical-align: top;
  342. }
  343. }
  344. .info-box {
  345. padding: 24rpx;
  346. padding-top: 300rpx;
  347. border-radius: 16rpx 16rpx 16rpx 16rpx;
  348. margin-top: -400rpx;
  349. position: relative;
  350. background: linear-gradient(179deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.8) 29.54%, #FFFFFF 46.99%, #FFFFFF 100%);
  351. .info {
  352. display: flex;
  353. position: relative;
  354. .icon {
  355. width: 218rpx;
  356. height: 298rpx;
  357. background: #aaa;
  358. border-radius: 16rpx;
  359. flex-shrink: 0;
  360. }
  361. .box {
  362. display: flex;
  363. flex-direction: column;
  364. justify-content: space-between;
  365. margin-left: 20rpx;
  366. .name {
  367. font-weight: 600;
  368. font-size: 28rpx;
  369. color: #222222;
  370. width: 400rpx;
  371. white-space: nowrap;
  372. overflow: hidden;
  373. text-overflow: ellipsis;
  374. }
  375. .score-box {
  376. font-size: 24rpx;
  377. color: #AAAAAA;
  378. position: absolute;
  379. top: 0;
  380. right: 0;
  381. text-align: right;
  382. .score {
  383. display: flex;
  384. align-items: center;
  385. justify-content: flex-end;
  386. .num {
  387. font-size: 28rpx;
  388. color: #FF4D3A;
  389. padding: 0 12rpx;
  390. }
  391. }
  392. .want-num {
  393. padding: 0 12rpx;
  394. align-self: flex-end;
  395. margin-top: 24rpx;
  396. // font-size: 24rpx;
  397. // color: #AAAAAA;
  398. }
  399. }
  400. .type-box {
  401. display: flex;
  402. align-items: center;
  403. font-size: 24rpx;
  404. color: #AAAAAA;
  405. .tag {
  406. padding: 6rpx 10rpx;
  407. background: #F0F0F0;
  408. border-radius: 8rpx 8rpx 8rpx 8rpx;
  409. font-size: 24rpx;
  410. color: #AAAAAA;
  411. margin-left: 10rpx;
  412. }
  413. }
  414. .publish-info {
  415. font-size: 24rpx;
  416. color: #AAAAAA;
  417. white-space: nowrap;
  418. text-overflow: ellipsis;
  419. overflow: hidden;
  420. max-width: 460rpx;
  421. }
  422. }
  423. }
  424. .title-box {
  425. display: flex;
  426. justify-content: space-between;
  427. margin-top: 28rpx;
  428. .title {
  429. font-weight: 600;
  430. font-size: 28rpx;
  431. color: #222222;
  432. }
  433. .open {
  434. display: flex;
  435. align-items: center;
  436. font-size: 24rpx;
  437. color: #AAAAAA;
  438. .icon {
  439. width: 24rpx;
  440. height: 24rpx;
  441. }
  442. }
  443. }
  444. .desc {
  445. font-size: 24rpx;
  446. color: #222222;
  447. font-weight: 300;
  448. margin-top: 20rpx;
  449. line-height: 40rpx;
  450. }
  451. }
  452. .choose-list{
  453. display: flex;
  454. padding: 24rpx 0;
  455. background: #fff;
  456. .choose-item{
  457. display: flex;
  458. align-items: center;
  459. margin-right: 80rpx;
  460. .choose-item-title{
  461. font-weight: bold;
  462. font-size: 32rpx;
  463. color: #222222;
  464. }
  465. .icon{
  466. width: 30rpx;
  467. height: 30rpx;
  468. margin-left: 12rpx;
  469. }
  470. &.active{
  471. .choose-item-title{
  472. color: var(--them-color);
  473. }
  474. }
  475. }
  476. }
  477. .film-list{
  478. padding: 0 24rpx;
  479. .film-item{
  480. background: #F9F9F9;
  481. border-radius: 16rpx 16rpx 16rpx 16rpx;
  482. padding: 24rpx;
  483. margin-bottom: 20rpx;
  484. .name-box{
  485. display: flex;
  486. justify-content: space-between;
  487. margin-bottom: 16rpx;
  488. .name{
  489. font-weight: bold;
  490. font-size: 28rpx;
  491. color: #222222;
  492. }
  493. .price-box{
  494. display: flex;
  495. align-items: center;
  496. .num{
  497. font-weight: bold;
  498. font-size: 36rpx;
  499. color: #FF4D3A;
  500. }
  501. .label{
  502. font-size: 24rpx;
  503. color: #AAAAAA;
  504. }
  505. }
  506. }
  507. .address-box{
  508. display: flex;
  509. justify-content: space-between;
  510. font-size: 24rpx;
  511. color: #AAAAAA;
  512. margin-bottom: 16rpx;
  513. .address {
  514. font-size: 24rpx;
  515. color: #AAAAAA;
  516. }
  517. .distance{
  518. }
  519. }
  520. .cantact{
  521. font-size: 24rpx;
  522. color: #AAAAAA;
  523. margin-bottom: 16rpx;
  524. }
  525. .time-box{
  526. font-size: 24rpx;
  527. color: #222222;
  528. }
  529. }
  530. }
  531. .content{
  532. padding: 0 24rpx;
  533. .choose-box{
  534. min-height: 500rpx;
  535. display: flex;
  536. .city-content{
  537. width: 30%;
  538. .name{
  539. font-size: 28rpx;
  540. color: #222222;
  541. padding: 14rpx 0;
  542. }
  543. }
  544. .choose-content{
  545. flex: 1;
  546. .choose-item{
  547. display: flex;
  548. justify-content: space-between;
  549. padding: 14rpx 0;
  550. .name{
  551. font-size: 28rpx;
  552. color: #222222;
  553. }
  554. .icon{
  555. width: 30rpx;
  556. height: 30rpx;
  557. }
  558. }
  559. }
  560. .name.active{
  561. color: var(--them-color);
  562. }
  563. }
  564. }
  565. }
  566. </style>