commit
This commit is contained in:
@@ -12,6 +12,7 @@ import com.budwk.app.web.commons.auth.satoken.StpInterfaceImpl;
|
||||
import com.budwk.app.web.commons.base.Globals;
|
||||
import com.budwk.app.web.commons.ext.pubsub.WebPubSub;
|
||||
import com.budwk.app.zhgh.dayofficework.message.service.GlobalMessageSendService;
|
||||
import com.budwk.app.zhgh.staffbenefit.difficultSubsidy.service.impl.DifficultSubsidySchemaInitializer;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.beetl.core.GroupTemplate;
|
||||
import org.nutz.boot.NbApp;
|
||||
@@ -61,6 +62,8 @@ public class MainLauncher {
|
||||
private SysTaskService sysTaskService;
|
||||
@Inject
|
||||
private Dao dao;
|
||||
@Inject
|
||||
private DifficultSubsidySchemaInitializer difficultSubsidySchemaInitializer;//确保特困补助实体迁移随应用启动执行
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
NbApp nb = new NbApp().setArgs(args).setPrintProcDoc(true);
|
||||
|
||||
@@ -19,25 +19,28 @@ import org.nutz.lang.Lang;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 获取申请人所在分工会的分工会主席
|
||||
* 获取申请人所在分工会的分工会主席和管理员
|
||||
*/
|
||||
public class FlowFghzxAssignmentHandler implements AssignmentHandler {
|
||||
@Override
|
||||
public List<String> assign(TaskModel model, Execution execution) {
|
||||
Dao dao = ServiceContext.find(Dao.class);
|
||||
SysRoleService sysRoleService = ServiceContext.find(SysRoleService.class);
|
||||
Sys_role sysRole = sysRoleService.getByCode(RoleConstant.BRANCH_UNION_CHAIRMAN);
|
||||
Sys_role chairmanRole = sysRoleService.getByCode(RoleConstant.BRANCH_UNION_CHAIRMAN);
|
||||
Sys_role administratorRole = sysRoleService.getByCode(RoleConstant.BRANCH_UNION_ADMIN);
|
||||
String unionId = StrUtil.blankToDefault(execution.getArgs().getStr(FlowConst.INITIATOR_UNIT_UNION_ID), SecurityUtil.getUnionId());
|
||||
List<Sys_user_role> user_roles = dao.query(Sys_user_role.class, Cnd.where(Sys_user_role::getRoleId, "=", sysRole.getId()).and(Sys_user_role::getUnionId, "=", unionId));
|
||||
// 同一分工会的主席和管理员均可处理该节点,重复配置的人员只返回一次。
|
||||
List<Sys_user_role> user_roles = dao.query(Sys_user_role.class, Cnd.where(Sys_user_role::getRoleId, "in", List.of(chairmanRole.getId(), administratorRole.getId()))
|
||||
.and(Sys_user_role::getUnionId, "=", unionId));
|
||||
if (Lang.isEmpty(user_roles)) {
|
||||
throw new BaseException("分工会主席没有设置,请联系校工会!", sysRole.getCode());
|
||||
throw new BaseException("提案人所属分工会的主席和管理员均未设置,请联系校工会!", chairmanRole.getCode());
|
||||
}
|
||||
return user_roles.stream().map(Sys_user_role::getUserId).distinct().toList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return "当前用户所属分工会主席";
|
||||
return "提案人所属分工会的主席和管理员";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.budwk.app.flow.service;
|
||||
|
||||
import cn.hutool.core.lang.Dict;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.budwk.app.base.event.flow.jumptofirsttask.FlowJumpToFirstTaskNodePublisher;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.flow.constant.FlowConst;
|
||||
@@ -9,9 +10,11 @@ import com.budwk.app.flow.engine.FlowEngine;
|
||||
import com.budwk.app.flow.engine.event.ProcessEvent;
|
||||
import com.budwk.app.flow.engine.event.ProcessPublisher;
|
||||
import com.budwk.app.flow.entity.ProcessInstance;
|
||||
import com.budwk.app.flow.entity.ProcessDefine;
|
||||
import com.budwk.app.flow.entity.ProcessTask;
|
||||
import com.budwk.app.flow.enums.*;
|
||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||
import com.budwk.app.sys.models.Sys_user_signature;
|
||||
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||
import org.nutz.dao.Chain;
|
||||
import org.nutz.dao.Cnd;
|
||||
@@ -22,10 +25,17 @@ import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.json.Json;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@IocBean
|
||||
public class FlowCommonService {
|
||||
|
||||
/** 教代会提案中从二级工会审核开始,可留存当前办理人的电子签名快照。 */
|
||||
private static final Set<String> PROPOSAL_SIGNATURE_TASK_NAMES = Set.of(
|
||||
"secondaryUnionAudit", "partyOrganizationAudit", "committee", "committeeFilingUnit",
|
||||
"unit_reply", "schoolLeader", "feedback"
|
||||
);
|
||||
|
||||
@Inject
|
||||
private FlowEngine flowEngine;
|
||||
|
||||
@@ -39,6 +49,9 @@ public class FlowCommonService {
|
||||
public void executeTask(Dict args){
|
||||
Long processTaskId = args.getLong(FlowConst.PROCESS_TASK_ID_KEY);
|
||||
|
||||
ProcessTask processTask = flowEngine.processTaskService().getById(processTaskId);
|
||||
appendProposalSignature(processTask, args);
|
||||
|
||||
String operator = SecurityUtil.getUserId();
|
||||
if (args.containsKey(FlowConst.EXT_ENABLE_OPERATOR)&&args.getBool(FlowConst.EXT_ENABLE_OPERATOR)){
|
||||
operator = FlowConst.ADMIN_ID;
|
||||
@@ -49,7 +62,6 @@ public class FlowCommonService {
|
||||
submitType = ProcessSubmitTypeEnum.AGREE.getCode();
|
||||
}
|
||||
|
||||
ProcessTask processTask = flowEngine.processTaskService().getById(processTaskId);
|
||||
ProcessTask parentTask = flowEngine.processTaskService().getById(processTask.getTaskParentId());
|
||||
if(parentTask != null) {
|
||||
Dict taskArgs = Json.fromJson(Dict.class, parentTask.getVariable());
|
||||
@@ -98,6 +110,34 @@ public class FlowCommonService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 为教代会提案审核任务保存签字 URL 快照。
|
||||
* 仅处理 JDHTA_NC 流程,避免电子签名快照影响系统其他工作流;用户已维护签名时才归档,
|
||||
* 未维护签名也允许正常提交。快照随任务变量归档,后续用户更新个人签名不会改变已办任务的导出结果。
|
||||
*
|
||||
* @param processTask 当前待办任务
|
||||
* @param args 即将写入任务变量的表单参数
|
||||
*/
|
||||
private void appendProposalSignature(ProcessTask processTask, Dict args) {
|
||||
if (processTask == null || !PROPOSAL_SIGNATURE_TASK_NAMES.contains(processTask.getTaskName())) {
|
||||
return;
|
||||
}
|
||||
ProcessInstance processInstance = dao.fetch(ProcessInstance.class, processTask.getProcessInstanceId());
|
||||
if (processInstance == null) {
|
||||
return;
|
||||
}
|
||||
ProcessDefine processDefine = dao.fetch(ProcessDefine.class, processInstance.getProcessDefineId());
|
||||
if (processDefine == null || !"JDHTA_NC".equals(processDefine.getName())) {
|
||||
return;
|
||||
}
|
||||
Sys_user_signature userSignature = dao.fetch(Sys_user_signature.class,
|
||||
Cnd.where(Sys_user_signature::getUserId, "=", SecurityUtil.getUserId()));
|
||||
if (userSignature == null || StrUtil.isBlank(userSignature.getSignature())) {
|
||||
return;
|
||||
}
|
||||
args.put(FlowConst.TASK_FORM_DATA_PREFIX + "signature", userSignature.getSignature());
|
||||
}
|
||||
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public Result revokeTask(Long taskId) {
|
||||
// 自己任务
|
||||
|
||||
@@ -120,6 +120,8 @@ public class ProcessTaskServiceImpl extends BaseServiceImpl<ProcessTask> impleme
|
||||
public List<ProcessTask> getDoneTaskList(Long processInstanceId, String[] taskNames) {
|
||||
Cnd cnd = Cnd.where(ProcessTask::getProcessInstanceId, "=", processInstanceId).and(ProcessTask::getTaskState, "=", ProcessTaskStateEnum.FINISHED.getCode());
|
||||
cnd.andEX(ProcessTask::getTaskName, "", taskNames);
|
||||
// 已办记录必须按实际办结时间返回,避免补迁历史任务因写入时间较晚而排在流程末尾。
|
||||
cnd.asc(ProcessTask::getFinishTime).asc(ProcessTask::getId);
|
||||
List<ProcessTask> processTaskList = query(cnd);
|
||||
return processTaskList;
|
||||
}
|
||||
|
||||
@@ -131,7 +131,9 @@ public class SysSignatureController {
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public Result update(@Param("file") TempFile tempFile) {
|
||||
String url = sysFileService.uploadReturnUrl(SysFileEngineTypeEnum.MINIO.getValue(), tempFile);
|
||||
Sys_user_signature sysUserSignature = dao.fetch(Sys_user_signature.class);
|
||||
// 每位用户维护独立的电子签名,不能取任意一条记录后覆盖其归属用户。
|
||||
Sys_user_signature sysUserSignature = dao.fetch(Sys_user_signature.class,
|
||||
Cnd.where(Sys_user_signature::getUserId, "=", SecurityUtil.getUserId()));
|
||||
if (ObjectUtil.isNull(sysUserSignature)) {
|
||||
sysUserSignature = new Sys_user_signature();
|
||||
}
|
||||
|
||||
@@ -259,11 +259,10 @@ public class SysUnionController {
|
||||
@At
|
||||
@SaCheckPermission("sys.manager.union")
|
||||
public Result branchUnionUserPageData(PageForm pageForm, String unionId, @Param("j") String j) {
|
||||
List<Sys_dict> branchUnionRoles = sysDictService.getSubListByCode("BRANCH_UNION_ROLES");
|
||||
if (Lang.isEmpty(branchUnionRoles)) {
|
||||
List<String> branchUnionRoleCodes = getBranchUnionRoleCodes();
|
||||
if (Lang.isEmpty(branchUnionRoleCodes)) {
|
||||
return Result.success();
|
||||
}
|
||||
List<String> branchUnionRoleCodes = branchUnionRoles.stream().map(Sys_dict::getCode).toList();
|
||||
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
@@ -334,11 +333,10 @@ public class SysUnionController {
|
||||
@At
|
||||
@SaCheckPermission("sys.manager.union")
|
||||
public Result branchUnionUserUsedJData(String unionId) {
|
||||
List<Sys_dict> branchUnionRoles = sysDictService.getSubListByCode("BRANCH_UNION_ROLES");
|
||||
if (Lang.isEmpty(branchUnionRoles)) {
|
||||
List<String> branchUnionRoleCodes = getBranchUnionRoleCodes();
|
||||
if (Lang.isEmpty(branchUnionRoleCodes)) {
|
||||
return Result.success(List.of());
|
||||
}
|
||||
List<String> branchUnionRoleCodes = branchUnionRoles.stream().map(Sys_dict::getCode).toList();
|
||||
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT DISTINCT
|
||||
@@ -371,16 +369,46 @@ public class SysUnionController {
|
||||
return Result.success(usedJCodes);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回分工会干部页面可维护的角色,审核角色不依赖字典重复配置,
|
||||
* 直接使用系统角色编码,避免单位党委书记在多个字典目录中出现同码数据。
|
||||
*/
|
||||
@At
|
||||
@SaCheckPermission("sys.manager.union")
|
||||
@ApiOperation("查询分工会干部可选角色")
|
||||
public Result branchUnionRoleOptions() {
|
||||
List<NutMap> options = getBranchUnionRoleCodes().stream()
|
||||
.map(sysRoleService::getByCode)
|
||||
.filter(role -> role != null)
|
||||
.map(role -> NutMap.NEW().addv("code", role.getCode()).addv("name", role.getName()))
|
||||
.toList();
|
||||
return Result.success(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* 汇总分工会干部和提案审核所需角色,后续列表、历史届次和新增校验统一使用同一范围。
|
||||
*/
|
||||
private List<String> getBranchUnionRoleCodes() {
|
||||
List<String> roleCodes = new ArrayList<>(sysDictService.getSubListByCode("BRANCH_UNION_ROLES")
|
||||
.stream().map(Sys_dict::getCode).toList());
|
||||
roleCodes.add(RoleConstant.BRANCH_UNION_ADMIN.name());
|
||||
roleCodes.add(RoleConstant.UNIT_PARTY_SECRETARY.name());
|
||||
return roleCodes.stream().filter(StrUtil::isNotBlank).distinct().toList();
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("sys.manager.union.branchOfficer")
|
||||
@ApiOperation("添加分工会人员角色")
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public Result insertBranchUnionUserRole(String userId, String roleCode, String unionId, String j) {
|
||||
if (!getBranchUnionRoleCodes().contains(roleCode)) {
|
||||
return Result.error("该角色不允许在分工会干部中维护");
|
||||
}
|
||||
Sys_role role = sysRoleService.fetch(Cnd.where("code", "=", roleCode));
|
||||
if (Lang.isEmpty(role)) {
|
||||
return Result.success("无法找到" + roleCode + "对应编码的角色");
|
||||
return Result.error("无法找到" + roleCode + "对应编码的角色");
|
||||
}
|
||||
int count = dao.count(Sys_user_role.class, Cnd.where("roleId", "=", role.getId()).and("userId", "=", userId));
|
||||
int count = dao.count(Sys_user_role.class, Cnd.where("roleId", "=", role.getId()).and("userId", "=", userId).and("unionId", "=", unionId));
|
||||
if (count > 0) {
|
||||
return Result.error("请勿重复添加");
|
||||
}
|
||||
@@ -404,6 +432,9 @@ public class SysUnionController {
|
||||
|
||||
// 构建表结构存储
|
||||
View_user user = dao.fetch(View_user.class, Cnd.where("id", "=", userId));
|
||||
if (user == null) {
|
||||
return Result.error("未找到人员信息");
|
||||
}
|
||||
|
||||
Sys_union_cadre unionCadre = new Sys_union_cadre();
|
||||
unionCadre.setUserId(userId);
|
||||
|
||||
@@ -50,6 +50,8 @@ import javax.validation.Valid;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
;
|
||||
|
||||
@@ -305,6 +307,7 @@ public class SysUnitController {
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.asc("unitcode");
|
||||
List<Sys_unit> list = sysUnitService.query(cnd);
|
||||
Set<String> unitIds = list.stream().map(Sys_unit::getId).collect(Collectors.toSet());
|
||||
|
||||
List<TreeNode<String>> nodeList = CollUtil.newArrayList();
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
@@ -312,8 +315,12 @@ public class SysUnitController {
|
||||
/*
|
||||
* 单位根节点存在 id 与 parentId 都为 0 的自引用数据。
|
||||
* 构建树时把当前查询根挂到虚拟根下,避免“中国地质大学”和 parentId=0 的学院被构造成同级。
|
||||
* 同时兼容迁移数据中根节点 parentId 为空或父级不存在的情况,确保这些节点可被树组件展示。
|
||||
*/
|
||||
String parentId = rootId.equals(unit.getId()) ? virtualRootId : unit.getParentId();
|
||||
String parentId = unit.getParentId();
|
||||
if (rootId.equals(unit.getId()) || StrUtil.isBlank(parentId) || !unitIds.contains(parentId)) {
|
||||
parentId = virtualRootId;
|
||||
}
|
||||
nodeList.add(new TreeNode<>(unit.getId(), parentId, unit.getName(), i)
|
||||
.setExtra(
|
||||
Map.of(
|
||||
|
||||
+2
-2
@@ -420,7 +420,7 @@ public class UnionReimburseMineController {
|
||||
@At
|
||||
private void exportAsPDF(String templateName, HashMap<String, Object> docData,
|
||||
UnionReimburse unionReimburse, HttpServletResponse response) throws Exception {
|
||||
String fileName = "中国地质大学(武汉)工会经费日常报销_" + unionReimburse.getUserName() + "_" +
|
||||
String fileName = "西南财经大学工会经费日常报销_" + unionReimburse.getUserName() + "_" +
|
||||
DateUtil.format(unionReimburse.getCreateTime(), "yyyyMMdd") + ".pdf";
|
||||
|
||||
try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
|
||||
@@ -446,7 +446,7 @@ public class UnionReimburseMineController {
|
||||
@At
|
||||
private void exportAsWord(String templateName, HashMap<String, Object> docData,
|
||||
UnionReimburse unionReimburse, HttpServletResponse response) throws Exception {
|
||||
String fileName = "中国地质大学(武汉)工会经费日常报销_" + unionReimburse.getUserName() + "_" +
|
||||
String fileName = "西南财经大学工会经费日常报销_" + unionReimburse.getUserName() + "_" +
|
||||
DateUtil.format(unionReimburse.getCreateTime(), "yyyyMMdd") + ".docx";
|
||||
|
||||
try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
|
||||
|
||||
+8
@@ -148,6 +148,14 @@ public class ProposalExportComprehensiveController {
|
||||
proposalExportService.exportProposalStatisticsAsDocx(pageForm, response);
|
||||
}
|
||||
|
||||
@At
|
||||
@Ok("void")
|
||||
@ApiOperation("按综合导出模板导出单条提案")
|
||||
@SaCheckPermission("proposal.query.comprehensive")
|
||||
public void exportProposalAsDocx(@Valid String id, HttpServletResponse response) {
|
||||
proposalExportService.exportProposalAsDocx(id, response);
|
||||
}
|
||||
|
||||
@At
|
||||
@Ok("void")
|
||||
@ApiOperation("导出全部提案反馈表ZIP")
|
||||
|
||||
+21
@@ -52,6 +52,16 @@ public class ProposalCommitteeFilingController {
|
||||
public void index() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 提案委员会立案 H5 办理页。
|
||||
* H5 权限与 PC 权限独立配置,避免手机端通过 PC 菜单权限访问审核页面。
|
||||
*/
|
||||
@At("/h5")
|
||||
@Ok("beetl:/platform/zhghh5/democratic/proposal/transact/committeeFiling/index.html")
|
||||
@SaCheckPermission("h5.proposal.committeeFiling")
|
||||
public void h5Index() {
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("proposal.committeeFiling")
|
||||
@ApiOperation("分页列表")
|
||||
@@ -116,6 +126,17 @@ public class ProposalCommitteeFilingController {
|
||||
return Result.success(pagination);
|
||||
}
|
||||
|
||||
/**
|
||||
* 提案委员会立案 H5 列表。
|
||||
* 列表数据与 PC 保持同一任务、参与人和状态口径,仅切换为 H5 菜单权限。
|
||||
*/
|
||||
@At("/h5/pageData")
|
||||
@SaCheckPermission("h5.proposal.committeeFiling")
|
||||
@ApiOperation("提案委员会立案 H5 分页列表")
|
||||
public Result h5PageData(@Valid ProposalSearchParam pageForm, boolean approval) {
|
||||
return pageData(pageForm, approval);
|
||||
}
|
||||
|
||||
@At
|
||||
@Ok("void")
|
||||
@SaCheckPermission("proposal.committeeFiling")
|
||||
|
||||
+35
@@ -65,6 +65,16 @@ public class ProposalCommitteeFilingUnitController {
|
||||
public void index() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 提案委员会确认承办单位 H5 办理页。
|
||||
* H5 权限与 PC 权限独立配置,避免手机端通过 PC 菜单权限访问审核页面。
|
||||
*/
|
||||
@At("/h5")
|
||||
@Ok("beetl:/platform/zhghh5/democratic/proposal/transact/committeeFilingUnit/index.html")
|
||||
@SaCheckPermission("h5.proposal.committeeFilingUnit")
|
||||
public void h5Index() {
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("proposal.committeeFilingUnit")
|
||||
@ApiOperation("分页列表")
|
||||
@@ -129,6 +139,17 @@ public class ProposalCommitteeFilingUnitController {
|
||||
return Result.success(pagination);
|
||||
}
|
||||
|
||||
/**
|
||||
* 提案委员会确认承办单位 H5 列表。
|
||||
* 列表数据与 PC 保持同一任务、参与人和状态口径,仅切换为 H5 菜单权限。
|
||||
*/
|
||||
@At("/h5/pageData")
|
||||
@SaCheckPermission("h5.proposal.committeeFilingUnit")
|
||||
@ApiOperation("提案委员会确认承办单位 H5 分页列表")
|
||||
public Result h5PageData(@Valid ProposalSearchParam pageForm, boolean approval) {
|
||||
return pageData(pageForm, approval);
|
||||
}
|
||||
|
||||
@At
|
||||
@Ok("void")
|
||||
@SaCheckPermission("proposal.committeeFilingUnit")
|
||||
@@ -148,6 +169,20 @@ public class ProposalCommitteeFilingUnitController {
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 确认承办单位 H5 提交。
|
||||
* 复用原有服务,保证并案提案、承办单位和立案结果的同步规则与 PC 一致。
|
||||
*/
|
||||
@At("/h5/executeTask")
|
||||
@SaCheckPermission("h5.proposal.committeeFilingUnit")
|
||||
@ApiOperation("提案委员会确认承办单位 H5 执行任务")
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public Result h5ExecuteTask(@Param("data") String data) {
|
||||
Dict args = Json.fromJson(Dict.class, data);
|
||||
proposalCommitteeFilingUnitService.executeFlowTask(args);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
|
||||
@At
|
||||
@SaCheckLogin
|
||||
|
||||
+5
@@ -26,6 +26,7 @@ import com.budwk.app.zhgh.democratic.proposal.models.ProposalConfig;
|
||||
import com.budwk.app.zhgh.democratic.proposal.models.ProposalInfo;
|
||||
import com.budwk.app.zhgh.democratic.proposal.models.ProposalSecond;
|
||||
import com.budwk.app.zhgh.democratic.proposal.param.ProposalSearchParam;
|
||||
import com.budwk.app.zhgh.democratic.proposal.service.ProposalMessageService;
|
||||
import com.budwk.app.zhgh.democratic.proposal.service.common.ProposalCommonService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
@@ -94,6 +95,8 @@ public class ProposalMineController {
|
||||
private ProcessTaskService processTaskService;
|
||||
@Inject
|
||||
private FlowCommonService flowCommonService;
|
||||
@Inject
|
||||
private ProposalMessageService proposalMessageService;
|
||||
|
||||
@At("")
|
||||
@Ok("beetl:/platform/zhgh/democratic/proposal/transact/mine/index.html")
|
||||
@@ -384,6 +387,8 @@ public class ProposalMineController {
|
||||
return seconded;
|
||||
}).toList();
|
||||
dao.insert(secondeds);
|
||||
// V3 在邀请附议人保存成功后逐个发送业务短信;实际下发仍由 SmsService 配置开关控制。
|
||||
proposalMessageService.sendInviteSeconderMessage(proposalId, userIds);
|
||||
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
package com.budwk.app.zhgh.democratic.proposal.controller.transact;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import com.budwk.app.base.param.ExportTableColumns;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.zhgh.democratic.proposal.param.ProposalSearchParam;
|
||||
import com.budwk.app.zhgh.democratic.proposal.service.common.ProposalCommonService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.mvc.annotation.At;
|
||||
import org.nutz.mvc.annotation.Ok;
|
||||
import org.nutz.mvc.annotation.Param;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
|
||||
/**
|
||||
* 提案院级党组织审核。
|
||||
*/
|
||||
@IocBean
|
||||
@At("/platform/proposal/partyOrganizationAudit")
|
||||
@Ok("json:full")
|
||||
@Api(tags = "提案办理-院级党组织审核")
|
||||
public class ProposalPartyOrganizationAuditController {
|
||||
|
||||
@Inject
|
||||
private ProposalCommonService proposalCommonService;
|
||||
|
||||
@At("")
|
||||
@Ok("beetl:/platform/zhgh/democratic/proposal/transact/delegation/index.html")
|
||||
@SaCheckPermission("proposal.partyOrganizationAudit")
|
||||
public void index() {
|
||||
}
|
||||
|
||||
@At("/h5")
|
||||
@Ok("beetl:/platform/zhghh5/democratic/proposal/transact/delegation/index.html")
|
||||
@SaCheckPermission("h5.proposal.partyOrganizationAudit")
|
||||
public void h5Index() {
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("proposal.partyOrganizationAudit")
|
||||
@ApiOperation("院级党组织审核分页列表")
|
||||
public Result pageData(@Valid ProposalSearchParam pageForm, boolean approval) {
|
||||
return Result.success(proposalCommonService.getWorkflowAuditPage("partyOrganizationAudit", pageForm, approval));
|
||||
}
|
||||
|
||||
@At("/h5/pageData")
|
||||
@SaCheckPermission("h5.proposal.partyOrganizationAudit")
|
||||
@ApiOperation("院级党组织审核手机端分页列表")
|
||||
public Result h5PageData(@Valid ProposalSearchParam pageForm, boolean approval) {
|
||||
return Result.success(proposalCommonService.getWorkflowAuditPage("partyOrganizationAudit", pageForm, approval));
|
||||
}
|
||||
|
||||
@At
|
||||
@Ok("void")
|
||||
@SaCheckPermission("proposal.partyOrganizationAudit")
|
||||
@ApiOperation("导出院级党组织审核列表")
|
||||
public void exportList(@Valid @Param("pageForm") ProposalSearchParam pageForm, boolean approval,
|
||||
@Param("tableColumns") ExportTableColumns[] tableColumns, HttpServletResponse response) {
|
||||
proposalCommonService.exportWorkflowList("partyOrganizationAudit", pageForm, approval, tableColumns, response);
|
||||
}
|
||||
}
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
package com.budwk.app.zhgh.democratic.proposal.controller.transact;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import com.budwk.app.base.param.ExportTableColumns;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.zhgh.democratic.proposal.param.ProposalSearchParam;
|
||||
import com.budwk.app.zhgh.democratic.proposal.service.common.ProposalCommonService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.mvc.annotation.At;
|
||||
import org.nutz.mvc.annotation.Ok;
|
||||
import org.nutz.mvc.annotation.Param;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
|
||||
/**
|
||||
* 提案二级工会审核。
|
||||
*/
|
||||
@IocBean
|
||||
@At("/platform/proposal/secondaryUnionAudit")
|
||||
@Ok("json:full")
|
||||
@Api(tags = "提案办理-二级工会审核")
|
||||
public class ProposalSecondaryUnionAuditController {
|
||||
|
||||
@Inject
|
||||
private ProposalCommonService proposalCommonService;
|
||||
|
||||
@At("")
|
||||
@Ok("beetl:/platform/zhgh/democratic/proposal/transact/delegation/index.html")
|
||||
@SaCheckPermission("proposal.secondaryUnionAudit")
|
||||
public void index() {
|
||||
}
|
||||
|
||||
@At("/h5")
|
||||
@Ok("beetl:/platform/zhghh5/democratic/proposal/transact/delegation/index.html")
|
||||
@SaCheckPermission("h5.proposal.secondaryUnionAudit")
|
||||
public void h5Index() {
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("proposal.secondaryUnionAudit")
|
||||
@ApiOperation("二级工会审核分页列表")
|
||||
public Result pageData(@Valid ProposalSearchParam pageForm, boolean approval) {
|
||||
return Result.success(proposalCommonService.getWorkflowAuditPage("secondaryUnionAudit", pageForm, approval));
|
||||
}
|
||||
|
||||
@At("/h5/pageData")
|
||||
@SaCheckPermission("h5.proposal.secondaryUnionAudit")
|
||||
@ApiOperation("二级工会审核手机端分页列表")
|
||||
public Result h5PageData(@Valid ProposalSearchParam pageForm, boolean approval) {
|
||||
return Result.success(proposalCommonService.getWorkflowAuditPage("secondaryUnionAudit", pageForm, approval));
|
||||
}
|
||||
|
||||
@At
|
||||
@Ok("void")
|
||||
@SaCheckPermission("proposal.secondaryUnionAudit")
|
||||
@ApiOperation("导出二级工会审核列表")
|
||||
public void exportList(@Valid @Param("pageForm") ProposalSearchParam pageForm, boolean approval,
|
||||
@Param("tableColumns") ExportTableColumns[] tableColumns, HttpServletResponse response) {
|
||||
proposalCommonService.exportWorkflowList("secondaryUnionAudit", pageForm, approval, tableColumns, response);
|
||||
}
|
||||
}
|
||||
+4
-12
@@ -198,19 +198,9 @@ public class ProposalSecondedController {
|
||||
}
|
||||
|
||||
// 更新 proposal_second,记录当前附议人的最终附议结果、附议意见和附议时间。
|
||||
ProposalSecond proposalSecond = dao.fetch(
|
||||
ProposalSecond.class,
|
||||
Cnd.where(ProposalSecond::getProposalId, "=", proposalId)
|
||||
.and(ProposalSecond::getSeconderId, "=", taskActorUserId)
|
||||
);
|
||||
if (proposalSecond == null) {
|
||||
if (!proposalSecondedService.updateSecondRecord(proposalId, taskActorUserId, opinion, submitType)) {
|
||||
return Result.error("未找到附议记录");
|
||||
}
|
||||
proposalSecond.setIsAgree(ObjectUtil.equals(submitType, ProcessSubmitTypeEnum.AGREE.getCode()));
|
||||
proposalSecond.setOpinion(opinion);
|
||||
proposalSecond.setIsAgree(submitType == 1);
|
||||
proposalSecond.setSecondedTime(DateUtil.date());
|
||||
dao.update(proposalSecond);
|
||||
|
||||
// 仅更新本次附议对应的 wf_process_task,不推动实例、也不创建后续任务。
|
||||
View_user user = dao.fetch(View_user.class, Cnd.where(View_user::getId, "=", taskActorUserId));
|
||||
@@ -269,7 +259,9 @@ public class ProposalSecondedController {
|
||||
return Result.error("参数错误");
|
||||
}
|
||||
flowCommonService.executeTask(args);
|
||||
proposalSecondedService.updateSecondRecord(proposalId, taskActorUserId, opinion, submitType);
|
||||
if (!proposalSecondedService.updateSecondRecord(proposalId, taskActorUserId, opinion, submitType)) {
|
||||
return Result.error("未找到附议记录");
|
||||
}
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
package com.budwk.app.zhgh.democratic.proposal.handler;
|
||||
|
||||
import com.budwk.app.base.constant.RoleConstant;
|
||||
import com.budwk.app.base.exception.BaseException;
|
||||
import com.budwk.app.flow.constant.FlowConst;
|
||||
import com.budwk.app.flow.engine.AssignmentHandler;
|
||||
import com.budwk.app.flow.engine.core.Execution;
|
||||
import com.budwk.app.flow.engine.core.ServiceContext;
|
||||
import com.budwk.app.flow.engine.model.TaskModel;
|
||||
import com.budwk.app.zhgh.democratic.proposal.models.ProposalInfo;
|
||||
import com.budwk.app.zhgh.democratic.proposal.service.common.ProposalCommonService;
|
||||
import org.nutz.json.Json;
|
||||
import org.nutz.lang.util.NutMap;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 提案院级党组织审核参与人。
|
||||
*/
|
||||
public class ProposalPartyOrganizationAssignmentHandler implements AssignmentHandler {
|
||||
|
||||
@Override
|
||||
public List<String> assign(TaskModel model, Execution execution) {
|
||||
NutMap variable = Json.fromJson(NutMap.class, execution.getProcessInstance().getVariable());
|
||||
ProposalInfo proposalInfo = variable.getAs(FlowConst.FORM_DATA, ProposalInfo.class);
|
||||
List<String> userIds = ServiceContext.find(ProposalCommonService.class).getProposalUnionRoleUserIds(proposalInfo,
|
||||
RoleConstant.UNIT_PARTY_SECRETARY.name());
|
||||
if (userIds.isEmpty()) {
|
||||
throw new BaseException("提案人所属分工会未设置党委书记,无法流转到院级党组织审核");
|
||||
}
|
||||
return userIds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return "提案人所属分工会党委书记";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return 240;
|
||||
}
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
package com.budwk.app.zhgh.democratic.proposal.handler;
|
||||
|
||||
import com.budwk.app.base.constant.RoleConstant;
|
||||
import com.budwk.app.base.exception.BaseException;
|
||||
import com.budwk.app.flow.constant.FlowConst;
|
||||
import com.budwk.app.flow.engine.AssignmentHandler;
|
||||
import com.budwk.app.flow.engine.core.Execution;
|
||||
import com.budwk.app.flow.engine.core.ServiceContext;
|
||||
import com.budwk.app.flow.engine.model.TaskModel;
|
||||
import com.budwk.app.zhgh.democratic.proposal.models.ProposalInfo;
|
||||
import com.budwk.app.zhgh.democratic.proposal.service.common.ProposalCommonService;
|
||||
import org.nutz.json.Json;
|
||||
import org.nutz.lang.util.NutMap;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 提案二级工会审核参与人。
|
||||
*/
|
||||
public class ProposalSecondaryUnionAssignmentHandler implements AssignmentHandler {
|
||||
|
||||
@Override
|
||||
public List<String> assign(TaskModel model, Execution execution) {
|
||||
NutMap variable = Json.fromJson(NutMap.class, execution.getProcessInstance().getVariable());
|
||||
ProposalInfo proposalInfo = variable.getAs(FlowConst.FORM_DATA, ProposalInfo.class);
|
||||
List<String> userIds = ServiceContext.find(ProposalCommonService.class).getProposalUnionRoleUserIds(proposalInfo,
|
||||
RoleConstant.BRANCH_UNION_CHAIRMAN.name(), RoleConstant.BRANCH_UNION_VICE_CHAIRMAN.name());
|
||||
if (userIds.isEmpty()) {
|
||||
throw new BaseException("提案人所属分工会未设置主席或副主席,无法流转到二级工会审核");
|
||||
}
|
||||
return userIds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return "提案人所属分工会主席或副主席";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return 230;
|
||||
}
|
||||
}
|
||||
+16
-8
@@ -18,7 +18,8 @@ import org.nutz.lang.util.NutMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 提案委员会主任
|
||||
* 提案委员会办理人。
|
||||
* 优先由届次内配置的提案委员会主任办理;历史届次未配置主任时,由副主任兜底办理。
|
||||
*/
|
||||
public class ProposalWyhAssignmentHandler implements AssignmentHandler {
|
||||
@Override
|
||||
@@ -29,19 +30,26 @@ public class ProposalWyhAssignmentHandler implements AssignmentHandler {
|
||||
String sessionId = info.getSessionId();
|
||||
|
||||
SysRoleService sysRoleService = ServiceContext.find(SysRoleService.class);
|
||||
Sys_role role = sysRoleService.getByCode(RoleConstant.PROPOSAL_COMMITTEE_DIRECTOR);
|
||||
Sys_role directorRole = sysRoleService.getByCode(RoleConstant.PROPOSAL_COMMITTEE_DIRECTOR);
|
||||
|
||||
Sys_user_role user_role = ServiceContext.find(Dao.class).fetch(Sys_user_role.class, Cnd.where(Sys_user_role::getRoleId, "=", role.getId()).and(Sys_user_role::getTcSessionId, "=", sessionId));
|
||||
|
||||
if (user_role == null) {
|
||||
throw new RuntimeException("没有设置提案委员会主任,无法流转到下一步,请联系校工会进行设置。");
|
||||
Sys_user_role userRole = ServiceContext.find(Dao.class).fetch(Sys_user_role.class,
|
||||
Cnd.where(Sys_user_role::getRoleId, "=", directorRole.getId()).and(Sys_user_role::getTcSessionId, "=", sessionId));
|
||||
if (userRole == null) {
|
||||
Sys_role deputyDirectorRole = sysRoleService.getByCode(RoleConstant.PROPOSAL_COMMITTEE_DEPUTY_DIRECTOR);
|
||||
// 历史届次可能仅配置副主任,确保迁入提案可继续完成立案和承办单位确认。
|
||||
userRole = ServiceContext.find(Dao.class).fetch(Sys_user_role.class,
|
||||
Cnd.where(Sys_user_role::getRoleId, "=", deputyDirectorRole.getId()).and(Sys_user_role::getTcSessionId, "=", sessionId));
|
||||
}
|
||||
return List.of(user_role.getUserId());
|
||||
|
||||
if (userRole == null) {
|
||||
throw new RuntimeException("没有设置提案委员会主任或副主任,无法流转到下一步,请联系校工会进行设置。");
|
||||
}
|
||||
return List.of(userRole.getUserId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return "教代会提案委员会主任";
|
||||
return "教代会提案委员会主任(未配置时由副主任办理)";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+17
@@ -66,6 +66,23 @@ public interface ProposalExportService extends BaseService<ProposalInfo> {
|
||||
*/
|
||||
void exportProposalStatisticsAsDocx(ProposalQueryComprehensiveParam pageForm, HttpServletResponse response);
|
||||
|
||||
/**
|
||||
* 按综合导出专用提案模板导出单条提案。
|
||||
* 该模板保留提案人及审核环节的电子签名,不影响其他页面使用的通用提案导出模板。
|
||||
*
|
||||
* @param proposalId 提案ID
|
||||
* @param response HTTP 响应
|
||||
*/
|
||||
void exportProposalAsDocx(String proposalId, HttpServletResponse response);
|
||||
|
||||
/**
|
||||
* 按综合导出专用提案模板写入单条 DOCX,用于 ZIP 与汇集文档导出。
|
||||
*
|
||||
* @param proposalId 提案ID
|
||||
* @param outputStream DOCX 输出流
|
||||
*/
|
||||
void exportProposalAsDocx(String proposalId, ByteArrayOutputStream outputStream);
|
||||
|
||||
/**
|
||||
* 导出反馈表
|
||||
*
|
||||
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
package com.budwk.app.zhgh.democratic.proposal.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 提案业务短信服务。
|
||||
*
|
||||
* 短信是否实际下发由统一的 SmsService 配置开关控制,本服务仅负责还原提案业务的收件人和文案。
|
||||
*/
|
||||
public interface ProposalMessageService {
|
||||
|
||||
/**
|
||||
* 向本次新增的附议人发送邀请附议短信。
|
||||
*
|
||||
* @param proposalId 提案ID
|
||||
* @param seconderUserIds 本次新增附议人的用户ID列表
|
||||
*/
|
||||
void sendInviteSeconderMessage(String proposalId, List<String> seconderUserIds);
|
||||
|
||||
/**
|
||||
* 向提案人所属分工会的主席、副主席发送附议人数达标短信。
|
||||
*
|
||||
* @param proposalId 提案ID
|
||||
*/
|
||||
void sendSecondaryUnionMessage(String proposalId);
|
||||
}
|
||||
+1
-1
@@ -13,5 +13,5 @@ public interface ProposalSecondedService extends BaseService<ProposalSecond> {
|
||||
* 3. opinion:附议意见,写入附议记录的 opinion 字段。
|
||||
* 4. submitType:附议结果,1 表示同意,20 表示不同意。
|
||||
*/
|
||||
void updateSecondRecord(String proposalId, String taskActorUserId, String opinion, Integer submitType);
|
||||
boolean updateSecondRecord(String proposalId, String taskActorUserId, String opinion, Integer submitType);
|
||||
}
|
||||
|
||||
+20
@@ -1,5 +1,6 @@
|
||||
package com.budwk.app.zhgh.democratic.proposal.service.common;
|
||||
|
||||
import com.budwk.app.base.page.Pagination;
|
||||
import com.budwk.app.base.service.BaseService;
|
||||
import com.budwk.app.base.param.PageForm;
|
||||
import com.budwk.app.base.param.ExportTableColumns;
|
||||
@@ -37,6 +38,25 @@ public interface ProposalCommonService extends BaseService<ProposalInfo> {
|
||||
*/
|
||||
boolean applySafeProposalListOrder(Cnd cnd, PageForm pageForm, String pageCode);
|
||||
|
||||
/**
|
||||
* 查询提案流程审核页面的数据,确保页面任务范围、参与人范围和排序规则保持一致。
|
||||
*
|
||||
* @param pageCode 审核页面代码
|
||||
* @param pageForm 页面筛选条件
|
||||
* @param approval 是否查询已审核记录
|
||||
* @return 审核任务分页数据
|
||||
*/
|
||||
Pagination getWorkflowAuditPage(String pageCode, ProposalSearchParam pageForm, boolean approval);
|
||||
|
||||
/**
|
||||
* 根据提案发起人所属分工会,查询指定角色的有效用户。
|
||||
*
|
||||
* @param proposalInfo 提案信息
|
||||
* @param roleCodes 参与人角色
|
||||
* @return 可参与流程的用户 ID
|
||||
*/
|
||||
List<String> getProposalUnionRoleUserIds(ProposalInfo proposalInfo, String... roleCodes);
|
||||
|
||||
/**
|
||||
* 按白名单字段对已汇总的统计结果进行后端排序。
|
||||
*
|
||||
|
||||
+117
-1
@@ -13,6 +13,7 @@ import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
|
||||
import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity;
|
||||
import com.budwk.app.base.constant.RoleConstant;
|
||||
import com.budwk.app.base.exception.BaseException;
|
||||
import com.budwk.app.base.page.Pagination;
|
||||
import com.budwk.app.base.param.ExportTableColumns;
|
||||
import com.budwk.app.base.param.PageForm;
|
||||
import com.budwk.app.base.service.impl.BaseServiceImpl;
|
||||
@@ -34,6 +35,7 @@ import com.budwk.app.sys.models.Sys_user_role;
|
||||
import com.budwk.app.sys.services.SysDictService;
|
||||
import com.budwk.app.sys.services.SysRoleService;
|
||||
import com.budwk.app.sys.services.SysUserService;
|
||||
import com.budwk.app.sys.views.View_user;
|
||||
import com.budwk.app.web.commons.auth.utils.AuthUtil;
|
||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||
import com.budwk.app.web.commons.base.Globals;
|
||||
@@ -147,6 +149,114 @@ public class ProposalCommonServiceImpl extends BaseServiceImpl<ProposalInfo> imp
|
||||
return applySafePageOrder(cnd, pageForm, PROPOSAL_LIST_ORDER_COLUMNS.get(pageCode));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询二级工会、院级党组织审核页面的任务数据。页面代码由控制器固定传入,
|
||||
* 防止请求参数篡改任务节点范围。
|
||||
*/
|
||||
@Override
|
||||
public Pagination getWorkflowAuditPage(String pageCode, ProposalSearchParam pageForm, boolean approval) {
|
||||
if (!Set.of("secondaryUnionAudit", "partyOrganizationAudit").contains(pageCode)) {
|
||||
throw new BaseException("不支持的提案审核页面");
|
||||
}
|
||||
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
info.*,
|
||||
type.name AS typeName,
|
||||
tcs.fullName AS sessionName,
|
||||
tcd.`name` AS delegationName,
|
||||
ins.id AS instanceId,
|
||||
ins.businessNo,
|
||||
ins.state AS instanceState,
|
||||
ins.variable AS instanceVariable,
|
||||
ins.processDefineId AS instanceProcessDefineId,
|
||||
t.id AS taskId,
|
||||
t.taskName AS taskKey,
|
||||
t.displayName AS taskName,
|
||||
t.taskType,
|
||||
t.performType AS taskPerformType,
|
||||
t.taskState,
|
||||
t.finishTime,
|
||||
t.taskParentId,
|
||||
t.variable AS taskVariable,
|
||||
IFNULL(GROUP_CONCAT(DISTINCT nt.displayName), '结束') AS curTaskName,
|
||||
IF(rt.id IS NOT NULL, 1, 0) AS canRevoke
|
||||
FROM wf_process_task t
|
||||
LEFT JOIN wf_process_instance ins ON ins.id = t.processInstanceId
|
||||
LEFT JOIN wf_process_task_actor ta ON ta.processTaskId = t.id
|
||||
LEFT JOIN wf_process_task nt ON nt.processInstanceId = ins.id AND nt.taskState = 10
|
||||
LEFT JOIN wf_process_task rt ON rt.processInstanceId = ins.id AND rt.taskParentId = t.id AND rt.taskState = 10
|
||||
LEFT JOIN proposal_info info ON info.id = ins.businessNo
|
||||
LEFT JOIN proposal_type type ON type.id = info.typeId
|
||||
LEFT JOIN teacher_congress_session tcs ON tcs.id = info.sessionId
|
||||
LEFT JOIN teacher_congress_delegation tcd ON tcd.id = info.delegationId
|
||||
$condition
|
||||
""");
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.and("t.taskName", "=", getWorkflowTaskName(pageCode));
|
||||
if (!AuthUtil.hasRole(RoleConstant.SYSADMIN.name())) {
|
||||
cnd.and("ta.actorId", "=", SecurityUtil.getUserId());
|
||||
}
|
||||
if (approval) {
|
||||
cnd.and("t.taskState", "in", List.of(ProcessTaskStateEnum.FINISHED.getCode(), ProcessTaskStateEnum.INTERRUPT.getCode()));
|
||||
} else {
|
||||
cnd.and("t.taskState", "=", ProcessTaskStateEnum.DOING.getCode());
|
||||
}
|
||||
ProposalSearchParam.buildSearch(cnd, pageForm);
|
||||
cnd.groupBy("t.id");
|
||||
if (!applySafeProposalListOrder(cnd, pageForm, pageCode)) {
|
||||
cnd.desc("t.createdAt");
|
||||
}
|
||||
sql.setCondition(cnd);
|
||||
return listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* 提案未保存分工会字段,流程分派时以提案人当前所属分工会为准,
|
||||
* 并过滤已删除、已禁用或不存在的人员,避免把无效角色关系写入流程任务。
|
||||
*/
|
||||
@Override
|
||||
public List<String> getProposalUnionRoleUserIds(ProposalInfo proposalInfo, String... roleCodes) {
|
||||
if (proposalInfo == null || StrUtil.isBlank(proposalInfo.getCreateUserId())) {
|
||||
throw new BaseException("提案缺少提案人,无法确定审核人员");
|
||||
}
|
||||
if (roleCodes == null || roleCodes.length == 0) {
|
||||
throw new BaseException("未配置审核人员角色");
|
||||
}
|
||||
|
||||
View_user proposalUser = dao().fetch(View_user.class,
|
||||
Cnd.where(View_user::getId, "=", proposalInfo.getCreateUserId()));
|
||||
if (proposalUser == null || StrUtil.isBlank(proposalUser.getUnionId())) {
|
||||
throw new BaseException("提案人未设置所属分工会,无法确定审核人员");
|
||||
}
|
||||
|
||||
List<String> roleIds = Arrays.stream(roleCodes)
|
||||
.filter(StrUtil::isNotBlank)
|
||||
.map(sysRoleService::getByCode)
|
||||
.filter(Objects::nonNull)
|
||||
.map(Sys_role::getId)
|
||||
.toList();
|
||||
if (roleIds.isEmpty()) {
|
||||
throw new BaseException("审核人员角色不存在,请联系校工会进行设置");
|
||||
}
|
||||
|
||||
List<Sys_user_role> userRoles = dao().query(Sys_user_role.class,
|
||||
Cnd.where(Sys_user_role::getRoleId, "in", roleIds)
|
||||
.and(Sys_user_role::getUnionId, "=", proposalUser.getUnionId()));
|
||||
return userRoles.stream()
|
||||
.map(Sys_user_role::getUserId)
|
||||
.filter(StrUtil::isNotBlank)
|
||||
.distinct()
|
||||
.filter(this::isEnabledUser)
|
||||
.toList();
|
||||
}
|
||||
|
||||
/** 校验流程参与人仍是可用系统用户。 */
|
||||
private boolean isEnabledUser(String userId) {
|
||||
Sys_user user = dao().fetch(Sys_user.class, userId);
|
||||
return user != null && !Boolean.TRUE.equals(user.getDelFlag()) && !user.isDisabled();
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建各列表页独立排序白名单,显示字段与真实SQL字段或固定查询别名一一对应。
|
||||
*
|
||||
@@ -163,6 +273,8 @@ public class ProposalCommonServiceImpl extends BaseServiceImpl<ProposalInfo> imp
|
||||
pages.put("commissioner", orderColumns("code", "info.code", "name", "info.name", "typeName", "type.name", "sessionName", "tcs.fullName", "delegationName", "tcd.name", "CONFIRM_FILING_COUNT", "CONFIRM_FILING_COUNT", "SUGGESTION_COUNT", "SUGGESTION_COUNT", "NOT_COUNT", "NOT_COUNT", "taskName", "taskName", "instanceState", "ins.state"));
|
||||
pages.put("feedbackEvaluation", orderColumns("code", "info.code", "name", "info.name", "typeName", "type.name", "merge", "merge", "curTaskName", "curTaskName", "instanceState", "ins.state"));
|
||||
pages.put("delegation", standardOrderColumns());
|
||||
pages.put("secondaryUnionAudit", standardOrderColumns());
|
||||
pages.put("partyOrganizationAudit", standardOrderColumns());
|
||||
pages.put("control", standardOrderColumns());
|
||||
pages.put("schoolLeaderApproval", orderColumns("code", "info.code", "name", "info.name", "typeName", "type.name", "undertakeUnits", "masterUnitName", "merge", "merge", "curTaskName", "curTaskName", "auditUser", "auditUser", "instanceState", "ins.state"));
|
||||
pages.put("committeeFilingUnit", orderColumns("code", "info.code", "name", "info.name", "typeName", "type.name", "sessionName", "tcs.fullName", "caseFilingResult", "info.caseFilingResult", "delegationName", "tcd.name", "curTaskName", "curTaskName", "instanceState", "ins.state"));
|
||||
@@ -252,7 +364,7 @@ public class ProposalCommonServiceImpl extends BaseServiceImpl<ProposalInfo> imp
|
||||
private Sql buildWorkflowExportSql(String pageCode, ProposalSearchParam pageForm, boolean approval) {
|
||||
boolean isUnitReply = "unitReply".equals(pageCode);
|
||||
boolean isSchoolLeaderApproval = "schoolLeaderApproval".equals(pageCode);
|
||||
boolean requiresUnionFilter = Set.of("preAudit", "committeeFiling", "committeeFilingUnit",
|
||||
boolean requiresUnionFilter = Set.of("preAudit", "secondaryUnionAudit", "partyOrganizationAudit", "committeeFiling", "committeeFilingUnit",
|
||||
"schoolLeaderApproval", "caseCheck").contains(pageCode);
|
||||
String taskName = getWorkflowTaskName(pageCode);
|
||||
|
||||
@@ -341,6 +453,8 @@ public class ProposalCommonServiceImpl extends BaseServiceImpl<ProposalInfo> imp
|
||||
Map<String, String> taskNames = Map.of(
|
||||
"delegation", "delegation",
|
||||
"preAudit", "preAudit",
|
||||
"secondaryUnionAudit", "secondaryUnionAudit",
|
||||
"partyOrganizationAudit", "partyOrganizationAudit",
|
||||
"committeeFiling", "committee",
|
||||
"committeeFilingUnit", "committeeFilingUnit",
|
||||
"schoolLeaderApproval", "schoolLeader",
|
||||
@@ -414,6 +528,8 @@ public class ProposalCommonServiceImpl extends BaseServiceImpl<ProposalInfo> imp
|
||||
Map<String, Set<String>> columns = new HashMap<>();
|
||||
columns.put("delegation", commonColumns);
|
||||
columns.put("preAudit", commonColumns);
|
||||
columns.put("secondaryUnionAudit", commonColumns);
|
||||
columns.put("partyOrganizationAudit", commonColumns);
|
||||
columns.put("caseCheck", Set.of("code", "caseFilingCode", "name", "createUserName", "typeName",
|
||||
"sessionName", "delegationName", "curTaskName", "instanceState", "finishTime"));
|
||||
columns.put("committeeFiling", Set.of("code", "caseFilingCode", "name", "typeName", "sessionName",
|
||||
|
||||
+180
-2
@@ -5,6 +5,8 @@ import cn.afterturn.easypoi.excel.entity.ExportParams;
|
||||
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
|
||||
import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity;
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.lang.Dict;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.http.HtmlUtil;
|
||||
import com.budwk.app.base.exception.BaseException;
|
||||
@@ -580,7 +582,7 @@ public class ProposalExportServiceImpl extends BaseServiceImpl<ProposalInfo> imp
|
||||
ZipOutputStream zipOutputStream = new ZipOutputStream(bos);
|
||||
for (NutMap proposalRow : list) {
|
||||
try (ByteArrayOutputStream docxByteArrayOutputStream = new ByteArrayOutputStream()) {
|
||||
proposalCommonService.exportProposalAsDocx(proposalRow.getString("id"), docxByteArrayOutputStream);
|
||||
exportProposalAsDocx(proposalRow.getString("id"), docxByteArrayOutputStream);
|
||||
ZipEntry zipEntry = new ZipEntry(proposalRow.getString("code") + "-" + sanitizeZipFileName(proposalRow.getString("name")) + ".docx");
|
||||
zipOutputStream.putNextEntry(zipEntry);
|
||||
docxByteArrayOutputStream.writeTo(zipOutputStream);
|
||||
@@ -611,7 +613,7 @@ public class ProposalExportServiceImpl extends BaseServiceImpl<ProposalInfo> imp
|
||||
try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
|
||||
for (NutMap proposalRow : list) {
|
||||
try (ByteArrayOutputStream oneDocOut = new ByteArrayOutputStream()) {
|
||||
proposalCommonService.exportProposalAsDocx(proposalRow.getString("id"), oneDocOut);
|
||||
exportProposalAsDocx(proposalRow.getString("id"), oneDocOut);
|
||||
if (mergedDoc == null) {
|
||||
mergedDoc = new XWPFDocument(new ByteArrayInputStream(oneDocOut.toByteArray()));
|
||||
} else {
|
||||
@@ -642,6 +644,182 @@ public class ProposalExportServiceImpl extends BaseServiceImpl<ProposalInfo> imp
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exportProposalAsDocx(String proposalId, HttpServletResponse response) {
|
||||
ProposalInfo proposalInfo = fetch(proposalId);
|
||||
if (proposalInfo == null) {
|
||||
throw new BaseException("提案信息不存在");
|
||||
}
|
||||
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
|
||||
exportProposalAsDocx(proposalId, outputStream);
|
||||
CommonDownloadUtil.download(proposalInfo.getCode() + "-" + proposalInfo.getName() + ".docx",
|
||||
outputStream.toByteArray(), response);
|
||||
} catch (IOException e) {
|
||||
log.error("综合导出单条提案失败,proposalId={}", proposalId, e);
|
||||
throw new BaseException("导出失败");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exportProposalAsDocx(String proposalId, ByteArrayOutputStream outputStream) {
|
||||
NutMap proposal = queryProposalTemplateData(proposalId);
|
||||
if (proposal == null) {
|
||||
throw new BaseException("提案信息不存在");
|
||||
}
|
||||
proposal.put("sign", sysOfficeTemplateUtil.createPictureRenderData(proposal.getString("signature")));
|
||||
proposal.put("secondedUserName", queryAgreedSecondedUserNames(proposalId));
|
||||
proposal.put("brief", sysOfficeTemplateUtil.convertRichTextToDocText(proposal.getString("brief")));
|
||||
proposal.put("measures", sysOfficeTemplateUtil.convertRichTextToDocText(proposal.getString("measures")));
|
||||
|
||||
HtmlRenderPolicy htmlRenderPolicy = new HtmlRenderPolicy();
|
||||
htmlRenderPolicy.getConfig().setShowDefaultTableBorderInTableCell(true);
|
||||
Configure config = Configure.builder()
|
||||
.bind("proposal.brief", htmlRenderPolicy)
|
||||
.bind("proposal.measures", htmlRenderPolicy)
|
||||
.bind("opinion", htmlRenderPolicy)
|
||||
.build();
|
||||
|
||||
Map<String, Object> renderData = new HashMap<>();
|
||||
renderData.put("schoolName", Globals.AppName);
|
||||
renderData.put("proposal", proposal);
|
||||
renderData.put("secondaryUnitAuditList", queryLatestProposalAudit(proposalId, "secondaryUnionAudit", proposal));
|
||||
renderData.put("partyOrganizationAuditList", queryLatestProposalAudit(proposalId, "partyOrganizationAudit", proposal));
|
||||
renderData.put("caseUnitRecordList", queryLatestProposalAudit(proposalId, "committee", proposal));
|
||||
try {
|
||||
XWPFTemplate.compile(sysOfficeTemplateUtil.getTemplate("proposal"), config)
|
||||
.render(renderData)
|
||||
.writeAndClose(outputStream);
|
||||
} catch (IOException e) {
|
||||
log.error("综合导出提案模板渲染失败,proposalId={}", proposalId, e);
|
||||
throw new BaseException("导出失败");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询模板使用的提案基础信息。字段名称与 SWUFE 提案模板保持一致,
|
||||
* 使模板替换后无需改动业务代码中的占位符命名。
|
||||
*/
|
||||
private NutMap queryProposalTemplateData(String proposalId) {
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
info.code AS proposalCode,
|
||||
info.caseFilingCode,
|
||||
info.name AS proposalName,
|
||||
info.createUserName AS username,
|
||||
info.unitName,
|
||||
COALESCE(NULLIF(info.mobile, ''), user.mobile) AS mobile,
|
||||
user.email,
|
||||
info.signature,
|
||||
info.caseFilingResult,
|
||||
info.brief,
|
||||
info.measures,
|
||||
DATE_FORMAT(info.createTime, '%Y年%m月%d日') AS createTime
|
||||
FROM proposal_info info
|
||||
LEFT JOIN sys_user user ON user.id = info.createUserId
|
||||
WHERE info.id = @proposalId
|
||||
""");
|
||||
sql.setParam("proposalId", proposalId);
|
||||
sql.setCallback(Sqls.callback.map());
|
||||
execute(sql);
|
||||
return (NutMap) sql.getResult();
|
||||
}
|
||||
|
||||
/** 查询已同意的附议人姓名,按附议完成时间保持稳定排序。 */
|
||||
private String queryAgreedSecondedUserNames(String proposalId) {
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT GROUP_CONCAT(userName ORDER BY secondedTime SEPARATOR '、') AS secondedUserName
|
||||
FROM proposal_second
|
||||
WHERE proposalId = @proposalId AND isAgree = 1
|
||||
""");
|
||||
sql.setParam("proposalId", proposalId);
|
||||
sql.setCallback(Sqls.callback.str());
|
||||
execute(sql);
|
||||
return StrUtil.blankToDefault(sql.getString(), "");
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取指定审核节点最后一次已办记录,并从任务变量中获取办理人、意见和签字快照。
|
||||
* 历史退回后重新审核时,模板只展示最终有效的一次审核结果,避免重复打印旧意见。
|
||||
*/
|
||||
private List<NutMap> queryLatestProposalAudit(String proposalId, String taskName, NutMap proposal) {
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT task.variable, task.finishTime
|
||||
FROM wf_process_task task
|
||||
INNER JOIN wf_process_instance instance ON instance.id = task.processInstanceId
|
||||
WHERE instance.businessNo = @proposalId
|
||||
AND task.taskName = @taskName
|
||||
AND task.taskState = @finishedState
|
||||
ORDER BY task.finishTime DESC, task.id DESC
|
||||
LIMIT 1
|
||||
""");
|
||||
sql.setParam("proposalId", proposalId);
|
||||
sql.setParam("taskName", taskName);
|
||||
sql.setParam("finishedState", ProcessTaskStateEnum.FINISHED.getCode());
|
||||
sql.setCallback(Sqls.callback.map());
|
||||
execute(sql);
|
||||
NutMap task = (NutMap) sql.getResult();
|
||||
if (task == null) {
|
||||
return List.of();
|
||||
}
|
||||
Dict variable = parseTaskVariable(task.getString("variable"));
|
||||
NutMap audit = new NutMap();
|
||||
audit.put("username", getTaskVariableString(variable, "userName"));
|
||||
audit.put("opinion", getTaskVariableString(variable, "opinion"));
|
||||
audit.put("auditTime", task.getTime("finishTime") == null ? "" : DateUtil.formatDate(task.getTime("finishTime")));
|
||||
audit.put("sign", sysOfficeTemplateUtil.createPictureRenderData(getTaskVariableString(variable, "signature")));
|
||||
if ("committee".equals(taskName)) {
|
||||
audit.put("resultAudit", buildCommitteeResultAudit(variable, proposal));
|
||||
}
|
||||
return List.of(audit);
|
||||
}
|
||||
|
||||
/** 兼容当前流程变量与已迁移 V3 历史任务变量的字段前缀。 */
|
||||
private String getTaskVariableString(Dict variable, String fieldName) {
|
||||
String taskFormValue = variable.getStr(FlowConst.TASK_FORM_DATA_PREFIX + fieldName);
|
||||
if (StrUtil.isNotBlank(taskFormValue)) {
|
||||
return taskFormValue;
|
||||
}
|
||||
return StrUtil.blankToDefault(variable.getStr("f_" + fieldName), "");
|
||||
}
|
||||
|
||||
/** 流程变量损坏或为空时按空字典处理,确保单条导出不会因历史脏数据中断。 */
|
||||
private Dict parseTaskVariable(String variableJson) {
|
||||
if (StrUtil.isBlank(variableJson)) {
|
||||
return Dict.create();
|
||||
}
|
||||
try {
|
||||
return Json.fromJson(Dict.class, variableJson);
|
||||
} catch (Exception e) {
|
||||
log.warn("提案审核任务变量解析失败,将按空变量导出");
|
||||
return Dict.create();
|
||||
}
|
||||
}
|
||||
|
||||
/** 构建提案委员会立案结论,沿用 V3 模板中“结论 + 审核意见”的展示方式。 */
|
||||
private String buildCommitteeResultAudit(Dict variable, NutMap proposal) {
|
||||
String caseFilingResult = StrUtil.blankToDefault(getTaskVariableString(variable, "caseFilingResult"),
|
||||
proposal.getString("caseFilingResult"));
|
||||
if ("CONFIRM_FILING".equals(caseFilingResult)) {
|
||||
String masterUnitName = getTaskVariableString(variable, "masterUnitNameStr");
|
||||
String slaveUnitName = getTaskVariableString(variable, "slaveUnitNameStr");
|
||||
String result = "经提案工作委员会研究,符合提案立案条件,予以立案";
|
||||
if (StrUtil.isNotBlank(masterUnitName)) {
|
||||
result += ",建议由" + masterUnitName + "办理";
|
||||
}
|
||||
if (StrUtil.isNotBlank(slaveUnitName)) {
|
||||
result += "," + slaveUnitName + "协办";
|
||||
}
|
||||
return result + "。";
|
||||
}
|
||||
if ("SUGGESTION".equals(caseFilingResult)) {
|
||||
return "作为意见建议转送参考。";
|
||||
}
|
||||
if ("NOT".equals(caseFilingResult)) {
|
||||
return "该提案不予立案。";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private List<NutMap> queryProposalBaseList(ProposalQueryComprehensiveParam pageForm) {
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
|
||||
+116
@@ -0,0 +1,116 @@
|
||||
package com.budwk.app.zhgh.democratic.proposal.service.impl;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.budwk.app.base.constant.RoleConstant;
|
||||
import com.budwk.app.base.sms.SmsService;
|
||||
import com.budwk.app.sys.models.Sys_user;
|
||||
import com.budwk.app.zhgh.democratic.proposal.models.ProposalInfo;
|
||||
import com.budwk.app.zhgh.democratic.proposal.service.ProposalMessageService;
|
||||
import com.budwk.app.zhgh.democratic.proposal.service.common.ProposalCommonService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 提案业务短信实现。
|
||||
*
|
||||
* 发送前不重复判断短信平台开关,统一交由 SmsService 按单点登录、系统参数和平台开关处理,
|
||||
* 避免提案模块和公共短信模块出现两套配置规则。
|
||||
*/
|
||||
@IocBean(args = {"refer:dao"})
|
||||
@Slf4j
|
||||
public class ProposalMessageServiceImpl implements ProposalMessageService {
|
||||
|
||||
private static final String INVITE_SECONDER_TEMPLATE = "{}代表,您好,{}代表的提案《{}》,邀请您作为附议人,请您登陆学校智慧工会系统进行附议。";
|
||||
private static final String SECONDARY_UNION_TEMPLATE = "{}您好,{}代表的提案《{}》,已经完成附议,请您登陆学校智慧工会系统进行审核。";
|
||||
|
||||
private final Dao dao;
|
||||
|
||||
@Inject
|
||||
private SmsService smsService;
|
||||
@Inject
|
||||
private ProposalCommonService proposalCommonService;
|
||||
|
||||
public ProposalMessageServiceImpl(Dao dao) {
|
||||
this.dao = dao;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendInviteSeconderMessage(String proposalId, List<String> seconderUserIds) {
|
||||
ProposalInfo proposalInfo = getProposal(proposalId);
|
||||
if (proposalInfo == null || seconderUserIds == null || seconderUserIds.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
Sys_user proposalCreator = dao.fetch(Sys_user.class, proposalInfo.getCreateUserId());
|
||||
if (proposalCreator == null) {
|
||||
log.warn("提案邀请附议短信未发送,未找到提案人,proposalId={}", proposalId);
|
||||
return;
|
||||
}
|
||||
List<Sys_user> seconders = dao.query(Sys_user.class,
|
||||
Cnd.where(Sys_user::getId, "in", seconderUserIds));
|
||||
for (Sys_user seconder : seconders) {
|
||||
String content = StrUtil.format(INVITE_SECONDER_TEMPLATE, seconder.getUsername(),
|
||||
proposalCreator.getUsername(), proposalInfo.getName());
|
||||
sendSms(seconder, content, proposalId, "邀请附议人");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendSecondaryUnionMessage(String proposalId) {
|
||||
ProposalInfo proposalInfo = getProposal(proposalId);
|
||||
if (proposalInfo == null) {
|
||||
return;
|
||||
}
|
||||
Sys_user proposalCreator = dao.fetch(Sys_user.class, proposalInfo.getCreateUserId());
|
||||
if (proposalCreator == null) {
|
||||
log.warn("提案附议达标短信未发送,未找到提案人,proposalId={}", proposalId);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
List<String> reviewerIds = proposalCommonService.getProposalUnionRoleUserIds(proposalInfo,
|
||||
RoleConstant.BRANCH_UNION_CHAIRMAN.name(), RoleConstant.BRANCH_UNION_VICE_CHAIRMAN.name());
|
||||
if (reviewerIds.isEmpty()) {
|
||||
log.warn("提案附议达标短信未发送,提案人所属分工会未设置主席或副主席,proposalId={}", proposalId);
|
||||
return;
|
||||
}
|
||||
List<Sys_user> reviewers = dao.query(Sys_user.class, Cnd.where(Sys_user::getId, "in", reviewerIds));
|
||||
for (Sys_user reviewer : reviewers) {
|
||||
String content = StrUtil.format(SECONDARY_UNION_TEMPLATE, reviewer.getUsername(),
|
||||
proposalCreator.getUsername(), proposalInfo.getName());
|
||||
sendSms(reviewer, content, proposalId, "附议人数达标");
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
// 短信通知失败不能影响已完成的附议业务和流程流转。
|
||||
log.error("提案附议达标短信发送失败,proposalId={}", proposalId, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送单个提案业务短信。
|
||||
*
|
||||
* SmsService 会按运行配置决定是否真实下发;没有工号的人员不能被短信平台识别,因此只记录并跳过。
|
||||
*/
|
||||
private void sendSms(Sys_user user, String content, String proposalId, String scene) {
|
||||
if (StrUtil.isBlank(user.getLoginname())) {
|
||||
log.warn("提案{}短信未发送,收件人未配置工号,proposalId={},userId={}", scene, proposalId, user.getId());
|
||||
return;
|
||||
}
|
||||
try {
|
||||
smsService.sendSmMsg(user.getLoginname(), content);
|
||||
} catch (RuntimeException e) {
|
||||
// 短信平台异常不能影响提案业务提交,异常留在日志中供后续排查。
|
||||
log.error("提案{}短信发送失败,proposalId={},userId={}", scene, proposalId, user.getId(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private ProposalInfo getProposal(String proposalId) {
|
||||
if (StrUtil.isBlank(proposalId)) {
|
||||
return null;
|
||||
}
|
||||
return dao.fetch(ProposalInfo.class, proposalId);
|
||||
}
|
||||
}
|
||||
+37
-4
@@ -4,34 +4,67 @@ import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.budwk.app.base.service.impl.BaseServiceImpl;
|
||||
import com.budwk.app.flow.enums.ProcessSubmitTypeEnum;
|
||||
import com.budwk.app.zhgh.democratic.proposal.models.ProposalConfig;
|
||||
import com.budwk.app.zhgh.democratic.proposal.models.ProposalSecond;
|
||||
import com.budwk.app.zhgh.democratic.proposal.service.ProposalMessageService;
|
||||
import com.budwk.app.zhgh.democratic.proposal.service.ProposalSecondedService;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.lang.Strings;
|
||||
|
||||
@IocBean(args = {"refer:dao"})
|
||||
public class ProposalSecondedServiceImpl extends BaseServiceImpl<ProposalSecond> implements ProposalSecondedService {
|
||||
|
||||
@Inject
|
||||
private ProposalMessageService proposalMessageService;
|
||||
|
||||
public ProposalSecondedServiceImpl(Dao dao) {
|
||||
super(dao);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateSecondRecord(String proposalId, String taskActorUserId, String opinion, Integer submitType) {
|
||||
public boolean updateSecondRecord(String proposalId, String taskActorUserId, String opinion, Integer submitType) {
|
||||
if (Strings.isBlank(proposalId) || Strings.isBlank(taskActorUserId) || submitType == null) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
// 仅更新当前提案、当前附议人的附议结果,不处理流程任务表。
|
||||
ProposalSecond proposalSecond = this.fetch(Cnd.where(ProposalSecond::getProposalId, "=", proposalId)
|
||||
.and(ProposalSecond::getSeconderId, "=", taskActorUserId));
|
||||
if (proposalSecond == null) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
proposalSecond.setIsAgree(ObjectUtil.equals(submitType, ProcessSubmitTypeEnum.AGREE.getCode()));
|
||||
boolean wasAgree = Boolean.TRUE.equals(proposalSecond.getIsAgree());
|
||||
boolean isAgree = ObjectUtil.equals(submitType, ProcessSubmitTypeEnum.AGREE.getCode());
|
||||
int agreedCountBefore = 0;
|
||||
if (isAgree && !wasAgree) {
|
||||
agreedCountBefore = this.count(Cnd.where(ProposalSecond::getProposalId, "=", proposalId)
|
||||
.and(ProposalSecond::getIsAgree, "=", true));
|
||||
}
|
||||
proposalSecond.setIsAgree(isAgree);
|
||||
proposalSecond.setOpinion(opinion);
|
||||
proposalSecond.setSecondedTime(DateUtil.date());
|
||||
this.update(proposalSecond);
|
||||
notifySecondaryUnionWhenThresholdReached(proposalId, isAgree, wasAgree, agreedCountBefore);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 仅在同意附议人数首次达到配置数量时发送二级工会审核短信,防止重复提交附议结果导致重复通知。
|
||||
*/
|
||||
private void notifySecondaryUnionWhenThresholdReached(String proposalId, boolean isAgree, boolean wasAgree,
|
||||
int agreedCountBefore) {
|
||||
if (!isAgree || wasAgree) {
|
||||
return;
|
||||
}
|
||||
ProposalConfig proposalConfig = this.dao().fetch(ProposalConfig.class, Cnd.NEW());
|
||||
if (proposalConfig == null || proposalConfig.getSeconderNum() == null || proposalConfig.getSeconderNum() <= 0) {
|
||||
return;
|
||||
}
|
||||
if (agreedCountBefore < proposalConfig.getSeconderNum()
|
||||
&& agreedCountBefore + 1 >= proposalConfig.getSeconderNum()) {
|
||||
proposalMessageService.sendSecondaryUnionMessage(proposalId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.budwk.app.zhgh.huazhu.constant;
|
||||
|
||||
public class HuaZhuConstant {
|
||||
/**
|
||||
* 华住接口请求超时,单位毫秒。
|
||||
*/
|
||||
public static final int TIMEOUT = 20000;
|
||||
|
||||
public static final String BASEURL = "https://htravelserver.huazhu.com";
|
||||
|
||||
public static final String OAUTH2_URL = "https://oauth2-api.huazhu.com";
|
||||
|
||||
/**
|
||||
* 公司卡号
|
||||
*/
|
||||
public static final String CARD_ID = "VCENTCRM1169099135";
|
||||
|
||||
/**
|
||||
* 公司密钥
|
||||
*/
|
||||
public static final String CARD_PASSWORD = "47CD8C9C-A4CD-4CBD-A30F-41C41BDF7E99";
|
||||
|
||||
/**
|
||||
* AES密钥
|
||||
*/
|
||||
public static final String AES_KEY = "JAE4YZJLXZW5HGBU";
|
||||
|
||||
/**
|
||||
* 客户端ID
|
||||
*/
|
||||
public static final String CLIENT_ID = "5e8651d8-a5a8-4358-9986-91f426e191c8";
|
||||
|
||||
/**
|
||||
* 客户端密钥
|
||||
*/
|
||||
public static final String CLIENT_SECRET = "2d20a7f3125b52b8e90936c3b30fb4b62b443a52716a090e55e302cf40f32b66d592ef1e98c1cf0a8e5ec3f9c444a9b4f53a337b1be57263d4fbb71044f67f12";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package com.budwk.app.zhgh.huazhu.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.zhgh.huazhu.param.HuaZhuEmployeePageForm;
|
||||
import com.budwk.app.zhgh.huazhu.service.HuaZhuEmployeeService;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.mvc.annotation.At;
|
||||
import org.nutz.mvc.annotation.Ok;
|
||||
import org.nutz.mvc.annotation.Param;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* PC 端华住员工同步管理。
|
||||
*/
|
||||
@IocBean
|
||||
@Ok("json:full")
|
||||
@At("/platform/huazhu")
|
||||
public class HuaZhuManageController {
|
||||
|
||||
@Inject
|
||||
private HuaZhuEmployeeService huaZhuEmployeeService;
|
||||
|
||||
@At("")
|
||||
@Ok("beetl:/platform/zhgh/huazhu/index.html")
|
||||
@SaCheckPermission("huazhu.manage")
|
||||
public void index() {
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("huazhu.manage")
|
||||
public Result pageData(@Valid HuaZhuEmployeePageForm pageForm) {
|
||||
return Result.success(huaZhuEmployeeService.pageUsers(pageForm));
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("huazhu.manage")
|
||||
public Result syncUsers(@Param("userIds") String[] userIds) {
|
||||
if (userIds == null || userIds.length == 0) {
|
||||
return Result.error("请先选择需要同步的员工");
|
||||
}
|
||||
return Result.success(huaZhuEmployeeService.syncUsers(Arrays.asList(userIds)));
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("huazhu.manage")
|
||||
public Result queryStatus(@Param("userId") String userId) {
|
||||
if (StrUtil.isBlank(userId)) {
|
||||
return Result.error("用户不能为空");
|
||||
}
|
||||
try {
|
||||
return Result.success(huaZhuEmployeeService.queryStatus(userId));
|
||||
} catch (IllegalArgumentException | IllegalStateException e) {
|
||||
return Result.error(e.getMessage());
|
||||
} catch (Exception e) {
|
||||
return Result.error("查询华住状态失败,请稍后重试");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.budwk.app.zhgh.huazhu.h5Controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||
import com.budwk.app.zhgh.huazhu.service.HuaZhuLoginService;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.mvc.annotation.At;
|
||||
import org.nutz.mvc.annotation.Ok;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* H5 幸福工荟中的华住免密登录入口。
|
||||
*/
|
||||
@IocBean
|
||||
@At("/platform/h5/huazhu")
|
||||
public class H5HuaZhuController {
|
||||
|
||||
@Inject
|
||||
private HuaZhuLoginService huaZhuLoginService;
|
||||
|
||||
/**
|
||||
* 校验幸福工荟访问权限后跳转至华住企业登录页面。
|
||||
*
|
||||
* @param response HTTP 响应,用于返回 302 跳转
|
||||
* @throws IOException 响应输出异常
|
||||
*/
|
||||
@At("/basicLogin")
|
||||
@Ok("void")
|
||||
@SaCheckPermission("h5.inclusive.benefit")
|
||||
public void basicLogin(HttpServletResponse response) throws IOException {
|
||||
response.setHeader("Cache-Control", "no-store");
|
||||
response.sendRedirect(huaZhuLoginService.buildBasicLoginUrl(SecurityUtil.getUserLoginname()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.budwk.app.zhgh.huazhu.param;
|
||||
|
||||
import com.budwk.app.base.param.PageForm;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 华住员工管理分页参数。
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class HuaZhuEmployeePageForm extends PageForm {
|
||||
private String searchKeyword;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.budwk.app.zhgh.huazhu.service;
|
||||
|
||||
import com.budwk.app.base.page.Pagination;
|
||||
import com.budwk.app.zhgh.huazhu.param.HuaZhuEmployeePageForm;
|
||||
import com.budwk.app.zhgh.huazhu.vo.HuaZhuEmployeeStatus;
|
||||
import com.budwk.app.zhgh.huazhu.vo.HuaZhuSyncResult;
|
||||
import org.nutz.lang.util.NutMap;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 华住员工同步与状态查询服务。
|
||||
*/
|
||||
public interface HuaZhuEmployeeService {
|
||||
|
||||
/**
|
||||
* 分页查询可同步的本项目员工。
|
||||
*
|
||||
* @param pageForm 查询参数
|
||||
* @return 员工分页数据
|
||||
*/
|
||||
Pagination<NutMap> pageUsers(HuaZhuEmployeePageForm pageForm);
|
||||
|
||||
/**
|
||||
* 将选中的本项目员工同步到华住。
|
||||
*
|
||||
* @param userIds 本项目用户主键列表
|
||||
* @return 每位员工的同步结果
|
||||
*/
|
||||
List<HuaZhuSyncResult> syncUsers(List<String> userIds);
|
||||
|
||||
/**
|
||||
* 查询指定本项目员工在华住的实时状态。
|
||||
*
|
||||
* @param userId 本项目用户主键
|
||||
* @return 华住员工状态
|
||||
*/
|
||||
HuaZhuEmployeeStatus queryStatus(String userId);
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.budwk.app.zhgh.huazhu.service;
|
||||
|
||||
/**
|
||||
* 华住免密登录服务。
|
||||
*/
|
||||
public interface HuaZhuLoginService {
|
||||
|
||||
/**
|
||||
* 按华住协议为当前职工工号生成免密登录跳转地址。
|
||||
*
|
||||
* @param loginName 当前登录职工的工号
|
||||
* @return 华住免密登录地址
|
||||
*/
|
||||
String buildBasicLoginUrl(String loginName);
|
||||
}
|
||||
@@ -0,0 +1,232 @@
|
||||
package com.budwk.app.zhgh.huazhu.service.impl;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.budwk.app.base.page.Pagination;
|
||||
import com.budwk.app.sys.models.Sys_user;
|
||||
import com.budwk.app.zhgh.huazhu.constant.HuaZhuConstant;
|
||||
import com.budwk.app.zhgh.huazhu.param.HuaZhuEmployeePageForm;
|
||||
import com.budwk.app.zhgh.huazhu.service.HuaZhuEmployeeService;
|
||||
import com.budwk.app.zhgh.huazhu.vo.HuaZhuEmployeeStatus;
|
||||
import com.budwk.app.zhgh.huazhu.vo.HuaZhuSyncResult;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.dao.Sqls;
|
||||
import org.nutz.dao.sql.Sql;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.lang.util.NutMap;
|
||||
import org.nutz.integration.jedis.RedisService;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Base64;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 华住员工同步与状态查询实现。
|
||||
*/
|
||||
@IocBean(args = {"refer:dao"})
|
||||
public class HuaZhuEmployeeServiceImpl implements HuaZhuEmployeeService {
|
||||
|
||||
private static final String TOKEN_CACHE_KEY = "zhgh:huazhu:oauth-token";
|
||||
|
||||
private final Dao dao;
|
||||
|
||||
@Inject
|
||||
private RedisService redisService;
|
||||
|
||||
public HuaZhuEmployeeServiceImpl(Dao dao) {
|
||||
this.dao = dao;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pagination<NutMap> pageUsers(HuaZhuEmployeePageForm pageForm) {
|
||||
String keyword = StrUtil.trim(pageForm.getSearchKeyword());
|
||||
String condition = " WHERE u.delFlag = 0 ";
|
||||
if (StrUtil.isNotBlank(keyword)) {
|
||||
condition += " AND (u.loginname LIKE @keyword OR u.username LIKE @keyword) ";
|
||||
}
|
||||
Sql countSql = Sqls.create("SELECT COUNT(1) FROM sys_user u" + condition);
|
||||
Sql listSql = Sqls.create("SELECT u.id, u.loginname, u.username, unit.name AS unitName "
|
||||
+ "FROM sys_user u LEFT JOIN sys_unit unit ON unit.id = u.unitId " + condition
|
||||
+ "ORDER BY u.createdAt DESC");
|
||||
if (StrUtil.isNotBlank(keyword)) {
|
||||
String likeKeyword = "%" + keyword + "%";
|
||||
countSql.setParam("keyword", likeKeyword);
|
||||
listSql.setParam("keyword", likeKeyword);
|
||||
}
|
||||
countSql.setCallback(Sqls.callback.integer());
|
||||
dao.execute(countSql);
|
||||
int totalCount = countSql.getInt();
|
||||
listSql.setPager(dao.createPager(pageForm.getPageNumber(), pageForm.getPageSize()));
|
||||
listSql.setCallback(Sqls.callback.maps());
|
||||
dao.execute(listSql);
|
||||
return new Pagination<>(pageForm.getPageNumber(), pageForm.getPageSize(), totalCount, listSql.getList(NutMap.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<HuaZhuSyncResult> syncUsers(List<String> userIds) {
|
||||
if (userIds == null || userIds.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<HuaZhuSyncResult> results = new ArrayList<>();
|
||||
for (String userId : userIds) {
|
||||
Sys_user user = findAvailableUser(userId);
|
||||
HuaZhuSyncResult result = new HuaZhuSyncResult()
|
||||
.setUserId(user.getId())
|
||||
.setLoginName(user.getLoginname())
|
||||
.setUserName(user.getUsername());
|
||||
try {
|
||||
request("/userInfo/addUser", buildEmployeeRequest(user.getLoginname()));
|
||||
result.setSuccess(true).setMessage("同步成功");
|
||||
} catch (Exception e) {
|
||||
result.setSuccess(false).setMessage("同步失败:" + safeMessage(e));
|
||||
}
|
||||
results.add(result);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HuaZhuEmployeeStatus queryStatus(String userId) {
|
||||
Sys_user user = findAvailableUser(userId);
|
||||
String body = request("/userInfo/queryUser", buildEmployeeRequest(user.getLoginname()));
|
||||
JSONObject payload = extractQueryPayload(body);
|
||||
try {
|
||||
return JSONUtil.toBean(payload, HuaZhuEmployeeStatus.class);
|
||||
} catch (Exception e) {
|
||||
throw new IllegalStateException("华住查询接口返回格式无法识别", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 兼容华住接口直接返回员工对象,以及以 data 或 result 包装员工对象的两种响应格式。
|
||||
* 响应中不包含员工状态时,只返回经筛选后的业务提示,避免透出第三方完整响应。
|
||||
*
|
||||
* @param body 华住查询接口响应正文
|
||||
* @return 可转换为员工状态的 JSON 对象
|
||||
*/
|
||||
private JSONObject extractQueryPayload(String body) {
|
||||
JSONObject response;
|
||||
try {
|
||||
response = JSONUtil.parseObj(body);
|
||||
} catch (Exception e) {
|
||||
throw new IllegalStateException("华住查询接口未返回有效数据", e);
|
||||
}
|
||||
JSONObject payload = extractObject(response, "data");
|
||||
if (payload == null) {
|
||||
payload = extractObject(response, "result");
|
||||
}
|
||||
if (payload != null) {
|
||||
return payload;
|
||||
}
|
||||
if (response.containsKey("statusCode") || response.containsKey("userNumber") || response.containsKey("userName")) {
|
||||
return response;
|
||||
}
|
||||
String message = StrUtil.blankToDefault(response.getStr("message"), response.getStr("msg"));
|
||||
throw new IllegalStateException(StrUtil.isBlank(message) ? "华住未返回该员工状态" : "华住查询失败:" + message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从包装响应中提取对象;部分网关会将 data/result 再序列化为 JSON 字符串。
|
||||
*
|
||||
* @param response 华住响应对象
|
||||
* @param key 包装字段名
|
||||
* @return 包装内的 JSON 对象,缺失或格式不匹配时返回 null
|
||||
*/
|
||||
private JSONObject extractObject(JSONObject response, String key) {
|
||||
Object value = response.get(key);
|
||||
if (value instanceof JSONObject) {
|
||||
return (JSONObject) value;
|
||||
}
|
||||
if (value instanceof CharSequence && StrUtil.isNotBlank(value.toString())) {
|
||||
try {
|
||||
return JSONUtil.parseObj(value.toString());
|
||||
} catch (Exception ignored) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 调用华住员工接口,并统一处理 OAuth Token 与非成功状态。
|
||||
*
|
||||
* @param path 华住接口路径
|
||||
* @param requestBody 请求体
|
||||
* @return 华住响应正文
|
||||
*/
|
||||
private String request(String path, NutMap requestBody) {
|
||||
HttpResponse response = HttpRequest.post(trimTrailingSlash(HuaZhuConstant.BASEURL) + path)
|
||||
.header("Authorization", getAccessToken())
|
||||
.header("accept", "application/json")
|
||||
.contentType("application/json; charset=UTF-8")
|
||||
.body(JSONUtil.toJsonStr(requestBody))
|
||||
.timeout(HuaZhuConstant.TIMEOUT)
|
||||
.execute();
|
||||
if (!response.isOk()) {
|
||||
throw new IllegalStateException("华住接口调用失败,状态码:" + response.getStatus());
|
||||
}
|
||||
return response.body();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取华住 OAuth Token,优先使用 Redis 缓存以避免频繁请求第三方认证接口。
|
||||
*
|
||||
* @return HTTP Authorization 头的 Bearer Token
|
||||
*/
|
||||
private String getAccessToken() {
|
||||
String cachedToken = redisService.get(TOKEN_CACHE_KEY);
|
||||
if (StrUtil.isNotBlank(cachedToken)) {
|
||||
return cachedToken;
|
||||
}
|
||||
String credential = Base64.getEncoder().encodeToString((HuaZhuConstant.CLIENT_ID + ":" + HuaZhuConstant.CLIENT_SECRET).getBytes(StandardCharsets.UTF_8));
|
||||
HttpResponse response = HttpRequest.post(trimTrailingSlash(HuaZhuConstant.OAUTH2_URL)
|
||||
+ "/oauth/token?scope=ALL&grant_type=client_credentials")
|
||||
.header("Authorization", "Basic " + credential)
|
||||
.timeout(HuaZhuConstant.TIMEOUT)
|
||||
.execute();
|
||||
if (!response.isOk()) {
|
||||
throw new IllegalStateException("获取华住认证 Token 失败,状态码:" + response.getStatus());
|
||||
}
|
||||
JSONObject tokenData = JSONUtil.parseObj(response.body());
|
||||
String accessToken = tokenData.getStr("access_token");
|
||||
String tokenType = StrUtil.blankToDefault(tokenData.getStr("token_type"), "Bearer");
|
||||
if (StrUtil.isBlank(accessToken)) {
|
||||
throw new IllegalStateException("华住认证接口未返回 Token");
|
||||
}
|
||||
String authorization = tokenType + " " + accessToken;
|
||||
redisService.setex(TOKEN_CACHE_KEY, 60 * 58, authorization);
|
||||
return authorization;
|
||||
}
|
||||
|
||||
private NutMap buildEmployeeRequest(String loginName) {
|
||||
return NutMap.NEW().addv("cardId", HuaZhuConstant.CARD_ID)
|
||||
.addv("cardPassWord", HuaZhuConstant.CARD_PASSWORD)
|
||||
.addv("userNumber", loginName);
|
||||
}
|
||||
|
||||
private Sys_user findAvailableUser(String userId) {
|
||||
Sys_user user = dao.fetch(Sys_user.class, Cnd.where("id", "=", userId).and("delFlag", "=", false));
|
||||
if (user == null) {
|
||||
throw new IllegalArgumentException("用户不存在或已删除");
|
||||
}
|
||||
if (StrUtil.isBlank(user.getLoginname())) {
|
||||
throw new IllegalArgumentException("用户缺少工号,无法同步华住");
|
||||
}
|
||||
return user;
|
||||
}
|
||||
|
||||
private String trimTrailingSlash(String value) {
|
||||
return value.endsWith("/") ? value.substring(0, value.length() - 1) : value;
|
||||
}
|
||||
|
||||
private String safeMessage(Exception e) {
|
||||
return StrUtil.isBlank(e.getMessage()) ? "请检查华住配置和网络连接" : e.getMessage();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package com.budwk.app.zhgh.huazhu.service.impl;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.budwk.app.zhgh.huazhu.constant.HuaZhuConstant;
|
||||
import com.budwk.app.zhgh.huazhu.service.HuaZhuLoginService;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Base64;
|
||||
|
||||
/**
|
||||
* 华住免密登录服务实现。
|
||||
*/
|
||||
@IocBean
|
||||
public class HuaZhuLoginServiceImpl implements HuaZhuLoginService {
|
||||
|
||||
private static final String TRAVEL_TYPE = "YS";
|
||||
|
||||
@Override
|
||||
public String buildBasicLoginUrl(String loginName) {
|
||||
if (StrUtil.isBlank(loginName)) {
|
||||
throw new IllegalArgumentException("当前登录用户缺少工号,无法进入华住");
|
||||
}
|
||||
|
||||
// 华住约定使用 AES/ECB/PKCS5Padding 对公司卡号、工号和当前时间生成签名。
|
||||
String authorizeSign = encrypt(HuaZhuConstant.CARD_ID + "&" + loginName + "&" + DateUtil.now(), HuaZhuConstant.AES_KEY);
|
||||
return trimTrailingSlash(HuaZhuConstant.BASEURL) + "/authentication/basicLogin?cardId=" + encode(HuaZhuConstant.CARD_ID)
|
||||
+ "&travelType=" + TRAVEL_TYPE
|
||||
+ "&userNumber=" + encode(loginName)
|
||||
+ "&invoiceNo="
|
||||
+ "&authorizeSign=" + encode(authorizeSign);
|
||||
}
|
||||
|
||||
/**
|
||||
* 按华住协议生成 AES 签名,不记录签名内容或密钥。
|
||||
*
|
||||
* @param source 待签名内容
|
||||
* @param aesKey 华住提供的 16 字节 AES 密钥
|
||||
* @return Base64 编码后的签名
|
||||
*/
|
||||
private String encrypt(String source, String aesKey) {
|
||||
try {
|
||||
byte[] keyBytes = aesKey.getBytes(StandardCharsets.UTF_8);
|
||||
if (keyBytes.length != 16) {
|
||||
throw new IllegalStateException("华住 AES 密钥必须为 16 字节");
|
||||
}
|
||||
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
|
||||
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(keyBytes, "AES"));
|
||||
return Base64.getEncoder().encodeToString(cipher.doFinal(source.getBytes(StandardCharsets.UTF_8)));
|
||||
} catch (IllegalStateException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
throw new IllegalStateException("生成华住登录签名失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
private String encode(String value) {
|
||||
return URLEncoder.encode(value, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
private String trimTrailingSlash(String value) {
|
||||
return value.endsWith("/") ? value.substring(0, value.length() - 1) : value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.budwk.app.zhgh.huazhu.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 华住查询员工接口的展示结果。
|
||||
*/
|
||||
@Data
|
||||
public class HuaZhuEmployeeStatus {
|
||||
private String statusCode;
|
||||
private String userNumber;
|
||||
private String userName;
|
||||
private String userDep;
|
||||
private String costCenter;
|
||||
private String rank;
|
||||
private String leader;
|
||||
private String mobile;
|
||||
private String email;
|
||||
private List<Permission> permissions;
|
||||
|
||||
/**
|
||||
* 华住返回的预订权限。
|
||||
*/
|
||||
@Data
|
||||
public static class Permission {
|
||||
private Boolean hasPermission;
|
||||
private String permissionCode;
|
||||
private String permissionValue;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.budwk.app.zhgh.huazhu.vo;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 单个员工同步到华住的执行结果。
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class HuaZhuSyncResult {
|
||||
private String userId;
|
||||
private String loginName;
|
||||
private String userName;
|
||||
private Boolean success;
|
||||
private String message;
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package com.budwk.app.zhgh.inclusive.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.zhgh.inclusive.model.InclusiveBenefit;
|
||||
import com.budwk.app.zhgh.inclusive.param.InclusiveBenefitPageForm;
|
||||
import com.budwk.app.zhgh.inclusive.service.InclusiveBenefitService;
|
||||
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||
import org.nutz.ioc.aop.Aop;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.mvc.annotation.At;
|
||||
import org.nutz.mvc.annotation.Ok;
|
||||
import org.nutz.mvc.annotation.Param;
|
||||
|
||||
import javax.validation.Valid;
|
||||
|
||||
/**
|
||||
* PC 端南航专惠管理。
|
||||
*/
|
||||
@IocBean
|
||||
@Ok("json:full")
|
||||
@At("/platform/inclusive")
|
||||
public class InclusiveBenefitController {
|
||||
|
||||
@Inject
|
||||
private InclusiveBenefitService inclusiveBenefitService;
|
||||
|
||||
@At("")
|
||||
@Ok("beetl:/platform/zhgh/inclusive/index.html")
|
||||
@SaCheckPermission("inclusive.benefit")
|
||||
public void index() {
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("inclusive.benefit")
|
||||
public Result pageData(@Valid InclusiveBenefitPageForm pageForm) {
|
||||
return Result.success(inclusiveBenefitService.pageData(pageForm));
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("inclusive.benefit")
|
||||
public Result findOne(@Param("id") String id) {
|
||||
return Result.success(inclusiveBenefitService.findVO(id, false));
|
||||
}
|
||||
|
||||
@At
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
@SaCheckPermission("inclusive.benefit")
|
||||
public Result save(InclusiveBenefit benefit, @Param("status") Integer status) {
|
||||
if (benefit == null || StrUtil.isBlank(benefit.getTitle())) {
|
||||
return Result.error("标题不能为空");
|
||||
}
|
||||
if (StrUtil.isBlank(benefit.getTagType())) {
|
||||
return Result.error("标签类型不能为空");
|
||||
}
|
||||
inclusiveBenefitService.saveBenefit(benefit, status);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@At
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
@SaCheckPermission("inclusive.benefit")
|
||||
public Result updateStatus(@Param("id") String id, @Param("status") Integer status) {
|
||||
inclusiveBenefitService.updateStatus(id, status);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@At
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
@SaCheckPermission("inclusive.benefit")
|
||||
public Result delete(@Param("id") String id) {
|
||||
inclusiveBenefitService.deleteBenefit(id);
|
||||
return Result.success();
|
||||
}
|
||||
}
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
package com.budwk.app.zhgh.inclusive.h5Controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.zhgh.inclusive.param.InclusiveBenefitPageForm;
|
||||
import com.budwk.app.zhgh.inclusive.service.InclusiveBenefitService;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.mvc.annotation.At;
|
||||
import org.nutz.mvc.annotation.Ok;
|
||||
import org.nutz.mvc.annotation.Param;
|
||||
|
||||
import javax.validation.Valid;
|
||||
|
||||
/**
|
||||
* H5 端南航专惠浏览。
|
||||
*/
|
||||
@IocBean
|
||||
@Ok("json:full")
|
||||
@At("/platform/h5/inclusive")
|
||||
public class H5InclusiveBenefitController {
|
||||
|
||||
@Inject
|
||||
private InclusiveBenefitService inclusiveBenefitService;
|
||||
|
||||
@At("")
|
||||
@Ok("beetl:/platform/zhghh5/inclusive/index.html")
|
||||
@SaCheckPermission("h5.inclusive.benefit")
|
||||
public void index() {
|
||||
}
|
||||
|
||||
@At("/detail")
|
||||
@Ok("beetl:/platform/zhghh5/inclusive/detail.html")
|
||||
@SaCheckPermission("h5.inclusive.benefit")
|
||||
public void detail() {
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("h5.inclusive.benefit")
|
||||
public Result pageData(@Valid InclusiveBenefitPageForm pageForm) {
|
||||
return Result.success(inclusiveBenefitService.pageData(pageForm));
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("h5.inclusive.benefit")
|
||||
public Result findOne(@Param("id") String id) {
|
||||
return Result.success(inclusiveBenefitService.findVO(id, true));
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("h5.inclusive.benefit")
|
||||
public Result tagOptions() {
|
||||
return Result.success(inclusiveBenefitService.tagOptions());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package com.budwk.app.zhgh.inclusive.model;
|
||||
|
||||
import com.budwk.app.base.model.BaseModel;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.nutz.dao.entity.annotation.ColDefine;
|
||||
import org.nutz.dao.entity.annotation.ColType;
|
||||
import org.nutz.dao.entity.annotation.Column;
|
||||
import org.nutz.dao.entity.annotation.Comment;
|
||||
import org.nutz.dao.entity.annotation.EL;
|
||||
import org.nutz.dao.entity.annotation.Name;
|
||||
import org.nutz.dao.entity.annotation.Table;
|
||||
import org.nutz.dao.interceptor.annotation.PrevInsert;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 南航专惠内容。
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Table("inclusive_benefit")
|
||||
@Comment("南航专惠")
|
||||
public class InclusiveBenefit extends BaseModel implements Serializable {
|
||||
|
||||
@Name
|
||||
@Column
|
||||
@Comment("主键")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
@PrevInsert(els = @EL("uuid()"))
|
||||
private String id;
|
||||
|
||||
@Column
|
||||
@Comment("年度")
|
||||
@ColDefine(type = ColType.INT)
|
||||
private Integer year;
|
||||
|
||||
@Column
|
||||
@Comment("标题")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||
private String title;
|
||||
|
||||
@Column
|
||||
@Comment("摘要")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 500)
|
||||
private String summary;
|
||||
|
||||
@Column
|
||||
@Comment("标签类型字典编码")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 50)
|
||||
private String tagType;
|
||||
|
||||
@Column
|
||||
@Comment("富文本内容")
|
||||
@ColDefine(type = ColType.TEXT)
|
||||
private String content;
|
||||
|
||||
@Column
|
||||
@Comment("性别限制:0全部开放,1男性,2女性")
|
||||
@ColDefine(type = ColType.INT)
|
||||
private Integer sexLimit;
|
||||
|
||||
@Column
|
||||
@Comment("封面图")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 255)
|
||||
private String cover;
|
||||
|
||||
@Column
|
||||
@Comment("外链地址")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 500)
|
||||
private String linkUrl;
|
||||
|
||||
@Column
|
||||
@Comment("发布状态:0草稿,1已发布")
|
||||
@ColDefine(type = ColType.INT)
|
||||
private Integer status;
|
||||
|
||||
@Column
|
||||
@Comment("发布时间")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 20)
|
||||
private String publishTime;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.budwk.app.zhgh.inclusive.param;
|
||||
|
||||
import com.budwk.app.base.param.PageForm;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 南航专惠分页查询参数。
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class InclusiveBenefitPageForm extends PageForm {
|
||||
private Integer year;
|
||||
private String title;
|
||||
private String tagType;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.budwk.app.zhgh.inclusive.service;
|
||||
|
||||
import com.budwk.app.base.page.Pagination;
|
||||
import com.budwk.app.base.service.BaseService;
|
||||
import com.budwk.app.zhgh.inclusive.model.InclusiveBenefit;
|
||||
import com.budwk.app.zhgh.inclusive.param.InclusiveBenefitPageForm;
|
||||
import com.budwk.app.zhgh.inclusive.vo.InclusiveBenefitVO;
|
||||
import org.nutz.lang.util.NutMap;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 南航专惠业务服务。
|
||||
*/
|
||||
public interface InclusiveBenefitService extends BaseService<InclusiveBenefit> {
|
||||
|
||||
Pagination<InclusiveBenefitVO> pageData(InclusiveBenefitPageForm pageForm);
|
||||
|
||||
InclusiveBenefitVO findVO(String id, boolean onlyPublished);
|
||||
|
||||
List<NutMap> tagOptions();
|
||||
|
||||
void saveBenefit(InclusiveBenefit benefit, Integer status);
|
||||
|
||||
void updateStatus(String id, Integer status);
|
||||
|
||||
void deleteBenefit(String id);
|
||||
}
|
||||
+170
@@ -0,0 +1,170 @@
|
||||
package com.budwk.app.zhgh.inclusive.service.impl;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.budwk.app.base.page.Pagination;
|
||||
import com.budwk.app.base.service.impl.BaseServiceImpl;
|
||||
import com.budwk.app.sys.models.Sys_dict;
|
||||
import com.budwk.app.zhgh.inclusive.model.InclusiveBenefit;
|
||||
import com.budwk.app.zhgh.inclusive.param.InclusiveBenefitPageForm;
|
||||
import com.budwk.app.zhgh.inclusive.service.InclusiveBenefitService;
|
||||
import com.budwk.app.zhgh.inclusive.vo.InclusiveBenefitVO;
|
||||
import org.nutz.dao.Chain;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.lang.Strings;
|
||||
import org.nutz.lang.util.NutMap;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 南航专惠业务实现。
|
||||
*/
|
||||
@IocBean(args = {"refer:dao"})
|
||||
public class InclusiveBenefitServiceImpl extends BaseServiceImpl<InclusiveBenefit> implements InclusiveBenefitService {
|
||||
|
||||
private static final String TAG_DICT_CODE = "INCLUSIVE_BENEFIT_TYPE";
|
||||
|
||||
public InclusiveBenefitServiceImpl(Dao dao) {
|
||||
super(dao);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pagination<InclusiveBenefitVO> pageData(InclusiveBenefitPageForm pageForm) {
|
||||
Cnd cnd = Cnd.where("delFlag", "=", false);
|
||||
if (pageForm.getYear() != null) {
|
||||
cnd.and("year", "=", pageForm.getYear());
|
||||
}
|
||||
if (Strings.isNotBlank(pageForm.getTitle())) {
|
||||
cnd.and(Cnd.likeEX("title", pageForm.getTitle()));
|
||||
}
|
||||
if (Strings.isNotBlank(pageForm.getTagType())) {
|
||||
cnd.and("tagType", "=", pageForm.getTagType());
|
||||
}
|
||||
cnd.desc("publishTime").desc("createdAt");
|
||||
Pagination<InclusiveBenefit> pagination = listPage(pageForm.getPageNumber(), pageForm.getPageSize(), cnd);
|
||||
Map<String, String> tagNameMap = getTagNameMap();
|
||||
List<InclusiveBenefitVO> list = pagination.getList().stream()
|
||||
.map(benefit -> toVO(benefit, tagNameMap))
|
||||
.collect(Collectors.toList());
|
||||
return new Pagination<>(pagination.getPageNo(), pagination.getPageSize(), pagination.getTotalCount(), list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InclusiveBenefitVO findVO(String id, boolean onlyPublished) {
|
||||
Cnd cnd = Cnd.where("id", "=", id).and("delFlag", "=", false);
|
||||
if (onlyPublished) {
|
||||
cnd.and("status", "=", 1);
|
||||
}
|
||||
return toVO(fetch(cnd), getTagNameMap());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<NutMap> tagOptions() {
|
||||
Sys_dict parent = dao().fetch(Sys_dict.class, Cnd.where("code", "=", TAG_DICT_CODE).and("delFlag", "=", false));
|
||||
if (parent == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return dao().query(Sys_dict.class, Cnd.where("parentId", "=", parent.getId())
|
||||
.and("disabled", "=", false).and("delFlag", "=", false).asc("location"))
|
||||
.stream()
|
||||
.map(dict -> NutMap.NEW().addv("text", dict.getName()).addv("value", dict.getCode()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveBenefit(InclusiveBenefit benefit, Integer status) {
|
||||
InclusiveBenefit target;
|
||||
if (StrUtil.isBlank(benefit.getId())) {
|
||||
target = new InclusiveBenefit();
|
||||
target.setYear(benefit.getYear() == null ? DateUtil.year(DateUtil.date()) : benefit.getYear());
|
||||
} else {
|
||||
target = fetch(Cnd.where("id", "=", benefit.getId()).and("delFlag", "=", false));
|
||||
if (target == null) {
|
||||
throw new IllegalArgumentException("南航专惠不存在或已删除");
|
||||
}
|
||||
target.setYear(benefit.getYear() == null ? target.getYear() : benefit.getYear());
|
||||
}
|
||||
target.setTitle(benefit.getTitle());
|
||||
target.setSummary(benefit.getSummary());
|
||||
target.setTagType(benefit.getTagType());
|
||||
target.setContent(benefit.getContent());
|
||||
target.setSexLimit(benefit.getSexLimit() == null ? 0 : benefit.getSexLimit());
|
||||
target.setCover(benefit.getCover());
|
||||
target.setLinkUrl(benefit.getLinkUrl());
|
||||
target.setStatus(status == null ? 0 : status);
|
||||
if (Integer.valueOf(1).equals(target.getStatus())) {
|
||||
target.setPublishTime(DateUtil.now());
|
||||
}
|
||||
if (StrUtil.isBlank(target.getId())) {
|
||||
insert(target);
|
||||
} else {
|
||||
update(target);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateStatus(String id, Integer status) {
|
||||
InclusiveBenefit benefit = fetch(Cnd.where("id", "=", id).and("delFlag", "=", false));
|
||||
if (benefit == null) {
|
||||
throw new IllegalArgumentException("南航专惠不存在或已删除");
|
||||
}
|
||||
Integer targetStatus = status == null ? 0 : status;
|
||||
Chain chain = Chain.make("status", targetStatus);
|
||||
if (Integer.valueOf(1).equals(targetStatus)) {
|
||||
chain.add("publishTime", DateUtil.now());
|
||||
}
|
||||
update(chain, Cnd.where("id", "=", id));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteBenefit(String id) {
|
||||
InclusiveBenefit benefit = fetch(Cnd.where("id", "=", id).and("delFlag", "=", false));
|
||||
if (benefit == null) {
|
||||
throw new IllegalArgumentException("南航专惠不存在或已删除");
|
||||
}
|
||||
vDelete(id);
|
||||
}
|
||||
|
||||
private InclusiveBenefitVO toVO(InclusiveBenefit benefit, Map<String, String> tagNameMap) {
|
||||
if (benefit == null) {
|
||||
return null;
|
||||
}
|
||||
return new InclusiveBenefitVO()
|
||||
.setId(benefit.getId())
|
||||
.setYear(benefit.getYear())
|
||||
.setTitle(benefit.getTitle())
|
||||
.setSummary(benefit.getSummary())
|
||||
.setTagType(benefit.getTagType())
|
||||
.setTagTypeName(tagNameMap.get(benefit.getTagType()))
|
||||
.setContent(benefit.getContent())
|
||||
.setSexLimit(benefit.getSexLimit())
|
||||
.setSexLimitName(getSexLimitName(benefit.getSexLimit()))
|
||||
.setCover(benefit.getCover())
|
||||
.setLinkUrl(benefit.getLinkUrl())
|
||||
.setStatus(benefit.getStatus())
|
||||
.setStatusName(Integer.valueOf(1).equals(benefit.getStatus()) ? "已发布" : "草稿")
|
||||
.setCreatedAt(benefit.getCreatedAt())
|
||||
.setUpdatedAt(benefit.getUpdatedAt())
|
||||
.setPublishTime(benefit.getPublishTime());
|
||||
}
|
||||
|
||||
private Map<String, String> getTagNameMap() {
|
||||
List<NutMap> options = tagOptions();
|
||||
return options.stream().collect(Collectors.toMap(option -> option.getString("value"), option -> option.getString("text")));
|
||||
}
|
||||
|
||||
private String getSexLimitName(Integer sexLimit) {
|
||||
if (Integer.valueOf(1).equals(sexLimit)) {
|
||||
return "男性";
|
||||
}
|
||||
if (Integer.valueOf(2).equals(sexLimit)) {
|
||||
return "女性";
|
||||
}
|
||||
return "全部开放";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.budwk.app.zhgh.inclusive.vo;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 南航专惠列表和详情展示对象。
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class InclusiveBenefitVO {
|
||||
private String id;
|
||||
private Integer year;
|
||||
private String title;
|
||||
private String summary;
|
||||
private String tagType;
|
||||
private String tagTypeName;
|
||||
private String content;
|
||||
private Integer sexLimit;
|
||||
private String sexLimitName;
|
||||
private String cover;
|
||||
private String linkUrl;
|
||||
private Integer status;
|
||||
private String statusName;
|
||||
private Long createdAt;
|
||||
private Long updatedAt;
|
||||
private String publishTime;
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
package com.budwk.app.zhgh.staffbenefit.difficultSubsidy.constants;
|
||||
|
||||
/**
|
||||
* 困难补助申请的业务状态。
|
||||
*
|
||||
* 仅用于草稿及流程结果的业务快照;审批中的真实状态以 TKBZ 工作流实例为准。
|
||||
*/
|
||||
public interface DifficultSubsidyState {
|
||||
|
||||
int TO_BE_SUBMITTED = 7000;
|
||||
int IN_PROCESS = 7010;
|
||||
int SCHOOL_REFUSE = 7050;
|
||||
int SCHOOL_BACK = 7060;
|
||||
int PASS = 7070;
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
package com.budwk.app.zhgh.staffbenefit.difficultSubsidy.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.dev33.satoken.annotation.SaMode;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.zhgh.staffbenefit.difficultSubsidy.service.DifficultSubsidyService;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.mvc.annotation.At;
|
||||
import org.nutz.mvc.annotation.Ok;
|
||||
|
||||
/**
|
||||
* 困难补助的公共查询接口。
|
||||
*/
|
||||
@IocBean
|
||||
@At("/platform/difficultSubsidy/common")
|
||||
@Ok("json")
|
||||
public class DifficultSubsidyCommonController {
|
||||
|
||||
@Inject
|
||||
private DifficultSubsidyService difficultSubsidyService;
|
||||
|
||||
@At
|
||||
@ApiOperation("查询申请详情及审核记录")
|
||||
@SaCheckPermission(value = {"difficultSubsidy.apply", "difficultSubsidy.mine",
|
||||
"difficultSubsidy.schoolAudit", "difficultSubsidy.query"}, mode = SaMode.OR)
|
||||
public Result findOne(String id) {
|
||||
return Result.success(difficultSubsidyService.findDetail(id));
|
||||
}
|
||||
|
||||
@At
|
||||
@ApiOperation("查询补助项目及疾病类型")
|
||||
@SaCheckPermission(value = {"difficultSubsidy.apply", "difficultSubsidy.mine",
|
||||
"difficultSubsidy.schoolAudit", "difficultSubsidy.query"}, mode = SaMode.OR)
|
||||
public Result projectInfo() {
|
||||
java.util.Map<String, Object> data = new java.util.HashMap<>();
|
||||
data.put("projectList", difficultSubsidyService.projectList());
|
||||
data.put("diseaseList", difficultSubsidyService.diseaseList(null, null));
|
||||
return Result.success(data);
|
||||
}
|
||||
}
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
package com.budwk.app.zhgh.staffbenefit.difficultSubsidy.controller.basicSetting;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.zhgh.staffbenefit.difficultSubsidy.models.DifficultSubsidyDiseaseType;
|
||||
import com.budwk.app.zhgh.staffbenefit.difficultSubsidy.models.DifficultSubsidyProject;
|
||||
import com.budwk.app.zhgh.staffbenefit.difficultSubsidy.service.DifficultSubsidyService;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.mvc.annotation.At;
|
||||
import org.nutz.mvc.annotation.Ok;
|
||||
import org.nutz.mvc.annotation.Param;
|
||||
|
||||
/**
|
||||
* 困难补助项目与疾病类型配置。
|
||||
*/
|
||||
@IocBean
|
||||
@At("/platform/difficultSubsidy/basicSetting/project")
|
||||
@Ok("json")
|
||||
public class DifficultSubsidyProjectController {
|
||||
|
||||
@Inject
|
||||
private DifficultSubsidyService difficultSubsidyService;
|
||||
|
||||
@At("")
|
||||
@SaCheckPermission("difficultSubsidy.basicSetting.project")
|
||||
@Ok("beetl:/platform/zhgh/staffbenefit/difficultSubsidy/basicSetting/project/index.html")
|
||||
public void index() {
|
||||
}
|
||||
|
||||
@At
|
||||
@ApiOperation("补助项目列表")
|
||||
@SaCheckPermission("difficultSubsidy.basicSetting.project")
|
||||
public Result projectList() {
|
||||
return Result.success(difficultSubsidyService.projectList());
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("difficultSubsidy.basicSetting.project")
|
||||
public Result saveProject(@Param("data") DifficultSubsidyProject project) {
|
||||
return Result.success(difficultSubsidyService.saveProject(project));
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("difficultSubsidy.basicSetting.project")
|
||||
public Result deleteProject(Integer id) {
|
||||
difficultSubsidyService.deleteProject(id);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("difficultSubsidy.basicSetting.project")
|
||||
public Result diseaseList(Integer projectId, String keyword) {
|
||||
return Result.success(difficultSubsidyService.diseaseList(projectId, keyword));
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("difficultSubsidy.basicSetting.project")
|
||||
public Result saveDisease(@Param("data") DifficultSubsidyDiseaseType diseaseType) {
|
||||
return Result.success(difficultSubsidyService.saveDisease(diseaseType));
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("difficultSubsidy.basicSetting.project")
|
||||
public Result deleteDisease(Integer id) {
|
||||
difficultSubsidyService.deleteDisease(id);
|
||||
return Result.success();
|
||||
}
|
||||
}
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
package com.budwk.app.zhgh.staffbenefit.difficultSubsidy.controller.process;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.zhgh.staffbenefit.difficultSubsidy.models.DifficultSubsidyApply;
|
||||
import com.budwk.app.zhgh.staffbenefit.difficultSubsidy.service.DifficultSubsidyService;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.mvc.annotation.At;
|
||||
import org.nutz.mvc.annotation.Ok;
|
||||
import org.nutz.mvc.annotation.Param;
|
||||
|
||||
/**
|
||||
* 特困补助申请表。
|
||||
*/
|
||||
@IocBean
|
||||
@At("/platform/difficultSubsidy/apply")
|
||||
@Ok("json")
|
||||
public class DifficultSubsidyApplyController {
|
||||
|
||||
@Inject
|
||||
private DifficultSubsidyService difficultSubsidyService;
|
||||
|
||||
@At("")
|
||||
@SaCheckPermission("difficultSubsidy.apply")
|
||||
@Ok("beetl:/platform/zhgh/staffbenefit/difficultSubsidy/process/apply/index.html")
|
||||
public void index() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 保留旧的表单子路径,避免已有链接失效;正式菜单入口仍为 /apply。
|
||||
*/
|
||||
@At("/form")
|
||||
@SaCheckPermission("difficultSubsidy.apply")
|
||||
@Ok("beetl:/platform/zhgh/staffbenefit/difficultSubsidy/process/apply/index.html")
|
||||
public void form() {
|
||||
}
|
||||
|
||||
@At
|
||||
@Ok("json")
|
||||
@SaCheckPermission("difficultSubsidy.apply")
|
||||
public Result save(@Param("data") DifficultSubsidyApply apply) {
|
||||
return Result.success(difficultSubsidyService.saveDraft(apply));
|
||||
}
|
||||
|
||||
@At
|
||||
@Ok("json")
|
||||
@SaCheckPermission("difficultSubsidy.apply")
|
||||
public Result submit(@Param("data") DifficultSubsidyApply apply) {
|
||||
return Result.success(difficultSubsidyService.submit(apply));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询当前登录人有权选择的补助申请人。
|
||||
*/
|
||||
@At
|
||||
@SaCheckPermission("difficultSubsidy.apply")
|
||||
public Result queryRecipients(String key) {
|
||||
return Result.success(difficultSubsidyService.listRecipients(key));
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("difficultSubsidy.apply")
|
||||
public Result findOne(String id) {
|
||||
return Result.success(difficultSubsidyService.findDetail(id));
|
||||
}
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
package com.budwk.app.zhgh.staffbenefit.difficultSubsidy.controller.process;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.base.utils.CommonDownloadUtil;
|
||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||
import com.budwk.app.zhgh.staffbenefit.difficultSubsidy.service.DifficultSubsidyService;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.mvc.annotation.At;
|
||||
import org.nutz.mvc.annotation.Ok;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* 当前登录人的特困补助申请记录。
|
||||
*/
|
||||
@IocBean
|
||||
@At("/platform/difficultSubsidy/mine")
|
||||
@Ok("json")
|
||||
public class DifficultSubsidyMineController {
|
||||
|
||||
@Inject
|
||||
private DifficultSubsidyService difficultSubsidyService;
|
||||
|
||||
@At("")
|
||||
@SaCheckPermission("difficultSubsidy.mine")
|
||||
@Ok("beetl:/platform/zhgh/staffbenefit/difficultSubsidy/process/mine/index.html")
|
||||
public void index() {
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("difficultSubsidy.mine")
|
||||
public Result pageData(Integer pageNumber, Integer pageSize, Integer year) {
|
||||
return Result.success(difficultSubsidyService.pageMine(
|
||||
pageNumber, pageSize, SecurityUtil.getUserId(), year));
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("difficultSubsidy.mine")
|
||||
public Result delete(String id) {
|
||||
difficultSubsidyService.deleteMineApplication(id, SecurityUtil.getUserId());
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@At
|
||||
@Ok("void")
|
||||
@SaCheckPermission("difficultSubsidy.mine")
|
||||
public void exportApplyInfo(String id, HttpServletResponse response) {
|
||||
CommonDownloadUtil.download("特困补助申请登记表.docx",
|
||||
difficultSubsidyService.exportApplyWord(id), response);
|
||||
}
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
package com.budwk.app.zhgh.staffbenefit.difficultSubsidy.controller.process;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.base.utils.CommonDownloadUtil;
|
||||
import com.budwk.app.zhgh.staffbenefit.difficultSubsidy.service.DifficultSubsidyService;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.mvc.annotation.At;
|
||||
import org.nutz.mvc.annotation.Ok;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* 已通过特困补助综合查询与汇总导出。
|
||||
*/
|
||||
@IocBean
|
||||
@At("/platform/difficultSubsidy/query")
|
||||
@Ok("json")
|
||||
public class DifficultSubsidyQueryController {
|
||||
|
||||
@Inject
|
||||
private DifficultSubsidyService difficultSubsidyService;
|
||||
|
||||
@At("")
|
||||
@SaCheckPermission("difficultSubsidy.query")
|
||||
@Ok("beetl:/platform/zhgh/staffbenefit/difficultSubsidy/query/index.html")
|
||||
public void index() {
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("difficultSubsidy.query")
|
||||
public Result pageData(Integer pageNumber, Integer pageSize,
|
||||
Integer year, String startMonth, String endMonth,
|
||||
String searchKeyword, String unionId, String unitId) {
|
||||
return Result.success(difficultSubsidyService.pageQuery(pageNumber, pageSize,
|
||||
year, startMonth, endMonth, searchKeyword, unionId, unitId));
|
||||
}
|
||||
|
||||
@At
|
||||
@Ok("void")
|
||||
@SaCheckPermission("difficultSubsidy.query")
|
||||
public void exportSummaryExcel(Integer year, String startMonth, String endMonth,
|
||||
HttpServletResponse response) {
|
||||
CommonDownloadUtil.download("特困补助人员名单.xlsx",
|
||||
difficultSubsidyService.exportSummaryExcel(year, startMonth, endMonth), response);
|
||||
}
|
||||
|
||||
@At
|
||||
@Ok("void")
|
||||
@SaCheckPermission("difficultSubsidy.query")
|
||||
public void exportSummary(Integer year, String startMonth, String endMonth,
|
||||
HttpServletResponse response) {
|
||||
CommonDownloadUtil.download("特困补助汇总表.docx",
|
||||
difficultSubsidyService.exportSummaryWord(year, startMonth, endMonth), response);
|
||||
}
|
||||
}
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
package com.budwk.app.zhgh.staffbenefit.difficultSubsidy.controller.process;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.base.utils.CommonDownloadUtil;
|
||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||
import com.budwk.app.zhgh.staffbenefit.difficultSubsidy.models.DifficultSubsidyApply;
|
||||
import com.budwk.app.zhgh.staffbenefit.difficultSubsidy.service.DifficultSubsidyService;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.mvc.annotation.At;
|
||||
import org.nutz.mvc.annotation.Ok;
|
||||
import org.nutz.mvc.annotation.Param;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* 特困补助校工会审核。
|
||||
*/
|
||||
@IocBean
|
||||
@At("/platform/difficultSubsidy/schoolAudit")
|
||||
@Ok("json")
|
||||
public class DifficultSubsidySchoolAuditController {
|
||||
|
||||
@Inject
|
||||
private DifficultSubsidyService difficultSubsidyService;
|
||||
|
||||
@At("")
|
||||
@SaCheckPermission("difficultSubsidy.schoolAudit")
|
||||
@Ok("beetl:/platform/zhgh/staffbenefit/difficultSubsidy/process/schoolAudit/index.html")
|
||||
public void index() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 复用申请表页面展示校工会修改表单,实际保存使用校工会专用接口。
|
||||
*/
|
||||
@At("/edit")
|
||||
@SaCheckPermission("difficultSubsidy.schoolAudit")
|
||||
@Ok("beetl:/platform/zhgh/staffbenefit/difficultSubsidy/process/apply/index.html")
|
||||
public void edit() {
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("difficultSubsidy.schoolAudit")
|
||||
public Result pageData(Integer pageNumber, Integer pageSize,
|
||||
Integer year, String startMonth, String endMonth,
|
||||
String searchKeyword, String unionId, String unitId, Integer isAudit) {
|
||||
return Result.success(difficultSubsidyService.pageSchoolAudit(pageNumber, pageSize,
|
||||
SecurityUtil.getUserId(), year, startMonth, endMonth,
|
||||
searchKeyword, unionId, unitId, isAudit));
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("difficultSubsidy.schoolAudit")
|
||||
public Result calculateSubsidy(String id) {
|
||||
return Result.success(difficultSubsidyService.calculateSubsidy(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改校工会待审核申请的基础表单信息,不推进工作流任务。
|
||||
*/
|
||||
@At
|
||||
@SaCheckPermission("difficultSubsidy.schoolAudit")
|
||||
public Result modifyApply(Long processTaskId, @Param("data") DifficultSubsidyApply apply) {
|
||||
difficultSubsidyService.modifySchoolAuditApply(processTaskId, apply);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("difficultSubsidy.schoolAudit")
|
||||
public Result executeTask(Long processTaskId, Integer submitType, String opinion,
|
||||
Float finalSubsidyAmount, String hospitalRecords) {
|
||||
difficultSubsidyService.executeSchoolAudit(processTaskId, submitType, opinion,
|
||||
finalSubsidyAmount, hospitalRecords);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("difficultSubsidy.schoolAudit")
|
||||
public Result revoke(Long processTaskId) {
|
||||
difficultSubsidyService.revokeSchoolAudit(processTaskId, SecurityUtil.getUserId());
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("difficultSubsidy.schoolAudit")
|
||||
public Result modifyFinalSubsidyAmount(String id, Float finalSubsidyAmount) {
|
||||
difficultSubsidyService.modifyFinalSubsidyAmount(id, finalSubsidyAmount);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@At
|
||||
@Ok("void")
|
||||
@SaCheckPermission("difficultSubsidy.schoolAudit")
|
||||
public void exportZip(Integer year, String startMonth, String endMonth,
|
||||
HttpServletResponse response) {
|
||||
CommonDownloadUtil.download("特困补助审核材料.zip",
|
||||
difficultSubsidyService.exportApprovedZip(year, startMonth, endMonth), response);
|
||||
}
|
||||
}
|
||||
+148
@@ -0,0 +1,148 @@
|
||||
package com.budwk.app.zhgh.staffbenefit.difficultSubsidy.models;
|
||||
|
||||
import com.budwk.app.base.model.BaseModel;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.nutz.dao.entity.annotation.ColDefine;
|
||||
import org.nutz.dao.entity.annotation.ColType;
|
||||
import org.nutz.dao.entity.annotation.Column;
|
||||
import org.nutz.dao.entity.annotation.Comment;
|
||||
import org.nutz.dao.entity.annotation.Name;
|
||||
import org.nutz.dao.interceptor.annotation.PrevInsert;
|
||||
import org.nutz.dao.entity.annotation.Table;
|
||||
import org.nutz.dao.entity.annotation.TableMeta;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 困难补助申请。申请提交后通过特困补助工作流处理,流程实例以本记录主键作为业务编号关联。
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Table("difficult_subsidy_apply")
|
||||
@TableMeta("{'mysql-charset':'utf8mb4'}")
|
||||
public class DifficultSubsidyApply extends BaseModel {
|
||||
|
||||
@Name
|
||||
@PrevInsert(uu32 = true)
|
||||
@Comment("主键")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
private String id;
|
||||
|
||||
@Comment("申请人用户ID")
|
||||
@Column
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
private String applyUserId;
|
||||
|
||||
@Comment("申请人姓名")
|
||||
@Column
|
||||
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||
private String applyUserName;
|
||||
|
||||
@Comment("申请人工号")
|
||||
@Column
|
||||
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||
private String applyLoginName;
|
||||
|
||||
@Comment("受助人用户ID")
|
||||
@Column
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
private String userId;
|
||||
|
||||
@Comment("受助人姓名")
|
||||
@Column
|
||||
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||
private String userName;
|
||||
|
||||
@Comment("受助人工号")
|
||||
@Column
|
||||
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||
private String loginName;
|
||||
|
||||
@Comment("性别")
|
||||
@Column
|
||||
@ColDefine(type = ColType.VARCHAR, width = 10)
|
||||
private String sex;
|
||||
|
||||
@Comment("年龄")
|
||||
@Column
|
||||
@ColDefine(type = ColType.INT)
|
||||
private Integer age;
|
||||
|
||||
@Comment("单位ID")
|
||||
@Column
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
private String unitId;
|
||||
|
||||
@Comment("单位名称")
|
||||
@Column
|
||||
@ColDefine(type = ColType.VARCHAR, width = 500)
|
||||
private String unitName;
|
||||
|
||||
@Comment("分工会ID")
|
||||
@Column
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
private String unionId;
|
||||
|
||||
@Comment("分工会名称")
|
||||
@Column
|
||||
@ColDefine(type = ColType.VARCHAR, width = 500)
|
||||
private String unionName;
|
||||
|
||||
@Comment("家庭住址")
|
||||
@Column
|
||||
@ColDefine(type = ColType.VARCHAR, width = 500)
|
||||
private String homeAddress;
|
||||
|
||||
@Comment("联系电话")
|
||||
@Column
|
||||
@ColDefine(type = ColType.VARCHAR, width = 50)
|
||||
private String mobile;
|
||||
|
||||
@Comment("补助项目ID集合")
|
||||
@Column
|
||||
@ColDefine(type = ColType.MYSQL_JSON)
|
||||
private List<Integer> subsidyType;
|
||||
|
||||
@Comment("申请补助原因")
|
||||
@Column
|
||||
@ColDefine(type = ColType.VARCHAR, width = 1000)
|
||||
private String reason;
|
||||
|
||||
@Comment("证明材料")
|
||||
@Column
|
||||
@ColDefine(type = ColType.MYSQL_JSON)
|
||||
private List<JSONObject> files;
|
||||
|
||||
@Comment("纸质申请表")
|
||||
@Column
|
||||
@ColDefine(type = ColType.MYSQL_JSON)
|
||||
private List<JSONObject> applyFile;
|
||||
|
||||
@Comment("住院记录")
|
||||
@Column
|
||||
@ColDefine(type = ColType.MYSQL_JSON)
|
||||
private List<JSONObject> hospitalRecords;
|
||||
|
||||
@Comment("申请时间")
|
||||
@Column
|
||||
@ColDefine(type = ColType.DATETIME)
|
||||
private Date applyDate;
|
||||
|
||||
@Comment("审核状态")
|
||||
@Column
|
||||
@ColDefine(type = ColType.INT)
|
||||
private Integer stateId;
|
||||
|
||||
@Comment("建议补助金额")
|
||||
@Column
|
||||
@ColDefine(type = ColType.FLOAT, width = 10)
|
||||
private Float subsidyAmount;
|
||||
|
||||
@Comment("最终补助金额")
|
||||
@Column
|
||||
@ColDefine(type = ColType.FLOAT, width = 10)
|
||||
private Float finalSubsidyAmount;
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
package com.budwk.app.zhgh.staffbenefit.difficultSubsidy.models;
|
||||
|
||||
import com.budwk.app.base.model.BaseModel;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.nutz.dao.entity.annotation.ColDefine;
|
||||
import org.nutz.dao.entity.annotation.ColType;
|
||||
import org.nutz.dao.entity.annotation.Column;
|
||||
import org.nutz.dao.entity.annotation.Comment;
|
||||
import org.nutz.dao.entity.annotation.Id;
|
||||
import org.nutz.dao.entity.annotation.Table;
|
||||
import org.nutz.dao.entity.annotation.TableMeta;
|
||||
|
||||
/**
|
||||
* 困难补助项目下的疾病及金额上限配置。
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Table("difficult_subsidy_disease_type")
|
||||
@TableMeta("{'mysql-charset':'utf8mb4'}")
|
||||
public class DifficultSubsidyDiseaseType extends BaseModel {
|
||||
|
||||
@Id(auto = true)
|
||||
@Comment("主键")
|
||||
@ColDefine(type = ColType.INT)
|
||||
private Integer id;
|
||||
|
||||
@Comment("补助项目ID")
|
||||
@Column
|
||||
@ColDefine(type = ColType.INT)
|
||||
private Integer projectId;
|
||||
|
||||
@Comment("疾病名称")
|
||||
@Column
|
||||
@ColDefine(type = ColType.VARCHAR, width = 200)
|
||||
private String diseaseName;
|
||||
|
||||
@Comment("补助金额上限")
|
||||
@Column
|
||||
@ColDefine(type = ColType.VARCHAR, width = 50)
|
||||
private String subsidyAmountUpperLimit;
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
package com.budwk.app.zhgh.staffbenefit.difficultSubsidy.models;
|
||||
|
||||
import com.budwk.app.base.model.BaseModel;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.nutz.dao.entity.annotation.ColDefine;
|
||||
import org.nutz.dao.entity.annotation.ColType;
|
||||
import org.nutz.dao.entity.annotation.Column;
|
||||
import org.nutz.dao.entity.annotation.Comment;
|
||||
import org.nutz.dao.entity.annotation.Id;
|
||||
import org.nutz.dao.entity.annotation.Many;
|
||||
import org.nutz.dao.entity.annotation.Table;
|
||||
import org.nutz.dao.entity.annotation.TableMeta;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 困难补助项目配置。
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Table("difficult_subsidy_project")
|
||||
@TableMeta("{'mysql-charset':'utf8mb4'}")
|
||||
public class DifficultSubsidyProject extends BaseModel {
|
||||
|
||||
@Id(auto = true)
|
||||
@Comment("主键")
|
||||
@ColDefine(type = ColType.INT)
|
||||
private Integer id;
|
||||
|
||||
@Comment("补助项目名称")
|
||||
@Column
|
||||
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||
private String projectName;
|
||||
|
||||
/**
|
||||
* 当前补助范围下的疾病或事项说明,仅用于关联查询,不单独落入项目表。
|
||||
*/
|
||||
@Many(target = DifficultSubsidyDiseaseType.class, field = "projectId", key = "id")
|
||||
private List<DifficultSubsidyDiseaseType> diseaseTypeList;
|
||||
}
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
package com.budwk.app.zhgh.staffbenefit.difficultSubsidy.service;
|
||||
|
||||
import com.budwk.app.base.page.Pagination;
|
||||
import com.budwk.app.base.service.BaseService;
|
||||
import com.budwk.app.zhgh.staffbenefit.difficultSubsidy.models.DifficultSubsidyApply;
|
||||
import com.budwk.app.zhgh.staffbenefit.difficultSubsidy.models.DifficultSubsidyDiseaseType;
|
||||
import com.budwk.app.zhgh.staffbenefit.difficultSubsidy.models.DifficultSubsidyProject;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.nutz.lang.util.NutMap;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 特困补助申请、审核、查询、配置和导出公共业务服务。
|
||||
*/
|
||||
public interface DifficultSubsidyService extends BaseService<DifficultSubsidyApply> {
|
||||
|
||||
DifficultSubsidyApply saveDraft(DifficultSubsidyApply apply);
|
||||
|
||||
DifficultSubsidyApply submit(DifficultSubsidyApply apply);
|
||||
|
||||
/**
|
||||
* 按当前用户的数据权限查询可选择的补助申请人。
|
||||
*
|
||||
* @param keyword 姓名或工号关键字
|
||||
* @return 最多十条申请人基础信息
|
||||
*/
|
||||
List<NutMap> listRecipients(String keyword);
|
||||
|
||||
/**
|
||||
* 查询当前登录人的申请记录及最新工作流状态。
|
||||
*/
|
||||
Pagination<NutMap> pageMine(Integer pageNumber, Integer pageSize, String applyUserId, Integer year);
|
||||
|
||||
/**
|
||||
* 查询当前审核人的校工会待办或已办记录,申请年份和月份范围共同约束申请时间。
|
||||
*/
|
||||
Pagination<NutMap> pageSchoolAudit(Integer pageNumber, Integer pageSize, String auditorId,
|
||||
Integer year, String startMonth, String endMonth,
|
||||
String searchKeyword, String unionId,
|
||||
String unitId, Integer isAudit);
|
||||
|
||||
/**
|
||||
* 查询指定申请年份、月份范围内最终通过的补助申请。
|
||||
*/
|
||||
Pagination<DifficultSubsidyApply> pageQuery(Integer pageNumber, Integer pageSize, Integer year,
|
||||
String startMonth, String endMonth,
|
||||
String searchKeyword, String unionId, String unitId);
|
||||
|
||||
/**
|
||||
* 返回申请、项目配置和工作流审核记录组成的完整查看数据。
|
||||
*/
|
||||
NutMap findDetail(String id);
|
||||
|
||||
List<DifficultSubsidyProject> projectList();
|
||||
|
||||
List<DifficultSubsidyDiseaseType> diseaseList(Integer projectId, String keyword);
|
||||
|
||||
DifficultSubsidyProject saveProject(DifficultSubsidyProject project);
|
||||
|
||||
DifficultSubsidyDiseaseType saveDisease(DifficultSubsidyDiseaseType diseaseType);
|
||||
|
||||
void deleteProject(Integer id);
|
||||
|
||||
void deleteDisease(Integer id);
|
||||
|
||||
/**
|
||||
* 删除当前登录人的特困补助申请,并同步清理该申请对应的流程实例、任务及待办办理人。
|
||||
*
|
||||
* @param id 申请记录ID
|
||||
* @param applyUserId 当前登录用户ID,用于校验申请归属
|
||||
*/
|
||||
void deleteMineApplication(String id, String applyUserId);
|
||||
|
||||
/**
|
||||
* 校工会审核期间修改申请基础表单信息,不变更申请人、受助人身份或流程状态。
|
||||
*
|
||||
* @param processTaskId 当前校工会审核待办任务ID
|
||||
* @param apply 页面提交的申请基础表单数据
|
||||
*/
|
||||
void modifySchoolAuditApply(Long processTaskId, DifficultSubsidyApply apply);
|
||||
|
||||
/**
|
||||
* 保存逐条补助项目审核结果与金额,并执行校工会工作流任务。
|
||||
*/
|
||||
void executeSchoolAudit(Long processTaskId, Integer submitType, String opinion,
|
||||
Float finalSubsidyAmount, String hospitalRecords);
|
||||
|
||||
/**
|
||||
* 撤销本人已经完成的校工会审核任务并重新激活该节点。
|
||||
*/
|
||||
void revokeSchoolAudit(Long processTaskId, String auditorId);
|
||||
|
||||
void modifyFinalSubsidyAmount(String id, Float finalSubsidyAmount);
|
||||
|
||||
NutMap calculateSubsidy(String id);
|
||||
|
||||
Workbook exportSummaryExcel(Integer year, String startMonth, String endMonth);
|
||||
|
||||
byte[] exportSummaryWord(Integer year, String startMonth, String endMonth);
|
||||
|
||||
byte[] exportApplyWord(String id);
|
||||
|
||||
byte[] exportApprovedZip(Integer year, String startMonth, String endMonth);
|
||||
}
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
package com.budwk.app.zhgh.staffbenefit.difficultSubsidy.service.impl;
|
||||
|
||||
import com.budwk.app.zhgh.staffbenefit.difficultSubsidy.models.DifficultSubsidyApply;
|
||||
import com.budwk.app.zhgh.staffbenefit.difficultSubsidy.models.DifficultSubsidyDiseaseType;
|
||||
import com.budwk.app.zhgh.staffbenefit.difficultSubsidy.models.DifficultSubsidyProject;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.dao.util.Daos;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
|
||||
/**
|
||||
* 特困补助模块表结构与基础补助范围初始化。
|
||||
*
|
||||
* 项目公共启动器只在 DEBUG 日志级别下执行实体迁移,因此本模块单独按实体补齐自己的三张表,
|
||||
* 不修改公共表,也不依赖额外 SQL 文件。基础数据仅在对应表为空时写入,避免覆盖管理员后续维护的数据。
|
||||
*/
|
||||
@IocBean(create = "init")
|
||||
public class DifficultSubsidySchemaInitializer {
|
||||
|
||||
@Inject
|
||||
private Dao dao;
|
||||
|
||||
/**
|
||||
* 根据实体补齐模块字段,并在全新配置表中写入参考项目的默认补助范围。
|
||||
*/
|
||||
public void init() {
|
||||
Daos.migration(dao, DifficultSubsidyApply.class, true, false);
|
||||
Daos.migration(dao, DifficultSubsidyProject.class, true, false);
|
||||
Daos.migration(dao, DifficultSubsidyDiseaseType.class, true, false);
|
||||
initDefaultProjects();
|
||||
}
|
||||
|
||||
/**
|
||||
* 仅当项目和说明表都为空时初始化默认数据,显式保留编号以兼容参考项目的补助测算规则。
|
||||
*/
|
||||
private void initDefaultProjects() {
|
||||
if (dao.count(DifficultSubsidyProject.class) > 0 || dao.count(DifficultSubsidyDiseaseType.class) > 0) {
|
||||
return;
|
||||
}
|
||||
insertProject(1, "重大疾病补助");
|
||||
insertProject(2, "门诊第二类特殊疾病补助");
|
||||
insertProject(3, "重大变故补助");
|
||||
insertProject(4, "住院护理补助");
|
||||
|
||||
insertDisease(1, 1, "重大器官移植术或造血干细胞移植术");
|
||||
insertDisease(2, 1, "恶性肿瘤");
|
||||
insertDisease(3, 1, "重型再生障碍性贫血");
|
||||
insertDisease(4, 1, "严重系统性红斑狼疮性肾病");
|
||||
insertDisease(5, 1, "持续植物人状态");
|
||||
insertDisease(6, 1, "其他自生病起本年度内自费超过5万的重大疾病");
|
||||
insertDisease(7, 2, "恶性肿瘤病人的补充放化疗及手术后门诊支持性治疗");
|
||||
insertDisease(8, 2, "慢性白血病");
|
||||
insertDisease(9, 2, "红斑狼疮");
|
||||
insertDisease(10, 2, "慢性肾功能衰竭的透析治疗");
|
||||
insertDisease(11, 2, "重大器官移植术后抗免疫排斥药物治疗");
|
||||
insertDisease(12, 2, "口服靶向药物治疗");
|
||||
insertDisease(13, 3, "本年度内,教职工家庭遭受地震、泥石流、火灾等自然灾害(财产损失价值20000元及以上),造成生活困难");
|
||||
insertDisease(14, 3, "本年度内,教职工本人或直系亲属(教职工子女、配偶和教职工本人父母)遭受突发性意外伤害(工伤等除外),个人承担治疗费用较大(减除保险、医保及责任方赔付以外20000元及以上),造成生活困难");
|
||||
insertDisease(15, 3, "本年度内,教职工本人或直系亲属(教职工子女、配偶和教职工本人父母)患严重疾病,教职工个人承担治疗费用较大(减除保险、医保以外20000元及以上),造成生活困难");
|
||||
insertDisease(18, 4, "普通疾病");
|
||||
insertDisease(19, 4, "重大疾病");
|
||||
}
|
||||
|
||||
private void insertProject(Integer id, String name) {
|
||||
if (dao.fetch(DifficultSubsidyProject.class, Cnd.where("id", "=", id)) == null) {
|
||||
DifficultSubsidyProject project = new DifficultSubsidyProject();
|
||||
project.setId(id);
|
||||
project.setProjectName(name);
|
||||
dao.insert(project);
|
||||
}
|
||||
}
|
||||
|
||||
private void insertDisease(Integer id, Integer projectId, String name) {
|
||||
if (dao.fetch(DifficultSubsidyDiseaseType.class, Cnd.where("id", "=", id)) == null) {
|
||||
DifficultSubsidyDiseaseType disease = new DifficultSubsidyDiseaseType();
|
||||
disease.setId(id);
|
||||
disease.setProjectId(projectId);
|
||||
disease.setDiseaseName(name);
|
||||
dao.insert(disease);
|
||||
}
|
||||
}
|
||||
}
|
||||
+1061
File diff suppressed because it is too large
Load Diff
+4
-4
@@ -299,7 +299,7 @@ public class DifficultHelpReadingController {
|
||||
docData.put("bankCardNum", record.getString("bankCardNum"));
|
||||
docData.put("reason", record.getString("reason"));
|
||||
docData.put("applyTime", DateUtil.format(DateUtil.parse(record.getString("applyTime")), "yyyy年MM月dd日"));
|
||||
docData.put("schoolname", "中国地质大学(武汉)");
|
||||
docData.put("schoolname", "西南财经大学");
|
||||
docData.put("year", DateUtil.format(DateUtil.parse(record.getString("applyTime")), "yyyy"));
|
||||
|
||||
String familyListStr = record.getString("familyList");
|
||||
@@ -350,7 +350,7 @@ public class DifficultHelpReadingController {
|
||||
docData.put("bankCardNum", difficultHelp.getBankCardNum());
|
||||
docData.put("reason", difficultHelp.getReason());
|
||||
docData.put("applyTime", DateUtil.format(difficultHelp.getApplyTime(), "yyyy-MM-dd"));
|
||||
docData.put("schoolname","中国地质大学(武汉)");
|
||||
docData.put("schoolname","西南财经大学");
|
||||
docData.put("year",DateUtil.format(difficultHelp.getApplyTime(), "yyyy"));
|
||||
|
||||
docData.put("familyList", difficultHelp.getFamilyList() != null ? difficultHelp.getFamilyList() : new ArrayList<>());
|
||||
@@ -371,7 +371,7 @@ public class DifficultHelpReadingController {
|
||||
@At
|
||||
private void exportAsPDF(String templateName, HashMap<String, Object> docData,Configure config,
|
||||
DifficultHelpInfo difficultHelp, HttpServletResponse response) throws Exception {
|
||||
String fileName = "中国地质大学(武汉)困难慰问申请表_" + difficultHelp.getUserName() + "_" +
|
||||
String fileName = "西南财经大学困难慰问申请表_" + difficultHelp.getUserName() + "_" +
|
||||
DateUtil.format(difficultHelp.getApplyTime(), "yyyyMMdd") + ".pdf";
|
||||
|
||||
try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
|
||||
@@ -396,7 +396,7 @@ public class DifficultHelpReadingController {
|
||||
@At
|
||||
private void exportAsWord(String templateName, HashMap<String, Object> docData,Configure config,
|
||||
DifficultHelpInfo difficultHelp, HttpServletResponse response) throws Exception {
|
||||
String fileName = "中国地质大学(武汉)困难慰问申请表_" + difficultHelp.getUserName() + "_" +
|
||||
String fileName = "西南财经大学困难慰问申请表_" + difficultHelp.getUserName() + "_" +
|
||||
DateUtil.format(difficultHelp.getApplyTime(), "yyyyMMdd") + ".docx";
|
||||
|
||||
try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
|
||||
|
||||
@@ -0,0 +1,192 @@
|
||||
<template>
|
||||
<div v-loading="loading">
|
||||
<div class="process-title">申请信息</div>
|
||||
<el-descriptions :column="3" border class="difficult-subsidy-info flow-task-form">
|
||||
<el-descriptions-item label="申请人姓名/工号">
|
||||
{{ detail.applyUserName }}({{ detail.applyLoginName }})
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="受助人姓名">{{ detail.userName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="受助人工号">{{ detail.loginName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="性别">{{ detail.sex }}</el-descriptions-item>
|
||||
<el-descriptions-item label="年龄">{{ detail.age }}</el-descriptions-item>
|
||||
<el-descriptions-item label="联系电话">{{ detail.mobile }}</el-descriptions-item>
|
||||
<el-descriptions-item label="所在部门">{{ detail.unitName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="所属工会">{{ detail.unionName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="申请时间">{{ detail.applyDate }}</el-descriptions-item>
|
||||
<el-descriptions-item label="申请补助类别" :span="3">
|
||||
{{ subsidyTypeNames(detail.subsidyType) }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="住院及补助事项记录" :span="3">
|
||||
<el-table :data="detail.hospitalRecords || []" border style="width: 100%">
|
||||
<el-table-column label="就诊医院" prop="hospitalName" min-width="130"></el-table-column>
|
||||
<el-table-column label="入院时间" prop="startDate" width="110"></el-table-column>
|
||||
<el-table-column label="出院时间" prop="endDate" width="110"></el-table-column>
|
||||
<el-table-column label="自费金额" prop="selfFundedAmount" width="100"></el-table-column>
|
||||
<el-table-column label="补助类型" min-width="150">
|
||||
<template slot-scope="scope">{{ projectName(scope.row.subsidyType) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="疾病详情" min-width="220">
|
||||
<template slot-scope="scope">{{ diseaseNames(scope.row.diseaseDetail) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" prop="notes" min-width="120"></el-table-column>
|
||||
</el-table>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="申请补助原因" :span="3">
|
||||
<div class="pre-line">{{ detail.reason }}</div>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="纸质申请表" :span="3">
|
||||
<file-preview :files="detail.applyFile" complete_result></file-preview>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="证明材料" :span="3">
|
||||
<file-preview :files="detail.files" complete_result></file-preview>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="建议补助金额">{{ detail.subsidyAmount }}</el-descriptions-item>
|
||||
<el-descriptions-item label="最终补助金额" :span="2">{{ detail.finalSubsidyAmount }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
|
||||
<div v-for="task in detail.approvalRecords || []" :key="task.id" class="mt10">
|
||||
<div class="process-title">{{ task.displayName }}</div>
|
||||
<el-descriptions :column="3" border class="difficult-subsidy-info flow-task-form">
|
||||
<el-descriptions-item label="办理用户">{{ auditUserName(task) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="办理时间">{{ task.finishTime }}</el-descriptions-item>
|
||||
<el-descriptions-item label="办理结果">{{ auditResultName(task) }}</el-descriptions-item>
|
||||
<el-descriptions-item v-if="taskOpinion(task)" label="办理意见" :span="3">
|
||||
<div class="pre-line">{{ taskOpinion(task) }}</div>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
module.exports = {
|
||||
name: "DifficultSubsidyProcessInfo",
|
||||
data: function () {
|
||||
return {
|
||||
loading: false,
|
||||
detail: {},
|
||||
projectList: [],
|
||||
diseaseList: []
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
open: function (id) {
|
||||
var self = this;
|
||||
this.$set(this, "loading", true);
|
||||
this.$set(this, "detail", {});
|
||||
return Promise.all([
|
||||
this.$axios.post("/platform/difficultSubsidy/common/findOne", {id: id}),
|
||||
this.$axios.post("/platform/difficultSubsidy/common/projectInfo")
|
||||
]).then(function (responses) {
|
||||
if (responses[0].code === 0) {
|
||||
var detail = responses[0].data || {};
|
||||
// v3 历史附件没有 response.data,先转换为本项目上传组件可识别的回显结构,避免详情页报错。
|
||||
self.$set(detail, "applyFile", self.normalizeLegacyFiles(detail.applyFile));
|
||||
self.$set(detail, "files", self.normalizeLegacyFiles(detail.files));
|
||||
self.$set(self, "detail", detail);
|
||||
}
|
||||
if (responses[1].code === 0) {
|
||||
self.$set(self, "projectList", responses[1].data.projectList || []);
|
||||
self.$set(self, "diseaseList", responses[1].data.diseaseList || []);
|
||||
}
|
||||
self.$set(self, "loading", false);
|
||||
}).catch(function () {
|
||||
self.$set(self, "loading", false);
|
||||
});
|
||||
},
|
||||
normalizeLegacyFiles: function (files) {
|
||||
var self = this;
|
||||
return (files || []).map(function (item) {
|
||||
if (!item.response || !item.response.data) {
|
||||
self.$set(item, "name", item.name || item.filename || "历史附件");
|
||||
self.$set(item, "response", {data: item.id || ""});
|
||||
}
|
||||
return item;
|
||||
});
|
||||
},
|
||||
auditUserName: function (row) {
|
||||
var formData = row.taskFormData || {};
|
||||
// 发起节点的流程表单不一定包含办理人姓名,使用申请记录快照展示姓名和工号。
|
||||
if (row.taskName === "startTask") {
|
||||
return this.formatUserName(this.detail.applyUserName, this.detail.applyLoginName);
|
||||
}
|
||||
if (formData.userName) {
|
||||
return this.formatUserName(formData.userName, formData.loginName);
|
||||
}
|
||||
// operator 是系统用户 ID,姓名无法解析时不向用户展示内部 ID。
|
||||
return "—";
|
||||
},
|
||||
formatUserName: function (userName, loginName) {
|
||||
if (!userName) {
|
||||
return "—";
|
||||
}
|
||||
return loginName ? userName + "(" + loginName + ")" : userName;
|
||||
},
|
||||
auditResultName: function (row) {
|
||||
var ext = row.ext || {};
|
||||
var resultNames = {
|
||||
0: "发起申请",
|
||||
1: "同意",
|
||||
2: "拒绝",
|
||||
3: "退回上一步",
|
||||
5: "重新提交",
|
||||
6: "退回申请人",
|
||||
20: "会签不同意"
|
||||
};
|
||||
return resultNames[ext.submitType] || "已办理";
|
||||
},
|
||||
taskOpinion: function (row) {
|
||||
var formData = row.taskFormData || {};
|
||||
return formData.approvalComment || formData.opinion || "";
|
||||
},
|
||||
projectName: function (id) {
|
||||
var item = this.projectList.find(function (project) {
|
||||
return project.id === id;
|
||||
});
|
||||
return item ? item.projectName : "";
|
||||
},
|
||||
subsidyTypeNames: function (ids) {
|
||||
var self = this;
|
||||
var idList = this.normalizeIdList(ids);
|
||||
return idList.map(function (id) {
|
||||
return self.projectName(id);
|
||||
}).filter(function (name) {
|
||||
return name;
|
||||
}).join("、");
|
||||
},
|
||||
normalizeIdList: function (ids) {
|
||||
if (Array.isArray(ids)) {
|
||||
return ids;
|
||||
}
|
||||
if (typeof ids === "string" && ids) {
|
||||
try {
|
||||
var parsedIds = JSON.parse(ids);
|
||||
return Array.isArray(parsedIds) ? parsedIds : [];
|
||||
} catch (e) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
return [];
|
||||
},
|
||||
diseaseNames: function (ids) {
|
||||
var diseaseIds = ids || [];
|
||||
return this.diseaseList.filter(function (item) {
|
||||
return diseaseIds.indexOf(item.id) >= 0;
|
||||
}).map(function (item) {
|
||||
return item.diseaseName;
|
||||
}).join("、");
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.difficult-subsidy-info .el-descriptions-item__label {
|
||||
min-width: 130px;
|
||||
}
|
||||
|
||||
.pre-line {
|
||||
white-space: pre-line;
|
||||
}
|
||||
</style>
|
||||
@@ -75,7 +75,14 @@ const branchUnionUserManage = {
|
||||
<el-dialog title="添加" :visible.sync="dialogFormVisible" width="600px" :close-on-click-modal="false">
|
||||
<el-form :model="formData" ref="form" size="small" label-width="80px">
|
||||
<el-form-item prop="roleCode" label="角色">
|
||||
<dict-select v-model="formData.roleCode" code="BRANCH_UNION_ROLES" placeholder="请选择角色"></dict-select>
|
||||
<el-select v-model="formData.roleCode" placeholder="请选择角色">
|
||||
<el-option
|
||||
v-for="item in roleOptions"
|
||||
:key="item.code"
|
||||
:label="item.name"
|
||||
:value="item.code"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item prop="j" label="届数">
|
||||
<dict-select v-model="formData.j" code="TEACHER_CONGRESS_J" placeholder="请选择届数"></dict-select>
|
||||
@@ -143,6 +150,7 @@ const branchUnionUserManage = {
|
||||
id: "",
|
||||
leaveDate: ""
|
||||
},
|
||||
roleOptions: [],
|
||||
jOptions: [],
|
||||
usedJCodes: []
|
||||
}
|
||||
@@ -154,6 +162,13 @@ const branchUnionUserManage = {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
loadRoleOptions() {
|
||||
return $.get("/platform/sys/union/branchUnionRoleOptions").then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.roleOptions = res.data || []
|
||||
}
|
||||
})
|
||||
},
|
||||
loadJOptions() {
|
||||
return $.get("/open/common/dictOptions", { code: "TEACHER_CONGRESS_J" }).then((res) => {
|
||||
this.jOptions = res.data || []
|
||||
@@ -279,6 +294,7 @@ const branchUnionUserManage = {
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.loadRoleOptions()
|
||||
this.initJSearch()
|
||||
},
|
||||
style: /*language=CSS*/ `
|
||||
|
||||
@@ -56,7 +56,7 @@ layout("/layouts/platform.html"){
|
||||
|
||||
<el-card class="mt10" shadow="never">
|
||||
<table-tool
|
||||
:label="pageForm.status==='2'?('中国地质大学(武汉)'+pageForm.year+'年教职工运动会获奖个数汇总表'):'奖品名单'">
|
||||
:label="pageForm.status==='2'?('西南财经大学'+pageForm.year+'年教职工运动会获奖个数汇总表'):'奖品名单'">
|
||||
<el-tag
|
||||
:effect="pageForm.status===item.code?'dark':'plain'"
|
||||
:key="item.code"
|
||||
@@ -76,7 +76,7 @@ layout("/layouts/platform.html"){
|
||||
<tr>
|
||||
<td class="text-center" colspan="11">
|
||||
<span v-if="activityList.find(v=>v.id === pageForm.activityId)">
|
||||
中国地质大学(武汉){{ activityList.find(v=>v.id === pageForm.activityId).name }}
|
||||
西南财经大学{{ activityList.find(v=>v.id === pageForm.activityId).name }}
|
||||
({{unionName}})获奖名单
|
||||
</span>
|
||||
</td>
|
||||
|
||||
@@ -149,7 +149,9 @@ const PROPOSAL_INFO = {
|
||||
<el-table-column label="姓名" prop="userName"></el-table-column>
|
||||
<el-table-column label="工号" prop="loginName"></el-table-column>
|
||||
<el-table-column label="性别" prop="sex"></el-table-column>
|
||||
<el-table-column label="联系方式" prop="mobile"></el-table-column>
|
||||
<el-table-column label="联系方式" prop="mobile">
|
||||
<template slot-scope="{row}">{{ row.mobile || '' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="单位" prop="unitName"></el-table-column>
|
||||
<el-table-column label="分工会" prop="unionName"></el-table-column>
|
||||
<el-table-column label="代表团" prop="delegationName"></el-table-column>
|
||||
@@ -271,9 +273,37 @@ const PROPOSAL_INFO = {
|
||||
this.$axios.post("/flow/common/doneTasks", {bizId: this.row.id}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
const tasks = res.data || []
|
||||
this.doneTasks = tasks
|
||||
// 提案历史按定义节点顺序展示,迁入任务不受数据库补写时间影响。
|
||||
const taskOrders = {
|
||||
startTask: 10,
|
||||
invite: 20,
|
||||
second: 30,
|
||||
secondaryUnionAudit: 40,
|
||||
partyOrganizationAudit: 50,
|
||||
committee: 60,
|
||||
committeeFiling: 60,
|
||||
committeeFilingUnit: 70,
|
||||
unit_reply: 80,
|
||||
unitReply: 80,
|
||||
schoolLeader: 90,
|
||||
feedback: 100,
|
||||
feedbackEvaluation: 100
|
||||
}
|
||||
tasks.sort((first, second) => {
|
||||
const orderDifference = (taskOrders[first.taskName] || 999) - (taskOrders[second.taskName] || 999)
|
||||
if (orderDifference !== 0) {
|
||||
return orderDifference
|
||||
}
|
||||
const firstTime = first.finishTime || ''
|
||||
const secondTime = second.finishTime || ''
|
||||
if (firstTime !== secondTime) {
|
||||
return firstTime.localeCompare(secondTime)
|
||||
}
|
||||
return first.id - second.id
|
||||
})
|
||||
this.$set(this, 'doneTasks', tasks)
|
||||
// 审核记录加载完成后默认全部折叠,由用户按需展开查看。
|
||||
this.activeTaskId = null
|
||||
this.$set(this, 'activeTaskId', null)
|
||||
// 通知外层页面已办节点数据已加载完成,便于当前环节做表单回显。
|
||||
this.$emit("done-tasks", tasks)
|
||||
}
|
||||
|
||||
+1
-1
@@ -285,7 +285,7 @@ layout("/layouts/platform.html"){
|
||||
})
|
||||
},
|
||||
exportDocx(id) {
|
||||
this.$downLoad("/platform/proposal/common/exportProposalAsDocx", {id})
|
||||
this.$downLoad("/platform/proposal/export/comprehensive/exportProposalAsDocx", {id})
|
||||
},
|
||||
exportSummaryAsExcel() {
|
||||
this.$downLoad("/platform/proposal/export/comprehensive/exportSummaryAsExcel", {
|
||||
|
||||
-1
@@ -148,7 +148,6 @@ layout("/layouts/platform.html"){
|
||||
return {
|
||||
tableColumns: [
|
||||
{label: "提案编号", prop: "code"},
|
||||
{label: "立案编号", prop: "caseFilingCode"},
|
||||
{label: "提案名称", prop: "name", width: "200px"},
|
||||
{label: "提案人", prop: "createUserName", width: "80px"},
|
||||
{label: "提案类别", prop: "typeName"},
|
||||
|
||||
-1
@@ -201,7 +201,6 @@ layout("/layouts/platform.html"){
|
||||
return {
|
||||
tableColumns: [
|
||||
{ label: "提案编号", prop: "code" },
|
||||
{ label: "立案编号", prop: "caseFilingCode" },
|
||||
{ label: "提案名称", prop: "name", width: "200px" },
|
||||
{ label: "提案类别", prop: "typeName" },
|
||||
{ label: "届次", prop: "sessionName" },
|
||||
|
||||
-1
@@ -209,7 +209,6 @@ layout("/layouts/platform.html"){
|
||||
return {
|
||||
tableColumns: [
|
||||
{label: "提案编号", prop: "code"},
|
||||
{label: "立案编号", prop: "caseFilingCode"},
|
||||
{label: "提案名称", prop: "name", width: "200px"},
|
||||
{label: "提案类别", prop: "typeName"},
|
||||
{label: "届次", prop: "sessionName"},
|
||||
|
||||
-1
@@ -108,7 +108,6 @@ layout("/layouts/platform.html"){
|
||||
return {
|
||||
tableColumns: [
|
||||
{label: "提案编号", prop: "code"},
|
||||
{label: "立案编号", prop: "caseFilingCode"},
|
||||
{label: "提案名称", prop: "name", width: "200px"},
|
||||
{label: "提案人", prop: "createUserName", width: "80px"},
|
||||
{label: "提案类别", prop: "typeName"},
|
||||
|
||||
-1
@@ -120,7 +120,6 @@ layout("/layouts/platform.html"){
|
||||
return {
|
||||
tableColumns: [
|
||||
{label: "提案编号", prop: "code"},
|
||||
{label: "立案编号", prop: "caseFilingCode"},
|
||||
{label: "提案名称", prop: "name", width: "200px"},
|
||||
{label: "提案类别", prop: "typeName"},
|
||||
{label: "是否并案", prop: "merge"},
|
||||
|
||||
-1
@@ -112,7 +112,6 @@ layout("/layouts/platform.html"){
|
||||
return {
|
||||
tableColumns: [
|
||||
{label: "提案编号", prop: "code"},
|
||||
{label: "立案编号", prop: "caseFilingCode"},
|
||||
{label: "提案名称", prop: "name", width: "200px"},
|
||||
{label: "提案人", prop: "createUserName", width: "80px"},
|
||||
{label: "提案类别", prop: "typeName"},
|
||||
|
||||
-1
@@ -146,7 +146,6 @@ layout("/layouts/platform.html"){
|
||||
return {
|
||||
tableColumns: [
|
||||
{label: "提案编号", prop: "code"},
|
||||
{label: "立案编号", prop: "caseFilingCode"},
|
||||
{label: "提案名称", prop: "name", width: "200px"},
|
||||
{label: "提案类别", prop: "typeName"},
|
||||
{label: "办理单位", prop: "undertakeUnits", width: "260px"},
|
||||
|
||||
-1
@@ -289,7 +289,6 @@ layout("/layouts/platform.html"){
|
||||
return {
|
||||
tableColumns: [
|
||||
{label: "提案编号", prop: "code"},
|
||||
{label: "立案编号", prop: "caseFilingCode"},
|
||||
{label: "提案名称", prop: "name", width: "200px"},
|
||||
{label: "提案类别", prop: "typeName"},
|
||||
{label: "立案结果", prop: "caseFilingResult"},
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
<!--#
|
||||
layout("/layouts/platform.html"){
|
||||
#-->
|
||||
<div id="app" v-cloak>
|
||||
<guava ref="guava">
|
||||
<template>
|
||||
<el-card shadow="never">
|
||||
<search @search="doSearch">
|
||||
<search-item label="员工信息">
|
||||
<el-input @keyup.enter.native="doSearch" clearable placeholder="请输入工号或姓名" v-model="pageForm.searchKeyword"></el-input>
|
||||
</search-item>
|
||||
</search>
|
||||
</el-card>
|
||||
<el-card class="mt10" shadow="never">
|
||||
<table-tool :app="this" label="华住员工管理">
|
||||
<el-button @click="syncSelected" icon="el-icon-refresh" size="small" type="primary">同步选中员工</el-button>
|
||||
</table-tool>
|
||||
<el-table :data="tableData" :size="tableSize" @selection-change="selectionChange" class="vi-table" v-loading="tableLoading">
|
||||
<el-table-column type="selection" width="55"></el-table-column>
|
||||
<el-table-column :index="indexMethod" label="序号" type="index" width="80"></el-table-column>
|
||||
<el-table-column label="工号" min-width="140" prop="loginname"></el-table-column>
|
||||
<el-table-column label="姓名" min-width="120" prop="username"></el-table-column>
|
||||
<el-table-column label="单位" min-width="180" prop="unitName" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column fixed="right" label="操作" width="130">
|
||||
<template slot-scope="{row}"><el-button @click="queryStatus(row)" size="mini" type="primary">查询状态</el-button></template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!--#include("/layouts/pagination.html"){}#-->
|
||||
</el-card>
|
||||
<el-dialog :visible.sync="statusDialogVisible" title="华住同步状态" width="520px">
|
||||
<el-descriptions :column="1" border size="small" v-if="statusData">
|
||||
<el-descriptions-item label="状态码">{{statusData.statusCode || "--"}}</el-descriptions-item>
|
||||
<el-descriptions-item label="工号">{{statusData.userNumber || "--"}}</el-descriptions-item>
|
||||
<el-descriptions-item label="姓名">{{statusData.userName || "--"}}</el-descriptions-item>
|
||||
<el-descriptions-item label="部门">{{statusData.userDep || "--"}}</el-descriptions-item>
|
||||
<el-descriptions-item label="成本中心">{{statusData.costCenter || "--"}}</el-descriptions-item>
|
||||
<el-descriptions-item label="职级">{{statusData.rank || "--"}}</el-descriptions-item>
|
||||
<el-descriptions-item label="直属领导">{{statusData.leader || "--"}}</el-descriptions-item>
|
||||
<el-descriptions-item label="邮箱">{{statusData.email || "--"}}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-dialog>
|
||||
</template>
|
||||
</guava>
|
||||
</div>
|
||||
<script nonce="${cspNonce!}">
|
||||
new Vue({
|
||||
el: "#app",
|
||||
mixins: [initTableMixins],
|
||||
data: function () { return {pageForm: {searchKeyword: "", pageNumber: 1, pageSize: 10, totalCount: 0}, selectedRows: [], statusDialogVisible: false, statusData: null} },
|
||||
methods: {
|
||||
selectionChange: function (rows) { this.$set(this, "selectedRows", rows) },
|
||||
syncSelected: function () {
|
||||
var self = this;
|
||||
if (!this.selectedRows.length) { this.$message.warning("请先选择需要同步的员工"); return }
|
||||
this.$confirm("确定同步选中的 " + this.selectedRows.length + " 名员工到华住吗?", "提示", {type: "warning"}).then(function () {
|
||||
self.$set(self, "tableLoading", true);
|
||||
return $.post(loc() + "/syncUsers", {userIds: self.selectedRows.map(function (row) { return row.id })})
|
||||
}).then(function (res) {
|
||||
if (res && res.code === 0) {
|
||||
var failed = (res.data || []).filter(function (item) { return !item.success });
|
||||
self.$message.success("同步完成,成功 " + ((res.data || []).length - failed.length) + " 人,失败 " + failed.length + " 人");
|
||||
if (failed.length) { self.$alert(failed.map(function (item) { return item.userName + "(" + item.loginName + "):" + item.message }).join("\n"), "失败明细") }
|
||||
} else if (res) { self.$message.warning(res.msg || "同步失败") }
|
||||
}).catch(function () {}).then(function () { self.$set(self, "tableLoading", false) })
|
||||
},
|
||||
queryStatus: function (row) {
|
||||
var self = this;
|
||||
this.$set(this, "tableLoading", true);
|
||||
$.post(loc() + "/queryStatus", {userId: row.id}).then(function (res) {
|
||||
if (res.code === 0) { self.$set(self, "statusData", res.data); self.$set(self, "statusDialogVisible", true) } else { self.$message.warning(res.msg || "查询失败") }
|
||||
}).catch(function (xhr) {
|
||||
var message = xhr && xhr.responseJSON && xhr.responseJSON.msg;
|
||||
self.$message.error(message || "查询华住状态失败,请稍后重试");
|
||||
}).then(function () { self.$set(self, "tableLoading", false) })
|
||||
}
|
||||
},
|
||||
created: function () { this.pageData() }
|
||||
})
|
||||
</script>
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
@@ -0,0 +1,136 @@
|
||||
<!--#
|
||||
layout("/layouts/platform.html"){
|
||||
#-->
|
||||
<div id="app" v-cloak>
|
||||
<guava ref="guava">
|
||||
<template>
|
||||
<el-card shadow="never">
|
||||
<search @search="doSearch">
|
||||
<search-item label="年度">
|
||||
<el-date-picker :clearable="true" placeholder="请选择年度" style="width: 100%" type="year" v-model="pageForm.year" value-format="yyyy"></el-date-picker>
|
||||
</search-item>
|
||||
<search-item label="标题">
|
||||
<el-input @keyup.enter.native="doSearch" clearable placeholder="请输入标题" v-model="pageForm.title"></el-input>
|
||||
</search-item>
|
||||
</search>
|
||||
</el-card>
|
||||
<el-card class="mt10" shadow="never">
|
||||
<table-tool :app="this">
|
||||
<el-button @click="openAdd" icon="el-icon-plus" size="small" type="primary">新增</el-button>
|
||||
</table-tool>
|
||||
<el-table :data="tableData" :size="tableSize" class="vi-table" v-loading="tableLoading">
|
||||
<el-table-column :index="indexMethod" label="序号" type="index" width="80"></el-table-column>
|
||||
<el-table-column label="标题" min-width="180" prop="title" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="标签类型" prop="tagTypeName" width="130">
|
||||
<template slot-scope="{row}"><el-tag v-if="row.tagTypeName" size="small">{{row.tagTypeName}}</el-tag><span v-else>--</span></template>
|
||||
</el-table-column>
|
||||
<el-table-column label="摘要" min-width="180" prop="summary" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="封面图" width="110">
|
||||
<template slot-scope="{row}"><el-image v-if="row.cover" :preview-src-list="[row.cover]" :src="row.cover" fit="cover" style="height: 36px; width: 72px"></el-image><span v-else>--</span></template>
|
||||
</el-table-column>
|
||||
<el-table-column label="创建时间" width="170">
|
||||
<template slot-scope="{row}">{{formatDate(row.createdAt)}}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="发布状态" width="100">
|
||||
<template slot-scope="{row}"><span :class="row.status === 1 ? 'text-success' : 'text-muted'">{{row.statusName}}</span></template>
|
||||
</el-table-column>
|
||||
<el-table-column fixed="right" label="操作" width="220">
|
||||
<template slot-scope="{row}">
|
||||
<el-button @click="openEdit(row)" size="mini" type="primary">编辑</el-button>
|
||||
<el-button @click="changeStatus(row, row.status === 1 ? 0 : 1)" size="mini">{{row.status === 1 ? '下架' : '发布'}}</el-button>
|
||||
<el-button @click="deleteRow(row)" size="mini" type="danger">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!--#include("/layouts/pagination.html"){}#-->
|
||||
</el-card>
|
||||
</template>
|
||||
<template #edit>
|
||||
<el-form :model="formData" :rules="formRules" label-width="90px" ref="form" v-loading="formLoading">
|
||||
<el-form-item label="标题" prop="title"><el-input maxlength="100" placeholder="请输入标题" v-model="formData.title"></el-input></el-form-item>
|
||||
<el-form-item label="摘要" prop="summary"><el-input maxlength="500" placeholder="请输入摘要" rows="3" type="textarea" v-model="formData.summary"></el-input></el-form-item>
|
||||
<el-form-item label="标签类型" prop="tagType">
|
||||
<el-select placeholder="请先维护标签类型字典" style="width: 100%" v-model="formData.tagType"><el-option :key="item.code" :label="item.label" :value="item.code" v-for="item in dict.type.INCLUSIVE_BENEFIT_TYPE || []"></el-option></el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="内容" prop="content"><text-editor v-model="formData.content"></text-editor></el-form-item>
|
||||
<el-form-item label="性别限制" prop="sexLimit"><el-radio-group v-model="formData.sexLimit"><el-radio :label="0">全部开放</el-radio><el-radio :label="1">男性</el-radio><el-radio :label="2">女性</el-radio></el-radio-group></el-form-item>
|
||||
<el-form-item label="封面图" prop="cover">
|
||||
<file-upload :upload_number="1" :value.sync="formData.cover" upload_mode="image" upload_result_category="interval" upload_result_type="url"></file-upload>
|
||||
</el-form-item>
|
||||
<el-form-item label="链接" prop="linkUrl"><el-input maxlength="500" placeholder="请输入外链地址" v-model="formData.linkUrl"></el-input></el-form-item>
|
||||
<el-form-item><el-button @click="back">取消</el-button><el-button :loading="formLoading" @click="saveForm(0)" type="primary">保存草稿</el-button><el-button :loading="formLoading" @click="saveForm(1)" type="primary">发布</el-button></el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
</guava>
|
||||
</div>
|
||||
<script nonce="${cspNonce!}">
|
||||
new Vue({
|
||||
el: "#app",
|
||||
dicts: ["INCLUSIVE_BENEFIT_TYPE"],
|
||||
mixins: [initTableMixins],
|
||||
data: function () {
|
||||
return {
|
||||
pageForm: {year: "", title: "", pageNumber: 1, pageSize: 10, totalCount: 0},
|
||||
formData: {},
|
||||
formLoading: false,
|
||||
formRules: {
|
||||
title: [{required: true, message: "请输入标题", trigger: "blur"}],
|
||||
summary: [{required: true, message: "请输入摘要", trigger: "blur"}],
|
||||
tagType: [{required: true, message: "请选择标签类型", trigger: "change"}],
|
||||
content: [{required: true, message: "请输入内容", trigger: "change"}],
|
||||
cover: [{required: true, message: "请上传封面图", trigger: "change"}]
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
emptyForm: function () { return {id: "", year: this.pageForm.year || new Date().getFullYear() + "", title: "", summary: "", tagType: "", content: "", sexLimit: 0, cover: "", linkUrl: ""} },
|
||||
formatDate: function (value) { return value ? moment(value).format("YYYY-MM-DD HH:mm") : "--" },
|
||||
back: function () { this.$refs.guava.index() },
|
||||
openAdd: function () { this.$set(this, "formData", this.emptyForm()); this.$refs.guava.edit() },
|
||||
openEdit: function (row) {
|
||||
var self = this;
|
||||
this.$set(this, "formLoading", true);
|
||||
$.post(loc() + "/findOne", {id: row.id}).then(function (res) {
|
||||
if (res.code === 0 && res.data) {
|
||||
var formData = self.emptyForm();
|
||||
Object.keys(res.data).forEach(function (key) {
|
||||
self.$set(formData, key, res.data[key]);
|
||||
});
|
||||
if (formData.year !== null && formData.year !== undefined) {
|
||||
self.$set(formData, "year", formData.year + "");
|
||||
}
|
||||
self.$set(self, "formData", formData);
|
||||
self.$refs.guava.edit();
|
||||
} else { self.$message.warning(res.msg || "未查询到数据") }
|
||||
}).always(function () { self.$set(self, "formLoading", false) })
|
||||
},
|
||||
saveForm: function (status) {
|
||||
var self = this;
|
||||
this.$refs.form.validate(function (valid) {
|
||||
if (!valid) { return }
|
||||
self.$set(self, "formLoading", true);
|
||||
self.$set(self.formData, "status", status);
|
||||
$.post(loc() + "/save", self.formData).then(function (res) {
|
||||
if (res.code === 0) { self.$message.success(res.msg || "保存成功"); self.$refs.guava.index(); self.doSearch() } else { self.$message.warning(res.msg) }
|
||||
}).always(function () { self.$set(self, "formLoading", false) })
|
||||
})
|
||||
},
|
||||
changeStatus: function (row, status) {
|
||||
var self = this;
|
||||
this.$confirm("确定要" + (status === 1 ? "发布" : "下架") + "该幸福工荟吗?", "提示", {type: "warning"}).then(function () {
|
||||
return $.post(loc() + "/updateStatus", {id: row.id, status: status})
|
||||
}).then(function (res) { if (res && res.code === 0) { self.$message.success(res.msg || "操作成功"); self.doSearch() } else if (res) { self.$message.warning(res.msg) } }).catch(function () {})
|
||||
},
|
||||
deleteRow: function (row) {
|
||||
var self = this;
|
||||
this.$confirm("确定要删除该幸福工荟吗?", "提示", {type: "warning"}).then(function () { return $.post(loc() + "/delete", {id: row.id}) }).then(function (res) {
|
||||
if (res && res.code === 0) { self.$message.success(res.msg || "删除成功"); self.doSearch() } else if (res) { self.$message.warning(res.msg) }
|
||||
}).catch(function () {})
|
||||
}
|
||||
},
|
||||
created: function () { this.pageData() }
|
||||
})
|
||||
</script>
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
+240
@@ -0,0 +1,240 @@
|
||||
<!--#
|
||||
layout("/layouts/platform.html"){
|
||||
#-->
|
||||
<style>
|
||||
.difficult-project-page { height: calc(100vh - 90px); }
|
||||
.difficult-project-page .el-row, .difficult-project-page .el-col, .difficult-project-page .el-card { height: 100%; }
|
||||
.difficult-project-page .project-list { margin-top: 10px; }
|
||||
.difficult-project-page .project-item { display:flex; align-items:center; justify-content:space-between; padding:10px 12px; cursor:pointer; }
|
||||
.difficult-project-page .project-item:hover, .difficult-project-page .project-item.active { background:#eef6ff; color:#1867b0; }
|
||||
.difficult-project-page .project-name { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; flex:1; }
|
||||
</style>
|
||||
<div id="app" class="difficult-project-page" v-cloak>
|
||||
<el-row :gutter="10">
|
||||
<el-col :span="5">
|
||||
<el-card shadow="never">
|
||||
<el-input v-model="projectKeyword" clearable placeholder="请输入内容">
|
||||
<el-button slot="append" @click="openProjectDialog()">新增补助范围</el-button>
|
||||
</el-input>
|
||||
<div class="project-list">
|
||||
<div v-for="item in filteredProjects" :key="item.id"
|
||||
:class="['project-item', selectedProject && selectedProject.id === item.id ? 'active' : '']"
|
||||
@click="selectProject(item)">
|
||||
<span class="project-name"><i class="el-icon-s-home"></i> {{ item.projectName }}</span>
|
||||
<span>
|
||||
<el-button type="text" size="mini" @click.stop="openProjectDialog(item)">编辑</el-button>
|
||||
<el-button type="text" size="mini" @click.stop="deleteProject(item)">删除</el-button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="19">
|
||||
<el-card shadow="never">
|
||||
<el-row style="height:auto">
|
||||
<el-col :span="18" style="height:auto;display:flex">
|
||||
<el-input v-model="diseaseKeyword" clearable placeholder="请输入名称"></el-input>
|
||||
<el-button type="primary" icon="el-icon-search" style="margin-left:10px"
|
||||
@click="loadDisease">查询</el-button>
|
||||
</el-col>
|
||||
<el-col :span="6" style="height:auto;text-align:right">
|
||||
<el-button type="primary" icon="el-icon-circle-plus-outline"
|
||||
:disabled="!selectedProject" @click="openDiseaseDialog()">新增子类</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-table :data="diseaseList" border style="width:100%;margin-top:10px" height="calc(100vh - 180px)">
|
||||
<el-table-column type="index" label="序号" width="60" align="center"></el-table-column>
|
||||
<el-table-column prop="diseaseName" label="说明" align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="操作" width="220" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="primary" size="mini" @click="openDiseaseDialog(scope.row)">编辑</el-button>
|
||||
<el-button type="danger" size="mini" @click="deleteDisease(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-dialog title="补助范围" :visible.sync="projectDialogVisible" width="440px" :close-on-click-modal="false">
|
||||
<el-form ref="projectFormRef" :model="projectForm" label-width="100px">
|
||||
<el-form-item label="补助项目" prop="projectName"
|
||||
:rules="[{required:true,message:'请输入补助项目',trigger:'blur'}]">
|
||||
<el-input v-model="projectForm.projectName" maxlength="100" clearable></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer">
|
||||
<el-button @click="closeProjectDialog">取消</el-button>
|
||||
<el-button type="primary" @click="saveProject">确定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog :title="diseaseForm.id ? '编辑' : '新增'" :visible.sync="diseaseDialogVisible"
|
||||
width="60%" :close-on-click-modal="false">
|
||||
<el-form ref="diseaseFormRef" :model="diseaseForm" label-width="100px">
|
||||
<el-form-item label="说明" prop="diseaseName"
|
||||
:rules="[{required:true,message:'请输入说明',trigger:'blur'}]">
|
||||
<el-input v-model="diseaseForm.diseaseName" type="textarea" :rows="4"
|
||||
maxlength="1000" show-word-limit></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer">
|
||||
<el-button @click="closeDiseaseDialog">取消</el-button>
|
||||
<el-button type="primary" @click="saveDisease">确定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
<script nonce="${cspNonce!}">
|
||||
new Vue({
|
||||
el: "#app",
|
||||
data: function () {
|
||||
return {
|
||||
projectList: [],
|
||||
diseaseList: [],
|
||||
selectedProject: null,
|
||||
projectKeyword: "",
|
||||
diseaseKeyword: "",
|
||||
projectDialogVisible: false,
|
||||
diseaseDialogVisible: false,
|
||||
projectForm: {},
|
||||
diseaseForm: {}
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
filteredProjects: function () {
|
||||
var keyword = this.projectKeyword;
|
||||
return this.projectList.filter(function (item) {
|
||||
return !keyword || item.projectName.indexOf(keyword) >= 0;
|
||||
});
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
loadProject: function () {
|
||||
var self = this;
|
||||
return this.$axios.post("/platform/difficultSubsidy/basicSetting/project/projectList").then(function (res) {
|
||||
if (res.code === 0) {
|
||||
self.$set(self, "projectList", res.data || []);
|
||||
if (!self.selectedProject && self.projectList.length > 0) {
|
||||
self.selectProject(self.projectList[0]);
|
||||
} else if (self.selectedProject) {
|
||||
var selected = self.projectList.find(function (item) {
|
||||
return item.id === self.selectedProject.id;
|
||||
});
|
||||
self.$set(self, "selectedProject", selected || null);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
selectProject: function (project) {
|
||||
this.$set(this, "selectedProject", project);
|
||||
this.$set(this, "diseaseKeyword", "");
|
||||
this.loadDisease();
|
||||
},
|
||||
loadDisease: function () {
|
||||
var self = this;
|
||||
if (!this.selectedProject) {
|
||||
this.$set(this, "diseaseList", []);
|
||||
return;
|
||||
}
|
||||
this.$axios.post("/platform/difficultSubsidy/basicSetting/project/diseaseList", {
|
||||
projectId: this.selectedProject.id,
|
||||
keyword: this.diseaseKeyword
|
||||
}).then(function (res) {
|
||||
if (res.code === 0) {
|
||||
self.$set(self, "diseaseList", res.data || []);
|
||||
}
|
||||
});
|
||||
},
|
||||
openProjectDialog: function (row) {
|
||||
this.$set(this, "projectForm", row ? {id: row.id, projectName: row.projectName} : {});
|
||||
this.$set(this, "projectDialogVisible", true);
|
||||
this.$nextTick(function () {
|
||||
this.$refs.projectFormRef.clearValidate();
|
||||
});
|
||||
},
|
||||
closeProjectDialog: function () {
|
||||
this.$set(this, "projectDialogVisible", false);
|
||||
},
|
||||
saveProject: function () {
|
||||
var self = this;
|
||||
this.$refs.projectFormRef.validate(function (valid) {
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
self.$axios.post("/platform/difficultSubsidy/basicSetting/project/saveProject", {
|
||||
data: JSON.stringify(self.projectForm)
|
||||
}).then(function (res) {
|
||||
if (res.code === 0) {
|
||||
self.$message.success("保存成功");
|
||||
self.$set(self, "projectDialogVisible", false);
|
||||
self.loadProject();
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
deleteProject: function (row) {
|
||||
var self = this;
|
||||
this.$confirm("确定删除该补助范围吗?", "提示", {type: "warning"}).then(function () {
|
||||
self.$axios.post("/platform/difficultSubsidy/basicSetting/project/deleteProject", {id: row.id}).then(function (res) {
|
||||
if (res.code === 0) {
|
||||
self.$message.success("删除成功");
|
||||
if (self.selectedProject && self.selectedProject.id === row.id) {
|
||||
self.$set(self, "selectedProject", null);
|
||||
self.$set(self, "diseaseList", []);
|
||||
}
|
||||
self.loadProject();
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
openDiseaseDialog: function (row) {
|
||||
var data = row ? {id: row.id, projectId: row.projectId, diseaseName: row.diseaseName,
|
||||
subsidyAmountUpperLimit: row.subsidyAmountUpperLimit} : {projectId: this.selectedProject.id};
|
||||
this.$set(this, "diseaseForm", data);
|
||||
this.$set(this, "diseaseDialogVisible", true);
|
||||
this.$nextTick(function () {
|
||||
this.$refs.diseaseFormRef.clearValidate();
|
||||
});
|
||||
},
|
||||
closeDiseaseDialog: function () {
|
||||
this.$set(this, "diseaseDialogVisible", false);
|
||||
},
|
||||
saveDisease: function () {
|
||||
var self = this;
|
||||
this.$refs.diseaseFormRef.validate(function (valid) {
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
self.$axios.post("/platform/difficultSubsidy/basicSetting/project/saveDisease", {
|
||||
data: JSON.stringify(self.diseaseForm)
|
||||
}).then(function (res) {
|
||||
if (res.code === 0) {
|
||||
self.$message.success("保存成功");
|
||||
self.$set(self, "diseaseDialogVisible", false);
|
||||
self.loadDisease();
|
||||
self.loadProject();
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
deleteDisease: function (row) {
|
||||
var self = this;
|
||||
this.$confirm("确定删除该说明吗?", "提示", {type: "warning"}).then(function () {
|
||||
self.$axios.post("/platform/difficultSubsidy/basicSetting/project/deleteDisease", {id: row.id}).then(function (res) {
|
||||
if (res.code === 0) {
|
||||
self.$message.success("删除成功");
|
||||
self.loadDisease();
|
||||
self.loadProject();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
created: function () {
|
||||
this.loadProject();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
+454
@@ -0,0 +1,454 @@
|
||||
<!--#
|
||||
layout("/layouts/platform.html"){
|
||||
#-->
|
||||
<style>
|
||||
.difficult-apply .el-form-item { margin-bottom: 0; }
|
||||
.difficult-apply .el-descriptions-item__label { min-width: 150px; }
|
||||
.difficult-apply .required-label:before { content: "*"; color: #f56c6c; margin-right: 4px; }
|
||||
.difficult-apply .proof-help { line-height: 2; color: #7b8794; }
|
||||
.difficult-apply .nowrap-select .el-select__tags { flex-wrap: nowrap; overflow: hidden; }
|
||||
</style>
|
||||
<div id="app" class="difficult-apply" v-cloak>
|
||||
<el-card shadow="never">
|
||||
<snaker-start slot="header" label="特困补助申请" define_key="TKBZ"></snaker-start>
|
||||
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="0"
|
||||
label-suffix=":" class="flow-task-form">
|
||||
<el-descriptions :column="3" border>
|
||||
<el-descriptions-item label="申请人姓名/工号">
|
||||
<el-form-item prop="applyUserName">
|
||||
{{ formData.applyUserName }}({{ formData.applyLoginName }})
|
||||
</el-form-item>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="姓名">
|
||||
<el-form-item prop="userId" :rules="requiredRule('请选择申请补助的教职工')">
|
||||
<el-select v-if="!isSchoolAuditEdit" v-model="formData.userId" filterable remote reserve-keyword
|
||||
:remote-method="queryRecipients" :loading="userLoading"
|
||||
placeholder="请输入姓名或工号查找" style="width:100%"
|
||||
@change="userChange">
|
||||
<el-option v-for="item in userOptions" :key="item.id"
|
||||
:label="item.username + '(' + item.loginname + ')'"
|
||||
:value="item.id"></el-option>
|
||||
</el-select>
|
||||
<el-input v-else :value="formData.userName + '(' + formData.loginName + ')'" readonly></el-input>
|
||||
</el-form-item>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="性别">
|
||||
<el-radio-group v-model="formData.sex" disabled>
|
||||
<el-radio border label="男">男</el-radio>
|
||||
<el-radio border label="女">女</el-radio>
|
||||
</el-radio-group>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item>
|
||||
<span slot="label">年龄</span>
|
||||
<el-form-item prop="age" :rules="requiredRule('请填写年龄')">
|
||||
<el-input-number v-model="formData.age" :min="0" :max="120"></el-input-number>
|
||||
</el-form-item>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="所在部门">
|
||||
<el-input v-model="formData.unitName" readonly></el-input>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item>
|
||||
<span slot="label">联系电话</span>
|
||||
<el-form-item prop="mobile" :rules="requiredRule('请填写联系电话')">
|
||||
<el-input v-model="formData.mobile" maxlength="30"></el-input>
|
||||
</el-form-item>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :span="3">
|
||||
<span slot="label">申请补助类别</span>
|
||||
<el-form-item prop="subsidyType" :rules="requiredRule('请选择申请补助类别')">
|
||||
<el-checkbox-group v-model="formData.subsidyType" @change="subsidyTypeChange">
|
||||
<el-checkbox v-for="item in projectList" :key="item.id" :label="item.id">
|
||||
{{ item.projectName }}
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :span="3">
|
||||
<span slot="label" class="required-label">住院记录</span>
|
||||
<el-table :data="formData.hospitalRecords" border style="width:100%">
|
||||
<el-table-column label="就诊医院" min-width="130">
|
||||
<template slot-scope="scope">
|
||||
<el-form-item :prop="'hospitalRecords.' + scope.$index + '.hospitalName'"
|
||||
:rules="requiredRule('必填')">
|
||||
<el-input v-model="scope.row.hospitalName"></el-input>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="入院时间" width="145">
|
||||
<template slot-scope="scope">
|
||||
<el-form-item :prop="'hospitalRecords.' + scope.$index + '.startDate'"
|
||||
:rules="conditionalRule(isHospitalCare(scope.row))">
|
||||
<el-date-picker v-model="scope.row.startDate" type="date" value-format="yyyy-MM-dd"
|
||||
:disabled="!isHospitalCare(scope.row)"
|
||||
style="width:100%"></el-date-picker>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="出院时间" width="145">
|
||||
<template slot-scope="scope">
|
||||
<el-form-item :prop="'hospitalRecords.' + scope.$index + '.endDate'"
|
||||
:rules="conditionalRule(isHospitalCare(scope.row))">
|
||||
<el-date-picker v-model="scope.row.endDate" type="date" value-format="yyyy-MM-dd"
|
||||
:disabled="!isHospitalCare(scope.row)"
|
||||
style="width:100%"></el-date-picker>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="自费金额" width="130">
|
||||
<template slot-scope="scope">
|
||||
<el-form-item :prop="'hospitalRecords.' + scope.$index + '.selfFundedAmount'"
|
||||
:rules="conditionalRule(isAccidentSubsidy(scope.row))">
|
||||
<el-input-number v-model="scope.row.selfFundedAmount" :min="0" :precision="2"
|
||||
:disabled="!isAccidentSubsidy(scope.row)"
|
||||
style="width:100%"></el-input-number>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="补助类型" min-width="165">
|
||||
<template slot-scope="scope">
|
||||
<el-form-item :prop="'hospitalRecords.' + scope.$index + '.subsidyType'"
|
||||
:rules="requiredRule('必填')">
|
||||
<el-select v-model="scope.row.subsidyType" class="nowrap-select"
|
||||
style="width:100%" @change="hospitalTypeChange(scope.row)">
|
||||
<el-option v-for="item in selectedProjects" :key="item.id"
|
||||
:label="item.projectName" :value="item.id"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="疾病详情" min-width="210">
|
||||
<template slot-scope="scope">
|
||||
<el-form-item :prop="'hospitalRecords.' + scope.$index + '.diseaseDetail'"
|
||||
:rules="requiredRule('必填')">
|
||||
<el-select v-model="scope.row.diseaseDetail" multiple collapse-tags
|
||||
class="nowrap-select" style="width:100%">
|
||||
<el-option v-for="item in diseasesByProject(scope.row.subsidyType)"
|
||||
:key="item.id" :label="item.diseaseName"
|
||||
:value="item.id"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" min-width="120">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.notes" maxlength="100"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="145" fixed="right">
|
||||
<template slot="header" slot-scope="scope">
|
||||
<el-button size="mini" type="primary" icon="el-icon-plus"
|
||||
@click="addHospitalRecord">增加记录</el-button>
|
||||
</template>
|
||||
<template slot-scope="scope">
|
||||
<el-button size="mini" type="danger" icon="el-icon-delete"
|
||||
@click="removeHospitalRecord(scope.$index)"></el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :span="3">
|
||||
<span slot="label">申请补助原因</span>
|
||||
<el-form-item prop="reason" :rules="requiredRule('请填写申请补助原因')">
|
||||
<el-input v-model="formData.reason" type="textarea" :rows="5"
|
||||
maxlength="2000" show-word-limit></el-input>
|
||||
</el-form-item>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :span="3">
|
||||
<span slot="label">纸质申请表</span>
|
||||
<el-form-item prop="applyFile" :rules="requiredRule('请上传纸质申请表')">
|
||||
<file-upload :value.sync="formData.applyFile" upload_mode="drag"
|
||||
:upload_number="1" upload_result_category="array"
|
||||
complete_result></file-upload>
|
||||
</el-form-item>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :span="3">
|
||||
<span slot="label">证明材料</span>
|
||||
<el-form-item prop="files" :rules="requiredRule('请上传证明材料')">
|
||||
<el-alert :closable="false" type="info" class="proof-help">
|
||||
<div>申请补助范围第1—3项的教职工需提交材料:</div>
|
||||
<div style="text-indent:2em">1. 医院疾病证明;</div>
|
||||
<div style="text-indent:2em">
|
||||
2. 住院证明等相关就医辅助材料,其中住院15天及以下天数按半个月计算,住院16天至30天按一个月计算,每次出院及住院为一个时间段计算天数。
|
||||
</div>
|
||||
<div>申请补助范围第4项重大变故项目的教职工需提交材料:</div>
|
||||
<div style="text-indent:2em">
|
||||
1. 遭受自然灾害需提交当地消防部门、公安部门及社区的相关证明材料,相关财产损失评估报告;
|
||||
</div>
|
||||
<div style="text-indent:2em">
|
||||
2. 遭受意外伤害需提交公安、消防、交通等相关部门证明材料,医院疾病证明和住院证明,保险、医保结算清单复印件;
|
||||
</div>
|
||||
<div style="text-indent:2em">
|
||||
3. 教职工直系亲属患严重疾病的需提交《户口薄》复印件,医院疾病证明,住院和治疗结算清单复印件,保险、医保结算清单复印件。
|
||||
</div>
|
||||
</el-alert>
|
||||
<file-upload :value.sync="formData.files" upload_mode="drag"
|
||||
:upload_number="25" upload_result_category="array"
|
||||
complete_result></file-upload>
|
||||
</el-form-item>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-form>
|
||||
<el-row type="flex" justify="end" class="mt20">
|
||||
<el-button v-if="!isSchoolAuditEdit" type="primary" plain @click="onSave">保存</el-button>
|
||||
<el-button type="primary" @click="onSubmit">提交</el-button>
|
||||
</el-row>
|
||||
</el-card>
|
||||
</div>
|
||||
<script nonce="${cspNonce!}">
|
||||
new Vue({
|
||||
el: "#app",
|
||||
mixins: [initTableMixins],
|
||||
store: store,
|
||||
data: function () {
|
||||
return {
|
||||
bizId: GetQueryString("bizId") || GetQueryString("id"),
|
||||
taskId: GetQueryString("taskId"),
|
||||
isSchoolAuditEdit: GetQueryString("schoolAuditEdit") === "1",
|
||||
formData: {
|
||||
id: GetQueryString("bizId") || GetQueryString("id"),
|
||||
subsidyType: [],
|
||||
hospitalRecords: [],
|
||||
applyFile: [],
|
||||
files: []
|
||||
},
|
||||
formRules: {
|
||||
applyUserName: [{required: true, message: "申请人不能为空", trigger: ["blur", "change"]}],
|
||||
userId: [{required: true, message: "请选择申请补助的教职工", trigger: ["blur", "change"]}],
|
||||
age: [{required: true, message: "请填写年龄", trigger: ["blur", "change"]}],
|
||||
mobile: [{required: true, message: "请填写联系电话", trigger: ["blur", "change"]}],
|
||||
subsidyType: [{required: true, type: "array", min: 1, message: "请选择申请补助类别", trigger: "change"}],
|
||||
reason: [{required: true, message: "请填写申请补助原因", trigger: ["blur", "change"]}],
|
||||
applyFile: [{required: true, type: "array", min: 1, message: "请上传纸质申请表", trigger: "change"}],
|
||||
files: [{required: true, type: "array", min: 1, message: "请上传证明材料", trigger: "change"}]
|
||||
},
|
||||
projectList: [],
|
||||
diseaseList: [],
|
||||
userOptions: [],
|
||||
userLoading: false
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
selectedProjects: function () {
|
||||
var selected = this.formData.subsidyType || [];
|
||||
return this.projectList.filter(function (item) {
|
||||
return selected.indexOf(item.id) >= 0;
|
||||
});
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
requiredRule: function (message) {
|
||||
return [{required: true, message: message, trigger: ["change", "blur"]}];
|
||||
},
|
||||
conditionalRule: function (required) {
|
||||
return [{required: required, message: "必填", trigger: ["change", "blur"]}];
|
||||
},
|
||||
loadProject: function () {
|
||||
var self = this;
|
||||
return this.$axios.post("/platform/difficultSubsidy/common/projectInfo").then(function (res) {
|
||||
if (res.code === 0) {
|
||||
self.$set(self, "projectList", res.data.projectList || []);
|
||||
self.$set(self, "diseaseList", res.data.diseaseList || []);
|
||||
}
|
||||
});
|
||||
},
|
||||
loadDetail: function () {
|
||||
var self = this;
|
||||
var id = this.bizId;
|
||||
if (!id) {
|
||||
this.initCurrentUser();
|
||||
return;
|
||||
}
|
||||
var detailUrl = this.isSchoolAuditEdit
|
||||
? "/platform/difficultSubsidy/common/findOne"
|
||||
: "/platform/difficultSubsidy/apply/findOne";
|
||||
this.$axios.post(detailUrl, {id: id}).then(function (res) {
|
||||
if (res.code === 0) {
|
||||
var data = res.data || {};
|
||||
self.ensureCollections(data);
|
||||
self.$set(self, "formData", data);
|
||||
if (!self.isSchoolAuditEdit) {
|
||||
self.queryRecipients(data.loginName, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
initCurrentUser: function () {
|
||||
var user = this.$store.state.user;
|
||||
if (!user) {
|
||||
this.$message.warning("当前登录人信息尚未加载,请刷新页面后重试");
|
||||
return;
|
||||
}
|
||||
this.$set(this.formData, "applyUserId", user.id);
|
||||
this.$set(this.formData, "applyUserName", user.username);
|
||||
this.$set(this.formData, "applyLoginName", user.loginname);
|
||||
this.$set(this, "userOptions", [user]);
|
||||
this.$set(this.formData, "userId", user.id);
|
||||
this.setSelectedUser(user);
|
||||
},
|
||||
ensureCollections: function (data) {
|
||||
if (!data.subsidyType) {
|
||||
this.$set(data, "subsidyType", []);
|
||||
}
|
||||
if (!data.hospitalRecords) {
|
||||
this.$set(data, "hospitalRecords", []);
|
||||
}
|
||||
if (!data.applyFile) {
|
||||
this.$set(data, "applyFile", []);
|
||||
}
|
||||
if (!data.files) {
|
||||
this.$set(data, "files", []);
|
||||
}
|
||||
},
|
||||
queryRecipients: function (keyword, selectFirst) {
|
||||
var self = this;
|
||||
if (!keyword) {
|
||||
this.$set(this, "userOptions", []);
|
||||
return;
|
||||
}
|
||||
this.$set(this, "userLoading", true);
|
||||
this.$axios.post("/platform/difficultSubsidy/apply/queryRecipients", {key: keyword}).then(function (res) {
|
||||
var users = res.code === 0 ? (res.data || []) : [];
|
||||
self.$set(self, "userOptions", users);
|
||||
self.$set(self, "userLoading", false);
|
||||
if (selectFirst && users.length > 0) {
|
||||
self.$set(self.formData, "userId", users[0].id);
|
||||
self.setSelectedUser(users[0]);
|
||||
}
|
||||
}).catch(function () {
|
||||
self.$set(self, "userLoading", false);
|
||||
});
|
||||
},
|
||||
userChange: function (userId) {
|
||||
var user = this.userOptions.find(function (item) {
|
||||
return item.id === userId;
|
||||
});
|
||||
if (user) {
|
||||
this.setSelectedUser(user);
|
||||
}
|
||||
},
|
||||
setSelectedUser: function (user) {
|
||||
var unit = user.unit || {};
|
||||
var union = user.union || {};
|
||||
this.$set(this.formData, "userName", user.username);
|
||||
this.$set(this.formData, "loginName", user.loginname);
|
||||
this.$set(this.formData, "sex", user.sex);
|
||||
this.$set(this.formData, "unitId", user.unitId || user.unitid || unit.id || "");
|
||||
this.$set(this.formData, "unitName", user.unitName || user.unitname || unit.name || "");
|
||||
this.$set(this.formData, "unionId", user.unionId || user.unionid || union.id || "");
|
||||
this.$set(this.formData, "unionName", user.unionName || user.unionname || union.name || "");
|
||||
this.$set(this.formData, "mobile", user.mobile || "");
|
||||
if (user.birthday) {
|
||||
this.$set(this.formData, "age", this.$moment().diff(user.birthday, "years"));
|
||||
}
|
||||
},
|
||||
subsidyTypeChange: function (values) {
|
||||
var self = this;
|
||||
values.forEach(function (projectId) {
|
||||
var exists = self.formData.hospitalRecords.some(function (record) {
|
||||
return record.subsidyType === projectId;
|
||||
});
|
||||
if (!exists) {
|
||||
self.formData.hospitalRecords.push({subsidyType: projectId, diseaseDetail: []});
|
||||
}
|
||||
});
|
||||
var records = this.formData.hospitalRecords.filter(function (record) {
|
||||
return values.indexOf(record.subsidyType) >= 0;
|
||||
});
|
||||
this.$set(this.formData, "hospitalRecords", records);
|
||||
},
|
||||
diseasesByProject: function (projectId) {
|
||||
return this.diseaseList.filter(function (item) {
|
||||
return item.projectId === projectId;
|
||||
});
|
||||
},
|
||||
projectName: function (projectId) {
|
||||
var project = this.projectList.find(function (item) {
|
||||
return item.id === projectId;
|
||||
});
|
||||
return project ? project.projectName : "";
|
||||
},
|
||||
isHospitalCare: function (row) {
|
||||
return this.projectName(row.subsidyType).indexOf("住院护理") >= 0;
|
||||
},
|
||||
isAccidentSubsidy: function (row) {
|
||||
return this.projectName(row.subsidyType).indexOf("重大变故") >= 0;
|
||||
},
|
||||
hospitalTypeChange: function (row) {
|
||||
this.$set(row, "diseaseDetail", []);
|
||||
if (!this.isHospitalCare(row)) {
|
||||
this.$set(row, "startDate", null);
|
||||
this.$set(row, "endDate", null);
|
||||
}
|
||||
if (!this.isAccidentSubsidy(row)) {
|
||||
this.$set(row, "selfFundedAmount", null);
|
||||
}
|
||||
},
|
||||
addHospitalRecord: function () {
|
||||
this.formData.hospitalRecords.push({diseaseDetail: []});
|
||||
},
|
||||
removeHospitalRecord: function (index) {
|
||||
this.formData.hospitalRecords.splice(index, 1);
|
||||
},
|
||||
onSave: function () {
|
||||
var self = this;
|
||||
this.$confirm("您确定保存吗?", "提示", {
|
||||
confirmButtonText: "确定", cancelButtonText: "取消", type: "warning"
|
||||
}).then(function () {
|
||||
self.$axios.post("/platform/difficultSubsidy/apply/save", {
|
||||
data: JSON.stringify(self.formData)
|
||||
}).then(function (res) {
|
||||
if (res.code === 0) {
|
||||
self.$message.success("保存成功");
|
||||
commonUtil.pjaxPush("/platform/difficultSubsidy/mine");
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
onSubmit: function () {
|
||||
var self = this;
|
||||
this.$refs.formRef.validate(function (valid) {
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
if (!self.formData.hospitalRecords || self.formData.hospitalRecords.length === 0) {
|
||||
self.$message.warning("请填写住院记录");
|
||||
return;
|
||||
}
|
||||
self.$confirm("您确定要提交吗?", "提示", {
|
||||
confirmButtonText: "确定", cancelButtonText: "取消", type: "warning"
|
||||
}).then(function () {
|
||||
if (self.isSchoolAuditEdit) {
|
||||
self.$axios.post("/platform/difficultSubsidy/schoolAudit/modifyApply", {
|
||||
processTaskId: self.taskId,
|
||||
data: JSON.stringify(self.formData)
|
||||
}).then(function (res) {
|
||||
if (res.code === 0) {
|
||||
self.$message.success("修改成功");
|
||||
commonUtil.pjaxPush("/platform/difficultSubsidy/schoolAudit");
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
self.$axios.post("/platform/difficultSubsidy/apply/submit", {
|
||||
data: JSON.stringify(self.formData)
|
||||
}).then(function (res) {
|
||||
if (res.code === 0) {
|
||||
self.$message.success("提交成功");
|
||||
commonUtil.pjaxPush("/platform/difficultSubsidy/mine");
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
created: function () {
|
||||
var self = this;
|
||||
this.loadProject().then(function () {
|
||||
self.loadDetail();
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
+166
@@ -0,0 +1,166 @@
|
||||
<!--#
|
||||
layout("/layouts/platform.html"){
|
||||
#-->
|
||||
<div id="app" v-cloak>
|
||||
<guava ref="guava">
|
||||
<el-card shadow="never">
|
||||
<search @search="doSearch">
|
||||
<search-item label="申请年份">
|
||||
<el-date-picker v-model="pageForm.year" type="year" value-format="yyyy"
|
||||
clearable placeholder="选择申请年份" style="width:100%"></el-date-picker>
|
||||
</search-item>
|
||||
</search>
|
||||
</el-card>
|
||||
<el-card class="mt10" shadow="never">
|
||||
<table-tool label="我的申请">
|
||||
<el-button type="primary" size="small" icon="el-icon-plus" @click="newApply">发起申请</el-button>
|
||||
</table-tool>
|
||||
<el-table :data="tableData" @sort-change="pageOrder" style="width:100%">
|
||||
<el-table-column :index="indexMethod" type="index" label="序号" width="65"></el-table-column>
|
||||
<el-table-column prop="userName" label="姓名" width="110"></el-table-column>
|
||||
<el-table-column prop="loginName" label="工号" width="130"></el-table-column>
|
||||
<el-table-column prop="unitName" label="所属单位" min-width="180" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="申请补助类别" min-width="220" show-overflow-tooltip>
|
||||
<template slot-scope="scope">{{ subsidyTypeNames(scope.row.subsidyType) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="applyDate" label="申请时间" width="170"></el-table-column>
|
||||
<el-table-column prop="currentTaskName" label="当前环节" width="150"></el-table-column>
|
||||
<el-table-column label="状态" width="120">
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="!scope.row.instanceId" type="info" size="small">待提交</el-tag>
|
||||
<enum-tag v-else :value="scope.row.instanceState" name="ProcessInstanceStateEnum"
|
||||
label_key="message" size="small"></enum-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="360" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="primary" size="mini" @click="viewDetail(scope.row)">查看</el-button>
|
||||
<el-button v-if="canEdit(scope.row)" type="primary" size="mini" @click="editApply(scope.row)">编辑</el-button>
|
||||
<el-button v-if="canRevoke(scope.row)" type="danger" size="mini" @click="revoke(scope.row)">撤回</el-button>
|
||||
<el-button type="primary" size="mini" @click="exportApply(scope.row)">导出</el-button>
|
||||
<el-button v-if="canEdit(scope.row)" type="danger" size="mini" @click="deleteApplication(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!--#include("/layouts/pagination.html"){}#-->
|
||||
</el-card>
|
||||
|
||||
<template #view>
|
||||
<difficult-subsidy-info ref="detailRef"></difficult-subsidy-info>
|
||||
</template>
|
||||
</guava>
|
||||
</div>
|
||||
<script nonce="${cspNonce!}">
|
||||
new Vue({
|
||||
el: "#app",
|
||||
store: store,
|
||||
mixins: [initTableMixins],
|
||||
components: {
|
||||
"difficult-subsidy-info": httpVueLoader("/components/zhgh/difficultSubsidy/ProcessInfo.vue")
|
||||
},
|
||||
data: function () {
|
||||
return {
|
||||
pageDataUrl: "/platform/difficultSubsidy/mine/pageData",
|
||||
pageForm: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
totalCount: 0,
|
||||
pageOrderName: "",
|
||||
pageOrderBy: "",
|
||||
year: ""
|
||||
},
|
||||
projectList: []
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
loadProject: function () {
|
||||
var self = this;
|
||||
this.$axios.post("/platform/difficultSubsidy/common/projectInfo").then(function (res) {
|
||||
if (res.code === 0) {
|
||||
self.$set(self, "projectList", res.data.projectList || []);
|
||||
}
|
||||
});
|
||||
},
|
||||
subsidyTypeNames: function (ids) {
|
||||
var selected = ids || [];
|
||||
return this.projectList.filter(function (item) {
|
||||
return selected.indexOf(item.id) >= 0;
|
||||
}).map(function (item) {
|
||||
return item.projectName;
|
||||
}).join("、");
|
||||
},
|
||||
canEdit: function (row) {
|
||||
return !row.instanceId || !!row.returnedStartTaskId;
|
||||
},
|
||||
canRevoke: function (row) {
|
||||
return !!row.instanceId && row.instanceState === 10 && !!row.startTaskId && !row.returnedStartTaskId;
|
||||
},
|
||||
newApply: function () {
|
||||
commonUtil.pjaxPush("/platform/difficultSubsidy/apply");
|
||||
},
|
||||
editApply: function (row) {
|
||||
commonUtil.pjaxPush("/platform/difficultSubsidy/apply?taskId="
|
||||
+ (row.returnedStartTaskId || "") + "&bizId=" + row.id);
|
||||
},
|
||||
viewDetail: function (row) {
|
||||
var self = this;
|
||||
this.$refs.guava.view(function () {
|
||||
self.openDetailWhenReady(row, 0);
|
||||
});
|
||||
},
|
||||
openDetailWhenReady: function (row, retryCount) {
|
||||
var self = this;
|
||||
this.$nextTick(function () {
|
||||
if (self.$refs.detailRef) {
|
||||
self.$refs.detailRef.open(row.id);
|
||||
return;
|
||||
}
|
||||
// httpVueLoader 首次进入时可能尚未挂载组件,短暂重试后再传入申请ID。
|
||||
if (retryCount < 20) {
|
||||
setTimeout(function () {
|
||||
self.openDetailWhenReady(row, retryCount + 1);
|
||||
}, 50);
|
||||
} else {
|
||||
self.$message.error("详情组件加载失败,请刷新后重试");
|
||||
}
|
||||
});
|
||||
},
|
||||
revoke: function (row) {
|
||||
var self = this;
|
||||
this.$confirm("确定撤回该申请吗?撤回后可以修改并重新提交。", "提示", {
|
||||
confirmButtonText: "确定", cancelButtonText: "取消", type: "warning"
|
||||
}).then(function () {
|
||||
self.$axios.post("/flow/common/revokeTask", {taskId: row.startTaskId}).then(function (res) {
|
||||
if (res.code === 0) {
|
||||
self.$message.success("撤回成功");
|
||||
self.pageData();
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
deleteApplication: function (row) {
|
||||
var self = this;
|
||||
this.$confirm("确定删除该申请吗?申请记录、审核记录及相关待办将一并永久删除。", "提示", {
|
||||
confirmButtonText: "确定", cancelButtonText: "取消", type: "warning"
|
||||
}).then(function () {
|
||||
self.$axios.post("/platform/difficultSubsidy/mine/delete", {id: row.id}).then(function (res) {
|
||||
if (res.code === 0) {
|
||||
self.$message.success("删除成功");
|
||||
self.pageData();
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
exportApply: function (row) {
|
||||
this.$downLoad("/platform/difficultSubsidy/mine/exportApplyInfo?id=" + row.id);
|
||||
}
|
||||
},
|
||||
created: function () {
|
||||
this.loadProject();
|
||||
this.pageData();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
+494
@@ -0,0 +1,494 @@
|
||||
<!--#
|
||||
layout("/layouts/platform.html"){
|
||||
#-->
|
||||
<div id="app" v-cloak>
|
||||
<guava ref="guava">
|
||||
<el-card shadow="never">
|
||||
<search @search="doSearch">
|
||||
<search-item label="申请年份">
|
||||
<el-date-picker v-model="pageForm.year" type="year" value-format="yyyy"
|
||||
clearable placeholder="选择申请年份" style="width:100%"></el-date-picker>
|
||||
</search-item>
|
||||
<search-item label="申请月份">
|
||||
<el-date-picker class="difficult-subsidy-month-range" v-model="monthRange" type="monthrange" value-format="yyyy-MM"
|
||||
clearable unlink-panels range-separator="至" start-placeholder="开始月份"
|
||||
end-placeholder="结束月份" style="width:100%"
|
||||
@change="monthRangeChange"></el-date-picker>
|
||||
</search-item>
|
||||
<search-item label="姓名工号">
|
||||
<el-input v-model="pageForm.searchKeyword" clearable maxlength="30"></el-input>
|
||||
</search-item>
|
||||
<search-item label="所属工会">
|
||||
<el-select v-model="pageForm.unionId" clearable placeholder="所属工会" style="width:100%"
|
||||
@change="flushUnits">
|
||||
<el-option v-for="item in unions" :key="item.id" :label="item.name" :value="item.id"></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
<search-item label="所属单位">
|
||||
<el-select v-model="pageForm.unitId" clearable filterable placeholder="所属单位" style="width:100%">
|
||||
<el-option v-for="item in units" :key="item.id" :label="item.name" :value="item.id"></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
</search>
|
||||
</el-card>
|
||||
<el-card class="mt10" shadow="never">
|
||||
<table-tool label="特困补助校工会审核">
|
||||
<el-button type="primary" size="small" style="margin-right:10px" @click="exportZip">导出审核材料</el-button>
|
||||
<el-radio-group v-model="pageForm.isAudit" size="small" @change="doSearch">
|
||||
<el-radio-button :label="0">全部</el-radio-button>
|
||||
<el-radio-button :label="1">已审核</el-radio-button>
|
||||
<el-radio-button :label="-1">未审核</el-radio-button>
|
||||
</el-radio-group>
|
||||
</table-tool>
|
||||
<el-table :data="tableData" @sort-change="pageOrder" style="width:100%">
|
||||
<el-table-column :index="indexMethod" type="index" label="序号" width="65"></el-table-column>
|
||||
<el-table-column prop="loginName" label="工号" width="130"></el-table-column>
|
||||
<el-table-column prop="userName" label="姓名" width="110"></el-table-column>
|
||||
<el-table-column prop="unitName" label="所属单位" min-width="170" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column prop="unionName" label="所属工会" min-width="160" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="申请补助类别" min-width="220" show-overflow-tooltip>
|
||||
<template slot-scope="scope">{{ subsidyTypeNames(scope.row.subsidyType) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="applyDate" label="申请时间" width="170"></el-table-column>
|
||||
<el-table-column prop="currentTaskName" label="当前环节" width="140"></el-table-column>
|
||||
<el-table-column label="操作" width="370" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="primary" size="mini" @click="viewDetail(scope.row)">查看</el-button>
|
||||
<el-button v-if="scope.row.taskState === 10" type="primary" size="mini"
|
||||
@click="openAudit(scope.row)">审核</el-button>
|
||||
<el-button v-if="scope.row.taskState === 20" type="danger" size="mini"
|
||||
@click="revoke(scope.row)">撤销</el-button>
|
||||
<el-button v-if="scope.row.stateId === 7070" type="warning" size="mini"
|
||||
@click="openAmount(scope.row)">修改金额</el-button>
|
||||
<el-button v-if="scope.row.taskState === 10" type="primary" size="mini"
|
||||
@click="editApply(scope.row)">修改</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!--#include("/layouts/pagination.html"){}#-->
|
||||
</el-card>
|
||||
|
||||
<template #view>
|
||||
<difficult-subsidy-info ref="detailRef">
|
||||
<div v-if="auditMode" style="margin-top:20px">
|
||||
<div class="process-title">校工会审核</div>
|
||||
<el-form ref="auditFormRef" :model="auditForm" class="school-audit-form">
|
||||
<el-descriptions :column="2" border class="flow-task-form">
|
||||
<el-descriptions-item label="审核人">
|
||||
<el-input :value="$store.state.user.username" readonly></el-input>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="审核时间">
|
||||
<el-input :value="auditForm.auditDate" readonly></el-input>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="审核意见" :span="2">
|
||||
<el-form-item prop="opinion"
|
||||
:rules="[{required:true,message:'请填写审核意见',trigger:['blur','change']}]">
|
||||
<el-input v-model="auditForm.opinion" type="textarea" :rows="3"
|
||||
maxlength="1000" show-word-limit></el-input>
|
||||
</el-form-item>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="补助项目" :span="2">
|
||||
<el-table :data="moneyData.hospitalRecords || []" border style="width:100%">
|
||||
<el-table-column label="就诊医院" prop="hospitalName" min-width="120"></el-table-column>
|
||||
<el-table-column label="入院时间" prop="startDate" width="110"></el-table-column>
|
||||
<el-table-column label="出院时间" prop="endDate" width="110"></el-table-column>
|
||||
<el-table-column label="自费金额(元)" prop="selfFundedAmount" width="120"></el-table-column>
|
||||
<el-table-column label="补助类型" min-width="150">
|
||||
<template slot-scope="scope">{{ projectName(scope.row.subsidyType) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="疾病详情" min-width="180" show-overflow-tooltip>
|
||||
<template slot-scope="scope">{{ diseaseNames(scope.row.diseaseDetail) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" prop="notes" min-width="110" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="是否通过" width="100">
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.isPass === true" type="success" size="small">通过</el-tag>
|
||||
<el-tag v-else-if="scope.row.isPass === false" type="danger" size="small">拒绝</el-tag>
|
||||
<el-tag v-else type="info" size="small">待审核</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="补助金额" width="110">
|
||||
<template slot-scope="scope">{{ recordSubsidyMoney(scope.row) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="160" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<el-button :type="scope.row.isPass === true ? 'primary' : 'default'" size="mini"
|
||||
@click="setRecordPass(scope.row, true)">通过</el-button>
|
||||
<el-button :type="scope.row.isPass === false ? 'danger' : 'default'" size="mini"
|
||||
@click="setRecordPass(scope.row, false)">拒绝</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="历史申请记录" :span="2">
|
||||
<el-table v-if="moneyData.flatHistoryRecords && moneyData.flatHistoryRecords.length"
|
||||
:data="moneyData.flatHistoryRecords" border style="width:100%">
|
||||
<el-table-column label="就诊医院" prop="hospitalName" min-width="130"></el-table-column>
|
||||
<el-table-column label="入院时间" prop="startDate" width="110"></el-table-column>
|
||||
<el-table-column label="出院时间" prop="endDate" width="110"></el-table-column>
|
||||
<el-table-column label="自费金额(元)" prop="selfFundedAmount" width="120"></el-table-column>
|
||||
<el-table-column label="补助类型" min-width="160">
|
||||
<template slot-scope="scope">{{ projectName(scope.row.subsidyType) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="疾病详情" min-width="200" show-overflow-tooltip>
|
||||
<template slot-scope="scope">{{ diseaseNames(scope.row.diseaseDetail) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="补助金额" width="110">
|
||||
<template slot-scope="scope">{{ recordSubsidyMoney(scope.row) }}</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-empty v-else description="暂无历史申请记录" :image-size="70"></el-empty>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="预测补助金额(元)" :span="2">
|
||||
<el-form-item prop="finalSubsidyAmount"
|
||||
:rules="[{required:true,message:'通过时请填写预测补助金额',trigger:'change'}]">
|
||||
<el-input-number v-model="auditForm.finalSubsidyAmount" :min="0" :precision="2"
|
||||
style="width:180px"></el-input-number>
|
||||
<span class="audit-amount-tip">(通过此项必填)</span>
|
||||
</el-form-item>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-form>
|
||||
</div>
|
||||
<div v-if="auditMode" style="padding-top:20px;text-align:right">
|
||||
<el-button @click="closeAudit">取消</el-button>
|
||||
<el-button type="danger" @click="submitAudit(2)">拒绝</el-button>
|
||||
<el-button type="info" @click="submitAudit(6)">退回</el-button>
|
||||
<el-button type="primary" @click="submitAudit(1)">通过</el-button>
|
||||
</div>
|
||||
</difficult-subsidy-info>
|
||||
</template>
|
||||
|
||||
<el-dialog title="修改最终补助金额" :visible.sync="amountVisible" width="460px" :close-on-click-modal="false">
|
||||
<el-form label-width="130px">
|
||||
<el-form-item label="最终补助金额">
|
||||
<el-input-number v-model="amountForm.finalSubsidyAmount" :min="0" :precision="2"
|
||||
style="width:100%"></el-input-number>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer">
|
||||
<el-button @click="closeAmount">取消</el-button>
|
||||
<el-button type="primary" @click="saveAmount">确定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</guava>
|
||||
</div>
|
||||
<style>
|
||||
/* 月份范围控件在筛选栏较窄时,固定分隔符宽度,避免“至”被压缩裁切。 */
|
||||
.difficult-subsidy-month-range .el-range-input {
|
||||
flex: 1 1 0;
|
||||
width: 0;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.difficult-subsidy-month-range .el-range-separator {
|
||||
flex: 0 0 24px;
|
||||
width: 24px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.school-audit-form .el-descriptions-item__label {
|
||||
width: 130px;
|
||||
}
|
||||
|
||||
.school-audit-form .el-form-item {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.audit-amount-tip {
|
||||
color: #f56c6c;
|
||||
margin-left: 8px;
|
||||
}
|
||||
</style>
|
||||
<script nonce="${cspNonce!}">
|
||||
new Vue({
|
||||
el: "#app",
|
||||
store: store,
|
||||
mixins: [initTableMixins],
|
||||
components: {
|
||||
"difficult-subsidy-info": httpVueLoader("/components/zhgh/difficultSubsidy/ProcessInfo.vue")
|
||||
},
|
||||
data: function () {
|
||||
return {
|
||||
pageDataUrl: "/platform/difficultSubsidy/schoolAudit/pageData",
|
||||
pageForm: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
totalCount: 0,
|
||||
pageOrderName: "",
|
||||
pageOrderBy: "",
|
||||
year: "",
|
||||
startMonth: "",
|
||||
endMonth: "",
|
||||
searchKeyword: "",
|
||||
unionId: "",
|
||||
unitId: "",
|
||||
isAudit: -1
|
||||
},
|
||||
monthRange: [],
|
||||
unions: [],
|
||||
units: [],
|
||||
projectList: [],
|
||||
diseaseList: [],
|
||||
auditMode: false,
|
||||
amountVisible: false,
|
||||
moneyData: {},
|
||||
auditForm: {},
|
||||
amountForm: {}
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
loadOptions: function () {
|
||||
var self = this;
|
||||
this.$businessTool.listUnion().then(function (items) {
|
||||
self.$set(self, "unions", items || []);
|
||||
});
|
||||
this.$axios.post("/platform/difficultSubsidy/common/projectInfo").then(function (res) {
|
||||
if (res.code === 0) {
|
||||
self.$set(self, "projectList", res.data.projectList || []);
|
||||
self.$set(self, "diseaseList", res.data.diseaseList || []);
|
||||
}
|
||||
});
|
||||
},
|
||||
flushUnits: function () {
|
||||
var self = this;
|
||||
this.$set(this.pageForm, "unitId", null);
|
||||
this.$set(this, "units", []);
|
||||
if (this.pageForm.unionId) {
|
||||
this.$businessTool.listUnit(this.pageForm.unionId).then(function (items) {
|
||||
self.$set(self, "units", items || []);
|
||||
});
|
||||
}
|
||||
},
|
||||
monthRangeChange: function (value) {
|
||||
var months = value || [];
|
||||
if (months.length === 2 && months[0].substring(0, 4) !== months[1].substring(0, 4)) {
|
||||
this.$message.warning("开始月份和结束月份必须属于同一年");
|
||||
this.$set(this, "monthRange", []);
|
||||
this.$set(this.pageForm, "startMonth", "");
|
||||
this.$set(this.pageForm, "endMonth", "");
|
||||
return;
|
||||
}
|
||||
this.$set(this.pageForm, "startMonth", months[0] || "");
|
||||
this.$set(this.pageForm, "endMonth", months[1] || "");
|
||||
if (months.length === 2) {
|
||||
this.$set(this.pageForm, "year", months[0].substring(0, 4));
|
||||
}
|
||||
},
|
||||
projectName: function (id) {
|
||||
var item = this.projectList.find(function (project) {
|
||||
return project.id === id;
|
||||
});
|
||||
return item ? item.projectName : "";
|
||||
},
|
||||
subsidyTypeNames: function (ids) {
|
||||
var self = this;
|
||||
var idList = this.normalizeIdList(ids);
|
||||
return idList.map(function (id) {
|
||||
return self.projectName(id);
|
||||
}).filter(function (name) {
|
||||
return name;
|
||||
}).join("、");
|
||||
},
|
||||
normalizeIdList: function (ids) {
|
||||
if (Array.isArray(ids)) {
|
||||
return ids;
|
||||
}
|
||||
if (typeof ids === "string" && ids) {
|
||||
try {
|
||||
var parsedIds = JSON.parse(ids);
|
||||
return Array.isArray(parsedIds) ? parsedIds : [];
|
||||
} catch (e) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
return [];
|
||||
},
|
||||
diseaseNames: function (ids) {
|
||||
var selected = ids || [];
|
||||
return this.diseaseList.filter(function (item) {
|
||||
return selected.indexOf(item.id) >= 0;
|
||||
}).map(function (item) {
|
||||
return item.diseaseName;
|
||||
}).join("、");
|
||||
},
|
||||
viewDetail: function (row) {
|
||||
var self = this;
|
||||
this.$set(this, "auditMode", false);
|
||||
this.$refs.guava.view(function () {
|
||||
self.openDetailWhenReady(row, 0);
|
||||
});
|
||||
},
|
||||
editApply: function (row) {
|
||||
commonUtil.pjaxPush("/platform/difficultSubsidy/schoolAudit/edit?schoolAuditEdit=1&taskId="
|
||||
+ row.taskId + "&bizId=" + row.id);
|
||||
},
|
||||
openAudit: function (row) {
|
||||
var self = this;
|
||||
this.$set(this, "auditMode", true);
|
||||
this.$set(this, "auditForm", {
|
||||
id: row.id,
|
||||
processTaskId: row.taskId,
|
||||
opinion: "",
|
||||
auditDate: this.$moment().format("YYYY-MM-DD"),
|
||||
finalSubsidyAmount: row.finalSubsidyAmount
|
||||
});
|
||||
this.$axios.post("/platform/difficultSubsidy/schoolAudit/calculateSubsidy", {id: row.id}).then(function (res) {
|
||||
if (res.code === 0) {
|
||||
var data = res.data || {};
|
||||
(data.hospitalRecords || []).forEach(function (record) {
|
||||
self.$set(record, "isPass", typeof record.isPass === "boolean" ? record.isPass : null);
|
||||
});
|
||||
self.$set(data, "flatHistoryRecords", self.flattenHistoryRecords(data.historyHospitalRecords));
|
||||
self.$set(self, "moneyData", data);
|
||||
if (self.auditForm.finalSubsidyAmount === null || self.auditForm.finalSubsidyAmount === undefined) {
|
||||
self.$set(self.auditForm, "finalSubsidyAmount", data.totalMoney || 0);
|
||||
}
|
||||
}
|
||||
});
|
||||
this.$refs.guava.view(function () {
|
||||
self.openDetailWhenReady(row, 0);
|
||||
});
|
||||
},
|
||||
openDetailWhenReady: function (row, retryCount) {
|
||||
var self = this;
|
||||
this.$nextTick(function () {
|
||||
if (self.$refs.detailRef) {
|
||||
self.$refs.detailRef.open(row.id);
|
||||
return;
|
||||
}
|
||||
// httpVueLoader 首次进入时可能尚未挂载组件,短暂重试后再传入申请ID。
|
||||
if (retryCount < 20) {
|
||||
setTimeout(function () {
|
||||
self.openDetailWhenReady(row, retryCount + 1);
|
||||
}, 50);
|
||||
} else {
|
||||
self.$message.error("详情组件加载失败,请刷新后重试");
|
||||
}
|
||||
});
|
||||
},
|
||||
closeAudit: function () {
|
||||
this.$set(this, "auditMode", false);
|
||||
this.$refs.guava.index();
|
||||
},
|
||||
setRecordPass: function (row, pass) {
|
||||
this.$set(row, "isPass", pass);
|
||||
this.refreshAuditMoney();
|
||||
},
|
||||
recordSubsidyMoney: function (row) {
|
||||
if (row.isPass === false) {
|
||||
return "0.00";
|
||||
}
|
||||
var subsidyMoney = Number(row.subsidyMoney || 0);
|
||||
var hospitalMoney = Number(row.hospitalMoney || 0);
|
||||
return (subsidyMoney + hospitalMoney).toFixed(2);
|
||||
},
|
||||
refreshAuditMoney: function () {
|
||||
var totalSubsidyMoney = 0;
|
||||
var totalHospitalMoney = 0;
|
||||
(this.moneyData.hospitalRecords || []).forEach(function (record) {
|
||||
if (record.isPass !== false) {
|
||||
totalSubsidyMoney += Number(record.subsidyMoney || 0);
|
||||
totalHospitalMoney += Number(record.hospitalMoney || 0);
|
||||
}
|
||||
});
|
||||
this.$set(this.moneyData, "totalSubsidyMoney", totalSubsidyMoney);
|
||||
this.$set(this.moneyData, "totalHospitalMoney", totalHospitalMoney);
|
||||
this.$set(this.moneyData, "totalMoney", totalSubsidyMoney + totalHospitalMoney);
|
||||
this.$set(this.auditForm, "finalSubsidyAmount", totalSubsidyMoney + totalHospitalMoney);
|
||||
},
|
||||
flattenHistoryRecords: function (historyHospitalRecords) {
|
||||
return (historyHospitalRecords || []).reduce(function (records, item) {
|
||||
return records.concat(Array.isArray(item) ? item : []);
|
||||
}, []);
|
||||
},
|
||||
submitAudit: function (submitType) {
|
||||
var self = this;
|
||||
if (!this.auditForm.opinion) {
|
||||
this.$message.warning("请填写审核意见");
|
||||
return;
|
||||
}
|
||||
if (submitType === 1 && (this.moneyData.hospitalRecords || []).some(function (record) {
|
||||
return typeof record.isPass !== "boolean";
|
||||
})) {
|
||||
this.$message.warning("请完成每个补助项目的通过或拒绝审核");
|
||||
return;
|
||||
}
|
||||
if (submitType === 1 && (this.auditForm.finalSubsidyAmount === null || this.auditForm.finalSubsidyAmount === undefined)) {
|
||||
this.$message.warning("请填写最终补助金额");
|
||||
return;
|
||||
}
|
||||
this.$confirm("确定提交该审核结果吗?", "提示", {
|
||||
confirmButtonText: "确定", cancelButtonText: "取消", type: "warning"
|
||||
}).then(function () {
|
||||
self.$axios.post("/platform/difficultSubsidy/schoolAudit/executeTask", {
|
||||
processTaskId: self.auditForm.processTaskId,
|
||||
submitType: submitType,
|
||||
opinion: self.auditForm.opinion,
|
||||
finalSubsidyAmount: self.auditForm.finalSubsidyAmount,
|
||||
hospitalRecords: JSON.stringify(self.moneyData.hospitalRecords || [])
|
||||
}).then(function (res) {
|
||||
if (res.code === 0) {
|
||||
self.$message.success("审核完成");
|
||||
self.$set(self, "auditMode", false);
|
||||
self.$refs.guava.index();
|
||||
self.pageData();
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
revoke: function (row) {
|
||||
var self = this;
|
||||
this.$confirm("确定撤销该审核结果吗?", "提示", {type: "warning"}).then(function () {
|
||||
self.$axios.post("/platform/difficultSubsidy/schoolAudit/revoke", {processTaskId: row.taskId}).then(function (res) {
|
||||
if (res.code === 0) {
|
||||
self.$message.success("撤销成功");
|
||||
self.pageData();
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
openAmount: function (row) {
|
||||
this.$set(this, "amountForm", {id: row.id, finalSubsidyAmount: row.finalSubsidyAmount});
|
||||
this.$set(this, "amountVisible", true);
|
||||
},
|
||||
closeAmount: function () {
|
||||
this.$set(this, "amountVisible", false);
|
||||
},
|
||||
saveAmount: function () {
|
||||
var self = this;
|
||||
if (this.amountForm.finalSubsidyAmount === null || this.amountForm.finalSubsidyAmount === undefined) {
|
||||
this.$message.warning("请填写最终补助金额");
|
||||
return;
|
||||
}
|
||||
this.$axios.post("/platform/difficultSubsidy/schoolAudit/modifyFinalSubsidyAmount", this.amountForm).then(function (res) {
|
||||
if (res.code === 0) {
|
||||
self.$message.success("修改成功");
|
||||
self.$set(self, "amountVisible", false);
|
||||
self.pageData();
|
||||
}
|
||||
});
|
||||
},
|
||||
exportZip: function () {
|
||||
var year = this.pageForm.year;
|
||||
if (!year) {
|
||||
this.$message.warning("请选择需要导出的申请年份");
|
||||
return;
|
||||
}
|
||||
var query = "?year=" + encodeURIComponent(year);
|
||||
if (this.pageForm.startMonth && this.pageForm.endMonth) {
|
||||
query += "&startMonth=" + encodeURIComponent(this.pageForm.startMonth)
|
||||
+ "&endMonth=" + encodeURIComponent(this.pageForm.endMonth);
|
||||
}
|
||||
this.$downLoad("/platform/difficultSubsidy/schoolAudit/exportZip" + query);
|
||||
}
|
||||
},
|
||||
created: function () {
|
||||
this.loadOptions();
|
||||
this.pageData();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
+211
@@ -0,0 +1,211 @@
|
||||
<!--#
|
||||
layout("/layouts/platform.html"){
|
||||
#-->
|
||||
<div id="app" v-cloak>
|
||||
<guava ref="guava">
|
||||
<el-card shadow="never">
|
||||
<search @search="doSearch">
|
||||
<search-item label="申请年份">
|
||||
<el-date-picker v-model="pageForm.year" type="year" value-format="yyyy"
|
||||
clearable placeholder="选择申请年份" style="width:100%"></el-date-picker>
|
||||
</search-item>
|
||||
<search-item label="申请月份">
|
||||
<el-date-picker class="difficult-subsidy-month-range" v-model="monthRange" type="monthrange" value-format="yyyy-MM"
|
||||
clearable unlink-panels range-separator="至" start-placeholder="开始月份"
|
||||
end-placeholder="结束月份" style="width:100%"
|
||||
@change="monthRangeChange"></el-date-picker>
|
||||
</search-item>
|
||||
<search-item label="姓名工号">
|
||||
<el-input v-model="pageForm.searchKeyword" clearable maxlength="30"></el-input>
|
||||
</search-item>
|
||||
<search-item label="所属工会">
|
||||
<el-select v-model="pageForm.unionId" clearable placeholder="所属工会" style="width:100%"
|
||||
@change="flushUnits">
|
||||
<el-option v-for="item in unions" :key="item.id" :label="item.name" :value="item.id"></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
<search-item label="所属单位">
|
||||
<el-select v-model="pageForm.unitId" clearable filterable placeholder="所属单位" style="width:100%">
|
||||
<el-option v-for="item in units" :key="item.id" :label="item.name" :value="item.id"></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
</search>
|
||||
</el-card>
|
||||
<el-card class="mt10" shadow="never">
|
||||
<table-tool label="特困补助查询">
|
||||
<el-button type="primary" size="small" @click="exportExcel">导出汇总表 Excel</el-button>
|
||||
<el-button type="primary" size="small" @click="exportWord">导出汇总表 Word</el-button>
|
||||
</table-tool>
|
||||
<el-table :data="tableData" @sort-change="pageOrder" style="width:100%">
|
||||
<el-table-column :index="indexMethod" type="index" label="序号" width="65"></el-table-column>
|
||||
<el-table-column prop="loginName" label="工号" width="130"></el-table-column>
|
||||
<el-table-column prop="userName" label="姓名" width="110"></el-table-column>
|
||||
<el-table-column prop="unitName" label="所属单位" min-width="180" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column prop="unionName" label="所属工会" min-width="160" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="申请补助类别" min-width="220" show-overflow-tooltip>
|
||||
<template slot-scope="scope">{{ subsidyTypeNames(scope.row.subsidyType) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="applyDate" label="申请时间" width="170"></el-table-column>
|
||||
<el-table-column prop="subsidyAmount" label="建议补助金额" width="130"></el-table-column>
|
||||
<el-table-column prop="finalSubsidyAmount" label="最终补助金额" width="130"></el-table-column>
|
||||
<el-table-column label="操作" width="90" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="primary" size="mini" @click="viewDetail(scope.row)">查看</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!--#include("/layouts/pagination.html"){}#-->
|
||||
</el-card>
|
||||
|
||||
<template #view>
|
||||
<difficult-subsidy-info ref="detailRef"></difficult-subsidy-info>
|
||||
</template>
|
||||
</guava>
|
||||
</div>
|
||||
<style>
|
||||
/* 月份范围控件在筛选栏较窄时,固定分隔符宽度,避免“至”被压缩裁切。 */
|
||||
.difficult-subsidy-month-range .el-range-input {
|
||||
flex: 1 1 0;
|
||||
width: 0;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.difficult-subsidy-month-range .el-range-separator {
|
||||
flex: 0 0 24px;
|
||||
width: 24px;
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
<script nonce="${cspNonce!}">
|
||||
new Vue({
|
||||
el: "#app",
|
||||
store: store,
|
||||
mixins: [initTableMixins],
|
||||
components: {
|
||||
"difficult-subsidy-info": httpVueLoader("/components/zhgh/difficultSubsidy/ProcessInfo.vue")
|
||||
},
|
||||
data: function () {
|
||||
return {
|
||||
pageDataUrl: "/platform/difficultSubsidy/query/pageData",
|
||||
pageForm: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
totalCount: 0,
|
||||
pageOrderName: "",
|
||||
pageOrderBy: "",
|
||||
year: "",
|
||||
startMonth: "",
|
||||
endMonth: "",
|
||||
searchKeyword: "",
|
||||
unionId: "",
|
||||
unitId: ""
|
||||
},
|
||||
monthRange: [],
|
||||
unions: [],
|
||||
units: [],
|
||||
projectList: []
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
loadOptions: function () {
|
||||
var self = this;
|
||||
this.$businessTool.listUnion().then(function (items) {
|
||||
self.$set(self, "unions", items || []);
|
||||
});
|
||||
this.$axios.post("/platform/difficultSubsidy/common/projectInfo").then(function (res) {
|
||||
if (res.code === 0) {
|
||||
self.$set(self, "projectList", res.data.projectList || []);
|
||||
}
|
||||
});
|
||||
},
|
||||
flushUnits: function () {
|
||||
var self = this;
|
||||
this.$set(this.pageForm, "unitId", null);
|
||||
this.$set(this, "units", []);
|
||||
if (this.pageForm.unionId) {
|
||||
this.$businessTool.listUnit(this.pageForm.unionId).then(function (items) {
|
||||
self.$set(self, "units", items || []);
|
||||
});
|
||||
}
|
||||
},
|
||||
monthRangeChange: function (value) {
|
||||
var months = value || [];
|
||||
if (months.length === 2 && months[0].substring(0, 4) !== months[1].substring(0, 4)) {
|
||||
this.$message.warning("开始月份和结束月份必须属于同一年");
|
||||
this.$set(this, "monthRange", []);
|
||||
this.$set(this.pageForm, "startMonth", "");
|
||||
this.$set(this.pageForm, "endMonth", "");
|
||||
return;
|
||||
}
|
||||
this.$set(this.pageForm, "startMonth", months[0] || "");
|
||||
this.$set(this.pageForm, "endMonth", months[1] || "");
|
||||
if (months.length === 2) {
|
||||
this.$set(this.pageForm, "year", months[0].substring(0, 4));
|
||||
}
|
||||
},
|
||||
subsidyTypeNames: function (ids) {
|
||||
var selected = ids || [];
|
||||
return this.projectList.filter(function (item) {
|
||||
return selected.indexOf(item.id) >= 0;
|
||||
}).map(function (item) {
|
||||
return item.projectName;
|
||||
}).join("、");
|
||||
},
|
||||
viewDetail: function (row) {
|
||||
var self = this;
|
||||
this.$refs.guava.view(function () {
|
||||
self.openDetailWhenReady(row, 0);
|
||||
});
|
||||
},
|
||||
openDetailWhenReady: function (row, retryCount) {
|
||||
var self = this;
|
||||
this.$nextTick(function () {
|
||||
if (self.$refs.detailRef) {
|
||||
self.$refs.detailRef.open(row.id);
|
||||
return;
|
||||
}
|
||||
// httpVueLoader 首次进入时可能尚未挂载组件,短暂重试后再传入申请ID。
|
||||
if (retryCount < 20) {
|
||||
setTimeout(function () {
|
||||
self.openDetailWhenReady(row, retryCount + 1);
|
||||
}, 50);
|
||||
} else {
|
||||
self.$message.error("详情组件加载失败,请刷新后重试");
|
||||
}
|
||||
});
|
||||
},
|
||||
yearQuery: function () {
|
||||
var year = this.pageForm.year;
|
||||
if (!year) {
|
||||
this.$message.warning("请选择需要导出的申请年份");
|
||||
return null;
|
||||
}
|
||||
var query = "?year=" + encodeURIComponent(year);
|
||||
if (this.pageForm.startMonth && this.pageForm.endMonth) {
|
||||
query += "&startMonth=" + encodeURIComponent(this.pageForm.startMonth)
|
||||
+ "&endMonth=" + encodeURIComponent(this.pageForm.endMonth);
|
||||
}
|
||||
return query;
|
||||
},
|
||||
exportExcel: function () {
|
||||
var query = this.yearQuery();
|
||||
if (query) {
|
||||
this.$downLoad("/platform/difficultSubsidy/query/exportSummaryExcel" + query);
|
||||
}
|
||||
},
|
||||
exportWord: function () {
|
||||
var query = this.yearQuery();
|
||||
if (query) {
|
||||
this.$downLoad("/platform/difficultSubsidy/query/exportSummary" + query);
|
||||
}
|
||||
}
|
||||
},
|
||||
created: function () {
|
||||
this.loadOptions();
|
||||
this.pageData();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
+2
-2
@@ -63,7 +63,7 @@ layout("/layouts/platform.html"){
|
||||
</el-checkbox>
|
||||
<div style="cursor: pointer;" @click="isReadClick" class="ml5">
|
||||
<div style="color: #1e88e5">
|
||||
中国地质大学(武汉)教职工重大疾病互助基金管理办法
|
||||
西南财经大学教职工重大疾病互助基金管理办法
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -137,7 +137,7 @@ layout("/layouts/platform.html"){
|
||||
this.$commonUtil.previewFile({
|
||||
suffix: "pdf",
|
||||
downloadPath: "/platform/sys/file/download?id=orpgde84uggjmpflbob83tadan",
|
||||
name: "中国地质大学(武汉)教职工重大疾病互助基金管理办法.pdf",
|
||||
name: "西南财经大学教职工重大疾病互助基金管理办法.pdf",
|
||||
id: "orpgde84uggjmpflbob83tadan"
|
||||
})
|
||||
},
|
||||
|
||||
+277
@@ -0,0 +1,277 @@
|
||||
<!--#
|
||||
layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
<div id="app" v-cloak>
|
||||
<van-nav-bar @click-left="historyBack" left-arrow left-text="返回" title="提案委员会立案" placeholder fixed></van-nav-bar>
|
||||
<van-sticky offset-top="46px">
|
||||
<van-search v-model="pageForm.name" :show-action="false" :reverse-color="false" input-align="left"
|
||||
placeholder="请输入提案名称搜索" @search="doSearch"></van-search>
|
||||
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||
<van-dropdown-item v-model="pageForm.sessionId" :options="sessionOptions" :multiple="false"
|
||||
@change="doSearch"></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
<van-tabs v-model="pageForm.approvalText" @change="changeApproval">
|
||||
<van-tab title="已审核" name="1"></van-tab>
|
||||
<van-tab title="未审核" name="0"></van-tab>
|
||||
</van-tabs>
|
||||
</van-sticky>
|
||||
|
||||
<table-list api="/platform/proposal/committeeFiling/h5/pageData" :page_form.sync="pageForm" @ready="onReady"
|
||||
ref="tableListRef" title="name">
|
||||
<template v-slot="{index,row}">
|
||||
<table-column label="提案编号">{{row.code}}</table-column>
|
||||
<table-column label="提案类别">{{row.typeName}}</table-column>
|
||||
<table-column label="提案人">{{row.createUserName}}</table-column>
|
||||
<table-column label="代表团">{{row.delegationName}}</table-column>
|
||||
<table-column label="当前节点">{{row.curTaskName}}</table-column>
|
||||
</template>
|
||||
<template #actions="{index,row}">
|
||||
<div class="action-btn" @click="onView(row)">
|
||||
<i class="fa fa-eye"></i><span>查看</span>
|
||||
</div>
|
||||
<div class="action-btn" v-if="row.taskState === 10" @click="onApproval(row)">
|
||||
<i class="fa fa-edit"></i><span>立案</span>
|
||||
</div>
|
||||
</template>
|
||||
</table-list>
|
||||
|
||||
<proposal-info ref="proposalInfoRef">
|
||||
<div v-if="showApprovalForm">
|
||||
<div class="process-title">{{formData.taskName}}</div>
|
||||
<van-form ref="formRef">
|
||||
<van-field v-model="formData.tf_caseFilingResultName" name="tf_caseFilingResultName" label="立案结果"
|
||||
placeholder="请选择立案结果" readonly is-link @click="openResultPicker"
|
||||
:rules="[{ required: true, message: '请选择立案结果' }]" required></van-field>
|
||||
<van-popup v-model="showResultPicker" position="bottom">
|
||||
<van-picker show-toolbar :columns="caseFilingResultOptions" @confirm="onResultConfirm"
|
||||
@cancel="closeResultPicker"></van-picker>
|
||||
</van-popup>
|
||||
<van-field v-if="showUndertakeUnit" :value="masterUnitNames" :label="masterUnitLabel" readonly is-link
|
||||
:placeholder="masterUnitLabel === '办理单位' ? '请选择办理单位' : '请选择主办单位'"
|
||||
@click="openMasterUnitPicker"
|
||||
:rules="[{ required: showUndertakeUnit, message: '请选择承办单位' }]" required></van-field>
|
||||
<van-popup v-model="showMasterUnitPicker" position="bottom" round>
|
||||
<div style="padding: 16px">
|
||||
<div class="process-title">{{masterUnitLabel}}</div>
|
||||
<van-checkbox-group v-model="formData.tf_masterUnitIds">
|
||||
<van-cell-group>
|
||||
<van-cell v-for="item in availableMasterUnits" :key="item.id" clickable :title="item.name"
|
||||
@click="toggleMasterUnit(item.id)">
|
||||
<template #right-icon><van-checkbox :name="item.id" @click.stop></van-checkbox></template>
|
||||
</van-cell>
|
||||
</van-cell-group>
|
||||
</van-checkbox-group>
|
||||
<van-button type="primary" block style="margin-top: 12px" @click="closeMasterUnitPicker">确定</van-button>
|
||||
</div>
|
||||
</van-popup>
|
||||
<van-field v-if="formData.tf_caseFilingResult === 'CONFIRM_FILING'" :value="slaveUnitNames" label="协办单位"
|
||||
readonly is-link placeholder="请选择协办单位" @click="openSlaveUnitPicker"></van-field>
|
||||
<van-popup v-model="showSlaveUnitPicker" position="bottom" round>
|
||||
<div style="padding: 16px">
|
||||
<div class="process-title">协办单位</div>
|
||||
<van-checkbox-group v-model="formData.tf_slaveUnitIds">
|
||||
<van-cell-group>
|
||||
<van-cell v-for="item in availableSlaveUnits" :key="item.id" clickable :title="item.name"
|
||||
@click="toggleSlaveUnit(item.id)">
|
||||
<template #right-icon><van-checkbox :name="item.id" @click.stop></van-checkbox></template>
|
||||
</van-cell>
|
||||
</van-cell-group>
|
||||
</van-checkbox-group>
|
||||
<van-button type="primary" block style="margin-top: 12px" @click="closeSlaveUnitPicker">确定</van-button>
|
||||
</div>
|
||||
</van-popup>
|
||||
<van-field v-model="formData.tf_opinion" name="tf_opinion" label="审核意见" placeholder="请输入审核意见"
|
||||
type="textarea" rows="3" maxlength="100" show-word-limit
|
||||
:rules="[{ required: true, message: '请填写审核意见' }]" required></van-field>
|
||||
</van-form>
|
||||
<div style="display: flex; column-gap: 10px; padding: 10px">
|
||||
<van-button type="danger" block @click="handleTaskAction(6)">退回提案人</van-button>
|
||||
<van-button type="primary" block @click="handleTaskAction(1)">提交</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</proposal-info>
|
||||
</div>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
<!--#include("../../common/info.js"){}#-->
|
||||
|
||||
const vue = new Vue({
|
||||
el: "#app",
|
||||
store,
|
||||
dicts: ["PROPOSAL_CASE_FILING_RESULT"],
|
||||
components: {"proposal-info": PROPOSAL_INFO},
|
||||
data() {
|
||||
return {
|
||||
pageForm: {pageNumber: 1, pageSize: 10, totalCount: 0, name: null, sessionId: null, approvalText: "0", approval: false},
|
||||
sessionOptions: [],
|
||||
underTakeOptions: [],
|
||||
formData: {},
|
||||
showApprovalForm: false,
|
||||
showResultPicker: false,
|
||||
showMasterUnitPicker: false,
|
||||
showSlaveUnitPicker: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
caseFilingResultOptions() {
|
||||
return (this.dict.type.PROPOSAL_CASE_FILING_RESULT || []).map(function (item) {
|
||||
return {text: item.label, value: item.code}
|
||||
})
|
||||
},
|
||||
showUndertakeUnit() {
|
||||
return ["CONFIRM_FILING", "SUGGESTION"].includes(this.formData.tf_caseFilingResult)
|
||||
},
|
||||
masterUnitLabel() {
|
||||
return this.formData.tf_caseFilingResult === "SUGGESTION" ? "办理单位" : "主办单位"
|
||||
},
|
||||
masterUnitNames() {
|
||||
return this.getUnitNames(this.formData.tf_masterUnitIds)
|
||||
},
|
||||
slaveUnitNames() {
|
||||
return this.getUnitNames(this.formData.tf_slaveUnitIds)
|
||||
},
|
||||
availableMasterUnits() {
|
||||
return this.underTakeOptions.filter((item) => !this.formData.tf_slaveUnitIds.includes(item.id))
|
||||
},
|
||||
availableSlaveUnits() {
|
||||
return this.underTakeOptions.filter((item) => !this.formData.tf_masterUnitIds.includes(item.id))
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onReady() {
|
||||
this.listSession()
|
||||
this.listUnderTake()
|
||||
},
|
||||
openResultPicker() {
|
||||
this.$set(this, "showResultPicker", true)
|
||||
},
|
||||
closeResultPicker() {
|
||||
this.$set(this, "showResultPicker", false)
|
||||
},
|
||||
openMasterUnitPicker() {
|
||||
this.$set(this, "showMasterUnitPicker", true)
|
||||
},
|
||||
closeMasterUnitPicker() {
|
||||
this.$set(this, "showMasterUnitPicker", false)
|
||||
},
|
||||
openSlaveUnitPicker() {
|
||||
this.$set(this, "showSlaveUnitPicker", true)
|
||||
},
|
||||
closeSlaveUnitPicker() {
|
||||
this.$set(this, "showSlaveUnitPicker", false)
|
||||
},
|
||||
listSession() {
|
||||
this.$axios.post("/platform/proposal/common/listSession").then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$set(this, "sessionOptions", [{text: "全部届次", value: null}].concat(res.data.map(function (item) {
|
||||
return {text: item.fullName, value: item.id}
|
||||
})))
|
||||
this.$set(this.pageForm, "sessionId", this.sessionOptions[0].value)
|
||||
this.doSearch()
|
||||
}
|
||||
})
|
||||
},
|
||||
listUnderTake() {
|
||||
this.$axios.post("/platform/proposal/common/listUnderTake").then((res) => {
|
||||
if (res.code === 0) this.$set(this, "underTakeOptions", res.data)
|
||||
})
|
||||
},
|
||||
changeApproval(value) {
|
||||
this.$set(this.pageForm, "approval", value === "1")
|
||||
this.doSearch()
|
||||
},
|
||||
onView(row) {
|
||||
this.$set(this, "showApprovalForm", false)
|
||||
this.$refs.proposalInfoRef.onOpen(row)
|
||||
},
|
||||
onApproval(row) {
|
||||
this.$set(this, "showApprovalForm", true)
|
||||
this.$set(this, "formData", {
|
||||
processTaskId: row.taskId,
|
||||
proposalId: row.id,
|
||||
taskName: row.taskName,
|
||||
tf_caseFilingResult: "",
|
||||
tf_caseFilingResultName: "",
|
||||
tf_masterUnitIds: [],
|
||||
tf_slaveUnitIds: [],
|
||||
tf_opinion: ""
|
||||
})
|
||||
this.$refs.proposalInfoRef.onOpen(row)
|
||||
},
|
||||
onResultConfirm(value) {
|
||||
this.$set(this.formData, "tf_caseFilingResult", value.value)
|
||||
this.$set(this.formData, "tf_caseFilingResultName", value.text)
|
||||
if (value.value === "SUGGESTION") this.$set(this.formData, "tf_slaveUnitIds", [])
|
||||
if (value.value !== "CONFIRM_FILING" && value.value !== "SUGGESTION") {
|
||||
this.$set(this.formData, "tf_masterUnitIds", [])
|
||||
this.$set(this.formData, "tf_slaveUnitIds", [])
|
||||
}
|
||||
this.$set(this, "showResultPicker", false)
|
||||
},
|
||||
toggleMasterUnit(unitId) {
|
||||
this.toggleUnit(this.formData.tf_masterUnitIds, unitId, "tf_masterUnitIds")
|
||||
},
|
||||
toggleSlaveUnit(unitId) {
|
||||
this.toggleUnit(this.formData.tf_slaveUnitIds, unitId, "tf_slaveUnitIds")
|
||||
},
|
||||
toggleUnit(unitIds, unitId, fieldName) {
|
||||
const nextUnitIds = unitIds.slice()
|
||||
const index = nextUnitIds.indexOf(unitId)
|
||||
if (index === -1) nextUnitIds.push(unitId)
|
||||
else nextUnitIds.splice(index, 1)
|
||||
this.$set(this.formData, fieldName, nextUnitIds)
|
||||
},
|
||||
getUnitNames(unitIds) {
|
||||
return this.underTakeOptions.filter(function (item) {
|
||||
return unitIds.includes(item.id)
|
||||
}).map(function (item) {
|
||||
return item.name
|
||||
}).join("、")
|
||||
},
|
||||
buildSubmitData(submitType) {
|
||||
const masterUnitIds = this.formData.tf_masterUnitIds || []
|
||||
const slaveUnitIds = this.formData.tf_caseFilingResult === "CONFIRM_FILING" ? (this.formData.tf_slaveUnitIds || []) : []
|
||||
return Object.assign({}, this.formData, {
|
||||
tf_masterUnitIds: masterUnitIds,
|
||||
tf_slaveUnitIds: slaveUnitIds,
|
||||
tf_masterUnitId: masterUnitIds.length ? masterUnitIds[0] : "",
|
||||
tf_masterUnitName: masterUnitIds.length ? this.getUnitName(masterUnitIds[0]) : "",
|
||||
tf_masterUnitNames: masterUnitIds.map((unitId) => this.getUnitName(unitId)),
|
||||
tf_masterUnitNameStr: this.getUnitNames(masterUnitIds),
|
||||
tf_slaveUnitNames: slaveUnitIds.map((unitId) => this.getUnitName(unitId)),
|
||||
tf_slaveUnitNameStr: this.getUnitNames(slaveUnitIds),
|
||||
tf_helpunitreply: slaveUnitIds.length ? "HAS_HELP_UNIT" : "NO_HELP_UNIT",
|
||||
submitType: submitType
|
||||
})
|
||||
},
|
||||
getUnitName(unitId) {
|
||||
const unit = this.underTakeOptions.find(function (item) { return item.id === unitId })
|
||||
return unit ? unit.name : ""
|
||||
},
|
||||
async handleTaskAction(submitType) {
|
||||
try {
|
||||
await this.$refs.formRef.validate()
|
||||
this.$dialog.confirm({title: "提示", message: "您确定要提交吗?"}).then(() => {
|
||||
this.$axios.post("/flow/common/executeTask", {data: JSON.stringify(this.buildSubmitData(submitType))}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$refs.proposalInfoRef.onClose()
|
||||
this.$toast.success(res.msg)
|
||||
this.doSearch()
|
||||
}
|
||||
})
|
||||
}).catch(function () {})
|
||||
} catch (error) {}
|
||||
},
|
||||
doSearch() {
|
||||
this.$nextTick(() => {
|
||||
this.$set(this.pageForm, "pageNumber", 1)
|
||||
this.$set(this.pageForm, "totalCount", 0)
|
||||
this.$refs.tableListRef.doSearch()
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
+322
@@ -0,0 +1,322 @@
|
||||
<!--#
|
||||
layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
<div id="app" v-cloak>
|
||||
<van-nav-bar @click-left="historyBack" left-arrow left-text="返回" title="委员会确认承办单位" placeholder fixed></van-nav-bar>
|
||||
<van-sticky offset-top="46px">
|
||||
<van-search v-model="pageForm.name" :show-action="false" :reverse-color="false" input-align="left"
|
||||
placeholder="请输入提案名称搜索" @search="doSearch"></van-search>
|
||||
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||
<van-dropdown-item v-model="pageForm.sessionId" :options="sessionOptions" :multiple="false"
|
||||
@change="doSearch"></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
<van-tabs v-model="pageForm.approvalText" @change="changeApproval">
|
||||
<van-tab title="已审核" name="1"></van-tab>
|
||||
<van-tab title="未审核" name="0"></van-tab>
|
||||
</van-tabs>
|
||||
</van-sticky>
|
||||
|
||||
<table-list api="/platform/proposal/committeeFilingUnit/h5/pageData" :page_form.sync="pageForm" @ready="onReady"
|
||||
ref="tableListRef" title="name">
|
||||
<template v-slot="{index,row}">
|
||||
<table-column label="提案编号">{{row.code}}</table-column>
|
||||
<table-column label="提案类别">{{row.typeName}}</table-column>
|
||||
<table-column label="提案人">{{row.createUserName}}</table-column>
|
||||
<table-column label="代表团">{{row.delegationName}}</table-column>
|
||||
<table-column label="当前节点">{{row.curTaskName}}</table-column>
|
||||
</template>
|
||||
<template #actions="{index,row}">
|
||||
<div class="action-btn" @click="onView(row)">
|
||||
<i class="fa fa-eye"></i><span>查看</span>
|
||||
</div>
|
||||
<div class="action-btn" v-if="row.taskState === 10" @click="onApproval(row)">
|
||||
<i class="fa fa-edit"></i><span>确认</span>
|
||||
</div>
|
||||
</template>
|
||||
</table-list>
|
||||
|
||||
<proposal-info ref="proposalInfoRef">
|
||||
<div v-if="showApprovalForm">
|
||||
<div class="process-title">{{formData.taskName}}</div>
|
||||
<van-form ref="formRef">
|
||||
<van-field v-model="formData.tf_caseFilingResultName" name="tf_caseFilingResultName" label="立案结果"
|
||||
placeholder="请选择立案结果" readonly is-link @click="openResultPicker"
|
||||
:rules="[{ required: true, message: '请选择立案结果' }]" required></van-field>
|
||||
<van-popup v-model="showResultPicker" position="bottom">
|
||||
<van-picker show-toolbar :columns="caseFilingResultOptions" @confirm="onResultConfirm"
|
||||
@cancel="closeResultPicker"></van-picker>
|
||||
</van-popup>
|
||||
<van-field v-if="formData.tf_caseFilingResult === 'CONFIRM_FILING'" v-model="formData.tf_caseFilingCode"
|
||||
name="tf_caseFilingCode" label="立案编号" placeholder="请输入立案编号" maxlength="20" show-word-limit
|
||||
:rules="[{ required: true, message: '请填写立案编号' }]" required></van-field>
|
||||
<van-field v-if="showUndertakeUnit" :value="masterUnitNames" :label="masterUnitLabel" readonly is-link
|
||||
:placeholder="masterUnitLabel === '办理单位' ? '请选择办理单位' : '请选择主办单位'"
|
||||
@click="openMasterUnitPicker"
|
||||
:rules="[{ required: showUndertakeUnit, message: '请选择承办单位' }]" required></van-field>
|
||||
<van-popup v-model="showMasterUnitPicker" position="bottom" round>
|
||||
<div style="padding: 16px">
|
||||
<div class="process-title">{{masterUnitLabel}}</div>
|
||||
<van-checkbox-group v-model="formData.tf_masterUnitIds">
|
||||
<van-cell-group>
|
||||
<van-cell v-for="item in availableMasterUnits" :key="item.id" clickable :title="item.name"
|
||||
@click="toggleMasterUnit(item.id)">
|
||||
<template #right-icon><van-checkbox :name="item.id" @click.stop></van-checkbox></template>
|
||||
</van-cell>
|
||||
</van-cell-group>
|
||||
</van-checkbox-group>
|
||||
<van-button type="primary" block style="margin-top: 12px" @click="closeMasterUnitPicker">确定</van-button>
|
||||
</div>
|
||||
</van-popup>
|
||||
<van-field v-if="formData.tf_caseFilingResult === 'CONFIRM_FILING'" :value="slaveUnitNames" label="协办单位"
|
||||
readonly is-link placeholder="请选择协办单位" @click="openSlaveUnitPicker"></van-field>
|
||||
<van-popup v-model="showSlaveUnitPicker" position="bottom" round>
|
||||
<div style="padding: 16px">
|
||||
<div class="process-title">协办单位</div>
|
||||
<van-checkbox-group v-model="formData.tf_slaveUnitIds">
|
||||
<van-cell-group>
|
||||
<van-cell v-for="item in availableSlaveUnits" :key="item.id" clickable :title="item.name"
|
||||
@click="toggleSlaveUnit(item.id)">
|
||||
<template #right-icon><van-checkbox :name="item.id" @click.stop></van-checkbox></template>
|
||||
</van-cell>
|
||||
</van-cell-group>
|
||||
</van-checkbox-group>
|
||||
<van-button type="primary" block style="margin-top: 12px" @click="closeSlaveUnitPicker">确定</van-button>
|
||||
</div>
|
||||
</van-popup>
|
||||
<van-field v-model="formData.tf_opinion" name="tf_opinion" label="审核意见" placeholder="请输入审核意见"
|
||||
type="textarea" rows="3" maxlength="100" show-word-limit
|
||||
:rules="[{ required: true, message: '请填写审核意见' }]" required></van-field>
|
||||
</van-form>
|
||||
<div style="display: flex; column-gap: 10px; padding: 10px">
|
||||
<van-button block @click="closeApproval">取消</van-button>
|
||||
<van-button type="primary" block @click="handleTaskAction(1)">提交</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</proposal-info>
|
||||
</div>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
<!--#include("../../common/info.js"){}#-->
|
||||
|
||||
const vue = new Vue({
|
||||
el: "#app",
|
||||
store,
|
||||
dicts: ["PROPOSAL_CASE_FILING_RESULT"],
|
||||
components: {"proposal-info": PROPOSAL_INFO},
|
||||
data() {
|
||||
return {
|
||||
pageForm: {pageNumber: 1, pageSize: 10, totalCount: 0, name: null, sessionId: null, approvalText: "0", approval: false},
|
||||
sessionOptions: [],
|
||||
underTakeOptions: [],
|
||||
formData: {},
|
||||
showApprovalForm: false,
|
||||
showResultPicker: false,
|
||||
showMasterUnitPicker: false,
|
||||
showSlaveUnitPicker: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
caseFilingResultOptions() {
|
||||
return (this.dict.type.PROPOSAL_CASE_FILING_RESULT || []).map(function (item) {
|
||||
return {text: item.label, value: item.code}
|
||||
})
|
||||
},
|
||||
showUndertakeUnit() {
|
||||
return ["CONFIRM_FILING", "SUGGESTION"].includes(this.formData.tf_caseFilingResult)
|
||||
},
|
||||
masterUnitLabel() {
|
||||
return this.formData.tf_caseFilingResult === "SUGGESTION" ? "办理单位" : "主办单位"
|
||||
},
|
||||
masterUnitNames() {
|
||||
return this.getUnitNames(this.formData.tf_masterUnitIds)
|
||||
},
|
||||
slaveUnitNames() {
|
||||
return this.getUnitNames(this.formData.tf_slaveUnitIds)
|
||||
},
|
||||
availableMasterUnits() {
|
||||
return this.underTakeOptions.filter((item) => !this.formData.tf_slaveUnitIds.includes(item.id))
|
||||
},
|
||||
availableSlaveUnits() {
|
||||
return this.underTakeOptions.filter((item) => !this.formData.tf_masterUnitIds.includes(item.id))
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onReady() {
|
||||
this.listSession()
|
||||
this.listUnderTake()
|
||||
},
|
||||
openResultPicker() {
|
||||
this.$set(this, "showResultPicker", true)
|
||||
},
|
||||
closeResultPicker() {
|
||||
this.$set(this, "showResultPicker", false)
|
||||
},
|
||||
openMasterUnitPicker() {
|
||||
this.$set(this, "showMasterUnitPicker", true)
|
||||
},
|
||||
closeMasterUnitPicker() {
|
||||
this.$set(this, "showMasterUnitPicker", false)
|
||||
},
|
||||
openSlaveUnitPicker() {
|
||||
this.$set(this, "showSlaveUnitPicker", true)
|
||||
},
|
||||
closeSlaveUnitPicker() {
|
||||
this.$set(this, "showSlaveUnitPicker", false)
|
||||
},
|
||||
listSession() {
|
||||
this.$axios.post("/platform/proposal/common/listSession").then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$set(this, "sessionOptions", [{text: "全部届次", value: null}].concat(res.data.map(function (item) {
|
||||
return {text: item.fullName, value: item.id}
|
||||
})))
|
||||
this.$set(this.pageForm, "sessionId", this.sessionOptions[0].value)
|
||||
this.doSearch()
|
||||
}
|
||||
})
|
||||
},
|
||||
listUnderTake() {
|
||||
this.$axios.post("/platform/proposal/common/listUnderTake").then((res) => {
|
||||
if (res.code === 0) this.$set(this, "underTakeOptions", res.data)
|
||||
})
|
||||
},
|
||||
changeApproval(value) {
|
||||
this.$set(this.pageForm, "approval", value === "1")
|
||||
this.doSearch()
|
||||
},
|
||||
onView(row) {
|
||||
this.$set(this, "showApprovalForm", false)
|
||||
this.$refs.proposalInfoRef.onOpen(row)
|
||||
},
|
||||
onApproval(row) {
|
||||
this.$set(this, "showApprovalForm", true)
|
||||
this.$set(this, "formData", {
|
||||
processTaskId: row.taskId,
|
||||
proposalId: row.id,
|
||||
taskName: row.taskName,
|
||||
tf_caseFilingResult: "",
|
||||
tf_caseFilingResultName: "",
|
||||
tf_caseFilingCode: "",
|
||||
tf_masterUnitIds: [],
|
||||
tf_slaveUnitIds: [],
|
||||
tf_opinion: ""
|
||||
})
|
||||
this.loadCommitteeFilingData(row.id)
|
||||
this.$refs.proposalInfoRef.onOpen(row)
|
||||
},
|
||||
/**
|
||||
* 确认承办单位必须延续上一“提案委员会立案”的结果和单位,
|
||||
* 先读取已办记录回显,仍允许审核人按 PC 页面规则调整后再提交。
|
||||
*/
|
||||
loadCommitteeFilingData(proposalId) {
|
||||
this.$axios.post("/flow/common/doneTasks", {bizId: proposalId}).then((res) => {
|
||||
if (res.code !== 0) return
|
||||
const committeeTasks = res.data.filter(function (task) { return task.taskName === "committee" })
|
||||
const committeeTask = committeeTasks.length ? committeeTasks[committeeTasks.length - 1] : null
|
||||
if (!committeeTask || !committeeTask.ext) return
|
||||
const ext = committeeTask.ext
|
||||
this.$set(this.formData, "tf_caseFilingResult", ext.tf_caseFilingResult || "")
|
||||
this.$set(this.formData, "tf_caseFilingResultName", this.getCaseFilingResultName(ext.tf_caseFilingResult))
|
||||
this.$set(this.formData, "tf_caseFilingCode", ext.tf_caseFilingCode || "")
|
||||
this.$set(this.formData, "tf_masterUnitIds", this.normalizeUnitIds(ext.tf_masterUnitIds))
|
||||
this.$set(this.formData, "tf_slaveUnitIds", this.normalizeUnitIds(ext.tf_slaveUnitIds))
|
||||
})
|
||||
},
|
||||
getCaseFilingResultName(code) {
|
||||
const result = (this.dict.type.PROPOSAL_CASE_FILING_RESULT || []).find(function (item) { return item.code === code })
|
||||
return result ? result.label : ""
|
||||
},
|
||||
normalizeUnitIds(unitIds) {
|
||||
if (Array.isArray(unitIds)) return unitIds
|
||||
if (!unitIds) return []
|
||||
if (typeof unitIds === "string") {
|
||||
try {
|
||||
const parsedValue = JSON.parse(unitIds)
|
||||
if (Array.isArray(parsedValue)) return parsedValue
|
||||
} catch (error) {}
|
||||
return unitIds.split(",").filter(function (item) { return item && item.trim() }).map(function (item) { return item.trim() })
|
||||
}
|
||||
return []
|
||||
},
|
||||
onResultConfirm(value) {
|
||||
this.$set(this.formData, "tf_caseFilingResult", value.value)
|
||||
this.$set(this.formData, "tf_caseFilingResultName", value.text)
|
||||
if (value.value === "SUGGESTION") this.$set(this.formData, "tf_slaveUnitIds", [])
|
||||
if (value.value !== "CONFIRM_FILING" && value.value !== "SUGGESTION") {
|
||||
this.$set(this.formData, "tf_caseFilingCode", "")
|
||||
this.$set(this.formData, "tf_masterUnitIds", [])
|
||||
this.$set(this.formData, "tf_slaveUnitIds", [])
|
||||
}
|
||||
this.$set(this, "showResultPicker", false)
|
||||
},
|
||||
toggleMasterUnit(unitId) {
|
||||
this.toggleUnit(this.formData.tf_masterUnitIds, unitId, "tf_masterUnitIds")
|
||||
},
|
||||
toggleSlaveUnit(unitId) {
|
||||
this.toggleUnit(this.formData.tf_slaveUnitIds, unitId, "tf_slaveUnitIds")
|
||||
},
|
||||
toggleUnit(unitIds, unitId, fieldName) {
|
||||
const nextUnitIds = unitIds.slice()
|
||||
const index = nextUnitIds.indexOf(unitId)
|
||||
if (index === -1) nextUnitIds.push(unitId)
|
||||
else nextUnitIds.splice(index, 1)
|
||||
this.$set(this.formData, fieldName, nextUnitIds)
|
||||
},
|
||||
getUnitNames(unitIds) {
|
||||
return this.underTakeOptions.filter(function (item) {
|
||||
return unitIds.includes(item.id)
|
||||
}).map(function (item) {
|
||||
return item.name
|
||||
}).join("、")
|
||||
},
|
||||
getUnitName(unitId) {
|
||||
const unit = this.underTakeOptions.find(function (item) { return item.id === unitId })
|
||||
return unit ? unit.name : ""
|
||||
},
|
||||
buildSubmitData() {
|
||||
const masterUnitIds = this.formData.tf_masterUnitIds || []
|
||||
const slaveUnitIds = this.formData.tf_caseFilingResult === "CONFIRM_FILING" ? (this.formData.tf_slaveUnitIds || []) : []
|
||||
return Object.assign({}, this.formData, {
|
||||
tf_masterUnitIds: masterUnitIds,
|
||||
tf_slaveUnitIds: slaveUnitIds,
|
||||
tf_masterUnitId: masterUnitIds.length ? masterUnitIds[0] : "",
|
||||
tf_masterUnitName: masterUnitIds.length ? this.getUnitName(masterUnitIds[0]) : "",
|
||||
tf_masterUnitNames: masterUnitIds.map((unitId) => this.getUnitName(unitId)),
|
||||
tf_masterUnitNameStr: this.getUnitNames(masterUnitIds),
|
||||
tf_slaveUnitNames: slaveUnitIds.map((unitId) => this.getUnitName(unitId)),
|
||||
tf_slaveUnitNameStr: this.getUnitNames(slaveUnitIds),
|
||||
tf_helpunitreply: slaveUnitIds.length ? "HAS_HELP_UNIT" : "NO_HELP_UNIT",
|
||||
submitType: 1
|
||||
})
|
||||
},
|
||||
async handleTaskAction() {
|
||||
try {
|
||||
await this.$refs.formRef.validate()
|
||||
this.$dialog.confirm({title: "提示", message: "您确定要提交吗?"}).then(() => {
|
||||
this.$axios.post("/platform/proposal/committeeFilingUnit/h5/executeTask", {
|
||||
data: JSON.stringify(this.buildSubmitData())
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$refs.proposalInfoRef.onClose()
|
||||
this.$toast.success(res.msg)
|
||||
this.doSearch()
|
||||
}
|
||||
})
|
||||
}).catch(function () {})
|
||||
} catch (error) {}
|
||||
},
|
||||
closeApproval() {
|
||||
this.$refs.proposalInfoRef.onClose()
|
||||
},
|
||||
doSearch() {
|
||||
this.$nextTick(() => {
|
||||
this.$set(this.pageForm, "pageNumber", 1)
|
||||
this.$set(this.pageForm, "totalCount", 0)
|
||||
this.$refs.tableListRef.doSearch()
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
+30
-2
@@ -2,7 +2,7 @@
|
||||
layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
<div id="app" v-cloak>
|
||||
<van-nav-bar @click-left="historyBack" left-arrow left-text="返回" title="团长审核" placeholder fixed></van-nav-bar>
|
||||
<van-nav-bar @click-left="historyBack" left-arrow left-text="返回" :title="pageTitle" placeholder fixed></van-nav-bar>
|
||||
<van-sticky offset-top="46px">
|
||||
<van-search
|
||||
v-model="pageForm.name"
|
||||
@@ -23,7 +23,7 @@ layout("/layouts/platform_h5.html"){
|
||||
</van-tabs>
|
||||
</van-sticky>
|
||||
|
||||
<table-list api="/platform/proposal/delegation/pageData" :page_form.sync="pageForm" @ready="onReady"
|
||||
<table-list :api="pageDataUrl" :page_form.sync="pageForm" @ready="onReady"
|
||||
ref="tableListRef"
|
||||
title="name">
|
||||
<template v-slot="{index,row}">
|
||||
@@ -76,6 +76,32 @@ layout("/layouts/platform_h5.html"){
|
||||
<script nonce="${cspNonce!}">
|
||||
<!--#include("../../common/info.js"){}#-->
|
||||
|
||||
/**
|
||||
* 同一审核页面模板按当前访问地址选择标题和手机端数据接口,
|
||||
* 使 PC、H5 的权限接口保持分离。
|
||||
*/
|
||||
function getH5AuditPageConfig() {
|
||||
const pathname = window.location.pathname
|
||||
if (pathname.indexOf("/secondaryUnionAudit/") !== -1) {
|
||||
return {
|
||||
title: "二级工会审核",
|
||||
pageDataUrl: "/platform/proposal/secondaryUnionAudit/h5/pageData"
|
||||
}
|
||||
}
|
||||
if (pathname.indexOf("/partyOrganizationAudit/") !== -1) {
|
||||
return {
|
||||
title: "院级党组织审核",
|
||||
pageDataUrl: "/platform/proposal/partyOrganizationAudit/h5/pageData"
|
||||
}
|
||||
}
|
||||
return {
|
||||
title: "团长审核",
|
||||
pageDataUrl: "/platform/proposal/delegation/pageData"
|
||||
}
|
||||
}
|
||||
|
||||
const auditPageConfig = getH5AuditPageConfig()
|
||||
|
||||
const vue = new Vue({
|
||||
el: "#app",
|
||||
store,
|
||||
@@ -91,6 +117,8 @@ layout("/layouts/platform_h5.html"){
|
||||
approval: false
|
||||
},
|
||||
|
||||
pageTitle: auditPageConfig.title,
|
||||
pageDataUrl: auditPageConfig.pageDataUrl,
|
||||
sessionOptions: [],
|
||||
formData: {},
|
||||
showApprovalForm: false
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
<!--#
|
||||
layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
<div id="app" v-cloak>
|
||||
<van-nav-bar @click-left="back" left-arrow left-text="返回" placeholder title="幸福工荟详情"></van-nav-bar>
|
||||
<van-image :src="previewUrl(detail.cover)" fit="cover" height="220" v-if="detail.cover" width="100%"></van-image>
|
||||
<van-cell-group>
|
||||
<van-cell :title="detail.title"></van-cell>
|
||||
<van-cell :value="detail.tagTypeName || '幸福工荟'" title="标签"></van-cell>
|
||||
<van-cell :value="formatDate(detail.publishTime || detail.createdAt)" title="发布时间"></van-cell>
|
||||
<van-cell :label="detail.summary" title="摘要"></van-cell>
|
||||
</van-cell-group>
|
||||
<div class="inclusive-content" v-html="detail.content"></div>
|
||||
<div class="inclusive-footer" v-if="hasLink"><van-button @click="openLink" block type="primary">查看活动页面</van-button></div>
|
||||
</div>
|
||||
<style>
|
||||
.inclusive-content { padding: 16px; line-height: 1.8; word-break: break-word; }
|
||||
.inclusive-content img { height: auto; max-width: 100%; }
|
||||
.inclusive-footer { padding: 12px; }
|
||||
</style>
|
||||
<script nonce="${cspNonce!}">
|
||||
new Vue({
|
||||
el: "#app",
|
||||
data: function () { return {id: "", detail: {}} },
|
||||
computed: { hasLink: function () { return !!(this.detail.linkUrl && this.detail.linkUrl.trim()) } },
|
||||
methods: {
|
||||
back: function () { history.back() },
|
||||
previewUrl: function (cover) { return cover || "" },
|
||||
formatDate: function (value) { return value ? moment(value).format("YYYY-MM-DD") : "" },
|
||||
findOne: function () { var self = this; $.post("/platform/h5/inclusive/findOne", {id: this.id}).then(function (res) { if (res.code === 0 && res.data) { self.$set(self, "detail", res.data) } else { self.$toast(res.msg || "未查询到活动详情") } }) },
|
||||
openLink: function () { if (this.hasLink) { window.location.href = this.detail.linkUrl.trim() } }
|
||||
},
|
||||
created: function () { this.$set(this, "id", GetQueryString("id")); this.findOne() }
|
||||
})
|
||||
</script>
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
@@ -0,0 +1,91 @@
|
||||
<!--#
|
||||
layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
<style>
|
||||
#app { background: #f6f7f9; min-height: 100vh; }
|
||||
.inclusive-tab-wrap { padding: 10px 12px 8px; background: #fff; box-shadow: 0 2px 8px rgba(8, 23, 118, .08); }
|
||||
.inclusive-tabs { background: transparent; border-radius: 0; padding: 0; box-shadow: none; }
|
||||
.inclusive-tabs .van-tabs__wrap { height: 32px; overflow: hidden; }
|
||||
.inclusive-tabs .van-tabs__nav { display: flex; overflow-x: auto; overflow-y: hidden; flex-wrap: nowrap; -webkit-overflow-scrolling: touch; padding-right: 10px; background: transparent; }
|
||||
.inclusive-tabs .van-tabs__nav::-webkit-scrollbar { display: none; }
|
||||
.inclusive-tabs .van-tab { flex: 0 0 auto; padding: 0 5px; }
|
||||
.inclusive-tabs .van-tab__text { padding: 7px 12px; border-radius: 9px; background: #f2f5f8; color: #303846; font-size: 12px; line-height: 18px; white-space: nowrap; font-weight: 600; }
|
||||
.inclusive-tabs .van-tab--active .van-tab__text { color: #fff; background: #081776; }
|
||||
.inclusive-tabs .van-tabs__line { display: none; }
|
||||
.inclusive-list { padding: 12px 12px 22px; }
|
||||
.inclusive-card { overflow: hidden; margin-bottom: 14px; background: #fff; border-radius: 12px; box-shadow: 0 3px 10px rgba(31, 45, 61, .14); }
|
||||
.inclusive-cover { width: 100%; height: 150px; overflow: hidden; background: #e8eef6; }
|
||||
.inclusive-cover img { width: 100%; height: 100%; display: block; }
|
||||
.inclusive-card-main { display: flex; flex-direction: column; min-width: 0; min-height: 132px; position: relative; padding: 12px 42px 14px 14px; }
|
||||
.inclusive-tag { display: inline-block; max-width: 120px; padding: 3px 9px; border-radius: 5px; color: #0b63d8; background: #eaf3ff; font-size: 12px; line-height: 18px; }
|
||||
.inclusive-title { margin-top: 8px; color: #111827; font-size: 16px; line-height: 24px; font-weight: bold; min-height: 24px; }
|
||||
.inclusive-summary { margin-top: 5px; color: #53657f; font-size: 13px; line-height: 19px; min-height: 38px; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
|
||||
.inclusive-date { margin-top: auto; color: #6b7c96; font-size: 12px; display: flex; align-items: center; gap: 4px; }
|
||||
.inclusive-arrow { color: #8a96a8; position: absolute; right: 14px; bottom: 16px; font-size: 22px; }
|
||||
.inclusive-empty { min-height: 320px; display: flex; align-items: center; justify-content: center; flex-direction: column; color: #909399; font-size: 14px; background: transparent; }
|
||||
.inclusive-empty-icon { width: 120px; height: 120px; margin-bottom: 10px; opacity: .56; }
|
||||
</style>
|
||||
<div id="app" v-cloak>
|
||||
<van-nav-bar @click-left="back" fixed left-arrow left-text="返回" placeholder title="幸福工荟"></van-nav-bar>
|
||||
<van-sticky :offset-top="46">
|
||||
<div class="inclusive-tab-wrap">
|
||||
<van-tabs @change="tagChange" class="inclusive-tabs" v-model="activeTag">
|
||||
<van-tab name="" title="全部"></van-tab>
|
||||
<van-tab :key="item.value" :name="item.value" :title="item.text" v-for="item in tagOptions"></van-tab>
|
||||
</van-tabs>
|
||||
</div>
|
||||
</van-sticky>
|
||||
<div class="inclusive-list">
|
||||
<van-pull-refresh @refresh="onRefresh" v-model="refreshing">
|
||||
<van-list :finished="finished" :finished-text="tableData.length ? '没有更多了' : ''" @load="pageData" v-model="loading">
|
||||
<div :key="item.id" @click="openDetail(item)" class="inclusive-card" v-for="item in tableData">
|
||||
<div class="inclusive-cover"><img :src="previewUrl(item.cover)" v-if="item.cover"></div>
|
||||
<div class="inclusive-card-main">
|
||||
<div class="inclusive-tag van-ellipsis">{{item.tagTypeName || '幸福工荟'}}</div>
|
||||
<div class="inclusive-title van-multi-ellipsis--l2">{{item.title}}</div>
|
||||
<div class="inclusive-summary">{{item.summary}}</div>
|
||||
<div class="inclusive-date"><van-icon name="underway-o"></van-icon><span>{{formatDate(item.publishTime || item.createdAt)}}</span></div>
|
||||
<van-icon class="inclusive-arrow" name="arrow"></van-icon>
|
||||
</div>
|
||||
</div>
|
||||
</van-list>
|
||||
</van-pull-refresh>
|
||||
<div class="inclusive-empty" v-if="!loading && tableData.length === 0">
|
||||
<img class="inclusive-empty-icon" src="https://img01.yzcdn.cn/vant/empty-image-default.png">
|
||||
<div>暂无数据</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script nonce="${cspNonce!}">
|
||||
new Vue({
|
||||
el: "#app",
|
||||
data: function () { return {activeTag: "", tagOptions: [], tableData: [], loading: false, refreshing: false, finished: false, pageForm: {pageNumber: 1, pageSize: 6, totalCount: 0, tagType: ""}} },
|
||||
methods: {
|
||||
previewUrl: function (cover) { return cover || "" },
|
||||
formatDate: function (value) { return value ? moment(value).format("YYYY-MM-DD") : "" },
|
||||
back: function () { history.back() },
|
||||
getTagOptions: function () { var self = this; $.post("/platform/h5/inclusive/tagOptions", {}).then(function (res) { if (res.code === 0) { self.$set(self, "tagOptions", res.data || []) } }) },
|
||||
pageData: function () {
|
||||
var self = this;
|
||||
this.$set(this, "loading", true);
|
||||
this.$set(this.pageForm, "tagType", this.activeTag);
|
||||
$.post("/platform/h5/inclusive/pageData", this.pageForm).then(function (res) {
|
||||
if (self.refreshing) { self.$set(self, "tableData", []); self.$set(self, "refreshing", false) }
|
||||
if (res.code === 0) {
|
||||
var data = res.data || {}; var list = data.list || [];
|
||||
self.$set(self, "tableData", self.tableData.concat(list)); self.$set(self.pageForm, "totalCount", data.totalCount || 0);
|
||||
if (self.tableData.length >= self.pageForm.totalCount) { self.$set(self, "finished", true) } else { self.$set(self.pageForm, "pageNumber", self.pageForm.pageNumber + 1) }
|
||||
} else { self.$toast(res.msg || "查询失败") }
|
||||
}).always(function () { self.$set(self, "loading", false) })
|
||||
},
|
||||
resetList: function () { this.$set(this, "tableData", []); this.$set(this, "finished", false); this.$set(this.pageForm, "pageNumber", 1); this.$set(this.pageForm, "totalCount", 0) },
|
||||
tagChange: function (value) { this.$set(this, "activeTag", value); this.resetList(); this.pageData() },
|
||||
onRefresh: function () { this.resetList(); this.$set(this, "refreshing", true); this.pageData() },
|
||||
openDetail: function (item) { window.location.href = "/platform/h5/inclusive/detail?id=" + item.id }
|
||||
},
|
||||
created: function () { this.getTagOptions() }
|
||||
})
|
||||
</script>
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
+2
-2
@@ -92,7 +92,7 @@ layout("/layouts/platform_h5.html"){
|
||||
<div style="padding: 10px;">
|
||||
<van-checkbox v-model="formData.isRead" shape="square" @change="isReadChange">
|
||||
<div style="color:#246FB4;" @click.stop="isReadClick">
|
||||
中国地质大学(武汉)教职工重大疾病互助基金管理办法
|
||||
西南财经大学教职工重大疾病互助基金管理办法
|
||||
</div>
|
||||
</van-checkbox>
|
||||
</div>
|
||||
@@ -203,7 +203,7 @@ layout("/layouts/platform_h5.html"){
|
||||
this.$commonUtil.previewFile({
|
||||
suffix: "pdf",
|
||||
downloadPath: "/platform/sys/file/download?id=orpgde84uggjmpflbob83tadan",
|
||||
name: "中国地质大学(武汉)教职工重大疾病互助基金管理办法.pdf",
|
||||
name: "西南财经大学教职工重大疾病互助基金管理办法.pdf",
|
||||
id: "orpgde84uggjmpflbob83tadan"
|
||||
})
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user