activityDetail.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614
  1. <template>
  2. <view class="act-deltail-main"
  3. :style="{paddingBottom: `${footerHeight}rpx`}">
  4. <network-error />
  5. <view class="over-view">
  6. <image class="detail-img"
  7. :src="detail.imgs"
  8. mode="aspectFill"></image>
  9. <view class="detail-over">
  10. <text class="detail-title u-line-2 u-font-40 line-56 u-tips-color bold">【{{detail.activity_type | activityTyepFilter}}】{{detail.title}}</text>
  11. <view class="u-flex u-col-bottom u-p-t-24 u-p-b-28 u-border-bottom">
  12. <text class="u-primary-color u-font-28 line-40">返利:</text>
  13. <block v-if="detail.activity_type === 1">
  14. <text class="u-flex-1 u-primary-color u-font-36 line-50 bold">实付全返</text>
  15. </block>
  16. <block v-if="detail.activity_type === 2">
  17. <view class="u-flex-1 u-primary-color bold">
  18. <text class="u-font-28 line-40">¥</text>
  19. <text class="u-font-36 line-50">{{(detail.rebate_amount / 100).toFixed(2)}}</text>
  20. </view>
  21. </block>
  22. <text class="u-primary-color u-font-24 line-34">{{detail.join_count - detail.join_number}}</text>
  23. <text class="u-content-color u-font-24 line-34">剩余名额</text>
  24. </view>
  25. <view class="u-flex u-row-between u-p-t-22 line-34">
  26. <text class="u-content-color">{{detail.join_number}}已参与</text>
  27. <button class="share-btn u-primary-color u-font-24 line-34"
  28. open-type="share">分享活动</button>
  29. </view>
  30. </view>
  31. </view>
  32. <view class="shop-info u-m-t-16">
  33. <view class="u-font-36 line-50 u-tips-color bold">店铺信息</view>
  34. <view class="u-flex">
  35. <view class="u-flex-1">
  36. <text class="shop-name u-font-28 u-tips-color line-40 u-line-1">【{{detail.plat_type | platFilter}}】{{detail.shop_name}}</text>
  37. <view class="u-flex"
  38. @click="openMap">
  39. <view class="icon-map-wh icon-map"></view>
  40. <view class="u-content-color u-m-l-8 u-m-r-16">{{(detail.distance / 1000).toFixed(1)}}km</view>
  41. <text class="shop-address u-flex-1 u-content-color u-line-1">{{detail.shop_address}}</text>
  42. </view>
  43. </view>
  44. <view class="divider-right"></view>
  45. <block v-if="detail.plat_type === 8">
  46. <view class="to-btn u-p-l-28"
  47. @click="openOtherApplte()">
  48. <view class="icon-mt-wh icon-elm"></view>
  49. <view class="u-m-t-2 u-font-22 u-content-color line-32">打开饿了么</view>
  50. </view>
  51. </block>
  52. <block v-if="detail.plat_type === 9">
  53. <view class="to-btn u-p-l-40"
  54. @click="openOtherApplte()">
  55. <view class="icon-mt-wh icon-mt"></view>
  56. <view class="u-m-t-2 u-font-22 u-content-color line-32">打开美团</view>
  57. </view>
  58. </block>
  59. </view>
  60. </view>
  61. <view class="act-able-time u-m-t-16">
  62. <view class="u-font-36 line-50 u-tips-color bold">活动可用时间</view>
  63. <view class="u-flex u-m-t-16">
  64. <text class="u-flex-1 u-content-color line-40 u-line-2 u-p-r-32">{{businessHours}}营业时间可用(当天参与报名,需当天提交资料才能有效返款)</text>
  65. <view class="divider-right"></view>
  66. <button class="to-btn contact-btn u-p-l-40"
  67. @click="copyWx">
  68. <view class="icon-phone-wh icon-phone"></view>
  69. <view class="u-m-t-2 u-font-22 u-content-color line-32">联系客服</view>
  70. </button>
  71. </view>
  72. </view>
  73. <view class="act-desc u-m-t-16">
  74. <view class="act-tabs u-border-bottom">
  75. <u-tabs :is-scroll="false"
  76. :list="[{name: '活动规则'}, {name: '评价要求'}]"
  77. :current="currentTab"
  78. height="104"
  79. font-size="30"
  80. active-color="#FF6632"
  81. inactive-color="#111111"
  82. :bar-style="{
  83. bottom: '-4rpx',
  84. marginLeft: '-40rpx',
  85. width: '120rpx',
  86. height: '6rpx',
  87. borderRadius: 0,
  88. backgroundColor: 'linear-gradient(270deg, #FFB76B 0%, #FE4028 100%)'
  89. }"
  90. @change="changeTab">
  91. </u-tabs>
  92. </view>
  93. <view class="u-m-b-18 u-p-t-32 u-p-b-32">
  94. <block v-if="currentTab === 0">
  95. <block v-for="(item, index) in detail.content"
  96. :key="index">
  97. <img-text :value="item.content"
  98. :type="item.contentType"></img-text>
  99. </block>
  100. </block>
  101. <block v-else>
  102. <img-text :value="detail.requirement"
  103. type="1"></img-text>
  104. </block>
  105. </view>
  106. </view>
  107. <block v-if="status">
  108. <fixed-bottom @get-height="getFooterHeight">
  109. <view class="bottom-footer u-flex">
  110. <block v-if="status * 1 === 1 || status * 1 === 2">
  111. <view class="u-flex-1">
  112. <view class="line-34 bold">距活动结束还有:</view>
  113. <view class="u-font-20 u-content-color line-28">{{remainingTime}}</view>
  114. </view>
  115. <block v-if="status * 1 === 1">
  116. <button class="sign-up-btn u-font-30 bold line-42"
  117. @click="join">我要报名</button>
  118. </block>
  119. <block v-if="status * 1 === 2">
  120. <view class="u-flex">
  121. <button class="canel-btn u-font-28 line-40"
  122. @click="cancelJoin">取消报名</button>
  123. <button class="submit-btn u-font-28 line-40 u-m-l-16"
  124. @click="toSubmiteOrder">提交结果</button>
  125. </view>
  126. </block>
  127. </block>
  128. <block v-if="status * 1 === 3 || status * 1 === 4">
  129. <block v-if="status * 1 === 3">
  130. <view class="u-flex-1">
  131. <view class="line-34 bold">等待审核:</view>
  132. <view class="u-font-20 u-content-color line-28">审核通过后将获得返利金额</view>
  133. </view>
  134. </block>
  135. <block v-if="status * 1 === 4">
  136. <view class="u-flex-1">
  137. <view class="line-34 bold">审核通过:</view>
  138. <view class="u-font-20 u-content-color line-28">返利金额将在第二日到账</view>
  139. </view>
  140. </block>
  141. <button class="sign-up-btn u-font-30 bold line-42"
  142. disabled>已提交</button>
  143. </block>
  144. <block v-if="status * 1 === 5">
  145. <view class="u-flex-1">
  146. <view class="line-34 bold">审核驳回:</view>
  147. <view class="u-font-20 u-content-color line-28">{{detail.reject_reason}}</view>
  148. </view>
  149. </block>
  150. <block v-if="status * 1 === 6">
  151. <button class="end-btn u-m-l-12"
  152. disabled>已结束</button>
  153. </block>
  154. <block v-if="status * 1 === 7">
  155. <button class="end-btn u-m-l-12"
  156. disabled>已抢光</button>
  157. </block>
  158. </view>
  159. </fixed-bottom>
  160. </block>
  161. <view class="fixed-copy">
  162. <view class="btn-copy u-font-22"
  163. :style="{marginBottom: `${footerHeight}rpx`}"
  164. @click.stop="copyShopName">复制店名</view>
  165. </view>
  166. </view>
  167. </template>
  168. <script>
  169. import fixedBottom from '@/components/fixedBottom'
  170. import imgText from '@/components/imgText'
  171. import { getActivityDetail } from '@/api/activityApi'
  172. import { editJoinActivity, cancelJoinActivity } from '@/api/userApi'
  173. export default {
  174. components: { fixedBottom, imgText },
  175. data () {
  176. return {
  177. showErr: false,
  178. errMsg: '',
  179. nowTime: '',
  180. timer: null,
  181. footerHeight: 0,
  182. currentTab: 0,
  183. activityId: '',
  184. recordId: '',
  185. detail: {
  186. imgs: '',
  187. activity_type: '',
  188. title: '',
  189. rebate_amount: '',
  190. join_count: 0,
  191. join_number: 0,
  192. plat_type: '',
  193. shop_name: '',
  194. distance: 0,
  195. shop_address: '',
  196. join_status: '',
  197. start_time: '',
  198. end_time: ''
  199. }
  200. }
  201. },
  202. computed: {
  203. userId () {
  204. return this.$store.state.userInfo.token
  205. },
  206. businessHours () {
  207. const date = this.$dayjs(`${this.detail.start_date}`).format('YYYY年MM月DD日')
  208. const start = this.$dayjs(`${this.detail.start_date} ${this.detail.start_time}`).format('HH:mm')
  209. const end = this.$dayjs(`${this.detail.end_date} ${this.detail.end_time}`).format('HH:mm')
  210. return `${date} ${start}-${end}`
  211. },
  212. status () {
  213. if (this.detail.join_status === 1) {
  214. return 2
  215. } else if (this.detail.join_status === 2) {
  216. return 3
  217. } else if (this.detail.join_status === 3) {
  218. return 4
  219. } else if (this.detail.join_status === 4) {
  220. return 5
  221. } else if (this.detail.join_status === 5) {
  222. return 1
  223. } else if (this.detail.join_status === 6) {
  224. return 6
  225. } else if (this.remainingTime === 0) {
  226. return 6
  227. } else if (this.detail.join_count === this.detail.join_number && this.detail.join_count) {
  228. return 7
  229. } else if (this.detail.join_status === 0) {
  230. return 1
  231. } else {
  232. return 0
  233. }
  234. },
  235. remainingTime () {
  236. if (!this.detail.end_time) { return }
  237. const endTime = this.$dayjs(`${this.$dayjs().format('YYYY-MM-DD')} ${this.detail.end_time}`)
  238. if (isNaN(endTime.diff(this.nowTime, 's'))) { return }
  239. if (!isNaN(endTime.diff(this.nowTime, 's')) && endTime.diff(this.nowTime, 's') === 0) {
  240. clearTimeout(this.timer)
  241. return 0
  242. }
  243. return this.$dayjs(endTime.diff(this.nowTime)).subtract(8, 'h').format('HH小时mm分ss秒')
  244. }
  245. },
  246. watch: {
  247. userId (e) {
  248. if (!e) {
  249. uni.navigateTo({
  250. url: '/pagesSub/other/login'
  251. })
  252. }
  253. }
  254. },
  255. onLoad (options) {
  256. this.activityId = options.id
  257. this.recordId = options.record_id
  258. },
  259. onShow () {
  260. if (!this.userId) {
  261. uni.navigateTo({
  262. url: '/pagesSub/other/login'
  263. })
  264. return
  265. }
  266. this.getDetailData()
  267. this.reNowTime()
  268. },
  269. onHide () {
  270. clearTimeout(this.timer)
  271. },
  272. onError () {
  273. clearTimeout(this.timer)
  274. },
  275. onPullDownRefresh () {
  276. clearTimeout(this.timer)
  277. this.getDetailData()
  278. this.reNowTime()
  279. },
  280. onPageNotFound () {
  281. clearTimeout(this.timer)
  282. },
  283. onShareAppMessage (res) {
  284. const title = `${this.detail.activity_type === 1 ? '【免费吃】' : '【返利餐】'}${this.detail.title}`
  285. return {
  286. title: title,
  287. path: `/pagesSub/activity/activityDetail?id=${this.detail.id}`,
  288. imageUrl: this.detail.imgs
  289. }
  290. },
  291. onShareTimeline (res) {
  292. const title = `${this.detail.activity_type === 1 ? '【免费吃】' : '【返利餐】'}${this.detail.title}`
  293. return {
  294. title: title,
  295. path: `/pagesSub/activity/activityDetail?id=${this.detail.id}`,
  296. imageUrl: this.detail.imgs
  297. }
  298. },
  299. methods: {
  300. reNowTime () {
  301. clearTimeout(this.timer)
  302. this.timer = setTimeout(() => {
  303. this.nowTime = this.$dayjs()
  304. this.reNowTime()
  305. }, 1000)
  306. },
  307. // 获取用户经纬度
  308. getLocation () {
  309. return new Promise((resolve, reject) => {
  310. uni.getLocation({
  311. type: 'gcj02',
  312. success: (res) => {
  313. resolve(res)
  314. },
  315. fail: () => {
  316. resolve(false)
  317. }
  318. })
  319. })
  320. },
  321. // 获取活动详情
  322. async getDetailData () {
  323. const location = await this.getLocation()
  324. if (!location) { return }
  325. const params = {
  326. id: this.activityId,
  327. lng: location.longitude,
  328. lat: location.latitude
  329. }
  330. if (this.recordId) {
  331. params.record_id = this.recordId
  332. }
  333. const { code, data } = await getActivityDetail(params)
  334. if (code === 200) {
  335. this.detail = data
  336. }
  337. uni.stopPullDownRefresh()
  338. },
  339. // 报名活动/取消报名
  340. async joinActivity (type) {
  341. const params = {
  342. type: type
  343. }
  344. if (type === 1) {
  345. params.id = this.detail.id
  346. } else {
  347. params.record_id = this.detail.user_activity_id
  348. }
  349. const { code, msg } = type === 1 ? await editJoinActivity(params) : await cancelJoinActivity(params)
  350. if (code === 200) {
  351. if (type === 1) {
  352. uni.navigateTo({
  353. url: `/pagesSub/activity/signUpOutcome?endTime=${this.detail.end_time}&platType=${this.detail.plat_type}`
  354. })
  355. } else {
  356. this.getDetailData()
  357. }
  358. } else {
  359. uni.showToast({
  360. title: msg,
  361. icon: 'none'
  362. })
  363. }
  364. },
  365. getFooterHeight (h) {
  366. this.footerHeight = h * 2
  367. },
  368. changeTab (index) {
  369. this.currentTab = index
  370. },
  371. openMap () {
  372. uni.openLocation({
  373. latitude: this.detail.shop_lat,
  374. longitude: this.detail.shop_lng
  375. })
  376. },
  377. // 我要报名
  378. join () {
  379. // uni.requestSubscribeMessage({
  380. // tmplIds: [''],
  381. // success: (res) => {
  382. // this.joinActivity(1)
  383. // }
  384. // })
  385. this.joinActivity(1)
  386. },
  387. // 取消报名
  388. cancelJoin () {
  389. uni.showModal({
  390. title: '提示',
  391. content: '确定取消报名',
  392. confirmColor: '#1677FF',
  393. cancelColor: '#1677FF',
  394. success: (res) => {
  395. if (res.confirm) {
  396. this.joinActivity(2)
  397. }
  398. }
  399. })
  400. },
  401. // 提交结果
  402. toSubmiteOrder () {
  403. if (!this.$store.state.userInfo.alipay_account) {
  404. uni.navigateTo({
  405. url: '/pagesSub/my/userDetail?toastType=1'
  406. })
  407. return
  408. }
  409. uni.navigateTo({
  410. url: `/pagesSub/order/submitOrder?activityId=${this.detail.id}&userActivityId=${this.detail.user_activity_id}`
  411. })
  412. },
  413. openOtherApplte () {
  414. uni.navigateToMiniProgram({
  415. appId: this.detail.app_info.appid,
  416. path: this.detail.app_info.path
  417. })
  418. },
  419. copyShopName () {
  420. uni.setClipboardData({
  421. data: this.detail.shop_name,
  422. success: () => {
  423. uni.showToast({
  424. icon: 'none',
  425. title: '平台门店复制成功'
  426. })
  427. }
  428. })
  429. },
  430. copyWx () {
  431. uni.setClipboardData({
  432. data: this.detail.kf_wechat,
  433. success: () => {
  434. uni.showToast({
  435. icon: 'none',
  436. title: '已复制客服微信号,请添加客服反馈'
  437. })
  438. }
  439. })
  440. }
  441. },
  442. filters: {
  443. activityTyepFilter (e) {
  444. const typeList = {
  445. 1: '免费吃',
  446. 2: '返利餐'
  447. }
  448. return typeList[e] || ''
  449. },
  450. platFilter (e) {
  451. const platList = {
  452. 8: '饿了么',
  453. 9: '美团'
  454. }
  455. return platList[e] || ''
  456. }
  457. }
  458. }
  459. </script>
  460. <style lang="scss" scoped>
  461. .act-deltail-main {
  462. .fixed-copy {
  463. position: fixed;
  464. bottom: 0;
  465. z-index: 99;
  466. width: 100%;
  467. display: flex;
  468. justify-content: flex-end;
  469. padding-bottom: 16rpx;
  470. .btn-copy {
  471. width: 72rpx;
  472. height: 72rpx;
  473. text-align: center;
  474. padding: 8rpx;
  475. margin-right: 16rpx;
  476. background: #111111;
  477. box-shadow: 0px 1px 4px 0px rgba(17, 17, 17, 0.6);
  478. opacity: 0.8;
  479. color: #eaebec;
  480. font-weight: 400;
  481. border-radius: 36rpx;
  482. }
  483. }
  484. .over-view {
  485. .detail-img {
  486. width: 100%;
  487. height: 424px;
  488. font-size: 0;
  489. }
  490. .detail-over {
  491. padding: 24px 40px 28px;
  492. background-color: #fff;
  493. }
  494. .detail-title {
  495. max-width: 670px;
  496. }
  497. .share-btn {
  498. margin: 0;
  499. padding-right: 0;
  500. background-color: #fff;
  501. &::after {
  502. border-color: transparent;
  503. }
  504. }
  505. }
  506. .act-able-time,
  507. .shop-info {
  508. padding: 32px 40px 28px;
  509. background-color: #fff;
  510. .shop-name {
  511. display: inline-block;
  512. margin: 16px 0;
  513. max-width: 510px;
  514. }
  515. .shop-address {
  516. display: inline-block;
  517. max-width: 396px;
  518. }
  519. .to-btn {
  520. display: flex;
  521. flex-direction: column;
  522. align-items: center;
  523. }
  524. .contact-btn {
  525. padding-right: 0;
  526. background-color: #fff;
  527. &::after {
  528. border-color: transparent;
  529. }
  530. }
  531. .icon-map-wh {
  532. width: 20px;
  533. height: 24px;
  534. }
  535. .icon-phone-wh,
  536. .icon-elm-wh,
  537. .icon-mt-wh {
  538. width: 56px;
  539. height: 56px;
  540. }
  541. .divider-right {
  542. width: 2px;
  543. height: 54px;
  544. background-color: $u-border-color;
  545. }
  546. }
  547. .act-desc {
  548. padding: 0 40px;
  549. background-color: #fff;
  550. }
  551. .bottom-footer {
  552. padding: 16px 40px 16px 28px;
  553. width: 100%;
  554. background-color: #fff;
  555. .sign-up-btn {
  556. padding: 24px 128px;
  557. width: 374px;
  558. height: 88px;
  559. border-radius: 44px;
  560. color: #fff;
  561. background-color: $u-type-primary;
  562. white-space: nowrap;
  563. }
  564. .canel-btn,
  565. .submit-btn {
  566. padding: 16px 40px;
  567. width: 192px;
  568. height: 72px;
  569. border-radius: 36px;
  570. }
  571. .canel-btn {
  572. position: relative;
  573. color: $u-type-primary;
  574. background-color: #fff;
  575. &::after {
  576. content: '';
  577. display: flex;
  578. align-items: center;
  579. width: 200%;
  580. height: 200%;
  581. border: 2px solid $u-type-primary;
  582. border-radius: 72px;
  583. box-sizing: border-box;
  584. pointer-events: none;
  585. transform-origin: 0 0;
  586. }
  587. }
  588. .submit-btn {
  589. color: #fff;
  590. background-color: $u-type-primary;
  591. }
  592. .end-btn {
  593. width: 670px;
  594. height: 88px;
  595. border-radius: 44px;
  596. }
  597. }
  598. }
  599. button[disabled] {
  600. color: #fff !important;
  601. background-color: #d3d4d5 !important;
  602. }
  603. button[disabled]::after {
  604. border-color: transparent;
  605. }
  606. </style>
  607. <style >
  608. .act-tabs >>> .u-tab-item + .u-tab-item {
  609. margin-left: 42px;
  610. }
  611. </style>