feat(金币代理收支明细页面): 调整接口并新增上拉加载功能

This commit is contained in:
hzj 2025-12-09 18:37:28 +08:00
parent 2c9c63ca52
commit 60468f1d70
2 changed files with 153 additions and 46 deletions

View File

@ -124,10 +124,17 @@ export function freightRecharge(data) {
* @param {string} data
* @returns {Promise} 返回交易流水记录
*/
export function getFreightWaterFlow(data) {
return get(
`/wallet/freight/balance/running/water/client/flowByUserId?userId=${data.userId}&type=${data.type}&searchId=${data.searchId}`
)
export const getFreightWaterFlow = async (data) => {
try {
const response = await get(
`/wallet/freight/balance/running/water/client/flowByUserId?userId=${data.userId}&type=${data.type}&searchId=${data.searchId}&lastId=${data.lastId}`
)
return response
} catch (error) {
console.error('Failed to fetch bank card list:', error)
console.error('error:' + error.response.errorMsg)
throw error
}
}
/**

View File

@ -55,7 +55,7 @@
v-for="tab in tabs"
:key="tab.id"
ref="tabItems"
@click="switchTab(tab.id)"
@click="switchTab(tab)"
:style="{
flex: 1,
padding: '8px 16px',
@ -63,7 +63,7 @@
border: 'none',
fontWeight: '600',
fontSize: '14px',
color: activeTabId === tab.id ? '#8B5CF6' : 'rgba(0, 0, 0, 0.6)',
color: selectedTab.id === tab.id ? '#8B5CF6' : 'rgba(0, 0, 0, 0.6)',
cursor: 'pointer',
transition: 'all 0.3s',
position: 'relative',
@ -80,7 +80,7 @@
<!-- 用户列表(加载中...) -->
<div
v-if="loading"
v-if="loading && !records.length"
style="
display: flex;
flex-direction: column;
@ -125,6 +125,7 @@
display: flex;
align-items: center;
gap: 4px;
"
>
<!-- 头像 -->
@ -155,6 +156,7 @@
/>
</div>
<!-- 个人资料 -->
<div
style="
flex: 1;
@ -214,6 +216,18 @@
</div>
</div>
</div>
<!-- 收入列表触发加载功能 -->
<div
ref="incomeLoadmore"
v-show="incomeRecords.length != 0 && selectedTab?.langKey === 'income'"
></div>
<!-- 支出列表触发加载功能 -->
<div
ref="expenditureLoadmore"
v-show="expenditureRecords.length != 0 && selectedTab?.langKey === 'expenditure'"
></div>
</div>
<!-- 用户列表(加载完且列表为空) -->
@ -240,28 +254,46 @@
</template>
<script setup>
import { ref, onMounted, computed } from 'vue'
import { ref, onMounted, computed, nextTick } from 'vue'
import { useI18n } from 'vue-i18n'
import GeneralHeader from '@/components/GeneralHeader.vue'
import { getFreightWaterFlow } from '@/api/wallet.js'
import { setDocumentDirection } from '@/locales/i18n'
import { formatUTCCustom } from '@/utils/utcFormat.js'
import { getUserId } from '@/utils/userStore.js'
import { setDocumentDirection } from '@/locales/i18n'
import { handleAvatarImageError } from '@/utils/imageHandler.js'
import { useDebounce, useThrottle } from '@/utils/useDebounce'
import { getFreightWaterFlow } from '@/api/wallet.js'
import GeneralHeader from '@/components/GeneralHeader.vue'
const { t, locale } = useI18n()
//
locale.value && setDocumentDirection(locale.value)
const userId = ref(getUserId())
const loading = ref(false)
const records = ref([])
const incomeRecords = ref([]) //
const expenditureRecords = ref([]) //
const records = computed(() => {
if (selectedTab.value.langKey === 'income') {
return incomeRecords.value
} else {
return expenditureRecords.value
}
})
// div
const incomeLoadmore = ref(null)
const expenditureLoadmore = ref(null)
const searchQuery = ref('')
const searchResults = ref([])
const searchResults = ref([]) //
const isSearching = ref(false)
const hasSearched = ref(false)
const activeTabId = ref(0)
const selectedTab = ref({ id: 0, langKey: 'income' })
const tabItems = ref([]) // DOM
//
const tabs = ref([
@ -270,9 +302,11 @@ const tabs = ref([
])
//
const switchTab = (tabId) => {
activeTabId.value = tabId
fetchRecords()
const switchTab = async (tab) => {
selectedTab.value = tab
await fetchRecords() //
reSetObserve() //
}
// 线
@ -280,7 +314,7 @@ const underlineStyle = computed(() => {
console.log('计算属性')
if (tabItems.value.length === 0) return {} //
const activeTab = tabItems.value[activeTabId.value]
const activeTab = tabItems.value[selectedTab.value.id]
console.log('选中元素的左边距', activeTab.offsetLeft)
return {
@ -298,43 +332,50 @@ const getAmountDisplay = (type, quantity) => {
}
//
const fetchRecords = async () => {
const fetchRecords = async (lastId = '') => {
loading.value = true
try {
// ID
const userId = getUserId()
if (!userId) {
if (!userId.value) {
console.error('无法获取用户ID')
records.value = []
return
}
//
if (records.value.length != 0 && lastId == '') {
return
}
//
let data = {
userId: userId,
type: activeTabId.value,
searchId: searchQuery.value,
userId: userId.value, //id
type: selectedTab.value.id, //
searchId: searchQuery.value, //id
lastId, //id
}
const response = await getFreightWaterFlow(data)
if (response && response.status && response.body) {
//
records.value = response.body.map((item) => ({
let records = response.body.map((item) => ({
...item,
amount: getAmountDisplay(item.type, item.quantity), //±
time: formatUTCCustom(item.createTime), //
}))
} else {
records.value = []
if (selectedTab.value.id == 1) {
expenditureRecords.value.push(...records)
} else {
incomeRecords.value.push(...records)
}
}
} catch (error) {
console.error('获取记录失败:', error)
records.value = []
} finally {
loading.value = false
console.log('加载完毕')
}
}
@ -342,33 +383,92 @@ const fetchRecords = async () => {
const clearSearch = () => {
hasSearched.value = false
searchQuery.value = ''
searchResults.value = members.value
searchResults.value = []
incomeRecords.value = [] //
expenditureRecords.value = [] //
fetchRecords() //
}
//
const performSearch = async () => {
console.log('searchQuery.value:', searchQuery.value)
const performSearch = useDebounce(
async () => {
console.log('searchQuery.value:', searchQuery.value)
if (!searchQuery.value.trim()) {
searchResults.value = members.value
return
}
if (!searchQuery.value.trim()) {
searchResults.value = []
return
}
isSearching.value = true
hasSearched.value = false
isSearching.value = true
hasSearched.value = false
searchResults.value = []
if (searchQuery.value.trim()) {
fetchRecords()
}
searchResults.value = []
if (searchQuery.value.trim()) {
incomeRecords.value = [] //
expenditureRecords.value = [] //
await fetchRecords() //
}
isSearching.value = false
hasSearched.value = true
isSearching.value = false
hasSearched.value = true
},
500,
true
)
const throttleFetch = useThrottle((fetchFn) => {
fetchFn()
}, 1000)
// IntersectionObserver
const obsever = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.intersectionRatio > 0) {
console.log('监控到底部')
let lastId = records.value[records.value.length - 1].id
console.log('lastId:', lastId)
if (entry.target === incomeLoadmore.value) {
console.log('incomeLoadmore')
throttleFetch(() => {
fetchRecords(lastId) //income
})
}
if (entry.target === expenditureLoadmore.value) {
console.log('expenditureLoadmore')
throttleFetch(() => {
fetchRecords(lastId) //expenditure
})
}
}
})
})
//
const reSetObserve = () => {
nextTick(() => {
if (incomeLoadmore.value) {
obsever.unobserve(incomeLoadmore.value)
obsever.observe(incomeLoadmore.value)
}
if (expenditureLoadmore.value) {
obsever.unobserve(expenditureLoadmore.value)
obsever.observe(expenditureLoadmore.value)
}
})
}
onMounted(async () => {
await fetchRecords()
underlineStyle.value //
if (incomeLoadmore.value) {
obsever.observe(incomeLoadmore.value) //
}
if (expenditureLoadmore.value) {
obsever.observe(expenditureLoadmore.value) //
}
})
</script>