阅读(4360) (8)

百度智能小程序 办理类服务(多流程)模板

2020-09-03 11:19:53 更新

page-multipage-form 办理类服务(多流程)模板

解释: 具有导航栏的办理类服务(多流程)模板,通常用来完成复杂多流程表单填写提交工作。本模板包含多个组件,可根据实际需要进行增删,支持代码的二次开发满足个性化诉求。

示例


前提条件

使用说明

  • 本示例为小程序前端代码,可直接在模拟器和真机预览。
  • 模板中使用的是测试数据,你需要从接口中获取真实的数据。
  • 页面模板功能从开发者工具 v2.25.1-rc 版本开始支持。
  • 该模板使用了 es6 语法,需要开启开发者工具的增强编译,操作步骤参看开启说明;同时也需开启上传代码时样式自动补全。

使用方式

方式一 【 NPM 】

  1. 在小程序根目录执行下方命令,下载页面模板的 npm 包:
    npm i @smt-ui-template/page-multipage-form
    
  2. 将 /node_modules/@smt-ui-template/page-multipage-form 下的 @smt-ui-template-page-multipage-form 文件夹拷贝到当前小程序合适的目录下 (如pages):
    .
    ├── project.swan.json                   
    ├── app.json                            
    ├── app.js                              
    ├── pages
        └── @smt-ui-template-page-multipage-form    // 模板文件
    
  3. 在小程序根目录的 app.json 中配置模板页面的 path 路径,查看效果,如:
    {
        "pages": [
            ...
            "pages/@smt-ui-template-page-multipage-form/index/index",
            "pages/@smt-ui-template-page-multipage-form/result/result",
            ...
        ]
    }
    
  4. 为了方便在开发者工具中查看模板页的效果,可以设置模板页为小程序预览的首页。详情请见自定义编译文档

页面内容

方式二 【 开发者工具-页面模板 】

  1. 打开开发者工具,点击 ”页面模板“,在下方找到 ”办理类服务(多流程)模板“,选中该模板后点击右下角 ”立即使用”,填写相关信息点击右下角 ”完成“ 按钮。
  2. 使用开发者工具的编辑器或者选择自己熟悉的编辑器对模板进行二次开发。

模板包含两个页面:多步骤表单页、提交状态页(成功/失败)。

多步骤表单页

页面路径:index/index

将整个表单划分为多个步骤,每个步骤收集不同分类的信息,开发者可自定义步骤长度,在每个步骤中提供了单选、多选、输入、上传图片等多种表单类型,可根据实际需求选用,模板还提供了提交状态页面,用于展示表单提交结果。


以下为部分代码示例注解,运行模板请按照上面的【使用步骤】

<!--  页面加载 -->
<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"
    }
}
  • 获取页面数据
    /**
     * 发送请求
     *
     * @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);
    }
    
  • 点击下一步按钮触发事件
    /**
     * 点击下一步按钮触发事件
     */
    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;
        }
    }
    
  • 页面一点击下一步时的校验逻辑
    /**
     * 第一步的校验函数,错误飘红,并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

用于展示表单提交结果。

  

<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"
    }
}
  • 页面初始化
    /**
     * 页面加载时触发
     *
     * @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});
        }
    }
    
  • 点击 ”返回首页“ 按钮触发事件
    /**
     * 返回首页
     */
    goBack() {
        //【需替换】:请为 url 设置真实的首页路径
        swan.redirectTo({
            url: ''
        });
    }
    
  • 点击 ”辅助按钮“ 按钮触发事件
    /**
     * 辅助按钮
     */
    viewDetails() {
        //【需替换】:请为 url 设置真实的跳转页面路径
        swan.redirectTo({
            url: ''
        });
    }

NPM 依赖

名称版本号
@smt-ui/component-govlatest
@smt-ui/componentlatest