Merge branch 'developer' of ssh://code.cyweb.top:30033/scj/zhxy/v3/cloud-ui into developer

This commit is contained in:
吴红兵
2026-03-12 21:47:48 +08:00
9 changed files with 1441 additions and 206 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -299,6 +299,35 @@
</span>
</template>
</el-dialog>
<!-- 证书导出弹窗 -->
<el-dialog title="证书导出" v-model="exportCertificateDialogVisible" :close-on-click-modal="false" draggable width="450px">
<el-form :model="exportCertificateForm" label-width="80px">
<el-form-item label="班级" required>
<el-select v-model="exportCertificateForm.classCode" placeholder="请选择班级" filterable style="width: 100%">
<el-option v-for="item in classList" :key="item.classCode" :label="item.classNo" :value="item.classCode" />
</el-select>
</el-form-item>
<el-form-item label="导出类型">
<el-select v-model="exportCertificateForm.exportType" placeholder="请选择导出类型" clearable style="width: 100%">
<el-option label="全部" :value="null" />
<el-option v-for="item in majorLevelList" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="exportCertificateDialogVisible = false"> </el-button>
<el-button
type="primary"
@click="handleExportCertificateConfirm"
:loading="exportCertificateLoading"
:disabled="!exportCertificateForm.classCode">
确认导出
</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
@@ -392,6 +421,14 @@ const workYearList = ref<any[]>([]);
const applyInternshipForm = reactive({
year: '',
});
// 证书导出相关
const exportCertificateDialogVisible = ref(false);
const exportCertificateLoading = ref(false);
const majorLevelList = ref<any[]>([]);
const exportCertificateForm = reactive({
classCode: '',
exportType: '' as string | null,
});
// 表格列配置
const tableColumns = [
@@ -817,14 +854,45 @@ const handleExportStudentCard = async () => {
// 证书导出
const handleExportCertificate = async () => {
// 获取导出类型字典
if (majorLevelList.value.length === 0) {
try {
const res = await getDicts('major_level');
if (res.data && Array.isArray(res.data)) {
majorLevelList.value = res.data.map((item: any) => ({
label: item.label || item.dictLabel || item.name,
value: item.value || item.dictValue || item.code,
}));
}
} catch (err) {
majorLevelList.value = [];
}
}
// 重置表单
exportCertificateForm.classCode = searchForm.classCode || '';
exportCertificateForm.exportType = null;
exportCertificateDialogVisible.value = true;
};
// 确认证书导出
const handleExportCertificateConfirm = async () => {
if (!exportCertificateForm.classCode) {
useMessage().warning('请选择班级');
return;
}
exportCertificateLoading.value = true;
try {
await makeExportSkillLevelTask({
deptCode: searchForm.deptCode,
classCode: searchForm.classCode,
classCode: exportCertificateForm.classCode,
exportType: exportCertificateForm.exportType || null,
});
useMessage().success('导出任务已创建,请在文件管理中下载');
exportCertificateDialogVisible.value = false;
} catch (err: any) {
useMessage().error(err.msg || '创建导出任务失败');
} finally {
exportCertificateLoading.value = false;
}
};

View File

@@ -59,6 +59,7 @@
</span>
<div class="header-actions">
<el-button icon="FolderAdd" type="primary" @click="formDialogRef.openDialog()"> 新增 </el-button>
<el-button icon="DataAnalysis" type="info" class="ml10" @click="handleOpenSummary"> 学期统计 </el-button>
<el-button icon="Upload" type="success" class="ml10" @click="handleImport"> 导入 </el-button>
<el-button icon="Download" type="warning" class="ml10" @click="handleExport"> 导出 </el-button>
<right-toolbar
@@ -166,19 +167,56 @@
:temp-url="templateUrl"
@refreshDataList="getDataList"
/>
<!-- 学期统计弹出框 -->
<el-dialog v-model="summaryVisible" title="日卫生学年学期统计" width="900px" destroy-on-close>
<el-form :model="summaryForm" :inline="true" class="mb10">
<el-form-item label="学年">
<el-select v-model="summaryForm.schoolYear" placeholder="请选择学年" clearable filterable style="width: 180px">
<el-option v-for="item in schoolYearList" :key="item.year" :label="item.year" :value="item.year" />
</el-select>
</el-form-item>
<el-form-item label="学期">
<el-select v-model="summaryForm.schoolTerm" placeholder="请选择学期" clearable style="width: 180px">
<el-option v-for="item in schoolTermList" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item label="学院">
<el-select v-model="summaryForm.deptCode" placeholder="请选择学院" clearable filterable style="width: 180px">
<el-option v-for="item in deptList" :key="item.deptCode" :label="item.deptName" :value="item.deptCode" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuerySummary">查询</el-button>
</el-form-item>
</el-form>
<el-table :data="summaryData" v-loading="summaryLoading" stripe max-height="400" :cell-style="{ padding: '8px 0', textAlign: 'center' }" :header-cell-style="{ background: '#f5f7fa', color: '#606266', fontWeight: 'bold', textAlign: 'center' }">
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column prop="deptName" label="学院" min-width="120" align="center" show-overflow-tooltip />
<el-table-column prop="className" label="班级" min-width="120" align="center" show-overflow-tooltip />
<el-table-column prop="totalScore" label="总分" min-width="100" align="center" />
<el-table-column prop="plusScore" label="加分" min-width="100" align="center" />
<el-table-column prop="minusScore" label="扣分" min-width="100" align="center" />
</el-table>
<template v-if="summaryData.length === 0 && !summaryLoading">
<el-empty description="暂无统计数据" :image-size="80" />
</template>
</el-dialog>
</div>
</template>
<script setup lang="ts" name="ClassRoomHygieneDaily">
import { ref, reactive, defineAsyncComponent, onMounted } from 'vue';
import { BasicTableProps, useTable } from '/@/hooks/table';
import { fetchList, delObjs } from '/@/api/stuwork/classroomhygienedaily';
import { fetchList, delObjs, summary } from '/@/api/stuwork/classroomhygienedaily';
import { downloadClassRoomHygieneDailyTemplate, makeExportClassRoomHygieneDailyTask, downloadBlobFile } from '/@/api/stuwork/file';
import { useMessage, useMessageBox } from '/@/hooks/message';
import { getDeptList } from '/@/api/basic/basicclass';
import { getClassListByRole } from '/@/api/basic/basicclass';
import { queryAllSchoolYear } from '/@/api/basic/basicyear';
import { getDicts } from '/@/api/admin/dict';
import TableColumnControl from '/@/components/TableColumnControl/index.vue';
import { List, OfficeBuilding, Grid, Calendar, Minus, Document, Setting, Menu, Search, EditPen } from '@element-plus/icons-vue';
import { List, OfficeBuilding, Grid, Calendar, Minus, Document, Setting, Menu, Search, EditPen, DataAnalysis } from '@element-plus/icons-vue';
import { useTableColumnControl } from '/@/hooks/tableColumn';
// 引入组件
@@ -197,6 +235,18 @@ const classList = ref<any[]>([]);
// 模板文件URL
const templateUrl = ref('/stuwork/classRoomHygieneDaily/import/template');
// 统计相关变量
const summaryVisible = ref(false);
const summaryLoading = ref(false);
const summaryData = ref<any[]>([]);
const schoolYearList = ref<any[]>([]);
const schoolTermList = ref<any[]>([]);
const summaryForm = reactive({
schoolYear: '',
schoolTerm: '',
deptCode: ''
});
// 表格列配置
const tableColumns = [
{ prop: 'deptName', label: '学院', icon: OfficeBuilding },
@@ -313,10 +363,72 @@ const handleDelete = async (ids: string[]) => {
}
};
// 打开统计弹窗
const handleOpenSummary = () => {
summaryVisible.value = true;
summaryForm.schoolYear = '';
summaryForm.schoolTerm = '';
summaryForm.deptCode = '';
summaryData.value = [];
};
// 查询统计数据
const handleQuerySummary = async () => {
if (!summaryForm.schoolYear || !summaryForm.schoolTerm) {
useMessage().warning('请选择学年和学期');
return;
}
summaryLoading.value = true;
try {
const res = await summary({
schoolYear: summaryForm.schoolYear,
schoolTerm: summaryForm.schoolTerm,
deptCode: summaryForm.deptCode
});
summaryData.value = Array.isArray(res.data) ? res.data : [];
} catch (err: any) {
useMessage().error(err.msg || '获取统计数据失败');
summaryData.value = [];
} finally {
summaryLoading.value = false;
}
};
// 获取学年列表
const getSchoolYearListData = async () => {
try {
const res = await queryAllSchoolYear();
if (res.data) {
schoolYearList.value = Array.isArray(res.data) ? res.data : [];
}
} catch (err) {
schoolYearList.value = [];
}
};
// 获取学期字典
const getSchoolTermDict = async () => {
try {
const res = await getDicts('school_term');
if (res.data) {
schoolTermList.value = Array.isArray(res.data)
? res.data.map((item: any) => ({
label: item.label || item.dictLabel || item.name,
value: item.value || item.dictValue || item.code,
}))
: [];
}
} catch (err) {
schoolTermList.value = [];
}
};
// 初始化
onMounted(() => {
getDeptListData();
getClassListData();
getSchoolYearListData();
getSchoolTermDict();
});
</script>

View File

@@ -59,6 +59,7 @@
<div class="header-actions">
<el-button icon="Upload" type="primary" @click="handleImport"> 导入 </el-button>
<el-button icon="Download" type="warning" class="ml10" @click="handleExport"> 导出 </el-button>
<el-button icon="DataAnalysis" type="info" class="ml10" @click="handleOpenSummary"> 学期统计 </el-button>
<el-button icon="DocumentChecked" type="success" class="ml10" @click="handleCheck"> 考核 </el-button>
<right-toolbar v-model:showSearch="showSearch" class="ml10" @queryTable="getDataList">
<TableColumnControl
@@ -192,6 +193,40 @@
</span>
</template>
</el-dialog>
<!-- 学期统计弹出框 -->
<el-dialog v-model="summaryVisible" title="月卫生学年学期统计" width="900px" destroy-on-close>
<el-form :model="summaryForm" :inline="true" class="mb10">
<el-form-item label="学年">
<el-select v-model="summaryForm.schoolYear" placeholder="请选择学年" clearable filterable style="width: 180px">
<el-option v-for="item in schoolYearList" :key="item.year" :label="item.year" :value="item.year" />
</el-select>
</el-form-item>
<el-form-item label="学期">
<el-select v-model="summaryForm.schoolTerm" placeholder="请选择学期" clearable style="width: 180px">
<el-option v-for="item in schoolTermList" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item label="学院">
<el-select v-model="summaryForm.deptCode" placeholder="请选择学院" clearable filterable style="width: 180px">
<el-option v-for="item in deptList" :key="item.deptCode" :label="item.deptName" :value="item.deptCode" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuerySummary">查询</el-button>
</el-form-item>
</el-form>
<el-table :data="summaryData" v-loading="summaryLoading" stripe max-height="400" :cell-style="{ padding: '8px 0', textAlign: 'center' }" :header-cell-style="{ background: '#f5f7fa', color: '#606266', fontWeight: 'bold', textAlign: 'center' }">
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column prop="deptName" label="学院" min-width="120" align="center" show-overflow-tooltip />
<el-table-column prop="className" label="班级" min-width="120" align="center" show-overflow-tooltip />
<el-table-column prop="avgScore" label="平均分" min-width="100" align="center" />
<el-table-column prop="recordCount" label="考核月数" min-width="100" align="center" />
</el-table>
<template v-if="summaryData.length === 0 && !summaryLoading">
<el-empty description="暂无统计数据" :image-size="80" />
</template>
</el-dialog>
</div>
</template>
@@ -199,7 +234,7 @@
import { ref, reactive, defineAsyncComponent, computed, onMounted } from 'vue';
import { useRoute } from 'vue-router';
import { BasicTableProps, useTable } from '/@/hooks/table';
import { fetchList, delObjs, checkClassRoomHygieneMonthly } from '/@/api/stuwork/classroomhygienemonthly';
import { fetchList, delObjs, checkClassRoomHygieneMonthly, monthlySummaryByYearTerm } from '/@/api/stuwork/classroomhygienemonthly';
import { makeExportClassRoomHygieneMonthlyTask } from '/@/api/stuwork/file';
import { useMessage, useMessageBox } from '/@/hooks/message';
import { queryAllSchoolYear } from '/@/api/basic/basicyear';
@@ -244,6 +279,16 @@ const checkDialogVisible = ref(false);
// 模板文件URL - 使用后端接口
const templateUrl = ref('/stuwork/classroomhygienemonthly/import/template');
// 统计相关变量
const summaryVisible = ref(false);
const summaryLoading = ref(false);
const summaryData = ref<any[]>([]);
const summaryForm = reactive({
schoolYear: '',
schoolTerm: '',
deptCode: ''
});
// 表格列配置
const tableColumns = [
{ prop: 'schoolYear', label: '学年' },
@@ -524,6 +569,37 @@ const formatSchoolTerm = (value: string | number) => {
return dictItem ? dictItem.label : value;
};
// 打开统计弹窗
const handleOpenSummary = () => {
summaryVisible.value = true;
summaryForm.schoolYear = '';
summaryForm.schoolTerm = '';
summaryForm.deptCode = '';
summaryData.value = [];
};
// 查询统计数据
const handleQuerySummary = async () => {
if (!summaryForm.schoolYear || !summaryForm.schoolTerm) {
useMessage().warning('请选择学年和学期');
return;
}
summaryLoading.value = true;
try {
const res = await monthlySummaryByYearTerm({
schoolYear: summaryForm.schoolYear,
schoolTerm: summaryForm.schoolTerm,
deptCode: summaryForm.deptCode
});
summaryData.value = Array.isArray(res.data) ? res.data : [];
} catch (err: any) {
useMessage().error(err.msg || '获取统计数据失败');
summaryData.value = [];
} finally {
summaryLoading.value = false;
}
};
// 初始化
onMounted(() => {
getSchoolYearList();

View File

@@ -62,16 +62,16 @@
每周工作计划列表
</span>
<div class="header-actions">
<el-button
icon="FolderAdd"
type="primary"
<el-button
icon="FolderAdd"
type="primary"
@click="formDialogRef.openDialog()">
新增
</el-button>
<right-toolbar
v-model:showSearch="showSearch"
<right-toolbar
v-model:showSearch="showSearch"
:export="'stuwork_weekPlan_export'"
@exportExcel="exportExcel"
@exportExcel="exportExcel"
class="ml10"
@queryTable="getDataList">
<TableColumnControl
@@ -132,30 +132,37 @@
</template>
</el-table-column>
</template>
<el-table-column label="操作" width="250" align="center" fixed="right">
<el-table-column label="操作" width="300" align="center" fixed="right">
<template #header>
<el-icon><Setting /></el-icon>
<span style="margin-left: 4px">操作</span>
</template>
<template #default="scope">
<el-button
icon="View"
<el-button
icon="View"
link
type="primary"
type="primary"
@click="handleViewDetail(scope.row.id)">
查看详情
</el-button>
<el-button
icon="EditPen"
<el-button
icon="DataAnalysis"
link
type="primary"
type="success"
@click="handleOpenStatistics(scope.row.id)">
查看统计
</el-button>
<el-button
icon="EditPen"
link
type="primary"
@click="formDialogRef.openDialog(scope.row.id)">
编辑
</el-button>
<el-button
icon="Delete"
<el-button
icon="Delete"
link
type="danger"
type="danger"
@click="handleDelete([scope.row.id])">
删除
</el-button>
@@ -180,21 +187,56 @@
<!-- 编辑新增 -->
<FormDialog ref="formDialogRef" @refresh="getDataList(false)" />
<!-- 详情对话框 -->
<DetailDialog ref="detailDialogRef" @refresh="getDataList(false)" />
<!-- 查看统计弹出框 -->
<el-dialog v-model="statisticsVisible" title="班级班主任查看状况统计" width="800px" destroy-on-close>
<el-form :model="statisticsForm" :inline="true" class="mb10">
<el-form-item label="学院">
<el-select v-model="statisticsForm.deptCode" placeholder="请选择学院" clearable filterable style="width: 180px">
<el-option v-for="item in deptList" :key="item.deptCode" :label="item.deptName" :value="item.deptCode" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQueryStatistics">查询</el-button>
</el-form-item>
</el-form>
<el-table :data="statisticsData" v-loading="statisticsLoading" stripe max-height="400" :cell-style="{ padding: '8px 0', textAlign: 'center' }" :header-cell-style="{ background: '#f5f7fa', color: '#606266', fontWeight: 'bold', textAlign: 'center' }">
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column prop="className" label="班级" min-width="150" align="center" show-overflow-tooltip />
<el-table-column prop="teacherRealName" label="班主任" min-width="100" align="center" show-overflow-tooltip />
<el-table-column prop="hasRead" label="是否已查看" min-width="100" align="center">
<template #default="scope">
<el-tag :type="scope.row.hasRead ? 'success' : 'danger'" size="small">
{{ scope.row.hasRead ? '已查看' : '未查看' }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="readTime" label="查看时间" min-width="160" align="center" show-overflow-tooltip>
<template #default="scope">
{{ scope.row.readTime || '-' }}
</template>
</el-table-column>
</el-table>
<template v-if="statisticsData.length === 0 && !statisticsLoading">
<el-empty description="暂无统计数据" :image-size="80" />
</template>
</el-dialog>
</div>
</template>
<script setup lang="ts" name="WeekPlan">
import { ref, reactive, defineAsyncComponent, onMounted, nextTick } from 'vue'
import { BasicTableProps, useTable } from "/@/hooks/table";
import { fetchList, delObjs } from "/@/api/stuwork/weekplan";
import { fetchList, delObjs, readStatistics } from "/@/api/stuwork/weekplan";
import { useMessage, useMessageBox } from "/@/hooks/message";
import { queryAllSchoolYear } from '/@/api/basic/basicyear'
import { getDeptList } from '/@/api/basic/basicclass'
import TableColumnControl from '/@/components/TableColumnControl/index.vue'
import {
List, Calendar, Clock, Document, User, Setting, Menu, Search, EditPen
import {
List, Calendar, Clock, Document, User, Setting, Menu, Search, EditPen, DataAnalysis
} from '@element-plus/icons-vue'
import { useTableColumnControl } from '/@/hooks/tableColumn'
@@ -210,6 +252,16 @@ const columnControlRef = ref<any>()
// 搜索变量
const showSearch = ref(true)
const schoolYearList = ref<any[]>([])
const deptList = ref<any[]>([])
// 统计相关变量
const statisticsVisible = ref(false)
const statisticsLoading = ref(false)
const statisticsData = ref<any[]>([])
const statisticsForm = reactive({
weekPlanId: '',
deptCode: ''
})
// 搜索表单
const searchForm = reactive({
@@ -326,9 +378,47 @@ const getSchoolYearList = async () => {
}
}
// 获取学院列表
const getDeptListData = async () => {
try {
const res = await getDeptList()
if (res.data) {
deptList.value = Array.isArray(res.data) ? res.data : []
}
} catch (err) {
deptList.value = []
}
}
// 打开统计弹窗
const handleOpenStatistics = (weekPlanId: string) => {
statisticsVisible.value = true
statisticsForm.weekPlanId = weekPlanId
statisticsForm.deptCode = ''
statisticsData.value = []
}
// 查询统计数据
const handleQueryStatistics = async () => {
statisticsLoading.value = true
try {
const res = await readStatistics({
weekPlanId: statisticsForm.weekPlanId,
deptCode: statisticsForm.deptCode
})
statisticsData.value = Array.isArray(res.data) ? res.data : []
} catch (err: any) {
useMessage().error(err.msg || '获取统计数据失败')
statisticsData.value = []
} finally {
statisticsLoading.value = false
}
}
// 初始化
onMounted(() => {
getSchoolYearList()
getDeptListData()
})
</script>