feat(client): 登录/注册页照原型重建,ds 真相源组件族统一全部屏
- 登录/注册(login.html/register.html 1:1):两栏卡片+品牌渐变面板+主题小衣服 pill(onSurface 变体)+记住我(记录并预填最近账号)+原型式 toast 校验; 登录 fidelity 1.4–2.1% 三主题全绿;注册暂不入闸(少 门店编号/兑换券 字段, 已记 CONTRACT,screens.mjs 留存根) - ds 原子补齐:DsToast(.toast 单例)/DsCheck(.check/.agree)/DsButton lg 档/ DsSelect 替换全部旧 DropdownButton/DsField label 在上/DsInput 后缀与密码形态 - 全屏统一:对话框按钮全 DsButton、盒式输入主题钉死(visualDensity.standard、 h38、InputDecorationTheme 渗漏修复)、图标全 lucide、JetBrains Mono 三端同源、 BrandMark 真相源 logo、只读模式写操作全量守卫(WriteGuard+DsToast) - 出入库列表:版式对齐原型(卡片对齐+搜索框居中)、KPI 近30天滚动、结清后 失效财务应收应付表;商品编辑抽屉介绍库改搜索下拉、图片双击全屏预览 - 删除旧 UI 死代码:DataTableCard/FormDialog/PageScaffold/SearchChip/ SelectProductDialog/tabStateProvider - golden/fidelity:stock-in/out 补注册(9%)、login 入册(8%)、goldens 全量重打; 修复 pubspec flutter_web_plugins 非法声明(CI pub get 阻断) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JJ1g8XV1YhhmHRzhwWEW7o
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
/// 字体真相源。
|
||||
///
|
||||
/// 等宽字体镜像原型 tokens.css `--font-mono` 首选 **JetBrains Mono**,
|
||||
/// 以资产打包(pubspec `JetBrainsMono` 400/700)——原型截图、golden 测试、
|
||||
/// 三端真机渲染完全同源。历史教训:曾写 CSS 泛型名 `'monospace'`,Flutter
|
||||
/// **不解析**并静默回退(真机无衬线、golden 里 tofu 方块),勿走回头路。
|
||||
/// CJK 字形不在 JetBrains Mono 内,回退链兜底系统等宽/默认字体。
|
||||
class AppFonts {
|
||||
const AppFonts._();
|
||||
|
||||
static const String mono = 'JetBrainsMono';
|
||||
static const List<String> monoFallback = [
|
||||
'Menlo',
|
||||
'SF Mono',
|
||||
'Consolas',
|
||||
'Roboto Mono',
|
||||
'monospace',
|
||||
];
|
||||
}
|
||||
@@ -2,61 +2,193 @@ import 'package:flutter/material.dart';
|
||||
|
||||
@immutable
|
||||
class AppTokens extends ThemeExtension<AppTokens> {
|
||||
final Color page, bg, surface, border, borderSubtle, text, heading, title, muted, faint;
|
||||
final Color page,
|
||||
bg,
|
||||
surface,
|
||||
border,
|
||||
borderSubtle,
|
||||
text,
|
||||
heading,
|
||||
title,
|
||||
muted,
|
||||
faint;
|
||||
final Color primary, primaryDark, onPrimary, brand400, brand50, accent;
|
||||
final Color success, danger, warn, infoSoft, okSoft, accentSoft, successBg, dangerBg, warnBg;
|
||||
final Color success,
|
||||
danger,
|
||||
warn,
|
||||
infoSoft,
|
||||
okSoft,
|
||||
accentSoft,
|
||||
successBg,
|
||||
dangerBg,
|
||||
warnBg;
|
||||
final Color thBg, rowHover, shadow;
|
||||
final Color topBg, topFg, topFaint, topBorder, topControl, topMarkBg, topMarkFg;
|
||||
final Color sideBg, sideFg, sideMuted, sideActiveBg, sideActiveFg, sideBorder, sideHover;
|
||||
final Color topBg,
|
||||
topFg,
|
||||
topFaint,
|
||||
topBorder,
|
||||
topControl,
|
||||
topMarkBg,
|
||||
topMarkFg;
|
||||
final Color sideBg,
|
||||
sideFg,
|
||||
sideMuted,
|
||||
sideActiveBg,
|
||||
sideActiveFg,
|
||||
sideBorder,
|
||||
sideHover;
|
||||
final Color menuUserBg, menuUserFg, menuUserHover;
|
||||
final Color toastBg; // 原型 --toast-bg(基础 :root 共用,主题不变)
|
||||
final bool isDark;
|
||||
|
||||
const AppTokens({
|
||||
required this.page, required this.bg, required this.surface, required this.border,
|
||||
required this.borderSubtle, required this.text, required this.heading, required this.title,
|
||||
required this.muted, required this.faint, required this.primary, required this.primaryDark,
|
||||
required this.onPrimary, required this.brand400, required this.brand50, required this.accent,
|
||||
required this.success, required this.danger, required this.warn, required this.infoSoft,
|
||||
required this.okSoft, required this.accentSoft, required this.successBg, required this.dangerBg,
|
||||
required this.warnBg, required this.thBg, required this.rowHover, required this.shadow,
|
||||
required this.topBg, required this.topFg, required this.topFaint, required this.topBorder,
|
||||
required this.topControl, required this.topMarkBg, required this.topMarkFg, required this.sideBg,
|
||||
required this.sideFg, required this.sideMuted, required this.sideActiveBg, required this.sideActiveFg,
|
||||
required this.sideBorder, required this.sideHover, required this.menuUserBg, required this.menuUserFg,
|
||||
required this.menuUserHover, required this.isDark,
|
||||
required this.page,
|
||||
required this.bg,
|
||||
required this.surface,
|
||||
required this.border,
|
||||
required this.borderSubtle,
|
||||
required this.text,
|
||||
required this.heading,
|
||||
required this.title,
|
||||
required this.muted,
|
||||
required this.faint,
|
||||
required this.primary,
|
||||
required this.primaryDark,
|
||||
required this.onPrimary,
|
||||
required this.brand400,
|
||||
required this.brand50,
|
||||
required this.accent,
|
||||
required this.success,
|
||||
required this.danger,
|
||||
required this.warn,
|
||||
required this.infoSoft,
|
||||
required this.okSoft,
|
||||
required this.accentSoft,
|
||||
required this.successBg,
|
||||
required this.dangerBg,
|
||||
required this.warnBg,
|
||||
required this.thBg,
|
||||
required this.rowHover,
|
||||
required this.shadow,
|
||||
required this.topBg,
|
||||
required this.topFg,
|
||||
required this.topFaint,
|
||||
required this.topBorder,
|
||||
required this.topControl,
|
||||
required this.topMarkBg,
|
||||
required this.topMarkFg,
|
||||
required this.sideBg,
|
||||
required this.sideFg,
|
||||
required this.sideMuted,
|
||||
required this.sideActiveBg,
|
||||
required this.sideActiveFg,
|
||||
required this.sideBorder,
|
||||
required this.sideHover,
|
||||
required this.menuUserBg,
|
||||
required this.menuUserFg,
|
||||
required this.menuUserHover,
|
||||
required this.toastBg,
|
||||
required this.isDark,
|
||||
});
|
||||
|
||||
@override
|
||||
AppTokens copyWith({
|
||||
Color? page, Color? bg, Color? surface, Color? border, Color? borderSubtle, Color? text,
|
||||
Color? heading, Color? title, Color? muted, Color? faint, Color? primary, Color? primaryDark,
|
||||
Color? onPrimary, Color? brand400, Color? brand50, Color? accent, Color? success, Color? danger,
|
||||
Color? warn, Color? infoSoft, Color? okSoft, Color? accentSoft, Color? successBg, Color? dangerBg,
|
||||
Color? warnBg, Color? thBg, Color? rowHover, Color? shadow, Color? topBg, Color? topFg,
|
||||
Color? topFaint, Color? topBorder, Color? topControl, Color? topMarkBg, Color? topMarkFg,
|
||||
Color? sideBg, Color? sideFg, Color? sideMuted, Color? sideActiveBg, Color? sideActiveFg,
|
||||
Color? sideBorder, Color? sideHover, Color? menuUserBg, Color? menuUserFg, Color? menuUserHover,
|
||||
Color? page,
|
||||
Color? bg,
|
||||
Color? surface,
|
||||
Color? border,
|
||||
Color? borderSubtle,
|
||||
Color? text,
|
||||
Color? heading,
|
||||
Color? title,
|
||||
Color? muted,
|
||||
Color? faint,
|
||||
Color? primary,
|
||||
Color? primaryDark,
|
||||
Color? onPrimary,
|
||||
Color? brand400,
|
||||
Color? brand50,
|
||||
Color? accent,
|
||||
Color? success,
|
||||
Color? danger,
|
||||
Color? warn,
|
||||
Color? infoSoft,
|
||||
Color? okSoft,
|
||||
Color? accentSoft,
|
||||
Color? successBg,
|
||||
Color? dangerBg,
|
||||
Color? warnBg,
|
||||
Color? thBg,
|
||||
Color? rowHover,
|
||||
Color? shadow,
|
||||
Color? topBg,
|
||||
Color? topFg,
|
||||
Color? topFaint,
|
||||
Color? topBorder,
|
||||
Color? topControl,
|
||||
Color? topMarkBg,
|
||||
Color? topMarkFg,
|
||||
Color? sideBg,
|
||||
Color? sideFg,
|
||||
Color? sideMuted,
|
||||
Color? sideActiveBg,
|
||||
Color? sideActiveFg,
|
||||
Color? sideBorder,
|
||||
Color? sideHover,
|
||||
Color? menuUserBg,
|
||||
Color? menuUserFg,
|
||||
Color? menuUserHover,
|
||||
Color? toastBg,
|
||||
bool? isDark,
|
||||
}) {
|
||||
return AppTokens(
|
||||
page: page ?? this.page, bg: bg ?? this.bg, surface: surface ?? this.surface,
|
||||
border: border ?? this.border, borderSubtle: borderSubtle ?? this.borderSubtle,
|
||||
text: text ?? this.text, heading: heading ?? this.heading, title: title ?? this.title,
|
||||
muted: muted ?? this.muted, faint: faint ?? this.faint, primary: primary ?? this.primary,
|
||||
primaryDark: primaryDark ?? this.primaryDark, onPrimary: onPrimary ?? this.onPrimary,
|
||||
brand400: brand400 ?? this.brand400, brand50: brand50 ?? this.brand50, accent: accent ?? this.accent,
|
||||
success: success ?? this.success, danger: danger ?? this.danger, warn: warn ?? this.warn,
|
||||
infoSoft: infoSoft ?? this.infoSoft, okSoft: okSoft ?? this.okSoft, accentSoft: accentSoft ?? this.accentSoft,
|
||||
successBg: successBg ?? this.successBg, dangerBg: dangerBg ?? this.dangerBg, warnBg: warnBg ?? this.warnBg,
|
||||
thBg: thBg ?? this.thBg, rowHover: rowHover ?? this.rowHover, shadow: shadow ?? this.shadow,
|
||||
topBg: topBg ?? this.topBg, topFg: topFg ?? this.topFg, topFaint: topFaint ?? this.topFaint,
|
||||
topBorder: topBorder ?? this.topBorder, topControl: topControl ?? this.topControl,
|
||||
topMarkBg: topMarkBg ?? this.topMarkBg, topMarkFg: topMarkFg ?? this.topMarkFg,
|
||||
sideBg: sideBg ?? this.sideBg, sideFg: sideFg ?? this.sideFg, sideMuted: sideMuted ?? this.sideMuted,
|
||||
sideActiveBg: sideActiveBg ?? this.sideActiveBg, sideActiveFg: sideActiveFg ?? this.sideActiveFg,
|
||||
sideBorder: sideBorder ?? this.sideBorder, sideHover: sideHover ?? this.sideHover,
|
||||
menuUserBg: menuUserBg ?? this.menuUserBg, menuUserFg: menuUserFg ?? this.menuUserFg,
|
||||
menuUserHover: menuUserHover ?? this.menuUserHover, isDark: isDark ?? this.isDark,
|
||||
page: page ?? this.page,
|
||||
bg: bg ?? this.bg,
|
||||
surface: surface ?? this.surface,
|
||||
border: border ?? this.border,
|
||||
borderSubtle: borderSubtle ?? this.borderSubtle,
|
||||
text: text ?? this.text,
|
||||
heading: heading ?? this.heading,
|
||||
title: title ?? this.title,
|
||||
muted: muted ?? this.muted,
|
||||
faint: faint ?? this.faint,
|
||||
primary: primary ?? this.primary,
|
||||
primaryDark: primaryDark ?? this.primaryDark,
|
||||
onPrimary: onPrimary ?? this.onPrimary,
|
||||
brand400: brand400 ?? this.brand400,
|
||||
brand50: brand50 ?? this.brand50,
|
||||
accent: accent ?? this.accent,
|
||||
success: success ?? this.success,
|
||||
danger: danger ?? this.danger,
|
||||
warn: warn ?? this.warn,
|
||||
infoSoft: infoSoft ?? this.infoSoft,
|
||||
okSoft: okSoft ?? this.okSoft,
|
||||
accentSoft: accentSoft ?? this.accentSoft,
|
||||
successBg: successBg ?? this.successBg,
|
||||
dangerBg: dangerBg ?? this.dangerBg,
|
||||
warnBg: warnBg ?? this.warnBg,
|
||||
thBg: thBg ?? this.thBg,
|
||||
rowHover: rowHover ?? this.rowHover,
|
||||
shadow: shadow ?? this.shadow,
|
||||
topBg: topBg ?? this.topBg,
|
||||
topFg: topFg ?? this.topFg,
|
||||
topFaint: topFaint ?? this.topFaint,
|
||||
topBorder: topBorder ?? this.topBorder,
|
||||
topControl: topControl ?? this.topControl,
|
||||
topMarkBg: topMarkBg ?? this.topMarkBg,
|
||||
topMarkFg: topMarkFg ?? this.topMarkFg,
|
||||
sideBg: sideBg ?? this.sideBg,
|
||||
sideFg: sideFg ?? this.sideFg,
|
||||
sideMuted: sideMuted ?? this.sideMuted,
|
||||
sideActiveBg: sideActiveBg ?? this.sideActiveBg,
|
||||
sideActiveFg: sideActiveFg ?? this.sideActiveFg,
|
||||
sideBorder: sideBorder ?? this.sideBorder,
|
||||
sideHover: sideHover ?? this.sideHover,
|
||||
menuUserBg: menuUserBg ?? this.menuUserBg,
|
||||
menuUserFg: menuUserFg ?? this.menuUserFg,
|
||||
menuUserHover: menuUserHover ?? this.menuUserHover,
|
||||
toastBg: toastBg ?? this.toastBg,
|
||||
isDark: isDark ?? this.isDark,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -65,24 +197,53 @@ class AppTokens extends ThemeExtension<AppTokens> {
|
||||
if (other is! AppTokens) return this;
|
||||
Color c(Color a, Color b) => Color.lerp(a, b, t)!;
|
||||
return AppTokens(
|
||||
page: c(page, other.page), bg: c(bg, other.bg), surface: c(surface, other.surface),
|
||||
border: c(border, other.border), borderSubtle: c(borderSubtle, other.borderSubtle),
|
||||
text: c(text, other.text), heading: c(heading, other.heading), title: c(title, other.title),
|
||||
muted: c(muted, other.muted), faint: c(faint, other.faint), primary: c(primary, other.primary),
|
||||
primaryDark: c(primaryDark, other.primaryDark), onPrimary: c(onPrimary, other.onPrimary),
|
||||
brand400: c(brand400, other.brand400), brand50: c(brand50, other.brand50), accent: c(accent, other.accent),
|
||||
success: c(success, other.success), danger: c(danger, other.danger), warn: c(warn, other.warn),
|
||||
infoSoft: c(infoSoft, other.infoSoft), okSoft: c(okSoft, other.okSoft), accentSoft: c(accentSoft, other.accentSoft),
|
||||
successBg: c(successBg, other.successBg), dangerBg: c(dangerBg, other.dangerBg), warnBg: c(warnBg, other.warnBg),
|
||||
thBg: c(thBg, other.thBg), rowHover: c(rowHover, other.rowHover), shadow: c(shadow, other.shadow),
|
||||
topBg: c(topBg, other.topBg), topFg: c(topFg, other.topFg), topFaint: c(topFaint, other.topFaint),
|
||||
topBorder: c(topBorder, other.topBorder), topControl: c(topControl, other.topControl),
|
||||
topMarkBg: c(topMarkBg, other.topMarkBg), topMarkFg: c(topMarkFg, other.topMarkFg),
|
||||
sideBg: c(sideBg, other.sideBg), sideFg: c(sideFg, other.sideFg), sideMuted: c(sideMuted, other.sideMuted),
|
||||
sideActiveBg: c(sideActiveBg, other.sideActiveBg), sideActiveFg: c(sideActiveFg, other.sideActiveFg),
|
||||
sideBorder: c(sideBorder, other.sideBorder), sideHover: c(sideHover, other.sideHover),
|
||||
menuUserBg: c(menuUserBg, other.menuUserBg), menuUserFg: c(menuUserFg, other.menuUserFg),
|
||||
menuUserHover: c(menuUserHover, other.menuUserHover), isDark: t < 0.5 ? isDark : other.isDark,
|
||||
page: c(page, other.page),
|
||||
bg: c(bg, other.bg),
|
||||
surface: c(surface, other.surface),
|
||||
border: c(border, other.border),
|
||||
borderSubtle: c(borderSubtle, other.borderSubtle),
|
||||
text: c(text, other.text),
|
||||
heading: c(heading, other.heading),
|
||||
title: c(title, other.title),
|
||||
muted: c(muted, other.muted),
|
||||
faint: c(faint, other.faint),
|
||||
primary: c(primary, other.primary),
|
||||
primaryDark: c(primaryDark, other.primaryDark),
|
||||
onPrimary: c(onPrimary, other.onPrimary),
|
||||
brand400: c(brand400, other.brand400),
|
||||
brand50: c(brand50, other.brand50),
|
||||
accent: c(accent, other.accent),
|
||||
success: c(success, other.success),
|
||||
danger: c(danger, other.danger),
|
||||
warn: c(warn, other.warn),
|
||||
infoSoft: c(infoSoft, other.infoSoft),
|
||||
okSoft: c(okSoft, other.okSoft),
|
||||
accentSoft: c(accentSoft, other.accentSoft),
|
||||
successBg: c(successBg, other.successBg),
|
||||
dangerBg: c(dangerBg, other.dangerBg),
|
||||
warnBg: c(warnBg, other.warnBg),
|
||||
thBg: c(thBg, other.thBg),
|
||||
rowHover: c(rowHover, other.rowHover),
|
||||
shadow: c(shadow, other.shadow),
|
||||
topBg: c(topBg, other.topBg),
|
||||
topFg: c(topFg, other.topFg),
|
||||
topFaint: c(topFaint, other.topFaint),
|
||||
topBorder: c(topBorder, other.topBorder),
|
||||
topControl: c(topControl, other.topControl),
|
||||
topMarkBg: c(topMarkBg, other.topMarkBg),
|
||||
topMarkFg: c(topMarkFg, other.topMarkFg),
|
||||
sideBg: c(sideBg, other.sideBg),
|
||||
sideFg: c(sideFg, other.sideFg),
|
||||
sideMuted: c(sideMuted, other.sideMuted),
|
||||
sideActiveBg: c(sideActiveBg, other.sideActiveBg),
|
||||
sideActiveFg: c(sideActiveFg, other.sideActiveFg),
|
||||
sideBorder: c(sideBorder, other.sideBorder),
|
||||
sideHover: c(sideHover, other.sideHover),
|
||||
menuUserBg: c(menuUserBg, other.menuUserBg),
|
||||
menuUserFg: c(menuUserFg, other.menuUserFg),
|
||||
menuUserHover: c(menuUserHover, other.menuUserHover),
|
||||
toastBg: c(toastBg, other.toastBg),
|
||||
isDark: t < 0.5 ? isDark : other.isDark,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@ const AppTokens kTokensA = AppTokens(
|
||||
menuUserBg: Color(0xFF3C79C0),
|
||||
menuUserFg: Color(0xFFFFFFFF),
|
||||
menuUserHover: Color(0xFF4D88CC),
|
||||
toastBg: Color(0xFF1F2330),
|
||||
isDark: false,
|
||||
);
|
||||
|
||||
@@ -98,6 +99,7 @@ const AppTokens kTokensB = AppTokens(
|
||||
menuUserBg: Color(0xFF3A3120),
|
||||
menuUserFg: Color(0xFFF0E7D6),
|
||||
menuUserHover: Color(0xFF473B27),
|
||||
toastBg: Color(0xFF1F2330),
|
||||
isDark: true,
|
||||
);
|
||||
|
||||
@@ -147,13 +149,17 @@ const AppTokens kTokensC = AppTokens(
|
||||
menuUserBg: Color(0xFF7E2B3B),
|
||||
menuUserFg: Color(0xFFF7E9D6),
|
||||
menuUserHover: Color(0xFF8E3344),
|
||||
toastBg: Color(0xFF1F2330),
|
||||
isDark: false,
|
||||
);
|
||||
|
||||
AppTokens appTokensOf(String key) {
|
||||
switch (key) {
|
||||
case 'b': return kTokensB;
|
||||
case 'c': return kTokensC;
|
||||
default: return kTokensA;
|
||||
case 'b':
|
||||
return kTokensB;
|
||||
case 'c':
|
||||
return kTokensC;
|
||||
default:
|
||||
return kTokensA;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'app_dims.g.dart';
|
||||
import 'app_tokens.g.dart';
|
||||
|
||||
ThemeData buildTheme(String key) {
|
||||
@@ -18,6 +19,88 @@ ThemeData buildTheme(String key) {
|
||||
brightness: brightness,
|
||||
colorScheme: scheme,
|
||||
scaffoldBackgroundColor: t.bg,
|
||||
// 桌面端默认 adaptivePlatformDensity=compact 会把输入框/按钮压矮 8px,
|
||||
// 与原型 px 规格(.input h38 等)和 golden(测试环境=standard)不一致——
|
||||
// 真机曾因此输入框只有 ~30 高。锁 standard,三端渲染与原型同几何。
|
||||
visualDensity: VisualDensity.standard,
|
||||
// ── 对话框/输入框/按钮的 Material 默认样式钉到 ds 真相源 ──
|
||||
// 原型 .modal:surface / border / r-xl / 标题 fs-h2 heading
|
||||
dialogTheme: DialogThemeData(
|
||||
backgroundColor: t.surface,
|
||||
surfaceTintColor: Colors.transparent,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(AppDims.rXl),
|
||||
side: BorderSide(color: t.border),
|
||||
),
|
||||
titleTextStyle: TextStyle(
|
||||
fontSize: AppDims.fsH2,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: t.heading),
|
||||
contentTextStyle: TextStyle(fontSize: AppDims.fsBody, color: t.text),
|
||||
),
|
||||
// 原型 .input:h38 盒式(surface/1px border/r-md/pad 0 11),聚焦主色边。
|
||||
// 全局兜底——未显式给 decoration 边框的 TextField/DropdownButtonFormField
|
||||
// 一律盒式,禁止 Material 默认下划线再出现。
|
||||
inputDecorationTheme: InputDecorationTheme(
|
||||
isDense: true,
|
||||
filled: true,
|
||||
fillColor: t.surface,
|
||||
hintStyle: TextStyle(fontSize: AppDims.fsBody, color: t.faint),
|
||||
labelStyle: TextStyle(fontSize: AppDims.fsSm, color: t.muted),
|
||||
contentPadding: const EdgeInsets.symmetric(horizontal: 11, vertical: 9),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(AppDims.rMd),
|
||||
borderSide: BorderSide(color: t.border),
|
||||
),
|
||||
disabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(AppDims.rMd),
|
||||
borderSide: BorderSide(color: t.border),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(AppDims.rMd),
|
||||
borderSide: BorderSide(color: t.primary),
|
||||
),
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(AppDims.rMd),
|
||||
borderSide: BorderSide(color: t.border),
|
||||
),
|
||||
),
|
||||
// 原型 .btn.primary:primary 底 / onPrimary 字 / h38 / r-md / w600 / 无阴影
|
||||
elevatedButtonTheme: ElevatedButtonThemeData(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: t.primary,
|
||||
foregroundColor: t.onPrimary,
|
||||
elevation: 0,
|
||||
minimumSize: const Size(0, 38),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
textStyle: const TextStyle(
|
||||
fontSize: AppDims.fsBody, fontWeight: FontWeight.w600),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(AppDims.rMd)),
|
||||
),
|
||||
),
|
||||
filledButtonTheme: FilledButtonThemeData(
|
||||
style: FilledButton.styleFrom(
|
||||
backgroundColor: t.primary,
|
||||
foregroundColor: t.onPrimary,
|
||||
minimumSize: const Size(0, 38),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
textStyle: const TextStyle(
|
||||
fontSize: AppDims.fsBody, fontWeight: FontWeight.w600),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(AppDims.rMd)),
|
||||
),
|
||||
),
|
||||
// TextButton 兼作行内链接,不加边框;只统一字号字重与圆角
|
||||
textButtonTheme: TextButtonThemeData(
|
||||
style: TextButton.styleFrom(
|
||||
minimumSize: const Size(0, 38),
|
||||
textStyle: const TextStyle(
|
||||
fontSize: AppDims.fsBody, fontWeight: FontWeight.w600),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(AppDims.rMd)),
|
||||
),
|
||||
),
|
||||
// 字体走系统默认(macOS/iOS=PingFang SC,与原型 --font 一致);不强制 Noto。
|
||||
// Noto 仅 golden 测试加载(CI 无中文字体),见 test/support/golden_harness.dart。
|
||||
extensions: <ThemeExtension<dynamic>>[t],
|
||||
|
||||
Reference in New Issue
Block a user