page-policy 政策文件库模板

解释: 本模板适用于信息公开类小程序的快速搭建,可应用于办税指南、法律宝典、街道信息公告通知等场景,可将信息结构化的呈现给用户,方便用户快速阅读获取有效的信息。

# 示例

扫码体验
重新加载
请使用百度APP扫码

# 前提条件

# 使用说明

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

# 使用方式

# 方式一 【 NPM 】

  1. 在小程序根目录执行下方命令,下载页面模板的 npm 包:
 npm i @smt-ui-template/page-policy
  1. 将 /node_modules/@smt-ui-template/page-policy 下的 @smt-ui-template-gov-policy 文件夹拷贝到当前小程序合适的目录下 (如pages):
.
├── project.swan.json                   
├── app.json                            
├── app.js                              
├── pages
    └── @smt-ui-template-gov-policy     // 模板文件
  1. 在小程序根目录的 app.json 中配置模板页面的 path 路径,查看效果,如:
{
    "pages": [
        ...
        "pages/@smt-ui-template-gov-policy/pages/indexTab/index",
        "pages/@smt-ui-template-gov-policy/pages/indexFilter/index",
        "pages/@smt-ui-template-gov-policy/pages/search/search",
        "pages/@smt-ui-template-gov-policy/pages/subscribe/subscribe",
        "pages/@smt-ui-template-gov-policy/pages/article/article",
        "pages/@smt-ui-template-gov-policy/pages/articleList/articleList",
        "pages/@smt-ui-template-gov-policy/pages/collect/collect"
        ...
    ]
}
  1. 为了方便在开发者工具中查看模板页的效果,可以设置模板页为小程序预览的首页。该功能的说明请参考自定义编译文档

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

  1. 打开开发者工具,点击 ”页面模板“,在下方找到 ”政策文件库“,选中该模板后点击右下角 ”立即使用”,填写相关信息点击右下角 ”完成“ 按钮。
  2. 使用开发者工具的编辑器或者选择自己熟悉的编辑器对模板进行二次开发。

# 页面内容

模板包含政策文件列表页、政策文件详情页、收藏以及订阅列表页、搜索结果页。

# 政策文件列表页

页面路径:pages/indexFilter/index、pages/indexTab/index

政策文件列表页包含搜索以及筛选组件,用户可以快速获取所需要的信息,同时页面包含跑马灯组件、tab 切换组件可实现信息轮播提示、板块切换等交互效果,丰富页面功能,提升使用体验。

:列表页提供了筛选器和 tab 两种效果样式。其中,pages/indexFilter/index 是带筛选器的模板页,pages/indexTab/index 是带 tab 切换的模板页。如果想查看不同的模板类型,可以修改小程序根目录下的 app.json 文件,将对应类型的模板页面路径放到第一个。

  • 以下是使用筛选器的首页模板代码:
    <view class="index-filter {{isIPhoneX ? 'iphone-x-compitable' : ''}} {{isOpenFilter ? 'locked' : ''}}">
        <zw-custom-title-bar
            class='policy-home-filter'
            common-bg-opacity="{{true}}"
            common-front-color="#ffffff"
            fixed-title="政策文件库"
            need-to-return="{{false}}"
            fixed-text-align="center"
            common-text-align="left"
            fixed-bg-color="#ffffff"
            common-bg-color="#2772fb"
            fixed-front-color="#000000"
            fixed-has-border="{{true}}"
            common-has-border="{{false}}"
            show-fixed-bar="{{true}}"
            namespace="policy-home-filter"
        >
        </zw-custom-title-bar>
        <view class="security-style" style="height:{{security}}"></view>
        <view class="header">
            <view class="app-handle">
                <view class="app">
                    <view class="row-main app-title">政策文件库</view>
                    <view class="row-sub">文件全文&nbsp;权威解读</view>
                </view>
                <view class="handle">
                    <view class="handle-item">
                        <view class="row-main handle-icon" bindtap="gotoSubscribe">
                            <zw-icon name="subscribe" size="{{iconsize}}" color="#fff" class="icon-1"/>
                        </view>
                        <view class="row-sub">我的订阅</view>
                    </view>
                    <view class="handle-item">
                        <view class="row-main handle-icon" bindtap="gotoCollect">
                            <zw-icon name="no-collect" size="{{iconsize}}" color="#fff" class="icon-2"/>
                        </view>
                        <view class="row-sub">我的收藏</view>
                    </view>
                </view>
            </view>
            <view class="search" bindtap="gotoSearch"></view>
        </view>
        <view class="notice-wrap" s-if="notice.text">
           <zw-notice-bar text="{{notice.text}}" bind:close="noticeClose" bind:clicknotice="clicknotice"/>
        </view>
        <view class="content">
            <view class="filter-section" s-if="{{filter.length}}">
                <zw-filter
                    s-for="item, findex in filter"
                    title="{{item.title}}"
                    class="filter"
                    mask-with-animation="{{false}}"
                    bind:openFilter="openFilter"
                    max-title-width="123.79"
                    is-immersive
                >
                    <zw-filter-item
                        s-for="sub,index in item.children"
                        bind:change="changeFilter"
                        value="{{findex + ':' + sub.id}}"
                        text="{{sub.name}}" />
                </zw-filter>
            </view>
            <view class="filter-content {{notice ? 'smaller' : 'normal'}}">
                <zw-loading s-if="showLoading" zw-loading-status-class="custom-loading">
                    <view slot="text">正在加载...</view>
                </zw-loading>
                <zw-state-page show-reload="{{stateBtn}}" type="{{errStatus}}" bind:reload="reload" zw-state-page-class="custom-state" fixed="{{false}}" s-if="{{errStatus !== ''}}"/>
                <block s-if="isLoaded">
                    <view class="feed-content">
                        <block s-for="page in list">
                            <zw-list-item
                                s-for="item, index in page"
                                title="{{item.title}}"
                                desc="{{'发文机关:' + item.office}}"
                                clickable="{{true}}"
                                data-aid="item.id"
                                bind:tap="gotoArticle"
                            />
                        </block>
                        <zw-spin status="{{status}}" bind:tap="reloadFeed" s-if="showStatus" zw-spin-class="custom-spin"></zw-spin>
                        <zw-footer s-if="feedEnd" zw-footer-class="custom-footer">
                            <view class="footer-txt">单行footer</view>
                        </zw-footer>
                    </view>
                </block>
            </view>
        </view>
    </view>
    
    {
        "navigationBarTitleText": "政策文件库",
        "navigationStyle": "custom",
        "backgroundColor": "#ffffff",
        "backgroundColorTop": "#2772fb",
        "navigationBarBackgroundColor": "#ffffff",
        "navigationBarTextStyle": "white",
        "onReachBottomDistance": 34,
         "usingComponents": {
            "zw-custom-title-bar": "../../components/CustomTitleBar/src/index",
            "zw-notice-bar": "../../components/NoticeBar/src/index",
            "zw-footer": "../../components/Footer/src/index",
            "zw-icon": "../../components/Icon/src/index",
            "zw-loading": "../../components/LoadingStatus/src/index",
            "zw-state-page": "../../components/StatePage/src/index",
            "zw-list-item": "../../components/ListItem/src/index",
            "zw-spin": "../../components/Spin/src/index",
            "zw-filter": "../../components/Filter/src/index",
            "zw-filter-item": "../../components/FilterItem/src/index"
        }
    }
    
    // 获取列表数据,以下为使用 mock 数据的请求示例
    getHomeList(query, ({code, msg, data}) => {
        if (code === 0) {
            // 设置筛选器数据
            !filter.length && (res.filter = data.filter);
            // 更新通知栏内容
            !notice && !this.data.hideNotice && data.notice && (res.notice = data.notice);
            // ...
        }
        else {
            // 请求异常处理
        }
    }),
    // 跳转到文章详情页。跳转携带的 id 参数只是 mock 数据举例,是否需要带参数跳转以及参数名称、参数值均可自定义
    gotoArticle(e) {
        const index = e.currentTarget.dataset.aid;
        navigateTo({
            url: `../article/article?id=${index}`
        });
    }
    

    # 政策文件详情页

    页面路径:pages/article/article

    分为标题以及文字信息区域,可将图文等内容结构化呈现,方便用户阅读。

      <view class="article-wrapper">
          <zw-loading s-if="showLoading">
              <view slot="text">正在加载...</view>
          </zw-loading>
          <zw-state-page show-reload="{{stateBtn}}" type="{{errStatus}}" s-if="errStatus !== ''" bind:reload="reload"/>
      
          <block s-if="isLoaded">
              <view class="{{isIPhoneX ? 'iphone-x-compitable' : '' }}">
                  <view class="main-container">
                      <view class="main-content">
                          <view class="content">
                              <view class="article-desc" bindtap="changeExpand">
                                  <view class="article-title">{{detail.title}}</view>
                                  <view class="article-info {{expand.length ? 'nomargin' : ''}}" >
                                      <view class="info-item">
                                          <view class="info-name">{{detail.info[0].name}}</view>
                                          <view class="info-value">{{detail.info[0].value}}</view>
                                      </view>
                                  </view>
                                  <view class="expand-icon">
                                      <zw-icon
                                          s-if="{{expand.length > 0}}"
                                          name="arrow-{{!expandStatus ? 'down' : 'up'}}"
                                          color="#ccc"
                                          size="{{actionFontSize}}">
                                      </zw-icon>
                                  </view>
                              </view>
      
                              <view
                                  class="expand-area" s-if="{{expand.length > 0}}"
                                  style="height: {{expandStatus ? expandHeight : 0}}px;"
                              >
                                  <view class="expand-area-inner">
                                      <view class="info-item" s-for="item in expand">
                                          <view class="info-name">{{item.name}}</view>
                                          <view class="info-value">{{item.value}}</view>
                                      </view>
                                   </view>
                              </view>
      
                              <rich-text nodes="{{detail.content}}" selectable="true"></rich-text>
      
                              <view class="subscribe border border-top">
                                  <zw-list-item
                                      title="{{detail.hoster}}"
                                      desc="{{detail.desc}}"
                                      clickable="{{false}}"
                                      zw-list-item-wrap-class="custom-list"
                                      no-border
                                  >
                                      <slot>
                                          <view class="btn-wrap" >
                                              <zw-button
                                                  button-size="xs-small"
                                                  button-color="{{detail.status ? 'secondly' : 'thirdly'}}"
                                                  button-text="{{detail.status ? '已订阅' : '订阅'}}"
                                                  bindtap="changeSub"
                                              />
                                          </view>
                                      </slot>
                                  </zw-list-item>
                              </view>
                          </view>
                          <view class="footer {{isIPhoneX ? 'iphone-x-compitable' : '' }} border border-top {{!isIos ? 'android-patch': ''}}">
                              <view class="footer-inner">
                                  <view class="actions-list" >
                                      <view class="action" bind:tap="addCollection">
                                          <zw-icon class="icon" name="{{detail.collected ? 'collect-color' : 'collect-thin'}}" size="{{iconSize}}">
                                          </zw-icon>
                                          {{detail.collected ? '已收藏' : '收藏'}}
                                      </view>
                                  </view>
                                  <view class="actions-list" >
                                      <view class="action" bind:tap="toShare">
                                          <zw-icon class="icon" name="share" size="{{iconSize}}"></zw-icon>
                                          分享
                                      </view>
                                  </view>
                              </view>
                          </view>
                      </view>
                  </view>
              </view>
          </block>
      </view>
      
      {
          "navigationBarBackgroundColor": "#ffffff",
          "navigationBarTextStyle": "black",
          "navigationBarTitleText": "政策文件库",
          "backgroundColor": "#ffffff",
          "backgroundTextStyle": "light",
          "usingComponents": {
              "zw-loading": "../../components/LoadingStatus/src/index",
              "zw-state-page": "../../components/StatePage/src/index",
              "zw-button": "../../components/Button/src/index",
              "zw-icon": "../../components/Icon/src/index",
              "zw-list-item": "../../components/ListItem/src/index"
          }
      }
      
      // 请求接口,获取文件详情
      getArticle(({code, msg, data}) => {
          // 请求正常响应
          if (code === 0) {
              // ...
          }
          // 请求异常
          else {
              // ...
          }
      }),
      // 切换订阅状态
      changeSub(e) {
          // 获取当前订阅状态
          const status = this.data.detail.status;
          // 请求接口,切换订阅状态
          changeStatus(status, ({code, data}) => {
              // 请求正常响应
              if (code === 0) {
                  // 更新订阅状态
              }
          });
      },
      // 切换收藏状态
      addCollection(e) {
          // 获取当前收藏状态
          const status = this.data.detail.collected;
          // 请求接口,切换收藏状态
          changeStatus(status, ({code, data}) => {
              // 请求正常响应
              if (code === 0) {
                  // 更新收藏状态
              }
          });
      },
      // 分享的标题、内容、路径、图片地址,分享成功、分享失败的回调都可以根据实际业务场景和需求自定义。
      toShare() {
          swan.openShare({
              title: '政策文件库分享示例',
              content: '中共中央办公厅印发《2019-2023年全国党员教育培训工作规划》',
              path: '/templates/gov/policy/pages/article/article?key=' + this.data.articleId,
              imageUrl: 'https://smartprogram.baidu.com/docs/img/logo_new.png',
              success: res => {
                  swan.showToast({
                      title: '分享成功'
                  });
                  console.log('openShare success', res);
              },
              fail: err => {
                  console.log('openShare fail', err);
              }
          });
      }
      

      # 我的收藏页面

      页面路径:pages/collect/collect

      用户收藏过的内容将通过一定的顺序呈现在收藏列表页,对于重点关注的内容,用户无需反复检索,在收藏列表页可直接阅读。

        <view class="collect-wrapper">
            <zw-tabs
                tabs="{{tabs}}"
                type="flex"
                mode="auto"
                active-tab="{{0}}"
                nav-bar-width="100%"
                show-with-animation="{{false}}"
                bindonChange="onCustomTabChange"
            />
            <view class="tab-content {{activeName === 'zc' ? 'show' : 'hide'}} {{isIPhoneX ? 'iphone-x-compitable' : ''}}">
                <zw-loading s-if="zc.showLoading">
                    <view slot="text">正在加载...</view>
                </zw-loading>
                <zw-state-page show-reload="{{zc.stateBtn}}" type="{{zc.errStatus}}" s-if="zc.errStatus !== ''" bind:reload="reloadZc" zw-state-page-class="custom-state" fixed="{{false}}"/>
                <block s-if="zc.isLoaded">
                    <!-- 上拉加载 -->
                    <smt-feed
                        class="smt-feed click-zc-refresh"
                        data-type="zc"
                        bind:scrolltolower="autoScrollToLower"
                    >
                        <block s-for="page in zc.list">
                            <zw-list-item
                                s-for="item, index in page"
                                title="{{item.title}}"
                                desc="{{'发文机关:' + item.office}}"
                                clickable="{{true}}"
                                data-aid="item.id"
                                bind:tap="gotoArticle"
                            />
                        </block>
        
                        <zw-spin status="{{zc.status}}" bind:tap="reloadZcFeed" zw-spin-class="custom-spin"></zw-spin>
                    </smt-feed>
                </block>
        
            </view>
            <view class="tab-content {{activeName === 'jd' ? 'show' : 'hide'}} {{isIPhoneX ? 'iphone-x-compitable' : ''}}">
                <zw-loading s-if="jd.showLoading">
                    <view slot="text">正在加载...</view>
                </zw-loading>
                <zw-state-page show-reload="{{jd.stateBtn}}" type="{{jd.errStatus}}" s-if="jd.errStatus !== ''" bind:reload="reloadJd" zw-state-page-class="custom-state" fixed="{{false}}"/>
                <block s-if="jd.isLoaded">
                    <!-- 上拉加载 -->
                    <zw-feed
                        class="smt-feed click-jd-refresh"
                        data-type="jd"
                        bind:scrolltolower="autoScrollToLower"
                    >
                        <block s-for="page in jd.list">
                            <zw-list-item
                                s-for="item, index in page"
                                title="{{item.title}}"
                                desc="{{'发文机关:' + item.office}}"
                                clickable="{{true}}"
                                data-aid="{{item.id}}"
                                bind:tap="gotoArticle"
                            />
                        </block>
                        <zw-spin status="{{jd.status}}" bind:tap="reloadJdFeed" zw-spin-class="custom-spin"></zw-spin>
                    </zw-feed>
                </block>
            </view>
        </view>
        
        {
            "navigationBarBackgroundColor": "#fffffe",
            "navigationBarTextStyle": "black",
            "navigationBarTitleText": "我的收藏",
            "backgroundColor": "#ffffff",
            "backgroundTextStyle": "light",
            "usingComponents": {
                "zw-loading": "../../components/LoadingStatus/src/index",
                "zw-state-page": "../../components/StatePage/src/index",
                "zw-list-item": "../../components/ListItem/src/index",
                "smt-feed": "@smt-ui/component/src/feed",
                "zw-spin": "../../components/Spin/src/index",
                "zw-tabs": "../../components/Tabs/src/index"
            }
        }
        
        // 请求接口,获取收藏数据
        getCollectList(name, ({code, msg, data}) => {
            if (code === 0) {
                // 请求正常响应处理
            }
            else {
                // 请求异常处理
            }
        }),
        // 跳转到文章详情页。跳转携带的 id 参数只是 mock 数据举例,是否需要带参数跳转以及参数名称、参数值均可自定义
        gotoArticle(e) {
            const index = e.currentTarget.dataset.aid;
            navigateTo({
                url: `../article/article?id=${index}`
            });
        }
        

        # 我的订阅页面

        页面路径:pages/subscribe/subscribe

        开发者可结合自身业务,向用户提供订阅功能。对于订阅后的内容或板块,用户无需反复检索,在订阅列表页可直接获取最新资讯。

          <view class="subscribe-wrap swan-security-padding-bottom">
              <zw-loading s-if="showLoading">
                  <view slot="text">正在加载...</view>
              </zw-loading>
              <zw-state-page
                  s-if="errStatus !== ''"
                  show-reload="{{stateBtn}}"
                  type="{{errStatus}}"
                  bind:reload="reload"
              />
              <view s-if="isLoaded">
                  <zw-list-item
                      s-for="item, index in subList"
                      title="{{item.title}}"
                      desc="{{item.desc}}"
                      clickable="{{false}}"
                      data-index={{index}}
                      bind:tap="gotoArticle"
                  >
                      <slot>
                          <view class="btn-wrap" >
                              <zw-button
                                  button-size="xs-small"
                                  button-color="{{item.status ? 'secondly' : 'thirdly'}}"
                                  button-text="{{item.status ? '已订阅' : '订阅'}}"
                                  data-index="{{index}}"
                                  catchtap="changeSub"
                              />
                          </view>
                      </slot>
                  </zw-list-item>
              </view>
          </view>
          
          {
              "navigationBarBackgroundColor": "#ffffff",
              "navigationBarTextStyle": "black",
              "navigationBarTitleText": "我的订阅",
              "backgroundColor": "#ffffff",
              "backgroundTextStyle": "light",
              "usingComponents": {
                  "zw-list-item": "../../components/ListItem/src/index",
                  "zw-loading": "../../components/LoadingStatus/src/index",
                  "zw-state-page": "../../components/StatePage/src/index",
                  "zw-button": "../../components/Button/src/index"
              }
          }
          
          // 请求接口,获取关注列表数据
          getList(({code, msg, data}) => {
              if (code === 0) {
                  // 请求正常响应处理
              }
              else {
                  // 请求异常处理
              }
          }),
          // 切换订阅状态
          changeSub(e) {
              // 获取当前订阅状态
              const status = this.data.subList[index].status;
          
              changeStatus(status, ({code, data}) => {
                  // 请求正常响应
                  if (code === 0) {
                      // 更新订阅状态
                  }
              });
          },
          // 跳转到文章详情页。跳转携带的 id 参数只是 mock 数据举例,是否需要带参数跳转以及参数名称、参数值均可自定义
          gotoArticle(e) {
              const index = e.currentTarget.dataset.aid;
              navigateTo({
                  url: `../articleList/articleList?id=${index}`
              });
          }
          

          # 搜索页

          页面路径:pages/search/search

          用户触发搜索功能后将跳转至搜索页,页面包含搜索历史以及搜索结果两部分。搜索结果高亮显示,方便用户辩识获取有效信息;搜索历史结构化呈现,方便用户再次进行检索。对于搜索历史,也可使用“清空”进行删除。

            <view class="search-wrapper">
                 <zw-custom-title-bar
                    show-fixed-bar='{{false}}'
                    fixed-title="搜索"
                    fixed-front-color="#000000"
                    common-front-color="#000000"
                    common-bg-color='#ffffff'
                    fixed-bg-color='#ffffff'
                    common-bg-opacity="{{false}}"
                    need-to-return="{{true}}"
                    common-title="搜索"
                    bind:navhome="navhome"
                />
                <view class="search-component clear">
                    <view class="search-bar border border-bottom {{!isIos ? 'android-patch': ''}}">
                        <zw-search-bar
                            class='search-bar-component'
                            value="{{value}}"
                            focus="{{focusing}}"
                            placeholder="{{placeholder}}"
                            confirm-type="{{confirmType}}"
                            search-text-color="{{searchTextColor}}"
                            bindfocus="focusHdl"
                            bindblur="blurHdl"
                            bindinput="iptHdl"
                            bindconfirm="searchBtnHdl"
                            bindclear="emptyHdl"
                            bindsearch="searchBtnHdl"
                        />
                    </view>
                    <!-- 状态 -->
                    <view class="status-content" s-if="showLoading || errStatus !== ''">
                        <zw-loading s-if="showLoading" zw-loading-status-class="custom-loading">
                            <view slot="text">正在加载...</view>
                        </zw-loading>
                        <zw-state-page
                            s-if="errStatus !== ''"
                            fixed="{{false}}"
                            show-reload="{{errStatus === 'noNetwork' || errStatus === 'warning'}}"
                            type="{{errStatus}}"
                            bind:reload="reload" class-name="custom-state"/>
                    </view>
                    <view
                        class="search-body"
                        s-if="!showLoading"
                    >
                        <!-- 历史搜索+热门搜索 -->
                        <view
                            class="history-info"
                            s-if="!value && !resultState"
                        >
                            <block s-if="searchInfo.info.length > 0">
                                <view class="history-title">
                                    <text>{{searchInfo.title}}</text>
                                    <zw-icon
                                        s-if="searchInfo.delete"
                                        name="trash"
                                        size="{{iconsize}}"
                                        bindtap="deleteHis"
                                        color="#999"
                                    />
                                </view>
                                <view class="history-body {{searchInfo.delete ? 'history-body-shrink' : ''}}"
                                >
                                    <view
                                        class="history-item"
                                        s-for="info in searchInfo.info"
                                        hover-class="list-hover-feedback"
                                        hover-stay-time="{{240}}"
                                        bindtap="itemSelect"
                                        data-item="{{info}}"
                                        data-type="{{item.type}}"
                                    >
                                        <text>
                                            {{info}}
                                        </text>
                                    </view>
                                </view>
                            </block>
                        </view>
                        <!-- 搜索结果 -->
                        <view
                            class="result"
                            s-if="resultState"
                        >
                            <view s-for="item, index in list">
                                <zw-list-item
                                    title="{{item.title}}"
                                    desc="{{'发文机关:' + item.office}}"
                                    clickable="{{true}}"
                                    data-aid="item.id"
                                    bind:tap="gotoArticle"
                                >
                                    <view slot="title">
                                        <rich-text nodes="{{item.title}}" selectable="true" />
                                    </view>
                                </zw-list-item>
                            </view>
                        </view>
                    </view>
                </view>
            </view>
            
            {
                "navigationBarTitleText": "搜索",
                "navigationBarBackgroundColor": "#ffffff",
                "navigationBarTextStyle": "black",
                "navigationStyle": "custom",
                "enablePullDownRefresh": false,
                "usingComponents": {
                    "zw-search-bar": "../../components/SearchBar/src/index",
                    "zw-state-page": "../../components/StatePage/src/index",
                    "zw-icon": "../../components/Icon/src/index",
                    "zw-loading": "../../components/LoadingStatus/src/index",
                    "zw-custom-title-bar": "../../components/CustomTitleBar/src/index",
                    "zw-list-item": "../../components/ListItem/src/index"
                }
            }
            
            onLoad() {
                // 从缓存中获取历史记录
                let searchInfo = {};
                swan.getStorage({
                    key: this.data.historyStorageName,
                    success: res => {
                        const localHistory = res.data;
                        if (localHistory) {
                            // 处理缓存的历史数据
                        }
                    },
                    fail: () => {
                        // 获取缓存异常处理
                    }
                });
            },
            // 将历史搜索存入 Storage,缓存搜索历史
            saveHistory(text) {
                // 设置搜索历史缓存
                swan.setStorage({
                    key: this.data.historyStorageName,
                    exp: 60 * 24 * 60 * 60 * 1000,
                    data: history
                });
            },
            // 删除历史记录,可直接通过清除缓存数据来删除搜索历史
            deleteHis() {
                // 弹窗二次确认
                swan.showModal({
                    title: '清空搜索历史',
                    content: '数据清空后,相关内容无法恢复',
                    confirmText: '确认清空',
                    cancelText: '取消',
                    success: res => {
                        // 确认清空
                        if (res.confirm) {
                            this.setData({
                                'searchInfo.info': []
                            });
                            // 移除缓存数据
                            swan.removeStorageSync(this.data.historyStorageName);
                        }
                    }
                });
            },
            // 格式化搜索结果数据。搜索词高亮处理,高亮处理也可以直接放在接口处理,接口返回带样式的内容放在富文本展示。示例中的高亮词是mock数据。
            fomateValue(value) {
                const arr = value.split('<em');
                return arr.map(item => {
                    if (item.indexOf('>') > -1) {
                        const result = item.slice(item.indexOf('>') + 1);
                        return result.split('</em>').join('');
                    }
                    return item;
                }).join('');
            },
            // 请求接口,获取搜索结果
            getResult(query, isSaveHis = false) {
                // 是否要保存历史记录
                isSaveHis && this.saveHistory(query);
                getSearchList(this.data.activeName, ({code, msg, data}) => {
                    if (code === 0) {
                        // 接口正常响应处理
                    }
                    else {
                        // 接口异常处理
                    }
                });
            },
            // 回到小程序的首页,url 路径可根据实际路径替换
            navhome() {
                navigateTo({
                    url: '../indexTab/index'
                });
            },
            // 跳转到文章详情页。跳转携带的 id 参数只是 mock 数据举例,是否需要带参数跳转以及参数名称、参数值均可自定义
            gotoArticle(e) {
                const index = e.currentTarget.dataset.aid;
                navigateTo({
                    url: `../article/article?id=${index}`
                });
            }
            

            # 自定义 UI 组件

            在政策文件库中,用到了如下自定义 UI 组件:

            组件名称 路径 说明
            Button 按钮组件 components/Button 按钮组件支持设置尺寸、文案、文字颜色、背景颜色、禁用置灰等。
            CustomTitleBar 沉浸式导航栏组件 components/CustomTitleBar 沉浸式导航栏组件可实现导航栏通栏配置,上滑、下拉导航栏渐变切换效果。
            Filter、FilterItem 筛选器组件 components/Filter、components/FilterItem 筛选器组件可以满足多条件筛选场景,支持多列筛选。Filter 组件需要配合 FilterItem 组件使用。
            Footer 页脚组件 components/Footer 页脚组件可自定义页脚内容。
            Icon 组件 components/Icon 图标组件,可设置不同图标类型、图标大小和颜色。
            ListItem 列表项组件 components/ListItems 列表项组件。
            LoadingStatus 加载态组件 components/LoadingStatus 可设置加载态的主题色、文案颜色。
            NoticeBar 跑马灯组件 components/NoticeBar 跑马灯组件可以自动广播提示消息。
            SearchBar 搜索框组件 components/SearchBar 搜索框组件支持保存搜索历史、删除搜索历史、清空搜索内容、搜索结果词高亮显示等功能。
            Spin 加载组件 components/Spin 加载组件用于展示上拉加载状态,显示加载态内容,包括点击加载、正在加载、加载完成、重新加载四种状态。
            StatePage 状态页组件 components/StatePage 状态页组件用于设置页面的不同展现状态,如无网络、无数据,还可配合描述文案、重新加载按钮一起使用。
            Tabs 组件 components/Tabs Tabs 组件可以满足在不同视图内容中进行切换。

            # NPM 依赖

            名称 版本号
            @smt-ui/component latest