Flutter 框架跨平台鸿蒙开发 - 篆刻石料记录应用开发教程
功能完整性石料档案管理使用记录追踪作品档案管理价值评估系统数据统计分析用户体验界面简洁美观操作流畅便捷信息展示清晰数据可视化技术实现代码结构清晰注释完整详细遵循最佳实践性能优化到位学习价值Flutter基础组件使用状态管理实践数据模型设计统计分析实现业务逻辑处理。
Flutter篆刻石料记录应用开发教程
项目简介
篆刻石料记录是一款专为篆刻爱好者和收藏家设计的石料管理应用,帮助用户系统化管理篆刻石料收藏、记录石料信息、追踪使用情况、管理作品档案。应用集成了石料档案管理、使用记录追踪、作品展示、价值评估、收藏统计等功能,为篆刻爱好者提供全方位的石料管理解决方案。
运行效果图



核心功能特性
- 石料档案管理:完整的石料信息录入,包含名称、产地、品种、尺寸、重量、颜色、纹理等
- 使用记录追踪:详细记录每次使用情况,包含作品信息、使用日期、剩余尺寸
- 作品档案管理:记录篆刻作品信息,关联使用的石料,保存作品照片
- 价值评估系统:记录购买价格、当前估值、升值情况
- 收藏分类管理:按产地、品种、价格等多维度分类管理
- 数据统计分析:全面的收藏统计,包含数量分析、价值统计、使用频率分析
技术架构
开发环境
- 框架:Flutter 3.x
- 开发语言:Dart
- UI组件:Material Design 3
- 状态管理:StatefulWidget + setState
- 动画效果:AnimationController + Tween
- 数据存储:本地存储 + SharedPreferences
项目结构
lib/
├── main.dart # 应用入口和主要逻辑
├── models/ # 数据模型
│ ├── stone.dart # 石料模型
│ ├── usage_record.dart # 使用记录模型
│ ├── artwork.dart # 作品模型
│ ├── category.dart # 分类模型
│ └── stats.dart # 统计数据模型
├── pages/ # 页面组件
│ ├── stones_page.dart # 石料列表页面
│ ├── records_page.dart # 使用记录页面
│ ├── artworks_page.dart # 作品展示页面
│ ├── categories_page.dart # 分类管理页面
│ └── stats_page.dart # 统计分析页面
└── widgets/ # 自定义组件
├── stone_card.dart # 石料卡片组件
├── artwork_card.dart # 作品卡片组件
└── stats_chart.dart # 统计图表组件
数据模型设计
石料模型(Stone)
石料模型是应用的核心数据结构,记录每块石料的详细信息:
class Stone {
final String id; // 石料唯一标识
final String name; // 石料名称
final String origin; // 产地:寿山、青田、昌化、巴林等
final String variety; // 品种:田黄、芙蓉、鸡血等
final StoneType type; // 类型:印章石、摆件石、雕刻石
final double length; // 长度(cm)
final double width; // 宽度(cm)
final double height; // 高度(cm)
final double weight; // 重量(g)
final String color; // 颜色描述
final String texture; // 质地描述
final String pattern; // 纹理描述
final double purchasePrice; // 购买价格
final DateTime purchaseDate; // 购买日期
final String purchaseFrom; // 购买来源
final double currentValue; // 当前估值
final StoneCondition condition; // 品相:完美/良好/一般/有瑕疵
final bool isUsed; // 是否已使用
final String storageLocation; // 存放位置
final List<String> photos; // 照片列表
final String notes; // 备注信息
final DateTime createdDate; // 创建日期
final bool isFavorite; // 是否收藏
}
enum StoneType {
seal, // 印章石
ornament, // 摆件石
carving // 雕刻石
}
enum StoneCondition {
perfect, // 完美
good, // 良好
fair, // 一般
flawed // 有瑕疵
}
使用记录模型(UsageRecord)
使用记录模型详细记录每次使用石料的完整信息:
class UsageRecord {
final String id; // 记录唯一标识
final String stoneId; // 关联石料ID
final String stoneName; // 石料名称
final DateTime usageDate; // 使用日期
final String purpose; // 使用目的:篆刻印章/雕刻作品/练习
final String artworkName; // 作品名称
final String content; // 篆刻内容
final String style; // 篆刻风格:汉印/流派印/肖形印等
final double usedLength; // 使用长度(cm)
final double usedWidth; // 使用宽度(cm)
final double usedHeight; // 使用高度(cm)
final double remainingLength; // 剩余长度(cm)
final double remainingWidth; // 剩余宽度(cm)
final double remainingHeight; // 剩余高度(cm)
final int duration; // 耗时(小时)
final String difficulty; // 难度:简单/中等/困难
final String satisfaction; // 满意度:非常满意/满意/一般/不满意
final List<String> photos; // 作品照片
final String notes; // 备注
final DateTime createdDate; // 创建日期
}
作品模型(Artwork)
作品模型记录篆刻作品的详细信息:
class Artwork {
final String id; // 作品唯一标识
final String name; // 作品名称
final String stoneId; // 关联石料ID
final String stoneName; // 石料名称
final String content; // 篆刻内容
final String style; // 篆刻风格
final ArtworkType type; // 作品类型:白文/朱文/朱白相间
final DateTime createDate; // 创建日期
final int duration; // 创作耗时(小时)
final String technique; // 技法描述
final double size; // 尺寸(边长cm)
final String description; // 作品描述
final List<String> photos; // 作品照片
final double rating; // 自评分(1-5)
final String exhibition; // 展览记录
final bool isForSale; // 是否出售
final double price; // 售价
final String notes; // 备注
final DateTime createdDate; // 记录创建日期
}
enum ArtworkType {
white, // 白文
red, // 朱文
mixed // 朱白相间
}
分类模型(Category)
分类模型用于组织和管理石料收藏:
class Category {
final String id; // 分类唯一标识
final String name; // 分类名称
final String description; // 分类描述
final CategoryType type; // 分类类型
final String icon; // 图标
final int stoneCount; // 石料数量
final DateTime createdDate; // 创建日期
}
enum CategoryType {
origin, // 按产地分类
variety, // 按品种分类
price, // 按价格分类
condition, // 按品相分类
custom // 自定义分类
}
统计数据模型(StoneStats)
统计数据模型汇总收藏的各项统计信息:
class StoneStats {
final int totalStones; // 石料总数
final int usedStones; // 已使用石料数
final int unusedStones; // 未使用石料数
final int totalArtworks; // 作品总数
final double totalValue; // 总价值
final double totalInvestment; // 总投资
final double appreciation; // 升值金额
final double appreciationRate; // 升值率
final Map<String, int> originDistribution; // 产地分布
final Map<String, int> varietyDistribution; // 品种分布
final Map<String, double> valueByOrigin; // 各产地价值
final Map<String, int> monthlyUsage; // 月度使用统计
final String mostUsedOrigin; // 最常用产地
final String mostValuableStone; // 最贵石料
final double averageStoneValue; // 平均石料价值
}
界面设计
主界面布局
应用采用底部导航栏设计,包含五个主要页面:
- 石料库:石料列表和详细信息展示
- 使用记录:石料使用历史记录
- 作品集:篆刻作品展示和管理
- 分类:石料分类管理
- 统计:收藏数据统计分析
色彩方案
- 主色调:深褐色系(#8D6E63)- 代表石料的质朴感
- 辅助色:
- 金色(#FFB74D)- 田黄等名贵石料
- 红色(#E57373)- 鸡血石
- 青色(#4DB6AC)- 青田石
- 灰色(#90A4AE)- 普通石料
状态指示设计
未使用 ● 绿色徽章 + "完整"文字
已使用 ● 橙色徽章 + "已用"文字
部分使用 ● 蓝色徽章 + "部分"文字
完全使用 ● 灰色徽章 + "用完"文字
核心功能实现
1. 石料列表展示
石料列表是应用的核心展示页面,支持多种视图模式和筛选功能:
顶部统计栏
- 显示石料总数、总价值、升值率
- 使用渐变背景和卡片布局
- 数字大字体突出显示
筛选和排序
- 按产地筛选(寿山、青田、昌化、巴林等)
- 按品种筛选(田黄、芙蓉、鸡血等)
- 按价格排序(从高到低/从低到高)
- 按购买日期排序
- 按使用状态筛选
石料卡片
Widget _buildStoneCard(Stone stone) {
return Card(
elevation: 2,
margin: EdgeInsets.only(bottom: 12),
child: InkWell(
onTap: () => _showStoneDetail(stone),
child: Padding(
padding: EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// 标题行:名称 + 状态徽章
Row(
children: [
Container(
width: 60,
height: 60,
decoration: BoxDecoration(
color: _getOriginColor(stone.origin).withOpacity(0.1),
borderRadius: BorderRadius.circular(8),
),
child: Icon(
_getStoneIcon(stone.type),
color: _getOriginColor(stone.origin),
size: 30,
),
),
SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(stone.name,
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
Text('${stone.origin} · ${stone.variety}',
style: TextStyle(color: Colors.grey, fontSize: 14)),
],
),
),
_buildUsageStatusBadge(stone.isUsed),
],
),
SizedBox(height: 12),
// 尺寸信息
Container(
padding: EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.grey.shade50,
borderRadius: BorderRadius.circular(8),
),
child: Row(
children: [
Icon(Icons.straighten, size: 16, color: Colors.grey.shade600),
SizedBox(width: 8),
Text('${stone.length}×${stone.width}×${stone.height}cm'),
SizedBox(width: 16),
Icon(Icons.scale, size: 16, color: Colors.grey.shade600),
SizedBox(width: 8),
Text('${stone.weight}g'),
],
),
),
SizedBox(height: 12),
// 价值信息
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('购买价格', style: TextStyle(fontSize: 12, color: Colors.grey)),
Text('¥${stone.purchasePrice.toStringAsFixed(0)}',
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
],
),
Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Text('当前估值', style: TextStyle(fontSize: 12, color: Colors.grey)),
Text('¥${stone.currentValue.toStringAsFixed(0)}',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: stone.currentValue > stone.purchasePrice
? Colors.green : Colors.red,
)),
],
),
if (stone.currentValue > stone.purchasePrice)
Container(
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration(
color: Colors.green.withOpacity(0.1),
borderRadius: BorderRadius.circular(12),
),
child: Row(
children: [
Icon(Icons.trending_up, size: 14, color: Colors.green),
SizedBox(width: 4),
Text(
'+${((stone.currentValue - stone.purchasePrice) / stone.purchasePrice * 100).toStringAsFixed(1)}%',
style: TextStyle(color: Colors.green, fontWeight: FontWeight.bold),
),
],
),
),
],
),
],
),
),
),
);
}
2. 石料详情页
详情信息展示
- 基本信息:名称、产地、品种、类型
- 尺寸重量:长宽高、重量
- 外观描述:颜色、质地、纹理
- 价值信息:购买价格、当前估值、升值情况
- 购买信息:购买日期、购买来源
- 存放信息:存放位置、品相状态
- 照片展示:多张照片轮播
操作按钮
- 编辑信息
- 记录使用
- 删除石料
- 分享信息
void _showStoneDetail(Stone stone) {
showModalBottomSheet(
context: context,
isScrollControlled: true,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
),
builder: (context) => DraggableScrollableSheet(
initialChildSize: 0.8,
minChildSize: 0.5,
maxChildSize: 0.95,
expand: false,
builder: (context, scrollController) => SingleChildScrollView(
controller: scrollController,
child: Padding(
padding: EdgeInsets.all(20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// 标题栏
Row(
children: [
Icon(_getStoneIcon(stone.type), size: 32),
SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(stone.name,
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold)),
Text('${stone.origin} · ${stone.variety}',
style: TextStyle(color: Colors.grey)),
],
),
),
_buildUsageStatusBadge(stone.isUsed),
],
),
Divider(height: 32),
// 基本信息
_buildDetailSection('基本信息', [
_buildDetailRow('产地', stone.origin),
_buildDetailRow('品种', stone.variety),
_buildDetailRow('类型', _getStoneTypeName(stone.type)),
_buildDetailRow('品相', _getConditionName(stone.condition)),
]),
// 尺寸重量
_buildDetailSection('尺寸重量', [
_buildDetailRow('长度', '${stone.length}cm'),
_buildDetailRow('宽度', '${stone.width}cm'),
_buildDetailRow('高度', '${stone.height}cm'),
_buildDetailRow('重量', '${stone.weight}g'),
]),
// 外观描述
_buildDetailSection('外观描述', [
_buildDetailRow('颜色', stone.color),
_buildDetailRow('质地', stone.texture),
_buildDetailRow('纹理', stone.pattern),
]),
// 价值信息
_buildDetailSection('价值信息', [
_buildDetailRow('购买价格', '¥${stone.purchasePrice.toStringAsFixed(2)}'),
_buildDetailRow('当前估值', '¥${stone.currentValue.toStringAsFixed(2)}'),
_buildDetailRow('升值金额',
'¥${(stone.currentValue - stone.purchasePrice).toStringAsFixed(2)}'),
_buildDetailRow('升值率',
'${((stone.currentValue - stone.purchasePrice) / stone.purchasePrice * 100).toStringAsFixed(2)}%'),
]),
// 购买信息
_buildDetailSection('购买信息', [
_buildDetailRow('购买日期', _formatDate(stone.purchaseDate)),
_buildDetailRow('购买来源', stone.purchaseFrom),
]),
// 存放信息
_buildDetailSection('存放信息', [
_buildDetailRow('存放位置', stone.storageLocation),
]),
// 备注
if (stone.notes.isNotEmpty)
_buildDetailSection('备注', [
Text(stone.notes, style: TextStyle(color: Colors.grey.shade700)),
]),
SizedBox(height: 20),
// 操作按钮
Row(
children: [
Expanded(
child: OutlinedButton.icon(
onPressed: () => _editStone(stone),
icon: Icon(Icons.edit),
label: Text('编辑'),
),
),
SizedBox(width: 12),
Expanded(
child: ElevatedButton.icon(
onPressed: () {
Navigator.pop(context);
_showUsageRecordDialog(stone);
},
icon: Icon(Icons.add),
label: Text('记录使用'),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.brown,
),
),
),
],
),
],
),
),
),
),
);
}
3. 使用记录管理
记录添加对话框
void _showUsageRecordDialog(Stone stone) {
final artworkNameController = TextEditingController();
final contentController = TextEditingController();
String purpose = '篆刻印章';
String style = '汉印';
String difficulty = '中等';
showDialog(
context: context,
builder: (context) => StatefulBuilder(
builder: (context, setState) => AlertDialog(
title: Text('记录使用 - ${stone.name}'),
content: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
// 使用目的
DropdownButtonFormField<String>(
value: purpose,
decoration: InputDecoration(labelText: '使用目的'),
items: ['篆刻印章', '雕刻作品', '练习'].map((p) =>
DropdownMenuItem(value: p, child: Text(p))
).toList(),
onChanged: (value) => setState(() => purpose = value!),
),
SizedBox(height: 12),
// 作品名称
TextField(
controller: artworkNameController,
decoration: InputDecoration(labelText: '作品名称'),
),
SizedBox(height: 12),
// 篆刻内容
TextField(
controller: contentController,
decoration: InputDecoration(labelText: '篆刻内容'),
),
SizedBox(height: 12),
// 篆刻风格
DropdownButtonFormField<String>(
value: style,
decoration: InputDecoration(labelText: '篆刻风格'),
items: ['汉印', '流派印', '肖形印', '鸟虫篆', '其他'].map((s) =>
DropdownMenuItem(value: s, child: Text(s))
).toList(),
onChanged: (value) => setState(() => style = value!),
),
SizedBox(height: 12),
// 难度
DropdownButtonFormField<String>(
value: difficulty,
decoration: InputDecoration(labelText: '难度'),
items: ['简单', '中等', '困难'].map((d) =>
DropdownMenuItem(value: d, child: Text(d))
).toList(),
onChanged: (value) => setState(() => difficulty = value!),
),
],
),
),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: Text('取消'),
),
ElevatedButton(
onPressed: () {
_saveUsageRecord(
stone,
artworkNameController.text,
contentController.text,
purpose,
style,
difficulty,
);
Navigator.pop(context);
},
child: Text('保存'),
),
],
),
),
);
}
使用记录列表
- 按时间倒序排列
- 显示石料名称、作品名称、使用日期
- 显示篆刻内容和风格
- 显示剩余尺寸信息
- 支持查看详情和删除
4. 作品展示
作品网格视图
- 瀑布流布局展示作品照片
- 显示作品名称和篆刻内容
- 显示创作日期和评分
- 点击查看作品详情
作品详情
- 作品照片轮播
- 作品基本信息(名称、内容、风格、类型)
- 关联石料信息
- 创作信息(日期、耗时、技法)
- 尺寸和描述
- 自评分和展览记录
- 出售信息
5. 数据统计分析
统计概览卡片
Widget _buildStatsOverview() {
final stats = _calculateStats();
return Card(
elevation: 4,
margin: EdgeInsets.all(16),
child: Padding(
padding: EdgeInsets.all(20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Icon(Icons.analytics, color: Colors.brown, size: 28),
SizedBox(width: 12),
Text('收藏统计',
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
],
),
SizedBox(height: 20),
// 数量统计
Row(
children: [
Expanded(child: _buildStatItem('石料总数', '${stats.totalStones}块', Icons.category)),
Expanded(child: _buildStatItem('作品总数', '${stats.totalArtworks}件', Icons.palette)),
],
),
SizedBox(height: 16),
// 价值统计
Row(
children: [
Expanded(child: _buildStatItem('总投资', '¥${stats.totalInvestment.toStringAsFixed(0)}', Icons.shopping_cart)),
Expanded(child: _buildStatItem('总价值', '¥${stats.totalValue.toStringAsFixed(0)}', Icons.account_balance_wallet)),
],
),
SizedBox(height: 16),
// 升值情况
Container(
width: double.infinity,
padding: EdgeInsets.all(16),
decoration: BoxDecoration(
color: stats.appreciation > 0
? Colors.green.withOpacity(0.1)
: Colors.red.withOpacity(0.1),
borderRadius: BorderRadius.circular(12),
border: Border.all(
color: stats.appreciation > 0
? Colors.green.withOpacity(0.3)
: Colors.red.withOpacity(0.3),
),
),
child: Column(
children: [
Icon(
stats.appreciation > 0 ? Icons.trending_up : Icons.trending_down,
color: stats.appreciation > 0 ? Colors.green : Colors.red,
size: 32,
),
SizedBox(height: 8),
Text('升值金额', style: TextStyle(fontSize: 14, color: Colors.grey)),
Text(
'¥${stats.appreciation.toStringAsFixed(2)}',
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: stats.appreciation > 0 ? Colors.green : Colors.red,
),
),
Text(
'升值率: ${stats.appreciationRate.toStringAsFixed(2)}%',
style: TextStyle(
fontSize: 14,
color: stats.appreciation > 0 ? Colors.green : Colors.red,
),
),
],
),
),
],
),
),
);
}
产地分布图表
- 饼图展示各产地石料数量占比
- 柱状图展示各产地价值分布
- 列表展示详细数据
品种分布统计
- 按品种统计石料数量
- 显示各品种平均价值
- 最贵品种排行
使用趋势分析
- 月度使用次数统计
- 使用频率最高的石料
- 创作作品数量趋势
数据初始化
示例数据
应用内置了完整的示例数据,包括多块石料、使用记录和作品信息:
void _initializeData() {
// 初始化石料数据
_stones = [
Stone(
id: 'stone001',
name: '寿山田黄石',
origin: '寿山',
variety: '田黄',
type: StoneType.seal,
length: 3.5,
width: 2.8,
height: 6.0,
weight: 185.0,
color: '金黄色',
texture: '细腻温润',
pattern: '萝卜纹明显',
purchasePrice: 15000.0,
purchaseDate: DateTime(2022, 5, 15),
purchaseFrom: '福州古玩市场',
currentValue: 18000.0,
condition: StoneCondition.perfect,
isUsed: false,
storageLocation: '保险柜A区',
photos: ['stone001_1.jpg', 'stone001_2.jpg'],
notes: '品质上乘,萝卜纹清晰,色泽纯正',
createdDate: DateTime.now().subtract(Duration(days: 600)),
isFavorite: true,
),
Stone(
id: 'stone002',
name: '青田封门青',
origin: '青田',
variety: '封门青',
type: StoneType.seal,
length: 2.5,
width: 2.5,
height: 5.0,
weight: 95.0,
color: '青绿色',
texture: '细腻通透',
pattern: '纯净无杂质',
purchasePrice: 3500.0,
purchaseDate: DateTime(2023, 3, 20),
purchaseFrom: '浙江青田石市场',
currentValue: 4200.0,
condition: StoneCondition.perfect,
isUsed: true,
storageLocation: '展示柜B区',
photos: ['stone002_1.jpg'],
notes: '封门青精品,适合篆刻细腻印文',
createdDate: DateTime.now().subtract(Duration(days: 300)),
isFavorite: true,
),
Stone(
id: 'stone003',
name: '昌化鸡血石',
origin: '昌化',
variety: '鸡血石',
type: StoneType.ornament,
length: 8.0,
width: 5.0,
height: 12.0,
weight: 1200.0,
color: '红白相间',
texture: '坚硬细密',
pattern: '血色鲜艳',
purchasePrice: 25000.0,
purchaseDate: DateTime(2021, 10, 8),
purchaseFrom: '杭州拍卖会',
currentValue: 32000.0,
condition: StoneCondition.good,
isUsed: false,
storageLocation: '保险柜A区',
photos: ['stone003_1.jpg', 'stone003_2.jpg', 'stone003_3.jpg'],
notes: '血色占比约40%,品相优良,适合收藏',
createdDate: DateTime.now().subtract(Duration(days: 800)),
isFavorite: true,
),
Stone(
id: 'stone004',
name: '巴林福黄石',
origin: '巴林',
variety: '福黄石',
type: StoneType.seal,
length: 2.0,
width: 2.0,
height: 4.5,
weight: 55.0,
color: '明黄色',
texture: '细腻柔和',
pattern: '色泽均匀',
purchasePrice: 800.0,
purchaseDate: DateTime(2023, 8, 12),
purchaseFrom: '内蒙古巴林右旗',
currentValue: 950.0,
condition: StoneCondition.good,
isUsed: true,
storageLocation: '工作台',
photos: ['stone004_1.jpg'],
notes: '性价比高,适合练习篆刻',
createdDate: DateTime.now().subtract(Duration(days: 150)),
isFavorite: false,
),
Stone(
id: 'stone005',
name: '寿山芙蓉石',
origin: '寿山',
variety: '芙蓉石',
type: StoneType.seal,
length: 3.0,
width: 3.0,
height: 5.5,
weight: 145.0,
color: '粉白色',
texture: '细腻如脂',
pattern: '温润通透',
purchasePrice: 2800.0,
purchaseDate: DateTime(2023, 1, 25),
purchaseFrom: '福州寿山石市场',
currentValue: 3200.0,
condition: StoneCondition.perfect,
isUsed: false,
storageLocation: '展示柜A区',
photos: ['stone005_1.jpg', 'stone005_2.jpg'],
notes: '芙蓉石精品,质地细腻,适合篆刻',
createdDate: DateTime.now().subtract(Duration(days: 360)),
isFavorite: true,
),
];
// 初始化使用记录
_usageRecords = [
UsageRecord(
id: 'ur001',
stoneId: 'stone002',
stoneName: '青田封门青',
usageDate: DateTime.now().subtract(Duration(days: 30)),
purpose: '篆刻印章',
artworkName: '清风徐来',
content: '清风徐来',
style: '汉印',
usedLength: 0.0,
usedWidth: 0.0,
usedHeight: 1.5,
remainingLength: 2.5,
remainingWidth: 2.5,
remainingHeight: 3.5,
duration: 4,
difficulty: '中等',
satisfaction: '非常满意',
photos: ['artwork001_1.jpg', 'artwork001_2.jpg'],
notes: '印文清晰,石质细腻,篆刻顺畅',
createdDate: DateTime.now().subtract(Duration(days: 30)),
),
UsageRecord(
id: 'ur002',
stoneId: 'stone004',
stoneName: '巴林福黄石',
usageDate: DateTime.now().subtract(Duration(days: 60)),
purpose: '练习',
artworkName: '练习作品',
content: '福',
style: '流派印',
usedLength: 0.0,
usedWidth: 0.0,
usedHeight: 1.0,
remainingLength: 2.0,
remainingWidth: 2.0,
remainingHeight: 3.5,
duration: 2,
difficulty: '简单',
satisfaction: '满意',
photos: ['practice001.jpg'],
notes: '练习刀法,石质适中',
createdDate: DateTime.now().subtract(Duration(days: 60)),
),
UsageRecord(
id: 'ur003',
stoneId: 'stone002',
stoneName: '青田封门青',
usageDate: DateTime.now().subtract(Duration(days: 90)),
purpose: '篆刻印章',
artworkName: '静以修身',
content: '静以修身',
style: '汉印',
usedLength: 0.0,
usedWidth: 0.0,
usedHeight: 1.5,
remainingLength: 2.5,
remainingWidth: 2.5,
remainingHeight: 5.0,
duration: 5,
difficulty: '困难',
satisfaction: '非常满意',
photos: ['artwork002_1.jpg'],
notes: '四字印章,布局合理,刀法流畅',
createdDate: DateTime.now().subtract(Duration(days: 90)),
),
];
// 初始化作品数据
_artworks = [
Artwork(
id: 'art001',
name: '清风徐来',
stoneId: 'stone002',
stoneName: '青田封门青',
content: '清风徐来',
style: '汉印',
type: ArtworkType.white,
createDate: DateTime.now().subtract(Duration(days: 30)),
duration: 4,
technique: '冲刀为主,切刀辅助',
size: 2.5,
description: '四字白文印,布局方正,刀法简洁有力',
photos: ['artwork001_1.jpg', 'artwork001_2.jpg'],
rating: 4.5,
exhibition: '',
isForSale: false,
price: 0.0,
notes: '个人满意作品',
createdDate: DateTime.now().subtract(Duration(days: 30)),
),
Artwork(
id: 'art002',
name: '静以修身',
stoneId: 'stone002',
stoneName: '青田封门青',
content: '静以修身',
style: '汉印',
type: ArtworkType.white,
createDate: DateTime.now().subtract(Duration(days: 90)),
duration: 5,
technique: '冲刀为主,注重笔意',
size: 2.5,
description: '四字白文印,字形端庄,章法严谨',
photos: ['artwork002_1.jpg'],
rating: 4.8,
exhibition: '2023年社区篆刻展',
isForSale: false,
price: 0.0,
notes: '参展作品,获得好评',
createdDate: DateTime.now().subtract(Duration(days: 90)),
),
];
}
辅助方法
工具函数
// 获取石料类型图标
IconData _getStoneIcon(StoneType type) {
switch (type) {
case StoneType.seal:
return Icons.crop_square;
case StoneType.ornament:
return Icons.diamond;
case StoneType.carving:
return Icons.brush;
}
}
// 获取产地颜色
Color _getOriginColor(String origin) {
switch (origin) {
case '寿山':
return Colors.brown.shade700;
case '青田':
return Colors.teal.shade600;
case '昌化':
return Colors.red.shade600;
case '巴林':
return Colors.amber.shade700;
default:
return Colors.grey.shade600;
}
}
// 获取石料类型名称
String _getStoneTypeName(StoneType type) {
switch (type) {
case StoneType.seal:
return '印章石';
case StoneType.ornament:
return '摆件石';
case StoneType.carving:
return '雕刻石';
}
}
// 获取品相名称
String _getConditionName(StoneCondition condition) {
switch (condition) {
case StoneCondition.perfect:
return '完美';
case StoneCondition.good:
return '良好';
case StoneCondition.fair:
return '一般';
case StoneCondition.flawed:
return '有瑕疵';
}
}
// 格式化日期
String _formatDate(DateTime date) {
return '${date.year}-${date.month.toString().padLeft(2, '0')}-${date.day.toString().padLeft(2, '0')}';
}
// 格式化日期时间
String _formatDateTime(DateTime dateTime) {
return '${_formatDate(dateTime)} ${dateTime.hour.toString().padLeft(2, '0')}:${dateTime.minute.toString().padLeft(2, '0')}';
}
// 计算统计数据
StoneStats _calculateStats() {
final totalStones = _stones.length;
final usedStones = _stones.where((s) => s.isUsed).length;
final unusedStones = totalStones - usedStones;
final totalArtworks = _artworks.length;
final totalInvestment = _stones.fold(0.0, (sum, s) => sum + s.purchasePrice);
final totalValue = _stones.fold(0.0, (sum, s) => sum + s.currentValue);
final appreciation = totalValue - totalInvestment;
final appreciationRate = totalInvestment > 0
? (appreciation / totalInvestment * 100)
: 0.0;
// 产地分布
final originDistribution = <String, int>{};
for (final stone in _stones) {
originDistribution[stone.origin] = (originDistribution[stone.origin] ?? 0) + 1;
}
// 品种分布
final varietyDistribution = <String, int>{};
for (final stone in _stones) {
varietyDistribution[stone.variety] = (varietyDistribution[stone.variety] ?? 0) + 1;
}
// 各产地价值
final valueByOrigin = <String, double>{};
for (final stone in _stones) {
valueByOrigin[stone.origin] = (valueByOrigin[stone.origin] ?? 0.0) + stone.currentValue;
}
// 月度使用统计
final monthlyUsage = <String, int>{};
for (final record in _usageRecords) {
final monthKey = '${record.usageDate.year}-${record.usageDate.month.toString().padLeft(2, '0')}';
monthlyUsage[monthKey] = (monthlyUsage[monthKey] ?? 0) + 1;
}
// 最常用产地
final originUsageCount = <String, int>{};
for (final record in _usageRecords) {
final stone = _stones.firstWhere((s) => s.id == record.stoneId);
originUsageCount[stone.origin] = (originUsageCount[stone.origin] ?? 0) + 1;
}
final mostUsedOrigin = originUsageCount.entries.isNotEmpty
? originUsageCount.entries.reduce((a, b) => a.value > b.value ? a : b).key
: '暂无';
// 最贵石料
final mostValuableStone = _stones.isNotEmpty
? _stones.reduce((a, b) => a.currentValue > b.currentValue ? a : b).name
: '暂无';
// 平均石料价值
final averageStoneValue = totalStones > 0 ? totalValue / totalStones : 0.0;
return StoneStats(
totalStones: totalStones,
usedStones: usedStones,
unusedStones: unusedStones,
totalArtworks: totalArtworks,
totalValue: totalValue,
totalInvestment: totalInvestment,
appreciation: appreciation,
appreciationRate: appreciationRate,
originDistribution: originDistribution,
varietyDistribution: varietyDistribution,
valueByOrigin: valueByOrigin,
monthlyUsage: monthlyUsage,
mostUsedOrigin: mostUsedOrigin,
mostValuableStone: mostValuableStone,
averageStoneValue: averageStoneValue,
);
}
性能优化
列表优化
使用ListView.builder而不是ListView,实现按需加载:
ListView.builder(
itemCount: stones.length,
itemBuilder: (context, index) {
return _buildStoneCard(stones[index]);
},
// 添加缓存范围
cacheExtent: 500,
)
图片优化
对于石料和作品照片,使用缩略图和懒加载:
// 使用Image.asset加载本地图片
Image.asset(
stone.photos.first,
width: 60,
height: 60,
fit: BoxFit.cover,
// 使用缓存
cacheWidth: 120,
cacheHeight: 120,
)
动画优化
使用FadeTransition实现页面切换动画:
FadeTransition(
opacity: _fadeAnimation,
child: IndexedStack(
index: _selectedIndex,
children: [
_buildStonesPage(),
_buildRecordsPage(),
_buildArtworksPage(),
_buildCategoriesPage(),
_buildStatsPage(),
],
),
)
扩展功能建议
1. 云端同步
- 数据云端备份
- 多设备同步
- 数据导入导出
2. 社交功能
- 作品分享到社交平台
- 篆刻爱好者社区
- 作品交流和点评
3. 智能识别
- 石料照片识别产地品种
- AI辅助估值
- 真伪鉴别辅助
4. 市场行情
- 石料市场价格行情
- 拍卖信息推送
- 投资价值分析
5. 学习资源
- 篆刻技法教程
- 名家作品欣赏
- 石料知识库
常见问题
Q1: 如何准确记录石料尺寸?
A: 建议使用游标卡尺测量,精确到0.1mm。对于不规则石料,记录最大尺寸。
Q2: 石料估值如何确定?
A: 可以参考市场行情、拍卖记录、专家评估等多方面因素,定期更新估值。
Q3: 如何保存石料照片?
A: 建议从多个角度拍摄,包括正面、侧面、纹理特写等,光线充足,背景简洁。
Q4: 使用记录中的剩余尺寸如何计算?
A: 根据实际使用情况,记录使用后的剩余长宽高。对于印章石,主要记录高度变化。
Q5: 如何分类管理大量石料?
A: 可以按产地、品种、价格区间、使用状态等多维度分类,使用标签系统。
项目总结
本项目实现了一个功能完整的篆刻石料记录应用,主要特点包括:
功能完整性
- 石料档案管理
- 使用记录追踪
- 作品档案管理
- 价值评估系统
- 数据统计分析
用户体验
- 界面简洁美观
- 操作流畅便捷
- 信息展示清晰
- 数据可视化
技术实现
- 代码结构清晰
- 注释完整详细
- 遵循最佳实践
- 性能优化到位
学习价值
- Flutter基础组件使用
- 状态管理实践
- 数据模型设计
- 统计分析实现
- 业务逻辑处理
通过本项目的学习和实践,可以掌握Flutter应用开发的核心技能,同时了解篆刻艺术和石料收藏的相关知识,为开发更专业的收藏管理应用打下基础。
参考资料
- Flutter官方文档:https://flutter.dev/docs
- Material Design 3:https://m3.material.io
- Dart语言指南:https://dart.dev/guides
- 篆刻艺术知识:相关专业书籍和网站
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
更多推荐



所有评论(0)