init: 初始化项目

This commit is contained in:
Max 2025-07-10 10:53:56 +08:00
parent 2dea1dfb45
commit 079ec78755
24 changed files with 1956 additions and 0 deletions

6
analysis_options.yaml Normal file
View File

@ -0,0 +1,6 @@
include: package:lints/recommended.yaml
analyzer:
exclude:
- temp_font_awesome/**
- temp_font_awesome/**/*

45
example/.gitignore vendored Normal file
View File

@ -0,0 +1,45 @@
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.build/
.buildlog/
.history
.svn/
.swiftpm/
migrate_working_dir/
# IntelliJ related
*.iml
*.ipr
*.iws
.idea/
# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/
# Flutter/Dart/Pub related
**/doc/api/
**/ios/Flutter/.last_build_id
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.pub-cache/
.pub/
/build/
# Symbolication related
app.*.symbols
# Obfuscation related
app.*.map.json
# Android Studio will place build artifacts here
/android/app/debug
/android/app/profile
/android/app/release

30
example/.metadata Normal file
View File

@ -0,0 +1,30 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.
version:
revision: "8defaa71a77c16e8547abdbfad2053ce3a6e2d5b"
channel: "stable"
project_type: app
# Tracks metadata for the flutter migrate command
migration:
platforms:
- platform: root
create_revision: 8defaa71a77c16e8547abdbfad2053ce3a6e2d5b
base_revision: 8defaa71a77c16e8547abdbfad2053ce3a6e2d5b
- platform: ios
create_revision: 8defaa71a77c16e8547abdbfad2053ce3a6e2d5b
base_revision: 8defaa71a77c16e8547abdbfad2053ce3a6e2d5b
# User provided section
# List of Local paths (relative to this file) that should be
# ignored by the migrate tool.
#
# Files that are not part of the templates will be ignored by default.
unmanaged_files:
- 'lib/main.dart'
- 'ios/Runner.xcodeproj/project.pbxproj'

3
example/README.md Normal file
View File

@ -0,0 +1,3 @@
# yx_icon_fonts_example
A new Flutter project.

View File

@ -0,0 +1 @@
include: package:flutter_lints/flutter.yaml

View File

@ -0,0 +1,24 @@
import 'package:flutter/widgets.dart';
///
///
///
class ExampleIcon implements Comparable {
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);
}

85
example/lib/icons.dart Normal file
View File

@ -0,0 +1,85 @@
import 'package:yx_icon_fonts/yx_icon_fonts.dart';
import 'package:yx_icon_fonts_example/example_icon.dart';
//
final icons = <ExampleIcon>[
//
ExampleIcon(YXIconFonts.iconMsgContacts, 'icon msg contacts'),
ExampleIcon(YXIconFonts.iconMsgViedo, 'icon msg viedo'),
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 msgadd'),
ExampleIcon(YXIconFonts.icon56Msgface, 'icon 56 msgface'),
ExampleIcon(YXIconFonts.icon56Msgvoice, 'icon 56 msgvoice'),
//
ExampleIcon(YXIconFonts.icon32Arrowright, 'icon 32 arrowright'),
ExampleIcon(YXIconFonts.icon44Arrowleft, 'icon 44 arrowleft'),
ExampleIcon(YXIconFonts.icon44Arrowright, 'icon 44 arrowright'),
ExampleIcon(YXIconFonts.icon24Arrowleft, 'icon 24 arrowleft'),
ExampleIcon(YXIconFonts.icon24Arrowdown, 'icon 24 arrowdown'),
//
ExampleIcon(YXIconFonts.icon44Edit, 'icon 44 edit'),
ExampleIcon(YXIconFonts.icon36Editline, 'icon 36 editline'),
ExampleIcon(YXIconFonts.icon24Edit, 'icon 24 edit'),
//
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(YXIconFonts.icon24, 'icon 24 -'),
//
ExampleIcon(YXIconFonts.icon36Team, 'icon 36 team'),
ExampleIcon(YXIconFonts.icon32Student, 'icon 32 student'),
//
ExampleIcon(YXIconFonts.icon32Filter, 'icon 32 filter'),
ExampleIcon(YXIconFonts.icon36Question, 'icon 36 question'),
ExampleIcon(YXIconFonts.icon36Onlysee, 'icon 36 onlysee'),
ExampleIcon(YXIconFonts.icon36Hint, 'icon 36 hint'),
ExampleIcon(YXIconFonts.icon24Switch, 'icon 24 switch'),
// 退
ExampleIcon(YXIconFonts.icon44Quitlite, 'icon 44 quitlite'),
ExampleIcon(YXIconFonts.icon32Quit, 'icon 32 quit'),
ExampleIcon(YXIconFonts.icon44Quit, 'icon 44 quit'),
//
ExampleIcon(YXIconFonts.icon44More2, 'icon 44 more2'),
ExampleIcon(YXIconFonts.icon44More, 'icon 44 more'),
//
ExampleIcon(YXIconFonts.icon24Copy, 'icon 24 copy'),
//
ExampleIcon(YXIconFonts.icon44Delete, 'icon 44 delete'),
ExampleIcon(YXIconFonts.icon36Delete, 'icon 36 delete'),
ExampleIcon(YXIconFonts.icon24Delete, 'icon 24 delete'),
//
ExampleIcon(YXIconFonts.icon44Calendar, 'icon 44 calendar'),
//
ExampleIcon(YXIconFonts.icon44Share, 'icon 44 share'),
//
ExampleIcon(YXIconFonts.icon24Add, 'icon 24 add'),
ExampleIcon(YXIconFonts.icon44Add, 'icon 44 add'),
ExampleIcon(YXIconFonts.icon32Add, 'icon 32 add'),
//
ExampleIcon(YXIconFonts.icon44Keyboard, 'icon 44 keyboard'),
];

142
example/lib/main.dart Normal file
View File

@ -0,0 +1,142 @@
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() {
runApp(const YXIconFontsGalleryApp());
}
/// YX Icon Fonts
class YXIconFontsGalleryApp extends StatelessWidget {
const YXIconFontsGalleryApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'YX Icon Fonts Gallery',
theme: ThemeData.light().copyWith(
iconTheme: const IconThemeData(size: 36.0, color: Colors.black87),
textTheme: const TextTheme(
bodyMedium: TextStyle(fontSize: 16.0, color: Colors.black87),
),
),
home: const YXIconFontsGalleryHome(),
);
}
}
///
class YXIconFontsGalleryHome extends StatefulWidget {
const YXIconFontsGalleryHome({super.key});
@override
State<StatefulWidget> createState() => _YXIconFontsGalleryHomeState();
}
class _YXIconFontsGalleryHomeState extends State<YXIconFontsGalleryHome> {
var _searchTerm = "";
var _isSearching = false;
@override
Widget build(BuildContext context) {
final filteredIcons = icons.where((icon) => _searchTerm.isEmpty || icon.title.toLowerCase().contains(_searchTerm.toLowerCase())).toList();
return Scaffold(
appBar: _isSearching ? _searchBar(context) : _titleBar(),
body: Scrollbar(
thumbVisibility: kIsWeb,
child: GridView.builder(
itemCount: filteredIcons.length,
gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 180,
),
itemBuilder: (context, index) {
final icon = filteredIcons[index];
return InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute<void>(
builder: (BuildContext context) {
return GestureDetector(
onTap: () {
Navigator.of(context).pop();
},
child: Container(
color: Colors.white,
alignment: Alignment.center,
child: Hero(
tag: icon,
child: YXIcon(
icon.iconData,
size: 100,
),
),
),
);
},
),
);
},
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Hero(tag: icon, child: YXIcon(icon.iconData)),
Container(
padding: const EdgeInsets.only(top: 16.0),
child: Text(
icon.title,
style: Theme.of(context).textTheme.labelSmall?.copyWith(
color: Colors.black,
),
),
)
],
),
);
},
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
setState(() {
_isSearching = !_isSearching;
if (!_isSearching) _searchTerm = "";
});
},
child: Icon(_isSearching ? Icons.close : Icons.search),
),
);
}
PreferredSizeWidget _titleBar() {
return AppBar(
title: const Text('YX Icon Fonts Gallery'),
);
}
PreferredSizeWidget _searchBar(BuildContext context) {
return AppBar(
title: TextField(
autofocus: true,
decoration: const InputDecoration(hintText: '搜索图标...'),
onChanged: (value) {
setState(() {
_searchTerm = value;
});
},
),
leading: IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: () {
setState(() {
_isSearching = false;
_searchTerm = "";
});
},
),
);
}
}

212
example/pubspec.lock Normal file
View File

@ -0,0 +1,212 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
async:
dependency: transitive
description:
name: async
sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.13.0"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.2"
characters:
dependency: transitive
description:
name: characters
sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803
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"
collection:
dependency: transitive
description:
name: collection
sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.19.1"
fake_async:
dependency: transitive
description:
name: fake_async
sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.3.3"
flutter:
dependency: "direct main"
description: flutter
source: sdk
version: "0.0.0"
flutter_lints:
dependency: "direct dev"
description:
name: flutter_lints
sha256: "9e8c3858111da373efc5aa341de011d9bd23e2c5c5e0c62bccf32438e192d7b1"
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: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0"
url: "https://pub.flutter-io.cn"
source: hosted
version: "10.0.9"
leak_tracker_flutter_testing:
dependency: transitive
description:
name: leak_tracker_flutter_testing
sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.0.9"
leak_tracker_testing:
dependency: transitive
description:
name: leak_tracker_testing
sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.0.1"
lints:
dependency: transitive
description:
name: lints
sha256: cbf8d4b858bb0134ef3ef87841abdf8d63bfc255c266b7bf6b39daa1085c4290
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.0.0"
matcher:
dependency: transitive
description:
name: matcher
sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2
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:
name: meta
sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.16.0"
path:
dependency: transitive
description:
name: path
sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.9.1"
sky_engine:
dependency: transitive
description: flutter
source: sdk
version: "0.0.0"
source_span:
dependency: transitive
description:
name: source_span
sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.10.1"
stack_trace:
dependency: transitive
description:
name: stack_trace
sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.12.1"
stream_channel:
dependency: transitive
description:
name: stream_channel
sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.4"
string_scanner:
dependency: transitive
description:
name: string_scanner
sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.4.1"
term_glyph:
dependency: transitive
description:
name: term_glyph
sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.2.2"
test_api:
dependency: transitive
description:
name: test_api
sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.7.4"
vector_math:
dependency: transitive
description:
name: vector_math
sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.4"
vm_service:
dependency: transitive
description:
name: vm_service
sha256: ddfa8d30d89985b96407efce8acbdd124701f96741f2d981ca860662f1c0dc02
url: "https://pub.flutter-io.cn"
source: hosted
version: "15.0.0"
yx_icon_fonts:
dependency: "direct main"
description:
path: ".."
relative: true
source: path
version: "1.0.0"
sdks:
dart: ">=3.7.0-0 <4.0.0"
flutter: ">=3.18.0-18.0.pre.54"

22
example/pubspec.yaml Normal file
View File

@ -0,0 +1,22 @@
name: yx_icon_fonts_example
description: 学习官OA系统图标字体库示例应用
publish_to: 'none'
version: 1.0.0+1
environment:
sdk: '>=3.0.0 <4.0.0'
dependencies:
flutter:
sdk: flutter
yx_icon_fonts:
path: ../
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^3.0.0
flutter:
uses-material-design: true

BIN
fonts/iconfont.ttf Normal file

Binary file not shown.

137
generate.sh Normal file
View File

@ -0,0 +1,137 @@
#!/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
}
# 生成图标数据
generate_icons() {
print_info "正在生成图标数据..."
dart scripts/generate_icons.dart
print_success "图标数据生成完成"
}
# 生成示例文件
generate_example() {
print_info "正在生成示例文件..."
dart scripts/generate_example.dart
print_success "示例文件生成完成"
}
# 生成所有文件
generate_all() {
print_info "开始生成所有文件..."
echo
generate_icons
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 " example 只生成示例文件 (example/lib/icons.dart)"
echo " all 生成所有文件 (默认)"
echo " help 显示此帮助信息"
echo
echo "示例:"
echo " $0 # 生成所有文件"
echo " $0 icons # 只生成图标数据"
echo " $0 example # 只生成示例文件"
echo
}
# 主函数
main() {
local action=${1:-all}
case $action in
"icons")
check_dart
check_files
generate_icons
;;
"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 "$@"

359
iconfont.json Normal file
View File

@ -0,0 +1,359 @@
{
"id": "4944890",
"name": "学习官OA系统",
"font_family": "iconfont",
"css_prefix_text": "",
"description": "学习官OA系统图标",
"glyphs": [
{
"icon_id": "44661359",
"name": "icon_msg_contacts",
"font_class": "icon_msg_contacts",
"unicode": "e644",
"unicode_decimal": 58948
},
{
"icon_id": "44659960",
"name": "icon_msg_viedo",
"font_class": "icon_msg_viedo",
"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_arrowright",
"font_class": "icon_32_arrowright",
"unicode": "e61d",
"unicode_decimal": 58909
},
{
"icon_id": "44625451",
"name": "icon_44_edit",
"font_class": "icon_44_edit",
"unicode": "e638",
"unicode_decimal": 58936
},
{
"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_-",
"font_class": "icon_24_-",
"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_quitlite",
"font_class": "icon_44_quitlite",
"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_onlysee",
"font_class": "icon_36_onlysee",
"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": "44625449",
"name": "icon_44_delete",
"font_class": "icon_44_delete",
"unicode": "e62f",
"unicode_decimal": 58927
},
{
"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_arrowleft",
"font_class": "icon_44_arrowleft",
"unicode": "e62a",
"unicode_decimal": 58922
},
{
"icon_id": "44572499",
"name": "icon_36_editline",
"font_class": "icon_36_editline",
"unicode": "e62b",
"unicode_decimal": 58923
},
{
"icon_id": "44572515",
"name": "icon_44_arrowright",
"font_class": "icon_44_arrowright",
"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_msgadd",
"font_class": "icon_56_msgadd",
"unicode": "e624",
"unicode_decimal": 58916
},
{
"icon_id": "44572511",
"name": "icon_56_msgface",
"font_class": "icon_56_msgface",
"unicode": "e625",
"unicode_decimal": 58917
},
{
"icon_id": "44572516",
"name": "icon_56_msgvoice",
"font_class": "icon_56_msgvoice",
"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_+",
"font_class": "a-icon_24_",
"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_arrowright(1)",
"font_class": "a-icon_44_arrowright1",
"unicode": "e61c",
"unicode_decimal": 58908
},
{
"icon_id": "44572493",
"name": "icon_24_arrowleft",
"font_class": "icon_24_arrowleft",
"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_arrowdown",
"font_class": "icon_24_arrowdown",
"unicode": "e621",
"unicode_decimal": 58913
}
]
}

20
lib/main.dart Normal file
View File

@ -0,0 +1,20 @@
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!'),
),
),
);
}
}

118
lib/src/yx_icon.dart Normal file
View File

@ -0,0 +1,118 @@
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));
}
}

15
lib/src/yx_icon_data.dart Normal file
View File

@ -0,0 +1,15 @@
import 'package:flutter/widgets.dart';
/// OA系统图标数据类
///
/// IconData
class YXIconData extends IconData {
///
///
/// [codePoint] Unicode码点
const YXIconData(super.codePoint)
: super(
fontFamily: 'iconfont',
fontPackage: 'yx_icon_fonts',
);
}

View File

@ -0,0 +1,262 @@
import 'package:flutter/widgets.dart';
import 'yx_icon_data.dart';
/// OA系统图标字体数据
///
/// Flutter Icon 使
/// 使 YXIcon
class YXIconFonts {
//
YXIconFonts._();
/// icon_msg_contacts
///
/// Unicode: e644
static const IconData iconMsgContacts = YXIconData(0xe644);
/// icon_msg_viedo
///
/// Unicode: e63e
static const IconData iconMsgViedo = 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_arrowright
///
/// Unicode: e61d
static const IconData icon32Arrowright = YXIconData(0xe61d);
/// icon_44_edit
///
/// Unicode: e638
static const IconData icon44Edit = YXIconData(0xe638);
/// 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_-
///
/// Unicode: e63b
static const IconData icon24 = 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_quitlite
///
/// 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_onlysee
///
/// 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_44_delete
///
/// Unicode: e62f
static const IconData icon44Delete = YXIconData(0xe62f);
/// 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_arrowleft
///
/// Unicode: e62a
static const IconData icon44Arrowleft = YXIconData(0xe62a);
/// icon_36_editline
///
/// Unicode: e62b
static const IconData icon36Editline = YXIconData(0xe62b);
/// icon_44_arrowright
///
/// Unicode: e622
static const IconData icon44Arrowright = YXIconData(0xe622);
/// icon_24_delete
///
/// Unicode: e623
static const IconData icon24Delete = YXIconData(0xe623);
/// icon_56_msgadd
///
/// Unicode: e624
static const IconData icon56Msgadd = YXIconData(0xe624);
/// icon_56_msgface
///
/// Unicode: e625
static const IconData icon56Msgface = YXIconData(0xe625);
/// icon_56_msgvoice
///
/// 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_+
///
/// 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_arrowright(1)
///
/// Unicode: e61c
static const IconData icon44Arrowright1 = YXIconData(0xe61c);
/// icon_24_arrowleft
///
/// Unicode: e61e
static const IconData icon24Arrowleft = 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_arrowdown
///
/// Unicode: e621
static const IconData icon24Arrowdown = YXIconData(0xe621);
}

26
lib/yx_icon_fonts.dart Normal file
View File

@ -0,0 +1,26 @@
library yx_icon_fonts;
//
export 'src/yx_icon.dart';
export 'src/yx_icon_data.dart';
export 'src/yx_icon_fonts_data.dart';
/// OA系统图标字体库
///
/// OA系统的图标字体支持
///
/// ## 使
///
/// ```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: () {},
/// )
/// ```

205
pubspec.lock Normal file
View File

@ -0,0 +1,205 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
async:
dependency: transitive
description:
name: async
sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.13.0"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.2"
characters:
dependency: transitive
description:
name: characters
sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803
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"
collection:
dependency: transitive
description:
name: collection
sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.19.1"
fake_async:
dependency: transitive
description:
name: fake_async
sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.3.3"
flutter:
dependency: "direct main"
description: flutter
source: sdk
version: "0.0.0"
flutter_lints:
dependency: "direct dev"
description:
name: flutter_lints
sha256: "9e8c3858111da373efc5aa341de011d9bd23e2c5c5e0c62bccf32438e192d7b1"
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: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0"
url: "https://pub.flutter-io.cn"
source: hosted
version: "10.0.9"
leak_tracker_flutter_testing:
dependency: transitive
description:
name: leak_tracker_flutter_testing
sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.0.9"
leak_tracker_testing:
dependency: transitive
description:
name: leak_tracker_testing
sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.0.1"
lints:
dependency: transitive
description:
name: lints
sha256: cbf8d4b858bb0134ef3ef87841abdf8d63bfc255c266b7bf6b39daa1085c4290
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.0.0"
matcher:
dependency: transitive
description:
name: matcher
sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2
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:
name: meta
sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.16.0"
path:
dependency: transitive
description:
name: path
sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.9.1"
sky_engine:
dependency: transitive
description: flutter
source: sdk
version: "0.0.0"
source_span:
dependency: transitive
description:
name: source_span
sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.10.1"
stack_trace:
dependency: transitive
description:
name: stack_trace
sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.12.1"
stream_channel:
dependency: transitive
description:
name: stream_channel
sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.4"
string_scanner:
dependency: transitive
description:
name: string_scanner
sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.4.1"
term_glyph:
dependency: transitive
description:
name: term_glyph
sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.2.2"
test_api:
dependency: transitive
description:
name: test_api
sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.7.4"
vector_math:
dependency: transitive
description:
name: vector_math
sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.4"
vm_service:
dependency: transitive
description:
name: vm_service
sha256: ddfa8d30d89985b96407efce8acbdd124701f96741f2d981ca860662f1c0dc02
url: "https://pub.flutter-io.cn"
source: hosted
version: "15.0.0"
sdks:
dart: ">=3.7.0-0 <4.0.0"
flutter: ">=3.18.0-18.0.pre.54"

23
pubspec.yaml Normal file
View File

@ -0,0 +1,23 @@
name: yx_icon_fonts
description: 学习官OA系统图标字体库基于iconfont.ttf和iconfont.json生成
version: 1.0.0
homepage: https://github.com/your-username/yx_icon_fonts
environment:
sdk: '>=3.0.0 <4.0.0'
flutter: ">=3.0.0"
dependencies:
flutter:
sdk: flutter
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^3.0.0
flutter:
fonts:
- family: iconfont
fonts:
- asset: fonts/iconfont.ttf

View File

@ -0,0 +1,96 @@
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('_', ' ');
}

View File

@ -0,0 +1,48 @@
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} 个图标常量');
}

48
scripts/utils.dart Normal file
View File

@ -0,0 +1,48 @@
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();
}

View File

@ -0,0 +1,29 @@
import 'package:flutter_test/flutter_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'));
});
test('should create YXIcon widget', () {
// YXIcon
final icon = YXIcon(YXIconFonts.iconMsgContacts);
expect(icon, isNotNull);
expect(icon.icon, equals(YXIconFonts.iconMsgContacts));
});
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);
});
});
}