Skip to main content

ecp_widget 2.2.0 copy "ecp_widget: ^2.2.0" to clipboard
ecp_widget: ^2.2.0 copied to clipboard

翼协云公共组件库

ecp_widget #

ecp_widget 是翼协云底座公共组件库

此库专为内部项目需求设计,若不符合您的使用场景,敬请谅解。

安装 #

在 pubspec.yaml 中添加依赖:

dependencies:
  ecp_widget: ^2.2.0

组件总览 #

分类 组件
弹窗 EcpAlertDialog、EcpBottomSheetDialog、EcpBottomSinglePicker、EcpCenterDialog、EcpTipsDialog
基础组件 EcpAvatar(头像)、EcpCachedNetImage(网络图缓存)、EcpCommonBtn(通用按钮)、EcpCornerMark(角标)、EcpIcon、EcpNavBarView(导航栏)、EcpSimpleCard(卡片)、EcpSimpleFormListView(表单列表)、EcpCommonOpinion(意见填写)、EcpGallery(图片预览)
日期时间 EcpDatePicker、EcpDateRangePicker、EcpDateTimePicker、EcpTimePicker
筛选 EcpFilterWidget、EcpFilterDialog、DateRangeFilterItem
选人/选部门 DepartmentUserPicker、EcpDepartmentPicker、EcpDepartmentUserPicker、EcpRolePicker、EcpUnitPicker、EcpUserPicker
搜索 SearchWithBtn、SearchWithDel
页面 LoginPage(登录页,2.2.0 起自 ecp_common_app 迁入:账号记忆、RSA 加密提交)
扫码 EcpScanManager(扫码分发:内容 URI 去掉 query 作为 key 分发;2.2.0 起自 ecp_scan_manager 迁入,底层 EcpScanPage 基于 mobile_scanner,内部页面不对外导出)
其他 IndexedTabScrollView、IndexedWidget、CrumbItem(面包屑)、UserPickerItem、字符串扩展、EcpHtml(富文本展示)

搜索 #

  • 带删除按钮的搜索框
SearchWithDel(
  onSearchClick: (text) => SmartDialog.showToast(text),///搜索时回调
);
  • 带按钮的搜索框
SearchWithBtn(
  onSearchClick: (text) => SmartDialog.showToast(text),///搜索时回调
);

Screenshot_20221123-175224.png

选人 #

  • 按部门选人
DepartmentUserPicker(
      {Key? key,
      this.limitNum = noLimited, ///限制数
      this.allowEmpty = false, ///是否允许不选人
      required this.userSelectorBuilder, ///选择人员列表Item样式
      required this.userSelectedBuilder, ///已选择人员列表Item样式
      required this.departmentBuilder, ///部门列表Item样式
      required this.crumbBuilder, ///面包屑列表Item样式
      this.departmentRepo, ///部门列表数据来源,包含子部门列表数据
      this.userRepo, /// 用户列表数据来源
      this.userSearchRepo, // 用户列表搜索数据来源
      });

或者直接使用翼协云公共样式

EcpDepartmentUserPicker({
    super.key,
    super.limitNum,///限制数
    super.allowEmpty,///是否允许不选人
  });
  • 选人控件 继承DepartmentUserPicker时,不传入departmentRepo即可
DepartmentUserPicker(
      {Key? key,
      this.limitNum = noLimited, ///限制数
      this.allowEmpty = false, ///是否允许不选人
      required this.userSelectorBuilder, ///选择人员列表Item样式
      required this.userSelectedBuilder, ///已选择人员列表Item样式
      required this.departmentBuilder, ///部门列表Item样式
      required this.crumbBuilder, ///面包屑列表Item样式
      this.departmentRepo, ///部门列表数据来源,包含子部门列表数据
      this.userRepo, /// 用户列表数据来源
      this.userSearchRepo, // 用户列表搜索数据来源
      });

默认翼协云公共样式

EcpUserPicker({
    super.key,
    super.limitNum,///限制数
    super.allowEmpty,///是否允许不选人
  });

登录页 #

LoginPage 为开箱即用的登录页(2.2.0 起自 ecp_common_app 迁入本库)。最典型的用法是作为 home:

import 'package:ecp_widget/ecp_widget.dart';

MaterialApp(
  home: LoginPage(
    ip: "http://135.0.123.110:8700/api", /// 可选:调试用登录地址
    nextPage: const MyHomePage(), /// 登录成功后跳转的页面
    onLoginSuccess: () async {
      /// 登录成功回调(先于 nextPage 跳转执行)
    },
  ),
);

在页面中跳转用法:

forwardPage(context, LoginPage(nextPage: const DemoPage()));

行为说明:

  • 账号密码自动记忆:登录成功后写入 SharedPreferences(keyLoginUser / keyLoginPassword),下次进入自动填充;debug 模式预填开发账号 tanantSuperAdmin / 123@Admin
  • 密码提交前经 rsaEncode RSA 加密,非明文传输;请求走 EcpGlobalApi.loginSimple,过程由 toDialogRequest 包裹(带弹窗反馈)
  • 登录成功顺序:RuntimeUtils.setRuntimeEntity + EcpGlobalDebugUtils.fillUserInfo() → onLoginSuccess → 跳转 nextPage
  • 隐藏交互:点击顶部图标,密码自动补全为「用户名@Sys」

配置注意事项:

  1. 网络初始化:登录请求依赖 ecp_net。宿主 App 需先完成 NetConfig 初始化(convert / initialDio / baseOptions),参照 example/lib/main.dart 的 initNet(),否则请求没有正确的 baseUrl 与转换规则
  2. 登录地址优先级:传入 ip 时直接与路径拼接为 "$ip" + "/km/sso/access/doLogin",必须包含完整前缀(协议+域名+端口+上下文,如 http://host:8700/api);不传则使用 NetConfig 的 baseUrl。ip 仅供调试时临时切换服务器
  3. 依赖版本:需 ecp_global ^2.1.0(提供 loginSimple、RuntimeUtils),登录成功会写入全局运行时供后续业务读取

扫码 #

扫码功能基于 mobile_scanner ^7.4.2(Android CameraX + MLKit;iOS AVFoundation + Vision)。推荐使用 EcpScanManager 做业务码分发:

// 1. 注册业务码回调。key 为二维码内容去掉 query 后的值:scheme://host + path
//    例如二维码内容 https://app.example.com/demo?from=qrcode → key 为 https://app.example.com/demo
EcpScanManager.register("https://app.example.com/demo", (uri) async {
  print("命中业务码,完整内容:$uri");
});

// 2. 打开扫码页
EcpScanManager.scan(context);

只关心原始内容时,可跳过 Manager 直接打开扫码页:

import 'package:ecp_widget/widgets/ecp_scan_page.dart';

var barcode = await forwardPage(context, const EcpScanPage());
print(barcode?.rawValue); /// 原始文本;barcode.displayValue / format 也可用

分发规则:扫码结果按「内容 URI 去掉 query」查找注册回调——

  • 命中 → 执行对应回调
  • 未命中 → 走 EcpScanManager.onErrorHandle;两者都没有时 toast「无法处理当前二维码」并抛出异常

配置注意事项:

  1. Android 权限:插件的 AndroidManifest 已声明 CAMERA 权限与 uses-feature(camera, required=false),manifest merger 会自动并入宿主,无需重复声明(example 中显式声明同样生效)
  2. 包体积:Android 默认使用 bundled 版 MLKit 条码模型,将增加约 3~10 MB 体积;如需瘦身,在宿主 android/gradle.properties 中添加 dev.steenbakker.mobile_scanner.useUnbundled=true(改用 unbundled 版,首次使用经 Google Play Services 下载,仅增约 600 KB,要求设备具备 GMS)
  3. iOS 权限:Info.plist 必须添加 NSCameraUsageDescription 及用途说明文案(example 已配置);当前实现未用相册识别,无需 NSPhotoLibraryUsageDescription,后续若启用 analyzeImage/相册选码再补
  4. 系统版本:插件要求 Android minSdk 23、最低 iOS 12.0;ecp_widget 2.1.0 已同步 minSdk 23 / iOS 部署目标 15.0(Podfile platform + post_install 强制),满足要求
  5. API 导出:EcpScanManager 从 ecp_widget.dart 主入口导出;EcpScanPage 未导出,需直接 import 'package:ecp_widget/widgets/ecp_scan_page.dart'(与 ecp_scaffold 的导出策略一致)
  6. 注册管理:register 对同 key 重复注册为幂等覆盖,页面重复进入无需清理;取消注册用 EcpScanManager().unRegister(key)

AI生成