From d22438647e48bb346ffbde2c5f2cbb0498e33359 Mon Sep 17 00:00:00 2001 From: wuzhen <52326163@qq.com> Date: Wed, 13 Aug 2025 17:52:57 +0800 Subject: [PATCH] =?UTF-8?q?wuzhen=20=E4=BF=AE=E6=94=B9=E5=AE=9E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/InternshipInfoController.java | 56 ++++- .../zsjy/service/IInternshipInfoService.java | 26 +++ .../impl/InternshipInfoServiceImpl.java | 106 +++++++++ web/src/api/zsjy/internship.ts | 13 +- web/src/api/zsjy/types.ts | 205 ++++++++++++++++++ .../views/zsjy/internship/msgmanage/index.vue | 69 +++++- 6 files changed, 458 insertions(+), 17 deletions(-) diff --git a/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/controller/InternshipInfoController.java b/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/controller/InternshipInfoController.java index 57d13f77..48580eef 100644 --- a/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/controller/InternshipInfoController.java +++ b/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/controller/InternshipInfoController.java @@ -7,6 +7,8 @@ import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.web.core.BaseController; import org.dromara.zsjy.domain.vo.InternshipInfoVO; import org.dromara.zsjy.domain.bo.InternshipInfoQueryBO; +import org.dromara.zsjy.domain.bo.InternshipInfoAddBO; +import org.dromara.zsjy.domain.bo.InternshipInfoEditBO; import org.dromara.zsjy.service.IInternshipInfoService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -14,6 +16,8 @@ import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.constraints.NotEmpty; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.dromara.common.core.validate.AddGroup; +import org.dromara.common.core.validate.EditGroup; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import jakarta.servlet.http.HttpServletResponse; @@ -103,9 +107,21 @@ public class InternshipInfoController extends BaseController { @Operation(summary = "新增实习信息", description = "为学生新增实习信息") @SaCheckPermission("zsjy:internship:add") @PostMapping - public R add(@RequestBody @Validated Object addBO) { - // TODO: 实现新增实习信息功能 - return R.ok(); + public R add(@RequestBody @Validated(AddGroup.class) InternshipInfoAddBO addBO) { + log.info("新增实习信息请求,参数:{}", addBO); + try { + Boolean result = internshipInfoService.insertInternshipInfo(addBO); + if (result) { + log.info("新增实习信息成功,学生ID:{}", addBO.getStudentId()); + return R.ok(); + } else { + log.error("新增实习信息失败,学生ID:{}", addBO.getStudentId()); + return R.fail("新增实习信息失败"); + } + } catch (Exception e) { + log.error("新增实习信息异常,学生ID:{},错误信息:{}", addBO.getStudentId(), e.getMessage(), e); + return R.fail("新增实习信息失败:" + e.getMessage()); + } } /** @@ -114,9 +130,21 @@ public class InternshipInfoController extends BaseController { @Operation(summary = "修改实习信息", description = "修改学生实习信息") @SaCheckPermission("zsjy:internship:edit") @PutMapping - public R edit(@RequestBody @Validated Object editBO) { - // TODO: 实现修改实习信息功能 - return R.ok(); + public R edit(@RequestBody @Validated(EditGroup.class) InternshipInfoEditBO editBO) { + log.info("修改实习信息请求,参数:{}", editBO); + try { + Boolean result = internshipInfoService.updateInternshipInfo(editBO); + if (result) { + log.info("修改实习信息成功,实习信息ID:{}", editBO.getInternshipId()); + return R.ok(); + } else { + log.error("修改实习信息失败,实习信息ID:{}", editBO.getInternshipId()); + return R.fail("修改实习信息失败"); + } + } catch (Exception e) { + log.error("修改实习信息异常,实习信息ID:{},错误信息:{}", editBO.getInternshipId(), e.getMessage(), e); + return R.fail("修改实习信息失败:" + e.getMessage()); + } } /** @@ -127,7 +155,19 @@ public class InternshipInfoController extends BaseController { @DeleteMapping("/{internshipIds}") public R remove(@Parameter(description = "实习信息ID串") @PathVariable Long[] internshipIds) { - // TODO: 实现删除实习信息功能 - return R.ok(); + log.info("删除实习信息请求,IDs:{}", (Object) internshipIds); + try { + Boolean result = internshipInfoService.deleteInternshipInfo(internshipIds); + if (result) { + log.info("删除实习信息成功,IDs:{}", (Object) internshipIds); + return R.ok(); + } else { + log.error("删除实习信息失败,IDs:{}", (Object) internshipIds); + return R.fail("删除实习信息失败"); + } + } catch (Exception e) { + log.error("删除实习信息异常,IDs:{},错误信息:{}", internshipIds, e.getMessage(), e); + return R.fail("删除实习信息失败:" + e.getMessage()); + } } } diff --git a/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/service/IInternshipInfoService.java b/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/service/IInternshipInfoService.java index 60ab45c0..15065e21 100644 --- a/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/service/IInternshipInfoService.java +++ b/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/service/IInternshipInfoService.java @@ -4,6 +4,8 @@ import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.zsjy.domain.vo.InternshipInfoVO; import org.dromara.zsjy.domain.bo.InternshipInfoQueryBO; +import org.dromara.zsjy.domain.bo.InternshipInfoAddBO; +import org.dromara.zsjy.domain.bo.InternshipInfoEditBO; import jakarta.servlet.http.HttpServletResponse; import java.util.List; @@ -72,4 +74,28 @@ public interface IInternshipInfoService { * @param queryBO 查询条件(会被设置权限参数) */ void setDataPermission(InternshipInfoQueryBO queryBO); + + /** + * 新增实习信息 + * + * @param addBO 新增参数 + * @return 是否成功 + */ + Boolean insertInternshipInfo(InternshipInfoAddBO addBO); + + /** + * 修改实习信息 + * + * @param editBO 修改参数 + * @return 是否成功 + */ + Boolean updateInternshipInfo(InternshipInfoEditBO editBO); + + /** + * 删除实习信息 + * + * @param internshipIds 实习信息ID数组 + * @return 是否成功 + */ + Boolean deleteInternshipInfo(Long[] internshipIds); } diff --git a/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/service/impl/InternshipInfoServiceImpl.java b/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/service/impl/InternshipInfoServiceImpl.java index 8e5e1cb5..a24fba68 100644 --- a/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/service/impl/InternshipInfoServiceImpl.java +++ b/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/service/impl/InternshipInfoServiceImpl.java @@ -15,10 +15,15 @@ import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.satoken.utils.LoginHelper; import org.dromara.zsjy.domain.bo.InternshipInfoQueryBO; +import org.dromara.zsjy.domain.bo.InternshipInfoAddBO; +import org.dromara.zsjy.domain.bo.InternshipInfoEditBO; import org.dromara.zsjy.domain.vo.InternshipInfoVO; +import org.dromara.zsjy.domain.ZsjyInternshipInfo; import org.dromara.zsjy.mapper.InternshipInfoMapper; +import org.dromara.zsjy.mapper.ZsjyInternshipInfoMapper; import org.dromara.zsjy.service.IInternshipInfoService; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import jakarta.servlet.http.HttpServletResponse; import java.util.*; @@ -35,6 +40,7 @@ import java.util.*; public class InternshipInfoServiceImpl implements IInternshipInfoService { private final InternshipInfoMapper internshipInfoMapper; + private final ZsjyInternshipInfoMapper zsjyInternshipInfoMapper; /** * 查询学生实习信息分页列表(班主任专用) @@ -250,4 +256,104 @@ public class InternshipInfoServiceImpl implements IInternshipInfoService { default -> "未知状态"; }; } + + /** + * 新增实习信息 + * + * @param addBO 新增参数 + * @return 是否成功 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public Boolean insertInternshipInfo(InternshipInfoAddBO addBO) { + log.info("新增实习信息,参数:{}", addBO); + + // 检查该学生是否已经有实习信息 + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(ZsjyInternshipInfo::getStudentId, addBO.getStudentId()); + ZsjyInternshipInfo existingInfo = zsjyInternshipInfoMapper.selectOne(queryWrapper); + + if (ObjectUtil.isNotNull(existingInfo)) { + log.warn("学生ID:{} 已存在实习信息,不能重复添加", addBO.getStudentId()); + throw new RuntimeException("该学生已存在实习信息,不能重复添加"); + } + + // 构建实习信息实体 + ZsjyInternshipInfo internshipInfo = new ZsjyInternshipInfo(); + BeanUtil.copyProperties(addBO, internshipInfo); + + // 映射字段名称差异 + internshipInfo.setPositionName(addBO.getInternshipPosition()); + internshipInfo.setStartDate(addBO.getInternshipStartDate()); + internshipInfo.setEndDate(addBO.getInternshipEndDate()); + internshipInfo.setCompanyContact(addBO.getContactPersonName()); + internshipInfo.setCompanyPhone(addBO.getContactPersonPhone()); + internshipInfo.setStatus(addBO.getAgreementStatus()); + + // 插入数据 + int result = zsjyInternshipInfoMapper.insert(internshipInfo); + log.info("新增实习信息结果:{}", result > 0 ? "成功" : "失败"); + + return result > 0; + } + + /** + * 修改实习信息 + * + * @param editBO 修改参数 + * @return 是否成功 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public Boolean updateInternshipInfo(InternshipInfoEditBO editBO) { + log.info("修改实习信息,参数:{}", editBO); + + // 检查实习信息是否存在 + ZsjyInternshipInfo existingInfo = zsjyInternshipInfoMapper.selectById(editBO.getInternshipId()); + if (ObjectUtil.isNull(existingInfo)) { + log.warn("实习信息ID:{} 不存在", editBO.getInternshipId()); + throw new RuntimeException("实习信息不存在"); + } + + // 构建更新实体 + ZsjyInternshipInfo internshipInfo = new ZsjyInternshipInfo(); + BeanUtil.copyProperties(editBO, internshipInfo); + + // 映射字段名称差异 + internshipInfo.setPositionName(editBO.getInternshipPosition()); + internshipInfo.setStartDate(editBO.getInternshipStartDate()); + internshipInfo.setEndDate(editBO.getInternshipEndDate()); + internshipInfo.setCompanyContact(editBO.getContactPersonName()); + internshipInfo.setCompanyPhone(editBO.getContactPersonPhone()); + internshipInfo.setStatus(editBO.getAgreementStatus()); + + // 更新数据 + int result = zsjyInternshipInfoMapper.updateById(internshipInfo); + log.info("修改实习信息结果:{}", result > 0 ? "成功" : "失败"); + + return result > 0; + } + + /** + * 删除实习信息 + * + * @param internshipIds 实习信息ID数组 + * @return 是否成功 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public Boolean deleteInternshipInfo(Long[] internshipIds) { + log.info("删除实习信息,IDs:{}", Arrays.toString(internshipIds)); + + if (ObjectUtil.isEmpty(internshipIds)) { + log.warn("删除实习信息参数为空"); + throw new RuntimeException("删除参数不能为空"); + } + + // 批量删除(逻辑删除) + int result = zsjyInternshipInfoMapper.deleteBatchIds(Arrays.asList(internshipIds)); + log.info("删除实习信息结果:删除了 {} 条记录", result); + + return result > 0; + } } diff --git a/web/src/api/zsjy/internship.ts b/web/src/api/zsjy/internship.ts index a48d91a1..6c056b14 100644 --- a/web/src/api/zsjy/internship.ts +++ b/web/src/api/zsjy/internship.ts @@ -1,6 +1,13 @@ import request from '@/utils/request'; import { AxiosPromise } from 'axios'; -import { InternshipInfoVO, InternshipInfoQuery, ClassInfoVO, InternshipStatisticsVO } from '@/api/zsjy/types'; +import { + InternshipInfoVO, + InternshipInfoQuery, + InternshipInfoAddBO, + InternshipInfoEditBO, + ClassInfoVO, + InternshipStatisticsVO +} from '@/api/zsjy/types'; import { TableDataInfo, R } from '@/api/types'; /** @@ -65,7 +72,7 @@ export const getInternshipStatistics = (query?: InternshipInfoQuery): AxiosPromi * 新增实习信息 * @param data 实习信息数据 */ -export const addInternshipInfo = (data: any): AxiosPromise> => { +export const addInternshipInfo = (data: InternshipInfoAddBO): AxiosPromise> => { return request({ url: '/zsjy/internship', method: 'post', @@ -77,7 +84,7 @@ export const addInternshipInfo = (data: any): AxiosPromise> => { * 修改实习信息 * @param data 实习信息数据 */ -export const updateInternshipInfo = (data: any): AxiosPromise> => { +export const updateInternshipInfo = (data: InternshipInfoEditBO): AxiosPromise> => { return request({ url: '/zsjy/internship', method: 'put', diff --git a/web/src/api/zsjy/types.ts b/web/src/api/zsjy/types.ts index a320bd7e..8668c151 100644 --- a/web/src/api/zsjy/types.ts +++ b/web/src/api/zsjy/types.ts @@ -862,6 +862,211 @@ export interface InternshipInfoVO { updateBy?: number; } +/** + * 实习信息新增 BO + */ +export interface InternshipInfoAddBO { + /** + * 学生ID + */ + studentId: string | number; + + /** + * 实习状态(1进行中 2已完成 3中断) + */ + internshipStatus: string; + + /** + * 实习单位名称 + */ + companyName: string; + + /** + * 实习单位地址 + */ + companyAddress: string; + + /** + * 行业类型 + */ + companyIndustry?: string; + + /** + * 单位规模 + */ + companyScale?: string; + + /** + * 单位联系人 + */ + companyContact: string; + + /** + * 联系人电话 + */ + companyPhone: string; + + /** + * 岗位名称 + */ + positionName: string; + + /** + * 岗位职责 + */ + positionDuties?: string; + + /** + * 实习津贴 + */ + internshipAllowance?: number; + + /** + * 工作时长 + */ + workHours?: string; + + /** + * 住宿地址 + */ + accommodationAddress?: string; + + /** + * 住宿类型 + */ + accommodationType?: string; + + /** + * 住宿费用 + */ + accommodationCost?: number; + + /** + * 实习开始日期 + */ + startDate: string; + + /** + * 实习结束日期 + */ + endDate: string; + + /** + * 实际结束日期 + */ + actualEndDate?: string; + + /** + * 备注 + */ + remark?: string; +} + +/** + * 实习信息编辑 BO + */ +export interface InternshipInfoEditBO { + /** + * 实习信息ID + */ + internshipId: string | number; + + /** + * 学生ID + */ + studentId: string | number; + + /** + * 实习状态(1进行中 2已完成 3中断) + */ + internshipStatus: string; + + /** + * 实习单位名称 + */ + companyName: string; + + /** + * 实习单位地址 + */ + companyAddress: string; + + /** + * 行业类型 + */ + companyIndustry?: string; + + /** + * 单位规模 + */ + companyScale?: string; + + /** + * 单位联系人 + */ + companyContact: string; + + /** + * 联系人电话 + */ + companyPhone: string; + + /** + * 岗位名称 + */ + positionName: string; + + /** + * 岗位职责 + */ + positionDuties?: string; + + /** + * 实习津贴 + */ + internshipAllowance?: number; + + /** + * 工作时长 + */ + workHours?: string; + + /** + * 住宿地址 + */ + accommodationAddress?: string; + + /** + * 住宿类型 + */ + accommodationType?: string; + + /** + * 住宿费用 + */ + accommodationCost?: number; + + /** + * 实习开始日期 + */ + startDate: string; + + /** + * 实习结束日期 + */ + endDate: string; + + /** + * 实际结束日期 + */ + actualEndDate?: string; + + /** + * 备注 + */ + remark?: string; +} + /** * 实习信息查询 BO */ diff --git a/web/src/views/zsjy/internship/msgmanage/index.vue b/web/src/views/zsjy/internship/msgmanage/index.vue index 5b6e15c0..2e72b55f 100644 --- a/web/src/views/zsjy/internship/msgmanage/index.vue +++ b/web/src/views/zsjy/internship/msgmanage/index.vue @@ -137,7 +137,8 @@ @@ -190,6 +191,8 @@ + +
@@ -206,7 +209,8 @@ - + 未实习 + {{ studentDetail.internshipCompany || '-' }} {{ studentDetail.internshipPosition || '-' }} @@ -227,6 +231,20 @@
+ + + + + + @@ -236,6 +254,9 @@ import { InternshipInfoVO, InternshipInfoQuery, ClassInfoVO, InternshipStatistic import { ComponentInternalInstance, getCurrentInstance, reactive, ref, toRefs } from 'vue'; import { parseTime } from '@/utils/ruoyi'; import { download } from '@/utils/request'; +import { ElMessage } from 'element-plus'; +import AddDialog from './components/AddDialog.vue'; +import EditDialog from './components/EditDialog.vue'; const { proxy } = getCurrentInstance() as ComponentInternalInstance; const { internship_status, sys_user_sex } = toRefs(proxy?.useDict('internship_status', 'sys_user_sex')); @@ -254,6 +275,20 @@ const total = ref(0); const dateRange = ref<[string, string]>([]); const studentDetail = ref(); +// 弹窗相关状态 +const showAddDialog = ref(false); +const showEditDialog = ref(false); +const selectedStudentInfo = ref<{ + studentId: string; + studentName: string; + studentNo: string; +}>({ + studentId: '', + studentName: '', + studentNo: '' +}); +const selectedStudentId = ref(''); + const data = reactive({ queryParams: { pageNum: 1, @@ -388,14 +423,23 @@ const handleExport = () => { /** 新增实习信息按钮操作 */ const handleAdd = (row: InternshipInfoVO) => { - // TODO: 实现新增实习信息功能 - proxy?.$modal.msgInfo('新增实习信息功能开发中...'); + selectedStudentInfo.value = { + studentId: row.studentId, + studentName: row.studentName, + studentNo: row.studentNo + }; + showAddDialog.value = true; }; /** 编辑实习信息按钮操作 */ const handleEdit = (row: InternshipInfoVO) => { - // TODO: 实现编辑实习信息功能 - proxy?.$modal.msgInfo('编辑实习信息功能开发中...'); + selectedStudentId.value = row.studentId; + showEditDialog.value = true; +}; + +/** 弹窗操作成功后刷新列表 */ +const handleDialogSuccess = () => { + getList(); }; /** 取消按钮 */ @@ -498,5 +542,18 @@ const cancel = () => { margin-top: 20px; } } + + .status-tag { + display: inline-block; + padding: 2px 8px; + border-radius: 4px; + font-size: 12px; + font-weight: 500; + + &.not-started { + background-color: #f56c6c; + color: white; + } + } }