Compare commits

...
12 changed files with 1492 additions and 261 deletions
@@ -106,6 +106,7 @@ RoleConstant {
LEGAL_DOCTOR("法律顾问"), LEGAL_DOCTOR("法律顾问"),
UNION_REIMBURSEMENT_MANAGER("分工会报销负责人"), UNION_REIMBURSEMENT_MANAGER("分工会报销负责人"),
UNION_TEMP_REIMBURSEMENT_APPLICANT("分工会临时报销人"),
CLUB_REIMBURSEMENT_MANAGER("协会报销负责人"), CLUB_REIMBURSEMENT_MANAGER("协会报销负责人"),
SCHOOL_REIMBURSEMENT_MANAGER("校工会报销负责人"), SCHOOL_REIMBURSEMENT_MANAGER("校工会报销负责人"),
@@ -161,7 +161,7 @@ public class FlowDesignController {
return Result.success(); return Result.success();
} }
@At @At("/xiugaiDesign")
@ApiOperation("修改流程设计") @ApiOperation("修改流程设计")
@SaCheckPermission("flow.design") @SaCheckPermission("flow.design")
public Result updateContent(@Param("design") ProcessDesign processDesign) { public Result updateContent(@Param("design") ProcessDesign processDesign) {
@@ -7,7 +7,6 @@ import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.budwk.app.base.annotation.SLog; import com.budwk.app.base.annotation.SLog;
import com.budwk.app.base.constant.RoleConstant;
import com.budwk.app.base.page.Pagination; import com.budwk.app.base.page.Pagination;
import com.budwk.app.base.result.Result; import com.budwk.app.base.result.Result;
import com.budwk.app.base.utils.PageUtil; import com.budwk.app.base.utils.PageUtil;
@@ -23,6 +22,7 @@ import com.budwk.app.zhgh.activity.declarereimbursement.declare.models.ActivityD
import com.budwk.app.zhgh.activity.declarereimbursement.vo.CommonPageParam; import com.budwk.app.zhgh.activity.declarereimbursement.vo.CommonPageParam;
import com.budwk.app.zhgh.activity.declarereimbursement.reimbursement.models.ActivityReimbursementInfo; import com.budwk.app.zhgh.activity.declarereimbursement.reimbursement.models.ActivityReimbursementInfo;
import com.budwk.app.zhgh.activity.declarereimbursement.reimbursement.service.ActivityReimbursementService; import com.budwk.app.zhgh.activity.declarereimbursement.reimbursement.service.ActivityReimbursementService;
import com.budwk.app.zhgh.dayofficework.outlay.activityBudget.models.ActivityBudget;
import com.budwk.app.zhgh.dayofficework.outlay.outlayReimburse.service.OutlayReimburseApplyService; import com.budwk.app.zhgh.dayofficework.outlay.outlayReimburse.service.OutlayReimburseApplyService;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import org.nutz.aop.interceptor.ioc.TransAop; import org.nutz.aop.interceptor.ioc.TransAop;
@@ -94,6 +94,10 @@ public class ActivityReimbursementApplyController {
@SaCheckPermission(value = {"activityReimbursement.apply", "h5.activityReimbursement.apply"}, mode = SaMode.OR) @SaCheckPermission(value = {"activityReimbursement.apply", "h5.activityReimbursement.apply"}, mode = SaMode.OR)
@SLog(tag = "活动申报", msg = "保存申请,申请人: ${args[0].username}") @SLog(tag = "活动申报", msg = "保存申请,申请人: ${args[0].username}")
public Result save(@Param("data") ActivityReimbursementInfo activityReimbursementInfo) { public Result save(@Param("data") ActivityReimbursementInfo activityReimbursementInfo) {
Result scopeResult = validateReimbursementIdentity(activityReimbursementInfo);
if (scopeResult != null) {
return scopeResult;
}
activityReimbursementInfo.setUserId(SecurityUtil.getUserId()); activityReimbursementInfo.setUserId(SecurityUtil.getUserId());
activityReimbursementInfo.setLoginName(SecurityUtil.getUserLoginname()); activityReimbursementInfo.setLoginName(SecurityUtil.getUserLoginname());
activityReimbursementInfo.setUserName(SecurityUtil.getUserUsername()); activityReimbursementInfo.setUserName(SecurityUtil.getUserUsername());
@@ -123,6 +127,10 @@ public class ActivityReimbursementApplyController {
@SaCheckPermission(value = {"activityReimbursement.apply", "h5.activityReimbursement.apply"}, mode = SaMode.OR) @SaCheckPermission(value = {"activityReimbursement.apply", "h5.activityReimbursement.apply"}, mode = SaMode.OR)
@SLog(tag = "活动申报", msg = "提交申请,申请人: ${args[0].username}") @SLog(tag = "活动申报", msg = "提交申请,申请人: ${args[0].username}")
public Result submit(@Param("data") ActivityReimbursementInfo activityReimbursementInfo) { public Result submit(@Param("data") ActivityReimbursementInfo activityReimbursementInfo) {
Result scopeResult = validateReimbursementIdentity(activityReimbursementInfo);
if (scopeResult != null) {
return scopeResult;
}
activityReimbursementInfo.setUserId(SecurityUtil.getUserId()); activityReimbursementInfo.setUserId(SecurityUtil.getUserId());
activityReimbursementInfo.setLoginName(SecurityUtil.getUserLoginname()); activityReimbursementInfo.setLoginName(SecurityUtil.getUserLoginname());
activityReimbursementInfo.setUserName(SecurityUtil.getUserUsername()); activityReimbursementInfo.setUserName(SecurityUtil.getUserUsername());
@@ -151,6 +159,7 @@ public class ActivityReimbursementApplyController {
args.set(FlowConst.FORM_DATA, activityReimbursementInfo); args.set(FlowConst.FORM_DATA, activityReimbursementInfo);
args.set("outlayManageSource", activityReimbursementInfo.getOutlayManageSource()); args.set("outlayManageSource", activityReimbursementInfo.getOutlayManageSource());
args.set("actualMoney", activityReimbursementInfo.getActualMoney()); args.set("actualMoney", activityReimbursementInfo.getActualMoney());
// 审批分支由本次选择的报销身份决定,不因兼有临时报销角色而改变。
args.set("next", activityReimbursementInfo.getReimbursementIdentity()); args.set("next", activityReimbursementInfo.getReimbursementIdentity());
args.set("clubId",activityReimbursementInfo.getClubId()); args.set("clubId",activityReimbursementInfo.getClubId());
ProcessInstance instance = flowEngine.startProcessInstanceByKey("HDBX", activityReimbursementInfo.getId(), SecurityUtil.getUserId(), args); ProcessInstance instance = flowEngine.startProcessInstanceByKey("HDBX", activityReimbursementInfo.getId(), SecurityUtil.getUserId(), args);
@@ -170,6 +179,10 @@ public class ActivityReimbursementApplyController {
@SaCheckPermission(value = {"activityReimbursement.apply", "h5.activityReimbursement.apply"}, mode = SaMode.OR) @SaCheckPermission(value = {"activityReimbursement.apply", "h5.activityReimbursement.apply"}, mode = SaMode.OR)
@SLog(tag = "活动申报", msg = "重新提交申请,申请人: ${args[0].username}") @SLog(tag = "活动申报", msg = "重新提交申请,申请人: ${args[0].username}")
public Result submitAgain(@Param("data") ActivityReimbursementInfo activityReimbursementInfo, @Param("taskId") Long taskId) { public Result submitAgain(@Param("data") ActivityReimbursementInfo activityReimbursementInfo, @Param("taskId") Long taskId) {
Result scopeResult = validateReimbursementIdentity(activityReimbursementInfo);
if (scopeResult != null) {
return scopeResult;
}
if (StrUtil.isBlank(activityReimbursementInfo.getDeclareId())) { if (StrUtil.isBlank(activityReimbursementInfo.getDeclareId())) {
activityReimbursementInfo.setDeclareId(activityReimbursementInfo.getDeclareId()); activityReimbursementInfo.setDeclareId(activityReimbursementInfo.getDeclareId());
} }
@@ -191,11 +204,95 @@ public class ActivityReimbursementApplyController {
Dict dict = Dict.create(); Dict dict = Dict.create();
dict.set(FlowConst.PROCESS_TASK_ID_KEY, taskId); dict.set(FlowConst.PROCESS_TASK_ID_KEY, taskId);
dict.set(FlowConst.SUBMIT_TYPE, ProcessSubmitTypeEnum.RE_APPLY.getCode()); dict.set(FlowConst.SUBMIT_TYPE, ProcessSubmitTypeEnum.RE_APPLY.getCode());
dict.set("next", activityReimbursementInfo.getReimbursementIdentity());
flowCommonService.executeTask(dict); flowCommonService.executeTask(dict);
return Result.success(); return Result.success();
} }
/**
* 按角色关联的菜单权限校验报销身份,代报销沿用所选经费的预算范围。
*/
private Result validateReimbursementIdentity(ActivityReimbursementInfo info) {
if (info == null || StrUtil.isBlank(info.getReimbursementIdentity())) {
return Result.error("请选择报销身份");
}
String permission = switch (info.getReimbursementIdentity()) {
case "school" -> "activityReimbursement.apply.schoolHas";
case "union" -> "activityReimbursement.apply.unionHas";
case "club" -> "activityReimbursement.apply.clubHas";
case "unionTemp" -> "activityReimbursement.apply.unionTempHas";
default -> null;
};
if (permission == null || !AuthUtil.hasPermission(permission)) {
return Result.error("无权使用所选报销身份");
}
if (!Objects.equals(info.getReimbursementIdentity(), "unionTemp")) {
return null;
}
String unionId = SecurityUtil.getUnionId();
if (StrUtil.isBlank(unionId)) {
return Result.error("当前用户未关联分工会,无法申请代报销");
}
if (StrUtil.isNotBlank(info.getId())) {
ActivityReimbursementInfo savedInfo = dao.fetch(ActivityReimbursementInfo.class, info.getId());
if (savedInfo == null || !Objects.equals(savedInfo.getUserId(), SecurityUtil.getUserId())
|| !Objects.equals(savedInfo.getUnionId(), unionId)) {
return Result.error("仅可修改本人所在分工会的报销申请");
}
}
String source = info.getOutlayManageSource();
String activityType;
if (Objects.equals(source, "ACTIVITY_BUDGET_TYPE_ONE")) {
activityType = "SCHOOL_UNION";
} else if (Objects.equals(source, "ACTIVITY_BUDGET_TYPE_TWO")) {
activityType = "BRANCH_UNION";
} else if (Objects.equals(source, "ACTIVITY_BUDGET_TYPE_THREE")
&& (AuthUtil.hasPermission("activityReimbursement.apply.schoolHas")
|| AuthUtil.hasPermission("activityReimbursement.apply.clubHas"))) {
activityType = "CLUB";
} else {
return Result.error("请选择有权限使用的经费类型");
}
if (StrUtil.isBlank(info.getDeductionBudgetId())) {
return Result.error("请选择扣款预算");
}
ActivityBudget budget = dao.fetch(ActivityBudget.class, info.getDeductionBudgetId());
// 使用原有预算查询的数据范围,并保留校工会预算的分工会、协会可用标记。
List<NutMap> availableBudgets = activityReimbursementService.getBudgetMoney(source, info.getClubId());
if (budget == null || !Objects.equals(budget.getOutlayManageSource(), source)
|| availableBudgets.stream().noneMatch(v -> Objects.equals(v.getString("id"), budget.getId()))) {
return Result.error("扣款预算不属于所选经费的可用范围");
}
if (Objects.equals(source, "ACTIVITY_BUDGET_TYPE_ONE")
&& !AuthUtil.hasPermission("activityReimbursement.apply.schoolHas")
&& !Boolean.TRUE.equals(budget.getIsUnionUse())
&& !(AuthUtil.hasPermission("activityReimbursement.apply.clubHas")
&& Boolean.TRUE.equals(budget.getIsClubUse()))) {
return Result.error("该校工会预算未开放给分工会或协会使用");
}
if (Objects.equals(info.getActivityReimbursementMode(), "activity")) {
if (StrUtil.isBlank(info.getDeclareId())) {
return Result.error("请选择申报活动");
}
ActivityDeclareInfo declareInfo = dao.fetch(ActivityDeclareInfo.class, info.getDeclareId());
if (declareInfo == null || !Objects.equals(declareInfo.getActivityType(), activityType)
|| (Objects.equals(source, "ACTIVITY_BUDGET_TYPE_TWO")
&& !Objects.equals(declareInfo.getUnionId(), unionId))
|| (Objects.equals(source, "ACTIVITY_BUDGET_TYPE_THREE")
&& !Objects.equals(declareInfo.getClubId(), info.getClubId()))) {
return Result.error("申报活动不属于所选经费的可用范围");
}
} else if (Objects.equals(info.getActivityReimbursementMode(), "daily")) {
info.setDeclareId(null);
} else {
return Result.error("请选择报销模式");
}
info.setUnionId(unionId);
info.setActivityType(activityType);
return null;
}
@At @At
@ApiOperation("获取当前用户活动报销") @ApiOperation("获取当前用户活动报销")
@SaCheckPermission(value = {"activityReimbursement.apply", "h5.activityReimbursement.apply"}, mode = SaMode.OR) @SaCheckPermission(value = {"activityReimbursement.apply", "h5.activityReimbursement.apply"}, mode = SaMode.OR)
@@ -203,6 +300,11 @@ public class ActivityReimbursementApplyController {
String activityType = ""; String activityType = "";
if (StrUtil.isNotBlank(id)) { if (StrUtil.isNotBlank(id)) {
ActivityReimbursementInfo reimbursementInfo = dao.fetch(ActivityReimbursementInfo.class, id); ActivityReimbursementInfo reimbursementInfo = dao.fetch(ActivityReimbursementInfo.class, id);
if (reimbursementInfo == null || (Objects.equals(reimbursementInfo.getReimbursementIdentity(), "unionTemp")
&& (!Objects.equals(reimbursementInfo.getUserId(), SecurityUtil.getUserId())
|| !Objects.equals(reimbursementInfo.getUnionId(), SecurityUtil.getUnionId())))) {
return Result.error("无权访问该报销申请");
}
if (Objects.equals(reimbursementInfo.getActivityReimbursementMode(), "daily")) { if (Objects.equals(reimbursementInfo.getActivityReimbursementMode(), "daily")) {
return Result.success(); return Result.success();
} }
@@ -37,7 +37,7 @@ public class ActivityReimbursementInfo extends ActivityDeclareInfo {
private String declareId; private String declareId;
@Column @Column
@Comment("报销身份(school/union/club") @Comment("报销身份(school/union/club/unionTempunionTemp为分工会代报销")
@ColDefine(type = ColType.VARCHAR, width = 30) @ColDefine(type = ColType.VARCHAR, width = 30)
private String reimbursementIdentity; private String reimbursementIdentity;
@@ -145,11 +145,13 @@ public class CondolenceApplyController {
} }
if(!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) { if(!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) {
if(AuthUtil.hasRoleOr( if(AuthUtil.hasRoleOr(
RoleConstant.BRANCH_UNION_ADMIN.name(), RoleConstant.BRANCH_UNION_ZUZHI_WY.name(),
RoleConstant.BRANCH_UNION_CHAIRMAN.name(), RoleConstant.BRANCH_UNION_CHAIRMAN.name(),
RoleConstant.BRANCH_UNION_WY.name(), RoleConstant.BRANCH_UNION_WY.name(),
RoleConstant.BRANCH_UNION_XUANCHUAN_WY.name(), RoleConstant.BRANCH_UNION_XUANCHUAN_WY.name(),
RoleConstant.BRANCH_UNION_WENTI_WY.name(), RoleConstant.BRANCH_UNION_WENTI_WY.name(),
RoleConstant.BRANCH_UNION_WENTI_SPORTS.name(),
RoleConstant.BRANCH_UNION_NVGONG_WY.name(),
RoleConstant.BRANCH_UNION_XJSHAN_PROMOTION.name() RoleConstant.BRANCH_UNION_XJSHAN_PROMOTION.name()
)) { )) {
cnd.and(View_user::getUnionId, "=", SecurityUtil.getUnionId()); cnd.and(View_user::getUnionId, "=", SecurityUtil.getUnionId());
@@ -0,0 +1,105 @@
-- 分工会临时报销人:新增分工会代报销身份权限,身份选项由后台角色关联菜单控制。
-- 适用于已配置费用报销菜单的 MySQL 数据库,可重复执行,不关联具体用户。
START TRANSACTION;
INSERT INTO sys_role
(id, name, code, aliasName, disabled, unitid, note, sort, createdBy, createdAt, updatedBy, updatedAt, delFlag)
SELECT REPLACE(UUID(), '-', ''), '分工会临时报销人', 'UNION_TEMP_REIMBURSEMENT_APPLICANT',
'分工会临时报销人', 0, '', '报销身份与经费范围由角色关联的菜单权限决定', 0,
'', FLOOR(UNIX_TIMESTAMP(CURRENT_TIMESTAMP(3)) * 1000),
'', FLOOR(UNIX_TIMESTAMP(CURRENT_TIMESTAMP(3)) * 1000), 0
WHERE NOT EXISTS (
SELECT 1 FROM sys_role WHERE code = 'UNION_TEMP_REIMBURSEMENT_APPLICANT'
);
-- 参照分工会(unionHas)身份权限创建同级菜单,沿用类型、平台及所属模块。
-- 每级路径为四位,追加在同级最后;不重复创建,也不复制校工会或分工会身份授权。
INSERT INTO sys_menu
(id, parentId, path, name, initialPinyinName, aliasName, type, href, target, icon, picIcon,
showit, disabled, permission, note, location, hasChildren, platform, moduleId,
isRecommendApp, isRecommendService, createdBy, createdAt, updatedBy, updatedAt, delFlag)
SELECT REPLACE(UUID(), '-', ''), template.parentId,
CONCAT(LEFT(template.path, CHAR_LENGTH(template.path) - 4),
LPAD(COALESCE(siblings.maxSuffix, 0) + 1, 4, '0')),
'分工会代报销', 'F', '分工会代报销', template.type, template.href, template.target,
template.icon, template.picIcon, template.showit, 0,
'activityReimbursement.apply.unionTempHas',
'报销身份:分工会代报销,申请直接进入校工会财务审核',
COALESCE(siblings.maxLocation, 0) + 1, 0, template.platform, template.moduleId,
0, 0, '', FLOOR(UNIX_TIMESTAMP(CURRENT_TIMESTAMP(3)) * 1000),
'', FLOOR(UNIX_TIMESTAMP(CURRENT_TIMESTAMP(3)) * 1000), 0
FROM sys_menu template
LEFT JOIN (
SELECT parentId, MAX(CAST(RIGHT(path, 4) AS UNSIGNED)) AS maxSuffix,
MAX(location) AS maxLocation
FROM sys_menu
GROUP BY parentId
) siblings ON siblings.parentId = template.parentId
WHERE template.permission = 'activityReimbursement.apply.unionHas'
AND NOT EXISTS (
SELECT 1 FROM sys_menu existing
WHERE existing.permission = 'activityReimbursement.apply.unionTempHas'
);
-- 默认给临时报销角色关联代报销身份、报销申请、我的报销及导航父级,其他身份由后台自行配置。
-- activityDeclare 用于报销选取活动后读取申报详情,不授权活动申报、预算申报或审核子菜单。
-- 同时关联已有的手机端报销菜单;通过路径前缀补齐导航父级,不授权同级菜单。
INSERT INTO sys_role_menu (roleId, menuId)
SELECT DISTINCT role.id, menu.id
FROM sys_role role
JOIN sys_menu entry ON entry.permission IN (
'activityReimbursement.apply',
'activityReimbursement.apply.unionTempHas',
'activityReimbursement.mine',
'h5.activityReimbursement.apply',
'h5.activityReimbursement.mine',
'activityDeclare'
)
JOIN sys_menu menu ON menu.id = entry.id OR (
menu.type = 'menu'
AND menu.path IS NOT NULL
AND menu.path <> ''
AND entry.path LIKE CONCAT(menu.path, '%')
)
WHERE role.code = 'UNION_TEMP_REIMBURSEMENT_APPLICANT'
AND entry.disabled = 0
AND menu.disabled = 0
AND NOT EXISTS (
SELECT 1 FROM sys_role_menu assigned
WHERE assigned.roleId = role.id AND assigned.menuId = menu.id
);
-- 工会管理的角色下拉框及人员列表均读取 BRANCH_UNION_ROLES 字典,角色表记录不会自动成为选项。
-- 沿用字典每级四位的路径规则,将新角色追加到已有子项之后,并按父级与角色编码避免重复插入。
INSERT INTO sys_dict
(id, parentId, path, name, remark, code, disabled, location, hasChildren,
createdBy, createdAt, updatedBy, updatedAt, delFlag)
SELECT REPLACE(UUID(), '-', ''), parent.id,
CONCAT(parent.path, LPAD(COALESCE(siblings.maxSuffix, 0) + 1, 4, '0')),
'分工会临时报销人', '可分配分工会代报销等报销身份权限', 'UNION_TEMP_REIMBURSEMENT_APPLICANT',
0, COALESCE(siblings.maxLocation, 0) + 1, 0,
'', FLOOR(UNIX_TIMESTAMP(CURRENT_TIMESTAMP(3)) * 1000),
'', FLOOR(UNIX_TIMESTAMP(CURRENT_TIMESTAMP(3)) * 1000), 0
FROM sys_dict parent
LEFT JOIN (
SELECT parentId, MAX(CAST(RIGHT(path, 4) AS UNSIGNED)) AS maxSuffix,
MAX(location) AS maxLocation
FROM sys_dict
GROUP BY parentId
) siblings ON siblings.parentId = parent.id
WHERE parent.code = 'BRANCH_UNION_ROLES'
AND NOT EXISTS (
SELECT 1 FROM sys_dict existing
WHERE existing.parentId = parent.id
AND existing.code = 'UNION_TEMP_REIMBURSEMENT_APPLICANT'
);
UPDATE sys_role
SET note = '报销身份与经费范围由角色关联的菜单权限决定'
WHERE code = 'UNION_TEMP_REIMBURSEMENT_APPLICANT';
UPDATE sys_dict
SET remark = '可分配分工会代报销等报销身份权限'
WHERE code = 'UNION_TEMP_REIMBURSEMENT_APPLICANT';
COMMIT;
+929
View File
@@ -0,0 +1,929 @@
{
"name": "HDBX",
"category": "3",
"displayName": "费用报销管理",
"instanceUrl": "/platform/activityReimbursement/apply",
"h5InstanceUrl": "/platform/activityReimbursement/apply/h5",
"nodes": [
{
"id": "686d23b6-707f-40d4-ab7c-1987616e4ae0",
"type": "snaker:start",
"x": 220,
"y": 240,
"properties": {
"postInterceptors": ""
},
"text": {
"x": 220,
"y": 280,
"value": "开始"
}
},
{
"id": "startTask",
"type": "snaker:task",
"x": 360,
"y": 240,
"properties": {
"form": "/platform/activityReimbursement/mine",
"h5form": "/platform/activityReimbursement/mine/h5",
"assignee": "initiator",
"assigneeMode": "initiator",
"assigneeText": "流程发起人",
"buttonConfig": [
{
"value": 0,
"visible": true,
"disabled": false,
"originalText": "提交"
}
],
"postInterceptors": ""
},
"text": {
"x": 360,
"y": 240,
"value": "提交申请"
}
},
{
"id": "5afcf810-7a8b-4896-9aa7-c99995e0856b",
"type": "snaker:task",
"x": 700,
"y": 240,
"properties": {
"form": "/platform/activityReimbursement/clubPrincipal",
"h5form": "/platform/activityReimbursement/clubPrincipal/h5",
"assignee": "",
"assigneeMode": "manual",
"assigneeText": "",
"buttonConfig": [
{
"value": 0,
"originalText": "发起申请"
},
{
"theme": "primary",
"value": 1,
"visible": true,
"originalText": "同意申请"
},
{
"theme": "danger",
"value": 2,
"visible": true,
"originalText": "拒绝申请"
},
{
"value": 3,
"originalText": "退回上一步"
},
{
"value": 4,
"originalText": "跳转"
},
{
"value": 5,
"originalText": "重新提交"
},
{
"theme": "danger",
"value": 6,
"visible": true,
"originalText": "退回发起人"
},
{
"value": 20,
"originalText": "会签拒绝申请"
}
],
"assignmentHandler": "com.budwk.app.flow.handler.FlowClubPresidentByArgsAssignmentHandler"
},
"text": {
"x": 700,
"y": 240,
"value": "协会负责人审核"
}
},
{
"id": "182768cf-ff70-4b59-8f5d-8523831380e8",
"type": "snaker:decision",
"x": 520,
"y": 240,
"properties": {}
},
{
"id": "1e4cc473-beae-427d-b9dc-c1c4d0eb07c8",
"type": "snaker:task",
"x": 700,
"y": 100,
"properties": {
"form": "/platform/activityReimbursement/branchUnion",
"h5form": "/platform/activityReimbursement/branchUnion/h5",
"assignee": "",
"assigneeMode": "manual",
"assigneeText": "",
"buttonConfig": [
{
"value": 0,
"originalText": "发起申请"
},
{
"theme": "primary",
"value": 1,
"visible": true,
"originalText": "同意申请"
},
{
"theme": "danger",
"value": 2,
"visible": true,
"originalText": "拒绝申请"
},
{
"value": 3,
"originalText": "退回上一步"
},
{
"value": 4,
"originalText": "跳转"
},
{
"value": 5,
"originalText": "重新提交"
},
{
"theme": "danger",
"value": 6,
"visible": true,
"originalText": "退回发起人"
},
{
"value": 20,
"originalText": "会签拒绝申请"
}
],
"assignmentHandler": "com.budwk.app.flow.handler.FlowFghzxAssignmentHandler"
},
"text": {
"x": 700,
"y": 100,
"value": "分工会审核"
}
},
{
"id": "6dd2e8b3-fd0d-4b35-bb2a-1eef227cba96",
"type": "snaker:task",
"x": 1120,
"y": 240,
"properties": {
"form": "/platform/activityReimbursement/schoolPrincipal",
"h5form": "/platform/activityReimbursement/schoolPrincipal/h5",
"assignee": "2c8b9143b5cd491ba49dd4b52a844b10",
"assigneeMode": "select",
"assigneeText": "陈曦",
"buttonConfig": [
{
"value": 0,
"originalText": "发起申请"
},
{
"theme": "primary",
"value": 1,
"visible": true,
"originalText": "同意申请"
},
{
"theme": "danger",
"value": 2,
"visible": true,
"originalText": "拒绝申请"
},
{
"theme": "danger",
"value": 3,
"visible": true,
"originalText": "退回上一步"
},
{
"value": 4,
"originalText": "跳转"
},
{
"value": 5,
"originalText": "重新提交"
},
{
"theme": "danger",
"value": 6,
"visible": true,
"originalText": "退回发起人"
},
{
"value": 20,
"originalText": "会签拒绝申请"
}
]
},
"text": {
"x": 1120,
"y": 240,
"value": "校工会预审"
}
},
{
"id": "47bfdf53-288c-4352-a403-0653483b54eb",
"type": "snaker:task",
"x": 1540,
"y": 240,
"properties": {
"form": "/platform/activityReimbursement/schoolUnion",
"h5form": "/platform/activityReimbursement/schoolUnion/h5",
"assignee": "fd76781c09c04147b5170179be127240",
"assigneeMode": "select",
"assigneeText": "张红萍",
"buttonConfig": [
{
"value": 0,
"originalText": "发起申请"
},
{
"theme": "primary",
"value": 1,
"visible": true,
"originalText": "同意申请"
},
{
"theme": "danger",
"value": 2,
"visible": true,
"originalText": "拒绝申请"
},
{
"theme": "danger",
"value": 3,
"visible": true,
"originalText": "退回上一步"
},
{
"value": 4,
"originalText": "跳转"
},
{
"value": 5,
"originalText": "重新提交"
},
{
"theme": "danger",
"value": 6,
"visible": true,
"originalText": "退回发起人"
},
{
"value": 20,
"originalText": "会签拒绝申请"
}
]
},
"text": {
"x": 1540,
"y": 240,
"value": "校工会主席审核"
}
},
{
"id": "776311f1-b016-4090-9112-1b4a11fb0d4a",
"type": "snaker:end",
"x": 1920,
"y": 240,
"properties": {},
"text": {
"x": 1920,
"y": 280,
"value": "结束"
}
},
{
"id": "ba496ac7-abb3-4e6d-8c8e-212863a0d6ee",
"type": "snaker:task",
"x": 900,
"y": 240,
"properties": {
"form": "/platform/activityReimbursement/schoolFinance",
"h5form": "/platform/activityReimbursement/schoolFinance/h5",
"assignee": "5b8880eeee384eb4be20084735aac6e6",
"assigneeMode": "select",
"assigneeText": "丁彩华",
"buttonConfig": [
{
"value": 0,
"originalText": "发起申请"
},
{
"value": 1,
"originalText": "同意申请"
},
{
"value": 2,
"originalText": "拒绝申请"
},
{
"value": 3,
"originalText": "退回上一步"
},
{
"value": 4,
"originalText": "跳转"
},
{
"value": 5,
"originalText": "重新提交"
},
{
"value": 6,
"originalText": "退回发起人"
},
{
"value": 20,
"originalText": "会签拒绝申请"
}
]
},
"text": {
"x": 900,
"y": 240,
"value": "校工会财务审核"
}
},
{
"id": "f9b8379f-f348-4985-ba58-b6ba28deb9af",
"type": "snaker:task",
"x": 1320,
"y": 240,
"properties": {
"form": "/platform/activityReimbursement/deputySchoolUnion",
"h5form": "/platform/activityReimbursement/deputySchoolUnion/h5",
"assignee": "b472656183e6408697b8ada687cad442",
"assigneeMode": "select",
"assigneeText": "张蕴梅",
"buttonConfig": [
{
"value": 0,
"originalText": "发起申请"
},
{
"value": 1,
"originalText": "同意申请"
},
{
"value": 2,
"originalText": "拒绝申请"
},
{
"value": 3,
"originalText": "退回上一步"
},
{
"value": 4,
"originalText": "跳转"
},
{
"value": 5,
"originalText": "重新提交"
},
{
"value": 6,
"originalText": "退回发起人"
},
{
"value": 20,
"originalText": "会签拒绝申请"
}
]
},
"text": {
"x": 1320,
"y": 240,
"value": "校工会副主席审核"
}
},
{
"id": "409e8fad-6bd5-485a-8b3e-e1d58688e05a",
"type": "snaker:decision",
"x": 1320,
"y": 420,
"properties": {}
},
{
"id": "e283f33f-4ac7-4c66-9b16-e0653e8dc452",
"type": "snaker:task",
"x": 1760,
"y": 240,
"properties": {
"form": "/platform/activityReimbursement/cashier",
"h5form": "/platform/activityReimbursement/cashier/h5",
"assignee": "762206d35f7041178e66956d859b823d",
"assigneeMode": "select",
"assigneeText": "嵇蓉静",
"buttonConfig": [
{
"value": 0,
"originalText": "发起申请"
},
{
"value": 1,
"originalText": "同意申请"
},
{
"value": 2,
"originalText": "拒绝申请"
},
{
"value": 3,
"originalText": "退回上一步"
},
{
"value": 4,
"originalText": "跳转"
},
{
"value": 5,
"originalText": "重新提交"
},
{
"value": 6,
"originalText": "退回发起人"
},
{
"value": 20,
"originalText": "会签拒绝申请"
}
]
},
"text": {
"x": 1760,
"y": 240,
"value": "出纳支付"
}
}
],
"edges": [
{
"id": "7eab997d-639c-49a8-bb1a-f6a0a9983eb7",
"type": "snaker:transition",
"sourceNodeId": "182768cf-ff70-4b59-8f5d-8523831380e8",
"targetNodeId": "ba496ac7-abb3-4e6d-8c8e-212863a0d6ee",
"startPoint": {
"x": 508,
"y": 253
},
"endPoint": {
"x": 940,
"y": 280
},
"properties": {
"expr": "{next=='unionTemp'}"
},
"text": {
"x": 700,
"y": 480,
"value": "分工会代报销"
},
"pointsList": [
{
"x": 508,
"y": 253
},
{
"x": 460,
"y": 253
},
{
"x": 460,
"y": 480
},
{
"x": 940,
"y": 480
},
{
"x": 940,
"y": 280
}
]
},
{
"id": "876385a3-18eb-4022-864b-068053ec9e06",
"type": "snaker:transition",
"sourceNodeId": "182768cf-ff70-4b59-8f5d-8523831380e8",
"targetNodeId": "1e4cc473-beae-427d-b9dc-c1c4d0eb07c8",
"startPoint": {
"x": 520,
"y": 215
},
"endPoint": {
"x": 640,
"y": 100
},
"properties": {
"expr": "{next=='union'}"
},
"text": {
"x": 520,
"y": 157.5,
"value": "分工会"
},
"pointsList": [
{
"x": 520,
"y": 215
},
{
"x": 520,
"y": 100
},
{
"x": 640,
"y": 100
}
]
},
{
"id": "add1a8a8-1bb5-4bb3-adf7-ef4868d4972c",
"type": "snaker:transition",
"sourceNodeId": "182768cf-ff70-4b59-8f5d-8523831380e8",
"targetNodeId": "5afcf810-7a8b-4896-9aa7-c99995e0856b",
"startPoint": {
"x": 545,
"y": 240
},
"endPoint": {
"x": 640,
"y": 240
},
"properties": {
"expr": "{next=='club'}"
},
"text": {
"x": 592.5,
"y": 240,
"value": "协会"
},
"pointsList": [
{
"x": 545,
"y": 240
},
{
"x": 640,
"y": 240
}
]
},
{
"id": "4c288069-d042-4070-9afd-4902baf148b0",
"type": "snaker:transition",
"sourceNodeId": "startTask",
"targetNodeId": "182768cf-ff70-4b59-8f5d-8523831380e8",
"startPoint": {
"x": 420,
"y": 240
},
"endPoint": {
"x": 495,
"y": 240
},
"properties": {},
"pointsList": [
{
"x": 420,
"y": 240
},
{
"x": 495,
"y": 240
}
]
},
{
"id": "de8ae26f-8660-4cd2-9507-ef573bdbef6c",
"type": "snaker:transition",
"sourceNodeId": "686d23b6-707f-40d4-ab7c-1987616e4ae0",
"targetNodeId": "startTask",
"startPoint": {
"x": 238,
"y": 240
},
"endPoint": {
"x": 300,
"y": 240
},
"properties": {},
"pointsList": [
{
"x": 238,
"y": 240
},
{
"x": 300,
"y": 240
}
]
},
{
"id": "b36a46d0-05ff-486c-9cbf-b6f9e4e50217",
"type": "snaker:transition",
"sourceNodeId": "182768cf-ff70-4b59-8f5d-8523831380e8",
"targetNodeId": "ba496ac7-abb3-4e6d-8c8e-212863a0d6ee",
"startPoint": {
"x": 519,
"y": 265
},
"endPoint": {
"x": 902,
"y": 280
},
"properties": {
"expr": "{next=='school'}"
},
"text": {
"x": 710.5,
"y": 376,
"value": "校工会"
},
"pointsList": [
{
"x": 519,
"y": 265
},
{
"x": 519,
"y": 376
},
{
"x": 902,
"y": 376
},
{
"x": 902,
"y": 280
}
]
},
{
"id": "bfb971df-c94b-46f5-9dc2-e0e0624b1f0f",
"type": "snaker:transition",
"sourceNodeId": "ba496ac7-abb3-4e6d-8c8e-212863a0d6ee",
"targetNodeId": "6dd2e8b3-fd0d-4b35-bb2a-1eef227cba96",
"startPoint": {
"x": 960,
"y": 240
},
"endPoint": {
"x": 1060,
"y": 240
},
"properties": {},
"pointsList": [
{
"x": 960,
"y": 240
},
{
"x": 1060,
"y": 240
}
]
},
{
"id": "aae8eac1-3613-49f9-8bdf-5e054de9a78d",
"type": "snaker:transition",
"sourceNodeId": "5afcf810-7a8b-4896-9aa7-c99995e0856b",
"targetNodeId": "ba496ac7-abb3-4e6d-8c8e-212863a0d6ee",
"startPoint": {
"x": 760,
"y": 240
},
"endPoint": {
"x": 840,
"y": 240
},
"properties": {},
"pointsList": [
{
"x": 760,
"y": 240
},
{
"x": 840,
"y": 240
}
]
},
{
"id": "ae58c15a-1a76-4201-9633-cfbdb47b3b2f",
"type": "snaker:transition",
"sourceNodeId": "1e4cc473-beae-427d-b9dc-c1c4d0eb07c8",
"targetNodeId": "ba496ac7-abb3-4e6d-8c8e-212863a0d6ee",
"startPoint": {
"x": 760,
"y": 100
},
"endPoint": {
"x": 900,
"y": 200
},
"properties": {},
"pointsList": [
{
"x": 760,
"y": 100
},
{
"x": 900,
"y": 100
},
{
"x": 900,
"y": 200
}
]
},
{
"id": "b3549e56-d9d4-4a40-ae41-f49f57b20fd4",
"type": "snaker:transition",
"sourceNodeId": "6dd2e8b3-fd0d-4b35-bb2a-1eef227cba96",
"targetNodeId": "f9b8379f-f348-4985-ba58-b6ba28deb9af",
"startPoint": {
"x": 1180,
"y": 240
},
"endPoint": {
"x": 1260,
"y": 240
},
"properties": {},
"pointsList": [
{
"x": 1180,
"y": 240
},
{
"x": 1260,
"y": 240
}
]
},
{
"id": "809cebae-3520-42b9-b781-a4e99f8e8493",
"type": "snaker:transition",
"sourceNodeId": "f9b8379f-f348-4985-ba58-b6ba28deb9af",
"targetNodeId": "409e8fad-6bd5-485a-8b3e-e1d58688e05a",
"startPoint": {
"x": 1315,
"y": 280
},
"endPoint": {
"x": 1315,
"y": 395
},
"properties": {},
"pointsList": [
{
"x": 1315,
"y": 280
},
{
"x": 1315,
"y": 395
}
]
},
{
"id": "d6c1ad28-0a92-463d-b8eb-3566cb996748",
"type": "snaker:transition",
"sourceNodeId": "409e8fad-6bd5-485a-8b3e-e1d58688e05a",
"targetNodeId": "47bfdf53-288c-4352-a403-0653483b54eb",
"startPoint": {
"x": 1345,
"y": 420
},
"endPoint": {
"x": 1574,
"y": 280
},
"properties": {
"expr": "{actualMoney>=10000}"
},
"text": {
"x": 1459.5,
"y": 420,
"value": "金额超过一万"
},
"pointsList": [
{
"x": 1345,
"y": 420
},
{
"x": 1574,
"y": 420
},
{
"x": 1574,
"y": 280
}
]
},
{
"id": "4749adda-4a3a-4fd4-a655-94007ce9eec6",
"type": "snaker:transition",
"sourceNodeId": "47bfdf53-288c-4352-a403-0653483b54eb",
"targetNodeId": "e283f33f-4ac7-4c66-9b16-e0653e8dc452",
"startPoint": {
"x": 1600,
"y": 240
},
"endPoint": {
"x": 1700,
"y": 240
},
"properties": {},
"pointsList": [
{
"x": 1600,
"y": 240
},
{
"x": 1700,
"y": 240
}
]
},
{
"id": "c68c6814-bd8f-4f4d-9dcb-0b79bf9af5c1",
"type": "snaker:transition",
"sourceNodeId": "e283f33f-4ac7-4c66-9b16-e0653e8dc452",
"targetNodeId": "776311f1-b016-4090-9112-1b4a11fb0d4a",
"startPoint": {
"x": 1820,
"y": 240
},
"endPoint": {
"x": 1902,
"y": 240
},
"properties": {},
"pointsList": [
{
"x": 1820,
"y": 240
},
{
"x": 1902,
"y": 240
}
]
},
{
"id": "218593d1-f31b-4c05-bf21-6da6110dc9dd",
"type": "snaker:transition",
"sourceNodeId": "409e8fad-6bd5-485a-8b3e-e1d58688e05a",
"targetNodeId": "e283f33f-4ac7-4c66-9b16-e0653e8dc452",
"startPoint": {
"x": 1320,
"y": 445
},
"endPoint": {
"x": 1760,
"y": 280
},
"properties": {
"expr": "{actualMoney<10000}"
},
"text": {
"x": 1540,
"y": 541,
"value": "金额没有超过一万"
},
"pointsList": [
{
"x": 1320,
"y": 445
},
{
"x": 1320,
"y": 541
},
{
"x": 1760,
"y": 541
},
{
"x": 1760,
"y": 280
}
]
}
]
}
@@ -140,7 +140,7 @@
...this.designerData, ...this.designerData,
content: val.json content: val.json
} }
$.post("/flow/design/updateContent", { design: JSON.stringify(design) }).then((res) => { $.post("/flow/design/xiugaiDesign", { design: JSON.stringify(design) }).then((res) => {
if (res.code === 0) { if (res.code === 0) {
window.parent.postMessage("success") window.parent.postMessage("success")
} else { } else {
@@ -361,11 +361,11 @@ layout("/layouts/platform.html"){
if (this.hasSchoolLevelRole()) { if (this.hasSchoolLevelRole()) {
return this.budgetOption; return this.budgetOption;
} else if (this.formData.outlayManageSource === "ACTIVITY_BUDGET_TYPE_ONE") { } else if (this.formData.outlayManageSource === "ACTIVITY_BUDGET_TYPE_ONE") {
if (this.hasUnionRole() || this.hasClubRole()) { if ((this.hasUnionRole() || this.hasUnionTempRole()) || this.hasClubRole()) {
return this.budgetOption.filter(item => { return this.budgetOption.filter(item => {
if (this.hasUnionRole() && this.hasClubRole()) { if ((this.hasUnionRole() || this.hasUnionTempRole()) && this.hasClubRole()) {
return item.isUnionUse === true || item.isClubUse === true; return item.isUnionUse === true || item.isClubUse === true;
} else if (this.hasUnionRole()) { } else if ((this.hasUnionRole() || this.hasUnionTempRole())) {
return item.isUnionUse === true; return item.isUnionUse === true;
} else if (this.hasClubRole()) { } else if (this.hasClubRole()) {
return item.isClubUse === true; return item.isClubUse === true;
@@ -380,6 +380,9 @@ layout("/layouts/platform.html"){
} }
}, },
methods: { methods: {
hasUnionTempRole() {
return this.$auth.hasPermission('activityReimbursement.apply.unionTempHas')
},
hasUnionRole() { hasUnionRole() {
return this.$auth.hasPermission('activityReimbursement.apply.unionHas') return this.$auth.hasPermission('activityReimbursement.apply.unionHas')
}, },
@@ -403,7 +406,7 @@ layout("/layouts/platform.html"){
this.$set(this.formData, "unionId", this.$store.state.user.union.id) this.$set(this.formData, "unionId", this.$store.state.user.union.id)
if (val === "school") { if (val === "school") {
this.$set(this.formData, "declareUnitName", "校工会") this.$set(this.formData, "declareUnitName", "校工会")
} else if (val === "union") { } else if (val === "union" || val === "unionTemp") {
this.$set(this.formData, "declareUnitName", this.$store.state.user.union.name) this.$set(this.formData, "declareUnitName", this.$store.state.user.union.name)
} }
}, },
@@ -436,7 +439,7 @@ layout("/layouts/platform.html"){
if (this.hasSchoolLevelRole()) { if (this.hasSchoolLevelRole()) {
return '预算名称:' + item.activityMatter + ',申报预算:' + item.totalBudgetMoney + ',已使用:' + item.usedBudgetMoney return '预算名称:' + item.activityMatter + ',申报预算:' + item.totalBudgetMoney + ',已使用:' + item.usedBudgetMoney
} else if (this.formData.outlayManageSource === "ACTIVITY_BUDGET_TYPE_ONE" && } else if (this.formData.outlayManageSource === "ACTIVITY_BUDGET_TYPE_ONE" &&
(this.hasUnionRole() || this.hasClubRole())) { ((this.hasUnionRole() || this.hasUnionTempRole()) || this.hasClubRole())) {
return '预算名称:' + item.activityMatter return '预算名称:' + item.activityMatter
} else { } else {
return '预算名称:' + item.activityMatter + ',申报预算:' + item.totalBudgetMoney + ',已使用:' + item.usedBudgetMoney return '预算名称:' + item.activityMatter + ',申报预算:' + item.totalBudgetMoney + ',已使用:' + item.usedBudgetMoney
@@ -565,6 +568,8 @@ layout("/layouts/platform.html"){
} }
this.formData.id = this.bizId ? this.bizId : null this.formData.id = this.bizId ? this.bizId : null
// 申报记录的ID不能作为报销主键,单独保留关联活动以供后端校验。
this.$set(this.formData, 'declareId', id)
if (data.planStartTime && data.planEndTime) { if (data.planStartTime && data.planEndTime) {
this.formData.planDate = [data.planStartTime, data.planEndTime] this.formData.planDate = [data.planStartTime, data.planEndTime]
@@ -618,7 +623,7 @@ layout("/layouts/platform.html"){
} }
}) })
} else { } else {
if (this.$auth.hasPermission('activityReimbursement.apply.unionHas')) { if (this.hasUnionRole() || this.hasUnionTempRole()) {
const typeTwoOption = resp.find(v => v.code === "ACTIVITY_BUDGET_TYPE_TWO") const typeTwoOption = resp.find(v => v.code === "ACTIVITY_BUDGET_TYPE_TWO")
if (typeTwoOption && !budgetTypeCloseOption.some(existing => existing.code === "ACTIVITY_BUDGET_TYPE_TWO")) { if (typeTwoOption && !budgetTypeCloseOption.some(existing => existing.code === "ACTIVITY_BUDGET_TYPE_TWO")) {
budgetTypeCloseOption.push(typeTwoOption) budgetTypeCloseOption.push(typeTwoOption)
@@ -636,6 +641,9 @@ layout("/layouts/platform.html"){
}) })
}, },
initReimbursementIdentity() { initReimbursementIdentity() {
if (this.hasUnionTempRole()) {
this.reimbursementIdentityOption.push({name: "分工会代报销", code: "unionTemp"})
}
if (this.$auth.hasPermission('activityReimbursement.apply.schoolHas')) { if (this.$auth.hasPermission('activityReimbursement.apply.schoolHas')) {
this.reimbursementIdentityOption.push({name: "校工会", code: "school"}) this.reimbursementIdentityOption.push({name: "校工会", code: "school"})
} }
@@ -226,12 +226,17 @@ layout("/layouts/platform.html"){
files: [{required: true, message: "必填", trigger: ["change", "blur"]}], files: [{required: true, message: "必填", trigger: ["change", "blur"]}],
signature: [{required: true, message: "必填", trigger: ["change", "blur"]}] signature: [{required: true, message: "必填", trigger: ["change", "blur"]}]
}, },
chooseType: {},
payUserOptions: [], payUserOptions: [],
helpUserOptions: [], helpUserOptions: [],
typeOptions: [] typeOptions: []
} }
}, },
computed: {
// 类型列表和申请详情独立加载,任一数据变化后重新匹配;未匹配时返回空对象,保证附件区域安全渲染。
chooseType() {
return this.typeOptions.find(o => o.id === this.formData.type) || {}
}
},
methods: { methods: {
createRemoteMethod(options) { createRemoteMethod(options) {
return (keyword) => { return (keyword) => {
@@ -267,10 +272,11 @@ layout("/layouts/platform.html"){
} }
}, },
typeChange(id) { typeChange(id) {
this.chooseType = this.typeOptions.find(o => o.id === id) // id 为用户选择的慰问类型 ID;仅匹配成功时更新金额和方式,详情回显时保留原申请值。
if (this.chooseType) { const type = this.typeOptions.find(o => o.id === id)
this.$set(this.formData, "money", this.chooseType.money) if (type) {
this.$set(this.formData, "way", this.chooseType.way) this.$set(this.formData, "money", type.money)
this.$set(this.formData, "way", type.way)
} }
}, },
onSave() { onSave() {
@@ -335,7 +341,6 @@ layout("/layouts/platform.html"){
this.formData = res.data this.formData = res.data
this.selectQueryUser(this.formData.helpLoginName, this.helpUserOptions) this.selectQueryUser(this.formData.helpLoginName, this.helpUserOptions)
this.selectQueryUser(this.formData.payLoginName, this.payUserOptions) this.selectQueryUser(this.formData.payLoginName, this.payUserOptions)
this.chooseType = this.typeOptions.find(o => o.id === this.formData.type)
} }
}) })
} else { } else {
@@ -352,9 +357,10 @@ layout("/layouts/platform.html"){
} }
}, },
queryCondolenceType() { queryCondolenceType() {
// 接口无需参数,返回 Resultcode 为 0 时 data 为启用类型数组,异常响应按空列表处理。
this.$axios.post("/platform/condolence/type/queryCondolenceType") this.$axios.post("/platform/condolence/type/queryCondolenceType")
.then((resp) => { .then((resp) => {
this.typeOptions = resp.data this.$set(this, "typeOptions", resp && resp.code === 0 && Array.isArray(resp.data) ? resp.data : [])
}) })
} }
}, },
@@ -245,12 +245,12 @@ layout("/layouts/platform_h5.html"){
return this.budgetOption return this.budgetOption
} }
if (this.formData.outlayManageSource === 'ACTIVITY_BUDGET_TYPE_ONE') { if (this.formData.outlayManageSource === 'ACTIVITY_BUDGET_TYPE_ONE') {
if (this.hasUnionRole() || this.hasClubRole()) { if ((this.hasUnionRole() || this.hasUnionTempRole()) || this.hasClubRole()) {
return this.budgetOption.filter((item) => { return this.budgetOption.filter((item) => {
if (this.hasUnionRole() && this.hasClubRole()) { if ((this.hasUnionRole() || this.hasUnionTempRole()) && this.hasClubRole()) {
return item.isUnionUse === true || item.isClubUse === true return item.isUnionUse === true || item.isClubUse === true
} }
if (this.hasUnionRole()) { if ((this.hasUnionRole() || this.hasUnionTempRole())) {
return item.isUnionUse === true return item.isUnionUse === true
} }
if (this.hasClubRole()) { if (this.hasClubRole()) {
@@ -276,6 +276,9 @@ layout("/layouts/platform_h5.html"){
} }
}, },
methods: { methods: {
hasUnionTempRole() {
return this.$auth.hasPermission('activityReimbursement.apply.unionTempHas')
},
hasUnionRole() { hasUnionRole() {
return this.$auth.hasPermission('activityReimbursement.apply.unionHas') return this.$auth.hasPermission('activityReimbursement.apply.unionHas')
}, },
@@ -363,7 +366,7 @@ layout("/layouts/platform_h5.html"){
this.$set(this.formData, 'unionId', this.$store.state.user.union.id) this.$set(this.formData, 'unionId', this.$store.state.user.union.id)
if (val === 'school') { if (val === 'school') {
this.$set(this.formData, 'declareUnitName', '校工会') this.$set(this.formData, 'declareUnitName', '校工会')
} else if (val === 'union') { } else if (val === 'union' || val === 'unionTemp') {
this.$set(this.formData, 'declareUnitName', this.$store.state.user.union.name) this.$set(this.formData, 'declareUnitName', this.$store.state.user.union.name)
} else if (val === 'club') { } else if (val === 'club') {
this.$set(this.formData, 'declareUnitName', this.formData.clubName || '') this.$set(this.formData, 'declareUnitName', this.formData.clubName || '')
@@ -409,7 +412,7 @@ layout("/layouts/platform_h5.html"){
if (this.hasSchoolLevelRole()) { if (this.hasSchoolLevelRole()) {
return this.getBudgetMoneyText(item) + ',名称:' + shortName return this.getBudgetMoneyText(item) + ',名称:' + shortName
} }
if (this.formData.outlayManageSource === 'ACTIVITY_BUDGET_TYPE_ONE' && (this.hasUnionRole() || this.hasClubRole())) { if (this.formData.outlayManageSource === 'ACTIVITY_BUDGET_TYPE_ONE' && ((this.hasUnionRole() || this.hasUnionTempRole()) || this.hasClubRole())) {
return '名称:' + shortName return '名称:' + shortName
} }
return this.getBudgetMoneyText(item) + ',名称:' + shortName return this.getBudgetMoneyText(item) + ',名称:' + shortName
@@ -740,6 +743,7 @@ layout("/layouts/platform_h5.html"){
const identityNameMap = { const identityNameMap = {
school: '校工会', school: '校工会',
union: '分工会', union: '分工会',
unionTemp: '分工会代报销',
club: '协会' club: '协会'
} }
this.$set(this.formData, 'reimbursementIdentityName', identityNameMap[this.formData.reimbursementIdentity] || '') this.$set(this.formData, 'reimbursementIdentityName', identityNameMap[this.formData.reimbursementIdentity] || '')
@@ -798,7 +802,7 @@ layout("/layouts/platform_h5.html"){
} }
}) })
} else { } else {
if (this.hasUnionRole()) { if (this.hasUnionRole() || this.hasUnionTempRole()) {
const typeTwo = resp.find((item) => item.code === 'ACTIVITY_BUDGET_TYPE_TWO') const typeTwo = resp.find((item) => item.code === 'ACTIVITY_BUDGET_TYPE_TWO')
if (typeTwo) { if (typeTwo) {
result.push(typeTwo) result.push(typeTwo)
@@ -815,6 +819,9 @@ layout("/layouts/platform_h5.html"){
}) })
}, },
initReimbursementIdentity() { initReimbursementIdentity() {
if (this.hasUnionTempRole()) {
this.reimbursementIdentityOption.push({name: '分工会代报销', code: 'unionTemp'})
}
if (this.hasSchoolLevelRole()) { if (this.hasSchoolLevelRole()) {
this.reimbursementIdentityOption.push({name: '校工会', code: 'school'}) this.reimbursementIdentityOption.push({name: '校工会', code: 'school'})
} }
@@ -34,10 +34,10 @@ layout("/layouts/platform_h5.html"){
readonly readonly
:rules="[{ required: true }]" :rules="[{ required: true }]"
placeholder="请点击选择慰问对象" placeholder="请点击选择慰问对象"
@click="helpUserSelectShow = true" @click="openUserSelect('help')"
is-link is-link
></van-field> ></van-field>
<van-action-sheet v-model="helpUserSelectShow" title="慰问对象" class="height100"> <van-action-sheet v-model="helpUserSelectShow" @close="resetUserSearch" title="慰问对象" class="height100">
<van-search <van-search
v-model="searchKeyword" v-model="searchKeyword"
:show-action="false" :show-action="false"
@@ -65,12 +65,13 @@ layout("/layouts/platform_h5.html"){
name="payUserName" name="payUserName"
label="收款人" label="收款人"
required required
readonly
:rules="[{ required: true }]" :rules="[{ required: true }]"
placeholder="请点击选择收款人" placeholder="请点击选择收款人"
@click="payUserSelectShow = true" @click="openUserSelect('pay')"
is-link is-link
></van-field> ></van-field>
<van-action-sheet v-model="payUserSelectShow" title="收款人" class="height100"> <van-action-sheet v-model="payUserSelectShow" @close="resetUserSearch" title="收款人" class="height100">
<van-search <van-search
v-model="searchKeyword" v-model="searchKeyword"
:show-action="false" :show-action="false"
@@ -101,12 +102,12 @@ layout("/layouts/platform_h5.html"){
readonly readonly
:rules="[{ required: true }]" :rules="[{ required: true }]"
placeholder="请点击选择慰问类型" placeholder="请点击选择慰问类型"
@click="showTypePicker = true" @click="this.$set(this, 'showTypePicker', true)"
clickable clickable
is-link is-link
></van-field> ></van-field>
<van-popup position="bottom" round v-model:show="showTypePicker"> <van-popup position="bottom" round v-model:show="showTypePicker">
<van-picker :columns="typeColumns" @cancel="showTypePicker = false" @confirm="onTypeConfirm" show-toolbar></van-picker> <van-picker :columns="typeColumns" @cancel="this.$set(this, 'showTypePicker', false)" @confirm="onTypeConfirm" show-toolbar></van-picker>
</van-popup> </van-popup>
<van-field <van-field
@@ -140,15 +141,15 @@ layout("/layouts/platform_h5.html"){
clickable clickable
is-link is-link
readonly readonly
@click="showTimePicker = true" @click="openTimePicker"
></van-field> ></van-field>
<van-popup position="bottom" round v-model:show="showTimePicker"> <van-popup position="bottom" round v-model:show="showTimePicker">
<van-datetime-picker <van-datetime-picker
v-model="formData.occurTime" v-model="timePickerValue"
type="date" type="date"
title="请选择慰问时间" title="请选择慰问时间"
@confirm="(val) => {formData.occurTime = $moment(val).format('YYYY-MM-DD'); showTimePicker = false}" @confirm="onTimeConfirm"
@cancel="showTimePicker = false" @cancel="this.$set(this, 'showTimePicker', false)"
></van-datetime-picker> ></van-datetime-picker>
</van-popup> </van-popup>
@@ -163,15 +164,15 @@ layout("/layouts/platform_h5.html"){
clickable clickable
is-link is-link
readonly readonly
@click="showChildPicker = true" @click="this.$set(this, 'showChildPicker', true)"
></van-field> ></van-field>
<van-popup position="bottom" round v-model:show="showChildPicker"> <van-popup position="bottom" round v-model:show="showChildPicker">
<van-picker <van-picker
title="请选择孩次" title="请选择孩次"
show-toolbar show-toolbar
:columns="['一孩', '二孩', '三孩']" :columns="['一孩', '二孩', '三孩']"
@confirm="(val) => {formData.child = val; showChildPicker = false}" @confirm="(val) => {this.$set(formData, 'child', val); this.$set(this, 'showChildPicker', false)}"
@cancel="showChildPicker = false" @cancel="this.$set(this, 'showChildPicker', false)"
></van-picker> ></van-picker>
</van-popup> </van-popup>
@@ -223,15 +224,15 @@ layout("/layouts/platform_h5.html"){
clickable clickable
is-link is-link
readonly readonly
@click="showFamilyPicker = true" @click="this.$set(this, 'showFamilyPicker', true)"
></van-field> ></van-field>
<van-popup position="bottom" round v-model:show="showFamilyPicker"> <van-popup position="bottom" round v-model:show="showFamilyPicker">
<van-picker <van-picker
title="请选择直系亲属" title="请选择直系亲属"
show-toolbar show-toolbar
:columns="['配偶', '父亲', '母亲', '子女']" :columns="['配偶', '父亲', '母亲', '子女']"
@confirm="(val) => {formData.deadImmediateFamily = val; showFamilyPicker = false}" @confirm="(val) => {this.$set(formData, 'deadImmediateFamily', val); this.$set(this, 'showFamilyPicker', false)}"
@cancel="showFamilyPicker = false" @cancel="this.$set(this, 'showFamilyPicker', false)"
></van-picker> ></van-picker>
</van-popup> </van-popup>
@@ -255,7 +256,7 @@ layout("/layouts/platform_h5.html"){
{{ '(附件说明:' + chooseType.uploadFileDesc + '' }} {{ '(附件说明:' + chooseType.uploadFileDesc + '' }}
</span> </span>
</template> </template>
<van-field class="direction-column-field" name="avatar" label=""> <van-field class="direction-column-field" name="files" label="" :rules="[{ validator: validateFiles, message: '请上传附件' }]">
<template #input> <template #input>
<h5-file-upload <h5-file-upload
slot="input" slot="input"
@@ -269,7 +270,7 @@ layout("/layouts/platform_h5.html"){
</van-cell-group> </van-cell-group>
<van-cell-group title="签字" class="form-section"> <van-cell-group title="签字" class="form-section">
<van-field class="direction-column-field" name="signature" label=""> <van-field class="direction-column-field" name="signature" label="" :rules="[{ validator: validateSignature, message: '请完成签字' }]">
<template #input> <template #input>
<h5-signature v-model="formData.signature" slot="input"></h5-signature> <h5-signature v-model="formData.signature" slot="input"></h5-signature>
</template> </template>
@@ -278,9 +279,9 @@ layout("/layouts/platform_h5.html"){
<!-- 提交按钮 --> <!-- 提交按钮 -->
<div class="form-actions"> <div class="form-actions">
<van-button native-type="button" @click="onSave" round type="info" plain>保存申请</van-button> <van-button native-type="button" @click="onSave" :loading="formLoading" :disabled="formLoading" round type="info" plain>保存申请</van-button>
<van-button @click="onSubmit" round type="info" v-if="!taskId">提交申请</van-button> <van-button native-type="button" @click="onSubmit" :loading="formLoading" :disabled="formLoading" round type="info" v-if="!taskId">提交申请</van-button>
<van-button @click="onFinishTask" round type="info" v-else>提交申请</van-button> <van-button native-type="button" @click="onFinishTask" :loading="formLoading" :disabled="formLoading" round type="info" v-else>提交申请</van-button>
</div> </div>
</van-form> </van-form>
</div> </div>
@@ -296,7 +297,8 @@ layout("/layouts/platform_h5.html"){
taskId: GetQueryString("taskId"), taskId: GetQueryString("taskId"),
formData: {}, formData: {},
chooseType: {}, formLoading: false,
userSearchSequence: 0,
userOptions: [], userOptions: [],
typeOptions: [], typeOptions: [],
@@ -307,20 +309,64 @@ layout("/layouts/platform_h5.html"){
searchKeyword: '', searchKeyword: '',
showTimePicker: false, showTimePicker: false,
timePickerValue: new Date(),
showChildPicker: false, showChildPicker: false,
showFamilyPicker: false, showFamilyPicker: false,
} }
}, },
methods: { computed: {
async userRemoteMethod(event, type) { // 详情和类型列表任意顺序返回都重新匹配;未匹配时保证附件区域可安全读取属性。
if (event) { chooseType() {
this.userOptions = await this.selectQueryUser(event) return this.typeOptions.find(o => o.id === this.formData.type) || {}
type === 'help' ? this.helpUserSelectShow = true : this.payUserSelectShow = true
} }
}, },
async selectQueryUser(keyword) { methods: {
const res = await this.$axios.post("/platform/condolence/apply/listUser", { keyword: keyword }) // 打开人员选择时清除上次搜索,并使之前尚未返回的请求失效。
return res.data openUserSelect(type) {
this.resetUserSearch()
this.$set(this, type === 'help' ? 'helpUserSelectShow' : 'payUserSelectShow', true)
},
resetUserSearch() {
this.userSearchSequence++
this.searchKeyword = ''
this.userOptions = []
},
// keyword 为姓名或工号,type 为 help/pay;只接收最新请求且对应弹框仍打开的结果。
userRemoteMethod(keyword, type) {
const sequence = ++this.userSearchSequence
this.userOptions = []
if (!keyword || !keyword.trim()) return
return this.selectQueryUser(keyword).then((users) => {
const visible = type === 'help' ? this.helpUserSelectShow : this.payUserSelectShow
if (sequence === this.userSearchSequence && visible) this.userOptions = users
}).catch(() => {
// 查询失败保留空结果,后续输入仍可重新查询。
})
},
// keyword 传姓名或工号;返回 Promise<Array>,数组项包含人员 ID、姓名、工号及单位工会信息。
selectQueryUser(keyword) {
return this.$axios.post("/platform/condolence/apply/listUser", { keyword: keyword })
.then((res) => res && res.code === 0 && Array.isArray(res.data) ? res.data : [])
},
// 选择器使用独立 Date 值,取消操作不会改变表单中的日期字符串。
openTimePicker() {
const date = this.$moment(this.formData.occurTime, 'YYYY-MM-DD', true)
this.timePickerValue = date.isValid() ? date.toDate() : new Date()
this.showTimePicker = true
},
onTimeConfirm(value) {
this.$set(this.formData, 'occurTime', this.$moment(value).format('YYYY-MM-DD'))
this.showTimePicker = false
},
// 自定义插槽没有普通输入值,校验直接读取业务附件数组;失败或上传中的文件不算有效附件。
validateFiles() {
return this.chooseType.isUploadFile !== true || (Array.isArray(this.formData.files)
&& this.formData.files.some(file => file && file.status !== 'fail' && file.status !== 'loading'
&& (file.url || file.downloadPath || file.path)))
},
// 签字组件上传成功后将地址写入表单,空地址不能通过提交校验。
validateSignature() {
return typeof this.formData.signature === 'string' && this.formData.signature.trim().length > 0
}, },
helpUserChange(user) { helpUserChange(user) {
const { id, userName, loginName, unitId, unitName, unionId, unionName } = user const { id, userName, loginName, unitId, unitName, unionId, unionName } = user
@@ -345,53 +391,78 @@ layout("/layouts/platform_h5.html"){
this.userOptions = [] this.userOptions = []
}, },
typeChange(id) { typeChange(id) {
this.chooseType = this.typeOptions.find(o => o.id === id) // 仅用户主动选择时联动金额和方式,详情回显保留历史申请值。
if (this.chooseType) { const type = this.typeOptions.find(o => o.id === id)
this.$set(this.formData, "money", this.chooseType.money) if (type) {
this.$set(this.formData, "way", this.chooseType.way) this.$set(this.formData, "money", type.money)
this.$set(this.formData, "way", type.way)
} }
}, },
onTypeConfirm(o) { onTypeConfirm(o) {
// 空列表或失效选项不能写入申请,提示用户重新选择。
if (!o || !this.typeOptions.some(type => type.id === o.value)) {
this.$toast('暂无可选慰问类型,请重新加载后选择')
return
}
this.$set(this.formData, "typeName", o.text) this.$set(this.formData, "typeName", o.text)
this.$set(this.formData, "type", o.value) this.$set(this.formData, "type", o.value)
this.typeChange(o.value) this.typeChange(o.value)
this.showTypePicker = false this.showTypePicker = false
}, },
onSave() { onSave() {
this.$dialog.confirm({ // 从确认框开始锁定操作,取消或请求结束后统一解除,避免重复保存。
if (this.formLoading) return
this.formLoading = true
return this.$dialog.confirm({
title: "提示", title: "提示",
message: "您确定保存吗?" message: "您确定保存吗?"
}).then(() => { }).then(() => {
this.$axios.post("/platform/condolence/apply/save", { data: JSON.stringify(this.formData) }).then(res => { return this.$axios.post("/platform/condolence/apply/save", { data: JSON.stringify(this.formData) }).then(res => {
if (res.code === 0) { if (res.code === 0) {
this.$toast(res.msg) this.$toast(res.msg)
this.$pjaxReplace("/platform/condolence/mine/h5") this.$pjaxReplace("/platform/condolence/mine/h5")
} }
}) })
}).catch((error) => {
if (error !== 'cancel' && error !== 'close') this.$toast('保存失败,请重试')
}).finally(() => {
this.formLoading = false
}) })
}, },
async onSubmit() { onSubmit() {
this.$refs.formRef.validate().then(() => { if (this.formLoading) return
this.$dialog.confirm({ return this.$refs.formRef.validate().then(() => {
// 公共校验失败会停止 Promise 链,因此校验通过后才加锁,并再次拦截并发点击。
if (this.formLoading) return
this.formLoading = true
return this.$dialog.confirm({
title: "提示", title: "提示",
message: "您确定要提交申请吗?" message: "您确定要提交申请吗?"
}).then(() => { }).then(() => {
this.$axios.post("/platform/condolence/apply/submit", { data: JSON.stringify(this.formData) }).then(res => { return this.$axios.post("/platform/condolence/apply/submit", { data: JSON.stringify(this.formData) }).then(res => {
if (res.code === 0) { if (res.code === 0) {
this.$toast(res.msg) this.$toast(res.msg)
this.$pjaxReplace("/platform/condolence/mine/h5") this.$pjaxReplace("/platform/condolence/mine/h5")
} }
}) })
}).catch((error) => {
if (error !== 'cancel' && error !== 'close') this.$toast('提交失败,请重试')
}).finally(() => {
this.formLoading = false
}) })
}) })
}, },
async onFinishTask() { onFinishTask() {
this.$refs.formRef.validate().then(() => { if (this.formLoading) return
this.$dialog.confirm({ return this.$refs.formRef.validate().then(() => {
// 重新提交与首次提交共用操作锁,校验未通过时保持按钮可用。
if (this.formLoading) return
this.formLoading = true
return this.$dialog.confirm({
title: "提示", title: "提示",
message: "您确定要提交申请吗?" message: "您确定要提交申请吗?"
}).then(() => { }).then(() => {
this.$axios.post("/platform/condolence/apply/submitAgain", { return this.$axios.post("/platform/condolence/apply/submitAgain", {
data: JSON.stringify(this.formData), data: JSON.stringify(this.formData),
taskId: GetQueryString("taskId") taskId: GetQueryString("taskId")
}).then(res => { }).then(res => {
@@ -400,6 +471,10 @@ layout("/layouts/platform_h5.html"){
this.$pjaxReplace("/platform/condolence/mine/h5") this.$pjaxReplace("/platform/condolence/mine/h5")
} }
}) })
}).catch((error) => {
if (error !== 'cancel' && error !== 'close') this.$toast('重新提交失败,请重试')
}).finally(() => {
this.formLoading = false
}) })
}) })
}, },
@@ -408,9 +483,6 @@ layout("/layouts/platform_h5.html"){
this.$axios.post("/platform/condolence/mine/info", { id: this.bizId }).then((res) => { this.$axios.post("/platform/condolence/mine/info", { id: this.bizId }).then((res) => {
if (res.code === 0) { if (res.code === 0) {
this.formData = res.data this.formData = res.data
this.selectQueryUser(this.formData.helpLoginName, this.helpUserOptions)
this.selectQueryUser(this.formData.payLoginName, this.payUserOptions)
this.chooseType = this.typeOptions.find(o => o.id === this.formData.type)
} }
}) })
} else { } else {
@@ -429,10 +501,9 @@ layout("/layouts/platform_h5.html"){
queryCondolenceType() { queryCondolenceType() {
this.$axios.post('/platform/condolence/type/queryCondolenceType') this.$axios.post('/platform/condolence/type/queryCondolenceType')
.then((res) => { .then((res) => {
this.typeOptions = JSON.parse(JSON.stringify(res.data)) // Result.code 为 0 时 data 为类型数组;异常响应使用空列表,重复加载不累积选项。
res.data.forEach((v) => { this.typeOptions = res && res.code === 0 && Array.isArray(res.data) ? res.data : []
this.typeColumns.push({ value: v.id, text: v.name + "(" + v.code + ")" }) this.typeColumns = this.typeOptions.map(v => ({ value: v.id, text: v.name + "(" + v.code + ")" }))
})
}) })
}, },
}, },