You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

398 lines
9.4 KiB

1 month ago
  1. <template>
  2. <view class="confrim-container">
  3. <view class="content">
  4. <view class="confrim-tips">
  5. <img src="/static/images/details/tips.svg" alt="" style="width: 12px;height: 12px;margin-right: 5px;">
  6. <text>如需取消请查看详情页的退改政策或咨询服务人员</text>
  7. </view>
  8. <view class="confirm-form">
  9. <uni-forms ref="baseForm" :modelValue="confirmData" label-position="top">
  10. <uni-forms-item>
  11. <label slot="label" class="form-label">手机号<span
  12. style="color: #FF3D3D;margin-left: 4px;">*</span></label>
  13. <uni-easyinput v-model="confirmData.phone" placeholder="请输入您的手机号以便我们联系您" />
  14. </uni-forms-item>
  15. <!-- <uni-forms-item>
  16. <label slot="label" class="form-label">微信号</label>
  17. <uni-easyinput v-model="confirmData.wechatId" placeholder="请输入您的微信号以便我们联系您" />
  18. </uni-forms-item> -->
  19. <uni-forms-item>
  20. <label slot="label" class="form-label">备注</label>
  21. <uni-easyinput v-model="confirmData.note" placeholder="请输入您的备注信息" />
  22. </uni-forms-item>
  23. </uni-forms>
  24. </view>
  25. <view class="content-container">
  26. <view class="normal-bolb-text">
  27. 价格明细
  28. </view>
  29. <view class="price-details">
  30. <view v-for="(item,index) in itemPrices" class="price-details-for" :key="index">
  31. <view class="normal-text">
  32. {{item.itemType}}
  33. </view>
  34. <view class="price-calculate">
  35. {{item.price}} x {{item.quantity}} {{item.unit}}
  36. <text style="color: #FF530A; margin-left:4px"> = {{item.price*item.quantity}}</text>
  37. </view>
  38. <view class="line" style="background-color: #FFE8C6;"></view>
  39. </view>
  40. <view class="price-details-for">
  41. <view class="normal-text">
  42. {{currentMember.itemType}}
  43. </view>
  44. <view class="price-calculate" style="color: #FF530A;">
  45. -{{submitData.totalPrice * currentMember.discount}}
  46. </view>
  47. </view>
  48. </view>
  49. </view>
  50. </view>
  51. <view class="payment">
  52. <view class="details-radio" style="width: 100%;padding-bottom: 10px;">
  53. <label class="details-radio" @click="changeAgree">
  54. <radio style="transform:scale(0.5);" color="#FFB13F" activeBorderColor="#FFB13F"
  55. activeBackgroundColor="#FFB13F" :checked="isAgree" />
  56. 我同意
  57. </label>
  58. <text class="details-agreement" @click="checkAgreement">猫妈狗爸用户服务协议和隐私协议</text>
  59. </view>
  60. <view class="total-price">
  61. <text class="total-price-text">应付价格</text>
  62. <text class="total-price-value">{{submitData.totalPrice * (1-(currentMember.discount?currentMember.discount:0))}}</text>
  63. </view>
  64. <button class="payment-btn" :loading="loading" @click="payment"> {{loading?'下单中':'支付'}}</button>
  65. </view>
  66. <Kefu></Kefu>
  67. </view>
  68. </template>
  69. <script>
  70. import Kefu from '../common/kefu.vue'
  71. import {
  72. getOpenId,
  73. createOrder
  74. } from '@/api/system/user.js'
  75. import { getToken,getOpenIdKey,setOpenIdKey } from '@/utils/auth'
  76. import {getPersonalInfo} from "@/api/system/personal.js"
  77. export default {
  78. data() {
  79. return {
  80. loading:false,
  81. totalPrice: 0,
  82. confirmData: {
  83. phone: "",
  84. wechatId: "",
  85. note: "",
  86. },
  87. submitData: {},
  88. itemPrices: [],
  89. isAgree: false,
  90. isPaying: false,
  91. openIdString: '',
  92. currentMember:{},
  93. memberDiscountList:[
  94. {
  95. itemType:"新晋家长9.5折优惠",
  96. discount:0.05
  97. },
  98. {
  99. itemType:"普卡会员9折优惠",
  100. discount:0.1
  101. },
  102. {
  103. itemType:"银卡会员8.8折优惠",
  104. discount:0.12
  105. },
  106. {
  107. itemType:"银卡会员8.5折优惠",
  108. discount:0.15
  109. }
  110. ]
  111. }
  112. },
  113. components:{
  114. Kefu
  115. },
  116. onLoad() {
  117. if (getToken() && getOpenIdKey()) {
  118. this.getPersonalInfo()
  119. }
  120. this.submitData = this.$globalData.submitData;
  121. this.itemPrices = [...this.$globalData.servicePrices, ...this.$globalData.itemPrices];
  122. this.confirmData = this.$globalData.confirmData;
  123. },
  124. methods: {
  125. payment() {
  126. if (!this.confirmData.phone) {
  127. this.$modal.showToast('请输入手机号');
  128. return;
  129. }
  130. const phoneNumberRegex = /^1[3456789]\d{9}$/
  131. if (!phoneNumberRegex.test(this.confirmData.phone)) {
  132. this.$modal.showToast('请输入正确的手机号');
  133. return;
  134. }
  135. if (!this.isAgree) {
  136. this.$modal.showToast('请阅读并同意《猫妈狗爸用户服务协议和隐私协议》');
  137. return;
  138. }
  139. if (this.openIdString) {
  140. this.setSubmitData(this.openIdString)
  141. } else {
  142. this.loading=true
  143. uni.login({
  144. provider: 'weixin',
  145. success: (loginRes) => {
  146. this.getOpenId(loginRes.code)
  147. },
  148. fail: function(error) {
  149. this.loading=false
  150. // 授权失败处理
  151. uni.showToast('授权失败,请授权后再试')
  152. }
  153. });
  154. }
  155. },
  156. getOpenId(code) {
  157. getOpenId(code).then(res => {
  158. if (res.code == 200 && res.data) {
  159. this.openIdString = JSON.parse(res.data).openId;
  160. this.$globalData.openIdStr = this.openIdString;
  161. setOpenIdKey(this.openIdString)
  162. this.throttle(this.setSubmitData(this.openIdString),1000)
  163. }else{
  164. this.loading=false
  165. }
  166. })
  167. },
  168. setSubmitData(openId) {
  169. this.submitData.phone = this.confirmData.phone;
  170. this.submitData.wechatId = this.confirmData.wechatId;
  171. this.submitData.note = this.confirmData.note;
  172. this.submitData.openId = openId;
  173. this.submitData.skuList = [...this.$globalData.mainSku, ...this.$globalData.augmentedSku]
  174. console.log(this.submitData);
  175. createOrder(this.submitData).then(res => {
  176. if (res.code == 200) {
  177. this.pay(res.data)
  178. } else {
  179. this.$modal.showToast('创建订单失败,请重试');
  180. this.loading=false
  181. }
  182. })
  183. // uni.navigateTo({
  184. // url:'/pages/details/successful'
  185. // });
  186. },
  187. pay(params) {
  188. if (this.isPaying) {
  189. return;
  190. }
  191. this.isPaying = true
  192. uni.requestPayment({
  193. provider: 'wxpay',
  194. timeStamp: params.timeStamp,
  195. nonceStr: params.nonceStr,
  196. package: params.package_,
  197. signType: params.signType,
  198. paySign: params.paySign,
  199. success: (res) => {
  200. this.$modal.showToast('支付成功')
  201. uni.navigateTo({
  202. url: '/pages/details/successful'
  203. });
  204. },
  205. fail: (err) => {
  206. this.loading=false
  207. console.log('支付失败', err)
  208. this.$modal.showToast('支付失败')
  209. },
  210. complete: () => {
  211. this.loading=false
  212. this.isPaying = false
  213. }
  214. })
  215. },
  216. changeAgree() {
  217. console.log(this.isAgree);
  218. if (this.isAgree) {
  219. this.isAgree = false
  220. } else {
  221. this.isAgree = true
  222. }
  223. },
  224. checkAgreement() {
  225. uni.navigateTo({
  226. url: '/pages/details/agreement'
  227. });
  228. },
  229. getPersonalInfo(){
  230. getPersonalInfo().then(res=>{
  231. if(res&&(res.id || res.id === 0)){
  232. let userLevel=res.level
  233. this.currentMember = this.memberDiscountList.find(item=>{
  234. if(item.itemType.includes(userLevel)){
  235. return item
  236. }
  237. })
  238. }
  239. })
  240. },
  241. // 节流
  242. throttle(func, delay) {
  243. let lastCall = 0;
  244. return function(...args) {
  245. const now = new Date().getTime();
  246. if (now - lastCall < delay) {
  247. return;
  248. }
  249. lastCall = now;
  250. func(...args);
  251. }
  252. }
  253. }
  254. }
  255. </script>
  256. <style lang="scss">
  257. .confrim-container {
  258. background-color: #F5F5F7;
  259. position: relative;
  260. height: 100%;
  261. padding-bottom: 90px;
  262. .confrim-tips {
  263. height: 36px;
  264. width: 100%;
  265. display: flex;
  266. justify-content: center;
  267. align-items: center;
  268. color: #A94F20;
  269. font-size: 10px;
  270. background-color: #FFF8DF;
  271. }
  272. .confirm-form {
  273. padding: 18px 20px;
  274. background-color: #ffffff;
  275. .form-label {
  276. color: #333;
  277. font-size: 16px;
  278. line-height: 16px;
  279. margin-bottom: 10px;
  280. font-weight: bold;
  281. display: flex;
  282. align-items: center;
  283. }
  284. }
  285. .content-container {
  286. margin-top: 10px;
  287. background-color: #ffffff;
  288. padding: 14px 20px;
  289. }
  290. .normal-bolb-text {
  291. font-size: 16px;
  292. font-weight: bold;
  293. line-height: 16px;
  294. color: #333;
  295. margin-bottom: 14px;
  296. }
  297. .normal-text {
  298. font-size: 14px;
  299. color: #A94F20;
  300. }
  301. .price-details {
  302. padding: 10px 20px;
  303. background-color: #FFFCF2;
  304. border: 1px solid #FFE8C6;
  305. border-radius: 4px;
  306. .price-details-for {
  307. display: flex;
  308. justify-content: space-between;
  309. align-items: center;
  310. flex-wrap: wrap;
  311. }
  312. .price-calculate {
  313. font-size: 14px;
  314. color: #999;
  315. }
  316. .line {
  317. height: 1px;
  318. width: 100%;
  319. margin: 10px 0;
  320. }
  321. }
  322. .payment {
  323. height: 90px;
  324. position: fixed;
  325. bottom: 0;
  326. width: 100%;
  327. padding: 10px 20px;
  328. background-color: #ffffff;
  329. display: flex;
  330. justify-content: space-between;
  331. align-items: center;
  332. flex-wrap: wrap;
  333. .total-price-text {
  334. color: #333;
  335. font-size: 16px;
  336. font-weight: blob;
  337. line-height: 16px;
  338. }
  339. .total-price-value {
  340. color: #FF530A;
  341. font-size: 22px;
  342. font-weight: blob;
  343. line-height: 16px;
  344. }
  345. .payment-btn {
  346. width: 140px;
  347. height: 38px;
  348. border-radius: 6px;
  349. background: #FFB13F;
  350. color: #fff;
  351. font-size: 16px;
  352. margin: 0;
  353. display: flex;
  354. align-items: center;
  355. justify-content: center;
  356. }
  357. }
  358. .details-radio {
  359. display: flex;
  360. justify-content: center;
  361. align-items: center;
  362. color: #858585;
  363. font-size: 14px;
  364. line-height: 16px;
  365. /* 133.333% */
  366. .details-agreement {
  367. color: #A94F20;
  368. }
  369. }
  370. }
  371. </style>