feat: 特殊慰问表单优化2

This commit is contained in:
2026-10-30 20:30:12 +08:00
parent efad953710
commit 81fd5cb773
15 changed files with 130 additions and 82 deletions
@@ -1,16 +1,16 @@
<el-descriptions-item label="慰问类型">
<el-descriptions-item label="慰问类型" :span="2">
<el-form-item label="慰问类型" prop="type">
<el-select v-model="formData.type" filterable @change="typeChange" style="width:100%" placeholder="请选择慰问类型">
<el-option v-for="t in typeOptions" :key="t.id" :value="t.id" :label="t.name"></el-option>
</el-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="慰问金额">
<el-descriptions-item label="慰问金额" :span="2">
<el-form-item label="慰问金额" prop="perMoney" :rules="recipientRules.money">
<el-input-number v-model="formData.perMoney" :precision="2" :min="0" :max="10000" :controls="false" style="width:100%" placeholder="每人慰问金额(元)"></el-input-number>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="慰问时间">
<el-descriptions-item label="慰问时间" :span="2">
<el-form-item label="慰问时间" prop="occurTime" :rules="recipientRules.occurTime">
<el-date-picker v-model="formData.occurTime" type="date" value-format="yyyy-MM-dd" style="width:100%" placeholder="请选择慰问时间"></el-date-picker>
</el-form-item>
@@ -12,24 +12,25 @@ layout("/layouts/platform.html"){
class="flow-task-form">
<el-tabs v-model="activeApplicationTab">
<el-tab-pane label="基础信息" name="form">
<el-descriptions :column="3" border size="small">
<el-descriptions-item label="事项"><el-form-item prop="subject" label="事项"><el-input v-model="formData.subject" maxlength="200" show-word-limit placeholder="请输入特殊慰问事项"></el-input></el-form-item></el-descriptions-item>
<el-descriptions :column="6" border size="small">
<el-descriptions-item label="事项" :span="2"><el-form-item prop="subject" label="事项"><el-input v-model="formData.subject" maxlength="200" show-word-limit placeholder="请输入特殊慰问事项"></el-input></el-form-item></el-descriptions-item>
<el-descriptions-item label="申请人姓名">{{formData.applyUserName}}</el-descriptions-item>
<el-descriptions-item label="申请人工号">{{formData.applyLoginName}}</el-descriptions-item>
<el-descriptions-item label="申请人单位" :span="2">{{formData.applyUnitName}}</el-descriptions-item>
<el-descriptions-item label="申请人工会">{{formData.applyUnionName}}</el-descriptions-item>
<el-descriptions-item label="申请人姓名" :span="2">{{formData.applyUserName}}</el-descriptions-item>
<el-descriptions-item label="申请人工号" :span="2">{{formData.applyLoginName}}</el-descriptions-item>
<!--#include('config.html'){}#-->
<el-descriptions-item label="申请事由" :span="3">
<el-descriptions-item label="申请人单位" :span="2">{{formData.applyUnitName}}</el-descriptions-item>
<el-descriptions-item label="申请人工会" :span="2">{{formData.applyUnionName}}</el-descriptions-item>
<el-descriptions-item label="" :span="2"><span></span></el-descriptions-item>
<el-descriptions-item label="申请事由" :span="6">
<el-form-item prop="remark" label="申请事由">
<el-input maxlength="500" v-model="formData.remark" placeholder="请填写申请事由"
type="textarea" :rows="3" resize="none"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item :span="3" v-if="chooseType.isUploadFile === true">
<el-descriptions-item :span="6" v-if="chooseType.isUploadFile === true">
<template slot="label">
附件
<el-tooltip class="item" effect="dark" :content="'上传附件说明:' + chooseType.uploadFileDesc"
@@ -49,7 +50,7 @@ layout("/layouts/platform.html"){
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="签字" :span="3">
<el-descriptions-item label="签字" :span="6">
<el-form-item prop="signature" label="签字">
<pc-signature v-model="formData.signature"></pc-signature>
</el-form-item>
@@ -221,11 +222,7 @@ layout("/layouts/platform.html"){
})
},
onSubmit() {
if (!Array.isArray(this.formData.recipients) || this.formData.recipients.length === 0) {
this.activeApplicationTab = 'recipients'
this.$message.error('请至少添加一位慰问对象')
return
}
if (!this.ensureApplicationRecipients()) return
this.$refs.formRef.validate((valid, invalidFields) => {
if (!valid) { this.showInvalidApplicationTab(invalidFields); return }
if (valid) {
@@ -247,11 +244,7 @@ layout("/layouts/platform.html"){
})
},
onFinishTask() {
if (!Array.isArray(this.formData.recipients) || this.formData.recipients.length === 0) {
this.activeApplicationTab = 'recipients'
this.$message.error('请至少添加一位慰问对象')
return
}
if (!this.ensureApplicationRecipients()) return
this.$refs.formRef.validate((valid, invalidFields) => {
if (!valid) { this.showInvalidApplicationTab(invalidFields); return }
if (valid) {
@@ -26,6 +26,20 @@ const specialCondolenceRecipients = {
const fields = Array.isArray(errors) ? errors.map(error => error.name || '') : Object.keys(errors || {})
if (!fields.length) return
this.activeApplicationTab = fields.some(field => !field.startsWith('recipients')) ? 'form' : 'recipients'
if (this.activeApplicationTab === 'recipients') this.notifyRecipientError('请完善慰问对象的必填信息')
},
notifyRecipientError(message) {
if (this.$toast && this.$toast.fail) this.$toast.fail(message)
else this.$message.error(message)
},
ensureApplicationRecipients() {
const rows = this.formData.recipients
if (!Array.isArray(rows) || rows.length === 0 || rows.some(row => !row || !String(row.helpUserId || '').trim())) {
this.activeApplicationTab = 'recipients'
this.notifyRecipientError('请先选择慰问对象,并填写完整信息')
return false
}
return true
},
createRecipientRules() {
const required = label => ({ required: true, whitespace: true, message: '请填写' + label, trigger: ['blur', 'change'] })
@@ -7,26 +7,27 @@ const specialcondolenceInfo = {
申请信息
<el-link type="primary" @click="openChart">点击查看流程图</el-link>
</div>
<el-descriptions :column="3" border>
<el-descriptions-item label="事项" :span="3">{{ viewData.subject || '--' }}</el-descriptions-item>
<el-descriptions-item label="申请人姓名">{{ viewData.applyUserName }}</el-descriptions-item>
<el-descriptions-item label="申请人工号">{{ viewData.applyLoginName }}</el-descriptions-item>
<el-descriptions-item label="申请人单位">{{ viewData.applyUnitName }}</el-descriptions-item>
<el-descriptions-item label="申请人工会">{{ viewData.applyUnionName }}</el-descriptions-item>
<el-descriptions :column="6" border size="small" :label-style="{ width: '130px', minWidth: '130px', maxWidth: '130px', fontSize: '14px', fontWeight: 400, lineHeight: '32px', padding: '8px 12px' }" :content-style="{ fontSize: '14px', fontWeight: 400, lineHeight: '32px', padding: '8px 12px' }">
<el-descriptions-item label="事项" :span="2">{{ viewData.subject || '--' }}</el-descriptions-item>
<el-descriptions-item label="申请人姓名" :span="2">{{ viewData.applyUserName }}</el-descriptions-item>
<el-descriptions-item label="申请人工号" :span="2">{{ viewData.applyLoginName }}</el-descriptions-item>
<template v-if="viewData.recipients && viewData.recipients.length">
<el-descriptions-item label="慰问类型">{{ viewData.typeName }}</el-descriptions-item>
<el-descriptions-item label="每人慰问金额">{{ viewData.perMoney }} 元</el-descriptions-item>
<el-descriptions-item label="慰问时间">{{ viewData.occurTime }}</el-descriptions-item>
<el-descriptions-item label="慰问类型" :span="2">{{ viewData.typeName }}</el-descriptions-item>
<el-descriptions-item label="每人慰问金额" :span="2">{{ viewData.perMoney }} 元</el-descriptions-item>
<el-descriptions-item label="慰问时间" :span="2">{{ viewData.occurTime }}</el-descriptions-item>
</template>
<el-descriptions-item label="申请事由" :span="3">
<el-descriptions-item label="申请人单位" :span="2">{{ viewData.applyUnitName }}</el-descriptions-item>
<el-descriptions-item label="申请人工会" :span="2">{{ viewData.applyUnionName }}</el-descriptions-item>
<el-descriptions-item label="" :span="2"><span></span></el-descriptions-item>
<el-descriptions-item label="申请事由" :span="6">
<div style="white-space: pre-line">{{ viewData.remark }}</div>
</el-descriptions-item>
<el-descriptions-item label="附件" :span="3">
<el-descriptions-item label="附件" :span="6">
<file-preview v-if="viewData.files && viewData.files.length > 0" :files="viewData.files"
complete_result></file-preview>
<span v-else>暂无附件</span>
</el-descriptions-item>
<el-descriptions-item label="签字" :span="3">
<el-descriptions-item label="签字" :span="6">
<el-image :src="viewData.signature"
v-if="viewData.signature"
class="signature-image"></el-image>
@@ -30,11 +30,15 @@ layout("/layouts/platform_h5.html"){
background: #f3f7fc;
}
.specialcondolence-apply-form > .van-tabs > .van-tabs__content {
padding-top: 11px;
}
.specialcondolence-apply-form .form-section {
margin-bottom: 11px;
overflow: hidden;
border: 1px solid #e9eff7;
border-radius: 10px;
border-radius: 0;
background: #fff;
box-shadow: 0 3px 11px rgba(51, 87, 126, 0.08);
}
@@ -173,7 +177,7 @@ layout("/layouts/platform_h5.html"){
placeholder></van-nav-bar>
<!-- 表单容器 -->
<van-form ref="formRef" class="form-container specialcondolence-apply-form">
<van-form ref="formRef" class="form-container specialcondolence-apply-form" :show-error="true" :show-error-message="true">
<van-tabs v-model="activeApplicationTab" :lazy-render="false">
<van-tab title="基础信息" name="form">
@@ -195,7 +199,7 @@ layout("/layouts/platform_h5.html"){
<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>
<van-popup v-model="showTimePicker" position="bottom" round get-container="body"><van-datetime-picker v-if="showTimePicker" v-model="formData.occurDate" type="date" :min-date="minDate" :max-date="maxDate" title="请选择慰问时间" @confirm="confirmOccurTime" @cancel="showTimePicker = false"></van-datetime-picker></van-popup>
<van-field
v-model="formData.remark"
name="remark"
@@ -252,7 +256,7 @@ layout("/layouts/platform_h5.html"){
<h2 class="specialcondolence-card__title">慰问对象</h2>
<van-cell-group :border="false">
<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-cell :title="'慰问对象 ' + (index + 1)" :title-style="{ fontWeight: 'bold' }"><van-button native-type="button" size="mini" @click="formData.recipients.splice(index, 1)">删除</van-button></van-cell>
<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>
@@ -288,7 +292,7 @@ layout("/layouts/platform_h5.html"){
return {
bizId: GetQueryString("bizId"),
taskId: GetQueryString("taskId"),
formData: { recipients: [] },
formData: { recipients: [this.newRecipient()], occurTime: this.$moment().format('YYYY-MM-DD') },
chooseType: {},
userOptions: [],
@@ -310,13 +314,30 @@ layout("/layouts/platform_h5.html"){
showHospitalizationTimePicker: false,
showLeaveHospitalTimePicker: false,
minDate: new Date(2024, 0, 1),
maxDate: new Date(),
maxDate: new Date(2100, 11, 31),
typeDefaultIndex: 0
}
},
watch: {
'$store.state.user'(user) {
if (user && !this.bizId && !this.formData.applyUserId) this.init()
}
},
methods: {
showInvalidApplicationTab(errors) {
if (!Array.isArray(errors) || !errors.length) return
const error = errors[0]
const name = String(error.name || '')
const recipient = name.match(/^recipients\.(\d+)\./)
this.activeApplicationTab = name.startsWith('recipients') ? 'recipients' : 'form'
const message = error.message || '请完善必填信息'
this.$toast.fail(recipient ? '第' + (Number(recipient[1]) + 1) + '位慰问对象:' + message : message)
this.$nextTick(() => {
this.$refs.formRef.scrollToField(error.name)
})
},
mobileRecipientRules(field, person) {
const names = { helpUserId: '慰问对象', helpLoginName: '工号', idCard: '身份证号码', bankOfDeposit: '开户行', bankUserName: '户名', bankCardNumber: '收款账户' }
if (field === 'helpLoginName') return [{ validator: value => person.personType === '劳务派遣人员' || !!String(value || '').trim(), message: '普通人员工号不能为空' }]
@@ -508,11 +529,10 @@ layout("/layouts/platform_h5.html"){
}
})
} else {
const { username, loginname, id, unit, union, mobile } = this.$store.state.user
this.formData = {
recipients: [this.newRecipient()],
perMoney: undefined,
occurTime: this.$moment().format('YYYY-MM-DD'),
const user = this.$store.state.user
if (!user) return
const { username, loginname, id, unit, union, mobile } = user
this.formData = Object.assign({}, this.formData, {
applyUserName: username,
applyLoginName: loginname,
applyUserId: id,
@@ -520,7 +540,7 @@ layout("/layouts/platform_h5.html"){
applyUnitName: unit?.name,
applyUnionId: union?.id,
applyUnionName: union?.name
}
})
}
},
querySpecialCondolenceType() {
@@ -36,11 +36,15 @@
padding: 12px 15px calc(18px + env(safe-area-inset-bottom));
}
.specialcondolence-info-main > .van-tabs > .van-tabs__content {
padding-top: 11px;
}
.specialcondolence-info-card {
margin-bottom: 11px;
overflow: hidden;
border: 1px solid #e9eff7;
border-radius: 10px;
border-radius: 0;
background: #fff;
box-shadow: 0 3px 11px rgba(51, 87, 126, .08);
}
@@ -79,7 +83,7 @@
padding: 12px;
box-sizing: border-box;
border: 1px solid #c9d5e5;
border-radius: 10px;
border-radius: 0;
background: #f7f9fd;
}
@@ -55,7 +55,7 @@ const specialcondolenceInfo = {
<h2 class="specialcondolence-info-card__title">慰问对象</h2>
<van-cell-group :border="false">
<template v-for="(person, index) in viewData.recipients">
<van-cell :title="'慰问对象 ' + (index + 1)" :value="person.helpUserName"></van-cell>
<van-cell :title="'慰问对象 ' + (index + 1)" :title-style="{ fontWeight: 'bold' }" :value="person.helpUserName"></van-cell>
<van-cell title="工号" :value="person.helpLoginName || '--'"></van-cell>
<van-cell title="身份证号码" :value="person.idCard"></van-cell>
<van-cell title="开户行" :value="person.bankOfDeposit"></van-cell>
@@ -134,7 +134,7 @@ layout("/layouts/platform_h5.html"){
<h2 class="specialcondolence-info-card__title">
审批意见<span class="specialcondolence-audit-card__required">*</span>
</h2>
<van-form ref="formRef">
<van-form ref="formRef" :show-error="true" :show-error-message="true">
<van-field
v-model="formData.tf_opinion"
class="specialcondolence-audit-field"
@@ -142,7 +142,7 @@ layout("/layouts/platform_h5.html"){
type="textarea"
rows="6"
placeholder="请输入审批意见"
:rules="[{ required: true, message: '请填写审批意见' }]"
:rules="[{ validator: value => !!String(value || '').trim(), message: '请填写审批意见' }]"
maxlength="100"
show-word-limit
></van-field>
@@ -262,7 +262,13 @@ layout("/layouts/platform_h5.html"){
if (window.h5HistoryLayerManager && window.h5HistoryLayerManager.open("specialcondolence-action-confirm")) return
this.$set(this, "confirmVisible", true)
})
.catch(() => {})
.catch(errors => {
if (!Array.isArray(errors) || !errors.length) return
this.$toast(errors[0].message || '请完善审批信息')
this.$nextTick(() => {
this.$refs.formRef.scrollToField(errors[0].name)
})
})
},
// 确认操作时先回退确认框历史,再根据操作类型调用办理或撤回接口。
confirmPendingAction() {
@@ -134,7 +134,7 @@ layout("/layouts/platform_h5.html"){
<h2 class="specialcondolence-info-card__title">
审批意见<span class="specialcondolence-audit-card__required">*</span>
</h2>
<van-form ref="formRef">
<van-form ref="formRef" :show-error="true" :show-error-message="true">
<van-field
v-model="formData.tf_opinion"
class="specialcondolence-audit-field"
@@ -142,7 +142,7 @@ layout("/layouts/platform_h5.html"){
type="textarea"
rows="6"
placeholder="请输入审批意见"
:rules="[{ required: true, message: '请填写审批意见' }]"
:rules="[{ validator: value => !!String(value || '').trim(), message: '请填写审批意见' }]"
maxlength="100"
show-word-limit
></van-field>
@@ -245,7 +245,13 @@ layout("/layouts/platform_h5.html"){
if (window.h5HistoryLayerManager && window.h5HistoryLayerManager.open("specialcondolence-action-confirm")) return
this.$set(this, "confirmVisible", true)
})
.catch(() => {})
.catch(errors => {
if (!Array.isArray(errors) || !errors.length) return
this.$toast(errors[0].message || '请完善审批信息')
this.$nextTick(() => {
this.$refs.formRef.scrollToField(errors[0].name)
})
})
},
// 确认操作时先回退确认框历史,再根据操作类型调用办理或撤回接口。
confirmPendingAction() {
@@ -134,7 +134,7 @@ layout("/layouts/platform_h5.html"){
<h2 class="specialcondolence-info-card__title">
审批意见<span class="specialcondolence-audit-card__required">*</span>
</h2>
<van-form ref="formRef">
<van-form ref="formRef" :show-error="true" :show-error-message="true">
<van-field
v-model="formData.tf_opinion"
class="specialcondolence-audit-field"
@@ -142,7 +142,7 @@ layout("/layouts/platform_h5.html"){
type="textarea"
rows="6"
placeholder="请输入审批意见"
:rules="[{ required: true, message: '请填写审批意见' }]"
:rules="[{ validator: value => !!String(value || '').trim(), message: '请填写审批意见' }]"
maxlength="100"
show-word-limit
></van-field>
@@ -245,7 +245,13 @@ layout("/layouts/platform_h5.html"){
if (window.h5HistoryLayerManager && window.h5HistoryLayerManager.open("specialcondolence-action-confirm")) return
this.$set(this, "confirmVisible", true)
})
.catch(() => {})
.catch(errors => {
if (!Array.isArray(errors) || !errors.length) return
this.$toast(errors[0].message || '请完善审批信息')
this.$nextTick(() => {
this.$refs.formRef.scrollToField(errors[0].name)
})
})
},
// 确认操作时先回退确认框历史,再根据操作类型调用办理或撤回接口。
confirmPendingAction() {