other.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501
  1. <script setup lang="ts">
  2. // import mpHtml from 'mp-html/dist/uni-app/components/mp-html/mp-html'
  3. import {
  4. getDyProductDetail,
  5. getJdProductDetail,
  6. getPddProductDetail, getShareId,
  7. getSuProductDetail,
  8. getTaobaoProductDetail,
  9. getVipProductDetail
  10. } from "~/apis/product";
  11. import CXBBasePage from "~/components/CXBBasePage/CXBBasePage.vue";
  12. import type {
  13. IProductDetail,
  14. JdProductDetailModel,
  15. TaobaoProductThirdPartyWaresModel,
  16. TaobaoWaresDetail
  17. } from "~/apis/model/product.model";
  18. import FPrice from "~/components/FPrice/FPrice.vue";
  19. import FButton from "~/components/FButton/FButton.vue";
  20. import CXBButton from "~/components/CXBButton/CXBButton.vue";
  21. import CXBBackTop from "~/components/CXBBackTop/CXBBackTop.vue";
  22. import {debounce, merge} from "lodash-es";
  23. import {useDebounceFn} from '@vueuse/core';
  24. import dayjs from "dayjs";
  25. import {decodeBase64} from "~/utils/http/helper";
  26. import {CDN_URL} from "~/config/app";
  27. const discount_coupon_bg_220804Image = CDN_URL + '/static/assets/discount_coupon_bg_220804.png'
  28. const productId = ref('')
  29. //
  30. const userStore = useUserStore()
  31. const isSubmit = ref(false)
  32. const productType = ref(-1)
  33. // 优惠券劵信息
  34. const coupon = ref({
  35. // 优惠券金额
  36. money: '',
  37. // 优惠券有效期
  38. startTime: '',
  39. endTime: ''
  40. })
  41. const productDetail = ref<JdProductDetailModel | TaobaoWaresDetail>()
  42. const props = defineProps({
  43. type: {
  44. type: Number,
  45. default: 0
  46. }
  47. })
  48. const state = reactive({
  49. data: {},
  50. shareId: ''
  51. })
  52. const detail = ref<IProductDetail>()
  53. onLoad((options: any) => {
  54. const data: Partial<IProductDetail> = JSON.parse(decodeBase64(options.params))
  55. // console.log(data)
  56. mergeProductDetail(data)
  57. // if (options.platform && options.id) {
  58. uni.showLoading({
  59. title: '数据加载中',
  60. icon: 'none'
  61. })
  62. loadProductDetail(data)
  63. // }
  64. })
  65. onShow(() => {
  66. isSubmit.value = false
  67. })
  68. function mergeProductDetail(data: Partial<IProductDetail> = {}) {
  69. detail.value = merge(detail.value, data)
  70. }
  71. function loadProductDetail(product: Partial<IProductDetail>) {
  72. // console.log('产品id')
  73. // console.log(product.id)
  74. // 京东
  75. if (product.platform == 6) {
  76. getJdProductDetail(product.id).then(res => {
  77. const jdProduct = res[0]
  78. // console.log(jdProduct)
  79. mergeProductDetail({
  80. images: jdProduct.detail,
  81. coupon: {
  82. amount: jdProduct.couMoney
  83. },
  84. ...jdProduct
  85. })
  86. uni.hideLoading()
  87. })
  88. }
  89. // 淘宝
  90. if (product.platform === 5) {
  91. getTaobaoProductDetail(product.id).then(res => {
  92. const product = res.waresDetail
  93. mergeProductDetail({
  94. images: product.small_images,
  95. coupon: {
  96. startTime: product.couponStartTime,
  97. endTime: product.couponEndTime
  98. },
  99. ...product
  100. })
  101. uni.hideLoading()
  102. })
  103. }
  104. // 拼多多
  105. if (product.platform == 1) {
  106. getPddProductDetail(product.id).then(res => {
  107. // detail.value = res
  108. mergeProductDetail({
  109. spreadUrl: res.pddlink.url,
  110. images: res.goods_gallery_urls,
  111. featured: res.goods_gallery_urls,
  112. mallName: res.mall_name,
  113. ...res
  114. // allowance:
  115. })
  116. if (res.coupon_start_time > 0) {
  117. mergeProductDetail({
  118. coupon: {
  119. // amount: (res.extra_coupon_amount / 100).toString(),
  120. startTime: dayjs.unix(res.coupon_start_time).format('YYYY-MM-DD'),
  121. endTime: dayjs.unix(res.coupon_end_time).format('YYYY-MM-DD')
  122. },
  123. })
  124. } else {
  125. mergeProductDetail({
  126. coupon: null
  127. })
  128. }
  129. uni.hideLoading()
  130. })
  131. }
  132. // 唯品会
  133. if (product.platform == 2) {
  134. getVipProductDetail(product.id).then(res => {
  135. // console.log(res.result[0])
  136. const product = res.result[0]
  137. // detail.value = product
  138. mergeProductDetail({
  139. featured: product.goodsCarouselPictures,
  140. images: product.goodsDetailPictures,
  141. mallName: '唯品自营',
  142. ...product,
  143. ...res
  144. })
  145. if (product.couponInfo) {
  146. mergeProductDetail({
  147. coupon: {
  148. amount: product.couponInfo.activedAmount,
  149. startTime: product.couponInfo.useBeginTime,
  150. endTime: product.couponInfo.useEndTime
  151. }
  152. })
  153. }
  154. uni.hideLoading()
  155. })
  156. }
  157. // 苏宁
  158. if (product.platform == 3) {
  159. getSuProductDetail(product.id).then(res => {
  160. // const product = res
  161. mergeProductDetail({
  162. images: res.detail,
  163. ...res
  164. })
  165. uni.hideLoading()
  166. })
  167. }
  168. // 抖音
  169. if (product.platform == 9) {
  170. getDyProductDetail(product.id).then(res => {
  171. console.log(res)
  172. mergeProductDetail({
  173. mallName: res.shopName,
  174. images: res.imgs,
  175. ...res
  176. })
  177. uni.hideLoading()
  178. })
  179. }
  180. }
  181. function handleBuyNow() {
  182. if (isSubmit.value) return
  183. if (!userStore.uid) {
  184. isSubmit.value = true
  185. uni.navigateTo({
  186. url: '/pages/user/login/index'
  187. })
  188. }
  189. if (detail.value?.platform) {
  190. // 京东
  191. if (detail.value?.platform == 6 && detail.value?.materialUrl) {
  192. // console.log(detail.value?.spreadUrl)
  193. console.log(detail.value)
  194. if (detail.value && detail.value.materialUrl) {
  195. uni.navigateToMiniProgram({
  196. appId: 'wx91d27dbf599dff74',
  197. // path: 'pages/union/proxy/proxy?spreadUrl=' + encodeURIComponent(detail.value?.spreadUrl),
  198. path: 'pages/union/proxy/proxy?spreadUrl=' + detail.value.materialUrl,
  199. extraData: {
  200. foo: 'bar'
  201. },
  202. envVersion: 'release',
  203. success(res) {
  204. // 打开成功
  205. // console.log(res);
  206. },
  207. fail: (error) => {
  208. console.log(error);
  209. }
  210. })
  211. } else {
  212. return uni.showToast({
  213. title: '跳转失败请重试',
  214. icon: 'none'
  215. })
  216. }
  217. } else if (detail.value?.platform == 1) {
  218. // console.log(detail.value)
  219. const pddWx = detail.value.pddlink.wx
  220. if (pddWx) {
  221. uni.navigateToMiniProgram({
  222. appId: pddWx.app_id,
  223. path: pddWx.page_path,
  224. // extraData: {
  225. // foo: 'bar'
  226. // },
  227. envVersion: 'release',
  228. success(res) {
  229. // 打开成功
  230. // console.log(res);
  231. },
  232. fail: (error) => {
  233. console.log(error);
  234. }
  235. })
  236. } else {
  237. uni.showToast({
  238. title: '跳转失败请重试',
  239. icon: 'none'
  240. })
  241. }
  242. // console.log(detail.value.pddlink)
  243. // console.log(pddWx)
  244. } else {
  245. /* let platformName = ''
  246. let clipboardData = ''
  247. if (detail.value?.platform == 5) {
  248. platformName = '淘宝'
  249. clipboardData = detail.value?.spreadUrl
  250. }
  251. if (detail.value?.platform == 9) {
  252. platformName = '抖音'
  253. clipboardData = detail.value?.dyZlink
  254. }
  255. if (detail.value?.platform == 2) {
  256. platformName = '唯品会'
  257. clipboardData = detail.value?.destUrl
  258. }
  259. if (detail.value?.platform == 3) {
  260. platformName = '苏宁易购'
  261. clipboardData = detail.value?.productUrlWap
  262. }
  263. return uni.setClipboardData({
  264. data: clipboardData,
  265. success(res) {
  266. return uni.showToast({
  267. title: `链接已复制,去【${platformName}】打开即可。`,
  268. icon: 'none'
  269. })
  270. },
  271. fail(res) {
  272. return uni.showToast({
  273. title: '请更新隐私协议',
  274. icon: 'none'
  275. })
  276. }
  277. })*/
  278. // }
  279. return uni.showToast({
  280. title: '商品维护中,请稍后再试',
  281. icon: 'none'
  282. })
  283. }
  284. }
  285. /*
  286. if (detail.value?.platform == 3) {
  287. }
  288. if (detail.value?.platform == 9) {
  289. console.log(detail.value)
  290. }
  291. if (detail.value?.platform == 2) {
  292. console.log(detail.value)
  293. }*/
  294. onShareAppMessage(async () => {
  295. await uni.showLoading({
  296. title: '分享中',
  297. icon: 'none'
  298. })
  299. return await getShareId({ pid: state.id, type: 1 }).then(res => {
  300. if (res) {
  301. state.shareId = res.share_id
  302. uni.hideLoading()
  303. return {
  304. title: `${detail.value.title}`,
  305. path: `pages/store/product/detail?id=${detail.value.id}&from=share&shareID=${state.shareId}`
  306. }
  307. }
  308. }).catch(error => {
  309. uni.showToast({
  310. title: '请登录后分享',
  311. icon: 'none'
  312. }).then(() => {
  313. setTimeout(() => {
  314. uni.navigateTo({
  315. url: '/pages/user/login/index'
  316. })
  317. }, 500)
  318. })
  319. uni.hideLoading()
  320. })
  321. })
  322. onShareTimeline(() => {
  323. if (!userStore.uid) {
  324. return uni.showToast({
  325. title: '请登录后分享',
  326. icon: 'none'
  327. }).then(() => {
  328. setTimeout(() => {
  329. uni.navigateTo({
  330. url: '/pages/user/login/index'
  331. })
  332. }, 500)
  333. })
  334. }
  335. return {
  336. title: `${detail.value.store_name}`,
  337. imageUrl: state.shareImage,
  338. query: `id=${state.id}&from=share&shareID=${state.shareId}`
  339. }
  340. })
  341. }
  342. /**
  343. * 有优惠券
  344. */
  345. const hasCoupon = computed(() => {
  346. return detail.value?.coupon && detail.value?.coupon.startTime
  347. })
  348. // 距离顶部距离
  349. let Scroll_X = ref(0)
  350. const headerClass = ref('')
  351. onPageScroll((page) => {
  352. // console.log('滚轮事件触发了',page.scrollTop.toFixed());
  353. // console.log(page.scrollTop.toFixed(),'距离顶部的距离')
  354. Scroll_X.value = Number(page.scrollTop.toFixed())
  355. if (page.scrollTop >= 76 ) {
  356. headerClass.value = 'bg-white !text-gray-900'
  357. } else {
  358. headerClass.value = ''
  359. }
  360. })
  361. </script>
  362. <template>
  363. <CXBBasePage>
  364. <div class="relative w-screen " v-if="detail">
  365. <swiper
  366. v-if="detail.featured"
  367. :indicator-dots="false"
  368. :circular="true"
  369. :autoplay="true"
  370. :interval="5000"
  371. :duration="500"
  372. class="h-95"
  373. >
  374. <swiper-item
  375. v-for="(item, index) in detail.featured"
  376. :key="index"
  377. >
  378. <image
  379. :key="index"
  380. :src="item"
  381. mode="aspectFill" class="h-full w-full"
  382. />
  383. </swiper-item>
  384. </swiper>
  385. <CXBBackTop :Scroll_X="Scroll_X"/>
  386. <div>
  387. <div class="relative p-3 bg-white">
  388. <div class="flex gap-2 items-end">
  389. <FPrice v-if="detail && detail.salePrice" :price="detail.salePrice" need-symbol :size="'large'"
  390. ex-class="!text-[24px]"/>
  391. <FPrice v-if="detail && detail.price" :price="detail.price" :ex-class="'!text-gray'" need-symbol
  392. strike-through/>
  393. </div>
  394. <div class="font-bold py-2">{{ detail.title }}</div>
  395. </div>
  396. <div class="relative"
  397. v-if="hasCoupon"
  398. >
  399. <div
  400. class="px-3 relative"
  401. @tap="handleBuyNow"
  402. >
  403. <image :src="discount_coupon_bg_220804Image"
  404. mode="widthFix"
  405. class="w-full"
  406. ></image>
  407. <div class="absolute top-2 left-15 h-full w-fit text-white"
  408. >
  409. <div class=" inline-flex justify-center items-end w-full py-2">
  410. <div class="text-[28px]">{{ detail.coupon.amount }}</div>
  411. 元代金劵
  412. </div>
  413. <div class="text-[10px]">使用期限:{{ detail.coupon.startTime }} -{{ detail.coupon.endTime }}</div>
  414. </div>
  415. </div>
  416. </div>
  417. <div class="relative pb-safe mt-3 bg-white">
  418. <div v-if="detail.mallName" class="p-3 font-bold">
  419. {{ detail.mallName }}
  420. </div>
  421. <!-- <mpHtml :content=""></mpHtml>-->
  422. <image v-for="(imgItem, index) in detail.images"
  423. :key="index"
  424. mode="widthFix"
  425. :src="imgItem"
  426. class="w-full h-full"
  427. ></image>
  428. </div>
  429. </div>
  430. <div class="fixed bottom-0 w-full h-15 shadow">
  431. <div class="w-full bg-white pb-safe">
  432. <div class="flex justify-between items-center p-3">
  433. <div class="inline-flex items-center">
  434. <div class="text-sm">预估养老金</div>
  435. <FPrice :price="detail.yanglao || detail.commission" need-symbol ex-class="text-[20px] font-bold"/>
  436. </div>
  437. <div>
  438. <nut-button type="primary" @tap="handleBuyNow" :disabled="isSubmit">
  439. 立即购买
  440. </nut-button>
  441. </div>
  442. </div>
  443. </div>
  444. </div>
  445. </div>
  446. </CXBBasePage>
  447. </template>
  448. <route lang="yaml">
  449. style:
  450. navigationBarTitleText: 商品详情
  451. enablePullDownRefresh: true
  452. </route>