鸿蒙ArkUI实现部门树列表

开发ERP系统的时候经常会用到部门树列表,页面主要由搜索框、顶部部门面包屑、多层级部门列表组成,部门列表项由不么名称和下一级右边箭头组成,点击部门名称区域可以回传部门数据到上一个页面,点击下一级箭头按钮可以展示下一级部门列表,同时将父级部门添加到顶部面包屑。

1、加载部门数数据

部门树数据由多个部门信息对象组成,部门对象中包含下级部门数组,里面可能会嵌套多个子级部门对象,这里用的json数据如下:

TypeScript 复制代码
[
  {
    "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图片组件组成。

TypeScript 复制代码
/**
 * 构建搜索框
 */
@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组件,点击部门名称,部门列表展示当前点击部门的所有子部门数据,具体代码如下:

TypeScript 复制代码
/**
 * 构建顶部部门面包屑
 */
@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、绘制部门列表

部门列表的每一项由部门名称和下一级按钮组成,点击部门名称区域会将当前部门传回到上一页面中,点击下一级按钮会展示下一级不么列数据,代码如下:

TypeScript 复制代码
 //构建部门列表
  @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是必传参数,这里返回上一页,可以直接传空字符。

TypeScript 复制代码
 //点击将选中的部门信息返回给上一个页面
 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']
    }
  }

完整代码如下:

TypeScript 复制代码
import { CommApiService } from "../../http/CommApiService";
import { DepartBean } from "../../model/DepartBean";
import { TitleBar } from "../../view/TitleBar";
import { router } from "@kit.ArkUI";
import { createWaterMarkView } from "../../view/WaterMarkView";

@Entry
@Component
export struct SelectDepPage {
  departments: Array<DepartBean> = [] //保存所有的层级部门列表数据
  @State depWord: string = "" // 搜索部门名称
  @State topDeps: Array<DepartBean> = [] // 顶级部门
  private topScroller: Scroller = new Scroller(); // 创建一个顶部面包屑滚动控制器
  private listScroller: Scroller = new Scroller(); // 创建一个部门列表滚动控制器
  @State listDeps: Array<DepartBean> = [] // 当前显示的部门列表数据

  aboutToAppear(): void {
    CommApiService.getInstance().httpGetDepartmentViewTree(list => {
      this.departments = list
      this.topDeps.push(list[0])
      this.listDeps = list[0].DepartmentListZtree ?? [] //默认添加所有部门数据
    })
  }

  build() {
    Column() {
      TitleBar({
        backShow: true,
        title: "选择部门",
        backCallBack: () => {
          router.back()
        }
      })
      Column() {
        //搜索框
        this.BuildSearch()
        //顶部部门面包屑
        this.BuildTopDep()
      }.backgroundColor(Color.White)
      .alignItems(HorizontalAlign.Start)
      .padding({ left: 12, right: 12, bottom: 12 })

      //部门列表
      this.BuildListDep()
    }.overlay(createWaterMarkView()) //页面添加水印
  }

  /**
   * 构建搜索框
   */
  @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)
  }

  /**
   * 构建顶部部门面包屑
   */
  @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 })
  }

  //构建部门列表
  @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 })
  }
}
相关推荐
莳花微语1 小时前
Euler 21.10(华为欧拉)安装oracle19c-RAC
数据库·华为·oracle
Lu_Ca3 小时前
鸿蒙APP之从开发到发布的一点心得
华为·harmonyos·鸿蒙
文火冰糖的硅基工坊6 小时前
[创业之路-241]:《从偶然到必然-华为研发投资与管理实践》-2- IPD流程中的业务线、技术线、职能支撑线
华为·产品运营·需求分析·产品·创业
IT 古月方源6 小时前
华为设备的监控和管理
运维·服务器·网络·安全·网络安全·华为
轻口味8 小时前
【每日学点鸿蒙知识】so 库瘦身、IDE 内存配置、判断前后台呢
ide·华为·harmonyos
ChinaDragonDreamer8 小时前
HarmonyOS:@Builder装饰器:自定义构建函数
harmonyos·鸿蒙
SoraLuna9 小时前
「Mac畅玩鸿蒙与硬件53」UI互动应用篇30 - 打卡提醒小应用
macos·ui·harmonyos
大土豆的bug记录10 小时前
Mac上鸿蒙配置HDC报错:zsh: command not found: hdc -v
macos·华为·harmonyos·arkts·鸿蒙·arkui
zhgjx_chen19 小时前
ENSP综合实验(中小型网络)
服务器·网络·华为
塞尔维亚大汉19 小时前
移植案例与原理 - startup子系统之bootstrap_lite服务启动引导部件(1)
harmonyos