share.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. <template>
  2. <view class="share-page">
  3. <!-- Background -->
  4. <image src="/packet/static/share/bg.png" class="bg-image" mode="widthFix"></image>
  5. <!-- Main Content -->
  6. <view class="content-wrapper">
  7. <!-- Loop through share list -->
  8. <view class="card" v-for="(item, index) in shareList" :key="index">
  9. <!-- Header -->
  10. <view class="card-header">
  11. <text class="card-title">邀请好友同享最高可得{{ item.shareSumPrice }}元红包</text>
  12. <text class="card-time">{{ item.shareRedBagExpire }}</text>
  13. </view>
  14. <!-- Progress Section -->
  15. <view class="progress-section">
  16. <!-- Left Icon -->
  17. <image src="/packet/static/share/invite-text.png" class="left-icon" mode="heightFix"></image>
  18. <!-- Center Content -->
  19. <view class="center-content">
  20. <!-- Progress Bubble -->
  21. <view class="progress-bubble">
  22. <text>已领{{ item.shareGetNum || 0 }}元,最高还可得{{ (item.shareSumPrice || 0) - (item.shareGetNum || 0) }}元</text>
  23. </view>
  24. <!-- Progress Bar -->
  25. <view class="progress-bar-container">
  26. <view class="progress-line"></view>
  27. <view class="progress-dot" :style="{ left: getProgressPercent(item) + '%' }"></view>
  28. </view>
  29. <!-- Progress Labels -->
  30. <view class="progress-labels">
  31. <text class="label">邀请好友</text>
  32. <text class="label">好友领取</text>
  33. <text class="label">获得红包</text>
  34. </view>
  35. </view>
  36. <!-- Right Packet Icon -->
  37. <image src="/packet/static/share/red-packet.png" class="right-packet" mode="heightFix"></image>
  38. </view>
  39. <!-- Share/Detail Button -->
  40. <button class="btn-wrapper" open-type="share" :data-index="index" @getuserinfo="handleShare">
  41. <text class="btn-text">立即分享</text>
  42. </button>
  43. </view>
  44. </view>
  45. </view>
  46. </template>
  47. <script>
  48. export default {
  49. data() {
  50. return {
  51. shareList: [] // 分享列表数据
  52. }
  53. },
  54. onLoad() {
  55. // 获取分享列表
  56. this.getShareList();
  57. },
  58. onShareAppMessage(options) {
  59. console.log(options);
  60. // 从 options 中获取卡片索引
  61. const index = options?.target?.dataset?.index || 0;
  62. const item = this.shareList[index] || this.shareList[0];
  63. // 设置分享内容 - 使用对应卡片的数据
  64. return {
  65. title: '邀请好友同享最高可得' + (item?.shareSumPrice) + '元红包',
  66. path: '/packet/pages/share',
  67. imageUrl: '' // 使用默认分享图
  68. };
  69. },
  70. methods: {
  71. // 获取分享列表
  72. async getShareList() {
  73. try {
  74. const res = await this.$u.api.getShareRedBagListAjax();
  75. if (res.code === 200 || res.code === 0) {
  76. this.shareList = res.data || [];
  77. } else {
  78. uni.showToast({
  79. title: res.msg || '获取分享列表失败',
  80. icon: 'none'
  81. });
  82. }
  83. } catch (e) {
  84. console.error('获取分享列表失败:', e);
  85. uni.showToast({
  86. title: '网络错误',
  87. icon: 'none'
  88. });
  89. }
  90. },
  91. // 计算进度百分比
  92. getProgressPercent(item) {
  93. if (!item.shareNum || item.shareNum === 0) {
  94. return 0;
  95. }
  96. return (item.shareGetNum / item.shareNum) * 100;
  97. },
  98. // 格式化过期时间
  99. formatExpireTime(timeStr) {
  100. if (!timeStr) {
  101. return this.formatTime(new Date());
  102. }
  103. const date = new Date(timeStr);
  104. return this.formatTime(date);
  105. },
  106. // 格式化时间
  107. formatTime(date) {
  108. const year = date.getFullYear();
  109. const month = String(date.getMonth() + 1).padStart(2, '0');
  110. const day = String(date.getDate()).padStart(2, '0');
  111. const hours = String(date.getHours()).padStart(2, '0');
  112. const minutes = String(date.getMinutes()).padStart(2, '0');
  113. const seconds = String(date.getSeconds()).padStart(2, '0');
  114. return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
  115. },
  116. handleShare() {
  117. // 分享逻辑
  118. uni.showToast({
  119. title: '分享成功',
  120. icon: 'success'
  121. });
  122. },
  123. handleViewDetail() {
  124. // 查看详情逻辑
  125. uni.showToast({
  126. title: '查看详情',
  127. icon: 'none'
  128. });
  129. }
  130. }
  131. }
  132. </script>
  133. <style lang="scss" scoped>
  134. .share-page {
  135. height: 100vh;
  136. position: relative;
  137. display: flex;
  138. flex-direction: column;
  139. align-items: center;
  140. padding: 40rpx 30rpx;
  141. box-sizing: border-box;
  142. padding-top: 0;
  143. .bg-image {
  144. position: fixed;
  145. top: 0;
  146. left: 0;
  147. width: 100%;
  148. height: 100%;
  149. z-index: 0;
  150. }
  151. .content-wrapper {
  152. position: relative;
  153. z-index: 1;
  154. width: 100%;
  155. max-width: 700rpx;
  156. padding: 60rpx 0;
  157. margin-top: 350rpx;
  158. .card {
  159. background: #fff;
  160. border-radius: 24rpx;
  161. overflow: hidden;
  162. margin-bottom: 40rpx;
  163. .card-header {
  164. background: #03A65F;
  165. padding: 24rpx 30rpx;
  166. display: flex;
  167. justify-content: space-between;
  168. align-items: center;
  169. height: 79rpx;
  170. box-sizing: border-box;
  171. .card-title {
  172. font-size: 28rpx;
  173. font-weight: 600;
  174. color: #fff;
  175. flex: 1;
  176. }
  177. .card-time {
  178. font-size: 22rpx;
  179. color: rgba(255, 255, 255, 0.9);
  180. white-space: nowrap;
  181. margin-left: 20rpx;
  182. }
  183. }
  184. .progress-section {
  185. padding: 30rpx 50rpx;
  186. display: flex;
  187. align-items: center;
  188. gap: 20rpx;
  189. position: relative;
  190. .left-icon {
  191. width: 80rpx;
  192. height: 80rpx;
  193. flex-shrink: 0;
  194. position: absolute;
  195. top: 20%;
  196. left: 40rpx;
  197. }
  198. .center-content {
  199. flex: 1;
  200. display: flex;
  201. flex-direction: column;
  202. align-items: center;
  203. margin-top: 40rpx;
  204. .progress-bubble {
  205. background: #18B94E;
  206. padding: 12rpx 28rpx;
  207. border-radius: 30rpx;
  208. margin-bottom: 30rpx;
  209. margin-left: 10rpx;
  210. text {
  211. font-size: 24rpx;
  212. color: #fff;
  213. font-weight: 500;
  214. }
  215. }
  216. .progress-bar-container {
  217. position: relative;
  218. width: 100%;
  219. height: 15rpx;
  220. background: #BDFAAD;
  221. border-radius: 6rpx;
  222. margin-bottom: 16rpx;
  223. .progress-line {
  224. position: absolute;
  225. left: 0;
  226. top: 0;
  227. height: 100%;
  228. background: linear-gradient(90deg, #4CAF50 0%, #8BC34A 100%);
  229. border-radius: 6rpx;
  230. }
  231. .progress-dot {
  232. position: absolute;
  233. top: 50%;
  234. transform: translate(-50%, -50%);
  235. width: 32rpx;
  236. height: 32rpx;
  237. background: #fff;
  238. border-radius: 50%;
  239. box-shadow: 0 2rpx 8rpx rgba(76, 175, 80, 0.3);
  240. display: flex;
  241. align-items: center;
  242. justify-content: center;
  243. &::after {
  244. content: '';
  245. width: 24rpx;
  246. height: 24rpx;
  247. background: linear-gradient(135deg, #4CAF50 0%, #66BB6A 100%);
  248. border-radius: 50%;
  249. }
  250. }
  251. }
  252. .progress-labels {
  253. display: flex;
  254. justify-content: space-between;
  255. width: 100%;
  256. .label {
  257. font-size: 26rpx;
  258. color: #333;
  259. text-align: center;
  260. font-weight: 600;
  261. flex: 1;
  262. }
  263. }
  264. }
  265. .right-packet {
  266. width: 60rpx;
  267. height: 80rpx;
  268. flex-shrink: 0;
  269. position: absolute;
  270. top: 20%;
  271. right: 40rpx;
  272. }
  273. }
  274. .btn-wrapper {
  275. position: relative;
  276. width: 300rpx;
  277. height: 90rpx;
  278. margin: 0 auto 30rpx;
  279. background: url('/packet/static/share/share-btn.png') no-repeat center center;
  280. background-size: 100% 100%;
  281. display: flex;
  282. align-items: center;
  283. justify-content: center;
  284. border: none;
  285. padding: 0;
  286. line-height: normal;
  287. font-size: 0;
  288. &::after {
  289. border: none;
  290. }
  291. .btn-text {
  292. font-family: Adobe Heiti Std;
  293. font-size: 42rpx;
  294. color: #FFFFFF;
  295. text-align: center;
  296. }
  297. }
  298. }
  299. }
  300. }
  301. </style>