鸿蒙flutter第三方库适配 - 批量重命名工具
运行效果图批量重命名工具是一款专注于文件批量管理的实用工具应用,旨在帮助用户高效地重命名大量文件。应用支持多种重命名规则、实时预览对比、一键撤销操作,让文件管理变得轻松便捷。应用以优雅紫色为主色调,象征创意与效率。涵盖规则设置、文件预览、批量执行、历史记录四大核心模块。用户可以设置前缀后缀、查找替换、序号命名、日期命名等多种规则,实时预览重命名效果,一键执行批量操作。序号规则类型图标描述示例1添加
批量重命名工具应用
欢迎加入开源鸿蒙跨平台社区:
https://openharmonycrossplatform.csdn.net
适配的第三方库地址:
- file_selector: https://pub.dev/packages/file_selector
- cross_file: https://pub.dev/packages/cross_file
- shared_preferences: https://pub.dev/packages/shared_preferences
- animations: https://pub.dev/packages/animations
一、项目概述
运行效果图


1.1 应用简介
批量重命名工具是一款专注于文件批量管理的实用工具应用,旨在帮助用户高效地重命名大量文件。应用支持多种重命名规则、实时预览对比、一键撤销操作,让文件管理变得轻松便捷。
应用以优雅紫色为主色调,象征创意与效率。涵盖规则设置、文件预览、批量执行、历史记录四大核心模块。用户可以设置前缀后缀、查找替换、序号命名、日期命名等多种规则,实时预览重命名效果,一键执行批量操作。
1.2 核心功能
| 功能模块 | 功能描述 | 实现方式 |
|---|---|---|
| 文件选择 | 选择需要重命名的文件 | 文件选择器 |
| 规则设置 | 设置重命名规则模板 | 规则引擎 |
| 实时预览 | 预览重命名前后对比 | UI渲染 |
| 批量执行 | 一键执行重命名操作 | 文件操作 |
| 撤销操作 | 撤销最近的重命名操作 | 历史记录 |
| 冲突检测 | 检测文件名冲突 | 算法检测 |
| 规则保存 | 保存常用重命名规则 | 本地存储 |
| 历史记录 | 查看操作历史记录 | 数据存储 |
1.3 重命名规则定义
| 序号 | 规则类型 | 图标 | 描述 | 示例 |
|---|---|---|---|---|
| 1 | 添加前缀 | ➕ | 在文件名前添加指定文本 | file → new_file |
| 2 | 添加后缀 | ➕ | 在文件名后添加指定文本 | file → file_backup |
| 3 | 查找替换 | 🔍 | 查找并替换指定文本 | IMG → Photo |
| 4 | 序号命名 | 🔢 | 按序号批量命名 | 001, 002, 003… |
| 5 | 日期命名 | 📅 | 使用日期作为文件名 | 20240115 |
| 6 | 大小写转换 | 🔤 | 转换文件名大小写 | FILE → file |
| 7 | 删除字符 | ❌ | 删除指定数量字符 | filename → name |
| 8 | 修改扩展名 | 📎 | 批量修改文件扩展名 | .txt → .md |
1.4 大小写转换类型
| 序号 | 转换类型 | 描述 | 示例 |
|---|---|---|---|
| 1 | 全部大写 | 所有字母转为大写 | file → FILE |
| 2 | 全部小写 | 所有字母转为小写 | FILE → file |
| 3 | 首字母大写 | 首字母大写其余小写 | file → File |
| 4 | 句首大写 | 每个单词首字母大写 | my file → My File |
1.5 日期格式定义
| 序号 | 格式代码 | 示例输出 | 描述 |
|---|---|---|---|
| 1 | yyyyMMdd | 20240115 | 年月日 |
| 2 | yyyy-MM-dd | 2024-01-15 | 年-月-日 |
| 3 | yyyyMMdd_HHmmss | 20240115_143025 | 年月日_时分秒 |
| 4 | MMdd | 0115 | 月日 |
1.6 序号格式定义
| 序号 | 位数 | 示例 | 描述 |
|---|---|---|---|
| 1 | 2位 | 01, 02, 03… | 01-99 |
| 2 | 3位 | 001, 002, 003… | 001-999 |
| 3 | 4位 | 0001, 0002, 0003… | 0001-9999 |
1.7 技术栈
| 技术领域 | 技术选型 | 版本要求 |
|---|---|---|
| 开发框架 | Flutter | >= 3.0.0 |
| 编程语言 | Dart | >= 2.17.0 |
| 设计规范 | Material Design 3 | - |
| 状态管理 | StatefulWidget | - |
| 文件选择 | File Selector | >= 1.0.0 |
| 文件操作 | Cross File | >= 1.0.0 |
| 规则存储 | SharedPreferences | >= 2.0.0 |
| 动画效果 | Animations | >= 2.0.0 |
| 目标平台 | 鸿蒙OS / Web | API 21+ |
1.8 项目结构
lib/
└── main_batch_rename.dart
├── BatchRenameApp # 应用入口
├── RenameRuleType # 重命名规则枚举
├── CaseType # 大小写类型枚举
├── FileItem # 文件项模型
├── RenameRule # 重命名规则模型
├── RenameHistory # 操作历史模型
├── BatchRenameHomePage # 主页面
├── _buildRulePanel # 规则面板
├── _buildMainPanel # 主面板
└── _buildFileList # 文件列表
二、系统架构
2.1 整体架构图
2.2 类图设计
2.3 页面导航流程
2.4 重命名执行流程
三、核心模块设计
3.1 数据模型设计
3.1.1 重命名规则枚举 (RenameRuleType)
enum RenameRuleType {
prefix('添加前缀', Icons.add_circle_outline),
suffix('添加后缀', Icons.add_circle),
replace('查找替换', Icons.find_replace),
sequence('序号命名', Icons.format_list_numbered),
date('日期命名', Icons.calendar_today),
caseChange('大小写转换', Icons.text_fields),
remove('删除字符', Icons.remove_circle_outline),
extension('修改扩展名', Icons.attachment);
final String label;
final IconData icon;
const RenameRuleType(this.label, this.icon);
}
3.1.2 文件项模型 (FileItem)
class FileItem {
final String id;
final String originalName;
final String newName;
final String extension;
final int size;
final DateTime modifiedTime;
final bool isSelected;
final bool hasConflict;
const FileItem({
required this.id,
required this.originalName,
required this.newName,
required this.extension,
required this.size,
required this.modifiedTime,
required this.isSelected,
required this.hasConflict,
});
FileItem copyWith({
String? newName,
bool? isSelected,
bool? hasConflict,
}) {
return FileItem(
id: id,
originalName: originalName,
newName: newName ?? this.newName,
extension: extension,
size: size,
modifiedTime: modifiedTime,
isSelected: isSelected ?? this.isSelected,
hasConflict: hasConflict ?? this.hasConflict,
);
}
String get displayName => '$newName$extension';
String get originalFullName => '$originalName$extension';
}
3.1.3 重命名规则模型 (RenameRule)
class RenameRule {
final RenameRuleType type;
final String? prefix;
final String? suffix;
final String? findText;
final String? replaceText;
final int? startIndex;
final int? step;
final int? digits;
final String? dateFormat;
final CaseType? caseType;
final int? removeCount;
final bool? removeFromStart;
final String? newExtension;
String apply(String originalName, int index) {
String result = originalName;
switch (type) {
case RenameRuleType.prefix:
result = '${prefix ?? ''}$result';
break;
case RenameRuleType.suffix:
result = '$result${suffix ?? ''}';
break;
case RenameRuleType.replace:
result = result.replaceAll(findText ?? '', replaceText ?? '');
break;
case RenameRuleType.sequence:
final start = startIndex ?? 1;
final stepVal = step ?? 1;
final digitCount = digits ?? 3;
final number = start + (index * stepVal);
result = number.toString().padLeft(digitCount, '0');
break;
// ... 其他规则
}
return result;
}
}
3.1.4 规则使用分布
3.2 页面结构设计
3.2.1 主页面布局
3.2.2 规则面板结构
3.2.3 文件列表结构
3.3 规则应用逻辑
3.4 冲突检测逻辑
四、UI设计规范
4.1 配色方案
应用以优雅紫色为主色调,象征创意与效率:
| 颜色类型 | 色值 | 用途 |
|---|---|---|
| 主色 | #9C27B0 (Purple) | 导航、主题元素 |
| 辅助色 | #BA68C8 | 卡片背景 |
| 第三色 | #CE93D8 | 进度条背景 |
| 强调色 | #E1BEE7 | 分组页面 |
| 背景色 | #FAFAFA | 页面背景 |
| 卡片背景 | #FFFFFF | 信息卡片 |
| 成功色 | #4CAF50 | 重命名成功 |
| 冲突色 | #F44336 | 文件名冲突 |
4.2 状态配色
| 状态 | 色值 | 视觉效果 |
|---|---|---|
| 未修改 | 默认 | 白色背景 |
| 已修改 | #E8F5E9 | 浅绿背景 |
| 冲突 | #FFEBEE | 浅红背景 |
| 选中 | #F3E5F5 | 浅紫背景 |
4.3 字体规范
| 元素 | 字号 | 字重 | 颜色 |
|---|---|---|---|
| 页面标题 | 20px | Bold | 主色 |
| 规则名称 | 16px | Medium | #000000 |
| 文件名 | 14px | Regular | #000000 |
| 提示文字 | 12px | Regular | #666666 |
| 冲突提示 | 12px | Medium | #F44336 |
4.4 组件规范
4.4.1 规则面板
┌─────────────────────────────────────┐
│ ✏️ 重命名规则 │
├─────────────────────────────────────┤
│ ┌─────────────────────────────┐ │
│ │ ➕ 添加前缀 │ │
│ └─────────────────────────────┘ │
│ ┌─────────────────────────────┐ │
│ │ ➕ 添加后缀 │ │
│ └─────────────────────────────┘ │
│ ┌─────────────────────────────┐ │
│ │ 🔍 查找替换 │ │
│ └─────────────────────────────┘ │
│ ... │
├─────────────────────────────────────┤
│ ┌─────────────────────────────┐ │
│ │ ✓ 执行重命名 │ │
│ └─────────────────────────────┘ │
│ ┌─────────────────────────────┐ │
│ │ ↻ 重置 │ │
│ └─────────────────────────────┘ │
└─────────────────────────────────────┘
4.4.2 文件列表项
┌─────────────────────────────────────────────────────────┐
│ ☑ IMG001.jpg → Photo001.jpg ✓ 2.5 MB 1/15 │
│ (删除线) (绿色加粗) │
└─────────────────────────────────────────────────────────┘
4.4.3 冲突提示
┌─────────────────────────────────────────────────────────┐
│ ☑ file.txt → newfile.txt ⚠ 1.2 MB 1/15 │
│ (删除线) (红色警告) │
└─────────────────────────────────────────────────────────┘
4.4.4 规则配置面板
┌─────────────────────────────────────┐
│ ➕ 添加前缀 │
│ ───────────────────────────────── │
│ ┌─────────────────────────────┐ │
│ │ 前缀内容 │ │
│ │ 输入要添加的前缀 │ │
│ └─────────────────────────────┘ │
│ │
│ ┌─────────────────────────────┐ │
│ │ 应用规则 │ │
│ └─────────────────────────────┘ │
└─────────────────────────────────────┘
五、核心功能实现
5.1 规则引擎实现
class RuleEngine {
String applyRule(RenameRule rule, String originalName, int index) {
String result = originalName;
switch (rule.type) {
case RenameRuleType.prefix:
result = '${rule.prefix ?? ''}$result';
break;
case RenameRuleType.suffix:
result = '$result${rule.suffix ?? ''}';
break;
case RenameRuleType.replace:
result = result.replaceAll(rule.findText ?? '', rule.replaceText ?? '');
break;
case RenameRuleType.sequence:
final start = rule.startIndex ?? 1;
final step = rule.step ?? 1;
final digits = rule.digits ?? 3;
final number = start + (index * step);
result = number.toString().padLeft(digits, '0');
break;
case RenameRuleType.date:
result = _formatDate(rule.dateFormat ?? 'yyyyMMdd');
break;
case RenameRuleType.caseChange:
result = _applyCaseChange(result, rule.caseType);
break;
case RenameRuleType.remove:
result = _removeChars(result, rule.removeCount ?? 0, rule.removeFromStart ?? true);
break;
case RenameRuleType.extension:
break;
}
return result;
}
String _formatDate(String format) {
final now = DateTime.now();
return format
.replaceAll('yyyy', now.year.toString())
.replaceAll('MM', now.month.toString().padLeft(2, '0'))
.replaceAll('dd', now.day.toString().padLeft(2, '0'))
.replaceAll('HH', now.hour.toString().padLeft(2, '0'))
.replaceAll('mm', now.minute.toString().padLeft(2, '0'))
.replaceAll('ss', now.second.toString().padLeft(2, '0'));
}
String _applyCaseChange(String text, CaseType? caseType) {
switch (caseType) {
case CaseType.upper:
return text.toUpperCase();
case CaseType.lower:
return text.toLowerCase();
case CaseType.capitalize:
return text.isNotEmpty ? text[0].toUpperCase() + text.substring(1) : text;
case CaseType.sentence:
return text.split(' ').map((word) {
return word.isNotEmpty ? word[0].toUpperCase() + word.substring(1).toLowerCase() : word;
}).join(' ');
default:
return text;
}
}
String _removeChars(String text, int count, bool fromStart) {
if (fromStart) {
return text.substring(count.clamp(0, text.length));
} else {
return text.substring(0, (text.length - count).clamp(0, text.length));
}
}
}
5.2 文件管理器实现
class FileManager {
final FileSelector _fileSelector = FileSelector();
List<FileItem> _files = [];
Future<void> selectFiles() async {
final result = await _fileSelector.openMultipleFiles();
for (final file in result) {
final stat = await file.stat();
_files.add(FileItem(
id: file.path,
originalName: file.nameWithoutExtension,
newName: file.nameWithoutExtension,
extension: file.extension,
size: stat.size,
modifiedTime: stat.modified,
isSelected: true,
hasConflict: false,
));
}
}
Future<void> renameFiles(List<FileItem> files) async {
for (final file in files) {
if (!file.isSelected) continue;
final oldPath = file.id;
final dir = p.dirname(oldPath);
final newPath = p.join(dir, file.displayName);
await File(oldPath).rename(newPath);
}
}
List<FileItem> get files => List.unmodifiable(_files);
}
5.3 冲突检测器实现
class ConflictDetector {
Map<String, List<FileItem>> detectConflicts(List<FileItem> files) {
final nameMap = <String, List<FileItem>>{};
for (final file in files) {
if (!file.isSelected) continue;
final fullName = file.displayName;
nameMap.putIfAbsent(fullName, () => []).add(file);
}
return Map.fromEntries(
nameMap.entries.where((entry) => entry.value.length > 1),
);
}
List<FileItem> markConflicts(List<FileItem> files) {
final conflicts = detectConflicts(files);
final conflictNames = conflicts.keys.toSet();
return files.map((file) {
return file.copyWith(
hasConflict: conflictNames.contains(file.displayName),
);
}).toList();
}
bool hasConflicts(List<FileItem> files) {
return detectConflicts(files).isNotEmpty;
}
}
5.4 历史管理器实现
class HistoryManager {
final SharedPreferences _prefs;
static const String _historyKey = 'rename_history';
HistoryManager(this._prefs);
Future<void> saveHistory(RenameHistory history) async {
final histories = await getHistories();
histories.insert(0, history);
if (histories.length > 50) {
histories.removeRange(50, histories.length);
}
final jsonList = histories.map((h) => h.toJson()).toList();
await _prefs.setString(_historyKey, jsonEncode(jsonList));
}
Future<List<RenameHistory>> getHistories() async {
final jsonString = _prefs.getString(_historyKey);
if (jsonString == null) return [];
final jsonList = jsonDecode(jsonString) as List;
return jsonList.map((json) => RenameHistory.fromJson(json)).toList();
}
Future<void> clearHistory() async {
await _prefs.remove(_historyKey);
}
Future<void> removeHistory(String historyId) async {
final histories = await getHistories();
histories.removeWhere((h) => h.id == historyId);
final jsonList = histories.map((h) => h.toJson()).toList();
await _prefs.setString(_historyKey, jsonEncode(jsonList));
}
}
5.5 规则存储实现
class RuleStorage {
final SharedPreferences _prefs;
static const String _rulesKey = 'saved_rules';
RuleStorage(this._prefs);
Future<void> saveRule(String name, RenameRule rule) async {
final rules = await getSavedRules();
rules[name] = rule;
final jsonMap = rules.map((key, value) => MapEntry(key, value.toJson()));
await _prefs.setString(_rulesKey, jsonEncode(jsonMap));
}
Future<Map<String, RenameRule>> getSavedRules() async {
final jsonString = _prefs.getString(_rulesKey);
if (jsonString == null) return {};
final jsonMap = jsonDecode(jsonString) as Map<String, dynamic>;
return jsonMap.map((key, value) => MapEntry(key, RenameRule.fromJson(value)));
}
Future<void> deleteRule(String name) async {
final rules = await getSavedRules();
rules.remove(name);
final jsonMap = rules.map((key, value) => MapEntry(key, value.toJson()));
await _prefs.setString(_rulesKey, jsonEncode(jsonMap));
}
}
六、交互设计
6.1 规则应用流程
6.2 执行重命名流程
6.3 撤销操作流程
七、扩展功能规划
7.1 后续版本规划
7.2 功能扩展建议
7.2.1 高级规则
规则功能:
- 正则表达式匹配
- 条件判断规则
- 组合规则应用
- 自定义脚本
7.2.2 文件管理
管理功能:
- 文件夹批量重命名
- 文件移动复制
- 文件分类整理
- 重复文件检测
7.2.3 云端同步
同步功能:
- 规则云端备份
- 多设备同步
- 规则分享
- 模板市场
八、注意事项
8.1 开发注意事项
-
文件权限:正确申请文件读写权限
-
数据安全:重命名前备份原始数据
-
冲突处理:确保正确处理文件名冲突
-
性能优化:大量文件时优化处理效率
-
撤销功能:确保撤销操作可靠执行
8.2 常见问题
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 文件名冲突 | 新名称重复 | 自动添加序号 |
| 权限不足 | 未获取权限 | 引导用户授权 |
| 文件占用 | 文件被其他程序使用 | 提示关闭程序 |
| 撤销失败 | 原文件已删除 | 提示无法撤销 |
| 规则无效 | 参数设置错误 | 验证规则参数 |
8.3 使用技巧
📝 批量重命名工具使用技巧 📝
规则设置
- 保存常用规则模板
- 组合使用多种规则
- 预览后再执行
- 注意文件名冲突
文件管理
- 按类型分类处理
- 先小批量测试
- 保留原始文件备份
- 定期清理历史记录
效率提升
- 使用快捷键操作
- 善用规则模板
- 批量选择文件
- 利用撤销功能
九、运行说明
9.1 环境要求
| 环境 | 版本要求 |
|---|---|
| Flutter SDK | >= 3.0.0 |
| Dart SDK | >= 2.17.0 |
| 鸿蒙OS | API 21+ |
| Android | API 21+ |
| iOS | 12.0+ |
| Web浏览器 | Chrome 90+ |
9.2 依赖配置
在 pubspec.yaml 中添加以下依赖:
dependencies:
flutter:
sdk: flutter
file_selector: ^1.0.0
cross_file: ^1.0.0
shared_preferences: ^2.0.0
animations: ^2.0.0
path: ^1.8.0
path_provider: ^2.0.0
9.3 权限配置
Android (android/app/src/main/AndroidManifest.xml):
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
iOS (ios/Runner/Info.plist):
<key>NSDocumentsFolderUsageDescription</key>
<string>需要访问文档文件夹以重命名文件</string>
<key>NSDownloadsFolderUsageDescription</key>
<string>需要访问下载文件夹以重命名文件</string>
9.4 运行命令
# 查看可用设备
flutter devices
# 运行到Web服务器
flutter run -d web-server -t lib/main_batch_rename.dart --web-port 8149
# 运行到鸿蒙设备
flutter run -d 127.0.0.1:5555 -t lib/main_batch_rename.dart
# 运行到Android设备
flutter run -d android -t lib/main_batch_rename.dart
# 代码分析
flutter analyze lib/main_batch_rename.dart
十、总结
批量重命名工具应用通过多种重命名规则、实时预览对比、一键撤销操作,帮助用户高效地重命名大量文件。应用支持添加前缀、添加后缀、查找替换、序号命名、日期命名、大小写转换、删除字符、修改扩展名8种重命名规则,满足用户多样化的文件管理需求。
应用采用 Material Design 3 设计规范,以优雅紫色为主色调,象征创意与效率。通过本应用,希望能够帮助用户轻松管理文件,让批量重命名变得简单高效。
批量重命名工具——高效管理您的文件
更多推荐



所有评论(0)