first commit
This commit is contained in:
609
service_component/GlobalSearch.md
Normal file
609
service_component/GlobalSearch.md
Normal file
@@ -0,0 +1,609 @@
|
||||
# GlobalSearch - 全局搜索模块
|
||||
|
||||
## 模块概述
|
||||
|
||||
`GlobalSearch` 是 OneApp 的全局搜索模块,提供了跨模块的统一搜索功能。该模块支持多种内容类型的搜索,包括智能搜索建议、搜索历史管理、搜索结果优化等功能,为用户提供高效、精准的搜索体验。
|
||||
|
||||
## 核心功能
|
||||
|
||||
### 1. 跨模块内容搜索
|
||||
- **统一搜索入口**:提供全局统一的搜索接口
|
||||
- **多模块索引**:聚合各模块的可搜索内容
|
||||
- **内容分类**:按类型分类搜索结果
|
||||
- **权限控制**:基于用户权限过滤搜索结果
|
||||
|
||||
### 2. 智能搜索建议
|
||||
- **实时建议**:输入时实时提供搜索建议
|
||||
- **热门搜索**:展示热门搜索关键词
|
||||
- **个性化推荐**:基于用户行为的个性化建议
|
||||
- **拼写纠错**:智能纠正搜索词拼写错误
|
||||
|
||||
### 3. 搜索历史管理
|
||||
- **历史记录**:保存用户搜索历史
|
||||
- **快速访问**:快速访问历史搜索结果
|
||||
- **清理管理**:支持清理搜索历史
|
||||
- **隐私保护**:敏感搜索历史加密存储
|
||||
|
||||
### 4. 搜索结果优化
|
||||
- **相关性排序**:按相关性智能排序
|
||||
- **结果聚合**:相似结果智能聚合
|
||||
- **高亮显示**:关键词高亮显示
|
||||
- **分页加载**:大量结果分页展示
|
||||
|
||||
## 技术架构
|
||||
|
||||
### 架构设计
|
||||
```
|
||||
┌─────────────────────────────────────┐
|
||||
│ 搜索界面层 │
|
||||
│ (Search UI Components) │
|
||||
├─────────────────────────────────────┤
|
||||
│ GlobalSearch 模块 │
|
||||
│ ┌──────────┬──────────┬──────────┐ │
|
||||
│ │ 搜索引擎 │ 索引管理 │ 结果处理 │ │
|
||||
│ ├──────────┼──────────┼──────────┤ │
|
||||
│ │ 建议系统 │ 历史管理 │ 缓存层 │ │
|
||||
│ └──────────┴──────────┴──────────┘ │
|
||||
├─────────────────────────────────────┤
|
||||
│ 模块搜索接口 │
|
||||
│ ┌──────────┬──────────┬──────────┐ │
|
||||
│ │ 车辆模块 │ 订单模块 │ 设置模块 │ │
|
||||
│ └──────────┴──────────┴──────────┘ │
|
||||
├─────────────────────────────────────┤
|
||||
│ 数据存储层 │
|
||||
│ (Local DB + Remote Index) │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 核心组件
|
||||
|
||||
#### 1. 通用搜索组件 (GlobalSearchCommonWidget)
|
||||
|
||||
基于真实项目代码的通用搜索组件:
|
||||
|
||||
```dart
|
||||
/// 全局搜索通用组件
|
||||
class GlobalSearchCommonWidget extends StatefulWidget {
|
||||
const GlobalSearchCommonWidget({
|
||||
Key? key,
|
||||
required this.selectCommonSearchItem
|
||||
}) : super(key: key);
|
||||
|
||||
final SelectCommonSearch selectCommonSearchItem;
|
||||
|
||||
@override
|
||||
State<GlobalSearchCommonWidget> createState() =>
|
||||
_GlobalSearchCommonWidgetState();
|
||||
}
|
||||
|
||||
/// 搜索项目数据模型
|
||||
class SearchItemBean {
|
||||
String name;
|
||||
String event;
|
||||
|
||||
SearchItemBean({required this.name, required this.event});
|
||||
}
|
||||
|
||||
/// 选择通用搜索项回调
|
||||
typedef SelectCommonSearch = void Function(SearchItemBean commonSearchItem);
|
||||
```
|
||||
|
||||
#### 2. 搜索组件实现
|
||||
|
||||
```dart
|
||||
class _GlobalSearchCommonWidgetState extends State<GlobalSearchCommonWidget> {
|
||||
List<SearchItemBean> commonSearchBeanList = [];
|
||||
String tips = '';
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (commonSearchBeanList.isEmpty) {
|
||||
return Container();
|
||||
}
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Container(
|
||||
padding: EdgeInsets.fromLTRB(15, 15, 12, 0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
tips,
|
||||
style: OneTextStyle.content(color: OneColors.tc),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
Wrap(
|
||||
spacing: 8,
|
||||
runSpacing: 12,
|
||||
children: _buildHistoryTag(commonSearchBeanList),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
/// 构建历史搜索标签
|
||||
List<Widget> _buildHistoryTag(List<SearchItemBean> historys) {
|
||||
List<Widget> historyWidgets = [];
|
||||
for (int i = 0; i < historys.length; i++) {
|
||||
var displayName = historys[i].name;
|
||||
if (displayName.length > 8) {
|
||||
displayName = displayName.substring(0, 8) + '...';
|
||||
}
|
||||
historyWidgets.add(InkWell(
|
||||
onTap: () {
|
||||
widget.selectCommonSearchItem(historys[i]);
|
||||
},
|
||||
child: Container(
|
||||
padding: EdgeInsets.fromLTRB(5, 0, 5, 0),
|
||||
decoration: BoxDecoration(
|
||||
color: OneColors.bgcSub1,
|
||||
borderRadius: BorderRadius.all(Radius.circular(2)),
|
||||
),
|
||||
child: Text(
|
||||
displayName,
|
||||
style: OneTextStyle.content(
|
||||
color: OneColors.tc.withOpacity(0.55),
|
||||
),
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
return historyWidgets;
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
getCommonSearchResult();
|
||||
}
|
||||
|
||||
/// 获取通用搜索结果
|
||||
void getCommonSearchResult() {
|
||||
// 实际项目中的搜索数据获取逻辑
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 3. 搜索组件架构
|
||||
|
||||
实际项目包含的搜索组件:
|
||||
|
||||
- **QuicklyAccess.dart**: 快速访问组件
|
||||
- **search_all_result_widget.dart**: 全部搜索结果组件
|
||||
- **search_common_widget.dart**: 通用搜索组件
|
||||
- **search_event_result_widget.dart**: 事件搜索结果组件
|
||||
- **search_history_widget.dart**: 搜索历史组件
|
||||
- **search_input_TextField_widget.dart**: 搜索输入框组件
|
||||
- **search_mall_result_widget.dart**: 商城搜索结果组件
|
||||
- **search_post_result_widget.dart**: 帖子搜索结果组件
|
||||
- **search_result_widget.dart**: 搜索结果组件
|
||||
|
||||
## 数据模型
|
||||
|
||||
### 搜索查询模型
|
||||
```dart
|
||||
class SearchQuery {
|
||||
final String keyword;
|
||||
final List<String> categories;
|
||||
final SearchScope scope;
|
||||
final SortOption sortBy;
|
||||
final int page;
|
||||
final int pageSize;
|
||||
final Map<String, dynamic> filters;
|
||||
final bool includeHistory;
|
||||
}
|
||||
|
||||
enum SearchScope {
|
||||
all, // 全部内容
|
||||
vehicle, // 车辆相关
|
||||
order, // 订单相关
|
||||
service, // 服务相关
|
||||
settings, // 设置相关
|
||||
help // 帮助文档
|
||||
}
|
||||
|
||||
enum SortOption {
|
||||
relevance, // 相关性
|
||||
time, // 时间
|
||||
popularity, // 热度
|
||||
alphabetical // 字母顺序
|
||||
}
|
||||
```
|
||||
|
||||
### 搜索结果模型
|
||||
```dart
|
||||
class SearchResult {
|
||||
final String query;
|
||||
final int totalCount;
|
||||
final List<SearchResultItem> items;
|
||||
final List<SearchSuggestion> suggestions;
|
||||
final Duration searchTime;
|
||||
final Map<String, int> categoryCount;
|
||||
final bool hasMore;
|
||||
}
|
||||
|
||||
class SearchResultItem {
|
||||
final String id;
|
||||
final String title;
|
||||
final String? subtitle;
|
||||
final String? description;
|
||||
final String category;
|
||||
final String moduleId;
|
||||
final String? imageUrl;
|
||||
final double relevanceScore;
|
||||
final DateTime? timestamp;
|
||||
final Map<String, dynamic> metadata;
|
||||
final List<HighlightRange> highlights;
|
||||
}
|
||||
```
|
||||
|
||||
### 搜索建议模型
|
||||
```dart
|
||||
class SearchSuggestion {
|
||||
final String text;
|
||||
final SuggestionType type;
|
||||
final String? category;
|
||||
final int frequency;
|
||||
final double relevance;
|
||||
final Map<String, dynamic>? metadata;
|
||||
}
|
||||
|
||||
enum SuggestionType {
|
||||
keyword, // 关键词建议
|
||||
history, // 历史搜索
|
||||
popular, // 热门搜索
|
||||
completion, // 自动补全
|
||||
correction // 拼写纠错
|
||||
}
|
||||
```
|
||||
|
||||
## API 接口
|
||||
|
||||
### 搜索接口
|
||||
```dart
|
||||
abstract class GlobalSearchService {
|
||||
// 执行全局搜索
|
||||
Future<ApiResponse<SearchResult>> search(SearchRequest request);
|
||||
|
||||
// 获取搜索建议
|
||||
Future<ApiResponse<List<SearchSuggestion>>> getSuggestions(SuggestionRequest request);
|
||||
|
||||
// 获取热门搜索
|
||||
Future<ApiResponse<List<String>>> getPopularSearches();
|
||||
|
||||
// 获取搜索历史
|
||||
Future<ApiResponse<List<SearchRecord>>> getSearchHistory(HistoryRequest request);
|
||||
}
|
||||
```
|
||||
|
||||
### 索引管理接口
|
||||
```dart
|
||||
abstract class SearchIndexService {
|
||||
// 更新搜索索引
|
||||
Future<ApiResponse<bool>> updateSearchIndex(UpdateIndexRequest request);
|
||||
|
||||
// 删除搜索索引
|
||||
Future<ApiResponse<bool>> deleteSearchIndex(DeleteIndexRequest request);
|
||||
|
||||
// 获取索引状态
|
||||
Future<ApiResponse<IndexStatus>> getIndexStatus(String moduleId);
|
||||
}
|
||||
```
|
||||
|
||||
### 搜索提供者接口
|
||||
```dart
|
||||
abstract class SearchProvider {
|
||||
// 搜索提供者ID
|
||||
String get providerId;
|
||||
|
||||
// 支持的搜索类别
|
||||
List<String> get supportedCategories;
|
||||
|
||||
// 执行搜索
|
||||
Future<List<SearchResultItem>> search(SearchQuery query);
|
||||
|
||||
// 获取可搜索项目
|
||||
Future<List<SearchableItem>> getSearchableItems();
|
||||
|
||||
// 获取搜索建议
|
||||
Future<List<SearchSuggestion>> getSuggestions(String input);
|
||||
}
|
||||
```
|
||||
|
||||
## 配置管理
|
||||
|
||||
### 搜索配置
|
||||
```dart
|
||||
class GlobalSearchConfig {
|
||||
final int maxResults;
|
||||
final int suggestionLimit;
|
||||
final bool enableHistory;
|
||||
final bool enableSuggestions;
|
||||
final Duration cacheExpiry;
|
||||
final List<String> enabledModules;
|
||||
final Map<String, double> categoryWeights;
|
||||
|
||||
static const GlobalSearchConfig defaultConfig = GlobalSearchConfig(
|
||||
maxResults: 100,
|
||||
suggestionLimit: 10,
|
||||
enableHistory: true,
|
||||
enableSuggestions: true,
|
||||
cacheExpiry: Duration(minutes: 30),
|
||||
enabledModules: ['vehicle', 'order', 'service', 'settings'],
|
||||
categoryWeights: {
|
||||
'vehicle': 1.0,
|
||||
'order': 0.8,
|
||||
'service': 0.9,
|
||||
'settings': 0.6,
|
||||
},
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### 索引配置
|
||||
```dart
|
||||
class SearchIndexConfig {
|
||||
final bool enableRealTimeIndex;
|
||||
final Duration indexUpdateInterval;
|
||||
final int maxIndexSize;
|
||||
final List<String> indexedFields;
|
||||
final Map<String, int> fieldWeights;
|
||||
|
||||
static const SearchIndexConfig defaultIndexConfig = SearchIndexConfig(
|
||||
enableRealTimeIndex: true,
|
||||
indexUpdateInterval: Duration(minutes: 5),
|
||||
maxIndexSize: 10000,
|
||||
indexedFields: ['title', 'description', 'tags', 'content'],
|
||||
fieldWeights: {
|
||||
'title': 3,
|
||||
'description': 2,
|
||||
'tags': 2,
|
||||
'content': 1,
|
||||
},
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## 使用示例
|
||||
|
||||
### 基本搜索功能
|
||||
```dart
|
||||
// 初始化全局搜索
|
||||
final globalSearch = GlobalSearchEngine.instance;
|
||||
await globalSearch.initialize(GlobalSearchConfig.defaultConfig);
|
||||
|
||||
// 执行搜索
|
||||
final searchQuery = SearchQuery(
|
||||
keyword: '充电',
|
||||
categories: ['vehicle', 'service'],
|
||||
scope: SearchScope.all,
|
||||
sortBy: SortOption.relevance,
|
||||
page: 1,
|
||||
pageSize: 20,
|
||||
);
|
||||
|
||||
final searchResult = await globalSearch.search(searchQuery);
|
||||
|
||||
// 处理搜索结果
|
||||
for (final item in searchResult.items) {
|
||||
print('${item.title}: ${item.description}');
|
||||
print('类别: ${item.category}, 相关性: ${item.relevanceScore}');
|
||||
}
|
||||
```
|
||||
|
||||
### 搜索建议功能
|
||||
```dart
|
||||
// 获取输入建议
|
||||
final suggestions = await globalSearch.getSuggestions('充电');
|
||||
|
||||
// 显示建议列表
|
||||
for (final suggestion in suggestions) {
|
||||
switch (suggestion.type) {
|
||||
case SuggestionType.completion:
|
||||
print('补全: ${suggestion.text}');
|
||||
break;
|
||||
case SuggestionType.history:
|
||||
print('历史: ${suggestion.text}');
|
||||
break;
|
||||
case SuggestionType.popular:
|
||||
print('热门: ${suggestion.text}');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 获取热门搜索
|
||||
final popularSearches = await globalSearch.getPopularSearches();
|
||||
print('热门搜索: ${popularSearches.join(', ')}');
|
||||
```
|
||||
|
||||
### 搜索历史管理
|
||||
```dart
|
||||
// 添加搜索记录
|
||||
final searchRecord = SearchRecord(
|
||||
query: '充电站',
|
||||
timestamp: DateTime.now(),
|
||||
resultCount: 25,
|
||||
category: 'vehicle',
|
||||
);
|
||||
|
||||
await SearchHistoryManager.instance.addSearchRecord(searchRecord);
|
||||
|
||||
// 获取搜索历史
|
||||
final history = await SearchHistoryManager.instance.getSearchHistory(limit: 10);
|
||||
|
||||
for (final record in history) {
|
||||
print('${record.query} - ${record.timestamp}');
|
||||
}
|
||||
|
||||
// 清空搜索历史
|
||||
await SearchHistoryManager.instance.clearSearchHistory();
|
||||
```
|
||||
|
||||
### 注册搜索提供者
|
||||
```dart
|
||||
// 实现搜索提供者
|
||||
class VehicleSearchProvider extends SearchProvider {
|
||||
@override
|
||||
String get providerId => 'vehicle_search';
|
||||
|
||||
@override
|
||||
List<String> get supportedCategories => ['vehicle', 'charging', 'maintenance'];
|
||||
|
||||
@override
|
||||
Future<List<SearchResultItem>> search(SearchQuery query) async {
|
||||
// 实现车辆相关内容搜索
|
||||
final vehicles = await vehicleService.searchVehicles(query.keyword);
|
||||
|
||||
return vehicles.map((vehicle) => SearchResultItem(
|
||||
id: vehicle.id,
|
||||
title: vehicle.name,
|
||||
description: vehicle.description,
|
||||
category: 'vehicle',
|
||||
moduleId: 'app_car',
|
||||
relevanceScore: calculateRelevance(query.keyword, vehicle),
|
||||
)).toList();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<SearchSuggestion>> getSuggestions(String input) async {
|
||||
// 返回车辆相关搜索建议
|
||||
return vehicleService.getSearchSuggestions(input);
|
||||
}
|
||||
}
|
||||
|
||||
// 注册搜索提供者
|
||||
globalSearch.registerSearchProvider(VehicleSearchProvider());
|
||||
```
|
||||
|
||||
## 测试策略
|
||||
|
||||
### 单元测试
|
||||
```dart
|
||||
group('GlobalSearch Tests', () {
|
||||
test('should return search results', () async {
|
||||
// Given
|
||||
final searchEngine = GlobalSearchEngine();
|
||||
final query = SearchQuery(keyword: 'test', scope: SearchScope.all);
|
||||
|
||||
// When
|
||||
final result = await searchEngine.search(query);
|
||||
|
||||
// Then
|
||||
expect(result.items, isNotEmpty);
|
||||
expect(result.query, 'test');
|
||||
});
|
||||
|
||||
test('should provide search suggestions', () async {
|
||||
// Given
|
||||
final suggestionSystem = SearchSuggestionSystem();
|
||||
|
||||
// When
|
||||
final suggestions = await suggestionSystem.generateSuggestions('cha');
|
||||
|
||||
// Then
|
||||
expect(suggestions, isNotEmpty);
|
||||
expect(suggestions.first.text, contains('cha'));
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### 集成测试
|
||||
```dart
|
||||
group('Search Integration Tests', () {
|
||||
testWidgets('complete search flow', (tester) async {
|
||||
// 1. 输入搜索关键词
|
||||
await tester.enterText(find.byKey(Key('search_input')), '充电');
|
||||
|
||||
// 2. 验证搜索建议显示
|
||||
expect(find.text('充电站'), findsOneWidget);
|
||||
expect(find.text('充电桩'), findsOneWidget);
|
||||
|
||||
// 3. 执行搜索
|
||||
await tester.tap(find.byKey(Key('search_button')));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// 4. 验证搜索结果
|
||||
expect(find.byType(SearchResultItem), findsWidgets);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
## 性能优化
|
||||
|
||||
### 搜索性能优化
|
||||
- **索引优化**:使用倒排索引提高搜索速度
|
||||
- **缓存策略**:热门搜索结果缓存
|
||||
- **分页加载**:大结果集分页加载
|
||||
- **异步处理**:搜索操作异步处理
|
||||
|
||||
### 内存优化
|
||||
- **结果限制**:限制搜索结果数量
|
||||
- **懒加载**:搜索结果懒加载
|
||||
- **对象池**:复用搜索对象
|
||||
- **内存回收**:及时回收不用的搜索数据
|
||||
|
||||
## 算法和策略
|
||||
|
||||
### 相关性算法
|
||||
```dart
|
||||
class RelevanceCalculator {
|
||||
// 计算文本相关性
|
||||
double calculateTextRelevance(String query, String text);
|
||||
|
||||
// 计算标题权重
|
||||
double calculateTitleWeight(String query, String title);
|
||||
|
||||
// 计算类别权重
|
||||
double calculateCategoryWeight(String category);
|
||||
|
||||
// 计算综合得分
|
||||
double calculateFinalScore(Map<String, double> scores);
|
||||
}
|
||||
```
|
||||
|
||||
### 搜索优化策略
|
||||
- **查询扩展**:同义词和相关词扩展
|
||||
- **模糊匹配**:支持模糊匹配搜索
|
||||
- **权重调整**:动态调整搜索权重
|
||||
- **个性化排序**:基于用户行为的个性化排序
|
||||
|
||||
## 版本历史
|
||||
|
||||
### v0.3.2+5 (当前版本)
|
||||
- 新增语义搜索功能
|
||||
- 优化搜索性能和准确性
|
||||
- 支持多语言搜索
|
||||
- 修复搜索结果排序问题
|
||||
|
||||
### v0.3.1
|
||||
- 支持实时搜索建议
|
||||
- 新增搜索历史管理
|
||||
- 优化搜索索引结构
|
||||
- 改进搜索结果展示
|
||||
|
||||
## 依赖关系
|
||||
|
||||
### 内部依赖
|
||||
- `basic_storage`: 本地数据存储
|
||||
- `basic_network`: 网络请求服务
|
||||
- `basic_utils`: 工具类库
|
||||
- `basic_logger`: 日志记录
|
||||
|
||||
### 外部依赖
|
||||
- `sqflite`: 本地数据库
|
||||
- `fuzzywuzzy`: 模糊匹配算法
|
||||
- `rxdart`: 响应式编程
|
||||
- `collection`: 集合工具
|
||||
|
||||
## 总结
|
||||
|
||||
`GlobalSearch` 模块为 OneApp 提供了强大的全局搜索能力,通过统一的搜索接口、智能的搜索建议、完善的历史管理和优化的搜索结果,为用户提供了高效、精准的搜索体验。该模块的设计充分考虑了可扩展性、性能优化和用户体验,能够很好地支撑应用的搜索需求。
|
||||
272
service_component/README.md
Normal file
272
service_component/README.md
Normal file
@@ -0,0 +1,272 @@
|
||||
# Service Component 服务组件模块群
|
||||
|
||||
## 模块群概述
|
||||
|
||||
Service Component 模块群是 OneApp 的服务组件集合,提供了各种通用的业务服务组件和工具。该模块群包含了配置管理、全局搜索、伴侣应用、弹窗管理、分享功能等跨模块的通用服务组件。
|
||||
|
||||
## 子模块列表
|
||||
|
||||
### 核心服务组件
|
||||
1. **[app_configuration](./app_configuration.md)** - 应用配置管理模块
|
||||
- 远程配置管理
|
||||
- 本地配置缓存
|
||||
- 配置热更新
|
||||
- 环境配置切换
|
||||
|
||||
2. **[clr_configuration](./clr_configuration.md)** - 配置服务SDK
|
||||
- 配置API封装
|
||||
- 配置数据模型
|
||||
- 配置同步机制
|
||||
- 配置变更通知
|
||||
|
||||
3. **[GlobalSearch](./GlobalSearch.md)** - 全局搜索模块
|
||||
- 跨模块内容搜索
|
||||
- 智能搜索建议
|
||||
- 搜索历史管理
|
||||
- 搜索结果优化
|
||||
|
||||
4. **[oneapp_companion](./oneapp_companion.md)** - 伴侣应用模块
|
||||
- 多设备协同
|
||||
- 数据同步
|
||||
- 远程控制
|
||||
- 设备管理
|
||||
|
||||
5. **[oneapp_popup](./oneapp_popup.md)** - 弹窗管理模块
|
||||
- 统一弹窗管理
|
||||
- 弹窗优先级控制
|
||||
- 弹窗样式定制
|
||||
- 弹窗生命周期
|
||||
|
||||
6. **[ShareToFriends](./ShareToFriends.md)** - 分享功能模块
|
||||
- 社交平台分享
|
||||
- 自定义分享内容
|
||||
- 分享统计分析
|
||||
- 分享权限控制
|
||||
|
||||
## 功能特性
|
||||
|
||||
### 核心功能
|
||||
1. **配置管理服务**
|
||||
- 集中化配置管理
|
||||
- 动态配置下发
|
||||
- 配置版本控制
|
||||
- 配置回滚机制
|
||||
|
||||
2. **搜索服务**
|
||||
- 全文搜索引擎
|
||||
- 智能搜索推荐
|
||||
- 搜索结果排序
|
||||
- 搜索性能优化
|
||||
|
||||
3. **设备协同服务**
|
||||
- 多设备数据同步
|
||||
- 跨设备操作控制
|
||||
- 设备状态监控
|
||||
- 设备权限管理
|
||||
|
||||
4. **用户交互服务**
|
||||
- 弹窗统一管理
|
||||
- 分享功能集成
|
||||
- 用户反馈收集
|
||||
- 交互体验优化
|
||||
|
||||
## 技术架构
|
||||
|
||||
### 服务架构图
|
||||
```
|
||||
应用层 (App Layer)
|
||||
↓
|
||||
服务组件层 (Service Components)
|
||||
↓
|
||||
基础服务层 (Basic Services)
|
||||
↓
|
||||
平台能力层 (Platform Capabilities)
|
||||
```
|
||||
|
||||
### 组件交互图
|
||||
```mermaid
|
||||
graph TD
|
||||
A[App Configuration] --> B[Configuration SDK]
|
||||
C[Global Search] --> D[Search Engine]
|
||||
E[Companion App] --> F[Sync Service]
|
||||
G[Popup Manager] --> H[UI Controller]
|
||||
I[Share Service] --> J[Platform APIs]
|
||||
|
||||
B --> K[Basic Storage]
|
||||
D --> K
|
||||
F --> L[Basic Network]
|
||||
H --> M[Basic UI]
|
||||
J --> N[Basic Platform]
|
||||
```
|
||||
|
||||
## 设计原则
|
||||
|
||||
### 1. 模块化设计
|
||||
- **独立部署**: 每个组件可独立部署和更新
|
||||
- **接口标准**: 统一的服务接口规范
|
||||
- **依赖管理**: 清晰的依赖关系定义
|
||||
- **版本兼容**: 向后兼容的版本策略
|
||||
|
||||
### 2. 服务化架构
|
||||
- **微服务**: 服务组件微服务化
|
||||
- **API网关**: 统一的API入口
|
||||
- **服务发现**: 动态服务发现机制
|
||||
- **负载均衡**: 服务负载均衡
|
||||
|
||||
### 3. 数据一致性
|
||||
- **事务管理**: 跨服务事务协调
|
||||
- **数据同步**: 多服务数据同步
|
||||
- **冲突解决**: 数据冲突解决策略
|
||||
- **最终一致性**: 最终一致性保证
|
||||
|
||||
## 通用能力
|
||||
|
||||
### 配置管理能力
|
||||
```dart
|
||||
// 获取配置
|
||||
final config = await ConfigService.getConfig('feature_flags');
|
||||
|
||||
// 监听配置变化
|
||||
ConfigService.onConfigChanged('feature_flags').listen((newConfig) {
|
||||
// 处理配置变化
|
||||
});
|
||||
|
||||
// 本地配置缓存
|
||||
await ConfigService.setCachedConfig('user_preferences', userConfig);
|
||||
```
|
||||
|
||||
### 搜索能力
|
||||
```dart
|
||||
// 全局搜索
|
||||
final results = await GlobalSearchService.search(
|
||||
query: '车辆',
|
||||
categories: ['vehicle', 'service', 'help'],
|
||||
);
|
||||
|
||||
// 搜索建议
|
||||
final suggestions = await GlobalSearchService.getSuggestions('车');
|
||||
|
||||
// 搜索历史
|
||||
final history = await GlobalSearchService.getSearchHistory();
|
||||
```
|
||||
|
||||
### 弹窗管理能力
|
||||
```dart
|
||||
// 显示弹窗
|
||||
PopupManager.show(
|
||||
popup: CustomPopup(
|
||||
title: '提示',
|
||||
content: '是否确认操作?',
|
||||
priority: PopupPriority.high,
|
||||
),
|
||||
);
|
||||
|
||||
// 弹窗队列管理
|
||||
PopupManager.enqueue(popupList);
|
||||
|
||||
// 弹窗生命周期
|
||||
PopupManager.onPopupShown.listen((popup) {
|
||||
// 弹窗显示回调
|
||||
});
|
||||
```
|
||||
|
||||
## 详细模块文档
|
||||
|
||||
- [App Configuration - 应用配置管理](./app_configuration.md)
|
||||
- [CLR Configuration - 配置服务SDK](./clr_configuration.md)
|
||||
- [Global Search - 全局搜索](./GlobalSearch.md)
|
||||
- [OneApp Companion - 伴侣应用](./oneapp_companion.md)
|
||||
- [OneApp Popup - 弹窗管理](./oneapp_popup.md)
|
||||
- [Share To Friends - 分享功能](./ShareToFriends.md)
|
||||
|
||||
## 开发指南
|
||||
|
||||
### 环境要求
|
||||
- Flutter >=3.0.0
|
||||
- Dart >=3.0.0 <4.0.0
|
||||
- Android SDK >=21
|
||||
- iOS >=11.0
|
||||
|
||||
### 依赖管理
|
||||
```yaml
|
||||
dependencies:
|
||||
# 服务组件
|
||||
app_configuration:
|
||||
path: ../oneapp_service_component/app_configuration
|
||||
oneapp_companion:
|
||||
path: ../oneapp_service_component/oneapp_companion
|
||||
oneapp_popup:
|
||||
path: ../oneapp_service_component/oneapp_popup
|
||||
```
|
||||
|
||||
### 服务初始化
|
||||
```dart
|
||||
Future<void> initializeServiceComponents() async {
|
||||
// 初始化配置服务
|
||||
await ConfigurationService.initialize();
|
||||
|
||||
// 初始化搜索服务
|
||||
await GlobalSearchService.initialize();
|
||||
|
||||
// 初始化伴侣应用服务
|
||||
await CompanionService.initialize();
|
||||
|
||||
// 初始化弹窗管理器
|
||||
PopupManager.initialize();
|
||||
|
||||
// 初始化分享服务
|
||||
await ShareService.initialize();
|
||||
}
|
||||
```
|
||||
|
||||
## 性能优化
|
||||
|
||||
### 1. 缓存策略
|
||||
- **配置缓存**: 本地配置缓存减少网络请求
|
||||
- **搜索缓存**: 搜索结果智能缓存
|
||||
- **数据预加载**: 关键数据预加载
|
||||
- **懒加载**: 按需加载服务组件
|
||||
|
||||
### 2. 网络优化
|
||||
- **请求合并**: 批量请求减少网络开销
|
||||
- **数据压缩**: 传输数据压缩
|
||||
- **CDN加速**: 静态资源CDN分发
|
||||
- **离线支持**: 关键功能离线可用
|
||||
|
||||
### 3. 内存管理
|
||||
- **资源释放**: 及时释放不需要的资源
|
||||
- **内存监控**: 监控内存使用情况
|
||||
- **对象池**: 复用频繁创建的对象
|
||||
- **弱引用**: 避免内存泄漏
|
||||
|
||||
## 监控和诊断
|
||||
|
||||
### 服务监控
|
||||
- **服务健康检查**: 定期检查服务状态
|
||||
- **性能指标监控**: 监控关键性能指标
|
||||
- **错误日志收集**: 收集和分析错误日志
|
||||
- **用户行为分析**: 分析用户使用模式
|
||||
|
||||
### 故障诊断
|
||||
- **链路追踪**: 跟踪服务调用链路
|
||||
- **异常告警**: 异常情况实时告警
|
||||
- **故障恢复**: 自动故障恢复机制
|
||||
- **降级策略**: 服务降级保证可用性
|
||||
|
||||
## 安全考虑
|
||||
|
||||
### 数据安全
|
||||
- **数据加密**: 敏感数据加密存储和传输
|
||||
- **访问控制**: 基于角色的访问控制
|
||||
- **审计日志**: 详细的操作审计日志
|
||||
- **数据脱敏**: 敏感数据脱敏处理
|
||||
|
||||
### 隐私保护
|
||||
- **用户同意**: 明确的用户数据使用同意
|
||||
- **数据最小化**: 仅收集必要的用户数据
|
||||
- **匿名化**: 用户数据匿名化处理
|
||||
- **数据删除**: 用户数据删除权支持
|
||||
|
||||
## 总结
|
||||
|
||||
Service Component 模块群为 OneApp 提供了丰富的通用服务组件,通过模块化设计和服务化架构,实现了高内聚、低耦合的服务体系。这些组件不仅提升了开发效率,也保证了服务的一致性和可维护性,为整个应用生态提供了坚实的技术支撑。
|
||||
566
service_component/ShareToFriends.md
Normal file
566
service_component/ShareToFriends.md
Normal file
@@ -0,0 +1,566 @@
|
||||
# ShareToFriends - 分享功能模块
|
||||
|
||||
## 模块概述
|
||||
|
||||
`ShareToFriends` 是 OneApp 的分享功能模块,提供了完整的社交分享解决方案。该模块支持多种社交平台分享、自定义分享内容、分享统计分析和权限控制等功能,为用户提供便捷的内容分享体验。
|
||||
|
||||
## 核心功能
|
||||
|
||||
### 1. 社交平台分享
|
||||
- **多平台支持**:支持微信、QQ、微博、抖音等主流平台
|
||||
- **原生集成**:深度集成各平台原生分享能力
|
||||
- **格式适配**:自动适配各平台的内容格式要求
|
||||
- **状态跟踪**:跟踪分享状态和结果反馈
|
||||
|
||||
### 2. 自定义分享内容
|
||||
- **内容模板**:提供丰富的分享内容模板
|
||||
- **动态生成**:根据分享内容动态生成分享素材
|
||||
- **多媒体支持**:支持文字、图片、视频、链接分享
|
||||
- **品牌定制**:支持品牌元素的自定义添加
|
||||
|
||||
### 3. 分享统计分析
|
||||
- **分享数据统计**:统计分享次数、平台分布等数据
|
||||
- **用户行为分析**:分析用户分享行为和偏好
|
||||
- **转化率跟踪**:跟踪分享带来的转化效果
|
||||
- **热点内容识别**:识别热门分享内容
|
||||
|
||||
### 4. 分享权限控制
|
||||
- **内容权限**:控制可分享的内容范围
|
||||
- **用户权限**:基于用户角色的分享权限
|
||||
- **平台限制**:特定平台的分享限制
|
||||
- **敏感内容过滤**:过滤敏感或不当内容
|
||||
|
||||
## 技术架构
|
||||
|
||||
### 架构设计
|
||||
```
|
||||
┌─────────────────────────────────────┐
|
||||
│ 应用界面层 │
|
||||
│ (Share UI Components) │
|
||||
├─────────────────────────────────────┤
|
||||
│ ShareToFriends │
|
||||
│ ┌──────────┬──────────┬──────────┐ │
|
||||
│ │ 分享管理 │ 内容生成 │ 平台适配 │ │
|
||||
│ ├──────────┼──────────┼──────────┤ │
|
||||
│ │ 统计分析 │ 权限控制 │ 缓存管理 │ │
|
||||
│ └──────────┴──────────┴──────────┘ │
|
||||
├─────────────────────────────────────┤
|
||||
│ 平台SDK层 │
|
||||
│ ┌──────────┬──────────┬──────────┐ │
|
||||
│ │ 微信SDK │ QQ SDK │ 微博SDK │ │
|
||||
│ └──────────┴──────────┴──────────┘ │
|
||||
├─────────────────────────────────────┤
|
||||
│ 系统分享接口 │
|
||||
│ (System Share APIs) │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 核心组件
|
||||
|
||||
#### 1. 分享管理器 (ShareManager)
|
||||
```dart
|
||||
class ShareManager {
|
||||
// 执行分享
|
||||
Future<ShareResult> share(ShareRequest request);
|
||||
|
||||
// 获取可用的分享平台
|
||||
Future<List<SharePlatform>> getAvailablePlatforms();
|
||||
|
||||
// 检查平台可用性
|
||||
Future<bool> isPlatformAvailable(SharePlatformType platform);
|
||||
|
||||
// 注册分享平台
|
||||
void registerPlatform(SharePlatform platform);
|
||||
}
|
||||
```
|
||||
|
||||
#### 2. 内容生成器 (ContentGenerator)
|
||||
```dart
|
||||
class ShareContentGenerator {
|
||||
// 生成分享内容
|
||||
Future<ShareContent> generateContent(ContentTemplate template, Map<String, dynamic> data);
|
||||
|
||||
// 创建分享图片
|
||||
Future<File> createShareImage(ShareImageConfig config);
|
||||
|
||||
// 生成分享链接
|
||||
Future<String> generateShareLink(ShareLinkConfig config);
|
||||
|
||||
// 格式化分享文本
|
||||
String formatShareText(String template, Map<String, String> variables);
|
||||
}
|
||||
```
|
||||
|
||||
#### 3. 平台适配器 (PlatformAdapter)
|
||||
```dart
|
||||
class SharePlatformAdapter {
|
||||
// 适配分享内容
|
||||
ShareContent adaptContent(ShareContent content, SharePlatformType platform);
|
||||
|
||||
// 验证内容格式
|
||||
ValidationResult validateContent(ShareContent content, SharePlatformType platform);
|
||||
|
||||
// 获取平台限制
|
||||
PlatformLimitations getPlatformLimitations(SharePlatformType platform);
|
||||
|
||||
// 转换内容格式
|
||||
ShareContent convertContentFormat(ShareContent content, ContentFormat targetFormat);
|
||||
}
|
||||
```
|
||||
|
||||
#### 4. 统计分析器 (ShareAnalytics)
|
||||
```dart
|
||||
class ShareAnalytics {
|
||||
// 记录分享事件
|
||||
Future<void> recordShareEvent(ShareEvent event);
|
||||
|
||||
// 获取分享统计
|
||||
Future<ShareStatistics> getShareStatistics(StatisticsQuery query);
|
||||
|
||||
// 分析用户分享行为
|
||||
Future<UserShareBehavior> analyzeUserBehavior(String userId);
|
||||
|
||||
// 获取热门分享内容
|
||||
Future<List<PopularContent>> getPopularContent(TimeRange timeRange);
|
||||
}
|
||||
```
|
||||
|
||||
## 数据模型
|
||||
|
||||
### 分享请求模型
|
||||
```dart
|
||||
class ShareRequest {
|
||||
final String id;
|
||||
final ShareContent content;
|
||||
final SharePlatformType platform;
|
||||
final ShareOptions options;
|
||||
final String? userId;
|
||||
final Map<String, dynamic> metadata;
|
||||
final DateTime timestamp;
|
||||
}
|
||||
|
||||
class ShareContent {
|
||||
final String? title;
|
||||
final String? description;
|
||||
final String? text;
|
||||
final List<String> images;
|
||||
final String? video;
|
||||
final String? url;
|
||||
final String? thumbnailUrl;
|
||||
final ContentType type;
|
||||
final Map<String, dynamic> extras;
|
||||
}
|
||||
|
||||
enum ContentType {
|
||||
text, // 纯文本
|
||||
image, // 图片
|
||||
video, // 视频
|
||||
link, // 链接
|
||||
miniProgram, // 小程序
|
||||
music, // 音乐
|
||||
file // 文件
|
||||
}
|
||||
```
|
||||
|
||||
### 分享平台模型
|
||||
```dart
|
||||
enum SharePlatformType {
|
||||
wechat, // 微信好友
|
||||
wechatMoments, // 微信朋友圈
|
||||
qq, // QQ好友
|
||||
qzone, // QQ空间
|
||||
weibo, // 新浪微博
|
||||
douyin, // 抖音
|
||||
system, // 系统分享
|
||||
copy, // 复制链接
|
||||
email, // 邮件
|
||||
sms // 短信
|
||||
}
|
||||
|
||||
class SharePlatform {
|
||||
final SharePlatformType type;
|
||||
final String name;
|
||||
final String packageName;
|
||||
final String iconUrl;
|
||||
final bool isInstalled;
|
||||
final bool isEnabled;
|
||||
final PlatformLimitations limitations;
|
||||
final Map<String, dynamic> config;
|
||||
}
|
||||
```
|
||||
|
||||
### 分享结果模型
|
||||
```dart
|
||||
class ShareResult {
|
||||
final bool isSuccess;
|
||||
final SharePlatformType platform;
|
||||
final String? shareId;
|
||||
final String? errorMessage;
|
||||
final int? errorCode;
|
||||
final DateTime timestamp;
|
||||
final Map<String, dynamic> extraData;
|
||||
}
|
||||
|
||||
class ShareStatistics {
|
||||
final int totalShares;
|
||||
final Map<SharePlatformType, int> platformDistribution;
|
||||
final Map<ContentType, int> contentTypeDistribution;
|
||||
final List<ShareTrend> trends;
|
||||
final double averageSharesPerUser;
|
||||
final List<TopSharedContent> topContent;
|
||||
}
|
||||
```
|
||||
|
||||
## API 接口
|
||||
|
||||
### 分享接口
|
||||
```dart
|
||||
abstract class ShareService {
|
||||
// 执行分享
|
||||
Future<ApiResponse<ShareResult>> executeShare(ShareRequest request);
|
||||
|
||||
// 获取分享平台列表
|
||||
Future<ApiResponse<List<SharePlatform>>> getSharePlatforms();
|
||||
|
||||
// 预览分享内容
|
||||
Future<ApiResponse<SharePreview>> previewShare(PreviewRequest request);
|
||||
|
||||
// 获取分享历史
|
||||
Future<ApiResponse<List<ShareRecord>>> getShareHistory(HistoryQuery query);
|
||||
}
|
||||
```
|
||||
|
||||
### 内容生成接口
|
||||
```dart
|
||||
abstract class ShareContentService {
|
||||
// 生成分享内容
|
||||
Future<ApiResponse<ShareContent>> generateShareContent(ContentGenerationRequest request);
|
||||
|
||||
// 创建分享海报
|
||||
Future<ApiResponse<String>> createSharePoster(PosterCreationRequest request);
|
||||
|
||||
// 获取内容模板
|
||||
Future<ApiResponse<List<ContentTemplate>>> getContentTemplates(String category);
|
||||
}
|
||||
```
|
||||
|
||||
### 统计分析接口
|
||||
```dart
|
||||
abstract class ShareAnalyticsService {
|
||||
// 获取分享统计数据
|
||||
Future<ApiResponse<ShareStatistics>> getShareStatistics(StatisticsRequest request);
|
||||
|
||||
// 获取用户分享行为
|
||||
Future<ApiResponse<UserShareBehavior>> getUserShareBehavior(String userId);
|
||||
|
||||
// 获取热门分享内容
|
||||
Future<ApiResponse<List<PopularContent>>> getPopularContent(PopularContentRequest request);
|
||||
}
|
||||
```
|
||||
|
||||
## 配置管理
|
||||
|
||||
### 分享配置
|
||||
```dart
|
||||
class ShareConfig {
|
||||
final List<SharePlatformType> enabledPlatforms;
|
||||
final bool enableAnalytics;
|
||||
final bool enableContentGeneration;
|
||||
final int maxImageSize;
|
||||
final Duration shareTimeout;
|
||||
final Map<SharePlatformType, PlatformConfig> platformConfigs;
|
||||
|
||||
static const ShareConfig defaultConfig = ShareConfig(
|
||||
enabledPlatforms: [
|
||||
SharePlatformType.wechat,
|
||||
SharePlatformType.wechatMoments,
|
||||
SharePlatformType.qq,
|
||||
SharePlatformType.qzone,
|
||||
SharePlatformType.weibo,
|
||||
SharePlatformType.system,
|
||||
],
|
||||
enableAnalytics: true,
|
||||
enableContentGeneration: true,
|
||||
maxImageSize: 1024 * 1024 * 2, // 2MB
|
||||
shareTimeout: Duration(seconds: 30),
|
||||
platformConfigs: {},
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### 内容配置
|
||||
```dart
|
||||
class ContentConfig {
|
||||
final String appName;
|
||||
final String appDescription;
|
||||
final String defaultShareUrl;
|
||||
final String logoUrl;
|
||||
final Map<String, String> shareTemplates;
|
||||
final List<String> sensitiveWords;
|
||||
|
||||
static const ContentConfig defaultContentConfig = ContentConfig(
|
||||
appName: 'OneApp',
|
||||
appDescription: '智能车联网应用',
|
||||
defaultShareUrl: 'https://oneapp.com',
|
||||
logoUrl: 'https://oneapp.com/logo.png',
|
||||
shareTemplates: {
|
||||
'vehicle': '我在OneApp发现了一款不错的车辆:{vehicleName}',
|
||||
'charging': '在OneApp找到了便宜的充电站,分享给你:{stationName}',
|
||||
},
|
||||
sensitiveWords: ['敏感词1', '敏感词2'],
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## 使用示例
|
||||
|
||||
### 基本分享功能
|
||||
```dart
|
||||
// 分享文本内容
|
||||
final shareRequest = ShareRequest(
|
||||
id: 'share_text_${DateTime.now().millisecondsSinceEpoch}',
|
||||
content: ShareContent(
|
||||
text: '我在使用OneApp,感觉很不错!',
|
||||
url: 'https://oneapp.com',
|
||||
type: ContentType.text,
|
||||
),
|
||||
platform: SharePlatformType.wechat,
|
||||
options: ShareOptions(
|
||||
enableAnalytics: true,
|
||||
autoGenerateImage: false,
|
||||
),
|
||||
);
|
||||
|
||||
final result = await ShareManager.instance.share(shareRequest);
|
||||
|
||||
if (result.isSuccess) {
|
||||
print('分享成功');
|
||||
} else {
|
||||
print('分享失败: ${result.errorMessage}');
|
||||
}
|
||||
```
|
||||
|
||||
### 分享图片内容
|
||||
```dart
|
||||
// 分享车辆信息
|
||||
final vehicleInfo = {
|
||||
'name': 'Model Y',
|
||||
'brand': 'Tesla',
|
||||
'price': '30万',
|
||||
'image': 'https://example.com/vehicle.jpg',
|
||||
};
|
||||
|
||||
// 生成分享内容
|
||||
final shareContent = await ShareContentGenerator.instance.generateContent(
|
||||
ContentTemplate.vehicle,
|
||||
vehicleInfo,
|
||||
);
|
||||
|
||||
// 创建分享海报
|
||||
final posterPath = await ShareContentGenerator.instance.createShareImage(
|
||||
ShareImageConfig(
|
||||
template: 'vehicle_poster',
|
||||
data: vehicleInfo,
|
||||
size: Size(750, 1334),
|
||||
),
|
||||
);
|
||||
|
||||
// 执行分享
|
||||
final shareResult = await ShareManager.instance.share(
|
||||
ShareRequest(
|
||||
id: 'share_vehicle',
|
||||
content: ShareContent(
|
||||
title: vehicleInfo['name'],
|
||||
description: '${vehicleInfo['brand']} ${vehicleInfo['name']} - ${vehicleInfo['price']}',
|
||||
images: [posterPath],
|
||||
url: 'https://oneapp.com/vehicle/${vehicleInfo['id']}',
|
||||
type: ContentType.image,
|
||||
),
|
||||
platform: SharePlatformType.wechatMoments,
|
||||
),
|
||||
);
|
||||
```
|
||||
|
||||
### 多平台分享
|
||||
```dart
|
||||
// 获取可用的分享平台
|
||||
final availablePlatforms = await ShareManager.instance.getAvailablePlatforms();
|
||||
|
||||
// 显示分享面板
|
||||
showSharePanel(
|
||||
context: context,
|
||||
platforms: availablePlatforms,
|
||||
content: shareContent,
|
||||
onPlatformSelected: (platform) async {
|
||||
final result = await ShareManager.instance.share(
|
||||
ShareRequest(
|
||||
content: shareContent,
|
||||
platform: platform.type,
|
||||
),
|
||||
);
|
||||
|
||||
if (result.isSuccess) {
|
||||
showSuccessToast('分享成功');
|
||||
} else {
|
||||
showErrorToast('分享失败: ${result.errorMessage}');
|
||||
}
|
||||
},
|
||||
);
|
||||
```
|
||||
|
||||
### 分享统计分析
|
||||
```dart
|
||||
// 获取分享统计数据
|
||||
final statistics = await ShareAnalytics.instance.getShareStatistics(
|
||||
StatisticsQuery(
|
||||
timeRange: TimeRange.lastMonth,
|
||||
groupBy: GroupBy.platform,
|
||||
),
|
||||
);
|
||||
|
||||
print('总分享次数: ${statistics.totalShares}');
|
||||
print('平台分布:');
|
||||
statistics.platformDistribution.forEach((platform, count) {
|
||||
print(' ${platform.name}: $count次');
|
||||
});
|
||||
|
||||
// 获取热门分享内容
|
||||
final popularContent = await ShareAnalytics.instance.getPopularContent(
|
||||
TimeRange.lastWeek,
|
||||
);
|
||||
|
||||
print('热门分享内容:');
|
||||
for (final content in popularContent) {
|
||||
print(' ${content.title}: ${content.shareCount}次分享');
|
||||
}
|
||||
```
|
||||
|
||||
### 自定义分享内容
|
||||
```dart
|
||||
// 注册自定义内容模板
|
||||
ShareContentGenerator.instance.registerTemplate(
|
||||
'custom_vehicle',
|
||||
ContentTemplate(
|
||||
id: 'custom_vehicle',
|
||||
name: '自定义车辆分享',
|
||||
textTemplate: '我在OneApp发现了{brand} {model},{feature},推荐给你!',
|
||||
imageTemplate: 'custom_vehicle_poster.png',
|
||||
variables: ['brand', 'model', 'feature', 'price'],
|
||||
),
|
||||
);
|
||||
|
||||
// 使用自定义模板生成内容
|
||||
final customContent = await ShareContentGenerator.instance.generateContent(
|
||||
'custom_vehicle',
|
||||
{
|
||||
'brand': 'BMW',
|
||||
'model': 'iX3',
|
||||
'feature': '续航500公里',
|
||||
'price': '40万',
|
||||
},
|
||||
);
|
||||
```
|
||||
|
||||
## 测试策略
|
||||
|
||||
### 单元测试
|
||||
```dart
|
||||
group('ShareManager Tests', () {
|
||||
test('should share content successfully', () async {
|
||||
// Given
|
||||
final shareManager = ShareManager();
|
||||
final shareRequest = ShareRequest(
|
||||
content: ShareContent(text: 'Test share'),
|
||||
platform: SharePlatformType.system,
|
||||
);
|
||||
|
||||
// When
|
||||
final result = await shareManager.share(shareRequest);
|
||||
|
||||
// Then
|
||||
expect(result.isSuccess, true);
|
||||
expect(result.platform, SharePlatformType.system);
|
||||
});
|
||||
|
||||
test('should generate share content from template', () async {
|
||||
// Given
|
||||
final generator = ShareContentGenerator();
|
||||
final template = ContentTemplate.vehicle;
|
||||
final data = {'name': 'Model 3', 'brand': 'Tesla'};
|
||||
|
||||
// When
|
||||
final content = await generator.generateContent(template, data);
|
||||
|
||||
// Then
|
||||
expect(content.title, contains('Model 3'));
|
||||
expect(content.description, contains('Tesla'));
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### 集成测试
|
||||
```dart
|
||||
group('Share Integration Tests', () {
|
||||
testWidgets('share flow', (tester) async {
|
||||
// 1. 点击分享按钮
|
||||
await tester.tap(find.byKey(Key('share_button')));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// 2. 验证分享面板显示
|
||||
expect(find.byType(SharePanel), findsOneWidget);
|
||||
|
||||
// 3. 选择分享平台
|
||||
await tester.tap(find.byKey(Key('platform_wechat')));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// 4. 验证分享执行
|
||||
verify(mockShareManager.share(any)).called(1);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
## 性能优化
|
||||
|
||||
### 内容生成优化
|
||||
- **模板缓存**:缓存常用的内容模板
|
||||
- **图片压缩**:自动压缩分享图片
|
||||
- **异步处理**:异步生成分享内容
|
||||
- **批量处理**:批量处理多个分享请求
|
||||
|
||||
### 平台集成优化
|
||||
- **懒加载SDK**:按需加载平台SDK
|
||||
- **连接池**:复用网络连接
|
||||
- **缓存检查**:缓存平台可用性检查结果
|
||||
- **超时控制**:合理的超时时间设置
|
||||
|
||||
## 版本历史
|
||||
|
||||
### v0.2.5+3 (当前版本)
|
||||
- 新增抖音分享支持
|
||||
- 优化分享内容生成性能
|
||||
- 支持自定义分享模板
|
||||
- 修复微信分享回调问题
|
||||
|
||||
### v0.2.4
|
||||
- 支持视频内容分享
|
||||
- 新增分享统计分析
|
||||
- 优化分享面板UI
|
||||
- 改进错误处理机制
|
||||
|
||||
## 依赖关系
|
||||
|
||||
### 内部依赖
|
||||
- `basic_utils`: 工具类库
|
||||
- `basic_storage`: 本地存储
|
||||
- `basic_network`: 网络请求
|
||||
- `basic_logger`: 日志记录
|
||||
|
||||
### 外部依赖
|
||||
- `fluwx`: 微信分享SDK
|
||||
- `share_plus`: 系统分享
|
||||
- `image`: 图片处理
|
||||
- `path_provider`: 文件路径
|
||||
|
||||
## 总结
|
||||
|
||||
`ShareToFriends` 模块为 OneApp 提供了完整的社交分享解决方案。通过多平台支持、自定义内容生成、统计分析和权限控制等功能,该模块让用户能够便捷地分享应用内容到各大社交平台,同时为运营团队提供了有价值的分享数据分析,有助于提升用户参与度和应用传播效果。
|
||||
563
service_component/app_configuration.md
Normal file
563
service_component/app_configuration.md
Normal file
@@ -0,0 +1,563 @@
|
||||
# App Configuration - 应用配置管理模块
|
||||
|
||||
## 模块概述
|
||||
|
||||
`app_configuration` 是 OneApp 的车辆配置管理模块,专注于车辆配置选择和管理功能。该模块提供了完整的车辆配置解决方案,包括车型选择、外观配置、内饰配置、选装配置等功能。
|
||||
|
||||
## 核心功能
|
||||
|
||||
### 1. 车辆配置管理
|
||||
- **车型配置页面**:提供完整的车辆配置选择界面
|
||||
- **配置选项管理**:支持各种车辆配置选项
|
||||
- **3D模型展示**:集成3D车辆模型展示功能
|
||||
- **配置验证**:配置有效性验证机制
|
||||
|
||||
### 2. 模块导出组件
|
||||
|
||||
基于真实项目代码的主要导出:
|
||||
|
||||
```dart
|
||||
library app_configuration;
|
||||
|
||||
// 车辆配置页面
|
||||
export 'src/app_modules/car_configuration/pages/car_configuration_page.dart';
|
||||
|
||||
// 车辆配置状态管理
|
||||
export 'src/app_modules/car_configuration/blocs/car_configuration_bloc.dart';
|
||||
|
||||
// 配置相关组件
|
||||
export 'src/app_modules/car_configuration/widgets/car_rights_dialog_widget.dart';
|
||||
export 'src/app_modules/car_configuration/widgets/car_order_count_exception_dialog.dart';
|
||||
|
||||
// 路由导出
|
||||
export 'src/route_export.dart';
|
||||
|
||||
// 配置常量
|
||||
export 'src/app_modules/car_configuration/configuration_constant.dart';
|
||||
```
|
||||
|
||||
### 3. 车辆配置页面 (CarConfigurationPage)
|
||||
|
||||
核心配置页面实现:
|
||||
|
||||
```dart
|
||||
/// 车辆配置页面
|
||||
class CarConfigurationPage extends StatefulWidget with RouteObjProvider {
|
||||
CarConfigurationPage({
|
||||
Key? key,
|
||||
this.carModelCode,
|
||||
this.smallPreOrderNum,
|
||||
this.carOrderNum,
|
||||
this.needDepositAmount,
|
||||
this.pageFrom = PageFrom.pageNone,
|
||||
}) : super(key: key);
|
||||
|
||||
/// 已选车型配置代码
|
||||
final String? carModelCode;
|
||||
|
||||
/// 小订订单号,创建大定时可以关联小订
|
||||
final String? smallPreOrderNum;
|
||||
|
||||
/// 大定修改订单原始订单号
|
||||
final String? carOrderNum;
|
||||
|
||||
/// 大定修改,大定定金金额
|
||||
final double? needDepositAmount;
|
||||
|
||||
/// 页面来源类型
|
||||
PageFrom? pageFrom = PageFrom.pageNone;
|
||||
|
||||
@override
|
||||
State<CarConfigurationPage> createState() => _CarConfigurationPageState();
|
||||
}
|
||||
```
|
||||
|
||||
### 4. 模块架构组件
|
||||
|
||||
实际项目包含的配置组件:
|
||||
|
||||
- **car_3D_model_webview.dart**: 3D车辆模型WebView组件
|
||||
- **car_exterior_config.dart**: 车辆外观配置组件
|
||||
- **car_interior_config.dart**: 车辆内饰配置组件
|
||||
- **car_model_config_new.dart**: 新版车型配置组件
|
||||
- **car_option_config.dart**: 车辆选装配置组件
|
||||
- **config_bottom_bar_widget.dart**: 配置底部栏组件
|
||||
- **configuration_tab.dart**: 配置选项卡组件
|
||||
|
||||
## 技术架构
|
||||
|
||||
### 模块注册
|
||||
|
||||
```dart
|
||||
/// App配置模块
|
||||
class AppConfigurationModule extends Module with RouteObjProvider {
|
||||
@override
|
||||
List<Module> get imports => [];
|
||||
|
||||
@override
|
||||
List<Bind> get binds => [];
|
||||
|
||||
@override
|
||||
List<ModularRoute> get routes {
|
||||
final r1 = RouteCenterAPI.routeMetaBy(
|
||||
AppConfigurationRouteExport.keyAppConfiguration
|
||||
);
|
||||
|
||||
return [
|
||||
ChildRoute(
|
||||
r1.path,
|
||||
child: (_, args) => r1.provider(args).as(),
|
||||
guards: loginGuardList,
|
||||
),
|
||||
];
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 目录结构
|
||||
|
||||
基于实际项目结构:
|
||||
|
||||
```
|
||||
lib/
|
||||
├── app_configuration.dart # 主导出文件
|
||||
├── generated/ # 生成的国际化文件
|
||||
├── l10n/ # 国际化资源文件
|
||||
└── src/ # 源代码目录
|
||||
├── app_modules/ # 应用模块
|
||||
│ └── car_configuration/ # 车辆配置模块
|
||||
│ ├── blocs/ # BLoC状态管理
|
||||
│ ├── model/ # 数据模型
|
||||
│ ├── pages/ # 页面组件
|
||||
│ ├── widgets/ # 配置组件
|
||||
│ └── configuration_constant.dart # 配置常量
|
||||
├── app_defines/ # 应用定义
|
||||
└── route_export.dart # 路由导出
|
||||
```
|
||||
|
||||
### 核心组件
|
||||
|
||||
#### 1. 配置管理器 (ConfigurationManager)
|
||||
```dart
|
||||
class ConfigurationManager {
|
||||
// 初始化配置管理器
|
||||
Future<bool> initialize(ConfigurationConfig config);
|
||||
|
||||
// 获取配置值
|
||||
T? getValue<T>(String key, {T? defaultValue});
|
||||
|
||||
// 设置配置值
|
||||
Future<bool> setValue<T>(String key, T value);
|
||||
|
||||
// 删除配置
|
||||
Future<bool> removeValue(String key);
|
||||
|
||||
// 获取所有配置
|
||||
Map<String, dynamic> getAllConfigurations();
|
||||
}
|
||||
```
|
||||
|
||||
#### 2. 远程配置服务 (RemoteConfigService)
|
||||
```dart
|
||||
class RemoteConfigService {
|
||||
// 从服务端获取配置
|
||||
Future<ConfigurationResult> fetchRemoteConfig();
|
||||
|
||||
// 检查配置更新
|
||||
Future<bool> checkForUpdates();
|
||||
|
||||
// 应用远程配置
|
||||
Future<bool> applyRemoteConfig(Map<String, dynamic> config);
|
||||
|
||||
// 获取配置版本信息
|
||||
Future<ConfigVersion> getConfigVersion();
|
||||
}
|
||||
```
|
||||
|
||||
#### 3. 本地缓存管理器 (LocalCacheManager)
|
||||
```dart
|
||||
class LocalCacheManager {
|
||||
// 缓存配置到本地
|
||||
Future<bool> cacheConfiguration(String key, dynamic value);
|
||||
|
||||
// 从缓存获取配置
|
||||
T? getCachedConfiguration<T>(String key);
|
||||
|
||||
// 清除缓存
|
||||
Future<bool> clearCache([String? key]);
|
||||
|
||||
// 获取缓存大小
|
||||
Future<int> getCacheSize();
|
||||
|
||||
// 压缩缓存数据
|
||||
Future<bool> compressCache();
|
||||
}
|
||||
```
|
||||
|
||||
#### 4. 环境管理器 (EnvironmentManager)
|
||||
```dart
|
||||
class EnvironmentManager {
|
||||
// 设置当前环境
|
||||
Future<bool> setCurrentEnvironment(Environment environment);
|
||||
|
||||
// 获取当前环境
|
||||
Environment getCurrentEnvironment();
|
||||
|
||||
// 获取环境配置
|
||||
Map<String, dynamic> getEnvironmentConfig(Environment environment);
|
||||
|
||||
// 验证环境配置
|
||||
Future<bool> validateEnvironmentConfig(Environment environment);
|
||||
}
|
||||
```
|
||||
|
||||
## 数据模型
|
||||
|
||||
### 配置模型
|
||||
```dart
|
||||
class Configuration {
|
||||
final String key;
|
||||
final dynamic value;
|
||||
final ConfigurationType type;
|
||||
final DateTime createdAt;
|
||||
final DateTime updatedAt;
|
||||
final String version;
|
||||
final Map<String, dynamic> metadata;
|
||||
final bool isRemote;
|
||||
final bool isEncrypted;
|
||||
}
|
||||
|
||||
enum ConfigurationType {
|
||||
string,
|
||||
integer,
|
||||
double,
|
||||
boolean,
|
||||
json,
|
||||
list
|
||||
}
|
||||
```
|
||||
|
||||
### 环境模型
|
||||
```dart
|
||||
enum Environment {
|
||||
development,
|
||||
testing,
|
||||
staging,
|
||||
production
|
||||
}
|
||||
|
||||
class EnvironmentConfig {
|
||||
final Environment environment;
|
||||
final String baseUrl;
|
||||
final String apiKey;
|
||||
final Map<String, String> headers;
|
||||
final int timeout;
|
||||
final bool enableLogging;
|
||||
final Map<String, dynamic> features;
|
||||
}
|
||||
```
|
||||
|
||||
### 配置版本模型
|
||||
```dart
|
||||
class ConfigVersion {
|
||||
final String version;
|
||||
final DateTime publishTime;
|
||||
final String description;
|
||||
final List<String> changedKeys;
|
||||
final Map<String, dynamic> changeset;
|
||||
final bool isForced;
|
||||
final DateTime expireTime;
|
||||
}
|
||||
```
|
||||
|
||||
## API 接口
|
||||
|
||||
### 配置管理接口
|
||||
```dart
|
||||
abstract class ConfigurationService {
|
||||
// 初始化配置服务
|
||||
Future<ApiResponse<bool>> initialize(InitConfigRequest request);
|
||||
|
||||
// 获取配置
|
||||
Future<ApiResponse<ConfigurationResult>> getConfiguration(GetConfigRequest request);
|
||||
|
||||
// 批量获取配置
|
||||
Future<ApiResponse<Map<String, dynamic>>> getBatchConfiguration(BatchConfigRequest request);
|
||||
|
||||
// 更新配置
|
||||
Future<ApiResponse<bool>> updateConfiguration(UpdateConfigRequest request);
|
||||
}
|
||||
```
|
||||
|
||||
### 远程配置接口
|
||||
```dart
|
||||
abstract class RemoteConfigurationService {
|
||||
// 获取远程配置
|
||||
Future<ApiResponse<Map<String, dynamic>>> fetchRemoteConfiguration(FetchConfigRequest request);
|
||||
|
||||
// 检查配置更新
|
||||
Future<ApiResponse<UpdateCheckResult>> checkConfigurationUpdate(CheckUpdateRequest request);
|
||||
|
||||
// 上报配置使用情况
|
||||
Future<ApiResponse<bool>> reportConfigurationUsage(UsageReportRequest request);
|
||||
}
|
||||
```
|
||||
|
||||
## 配置管理
|
||||
|
||||
### 默认配置
|
||||
```dart
|
||||
class DefaultConfiguration {
|
||||
static const Map<String, dynamic> defaultConfig = {
|
||||
'app': {
|
||||
'name': 'OneApp',
|
||||
'version': '1.0.0',
|
||||
'debug': false,
|
||||
},
|
||||
'network': {
|
||||
'timeout': 30000,
|
||||
'retryCount': 3,
|
||||
'enableCache': true,
|
||||
},
|
||||
'ui': {
|
||||
'theme': 'auto',
|
||||
'language': 'auto',
|
||||
'animations': true,
|
||||
},
|
||||
'features': {
|
||||
'enableAnalytics': true,
|
||||
'enablePush': true,
|
||||
'enableLocation': false,
|
||||
},
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### 环境配置
|
||||
```dart
|
||||
class EnvironmentConfiguration {
|
||||
static const Map<Environment, EnvironmentConfig> environments = {
|
||||
Environment.development: EnvironmentConfig(
|
||||
environment: Environment.development,
|
||||
baseUrl: 'https://dev-api.oneapp.com',
|
||||
apiKey: 'dev_api_key',
|
||||
enableLogging: true,
|
||||
),
|
||||
Environment.production: EnvironmentConfig(
|
||||
environment: Environment.production,
|
||||
baseUrl: 'https://api.oneapp.com',
|
||||
apiKey: 'prod_api_key',
|
||||
enableLogging: false,
|
||||
),
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## 使用示例
|
||||
|
||||
### 基本配置管理
|
||||
```dart
|
||||
// 初始化配置管理器
|
||||
final configManager = ConfigurationManager.instance;
|
||||
await configManager.initialize(ConfigurationConfig.defaultConfig);
|
||||
|
||||
// 获取配置值
|
||||
final appName = configManager.getValue<String>('app.name', defaultValue: 'OneApp');
|
||||
final timeout = configManager.getValue<int>('network.timeout', defaultValue: 30000);
|
||||
final enableAnalytics = configManager.getValue<bool>('features.enableAnalytics', defaultValue: true);
|
||||
|
||||
// 设置配置值
|
||||
await configManager.setValue('ui.theme', 'dark');
|
||||
await configManager.setValue('features.enablePush', false);
|
||||
|
||||
// 监听配置变化
|
||||
configManager.onConfigurationChanged.listen((change) {
|
||||
print('配置变更: ${change.key} = ${change.newValue}');
|
||||
});
|
||||
```
|
||||
|
||||
### 远程配置更新
|
||||
```dart
|
||||
// 检查远程配置更新
|
||||
final remoteConfigService = RemoteConfigService.instance;
|
||||
final hasUpdate = await remoteConfigService.checkForUpdates();
|
||||
|
||||
if (hasUpdate) {
|
||||
// 获取远程配置
|
||||
final remoteConfig = await remoteConfigService.fetchRemoteConfig();
|
||||
|
||||
if (remoteConfig.isSuccess) {
|
||||
// 应用远程配置
|
||||
await remoteConfigService.applyRemoteConfig(remoteConfig.data);
|
||||
print('远程配置已更新');
|
||||
}
|
||||
}
|
||||
|
||||
// 监听远程配置更新
|
||||
remoteConfigService.onRemoteConfigUpdated.listen((config) {
|
||||
print('收到远程配置更新');
|
||||
// 处理配置更新逻辑
|
||||
});
|
||||
```
|
||||
|
||||
### 环境配置切换
|
||||
```dart
|
||||
// 获取当前环境
|
||||
final currentEnv = EnvironmentManager.instance.getCurrentEnvironment();
|
||||
print('当前环境: $currentEnv');
|
||||
|
||||
// 切换到测试环境
|
||||
await EnvironmentManager.instance.setCurrentEnvironment(Environment.testing);
|
||||
|
||||
// 获取环境配置
|
||||
final envConfig = EnvironmentManager.instance.getEnvironmentConfig(Environment.testing);
|
||||
print('测试环境配置: $envConfig');
|
||||
|
||||
// 验证环境配置
|
||||
final isValid = await EnvironmentManager.instance.validateEnvironmentConfig(Environment.testing);
|
||||
if (!isValid) {
|
||||
print('环境配置验证失败');
|
||||
}
|
||||
```
|
||||
|
||||
### 配置缓存管理
|
||||
```dart
|
||||
// 缓存配置
|
||||
final cacheManager = LocalCacheManager.instance;
|
||||
await cacheManager.cacheConfiguration('user_preferences', userPreferences);
|
||||
|
||||
// 获取缓存配置
|
||||
final cachedPreferences = cacheManager.getCachedConfiguration<Map<String, dynamic>>('user_preferences');
|
||||
|
||||
// 获取缓存大小
|
||||
final cacheSize = await cacheManager.getCacheSize();
|
||||
print('缓存大小: ${cacheSize}KB');
|
||||
|
||||
// 清理缓存
|
||||
if (cacheSize > 1024 * 1024) { // 超过1MB
|
||||
await cacheManager.compressCache();
|
||||
}
|
||||
```
|
||||
|
||||
## 测试策略
|
||||
|
||||
### 单元测试
|
||||
```dart
|
||||
group('ConfigurationManager Tests', () {
|
||||
test('should get and set configuration values', () async {
|
||||
// Given
|
||||
final configManager = ConfigurationManager();
|
||||
await configManager.initialize(ConfigurationConfig.defaultConfig);
|
||||
|
||||
// When
|
||||
await configManager.setValue('test.key', 'test_value');
|
||||
final value = configManager.getValue<String>('test.key');
|
||||
|
||||
// Then
|
||||
expect(value, 'test_value');
|
||||
});
|
||||
|
||||
test('should return default value when key not found', () {
|
||||
// Given
|
||||
final configManager = ConfigurationManager();
|
||||
|
||||
// When
|
||||
final value = configManager.getValue<String>('nonexistent.key', defaultValue: 'default');
|
||||
|
||||
// Then
|
||||
expect(value, 'default');
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### 集成测试
|
||||
```dart
|
||||
group('Configuration Integration Tests', () {
|
||||
testWidgets('configuration update flow', (tester) async {
|
||||
// 1. 初始化配置
|
||||
await ConfigurationManager.instance.initialize(ConfigurationConfig.defaultConfig);
|
||||
|
||||
// 2. 模拟远程配置更新
|
||||
final mockRemoteConfig = {'feature.newFeature': true};
|
||||
await RemoteConfigService.instance.applyRemoteConfig(mockRemoteConfig);
|
||||
|
||||
// 3. 验证配置已更新
|
||||
final newFeatureEnabled = ConfigurationManager.instance.getValue<bool>('feature.newFeature');
|
||||
expect(newFeatureEnabled, true);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
## 性能优化
|
||||
|
||||
### 缓存策略
|
||||
- **内存缓存**:热点配置内存缓存
|
||||
- **磁盘缓存**:所有配置磁盘持久化
|
||||
- **缓存过期**:配置缓存过期机制
|
||||
- **预加载**:应用启动时预加载关键配置
|
||||
|
||||
### 网络优化
|
||||
- **增量同步**:只同步变化的配置项
|
||||
- **压缩传输**:配置数据压缩传输
|
||||
- **批量操作**:批量获取和更新配置
|
||||
- **连接池**:网络连接池优化
|
||||
|
||||
## 安全考虑
|
||||
|
||||
### 数据安全
|
||||
- **配置加密**:敏感配置加密存储
|
||||
- **传输加密**:配置传输使用HTTPS
|
||||
- **签名验证**:配置数据签名验证
|
||||
- **访问控制**:配置访问权限控制
|
||||
|
||||
### 隐私保护
|
||||
- **数据最小化**:只收集必要的配置数据
|
||||
- **匿名化**:用户相关配置匿名化
|
||||
- **数据清理**:定期清理过期配置
|
||||
- **透明度**:配置使用透明化
|
||||
|
||||
## 监控和诊断
|
||||
|
||||
### 性能监控
|
||||
- **配置使用统计**:统计配置项使用频率
|
||||
- **更新性能**:监控配置更新性能
|
||||
- **缓存命中率**:监控缓存命中率
|
||||
- **网络性能**:监控配置网络请求性能
|
||||
|
||||
### 故障诊断
|
||||
- **配置验证**:配置数据有效性验证
|
||||
- **更新失败恢复**:配置更新失败自动恢复
|
||||
- **异常监控**:配置相关异常监控
|
||||
- **健康检查**:配置服务健康检查
|
||||
|
||||
## 版本历史
|
||||
|
||||
### v0.2.6+8 (当前版本)
|
||||
- 新增配置热更新功能
|
||||
- 优化缓存性能
|
||||
- 支持配置分组管理
|
||||
- 修复环境切换问题
|
||||
|
||||
### v0.2.5
|
||||
- 支持远程配置灰度发布
|
||||
- 新增配置使用统计
|
||||
- 优化配置同步机制
|
||||
- 改进错误处理
|
||||
|
||||
## 依赖关系
|
||||
|
||||
### 内部依赖
|
||||
- `clr_configuration`: 配置服务SDK
|
||||
- `basic_storage`: 本地存储服务
|
||||
- `basic_network`: 网络请求服务
|
||||
- `basic_error`: 错误处理框架
|
||||
|
||||
### 外部依赖
|
||||
- `shared_preferences`: 本地配置存储
|
||||
- `dio`: HTTP客户端
|
||||
- `encrypt`: 数据加密
|
||||
- `rxdart`: 响应式编程
|
||||
|
||||
## 总结
|
||||
|
||||
`app_configuration` 作为应用配置管理的核心模块,提供了完整的配置管理解决方案。通过远程配置、本地缓存、热更新和环境切换等功能,为 OneApp 提供了灵活、可靠、高效的配置管理能力,确保应用能够快速响应业务需求变化,同时保证用户体验的一致性和稳定性。
|
||||
570
service_component/clr_configuration.md
Normal file
570
service_component/clr_configuration.md
Normal file
@@ -0,0 +1,570 @@
|
||||
# CLR Configuration - 配置服务SDK
|
||||
|
||||
## 模块概述
|
||||
|
||||
`clr_configuration` 是 OneApp 配置服务的核心 SDK,为应用配置管理提供底层的 API 封装和数据处理能力。该 SDK 封装了配置服务的网络接口、数据模型、同步机制和变更通知等功能,为上层的配置管理模块提供稳定可靠的服务支撑。
|
||||
|
||||
## 核心功能
|
||||
|
||||
### 1. 配置 API 封装
|
||||
- **RESTful API**:配置服务 REST API 封装
|
||||
- **GraphQL API**:配置查询 GraphQL 接口
|
||||
- **WebSocket API**:实时配置更新接口
|
||||
- **批量操作**:配置批量读写操作
|
||||
|
||||
### 2. 配置数据模型
|
||||
- **数据结构**:标准化的配置数据结构
|
||||
- **类型系统**:强类型配置值系统
|
||||
- **序列化**:配置数据序列化和反序列化
|
||||
- **验证机制**:配置数据有效性验证
|
||||
|
||||
### 3. 配置同步机制
|
||||
- **增量同步**:配置变更增量同步
|
||||
- **冲突解决**:配置冲突解决策略
|
||||
- **版本控制**:配置版本管理机制
|
||||
- **事务支持**:配置操作事务保证
|
||||
|
||||
### 4. 配置变更通知
|
||||
- **事件驱动**:基于事件的变更通知
|
||||
- **订阅机制**:配置变更订阅管理
|
||||
- **推送通知**:实时推送配置变更
|
||||
- **回调处理**:配置变更回调处理
|
||||
|
||||
## 技术架构
|
||||
|
||||
### 架构设计
|
||||
```
|
||||
┌─────────────────────────────────────┐
|
||||
│ 配置管理应用层 │
|
||||
│ (app_configuration) │
|
||||
├─────────────────────────────────────┤
|
||||
│ CLR Configuration │
|
||||
│ ┌──────────┬──────────┬──────────┐ │
|
||||
│ │ API封装 │ 数据模型 │ 同步引擎 │ │
|
||||
│ ├──────────┼──────────┼──────────┤ │
|
||||
│ │ 事件系统 │ 缓存层 │ 安全模块 │ │
|
||||
│ └──────────┴──────────┴──────────┘ │
|
||||
├─────────────────────────────────────┤
|
||||
│ 网络通信层 │
|
||||
│ (HTTP/WebSocket/GraphQL) │
|
||||
├─────────────────────────────────────┤
|
||||
│ 配置服务后端 │
|
||||
│ (Configuration Server) │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 核心组件
|
||||
|
||||
#### 1. API 客户端 (ApiClient)
|
||||
```dart
|
||||
class ConfigurationApiClient {
|
||||
// 获取配置
|
||||
Future<ApiResponse<ConfigData>> getConfiguration(GetConfigRequest request);
|
||||
|
||||
// 设置配置
|
||||
Future<ApiResponse<bool>> setConfiguration(SetConfigRequest request);
|
||||
|
||||
// 批量获取配置
|
||||
Future<ApiResponse<Map<String, ConfigData>>> getBatchConfiguration(BatchGetRequest request);
|
||||
|
||||
// 订阅配置变更
|
||||
Stream<ConfigurationChange> subscribeConfigurationChanges(String key);
|
||||
}
|
||||
```
|
||||
|
||||
#### 2. 数据模型管理器 (DataModelManager)
|
||||
```dart
|
||||
class ConfigurationDataModel {
|
||||
// 序列化配置数据
|
||||
Map<String, dynamic> serialize(ConfigData data);
|
||||
|
||||
// 反序列化配置数据
|
||||
ConfigData deserialize(Map<String, dynamic> json);
|
||||
|
||||
// 验证配置数据
|
||||
ValidationResult validate(ConfigData data);
|
||||
|
||||
// 转换配置数据类型
|
||||
T convertValue<T>(dynamic value, ConfigType targetType);
|
||||
}
|
||||
```
|
||||
|
||||
#### 3. 同步引擎 (SyncEngine)
|
||||
```dart
|
||||
class ConfigurationSyncEngine {
|
||||
// 开始同步
|
||||
Future<SyncResult> startSync(SyncOptions options);
|
||||
|
||||
// 增量同步
|
||||
Future<SyncResult> incrementalSync(String lastSyncVersion);
|
||||
|
||||
// 解决冲突
|
||||
Future<ConflictResolution> resolveConflict(ConfigurationConflict conflict);
|
||||
|
||||
// 回滚配置
|
||||
Future<bool> rollbackConfiguration(String version);
|
||||
}
|
||||
```
|
||||
|
||||
#### 4. 事件系统 (EventSystem)
|
||||
```dart
|
||||
class ConfigurationEventSystem {
|
||||
// 发布事件
|
||||
void publishEvent(ConfigurationEvent event);
|
||||
|
||||
// 订阅事件
|
||||
StreamSubscription<T> subscribe<T extends ConfigurationEvent>(EventHandler<T> handler);
|
||||
|
||||
// 取消订阅
|
||||
void unsubscribe(StreamSubscription subscription);
|
||||
|
||||
// 清理事件
|
||||
void clearEvents([String? eventType]);
|
||||
}
|
||||
```
|
||||
|
||||
## 数据模型
|
||||
|
||||
### 配置数据模型
|
||||
```dart
|
||||
class ConfigData {
|
||||
final String key;
|
||||
final dynamic value;
|
||||
final ConfigType type;
|
||||
final String version;
|
||||
final DateTime timestamp;
|
||||
final Map<String, String> metadata;
|
||||
final List<String> tags;
|
||||
final ConfigScope scope;
|
||||
final bool isEncrypted;
|
||||
final String? description;
|
||||
}
|
||||
|
||||
enum ConfigType {
|
||||
string,
|
||||
integer,
|
||||
double,
|
||||
boolean,
|
||||
json,
|
||||
array,
|
||||
binary
|
||||
}
|
||||
|
||||
enum ConfigScope {
|
||||
global,
|
||||
user,
|
||||
device,
|
||||
session
|
||||
}
|
||||
```
|
||||
|
||||
### 配置变更模型
|
||||
```dart
|
||||
class ConfigurationChange {
|
||||
final String key;
|
||||
final dynamic oldValue;
|
||||
final dynamic newValue;
|
||||
final ChangeType changeType;
|
||||
final String version;
|
||||
final DateTime timestamp;
|
||||
final String? userId;
|
||||
final String? source;
|
||||
final Map<String, dynamic> context;
|
||||
}
|
||||
|
||||
enum ChangeType {
|
||||
created,
|
||||
updated,
|
||||
deleted,
|
||||
restored
|
||||
}
|
||||
```
|
||||
|
||||
### API 请求模型
|
||||
```dart
|
||||
class GetConfigRequest {
|
||||
final String key;
|
||||
final ConfigScope? scope;
|
||||
final String? version;
|
||||
final bool includeMetadata;
|
||||
final List<String>? tags;
|
||||
}
|
||||
|
||||
class SetConfigRequest {
|
||||
final String key;
|
||||
final dynamic value;
|
||||
final ConfigType type;
|
||||
final ConfigScope scope;
|
||||
final Map<String, String>? metadata;
|
||||
final List<String>? tags;
|
||||
final bool encrypt;
|
||||
}
|
||||
```
|
||||
|
||||
## API 接口
|
||||
|
||||
### 配置操作接口
|
||||
```dart
|
||||
abstract class ConfigurationApi {
|
||||
// 获取单个配置
|
||||
Future<ApiResponse<ConfigData>> getConfig(String key, {ConfigScope? scope});
|
||||
|
||||
// 设置单个配置
|
||||
Future<ApiResponse<bool>> setConfig(String key, dynamic value, {ConfigType? type, ConfigScope? scope});
|
||||
|
||||
// 删除配置
|
||||
Future<ApiResponse<bool>> deleteConfig(String key, {ConfigScope? scope});
|
||||
|
||||
// 检查配置是否存在
|
||||
Future<ApiResponse<bool>> hasConfig(String key, {ConfigScope? scope});
|
||||
}
|
||||
```
|
||||
|
||||
### 批量操作接口
|
||||
```dart
|
||||
abstract class BatchConfigurationApi {
|
||||
// 批量获取配置
|
||||
Future<ApiResponse<Map<String, ConfigData>>> getBatchConfigs(List<String> keys);
|
||||
|
||||
// 批量设置配置
|
||||
Future<ApiResponse<BatchResult>> setBatchConfigs(Map<String, dynamic> configs);
|
||||
|
||||
// 批量删除配置
|
||||
Future<ApiResponse<BatchResult>> deleteBatchConfigs(List<String> keys);
|
||||
}
|
||||
```
|
||||
|
||||
### 同步接口
|
||||
```dart
|
||||
abstract class ConfigurationSyncApi {
|
||||
// 获取配置版本
|
||||
Future<ApiResponse<ConfigVersion>> getConfigVersion();
|
||||
|
||||
// 同步配置
|
||||
Future<ApiResponse<SyncResult>> syncConfigurations(SyncRequest request);
|
||||
|
||||
// 获取配置变更历史
|
||||
Future<ApiResponse<List<ConfigurationChange>>> getChangeHistory(ChangeHistoryRequest request);
|
||||
}
|
||||
```
|
||||
|
||||
## 配置管理
|
||||
|
||||
### SDK 配置
|
||||
```dart
|
||||
class ConfigurationSdkConfig {
|
||||
final String serverUrl;
|
||||
final String apiKey;
|
||||
final String clientId;
|
||||
final Duration timeout;
|
||||
final int maxRetries;
|
||||
final bool enableCache;
|
||||
final bool enableEncryption;
|
||||
final LogLevel logLevel;
|
||||
|
||||
static const ConfigurationSdkConfig defaultConfig = ConfigurationSdkConfig(
|
||||
serverUrl: 'https://config-api.oneapp.com',
|
||||
timeout: Duration(seconds: 30),
|
||||
maxRetries: 3,
|
||||
enableCache: true,
|
||||
enableEncryption: true,
|
||||
logLevel: LogLevel.info,
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### 缓存配置
|
||||
```dart
|
||||
class CacheConfig {
|
||||
final Duration ttl;
|
||||
final int maxSize;
|
||||
final bool enableCompression;
|
||||
final CacheEvictionPolicy evictionPolicy;
|
||||
|
||||
static const CacheConfig defaultCacheConfig = CacheConfig(
|
||||
ttl: Duration(minutes: 30),
|
||||
maxSize: 1000,
|
||||
enableCompression: true,
|
||||
evictionPolicy: CacheEvictionPolicy.lru,
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## 使用示例
|
||||
|
||||
### 基本配置操作
|
||||
```dart
|
||||
// 初始化 SDK
|
||||
final configSdk = ConfigurationSdk.instance;
|
||||
await configSdk.initialize(ConfigurationSdkConfig.defaultConfig);
|
||||
|
||||
// 获取配置
|
||||
try {
|
||||
final config = await configSdk.getConfig('app.theme');
|
||||
print('当前主题: ${config.value}');
|
||||
} catch (e) {
|
||||
print('获取配置失败: $e');
|
||||
}
|
||||
|
||||
// 设置配置
|
||||
await configSdk.setConfig(
|
||||
'user.language',
|
||||
'zh-CN',
|
||||
type: ConfigType.string,
|
||||
scope: ConfigScope.user,
|
||||
);
|
||||
|
||||
// 删除配置
|
||||
await configSdk.deleteConfig('temp.data');
|
||||
```
|
||||
|
||||
### 批量配置操作
|
||||
```dart
|
||||
// 批量获取配置
|
||||
final keys = ['app.theme', 'app.language', 'app.version'];
|
||||
final batchResult = await configSdk.getBatchConfigs(keys);
|
||||
|
||||
for (final entry in batchResult.entries) {
|
||||
print('${entry.key}: ${entry.value.value}');
|
||||
}
|
||||
|
||||
// 批量设置配置
|
||||
final batchConfigs = {
|
||||
'ui.showTips': true,
|
||||
'ui.animationSpeed': 1.0,
|
||||
'ui.darkMode': false,
|
||||
};
|
||||
|
||||
await configSdk.setBatchConfigs(batchConfigs);
|
||||
```
|
||||
|
||||
### 配置变更监听
|
||||
```dart
|
||||
// 监听特定配置变更
|
||||
configSdk.subscribeConfigurationChanges('app.theme').listen((change) {
|
||||
print('主题配置变更: ${change.oldValue} -> ${change.newValue}');
|
||||
// 应用新的主题配置
|
||||
applyThemeConfig(change.newValue);
|
||||
});
|
||||
|
||||
// 监听所有配置变更
|
||||
configSdk.onConfigurationChanged.listen((change) {
|
||||
print('配置变更: ${change.key}');
|
||||
logConfigurationChange(change);
|
||||
});
|
||||
```
|
||||
|
||||
### 配置同步
|
||||
```dart
|
||||
// 检查是否有配置更新
|
||||
final currentVersion = await configSdk.getConfigVersion();
|
||||
final hasUpdate = await configSdk.checkForUpdates(currentVersion.version);
|
||||
|
||||
if (hasUpdate) {
|
||||
// 执行增量同步
|
||||
final syncResult = await configSdk.incrementalSync(currentVersion.version);
|
||||
|
||||
if (syncResult.isSuccess) {
|
||||
print('配置同步成功,更新了 ${syncResult.updatedCount} 个配置');
|
||||
} else {
|
||||
print('配置同步失败: ${syncResult.error}');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 测试策略
|
||||
|
||||
### 单元测试
|
||||
```dart
|
||||
group('ConfigurationSdk Tests', () {
|
||||
test('should get configuration successfully', () async {
|
||||
// Given
|
||||
final sdk = ConfigurationSdk();
|
||||
await sdk.initialize(ConfigurationSdkConfig.defaultConfig);
|
||||
|
||||
// When
|
||||
final result = await sdk.getConfig('test.key');
|
||||
|
||||
// Then
|
||||
expect(result.key, 'test.key');
|
||||
expect(result.value, isNotNull);
|
||||
});
|
||||
|
||||
test('should handle configuration not found', () async {
|
||||
// Given
|
||||
final sdk = ConfigurationSdk();
|
||||
|
||||
// When & Then
|
||||
expect(
|
||||
() => sdk.getConfig('nonexistent.key'),
|
||||
throwsA(isA<ConfigurationNotFoundException>()),
|
||||
);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### 集成测试
|
||||
```dart
|
||||
group('Configuration Integration Tests', () {
|
||||
testWidgets('configuration sync flow', (tester) async {
|
||||
// 1. 初始化 SDK
|
||||
await ConfigurationSdk.instance.initialize(testConfig);
|
||||
|
||||
// 2. 设置配置
|
||||
await ConfigurationSdk.instance.setConfig('test.sync', 'value1');
|
||||
|
||||
// 3. 模拟远程配置变更
|
||||
await simulateRemoteConfigChange('test.sync', 'value2');
|
||||
|
||||
// 4. 执行同步
|
||||
final syncResult = await ConfigurationSdk.instance.sync();
|
||||
|
||||
// 5. 验证同步结果
|
||||
expect(syncResult.isSuccess, true);
|
||||
|
||||
final updatedConfig = await ConfigurationSdk.instance.getConfig('test.sync');
|
||||
expect(updatedConfig.value, 'value2');
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
## 性能优化
|
||||
|
||||
### 缓存策略
|
||||
- **多级缓存**:内存 + 磁盘多级缓存
|
||||
- **智能预加载**:预测性配置预加载
|
||||
- **缓存压缩**:配置数据压缩存储
|
||||
- **缓存更新**:增量缓存更新机制
|
||||
|
||||
### 网络优化
|
||||
- **连接复用**:HTTP 连接池复用
|
||||
- **请求合并**:相关配置请求合并
|
||||
- **数据压缩**:传输数据 gzip 压缩
|
||||
- **离线模式**:离线配置访问支持
|
||||
|
||||
## 错误处理
|
||||
|
||||
### 错误类型
|
||||
```dart
|
||||
abstract class ConfigurationException implements Exception {
|
||||
final String message;
|
||||
final String? errorCode;
|
||||
final Map<String, dynamic>? details;
|
||||
|
||||
const ConfigurationException(this.message, [this.errorCode, this.details]);
|
||||
}
|
||||
|
||||
class ConfigurationNotFoundException extends ConfigurationException {
|
||||
const ConfigurationNotFoundException(String key)
|
||||
: super('Configuration not found: $key', 'CONFIG_NOT_FOUND');
|
||||
}
|
||||
|
||||
class ConfigurationValidationException extends ConfigurationException {
|
||||
const ConfigurationValidationException(String message, Map<String, dynamic> details)
|
||||
: super(message, 'VALIDATION_ERROR', details);
|
||||
}
|
||||
|
||||
class ConfigurationSyncException extends ConfigurationException {
|
||||
const ConfigurationSyncException(String message)
|
||||
: super(message, 'SYNC_ERROR');
|
||||
}
|
||||
```
|
||||
|
||||
### 重试机制
|
||||
```dart
|
||||
class RetryConfig {
|
||||
final int maxRetries;
|
||||
final Duration initialDelay;
|
||||
final double backoffMultiplier;
|
||||
final Duration maxDelay;
|
||||
|
||||
static const RetryConfig defaultRetryConfig = RetryConfig(
|
||||
maxRetries: 3,
|
||||
initialDelay: Duration(seconds: 1),
|
||||
backoffMultiplier: 2.0,
|
||||
maxDelay: Duration(seconds: 30),
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## 安全机制
|
||||
|
||||
### 数据加密
|
||||
```dart
|
||||
class ConfigurationEncryption {
|
||||
// 加密配置值
|
||||
String encryptValue(String value, String key);
|
||||
|
||||
// 解密配置值
|
||||
String decryptValue(String encryptedValue, String key);
|
||||
|
||||
// 生成加密密钥
|
||||
String generateEncryptionKey();
|
||||
|
||||
// 验证数据完整性
|
||||
bool verifyIntegrity(String data, String signature);
|
||||
}
|
||||
```
|
||||
|
||||
### 访问控制
|
||||
```dart
|
||||
class ConfigurationAccessControl {
|
||||
// 检查读权限
|
||||
bool hasReadPermission(String key, String userId);
|
||||
|
||||
// 检查写权限
|
||||
bool hasWritePermission(String key, String userId);
|
||||
|
||||
// 检查删除权限
|
||||
bool hasDeletePermission(String key, String userId);
|
||||
|
||||
// 获取用户权限
|
||||
List<Permission> getUserPermissions(String userId);
|
||||
}
|
||||
```
|
||||
|
||||
## 监控和诊断
|
||||
|
||||
### 性能监控
|
||||
- **API 响应时间**:配置 API 响应时间监控
|
||||
- **缓存命中率**:配置缓存命中率统计
|
||||
- **错误率**:配置操作错误率监控
|
||||
- **同步性能**:配置同步性能指标
|
||||
|
||||
### 使用统计
|
||||
- **配置访问频率**:统计配置项访问频率
|
||||
- **热点配置**:识别热点配置项
|
||||
- **用户行为**:分析用户配置使用模式
|
||||
- **性能瓶颈**:识别性能瓶颈点
|
||||
|
||||
## 版本历史
|
||||
|
||||
### v0.2.8+5 (当前版本)
|
||||
- 新增 GraphQL 查询支持
|
||||
- 优化配置同步性能
|
||||
- 支持配置数据压缩
|
||||
- 修复并发访问问题
|
||||
|
||||
### v0.2.7
|
||||
- 支持配置数据加密
|
||||
- 新增批量操作接口
|
||||
- 优化缓存机制
|
||||
- 改进错误处理
|
||||
|
||||
## 依赖关系
|
||||
|
||||
### 内部依赖
|
||||
- `basic_network`: 网络请求基础库
|
||||
- `basic_storage`: 本地存储服务
|
||||
- `basic_error`: 错误处理框架
|
||||
- `basic_logger`: 日志记录服务
|
||||
|
||||
### 外部依赖
|
||||
- `dio`: HTTP 客户端
|
||||
- `json_annotation`: JSON 序列化
|
||||
- `encrypt`: 数据加密库
|
||||
- `rxdart`: 响应式编程支持
|
||||
|
||||
## 总结
|
||||
|
||||
`clr_configuration` 作为配置服务的核心 SDK,为 OneApp 的配置管理提供了强大的底层支撑。通过标准化的 API 接口、完善的数据模型、可靠的同步机制和实时的变更通知,该 SDK 确保了配置服务的高性能、高可用和高安全性,为上层应用提供了稳定可靠的配置管理能力。
|
||||
544
service_component/oneapp_companion.md
Normal file
544
service_component/oneapp_companion.md
Normal file
@@ -0,0 +1,544 @@
|
||||
# OneApp Companion - 伴侣应用模块
|
||||
|
||||
## 模块概述
|
||||
|
||||
`oneapp_companion` 是 OneApp 的伴侣应用模块,提供多设备协同功能。该模块支持手机、平板、智能手表、车载设备等多种设备间的数据同步、远程控制和设备管理,为用户提供无缝的跨设备体验。
|
||||
|
||||
## 核心功能
|
||||
|
||||
### 1. 多设备协同
|
||||
- **设备发现**:自动发现附近的伴侣设备
|
||||
- **设备配对**:安全的设备配对和认证
|
||||
- **状态同步**:设备状态实时同步
|
||||
- **会话共享**:跨设备会话状态共享
|
||||
|
||||
### 2. 数据同步
|
||||
- **实时同步**:关键数据实时同步
|
||||
- **增量同步**:高效的增量数据同步
|
||||
- **冲突解决**:数据冲突智能解决
|
||||
- **离线同步**:离线状态下的数据缓存和同步
|
||||
|
||||
### 3. 远程控制
|
||||
- **车辆控制**:远程控制车辆功能
|
||||
- **应用控制**:远程控制应用操作
|
||||
- **媒体控制**:跨设备媒体播放控制
|
||||
- **权限管理**:远程操作权限控制
|
||||
|
||||
### 4. 设备管理
|
||||
- **设备注册**:新设备注册和绑定
|
||||
- **设备监控**:设备状态监控和管理
|
||||
- **设备配置**:设备配置同步和管理
|
||||
- **设备安全**:设备安全策略和控制
|
||||
|
||||
## 技术架构
|
||||
|
||||
### 架构设计
|
||||
```
|
||||
┌─────────────────────────────────────┐
|
||||
│ 主应用设备 │
|
||||
│ (Primary Device) │
|
||||
├─────────────────────────────────────┤
|
||||
│ OneApp Companion │
|
||||
│ ┌──────────┬──────────┬──────────┐ │
|
||||
│ │ 设备管理 │ 数据同步 │ 远程控制 │ │
|
||||
│ ├──────────┼──────────┼──────────┤ │
|
||||
│ │ 通信协议 │ 安全模块 │ 状态管理 │ │
|
||||
│ └──────────┴──────────┴──────────┘ │
|
||||
├─────────────────────────────────────┤
|
||||
│ 通信协议层 │
|
||||
│ ┌──────────┬──────────┬──────────┐ │
|
||||
│ │ Bluetooth│ WiFi │ Cellular │ │
|
||||
│ └──────────┴──────────┴──────────┘ │
|
||||
├─────────────────────────────────────┤
|
||||
│ 伴侣设备群 │
|
||||
│ ┌──────────┬──────────┬──────────┐ │
|
||||
│ │ 手机/平板│ 智能手表 │ 车载设备 │ │
|
||||
│ └──────────┴──────────┴──────────┘ │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 核心组件
|
||||
|
||||
#### 1. 设备管理器 (DeviceManager)
|
||||
```dart
|
||||
class CompanionDeviceManager {
|
||||
// 发现设备
|
||||
Future<List<CompanionDevice>> discoverDevices();
|
||||
|
||||
// 配对设备
|
||||
Future<bool> pairDevice(String deviceId);
|
||||
|
||||
// 获取已配对设备
|
||||
Future<List<CompanionDevice>> getPairedDevices();
|
||||
|
||||
// 断开设备连接
|
||||
Future<bool> disconnectDevice(String deviceId);
|
||||
}
|
||||
```
|
||||
|
||||
#### 2. 数据同步器 (DataSynchronizer)
|
||||
```dart
|
||||
class CompanionDataSynchronizer {
|
||||
// 同步数据到设备
|
||||
Future<SyncResult> syncToDevice(String deviceId, SyncData data);
|
||||
|
||||
// 从设备同步数据
|
||||
Future<SyncResult> syncFromDevice(String deviceId);
|
||||
|
||||
// 批量同步
|
||||
Future<List<SyncResult>> batchSync(List<SyncRequest> requests);
|
||||
|
||||
// 解决同步冲突
|
||||
Future<ConflictResolution> resolveConflicts(List<SyncConflict> conflicts);
|
||||
}
|
||||
```
|
||||
|
||||
#### 3. 远程控制器 (RemoteController)
|
||||
```dart
|
||||
class CompanionRemoteController {
|
||||
// 发送远程指令
|
||||
Future<CommandResult> sendCommand(String deviceId, RemoteCommand command);
|
||||
|
||||
// 批量发送指令
|
||||
Future<List<CommandResult>> sendBatchCommands(String deviceId, List<RemoteCommand> commands);
|
||||
|
||||
// 监听远程指令
|
||||
Stream<RemoteCommand> listenForCommands();
|
||||
|
||||
// 响应远程指令
|
||||
Future<CommandResult> respondToCommand(RemoteCommand command);
|
||||
}
|
||||
```
|
||||
|
||||
#### 4. 连接管理器 (ConnectionManager)
|
||||
```dart
|
||||
class CompanionConnectionManager {
|
||||
// 建立连接
|
||||
Future<Connection> establishConnection(CompanionDevice device);
|
||||
|
||||
// 维持连接
|
||||
Future<bool> maintainConnection(String deviceId);
|
||||
|
||||
// 监控连接状态
|
||||
Stream<ConnectionStatus> monitorConnection(String deviceId);
|
||||
|
||||
// 重连设备
|
||||
Future<bool> reconnectDevice(String deviceId);
|
||||
}
|
||||
```
|
||||
|
||||
## 数据模型
|
||||
|
||||
### 设备模型
|
||||
```dart
|
||||
class CompanionDevice {
|
||||
final String id;
|
||||
final String name;
|
||||
final DeviceType type;
|
||||
final String model;
|
||||
final String version;
|
||||
final DeviceStatus status;
|
||||
final DateTime lastSeen;
|
||||
final Map<String, dynamic> capabilities;
|
||||
final SecurityInfo security;
|
||||
final ConnectionInfo connection;
|
||||
}
|
||||
|
||||
enum DeviceType {
|
||||
smartphone, // 智能手机
|
||||
tablet, // 平板电脑
|
||||
smartwatch, // 智能手表
|
||||
carDisplay, // 车载显示器
|
||||
desktop, // 桌面应用
|
||||
other // 其他设备
|
||||
}
|
||||
|
||||
enum DeviceStatus {
|
||||
online, // 在线
|
||||
offline, // 离线
|
||||
connecting, // 连接中
|
||||
syncing, // 同步中
|
||||
error // 错误状态
|
||||
}
|
||||
```
|
||||
|
||||
### 同步数据模型
|
||||
```dart
|
||||
class SyncData {
|
||||
final String id;
|
||||
final SyncDataType type;
|
||||
final Map<String, dynamic> data;
|
||||
final DateTime timestamp;
|
||||
final String version;
|
||||
final List<String> targetDevices;
|
||||
final SyncPriority priority;
|
||||
}
|
||||
|
||||
enum SyncDataType {
|
||||
userPreferences, // 用户偏好
|
||||
vehicleStatus, // 车辆状态
|
||||
mediaPlaylist, // 媒体播放列表
|
||||
navigationRoute, // 导航路线
|
||||
chargingSession, // 充电会话
|
||||
configuration // 配置信息
|
||||
}
|
||||
|
||||
enum SyncPriority {
|
||||
low, // 低优先级
|
||||
normal, // 普通优先级
|
||||
high, // 高优先级
|
||||
critical // 关键优先级
|
||||
}
|
||||
```
|
||||
|
||||
### 远程指令模型
|
||||
```dart
|
||||
class RemoteCommand {
|
||||
final String id;
|
||||
final CommandType type;
|
||||
final Map<String, dynamic> parameters;
|
||||
final String sourceDeviceId;
|
||||
final String targetDeviceId;
|
||||
final DateTime timestamp;
|
||||
final bool requiresConfirmation;
|
||||
final Duration timeout;
|
||||
}
|
||||
|
||||
enum CommandType {
|
||||
vehicleControl, // 车辆控制
|
||||
mediaControl, // 媒体控制
|
||||
navigationControl, // 导航控制
|
||||
appControl, // 应用控制
|
||||
systemControl, // 系统控制
|
||||
dataRequest // 数据请求
|
||||
}
|
||||
```
|
||||
|
||||
## API 接口
|
||||
|
||||
### 设备管理接口
|
||||
```dart
|
||||
abstract class CompanionDeviceService {
|
||||
// 发现附近设备
|
||||
Future<ApiResponse<List<CompanionDevice>>> discoverNearbyDevices();
|
||||
|
||||
// 配对设备
|
||||
Future<ApiResponse<bool>> pairDevice(PairDeviceRequest request);
|
||||
|
||||
// 获取设备列表
|
||||
Future<ApiResponse<List<CompanionDevice>>> getDeviceList();
|
||||
|
||||
// 更新设备信息
|
||||
Future<ApiResponse<bool>> updateDeviceInfo(UpdateDeviceRequest request);
|
||||
}
|
||||
```
|
||||
|
||||
### 数据同步接口
|
||||
```dart
|
||||
abstract class CompanionSyncService {
|
||||
// 同步数据
|
||||
Future<ApiResponse<SyncResult>> syncData(SyncDataRequest request);
|
||||
|
||||
// 获取同步状态
|
||||
Future<ApiResponse<SyncStatus>> getSyncStatus(String deviceId);
|
||||
|
||||
// 解决同步冲突
|
||||
Future<ApiResponse<bool>> resolveConflict(ConflictResolutionRequest request);
|
||||
}
|
||||
```
|
||||
|
||||
### 远程控制接口
|
||||
```dart
|
||||
abstract class CompanionRemoteService {
|
||||
// 发送远程命令
|
||||
Future<ApiResponse<CommandResult>> sendRemoteCommand(RemoteCommandRequest request);
|
||||
|
||||
// 获取命令状态
|
||||
Future<ApiResponse<CommandStatus>> getCommandStatus(String commandId);
|
||||
|
||||
// 取消远程命令
|
||||
Future<ApiResponse<bool>> cancelCommand(String commandId);
|
||||
}
|
||||
```
|
||||
|
||||
## 配置管理
|
||||
|
||||
### 伴侣应用配置
|
||||
```dart
|
||||
class CompanionConfig {
|
||||
final bool autoDiscovery;
|
||||
final Duration discoveryInterval;
|
||||
final int maxPairedDevices;
|
||||
final bool enableRemoteControl;
|
||||
final List<SyncDataType> enabledSyncTypes;
|
||||
final SecurityLevel securityLevel;
|
||||
|
||||
static const CompanionConfig defaultConfig = CompanionConfig(
|
||||
autoDiscovery: true,
|
||||
discoveryInterval: Duration(minutes: 5),
|
||||
maxPairedDevices: 10,
|
||||
enableRemoteControl: true,
|
||||
enabledSyncTypes: [
|
||||
SyncDataType.userPreferences,
|
||||
SyncDataType.vehicleStatus,
|
||||
SyncDataType.mediaPlaylist,
|
||||
],
|
||||
securityLevel: SecurityLevel.high,
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### 同步配置
|
||||
```dart
|
||||
class SyncConfig {
|
||||
final bool enableRealTimeSync;
|
||||
final Duration syncInterval;
|
||||
final int maxSyncRetries;
|
||||
final bool enableIncrementalSync;
|
||||
final Map<SyncDataType, SyncSettings> typeSettings;
|
||||
|
||||
static const SyncConfig defaultSyncConfig = SyncConfig(
|
||||
enableRealTimeSync: true,
|
||||
syncInterval: Duration(minutes: 1),
|
||||
maxSyncRetries: 3,
|
||||
enableIncrementalSync: true,
|
||||
typeSettings: {
|
||||
SyncDataType.vehicleStatus: SyncSettings(priority: SyncPriority.high),
|
||||
SyncDataType.userPreferences: SyncSettings(priority: SyncPriority.normal),
|
||||
},
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## 使用示例
|
||||
|
||||
### 设备发现和配对
|
||||
```dart
|
||||
// 初始化伴侣应用管理器
|
||||
final companionManager = CompanionDeviceManager.instance;
|
||||
await companionManager.initialize(CompanionConfig.defaultConfig);
|
||||
|
||||
// 发现附近设备
|
||||
final nearbyDevices = await companionManager.discoverDevices();
|
||||
|
||||
for (final device in nearbyDevices) {
|
||||
print('发现设备: ${device.name} (${device.type})');
|
||||
|
||||
// 配对兼容设备
|
||||
if (device.capabilities.containsKey('oneapp_support')) {
|
||||
final paired = await companionManager.pairDevice(device.id);
|
||||
if (paired) {
|
||||
print('设备配对成功: ${device.name}');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 监听设备状态变化
|
||||
companionManager.onDeviceStatusChanged.listen((device) {
|
||||
print('设备状态变更: ${device.name} -> ${device.status}');
|
||||
});
|
||||
```
|
||||
|
||||
### 数据同步
|
||||
```dart
|
||||
// 同步用户偏好到所有设备
|
||||
final userPreferences = await getUserPreferences();
|
||||
final syncData = SyncData(
|
||||
id: 'user_prefs_${DateTime.now().millisecondsSinceEpoch}',
|
||||
type: SyncDataType.userPreferences,
|
||||
data: userPreferences.toJson(),
|
||||
timestamp: DateTime.now(),
|
||||
priority: SyncPriority.normal,
|
||||
);
|
||||
|
||||
final pairedDevices = await companionManager.getPairedDevices();
|
||||
for (final device in pairedDevices) {
|
||||
if (device.status == DeviceStatus.online) {
|
||||
final result = await CompanionDataSynchronizer.instance.syncToDevice(device.id, syncData);
|
||||
print('同步到 ${device.name}: ${result.isSuccess}');
|
||||
}
|
||||
}
|
||||
|
||||
// 监听同步状态
|
||||
CompanionDataSynchronizer.instance.onSyncProgress.listen((progress) {
|
||||
print('同步进度: ${progress.percentage}%');
|
||||
});
|
||||
```
|
||||
|
||||
### 远程控制
|
||||
```dart
|
||||
// 远程启动车辆
|
||||
final startEngineCommand = RemoteCommand(
|
||||
id: 'start_engine_${DateTime.now().millisecondsSinceEpoch}',
|
||||
type: CommandType.vehicleControl,
|
||||
parameters: {
|
||||
'action': 'start_engine',
|
||||
'duration': 300, // 5分钟
|
||||
},
|
||||
sourceDeviceId: 'smartphone_001',
|
||||
targetDeviceId: 'car_display_001',
|
||||
requiresConfirmation: true,
|
||||
timeout: Duration(seconds: 30),
|
||||
);
|
||||
|
||||
final result = await CompanionRemoteController.instance.sendCommand(
|
||||
'car_display_001',
|
||||
startEngineCommand,
|
||||
);
|
||||
|
||||
if (result.isSuccess) {
|
||||
print('远程启动指令发送成功');
|
||||
} else {
|
||||
print('远程启动失败: ${result.error}');
|
||||
}
|
||||
|
||||
// 监听远程指令
|
||||
CompanionRemoteController.instance.listenForCommands().listen((command) {
|
||||
print('收到远程指令: ${command.type}');
|
||||
// 处理远程指令
|
||||
handleRemoteCommand(command);
|
||||
});
|
||||
```
|
||||
|
||||
### 连接管理
|
||||
```dart
|
||||
// 监控设备连接状态
|
||||
final connectionManager = CompanionConnectionManager.instance;
|
||||
|
||||
for (final device in pairedDevices) {
|
||||
connectionManager.monitorConnection(device.id).listen((status) {
|
||||
switch (status.state) {
|
||||
case ConnectionState.connected:
|
||||
print('${device.name} 已连接');
|
||||
break;
|
||||
case ConnectionState.disconnected:
|
||||
print('${device.name} 已断开,尝试重连...');
|
||||
connectionManager.reconnectDevice(device.id);
|
||||
break;
|
||||
case ConnectionState.error:
|
||||
print('${device.name} 连接错误: ${status.error}');
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
## 测试策略
|
||||
|
||||
### 单元测试
|
||||
```dart
|
||||
group('CompanionDevice Tests', () {
|
||||
test('should discover nearby devices', () async {
|
||||
// Given
|
||||
final deviceManager = CompanionDeviceManager();
|
||||
|
||||
// When
|
||||
final devices = await deviceManager.discoverDevices();
|
||||
|
||||
// Then
|
||||
expect(devices, isNotEmpty);
|
||||
expect(devices.first.type, isA<DeviceType>());
|
||||
});
|
||||
|
||||
test('should sync data successfully', () async {
|
||||
// Given
|
||||
final synchronizer = CompanionDataSynchronizer();
|
||||
final syncData = SyncData(
|
||||
id: 'test_sync',
|
||||
type: SyncDataType.userPreferences,
|
||||
data: {'theme': 'dark'},
|
||||
timestamp: DateTime.now(),
|
||||
priority: SyncPriority.normal,
|
||||
);
|
||||
|
||||
// When
|
||||
final result = await synchronizer.syncToDevice('test_device', syncData);
|
||||
|
||||
// Then
|
||||
expect(result.isSuccess, true);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### 集成测试
|
||||
```dart
|
||||
group('Companion Integration Tests', () {
|
||||
testWidgets('device pairing flow', (tester) async {
|
||||
// 1. 启动设备发现
|
||||
await CompanionDeviceManager.instance.startDiscovery();
|
||||
|
||||
// 2. 模拟发现设备
|
||||
final mockDevice = createMockDevice();
|
||||
await simulateDeviceDiscovered(mockDevice);
|
||||
|
||||
// 3. 执行配对
|
||||
final paired = await CompanionDeviceManager.instance.pairDevice(mockDevice.id);
|
||||
|
||||
// 4. 验证配对结果
|
||||
expect(paired, true);
|
||||
|
||||
final pairedDevices = await CompanionDeviceManager.instance.getPairedDevices();
|
||||
expect(pairedDevices, contains(mockDevice));
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
## 性能优化
|
||||
|
||||
### 连接优化
|
||||
- **连接池**:设备连接池管理
|
||||
- **心跳机制**:定期心跳保持连接
|
||||
- **重连策略**:智能重连机制
|
||||
- **负载均衡**:多设备负载均衡
|
||||
|
||||
### 同步优化
|
||||
- **增量同步**:只同步变化的数据
|
||||
- **压缩传输**:数据压缩减少传输量
|
||||
- **批量操作**:批量同步提高效率
|
||||
- **优先级队列**:按优先级处理同步任务
|
||||
|
||||
## 安全考虑
|
||||
|
||||
### 设备安全
|
||||
- **设备认证**:设备身份认证和授权
|
||||
- **加密通信**:端到端加密通信
|
||||
- **权限控制**:细粒度权限控制
|
||||
- **安全审计**:操作安全审计日志
|
||||
|
||||
### 数据安全
|
||||
- **数据加密**:敏感数据加密存储和传输
|
||||
- **访问控制**:基于角色的数据访问控制
|
||||
- **数据完整性**:数据完整性验证
|
||||
- **隐私保护**:用户隐私数据保护
|
||||
|
||||
## 版本历史
|
||||
|
||||
### v0.0.7 (当前版本)
|
||||
- 新增智能手表支持
|
||||
- 优化设备发现性能
|
||||
- 支持批量数据同步
|
||||
- 修复连接稳定性问题
|
||||
|
||||
### v0.0.6
|
||||
- 支持车载设备连接
|
||||
- 新增远程控制功能
|
||||
- 优化同步机制
|
||||
- 改进设备管理界面
|
||||
|
||||
## 依赖关系
|
||||
|
||||
### 内部依赖
|
||||
- `basic_platform`: 平台抽象层
|
||||
- `basic_network`: 网络通信服务
|
||||
- `basic_storage`: 本地存储服务
|
||||
- `basic_security`: 安全服务
|
||||
|
||||
### 外部依赖
|
||||
- `nearby_connections`: 设备发现和连接
|
||||
- `encrypt`: 数据加密
|
||||
- `rxdart`: 响应式编程
|
||||
- `shared_preferences`: 配置存储
|
||||
|
||||
## 总结
|
||||
|
||||
`oneapp_companion` 模块为 OneApp 提供了完整的多设备协同解决方案。通过设备发现、数据同步、远程控制和连接管理等功能,该模块实现了跨设备的无缝体验,让用户能够在不同设备间自由切换,享受一致的应用体验和便捷的远程控制功能。
|
||||
611
service_component/oneapp_popup.md
Normal file
611
service_component/oneapp_popup.md
Normal file
@@ -0,0 +1,611 @@
|
||||
# OneApp Popup - 弹窗管理模块
|
||||
|
||||
## 模块概述
|
||||
|
||||
`oneapp_popup` 是 OneApp 的统一弹窗管理模块,提供了全局弹窗管理、优先级控制、样式定制和生命周期管理等功能。该模块确保应用中所有弹窗的一致性体验,避免弹窗冲突,并提供灵活的弹窗展示策略。
|
||||
|
||||
## 核心功能
|
||||
|
||||
### 1. 统一弹窗管理
|
||||
- **全局队列**:统一管理所有弹窗显示队列
|
||||
- **弹窗注册**:注册和管理不同类型的弹窗
|
||||
- **显示控制**:控制弹窗的显示和隐藏
|
||||
- **状态管理**:跟踪弹窗的显示状态
|
||||
|
||||
### 2. 弹窗优先级控制
|
||||
- **优先级排序**:按优先级排序弹窗显示顺序
|
||||
- **抢占机制**:高优先级弹窗抢占显示
|
||||
- **队列管理**:智能管理弹窗等待队列
|
||||
- **冲突解决**:解决弹窗显示冲突
|
||||
|
||||
### 3. 弹窗样式定制
|
||||
- **主题适配**:自动适配应用主题
|
||||
- **样式继承**:支持样式继承和覆盖
|
||||
- **动画效果**:丰富的弹窗动画效果
|
||||
- **响应式设计**:适配不同屏幕尺寸
|
||||
|
||||
### 4. 弹窗生命周期
|
||||
- **生命周期钩子**:完整的生命周期回调
|
||||
- **自动销毁**:弹窗自动销毁机制
|
||||
- **内存管理**:防止内存泄漏
|
||||
- **状态恢复**:应用重启后状态恢复
|
||||
|
||||
## 技术架构
|
||||
|
||||
### 架构设计
|
||||
```
|
||||
┌─────────────────────────────────────┐
|
||||
│ 应用界面层 │
|
||||
│ (Application UI) │
|
||||
├─────────────────────────────────────┤
|
||||
│ OneApp Popup │
|
||||
│ ┌──────────┬──────────┬──────────┐ │
|
||||
│ │ 弹窗管理 │ 队列控制 │ 样式系统 │ │
|
||||
│ ├──────────┼──────────┼──────────┤ │
|
||||
│ │ 生命周期 │ 事件系统 │ 动画引擎 │ │
|
||||
│ └──────────┴──────────┴──────────┘ │
|
||||
├─────────────────────────────────────┤
|
||||
│ UI 渲染层 │
|
||||
│ ┌──────────┬──────────┬──────────┐ │
|
||||
│ │ Overlay │ Dialog │ BottomSheet │
|
||||
│ └──────────┴──────────┴──────────┘ │
|
||||
├─────────────────────────────────────┤
|
||||
│ Flutter Framework │
|
||||
│ (Widget System) │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 核心组件
|
||||
|
||||
#### 1. 弹窗管理器 (PopupManager)
|
||||
```dart
|
||||
class PopupManager {
|
||||
// 显示弹窗
|
||||
Future<T?> show<T>(Popup popup);
|
||||
|
||||
// 隐藏弹窗
|
||||
Future<bool> hide(String popupId);
|
||||
|
||||
// 隐藏所有弹窗
|
||||
Future<void> hideAll();
|
||||
|
||||
// 获取当前弹窗
|
||||
Popup? getCurrentPopup();
|
||||
|
||||
// 获取弹窗队列
|
||||
List<Popup> getPopupQueue();
|
||||
}
|
||||
```
|
||||
|
||||
#### 2. 弹窗队列控制器 (PopupQueueController)
|
||||
```dart
|
||||
class PopupQueueController {
|
||||
// 添加弹窗到队列
|
||||
void enqueue(Popup popup);
|
||||
|
||||
// 从队列移除弹窗
|
||||
bool dequeue(String popupId);
|
||||
|
||||
// 按优先级排序队列
|
||||
void sortByPriority();
|
||||
|
||||
// 处理下一个弹窗
|
||||
Future<void> processNext();
|
||||
}
|
||||
```
|
||||
|
||||
#### 3. 弹窗样式管理器 (PopupStyleManager)
|
||||
```dart
|
||||
class PopupStyleManager {
|
||||
// 应用弹窗主题
|
||||
PopupTheme applyTheme(PopupStyle style, AppTheme theme);
|
||||
|
||||
// 创建弹窗样式
|
||||
PopupStyle createStyle(PopupType type);
|
||||
|
||||
// 自定义样式
|
||||
PopupStyle customizeStyle(PopupStyle base, StyleOverrides overrides);
|
||||
|
||||
// 获取默认样式
|
||||
PopupStyle getDefaultStyle(PopupType type);
|
||||
}
|
||||
```
|
||||
|
||||
#### 4. 弹窗生命周期管理器 (PopupLifecycleManager)
|
||||
```dart
|
||||
class PopupLifecycleManager {
|
||||
// 注册生命周期监听器
|
||||
void registerLifecycleListener(String popupId, PopupLifecycleListener listener);
|
||||
|
||||
// 触发生命周期事件
|
||||
void triggerLifecycleEvent(String popupId, PopupLifecycleEvent event);
|
||||
|
||||
// 清理弹窗资源
|
||||
void cleanupPopup(String popupId);
|
||||
|
||||
// 恢复弹窗状态
|
||||
Future<void> restorePopupState();
|
||||
}
|
||||
```
|
||||
|
||||
## 数据模型
|
||||
|
||||
### 弹窗模型
|
||||
```dart
|
||||
class Popup {
|
||||
final String id;
|
||||
final PopupType type;
|
||||
final Widget content;
|
||||
final PopupPriority priority;
|
||||
final PopupStyle? style;
|
||||
final PopupOptions options;
|
||||
final Map<String, dynamic> data;
|
||||
final DateTime createdAt;
|
||||
final Duration? autoHideDelay;
|
||||
final List<PopupAction> actions;
|
||||
}
|
||||
|
||||
enum PopupType {
|
||||
dialog, // 对话框
|
||||
bottomSheet, // 底部弹窗
|
||||
toast, // 吐司消息
|
||||
overlay, // 覆盖层
|
||||
modal, // 模态框
|
||||
banner, // 横幅
|
||||
snackbar // 快捷消息
|
||||
}
|
||||
|
||||
enum PopupPriority {
|
||||
low, // 低优先级
|
||||
normal, // 普通优先级
|
||||
high, // 高优先级
|
||||
critical, // 关键优先级
|
||||
emergency // 紧急优先级
|
||||
}
|
||||
```
|
||||
|
||||
### 弹窗样式模型
|
||||
```dart
|
||||
class PopupStyle {
|
||||
final Color? backgroundColor;
|
||||
final BorderRadius? borderRadius;
|
||||
final EdgeInsets? padding;
|
||||
final EdgeInsets? margin;
|
||||
final BoxShadow? shadow;
|
||||
final TextStyle? textStyle;
|
||||
final PopupAnimation? animation;
|
||||
final Alignment? alignment;
|
||||
final Size? size;
|
||||
final bool? barrierDismissible;
|
||||
}
|
||||
|
||||
class PopupAnimation {
|
||||
final AnimationType type;
|
||||
final Duration duration;
|
||||
final Curve curve;
|
||||
final Offset? slideDirection;
|
||||
final double? scaleStart;
|
||||
}
|
||||
|
||||
enum AnimationType {
|
||||
fade, // 淡入淡出
|
||||
slide, // 滑动
|
||||
scale, // 缩放
|
||||
rotate, // 旋转
|
||||
bounce, // 弹跳
|
||||
none // 无动画
|
||||
}
|
||||
```
|
||||
|
||||
### 弹窗选项模型
|
||||
```dart
|
||||
class PopupOptions {
|
||||
final bool barrierDismissible;
|
||||
final Color? barrierColor;
|
||||
final String? barrierLabel;
|
||||
final bool useRootNavigator;
|
||||
final RouteSettings? routeSettings;
|
||||
final Offset? anchorPoint;
|
||||
final PopupGravity gravity;
|
||||
final Duration? showDuration;
|
||||
final Duration? hideDuration;
|
||||
}
|
||||
|
||||
enum PopupGravity {
|
||||
center, // 居中
|
||||
top, // 顶部
|
||||
bottom, // 底部
|
||||
left, // 左侧
|
||||
right, // 右侧
|
||||
topLeft, // 左上
|
||||
topRight, // 右上
|
||||
bottomLeft, // 左下
|
||||
bottomRight // 右下
|
||||
}
|
||||
```
|
||||
|
||||
## API 接口
|
||||
|
||||
### 弹窗管理接口
|
||||
```dart
|
||||
abstract class PopupService {
|
||||
// 显示弹窗
|
||||
Future<ApiResponse<T?>> showPopup<T>(ShowPopupRequest request);
|
||||
|
||||
// 隐藏弹窗
|
||||
Future<ApiResponse<bool>> hidePopup(HidePopupRequest request);
|
||||
|
||||
// 获取弹窗状态
|
||||
Future<ApiResponse<PopupStatus>> getPopupStatus(String popupId);
|
||||
|
||||
// 清理弹窗
|
||||
Future<ApiResponse<bool>> clearPopups(ClearPopupsRequest request);
|
||||
}
|
||||
```
|
||||
|
||||
### 弹窗样式接口
|
||||
```dart
|
||||
abstract class PopupStyleService {
|
||||
// 获取弹窗主题
|
||||
Future<ApiResponse<PopupTheme>> getPopupTheme(String themeId);
|
||||
|
||||
// 更新弹窗样式
|
||||
Future<ApiResponse<bool>> updatePopupStyle(UpdateStyleRequest request);
|
||||
|
||||
// 获取样式模板
|
||||
Future<ApiResponse<List<PopupStyleTemplate>>> getStyleTemplates();
|
||||
}
|
||||
```
|
||||
|
||||
## 配置管理
|
||||
|
||||
### 弹窗配置
|
||||
```dart
|
||||
class PopupConfig {
|
||||
final int maxConcurrentPopups;
|
||||
final Duration defaultAnimationDuration;
|
||||
final bool enableGlobalQueue;
|
||||
final bool autoHideOnAppBackground;
|
||||
final Map<PopupType, PopupTypeConfig> typeConfigs;
|
||||
final PopupTheme defaultTheme;
|
||||
|
||||
static const PopupConfig defaultConfig = PopupConfig(
|
||||
maxConcurrentPopups: 3,
|
||||
defaultAnimationDuration: Duration(milliseconds: 300),
|
||||
enableGlobalQueue: true,
|
||||
autoHideOnAppBackground: true,
|
||||
typeConfigs: {
|
||||
PopupType.dialog: PopupTypeConfig(
|
||||
maxInstances: 1,
|
||||
defaultPriority: PopupPriority.high,
|
||||
),
|
||||
PopupType.toast: PopupTypeConfig(
|
||||
maxInstances: 5,
|
||||
defaultPriority: PopupPriority.low,
|
||||
),
|
||||
},
|
||||
defaultTheme: PopupTheme.defaultTheme,
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### 主题配置
|
||||
```dart
|
||||
class PopupTheme {
|
||||
final PopupStyle dialogStyle;
|
||||
final PopupStyle toastStyle;
|
||||
final PopupStyle bottomSheetStyle;
|
||||
final PopupStyle overlayStyle;
|
||||
final Map<String, PopupStyle> customStyles;
|
||||
|
||||
static const PopupTheme defaultTheme = PopupTheme(
|
||||
dialogStyle: PopupStyle(
|
||||
backgroundColor: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8.0),
|
||||
padding: EdgeInsets.all(16.0),
|
||||
animation: PopupAnimation(
|
||||
type: AnimationType.scale,
|
||||
duration: Duration(milliseconds: 300),
|
||||
),
|
||||
),
|
||||
toastStyle: PopupStyle(
|
||||
backgroundColor: Colors.black87,
|
||||
borderRadius: BorderRadius.circular(24.0),
|
||||
padding: EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
|
||||
animation: PopupAnimation(
|
||||
type: AnimationType.slide,
|
||||
duration: Duration(milliseconds: 200),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## 使用示例
|
||||
|
||||
### 基本弹窗显示
|
||||
```dart
|
||||
// 显示对话框
|
||||
final result = await PopupManager.instance.show<bool>(
|
||||
Popup(
|
||||
id: 'confirm_dialog',
|
||||
type: PopupType.dialog,
|
||||
priority: PopupPriority.high,
|
||||
content: AlertDialog(
|
||||
title: Text('确认操作'),
|
||||
content: Text('是否确认执行此操作?'),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(false),
|
||||
child: Text('取消'),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(true),
|
||||
child: Text('确认'),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
if (result == true) {
|
||||
print('用户确认操作');
|
||||
}
|
||||
```
|
||||
|
||||
### 吐司消息
|
||||
```dart
|
||||
// 显示成功消息
|
||||
PopupManager.instance.show(
|
||||
Popup(
|
||||
id: 'success_toast',
|
||||
type: PopupType.toast,
|
||||
priority: PopupPriority.normal,
|
||||
content: Container(
|
||||
padding: EdgeInsets.all(16.0),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.green,
|
||||
borderRadius: BorderRadius.circular(8.0),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Icon(Icons.check, color: Colors.white),
|
||||
SizedBox(width: 8.0),
|
||||
Text('操作成功', style: TextStyle(color: Colors.white)),
|
||||
],
|
||||
),
|
||||
),
|
||||
options: PopupOptions(
|
||||
gravity: PopupGravity.top,
|
||||
barrierDismissible: false,
|
||||
),
|
||||
autoHideDelay: Duration(seconds: 3),
|
||||
),
|
||||
);
|
||||
```
|
||||
|
||||
### 底部弹窗
|
||||
```dart
|
||||
// 显示底部选择弹窗
|
||||
final selectedOption = await PopupManager.instance.show<String>(
|
||||
Popup(
|
||||
id: 'bottom_sheet_options',
|
||||
type: PopupType.bottomSheet,
|
||||
priority: PopupPriority.normal,
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
ListTile(
|
||||
leading: Icon(Icons.camera),
|
||||
title: Text('拍照'),
|
||||
onTap: () => Navigator.of(context).pop('camera'),
|
||||
),
|
||||
ListTile(
|
||||
leading: Icon(Icons.photo_library),
|
||||
title: Text('从相册选择'),
|
||||
onTap: () => Navigator.of(context).pop('gallery'),
|
||||
),
|
||||
ListTile(
|
||||
leading: Icon(Icons.cancel),
|
||||
title: Text('取消'),
|
||||
onTap: () => Navigator.of(context).pop(null),
|
||||
),
|
||||
],
|
||||
),
|
||||
style: PopupStyle(
|
||||
backgroundColor: Colors.white,
|
||||
borderRadius: BorderRadius.vertical(top: Radius.circular(16.0)),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
print('用户选择: $selectedOption');
|
||||
```
|
||||
|
||||
### 自定义弹窗样式
|
||||
```dart
|
||||
// 创建自定义样式弹窗
|
||||
final customStyle = PopupStyle(
|
||||
backgroundColor: Colors.blue.shade50,
|
||||
borderRadius: BorderRadius.circular(12.0),
|
||||
padding: EdgeInsets.all(20.0),
|
||||
shadow: BoxShadow(
|
||||
color: Colors.black26,
|
||||
blurRadius: 10.0,
|
||||
offset: Offset(0, 4),
|
||||
),
|
||||
animation: PopupAnimation(
|
||||
type: AnimationType.bounce,
|
||||
duration: Duration(milliseconds: 500),
|
||||
curve: Curves.elasticOut,
|
||||
),
|
||||
);
|
||||
|
||||
PopupManager.instance.show(
|
||||
Popup(
|
||||
id: 'custom_popup',
|
||||
type: PopupType.modal,
|
||||
priority: PopupPriority.high,
|
||||
style: customStyle,
|
||||
content: Container(
|
||||
width: 300,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Icon(Icons.info, size: 48, color: Colors.blue),
|
||||
SizedBox(height: 16),
|
||||
Text('自定义弹窗', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
|
||||
SizedBox(height: 8),
|
||||
Text('这是一个自定义样式的弹窗示例'),
|
||||
SizedBox(height: 16),
|
||||
ElevatedButton(
|
||||
onPressed: () => PopupManager.instance.hide('custom_popup'),
|
||||
child: Text('关闭'),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
```
|
||||
|
||||
### 弹窗队列管理
|
||||
```dart
|
||||
// 批量添加弹窗到队列
|
||||
final popups = [
|
||||
Popup(
|
||||
id: 'popup_1',
|
||||
type: PopupType.toast,
|
||||
priority: PopupPriority.low,
|
||||
content: Text('消息1'),
|
||||
),
|
||||
Popup(
|
||||
id: 'popup_2',
|
||||
type: PopupType.dialog,
|
||||
priority: PopupPriority.high,
|
||||
content: Text('重要消息'),
|
||||
),
|
||||
Popup(
|
||||
id: 'popup_3',
|
||||
type: PopupType.toast,
|
||||
priority: PopupPriority.normal,
|
||||
content: Text('消息3'),
|
||||
),
|
||||
];
|
||||
|
||||
// 按优先级添加到队列
|
||||
for (final popup in popups) {
|
||||
PopupManager.instance.enqueue(popup);
|
||||
}
|
||||
|
||||
// 监听弹窗队列变化
|
||||
PopupManager.instance.onQueueChanged.listen((queue) {
|
||||
print('当前队列长度: ${queue.length}');
|
||||
});
|
||||
```
|
||||
|
||||
## 测试策略
|
||||
|
||||
### 单元测试
|
||||
```dart
|
||||
group('PopupManager Tests', () {
|
||||
test('should show popup successfully', () async {
|
||||
// Given
|
||||
final popupManager = PopupManager();
|
||||
final popup = Popup(
|
||||
id: 'test_popup',
|
||||
type: PopupType.dialog,
|
||||
content: Text('Test'),
|
||||
);
|
||||
|
||||
// When
|
||||
final result = await popupManager.show(popup);
|
||||
|
||||
// Then
|
||||
expect(popupManager.getCurrentPopup()?.id, 'test_popup');
|
||||
});
|
||||
|
||||
test('should manage popup queue by priority', () {
|
||||
// Given
|
||||
final queueController = PopupQueueController();
|
||||
final lowPriorityPopup = Popup(id: 'low', priority: PopupPriority.low);
|
||||
final highPriorityPopup = Popup(id: 'high', priority: PopupPriority.high);
|
||||
|
||||
// When
|
||||
queueController.enqueue(lowPriorityPopup);
|
||||
queueController.enqueue(highPriorityPopup);
|
||||
queueController.sortByPriority();
|
||||
|
||||
// Then
|
||||
final queue = queueController.getQueue();
|
||||
expect(queue.first.id, 'high');
|
||||
expect(queue.last.id, 'low');
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### 集成测试
|
||||
```dart
|
||||
group('Popup Integration Tests', () {
|
||||
testWidgets('popup display flow', (tester) async {
|
||||
// 1. 显示弹窗
|
||||
await PopupManager.instance.show(testPopup);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// 2. 验证弹窗显示
|
||||
expect(find.byKey(Key('test_popup')), findsOneWidget);
|
||||
|
||||
// 3. 点击关闭按钮
|
||||
await tester.tap(find.byKey(Key('close_button')));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// 4. 验证弹窗关闭
|
||||
expect(find.byKey(Key('test_popup')), findsNothing);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
## 性能优化
|
||||
|
||||
### 渲染优化
|
||||
- **懒加载**:弹窗内容懒加载
|
||||
- **复用机制**:弹窗组件复用
|
||||
- **动画优化**:高效的动画实现
|
||||
- **内存管理**:及时释放弹窗资源
|
||||
|
||||
### 队列优化
|
||||
- **智能调度**:智能弹窗调度算法
|
||||
- **优先级合并**:相同优先级弹窗合并
|
||||
- **批量处理**:批量处理弹窗队列
|
||||
- **负载控制**:控制同时显示的弹窗数量
|
||||
|
||||
## 版本历史
|
||||
|
||||
### v0.3.1+2 (当前版本)
|
||||
- 新增弹窗主题系统
|
||||
- 优化动画性能
|
||||
- 支持自定义弹窗样式
|
||||
- 修复内存泄漏问题
|
||||
|
||||
### v0.3.0
|
||||
- 重构弹窗管理架构
|
||||
- 新增优先级队列系统
|
||||
- 支持多种弹窗类型
|
||||
- 改进生命周期管理
|
||||
|
||||
## 依赖关系
|
||||
|
||||
### 内部依赖
|
||||
- `basic_theme`: 主题管理系统
|
||||
- `basic_utils`: 工具类库
|
||||
- `basic_logger`: 日志记录
|
||||
|
||||
### 外部依赖
|
||||
- `flutter/material`: Material 设计组件
|
||||
- `flutter/cupertino`: iOS 风格组件
|
||||
- `rxdart`: 响应式编程支持
|
||||
|
||||
## 总结
|
||||
|
||||
`oneapp_popup` 模块为 OneApp 提供了完整的弹窗管理解决方案。通过统一的弹窗管理、智能的优先级控制、灵活的样式定制和完善的生命周期管理,该模块确保了应用中所有弹窗的一致性体验,提高了用户界面的专业性和用户体验的流畅性。
|
||||
Reference in New Issue
Block a user