detail.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  1. <template>
  2. <view>
  3. <view class="goods">
  4. <image :src="detail.image" style="width: 100vw;" mode="widthFix"></image>
  5. <view class="title">
  6. <view class="text-bold">{{detail.name}}</view>
  7. <view class="padding-tb-xs">
  8. <text class="text-sm">¥</text>
  9. <text class="">{{detail.cashValue}} / {{detail.equalPoints}}积分</text>
  10. </view>
  11. <block v-if="!$u.test.isEmpty(detail.description)">
  12. <view class="text-sm text-gray">产品说明:{{detail.description}}</view>
  13. </block>
  14. </view>
  15. </view>
  16. <block v-if="exchangeShow">
  17. <navigator :url="'../mine/order/address?userId='+userId" hover-class="none"
  18. class="container flex align-center justify-between" style="border-bottom: 1rpx solid #efefef;">
  19. <view class="flex padding align-center">
  20. <image src="/static/address.png" style="width: 65upx;height: 65upx;"></image>
  21. <view class="padding-left text-sm" v-if="!$u.test.isEmpty(address)">
  22. <view style="font-size: 28upx;font-family: PingFang SC;font-weight: 800;color: #000000;">
  23. {{address.consignee}} {{address.phone}}
  24. </view>
  25. <view class="text-gray">{{address.area}} {{address.detail}}</view>
  26. </view>
  27. <view class="padding-left"
  28. style="font-size: 28upx;font-family: PingFang SC;font-weight: 800;color: #000000;" v-else>
  29. 请选择收货地址</view>
  30. </view>
  31. <view class="padding">
  32. <u-icon name="arrow-right" color="#d4d4d4"></u-icon>
  33. </view>
  34. </navigator>
  35. <view class="text-red padding-sm">
  36. <view class="padding-tb-xs">
  37. 1:请选择要兑换商品的组合方式
  38. </view>
  39. <view class="">
  40. 2:组合合计达到 {{detail.cashValue}} 元即可兑换
  41. </view>
  42. </view>
  43. <view class="padding-sm">
  44. <view class="flex padding-xs">
  45. <text class="flex justify-center align-center">热力值:</text>
  46. <u-number-box :disabled="$u.test.isEmpty(proportion.usableHot)" :step="otherStep"
  47. :positive-integer="otherPositive" @change="hotValueChange" :input-width="200" :min="0"
  48. :max="+proportion.usableHot" v-model="data.hotValue">
  49. </u-number-box>
  50. <view v-if="changeCash.hotCash!=0"
  51. class="padding-left-sm text-red flex justify-center align-center">
  52. =
  53. <text class="padding-left-sm ">{{changeCash.hotCash}} 元</text>
  54. </view>
  55. </view>
  56. <view class="flex padding-xs">
  57. <text class="flex justify-center align-center">积分值:</text>
  58. <u-number-box :disabled="$u.test.isEmpty(proportion.usablePoints)" :step="otherStep"
  59. :positive-integer="otherPositive" @change="pointsValueChange" :input-width="200" :min="0"
  60. :max="+proportion.usablePoints" v-model="data.pointsValue">
  61. </u-number-box>
  62. <view v-if="changeCash.pointsCash!=0"
  63. class="padding-left-sm text-red flex justify-center align-center">
  64. =
  65. <text class="padding-left-sm ">{{changeCash.pointsCash}} 元</text>
  66. </view>
  67. </view>
  68. <view style="padding-top: 20rpx;display: flex;flex-direction: column;">
  69. <text
  70. class="text-gray padding-top-sm">可用热力值为:{{proportion.usableHot || 0}},价值{{ hotCashMul }}元</text>
  71. <text
  72. class="text-gray padding-top-sm">可用积分值为:{{proportion.usablePoints || 0}},价值{{ pointsCashMul}}元</text>
  73. </view>
  74. </view>
  75. </block>
  76. <view class="" style="height: 140rpx;">
  77. </view>
  78. <view v-if="!exchangeShow" class="footer-fixed flex align-center justify-end padding bg-white"
  79. style="padding: 30rpx;;border-top: 1rpx solid #e5e5e5;z-index: 9;">
  80. <button class="cu-btn round text-white theme-bg-color" style="width: 180upx;height: 80upx;"
  81. @click="exchange">兑换</button>
  82. </view>
  83. <view v-else class="footer-fixed flex align-center justify-between bg-white"
  84. style="border-top: 1rpx solid #e5e5e5;padding: 30rpx;z-index: 9;">
  85. <view class="text-red">
  86. <text>需支付现金</text>
  87. <text>¥</text>
  88. <text>{{cashValue}}</text>
  89. </view>
  90. <view>
  91. <button class="cu-btn round text-white theme-bg-color"
  92. style="width: 180upx;height: 80upx;margin-right: 10upx;" @click="confirm">兑换</button>
  93. <button @click="exchangeShow = false" class="cu-btn round line-gray"
  94. style="width: 180upx;height: 80upx;z-index: 99;">取消</button>
  95. </view>
  96. </view>
  97. <u-popup v-model="payShow" mode="center" width="500rpx" height="320rpx" border-radius="30">
  98. <view class="text-center text-lg padding">请确定支付是否已完成</view>
  99. <u-line color="#c2c2c2"></u-line>
  100. <view class="text-red text-center text-lg padding" @click="checkPayInterval">已完成支付</view>
  101. <u-line color="#c2c2c2"></u-line>
  102. <view class="text-gray text-center text-lg padding" @click="confirm">支付遇到问题,重新支付</view>
  103. </u-popup>
  104. <u-popup v-model="errorShow" mode="center" width="500rpx" height="600rpx" border-radius="30">
  105. <view class="bg-img text-center" style="background-image: url('https://upload-file-data.obs.cn-south-1.myhuaweicloud.com/e914f556be414767aca011a30961560a-dialogBgImg.png');height: 600rpx;">
  106. <view style="height: 120upx;"></view>
  107. <u-avatar :src="detail.image" size="160"></u-avatar>
  108. <view class="text-center margin-top text-lg text-bold">支付失败</view>
  109. <view class="padding">
  110. <u-button class="custom-style" shape="circle" @click="errorShow = false">确定</u-button>
  111. </view>
  112. </view>
  113. </u-popup>
  114. </view>
  115. </template>
  116. <script>
  117. import {
  118. appId
  119. } from '@/common/conf/config.js';
  120. import {
  121. authUrl
  122. } from '@/common/conf/config.js';
  123. import {
  124. getUrlParams
  125. } from '@/common/utils/utils.js';
  126. export default {
  127. data() {
  128. return {
  129. activityId: '',
  130. userId: '',
  131. id: '',
  132. proportion: {},
  133. pointsCashMul:null,
  134. hotCashMul:null,
  135. detail: {},
  136. address: {},
  137. exchangeShow: false,
  138. data: {
  139. cashValue: 0,
  140. hotValue: 0,
  141. pointsValue: 0
  142. },
  143. changeCash: {
  144. hotCash: 0,
  145. pointsCash: 0
  146. },
  147. cashStep: 1,
  148. cashPositive: true,
  149. otherStep: 10,
  150. otherPositive: true,
  151. orderId:"",
  152. payShow:false,
  153. errorShow:false,
  154. }
  155. },
  156. onLoad(options) {
  157. this.id = options.id;
  158. this.activityId = options.activityId;
  159. if (this.$u.test.isEmpty(this.id)) {
  160. this.$u.toast('商品id不能为空')
  161. return
  162. }
  163. this.userId = uni.getStorageSync("userId");
  164. this.authorization();
  165. this.fetchGoodsDetail();
  166. },
  167. computed: {
  168. totalCash: {
  169. get() {
  170. let tmp=this.floatAdd(this.data.cashValue,this.changeCash.hotCash)
  171. let total = this.floatAdd(tmp,this.changeCash.pointsCash)
  172. return total
  173. }
  174. },
  175. cashValue: {
  176. get() {
  177. let m = this.detail.cashValue
  178. let n = this.floatAdd(this.changeCash.hotCash,this.changeCash.pointsCash)
  179. let val = this.floatSub(m, n)
  180. if (val < 0) {
  181. this.$u.toast('不可以超过商品价格')
  182. return 0
  183. }
  184. this.data.cashValue = val
  185. return val
  186. }
  187. }
  188. },
  189. onShow() {
  190. this.getAddress()
  191. },
  192. methods: {
  193. floatAdd(arg1, arg2) {
  194. var r1,r2,m;
  195. try {
  196. r1 = arg1.toString().split(".")[1].length
  197. } catch (e) {
  198. r1 = 0
  199. }
  200. try {
  201. r2 = arg2.toString().split(".")[1].length
  202. } catch (e) {
  203. r2 = 0
  204. }
  205. m = Math.pow(10, Math.max(r1, r2));
  206. return (arg1 * m + arg2 * m) / m;
  207. },
  208. floatSub(arg1, arg2) {
  209. var r1, r2, m, n;
  210. try {
  211. r1 = arg1.toString().split(".")[1].length
  212. } catch (e) {
  213. r1 = 0
  214. }
  215. try {
  216. r2 = arg2.toString().split(".")[1].length
  217. } catch (e) {
  218. r2 = 0
  219. }
  220. m = Math.pow(10, Math.max(r1, r2));
  221. n = (r1 >= r2) ? r1 : r2;
  222. return ((arg1 * m - arg2 * m) / m).toFixed(n)
  223. },
  224. initStep() {
  225. let cashValue = parseFloat(this.detail.cashValue)
  226. let equalPoints = parseFloat(this.detail.equalPoints)
  227. if (cashValue < 1.0) {
  228. this.cashStep = 0.1
  229. this.cashPositive = false
  230. }
  231. if (equalPoints < 1.0) {
  232. this.otherStep = 0.1
  233. this.otherPositive = false
  234. }
  235. console.log(this.cashStep, this.otherStep);
  236. },
  237. getAddress() {
  238. this.$u.api.user.userAddress({
  239. userId: this.userId
  240. }).then(res => {
  241. this.address = res.records[0];
  242. })
  243. },
  244. fetchGoodsDetail() {
  245. this.$u.api.pointsGoods.list({
  246. id: this.id
  247. }).then(res => {
  248. this.detail = res.records[0];
  249. this.initStep()
  250. })
  251. },
  252. getUsableHotAndPoints() {
  253. let params = {
  254. activityId: this.activityId,
  255. userId: this.userId
  256. }
  257. this.$u.api.pointsGoods.getUsableHotAndPoints(params).then(res => {
  258. this.proportion = res
  259. this.pointsCashMul=this.numberMul(this.proportion.usablePoints,this.proportion.pointsProportion)
  260. this.hotCashMul=this.numberMul(this.proportion.usableHot,this.proportion.hotProportion)
  261. })
  262. },
  263. //计数器变化
  264. hotValueChange(item) {
  265. this.changeCash.hotCash = this.numberMul(item.value, this.proportion.hotProportion)
  266. },
  267. pointsValueChange(item) {
  268. this.changeCash.pointsCash = this.numberMul(item.value, this.proportion.pointsProportion)
  269. },
  270. async confirm() {
  271. this.payShow = false;
  272. let _this = this;
  273. if (this.$u.test.isEmpty(this.address) || this.$u.test.isEmpty(this.address.id)) {
  274. this.$u.toast('请选择地址')
  275. return;
  276. }
  277. let m=parseFloat(this.detail.cashValue)
  278. let n=parseFloat(this.totalCash)
  279. if (this.floatSub(m,n)!=parseFloat(0)) {
  280. uni.showToast({
  281. title: "总金额不等于商品所需金额",
  282. duration: 3000,
  283. icon: "none"
  284. })
  285. return;
  286. }
  287. if (!this.$u.test.isEmpty(parseFloat(this.data.cashValue))) {
  288. this.orderId = this.$u.guid(16);
  289. //去支付,支付成功后
  290. let orderInfo = (await this.$u.api.yeePay.initOrder(
  291. {
  292. "channel": "ALIPAY",
  293. "goodsName": this.detail.name,
  294. "notifyUrl": "1",
  295. "orderAmount": this.data.cashValue,
  296. "orderId": this.orderId,
  297. "payWay": "USER_SCAN",
  298. "scene": "OFFLINE",
  299. "userIp": "127.0.0.1"
  300. }
  301. ));
  302. this.$u.api.boost.billRecord({
  303. orderId: this.orderId,
  304. payPath: encodeURIComponent(window.location.href),
  305. userId: this.userId,
  306. activityId: this.activityId,
  307. price: this.data.cashValue,
  308. pointsValue:this.data.pointsValue,
  309. hotValue:this.data.hotValue,
  310. presentId: '',
  311. presentCount: '',
  312. relationId: this.id,
  313. type: 3,
  314. payStatus: 0,
  315. }).then(res => {
  316. if (typeof orderInfo.prePayTn != 'undefined') {
  317. //调起支付
  318. this.toPay(orderInfo.prePayTn);
  319. }
  320. })
  321. } else {
  322. this.doConfirm()
  323. }
  324. },
  325. toPay(info) {
  326. location.href = `alipays://platformapi/startapp?saId=10000007&clientVersion=3.7.0.0718&qrcode=${info}`;
  327. setTimeout(() => {
  328. this.payShow = true;
  329. }, 4000)
  330. },
  331. async checkPayInterval() {
  332. this.payShow = false;
  333. let res = await this.$u.api.boost.billRecordDetail({orderId: this.orderId})
  334. if (res && res.payStatus == 1) {
  335. this.exchangeSuccess()
  336. } else {
  337. this.errorShow = true;
  338. }
  339. },
  340. async doConfirm() {
  341. this.data.pointsGoodsId = this.id
  342. this.data.userId = this.userId
  343. let res = await this.$u.api.pointsGoods.exchange(this.data)
  344. if (res.code == 400) {
  345. uni.showToast({
  346. title: res.msg,
  347. duration: 3000,
  348. icon: "none"
  349. })
  350. return;
  351. }
  352. this.exchangeSuccess()
  353. },
  354. exchangeSuccess(){
  355. uni.showModal({
  356. title: "提示",
  357. content: "兑换成功,可到个人中心查看!",
  358. confirmColor: "#5a3ee8",
  359. showCancel: true,
  360. confirmText: "去查看",
  361. cancelText: "暂不查看",
  362. success: (res) => {
  363. this.getUsableHotAndPoints()
  364. if (res.confirm) {
  365. uni.navigateTo({
  366. url: "/pages/activityList/mine/pointsGoods/list"
  367. })
  368. }
  369. }
  370. })
  371. },
  372. numberMul(arg1, arg2) {
  373. var m = 0;
  374. var s1 = arg1.toString();
  375. var s2 = arg2.toString();
  376. try {
  377. m += s1.split(".")[1].length;
  378. } catch (e) {}
  379. try {
  380. m += s2.split(".")[1].length;
  381. } catch (e) {}
  382. return Number(s1.replace(".", "")) * Number(s2.replace(".", "")) / Math.pow(10, m);
  383. },
  384. exchange() {
  385. if (this.$u.test.isEmpty(this.userId)) {
  386. let path = "pages/activityList/goods/detail?id=" + this.id + "&activityId=" + this.activityId
  387. window.location.href = authUrl(path);
  388. } else {
  389. this.exchangeShow = true;
  390. this.getUsableHotAndPoints()
  391. this.getAddress()
  392. }
  393. },
  394. async authorization() {
  395. let agenterId = uni.getStorageSync("agenterId")
  396. let params = getUrlParams(window.location.search);
  397. if (!this.$u.test.isEmpty(params.code)) {
  398. let res = await this.$u.api.wxInfo.getUserInfo({
  399. userCode: params.code
  400. });
  401. uni.setStorageSync("openid", res.openid);
  402. let datas = {
  403. nickName: res.nickname,
  404. avatar: res.headimgurl,
  405. gender: res.sex,
  406. openid: res.openid,
  407. unionid: res.unionid,
  408. province: res.province,
  409. city: res.city
  410. }
  411. if (!this.$u.test.isEmpty(agenterId)) {
  412. datas.agenterId = agenterId
  413. }
  414. let result = await this.$u.api.user.login(datas);
  415. if (result) {
  416. this.userId = result.id;
  417. uni.setStorageSync("userId", result.id);
  418. }
  419. }
  420. },
  421. }
  422. }
  423. </script>
  424. <style lang="scss">
  425. page {
  426. background-color: #FFFFFF;
  427. }
  428. .goods {
  429. padding-bottom: 20rpx;
  430. border-bottom: 1rpx solid #efefef;
  431. .title {
  432. padding-top: 10rpx;
  433. margin-left: 20rpx;
  434. font-size: 32rpx;
  435. color: #363636;
  436. }
  437. }
  438. </style>