This commit is contained in:
biss committed 2026-08-12 11:39:30 +08:00
1 parent e5afe60a11
commit 7994ed1ed3
8 files changed
+408 -13

No files matched your search

+56 -2
View File
@@ -25,6 +25,7 @@ const importing = ref(false)
const fileInput = ref<HTMLInputElement>()
const rows = ref<any[]>([])
const total = ref(0)
const selectedRows = ref<any[]>([])
const dialogVisible = ref(false)
const activationDialog = ref(false)
const activationLoading = ref(false)
@@ -54,6 +55,11 @@ const canManage = computed(() =>
['SuperAdmin', 'AcademicAdmin', 'CollegeAdmin'].includes(role),
) ?? false,
)
const canExport = computed(() =>
auth.user?.roles.some((role) =>
['SuperAdmin', 'AcademicAdmin', 'CollegeAdmin', 'Counselor'].includes(role),
) ?? false,
)
const scopedCollegeId = computed(() =>
auth.user?.roles.some((role) => ['CollegeAdmin', 'Counselor'].includes(role))
? auth.user.collegeId
@@ -179,6 +185,17 @@ async function load() {
const { data } = await http.get<PageResult>(`/personnel/${active.value}`, { params })
rows.value = data.items
total.value = data.total
selectedRows.value = []
if (active.value === 'students' && rows.value.length) {
const ids = rows.value.map((row) => row.id)
const { data: summaries } = await http.get('/personnel/students/current-courses', {
params: { studentIds: ids },
})
const byId = new Map(summaries.map((item: any) => [item.id, item]))
rows.value = rows.value.map((row) => ({ ...row, ...(byId.get(row.id) ?? {
currentCourses: [], totalCredits: 0,
}) }))
}
} catch (error) {
ElMessage.error(apiErrorMessage(error))
} finally {
@@ -252,6 +269,28 @@ async function exportRows() {
}
}
async function exportStudentCurrentCourses(selectedOnly = false) {
if (selectedOnly && selectedRows.value.length === 0) {
ElMessage.warning('请先勾选需要导出的学生。')
return
}
try {
await downloadApiFile(
'/personnel/students/current-courses/export',
'学生正在修读课程.xlsx',
{ params: { ...exportParams(), studentIds: selectedOnly
? selectedRows.value.map((row) => row.id) : undefined } },
)
ElMessage.success(selectedOnly ? `已导出所选 ${selectedRows.value.length} 名学生` : '已导出筛选学生的修读课程')
} catch (error) {
ElMessage.error(apiErrorMessage(error))
}
}
function onSelectionChange(selection: any[]) {
selectedRows.value = selection
}
function chooseImportFile() {
fileInput.value?.click()
}
@@ -420,6 +459,7 @@ watch(active, async () => {
<el-select v-model="query.majorId" clearable filterable placeholder="全部专业">
<el-option v-for="item in filteredMajors" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
<el-input-number v-model="query.enrollmentYear" :min="2000" :max="2200" controls-position="right" placeholder="入学年级" />
<el-select v-model="query.classId" clearable filterable placeholder="全部班级">
<el-option v-for="item in filteredClasses" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
@@ -445,10 +485,15 @@ watch(active, async () => {
@change="handleImport"
/>
</template>
<el-button :icon="Download" @click="exportRows">导出结果</el-button>
<el-button v-if="canExport" :icon="Download" @click="exportRows">导出结果</el-button>
<template v-if="active === 'students' && canExport">
<el-button :icon="Download" type="primary" @click="exportStudentCurrentCourses()">导出修读课程</el-button>
<el-button :icon="Download" :disabled="selectedRows.length === 0" @click="exportStudentCurrentCourses(true)">导出所选({{ selectedRows.length }})</el-button>
</template>
</div>
<el-table v-loading="loading" :data="rows" class="data-table registry-table">
<el-table v-loading="loading" :data="rows" class="data-table registry-table" @selection-change="onSelectionChange">
<el-table-column v-if="active === 'students'" type="selection" width="48" />
<el-table-column :label="numberLabel" width="135">
<template #default="{ row }"><span class="registry-number">{{ active === 'teachers' ? row.teacherNumber : row.studentNumber }}</span></template>
</el-table-column>
@@ -470,6 +515,15 @@ watch(active, async () => {
<el-table-column v-if="active === 'students'" prop="className" label="行政班" min-width="155" />
<el-table-column v-if="active === 'students'" prop="majorName" label="专业" min-width="170" />
<el-table-column v-if="active === 'students'" prop="enrollmentYear" label="入学年级" width="105" />
<el-table-column v-if="active === 'students'" label="正在修读课程 / 学分" min-width="240">
<template #default="{ row }">
<span v-if="row.currentCourses?.length">{{ row.currentCourses.map((course: any) => `${course.courseName}(${course.credits}学分)`).join(';') }}</span>
<span v-else>—</span>
</template>
</el-table-column>
<el-table-column v-if="active === 'students'" label="总学分" width="95">
<template #default="{ row }">{{ row.totalCredits ?? 0 }}</template>
</el-table-column>
<el-table-column label="状态" width="95">
<template #default="{ row }">
<span class="table-status" :class="{ off: row.status !== 'Active' }">