Files
ycc-proxy-webview/src/views/HistoryQuery.vue
2026-02-08 16:56:41 +08:00

212 lines
7.2 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.

<script setup>
import { ref, onMounted, computed } from 'vue'
import { useRouter } from 'vue-router'
import { storeToRefs } from 'pinia'
import { useUserStore } from '@/stores/userStore'
import { useAppStore } from '@/stores/appStore'
import { useDialogStore } from '@/stores/dialogStore'
import BindPhoneOnlyDialog from '@/components/BindPhoneOnlyDialog.vue'
import ShareReportButtonList from '@/components/ShareReportButtonList.vue'
const router = useRouter()
const userStore = useUserStore()
const appStore = useAppStore()
const dialogStore = useDialogStore()
const { isLoggedIn, mobile } = storeToRefs(userStore)
const page = ref(1)
const pageSize = ref(10)
const total = ref(0)
const reportList = ref([])
const num = ref(0)
const max = ref(60)
const loading = ref(false)
const finished = ref(false)
const showBindNotice = computed(() => isLoggedIn.value && !mobile.value && reportList.value.length > 0)
const hasNoRecords = computed(() => reportList.value.length === 0)
// 初始加载数据
async function fetchData() {
if (loading.value || finished.value) return
loading.value = true
try {
const { data, error } = await useApiFetch(`query/list?page=${page.value}&page_size=${pageSize.value}`)
.get()
.json()
if (data.value && !error.value) {
if (data.value.code === 200) {
total.value = data.value.data.total
if (data.value.data.list && data.value.data.list.length > 0) {
reportList.value.push(...data.value.data.list)
page.value += 1
}
if (reportList.value.length >= total.value) {
finished.value = true
}
} else {
// 接口返回错误,停止翻页
finished.value = true
console.error('获取查询列表失败:', data.value.msg || '未知错误')
}
} else {
// 请求失败或返回错误,停止翻页
finished.value = true
console.error('获取查询列表失败:', error.value || '请求失败')
}
} catch (err) {
// 捕获异常,停止翻页
finished.value = true
console.error('获取查询列表失败:', err)
} finally {
loading.value = false
}
}
// 初始加载
onMounted(async () => {
fetchData()
})
// 下拉触底加载更多
const onLoad = () => {
if (!finished.value) {
console.log("finished", finished.value)
if (num.value >= max.value) {
finished.value = true
} else {
fetchData()
}
}
}
function toDetail(item) {
if (item.query_state != "success") return
router.push({ path: '/report', query: { orderId: item.order_id } });
}
function toLogin() {
const redirect = encodeURIComponent('/historyQuery')
router.push({ path: '/login', query: { redirect, from: 'promotionInquire' } })
}
function handleBindSuccess() {
reportList.value = []
page.value = 1
finished.value = false
loading.value = false
fetchData()
}
// 状态文字映射
function stateText(state) {
switch (state) {
case 'pending':
return '查询中'
case 'success':
return '查询成功'
case 'failed':
return '查询失败'
case 'refunded':
return '已退款'
default:
return '未知状态'
}
}
// 状态颜色映射
function statusClass(state) {
switch (state) {
case 'pending':
return 'status-pending'
case 'success':
return 'status-success'
case 'failed':
return 'status-failed'
case 'refunded':
return 'status-refunded'
default:
return ''
}
}
</script>
<template>
<div class="flex flex-col gap-4 p-4">
<BindPhoneOnlyDialog @bind-success="handleBindSuccess" />
<div v-if="showBindNotice"
class="bg-yellow-50 border border-yellow-200 text-yellow-700 rounded-lg p-3 flex items-center justify-between">
<div class="text-sm">为防止报告丢失请绑定手机号</div>
<button class="px-3 py-1 text-sm font-medium bg-blue-500 text-white rounded"
@click="dialogStore.openBindPhone">绑定手机号</button>
</div>
<div class="text-xs text-gray-500">为保障用户隐私及数据安全报告保留{{ appStore.queryRetentionDays || 30 }}过期自动清理</div>
<div v-if="hasNoRecords"
class="bg-white rounded-lg shadow-sm p-6 flex flex-col items-center justify-center gap-3">
<div class="text-gray-600 text-sm">暂无历史报告</div>
<button v-if="!isLoggedIn || !mobile" class="px-4 py-2 bg-blue-500 text-white rounded"
@click="toLogin">登录</button>
</div>
<van-list v-model:loading="loading" :finished="finished" finished-text="没有更多了" @load="onLoad">
<div v-for="item in reportList" :key="item.id" class="bg-white rounded-lg shadow-sm p-4 mb-4">
<!-- 顶部标签 -->
<div class="flex items-center gap-2 mb-3">
<span class="px-2 py-1 text-xs rounded bg-blue-100 text-blue-700">{{ item.product_name }}</span>
</div>
<!-- 主要内容区域 -->
<div class="flex justify-between items-start mb-3">
<!-- 左侧姓名手机号查询时间 -->
<div class="flex-1">
<div v-if="item.params" class="mb-2 flex items-center gap-2">
<div v-if="item.params.name" class="text-lg font-medium text-black">
{{ item.params.name }}
</div>
<div v-if="item.params.mobile" class="text-sm text-gray-600">
{{ item.params.mobile }}
</div>
</div>
<div class="text-sm text-gray-500">
查询时间: {{ item.create_time }}
</div>
</div>
<!-- 右侧价格 -->
<div v-if="item.price" class="text-lg font-semibold text-blue-600">
¥{{ item.price.toFixed(2) }}
</div>
</div>
<!-- 底部按钮 -->
<div v-if="item.query_state === 'success'" class="flex gap-2 mt-3" @click.stop>
<button @click="toDetail(item)"
class="flex-1 px-4 py-2 text-sm bg-white border border-gray-300 text-gray-700 rounded-lg hover:bg-gray-50 transition-colors">
查看
</button>
<ShareReportButtonList :order-id="item.order_id" :disabled="false" />
</div>
</div>
</van-list>
</div>
</template>
<style scoped>
.status-pending {
background-color: #1976d2;
color: white;
}
.status-success {
background-color: #1FBE5D;
color: white;
}
.status-failed {
background-color: #EB3C3C;
color: white;
}
.status-refunded {
background-color: #999999;
color: white;
}
</style>