feat:参照研听的基础工程

This commit is contained in:
jingyun
2026-06-18 15:02:28 +08:00
commit 364fc837b3
367 changed files with 16495 additions and 0 deletions
+15
View File
@@ -0,0 +1,15 @@
import 'package:flutter_remix/flutter_remix.dart';
// flutter_remix 0.0.3: icon class is FlutterRemix
class AppIcons {
static const assetsFill = FlutterRemix.wallet_3_fill;
static const assetsLine = FlutterRemix.wallet_3_line;
static const marketFill = FlutterRemix.line_chart_fill;
static const marketLine = FlutterRemix.line_chart_line;
static const newsFill = FlutterRemix.article_fill;
static const newsLine = FlutterRemix.article_line;
static const meFill = FlutterRemix.user_3_fill;
static const meLine = FlutterRemix.user_3_line;
static const arrowRight = FlutterRemix.arrow_right_s_line;
static const arrowLeft = FlutterRemix.arrow_left_s_line;
}
+57
View File
@@ -0,0 +1,57 @@
import 'package:flutter/widgets.dart';
/// 字号刻度常量。
/// 颜色在用处通过 ShadTheme.of(context).colorScheme 取,此处只定义尺寸/粗细/行高。
abstract class AppText {
/// App 大标题: 34px / w800 / lh 1.15
static const TextStyle appTitle = TextStyle(
fontSize: 34,
fontWeight: FontWeight.w800,
height: 1.15,
);
/// 区块标题: 22px / w700
static const TextStyle sectionTitle = TextStyle(
fontSize: 22,
fontWeight: FontWeight.w700,
);
/// 卡片标题: 19px / w620 / lh 1.4
static const TextStyle cardTitle = TextStyle(
fontSize: 19,
fontWeight: FontWeight.w600, // 最接近 w620
height: 1.4,
);
/// 列表标题: 16.5px / w600
static const TextStyle listTitle = TextStyle(
fontSize: 16.5,
fontWeight: FontWeight.w600,
);
/// 正文: 15px / w400 / lh 1.6
static const TextStyle body = TextStyle(
fontSize: 15,
fontWeight: FontWeight.w400,
height: 1.6,
);
/// meta 信息: 13px / w400
static const TextStyle meta = TextStyle(
fontSize: 13,
fontWeight: FontWeight.w400,
);
/// chip 筛选: 15px / w500
static const TextStyle chip = TextStyle(
fontSize: 15,
fontWeight: FontWeight.w500,
);
/// badge 标签: 12px / w500
static const TextStyle badge = TextStyle(
fontSize: 12,
fontWeight: FontWeight.w500,
height: 1.5,
);
}
+81
View File
@@ -0,0 +1,81 @@
import 'package:flutter/widgets.dart';
import 'package:shadcn_ui/shadcn_ui.dart';
const jinzhiLightScheme = ShadColorScheme(
background: Color(0xFFFBFAF7),
foreground: Color(0xFF1A1A17),
card: Color(0xFFFFFFFF),
cardForeground: Color(0xFF1A1A17),
popover: Color(0xFFFFFFFF),
popoverForeground: Color(0xFF1A1A17),
primary: Color(0xFFB5862A),
primaryForeground: Color(0xFFFFFFFF),
secondary: Color(0xFFF6ECD6),
secondaryForeground: Color(0xFF7A5B12),
muted: Color(0xFFF1EFE9),
mutedForeground: Color(0xFF8A8780),
accent: Color(0xFFF6ECD6),
accentForeground: Color(0xFF7A5B12),
destructive: Color(0xFFC0392B),
destructiveForeground: Color(0xFFFFFFFF),
border: Color(0xFFECEAE3),
input: Color(0xFFECEAE3),
ring: Color(0xFFB5862A),
selection: Color(0xFF1A1A17),
);
/// Hero 卡描边 = demo `--brand-soft-border`(比 brand-soft 填充更深一档的绿)。
/// ShadColorScheme 无对应 slot,单列于此(色值仍集中在 theme,widget 不写 hex);
/// widget 按 brightness 取值。light=oklch(0.9 0.07 128)、dark=oklch(0.42 0.07 131)。
const jinzhiBrandSoftBorderLight = Color(0xFFE3D6B4);
const jinzhiBrandSoftBorderDark = Color(0xFF5E4A22);
Color brandSoftBorder(Brightness b) => b == Brightness.dark
? jinzhiBrandSoftBorderDark
: jinzhiBrandSoftBorderLight;
/// Herobrand-soft 绿底)上的副/弱文本色。
/// 规范:次级文本是**中性 muted**,不挪用语义色(accentForeground 是链接/强调专用)。
/// 浅绿底上灰 muted(#8E8E93) 对比不足,故用 foreground 降透明的**中性深灰**
/// (叠在绿底上自然带轻微绿调、和谐且达 AA);深色底仍用灰 muted(已够对比)。
Color brandSoftMutedForeground(Brightness b, ShadColorScheme cs) =>
b == Brightness.dark
? cs.mutedForeground
: cs.foreground.withValues(alpha: 0.7);
/// 危险警示卡 soft-tintdemo `.da-warn`,与 brand-soft 同语言的 destructive 变体)。
const jinzhiDestructiveSoftLight = Color(0xFFFBEDEA);
const jinzhiDestructiveSoftBorderLight = Color(0xFFE8C7BF);
const jinzhiDestructiveSoftDark = Color(0x1AEF4444);
const jinzhiDestructiveSoftBorderDark = Color(0x52EF4444);
Color destructiveSoft(Brightness b) => b == Brightness.dark
? jinzhiDestructiveSoftDark
: jinzhiDestructiveSoftLight;
Color destructiveSoftBorder(Brightness b) => b == Brightness.dark
? jinzhiDestructiveSoftBorderDark
: jinzhiDestructiveSoftBorderLight;
const jinzhiDarkScheme = ShadColorScheme(
background: Color(0xFF0F0F0F),
foreground: Color(0xFFF0F0F0),
card: Color(0xFF1A1A1A),
cardForeground: Color(0xFFF0F0F0),
popover: Color(0xFF1A1A1A),
popoverForeground: Color(0xFFF0F0F0),
primary: Color(0xFFD9B45D),
primaryForeground: Color(0xFF1A1A17),
secondary: Color(0xFF27272A),
secondaryForeground: Color(0xFFF0F0F0),
muted: Color(0xFF262626),
mutedForeground: Color(0xFFA1A1AA),
accent: Color(0xFF3A2A0D),
accentForeground: Color(0xFFD9B45D),
destructive: Color(0xFFEF4444),
destructiveForeground: Color(0xFFFFFFFF),
border: Color(0x1FFFFFFF),
input: Color(0x26FFFFFF),
ring: Color(0xFFD9B45D),
selection: Color(0xFFF0F0F0),
);
+10
View File
@@ -0,0 +1,10 @@
class Spacing {
static const page = 20.0;
static const cardPadding = 18.0;
static const cardGap = 14.0;
static const sectionGap = 30.0;
static const radiusBase = 7.2; // 0.45rem --radius
static const radiusBadge = 3.2; // --radius-sm (badge / tag)
static const radiusBtn = 5.2; // --radius-md (button / input)
static const radiusCard = 11.2; // --radius-xl (card / hero 容器)
}
+24
View File
@@ -0,0 +1,24 @@
import 'package:flutter/material.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import '../storage/storage_service.dart';
import '../storage/storage_keys.dart';
part 'theme_controller.g.dart';
@riverpod
class ThemeModeController extends _$ThemeModeController {
@override
ThemeMode build() {
final v = StorageService.to.getString(storageThemeMode);
return switch (v) {
'light' => ThemeMode.light,
'dark' => ThemeMode.dark,
_ => ThemeMode.system,
};
}
Future<void> set(ThemeMode mode) async {
state = mode;
await StorageService.to.setString(storageThemeMode, mode.name);
}
}