aslan-h5/src/views/SellerRecordsView.vue

466 lines
9.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="seller-records gradient-background-circles">
<!-- 使用 GeneralHeader 替换 MobileHeader -->
<GeneralHeader
:title="t('seller_records')"
:isHomePage="false"
:showLanguageList="true"
color="black"
style="box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); z-index: 999"
/>
<div class="content">
<!-- 搜索框 -->
<!-- <div style="display: flex; align-items: center; gap: 8px; margin-bottom: 8px">
<div
style="
flex: 1;
border-radius: 32px;
border: 1px solid #fff;
box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.25);
padding: 0 8px;
display: flex;
align-items: center;
height: max-content;
"
>
<img
src="../assets/icon/search.png"
alt=""
width="24px"
style="opacity: 0.6"
class="search-icon"
/>
<input
v-model="searchQuery"
type="text"
name=""
id=""
:placeholder="t('enter_user_id')"
@keyup.enter="handleEnterPress"
@input="handleInputChange"
style="
width: 100%;
color: rgba(0, 0, 0, 0.4);
font-weight: 600;
font-size: 14px;
outline: none;
border: none;
background-color: transparent;
padding: 10px 8px;
"
/>
<button
v-if="searchQuery"
@click="clearSearch"
style="
background: none;
border: none;
font-size: 18px;
color: #9ca3af;
cursor: pointer;
padding: 0 8px;
"
>
×
</button>
</div>
<div style="font-weight: 600" @click="handleActionButton" :disabled="isSearching">
{{ getActionButtonText() }}
</div>
</div> -->
<!-- 总信息 -->
<!-- <div
style="
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 12px;
"
>
<div style="font-size: 0.9em; font-weight: 600">{{ t('total_recharge') }}: +30000</div>
<div style="font-size: 0.9em; font-weight: 600">{{ t('total_expenditure') }}: -20000</div>
</div> -->
<!-- 用户列表 -->
<div v-if="loading" class="loading-state">
<div class="loading-spinner"></div>
<p>{{ t('loading') }}...</p>
</div>
<div v-else class="records-list">
<div v-for="record in records" :key="record.id" class="record-item">
<div class="record-info">
<div class="user-avatar">
<span>{{ record.userName.charAt(0) }}</span>
</div>
<div class="record-details">
<div style="display: flex; align-items: center">
<h4>User</h4>
<h4>{{ record.userName }}</h4>
<h4>...</h4>
</div>
<p>
<span style="display: flex; align-items: center">
<span>ID</span>
<span style="margin: 0 2px">:</span>
<span>{{ record.account }}</span>
</span>
</p>
</div>
</div>
<div class="record-amount">
<div class="coins-amount">{{ record.amount }} {{ t('coins') }}</div>
<div class="record-time">{{ record.time }}</div>
</div>
</div>
</div>
<div v-if="!loading && records.length === 0" class="empty-state">
<div class="empty-icon">📋</div>
<p>{{ t('no_transaction_records') }}</p>
<span>{{ t('no_selling_records_yet') }}</span>
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { useI18n } from 'vue-i18n'
import GeneralHeader from '../components/GeneralHeader.vue'
import { getFreightWaterFlow } from '../api/wallet.js'
import { formatUTCCustom } from '@/utils/utcFormat.js'
import { getUserId } from '@/utils/userStore.js'
import { setDocumentDirection } from '@/locales/i18n'
const { t, locale } = useI18n()
// 监听语言变化并设置文档方向
locale.value && setDocumentDirection(locale.value)
const loading = ref(false)
const records = ref([])
const searchQuery = ref('')
const searchResults = ref([])
const isSearching = ref(false)
const hasSearched = ref(false)
// Handle input changes
const handleInputChange = () => {
if (!searchQuery.value.trim()) {
searchResults.value = []
hasSearched.value = false
}
}
// Handle enter key press
const handleEnterPress = () => {
if (searchQuery.value.trim()) {
performSearch()
}
}
// Handle action button click
const handleActionButton = () => {
if (searchQuery.value.trim() && !hasSearched.value) {
performSearch()
} else {
cancelSearch()
}
}
// Clear search
const clearSearch = () => {
searchQuery.value = ''
searchResults.value = []
hasSearched.value = false
}
// Cancel search
const cancelSearch = () => {
// 这里应该使用 router但原代码中未导入 router
console.log('Cancel search')
}
// Get button text
const getActionButtonText = () => {
if (isSearching.value) return t('searching')
if (searchQuery.value.trim() && !hasSearched.value) return t('confirm')
return t('cancel')
}
// 获取金额显示
const getAmountDisplay = (type, quantity) => {
const prefix = type === 0 ? '+' : '-'
return `${prefix}${quantity}`
}
// 获取记录
const fetchRecords = async () => {
loading.value = true
try {
// 先获取用户ID
const userId = getUserId()
if (!userId) {
console.error('无法获取用户ID')
records.value = []
return
}
const response = await getFreightWaterFlow(userId)
if (response && response.status && response.body) {
// 处理返回的数据
records.value = response.body.map((item) => ({
id: item.id,
account: item.account,
userId: item.acceptUserId,
userName: `${item.acceptUserId.toString().slice(-6)}`, // 显示最后6位
amount: getAmountDisplay(item.type, item.quantity),
time: formatUTCCustom(item.createTime),
type: item.type,
quantity: item.quantity,
balance: item.balance,
origin: item.origin,
remark: item.remark,
rechargeType: item.rechargeType,
}))
} else {
records.value = []
}
} catch (error) {
console.error('获取记录失败:', error)
records.value = []
} finally {
loading.value = false
}
}
onMounted(async () => {
await fetchRecords()
})
</script>
<style scoped>
* {
color: rgba(0, 0, 0, 0.8);
font-family: 'SF Pro Text';
}
.seller-records {
font-family: -apple-system, BlinkMacSystemFont, sans-serif;
overflow-y: auto;
max-height: 100vh;
}
.seller-records::-webkit-scrollbar {
display: none;
}
.content {
padding: 16px;
position: relative;
z-index: 2;
}
/* 加载状态 */
.loading-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 60px 20px;
color: #666;
}
.loading-spinner {
width: 32px;
height: 32px;
border: 3px solid #f3f3f3;
border-top: 3px solid #f59e0b;
border-radius: 50%;
animation: spin 1s linear infinite;
margin-bottom: 16px;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.loading-state p {
margin: 0;
font-size: 14px;
}
/* 记录列表 */
.records-list {
display: flex;
flex-direction: column;
gap: 12px;
}
.record-item {
background-color: white;
padding: 16px;
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
display: flex;
align-items: center;
justify-content: space-between;
}
.record-info {
display: flex;
align-items: center;
flex: 1;
}
.user-avatar {
width: 50px;
height: 50px;
border-radius: 25px;
background-color: #9ca3af;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 18px;
font-weight: 600;
margin-right: 12px;
}
.record-details {
flex: 1;
}
.record-details h4 {
margin-bottom: 4px;
font-size: 0.9em;
font-weight: 600;
color: #333;
}
.record-details p {
font-size: 0.8em;
font-weight: 590;
color: rgba(0, 0, 0, 0.4);
}
.record-time {
font-size: 0.8em;
font-weight: 510;
color: rgba(0, 0, 0, 0.4);
}
.record-amount {
display: flex;
flex-direction: column;
align-items: flex-end;
gap: 4px;
}
.coins-amount {
font-size: 0.9em;
color: rgba(0, 0, 0, 0.4);
font-weight: 510;
}
.transaction-type {
font-size: 12px;
color: #9ca3af;
margin-top: 2px;
}
/* 空状态 */
.empty-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 60px 20px;
color: #666;
text-align: center;
}
.empty-icon {
font-size: 48px;
margin-bottom: 16px;
}
.empty-state p {
margin: 0 0 8px 0;
font-size: 16px;
font-weight: 500;
}
.empty-state span {
font-size: 14px;
color: #9ca3af;
}
input::placeholder {
font-weight: bold;
color: rgba(0, 0, 0, 0.4);
}
@media screen and (max-width: 360px) {
* {
font-size: 10px;
}
.help-btn {
width: 14px;
}
}
@media screen and (min-width: 360px) {
* {
font-size: 12px;
}
.help-btn {
width: 16px;
}
}
@media screen and (min-width: 768px) {
* {
font-size: 24px;
}
.help-btn {
width: 28px;
}
}
/* RTL支持 */
[dir='rtl'] .search-icon {
transform: scaleX(-1);
}
[dir='rtl'] .user-avatar {
margin-right: 0;
margin-left: 12px;
}
[dir='rtl'] .record-info {
text-align: right;
}
[dir='rtl'] .record-amount {
align-items: flex-start;
}
</style>