index.vue 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942
  1. <template>
  2. <!-- 不同类型进入的loadType(1:学校课程;2:体育馆课程;3:教练课程) -->
  3. <view class="content">
  4. <view class="g-orderinfo-card">
  5. <view class="g-shoping-info" v-if="previewCourseInfo">
  6. <image class="shoping-img" :src="previewCourseInfo.cover" mode=""></image>
  7. <view class="shoping-info">
  8. <view class="name">{{ previewCourseInfo.placeName||previewCourseInfo.name }}</view>
  9. <view class="price-info">
  10. <view class="price"><text class="mini-text">¥</text>{{ previewCourseInfo.sellingPrice.toFixed(2) }}</view>
  11. <view class="price-stepper">
  12. <view class="minus" @click="minusNum">-</view>
  13. <input v-model="countTotal" disabled type="number" />
  14. <view class="add" @click="addNum">+</view>
  15. </view>
  16. </view>
  17. </view>
  18. </view>
  19. <view class="g-shoping-total">
  20. <view class="total-price">
  21. <view class="">商品总价(共1件)</view>
  22. <view class="">¥{{ previewCourseInfo.sellingPrice.toFixed(2) }}</view>
  23. </view>
  24. <view class="total-price">
  25. <view class="">
  26. <text v-if="buyType == 1">试听优惠</text>
  27. <text v-if="buyType == 0 || placeId">团购优惠</text>
  28. </view>
  29. <view class="">-¥
  30. <text v-if="buyType == 0 || !placeId">{{ previewCourseInfo.discountPrice }}</text>
  31. <text v-else>{{ (previewCourseInfo.originalPrice - previewCourseInfo.sellingPrice).toFixed(2) }}</text>
  32. </view>
  33. </view>
  34. </view>
  35. <view class="subtotal">小计 ¥{{totalPriceDisplay }}</view>
  36. </view>
  37. <!-- 课程进入 -->
  38. <view class="r-insurance" v-for="item in insureIdList" :key="item.id">
  39. <view class="r-insurance-infobox">
  40. <view class="r-image-box">
  41. <image :src="item.coverImg" mode=""></image>
  42. </view>
  43. <view class="r-insurance-title">
  44. <view class="r-insurance-name">
  45. <view class="r-name">{{ item.name }}</view>
  46. <view class="r-tags">不支持退款</view>
  47. </view>
  48. <view class="r-insurance-desc" v-for="(desc, index) in item.insuranceObvious" :key="index">
  49. <text v-for="([key, value], idx) in Object.entries(desc)" :key="key + idx">{{ key }}, {{
  50. value }};</text>
  51. </view>
  52. <view class="r-insurance-type">保险公司:{{ item.insuranceName_dictText }}</view>
  53. <view class="r-insurance-price">
  54. <view class="r-price">¥{{ insurePrice }}/天·人</view>
  55. <view class="r-insurance-btn" v-if="insureData.length < 1"
  56. @click="gotoInsuracePage(item, item.priceDataList)">去投保
  57. </view>
  58. </view>
  59. </view>
  60. </view>
  61. <view class="line" v-if="insureData.length > 0"></view>
  62. <blcok v-if="insureData.length > 0">
  63. <view class="r-insurance-adduser" v-for="(insureUser, index) in insureData" :key="index">
  64. <view class="r-adduser-btn">
  65. <view class="r-celar" @click="clearUser">清除</view>
  66. <view class="r-edit"
  67. @click="RouterUtils.to_page(`/pages/index/insure/index?priceDataList=${JSON.stringify(item.priceDataList)}`)">
  68. 修改</view>
  69. </view>
  70. <view class="r-userinfo-list">
  71. <view class="r-userinfo-item">
  72. <view class="r-item-title">被保人</view>
  73. <view class="r-item-info">{{ insureUser.userData.length }}人(<text
  74. v-for="user in insureUser.userData" :key="user.id">{{ user.fullName }},</text>)
  75. </view>
  76. </view>
  77. <view class="r-userinfo-item">
  78. <view class="r-item-title">生效时间</view>
  79. <view class="r-item-info">{{ insureUser.slectObj.day }}天({{ insureUser.startDate }}-{{
  80. insureUser.endDate }})
  81. </view>
  82. </view>
  83. <view class="r-userinfo-item">
  84. <view class="r-item-title">保费总金额</view>
  85. <view class="r-item-info">¥{{ insureUser.totalPrice }}</view>
  86. </view>
  87. </view>
  88. </view>
  89. </blcok>
  90. </view>
  91. <view class="g-userinfo-card" v-if="!placeId">
  92. <view class="r-user">
  93. <view class="user-title">用户信息 <text class="mini-text">至少需选择{{ countTotal }}人</text></view>
  94. <view class="invite">
  95. <zzx-icon name="wechat" size="16"></zzx-icon>
  96. <view style="margin-bottom: 8rpx;">邀请微信好友</view>
  97. <zzx-icon name="ashRight" size="12"></zzx-icon>
  98. <button class="g-share-btn" open-type="share"></button>
  99. </view>
  100. </view>
  101. <!-- <view class="user-tags">张三</view> -->
  102. <view class="r-user-list" v-for="item in userData" :key="item.id">
  103. <view class="minus-user" @click="deleteUser(item)">-</view>
  104. <view class="r-list">
  105. <view class="name">{{ item.fullName }}</view>
  106. <view class="id-num">身份证 {{ idCardHide(item.identityCard) }}</view>
  107. </view>
  108. </view>
  109. <view class="g-adduser-btn" @click="toUserList">
  110. <view class="add-icon">+</view>
  111. <view class="add-text">添加用户</view>
  112. </view>
  113. </view>
  114. <view class="g-usetips-card">
  115. <view class="use-title">{{ placeId ? '使用须知' : '购买须知' }}</view>
  116. <view class="use-text">
  117. <view class="item-text">
  118. <rich-text :nodes="previewCourseInfo.reminder"></rich-text>
  119. </view>
  120. </view>
  121. <view class="use-tips-more" @click="RouterUtils.to_page('/pages/index/useNotice/index')">
  122. <view class="more-text">查看更多</view>
  123. <view class="use-line"></view>
  124. </view>
  125. </view>
  126. <view class="g-usetips-card">
  127. <view class="use-title">服务保障</view>
  128. <view class="use-text">
  129. <view class="item-text">
  130. {{ previewCourseInfo.refundType == 1 ? '未消费随时退款,过期未消费自动退款。' : '不支退款,请慎重考虑后购买。' }}
  131. </view>
  132. </view>
  133. <view class="use-tips-more" @click="RouterUtils.to_page('/pages/index/useNotice/index')">
  134. <view class="more-text">查看更多</view>
  135. <view class="use-line"></view>
  136. </view>
  137. </view>
  138. <view style="height: 166rpx;"></view>
  139. <view class="footer footer-box">
  140. <view class="footer-price">
  141. <view class="total-price">合计:</view>
  142. <view class="price"><text class="mini-text">¥</text>
  143. <text>{{ totalPriceDisplay }}</text>
  144. </view>
  145. <view class="discount">优惠¥{{ previewCourseInfo.totalDiscount }}</view>
  146. </view>
  147. <view class="footer-btn" @click="submitOrder">
  148. <button>
  149. <view class="btn-price">
  150. <text> ¥{{ totalPriceDisplay }}</text>
  151. </view>
  152. <view class="btn-price">立即支付</view>
  153. </button>
  154. </view>
  155. </view>
  156. </view>
  157. <uni-popup ref="insurePopup" type="center">
  158. <view class="r-center-popup" v-if="agreementContent">
  159. <view class="r-popup-title">{{ agreementContent.protocolName }}</view>
  160. <view class="r-popup-content">
  161. <rich-text :nodes="agreementContent.protocolContent"></rich-text>
  162. </view>
  163. <view class="r-popup-footer">
  164. <view class="r-popup-needbtn" @click="toNeed">我需要购买保险</view>
  165. <view class="r-popup-refusebtn" @click="toRefuse">我拒绝购买保险</view>
  166. <view class="r-popup-checkbox" @click="select_insurance = !select_insurance">
  167. <zzx-icon :name="select_insurance ? 'selected' : 'unchecked'" size="14"></zzx-icon>
  168. <text>我已认真阅读及确认</text>
  169. </view>
  170. </view>
  171. </view>
  172. </uni-popup>
  173. </template>
  174. <script lang="ts" setup>
  175. import { ref, onMounted, computed } from 'vue';
  176. import { onLoad } from '@dcloudio/uni-app';
  177. import { RouterUtils, TipsUtils, idCardHide } from '@/utils/util';
  178. import { http } from '@/utils/http'
  179. const insurePopup = ref()
  180. const select_insurance = ref(false)
  181. const loadType = ref(1)
  182. const buyType = ref()
  183. const placeId = ref()
  184. onLoad((options) => {
  185. console.log(options);
  186. loadType.value = options.type
  187. courseId.value = options.courseId
  188. placeId.value = options.placeId
  189. buyType.value = options.buyType
  190. orderFormData.value.type = options.orderType
  191. orderFormData.value.orFreeOrder = options.buyType
  192. orderFormData.value.amount = 1
  193. })
  194. // 优化价格计算,合并保险价格
  195. const totalPrice = computed(() => {
  196. let basePrice = 0;
  197. if (previewCourseInfo.value) {
  198. if (previewCourseInfo.value.totalPrice) {
  199. basePrice = Number(previewCourseInfo.value.totalPrice) * Number(countTotal.value);
  200. } else if (previewCourseInfo.value.sellingPrice) {
  201. basePrice = Number(previewCourseInfo.value.sellingPrice) * Number(countTotal.value);
  202. }
  203. }
  204. let insureTotal = 0;
  205. if (Array.isArray(insureData.value) && insureData.value.length > 0) {
  206. insureTotal = insureData.value.reduce((sum, item) => {
  207. const price = Number(item.totalPrice) || 0;
  208. return sum + price;
  209. }, 0);
  210. }
  211. return basePrice + insureTotal;
  212. });
  213. const totalPriceDisplay = computed(() => {
  214. return totalPrice.value.toFixed(2);
  215. });
  216. onMounted(() => {
  217. if (placeId.value) {
  218. getEventsDetail()
  219. } else {
  220. get_previewOrderCourse()
  221. }
  222. get_userData()
  223. getInsureData()
  224. })
  225. const toUserList = () => {
  226. RouterUtils.to_page('/pages/index/userList/index')
  227. }
  228. const userData = ref([])
  229. const get_userData = () => {
  230. uni.$on('userData', function (data) {
  231. userData.value = data
  232. if (data.length > 0) {
  233. let familyIds = data.map(item => item.id)
  234. orderFormData.value.familyIds = familyIds.join(',')
  235. } else {
  236. orderFormData.value.familyIds = []
  237. }
  238. })
  239. }
  240. const deleteUser = async (e) => {
  241. let res = await TipsUtils.tips_alert('确定删除该用户吗?', true)
  242. if (res.confirm) {
  243. userData.value = userData.value.filter(user => user.id !== e.id)
  244. }
  245. }
  246. const priceDataListData = ref([])
  247. const gotoInsuracePage = (e1: any, e2: any) => {
  248. getFindByType(e1.insuranceName)
  249. priceDataListData.value = e2
  250. orderFormData.value.insureOrderInfoForm.insureId = e1.id
  251. }
  252. const agreementContent = ref()
  253. const getFindByType = (insuranceName: any) => {
  254. http.get('/my/feedback/findByType', { data: { insuranceName: insuranceName, protocolType: 0 }, loading: true }).then((res: any) => {
  255. agreementContent.value = res.result
  256. insurePopup.value.open()
  257. })
  258. }
  259. const courseId = ref()
  260. const previewCourseInfo = ref()
  261. const insureIdList = ref([]) // 保险列表
  262. const insurePrice = ref() // 保险价格
  263. // 课程预览
  264. const get_previewOrderCourse = () => {
  265. http.get('/order/previewOrderCourse', { data: { courseId: courseId.value }, loading: true }).then((res) => {
  266. previewCourseInfo.value = res.result
  267. orderFormData.value.productIds = res.result.id
  268. res.result.insureIdList.map((item: any) => {
  269. item.insuranceObvious = JSON.parse(item.insuranceObvious)
  270. item.insuranceObvious = [item.insuranceObvious]
  271. item.priceDataList.map((item2: any) => {
  272. if (item2.insureDay === 1) {
  273. insurePrice.value = item2.insurePrice
  274. }
  275. })
  276. })
  277. insureIdList.value = res.result.insureIdList
  278. })
  279. }
  280. // 场地预览
  281. const getEventsDetail = () => {
  282. http.get('/order/PreviewOrderPlaceGymnasiumNoFixation', { data: { placeId: placeId.value }, loading: true }).then((res) => {
  283. previewCourseInfo.value = res.result
  284. orderFormData.value.productIds = res.result.id || res.result.placeId
  285. })
  286. }
  287. const insureData = ref([])
  288. const getInsureData = () => {
  289. uni.$on('insureData', function (data) {
  290. insureData.value = data
  291. console.log(insureData.value, '投保人信息');
  292. orderFormData.value.insureOrderInfoForm.assertStartTime = insureData.value[0].startDate
  293. orderFormData.value.insureOrderInfoForm.assertEndTime = insureData.value[0].endDate
  294. orderFormData.value.insureOrderInfoForm.insurePriceId = insureData.value[0].slectObj.id
  295. if (data.length > 0) {
  296. let familyMembersIds = data[0].userData.map(item => item.id)
  297. orderFormData.value.insureOrderInfoForm.familyMembersIds = familyMembersIds.join(',')
  298. } else {
  299. orderFormData.value.insureOrderInfoForm.familyMembersIds = []
  300. }
  301. })
  302. }
  303. const clearUser = async () => {
  304. let res: any = await TipsUtils.tips_alert('确定清除投保人信息吗?', true)
  305. if (res.confirm) {
  306. insureData.value = []
  307. }
  308. }
  309. const countTotal = ref(1)
  310. const minusNum = () => {
  311. if (countTotal.value > 1) {
  312. countTotal.value--
  313. orderFormData.value.amount = countTotal.value
  314. }
  315. }
  316. const addNum = () => {
  317. if (buyType.value == 1) return TipsUtils.tips_toast('试听课程不支持多个购买')
  318. if(courseId.value){
  319. get_checkCourseLimitNum(countTotal.value + 1)
  320. }else{
  321. countTotal.value++
  322. }
  323. }
  324. const get_checkCourseLimitNum = (targetNum) => {
  325. http.get('/order/checkCourseLimitNum', {
  326. data: {
  327. courseId: courseId.value,
  328. limitNum: targetNum
  329. },
  330. loading: true
  331. }).then((res) => {
  332. if (res.result === true) {
  333. countTotal.value = targetNum
  334. } else {
  335. TipsUtils.tips_toast('超出可购数量')
  336. }
  337. })
  338. }
  339. const toNeed = () => {
  340. if (!select_insurance.value) return TipsUtils.tips_toast('请先阅读并同意协议')
  341. RouterUtils.to_page(`/pages/index/insure/index?priceDataList=${JSON.stringify(priceDataListData.value)}`)
  342. insurePopup.value.close()
  343. }
  344. const toRefuse = () => {
  345. if (select_insurance.value) {
  346. insurePopup.value.close()
  347. } else {
  348. TipsUtils.tips_toast('请先阅读并同意协议')
  349. }
  350. }
  351. let orderFormData = ref({
  352. type: null,
  353. orderType: null,
  354. orFreeOrder: 1,
  355. productIds: null,
  356. amount: null,
  357. familyIds: '',
  358. insureOrderInfoForm: {
  359. insureId: '',
  360. assertStartTime: '',
  361. assertEndTime: '',
  362. insurePriceId: '',
  363. familyMembersIds: '',
  364. }
  365. })
  366. const submitOrder = () => {
  367. orderFormData.value.amount = countTotal.value
  368. if (!placeId.value) {
  369. if (!userData.value) return TipsUtils.tips_toast('请添加用户信息')
  370. if (userData.value.length < countTotal.value) return TipsUtils.tips_toast(`请至少选择${countTotal.value}人`)
  371. if(userData.value.length > countTotal.value) return TipsUtils.tips_toast(`最多选择${countTotal.value}人`)
  372. orderFormData.value.orderType = 5
  373. orderFormData.value.type = 2
  374. } else {
  375. orderFormData.value.type = 0
  376. orderFormData.value.orderType = 2
  377. }
  378. let data = { ...orderFormData.value };
  379. if (!insureData.value || insureData.value.length === 0) {
  380. delete data.insureOrderInfoForm;
  381. }
  382. if(!userData||userData.value.length === 0){
  383. delete data.familyIds
  384. }
  385. http.post('/order/createOrder', data, { loading: true }).then((res) => {
  386. RouterUtils.to_page(`/pages/index/toBeUsed/index?orderId=${res.result.orderId}&orderType=${orderFormData.value.orderType}`)
  387. })
  388. }
  389. </script>
  390. <style lang="less" scoped>
  391. .g-orderinfo-card {
  392. background: #FFFFFF;
  393. border-radius: 32rpx;
  394. padding: 20rpx;
  395. margin-top: 20rpx;
  396. .g-shoping-info {
  397. display: flex;
  398. align-items: center;
  399. gap: 20rpx;
  400. .shoping-img {
  401. width: 200rpx;
  402. height: 200rpx;
  403. border-radius: 32rpx;
  404. }
  405. .shoping-info {
  406. width: 440rpx;
  407. .name {
  408. font-weight: 800;
  409. font-size: 32rpx;
  410. color: #222222;
  411. line-height: 44rp
  412. }
  413. .price-info {
  414. display: flex;
  415. align-items: center;
  416. justify-content: space-between;
  417. margin-top: 26rpx;
  418. .price {
  419. font-weight: 800;
  420. font-size: 48rpx;
  421. color: #FB5B5B;
  422. }
  423. .price-stepper {
  424. display: flex;
  425. align-items: center;
  426. border: 1rpx solid #F0F0F0;
  427. border-radius: 8rpx;
  428. .minus {
  429. text-align: center;
  430. width: 44rpx;
  431. border-right: 1rpx solid #F0F0F0;
  432. }
  433. &>input {
  434. width: 80rpx;
  435. font-size: 28rpx;
  436. color: #222222;
  437. text-align: center;
  438. }
  439. .add {
  440. text-align: center;
  441. width: 44rpx;
  442. border-left: 1rpx solid #F0F0F0;
  443. }
  444. }
  445. }
  446. }
  447. }
  448. .g-shoping-total {
  449. height: 148rpx;
  450. margin-top: 24rpx;
  451. border-top: 1rpx solid #F0F0F0;
  452. .total-price {
  453. margin-top: 24rpx;
  454. display: flex;
  455. align-items: center;
  456. justify-content: space-between;
  457. font-size: 28rpx;
  458. color: #222222;
  459. }
  460. }
  461. .subtotal {
  462. border-top: 1rpx solid #F0F0F0;
  463. height: 84rpx;
  464. line-height: 84rpx;
  465. font-weight: bold;
  466. font-size: 28rpx;
  467. color: #FB5B5B;
  468. text-align: right;
  469. }
  470. }
  471. .g-buy-tips {
  472. margin-top: 20rpx;
  473. .tips-title {
  474. font-weight: bold;
  475. font-size: 32rpx;
  476. color: #222222;
  477. }
  478. .tips-info-card {
  479. background: #FFFFFF;
  480. border-radius: 32rpx;
  481. padding: 20rpx;
  482. margin-top: 20rpx;
  483. .title {
  484. font-weight: bold;
  485. font-size: 28rpx;
  486. color: #222222;
  487. }
  488. .text {
  489. font-size: 24rpx;
  490. color: #AAAAAA;
  491. margin-top: 20rpx;
  492. margin-bottom: 20rpx;
  493. }
  494. }
  495. }
  496. .r-insurance {
  497. margin-top: 20rpx;
  498. padding: 20rpx;
  499. background: #FFFFFF;
  500. border-radius: 32rpx;
  501. .r-insurance-infobox {
  502. display: flex;
  503. align-items: center;
  504. justify-content: space-between;
  505. gap: 20rpx;
  506. margin-bottom: 20rpx;
  507. .r-image-box {
  508. &>image {
  509. width: 200rpx;
  510. height: 200rpx;
  511. border-radius: 32rpx;
  512. }
  513. }
  514. .r-insurance-title {
  515. .r-insurance-name {
  516. display: flex;
  517. align-items: center;
  518. gap: 16rpx;
  519. .r-name {
  520. font-weight: 800;
  521. font-size: 28rpx;
  522. color: #222222;
  523. }
  524. .r-tags {
  525. width: 136rpx;
  526. height: 36rpx;
  527. background: #FDD143;
  528. border-radius: 8rpx;
  529. font-size: 22rpx;
  530. color: #222222;
  531. text-align: center;
  532. line-height: 36rpx;
  533. }
  534. }
  535. .r-insurance-desc {
  536. width: 440rpx;
  537. margin-top: 10rpx;
  538. font-size: 24rpx;
  539. color: #AAAAAA;
  540. }
  541. .r-insurance-type {
  542. margin-top: 10rpx;
  543. font-size: 24rpx;
  544. color: #AAAAAA;
  545. }
  546. .r-insurance-price {
  547. display: flex;
  548. align-items: center;
  549. justify-content: space-between;
  550. .r-price {
  551. font-weight: bold;
  552. font-size: 28rpx;
  553. color: #FB5B5B;
  554. }
  555. .r-insurance-btn {
  556. width: 200rpx;
  557. height: 68rpx;
  558. background: #C8FF0C;
  559. border-radius: 60rpx;
  560. font-weight: bold;
  561. font-size: 28rpx;
  562. color: #222222;
  563. text-align: center;
  564. line-height: 68rpx;
  565. }
  566. }
  567. }
  568. }
  569. .r-insurance-adduser {
  570. background: #F6F6F6;
  571. border-radius: 32rpx;
  572. padding: 20rpx;
  573. margin-top: 20rpx;
  574. .r-adduser-btn {
  575. display: flex;
  576. align-items: center;
  577. justify-content: flex-end;
  578. gap: 20rpx;
  579. .r-celar {
  580. width: 192rpx;
  581. height: 60rpx;
  582. background: #FFFFFF;
  583. border-radius: 60rpx;
  584. border: 2rpx solid #FB5B5B;
  585. font-weight: bold;
  586. font-size: 28rpx;
  587. color: #FB5B5B;
  588. text-align: center;
  589. line-height: 68rpx;
  590. }
  591. .r-edit {
  592. width: 200rpx;
  593. height: 68rpx;
  594. background: #C8FF0C;
  595. border-radius: 60rpx;
  596. font-weight: bold;
  597. font-size: 28rpx;
  598. color: #222222;
  599. text-align: center;
  600. line-height: 68rpx;
  601. }
  602. }
  603. .r-userinfo-list {
  604. .r-userinfo-item {
  605. display: flex;
  606. align-items: center;
  607. justify-content: space-between;
  608. margin-top: 20rpx;
  609. .r-item-title {
  610. font-size: 28rpx;
  611. color: #AAAAAA;
  612. }
  613. .r-item-info {
  614. font-size: 28rpx;
  615. color: #222222;
  616. }
  617. }
  618. }
  619. }
  620. }
  621. .g-userinfo-card {
  622. margin-top: 20rpx;
  623. padding: 20rpx;
  624. background: #FFFFFF;
  625. border-radius: 32rpx;
  626. .r-user {
  627. display: flex;
  628. align-items: center;
  629. justify-content: space-between;
  630. .user-title {
  631. font-weight: bold;
  632. font-size: 28rpx;
  633. color: #222222;
  634. }
  635. .invite {
  636. display: flex;
  637. align-items: center;
  638. gap: 8rpx;
  639. font-size: 24rpx;
  640. color: #AAAAAA;
  641. position: relative;
  642. .g-share-btn {
  643. position: absolute;
  644. width: 200rpx;
  645. height: 60rpx;
  646. opacity: 0;
  647. }
  648. }
  649. }
  650. .user-tags {
  651. margin-top: 20rpx;
  652. width: 112rpx;
  653. height: 40rpx;
  654. background: #FDD143;
  655. border-radius: 8rpx;
  656. line-height: 40rpx;
  657. font-weight: bold;
  658. font-size: 28rpx;
  659. color: #222222;
  660. text-align: center;
  661. font-size: 28rpx;
  662. color: #222222;
  663. }
  664. .r-user-list {
  665. margin-top: 20rpx;
  666. display: flex;
  667. align-items: center;
  668. gap: 20rpx;
  669. border-top: 1rpx solid #F0F0F0;
  670. height: 140rpx;
  671. .minus-user {
  672. width: 30rpx;
  673. height: 30rpx;
  674. border-radius: 50%;
  675. background: #FB5B5B;
  676. text-align: center;
  677. line-height: 20rpx;
  678. font-weight: 600;
  679. color: #fff;
  680. font-size: 40rpx;
  681. }
  682. .r-list {
  683. .name {
  684. font-weight: bold;
  685. font-size: 28rpx;
  686. color: #222222;
  687. }
  688. .id-num {
  689. font-size: 28rpx;
  690. color: #222222;
  691. }
  692. }
  693. }
  694. .g-adduser-btn {
  695. display: flex;
  696. height: 88rpx;
  697. align-items: center;
  698. justify-content: center;
  699. gap: 20rpx;
  700. border-top: 1rpx solid #F0F0F0;
  701. .add-icon {
  702. width: 30rpx;
  703. height: 30rpx;
  704. border-radius: 50%;
  705. background: #FDD143;
  706. font-size: 30rpx;
  707. font-weight: 600;
  708. color: #fff;
  709. text-align: center;
  710. line-height: 20rpx;
  711. }
  712. .add-text {
  713. font-size: 28rpx;
  714. color: #FDD143;
  715. }
  716. }
  717. }
  718. .g-usetips-card {
  719. margin-top: 20rpx;
  720. padding: 20rpx;
  721. background: #FFFFFF;
  722. border-radius: 32rpx;
  723. .use-title {
  724. font-weight: bold;
  725. font-size: 28rpx;
  726. color: #222222;
  727. }
  728. .use-text {
  729. font-size: 24rpx;
  730. color: #222222;
  731. .item-text {
  732. margin-top: 20rpx;
  733. }
  734. }
  735. .use-tips-more {
  736. margin-top: 20rpx;
  737. .more-text {
  738. text-align: center;
  739. font-size: 24rpx;
  740. color: #CCCCCC;
  741. }
  742. .use-line {
  743. margin: auto;
  744. margin-top: 10rpx;
  745. width: 38rpx;
  746. height: 4rpx;
  747. background: #CCCCCC;
  748. border-radius: 2rpx;
  749. }
  750. }
  751. }
  752. .footer {
  753. left: 0;
  754. .footer-price {
  755. display: flex;
  756. align-items: center;
  757. .total-price {
  758. font-weight: bold;
  759. font-size: 28rpx;
  760. color: #222222;
  761. }
  762. .price {
  763. font-weight: 800;
  764. font-size: 48rpx;
  765. color: #FB5B5B;
  766. }
  767. .discount {
  768. margin-left: 10rpx;
  769. font-size: 24rpx;
  770. color: #222222;
  771. }
  772. }
  773. .footer-btn {
  774. &>button {
  775. width: 226rpx;
  776. height: 100rpx;
  777. background: #C8FF0C;
  778. border-radius: 60rpx;
  779. font-weight: bold;
  780. font-size: 26rpx;
  781. color: #222222;
  782. line-height: 30rpx;
  783. .btn-price:nth-child(1) {
  784. margin-top: 20rpx;
  785. }
  786. }
  787. &>button::after {
  788. border: none;
  789. }
  790. }
  791. }
  792. .r-center-popup {
  793. width: 646rpx;
  794. max-height: 1000rpx;
  795. background: #F6F6F6;
  796. border-radius: 32rpx;
  797. padding: 20rpx;
  798. .r-popup-title {
  799. font-weight: bold;
  800. font-size: 32rpx;
  801. color: #222222;
  802. text-align: center;
  803. }
  804. .r-popup-content {
  805. margin-top: 28rpx;
  806. font-size: 28rpx;
  807. color: #222222;
  808. max-height: 600rpx;
  809. overflow: auto;
  810. }
  811. .r-popup-footer {
  812. margin-top: 20rpx;
  813. .r-popup-needbtn {
  814. margin: auto;
  815. width: 598rpx;
  816. height: 100rpx;
  817. background: #C8FF0C;
  818. border-radius: 60rpx;
  819. font-weight: bold;
  820. font-size: 32rpx;
  821. color: #222222;
  822. text-align: center;
  823. line-height: 100rpx;
  824. }
  825. .r-popup-refusebtn {
  826. margin: auto;
  827. margin-top: 24rpx;
  828. width: 598rpx;
  829. height: 100rpx;
  830. background: #f0eeee;
  831. border-radius: 60rpx;
  832. font-weight: bold;
  833. font-size: 32rpx;
  834. color: #AAAAAA;
  835. text-align: center;
  836. line-height: 100rpx;
  837. }
  838. .r-popup-checkbox {
  839. margin-top: 20rpx;
  840. display: flex;
  841. align-items: center;
  842. justify-content: center;
  843. gap: 16rpx;
  844. font-size: 24rpx;
  845. color: #AAAAAA;
  846. &>text {
  847. margin-bottom: 8rpx;
  848. }
  849. }
  850. }
  851. }
  852. </style>