212 lines
7.2 KiB
Vue
212 lines
7.2 KiB
Vue
<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>
|