From 079ec78755a2d9a6c34c147e9a0ec308cfb71277 Mon Sep 17 00:00:00 2001 From: Max Date: Thu, 10 Jul 2025 10:53:56 +0800 Subject: [PATCH] =?UTF-8?q?init:=20=E5=88=9D=E5=A7=8B=E5=8C=96=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- analysis_options.yaml | 6 + example/.gitignore | 45 ++++ example/.metadata | 30 +++ example/README.md | 3 + example/analysis_options.yaml | 1 + example/lib/example_icon.dart | 24 +++ example/lib/icons.dart | 85 ++++++++ example/lib/main.dart | 142 +++++++++++++ example/pubspec.lock | 212 +++++++++++++++++++ example/pubspec.yaml | 22 ++ fonts/iconfont.ttf | Bin 0 -> 12656 bytes generate.sh | 137 ++++++++++++ iconfont.json | 359 ++++++++++++++++++++++++++++++++ lib/main.dart | 20 ++ lib/src/yx_icon.dart | 118 +++++++++++ lib/src/yx_icon_data.dart | 15 ++ lib/src/yx_icon_fonts_data.dart | 262 +++++++++++++++++++++++ lib/yx_icon_fonts.dart | 26 +++ pubspec.lock | 205 ++++++++++++++++++ pubspec.yaml | 23 ++ scripts/generate_example.dart | 96 +++++++++ scripts/generate_icons.dart | 48 +++++ scripts/utils.dart | 48 +++++ test/yx_icon_fonts_test.dart | 29 +++ 24 files changed, 1956 insertions(+) create mode 100644 analysis_options.yaml create mode 100644 example/.gitignore create mode 100644 example/.metadata create mode 100644 example/README.md create mode 100644 example/analysis_options.yaml create mode 100644 example/lib/example_icon.dart create mode 100644 example/lib/icons.dart create mode 100644 example/lib/main.dart create mode 100644 example/pubspec.lock create mode 100644 example/pubspec.yaml create mode 100644 fonts/iconfont.ttf create mode 100644 generate.sh create mode 100644 iconfont.json create mode 100644 lib/main.dart create mode 100644 lib/src/yx_icon.dart create mode 100644 lib/src/yx_icon_data.dart create mode 100644 lib/src/yx_icon_fonts_data.dart create mode 100644 lib/yx_icon_fonts.dart create mode 100644 pubspec.lock create mode 100644 pubspec.yaml create mode 100644 scripts/generate_example.dart create mode 100644 scripts/generate_icons.dart create mode 100644 scripts/utils.dart create mode 100644 test/yx_icon_fonts_test.dart diff --git a/analysis_options.yaml b/analysis_options.yaml new file mode 100644 index 0000000..33a5fb4 --- /dev/null +++ b/analysis_options.yaml @@ -0,0 +1,6 @@ +include: package:lints/recommended.yaml + +analyzer: + exclude: + - temp_font_awesome/** + - temp_font_awesome/**/* diff --git a/example/.gitignore b/example/.gitignore new file mode 100644 index 0000000..79c113f --- /dev/null +++ b/example/.gitignore @@ -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 diff --git a/example/.metadata b/example/.metadata new file mode 100644 index 0000000..cca80bc --- /dev/null +++ b/example/.metadata @@ -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' diff --git a/example/README.md b/example/README.md new file mode 100644 index 0000000..b374f0e --- /dev/null +++ b/example/README.md @@ -0,0 +1,3 @@ +# yx_icon_fonts_example + +A new Flutter project. diff --git a/example/analysis_options.yaml b/example/analysis_options.yaml new file mode 100644 index 0000000..f9b3034 --- /dev/null +++ b/example/analysis_options.yaml @@ -0,0 +1 @@ +include: package:flutter_lints/flutter.yaml diff --git a/example/lib/example_icon.dart b/example/lib/example_icon.dart new file mode 100644 index 0000000..02b5322 --- /dev/null +++ b/example/lib/example_icon.dart @@ -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); +} diff --git a/example/lib/icons.dart b/example/lib/icons.dart new file mode 100644 index 0000000..9792d3f --- /dev/null +++ b/example/lib/icons.dart @@ -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(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'), + +]; diff --git a/example/lib/main.dart b/example/lib/main.dart new file mode 100644 index 0000000..834ed4e --- /dev/null +++ b/example/lib/main.dart @@ -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 createState() => _YXIconFontsGalleryHomeState(); +} + +class _YXIconFontsGalleryHomeState extends State { + 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( + 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: [ + 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 = ""; + }); + }, + ), + ); + } +} diff --git a/example/pubspec.lock b/example/pubspec.lock new file mode 100644 index 0000000..a630b43 --- /dev/null +++ b/example/pubspec.lock @@ -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" diff --git a/example/pubspec.yaml b/example/pubspec.yaml new file mode 100644 index 0000000..6ded487 --- /dev/null +++ b/example/pubspec.yaml @@ -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 \ No newline at end of file diff --git a/fonts/iconfont.ttf b/fonts/iconfont.ttf new file mode 100644 index 0000000000000000000000000000000000000000..c964ade21f1b02bb4f8b58e45141ca56ac0a0b65 GIT binary patch literal 12656 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 XKysT@VM8yTz{a7I3uoag6hi(J_eVYh literal 0 HcmV?d00001 diff --git a/generate.sh b/generate.sh new file mode 100644 index 0000000..affeca0 --- /dev/null +++ b/generate.sh @@ -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 "$@" \ No newline at end of file diff --git a/iconfont.json b/iconfont.json new file mode 100644 index 0000000..4c26519 --- /dev/null +++ b/iconfont.json @@ -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 + } + ] +} diff --git a/lib/main.dart b/lib/main.dart new file mode 100644 index 0000000..a725658 --- /dev/null +++ b/lib/main.dart @@ -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!'), + ), + ), + ); + } +} diff --git a/lib/src/yx_icon.dart b/lib/src/yx_icon.dart new file mode 100644 index 0000000..dac3271 --- /dev/null +++ b/lib/src/yx_icon.dart @@ -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? 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? 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: '', showName: false)); + properties.add(DoubleProperty('size', size, defaultValue: null)); + properties.add(ColorProperty('color', color, defaultValue: null)); + properties.add(IterableProperty('shadows', shadows, defaultValue: null)); + } +} diff --git a/lib/src/yx_icon_data.dart b/lib/src/yx_icon_data.dart new file mode 100644 index 0000000..9ea9930 --- /dev/null +++ b/lib/src/yx_icon_data.dart @@ -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', + ); +} diff --git a/lib/src/yx_icon_fonts_data.dart b/lib/src/yx_icon_fonts_data.dart new file mode 100644 index 0000000..053329b --- /dev/null +++ b/lib/src/yx_icon_fonts_data.dart @@ -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); + +} diff --git a/lib/yx_icon_fonts.dart b/lib/yx_icon_fonts.dart new file mode 100644 index 0000000..9e7ef30 --- /dev/null +++ b/lib/yx_icon_fonts.dart @@ -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: () {}, +/// ) +/// ``` diff --git a/pubspec.lock b/pubspec.lock new file mode 100644 index 0000000..f490b88 --- /dev/null +++ b/pubspec.lock @@ -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" diff --git a/pubspec.yaml b/pubspec.yaml new file mode 100644 index 0000000..8ac2fd8 --- /dev/null +++ b/pubspec.yaml @@ -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 \ No newline at end of file diff --git a/scripts/generate_example.dart b/scripts/generate_example.dart new file mode 100644 index 0000000..bb13ccc --- /dev/null +++ b/scripts/generate_example.dart @@ -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 glyphs, Set 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 = ["); + + // 按类别分组图标 + final categories = >>{}; + 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('_', ' '); +} diff --git a/scripts/generate_icons.dart b/scripts/generate_icons.dart new file mode 100644 index 0000000..9a2f500 --- /dev/null +++ b/scripts/generate_icons.dart @@ -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 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} 个图标常量'); +} diff --git a/scripts/utils.dart b/scripts/utils.dart new file mode 100644 index 0000000..96d1abc --- /dev/null +++ b/scripts/utils.dart @@ -0,0 +1,48 @@ +import 'dart:convert'; +import 'dart:io'; + +/// 读取 iconfont.json 文件,返回解析后的 Map +Map 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; +} + +/// 获取 glyphs 列表 +List getGlyphs(Map iconData) { + return iconData['glyphs'] as List; +} + +/// 下划线转驼峰命名,并处理常见特殊字符,保证 Dart 标识符合法 +String toCamelCase(String input) { + String processedInput = input.replaceAll('-', '_').replaceAll('+', 'plus').replaceAll('(', '').replaceAll(')', '').replaceAll(' ', ''); + final List 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 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(); +} diff --git a/test/yx_icon_fonts_test.dart b/test/yx_icon_fonts_test.dart new file mode 100644 index 0000000..318dc02 --- /dev/null +++ b/test/yx_icon_fonts_test.dart @@ -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()); + 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); + }); + }); +}