开发ERP系统的时候经常会用到部门树列表,页面主要由搜索框、顶部部门面包屑、多层级部门列表组成。
部门列表项由不么名称和下一级右边箭头组成,点击部门名称区域可以回传部门数据到上一个页面,点击下一级箭头按钮可以展示下一级部门列表,同时将父级部门添加到顶部面包屑。
1、加载部门数数据
部门树数据由多个部门信息对象组成,部门对象中包含下级部门数组,里面可能会嵌套多个子级部门对象,这里用的json数据如下:
[
{
"DepartCode": 0,
"DepartNo": "",
"FirstName": "",
"DepartName": "所有部门",
"SystemTag": 0,
"DepartType": 0,
"DepartStatus": 0,
"DepartLevel": 0,
"DepartStatusName": "",
"DepartmentListZtree": [
{
"DepartCode": 50001,
"DepartNo": "002",
"FirstName": "测试大区",
"DepartName": "测试大区",
"SystemTag": 1,
"DepartType": 1,
"DepartStatus": 1,
"DepartLevel": 1,
"DepartStatusName": "",
"DepartmentListZtree": []
}
]
}
]
2、自定义顶部输入框
顶部输入框由Stack组件包裹TextInput输入框组件和Image图片组件组成。
/**
* 构建搜索框
*/
@Builder
BuildSearch() {
Stack() {
TextInput({ text: this.depWord, placeholder: "搜索部门" })
.height(36)
.placeholderFont({ size: 14 })
.placeholderColor($r("app.color.text_auxiliary"))
.backgroundColor($r("app.color.tag_default"))
.borderRadius(4)
.padding({ left: 36 })
.onChange((value) => {
this.depWord = value
})
Image($r("app.media.icon_search")).width(14).height(14).margin({ left: 12 })
}.align(Alignment.Start)
}
3、自定义部门面包屑
部门面包屑由Scroll组件包裹Row组件,当有选择多个层级,超出一屏时,可以滑动展示,Row组件中包裹部门名称Text和右箭头图标Image组件,点击部门名称,部门列表展示当前点击部门的所有子部门数据,具体代码如下:
/**
* 构建顶部部门面包屑
*/
@Builder
BuildTopDep() {
Scroll(this.topScroller) {
Row() {
ForEach(this.topDeps, (item: DepartBean, index) => {
Text(item.DepartName).fontSize(14).fontColor($r("app.color.main_color"))
.onClick(() => {
this.topDeps.splice(index + 1, this.topDeps.length - index - 1)
this.listDeps = item.DepartmentListZtree ?? []
})
if (index < this.topDeps.length - 1) {
Image($r("app.media.icon_back"))
.width(12).height(12).margin({ left: 4, right: 4 })
.rotate({ angle: 180 })
}
})
}
}.scrollable(ScrollDirection.Horizontal) //水平方向滚动
.scrollBar(BarState.Off)
.margin({ top: 12 })
}
4、绘制部门列表
部门列表的每一项由部门名称和下一级按钮组成,点击部门名称区域会将当前部门传回到上一页面中,点击下一级按钮会展示下一级不么列数据,代码如下:
//构建部门列表
@Builder
BuildListDep() {
List({ space: 1, scroller: this.listScroller }) {
ForEach(this.listDeps, (item: DepartBean, index) => {
ListItem() {
Row() {
Text(item.DepartName).fontSize(14).fontColor($r("app.color.text_two")).layoutWeight(1)
//如果存在子部门就展示右箭头
if (item.DepartmentListZtree?.length ?? 0 > 0) {
Image($r("app.media.icon_back"))
.width(12).height(12).margin({ left: 4, right: 4 })
.rotate({ angle: 180 })
.margin({right: 12})
.onClick(()=>{
//点击跳转到下一级部门
this.topDeps.push(item)
this.listDeps = item.DepartmentListZtree ?? []
this.topScroller.scrollPage({ next: true }) //面包屑滚动到最右边
})
}
}
.margin({ left: 12 })
}
.backgroundColor(Color.White)
.height(50)
.width("100%")
.align(Alignment.Start)
.onClick(() => {
//点击将选中的部门信息返回给上一个页面
router.back({
url:"",
params:{
depBean:item
}
})
})
})
}.layoutWeight(1)
.scrollBar(BarState.Off)
.margin({ top: 8 })
}
5、部门数据回传上一页
点击部门名称后,调用router.back方法,返回到上一页,将部门数据通过params回传到上一页中,注意url是必传参数,这里返回上一页,可以直接传空字符。
//点击将选中的部门信息返回给上一个页面
router.back({
url:"",
params:{
depBean:item
}
})
6、接收页面回传数据
在页面生命周期onPageShow方法中接收回传数据,通过router.getParams()可以拿到回传参数,params['depBean']可以拿到部门对象数据,depBean对应的回传参数的Key.
onPageShow(): void {
let params=router.getParams() as Record<string, DepartBean>
if (params) {
this.depBean=params['depBean']
}
}
完整代码如下:
import { AppUtil, JSONUtil, LogUtil, ToastUtil } from '@pura/harmony-utils'
import { TAB_ARRAY } from '../constant/HomeConstant'
import { Tab } from '../model/HomeModel'
import { createWaterMarkView } from '../view/WaterMarkView'
import { CustomerPage } from './customer/CustomerPage'
import { HomePage } from './home/HomePage'
import { HousePage } from './house/HousePage'
import { MessagePage } from './message/MessagePage'
import { MinePage } from './mine/MinePage'
import { DepartBean } from '../model/DepartBean'
import { router } from '@kit.ArkUI'
@Entry
@Component
struct Index {
@State currentIndex: number = 0
@State depBean: DepartBean = new DepartBean()
onPageShow(): void {
let params=router.getParams() as Record<string, DepartBean>
if (params) {
this.depBean=params['depBean']
}
}
build() {
Tabs({ barPosition: BarPosition.End }) {
ForEach(TAB_ARRAY, (item: Tab, index) => {
TabContent() {
if (index == 0) {
HomePage({ depBean: this.depBean })
} else if (index == 1) {
HousePage()
} else if (index == 2) {
CustomerPage()
} else if (index == 3) {
MessagePage()
} else {
MinePage()
}
}.align(Alignment.Top)
.tabBar(this.tabBuilder(item.tabText, index, item.tabSelectIcon, item.tabNormalIcon))
})
}
.overlay(createWaterMarkView())
.scrollable(false)
.animationDuration(0)
.backgroundColor($r("app.color.white"))
.padding({ bottom: px2vp(AppUtil.getNavigationIndicatorHeight()) })
.onChange((index) => {
this.currentIndex = index
})
}
@Builder
tabBuilder(title: string, targetIndex: number, selectedImg: Resource, normalImg: Resource) {
Column() {
Image(this.currentIndex === targetIndex ? selectedImg : normalImg)
.size({ width: 24, height: 24 })
Text(title)
.fontColor(this.currentIndex == targetIndex ? $r("app.color.main_color") : $r("app.color.text_auxiliary"))
.fontSize(10)
.padding(2)
}
.width('100%')
.padding({ top: 8, bottom: 8 })
.backgroundColor($r("app.color.white"))
.borderWidth({ top: 0.5 })
.borderColor($r("app.color.border_color"))
.justifyContent(FlexAlign.Center)
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。