云校:
@@ -464,6 +491,21 @@ const classList = [
{ value: 'class4', label: '高二2班' },
]
+const hasActiveFilters = computed(() => {
+ return selectedCloud.value !== '' ||
+ selectedSchool.value !== '' ||
+ selectedGrade.value !== '' ||
+ selectedClass.value !== ''
+})
+
+const resetFilters = () => {
+ selectedCloud.value = ''
+ selectedSchool.value = ''
+ selectedGrade.value = ''
+ selectedClass.value = ''
+ MessagePlugin.success('筛选条件已重置')
+}
+
// ── 总体学情统计 ──────────────────────────────────────────
const disabledFutureDate = (date) => {
return dayjs(date).isAfter(dayjs().endOf('day'))
@@ -939,11 +981,11 @@ const progressDistData = ref([
const progressColor = (range) => {
const value = parseInt(range)
- if (value >= 90) return '#00a870'
- if (value >= 80) return '#0052d9'
- if (value >= 60) return '#ed7b2f'
- if (value >= 40) return '#f5a623'
- return '#e34d59'
+ if (value >= 90) return '#10B981'
+ if (value >= 80) return '#3B82F6'
+ if (value >= 60) return '#F59E0B'
+ if (value >= 40) return '#F97316'
+ return '#EF4444'
}
const progressDistColumns = [
@@ -975,25 +1017,39 @@ const initProgressChart = () => {
progressChart = echarts.init(progressChartRef.value)
- // 翻转数据以使其在图表上从0到100显示,或者保持从高到低视需求而定
- // 这里我们让X轴从0%到100%排列
const chartData = [...progressDistData.value].reverse()
const option = {
tooltip: {
trigger: 'axis',
- axisPointer: { type: 'shadow' },
- formatter: '{b}
学生人数: {c}人',
- backgroundColor: 'rgba(255, 255, 255, 0.95)',
- borderColor: '#e2e8f0',
+ axisPointer: {
+ type: 'shadow',
+ shadowStyle: {
+ color: 'rgba(30, 64, 175, 0.08)'
+ }
+ },
+ formatter: (params) => {
+ const data = params[0]
+ return `
+
${data.name}
+
+
+ 学生人数:
+ ${data.value}人
+
+
`
+ },
+ backgroundColor: 'rgba(255, 255, 255, 0.98)',
+ borderColor: 'rgba(30, 64, 175, 0.15)',
+ borderWidth: 1,
textStyle: { color: '#1e293b' },
- extraCssText: 'box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); border-radius: 8px;'
+ extraCssText: 'box-shadow: 0 10px 25px rgba(0, 0, 0, 0.12), 0 4px 10px rgba(30, 64, 175, 0.08); border-radius: 12px; backdrop-filter: blur(10px);'
},
grid: {
- top: '10%',
- left: '3%',
- right: '4%',
- bottom: '10%',
+ top: '8%',
+ left: '4%',
+ right: '3%',
+ bottom: '12%',
containLabel: true
},
xAxis: {
@@ -1001,29 +1057,59 @@ const initProgressChart = () => {
data: chartData.map(item => item.progressRange),
axisLabel: {
interval: 0,
- rotate: 45,
+ rotate: 30,
color: '#64748b',
- fontSize: 12
+ fontSize: 11,
+ fontWeight: 500
},
- axisLine: { lineStyle: { color: '#e2e8f0' } }
+ axisLine: {
+ lineStyle: {
+ color: '#cbd5e1',
+ width: 2
+ }
+ },
+ axisTick: {
+ show: false
+ }
},
yAxis: {
type: 'value',
- name: '人数',
- nameTextStyle: { color: '#64748b', padding: [0, 0, 0, 20] },
- splitLine: { lineStyle: { type: 'dashed', color: '#f1f5f9' } },
- axisLabel: { color: '#64748b' }
+ name: '学生人数',
+ nameTextStyle: {
+ color: '#475569',
+ padding: [0, 0, 10, 0],
+ fontSize: 13,
+ fontWeight: 600
+ },
+ splitLine: {
+ lineStyle: {
+ type: 'dashed',
+ color: '#e2e8f0',
+ width: 1
+ }
+ },
+ axisLabel: {
+ color: '#64748b',
+ fontSize: 12,
+ fontWeight: 500,
+ padding: [0, 8, 0, 0]
+ },
+ axisLine: { show: false },
+ axisTick: { show: false }
},
series: [
{
name: '学生人数',
type: 'bar',
- barWidth: '60%',
- data: chartData.map(item => ({
+ barWidth: '55%',
+ data: chartData.map((item, index) => ({
value: item.studentCount,
itemStyle: {
- color: progressColor(item.progressRange),
- borderRadius: [4, 4, 0, 0]
+ color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+ { offset: 0, color: progressColor(item.progressRange) },
+ { offset: 1, color: progressColor(item.progressRange) + '99' }
+ ]),
+ borderRadius: [8, 8, 0, 0]
}
})),
label: {
@@ -1031,24 +1117,39 @@ const initProgressChart = () => {
position: 'top',
color: '#475569',
fontSize: 12,
- formatter: (params) => params.value > 0 ? params.value : ''
- }
+ fontWeight: 600,
+ formatter: (params) => params.value > 0 ? `${params.value}人` : '',
+ offset: [0, -4]
+ },
+ animationDelay: (idx) => idx * 80,
+ animationDuration: 1000,
+ animationEasing: 'cubicOut'
}
- ]
+ ],
+ animationDuration: 1200,
+ animationEasing: 'cubicOut'
}
progressChart.setOption(option)
}
// 监听 Tab 切换,重新渲染图表
-// watch(activeTab, (newVal) => {
-// currentPage.value = 1
-// if (newVal === 'progress_dist') {
-// nextTick(() => {
-// initProgressChart()
-// })
-// }
-// })
+watch(activeTab, (newVal) => {
+ currentPage.value = 1
+ if (newVal === 'progress_dist') {
+ nextTick(() => {
+ initProgressChart()
+ })
+ } else if (newVal === 'accuracy_dist') {
+ nextTick(() => {
+ initAccuracyChart()
+ })
+ } else if (newVal === 'online_stats') {
+ nextTick(() => {
+ initOnlineTrendChart()
+ })
+ }
+})
// 窗口大小变化时重绘图表
const handleResize = () => {
@@ -1109,11 +1210,11 @@ const accuracyDistData = ref([
const levelColor = (range) => {
const value = parseInt(range)
- if (value >= 90) return '#00a870'
- if (value >= 80) return '#0052d9'
- if (value >= 60) return '#ed7b2f'
- if (value >= 40) return '#f5a623'
- return '#e34d59'
+ if (value >= 90) return '#10B981'
+ if (value >= 80) return '#3B82F6'
+ if (value >= 60) return '#F59E0B'
+ if (value >= 40) return '#F97316'
+ return '#EF4444'
}
const accuracyDistColumns = [
@@ -1150,18 +1251,34 @@ const initAccuracyChart = () => {
const option = {
tooltip: {
trigger: 'axis',
- axisPointer: { type: 'shadow' },
- formatter: '{b}
学生人数: {c}人',
- backgroundColor: 'rgba(255, 255, 255, 0.95)',
- borderColor: '#e2e8f0',
+ axisPointer: {
+ type: 'shadow',
+ shadowStyle: {
+ color: 'rgba(30, 64, 175, 0.08)'
+ }
+ },
+ formatter: (params) => {
+ const data = params[0]
+ return `
+
${data.name}
+
+
+ 学生人数:
+ ${data.value}人
+
+
`
+ },
+ backgroundColor: 'rgba(255, 255, 255, 0.98)',
+ borderColor: 'rgba(30, 64, 175, 0.15)',
+ borderWidth: 1,
textStyle: { color: '#1e293b' },
- extraCssText: 'box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); border-radius: 8px;'
+ extraCssText: 'box-shadow: 0 10px 25px rgba(0, 0, 0, 0.12), 0 4px 10px rgba(30, 64, 175, 0.08); border-radius: 12px; backdrop-filter: blur(10px);'
},
grid: {
- top: '10%',
- left: '3%',
- right: '4%',
- bottom: '10%',
+ top: '8%',
+ left: '4%',
+ right: '3%',
+ bottom: '12%',
containLabel: true
},
xAxis: {
@@ -1169,29 +1286,59 @@ const initAccuracyChart = () => {
data: chartData.map(item => item.accuracyRange),
axisLabel: {
interval: 0,
- rotate: 45,
+ rotate: 30,
color: '#64748b',
- fontSize: 12
+ fontSize: 11,
+ fontWeight: 500
},
- axisLine: { lineStyle: { color: '#e2e8f0' } }
+ axisLine: {
+ lineStyle: {
+ color: '#cbd5e1',
+ width: 2
+ }
+ },
+ axisTick: {
+ show: false
+ }
},
yAxis: {
type: 'value',
- name: '人数',
- nameTextStyle: { color: '#64748b', padding: [0, 0, 0, 20] },
- splitLine: { lineStyle: { type: 'dashed', color: '#f1f5f9' } },
- axisLabel: { color: '#64748b' }
+ name: '学生人数',
+ nameTextStyle: {
+ color: '#475569',
+ padding: [0, 0, 10, 0],
+ fontSize: 13,
+ fontWeight: 600
+ },
+ splitLine: {
+ lineStyle: {
+ type: 'dashed',
+ color: '#e2e8f0',
+ width: 1
+ }
+ },
+ axisLabel: {
+ color: '#64748b',
+ fontSize: 12,
+ fontWeight: 500,
+ padding: [0, 8, 0, 0]
+ },
+ axisLine: { show: false },
+ axisTick: { show: false }
},
series: [
{
name: '学生人数',
type: 'bar',
- barWidth: '40%',
+ barWidth: '45%',
data: chartData.map(item => ({
value: item.studentCount,
itemStyle: {
- color: levelColor(item.accuracyRange),
- borderRadius: [4, 4, 0, 0]
+ color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+ { offset: 0, color: levelColor(item.accuracyRange) },
+ { offset: 1, color: levelColor(item.accuracyRange) + '99' }
+ ]),
+ borderRadius: [8, 8, 0, 0]
}
})),
label: {
@@ -1199,10 +1346,17 @@ const initAccuracyChart = () => {
position: 'top',
color: '#475569',
fontSize: 12,
- formatter: (params) => params.value > 0 ? params.value : ''
- }
+ fontWeight: 600,
+ formatter: (params) => params.value > 0 ? `${params.value}人` : '',
+ offset: [0, -4]
+ },
+ animationDelay: (idx) => idx * 80,
+ animationDuration: 1000,
+ animationEasing: 'cubicOut'
}
- ]
+ ],
+ animationDuration: 1200,
+ animationEasing: 'cubicOut'
}
accuracyChart.setOption(option)
@@ -1373,22 +1527,58 @@ const initOnlineTrendChart = () => {
const option = {
tooltip: {
trigger: 'axis',
- axisPointer: { type: 'cross' },
- backgroundColor: 'rgba(255, 255, 255, 0.95)',
- borderColor: '#e2e8f0',
+ axisPointer: {
+ type: 'cross',
+ crossStyle: {
+ color: '#94A3B8',
+ width: 1,
+ type: 'dashed'
+ },
+ lineStyle: {
+ color: '#94A3B8',
+ width: 2,
+ type: 'dashed'
+ }
+ },
+ formatter: (params) => {
+ return `
+
${params[0].axisValue}
+
+
+ 在线用户数:
+ ${params[0].value}人
+
+
+
+ 答题数量:
+ ${params[1].value}次
+
+
`
+ },
+ backgroundColor: 'rgba(255, 255, 255, 0.98)',
+ borderColor: 'rgba(30, 64, 175, 0.15)',
+ borderWidth: 1,
textStyle: { color: '#1e293b' },
- extraCssText: 'box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); border-radius: 8px;'
+ extraCssText: 'box-shadow: 0 10px 25px rgba(0, 0, 0, 0.12), 0 4px 10px rgba(30, 64, 175, 0.08); border-radius: 12px; backdrop-filter: blur(10px);'
},
legend: {
data: ['在线用户数', '答题数量'],
- top: 0,
- textStyle: { color: '#475569' }
+ top: 8,
+ itemWidth: 18,
+ itemHeight: 10,
+ itemGap: 24,
+ textStyle: {
+ color: '#475569',
+ fontSize: 13,
+ fontWeight: 500
+ },
+ icon: 'roundRect'
},
grid: {
- top: '15%',
- left: '3%',
+ top: '16%',
+ left: '4%',
right: '4%',
- bottom: '10%',
+ bottom: '12%',
containLabel: true
},
xAxis: {
@@ -1397,60 +1587,132 @@ const initOnlineTrendChart = () => {
data: trendData.time,
axisLabel: {
color: '#64748b',
- fontSize: 12,
- interval: onlineTimeDimension.value === 'minute' ? 5 : 0, // 10分钟维度下每隔5个点(即1小时)显示一个标签
- rotate: onlineTimeDimension.value === 'day' ? 45 : 0 // 按天显示时倾斜标签以防重叠
+ fontSize: 11,
+ fontWeight: 500,
+ interval: onlineTimeDimension.value === 'minute' ? 5 : 0,
+ rotate: onlineTimeDimension.value === 'day' ? 30 : 0,
+ padding: [8, 0, 0, 0]
},
- axisLine: { lineStyle: { color: '#e2e8f0' } }
+ axisLine: {
+ lineStyle: {
+ color: '#cbd5e1',
+ width: 2
+ }
+ },
+ axisTick: { show: false }
},
yAxis: [
{
type: 'value',
name: '在线用户数',
position: 'left',
- splitLine: { lineStyle: { type: 'dashed', color: '#f1f5f9' } },
- axisLabel: { color: '#64748b' },
- nameTextStyle: { color: '#64748b', padding: [0, 0, 0, 20] }
+ splitLine: {
+ lineStyle: {
+ type: 'dashed',
+ color: '#e2e8f0',
+ width: 1
+ }
+ },
+ axisLabel: {
+ color: '#64748b',
+ fontSize: 12,
+ fontWeight: 500,
+ padding: [0, 8, 0, 0]
+ },
+ nameTextStyle: {
+ color: '#475569',
+ padding: [0, 0, 10, 0],
+ fontSize: 13,
+ fontWeight: 600
+ },
+ axisLine: { show: false },
+ axisTick: { show: false }
},
{
type: 'value',
name: '答题数量',
position: 'right',
splitLine: { show: false },
- axisLabel: { color: '#64748b' },
- nameTextStyle: { color: '#64748b', padding: [0, 20, 0, 0] }
+ axisLabel: {
+ color: '#64748b',
+ fontSize: 12,
+ fontWeight: 500,
+ padding: [0, 0, 0, 8]
+ },
+ nameTextStyle: {
+ color: '#475569',
+ padding: [0, 20, 10, 0],
+ fontSize: 13,
+ fontWeight: 600
+ },
+ axisLine: { show: false },
+ axisTick: { show: false }
}
],
series: [
{
name: '在线用户数',
type: 'line',
- smooth: true,
+ smooth: 0.4,
yAxisIndex: 0,
- itemStyle: { color: '#0052d9' },
+ symbol: 'circle',
+ symbolSize: 6,
+ itemStyle: {
+ color: '#1E40AF',
+ borderWidth: 2,
+ borderColor: '#fff'
+ },
+ lineStyle: {
+ width: 3,
+ shadowColor: 'rgba(30, 64, 175, 0.3)',
+ shadowBlur: 10,
+ shadowOffsetY: 4
+ },
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
- { offset: 0, color: 'rgba(0, 82, 217, 0.3)' },
- { offset: 1, color: 'rgba(0, 82, 217, 0.05)' }
+ { offset: 0, color: 'rgba(30, 64, 175, 0.35)' },
+ { offset: 0.5, color: 'rgba(30, 64, 175, 0.15)' },
+ { offset: 1, color: 'rgba(30, 64, 175, 0.02)' }
])
},
- data: trendData.onlineCount
+ data: trendData.onlineCount,
+ animationDelay: 0,
+ animationDuration: 1200,
+ animationEasing: 'cubicOut'
},
{
name: '答题数量',
type: 'line',
- smooth: true,
+ smooth: 0.4,
yAxisIndex: 1,
- itemStyle: { color: '#00a870' },
+ symbol: 'circle',
+ symbolSize: 6,
+ itemStyle: {
+ color: '#10B981',
+ borderWidth: 2,
+ borderColor: '#fff'
+ },
+ lineStyle: {
+ width: 3,
+ shadowColor: 'rgba(16, 185, 129, 0.3)',
+ shadowBlur: 10,
+ shadowOffsetY: 4
+ },
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
- { offset: 0, color: 'rgba(0, 168, 112, 0.3)' },
- { offset: 1, color: 'rgba(0, 168, 112, 0.05)' }
+ { offset: 0, color: 'rgba(16, 185, 129, 0.35)' },
+ { offset: 0.5, color: 'rgba(16, 185, 129, 0.15)' },
+ { offset: 1, color: 'rgba(16, 185, 129, 0.02)' }
])
},
- data: trendData.answerCount
+ data: trendData.answerCount,
+ animationDelay: 200,
+ animationDuration: 1200,
+ animationEasing: 'cubicOut'
}
- ]
+ ],
+ animationDuration: 1400,
+ animationEasing: 'cubicOut'
}
onlineTrendChart.setOption(option)
@@ -1465,6 +1727,24 @@ import * as XLSX from 'xlsx'
const exportDialogVisible = ref(false)
const exportType = ref('')
+const exporting = ref(false)
+
+const exportDialogTitle = computed(() => {
+ switch (exportType.value) {
+ case 'overview':
+ return '总体学情统计'
+ case 'accuracy_rank':
+ return '答题正确率排名'
+ case 'progress_dist':
+ return '答题进度分布'
+ case 'accuracy_dist':
+ return '正确率分布'
+ case 'online_stats':
+ return '学生在线统计'
+ default:
+ return '数据'
+ }
+})
const exportFilters = ref({
cloud: '',
@@ -1506,97 +1786,94 @@ const handleExport = (type) => {
exportDialogVisible.value = true
}
-const confirmExport = () => {
- exportDialogVisible.value = false
+const confirmExport = async () => {
+ exporting.value = true
- let dataToExport = []
- let columns = []
- let fileName = ''
+ try {
+ let dataToExport = []
+ let columns = []
+ let fileName = ''
- // 在实际应用中,这里应该根据 exportFilters 的值重新请求数据
- // 由于当前是静态数据展示,我们直接使用现有的数据作为导出数据
+ switch (exportType.value) {
+ case 'overview':
+ dataToExport = overviewData.value
+ columns = overviewColumns
+ fileName = '总体学情统计分析表'
+ break
+ case 'accuracy_rank':
+ dataToExport = accuracyRankData.value
+ columns = accuracyRankColumns
+ fileName = '学生答题正确率排名表'
+ break
+ case 'progress_dist':
+ dataToExport = progressDistData.value
+ columns = progressDistColumns
+ fileName = '学生答题进度分布表'
+ break
+ case 'accuracy_dist':
+ dataToExport = accuracyDistData.value
+ columns = accuracyDistColumns
+ fileName = '学生答题正确率分布表'
+ break
+ case 'online_stats':
+ const originalOnlineSingleDate = onlineSingleDate.value
+ const originalOnlineDateRange = onlineDateRange.value
+
+ if (onlineTimeDimension.value === 'minute' || onlineTimeDimension.value === 'hour') {
+ onlineSingleDate.value = exportFilters.value.singleDate
+ } else {
+ onlineDateRange.value = exportFilters.value.dateRange
+ }
+
+ const trendData = generateTrendData(onlineTimeDimension.value)
+
+ onlineSingleDate.value = originalOnlineSingleDate
+ onlineDateRange.value = originalOnlineDateRange
+
+ dataToExport = trendData.time.map((t, index) => ({
+ time: t,
+ onlineCount: trendData.onlineCount[index],
+ answerCount: trendData.answerCount[index]
+ }))
+ columns = [
+ { colKey: 'time', title: '时间' },
+ { colKey: 'onlineCount', title: '在线用户数' },
+ { colKey: 'answerCount', title: '答题数量' }
+ ]
+ fileName = '学生在线与答题趋势'
+ break
+ }
- switch (exportType.value) {
- case 'overview':
- dataToExport = overviewData.value
- columns = overviewColumns
- fileName = '总体学情统计分析表'
- break
- case 'accuracy_rank':
- dataToExport = accuracyRankData.value
- columns = accuracyRankColumns
- fileName = '学生答题正确率排名表'
- break
- case 'progress_dist':
- dataToExport = progressDistData.value
- columns = progressDistColumns
- fileName = '学生答题进度分布表'
- break
- case 'accuracy_dist':
- dataToExport = accuracyDistData.value
- columns = accuracyDistColumns
- fileName = '学生答题正确率分布表'
- break
- case 'online_stats':
- // 模拟根据导出对话框中的筛选条件生成数据
- // 实际应用中应该传递 exportFilters 重新请求数据
- // 这里为了保持演示,临时修改一下组件内的状态来生成对应数据,生成后再恢复
- const originalOnlineSingleDate = onlineSingleDate.value
- const originalOnlineDateRange = onlineDateRange.value
-
- if (onlineTimeDimension.value === 'minute' || onlineTimeDimension.value === 'hour') {
- onlineSingleDate.value = exportFilters.value.singleDate
- } else {
- onlineDateRange.value = exportFilters.value.dateRange
- }
-
- const trendData = generateTrendData(onlineTimeDimension.value)
-
- // 恢复原始状态
- onlineSingleDate.value = originalOnlineSingleDate
- onlineDateRange.value = originalOnlineDateRange
-
- dataToExport = trendData.time.map((t, index) => ({
- time: t,
- onlineCount: trendData.onlineCount[index],
- answerCount: trendData.answerCount[index]
- }))
- columns = [
- { colKey: 'time', title: '时间' },
- { colKey: 'onlineCount', title: '在线用户数' },
- { colKey: 'answerCount', title: '答题数量' }
- ]
- fileName = '学生在线与答题趋势'
- break
- }
-
- // 提取表头
- const headers = columns.map(col => col.title)
- // 提取数据
- const rows = dataToExport.map(row => {
- return columns.map(col => {
- return row[col.colKey]
+ const headers = columns.map(col => col.title)
+ const rows = dataToExport.map(row => {
+ return columns.map(col => {
+ return row[col.colKey]
+ })
})
- })
- // 组装工作表数据
- const worksheetData = [headers, ...rows]
- const worksheet = XLSX.utils.aoa_to_sheet(worksheetData)
- const workbook = XLSX.utils.book_new()
- XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1')
+ const worksheetData = [headers, ...rows]
+ const worksheet = XLSX.utils.aoa_to_sheet(worksheetData)
+ const workbook = XLSX.utils.book_new()
+ XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1')
- // 获取筛选条件的标签用于生成文件名
- const expCloudLabel = cloudList.find(item => item.value === exportFilters.value.cloud)?.label || ''
- const expSchoolLabel = schoolList.find(item => item.value === exportFilters.value.school)?.label || ''
- const expGradeLabel = gradeList.find(item => item.value === exportFilters.value.grade)?.label || ''
- const expClassLabel = classList.find(item => item.value === exportFilters.value.class)?.label || ''
+ const expCloudLabel = cloudList.find(item => item.value === exportFilters.value.cloud)?.label || ''
+ const expSchoolLabel = schoolList.find(item => item.value === exportFilters.value.school)?.label || ''
+ const expGradeLabel = gradeList.find(item => item.value === exportFilters.value.grade)?.label || ''
+ const expClassLabel = classList.find(item => item.value === exportFilters.value.class)?.label || ''
- // 构造文件名,包含筛选条件
- const filterStr = [expCloudLabel, expSchoolLabel, expGradeLabel, expClassLabel].filter(Boolean).join('_')
- const finalFileName = `${fileName}${filterStr ? '_' + filterStr : ''}.xlsx`
+ const filterStr = [expCloudLabel, expSchoolLabel, expGradeLabel, expClassLabel].filter(Boolean).join('_')
+ const finalFileName = `${fileName}${filterStr ? '_' + filterStr : ''}.xlsx`
- XLSX.writeFile(workbook, finalFileName)
- MessagePlugin.success('导出成功')
+ await new Promise(resolve => setTimeout(resolve, 500))
+
+ XLSX.writeFile(workbook, finalFileName)
+ exportDialogVisible.value = false
+ MessagePlugin.success('导出成功')
+ } catch (error) {
+ MessagePlugin.error('导出失败,请重试')
+ } finally {
+ exporting.value = false
+ }
}
// 级联重置:切换学校时清空年级和班级
@@ -1860,111 +2137,147 @@ watch(activeTab, (newVal) => {