@@ -1,148 +1,166 @@
< template >
< template >
< n-grid v-if = "submission" :cols="5" :x-gap="16" >
< n-grid v-if = "submission" :cols="5" :x-gap="16" >
< ! - - 左侧 : 流程图预览区域 - - >
< ! - - 左侧 : 流程图预览区域 - - >
< n-gi :span = " 3">
< n-gi : span = "showLargeImage ? 5 : 3">
< n-card title = "流程图预览" >
< n-card title = "流程图预览" >
< div class = "flowchart" >
< template # header -extra >
< n-alert v-if = "renderError" type="error" title="流程图渲染失败" >
< n-button
{{ renderError }}
v-if = "!renderError && submission?.mermaid_code"
< / n -alert >
quaternary
< div class = "flowchart" v-else ref = "mermaidContainer" > < / div >
size = "small"
< / div >
@click ="showLargeImage = !showLargeImage"
< / n-card >
>
< / n-gi >
< template # icon >
< Icon
<!-- 右侧 : 评分详情区域 -- >
: icon = "
< n-gi :span = "2" >
showLargeImage ? 'mdi:fullscreen-exit' : 'mdi:fullscreen'
<!-- AI反馈 -- >
"
< n-card
/ >
v-if = "submission.ai_feedback"
< / template >
size = "small"
{ { showLargeImage ? "退出大图" : "查看大图" } }
title = "AI反馈"
< / n-button >
style = "margin-bottom: 16px"
< / template >
>
< div class = "flowchart" >
< n-text > { { submission . ai _feedback } } < / n-text >
< n-alert v-if = "renderError" type="error" title="流程图渲染失败" >
< / n-card >
{{ renderError }}
< / n -alert >
<!-- 改进建议 -- >
< div class = "flowchart" v-else ref = "mermaidContainer" > < / div >
< n-card
< / div >
v-if = "submission.ai_suggestions"
< / n-card >
size = "small"
< / n-gi >
title = "改进建议"
style = "margin-bottom: 16px"
<!-- 右侧 : 评分详情区域 -- >
>
< n-gi v-if = "!showLargeImage" :span="2" >
< n-text > { { submission . ai _suggestions } } < / n-text >
< ! - - AI反馈 - - >
< / n-card >
< n-card
v-if = "submission.ai_feedback"
<!-- 详细评分 -- >
size = "small"
< n-card
title = "AI反馈"
v-if ="
style = "margin-bottom: 16px"
submission.ai_criteria_details &&
>
Object.keys(submission.ai_criteria_details).length > 0
< n-text > { { submission . ai _feedback } } < / n-text >
"
< / n-card >
size="small"
title="详细评分"
<!-- 改进建议 -- >
>
< n-card
<div
v-if = "submission.ai_suggestions"
v-for="(detail, key) in submission.ai_criteria_details"
size = "small"
:key="key"
title = "改进建议"
style= "margin-bottom: 12 px"
style = "margin-bottom: 16 px"
>
>
<!-- 评分项标题和分数 -->
< n-text > { { submission . ai _suggestions } } < / n-text >
<n-flex
< / n-card >
justify="space-between"
align="center"
<!-- 详细评分 -- >
style="margin-bottom: 4px"
< n-card
>
v-if ="
<n-text strong>{{ key }}</n-text>
submission.ai_criteria_details &&
<n-tag
Object.keys(submission.ai_criteria_details).length > 0
:type="getPercentType(detail.score / detail.max) "
"
size="small"
size="small"
round
title="详细评分"
>
>
{{ detail.score || 0 }}分 / {{ detail.max }}分
<div
</n-tag>
v-for="(detail, key) in submission.ai_criteria_details"
</n-flex>
:key="key"
<!-- 评分项详细说明 -->
style="margin-bottom: 12px"
<n-text v-if="detail.comment" depth="3" style="font-size: 12px" >
>
{{ detail.comment }}
<!-- 评分项标题和分数 -->
</ n-text>
<n-flex
</div>
justify="space-between"
</n-card>
align="center"
</n-gi>
style="margin-bottom: 4px"
</n-grid >
>
<n-spin v-else :show="loading" class="loading-container" >
<n-text strong>{{ key }}</n-text >
</n-spin>
<n-tag
</template>
:type="getPercentType(detail.score / detail.max)"
size="small"
<script setup lang="ts">
round
import { FlowchartSubmission } from "utils/types"
>
import { useMermaid } from "shared/composables/useMermaid"
{{ detail.score || 0 }}分 / {{ detail.max }}分
</n-tag>
interface Props {
</n-flex>
submissionId: string
<!-- 评分项详细说明 -->
}
<n-text v-if="detail.comment" depth="3" style="font-size: 12px">
{{ detail.comment }}
const props = defineProps<Props>()
</n-text>
const mermaidContainer = useTemplateRef<HTMLElement>("mermaidContainer")
</div>
const { renderError, renderFlowchart } = useMermaid()
</n-card>
</n-gi>
const submission = ref<FlowchartSubmission | null>(null)
</n-grid>
const loading = ref(false)
<n-spin v-else :show="loading" class="loading-container"> </n-spin>
const rendering = ref(false)
</template>
function getPercentType(percent: number) {
<script setup lang="ts">
if (percent >= 0.8) return "primary "
import { Icon } from "@iconify/vue "
else if (percent >= 0.6) return "info "
import { FlowchartSubmission } from "utils/types "
else if (percent >= 0.4) return "warning "
import { useMermaid } from "shared/composables/useMermaid "
return "error"
}
interface Props {
submissionId: string
async function loadSubmission ( ) {
}
if ( ! props.submissionId ) return
loading.value = true
const props = defineProps<Props>()
try {
const mermaidContainer = useTemplateRef<HTMLElement>("mermaidContainer")
const { getFlowchartSubmission } = await import ( " oj / api " )
const { renderError, renderFlowchart } = useMermaid()
const res = await getFlowchartSubmission ( props.submissionId )
submission.value = res.data
const submission = ref<FlowchartSubmission | null>(null)
const loading = ref(false)
/ / 渲染流程图
const rendering = ref(false)
if ( submission.value ? .mermaid_code ) {
const showLargeImage = ref(false)
rendering.value = true
await nextTick ( )
function getPercentType(percent: number) {
await renderFlowchart (
if (percent >= 0.8) return "primary"
mermaidContainer.value ,
else if (percent >= 0.6) return "info"
submission.value.mermaid_code ,
else if (percent >= 0.4) return "warning"
)
return "error"
rendering.value = false
}
}
} catch ( error ) {
async function loadSubmission ( ) {
console.error ( " Failed to load submission : " , error )
if ( ! props.submissionId ) return
} finally {
loading.value = true
loading.value = false
try {
}
const { getFlowchartSubmission } = await import ( " oj / api " )
}
const res = await getFlowchartSubmission ( props.submissionId )
submission.value = res.data
watch ( ( ) = > props . submissionId , loadSubmission , { immediate : true } )
< / script >
/ / 渲染流程图
if ( submission.value ? .mermaid_code ) {
< style scoped >
rendering.value = true
. flowchart {
await nextTick ( )
height : 500 px ;
await renderFlowchart (
display : flex ;
mermaidContainer.value ,
justify - content : center ;
submission.value.mermaid_code ,
align - items : center ;
)
}
rendering.value = false
}
/* 确保 SVG 图表占满容器 */
} catch ( error ) {
: deep ( . flowchart > svg ) {
console.error ( " Failed to load submission : " , error )
height : 100 % ;
} finally {
}
loading.value = false
}
. loading - container {
}
min - height : 600 px ;
display : flex ;
watch ( ( ) = > props . submissionId , loadSubmission , { immediate : true } )
justify - content : center ;
< / script >
align - items : center ;
}
< style scoped >
< / style >
. flowchart {
height : 500 px ;
display : flex ;
justify - content : center ;
align - items : center ;
}
/* 确保 SVG 图表占满容器 */
: deep ( . flowchart > svg ) {
height : 100 % ;
}
. loading - container {
min - height : 600 px ;
display : flex ;
justify - content : center ;
align - items : center ;
}
< / style >