HarmonyOS 鸿蒙Next中子组件没有按照起始端对齐

HarmonyOS 鸿蒙Next中子组件没有按照起始端对齐

import router from '[@ohos](/user/ohos).router'
import { promptAction, UIContext } from '[@kit](/user/kit).ArkUI';
import { UserRepository } from '../util/UserRepository';
import {
  TyResult,
  SysDictData,
  SysDictDataResult,
  PaginationParams,
  PaginationResult,
  InspectionLog,
  InspectionQuestion,
  Inspectionlogsoid
} from '../util/dbutil';
import common from '[@ohos](/user/ohos).app.ability.common';

// 问题数据结构接口
interface ProblemItem {
  question: string;
  ft: string;
}

// Select选项接口
interface SelectOption {
  value: string;
  icon?: Resource;
}

// 搜索表单类
class SearchForm {
  id: string = '';
  area: string = '';
  date: string = '';
  status: number | undefined = undefined;
}

[@Entry](/user/Entry)
[@Component](/user/Component)
struct MainPage {
  private uiContext = new UIContext();
  // 状态管理
  [@State](/user/State) currentMenu: string = 'check-record'
  [@State](/user/State) dataList: boolean = true
  [@State](/user/State) formPd: string = ''
  [@State](/user/State) isLoading: boolean = false
  [@State](/user/State) isDatabaseReady: boolean = false
  // 数据管理
  [@State](/user/State) sysDictdata: SysDictData[] = []
  [@State](/user/State) inspectionLog: InspectionLog[] = []
  [@State](/user/State) searchForm: SearchForm = new SearchForm()
  [@State](/user/State) bh: string = ''
  // 分页管理
  [@State](/user/State) currentPage: number = 1
  [@State](/user/State) pageSize: number = 10
  [@State](/user/State) totalPages: number = 0
  [@State](/user/State) totalRecords: number = 0
  // 表返回消息  PaginationResult中的data 可能是任何对象
  [@State](/user/State) inspectionlogsResult: PaginationResult<InspectionLog> = {
    success: false,
    data: undefined,
    message: '',
    total: 0,
    page: 0,
    pageSize: 0,
    totalPages: 0
  }
  //码表返回消息
  [@State](/user/State) sysDictDataResult: SysDictDataResult = {
    success: false,
    data: undefined,
    message: '',
    errorCode: ''
  }
  private context = getContext(this) as common.UIAbilityContext

  async aboutToAppear() {
    await this.initializeDatabase();
    if (this.isDatabaseReady) {
      await this.getSysDictdata();
      await this.loadTableData();
    }
  }

  // 初始化数据库
  async initializeDatabase() {
    console.log("准备连数据库了!!!")
    this.isLoading = true
    try {
      const context = getContext(this) as common.Context
      this.isDatabaseReady = await UserRepository.initialize(context)

      if (this.isDatabaseReady) {
        promptAction.showToast({
          message: '数据库初始化成功',
          duration: 2000
        })
      } else {
        promptAction.showToast({
          message: '数据库初始化失败',
          duration: 2000
        })
      }
    } catch (error) {
      promptAction.showToast({
        message: '初始化数据库时出错',
        duration: 2000
      })
    } finally {
      this.isLoading = false
    }
  }

  // 加载表格数据
  async loadTableData() {
    this.isLoading = true
    let status = 0;
    if (this.currentMenu === 'check-record') { //'检查记录'
      status = 0;
    } else if (this.currentMenu === 'review-record') { //复查记录
      status = 2;
    } else if (this.currentMenu === 'done-record') { //已办记录
      status = 1;
    }
    try {
      const paginationParams: PaginationParams = {
        page: this.currentPage,
        pageSize: this.pageSize,
        inspection_no: this.searchForm.id || undefined,
        inspection_region: this.searchForm.area || undefined,
        create_time: this.searchForm.date || undefined,
        status: status
      }

      this.inspectionlogsResult = await UserRepository.getInspectionLogs(paginationParams);

      if (this.inspectionlogsResult.success && this.inspectionlogsResult.data) {
        this.inspectionLog = this.inspectionlogsResult.data;
        this.totalRecords = this.inspectionlogsResult.total;
        this.totalPages = this.inspectionlogsResult.totalPages;

        // promptAction.showToast({
        //   message: `查询成功,共${this.totalRecords}条记录`,
        //   duration: 2000
        // });
      } else {
        promptAction.showToast({
          message: this.inspectionlogsResult.message,
          duration: 2000
        });
      }
    } catch (error) {
      console.error('获取检查表失败:', error)
      promptAction.showToast({
        message: '查询失败,请重试',
        duration: 2000
      });
    } finally {
      this.isLoading = false
    }
  }

  // 获取码表数据
  async getSysDictdata() {
    this.isLoading = true
    try {
      this.sysDictDataResult = await UserRepository.getDictDatas('jcqy');
      if (this.sysDictDataResult.data) {
        this.sysDictdata = this.sysDictDataResult.data;
      }
      console.info('获取成功!!:', this.sysDictdata.length);
      if (this.sysDictDataResult.success) {
        promptAction.openToast({
          message: "获取码表数据成功",
          duration: 2000
        });
      } else {
        promptAction.openToast({
          message: this.sysDictDataResult.message,
          duration: 2000
        });
      }
    } catch (error) {
      console.error('获取码表数据失败:', error)
    } finally {
      this.isLoading = false
    }
  }

  // 添加测试数据
  async addSysDictdata() {
    const dictDataList: SysDictData[] = [
      {
        dict_sort: "1",
        dict_label: "检查区域1",
        dict_value: "检查区域1",
        dict_type: "jcqy",
      },
      {
        dict_sort: "2",
        dict_label: "检查区域2",
        dict_value: "检查区域2",
        dict_type: "jcqy",
      },
      {
        dict_sort: "3",
        dict_label: "检查区域3",
        dict_value: "检查区域3",
        dict_type: "jcqy",
      },
      {
        dict_sort: "1",
        dict_label: "条1",
        dict_value: "条1",
        dict_type: "ft",
      },
      {
        dict_sort: "2",
        dict_label: "条2",
        dict_value: "条2",
        dict_type: "ft",
      },
      {
        dict_sort: "3",
        dict_label: "条3",
        dict_value: "条3",
        dict_type: "ft",
      },
      {
        dict_sort: "1",
        dict_label: new Date().getFullYear().toString(),
        dict_value: "00000",
        dict_type: "bh",
      }
    ];

    for (const data of dictDataList) {
      await UserRepository.addSysDictData(data);
    }

    promptAction.showToast({
      message: '测试数据添加成功',
      duration: 2000
    });
  }

  // 获取编号
  async getBh() {
    try {
      this.bh = await UserRepository.getBh();
      console.log('获取编号成功:', this.bh)
    } catch (error) {
      console.error('获取编号失败:', error)
    }
  }
  // 获取前一天日期的方法
  private getYesterdayDate(): string {
    const yesterday = new Date();
    // yesterday.setDate(yesterday.getDate() - 2);
    yesterday.setDate(yesterday.getDate());
    return yesterday.toISOString().split('T')[0];
  }
  // 添加新检查
  async addInspectionLogs() {
    try {
      await this.getBh();

      const inspectionQuestions: InspectionQuestion[] = [
        {
          inspection_id: 0,
          question_pic: "图片路径1,图片路径2",
          question_czwt: JSON.stringify([
            { "question": "存在问题1", "ft": "相关条1" },
            { "question": "存在问题2", "ft": "相关条2" }
          ])
        }
      ];

      const newInspectionLog: InspectionLog = {
        inspection_no: this.bh,
        inspection_dep: "部门",
        inspection_name: "人",
        inspection_date: this.getYesterdayDate(),
        inspection_region: "区域",
        inspection_address: "详细地址",
        inspection_zrr: "责任人",
        inspection_zgyj: "意见",
        status: 1,
        inspection_endDate: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString().split('T')[0],
        inspectionQuestion: inspectionQuestions
      }

      const result = await UserRepository.addInspectionLog(newInspectionLog)
      if (result.success) {
        const inspectionlogsoid = JSON.parse(result.message) as Inspectionlogsoid
        promptAction.showToast({
          message: `添加表成功,ID: ${inspectionlogsoid.oid}`,
          duration: 2000
        });
        // 刷新列表
        await this.loadTableData();
      } else {
        promptAction.showToast({
          message: result.message,
          duration: 2000
        });
      }
    } catch (error) {
      console.error('添加记录失败:', error)
      promptAction.showToast({
        message: '添加失败,请重试',
        duration: 2000
      });
    }
  }

  // 菜单切换
  corder(menu: string) {
    this.currentMenu = menu
    this.dataList = true
    this.currentPage = 1 // 重置到第一页
    this.loadTableData()
  }

  // 查询
  handleSearch() {
    this.currentPage = 1 // 重置到第一页
    this.loadTableData()
  }

  // 重置查询
  handleReset() {
    this.searchForm = new SearchForm()
    this.currentPage = 1
    this.loadTableData()
  }

  // 新登记
  handleNewRegister() {
    this.formPd = '修改'
    this.dataList = false
    router.pushUrl({
      url: 'pages/DetailPage'
    })
  }

  // 查看
  handleView(item: InspectionLog) {
    this.formPd = '查看'
    this.dataList = false
    console.log('查看记录:', item.id)
    // 跳转到详情页面
  }

  // 修改
  handleEdit(item: InspectionLog) {
    this.formPd = '修改'
    this.dataList = false
    console.log('修改记录:', item.id)
    // 跳转到编辑页面
  }

  // 复查
  handleEditFuCa(item: InspectionLog) {
    this.formPd = '复查'
    this.dataList = false
    console.log('复查记录:', item.id)
    // 跳转到复查页面
  }

  // 分页操作
  handleFirstPage() {
    this.currentPage = 1
    this.loadTableData()
  }

  handlePrevPage() {
    if (this.currentPage > 1) {
      this.currentPage--
      this.loadTableData()
    }
  }

  handleNextPage() {
    if (this.currentPage < this.totalPages) {
      this.currentPage++
      this.loadTableData()
    }
  }

  handleLastPage() {
    this.currentPage = this.totalPages
    this.loadTableData()
  }

  handlePageJump(page: number) {
    if (page >= 1 && page <= this.totalPages) {
      this.currentPage = page
      this.loadTableData()
    }
  }

  build() {
    Column() {
      // 顶部栏
      this.TopBar()

      // 主体区域
      Row() {
        // 左侧导航
        this.Sidebar()

        // 右侧内容区
        if (this.isLoading && this.inspectionLog.length === 0) {
          this.LoadingState()
        } else if (!this.isDatabaseReady) {
          this.ErrorState('数据库未就绪')
        } else {
          this.ContentArea()
        }
      }
      .layoutWeight(1)
      .width('100%')
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#F5F7FA')
  }

  [@Builder](/user/Builder)
  TopBar() {
    Row() {
      Image($r('app.media.navleft'))
        .height('100%')
        .objectFit(ImageFit.Contain)

      Image($r('app.media.bt_bjlk'))
        .width(350)
        .height(50)
        .position({ x: 0, y: 0 })
        .objectFit(ImageFit.Contain)
    }
    .height(43)
    .width('100%')
    .backgroundColor('#0C9D72')
  }

  [@Builder](/user/Builder)
  Sidebar() {
    Column() {
      // 标题
      Row() {
        Image($r('app.media.left_jt'))
          .width(15)
          .height(15)
        Text('标题')
          .fontSize(14)
          .fontColor('#FFFFFF')
          .margin({ left: 10 })
      }
      .width('100%')
      .padding({ left: 10, top: 5, bottom: 5 })
      .backgroundColor('#52BF97')
      .alignItems(VerticalAlign.Center)

      // 菜单项
      this.MenuItem('check-record', $r('app.media.foreground'), '记录1')
      this.MenuItem('review-record', $r('app.media.foreground'), '记录2')
      this.MenuItem('done-record', $r('app.media.foreground'), '已办记录')
    }
    .width('15%')
    .height('100%')
    .backgroundColor('#EEEEEE')
    .border({ width: { right: 1 }, color: { right: '#868686' } })
  }

  [@Builder](/user/Builder)
  MenuItem(menuType: string, icon: Resource, text: string) {
    Row() {
      Image(icon)
        .width(15)
        .height(15)
        .margin({ left: 10, right: 5 })
      Text(text)
        .fontSize(14)
        .fontColor(this.currentMenu === menuType ? '#FFFFFF' : '#333333')
    }
    .width('100%')
    .padding({ top: 5, bottom: 5 })
    .backgroundColor(this.currentMenu === menuType ? '#0C9D72' : '#EEEEEE')
    .border({ width: { bottom: 1 }, color: { bottom: '#868686' } })
    .alignItems(VerticalAlign.Center)
    .onClick(() => {
      this.corder(menuType)
    })
  }

  [@Builder](/user/Builder)
  ContentArea() {
    Column() {
      // 标题区域
      this.TitleArea()

      // 搜索区域
      if (this.dataList) {
        this.SearchArea()
      }

      // 表格区域
      if (this.dataList) {
        this.TableArea()
      }

      // 分页区域
      if (this.dataList) {
        this.PaginationArea()
      }
    }
    .width('85%')
    .backgroundColor('#FFFFFF')
  }

  [@Builder](/user/Builder)
  TitleArea() {
    Row() {
      Image($r('app.media.foreground'))
        .width(10)
        .height(10)
        .margin({ left: 10, right: 4 })

      if (this.currentMenu === 'check-record') {
        Text('记录1')
          .fontWeight(FontWeight.Bold)
          .fontSize(16)
      } else if (this.currentMenu === 'review-record') {
        Text('记录2')
          .fontWeight(FontWeight.Bold)
          .fontSize(16)
      } else if (this.currentMenu === 'done-record') {
        Text('已办记录')
          .fontWeight(FontWeight.Bold)
          .fontSize(16)
      }
    }
    .width('100%')
    .height(30)
    .backgroundColor('#EEEEEE')
    .alignItems(VerticalAlign.Center)
  }

  [@Builder](/user/Builder)
  SearchArea() {
    Column() {
      Flex({
        direction: FlexDirection.Row,
        wrap: FlexWrap.Wrap,
        justifyContent: FlexAlign.Start,
        alignItems: ItemAlign.Center
      }) {
        // 编号输入
        this.SearchItem('编号', 'id', '请输入编号')

        // 区域输入
        this.AreaFilter();

        // 登记时间选择
        this.DatePickerItem()

        // 按钮组
        this.ButtonGroup()
      }
      .width('100%')
    }
    .width('100%')
    .padding(10)
    .margin({ top: 10, left: 8, right: 8 })
    .backgroundColor('#EEEEEE')
  }

  [@Builder](/user/Builder)
  SearchItem(label: string, field: string, placeholder: string) {
    Row() {
      Text(label)
        .fontSize(15)
        .fontColor('#333333')
        .width(60)
        .textAlign(TextAlign.End)
        .margin({ right: 8 })

      TextInput({ placeholder: placeholder, text: this.getFieldValue(field) })
        .onChange((value: string) => {
          this.setFieldValue(field, value)
        })
        .width(150)
        .height(32)
        .border({ width: 1, color: '#DDDDDD' })
        .borderRadius(4)
        .padding(4)
        .fontSize(12)
    }
    .margin({ right: 16, bottom: 8 })
    .alignItems(VerticalAlign.Center)
  }

  [@Builder](/user/Builder)
  DatePickerItem() {
    Row() {
      Text('登记时间')
        .fontSize(15)
        .fontColor('#333333')
        .width(60)
        .textAlign(TextAlign.End)
        .margin({ right: 8 })

      Text(this.searchForm.date || '请选择登记日期')
        .width(150)
        .backgroundColor('#FFFFFF')
        .border({ width: 1, color: '#DDDDDD' })
        .borderRadius(0)
        .padding(5)
        .onClick(() => {
          this.uiContext.showDatePickerDialog({
            start: new Date('2000-01-01'),
            selected: new Date(),
            onAccept: (value: Date

更多关于HarmonyOS 鸿蒙Next中子组件没有按照起始端对齐的实战教程也可以访问 https://www.itying.com/category-93-b0.html

7 回复

你可以吧代码打包发出来,我用你的代码跑不起来1

更多关于HarmonyOS 鸿蒙Next中子组件没有按照起始端对齐的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


谢谢已经解决了,

已处理将TableArea整体改造即可

@Builder
TableArea() {
  Column() {
    // 表头 - 固定高度
    this.TableHeader()

    // 表格内容 - 使用剩余空间
    Column() {
      if (this.inspectionLog.length > 0) {
        List({ space: 0 }) {
          ForEach(this.inspectionLog, (item: InspectionLog, index: number) => {
            ListItem() {
              this.TableRow(item, index)
            }
          }, (item: InspectionLog) => item.id?.toString() ?? Math.random().toString())
        }
        .width('100%')
        .layoutWeight(1)
      } else {
        this.EmptyState()
      }
    }
    .width('100%')
    .layoutWeight(1)
    .alignItems(HorizontalAlign.Start)
  }
  .width('100%')
  .height('70%')
  .margin({
    top: 10,
    left: 8,
    right: 8,
    bottom: 8
  })
  .border({ width: 1, color: '#DDDDDD' })
}

将tableRow外层的Row设置justifyContent(FlexAlign.Start),删除里面Text中的textAlign(TextAlign.Center)

@Builder TableRow(item: InspectionLog, index: number) { Row() { Text(item.inspection_no || ‘-’) .width(‘13%’) .fontSize(15) .textAlign(TextAlign.Center) //删除文字在Text组件居中显示,默认为TextAlign.Start居左 .padding(8) .border({ width: { right: 1 }, color: ‘#DDDDDD’ }) Text(item.inspection_dep || ‘-’) .width(‘15%’) .fontSize(15) .textAlign(TextAlign.Center) .padding(8) .border({ width: { right: 1 }, color: ‘#DDDDDD’ }) Text(item.inspection_name || ‘-’) .width(‘12%’) .fontSize(15) .textAlign(TextAlign.Center) .padding(8) .border({ width: { right: 1 }, color: ‘#DDDDDD’ }) Text(item.inspection_region || ‘-’) .width(‘15%’) .fontSize(15) .textAlign(TextAlign.Center) .padding(8) .border({ width: { right: 1 }, color: ‘#DDDDDD’ }) Text(item.inspection_date || ‘-’) .width(‘15%’) .fontSize(15) .textAlign(TextAlign.Center) .padding(8) .border({ width: { right: 1 }, color: ‘#DDDDDD’ }) Text(this.getStatusText(item.status)) .width(‘10%’) .fontSize(15) .textAlign(TextAlign.Center) .padding(8) .border({ width: { right: 1 }, color: ‘#DDDDDD’ }) this.OperationButtonsWithStyle(item) } .width(‘100%’) .justifyContent(FlexAlign.Start) //新增,元素在水平方向左对齐

您好 我的问题并不是元素内部左对齐或者是居中对齐的问题,是我整个列表内容在呈现上并没有紧贴表头,

在HarmonyOS鸿蒙Next中,子组件未按起始端对齐通常是由于布局容器属性设置问题。检查父容器的alignItems属性是否设为HorizontalAlign.StartVerticalAlign.Top。若使用Flex布局,确认justifyContent设为FlexAlign.Start。对于Stack组件,需设置alignContent为起始对齐方式。同时验证子组件的尺寸和位置属性是否冲突,例如widthheightmargin可能影响对齐效果。

在您的代码中,表格行没有按照起始端对齐的主要原因是 TableArea 中的布局设置问题。

具体分析:

  1. Scroll容器内的Column布局:在 TableAreaScroll 容器内,您使用了 Column 来包裹表格行,但没有设置正确的对齐方式。

  2. 默认对齐方式:Column 默认是垂直居中对齐的,这导致表格行在滚动区域内垂直居中显示,而不是从顶部开始排列。

解决方案

修改 TableArea 中的 Scroll 容器部分:

@Builder
TableArea() {
  Column() {
    // 表头
    this.TableHeader()

    // 表格内容
    Scroll() {
      Column() {
        if (this.inspectionLog.length > 0) {
          ForEach(this.inspectionLog, (item: InspectionLog, index: number) => {
            this.TableRow(item, index)
          }, (item: InspectionLog) => item.id?.toString() ?? Math.random().toString())
        } else {
          this.EmptyState()
        }
      }
      .width('100%')
      .alignItems(HorizontalAlign.Start)
      .justifyContent(FlexAlign.Start) // 添加这行确保从顶部开始
    }
    .scrollBar(BarState.On)
    .layoutWeight(1)
  }
  .width('100%')
  .layoutWeight(1)
  .margin({
    top: 10,
    left: 8,
    right: 8,
    bottom: 8
  })
  .border({ width: 1, color: '#DDDDDD' })
}

关键修改:

  • 添加 .justifyContent(FlexAlign.Start) 确保内容从容器顶部开始排列
  • 保持 .alignItems(HorizontalAlign.Start) 确保水平方向也从左侧开始

这样修改后,表格行就会从滚动区域的顶部开始排列,实现您期望的起始端对齐效果。

回到顶部