fmt
This commit is contained in:
@@ -871,7 +871,10 @@ const radarChartOptions = {
|
|||||||
class="stat-avg-ac"
|
class="stat-avg-ac"
|
||||||
>
|
>
|
||||||
<template #suffix>
|
<template #suffix>
|
||||||
<Icon icon="streamline-ultimate-color:analytics-pie-2" width="20" />
|
<Icon
|
||||||
|
icon="streamline-ultimate-color:analytics-pie-2"
|
||||||
|
width="20"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
</n-statistic>
|
</n-statistic>
|
||||||
</n-gi>
|
</n-gi>
|
||||||
@@ -883,7 +886,10 @@ const radarChartOptions = {
|
|||||||
class="stat-median-ac"
|
class="stat-median-ac"
|
||||||
>
|
>
|
||||||
<template #suffix>
|
<template #suffix>
|
||||||
<Icon icon="streamline-ultimate-color:cursor-target-1" width="20" />
|
<Icon
|
||||||
|
icon="streamline-ultimate-color:cursor-target-1"
|
||||||
|
width="20"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
</n-statistic>
|
</n-statistic>
|
||||||
</n-gi>
|
</n-gi>
|
||||||
@@ -895,7 +901,10 @@ const radarChartOptions = {
|
|||||||
class="stat-total-submission"
|
class="stat-total-submission"
|
||||||
>
|
>
|
||||||
<template #suffix>
|
<template #suffix>
|
||||||
<Icon icon="streamline-ultimate-color:common-file-text" width="20" />
|
<Icon
|
||||||
|
icon="streamline-ultimate-color:common-file-text"
|
||||||
|
width="20"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
</n-statistic>
|
</n-statistic>
|
||||||
</n-gi>
|
</n-gi>
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
import type { Exercise } from "utils/types"
|
import type { Exercise } from "utils/types"
|
||||||
|
|
||||||
type Segment =
|
type Segment =
|
||||||
| { type: "md"; content: string }
|
{ type: "md"; content: string } | { type: "exercise"; exercise: Exercise }
|
||||||
| { type: "exercise"; exercise: Exercise }
|
|
||||||
|
|
||||||
export function parseExercises(
|
export function parseExercises(
|
||||||
content: string,
|
content: string,
|
||||||
|
|||||||
@@ -195,13 +195,6 @@ onMounted(() => {
|
|||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<IconButton
|
|
||||||
v-if="isDesktop && userStore.isSuperAdmin"
|
|
||||||
icon="streamline-ultimate-color:common-file-edit"
|
|
||||||
tip="编辑题目"
|
|
||||||
@click="goEdit"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<template v-if="showSyncFeature">
|
<template v-if="showSyncFeature">
|
||||||
<IconButton
|
<IconButton
|
||||||
:icon="
|
:icon="
|
||||||
@@ -231,6 +224,13 @@ onMounted(() => {
|
|||||||
</n-tag>
|
</n-tag>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<IconButton
|
||||||
|
v-if="isDesktop && userStore.isSuperAdmin"
|
||||||
|
icon="streamline-ultimate-color:common-file-edit"
|
||||||
|
tip="编辑题目"
|
||||||
|
@click="goEdit"
|
||||||
|
/>
|
||||||
</n-flex>
|
</n-flex>
|
||||||
|
|
||||||
<n-modal
|
<n-modal
|
||||||
|
|||||||
@@ -77,10 +77,7 @@ const columns: DataTableColumn<Submission>[] = [
|
|||||||
render: (row) => h(SubmissionResultTag, { result: row.result }),
|
render: (row) => h(SubmissionResultTag, { result: row.result }),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: renderTableTitle(
|
title: renderTableTitle("语言", "streamline-ultimate-color:earth-pin-2"),
|
||||||
"语言",
|
|
||||||
"streamline-ultimate-color:earth-pin-2",
|
|
||||||
),
|
|
||||||
key: "language",
|
key: "language",
|
||||||
width: 100,
|
width: 100,
|
||||||
render: (row) => LANGUAGE_SHOW_VALUE[row.language],
|
render: (row) => LANGUAGE_SHOW_VALUE[row.language],
|
||||||
|
|||||||
@@ -160,12 +160,18 @@ const baseColumns: DataTableColumn<ProblemFiltered>[] = [
|
|||||||
render: (row) => h(ProblemStatus, { status: row.status }),
|
render: (row) => h(ProblemStatus, { status: row.status }),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: renderTableTitle("编号", "streamline-ultimate-color:board-game-dice-1"),
|
title: renderTableTitle(
|
||||||
|
"编号",
|
||||||
|
"streamline-ultimate-color:board-game-dice-1",
|
||||||
|
),
|
||||||
key: "_id",
|
key: "_id",
|
||||||
width: 100,
|
width: 100,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: renderTableTitle("题目", "streamline-ultimate-color:fruit-watermelon"),
|
title: renderTableTitle(
|
||||||
|
"题目",
|
||||||
|
"streamline-ultimate-color:fruit-watermelon",
|
||||||
|
),
|
||||||
key: "title",
|
key: "title",
|
||||||
minWidth: 200,
|
minWidth: 200,
|
||||||
render: (row) => h(ProblemListTitle, { problem: row }),
|
render: (row) => h(ProblemListTitle, { problem: row }),
|
||||||
|
|||||||
@@ -110,7 +110,11 @@ async function analyzeSingleClassWithAI() {
|
|||||||
if (event === "end" && !hasStarted) classDetailAiLoading.value = false
|
if (event === "end" && !hasStarted) classDetailAiLoading.value = false
|
||||||
},
|
},
|
||||||
onMessage(payload) {
|
onMessage(payload) {
|
||||||
const parsed = payload as { type?: string; content?: string; message?: string }
|
const parsed = payload as {
|
||||||
|
type?: string
|
||||||
|
content?: string
|
||||||
|
message?: string
|
||||||
|
}
|
||||||
if (parsed.type === "delta" && parsed.content) {
|
if (parsed.type === "delta" && parsed.content) {
|
||||||
if (!hasStarted) {
|
if (!hasStarted) {
|
||||||
hasStarted = true
|
hasStarted = true
|
||||||
@@ -221,7 +225,10 @@ const columns: DataTableColumn<Rank>[] = [
|
|||||||
align: "center",
|
align: "center",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: renderTableTitle("提交数", "streamline-ultimate-color:space-rocket-earth"),
|
title: renderTableTitle(
|
||||||
|
"提交数",
|
||||||
|
"streamline-ultimate-color:space-rocket-earth",
|
||||||
|
),
|
||||||
key: "submission_number",
|
key: "submission_number",
|
||||||
width: 120,
|
width: 120,
|
||||||
align: "center",
|
align: "center",
|
||||||
@@ -606,7 +613,10 @@ watch(
|
|||||||
class="stat-avg-ac"
|
class="stat-avg-ac"
|
||||||
>
|
>
|
||||||
<template #suffix>
|
<template #suffix>
|
||||||
<Icon icon="streamline-ultimate-color:analytics-pie-2" width="20" />
|
<Icon
|
||||||
|
icon="streamline-ultimate-color:analytics-pie-2"
|
||||||
|
width="20"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
</n-statistic>
|
</n-statistic>
|
||||||
</n-gi>
|
</n-gi>
|
||||||
@@ -618,7 +628,10 @@ watch(
|
|||||||
class="stat-median-ac"
|
class="stat-median-ac"
|
||||||
>
|
>
|
||||||
<template #suffix>
|
<template #suffix>
|
||||||
<Icon icon="streamline-ultimate-color:cursor-target-1" width="20" />
|
<Icon
|
||||||
|
icon="streamline-ultimate-color:cursor-target-1"
|
||||||
|
width="20"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
</n-statistic>
|
</n-statistic>
|
||||||
</n-gi>
|
</n-gi>
|
||||||
@@ -630,7 +643,10 @@ watch(
|
|||||||
class="stat-total-submission"
|
class="stat-total-submission"
|
||||||
>
|
>
|
||||||
<template #suffix>
|
<template #suffix>
|
||||||
<Icon icon="streamline-ultimate-color:common-file-text" width="20" />
|
<Icon
|
||||||
|
icon="streamline-ultimate-color:common-file-text"
|
||||||
|
width="20"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
</n-statistic>
|
</n-statistic>
|
||||||
</n-gi>
|
</n-gi>
|
||||||
@@ -736,7 +752,12 @@ watch(
|
|||||||
</n-space>
|
</n-space>
|
||||||
</n-card>
|
</n-card>
|
||||||
|
|
||||||
<n-flex justify="center" align="center" :size="12" style="margin-top: 12px">
|
<n-flex
|
||||||
|
justify="center"
|
||||||
|
align="center"
|
||||||
|
:size="12"
|
||||||
|
style="margin-top: 12px"
|
||||||
|
>
|
||||||
<n-tag type="success" size="large">
|
<n-tag type="success" size="large">
|
||||||
综合分: {{ classDetailData.composite_score.toFixed(1) }}
|
综合分: {{ classDetailData.composite_score.toFixed(1) }}
|
||||||
</n-tag>
|
</n-tag>
|
||||||
@@ -769,7 +790,10 @@ watch(
|
|||||||
>
|
>
|
||||||
<n-spin :show="classDetailAiLoading" :delay="50">
|
<n-spin :show="classDetailAiLoading" :delay="50">
|
||||||
<div style="min-height: 200px">
|
<div style="min-height: 200px">
|
||||||
<MdPreview v-if="classDetailAiContent" :model-value="classDetailAiContent" />
|
<MdPreview
|
||||||
|
v-if="classDetailAiContent"
|
||||||
|
:model-value="classDetailAiContent"
|
||||||
|
/>
|
||||||
<n-flex
|
<n-flex
|
||||||
v-else-if="!classDetailAiLoading"
|
v-else-if="!classDetailAiLoading"
|
||||||
align="center"
|
align="center"
|
||||||
|
|||||||
@@ -267,10 +267,7 @@ const columns = computed(() => {
|
|||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: renderTableTitle(
|
title: renderTableTitle("语言", "streamline-ultimate-color:earth-pin-2"),
|
||||||
"语言",
|
|
||||||
"streamline-ultimate-color:earth-pin-2",
|
|
||||||
),
|
|
||||||
key: "language",
|
key: "language",
|
||||||
minWidth: 120,
|
minWidth: 120,
|
||||||
render: (row) => LANGUAGE_SHOW_VALUE[row.language],
|
render: (row) => LANGUAGE_SHOW_VALUE[row.language],
|
||||||
@@ -347,7 +344,10 @@ const flowchartColumns = computed(() => {
|
|||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: renderTableTitle("评分", "streamline-ultimate-color:analytics-bars-3d"),
|
title: renderTableTitle(
|
||||||
|
"评分",
|
||||||
|
"streamline-ultimate-color:analytics-bars-3d",
|
||||||
|
),
|
||||||
key: "ai_score",
|
key: "ai_score",
|
||||||
render: (row) => h(Grade, { score: row.ai_score, grade: row.ai_grade }),
|
render: (row) => h(Grade, { score: row.ai_score, grade: row.ai_grade }),
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -7,7 +7,11 @@ interface Props {
|
|||||||
page: number
|
page: number
|
||||||
}
|
}
|
||||||
|
|
||||||
const { total, limit: initialLimit = 10, page: initialPage = 1 } = defineProps<Props>()
|
const {
|
||||||
|
total,
|
||||||
|
limit: initialLimit = 10,
|
||||||
|
page: initialPage = 1,
|
||||||
|
} = defineProps<Props>()
|
||||||
|
|
||||||
const emit = defineEmits(["update:limit", "update:page"])
|
const emit = defineEmits(["update:limit", "update:page"])
|
||||||
|
|
||||||
|
|||||||
@@ -23,27 +23,26 @@ export const SYNC_ERROR_CODES = {
|
|||||||
// 界面和通知文案
|
// 界面和通知文案
|
||||||
export const SYNC_MESSAGES = {
|
export const SYNC_MESSAGES = {
|
||||||
// 超管离开
|
// 超管离开
|
||||||
SUPER_ADMIN_LEFT: (name: string) => `👋 超管 ${name} 已离开`,
|
SUPER_ADMIN_LEFT: (name: string) => `超管 ${name} 已离开`,
|
||||||
|
|
||||||
// 缺少超管
|
// 缺少超管
|
||||||
MISSING_SUPER_ADMIN: "⚠️ 协同编辑需要超管",
|
MISSING_SUPER_ADMIN: "协同编辑需要超管",
|
||||||
|
|
||||||
// 连接成功
|
// 连接成功
|
||||||
SYNC_ACTIVE: "✅ 协同编辑已激活!",
|
SYNC_ACTIVE: "协同编辑已激活!",
|
||||||
|
|
||||||
// 连接断开
|
// 连接断开
|
||||||
CONNECTION_LOST: "⚠️ 协同编辑已断开",
|
CONNECTION_LOST: "协同编辑已断开",
|
||||||
|
|
||||||
// 等待相关
|
// 等待相关
|
||||||
WAITING_STUDENT: "⏳ 正在等待学生加入...",
|
WAITING_STUDENT: "正在等待学生加入...",
|
||||||
WAITING_ADMIN: "⏳ 正在等待超管加入...",
|
WAITING_ADMIN: "正在等待超管加入...",
|
||||||
|
|
||||||
// Form.vue 界面文案
|
// Form.vue 界面文案
|
||||||
SYNC_ON: "断开同步",
|
SYNC_ON: "断开同步",
|
||||||
SYNC_OFF: "开启同步",
|
SYNC_OFF: "开启同步",
|
||||||
SYNCING_WITH: (name: string) => `🔗 与 ${name} 同步中`,
|
SYNCING_WITH: (name: string) => `与 ${name} 同步中`,
|
||||||
STUDENT_LEFT: (name?: string) =>
|
STUDENT_LEFT: (name?: string) => (name ? `${name}已离开` : "可以关闭同步"),
|
||||||
name ? `💡 ${name}已离开` : "💡 可以关闭同步",
|
|
||||||
} as const
|
} as const
|
||||||
|
|
||||||
// 类型定义
|
// 类型定义
|
||||||
|
|||||||
@@ -4,10 +4,7 @@ import { ref, onUnmounted, type Ref } from "vue"
|
|||||||
* WebSocket 连接状态
|
* WebSocket 连接状态
|
||||||
*/
|
*/
|
||||||
export type ConnectionStatus =
|
export type ConnectionStatus =
|
||||||
| "disconnected"
|
"disconnected" | "connecting" | "connected" | "error"
|
||||||
| "connecting"
|
|
||||||
| "connected"
|
|
||||||
| "error"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* WebSocket 消息类型
|
* WebSocket 消息类型
|
||||||
|
|||||||
Reference in New Issue
Block a user