“完成出国申请审批流程11.3”
This commit is contained in:
1 parent
4277e2fca8
commit
9af67076a1
12 files changed
+1338
-979
No files matched your search
+73
@@ -550,6 +550,79 @@ public class RsOverseasApplicationController extends BaseController {
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 党籍保留附件上传接口 ====================
|
||||
|
||||
/**
|
||||
* 上传党籍保留附件
|
||||
*/
|
||||
@SaCheckPermission("rs:overseas:add")
|
||||
@PostMapping("/uploadPartyRetentionFile")
|
||||
@Log(title = "上传党籍保留附件", businessType = BusinessType.OTHER)
|
||||
public R<Map<String, Object>> uploadPartyRetentionFile(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam("applicationId") Long applicationId) {
|
||||
try {
|
||||
// 验证文件格式
|
||||
String contentType = file.getContentType();
|
||||
if (!isValidFileType(contentType)) {
|
||||
return R.fail("不支持的文件格式,请上传PDF、JPG或PNG文件");
|
||||
}
|
||||
|
||||
// 验证文件大小(10MB)
|
||||
long maxSize = 10 * 1024 * 1024; // 10MB
|
||||
if (file.getSize() > maxSize) {
|
||||
return R.fail("文件大小超过10MB限制");
|
||||
}
|
||||
|
||||
// 使用系统OSS服务上传文件(自动保存到sys_oss表)
|
||||
SysOssVo ossResult = ossService.upload(file);
|
||||
|
||||
// 更新申请记录 - 存储OSS ID和文件路径
|
||||
applicationService.updatePartyRetentionFileInfo(
|
||||
applicationId,
|
||||
ossResult.getUrl(), // 文件URL
|
||||
ossResult.getOriginalName(), // 原始文件名
|
||||
new Date(), // 上传时间
|
||||
"1", // 上传状态:已上传
|
||||
ossResult.getOssId() // OSS文件ID
|
||||
);
|
||||
|
||||
// 返回结果
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("filePath", ossResult.getUrl());
|
||||
result.put("fileName", ossResult.getOriginalName());
|
||||
result.put("uploadTime", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
|
||||
result.put("ossId", ossResult.getOssId());
|
||||
|
||||
return R.ok("党籍保留附件上传成功", result);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return R.fail("系统异常:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载党籍保留附件(安全下载)
|
||||
*/
|
||||
@SaCheckPermission("rs:overseas:query")
|
||||
@GetMapping("/downloadPartyRetentionFile/{applicationId}")
|
||||
public void downloadPartyRetentionFile(@PathVariable Long applicationId, HttpServletResponse response) {
|
||||
try {
|
||||
RsOverseasApplicationVo application = applicationService.queryById(applicationId);
|
||||
if (application == null || application.getPartyRetentionFileOssId() == null) {
|
||||
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
|
||||
response.setContentType("application/json;charset=UTF-8");
|
||||
response.getWriter().write("{\"code\":404,\"msg\":\"文件不存在\"}");
|
||||
return;
|
||||
}
|
||||
|
||||
// 使用系统OSS服务进行安全下载
|
||||
ossService.secureDownload(application.getPartyRetentionFileOssId(), response);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证文件类型
|
||||
*/
|
||||
|
||||
+15
@@ -30,6 +30,7 @@ import org.dromara.rs.domain.bo.RsOverseasRecordBo;
|
||||
import org.dromara.rs.domain.vo.RsOverseasRecordVo;
|
||||
import org.dromara.rs.domain.query.RsOverseasRecordQuery;
|
||||
import org.dromara.rs.service.IRsOverseasRecordService;
|
||||
import org.dromara.rs.service.IRegistrationFormService;
|
||||
import org.dromara.rs.util.OverseasReceiptPdfUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -50,6 +51,9 @@ public class RsOverseasRecordController extends BaseController {
|
||||
@Autowired
|
||||
private IRsOverseasRecordService recordService;
|
||||
|
||||
@Autowired
|
||||
private IRegistrationFormService registrationFormService;
|
||||
|
||||
/**
|
||||
* 查询出国记录列表
|
||||
*/
|
||||
@@ -100,6 +104,17 @@ public class RsOverseasRecordController extends BaseController {
|
||||
ExcelUtil.exportExcel(list, "出国记录数据", RsOverseasRecordVo.class, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载党籍保留申请PDF模板
|
||||
* 注意:此接口必须放在 /{recordId} 之前,避免路由冲突
|
||||
*/
|
||||
@SaCheckPermission("rs:overseas:query")
|
||||
@Log(title = "下载党籍保留申请模板", businessType = BusinessType.EXPORT)
|
||||
@GetMapping("/downloadPartyRetention")
|
||||
public void downloadPartyRetention(HttpServletResponse response) {
|
||||
registrationFormService.downloadPartyMembershipTemplate(response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取出国记录详细信息
|
||||
*/
|
||||
|
||||
+6
@@ -315,6 +315,12 @@ public class RsOverseasApplication extends BaseEntity {
|
||||
@ExcelProperty(value = "应急联系人及电话")
|
||||
private String emergencyContact;
|
||||
|
||||
/**
|
||||
* 附件OSS ID列表(逗号分隔)
|
||||
*/
|
||||
@ExcelProperty(value = "附件ID列表")
|
||||
private String attachmentIds;
|
||||
|
||||
/**
|
||||
* 手写签字(base64格式)
|
||||
*/
|
||||
|
||||
+5
@@ -251,6 +251,11 @@ public class RsOverseasApplicationBo extends BaseEntity {
|
||||
*/
|
||||
private String emergencyContact;
|
||||
|
||||
/**
|
||||
* 附件OSS ID列表(逗号分隔)
|
||||
*/
|
||||
private String attachmentIds;
|
||||
|
||||
/**
|
||||
* 手写签字(base64格式)
|
||||
*/
|
||||
|
||||
+5
@@ -33,6 +33,11 @@ public class RsOverseasApplicationQuery extends PageQuery {
|
||||
*/
|
||||
private String purpose;
|
||||
|
||||
/**
|
||||
* 出境事由
|
||||
*/
|
||||
private String exitReason;
|
||||
|
||||
/**
|
||||
* 目的地国家
|
||||
*/
|
||||
|
||||
+5
@@ -297,6 +297,11 @@ public class RsOverseasApplicationVo implements Serializable {
|
||||
*/
|
||||
private String emergencyContact;
|
||||
|
||||
/**
|
||||
* 附件OSS ID列表(逗号分隔)
|
||||
*/
|
||||
private String attachmentIds;
|
||||
|
||||
/**
|
||||
* 手写签字(base64格式)
|
||||
*/
|
||||
|
||||
+14
@@ -195,6 +195,20 @@ public interface IRsOverseasApplicationService {
|
||||
Boolean updateStampedFileInfo(Long applicationId, String filePath, String fileName,
|
||||
java.util.Date uploadTime, String uploadStatus, Long ossId);
|
||||
|
||||
/**
|
||||
* 更新党籍保留附件信息
|
||||
*
|
||||
* @param applicationId 申请ID
|
||||
* @param filePath 文件路径
|
||||
* @param fileName 文件名
|
||||
* @param uploadTime 上传时间
|
||||
* @param uploadStatus 上传状态
|
||||
* @param ossId OSS文件ID
|
||||
* @return 是否成功
|
||||
*/
|
||||
Boolean updatePartyRetentionFileInfo(Long applicationId, String filePath, String fileName,
|
||||
java.util.Date uploadTime, String uploadStatus, Long ossId);
|
||||
|
||||
/**
|
||||
* 校验出国登记前置条件
|
||||
* 检查近3个月内是否有已通过的出国登记记录
|
||||
|
||||
+17
@@ -983,6 +983,23 @@ public class RsOverseasApplicationServiceImpl extends ServiceImpl<RsOverseasAppl
|
||||
.set(RsOverseasApplication::getStampedFileOssId, ossId)) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新党籍保留附件信息
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public Boolean updatePartyRetentionFileInfo(Long applicationId, String filePath, String fileName,
|
||||
java.util.Date uploadTime, String uploadStatus, Long ossId) {
|
||||
return baseMapper.update(null,
|
||||
new LambdaUpdateWrapper<RsOverseasApplication>()
|
||||
.eq(RsOverseasApplication::getApplicationId, applicationId)
|
||||
.set(RsOverseasApplication::getPartyRetentionFilePath, filePath)
|
||||
.set(RsOverseasApplication::getPartyRetentionFileName, fileName)
|
||||
.set(RsOverseasApplication::getPartyRetentionUploadTime, uploadTime)
|
||||
.set(RsOverseasApplication::getPartyRetentionUploadStatus, uploadStatus)
|
||||
.set(RsOverseasApplication::getPartyRetentionFileOssId, ossId)) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验出国登记前置条件
|
||||
* 检查当前自然年内是否有已通过的出国登记记录
|
||||
|
||||
+15
-1
@@ -52,12 +52,18 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<result property="adminRemark" column="admin_remark"/>
|
||||
<result property="applicantRemark" column="applicant_remark"/>
|
||||
<result property="emergencyContact" column="emergency_contact"/>
|
||||
<result property="attachmentIds" column="attachment_ids"/>
|
||||
<result property="signature" column="signature"/>
|
||||
<result property="stampedRegistrationFilePath" column="stamped_registration_file_path"/>
|
||||
<result property="stampedRegistrationFileName" column="stamped_registration_file_name"/>
|
||||
<result property="stampedFileOssId" column="stamped_file_oss_id"/>
|
||||
<result property="stampedFileUploadTime" column="stamped_file_upload_time"/>
|
||||
<result property="stampedFileUploadStatus" column="stamped_file_upload_status"/>
|
||||
<result property="partyRetentionFilePath" column="party_retention_file_path"/>
|
||||
<result property="partyRetentionFileName" column="party_retention_file_name"/>
|
||||
<result property="partyRetentionUploadTime" column="party_retention_upload_time"/>
|
||||
<result property="partyRetentionUploadStatus" column="party_retention_upload_status"/>
|
||||
<result property="partyRetentionFileOssId" column="party_retention_file_oss_id"/>
|
||||
<result property="tenantId" column="tenant_id"/>
|
||||
<result property="createBy" column="create_by"/>
|
||||
<result property="createTime" column="create_time"/>
|
||||
@@ -89,9 +95,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
oa.start_date, oa.end_date, oa.duration, oa.invitation, oa.itinerary,
|
||||
oa.accommodation_plan, oa.transportation_plan, oa.status, oa.approval_status, oa.current_approver, oa.approval_level,
|
||||
oa.apply_time, oa.approval_time, oa.admin_remark, oa.applicant_remark,
|
||||
oa.emergency_contact, oa.signature,
|
||||
oa.emergency_contact, oa.attachment_ids, oa.signature,
|
||||
oa.stamped_registration_file_path, oa.stamped_registration_file_name,
|
||||
oa.stamped_file_upload_time, oa.stamped_file_upload_status, oa.stamped_file_oss_id,
|
||||
oa.party_retention_file_path, oa.party_retention_file_name,
|
||||
oa.party_retention_upload_time, oa.party_retention_upload_status, oa.party_retention_file_oss_id,
|
||||
oa.tenant_id, oa.create_by, oa.create_time, oa.update_by, oa.update_time, oa.deleted,
|
||||
CASE
|
||||
WHEN oa.status IS NULL OR oa.status = '' THEN '草稿'
|
||||
@@ -199,6 +207,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="purpose != null and purpose != ''">
|
||||
AND oa.purpose = #{purpose}
|
||||
</if>
|
||||
<if test="exitReason != null and exitReason != ''">
|
||||
AND oa.exit_reason = #{exitReason}
|
||||
</if>
|
||||
<if test="destination != null and destination != ''">
|
||||
AND oa.destination like concat('%', #{destination}, '%')
|
||||
</if>
|
||||
@@ -257,6 +268,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="purpose != null and purpose != ''">
|
||||
AND oa.purpose = #{purpose}
|
||||
</if>
|
||||
<if test="exitReason != null and exitReason != ''">
|
||||
AND oa.exit_reason = #{exitReason}
|
||||
</if>
|
||||
<if test="destination != null and destination != ''">
|
||||
AND oa.destination like concat('%', #{destination}, '%')
|
||||
</if>
|
||||
|
||||
@@ -6,7 +6,7 @@ export interface OverseasApplicationQuery {
|
||||
pageSize: number;
|
||||
applicantName?: string;
|
||||
department?: string;
|
||||
purpose?: string;
|
||||
exitReason?: string;
|
||||
destination?: string;
|
||||
status?: string;
|
||||
approvalLevel?: string;
|
||||
@@ -96,6 +96,8 @@ export interface OverseasApplicationVO {
|
||||
approvalStatus?: string; // 工作流审批状态:draft/waiting/finish/back/cancel
|
||||
approvalStatusText?: string; // 工作流审批状态文本
|
||||
taskId?: string; // 当前待办任务ID(用于审批跳转)
|
||||
// 附件相关字段
|
||||
attachmentIds?: string; // 附件OSS ID列表(逗号分隔)
|
||||
}
|
||||
|
||||
// 出国申请表单类型
|
||||
@@ -150,6 +152,8 @@ export interface OverseasApplicationForm {
|
||||
applicantRemark?: string;
|
||||
// 工作流相关字段
|
||||
approvalStatus?: string; // 工作流审批状态
|
||||
// 附件相关字段
|
||||
attachmentIds?: string; // 附件OSS ID列表(逗号分隔)
|
||||
}
|
||||
|
||||
// 审批请求类型(支持标准工作流模式)
|
||||
|
||||
@@ -7,39 +7,20 @@
|
||||
<el-card shadow="hover">
|
||||
<el-form ref="queryForm" :model="queryParams" label-width="100px">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="5">
|
||||
<el-form-item label="申请人" prop="applicantName">
|
||||
<el-input
|
||||
v-model="queryParams.applicantName"
|
||||
placeholder="请输入申请人姓名"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="5">
|
||||
<el-form-item label="所属部门" prop="department">
|
||||
<el-input v-model="queryParams.department" placeholder="请输入所属部门" clearable @keyup.enter="handleQuery" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="5">
|
||||
<el-form-item label="目的地" prop="destination">
|
||||
<el-col :span="6">
|
||||
<el-form-item label="前往国家" prop="destination">
|
||||
<el-input
|
||||
v-model="queryParams.destination"
|
||||
placeholder="请输入目的地国家"
|
||||
placeholder="请输入前往国家"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="5">
|
||||
<el-form-item label="申请状态" prop="status">
|
||||
<el-select v-model="queryParams.status" placeholder="请选择申请状态" clearable style="width: 100%">
|
||||
<el-option label="待审核" value="0" />
|
||||
<el-option label="已通过" value="1" />
|
||||
<el-option label="已拒绝" value="2" />
|
||||
<el-option label="已取消" value="3" />
|
||||
<el-option label="已完成" value="4" />
|
||||
<el-col :span="6">
|
||||
<el-form-item label="出境事由" prop="exitReason">
|
||||
<el-select v-model="queryParams.exitReason" placeholder="请选择出境事由" clearable style="width: 100%">
|
||||
<el-option v-for="dict in exitReasonOptions" :key="dict.label" :label="dict.label" :value="dict.label" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
@@ -79,8 +60,14 @@
|
||||
>
|
||||
<el-table-column label="申请人" align="center" prop="applicantName" min-width="100" show-overflow-tooltip />
|
||||
<el-table-column label="部门" align="center" prop="department" min-width="140" show-overflow-tooltip />
|
||||
<el-table-column label="目的地" align="center" prop="destination" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column label="出国事由" align="center" prop="purpose" min-width="140" show-overflow-tooltip />
|
||||
<el-table-column label="政治面貌" align="center" prop="politicalStatusText" min-width="100" show-overflow-tooltip />
|
||||
<el-table-column label="前往国家" align="center" prop="destination" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column label="出境事由" align="center" prop="exitReason" min-width="140" show-overflow-tooltip />
|
||||
<el-table-column label="出国天数" align="center" prop="duration" min-width="100">
|
||||
<template #default="scope">
|
||||
<span>{{ scope.row.duration || 0 }}天</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="申请时间" align="center" prop="applyTime" min-width="170">
|
||||
<template #default="scope">
|
||||
<span>{{ scope.row.applyTime ? new Date(scope.row.applyTime).toLocaleString() : '-' }}</span>
|
||||
@@ -392,12 +379,15 @@ const state = reactive({
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
applicantName: '',
|
||||
department: '',
|
||||
destination: '',
|
||||
status: ''
|
||||
exitReason: ''
|
||||
} as OverseasApplicationQuery,
|
||||
|
||||
// 出境事由选项
|
||||
exitReasonOptions: [
|
||||
{ label: '旅游', value: 'tourism' },
|
||||
{ label: '探亲', value: 'visiting_relatives' }
|
||||
],
|
||||
|
||||
// 查看详情
|
||||
viewDialog: {
|
||||
@@ -427,6 +417,7 @@ const {
|
||||
total,
|
||||
showSearch,
|
||||
queryParams,
|
||||
exitReasonOptions,
|
||||
viewDialog,
|
||||
viewData,
|
||||
approvalDialog,
|
||||
@@ -469,27 +460,15 @@ const applyFilterAndPagination = () => {
|
||||
let filteredList = [...state.allApplicationList];
|
||||
|
||||
// 🔴 应用搜索过滤
|
||||
if (state.queryParams.applicantName) {
|
||||
filteredList = filteredList.filter(item =>
|
||||
item.applicantName?.includes(state.queryParams.applicantName || '')
|
||||
);
|
||||
}
|
||||
|
||||
if (state.queryParams.department) {
|
||||
filteredList = filteredList.filter(item =>
|
||||
item.department?.includes(state.queryParams.department || '')
|
||||
);
|
||||
}
|
||||
|
||||
if (state.queryParams.destination) {
|
||||
filteredList = filteredList.filter(item =>
|
||||
item.destination?.includes(state.queryParams.destination || '')
|
||||
);
|
||||
}
|
||||
|
||||
if (state.queryParams.status) {
|
||||
if (state.queryParams.exitReason) {
|
||||
filteredList = filteredList.filter(item =>
|
||||
item.status === state.queryParams.status
|
||||
item.exitReason === state.queryParams.exitReason
|
||||
);
|
||||
}
|
||||
|
||||
@@ -518,10 +497,8 @@ const resetQuery = () => {
|
||||
Object.assign(state.queryParams, {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
applicantName: '',
|
||||
department: '',
|
||||
destination: '',
|
||||
status: ''
|
||||
exitReason: ''
|
||||
});
|
||||
const form = proxy.$refs.queryForm;
|
||||
if (form && typeof form.resetFields === 'function') {
|
||||
|
||||
+1153
-929
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user