@@ -200,6 +207,14 @@ import { ref, computed, watch, onBeforeUnmount } from 'vue'
import { Document, ArrowDown, Upload, Loading, CircleCheckFilled } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'
import { posterApi } from '@/utils/poster-api'
+import ReviewStatusSummary from '@/components/generation/ReviewStatusSummary.vue'
+
+type ReviewStatusItem = {
+ key: string
+ label: string
+ value: number | string
+ tone?: 'neutral' | 'success' | 'warning' | 'danger'
+}
const props = defineProps<{
productId: string
@@ -297,6 +312,27 @@ const hasManualChanges = computed(() => Object.keys(localFields.value).some((key
if (key === 'meta' || key === 'benefit_table') return false
return localFields.value[key] !== props.parsedFields?.[key]
}))
+const provenanceEntries = computed
(() => Object.values(parseDiagnostics.value?.provenance || {}))
+const manualSourceCount = computed(() => provenanceEntries.value.filter(item => item?.source === 'manual_override').length)
+const derivedSourceCount = computed(() => provenanceEntries.value.filter(item => item?.source === 'system_derived').length)
+const missingFieldCount = computed(() => (parseDiagnostics.value?.missingFields || []).length)
+const conflictFieldCount = computed(() => (parseDiagnostics.value?.conflicts || []).length)
+const automaticFieldCount = computed(() => Math.max(
+ 0,
+ confirmedFieldCount.value - manualSourceCount.value - derivedSourceCount.value,
+))
+const sourceReviewItems = computed(() => [
+ { key: 'automatic', label: '自动提取', value: automaticFieldCount.value, tone: 'success' },
+ { key: 'missing', label: '缺失', value: missingFieldCount.value, tone: missingFieldCount.value ? 'danger' : 'neutral' },
+ { key: 'conflict', label: '冲突', value: conflictFieldCount.value, tone: conflictFieldCount.value ? 'danger' : 'neutral' },
+ { key: 'derived', label: '系统推导', value: derivedSourceCount.value, tone: derivedSourceCount.value ? 'warning' : 'neutral' },
+ { key: 'manual', label: '人工覆盖', value: manualSourceCount.value + (hasManualChanges.value ? 1 : 0), tone: manualSourceCount.value || hasManualChanges.value ? 'warning' : 'neutral' },
+])
+const sourceReviewDescription = computed(() => {
+ if (props.dataConfirmed) return '这份数据已经人工确认;再次修改后需要重新确认。'
+ if (missingFieldCount.value || conflictFieldCount.value) return '请补齐缺失项并处理冲突,服务端会在确认时再次校验。'
+ return '请核对金额、币种和客户信息,确认后才能进入生成。'
+})
function fieldSourceText(field: string, derivedText: string) {
const source = parseDiagnostics.value?.provenance?.[field]?.source
@@ -521,14 +557,23 @@ onBeforeUnmount(stopPolling)
diff --git a/frontend/src/pages/admin/PptProductsAdmin.vue b/frontend/src/pages/admin/PptProductsAdmin.vue
index a145472..8d64e93 100644
--- a/frontend/src/pages/admin/PptProductsAdmin.vue
+++ b/frontend/src/pages/admin/PptProductsAdmin.vue
@@ -238,7 +238,7 @@ const reviewSaving = ref(false)
const pdfPreviewUrl = computed(() => reviewTarget.value ? pptAdminApi.getManualFileUrl(reviewTarget.value.id) : '')
// 轮询管理
-let pollTimers: Record> = {}
+const pollTimers: Record> = {}
const MAX_POLL_DURATION = 7 * 60 * 1000 // 略长于后端 6 分钟硬超时
onMounted(async () => {
diff --git a/frontend/src/pages/admin/PptSettingsAdmin.vue b/frontend/src/pages/admin/PptSettingsAdmin.vue
index 08b6801..6d25553 100644
--- a/frontend/src/pages/admin/PptSettingsAdmin.vue
+++ b/frontend/src/pages/admin/PptSettingsAdmin.vue
@@ -217,23 +217,6 @@ function onPosterProviderChange(val: string) {
}
}
-// 从模型名推断 base_url
-const MODEL_BASE_URLS: Record = {
- 'deepseek': 'https://api.deepseek.com/v1',
- 'minimax': 'https://api.minimax.chat/v1',
- 'gemini': 'https://generativelanguage.googleapis.com/v1/models',
- 'gpt': 'https://api.openai.com/v1',
- 'claude': 'https://api.anthropic.com/v1',
-}
-
-function inferBaseUrl(model: string): string {
- const lower = model.toLowerCase()
- for (const [keyword, url] of Object.entries(MODEL_BASE_URLS)) {
- if (lower.startsWith(keyword)) return url
- }
- return ''
-}
-
async function handleSyncModels() {
syncingModels.value = true
try {
diff --git a/frontend/src/pages/components/ppt/PdfPagePreview.vue b/frontend/src/pages/components/ppt/PdfPagePreview.vue
index aa14466..d90f8a8 100644
--- a/frontend/src/pages/components/ppt/PdfPagePreview.vue
+++ b/frontend/src/pages/components/ppt/PdfPagePreview.vue
@@ -17,13 +17,15 @@
加载中...