393 lines
9.0 KiB
Vue
393 lines
9.0 KiB
Vue
<template>
|
|
<view class="page">
|
|
<u-navbar :title="navTitle" :border-bottom="false" :background="bgc" back-icon-color="#111827" title-color="#111827" title-size="34" height="44"></u-navbar>
|
|
|
|
<view class="log-summary" v-if="total > 0">
|
|
<text>共 {{ total }} 条记录</text>
|
|
<text class="log-summary-tip">下拉可刷新</text>
|
|
</view>
|
|
|
|
<scroll-view
|
|
class=""
|
|
scroll-y
|
|
:refresher-enabled="true"
|
|
:refresher-triggered="refreshing"
|
|
refresher-default-style="black"
|
|
@refresherrefresh="onRefresherRefresh"
|
|
@scrolltolower="loadMore"
|
|
>
|
|
<view class="log-loading" v-if="loading && !logList.length">加载中...</view>
|
|
<view class="log-empty" v-else-if="!logList.length">暂无流水记录</view>
|
|
|
|
<view class="log-list" v-else>
|
|
<view class="log-item" v-for="(item, index) in logList" :key="item.id || index">
|
|
<view class="log-item-meta">
|
|
<text class="log-meta-text">{{ item.abilityName || '--' }}</text>
|
|
<text class="log-time">{{ item.createTime || '--' }}</text>
|
|
</view>
|
|
<view class="log-item-top">
|
|
<view class="log-item-top-left">
|
|
<text class="log-reason">{{ item.reason || '--' }}</text>
|
|
</view>
|
|
</view>
|
|
<view class="log-item-bottom">
|
|
<view class="log-count-inline">
|
|
<text class="log-count-label">变化</text>
|
|
<text class="log-count-val" :class="{ 'log-count-val--up': item.changeUp, 'log-count-val--down': item.changeDown }">{{ item.changeCountText }}</text>
|
|
</view>
|
|
<view class="log-count-inline">
|
|
<text class="log-count-label">前</text>
|
|
<text class="log-count-val">{{ item.changeBeforeText }}</text>
|
|
</view>
|
|
<view class="log-count-inline">
|
|
<text class="log-count-label">后</text>
|
|
<text class="log-count-val">{{ item.changeAfterText }}</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="log-footer-tip" v-if="logList.length && loadingMore">加载中...</view>
|
|
<view class="log-footer-tip" v-else-if="logList.length && noMore">— 没有更多了 —</view>
|
|
<view class="scroll-bottom-space"></view>
|
|
</scroll-view>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
export default {
|
|
data() {
|
|
return {
|
|
bgc: { backgroundColor: '#fff' },
|
|
areaId: '',
|
|
areaName: '',
|
|
areaAbilityId: '',
|
|
abilityName: '',
|
|
logList: [],
|
|
loading: false,
|
|
loadingMore: false,
|
|
refreshing: false,
|
|
noMore: false,
|
|
pageNum: 1,
|
|
pageSize: 15,
|
|
total: 0
|
|
}
|
|
},
|
|
computed: {
|
|
navTitle() {
|
|
const name = this.abilityName || '拓展能力'
|
|
return `${name} · 流水`
|
|
}
|
|
},
|
|
onLoad(e) {
|
|
this.areaId = e.areaId || ''
|
|
this.areaName = e.areaName ? decodeURIComponent(e.areaName) : ''
|
|
this.areaAbilityId = e.areaAbilityId || ''
|
|
this.abilityName = e.abilityName ? decodeURIComponent(e.abilityName) : ''
|
|
this.resetAndFetch()
|
|
},
|
|
onPullDownRefresh() {
|
|
this.onRefresherRefresh()
|
|
},
|
|
onReachBottom() {
|
|
this.loadMore()
|
|
},
|
|
methods: {
|
|
formatCount(val) {
|
|
const n = Number(val)
|
|
return Number.isFinite(n) ? n : 0
|
|
},
|
|
bstTypeLabel(item) {
|
|
const type = (item && item.bstType) || ''
|
|
const map = {
|
|
RECHARGE: '充值',
|
|
CONSUME: '消费',
|
|
DEDUCT: '扣减',
|
|
GIFT: '赠送',
|
|
BUY: '购买',
|
|
REFUND: '退款',
|
|
ADJUST: '调整'
|
|
}
|
|
if (map[type]) return map[type]
|
|
if (type) return type
|
|
const reason = (item && item.reason) || ''
|
|
if (reason.indexOf('充值') !== -1) return '充值'
|
|
if (reason.indexOf('购买') !== -1) return '购买'
|
|
if (reason.indexOf('赠送') !== -1) return '赠送'
|
|
return ''
|
|
},
|
|
mapLogItem(item) {
|
|
const changeCount = Number(item && item.changeCount)
|
|
const changeUp = Number.isFinite(changeCount) && changeCount > 0
|
|
const changeDown = Number.isFinite(changeCount) && changeCount < 0
|
|
let changeCountText = '0'
|
|
if (Number.isFinite(changeCount)) {
|
|
changeCountText = changeCount > 0 ? '+' + changeCount : String(changeCount)
|
|
}
|
|
return {
|
|
...item,
|
|
typeLabel: this.bstTypeLabel(item),
|
|
changeUp,
|
|
changeDown,
|
|
changeCountText,
|
|
changeBeforeText: this.formatCount(item && item.changeBefore),
|
|
changeAfterText: this.formatCount(item && item.changeAfter)
|
|
}
|
|
},
|
|
normalizeRows(res) {
|
|
if (res.code != 200) return []
|
|
const rows = res.rows != null ? res.rows : (Array.isArray(res.data) ? res.data : [])
|
|
return rows.map((item) => this.mapLogItem(item))
|
|
},
|
|
onRefresherRefresh() {
|
|
this.refreshing = true
|
|
this.resetAndFetch()
|
|
},
|
|
resetAndFetch() {
|
|
this.pageNum = 1
|
|
this.logList = []
|
|
this.noMore = false
|
|
this.fetchList(true)
|
|
},
|
|
fetchList(reset) {
|
|
if (!this.areaAbilityId && !this.areaId) {
|
|
this.logList = []
|
|
this.finishRefresh()
|
|
return
|
|
}
|
|
if (reset) {
|
|
this.loading = true
|
|
} else {
|
|
this.loadingMore = true
|
|
}
|
|
const params = {
|
|
pageNum: this.pageNum,
|
|
pageSize: this.pageSize,
|
|
orderByColumn: 'createTime',
|
|
isAsc: 'desc'
|
|
}
|
|
if (this.areaAbilityId) {
|
|
params.areaAbilityId = this.areaAbilityId
|
|
}
|
|
if (this.areaId) {
|
|
params.areaId = this.areaId
|
|
}
|
|
this.$u
|
|
.get('/bst/areaAbilityLog/list', params)
|
|
.then((res) => {
|
|
if (res.code == 200) {
|
|
const rows = this.normalizeRows(res)
|
|
this.total = res.total != null ? res.total : 0
|
|
if (reset) {
|
|
this.logList = rows
|
|
} else {
|
|
this.logList = this.logList.concat(rows)
|
|
}
|
|
if (rows.length < this.pageSize) {
|
|
this.noMore = true
|
|
} else {
|
|
this.pageNum += 1
|
|
}
|
|
} else {
|
|
if (reset) {
|
|
this.logList = []
|
|
this.total = 0
|
|
}
|
|
uni.showToast({ title: res.msg || '加载失败', icon: 'none' })
|
|
}
|
|
})
|
|
.catch(() => {
|
|
if (reset) {
|
|
this.logList = []
|
|
this.total = 0
|
|
}
|
|
uni.showToast({ title: '加载失败', icon: 'none' })
|
|
})
|
|
.finally(() => {
|
|
this.loading = false
|
|
this.loadingMore = false
|
|
this.finishRefresh()
|
|
})
|
|
},
|
|
finishRefresh() {
|
|
this.refreshing = false
|
|
uni.stopPullDownRefresh()
|
|
},
|
|
loadMore() {
|
|
if (this.loading || this.loadingMore || this.noMore) return
|
|
this.fetchList(false)
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss">
|
|
page {
|
|
background: #f6f8fa;
|
|
height: 100%;
|
|
}
|
|
.page {
|
|
height: 100vh;
|
|
display: flex;
|
|
flex-direction: column;
|
|
overflow: hidden;
|
|
}
|
|
.log-summary {
|
|
flex-shrink: 0;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding: 12rpx 24rpx;
|
|
font-size: 22rpx;
|
|
color: #6b7280;
|
|
background: #fff;
|
|
border-bottom: 1rpx solid #eef2f7;
|
|
}
|
|
.log-summary-tip {
|
|
color: #9ca3af;
|
|
font-size: 20rpx;
|
|
}
|
|
.log-scroll {
|
|
height: 85vh;
|
|
}
|
|
.log-loading,
|
|
.log-empty {
|
|
margin: 16rpx;
|
|
padding: 48rpx 0;
|
|
text-align: center;
|
|
font-size: 26rpx;
|
|
color: #9ca3af;
|
|
background: #fff;
|
|
border-radius: 12rpx;
|
|
}
|
|
.log-list {
|
|
background: #fff;
|
|
margin: 12rpx 16rpx 0;
|
|
border-radius: 12rpx;
|
|
overflow: hidden;
|
|
border: 1rpx solid #eef2f7;
|
|
}
|
|
.log-item {
|
|
padding: 16rpx 20rpx;
|
|
border-bottom: 1rpx solid #f3f4f6;
|
|
&:last-child {
|
|
border-bottom: none;
|
|
}
|
|
}
|
|
.log-item-top {
|
|
display: flex;
|
|
align-items: flex-start;
|
|
justify-content: space-between;
|
|
gap: 12rpx;
|
|
}
|
|
.log-item-top-left {
|
|
flex: 1;
|
|
min-width: 0;
|
|
display: flex;
|
|
align-items: flex-start;
|
|
gap: 8rpx;
|
|
}
|
|
.log-tag {
|
|
flex-shrink: 0;
|
|
margin-top: 2rpx;
|
|
padding: 2rpx 10rpx;
|
|
font-size: 20rpx;
|
|
line-height: 1.3;
|
|
color: #4297F3;
|
|
background: #eff6ff;
|
|
border-radius: 6rpx;
|
|
}
|
|
.log-reason {
|
|
flex: 1;
|
|
font-size: 24rpx;
|
|
color: #374151;
|
|
line-height: 1.4;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
display: -webkit-box;
|
|
-webkit-line-clamp: 2;
|
|
-webkit-box-orient: vertical;
|
|
}
|
|
.log-time {
|
|
flex-shrink: 0;
|
|
font-size: 20rpx;
|
|
color: #9ca3af;
|
|
line-height: 1.4;
|
|
max-width: 200rpx;
|
|
text-align: right;
|
|
}
|
|
.log-item-meta {
|
|
margin-top: 8rpx;
|
|
font-size: 22rpx;
|
|
line-height: 1.35;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
width: 100%;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
}
|
|
.log-meta-text {
|
|
color: #111827;
|
|
font-weight: 600;
|
|
font-size: 28rpx;
|
|
}
|
|
.log-meta-link {
|
|
color: #4297F3;
|
|
}
|
|
.log-meta-sub {
|
|
color: #9ca3af;
|
|
}
|
|
.log-meta-dot,
|
|
.log-meta-split {
|
|
margin: 0 6rpx;
|
|
color: #d1d5db;
|
|
}
|
|
.log-item-bottom {
|
|
margin-top: 10rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
flex-wrap: wrap;
|
|
gap: 16rpx 20rpx;
|
|
}
|
|
.log-count-inline {
|
|
display: flex;
|
|
align-items: baseline;
|
|
gap: 4rpx;
|
|
}
|
|
.log-count-label {
|
|
font-size: 20rpx;
|
|
color: #9ca3af;
|
|
}
|
|
.log-count-val {
|
|
font-size: 24rpx;
|
|
font-weight: 600;
|
|
color: #111827;
|
|
}
|
|
.log-count-val--up {
|
|
color: #16a34a;
|
|
}
|
|
.log-count-val--down {
|
|
color: #ef4444;
|
|
}
|
|
.log-operator {
|
|
margin-left: auto;
|
|
font-size: 22rpx;
|
|
color: #4297F3;
|
|
max-width: 160rpx;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
}
|
|
.log-footer-tip {
|
|
padding: 20rpx;
|
|
text-align: center;
|
|
font-size: 22rpx;
|
|
color: #9ca3af;
|
|
}
|
|
.scroll-bottom-space {
|
|
height: 24rpx;
|
|
}
|
|
</style>
|