在这里插入图片描述

前言

工作台是OA系统的核心页面,快捷入口组件作为工作台的重要组成部分,为用户提供了快速访问常用功能的途径。一个设计良好的快捷入口组件需要支持图标展示、功能分类、自定义排序、角标提示等功能。本文将详细介绍如何使用Flutter和OpenHarmony开发一个灵活实用的工作台快捷入口组件,提升用户的工作效率。

组件功能规划

快捷入口组件通常采用宫格布局,每个入口包含图标、名称和可选的角标。组件需要支持动态配置入口项,不同用户可以看到不同的功能入口。同时支持编辑模式,用户可以自定义入口的显示顺序和是否显示。在交互上,点击入口跳转到对应功能页面,长按进入编辑模式。

Flutter端实现

定义快捷入口数据模型:

class QuickEntry {
  final String id;
  final String name;
  final String icon;
  final String route;
  final int? badge;
  final Color? backgroundColor;
  int sortOrder;
  bool isVisible;
  
  QuickEntry({
    required this.id,
    required this.name,
    required this.icon,
    required this.route,
    this.badge,
    this.backgroundColor,
    this.sortOrder = 0,
    this.isVisible = true,
  });
}

数据模型包含入口的基本信息和配置选项。badge字段用于显示未处理数量,如待审批数、未读消息数等。sortOrder和isVisible用于支持用户自定义排序和显示控制,这两个字段设为可变以便运行时修改。

快捷入口组件的基础结构:

class QuickEntryGrid extends StatefulWidget {
  final List<QuickEntry> entries;
  final Function(QuickEntry) onTap;
  final Function(List<QuickEntry>) onOrderChanged;
  
  const QuickEntryGrid({
    Key? key,
    required this.entries,
    required this.onTap,
    required this.onOrderChanged,
  }) : super(key: key);
  
  
  State<QuickEntryGrid> createState() => _QuickEntryGridState();
}

组件接收入口列表和回调函数,onTap处理点击事件,onOrderChanged在排序变化时触发,用于持久化用户的自定义排序。

状态类中的编辑模式管理:

class _QuickEntryGridState extends State<QuickEntryGrid> {
  bool _isEditMode = false;
  
  void _toggleEditMode() {
    setState(() => _isEditMode = !_isEditMode);
  }
  
  void _onReorder(int oldIndex, int newIndex) {
    setState(() {
      final item = widget.entries.removeAt(oldIndex);
      widget.entries.insert(newIndex, item);
      for (int i = 0; i < widget.entries.length; i++) {
        widget.entries[i].sortOrder = i;
      }
    });
    widget.onOrderChanged(widget.entries);
  }
}

编辑模式下用户可以拖拽调整入口顺序。_onReorder方法处理拖拽排序,更新列表顺序后同步更新每个入口的sortOrder字段,然后通知父组件保存新的排序。

宫格布局的构建:

GridView.builder(
  gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
    crossAxisCount: 4,
    mainAxisSpacing: 16,
    crossAxisSpacing: 16,
    childAspectRatio: 0.9,
  ),
  itemCount: widget.entries.where((e) => e.isVisible).length,
  itemBuilder: (context, index) {
    final entry = widget.entries.where((e) => e.isVisible).toList()[index];
    return _buildEntryItem(entry);
  },
)

GridView构建4列的宫格布局,mainAxisSpacing和crossAxisSpacing设置网格间距。childAspectRatio控制每个格子的宽高比,0.9使格子略高于宽,为图标和文字留出足够空间。只显示isVisible为true的入口。

入口项的构建:

Widget _buildEntryItem(QuickEntry entry) {
  return GestureDetector(
    onTap: () => widget.onTap(entry),
    onLongPress: _toggleEditMode,
    child: Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        Stack(
          clipBehavior: Clip.none,
          children: [
            Container(
              width: 48,
              height: 48,
              decoration: BoxDecoration(
                color: entry.backgroundColor ?? Colors.blue.withOpacity(0.1),
                borderRadius: BorderRadius.circular(12),
              ),
              child: Icon(
                _getIconData(entry.icon),
                color: Colors.blue,
              ),
            ),
            if (entry.badge != null && entry.badge! > 0)
              Positioned(
                right: -8,
                top: -8,
                child: _buildBadge(entry.badge!),
              ),
          ],
        ),
        SizedBox(height: 8),
        Text(
          entry.name,
          style: TextStyle(fontSize: 12),
          maxLines: 1,
          overflow: TextOverflow.ellipsis,
        ),
      ],
    ),
  );
}

入口项使用Column垂直排列图标和名称,Stack用于叠加角标。长按触发编辑模式,点击触发跳转。角标使用Positioned定位在图标右上角,clipBehavior设为none允许角标超出Stack边界。

OpenHarmony鸿蒙端实现

定义快捷入口接口:

interface QuickEntry {
  id: string
  name: string
  icon: Resource
  route: string
  badge?: number
  backgroundColor?: ResourceColor
  sortOrder: number
  isVisible: boolean
}

icon字段使用Resource类型,可以引用资源文件中的图片。backgroundColor使用ResourceColor类型,支持颜色字符串和Color枚举。

快捷入口组件的基础结构:

@Component
struct QuickEntryGrid {
  @Prop entries: QuickEntry[] = []
  @State isEditMode: boolean = false
  private onEntryClick: (entry: QuickEntry) => void = () => {}
  private onOrderChange: (entries: QuickEntry[]) => void = () => {}
}

使用@State管理编辑模式状态,@Prop接收入口列表。回调函数处理点击和排序变化事件。

宫格布局的构建:

Grid() {
  ForEach(this.getVisibleEntries(), (entry: QuickEntry, index: number) => {
    GridItem() {
      this.EntryItem(entry)
    }
  })
}
.columnsTemplate('1fr 1fr 1fr 1fr')
.rowsGap(16)
.columnsGap(16)
.padding(16)

Grid组件构建4列等宽布局,columnsTemplate使用1fr定义等分列。rowsGap和columnsGap设置网格间距,padding设置整体内边距。ForEach只渲染可见的入口项。

入口项的构建:

@Builder
EntryItem(entry: QuickEntry) {
  Column() {
    Badge({
      count: entry.badge || 0,
      position: BadgePosition.RightTop,
      style: { badgeSize: 16, badgeColor: '#F44336' }
    }) {
      Column() {
        Image(entry.icon)
          .width(32)
          .height(32)
      }
      .width(48)
      .height(48)
      .backgroundColor(entry.backgroundColor || '#E6F7FF')
      .borderRadius(12)
      .justifyContent(FlexAlign.Center)
    }
    
    Text(entry.name)
      .fontSize(12)
      .fontColor('#333333')
      .maxLines(1)
      .textOverflow({ overflow: TextOverflow.Ellipsis })
      .margin({ top: 8 })
  }
  .onClick(() => this.onEntryClick(entry))
  .gesture(
    LongPressGesture()
      .onAction(() => {
        this.isEditMode = true
      })
  )
}

鸿蒙的Badge组件内置了角标功能,count为0时自动隐藏。LongPressGesture处理长按手势,触发编辑模式。Image组件直接使用Resource类型的图标资源。

编辑模式下的拖拽排序:

@Builder
EditableGrid() {
  List() {
    ForEach(this.entries, (entry: QuickEntry, index: number) => {
      ListItem() {
        Row() {
          Image($r('app.media.drag_handle'))
            .width(24)
            .height(24)
          
          Image(entry.icon)
            .width(32)
            .height(32)
            .margin({ left: 12 })
          
          Text(entry.name)
            .fontSize(14)
            .margin({ left: 8 })
            .layoutWeight(1)
          
          Toggle({ type: ToggleType.Switch, isOn: entry.isVisible })
            .onChange((isOn: boolean) => {
              entry.isVisible = isOn
            })
        }
        .width('100%')
        .padding(12)
      }
    })
  }
  .editMode(true)
  .onItemMove((from: number, to: number) => {
    this.moveEntry(from, to)
    return true
  })
}

编辑模式使用List组件的editMode功能实现拖拽排序,onItemMove回调处理排序逻辑。每个列表项包含拖拽手柄、图标、名称和显示开关,用户可以调整顺序和控制显示隐藏。

总结

本文详细介绍了Flutter和OpenHarmony平台上工作台快捷入口组件的开发方法。快捷入口是OA系统工作台的核心组件,直接影响用户的操作效率。通过支持自定义排序和显示控制,可以让每个用户根据自己的使用习惯定制工作台。两个平台都提供了网格布局和拖拽排序的支持,开发者可以根据需求灵活实现。

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐