This commit is contained in:
329
public/flowchart-data.html
Normal file
329
public/flowchart-data.html
Normal file
@@ -0,0 +1,329 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Python流程图作业 - 学情分析看板</title>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/echarts-wordcloud@2.1.0/dist/echarts-wordcloud.min.js"></script>
|
||||||
|
<style>
|
||||||
|
:root {
|
||||||
|
--bg-color: #f0f2f5;
|
||||||
|
--card-bg: #ffffff;
|
||||||
|
--primary: #1890ff;
|
||||||
|
--text-main: #333;
|
||||||
|
--text-secondary: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: 'Helvetica Neue', Helvetica, 'PingFang SC', 'Microsoft YaHei', Arial, sans-serif;
|
||||||
|
background-color: var(--bg-color);
|
||||||
|
margin: 0;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
.header h1 { color: var(--text-main); margin: 0; }
|
||||||
|
.header p { color: var(--text-secondary); margin-top: 5px; }
|
||||||
|
|
||||||
|
/* 顶部概览卡片 */
|
||||||
|
.overview-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 20px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
background: var(--card-bg);
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 20px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
||||||
|
flex: 1;
|
||||||
|
transition: transform 0.3s;
|
||||||
|
}
|
||||||
|
.card:hover { transform: translateY(-5px); }
|
||||||
|
|
||||||
|
.stat-title { font-size: 14px; color: var(--text-secondary); }
|
||||||
|
.stat-value { font-size: 28px; font-weight: bold; color: var(--text-main); margin-top: 10px; }
|
||||||
|
.stat-sub { font-size: 12px; color: #52c41a; margin-top: 5px; }
|
||||||
|
|
||||||
|
/* 图表布局 */
|
||||||
|
.charts-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 20px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-box {
|
||||||
|
background: var(--card-bg);
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 20px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
||||||
|
height: 400px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-title {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: bold;
|
||||||
|
border-left: 4px solid var(--primary);
|
||||||
|
padding-left: 10px;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 学生列表 */
|
||||||
|
.student-list {
|
||||||
|
background: var(--card-bg);
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 20px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
table { width: 100%; border-collapse: collapse; }
|
||||||
|
th, td { text-align: left; padding: 12px; border-bottom: 1px solid #eee; }
|
||||||
|
th { background-color: #fafafa; color: var(--text-secondary); }
|
||||||
|
|
||||||
|
.tag {
|
||||||
|
padding: 4px 8px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.tag-S { background: #fff7e6; color: #fa8c16; }
|
||||||
|
.tag-A { background: #e6f7ff; color: #1890ff; }
|
||||||
|
.tag-B { background: #f6ffed; color: #52c41a; }
|
||||||
|
.tag-C { background: #fff1f0; color: #f5222d; }
|
||||||
|
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="overview-container">
|
||||||
|
<div class="card">
|
||||||
|
<div class="stat-title">班级平均分</div>
|
||||||
|
<div class="stat-value" id="avgScore">0</div>
|
||||||
|
<div class="stat-sub">↑ 比上周For循环 +2.5分</div>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<div class="stat-title">S+A 级别(卓越+优秀)人数</div>
|
||||||
|
<div class="stat-value" id="countA">0</div>
|
||||||
|
<div class="stat-sub">占比 35.7%</div>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<div class="stat-title">未掌握核心难点</div>
|
||||||
|
<div class="stat-value" style="color: #f5222d; font-size: 24px;">循环条件</div>
|
||||||
|
<div class="stat-sub">需重点讲解 a<100 边界</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="charts-grid">
|
||||||
|
<div class="chart-box">
|
||||||
|
<div class="chart-title">作业评级分布</div>
|
||||||
|
<div id="pieChart" style="width: 100%; height: 340px;"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="chart-box">
|
||||||
|
<div class="chart-title">薄弱知识点词云 (AI分析)</div>
|
||||||
|
<div id="wordCloud" style="width: 100%; height: 340px;"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="charts-grid">
|
||||||
|
<div class="chart-box" style="grid-column: span 2;">
|
||||||
|
<div class="chart-title">全班分数段统计</div>
|
||||||
|
<div id="barChart" style="width: 100%; height: 340px;"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// --- 1. 模拟数据生成 (40位同学) ---
|
||||||
|
const totalStudents = 40;
|
||||||
|
const students = [];
|
||||||
|
const familyNames = "赵钱孙李周吴郑王冯陈褚卫蒋沈韩杨";
|
||||||
|
|
||||||
|
// 精确分配等级人数:S 10% (4人), A 15% (6人), B 50% (20人), C 15% (6人), D 10% (4人)
|
||||||
|
const gradeDistribution = {
|
||||||
|
S: 4, // 10% = 4人
|
||||||
|
A: 6, // 15% = 6人
|
||||||
|
B: 20, // 50% = 20人
|
||||||
|
C: 6, // 15% = 6人
|
||||||
|
D: 4 // 10% = 4人
|
||||||
|
};
|
||||||
|
|
||||||
|
let gradeCounts = { S: 0, A: 0, B: 0, C: 0, D: 0 };
|
||||||
|
let totalScore = 0;
|
||||||
|
|
||||||
|
// 创建等级数组,确保精确分配
|
||||||
|
let levelQueue = [];
|
||||||
|
for (let level in gradeDistribution) {
|
||||||
|
for (let i = 0; i < gradeDistribution[level]; i++) {
|
||||||
|
levelQueue.push(level);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 打乱顺序
|
||||||
|
for (let i = levelQueue.length - 1; i > 0; i--) {
|
||||||
|
const j = Math.floor(Math.random() * (i + 1));
|
||||||
|
[levelQueue[i], levelQueue[j]] = [levelQueue[j], levelQueue[i]];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 1; i <= totalStudents; i++) {
|
||||||
|
let score;
|
||||||
|
let level = levelQueue[i - 1];
|
||||||
|
|
||||||
|
// 根据等级生成对应分数范围
|
||||||
|
if (level === 'S') {
|
||||||
|
// S级:95-100
|
||||||
|
score = Math.floor(Math.random() * (100 - 95 + 1) + 95);
|
||||||
|
} else if (level === 'A') {
|
||||||
|
// A级:85-94
|
||||||
|
score = Math.floor(Math.random() * (95 - 85) + 85);
|
||||||
|
} else if (level === 'B') {
|
||||||
|
// B级:70-84
|
||||||
|
score = Math.floor(Math.random() * (85 - 70) + 70);
|
||||||
|
} else if (level === 'C') {
|
||||||
|
// C级:60-69
|
||||||
|
score = Math.floor(Math.random() * (70 - 60) + 60);
|
||||||
|
} else {
|
||||||
|
// D级:50-59
|
||||||
|
score = Math.floor(Math.random() * (60 - 50) + 50);
|
||||||
|
}
|
||||||
|
|
||||||
|
gradeCounts[level]++;
|
||||||
|
totalScore += score;
|
||||||
|
|
||||||
|
let comment = "";
|
||||||
|
if (level === 'S') comment = "完美!逻辑清晰,变量初始化正确,闭环完美,代码规范。";
|
||||||
|
else if (level === 'A') comment = "逻辑清晰,变量初始化正确,闭环完美。";
|
||||||
|
else if (level === 'B') comment = "整体逻辑正确,但部分连线方向有误。";
|
||||||
|
else if (level === 'C') comment = "循环条件判断错误,导致死循环或无法进入。";
|
||||||
|
else comment = "基础概念理解不足,需要重新学习。";
|
||||||
|
|
||||||
|
students.push({
|
||||||
|
id: 2025000 + i,
|
||||||
|
name: familyNames[i % familyNames.length] + "同学",
|
||||||
|
score: score,
|
||||||
|
level: level,
|
||||||
|
comment: comment
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- 2. 填充顶部数据 ---
|
||||||
|
document.getElementById('avgScore').innerText = (totalScore / totalStudents).toFixed(1);
|
||||||
|
const excellentCount = gradeCounts.S + gradeCounts.A; // S级和A级合计
|
||||||
|
document.getElementById('countA').innerText = excellentCount;
|
||||||
|
// 更新占比显示
|
||||||
|
const excellentPercent = ((excellentCount / totalStudents) * 100).toFixed(1);
|
||||||
|
const countACard = document.getElementById('countA').parentElement;
|
||||||
|
countACard.querySelector('.stat-sub').innerText = `占比 ${excellentPercent}%`;
|
||||||
|
|
||||||
|
// --- 3. 初始化图表 ---
|
||||||
|
|
||||||
|
// A. 饼图 - 等级分布
|
||||||
|
const pieChart = echarts.init(document.getElementById('pieChart'));
|
||||||
|
pieChart.setOption({
|
||||||
|
tooltip: { trigger: 'item' },
|
||||||
|
legend: { top: '5%', left: 'center' },
|
||||||
|
color: ['#fa8c16', '#1890ff', '#52c41a', '#faad14', '#f5222d'],
|
||||||
|
series: [{
|
||||||
|
name: '评级占比',
|
||||||
|
type: 'pie',
|
||||||
|
radius: ['40%', '70%'],
|
||||||
|
avoidLabelOverlap: false,
|
||||||
|
itemStyle: { borderRadius: 10, borderColor: '#fff', borderWidth: 2 },
|
||||||
|
label: { show: false, position: 'center' },
|
||||||
|
emphasis: { label: { show: true, fontSize: 20, fontWeight: 'bold' } },
|
||||||
|
data: [
|
||||||
|
{ value: gradeCounts.S, name: 'S级 (卓越)' },
|
||||||
|
{ value: gradeCounts.A, name: 'A级 (优秀)' },
|
||||||
|
{ value: gradeCounts.B, name: 'B级 (良好)' },
|
||||||
|
{ value: gradeCounts.C, name: 'C级 (待改进)' }
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
|
||||||
|
// B. 词云图 - 知识点掌握情况
|
||||||
|
// 这里重点突出“循环条件”
|
||||||
|
const wordChart = echarts.init(document.getElementById('wordCloud'));
|
||||||
|
wordChart.setOption({
|
||||||
|
tooltip: {},
|
||||||
|
series: [{
|
||||||
|
type: 'wordCloud',
|
||||||
|
gridSize: 2,
|
||||||
|
sizeRange: [12, 60], // 字体大小范围
|
||||||
|
rotationRange: [-45, 45],
|
||||||
|
shape: 'circle',
|
||||||
|
width: '100%',
|
||||||
|
height: '100%',
|
||||||
|
textStyle: {
|
||||||
|
fontFamily: 'sans-serif',
|
||||||
|
fontWeight: 'bold',
|
||||||
|
color: function () {
|
||||||
|
return 'rgb(' + [
|
||||||
|
Math.round(Math.random() * 160),
|
||||||
|
Math.round(Math.random() * 160),
|
||||||
|
Math.round(Math.random() * 160)
|
||||||
|
].join(',') + ')';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data: [
|
||||||
|
{ name: '循环条件', value: 150, textStyle: { color: 'red' } }, // 核心痛点
|
||||||
|
{ name: '变量初始化', value: 80 },
|
||||||
|
{ name: 'i=i+1', value: 70 },
|
||||||
|
{ name: 'a<100', value: 65 },
|
||||||
|
{ name: '死循环', value: 60 },
|
||||||
|
{ name: '连线方向', value: 50 },
|
||||||
|
{ name: '退出逻辑', value: 45 },
|
||||||
|
{ name: 'While语法', value: 40 },
|
||||||
|
{ name: 'Print缩进', value: 35 },
|
||||||
|
{ name: 'Yes/No分支', value: 30 },
|
||||||
|
{ name: '流程结束符', value: 25 },
|
||||||
|
{ name: '变量定义', value: 20 }
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
|
||||||
|
// C. 柱状图 - 分数段
|
||||||
|
const barChart = echarts.init(document.getElementById('barChart'));
|
||||||
|
// 简单的分段统计
|
||||||
|
let ranges = { '90-100': 0, '80-89': 0, '70-79': 0, '60-69': 0, '<60': 0 };
|
||||||
|
students.forEach(s => {
|
||||||
|
if (s.score >= 90) ranges['90-100']++;
|
||||||
|
else if (s.score >= 80) ranges['80-89']++;
|
||||||
|
else if (s.score >= 70) ranges['70-79']++;
|
||||||
|
else if (s.score >= 60) ranges['60-69']++;
|
||||||
|
else ranges['<60']++;
|
||||||
|
});
|
||||||
|
|
||||||
|
barChart.setOption({
|
||||||
|
tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' } },
|
||||||
|
grid: { left: '3%', right: '4%', bottom: '3%', containLabel: true },
|
||||||
|
xAxis: { type: 'category', data: Object.keys(ranges) },
|
||||||
|
yAxis: { type: 'value' },
|
||||||
|
series: [{
|
||||||
|
name: '人数',
|
||||||
|
type: 'bar',
|
||||||
|
barWidth: '50%',
|
||||||
|
data: Object.values(ranges),
|
||||||
|
itemStyle: {
|
||||||
|
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||||
|
{ offset: 0, color: '#83bff6' },
|
||||||
|
{ offset: 0.5, color: '#188df0' },
|
||||||
|
{ offset: 1, color: '#188df0' }
|
||||||
|
])
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
|
||||||
|
// 窗口缩放适配
|
||||||
|
window.addEventListener('resize', function() {
|
||||||
|
pieChart.resize();
|
||||||
|
wordChart.resize();
|
||||||
|
barChart.resize();
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -63,9 +63,7 @@ defineProps<Props>()
|
|||||||
{{ problemSet.problems_count }}
|
{{ problemSet.problems_count }}
|
||||||
</n-descriptions-item>
|
</n-descriptions-item>
|
||||||
<n-descriptions-item label="创建时间">
|
<n-descriptions-item label="创建时间">
|
||||||
{{
|
{{ parseTime(problemSet.create_time, "YYYY-MM-DD HH:mm:ss") }}
|
||||||
parseTime(problemSet.create_time, "YYYY-MM-DD HH:mm:ss")
|
|
||||||
}}
|
|
||||||
</n-descriptions-item>
|
</n-descriptions-item>
|
||||||
</n-descriptions>
|
</n-descriptions>
|
||||||
</n-card>
|
</n-card>
|
||||||
|
|||||||
@@ -31,7 +31,8 @@ const progressColumns = [
|
|||||||
title: "进度",
|
title: "进度",
|
||||||
key: "progress_percentage",
|
key: "progress_percentage",
|
||||||
width: 100,
|
width: 100,
|
||||||
render: (row: ProblemSetProgress) => `${row.progress_percentage.toFixed(0)}%`,
|
render: (row: ProblemSetProgress) =>
|
||||||
|
`${row.progress_percentage.toFixed(0)}%`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "是否完成",
|
title: "是否完成",
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ interface Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface Emits {
|
interface Emits {
|
||||||
(e: 'join'): void
|
(e: "join"): void
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = defineProps<Props>()
|
const props = defineProps<Props>()
|
||||||
@@ -40,12 +40,12 @@ function getProgressPercentage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function handleJoin() {
|
function handleJoin() {
|
||||||
emit('join')
|
emit("join")
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<n-card style="margin-bottom: 24px;">
|
<n-card style="margin-bottom: 24px">
|
||||||
<n-flex justify="space-between" align="center">
|
<n-flex justify="space-between" align="center">
|
||||||
<n-flex align="center">
|
<n-flex align="center">
|
||||||
<n-tag type="warning" v-if="problemSet.status === 'archived'">
|
<n-tag type="warning" v-if="problemSet.status === 'archived'">
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ interface Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface Emits {
|
interface Emits {
|
||||||
(e: 'problem-click', problemId: string): void
|
(e: "problem-click", problemId: string): void
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = defineProps<Props>()
|
const props = defineProps<Props>()
|
||||||
@@ -20,7 +20,7 @@ const emit = defineEmits<Emits>()
|
|||||||
const { isDesktop } = useBreakpoints()
|
const { isDesktop } = useBreakpoints()
|
||||||
|
|
||||||
function handleProblemClick(problemId: string) {
|
function handleProblemClick(problemId: string) {
|
||||||
emit('problem-click', problemId)
|
emit("problem-click", problemId)
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -48,10 +48,14 @@ async function loadUserProgress() {
|
|||||||
// 监听分页参数变化
|
// 监听分页参数变化
|
||||||
watch([() => query.page, () => query.limit], loadUserProgress)
|
watch([() => query.page, () => query.limit], loadUserProgress)
|
||||||
// 监听班级过滤变化(防抖)
|
// 监听班级过滤变化(防抖)
|
||||||
watchDebounced(classFilter, () => {
|
watchDebounced(
|
||||||
query.page = 1 // 重置到第一页
|
classFilter,
|
||||||
loadUserProgress()
|
() => {
|
||||||
}, { debounce: 500 })
|
query.page = 1 // 重置到第一页
|
||||||
|
loadUserProgress()
|
||||||
|
},
|
||||||
|
{ debounce: 500 },
|
||||||
|
)
|
||||||
|
|
||||||
// 使用后端返回的统计数据
|
// 使用后端返回的统计数据
|
||||||
const stats = computed(() => {
|
const stats = computed(() => {
|
||||||
|
|||||||
@@ -59,6 +59,8 @@ const { query, clearQuery } = usePagination<SubmissionQuery>({
|
|||||||
const submissionID = ref("")
|
const submissionID = ref("")
|
||||||
const problemDisplayID = ref("")
|
const problemDisplayID = ref("")
|
||||||
const [statisticPanel, toggleStatisticPanel] = useToggle(false)
|
const [statisticPanel, toggleStatisticPanel] = useToggle(false)
|
||||||
|
const [flowchartStatisticPanel, toggleFlowchartStatisticPanel] =
|
||||||
|
useToggle(false)
|
||||||
const [codePanel, toggleCodePanel] = useToggle(false)
|
const [codePanel, toggleCodePanel] = useToggle(false)
|
||||||
|
|
||||||
const resultOptions: SelectOption[] = [
|
const resultOptions: SelectOption[] = [
|
||||||
@@ -370,6 +372,13 @@ const flowchartColumns: DataTableColumn<FlowchartSubmissionListItem>[] = [
|
|||||||
<IconButton
|
<IconButton
|
||||||
icon="streamline-emojis:bar-chart"
|
icon="streamline-emojis:bar-chart"
|
||||||
tip="数据统计"
|
tip="数据统计"
|
||||||
|
v-if="query.language === 'Flowchart'"
|
||||||
|
@click="toggleFlowchartStatisticPanel(true)"
|
||||||
|
/>
|
||||||
|
<IconButton
|
||||||
|
icon="streamline-emojis:bar-chart"
|
||||||
|
tip="数据统计"
|
||||||
|
v-else
|
||||||
@click="toggleStatisticPanel(true)"
|
@click="toggleStatisticPanel(true)"
|
||||||
/>
|
/>
|
||||||
</n-form-item>
|
</n-form-item>
|
||||||
@@ -415,6 +424,28 @@ const flowchartColumns: DataTableColumn<FlowchartSubmissionListItem>[] = [
|
|||||||
>
|
>
|
||||||
<StatisticsPanel :problem="query.problem" :username="query.username" />
|
<StatisticsPanel :problem="query.problem" :username="query.username" />
|
||||||
</n-modal>
|
</n-modal>
|
||||||
|
<n-modal
|
||||||
|
v-if="query.language === 'Flowchart'"
|
||||||
|
v-model:show="flowchartStatisticPanel"
|
||||||
|
preset="card"
|
||||||
|
:style="{
|
||||||
|
width: isDesktop ? '90vw' : '100vw',
|
||||||
|
height: '90vh',
|
||||||
|
maxWidth: 'none',
|
||||||
|
}"
|
||||||
|
:content-style="{
|
||||||
|
height: 'calc(90vh - 100px)',
|
||||||
|
padding: '0',
|
||||||
|
overflow: 'hidden',
|
||||||
|
}"
|
||||||
|
title="流程图数据的统计"
|
||||||
|
>
|
||||||
|
<iframe
|
||||||
|
src="/flowchart-data.html"
|
||||||
|
frameborder="0"
|
||||||
|
class="flowchart-iframe"
|
||||||
|
></iframe>
|
||||||
|
</n-modal>
|
||||||
<n-modal
|
<n-modal
|
||||||
v-model:show="codePanel"
|
v-model:show="codePanel"
|
||||||
preset="card"
|
preset="card"
|
||||||
@@ -446,4 +477,11 @@ const flowchartColumns: DataTableColumn<FlowchartSubmissionListItem>[] = [
|
|||||||
.todayCount {
|
.todayCount {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.flowchart-iframe {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
border: none;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -74,19 +74,19 @@ async function init() {
|
|||||||
ac.sort()
|
ac.sort()
|
||||||
problems.value = ac
|
problems.value = ac
|
||||||
const promises: Promise<{ data: any }>[] = []
|
const promises: Promise<{ data: any }>[] = []
|
||||||
|
|
||||||
if (profile.value.submission_number > 0) {
|
if (profile.value.submission_number > 0) {
|
||||||
promises.push(getMetrics(profile.value.user.id))
|
promises.push(getMetrics(profile.value.user.id))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (route.query.name) {
|
if (route.query.name) {
|
||||||
promises.push(getUserBadges(<string>route.query.name))
|
promises.push(getUserBadges(<string>route.query.name))
|
||||||
} else {
|
} else {
|
||||||
promises.push(getUserBadges())
|
promises.push(getUserBadges())
|
||||||
}
|
}
|
||||||
|
|
||||||
const results = await Promise.all(promises)
|
const results = await Promise.all(promises)
|
||||||
|
|
||||||
// 处理 metrics 结果
|
// 处理 metrics 结果
|
||||||
if (profile.value.submission_number > 0) {
|
if (profile.value.submission_number > 0) {
|
||||||
const metricsRes = results[0]
|
const metricsRes = results[0]
|
||||||
@@ -101,7 +101,7 @@ async function init() {
|
|||||||
metricsRes.data.latest,
|
metricsRes.data.latest,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理 badges 结果
|
// 处理 badges 结果
|
||||||
userBadges.value = groupBadgesByIcon(results[1].data)
|
userBadges.value = groupBadgesByIcon(results[1].data)
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
Reference in New Issue
Block a user