规范风险报告生成与方案追加规则
This commit is contained in:
parent
173e05eda6
commit
7f74f5a041
@ -17,7 +17,10 @@ import { useRouter } from "vue-router";
|
|||||||
import type { AssistantResponseCard } from "@/types/conversation";
|
import type { AssistantResponseCard } from "@/types/conversation";
|
||||||
import type { ReportCard } from "@/types/risk";
|
import type { ReportCard } from "@/types/risk";
|
||||||
|
|
||||||
const props = defineProps<{ card: AssistantResponseCard }>();
|
const props = defineProps<{
|
||||||
|
card: AssistantResponseCard;
|
||||||
|
canAppendReport?: boolean;
|
||||||
|
}>();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
generateReport: [card: ReportCard];
|
generateReport: [card: ReportCard];
|
||||||
@ -381,12 +384,13 @@ function generateReport() {
|
|||||||
|
|
||||||
<div class="response-actions">
|
<div class="response-actions">
|
||||||
<button
|
<button
|
||||||
|
v-if="card.type === 'solution' && canAppendReport"
|
||||||
type="button"
|
type="button"
|
||||||
class="response-actions__primary"
|
class="response-actions__primary"
|
||||||
title="追加到当前风险报告"
|
title="追加到当前风险报告"
|
||||||
@click="generateReport"
|
@click="generateReport"
|
||||||
>
|
>
|
||||||
<CheckCircle2 :size="14" />生成报告
|
<CheckCircle2 :size="14" />追加到报告
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
|
|||||||
@ -47,6 +47,7 @@ const toolInput = ref("");
|
|||||||
const toolError = ref("");
|
const toolError = ref("");
|
||||||
const toolFile = ref<File | null>(null);
|
const toolFile = ref<File | null>(null);
|
||||||
const expandedReplies = ref(new Set<number>());
|
const expandedReplies = ref(new Set<number>());
|
||||||
|
const primaryReportReady = ref(false);
|
||||||
const assessmentFields = ref({
|
const assessmentFields = ref({
|
||||||
category: "",
|
category: "",
|
||||||
specification: "",
|
specification: "",
|
||||||
@ -116,15 +117,22 @@ onActivated(async () => {
|
|||||||
// MainLayout keeps this page alive. Returning from report/dashboard therefore
|
// MainLayout keeps this page alive. Returning from report/dashboard therefore
|
||||||
// does not remount it, so explicitly reveal the newest message on re-entry.
|
// does not remount it, so explicitly reveal the newest message on re-entry.
|
||||||
if (conversation.value?.messages.length) await scrollToBottom("auto");
|
if (conversation.value?.messages.length) await scrollToBottom("auto");
|
||||||
|
refreshPrimaryReportState();
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => route.query.conversation,
|
() => route.query.conversation,
|
||||||
async () => {
|
async () => {
|
||||||
await openFromRoute();
|
await openFromRoute();
|
||||||
|
refreshPrimaryReportState();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => conversation.value?.id,
|
||||||
|
() => refreshPrimaryReportState(),
|
||||||
|
);
|
||||||
|
|
||||||
async function usePrompt(value: string) {
|
async function usePrompt(value: string) {
|
||||||
const current = prompt.value.trim();
|
const current = prompt.value.trim();
|
||||||
prompt.value = current ? `${current}\n${value}` : value;
|
prompt.value = current ? `${current}\n${value}` : value;
|
||||||
@ -356,6 +364,28 @@ function legacySolutionCards(result: RiskAssessmentResult): ReportCard[] {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isPrimaryRiskReport(
|
||||||
|
report: RiskAssessmentResult | null,
|
||||||
|
): report is RiskAssessmentResult {
|
||||||
|
return Boolean(
|
||||||
|
report &&
|
||||||
|
(report.dimensionScores?.length ||
|
||||||
|
report.factors?.length ||
|
||||||
|
report.categoryWarning ||
|
||||||
|
report.supplierFreq),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function refreshPrimaryReportState() {
|
||||||
|
const conversationId = conversation.value?.id;
|
||||||
|
primaryReportReady.value = Boolean(
|
||||||
|
conversationId &&
|
||||||
|
isPrimaryRiskReport(
|
||||||
|
readConversationReport(conversationId, auth.user?.id),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function openReport(result: RiskAssessmentResult) {
|
function openReport(result: RiskAssessmentResult) {
|
||||||
const conversationId = conversation.value?.id;
|
const conversationId = conversation.value?.id;
|
||||||
if (!conversationId) return;
|
if (!conversationId) return;
|
||||||
@ -376,6 +406,7 @@ function openReport(result: RiskAssessmentResult) {
|
|||||||
}
|
}
|
||||||
: cloneReport(result);
|
: cloneReport(result);
|
||||||
writeConversationReport(conversationId, merged, auth.user?.id);
|
writeConversationReport(conversationId, merged, auth.user?.id);
|
||||||
|
primaryReportReady.value = true;
|
||||||
void router.push({
|
void router.push({
|
||||||
name: "report",
|
name: "report",
|
||||||
query: { conversation: String(conversationId) },
|
query: { conversation: String(conversationId) },
|
||||||
@ -384,27 +415,11 @@ function openReport(result: RiskAssessmentResult) {
|
|||||||
|
|
||||||
function openSolutionReport(card: ReportCard) {
|
function openSolutionReport(card: ReportCard) {
|
||||||
const conversationId = conversation.value?.id;
|
const conversationId = conversation.value?.id;
|
||||||
if (!conversationId) return;
|
if (!conversationId || card.type !== "solution" || !primaryReportReady.value)
|
||||||
const current = conversation.value?.messages
|
return;
|
||||||
.slice()
|
|
||||||
.reverse()
|
|
||||||
.find((message) => message.riskResult)?.riskResult;
|
|
||||||
const stored = readConversationReport(conversationId, auth.user?.id);
|
const stored = readConversationReport(conversationId, auth.user?.id);
|
||||||
const sameReport = Boolean(
|
if (!isPrimaryRiskReport(stored)) return;
|
||||||
current && stored && current.subjectId === stored.subjectId,
|
const base = cloneReport(stored);
|
||||||
);
|
|
||||||
const base: RiskAssessmentResult =
|
|
||||||
sameReport && stored
|
|
||||||
? cloneReport(stored)
|
|
||||||
: current
|
|
||||||
? cloneReport(current)
|
|
||||||
: stored || {
|
|
||||||
subjectId: "AI 案例推理方案",
|
|
||||||
score: 50,
|
|
||||||
level: "medium",
|
|
||||||
modelVersion: "ai-solution-card",
|
|
||||||
factors: [],
|
|
||||||
};
|
|
||||||
const existingCards = base.reportCards ?? [];
|
const existingCards = base.reportCards ?? [];
|
||||||
const merged: RiskAssessmentResult = {
|
const merged: RiskAssessmentResult = {
|
||||||
...base,
|
...base,
|
||||||
@ -571,6 +586,7 @@ async function scrollToBottom(behavior: "smooth" | "auto" = "smooth") {
|
|||||||
<AssistantResponseCard
|
<AssistantResponseCard
|
||||||
v-if="message.responseCard"
|
v-if="message.responseCard"
|
||||||
:card="message.responseCard"
|
:card="message.responseCard"
|
||||||
|
:can-append-report="primaryReportReady"
|
||||||
@generate-report="openSolutionReport"
|
@generate-report="openSolutionReport"
|
||||||
/>
|
/>
|
||||||
<time class="message-time">{{
|
<time class="message-time">{{
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user