本篇要记录的是一个完整功能里的其中一部分,这个功能需求大致是在移动端给所选分组下的管理员用户留言,管理员用户可在PC端对留言用户进行回复,而这个功能中除了移动端和PC管理端的列表操作,还涉及一个重要的功能模块——带搜索功能的树状结构组织选择器,大概长下图这样:
由于移动端项目之前没有这种功能的存量代码,因此需要从零开始手动实现。下面开始记录实现过程和思路。
目录
分析需求
分析需求
该功能的需求为页面载入后先展示最顶级的分组列表,没有下级分组的列表项不可点击,不显示“>”符号,点击其中一项展示该分组下的分组列表,需覆盖点击之前的列表内容而非采用层级嵌套的形式,并在分组列表顶部展示当前点击的分组路径,点击之前的路径可返回上级分组。
看到这个需求首先能想到的就是树形结构、递归和数组操作,需要做的就是根据每次点击所选择的分组项,更新当前的数据节点。
具体实现
移动端组件库使用了Vant,基本需求都能满足,组件的具体使用就不做赘述,直接贴代码。
页面结构搭建
本页的结构并不复杂,主要就是搜索框、组织路径,以及展示列表区块
组织选择页
<template>
<div style="display: flex;height: 100%;flex-direction:column;background: #F5F5F5;overflow-x: hidden"
:class="backClicked?'slideOutBack':'slideIn'">
<PageHeader title='选择组织' :themeType="2"/>
<div class="container">
<van-search
placeholder="请输入搜索关键词"
input-align="center"
shape="round"
disabled
@click="searchOrg"
/>
<p class="title-tip">请选择要切换的组织</p>
<!-- 下拉刷新容器 -->
<van-pull-refresh v-model="refreshing" @refresh="onRefresh">
<div class="org-container">
<!-- 组织路径 -->
<van-cell class="org-path">
<span class="org-path-parent" @click="renderTopTree">{
{ $store.state.userInfo.companyName }}</span>
<span class="org-path-child" v-for="item in orgPath" :key="item.id">
<van-icon name="arrow"/>
<span @click="updateTreeData(item,2)">{
{ item.name }}</span>
</span>
</van-cell>
<van-cell v-if="loading">
<van-loading color="#2A89FF" style="text-align: center"/>
</van-cell>
<!-- 分组列表 -->
<van-radio-group id="org-group" :class="transition" v-else v-model="radio" direction="horizontal">
<van-cell v-for="item in orgTree" :key="item.id" :is-link="isShowLink(item)">
<template #icon>
<van-radio @click="bindSelectedItem(item)" checked-color="#ee0a24" :name="item.id"/>
</template>
<template #title>
<p @click="selectOrg(item)">{
{ item.orgFullName }}</p>
</template>
</van-cell>
</van-radio-group>
</div>
</van-pull-refresh>
<confirmBtn class="confirm-button" :selected-org="selectedOrg"/>
</div>
</div>
</template>
点击搜索框后跳转至搜索页面,结构于选择页类似,多了搜索建议关键词和搜索结果关键词高亮等。
组织搜索页
<template>
<div style="background: #F5F5F5;height: 100%;display: flex;flex-direction: column">
<PageHeader title='搜索' :backFn='backFn' :themeType="2"/>
<div class="container">
<van-search
v-model.trim="searchValue"
placeholder="请输入搜索关键词"
shape="round"
show-action
@search="searchFn"
@cancel="cancelFn"
/>
<p class="title-tip">{
{ searchTip }}</p>
<div class="org-container" v-if="searchFinish">
<van-cell class="org-path">
<span class="org-path-parent" @click="renderTopTree(resetOrgPath)">{
{ companyName }}</span>
<span v-if="hasBackToTop">
<span class="org-path-child" v-for="item in orgPath" :key="item.id">
<van-icon name="arrow"/>
<span @click="updateTreeData(item,2)">{
{ item.name }}</span>
</span>
</span>
<span v-else>
<van-icon name="arrow"/>
<span>_</span>
</span>
</van-cell>
<van-radio-group id="org-group" :class="transition" v-model="radio" direction="horizontal"
v-if="orgTree.length>0 && searchFinish">
<van-cell v-for="item in orgTree" :key="item.id" :is-link="isShowLink(item)"
style="display: flex;align-items: center">
<template #icon>
<van-radio @click="checkFn(item)" checked-color="#ee0a24" :name="item.id || item.orgCode"/>
</template>
<template #title>
<div @click=&#