- 前端免费排盘默认不保存,勾选同意后才调用保存接口 - 服务端要求 consentVersion,记录 consentAt,校验并限流公开保存接口 - 付费结算单独披露报告快照与订单信息将由服务端存储 - 管理端展示同意版本与时间,历史无同意证据记录保留并标注 Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
58 lines
4.0 KiB
JavaScript
58 lines
4.0 KiB
JavaScript
import { onMounted, ref } from 'vue';
|
|
import { adminHeader } from './AdminHeader.js';
|
|
|
|
export default {
|
|
setup() {
|
|
const records = ref([]);
|
|
const total = ref(0);
|
|
const loading = ref(true);
|
|
const error = ref('');
|
|
const search = ref('');
|
|
|
|
const load = async () => {
|
|
loading.value = true;
|
|
error.value = '';
|
|
try {
|
|
const params = new URLSearchParams({ page: '1', pageSize: '100' });
|
|
if (search.value) params.set('search', search.value);
|
|
const response = await fetch('/admin/api/charts?' + params.toString(), { credentials: 'same-origin' });
|
|
if (!response.ok) throw new Error('加载排盘记录失败');
|
|
const payload = await response.json();
|
|
records.value = payload.data.list || [];
|
|
total.value = payload.data.total || 0;
|
|
} catch (reason) {
|
|
error.value = reason instanceof Error ? reason.message : '加载排盘记录失败';
|
|
} finally {
|
|
loading.value = false;
|
|
}
|
|
};
|
|
|
|
onMounted(load);
|
|
return { records, total, loading, error, search, load };
|
|
},
|
|
template: `
|
|
<div class="min-h-screen bg-gray-100">
|
|
${adminHeader('charts')}
|
|
<main class="max-w-7xl mx-auto py-8 px-4 sm:px-6 lg:px-8">
|
|
<div class="bg-white shadow rounded-lg">
|
|
<div class="p-5 border-b flex flex-col sm:flex-row gap-3 sm:items-center sm:justify-between">
|
|
<div><h2 class="text-lg font-medium">排盘记录</h2><p class="text-xs text-gray-500 mt-1">共 {{ total }} 条用户主动同意保存的记录;付费报告快照另行关联</p></div>
|
|
<div class="flex gap-2"><input v-model="search" @keyup.enter="load" class="border rounded px-3 py-2 text-sm" placeholder="报告编号 / 姓名 / 城市" /><button @click="load" class="bg-red-700 text-white rounded px-4 py-2 text-sm">查询</button></div>
|
|
</div>
|
|
<div v-if="error" class="m-5 p-3 bg-red-50 text-red-700 text-sm">{{ error }}</div>
|
|
<div class="overflow-x-auto">
|
|
<table class="min-w-full divide-y divide-gray-200">
|
|
<thead class="bg-gray-50"><tr><th class="px-4 py-3 text-left text-xs text-gray-500">报告编号</th><th class="px-4 py-3 text-left text-xs text-gray-500">称呼</th><th class="px-4 py-3 text-left text-xs text-gray-500">出生信息</th><th class="px-4 py-3 text-left text-xs text-gray-500">城市</th><th class="px-4 py-3 text-left text-xs text-gray-500">同意记录</th><th class="px-4 py-3 text-left text-xs text-gray-500">记录时间</th></tr></thead>
|
|
<tbody class="divide-y divide-gray-100">
|
|
<tr v-if="loading"><td colspan="6" class="p-10 text-center text-sm text-gray-500">正在加载...</td></tr>
|
|
<tr v-else-if="records.length === 0"><td colspan="6" class="p-10 text-center text-sm text-gray-500">暂无排盘记录</td></tr>
|
|
<tr v-for="record in records" :key="record.id" class="hover:bg-gray-50"><td class="px-4 py-4 text-xs font-medium">{{ record.reportId }}</td><td class="px-4 py-4 text-sm">{{ record.name || '-' }}</td><td class="px-4 py-4 text-sm">{{ record.birthDate }} {{ record.birthTime }} / {{ record.gender }}</td><td class="px-4 py-4 text-sm">{{ record.city }}</td><td class="px-4 py-4 text-xs text-gray-500">{{ record.consentVersion || '迁移前记录(无同意凭证)' }}<br />{{ record.consentAt ? new Date(record.consentAt).toLocaleString('zh-CN', { hour12: false }) : '-' }}</td><td class="px-4 py-4 text-xs text-gray-500">{{ new Date(record.createdAt).toLocaleString('zh-CN', { hour12: false }) }}</td></tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</main>
|
|
</div>
|
|
`,
|
|
};
|