Browse Source

feat: 隐藏 AI 全能助手并应用精简布局

新增全局开关 AppConfig.hideAiAssistant 以支持特定客户需求。当开关为 true 时:
- 首页(HomeView)隐藏 AI 全能助手卡片,翻译和会议助手卡片改为等宽方形布局
- 发现页(ExploreView)隐藏 AI 全能助手卡片,剩余功能改为上下堆叠的横幅布局
- 新手引导跳过引导用户打开 AI 全能助手的步骤
默认值为 false,以保持现有用户的原版体验。

具体修改包括:
1. 在 appconfig.dart 中添加静态布尔字段
2. 在 home_view.dart 中新增 _buildSimplifiedAILayout 方法并调整构建逻辑
3. 在 explore_view.dart 中新增 _buildSimplifiedAILayout 方法并调整构建逻辑
4. 新增相关设计文档和实施计划文档
newdev_shunjiawei
lxm 6 months ago
parent
commit
5542b39dbe
  1. 416
      docs/superpowers/plans/2026-04-28-hide-ai-assistant.md
  2. 171
      docs/superpowers/specs/2026-04-28-hide-ai-assistant-design.md
  3. 2
      lib/data/models/appconfig.dart
  4. 44
      lib/modules/explore/views/explore_view.dart
  5. 93
      lib/modules/home/views/home_view.dart

416
docs/superpowers/plans/2026-04-28-hide-ai-assistant.md

@ -0,0 +1,416 @@
# 隐藏"AI 全能助手"模块 实施计划
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** 通过新增全局开关 `AppConfig.hideAiAssistant`,在 true 时让首页和发现页切换为隐藏"AI 全能助手"的精简布局。
**Architecture:** 单一全局静态 bool 控制 UI 分支。两个 View 各新增一个 `_buildSimplifiedAILayout()` 方法,原有方法和 controller 数据完全不动。新布局使用现有的卡片样式语言(渐变色、圆角、阴影),保持视觉一致性。
**Tech Stack:** Flutter, GetX, flutter_screenutil, flutter_intro
**Spec:** [`docs/superpowers/specs/2026-04-28-hide-ai-assistant-design.md`](../specs/2026-04-28-hide-ai-assistant-design.md)
---
## 文件清单
| 文件 | 改动 | 说明 |
|---|---|---|
| `lib/data/models/appconfig.dart` | 修改 | 新增静态字段 `hideAiAssistant` |
| `lib/modules/home/views/home_view.dart` | 修改 | 新增 `_buildSimplifiedAILayout()`;`build()` 中按开关分发 |
| `lib/modules/explore/views/explore_view.dart` | 修改 | 新增 `_buildSimplifiedAILayout()`;`build()` 中按开关分发 |
无需新建文件,无需修改 controller、路由、翻译资源。
---
## 关于测试策略
本项目 `test/` 目录只有翻译资源测试,没有 widget test 体系。本次为纯 UI 布局调整,强行写 widget test 既不符合项目惯例又脆弱。验证手段为:
- **静态校验**:`flutter analyze` 不引入新 warning
- **手动验证**:在两种开关值下分别启动应用,肉眼比对首页和发现页
每个 Task 末尾会包含静态校验步骤。手动验证集中放在最后的 Task 4。
---
## Task 1: 新增配置开关
**Files:**
- Modify: `lib/data/models/appconfig.dart`
- [ ] **Step 1: 在 AppConfig 类中新增静态字段**
打开 `lib/data/models/appconfig.dart`,找到 `class AppConfig {` 后第一行(`static late UserGetAppConfigResp config;` 上方),插入字段。
最终类的开头部分应是:
```dart
class AppConfig {
// 中文注释:是否隐藏"AI全能助手"模块。
// true => 首页/发现页切换为精简布局,新手引导跳过 AI 引导步骤
// false => 保持原有布局
// TODO: 后续接入 BLE PID 判断逻辑,B017 设备连接时自动置 true
static bool hideAiAssistant = false;
static late UserGetAppConfigResp config;
// 新增一个私有的静态布尔值来跟踪初始化状态
static bool _isInitialized = false;
// ... 其余方法保持不变
```
- [ ] **Step 2: 静态校验**
Run: `cd /Users/liuxiamin/work/flutter_projects/deep_voice && flutter analyze lib/data/models/appconfig.dart`
Expected: 无新增 warning/error
- [ ] **Step 3: 提交**
```bash
git add lib/data/models/appconfig.dart
git commit -m "feat: 新增 AppConfig.hideAiAssistant 全局开关"
```
---
## Task 2: 首页新增精简布局
**Files:**
- Modify: `lib/modules/home/views/home_view.dart`
- [ ] **Step 1: 新增 import**
确认 `home_view.dart` 顶部已 import `'../../../data/models/appconfig.dart'`。该文件第 9 行已有 `import '../../../data/models/appconfig_model.dart';`,需要**追加**一行:
```dart
import '../../../data/models/appconfig.dart';
```
- [ ] **Step 2: 在 build() 中按开关分发**
在 `home_view.dart` 找到 `build()` 方法中以下代码(约 145-147 行):
```dart
// 热门AI体验
_buildSectionTitle(isDarkMode),
SizedBox(height: 16.h),
_buildPremiumAILayout(),
```
替换为:
```dart
// 热门AI体验
_buildSectionTitle(isDarkMode),
SizedBox(height: 16.h),
AppConfig.hideAiAssistant
? _buildSimplifiedAILayout()
: _buildPremiumAILayout(),
```
- [ ] **Step 3: 在文件末尾(HomeView 类的最后一个方法 `_buildFeatureCard` 之后、类闭合 `}` 之前)新增精简布局方法**
在 `_buildFeatureCard` 方法结束后,类闭合大括号之前,添加:
```dart
// 精简布局:隐藏"AI全能助手",仅保留翻译 + 会议助手,左右等宽
// 注意:本布局不包裹 IntroStepBuilder(order: 3),新手引导走完唤醒后自然结束
Widget _buildSimplifiedAILayout() {
final bool isDarkMode = Get.isDarkMode;
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// 左侧:翻译
Expanded(
flex: 1,
child: _buildFeatureCard(
title: 'interpretation'.tr,
description: 'simultaneousInterpretationInfo'.tr,
icon: Icons.translate,
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
const Color(0xFF4CAF50).withOpacity(0.3),
const Color(0xFF009688).withOpacity(0.3),
],
),
onTap: controller.openTranslation,
iconOnTop: true,
height: 140.h,
isDarkMode: isDarkMode,
iconColor: const Color(0xFF4CAF50),
),
),
SizedBox(width: 16.w),
// 右侧:会议助手
Expanded(
flex: 1,
child: _buildFeatureCard(
title: 'conferenceAssistant'.tr,
description: 'conferenceAssistantInfo'.tr,
icon: Icons.people,
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
const Color(0xFFab47bc).withOpacity(0.3),
const Color(0xFFec407a).withOpacity(0.3),
],
),
onTap: () => controller.openMeet(),
iconOnTop: true,
height: 140.h,
isDarkMode: isDarkMode,
iconColor: const Color(0xFFd81b60),
),
),
],
);
}
```
- [ ] **Step 4: 静态校验**
Run: `cd /Users/liuxiamin/work/flutter_projects/deep_voice && flutter analyze lib/modules/home/views/home_view.dart`
Expected: 无新增 warning/error
- [ ] **Step 5: 提交**
```bash
git add lib/modules/home/views/home_view.dart
git commit -m "feat(home): 新增精简布局,隐藏 AI 全能助手时使用"
```
---
## Task 3: 发现页新增精简布局
**Files:**
- Modify: `lib/modules/explore/views/explore_view.dart`
- [ ] **Step 1: 新增 import**
在 `explore_view.dart` 顶部 import 区追加:
```dart
import '../../../data/models/appconfig.dart';
```
- [ ] **Step 2: 在 build() 中按开关分发**
找到 `explore_view.dart` 中以下代码(约第 67-68 行):
```dart
// AI功能列表
SizedBox(height: 24.h),
_buildCustomAILayout(isDarkMode),
```
替换为:
```dart
// AI功能列表
SizedBox(height: 24.h),
AppConfig.hideAiAssistant
? _buildSimplifiedAILayout(isDarkMode)
: _buildCustomAILayout(isDarkMode),
```
- [ ] **Step 3: 在文件末尾(`_buildAIFeatureItemWide` 方法之后、ExploreView 类闭合 `}` 之前)新增精简布局方法**
```dart
// 精简布局:隐藏"AI全能助手",仅保留翻译 + 会议助手,上下堆叠 banner 卡
// 复用 controller.aiFeatures 中索引 1(翻译)和 2(会议助手)的数据
Widget _buildSimplifiedAILayout(bool isDarkMode) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'aiFunction'.tr, // AI功能
style: TextStyle(
fontSize: 18.sp,
fontWeight: FontWeight.w600,
color: isDarkMode ? Colors.white : Colors.grey[800],
),
),
SizedBox(height: 16.h),
// 翻译(banner 卡)
_buildSimplifiedBannerCard(controller.aiFeatures[1], 1, isDarkMode),
SizedBox(height: 12.h),
// 会议助手(banner 卡)
_buildSimplifiedBannerCard(controller.aiFeatures[2], 2, isDarkMode),
],
);
}
// 精简布局下的 banner 卡(图标右上角,标题/描述左下角)
Widget _buildSimplifiedBannerCard(
AIFeature feature, int index, bool isDarkMode) {
return GestureDetector(
onTap: () => controller.onAIFeatureTap(index),
child: Container(
height: 130.h,
padding: EdgeInsets.all(16.w),
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
feature.startColor.withOpacity(0.3),
feature.endColor.withOpacity(0.3),
],
),
borderRadius: BorderRadius.circular(20.r),
boxShadow: [
BoxShadow(
color: isDarkMode
? Colors.black.withOpacity(0.2)
: Colors.grey.withOpacity(0.1),
blurRadius: 8,
offset: const Offset(0, 4),
),
],
),
child: Stack(
children: [
// 图标右上角
Positioned(
top: 0,
right: 0,
child: Container(
width: 44.w,
height: 44.w,
decoration: BoxDecoration(
color: feature.iconColor.withOpacity(0.2),
shape: BoxShape.circle,
),
child: Icon(
feature.icon,
size: 22.sp,
color: feature.iconColor,
),
),
),
// 标题 + 描述左下角
Align(
alignment: Alignment.bottomLeft,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text(
feature.title,
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w600,
color: isDarkMode ? Colors.white : Colors.grey[800],
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
SizedBox(height: 4.h),
Text(
feature.description,
style: TextStyle(
fontSize: 12.sp,
color: isDarkMode ? Colors.grey[400] : Colors.grey[600],
),
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
],
),
),
],
),
),
);
}
```
- [ ] **Step 4: 静态校验**
Run: `cd /Users/liuxiamin/work/flutter_projects/deep_voice && flutter analyze lib/modules/explore/views/explore_view.dart`
Expected: 无新增 warning/error
- [ ] **Step 5: 提交**
```bash
git add lib/modules/explore/views/explore_view.dart
git commit -m "feat(explore): 新增精简布局,隐藏 AI 全能助手时使用"
```
---
## Task 4: 全量校验与手动验证
- [ ] **Step 1: 整个项目静态校验**
Run: `cd /Users/liuxiamin/work/flutter_projects/deep_voice && flutter analyze`
Expected: 无新增 warning/error(项目已有的告警可忽略)
- [ ] **Step 2: 跑现有测试**
Run: `cd /Users/liuxiamin/work/flutter_projects/deep_voice && flutter test`
Expected: 全部 PASS(应不受本次改动影响)
- [ ] **Step 3: 默认场景手动验证(hideAiAssistant = false)**
确认 `AppConfig.hideAiAssistant` 为 `false`(默认值),启动应用:
Run: `cd /Users/liuxiamin/work/flutter_projects/deep_voice && flutter run`
肉眼检查:
- 首页"热门AI体验"区域:左大卡(AI 全能助手)+ 右两小卡(翻译、会议助手),与改动前一致
- 发现页"AI 功能"区域:上层 2 方卡(AI 全能助手 + 同声传译)+ 下层 1 宽卡(商务会议助手),与改动前一致
- 新手引导走完三步:设备状态 → 唤醒 → AI 全能助手
- 暗色主题切换正常
- [ ] **Step 4: 精简场景手动验证(hideAiAssistant = true)**
临时修改 `lib/data/models/appconfig.dart` 中:
```dart
static bool hideAiAssistant = true;
```
重启应用,肉眼检查:
- 首页"热门AI体验":仅显示翻译 + 会议助手,左右等宽,高度约 140.h,绿色/紫粉渐变
- 发现页"AI 功能":上下堆叠两张 banner 卡,高度约 130.h,图标右上、标题左下
- 新手引导走完两步后正常结束(不再被引到 AI 全能助手)
- 翻译卡和会议助手卡点击能正常跳转
- 暗色主题切换正常
- [ ] **Step 5: 还原默认值**
把 `hideAiAssistant` 改回 `false`:
```dart
static bool hideAiAssistant = false;
```
确认本次改动**不修改默认值**进入仓库。
- [ ] **Step 6: 最终提交(如 Step 5 有改动)**
```bash
git status # 确认无未提交改动
```
如果有,则:
```bash
git add lib/data/models/appconfig.dart
git commit -m "chore: 还原 hideAiAssistant 默认值为 false"
```
---
## 完成标准
- 三次提交(Task 1/2/3 各一次),代码符合 spec 中的"文件改动清单"
- `flutter analyze` 通过
- 手动验证两种开关值下首页和发现页表现符合预期
- 新手引导在两种值下都能走完不卡顿

171
docs/superpowers/specs/2026-04-28-hide-ai-assistant-design.md

@ -0,0 +1,171 @@
# 隐藏"AI 全能助手"模块 · UI 排版重设计
**日期**:2026-04-28
**背景**:某客户(对应 BLE 设备 PID 为 `B017`)的产品定位上不需要"AI 全能助手"模块,需要在 UI 上屏蔽该入口,并对首页和发现页的"翻译 / 会议助手"两个剩余模块重新排版。
---
## 一、目标与范围
### 范围内
- 新增一个全局开关 `AppConfig.hideAiAssistant`
- 当开关为 `true` 时,**首页(HomeView)** 与 **发现页(ExploreView)** 切换为新的 UI 排版(隐藏 AI 全能助手入口)
- 当开关为 `true` 时,**新手引导(novice guide)** 跳过引导用户点开 AI 全能助手的步骤
- 当开关为 `false`(默认)时,所有 UI 行为与当前一致
### 范围外
- AI agent 模块本身(`lib/modules/agent/`)的代码、路由、controller **保持原样**,不做删除
- 翻译资源 key(`aiAssistant`、`aiAssistantInfo` 等)**全部保留**
- 开关与 BLE PID 的联动逻辑(即"连接 B017 设备时自动设置开关为 true")**留待后续单独实现**
- 其它可能与 AI 全能助手相关的次要露出(如设置页、付费页面)目前未发现,后续如发现再补
---
## 二、配置开关
### 位置与定义
在已有的 `lib/data/models/appconfig.dart` 的 `AppConfig` 类中新增一个静态字段:
```dart
class AppConfig {
static late UserGetAppConfigResp config;
static bool _isInitialized = false;
// 中文注释:是否隐藏"AI全能助手"模块。
// true => 首页/发现页切换为精简布局,新手引导跳过 AI 引导步骤
// false => 保持原有布局
// TODO: 后续接入 BLE PID 判断逻辑,B017 设备连接时自动置 true
static bool hideAiAssistant = false;
// ... 其它已有方法
}
```
### 调用方式
UI 层直接读取:`AppConfig.hideAiAssistant`,不引入新的 service 或新文件。
### 默认值
`false`(保持当前所有用户的体验不变)。
需要为 B017 客户验证新布局时,临时把默认值改为 `true` 重新编译即可,或在测试入口手动赋值。
---
## 三、首页(HomeView)改造
### 当前布局
`_buildPremiumAILayout()` 当前是 **左侧大卡片(AI 全能助手)+ 右侧两个小卡片(翻译 + 会议助手)** 的 1+2 结构。
### 新布局(开关为 true 时)
**方案 A:左右等宽方形双卡**
- 删除"AI 全能助手"卡片
- 翻译 / 会议助手两张卡片**等宽并列**,高度统一约 `140.h`(介于原大卡片 175 和小卡片 85 之间)
- 卡片样式延用现有渐变色方案:
- 翻译:`#4CAF50 → #009688` 绿色系
- 会议助手:`#ab47bc → #ec407a` 紫粉系
- 图标置左上角,标题加粗、描述 2 行省略,与原小卡片保持一致的视觉语言但放大
### 实现方式
在 `home_view.dart` 中:
- 保留原 `_buildPremiumAILayout()` 方法不动
- 新增 `_buildSimplifiedAILayout()` 方法返回新布局
- 在 `build()` 中按开关分发:
```dart
AppConfig.hideAiAssistant
? _buildSimplifiedAILayout()
: _buildPremiumAILayout(),
```
区域标题"热门AI体验"(`topAiExperiences`)继续保留,不修改。
---
## 四、发现页(ExploreView)改造
### 当前布局
`_buildCustomAILayout()` 当前是 **2x2 网格**:上层左 AI 全能助手 + 上层右 同声传译,下层会议助手占满整行。`controller.aiFeatures` 列表有 3 项,索引 0 是 AI 全能助手。
### 新布局(开关为 true 时)
**方案 C:上下堆叠大型 banner 卡**
- 删除 AI 全能助手卡片
- 翻译 / 会议助手两张卡片**上下堆叠**,每张占满整行
- 每张卡片高度约 `130.h`,padding 加大(`16.w`)
- 图标置右上角约 `44.w`,标题左下角加粗放大(`16.sp`),描述放在标题下方
- 渐变色与首页保持一致(绿色系 / 紫粉系)
### 实现方式
在 `explore_view.dart` 中:
**a. 不改动 `controller.aiFeatures` 列表本身**(保持向后兼容)
**b. 在 view 中根据开关分支**:
- 保留原 `_buildCustomAILayout()` 方法不动
- 新增 `_buildSimplifiedAILayout()` 方法返回新布局,内部直接使用 `controller.aiFeatures[1]`(翻译)和 `controller.aiFeatures[2]`(会议助手),跳过索引 0
- 在 `build()` 中按开关分发
区域标题"AI 功能"(`aiFunction`)继续保留。
---
## 五、新手引导(novice guide)调整
### 现状
`home_view.dart` 中 `IntroStepBuilder(group: 'home', order: 3)` 包裹了 AI 全能助手大卡片,引导用户在唤醒成功后点开 AI 全能助手。
### 调整
当 `AppConfig.hideAiAssistant == true` 时:
- 精简布局中**不渲染 order:3 的 IntroStepBuilder**
- 用户完成 order:1(设备状态)和 order:2(唤醒)后,引导自然结束
### 实现方式
在 `_buildSimplifiedAILayout()` 中**不包裹任何 IntroStepBuilder**,引导框架找不到 order:3 的目标 widget 后会自动跳过。
也可以在 `NoviceGuideService` 的 `home` group 流程中加判断,但前者改动更小、更稳。
---
## 六、风险与注意事项
1. **GlobalKey 缺失**:原 `IntroStepBuilder(order: 3)` 不渲染时,必须确认引导服务不会因找不到目标 widget 报错或卡住。需要在测试时验证 B017 用户的引导走完是否顺畅。
2. **后续 PID 联动**:`AppConfig.hideAiAssistant` 现在是普通静态字段,赋值后不会触发 `Obx` 重建。如果后续做 PID 联动并要求"插拔 B017 实时切换 UI",需要把字段改造成 `Rx<bool>` 或在赋值时主动触发 controller 刷新。本次设计不引入响应式包装。
3. **页面缓存**:GetX 的 controller 默认是单例,UI 切换是在 `build()` 阶段判断的。第一次进入页面后,开关变化需要重新构建页面才能生效。本次场景下开关在编译期/启动期就已确定,不存在运行时切换问题。
4. **资源未删除**:AI 全能助手相关的图标/文案/路由都保留,包体积无变化。
---
## 七、文件改动清单
| 文件 | 改动类型 | 说明 |
|---|---|---|
| `lib/data/models/appconfig.dart` | 修改 | 新增静态字段 `hideAiAssistant` |
| `lib/modules/home/views/home_view.dart` | 修改 | 新增 `_buildSimplifiedAILayout()`;`build()` 中按开关分发 |
| `lib/modules/explore/views/explore_view.dart` | 修改 | 新增 `_buildSimplifiedAILayout()`;`build()` 中按开关分发 |
无需新建文件,无需修改 controller、route、translations。
---
## 八、验证清单
- [ ] `AppConfig.hideAiAssistant = false` 时,首页和发现页 UI 与当前完全一致
- [ ] `AppConfig.hideAiAssistant = false` 时,新手引导走完 3 步并跳到 AI 全能助手
- [ ] `AppConfig.hideAiAssistant = true` 时,首页"热门AI体验"区域显示翻译 + 会议助手等宽并列
- [ ] `AppConfig.hideAiAssistant = true` 时,发现页"AI 功能"区域显示翻译 + 会议助手上下堆叠 banner
- [ ] `AppConfig.hideAiAssistant = true` 时,新手引导走完 2 步后正常结束,无卡顿/异常
- [ ] 暗色主题下两种布局的渐变和文字对比度符合预期
- [ ] 翻译/会议助手卡片的点击仍然能跳转到对应页面

2
lib/data/models/appconfig.dart

@ -7,7 +7,7 @@ class AppConfig {
// true => 首页/发现页切换为精简布局,新手引导跳过 AI 引导步骤 // true => 首页/发现页切换为精简布局,新手引导跳过 AI 引导步骤
// false => 保持原有布局 // false => 保持原有布局
// TODO: 后续接入 BLE PID 判断逻辑,B017 设备连接时自动置 true // TODO: 后续接入 BLE PID 判断逻辑,B017 设备连接时自动置 true
static bool hideAiAssistant = false; static bool hideAiAssistant = true;
static late UserGetAppConfigResp config; static late UserGetAppConfigResp config;

44
lib/modules/explore/views/explore_view.dart

@ -467,14 +467,14 @@ class ExploreView extends GetView<ExploreController> {
); );
} }
// 精简布局下的 banner 卡(图标右上角,标题/描述左下角) // 精简布局下的 banner 卡:Row 布局,图标在左,文字在右占满剩余空间
Widget _buildSimplifiedBannerCard( Widget _buildSimplifiedBannerCard(
AIFeature feature, int index, bool isDarkMode) { AIFeature feature, int index, bool isDarkMode) {
return GestureDetector( return GestureDetector(
onTap: () => controller.onAIFeatureTap(index), onTap: () => controller.onAIFeatureTap(index),
child: Container( child: Container(
height: 130.h, height: 110.h,
padding: EdgeInsets.all(16.w), padding: EdgeInsets.symmetric(horizontal: 18.w, vertical: 16.h),
decoration: BoxDecoration( decoration: BoxDecoration(
gradient: LinearGradient( gradient: LinearGradient(
begin: Alignment.topLeft, begin: Alignment.topLeft,
@ -495,38 +495,36 @@ class ExploreView extends GetView<ExploreController> {
), ),
], ],
), ),
child: Stack( child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
// 图标右上角 // 左侧图标
Positioned( Container(
top: 0, width: 56.w,
right: 0, height: 56.w,
child: Container(
width: 44.w,
height: 44.w,
decoration: BoxDecoration( decoration: BoxDecoration(
color: feature.iconColor.withOpacity(0.2), color: feature.iconColor.withOpacity(0.2),
shape: BoxShape.circle, shape: BoxShape.circle,
), ),
child: Icon( child: Icon(
feature.icon, feature.icon,
size: 22.sp, size: 30.sp,
color: feature.iconColor, color: feature.iconColor,
), ),
), ),
), SizedBox(width: 16.w),
// 标题 + 描述左下角 // 中间标题 + 描述
Align( Expanded(
alignment: Alignment.bottomLeft,
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
Text( Text(
feature.title, feature.title,
style: TextStyle( style: TextStyle(
fontSize: 16.sp, fontSize: 18.sp,
fontWeight: FontWeight.w600, fontWeight: FontWeight.bold,
color: isDarkMode ? Colors.white : Colors.grey[800], color: isDarkMode ? Colors.white : Colors.grey[800],
), ),
maxLines: 1, maxLines: 1,
@ -536,7 +534,8 @@ class ExploreView extends GetView<ExploreController> {
Text( Text(
feature.description, feature.description,
style: TextStyle( style: TextStyle(
fontSize: 12.sp, fontSize: 13.sp,
height: 1.35,
color: isDarkMode ? Colors.grey[400] : Colors.grey[600], color: isDarkMode ? Colors.grey[400] : Colors.grey[600],
), ),
maxLines: 2, maxLines: 2,
@ -545,6 +544,13 @@ class ExploreView extends GetView<ExploreController> {
], ],
), ),
), ),
SizedBox(width: 8.w),
// 右侧"›"指示符
Icon(
Icons.chevron_right,
size: 24.sp,
color: feature.iconColor,
),
], ],
), ),
), ),

93
lib/modules/home/views/home_view.dart

@ -148,7 +148,6 @@ class HomeView extends GetView<HomeController> {
AppConfig.hideAiAssistant AppConfig.hideAiAssistant
? _buildSimplifiedAILayout() ? _buildSimplifiedAILayout()
: _buildPremiumAILayout(), : _buildPremiumAILayout(),
], ],
), ),
), ),
@ -1044,7 +1043,8 @@ class HomeView extends GetView<HomeController> {
); );
} }
// 精简布局:隐藏"AI全能助手",仅保留翻译 + 会议助手,左右等宽 // 精简布局:隐藏"AI全能助手",仅保留翻译 + 会议助手,左右等宽方形
// 用 AspectRatio 强制 1:1 让高度跟随宽度,避免渲染成矩形
// 注意:本布局不包裹 IntroStepBuilder(order: 3),新手引导走完唤醒后自然结束 // 注意:本布局不包裹 IntroStepBuilder(order: 3),新手引导走完唤醒后自然结束
Widget _buildSimplifiedAILayout() { Widget _buildSimplifiedAILayout() {
final bool isDarkMode = Get.isDarkMode; final bool isDarkMode = Get.isDarkMode;
@ -1054,7 +1054,9 @@ class HomeView extends GetView<HomeController> {
// 左侧:翻译 // 左侧:翻译
Expanded( Expanded(
flex: 1, flex: 1,
child: _buildFeatureCard( child: AspectRatio(
aspectRatio: 1.0,
child: _buildSimplifiedFeatureCard(
title: 'interpretation'.tr, title: 'interpretation'.tr,
description: 'simultaneousInterpretationInfo'.tr, description: 'simultaneousInterpretationInfo'.tr,
icon: Icons.translate, icon: Icons.translate,
@ -1067,17 +1069,18 @@ class HomeView extends GetView<HomeController> {
], ],
), ),
onTap: controller.openTranslation, onTap: controller.openTranslation,
iconOnTop: true,
height: 140.h,
isDarkMode: isDarkMode, isDarkMode: isDarkMode,
iconColor: const Color(0xFF4CAF50), iconColor: const Color(0xFF4CAF50),
), ),
), ),
),
SizedBox(width: 16.w), SizedBox(width: 16.w),
// 右侧:会议助手 // 右侧:会议助手
Expanded( Expanded(
flex: 1, flex: 1,
child: _buildFeatureCard( child: AspectRatio(
aspectRatio: 1.0,
child: _buildSimplifiedFeatureCard(
title: 'conferenceAssistant'.tr, title: 'conferenceAssistant'.tr,
description: 'conferenceAssistantInfo'.tr, description: 'conferenceAssistantInfo'.tr,
icon: Icons.people, icon: Icons.people,
@ -1090,13 +1093,87 @@ class HomeView extends GetView<HomeController> {
], ],
), ),
onTap: () => controller.openMeet(), onTap: () => controller.openMeet(),
iconOnTop: true,
height: 140.h,
isDarkMode: isDarkMode, isDarkMode: isDarkMode,
iconColor: const Color(0xFFd81b60), iconColor: const Color(0xFFd81b60),
), ),
), ),
),
],
);
}
// 精简布局专用方形卡片:不写死 height,由外部 AspectRatio 决定尺寸
Widget _buildSimplifiedFeatureCard({
required String title,
required String description,
required IconData icon,
required LinearGradient gradient,
required VoidCallback onTap,
bool isDarkMode = false,
Color iconColor = Colors.white,
}) {
return GestureDetector(
onTap: onTap,
child: Container(
padding: EdgeInsets.all(14.w),
decoration: BoxDecoration(
gradient: gradient,
borderRadius: BorderRadius.circular(16.r),
boxShadow: [
BoxShadow(
color: isDarkMode
? Colors.black.withOpacity(0.2)
: Colors.grey.withOpacity(0.1),
blurRadius: 8,
offset: const Offset(0, 4),
),
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// 图标
Container(
width: 45.w,
height: 45.w,
decoration: BoxDecoration(
color: iconColor.withOpacity(0.2),
shape: BoxShape.circle,
),
child: Icon(
icon,
color: iconColor,
size: 24.w,
),
),
SizedBox(height: 10.h),
// 标题
Text(
title,
style: TextStyle(
color: isDarkMode ? Colors.white : Colors.grey[800],
fontSize: 16.sp,
fontWeight: FontWeight.bold,
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
SizedBox(height: 4.h),
// 描述
Expanded(
child: Text(
description,
style: TextStyle(
color: isDarkMode ? Colors.grey[400] : Colors.grey[600],
fontSize: 12.sp,
),
maxLines: 3,
overflow: TextOverflow.ellipsis,
),
),
], ],
),
),
); );
} }
} }

Loading…
Cancel
Save