page-multipage-form 办理类服务(多流程)模板
从开发者工具 v2.25.1-rc 版本开始支持。
解释:具有导航栏的办理类服务(多流程)模板,通常用来完成复杂多流程表单填写提交工作。本模板包含多个组件,可根据实际需要进行增删,支持代码的二次开发满足个性化诉求。
示例
扫码体验
代码示例
请使用百度APP扫码
页面内容
模板包含两个页面:多步骤表单页、提交状态页(成功 / 失败)。
多步骤表单页
将整个表单划分为多个步骤,每个步骤收集不同分类的信息,开发者可自定义步骤长度,在每个步骤中提供了单选、多选、输入、上传图片等多种表单类型,可根据实际需求选用,模板还提供了提交状态页面,用于展示表单提交结果。
页面路径:index/index
代码示例
以下为部分代码示例注解
- SWAN
- JSON
<!-- 页面加载 -->
<smt-page-status s-if="isPageLoading || pageResult"
class="content"
loading="{{isPageLoading}}"
icon="{{errorConfig[pageResult].icon}}"
title="{{errorConfig[pageResult].title}}"
desc="{{errorConfig[pageResult].desc}}"
showBtn="{{errorConfig[pageResult].showBtn}}"
bind:smtreloading="check">
</smt-page-status>
<!-- 办理类服务(多流程)模板 -->
<view s-else class="{{isFullScreen ? 'iphonexs' : 'normal'}}">
<view class="thick-divid">
<gov-steps
active="{{active}}"
line-width="{{2}}"
steps="{{step}}">
</gov-steps>
</view>
<!-- 页面一 -->
<block s-if="{{active === 1}}">
<view class="thick-divid">
<gov-page-title title="标题一" size="middle" hasBorder></gov-page-title>
<!--
gov-input 输入框
1. ipt-item-type: short/long 标题可是四字或六字
在一个表单内,建议使用一致的标题宽度设置
2.ipt-value= "{{formData.key}}" //
ipt-name="key"
ipt-error-info="{{errorInfp.key+Error}}"
三项必配置,且key要一致
3. 输入框中清除事件 iptKeyClean, input事件 iptKeyInput
-->
<gov-input
type="idcard"
ipt-item-type="idcard"
ipt-title="身份证号"
ipt-value="{{formData.idcard}}"
iptErrorInfo="{{errorInfo.idcardError}}"
ipt-name="idcard"
maxlength="18"
ipt-item-width="100%"
placeholder-content="请输入"
bindiptclean="iptKeyClean"
bindkeyinput="iptKeyInput"
bindiptblur="iptblursfz">
</gov-input>
<gov-input
type="number"
ipt-item-type="phone"
ipt-title="手机号"
ipt-value="{{formData.phone}}"
ipt-error-info="{{errorInfo.phoneError}}"
ipt-name="phone"
maxlength="11"
ipt-item-width="100%"
placeholder-content="请输入"
bindiptclean="iptKeyClean"
bindkeyinput="iptKeyInput"
bindiptblur="iptblursjh">
</gov-input>
<gov-picker
label="日期"
mode=date
placeholder="请选择"
labelWidth="4em"
data-value="date"
start="{{startDate}}"
end="{{endDate}}"
errStatus="{{errorInfo.dateError}}"
value="{{formData.date}}"
bindchange="handleChange1">
</gov-picker>
<gov-picker
label="所在位置"
mode="location"
placeholder="请选择"
labelWidth="4em"
noborder="{{true}}"
errStatus="{{errorInfo.placeError}}"
locationName="{{formData.place}}"
bindchoosesuccess="choosesuccess"
bindchoosefail="choosefail">
</gov-picker>
</view>
<view>
<gov-page-title title="标题二" size="middle" hasBorder></gov-page-title>
<gov-input
type="text"
ipt-item-type="short"
ipt-title="输入框"
ipt-value="{{formData.iptone}}"
ipt-error-info="{{errorInfo.iptoneError}}"
ipt-name="iptone"
ipt-item-width="100%"
placeholder-content="请输入"
bindiptclean="iptKeyClean"
bindkeyinput="iptKeyInput">
</gov-input>
<gov-input
type="text"
ipt-item-type="short"
ipt-title="输入框"
ipt-value="{{formData.ipttwo}}"
ipt-error-info="{{errorInfo.ipttwoError}}"
ipt-notic-info="{{noticInfo.iptNoticInfo}}"
ipt-name="ipttwo"
ipt-item-width="100%"
placeholder-content="请输入"
bindiptclean="iptKeyClean"
bindkeyinput="iptKeyInput">
</gov-input>
<gov-picker
mode="selector"
range="{{options.singPicker}}"
label="选择框"
labelWidth="4em"
bindchange="handleChange3"
value="{{formData.sltsingle}}"
rangeKey="name"
errStatus="{{errorInfo.sltsingleError}}"
placeholder="请选择">
</gov-picker>
<gov-cascade
range="{{options.cascader}}"
label="选择框"
value="{{formData.sltdouble}}"
rangeKey="name"
labelWidth="4em"
tips="{{['请选择', '请选择', '请选择']}}"
bindchange="cacadaChange"
errStatus= "{{errorInfo.sltdoubleError}}"
placeholder="{{['请选择', '请选择', '请选择']}}"/>
</view>
</block>
<!-- 页面二 -->
<block s-if="{{active === 2}}">
<view class="thick-divid">
<gov-page-title title="单选标题" size="middle" hasBorder></gov-page-title>
<view class="radios">
<gov-radio-group
inline="{{false}}"
option-key="name"
active-color="#2772fb"
options="{{options.radiosValue}}"
bindchange="radioChange"
value="{{formData.radios}}">
</gov-radio-group>
</view>
</view>
<view>
<gov-page-title title="多选标题" size="middle" hasBorder></gov-page-title>
<view class="checkboxs">
<gov-checkbox-group
groupStyle="border-bottom: 0.6rpx solid #e6e6e6 !important"
inline="{{false}}"
option-key="name"
activeColor="#2772fb"
options="{{options.checkboxsValue}}"
bindchange="checkboxChange"
gov-checkbox-group="border"
value="{{formData.checkbox}}">
</gov-checkbox-group>
<gov-checkbox
bindchange="noHas"
activeColor="#2772fb"
value="{{formData.nochecked}}"
gov-checkbox="border">
不含以上情况
</gov-checkbox>
</view>
</view>
</block>
<!-- 页面三 -->
<block s-if="{{active === 3}}">
<view class="thick-divid">
<gov-textarea
gov-textarea-wrap="textareaWrap"
gov-textarea-element="textareaElement"
bindinput="iptTextarea"
placeholder="请输入"
head="长文本输入框标题"
value="{{formData.textBox}}"
maxlength="100">
</gov-textarea>
</view>
<view>
<view class="upload-title">
<gov-page-title title="上传照片标题" size="middle" hasBorder></gov-page-title>
</view>
<gov-upload
count="5"
gov-tips="tips"
bind:delete="clickDelete"
bind:uploadsuccess="uploadsuccess"
bind:urlempty="urlempty"
bind:previewfail="previewfail"
tips="最多支持5张图片,单张体积10M一下"
imageList="{{formData.uploadphotos}}"
limitSize="10"/>
</view>
</block>
<!-- 页面四 -->
<block s-if="{{active === 4}}">
<view s-for="informateFour.lists trackBy item" class="thick-divid">
<gov-page-title title="{{item.bigTitle}}" size="middle" hasBorder></gov-page-title>
<gov-list-item s-for="items, index in item.msg trackBy index"
gov-list-item="listItem"
gov-label="label"
label="{{items.title}}"
labelWidth="4em"
content="{{items.sub}}"
clickable
border="{{index !== item.msg.length-1}}">
</gov-list-item>
</view>
<view s-for="informateFour.expand trackBy item" class="thick-divid">
<gov-page-title
title="{{item.bigTitle}}"
size="middle"
gov-title-wrap="titleWrap">
</gov-page-title>
<view class="expand-wrap">
<gov-text-collapse
text="{{item.msg}}"
line="5">
</gov-text-collapse>
</view>
</view>
<view>
<gov-page-title title="{{informateFour.photos.bigTitle}}" size="middle" hasBorder></gov-page-title>
<view class="gov-image-wrap">
<gov-image-item s-for="informateFour.photos.msg trackBy item"
class="gov-plate-img"
image-src="{{item}}"
image-width="224.64"
image-height="224.64"
border-radius="10">
</gov-image-item>
</view>
</view>
<view class="wen">
<gov-prompt>
<view slot="title">温馨提示:</view>
<view slot="content">此板块为提示区,可用户提醒用户业务填写中的注意事项及要求<view class="prompt-view" bindtap="toView">点击查看</view>
</view>
</gov-prompt>
</view>
</block>
<view class="bottoms"></view>
<view class="tail">
<view class="btn">
<gov-button s-if="{{active !== 1}}"
button-size="middle"
button-text="上一步"
button-color="plain"
bindtap="prev">
</gov-button>
<gov-button
button-size="{{active===1 ? 'large':'middle'}}"
button-text="{{active === 4 ? '提交': '下一步'}}"
button-color="default"
bindtap="next">
</gov-button>
</view>
<view s-if="{{isFullScreen}}" class="{{isFullScreen ? 'iphonex-safe-height': 'normal-height'}}"></view>
</view>
</view>
{
"navigationBarTitleText": "办理类服务(多流程)模板",
"backgroundColor": "#fff",
"navigationBarBackgroundColor": "#fff",
"navigationBarTextStyle": "black",
"usingComponents": {
"gov-steps": "@smt-ui/component-gov/src/steps",
"gov-prompt": "@smt-ui/component-gov/src/prompt",
"gov-picker": "@smt-ui/component-gov/src/picker",
"gov-upload": "@smt-ui/component-gov/src/upload",
"gov-input": "@smt-ui/component-gov/src/input",
"gov-button": "@smt-ui/component-gov/src/button",
"gov-cascade": "@smt-ui/component-gov/src/cascade",
"gov-image-item": "@smt-ui/component-gov/src/image-item",
"gov-textarea": "@smt-ui/component-gov/src/textarea",
"gov-page-title": "@smt-ui/component-gov/src/page-title",
"smt-page-status": "@smt-ui/component/src/page-status",
"gov-list-item": "@smt-ui/component-gov/src/list-item",
"gov-radio-group": "@smt-ui/component-gov/src/radio-group",
"gov-checkbox": "@smt-ui/component-gov/src/checkbox",
"gov-checkbox-group": "@smt-ui/component-gov/src/checkbox-group",
"gov-text-collapse": "@smt-ui/component-gov/src/text-collapse"
}
}
获取页面数据
JS
/**
* 发送请求
*
* @param {Object=} data 请求接口参数
*/
getDetail(data = {}) {
//【需替换】:获取内容详情所需要的数据,请修改 url 字段为真实的请求地址,该接口仅做示例
let params = {
url: 'https://www.ceshi.com',
method: 'GET',
data,
success: res => {
// 接口正常返回处理逻辑
if (+res.code === 0) {
if (Object.keys(res.data).length) {
this.setData({
// merge 本地数据和异步数据赋值给 options
options: {...this.data.options, ...res.data}
}, () => {
this.setData({
isPageLoading: false,
pageResult: ''
});
});
}
else {
// 没有数据
this.setData({
isPageLoading: false,
pageResult: 'noData'
});
}
}
else {
// 接口异常处理逻辑
this.setData({
isPageLoading: false,
pageResult: 'warning'
});
}
},
fail: err => {
// 接口异常处理逻辑
this.setData({
isPageLoading: false,
pageResult: 'warning'
});
}
};
swan.request(params);
}
点击下一步按钮触发事件
JS
/**
* 点击下一步按钮触发事件
*/
next() {
// 输入框,选择框根据错误状态判断 toast 的状态,
// 多选,单选,长文本,上传照片根据 value 值判断 toast 的状态
const formData = this.data.formData;
// datas 用于保存第四步提交时的参数字符串
let datas = '';
// this.data.active 表示当前处于第几步
switch (this.data.active) {
case 1:
this.verifyfirst();
break;
case 2:
// 判断第二步单选框是否选择了
if (Number(formData.radios) < 0) {
this.showToast('请选择单选');
return;
}
// 判断第二步多选框是否选择了
if (!formData.checkbox.length && !formData.nochecked) {
this.showToast('请选择多选');
return;
}
// 第二步校验通过,设置页面索引为 3
this.setData('active', 3);
break;
case 3:
// 判断第三步长文本输入框是否有值
if (!formData.textBox) {
this.showToast('请输入长文本');
return;
}
// 第三步校验通过,设置页面索引为 4
this.setData('active', 4);
// 核对信息页面的数据
this.fiveInfor();
break;
case 4:
// 设置参数,参数格式可根据业务接口自定义
datas = JSON.stringify(this.parameter());
swan.showModal({
title: '信息确认信息',
content: '请确认填写的信息无误,提交后不支持修改',
confirmText: '确认提交',
confirmColor: '#108EE9',
cancelText: '返回修改',
cancelColor: '#999',
success(res) {
if (res.confirm) {
// 此处可自定义业务逻辑
swan.redirectTo({
url: `../result/result?result=${datas}`
});
}
}
});
break;
}
}
页面一点击下一步时的校验逻辑
JS
/**
* 第一步的校验函数,错误飘红,并toast提示相关错误信息
*/
verifyfirst() {
// 页面中所有表单输入值的集合
const formData = this.data.formData;
// 页面一中 input,选择框的 error 状态设置
let errorInfo = {
// checkIdcard、checkPhone、checkEmpty校验方法的详细说明可看 utils.js
idcardError: checkIdcard(formData.idcard),
phoneError: checkPhone(formData.phone),
dateError: !formData.date,
placeError: !formData.place,
iptoneError: checkEmpty(formData.iptone, '请输入输入框一'),
ipttwoError: checkEmpty(formData.ipttwo, '请输入输入框二'),
sltsingleError: formData.sltsingle < 0,
sltdoubleError: formData.sltdouble.length !== 3
};
this.setData({errorInfo}, () => {
this.showCurToast();
});
}
提交状态页
用于展示表单提交结果。
页面路径:result/result
代码示例
- SWAN
- JSON
<smt-page-status s-if="isPageLoading || errorPage"
class="content"
loading="{{isPageLoading}}"
icon="{{errorConfig[errorPage].icon}}"
title="{{errorConfig[errorPage].title}}"
desc="{{errorConfig[errorPage].desc}}"
showBtn="{{errorConfig[errorPage].showBtn}}"
bind:smtreloading="check">
</smt-page-status>
<view s-else class='wrap'>
<gov-page-result
iconName="{{icon.iconName}}"
iconColor="{{icon.iconColor}}"
gov-main-btn="gov-main-btn"
gov-ext-info-text="gov-ext-info-text"
title="{{pageResult.title}}"
desc="{{pageResult.desc}}"
main-btn-text="回到首页"
sub-btn-text="辅助按钮"
bind:goback="goBack"
bind:viewdetails="viewDetails">
<view slot="suppl-cont" class="list" s-if="{{pageResult.list}}">
<view s-for="pageResult.list trackBy item" class='every'>
<text>{{item.title}}</text>
<text>{{item.sub}}</text>
</view>
</view>
</gov-page-result>
</view>
{
"navigationBarTitleText": "结果页",
"backgroundColor": "#fff",
"navigationBarBackgroundColor": "#fff",
"navigationBarTextStyle": "black",
"usingComponents": {
"ga-button": "@smt-ui/component-gov/src/button",
"smt-page-status": "@smt-ui/component/src/page-status",
"gov-page-result": "@smt-ui/component-gov/src/page-result"
}
}
页面初始化
JS
/**
* 页面加载时触发
*
* @param {Object} options 提交页面传的参数
* @param {string} options.result 传的数据
*/
onLoad(options) {
this.setData({
// 页面需要展示的数据,依赖server端返回
pageResult: '',
options: JSON.parse(options.result)
});
let icon;
// 根据接口返回的数据或提交页面传入的数据判断需要展示的 icon 类型
if (pageResult.data.type !== 'success') {
icon = {
iconName: 'warning-o',
iconColor: '#c40311'
};
this.setData({icon});
}
}
点击“返回首页”按钮触发事件
JS
/**
* 返回首页
*/
goBack() {
//【需替换】:请为 url 设置真实的首页路径
swan.redirectTo({
url: ''
});
}
点击“辅助按钮”按钮触发事件
JS
/**
* 辅助按钮
*/
viewDetails() {
//【需替换】:请为 url 设置真实的跳转页面路径
swan.redirectTo({
url: ''
});
}
npm 依赖
名称 | 版本号 |
---|---|
@smt-ui/component-gov | latest |
@smt-ui/component | latest |
Bug & Tip
- Tip:该模板使用了 ES6 语法,需要开启开发者工具的增强编译,操作步骤参看开启说明;同时也需开启上传代码时样式自动补全。
- Tip:以上代码示例为小程序前端代码,可直接在模拟器和真机预览。
- Tip:模板中使用的是测试数据,你需要从接口中获取真实的数据。