feat: 慰问、困难帮扶

This commit is contained in:
2026-10-30 17:49:45 +08:00
parent 16cae3ed2b
commit f8457386fd
22 changed files with 207 additions and 290 deletions
@@ -114,33 +114,6 @@ layout("/layouts/platform_h5.html"){
审批意见<span class="difficult-help-audit-card__required">*</span>
</h2>
<van-form ref="formRef">
<section class="difficult-help-info-card">
<h2 class="difficult-help-info-card__title">审核信息</h2>
<div class="difficult-help-audit-form">
<van-field
v-model="formData.level"
class="difficult-help-audit-select"
name="level"
label="级别"
placeholder="请选择级别"
readonly
is-link
required
@click="openLevelPicker"
:rules="[{ required: true, message: '请选择级别' }]"
></van-field>
<van-field
v-model="formData.money"
class="difficult-help-audit-money"
name="money"
label="帮扶金额(元)"
placeholder="请输入帮扶金额(元)"
type="number"
required
:rules="[{ required: true, message: '请输入帮扶金额(元)' }]"
></van-field>
</div>
</section>
<van-field
v-model="formData.tf_opinion"
class="difficult-help-audit-textarea"
@@ -167,14 +140,6 @@ layout("/layouts/platform_h5.html"){
</div>
</div>
</info>
<van-popup :value="showLevelPicker" position="bottom" :close-on-click-overlay="false">
<van-picker
show-toolbar
:columns="levelColumns"
@confirm="onLevelConfirm"
@cancel="closeLevelPicker">
</van-picker>
</van-popup>
<van-dialog
:value="confirmVisible"
title="提示"
@@ -214,8 +179,6 @@ layout("/layouts/platform_h5.html"){
skeletonLoading: true,
formData: {},
levelColumns: [],
showLevelPicker: false,
showApprovalForm: false,
formLoading: false,
confirmVisible: false,
@@ -280,42 +243,11 @@ layout("/layouts/platform_h5.html"){
this.$set(this, "formData", {
processTaskId: row.taskId,
taskName: row.curTaskName,
level: "",
money: undefined,
tf_sign: "", tf_opinion: ""
})
this.$refs.infoRef.onOpen(row, row.curTaskName || "帮扶审核")
},
// 加载困难级别字典并转换为 Vant Picker 所需的 text/value 结构。
initLevelDict() {
return this.$axios.post("/open/common/dictOptions", {code: "DIFFICULT_LEVEL"}, {h5SkeletonLoading: true}).then((res) => {
const levelData = res && res.code === 0 ? res.data : []
this.$set(this, "levelColumns", (levelData || []).map((item) => ({
text: item.name,
value: item.code
})))
})
},
// 级别选择器作为详情上层弹框,打开时同步增加浏览器历史。
openLevelPicker() {
if (window.h5HistoryLayerManager && window.h5HistoryLayerManager.open("difficult-help-level-picker")) return
this.$set(this, "showLevelPicker", true)
},
closeLevelPicker(afterClose = null) {
if (window.h5HistoryLayerManager && window.h5HistoryLayerManager.close("difficult-help-level-picker", afterClose)) return
this.$set(this, "showLevelPicker", false)
if (typeof afterClose === "function") afterClose()
},
onLevelConfirm(option) {
this.closeLevelPicker(() => {
this.$set(this.formData, "level", option.value)
})
},
// val 为流程提交类型:1 同意、2 拒绝、6 退回;校验通过后打开历史栈确认框。
handleTaskAction(val) {
this.$refs.formRef.validate()
@@ -427,14 +359,12 @@ layout("/layouts/platform_h5.html"){
},
},
created() {
// 先订阅弹框状态,工会加载异常也不能阻断等级选择器与确认框的打开、返回。
// 先订阅弹框状态,工会加载异常也不能阻断确认框的打开、返回。
if (window.h5HistoryLayerManager) {
this.$set(this, "historyLayerUnsubscribe", window.h5HistoryLayerManager.subscribe((stack) => {
this.$set(this, "confirmVisible", stack.includes("difficult-help-action-confirm"))
this.$set(this, "showLevelPicker", stack.includes("difficult-help-level-picker"))
}))
}
this.initLevelDict()
// 缓存已就绪时立即加载,否则等待用户接口回填;只初始化一次,避免重置已选筛选条件。
// $watch 由当前 Vue 实例管理,页面销毁时自动注销。
let filtersInitialized = false
@@ -113,18 +113,6 @@ layout("/layouts/platform_h5.html"){
<section class="difficult-help-info-card">
<h2 class="difficult-help-info-card__title">审核信息</h2>
<div class="difficult-help-audit-form">
<van-field
v-model="formData.level"
class="difficult-help-audit-select"
name="level"
label="级别"
placeholder="请选择级别"
readonly
is-link
required
@click="openLevelPicker"
:rules="[{ required: true, message: '请选择级别' }]"
></van-field>
<van-field
v-model="formData.money"
class="difficult-help-audit-money"
@@ -167,14 +155,6 @@ layout("/layouts/platform_h5.html"){
</div>
</div>
</info>
<van-popup :value="showLevelPicker" position="bottom" :close-on-click-overlay="false">
<van-picker
show-toolbar
:columns="levelColumns"
@confirm="onLevelConfirm"
@cancel="closeLevelPicker">
</van-picker>
</van-popup>
<van-dialog
:value="confirmVisible"
title="提示"
@@ -216,8 +196,6 @@ layout("/layouts/platform_h5.html"){
formData: {},
showApprovalForm: false,
formLoading: false,
showLevelPicker: false,
levelColumns: [],
confirmVisible: false,
confirmActionType: "task",
pendingSubmitType: null,
@@ -272,42 +250,12 @@ layout("/layouts/platform_h5.html"){
this.$set(this, "formData", {
processTaskId: row.taskId,
taskName: row.curTaskName,
level: "",
money: undefined,
tf_sign: "", tf_opinion: ""
})
this.$refs.infoRef.onOpen(row, row.curTaskName || "帮扶审核")
},
// 加载困难级别字典并转换为 Vant Picker 所需的 text/value 结构。
initLevelDict() {
return this.$axios.post("/open/common/dictOptions", {code: "DIFFICULT_LEVEL"}, {h5SkeletonLoading: true}).then((res) => {
const levelData = res && res.code === 0 ? res.data : []
this.$set(this, "levelColumns", (levelData || []).map((item) => ({
text: item.name,
value: item.code
})))
})
},
// 级别选择器作为详情上层弹框,打开时同步增加浏览器历史。
openLevelPicker() {
if (window.h5HistoryLayerManager && window.h5HistoryLayerManager.open("difficult-help-level-picker")) return
this.$set(this, "showLevelPicker", true)
},
closeLevelPicker(afterClose = null) {
if (window.h5HistoryLayerManager && window.h5HistoryLayerManager.close("difficult-help-level-picker", afterClose)) return
this.$set(this, "showLevelPicker", false)
if (typeof afterClose === "function") afterClose()
},
onLevelConfirm(option) {
this.closeLevelPicker(() => {
this.$set(this.formData, "level", option.value)
})
},
// val 为流程提交类型:1 同意、2 拒绝、6 退回;校验通过后打开历史栈确认框。
handleTaskAction(val) {
this.$refs.formRef.validate()
@@ -420,11 +368,9 @@ layout("/layouts/platform_h5.html"){
},
created() {
this.initUnion().then(() => this.flushUnits())
this.initLevelDict()
if (!window.h5HistoryLayerManager) return
this.$set(this, "historyLayerUnsubscribe", window.h5HistoryLayerManager.subscribe((stack) => {
this.$set(this, "confirmVisible", stack.includes("difficult-help-action-confirm"))
this.$set(this, "showLevelPicker", stack.includes("difficult-help-level-picker"))
}))
},
beforeDestroy() {
@@ -162,6 +162,9 @@ layout("/layouts/platform_h5.html"){
#app .van-picker-column__item {
font-size: 18px;
}
.specialcondolence-apply-form .van-field__error-message,
.specialcondolence-apply-form .van-field--error .van-field__control { color: #ee0a24 !important; }
.specialcondolence-apply-form .van-field__error-message { font-size: 12px; line-height: 18px; padding-top: 4px; }
</style>
<div id="app">
@@ -185,19 +188,22 @@ layout("/layouts/platform_h5.html"){
<van-field label="申请人工会" :rules="[{ required: true }]" v-model="formData.applyUnionName" readonly
required name="applyUnionName"></van-field>
<van-field label="慰问类型" required><template #input><select v-model="formData.type" @change="typeChange(formData.type)"><option value="">请选择</option><option v-for="t in typeOptions" :key="t.id" :value="t.id">{{t.name}}</option></select></template></van-field>
<van-field v-model="formData.perMoney" label="每人金额" type="number" required :rules="[{ validator: validateMoney, message: '金额须大于0且不超过10000元,最多两位小数' }]"></van-field>
<van-field v-model="formData.occurTime" label="慰问时间" placeholder="yyyy-MM-dd" required :rules="[{required:true}]"></van-field>
<van-field :value="chooseType.name || formData.typeName" name="type" label="慰问类型" readonly clickable is-link required placeholder="请选择慰问类型" :rules="[{ validator: () => !!formData.type, message: '请选择慰问类型' }]" @click="showTypePickerClick"></van-field>
<van-popup v-model="showTypePicker" position="bottom" round get-container="body"><van-picker :columns="typeColumns" :default-index="typeDefaultIndex" show-toolbar @confirm="onTypeConfirm" @cancel="showTypePicker = false"></van-picker></van-popup>
<van-field v-model="formData.perMoney" name="perMoney" label="每人金额" type="number" required :rules="[{ validator: validateMoney, message: '金额须大于0且不超过10000元,最多两位小数' }]"></van-field>
<van-field v-model="formData.occurTime" name="occurTime" label="慰问时间" readonly clickable is-link placeholder="请选择慰问时间" required :rules="[{ validator: value => $moment(value, 'YYYY-MM-DD', true).isValid(), message: '请选择有效慰问时间' }]" @click="showTimePickerClick"></van-field>
<van-popup v-model="showTimePicker" position="bottom" round get-container="body"><van-datetime-picker v-model="formData.occurDate" type="date" :min-date="minDate" :max-date="new Date(2100, 11, 31)" title="请选择慰问时间" @confirm="confirmOccurTime" @cancel="showTimePicker = false"></van-datetime-picker></van-popup>
<div v-for="(person, index) in formData.recipients" :key="index">
<van-cell :title="'慰问对象 ' + (index + 1)"><van-button native-type="button" size="mini" @click="formData.recipients.splice(index, 1)">删除</van-button></van-cell>
<van-field v-model="person.helpUserName" label="慰问对象" required :rules="[{required:true}]"></van-field>
<van-field v-model="person.helpLoginName" label="工号" placeholder="普通人员必填,劳务派遣可空"></van-field>
<van-field v-model="person.idCard" label="身份证号码" maxlength="18" required :rules="[{required:true}]"></van-field>
<van-field v-model="person.bankOfDeposit" label="开户行" maxlength="100" required :rules="[{required:true}]"></van-field>
<van-field v-model="person.bankUserName" label="户名" maxlength="100" required :rules="[{required:true}]"></van-field>
<van-field v-model="person.bankCardNumber" label="收款账户" maxlength="30" required :rules="[{required:true}]"></van-field>
<h5-user-select v-model="person.helpUserId" :display-name="person.helpUserName" api="/platform/special_condolence/apply/listUser" label="慰问对象" placeholder="点击选择本工会人员" required :name="'recipients.' + index + '.helpUserId'" :rules="mobileRecipientRules('helpUserId', person)" @selected="(user, id) => recipientUserChange(person, index, id, user)"></h5-user-select>
<van-field v-model="person.helpLoginName" label="工号" readonly placeholder="选人后带出,劳务派遣可空" :required="person.personType !== '劳务派遣人员'" :name="'recipients.' + index + '.helpLoginName'" :rules="mobileRecipientRules('helpLoginName', person)"></van-field>
<van-field v-model="person.idCard" label="身份证号码" maxlength="18" required :name="'recipients.' + index + '.idCard'" :rules="mobileRecipientRules('idCard', person)"></van-field>
<van-field v-model="person.bankOfDeposit" label="开户行" maxlength="100" required :name="'recipients.' + index + '.bankOfDeposit'" :rules="mobileRecipientRules('bankOfDeposit', person)"></van-field>
<van-field v-model="person.bankUserName" label="户名" maxlength="100" required :name="'recipients.' + index + '.bankUserName'" :rules="mobileRecipientRules('bankUserName', person)"></van-field>
<van-field v-model="person.bankCardNumber" label="收款账户" maxlength="30" required :name="'recipients.' + index + '.bankCardNumber'" :rules="mobileRecipientRules('bankCardNumber', person)"></van-field>
</div>
<van-button native-type="button" @click="formData.recipients.push(newRecipient())">增加一行</van-button>
<van-field name="recipients" :value="recipientCount" :rules="[{ validator: value => Number(value) > 0, message: '请至少添加一位慰问对象' }]"><template #input><van-button native-type="button" size="small" type="info" plain @click="formData.recipients.push(newRecipient())">增加一行</van-button></template></van-field>
<van-cell title="慰问金额合计" :value="'¥ ' + recipientTotal + '(' + recipientCount + '人)'"></van-cell>
<van-field
v-model="formData.remark"
name="remark"
@@ -263,7 +269,9 @@ layout("/layouts/platform_h5.html"){
el: "#app",
store,
mixins: [specialCondolenceRecipients],
components: {},
components: {
'h5-user-select': httpVueLoader('/components/plugins/sysUserSelect/h5Index.vue?v=' + h5ComponentVersion)
},
data() {
return {
bizId: GetQueryString("bizId"),
@@ -297,6 +305,17 @@ layout("/layouts/platform_h5.html"){
}
},
methods: {
mobileRecipientRules(field, person) {
const names = { helpUserId: '慰问对象', helpLoginName: '工号', idCard: '身份证号码', bankOfDeposit: '开户行', bankUserName: '户名', bankCardNumber: '收款账户' }
if (field === 'helpLoginName') return [{ validator: value => person.personType === '劳务派遣人员' || !!String(value || '').trim(), message: '普通人员工号不能为空' }]
if (field === 'helpUserId') return [{ validator: () => !!person.helpUserId, message: '请选择慰问对象' }]
const rules = [{ validator: value => !!String(value || '').trim(), message: '请填写' + names[field] }]
if (field === 'idCard') rules.push({ validator: value => this.validRecipientIdCard(value), message: '身份证号码不正确' })
if (field === 'bankCardNumber') rules.push({ pattern: /^[0-9]{6,30}$/, message: '收款账户须为6至30位数字' })
if (field === 'bankOfDeposit' || field === 'bankUserName') rules.push({ validator: value => String(value || '').length <= 100, message: names[field] + '最多100字' })
return rules
},
validateMoney(value) {
return /^(0|[1-9][0-9]*)(\.[0-9]{1,2})?$/.test(String(value)) && Number(value) > 0 && Number(value) <= 10000
},
@@ -316,13 +335,14 @@ layout("/layouts/platform_h5.html"){
},
// 选择慰问时间
showTimePickerClick() {
if (this.formData.occurTime) {
this.formData.occurDate = new Date(this.formData.occurTime)
}else{
this.formData.occurDate = new Date()
}
this.$set(this.formData, 'occurDate', this.formData.occurTime ? this.$moment(this.formData.occurTime, 'YYYY-MM-DD').toDate() : new Date())
this.showTimePicker = true
},
confirmOccurTime(value) {
this.$set(this.formData, 'occurTime', this.$moment(value).format('YYYY-MM-DD'))
this.showTimePicker = false
this.$nextTick(() => this.$refs.formRef.validate('occurTime').catch(() => {}))
},
// 选择慰问类型
showTypePickerClick() {
if (this.formData.type) {
@@ -411,6 +431,7 @@ layout("/layouts/platform_h5.html"){
this.showTypePicker = false
},
onSave() {
this.$refs.formRef.validate().then(() => {
this.$dialog.confirm({
title: "提示",
message: "您确定保存吗?"
@@ -418,10 +439,11 @@ layout("/layouts/platform_h5.html"){
this.$axios.post("/platform/special_condolence/apply/save", { data: JSON.stringify(this.formData) }).then(res => {
if (res.code === 0) {
this.$toast(res.msg)
this.$pjaxReplace("/platform/special_condolence/mine/h5")
window.location.replace("/platform/special_condolence/mine/h5")
}
})
})
}).catch(() => {})
},
async onSubmit() {
this.$refs.formRef.validate().then(() => {
@@ -436,7 +458,7 @@ layout("/layouts/platform_h5.html"){
this.$axios.post("/platform/special_condolence/apply/submit", { data: JSON.stringify(this.formData) }).then(res => {
if (res.code === 0) {
this.$toast(res.msg)
this.$pjaxReplace("/platform/special_condolence/mine/h5")
window.location.replace("/platform/special_condolence/mine/h5")
}
})
})
@@ -458,7 +480,7 @@ layout("/layouts/platform_h5.html"){
}).then(res => {
if (res.code === 0) {
this.$toast(res.msg)
this.$pjaxReplace("/platform/special_condolence/mine/h5")
window.location.replace("/platform/special_condolence/mine/h5")
}
})
})
@@ -470,9 +492,7 @@ layout("/layouts/platform_h5.html"){
if (res.code === 0) {
this.formData = res.data
this.initRecipients()
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)
this.chooseType = this.typeOptions.find(o => o.id === this.formData.type) || {}
}
})
} else {
@@ -328,7 +328,6 @@ layout("/layouts/platform_h5.html"){
<div class="specialcondolence-card-header">
<div class="specialcondolence-card-heading">
<div class="specialcondolence-card-title">{{row.helpUserName || '--'}}</div>
<div class="specialcondolence-card-code">工号:{{row.helpLoginName || '--'}}</div>
</div>
<enum-tag class="specialcondolence-card-status" v-if="row.instanceState" :value="row.instanceState"
name="ProcessInstanceStateEnum" label_key="message" size="small"></enum-tag>
@@ -336,11 +335,11 @@ layout("/layouts/platform_h5.html"){
</template>
<template v-slot="{index,row}">
<table-column label="慰问对象">{{row.helpUserName}}</table-column>
<table-column label="慰问对象工号">{{row.helpLoginName}}</table-column>
<table-column label="申请人">{{row.applyUserName}}</table-column>
<table-column label="所属工会">{{row.applyUnionName}}</table-column>
<table-column label="所属单位">{{row.applyUnitName}}</table-column>
<table-column label="慰问类型">{{row.typeName}}</table-column>
<table-column label="慰问人数">{{row.recipientCount}} 人</table-column>
<table-column label="当前节点">{{row.taskName}}</table-column>
</template>
<template #actions="{index,row}">