diff --git a/src/api/stuwork/stuassociation.ts b/src/api/stuwork/stuassociation.ts index 8b35261..ea4bc80 100644 --- a/src/api/stuwork/stuassociation.ts +++ b/src/api/stuwork/stuassociation.ts @@ -59,3 +59,13 @@ export const delObj = (ids: string[]) => { }); }; +/** + * 社团统计 - 根据学院统计社团数量 + */ +export const getAssociationStats = () => { + return request({ + url: '/stuwork/stuassociation/stats', + method: 'get' + }); +}; + diff --git a/src/api/stuwork/stugraducheck.ts b/src/api/stuwork/stugraducheck.ts index b877870..eb0d20e 100644 --- a/src/api/stuwork/stugraducheck.ts +++ b/src/api/stuwork/stugraducheck.ts @@ -23,3 +23,51 @@ export const fetchList = (query?: any) => { } }) } + +/** + * 学分确认 + * @param graduYear 毕业年份 + */ +export const confirmScore = (graduYear: string) => { + return request({ + url: '/stuwork/stugraducheck/confirmScore', + method: 'get', + params: { graduYear } + }) +} + +/** + * 操行考核确认 + * @param graduYear 毕业年份 + */ +export const confirmConduct = (graduYear: string) => { + return request({ + url: '/stuwork/stugraducheck/confirmConduct', + method: 'get', + params: { graduYear } + }) +} + +/** + * 违纪确认 + * @param graduYear 毕业年份 + */ +export const confirmPunish = (graduYear: string) => { + return request({ + url: '/stuwork/stugraducheck/confirmPunish', + method: 'get', + params: { graduYear } + }) +} + +/** + * 等级工确认 + * @param graduYear 毕业年份 + */ +export const confirmSkill = (graduYear: string) => { + return request({ + url: '/stuwork/stugraducheck/confirmSkill', + method: 'get', + params: { graduYear } + }) +} diff --git a/src/api/stuwork/stuunionleague.ts b/src/api/stuwork/stuunionleague.ts index 5d7ae57..f718f35 100644 --- a/src/api/stuwork/stuunionleague.ts +++ b/src/api/stuwork/stuunionleague.ts @@ -89,3 +89,13 @@ export const exportExcel = (query?: any) => { }); }; +/** + * 获取团员统计信息(全校总数+各学院统计) + */ +export const getStatistics = () => { + return request({ + url: '/stuwork/stuunionleague/statistics', + method: 'get' + }); +}; + diff --git a/src/views/stuwork/stuassociation/index.vue b/src/views/stuwork/stuassociation/index.vue index 9ff5aaa..cfd7fc5 100644 --- a/src/views/stuwork/stuassociation/index.vue +++ b/src/views/stuwork/stuassociation/index.vue @@ -64,12 +64,19 @@ 学生社团列表
- 新增 + + 社团统计 + - + + + + + + + + + + + + +
+ + +
+ 学院总数: + {{ statsData.length }} +
+
+ +
+ 社团总数: + {{ totalAssociationCount }} +
+
+
+
+ +
@@ -197,7 +249,7 @@ import { reactive, ref, onMounted, computed, nextTick } from 'vue' import { useRoute } from 'vue-router' import { BasicTableProps, useTable } from "/@/hooks/table"; -import { fetchList, delObj } from "/@/api/stuwork/stuassociation"; +import { fetchList, delObj, getAssociationStats } from "/@/api/stuwork/stuassociation"; import { getDeptList } from "/@/api/basic/basicclass"; import { getDicts } from "/@/api/admin/dict"; import { useMessage, useMessageBox } from "/@/hooks/message"; @@ -205,9 +257,9 @@ import { parseTime } from "/@/utils/formatTime"; import TableColumnControl from '/@/components/TableColumnControl/index.vue' import FormDialog from './form.vue' import MemberDialog from './member.vue' -import { - List, Trophy, OfficeBuilding, User, UserFilled, Calendar, - Phone, Collection, Document, Files, Setting, Menu, Search +import { + List, Trophy, OfficeBuilding, User, UserFilled, Calendar, + Phone, Collection, Document, Files, Setting, Menu, Search, DataAnalysis } from '@element-plus/icons-vue' import { useTableColumnControl } from '/@/hooks/tableColumn' @@ -222,6 +274,11 @@ const showSearch = ref(true) const deptList = ref([]) const typeList = ref([]) +// 社团统计相关 +const statsDialogVisible = ref(false) +const statsLoading = ref(false) +const statsData = ref([]) + // 表格列配置 const tableColumns = [ { prop: 'associationName', label: '社团名称', minWidth: 200 }, @@ -362,6 +419,31 @@ const getTypeDict = async () => { } } +// 社团统计 +const handleStats = async () => { + statsDialogVisible.value = true + statsLoading.value = true + statsData.value = [] + try { + const res = await getAssociationStats() + if (res.data && Array.isArray(res.data)) { + statsData.value = res.data + } else { + statsData.value = [] + } + } catch (err: any) { + useMessage().error(err.msg || '获取统计数据失败') + statsData.value = [] + } finally { + statsLoading.value = false + } +} + +// 社团总数计算 +const totalAssociationCount = computed(() => { + return statsData.value.reduce((sum, item) => sum + (item.associationCount || 0), 0) +}) + // 初始化 onMounted(() => { getDeptListData() @@ -375,5 +457,32 @@ onMounted(() => { diff --git a/src/views/stuwork/stugraducheck/index.vue b/src/views/stuwork/stugraducheck/index.vue index b484928..fcb229c 100644 --- a/src/views/stuwork/stugraducheck/index.vue +++ b/src/views/stuwork/stugraducheck/index.vue @@ -103,6 +103,10 @@ 毕业学生名单
+ 学分确认 + 操行确认 + 违纪确认 + 等级工确认
+ + + +
+ + + + + + + + + + + + + + + + + + + + 不合格学生列表 + + + + + + + + + + +
+ + +
@@ -188,7 +247,7 @@ import { reactive, ref, computed, onMounted } from 'vue' import { useRoute } from 'vue-router' import { BasicTableProps, useTable } from '/@/hooks/table' -import { fetchList } from '/@/api/stuwork/stugraducheck' +import { fetchList, confirmScore, confirmConduct, confirmPunish, confirmSkill } from '/@/api/stuwork/stugraducheck' import { getDeptList } from '/@/api/basic/basicclass' import TableColumnControl from '/@/components/TableColumnControl/index.vue' import { @@ -198,9 +257,11 @@ import { Document, Menu, Search, - Grid + Grid, + DataAnalysis } from '@element-plus/icons-vue' import { useTableColumnControl } from '/@/hooks/tableColumn' +import { useMessage } from '/@/hooks/message' const route = useRoute() const searchFormRef = ref() @@ -208,6 +269,26 @@ const columnControlRef = ref() const showSearch = ref(true) const deptList = ref([]) +// 确认对话框相关变量 +const confirmDialogVisible = ref(false) +const confirmLoading = ref(false) +const confirmResult = ref({ + confirmType: '', + totalCount: 0, + qualifiedCount: 0, + unqualifiedCount: 0, + unqualifiedList: [] +}) +const confirmTypeLabel = computed(() => { + const map: Record = { + score: '学分确认', + conduct: '操行确认', + punish: '违纪确认', + skill: '等级工确认' + } + return map[confirmResult.value.confirmType] || '确认结果' +}) + // 毕业年份:当前年前后各 5 年 const graduYearOptions = computed(() => { const y = new Date().getFullYear() @@ -299,6 +380,86 @@ const loadDeptList = async () => { } } +// 学分确认 +const handleConfirmScore = async () => { + if (!searchForm.graduYear) { + useMessage().warning('请先选择毕业年份') + return + } + confirmLoading.value = true + confirmDialogVisible.value = true + try { + const res = await confirmScore(searchForm.graduYear) + if (res.data) { + confirmResult.value = res.data + } + } catch (err: any) { + useMessage().error(err.msg || '学分确认失败') + } finally { + confirmLoading.value = false + } +} + +// 操行确认 +const handleConfirmConduct = async () => { + if (!searchForm.graduYear) { + useMessage().warning('请先选择毕业年份') + return + } + confirmLoading.value = true + confirmDialogVisible.value = true + try { + const res = await confirmConduct(searchForm.graduYear) + if (res.data) { + confirmResult.value = res.data + } + } catch (err: any) { + useMessage().error(err.msg || '操行确认失败') + } finally { + confirmLoading.value = false + } +} + +// 违纪确认 +const handleConfirmPunish = async () => { + if (!searchForm.graduYear) { + useMessage().warning('请先选择毕业年份') + return + } + confirmLoading.value = true + confirmDialogVisible.value = true + try { + const res = await confirmPunish(searchForm.graduYear) + if (res.data) { + confirmResult.value = res.data + } + } catch (err: any) { + useMessage().error(err.msg || '违纪确认失败') + } finally { + confirmLoading.value = false + } +} + +// 等级工确认 +const handleConfirmSkill = async () => { + if (!searchForm.graduYear) { + useMessage().warning('请先选择毕业年份') + return + } + confirmLoading.value = true + confirmDialogVisible.value = true + try { + const res = await confirmSkill(searchForm.graduYear) + if (res.data) { + confirmResult.value = res.data + } + } catch (err: any) { + useMessage().error(err.msg || '等级工确认失败') + } finally { + confirmLoading.value = false + } +} + onMounted(() => { loadDeptList() }) diff --git a/src/views/stuwork/stuunionleague/index.vue b/src/views/stuwork/stuunionleague/index.vue index 2279b75..8d5de1c 100644 --- a/src/views/stuwork/stuunionleague/index.vue +++ b/src/views/stuwork/stuunionleague/index.vue @@ -78,23 +78,29 @@ 学生团组织列表
- + 团员统计 + + 新增 - 导入 - 导出 @@ -204,10 +210,10 @@ - + + + + +
+ + + +
+ + 各学院团员统计 + + + + + + + + + + + +
@@ -242,13 +289,13 @@ import { reactive, ref, onMounted, computed, nextTick } from 'vue' import { useRoute } from 'vue-router' import { BasicTableProps, useTable } from "/@/hooks/table"; -import { fetchList, delObj, importExcel, exportExcel } from "/@/api/stuwork/stuunionleague"; +import { fetchList, delObj, importExcel, exportExcel, getStatistics } from "/@/api/stuwork/stuunionleague"; import { getClassListByRole } from "/@/api/basic/basicclass"; import { getGradeList } from "/@/api/basic/basicclass"; import { useMessage, useMessageBox } from "/@/hooks/message"; import { parseTime } from "/@/utils/formatTime"; import TableColumnControl from '/@/components/TableColumnControl/index.vue' -import { UploadFilled, List, OfficeBuilding, Grid, CreditCard, Avatar, Phone, Calendar, Postcard, Briefcase, Setting, Menu, Search, Document } from '@element-plus/icons-vue' +import { UploadFilled, List, OfficeBuilding, Grid, CreditCard, Avatar, Phone, Calendar, Postcard, Briefcase, Setting, Menu, Search, Document, DataAnalysis } from '@element-plus/icons-vue' import { useTableColumnControl } from '/@/hooks/tableColumn' import type { UploadFile, UploadFiles } from 'element-plus'; @@ -267,6 +314,14 @@ const importDialogVisible = ref(false) const importLoading = ref(false) const fileList = ref([]) +// 统计相关变量 +const statisticsDialogVisible = ref(false) +const statisticsLoading = ref(false) +const statisticsData = ref({ + totalCount: 0, + deptList: [] +}) + // 表格列配置 const tableColumns = [ { prop: 'deptName', label: '学院名称', minWidth: 150 }, @@ -452,6 +507,22 @@ const getGradeListData = async () => { } } +// 打开统计对话框 +const handleStatistics = async () => { + statisticsDialogVisible.value = true + statisticsLoading.value = true + try { + const res = await getStatistics() + if (res.data) { + statisticsData.value = res.data + } + } catch (err: any) { + useMessage().error(err.msg || '获取统计数据失败') + } finally { + statisticsLoading.value = false + } +} + // ??? onMounted(() => { getClassListData()