feat: 品牌工作室迁移完成

This commit is contained in:
2026-08-19 18:04:39 +08:00
parent d38d48a147
commit 19bbd61436
15 changed files with 1512 additions and 283 deletions
@@ -18,6 +18,7 @@ import org.nutz.mvc.annotation.Param;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;
@IocBean
@@ -34,6 +35,11 @@ public class BrandStudioApplicationController {
return Result.success(leaderHonorVO);
}
@At("/members")
public Result listMemberCandidates(String unionId, String keyword) {
return Result.success(applicationService.listMemberCandidates(unionId, keyword));
}
@At("/page")
public Result page(@Valid BrandStudioApplicationPageDTO dto) {
return Result.success(applicationService.page(dto));
@@ -45,7 +51,7 @@ public class BrandStudioApplicationController {
return Result.success(applicationVO);
}
@At
@At("")
public Result save(@Param("..") @Valid BrandStudioApplicationCreateDTO dto) {
applicationService.save(dto);
return Result.success();
@@ -59,7 +65,23 @@ public class BrandStudioApplicationController {
@At("/delete")
public Result delete(@Param("..") NutMap request) {
applicationService.delete((List<String>) request.get("data"));
List<String> ids = new ArrayList<>();
Object data = request.get("data");
if (data instanceof List<?>) {
((List<?>) data).forEach(item -> ids.add(String.valueOf(item)));
} else if (data != null) {
ids.add(String.valueOf(data));
}
Object id = request.get("id");
if (id != null) {
ids.add(String.valueOf(id));
}
request.forEach((key, value) -> {
if (key != null && String.valueOf(key).startsWith("data[") && value != null) {
ids.add(String.valueOf(value));
}
});
applicationService.delete(ids);
return Result.success();
}
@@ -50,6 +50,11 @@ public class BrandApplicationAuditDTO {
*/
private String bpmTaskApprovalType;
/**
* 流程提交类型
*/
private Integer submitType;
/**
* 下一个任务接收人
*/
@@ -1,6 +1,8 @@
package com.budwk.app.zhgh.brand.domain.dto;
import lombok.Data;
import org.nutz.json.Json;
import org.nutz.lang.Strings;
import javax.validation.Valid;
import javax.validation.constraints.*;
@@ -137,4 +139,16 @@ public class BrandStudioApplicationCreateDTO {
@NotEmpty(message = "至少需要1位成员")
@Valid
private List<BrandStudioMemberCreateDTO> brandStudioMembers;
/**
* 工作室成员列表 JSON
*/
private String brandStudioMembersJson;
public void setBrandStudioMembersJson(String brandStudioMembersJson) {
this.brandStudioMembersJson = brandStudioMembersJson;
if (Strings.isNotBlank(brandStudioMembersJson)) {
this.brandStudioMembers = Json.fromJsonAsList(BrandStudioMemberCreateDTO.class, brandStudioMembersJson);
}
}
}
@@ -134,6 +134,11 @@ public class BrandStudioApplicationPageDTO extends PageForm {
*/
private Integer processStatus;
/**
* 是否已审核
*/
private Boolean audit = false;
@Override
public Integer getPageNumber() {
Integer pageNumber = super.getPageNumber();
@@ -1,6 +1,8 @@
package com.budwk.app.zhgh.brand.domain.dto;
import lombok.Data;
import org.nutz.json.Json;
import org.nutz.lang.Strings;
import java.util.List;
@@ -67,6 +69,11 @@ public class BrandStudioApplicationUpdateDTO {
*/
private Integer status;
/**
* 发起任务ID
*/
private String startTaskId;
/**
* 归档
*/
@@ -107,6 +114,30 @@ public class BrandStudioApplicationUpdateDTO {
* */
private List<BrandStudioMemberCreateDTO> brandStudioMembers;
/**
* 添加的成员 JSON
*/
private String brandStudioMembersJson;
public void setBrandStudioMembersJson(String brandStudioMembersJson) {
this.brandStudioMembersJson = brandStudioMembersJson;
if (Strings.isNotBlank(brandStudioMembersJson)) {
this.brandStudioMembers = Json.fromJsonAsList(BrandStudioMemberCreateDTO.class, brandStudioMembersJson);
}
}
private List<BrandStudioHonorCreateDTO> brandStudioHonors;
/**
* 添加的荣誉 JSON
*/
private String brandStudioHonorsJson;
public void setBrandStudioHonorsJson(String brandStudioHonorsJson) {
this.brandStudioHonorsJson = brandStudioHonorsJson;
if (Strings.isNotBlank(brandStudioHonorsJson)) {
this.brandStudioHonors = Json.fromJsonAsList(BrandStudioHonorCreateDTO.class, brandStudioHonorsJson);
}
}
}
@@ -85,6 +85,56 @@ public class BrandStudioApplicationVO implements Serializable {
*/
private Integer status;
/**
* 流程实例ID
*/
private Long instanceId;
/**
* 流程业务编号
*/
private String businessNo;
/**
* 流程状态
*/
private Integer instanceState;
/**
* 流程定义ID
*/
private String instanceProcessDefineId;
/**
* 当前任务ID
*/
private String taskId;
/**
* 当前任务标识
*/
private String taskKey;
/**
* 当前任务名称
*/
private String taskName;
/**
* 当前任务状态
*/
private Integer taskState;
/**
* 是否可以撤回
*/
private Boolean canRevoke;
/**
* 发起任务ID
*/
private String startTaskId;
/**
* 归档
*/
@@ -156,6 +156,51 @@ public class BrandStudioApplyFlowVO implements Serializable {
private String processTaskReason;
/**
* 流程任务状态
*/
private Integer taskState;
/**
* 当前任务ID
*/
private String taskId;
/**
* 当前任务标识
*/
private String taskKey;
/**
* 当前任务名称
*/
private String taskName;
/**
* 当前节点
*/
private String curTaskName;
/**
* 审核时间
*/
private Date finishTime;
/**
* 是否可以撤回
*/
private Boolean canRevoke;
/**
* 流程状态
*/
private Integer instanceState;
/**
* 流程定义ID
*/
private String instanceProcessDefineId;
private String processTaskNode;
@@ -12,6 +12,7 @@ import com.budwk.app.zhgh.brand.models.BrandStudioApplication;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.util.List;
import org.nutz.lang.util.NutMap;
public interface BrandStudioApplicationService extends BaseService<BrandStudioApplication> {
@@ -43,6 +44,8 @@ public interface BrandStudioApplicationService extends BaseService<BrandStudioAp
List<LeaderHonorGroupVO> queryLeaderHonor();
List<NutMap> listMemberCandidates(String unionId, String keyword);
Pagination<BrandStudioApplicationHonorVO> summaryPage(@Valid BrandStudioApplicationPageDTO pageDTO);
List<BrandStudioApplicationHonorVO> getHonorDetailById(String id);
@@ -1,17 +1,18 @@
package com.budwk.app.zhgh.brand.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.StrUtil;
import com.budwk.app.base.constant.RoleConstant;
import com.budwk.app.base.service.impl.BaseServiceImpl;
import com.budwk.app.bpm.enums.BpmProcessInstanceStatusEnum;
import com.budwk.app.bpm.enums.BpmTaskApprovalTypeEnum;
import com.budwk.app.bpm.models.BpmProcessInstance;
import com.budwk.app.bpm.service.BpmService;
import com.budwk.app.flow.constant.FlowConst;
import com.budwk.app.flow.engine.FlowEngine;
import com.budwk.app.flow.entity.ProcessInstance;
import com.budwk.app.flow.enums.ProcessInstanceStateEnum;
import com.budwk.app.flow.enums.ProcessSubmitTypeEnum;
import com.budwk.app.flow.service.FlowCommonService;
import com.budwk.app.sys.models.Sys_union;
import com.budwk.app.sys.models.Sys_user;
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
import com.budwk.app.web.controllers.open.commons.service.CommonService;
import com.budwk.app.zhgh.brand.convert.BrandApplicationFlowConvert;
import com.budwk.app.zhgh.brand.domain.dto.BrandApplicationAuditDTO;
import com.budwk.app.zhgh.brand.domain.dto.BrandApplicationRecallDTO;
@@ -28,7 +29,6 @@ import org.nutz.dao.Dao;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.ioc.loader.annotation.Inject;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
@@ -38,10 +38,10 @@ import java.util.stream.Collectors;
public class BrandApplicationFlowServiceImpl extends BaseServiceImpl<BrandApplicationFlow> implements BrandApplicationFlowService {
@Inject
private BpmService bpmService;
private FlowCommonService flowCommonService;
@Inject
private CommonService commonService;
private FlowEngine flowEngine;
public BrandApplicationFlowServiceImpl(Dao dao) {
super(dao);
@@ -92,56 +92,68 @@ public class BrandApplicationFlowServiceImpl extends BaseServiceImpl<BrandApplic
if (StrUtil.isBlank(taskId)) {
throw new RuntimeException("流程任务ID不能为空");
}
BpmTaskApprovalTypeEnum approvalTypeEnum = getBpmTaskApprovalTypeEnum(dto);
HashMap<String, Object> variables = new HashMap<>(BeanUtil.beanToMap(dto));
variables.put("bpmTaskApprovalType", approvalTypeEnum.name());
variables.put("approvalOpinion", dto.getRemark());
bpmService.completeTask(taskId, approvalTypeEnum, variables, getAssignments(dto, approvalTypeEnum));
ApplicationFlowStatusEnum statusEnum = getFlowStatusEnum(dto);
Dict args = Dict.create();
args.putAll(BeanUtil.beanToMap(dto));
args.set(FlowConst.PROCESS_TASK_ID_KEY, Long.valueOf(taskId));
args.set(FlowConst.APPROVAL_COMMENT, dto.getRemark());
args.set("tf_remark", dto.getRemark());
args.set(FlowConst.SUBMIT_TYPE, getProcessSubmitType(statusEnum));
flowCommonService.executeTask(args);
BpmProcessInstance instance = dao().fetch(BpmProcessInstance.class, Cnd.where("processInstanceBusinessId", "=", applicationId));
if (approvalTypeEnum == BpmTaskApprovalTypeEnum.REJECT) {
ProcessInstance instance = dao().fetch(ProcessInstance.class, Cnd.where("businessNo", "=", applicationId));
if (statusEnum == ApplicationFlowStatusEnum.REJECT) {
dao().update(BrandStudioApplication.class,
Chain.make("status", BrandApplicationStatusEnums.REJECT.getCode()),
Cnd.where("id", "=", applicationId));
} else if (approvalTypeEnum == BpmTaskApprovalTypeEnum.BACK || approvalTypeEnum == BpmTaskApprovalTypeEnum.BACK_OTHER_NODE) {
} else if (statusEnum == ApplicationFlowStatusEnum.RECALL) {
dao().update(BrandStudioApplication.class,
Chain.make("status", BrandApplicationStatusEnums.IN_REVIEW.getCode()),
Chain.make("status", BrandApplicationStatusEnums.DRAFT.getCode()),
Cnd.where("id", "=", applicationId));
} else if (instance != null && BpmProcessInstanceStatusEnum.COMPLETED.name().equals(instance.getProcessInstanceStatus())) {
} else if (instance != null && ProcessInstanceStateEnum.FINISHED.getCode().equals(instance.getState())) {
dao().update(BrandStudioApplication.class,
Chain.make("status", BrandApplicationStatusEnums.PASSED.getCode()),
Cnd.where("id", "=", applicationId));
}
}
private List<String> getAssignments(BrandApplicationAuditDTO dto, BpmTaskApprovalTypeEnum approvalTypeEnum) {
if (dto.getAssignments() != null && !dto.getAssignments().isEmpty()) {
return dto.getAssignments();
private ApplicationFlowStatusEnum getFlowStatusEnum(BrandApplicationAuditDTO dto) {
if (ProcessSubmitTypeEnum.AGREE.getCode().equals(dto.getSubmitType())) {
return ApplicationFlowStatusEnum.PASSED;
}
if (approvalTypeEnum == BpmTaskApprovalTypeEnum.PASS) {
String approvalLoginName = commonService.findUserLoginNameByRoleCode(RoleConstant.SCHOOL_UNION_ADMIN);
if (StrUtil.isBlank(approvalLoginName)) {
throw new RuntimeException("校工会未配置审批人,请联系管理员");
}
return List.of(approvalLoginName);
if (ProcessSubmitTypeEnum.REJECT.getCode().equals(dto.getSubmitType())) {
return ApplicationFlowStatusEnum.REJECT;
}
return null;
}
private BpmTaskApprovalTypeEnum getBpmTaskApprovalTypeEnum(BrandApplicationAuditDTO dto) {
if (StrUtil.isNotBlank(dto.getBpmTaskApprovalType())) {
return BpmTaskApprovalTypeEnum.valueOf(dto.getBpmTaskApprovalType());
if (ProcessSubmitTypeEnum.ROLLBACK_TO_OPERATOR.getCode().equals(dto.getSubmitType())) {
return ApplicationFlowStatusEnum.RECALL;
}
if (StrUtil.equalsIgnoreCase(dto.getBpmTaskApprovalType(), "PASS")) {
return ApplicationFlowStatusEnum.PASSED;
}
if (StrUtil.equalsIgnoreCase(dto.getBpmTaskApprovalType(), "REJECT")) {
return ApplicationFlowStatusEnum.REJECT;
}
if (StrUtil.equalsIgnoreCase(dto.getBpmTaskApprovalType(), "BACK")
|| StrUtil.equalsIgnoreCase(dto.getBpmTaskApprovalType(), "BACK_OTHER_NODE")) {
return ApplicationFlowStatusEnum.RECALL;
}
if (dto.getStatus() == null) {
throw new RuntimeException("任务审批类型错误,请传入正确的任务审批类型。");
}
ApplicationFlowStatusEnum statusEnum = ApplicationFlowStatusEnum.getStatusEnumByValue(dto.getStatus());
if (statusEnum == null) {
throw new RuntimeException("任务审批类型错误,请传入正确的任务审批类型。");
}
return statusEnum;
}
private Integer getProcessSubmitType(ApplicationFlowStatusEnum statusEnum) {
if (statusEnum == ApplicationFlowStatusEnum.PASSED) {
return BpmTaskApprovalTypeEnum.PASS;
return ProcessSubmitTypeEnum.AGREE.getCode();
} else if (statusEnum == ApplicationFlowStatusEnum.REJECT) {
return BpmTaskApprovalTypeEnum.REJECT;
return ProcessSubmitTypeEnum.REJECT.getCode();
} else if (statusEnum == ApplicationFlowStatusEnum.RECALL) {
return BpmTaskApprovalTypeEnum.BACK;
return ProcessSubmitTypeEnum.ROLLBACK_TO_OPERATOR.getCode();
}
throw new RuntimeException("任务审批类型错误,请传入正确的任务审批类型。");
}
@@ -208,16 +220,17 @@ public class BrandApplicationFlowServiceImpl extends BaseServiceImpl<BrandApplic
public void recall(BrandApplicationRecallDTO dto) {
String taskId = StrUtil.blankToDefault(dto.getProcessInstanceTaskId(), dto.getFlowId());
if (StrUtil.isNotBlank(taskId)) {
bpmService.revokeTask(taskId);
flowCommonService.revokeTask(Long.valueOf(taskId));
dao().update(BrandStudioApplication.class,
Chain.make("status", BrandApplicationStatusEnums.IN_REVIEW.getCode()),
Chain.make("status", BrandApplicationStatusEnums.DRAFT.getCode()),
Cnd.where("id", "=", dto.getApplicationId()));
flowEngine.processInstanceService().deleteProcessInstanceByBusinessKey(dto.getApplicationId());
return;
}
bpmService.revokeApply(dto.getApplicationId());
dao().update(BrandStudioApplication.class,
Chain.make("status", BrandApplicationStatusEnums.DRAFT.getCode()),
Cnd.where("id", "=", dto.getApplicationId()));
flowEngine.processInstanceService().deleteProcessInstanceByBusinessKey(dto.getApplicationId());
}
public void recallOld(BrandApplicationRecallDTO dto) {
@@ -1,18 +1,22 @@
package com.budwk.app.zhgh.brand.service.impl;
import cn.hutool.core.util.StrUtil;
import com.budwk.app.base.constant.BpmProcessConstant;
import com.budwk.app.base.constant.RoleConstant;
import com.budwk.app.base.page.Pagination;
import com.budwk.app.base.service.impl.BaseServiceImpl;
import com.budwk.app.bpm.enums.BpmProcessTaskStatusEnum;
import com.budwk.app.bpm.service.BpmService;
import cn.hutool.core.lang.Dict;
import com.budwk.app.flow.constant.FlowConst;
import com.budwk.app.flow.engine.FlowEngine;
import com.budwk.app.flow.entity.ProcessInstance;
import com.budwk.app.flow.entity.ProcessTask;
import com.budwk.app.flow.enums.ProcessSubmitTypeEnum;
import com.budwk.app.flow.enums.ProcessTaskStateEnum;
import com.budwk.app.flow.service.FlowCommonService;
import com.budwk.app.sys.models.Sys_union;
import com.budwk.app.sys.models.Sys_unit;
import com.budwk.app.sys.models.Sys_user;
import com.budwk.app.sys.models.Sys_user_role;
import com.budwk.app.web.commons.auth.utils.AuthUtil;
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
import com.budwk.app.web.controllers.open.commons.service.CommonService;
import com.budwk.app.zhgh.brand.convert.BrandStudioApplicationConvert;
import com.budwk.app.zhgh.brand.convert.BrandStudioHonorConvert;
import com.budwk.app.zhgh.brand.convert.BrandStudioMemberConvert;
@@ -30,8 +34,10 @@ import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.nutz.dao.util.cri.SqlExpressionGroup;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.util.NutMap;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
@@ -49,10 +55,9 @@ public class BrandStudioApplicationServiceImpl extends BaseServiceImpl<BrandStud
private BrandApplicationFlowService flowService;
@Inject
private BpmService bpmService;
private FlowEngine flowEngine;
@Inject
private CommonService commonService;
private FlowCommonService flowCommonService;
public BrandStudioApplicationServiceImpl(Dao dao) {
super(dao);
@@ -63,28 +68,44 @@ public class BrandStudioApplicationServiceImpl extends BaseServiceImpl<BrandStud
public Pagination<BrandStudioApplicationVO> page(BrandStudioApplicationPageDTO pageDTO) {
String userId = SecurityUtil.getUserId();
Cnd cnd = Cnd.where("delFlag", "=", false);
Sql sql = Sqls.create("""
select bsa.*,
ins.id as instanceId,
ins.businessNo,
ins.state as instanceState,
ins.processDefineId as instanceProcessDefineId,
task.id as taskId,
task.taskName as taskKey,
task.displayName as taskName,
task.taskState,
if((select taskName from wf_process_task tt where tt.id = task.taskParentId) = 'startTask', 1, 0) as canRevoke,
(select max(id) from wf_process_task where processInstanceId = ins.id and taskName = 'startTask' and taskState in (10,20)) as startTaskId
from brand_studio_application bsa
left join wf_process_instance ins on ins.businessNo = bsa.id
left join wf_process_task task on task.processInstanceId = ins.id and task.taskState = 10
$condition
""");
Cnd cnd = Cnd.where("bsa.delFlag", "=", false);
/// 2. 先写“普通筛选”这一整组
if (StrUtil.isNotBlank(pageDTO.getName())) {
cnd.and("name", "like", "%" + pageDTO.getName() + "%");
cnd.and("bsa.name", "like", "%" + pageDTO.getName() + "%");
}
if (StrUtil.isNotBlank(userId)) {
cnd.and("createdBy", "=", userId);
cnd.and("bsa.createdBy", "=", userId);
}
if (StrUtil.isNotBlank(pageDTO.getCreateYear())) {
cnd.and("createYear", "=", pageDTO.getCreateYear());
cnd.and("bsa.createYear", "=", pageDTO.getCreateYear());
}
if (pageDTO.getStatus() != null) {
cnd.and("status", "=", pageDTO.getStatus());
cnd.and("bsa.status", "=", pageDTO.getStatus());
}
if (StrUtil.isNotBlank(pageDTO.getLeadPeople())) {
cnd.and("leadPeople", "like", "%" + pageDTO.getLeadPeople() + "%");
cnd.and("bsa.leadPeople", "like", "%" + pageDTO.getLeadPeople() + "%");
}
cnd.desc("createYear");
cnd.desc("createdAt");
Pagination<BrandStudioApplication> page = listPage(pageDTO.getPageNumber(), pageDTO.getPageSize(), BrandStudioApplication.class, cnd);
List<BrandStudioApplicationVO> list = BrandStudioApplicationConvert.convertList(page.getList());
return new Pagination<>(page.getPageNo(), page.getPageSize(), page.getTotalCount(), list);
cnd.desc("bsa.createYear");
cnd.desc("bsa.createdAt");
sql.setCondition(cnd);
return listPageVO(pageDTO, sql, BrandStudioApplicationVO.class);
}
private Sys_user getCheckedUserDetail() {
@@ -147,16 +168,22 @@ public class BrandStudioApplicationServiceImpl extends BaseServiceImpl<BrandStud
if (application == null) {
throw new RuntimeException("提交申请失败");
}
String approvalLoginName = commonService.findUserLoginNameByRoleCode(RoleConstant.BRANCH_UNION_CHAIRMAN, Cnd.where(Sys_user_role::getUnionId, "=", application.getUnionId()));
if (StrUtil.isBlank(approvalLoginName)) {
throw new RuntimeException("分工会未配置审批人,请联系管理员");
}
try {
HashMap<String, Object> variables = new HashMap<>();
variables.put("applicationId", application.getId());
variables.put("status", BrandApplicationStatusEnums.IN_REVIEW.getCode());
variables.put("userId", user.getId());
bpmService.startSubmitProcessInstance(BpmProcessConstant.BRAND_STUDIO.name(), application.getName(), application.getId(), List.of(approvalLoginName), variables);
Dict args = Dict.create();
args.set(FlowConst.SUBMIT_TYPE, ProcessSubmitTypeEnum.APPLY.getCode());
args.set(FlowConst.FORM_DATA, application);
args.set("applicationId", application.getId());
args.set("status", BrandApplicationStatusEnums.IN_REVIEW.getCode());
args.set("userId", user.getId());
// 启动老工作流流程实例,复用 wf_process_define 中的 BRAND_STUDIO 流程定义
ProcessInstance instance = flowEngine.startProcessInstanceByKey("BRAND_STUDIO", application.getId(), SecurityUtil.getUserId(), args);
// 自动完成第一个申请任务
List<ProcessTask> doingTaskList = flowEngine.processTaskService().getDoingTaskList(instance.getId(), null);
for (ProcessTask task : doingTaskList) {
flowEngine.executeProcessTask(task.getId(), SecurityUtil.getUserId(), args);
}
updateApplicationStatusToFail(application.getId(), true);
} catch (RuntimeException e) {
updateApplicationStatusToFail(application.getId(), false);
@@ -203,11 +230,32 @@ public class BrandStudioApplicationServiceImpl extends BaseServiceImpl<BrandStud
/// 再插入新的成员信息
insertBatchBrandStudioMember(dto.getBrandStudioMembers(), dto.getId());
if (statusByCode == BrandApplicationStatusEnums.CREATING) {
/// 提交审核的话会记录在审核流表中
submitAudit(fetch(dto.getId()), getCheckedUserDetail());
if (StrUtil.isNotBlank(dto.getStartTaskId())) {
submitAgain(fetch(dto.getId()), dto.getStartTaskId(), getCheckedUserDetail());
} else {
/// 提交审核的话会记录在审核流表中
submitAudit(fetch(dto.getId()), getCheckedUserDetail());
}
}
}
private void submitAgain(BrandStudioApplication application, String taskId, Sys_user user) {
if (application == null) {
throw new RuntimeException("提交申请失败");
}
Dict args = Dict.create();
args.set(FlowConst.PROCESS_TASK_ID_KEY, Long.valueOf(taskId));
args.set(FlowConst.SUBMIT_TYPE, ProcessSubmitTypeEnum.RE_APPLY.getCode());
args.set(FlowConst.FORM_DATA, application);
args.set("applicationId", application.getId());
args.set("status", BrandApplicationStatusEnums.IN_REVIEW.getCode());
args.set("userId", user.getId());
flowCommonService.executeTask(args);
dao().update(BrandStudioApplication.class,
Chain.make("status", BrandApplicationStatusEnums.IN_REVIEW.getCode()),
Cnd.where("id", "=", application.getId()));
}
@Override
public void updateMemberOrHonor(BrandStudioApplicationUpdateDTO dto) {
dao().update(BrandStudioApplication.class, Chain.make("memberNum", dto.getMemberNum()), Cnd.where("id", "=", dto.getId()));
@@ -228,10 +276,16 @@ public class BrandStudioApplicationServiceImpl extends BaseServiceImpl<BrandStud
@Override
public void delete(List<String> ids) {
if (ids == null || ids.isEmpty()) {
throw new RuntimeException("请选择要删除的数据");
}
String userId = SecurityUtil.getUserId();
SqlExpressionGroup userGroup = new SqlExpressionGroup();
userGroup.or("userId", "=", userId);
userGroup.or("createdBy", "=", userId);
List<String> validIds = dao().query(BrandStudioApplication.class, Cnd.where("id", "in", ids)
.and("userId", "=", userId)
.and(userGroup)
.and("delFlag", "=", false))
.stream().map(BrandStudioApplication::getId).collect(toList());
@@ -244,6 +298,7 @@ public class BrandStudioApplicationServiceImpl extends BaseServiceImpl<BrandStud
dao().update(BrandStudioApplication.class, Chain.make("delFlag", true), Cnd.where("id", "in", validIds));
((BrandStudioMemberServiceImpl) studioMemberService).deleteByApplicationIds(validIds);
flowService.deleteByApplicationIds(validIds);
validIds.forEach(id -> flowEngine.processInstanceService().deleteProcessInstanceByBusinessKey(id));
}
@Override
@@ -287,12 +342,51 @@ public class BrandStudioApplicationServiceImpl extends BaseServiceImpl<BrandStud
Integer age = list.get(0).getAge();
List<String> honorNames = list.stream()
.map(LeaderHonorVO::getHonorName)
.filter(StrUtil::isNotBlank)
.distinct()
.collect(Collectors.toList());
return new LeaderHonorGroupVO(emplid, userName, age, honorNames);
})
.collect(Collectors.toList());
}
@Override
public List<NutMap> listMemberCandidates(String unionId, String keyword) {
Sql sql = Sqls.create("""
select id,
id as userId,
loginname as emplid,
loginname,
username as name,
username,
date_format(birthday, '%Y-%m') as birthdate,
academicDegree as grade,
professionalTitle as professional,
unitName as deptName,
unitName,
unionId
from vw_user
$condition
""");
Cnd cnd = Cnd.NEW();
boolean isAdmin = AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name());
if (isAdmin) {
cnd.andEX("unionId", "=", unionId);
} else {
cnd.and("unionId", "=", SecurityUtil.getUnionId());
}
if (StrUtil.isNotBlank(keyword)) {
SqlExpressionGroup group = new SqlExpressionGroup();
group.orLike("loginname", keyword, true);
group.orLike("username", keyword, true);
cnd.and(group);
}
cnd.asc("loginname");
sql.setCondition(cnd);
Pagination pagination = listPageMap(1, 50, sql);
return pagination.getList();
}
@Override
public BrandStudioApplicationVO getDetailById(String id) {
BrandStudioApplication entity = fetch(id);
@@ -312,7 +406,21 @@ public class BrandStudioApplicationServiceImpl extends BaseServiceImpl<BrandStud
applicationVO.setBrandStudioHonors(honorVOS);
}
/// 查询当前工作流待审核 ID
ProcessInstance instance = dao().fetch(ProcessInstance.class, Cnd.where("businessNo", "=", id).desc("createdAt"));
if (instance != null) {
applicationVO.setInstanceId(instance.getId());
applicationVO.setBusinessNo(instance.getBusinessNo());
applicationVO.setInstanceState(instance.getState());
applicationVO.setInstanceProcessDefineId(String.valueOf(instance.getProcessDefineId()));
ProcessTask startTask = dao().fetch(ProcessTask.class, Cnd.where("processInstanceId", "=", instance.getId())
.and("taskName", "=", "startTask")
.and("taskState", "=", ProcessTaskStateEnum.DOING.getCode())
.desc("id"));
if (startTask != null) {
applicationVO.setStartTaskId(String.valueOf(startTask.getId()));
}
}
return applicationVO;
}
@@ -334,18 +442,45 @@ public class BrandStudioApplicationServiceImpl extends BaseServiceImpl<BrandStud
@Override
public Pagination<BrandStudioApplyFlowVO> flowAuditPage(BrandStudioApplicationPageDTO dto) {
Sql sql = Sqls.create("""
select bsa.*, inst.id as processInstanceId, inst.processInstanceNodeName as processTaskNode,
task.id as flowId, task.id as processInstanceTaskId, task.taskStatus as processTaskReason,
task.createdOn as processTaskStartTime, task.endOn as processTaskEndTime
from brand_studio_application bsa
inner join bpm_process_instance inst on bsa.id = inst.processInstanceBusinessId
inner join bpm_process_task task on inst.id = task.processInstanceId and task.delFlag = 0
inner join bpm_process_define def on inst.processDefineId = def.id and def.code = 'BRAND_STUDIO'
where bsa.delFlag = 0
select bsa.*, inst.id as processInstanceId, inst.state as instanceState,
inst.processDefineId as instanceProcessDefineId,
task.id as taskId, task.id as flowId, task.id as processInstanceTaskId,
task.taskName as taskKey, task.displayName as taskName, task.displayName as processTaskNode,
task.taskState, task.finishTime,
ifnull(group_concat(distinct nextTask.displayName), '结束') as curTaskName,
if(revokeTask.id is not null, 1, 0) as canRevoke,
case task.taskState
when 10 then 'ACTIVE'
when 20 then 'COMPLETE'
when 30 then 'WITHDRAW'
when 40 then 'INTERRUPT'
when 50 then 'PENDING'
when 60 then 'TRANSFER'
when 99 then 'ABANDON'
else cast(task.taskState as char)
end as processTaskReason,
from_unixtime(task.createdAt / 1000) as processTaskStartTime,
task.finishTime as processTaskEndTime
from wf_process_task task
left join wf_process_instance inst on inst.id = task.processInstanceId
left join brand_studio_application bsa on bsa.id = inst.businessNo
left join wf_process_task_actor taskActor on taskActor.processTaskId = task.id
left join wf_process_task nextTask on nextTask.processInstanceId = inst.id and nextTask.taskState = 10
left join wf_process_task revokeTask on revokeTask.processInstanceId = inst.id and revokeTask.taskParentId = task.id and revokeTask.taskState = 10
inner join wf_process_define def on inst.processDefineId = def.id and def.name = 'BRAND_STUDIO'
$condition
order by task.createdOn desc
order by task.createdAt desc
""");
Cnd cnd = Cnd.NEW();
Cnd cnd = Cnd.where("bsa.delFlag", "=", 0);
cnd.and("taskActor.actorId", "in", List.of(SecurityUtil.getUserId()));
cnd.and("task.taskName", "!=", "startTask");
if (AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name(),
RoleConstant.SCHOOL_UNION_CHAIRMAN.name(), RoleConstant.SCHOOL_UNION_VICE_CHAIRMAN.name())) {
cnd.and("task.displayName", "like", "%校工会%");
} else if (AuthUtil.hasRoleOr(RoleConstant.BRANCH_UNION_ADMIN.name(), RoleConstant.BRANCH_UNION_CHAIRMAN.name(),
RoleConstant.BRANCH_UNION_VICE_CHAIRMAN.name(), RoleConstant.BRANCH_UNION_OPERATOR.name())) {
cnd.and("task.displayName", "like", "%分工会%");
}
if (StrUtil.isNotBlank(dto.getName())) {
cnd.and("bsa.name", "like", "%" + dto.getName() + "%");
}
@@ -355,37 +490,44 @@ public class BrandStudioApplicationServiceImpl extends BaseServiceImpl<BrandStud
if (StrUtil.isNotBlank(dto.getLeadPeople())) {
cnd.and("bsa.leadPeople", "like", "%" + dto.getLeadPeople() + "%");
}
if (Boolean.TRUE.equals(dto.getAudit())) {
cnd.and("task.taskState", "in", List.of(ProcessTaskStateEnum.FINISHED.getCode(), ProcessTaskStateEnum.INTERRUPT.getCode()));
} else {
cnd.and("task.taskState", "=", ProcessTaskStateEnum.DOING.getCode());
cnd.and("bsa.status", "=", BrandApplicationStatusEnums.IN_REVIEW.getCode());
}
if (dto.getProcessStatus() != null) {
cnd.and("task.taskStatus", "=", getProcessTaskStatus(dto.getProcessStatus()));
cnd.and("task.taskState", "=", getProcessTaskStatus(dto.getProcessStatus()));
}
if (dto.getStatus() != null) {
cnd.and("bsa.status", "=", dto.getStatus());
}
cnd.groupBy("task.id");
sql.setCondition(cnd);
return listPageVO(dto, sql, BrandStudioApplyFlowVO.class);
}
private String getProcessTaskStatus(Integer processStatus) {
private Integer getProcessTaskStatus(Integer processStatus) {
if (Objects.equals(processStatus, 1)) {
return BpmProcessTaskStatusEnum.ACTIVE.name();
return ProcessTaskStateEnum.DOING.getCode();
}
if (Objects.equals(processStatus, 5)) {
return BpmProcessTaskStatusEnum.COMPLETE.name();
return ProcessTaskStateEnum.FINISHED.getCode();
}
return String.valueOf(processStatus);
return processStatus;
}
@Override
public Pagination<BrandStudioApplicationHonorVO> summaryPage(BrandStudioApplicationPageDTO pageDTO) {
Sql sql = Sqls.create("""
select bsa.*, bsh.id as honorId, bsh.honorName, bsh.honorGrade, bsh.requireYear, bsh.honorCategory
select bsa.*, group_concat(bsh.honorName order by bsh.requireYear desc separator ',') as honorName
from brand_studio_application bsa
left join brand_studio_honor bsh on bsa.id = bsh.applicationId and bsh.delFlag = 0
where bsa.delFlag = 0
$condition
group by bsa.id
order by bsa.createYear desc, bsa.createdAt desc
""");
Cnd cnd = Cnd.NEW();
Cnd cnd = Cnd.where("bsa.delFlag", "=", 0);
if (StrUtil.isNotBlank(pageDTO.getName())) {
cnd.and("bsa.name", "like", "%" + pageDTO.getName() + "%");
}
@@ -420,18 +562,23 @@ public class BrandStudioApplicationServiceImpl extends BaseServiceImpl<BrandStud
private List<LeaderHonorVO> selectLeaderHonor() {
Sql sql = Sqls.create("""
select su.id,
su.loginname as emplid,
su.username as userName,
su.unitId as deptid,
su.unitId,
su.birthday,
su.professionalTitle as honorName,
u.unionId as unionId
from sys_user su
left join sys_unit u on su.unitId = u.id
where su.delFlag = 0
and su.disabled = 0
select h.id,
u.loginname as emplid,
h.userName,
timestampdiff(year, u.birthday, curdate()) as age,
h.unitId as deptid,
h.unionId,
h.unitName as deptName,
year(h.grantDate) as year,
prize.name as honorName,
h.prize as honorCode
from honor h
left join vw_user u on h.userId = u.id
left join honor_basic_settings prize on prize.id = h.prize
left join honor_basic_settings type on type.id = h.honorType
where h.userId is not null
and prize.name is not null
and (type.queryTypeCode = 'HONOR_SINGLE' or type.name = '个人荣誉')
""");
return listVO(sql, LeaderHonorVO.class);
}
@@ -3,20 +3,26 @@ layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava ref="guava">
<el-card shadow="never">
<el-form :inline="true" :model="pageForm">
<el-form-item label="创立年度">
<el-date-picker v-model="pageForm.createYear" type="year" value-format="yyyy"></el-date-picker>
</el-form-item>
<el-form-item label="工作室名称">
<el-input v-model="pageForm.name" clearable></el-input>
</el-form-item>
<el-form-item label="创建年份">
<el-date-picker v-model="pageForm.createYear" type="year" value-format="yyyy"></el-date-picker>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="pageData">查询</el-button>
<el-button @click="openApply()">新建</el-button>
</el-form-item>
</el-form>
<el-table :data="tableData" border>
</el-card>
<el-card shadow="never" class="mt10">
<table-tool label="申请列表">
<el-button size="small" type="primary" @click="openApply()">申请品牌工作室</el-button>
</table-tool>
<el-table :data="tableData" border style="width: 100%">
<el-table-column type="index" label="序号" width="60"></el-table-column>
<el-table-column prop="name" label="工作室名称" min-width="160"></el-table-column>
<el-table-column prop="createYear" label="创立年度" width="100"></el-table-column>
@@ -25,28 +31,100 @@ layout("/layouts/platform.html"){
<el-table-column prop="type" label="工作室类型" width="120"></el-table-column>
<el-table-column prop="track" label="工作室赛道" width="120"></el-table-column>
<el-table-column prop="memberNum" label="成员人数" width="90"></el-table-column>
<el-table-column label="状态" width="100">
<el-table-column label="流程状态" width="100">
<template slot-scope="{row}">
<el-tag v-if="row.status===0" type="info">草稿</el-tag>
<el-tag v-else-if="row.status===1" type="warning">审核中</el-tag>
<el-tag v-else-if="row.status===2" type="danger">驳回</el-tag>
<el-tag v-else-if="row.status===5" type="success">通过</el-tag>
<el-tag v-else>{{row.status}}</el-tag>
<el-tag v-if="!row.instanceId" type="info">草稿</el-tag>
<enum-tag
v-else
:value="row.instanceState"
name="ProcessInstanceStateEnum"
label_key="message"
size="small">
</enum-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="180">
<el-table-column label="操作" width="260" fixed="right">
<template slot-scope="{row}">
<el-button type="text" @click="openApply(row.id)">编辑</el-button>
<el-button type="text" @click="submitApply(row)" v-if="row.status===0 || row.status===7">申请</el-button>
<el-button size="mini" type="primary" @click="openView(row)" v-if="row.instanceId">查看</el-button>
<el-button size="mini" type="primary" @click="openApply(row.id)" v-if="row.taskKey === 'startTask' || !row.instanceId">编辑</el-button>
<el-button size="mini" type="danger" @click="recallApply(row)" v-if="row.canRevoke === true || row.canRevoke === 1">撤回</el-button>
<el-button size="mini" type="danger" @click="deleteApply(row.id)" v-if="row.taskKey === 'startTask' || !row.instanceId">删除</el-button>
</template>
</el-table-column>
</el-table>
</el-card>
<template #view>
<div>
<el-tabs tab-position="top" v-model="activeName">
<el-tab-pane name="1" label="基础信息">
<div class="process-title">
品牌工作室申请
<el-link type="primary" @click="openChart">点击查看流程图</el-link>
</div>
<el-descriptions :column="2" border>
<el-descriptions-item label="工作室名称">{{detail.name}}</el-descriptions-item>
<el-descriptions-item label="创立年度">{{detail.createYear}}</el-descriptions-item>
<el-descriptions-item label="所属工会">{{detail.unionName}}</el-descriptions-item>
<el-descriptions-item label="所在单位">{{detail.deptName}}</el-descriptions-item>
<el-descriptions-item label="领衔人">{{detail.leadPeople}}</el-descriptions-item>
<el-descriptions-item label="领衔人年龄">{{detail.leadAge}}</el-descriptions-item>
<el-descriptions-item label="领衔人身份">{{detail.leadIdentity}}</el-descriptions-item>
<el-descriptions-item label="领衔人荣誉">{{detail.leadHonor}}</el-descriptions-item>
<el-descriptions-item label="工作室类型">{{detail.type}}</el-descriptions-item>
<el-descriptions-item label="所属赛道">{{detail.track}}</el-descriptions-item>
<el-descriptions-item label="工作室地址" :span="2">{{detail.address}}</el-descriptions-item>
<el-descriptions-item label="工作室介绍" :span="2">{{detail.introduction}}</el-descriptions-item>
<el-descriptions-item label="备注" :span="2">{{detail.remark}}</el-descriptions-item>
</el-descriptions>
<snaker-chart ref="snakerChartRef"></snaker-chart>
</el-tab-pane>
<el-tab-pane name="2" label="成员信息">
<div class="process-title">成员信息</div>
<el-table :data="detail.brandStudioMembers || []" border size="small">
<el-table-column label="姓名" prop="name" width="120"></el-table-column>
<el-table-column label="出生年月" prop="birthdate" width="120"></el-table-column>
<el-table-column label="学位" prop="grade" show-overflow-tooltip></el-table-column>
<el-table-column label="职称" prop="professional" show-overflow-tooltip></el-table-column>
<el-table-column label="所在单位" prop="deptName" show-overflow-tooltip></el-table-column>
</el-table>
</el-tab-pane>
<el-tab-pane name="3" label="审核记录">
<template v-if="doneTasks.length > 0" v-for="task in doneTasks">
<div class="mt10">
<div class="process-title">{{ task.displayName }}</div>
<el-descriptions border class="flow-task-form" :column="3" :key="task.id"
v-if="task.ext.isFirstTaskNode">
<el-descriptions-item label="申请用户">{{ task.ext.initiatorName }}({{task.ext.initiatorAccount}})</el-descriptions-item>
<el-descriptions-item label="申请时间">{{ task.finishTime }}</el-descriptions-item>
<el-descriptions-item label="办理结果">
<dict-tag :options="dict.type.PROCESS_TASK_SUBMIT_TYPE" :value="task.ext.submitType"></dict-tag>
</el-descriptions-item>
</el-descriptions>
<el-descriptions border class="flow-task-form" :column="3" :key="task.id" v-else>
<el-descriptions-item label="办理用户">{{ task.taskFormData.userName }}({{task.taskFormData.loginName}})</el-descriptions-item>
<el-descriptions-item label="办理时间">{{ task.finishTime }}</el-descriptions-item>
<el-descriptions-item label="办理结果">
<dict-tag :options="dict.type.PROCESS_TASK_SUBMIT_TYPE" :value="task.ext.submitType"></dict-tag>
</el-descriptions-item>
<el-descriptions-item label="办理意见" v-if="!task.ext.isFirstTaskNode">{{ task.taskFormData.opinion || task.taskFormData.remark || task.taskFormData.approvalComment }}</el-descriptions-item>
</el-descriptions>
</div>
</template>
<template v-else>
<el-empty description="暂无审核记录"></el-empty>
</template>
</el-tab-pane>
</el-tabs>
</div>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
new Vue({
el: "#app",
dicts: ["PROCESS_TASK_SUBMIT_TYPE"],
data() {
return {
pageForm: {
@@ -54,7 +132,11 @@ layout("/layouts/platform.html"){
limit: 20,
createYear: String(new Date().getFullYear())
},
tableData: []
tableData: [],
detail: {},
currentRow: {},
activeName: "1",
doneTasks: []
}
},
methods: {
@@ -67,16 +149,78 @@ layout("/layouts/platform.html"){
this.tableData = data.list || data.data || []
})
},
openApply(id) {
window.location.href = '/platform/zhgh/brand/apply/index' + (id ? '?id=' + id : '')
openApply(id, mode) {
let url = '/platform/zhgh/brand/apply/index'
const params = []
if (id) {
params.push('id=' + id)
}
if (mode) {
params.push('mode=' + mode)
}
if (params.length) {
url += '?' + params.join('&')
}
window.location.href = url
},
submitApply(row) {
this.$axios.post('/platform/zhgh/brand/application/submitApply', {
applicationId: row.id,
status: 1
openView(row) {
this.$refs.guava.view(() => {
this.currentRow = row
this.activeName = "1"
this.loadDetail(row.id)
this.getDoneTasks(row)
})
},
loadDetail(id) {
this.$axios.get('/platform/zhgh/brand/application/' + id).then((res) => {
this.detail = this.getData(res) || {}
this.detail.brandStudioMembers = this.detail.brandStudioMembers || []
})
},
getDoneTasks(row) {
this.$axios.post('/flow/common/doneTasks', {
instanceId: row.instanceId,
bizId: row.id
}).then((res) => {
if (res.code === 0) {
this.doneTasks = res.data || []
}
})
},
openChart() {
if (!this.currentRow.instanceId || !this.currentRow.instanceProcessDefineId) {
this.$message.warning('暂无流程图信息')
return
}
this.$refs.snakerChartRef.onOpenFull(this.currentRow.instanceProcessDefineId, this.currentRow.instanceId)
},
recallApply(row) {
this.$confirm('您确定要撤回吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.$message.success('申请成功')
this.pageData()
this.$axios.post('/platform/zhgh/brand/flow/recall', {
applicationId: row.id,
processInstanceTaskId: row.startTaskId
}).then(() => {
this.$message.success('撤回成功')
this.pageData()
})
})
},
deleteApply(id) {
this.$confirm('您确定要删除吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.$axios.post('/platform/zhgh/brand/application/delete', {
data: [id]
}).then(() => {
this.$message.success('删除成功')
this.pageData()
})
})
}
},
@@ -4,10 +4,8 @@ layout("/layouts/platform.html"){
<div id="app" v-cloak>
<el-card shadow="never">
<div slot="header">
<span>{{form.id ? '修改申请' : '创建申请'}}</span>
</div>
<el-form ref="form" :model="form" label-width="130px">
<snaker-start slot="header" label="品牌工作室申请" define_key="BRAND_STUDIO"></snaker-start>
<el-form ref="form" :model="form" label-width="130px" :disabled="isView">
<el-row :gutter="15">
<el-col :span="12">
<el-form-item label="工作室名称">
@@ -16,22 +14,36 @@ layout("/layouts/platform.html"){
</el-col>
<el-col :span="12">
<el-form-item label="创建年份">
<el-date-picker v-model="form.createYear" type="year" value-format="yyyy" style="width: 100%"></el-date-picker>
<el-input v-model="form.createYear" disabled></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="所属工会">
<el-input v-model="form.unionName"></el-input>
<el-select v-model="form.unionId" filterable placeholder="请选择所属工会" style="width: 100%" @change="unionChange">
<el-option
v-for="item in unionOptions"
:key="item.id"
:label="item.name"
:value="item.id">
</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="所属机构">
<el-input v-model="form.deptName"></el-input>
<el-form-item label="所在单位">
<el-input v-model="form.deptName" disabled></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="领衔人">
<el-input v-model="form.leadPeople"></el-input>
<el-select v-model="leadPeopleEmplid" filterable placeholder="请选择领衔人" style="width: 100%" @change="leaderChange">
<el-option
v-for="item in leaderHonors"
:key="item.emplid"
:label="item.label"
:value="item.emplid">
</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
@@ -41,7 +53,14 @@ layout("/layouts/platform.html"){
</el-col>
<el-col :span="12">
<el-form-item label="领衔人身份">
<el-input v-model="form.leadIdentity"></el-input>
<el-select v-model="form.leadIdentity" multiple filterable placeholder="请选择领衔人身份" style="width: 100%">
<el-option
v-for="item in leadPeopleDict"
:key="item.id"
:label="item.name"
:value="item.name">
</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
@@ -51,22 +70,26 @@ layout("/layouts/platform.html"){
</el-col>
<el-col :span="12">
<el-form-item label="工作室类型">
<el-input v-model="form.type"></el-input>
<el-select v-model="form.type" filterable placeholder="请选择工作室类型" style="width: 100%">
<el-option
v-for="item in brandOfficeTypeDict"
:key="item.id"
:label="item.name"
:value="item.name">
</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="所属赛道">
<el-input v-model="form.track"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="所属领域">
<el-input v-model="form.domain"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="成员人数">
<el-input-number v-model="form.memberNum" :min="1" style="width: 100%"></el-input-number>
<el-select v-model="form.track" filterable placeholder="请选择所属赛道" style="width: 100%" @change="trackChange">
<el-option
v-for="item in brandOfficeTrackDict"
:key="item.id"
:label="item.name"
:value="item.name">
</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="24">
@@ -86,26 +109,42 @@ layout("/layouts/platform.html"){
</el-col>
</el-row>
<el-divider content-position="left">工作室成员</el-divider>
<el-table :data="form.brandStudioMembers" border size="small">
<el-divider content-position="left">选择工作室成员</el-divider>
<div class="brand-member-toolbar" v-if="!isView">
<div class="brand-member-count">已选择 {{form.brandStudioMembers.length}} 人</div>
<el-button size="small" type="primary" icon="el-icon-plus" @click="openMemberDialog">选择工作室成员</el-button>
</div>
<div class="brand-member-toolbar" v-else>
<div class="brand-member-count">已选择 {{form.brandStudioMembers.length}} 人</div>
</div>
<div class="brand-member-table">
<el-table :data="form.brandStudioMembers" border size="small">
<el-table-column label="姓名" min-width="120">
<template slot-scope="{row}">
<el-input v-model="row.name"></el-input>
</template>
</el-table-column>
<el-table-column label="角色" min-width="120">
<template slot-scope="{row}">
<el-input v-model="row.role"></el-input>
<el-input v-model="row.name" disabled></el-input>
</template>
</el-table-column>
<el-table-column label="出生年月" min-width="120">
<template slot-scope="{row}">
<el-input v-model="row.birthdate"></el-input>
<el-date-picker
v-model="row.birthdate"
type="month"
value-format="yyyy-MM"
placeholder="请选择出生年月"
style="width: 100%">
</el-date-picker>
</template>
</el-table-column>
<el-table-column label="学" min-width="120">
<el-table-column label="学" min-width="120">
<template slot-scope="{row}">
<el-input v-model="row.grade"></el-input>
<el-select v-model="row.grade" filterable placeholder="请选择学位" style="width: 100%">
<el-option
v-for="item in memberDegreeDict"
:key="item.id"
:label="item.name"
:value="item.name">
</el-option>
</el-select>
</template>
</el-table-column>
<el-table-column label="职称" min-width="120">
@@ -113,23 +152,43 @@ layout("/layouts/platform.html"){
<el-input v-model="row.professional"></el-input>
</template>
</el-table-column>
<el-table-column label="操作" width="90">
<template slot-scope="scope">
<el-button type="text" @click="removeMember(scope.$index)">删除</el-button>
<el-table-column label="所在单位" min-width="160">
<template slot-scope="{row}">
<el-input v-model="row.deptName" disabled></el-input>
</template>
</el-table-column>
</el-table>
<div style="margin-top: 10px">
<el-button size="small" @click="addMember">添加成员</el-button>
<el-table-column label="操作" width="90" v-if="!isView">
<template slot-scope="scope">
<el-button size="mini" type="danger" @click="removeMember(scope.$index)">删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
<el-form-item style="margin-top: 20px">
<el-button @click="goBack">返回</el-button>
<el-form-item class="brand-form-actions" v-if="!isView">
<el-button type="primary" :loading="loading" @click="save(0)">保存草稿</el-button>
<el-button type="primary" :loading="loading" @click="save(6)">提交申请</el-button>
</el-form-item>
</el-form>
</el-card>
<el-dialog title="选择工作室成员" :visible.sync="memberDialogVisible" width="760px" class="brand-member-dialog">
<div class="brand-member-search">
<el-input v-model="memberKeyword" placeholder="请输入姓名或工号" clearable @keyup.enter.native="loadMemberCandidates"></el-input>
<el-button type="primary" icon="el-icon-search" @click="loadMemberCandidates">查询</el-button>
</div>
<el-table :data="memberCandidates" border size="small" height="360" @selection-change="memberSelectionChange">
<el-table-column type="selection" width="55"></el-table-column>
<el-table-column prop="loginname" label="工号" width="120"></el-table-column>
<el-table-column prop="username" label="姓名" width="120"></el-table-column>
<el-table-column prop="unitName" label="所属机构" show-overflow-tooltip></el-table-column>
</el-table>
<div slot="footer">
<el-button @click="memberDialogVisible = false">取消</el-button>
<el-button type="primary" @click="confirmSelectMembers">确定</el-button>
</div>
</el-dialog>
</div>
<script nonce="${cspNonce!}">
@@ -139,11 +198,25 @@ layout("/layouts/platform.html"){
data() {
return {
loading: false,
isView: false,
form: {
archive: 0,
status: 0,
createYear: String(new Date().getFullYear()),
leadIdentity: [],
brandStudioMembers: []
}
},
unionOptions: [],
leaderHonors: [],
leadPeopleDict: [],
brandOfficeTypeDict: [],
brandOfficeTrackDict: [],
memberDegreeDict: [],
leadPeopleEmplid: '',
memberDialogVisible: false,
memberKeyword: '',
memberCandidates: [],
selectedMemberCandidates: []
}
},
methods: {
@@ -161,26 +234,139 @@ layout("/layouts/platform.html"){
this.form.unionName = union.name
this.form.deptid = user.unitId || unit.id
this.form.deptName = unit.name
this.form.createYear = String(new Date().getFullYear())
},
async loadUnionOptions() {
const user = this.$store.state.user || {}
const union = user.union || {}
const roles = user.roles || []
const isAdmin = roles.some(item => item.code === 'SYSADMIN' || item.code === 'SCHOOL_UNION_ADMIN')
this.unionOptions = await this.$businessTool.listUnion(isAdmin ? null : union.id)
if (!this.form.unionId && this.unionOptions.length > 0) {
this.form.unionId = this.unionOptions[0].id
this.form.unionName = this.unionOptions[0].name
}
},
unionChange(unionId) {
const union = this.unionOptions.find(item => item.id === unionId)
this.form.unionName = union ? union.name : ''
},
loadDictOptions(code) {
return this.$axios.get('/open/common/dictOptions', {params: {code: code}}).then((res) => {
return this.getData(res) || []
})
},
loadDicts() {
Promise.all([
this.loadDictOptions('brand_office_lead_people'),
this.loadDictOptions('brand_office_type'),
this.loadDictOptions('brand_office_track'),
this.loadDictOptions('USER_ACADEMIC_DEGREE')
]).then(([leadPeopleDict, brandOfficeTypeDict, brandOfficeTrackDict, memberDegreeDict]) => {
this.leadPeopleDict = leadPeopleDict
this.brandOfficeTypeDict = brandOfficeTypeDict
this.brandOfficeTrackDict = brandOfficeTrackDict
this.memberDegreeDict = memberDegreeDict
})
},
loadLeaderHonors() {
this.$axios.get('/platform/zhgh/brand/application/leader').then((res) => {
const data = this.getData(res) || []
this.leaderHonors = data.map(item => {
item.label = item.userName + '' + item.emplid + ''
return item
})
if (this.form.leadPeople) {
const leader = this.leaderHonors.find(item => item.userName === this.form.leadPeople)
this.leadPeopleEmplid = leader ? leader.emplid : ''
}
})
},
leaderChange(emplid) {
const leader = this.leaderHonors.find(item => item.emplid === emplid)
if (leader) {
this.form.leadPeople = leader.userName
this.form.leadAge = leader.age
this.form.leadHonor = (leader.honorNames || []).join(',')
} else {
this.form.leadPeople = ''
this.form.leadAge = ''
this.form.leadHonor = ''
}
},
trackChange(track) {
this.form.domain = track
},
openMemberDialog() {
this.memberDialogVisible = true
this.loadMemberCandidates()
},
loadMemberCandidates() {
this.$axios.get('/platform/zhgh/brand/application/members', {
params: {
unionId: this.form.unionId,
keyword: this.memberKeyword
}
}).then((res) => {
this.memberCandidates = this.getData(res) || []
})
},
memberSelectionChange(selection) {
this.selectedMemberCandidates = selection
},
confirmSelectMembers() {
if (!this.selectedMemberCandidates.length) {
this.$message.warning('请至少选择一位工作室成员')
return
}
const existingIds = new Set((this.form.brandStudioMembers || []).map(item => item.userId || item.id))
const members = this.selectedMemberCandidates
.filter(item => !existingIds.has(item.id))
.map(item => ({
userId: item.id,
emplid: item.emplid || item.loginname,
name: item.name || item.username,
role: '',
birthdate: item.birthdate,
grade: item.grade,
professional: item.professional,
deptName: item.deptName || item.unitName
}))
this.form.brandStudioMembers = [...(this.form.brandStudioMembers || []), ...members]
this.form.memberNum = this.form.brandStudioMembers.length
this.memberDialogVisible = false
},
loadDetail(id) {
this.$axios.get('/platform/zhgh/brand/application/' + id).then((res) => {
const data = this.getData(res) || {}
data.brandStudioMembers = data.brandStudioMembers || []
data.memberNum = data.brandStudioMembers.length
data.leadIdentity = data.leadIdentity ? data.leadIdentity.split(',') : []
this.form = data
this.loadUnionOptions()
this.loadLeaderHonors()
})
},
addMember() {
this.form.brandStudioMembers.push({})
this.form.memberNum = this.form.brandStudioMembers.length
},
removeMember(index) {
this.form.brandStudioMembers.splice(index, 1)
this.form.memberNum = this.form.brandStudioMembers.length
},
save(status) {
this.loading = true
this.form.status = status
const params = Object.assign({}, this.form)
params.leadIdentity = (params.leadIdentity || []).join(',')
params.domain = params.track
params.memberNum = (params.brandStudioMembers || []).length
params.brandStudioMembersJson = JSON.stringify(params.brandStudioMembers || [])
delete params.brandStudioMembers
const request = this.form.id
? this.$axios.post('/platform/zhgh/brand/application/update', this.form)
: this.$axios.post('/platform/zhgh/brand/application', this.form)
? this.$axios.post('/platform/zhgh/brand/application/update', params)
: this.$axios.post('/platform/zhgh/brand/application', params)
request.then(() => {
this.$message.success('保存成功')
this.goBack()
@@ -193,17 +379,53 @@ layout("/layouts/platform.html"){
}
},
created() {
this.loadDicts()
this.loadLeaderHonors()
const id = this.getParam('id')
this.isView = this.getParam('mode') === 'view'
if (id) {
this.loadDetail(id)
} else {
this.loadUserInfo()
this.addMember()
this.loadUnionOptions()
}
}
})
</script>
<style>
.brand-member-toolbar {
display: flex;
align-items: center;
justify-content: space-between;
margin: 0 0 12px;
padding: 0 2px 0 16px;
}
.brand-member-count {
color: #606266;
font-size: 13px;
}
.brand-member-table {
padding-left: 16px;
}
.brand-form-actions {
margin-top: 20px;
text-align: right;
}
.brand-member-search {
display: flex;
gap: 10px;
margin-bottom: 12px;
}
.brand-member-search .el-input {
flex: 1;
}
.brand-member-dialog .el-dialog__body {
padding-top: 12px;
padding-bottom: 12px;
}
</style>
<!--#
}
#-->
@@ -3,34 +3,153 @@ layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<el-card shadow="never">
<el-form :inline="true" :model="pageForm">
<el-form-item label="工作室名称">
<el-input v-model="pageForm.name" clearable></el-input>
</el-form-item>
<el-form-item label="创建年份">
<el-date-picker v-model="pageForm.createYear" type="year" value-format="yyyy"></el-date-picker>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="pageData">查询</el-button>
</el-form-item>
</el-form>
<el-table :data="tableData" border>
<el-table-column type="index" label="序号" width="60"></el-table-column>
<el-table-column prop="name" label="工作室名称" min-width="160"></el-table-column>
<el-table-column prop="createYear" label="创立年度" width="100"></el-table-column>
<el-table-column prop="leadPeople" label="领衔人" width="120"></el-table-column>
<el-table-column prop="deptName" label="所属机构" min-width="140"></el-table-column>
<el-table-column prop="type" label="工作室类型" width="120"></el-table-column>
<el-table-column prop="track" label="工作室赛道" width="120"></el-table-column>
<el-table-column prop="memberNum" label="成员人数" width="90"></el-table-column>
<el-table-column label="操作" width="120">
<template slot-scope="{row}">
<el-button type="text" @click="openApply(row.id)">编辑工作室</el-button>
</template>
</el-table-column>
<guava ref="guava">
<el-card shadow="never">
<el-form :inline="true" :model="pageForm">
<el-form-item label="创立年度">
<el-date-picker v-model="pageForm.createYear" type="year" value-format="yyyy"></el-date-picker>
</el-form-item>
<el-form-item label="工作室名称">
<el-input v-model="pageForm.name" clearable></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="pageData">查询</el-button>
</el-form-item>
</el-form>
</el-card>
<el-card shadow="never" class="mt10">
<table-tool label="工作室列表"></table-tool>
<el-table :data="tableData" border style="width: 100%">
<el-table-column type="index" label="序号" width="60"></el-table-column>
<el-table-column prop="name" label="工作室名称" min-width="160"></el-table-column>
<el-table-column prop="createYear" label="创立年度" width="100"></el-table-column>
<el-table-column prop="leadPeople" label="领衔人" width="120"></el-table-column>
<el-table-column prop="deptName" label="所在单位" min-width="140"></el-table-column>
<el-table-column prop="type" label="工作室类型" width="120"></el-table-column>
<el-table-column prop="track" label="工作室赛道" width="120"></el-table-column>
<el-table-column prop="memberNum" label="成员人数" width="90"></el-table-column>
<el-table-column label="操作" width="150" fixed="right">
<template slot-scope="{row}">
<el-button size="mini" type="primary" @click="openDetail(row)">编辑品牌工作室</el-button>
</template>
</el-table-column>
</el-table>
</el-card>
<template #public>
<div>
<div class="process-title">编辑品牌工作室</div>
<el-tabs v-model="activeName">
<el-tab-pane name="base" label="基本信息">
<el-descriptions :column="2" border>
<el-descriptions-item label="工作室名称">{{form.name}}</el-descriptions-item>
<el-descriptions-item label="创立年度">{{form.createYear}}</el-descriptions-item>
<el-descriptions-item label="所属工会">{{form.unionName}}</el-descriptions-item>
<el-descriptions-item label="所在单位">{{form.deptName}}</el-descriptions-item>
<el-descriptions-item label="领衔人">{{form.leadPeople}}</el-descriptions-item>
<el-descriptions-item label="领衔人年龄">{{form.leadAge}}</el-descriptions-item>
<el-descriptions-item label="领衔人身份">{{Array.isArray(form.leadIdentity) ? form.leadIdentity.join(',') : form.leadIdentity}}</el-descriptions-item>
<el-descriptions-item label="领衔人荣誉">{{form.leadHonor}}</el-descriptions-item>
<el-descriptions-item label="工作室类型">{{form.type}}</el-descriptions-item>
<el-descriptions-item label="工作室赛道">{{form.track}}</el-descriptions-item>
<el-descriptions-item label="工作室地址" :span="2">{{form.address}}</el-descriptions-item>
<el-descriptions-item label="工作室介绍" :span="2">{{form.introduction}}</el-descriptions-item>
<el-descriptions-item label="备注" :span="2">{{form.remark}}</el-descriptions-item>
</el-descriptions>
</el-tab-pane>
<el-tab-pane name="members" label="成员信息">
<div class="brand-member-toolbar">
<span>成员人数:{{(form.brandStudioMembers || []).length}}</span>
<div>
<el-button type="primary" size="small" @click="openMemberDialog">选择成员</el-button>
<el-button type="primary" size="small" :loading="savingMembers" @click="saveMembers">保存人员</el-button>
</div>
</div>
<el-table :data="form.brandStudioMembers || []" border size="small">
<el-table-column label="姓名" prop="name" width="120"></el-table-column>
<el-table-column label="出生年月" prop="birthdate" width="180">
<template slot-scope="{row}">
<el-date-picker v-model="row.birthdate" type="month" value-format="yyyy-MM" style="width: 100%"></el-date-picker>
</template>
</el-table-column>
<el-table-column label="学位" prop="grade" min-width="180">
<template slot-scope="{row}">
<el-select v-model="row.grade" style="width: 100%">
<el-option v-for="item in memberDegreeDict" :key="item.value || item.code" :label="item.label || item.name" :value="item.value || item.code"></el-option>
</el-select>
</template>
</el-table-column>
<el-table-column label="职称" prop="professional" min-width="180">
<template slot-scope="{row}">
<el-input v-model="row.professional"></el-input>
</template>
</el-table-column>
<el-table-column label="所在单位" prop="deptName" min-width="180"></el-table-column>
<el-table-column label="操作" width="90">
<template slot-scope="scope">
<el-button size="mini" type="danger" @click="removeMember(scope.$index)">删除</el-button>
</template>
</el-table-column>
</el-table>
</el-tab-pane>
<el-tab-pane name="honors" label="荣誉信息">
<div class="brand-member-toolbar">
<span>荣誉数量:{{(form.brandStudioHonors || []).length}}</span>
<div>
<el-button type="primary" size="small" @click="addHonor">添加荣誉</el-button>
<el-button type="primary" size="small" :loading="savingHonors" @click="saveHonors">保存荣誉</el-button>
</div>
</div>
<el-table :data="form.brandStudioHonors || []" border size="small">
<el-table-column label="荣誉称号" prop="honorName" min-width="160">
<template slot-scope="{row}">
<el-input v-model="row.honorName"></el-input>
</template>
</el-table-column>
<el-table-column label="获取年度" prop="requireYear" min-width="180">
<template slot-scope="{row}">
<el-date-picker v-model="row.requireYear" type="year" value-format="yyyy" style="width: 100%"></el-date-picker>
</template>
</el-table-column>
<el-table-column label="荣誉类别" prop="honorCategory" min-width="180">
<template slot-scope="{row}">
<el-select v-model="row.honorCategory" style="width: 100%">
<el-option label="外部荣誉" :value="1"></el-option>
<el-option label="行内荣誉" :value="2"></el-option>
</el-select>
</template>
</el-table-column>
<el-table-column label="操作" min-width="160">
<template slot-scope="scope">
<el-button size="mini" type="danger" @click="removeHonor(scope.$index)">删除</el-button>
</template>
</el-table-column>
</el-table>
</el-tab-pane>
</el-tabs>
<el-row type="flex" justify="end" class="brand-detail-actions">
</el-row>
</div>
</template>
</guava>
<el-dialog title="选择工作室成员" :visible.sync="memberDialogVisible" width="760px" class="brand-member-dialog">
<div class="brand-member-search">
<el-input v-model="memberKeyword" placeholder="请输入姓名或工号" clearable @keyup.enter.native="loadMemberCandidates"></el-input>
<el-button type="primary" icon="el-icon-search" @click="loadMemberCandidates">查询</el-button>
</div>
<el-table :data="memberCandidates" border size="small" height="360" @selection-change="memberSelectionChange">
<el-table-column type="selection" width="55"></el-table-column>
<el-table-column prop="loginname" label="工号" width="120"></el-table-column>
<el-table-column prop="username" label="姓名" width="120"></el-table-column>
<el-table-column prop="unitName" label="所在单位" show-overflow-tooltip></el-table-column>
</el-table>
</el-card>
<div slot="footer">
<el-button @click="memberDialogVisible = false">取消</el-button>
<el-button type="primary" @click="confirmSelectMembers">确定</el-button>
</div>
</el-dialog>
</div>
<script nonce="${cspNonce!}">
@@ -44,7 +163,20 @@ layout("/layouts/platform.html"){
status: 5,
createYear: String(new Date().getFullYear())
},
tableData: []
tableData: [],
activeName: 'base',
savingMembers: false,
savingHonors: false,
form: {
brandStudioMembers: [],
brandStudioHonors: [],
leadIdentity: []
},
memberDegreeDict: [],
memberDialogVisible: false,
memberKeyword: '',
memberCandidates: [],
selectedMemberCandidates: []
}
},
methods: {
@@ -57,16 +189,157 @@ layout("/layouts/platform.html"){
this.tableData = data.list || data.data || []
})
},
openApply(id) {
window.location.href = '/platform/zhgh/brand/apply/index?id=' + id
loadDictOptions(code) {
return this.$axios.get('/open/common/dictOptions', {params: {code: code}}).then((res) => {
return this.getData(res) || []
})
},
loadDicts() {
Promise.all([
this.loadDictOptions('USER_ACADEMIC_DEGREE')
]).then(([memberDegreeDict]) => {
this.memberDegreeDict = memberDegreeDict
})
},
openDetail(row) {
this.$refs.guava.public(() => {
this.activeName = 'base'
this.$axios.get('/platform/zhgh/brand/application/' + row.id).then((res) => {
const data = this.getData(res) || {}
data.brandStudioMembers = data.brandStudioMembers || []
data.brandStudioHonors = data.brandStudioHonors || []
data.memberNum = data.brandStudioMembers.length
data.leadIdentity = data.leadIdentity ? data.leadIdentity.split(',') : []
this.form = data
})
})
},
openMemberDialog() {
this.memberDialogVisible = true
this.selectedMemberCandidates = []
this.loadMemberCandidates()
},
loadMemberCandidates() {
this.$axios.get('/platform/zhgh/brand/application/members', {
params: {
unionId: this.form.unionId,
keyword: this.memberKeyword
}
}).then((res) => {
this.memberCandidates = this.getData(res) || []
})
},
memberSelectionChange(selection) {
this.selectedMemberCandidates = selection
},
confirmSelectMembers() {
if (!this.selectedMemberCandidates.length) {
this.$message.warning('请至少选择一位工作室成员')
return
}
const existingIds = new Set((this.form.brandStudioMembers || []).map(item => item.userId || item.id))
const members = this.selectedMemberCandidates
.filter(item => !existingIds.has(item.id))
.map(item => ({
userId: item.id,
emplid: item.emplid || item.loginname,
name: item.name || item.username,
role: '',
birthdate: item.birthdate,
grade: item.grade,
professional: item.professional,
deptName: item.deptName || item.unitName
}))
this.form.brandStudioMembers = [...(this.form.brandStudioMembers || []), ...members]
this.form.memberNum = this.form.brandStudioMembers.length
this.memberDialogVisible = false
},
removeMember(index) {
this.form.brandStudioMembers.splice(index, 1)
this.form.memberNum = this.form.brandStudioMembers.length
},
addHonor() {
this.form.brandStudioHonors = this.form.brandStudioHonors || []
this.form.brandStudioHonors.push({
applicationId: this.form.id,
honorName: '',
requireYear: String(new Date().getFullYear()),
honorCategory: 1
})
},
removeHonor(index) {
this.form.brandStudioHonors.splice(index, 1)
},
buildSaveParams() {
const params = Object.assign({}, this.form)
params.status = 5
params.leadIdentity = (params.leadIdentity || []).join(',')
params.domain = params.track
params.memberNum = (params.brandStudioMembers || []).length
params.brandStudioMembersJson = JSON.stringify(params.brandStudioMembers || [])
delete params.brandStudioMembers
return params
},
saveMembers() {
this.savingMembers = true
const params = this.buildSaveParams()
this.$axios.post('/platform/zhgh/brand/application/honor', params).then(() => {
this.$message.success('保存人员成功')
this.pageData()
}).finally(() => {
this.savingMembers = false
})
},
saveHonors() {
this.savingHonors = true
const params = this.buildSaveParams()
params.brandStudioHonors = (this.form.brandStudioHonors || []).map(item => ({
applicationId: this.form.id,
honorName: item.honorName,
honorGrade: item.honorGrade,
requireYear: item.requireYear,
honorCategory: item.honorCategory
}))
params.brandStudioHonorsJson = JSON.stringify(params.brandStudioHonors)
this.$axios.post('/platform/zhgh/brand/application/honor', params).then(() => {
this.$message.success('保存荣誉成功')
this.pageData()
}).finally(() => {
this.savingHonors = false
})
}
},
created() {
this.loadDicts()
this.pageData()
}
})
</script>
<style>
.brand-detail-actions {
margin-top: 16px;
}
.brand-member-toolbar {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 12px;
}
.brand-member-search {
display: flex;
gap: 10px;
margin-bottom: 12px;
}
.brand-member-search .el-input {
flex: 1;
}
.brand-member-dialog .el-dialog__body {
padding-top: 12px;
padding-bottom: 12px;
}
</style>
<!--#
}
#-->
@@ -3,82 +3,264 @@ layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<el-card shadow="never">
<el-form :inline="true" :model="pageForm">
<el-form-item label="工作室名称">
<el-input v-model="pageForm.name" clearable></el-input>
</el-form-item>
<el-form-item label="创建年份">
<el-date-picker v-model="pageForm.createYear" type="year" value-format="yyyy"></el-date-picker>
</el-form-item>
<el-form-item label="审核状态">
<el-select v-model="pageForm.processStatus" clearable>
<el-option label="待审核" :value="1"></el-option>
<el-option label="已审核" :value="5"></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="pageData">查询</el-button>
</el-form-item>
</el-form>
<el-table :data="tableData" border>
<el-table-column type="index" label="序号" width="60"></el-table-column>
<el-table-column prop="name" label="工作室名称" min-width="160"></el-table-column>
<el-table-column prop="createYear" label="创立年度" width="100"></el-table-column>
<el-table-column prop="leadPeople" label="领衔人" width="120"></el-table-column>
<el-table-column prop="deptName" label="所属机构" min-width="140"></el-table-column>
<el-table-column prop="processTaskNode" label="审核节点" width="140"></el-table-column>
<el-table-column prop="processTaskReason" label="任务状态" width="100"></el-table-column>
<el-table-column label="操作" width="180">
<template slot-scope="{row}">
<el-button type="text" @click="audit(row, 'PASS')" v-if="row.processTaskReason==='ACTIVE'">通过</el-button>
<el-button type="text" @click="audit(row, 'REJECT')" v-if="row.processTaskReason==='ACTIVE'">驳回</el-button>
</template>
</el-table-column>
</el-table>
</el-card>
<guava ref="guava">
<el-card shadow="never">
<search @search="doSearch">
<search-item label="创立年度:">
<el-date-picker
placeholder="选择创立年度"
type="year"
style="width: 100%"
v-model="pageForm.createYear"
value-format="yyyy"
></el-date-picker>
</search-item>
<search-item label="工作室名称:">
<el-input
@keyup.enter.native="doSearch"
clearable
placeholder="请输入工作室名称"
style="width: 100%"
v-model="pageForm.name"
></el-input>
</search-item>
</search>
</el-card>
<el-card shadow="never" class="mt10">
<table-tool label="申请列表">
<el-radio-group @change="doSearch" size="small" v-model="pageForm.audit">
<el-radio-button :label="true">已审核</el-radio-button>
<el-radio-button :label="false">未审核</el-radio-button>
</el-radio-group>
</table-tool>
<el-table :data="tableData" :size="tableSize">
<el-table-column :index="indexMethod" label="序号" type="index" width="80px"></el-table-column>
<el-table-column label="工作室名称" prop="name" sortable show-overflow-tooltip min-width="180"></el-table-column>
<el-table-column label="创立年度" prop="createYear" sortable show-overflow-tooltip width="120"></el-table-column>
<el-table-column label="领衔人" prop="leadPeople" sortable show-overflow-tooltip width="120"></el-table-column>
<el-table-column label="所在单位" prop="deptName" sortable show-overflow-tooltip min-width="180"></el-table-column>
<el-table-column label="工作室类型" prop="type" sortable show-overflow-tooltip min-width="140"></el-table-column>
<el-table-column label="工作室赛道" prop="track" sortable show-overflow-tooltip min-width="140"></el-table-column>
<el-table-column label="成员人数" prop="memberNum" sortable show-overflow-tooltip width="110"></el-table-column>
<el-table-column label="工作室地址" prop="address" show-overflow-tooltip min-width="220"></el-table-column>
<el-table-column label="当前节点" prop="curTaskName" show-overflow-tooltip min-width="180"></el-table-column>
<el-table-column label="审核时间" prop="finishTime" show-overflow-tooltip min-width="180">
<template v-slot="{ row }">
<span>{{ row.finishTime ? $moment(row.finishTime).format('YYYY-MM-DD HH:mm:ss') : '-' }}</span>
</template>
</el-table-column>
<el-table-column label="流程状态" prop="instanceState" show-overflow-tooltip min-width="180">
<template v-slot="{ row }">
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message" size="small"></enum-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="180">
<template v-slot="{row}">
<el-button @click="onView(row)" size="mini" type="primary">查看</el-button>
<el-button v-if="row.taskState === 10" @click="onAudit(row)" size="mini" type="primary">审核</el-button>
<el-button v-if="row.canRevoke" @click="onRevoke(row)" size="mini" type="danger">撤回</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<template #public>
<div>
<el-tabs tab-position="top" v-model="activeName">
<el-tab-pane name="1" label="基础信息">
<div class="process-title">
品牌工作室申请
<el-link type="primary" @click="openChart">点击查看流程图</el-link>
</div>
<el-descriptions :column="2" border>
<el-descriptions-item label="工作室名称">{{detail.name}}</el-descriptions-item>
<el-descriptions-item label="创立年度">{{detail.createYear}}</el-descriptions-item>
<el-descriptions-item label="所属工会">{{detail.unionName}}</el-descriptions-item>
<el-descriptions-item label="所在单位">{{detail.deptName}}</el-descriptions-item>
<el-descriptions-item label="领衔人">{{detail.leadPeople}}</el-descriptions-item>
<el-descriptions-item label="领衔人年龄">{{detail.leadAge}}</el-descriptions-item>
<el-descriptions-item label="领衔人身份">{{detail.leadIdentity}}</el-descriptions-item>
<el-descriptions-item label="领衔人荣誉">{{detail.leadHonor}}</el-descriptions-item>
<el-descriptions-item label="工作室类型">{{detail.type}}</el-descriptions-item>
<el-descriptions-item label="所属赛道">{{detail.track}}</el-descriptions-item>
<el-descriptions-item label="工作室地址" :span="2">{{detail.address}}</el-descriptions-item>
<el-descriptions-item label="工作室介绍" :span="2">{{detail.introduction}}</el-descriptions-item>
<el-descriptions-item label="备注" :span="2">{{detail.remark}}</el-descriptions-item>
</el-descriptions>
<snaker-chart ref="snakerChartRef"></snaker-chart>
<div v-if="showApprovalForm">
<div class="process-title">
{{formData.taskName}}
</div>
<el-form :model="formData" ref="formRef" label-width="0" label-suffix="" class="flow-task-form">
<el-form-item label="审批意见" prop="remark"
:rules="[{required:true,message:'必填',trigger:['change','blur']}]">
<user-opinion-textarea v-model="formData.remark"></user-opinion-textarea>
</el-form-item>
</el-form>
<el-row type="flex" justify="end">
<el-button @click="handleTaskAction(1)" size="small" type="primary">同意申请</el-button>
<el-button @click="handleTaskAction(2)" size="small" type="danger">拒绝申请</el-button>
<el-button @click="handleTaskAction(6)" size="small" type="info">退回到发起人</el-button>
<el-button @click="$refs.guava.index()" size="small">取消</el-button>
</el-row>
</div>
</el-tab-pane>
<el-tab-pane name="2" label="成员信息">
<div class="process-title">成员信息</div>
<el-table :data="detail.brandStudioMembers || []" border size="small">
<el-table-column label="姓名" prop="name" width="120"></el-table-column>
<el-table-column label="出生年月" prop="birthdate" width="120"></el-table-column>
<el-table-column label="学位" prop="grade" show-overflow-tooltip></el-table-column>
<el-table-column label="职称" prop="professional" show-overflow-tooltip></el-table-column>
<el-table-column label="所在单位" prop="deptName" show-overflow-tooltip></el-table-column>
</el-table>
</el-tab-pane>
<el-tab-pane name="3" label="审核记录">
<template v-if="doneTasks.length > 0" v-for="task in doneTasks">
<div class="mt10">
<div class="process-title">{{ task.displayName }}</div>
<el-descriptions border class="flow-task-form" :column="3" :key="task.id"
v-if="task.ext.isFirstTaskNode">
<el-descriptions-item label="申请用户">{{ task.ext.initiatorName }}({{task.ext.initiatorAccount}})</el-descriptions-item>
<el-descriptions-item label="申请时间">{{ task.finishTime }}</el-descriptions-item>
<el-descriptions-item label="办理结果">
<dict-tag :options="dict.type.PROCESS_TASK_SUBMIT_TYPE" :value="task.ext.submitType"></dict-tag>
</el-descriptions-item>
</el-descriptions>
<el-descriptions border class="flow-task-form" :column="3" :key="task.id" v-else>
<el-descriptions-item label="办理用户">{{ task.taskFormData.userName }}({{task.taskFormData.loginName}})</el-descriptions-item>
<el-descriptions-item label="办理时间">{{ task.finishTime }}</el-descriptions-item>
<el-descriptions-item label="办理结果">
<dict-tag :options="dict.type.PROCESS_TASK_SUBMIT_TYPE" :value="task.ext.submitType"></dict-tag>
</el-descriptions-item>
<el-descriptions-item label="办理意见" v-if="!task.ext.isFirstTaskNode">{{ task.taskFormData.opinion || task.taskFormData.remark || task.taskFormData.approvalComment }}</el-descriptions-item>
</el-descriptions>
</div>
</template>
<template v-else>
<el-empty description="暂无审核记录"></el-empty>
</template>
</el-tab-pane>
</el-tabs>
</div>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
new Vue({
el: "#app",
mixins: [initTableMixins],
dicts: ["PROCESS_TASK_SUBMIT_TYPE"],
data() {
return {
pageForm: {
page: 1,
limit: 20,
processStatus: 1,
audit: false,
createYear: String(new Date().getFullYear())
},
tableData: []
detail: {},
formData: {},
currentRow: {},
showApprovalForm: false,
activeName: "1",
doneTasks: []
}
},
methods: {
getData(res) {
return res.data && res.data.data !== undefined ? res.data.data : res.data
},
pageData() {
this.$axios.get('/platform/zhgh/brand/application/auditPage', {params: this.pageForm}).then((res) => {
const data = this.getData(res) || {}
this.tableData = data.list || data.data || []
onView(row) {
this.$refs.guava.public(() => {
this.currentRow = row
this.activeName = "1"
this.showApprovalForm = false
this.loadDetail(row.id)
this.getDoneTasks(row)
})
},
audit(row, type) {
this.$prompt('请输入审批意见', '审批', {
inputType: 'textarea',
inputValue: type === 'PASS' ? '同意' : ''
}).then(({value}) => {
this.$axios.post('/platform/zhgh/brand/flow/audit', {
onAudit(row) {
this.$refs.guava.public(() => {
this.currentRow = row
this.activeName = "1"
this.formData = {
applicationId: row.id,
processInstanceId: row.processInstanceId,
processInstanceTaskId: row.processInstanceTaskId || row.flowId,
bpmTaskApprovalType: type,
remark: value
}).then(() => {
this.$message.success('操作成功')
this.pageData()
processInstanceTaskId: row.processInstanceTaskId || row.taskId,
taskName: row.curTaskName,
remark: ''
}
this.showApprovalForm = true
this.loadDetail(row.id)
this.getDoneTasks(row)
})
},
loadDetail(id) {
this.$axios.get('/platform/zhgh/brand/application/' + id).then((res) => {
this.detail = this.getData(res) || {}
this.detail.brandStudioMembers = this.detail.brandStudioMembers || []
})
},
getDoneTasks(row) {
this.$axios.post('/flow/common/doneTasks', {
instanceId: row.processInstanceId || row.instanceId,
bizId: row.id
}).then((res) => {
if (res.code === 0) {
this.doneTasks = res.data || []
}
})
},
openChart() {
if (!this.currentRow.processInstanceId || !this.currentRow.instanceProcessDefineId) {
this.$message.warning('暂无流程图信息')
return
}
this.$refs.snakerChartRef.onOpenFull(this.currentRow.instanceProcessDefineId, this.currentRow.processInstanceId)
},
handleTaskAction(val) {
this.$confirm("您确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post('/platform/zhgh/brand/flow/audit', {
...this.formData,
submitType: val
}).then((res) => {
if (res.code === 0) {
this.$refs.guava.index()
this.$message.success(res.msg)
this.doSearch()
}
})
})
},
onRevoke(row) {
this.$confirm("您确定要撤回吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "info"
}).then(() => {
this.$axios.post("/flow/common/revokeTask", {taskId: row.taskId}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.doSearch()
}
})
})
},
async pageData() {
const resp = await this.$axios.post('/platform/zhgh/brand/application/auditPage', this.pageForm)
if (resp.code === 0) {
this.tableData = resp.data.list
this.pageForm.totalCount = resp.data.totalCount
} else {
this.$message.warning(resp.msg)
}
}
},
created() {
@@ -3,31 +3,87 @@ layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<el-card shadow="never">
<el-form :inline="true" :model="pageForm">
<el-form-item label="工作室名称">
<el-input v-model="pageForm.name" clearable></el-input>
</el-form-item>
<el-form-item label="创建年份">
<el-date-picker v-model="pageForm.createYear" type="year" value-format="yyyy"></el-date-picker>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="pageData">查询</el-button>
</el-form-item>
</el-form>
<el-table :data="tableData" border>
<el-table-column type="index" label="序号" width="60"></el-table-column>
<el-table-column prop="deptName" label="一级机构" min-width="120"></el-table-column>
<el-table-column prop="name" label="工作室名称" min-width="160"></el-table-column>
<el-table-column prop="leadPeople" label="领衔人" width="120"></el-table-column>
<el-table-column prop="honorName" label="外部荣誉称号" min-width="150"></el-table-column>
<el-table-column prop="createYear" label="创立年度" width="100"></el-table-column>
<el-table-column prop="track" label="所属领域" width="120"></el-table-column>
<el-table-column prop="leadHonor" label="领衔人荣誉称号" min-width="160"></el-table-column>
<el-table-column prop="memberNum" label="成员人数" width="90"></el-table-column>
<el-table-column prop="address" label="工作室地址" min-width="160"></el-table-column>
</el-table>
</el-card>
<guava ref="guava">
<el-card shadow="never">
<el-form :inline="true" :model="pageForm">
<el-form-item label="创立年度">
<el-date-picker v-model="pageForm.createYear" type="year" value-format="yyyy"></el-date-picker>
</el-form-item>
<el-form-item label="工作室名称">
<el-input v-model="pageForm.name" clearable></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="pageData">查询</el-button>
</el-form-item>
</el-form>
</el-card>
<el-card shadow="never" class="mt10">
<table-tool label="工作室台账"></table-tool>
<el-table :data="tableData" border style="width: 100%">
<el-table-column type="index" label="序号" width="60"></el-table-column>
<el-table-column prop="name" label="工作室名称" min-width="160"></el-table-column>
<el-table-column prop="createYear" label="创立年度" width="100"></el-table-column>
<el-table-column prop="leadPeople" label="领衔人" width="120"></el-table-column>
<el-table-column prop="deptName" label="所在单位" min-width="140"></el-table-column>
<el-table-column prop="honorName" label="荣誉称号" min-width="150"></el-table-column>
<el-table-column prop="track" label="所属领域" width="120"></el-table-column>
<el-table-column prop="leadHonor" label="领衔人荣誉称号" min-width="160"></el-table-column>
<el-table-column prop="memberNum" label="成员人数" width="90"></el-table-column>
<el-table-column prop="address" label="工作室地址" min-width="180"></el-table-column>
<el-table-column label="操作" width="90" fixed="right">
<template slot-scope="{row}">
<el-button size="mini" type="primary" @click="openView(row)">查看</el-button>
</template>
</el-table-column>
</el-table>
</el-card>
<template #public>
<div>
<div class="process-title">查看品牌工作室</div>
<el-tabs v-model="activeName">
<el-tab-pane name="base" label="基本信息">
<el-descriptions :column="2" border>
<el-descriptions-item label="工作室名称">{{form.name}}</el-descriptions-item>
<el-descriptions-item label="创立年度">{{form.createYear}}</el-descriptions-item>
<el-descriptions-item label="所属工会">{{form.unionName}}</el-descriptions-item>
<el-descriptions-item label="所在单位">{{form.deptName}}</el-descriptions-item>
<el-descriptions-item label="领衔人">{{form.leadPeople}}</el-descriptions-item>
<el-descriptions-item label="领衔人年龄">{{form.leadAge}}</el-descriptions-item>
<el-descriptions-item label="领衔人身份">{{form.leadIdentity}}</el-descriptions-item>
<el-descriptions-item label="领衔人荣誉">{{form.leadHonor}}</el-descriptions-item>
<el-descriptions-item label="工作室类型">{{form.type}}</el-descriptions-item>
<el-descriptions-item label="所属领域">{{form.track}}</el-descriptions-item>
<el-descriptions-item label="工作室地址" :span="2">{{form.address}}</el-descriptions-item>
<el-descriptions-item label="工作室介绍" :span="2">{{form.introduction}}</el-descriptions-item>
<el-descriptions-item label="备注" :span="2">{{form.remark}}</el-descriptions-item>
</el-descriptions>
</el-tab-pane>
<el-tab-pane name="members" label="成员信息">
<el-table :data="form.brandStudioMembers || []" border size="small">
<el-table-column label="姓名" prop="name" width="120"></el-table-column>
<el-table-column label="出生年月" prop="birthdate" width="120"></el-table-column>
<el-table-column label="学位" prop="grade" show-overflow-tooltip></el-table-column>
<el-table-column label="职称" prop="professional" show-overflow-tooltip></el-table-column>
<el-table-column label="所在单位" prop="deptName" show-overflow-tooltip></el-table-column>
</el-table>
</el-tab-pane>
<el-tab-pane name="honors" label="荣誉信息">
<el-table :data="form.brandStudioHonors || []" border size="small">
<el-table-column label="荣誉称号" prop="honorName" min-width="160"></el-table-column>
<el-table-column label="获取年度" prop="requireYear" min-width="120"></el-table-column>
<el-table-column label="荣誉类别" prop="honorCategory" min-width="120">
<template slot-scope="{row}">
<span>{{row.honorCategory === 1 ? '外部荣誉' : (row.honorCategory === 2 ? '行内荣誉' : row.honorCategory)}}</span>
</template>
</el-table-column>
</el-table>
</el-tab-pane>
</el-tabs>
</div>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
@@ -38,9 +94,15 @@ layout("/layouts/platform.html"){
pageForm: {
page: 1,
limit: 20,
status: 5
status: 5,
createYear: String(new Date().getFullYear())
},
tableData: []
tableData: [],
activeName: 'base',
form: {
brandStudioMembers: [],
brandStudioHonors: []
}
}
},
methods: {
@@ -52,6 +114,17 @@ layout("/layouts/platform.html"){
const data = this.getData(res) || {}
this.tableData = data.list || data.data || []
})
},
openView(row) {
this.$refs.guava.public(() => {
this.activeName = 'base'
this.$axios.get('/platform/zhgh/brand/application/' + row.id).then((res) => {
const data = this.getData(res) || {}
data.brandStudioMembers = data.brandStudioMembers || []
data.brandStudioHonors = data.brandStudioHonors || []
this.form = data
})
})
}
},
created() {