- 合并 getFriendApplicationListAsApplicant(我发出的)+ AsRecipient(我收到的), 按 fromUserID 是否等于自己判断方向 - 我发出的待处理 → 灰字「等待对方通过」且无操作按钮;我收到的待处理才渲染 「接受/拒绝」;已同意→已添加、已拒绝→已拒绝(视觉规范 5.1) - 接受/拒绝按钮 shape 复用 theme.dart 新增的统一 8px Token(AppRadius.button), 不再用 Material3 默认胶囊圆角,页面内零魔法数值 - 窄屏(<360)按钮组/状态字换第二行右对齐不挤压姓名;非窄屏状态区固定 132px 双机实测:A(t2001)发→A 侧 AsApplicant 显示 handleResult=0(等待对方通过、无按钮); B(t2002)收→AsRecipient 显示接受/拒绝按钮,点接受后双方 handleResult=1(已添加) Co-authored-by: multica-agent <github@multica.ai>
129 lines
3.4 KiB
Dart
129 lines
3.4 KiB
Dart
import 'package:flutter/material.dart';
|
|
|
|
/// 全 App 统一的视觉常量:颜色、字号阶梯、间距。
|
|
/// 字号只保留 4 级,间距全部取 4 的倍数,保证两端(手机/电脑)观感一致。
|
|
class AppColors {
|
|
AppColors._();
|
|
|
|
/// 主色蓝(按钮、选中态、头像蓝)
|
|
static const Color primary = Color(0xFF3B87F5);
|
|
|
|
/// 头像灰蓝
|
|
static const Color avatarGray = Color(0xFF8593A8);
|
|
|
|
/// 聊天页背景
|
|
static const Color chatBg = Color(0xFFF5F6F8);
|
|
|
|
/// 页面背景
|
|
static const Color pageBg = Color(0xFFFFFFFF);
|
|
|
|
/// 己方气泡浅蓝
|
|
static const Color bubbleMine = Color(0xFFD6E7FC);
|
|
|
|
/// 对方气泡白
|
|
static const Color bubbleOther = Color(0xFFFFFFFF);
|
|
|
|
/// 搜索框灰底
|
|
static const Color searchBg = Color(0xFFF2F3F5);
|
|
|
|
/// 置顶会话底色(略灰)
|
|
static const Color pinnedBg = Color(0xFFF7F8FA);
|
|
|
|
/// 主要文字
|
|
static const Color textPrimary = Color(0xFF1D2129);
|
|
|
|
/// 次要文字(预览、时间、提示)
|
|
static const Color textSecondary = Color(0xFF86909C);
|
|
|
|
/// 危险/未读红
|
|
static const Color danger = Color(0xFFF53F3F);
|
|
|
|
/// 分隔线
|
|
static const Color divider = Color(0xFFEEEEEE);
|
|
|
|
/// 断网横幅深色底
|
|
static const Color bannerBg = Color(0xFF3A3F47);
|
|
}
|
|
|
|
/// 字号阶梯(全 App 只用这 4 级)
|
|
class AppFont {
|
|
AppFont._();
|
|
|
|
/// 辅助文字:时间、角标、提示小字
|
|
static const double small = 12;
|
|
|
|
/// 次要文字:预览、职务、副标题
|
|
static const double sub = 14;
|
|
|
|
/// 正文:名字、消息内容、按钮
|
|
static const double body = 16;
|
|
|
|
/// 标题:导航栏、页面大标题
|
|
static const double title = 18;
|
|
}
|
|
|
|
/// 间距常量(4 的倍数)
|
|
class AppGap {
|
|
AppGap._();
|
|
|
|
static const double x1 = 4;
|
|
static const double x2 = 8;
|
|
static const double x3 = 12;
|
|
static const double x4 = 16;
|
|
static const double x6 = 24;
|
|
static const double x8 = 32;
|
|
static const double x12 = 48;
|
|
}
|
|
|
|
/// 圆角常量(视觉规范 v1 §2:按钮/输入框/列表项 = 8,弹窗 = 12,气泡 = 8)
|
|
class AppRadius {
|
|
AppRadius._();
|
|
|
|
/// 按钮 / 输入框 / 列表项
|
|
static const double button = 8;
|
|
|
|
/// 弹窗
|
|
static const double modal = 12;
|
|
|
|
/// 气泡
|
|
static const double bubble = 8;
|
|
}
|
|
|
|
/// 统一的主题
|
|
ThemeData buildAppTheme() {
|
|
return ThemeData(
|
|
useMaterial3: true,
|
|
primaryColor: AppColors.primary,
|
|
scaffoldBackgroundColor: AppColors.pageBg,
|
|
colorScheme: ColorScheme.fromSeed(
|
|
seedColor: AppColors.primary,
|
|
primary: AppColors.primary,
|
|
error: AppColors.danger,
|
|
),
|
|
appBarTheme: const AppBarTheme(
|
|
backgroundColor: AppColors.pageBg,
|
|
foregroundColor: AppColors.textPrimary,
|
|
elevation: 0,
|
|
scrolledUnderElevation: 0,
|
|
centerTitle: true,
|
|
titleTextStyle: TextStyle(
|
|
color: AppColors.textPrimary,
|
|
fontSize: AppFont.title,
|
|
fontWeight: FontWeight.w600,
|
|
),
|
|
),
|
|
bottomNavigationBarTheme: const BottomNavigationBarThemeData(
|
|
selectedItemColor: AppColors.primary,
|
|
unselectedItemColor: AppColors.textSecondary,
|
|
selectedLabelStyle: TextStyle(fontSize: AppFont.small),
|
|
unselectedLabelStyle: TextStyle(fontSize: AppFont.small),
|
|
type: BottomNavigationBarType.fixed,
|
|
),
|
|
dividerTheme: const DividerThemeData(
|
|
color: AppColors.divider,
|
|
thickness: 0.5,
|
|
space: 0,
|
|
),
|
|
);
|
|
}
|