This commit is contained in:
2026-09-10 16:09:33 +08:00
parent 9f7c0f214e
commit 584e710136
4 changed files with 323 additions and 246 deletions
@@ -41,212 +41,212 @@ import java.util.*;
@Slf4j @Slf4j
public class FlowDesignController { public class FlowDesignController {
@Inject @Inject
private SysUserService sysUserService; private SysUserService sysUserService;
@Inject @Inject
private ProcessDesignService processDesignService; private ProcessDesignService processDesignService;
@Inject @Inject
private Dao dao; private Dao dao;
// 获取所有任务参与者处理类 // 获取所有任务参与者处理类
public static final List<JSONObject> ASSIGMENT_HANDLER_LIST; public static final List<JSONObject> ASSIGMENT_HANDLER_LIST;
// 获取所有候选用户处理类 // 获取所有候选用户处理类
public static final List<JSONObject> CANDIDATE_HANDLER_LIST; public static final List<JSONObject> CANDIDATE_HANDLER_LIST;
static { static {
Set<Class<?>> classes = ClassScanner.scanPackageBySuper("com.budwk.app", AssignmentHandler.class); Set<Class<?>> classes = ClassScanner.scanPackageBySuper("com.budwk.app", AssignmentHandler.class);
ArrayList<JSONObject> list = new ArrayList<>(classes.size()); ArrayList<JSONObject> list = new ArrayList<>(classes.size());
for (Class<?> aClass : classes) { for (Class<?> aClass : classes) {
try { try {
AssignmentHandler handler = (AssignmentHandler) ReflectUtil.newInstance(aClass); AssignmentHandler handler = (AssignmentHandler) ReflectUtil.newInstance(aClass);
JSONObject jsonObject = new JSONObject(); JSONObject jsonObject = new JSONObject();
jsonObject.set("value", handler.getClass().getName()); jsonObject.set("value", handler.getClass().getName());
jsonObject.set("order", handler.getOrder()); jsonObject.set("order", handler.getOrder());
jsonObject.set("name", handler.getMessage()); jsonObject.set("name", handler.getMessage());
list.add(jsonObject); list.add(jsonObject);
} catch (Exception e) { } catch (Exception e) {
log.error("初始化AssignmentHandler失败: {}", aClass.getName()); log.error("初始化AssignmentHandler失败: {}", aClass.getName());
} }
} }
// 排序 按order // 排序 按order
list.sort(Comparator.comparingInt(o -> o.getInt("order"))); list.sort(Comparator.comparingInt(o -> o.getInt("order")));
ASSIGMENT_HANDLER_LIST = Collections.unmodifiableList(list); ASSIGMENT_HANDLER_LIST = Collections.unmodifiableList(list);
} }
static { static {
Set<Class<?>> classes = ClassScanner.scanPackageBySuper("com.budwk.app", CandidateHandler.class); Set<Class<?>> classes = ClassScanner.scanPackageBySuper("com.budwk.app", CandidateHandler.class);
ArrayList<JSONObject> list = new ArrayList<>(classes.size()); ArrayList<JSONObject> list = new ArrayList<>(classes.size());
for (Class<?> aClass : classes) { for (Class<?> aClass : classes) {
try { try {
CandidateHandler handler = (CandidateHandler) ReflectUtil.newInstance(aClass); CandidateHandler handler = (CandidateHandler) ReflectUtil.newInstance(aClass);
JSONObject jsonObject = new JSONObject(); JSONObject jsonObject = new JSONObject();
jsonObject.set("value", handler.getClass().getName()); jsonObject.set("value", handler.getClass().getName());
jsonObject.set("order", handler.getOrder()); jsonObject.set("order", handler.getOrder());
jsonObject.set("name", handler.getMessage()); jsonObject.set("name", handler.getMessage());
list.add(jsonObject); list.add(jsonObject);
} catch (Exception e) { } catch (Exception e) {
log.error("初始化CandidateHandler失败: {}", aClass.getName()); log.error("初始化CandidateHandler失败: {}", aClass.getName());
} }
} }
// 排序 按order // 排序 按order
list.sort(Comparator.comparingInt(o -> o.getInt("order"))); list.sort(Comparator.comparingInt(o -> o.getInt("order")));
CANDIDATE_HANDLER_LIST = Collections.unmodifiableList(list); CANDIDATE_HANDLER_LIST = Collections.unmodifiableList(list);
} }
@At("") @At("")
@Ok("beetl:/platform/flow/design/index.html") @Ok("beetl:/platform/flow/design/index.html")
@SaCheckPermission("flow.design") @SaCheckPermission("flow.design")
public void index() { public void index() {
} }
@At @At
@Ok("beetl:/platform/flow/design/designer.html") @Ok("beetl:/platform/flow/design/designer.html")
@SaCheckLogin @SaCheckLogin
public void designer(HttpServletRequest request) { public void designer(HttpServletRequest request) {
request.setAttribute("id", request.getParameter("id")); request.setAttribute("id", request.getParameter("id"));
} }
@At @At
@ApiOperation("获取流程设计分页列表") @ApiOperation("获取流程设计分页列表")
@SaCheckPermission("flow.design") @SaCheckPermission("flow.design")
public Result pageData(PageForm pageForm, String displayName, String name, String category, Boolean deployed) { public Result pageData(PageForm pageForm, String displayName, String name, String category, Boolean deployed) {
Cnd cnd = Cnd.NEW(); Cnd cnd = Cnd.NEW();
cnd.and(Cnd.likeEX(ProcessDesign::getDisplayName, displayName)); cnd.and(Cnd.likeEX(ProcessDesign::getDisplayName, displayName));
cnd.and(Cnd.likeEX(ProcessDesign::getName, name)); cnd.and(Cnd.likeEX(ProcessDesign::getName, name));
cnd.andEX(ProcessDesign::getCategory, "=", category); cnd.andEX(ProcessDesign::getCategory, "=", category);
cnd.andEX(ProcessDesign::getIsDeployed, "=", deployed); cnd.andEX(ProcessDesign::getIsDeployed, "=", deployed);
Pagination pagination = processDesignService.listPage(pageForm.getPageNumber(), pageForm.getPageSize(), cnd); Pagination pagination = processDesignService.listPage(pageForm.getPageNumber(), pageForm.getPageSize(), cnd);
return Result.success(pagination); return Result.success(pagination);
} }
@At @At
@ApiOperation("保存流程设计") @ApiOperation("保存流程设计")
@SaCheckPermission("flow.design") @SaCheckPermission("flow.design")
public Result insert(@Param("design") ProcessDesign processDesign) { public Result insert(@Param("design") ProcessDesign processDesign) {
JSONObject jsonObject = new JSONObject(); JSONObject jsonObject = new JSONObject();
jsonObject.set("name", processDesign.getName()); jsonObject.set("name", processDesign.getName());
jsonObject.set("displayName", processDesign.getDisplayName()); jsonObject.set("displayName", processDesign.getDisplayName());
jsonObject.set("category", processDesign.getCategory()); jsonObject.set("category", processDesign.getCategory());
jsonObject.set("instanceUrl", processDesign.getInstanceUrl()); jsonObject.set("instanceUrl", processDesign.getInstanceUrl());
jsonObject.set("h5InstanceUrl", processDesign.getH5InstanceUrl()); jsonObject.set("h5InstanceUrl", processDesign.getH5InstanceUrl());
jsonObject.set("instanceViewUrl", processDesign.getInstanceViewUrl()); jsonObject.set("instanceViewUrl", processDesign.getInstanceViewUrl());
jsonObject.set("h5InstanceViewUrl", processDesign.getH5InstanceViewUrl()); jsonObject.set("h5InstanceViewUrl", processDesign.getH5InstanceViewUrl());
jsonObject.set("icon", processDesign.getIcon()); jsonObject.set("icon", processDesign.getIcon());
jsonObject.set("picIcon", processDesign.getPicIcon()); jsonObject.set("picIcon", processDesign.getPicIcon());
jsonObject.set("description", processDesign.getDescription()); jsonObject.set("description", processDesign.getDescription());
processDesign.setContent(jsonObject); processDesign.setContent(jsonObject);
dao.insert(processDesign); dao.insert(processDesign);
return Result.success(); return Result.success();
} }
@At @At
@ApiOperation("修改流程设计") @ApiOperation("修改流程设计")
@SaCheckPermission("flow.design") @SaCheckPermission("flow.design")
public Result update(@Param("design") ProcessDesign processDesign) { public Result update(@Param("design") ProcessDesign processDesign) {
JSONObject jsonObject = processDesign.getContent(); JSONObject jsonObject = processDesign.getContent();
jsonObject.set("name", processDesign.getName()); jsonObject.set("name", processDesign.getName());
jsonObject.set("displayName", processDesign.getDisplayName()); jsonObject.set("displayName", processDesign.getDisplayName());
jsonObject.set("category", processDesign.getCategory()); jsonObject.set("category", processDesign.getCategory());
jsonObject.set("instanceUrl", processDesign.getInstanceUrl()); jsonObject.set("instanceUrl", processDesign.getInstanceUrl());
jsonObject.set("h5InstanceUrl", processDesign.getH5InstanceUrl()); jsonObject.set("h5InstanceUrl", processDesign.getH5InstanceUrl());
jsonObject.set("instanceViewUrl", processDesign.getInstanceViewUrl()); jsonObject.set("instanceViewUrl", processDesign.getInstanceViewUrl());
jsonObject.set("h5InstanceViewUrl", processDesign.getH5InstanceViewUrl()); jsonObject.set("h5InstanceViewUrl", processDesign.getH5InstanceViewUrl());
jsonObject.set("icon", processDesign.getIcon()); jsonObject.set("icon", processDesign.getIcon());
jsonObject.set("picIcon", processDesign.getPicIcon()); jsonObject.set("picIcon", processDesign.getPicIcon());
jsonObject.set("description", processDesign.getDescription()); jsonObject.set("description", processDesign.getDescription());
processDesign.setContent(jsonObject); processDesign.setContent(jsonObject);
processDesignService.update(processDesign); processDesignService.update(processDesign);
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) {
JSONObject jsonObject = processDesign.getContent(); JSONObject jsonObject = processDesign.getContent();
jsonObject.set("name", processDesign.getName()); jsonObject.set("name", processDesign.getName());
jsonObject.set("displayName", processDesign.getDisplayName()); jsonObject.set("displayName", processDesign.getDisplayName());
jsonObject.set("category", processDesign.getCategory()); jsonObject.set("category", processDesign.getCategory());
jsonObject.set("instanceUrl", processDesign.getInstanceUrl()); jsonObject.set("instanceUrl", processDesign.getInstanceUrl());
jsonObject.set("h5InstanceUrl", processDesign.getH5InstanceUrl()); jsonObject.set("h5InstanceUrl", processDesign.getH5InstanceUrl());
jsonObject.set("instanceViewUrl", processDesign.getInstanceViewUrl()); jsonObject.set("instanceViewUrl", processDesign.getInstanceViewUrl());
jsonObject.set("h5InstanceViewUrl", processDesign.getH5InstanceViewUrl()); jsonObject.set("h5InstanceViewUrl", processDesign.getH5InstanceViewUrl());
jsonObject.set("icon", processDesign.getIcon()); jsonObject.set("icon", processDesign.getIcon());
jsonObject.set("picIcon", processDesign.getPicIcon()); jsonObject.set("picIcon", processDesign.getPicIcon());
jsonObject.set("description", processDesign.getDescription()); jsonObject.set("description", processDesign.getDescription());
processDesign.setContent(jsonObject); processDesign.setContent(jsonObject);
processDesignService.update(processDesign); processDesignService.update(processDesign);
return Result.success(); return Result.success();
} }
@At @At
@ApiOperation("删除流程设计") @ApiOperation("删除流程设计")
@SaCheckPermission("flow.design") @SaCheckPermission("flow.design")
public Result delete(@Param("id") Long id) { public Result delete(@Param("id") Long id) {
dao.delete(ProcessDesign.class, id); dao.delete(ProcessDesign.class, id);
return Result.success(); return Result.success();
} }
@At @At
@SaCheckLogin @SaCheckLogin
@ApiOperation("流程设计详情") @ApiOperation("流程设计详情")
public Result detail(@Param("id") Long id) { public Result detail(@Param("id") Long id) {
ProcessDesign design = dao.fetch(ProcessDesign.class, id); ProcessDesign design = dao.fetch(ProcessDesign.class, id);
return Result.success(design); return Result.success(design);
} }
@At @At
@ApiOperation("发布流程设计") @ApiOperation("发布流程设计")
@Aop(TransAop.READ_COMMITTED) @Aop(TransAop.READ_COMMITTED)
@SaCheckPermission("flow.design") @SaCheckPermission("flow.design")
public Result deploy(@Param("id") Long id) { public Result deploy(@Param("id") Long id) {
processDesignService.deploy(id); processDesignService.deploy(id);
return Result.success(); return Result.success();
} }
@At @At
@SaCheckLogin @SaCheckLogin
@ApiOperation("获取流程设计任务参与者处理类") @ApiOperation("获取流程设计任务参与者处理类")
public Result assigmentHandlerClass() { public Result assigmentHandlerClass() {
return Result.success(ASSIGMENT_HANDLER_LIST); return Result.success(ASSIGMENT_HANDLER_LIST);
} }
@At @At
@SaCheckLogin @SaCheckLogin
@ApiOperation("获取流程设计任务参与者处理类") @ApiOperation("获取流程设计任务参与者处理类")
public Result candidateHandlerClass() { public Result candidateHandlerClass() {
return Result.success(CANDIDATE_HANDLER_LIST); return Result.success(CANDIDATE_HANDLER_LIST);
} }
@At @At
@SaCheckLogin @SaCheckLogin
@ApiOperation("获取流程设计任务参与者分页数据") @ApiOperation("获取流程设计任务参与者分页数据")
public Result assigneePage(Integer pageNumber, Integer pageSize, String searchKeyword, @Param("userIds") String[] userIds) { public Result assigneePage(Integer pageNumber, Integer pageSize, String searchKeyword, @Param("userIds") String[] userIds) {
Sql sql = Sqls.create("select id,loginname,username,unitName from vw_user $condition"); Sql sql = Sqls.create("select id,loginname,username,unitName from vw_user $condition");
Cnd cnd = Cnd.NEW(); Cnd cnd = Cnd.NEW();
if(StrUtil.isNotBlank(searchKeyword)) { if (StrUtil.isNotBlank(searchKeyword)) {
SqlExpressionGroup group = new SqlExpressionGroup(); SqlExpressionGroup group = new SqlExpressionGroup();
group.orLike("username", searchKeyword); group.orLike("username", searchKeyword);
group.orLike("loginname", searchKeyword); group.orLike("loginname", searchKeyword);
cnd.and(group); cnd.and(group);
} }
sql.setCondition(cnd); sql.setCondition(cnd);
// cnd.andEX("id", "in", userIds); // cnd.andEX("id", "in", userIds);
Pagination pagination = sysUserService.listPageMap(pageNumber, pageSize, sql); Pagination pagination = sysUserService.listPageMap(pageNumber, pageSize, sql);
return Result.success(pagination); return Result.success(pagination);
} }
@At @At
@SaCheckLogin @SaCheckLogin
@ApiOperation("获取流程设计任务参与者分页数据回显") @ApiOperation("获取流程设计任务参与者分页数据回显")
public Result assigneeEcho(@Param("userIds") String[] userIds) { public Result assigneeEcho(@Param("userIds") String[] userIds) {
Sql sql = Sqls.create("select id,loginname,username,unitName from vw_user where id in (@userIds)"); Sql sql = Sqls.create("select id,loginname,username,unitName from vw_user where id in (@userIds)");
sql.setParam("userIds", userIds); sql.setParam("userIds", userIds);
List<NutMap> list = sysUserService.listMap(sql); List<NutMap> list = sysUserService.listMap(sql);
return Result.success(list); return Result.success(list);
} }
} }
@@ -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 {
@@ -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 : [])
}) })
} }
}, },
@@ -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,
} }
}, },
computed: {
// 详情和类型列表任意顺序返回都重新匹配;未匹配时保证附件区域可安全读取属性。
chooseType() {
return this.typeOptions.find(o => o.id === this.formData.type) || {}
}
},
methods: { methods: {
async userRemoteMethod(event, type) { // 打开人员选择时清除上次搜索,并使之前尚未返回的请求失效。
if (event) { openUserSelect(type) {
this.userOptions = await this.selectQueryUser(event) this.resetUserSearch()
type === 'help' ? this.helpUserSelectShow = true : this.payUserSelectShow = true this.$set(this, type === 'help' ? 'helpUserSelectShow' : 'payUserSelectShow', true)
}
}, },
async selectQueryUser(keyword) { resetUserSearch() {
const res = await this.$axios.post("/platform/condolence/apply/listUser", { keyword: keyword }) this.userSearchSequence++
return res.data 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 + ")" }))
})
}) })
}, },
}, },