- 新增钱包流水功能,包括充值记录和支付记录展示 - 新增签到记录弹窗组件 - 优化小说详情页的订阅和阅读体验 - 修复修改个人信息页面签名字段不显示的问题 - 调整章节编辑页面的付费开关样式和大小 - 优化书架页面跳转逻辑,支持直接跳转到阅读记录章节 - 修复任务中心签到状态判断逻辑 - 新增书籍状态组件,统一展示连载/完结状态 - 优化评论列表和我的评论页面显示逻辑 - 调整个人中心页面布局和样式 - 新增充值功能入口页面 - 优化章节列表和章节内容的付费标识显示 - 修复成就等级设置页面数据加载问题 - 优化打赏排行榜数据显示和交互 - 调整环境配置为开发环境master
| @ -0,0 +1,17 @@ | |||
| const api = { | |||
| // 获取我的可用积分数 | |||
| getMyMoneyNum : { | |||
| url: '/all_money/getMyMoneyNum', | |||
| method: 'GET', | |||
| auth: true, | |||
| }, | |||
| // 获取我的流水列表带分页 | |||
| getMyMoneyLogPage : { | |||
| url: '/all_money/getMyMoneyLogPage', | |||
| method: 'GET', | |||
| auth: true, | |||
| }, | |||
| } | |||
| export default api | |||
| @ -0,0 +1,51 @@ | |||
| <template> | |||
| <view class="book-status" | |||
| :class="statusClass"> | |||
| {{ statusText }} | |||
| </view> | |||
| </template> | |||
| <script> | |||
| export default { | |||
| props : ['status'], | |||
| computed: { | |||
| statusClass() { | |||
| const statusMap = { | |||
| '0': 'ongoing', | |||
| '1': 'completed' | |||
| }; | |||
| return statusMap[this.status] || 'ongoing'; | |||
| }, | |||
| statusText() { | |||
| const textMap = { | |||
| // '0': '新建', | |||
| '0': '连载中', | |||
| '1': '已完结' | |||
| }; | |||
| return textMap[this.status] || '连载中'; | |||
| }, | |||
| }, | |||
| data() { | |||
| return { | |||
| } | |||
| }, | |||
| methods: { | |||
| } | |||
| } | |||
| </script> | |||
| <style scoped lang="scss"> | |||
| .book-status { | |||
| font-size: 20rpx; | |||
| color: #67C23A; | |||
| background-color: rgba(103, 194, 58, 0.1); | |||
| border-radius: 20rpx; | |||
| padding: 4rpx 12rpx; | |||
| &.ongoing{ | |||
| color: #ffa502; | |||
| background-color: #ffa50223; | |||
| } | |||
| } | |||
| </style> | |||
| @ -0,0 +1,408 @@ | |||
| <template> | |||
| <uv-popup ref="popup" mode="bottom" :round="20" :safeAreaInsetBottom="true" @close="handleClose"> | |||
| <view class="interactive-gift-popup"> | |||
| <!-- 标题栏 --> | |||
| <view class="popup-header"> | |||
| <text class="popup-title">互动打赏</text> | |||
| <uv-icon name="close" size="40rpx" color="#999" @click="close"></uv-icon> | |||
| </view> | |||
| <!-- 当前选中礼物信息 --> | |||
| <view class="selected-gift-info" v-if="selectedGift"> | |||
| <view class="selected-gift-left"> | |||
| <view class="selected-gift-img"> | |||
| <image :src="selectedGift.image" mode="aspectFill"></image> | |||
| </view> | |||
| <view class="selected-gift-details"> | |||
| <text class="selected-gift-name">{{ selectedGift.title }}</text> | |||
| <text class="selected-gift-price">{{ selectedGift.integerPrice }}豆豆</text> | |||
| </view> | |||
| </view> | |||
| <view class="selected-gift-right"> | |||
| <uv-number-box | |||
| v-model="giftCount" | |||
| :min="1" | |||
| :max="99" | |||
| size="small" | |||
| bgColor="#f5f5f5" | |||
| color="#223a7a" | |||
| /> | |||
| </view> | |||
| </view> | |||
| <!-- 用户余额信息 --> | |||
| <view class="balance-info"> | |||
| <view class="balance-text"> | |||
| 账户余额:<text class="bean-amount">{{ userInfo.integerPrice }} 豆豆</text> | |||
| </view> | |||
| <view v-if="selectedGift && totalPrice > userInfo.integerPrice" class="insufficient-tip"> | |||
| 余额不足,请先充值 | |||
| </view> | |||
| </view> | |||
| <view class="gift-grid"> | |||
| <view | |||
| v-for="(gift, idx) in giftList" | |||
| :key="gift.id" | |||
| :class="['gift-item', { selected: selectedIndex === idx }]" | |||
| @click="selectGift(idx)" | |||
| > | |||
| <view class="gift-img"> | |||
| <image :src="gift.image" mode="aspectFill"></image> | |||
| </view> | |||
| <view class="gift-name">{{ gift.title }}</view> | |||
| <view class="gift-price">{{ gift.integerPrice }}豆豆</view> | |||
| </view> | |||
| </view> | |||
| <!-- 底部操作栏 --> | |||
| <view class="popup-bottom"> | |||
| <view class="total-info"> | |||
| <text class="total-text">总计:</text> | |||
| <text class="total-price">{{ totalPrice }}豆豆</text> | |||
| </view> | |||
| <button class="gift-btn" @click="sendGift" :disabled="!selectedGift || loading"> | |||
| {{ loading ? '赠送中...' : '赠送' }} | |||
| </button> | |||
| </view> | |||
| </view> | |||
| </uv-popup> | |||
| </template> | |||
| <script> | |||
| export default { | |||
| name: 'InteractiveGiftPopup', | |||
| props: { | |||
| bookId: { | |||
| type: [String, Number], | |||
| required: true | |||
| } | |||
| }, | |||
| data() { | |||
| return { | |||
| giftList: [], | |||
| selectedIndex: 0, | |||
| selectedGift: null, | |||
| giftCount: 1, | |||
| loading: false, | |||
| } | |||
| }, | |||
| computed: { | |||
| totalPrice() { | |||
| if (!this.selectedGift) return 0; | |||
| return this.selectedGift.integerPrice * this.giftCount; | |||
| } | |||
| }, | |||
| methods: { | |||
| // 打开弹窗 | |||
| open() { | |||
| this.$refs.popup.open(); | |||
| this.getGiftList(); | |||
| this.getUserBalance(); | |||
| }, | |||
| // 关闭弹窗 | |||
| close() { | |||
| this.$refs.popup.close(); | |||
| }, | |||
| // 处理关闭事件 | |||
| handleClose() { | |||
| this.resetData(); | |||
| }, | |||
| // 重置数据 | |||
| resetData() { | |||
| this.selectedIndex = 0; | |||
| this.selectedGift = null; | |||
| this.giftCount = 1; | |||
| this.loading = false; | |||
| }, | |||
| // 获取礼物列表 | |||
| getGiftList() { | |||
| this.$fetch('getInteractionGiftList').then(res => { | |||
| this.giftList = res.records || []; | |||
| if (this.giftList.length > 0) { | |||
| this.selectGift(0); | |||
| } | |||
| }).catch(err => { | |||
| console.error('获取礼物列表失败:', err); | |||
| uni.showToast({ | |||
| title: '获取礼物列表失败', | |||
| icon: 'none' | |||
| }); | |||
| }); | |||
| }, | |||
| // 选择礼物 | |||
| selectGift(index) { | |||
| this.selectedIndex = index; | |||
| this.selectedGift = this.giftList[index]; | |||
| this.giftCount = 1; | |||
| }, | |||
| // 获取用户余额 | |||
| getUserBalance() { | |||
| // 从store中获取用户信息 | |||
| this.$store.commit('getUserInfo'); | |||
| }, | |||
| // 赠送礼物 | |||
| sendGift() { | |||
| if (!this.selectedGift) { | |||
| uni.showToast({ | |||
| title: '请选择礼物', | |||
| icon: 'none' | |||
| }); | |||
| return; | |||
| } | |||
| // 检查余额是否足够 | |||
| if (this.totalPrice > this.userInfo.integerPrice) { | |||
| uni.showToast({ | |||
| title: '余额不足,请先充值', | |||
| icon: 'none' | |||
| }); | |||
| setTimeout(() => { | |||
| uni.navigateTo({ | |||
| url: '/pages_order/mine/recharge' | |||
| }) | |||
| }, 600) | |||
| return; | |||
| } | |||
| this.loading = true; | |||
| // 创建订单 | |||
| this.$fetch('giveGift', { | |||
| giftId: this.selectedGift.id, | |||
| num: this.giftCount, | |||
| bookId: this.bookId, | |||
| }).then(res => { | |||
| // 支付成功 | |||
| uni.showToast({ | |||
| title: '赠送成功', | |||
| icon: 'success' | |||
| }); | |||
| // 通知父组件更新数据 | |||
| this.$emit('giftSent', { | |||
| gift: this.selectedGift, | |||
| count: this.giftCount, | |||
| totalPrice: this.totalPrice | |||
| }); | |||
| this.getUserBalance() | |||
| this.close(); | |||
| }).catch(err => { | |||
| console.error('赠送失败:', err); | |||
| uni.showToast({ | |||
| title: err.message || '赠送失败', | |||
| icon: 'none' | |||
| }); | |||
| }).finally(() => { | |||
| this.loading = false; | |||
| }); | |||
| } | |||
| } | |||
| } | |||
| </script> | |||
| <style lang="scss" scoped> | |||
| .interactive-gift-popup { | |||
| background: #fff; | |||
| border-radius: 20rpx 20rpx 0 0; | |||
| max-height: 80vh; | |||
| display: flex; | |||
| flex-direction: column; | |||
| } | |||
| .popup-header { | |||
| display: flex; | |||
| justify-content: space-between; | |||
| align-items: center; | |||
| padding: 32rpx 32rpx 24rpx 32rpx; | |||
| border-bottom: 1rpx solid #f5f5f5; | |||
| .popup-title { | |||
| font-size: 32rpx; | |||
| font-weight: bold; | |||
| color: #333; | |||
| } | |||
| } | |||
| .selected-gift-info { | |||
| display: flex; | |||
| justify-content: space-between; | |||
| align-items: center; | |||
| padding: 24rpx 32rpx; | |||
| background: #f8f9ff; | |||
| margin: 0 32rpx 24rpx 32rpx; | |||
| border-radius: 16rpx; | |||
| .selected-gift-left { | |||
| display: flex; | |||
| align-items: center; | |||
| gap: 16rpx; | |||
| .selected-gift-img { | |||
| width: 60rpx; | |||
| height: 60rpx; | |||
| border-radius: 8rpx; | |||
| overflow: hidden; | |||
| image { | |||
| width: 100%; | |||
| height: 100%; | |||
| } | |||
| } | |||
| .selected-gift-details { | |||
| display: flex; | |||
| flex-direction: column; | |||
| gap: 4rpx; | |||
| .selected-gift-name { | |||
| font-size: 28rpx; | |||
| color: #333; | |||
| font-weight: 500; | |||
| } | |||
| .selected-gift-price { | |||
| font-size: 24rpx; | |||
| color: #223a7a; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| .balance-info { | |||
| padding: 0 32rpx 24rpx 32rpx; | |||
| .balance-text { | |||
| font-size: 28rpx; | |||
| color: #333; | |||
| margin-bottom: 8rpx; | |||
| .bean-amount { | |||
| color: #223a7a; | |||
| font-weight: 600; | |||
| } | |||
| } | |||
| .insufficient-tip { | |||
| font-size: 24rpx; | |||
| color: #e94f7a; | |||
| background: rgba(233, 79, 122, 0.1); | |||
| padding: 8rpx 16rpx; | |||
| border-radius: 8rpx; | |||
| text-align: center; | |||
| } | |||
| } | |||
| .gift-grid { | |||
| flex: 1; | |||
| display: flex; | |||
| flex-wrap: wrap; | |||
| gap: 20rpx; | |||
| padding: 0 32rpx; | |||
| max-height: 400rpx; | |||
| overflow-y: auto; | |||
| } | |||
| .gift-item { | |||
| width: calc(25% - 18rpx); | |||
| background: #fff; | |||
| border-radius: 12rpx; | |||
| box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.06); | |||
| display: flex; | |||
| flex-direction: column; | |||
| align-items: center; | |||
| padding: 20rpx 4rpx; | |||
| border: 2rpx solid transparent; | |||
| transition: all 0.2s; | |||
| box-sizing: border-box; | |||
| &.selected { | |||
| border-color: #223a7a; | |||
| background: #f8f9ff; | |||
| } | |||
| .gift-img { | |||
| width: 70rpx; | |||
| height: 70rpx; | |||
| border-radius: 8rpx; | |||
| overflow: hidden; | |||
| margin-bottom: 8rpx; | |||
| image { | |||
| width: 100%; | |||
| height: 100%; | |||
| } | |||
| } | |||
| .gift-name { | |||
| font-size: 22rpx; | |||
| color: #333; | |||
| text-align: center; | |||
| margin-bottom: 4rpx; | |||
| line-height: 1.2; | |||
| } | |||
| .gift-price { | |||
| font-size: 20rpx; | |||
| color: #223a7a; | |||
| text-align: center; | |||
| } | |||
| } | |||
| .popup-bottom { | |||
| display: flex; | |||
| justify-content: space-between; | |||
| align-items: center; | |||
| padding: 24rpx 32rpx; | |||
| border-top: 1rpx solid #f5f5f5; | |||
| background: #fff; | |||
| width: 100%; | |||
| box-sizing: border-box; | |||
| .total-info { | |||
| display: flex; | |||
| align-items: center; | |||
| gap: 8rpx; | |||
| .total-text { | |||
| font-size: 28rpx; | |||
| color: #666; | |||
| } | |||
| .total-price { | |||
| font-size: 32rpx; | |||
| color: #223a7a; | |||
| font-weight: bold; | |||
| } | |||
| } | |||
| .gift-btn { | |||
| background: #223a7a; | |||
| color: #fff; | |||
| font-size: 28rpx; | |||
| border-radius: 32rpx; | |||
| padding: 0 48rpx; | |||
| height: 68rpx; | |||
| line-height: 68rpx; | |||
| border: none; | |||
| min-width: 140rpx; | |||
| margin-left: auto; | |||
| margin-right: 20rpx; | |||
| &[disabled] { | |||
| background: #ccc; | |||
| color: #999; | |||
| } | |||
| } | |||
| } | |||
| </style> | |||
| @ -0,0 +1,218 @@ | |||
| <template> | |||
| <view class="sign-record-popup" :class="{'dark-mode': isDarkMode}"> | |||
| <uv-popup ref="popup" mode="center" :closeOnClickOverlay="true" :customStyle="popupStyle"> | |||
| <view class="content theme-transition"> | |||
| <view class="popup-header"> | |||
| <view class="popup-title theme-transition">签到记录</view> | |||
| <view class="close-btn" @click="close"> | |||
| <uv-icon name="close" :color="isDarkMode ? '#ccc' : '#666'" size="32rpx"></uv-icon> | |||
| </view> | |||
| </view> | |||
| <view class="record-list"> | |||
| <scroll-view scroll-y class="record-scroll"> | |||
| <view class="record-item" v-for="(record, index) in recordList" :key="index"> | |||
| <view class="record-left"> | |||
| <view class="record-date">{{ formatDate(record.createTime) }}</view> | |||
| <view class="record-task">{{ record.taskName || '每日签到' }}</view> | |||
| </view> | |||
| <view class="record-right"> | |||
| <text class="record-reward">+{{ record.num || 1 }}推荐票</text> | |||
| <text class="record-status success">已签到</text> | |||
| </view> | |||
| </view> | |||
| <view class="no-record" v-if="recordList.length === 0 && !loading">暂无签到记录</view> | |||
| <view class="loading" v-if="loading">加载中...</view> | |||
| </scroll-view> | |||
| </view> | |||
| </view> | |||
| </uv-popup> | |||
| </view> | |||
| </template> | |||
| <script> | |||
| import themeMixin from '@/mixins/themeMode.js' | |||
| export default { | |||
| name: 'signRecordPopup', | |||
| mixins: [themeMixin], | |||
| data() { | |||
| return { | |||
| recordList: [], | |||
| loading: false, | |||
| pageNo: 1, | |||
| pageSize: 20 | |||
| } | |||
| }, | |||
| computed: { | |||
| popupStyle() { | |||
| return { | |||
| 'background': this.isDarkMode ? '#232323' : '#fff', | |||
| 'border-radius': '24rpx', | |||
| 'width': '600rpx', | |||
| 'max-height': '700rpx' | |||
| } | |||
| } | |||
| }, | |||
| methods: { | |||
| // 打开弹窗 | |||
| open() { | |||
| this.$refs.popup.open(); | |||
| this.getRecordList(); | |||
| }, | |||
| // 关闭弹窗 | |||
| close() { | |||
| this.$refs.popup.close(); | |||
| }, | |||
| // 获取签到记录列表 | |||
| getRecordList() { | |||
| this.loading = true; | |||
| this.$fetch('getSignTaskRecordPage', { | |||
| pageNo: this.pageNo, | |||
| pageSize: this.pageSize | |||
| }).then(res => { | |||
| this.recordList = res.records || []; | |||
| this.loading = false; | |||
| }).catch(err => { | |||
| console.error('获取签到记录失败:', err); | |||
| this.loading = false; | |||
| }); | |||
| }, | |||
| // 格式化日期 | |||
| formatDate(dateString) { | |||
| if (!dateString) return ''; | |||
| const date = new Date(dateString); | |||
| const month = (date.getMonth() + 1).toString().padStart(2, '0'); | |||
| const day = date.getDate().toString().padStart(2, '0'); | |||
| return `${month}-${day}`; | |||
| } | |||
| } | |||
| } | |||
| </script> | |||
| <style lang="scss" scoped> | |||
| .sign-record-popup { | |||
| .content { | |||
| padding: 0; | |||
| .popup-header { | |||
| display: flex; | |||
| justify-content: space-between; | |||
| align-items: center; | |||
| padding: 32rpx 32rpx 24rpx; | |||
| border-bottom: 1rpx solid #f5f5f5; | |||
| .popup-title { | |||
| font-size: 32rpx; | |||
| font-weight: bold; | |||
| color: #222; | |||
| } | |||
| .close-btn { | |||
| width: 48rpx; | |||
| height: 48rpx; | |||
| display: flex; | |||
| align-items: center; | |||
| justify-content: center; | |||
| } | |||
| } | |||
| .record-list { | |||
| .record-scroll { | |||
| max-height: 560rpx; | |||
| .record-item { | |||
| display: flex; | |||
| justify-content: space-between; | |||
| align-items: center; | |||
| padding: 32rpx; | |||
| border-bottom: 1rpx solid #f8f8f8; | |||
| .record-left { | |||
| display: flex; | |||
| flex-direction: column; | |||
| align-items: flex-start; | |||
| .record-date { | |||
| font-size: 28rpx; | |||
| color: #333; | |||
| font-weight: 500; | |||
| margin-bottom: 8rpx; | |||
| } | |||
| .record-task { | |||
| font-size: 24rpx; | |||
| color: #999; | |||
| } | |||
| } | |||
| .record-right { | |||
| display: flex; | |||
| flex-direction: column; | |||
| align-items: flex-end; | |||
| .record-reward { | |||
| font-size: 26rpx; | |||
| color: #ff6b35; | |||
| margin-bottom: 4rpx; | |||
| font-weight: 500; | |||
| } | |||
| .record-status { | |||
| font-size: 22rpx; | |||
| &.success { | |||
| color: #4caf50; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| .no-record, .loading { | |||
| text-align: center; | |||
| padding: 80rpx 32rpx; | |||
| color: #999; | |||
| font-size: 26rpx; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| &.dark-mode { | |||
| .content { | |||
| .popup-header { | |||
| border-bottom-color: #333; | |||
| .popup-title { | |||
| color: #eee; | |||
| } | |||
| } | |||
| .record-list { | |||
| .record-scroll { | |||
| .record-item { | |||
| border-bottom-color: #333; | |||
| .record-left { | |||
| .record-date { | |||
| color: #ccc; | |||
| } | |||
| .record-task { | |||
| color: #888; | |||
| } | |||
| } | |||
| } | |||
| .no-record, .loading { | |||
| color: #666; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| </style> | |||
| @ -0,0 +1,364 @@ | |||
| <!-- 钱包流水页面 --> | |||
| <template> | |||
| <view class="walletflow-page"> | |||
| <!-- 顶部导航栏 --> | |||
| <navbar title="钱包流水" leftClick @leftClick="$utils.navigateBack" /> | |||
| <!-- 账户余额卡片 --> | |||
| <view class="balance-card"> | |||
| <view class="balance-label">账户</view> | |||
| <view class="balance-row"> | |||
| <text class="balance-amount">{{ accountBalance }}</text> | |||
| <button class="recharge-btn" @click="goRecharge">充值</button> | |||
| </view> | |||
| </view> | |||
| <!-- tab和流水列表卡片 --> | |||
| <view class="flow-card"> | |||
| <uv-tabs | |||
| :list="tabList" | |||
| :current="activeTab" | |||
| @change="switchTab" | |||
| :scrollable="false" | |||
| activeColor="#223a7a" | |||
| inactiveColor="#888" | |||
| lineColor="#223a7a" | |||
| lineWidth="44rpx" | |||
| lineHeight="4rpx" | |||
| :itemStyle="{ | |||
| height: '88rpx', | |||
| fontSize: '30rpx', | |||
| fontWeight: 'bold' | |||
| }" | |||
| ></uv-tabs> | |||
| <scroll-view scroll-y class="flow-list" @scrolltolower="loadMore"> | |||
| <view v-if="activeTab === 0"> | |||
| <view class="flow-item" v-for="(item, idx) in rechargeList" :key="idx"> | |||
| <view class="flow-item-row"> | |||
| <view class="flow-item-left"> | |||
| <view class="flow-title">{{ item.title || item.type || '充值' }}</view> | |||
| <view class="flow-date">{{ formatDate(item.createTime) }}</view> | |||
| </view> | |||
| <view class="flow-amount plus">+{{ item.num }}</view> | |||
| </view> | |||
| </view> | |||
| <view v-if="rechargeList.length === 0 && !loading" class="empty-tip">暂无充值记录</view> | |||
| </view> | |||
| <view v-else> | |||
| <view class="flow-item" v-for="(item, idx) in payList" :key="idx"> | |||
| <view class="flow-item-row"> | |||
| <view class="flow-item-left"> | |||
| <view class="flow-title">{{ item.title || item.type || '支付' }}</view> | |||
| <view class="flow-date">{{ formatDate(item.createTime) }}</view> | |||
| </view> | |||
| <view class="flow-amount minus">-{{ item.num }}</view> | |||
| </view> | |||
| </view> | |||
| <view v-if="payList.length === 0 && !loading" class="empty-tip">暂无支付记录</view> | |||
| </view> | |||
| <view v-if="loading" class="loading-tip">加载中...</view> | |||
| <view v-if="noMore && (rechargeList.length > 0 || payList.length > 0)" class="no-more-tip">没有更多了</view> | |||
| </scroll-view> | |||
| </view> | |||
| </view> | |||
| </template> | |||
| <script> | |||
| import mixinsList from '@/mixins/list.js' | |||
| export default { | |||
| mixins: [mixinsList], | |||
| components: { | |||
| }, | |||
| data() { | |||
| return { | |||
| accountBalance: 0, | |||
| activeTab: 0, | |||
| rechargeList: [], | |||
| payList: [], | |||
| loading: false, | |||
| noMore: false, | |||
| pageNo: 1, | |||
| pageSize: 20, | |||
| tabList: [ | |||
| { | |||
| name: '充值', | |||
| value: 0 | |||
| }, | |||
| { | |||
| name: '支付', | |||
| value: 1 | |||
| } | |||
| ] | |||
| } | |||
| }, | |||
| onLoad() { | |||
| this.getAccountBalance(); | |||
| this.getFlowList(); | |||
| }, | |||
| methods: { | |||
| // 获取账户余额 | |||
| getAccountBalance() { | |||
| this.$fetch('getMyMoneyNum').then(res => { | |||
| this.accountBalance = res || 0; | |||
| }).catch(err => { | |||
| console.error('获取账户余额失败:', err); | |||
| this.accountBalance = 0; | |||
| }); | |||
| }, | |||
| // 切换tab | |||
| switchTab(tab) { | |||
| // uv-tabs组件传递的可能是对象,需要获取index | |||
| const tabIndex = typeof tab === 'object' ? tab.index : tab; | |||
| if (this.activeTab === tabIndex) return; | |||
| this.activeTab = tabIndex; | |||
| this.pageNo = 1; | |||
| this.noMore = false; | |||
| // 清空对应列表 | |||
| if (tabIndex === 0) { | |||
| this.rechargeList = []; | |||
| } else { | |||
| this.payList = []; | |||
| } | |||
| this.getFlowList(); | |||
| }, | |||
| // 获取流水列表 | |||
| getFlowList() { | |||
| if (this.loading || this.noMore) return; | |||
| this.loading = true; | |||
| // 根据当前tab确定流水类型:0-充值,1-支付 | |||
| const logType = this.activeTab === 0 ? 0 : 1; | |||
| this.$fetch('getMyMoneyLogPage', { | |||
| pageNo: this.pageNo, | |||
| pageSize: this.pageSize, | |||
| status: logType // 0-充值记录,1-支付记录 | |||
| }).then(res => { | |||
| const records = res.records || []; | |||
| if (records.length === 0) { | |||
| this.noMore = true; | |||
| } else { | |||
| if (this.activeTab === 0) { | |||
| // 充值记录 | |||
| if (this.pageNo === 1) { | |||
| this.rechargeList = records; | |||
| } else { | |||
| this.rechargeList = [...this.rechargeList, ...records]; | |||
| } | |||
| } else { | |||
| // 支付记录 | |||
| if (this.pageNo === 1) { | |||
| this.payList = records; | |||
| } else { | |||
| this.payList = [...this.payList, ...records]; | |||
| } | |||
| } | |||
| // 如果返回的记录数少于pageSize,说明没有更多了 | |||
| if (records.length < this.pageSize) { | |||
| this.noMore = true; | |||
| } | |||
| } | |||
| this.loading = false; | |||
| }).catch(err => { | |||
| console.error('获取流水列表失败:', err); | |||
| this.loading = false; | |||
| uni.showToast({ | |||
| title: '获取流水失败', | |||
| icon: 'none' | |||
| }); | |||
| }); | |||
| }, | |||
| // 加载更多 | |||
| loadMore() { | |||
| if (this.loading || this.noMore) return; | |||
| this.pageNo++; | |||
| this.getFlowList(); | |||
| }, | |||
| // 格式化日期 | |||
| formatDate(dateString) { | |||
| if (!dateString) return ''; | |||
| const date = new Date(dateString); | |||
| const year = date.getFullYear(); | |||
| const month = (date.getMonth() + 1).toString().padStart(2, '0'); | |||
| const day = date.getDate().toString().padStart(2, '0'); | |||
| return `${year}.${month}.${day}`; | |||
| }, | |||
| goRecharge() { | |||
| uni.navigateTo({ | |||
| url: '/pages_order/mine/recharge' | |||
| }) | |||
| } | |||
| } | |||
| } | |||
| </script> | |||
| <style lang="scss" scoped> | |||
| .walletflow-page { | |||
| min-height: 100vh; | |||
| background: linear-gradient(180deg, #f8f8fc 0%, #fff 100%); | |||
| padding-bottom: 30rpx; | |||
| } | |||
| .balance-card { | |||
| background: linear-gradient(90deg, #f7f2fa 0%, #fbeaf2 100%); | |||
| border-radius: 18rpx; | |||
| margin: 24rpx 12rpx 0 12rpx; | |||
| padding: 18rpx 24rpx 14rpx 24rpx; | |||
| box-shadow: none; | |||
| border: 1rpx solid #ede7ef; | |||
| position: relative; | |||
| display: flex; | |||
| flex-direction: column; | |||
| min-height: 130rpx; | |||
| justify-content: center; | |||
| .balance-label { | |||
| color: #bbb; | |||
| font-size: 26rpx; | |||
| margin-bottom: 8rpx; | |||
| } | |||
| .balance-row { | |||
| display: flex; | |||
| align-items: center; | |||
| margin-top: 0; | |||
| position: relative; | |||
| .balance-amount { | |||
| color: #e94f7a; | |||
| font-size: 48rpx; | |||
| font-weight: bold; | |||
| } | |||
| .recharge-btn { | |||
| position: absolute; | |||
| right: 0; | |||
| top: 50%; | |||
| transform: translateY(-50%); | |||
| background: linear-gradient(90deg, #ffb6c1 0%, #fa5a99 100%); | |||
| color: #fff; | |||
| font-size: 28rpx; | |||
| border-radius: 32rpx; | |||
| padding: 0 40rpx; | |||
| height: 56rpx; | |||
| line-height: 56rpx; | |||
| font-weight: 500; | |||
| border: none; | |||
| box-shadow: none; | |||
| display: flex; | |||
| align-items: center; | |||
| justify-content: center; | |||
| } | |||
| } | |||
| } | |||
| .flow-card { | |||
| background: #fff; | |||
| border-radius: 20rpx; | |||
| margin: 32rpx 16rpx 0 16rpx; | |||
| box-shadow: 0 4rpx 24rpx 0 rgba(0, 0, 0, 0.06); | |||
| padding-bottom: 8rpx; | |||
| overflow: hidden; | |||
| // uv-tabs组件样式调整 | |||
| :deep(.uv-tabs) { | |||
| background: #fff; | |||
| border-top-left-radius: 20rpx; | |||
| border-top-right-radius: 20rpx; | |||
| } | |||
| :deep(.uv-tabs__wrapper__nav__line) { | |||
| border-radius: 2rpx !important; | |||
| } | |||
| } | |||
| .flow-list { | |||
| margin: 0; | |||
| padding: 0 16rpx; | |||
| max-height: calc(75vh - 88rpx); | |||
| background: #fff; | |||
| } | |||
| .flow-item { | |||
| border-bottom: 1px solid #f5f5f5; | |||
| padding: 18rpx 0 8rpx 0; | |||
| &:last-child { | |||
| border-bottom: none; | |||
| } | |||
| .flow-item-row { | |||
| display: flex; | |||
| align-items: flex-start; | |||
| justify-content: space-between; | |||
| padding-right: 45rpx; | |||
| padding-left: 15rpx; | |||
| } | |||
| .flow-item-left { | |||
| display: flex; | |||
| flex-direction: column; | |||
| align-items: flex-start; | |||
| .flow-title { | |||
| font-size: 28rpx; | |||
| color: #222; | |||
| font-weight: 500; | |||
| margin-bottom: 2rpx; | |||
| } | |||
| .flow-date { | |||
| color: #bbb; | |||
| font-size: 22rpx; | |||
| margin-top: 0; | |||
| } | |||
| } | |||
| .flow-amount { | |||
| font-size: 26rpx; | |||
| font-weight: 500; | |||
| margin-left: 24rpx; | |||
| margin-top: 2rpx; | |||
| &.plus { | |||
| color: #223a7a; | |||
| } | |||
| &.minus { | |||
| color: #e94f7a; | |||
| } | |||
| } | |||
| } | |||
| // 提示文字样式 | |||
| .empty-tip, | |||
| .loading-tip, | |||
| .no-more-tip { | |||
| text-align: center; | |||
| padding: 40rpx 0; | |||
| color: #999; | |||
| font-size: 26rpx; | |||
| } | |||
| .loading-tip { | |||
| color: #666; | |||
| } | |||
| </style> | |||
| @ -0,0 +1,530 @@ | |||
| <template> | |||
| <!-- 豆豆充值页面 --> | |||
| <view class="recharge-page"> | |||
| <!-- 顶部导航栏 --> | |||
| <navbar title="豆豆充值" leftClick @leftClick="$utils.navigateBack" /> | |||
| <!-- 当前余额卡片 --> | |||
| <view class="card balance-card"> | |||
| <view class="card-title">当前余额</view> | |||
| <view class="current-balance"> | |||
| <text class="balance-amount">{{ userInfo.integerPrice || 0 }}</text> | |||
| <text class="balance-unit">豆豆</text> | |||
| </view> | |||
| </view> | |||
| <!-- 充值套餐选择 --> | |||
| <view class="card package-card"> | |||
| <view class="card-title">选择充值套餐</view> | |||
| <view class="package-grid"> | |||
| <view | |||
| v-for="(item, index) in rechargePackages" | |||
| :key="index" | |||
| :class="['package-item', { selected: selectedPackage === index }]" | |||
| @click="selectPackage(index)" | |||
| > | |||
| <view class="package-beans">{{ item.num }}豆豆</view> | |||
| <view class="package-price">¥{{ item.money }}</view> | |||
| <view v-if="item.giveNum" class="package-bonus">送{{ item.giveNum }}豆豆</view> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| <!-- 自定义充值 --> | |||
| <!-- <view class="card custom-card"> | |||
| <view class="card-title">自定义充值</view> | |||
| <view class="form-row"> | |||
| <view class="form-label required"> | |||
| <text class="star">*</text> 充值金额(元) | |||
| </view> | |||
| <input | |||
| class="form-input" | |||
| placeholder="请输入充值金额" | |||
| v-model="customAmount" | |||
| type="number" | |||
| :placeholder-style="'color:#bbb;'" | |||
| :style="customAmount ? 'color:#222;' : ''" | |||
| @input="onCustomAmountChange" | |||
| /> | |||
| </view> | |||
| <view class="divider"></view> | |||
| <view class="form-row"> | |||
| <view class="form-label">可获得豆豆</view> | |||
| <view class="form-value">{{ customBeans }}豆豆</view> | |||
| </view> | |||
| </view> --> | |||
| <!-- 订单信息卡片 --> | |||
| <view class="card order-card" v-if="totalPrice > 0"> | |||
| <view class="order-title">订单信息</view> | |||
| <view class="order-item"> | |||
| <text class="order-label">充值金额:</text> | |||
| <text class="order-value">¥{{ totalPrice.toFixed(2) }}</text> | |||
| </view> | |||
| <view class="order-item"> | |||
| <text class="order-label">获得豆豆:</text> | |||
| <text class="order-value">{{ totalBeans }}豆豆</text> | |||
| </view> | |||
| <view class="order-divider"></view> | |||
| <view class="order-item total-row"> | |||
| <view class="order-total-label">合计:</view> | |||
| <view class="order-total"> | |||
| <text class="order-total-highlight">¥{{ totalPrice.toFixed(2) }}</text> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| <!-- 支付方式 --> | |||
| <!-- <view class="card payment-card"> | |||
| <view class="card-title">支付方式</view> | |||
| <view class="payment-methods"> | |||
| <view | |||
| v-for="(method, index) in paymentMethods" | |||
| :key="index" | |||
| :class="['payment-item', { selected: selectedPayment === index }]" | |||
| @click="selectPayment(index)" | |||
| > | |||
| <view class="payment-icon"> | |||
| <uv-icon :name="method.icon" size="40rpx" color="#223a7a" /> | |||
| </view> | |||
| <text class="payment-name">{{ method.name }}</text> | |||
| <view class="payment-radio"> | |||
| <view v-if="selectedPayment === index" class="radio-checked"></view> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| </view> --> | |||
| <!-- 提示信息 --> | |||
| <view class="tip-text"> | |||
| 请仔细核查并确认相关信息。因用户个人疏忽导致的充值错误,需由用户自行承担。一旦完成充值,概不退换。 | |||
| </view> | |||
| <!-- 底部充值按钮 --> | |||
| <view class="footer-bar"> | |||
| <button class="recharge-btn" @click="handleRecharge" :disabled="totalPrice <= 0"> | |||
| 立即充值 ¥{{ totalPrice.toFixed(2) }} | |||
| </button> | |||
| </view> | |||
| </view> | |||
| </template> | |||
| <script> | |||
| export default { | |||
| data() { | |||
| return { | |||
| selectedPackage: null, | |||
| customAmount: '', | |||
| selectedPayment: 0, | |||
| rechargePackages: [ | |||
| // { beans: 100, price: 10, bonus: 0 }, | |||
| // { beans: 300, price: 30, bonus: 20 }, | |||
| // { beans: 680, price: 68, bonus: 50 }, | |||
| // { beans: 1280, price: 128, bonus: 120 }, | |||
| // { beans: 3280, price: 328, bonus: 320 }, | |||
| // { beans: 6480, price: 648, bonus: 680 } | |||
| ], | |||
| paymentMethods: [ | |||
| { name: '微信支付', icon: 'weixin-fill' }, | |||
| ] | |||
| } | |||
| }, | |||
| computed: { | |||
| customBeans() { | |||
| const amount = parseFloat(this.customAmount) | |||
| return isNaN(amount) ? 0 : Math.floor(amount * 10) | |||
| }, | |||
| totalPrice() { | |||
| if (this.selectedPackage !== null) { | |||
| return this.rechargePackages[this.selectedPackage].money | |||
| } else if (this.customAmount) { | |||
| return parseFloat(this.customAmount) || 0 | |||
| } | |||
| return 0 | |||
| }, | |||
| totalBeans() { | |||
| if (this.selectedPackage !== null) { | |||
| const pkg = this.rechargePackages[this.selectedPackage] | |||
| return pkg.num + (pkg.giveNum || 0) | |||
| } else if (this.customAmount) { | |||
| return this.customBeans | |||
| } | |||
| return 0 | |||
| } | |||
| }, | |||
| onLoad(query) { | |||
| // 可以通过参数预设充值金额 | |||
| if (query.amount) { | |||
| this.customAmount = query.amount | |||
| } | |||
| }, | |||
| onShow() { | |||
| this.$store.commit('getUserInfo') | |||
| this.getPayPackageList() | |||
| }, | |||
| methods: { | |||
| getPayPackageList(){ | |||
| this.$api('getPayPackageList') | |||
| .then(res => { | |||
| if(res.code == 200){ | |||
| this.rechargePackages = res.result | |||
| } | |||
| }) | |||
| }, | |||
| // 选择充值套餐 | |||
| selectPackage(index) { | |||
| this.selectedPackage = index | |||
| this.customAmount = '' | |||
| }, | |||
| // 选择支付方式 | |||
| selectPayment(index) { | |||
| this.selectedPayment = index | |||
| }, | |||
| // 自定义金额输入变化 | |||
| onCustomAmountChange() { | |||
| if (this.customAmount) { | |||
| this.selectedPackage = null | |||
| } | |||
| }, | |||
| // 处理充值 | |||
| async handleRecharge() { | |||
| if (this.totalPrice <= 0) { | |||
| uni.showToast({ | |||
| title: '请选择充值套餐或输入充值金额', | |||
| icon: 'none' | |||
| }) | |||
| return | |||
| } | |||
| if (this.selectedPayment === null) { | |||
| uni.showToast({ | |||
| title: '请选择支付方式', | |||
| icon: 'none' | |||
| }) | |||
| return | |||
| } | |||
| try { | |||
| // 这里应该调用充值接口 | |||
| const result = await this.$fetch('createPayPackageOrder', { | |||
| // amount: this.totalPrice, | |||
| // beans: this.totalBeans, | |||
| // paymentMethod: this.paymentMethods[this.selectedPayment].name | |||
| packageId : this.rechargePackages[this.selectedPackage].id | |||
| }) | |||
| await uni.requestPaymentWxPay({result}) | |||
| uni.showToast({ | |||
| title: `充值成功,获得${this.totalBeans}豆豆`, | |||
| icon: 'success' | |||
| }) | |||
| // 更新用户信息 | |||
| this.$store.commit('getUserInfo') | |||
| setTimeout(() => { | |||
| uni.navigateBack() | |||
| }, 1500) | |||
| } catch (error) { | |||
| uni.showToast({ | |||
| title: '充值失败,请重试', | |||
| icon: 'none' | |||
| }) | |||
| } | |||
| } | |||
| } | |||
| } | |||
| </script> | |||
| <style scoped lang="scss"> | |||
| .recharge-page { | |||
| min-height: 100vh; | |||
| background: #f8f8f8; | |||
| padding-bottom: 120rpx; | |||
| } | |||
| .card { | |||
| background: #fff; | |||
| border-radius: 20rpx; | |||
| margin: 24rpx 16rpx 0 16rpx; | |||
| padding: 24rpx; | |||
| box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.03); | |||
| } | |||
| .card-title { | |||
| font-size: 32rpx; | |||
| font-weight: bold; | |||
| color: #222; | |||
| margin-bottom: 24rpx; | |||
| } | |||
| // 当前余额卡片 | |||
| .balance-card { | |||
| background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | |||
| color: #fff; | |||
| text-align: center; | |||
| .card-title { | |||
| color: #fff; | |||
| opacity: 0.9; | |||
| } | |||
| .current-balance { | |||
| display: flex; | |||
| align-items: baseline; | |||
| justify-content: center; | |||
| gap: 8rpx; | |||
| margin-top: 16rpx; | |||
| .balance-amount { | |||
| font-size: 56rpx; | |||
| font-weight: bold; | |||
| } | |||
| .balance-unit { | |||
| font-size: 28rpx; | |||
| opacity: 0.8; | |||
| } | |||
| } | |||
| } | |||
| // 充值套餐 | |||
| .package-grid { | |||
| display: flex; | |||
| flex-wrap: wrap; | |||
| gap: 16rpx; | |||
| } | |||
| .package-item { | |||
| width: calc(50% - 8rpx); | |||
| background: #f8f9ff; | |||
| border: 2rpx solid #f0f0f0; | |||
| border-radius: 16rpx; | |||
| padding: 24rpx 16rpx; | |||
| text-align: center; | |||
| transition: all 0.2s; | |||
| position: relative; | |||
| box-sizing: border-box; | |||
| &.selected { | |||
| border-color: #223a7a; | |||
| background: rgba(34, 58, 122, 0.05); | |||
| } | |||
| .package-beans { | |||
| font-size: 32rpx; | |||
| font-weight: bold; | |||
| color: #222; | |||
| margin-bottom: 8rpx; | |||
| } | |||
| .package-price { | |||
| font-size: 28rpx; | |||
| color: #223a7a; | |||
| font-weight: 500; | |||
| margin-bottom: 4rpx; | |||
| } | |||
| .package-bonus { | |||
| font-size: 20rpx; | |||
| color: #e94f7a; | |||
| background: rgba(233, 79, 122, 0.1); | |||
| padding: 2rpx 8rpx; | |||
| border-radius: 8rpx; | |||
| display: inline-block; | |||
| } | |||
| } | |||
| // 表单样式 | |||
| .form-row { | |||
| display: flex; | |||
| flex-direction: column; | |||
| align-items: flex-start; | |||
| margin-bottom: 24rpx; | |||
| } | |||
| .form-label { | |||
| color: #888; | |||
| font-size: 28rpx; | |||
| margin-bottom: 12rpx; | |||
| font-weight: 400; | |||
| &.required { | |||
| color: #222; | |||
| font-weight: 500; | |||
| display: flex; | |||
| align-items: center; | |||
| } | |||
| } | |||
| .star { | |||
| color: #e94f7a; | |||
| margin-right: 4rpx; | |||
| font-size: 28rpx; | |||
| } | |||
| .form-value { | |||
| color: #222; | |||
| font-size: 28rpx; | |||
| font-weight: 600; | |||
| } | |||
| .form-input { | |||
| width: 100%; | |||
| border: 1rpx solid #e5e5e5; | |||
| border-radius: 12rpx; | |||
| font-size: 28rpx; | |||
| padding: 16rpx; | |||
| background: #fafafa; | |||
| color: #222; | |||
| box-sizing: border-box; | |||
| } | |||
| .divider { | |||
| height: 1rpx; | |||
| background: #f2f2f2; | |||
| margin: 16rpx 0; | |||
| width: 100%; | |||
| } | |||
| // 订单信息 | |||
| .order-card { | |||
| .order-item { | |||
| display: flex; | |||
| justify-content: space-between; | |||
| align-items: center; | |||
| margin-bottom: 16rpx; | |||
| .order-label { | |||
| font-size: 28rpx; | |||
| color: #666; | |||
| } | |||
| .order-value { | |||
| font-size: 28rpx; | |||
| color: #222; | |||
| font-weight: 500; | |||
| } | |||
| &.total-row { | |||
| margin-bottom: 0; | |||
| margin-top: 16rpx; | |||
| .order-total-label { | |||
| font-size: 32rpx; | |||
| color: #222; | |||
| font-weight: 600; | |||
| } | |||
| .order-total-highlight { | |||
| font-size: 32rpx; | |||
| color: #223a7a; | |||
| font-weight: bold; | |||
| } | |||
| } | |||
| } | |||
| .order-divider { | |||
| height: 1rpx; | |||
| background: #f2f2f2; | |||
| margin: 16rpx 0; | |||
| } | |||
| } | |||
| // 支付方式 | |||
| .payment-methods { | |||
| display: flex; | |||
| flex-direction: column; | |||
| gap: 16rpx; | |||
| } | |||
| .payment-item { | |||
| display: flex; | |||
| align-items: center; | |||
| padding: 20rpx; | |||
| border: 2rpx solid #f0f0f0; | |||
| border-radius: 12rpx; | |||
| transition: all 0.2s; | |||
| &.selected { | |||
| border-color: #223a7a; | |||
| background: rgba(34, 58, 122, 0.05); | |||
| } | |||
| .payment-icon { | |||
| width: 48rpx; | |||
| height: 48rpx; | |||
| margin-right: 16rpx; | |||
| image { | |||
| width: 100%; | |||
| height: 100%; | |||
| } | |||
| } | |||
| .payment-name { | |||
| flex: 1; | |||
| font-size: 28rpx; | |||
| color: #222; | |||
| } | |||
| .payment-radio { | |||
| width: 32rpx; | |||
| height: 32rpx; | |||
| border: 2rpx solid #ddd; | |||
| border-radius: 50%; | |||
| position: relative; | |||
| .radio-checked { | |||
| width: 16rpx; | |||
| height: 16rpx; | |||
| background: #223a7a; | |||
| border-radius: 50%; | |||
| position: absolute; | |||
| top: 50%; | |||
| left: 50%; | |||
| transform: translate(-50%, -50%); | |||
| } | |||
| } | |||
| } | |||
| .tip-text { | |||
| color: #bbb; | |||
| font-size: 22rpx; | |||
| margin: 32rpx 32rpx 0 32rpx; | |||
| line-height: 1.6; | |||
| } | |||
| .footer-bar { | |||
| // position: fixed; | |||
| // left: 0; | |||
| // right: 0; | |||
| // bottom: 90rpx; | |||
| background: #fff; | |||
| padding: 24rpx 32rpx 32rpx 32rpx; | |||
| box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.05); | |||
| z-index: 10; | |||
| } | |||
| .recharge-btn { | |||
| width: 100%; | |||
| background: #223a7a; | |||
| color: #fff; | |||
| font-size: 32rpx; | |||
| border-radius: 32rpx; | |||
| height: 88rpx; | |||
| line-height: 88rpx; | |||
| border: none; | |||
| font-weight: 500; | |||
| &[disabled] { | |||
| background: #ccc; | |||
| color: #999; | |||
| } | |||
| } | |||
| </style> | |||
| @ -1,388 +0,0 @@ | |||
| <!-- 钱包流水页面 --> | |||
| <template> | |||
| <view class="walletflow-page"> | |||
| <!-- 顶部导航栏 --> | |||
| <navbar title="钱包流水" leftClick @leftClick="$utils.navigateBack" /> | |||
| <!-- 账户余额卡片 --> | |||
| <view class="balance-card"> | |||
| <view class="balance-label">账户</view> | |||
| <view class="balance-row"> | |||
| <text class="balance-amount">{{ balance }}</text> | |||
| <button class="recharge-btn" @click="goRecharge">充值</button> | |||
| </view> | |||
| </view> | |||
| <!-- tab和流水列表卡片 --> | |||
| <view class="flow-card"> | |||
| <view class="tab-header"> | |||
| <view :class="['tab-item', {active: activeTab === 0}]" @click="activeTab = 0"> | |||
| 充值 | |||
| <view v-if="activeTab === 0" class="tab-underline"></view> | |||
| </view> | |||
| <view :class="['tab-item', {active: activeTab === 1}]" @click="activeTab = 1"> | |||
| 支付 | |||
| <view v-if="activeTab === 1" class="tab-underline"></view> | |||
| </view> | |||
| </view> | |||
| <scroll-view scroll-y class="flow-list"> | |||
| <view v-if="activeTab === 0"> | |||
| <view class="flow-item" v-for="(item, idx) in rechargeList" :key="idx"> | |||
| <view class="flow-item-row"> | |||
| <view class="flow-item-left"> | |||
| <view class="flow-title">{{ item.title }}</view> | |||
| <view class="flow-date">{{ item.date }}</view> | |||
| </view> | |||
| <view class="flow-amount plus">+{{ item.amount }}</view> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| <view v-else> | |||
| <view class="flow-item" v-for="(item, idx) in payList" :key="idx"> | |||
| <view class="flow-item-row"> | |||
| <view class="flow-item-left"> | |||
| <view class="flow-title">{{ item.title }}</view> | |||
| <view class="flow-date">{{ item.date }}</view> | |||
| </view> | |||
| <view class="flow-amount minus">-{{ item.amount }}</view> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| </scroll-view> | |||
| </view> | |||
| </view> | |||
| </template> | |||
| <script> | |||
| export default { | |||
| components: { | |||
| }, | |||
| data() { | |||
| return { | |||
| balance: 34532, | |||
| activeTab: 0, | |||
| rechargeList: [{ | |||
| title: '豆豆充值', | |||
| date: '2025.03.18', | |||
| amount: 55 | |||
| }, | |||
| { | |||
| title: '豆豆充值', | |||
| date: '2025.03.18', | |||
| amount: 55 | |||
| }, | |||
| { | |||
| title: '豆豆充值', | |||
| date: '2025.03.18', | |||
| amount: 55 | |||
| }, | |||
| { | |||
| title: '推荐票', | |||
| date: '2025.03.18', | |||
| amount: 5 | |||
| }, | |||
| { | |||
| title: '豆豆充值', | |||
| date: '2025.03.18', | |||
| amount: 55 | |||
| }, | |||
| { | |||
| title: '豆豆充值', | |||
| date: '2025.03.18', | |||
| amount: 55 | |||
| }, | |||
| { | |||
| title: '豆豆充值', | |||
| date: '2025.03.18', | |||
| amount: 55 | |||
| }, | |||
| { | |||
| title: '豆豆充值', | |||
| date: '2025.03.18', | |||
| amount: 55 | |||
| }, | |||
| { | |||
| title: '豆豆充值', | |||
| date: '2025.03.18', | |||
| amount: 55 | |||
| }, | |||
| { | |||
| title: '豆豆充值', | |||
| date: '2025.03.18', | |||
| amount: 55 | |||
| }, | |||
| { | |||
| title: '豆豆充值', | |||
| date: '2025.03.18', | |||
| amount: 55 | |||
| }, | |||
| { | |||
| title: '豆豆充值', | |||
| date: '2025.03.18', | |||
| amount: 55 | |||
| }, | |||
| { | |||
| title: '豆豆充值', | |||
| date: '2025.03.18', | |||
| amount: 55 | |||
| }, | |||
| { | |||
| title: '豆豆充值', | |||
| date: '2025.03.18', | |||
| amount: 55 | |||
| }, | |||
| ], | |||
| payList: [{ | |||
| title: '章节支付', | |||
| date: '2025.03.18', | |||
| amount: 10 | |||
| }, | |||
| { | |||
| title: '章节支付', | |||
| date: '2025.03.18', | |||
| amount: 10 | |||
| }, | |||
| { | |||
| title: '章节支付', | |||
| date: '2025.03.18', | |||
| amount: 10 | |||
| }, | |||
| { | |||
| title: '章节支付', | |||
| date: '2025.03.18', | |||
| amount: 10 | |||
| }, | |||
| { | |||
| title: '章节支付', | |||
| date: '2025.03.18', | |||
| amount: 10 | |||
| }, | |||
| { | |||
| title: '章节支付', | |||
| date: '2025.03.18', | |||
| amount: 10 | |||
| }, | |||
| { | |||
| title: '章节支付', | |||
| date: '2025.03.18', | |||
| amount: 10 | |||
| }, | |||
| { | |||
| title: '章节支付', | |||
| date: '2025.03.18', | |||
| amount: 10 | |||
| }, | |||
| { | |||
| title: '章节支付', | |||
| date: '2025.03.18', | |||
| amount: 10 | |||
| }, | |||
| { | |||
| title: '章节支付', | |||
| date: '2025.03.18', | |||
| amount: 10 | |||
| }, | |||
| { | |||
| title: '章节支付', | |||
| date: '2025.03.18', | |||
| amount: 10 | |||
| }, | |||
| { | |||
| title: '章节支付', | |||
| date: '2025.03.18', | |||
| amount: 10 | |||
| }, | |||
| { | |||
| title: '章节支付', | |||
| date: '2025.03.18', | |||
| amount: 10 | |||
| }, | |||
| { | |||
| title: '章节支付', | |||
| date: '2025.03.18', | |||
| amount: 10 | |||
| }, | |||
| { | |||
| title: '章节支付', | |||
| date: '2025.03.18', | |||
| amount: 10 | |||
| }, | |||
| ] | |||
| } | |||
| }, | |||
| methods: { | |||
| goRecharge() { | |||
| uni.showToast({ | |||
| title: '充值功能开发中', | |||
| icon: 'none' | |||
| }) | |||
| } | |||
| } | |||
| } | |||
| </script> | |||
| <style lang="scss" scoped> | |||
| .walletflow-page { | |||
| min-height: 100vh; | |||
| background: linear-gradient(180deg, #f8f8fc 0%, #fff 100%); | |||
| padding-bottom: 30rpx; | |||
| } | |||
| .balance-card { | |||
| background: linear-gradient(90deg, #f7f2fa 0%, #fbeaf2 100%); | |||
| border-radius: 18rpx; | |||
| margin: 24rpx 12rpx 0 12rpx; | |||
| padding: 18rpx 24rpx 14rpx 24rpx; | |||
| box-shadow: none; | |||
| border: 1rpx solid #ede7ef; | |||
| position: relative; | |||
| display: flex; | |||
| flex-direction: column; | |||
| min-height: 130rpx; | |||
| justify-content: center; | |||
| .balance-label { | |||
| color: #bbb; | |||
| font-size: 26rpx; | |||
| margin-bottom: 8rpx; | |||
| } | |||
| .balance-row { | |||
| display: flex; | |||
| align-items: center; | |||
| margin-top: 0; | |||
| position: relative; | |||
| .balance-amount { | |||
| color: #e94f7a; | |||
| font-size: 48rpx; | |||
| font-weight: bold; | |||
| } | |||
| .recharge-btn { | |||
| position: absolute; | |||
| right: 0; | |||
| top: 50%; | |||
| transform: translateY(-50%); | |||
| background: linear-gradient(90deg, #ffb6c1 0%, #fa5a99 100%); | |||
| color: #fff; | |||
| font-size: 28rpx; | |||
| border-radius: 32rpx; | |||
| padding: 0 40rpx; | |||
| height: 56rpx; | |||
| line-height: 56rpx; | |||
| font-weight: 500; | |||
| border: none; | |||
| box-shadow: none; | |||
| display: flex; | |||
| align-items: center; | |||
| justify-content: center; | |||
| } | |||
| } | |||
| } | |||
| .flow-card { | |||
| background: #fff; | |||
| border-radius: 20rpx; | |||
| margin: 32rpx 16rpx 0 16rpx; | |||
| box-shadow: 0 4rpx 24rpx 0 rgba(0, 0, 0, 0.06); | |||
| padding-bottom: 8rpx; | |||
| overflow: hidden; | |||
| } | |||
| .tab-header { | |||
| display: flex; | |||
| margin: 0; | |||
| background: #fff; | |||
| border-top-left-radius: 20rpx; | |||
| border-top-right-radius: 20rpx; | |||
| overflow: hidden; | |||
| .tab-item { | |||
| flex: 1; | |||
| text-align: center; | |||
| font-size: 30rpx; | |||
| color: #888; | |||
| padding: 0 0 18rpx 0; | |||
| font-weight: bold; | |||
| background: transparent; | |||
| position: relative; | |||
| &.active { | |||
| color: #223a7a; | |||
| font-weight: bold; | |||
| } | |||
| .tab-underline { | |||
| position: absolute; | |||
| left: 50%; | |||
| bottom: 0; | |||
| transform: translateX(-50%); | |||
| width: 44rpx; | |||
| height: 4rpx; | |||
| background: #223a7a; | |||
| border-radius: 2rpx; | |||
| margin-top: 4rpx; | |||
| } | |||
| } | |||
| } | |||
| .flow-list { | |||
| margin: 0; | |||
| padding: 0 16rpx; | |||
| max-height: 75vh; | |||
| background: #fff; | |||
| } | |||
| .flow-item { | |||
| border-bottom: 1px solid #f5f5f5; | |||
| padding: 18rpx 0 8rpx 0; | |||
| &:last-child { | |||
| border-bottom: none; | |||
| } | |||
| .flow-item-row { | |||
| display: flex; | |||
| align-items: flex-start; | |||
| justify-content: space-between; | |||
| padding-right: 45rpx; | |||
| padding-left: 15rpx; | |||
| } | |||
| .flow-item-left { | |||
| display: flex; | |||
| flex-direction: column; | |||
| align-items: flex-start; | |||
| .flow-title { | |||
| font-size: 28rpx; | |||
| color: #222; | |||
| font-weight: 500; | |||
| margin-bottom: 2rpx; | |||
| } | |||
| .flow-date { | |||
| color: #bbb; | |||
| font-size: 22rpx; | |||
| margin-top: 0; | |||
| } | |||
| } | |||
| .flow-amount { | |||
| font-size: 26rpx; | |||
| font-weight: 500; | |||
| margin-left: 24rpx; | |||
| margin-top: 2rpx; | |||
| &.plus { | |||
| color: #223a7a; | |||
| } | |||
| &.minus { | |||
| color: #e94f7a; | |||
| } | |||
| } | |||
| } | |||
| </style> | |||