Merge branch 'release/2.1.0'
This commit is contained in:
commit
9335f4fddb
|
|
@ -0,0 +1,11 @@
|
|||
## 2.1.0
|
||||
|
||||
- Feat: 支持配置 `font_package` 以支持从其他包加载字体。
|
||||
- Refactor: 优化生成的代码结构,使用私有工厂方法减少代码体积。
|
||||
- Refactor: 统一 `fontFamily` 常量定义。
|
||||
|
||||
## 2.0.0
|
||||
|
||||
- Feat: 重构为 Dart CLI 工具。
|
||||
- Feat: 支持 YAML 配置文件。
|
||||
- Feat: 优化代码生成逻辑。
|
||||
483
README.md
483
README.md
|
|
@ -1,339 +1,202 @@
|
|||
# YX Icon Fonts
|
||||
|
||||
学习官OA系统图标字体库,基于iconfont.ttf和iconfont.json生成的Flutter图标库。
|
||||
从 iconfont.json 生成 Flutter IconData 常量的 Dart CLI 工具。
|
||||
|
||||
## 特性
|
||||
|
||||
- 🎨 包含50+个精心设计的图标
|
||||
- 📱 支持Flutter应用
|
||||
- 🎯 类型安全的图标使用
|
||||
- 📦 轻量级,无额外依赖
|
||||
- 🔧 易于集成和使用
|
||||
- ⚡ 自动化生成脚本
|
||||
- 🎨 解析 iconfont.cn 导出的 JSON 文件
|
||||
- 📝 生成类型安全的 Flutter IconData 常量
|
||||
- ⚙️ YAML 配置文件支持
|
||||
- 🏗️ 自定义类名和输出路径
|
||||
- 📚 自动生成文档注释
|
||||
|
||||
## 安装
|
||||
|
||||
在您的`pubspec.yaml`文件中添加依赖:
|
||||
在您的 Flutter 项目的 `pubspec.yaml` 中添加为开发依赖:
|
||||
|
||||
```yaml
|
||||
dependencies:
|
||||
yx_icon_fonts: ^1.0.0
|
||||
dev_dependencies:
|
||||
yx_icon_fonts:
|
||||
git:
|
||||
url: https://gitea.23544.com/wangyang/yx_icon_fonts_flutter
|
||||
ref: v2.0.0
|
||||
```
|
||||
|
||||
然后运行:
|
||||
|
||||
```bash
|
||||
flutter pub get
|
||||
dart pub get
|
||||
```
|
||||
|
||||
## 使用方法
|
||||
## 快速开始
|
||||
|
||||
### 基本用法
|
||||
### 1. 初始化配置文件
|
||||
|
||||
```bash
|
||||
dart run yx_icon_fonts init
|
||||
```
|
||||
|
||||
这将在项目根目录创建 `icon_generator_config.yaml` 配置模板。
|
||||
|
||||
### 2. 准备资源文件
|
||||
|
||||
从 [iconfont.cn](https://www.iconfont.cn/) 下载您的图标项目,将以下文件放到项目中:
|
||||
|
||||
- `iconfont.ttf` - 字体文件
|
||||
- `iconfont.json` - 图标配置文件
|
||||
|
||||
### 3. 配置 pubspec.yaml
|
||||
|
||||
在 `pubspec.yaml` 中注册字体:
|
||||
|
||||
```yaml
|
||||
flutter:
|
||||
fonts:
|
||||
- family: iconfont
|
||||
fonts:
|
||||
- asset: assets/fonts/iconfont.ttf
|
||||
```
|
||||
|
||||
### 4. 编辑配置文件
|
||||
|
||||
修改 `icon_generator_config.yaml`:
|
||||
|
||||
```yaml
|
||||
input:
|
||||
font_file: "assets/fonts/iconfont.ttf"
|
||||
json_file: "assets/fonts/iconfont.json"
|
||||
font_family: "iconfont"
|
||||
|
||||
output:
|
||||
file_path: "lib/generated/icons.dart"
|
||||
class_name: "AppIcons"
|
||||
```
|
||||
|
||||
### 5. 生成代码
|
||||
|
||||
```bash
|
||||
dart run yx_icon_fonts generate
|
||||
```
|
||||
|
||||
### 6. 使用生成的图标
|
||||
|
||||
```dart
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:yx_icon_fonts/yx_icon_fonts.dart';
|
||||
import 'package:your_app/generated/icons.dart';
|
||||
|
||||
class MyWidget extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Icon(
|
||||
YXIconFonts.iconMsgContacts,
|
||||
size: 24,
|
||||
color: Colors.blue,
|
||||
);
|
||||
}
|
||||
// 在 Widget 中使用
|
||||
Icon(AppIcons.iconHome, size: 24, color: Colors.blue)
|
||||
|
||||
// 在 IconButton 中使用
|
||||
IconButton(
|
||||
icon: Icon(AppIcons.iconSettings),
|
||||
onPressed: () {},
|
||||
)
|
||||
```
|
||||
|
||||
## 命令参考
|
||||
|
||||
### help - 显示帮助
|
||||
|
||||
```bash
|
||||
dart run yx_icon_fonts help
|
||||
```
|
||||
|
||||
### init - 初始化配置
|
||||
|
||||
```bash
|
||||
# 创建配置文件
|
||||
dart run yx_icon_fonts init
|
||||
|
||||
# 强制覆盖已存在的配置文件
|
||||
dart run yx_icon_fonts init --force
|
||||
```
|
||||
|
||||
### generate - 生成代码
|
||||
|
||||
```bash
|
||||
# 使用默认配置文件
|
||||
dart run yx_icon_fonts generate
|
||||
|
||||
# 指定配置文件
|
||||
dart run yx_icon_fonts generate --config my_config.yaml
|
||||
|
||||
# 详细输出
|
||||
dart run yx_icon_fonts generate --verbose
|
||||
```
|
||||
|
||||
## 配置选项
|
||||
|
||||
完整的配置选项请参考 [icon_generator_config.template.yaml](./icon_generator_config.template.yaml)。
|
||||
|
||||
### generator 配置
|
||||
|
||||
| 选项 | 类型 | 默认值 | 说明 |
|
||||
|------|------|--------|------|
|
||||
| name | string | "Icon Generator" | 生成器名称,用于代码注释 |
|
||||
| version | string | "1.0" | 版本号 |
|
||||
| author | string | "" | 作者信息 |
|
||||
|
||||
### input 配置
|
||||
|
||||
| 选项 | 类型 | 默认值 | 说明 |
|
||||
|------|------|--------|------|
|
||||
| font_file | string | "assets/fonts/iconfont.ttf" | 字体文件路径 |
|
||||
| json_file | string | "assets/fonts/iconfont.json" | JSON 配置文件路径 |
|
||||
| font_family | string | "iconfont" | 字体家族名称 |
|
||||
|
||||
### output 配置
|
||||
|
||||
| 选项 | 类型 | 默认值 | 说明 |
|
||||
|------|------|--------|------|
|
||||
| file_path | string | "lib/generated/icons.dart" | 输出文件路径 |
|
||||
| class_name | string | "AppIcons" | 生成的类名 |
|
||||
| generate_docs | bool | true | 是否生成文档注释 |
|
||||
| use_const_constructor | bool | true | 是否使用 const 构造函数 |
|
||||
|
||||
## 生成的代码示例
|
||||
|
||||
```dart
|
||||
// ignore_for_file: constant_identifier_names
|
||||
|
||||
// ============================================
|
||||
// 此文件由 yx_icon_fonts 自动生成,请勿手动修改
|
||||
// 生成时间: 2025-01-01 12:00
|
||||
// 图标数量: 50
|
||||
// ============================================
|
||||
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
/// MyApp Icons 图标常量
|
||||
class AppIcons {
|
||||
AppIcons._();
|
||||
|
||||
// 统一的 IconData 构造方法
|
||||
static const _icon = _IconDataFactory._();
|
||||
|
||||
/// icon_home (U+E600)
|
||||
static final IconData iconHome = _icon(0xe600);
|
||||
|
||||
// ... 更多图标
|
||||
}
|
||||
|
||||
/// 内部 IconData 工厂类
|
||||
class _IconDataFactory {
|
||||
const _IconDataFactory._();
|
||||
|
||||
static const String _fontFamily = 'iconfont';
|
||||
|
||||
IconData call(int codePoint) => IconData(codePoint, fontFamily: _fontFamily);
|
||||
}
|
||||
```
|
||||
|
||||
### 使用YXIcon组件
|
||||
## 从 v1.x 迁移
|
||||
|
||||
```dart
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:yx_icon_fonts/yx_icon_fonts.dart';
|
||||
v2.0 版本将 yx_icon_fonts 从 Flutter 库转换为了 CLI 工具。主要变化:
|
||||
|
||||
class MyWidget extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return YXIcon(
|
||||
YXIconFonts.iconMsgContacts,
|
||||
size: 24,
|
||||
color: Colors.blue,
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
1. **安装方式变化**:从 `dependencies` 改为 `dev_dependencies`
|
||||
2. **资源文件位置**:字体和 JSON 文件现在放在使用项目中,而非库中
|
||||
3. **配置方式**:使用 YAML 配置文件,支持自定义类名和路径
|
||||
|
||||
### 在AppBar中使用
|
||||
|
||||
```dart
|
||||
AppBar(
|
||||
title: Text('我的应用'),
|
||||
actions: [
|
||||
IconButton(
|
||||
icon: Icon(YXIconFonts.iconMsgSearch),
|
||||
onPressed: () {
|
||||
// 搜索操作
|
||||
},
|
||||
),
|
||||
],
|
||||
)
|
||||
```
|
||||
|
||||
## 可用图标
|
||||
|
||||
### 消息相关图标
|
||||
- `YXIconFonts.iconMsgContacts` - 联系人
|
||||
- `YXIconFonts.iconMsgViedo` - 视频
|
||||
- `YXIconFonts.iconMsgSearch` - 搜索
|
||||
- `YXIconFonts.iconMsgCall` - 通话
|
||||
- `YXIconFonts.iconMsgPhoto` - 照片
|
||||
- `YXIconFonts.iconMsgImg` - 图片
|
||||
- `YXIconFonts.iconMsgFile` - 文件
|
||||
|
||||
### 箭头相关图标
|
||||
- `YXIconFonts.icon32Arrowright` - 右箭头32
|
||||
- `YXIconFonts.icon44Arrowleft` - 左箭头44
|
||||
- `YXIconFonts.icon44Arrowright` - 右箭头44
|
||||
- `YXIconFonts.icon24Arrowleft` - 左箭头24
|
||||
- `YXIconFonts.icon24Arrowdown` - 下箭头24
|
||||
- `YXIconFonts.icon44Arrowright1` - 右箭头44(1)
|
||||
|
||||
### 编辑相关图标
|
||||
- `YXIconFonts.icon44Edit` - 编辑44
|
||||
- `YXIconFonts.icon24Edit` - 编辑24
|
||||
- `YXIconFonts.icon36Editline` - 编辑线36
|
||||
|
||||
### 个人中心相关图标
|
||||
- `YXIconFonts.icon44MePassword` - 密码
|
||||
- `YXIconFonts.icon44MeHelp` - 帮助
|
||||
- `YXIconFonts.icon44MeVersion` - 版本
|
||||
- `YXIconFonts.icon44MePrivacy` - 隐私
|
||||
- `YXIconFonts.icon44MeUser` - 用户
|
||||
- `YXIconFonts.icon44MeSafe` - 安全
|
||||
- `YXIconFonts.icon44MePhone` - 手机
|
||||
|
||||
### 功能图标
|
||||
- `YXIconFonts.icon32Filter` - 筛选
|
||||
- `YXIconFonts.icon36Question` - 问题
|
||||
- `YXIconFonts.icon36Onlysee` - 仅查看
|
||||
- `YXIconFonts.icon36Hint` - 提示
|
||||
- `YXIconFonts.icon24Switch` - 切换
|
||||
|
||||
### 操作图标
|
||||
- `YXIconFonts.icon44Delete` - 删除44
|
||||
- `YXIconFonts.icon36Delete` - 删除36
|
||||
- `YXIconFonts.icon24Delete` - 删除24
|
||||
- `YXIconFonts.icon44More` - 更多
|
||||
- `YXIconFonts.icon44More2` - 更多2
|
||||
- `YXIconFonts.icon24Copy` - 复制
|
||||
- `YXIconFonts.icon44Share` - 分享
|
||||
- `YXIconFonts.icon44Calendar` - 日历
|
||||
|
||||
### 添加相关图标
|
||||
- `YXIconFonts.icon24Add` - 添加24
|
||||
- `YXIconFonts.icon24Plus` - 加号
|
||||
- `YXIconFonts.icon44Add` - 添加44
|
||||
- `YXIconFonts.icon32Add` - 添加32
|
||||
|
||||
### 消息功能图标
|
||||
- `YXIconFonts.icon56Msgadd` - 消息添加
|
||||
- `YXIconFonts.icon56Msgface` - 消息表情
|
||||
- `YXIconFonts.icon56Msgvoice` - 消息语音
|
||||
|
||||
### 其他图标
|
||||
- `YXIconFonts.icon36Team` - 团队
|
||||
- `YXIconFonts.icon32Student` - 学生
|
||||
- `YXIconFonts.icon44Keyboard` - 键盘
|
||||
- `YXIconFonts.icon24Minus` - 减号
|
||||
- `YXIconFonts.icon44Quitlite` - 退出轻量
|
||||
- `YXIconFonts.icon32Quit` - 退出32
|
||||
- `YXIconFonts.icon44Quit` - 退出44
|
||||
|
||||
## 示例
|
||||
|
||||
运行示例应用查看所有图标:
|
||||
|
||||
```bash
|
||||
cd example
|
||||
flutter run
|
||||
```
|
||||
|
||||
## 自定义
|
||||
|
||||
### 修改图标大小
|
||||
|
||||
```dart
|
||||
Icon(
|
||||
YXIconFonts.iconMsgContacts,
|
||||
size: 48, // 自定义大小
|
||||
)
|
||||
```
|
||||
|
||||
### 修改图标颜色
|
||||
|
||||
```dart
|
||||
Icon(
|
||||
YXIconFonts.iconMsgContacts,
|
||||
color: Colors.red, // 自定义颜色
|
||||
)
|
||||
```
|
||||
|
||||
### 在主题中使用
|
||||
|
||||
```dart
|
||||
Theme(
|
||||
data: Theme.of(context).copyWith(
|
||||
iconTheme: IconThemeData(
|
||||
color: Colors.blue,
|
||||
size: 24,
|
||||
),
|
||||
),
|
||||
child: Icon(YXIconFonts.iconMsgContacts),
|
||||
)
|
||||
```
|
||||
|
||||
## 开发
|
||||
|
||||
### 自动化生成脚本
|
||||
|
||||
项目提供了 `generate.sh` 脚本来自动化图标数据的生成过程。
|
||||
|
||||
#### 脚本功能
|
||||
|
||||
- 🔄 自动生成图标数据文件 (`lib/src/yx_icon_fonts_data.dart`)
|
||||
- 📝 自动生成示例文件 (`example/lib/icons.dart`)
|
||||
- ✅ 错误检查和验证
|
||||
- 🎨 彩色输出和进度提示
|
||||
|
||||
#### 使用方法
|
||||
|
||||
```bash
|
||||
# 生成所有文件(默认)
|
||||
./generate.sh
|
||||
|
||||
# 只生成图标数据
|
||||
./generate.sh icons
|
||||
|
||||
# 只生成示例文件
|
||||
./generate.sh example
|
||||
|
||||
# 显示帮助信息
|
||||
./generate.sh help
|
||||
```
|
||||
|
||||
#### 脚本选项
|
||||
|
||||
| 选项 | 功能 | 生成文件 |
|
||||
|------|------|----------|
|
||||
| `all` (默认) | 生成所有文件 | `lib/src/yx_icon_fonts_data.dart` + `example/lib/icons.dart` |
|
||||
| `icons` | 只生成图标数据 | `lib/src/yx_icon_fonts_data.dart` |
|
||||
| `example` | 只生成示例文件 | `example/lib/icons.dart` |
|
||||
| `help` | 显示帮助信息 | - |
|
||||
|
||||
#### 使用示例
|
||||
|
||||
```bash
|
||||
# 首次使用,确保脚本有执行权限
|
||||
chmod +x generate.sh
|
||||
|
||||
# 生成所有文件
|
||||
./generate.sh
|
||||
|
||||
# 只更新图标数据(当修改了 iconfont.json 时)
|
||||
./generate.sh icons
|
||||
|
||||
# 只更新示例文件(当修改了图标数据时)
|
||||
./generate.sh example
|
||||
```
|
||||
|
||||
#### 脚本输出示例
|
||||
|
||||
```
|
||||
ℹ️ 开始生成所有文件...
|
||||
|
||||
ℹ️ 正在生成图标数据...
|
||||
✅ 图标数据生成完成
|
||||
|
||||
ℹ️ 正在生成示例文件...
|
||||
✅ 示例文件生成完成
|
||||
|
||||
✅ 所有文件生成完成!
|
||||
```
|
||||
|
||||
### 项目结构
|
||||
|
||||
```
|
||||
yx_icon_fonts/
|
||||
├── lib/
|
||||
│ ├── yx_icon_fonts.dart # 主库文件
|
||||
│ ├── main.dart # 库入口文件
|
||||
│ └── src/
|
||||
│ ├── yx_icon_data.dart # 图标数据类
|
||||
│ ├── yx_icon.dart # 图标组件
|
||||
│ └── yx_icon_fonts_data.dart # 图标常量定义(自动生成)
|
||||
├── fonts/
|
||||
│ └── iconfont.ttf # 字体文件
|
||||
├── scripts/
|
||||
│ ├── generate_icons.dart # 图标数据生成脚本
|
||||
│ ├── generate_example.dart # 示例文件生成脚本
|
||||
│ └── utils.dart # 共享工具函数
|
||||
├── example/
|
||||
│ └── lib/
|
||||
│ ├── main.dart # 示例应用
|
||||
│ └── icons.dart # 示例图标文件(自动生成)
|
||||
├── generate.sh # 自动化生成脚本
|
||||
├── iconfont.json # 图标配置数据
|
||||
├── pubspec.yaml # 包配置
|
||||
└── README.md # 项目文档
|
||||
```
|
||||
|
||||
### 更新图标
|
||||
|
||||
1. 替换 `fonts/iconfont.ttf` 文件
|
||||
2. 更新 `iconfont.json` 文件
|
||||
3. 运行生成脚本:
|
||||
```bash
|
||||
./generate.sh icons
|
||||
```
|
||||
4. 更新版本号
|
||||
|
||||
### 开发工作流
|
||||
|
||||
1. **修改图标源文件**:
|
||||
- 更新 `fonts/iconfont.ttf`
|
||||
- 更新 `iconfont.json`
|
||||
|
||||
2. **生成代码**:
|
||||
```bash
|
||||
./generate.sh
|
||||
```
|
||||
|
||||
3. **测试**:
|
||||
```bash
|
||||
flutter analyze
|
||||
flutter test
|
||||
cd example && flutter run
|
||||
```
|
||||
|
||||
4. **发布**:
|
||||
```bash
|
||||
flutter pub publish
|
||||
```
|
||||
|
||||
## 许可证
|
||||
## License
|
||||
|
||||
MIT License
|
||||
|
||||
## 贡献
|
||||
|
||||
欢迎提交Issue和Pull Request!
|
||||
|
||||
## 更新日志
|
||||
|
||||
### 1.0.0
|
||||
- 初始版本
|
||||
- 包含50+个图标
|
||||
- 支持Flutter 3.0+
|
||||
- 添加自动化生成脚本
|
||||
- 优化项目结构和文档
|
||||
|
|
@ -1,6 +1,17 @@
|
|||
include: package:lints/recommended.yaml
|
||||
include: package:very_good_analysis/analysis_options.yaml
|
||||
|
||||
analyzer:
|
||||
exclude:
|
||||
- temp_font_awesome/**
|
||||
- temp_font_awesome/**/*
|
||||
- generate/**
|
||||
- example/**
|
||||
|
||||
linter:
|
||||
rules:
|
||||
# 允许在生成的代码中使用常量标识符命名
|
||||
constant_identifier_names: false
|
||||
# 允许单行过长(生成的代码可能较长)
|
||||
lines_longer_than_80_chars: false
|
||||
# 允许公共成员不写文档
|
||||
public_member_api_docs: false
|
||||
|
|
|
|||
|
|
@ -0,0 +1,71 @@
|
|||
#!/usr/bin/env dart
|
||||
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:yx_icon_fonts/yx_icon_fonts.dart';
|
||||
|
||||
/// YX Icon Fonts CLI 工具主入口
|
||||
///
|
||||
/// 这是一个图标字体代码生成工具,可以:
|
||||
/// - 解析 iconfont.json 文件
|
||||
/// - 生成 Flutter IconData 常量
|
||||
/// - 支持自定义类名和输出路径
|
||||
///
|
||||
/// 使用方法:
|
||||
/// `dart run yx_icon_fonts <command> [options]`
|
||||
///
|
||||
/// 可用命令:
|
||||
/// - generate: 生成代码文件
|
||||
/// - init: 初始化配置文件
|
||||
/// - help: 显示帮助信息
|
||||
/// - version: 显示版本信息
|
||||
Future<void> main(List<String> arguments) async {
|
||||
setupLogging(level: Level.ALL);
|
||||
|
||||
// 检查是否有参数
|
||||
var resolvedArgs = arguments;
|
||||
if (resolvedArgs.isEmpty) {
|
||||
_showWelcome();
|
||||
resolvedArgs = ['help'];
|
||||
}
|
||||
|
||||
// 检查特殊命令
|
||||
if (resolvedArgs.contains('--version') || resolvedArgs.contains('-v')) {
|
||||
_showVersion();
|
||||
return;
|
||||
}
|
||||
|
||||
// 使用 CLI 运行器
|
||||
final cli = IconFontsCLI();
|
||||
final exitCode = await cli.run(resolvedArgs);
|
||||
|
||||
// 设置退出代码
|
||||
exit(exitCode);
|
||||
}
|
||||
|
||||
/// 显示欢迎信息
|
||||
void _showWelcome() {
|
||||
appLogger
|
||||
..info('🎨 欢迎使用 YX Icon Fonts CLI 工具!')
|
||||
..info('这是一个强大的图标字体代码生成工具,可以帮助您:')
|
||||
..info(' 📋 解析 iconfont.json 文件')
|
||||
..info(' 🛠️ 生成 Flutter IconData 常量')
|
||||
..info(' 📁 自定义输出路径和类名')
|
||||
..info('使用 --help 查看详细帮助信息');
|
||||
}
|
||||
|
||||
/// 显示版本信息
|
||||
void _showVersion() {
|
||||
appLogger
|
||||
..info('🎨 YX Icon Fonts CLI v2.0.0')
|
||||
..info('构建信息:')
|
||||
..info(' - Dart SDK: ${Platform.version}')
|
||||
..info(' - 平台: ${Platform.operatingSystem}')
|
||||
..info('特性:')
|
||||
..info(' ✨ YAML 配置文件支持')
|
||||
..info(' 🏗️ 模块化架构设计')
|
||||
..info(' 🚀 快速代码生成')
|
||||
..info(' 📝 自定义类名和路径')
|
||||
..info('更多信息请访问: https://gitea.23544.com/wangyang/yx_icon_fonts_flutter');
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
#!/usr/bin/env dart
|
||||
// YX Icon Fonts CLI 主入口
|
||||
// 这是包的默认可执行文件入口点
|
||||
// 当用户运行 `dart run yx_icon_fonts` 时会执行此文件
|
||||
|
||||
import 'main.dart' as entry;
|
||||
|
||||
void main(List<String> arguments) => entry.main(arguments);
|
||||
|
|
@ -0,0 +1,541 @@
|
|||
{
|
||||
"id": "4944890",
|
||||
"name": "劝学APP-学习官OA系统",
|
||||
"font_family": "iconfont",
|
||||
"css_prefix_text": "",
|
||||
"description": "劝学APP-学习官OA系统图标",
|
||||
"glyphs": [
|
||||
{
|
||||
"icon_id": "46349152",
|
||||
"name": "icon_32_clean",
|
||||
"font_class": "icon_32_clean",
|
||||
"unicode": "e660",
|
||||
"unicode_decimal": 58976
|
||||
},
|
||||
{
|
||||
"icon_id": "46348938",
|
||||
"name": "icon_36_viewhistory",
|
||||
"font_class": "icon_36_viewhistory",
|
||||
"unicode": "e65f",
|
||||
"unicode_decimal": 58975
|
||||
},
|
||||
{
|
||||
"icon_id": "46205256",
|
||||
"name": "icon_36_revoke",
|
||||
"font_class": "icon_36_revoke",
|
||||
"unicode": "e65e",
|
||||
"unicode_decimal": 58974
|
||||
},
|
||||
{
|
||||
"icon_id": "46077069",
|
||||
"name": "icon_30_edit",
|
||||
"font_class": "icon_30_edit",
|
||||
"unicode": "e65b",
|
||||
"unicode_decimal": 58971
|
||||
},
|
||||
{
|
||||
"icon_id": "46077068",
|
||||
"name": "icon_24_copy2",
|
||||
"font_class": "icon_24_copy2",
|
||||
"unicode": "e65c",
|
||||
"unicode_decimal": 58972
|
||||
},
|
||||
{
|
||||
"icon_id": "46077067",
|
||||
"name": "icon_30_delete",
|
||||
"font_class": "icon_30_delete",
|
||||
"unicode": "e65d",
|
||||
"unicode_decimal": 58973
|
||||
},
|
||||
{
|
||||
"icon_id": "46077053",
|
||||
"name": "icon_36_add",
|
||||
"font_class": "icon_36_add",
|
||||
"unicode": "e65a",
|
||||
"unicode_decimal": 58970
|
||||
},
|
||||
{
|
||||
"icon_id": "46076927",
|
||||
"name": "icon_32_location",
|
||||
"font_class": "icon_32_location",
|
||||
"unicode": "e659",
|
||||
"unicode_decimal": 58969
|
||||
},
|
||||
{
|
||||
"icon_id": "46076827",
|
||||
"name": "icon_24_mypoints",
|
||||
"font_class": "icon_24_mypoints",
|
||||
"unicode": "e657",
|
||||
"unicode_decimal": 58967
|
||||
},
|
||||
{
|
||||
"icon_id": "45986664",
|
||||
"name": "icon_44_me_about",
|
||||
"font_class": "icon_44_me_about",
|
||||
"unicode": "e656",
|
||||
"unicode_decimal": 58966
|
||||
},
|
||||
{
|
||||
"icon_id": "45986657",
|
||||
"name": "icon_44_me_pointsmall",
|
||||
"font_class": "icon_44_me_pointsmall",
|
||||
"unicode": "e658",
|
||||
"unicode_decimal": 58968
|
||||
},
|
||||
{
|
||||
"icon_id": "45876267",
|
||||
"name": "icon_44_search",
|
||||
"font_class": "icon_44_search",
|
||||
"unicode": "e655",
|
||||
"unicode_decimal": 58965
|
||||
},
|
||||
{
|
||||
"icon_id": "45855059",
|
||||
"name": "icon_36_clear_people",
|
||||
"font_class": "icon_36_clear_people",
|
||||
"unicode": "e654",
|
||||
"unicode_decimal": 58964
|
||||
},
|
||||
{
|
||||
"icon_id": "45530506",
|
||||
"name": "icon_44_me_log_out",
|
||||
"font_class": "icon_44_me_log_out",
|
||||
"unicode": "e652",
|
||||
"unicode_decimal": 58962
|
||||
},
|
||||
{
|
||||
"icon_id": "45530507",
|
||||
"name": "icon_44_me_switch",
|
||||
"font_class": "icon_44_me_switch",
|
||||
"unicode": "e653",
|
||||
"unicode_decimal": 58963
|
||||
},
|
||||
{
|
||||
"icon_id": "45513436",
|
||||
"name": "icon_44_wechat_share_white",
|
||||
"font_class": "icon_44_wechat_share_white",
|
||||
"unicode": "e651",
|
||||
"unicode_decimal": 58961
|
||||
},
|
||||
{
|
||||
"icon_id": "45513173",
|
||||
"name": "icon_32_publish",
|
||||
"font_class": "icon_32_publish",
|
||||
"unicode": "e64e",
|
||||
"unicode_decimal": 58958
|
||||
},
|
||||
{
|
||||
"icon_id": "45513174",
|
||||
"name": "icon_32_close",
|
||||
"font_class": "icon_32_close",
|
||||
"unicode": "e64f",
|
||||
"unicode_decimal": 58959
|
||||
},
|
||||
{
|
||||
"icon_id": "45513172",
|
||||
"name": "icon_32_output",
|
||||
"font_class": "icon_32_output",
|
||||
"unicode": "e650",
|
||||
"unicode_decimal": 58960
|
||||
},
|
||||
{
|
||||
"icon_id": "45500127",
|
||||
"name": "icon_24_download",
|
||||
"font_class": "icon_24_download",
|
||||
"unicode": "e64d",
|
||||
"unicode_decimal": 58957
|
||||
},
|
||||
{
|
||||
"icon_id": "45492400",
|
||||
"name": "icon_voice_pause",
|
||||
"font_class": "icon_voice_pause",
|
||||
"unicode": "e64b",
|
||||
"unicode_decimal": 58955
|
||||
},
|
||||
{
|
||||
"icon_id": "45492399",
|
||||
"name": "icon_voice",
|
||||
"font_class": "icon_voice",
|
||||
"unicode": "e64c",
|
||||
"unicode_decimal": 58956
|
||||
},
|
||||
{
|
||||
"icon_id": "45263171",
|
||||
"name": "icon_subtract",
|
||||
"font_class": "icon_subtract",
|
||||
"unicode": "e64a",
|
||||
"unicode_decimal": 58954
|
||||
},
|
||||
{
|
||||
"icon_id": "45214203",
|
||||
"name": "icon_44_edit",
|
||||
"font_class": "icon_44_edit",
|
||||
"unicode": "e648",
|
||||
"unicode_decimal": 58952
|
||||
},
|
||||
{
|
||||
"icon_id": "45214202",
|
||||
"name": "icon_44_delete",
|
||||
"font_class": "icon_44_delete",
|
||||
"unicode": "e649",
|
||||
"unicode_decimal": 58953
|
||||
},
|
||||
{
|
||||
"icon_id": "45160662",
|
||||
"name": "icon_44_cancel_account",
|
||||
"font_class": "icon_44_cancel_account",
|
||||
"unicode": "e647",
|
||||
"unicode_decimal": 58951
|
||||
},
|
||||
{
|
||||
"icon_id": "45103313",
|
||||
"name": "icon_24_search",
|
||||
"font_class": "icon_24_search",
|
||||
"unicode": "e646",
|
||||
"unicode_decimal": 58950
|
||||
},
|
||||
{
|
||||
"icon_id": "45037865",
|
||||
"name": "icon_24_up",
|
||||
"font_class": "icon_24_up",
|
||||
"unicode": "e645",
|
||||
"unicode_decimal": 58949
|
||||
},
|
||||
{
|
||||
"icon_id": "44661359",
|
||||
"name": "icon_msg_contacts",
|
||||
"font_class": "icon_msg_contacts",
|
||||
"unicode": "e644",
|
||||
"unicode_decimal": 58948
|
||||
},
|
||||
{
|
||||
"icon_id": "44659960",
|
||||
"name": "icon_msg_video",
|
||||
"font_class": "icon_msg_video",
|
||||
"unicode": "e63e",
|
||||
"unicode_decimal": 58942
|
||||
},
|
||||
{
|
||||
"icon_id": "44659959",
|
||||
"name": "icon_msg_search",
|
||||
"font_class": "icon_msg_search",
|
||||
"unicode": "e63f",
|
||||
"unicode_decimal": 58943
|
||||
},
|
||||
{
|
||||
"icon_id": "44659958",
|
||||
"name": "icon_msg_call",
|
||||
"font_class": "icon_msg_call",
|
||||
"unicode": "e640",
|
||||
"unicode_decimal": 58944
|
||||
},
|
||||
{
|
||||
"icon_id": "44659956",
|
||||
"name": "icon_msg_photo",
|
||||
"font_class": "icon_msg_photo",
|
||||
"unicode": "e641",
|
||||
"unicode_decimal": 58945
|
||||
},
|
||||
{
|
||||
"icon_id": "44659957",
|
||||
"name": "icon_msg_img",
|
||||
"font_class": "icon_msg_img",
|
||||
"unicode": "e642",
|
||||
"unicode_decimal": 58946
|
||||
},
|
||||
{
|
||||
"icon_id": "44659955",
|
||||
"name": "icon_msg_file",
|
||||
"font_class": "icon_msg_file",
|
||||
"unicode": "e643",
|
||||
"unicode_decimal": 58947
|
||||
},
|
||||
{
|
||||
"icon_id": "44625643",
|
||||
"name": "icon_32_arrow_right",
|
||||
"font_class": "icon_32_arrow_right",
|
||||
"unicode": "e61d",
|
||||
"unicode_decimal": 58909
|
||||
},
|
||||
{
|
||||
"icon_id": "44625452",
|
||||
"name": "icon_44_me_password",
|
||||
"font_class": "icon_44_me_password",
|
||||
"unicode": "e639",
|
||||
"unicode_decimal": 58937
|
||||
},
|
||||
{
|
||||
"icon_id": "44625448",
|
||||
"name": "icon_44_me_help",
|
||||
"font_class": "icon_44_me_help",
|
||||
"unicode": "e63a",
|
||||
"unicode_decimal": 58938
|
||||
},
|
||||
{
|
||||
"icon_id": "44625447",
|
||||
"name": "icon_24_minus",
|
||||
"font_class": "icon_24_minus",
|
||||
"unicode": "e63b",
|
||||
"unicode_decimal": 58939
|
||||
},
|
||||
{
|
||||
"icon_id": "44625450",
|
||||
"name": "icon_36_team",
|
||||
"font_class": "icon_36_team",
|
||||
"unicode": "e63c",
|
||||
"unicode_decimal": 58940
|
||||
},
|
||||
{
|
||||
"icon_id": "44625446",
|
||||
"name": "icon_32_filter",
|
||||
"font_class": "icon_32_filter",
|
||||
"unicode": "e63d",
|
||||
"unicode_decimal": 58941
|
||||
},
|
||||
{
|
||||
"icon_id": "44625458",
|
||||
"name": "icon_44_quit_lite",
|
||||
"font_class": "icon_44_quit_lite",
|
||||
"unicode": "e631",
|
||||
"unicode_decimal": 58929
|
||||
},
|
||||
{
|
||||
"icon_id": "44625459",
|
||||
"name": "icon_44_me_version",
|
||||
"font_class": "icon_44_me_version",
|
||||
"unicode": "e632",
|
||||
"unicode_decimal": 58930
|
||||
},
|
||||
{
|
||||
"icon_id": "44625456",
|
||||
"name": "icon_36_question",
|
||||
"font_class": "icon_36_question",
|
||||
"unicode": "e633",
|
||||
"unicode_decimal": 58931
|
||||
},
|
||||
{
|
||||
"icon_id": "44625457",
|
||||
"name": "icon_44_me_privacy",
|
||||
"font_class": "icon_44_me_privacy",
|
||||
"unicode": "e634",
|
||||
"unicode_decimal": 58932
|
||||
},
|
||||
{
|
||||
"icon_id": "44625455",
|
||||
"name": "icon_44_more2",
|
||||
"font_class": "icon_44_more2",
|
||||
"unicode": "e635",
|
||||
"unicode_decimal": 58933
|
||||
},
|
||||
{
|
||||
"icon_id": "44625453",
|
||||
"name": "icon_36_only_see",
|
||||
"font_class": "icon_36_only_see",
|
||||
"unicode": "e636",
|
||||
"unicode_decimal": 58934
|
||||
},
|
||||
{
|
||||
"icon_id": "44625454",
|
||||
"name": "icon_44_me_user",
|
||||
"font_class": "icon_44_me_user",
|
||||
"unicode": "e637",
|
||||
"unicode_decimal": 58935
|
||||
},
|
||||
{
|
||||
"icon_id": "44625461",
|
||||
"name": "icon_44_me_safe",
|
||||
"font_class": "icon_44_me_safe",
|
||||
"unicode": "e62c",
|
||||
"unicode_decimal": 58924
|
||||
},
|
||||
{
|
||||
"icon_id": "44625460",
|
||||
"name": "icon_44_me_phone",
|
||||
"font_class": "icon_44_me_phone",
|
||||
"unicode": "e62d",
|
||||
"unicode_decimal": 58925
|
||||
},
|
||||
{
|
||||
"icon_id": "44625445",
|
||||
"name": "icon_24_copy",
|
||||
"font_class": "icon_24_copy",
|
||||
"unicode": "e62e",
|
||||
"unicode_decimal": 58926
|
||||
},
|
||||
{
|
||||
"icon_id": "44625444",
|
||||
"name": "icon_32_quit",
|
||||
"font_class": "icon_32_quit",
|
||||
"unicode": "e630",
|
||||
"unicode_decimal": 58928
|
||||
},
|
||||
{
|
||||
"icon_id": "44572509",
|
||||
"name": "icon_44_calendar",
|
||||
"font_class": "icon_44_calendar",
|
||||
"unicode": "e626",
|
||||
"unicode_decimal": 58918
|
||||
},
|
||||
{
|
||||
"icon_id": "44572496",
|
||||
"name": "icon_32_student",
|
||||
"font_class": "icon_32_student",
|
||||
"unicode": "e627",
|
||||
"unicode_decimal": 58919
|
||||
},
|
||||
{
|
||||
"icon_id": "44572501",
|
||||
"name": "icon_36_delete",
|
||||
"font_class": "icon_36_delete",
|
||||
"unicode": "e628",
|
||||
"unicode_decimal": 58920
|
||||
},
|
||||
{
|
||||
"icon_id": "44572505",
|
||||
"name": "icon_44_more",
|
||||
"font_class": "icon_44_more",
|
||||
"unicode": "e629",
|
||||
"unicode_decimal": 58921
|
||||
},
|
||||
{
|
||||
"icon_id": "44572502",
|
||||
"name": "icon_44_arrow_left",
|
||||
"font_class": "icon_44_arrow_left",
|
||||
"unicode": "e62a",
|
||||
"unicode_decimal": 58922
|
||||
},
|
||||
{
|
||||
"icon_id": "44572499",
|
||||
"name": "icon_36_edit_line",
|
||||
"font_class": "icon_36_edit_line",
|
||||
"unicode": "e62b",
|
||||
"unicode_decimal": 58923
|
||||
},
|
||||
{
|
||||
"icon_id": "44572515",
|
||||
"name": "icon_44_arrow_right",
|
||||
"font_class": "icon_44_arrow_right",
|
||||
"unicode": "e622",
|
||||
"unicode_decimal": 58914
|
||||
},
|
||||
{
|
||||
"icon_id": "44572507",
|
||||
"name": "icon_24_delete",
|
||||
"font_class": "icon_24_delete",
|
||||
"unicode": "e623",
|
||||
"unicode_decimal": 58915
|
||||
},
|
||||
{
|
||||
"icon_id": "44572513",
|
||||
"name": "icon_56_msg_add",
|
||||
"font_class": "icon_56_msg_add",
|
||||
"unicode": "e624",
|
||||
"unicode_decimal": 58916
|
||||
},
|
||||
{
|
||||
"icon_id": "44572511",
|
||||
"name": "icon_56_msg_face",
|
||||
"font_class": "icon_56_msg_face",
|
||||
"unicode": "e625",
|
||||
"unicode_decimal": 58917
|
||||
},
|
||||
{
|
||||
"icon_id": "44572516",
|
||||
"name": "icon_56_msg_voice",
|
||||
"font_class": "icon_56_msg_voice",
|
||||
"unicode": "e616",
|
||||
"unicode_decimal": 58902
|
||||
},
|
||||
{
|
||||
"icon_id": "44572514",
|
||||
"name": "icon_44_share",
|
||||
"font_class": "icon_44_share",
|
||||
"unicode": "e615",
|
||||
"unicode_decimal": 58901
|
||||
},
|
||||
{
|
||||
"icon_id": "44572500",
|
||||
"name": "icon_36_hint",
|
||||
"font_class": "icon_36_hint",
|
||||
"unicode": "e613",
|
||||
"unicode_decimal": 58899
|
||||
},
|
||||
{
|
||||
"icon_id": "44572510",
|
||||
"name": "icon_24_add",
|
||||
"font_class": "icon_24_add",
|
||||
"unicode": "e617",
|
||||
"unicode_decimal": 58903
|
||||
},
|
||||
{
|
||||
"icon_id": "44572512",
|
||||
"name": "icon_24_plus",
|
||||
"font_class": "icon_24_plus",
|
||||
"unicode": "e618",
|
||||
"unicode_decimal": 58904
|
||||
},
|
||||
{
|
||||
"icon_id": "44572508",
|
||||
"name": "icon_44_keyboard",
|
||||
"font_class": "icon_44_keyboard",
|
||||
"unicode": "e614",
|
||||
"unicode_decimal": 58900
|
||||
},
|
||||
{
|
||||
"icon_id": "44572506",
|
||||
"name": "icon_44_quit",
|
||||
"font_class": "icon_44_quit",
|
||||
"unicode": "e619",
|
||||
"unicode_decimal": 58905
|
||||
},
|
||||
{
|
||||
"icon_id": "44572504",
|
||||
"name": "icon_44_add",
|
||||
"font_class": "icon_44_add",
|
||||
"unicode": "e61a",
|
||||
"unicode_decimal": 58906
|
||||
},
|
||||
{
|
||||
"icon_id": "44572495",
|
||||
"name": "icon_24_switch",
|
||||
"font_class": "icon_24_switch",
|
||||
"unicode": "e61b",
|
||||
"unicode_decimal": 58907
|
||||
},
|
||||
{
|
||||
"icon_id": "44572503",
|
||||
"name": "icon_44_arrow_down_line",
|
||||
"font_class": "icon_44_arrow_down_line",
|
||||
"unicode": "e61c",
|
||||
"unicode_decimal": 58908
|
||||
},
|
||||
{
|
||||
"icon_id": "44572493",
|
||||
"name": "icon_24_arrow_right",
|
||||
"font_class": "icon_24_arrow_right",
|
||||
"unicode": "e61e",
|
||||
"unicode_decimal": 58910
|
||||
},
|
||||
{
|
||||
"icon_id": "44572498",
|
||||
"name": "icon_32_add",
|
||||
"font_class": "icon_32_add",
|
||||
"unicode": "e61f",
|
||||
"unicode_decimal": 58911
|
||||
},
|
||||
{
|
||||
"icon_id": "44572494",
|
||||
"name": "icon_24_edit",
|
||||
"font_class": "icon_24_edit",
|
||||
"unicode": "e620",
|
||||
"unicode_decimal": 58912
|
||||
},
|
||||
{
|
||||
"icon_id": "44572492",
|
||||
"name": "icon_24_arrow_down",
|
||||
"font_class": "icon_24_arrow_down",
|
||||
"unicode": "e621",
|
||||
"unicode_decimal": 58913
|
||||
}
|
||||
]
|
||||
}
|
||||
Binary file not shown.
|
|
@ -0,0 +1,23 @@
|
|||
# 图标字体生成器配置文件
|
||||
# 用于生成 Flutter IconData 常量
|
||||
|
||||
generator:
|
||||
name: "Example App Icons"
|
||||
version: "1.0"
|
||||
author: "Example"
|
||||
|
||||
input:
|
||||
# 字体文件路径
|
||||
font_file: "assets/fonts/iconfont.ttf"
|
||||
# JSON 配置文件路径
|
||||
json_file: "assets/fonts/iconfont.json"
|
||||
# 字体家族名称
|
||||
font_family: "iconfont"
|
||||
|
||||
output:
|
||||
# 生成的 Dart 文件路径
|
||||
file_path: "lib/generated/icons.dart"
|
||||
# 生成的类名
|
||||
class_name: "AppIcons"
|
||||
# 是否生成文档注释
|
||||
generate_docs: true
|
||||
|
|
@ -1,24 +1,9 @@
|
|||
import 'package:flutter/widgets.dart';
|
||||
|
||||
/// 示例图标类
|
||||
///
|
||||
/// 用于在示例应用中展示图标
|
||||
class ExampleIcon implements Comparable {
|
||||
/// 示例图标模型
|
||||
class ExampleIcon {
|
||||
const ExampleIcon(this.iconData, this.title);
|
||||
|
||||
final IconData iconData;
|
||||
final String title;
|
||||
|
||||
ExampleIcon(this.iconData, this.title);
|
||||
|
||||
@override
|
||||
String toString() => 'ExampleIcon{iconData: $iconData, title: $title}';
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) || other is ExampleIcon && runtimeType == other.runtimeType && iconData == other.iconData && title == other.title;
|
||||
|
||||
@override
|
||||
int get hashCode => iconData.hashCode ^ title.hashCode;
|
||||
|
||||
@override
|
||||
int compareTo(other) => title.compareTo(other.title);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,261 @@
|
|||
// ignore_for_file: constant_identifier_names
|
||||
|
||||
// ============================================
|
||||
// 此文件由 yx_icon_fonts 自动生成,请勿手动修改
|
||||
// 生成时间: 2025-12-17 11:07
|
||||
// 图标数量: 76
|
||||
// ============================================
|
||||
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
/// Example App Icons 图标常量
|
||||
///
|
||||
/// 包含所有图标的常量定义,可以直接在 Flutter 的 Icon 组件中使用
|
||||
///
|
||||
/// 示例:
|
||||
/// ```dart
|
||||
/// Icon(AppIcons.iconName, size: 24)
|
||||
/// ```
|
||||
class AppIcons {
|
||||
AppIcons._();
|
||||
|
||||
// 统一的 IconData 构造方法
|
||||
static const _icon = _IconDataFactory._();
|
||||
|
||||
/// icon_32_clean (U+E660)
|
||||
static final IconData icon32Clean = _icon(0xe660);
|
||||
|
||||
/// icon_36_viewhistory (U+E65F)
|
||||
static final IconData icon36Viewhistory = _icon(0xe65f);
|
||||
|
||||
/// icon_36_revoke (U+E65E)
|
||||
static final IconData icon36Revoke = _icon(0xe65e);
|
||||
|
||||
/// icon_30_edit (U+E65B)
|
||||
static final IconData icon30Edit = _icon(0xe65b);
|
||||
|
||||
/// icon_24_copy2 (U+E65C)
|
||||
static final IconData icon24Copy2 = _icon(0xe65c);
|
||||
|
||||
/// icon_30_delete (U+E65D)
|
||||
static final IconData icon30Delete = _icon(0xe65d);
|
||||
|
||||
/// icon_36_add (U+E65A)
|
||||
static final IconData icon36Add = _icon(0xe65a);
|
||||
|
||||
/// icon_32_location (U+E659)
|
||||
static final IconData icon32Location = _icon(0xe659);
|
||||
|
||||
/// icon_24_mypoints (U+E657)
|
||||
static final IconData icon24Mypoints = _icon(0xe657);
|
||||
|
||||
/// icon_44_me_about (U+E656)
|
||||
static final IconData icon44MeAbout = _icon(0xe656);
|
||||
|
||||
/// icon_44_me_pointsmall (U+E658)
|
||||
static final IconData icon44MePointsmall = _icon(0xe658);
|
||||
|
||||
/// icon_44_search (U+E655)
|
||||
static final IconData icon44Search = _icon(0xe655);
|
||||
|
||||
/// icon_36_clear_people (U+E654)
|
||||
static final IconData icon36ClearPeople = _icon(0xe654);
|
||||
|
||||
/// icon_44_me_log_out (U+E652)
|
||||
static final IconData icon44MeLogOut = _icon(0xe652);
|
||||
|
||||
/// icon_44_me_switch (U+E653)
|
||||
static final IconData icon44MeSwitch = _icon(0xe653);
|
||||
|
||||
/// icon_44_wechat_share_white (U+E651)
|
||||
static final IconData icon44WechatShareWhite = _icon(0xe651);
|
||||
|
||||
/// icon_32_publish (U+E64E)
|
||||
static final IconData icon32Publish = _icon(0xe64e);
|
||||
|
||||
/// icon_32_close (U+E64F)
|
||||
static final IconData icon32Close = _icon(0xe64f);
|
||||
|
||||
/// icon_32_output (U+E650)
|
||||
static final IconData icon32Output = _icon(0xe650);
|
||||
|
||||
/// icon_24_download (U+E64D)
|
||||
static final IconData icon24Download = _icon(0xe64d);
|
||||
|
||||
/// icon_voice_pause (U+E64B)
|
||||
static final IconData iconVoicePause = _icon(0xe64b);
|
||||
|
||||
/// icon_voice (U+E64C)
|
||||
static final IconData iconVoice = _icon(0xe64c);
|
||||
|
||||
/// icon_subtract (U+E64A)
|
||||
static final IconData iconSubtract = _icon(0xe64a);
|
||||
|
||||
/// icon_44_edit (U+E648)
|
||||
static final IconData icon44Edit = _icon(0xe648);
|
||||
|
||||
/// icon_44_delete (U+E649)
|
||||
static final IconData icon44Delete = _icon(0xe649);
|
||||
|
||||
/// icon_44_cancel_account (U+E647)
|
||||
static final IconData icon44CancelAccount = _icon(0xe647);
|
||||
|
||||
/// icon_24_search (U+E646)
|
||||
static final IconData icon24Search = _icon(0xe646);
|
||||
|
||||
/// icon_24_up (U+E645)
|
||||
static final IconData icon24Up = _icon(0xe645);
|
||||
|
||||
/// icon_msg_contacts (U+E644)
|
||||
static final IconData iconMsgContacts = _icon(0xe644);
|
||||
|
||||
/// icon_msg_video (U+E63E)
|
||||
static final IconData iconMsgVideo = _icon(0xe63e);
|
||||
|
||||
/// icon_msg_search (U+E63F)
|
||||
static final IconData iconMsgSearch = _icon(0xe63f);
|
||||
|
||||
/// icon_msg_call (U+E640)
|
||||
static final IconData iconMsgCall = _icon(0xe640);
|
||||
|
||||
/// icon_msg_photo (U+E641)
|
||||
static final IconData iconMsgPhoto = _icon(0xe641);
|
||||
|
||||
/// icon_msg_img (U+E642)
|
||||
static final IconData iconMsgImg = _icon(0xe642);
|
||||
|
||||
/// icon_msg_file (U+E643)
|
||||
static final IconData iconMsgFile = _icon(0xe643);
|
||||
|
||||
/// icon_32_arrow_right (U+E61D)
|
||||
static final IconData icon32ArrowRight = _icon(0xe61d);
|
||||
|
||||
/// icon_44_me_password (U+E639)
|
||||
static final IconData icon44MePassword = _icon(0xe639);
|
||||
|
||||
/// icon_44_me_help (U+E63A)
|
||||
static final IconData icon44MeHelp = _icon(0xe63a);
|
||||
|
||||
/// icon_24_minus (U+E63B)
|
||||
static final IconData icon24Minus = _icon(0xe63b);
|
||||
|
||||
/// icon_36_team (U+E63C)
|
||||
static final IconData icon36Team = _icon(0xe63c);
|
||||
|
||||
/// icon_32_filter (U+E63D)
|
||||
static final IconData icon32Filter = _icon(0xe63d);
|
||||
|
||||
/// icon_44_quit_lite (U+E631)
|
||||
static final IconData icon44QuitLite = _icon(0xe631);
|
||||
|
||||
/// icon_44_me_version (U+E632)
|
||||
static final IconData icon44MeVersion = _icon(0xe632);
|
||||
|
||||
/// icon_36_question (U+E633)
|
||||
static final IconData icon36Question = _icon(0xe633);
|
||||
|
||||
/// icon_44_me_privacy (U+E634)
|
||||
static final IconData icon44MePrivacy = _icon(0xe634);
|
||||
|
||||
/// icon_44_more2 (U+E635)
|
||||
static final IconData icon44More2 = _icon(0xe635);
|
||||
|
||||
/// icon_36_only_see (U+E636)
|
||||
static final IconData icon36OnlySee = _icon(0xe636);
|
||||
|
||||
/// icon_44_me_user (U+E637)
|
||||
static final IconData icon44MeUser = _icon(0xe637);
|
||||
|
||||
/// icon_44_me_safe (U+E62C)
|
||||
static final IconData icon44MeSafe = _icon(0xe62c);
|
||||
|
||||
/// icon_44_me_phone (U+E62D)
|
||||
static final IconData icon44MePhone = _icon(0xe62d);
|
||||
|
||||
/// icon_24_copy (U+E62E)
|
||||
static final IconData icon24Copy = _icon(0xe62e);
|
||||
|
||||
/// icon_32_quit (U+E630)
|
||||
static final IconData icon32Quit = _icon(0xe630);
|
||||
|
||||
/// icon_44_calendar (U+E626)
|
||||
static final IconData icon44Calendar = _icon(0xe626);
|
||||
|
||||
/// icon_32_student (U+E627)
|
||||
static final IconData icon32Student = _icon(0xe627);
|
||||
|
||||
/// icon_36_delete (U+E628)
|
||||
static final IconData icon36Delete = _icon(0xe628);
|
||||
|
||||
/// icon_44_more (U+E629)
|
||||
static final IconData icon44More = _icon(0xe629);
|
||||
|
||||
/// icon_44_arrow_left (U+E62A)
|
||||
static final IconData icon44ArrowLeft = _icon(0xe62a);
|
||||
|
||||
/// icon_36_edit_line (U+E62B)
|
||||
static final IconData icon36EditLine = _icon(0xe62b);
|
||||
|
||||
/// icon_44_arrow_right (U+E622)
|
||||
static final IconData icon44ArrowRight = _icon(0xe622);
|
||||
|
||||
/// icon_24_delete (U+E623)
|
||||
static final IconData icon24Delete = _icon(0xe623);
|
||||
|
||||
/// icon_56_msg_add (U+E624)
|
||||
static final IconData icon56MsgAdd = _icon(0xe624);
|
||||
|
||||
/// icon_56_msg_face (U+E625)
|
||||
static final IconData icon56MsgFace = _icon(0xe625);
|
||||
|
||||
/// icon_56_msg_voice (U+E616)
|
||||
static final IconData icon56MsgVoice = _icon(0xe616);
|
||||
|
||||
/// icon_44_share (U+E615)
|
||||
static final IconData icon44Share = _icon(0xe615);
|
||||
|
||||
/// icon_36_hint (U+E613)
|
||||
static final IconData icon36Hint = _icon(0xe613);
|
||||
|
||||
/// icon_24_add (U+E617)
|
||||
static final IconData icon24Add = _icon(0xe617);
|
||||
|
||||
/// icon_24_plus (U+E618)
|
||||
static final IconData icon24Plus = _icon(0xe618);
|
||||
|
||||
/// icon_44_keyboard (U+E614)
|
||||
static final IconData icon44Keyboard = _icon(0xe614);
|
||||
|
||||
/// icon_44_quit (U+E619)
|
||||
static final IconData icon44Quit = _icon(0xe619);
|
||||
|
||||
/// icon_44_add (U+E61A)
|
||||
static final IconData icon44Add = _icon(0xe61a);
|
||||
|
||||
/// icon_24_switch (U+E61B)
|
||||
static final IconData icon24Switch = _icon(0xe61b);
|
||||
|
||||
/// icon_44_arrow_down_line (U+E61C)
|
||||
static final IconData icon44ArrowDownLine = _icon(0xe61c);
|
||||
|
||||
/// icon_24_arrow_right (U+E61E)
|
||||
static final IconData icon24ArrowRight = _icon(0xe61e);
|
||||
|
||||
/// icon_32_add (U+E61F)
|
||||
static final IconData icon32Add = _icon(0xe61f);
|
||||
|
||||
/// icon_24_edit (U+E620)
|
||||
static final IconData icon24Edit = _icon(0xe620);
|
||||
|
||||
/// icon_24_arrow_down (U+E621)
|
||||
static final IconData icon24ArrowDown = _icon(0xe621);
|
||||
}
|
||||
|
||||
/// 内部 IconData 工厂类
|
||||
class _IconDataFactory {
|
||||
const _IconDataFactory._();
|
||||
|
||||
static const String _fontFamily = 'iconfont';
|
||||
|
||||
IconData call(int codePoint) => IconData(codePoint, fontFamily: _fontFamily);
|
||||
}
|
||||
|
|
@ -1,113 +1,112 @@
|
|||
import 'package:yx_icon_fonts/yx_icon_fonts.dart';
|
||||
import 'package:yx_icon_fonts_example/example_icon.dart';
|
||||
import 'package:yx_icon_fonts_example/generated/icons.dart';
|
||||
|
||||
// 此文件由脚本自动生成!
|
||||
// 此文件用于示例展示,使用生成的 AppIcons 类
|
||||
|
||||
final icons = <ExampleIcon>[
|
||||
// 其他图标
|
||||
ExampleIcon(YXIconFonts.icon32Clean, 'icon 32 clean'),
|
||||
ExampleIcon(YXIconFonts.icon36Viewhistory, 'icon 36 viewhistory'),
|
||||
ExampleIcon(YXIconFonts.icon36Revoke, 'icon 36 revoke'),
|
||||
ExampleIcon(YXIconFonts.icon32Location, 'icon 32 location'),
|
||||
ExampleIcon(YXIconFonts.icon24Mypoints, 'icon 24 mypoints'),
|
||||
ExampleIcon(YXIconFonts.icon44Search, 'icon 44 search'),
|
||||
ExampleIcon(YXIconFonts.icon36ClearPeople, 'icon 36 clear people'),
|
||||
ExampleIcon(YXIconFonts.icon32Publish, 'icon 32 publish'),
|
||||
ExampleIcon(YXIconFonts.icon32Close, 'icon 32 close'),
|
||||
ExampleIcon(YXIconFonts.icon32Output, 'icon 32 output'),
|
||||
ExampleIcon(YXIconFonts.icon24Download, 'icon 24 download'),
|
||||
ExampleIcon(YXIconFonts.iconVoicePause, 'icon voice pause'),
|
||||
ExampleIcon(YXIconFonts.iconVoice, 'icon voice'),
|
||||
ExampleIcon(YXIconFonts.iconSubtract, 'icon subtract'),
|
||||
ExampleIcon(YXIconFonts.icon44CancelAccount, 'icon 44 cancel account'),
|
||||
ExampleIcon(YXIconFonts.icon24Search, 'icon 24 search'),
|
||||
ExampleIcon(YXIconFonts.icon24Up, 'icon 24 up'),
|
||||
ExampleIcon(YXIconFonts.icon24Minus, 'icon 24 minus'),
|
||||
ExampleIcon(YXIconFonts.icon36OnlySee, 'icon 36 only see'),
|
||||
ExampleIcon(YXIconFonts.icon24Plus, 'icon 24 plus'),
|
||||
ExampleIcon(AppIcons.icon32Clean, 'icon 32 clean'),
|
||||
ExampleIcon(AppIcons.icon36Viewhistory, 'icon 36 viewhistory'),
|
||||
ExampleIcon(AppIcons.icon36Revoke, 'icon 36 revoke'),
|
||||
ExampleIcon(AppIcons.icon32Location, 'icon 32 location'),
|
||||
ExampleIcon(AppIcons.icon24Mypoints, 'icon 24 mypoints'),
|
||||
ExampleIcon(AppIcons.icon44Search, 'icon 44 search'),
|
||||
ExampleIcon(AppIcons.icon36ClearPeople, 'icon 36 clear people'),
|
||||
ExampleIcon(AppIcons.icon32Publish, 'icon 32 publish'),
|
||||
ExampleIcon(AppIcons.icon32Close, 'icon 32 close'),
|
||||
ExampleIcon(AppIcons.icon32Output, 'icon 32 output'),
|
||||
ExampleIcon(AppIcons.icon24Download, 'icon 24 download'),
|
||||
ExampleIcon(AppIcons.iconVoicePause, 'icon voice pause'),
|
||||
ExampleIcon(AppIcons.iconVoice, 'icon voice'),
|
||||
ExampleIcon(AppIcons.iconSubtract, 'icon subtract'),
|
||||
ExampleIcon(AppIcons.icon44CancelAccount, 'icon 44 cancel account'),
|
||||
ExampleIcon(AppIcons.icon24Search, 'icon 24 search'),
|
||||
ExampleIcon(AppIcons.icon24Up, 'icon 24 up'),
|
||||
ExampleIcon(AppIcons.icon24Minus, 'icon 24 minus'),
|
||||
ExampleIcon(AppIcons.icon36OnlySee, 'icon 36 only see'),
|
||||
ExampleIcon(AppIcons.icon24Plus, 'icon 24 plus'),
|
||||
|
||||
// 编辑相关图标
|
||||
ExampleIcon(YXIconFonts.icon30Edit, 'icon 30 edit'),
|
||||
ExampleIcon(YXIconFonts.icon44Edit, 'icon 44 edit'),
|
||||
ExampleIcon(YXIconFonts.icon36EditLine, 'icon 36 edit line'),
|
||||
ExampleIcon(YXIconFonts.icon24Edit, 'icon 24 edit'),
|
||||
ExampleIcon(AppIcons.icon30Edit, 'icon 30 edit'),
|
||||
ExampleIcon(AppIcons.icon44Edit, 'icon 44 edit'),
|
||||
ExampleIcon(AppIcons.icon36EditLine, 'icon 36 edit line'),
|
||||
ExampleIcon(AppIcons.icon24Edit, 'icon 24 edit'),
|
||||
|
||||
// 复制相关图标
|
||||
ExampleIcon(YXIconFonts.icon24Copy2, 'icon 24 copy2'),
|
||||
ExampleIcon(YXIconFonts.icon24Copy, 'icon 24 copy'),
|
||||
ExampleIcon(AppIcons.icon24Copy2, 'icon 24 copy2'),
|
||||
ExampleIcon(AppIcons.icon24Copy, 'icon 24 copy'),
|
||||
|
||||
// 删除相关图标
|
||||
ExampleIcon(YXIconFonts.icon30Delete, 'icon 30 delete'),
|
||||
ExampleIcon(YXIconFonts.icon44Delete, 'icon 44 delete'),
|
||||
ExampleIcon(YXIconFonts.icon36Delete, 'icon 36 delete'),
|
||||
ExampleIcon(YXIconFonts.icon24Delete, 'icon 24 delete'),
|
||||
ExampleIcon(AppIcons.icon30Delete, 'icon 30 delete'),
|
||||
ExampleIcon(AppIcons.icon44Delete, 'icon 44 delete'),
|
||||
ExampleIcon(AppIcons.icon36Delete, 'icon 36 delete'),
|
||||
ExampleIcon(AppIcons.icon24Delete, 'icon 24 delete'),
|
||||
|
||||
// 添加相关图标
|
||||
ExampleIcon(YXIconFonts.icon36Add, 'icon 36 add'),
|
||||
ExampleIcon(YXIconFonts.icon24Add, 'icon 24 add'),
|
||||
ExampleIcon(YXIconFonts.icon44Add, 'icon 44 add'),
|
||||
ExampleIcon(YXIconFonts.icon32Add, 'icon 32 add'),
|
||||
ExampleIcon(AppIcons.icon36Add, 'icon 36 add'),
|
||||
ExampleIcon(AppIcons.icon24Add, 'icon 24 add'),
|
||||
ExampleIcon(AppIcons.icon44Add, 'icon 44 add'),
|
||||
ExampleIcon(AppIcons.icon32Add, 'icon 32 add'),
|
||||
|
||||
// 个人中心相关图标
|
||||
ExampleIcon(YXIconFonts.icon44MeAbout, 'icon 44 me about'),
|
||||
ExampleIcon(YXIconFonts.icon44MePointsmall, 'icon 44 me pointsmall'),
|
||||
ExampleIcon(YXIconFonts.icon44MeLogOut, 'icon 44 me log out'),
|
||||
ExampleIcon(YXIconFonts.icon44MeSwitch, 'icon 44 me switch'),
|
||||
ExampleIcon(YXIconFonts.icon44MePassword, 'icon 44 me password'),
|
||||
ExampleIcon(YXIconFonts.icon44MeHelp, 'icon 44 me help'),
|
||||
ExampleIcon(YXIconFonts.icon44MeVersion, 'icon 44 me version'),
|
||||
ExampleIcon(YXIconFonts.icon44MePrivacy, 'icon 44 me privacy'),
|
||||
ExampleIcon(YXIconFonts.icon44MeUser, 'icon 44 me user'),
|
||||
ExampleIcon(YXIconFonts.icon44MeSafe, 'icon 44 me safe'),
|
||||
ExampleIcon(YXIconFonts.icon44MePhone, 'icon 44 me phone'),
|
||||
ExampleIcon(AppIcons.icon44MeAbout, 'icon 44 me about'),
|
||||
ExampleIcon(AppIcons.icon44MePointsmall, 'icon 44 me pointsmall'),
|
||||
ExampleIcon(AppIcons.icon44MeLogOut, 'icon 44 me log out'),
|
||||
ExampleIcon(AppIcons.icon44MeSwitch, 'icon 44 me switch'),
|
||||
ExampleIcon(AppIcons.icon44MePassword, 'icon 44 me password'),
|
||||
ExampleIcon(AppIcons.icon44MeHelp, 'icon 44 me help'),
|
||||
ExampleIcon(AppIcons.icon44MeVersion, 'icon 44 me version'),
|
||||
ExampleIcon(AppIcons.icon44MePrivacy, 'icon 44 me privacy'),
|
||||
ExampleIcon(AppIcons.icon44MeUser, 'icon 44 me user'),
|
||||
ExampleIcon(AppIcons.icon44MeSafe, 'icon 44 me safe'),
|
||||
ExampleIcon(AppIcons.icon44MePhone, 'icon 44 me phone'),
|
||||
|
||||
// 分享相关图标
|
||||
ExampleIcon(YXIconFonts.icon44WechatShareWhite, 'icon 44 wechat share white'),
|
||||
ExampleIcon(YXIconFonts.icon44Share, 'icon 44 share'),
|
||||
ExampleIcon(AppIcons.icon44WechatShareWhite, 'icon 44 wechat share white'),
|
||||
ExampleIcon(AppIcons.icon44Share, 'icon 44 share'),
|
||||
|
||||
// 消息相关图标
|
||||
ExampleIcon(YXIconFonts.iconMsgContacts, 'icon msg contacts'),
|
||||
ExampleIcon(YXIconFonts.iconMsgVideo, 'icon msg video'),
|
||||
ExampleIcon(YXIconFonts.iconMsgSearch, 'icon msg search'),
|
||||
ExampleIcon(YXIconFonts.iconMsgCall, 'icon msg call'),
|
||||
ExampleIcon(YXIconFonts.iconMsgPhoto, 'icon msg photo'),
|
||||
ExampleIcon(YXIconFonts.iconMsgImg, 'icon msg img'),
|
||||
ExampleIcon(YXIconFonts.iconMsgFile, 'icon msg file'),
|
||||
ExampleIcon(YXIconFonts.icon56MsgAdd, 'icon 56 msg add'),
|
||||
ExampleIcon(YXIconFonts.icon56MsgFace, 'icon 56 msg face'),
|
||||
ExampleIcon(YXIconFonts.icon56MsgVoice, 'icon 56 msg voice'),
|
||||
ExampleIcon(AppIcons.iconMsgContacts, 'icon msg contacts'),
|
||||
ExampleIcon(AppIcons.iconMsgVideo, 'icon msg video'),
|
||||
ExampleIcon(AppIcons.iconMsgSearch, 'icon msg search'),
|
||||
ExampleIcon(AppIcons.iconMsgCall, 'icon msg call'),
|
||||
ExampleIcon(AppIcons.iconMsgPhoto, 'icon msg photo'),
|
||||
ExampleIcon(AppIcons.iconMsgImg, 'icon msg img'),
|
||||
ExampleIcon(AppIcons.iconMsgFile, 'icon msg file'),
|
||||
ExampleIcon(AppIcons.icon56MsgAdd, 'icon 56 msg add'),
|
||||
ExampleIcon(AppIcons.icon56MsgFace, 'icon 56 msg face'),
|
||||
ExampleIcon(AppIcons.icon56MsgVoice, 'icon 56 msg voice'),
|
||||
|
||||
// 箭头相关图标
|
||||
ExampleIcon(YXIconFonts.icon32ArrowRight, 'icon 32 arrow right'),
|
||||
ExampleIcon(YXIconFonts.icon44ArrowLeft, 'icon 44 arrow left'),
|
||||
ExampleIcon(YXIconFonts.icon44ArrowRight, 'icon 44 arrow right'),
|
||||
ExampleIcon(YXIconFonts.icon44ArrowDownLine, 'icon 44 arrow down line'),
|
||||
ExampleIcon(YXIconFonts.icon24ArrowRight, 'icon 24 arrow right'),
|
||||
ExampleIcon(YXIconFonts.icon24ArrowDown, 'icon 24 arrow down'),
|
||||
ExampleIcon(AppIcons.icon32ArrowRight, 'icon 32 arrow right'),
|
||||
ExampleIcon(AppIcons.icon44ArrowLeft, 'icon 44 arrow left'),
|
||||
ExampleIcon(AppIcons.icon44ArrowRight, 'icon 44 arrow right'),
|
||||
ExampleIcon(AppIcons.icon44ArrowDownLine, 'icon 44 arrow down line'),
|
||||
ExampleIcon(AppIcons.icon24ArrowRight, 'icon 24 arrow right'),
|
||||
ExampleIcon(AppIcons.icon24ArrowDown, 'icon 24 arrow down'),
|
||||
|
||||
// 团队和用户相关图标
|
||||
ExampleIcon(YXIconFonts.icon36Team, 'icon 36 team'),
|
||||
ExampleIcon(YXIconFonts.icon32Student, 'icon 32 student'),
|
||||
ExampleIcon(AppIcons.icon36Team, 'icon 36 team'),
|
||||
ExampleIcon(AppIcons.icon32Student, 'icon 32 student'),
|
||||
|
||||
// 功能图标
|
||||
ExampleIcon(YXIconFonts.icon32Filter, 'icon 32 filter'),
|
||||
ExampleIcon(YXIconFonts.icon36Question, 'icon 36 question'),
|
||||
ExampleIcon(YXIconFonts.icon36Hint, 'icon 36 hint'),
|
||||
ExampleIcon(YXIconFonts.icon24Switch, 'icon 24 switch'),
|
||||
ExampleIcon(AppIcons.icon32Filter, 'icon 32 filter'),
|
||||
ExampleIcon(AppIcons.icon36Question, 'icon 36 question'),
|
||||
ExampleIcon(AppIcons.icon36Hint, 'icon 36 hint'),
|
||||
ExampleIcon(AppIcons.icon24Switch, 'icon 24 switch'),
|
||||
|
||||
// 退出相关图标
|
||||
ExampleIcon(YXIconFonts.icon44QuitLite, 'icon 44 quit lite'),
|
||||
ExampleIcon(YXIconFonts.icon32Quit, 'icon 32 quit'),
|
||||
ExampleIcon(YXIconFonts.icon44Quit, 'icon 44 quit'),
|
||||
ExampleIcon(AppIcons.icon44QuitLite, 'icon 44 quit lite'),
|
||||
ExampleIcon(AppIcons.icon32Quit, 'icon 32 quit'),
|
||||
ExampleIcon(AppIcons.icon44Quit, 'icon 44 quit'),
|
||||
|
||||
// 更多和菜单相关图标
|
||||
ExampleIcon(YXIconFonts.icon44More2, 'icon 44 more2'),
|
||||
ExampleIcon(YXIconFonts.icon44More, 'icon 44 more'),
|
||||
ExampleIcon(AppIcons.icon44More2, 'icon 44 more2'),
|
||||
ExampleIcon(AppIcons.icon44More, 'icon 44 more'),
|
||||
|
||||
// 日历相关图标
|
||||
ExampleIcon(YXIconFonts.icon44Calendar, 'icon 44 calendar'),
|
||||
ExampleIcon(AppIcons.icon44Calendar, 'icon 44 calendar'),
|
||||
|
||||
// 键盘相关图标
|
||||
ExampleIcon(YXIconFonts.icon44Keyboard, 'icon 44 keyboard'),
|
||||
|
||||
ExampleIcon(AppIcons.icon44Keyboard, 'icon 44 keyboard'),
|
||||
];
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:yx_icon_fonts/yx_icon_fonts.dart';
|
||||
import 'package:yx_icon_fonts_example/icons.dart';
|
||||
|
||||
void main() {
|
||||
|
|
@ -35,12 +34,18 @@ class YXIconFontsGalleryHome extends StatefulWidget {
|
|||
}
|
||||
|
||||
class _YXIconFontsGalleryHomeState extends State<YXIconFontsGalleryHome> {
|
||||
var _searchTerm = "";
|
||||
var _searchTerm = '';
|
||||
var _isSearching = false;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final filteredIcons = icons.where((icon) => _searchTerm.isEmpty || icon.title.toLowerCase().contains(_searchTerm.toLowerCase())).toList();
|
||||
final filteredIcons = icons
|
||||
.where(
|
||||
(icon) =>
|
||||
_searchTerm.isEmpty ||
|
||||
icon.title.toLowerCase().contains(_searchTerm.toLowerCase()),
|
||||
)
|
||||
.toList();
|
||||
|
||||
return Scaffold(
|
||||
appBar: _isSearching ? _searchBar(context) : _titleBar(),
|
||||
|
|
@ -69,7 +74,7 @@ class _YXIconFontsGalleryHomeState extends State<YXIconFontsGalleryHome> {
|
|||
alignment: Alignment.center,
|
||||
child: Hero(
|
||||
tag: icon,
|
||||
child: YXIcon(
|
||||
child: Icon(
|
||||
icon.iconData,
|
||||
size: 100,
|
||||
),
|
||||
|
|
@ -83,7 +88,7 @@ class _YXIconFontsGalleryHomeState extends State<YXIconFontsGalleryHome> {
|
|||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Hero(tag: icon, child: YXIcon(icon.iconData)),
|
||||
Hero(tag: icon, child: Icon(icon.iconData)),
|
||||
Container(
|
||||
padding: const EdgeInsets.only(top: 16.0),
|
||||
child: Text(
|
||||
|
|
@ -92,7 +97,7 @@ class _YXIconFontsGalleryHomeState extends State<YXIconFontsGalleryHome> {
|
|||
color: Colors.black,
|
||||
),
|
||||
),
|
||||
)
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
|
@ -103,7 +108,7 @@ class _YXIconFontsGalleryHomeState extends State<YXIconFontsGalleryHome> {
|
|||
onPressed: () {
|
||||
setState(() {
|
||||
_isSearching = !_isSearching;
|
||||
if (!_isSearching) _searchTerm = "";
|
||||
if (!_isSearching) _searchTerm = '';
|
||||
});
|
||||
},
|
||||
child: Icon(_isSearching ? Icons.close : Icons.search),
|
||||
|
|
@ -133,7 +138,7 @@ class _YXIconFontsGalleryHomeState extends State<YXIconFontsGalleryHome> {
|
|||
onPressed: () {
|
||||
setState(() {
|
||||
_isSearching = false;
|
||||
_searchTerm = "";
|
||||
_searchTerm = '';
|
||||
});
|
||||
},
|
||||
),
|
||||
|
|
|
|||
|
|
@ -99,6 +99,14 @@ packages:
|
|||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "3.0.0"
|
||||
logging:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: logging
|
||||
sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.3.0"
|
||||
matcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -200,13 +208,21 @@ packages:
|
|||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "15.0.2"
|
||||
yaml:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: yaml
|
||||
sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "3.1.3"
|
||||
yx_icon_fonts:
|
||||
dependency: "direct main"
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
path: ".."
|
||||
relative: true
|
||||
source: path
|
||||
version: "1.0.5"
|
||||
version: "2.0.0"
|
||||
sdks:
|
||||
dart: ">=3.8.0-0 <4.0.0"
|
||||
flutter: ">=3.18.0-18.0.pre.54"
|
||||
|
|
|
|||
|
|
@ -10,13 +10,20 @@ environment:
|
|||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
|
||||
dev_dependencies:
|
||||
flutter_lints: ^3.0.0
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
# CLI 代码生成工具
|
||||
yx_icon_fonts:
|
||||
path: ../
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
flutter_lints: ^3.0.0
|
||||
|
||||
flutter:
|
||||
uses-material-design: true
|
||||
|
||||
# 字体配置
|
||||
fonts:
|
||||
- family: iconfont
|
||||
fonts:
|
||||
- asset: assets/fonts/iconfont.ttf
|
||||
158
generate.sh
158
generate.sh
|
|
@ -1,158 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
# YX Icon Fonts 生成脚本
|
||||
# 用于生成图标数据和示例文件
|
||||
|
||||
set -e # 遇到错误时退出
|
||||
|
||||
# 颜色定义
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# 打印带颜色的消息
|
||||
print_info() {
|
||||
echo -e "${BLUE}ℹ️ $1${NC}"
|
||||
}
|
||||
|
||||
print_success() {
|
||||
echo -e "${GREEN}✅ $1${NC}"
|
||||
}
|
||||
|
||||
print_warning() {
|
||||
echo -e "${YELLOW}⚠️ $1${NC}"
|
||||
}
|
||||
|
||||
print_error() {
|
||||
echo -e "${RED}❌ $1${NC}"
|
||||
}
|
||||
|
||||
# 检查 Dart 是否安装
|
||||
check_dart() {
|
||||
if ! command -v dart &> /dev/null; then
|
||||
print_error "Dart 未安装或不在 PATH 中"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# 检查必要文件是否存在
|
||||
check_files() {
|
||||
if [ ! -f "iconfont.json" ]; then
|
||||
print_error "找不到 iconfont.json 文件"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "scripts/generate_icons.dart" ]; then
|
||||
print_error "找不到 scripts/generate_icons.dart 文件"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "scripts/generate_example.dart" ]; then
|
||||
print_error "找不到 scripts/generate_example.dart 文件"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "scripts/generate_wrapper.dart" ]; then
|
||||
print_error "找不到 scripts/generate_wrapper.dart 文件"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# 生成图标数据
|
||||
generate_icons() {
|
||||
print_info "正在生成图标数据..."
|
||||
dart scripts/generate_icons.dart
|
||||
print_success "图标数据生成完成"
|
||||
}
|
||||
|
||||
# 生成示例文件
|
||||
generate_example() {
|
||||
print_info "正在生成示例文件..."
|
||||
dart scripts/generate_example.dart
|
||||
print_success "示例文件生成完成"
|
||||
}
|
||||
|
||||
# 生成外部封装文件
|
||||
generate_wrapper() {
|
||||
print_info "正在生成外部封装文件..."
|
||||
dart scripts/generate_wrapper.dart
|
||||
print_success "外部封装文件生成完成"
|
||||
}
|
||||
|
||||
# 生成所有文件
|
||||
generate_all() {
|
||||
print_info "开始生成所有文件..."
|
||||
echo
|
||||
|
||||
generate_icons
|
||||
echo
|
||||
generate_wrapper
|
||||
echo
|
||||
generate_example
|
||||
echo
|
||||
|
||||
print_success "所有文件生成完成!"
|
||||
}
|
||||
|
||||
# 显示帮助信息
|
||||
show_help() {
|
||||
echo "YX Icon Fonts 生成脚本"
|
||||
echo
|
||||
echo "用法: $0 [选项]"
|
||||
echo
|
||||
echo "选项:"
|
||||
echo " icons 只生成图标数据 (lib/src/yx_icon_fonts_data.dart)"
|
||||
echo " wrapper 只生成外部封装文件 (generate/icons.dart)"
|
||||
echo " example 只生成示例文件 (example/lib/icons.dart)"
|
||||
echo " all 生成所有文件 (默认)"
|
||||
echo " help 显示此帮助信息"
|
||||
echo
|
||||
echo "示例:"
|
||||
echo " $0 # 生成所有文件"
|
||||
echo " $0 icons # 只生成图标数据"
|
||||
echo " $0 wrapper # 只生成外部封装文件"
|
||||
echo " $0 example # 只生成示例文件"
|
||||
echo
|
||||
}
|
||||
|
||||
# 主函数
|
||||
main() {
|
||||
local action=${1:-all}
|
||||
|
||||
case $action in
|
||||
"icons")
|
||||
check_dart
|
||||
check_files
|
||||
generate_icons
|
||||
;;
|
||||
"wrapper")
|
||||
check_dart
|
||||
check_files
|
||||
generate_wrapper
|
||||
;;
|
||||
"example")
|
||||
check_dart
|
||||
check_files
|
||||
generate_example
|
||||
;;
|
||||
"all")
|
||||
check_dart
|
||||
check_files
|
||||
generate_all
|
||||
;;
|
||||
"help"|"-h"|"--help")
|
||||
show_help
|
||||
;;
|
||||
*)
|
||||
print_error "未知选项: $action"
|
||||
echo
|
||||
show_help
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# 运行主函数
|
||||
main "$@"
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
# 图标字体生成器配置文件模板
|
||||
# 复制此文件到您的项目根目录,重命名为 icon_generator_config.yaml
|
||||
# 并根据需要修改配置
|
||||
|
||||
# 生成器信息
|
||||
generator:
|
||||
# 项目名称(用于生成的代码注释)
|
||||
name: "MyApp Icons"
|
||||
# 版本
|
||||
version: "1.0"
|
||||
# 作者
|
||||
author: "Your Name"
|
||||
|
||||
# 输入配置
|
||||
input:
|
||||
# 字体文件路径(相对于项目根目录)
|
||||
# 这个文件从 iconfont.cn 下载
|
||||
font_file: "assets/fonts/iconfont.ttf"
|
||||
|
||||
# JSON 配置文件路径(从 iconfont.cn 下载)
|
||||
# 包含所有图标的 unicode 编码和名称
|
||||
json_file: "assets/fonts/iconfont.json"
|
||||
|
||||
# 字体家族名称
|
||||
# 需要与 pubspec.yaml 中 flutter.fonts 配置的 family 一致
|
||||
# 例如:
|
||||
# flutter:
|
||||
# fonts:
|
||||
# - family: iconfont
|
||||
# fonts:
|
||||
# - asset: assets/fonts/iconfont.ttf
|
||||
font_family: "iconfont"
|
||||
|
||||
# 字体包名(可选)
|
||||
# 如果字体文件位于另一个 package 中,请指定包名
|
||||
# font_package: "my_icons_package"
|
||||
|
||||
# 输出配置
|
||||
output:
|
||||
# 生成的 Dart 文件路径
|
||||
# 建议放在 lib/generated/ 目录下,并添加到 .gitignore
|
||||
file_path: "lib/generated/icons.dart"
|
||||
|
||||
# 生成的类名
|
||||
# 使用时: Icon(AppIcons.iconName, size: 24)
|
||||
class_name: "AppIcons"
|
||||
|
||||
# 是否生成文档注释
|
||||
# 设为 true 会为每个图标生成 Unicode 说明
|
||||
generate_docs: true
|
||||
|
||||
# 是否使用 const 构造函数
|
||||
use_const_constructor: true
|
||||
|
||||
# 包导入路径(可选)
|
||||
# 如果需要在生成的文件中添加特定的 package 导入
|
||||
# package_import: "package:my_app/common/icons.dart"
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
void main() {
|
||||
runApp(const MainApp());
|
||||
}
|
||||
|
||||
class MainApp extends StatelessWidget {
|
||||
const MainApp({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return const MaterialApp(
|
||||
home: Scaffold(
|
||||
body: Center(
|
||||
child: Text('Hello World!'),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,172 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:yx_icon_fonts/src/commands/base_command.dart';
|
||||
import 'package:yx_icon_fonts/src/commands/generate_command.dart';
|
||||
import 'package:yx_icon_fonts/src/commands/init_command.dart';
|
||||
import 'package:yx_icon_fonts/src/utils/string_helper.dart';
|
||||
|
||||
/// YX Icon Fonts CLI 应用程序
|
||||
///
|
||||
/// 使用命令模式架构的 CLI 工具
|
||||
class IconFontsCLI {
|
||||
IconFontsCLI() {
|
||||
_registerCommands();
|
||||
}
|
||||
|
||||
static final Logger _logger = Logger('IconFontsCLI');
|
||||
final Map<String, BaseCommand> _commands = {};
|
||||
|
||||
/// 注册所有命令
|
||||
void _registerCommands() {
|
||||
_registerCommand(GenerateCommand());
|
||||
_registerCommand(InitCommand());
|
||||
}
|
||||
|
||||
/// 注册单个命令
|
||||
void _registerCommand(BaseCommand command) {
|
||||
_commands[command.name] = command;
|
||||
}
|
||||
|
||||
/// 运行 CLI 应用程序
|
||||
Future<int> run(List<String> arguments) async {
|
||||
try {
|
||||
_showBanner();
|
||||
|
||||
if (arguments.isEmpty ||
|
||||
arguments.first == 'help' ||
|
||||
arguments.first == '--help') {
|
||||
_showHelp();
|
||||
return 0;
|
||||
}
|
||||
|
||||
final commandName = arguments.first;
|
||||
final commandArgs =
|
||||
arguments.length > 1 ? arguments.sublist(1) : <String>[];
|
||||
|
||||
// 检查特殊命令
|
||||
if (commandName == 'version' || commandName == '--version') {
|
||||
_showVersion();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 查找并执行命令
|
||||
final command = _commands[commandName];
|
||||
if (command == null) {
|
||||
_logger
|
||||
..severe('❌ 未知命令: $commandName')
|
||||
..info('');
|
||||
_showAvailableCommands();
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 检查命令帮助
|
||||
if (commandArgs.contains('--help') || commandArgs.contains('-h')) {
|
||||
command.showHelp();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 执行命令
|
||||
final stopwatch = Stopwatch()..start();
|
||||
final exitCode = await command.execute(commandArgs);
|
||||
stopwatch.stop();
|
||||
|
||||
// 显示执行时间
|
||||
if (exitCode == 0) {
|
||||
_logger
|
||||
..info('')
|
||||
..info(
|
||||
'⏱️ 总耗时: ${StringHelper.formatDuration(stopwatch.elapsed)}',
|
||||
);
|
||||
}
|
||||
|
||||
return exitCode;
|
||||
} on Exception catch (error, stackTrace) {
|
||||
_logger
|
||||
..severe('❌ 应用程序错误: $error')
|
||||
..severe('堆栈跟踪: $stackTrace');
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/// 显示应用程序横幅
|
||||
void _showBanner() {
|
||||
_logger
|
||||
..info('')
|
||||
..info('🎨 YX Icon Fonts 代码生成器 v2.0')
|
||||
..info('=====================================')
|
||||
..info('从 iconfont.json 生成 Flutter IconData 常量')
|
||||
..info('');
|
||||
}
|
||||
|
||||
/// 显示帮助信息
|
||||
void _showHelp() {
|
||||
_logger
|
||||
..info('用法: dart run yx_icon_fonts <命令> [选项]')
|
||||
..info('')
|
||||
..info('支持 YAML 配置文件,可自定义输出路径和类名。')
|
||||
..info('');
|
||||
_showAvailableCommands();
|
||||
_showGlobalOptions();
|
||||
_showExamples();
|
||||
}
|
||||
|
||||
/// 显示可用命令
|
||||
void _showAvailableCommands() {
|
||||
_logger
|
||||
..info('📋 可用命令:')
|
||||
..info('');
|
||||
|
||||
for (final command in _commands.values) {
|
||||
_logger.info(' ${command.name.padRight(12)} ${command.description}');
|
||||
}
|
||||
|
||||
_logger
|
||||
..info(' help 显示帮助信息')
|
||||
..info(' version 显示版本信息')
|
||||
..info('');
|
||||
}
|
||||
|
||||
/// 显示全局选项
|
||||
void _showGlobalOptions() {
|
||||
_logger
|
||||
..info('🔧 全局选项:')
|
||||
..info(' -h, --help 显示帮助信息')
|
||||
..info(' --version 显示版本信息')
|
||||
..info('');
|
||||
}
|
||||
|
||||
/// 显示使用示例
|
||||
void _showExamples() {
|
||||
_logger
|
||||
..info('💡 使用示例:')
|
||||
..info('')
|
||||
..info(' # 初始化配置文件')
|
||||
..info(' dart run yx_icon_fonts init')
|
||||
..info('')
|
||||
..info(' # 生成图标代码')
|
||||
..info(' dart run yx_icon_fonts generate')
|
||||
..info('')
|
||||
..info(' # 使用指定配置文件')
|
||||
..info(' dart run yx_icon_fonts generate --config my_config.yaml')
|
||||
..info('')
|
||||
..info(' # 查看命令帮助')
|
||||
..info(' dart run yx_icon_fonts generate --help')
|
||||
..info('');
|
||||
}
|
||||
|
||||
/// 显示版本信息
|
||||
void _showVersion() {
|
||||
_logger
|
||||
..info('YX Icon Fonts CLI v2.0.0')
|
||||
..info('构建于: ${DateTime.now().toIso8601String()}')
|
||||
..info('Dart SDK: ${Platform.version}')
|
||||
..info('')
|
||||
..info('功能特性:')
|
||||
..info('- 🎨 从 iconfont.json 生成代码')
|
||||
..info('- 📝 YAML 配置文件支持')
|
||||
..info('- 🏗️ 自定义类名和输出路径')
|
||||
..info('- 📚 自动生成文档注释')
|
||||
..info('');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
import 'package:logging/logging.dart';
|
||||
|
||||
/// 命令基类
|
||||
///
|
||||
/// 所有 CLI 命令都应继承此类
|
||||
abstract class BaseCommand {
|
||||
/// 命令名称
|
||||
String get name;
|
||||
|
||||
/// 命令描述
|
||||
String get description;
|
||||
|
||||
/// 日志器
|
||||
Logger get logger => Logger(name);
|
||||
|
||||
/// 执行命令
|
||||
///
|
||||
/// 返回退出码:0 表示成功,非 0 表示失败
|
||||
Future<int> execute(List<String> arguments);
|
||||
|
||||
/// 显示帮助信息
|
||||
void showHelp() {
|
||||
logger
|
||||
..info('命令: $name')
|
||||
..info('描述: $description')
|
||||
..info('')
|
||||
..info('用法: dart run yx_icon_fonts $name [选项]')
|
||||
..info('')
|
||||
..info('选项:');
|
||||
showOptions();
|
||||
}
|
||||
|
||||
/// 显示命令选项
|
||||
void showOptions() {
|
||||
logger.info(' -h, --help 显示帮助信息');
|
||||
}
|
||||
|
||||
/// 解析参数中的选项值
|
||||
String? getOption(List<String> arguments, String name, {String? shortName}) {
|
||||
for (var i = 0; i < arguments.length; i++) {
|
||||
final arg = arguments[i];
|
||||
if (arg == '--$name' || (shortName != null && arg == '-$shortName')) {
|
||||
if (i + 1 < arguments.length) {
|
||||
return arguments[i + 1];
|
||||
}
|
||||
}
|
||||
if (arg.startsWith('--$name=')) {
|
||||
return arg.substring('--$name='.length);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// 检查参数中是否有指定标志
|
||||
bool hasFlag(List<String> arguments, String name, {String? shortName}) {
|
||||
for (final arg in arguments) {
|
||||
if (arg == '--$name' || (shortName != null && arg == '-$shortName')) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
import 'package:yx_icon_fonts/src/commands/base_command.dart';
|
||||
import 'package:yx_icon_fonts/src/config/config_loader.dart';
|
||||
import 'package:yx_icon_fonts/src/generator/icon_generator.dart';
|
||||
import 'package:yx_icon_fonts/src/utils/logger.dart';
|
||||
import 'package:yx_icon_fonts/src/utils/string_helper.dart';
|
||||
|
||||
/// 生成命令
|
||||
///
|
||||
/// 从配置文件读取配置,生成图标常量代码
|
||||
class GenerateCommand extends BaseCommand {
|
||||
@override
|
||||
String get name => 'generate';
|
||||
|
||||
@override
|
||||
String get description => '从 iconfont.json 生成 Flutter IconData 常量';
|
||||
|
||||
@override
|
||||
void showOptions() {
|
||||
super.showOptions();
|
||||
logger
|
||||
..info(' -c, --config <path> 指定配置文件路径 '
|
||||
'(默认: icon_generator_config.yaml)')
|
||||
..info(' -v, --verbose 显示详细输出');
|
||||
}
|
||||
|
||||
@override
|
||||
Future<int> execute(List<String> arguments) async {
|
||||
try {
|
||||
// 解析参数
|
||||
final configPath = getOption(arguments, 'config', shortName: 'c');
|
||||
final verbose = hasFlag(arguments, 'verbose', shortName: 'v');
|
||||
|
||||
if (verbose) {
|
||||
appLogger.info('🔍 详细模式已启用');
|
||||
}
|
||||
|
||||
// 加载配置
|
||||
appLogger.progress('正在加载配置...');
|
||||
final config = ConfigLoader.load(configPath: configPath);
|
||||
|
||||
if (verbose) {
|
||||
appLogger
|
||||
..info('📋 配置信息:')
|
||||
..info(' - 输入文件: ${config.input.jsonFile}')
|
||||
..info(' - 字体家族: ${config.input.fontFamily}')
|
||||
..info(' - 输出文件: ${config.output.filePath}')
|
||||
..info(' - 类名: ${config.output.className}');
|
||||
}
|
||||
|
||||
// 执行生成
|
||||
final generator = IconGenerator(config: config);
|
||||
final result = await generator.generate();
|
||||
|
||||
if (result.success) {
|
||||
appLogger
|
||||
..success('代码生成成功!')
|
||||
..info('')
|
||||
..info('📁 输出文件: ${result.outputPath}')
|
||||
..stats('共生成 ${result.iconCount} 个图标常量');
|
||||
|
||||
if (result.duration != null) {
|
||||
appLogger.info(
|
||||
'⏱️ 耗时: ${StringHelper.formatDuration(result.duration!)}',
|
||||
);
|
||||
}
|
||||
|
||||
return 0;
|
||||
} else {
|
||||
appLogger.severe('❌ 生成失败: ${result.error}');
|
||||
return 1;
|
||||
}
|
||||
} on ConfigNotFoundException catch (e) {
|
||||
appLogger
|
||||
..severe('❌ ${e.message}')
|
||||
..info('')
|
||||
..info('💡 提示: 运行 "dart run yx_icon_fonts init" 创建配置文件');
|
||||
return 1;
|
||||
} on Exception catch (e) {
|
||||
appLogger.severe('❌ 发生错误: $e');
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:path/path.dart' as path;
|
||||
import 'package:yx_icon_fonts/src/commands/base_command.dart';
|
||||
import 'package:yx_icon_fonts/src/config/config_loader.dart';
|
||||
import 'package:yx_icon_fonts/src/utils/logger.dart';
|
||||
|
||||
/// 初始化命令
|
||||
///
|
||||
/// 在当前目录创建配置文件模板
|
||||
class InitCommand extends BaseCommand {
|
||||
@override
|
||||
String get name => 'init';
|
||||
|
||||
@override
|
||||
String get description => '创建配置文件模板';
|
||||
|
||||
@override
|
||||
void showOptions() {
|
||||
super.showOptions();
|
||||
logger
|
||||
..info(' -f, --force 强制覆盖已存在的配置文件')
|
||||
..info(' -o, --output <path> 指定配置文件输出路径');
|
||||
}
|
||||
|
||||
@override
|
||||
Future<int> execute(List<String> arguments) async {
|
||||
try {
|
||||
final force = hasFlag(arguments, 'force', shortName: 'f');
|
||||
final outputPath = getOption(arguments, 'output', shortName: 'o');
|
||||
|
||||
final configPath = outputPath ??
|
||||
path.join(
|
||||
Directory.current.path,
|
||||
ConfigLoader.defaultConfigFileName,
|
||||
);
|
||||
|
||||
// 检查文件是否已存在
|
||||
if (File(configPath).existsSync() && !force) {
|
||||
appLogger
|
||||
..warning('⚠️ 配置文件已存在: $configPath')
|
||||
..info('')
|
||||
..info('💡 使用 --force 选项覆盖现有文件');
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 写入配置模板
|
||||
appLogger.progress('正在创建配置文件...');
|
||||
File(configPath).writeAsStringSync(_configTemplate);
|
||||
|
||||
appLogger
|
||||
..success('配置文件创建成功!')
|
||||
..info('')
|
||||
..info('📁 配置文件: $configPath')
|
||||
..info('')
|
||||
..info('📝 下一步:')
|
||||
..info(' 1. 编辑配置文件,设置输入输出路径')
|
||||
..info(' 2. 运行 "dart run yx_icon_fonts generate" 生成代码');
|
||||
|
||||
return 0;
|
||||
} on Exception catch (e) {
|
||||
appLogger.severe('❌ 发生错误: $e');
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/// 配置文件模板
|
||||
static const String _configTemplate = '''
|
||||
# 图标字体生成器配置文件
|
||||
# 由 yx_icon_fonts init 命令生成
|
||||
|
||||
# 生成器信息
|
||||
generator:
|
||||
name: "MyApp Icons"
|
||||
version: "1.0"
|
||||
author: "Your Name"
|
||||
|
||||
# 输入配置
|
||||
input:
|
||||
# 字体文件路径(相对于项目根目录)
|
||||
font_file: "assets/fonts/iconfont.ttf"
|
||||
|
||||
# JSON 配置文件路径(从 iconfont.cn 下载)
|
||||
json_file: "assets/fonts/iconfont.json"
|
||||
|
||||
# 字体家族名称(与 pubspec.yaml 中配置的一致)
|
||||
font_family: "iconfont"
|
||||
|
||||
# 字体包名(可选)
|
||||
# 如果字体文件位于另一个 package 中,请指定包名
|
||||
# font_package: "my_icons_package"
|
||||
|
||||
# 输出配置
|
||||
output:
|
||||
# 生成的 Dart 文件路径
|
||||
file_path: "lib/generated/icons.dart"
|
||||
|
||||
# 生成的类名
|
||||
class_name: "AppIcons"
|
||||
|
||||
# 是否生成文档注释
|
||||
generate_docs: true
|
||||
|
||||
# 是否使用 const 构造函数
|
||||
use_const_constructor: true
|
||||
''';
|
||||
}
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:path/path.dart' as path;
|
||||
import 'package:yaml/yaml.dart';
|
||||
import 'package:yx_icon_fonts/src/config/generator_config.dart';
|
||||
|
||||
/// 配置加载器
|
||||
///
|
||||
/// 负责从 YAML 文件加载配置
|
||||
class ConfigLoader {
|
||||
/// 默认配置文件名
|
||||
static const String defaultConfigFileName = 'icon_generator_config.yaml';
|
||||
|
||||
/// 加载配置文件
|
||||
///
|
||||
/// [configPath] 配置文件路径,如果为 null 则使用默认路径
|
||||
/// [workingDir] 工作目录,默认为当前目录
|
||||
static GeneratorConfig load({
|
||||
String? configPath,
|
||||
String? workingDir,
|
||||
}) {
|
||||
final directory = workingDir ?? Directory.current.path;
|
||||
final filePath = configPath ?? path.join(directory, defaultConfigFileName);
|
||||
final file = File(filePath);
|
||||
|
||||
if (!file.existsSync()) {
|
||||
throw ConfigNotFoundException(
|
||||
'配置文件不存在: $filePath\n'
|
||||
'请运行 "dart run yx_icon_fonts init" 创建配置文件',
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
final content = file.readAsStringSync();
|
||||
final yamlMap = loadYaml(content) as YamlMap?;
|
||||
|
||||
if (yamlMap == null) {
|
||||
throw ConfigParseException('配置文件为空或格式错误');
|
||||
}
|
||||
|
||||
// 将 YamlMap 转换为 Map<String, dynamic>
|
||||
final map = _convertYamlMap(yamlMap);
|
||||
return GeneratorConfig.fromMap(map);
|
||||
} on YamlException catch (e) {
|
||||
throw ConfigParseException('YAML 解析错误: ${e.message}');
|
||||
}
|
||||
}
|
||||
|
||||
/// 检查配置文件是否存在
|
||||
static bool exists({String? configPath, String? workingDir}) {
|
||||
final directory = workingDir ?? Directory.current.path;
|
||||
final filePath = configPath ?? path.join(directory, defaultConfigFileName);
|
||||
return File(filePath).existsSync();
|
||||
}
|
||||
|
||||
/// 将 YamlMap 递归转换为 Map<String, dynamic>
|
||||
static Map<String, dynamic> _convertYamlMap(YamlMap yamlMap) {
|
||||
final result = <String, dynamic>{};
|
||||
for (final key in yamlMap.keys) {
|
||||
final value = yamlMap[key];
|
||||
if (value is YamlMap) {
|
||||
result[key.toString()] = _convertYamlMap(value);
|
||||
} else if (value is YamlList) {
|
||||
result[key.toString()] = _convertYamlList(value);
|
||||
} else {
|
||||
result[key.toString()] = value;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// 将 YamlList 递归转换为 List<dynamic>
|
||||
static List<dynamic> _convertYamlList(YamlList yamlList) {
|
||||
return yamlList.map((item) {
|
||||
if (item is YamlMap) {
|
||||
return _convertYamlMap(item);
|
||||
} else if (item is YamlList) {
|
||||
return _convertYamlList(item);
|
||||
}
|
||||
return item;
|
||||
}).toList();
|
||||
}
|
||||
}
|
||||
|
||||
/// 配置文件未找到异常
|
||||
class ConfigNotFoundException implements Exception {
|
||||
ConfigNotFoundException(this.message);
|
||||
|
||||
final String message;
|
||||
|
||||
@override
|
||||
String toString() => 'ConfigNotFoundException: $message';
|
||||
}
|
||||
|
||||
/// 配置解析异常
|
||||
class ConfigParseException implements Exception {
|
||||
ConfigParseException(this.message);
|
||||
|
||||
final String message;
|
||||
|
||||
@override
|
||||
String toString() => 'ConfigParseException: $message';
|
||||
}
|
||||
|
|
@ -0,0 +1,178 @@
|
|||
// 配置模型类
|
||||
//
|
||||
// 定义图标生成器的配置结构
|
||||
|
||||
/// 总配置类
|
||||
class GeneratorConfig {
|
||||
const GeneratorConfig({
|
||||
required this.generator,
|
||||
required this.input,
|
||||
required this.output,
|
||||
});
|
||||
|
||||
/// 从 Map 创建配置
|
||||
factory GeneratorConfig.fromMap(Map<String, dynamic> map) {
|
||||
return GeneratorConfig(
|
||||
generator: GeneratorInfo.fromMap(
|
||||
map['generator'] as Map<String, dynamic>? ?? {},
|
||||
),
|
||||
input: InputConfig.fromMap(
|
||||
map['input'] as Map<String, dynamic>? ?? {},
|
||||
),
|
||||
output: OutputConfig.fromMap(
|
||||
map['output'] as Map<String, dynamic>? ?? {},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// 创建默认配置
|
||||
factory GeneratorConfig.defaults() {
|
||||
return GeneratorConfig(
|
||||
generator: GeneratorInfo.defaults(),
|
||||
input: InputConfig.defaults(),
|
||||
output: OutputConfig.defaults(),
|
||||
);
|
||||
}
|
||||
|
||||
/// 生成器信息
|
||||
final GeneratorInfo generator;
|
||||
|
||||
/// 输入配置
|
||||
final InputConfig input;
|
||||
|
||||
/// 输出配置
|
||||
final OutputConfig output;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'GeneratorConfig(generator: $generator, input: $input, '
|
||||
'output: $output)';
|
||||
}
|
||||
}
|
||||
|
||||
/// 生成器信息
|
||||
class GeneratorInfo {
|
||||
const GeneratorInfo({
|
||||
required this.name,
|
||||
this.version = '1.0',
|
||||
this.author = '',
|
||||
});
|
||||
|
||||
factory GeneratorInfo.fromMap(Map<String, dynamic> map) {
|
||||
return GeneratorInfo(
|
||||
name: map['name'] as String? ?? 'Icon Generator',
|
||||
version: map['version'] as String? ?? '1.0',
|
||||
author: map['author'] as String? ?? '',
|
||||
);
|
||||
}
|
||||
|
||||
factory GeneratorInfo.defaults() {
|
||||
return const GeneratorInfo(name: 'Icon Generator');
|
||||
}
|
||||
|
||||
/// 生成器名称
|
||||
final String name;
|
||||
|
||||
/// 版本
|
||||
final String version;
|
||||
|
||||
/// 作者
|
||||
final String author;
|
||||
|
||||
@override
|
||||
String toString() => 'GeneratorInfo(name: $name, version: $version)';
|
||||
}
|
||||
|
||||
/// 输入配置
|
||||
class InputConfig {
|
||||
const InputConfig({
|
||||
required this.fontFile,
|
||||
required this.jsonFile,
|
||||
required this.fontFamily,
|
||||
this.fontPackage,
|
||||
});
|
||||
|
||||
factory InputConfig.fromMap(Map<String, dynamic> map) {
|
||||
return InputConfig(
|
||||
fontFile: map['font_file'] as String? ?? 'assets/fonts/iconfont.ttf',
|
||||
jsonFile: map['json_file'] as String? ?? 'assets/fonts/iconfont.json',
|
||||
fontFamily: map['font_family'] as String? ?? 'iconfont',
|
||||
fontPackage: map['font_package'] as String?,
|
||||
);
|
||||
}
|
||||
|
||||
factory InputConfig.defaults() {
|
||||
return const InputConfig(
|
||||
fontFile: 'assets/fonts/iconfont.ttf',
|
||||
jsonFile: 'assets/fonts/iconfont.json',
|
||||
fontFamily: 'iconfont',
|
||||
);
|
||||
}
|
||||
|
||||
/// 字体文件路径(相对于项目根目录)
|
||||
final String fontFile;
|
||||
|
||||
/// JSON 配置文件路径
|
||||
final String jsonFile;
|
||||
|
||||
/// 字体家族名称
|
||||
final String fontFamily;
|
||||
|
||||
/// 字体包名
|
||||
final String? fontPackage;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'InputConfig(fontFile: $fontFile, jsonFile: $jsonFile, '
|
||||
'fontFamily: $fontFamily, fontPackage: $fontPackage)';
|
||||
}
|
||||
}
|
||||
|
||||
/// 输出配置
|
||||
class OutputConfig {
|
||||
const OutputConfig({
|
||||
required this.filePath,
|
||||
required this.className,
|
||||
this.generateDocs = true,
|
||||
this.useConstConstructor = true,
|
||||
this.packageImport,
|
||||
});
|
||||
|
||||
factory OutputConfig.fromMap(Map<String, dynamic> map) {
|
||||
return OutputConfig(
|
||||
filePath: map['file_path'] as String? ?? 'lib/generated/icons.dart',
|
||||
className: map['class_name'] as String? ?? 'AppIcons',
|
||||
generateDocs: map['generate_docs'] as bool? ?? true,
|
||||
useConstConstructor: map['use_const_constructor'] as bool? ?? true,
|
||||
packageImport: map['package_import'] as String?,
|
||||
);
|
||||
}
|
||||
|
||||
factory OutputConfig.defaults() {
|
||||
return const OutputConfig(
|
||||
filePath: 'lib/generated/icons.dart',
|
||||
className: 'AppIcons',
|
||||
);
|
||||
}
|
||||
|
||||
/// 生成的 Dart 文件路径
|
||||
final String filePath;
|
||||
|
||||
/// 生成的类名
|
||||
final String className;
|
||||
|
||||
/// 是否生成文档注释
|
||||
final bool generateDocs;
|
||||
|
||||
/// 是否使用 const 构造函数
|
||||
final bool useConstConstructor;
|
||||
|
||||
/// 包导入路径(可选,用于生成 part of 指令)
|
||||
final String? packageImport;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'OutputConfig(filePath: $filePath, className: $className, '
|
||||
'generateDocs: $generateDocs)';
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,159 @@
|
|||
import 'package:yx_icon_fonts/src/config/generator_config.dart';
|
||||
import 'package:yx_icon_fonts/src/generator/icon_parser.dart';
|
||||
import 'package:yx_icon_fonts/src/utils/string_helper.dart';
|
||||
|
||||
/// Dart 代码构建器
|
||||
///
|
||||
/// 负责生成 Flutter IconData 常量代码
|
||||
class DartCodeBuilder {
|
||||
const DartCodeBuilder({
|
||||
required this.config,
|
||||
required this.meta,
|
||||
});
|
||||
|
||||
/// 配置
|
||||
final GeneratorConfig config;
|
||||
|
||||
/// 图标元数据
|
||||
final IconFontMeta meta;
|
||||
|
||||
/// 构建完整的 Dart 文件内容
|
||||
String build() {
|
||||
final buffer = StringBuffer()
|
||||
// 文件头注释
|
||||
.._writeHeader(meta)
|
||||
// 导入语句
|
||||
.._writeImports()
|
||||
// 类定义
|
||||
.._writeClass(config, meta);
|
||||
|
||||
return buffer.toString();
|
||||
}
|
||||
}
|
||||
|
||||
extension _StringBufferExt on StringBuffer {
|
||||
/// 写入文件头注释
|
||||
void _writeHeader(IconFontMeta meta) {
|
||||
final now = DateTime.now();
|
||||
final timestamp = '${now.year}-${_pad(now.month)}-${_pad(now.day)} '
|
||||
'${_pad(now.hour)}:${_pad(now.minute)}';
|
||||
|
||||
this
|
||||
..writeln('// ignore_for_file: constant_identifier_names')
|
||||
..writeln()
|
||||
..writeln('// ============================================')
|
||||
..writeln('// 此文件由 yx_icon_fonts 自动生成,请勿手动修改')
|
||||
..writeln('// 生成时间: $timestamp')
|
||||
..writeln('// 图标数量: ${meta.icons.length}')
|
||||
..writeln('// ============================================')
|
||||
..writeln();
|
||||
}
|
||||
|
||||
String _pad(int n) => n.toString().padLeft(2, '0');
|
||||
|
||||
/// 写入导入语句
|
||||
void _writeImports() {
|
||||
this
|
||||
..writeln("import 'package:flutter/widgets.dart';")
|
||||
..writeln();
|
||||
}
|
||||
|
||||
/// 写入类定义
|
||||
void _writeClass(GeneratorConfig config, IconFontMeta meta) {
|
||||
final className = config.output.className;
|
||||
final fontFamily = config.input.fontFamily;
|
||||
final fontPackage = config.input.fontPackage;
|
||||
final generateDocs = config.output.generateDocs;
|
||||
|
||||
if (generateDocs) {
|
||||
this
|
||||
..writeln('/// ${config.generator.name} 图标常量')
|
||||
..writeln('///')
|
||||
..writeln(
|
||||
'/// 包含所有图标的常量定义,可以直接在 Flutter 的 Icon 组件中使用',
|
||||
)
|
||||
..writeln('///')
|
||||
..writeln('/// 示例:')
|
||||
..writeln('/// ```dart')
|
||||
..writeln('/// Icon($className.iconName, size: 24)')
|
||||
..writeln('/// ```');
|
||||
}
|
||||
|
||||
this
|
||||
..writeln('class $className {')
|
||||
..writeln(' $className._();')
|
||||
..writeln();
|
||||
|
||||
if (!config.output.useConstConstructor) {
|
||||
// 添加私有 _icon 工厂方法
|
||||
this
|
||||
..writeln(' // 统一的 IconData 构造方法')
|
||||
..writeln(' static const _icon = _IconDataFactory._();')
|
||||
..writeln();
|
||||
}
|
||||
|
||||
// 生成图标常量
|
||||
for (final icon in meta.icons) {
|
||||
_writeIconConstant(
|
||||
icon,
|
||||
generateDocs: generateDocs,
|
||||
useConst: config.output.useConstConstructor,
|
||||
fontFamily: fontFamily,
|
||||
fontPackage: fontPackage,
|
||||
);
|
||||
}
|
||||
|
||||
this
|
||||
..writeln('}')
|
||||
..writeln();
|
||||
|
||||
if (!config.output.useConstConstructor) {
|
||||
final hasPackage = fontPackage != null;
|
||||
// 添加私有 IconData 工厂类
|
||||
this
|
||||
..writeln('/// 内部 IconData 工厂类')
|
||||
..writeln('class _IconDataFactory {')
|
||||
..writeln(' const _IconDataFactory._();')
|
||||
..writeln()
|
||||
..writeln(" static const String _fontFamily = '$fontFamily';")
|
||||
..writeln(
|
||||
hasPackage
|
||||
? " static const String _fontPackage = '$fontPackage';"
|
||||
: '',
|
||||
)
|
||||
..writeln()
|
||||
..writeln(
|
||||
' IconData call(int codePoint) => '
|
||||
"IconData(codePoint, fontFamily: _fontFamily${hasPackage ? ', fontPackage: _fontPackage' : ''});",
|
||||
)
|
||||
..writeln('}');
|
||||
}
|
||||
}
|
||||
|
||||
/// 写入单个图标常量
|
||||
void _writeIconConstant(
|
||||
IconInfo icon, {
|
||||
required bool generateDocs,
|
||||
required bool useConst,
|
||||
required String fontFamily,
|
||||
String? fontPackage,
|
||||
}) {
|
||||
final constantName = StringHelper.toLegalDartName(icon.fontClass);
|
||||
|
||||
if (generateDocs) {
|
||||
writeln(' /// ${icon.name} (U+${icon.unicode.toUpperCase()})');
|
||||
}
|
||||
|
||||
if (useConst) {
|
||||
final packageParam =
|
||||
fontPackage != null ? ", fontPackage: '$fontPackage'" : '';
|
||||
writeln(
|
||||
" static const IconData $constantName = IconData(0x${icon.unicode}, fontFamily: '$fontFamily'$packageParam);",
|
||||
);
|
||||
} else {
|
||||
writeln(
|
||||
' static final IconData $constantName = _icon(0x${icon.unicode});',
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
import 'package:yx_icon_fonts/src/config/generator_config.dart';
|
||||
import 'package:yx_icon_fonts/src/generator/dart_code_builder.dart';
|
||||
import 'package:yx_icon_fonts/src/generator/icon_parser.dart';
|
||||
import 'package:yx_icon_fonts/src/utils/file_helper.dart';
|
||||
import 'package:yx_icon_fonts/src/utils/logger.dart';
|
||||
|
||||
/// 图标生成器
|
||||
///
|
||||
/// 协调整个代码生成流程
|
||||
class IconGenerator {
|
||||
IconGenerator({
|
||||
required this.config,
|
||||
this.workingDir,
|
||||
});
|
||||
|
||||
/// 配置
|
||||
final GeneratorConfig config;
|
||||
|
||||
/// 工作目录
|
||||
final String? workingDir;
|
||||
|
||||
/// 生成的图标元数据
|
||||
IconFontMeta? _meta;
|
||||
|
||||
/// 获取图标元数据
|
||||
IconFontMeta? get meta => _meta;
|
||||
|
||||
/// 执行生成
|
||||
Future<GenerationResult> generate() async {
|
||||
final stopwatch = Stopwatch()..start();
|
||||
|
||||
try {
|
||||
// 1. 解析 JSON 文件
|
||||
appLogger.progress('正在解析图标配置文件...');
|
||||
final jsonPath = FileHelper.resolvePropertyPath(
|
||||
config.input.jsonFile,
|
||||
workingDir: workingDir,
|
||||
);
|
||||
|
||||
if (!FileHelper.fileExists(jsonPath)) {
|
||||
return GenerationResult(
|
||||
success: false,
|
||||
error: '图标配置文件不存在: $jsonPath',
|
||||
);
|
||||
}
|
||||
|
||||
_meta = IconParser.parseFile(jsonPath);
|
||||
appLogger
|
||||
..stats('解析完成: 找到 ${_meta!.icons.length} 个图标')
|
||||
// 2. 生成代码
|
||||
..progress('正在生成 Dart 代码...');
|
||||
final builder = DartCodeBuilder(
|
||||
config: config,
|
||||
meta: _meta!,
|
||||
);
|
||||
final code = builder.build();
|
||||
|
||||
// 3. 写入文件
|
||||
final outputPath = FileHelper.resolvePropertyPath(
|
||||
config.output.filePath,
|
||||
workingDir: workingDir,
|
||||
);
|
||||
|
||||
appLogger.progress('正在写入文件: $outputPath');
|
||||
FileHelper.writeFile(outputPath, code);
|
||||
|
||||
stopwatch.stop();
|
||||
|
||||
return GenerationResult(
|
||||
success: true,
|
||||
outputPath: outputPath,
|
||||
iconCount: _meta!.icons.length,
|
||||
duration: stopwatch.elapsed,
|
||||
);
|
||||
} on Exception catch (e) {
|
||||
stopwatch.stop();
|
||||
return GenerationResult(
|
||||
success: false,
|
||||
error: e.toString(),
|
||||
duration: stopwatch.elapsed,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 生成结果
|
||||
class GenerationResult {
|
||||
const GenerationResult({
|
||||
required this.success,
|
||||
this.outputPath,
|
||||
this.iconCount = 0,
|
||||
this.error,
|
||||
this.duration,
|
||||
});
|
||||
|
||||
/// 是否成功
|
||||
final bool success;
|
||||
|
||||
/// 输出文件路径
|
||||
final String? outputPath;
|
||||
|
||||
/// 生成的图标数量
|
||||
final int iconCount;
|
||||
|
||||
/// 错误信息
|
||||
final String? error;
|
||||
|
||||
/// 执行时间
|
||||
final Duration? duration;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
if (success) {
|
||||
return 'GenerationResult(success: true, icons: $iconCount, '
|
||||
'path: $outputPath)';
|
||||
}
|
||||
return 'GenerationResult(success: false, error: $error)';
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,109 @@
|
|||
import 'package:yx_icon_fonts/src/utils/file_helper.dart';
|
||||
|
||||
/// 图标数据模型
|
||||
class IconInfo {
|
||||
const IconInfo({
|
||||
required this.iconId,
|
||||
required this.name,
|
||||
required this.fontClass,
|
||||
required this.unicode,
|
||||
required this.unicodeDecimal,
|
||||
});
|
||||
|
||||
/// 从 JSON Map 创建
|
||||
factory IconInfo.fromJson(Map<String, dynamic> json) {
|
||||
return IconInfo(
|
||||
iconId: json['icon_id']?.toString() ?? '',
|
||||
name: json['name'] as String? ?? '',
|
||||
fontClass: json['font_class'] as String? ?? '',
|
||||
unicode: json['unicode'] as String? ?? '',
|
||||
unicodeDecimal: json['unicode_decimal'] as int? ?? 0,
|
||||
);
|
||||
}
|
||||
|
||||
/// 图标 ID
|
||||
final String iconId;
|
||||
|
||||
/// 图标名称
|
||||
final String name;
|
||||
|
||||
/// CSS 类名
|
||||
final String fontClass;
|
||||
|
||||
/// Unicode 值(十六进制字符串)
|
||||
final String unicode;
|
||||
|
||||
/// Unicode 值(十进制)
|
||||
final int unicodeDecimal;
|
||||
|
||||
@override
|
||||
String toString() => 'IconInfo(name: $name, unicode: $unicode)';
|
||||
}
|
||||
|
||||
/// 图标字体元数据
|
||||
class IconFontMeta {
|
||||
const IconFontMeta({
|
||||
required this.id,
|
||||
required this.name,
|
||||
required this.fontFamily,
|
||||
required this.cssPrefix,
|
||||
required this.description,
|
||||
required this.icons,
|
||||
});
|
||||
|
||||
/// 从 JSON Map 创建
|
||||
factory IconFontMeta.fromJson(Map<String, dynamic> json) {
|
||||
final glyphs = json['glyphs'] as List<dynamic>? ?? [];
|
||||
return IconFontMeta(
|
||||
id: json['id']?.toString() ?? '',
|
||||
name: json['name'] as String? ?? '',
|
||||
fontFamily: json['font_family'] as String? ?? 'iconfont',
|
||||
cssPrefix: json['css_prefix_text'] as String? ?? '',
|
||||
description: json['description'] as String? ?? '',
|
||||
icons: glyphs
|
||||
.map((g) => IconInfo.fromJson(g as Map<String, dynamic>))
|
||||
.toList(),
|
||||
);
|
||||
}
|
||||
|
||||
/// 字体 ID
|
||||
final String id;
|
||||
|
||||
/// 字体名称
|
||||
final String name;
|
||||
|
||||
/// 字体家族
|
||||
final String fontFamily;
|
||||
|
||||
/// CSS 前缀
|
||||
final String cssPrefix;
|
||||
|
||||
/// 描述
|
||||
final String description;
|
||||
|
||||
/// 图标列表
|
||||
final List<IconInfo> icons;
|
||||
|
||||
@override
|
||||
String toString() => 'IconFontMeta(name: $name, fontFamily: $fontFamily, '
|
||||
'icons: ${icons.length})';
|
||||
}
|
||||
|
||||
/// 图标解析器
|
||||
///
|
||||
/// 负责解析 iconfont.json 文件
|
||||
class IconParser {
|
||||
/// 私有构造函数
|
||||
IconParser._();
|
||||
|
||||
/// 从文件解析
|
||||
static IconFontMeta parseFile(String jsonFilePath) {
|
||||
final jsonData = FileHelper.readJsonFile(jsonFilePath);
|
||||
return IconFontMeta.fromJson(jsonData);
|
||||
}
|
||||
|
||||
/// 从 Map 解析
|
||||
static IconFontMeta parseMap(Map<String, dynamic> jsonData) {
|
||||
return IconFontMeta.fromJson(jsonData);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:path/path.dart' as path;
|
||||
|
||||
/// 文件操作工具类
|
||||
class FileHelper {
|
||||
/// 私有构造函数,防止实例化
|
||||
FileHelper._();
|
||||
|
||||
/// 读取 JSON 文件并解析
|
||||
static Map<String, dynamic> readJsonFile(String filePath) {
|
||||
final file = File(filePath);
|
||||
|
||||
if (!file.existsSync()) {
|
||||
throw FileNotFoundException('文件不存在: $filePath');
|
||||
}
|
||||
|
||||
try {
|
||||
final content = file.readAsStringSync();
|
||||
return json.decode(content) as Map<String, dynamic>;
|
||||
} on FormatException catch (e) {
|
||||
throw FileParseException('JSON 解析错误: ${e.message}');
|
||||
}
|
||||
}
|
||||
|
||||
/// 写入文件内容
|
||||
///
|
||||
/// 如果目录不存在,会自动创建
|
||||
static void writeFile(String filePath, String content) {
|
||||
final file = File(filePath);
|
||||
final directory = file.parent;
|
||||
|
||||
// 确保目录存在
|
||||
if (!directory.existsSync()) {
|
||||
directory.createSync(recursive: true);
|
||||
}
|
||||
|
||||
file.writeAsStringSync(content);
|
||||
}
|
||||
|
||||
/// 检查文件是否存在
|
||||
static bool fileExists(String filePath) {
|
||||
return File(filePath).existsSync();
|
||||
}
|
||||
|
||||
/// 获取相对于工作目录的绝对路径
|
||||
static String resolvePropertyPath(String relativePath, {String? workingDir}) {
|
||||
final directory = workingDir ?? Directory.current.path;
|
||||
if (path.isAbsolute(relativePath)) {
|
||||
return relativePath;
|
||||
}
|
||||
return path.join(directory, relativePath);
|
||||
}
|
||||
|
||||
/// 获取文件的目录路径
|
||||
static String getDirectoryPath(String filePath) {
|
||||
return path.dirname(filePath);
|
||||
}
|
||||
|
||||
/// 获取文件名(不含扩展名)
|
||||
static String getFileNameWithoutExtension(String filePath) {
|
||||
return path.basenameWithoutExtension(filePath);
|
||||
}
|
||||
|
||||
/// 获取文件名(含扩展名)
|
||||
static String getFileName(String filePath) {
|
||||
return path.basename(filePath);
|
||||
}
|
||||
}
|
||||
|
||||
/// 文件未找到异常
|
||||
class FileNotFoundException implements Exception {
|
||||
FileNotFoundException(this.message);
|
||||
|
||||
final String message;
|
||||
|
||||
@override
|
||||
String toString() => 'FileNotFoundException: $message';
|
||||
}
|
||||
|
||||
/// 文件解析异常
|
||||
class FileParseException implements Exception {
|
||||
FileParseException(this.message);
|
||||
|
||||
final String message;
|
||||
|
||||
@override
|
||||
String toString() => 'FileParseException: $message';
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:logging/logging.dart';
|
||||
|
||||
/// 应用程序日志器
|
||||
final Logger appLogger = Logger('YXIconFonts');
|
||||
|
||||
/// 设置日志
|
||||
void setupLogging({Level level = Level.INFO}) {
|
||||
Logger.root.level = level;
|
||||
Logger.root.onRecord.listen((record) {
|
||||
if (record.level >= Level.SEVERE) {
|
||||
stderr.writeln(record.message);
|
||||
} else {
|
||||
stdout.writeln(record.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// 日志工具扩展
|
||||
extension LoggerExtension on Logger {
|
||||
/// 成功消息(绿色)
|
||||
void success(String message) {
|
||||
info('✅ $message');
|
||||
}
|
||||
|
||||
/// 进度消息
|
||||
void progress(String message) {
|
||||
info('⏳ $message');
|
||||
}
|
||||
|
||||
/// 完成消息
|
||||
void done(String message) {
|
||||
info('✨ $message');
|
||||
}
|
||||
|
||||
/// 统计消息
|
||||
void stats(String message) {
|
||||
info('📊 $message');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
/// 字符串工具类
|
||||
///
|
||||
/// 提供字符串转换和格式化功能
|
||||
class StringHelper {
|
||||
/// 私有构造函数,防止实例化
|
||||
StringHelper._();
|
||||
|
||||
/// 下划线转驼峰命名
|
||||
///
|
||||
/// 例如:icon_32_clean -> icon32Clean
|
||||
static String toCamelCase(String input) {
|
||||
// 预处理:将常见特殊字符转换
|
||||
final processedInput = input
|
||||
.replaceAll('-', '_')
|
||||
.replaceAll('+', 'plus')
|
||||
.replaceAll('(', '')
|
||||
.replaceAll(')', '')
|
||||
.replaceAll(' ', '');
|
||||
|
||||
final parts = processedInput.split('_');
|
||||
if (parts.isEmpty) return input;
|
||||
|
||||
final firstPart = parts[0];
|
||||
final remainingParts = parts.skip(1).map((part) {
|
||||
if (part.isEmpty) return '';
|
||||
return part[0].toUpperCase() + part.substring(1);
|
||||
}).join();
|
||||
|
||||
return firstPart + remainingParts;
|
||||
}
|
||||
|
||||
/// 转换为合法的 Dart 标识符
|
||||
///
|
||||
/// 确保首字符不是数字,只包含字母、数字和下划线
|
||||
static String toLegalDartName(String input) {
|
||||
var name = toCamelCase(input);
|
||||
|
||||
// 首字符为数字,前面加下划线
|
||||
if (name.isNotEmpty && RegExp('^[0-9]').hasMatch(name[0])) {
|
||||
name = '_$name';
|
||||
}
|
||||
|
||||
// 只保留字母、数字和下划线
|
||||
return name.replaceAll(RegExp('[^a-zA-Z0-9_]'), '');
|
||||
}
|
||||
|
||||
/// 转换为 PascalCase(首字母大写的驼峰命名)
|
||||
///
|
||||
/// 例如:icon_class -> IconClass
|
||||
static String toPascalCase(String input) {
|
||||
final camelCase = toCamelCase(input);
|
||||
if (camelCase.isEmpty) return camelCase;
|
||||
return camelCase[0].toUpperCase() + camelCase.substring(1);
|
||||
}
|
||||
|
||||
/// 格式化时间长度
|
||||
static String formatDuration(Duration duration) {
|
||||
if (duration.inMinutes > 0) {
|
||||
return '${duration.inMinutes}m ${duration.inSeconds % 60}s';
|
||||
} else if (duration.inSeconds > 0) {
|
||||
return '${duration.inSeconds}.${(duration.inMilliseconds % 1000) ~/ 100}s';
|
||||
} else {
|
||||
return '${duration.inMilliseconds}ms';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,118 +0,0 @@
|
|||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
/// 学习官OA系统图标组件
|
||||
///
|
||||
/// 专门为学习官OA系统图标设计的组件,处理图标渲染和布局
|
||||
/// 可以直接使用 Flutter 的 Icon 组件,也可以使用此专门的 YXIcon 组件
|
||||
class YXIcon extends StatelessWidget {
|
||||
/// 创建图标组件
|
||||
///
|
||||
/// [icon] 图标数据,可以是 YXIconData 或任何 IconData
|
||||
/// [size] 图标大小
|
||||
/// [color] 图标颜色
|
||||
/// [semanticLabel] 语义标签
|
||||
/// [textDirection] 文本方向
|
||||
/// [shadows] 阴影效果
|
||||
const YXIcon(
|
||||
this.icon, {
|
||||
super.key,
|
||||
this.size,
|
||||
this.color,
|
||||
this.semanticLabel,
|
||||
this.textDirection,
|
||||
this.shadows,
|
||||
});
|
||||
|
||||
/// 图标数据
|
||||
///
|
||||
/// 支持 YXIconData 和任何 IconData 类型
|
||||
final IconData? icon;
|
||||
|
||||
/// 图标大小
|
||||
final double? size;
|
||||
|
||||
/// 图标颜色
|
||||
final Color? color;
|
||||
|
||||
/// 图标语义标签
|
||||
final String? semanticLabel;
|
||||
|
||||
/// 文本方向
|
||||
final TextDirection? textDirection;
|
||||
|
||||
/// 阴影效果
|
||||
final List<Shadow>? shadows;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
assert(this.textDirection != null || debugCheckHasDirectionality(context));
|
||||
final TextDirection textDirection = this.textDirection ?? Directionality.of(context);
|
||||
|
||||
final IconThemeData iconTheme = IconTheme.of(context);
|
||||
|
||||
final double? iconSize = size ?? iconTheme.size;
|
||||
final List<Shadow>? iconShadows = shadows ?? iconTheme.shadows;
|
||||
|
||||
if (icon == null) {
|
||||
return Semantics(
|
||||
label: semanticLabel,
|
||||
child: SizedBox(width: iconSize, height: iconSize),
|
||||
);
|
||||
}
|
||||
|
||||
final double iconOpacity = iconTheme.opacity ?? 1.0;
|
||||
Color iconColor = color ?? iconTheme.color!;
|
||||
if (iconOpacity != 1.0) {
|
||||
iconColor = iconColor.withValues(alpha: iconColor.a * iconOpacity);
|
||||
}
|
||||
|
||||
Widget iconWidget = RichText(
|
||||
overflow: TextOverflow.visible,
|
||||
textDirection: textDirection,
|
||||
text: TextSpan(
|
||||
text: String.fromCharCode(icon!.codePoint),
|
||||
style: TextStyle(
|
||||
inherit: false,
|
||||
color: iconColor,
|
||||
fontSize: iconSize,
|
||||
fontFamily: icon!.fontFamily,
|
||||
package: icon!.fontPackage,
|
||||
shadows: iconShadows,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
if (icon!.matchTextDirection) {
|
||||
switch (textDirection) {
|
||||
case TextDirection.rtl:
|
||||
iconWidget = Transform(
|
||||
transform: Matrix4.identity()..scale(-1.0, 1.0, 1.0),
|
||||
alignment: Alignment.center,
|
||||
transformHitTests: false,
|
||||
child: iconWidget,
|
||||
);
|
||||
break;
|
||||
case TextDirection.ltr:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return Semantics(
|
||||
label: semanticLabel,
|
||||
child: ExcludeSemantics(
|
||||
child: iconWidget,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
||||
super.debugFillProperties(properties);
|
||||
properties.add(IconDataProperty('icon', icon, ifNull: '<empty>', showName: false));
|
||||
properties.add(DoubleProperty('size', size, defaultValue: null));
|
||||
properties.add(ColorProperty('color', color, defaultValue: null));
|
||||
properties.add(IterableProperty<Shadow>('shadows', shadows, defaultValue: null));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
import 'package:flutter/widgets.dart';
|
||||
|
||||
/// 学习官OA系统图标数据类
|
||||
///
|
||||
/// 继承自 IconData,提供统一的图标数据接口
|
||||
class YXIconData extends IconData {
|
||||
/// 创建图标数据实例
|
||||
///
|
||||
/// [codePoint] Unicode码点
|
||||
const YXIconData(super.codePoint)
|
||||
: super(
|
||||
fontFamily: 'iconfont',
|
||||
fontPackage: 'yx_icon_fonts',
|
||||
);
|
||||
}
|
||||
|
|
@ -1,392 +0,0 @@
|
|||
import 'package:flutter/widgets.dart';
|
||||
import 'yx_icon_data.dart';
|
||||
|
||||
/// 学习官OA系统图标字体数据
|
||||
///
|
||||
/// 包含所有图标的常量定义,可以直接在 Flutter 的 Icon 组件中使用
|
||||
/// 也可以使用专门的 YXIcon 组件
|
||||
class YXIconFonts {
|
||||
// 私有构造函数,防止实例化
|
||||
YXIconFonts._();
|
||||
|
||||
/// icon_32_clean 图标
|
||||
///
|
||||
/// Unicode: e660
|
||||
static const IconData icon32Clean = YXIconData(0xe660);
|
||||
|
||||
/// icon_36_viewhistory 图标
|
||||
///
|
||||
/// Unicode: e65f
|
||||
static const IconData icon36Viewhistory = YXIconData(0xe65f);
|
||||
|
||||
/// icon_36_revoke 图标
|
||||
///
|
||||
/// Unicode: e65e
|
||||
static const IconData icon36Revoke = YXIconData(0xe65e);
|
||||
|
||||
/// icon_30_edit 图标
|
||||
///
|
||||
/// Unicode: e65b
|
||||
static const IconData icon30Edit = YXIconData(0xe65b);
|
||||
|
||||
/// icon_24_copy2 图标
|
||||
///
|
||||
/// Unicode: e65c
|
||||
static const IconData icon24Copy2 = YXIconData(0xe65c);
|
||||
|
||||
/// icon_30_delete 图标
|
||||
///
|
||||
/// Unicode: e65d
|
||||
static const IconData icon30Delete = YXIconData(0xe65d);
|
||||
|
||||
/// icon_36_add 图标
|
||||
///
|
||||
/// Unicode: e65a
|
||||
static const IconData icon36Add = YXIconData(0xe65a);
|
||||
|
||||
/// icon_32_location 图标
|
||||
///
|
||||
/// Unicode: e659
|
||||
static const IconData icon32Location = YXIconData(0xe659);
|
||||
|
||||
/// icon_24_mypoints 图标
|
||||
///
|
||||
/// Unicode: e657
|
||||
static const IconData icon24Mypoints = YXIconData(0xe657);
|
||||
|
||||
/// icon_44_me_about 图标
|
||||
///
|
||||
/// Unicode: e656
|
||||
static const IconData icon44MeAbout = YXIconData(0xe656);
|
||||
|
||||
/// icon_44_me_pointsmall 图标
|
||||
///
|
||||
/// Unicode: e658
|
||||
static const IconData icon44MePointsmall = YXIconData(0xe658);
|
||||
|
||||
/// icon_44_search 图标
|
||||
///
|
||||
/// Unicode: e655
|
||||
static const IconData icon44Search = YXIconData(0xe655);
|
||||
|
||||
/// icon_36_clear_people 图标
|
||||
///
|
||||
/// Unicode: e654
|
||||
static const IconData icon36ClearPeople = YXIconData(0xe654);
|
||||
|
||||
/// icon_44_me_log_out 图标
|
||||
///
|
||||
/// Unicode: e652
|
||||
static const IconData icon44MeLogOut = YXIconData(0xe652);
|
||||
|
||||
/// icon_44_me_switch 图标
|
||||
///
|
||||
/// Unicode: e653
|
||||
static const IconData icon44MeSwitch = YXIconData(0xe653);
|
||||
|
||||
/// icon_44_wechat_share_white 图标
|
||||
///
|
||||
/// Unicode: e651
|
||||
static const IconData icon44WechatShareWhite = YXIconData(0xe651);
|
||||
|
||||
/// icon_32_publish 图标
|
||||
///
|
||||
/// Unicode: e64e
|
||||
static const IconData icon32Publish = YXIconData(0xe64e);
|
||||
|
||||
/// icon_32_close 图标
|
||||
///
|
||||
/// Unicode: e64f
|
||||
static const IconData icon32Close = YXIconData(0xe64f);
|
||||
|
||||
/// icon_32_output 图标
|
||||
///
|
||||
/// Unicode: e650
|
||||
static const IconData icon32Output = YXIconData(0xe650);
|
||||
|
||||
/// icon_24_download 图标
|
||||
///
|
||||
/// Unicode: e64d
|
||||
static const IconData icon24Download = YXIconData(0xe64d);
|
||||
|
||||
/// icon_voice_pause 图标
|
||||
///
|
||||
/// Unicode: e64b
|
||||
static const IconData iconVoicePause = YXIconData(0xe64b);
|
||||
|
||||
/// icon_voice 图标
|
||||
///
|
||||
/// Unicode: e64c
|
||||
static const IconData iconVoice = YXIconData(0xe64c);
|
||||
|
||||
/// icon_subtract 图标
|
||||
///
|
||||
/// Unicode: e64a
|
||||
static const IconData iconSubtract = YXIconData(0xe64a);
|
||||
|
||||
/// icon_44_edit 图标
|
||||
///
|
||||
/// Unicode: e648
|
||||
static const IconData icon44Edit = YXIconData(0xe648);
|
||||
|
||||
/// icon_44_delete 图标
|
||||
///
|
||||
/// Unicode: e649
|
||||
static const IconData icon44Delete = YXIconData(0xe649);
|
||||
|
||||
/// icon_44_cancel_account 图标
|
||||
///
|
||||
/// Unicode: e647
|
||||
static const IconData icon44CancelAccount = YXIconData(0xe647);
|
||||
|
||||
/// icon_24_search 图标
|
||||
///
|
||||
/// Unicode: e646
|
||||
static const IconData icon24Search = YXIconData(0xe646);
|
||||
|
||||
/// icon_24_up 图标
|
||||
///
|
||||
/// Unicode: e645
|
||||
static const IconData icon24Up = YXIconData(0xe645);
|
||||
|
||||
/// icon_msg_contacts 图标
|
||||
///
|
||||
/// Unicode: e644
|
||||
static const IconData iconMsgContacts = YXIconData(0xe644);
|
||||
|
||||
/// icon_msg_video 图标
|
||||
///
|
||||
/// Unicode: e63e
|
||||
static const IconData iconMsgVideo = YXIconData(0xe63e);
|
||||
|
||||
/// icon_msg_search 图标
|
||||
///
|
||||
/// Unicode: e63f
|
||||
static const IconData iconMsgSearch = YXIconData(0xe63f);
|
||||
|
||||
/// icon_msg_call 图标
|
||||
///
|
||||
/// Unicode: e640
|
||||
static const IconData iconMsgCall = YXIconData(0xe640);
|
||||
|
||||
/// icon_msg_photo 图标
|
||||
///
|
||||
/// Unicode: e641
|
||||
static const IconData iconMsgPhoto = YXIconData(0xe641);
|
||||
|
||||
/// icon_msg_img 图标
|
||||
///
|
||||
/// Unicode: e642
|
||||
static const IconData iconMsgImg = YXIconData(0xe642);
|
||||
|
||||
/// icon_msg_file 图标
|
||||
///
|
||||
/// Unicode: e643
|
||||
static const IconData iconMsgFile = YXIconData(0xe643);
|
||||
|
||||
/// icon_32_arrow_right 图标
|
||||
///
|
||||
/// Unicode: e61d
|
||||
static const IconData icon32ArrowRight = YXIconData(0xe61d);
|
||||
|
||||
/// icon_44_me_password 图标
|
||||
///
|
||||
/// Unicode: e639
|
||||
static const IconData icon44MePassword = YXIconData(0xe639);
|
||||
|
||||
/// icon_44_me_help 图标
|
||||
///
|
||||
/// Unicode: e63a
|
||||
static const IconData icon44MeHelp = YXIconData(0xe63a);
|
||||
|
||||
/// icon_24_minus 图标
|
||||
///
|
||||
/// Unicode: e63b
|
||||
static const IconData icon24Minus = YXIconData(0xe63b);
|
||||
|
||||
/// icon_36_team 图标
|
||||
///
|
||||
/// Unicode: e63c
|
||||
static const IconData icon36Team = YXIconData(0xe63c);
|
||||
|
||||
/// icon_32_filter 图标
|
||||
///
|
||||
/// Unicode: e63d
|
||||
static const IconData icon32Filter = YXIconData(0xe63d);
|
||||
|
||||
/// icon_44_quit_lite 图标
|
||||
///
|
||||
/// Unicode: e631
|
||||
static const IconData icon44QuitLite = YXIconData(0xe631);
|
||||
|
||||
/// icon_44_me_version 图标
|
||||
///
|
||||
/// Unicode: e632
|
||||
static const IconData icon44MeVersion = YXIconData(0xe632);
|
||||
|
||||
/// icon_36_question 图标
|
||||
///
|
||||
/// Unicode: e633
|
||||
static const IconData icon36Question = YXIconData(0xe633);
|
||||
|
||||
/// icon_44_me_privacy 图标
|
||||
///
|
||||
/// Unicode: e634
|
||||
static const IconData icon44MePrivacy = YXIconData(0xe634);
|
||||
|
||||
/// icon_44_more2 图标
|
||||
///
|
||||
/// Unicode: e635
|
||||
static const IconData icon44More2 = YXIconData(0xe635);
|
||||
|
||||
/// icon_36_only_see 图标
|
||||
///
|
||||
/// Unicode: e636
|
||||
static const IconData icon36OnlySee = YXIconData(0xe636);
|
||||
|
||||
/// icon_44_me_user 图标
|
||||
///
|
||||
/// Unicode: e637
|
||||
static const IconData icon44MeUser = YXIconData(0xe637);
|
||||
|
||||
/// icon_44_me_safe 图标
|
||||
///
|
||||
/// Unicode: e62c
|
||||
static const IconData icon44MeSafe = YXIconData(0xe62c);
|
||||
|
||||
/// icon_44_me_phone 图标
|
||||
///
|
||||
/// Unicode: e62d
|
||||
static const IconData icon44MePhone = YXIconData(0xe62d);
|
||||
|
||||
/// icon_24_copy 图标
|
||||
///
|
||||
/// Unicode: e62e
|
||||
static const IconData icon24Copy = YXIconData(0xe62e);
|
||||
|
||||
/// icon_32_quit 图标
|
||||
///
|
||||
/// Unicode: e630
|
||||
static const IconData icon32Quit = YXIconData(0xe630);
|
||||
|
||||
/// icon_44_calendar 图标
|
||||
///
|
||||
/// Unicode: e626
|
||||
static const IconData icon44Calendar = YXIconData(0xe626);
|
||||
|
||||
/// icon_32_student 图标
|
||||
///
|
||||
/// Unicode: e627
|
||||
static const IconData icon32Student = YXIconData(0xe627);
|
||||
|
||||
/// icon_36_delete 图标
|
||||
///
|
||||
/// Unicode: e628
|
||||
static const IconData icon36Delete = YXIconData(0xe628);
|
||||
|
||||
/// icon_44_more 图标
|
||||
///
|
||||
/// Unicode: e629
|
||||
static const IconData icon44More = YXIconData(0xe629);
|
||||
|
||||
/// icon_44_arrow_left 图标
|
||||
///
|
||||
/// Unicode: e62a
|
||||
static const IconData icon44ArrowLeft = YXIconData(0xe62a);
|
||||
|
||||
/// icon_36_edit_line 图标
|
||||
///
|
||||
/// Unicode: e62b
|
||||
static const IconData icon36EditLine = YXIconData(0xe62b);
|
||||
|
||||
/// icon_44_arrow_right 图标
|
||||
///
|
||||
/// Unicode: e622
|
||||
static const IconData icon44ArrowRight = YXIconData(0xe622);
|
||||
|
||||
/// icon_24_delete 图标
|
||||
///
|
||||
/// Unicode: e623
|
||||
static const IconData icon24Delete = YXIconData(0xe623);
|
||||
|
||||
/// icon_56_msg_add 图标
|
||||
///
|
||||
/// Unicode: e624
|
||||
static const IconData icon56MsgAdd = YXIconData(0xe624);
|
||||
|
||||
/// icon_56_msg_face 图标
|
||||
///
|
||||
/// Unicode: e625
|
||||
static const IconData icon56MsgFace = YXIconData(0xe625);
|
||||
|
||||
/// icon_56_msg_voice 图标
|
||||
///
|
||||
/// Unicode: e616
|
||||
static const IconData icon56MsgVoice = YXIconData(0xe616);
|
||||
|
||||
/// icon_44_share 图标
|
||||
///
|
||||
/// Unicode: e615
|
||||
static const IconData icon44Share = YXIconData(0xe615);
|
||||
|
||||
/// icon_36_hint 图标
|
||||
///
|
||||
/// Unicode: e613
|
||||
static const IconData icon36Hint = YXIconData(0xe613);
|
||||
|
||||
/// icon_24_add 图标
|
||||
///
|
||||
/// Unicode: e617
|
||||
static const IconData icon24Add = YXIconData(0xe617);
|
||||
|
||||
/// icon_24_plus 图标
|
||||
///
|
||||
/// Unicode: e618
|
||||
static const IconData icon24Plus = YXIconData(0xe618);
|
||||
|
||||
/// icon_44_keyboard 图标
|
||||
///
|
||||
/// Unicode: e614
|
||||
static const IconData icon44Keyboard = YXIconData(0xe614);
|
||||
|
||||
/// icon_44_quit 图标
|
||||
///
|
||||
/// Unicode: e619
|
||||
static const IconData icon44Quit = YXIconData(0xe619);
|
||||
|
||||
/// icon_44_add 图标
|
||||
///
|
||||
/// Unicode: e61a
|
||||
static const IconData icon44Add = YXIconData(0xe61a);
|
||||
|
||||
/// icon_24_switch 图标
|
||||
///
|
||||
/// Unicode: e61b
|
||||
static const IconData icon24Switch = YXIconData(0xe61b);
|
||||
|
||||
/// icon_44_arrow_down_line 图标
|
||||
///
|
||||
/// Unicode: e61c
|
||||
static const IconData icon44ArrowDownLine = YXIconData(0xe61c);
|
||||
|
||||
/// icon_24_arrow_right 图标
|
||||
///
|
||||
/// Unicode: e61e
|
||||
static const IconData icon24ArrowRight = YXIconData(0xe61e);
|
||||
|
||||
/// icon_32_add 图标
|
||||
///
|
||||
/// Unicode: e61f
|
||||
static const IconData icon32Add = YXIconData(0xe61f);
|
||||
|
||||
/// icon_24_edit 图标
|
||||
///
|
||||
/// Unicode: e620
|
||||
static const IconData icon24Edit = YXIconData(0xe620);
|
||||
|
||||
/// icon_24_arrow_down 图标
|
||||
///
|
||||
/// Unicode: e621
|
||||
static const IconData icon24ArrowDown = YXIconData(0xe621);
|
||||
|
||||
}
|
||||
|
|
@ -1,26 +1,48 @@
|
|||
library yx_icon_fonts;
|
||||
|
||||
// 导出所有公共组件和类
|
||||
export 'src/yx_icon.dart';
|
||||
export 'src/yx_icon_data.dart';
|
||||
export 'src/yx_icon_fonts_data.dart';
|
||||
|
||||
/// 学习官OA系统图标字体库
|
||||
/// YX Icon Fonts - 图标字体代码生成器
|
||||
///
|
||||
/// 提供学习官OA系统的图标字体支持,包含所有图标常量和组件
|
||||
/// 从 iconfont.json 生成 Flutter IconData 常量
|
||||
///
|
||||
/// ## 使用方法
|
||||
///
|
||||
/// ```dart
|
||||
/// // 使用 YXIcon 组件
|
||||
/// YXIcon(YXIconFonts.iconMsgContacts, size: 24, color: Colors.blue)
|
||||
///
|
||||
/// // 使用 Flutter 原生 Icon 组件
|
||||
/// Icon(YXIconFonts.iconMsgContacts, size: 24, color: Colors.blue)
|
||||
///
|
||||
/// // 在 IconButton 中使用
|
||||
/// IconButton(
|
||||
/// icon: YXIcon(YXIconFonts.iconMsgContacts),
|
||||
/// onPressed: () {},
|
||||
/// )
|
||||
/// 1. 添加到 dev_dependencies:
|
||||
/// ```yaml
|
||||
/// dev_dependencies:
|
||||
/// yx_icon_fonts:
|
||||
/// git:
|
||||
/// url: https://gitea.23544.com/wangyang/yx_icon_fonts_flutter
|
||||
/// ```
|
||||
///
|
||||
/// 2. 初始化配置文件:
|
||||
/// ```bash
|
||||
/// dart run yx_icon_fonts init
|
||||
/// ```
|
||||
///
|
||||
/// 3. 编辑配置文件 `icon_generator_config.yaml`
|
||||
///
|
||||
/// 4. 生成代码:
|
||||
/// ```bash
|
||||
/// dart run yx_icon_fonts generate
|
||||
/// ```
|
||||
library yx_icon_fonts;
|
||||
|
||||
// CLI
|
||||
export 'src/cli/icon_fonts_cli.dart';
|
||||
|
||||
// 命令
|
||||
export 'src/commands/base_command.dart';
|
||||
export 'src/commands/generate_command.dart';
|
||||
export 'src/commands/init_command.dart';
|
||||
|
||||
// 配置
|
||||
export 'src/config/config_loader.dart';
|
||||
export 'src/config/generator_config.dart';
|
||||
|
||||
// 生成器
|
||||
export 'src/generator/dart_code_builder.dart';
|
||||
export 'src/generator/icon_generator.dart';
|
||||
export 'src/generator/icon_parser.dart';
|
||||
|
||||
// 工具
|
||||
export 'src/utils/file_helper.dart';
|
||||
export 'src/utils/logger.dart';
|
||||
export 'src/utils/string_helper.dart';
|
||||
|
|
|
|||
350
pubspec.lock
350
pubspec.lock
|
|
@ -1,6 +1,30 @@
|
|||
# Generated by pub
|
||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||
packages:
|
||||
_fe_analyzer_shared:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: _fe_analyzer_shared
|
||||
sha256: "5b7468c326d2f8a4f630056404ca0d291ade42918f4a3c6233618e724f39da8e"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "92.0.0"
|
||||
analyzer:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: analyzer
|
||||
sha256: "70e4b1ef8003c64793a9e268a551a82869a8a96f39deb73dea28084b0e8bf75e"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "9.0.0"
|
||||
args:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: args
|
||||
sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.7.0"
|
||||
async:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -17,22 +41,14 @@ packages:
|
|||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.1.2"
|
||||
characters:
|
||||
cli_config:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: characters
|
||||
sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803
|
||||
name: cli_config
|
||||
sha256: ac20a183a07002b700f0c25e61b7ee46b23c309d76ab7b7640a028f18e4d99ec
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.4.0"
|
||||
clock:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: clock
|
||||
sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.1.2"
|
||||
version: "0.2.0"
|
||||
collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -41,64 +57,86 @@ packages:
|
|||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.19.1"
|
||||
fake_async:
|
||||
convert:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: fake_async
|
||||
sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44"
|
||||
name: convert
|
||||
sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.3.3"
|
||||
flutter:
|
||||
version: "3.1.2"
|
||||
coverage:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: coverage
|
||||
sha256: "5da775aa218eaf2151c721b16c01c7676fbfdd99cebba2bf64e8b807a28ff94d"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.15.0"
|
||||
crypto:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: crypto
|
||||
sha256: c8ea0233063ba03258fbcf2ca4d6dadfefe14f02fab57702265467a19f27fadf
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "3.0.7"
|
||||
file:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file
|
||||
sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "7.0.1"
|
||||
frontend_server_client:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: frontend_server_client
|
||||
sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "4.0.0"
|
||||
glob:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: glob
|
||||
sha256: c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.1.3"
|
||||
http_multi_server:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: http_multi_server
|
||||
sha256: aa6199f908078bb1c5efb8d8638d4ae191aac11b311132c3ef48ce352fb52ef8
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "3.2.2"
|
||||
http_parser:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: http_parser
|
||||
sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "4.1.2"
|
||||
io:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: io
|
||||
sha256: dfd5a80599cf0165756e3181807ed3e77daf6dd4137caaad72d0b7931597650b
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.0.5"
|
||||
logging:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_lints:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: flutter_lints
|
||||
sha256: "9e8c3858111da373efc5aa341de011d9bd23e2c5c5e0c62bccf32438e192d7b1"
|
||||
name: logging
|
||||
sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "3.0.2"
|
||||
flutter_test:
|
||||
dependency: "direct dev"
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
leak_tracker:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker
|
||||
sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "11.0.2"
|
||||
leak_tracker_flutter_testing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker_flutter_testing
|
||||
sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "3.0.10"
|
||||
leak_tracker_testing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker_testing
|
||||
sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "3.0.2"
|
||||
lints:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: lints
|
||||
sha256: cbf8d4b858bb0134ef3ef87841abdf8d63bfc255c266b7bf6b39daa1085c4290
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "3.0.0"
|
||||
version: "1.3.0"
|
||||
matcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -107,14 +145,6 @@ packages:
|
|||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.12.17"
|
||||
material_color_utilities:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: material_color_utilities
|
||||
sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.11.1"
|
||||
meta:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -123,19 +153,102 @@ packages:
|
|||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.16.0"
|
||||
path:
|
||||
mime:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: mime
|
||||
sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
node_preamble:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: node_preamble
|
||||
sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.0.2"
|
||||
package_config:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: package_config
|
||||
sha256: f096c55ebb7deb7e384101542bfba8c52696c1b56fca2eb62827989ef2353bbc
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.2.0"
|
||||
path:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: path
|
||||
sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.9.1"
|
||||
sky_engine:
|
||||
pool:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
description:
|
||||
name: pool
|
||||
sha256: "978783255c543aa3586a1b3c21f6e9d720eb315376a915872c61ef8b5c20177d"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.5.2"
|
||||
pub_semver:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pub_semver
|
||||
sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.2.0"
|
||||
shelf:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shelf
|
||||
sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.4.2"
|
||||
shelf_packages_handler:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shelf_packages_handler
|
||||
sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "3.0.2"
|
||||
shelf_static:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shelf_static
|
||||
sha256: c87c3875f91262785dade62d135760c2c69cb217ac759485334c5857ad89f6e3
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.1.3"
|
||||
shelf_web_socket:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shelf_web_socket
|
||||
sha256: "3632775c8e90d6c9712f883e633716432a27758216dfb61bd86a8321c0580925"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "3.0.0"
|
||||
source_map_stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_map_stack_trace
|
||||
sha256: c0713a43e323c3302c2abe2a1cc89aa057a387101ebd280371d6a6c9fa68516b
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.1.2"
|
||||
source_maps:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_maps
|
||||
sha256: "190222579a448b03896e0ca6eca5998fa810fda630c1d65e2f78b3f638f54812"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.10.13"
|
||||
source_span:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -176,22 +289,46 @@ packages:
|
|||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.2.2"
|
||||
test:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: test
|
||||
sha256: "77cc98ea27006c84e71a7356cf3daf9ddbde2d91d84f77dbfe64cf0e4d9611ae"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.28.0"
|
||||
test_api:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00"
|
||||
sha256: "19a78f63e83d3a61f00826d09bc2f60e191bf3504183c001262be6ac75589fb8"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.7.6"
|
||||
vector_math:
|
||||
version: "0.7.8"
|
||||
test_core:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vector_math
|
||||
sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b
|
||||
name: test_core
|
||||
sha256: f1072617a6657e5fc09662e721307f7fb009b4ed89b19f47175d11d5254a62d4
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.2.0"
|
||||
version: "0.6.14"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: typed_data
|
||||
sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.4.0"
|
||||
very_good_analysis:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: very_good_analysis
|
||||
sha256: "1fb637c0022034b1f19ea2acb42a3603cbd8314a470646a59a2fb01f5f3a8629"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "6.0.0"
|
||||
vm_service:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -200,6 +337,53 @@ packages:
|
|||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "15.0.2"
|
||||
watcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: watcher
|
||||
sha256: f52385d4f73589977c80797e60fe51014f7f2b957b5e9a62c3f6ada439889249
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web
|
||||
sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.1.1"
|
||||
web_socket:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web_socket
|
||||
sha256: "34d64019aa8e36bf9842ac014bb5d2f5586ca73df5e4d9bf5c936975cae6982c"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
web_socket_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web_socket_channel
|
||||
sha256: d645757fb0f4773d602444000a8131ff5d48c9e47adfe9772652dd1a4f2d45c8
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "3.0.3"
|
||||
webkit_inspection_protocol:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: webkit_inspection_protocol
|
||||
sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.2.1"
|
||||
yaml:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: yaml
|
||||
sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "3.1.3"
|
||||
sdks:
|
||||
dart: ">=3.8.0-0 <4.0.0"
|
||||
flutter: ">=3.18.0-18.0.pre.54"
|
||||
dart: ">=3.9.0 <4.0.0"
|
||||
|
|
|
|||
30
pubspec.yaml
30
pubspec.yaml
|
|
@ -1,23 +1,25 @@
|
|||
name: yx_icon_fonts
|
||||
description: 学习官OA系统图标字体库,基于iconfont.ttf和iconfont.json生成
|
||||
version: 1.0.7
|
||||
description: 图标字体代码生成器 - 从 iconfont.json 生成 Flutter IconData 常量
|
||||
version: 2.1.0
|
||||
homepage: https://gitea.23544.com/wangyang/yx_icon_fonts_flutter
|
||||
|
||||
environment:
|
||||
sdk: '>=3.0.0 <4.0.0'
|
||||
flutter: ">=3.0.0"
|
||||
|
||||
# 可执行命令配置
|
||||
# 使用方式:dart run yx_icon_fonts generate
|
||||
# 或者使用别名:dart run yx_icon_fonts:yx_icon_fonts
|
||||
executables:
|
||||
yx_icon_fonts: main
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
# 日志
|
||||
logging: ^1.3.0
|
||||
# 路径处理
|
||||
path: ^1.9.1
|
||||
# YAML 解析
|
||||
yaml: ^3.1.3
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
flutter_lints: ^3.0.0
|
||||
|
||||
flutter:
|
||||
fonts:
|
||||
- family: iconfont
|
||||
fonts:
|
||||
- asset: fonts/iconfont.ttf
|
||||
test: ^1.24.0
|
||||
very_good_analysis: ^6.0.0
|
||||
|
|
@ -1,96 +0,0 @@
|
|||
import 'dart:io';
|
||||
import 'utils.dart';
|
||||
|
||||
/// 自动生成示例内容的脚本
|
||||
///
|
||||
/// 使用方法:
|
||||
/// dart scripts/generate_example.dart
|
||||
void main() {
|
||||
final iconData = readIconFontJson();
|
||||
final glyphs = getGlyphs(iconData);
|
||||
// 读取已定义的 YXIconFonts 静态常量
|
||||
final definedIcons = getDefinedIconNames();
|
||||
|
||||
// 生成 icons.dart
|
||||
_generateIconsFile(glyphs, definedIcons);
|
||||
|
||||
print('✅ 成功生成示例应用文件');
|
||||
print('📁 生成的文件:');
|
||||
print(' - example/lib/icons.dart');
|
||||
}
|
||||
|
||||
/// 生成 icons.dart 文件
|
||||
void _generateIconsFile(List<dynamic> glyphs, Set<String> definedIcons) {
|
||||
final buffer = StringBuffer();
|
||||
buffer.writeln("import 'package:yx_icon_fonts/yx_icon_fonts.dart';");
|
||||
buffer.writeln("import 'package:yx_icon_fonts_example/example_icon.dart';");
|
||||
buffer.writeln();
|
||||
buffer.writeln("// 此文件由脚本自动生成!");
|
||||
buffer.writeln();
|
||||
buffer.writeln("final icons = <ExampleIcon>[");
|
||||
|
||||
// 按类别分组图标
|
||||
final categories = <String, List<Map<String, dynamic>>>{};
|
||||
for (final glyph in glyphs) {
|
||||
final name = glyph['font_class'] as String;
|
||||
final unicodeDecimal = glyph['unicode_decimal'] as int;
|
||||
String category = '其他图标';
|
||||
if (name.contains('msg')) {
|
||||
category = '消息相关图标';
|
||||
} else if (name.contains('arrow')) {
|
||||
category = '箭头相关图标';
|
||||
} else if (name.contains('edit')) {
|
||||
category = '编辑相关图标';
|
||||
} else if (name.contains('me_')) {
|
||||
category = '个人中心相关图标';
|
||||
} else if (name.contains('team') || name.contains('student')) {
|
||||
category = '团队和用户相关图标';
|
||||
} else if (name.contains('filter') || name.contains('question') || name.contains('onlysee') || name.contains('hint') || name.contains('switch')) {
|
||||
category = '功能图标';
|
||||
} else if (name.contains('delete')) {
|
||||
category = '删除相关图标';
|
||||
} else if (name.contains('more')) {
|
||||
category = '更多和菜单相关图标';
|
||||
} else if (name.contains('quit')) {
|
||||
category = '退出相关图标';
|
||||
} else if (name.contains('copy')) {
|
||||
category = '复制相关图标';
|
||||
} else if (name.contains('calendar')) {
|
||||
category = '日历相关图标';
|
||||
} else if (name.contains('share')) {
|
||||
category = '分享相关图标';
|
||||
} else if (name.contains('add') || name.contains('+')) {
|
||||
category = '添加相关图标';
|
||||
} else if (name.contains('keyboard')) {
|
||||
category = '键盘相关图标';
|
||||
} else if (name.contains('-')) {
|
||||
category = '特殊字符图标';
|
||||
}
|
||||
categories.putIfAbsent(category, () => []);
|
||||
categories[category]!.add({
|
||||
'name': name,
|
||||
'unicodeDecimal': unicodeDecimal,
|
||||
});
|
||||
}
|
||||
|
||||
// 生成图标列表
|
||||
for (final category in categories.keys) {
|
||||
buffer.writeln(" // $category");
|
||||
for (final icon in categories[category]!) {
|
||||
final name = icon['name'] as String;
|
||||
final camelCaseName = toLegalDartName(name);
|
||||
if (!definedIcons.contains(camelCaseName)) continue; // 跳过未定义的
|
||||
final displayName = _getDisplayName(name);
|
||||
buffer.writeln(" ExampleIcon(YXIconFonts.$camelCaseName, '$displayName'),");
|
||||
}
|
||||
buffer.writeln();
|
||||
}
|
||||
buffer.writeln("];");
|
||||
final file = File('example/lib/icons.dart');
|
||||
file.writeAsStringSync(buffer.toString());
|
||||
}
|
||||
|
||||
/// 获取展示用名称
|
||||
String _getDisplayName(String name) {
|
||||
return name.replaceAll('_', ' ');
|
||||
}
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
import 'dart:io';
|
||||
import 'utils.dart';
|
||||
|
||||
/// 自动生成图标数据文件
|
||||
///
|
||||
/// 从 iconfont.json 文件读取图标信息,生成 Dart 代码
|
||||
void main() {
|
||||
final iconData = readIconFontJson();
|
||||
final icons = getGlyphs(iconData);
|
||||
|
||||
final StringBuffer buffer = StringBuffer();
|
||||
|
||||
// 添加文件头部
|
||||
buffer.writeln("import 'package:flutter/widgets.dart';");
|
||||
buffer.writeln("import 'yx_icon_data.dart';");
|
||||
buffer.writeln();
|
||||
buffer.writeln("/// 学习官OA系统图标字体数据");
|
||||
buffer.writeln("/// ");
|
||||
buffer.writeln("/// 包含所有图标的常量定义,可以直接在 Flutter 的 Icon 组件中使用");
|
||||
buffer.writeln("/// 也可以使用专门的 YXIcon 组件");
|
||||
buffer.writeln("class YXIconFonts {");
|
||||
buffer.writeln(" // 私有构造函数,防止实例化");
|
||||
buffer.writeln(" YXIconFonts._();");
|
||||
buffer.writeln();
|
||||
|
||||
// 生成图标常量
|
||||
for (final Map<String, dynamic> icon in icons) {
|
||||
final String name = icon['name'] as String;
|
||||
final String unicode = icon['unicode'] as String;
|
||||
// 转换为驼峰命名并处理特殊字符
|
||||
final String camelCaseName = toCamelCase(name);
|
||||
// 添加注释
|
||||
buffer.writeln(" /// $name 图标");
|
||||
buffer.writeln(" /// ");
|
||||
buffer.writeln(" /// Unicode: $unicode");
|
||||
buffer.writeln(" static const IconData $camelCaseName = YXIconData(0x$unicode);");
|
||||
buffer.writeln();
|
||||
}
|
||||
|
||||
buffer.writeln("}");
|
||||
|
||||
// 写入文件
|
||||
final File outputFile = File('lib/src/yx_icon_fonts_data.dart');
|
||||
outputFile.writeAsStringSync(buffer.toString());
|
||||
|
||||
print('✅ 图标数据文件生成成功: [32m${outputFile.path} [0m');
|
||||
print('📊 共生成 ${icons.length} 个图标常量');
|
||||
}
|
||||
|
|
@ -1,144 +0,0 @@
|
|||
import 'dart:io';
|
||||
import 'utils.dart';
|
||||
|
||||
/// 自动生成外部使用的图标封装文件
|
||||
///
|
||||
/// 从 iconfont.json 文件读取图标信息,生成 FontIcons 封装类
|
||||
/// 生成位置:项目根目录的 icons.dart
|
||||
void main() {
|
||||
final iconData = readIconFontJson();
|
||||
final glyphs = getGlyphs(iconData);
|
||||
final definedIcons = getDefinedIconNames();
|
||||
|
||||
_generateWrapperFile(glyphs, definedIcons);
|
||||
|
||||
print('✅ 外部图标封装文件生成成功: \x1B[32mgenerate/icons.dart\x1B[0m');
|
||||
print('📊 共生成 ${definedIcons.length} 个图标常量');
|
||||
}
|
||||
|
||||
/// 生成 icons.dart 文件
|
||||
void _generateWrapperFile(List<dynamic> glyphs, Set<String> definedIcons) {
|
||||
final buffer = StringBuffer();
|
||||
|
||||
// 文件头部
|
||||
buffer.writeln("// ignore_for_file: constant_identifier_names");
|
||||
buffer.writeln();
|
||||
buffer.writeln("import 'package:flutter/material.dart';");
|
||||
buffer.writeln("import 'package:yx_icon_fonts/yx_icon_fonts.dart';");
|
||||
buffer.writeln();
|
||||
buffer.writeln("class FontIcons {");
|
||||
buffer.writeln(" // 私有构造函数,防止实例化");
|
||||
buffer.writeln(" FontIcons._();");
|
||||
buffer.writeln();
|
||||
|
||||
// 按类别分组图标
|
||||
final categories = _categorizeIcons(glyphs, definedIcons);
|
||||
|
||||
// 定义类别显示顺序
|
||||
final categoryOrder = [
|
||||
'其他图标',
|
||||
'编辑相关图标',
|
||||
'删除相关图标',
|
||||
'个人中心相关图标',
|
||||
'消息相关图标',
|
||||
'箭头相关图标',
|
||||
'特殊字符图标',
|
||||
'团队和用户相关图标',
|
||||
'功能图标',
|
||||
'退出相关图标',
|
||||
'更多和菜单相关图标',
|
||||
'复制相关图标',
|
||||
'日历相关图标',
|
||||
'分享相关图标',
|
||||
'添加相关图标',
|
||||
'键盘相关图标',
|
||||
];
|
||||
|
||||
// 按顺序生成图标
|
||||
for (final category in categoryOrder) {
|
||||
if (categories.containsKey(category) && categories[category]!.isNotEmpty) {
|
||||
buffer.writeln(" // $category");
|
||||
for (final iconName in categories[category]!) {
|
||||
buffer.writeln(" static const IconData $iconName = YXIconFonts.$iconName;");
|
||||
}
|
||||
buffer.writeln();
|
||||
}
|
||||
}
|
||||
|
||||
buffer.writeln("}");
|
||||
|
||||
// 确保 generate 目录存在
|
||||
final dir = Directory('generate');
|
||||
if (!dir.existsSync()) {
|
||||
dir.createSync(recursive: true);
|
||||
}
|
||||
|
||||
// 写入文件
|
||||
final file = File('generate/icons.dart');
|
||||
file.writeAsStringSync(buffer.toString());
|
||||
}
|
||||
|
||||
/// 将图标按类别分组
|
||||
Map<String, List<String>> _categorizeIcons(List<dynamic> glyphs, Set<String> definedIcons) {
|
||||
final categories = <String, List<String>>{};
|
||||
|
||||
for (final glyph in glyphs) {
|
||||
final name = glyph['font_class'] as String;
|
||||
final camelCaseName = toLegalDartName(name);
|
||||
|
||||
// 跳过未定义的图标
|
||||
if (!definedIcons.contains(camelCaseName)) continue;
|
||||
|
||||
// 确定类别
|
||||
String category = _getCategory(name);
|
||||
|
||||
categories.putIfAbsent(category, () => []);
|
||||
categories[category]!.add(camelCaseName);
|
||||
}
|
||||
|
||||
return categories;
|
||||
}
|
||||
|
||||
/// 根据图标名称确定类别
|
||||
String _getCategory(String name) {
|
||||
final lowerName = name.toLowerCase();
|
||||
|
||||
if (lowerName.contains('edit')) {
|
||||
return '编辑相关图标';
|
||||
} else if (lowerName.contains('delete')) {
|
||||
return '删除相关图标';
|
||||
} else if (lowerName.contains('me_')) {
|
||||
return '个人中心相关图标';
|
||||
} else if (lowerName.contains('msg')) {
|
||||
return '消息相关图标';
|
||||
} else if (lowerName.contains('arrow')) {
|
||||
return '箭头相关图标';
|
||||
} else if (lowerName == '24_-' || lowerName.contains('subtract')) {
|
||||
return '特殊字符图标';
|
||||
} else if (lowerName.contains('team') || lowerName.contains('student')) {
|
||||
return '团队和用户相关图标';
|
||||
} else if (lowerName.contains('filter') ||
|
||||
lowerName.contains('question') ||
|
||||
lowerName.contains('onlysee') ||
|
||||
lowerName.contains('hint') ||
|
||||
lowerName.contains('switch')) {
|
||||
return '功能图标';
|
||||
} else if (lowerName.contains('quit')) {
|
||||
return '退出相关图标';
|
||||
} else if (lowerName.contains('more')) {
|
||||
return '更多和菜单相关图标';
|
||||
} else if (lowerName.contains('copy')) {
|
||||
return '复制相关图标';
|
||||
} else if (lowerName.contains('calendar')) {
|
||||
return '日历相关图标';
|
||||
} else if (lowerName.contains('share')) {
|
||||
return '分享相关图标';
|
||||
} else if (lowerName.contains('add') || lowerName.contains('+') || lowerName.contains('plus')) {
|
||||
return '添加相关图标';
|
||||
} else if (lowerName.contains('keyboard')) {
|
||||
return '键盘相关图标';
|
||||
} else {
|
||||
return '其他图标';
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
/// 读取 iconfont.json 文件,返回解析后的 Map
|
||||
Map<String, dynamic> readIconFontJson([String path = 'iconfont.json']) {
|
||||
final file = File(path);
|
||||
if (!file.existsSync()) {
|
||||
throw Exception('未找到 $path 文件');
|
||||
}
|
||||
final content = file.readAsStringSync();
|
||||
return json.decode(content) as Map<String, dynamic>;
|
||||
}
|
||||
|
||||
/// 获取 glyphs 列表
|
||||
List<dynamic> getGlyphs(Map<String, dynamic> iconData) {
|
||||
return iconData['glyphs'] as List<dynamic>;
|
||||
}
|
||||
|
||||
/// 下划线转驼峰命名,并处理常见特殊字符,保证 Dart 标识符合法
|
||||
String toCamelCase(String input) {
|
||||
String processedInput = input.replaceAll('-', '_').replaceAll('+', 'plus').replaceAll('(', '').replaceAll(')', '').replaceAll(' ', '');
|
||||
final List<String> parts = processedInput.split('_');
|
||||
if (parts.isEmpty) return input;
|
||||
final String firstPart = parts[0];
|
||||
final String remainingParts = parts.skip(1).map((part) => part.isNotEmpty ? part[0].toUpperCase() + part.substring(1) : '').join();
|
||||
return firstPart + remainingParts;
|
||||
}
|
||||
|
||||
/// Dart 标识符合法化(首字符不能为数字,不能有特殊符号)
|
||||
String toLegalDartName(String input) {
|
||||
String name = toCamelCase(input);
|
||||
// 首字符为数字,前面加下划线
|
||||
if (name.isNotEmpty && RegExp(r'^[0-9]').hasMatch(name[0])) {
|
||||
name = '_$name';
|
||||
}
|
||||
// 只保留字母、数字和下划线
|
||||
name = name.replaceAll(RegExp(r'[^a-zA-Z0-9_]'), '');
|
||||
return name;
|
||||
}
|
||||
|
||||
/// 读取 Dart 文件中已定义的静态常量名(如 static const IconData xxx = ...)
|
||||
Set<String> getDefinedIconNames([String path = 'lib/src/yx_icon_fonts_data.dart']) {
|
||||
final file = File(path);
|
||||
if (!file.existsSync()) return {};
|
||||
final content = file.readAsStringSync();
|
||||
final reg = RegExp(r'static const IconData (\w+) =');
|
||||
return reg.allMatches(content).map((m) => m.group(1)!).toSet();
|
||||
}
|
||||
|
|
@ -1,29 +1,82 @@
|
|||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:test/test.dart';
|
||||
import 'package:yx_icon_fonts/yx_icon_fonts.dart';
|
||||
|
||||
void main() {
|
||||
group('YXIconFonts', () {
|
||||
test('should have valid icon data', () {
|
||||
// 测试图标常量是否存在且有效
|
||||
expect(YXIconFonts.iconMsgContacts, isNotNull);
|
||||
expect(YXIconFonts.iconMsgContacts.codePoint, isA<int>());
|
||||
expect(YXIconFonts.iconMsgContacts.fontFamily, equals('iconfont'));
|
||||
group('StringHelper', () {
|
||||
test('toCamelCase converts underscore to camelCase', () {
|
||||
expect(StringHelper.toCamelCase('icon_32_clean'), equals('icon32Clean'));
|
||||
expect(
|
||||
StringHelper.toCamelCase('icon_msg_contacts'),
|
||||
equals('iconMsgContacts'),
|
||||
);
|
||||
});
|
||||
|
||||
test('should create YXIcon widget', () {
|
||||
// 测试 YXIcon 组件创建
|
||||
final icon = YXIcon(YXIconFonts.iconMsgContacts);
|
||||
expect(icon, isNotNull);
|
||||
expect(icon.icon, equals(YXIconFonts.iconMsgContacts));
|
||||
test('toLegalDartName handles numeric prefix', () {
|
||||
expect(StringHelper.toLegalDartName('32_icon'), equals('_32Icon'));
|
||||
});
|
||||
|
||||
test('should have multiple icons defined', () {
|
||||
// 测试多个图标常量
|
||||
expect(YXIconFonts.iconMsgContacts, isNotNull);
|
||||
expect(YXIconFonts.iconMsgSearch, isNotNull);
|
||||
expect(YXIconFonts.icon44Edit, isNotNull);
|
||||
expect(YXIconFonts.icon44Delete, isNotNull);
|
||||
expect(YXIconFonts.icon44Add, isNotNull);
|
||||
test('toPascalCase converts to PascalCase', () {
|
||||
expect(StringHelper.toPascalCase('icon_class'), equals('IconClass'));
|
||||
});
|
||||
});
|
||||
|
||||
group('GeneratorConfig', () {
|
||||
test('fromMap creates config from map', () {
|
||||
final map = {
|
||||
'generator': {'name': 'Test'},
|
||||
'input': {
|
||||
'font_file': 'test.ttf',
|
||||
'json_file': 'test.json',
|
||||
'font_family': 'test',
|
||||
},
|
||||
'output': {
|
||||
'file_path': 'lib/icons.dart',
|
||||
'class_name': 'TestIcons',
|
||||
},
|
||||
};
|
||||
|
||||
final config = GeneratorConfig.fromMap(map);
|
||||
|
||||
expect(config.generator.name, equals('Test'));
|
||||
expect(config.input.fontFile, equals('test.ttf'));
|
||||
expect(config.input.jsonFile, equals('test.json'));
|
||||
expect(config.output.filePath, equals('lib/icons.dart'));
|
||||
expect(config.output.className, equals('TestIcons'));
|
||||
});
|
||||
|
||||
test('defaults creates default config', () {
|
||||
final config = GeneratorConfig.defaults();
|
||||
|
||||
expect(config.input.fontFamily, equals('iconfont'));
|
||||
expect(config.output.className, equals('AppIcons'));
|
||||
expect(config.output.generateDocs, isTrue);
|
||||
});
|
||||
});
|
||||
|
||||
group('IconParser', () {
|
||||
test('parseMap parses icon font metadata', () {
|
||||
final jsonData = {
|
||||
'id': '123',
|
||||
'name': 'Test Font',
|
||||
'font_family': 'testfont',
|
||||
'glyphs': [
|
||||
{
|
||||
'icon_id': '1',
|
||||
'name': 'icon_test',
|
||||
'font_class': 'icon_test',
|
||||
'unicode': 'e600',
|
||||
'unicode_decimal': 58880,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
final meta = IconParser.parseMap(jsonData);
|
||||
|
||||
expect(meta.name, equals('Test Font'));
|
||||
expect(meta.fontFamily, equals('testfont'));
|
||||
expect(meta.icons.length, equals(1));
|
||||
expect(meta.icons.first.name, equals('icon_test'));
|
||||
expect(meta.icons.first.unicode, equals('e600'));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue