diff --git a/src/api/reports.ts b/src/api/reports.ts new file mode 100644 index 0000000..dc40894 --- /dev/null +++ b/src/api/reports.ts @@ -0,0 +1,16 @@ +import { http } from "@/api/http"; +import type { RiskReportResult } from "@/types/risk"; + +export function downloadReportPdf(payload: RiskReportResult) { + return http.post("/v1/reports/pdf", payload, { + responseType: "blob", + timeout: 60_000, + }); +} + +export function downloadReportWord(payload: RiskReportResult) { + return http.post("/v1/reports/word", payload, { + responseType: "blob", + timeout: 60_000, + }); +} diff --git a/src/components/assistant/AssistantResponseCard.vue b/src/components/assistant/AssistantResponseCard.vue index 1a675db..2742822 100644 --- a/src/components/assistant/AssistantResponseCard.vue +++ b/src/components/assistant/AssistantResponseCard.vue @@ -98,9 +98,9 @@ function formatCount(value: unknown) { {{ formatCount(data.anomalyCount) }}近3年异常 -
+
{{ formatCount(data.cooperationCount) }}合作频次(代理) + >合作频次(采购订单)
×{{ data.frequencyCoefficient?.toFixed(2) ?? "1.00" }}(); +const emit = defineEmits<{ generateReport: [] }>(); const expanded = ref(true); const feedback = ref(""); @@ -161,16 +162,9 @@ const stars = computed(() => { 供应商层级{{ result.supplierFreq.tier }}
-
- 合作频次(代理) - {{ - result.supplierFreq.cooperationCount ?? - result.supplierFreq.anomalyCount ?? - 0 - }} - 次 +
+ 合作频次(采购订单) + {{ result.supplierFreq.cooperationCount }} 次
管理建议{{ result.supplierFreq.suggestion }} @@ -190,7 +184,7 @@ const stars = computed(() => { > {{ result.supplierFreq.note || - "当前以近3年异常记录数作为合作频次代理,不代表真实采购订单合作次数。" + "合作频次按近3年采购订单去重单据编号统计;异常数仍按异常案例库统计。" }} @@ -298,7 +292,7 @@ const stars = computed(() => { diff --git a/src/pages/ReportPage.vue b/src/pages/ReportPage.vue new file mode 100644 index 0000000..7a8bf7e --- /dev/null +++ b/src/pages/ReportPage.vue @@ -0,0 +1,488 @@ + + + + + diff --git a/src/pages/RiskAssistantPage.vue b/src/pages/RiskAssistantPage.vue index 5620d4e..808c87b 100644 --- a/src/pages/RiskAssistantPage.vue +++ b/src/pages/RiskAssistantPage.vue @@ -11,6 +11,7 @@ import OcrRecognitionDialog from "@/components/ocr/OcrRecognitionDialog.vue"; import { useConversationStore } from "@/stores/conversation.store"; import { useAuthStore } from "@/stores/auth.store"; import { storeToRefs } from "pinia"; +import type { RiskAssessmentResult } from "@/types/risk"; const route = useRoute(); const router = useRouter(); @@ -217,6 +218,11 @@ async function openFromRoute() { } } +function openReport(result: RiskAssessmentResult) { + sessionStorage.setItem("dieya-risk-report", JSON.stringify(result)); + void router.push({ name: "report" }); +} + async function submit( messageType: "text" | "image" | "file" | "audio" = "text", ) { @@ -315,6 +321,7 @@ async function scrollToBottom(behavior: "smooth" | "auto" = "smooth") { v-if="message.riskResult" :result="message.riskResult" :can-monitor="canMonitor" + @generate-report="openReport(message.riskResult)" /> import("@/pages/ReportPage.vue"), + meta: { + title: "风险报告", + requiresAuth: true, + permission: "risk.assess", + }, + }, { path: "overview", name: "overview", diff --git a/src/types/risk.ts b/src/types/risk.ts index d3a0bd6..cc7b92b 100644 --- a/src/types/risk.ts +++ b/src/types/risk.ts @@ -77,6 +77,8 @@ export interface RiskAssessmentResult { dimensionScores?: RiskDimensionScore[]; } +export type RiskReportResult = RiskAssessmentResult; + export interface ModelInfo { modelVersion: string; scoreRange: string;