优化毕业审核、学位审核

This commit is contained in:
biss committed 2026-10-05 11:07:23 +08:00
1 parent 71ee21b063
commit 5dc1ae4e3a
19 files changed
+9645 -57

No files matched your search

+26 -8
View File
@@ -1,7 +1,8 @@
<script setup lang="ts">
import { computed, onMounted, onUnmounted, reactive, ref, watch } from 'vue'
import { Check, DocumentChecked, Plus, Refresh, Stamp } from '@element-plus/icons-vue'
import { Check, DocumentChecked, Download, Plus, Refresh, Stamp } from '@element-plus/icons-vue'
import http, { apiErrorMessage } from '../api/http'
import { downloadApiFile } from '../api/excel'
import { useAuthStore } from '../stores/auth'
const auth = useAuthStore()
@@ -17,6 +18,10 @@ const decisionDialog = ref(false)
const decisionTarget = ref<any | null>(null)
const keyword = ref('')
const conclusionFilter = ref('')
const majorId = ref('')
const administrativeClassId = ref('')
const majors = ref<any[]>([])
const classes = ref<any[]>([])
const resultPage = ref(1)
const resultPageSize = 20
const resultRequestId = ref(0)
@@ -51,7 +56,10 @@ async function load() {
myResult.value = (await http.get('/graduation-audits/my-result')).data
return
}
batches.value = (await http.get('/graduation-audits/batches')).data
const [batchResponse, majorResponse, classResponse] = await Promise.all([
http.get('/graduation-audits/batches'), http.get('/base-data/majors'), http.get('/base-data/classes'),
])
batches.value = batchResponse.data; majors.value = majorResponse.data; classes.value = classResponse.data
const batch = batches.value.find((x) => x.id === selected.value?.id) ?? batches.value[0]
if (batch) await selectBatch(batch.id)
else selected.value = null
@@ -76,6 +84,8 @@ async function loadBatch(id = selected.value?.id) {
pageSize: resultPageSize,
keyword: keyword.value.trim() || undefined,
conclusion: conclusionFilter.value || undefined,
majorId: majorId.value || undefined,
administrativeClassId: administrativeClassId.value || undefined,
},
})
if (requestId === resultRequestId.value) selected.value = response.data
@@ -85,13 +95,15 @@ async function loadBatch(id = selected.value?.id) {
if (requestId === resultRequestId.value) loading.value = false
}
}
async function exportRows() { try { await downloadApiFile(`/graduation-audits/batches/${selected.value.id}/export.xlsx`, '毕业资格审核.xlsx', { params: { keyword: keyword.value.trim() || undefined, conclusion: conclusionFilter.value || undefined, majorId: majorId.value || undefined, administrativeClassId: administrativeClassId.value || undefined } }); ElMessage.success('已导出当前筛选范围的全部记录。') } catch (error) { ElMessage.error(apiErrorMessage(error)) } }
async function removeBatch() { try { await ElMessageBox.confirm(`删除草稿批次“${selected.value.name}”及其审核结果?此操作不可恢复。`, '删除审核批次', { type: 'warning', confirmButtonText: '删除' }); await http.delete(`/graduation-audits/batches/${selected.value.id}`); ElMessage.success('草稿批次已删除。'); await load() } catch (error: any) { if (error !== 'cancel' && error !== 'close') ElMessage.error(apiErrorMessage(error)) } }
async function createBatch() {
if (!batchForm.name.trim()) return
try {
const response = await http.post('/graduation-audits/batches', batchForm)
createDialog.value = false
await http.post(`/graduation-audits/batches/${response.data.id}/calculate`)
ElMessage.success('审核批次已建立,并完成首次资格计算。')
ElMessage.success('审核批次已建立,资格计算已进入后台队列。')
await load()
} catch (error) {
ElMessage.error(apiErrorMessage(error))
@@ -103,7 +115,7 @@ async function calculate() {
type: 'warning', confirmButtonText: '重新计算',
})
await http.post(`/graduation-audits/batches/${selected.value.id}/calculate`)
ElMessage.success('已按最新培养方案与发布成绩重新计算。')
ElMessage.success('已提交后台重新计算,请刷新查看结果。')
await load()
} catch (error: any) {
if (error !== 'cancel' && error !== 'close') ElMessage.error(apiErrorMessage(error))
@@ -144,7 +156,7 @@ async function publish() {
}
}
watch([keyword, conclusionFilter], () => {
watch([keyword, conclusionFilter, majorId, administrativeClassId], () => {
resultPage.value = 1
if (filterTimer) clearTimeout(filterTimer)
filterTimer = setTimeout(() => loadBatch(), 300)
@@ -210,12 +222,16 @@ onMounted(load)
<section v-if="selected" class="graduation-workbench" v-loading="loading">
<header>
<div><span>AUDIT REGISTER</span><h3>{{ selected.name }}</h3><p>计算时间 {{ dateText(selected.calculatedAt) }} · 规则基于已发布培养方案与成绩</p></div>
<div v-if="selected.status === 'Draft' && isPublisher">
<div><span>AUDIT REGISTER</span><h3>{{ selected.name }}</h3><p>{{ selected.calculationStatus === 'Queued' ? '后台计算排队中' : selected.calculationStatus === 'Running' ? '后台计算进行中' : `计算时间 ${dateText(selected.calculatedAt)}` }} · 规则基于已发布培养方案与成绩</p></div>
<div>
<el-button :icon="Download" @click="exportRows">导出</el-button>
<template v-if="selected.status === 'Draft' && isPublisher">
<el-button :icon="Refresh" @click="calculate">重新计算</el-button>
<el-button type="danger" plain @click="removeBatch">删除批次</el-button>
<el-button type="primary" :icon="Stamp" @click="publish">发布结果</el-button>
</template>
<el-tag v-else type="success" effect="plain">结果已锁定</el-tag>
</div>
<el-tag v-else type="success" effect="plain">结果已锁定</el-tag>
</header>
<div class="graduation-summary">
@@ -231,6 +247,8 @@ onMounted(load)
<el-option label="符合毕业条件" value="Eligible" />
<el-option label="暂不符合" value="Ineligible" />
</el-select>
<el-select v-model="majorId" clearable filterable placeholder="全部专业"><el-option v-for="item in majors" :key="item.id" :label="item.name" :value="item.id" /></el-select>
<el-select v-model="administrativeClassId" clearable filterable placeholder="全部班级"><el-option v-for="item in classes.filter((x: any) => !majorId || x.majorId === majorId)" :key="item.id" :label="`${item.majorName} · ${item.name}`" :value="item.id" /></el-select>
<span>共 {{ resultTotal }} 条</span>
</div>