修改打包报错问题
This commit is contained in:
@@ -8,4 +8,4 @@ VITE_OPEN=true
|
|||||||
ENV=development
|
ENV=development
|
||||||
|
|
||||||
# ADMIN 服务地址
|
# ADMIN 服务地址
|
||||||
VITE_ADMIN_PROXY_PATH = http://localhost:9999
|
VITE_ADMIN_PROXY_PATH = http://scj-v3.zhxy.link/api
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
16
src/api/asset/loading.ts
Normal file
16
src/api/asset/loading.ts
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import { NextLoading } from '/@/utils/loading';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 显示加载动画
|
||||||
|
*/
|
||||||
|
export const showLoading = () => {
|
||||||
|
NextLoading.start();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 隐藏加载动画
|
||||||
|
*/
|
||||||
|
export const hideLoading = () => {
|
||||||
|
NextLoading.done();
|
||||||
|
};
|
||||||
|
|
||||||
@@ -222,6 +222,16 @@ export const queryNoLeavelClass = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询所有班级
|
||||||
|
*/
|
||||||
|
export const queryAllClass = () => {
|
||||||
|
return request({
|
||||||
|
url: '/basic/basicclass/queryAllClass',
|
||||||
|
method: 'get',
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取班级流失情况
|
* 获取班级流失情况
|
||||||
* @param query
|
* @param query
|
||||||
|
|||||||
13
src/api/contract/contract.ts
Normal file
13
src/api/contract/contract.ts
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import request from '/@/utils/request';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据字典类型获取字典数据
|
||||||
|
* @param type 字典类型
|
||||||
|
*/
|
||||||
|
export const getDictByType = (type: string) => {
|
||||||
|
return request({
|
||||||
|
url: `/admin/dict/item/type/${type}`,
|
||||||
|
method: 'get',
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
26
src/api/finance/financenormalstu.ts
Normal file
26
src/api/finance/financenormalstu.ts
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import request from '/@/utils/request';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新缴费状态(单个学生)
|
||||||
|
* @param data 包含 serialNumber 的对象
|
||||||
|
*/
|
||||||
|
export const updateFs = (data: { serialNumber: string }) => {
|
||||||
|
return request({
|
||||||
|
url: '/finance/financenormalstu/updateFs',
|
||||||
|
method: 'post',
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量更新缴费状态
|
||||||
|
* @param data 包含 year 和 stuSource 的对象
|
||||||
|
*/
|
||||||
|
export const updateAllFS = (data: { year: string; stuSource: string }) => {
|
||||||
|
return request({
|
||||||
|
url: '/finance/financenormalstu/updateAllFS',
|
||||||
|
method: 'post',
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
6
src/api/professional/teacherbase.ts
Normal file
6
src/api/professional/teacherbase.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
/**
|
||||||
|
* 重新导出 teacherbase 相关函数
|
||||||
|
* 为了保持向后兼容性,从 professionaluser/teacherbase 重新导出
|
||||||
|
*/
|
||||||
|
export * from '/@/api/professional/professionaluser/teacherbase';
|
||||||
|
|
||||||
36
src/api/stuwork/classattendance.ts
Normal file
36
src/api/stuwork/classattendance.ts
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
import request from '/@/utils/request';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询班级考勤列表
|
||||||
|
* @param query
|
||||||
|
*/
|
||||||
|
export const fetchList = (query?: any) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/classattendance/page',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询我的班级列表
|
||||||
|
*/
|
||||||
|
export const queryMyClassList = () => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/classattendance/queryMyClassList',
|
||||||
|
method: 'get'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提交考勤
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
export const saveDataBatch = (data: any) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/classattendance/saveDataBatch',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
86
src/api/stuwork/classleaveapply.ts
Normal file
86
src/api/stuwork/classleaveapply.ts
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
import request from '/@/utils/request';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询批量请假列表
|
||||||
|
* @param query
|
||||||
|
*/
|
||||||
|
export const fetchList = (query?: any) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/classleaveapply/page',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增批量请假
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
export const addObj = (data: any) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/classleaveapply',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取详情
|
||||||
|
* @param id
|
||||||
|
*/
|
||||||
|
export const getDetail = (id: string) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/classleaveapply/detail',
|
||||||
|
method: 'get',
|
||||||
|
params: { id }
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编辑批量请假
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
export const editObj = (data: any) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/classleaveapply/edit',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除批量请假
|
||||||
|
* @param ids
|
||||||
|
*/
|
||||||
|
export const delObj = (ids: string[]) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/classleaveapply/delete',
|
||||||
|
method: 'post',
|
||||||
|
data: ids
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 整班删除
|
||||||
|
* @param id
|
||||||
|
*/
|
||||||
|
export const deleteByClass = (id: string) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/classleaveapply/deleteByClass',
|
||||||
|
method: 'post',
|
||||||
|
data: { id }
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取待办任务
|
||||||
|
* @param query
|
||||||
|
*/
|
||||||
|
export const getClassLeaveApplyTask = (query?: any) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/classleaveapply/task',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
61
src/api/stuwork/classroombase.ts
Normal file
61
src/api/stuwork/classroombase.ts
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
import request from '/@/utils/request';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询教室安排及公物管理列表
|
||||||
|
* @param query
|
||||||
|
*/
|
||||||
|
export const fetchList = (query?: any) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/teachclassroom/fetchClassRoomBaseList',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取详情
|
||||||
|
* @param id
|
||||||
|
*/
|
||||||
|
export const getDetail = (id: string) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/classroombase/detail',
|
||||||
|
method: 'get',
|
||||||
|
params: { id }
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编辑教室安排
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
export const editObj = (data: any) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/classroombase/edit',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出教室安排
|
||||||
|
* @param query
|
||||||
|
*/
|
||||||
|
export const exportData = (query?: any) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/classroombase/export',
|
||||||
|
method: 'post',
|
||||||
|
data: query,
|
||||||
|
responseType: 'blob'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 同步教室安排
|
||||||
|
*/
|
||||||
|
export const syncClassroomArrangement = () => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/classroombase/sync',
|
||||||
|
method: 'post'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
75
src/api/stuwork/dormliveapply.ts
Normal file
75
src/api/stuwork/dormliveapply.ts
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
import request from '/@/utils/request';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询留宿申请列表
|
||||||
|
* @param query
|
||||||
|
*/
|
||||||
|
export const fetchList = (query?: any) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/dormliveapply/page',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增留宿申请
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
export const addObj = (data: any) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/dormliveapply',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取详情
|
||||||
|
* @param id
|
||||||
|
*/
|
||||||
|
export const getDetail = (id: string) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/dormliveapply/detail',
|
||||||
|
method: 'get',
|
||||||
|
params: { id }
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编辑留宿申请
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
export const editObj = (data: any) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/dormliveapply/edit',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除留宿申请
|
||||||
|
* @param ids
|
||||||
|
*/
|
||||||
|
export const delObj = (ids: string[]) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/dormliveapply/delete',
|
||||||
|
method: 'post',
|
||||||
|
data: ids
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出留宿申请
|
||||||
|
* @param query
|
||||||
|
*/
|
||||||
|
export const exportData = (query?: any) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/dormliveapply/export',
|
||||||
|
method: 'post',
|
||||||
|
data: query,
|
||||||
|
responseType: 'blob'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
@@ -87,3 +87,15 @@ export const fetchDormRoomTreeList = (dormdataType?: string) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据房间号查询宿舍数据
|
||||||
|
* @param data 包含 roomNo 的对象
|
||||||
|
*/
|
||||||
|
export const getDataByRoomNo = (data: { roomNo: string }) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/dormroom/getDataByRoomNo',
|
||||||
|
method: 'get',
|
||||||
|
params: data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|||||||
62
src/api/stuwork/stuinnerleaveapplygroup.ts
Normal file
62
src/api/stuwork/stuinnerleaveapplygroup.ts
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
import request from '/@/utils/request';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询校内请假列表
|
||||||
|
* @param query
|
||||||
|
*/
|
||||||
|
export const fetchList = (query?: any) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/stuinnerleaveapplygroup/page',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增校内请假
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
export const addObj = (data: any) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/stuinnerleaveapplygroup',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取详情
|
||||||
|
* @param id
|
||||||
|
*/
|
||||||
|
export const getDetail = (id: string) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/stuinnerleaveapplygroup/detail',
|
||||||
|
method: 'get',
|
||||||
|
params: { id }
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编辑校内请假
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
export const editObj = (data: any) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/stuinnerleaveapplygroup/edit',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除校内请假
|
||||||
|
* @param ids
|
||||||
|
*/
|
||||||
|
export const delObj = (ids: string[]) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/stuinnerleaveapplygroup/delete',
|
||||||
|
method: 'post',
|
||||||
|
data: ids
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
99
src/api/stuwork/stuleaveapply.ts
Normal file
99
src/api/stuwork/stuleaveapply.ts
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
import request from '/@/utils/request';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询学生请假列表
|
||||||
|
* @param query
|
||||||
|
*/
|
||||||
|
export const fetchList = (query?: any) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/stuleaveapply/page',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增学生请假
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
export const addObj = (data: any) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/stuleaveapply',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取详情
|
||||||
|
* @param id
|
||||||
|
*/
|
||||||
|
export const getDetail = (id: string) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/stuleaveapply/detail',
|
||||||
|
method: 'get',
|
||||||
|
params: { id }
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编辑学生请假
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
export const editObj = (data: any) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/stuleaveapply/edit',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除学生请假
|
||||||
|
* @param ids
|
||||||
|
*/
|
||||||
|
export const delObj = (ids: string[]) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/stuleaveapply/delete',
|
||||||
|
method: 'post',
|
||||||
|
data: ids
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出学生请假
|
||||||
|
* @param query
|
||||||
|
*/
|
||||||
|
export const exportData = (query?: any) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/stuleaveapply/export',
|
||||||
|
method: 'post',
|
||||||
|
data: query,
|
||||||
|
responseType: 'blob'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 撤销学生请假
|
||||||
|
* @param id
|
||||||
|
*/
|
||||||
|
export const cancelObj = (id: string) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/stuleaveapply/cancel',
|
||||||
|
method: 'post',
|
||||||
|
data: { id }
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取待办任务
|
||||||
|
* @param query
|
||||||
|
*/
|
||||||
|
export const getStuLeaveApplyTask = (query?: any) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/stuleaveapply/task',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
@@ -1,5 +1,78 @@
|
|||||||
import request from '/@/utils/request';
|
import request from '/@/utils/request';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询学生违纪列表
|
||||||
|
* @param query
|
||||||
|
*/
|
||||||
|
export const fetchList = (query?: any) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/stupunlish/page',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增学生违纪
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
export const addObj = (data: any) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/stupunlish',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取详情
|
||||||
|
* @param id
|
||||||
|
*/
|
||||||
|
export const getDetail = (id: string) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/stupunlish/detail',
|
||||||
|
method: 'get',
|
||||||
|
params: { id }
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编辑学生违纪
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
export const editObj = (data: any) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/stupunlish/edit',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除学生违纪
|
||||||
|
* @param ids
|
||||||
|
*/
|
||||||
|
export const delObj = (ids: string[]) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/stupunlish/delete',
|
||||||
|
method: 'post',
|
||||||
|
data: ids
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出学生违纪
|
||||||
|
* @param query
|
||||||
|
*/
|
||||||
|
export const exportData = (query?: any) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/stupunlish/export',
|
||||||
|
method: 'post',
|
||||||
|
data: query,
|
||||||
|
responseType: 'blob'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据班级代码查询惩罚数量
|
* 根据班级代码查询惩罚数量
|
||||||
* @param classCode 班级代码
|
* @param classCode 班级代码
|
||||||
@@ -7,7 +80,18 @@ import request from '/@/utils/request';
|
|||||||
export const queryPunlishNumByClass = (classCode: string | number) => {
|
export const queryPunlishNumByClass = (classCode: string | number) => {
|
||||||
return request({
|
return request({
|
||||||
url: `/stuwork/stupunlish/queryPunlishNumByClass/${classCode}`,
|
url: `/stuwork/stupunlish/queryPunlishNumByClass/${classCode}`,
|
||||||
method: 'get',
|
method: 'get'
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 撤销处分
|
||||||
|
* @param data 包含id和publishStatus的对象,publishStatus设置为"0"即可撤销处分
|
||||||
|
*/
|
||||||
|
export const revokePunishment = (data: any) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/stupunlish/cancelStatus',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|||||||
62
src/api/stuwork/stutemleaveapply.ts
Normal file
62
src/api/stuwork/stutemleaveapply.ts
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
import request from '/@/utils/request';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询临时请假列表
|
||||||
|
* @param query
|
||||||
|
*/
|
||||||
|
export const fetchList = (query?: any) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/stutemleaveapply/page',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增临时请假
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
export const addObj = (data: any) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/stutemleaveapply',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取详情
|
||||||
|
* @param id
|
||||||
|
*/
|
||||||
|
export const getDetail = (id: string) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/stutemleaveapply/detail',
|
||||||
|
method: 'get',
|
||||||
|
params: { id }
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编辑临时请假
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
export const editObj = (data: any) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/stutemleaveapply/edit',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除临时请假
|
||||||
|
* @param ids
|
||||||
|
*/
|
||||||
|
export const delObj = (ids: string[]) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/stutemleaveapply/delete',
|
||||||
|
method: 'post',
|
||||||
|
data: ids
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
75
src/api/stuwork/stuturnover.ts
Normal file
75
src/api/stuwork/stuturnover.ts
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
import request from '/@/utils/request';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询学籍异动列表
|
||||||
|
* @param query
|
||||||
|
*/
|
||||||
|
export const fetchList = (query?: any) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/stuturnover/page',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增学籍异动(批量)
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
export const addObj = (data: any) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/stuturnover',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取详情
|
||||||
|
* @param id
|
||||||
|
*/
|
||||||
|
export const getDetail = (id: string) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/stuturnover/detail',
|
||||||
|
method: 'get',
|
||||||
|
params: { id }
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编辑学籍异动
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
export const editObj = (data: any) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/stuturnover/edit',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除学籍异动
|
||||||
|
* @param ids
|
||||||
|
*/
|
||||||
|
export const delObj = (ids: string[]) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/stuturnover/delete',
|
||||||
|
method: 'post',
|
||||||
|
data: ids
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出学籍异动
|
||||||
|
* @param query
|
||||||
|
*/
|
||||||
|
export const exportData = (query?: any) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/stuturnover/export',
|
||||||
|
method: 'post',
|
||||||
|
data: query,
|
||||||
|
responseType: 'blob'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
72
src/api/stuwork/teachbuilding.ts
Normal file
72
src/api/stuwork/teachbuilding.ts
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
import request from '/@/utils/request';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询教学楼列表
|
||||||
|
* @param query
|
||||||
|
*/
|
||||||
|
export const fetchList = (query?: any) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/teachbuilding/page',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取教学楼列表(不分页)
|
||||||
|
*/
|
||||||
|
export const getBuildingList = () => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/teachbuilding/list',
|
||||||
|
method: 'get'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增教学楼
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
export const addObj = (data: any) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/teachbuilding',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取详情
|
||||||
|
* @param id
|
||||||
|
*/
|
||||||
|
export const getDetail = (id: string) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/teachbuilding/detail',
|
||||||
|
method: 'get',
|
||||||
|
params: { id }
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编辑教学楼
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
export const editObj = (data: any) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/teachbuilding/edit',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除教学楼
|
||||||
|
* @param ids
|
||||||
|
*/
|
||||||
|
export const delObj = (ids: string[]) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/teachbuilding/delete',
|
||||||
|
method: 'post',
|
||||||
|
data: ids
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
84
src/api/stuwork/teachclassroom.ts
Normal file
84
src/api/stuwork/teachclassroom.ts
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
import request from '/@/utils/request';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询教室列表
|
||||||
|
* @param query
|
||||||
|
*/
|
||||||
|
export const fetchList = (query?: any) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/teachclassroom/page',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取教室列表(不分页)
|
||||||
|
*/
|
||||||
|
export const getClassRoomList = () => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/teachclassroom/list',
|
||||||
|
method: 'get'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增教室
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
export const addObj = (data: any) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/teachclassroom',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取详情
|
||||||
|
* @param id
|
||||||
|
*/
|
||||||
|
export const getDetail = (id: string) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/teachclassroom/detail',
|
||||||
|
method: 'get',
|
||||||
|
params: { id }
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编辑教室
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
export const editObj = (data: any) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/teachclassroom/edit',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除教室
|
||||||
|
* @param ids
|
||||||
|
*/
|
||||||
|
export const delObj = (ids: string[]) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/teachclassroom/delete',
|
||||||
|
method: 'post',
|
||||||
|
data: ids
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量设置(批量更新选中教室的学院)
|
||||||
|
* @param data 包含ids(教室ID数组)和deptCode(学院代码)
|
||||||
|
*/
|
||||||
|
export const batchSet = (data: any) => {
|
||||||
|
return request({
|
||||||
|
url: '/stuwork/teachclassroom/batchSet',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
24
src/config/global.ts
Normal file
24
src/config/global.ts
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
/**
|
||||||
|
* 全局常量配置
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 角色代码常量
|
||||||
|
*/
|
||||||
|
export const ROLE_CODE = {
|
||||||
|
ROLE_RECRUIT: 'ROLE_RECRUIT',
|
||||||
|
ROLE_RECRUIT_SECOND: 'ROLE_RECRUIT_SECOND'
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前学期
|
||||||
|
* 注意:这个值可能需要从后端获取或从配置中读取
|
||||||
|
*/
|
||||||
|
export const CURRENT_SCHOOL_TERM = '1'; // 默认值,实际应该从后端获取
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前学年
|
||||||
|
* 注意:这个值可能需要从后端获取或从配置中读取
|
||||||
|
*/
|
||||||
|
export const CURRENT_SCHOOL_YEAR = ''; // 默认值,实际应该从后端获取
|
||||||
|
|
||||||
@@ -69,7 +69,7 @@ import { ref, reactive, onMounted } from 'vue'
|
|||||||
import { list } from '/@/api/recruit/recruitstudentplangroup'
|
import { list } from '/@/api/recruit/recruitstudentplangroup'
|
||||||
import { getTabStaticDataList as getTabStaticDataListApi } from '/@/api/recruit/recruitstudentsignup'
|
import { getTabStaticDataList as getTabStaticDataListApi } from '/@/api/recruit/recruitstudentsignup'
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import global from '@/components/tools/commondict'
|
import global from '@/components/tools/commondict.vue'
|
||||||
import { useTable } from '/@/hooks/table'
|
import { useTable } from '/@/hooks/table'
|
||||||
|
|
||||||
// 表格引用
|
// 表格引用
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ import { useMessage } from '/@/hooks/message'
|
|||||||
import { getDataStatistics } from '/@/api/recruit/newstucheckin'
|
import { getDataStatistics } from '/@/api/recruit/newstucheckin'
|
||||||
import { list } from '/@/api/recruit/recruitstudentplangroup'
|
import { list } from '/@/api/recruit/recruitstudentplangroup'
|
||||||
import { getDeptList } from '/@/api/basic/basicclass'
|
import { getDeptList } from '/@/api/basic/basicclass'
|
||||||
import { getClasslist } from '/@/api/stuwork/stupunlish'
|
import { queryAllClass } from '/@/api/basic/basicclass'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
|
|
||||||
// 使用 Pinia store
|
// 使用 Pinia store
|
||||||
@@ -173,7 +173,7 @@ const getDeptData = async () => {
|
|||||||
// 查找所有班级
|
// 查找所有班级
|
||||||
const getClassData = async () => {
|
const getClassData = async () => {
|
||||||
try {
|
try {
|
||||||
const data = await getClasslist()
|
const data = await queryAllClass()
|
||||||
classData.value = data.data || []
|
classData.value = data.data || []
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('获取班级列表失败', error)
|
console.error('获取班级列表失败', error)
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ import { useMessage } from '/@/hooks/message'
|
|||||||
import { getDataStatistics } from '/@/api/recruit/newstucheckin'
|
import { getDataStatistics } from '/@/api/recruit/newstucheckin'
|
||||||
import { list } from '/@/api/recruit/recruitstudentplangroup'
|
import { list } from '/@/api/recruit/recruitstudentplangroup'
|
||||||
import { getDeptList } from '/@/api/basic/basicclass'
|
import { getDeptList } from '/@/api/basic/basicclass'
|
||||||
import { getClasslist } from '/@/api/stuwork/stupunlish'
|
import { queryAllClass } from '/@/api/basic/basicclass'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
|
|
||||||
// 使用 Pinia store
|
// 使用 Pinia store
|
||||||
@@ -173,7 +173,7 @@ const getDeptData = async () => {
|
|||||||
// 查找所有班级
|
// 查找所有班级
|
||||||
const getClassData = async () => {
|
const getClassData = async () => {
|
||||||
try {
|
try {
|
||||||
const data = await getClasslist()
|
const data = await queryAllClass()
|
||||||
classData.value = data.data || []
|
classData.value = data.data || []
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('获取班级列表失败', error)
|
console.error('获取班级列表失败', error)
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ import { getMNStuList, delMNObj } from '@/api/recruit/recruitImitateAdjustBatch'
|
|||||||
import { listPlanByCondition as planMajor } from "@/api/recruit/recruitstudentplan"
|
import { listPlanByCondition as planMajor } from "@/api/recruit/recruitstudentplan"
|
||||||
import { getTypeValue } from "@/api/admin/dict"
|
import { getTypeValue } from "@/api/admin/dict"
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import global from '@/components/tools/commondict'
|
import global from '@/components/tools/commondict.vue'
|
||||||
|
|
||||||
const AddMNStu = defineAsyncComponent(() => import('./addMNStu.vue'))
|
const AddMNStu = defineAsyncComponent(() => import('./addMNStu.vue'))
|
||||||
|
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ import { getDeptList } from "@/api/basic/basicclass"
|
|||||||
import { dormApplyAnalysis } from "@/api/recruit/recruitstudentsignup"
|
import { dormApplyAnalysis } from "@/api/recruit/recruitstudentsignup"
|
||||||
import { list } from '@/api/recruit/recruitstudentplangroup'
|
import { list } from '@/api/recruit/recruitstudentplangroup'
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import global from '@/components/tools/commondict'
|
import global from '@/components/tools/commondict.vue'
|
||||||
|
|
||||||
// 响应式数据
|
// 响应式数据
|
||||||
const deptList = ref<any[]>([])
|
const deptList = ref<any[]>([])
|
||||||
|
|||||||
@@ -445,7 +445,7 @@ import {
|
|||||||
oneStuNo,
|
oneStuNo,
|
||||||
changeClassInfo, getMajorClass
|
changeClassInfo, getMajorClass
|
||||||
} from '@/api/recruit/recruitstudentsignup'
|
} from '@/api/recruit/recruitstudentsignup'
|
||||||
import global from '@/components/tools/commondict'
|
import global from '@/components/tools/commondict.vue'
|
||||||
import { getClassListByRole, getDeptList, queryAllClassByInfo } from "@/api/basic/basicclass"
|
import { getClassListByRole, getDeptList, queryAllClassByInfo } from "@/api/basic/basicclass"
|
||||||
import {listPlanByCondition as planMajor} from "@/api/recruit/recruitstudentplan"
|
import {listPlanByCondition as planMajor} from "@/api/recruit/recruitstudentplan"
|
||||||
import { getTypeValue } from "@/api/admin/dict"
|
import { getTypeValue } from "@/api/admin/dict"
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
import { ref, reactive } from 'vue'
|
import { ref, reactive } from 'vue'
|
||||||
import { useMessage } from '/@/hooks/message'
|
import { useMessage } from '/@/hooks/message'
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import global from "@/components/tools/commondict"
|
import global from "@/components/tools/commondict.vue"
|
||||||
import { interview } from "@/api/recruit/recruitstudentsignup"
|
import { interview } from "@/api/recruit/recruitstudentsignup"
|
||||||
|
|
||||||
// 消息提示 hooks
|
// 消息提示 hooks
|
||||||
|
|||||||
@@ -269,7 +269,7 @@ import { list } from '/@/api/recruit/recruitstudentplangroup'
|
|||||||
import { fetchListStuDorm, yjOut, setFw, delFw, yjSend } from '/@/api/recruit/recruitstudentsignup'
|
import { fetchListStuDorm, yjOut, setFw, delFw, yjSend } from '/@/api/recruit/recruitstudentsignup'
|
||||||
import { getDeptList } from '/@/api/basic/basicclass'
|
import { getDeptList } from '/@/api/basic/basicclass'
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import global from '@/components/tools/commondict'
|
import global from '@/components/tools/commondict.vue'
|
||||||
|
|
||||||
const DormFW = defineAsyncComponent(() => import('./dormFW.vue'))
|
const DormFW = defineAsyncComponent(() => import('./dormFW.vue'))
|
||||||
const ShowMap = defineAsyncComponent(() => import('./showMap.vue'))
|
const ShowMap = defineAsyncComponent(() => import('./showMap.vue'))
|
||||||
|
|||||||
@@ -1,160 +0,0 @@
|
|||||||
<!--
|
|
||||||
- Copyright (c) 2018-2025, cyweb All rights reserved.
|
|
||||||
-
|
|
||||||
- Redistribution and use in source and binary forms, with or without
|
|
||||||
- modification, are permitted provided that the following conditions are met:
|
|
||||||
-
|
|
||||||
- Redistributions of source code must retain the above copyright notice,
|
|
||||||
- this list of conditions and the following disclaimer.
|
|
||||||
- Redistributions in binary form must reproduce the above copyright
|
|
||||||
- notice, this list of conditions and the following disclaimer in the
|
|
||||||
- documentation and/or other materials provided with the distribution.
|
|
||||||
- Neither the name of the pig4cloud.com developer nor the names of its
|
|
||||||
- contributors may be used to endorse or promote products derived from
|
|
||||||
- this software without specific prior written permission.
|
|
||||||
-
|
|
||||||
-->
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="execution">
|
|
||||||
<basic-container>
|
|
||||||
<avue-crud ref="crud"
|
|
||||||
:page="page"
|
|
||||||
:data="tableData"
|
|
||||||
:table-loading="tableLoading"
|
|
||||||
:option="tableOption"
|
|
||||||
@on-load="getList"
|
|
||||||
@search-change="handleFilter"
|
|
||||||
@refresh-change="refreshChange"
|
|
||||||
@row-update="handleUpdate"
|
|
||||||
@row-save="handleSave"
|
|
||||||
@row-del="rowDel">
|
|
||||||
</avue-crud>
|
|
||||||
</basic-container>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import {addObj, delObj, fetchList, putObj} from '@/api/recruit/recruitstudentsignupturnover'
|
|
||||||
import {tableOption} from '@/const/crud/recruit/recruitstudentsignupturnover'
|
|
||||||
import {mapGetters} from 'vuex'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'recruitstudentsignupturnover',
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
tableData: [],
|
|
||||||
page: {
|
|
||||||
total: 0, // 总页数
|
|
||||||
currentPage: 1, // 当前页数
|
|
||||||
pageSize: 10 // 每页显示多少条
|
|
||||||
},
|
|
||||||
tableLoading: false,
|
|
||||||
tableOption: tableOption,
|
|
||||||
params:{}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
},
|
|
||||||
mounted: function() { },
|
|
||||||
computed: {
|
|
||||||
...mapGetters(['permissions'])
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
getList(page) {
|
|
||||||
this.tableLoading = true
|
|
||||||
fetchList(Object.assign({
|
|
||||||
current: page.currentPage,
|
|
||||||
size: page.pageSize
|
|
||||||
}, this.params)).then(response => {
|
|
||||||
this.tableData = response.data.records
|
|
||||||
this.page.total = response.data.total
|
|
||||||
this.tableLoading = false
|
|
||||||
})
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* @title 打开新增窗口
|
|
||||||
* @detail 调用crud的handleadd方法即可
|
|
||||||
*
|
|
||||||
**/
|
|
||||||
handleAdd: function() {
|
|
||||||
this.$refs.crud.rowAdd()
|
|
||||||
},
|
|
||||||
handleEdit(row, index) {
|
|
||||||
this.$refs.crud.rowEdit(row, index)
|
|
||||||
},
|
|
||||||
handleDel(row, index) {
|
|
||||||
this.$refs.crud.rowDel(row, index)
|
|
||||||
},
|
|
||||||
rowDel: function(row, index) {
|
|
||||||
var _this = this
|
|
||||||
this.$confirm('是否确认删除ID为' + row.id, '提示', {
|
|
||||||
confirmButtonText: '确定',
|
|
||||||
cancelButtonText: '取消',
|
|
||||||
type: 'warning'
|
|
||||||
}).then(function() {
|
|
||||||
return delObj(row.id)
|
|
||||||
}).then(data => {
|
|
||||||
_this.tableData.splice(index, 1)
|
|
||||||
_this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: '删除成功',
|
|
||||||
type: 'success'
|
|
||||||
})
|
|
||||||
this.getList(this.page)
|
|
||||||
}).catch(function(err) { })
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* @title 数据更新
|
|
||||||
* @param row 为当前的数据
|
|
||||||
* @param index 为当前更新数据的行数
|
|
||||||
* @param done 为表单关闭函数
|
|
||||||
*
|
|
||||||
**/
|
|
||||||
handleUpdate: function(row, index, done) {
|
|
||||||
putObj(row).then(data => {
|
|
||||||
this.tableData.splice(index, 1, Object.assign({}, row))
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: '修改成功',
|
|
||||||
type: 'success'
|
|
||||||
})
|
|
||||||
done()
|
|
||||||
this.getList(this.page)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* @title 数据添加
|
|
||||||
* @param row 为当前的数据
|
|
||||||
* @param done 为表单关闭函数
|
|
||||||
*
|
|
||||||
**/
|
|
||||||
handleSave: function(row, done) {
|
|
||||||
addObj(row).then(data => {
|
|
||||||
this.tableData.push(Object.assign({}, row))
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: '添加成功',
|
|
||||||
type: 'success'
|
|
||||||
})
|
|
||||||
done()
|
|
||||||
this.getList(this.page)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 刷新回调
|
|
||||||
*/
|
|
||||||
refreshChange() {
|
|
||||||
this.getList(this.page)
|
|
||||||
},
|
|
||||||
handleFilter(param){
|
|
||||||
this.params = param;
|
|
||||||
this.page.currentPage = 1;
|
|
||||||
this.getList(this.page);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
</style>
|
|
||||||
279
src/views/stuwork/classattendance/index.vue
Normal file
279
src/views/stuwork/classattendance/index.vue
Normal file
@@ -0,0 +1,279 @@
|
|||||||
|
<template>
|
||||||
|
<div class="layout-padding">
|
||||||
|
<div class="layout-padding-auto layout-padding-view">
|
||||||
|
<!-- 搜索表单 -->
|
||||||
|
<el-row v-show="showSearch">
|
||||||
|
<el-form :model="searchForm" ref="searchFormRef" :inline="true" @keyup.enter="handleSearch">
|
||||||
|
<el-form-item label="班级" prop="classCode">
|
||||||
|
<el-select
|
||||||
|
v-model="searchForm.classCode"
|
||||||
|
placeholder="请选择班级"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
style="width: 200px">
|
||||||
|
<el-option
|
||||||
|
v-for="item in classList"
|
||||||
|
:key="item.classCode"
|
||||||
|
:label="item.classNo"
|
||||||
|
:value="item.classCode">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="点名类型" prop="orderType">
|
||||||
|
<el-select
|
||||||
|
v-model="searchForm.orderType"
|
||||||
|
placeholder="请选择点名类型"
|
||||||
|
clearable
|
||||||
|
style="width: 200px">
|
||||||
|
<el-option
|
||||||
|
v-for="item in orderTypeList"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" plain icon="Search" @click="handleSearch">查询</el-button>
|
||||||
|
<el-button icon="Refresh" @click="handleReset">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<!-- 操作按钮 -->
|
||||||
|
<el-row>
|
||||||
|
<div class="mb8" style="width: 100%">
|
||||||
|
<right-toolbar
|
||||||
|
v-model:showSearch="showSearch"
|
||||||
|
class="ml10 mr20"
|
||||||
|
style="float: right;"
|
||||||
|
@queryTable="getDataList">
|
||||||
|
</right-toolbar>
|
||||||
|
</div>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<!-- 表格 -->
|
||||||
|
<el-table
|
||||||
|
:data="dataList"
|
||||||
|
v-loading="loading"
|
||||||
|
border
|
||||||
|
:cell-style="tableStyle.cellStyle"
|
||||||
|
:header-cell-style="tableStyle.headerCellStyle">
|
||||||
|
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||||
|
<el-table-column prop="stuNo" label="学号" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="realName" label="姓名" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="phone" label="联系电话" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="parentPhoneA" label="家长联系电话1" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="parentPhoneB" label="家长联系电话2" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="stuStatus" label="学生状态" show-overflow-tooltip align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ formatStudentStatus(scope.row.stuStatus) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="attendanceType" label="考勤类型" show-overflow-tooltip align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ formatAttendanceType(scope.row.attendanceType) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="isRoom" label="是否住宿" show-overflow-tooltip align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ formatYesNo(scope.row.isRoom) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="roomNo" label="宿舍号" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="isDeviceIn" label="是否扫脸" show-overflow-tooltip align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-tag :type="scope.row.isDeviceIn === '1' ? 'success' : 'danger'">
|
||||||
|
{{ scope.row.isDeviceIn === '1' ? '是' : '否' }}
|
||||||
|
</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" width="100" align="center" fixed="right">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button
|
||||||
|
icon="Edit"
|
||||||
|
text
|
||||||
|
type="primary"
|
||||||
|
@click="handleEdit(scope.row)">
|
||||||
|
编辑
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts" name="ClassAttendance">
|
||||||
|
import { reactive, ref, onMounted } from 'vue'
|
||||||
|
import { fetchList, queryMyClassList } from '/@/api/stuwork/classattendance'
|
||||||
|
import { getDicts } from '/@/api/admin/dict'
|
||||||
|
import { useMessage } from '/@/hooks/message'
|
||||||
|
|
||||||
|
// 定义变量内容
|
||||||
|
const searchFormRef = ref()
|
||||||
|
const showSearch = ref(true)
|
||||||
|
const loading = ref(false)
|
||||||
|
const dataList = ref<any[]>([])
|
||||||
|
const classList = ref<any[]>([])
|
||||||
|
const orderTypeList = ref<any[]>([])
|
||||||
|
const studentStatusList = ref<any[]>([])
|
||||||
|
const attendanceTypeList = ref<any[]>([])
|
||||||
|
|
||||||
|
// 搜索表单
|
||||||
|
const searchForm = reactive({
|
||||||
|
classCode: '',
|
||||||
|
orderType: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
// 表格样式
|
||||||
|
const tableStyle = {
|
||||||
|
cellStyle: { textAlign: 'center' },
|
||||||
|
headerCellStyle: {
|
||||||
|
textAlign: 'center',
|
||||||
|
background: 'var(--el-table-row-hover-bg-color)',
|
||||||
|
color: 'var(--el-text-color-primary)',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化学生状态
|
||||||
|
const formatStudentStatus = (value: string) => {
|
||||||
|
if (!value) return '-'
|
||||||
|
const item = studentStatusList.value.find((item: any) => item.value === value)
|
||||||
|
return item ? item.label : value
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化考勤类型
|
||||||
|
const formatAttendanceType = (value: string) => {
|
||||||
|
if (!value) return '-'
|
||||||
|
const item = attendanceTypeList.value.find((item: any) => item.value === value)
|
||||||
|
return item ? item.label : value
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化是否
|
||||||
|
const formatYesNo = (value: string | null) => {
|
||||||
|
if (value === null || value === undefined || value === '') return '-'
|
||||||
|
return value === '1' || value === 'true' ? '是' : '否'
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询
|
||||||
|
const handleSearch = () => {
|
||||||
|
getDataList()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置
|
||||||
|
const handleReset = () => {
|
||||||
|
searchFormRef.value?.resetFields()
|
||||||
|
searchForm.classCode = ''
|
||||||
|
searchForm.orderType = ''
|
||||||
|
getDataList()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 编辑
|
||||||
|
const handleEdit = (row: any) => {
|
||||||
|
// TODO: 实现编辑功能
|
||||||
|
useMessage().info('编辑功能待实现')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取数据列表
|
||||||
|
const getDataList = async () => {
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const params: any = {
|
||||||
|
classCode: searchForm.classCode || undefined,
|
||||||
|
orderType: searchForm.orderType || undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
const res = await fetchList(params)
|
||||||
|
if (res.data && Array.isArray(res.data)) {
|
||||||
|
dataList.value = res.data
|
||||||
|
} else {
|
||||||
|
dataList.value = []
|
||||||
|
}
|
||||||
|
} catch (err: any) {
|
||||||
|
console.error('获取数据列表失败', err)
|
||||||
|
useMessage().error(err.msg || '获取数据列表失败')
|
||||||
|
dataList.value = []
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取班级列表
|
||||||
|
const getClassListData = async () => {
|
||||||
|
try {
|
||||||
|
const res = await queryMyClassList()
|
||||||
|
if (res.data && Array.isArray(res.data)) {
|
||||||
|
classList.value = res.data
|
||||||
|
} else {
|
||||||
|
classList.value = []
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取班级列表失败', err)
|
||||||
|
classList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取点名类型字典
|
||||||
|
const getOrderTypeDict = async () => {
|
||||||
|
try {
|
||||||
|
// 根据业务逻辑,点名类型可能是固定的几个值
|
||||||
|
// 这里先使用常见的值,如果不对可以根据实际情况调整
|
||||||
|
orderTypeList.value = [
|
||||||
|
{ label: '早读', value: '1' },
|
||||||
|
{ label: '上午', value: '2' },
|
||||||
|
{ label: '下午', value: '3' },
|
||||||
|
{ label: '晚自习', value: '4' }
|
||||||
|
]
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取点名类型失败', err)
|
||||||
|
orderTypeList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取学生状态字典
|
||||||
|
const getStudentStatusDict = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getDicts('student_status')
|
||||||
|
if (res.data && Array.isArray(res.data)) {
|
||||||
|
studentStatusList.value = res.data.map((item: any) => ({
|
||||||
|
label: item.label || item.dictLabel || item.name,
|
||||||
|
value: item.value || item.dictValue || item.code
|
||||||
|
}))
|
||||||
|
} else {
|
||||||
|
studentStatusList.value = []
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取学生状态字典失败', err)
|
||||||
|
studentStatusList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取考勤类型字典
|
||||||
|
const getAttendanceTypeDict = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getDicts('attend_type')
|
||||||
|
if (res.data && Array.isArray(res.data)) {
|
||||||
|
attendanceTypeList.value = res.data.map((item: any) => ({
|
||||||
|
label: item.label || item.dictLabel || item.name,
|
||||||
|
value: item.value || item.dictValue || item.code
|
||||||
|
}))
|
||||||
|
} else {
|
||||||
|
attendanceTypeList.value = []
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取考勤类型字典失败', err)
|
||||||
|
attendanceTypeList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化
|
||||||
|
onMounted(() => {
|
||||||
|
getClassListData()
|
||||||
|
getOrderTypeDict()
|
||||||
|
getStudentStatusDict()
|
||||||
|
getAttendanceTypeDict()
|
||||||
|
// 不自动加载数据,需要先选择班级和点名类型
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
223
src/views/stuwork/classleaveapply/detail.vue
Normal file
223
src/views/stuwork/classleaveapply/detail.vue
Normal file
@@ -0,0 +1,223 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
title="查看详情"
|
||||||
|
v-model="visible"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
draggable
|
||||||
|
width="900px">
|
||||||
|
<el-descriptions :column="2" border v-loading="loading" v-if="detailData">
|
||||||
|
<el-descriptions-item label="学年">{{ detailData.schoolYear || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="学期">
|
||||||
|
<span>{{ formatSchoolTerm(detailData.schoolTerm) }}</span>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="学院">{{ detailData.deptName || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="班号">{{ detailData.classNo || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="班主任">{{ detailData.teacherRealName || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="人数">{{ detailData.num || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="请假开始时间">
|
||||||
|
<span>{{ detailData.startTime ? formatDateTime(detailData.startTime) : '-' }}</span>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="请假结束时间">
|
||||||
|
<span>{{ detailData.endTime ? formatDateTime(detailData.endTime) : '-' }}</span>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="请假类型">
|
||||||
|
<span>{{ formatLeaveType(detailData.leaveType) }}</span>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="是否住宿">
|
||||||
|
<span>{{ formatYesNo(detailData.stayDorm) }}</span>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="时段请假">
|
||||||
|
<span>{{ formatYesNo(detailData.isSegment) }}</span>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="请假时段" :span="2">{{ detailData.segmentString || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="请假校门">
|
||||||
|
<span>{{ formatSchoolDoor(detailData.schoolDoor) }}</span>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="基础部审核">
|
||||||
|
<span>{{ formatAuditType(detailData.deptAudit) }}</span>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="学工处审批">
|
||||||
|
<span>{{ formatAuditType(detailData.schoolAudit) }}</span>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="驳回原因" :span="2">{{ detailData.rejectReason || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="请假事由" :span="2">{{ detailData.reason || '-' }}</el-descriptions-item>
|
||||||
|
</el-descriptions>
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click="visible = false">关 闭</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts" name="ClassLeaveApplyDetailDialog">
|
||||||
|
import { ref, onMounted } from 'vue'
|
||||||
|
import { getDetail } from '/@/api/stuwork/classleaveapply'
|
||||||
|
import { getDicts } from '/@/api/admin/dict'
|
||||||
|
|
||||||
|
// 定义变量内容
|
||||||
|
const visible = ref(false)
|
||||||
|
const loading = ref(false)
|
||||||
|
const detailData = ref<any>(null)
|
||||||
|
const schoolTermList = ref<any[]>([])
|
||||||
|
const leaveTypeList = ref<any[]>([])
|
||||||
|
const yesNoList = ref<any[]>([])
|
||||||
|
const auditTypeList = ref<any[]>([])
|
||||||
|
const schoolDoorList = ref<any[]>([])
|
||||||
|
|
||||||
|
// 校门列表
|
||||||
|
const schoolDoorListData = [
|
||||||
|
{ label: '校门东', value: '0' },
|
||||||
|
{ label: '校门南', value: '1' },
|
||||||
|
{ label: '校门西', value: '2' }
|
||||||
|
]
|
||||||
|
|
||||||
|
// 格式化学期
|
||||||
|
const formatSchoolTerm = (value: string | number) => {
|
||||||
|
if (value === null || value === undefined || value === '') {
|
||||||
|
return '-'
|
||||||
|
}
|
||||||
|
const dictItem = schoolTermList.value.find(item => item.value == value)
|
||||||
|
return dictItem ? dictItem.label : value
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化日期时间
|
||||||
|
const formatDateTime = (dateTime: string) => {
|
||||||
|
if (!dateTime) return '-'
|
||||||
|
if (dateTime.includes(' ')) {
|
||||||
|
return dateTime.split('.')[0]
|
||||||
|
}
|
||||||
|
return dateTime
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化请假类型
|
||||||
|
const formatLeaveType = (value: string) => {
|
||||||
|
if (!value) return '-'
|
||||||
|
const item = leaveTypeList.value.find((item: any) => item.value === value)
|
||||||
|
return item ? item.label : value
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化是否
|
||||||
|
const formatYesNo = (value: string) => {
|
||||||
|
if (value === null || value === undefined || value === '') {
|
||||||
|
return '-'
|
||||||
|
}
|
||||||
|
const dictItem = yesNoList.value.find(item => item.value == value)
|
||||||
|
return dictItem ? dictItem.label : value
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化校门
|
||||||
|
const formatSchoolDoor = (value: string) => {
|
||||||
|
if (!value) return '-'
|
||||||
|
const item = schoolDoorList.value.find((item: any) => item.value === value)
|
||||||
|
return item ? item.label : value
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化审核类型
|
||||||
|
const formatAuditType = (value: string) => {
|
||||||
|
if (value === null || value === undefined || value === '') {
|
||||||
|
return '-'
|
||||||
|
}
|
||||||
|
const dictItem = auditTypeList.value.find(item => item.value == value)
|
||||||
|
return dictItem ? dictItem.label : value
|
||||||
|
}
|
||||||
|
|
||||||
|
// 打开弹窗
|
||||||
|
const openDialog = async (id: string) => {
|
||||||
|
visible.value = true
|
||||||
|
detailData.value = null
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const res = await getDetail(id)
|
||||||
|
if (res.data) {
|
||||||
|
detailData.value = res.data
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取详情失败', err)
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取学期字典
|
||||||
|
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) {
|
||||||
|
console.error('获取学期字典失败', err)
|
||||||
|
schoolTermList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取请假类型字典
|
||||||
|
const getLeaveTypeDict = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getDicts('leave_type')
|
||||||
|
if (res.data) {
|
||||||
|
leaveTypeList.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) {
|
||||||
|
console.error('获取请假类型字典失败', err)
|
||||||
|
leaveTypeList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取是否字典
|
||||||
|
const getYesNoDict = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getDicts('yes_no')
|
||||||
|
if (res.data) {
|
||||||
|
yesNoList.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) {
|
||||||
|
console.error('获取是否字典失败', err)
|
||||||
|
yesNoList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取审核类型字典
|
||||||
|
const getAuditTypeDict = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getDicts('class_audit_type')
|
||||||
|
if (res.data) {
|
||||||
|
auditTypeList.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) {
|
||||||
|
console.error('获取审核类型字典失败', err)
|
||||||
|
auditTypeList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化
|
||||||
|
onMounted(() => {
|
||||||
|
schoolDoorList.value = schoolDoorListData
|
||||||
|
getSchoolTermDict()
|
||||||
|
getLeaveTypeDict()
|
||||||
|
getYesNoDict()
|
||||||
|
getAuditTypeDict()
|
||||||
|
})
|
||||||
|
|
||||||
|
// 暴露方法
|
||||||
|
defineExpose({
|
||||||
|
openDialog
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
</style>
|
||||||
|
|
||||||
471
src/views/stuwork/classleaveapply/form.vue
Normal file
471
src/views/stuwork/classleaveapply/form.vue
Normal file
@@ -0,0 +1,471 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
title="批量新增"
|
||||||
|
v-model="visible"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
draggable
|
||||||
|
width="900px">
|
||||||
|
<el-form
|
||||||
|
ref="dataFormRef"
|
||||||
|
:model="form"
|
||||||
|
:rules="dataRules"
|
||||||
|
label-width="120px"
|
||||||
|
v-loading="loading">
|
||||||
|
<el-row :gutter="24">
|
||||||
|
<el-col :span="12" class="mb20">
|
||||||
|
<el-form-item label="学年" prop="schoolYear">
|
||||||
|
<el-select
|
||||||
|
v-model="form.schoolYear"
|
||||||
|
placeholder="请选择学年"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
style="width: 100%">
|
||||||
|
<el-option
|
||||||
|
v-for="item in schoolYearList"
|
||||||
|
:key="item.year"
|
||||||
|
:label="item.year"
|
||||||
|
:value="item.year">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<el-col :span="12" class="mb20">
|
||||||
|
<el-form-item label="学期" prop="schoolTerm">
|
||||||
|
<el-select
|
||||||
|
v-model="form.schoolTerm"
|
||||||
|
placeholder="请选择学期"
|
||||||
|
clearable
|
||||||
|
style="width: 100%">
|
||||||
|
<el-option
|
||||||
|
v-for="item in schoolTermList"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<el-col :span="12" class="mb20">
|
||||||
|
<el-form-item label="班号" prop="classCode">
|
||||||
|
<el-select
|
||||||
|
v-model="form.classCode"
|
||||||
|
placeholder="请选择班号"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
style="width: 100%">
|
||||||
|
<el-option
|
||||||
|
v-for="item in classList"
|
||||||
|
:key="item.classCode"
|
||||||
|
:label="item.classNo"
|
||||||
|
:value="item.classCode">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<el-col :span="12" class="mb20">
|
||||||
|
<el-form-item label="请假类型" prop="leaveType">
|
||||||
|
<el-select
|
||||||
|
v-model="form.leaveType"
|
||||||
|
placeholder="请选择请假类型"
|
||||||
|
clearable
|
||||||
|
style="width: 100%">
|
||||||
|
<el-option
|
||||||
|
v-for="item in leaveTypeList"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<el-col :span="24" class="mb20">
|
||||||
|
<el-form-item label="请假时间" prop="leaveTime">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="form.leaveTime"
|
||||||
|
type="datetimerange"
|
||||||
|
range-separator="至"
|
||||||
|
start-placeholder="开始时间"
|
||||||
|
end-placeholder="结束时间"
|
||||||
|
format="YYYY-MM-DD HH:mm"
|
||||||
|
value-format="YYYY-MM-DD HH:mm:ss"
|
||||||
|
style="width: 100%" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<el-col :span="12" class="mb20">
|
||||||
|
<el-form-item label="是否住宿" prop="stayDorm">
|
||||||
|
<el-select
|
||||||
|
v-model="form.stayDorm"
|
||||||
|
placeholder="请选择是否住宿"
|
||||||
|
clearable
|
||||||
|
style="width: 100%">
|
||||||
|
<el-option
|
||||||
|
v-for="item in yesNoList"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<el-col :span="12" class="mb20">
|
||||||
|
<el-form-item label="时段请假" prop="isSegment">
|
||||||
|
<el-switch
|
||||||
|
v-model="form.isSegment"
|
||||||
|
active-value="1"
|
||||||
|
inactive-value="0"
|
||||||
|
active-text="是"
|
||||||
|
inactive-text="否"
|
||||||
|
@change="handleSegmentChange" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<template v-if="form.isSegment === '1'">
|
||||||
|
<el-col :span="12" class="mb20">
|
||||||
|
<el-form-item label="时段开始时间" prop="segmentStartTime">
|
||||||
|
<el-time-picker
|
||||||
|
v-model="form.segmentStartTime"
|
||||||
|
placeholder="请选择时段开始时间"
|
||||||
|
format="HH:mm"
|
||||||
|
value-format="HH:mm"
|
||||||
|
style="width: 100%" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<el-col :span="12" class="mb20">
|
||||||
|
<el-form-item label="时段结束时间" prop="segmentEndTime">
|
||||||
|
<el-time-picker
|
||||||
|
v-model="form.segmentEndTime"
|
||||||
|
placeholder="请选择时段结束时间"
|
||||||
|
format="HH:mm"
|
||||||
|
value-format="HH:mm"
|
||||||
|
style="width: 100%" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<el-col :span="12" class="mb20">
|
||||||
|
<el-form-item label="校门" prop="schoolDoor">
|
||||||
|
<el-select
|
||||||
|
v-model="form.schoolDoor"
|
||||||
|
placeholder="请选择校门"
|
||||||
|
clearable
|
||||||
|
style="width: 100%">
|
||||||
|
<el-option
|
||||||
|
v-for="item in schoolDoorList"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<el-col :span="24" class="mb20">
|
||||||
|
<el-form-item label="请假事由" prop="reason">
|
||||||
|
<el-input
|
||||||
|
v-model="form.reason"
|
||||||
|
type="textarea"
|
||||||
|
:rows="4"
|
||||||
|
placeholder="请输入请假事由" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click="visible = false">取 消</el-button>
|
||||||
|
<el-button type="primary" @click="onSubmit" :disabled="loading">确 认</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts" name="ClassLeaveApplyFormDialog">
|
||||||
|
import { ref, reactive, nextTick, onMounted, computed } from 'vue'
|
||||||
|
import { useMessage } from '/@/hooks/message'
|
||||||
|
import { addObj } from '/@/api/stuwork/classleaveapply'
|
||||||
|
import { queryAllSchoolYear } from '/@/api/basic/basicyear'
|
||||||
|
import { getDicts } from '/@/api/admin/dict'
|
||||||
|
import { getClassListByRole } from '/@/api/basic/basicclass'
|
||||||
|
|
||||||
|
const emit = defineEmits(['refresh'])
|
||||||
|
|
||||||
|
// 定义变量内容
|
||||||
|
const dataFormRef = ref()
|
||||||
|
const visible = ref(false)
|
||||||
|
const loading = ref(false)
|
||||||
|
const schoolYearList = ref<any[]>([])
|
||||||
|
const schoolTermList = ref<any[]>([])
|
||||||
|
const classList = ref<any[]>([])
|
||||||
|
const leaveTypeList = ref<any[]>([])
|
||||||
|
const yesNoList = ref<any[]>([])
|
||||||
|
const schoolDoorList = ref<any[]>([])
|
||||||
|
|
||||||
|
// 校门列表
|
||||||
|
const schoolDoorListData = [
|
||||||
|
{ label: '校门东', value: '0' },
|
||||||
|
{ label: '校门南', value: '1' },
|
||||||
|
{ label: '校门西', value: '2' }
|
||||||
|
]
|
||||||
|
|
||||||
|
// 提交表单数据
|
||||||
|
const form = reactive({
|
||||||
|
schoolYear: '',
|
||||||
|
schoolTerm: '',
|
||||||
|
classCode: '',
|
||||||
|
leaveTime: null as [string, string] | null,
|
||||||
|
leaveType: '',
|
||||||
|
reason: '',
|
||||||
|
stayDorm: '',
|
||||||
|
isSegment: '0',
|
||||||
|
segmentStartTime: '',
|
||||||
|
segmentEndTime: '',
|
||||||
|
schoolDoor: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
// 定义校验规则
|
||||||
|
const dataRules = {
|
||||||
|
schoolYear: [
|
||||||
|
{ required: true, message: '请选择学年', trigger: 'change' }
|
||||||
|
],
|
||||||
|
schoolTerm: [
|
||||||
|
{ required: true, message: '请选择学期', trigger: 'change' }
|
||||||
|
],
|
||||||
|
classCode: [
|
||||||
|
{ required: true, message: '请选择班号', trigger: 'change' }
|
||||||
|
],
|
||||||
|
leaveTime: [
|
||||||
|
{ required: true, message: '请选择请假时间', trigger: 'change' }
|
||||||
|
],
|
||||||
|
leaveType: [
|
||||||
|
{ required: true, message: '请选择请假类型', trigger: 'change' }
|
||||||
|
],
|
||||||
|
reason: [
|
||||||
|
{ required: true, message: '请输入请假事由', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
segmentStartTime: [
|
||||||
|
{
|
||||||
|
validator: (rule: any, value: any, callback: any) => {
|
||||||
|
if (form.isSegment === '1' && !value) {
|
||||||
|
callback(new Error('请选择时段开始时间'))
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
trigger: 'change'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
segmentEndTime: [
|
||||||
|
{
|
||||||
|
validator: (rule: any, value: any, callback: any) => {
|
||||||
|
if (form.isSegment === '1' && !value) {
|
||||||
|
callback(new Error('请选择时段结束时间'))
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
trigger: 'change'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 打开弹窗
|
||||||
|
const openDialog = () => {
|
||||||
|
visible.value = true
|
||||||
|
resetForm()
|
||||||
|
nextTick(() => {
|
||||||
|
dataFormRef.value?.resetFields()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置表单
|
||||||
|
const resetForm = () => {
|
||||||
|
form.schoolYear = ''
|
||||||
|
form.schoolTerm = ''
|
||||||
|
form.classCode = ''
|
||||||
|
form.leaveTime = null
|
||||||
|
form.leaveType = ''
|
||||||
|
form.reason = ''
|
||||||
|
form.stayDorm = ''
|
||||||
|
form.isSegment = '0'
|
||||||
|
form.segmentStartTime = ''
|
||||||
|
form.segmentEndTime = ''
|
||||||
|
form.schoolDoor = ''
|
||||||
|
}
|
||||||
|
|
||||||
|
// 时段请假变化
|
||||||
|
const handleSegmentChange = () => {
|
||||||
|
if (form.isSegment !== '1') {
|
||||||
|
form.segmentStartTime = ''
|
||||||
|
form.segmentEndTime = ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提交表单
|
||||||
|
const onSubmit = async () => {
|
||||||
|
if (!dataFormRef.value) return
|
||||||
|
|
||||||
|
await dataFormRef.value.validate(async (valid: boolean) => {
|
||||||
|
if (!valid) return
|
||||||
|
|
||||||
|
// 验证请假时间范围
|
||||||
|
if (!form.leaveTime || form.leaveTime.length !== 2) {
|
||||||
|
useMessage().error('请选择请假时间范围')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const [startTime, endTime] = form.leaveTime
|
||||||
|
const start = new Date(startTime)
|
||||||
|
const end = new Date(endTime)
|
||||||
|
if (end <= start) {
|
||||||
|
useMessage().error('请假结束时间必须大于开始时间')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证时段时间(如果开启了时段请假)
|
||||||
|
if (form.isSegment === '1') {
|
||||||
|
if (!form.segmentStartTime || !form.segmentEndTime) {
|
||||||
|
useMessage().error('请选择时段开始时间和结束时间')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 简单的时段验证(可以更复杂)
|
||||||
|
if (form.segmentEndTime <= form.segmentStartTime) {
|
||||||
|
useMessage().error('时段结束时间必须大于开始时间')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
// 构建时段JSON(如果开启了时段请假)
|
||||||
|
let segmentJson = ''
|
||||||
|
if (form.isSegment === '1' && form.segmentStartTime && form.segmentEndTime) {
|
||||||
|
segmentJson = JSON.stringify({
|
||||||
|
startTime: form.segmentStartTime,
|
||||||
|
endTime: form.segmentEndTime
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
await addObj({
|
||||||
|
schoolYear: form.schoolYear,
|
||||||
|
schoolTerm: form.schoolTerm,
|
||||||
|
classCode: form.classCode,
|
||||||
|
startTime: startTime,
|
||||||
|
endTime: endTime,
|
||||||
|
leaveType: form.leaveType,
|
||||||
|
reason: form.reason,
|
||||||
|
stayDorm: form.stayDorm,
|
||||||
|
isSegment: form.isSegment,
|
||||||
|
segmentJson: segmentJson,
|
||||||
|
schoolDoor: form.schoolDoor
|
||||||
|
})
|
||||||
|
useMessage().success('新增成功')
|
||||||
|
visible.value = false
|
||||||
|
emit('refresh')
|
||||||
|
} catch (err: any) {
|
||||||
|
useMessage().error(err.msg || '新增失败')
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取学年列表
|
||||||
|
const getSchoolYearListData = async () => {
|
||||||
|
try {
|
||||||
|
const res = await queryAllSchoolYear()
|
||||||
|
if (res.data) {
|
||||||
|
schoolYearList.value = Array.isArray(res.data) ? res.data : []
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取学年列表失败', 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) {
|
||||||
|
console.error('获取学期字典失败', err)
|
||||||
|
schoolTermList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取班级列表
|
||||||
|
const getClassListData = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getClassListByRole()
|
||||||
|
if (res.data) {
|
||||||
|
classList.value = Array.isArray(res.data) ? res.data : []
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取班级列表失败', err)
|
||||||
|
classList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取请假类型字典
|
||||||
|
const getLeaveTypeDict = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getDicts('leave_type')
|
||||||
|
if (res.data) {
|
||||||
|
leaveTypeList.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) {
|
||||||
|
console.error('获取请假类型字典失败', err)
|
||||||
|
leaveTypeList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取是否字典
|
||||||
|
const getYesNoDict = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getDicts('yes_no')
|
||||||
|
if (res.data) {
|
||||||
|
yesNoList.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) {
|
||||||
|
console.error('获取是否字典失败', err)
|
||||||
|
yesNoList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化
|
||||||
|
onMounted(() => {
|
||||||
|
schoolDoorList.value = schoolDoorListData
|
||||||
|
getSchoolYearListData()
|
||||||
|
getSchoolTermDict()
|
||||||
|
getClassListData()
|
||||||
|
getLeaveTypeDict()
|
||||||
|
getYesNoDict()
|
||||||
|
})
|
||||||
|
|
||||||
|
// 暴露方法
|
||||||
|
defineExpose({
|
||||||
|
openDialog
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
</style>
|
||||||
|
|
||||||
504
src/views/stuwork/classleaveapply/index.vue
Normal file
504
src/views/stuwork/classleaveapply/index.vue
Normal file
@@ -0,0 +1,504 @@
|
|||||||
|
<template>
|
||||||
|
<div class="layout-padding">
|
||||||
|
<div class="layout-padding-auto layout-padding-view">
|
||||||
|
<!-- 搜索表单 -->
|
||||||
|
<el-row v-show="showSearch">
|
||||||
|
<el-form :model="searchForm" ref="searchFormRef" :inline="true" @keyup.enter="handleSearch">
|
||||||
|
<el-form-item label="学年" prop="schoolYear">
|
||||||
|
<el-select
|
||||||
|
v-model="searchForm.schoolYear"
|
||||||
|
placeholder="请选择学年"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
style="width: 200px">
|
||||||
|
<el-option
|
||||||
|
v-for="item in schoolYearList"
|
||||||
|
:key="item.year"
|
||||||
|
:label="item.year"
|
||||||
|
:value="item.year">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="学期" prop="schoolTerm">
|
||||||
|
<el-select
|
||||||
|
v-model="searchForm.schoolTerm"
|
||||||
|
placeholder="请选择学期"
|
||||||
|
clearable
|
||||||
|
style="width: 200px">
|
||||||
|
<el-option
|
||||||
|
v-for="item in schoolTermList"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="学院" prop="deptCode">
|
||||||
|
<el-select
|
||||||
|
v-model="searchForm.deptCode"
|
||||||
|
placeholder="请选择学院"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
style="width: 200px">
|
||||||
|
<el-option
|
||||||
|
v-for="item in deptList"
|
||||||
|
:key="item.deptCode"
|
||||||
|
:label="item.deptName"
|
||||||
|
:value="item.deptCode">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="班号" prop="classCode">
|
||||||
|
<el-select
|
||||||
|
v-model="searchForm.classCode"
|
||||||
|
placeholder="请选择班号"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
style="width: 200px">
|
||||||
|
<el-option
|
||||||
|
v-for="item in classList"
|
||||||
|
:key="item.classCode"
|
||||||
|
:label="item.classNo"
|
||||||
|
:value="item.classCode">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="请假类型" prop="leaveType">
|
||||||
|
<el-select
|
||||||
|
v-model="searchForm.leaveType"
|
||||||
|
placeholder="请选择请假类型"
|
||||||
|
clearable
|
||||||
|
style="width: 200px">
|
||||||
|
<el-option
|
||||||
|
v-for="item in leaveTypeList"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="校门" prop="schoolDoor">
|
||||||
|
<el-select
|
||||||
|
v-model="searchForm.schoolDoor"
|
||||||
|
placeholder="请选择校门"
|
||||||
|
clearable
|
||||||
|
style="width: 200px">
|
||||||
|
<el-option
|
||||||
|
v-for="item in schoolDoorList"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" plain icon="Search" @click="handleSearch">查询</el-button>
|
||||||
|
<el-button icon="Refresh" @click="handleReset">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<!-- 操作按钮 -->
|
||||||
|
<el-row>
|
||||||
|
<div class="mb8" style="width: 100%">
|
||||||
|
<el-button
|
||||||
|
icon="Plus"
|
||||||
|
type="primary"
|
||||||
|
class="ml10"
|
||||||
|
@click="formDialogRef.openDialog()">
|
||||||
|
批量新增
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
icon="Delete"
|
||||||
|
type="danger"
|
||||||
|
class="ml10"
|
||||||
|
@click="handleDeleteByClass">
|
||||||
|
整班删除
|
||||||
|
</el-button>
|
||||||
|
<right-toolbar
|
||||||
|
v-model:showSearch="showSearch"
|
||||||
|
class="ml10 mr20"
|
||||||
|
style="float: right;"
|
||||||
|
@queryTable="getDataList">
|
||||||
|
</right-toolbar>
|
||||||
|
</div>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<!-- 表格 -->
|
||||||
|
<el-table
|
||||||
|
:data="state.dataList"
|
||||||
|
v-loading="state.loading"
|
||||||
|
border
|
||||||
|
:cell-style="tableStyle.cellStyle"
|
||||||
|
:header-cell-style="tableStyle.headerCellStyle">
|
||||||
|
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||||
|
<el-table-column prop="schoolYear" label="学年" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="schoolTerm" label="学期" show-overflow-tooltip align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ formatSchoolTerm(scope.row.schoolTerm) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="deptName" label="学院" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="classNo" label="班号" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="teacherRealName" label="班主任" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="num" label="人数" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="startTime" label="请假开始时间" show-overflow-tooltip align="center" width="180">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ scope.row.startTime ? formatDateTime(scope.row.startTime) : '-' }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="endTime" label="请假结束时间" show-overflow-tooltip align="center" width="180">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ scope.row.endTime ? formatDateTime(scope.row.endTime) : '-' }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="leaveType" label="请假类型" show-overflow-tooltip align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ formatLeaveType(scope.row.leaveType) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="reason" label="请假事由" show-overflow-tooltip align="center" min-width="150" />
|
||||||
|
<el-table-column prop="stayDorm" label="是否住宿" show-overflow-tooltip align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ formatYesNo(scope.row.stayDorm) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="isSegment" label="时段请假" show-overflow-tooltip align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ formatYesNo(scope.row.isSegment) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="segmentString" label="请假时段" show-overflow-tooltip align="center" min-width="150" />
|
||||||
|
<el-table-column prop="schoolDoor" label="请假校门" show-overflow-tooltip align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ formatSchoolDoor(scope.row.schoolDoor) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="deptAudit" label="基础部审核" show-overflow-tooltip align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ formatAuditType(scope.row.deptAudit) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="schoolAudit" label="学工处审批" show-overflow-tooltip align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ formatAuditType(scope.row.schoolAudit) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="rejectReason" label="驳回原因" show-overflow-tooltip align="center" min-width="150" />
|
||||||
|
<el-table-column label="操作" width="150" align="center" fixed="right">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button
|
||||||
|
icon="View"
|
||||||
|
text
|
||||||
|
type="primary"
|
||||||
|
@click="handleView(scope.row)">
|
||||||
|
查看
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
icon="Delete"
|
||||||
|
text
|
||||||
|
type="danger"
|
||||||
|
@click="handleDelete(scope.row)">
|
||||||
|
删除
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<!-- 分页 -->
|
||||||
|
<pagination
|
||||||
|
@size-change="sizeChangeHandle"
|
||||||
|
@current-change="currentChangeHandle"
|
||||||
|
v-bind="state.pagination" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 批量新增表单弹窗 -->
|
||||||
|
<form-dialog ref="formDialogRef" @refresh="getDataList" />
|
||||||
|
|
||||||
|
<!-- 查看详情弹窗 -->
|
||||||
|
<detail-dialog ref="detailDialogRef" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts" name="ClassLeaveApply">
|
||||||
|
import { reactive, ref, onMounted } from 'vue'
|
||||||
|
import { BasicTableProps, useTable } from "/@/hooks/table";
|
||||||
|
import { fetchList, delObj, deleteByClass } from "/@/api/stuwork/classleaveapply";
|
||||||
|
import { queryAllSchoolYear } from "/@/api/basic/basicyear";
|
||||||
|
import { getDicts } from "/@/api/admin/dict";
|
||||||
|
import { getDeptListByLevelTwo } from "/@/api/basic/basicdept";
|
||||||
|
import { getClassListByRole } from "/@/api/basic/basicclass";
|
||||||
|
import { useMessage, useMessageBox } from "/@/hooks/message";
|
||||||
|
import FormDialog from './form.vue'
|
||||||
|
import DetailDialog from './detail.vue'
|
||||||
|
|
||||||
|
// 定义变量内容
|
||||||
|
const searchFormRef = ref()
|
||||||
|
const showSearch = ref(true)
|
||||||
|
const schoolYearList = ref<any[]>([])
|
||||||
|
const schoolTermList = ref<any[]>([])
|
||||||
|
const deptList = ref<any[]>([])
|
||||||
|
const classList = ref<any[]>([])
|
||||||
|
const leaveTypeList = ref<any[]>([])
|
||||||
|
const yesNoList = ref<any[]>([])
|
||||||
|
const auditTypeList = ref<any[]>([])
|
||||||
|
const schoolDoorList = ref<any[]>([])
|
||||||
|
const formDialogRef = ref()
|
||||||
|
const detailDialogRef = ref()
|
||||||
|
|
||||||
|
// 校门列表
|
||||||
|
const schoolDoorListData = [
|
||||||
|
{ label: '校门东', value: '0' },
|
||||||
|
{ label: '校门南', value: '1' },
|
||||||
|
{ label: '校门西', value: '2' }
|
||||||
|
]
|
||||||
|
|
||||||
|
// 搜索表单
|
||||||
|
const searchForm = reactive({
|
||||||
|
schoolYear: '',
|
||||||
|
schoolTerm: '',
|
||||||
|
deptCode: '',
|
||||||
|
classCode: '',
|
||||||
|
leaveType: '',
|
||||||
|
schoolDoor: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
// 配置 useTable
|
||||||
|
const state: BasicTableProps = reactive<BasicTableProps>({
|
||||||
|
queryForm: searchForm,
|
||||||
|
pageList: fetchList,
|
||||||
|
props: {
|
||||||
|
item: 'records',
|
||||||
|
totalCount: 'total'
|
||||||
|
},
|
||||||
|
createdIsNeed: true
|
||||||
|
})
|
||||||
|
|
||||||
|
// table hook
|
||||||
|
const {
|
||||||
|
getDataList,
|
||||||
|
currentChangeHandle,
|
||||||
|
sizeChangeHandle,
|
||||||
|
tableStyle
|
||||||
|
} = useTable(state)
|
||||||
|
|
||||||
|
// 格式化学期
|
||||||
|
const formatSchoolTerm = (value: string | number) => {
|
||||||
|
if (value === null || value === undefined || value === '') {
|
||||||
|
return '-'
|
||||||
|
}
|
||||||
|
const dictItem = schoolTermList.value.find(item => item.value == value)
|
||||||
|
return dictItem ? dictItem.label : value
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化日期时间
|
||||||
|
const formatDateTime = (dateTime: string) => {
|
||||||
|
if (!dateTime) return '-'
|
||||||
|
if (dateTime.includes(' ')) {
|
||||||
|
return dateTime.split('.')[0]
|
||||||
|
}
|
||||||
|
return dateTime
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化请假类型
|
||||||
|
const formatLeaveType = (value: string) => {
|
||||||
|
if (!value) return '-'
|
||||||
|
const item = leaveTypeList.value.find((item: any) => item.value === value)
|
||||||
|
return item ? item.label : value
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化是否
|
||||||
|
const formatYesNo = (value: string) => {
|
||||||
|
if (value === null || value === undefined || value === '') {
|
||||||
|
return '-'
|
||||||
|
}
|
||||||
|
const dictItem = yesNoList.value.find(item => item.value == value)
|
||||||
|
return dictItem ? dictItem.label : value
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化校门
|
||||||
|
const formatSchoolDoor = (value: string) => {
|
||||||
|
if (!value) return '-'
|
||||||
|
const item = schoolDoorList.value.find((item: any) => item.value === value)
|
||||||
|
return item ? item.label : value
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化审核类型
|
||||||
|
const formatAuditType = (value: string) => {
|
||||||
|
if (value === null || value === undefined || value === '') {
|
||||||
|
return '-'
|
||||||
|
}
|
||||||
|
const dictItem = auditTypeList.value.find(item => item.value == value)
|
||||||
|
return dictItem ? dictItem.label : value
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询
|
||||||
|
const handleSearch = () => {
|
||||||
|
getDataList()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置
|
||||||
|
const handleReset = () => {
|
||||||
|
searchFormRef.value?.resetFields()
|
||||||
|
getDataList()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查看
|
||||||
|
const handleView = (row: any) => {
|
||||||
|
detailDialogRef.value.openDialog(row.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除
|
||||||
|
const handleDelete = async (row: any) => {
|
||||||
|
const { confirm } = useMessageBox()
|
||||||
|
try {
|
||||||
|
await confirm('确定要删除该批量请假记录吗?')
|
||||||
|
await delObj([row.id])
|
||||||
|
useMessage().success('删除成功')
|
||||||
|
getDataList()
|
||||||
|
} catch (err: any) {
|
||||||
|
if (err !== 'cancel') {
|
||||||
|
useMessage().error(err.msg || '删除失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 整班删除
|
||||||
|
const handleDeleteByClass = async () => {
|
||||||
|
const { confirm, prompt } = useMessageBox()
|
||||||
|
try {
|
||||||
|
const { value } = await prompt('请输入要删除的班级ID')
|
||||||
|
if (!value) {
|
||||||
|
useMessage().warning('请输入班级ID')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
await confirm('确定要删除该班级的所有请假记录吗?')
|
||||||
|
await deleteByClass(value)
|
||||||
|
useMessage().success('删除成功')
|
||||||
|
getDataList()
|
||||||
|
} catch (err: any) {
|
||||||
|
if (err !== 'cancel') {
|
||||||
|
useMessage().error(err.msg || '删除失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取学年列表
|
||||||
|
const getSchoolYearListData = async () => {
|
||||||
|
try {
|
||||||
|
const res = await queryAllSchoolYear()
|
||||||
|
if (res.data) {
|
||||||
|
schoolYearList.value = Array.isArray(res.data) ? res.data : []
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取学年列表失败', 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) {
|
||||||
|
console.error('获取学期字典失败', err)
|
||||||
|
schoolTermList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取系部列表
|
||||||
|
const getDeptListData = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getDeptListByLevelTwo()
|
||||||
|
if (res.data) {
|
||||||
|
deptList.value = Array.isArray(res.data) ? res.data : []
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取系部列表失败', err)
|
||||||
|
deptList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取班级列表
|
||||||
|
const getClassListData = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getClassListByRole()
|
||||||
|
if (res.data) {
|
||||||
|
classList.value = Array.isArray(res.data) ? res.data : []
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取班级列表失败', err)
|
||||||
|
classList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取请假类型字典
|
||||||
|
const getLeaveTypeDict = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getDicts('leave_type')
|
||||||
|
if (res.data) {
|
||||||
|
leaveTypeList.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) {
|
||||||
|
console.error('获取请假类型字典失败', err)
|
||||||
|
leaveTypeList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取是否字典
|
||||||
|
const getYesNoDict = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getDicts('yes_no')
|
||||||
|
if (res.data) {
|
||||||
|
yesNoList.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) {
|
||||||
|
console.error('获取是否字典失败', err)
|
||||||
|
yesNoList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取审核类型字典
|
||||||
|
const getAuditTypeDict = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getDicts('class_audit_type')
|
||||||
|
if (res.data) {
|
||||||
|
auditTypeList.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) {
|
||||||
|
console.error('获取审核类型字典失败', err)
|
||||||
|
auditTypeList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化
|
||||||
|
onMounted(() => {
|
||||||
|
schoolDoorList.value = schoolDoorListData
|
||||||
|
getSchoolYearListData()
|
||||||
|
getSchoolTermDict()
|
||||||
|
getDeptListData()
|
||||||
|
getClassListData()
|
||||||
|
getLeaveTypeDict()
|
||||||
|
getYesNoDict()
|
||||||
|
getAuditTypeDict()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
</style>
|
||||||
|
|
||||||
223
src/views/stuwork/classroombase/arrange.vue
Normal file
223
src/views/stuwork/classroombase/arrange.vue
Normal file
@@ -0,0 +1,223 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
title="教室安排"
|
||||||
|
v-model="visible"
|
||||||
|
:width="600"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
draggable>
|
||||||
|
<el-form
|
||||||
|
ref="dataFormRef"
|
||||||
|
:model="form"
|
||||||
|
:rules="dataRules"
|
||||||
|
label-width="120px"
|
||||||
|
v-loading="loading">
|
||||||
|
<el-row :gutter="24">
|
||||||
|
<el-col :span="24" class="mb20">
|
||||||
|
<el-form-item label="楼号" prop="buildingNo">
|
||||||
|
<el-select
|
||||||
|
v-model="form.buildingNo"
|
||||||
|
placeholder="请选择楼号"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
style="width: 100%">
|
||||||
|
<el-option
|
||||||
|
v-for="item in buildingList"
|
||||||
|
:key="item.buildingNo"
|
||||||
|
:label="item.buildingNo"
|
||||||
|
:value="item.buildingNo">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<el-col :span="24" class="mb20">
|
||||||
|
<el-form-item label="教室位置" prop="position">
|
||||||
|
<el-select
|
||||||
|
v-model="form.position"
|
||||||
|
placeholder="请选择教室位置"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
style="width: 100%">
|
||||||
|
<el-option
|
||||||
|
v-for="item in classroomList"
|
||||||
|
:key="item.position"
|
||||||
|
:label="item.position"
|
||||||
|
:value="item.position">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<el-col :span="24" class="mb20">
|
||||||
|
<el-form-item label="班级" prop="classCode">
|
||||||
|
<el-select
|
||||||
|
v-model="form.classCode"
|
||||||
|
placeholder="请选择班级"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
style="width: 100%">
|
||||||
|
<el-option
|
||||||
|
v-for="item in classList"
|
||||||
|
:key="item.classCode"
|
||||||
|
:label="item.classNo"
|
||||||
|
:value="item.classCode">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click="visible = false">取 消</el-button>
|
||||||
|
<el-button type="primary" @click="onSubmit" :disabled="loading">确 认</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts" name="ClassroomBaseArrangeDialog">
|
||||||
|
import { ref, reactive, nextTick, onMounted } from 'vue'
|
||||||
|
import { useMessage } from '/@/hooks/message'
|
||||||
|
import { editObj } from '/@/api/stuwork/classroombase'
|
||||||
|
import { queryAllClass } from '/@/api/basic/basicclass'
|
||||||
|
import { getClassRoomList, getBuildingList } from '/@/api/stuwork/teachclassroom'
|
||||||
|
|
||||||
|
const emit = defineEmits(['refresh'])
|
||||||
|
|
||||||
|
// 定义变量内容
|
||||||
|
const dataFormRef = ref()
|
||||||
|
const visible = ref(false)
|
||||||
|
const loading = ref(false)
|
||||||
|
const classList = ref<any[]>([])
|
||||||
|
const classroomList = ref<any[]>([])
|
||||||
|
const buildingList = ref<any[]>([])
|
||||||
|
|
||||||
|
// 提交表单数据
|
||||||
|
const form = reactive({
|
||||||
|
id: '',
|
||||||
|
buildingNo: '',
|
||||||
|
classCode: '',
|
||||||
|
position: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
// 定义校验规则
|
||||||
|
const dataRules = {
|
||||||
|
buildingNo: [
|
||||||
|
{ required: true, message: '请选择楼号', trigger: 'change' }
|
||||||
|
],
|
||||||
|
position: [
|
||||||
|
{ required: true, message: '请选择教室位置', trigger: 'change' }
|
||||||
|
],
|
||||||
|
classCode: [
|
||||||
|
{ required: true, message: '请选择班级', trigger: 'change' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 打开弹窗
|
||||||
|
const openDialog = async (row: any) => {
|
||||||
|
visible.value = true
|
||||||
|
resetForm()
|
||||||
|
|
||||||
|
// 填充现有数据
|
||||||
|
if (row) {
|
||||||
|
form.id = row.id || ''
|
||||||
|
form.buildingNo = row.buildingNo || ''
|
||||||
|
form.classCode = row.classCode || ''
|
||||||
|
form.position = row.position || ''
|
||||||
|
}
|
||||||
|
|
||||||
|
nextTick(() => {
|
||||||
|
dataFormRef.value?.clearValidate()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置表单
|
||||||
|
const resetForm = () => {
|
||||||
|
form.id = ''
|
||||||
|
form.buildingNo = ''
|
||||||
|
form.classCode = ''
|
||||||
|
form.position = ''
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提交表单
|
||||||
|
const onSubmit = async () => {
|
||||||
|
if (!dataFormRef.value) return
|
||||||
|
|
||||||
|
await dataFormRef.value.validate(async (valid: boolean) => {
|
||||||
|
if (!valid) return
|
||||||
|
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
await editObj({
|
||||||
|
id: form.id,
|
||||||
|
buildingNo: form.buildingNo,
|
||||||
|
classCode: form.classCode,
|
||||||
|
position: form.position
|
||||||
|
})
|
||||||
|
useMessage().success('教室安排成功')
|
||||||
|
visible.value = false
|
||||||
|
emit('refresh')
|
||||||
|
} catch (err: any) {
|
||||||
|
useMessage().error(err.msg || '教室安排失败')
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取班级列表
|
||||||
|
const getClassListData = async () => {
|
||||||
|
try {
|
||||||
|
const res = await queryAllClass()
|
||||||
|
if (res.data) {
|
||||||
|
classList.value = Array.isArray(res.data) ? res.data : []
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取班级列表失败', err)
|
||||||
|
classList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取教室列表
|
||||||
|
const getClassroomListData = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getClassRoomList()
|
||||||
|
if (res.data) {
|
||||||
|
classroomList.value = Array.isArray(res.data) ? res.data : []
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取教室列表失败', err)
|
||||||
|
classroomList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取楼号列表
|
||||||
|
const getBuildingListData = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getBuildingList()
|
||||||
|
if (res.data) {
|
||||||
|
buildingList.value = Array.isArray(res.data) ? res.data : []
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取楼号列表失败', err)
|
||||||
|
buildingList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化
|
||||||
|
onMounted(() => {
|
||||||
|
getClassListData()
|
||||||
|
getClassroomListData()
|
||||||
|
getBuildingListData()
|
||||||
|
})
|
||||||
|
|
||||||
|
// 暴露方法
|
||||||
|
defineExpose({
|
||||||
|
openDialog
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
</style>
|
||||||
|
|
||||||
413
src/views/stuwork/classroombase/index.vue
Normal file
413
src/views/stuwork/classroombase/index.vue
Normal file
@@ -0,0 +1,413 @@
|
|||||||
|
<template>
|
||||||
|
<div class="layout-padding">
|
||||||
|
<div class="layout-padding-auto layout-padding-view">
|
||||||
|
<!-- 搜索表单 -->
|
||||||
|
<el-row v-show="showSearch">
|
||||||
|
<el-form :model="searchForm" ref="searchFormRef" :inline="true" @keyup.enter="handleSearch">
|
||||||
|
<el-form-item label="学院" prop="deptName">
|
||||||
|
<el-select
|
||||||
|
v-model="searchForm.deptName"
|
||||||
|
placeholder="请选择学院"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
style="width: 200px">
|
||||||
|
<el-option
|
||||||
|
v-for="item in deptList"
|
||||||
|
:key="item.deptCode"
|
||||||
|
:label="item.deptName"
|
||||||
|
:value="item.deptName">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="班号" prop="classCode">
|
||||||
|
<el-select
|
||||||
|
v-model="searchForm.classCode"
|
||||||
|
placeholder="请选择班号"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
style="width: 200px">
|
||||||
|
<el-option
|
||||||
|
v-for="item in classList"
|
||||||
|
:key="item.classCode"
|
||||||
|
:label="item.classNo"
|
||||||
|
:value="item.classCode">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="班级状态" prop="classStatus">
|
||||||
|
<el-select
|
||||||
|
v-model="searchForm.classStatus"
|
||||||
|
placeholder="请选择班级状态"
|
||||||
|
clearable
|
||||||
|
style="width: 200px">
|
||||||
|
<el-option
|
||||||
|
v-for="item in classStatusList"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="教室位置" prop="position">
|
||||||
|
<el-input
|
||||||
|
v-model="searchForm.position"
|
||||||
|
placeholder="请输入教室位置"
|
||||||
|
clearable
|
||||||
|
style="width: 200px" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" plain icon="Search" @click="handleSearch">查询</el-button>
|
||||||
|
<el-button icon="Refresh" @click="handleReset">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<!-- 操作按钮 -->
|
||||||
|
<el-row>
|
||||||
|
<div class="mb8" style="width: 100%">
|
||||||
|
<el-button
|
||||||
|
icon="Download"
|
||||||
|
type="success"
|
||||||
|
class="ml10"
|
||||||
|
@click="handleExport">
|
||||||
|
导出
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
icon="Refresh"
|
||||||
|
type="primary"
|
||||||
|
class="ml10"
|
||||||
|
@click="handleSync">
|
||||||
|
同步教室安排
|
||||||
|
</el-button>
|
||||||
|
<right-toolbar
|
||||||
|
v-model:showSearch="showSearch"
|
||||||
|
class="ml10 mr20"
|
||||||
|
style="float: right;"
|
||||||
|
@queryTable="getDataList">
|
||||||
|
</right-toolbar>
|
||||||
|
</div>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<!-- 表格 -->
|
||||||
|
<el-table
|
||||||
|
:data="state.dataList"
|
||||||
|
v-loading="state.loading"
|
||||||
|
border
|
||||||
|
row-key="id"
|
||||||
|
:cell-style="tableStyle.cellStyle"
|
||||||
|
:header-cell-style="tableStyle.headerCellStyle">
|
||||||
|
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||||
|
<el-table-column prop="buildingNo" label="楼号" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="deptName" label="学院" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="classStatus" label="班级状态" show-overflow-tooltip align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ formatClassStatus(scope.row.classStatus) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="position" label="教室位置" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="stuNum" label="人数" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="teacherRealName" label="班主任" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="platformType" label="讲台类型" show-overflow-tooltip align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ formatDict(scope.row.platformType, platformTypeList) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="tyType" label="投影类型" show-overflow-tooltip align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ formatDict(scope.row.tyType, tyTypeList) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="tvType" label="电视机" show-overflow-tooltip align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ formatDict(scope.row.tvType, tvTypeList) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="chairCnt" label="方凳数量" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="tableCnt" label="课桌数量" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="password" label="锁密码" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column label="操作" width="120" align="center" fixed="right">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button
|
||||||
|
icon="Setting"
|
||||||
|
text
|
||||||
|
type="primary"
|
||||||
|
@click="handleArrange(scope.row)">
|
||||||
|
教室安排
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<!-- 分页 -->
|
||||||
|
<pagination
|
||||||
|
@size-change="sizeChangeHandle"
|
||||||
|
@current-change="currentChangeHandle"
|
||||||
|
v-bind="state.pagination" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 教室安排表单弹窗 -->
|
||||||
|
<arrange-dialog ref="arrangeDialogRef" @refresh="getDataList" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts" name="ClassroomBase">
|
||||||
|
import { reactive, ref, onMounted } from 'vue'
|
||||||
|
import { BasicTableProps, useTable } from "/@/hooks/table";
|
||||||
|
import { fetchList, exportData, syncClassroomArrangement } from "/@/api/stuwork/classroombase";
|
||||||
|
import { getDeptListByLevelTwo } from "/@/api/basic/basicdept";
|
||||||
|
import { queryAllClass } from "/@/api/basic/basicclass";
|
||||||
|
import { getDicts } from "/@/api/admin/dict";
|
||||||
|
import { useMessage, useMessageBox } from "/@/hooks/message";
|
||||||
|
import ArrangeDialog from './arrange.vue'
|
||||||
|
|
||||||
|
// 定义变量内容
|
||||||
|
const searchFormRef = ref()
|
||||||
|
const showSearch = ref(true)
|
||||||
|
const deptList = ref<any[]>([])
|
||||||
|
const classList = ref<any[]>([])
|
||||||
|
const classStatusList = ref<any[]>([])
|
||||||
|
const platformTypeList = ref<any[]>([])
|
||||||
|
const tyTypeList = ref<any[]>([])
|
||||||
|
const tvTypeList = ref<any[]>([])
|
||||||
|
const arrangeDialogRef = ref()
|
||||||
|
|
||||||
|
// 班级状态列表
|
||||||
|
const classStatusListData = [
|
||||||
|
{ label: '在校', value: '0' },
|
||||||
|
{ label: '顶岗', value: '1' },
|
||||||
|
{ label: '更岗', value: '2' },
|
||||||
|
{ label: '离校', value: '3' }
|
||||||
|
]
|
||||||
|
|
||||||
|
// 搜索表单
|
||||||
|
const searchForm = reactive({
|
||||||
|
deptName: '',
|
||||||
|
classCode: '',
|
||||||
|
classStatus: '',
|
||||||
|
position: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
// 配置 useTable
|
||||||
|
const state: BasicTableProps = reactive<BasicTableProps>({
|
||||||
|
queryForm: searchForm,
|
||||||
|
pageList: async (queryParams: any) => {
|
||||||
|
try {
|
||||||
|
const response = await fetchList(queryParams)
|
||||||
|
// 处理 ipage 数据结构
|
||||||
|
if (response && response.data) {
|
||||||
|
if (response.data.ipage) {
|
||||||
|
// 如果 ipage 是包含 records 和 total 的对象
|
||||||
|
if (Array.isArray(response.data.ipage)) {
|
||||||
|
// ipage 是数组
|
||||||
|
return {
|
||||||
|
...response,
|
||||||
|
data: {
|
||||||
|
records: response.data.ipage || [],
|
||||||
|
total: response.data.total || response.data.ipage.length || 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// ipage 是对象,包含 records 和 total
|
||||||
|
return {
|
||||||
|
...response,
|
||||||
|
data: {
|
||||||
|
records: response.data.ipage.records || [],
|
||||||
|
total: response.data.ipage.total || 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 如果没有 ipage,尝试直接使用 data
|
||||||
|
return {
|
||||||
|
...response,
|
||||||
|
data: {
|
||||||
|
records: response.data.records || response.data || [],
|
||||||
|
total: response.data.total || 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 如果 response 结构不对,返回空数据
|
||||||
|
return {
|
||||||
|
...response,
|
||||||
|
data: {
|
||||||
|
records: [],
|
||||||
|
total: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (err: any) {
|
||||||
|
// 确保即使出错也返回正确的数据结构
|
||||||
|
console.error('获取数据失败', err)
|
||||||
|
throw err
|
||||||
|
}
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
item: 'records',
|
||||||
|
totalCount: 'total'
|
||||||
|
},
|
||||||
|
createdIsNeed: true
|
||||||
|
})
|
||||||
|
|
||||||
|
// table hook
|
||||||
|
const {
|
||||||
|
getDataList,
|
||||||
|
currentChangeHandle,
|
||||||
|
sizeChangeHandle,
|
||||||
|
tableStyle
|
||||||
|
} = useTable(state)
|
||||||
|
|
||||||
|
// 格式化班级状态
|
||||||
|
const formatClassStatus = (value: string) => {
|
||||||
|
if (value === null || value === undefined || value === '') {
|
||||||
|
return '-'
|
||||||
|
}
|
||||||
|
const dictItem = classStatusList.value.find(item => item.value == value)
|
||||||
|
return dictItem ? dictItem.label : value
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化字典
|
||||||
|
const formatDict = (value: string, dictList: any[]) => {
|
||||||
|
if (!value) return '-'
|
||||||
|
const item = dictList.find((item: any) => item.value === value)
|
||||||
|
return item ? item.label : value
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询
|
||||||
|
const handleSearch = () => {
|
||||||
|
getDataList()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置
|
||||||
|
const handleReset = () => {
|
||||||
|
searchFormRef.value?.resetFields()
|
||||||
|
getDataList()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 导出
|
||||||
|
const handleExport = async () => {
|
||||||
|
try {
|
||||||
|
const res = await exportData(searchForm)
|
||||||
|
// 创建下载链接
|
||||||
|
const blob = new Blob([res.data], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' })
|
||||||
|
const url = window.URL.createObjectURL(blob)
|
||||||
|
const elink = document.createElement('a')
|
||||||
|
elink.style.display = 'none'
|
||||||
|
elink.href = url
|
||||||
|
elink.setAttribute('download', `教室安排及公物管理_${new Date().getTime()}.xlsx`)
|
||||||
|
document.body.appendChild(elink)
|
||||||
|
elink.click()
|
||||||
|
URL.revokeObjectURL(elink.href)
|
||||||
|
document.body.removeChild(elink)
|
||||||
|
useMessage().success('导出成功')
|
||||||
|
} catch (err: any) {
|
||||||
|
useMessage().error(err.msg || '导出失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 同步教室安排
|
||||||
|
const handleSync = async () => {
|
||||||
|
const { confirm } = useMessageBox()
|
||||||
|
try {
|
||||||
|
await confirm('确定要同步教室安排吗?')
|
||||||
|
await syncClassroomArrangement()
|
||||||
|
useMessage().success('同步成功')
|
||||||
|
getDataList()
|
||||||
|
} catch (err: any) {
|
||||||
|
if (err !== 'cancel') {
|
||||||
|
useMessage().error(err.msg || '同步失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 教室安排
|
||||||
|
const handleArrange = (row: any) => {
|
||||||
|
arrangeDialogRef.value?.openDialog(row)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取系部列表
|
||||||
|
const getDeptListData = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getDeptListByLevelTwo()
|
||||||
|
if (res.data) {
|
||||||
|
deptList.value = Array.isArray(res.data) ? res.data : []
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取系部列表失败', err)
|
||||||
|
deptList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取班级列表
|
||||||
|
const getClassListData = async () => {
|
||||||
|
try {
|
||||||
|
const res = await queryAllClass()
|
||||||
|
if (res.data) {
|
||||||
|
classList.value = Array.isArray(res.data) ? res.data : []
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取班级列表失败', err)
|
||||||
|
classList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取讲台类型字典
|
||||||
|
const getPlatformTypeDict = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getDicts('platform_type')
|
||||||
|
if (res.data) {
|
||||||
|
platformTypeList.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) {
|
||||||
|
console.error('获取讲台类型字典失败', err)
|
||||||
|
platformTypeList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取投影类型字典
|
||||||
|
const getTyTypeDict = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getDicts('ty_type')
|
||||||
|
if (res.data) {
|
||||||
|
tyTypeList.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) {
|
||||||
|
console.error('获取投影类型字典失败', err)
|
||||||
|
tyTypeList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取电视机类型字典
|
||||||
|
const getTvTypeDict = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getDicts('tv_type')
|
||||||
|
if (res.data) {
|
||||||
|
tvTypeList.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) {
|
||||||
|
console.error('获取电视机类型字典失败', err)
|
||||||
|
tvTypeList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化
|
||||||
|
onMounted(() => {
|
||||||
|
classStatusList.value = classStatusListData
|
||||||
|
getDeptListData()
|
||||||
|
getClassListData()
|
||||||
|
getPlatformTypeDict()
|
||||||
|
getTyTypeDict()
|
||||||
|
getTvTypeDict()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
</style>
|
||||||
|
|
||||||
199
src/views/stuwork/dormliveapply/form.vue
Normal file
199
src/views/stuwork/dormliveapply/form.vue
Normal file
@@ -0,0 +1,199 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
:title="form.id ? '编辑' : '新增'"
|
||||||
|
v-model="visible"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
draggable
|
||||||
|
width="600px">
|
||||||
|
<el-form
|
||||||
|
ref="dataFormRef"
|
||||||
|
:model="form"
|
||||||
|
:rules="dataRules"
|
||||||
|
label-width="100px"
|
||||||
|
v-loading="loading">
|
||||||
|
<el-form-item label="留宿类型" prop="liveType">
|
||||||
|
<el-select
|
||||||
|
v-model="form.liveType"
|
||||||
|
placeholder="请选择留宿类型"
|
||||||
|
clearable
|
||||||
|
style="width: 100%">
|
||||||
|
<el-option
|
||||||
|
v-for="item in liveTypeList"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="留宿日期" prop="liveDates">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="form.liveDates"
|
||||||
|
type="dates"
|
||||||
|
placeholder="选择留宿日期(可多选)"
|
||||||
|
format="YYYY-MM-DD"
|
||||||
|
value-format="YYYY-MM-DD"
|
||||||
|
style="width: 100%" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click="visible = false">取 消</el-button>
|
||||||
|
<el-button type="primary" @click="onSubmit" :disabled="loading">确 认</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts" name="DormLiveApplyFormDialog">
|
||||||
|
import { ref, reactive, nextTick, onMounted } from 'vue'
|
||||||
|
import { useMessage } from '/@/hooks/message'
|
||||||
|
import { addObj, editObj, getDetail } from '/@/api/stuwork/dormliveapply'
|
||||||
|
import { getDicts } from '/@/api/admin/dict'
|
||||||
|
|
||||||
|
const emit = defineEmits(['refresh'])
|
||||||
|
|
||||||
|
// 定义变量内容
|
||||||
|
const dataFormRef = ref()
|
||||||
|
const visible = ref(false)
|
||||||
|
const loading = ref(false)
|
||||||
|
const operType = ref('add') // add 或 edit
|
||||||
|
const liveTypeList = ref<any[]>([])
|
||||||
|
|
||||||
|
// 提交表单数据
|
||||||
|
const form = reactive({
|
||||||
|
id: '',
|
||||||
|
liveType: '',
|
||||||
|
liveDates: [] as string[]
|
||||||
|
})
|
||||||
|
|
||||||
|
// 定义校验规则
|
||||||
|
const dataRules = {
|
||||||
|
liveType: [
|
||||||
|
{ required: true, message: '请选择留宿类型', trigger: 'change' }
|
||||||
|
],
|
||||||
|
liveDates: [
|
||||||
|
{ required: true, message: '请选择留宿日期', trigger: 'change', type: 'array', min: 1 }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 打开弹窗
|
||||||
|
const openDialog = async (type: string = 'add', row?: any) => {
|
||||||
|
visible.value = true
|
||||||
|
operType.value = type
|
||||||
|
|
||||||
|
// 重置表单数据
|
||||||
|
nextTick(() => {
|
||||||
|
dataFormRef.value?.resetFields()
|
||||||
|
form.id = ''
|
||||||
|
form.liveType = ''
|
||||||
|
form.liveDates = []
|
||||||
|
|
||||||
|
// 编辑时填充数据
|
||||||
|
if (type === 'edit' && row) {
|
||||||
|
form.id = row.id
|
||||||
|
form.liveType = row.liveType || ''
|
||||||
|
|
||||||
|
// 获取详情以获取liveDates
|
||||||
|
if (row.id) {
|
||||||
|
getDetailData(row.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取详情
|
||||||
|
const getDetailData = async (id: string) => {
|
||||||
|
try {
|
||||||
|
loading.value = true
|
||||||
|
const res = await getDetail(id)
|
||||||
|
if (res.data && res.data.records && res.data.records.length > 0) {
|
||||||
|
const detail = res.data.records[0]
|
||||||
|
form.liveType = detail.liveType || ''
|
||||||
|
// 处理留宿日期,可能是字符串或数组
|
||||||
|
if (detail.liveDates) {
|
||||||
|
if (Array.isArray(detail.liveDates)) {
|
||||||
|
form.liveDates = detail.liveDates
|
||||||
|
} else if (typeof detail.liveDates === 'string') {
|
||||||
|
// 如果是逗号分隔的字符串,转换为数组
|
||||||
|
form.liveDates = detail.liveDates.split(',').filter((d: string) => d.trim())
|
||||||
|
}
|
||||||
|
} else if (detail.liveDate) {
|
||||||
|
// 如果只有单个日期,转换为数组
|
||||||
|
form.liveDates = [detail.liveDate]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取详情失败', err)
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提交表单
|
||||||
|
const onSubmit = async () => {
|
||||||
|
if (!dataFormRef.value) return
|
||||||
|
|
||||||
|
await dataFormRef.value.validate(async (valid: boolean) => {
|
||||||
|
if (!valid) return
|
||||||
|
|
||||||
|
if (!form.liveDates || form.liveDates.length === 0) {
|
||||||
|
useMessage().error('请至少选择一个留宿日期')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const submitData: any = {
|
||||||
|
liveType: form.liveType,
|
||||||
|
liveDates: form.liveDates
|
||||||
|
}
|
||||||
|
|
||||||
|
// 编辑时需要包含id
|
||||||
|
if (operType.value === 'edit') {
|
||||||
|
submitData.id = form.id
|
||||||
|
}
|
||||||
|
|
||||||
|
if (operType.value === 'add') {
|
||||||
|
await addObj(submitData)
|
||||||
|
useMessage().success('新增成功')
|
||||||
|
} else {
|
||||||
|
await editObj(submitData)
|
||||||
|
useMessage().success('编辑成功')
|
||||||
|
}
|
||||||
|
visible.value = false
|
||||||
|
emit('refresh')
|
||||||
|
} catch (err: any) {
|
||||||
|
useMessage().error(err.msg || (operType.value === 'add' ? '新增失败' : '编辑失败'))
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取留宿类型字典
|
||||||
|
const getLiveTypeDict = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getDicts('live_type')
|
||||||
|
if (res.data) {
|
||||||
|
liveTypeList.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) {
|
||||||
|
console.error('获取留宿类型字典失败', err)
|
||||||
|
liveTypeList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化
|
||||||
|
onMounted(() => {
|
||||||
|
getLiveTypeDict()
|
||||||
|
})
|
||||||
|
|
||||||
|
// 暴露方法给父组件
|
||||||
|
defineExpose({
|
||||||
|
openDialog
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
407
src/views/stuwork/dormliveapply/index.vue
Normal file
407
src/views/stuwork/dormliveapply/index.vue
Normal file
@@ -0,0 +1,407 @@
|
|||||||
|
<template>
|
||||||
|
<div class="layout-padding">
|
||||||
|
<div class="layout-padding-auto layout-padding-view">
|
||||||
|
<!-- 搜索表单 -->
|
||||||
|
<el-row v-show="showSearch">
|
||||||
|
<el-form :model="searchForm" ref="searchFormRef" :inline="true" @keyup.enter="handleSearch">
|
||||||
|
<el-form-item label="学年" prop="schoolYear">
|
||||||
|
<el-select
|
||||||
|
v-model="searchForm.schoolYear"
|
||||||
|
placeholder="请选择学年"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
style="width: 200px">
|
||||||
|
<el-option
|
||||||
|
v-for="item in schoolYearList"
|
||||||
|
:key="item.year"
|
||||||
|
:label="item.year"
|
||||||
|
:value="item.year">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="学期" prop="schoolTerm">
|
||||||
|
<el-select
|
||||||
|
v-model="searchForm.schoolTerm"
|
||||||
|
placeholder="请选择学期"
|
||||||
|
clearable
|
||||||
|
style="width: 200px">
|
||||||
|
<el-option
|
||||||
|
v-for="item in schoolTermList"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="楼号" prop="buildingNo">
|
||||||
|
<el-select
|
||||||
|
v-model="searchForm.buildingNo"
|
||||||
|
placeholder="请选择楼号"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
style="width: 200px">
|
||||||
|
<el-option
|
||||||
|
v-for="item in buildingList"
|
||||||
|
:key="item.buildingNo"
|
||||||
|
:label="item.buildingNo"
|
||||||
|
:value="item.buildingNo">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="开始时间" prop="startTime">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="searchForm.startTime"
|
||||||
|
type="date"
|
||||||
|
placeholder="选择开始时间"
|
||||||
|
format="YYYY-MM-DD"
|
||||||
|
value-format="YYYY-MM-DD"
|
||||||
|
clearable
|
||||||
|
style="width: 200px" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="结束时间" prop="endTime">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="searchForm.endTime"
|
||||||
|
type="date"
|
||||||
|
placeholder="选择结束时间"
|
||||||
|
format="YYYY-MM-DD"
|
||||||
|
value-format="YYYY-MM-DD"
|
||||||
|
clearable
|
||||||
|
style="width: 200px" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="班级" prop="classCode">
|
||||||
|
<el-select
|
||||||
|
v-model="searchForm.classCode"
|
||||||
|
placeholder="请选择班级"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
style="width: 200px">
|
||||||
|
<el-option
|
||||||
|
v-for="item in classList"
|
||||||
|
:key="item.classCode"
|
||||||
|
:label="item.classNo"
|
||||||
|
:value="item.classCode">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" plain icon="Search" @click="handleSearch">查询</el-button>
|
||||||
|
<el-button icon="Refresh" @click="handleReset">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<!-- 操作按钮 -->
|
||||||
|
<el-row>
|
||||||
|
<div class="mb8" style="width: 100%">
|
||||||
|
<el-button
|
||||||
|
icon="FolderAdd"
|
||||||
|
type="primary"
|
||||||
|
class="ml10"
|
||||||
|
@click="formDialogRef.openDialog()">
|
||||||
|
新 增
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
icon="Download"
|
||||||
|
type="success"
|
||||||
|
class="ml10"
|
||||||
|
@click="handleExport">
|
||||||
|
导 出
|
||||||
|
</el-button>
|
||||||
|
<right-toolbar
|
||||||
|
v-model:showSearch="showSearch"
|
||||||
|
class="ml10 mr20"
|
||||||
|
style="float: right;"
|
||||||
|
@queryTable="getDataList">
|
||||||
|
</right-toolbar>
|
||||||
|
</div>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<!-- 表格 -->
|
||||||
|
<el-table
|
||||||
|
:data="state.dataList"
|
||||||
|
v-loading="state.loading"
|
||||||
|
border
|
||||||
|
:cell-style="tableStyle.cellStyle"
|
||||||
|
:header-cell-style="tableStyle.headerCellStyle">
|
||||||
|
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||||
|
<el-table-column prop="schoolYear" label="学年" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="schoolTerm" label="学期" show-overflow-tooltip align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ formatSchoolTerm(scope.row.schoolTerm) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="deptName" label="学院" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="classNo" label="班级" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="realName" label="姓名" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="roomNo" label="宿舍号" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="liveType" label="留宿类型" show-overflow-tooltip align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ formatLiveType(scope.row.liveType) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="liveDate" label="留宿日期" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="auditStatus" label="审核状态" show-overflow-tooltip align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ formatAuditStatus(scope.row.auditStatus) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" width="150" align="center" fixed="right">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button
|
||||||
|
icon="Edit"
|
||||||
|
text
|
||||||
|
type="primary"
|
||||||
|
@click="handleEdit(scope.row)">
|
||||||
|
编辑
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
icon="Delete"
|
||||||
|
text
|
||||||
|
type="danger"
|
||||||
|
@click="handleDelete(scope.row)">
|
||||||
|
删除
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<!-- 分页 -->
|
||||||
|
<pagination
|
||||||
|
@size-change="sizeChangeHandle"
|
||||||
|
@current-change="currentChangeHandle"
|
||||||
|
v-bind="state.pagination" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 新增/编辑表单弹窗 -->
|
||||||
|
<form-dialog ref="formDialogRef" @refresh="getDataList" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts" name="DormLiveApply">
|
||||||
|
import { reactive, ref, onMounted } from 'vue'
|
||||||
|
import { BasicTableProps, useTable } from "/@/hooks/table";
|
||||||
|
import { fetchList, delObj, exportData } from "/@/api/stuwork/dormliveapply";
|
||||||
|
import { queryAllSchoolYear } from "/@/api/basic/basicyear";
|
||||||
|
import { getDicts } from "/@/api/admin/dict";
|
||||||
|
import { getBuildingList } from "/@/api/stuwork/dormbuilding";
|
||||||
|
import { getClassListByRole } from "/@/api/basic/basicclass";
|
||||||
|
import { useMessage, useMessageBox } from "/@/hooks/message";
|
||||||
|
import FormDialog from './form.vue'
|
||||||
|
|
||||||
|
// 定义变量内容
|
||||||
|
const searchFormRef = ref()
|
||||||
|
const showSearch = ref(true)
|
||||||
|
const schoolYearList = ref<any[]>([])
|
||||||
|
const schoolTermList = ref<any[]>([])
|
||||||
|
const buildingList = ref<any[]>([])
|
||||||
|
const classList = ref<any[]>([])
|
||||||
|
const liveTypeList = ref<any[]>([])
|
||||||
|
const auditStatusList = ref<any[]>([])
|
||||||
|
const formDialogRef = ref()
|
||||||
|
|
||||||
|
// 搜索表单
|
||||||
|
const searchForm = reactive({
|
||||||
|
schoolYear: '',
|
||||||
|
schoolTerm: '',
|
||||||
|
buildingNo: '',
|
||||||
|
startTime: '',
|
||||||
|
endTime: '',
|
||||||
|
classCode: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
// 配置 useTable
|
||||||
|
const state: BasicTableProps = reactive<BasicTableProps>({
|
||||||
|
queryForm: searchForm,
|
||||||
|
pageList: fetchList,
|
||||||
|
props: {
|
||||||
|
item: 'records',
|
||||||
|
totalCount: 'total'
|
||||||
|
},
|
||||||
|
createdIsNeed: true
|
||||||
|
})
|
||||||
|
|
||||||
|
// table hook
|
||||||
|
const {
|
||||||
|
getDataList,
|
||||||
|
currentChangeHandle,
|
||||||
|
sizeChangeHandle,
|
||||||
|
tableStyle
|
||||||
|
} = useTable(state)
|
||||||
|
|
||||||
|
// 格式化学期
|
||||||
|
const formatSchoolTerm = (value: string | number) => {
|
||||||
|
if (value === null || value === undefined || value === '') {
|
||||||
|
return '-'
|
||||||
|
}
|
||||||
|
const dictItem = schoolTermList.value.find(item => item.value == value)
|
||||||
|
return dictItem ? dictItem.label : value
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化留宿类型
|
||||||
|
const formatLiveType = (value: string) => {
|
||||||
|
if (!value) return '-'
|
||||||
|
const item = liveTypeList.value.find((item: any) => item.value === value)
|
||||||
|
return item ? item.label : value
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化审核状态
|
||||||
|
const formatAuditStatus = (value: string) => {
|
||||||
|
if (!value) return '-'
|
||||||
|
const item = auditStatusList.value.find((item: any) => item.value === value)
|
||||||
|
return item ? item.label : value
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询
|
||||||
|
const handleSearch = () => {
|
||||||
|
getDataList()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置
|
||||||
|
const handleReset = () => {
|
||||||
|
searchFormRef.value?.resetFields()
|
||||||
|
searchForm.schoolYear = ''
|
||||||
|
searchForm.schoolTerm = ''
|
||||||
|
searchForm.buildingNo = ''
|
||||||
|
searchForm.startTime = ''
|
||||||
|
searchForm.endTime = ''
|
||||||
|
searchForm.classCode = ''
|
||||||
|
getDataList()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 编辑
|
||||||
|
const handleEdit = (row: any) => {
|
||||||
|
formDialogRef.value?.openDialog('edit', row)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除
|
||||||
|
const handleDelete = async (row: any) => {
|
||||||
|
try {
|
||||||
|
await useMessageBox().confirm('确定要删除这条记录吗?')
|
||||||
|
await delObj([row.id])
|
||||||
|
useMessage().success('删除成功')
|
||||||
|
getDataList()
|
||||||
|
} catch (err: any) {
|
||||||
|
if (err !== 'cancel') {
|
||||||
|
useMessage().error(err.msg || '删除失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 导出
|
||||||
|
const handleExport = async () => {
|
||||||
|
try {
|
||||||
|
const res = await exportData(searchForm)
|
||||||
|
// 处理返回的文件流
|
||||||
|
const blob = new Blob([res.data])
|
||||||
|
const elink = document.createElement('a')
|
||||||
|
elink.download = '留宿申请.xlsx'
|
||||||
|
elink.style.display = 'none'
|
||||||
|
elink.href = URL.createObjectURL(blob)
|
||||||
|
document.body.appendChild(elink)
|
||||||
|
elink.click()
|
||||||
|
URL.revokeObjectURL(elink.href)
|
||||||
|
document.body.removeChild(elink)
|
||||||
|
useMessage().success('导出成功')
|
||||||
|
} catch (err: any) {
|
||||||
|
useMessage().error(err.msg || '导出失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取学年列表
|
||||||
|
const getSchoolYearList = async () => {
|
||||||
|
try {
|
||||||
|
const res = await queryAllSchoolYear()
|
||||||
|
if (res.data) {
|
||||||
|
schoolYearList.value = Array.isArray(res.data) ? res.data : []
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取学年列表失败', 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) {
|
||||||
|
console.error('获取学期字典失败', err)
|
||||||
|
schoolTermList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取楼号列表
|
||||||
|
const getBuildingListData = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getBuildingList()
|
||||||
|
if (res.data) {
|
||||||
|
buildingList.value = Array.isArray(res.data) ? res.data : []
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取楼号列表失败', err)
|
||||||
|
buildingList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取班级列表
|
||||||
|
const getClassListData = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getClassListByRole()
|
||||||
|
if (res.data) {
|
||||||
|
classList.value = Array.isArray(res.data) ? res.data : []
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取班级列表失败', err)
|
||||||
|
classList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取留宿类型字典
|
||||||
|
const getLiveTypeDict = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getDicts('live_type')
|
||||||
|
if (res.data) {
|
||||||
|
liveTypeList.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) {
|
||||||
|
console.error('获取留宿类型字典失败', err)
|
||||||
|
liveTypeList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取审核状态字典
|
||||||
|
const getAuditStatusDict = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getDicts('dorm_live_audit_status')
|
||||||
|
if (res.data) {
|
||||||
|
auditStatusList.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) {
|
||||||
|
console.error('获取审核状态字典失败', err)
|
||||||
|
auditStatusList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化
|
||||||
|
onMounted(() => {
|
||||||
|
getSchoolYearList()
|
||||||
|
getSchoolTermDict()
|
||||||
|
getBuildingListData()
|
||||||
|
getClassListData()
|
||||||
|
getLiveTypeDict()
|
||||||
|
getAuditStatusDict()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
516
src/views/stuwork/stuinnerleaveapplygroup/form.vue
Normal file
516
src/views/stuwork/stuinnerleaveapplygroup/form.vue
Normal file
@@ -0,0 +1,516 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
:title="form.id ? '编辑' : '新增'"
|
||||||
|
v-model="visible"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
draggable
|
||||||
|
width="800px">
|
||||||
|
<el-form
|
||||||
|
ref="dataFormRef"
|
||||||
|
:model="form"
|
||||||
|
:rules="dataRules"
|
||||||
|
label-width="120px"
|
||||||
|
v-loading="loading">
|
||||||
|
<el-row :gutter="24">
|
||||||
|
<el-col :span="12" class="mb20">
|
||||||
|
<el-form-item label="开始时间" prop="startTime">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="form.startTime"
|
||||||
|
type="datetime"
|
||||||
|
placeholder="选择开始时间"
|
||||||
|
format="YYYY-MM-DD HH:mm:ss"
|
||||||
|
value-format="YYYY-MM-DD HH:mm:ss"
|
||||||
|
style="width: 100%" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<el-col :span="12" class="mb20">
|
||||||
|
<el-form-item label="结束时间" prop="endTime">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="form.endTime"
|
||||||
|
type="datetime"
|
||||||
|
placeholder="选择结束时间"
|
||||||
|
format="YYYY-MM-DD HH:mm:ss"
|
||||||
|
value-format="YYYY-MM-DD HH:mm:ss"
|
||||||
|
style="width: 100%" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<el-col :span="12" class="mb20">
|
||||||
|
<el-form-item label="班级" prop="classCode">
|
||||||
|
<el-select
|
||||||
|
v-model="form.classCode"
|
||||||
|
placeholder="请选择班级"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
style="width: 100%"
|
||||||
|
@change="handleClassChange">
|
||||||
|
<el-option
|
||||||
|
v-for="item in classList"
|
||||||
|
:key="item.classCode"
|
||||||
|
:label="item.classNo"
|
||||||
|
:value="item.classCode">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<el-col :span="12" class="mb20">
|
||||||
|
<el-form-item label="选择学生" prop="selectedStudents">
|
||||||
|
<el-input
|
||||||
|
v-model="selectedStudentsText"
|
||||||
|
placeholder="请选择学生"
|
||||||
|
readonly
|
||||||
|
style="width: 100%"
|
||||||
|
@click="openStudentDialog">
|
||||||
|
<template #suffix>
|
||||||
|
<el-button
|
||||||
|
icon="Search"
|
||||||
|
circle
|
||||||
|
@click.stop="openStudentDialog" />
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<el-col :span="24" class="mb20">
|
||||||
|
<el-form-item label="请假事由" prop="reason">
|
||||||
|
<el-input
|
||||||
|
v-model="form.reason"
|
||||||
|
type="textarea"
|
||||||
|
:rows="4"
|
||||||
|
placeholder="请输入请假事由" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click="visible = false">取 消</el-button>
|
||||||
|
<el-button type="primary" @click="onSubmit" :disabled="loading">确 认</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
|
<!-- 学生选择弹窗 -->
|
||||||
|
<el-dialog
|
||||||
|
title="选择学生"
|
||||||
|
v-model="studentDialogVisible"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
draggable
|
||||||
|
width="900px">
|
||||||
|
<!-- 搜索表单 -->
|
||||||
|
<el-form :model="studentSearchForm" :inline="true" @keyup.enter="handleStudentSearch">
|
||||||
|
<el-form-item label="班号" prop="classNo">
|
||||||
|
<el-input
|
||||||
|
v-model="studentSearchForm.classNo"
|
||||||
|
placeholder="请输入班号"
|
||||||
|
clearable
|
||||||
|
style="width: 200px" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="学号" prop="stuNo">
|
||||||
|
<el-input
|
||||||
|
v-model="studentSearchForm.stuNo"
|
||||||
|
placeholder="请输入学号"
|
||||||
|
clearable
|
||||||
|
style="width: 200px" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="姓名" prop="realName">
|
||||||
|
<el-input
|
||||||
|
v-model="studentSearchForm.realName"
|
||||||
|
placeholder="请输入姓名"
|
||||||
|
clearable
|
||||||
|
style="width: 200px" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" plain icon="Search" @click="handleStudentSearch">查询</el-button>
|
||||||
|
<el-button icon="Refresh" @click="handleStudentReset">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
|
||||||
|
<!-- 学生表格 -->
|
||||||
|
<el-table
|
||||||
|
ref="studentTableRef"
|
||||||
|
:data="studentTableData"
|
||||||
|
v-loading="studentTableLoading"
|
||||||
|
border
|
||||||
|
@selection-change="handleStudentSelectionChange"
|
||||||
|
style="margin-top: 20px; max-height: 400px; overflow-y: auto;">
|
||||||
|
<el-table-column type="selection" width="55" align="center" />
|
||||||
|
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||||
|
<el-table-column prop="classNo" label="班号" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="stuNo" label="学号" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="realName" label="姓名" show-overflow-tooltip align="center" />
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<!-- 分页 -->
|
||||||
|
<pagination
|
||||||
|
@size-change="studentSizeChangeHandle"
|
||||||
|
@current-change="studentCurrentChangeHandle"
|
||||||
|
v-bind="studentPagination"
|
||||||
|
style="margin-top: 20px" />
|
||||||
|
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click="studentDialogVisible = false">取 消</el-button>
|
||||||
|
<el-button type="primary" @click="confirmStudentSelection">确 认</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts" name="StuInnerLeaveApplyGroupFormDialog">
|
||||||
|
import { ref, reactive, nextTick, onMounted, computed } from 'vue'
|
||||||
|
import { useMessage } from '/@/hooks/message'
|
||||||
|
import { addObj, editObj, getDetail } from '/@/api/stuwork/stuinnerleaveapplygroup'
|
||||||
|
import { getClassListByRole } from '/@/api/basic/basicclass'
|
||||||
|
import { fetchList as getStudentList } from '/@/api/basic/basicstudent'
|
||||||
|
|
||||||
|
const emit = defineEmits(['refresh'])
|
||||||
|
|
||||||
|
// 定义变量内容
|
||||||
|
const dataFormRef = ref()
|
||||||
|
const studentTableRef = ref()
|
||||||
|
const visible = ref(false)
|
||||||
|
const loading = ref(false)
|
||||||
|
const operType = ref('add') // add 或 edit
|
||||||
|
const classList = ref<any[]>([])
|
||||||
|
|
||||||
|
// 学生选择弹窗相关
|
||||||
|
const studentDialogVisible = ref(false)
|
||||||
|
const studentTableLoading = ref(false)
|
||||||
|
const studentTableData = ref<any[]>([])
|
||||||
|
const selectedStudentRows = ref<any[]>([]) // 表格中选中的行
|
||||||
|
const studentSearchForm = reactive({
|
||||||
|
classNo: '',
|
||||||
|
stuNo: '',
|
||||||
|
realName: ''
|
||||||
|
})
|
||||||
|
const studentPagination = reactive({
|
||||||
|
total: 0,
|
||||||
|
pageSize: 10,
|
||||||
|
currentPage: 1
|
||||||
|
})
|
||||||
|
|
||||||
|
// 已选学生文本显示
|
||||||
|
const selectedStudentsText = computed(() => {
|
||||||
|
if (!form.selectedStudents || form.selectedStudents.length === 0) {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
return `已选择 ${form.selectedStudents.length} 名学生`
|
||||||
|
})
|
||||||
|
|
||||||
|
// 提交表单数据
|
||||||
|
const form = reactive({
|
||||||
|
id: '',
|
||||||
|
startTime: '',
|
||||||
|
endTime: '',
|
||||||
|
classCode: '',
|
||||||
|
selectedStudents: [] as string[], // 选中的学号数组
|
||||||
|
reason: '',
|
||||||
|
stuList: [] as any[]
|
||||||
|
})
|
||||||
|
|
||||||
|
// 定义校验规则
|
||||||
|
const dataRules = {
|
||||||
|
startTime: [
|
||||||
|
{ required: true, message: '请选择开始时间', trigger: 'change' }
|
||||||
|
],
|
||||||
|
endTime: [
|
||||||
|
{ required: true, message: '请选择结束时间', trigger: 'change' }
|
||||||
|
],
|
||||||
|
classCode: [
|
||||||
|
{ required: true, message: '请选择班级', trigger: 'change' }
|
||||||
|
],
|
||||||
|
selectedStudents: [
|
||||||
|
{ required: true, message: '请至少选择一个学生', trigger: 'change', type: 'array', min: 1 }
|
||||||
|
],
|
||||||
|
reason: [
|
||||||
|
{ required: true, message: '请输入请假事由', trigger: 'blur' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 打开学生选择弹窗
|
||||||
|
const openStudentDialog = () => {
|
||||||
|
if (!form.classCode) {
|
||||||
|
useMessage().warning('请先选择班级')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
studentDialogVisible.value = true
|
||||||
|
// 重置搜索表单,但保留班级代码
|
||||||
|
studentSearchForm.classNo = ''
|
||||||
|
studentSearchForm.stuNo = ''
|
||||||
|
studentSearchForm.realName = ''
|
||||||
|
// 加载学生列表
|
||||||
|
loadStudentTableData()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载学生表格数据
|
||||||
|
const loadStudentTableData = async () => {
|
||||||
|
studentTableLoading.value = true
|
||||||
|
try {
|
||||||
|
const params: any = {
|
||||||
|
current: studentPagination.currentPage,
|
||||||
|
size: studentPagination.pageSize,
|
||||||
|
classCode: form.classCode
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加搜索条件
|
||||||
|
if (studentSearchForm.classNo) {
|
||||||
|
params.classNo = studentSearchForm.classNo
|
||||||
|
}
|
||||||
|
if (studentSearchForm.stuNo) {
|
||||||
|
params.stuNo = studentSearchForm.stuNo
|
||||||
|
}
|
||||||
|
if (studentSearchForm.realName) {
|
||||||
|
params.realName = studentSearchForm.realName
|
||||||
|
}
|
||||||
|
|
||||||
|
const res = await getStudentList(params)
|
||||||
|
if (res.data) {
|
||||||
|
studentTableData.value = res.data.records || []
|
||||||
|
studentPagination.total = res.data.total || 0
|
||||||
|
|
||||||
|
// 如果有已选中的学生,自动勾选
|
||||||
|
nextTick(() => {
|
||||||
|
if (form.selectedStudents && form.selectedStudents.length > 0 && studentTableRef.value) {
|
||||||
|
studentTableData.value.forEach((row: any) => {
|
||||||
|
if (form.selectedStudents.includes(row.stuNo)) {
|
||||||
|
studentTableRef.value.toggleRowSelection(row, true)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
studentTableData.value = []
|
||||||
|
studentPagination.total = 0
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取学生列表失败', err)
|
||||||
|
studentTableData.value = []
|
||||||
|
studentPagination.total = 0
|
||||||
|
} finally {
|
||||||
|
studentTableLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 学生搜索
|
||||||
|
const handleStudentSearch = () => {
|
||||||
|
studentPagination.currentPage = 1
|
||||||
|
loadStudentTableData()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 学生搜索重置
|
||||||
|
const handleStudentReset = () => {
|
||||||
|
studentSearchForm.classNo = ''
|
||||||
|
studentSearchForm.stuNo = ''
|
||||||
|
studentSearchForm.realName = ''
|
||||||
|
studentPagination.currentPage = 1
|
||||||
|
loadStudentTableData()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 学生表格选择变化
|
||||||
|
const handleStudentSelectionChange = (selection: any[]) => {
|
||||||
|
selectedStudentRows.value = selection
|
||||||
|
}
|
||||||
|
|
||||||
|
// 学生分页大小变化
|
||||||
|
const studentSizeChangeHandle = (size: number) => {
|
||||||
|
studentPagination.pageSize = size
|
||||||
|
studentPagination.currentPage = 1
|
||||||
|
loadStudentTableData()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 学生分页页码变化
|
||||||
|
const studentCurrentChangeHandle = (page: number) => {
|
||||||
|
studentPagination.currentPage = page
|
||||||
|
loadStudentTableData()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确认学生选择
|
||||||
|
const confirmStudentSelection = () => {
|
||||||
|
if (selectedStudentRows.value.length === 0) {
|
||||||
|
useMessage().warning('请至少选择一个学生')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新选中的学号数组
|
||||||
|
form.selectedStudents = selectedStudentRows.value.map((row: any) => row.stuNo)
|
||||||
|
studentDialogVisible.value = false
|
||||||
|
useMessage().success(`已选择 ${form.selectedStudents.length} 名学生`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 打开弹窗
|
||||||
|
const openDialog = async (type: string = 'add', row?: any) => {
|
||||||
|
visible.value = true
|
||||||
|
operType.value = type
|
||||||
|
|
||||||
|
// 重置表单数据
|
||||||
|
nextTick(() => {
|
||||||
|
dataFormRef.value?.resetFields()
|
||||||
|
form.id = ''
|
||||||
|
form.startTime = ''
|
||||||
|
form.endTime = ''
|
||||||
|
form.classCode = ''
|
||||||
|
form.selectedStudents = []
|
||||||
|
form.reason = ''
|
||||||
|
form.stuList = []
|
||||||
|
selectedStudentRows.value = []
|
||||||
|
|
||||||
|
// 编辑时填充数据
|
||||||
|
if (type === 'edit' && row) {
|
||||||
|
form.id = row.id
|
||||||
|
form.startTime = row.startTime || ''
|
||||||
|
form.endTime = row.endTime || ''
|
||||||
|
form.reason = row.reason || ''
|
||||||
|
|
||||||
|
// 获取详情以获取stuList和classCode
|
||||||
|
if (row.id) {
|
||||||
|
getDetailData(row.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取详情
|
||||||
|
const getDetailData = async (id: string) => {
|
||||||
|
try {
|
||||||
|
loading.value = true
|
||||||
|
const res = await getDetail(id)
|
||||||
|
if (res.data && Array.isArray(res.data) && res.data.length > 0) {
|
||||||
|
const detail = res.data[0]
|
||||||
|
form.stuList = detail.stuList || []
|
||||||
|
|
||||||
|
// 如果有学生列表,提取学号和班级代码
|
||||||
|
if (form.stuList.length > 0) {
|
||||||
|
// 获取第一个学生的班级代码
|
||||||
|
const firstStudent = form.stuList[0]
|
||||||
|
if (firstStudent.classCode) {
|
||||||
|
form.classCode = firstStudent.classCode
|
||||||
|
// 设置选中的学生
|
||||||
|
form.selectedStudents = form.stuList.map((stu: any) => stu.stuNo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取详情失败', err)
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提交表单
|
||||||
|
const onSubmit = async () => {
|
||||||
|
if (!dataFormRef.value) return
|
||||||
|
|
||||||
|
await dataFormRef.value.validate(async (valid: boolean) => {
|
||||||
|
if (!valid) return
|
||||||
|
|
||||||
|
// 验证结束时间必须大于开始时间
|
||||||
|
if (form.startTime && form.endTime) {
|
||||||
|
const start = new Date(form.startTime)
|
||||||
|
const end = new Date(form.endTime)
|
||||||
|
if (end <= start) {
|
||||||
|
useMessage().error('结束时间必须大于开始时间')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建stuList数组
|
||||||
|
const buildStuList = async () => {
|
||||||
|
if (!form.selectedStudents || form.selectedStudents.length === 0) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
// 需要重新获取学生信息来构建stuList
|
||||||
|
try {
|
||||||
|
const params: any = {
|
||||||
|
current: 1,
|
||||||
|
size: 1000,
|
||||||
|
classCode: form.classCode
|
||||||
|
}
|
||||||
|
const res = await getStudentList(params)
|
||||||
|
const allStudents = res.data?.records || []
|
||||||
|
|
||||||
|
return form.selectedStudents.map((stuNo: string) => {
|
||||||
|
const student = allStudents.find((s: any) => s.stuNo === stuNo)
|
||||||
|
if (student) {
|
||||||
|
return {
|
||||||
|
stuNo: student.stuNo,
|
||||||
|
realName: student.realName,
|
||||||
|
classCode: form.classCode,
|
||||||
|
status: '0', // 审核状态,默认0
|
||||||
|
inOut: student.inOut || '1' // 是否允许离校,默认1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}).filter((item: any) => item !== null)
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取学生信息失败', err)
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const stuList = await buildStuList()
|
||||||
|
|
||||||
|
if (stuList.length === 0) {
|
||||||
|
useMessage().error('请至少选择一个学生')
|
||||||
|
loading.value = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const submitData: any = {
|
||||||
|
startTime: form.startTime,
|
||||||
|
endTime: form.endTime,
|
||||||
|
reason: form.reason,
|
||||||
|
stuList: stuList
|
||||||
|
}
|
||||||
|
|
||||||
|
// 编辑时需要包含id
|
||||||
|
if (operType.value === 'edit') {
|
||||||
|
submitData.id = form.id
|
||||||
|
}
|
||||||
|
|
||||||
|
if (operType.value === 'add') {
|
||||||
|
await addObj(submitData)
|
||||||
|
useMessage().success('新增成功')
|
||||||
|
} else {
|
||||||
|
await editObj(submitData)
|
||||||
|
useMessage().success('编辑成功')
|
||||||
|
}
|
||||||
|
visible.value = false
|
||||||
|
emit('refresh')
|
||||||
|
} catch (err: any) {
|
||||||
|
useMessage().error(err.msg || (operType.value === 'add' ? '新增失败' : '编辑失败'))
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取班级列表
|
||||||
|
const getClassListData = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getClassListByRole()
|
||||||
|
if (res.data) {
|
||||||
|
classList.value = Array.isArray(res.data) ? res.data : []
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取班级列表失败', err)
|
||||||
|
classList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化
|
||||||
|
onMounted(() => {
|
||||||
|
getClassListData()
|
||||||
|
})
|
||||||
|
|
||||||
|
// 暴露方法给父组件
|
||||||
|
defineExpose({
|
||||||
|
openDialog
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
196
src/views/stuwork/stuinnerleaveapplygroup/index.vue
Normal file
196
src/views/stuwork/stuinnerleaveapplygroup/index.vue
Normal file
@@ -0,0 +1,196 @@
|
|||||||
|
<template>
|
||||||
|
<div class="layout-padding">
|
||||||
|
<div class="layout-padding-auto layout-padding-view">
|
||||||
|
<!-- 搜索表单 -->
|
||||||
|
<el-row v-show="showSearch">
|
||||||
|
<el-form :model="searchForm" ref="searchFormRef" :inline="true" @keyup.enter="handleSearch">
|
||||||
|
<el-form-item label="发起部门" prop="deptCode">
|
||||||
|
<el-select
|
||||||
|
v-model="searchForm.deptCode"
|
||||||
|
placeholder="请选择发起部门"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
style="width: 200px">
|
||||||
|
<el-option
|
||||||
|
v-for="item in deptList"
|
||||||
|
:key="item.deptCode"
|
||||||
|
:label="item.deptName"
|
||||||
|
:value="item.deptCode">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" plain icon="Search" @click="handleSearch">查询</el-button>
|
||||||
|
<el-button icon="Refresh" @click="handleReset">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<!-- 操作按钮 -->
|
||||||
|
<el-row>
|
||||||
|
<div class="mb8" style="width: 100%">
|
||||||
|
<el-button
|
||||||
|
icon="FolderAdd"
|
||||||
|
type="primary"
|
||||||
|
class="ml10"
|
||||||
|
@click="formDialogRef.openDialog()">
|
||||||
|
新 增
|
||||||
|
</el-button>
|
||||||
|
<right-toolbar
|
||||||
|
v-model:showSearch="showSearch"
|
||||||
|
class="ml10 mr20"
|
||||||
|
style="float: right;"
|
||||||
|
@queryTable="getDataList">
|
||||||
|
</right-toolbar>
|
||||||
|
</div>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<!-- 表格 -->
|
||||||
|
<el-table
|
||||||
|
:data="state.dataList"
|
||||||
|
v-loading="state.loading"
|
||||||
|
border
|
||||||
|
:cell-style="tableStyle.cellStyle"
|
||||||
|
:header-cell-style="tableStyle.headerCellStyle">
|
||||||
|
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||||
|
<el-table-column prop="startTime" label="开始时间" show-overflow-tooltip align="center" width="180">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ scope.row.startTime ? formatDateTime(scope.row.startTime) : '-' }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="endTime" label="结束时间" show-overflow-tooltip align="center" width="180">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ scope.row.endTime ? formatDateTime(scope.row.endTime) : '-' }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="reason" label="请假事由" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="deptName" label="发起部门" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column label="操作" width="150" align="center" fixed="right">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button
|
||||||
|
icon="Edit"
|
||||||
|
text
|
||||||
|
type="primary"
|
||||||
|
@click="handleEdit(scope.row)">
|
||||||
|
编辑
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
icon="Delete"
|
||||||
|
text
|
||||||
|
type="danger"
|
||||||
|
@click="handleDelete(scope.row)">
|
||||||
|
删除
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<!-- 分页 -->
|
||||||
|
<pagination
|
||||||
|
@size-change="sizeChangeHandle"
|
||||||
|
@current-change="currentChangeHandle"
|
||||||
|
v-bind="state.pagination" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 新增/编辑表单弹窗 -->
|
||||||
|
<form-dialog ref="formDialogRef" @refresh="getDataList" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts" name="StuInnerLeaveApplyGroup">
|
||||||
|
import { reactive, ref, onMounted } from 'vue'
|
||||||
|
import { BasicTableProps, useTable } from "/@/hooks/table";
|
||||||
|
import { fetchList, delObj } from "/@/api/stuwork/stuinnerleaveapplygroup";
|
||||||
|
import { getDeptListByLevelTwo } from "/@/api/basic/basicdept";
|
||||||
|
import { useMessage, useMessageBox } from "/@/hooks/message";
|
||||||
|
import FormDialog from './form.vue'
|
||||||
|
|
||||||
|
// 定义变量内容
|
||||||
|
const searchFormRef = ref()
|
||||||
|
const showSearch = ref(true)
|
||||||
|
const deptList = ref<any[]>([])
|
||||||
|
const formDialogRef = ref()
|
||||||
|
|
||||||
|
// 搜索表单
|
||||||
|
const searchForm = reactive({
|
||||||
|
deptCode: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
// 配置 useTable
|
||||||
|
const state: BasicTableProps = reactive<BasicTableProps>({
|
||||||
|
queryForm: searchForm,
|
||||||
|
pageList: fetchList,
|
||||||
|
props: {
|
||||||
|
item: 'records',
|
||||||
|
totalCount: 'total'
|
||||||
|
},
|
||||||
|
createdIsNeed: true
|
||||||
|
})
|
||||||
|
|
||||||
|
// table hook
|
||||||
|
const {
|
||||||
|
getDataList,
|
||||||
|
currentChangeHandle,
|
||||||
|
sizeChangeHandle,
|
||||||
|
tableStyle
|
||||||
|
} = useTable(state)
|
||||||
|
|
||||||
|
// 格式化日期时间
|
||||||
|
const formatDateTime = (dateTime: string) => {
|
||||||
|
if (!dateTime) return '-'
|
||||||
|
// 如果包含时间部分,只显示日期部分
|
||||||
|
if (dateTime.includes(' ')) {
|
||||||
|
return dateTime.split(' ')[0]
|
||||||
|
}
|
||||||
|
return dateTime
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询
|
||||||
|
const handleSearch = () => {
|
||||||
|
getDataList()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置
|
||||||
|
const handleReset = () => {
|
||||||
|
searchFormRef.value?.resetFields()
|
||||||
|
searchForm.deptCode = ''
|
||||||
|
getDataList()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 编辑
|
||||||
|
const handleEdit = (row: any) => {
|
||||||
|
formDialogRef.value?.openDialog('edit', row)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除
|
||||||
|
const handleDelete = async (row: any) => {
|
||||||
|
try {
|
||||||
|
await useMessageBox().confirm('确定要删除这条记录吗?')
|
||||||
|
await delObj([row.id])
|
||||||
|
useMessage().success('删除成功')
|
||||||
|
getDataList()
|
||||||
|
} catch (err: any) {
|
||||||
|
if (err !== 'cancel') {
|
||||||
|
useMessage().error(err.msg || '删除失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取部门列表
|
||||||
|
const getDeptListData = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getDeptListByLevelTwo()
|
||||||
|
if (res.data) {
|
||||||
|
deptList.value = Array.isArray(res.data) ? res.data : []
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取部门列表失败', err)
|
||||||
|
deptList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化
|
||||||
|
onMounted(() => {
|
||||||
|
getDeptListData()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
327
src/views/stuwork/stuleaveapply/form.vue
Normal file
327
src/views/stuwork/stuleaveapply/form.vue
Normal file
@@ -0,0 +1,327 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
title="新增"
|
||||||
|
v-model="visible"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
draggable
|
||||||
|
width="800px">
|
||||||
|
<el-form
|
||||||
|
ref="dataFormRef"
|
||||||
|
:model="form"
|
||||||
|
:rules="dataRules"
|
||||||
|
label-width="120px"
|
||||||
|
v-loading="loading">
|
||||||
|
<el-row :gutter="24">
|
||||||
|
<el-col :span="12" class="mb20">
|
||||||
|
<el-form-item label="班级" prop="classCode">
|
||||||
|
<el-select
|
||||||
|
v-model="form.classCode"
|
||||||
|
placeholder="请选择班级"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
style="width: 100%"
|
||||||
|
@change="handleClassChange">
|
||||||
|
<el-option
|
||||||
|
v-for="item in classList"
|
||||||
|
:key="item.classCode"
|
||||||
|
:label="item.classNo"
|
||||||
|
:value="item.classCode">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<el-col :span="12" class="mb20">
|
||||||
|
<el-form-item label="学号" prop="stuNo">
|
||||||
|
<el-select
|
||||||
|
v-model="form.stuNo"
|
||||||
|
placeholder="请选择学生"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
style="width: 100%"
|
||||||
|
:disabled="!form.classCode"
|
||||||
|
@change="handleStudentChange">
|
||||||
|
<el-option
|
||||||
|
v-for="item in studentList"
|
||||||
|
:key="item.stuNo"
|
||||||
|
:label="`${item.realName} (${item.stuNo})`"
|
||||||
|
:value="item.stuNo">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<el-col :span="24" class="mb20">
|
||||||
|
<el-form-item label="请假时间" prop="leaveTime">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="form.leaveTime"
|
||||||
|
type="datetimerange"
|
||||||
|
range-separator="至"
|
||||||
|
start-placeholder="开始时间"
|
||||||
|
end-placeholder="结束时间"
|
||||||
|
format="YYYY-MM-DD HH:mm"
|
||||||
|
value-format="YYYY-MM-DD HH:mm:ss"
|
||||||
|
style="width: 100%" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<el-col :span="12" class="mb20">
|
||||||
|
<el-form-item label="请假类型" prop="leaveType">
|
||||||
|
<el-select
|
||||||
|
v-model="form.leaveType"
|
||||||
|
placeholder="请选择请假类型"
|
||||||
|
clearable
|
||||||
|
style="width: 100%">
|
||||||
|
<el-option
|
||||||
|
v-for="item in leaveTypeList"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<el-col :span="12" class="mb20">
|
||||||
|
<el-form-item label="是否住宿" prop="stayDorm">
|
||||||
|
<el-switch
|
||||||
|
v-model="form.stayDorm"
|
||||||
|
active-value="1"
|
||||||
|
inactive-value="0"
|
||||||
|
active-text="是"
|
||||||
|
inactive-text="否" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<el-col :span="12" class="mb20">
|
||||||
|
<el-form-item label="是否发热" prop="isFever">
|
||||||
|
<el-switch
|
||||||
|
v-model="form.isFever"
|
||||||
|
active-value="1"
|
||||||
|
inactive-value="0"
|
||||||
|
active-text="是"
|
||||||
|
inactive-text="否" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<el-col :span="24" class="mb20">
|
||||||
|
<el-form-item label="请假事由" prop="reason">
|
||||||
|
<el-input
|
||||||
|
v-model="form.reason"
|
||||||
|
type="textarea"
|
||||||
|
:rows="4"
|
||||||
|
placeholder="请输入请假事由" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click="visible = false">取 消</el-button>
|
||||||
|
<el-button type="primary" @click="onSubmit" :disabled="loading">确 认</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts" name="StuLeaveApplyFormDialog">
|
||||||
|
import { ref, reactive, nextTick, onMounted } from 'vue'
|
||||||
|
import { useMessage } from '/@/hooks/message'
|
||||||
|
import { addObj } from '/@/api/stuwork/stuleaveapply'
|
||||||
|
import { getDicts } from '/@/api/admin/dict'
|
||||||
|
import { getClassListByRole } from '/@/api/basic/basicclass'
|
||||||
|
import { queryStudentListByClass } from '/@/api/basic/basicstudent'
|
||||||
|
|
||||||
|
const emit = defineEmits(['refresh'])
|
||||||
|
|
||||||
|
// 定义变量内容
|
||||||
|
const dataFormRef = ref()
|
||||||
|
const visible = ref(false)
|
||||||
|
const loading = ref(false)
|
||||||
|
const classList = ref<any[]>([])
|
||||||
|
const studentList = ref<any[]>([])
|
||||||
|
const leaveTypeList = ref<any[]>([])
|
||||||
|
const yesNoList = ref<any[]>([])
|
||||||
|
|
||||||
|
// 提交表单数据
|
||||||
|
const form = reactive({
|
||||||
|
classCode: '',
|
||||||
|
stuNo: '',
|
||||||
|
leaveTime: null as [string, string] | null,
|
||||||
|
leaveType: '',
|
||||||
|
reason: '',
|
||||||
|
stayDorm: '',
|
||||||
|
isFever: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
// 定义校验规则
|
||||||
|
const dataRules = {
|
||||||
|
classCode: [
|
||||||
|
{ required: true, message: '请选择班级', trigger: 'change' }
|
||||||
|
],
|
||||||
|
stuNo: [
|
||||||
|
{ required: true, message: '请选择学生', trigger: 'change' }
|
||||||
|
],
|
||||||
|
leaveTime: [
|
||||||
|
{ required: true, message: '请选择请假时间', trigger: 'change', type: 'array', min: 2 }
|
||||||
|
],
|
||||||
|
leaveType: [
|
||||||
|
{ required: true, message: '请选择请假类型', trigger: 'change' }
|
||||||
|
],
|
||||||
|
reason: [
|
||||||
|
{ required: true, message: '请输入请假事由', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
stayDorm: [
|
||||||
|
{ required: true, message: '请选择是否住宿', trigger: 'change' }
|
||||||
|
],
|
||||||
|
isFever: [
|
||||||
|
{ required: true, message: '请选择是否发热', trigger: 'change' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 班级变化时获取学生列表
|
||||||
|
const handleClassChange = async (classCode: string) => {
|
||||||
|
form.stuNo = ''
|
||||||
|
studentList.value = []
|
||||||
|
if (!classCode) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await queryStudentListByClass({ classCode, current: 1, size: 10000 })
|
||||||
|
if (res.data && Array.isArray(res.data.records)) {
|
||||||
|
studentList.value = res.data.records
|
||||||
|
} else {
|
||||||
|
studentList.value = []
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取学生列表失败', err)
|
||||||
|
studentList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 学生变化
|
||||||
|
const handleStudentChange = (stuNo: string) => {
|
||||||
|
// 可以在这里处理学生变化后的逻辑
|
||||||
|
}
|
||||||
|
|
||||||
|
// 打开弹窗
|
||||||
|
const openDialog = async () => {
|
||||||
|
visible.value = true
|
||||||
|
|
||||||
|
// 重置表单数据
|
||||||
|
nextTick(() => {
|
||||||
|
dataFormRef.value?.resetFields()
|
||||||
|
form.classCode = ''
|
||||||
|
form.stuNo = ''
|
||||||
|
form.leaveTime = null
|
||||||
|
form.leaveType = ''
|
||||||
|
form.reason = ''
|
||||||
|
form.stayDorm = '0'
|
||||||
|
form.isFever = '0'
|
||||||
|
studentList.value = []
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提交表单
|
||||||
|
const onSubmit = async () => {
|
||||||
|
if (!dataFormRef.value) return
|
||||||
|
|
||||||
|
await dataFormRef.value.validate(async (valid: boolean) => {
|
||||||
|
if (!valid) return
|
||||||
|
|
||||||
|
// 验证请假时间范围
|
||||||
|
if (!form.leaveTime || form.leaveTime.length !== 2) {
|
||||||
|
useMessage().error('请选择请假时间范围')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const [startTime, endTime] = form.leaveTime
|
||||||
|
const start = new Date(startTime)
|
||||||
|
const end = new Date(endTime)
|
||||||
|
if (end <= start) {
|
||||||
|
useMessage().error('请假结束时间必须大于开始时间')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
await addObj({
|
||||||
|
classCode: form.classCode,
|
||||||
|
stuNo: form.stuNo,
|
||||||
|
startTime: startTime,
|
||||||
|
endTime: endTime,
|
||||||
|
leaveType: form.leaveType,
|
||||||
|
reason: form.reason,
|
||||||
|
stayDorm: form.stayDorm,
|
||||||
|
isFever: form.isFever
|
||||||
|
})
|
||||||
|
useMessage().success('新增成功')
|
||||||
|
visible.value = false
|
||||||
|
emit('refresh')
|
||||||
|
} catch (err: any) {
|
||||||
|
useMessage().error(err.msg || '新增失败')
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取班级列表
|
||||||
|
const getClassListData = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getClassListByRole()
|
||||||
|
if (res.data) {
|
||||||
|
classList.value = Array.isArray(res.data) ? res.data : []
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取班级列表失败', err)
|
||||||
|
classList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取请假类型字典
|
||||||
|
const getLeaveTypeDict = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getDicts('leave_type')
|
||||||
|
if (res.data) {
|
||||||
|
leaveTypeList.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) {
|
||||||
|
console.error('获取请假类型字典失败', err)
|
||||||
|
leaveTypeList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取是否字典
|
||||||
|
const getYesNoDict = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getDicts('yes_no')
|
||||||
|
if (res.data) {
|
||||||
|
yesNoList.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) {
|
||||||
|
console.error('获取是否字典失败', err)
|
||||||
|
yesNoList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化
|
||||||
|
onMounted(() => {
|
||||||
|
getClassListData()
|
||||||
|
getLeaveTypeDict()
|
||||||
|
getYesNoDict()
|
||||||
|
})
|
||||||
|
|
||||||
|
// 暴露方法给父组件
|
||||||
|
defineExpose({
|
||||||
|
openDialog
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
537
src/views/stuwork/stuleaveapply/index.vue
Normal file
537
src/views/stuwork/stuleaveapply/index.vue
Normal file
@@ -0,0 +1,537 @@
|
|||||||
|
<template>
|
||||||
|
<div class="layout-padding">
|
||||||
|
<div class="layout-padding-auto layout-padding-view">
|
||||||
|
<!-- 搜索表单 -->
|
||||||
|
<el-row v-show="showSearch">
|
||||||
|
<el-form :model="searchForm" ref="searchFormRef" :inline="true" @keyup.enter="handleSearch">
|
||||||
|
<el-form-item label="学年" prop="schoolYear">
|
||||||
|
<el-select
|
||||||
|
v-model="searchForm.schoolYear"
|
||||||
|
placeholder="请选择学年"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
style="width: 200px">
|
||||||
|
<el-option
|
||||||
|
v-for="item in schoolYearList"
|
||||||
|
:key="item.year"
|
||||||
|
:label="item.year"
|
||||||
|
:value="item.year">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="学期" prop="schoolTerm">
|
||||||
|
<el-select
|
||||||
|
v-model="searchForm.schoolTerm"
|
||||||
|
placeholder="请选择学期"
|
||||||
|
clearable
|
||||||
|
style="width: 200px">
|
||||||
|
<el-option
|
||||||
|
v-for="item in schoolTermList"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="学院" prop="deptCode">
|
||||||
|
<el-select
|
||||||
|
v-model="searchForm.deptCode"
|
||||||
|
placeholder="请选择学院"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
style="width: 200px">
|
||||||
|
<el-option
|
||||||
|
v-for="item in deptList"
|
||||||
|
:key="item.deptCode"
|
||||||
|
:label="item.deptName"
|
||||||
|
:value="item.deptCode">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="班级" prop="classCode">
|
||||||
|
<el-select
|
||||||
|
v-model="searchForm.classCode"
|
||||||
|
placeholder="请选择班级"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
style="width: 200px">
|
||||||
|
<el-option
|
||||||
|
v-for="item in classList"
|
||||||
|
:key="item.classCode"
|
||||||
|
:label="item.classNo"
|
||||||
|
:value="item.classCode">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="姓名" prop="realName">
|
||||||
|
<el-input
|
||||||
|
v-model="searchForm.realName"
|
||||||
|
placeholder="请输入姓名"
|
||||||
|
clearable
|
||||||
|
style="width: 200px" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="请假类型" prop="leaveType">
|
||||||
|
<el-select
|
||||||
|
v-model="searchForm.leaveType"
|
||||||
|
placeholder="请选择请假类型"
|
||||||
|
clearable
|
||||||
|
style="width: 200px">
|
||||||
|
<el-option
|
||||||
|
v-for="item in leaveTypeList"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="住宿类型" prop="goOrStay">
|
||||||
|
<el-select
|
||||||
|
v-model="searchForm.goOrStay"
|
||||||
|
placeholder="请选择住宿类型"
|
||||||
|
clearable
|
||||||
|
style="width: 200px">
|
||||||
|
<el-option label="走读生" value="0" />
|
||||||
|
<el-option label="住宿生" value="1" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="是否住宿" prop="stayDorm">
|
||||||
|
<el-select
|
||||||
|
v-model="searchForm.stayDorm"
|
||||||
|
placeholder="请选择是否住宿"
|
||||||
|
clearable
|
||||||
|
style="width: 200px">
|
||||||
|
<el-option
|
||||||
|
v-for="item in yesNoList"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="班主任审核" prop="classAudit">
|
||||||
|
<el-select
|
||||||
|
v-model="searchForm.classAudit"
|
||||||
|
placeholder="请选择班主任审核"
|
||||||
|
clearable
|
||||||
|
style="width: 200px">
|
||||||
|
<el-option
|
||||||
|
v-for="item in auditTypeList"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="学生科审核" prop="deptAudit">
|
||||||
|
<el-select
|
||||||
|
v-model="searchForm.deptAudit"
|
||||||
|
placeholder="请选择学生科审核"
|
||||||
|
clearable
|
||||||
|
style="width: 200px">
|
||||||
|
<el-option
|
||||||
|
v-for="item in auditTypeList"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="学工处审批" prop="schoolAudit">
|
||||||
|
<el-select
|
||||||
|
v-model="searchForm.schoolAudit"
|
||||||
|
placeholder="请选择学工处审批"
|
||||||
|
clearable
|
||||||
|
style="width: 200px">
|
||||||
|
<el-option
|
||||||
|
v-for="item in auditTypeList"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" plain icon="Search" @click="handleSearch">查询</el-button>
|
||||||
|
<el-button icon="Refresh" @click="handleReset">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<!-- 操作按钮 -->
|
||||||
|
<el-row>
|
||||||
|
<div class="mb8" style="width: 100%">
|
||||||
|
<el-button
|
||||||
|
icon="FolderAdd"
|
||||||
|
type="primary"
|
||||||
|
class="ml10"
|
||||||
|
@click="formDialogRef.openDialog()">
|
||||||
|
新 增
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
icon="Download"
|
||||||
|
type="success"
|
||||||
|
class="ml10"
|
||||||
|
@click="handleExport">
|
||||||
|
导 出
|
||||||
|
</el-button>
|
||||||
|
<right-toolbar
|
||||||
|
v-model:showSearch="showSearch"
|
||||||
|
class="ml10 mr20"
|
||||||
|
style="float: right;"
|
||||||
|
@queryTable="getDataList">
|
||||||
|
</right-toolbar>
|
||||||
|
</div>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<!-- 表格 -->
|
||||||
|
<el-table
|
||||||
|
:data="state.dataList"
|
||||||
|
v-loading="state.loading"
|
||||||
|
border
|
||||||
|
:cell-style="tableStyle.cellStyle"
|
||||||
|
:header-cell-style="tableStyle.headerCellStyle">
|
||||||
|
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||||
|
<el-table-column prop="schoolYear" label="学年" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="schoolTerm" label="学期" show-overflow-tooltip align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ formatSchoolTerm(scope.row.schoolTerm) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="deptName" label="学院" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="realName" label="姓名" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="startTime" label="请假开始时间" show-overflow-tooltip align="center" width="180">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ scope.row.startTime ? formatDateTime(scope.row.startTime) : '-' }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="endTime" label="请假结束时间" show-overflow-tooltip align="center" width="180">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ scope.row.endTime ? formatDateTime(scope.row.endTime) : '-' }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="leaveType" label="请假类型" show-overflow-tooltip align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ formatLeaveType(scope.row.leaveType) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="reason" label="请假事由" show-overflow-tooltip align="center" min-width="150" />
|
||||||
|
<el-table-column prop="stayDorm" label="是否住宿" show-overflow-tooltip align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ formatYesNo(scope.row.stayDorm) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="isFever" label="是否发热" show-overflow-tooltip align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ formatYesNo(scope.row.isFever) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="classAudit" label="班主任审核" show-overflow-tooltip align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ formatAuditType(scope.row.classAudit) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="deptAudit" label="学生科审核" show-overflow-tooltip align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ formatAuditType(scope.row.deptAudit) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="schoolAudit" label="学工处审批" show-overflow-tooltip align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ formatAuditType(scope.row.schoolAudit) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="remarks" label="备注" show-overflow-tooltip align="center" min-width="150" />
|
||||||
|
<el-table-column prop="rejectReason" label="驳回原因" show-overflow-tooltip align="center" min-width="150" />
|
||||||
|
<el-table-column label="操作" width="100" align="center" fixed="right">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button
|
||||||
|
icon="CircleClose"
|
||||||
|
text
|
||||||
|
type="warning"
|
||||||
|
@click="handleCancel(scope.row)">
|
||||||
|
撤销
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<!-- 分页 -->
|
||||||
|
<pagination
|
||||||
|
@size-change="sizeChangeHandle"
|
||||||
|
@current-change="currentChangeHandle"
|
||||||
|
v-bind="state.pagination" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 新增表单弹窗 -->
|
||||||
|
<form-dialog ref="formDialogRef" @refresh="getDataList" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts" name="StuLeaveApply">
|
||||||
|
import { reactive, ref, onMounted } from 'vue'
|
||||||
|
import { BasicTableProps, useTable } from "/@/hooks/table";
|
||||||
|
import { fetchList, exportData, cancelObj } from "/@/api/stuwork/stuleaveapply";
|
||||||
|
import { queryAllSchoolYear } from "/@/api/basic/basicyear";
|
||||||
|
import { getDicts } from "/@/api/admin/dict";
|
||||||
|
import { getDeptListByLevelTwo } from "/@/api/basic/basicdept";
|
||||||
|
import { getClassListByRole } from "/@/api/basic/basicclass";
|
||||||
|
import { useMessage, useMessageBox } from "/@/hooks/message";
|
||||||
|
import FormDialog from './form.vue'
|
||||||
|
|
||||||
|
// 定义变量内容
|
||||||
|
const searchFormRef = ref()
|
||||||
|
const showSearch = ref(true)
|
||||||
|
const schoolYearList = ref<any[]>([])
|
||||||
|
const schoolTermList = ref<any[]>([])
|
||||||
|
const deptList = ref<any[]>([])
|
||||||
|
const classList = ref<any[]>([])
|
||||||
|
const leaveTypeList = ref<any[]>([])
|
||||||
|
const yesNoList = ref<any[]>([])
|
||||||
|
const auditTypeList = ref<any[]>([])
|
||||||
|
const formDialogRef = ref()
|
||||||
|
|
||||||
|
// 搜索表单
|
||||||
|
const searchForm = reactive({
|
||||||
|
schoolYear: '',
|
||||||
|
schoolTerm: '',
|
||||||
|
deptCode: '',
|
||||||
|
classCode: '',
|
||||||
|
realName: '',
|
||||||
|
leaveType: '',
|
||||||
|
goOrStay: '',
|
||||||
|
stayDorm: '',
|
||||||
|
classAudit: '',
|
||||||
|
deptAudit: '',
|
||||||
|
schoolAudit: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
// 配置 useTable
|
||||||
|
const state: BasicTableProps = reactive<BasicTableProps>({
|
||||||
|
queryForm: searchForm,
|
||||||
|
pageList: fetchList,
|
||||||
|
props: {
|
||||||
|
item: 'records',
|
||||||
|
totalCount: 'total'
|
||||||
|
},
|
||||||
|
createdIsNeed: true
|
||||||
|
})
|
||||||
|
|
||||||
|
// table hook
|
||||||
|
const {
|
||||||
|
getDataList,
|
||||||
|
currentChangeHandle,
|
||||||
|
sizeChangeHandle,
|
||||||
|
tableStyle
|
||||||
|
} = useTable(state)
|
||||||
|
|
||||||
|
// 格式化学期
|
||||||
|
const formatSchoolTerm = (value: string | number) => {
|
||||||
|
if (value === null || value === undefined || value === '') {
|
||||||
|
return '-'
|
||||||
|
}
|
||||||
|
const dictItem = schoolTermList.value.find(item => item.value == value)
|
||||||
|
return dictItem ? dictItem.label : value
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化日期时间
|
||||||
|
const formatDateTime = (dateTime: string) => {
|
||||||
|
if (!dateTime) return '-'
|
||||||
|
// 如果包含时间部分,只显示日期和时间
|
||||||
|
if (dateTime.includes(' ')) {
|
||||||
|
return dateTime.split('.')[0] // 移除毫秒部分
|
||||||
|
}
|
||||||
|
return dateTime
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化请假类型
|
||||||
|
const formatLeaveType = (value: string) => {
|
||||||
|
if (!value) return '-'
|
||||||
|
const item = leaveTypeList.value.find((item: any) => item.value === value)
|
||||||
|
return item ? item.label : value
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化是否
|
||||||
|
const formatYesNo = (value: string | null) => {
|
||||||
|
if (value === null || value === undefined || value === '') return '-'
|
||||||
|
const item = yesNoList.value.find((item: any) => item.value === value)
|
||||||
|
return item ? item.label : (value === '1' || value === 'true' ? '是' : '否')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化审核类型
|
||||||
|
const formatAuditType = (value: string) => {
|
||||||
|
if (!value) return '-'
|
||||||
|
const item = auditTypeList.value.find((item: any) => item.value === value)
|
||||||
|
return item ? item.label : value
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询
|
||||||
|
const handleSearch = () => {
|
||||||
|
getDataList()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置
|
||||||
|
const handleReset = () => {
|
||||||
|
searchFormRef.value?.resetFields()
|
||||||
|
searchForm.schoolYear = ''
|
||||||
|
searchForm.schoolTerm = ''
|
||||||
|
searchForm.deptCode = ''
|
||||||
|
searchForm.classCode = ''
|
||||||
|
searchForm.realName = ''
|
||||||
|
searchForm.leaveType = ''
|
||||||
|
searchForm.goOrStay = ''
|
||||||
|
searchForm.stayDorm = ''
|
||||||
|
searchForm.classAudit = ''
|
||||||
|
searchForm.deptAudit = ''
|
||||||
|
searchForm.schoolAudit = ''
|
||||||
|
getDataList()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 撤销
|
||||||
|
const handleCancel = async (row: any) => {
|
||||||
|
try {
|
||||||
|
await useMessageBox().confirm('确定要撤销这条请假记录吗?')
|
||||||
|
await cancelObj(row.id)
|
||||||
|
useMessage().success('撤销成功')
|
||||||
|
getDataList()
|
||||||
|
} catch (err: any) {
|
||||||
|
if (err !== 'cancel') {
|
||||||
|
useMessage().error(err.msg || '撤销失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 导出
|
||||||
|
const handleExport = async () => {
|
||||||
|
try {
|
||||||
|
const res = await exportData(searchForm)
|
||||||
|
// 处理返回的文件流
|
||||||
|
const blob = new Blob([res.data])
|
||||||
|
const elink = document.createElement('a')
|
||||||
|
elink.download = '学生请假.xlsx'
|
||||||
|
elink.style.display = 'none'
|
||||||
|
elink.href = URL.createObjectURL(blob)
|
||||||
|
document.body.appendChild(elink)
|
||||||
|
elink.click()
|
||||||
|
URL.revokeObjectURL(elink.href)
|
||||||
|
document.body.removeChild(elink)
|
||||||
|
useMessage().success('导出成功')
|
||||||
|
} catch (err: any) {
|
||||||
|
useMessage().error(err.msg || '导出失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取学年列表
|
||||||
|
const getSchoolYearList = async () => {
|
||||||
|
try {
|
||||||
|
const res = await queryAllSchoolYear()
|
||||||
|
if (res.data) {
|
||||||
|
schoolYearList.value = Array.isArray(res.data) ? res.data : []
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取学年列表失败', 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) {
|
||||||
|
console.error('获取学期字典失败', err)
|
||||||
|
schoolTermList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取学院列表
|
||||||
|
const getDeptListData = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getDeptListByLevelTwo()
|
||||||
|
if (res.data) {
|
||||||
|
deptList.value = Array.isArray(res.data) ? res.data : []
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取学院列表失败', err)
|
||||||
|
deptList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取班级列表
|
||||||
|
const getClassListData = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getClassListByRole()
|
||||||
|
if (res.data) {
|
||||||
|
classList.value = Array.isArray(res.data) ? res.data : []
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取班级列表失败', err)
|
||||||
|
classList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取请假类型字典
|
||||||
|
const getLeaveTypeDict = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getDicts('leave_type')
|
||||||
|
if (res.data) {
|
||||||
|
leaveTypeList.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) {
|
||||||
|
console.error('获取请假类型字典失败', err)
|
||||||
|
leaveTypeList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取是否字典
|
||||||
|
const getYesNoDict = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getDicts('yes_no')
|
||||||
|
if (res.data) {
|
||||||
|
yesNoList.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) {
|
||||||
|
console.error('获取是否字典失败', err)
|
||||||
|
yesNoList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取审核类型字典
|
||||||
|
const getAuditTypeDict = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getDicts('class_audit_type')
|
||||||
|
if (res.data) {
|
||||||
|
auditTypeList.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) {
|
||||||
|
console.error('获取审核类型字典失败', err)
|
||||||
|
auditTypeList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化
|
||||||
|
onMounted(() => {
|
||||||
|
getSchoolYearList()
|
||||||
|
getSchoolTermDict()
|
||||||
|
getDeptListData()
|
||||||
|
getClassListData()
|
||||||
|
getLeaveTypeDict()
|
||||||
|
getYesNoDict()
|
||||||
|
getAuditTypeDict()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
386
src/views/stuwork/stupunlish/form.vue
Normal file
386
src/views/stuwork/stupunlish/form.vue
Normal file
@@ -0,0 +1,386 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
:title="form.id ? '编辑' : '新增'"
|
||||||
|
v-model="visible"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
draggable
|
||||||
|
width="800px">
|
||||||
|
<el-form
|
||||||
|
ref="dataFormRef"
|
||||||
|
:model="form"
|
||||||
|
:rules="dataRules"
|
||||||
|
label-width="120px"
|
||||||
|
v-loading="loading">
|
||||||
|
<el-row :gutter="24">
|
||||||
|
<el-col :span="12" class="mb20">
|
||||||
|
<el-form-item label="班级" prop="classCode">
|
||||||
|
<el-select
|
||||||
|
v-model="form.classCode"
|
||||||
|
placeholder="请选择班级"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
style="width: 100%"
|
||||||
|
@change="handleClassChange">
|
||||||
|
<el-option
|
||||||
|
v-for="item in classList"
|
||||||
|
:key="item.classCode"
|
||||||
|
:label="item.classNo"
|
||||||
|
:value="item.classCode">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<el-col :span="12" class="mb20">
|
||||||
|
<el-form-item label="学号" prop="stuNo">
|
||||||
|
<el-select
|
||||||
|
v-model="form.stuNo"
|
||||||
|
placeholder="请选择学生"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
style="width: 100%"
|
||||||
|
:disabled="!form.classCode"
|
||||||
|
@change="handleStudentChange">
|
||||||
|
<el-option
|
||||||
|
v-for="item in studentList"
|
||||||
|
:key="item.stuNo"
|
||||||
|
:label="`${item.realName} (${item.stuNo})`"
|
||||||
|
:value="item.stuNo">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<el-col :span="12" class="mb20">
|
||||||
|
<el-form-item label="处分时间" prop="punlishStartDate">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="form.punlishStartDate"
|
||||||
|
type="date"
|
||||||
|
placeholder="选择处分时间"
|
||||||
|
format="YYYY-MM-DD"
|
||||||
|
value-format="YYYY-MM-DD HH:mm:ss"
|
||||||
|
style="width: 100%" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<el-col :span="12" class="mb20">
|
||||||
|
<el-form-item label="到期日" prop="punlishEndDate">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="form.punlishEndDate"
|
||||||
|
type="date"
|
||||||
|
placeholder="选择到期日"
|
||||||
|
format="YYYY-MM-DD"
|
||||||
|
value-format="YYYY-MM-DD HH:mm:ss"
|
||||||
|
style="width: 100%" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<el-col :span="12" class="mb20">
|
||||||
|
<el-form-item label="处分级别" prop="punlishLevel">
|
||||||
|
<el-select
|
||||||
|
v-model="form.punlishLevel"
|
||||||
|
placeholder="请选择处分级别"
|
||||||
|
clearable
|
||||||
|
style="width: 100%">
|
||||||
|
<el-option
|
||||||
|
v-for="item in punlishLevelList"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<el-col :span="24" class="mb20">
|
||||||
|
<el-form-item label="处分内容" prop="punlishContent">
|
||||||
|
<el-input
|
||||||
|
v-model="form.punlishContent"
|
||||||
|
type="textarea"
|
||||||
|
:rows="4"
|
||||||
|
placeholder="请输入处分内容" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click="visible = false">取 消</el-button>
|
||||||
|
<el-button type="primary" @click="onSubmit" :disabled="loading">确 认</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts" name="StuPunlishFormDialog">
|
||||||
|
import { ref, reactive, nextTick, onMounted, watch } from 'vue'
|
||||||
|
import { useMessage } from '/@/hooks/message'
|
||||||
|
import { addObj, editObj, getDetail } from '/@/api/stuwork/stupunlish'
|
||||||
|
import { queryAllSchoolYear } from '/@/api/basic/basicyear'
|
||||||
|
import { getDicts } from '/@/api/admin/dict'
|
||||||
|
import { getClassListByRole } from '/@/api/basic/basicclass'
|
||||||
|
import { queryStudentListByClass } from '/@/api/basic/basicstudent'
|
||||||
|
|
||||||
|
const emit = defineEmits(['refresh'])
|
||||||
|
|
||||||
|
// 定义变量内容
|
||||||
|
const dataFormRef = ref()
|
||||||
|
const visible = ref(false)
|
||||||
|
const loading = ref(false)
|
||||||
|
const operType = ref('add') // add 或 edit
|
||||||
|
const schoolYearList = ref<any[]>([])
|
||||||
|
const schoolTermList = ref<any[]>([])
|
||||||
|
const classList = ref<any[]>([])
|
||||||
|
const studentList = ref<any[]>([])
|
||||||
|
const punlishLevelList = ref<any[]>([])
|
||||||
|
const publishStatusList = ref<any[]>([])
|
||||||
|
|
||||||
|
// 提交表单数据
|
||||||
|
const form = reactive({
|
||||||
|
id: '',
|
||||||
|
schoolYear: '',
|
||||||
|
schoolTerm: '',
|
||||||
|
classCode: '',
|
||||||
|
stuNo: '',
|
||||||
|
punlishStartDate: '',
|
||||||
|
punlishEndDate: '',
|
||||||
|
punlishLevel: '',
|
||||||
|
punlishContent: '',
|
||||||
|
publishStatus: '',
|
||||||
|
attachment: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
// 定义校验规则
|
||||||
|
const dataRules = {
|
||||||
|
classCode: [
|
||||||
|
{ required: true, message: '请选择班级', trigger: 'change' }
|
||||||
|
],
|
||||||
|
stuNo: [
|
||||||
|
{ required: true, message: '请选择学生', trigger: 'change' }
|
||||||
|
],
|
||||||
|
punlishStartDate: [
|
||||||
|
{ required: true, message: '请选择处分时间', trigger: 'change' }
|
||||||
|
],
|
||||||
|
punlishEndDate: [
|
||||||
|
{ required: true, message: '请选择到期日', trigger: 'change' }
|
||||||
|
],
|
||||||
|
punlishLevel: [
|
||||||
|
{ required: true, message: '请选择处分级别', trigger: 'change' }
|
||||||
|
],
|
||||||
|
punlishContent: [
|
||||||
|
{ required: true, message: '请输入处分内容', trigger: 'blur' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 班级变化时获取学生列表
|
||||||
|
const handleClassChange = async (classCode: string) => {
|
||||||
|
form.stuNo = ''
|
||||||
|
studentList.value = []
|
||||||
|
if (!classCode) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await queryStudentListByClass({ classCode, current: 1, size: 10000 })
|
||||||
|
if (res.data && Array.isArray(res.data.records)) {
|
||||||
|
studentList.value = res.data.records
|
||||||
|
} else {
|
||||||
|
studentList.value = []
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取学生列表失败', err)
|
||||||
|
studentList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 学生变化
|
||||||
|
const handleStudentChange = (stuNo: string) => {
|
||||||
|
// 可以在这里处理学生变化后的逻辑
|
||||||
|
}
|
||||||
|
|
||||||
|
// 打开弹窗
|
||||||
|
const openDialog = async (type: string = 'add', row?: any) => {
|
||||||
|
visible.value = true
|
||||||
|
operType.value = type
|
||||||
|
|
||||||
|
// 重置表单数据
|
||||||
|
nextTick(() => {
|
||||||
|
dataFormRef.value?.resetFields()
|
||||||
|
form.id = ''
|
||||||
|
form.schoolYear = ''
|
||||||
|
form.schoolTerm = ''
|
||||||
|
form.classCode = ''
|
||||||
|
form.stuNo = ''
|
||||||
|
form.punlishStartDate = ''
|
||||||
|
form.punlishEndDate = ''
|
||||||
|
form.punlishLevel = ''
|
||||||
|
form.punlishContent = ''
|
||||||
|
form.publishStatus = ''
|
||||||
|
form.attachment = ''
|
||||||
|
studentList.value = []
|
||||||
|
|
||||||
|
// 编辑时填充数据
|
||||||
|
if (type === 'edit' && row) {
|
||||||
|
form.id = row.id
|
||||||
|
form.schoolYear = row.schoolYear || ''
|
||||||
|
form.schoolTerm = row.schoolTerm || ''
|
||||||
|
form.classCode = row.classCode || ''
|
||||||
|
form.stuNo = row.stuNo || ''
|
||||||
|
form.punlishStartDate = row.punlishStartDate || ''
|
||||||
|
form.punlishEndDate = row.punlishEndDate || ''
|
||||||
|
form.punlishLevel = row.punlishLevel || ''
|
||||||
|
form.punlishContent = row.punlishContent || ''
|
||||||
|
form.publishStatus = row.publishStatus || ''
|
||||||
|
form.attachment = row.attachment || ''
|
||||||
|
|
||||||
|
// 如果有班级代码,加载学生列表
|
||||||
|
if (form.classCode) {
|
||||||
|
handleClassChange(form.classCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提交表单
|
||||||
|
const onSubmit = async () => {
|
||||||
|
if (!dataFormRef.value) return
|
||||||
|
|
||||||
|
await dataFormRef.value.validate(async (valid: boolean) => {
|
||||||
|
if (!valid) return
|
||||||
|
|
||||||
|
// 验证到期日必须大于处分时间
|
||||||
|
if (form.punlishStartDate && form.punlishEndDate) {
|
||||||
|
const start = new Date(form.punlishStartDate)
|
||||||
|
const end = new Date(form.punlishEndDate)
|
||||||
|
if (end <= start) {
|
||||||
|
useMessage().error('到期日必须大于处分时间')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const submitData: any = {
|
||||||
|
classCode: form.classCode,
|
||||||
|
stuNo: form.stuNo,
|
||||||
|
punlishStartDate: form.punlishStartDate,
|
||||||
|
punlishEndDate: form.punlishEndDate,
|
||||||
|
punlishLevel: form.punlishLevel,
|
||||||
|
punlishContent: form.punlishContent,
|
||||||
|
publishStatus: form.publishStatus || '1',
|
||||||
|
attachment: form.attachment || ''
|
||||||
|
}
|
||||||
|
|
||||||
|
// 编辑时需要包含id和学年学期
|
||||||
|
if (operType.value === 'edit') {
|
||||||
|
submitData.id = form.id
|
||||||
|
submitData.schoolYear = form.schoolYear
|
||||||
|
submitData.schoolTerm = form.schoolTerm
|
||||||
|
}
|
||||||
|
|
||||||
|
if (operType.value === 'add') {
|
||||||
|
await addObj(submitData)
|
||||||
|
useMessage().success('新增成功')
|
||||||
|
} else {
|
||||||
|
await editObj(submitData)
|
||||||
|
useMessage().success('编辑成功')
|
||||||
|
}
|
||||||
|
visible.value = false
|
||||||
|
emit('refresh')
|
||||||
|
} catch (err: any) {
|
||||||
|
useMessage().error(err.msg || (operType.value === 'add' ? '新增失败' : '编辑失败'))
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取学年列表
|
||||||
|
const getSchoolYearList = async () => {
|
||||||
|
try {
|
||||||
|
const res = await queryAllSchoolYear()
|
||||||
|
if (res.data) {
|
||||||
|
schoolYearList.value = Array.isArray(res.data) ? res.data : []
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取学年列表失败', 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) {
|
||||||
|
console.error('获取学期字典失败', err)
|
||||||
|
schoolTermList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取班级列表
|
||||||
|
const getClassListData = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getClassListByRole()
|
||||||
|
if (res.data) {
|
||||||
|
classList.value = Array.isArray(res.data) ? res.data : []
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取班级列表失败', err)
|
||||||
|
classList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取处分级别字典
|
||||||
|
const getPunlishLevelDict = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getDicts('punlish_level')
|
||||||
|
if (res.data) {
|
||||||
|
punlishLevelList.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) {
|
||||||
|
console.error('获取处分级别字典失败', err)
|
||||||
|
punlishLevelList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取处分状态字典
|
||||||
|
const getPublishStatusDict = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getDicts('publish_status')
|
||||||
|
if (res.data) {
|
||||||
|
publishStatusList.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) {
|
||||||
|
console.error('获取处分状态字典失败', err)
|
||||||
|
publishStatusList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化
|
||||||
|
onMounted(() => {
|
||||||
|
getSchoolYearList()
|
||||||
|
getSchoolTermDict()
|
||||||
|
getClassListData()
|
||||||
|
getPunlishLevelDict()
|
||||||
|
getPublishStatusDict()
|
||||||
|
})
|
||||||
|
|
||||||
|
// 暴露方法给父组件
|
||||||
|
defineExpose({
|
||||||
|
openDialog
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
517
src/views/stuwork/stupunlish/index.vue
Normal file
517
src/views/stuwork/stupunlish/index.vue
Normal file
@@ -0,0 +1,517 @@
|
|||||||
|
<template>
|
||||||
|
<div class="layout-padding">
|
||||||
|
<div class="layout-padding-auto layout-padding-view">
|
||||||
|
<!-- 搜索表单 -->
|
||||||
|
<el-row v-show="showSearch">
|
||||||
|
<el-form :model="searchForm" ref="searchFormRef" :inline="true" @keyup.enter="handleSearch">
|
||||||
|
<el-form-item label="学年" prop="schoolYear">
|
||||||
|
<el-select
|
||||||
|
v-model="searchForm.schoolYear"
|
||||||
|
placeholder="请选择学年"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
style="width: 200px">
|
||||||
|
<el-option
|
||||||
|
v-for="item in schoolYearList"
|
||||||
|
:key="item.year"
|
||||||
|
:label="item.year"
|
||||||
|
:value="item.year">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="学期" prop="schoolTerm">
|
||||||
|
<el-select
|
||||||
|
v-model="searchForm.schoolTerm"
|
||||||
|
placeholder="请选择学期"
|
||||||
|
clearable
|
||||||
|
style="width: 200px">
|
||||||
|
<el-option
|
||||||
|
v-for="item in schoolTermList"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="学院" prop="deptCode">
|
||||||
|
<el-select
|
||||||
|
v-model="searchForm.deptCode"
|
||||||
|
placeholder="请选择学院"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
style="width: 200px">
|
||||||
|
<el-option
|
||||||
|
v-for="item in deptList"
|
||||||
|
:key="item.deptCode"
|
||||||
|
:label="item.deptName"
|
||||||
|
:value="item.deptCode">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="班级" prop="classCode">
|
||||||
|
<el-select
|
||||||
|
v-model="searchForm.classCode"
|
||||||
|
placeholder="请选择班级"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
style="width: 200px">
|
||||||
|
<el-option
|
||||||
|
v-for="item in classList"
|
||||||
|
:key="item.classCode"
|
||||||
|
:label="item.classNo"
|
||||||
|
:value="item.classCode">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="姓名" prop="realName">
|
||||||
|
<el-input
|
||||||
|
v-model="searchForm.realName"
|
||||||
|
placeholder="请输入姓名"
|
||||||
|
clearable
|
||||||
|
style="width: 200px" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="学号" prop="stuNo">
|
||||||
|
<el-input
|
||||||
|
v-model="searchForm.stuNo"
|
||||||
|
placeholder="请输入学号"
|
||||||
|
clearable
|
||||||
|
style="width: 200px" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="处分月份" prop="punlishMonth">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="searchForm.punlishMonth"
|
||||||
|
type="month"
|
||||||
|
placeholder="选择处分月份"
|
||||||
|
format="YYYY-MM"
|
||||||
|
value-format="YYYY-MM"
|
||||||
|
clearable
|
||||||
|
style="width: 200px" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="处分级别" prop="punlishLevel">
|
||||||
|
<el-select
|
||||||
|
v-model="searchForm.punlishLevel"
|
||||||
|
placeholder="请选择处分级别"
|
||||||
|
clearable
|
||||||
|
style="width: 200px">
|
||||||
|
<el-option
|
||||||
|
v-for="item in punlishLevelList"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" plain icon="Search" @click="handleSearch">查询</el-button>
|
||||||
|
<el-button icon="Refresh" @click="handleReset">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<!-- 操作按钮 -->
|
||||||
|
<el-row>
|
||||||
|
<div class="mb8" style="width: 100%">
|
||||||
|
<el-button
|
||||||
|
icon="FolderAdd"
|
||||||
|
type="primary"
|
||||||
|
class="ml10"
|
||||||
|
@click="formDialogRef.openDialog()">
|
||||||
|
新 增
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
icon="Download"
|
||||||
|
type="success"
|
||||||
|
class="ml10"
|
||||||
|
@click="handleExport">
|
||||||
|
导 出
|
||||||
|
</el-button>
|
||||||
|
<right-toolbar
|
||||||
|
v-model:showSearch="showSearch"
|
||||||
|
class="ml10 mr20"
|
||||||
|
style="float: right;"
|
||||||
|
@queryTable="getDataList">
|
||||||
|
</right-toolbar>
|
||||||
|
</div>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<!-- 表格 -->
|
||||||
|
<el-table
|
||||||
|
:data="state.dataList"
|
||||||
|
v-loading="state.loading"
|
||||||
|
border
|
||||||
|
:cell-style="tableStyle.cellStyle"
|
||||||
|
:header-cell-style="tableStyle.headerCellStyle">
|
||||||
|
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||||
|
<el-table-column prop="schoolYear" label="学年" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="schoolTerm" label="学期" show-overflow-tooltip align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ formatSchoolTerm(scope.row.schoolTerm) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="deptName" label="学院" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="classNo" label="班级" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="stuRealName" label="姓名" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="stuNo" label="学号" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="punlishStartDate" label="处分时间" show-overflow-tooltip align="center" width="180">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ scope.row.punlishStartDate ? formatDate(scope.row.punlishStartDate) : '-' }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="punlishEndDate" label="到期日" show-overflow-tooltip align="center" width="180">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ scope.row.punlishEndDate ? formatDate(scope.row.punlishEndDate) : '-' }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="punlishLevel" label="处分级别" show-overflow-tooltip align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ formatPunlishLevel(scope.row.punlishLevel) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="punlishContent" label="处分内容" show-overflow-tooltip align="center" min-width="150" />
|
||||||
|
<el-table-column prop="publishStatus" label="处分状态" show-overflow-tooltip align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ formatPublishStatus(scope.row.publishStatus) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" width="250" align="center" fixed="right">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button
|
||||||
|
icon="Document"
|
||||||
|
text
|
||||||
|
type="primary"
|
||||||
|
@click="handleReport(scope.row)">
|
||||||
|
思想汇报
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
icon="CircleClose"
|
||||||
|
text
|
||||||
|
type="warning"
|
||||||
|
@click="handleCancel(scope.row)">
|
||||||
|
撤销处分
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
icon="Edit"
|
||||||
|
text
|
||||||
|
type="primary"
|
||||||
|
@click="handleEdit(scope.row)">
|
||||||
|
编辑
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
icon="Delete"
|
||||||
|
text
|
||||||
|
type="danger"
|
||||||
|
@click="handleDelete(scope.row)">
|
||||||
|
删除
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<!-- 分页 -->
|
||||||
|
<pagination
|
||||||
|
@size-change="sizeChangeHandle"
|
||||||
|
@current-change="currentChangeHandle"
|
||||||
|
v-bind="state.pagination" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 新增/编辑表单弹窗 -->
|
||||||
|
<form-dialog ref="formDialogRef" @refresh="getDataList" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts" name="StuPunlish">
|
||||||
|
import { reactive, ref, onMounted } from 'vue'
|
||||||
|
import { BasicTableProps, useTable } from "/@/hooks/table";
|
||||||
|
import { fetchList, delObj, exportData, revokePunishment, getDetail } from "/@/api/stuwork/stupunlish";
|
||||||
|
import { queryAllSchoolYear } from "/@/api/basic/basicyear";
|
||||||
|
import { getDicts } from "/@/api/admin/dict";
|
||||||
|
import { getDeptListByLevelTwo } from "/@/api/basic/basicdept";
|
||||||
|
import { getClassListByRole } from "/@/api/basic/basicclass";
|
||||||
|
import { useMessage, useMessageBox } from "/@/hooks/message";
|
||||||
|
import FormDialog from './form.vue'
|
||||||
|
|
||||||
|
// 定义变量内容
|
||||||
|
const searchFormRef = ref()
|
||||||
|
const showSearch = ref(true)
|
||||||
|
const schoolYearList = ref<any[]>([])
|
||||||
|
const schoolTermList = ref<any[]>([])
|
||||||
|
const deptList = ref<any[]>([])
|
||||||
|
const classList = ref<any[]>([])
|
||||||
|
const punlishLevelList = ref<any[]>([])
|
||||||
|
const publishStatusList = ref<any[]>([])
|
||||||
|
const formDialogRef = ref()
|
||||||
|
|
||||||
|
// 搜索表单
|
||||||
|
const searchForm = reactive({
|
||||||
|
schoolYear: '',
|
||||||
|
schoolTerm: '',
|
||||||
|
deptCode: '',
|
||||||
|
classCode: '',
|
||||||
|
realName: '',
|
||||||
|
stuNo: '',
|
||||||
|
punlishMonth: '',
|
||||||
|
punlishLevel: '',
|
||||||
|
punlishMonthArray: [] as string[]
|
||||||
|
})
|
||||||
|
|
||||||
|
// 配置 useTable
|
||||||
|
const state: BasicTableProps = reactive<BasicTableProps>({
|
||||||
|
queryForm: searchForm,
|
||||||
|
pageList: async (params: any) => {
|
||||||
|
// 处理处分月份参数,API需要数组格式
|
||||||
|
const queryParams = { ...params }
|
||||||
|
if (queryParams.punlishMonth) {
|
||||||
|
queryParams.punlishMonth = [queryParams.punlishMonth]
|
||||||
|
} else {
|
||||||
|
delete queryParams.punlishMonth
|
||||||
|
}
|
||||||
|
delete queryParams.punlishMonthArray
|
||||||
|
return await fetchList(queryParams)
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
item: 'records',
|
||||||
|
totalCount: 'total'
|
||||||
|
},
|
||||||
|
createdIsNeed: true
|
||||||
|
})
|
||||||
|
|
||||||
|
// table hook
|
||||||
|
const {
|
||||||
|
getDataList,
|
||||||
|
currentChangeHandle,
|
||||||
|
sizeChangeHandle,
|
||||||
|
tableStyle
|
||||||
|
} = useTable(state)
|
||||||
|
|
||||||
|
// 格式化学期
|
||||||
|
const formatSchoolTerm = (value: string | number) => {
|
||||||
|
if (value === null || value === undefined || value === '') {
|
||||||
|
return '-'
|
||||||
|
}
|
||||||
|
const dictItem = schoolTermList.value.find(item => item.value == value)
|
||||||
|
return dictItem ? dictItem.label : value
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化日期
|
||||||
|
const formatDate = (dateStr: string) => {
|
||||||
|
if (!dateStr) return '-'
|
||||||
|
// 如果包含时间部分,只显示日期部分
|
||||||
|
if (dateStr.includes(' ')) {
|
||||||
|
return dateStr.split(' ')[0]
|
||||||
|
}
|
||||||
|
return dateStr
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化处分级别
|
||||||
|
const formatPunlishLevel = (value: string) => {
|
||||||
|
if (!value) return '-'
|
||||||
|
const item = punlishLevelList.value.find((item: any) => item.value === value)
|
||||||
|
return item ? item.label : value
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化处分状态
|
||||||
|
const formatPublishStatus = (value: string) => {
|
||||||
|
if (!value) return '-'
|
||||||
|
const item = publishStatusList.value.find((item: any) => item.value === value)
|
||||||
|
return item ? item.label : value
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询
|
||||||
|
const handleSearch = () => {
|
||||||
|
getDataList()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置
|
||||||
|
const handleReset = () => {
|
||||||
|
searchFormRef.value?.resetFields()
|
||||||
|
searchForm.schoolYear = ''
|
||||||
|
searchForm.schoolTerm = ''
|
||||||
|
searchForm.deptCode = ''
|
||||||
|
searchForm.classCode = ''
|
||||||
|
searchForm.realName = ''
|
||||||
|
searchForm.stuNo = ''
|
||||||
|
searchForm.punlishMonth = ''
|
||||||
|
searchForm.punlishLevel = ''
|
||||||
|
getDataList()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 编辑
|
||||||
|
const handleEdit = (row: any) => {
|
||||||
|
formDialogRef.value?.openDialog('edit', row)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除
|
||||||
|
const handleDelete = async (row: any) => {
|
||||||
|
try {
|
||||||
|
await useMessageBox().confirm('确定要删除这条记录吗?')
|
||||||
|
await delObj([row.id])
|
||||||
|
useMessage().success('删除成功')
|
||||||
|
getDataList()
|
||||||
|
} catch (err: any) {
|
||||||
|
if (err !== 'cancel') {
|
||||||
|
useMessage().error(err.msg || '删除失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 思想汇报
|
||||||
|
const handleReport = (row: any) => {
|
||||||
|
useMessage().info('思想汇报功能待实现')
|
||||||
|
// TODO: 实现思想汇报功能
|
||||||
|
}
|
||||||
|
|
||||||
|
// 撤销处分
|
||||||
|
const handleCancel = async (row: any) => {
|
||||||
|
const { confirm } = useMessageBox()
|
||||||
|
try {
|
||||||
|
await confirm('确定要撤销该处分吗?')
|
||||||
|
|
||||||
|
// 获取完整的处分信息
|
||||||
|
const res = await getDetail(row.id)
|
||||||
|
if (!res.data) {
|
||||||
|
useMessage().error('获取处分信息失败')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新publishStatus为"0"来撤销处分
|
||||||
|
const updateData = {
|
||||||
|
...res.data,
|
||||||
|
publishStatus: '0'
|
||||||
|
}
|
||||||
|
|
||||||
|
await revokePunishment(updateData)
|
||||||
|
useMessage().success('撤销处分成功')
|
||||||
|
getDataList()
|
||||||
|
} catch (err: any) {
|
||||||
|
if (err !== 'cancel') {
|
||||||
|
useMessage().error(err.msg || '撤销处分失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 导出
|
||||||
|
const handleExport = async () => {
|
||||||
|
try {
|
||||||
|
const params: any = { ...searchForm }
|
||||||
|
// 处理处分月份参数,API需要数组格式
|
||||||
|
if (params.punlishMonth) {
|
||||||
|
params.punlishMonth = [params.punlishMonth]
|
||||||
|
} else {
|
||||||
|
delete params.punlishMonth
|
||||||
|
}
|
||||||
|
delete params.punlishMonthArray
|
||||||
|
const res = await exportData(params)
|
||||||
|
// 处理返回的文件流
|
||||||
|
const blob = new Blob([res.data])
|
||||||
|
const elink = document.createElement('a')
|
||||||
|
elink.download = '学生违纪.xlsx'
|
||||||
|
elink.style.display = 'none'
|
||||||
|
elink.href = URL.createObjectURL(blob)
|
||||||
|
document.body.appendChild(elink)
|
||||||
|
elink.click()
|
||||||
|
URL.revokeObjectURL(elink.href)
|
||||||
|
document.body.removeChild(elink)
|
||||||
|
useMessage().success('导出成功')
|
||||||
|
} catch (err: any) {
|
||||||
|
useMessage().error(err.msg || '导出失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取学年列表
|
||||||
|
const getSchoolYearList = async () => {
|
||||||
|
try {
|
||||||
|
const res = await queryAllSchoolYear()
|
||||||
|
if (res.data) {
|
||||||
|
schoolYearList.value = Array.isArray(res.data) ? res.data : []
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取学年列表失败', 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) {
|
||||||
|
console.error('获取学期字典失败', err)
|
||||||
|
schoolTermList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取学院列表
|
||||||
|
const getDeptListData = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getDeptListByLevelTwo()
|
||||||
|
if (res.data) {
|
||||||
|
deptList.value = Array.isArray(res.data) ? res.data : []
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取学院列表失败', err)
|
||||||
|
deptList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取班级列表
|
||||||
|
const getClassListData = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getClassListByRole()
|
||||||
|
if (res.data) {
|
||||||
|
classList.value = Array.isArray(res.data) ? res.data : []
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取班级列表失败', err)
|
||||||
|
classList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取处分级别字典
|
||||||
|
const getPunlishLevelDict = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getDicts('punlish_level')
|
||||||
|
if (res.data) {
|
||||||
|
punlishLevelList.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) {
|
||||||
|
console.error('获取处分级别字典失败', err)
|
||||||
|
punlishLevelList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取处分状态字典
|
||||||
|
const getPublishStatusDict = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getDicts('publish_status')
|
||||||
|
if (res.data) {
|
||||||
|
publishStatusList.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) {
|
||||||
|
console.error('获取处分状态字典失败', err)
|
||||||
|
publishStatusList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化
|
||||||
|
onMounted(() => {
|
||||||
|
getSchoolYearList()
|
||||||
|
getSchoolTermDict()
|
||||||
|
getDeptListData()
|
||||||
|
getClassListData()
|
||||||
|
getPunlishLevelDict()
|
||||||
|
getPublishStatusDict()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
338
src/views/stuwork/stutemleaveapply/form.vue
Normal file
338
src/views/stuwork/stutemleaveapply/form.vue
Normal file
@@ -0,0 +1,338 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
title="新增"
|
||||||
|
v-model="visible"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
draggable
|
||||||
|
width="800px">
|
||||||
|
<el-form
|
||||||
|
ref="dataFormRef"
|
||||||
|
:model="form"
|
||||||
|
:rules="dataRules"
|
||||||
|
label-width="120px"
|
||||||
|
v-loading="loading">
|
||||||
|
<el-row :gutter="24">
|
||||||
|
<el-col :span="12" class="mb20">
|
||||||
|
<el-form-item label="系部代码" prop="deptCode">
|
||||||
|
<el-select
|
||||||
|
v-model="form.deptCode"
|
||||||
|
placeholder="请选择系部"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
style="width: 100%"
|
||||||
|
@change="handleDeptChange">
|
||||||
|
<el-option
|
||||||
|
v-for="item in deptList"
|
||||||
|
:key="item.deptCode"
|
||||||
|
:label="item.deptName"
|
||||||
|
:value="item.deptCode">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<el-col :span="12" class="mb20">
|
||||||
|
<el-form-item label="班级代码" prop="classCode">
|
||||||
|
<el-select
|
||||||
|
v-model="form.classCode"
|
||||||
|
placeholder="请选择班级"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
style="width: 100%"
|
||||||
|
@change="handleClassChange">
|
||||||
|
<el-option
|
||||||
|
v-for="item in classList"
|
||||||
|
:key="item.classCode"
|
||||||
|
:label="item.classNo"
|
||||||
|
:value="item.classCode">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<el-col :span="12" class="mb20">
|
||||||
|
<el-form-item label="学号" prop="stuNo">
|
||||||
|
<el-select
|
||||||
|
v-model="form.stuNo"
|
||||||
|
placeholder="请选择学生"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
style="width: 100%"
|
||||||
|
:disabled="!form.classCode"
|
||||||
|
@change="handleStudentChange">
|
||||||
|
<el-option
|
||||||
|
v-for="item in studentList"
|
||||||
|
:key="item.stuNo"
|
||||||
|
:label="`${item.realName} (${item.stuNo})`"
|
||||||
|
:value="item.stuNo">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<el-col :span="12" class="mb20">
|
||||||
|
<el-form-item label="姓名" prop="realName">
|
||||||
|
<el-input
|
||||||
|
v-model="form.realName"
|
||||||
|
placeholder="自动填充"
|
||||||
|
disabled
|
||||||
|
style="width: 100%" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<el-col :span="12" class="mb20">
|
||||||
|
<el-form-item label="请假开始时间" prop="startTime">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="form.startTime"
|
||||||
|
type="datetime"
|
||||||
|
placeholder="请选择开始时间"
|
||||||
|
format="YYYY-MM-DD HH:mm"
|
||||||
|
value-format="YYYY-MM-DD HH:mm:ss"
|
||||||
|
style="width: 100%" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<el-col :span="12" class="mb20">
|
||||||
|
<el-form-item label="请假结束时间" prop="endTime">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="form.endTime"
|
||||||
|
type="datetime"
|
||||||
|
placeholder="请选择结束时间"
|
||||||
|
format="YYYY-MM-DD HH:mm"
|
||||||
|
value-format="YYYY-MM-DD HH:mm:ss"
|
||||||
|
style="width: 100%" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<el-col :span="24" class="mb20">
|
||||||
|
<el-form-item label="请假事由" prop="reason">
|
||||||
|
<el-input
|
||||||
|
v-model="form.reason"
|
||||||
|
type="textarea"
|
||||||
|
:rows="4"
|
||||||
|
placeholder="请输入请假事由" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<el-col :span="24" class="mb20">
|
||||||
|
<el-form-item label="备注" prop="remarks">
|
||||||
|
<el-input
|
||||||
|
v-model="form.remarks"
|
||||||
|
type="textarea"
|
||||||
|
:rows="3"
|
||||||
|
placeholder="请输入备注" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click="visible = false">取 消</el-button>
|
||||||
|
<el-button type="primary" @click="onSubmit" :disabled="loading">确 认</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts" name="StuTemLeaveApplyFormDialog">
|
||||||
|
import { ref, reactive, nextTick, onMounted } from 'vue'
|
||||||
|
import { useMessage } from '/@/hooks/message'
|
||||||
|
import { addObj } from '/@/api/stuwork/stutemleaveapply'
|
||||||
|
import { getDeptListByLevelTwo } from '/@/api/basic/basicdept'
|
||||||
|
import { list as getClassList } from '/@/api/basic/basicclass'
|
||||||
|
import { queryStudentListByClass } from '/@/api/basic/basicstudent'
|
||||||
|
|
||||||
|
const emit = defineEmits(['refresh'])
|
||||||
|
|
||||||
|
// 定义变量内容
|
||||||
|
const dataFormRef = ref()
|
||||||
|
const visible = ref(false)
|
||||||
|
const loading = ref(false)
|
||||||
|
const deptList = ref<any[]>([])
|
||||||
|
const classList = ref<any[]>([])
|
||||||
|
const studentList = ref<any[]>([])
|
||||||
|
|
||||||
|
// 提交表单数据
|
||||||
|
const form = reactive({
|
||||||
|
deptCode: '',
|
||||||
|
classCode: '',
|
||||||
|
stuNo: '',
|
||||||
|
realName: '',
|
||||||
|
startTime: '',
|
||||||
|
endTime: '',
|
||||||
|
reason: '',
|
||||||
|
remarks: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
// 定义校验规则
|
||||||
|
const dataRules = {
|
||||||
|
deptCode: [
|
||||||
|
{ required: true, message: '请选择系部代码', trigger: 'change' }
|
||||||
|
],
|
||||||
|
classCode: [
|
||||||
|
{ required: true, message: '请选择班级代码', trigger: 'change' }
|
||||||
|
],
|
||||||
|
stuNo: [
|
||||||
|
{ required: true, message: '请选择学号', trigger: 'change' }
|
||||||
|
],
|
||||||
|
startTime: [
|
||||||
|
{ required: true, message: '请选择请假开始时间', trigger: 'change' }
|
||||||
|
],
|
||||||
|
endTime: [
|
||||||
|
{ required: true, message: '请选择请假结束时间', trigger: 'change' }
|
||||||
|
],
|
||||||
|
reason: [
|
||||||
|
{ required: true, message: '请输入请假事由', trigger: 'blur' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 打开弹窗
|
||||||
|
const openDialog = () => {
|
||||||
|
visible.value = true
|
||||||
|
resetForm()
|
||||||
|
nextTick(() => {
|
||||||
|
dataFormRef.value?.resetFields()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置表单
|
||||||
|
const resetForm = () => {
|
||||||
|
form.deptCode = ''
|
||||||
|
form.classCode = ''
|
||||||
|
form.stuNo = ''
|
||||||
|
form.realName = ''
|
||||||
|
form.startTime = ''
|
||||||
|
form.endTime = ''
|
||||||
|
form.reason = ''
|
||||||
|
form.remarks = ''
|
||||||
|
studentList.value = []
|
||||||
|
}
|
||||||
|
|
||||||
|
// 系部变化
|
||||||
|
const handleDeptChange = () => {
|
||||||
|
form.classCode = ''
|
||||||
|
form.stuNo = ''
|
||||||
|
form.realName = ''
|
||||||
|
studentList.value = []
|
||||||
|
// 根据系部筛选班级
|
||||||
|
if (form.deptCode) {
|
||||||
|
classList.value = classList.value.filter((item: any) => item.deptCode === form.deptCode)
|
||||||
|
} else {
|
||||||
|
getClassListData()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 班级变化
|
||||||
|
const handleClassChange = async () => {
|
||||||
|
form.stuNo = ''
|
||||||
|
form.realName = ''
|
||||||
|
studentList.value = []
|
||||||
|
if (form.classCode) {
|
||||||
|
await getStudentListData()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 学生变化
|
||||||
|
const handleStudentChange = () => {
|
||||||
|
const student = studentList.value.find((item: any) => item.stuNo === form.stuNo)
|
||||||
|
if (student) {
|
||||||
|
form.realName = student.realName || ''
|
||||||
|
} else {
|
||||||
|
form.realName = ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提交表单
|
||||||
|
const onSubmit = async () => {
|
||||||
|
if (!dataFormRef.value) return
|
||||||
|
|
||||||
|
await dataFormRef.value.validate(async (valid: boolean) => {
|
||||||
|
if (!valid) return
|
||||||
|
|
||||||
|
// 验证时间
|
||||||
|
if (form.startTime && form.endTime) {
|
||||||
|
const start = new Date(form.startTime)
|
||||||
|
const end = new Date(form.endTime)
|
||||||
|
if (end <= start) {
|
||||||
|
useMessage().error('请假结束时间必须大于开始时间')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
await addObj({
|
||||||
|
deptCode: form.deptCode,
|
||||||
|
classCode: form.classCode,
|
||||||
|
stuNo: form.stuNo,
|
||||||
|
startTime: form.startTime,
|
||||||
|
endTime: form.endTime,
|
||||||
|
reason: form.reason,
|
||||||
|
remarks: form.remarks
|
||||||
|
})
|
||||||
|
useMessage().success('新增成功')
|
||||||
|
visible.value = false
|
||||||
|
emit('refresh')
|
||||||
|
} catch (err: any) {
|
||||||
|
useMessage().error(err.msg || '新增失败')
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取系部列表
|
||||||
|
const getDeptListData = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getDeptListByLevelTwo()
|
||||||
|
if (res.data) {
|
||||||
|
deptList.value = Array.isArray(res.data) ? res.data : []
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取系部列表失败', err)
|
||||||
|
deptList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取班级列表
|
||||||
|
const getClassListData = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getClassList()
|
||||||
|
if (res.data) {
|
||||||
|
classList.value = Array.isArray(res.data) ? res.data : []
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取班级列表失败', err)
|
||||||
|
classList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取学生列表
|
||||||
|
const getStudentListData = async () => {
|
||||||
|
if (!form.classCode) return
|
||||||
|
try {
|
||||||
|
const res = await queryStudentListByClass(form.classCode)
|
||||||
|
if (res.data) {
|
||||||
|
studentList.value = Array.isArray(res.data) ? res.data : []
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取学生列表失败', err)
|
||||||
|
studentList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化
|
||||||
|
onMounted(() => {
|
||||||
|
getDeptListData()
|
||||||
|
getClassListData()
|
||||||
|
})
|
||||||
|
|
||||||
|
// 暴露方法
|
||||||
|
defineExpose({
|
||||||
|
openDialog
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
</style>
|
||||||
|
|
||||||
268
src/views/stuwork/stutemleaveapply/index.vue
Normal file
268
src/views/stuwork/stutemleaveapply/index.vue
Normal file
@@ -0,0 +1,268 @@
|
|||||||
|
<template>
|
||||||
|
<div class="layout-padding">
|
||||||
|
<div class="layout-padding-auto layout-padding-view">
|
||||||
|
<!-- 搜索表单 -->
|
||||||
|
<el-row v-show="showSearch">
|
||||||
|
<el-form :model="searchForm" ref="searchFormRef" :inline="true" @keyup.enter="handleSearch">
|
||||||
|
<el-form-item label="系部代码" prop="deptCode">
|
||||||
|
<el-select
|
||||||
|
v-model="searchForm.deptCode"
|
||||||
|
placeholder="请选择系部"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
style="width: 200px">
|
||||||
|
<el-option
|
||||||
|
v-for="item in deptList"
|
||||||
|
:key="item.deptCode"
|
||||||
|
:label="item.deptName"
|
||||||
|
:value="item.deptCode">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="班级代码" prop="classCode">
|
||||||
|
<el-select
|
||||||
|
v-model="searchForm.classCode"
|
||||||
|
placeholder="请选择班级"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
style="width: 200px">
|
||||||
|
<el-option
|
||||||
|
v-for="item in classList"
|
||||||
|
:key="item.classCode"
|
||||||
|
:label="item.classNo"
|
||||||
|
:value="item.classCode">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="学号" prop="stuNo">
|
||||||
|
<el-input
|
||||||
|
v-model="searchForm.stuNo"
|
||||||
|
placeholder="请输入学号"
|
||||||
|
clearable
|
||||||
|
style="width: 200px" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" plain icon="Search" @click="handleSearch">查询</el-button>
|
||||||
|
<el-button icon="Refresh" @click="handleReset">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<!-- 操作按钮 -->
|
||||||
|
<el-row>
|
||||||
|
<div class="mb8" style="width: 100%">
|
||||||
|
<el-button
|
||||||
|
icon="Plus"
|
||||||
|
type="primary"
|
||||||
|
class="ml10"
|
||||||
|
@click="formDialogRef.openDialog()">
|
||||||
|
新增
|
||||||
|
</el-button>
|
||||||
|
<right-toolbar
|
||||||
|
v-model:showSearch="showSearch"
|
||||||
|
class="ml10 mr20"
|
||||||
|
style="float: right;"
|
||||||
|
@queryTable="getDataList">
|
||||||
|
</right-toolbar>
|
||||||
|
</div>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<!-- 表格 -->
|
||||||
|
<el-table
|
||||||
|
:data="state.dataList"
|
||||||
|
v-loading="state.loading"
|
||||||
|
border
|
||||||
|
:cell-style="tableStyle.cellStyle"
|
||||||
|
:header-cell-style="tableStyle.headerCellStyle">
|
||||||
|
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||||
|
<el-table-column prop="schoolYear" label="学年" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="schoolTerm" label="学期" show-overflow-tooltip align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ formatSchoolTerm(scope.row.schoolTerm) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="deptCode" label="系部代码" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="classCode" label="班级代码" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="stuNo" label="学号" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="realName" label="姓名" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="startTime" label="请假开始时间" show-overflow-tooltip align="center" width="180">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ scope.row.startTime ? formatDateTime(scope.row.startTime) : '-' }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="endTime" label="请假结束时间" show-overflow-tooltip align="center" width="180">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ scope.row.endTime ? formatDateTime(scope.row.endTime) : '-' }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="reason" label="请假事由" show-overflow-tooltip align="center" min-width="150" />
|
||||||
|
<el-table-column prop="classTeach" label="班主任" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="stuPhote" label="联系方式" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="remarks" label="备注" show-overflow-tooltip align="center" min-width="150" />
|
||||||
|
<el-table-column label="操作" width="100" align="center" fixed="right">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button
|
||||||
|
icon="Delete"
|
||||||
|
text
|
||||||
|
type="danger"
|
||||||
|
@click="handleDelete(scope.row)">
|
||||||
|
删除
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<!-- 分页 -->
|
||||||
|
<pagination
|
||||||
|
@size-change="sizeChangeHandle"
|
||||||
|
@current-change="currentChangeHandle"
|
||||||
|
v-bind="state.pagination" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 新增表单弹窗 -->
|
||||||
|
<form-dialog ref="formDialogRef" @refresh="getDataList" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts" name="StuTemLeaveApply">
|
||||||
|
import { reactive, ref, onMounted } from 'vue'
|
||||||
|
import { BasicTableProps, useTable } from "/@/hooks/table";
|
||||||
|
import { fetchList, delObj } from "/@/api/stuwork/stutemleaveapply";
|
||||||
|
import { getDicts } from "/@/api/admin/dict";
|
||||||
|
import { getDeptListByLevelTwo } from "/@/api/basic/basicdept";
|
||||||
|
import { getClassListByRole } from "/@/api/basic/basicclass";
|
||||||
|
import { useMessage, useMessageBox } from "/@/hooks/message";
|
||||||
|
import FormDialog from './form.vue'
|
||||||
|
|
||||||
|
// 定义变量内容
|
||||||
|
const searchFormRef = ref()
|
||||||
|
const showSearch = ref(true)
|
||||||
|
const deptList = ref<any[]>([])
|
||||||
|
const classList = ref<any[]>([])
|
||||||
|
const schoolTermList = ref<any[]>([])
|
||||||
|
const formDialogRef = ref()
|
||||||
|
|
||||||
|
// 搜索表单
|
||||||
|
const searchForm = reactive({
|
||||||
|
deptCode: '',
|
||||||
|
classCode: '',
|
||||||
|
stuNo: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
// 配置 useTable
|
||||||
|
const state: BasicTableProps = reactive<BasicTableProps>({
|
||||||
|
queryForm: searchForm,
|
||||||
|
pageList: fetchList,
|
||||||
|
props: {
|
||||||
|
item: 'records',
|
||||||
|
totalCount: 'total'
|
||||||
|
},
|
||||||
|
createdIsNeed: true
|
||||||
|
})
|
||||||
|
|
||||||
|
// table hook
|
||||||
|
const {
|
||||||
|
getDataList,
|
||||||
|
currentChangeHandle,
|
||||||
|
sizeChangeHandle,
|
||||||
|
tableStyle
|
||||||
|
} = useTable(state)
|
||||||
|
|
||||||
|
// 格式化学期
|
||||||
|
const formatSchoolTerm = (value: string | number) => {
|
||||||
|
if (value === null || value === undefined || value === '') {
|
||||||
|
return '-'
|
||||||
|
}
|
||||||
|
const dictItem = schoolTermList.value.find(item => item.value == value)
|
||||||
|
return dictItem ? dictItem.label : value
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化日期时间
|
||||||
|
const formatDateTime = (dateTime: string) => {
|
||||||
|
if (!dateTime) return '-'
|
||||||
|
// 如果包含时间部分,只显示日期和时间
|
||||||
|
if (dateTime.includes(' ')) {
|
||||||
|
return dateTime.split('.')[0] // 移除毫秒部分
|
||||||
|
}
|
||||||
|
return dateTime
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询
|
||||||
|
const handleSearch = () => {
|
||||||
|
getDataList()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置
|
||||||
|
const handleReset = () => {
|
||||||
|
searchFormRef.value?.resetFields()
|
||||||
|
getDataList()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除
|
||||||
|
const handleDelete = async (row: any) => {
|
||||||
|
const { confirm } = useMessageBox()
|
||||||
|
try {
|
||||||
|
await confirm('确定要删除该临时请假记录吗?')
|
||||||
|
await delObj([row.id])
|
||||||
|
useMessage().success('删除成功')
|
||||||
|
getDataList()
|
||||||
|
} catch (err: any) {
|
||||||
|
if (err !== 'cancel') {
|
||||||
|
useMessage().error(err.msg || '删除失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取系部列表
|
||||||
|
const getDeptListData = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getDeptListByLevelTwo()
|
||||||
|
if (res.data) {
|
||||||
|
deptList.value = Array.isArray(res.data) ? res.data : []
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取系部列表失败', err)
|
||||||
|
deptList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取班级列表
|
||||||
|
const getClassListData = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getClassListByRole()
|
||||||
|
if (res.data) {
|
||||||
|
classList.value = Array.isArray(res.data) ? res.data : []
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取班级列表失败', err)
|
||||||
|
classList.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) {
|
||||||
|
console.error('获取学期字典失败', err)
|
||||||
|
schoolTermList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化
|
||||||
|
onMounted(() => {
|
||||||
|
getDeptListData()
|
||||||
|
getClassListData()
|
||||||
|
getSchoolTermDict()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
</style>
|
||||||
|
|
||||||
624
src/views/stuwork/stuturnover/form.vue
Normal file
624
src/views/stuwork/stuturnover/form.vue
Normal file
@@ -0,0 +1,624 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
:title="form.id ? '编辑' : '批量新增异动'"
|
||||||
|
v-model="visible"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
draggable
|
||||||
|
width="900px">
|
||||||
|
<el-form
|
||||||
|
ref="dataFormRef"
|
||||||
|
:model="form"
|
||||||
|
:rules="dataRules"
|
||||||
|
label-width="120px"
|
||||||
|
v-loading="loading">
|
||||||
|
<el-row :gutter="24">
|
||||||
|
<el-col :span="12" class="mb20">
|
||||||
|
<el-form-item label="学年" prop="schoolYear">
|
||||||
|
<el-select
|
||||||
|
v-model="form.schoolYear"
|
||||||
|
placeholder="请选择学年"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
style="width: 100%">
|
||||||
|
<el-option
|
||||||
|
v-for="item in schoolYearList"
|
||||||
|
:key="item.year"
|
||||||
|
:label="item.year"
|
||||||
|
:value="item.year">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<el-col :span="12" class="mb20">
|
||||||
|
<el-form-item label="学期" prop="schoolTerm">
|
||||||
|
<el-select
|
||||||
|
v-model="form.schoolTerm"
|
||||||
|
placeholder="请选择学期"
|
||||||
|
clearable
|
||||||
|
style="width: 100%">
|
||||||
|
<el-option
|
||||||
|
v-for="item in schoolTermList"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<el-col :span="12" class="mb20">
|
||||||
|
<el-form-item label="原班级" prop="oldClassCode">
|
||||||
|
<el-select
|
||||||
|
v-model="form.oldClassCode"
|
||||||
|
placeholder="请选择原班级"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
style="width: 100%"
|
||||||
|
@change="handleOldClassChange">
|
||||||
|
<el-option
|
||||||
|
v-for="item in classList"
|
||||||
|
:key="item.classCode"
|
||||||
|
:label="item.classNo"
|
||||||
|
:value="item.classCode">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<el-col :span="12" class="mb20">
|
||||||
|
<el-form-item label="现班级" prop="newClassCode">
|
||||||
|
<el-select
|
||||||
|
v-model="form.newClassCode"
|
||||||
|
placeholder="请选择现班级"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
style="width: 100%">
|
||||||
|
<el-option
|
||||||
|
v-for="item in classList"
|
||||||
|
:key="item.classCode"
|
||||||
|
:label="item.classNo"
|
||||||
|
:value="item.classCode">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<el-col :span="12" class="mb20">
|
||||||
|
<el-form-item label="异动类型" prop="turnoverType">
|
||||||
|
<el-select
|
||||||
|
v-model="form.turnoverType"
|
||||||
|
placeholder="请选择异动类型"
|
||||||
|
clearable
|
||||||
|
style="width: 100%">
|
||||||
|
<el-option
|
||||||
|
v-for="item in turnoverTypeList"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<el-col :span="12" class="mb20">
|
||||||
|
<el-form-item label="转制类型" prop="turnYear">
|
||||||
|
<el-select
|
||||||
|
v-model="form.turnYear"
|
||||||
|
placeholder="请选择转制类型"
|
||||||
|
clearable
|
||||||
|
style="width: 100%">
|
||||||
|
<el-option
|
||||||
|
v-for="item in turnYearList"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<el-col :span="12" class="mb20">
|
||||||
|
<el-form-item label="异动时间" prop="turnoverDate">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="form.turnoverDate"
|
||||||
|
type="datetime"
|
||||||
|
placeholder="选择异动时间"
|
||||||
|
format="YYYY-MM-DD HH:mm:ss"
|
||||||
|
value-format="YYYY-MM-DD HH:mm:ss"
|
||||||
|
style="width: 100%" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<el-col :span="12" class="mb20">
|
||||||
|
<el-form-item label="选择学生" prop="selectedStudents">
|
||||||
|
<el-input
|
||||||
|
v-model="selectedStudentsText"
|
||||||
|
placeholder="请选择学生"
|
||||||
|
readonly
|
||||||
|
style="width: 100%"
|
||||||
|
@click="openStudentDialog">
|
||||||
|
<template #suffix>
|
||||||
|
<el-button
|
||||||
|
icon="Search"
|
||||||
|
circle
|
||||||
|
@click.stop="openStudentDialog" />
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
|
<span v-if="form.selectedStudents.length > 0" class="ml5" style="color: #409eff;">
|
||||||
|
已选 {{ form.selectedStudents.length }} 人
|
||||||
|
</span>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<el-col :span="24" class="mb20">
|
||||||
|
<el-form-item label="异动原因" prop="remarks">
|
||||||
|
<el-input
|
||||||
|
v-model="form.remarks"
|
||||||
|
type="textarea"
|
||||||
|
:rows="4"
|
||||||
|
placeholder="请输入异动原因" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click="visible = false">取 消</el-button>
|
||||||
|
<el-button type="primary" @click="onSubmit" :disabled="loading">确 认</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
|
<!-- 学生选择弹窗 -->
|
||||||
|
<el-dialog
|
||||||
|
title="选择学生"
|
||||||
|
v-model="studentDialogVisible"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
draggable
|
||||||
|
width="900px">
|
||||||
|
<!-- 搜索表单 -->
|
||||||
|
<el-form :model="studentSearchForm" :inline="true" @keyup.enter="handleStudentSearch">
|
||||||
|
<el-form-item label="班号" prop="classNo">
|
||||||
|
<el-input
|
||||||
|
v-model="studentSearchForm.classNo"
|
||||||
|
placeholder="请输入班号"
|
||||||
|
clearable
|
||||||
|
style="width: 200px" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="学号" prop="stuNo">
|
||||||
|
<el-input
|
||||||
|
v-model="studentSearchForm.stuNo"
|
||||||
|
placeholder="请输入学号"
|
||||||
|
clearable
|
||||||
|
style="width: 200px" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="姓名" prop="realName">
|
||||||
|
<el-input
|
||||||
|
v-model="studentSearchForm.realName"
|
||||||
|
placeholder="请输入姓名"
|
||||||
|
clearable
|
||||||
|
style="width: 200px" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" plain icon="Search" @click="handleStudentSearch">查询</el-button>
|
||||||
|
<el-button icon="Refresh" @click="handleStudentReset">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
|
||||||
|
<!-- 学生表格 -->
|
||||||
|
<el-table
|
||||||
|
ref="studentTableRef"
|
||||||
|
:data="studentTableData"
|
||||||
|
v-loading="studentTableLoading"
|
||||||
|
border
|
||||||
|
@selection-change="handleStudentSelectionChange"
|
||||||
|
style="margin-top: 20px; max-height: 400px; overflow-y: auto;">
|
||||||
|
<el-table-column type="selection" width="55" align="center" />
|
||||||
|
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||||
|
<el-table-column prop="classNo" label="班号" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="stuNo" label="学号" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="realName" label="姓名" show-overflow-tooltip align="center" />
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<!-- 分页 -->
|
||||||
|
<pagination
|
||||||
|
@size-change="studentSizeChangeHandle"
|
||||||
|
@current-change="studentCurrentChangeHandle"
|
||||||
|
v-bind="studentPagination"
|
||||||
|
style="margin-top: 20px" />
|
||||||
|
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click="studentDialogVisible = false">取 消</el-button>
|
||||||
|
<el-button type="primary" @click="confirmStudentSelection">确 认</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts" name="StuTurnoverFormDialog">
|
||||||
|
import { ref, reactive, nextTick, onMounted, computed } from 'vue'
|
||||||
|
import { useMessage } from '/@/hooks/message'
|
||||||
|
import { addObj, editObj, getDetail } from '/@/api/stuwork/stuturnover'
|
||||||
|
import { queryAllSchoolYear } from '/@/api/basic/basicyear'
|
||||||
|
import { getDicts } from '/@/api/admin/dict'
|
||||||
|
import { list as getClassList } from '/@/api/basic/basicclass'
|
||||||
|
import { fetchList as getStudentList } from '/@/api/basic/basicstudent'
|
||||||
|
|
||||||
|
const emit = defineEmits(['refresh'])
|
||||||
|
|
||||||
|
// 定义变量内容
|
||||||
|
const dataFormRef = ref()
|
||||||
|
const studentTableRef = ref()
|
||||||
|
const visible = ref(false)
|
||||||
|
const loading = ref(false)
|
||||||
|
const operType = ref('add') // add 或 edit
|
||||||
|
const schoolYearList = ref<any[]>([])
|
||||||
|
const schoolTermList = ref<any[]>([])
|
||||||
|
const classList = ref<any[]>([])
|
||||||
|
const turnoverTypeList = ref<any[]>([])
|
||||||
|
const turnYearList = ref<any[]>([])
|
||||||
|
|
||||||
|
// 学生选择弹窗相关
|
||||||
|
const studentDialogVisible = ref(false)
|
||||||
|
const studentTableLoading = ref(false)
|
||||||
|
const studentTableData = ref<any[]>([])
|
||||||
|
const selectedStudentRows = ref<any[]>([]) // 表格中选中的行
|
||||||
|
const studentSearchForm = reactive({
|
||||||
|
classCode: '',
|
||||||
|
classNo: '',
|
||||||
|
stuNo: '',
|
||||||
|
realName: ''
|
||||||
|
})
|
||||||
|
const studentPagination = reactive({
|
||||||
|
total: 0,
|
||||||
|
pageSize: 10,
|
||||||
|
currentPage: 1
|
||||||
|
})
|
||||||
|
|
||||||
|
// 提交表单数据
|
||||||
|
const form = reactive({
|
||||||
|
id: '',
|
||||||
|
schoolYear: '',
|
||||||
|
schoolTerm: '',
|
||||||
|
oldClassCode: '',
|
||||||
|
newClassCode: '',
|
||||||
|
turnoverType: '',
|
||||||
|
turnYear: '',
|
||||||
|
turnoverDate: '',
|
||||||
|
remarks: '',
|
||||||
|
selectedStudents: [] as any[] // 选中的学生对象数组
|
||||||
|
})
|
||||||
|
|
||||||
|
// 已选学生文本显示
|
||||||
|
const selectedStudentsText = computed(() => {
|
||||||
|
if (!form.selectedStudents || form.selectedStudents.length === 0) {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
return `已选择 ${form.selectedStudents.length} 名学生`
|
||||||
|
})
|
||||||
|
|
||||||
|
// 定义校验规则
|
||||||
|
const dataRules = {
|
||||||
|
schoolYear: [
|
||||||
|
{ required: true, message: '请选择学年', trigger: 'change' }
|
||||||
|
],
|
||||||
|
schoolTerm: [
|
||||||
|
{ required: true, message: '请选择学期', trigger: 'change' }
|
||||||
|
],
|
||||||
|
oldClassCode: [
|
||||||
|
{ required: true, message: '请选择原班级', trigger: 'change' }
|
||||||
|
],
|
||||||
|
newClassCode: [
|
||||||
|
{ required: true, message: '请选择现班级', trigger: 'change' }
|
||||||
|
],
|
||||||
|
turnoverType: [
|
||||||
|
{ required: true, message: '请选择异动类型', trigger: 'change' }
|
||||||
|
],
|
||||||
|
turnoverDate: [
|
||||||
|
{ required: true, message: '请选择异动时间', trigger: 'change' }
|
||||||
|
],
|
||||||
|
selectedStudents: [
|
||||||
|
{ required: true, message: '请至少选择一个学生', trigger: 'change', type: 'array', min: 1 }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 原班级变化时,更新学生搜索条件
|
||||||
|
const handleOldClassChange = () => {
|
||||||
|
studentSearchForm.classCode = form.oldClassCode
|
||||||
|
// 清空已选学生
|
||||||
|
form.selectedStudents = []
|
||||||
|
}
|
||||||
|
|
||||||
|
// 打开学生选择弹窗
|
||||||
|
const openStudentDialog = () => {
|
||||||
|
if (!form.oldClassCode) {
|
||||||
|
useMessage().warning('请先选择原班级')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
studentDialogVisible.value = true
|
||||||
|
studentSearchForm.classCode = form.oldClassCode
|
||||||
|
studentSearchForm.classNo = ''
|
||||||
|
studentSearchForm.stuNo = ''
|
||||||
|
studentSearchForm.realName = ''
|
||||||
|
selectedStudentRows.value = []
|
||||||
|
studentPagination.currentPage = 1
|
||||||
|
handleStudentSearch()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 学生搜索
|
||||||
|
const handleStudentSearch = async () => {
|
||||||
|
studentTableLoading.value = true
|
||||||
|
try {
|
||||||
|
const params: any = {
|
||||||
|
current: studentPagination.currentPage,
|
||||||
|
size: studentPagination.pageSize,
|
||||||
|
classCode: studentSearchForm.classCode || undefined,
|
||||||
|
stuNo: studentSearchForm.stuNo || undefined,
|
||||||
|
realName: studentSearchForm.realName || undefined
|
||||||
|
}
|
||||||
|
const res = await getStudentList(params)
|
||||||
|
if (res.data && res.data.records) {
|
||||||
|
studentTableData.value = res.data.records
|
||||||
|
studentPagination.total = res.data.total || 0
|
||||||
|
} else {
|
||||||
|
studentTableData.value = []
|
||||||
|
studentPagination.total = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// 恢复之前选中的学生
|
||||||
|
nextTick(() => {
|
||||||
|
if (form.selectedStudents.length > 0) {
|
||||||
|
studentTableData.value.forEach((row: any) => {
|
||||||
|
const isSelected = form.selectedStudents.some((s: any) => s.stuNo === row.stuNo)
|
||||||
|
if (isSelected) {
|
||||||
|
studentTableRef.value?.toggleRowSelection(row, true)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取学生列表失败', err)
|
||||||
|
studentTableData.value = []
|
||||||
|
} finally {
|
||||||
|
studentTableLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 学生搜索重置
|
||||||
|
const handleStudentReset = () => {
|
||||||
|
studentSearchForm.classNo = ''
|
||||||
|
studentSearchForm.stuNo = ''
|
||||||
|
studentSearchForm.realName = ''
|
||||||
|
handleStudentSearch()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 学生表格选择变化
|
||||||
|
const handleStudentSelectionChange = (selection: any[]) => {
|
||||||
|
selectedStudentRows.value = selection
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确认学生选择
|
||||||
|
const confirmStudentSelection = () => {
|
||||||
|
if (selectedStudentRows.value.length === 0) {
|
||||||
|
useMessage().warning('请至少选择一个学生')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 合并已选学生(避免重复)
|
||||||
|
const newStudents = selectedStudentRows.value.map((row: any) => ({
|
||||||
|
stuNo: row.stuNo,
|
||||||
|
realName: row.realName
|
||||||
|
}))
|
||||||
|
|
||||||
|
// 合并到已选列表,去重
|
||||||
|
const existingStuNos = form.selectedStudents.map((s: any) => s.stuNo)
|
||||||
|
newStudents.forEach((student: any) => {
|
||||||
|
if (!existingStuNos.includes(student.stuNo)) {
|
||||||
|
form.selectedStudents.push(student)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
studentDialogVisible.value = false
|
||||||
|
useMessage().success(`已选择 ${form.selectedStudents.length} 名学生`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 学生分页变化
|
||||||
|
const studentSizeChangeHandle = (size: number) => {
|
||||||
|
studentPagination.pageSize = size
|
||||||
|
studentPagination.currentPage = 1
|
||||||
|
handleStudentSearch()
|
||||||
|
}
|
||||||
|
|
||||||
|
const studentCurrentChangeHandle = (current: number) => {
|
||||||
|
studentPagination.currentPage = current
|
||||||
|
handleStudentSearch()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 打开弹窗
|
||||||
|
const openDialog = async (type: string = 'add', row?: any) => {
|
||||||
|
visible.value = true
|
||||||
|
operType.value = type
|
||||||
|
|
||||||
|
// 重置表单数据
|
||||||
|
nextTick(() => {
|
||||||
|
dataFormRef.value?.resetFields()
|
||||||
|
form.id = ''
|
||||||
|
form.schoolYear = ''
|
||||||
|
form.schoolTerm = ''
|
||||||
|
form.oldClassCode = ''
|
||||||
|
form.newClassCode = ''
|
||||||
|
form.turnoverType = ''
|
||||||
|
form.turnYear = ''
|
||||||
|
form.turnoverDate = ''
|
||||||
|
form.remarks = ''
|
||||||
|
form.selectedStudents = []
|
||||||
|
|
||||||
|
// 编辑时填充数据
|
||||||
|
if (type === 'edit' && row) {
|
||||||
|
form.id = row.id
|
||||||
|
form.schoolYear = row.schoolYear || ''
|
||||||
|
form.schoolTerm = row.schoolTerm || ''
|
||||||
|
form.oldClassCode = row.oldClassCode || ''
|
||||||
|
form.newClassCode = row.newClassCode || ''
|
||||||
|
form.turnoverType = row.turnoverType || ''
|
||||||
|
form.turnYear = row.turnYear || ''
|
||||||
|
form.turnoverDate = row.turnoverDate || ''
|
||||||
|
form.remarks = row.remarks || ''
|
||||||
|
|
||||||
|
// 编辑时,学生列表只有当前学生
|
||||||
|
if (row.stuNo && row.realName) {
|
||||||
|
form.selectedStudents = [{
|
||||||
|
stuNo: row.stuNo,
|
||||||
|
realName: row.realName
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提交表单
|
||||||
|
const onSubmit = async () => {
|
||||||
|
if (!dataFormRef.value) return
|
||||||
|
|
||||||
|
await dataFormRef.value.validate(async (valid: boolean) => {
|
||||||
|
if (!valid) return
|
||||||
|
|
||||||
|
if (!form.selectedStudents || form.selectedStudents.length === 0) {
|
||||||
|
useMessage().error('请至少选择一个学生')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const submitData: any = {
|
||||||
|
schoolYear: form.schoolYear,
|
||||||
|
schoolTerm: form.schoolTerm,
|
||||||
|
oldClassCode: form.oldClassCode,
|
||||||
|
newClassCode: form.newClassCode,
|
||||||
|
turnoverType: form.turnoverType,
|
||||||
|
turnYear: form.turnYear || '',
|
||||||
|
turnoverDate: form.turnoverDate,
|
||||||
|
remarks: form.remarks || '',
|
||||||
|
stuList: form.selectedStudents.map((s: any) => ({
|
||||||
|
stuNo: s.stuNo,
|
||||||
|
realName: s.realName
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 编辑时需要包含id和单个学生信息
|
||||||
|
if (operType.value === 'edit') {
|
||||||
|
submitData.id = form.id
|
||||||
|
submitData.stuNo = form.selectedStudents[0]?.stuNo
|
||||||
|
submitData.realName = form.selectedStudents[0]?.realName
|
||||||
|
// 编辑时不需要stuList
|
||||||
|
delete submitData.stuList
|
||||||
|
}
|
||||||
|
|
||||||
|
if (operType.value === 'add') {
|
||||||
|
await addObj(submitData)
|
||||||
|
useMessage().success('批量新增成功')
|
||||||
|
} else {
|
||||||
|
await editObj(submitData)
|
||||||
|
useMessage().success('编辑成功')
|
||||||
|
}
|
||||||
|
visible.value = false
|
||||||
|
emit('refresh')
|
||||||
|
} catch (err: any) {
|
||||||
|
useMessage().error(err.msg || (operType.value === 'add' ? '批量新增失败' : '编辑失败'))
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取学年列表
|
||||||
|
const getSchoolYearList = async () => {
|
||||||
|
try {
|
||||||
|
const res = await queryAllSchoolYear()
|
||||||
|
if (res.data) {
|
||||||
|
schoolYearList.value = Array.isArray(res.data) ? res.data : []
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取学年列表失败', 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) {
|
||||||
|
console.error('获取学期字典失败', err)
|
||||||
|
schoolTermList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取班级列表
|
||||||
|
const getClassListData = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getClassList()
|
||||||
|
if (res.data) {
|
||||||
|
classList.value = Array.isArray(res.data) ? res.data : []
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取班级列表失败', err)
|
||||||
|
classList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取异动类型字典
|
||||||
|
const getTurnoverTypeDict = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getDicts('turnover_type')
|
||||||
|
if (res.data) {
|
||||||
|
turnoverTypeList.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) {
|
||||||
|
console.error('获取异动类型字典失败', err)
|
||||||
|
turnoverTypeList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取转制类型字典
|
||||||
|
const getTurnYearDict = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getDicts('turn_year_type')
|
||||||
|
if (res.data) {
|
||||||
|
turnYearList.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) {
|
||||||
|
console.error('获取转制类型字典失败', err)
|
||||||
|
turnYearList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化
|
||||||
|
onMounted(() => {
|
||||||
|
getSchoolYearList()
|
||||||
|
getSchoolTermDict()
|
||||||
|
getClassListData()
|
||||||
|
getTurnoverTypeDict()
|
||||||
|
getTurnYearDict()
|
||||||
|
})
|
||||||
|
|
||||||
|
// 暴露方法给父组件
|
||||||
|
defineExpose({
|
||||||
|
openDialog
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
433
src/views/stuwork/stuturnover/index.vue
Normal file
433
src/views/stuwork/stuturnover/index.vue
Normal file
@@ -0,0 +1,433 @@
|
|||||||
|
<template>
|
||||||
|
<div class="layout-padding">
|
||||||
|
<div class="layout-padding-auto layout-padding-view">
|
||||||
|
<!-- 搜索表单 -->
|
||||||
|
<el-row v-show="showSearch">
|
||||||
|
<el-form :model="searchForm" ref="searchFormRef" :inline="true" @keyup.enter="handleSearch">
|
||||||
|
<el-form-item label="学年" prop="schoolYear">
|
||||||
|
<el-select
|
||||||
|
v-model="searchForm.schoolYear"
|
||||||
|
placeholder="请选择学年"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
style="width: 200px">
|
||||||
|
<el-option
|
||||||
|
v-for="item in schoolYearList"
|
||||||
|
:key="item.year"
|
||||||
|
:label="item.year"
|
||||||
|
:value="item.year">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="学期" prop="schoolTerm">
|
||||||
|
<el-select
|
||||||
|
v-model="searchForm.schoolTerm"
|
||||||
|
placeholder="请选择学期"
|
||||||
|
clearable
|
||||||
|
style="width: 200px">
|
||||||
|
<el-option
|
||||||
|
v-for="item in schoolTermList"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="学院" prop="deptCode">
|
||||||
|
<el-select
|
||||||
|
v-model="searchForm.deptCode"
|
||||||
|
placeholder="请选择学院"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
style="width: 200px">
|
||||||
|
<el-option
|
||||||
|
v-for="item in deptList"
|
||||||
|
:key="item.deptCode"
|
||||||
|
:label="item.deptName"
|
||||||
|
:value="item.deptCode">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="原班级" prop="oldClassCode">
|
||||||
|
<el-select
|
||||||
|
v-model="searchForm.oldClassCode"
|
||||||
|
placeholder="请选择原班级"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
style="width: 200px">
|
||||||
|
<el-option
|
||||||
|
v-for="item in classList"
|
||||||
|
:key="item.classCode"
|
||||||
|
:label="item.classNo"
|
||||||
|
:value="item.classCode">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="学号" prop="stuNo">
|
||||||
|
<el-input
|
||||||
|
v-model="searchForm.stuNo"
|
||||||
|
placeholder="请输入学号"
|
||||||
|
clearable
|
||||||
|
style="width: 200px" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="姓名" prop="realName">
|
||||||
|
<el-input
|
||||||
|
v-model="searchForm.realName"
|
||||||
|
placeholder="请输入姓名"
|
||||||
|
clearable
|
||||||
|
style="width: 200px" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="异动类型" prop="turnoverType">
|
||||||
|
<el-select
|
||||||
|
v-model="searchForm.turnoverType"
|
||||||
|
placeholder="请选择异动类型"
|
||||||
|
clearable
|
||||||
|
style="width: 200px">
|
||||||
|
<el-option
|
||||||
|
v-for="item in turnoverTypeList"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" plain icon="Search" @click="handleSearch">查询</el-button>
|
||||||
|
<el-button icon="Refresh" @click="handleReset">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<!-- 操作按钮 -->
|
||||||
|
<el-row>
|
||||||
|
<div class="mb8" style="width: 100%">
|
||||||
|
<el-button
|
||||||
|
icon="FolderAdd"
|
||||||
|
type="primary"
|
||||||
|
class="ml10"
|
||||||
|
@click="formDialogRef.openDialog()">
|
||||||
|
批量新增异动
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
icon="Download"
|
||||||
|
type="success"
|
||||||
|
class="ml10"
|
||||||
|
@click="handleExport">
|
||||||
|
导 出
|
||||||
|
</el-button>
|
||||||
|
<right-toolbar
|
||||||
|
v-model:showSearch="showSearch"
|
||||||
|
class="ml10 mr20"
|
||||||
|
style="float: right;"
|
||||||
|
@queryTable="getDataList">
|
||||||
|
</right-toolbar>
|
||||||
|
</div>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<!-- 表格 -->
|
||||||
|
<el-table
|
||||||
|
:data="state.dataList"
|
||||||
|
v-loading="state.loading"
|
||||||
|
border
|
||||||
|
:cell-style="tableStyle.cellStyle"
|
||||||
|
:header-cell-style="tableStyle.headerCellStyle">
|
||||||
|
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||||
|
<el-table-column prop="schoolYear" label="学年" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="schoolTerm" label="学期" show-overflow-tooltip align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ formatSchoolTerm(scope.row.schoolTerm) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="deptName" label="学院" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="oldClassNo" label="原班级" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="newClassNo" label="现班级" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="stuNo" label="学号" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="realName" label="姓名" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="turnoverDate" label="异动时间" show-overflow-tooltip align="center" width="180">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ scope.row.turnoverDate ? formatDate(scope.row.turnoverDate) : '-' }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="turnoverType" label="异动类型" show-overflow-tooltip align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ formatTurnoverType(scope.row.turnoverType) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="turnYear" label="转制类型" show-overflow-tooltip align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ formatTurnYear(scope.row.turnYear) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="remarks" label="异动原因" show-overflow-tooltip align="center" min-width="150" />
|
||||||
|
<el-table-column label="操作" width="150" align="center" fixed="right">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button
|
||||||
|
icon="Edit"
|
||||||
|
text
|
||||||
|
type="primary"
|
||||||
|
@click="handleEdit(scope.row)">
|
||||||
|
编辑
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
icon="Delete"
|
||||||
|
text
|
||||||
|
type="danger"
|
||||||
|
@click="handleDelete(scope.row)">
|
||||||
|
删除
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<!-- 分页 -->
|
||||||
|
<pagination
|
||||||
|
@size-change="sizeChangeHandle"
|
||||||
|
@current-change="currentChangeHandle"
|
||||||
|
v-bind="state.pagination" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 批量新增/编辑表单弹窗 -->
|
||||||
|
<form-dialog ref="formDialogRef" @refresh="getDataList" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts" name="StuTurnover">
|
||||||
|
import { reactive, ref, onMounted } from 'vue'
|
||||||
|
import { BasicTableProps, useTable } from "/@/hooks/table";
|
||||||
|
import { fetchList, delObj, exportData } from "/@/api/stuwork/stuturnover";
|
||||||
|
import { queryAllSchoolYear } from "/@/api/basic/basicyear";
|
||||||
|
import { getDicts } from "/@/api/admin/dict";
|
||||||
|
import { getDeptListByLevelTwo } from "/@/api/basic/basicdept";
|
||||||
|
import { list as getClassList } from "/@/api/basic/basicclass";
|
||||||
|
import { useMessage, useMessageBox } from "/@/hooks/message";
|
||||||
|
import FormDialog from './form.vue'
|
||||||
|
|
||||||
|
// 定义变量内容
|
||||||
|
const searchFormRef = ref()
|
||||||
|
const showSearch = ref(true)
|
||||||
|
const schoolYearList = ref<any[]>([])
|
||||||
|
const schoolTermList = ref<any[]>([])
|
||||||
|
const deptList = ref<any[]>([])
|
||||||
|
const classList = ref<any[]>([])
|
||||||
|
const turnoverTypeList = ref<any[]>([])
|
||||||
|
const turnYearList = ref<any[]>([])
|
||||||
|
const formDialogRef = ref()
|
||||||
|
|
||||||
|
// 搜索表单
|
||||||
|
const searchForm = reactive({
|
||||||
|
schoolYear: '',
|
||||||
|
schoolTerm: '',
|
||||||
|
deptCode: '',
|
||||||
|
oldClassCode: '',
|
||||||
|
stuNo: '',
|
||||||
|
realName: '',
|
||||||
|
turnoverType: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
// 配置 useTable
|
||||||
|
const state: BasicTableProps = reactive<BasicTableProps>({
|
||||||
|
queryForm: searchForm,
|
||||||
|
pageList: fetchList,
|
||||||
|
props: {
|
||||||
|
item: 'records',
|
||||||
|
totalCount: 'total'
|
||||||
|
},
|
||||||
|
createdIsNeed: true
|
||||||
|
})
|
||||||
|
|
||||||
|
// table hook
|
||||||
|
const {
|
||||||
|
getDataList,
|
||||||
|
currentChangeHandle,
|
||||||
|
sizeChangeHandle,
|
||||||
|
tableStyle
|
||||||
|
} = useTable(state)
|
||||||
|
|
||||||
|
// 格式化学期
|
||||||
|
const formatSchoolTerm = (value: string | number) => {
|
||||||
|
if (value === null || value === undefined || value === '') {
|
||||||
|
return '-'
|
||||||
|
}
|
||||||
|
const dictItem = schoolTermList.value.find(item => item.value == value)
|
||||||
|
return dictItem ? dictItem.label : value
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化日期
|
||||||
|
const formatDate = (dateStr: string) => {
|
||||||
|
if (!dateStr) return '-'
|
||||||
|
// 如果包含时间部分,只显示日期部分
|
||||||
|
if (dateStr.includes(' ')) {
|
||||||
|
return dateStr.split(' ')[0]
|
||||||
|
}
|
||||||
|
return dateStr
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化异动类型
|
||||||
|
const formatTurnoverType = (value: string) => {
|
||||||
|
if (!value) return '-'
|
||||||
|
const item = turnoverTypeList.value.find((item: any) => item.value === value)
|
||||||
|
return item ? item.label : value
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化转制类型
|
||||||
|
const formatTurnYear = (value: string) => {
|
||||||
|
if (!value) return '-'
|
||||||
|
const item = turnYearList.value.find((item: any) => item.value === value)
|
||||||
|
return item ? item.label : value
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询
|
||||||
|
const handleSearch = () => {
|
||||||
|
getDataList()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置
|
||||||
|
const handleReset = () => {
|
||||||
|
searchFormRef.value?.resetFields()
|
||||||
|
searchForm.schoolYear = ''
|
||||||
|
searchForm.schoolTerm = ''
|
||||||
|
searchForm.deptCode = ''
|
||||||
|
searchForm.oldClassCode = ''
|
||||||
|
searchForm.stuNo = ''
|
||||||
|
searchForm.realName = ''
|
||||||
|
searchForm.turnoverType = ''
|
||||||
|
getDataList()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 编辑
|
||||||
|
const handleEdit = (row: any) => {
|
||||||
|
formDialogRef.value?.openDialog('edit', row)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除
|
||||||
|
const handleDelete = async (row: any) => {
|
||||||
|
try {
|
||||||
|
await useMessageBox().confirm('确定要删除这条记录吗?')
|
||||||
|
await delObj([row.id])
|
||||||
|
useMessage().success('删除成功')
|
||||||
|
getDataList()
|
||||||
|
} catch (err: any) {
|
||||||
|
if (err !== 'cancel') {
|
||||||
|
useMessage().error(err.msg || '删除失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 导出
|
||||||
|
const handleExport = async () => {
|
||||||
|
try {
|
||||||
|
const res = await exportData(searchForm)
|
||||||
|
// 处理返回的文件流
|
||||||
|
const blob = new Blob([res.data])
|
||||||
|
const elink = document.createElement('a')
|
||||||
|
elink.download = '学籍异动.xlsx'
|
||||||
|
elink.style.display = 'none'
|
||||||
|
elink.href = URL.createObjectURL(blob)
|
||||||
|
document.body.appendChild(elink)
|
||||||
|
elink.click()
|
||||||
|
URL.revokeObjectURL(elink.href)
|
||||||
|
document.body.removeChild(elink)
|
||||||
|
useMessage().success('导出成功')
|
||||||
|
} catch (err: any) {
|
||||||
|
useMessage().error(err.msg || '导出失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取学年列表
|
||||||
|
const getSchoolYearList = async () => {
|
||||||
|
try {
|
||||||
|
const res = await queryAllSchoolYear()
|
||||||
|
if (res.data) {
|
||||||
|
schoolYearList.value = Array.isArray(res.data) ? res.data : []
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取学年列表失败', 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) {
|
||||||
|
console.error('获取学期字典失败', err)
|
||||||
|
schoolTermList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取学院列表
|
||||||
|
const getDeptListData = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getDeptListByLevelTwo()
|
||||||
|
if (res.data) {
|
||||||
|
deptList.value = Array.isArray(res.data) ? res.data : []
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取学院列表失败', err)
|
||||||
|
deptList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取班级列表
|
||||||
|
const getClassListData = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getClassList()
|
||||||
|
if (res.data) {
|
||||||
|
classList.value = Array.isArray(res.data) ? res.data : []
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取班级列表失败', err)
|
||||||
|
classList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取异动类型字典
|
||||||
|
const getTurnoverTypeDict = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getDicts('turnover_type')
|
||||||
|
if (res.data) {
|
||||||
|
turnoverTypeList.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) {
|
||||||
|
console.error('获取异动类型字典失败', err)
|
||||||
|
turnoverTypeList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取转制类型字典
|
||||||
|
const getTurnYearDict = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getDicts('turn_year_type')
|
||||||
|
if (res.data) {
|
||||||
|
turnYearList.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) {
|
||||||
|
console.error('获取转制类型字典失败', err)
|
||||||
|
turnYearList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化
|
||||||
|
onMounted(() => {
|
||||||
|
getSchoolYearList()
|
||||||
|
getSchoolTermDict()
|
||||||
|
getDeptListData()
|
||||||
|
getClassListData()
|
||||||
|
getTurnoverTypeDict()
|
||||||
|
getTurnYearDict()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
128
src/views/stuwork/teachbuilding/form.vue
Normal file
128
src/views/stuwork/teachbuilding/form.vue
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
:title="form.id ? '编辑' : '新增'"
|
||||||
|
v-model="visible"
|
||||||
|
:width="600"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
draggable>
|
||||||
|
<el-form
|
||||||
|
ref="dataFormRef"
|
||||||
|
:model="form"
|
||||||
|
:rules="dataRules"
|
||||||
|
label-width="100px"
|
||||||
|
v-loading="loading">
|
||||||
|
<el-form-item label="楼号" prop="buildingNo">
|
||||||
|
<el-input-number
|
||||||
|
v-model="form.buildingNo"
|
||||||
|
:min="1"
|
||||||
|
placeholder="请输入楼号"
|
||||||
|
style="width: 100%" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="备注" prop="remarks">
|
||||||
|
<el-input
|
||||||
|
v-model="form.remarks"
|
||||||
|
type="textarea"
|
||||||
|
:rows="4"
|
||||||
|
placeholder="请输入备注" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click="visible = false">取 消</el-button>
|
||||||
|
<el-button type="primary" @click="onSubmit" :disabled="loading">确 认</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts" name="TeachBuildingFormDialog">
|
||||||
|
import { ref, reactive, nextTick } from 'vue'
|
||||||
|
import { useMessage } from '/@/hooks/message'
|
||||||
|
import { addObj, editObj, getDetail } from '/@/api/stuwork/teachbuilding'
|
||||||
|
|
||||||
|
const emit = defineEmits(['refresh'])
|
||||||
|
|
||||||
|
// 定义变量内容
|
||||||
|
const dataFormRef = ref()
|
||||||
|
const visible = ref(false)
|
||||||
|
const loading = ref(false)
|
||||||
|
const operType = ref('add') // add 或 edit
|
||||||
|
|
||||||
|
// 提交表单数据
|
||||||
|
const form = reactive({
|
||||||
|
id: '',
|
||||||
|
buildingNo: undefined as number | undefined,
|
||||||
|
remarks: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
// 定义校验规则
|
||||||
|
const dataRules = {
|
||||||
|
buildingNo: [
|
||||||
|
{ required: true, message: '请输入楼号', trigger: 'blur' },
|
||||||
|
{ type: 'number', min: 1, message: '楼号必须大于0', trigger: 'blur' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 打开弹窗
|
||||||
|
const openDialog = (type: string = 'add', row?: any) => {
|
||||||
|
visible.value = true
|
||||||
|
operType.value = type
|
||||||
|
|
||||||
|
// 重置表单数据
|
||||||
|
nextTick(() => {
|
||||||
|
dataFormRef.value?.resetFields()
|
||||||
|
form.id = ''
|
||||||
|
form.buildingNo = undefined
|
||||||
|
form.remarks = ''
|
||||||
|
|
||||||
|
// 编辑时填充数据
|
||||||
|
if (type === 'edit' && row) {
|
||||||
|
form.id = row.id
|
||||||
|
form.buildingNo = row.buildingNo
|
||||||
|
form.remarks = row.remarks || ''
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提交表单
|
||||||
|
const onSubmit = async () => {
|
||||||
|
if (!dataFormRef.value) return
|
||||||
|
|
||||||
|
await dataFormRef.value.validate(async (valid: boolean) => {
|
||||||
|
if (!valid) return
|
||||||
|
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
if (operType.value === 'add') {
|
||||||
|
await addObj({
|
||||||
|
buildingNo: form.buildingNo,
|
||||||
|
remarks: form.remarks
|
||||||
|
})
|
||||||
|
useMessage().success('新增成功')
|
||||||
|
} else {
|
||||||
|
await editObj({
|
||||||
|
id: form.id,
|
||||||
|
buildingNo: form.buildingNo,
|
||||||
|
remarks: form.remarks
|
||||||
|
})
|
||||||
|
useMessage().success('编辑成功')
|
||||||
|
}
|
||||||
|
visible.value = false
|
||||||
|
emit('refresh')
|
||||||
|
} catch (err: any) {
|
||||||
|
useMessage().error(err.msg || (operType.value === 'add' ? '新增失败' : '编辑失败'))
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 暴露方法
|
||||||
|
defineExpose({
|
||||||
|
openDialog
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
</style>
|
||||||
|
|
||||||
116
src/views/stuwork/teachbuilding/index.vue
Normal file
116
src/views/stuwork/teachbuilding/index.vue
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
<template>
|
||||||
|
<div class="layout-padding">
|
||||||
|
<div class="layout-padding-auto layout-padding-view">
|
||||||
|
<!-- 操作按钮 -->
|
||||||
|
<el-row>
|
||||||
|
<div class="mb8" style="width: 100%">
|
||||||
|
<el-button
|
||||||
|
icon="Plus"
|
||||||
|
type="primary"
|
||||||
|
class="ml10"
|
||||||
|
@click="formDialogRef.openDialog()">
|
||||||
|
新增
|
||||||
|
</el-button>
|
||||||
|
<right-toolbar
|
||||||
|
class="ml10 mr20"
|
||||||
|
style="float: right;"
|
||||||
|
@queryTable="getDataList">
|
||||||
|
</right-toolbar>
|
||||||
|
</div>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<!-- 表格 -->
|
||||||
|
<el-table
|
||||||
|
:data="state.dataList"
|
||||||
|
v-loading="state.loading"
|
||||||
|
border
|
||||||
|
:cell-style="tableStyle.cellStyle"
|
||||||
|
:header-cell-style="tableStyle.headerCellStyle">
|
||||||
|
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||||
|
<el-table-column prop="buildingNo" label="楼号" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="remarks" label="备注" show-overflow-tooltip align="center" min-width="200" />
|
||||||
|
<el-table-column label="操作" width="150" align="center" fixed="right">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button
|
||||||
|
icon="Edit"
|
||||||
|
text
|
||||||
|
type="primary"
|
||||||
|
@click="handleEdit(scope.row)">
|
||||||
|
编辑
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
icon="Delete"
|
||||||
|
text
|
||||||
|
type="danger"
|
||||||
|
@click="handleDelete(scope.row)">
|
||||||
|
删除
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<!-- 分页 -->
|
||||||
|
<pagination
|
||||||
|
@size-change="sizeChangeHandle"
|
||||||
|
@current-change="currentChangeHandle"
|
||||||
|
v-bind="state.pagination" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 新增/编辑表单弹窗 -->
|
||||||
|
<form-dialog ref="formDialogRef" @refresh="getDataList" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts" name="TeachBuilding">
|
||||||
|
import { reactive, ref, onMounted } from 'vue'
|
||||||
|
import { BasicTableProps, useTable } from "/@/hooks/table";
|
||||||
|
import { fetchList, delObj } from "/@/api/stuwork/teachbuilding";
|
||||||
|
import { useMessage, useMessageBox } from "/@/hooks/message";
|
||||||
|
import FormDialog from './form.vue'
|
||||||
|
|
||||||
|
// 定义变量内容
|
||||||
|
const formDialogRef = ref()
|
||||||
|
|
||||||
|
// 配置 useTable
|
||||||
|
const state: BasicTableProps = reactive<BasicTableProps>({
|
||||||
|
queryForm: {},
|
||||||
|
pageList: fetchList,
|
||||||
|
props: {
|
||||||
|
item: 'records',
|
||||||
|
totalCount: 'total'
|
||||||
|
},
|
||||||
|
createdIsNeed: true
|
||||||
|
})
|
||||||
|
|
||||||
|
// table hook
|
||||||
|
const {
|
||||||
|
getDataList,
|
||||||
|
currentChangeHandle,
|
||||||
|
sizeChangeHandle,
|
||||||
|
tableStyle
|
||||||
|
} = useTable(state)
|
||||||
|
|
||||||
|
// 编辑
|
||||||
|
const handleEdit = (row: any) => {
|
||||||
|
formDialogRef.value?.openDialog('edit', row)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除
|
||||||
|
const handleDelete = async (row: any) => {
|
||||||
|
const { confirm } = useMessageBox()
|
||||||
|
try {
|
||||||
|
await confirm('确定要删除该教学楼吗?')
|
||||||
|
await delObj([row.id])
|
||||||
|
useMessage().success('删除成功')
|
||||||
|
getDataList()
|
||||||
|
} catch (err: any) {
|
||||||
|
if (err !== 'cancel') {
|
||||||
|
useMessage().error(err.msg || '删除失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
</style>
|
||||||
|
|
||||||
150
src/views/stuwork/teachclassroom/batch.vue
Normal file
150
src/views/stuwork/teachclassroom/batch.vue
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
title="批量设置"
|
||||||
|
v-model="visible"
|
||||||
|
:width="600"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
draggable>
|
||||||
|
<el-form
|
||||||
|
ref="dataFormRef"
|
||||||
|
:model="form"
|
||||||
|
:rules="dataRules"
|
||||||
|
label-width="100px"
|
||||||
|
v-loading="loading">
|
||||||
|
<el-alert
|
||||||
|
title="提示"
|
||||||
|
type="info"
|
||||||
|
:closable="false"
|
||||||
|
style="margin-bottom: 20px;">
|
||||||
|
<template #default>
|
||||||
|
<div>已选择 {{ selectedCount }} 条教室记录,请选择要设置的二级学院</div>
|
||||||
|
</template>
|
||||||
|
</el-alert>
|
||||||
|
<el-form-item label="二级学院" prop="deptCode">
|
||||||
|
<el-select
|
||||||
|
v-model="form.deptCode"
|
||||||
|
placeholder="请选择二级学院"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
style="width: 100%">
|
||||||
|
<el-option
|
||||||
|
v-for="item in deptList"
|
||||||
|
:key="item.deptCode"
|
||||||
|
:label="item.deptName"
|
||||||
|
:value="item.deptCode">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click="visible = false">取 消</el-button>
|
||||||
|
<el-button type="primary" @click="onSubmit" :disabled="loading">确 认</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts" name="TeachClassroomBatchDialog">
|
||||||
|
import { ref, reactive, nextTick, onMounted, computed } from 'vue'
|
||||||
|
import { useMessage } from '/@/hooks/message'
|
||||||
|
import { batchSet } from '/@/api/stuwork/teachclassroom'
|
||||||
|
import { getDeptListByLevelTwo } from '/@/api/basic/basicdept'
|
||||||
|
|
||||||
|
const emit = defineEmits(['refresh'])
|
||||||
|
|
||||||
|
// 定义变量内容
|
||||||
|
const dataFormRef = ref()
|
||||||
|
const visible = ref(false)
|
||||||
|
const loading = ref(false)
|
||||||
|
const deptList = ref<any[]>([])
|
||||||
|
const selectedRows = ref<any[]>([])
|
||||||
|
|
||||||
|
// 提交表单数据
|
||||||
|
const form = reactive({
|
||||||
|
deptCode: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
// 选中数量
|
||||||
|
const selectedCount = computed(() => selectedRows.value.length)
|
||||||
|
|
||||||
|
// 定义校验规则
|
||||||
|
const dataRules = {
|
||||||
|
deptCode: [
|
||||||
|
{ required: true, message: '请选择二级学院', trigger: 'change' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 打开弹窗
|
||||||
|
const openDialog = (rows: any[]) => {
|
||||||
|
selectedRows.value = rows
|
||||||
|
visible.value = true
|
||||||
|
resetForm()
|
||||||
|
nextTick(() => {
|
||||||
|
dataFormRef.value?.resetFields()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置表单
|
||||||
|
const resetForm = () => {
|
||||||
|
form.deptCode = ''
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提交表单
|
||||||
|
const onSubmit = async () => {
|
||||||
|
if (!dataFormRef.value) return
|
||||||
|
|
||||||
|
await dataFormRef.value.validate(async (valid: boolean) => {
|
||||||
|
if (!valid) return
|
||||||
|
|
||||||
|
if (selectedRows.value.length === 0) {
|
||||||
|
useMessage().warning('请先选择要设置的教室')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const ids = selectedRows.value.map((row: any) => row.id)
|
||||||
|
await batchSet({
|
||||||
|
ids: ids,
|
||||||
|
deptCode: form.deptCode
|
||||||
|
})
|
||||||
|
useMessage().success('批量设置成功')
|
||||||
|
visible.value = false
|
||||||
|
selectedRows.value = []
|
||||||
|
emit('refresh')
|
||||||
|
} catch (err: any) {
|
||||||
|
useMessage().error(err.msg || '批量设置失败')
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取系部列表
|
||||||
|
const getDeptListData = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getDeptListByLevelTwo()
|
||||||
|
if (res.data) {
|
||||||
|
deptList.value = Array.isArray(res.data) ? res.data : []
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取系部列表失败', err)
|
||||||
|
deptList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化
|
||||||
|
onMounted(() => {
|
||||||
|
getDeptListData()
|
||||||
|
})
|
||||||
|
|
||||||
|
// 暴露方法
|
||||||
|
defineExpose({
|
||||||
|
openDialog
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
</style>
|
||||||
|
|
||||||
195
src/views/stuwork/teachclassroom/form.vue
Normal file
195
src/views/stuwork/teachclassroom/form.vue
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
:title="form.id ? '编辑' : '新增'"
|
||||||
|
v-model="visible"
|
||||||
|
:width="600"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
draggable>
|
||||||
|
<el-form
|
||||||
|
ref="dataFormRef"
|
||||||
|
:model="form"
|
||||||
|
:rules="dataRules"
|
||||||
|
label-width="100px"
|
||||||
|
v-loading="loading">
|
||||||
|
<el-form-item label="学院" prop="deptCode">
|
||||||
|
<el-select
|
||||||
|
v-model="form.deptCode"
|
||||||
|
placeholder="请选择学院"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
style="width: 100%">
|
||||||
|
<el-option
|
||||||
|
v-for="item in deptList"
|
||||||
|
:key="item.deptCode"
|
||||||
|
:label="item.deptName"
|
||||||
|
:value="item.deptCode">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="楼号" prop="buildingNo">
|
||||||
|
<el-select
|
||||||
|
v-model="form.buildingNo"
|
||||||
|
placeholder="请选择楼号"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
style="width: 100%">
|
||||||
|
<el-option
|
||||||
|
v-for="item in buildingList"
|
||||||
|
:key="item.buildingNo"
|
||||||
|
:label="item.buildingNo"
|
||||||
|
:value="item.buildingNo">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="教室位置" prop="position">
|
||||||
|
<el-input
|
||||||
|
v-model="form.position"
|
||||||
|
placeholder="请输入教室位置" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click="visible = false">取 消</el-button>
|
||||||
|
<el-button type="primary" @click="onSubmit" :disabled="loading">确 认</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts" name="TeachClassroomFormDialog">
|
||||||
|
import { ref, reactive, nextTick, onMounted } from 'vue'
|
||||||
|
import { useMessage } from '/@/hooks/message'
|
||||||
|
import { addObj, editObj } from '/@/api/stuwork/teachclassroom'
|
||||||
|
import { getDeptListByLevelTwo } from '/@/api/basic/basicdept'
|
||||||
|
import { getBuildingList } from '/@/api/stuwork/teachbuilding'
|
||||||
|
|
||||||
|
const emit = defineEmits(['refresh'])
|
||||||
|
|
||||||
|
// 定义变量内容
|
||||||
|
const dataFormRef = ref()
|
||||||
|
const visible = ref(false)
|
||||||
|
const loading = ref(false)
|
||||||
|
const deptList = ref<any[]>([])
|
||||||
|
const buildingList = ref<any[]>([])
|
||||||
|
const operType = ref('add') // add 或 edit
|
||||||
|
|
||||||
|
// 提交表单数据
|
||||||
|
const form = reactive({
|
||||||
|
id: '',
|
||||||
|
deptCode: '',
|
||||||
|
buildingNo: '',
|
||||||
|
position: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
// 定义校验规则
|
||||||
|
const dataRules = {
|
||||||
|
deptCode: [
|
||||||
|
{ required: true, message: '请选择学院', trigger: 'change' }
|
||||||
|
],
|
||||||
|
buildingNo: [
|
||||||
|
{ required: true, message: '请选择楼号', trigger: 'change' }
|
||||||
|
],
|
||||||
|
position: [
|
||||||
|
{ required: true, message: '请输入教室位置', trigger: 'blur' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 打开弹窗
|
||||||
|
const openDialog = (type: string = 'add', row?: any) => {
|
||||||
|
visible.value = true
|
||||||
|
operType.value = type
|
||||||
|
|
||||||
|
// 重置表单数据
|
||||||
|
nextTick(() => {
|
||||||
|
dataFormRef.value?.resetFields()
|
||||||
|
form.id = ''
|
||||||
|
form.deptCode = ''
|
||||||
|
form.buildingNo = ''
|
||||||
|
form.position = ''
|
||||||
|
|
||||||
|
// 编辑时填充数据
|
||||||
|
if (type === 'edit' && row) {
|
||||||
|
form.id = row.id
|
||||||
|
form.deptCode = row.deptCode || ''
|
||||||
|
form.buildingNo = row.buildingNo || ''
|
||||||
|
form.position = row.position || ''
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提交表单
|
||||||
|
const onSubmit = async () => {
|
||||||
|
if (!dataFormRef.value) return
|
||||||
|
|
||||||
|
await dataFormRef.value.validate(async (valid: boolean) => {
|
||||||
|
if (!valid) return
|
||||||
|
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
if (operType.value === 'add') {
|
||||||
|
await addObj({
|
||||||
|
deptCode: form.deptCode,
|
||||||
|
buildingNo: form.buildingNo,
|
||||||
|
position: form.position
|
||||||
|
})
|
||||||
|
useMessage().success('新增成功')
|
||||||
|
} else {
|
||||||
|
await editObj({
|
||||||
|
id: form.id,
|
||||||
|
deptCode: form.deptCode,
|
||||||
|
buildingNo: form.buildingNo,
|
||||||
|
position: form.position
|
||||||
|
})
|
||||||
|
useMessage().success('编辑成功')
|
||||||
|
}
|
||||||
|
visible.value = false
|
||||||
|
emit('refresh')
|
||||||
|
} catch (err: any) {
|
||||||
|
useMessage().error(err.msg || (operType.value === 'add' ? '新增失败' : '编辑失败'))
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取系部列表
|
||||||
|
const getDeptListData = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getDeptListByLevelTwo()
|
||||||
|
if (res.data) {
|
||||||
|
deptList.value = Array.isArray(res.data) ? res.data : []
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取系部列表失败', err)
|
||||||
|
deptList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取楼号列表
|
||||||
|
const getBuildingListData = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getBuildingList()
|
||||||
|
if (res.data) {
|
||||||
|
buildingList.value = Array.isArray(res.data) ? res.data : []
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取楼号列表失败', err)
|
||||||
|
buildingList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化
|
||||||
|
onMounted(() => {
|
||||||
|
getDeptListData()
|
||||||
|
getBuildingListData()
|
||||||
|
})
|
||||||
|
|
||||||
|
// 暴露方法
|
||||||
|
defineExpose({
|
||||||
|
openDialog
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
</style>
|
||||||
|
|
||||||
244
src/views/stuwork/teachclassroom/index.vue
Normal file
244
src/views/stuwork/teachclassroom/index.vue
Normal file
@@ -0,0 +1,244 @@
|
|||||||
|
<template>
|
||||||
|
<div class="layout-padding">
|
||||||
|
<div class="layout-padding-auto layout-padding-view">
|
||||||
|
<!-- 搜索表单 -->
|
||||||
|
<el-row v-show="showSearch">
|
||||||
|
<el-form :model="searchForm" ref="searchFormRef" :inline="true" @keyup.enter="handleSearch">
|
||||||
|
<el-form-item label="学院" prop="deptCode">
|
||||||
|
<el-select
|
||||||
|
v-model="searchForm.deptCode"
|
||||||
|
placeholder="请选择学院"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
style="width: 200px">
|
||||||
|
<el-option
|
||||||
|
v-for="item in deptList"
|
||||||
|
:key="item.deptCode"
|
||||||
|
:label="item.deptName"
|
||||||
|
:value="item.deptCode">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="楼号" prop="buildingNo">
|
||||||
|
<el-select
|
||||||
|
v-model="searchForm.buildingNo"
|
||||||
|
placeholder="请选择楼号"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
style="width: 200px">
|
||||||
|
<el-option
|
||||||
|
v-for="item in buildingList"
|
||||||
|
:key="item.buildingNo"
|
||||||
|
:label="item.buildingNo"
|
||||||
|
:value="item.buildingNo">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" plain icon="Search" @click="handleSearch">查询</el-button>
|
||||||
|
<el-button icon="Refresh" @click="handleReset">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<!-- 操作按钮 -->
|
||||||
|
<el-row>
|
||||||
|
<div class="mb8" style="width: 100%">
|
||||||
|
<el-button
|
||||||
|
icon="Plus"
|
||||||
|
type="primary"
|
||||||
|
class="ml10"
|
||||||
|
@click="formDialogRef.openDialog()">
|
||||||
|
新增
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
icon="Setting"
|
||||||
|
type="success"
|
||||||
|
class="ml10"
|
||||||
|
:disabled="selectedRows.length === 0"
|
||||||
|
@click="handleBatchSet">
|
||||||
|
批量设置
|
||||||
|
</el-button>
|
||||||
|
<right-toolbar
|
||||||
|
v-model:showSearch="showSearch"
|
||||||
|
class="ml10 mr20"
|
||||||
|
style="float: right;"
|
||||||
|
@queryTable="getDataList">
|
||||||
|
</right-toolbar>
|
||||||
|
</div>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<!-- 表格 -->
|
||||||
|
<el-table
|
||||||
|
:data="state.dataList"
|
||||||
|
v-loading="state.loading"
|
||||||
|
border
|
||||||
|
row-key="id"
|
||||||
|
:cell-style="tableStyle.cellStyle"
|
||||||
|
:header-cell-style="tableStyle.headerCellStyle"
|
||||||
|
@selection-change="handleSelectionChange">
|
||||||
|
<el-table-column type="selection" width="55" align="center" />
|
||||||
|
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||||
|
<el-table-column prop="deptName" label="学院" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="buildingNo" label="楼号" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="position" label="教室位置" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column label="操作" width="150" align="center" fixed="right">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button
|
||||||
|
icon="Edit"
|
||||||
|
text
|
||||||
|
type="primary"
|
||||||
|
@click="handleEdit(scope.row)">
|
||||||
|
编辑
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
icon="Delete"
|
||||||
|
text
|
||||||
|
type="danger"
|
||||||
|
@click="handleDelete(scope.row)">
|
||||||
|
删除
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<!-- 分页 -->
|
||||||
|
<pagination
|
||||||
|
@size-change="sizeChangeHandle"
|
||||||
|
@current-change="currentChangeHandle"
|
||||||
|
v-bind="state.pagination" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 新增/编辑表单弹窗 -->
|
||||||
|
<form-dialog ref="formDialogRef" @refresh="getDataList" />
|
||||||
|
|
||||||
|
<!-- 批量设置弹窗 -->
|
||||||
|
<batch-dialog ref="batchDialogRef" @refresh="getDataList" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts" name="TeachClassroom">
|
||||||
|
import { reactive, ref, onMounted } from 'vue'
|
||||||
|
import { BasicTableProps, useTable } from "/@/hooks/table";
|
||||||
|
import { fetchList, delObj } from "/@/api/stuwork/teachclassroom";
|
||||||
|
import { getDeptListByLevelTwo } from "/@/api/basic/basicdept";
|
||||||
|
import { getBuildingList } from "/@/api/stuwork/teachbuilding";
|
||||||
|
import { useMessage, useMessageBox } from "/@/hooks/message";
|
||||||
|
import FormDialog from './form.vue'
|
||||||
|
import BatchDialog from './batch.vue'
|
||||||
|
|
||||||
|
// 定义变量内容
|
||||||
|
const searchFormRef = ref()
|
||||||
|
const showSearch = ref(true)
|
||||||
|
const deptList = ref<any[]>([])
|
||||||
|
const buildingList = ref<any[]>([])
|
||||||
|
const formDialogRef = ref()
|
||||||
|
const batchDialogRef = ref()
|
||||||
|
const selectedRows = ref<any[]>([])
|
||||||
|
|
||||||
|
// 搜索表单
|
||||||
|
const searchForm = reactive({
|
||||||
|
deptCode: '',
|
||||||
|
buildingNo: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
// 配置 useTable
|
||||||
|
const state: BasicTableProps = reactive<BasicTableProps>({
|
||||||
|
queryForm: searchForm,
|
||||||
|
pageList: fetchList,
|
||||||
|
props: {
|
||||||
|
item: 'records',
|
||||||
|
totalCount: 'total'
|
||||||
|
},
|
||||||
|
createdIsNeed: true
|
||||||
|
})
|
||||||
|
|
||||||
|
// table hook
|
||||||
|
const {
|
||||||
|
getDataList,
|
||||||
|
currentChangeHandle,
|
||||||
|
sizeChangeHandle,
|
||||||
|
tableStyle
|
||||||
|
} = useTable(state)
|
||||||
|
|
||||||
|
// 查询
|
||||||
|
const handleSearch = () => {
|
||||||
|
getDataList()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置
|
||||||
|
const handleReset = () => {
|
||||||
|
searchFormRef.value?.resetFields()
|
||||||
|
getDataList()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 编辑
|
||||||
|
const handleEdit = (row: any) => {
|
||||||
|
formDialogRef.value?.openDialog('edit', row)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除
|
||||||
|
const handleDelete = async (row: any) => {
|
||||||
|
const { confirm } = useMessageBox()
|
||||||
|
try {
|
||||||
|
await confirm('确定要删除该教室吗?')
|
||||||
|
await delObj([row.id])
|
||||||
|
useMessage().success('删除成功')
|
||||||
|
getDataList()
|
||||||
|
} catch (err: any) {
|
||||||
|
if (err !== 'cancel') {
|
||||||
|
useMessage().error(err.msg || '删除失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 选择变化
|
||||||
|
const handleSelectionChange = (selection: any[]) => {
|
||||||
|
selectedRows.value = selection
|
||||||
|
}
|
||||||
|
|
||||||
|
// 批量设置
|
||||||
|
const handleBatchSet = () => {
|
||||||
|
if (selectedRows.value.length === 0) {
|
||||||
|
useMessage().warning('请先选择要设置的教室')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
batchDialogRef.value?.openDialog(selectedRows.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取系部列表
|
||||||
|
const getDeptListData = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getDeptListByLevelTwo()
|
||||||
|
if (res.data) {
|
||||||
|
deptList.value = Array.isArray(res.data) ? res.data : []
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取系部列表失败', err)
|
||||||
|
deptList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取楼号列表
|
||||||
|
const getBuildingListData = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getBuildingList()
|
||||||
|
if (res.data) {
|
||||||
|
buildingList.value = Array.isArray(res.data) ? res.data : []
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取楼号列表失败', err)
|
||||||
|
buildingList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化
|
||||||
|
onMounted(() => {
|
||||||
|
getDeptListData()
|
||||||
|
getBuildingListData()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
</style>
|
||||||
|
|
||||||
Reference in New Issue
Block a user