开发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)
  }
}

曹晶
1 声望0 粉丝

移动应用开发者