@@ -3194,7 +3211,7 @@
if (reviews.length === 0) {
document.getElementById('reviewsTable').innerHTML = `
-
| 暂无数据 |
+
| 暂无数据 |
`;
return;
}
@@ -3207,20 +3224,34 @@
const html = reviews.map(r => {
const catName = categories.find(c => c.id === r.category_id)?.name || r.category_id;
+ // 提取关键参数预览
+ const data = r.data || {};
+ const previewFields = [];
+ ['organization', 'model_type', 'parameters', 'context_length', 'release_year'].forEach(key => {
+ if (data[key]) previewFields.push(`
${data[key]}`);
+ });
+ const preview = previewFields.length > 0 ? previewFields.slice(0, 3).join(' · ') : '-';
+
return `
-
- | ${r.data?.name || '-'} |
+
+ |
+ ${r.data?.name || '-'}
+ ${preview}
+ |
${catName} |
${r.source === 'api' ? 'API' : '网页'}
|
+
+ ${r.submitter ? `${r.submitter}` : '匿名'}
+ |
${r.created_at} |
${statusLabels[r.status] || r.status} |
${r.status === 'pending' ? `
-
+
+
-
` : `
`}
@@ -3232,7 +3263,7 @@
document.getElementById('reviewsTable').innerHTML = html;
} catch (e) {
document.getElementById('reviewsTable').innerHTML = `
- |
| 加载失败: ${e.message} |
+
| 加载失败: ${e.message} |
`;
}
}
@@ -3279,26 +3310,205 @@
}
}
+ // 当前审核详情ID
+ let currentReviewId = '';
+
// 查看审核详情
async function viewReviewDetail(reviewId) {
+ currentReviewId = reviewId;
try {
const res = await fetch(`/api/reviews/${reviewId}`);
const review = await res.json();
- let html = '
';
- html += `
状态: ${review.status}
`;
- html += `
分类: ${review.category_id}
`;
- html += `
来源: ${review.source}
`;
- html += `
提交时间: ${review.created_at}
`;
- html += '
产品数据:
';
- html += '
' + JSON.stringify(review.data, null, 2) + '
';
- html += '
';
+ const catName = categories.find(c => c.id === review.category_id)?.name || review.category_id;
+ const statusLabels = {
+ pending: '
待审核',
+ approved: '
已通过',
+ rejected: '
已拒绝'
+ };
- alert(html.replace(/<[^>]+>/g, ' ').replace(/\s+/g, ' ').trim());
+ let html = `
+
+
+
+
基本信息
+
+
状态:${statusLabels[review.status] || review.status}
+
分类:${catName}
+
来源:${review.source === 'api' ? 'API提交' : '网页提交'}
+
提交者:${review.submitter || '匿名'}
+
提交时间:${review.created_at}
+
+ ${review.status === 'rejected' && review.reject_reason ? `
+
+ 拒绝原因:
+ ${review.reject_reason}
+
+ ` : ''}
+ ${review.status === 'approved' ? `
+
+ 审核通过时间:
+ ${review.approved_at || '-'}
+
+ ` : ''}
+
+
+
+
+
产品数据
+
+ ${renderProductData(review.data, review.category_id)}
+
+
+
+ `;
+
+ document.getElementById('reviewDetailContent').innerHTML = html;
+
+ // 操作按钮
+ let actionsHtml = '';
+ if (review.status === 'pending') {
+ actionsHtml = `
+
+
+
+ `;
+ } else {
+ actionsHtml = `
`;
+ }
+ document.getElementById('reviewDetailActions').innerHTML = actionsHtml;
+
+ document.getElementById('reviewDetailModal').classList.remove('hidden');
} catch (e) {
alert('加载失败: ' + e.message);
}
}
+
+ // 渲染产品数据(格式化显示)
+ function renderProductData(data, categoryId) {
+ if (!data) return '
无数据
';
+
+ // 获取分类的字段配置
+ const cat = categories.find(c => c.id === categoryId);
+ const fields = cat ? (cat.fields || []) : [];
+
+ // 排序字段:名称放第一
+ const sortedFields = [...fields].sort((a, b) => {
+ if (a.key === 'name') return -1;
+ if (b.key === 'name') return 1;
+ return 0;
+ });
+
+ let html = '';
+
+ // 先显示有字段配置的值
+ sortedFields.forEach(field => {
+ const value = data[field.key];
+ if (value !== undefined && value !== null && value !== '') {
+ html += renderFieldRow(field, value);
+ }
+ });
+
+ // 再显示其他没有字段配置的值
+ Object.keys(data).forEach(key => {
+ if (!fields.find(f => f.key === key)) {
+ const value = data[key];
+ if (value !== undefined && value !== null && value !== '') {
+ html += `
+
${key}
+
${formatValue(value)}
+
`;
+ }
+ }
+ });
+
+ return html || '
无数据
';
+ }
+
+ // 渲染单个字段行
+ function renderFieldRow(field, value) {
+ const label = field.label || field.key;
+ const type = field.type || 'text';
+ let displayValue = formatValue(value, type);
+
+ return `
+
${label}
+
${displayValue}
+
`;
+ }
+
+ // 格式化值
+ function formatValue(value, type = 'text') {
+ if (value === null || value === undefined) return '-';
+ if (typeof value === 'boolean') return value ? '
是' : '
否';
+ if (typeof value === 'object') {
+ if (Array.isArray(value)) {
+ if (value.length === 0) return '-';
+ // 如果是图片数组
+ if (typeof value[0] === 'string' && (value[0].startsWith('http') || value[0].startsWith('/'))) {
+ return value.map(url => `

`).join('');
+ }
+ return value.join(', ');
+ }
+ return `
${JSON.stringify(value, null, 2)}`;
+ }
+ if (type === 'url' || (typeof value === 'string' && value.startsWith('http'))) {
+ return `
${value}`;
+ }
+ return String(value);
+ }
+
+ // 关闭审核详情弹窗
+ function closeReviewDetailModal() {
+ document.getElementById('reviewDetailModal').classList.add('hidden');
+ currentReviewId = '';
+ }
+
+ // 从弹窗中通过审核
+ async function approveReviewFromModal() {
+ if (!currentReviewId) return;
+ if (!confirm('确认通过该产品审核?')) return;
+ try {
+ const res = await fetch(`/api/reviews/${currentReviewId}/approve`, {method: 'POST'});
+ const data = await res.json();
+ if (data.error) {
+ alert('操作失败: ' + data.error);
+ } else {
+ alert('审核通过,产品已发布!');
+ closeReviewDetailModal();
+ loadReviews();
+ loadNotificationCounts();
+ loadOverview();
+ }
+ } catch (e) {
+ alert('操作失败: ' + e.message);
+ }
+ }
+
+ // 从弹窗中拒绝审核
+ async function rejectReviewFromModal() {
+ if (!currentReviewId) return;
+ const reason = prompt('请输入拒绝原因(可选):');
+ if (reason === null) return; // 用户取消
+ try {
+ const res = await fetch(`/api/reviews/${currentReviewId}/reject`, {
+ method: 'POST',
+ headers: {'Content-Type': 'application/json'},
+ body: JSON.stringify({reason})
+ });
+ const data = await res.json();
+ if (data.error) {
+ alert('操作失败: ' + data.error);
+ } else {
+ alert('已拒绝该产品!');
+ closeReviewDetailModal();
+ loadReviews();
+ loadNotificationCounts();
+ }
+ } catch (e) {
+ alert('操作失败: ' + e.message);
+ }
+ }
init();