feat(recite): 完成背诵模块基础框架与核心页面开发
本次提交实现了背诵模块的完整基础链路: 1. 新增词书、背单词接口层与对应数据模型 2. 完成背诵首页、章节列表页等核心页面开发 3. 实现音频播放、加载弹窗等通用组件 4. 配置路由跳转链路,替换旧版缓存传参方案 5. 对齐Vue端业务逻辑与UI样式
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
import 'dart:math' as math;
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
|
||||
/// ============================================================
|
||||
/// 【ReciteCircleProgress】圆环进度 —— 对标 Vue l-circle(canvas)
|
||||
///
|
||||
/// 用在:
|
||||
/// 1. 章节页右上角「总进度」(顺时针,绿色 #1BC26E,底 #EBEBEB)
|
||||
/// 2. 学习小结正确率(Vue :clockwise="false",逆时针绘制,视觉对称)
|
||||
///
|
||||
/// percent:0~100;中间内容由 child 自定义。
|
||||
/// ============================================================
|
||||
class ReciteCircleProgress extends StatelessWidget {
|
||||
const ReciteCircleProgress({
|
||||
super.key,
|
||||
required this.percent,
|
||||
required this.size,
|
||||
this.strokeWidth = 4,
|
||||
this.color = const Color(0xFF1BC26E),
|
||||
this.trailColor = const Color(0xFFEBEBEB),
|
||||
this.clockwise = true,
|
||||
this.child,
|
||||
});
|
||||
|
||||
final double percent;
|
||||
final double size; // 直径
|
||||
final double strokeWidth;
|
||||
final Color color;
|
||||
final Color trailColor;
|
||||
|
||||
/// false = 逆时针起笔(对标 l-circle :clockwise="false")
|
||||
final bool clockwise;
|
||||
final Widget? child;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SizedBox(
|
||||
width: size.w,
|
||||
height: size.w,
|
||||
child: CustomPaint(
|
||||
painter: _CirclePainter(
|
||||
percent: percent.clamp(0, 100).toDouble(),
|
||||
strokeWidth: strokeWidth.w,
|
||||
color: color,
|
||||
trailColor: trailColor,
|
||||
clockwise: clockwise,
|
||||
),
|
||||
child: Center(child: child),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _CirclePainter extends CustomPainter {
|
||||
_CirclePainter({
|
||||
required this.percent,
|
||||
required this.strokeWidth,
|
||||
required this.color,
|
||||
required this.trailColor,
|
||||
required this.clockwise,
|
||||
});
|
||||
|
||||
final double percent;
|
||||
final double strokeWidth;
|
||||
final Color color;
|
||||
final Color trailColor;
|
||||
final bool clockwise;
|
||||
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
final center = Offset(size.width / 2, size.height / 2);
|
||||
final radius = (size.width - strokeWidth) / 2;
|
||||
|
||||
final trackPaint =
|
||||
Paint()
|
||||
..style = PaintingStyle.stroke
|
||||
..strokeWidth = strokeWidth
|
||||
..color = trailColor;
|
||||
|
||||
final progressPaint =
|
||||
Paint()
|
||||
..style = PaintingStyle.stroke
|
||||
..strokeWidth = strokeWidth
|
||||
..strokeCap = StrokeCap.round
|
||||
..color = color;
|
||||
|
||||
canvas.drawCircle(center, radius, trackPaint);
|
||||
|
||||
const start = -math.pi / 2; // 12 点方向
|
||||
final sweep = 2 * math.pi * percent / 100;
|
||||
canvas.drawArc(
|
||||
Rect.fromCircle(center: center, radius: radius),
|
||||
clockwise ? start : start - sweep,
|
||||
sweep,
|
||||
false,
|
||||
progressPaint,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRepaint(covariant _CirclePainter old) =>
|
||||
old.percent != percent ||
|
||||
old.strokeWidth != strokeWidth ||
|
||||
old.color != color ||
|
||||
old.clockwise != clockwise;
|
||||
}
|
||||
Reference in New Issue
Block a user