# ecp_widget **Repository Path**: kitman/ecp_widget ## Basic Information - **Project Name**: ecp_widget - **Description**: No description available - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-07-25 - **Last Updated**: 2026-10-29 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # ecp_widget > ecp_widget 是翼协云底座公共组件库 > 此库专为内部项目需求设计,若不符合您的使用场景,敬请谅解。 ## 安装 在 `pubspec.yaml` 中添加依赖: ```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`(富文本展示) | ## 搜索 - 带删除按钮的搜索框 ```dart SearchWithDel( onSearchClick: (text) => SmartDialog.showToast(text),///搜索时回调 ); ``` - 带按钮的搜索框 ```dart SearchWithBtn( onSearchClick: (text) => SmartDialog.showToast(text),///搜索时回调 ); ``` ![Screenshot_20221123-175224.png](https://cdn.nlark.com/yuque/0/2022/png/2940130/1669253493263-b37af88e-a3c3-4c64-96e4-e2fe52302afe.png#averageHue=%23e9eaed&clientId=u357650aa-c500-4&crop=0&crop=0.1153&crop=1&crop=0.4389&from=drop&id=uaaf5e248&margin=%5Bobject%20Object%5D&name=Screenshot_20221123-175224.png&originHeight=1440&originWidth=720&originalType=binary&ratio=1&rotation=0&showTitle=false&size=55159&status=done&style=shadow&taskId=u815218ac-b8c0-473c-b001-8c52d8dd2b2&title=) ## 选人 - 按部门选人 ```dart 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, // 用户列表搜索数据来源 }); ``` 或者直接使用翼协云公共样式 ```dart EcpDepartmentUserPicker({ super.key, super.limitNum,///限制数 super.allowEmpty,///是否允许不选人 }); ``` - 选人控件 继承DepartmentUserPicker时,不传入departmentRepo即可 ```dart 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, // 用户列表搜索数据来源 }); ``` 默认翼协云公共样式 ```dart EcpUserPicker({ super.key, super.limitNum,///限制数 super.allowEmpty,///是否允许不选人 }); ``` ## 登录页 `LoginPage` 为开箱即用的登录页(2.2.0 起自 ecp_common_app 迁入本库)。最典型的用法是作为 `home`: ```dart import 'package:ecp_widget/ecp_widget.dart'; MaterialApp( home: LoginPage( ip: "http://135.0.123.110:8700/api", /// 可选:调试用登录地址 nextPage: const MyHomePage(), /// 登录成功后跳转的页面 onLoginSuccess: () async { /// 登录成功回调(先于 nextPage 跳转执行) }, ), ); ``` 在页面中跳转用法: ```dart 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` 做业务码分发: ```dart // 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 直接打开扫码页: ```dart 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生成