@@ -0,0 +1,208 @@ | |||
import 'package:flutter/material.dart'; | |||
import 'package:zhiying_base_widget/pages/about_us_page/about_us_page_sk.dart'; | |||
import 'package:zhiying_base_widget/pages/about_us_page/bloc/about_us_bloc.dart'; | |||
import 'package:zhiying_base_widget/pages/about_us_page/bloc/about_us_repository.dart'; | |||
import 'package:zhiying_base_widget/pages/about_us_page/model/about_us_model.dart'; | |||
import 'package:zhiying_comm/zhiying_comm.dart'; | |||
import 'package:flutter_bloc/flutter_bloc.dart'; | |||
import 'bloc/about_us_bloc.dart'; | |||
import 'bloc/about_us_event.dart'; | |||
import 'bloc/about_us_state.dart'; | |||
/// | |||
/// 关于我们 | |||
/// | |||
class AboutUsPage extends StatelessWidget { | |||
final Map<String, dynamic> data; | |||
AboutUsPage(this.data); | |||
@override | |||
Widget build(BuildContext context) { | |||
return BlocProvider<AboutUsBloc>( | |||
create: (_) => AboutUsBloc(AboutUsRepository())..add(AboutUsInitEvent(data)), | |||
child: _AboutUsPageContainer(), | |||
); | |||
} | |||
} | |||
class _AboutUsPageContainer extends StatefulWidget { | |||
@override | |||
__AboutUsPageContainerState createState() => __AboutUsPageContainerState(); | |||
} | |||
class __AboutUsPageContainerState extends State<_AboutUsPageContainer> { | |||
/// 检查更新 | |||
void _onClickCheckUpdate() { | |||
Logger.log('点击了更新'); | |||
} | |||
/// 给个评价 | |||
void _onClickEvaluation() { | |||
Logger.log('点击了评价'); | |||
} | |||
/// list 子点击 | |||
void _onClickListItem(Settings model) { | |||
if (model.type == 'check_app') { | |||
_onClickCheckUpdate(); | |||
} else if (model.type == 'comment') { | |||
_onClickEvaluation(); | |||
} | |||
} | |||
@override | |||
Widget build(BuildContext context) { | |||
return BlocBuilder<AboutUsBloc, AboutUsState>( | |||
builder: (context, state) { | |||
if (state is AboutUsLoadedState) { | |||
return _buildMainWidget(state?.model); | |||
} | |||
return _buildSkeletion(); | |||
}, | |||
); | |||
} | |||
/// 主视图 | |||
Widget _buildMainWidget(AboutUsModel model) { | |||
return Scaffold( | |||
backgroundColor: HexColor.fromHex(model?.bgColor ?? '#F9F9F9'), | |||
appBar: _buildAppBarWidget(null), | |||
body: Padding( | |||
padding: const EdgeInsets.only(top: 5), | |||
child: Column( | |||
mainAxisAlignment: MainAxisAlignment.start, | |||
crossAxisAlignment: CrossAxisAlignment.center, | |||
children: <Widget>[ | |||
_buildHeadWidget(model), | |||
/// 文字 | |||
Expanded(child: Padding(padding: const EdgeInsets.only(bottom: 21), child: _buildCompanyInfoWidget(model))), | |||
], | |||
), | |||
), | |||
); | |||
} | |||
/// 骨架图 | |||
Widget _buildSkeletion() { | |||
return Scaffold( | |||
appBar: _buildAppBarWidget(null), | |||
body: AboutUsPageSkeleton(), | |||
); | |||
} | |||
/// Icon等信息 | |||
Widget _buildHeadWidget(AboutUsModel model) { | |||
return Container( | |||
padding: const EdgeInsets.only(top: 25, left: 12.5, right: 12.5), | |||
width: double.infinity, | |||
decoration: BoxDecoration( | |||
color: HexColor.fromHex(model?.settingsBgColor ?? '#FFFFFF'), | |||
), | |||
child: Column( | |||
children: <Widget>[ | |||
/// icon | |||
CachedNetworkImage( | |||
imageUrl: model?.appLogo ?? '', | |||
width: 84, | |||
), | |||
const SizedBox(height: 7.5), | |||
/// 版本号 | |||
RichText( | |||
text: TextSpan(children: [ | |||
TextSpan( | |||
text: model?.appVersionText ?? '版本号', | |||
style: TextStyle( | |||
fontSize: 11, | |||
color: HexColor.fromHex(model?.appVersionColor ?? '#999999'), | |||
)), | |||
TextSpan( | |||
text: ' ${model?.appVerison ?? '1.0.0'}', | |||
style: TextStyle( | |||
fontSize: 11, | |||
color: HexColor.fromHex(model?.appVersionColor ?? '#999999'), | |||
)), | |||
]), | |||
), | |||
const SizedBox(height: 20), | |||
/// 更新,评价 | |||
_buildListWidget(model), | |||
], | |||
), | |||
); | |||
} | |||
/// 列表 | |||
Widget _buildListWidget(AboutUsModel model) { | |||
List<Widget> widgets = []; | |||
int length = model?.settings?.length ?? 0; | |||
if (length == 0) { | |||
widgets.add(Container()); | |||
} else { | |||
model.settings.forEach((element) { | |||
widgets.add(GestureDetector( | |||
onTap: () => _onClickListItem(element), | |||
behavior: HitTestBehavior.opaque, | |||
child: Container( | |||
margin: const EdgeInsets.symmetric(vertical: 15), | |||
child: Row( | |||
mainAxisAlignment: MainAxisAlignment.spaceBetween, | |||
children: <Widget>[ | |||
Text( | |||
element?.name ?? '', | |||
style: TextStyle(color: HexColor.fromHex(element?.nameColor ?? '#333333'), fontSize: 13, fontWeight: FontWeight.bold), | |||
), | |||
Icon( | |||
Icons.arrow_forward_ios, | |||
color: HexColor.fromHex(element?.descColor ?? '#999999'), | |||
size: 14, | |||
) | |||
], | |||
), | |||
), | |||
)); | |||
}); | |||
return Column( | |||
children: widgets, | |||
); | |||
} | |||
} | |||
/// 公司信息等 | |||
Widget _buildCompanyInfoWidget(AboutUsModel model) { | |||
return Align( | |||
alignment: Alignment.bottomCenter, | |||
child: Text( | |||
model?.bottomName ?? '', | |||
style: TextStyle(fontSize: 11, color: HexColor.fromHex(model?.bottomNameColor ?? '#999999')), | |||
), | |||
); | |||
} | |||
/// appbar | |||
Widget _buildAppBarWidget(AboutUsModel model) { | |||
return AppBar( | |||
backgroundColor: HexColor.fromHex(model?.appBarBgColor ?? '#FFFFFF'), | |||
brightness: Brightness.light, | |||
leading: IconButton( | |||
icon: Icon( | |||
Icons.arrow_back_ios, | |||
size: 22, | |||
color: HexColor.fromHex('#333333'), | |||
), | |||
onPressed: () => Navigator.maybePop(context), | |||
), | |||
title: Text( | |||
model?.appBarName ?? '关于我们', | |||
style: TextStyle(color: HexColor.fromHex(model?.appBarNameColor ?? '#333333'), fontSize: 15, fontWeight: FontWeight.bold), | |||
), | |||
centerTitle: true, | |||
elevation: 0, | |||
); | |||
} | |||
} |
@@ -0,0 +1,8 @@ | |||
import 'package:flutter/material.dart'; | |||
class AboutUsPageSkeleton extends StatelessWidget { | |||
@override | |||
Widget build(BuildContext context) { | |||
return Container(); | |||
} | |||
} |
@@ -0,0 +1,47 @@ | |||
import 'dart:async'; | |||
import 'package:bloc/bloc.dart'; | |||
import 'package:zhiying_base_widget/pages/about_us_page/bloc/about_us_repository.dart'; | |||
import 'package:zhiying_comm/zhiying_comm.dart'; | |||
import 'about_us_state.dart'; | |||
import 'about_us_event.dart'; | |||
class AboutUsBloc extends Bloc<AboutUsEvent, AboutUsState> { | |||
// AboutUsBloc() : super(AboutUsInitial()); | |||
AboutUsRepository repository; | |||
AboutUsBloc(this.repository); | |||
@override | |||
AboutUsState get initialState => AboutUsInitial(); | |||
@override | |||
Stream<AboutUsState> mapEventToState( | |||
AboutUsEvent event, | |||
) async* { | |||
if (event is AboutUsInitEvent) { | |||
yield* _mapInitEventToState(event); | |||
} | |||
} | |||
/// 初始化数据 | |||
Stream<AboutUsState> _mapInitEventToState(AboutUsInitEvent event) async* { | |||
/// 1、父页面数据 | |||
var parentData = await repository.fetchParentData(event?.data); | |||
if (!EmptyUtil.isEmpty(parentData)) { | |||
yield AboutUsLoadedState(model: parentData); | |||
return; | |||
} | |||
var cacheData = await repository.fetchCacheData(event?.data); | |||
if (!EmptyUtil.isEmpty(cacheData)) { | |||
yield AboutUsLoadedState(model: cacheData); | |||
} | |||
var netData = await repository.fetchNetData(event?.data); | |||
if (!EmptyUtil.isEmpty(netData)) { | |||
yield AboutUsLoadedState(model: netData); | |||
} else { | |||
yield AboutUsErrorState(); | |||
} | |||
} | |||
} |
@@ -0,0 +1,10 @@ | |||
import 'package:meta/meta.dart'; | |||
@immutable | |||
abstract class AboutUsEvent {} | |||
/// 初始化 | |||
class AboutUsInitEvent extends AboutUsEvent{ | |||
final Map<String, dynamic> data; | |||
AboutUsInitEvent(this.data); | |||
} |
@@ -0,0 +1,91 @@ | |||
import 'dart:convert'; | |||
import 'package:zhiying_base_widget/pages/about_us_page/model/about_us_model.dart'; | |||
import 'package:package_info/package_info.dart'; | |||
import 'package:zhiying_comm/zhiying_comm.dart'; | |||
class AboutUsRepository { | |||
/// 检查更新 | |||
Future<AboutUsModel> checkUpdate() async { | |||
try { | |||
var result = await NetUtil.post('/api/v1/appcheck', method: NetMethod.POST); | |||
} catch (e, s) { | |||
Logger.error(e, s); | |||
} | |||
return null; | |||
} | |||
/// 返回父页面传进来的数据 | |||
Future<AboutUsModel> fetchParentData(final Map<String, dynamic> data) async { | |||
try { | |||
if (!EmptyUtil.isEmpty(data) && !EmptyUtil.isEmpty(data['data'])) { | |||
PackageInfo packageInfo = await PackageInfo.fromPlatform(); | |||
if (data['data'] is String) { | |||
AboutUsModel model = AboutUsModel.fromJson(jsonDecode(data['data'])); | |||
if (!EmptyUtil.isEmpty(packageInfo) && !EmptyUtil.isEmpty(model)) { | |||
model.appVerison = packageInfo.version; | |||
return model; | |||
} | |||
} | |||
if (data['data'] is Map) { | |||
AboutUsModel model = AboutUsModel.fromJson(data['data']); | |||
if (!EmptyUtil.isEmpty(packageInfo) && !EmptyUtil.isEmpty(model)) { | |||
model.appVerison = packageInfo.version; | |||
return model; | |||
} | |||
} | |||
} | |||
} catch (e, s) { | |||
Logger.error(e, s); | |||
} | |||
return null; | |||
} | |||
/// 获取网络数据 | |||
Future<AboutUsModel> fetchNetData(final Map<String, dynamic> data) async { | |||
try { | |||
String skip_identifier = | |||
!EmptyUtil.isEmpty(data) && data.containsKey('skip_identifier') && !EmptyUtil.isEmpty(data['skip_identifier']) ? data['skip_identifier'] : 'pub.flutter.about_us'; | |||
var result = await NetUtil.post('/api/v1/mod/$skip_identifier', method: NetMethod.GET, cache: true); | |||
if (NetUtil.isSuccess(result) && !EmptyUtil.isEmpty(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA])) { | |||
var modListData = result[GlobalConfig.HTTP_RESPONSE_KEY_DATA]['mod_list'][0]['data']; | |||
if (!EmptyUtil.isEmpty(modListData)) { | |||
PackageInfo packageInfo = await PackageInfo.fromPlatform(); | |||
AboutUsModel model = AboutUsModel.fromJson(jsonDecode(modListData)); | |||
if (!EmptyUtil.isEmpty(packageInfo) && !EmptyUtil.isEmpty(model)) { | |||
model.appVerison = packageInfo.version; | |||
return model; | |||
} | |||
} | |||
} | |||
} catch (e, s) { | |||
Logger.error(e, s); | |||
} | |||
return null; | |||
} | |||
/// 获取缓存数据 | |||
Future<AboutUsModel> fetchCacheData(final Map<String, dynamic> data) async { | |||
try { | |||
String skip_identifier = | |||
!EmptyUtil.isEmpty(data) && data.containsKey('skip_identifier') && !EmptyUtil.isEmpty(data['skip_identifier']) ? data['skip_identifier'] : 'pub.flutter.about_us'; | |||
var result = await NetUtil.getRequestCachedData('/api/v1/mod/$skip_identifier'); | |||
if (!EmptyUtil.isEmpty(result)) { | |||
var modListData = result['mod_list'][0]['data']; | |||
if (!EmptyUtil.isEmpty(modListData)) { | |||
PackageInfo packageInfo = await PackageInfo.fromPlatform(); | |||
AboutUsModel model = AboutUsModel.fromJson(jsonDecode(modListData)); | |||
if (!EmptyUtil.isEmpty(packageInfo) && !EmptyUtil.isEmpty(model)) { | |||
model.appVerison = packageInfo.version; | |||
return model; | |||
} | |||
} | |||
} | |||
} catch (e, s) { | |||
Logger.error(e, s); | |||
} | |||
return null; | |||
} | |||
} |
@@ -0,0 +1,17 @@ | |||
import 'package:meta/meta.dart'; | |||
import 'package:zhiying_base_widget/pages/about_us_page/model/about_us_model.dart'; | |||
@immutable | |||
abstract class AboutUsState {} | |||
class AboutUsInitial extends AboutUsState {} | |||
/// 数据加载成功 | |||
class AboutUsLoadedState extends AboutUsState{ | |||
AboutUsModel model; | |||
AboutUsLoadedState({this.model}); | |||
} | |||
/// 数据加载失败 | |||
class AboutUsErrorState extends AboutUsState{} |
@@ -0,0 +1,112 @@ | |||
class AboutUsModel { | |||
String appBarName; | |||
String appBarNameColor; | |||
String appBarBgColor; | |||
String bgColor; | |||
String settingsBgColor; | |||
String appLogo; | |||
String appVersionText; | |||
String appVersionColor; | |||
List<String> dataKeys; | |||
List<Settings> settings; | |||
String bottomName; | |||
String bottomNameColor; | |||
String appVerison; | |||
AboutUsModel({ | |||
this.appBarName, | |||
this.appBarNameColor, | |||
this.appBarBgColor, | |||
this.bgColor, | |||
this.settingsBgColor, | |||
this.appLogo, | |||
this.appVersionText, | |||
this.appVersionColor, | |||
this.dataKeys, | |||
this.settings, | |||
this.bottomName, | |||
this.bottomNameColor, | |||
this.appVerison, | |||
}); | |||
AboutUsModel.fromJson(Map<String, dynamic> json) { | |||
appBarName = json['app_bar_name']; | |||
appBarNameColor = json['app_bar_name_color']; | |||
appBarBgColor = json['app_bar_bg_color']; | |||
bgColor = json['bg_color']; | |||
settingsBgColor = json['settings_bg_color']; | |||
appLogo = json['app_logo']; | |||
appVersionText = json['app_version_text']; | |||
appVersionColor = json['app_version_color']; | |||
appVerison = json['appVerison']; | |||
dataKeys = json['data_keys'].cast<String>(); | |||
if (json['settings'] != null) { | |||
settings = new List<Settings>(); | |||
json['settings'].forEach((v) { | |||
settings.add(new Settings.fromJson(v)); | |||
}); | |||
} | |||
bottomName = json['bottom_name']; | |||
bottomNameColor = json['bottom_name_color']; | |||
} | |||
Map<String, dynamic> toJson() { | |||
final Map<String, dynamic> data = new Map<String, dynamic>(); | |||
data['app_bar_name'] = this.appBarName; | |||
data['app_bar_name_color'] = this.appBarNameColor; | |||
data['app_bar_bg_color'] = this.appBarBgColor; | |||
data['bg_color'] = this.bgColor; | |||
data['settings_bg_color'] = this.settingsBgColor; | |||
data['app_logo'] = this.appLogo; | |||
data['app_version_text'] = this.appVersionText; | |||
data['app_version_color'] = this.appVersionColor; | |||
data['data_keys'] = this.dataKeys; | |||
if (this.settings != null) { | |||
data['settings'] = this.settings.map((v) => v.toJson()).toList(); | |||
} | |||
data['bottom_name'] = this.bottomName; | |||
data['bottom_name_color'] = this.bottomNameColor; | |||
data['appVerison'] = this.appVerison; | |||
return data; | |||
} | |||
} | |||
class Settings { | |||
List<String> dataKeys; | |||
String type; | |||
String name; | |||
String subName; | |||
String nameColor; | |||
String subNameColor; | |||
String descText; | |||
String descColor; | |||
String skipIdentifier; | |||
Settings({this.dataKeys, this.name, this.subName, this.nameColor, this.subNameColor, this.descText, this.descColor, this.skipIdentifier}); | |||
Settings.fromJson(Map<String, dynamic> json) { | |||
dataKeys = json['data_keys'].cast<String>(); | |||
name = json['name']; | |||
type = json['type']; | |||
subName = json['sub_name']; | |||
nameColor = json['name_color']; | |||
subNameColor = json['sub_name_color']; | |||
descText = json['desc_text']; | |||
descColor = json['desc_color']; | |||
skipIdentifier = json['skip_identifier']; | |||
} | |||
Map<String, dynamic> toJson() { | |||
final Map<String, dynamic> data = new Map<String, dynamic>(); | |||
data['data_keys'] = this.dataKeys; | |||
data['type'] = this.type; | |||
data['name'] = this.name; | |||
data['sub_name'] = this.subName; | |||
data['name_color'] = this.nameColor; | |||
data['sub_name_color'] = this.subNameColor; | |||
data['desc_text'] = this.descText; | |||
data['desc_color'] = this.descColor; | |||
data['skip_identifier'] = this.skipIdentifier; | |||
return data; | |||
} | |||
} |
@@ -24,7 +24,7 @@ class FavoritesRepository { | |||
/// 获取缓存样式 | |||
Future<FavoritesStyleModel> fetchCachedStyle() async { | |||
try { | |||
var result = await NetUtil.getRequestCachedData(''); | |||
var result = await NetUtil.getRequestCachedData('/api/v1/mod/pub.flutter.my_fav'); | |||
if(!EmptyUtil.isEmpty(result)){ | |||
var modListData = result['mod_list'][0]['data']; | |||
if(!EmptyUtil.isEmpty(modListData)){ | |||
@@ -19,6 +19,10 @@ import 'notifier/favorites_page_notifier.dart'; | |||
/// 收藏夹 | |||
/// | |||
class FavoritesPage extends StatelessWidget { | |||
final Map<String, dynamic> data; | |||
FavoritesPage(this.data); | |||
@override | |||
Widget build(BuildContext context) { | |||
return MultiProvider( | |||
@@ -0,0 +1,65 @@ | |||
import 'dart:async'; | |||
import 'package:bloc/bloc.dart'; | |||
import 'package:meta/meta.dart'; | |||
import 'package:zhiying_base_widget/pages/message_settings_page/bloc/message_settings_repository.dart'; | |||
import 'package:zhiying_comm/zhiying_comm.dart'; | |||
import 'message_settings_event.dart'; | |||
import 'message_settings_state.dart'; | |||
class MessageSettingsBloc extends Bloc<MessageSettingsEvent, MessageSettingsState> { | |||
@override | |||
MessageSettingsState get initialState => MessageSettingsInitial(); | |||
MessageSettingsRepository repository; | |||
MessageSettingsBloc(this.repository); | |||
@override | |||
Stream<MessageSettingsState> mapEventToState( | |||
MessageSettingsEvent event, | |||
) async* { | |||
/// 初始化 | |||
if (event is MessageSettingsInitEvent) { | |||
yield* _mapInitEventToState(event); | |||
} | |||
/// 跟新 | |||
if (event is MessageSettingsUpdateEvent) { | |||
yield* _mapUpdateEventToState(event); | |||
} | |||
} | |||
/// 初始化 | |||
Stream<MessageSettingsState> _mapInitEventToState(MessageSettingsInitEvent event) async* { | |||
/// 1、父页面数据 | |||
var parentStyleData = await repository.fetchParentStyleData(event?.data); | |||
var result = await repository.fetchNetData(); | |||
if (!EmptyUtil.isEmpty(parentStyleData)) { | |||
yield MessageSettingsLoadedState(styleModel: parentStyleData, dataModel: result); | |||
return; | |||
} | |||
var cacheStyleData = await repository.fetchCacheStyleData(event?.data); | |||
if (!EmptyUtil.isEmpty(cacheStyleData)) { | |||
yield MessageSettingsLoadedState(styleModel: cacheStyleData, dataModel: result); | |||
} | |||
var netStyleData = await repository.fetchNetStyleData(event?.data); | |||
if (!EmptyUtil.isEmpty(netStyleData)) { | |||
yield MessageSettingsLoadedState(styleModel: netStyleData, dataModel: result); | |||
} else { | |||
yield MessageSettingsErrorState(); | |||
} | |||
} | |||
/// 更新值 | |||
Stream<MessageSettingsState> _mapUpdateEventToState(MessageSettingsUpdateEvent event) async* { | |||
var styleModel = repository.getStyleModel(); | |||
var dataModel = await repository.updateData(key: event.key, value: event.value); | |||
if (!EmptyUtil.isEmpty(styleModel) && !EmptyUtil.isEmpty(dataModel)) { | |||
yield MessageSettingsLoadedState(dataModel: dataModel, styleModel: styleModel); | |||
} else { | |||
yield MessageSettingsUpdateErrorState(); | |||
} | |||
} | |||
} |
@@ -0,0 +1,19 @@ | |||
import 'package:meta/meta.dart'; | |||
@immutable | |||
abstract class MessageSettingsEvent {} | |||
/// 初始化数据 | |||
class MessageSettingsInitEvent extends MessageSettingsEvent { | |||
final Map<String, dynamic> data; | |||
MessageSettingsInitEvent(this.data); | |||
} | |||
/// 更新数据 | |||
class MessageSettingsUpdateEvent extends MessageSettingsEvent { | |||
String key; | |||
bool value; | |||
MessageSettingsUpdateEvent({this.value, this.key}); | |||
} |
@@ -0,0 +1,114 @@ | |||
import 'dart:convert'; | |||
import 'package:zhiying_base_widget/pages/message_settings_page/model/message_settings_data_model.dart'; | |||
import 'package:zhiying_base_widget/pages/message_settings_page/model/message_settings_style_model.dart'; | |||
import 'package:zhiying_comm/zhiying_comm.dart'; | |||
class MessageSettingsRepository { | |||
// 样式 | |||
MessageSettingsStyleModel _styleModel; | |||
// 数据 | |||
MessageSettingsDataModel _dataModel; | |||
/// 获取style | |||
MessageSettingsStyleModel getStyleModel() { | |||
return _styleModel; | |||
} | |||
/// 获取data | |||
Future<MessageSettingsDataModel> fetchNetData() async { | |||
try { | |||
var result = await NetUtil.post('/api/v1/settings/message_settings', method: NetMethod.GET); | |||
if (NetUtil.isSuccess(result) && !EmptyUtil.isEmpty(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA])) { | |||
_dataModel = MessageSettingsDataModel(); | |||
_dataModel.data = result[GlobalConfig.HTTP_RESPONSE_KEY_DATA]; | |||
return _dataModel; | |||
} | |||
} catch (e, s) { | |||
Logger.error(e, s); | |||
} | |||
return null; | |||
} | |||
/// 更新data | |||
Future<MessageSettingsDataModel> updateData({String key, bool value}) async { | |||
try { | |||
/// 刷新 | |||
_dataModel.data[key] = value ? '1' : '0'; | |||
String newMsgNotice = _dataModel.data['new_msg_notice']; | |||
var result = await NetUtil.post('/api/v1/settings/message_settings', params: {'new_msg_notice': newMsgNotice}, method: NetMethod.POST); | |||
if (NetUtil.isSuccess(result) && !EmptyUtil.isEmpty(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA])) { | |||
return _dataModel; | |||
} | |||
} catch (e, s) { | |||
Logger.error(e, s); | |||
} | |||
try { | |||
/// 失败 | |||
_dataModel.data[key] = value ? '0' : '1'; | |||
} catch (e) {} | |||
return null; | |||
} | |||
/// 返回父页面传进来的数据 | |||
Future<MessageSettingsStyleModel> fetchParentStyleData(final Map<String, dynamic> data) async { | |||
try { | |||
if (!EmptyUtil.isEmpty(data) && !EmptyUtil.isEmpty(data['data'])) { | |||
if (data['data'] is String) { | |||
_styleModel = MessageSettingsStyleModel.fromJson(jsonDecode(data['data'])); | |||
return _styleModel; | |||
} | |||
if (data['data'] is Map) { | |||
_styleModel = MessageSettingsStyleModel.fromJson(data['data']); | |||
return _styleModel; | |||
} | |||
} | |||
} catch (e, s) { | |||
Logger.error(e, s); | |||
} | |||
return null; | |||
} | |||
/// 获取网络数据 | |||
Future<MessageSettingsStyleModel> fetchNetStyleData(final Map<String, dynamic> data) async { | |||
try { | |||
String skip_identifier = | |||
!EmptyUtil.isEmpty(data) && data.containsKey('skip_identifier') && !EmptyUtil.isEmpty(data['skip_identifier']) ? data['skip_identifier'] : 'pub.flutter.privacy_settings'; | |||
var result = await NetUtil.post('/api/v1/mod/$skip_identifier', method: NetMethod.GET, cache: true); | |||
if (NetUtil.isSuccess(result) && !EmptyUtil.isEmpty(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA])) { | |||
var modListData = result[GlobalConfig.HTTP_RESPONSE_KEY_DATA]['mod_list'][0]['data']; | |||
if (!EmptyUtil.isEmpty(modListData)) { | |||
_styleModel = MessageSettingsStyleModel.fromJson(jsonDecode(modListData)); | |||
return _styleModel; | |||
} | |||
} | |||
} catch (e, s) { | |||
Logger.error(e, s); | |||
} | |||
return null; | |||
} | |||
/// 获取缓存数据 | |||
Future<MessageSettingsStyleModel> fetchCacheStyleData(final Map<String, dynamic> data) async { | |||
try { | |||
String skip_identifier = | |||
!EmptyUtil.isEmpty(data) && data.containsKey('skip_identifier') && !EmptyUtil.isEmpty(data['skip_identifier']) ? data['skip_identifier'] : 'pub.flutter.privacy_settings'; | |||
var result = await NetUtil.getRequestCachedData('/api/v1/mod/$skip_identifier'); | |||
if (!EmptyUtil.isEmpty(result)) { | |||
var modListData = result['mod_list'][0]['data']; | |||
if (!EmptyUtil.isEmpty(modListData)) { | |||
_styleModel = MessageSettingsStyleModel.fromJson(jsonDecode(modListData)); | |||
return _styleModel; | |||
} | |||
} | |||
} catch (e, s) { | |||
Logger.error(e, s); | |||
} | |||
return null; | |||
} | |||
} |
@@ -0,0 +1,19 @@ | |||
import 'package:meta/meta.dart'; | |||
import 'package:zhiying_base_widget/pages/message_settings_page/model/message_settings_data_model.dart'; | |||
import 'package:zhiying_base_widget/pages/message_settings_page/model/message_settings_style_model.dart'; | |||
@immutable | |||
abstract class MessageSettingsState {} | |||
class MessageSettingsInitial extends MessageSettingsState {} | |||
class MessageSettingsLoadedState extends MessageSettingsState { | |||
MessageSettingsStyleModel styleModel; | |||
MessageSettingsDataModel dataModel; | |||
MessageSettingsLoadedState({this.styleModel, this.dataModel}); | |||
} | |||
class MessageSettingsUpdateErrorState extends MessageSettingsState {} | |||
class MessageSettingsErrorState extends MessageSettingsState {} |
@@ -0,0 +1,230 @@ | |||
import 'package:flutter/material.dart'; | |||
import 'package:flutter_bloc/flutter_bloc.dart'; | |||
import 'package:zhiying_base_widget/pages/message_settings_page/model/message_settings_data_model.dart'; | |||
import 'package:zhiying_base_widget/pages/message_settings_page/model/message_settings_style_model.dart'; | |||
import 'package:zhiying_comm/zhiying_comm.dart'; | |||
import 'bloc/message_settings_bloc.dart'; | |||
import 'bloc/message_settings_event.dart'; | |||
import 'bloc/message_settings_repository.dart'; | |||
import 'bloc/message_settings_state.dart'; | |||
/// | |||
/// 消息设置 | |||
/// | |||
class MessageSettingsPage extends StatelessWidget { | |||
final Map<String, dynamic> data; | |||
MessageSettingsPage(this.data); | |||
@override | |||
Widget build(BuildContext context) { | |||
return BlocProvider<MessageSettingsBloc>( | |||
create: (_) => MessageSettingsBloc(MessageSettingsRepository())..add(MessageSettingsInitEvent(data)), | |||
child: _MessageSettingsPageContainer(), | |||
); | |||
} | |||
} | |||
class _MessageSettingsPageContainer extends StatefulWidget { | |||
@override | |||
__MessageSettingsPageContainerState createState() => __MessageSettingsPageContainerState(); | |||
} | |||
class __MessageSettingsPageContainerState extends State<_MessageSettingsPageContainer> { | |||
/// 列表点击 | |||
void _onClickListItem(Settings model, MessageSettingsDataModel dataModel) { | |||
/// 跳转查看隐私协议 | |||
if (model.type == 'hid_url') { | |||
RouterUtil.openWebview(dataModel.data[model.dataKeys[0]], context); | |||
} | |||
} | |||
/// 隐私开关 | |||
void _switchOnChange(String key, bool value) { | |||
BlocProvider.of<MessageSettingsBloc>(context).add(MessageSettingsUpdateEvent(value: value, key: key)); | |||
} | |||
@override | |||
Widget build(BuildContext context) { | |||
return BlocConsumer<MessageSettingsBloc, MessageSettingsState>( | |||
listener: (context, state) {}, | |||
buildWhen: (prev, current) { | |||
if (current is MessageSettingsUpdateErrorState) { | |||
return false; | |||
} | |||
return true; | |||
}, | |||
builder: (context, state) { | |||
if (state is MessageSettingsLoadedState) { | |||
return _buildMainWidget(state?.styleModel, state.dataModel); | |||
} | |||
return _buildEmptyWidget(); | |||
}, | |||
); | |||
} | |||
/// 空数据 | |||
Widget _buildEmptyWidget() { | |||
return Scaffold( | |||
backgroundColor: HexColor.fromHex('#F9F9F9'), | |||
appBar: _buildAppBarWidget(null), | |||
body: Container(), | |||
); | |||
} | |||
/// 有数据 | |||
Widget _buildMainWidget(MessageSettingsStyleModel model, MessageSettingsDataModel dataModel) { | |||
return Scaffold( | |||
backgroundColor: HexColor.fromHex(model?.bgColor ?? '#F9F9F9'), | |||
appBar: _buildAppBarWidget(model), | |||
body: Column( | |||
children: <Widget>[ | |||
/// 隐私订单 | |||
Container( | |||
margin: const EdgeInsets.only(top: 5), | |||
padding: const EdgeInsets.symmetric(horizontal: 12.5), | |||
color: HexColor.fromHex(model?.settingsBgColor ?? '#FFFFFF'), | |||
child: _buildHeadWidge(model?.settings, dataModel), | |||
), | |||
/// 隐私协议 | |||
Container( | |||
margin: const EdgeInsets.only(top: 5), | |||
padding: const EdgeInsets.symmetric(horizontal: 12.5), | |||
color: HexColor.fromHex(model?.settingsBgColor ?? '#FFFFFF'), | |||
child: _buildListWidget(model?.otherSettings, dataModel), | |||
) | |||
], | |||
), | |||
); | |||
} | |||
/// 根据列表生成list集合 | |||
Widget _buildHeadWidge(List<Settings> model, MessageSettingsDataModel dataModel) { | |||
List<Widget> lists = []; | |||
int length = model?.length ?? 0; | |||
if (length == 0) { | |||
lists.add(Container()); | |||
} else { | |||
model.forEach((element) { | |||
lists.add(GestureDetector( | |||
onTap: () => _onClickListItem(element, dataModel), | |||
behavior: HitTestBehavior.opaque, | |||
child: Container( | |||
margin: const EdgeInsets.symmetric(vertical: 15), | |||
child: Row( | |||
mainAxisAlignment: MainAxisAlignment.spaceBetween, | |||
crossAxisAlignment: CrossAxisAlignment.center, | |||
children: <Widget>[ | |||
Column( | |||
crossAxisAlignment: CrossAxisAlignment.start, | |||
mainAxisAlignment: MainAxisAlignment.center, | |||
children: <Widget>[ | |||
Text( | |||
element?.name ?? '', | |||
style: TextStyle(color: HexColor.fromHex(element?.nameColor ?? '#333333'), fontSize: 13, fontWeight: FontWeight.bold), | |||
), | |||
Visibility( | |||
visible: !EmptyUtil.isEmpty(element?.subName), | |||
child: Text( | |||
element?.subName ?? '', | |||
style: TextStyle(color: HexColor.fromHex(element?.subNameColor ?? '#999999'), fontSize: 11), | |||
), | |||
) | |||
], | |||
), | |||
Container( | |||
width: 60, | |||
height: 15, | |||
child: Switch( | |||
value: dataModel.data[element.dataKeys[0]] == '1', | |||
activeColor: HexColor.fromHex('#FF4B4B'), | |||
// trackColor: HexColor.fromHex('#F9F9F9') , | |||
onChanged: (bool value) { | |||
_switchOnChange(element.dataKeys[0], value); | |||
}, | |||
), | |||
), | |||
], | |||
), | |||
), | |||
)); | |||
}); | |||
} | |||
return Column( | |||
children: lists, | |||
); | |||
} | |||
/// 根据列表根据列表生成List集合 | |||
Widget _buildListWidget(List<Settings> model, MessageSettingsDataModel dataModel) { | |||
List<Widget> lists = []; | |||
int length = model?.length ?? 0; | |||
if (length == 0) { | |||
lists.add(Container()); | |||
} else { | |||
model.forEach((element) { | |||
lists.add(GestureDetector( | |||
onTap: () => _onClickListItem(element, dataModel), | |||
behavior: HitTestBehavior.opaque, | |||
child: Container( | |||
margin: const EdgeInsets.symmetric(vertical: 15), | |||
child: Row( | |||
mainAxisAlignment: MainAxisAlignment.spaceBetween, | |||
children: <Widget>[ | |||
Text( | |||
element?.name ?? '', | |||
style: TextStyle(color: HexColor.fromHex(element?.nameColor ?? '#333333'), fontSize: 13, fontWeight: FontWeight.bold), | |||
), | |||
Row( | |||
children: <Widget>[ | |||
Text( | |||
element?.descText ?? '', | |||
style: TextStyle(color: HexColor.fromHex(element?.descColor ?? '#999999'), fontSize: 13), | |||
), | |||
const SizedBox(width: 7.5), | |||
Icon( | |||
Icons.arrow_forward_ios, | |||
color: HexColor.fromHex(element?.descColor ?? '#999999'), | |||
size: 14, | |||
), | |||
], | |||
) | |||
], | |||
), | |||
), | |||
)); | |||
}); | |||
} | |||
return Column( | |||
children: lists, | |||
); | |||
} | |||
/// appBar | |||
Widget _buildAppBarWidget(MessageSettingsStyleModel model) { | |||
return AppBar( | |||
backgroundColor: HexColor.fromHex(model?.appBarBgColor ?? '#FFFFFF'), | |||
brightness: Brightness.light, | |||
leading: IconButton( | |||
icon: Icon( | |||
Icons.arrow_back_ios, | |||
size: 22, | |||
color: HexColor.fromHex('#333333'), | |||
), | |||
onPressed: () => Navigator.maybePop(context), | |||
), | |||
title: Text( | |||
model?.appBarName ?? '隐私设置', | |||
style: TextStyle(color: HexColor.fromHex(model?.appBarNameColor ?? '#333333'), fontSize: 15, fontWeight: FontWeight.bold), | |||
), | |||
centerTitle: true, | |||
elevation: 0, | |||
); | |||
} | |||
} |
@@ -0,0 +1,4 @@ | |||
class MessageSettingsDataModel { | |||
Map<String, dynamic> data; | |||
} |
@@ -0,0 +1,94 @@ | |||
class MessageSettingsStyleModel { | |||
String appBarName; | |||
String appBarNameColor; | |||
String appBarBgColor; | |||
String bgColor; | |||
String settingsBgColor; | |||
String noSelectedColor; | |||
String selectedColor; | |||
List<Settings> settings; | |||
List<Settings> otherSettings; | |||
MessageSettingsStyleModel( | |||
{this.appBarName, this.appBarNameColor, this.appBarBgColor, this.bgColor, this.settingsBgColor, this.noSelectedColor, this.selectedColor, this.settings, this.otherSettings}); | |||
MessageSettingsStyleModel.fromJson(Map<String, dynamic> json) { | |||
appBarName = json['app_bar_name']; | |||
appBarNameColor = json['app_bar_name_color']; | |||
appBarBgColor = json['app_bar_bg_color']; | |||
bgColor = json['bg_color']; | |||
settingsBgColor = json['settings_bg_color']; | |||
noSelectedColor = json['no_selected_color']; | |||
selectedColor = json['selected_color']; | |||
if (json['settings'] != null) { | |||
settings = new List<Settings>(); | |||
json['settings'].forEach((v) { | |||
settings.add(new Settings.fromJson(v)); | |||
}); | |||
} | |||
if (json['other_settings'] != null) { | |||
otherSettings = new List<Settings>(); | |||
json['other_settings'].forEach((v) { | |||
otherSettings.add(new Settings.fromJson(v)); | |||
}); | |||
} | |||
} | |||
Map<String, dynamic> toJson() { | |||
final Map<String, dynamic> data = new Map<String, dynamic>(); | |||
data['app_bar_name'] = this.appBarName; | |||
data['app_bar_name_color'] = this.appBarNameColor; | |||
data['app_bar_bg_color'] = this.appBarBgColor; | |||
data['bg_color'] = this.bgColor; | |||
data['settings_bg_color'] = this.settingsBgColor; | |||
data['no_selected_color'] = this.noSelectedColor; | |||
data['selected_color'] = this.selectedColor; | |||
if (this.settings != null) { | |||
data['settings'] = this.settings.map((v) => v.toJson()).toList(); | |||
} | |||
if (this.otherSettings != null) { | |||
data['other_settings'] = this.otherSettings.map((v) => v.toJson()).toList(); | |||
} | |||
return data; | |||
} | |||
} | |||
class Settings { | |||
List<String> dataKeys; | |||
String type; | |||
String name; | |||
String subName; | |||
String nameColor; | |||
String subNameColor; | |||
String descText; | |||
String descColor; | |||
String skipIdentifier; | |||
Settings({this.dataKeys, this.type, this.name, this.subName, this.nameColor, this.subNameColor, this.descText, this.descColor, this.skipIdentifier}); | |||
Settings.fromJson(Map<String, dynamic> json) { | |||
dataKeys = json['data_keys'].cast<String>(); | |||
type = json['type']; | |||
name = json['name']; | |||
subName = json['sub_name']; | |||
nameColor = json['name_color']; | |||
subNameColor = json['sub_name_color']; | |||
descText = json['desc_text']; | |||
descColor = json['desc_color']; | |||
skipIdentifier = json['skip_identifier']; | |||
} | |||
Map<String, dynamic> toJson() { | |||
final Map<String, dynamic> data = new Map<String, dynamic>(); | |||
data['data_keys'] = this.dataKeys; | |||
data['type'] = this.type; | |||
data['name'] = this.name; | |||
data['sub_name'] = this.subName; | |||
data['name_color'] = this.nameColor; | |||
data['sub_name_color'] = this.subNameColor; | |||
data['desc_text'] = this.descText; | |||
data['desc_color'] = this.descColor; | |||
data['skip_identifier'] = this.skipIdentifier; | |||
return data; | |||
} | |||
} |
@@ -0,0 +1,66 @@ | |||
import 'dart:async'; | |||
import 'package:bloc/bloc.dart'; | |||
import 'package:zhiying_base_widget/pages/privacy_settings_page/bloc/privacy_settings_repository.dart'; | |||
import 'privacy_settings_event.dart'; | |||
import 'privacy_settings_state.dart'; | |||
import 'package:zhiying_comm/zhiying_comm.dart'; | |||
class PrivacySettingsBloc extends Bloc<PrivacySettingsEvent, PrivacySettingsState> { | |||
@override | |||
PrivacySettingsState get initialState => PrivacySettingsInitial(); | |||
PrivacySettingsRepository repository; | |||
PrivacySettingsBloc(this.repository); | |||
@override | |||
Stream<PrivacySettingsState> mapEventToState( | |||
PrivacySettingsEvent event, | |||
) async* { | |||
if (event is PrivacySettingsInitEvent) { | |||
yield* _mapInitEventToState(event); | |||
} | |||
if(event is PrivacySettingsUpdateEvent){ | |||
yield* _mapUpdateEventToState(event); | |||
} | |||
} | |||
/// 初始化 | |||
Stream<PrivacySettingsState> _mapInitEventToState(PrivacySettingsInitEvent event) async* { | |||
/// 1、父页面数据 | |||
var parentStyleData = await repository.fetchParentStyleData(event?.data); | |||
var result = await repository.fetchNetData(); | |||
if (!EmptyUtil.isEmpty(parentStyleData)) { | |||
yield PrivacySettingsLoadedState(model: parentStyleData, dataModel: result); | |||
return; | |||
} | |||
var cacheStyleData = await repository.fetchCacheStyleData(event?.data); | |||
if (!EmptyUtil.isEmpty(cacheStyleData)) { | |||
yield PrivacySettingsLoadedState(model: cacheStyleData, dataModel: result); | |||
} | |||
var netStyleData = await repository.fetchNetStyleData(event?.data); | |||
if (!EmptyUtil.isEmpty(netStyleData)) { | |||
yield PrivacySettingsLoadedState(model: netStyleData, dataModel: result); | |||
} else { | |||
yield PrivacySettingsErrorState(); | |||
} | |||
} | |||
/// 更新值 | |||
Stream<PrivacySettingsState> _mapUpdateEventToState(PrivacySettingsUpdateEvent event) async*{ | |||
var styleModel = repository.getStyleModel(); | |||
var dataModel = await repository.updateData(key: event.key, value: event.value); | |||
if(!EmptyUtil.isEmpty(styleModel) && !EmptyUtil.isEmpty(dataModel)){ | |||
yield PrivacySettingsLoadedState(dataModel: dataModel, model: styleModel); | |||
}else{ | |||
yield PrivacySettingsUpdateErrorState(); | |||
} | |||
} | |||
} |
@@ -0,0 +1,18 @@ | |||
import 'package:meta/meta.dart'; | |||
@immutable | |||
abstract class PrivacySettingsEvent {} | |||
/// 初始化数据 | |||
class PrivacySettingsInitEvent extends PrivacySettingsEvent { | |||
final Map<String, dynamic> data; | |||
PrivacySettingsInitEvent(this.data); | |||
} | |||
/// 更新数据 | |||
class PrivacySettingsUpdateEvent extends PrivacySettingsEvent { | |||
String key; | |||
bool value; | |||
PrivacySettingsUpdateEvent({this.value, this.key}); | |||
} |
@@ -0,0 +1,121 @@ | |||
import 'dart:convert'; | |||
import 'package:zhiying_base_widget/pages/privacy_settings_page/model/privacy_settings_data_model.dart'; | |||
import 'package:zhiying_base_widget/pages/privacy_settings_page/model/privacy_settings_model.dart'; | |||
import 'package:zhiying_comm/zhiying_comm.dart'; | |||
class PrivacySettingsRepository { | |||
// 样式 | |||
PrivacySettingsModel _styleModel; | |||
// 数据 | |||
PrivacySettingsDataModel _dataModel; | |||
/// 获取style | |||
PrivacySettingsModel getStyleModel() { | |||
return _styleModel; | |||
} | |||
/// 获取data | |||
Future<PrivacySettingsDataModel> fetchNetData() async { | |||
try { | |||
var result = await NetUtil.post('/api/v1/settings/privacy_settings', method: NetMethod.GET); | |||
if (NetUtil.isSuccess(result) && !EmptyUtil.isEmpty(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA])) { | |||
_dataModel = PrivacySettingsDataModel(); | |||
_dataModel.data = result[GlobalConfig.HTTP_RESPONSE_KEY_DATA]; | |||
return _dataModel; | |||
} | |||
} catch (e, s) { | |||
Logger.error(e, s); | |||
} | |||
return null; | |||
} | |||
/// 更新data | |||
Future<PrivacySettingsDataModel> updateData({String key, bool value}) async { | |||
try { | |||
/// 刷新 | |||
_dataModel.data[key] = value ? '1' : '0'; | |||
String hidOrder = _dataModel.data['hid_order']; | |||
String hidContact = _dataModel.data['hid_contact']; | |||
var result = await NetUtil.post('/api/v1/settings/privacy_settings', params: {'hid_order': hidOrder, 'hid_contact': hidContact}, method: NetMethod.POST); | |||
if (NetUtil.isSuccess(result) && !EmptyUtil.isEmpty(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA])) { | |||
// Map<String, dynamic> data = result[GlobalConfig.HTTP_RESPONSE_KEY_DATA]; | |||
// | |||
// data.forEach((key, value) { | |||
// _dataModel.data[key] = value; | |||
// }); | |||
return _dataModel; | |||
} | |||
} catch (e, s) { | |||
Logger.error(e, s); | |||
} | |||
try{ | |||
/// 失败 | |||
_dataModel.data[key] = value ? '0' : '1'; | |||
}catch(e){} | |||
return null; | |||
} | |||
/// 返回父页面传进来的数据 | |||
Future<PrivacySettingsModel> fetchParentStyleData(final Map<String, dynamic> data) async { | |||
try { | |||
if (!EmptyUtil.isEmpty(data) && !EmptyUtil.isEmpty(data['data'])) { | |||
if (data['data'] is String) { | |||
_styleModel = PrivacySettingsModel.fromJson(jsonDecode(data['data'])); | |||
return _styleModel; | |||
} | |||
if (data['data'] is Map) { | |||
_styleModel = PrivacySettingsModel.fromJson(data['data']); | |||
return _styleModel; | |||
} | |||
} | |||
} catch (e, s) { | |||
Logger.error(e, s); | |||
} | |||
return null; | |||
} | |||
/// 获取网络数据 | |||
Future<PrivacySettingsModel> fetchNetStyleData(final Map<String, dynamic> data) async { | |||
try { | |||
String skip_identifier = | |||
!EmptyUtil.isEmpty(data) && data.containsKey('skip_identifier') && !EmptyUtil.isEmpty(data['skip_identifier']) ? data['skip_identifier'] : 'pub.flutter.privacy_settings'; | |||
var result = await NetUtil.post('/api/v1/mod/$skip_identifier', method: NetMethod.GET, cache: true); | |||
if (NetUtil.isSuccess(result) && !EmptyUtil.isEmpty(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA])) { | |||
var modListData = result[GlobalConfig.HTTP_RESPONSE_KEY_DATA]['mod_list'][0]['data']; | |||
if (!EmptyUtil.isEmpty(modListData)) { | |||
_styleModel = PrivacySettingsModel.fromJson(jsonDecode(modListData)); | |||
return _styleModel; | |||
} | |||
} | |||
} catch (e, s) { | |||
Logger.error(e, s); | |||
} | |||
return null; | |||
} | |||
/// 获取缓存数据 | |||
Future<PrivacySettingsModel> fetchCacheStyleData(final Map<String, dynamic> data) async { | |||
try { | |||
String skip_identifier = | |||
!EmptyUtil.isEmpty(data) && data.containsKey('skip_identifier') && !EmptyUtil.isEmpty(data['skip_identifier']) ? data['skip_identifier'] : 'pub.flutter.privacy_settings'; | |||
var result = await NetUtil.getRequestCachedData('/api/v1/mod/$skip_identifier'); | |||
if (!EmptyUtil.isEmpty(result)) { | |||
var modListData = result['mod_list'][0]['data']; | |||
if (!EmptyUtil.isEmpty(modListData)) { | |||
_styleModel = PrivacySettingsModel.fromJson(jsonDecode(modListData)); | |||
return _styleModel; | |||
} | |||
} | |||
} catch (e, s) { | |||
Logger.error(e, s); | |||
} | |||
return null; | |||
} | |||
} |
@@ -0,0 +1,20 @@ | |||
import 'package:meta/meta.dart'; | |||
import 'package:zhiying_base_widget/pages/privacy_settings_page/model/privacy_settings_data_model.dart'; | |||
import 'package:zhiying_base_widget/pages/privacy_settings_page/model/privacy_settings_model.dart'; | |||
@immutable | |||
abstract class PrivacySettingsState {} | |||
class PrivacySettingsInitial extends PrivacySettingsState {} | |||
class PrivacySettingsLoadedState extends PrivacySettingsState { | |||
PrivacySettingsModel model; | |||
PrivacySettingsDataModel dataModel; | |||
PrivacySettingsLoadedState({this.model, this.dataModel}); | |||
} | |||
class PrivacySettingsErrorState extends PrivacySettingsState {} | |||
/// 更新失败 | |||
class PrivacySettingsUpdateErrorState extends PrivacySettingsState{} |
@@ -0,0 +1,3 @@ | |||
class PrivacySettingsDataModel { | |||
Map<String, dynamic> data; | |||
} |
@@ -0,0 +1,94 @@ | |||
class PrivacySettingsModel { | |||
String appBarName; | |||
String appBarNameColor; | |||
String appBarBgColor; | |||
String bgColor; | |||
String settingsBgColor; | |||
String noSelectedColor; | |||
String selectedColor; | |||
List<Settings> settings; | |||
List<Settings> otherSettings; | |||
PrivacySettingsModel( | |||
{this.appBarName, this.appBarNameColor, this.appBarBgColor, this.bgColor, this.settingsBgColor, this.noSelectedColor, this.selectedColor, this.settings, this.otherSettings}); | |||
PrivacySettingsModel.fromJson(Map<String, dynamic> json) { | |||
appBarName = json['app_bar_name']; | |||
appBarNameColor = json['app_bar_name_color']; | |||
appBarBgColor = json['app_bar_bg_color']; | |||
bgColor = json['bg_color']; | |||
settingsBgColor = json['settings_bg_color']; | |||
noSelectedColor = json['no_selected_color']; | |||
selectedColor = json['selected_color']; | |||
if (json['settings'] != null) { | |||
settings = new List<Settings>(); | |||
json['settings'].forEach((v) { | |||
settings.add(new Settings.fromJson(v)); | |||
}); | |||
} | |||
if (json['other_settings'] != null) { | |||
otherSettings = new List<Settings>(); | |||
json['other_settings'].forEach((v) { | |||
otherSettings.add(new Settings.fromJson(v)); | |||
}); | |||
} | |||
} | |||
Map<String, dynamic> toJson() { | |||
final Map<String, dynamic> data = new Map<String, dynamic>(); | |||
data['app_bar_name'] = this.appBarName; | |||
data['app_bar_name_color'] = this.appBarNameColor; | |||
data['app_bar_bg_color'] = this.appBarBgColor; | |||
data['bg_color'] = this.bgColor; | |||
data['settings_bg_color'] = this.settingsBgColor; | |||
data['no_selected_color'] = this.noSelectedColor; | |||
data['selected_color'] = this.selectedColor; | |||
if (this.settings != null) { | |||
data['settings'] = this.settings.map((v) => v.toJson()).toList(); | |||
} | |||
if (this.otherSettings != null) { | |||
data['other_settings'] = this.otherSettings.map((v) => v.toJson()).toList(); | |||
} | |||
return data; | |||
} | |||
} | |||
class Settings { | |||
List<String> dataKeys; | |||
String type; | |||
String name; | |||
String subName; | |||
String nameColor; | |||
String subNameColor; | |||
String descText; | |||
String descColor; | |||
String skipIdentifier; | |||
Settings({this.dataKeys, this.type, this.name, this.subName, this.nameColor, this.subNameColor, this.descText, this.descColor, this.skipIdentifier}); | |||
Settings.fromJson(Map<String, dynamic> json) { | |||
dataKeys = json['data_keys'].cast<String>(); | |||
type = json['type']; | |||
name = json['name']; | |||
subName = json['sub_name']; | |||
nameColor = json['name_color']; | |||
subNameColor = json['sub_name_color']; | |||
descText = json['desc_text']; | |||
descColor = json['desc_color']; | |||
skipIdentifier = json['skip_identifier']; | |||
} | |||
Map<String, dynamic> toJson() { | |||
final Map<String, dynamic> data = new Map<String, dynamic>(); | |||
data['data_keys'] = this.dataKeys; | |||
data['type'] = this.type; | |||
data['name'] = this.name; | |||
data['sub_name'] = this.subName; | |||
data['name_color'] = this.nameColor; | |||
data['sub_name_color'] = this.subNameColor; | |||
data['desc_text'] = this.descText; | |||
data['desc_color'] = this.descColor; | |||
data['skip_identifier'] = this.skipIdentifier; | |||
return data; | |||
} | |||
} |
@@ -0,0 +1,231 @@ | |||
import 'package:flutter/cupertino.dart'; | |||
import 'package:zhiying_base_widget/pages/privacy_settings_page/bloc/privacy_settings_bloc.dart'; | |||
import 'package:zhiying_base_widget/pages/privacy_settings_page/bloc/privacy_settings_repository.dart'; | |||
import 'package:zhiying_base_widget/pages/privacy_settings_page/model/privacy_settings_data_model.dart'; | |||
import 'package:zhiying_base_widget/pages/privacy_settings_page/model/privacy_settings_model.dart'; | |||
import 'package:zhiying_comm/zhiying_comm.dart'; | |||
import 'package:flutter/material.dart'; | |||
import 'package:flutter_bloc/flutter_bloc.dart'; | |||
import 'bloc/privacy_settings_bloc.dart'; | |||
import 'bloc/privacy_settings_event.dart'; | |||
import 'bloc/privacy_settings_state.dart'; | |||
/// | |||
/// 隐私设置 | |||
/// | |||
class PrivacySettingsPage extends StatelessWidget { | |||
final Map<String, dynamic> data; | |||
PrivacySettingsPage(this.data); | |||
@override | |||
Widget build(BuildContext context) { | |||
return BlocProvider<PrivacySettingsBloc>( | |||
create: (_) => PrivacySettingsBloc(PrivacySettingsRepository())..add(PrivacySettingsInitEvent(data)), | |||
child: _PrivacySettingsContainer(), | |||
); | |||
} | |||
} | |||
class _PrivacySettingsContainer extends StatefulWidget { | |||
@override | |||
_PrivacySettingsContainerState createState() => _PrivacySettingsContainerState(); | |||
} | |||
class _PrivacySettingsContainerState extends State<_PrivacySettingsContainer> { | |||
/// 列表点击 | |||
void _onClickListItem(Settings model, PrivacySettingsDataModel dataModel) { | |||
/// 跳转查看隐私协议 | |||
if (model.type == 'hid_url') { | |||
RouterUtil.openWebview(dataModel.data[model.dataKeys[0]], context); | |||
} | |||
} | |||
/// 隐私开关 | |||
void _switchOnChange(String key, bool value) { | |||
BlocProvider.of<PrivacySettingsBloc>(context).add(PrivacySettingsUpdateEvent(value: value, key: key)); | |||
} | |||
@override | |||
Widget build(BuildContext context) { | |||
return BlocConsumer<PrivacySettingsBloc, PrivacySettingsState>( | |||
listener: (context, state) {}, | |||
buildWhen: (prev, current) { | |||
if (current is PrivacySettingsUpdateErrorState) { | |||
return false; | |||
} | |||
return true; | |||
}, | |||
builder: (context, state) { | |||
if (state is PrivacySettingsLoadedState) { | |||
return _buildMainWidget(state?.model, state.dataModel); | |||
} | |||
return _buildEmptyWidget(); | |||
}, | |||
); | |||
} | |||
/// 空数据 | |||
Widget _buildEmptyWidget() { | |||
return Scaffold( | |||
backgroundColor: HexColor.fromHex('#F9F9F9'), | |||
appBar: _buildAppBarWidget(null), | |||
body: Container(), | |||
); | |||
} | |||
/// 有数据 | |||
Widget _buildMainWidget(PrivacySettingsModel model, PrivacySettingsDataModel dataModel) { | |||
return Scaffold( | |||
backgroundColor: HexColor.fromHex(model?.bgColor ?? '#F9F9F9'), | |||
appBar: _buildAppBarWidget(model), | |||
body: Column( | |||
children: <Widget>[ | |||
/// 隐私订单 | |||
Container( | |||
margin: const EdgeInsets.only(top: 5), | |||
padding: const EdgeInsets.symmetric(horizontal: 12.5), | |||
color: HexColor.fromHex(model?.settingsBgColor ?? '#FFFFFF'), | |||
child: _buildHeadWidge(model?.settings, dataModel), | |||
), | |||
/// 隐私协议 | |||
Container( | |||
margin: const EdgeInsets.only(top: 5), | |||
padding: const EdgeInsets.symmetric(horizontal: 12.5), | |||
color: HexColor.fromHex(model?.settingsBgColor ?? '#FFFFFF'), | |||
child: _buildListWidget(model?.otherSettings, dataModel), | |||
) | |||
], | |||
), | |||
); | |||
} | |||
/// 根据列表生成list集合 | |||
Widget _buildHeadWidge(List<Settings> model, PrivacySettingsDataModel dataModel) { | |||
List<Widget> lists = []; | |||
int length = model?.length ?? 0; | |||
if (length == 0) { | |||
lists.add(Container()); | |||
} else { | |||
model.forEach((element) { | |||
lists.add(GestureDetector( | |||
onTap: () => _onClickListItem(element, dataModel), | |||
behavior: HitTestBehavior.opaque, | |||
child: Container( | |||
margin: const EdgeInsets.symmetric(vertical: 15), | |||
child: Row( | |||
mainAxisAlignment: MainAxisAlignment.spaceBetween, | |||
crossAxisAlignment: CrossAxisAlignment.center, | |||
children: <Widget>[ | |||
Column( | |||
crossAxisAlignment: CrossAxisAlignment.start, | |||
mainAxisAlignment: MainAxisAlignment.center, | |||
children: <Widget>[ | |||
Text( | |||
element?.name ?? '', | |||
style: TextStyle(color: HexColor.fromHex(element?.nameColor ?? '#333333'), fontSize: 13, fontWeight: FontWeight.bold), | |||
), | |||
Visibility( | |||
visible: !EmptyUtil.isEmpty(element?.subName), | |||
child: Text( | |||
element?.subName ?? '', | |||
style: TextStyle(color: HexColor.fromHex(element?.subNameColor ?? '#999999'), fontSize: 11), | |||
), | |||
) | |||
], | |||
), | |||
Container( | |||
width: 60, | |||
height: 15, | |||
child: Switch( | |||
value: dataModel.data[element.dataKeys[0]] == '1', | |||
activeColor: HexColor.fromHex('#FF4B4B'), | |||
// trackColor: HexColor.fromHex('#F9F9F9') , | |||
onChanged: (bool value) { | |||
_switchOnChange(element.dataKeys[0], value); | |||
}, | |||
), | |||
), | |||
], | |||
), | |||
), | |||
)); | |||
}); | |||
} | |||
return Column( | |||
children: lists, | |||
); | |||
} | |||
/// 根据列表根据列表生成List集合 | |||
Widget _buildListWidget(List<Settings> model, PrivacySettingsDataModel dataModel) { | |||
List<Widget> lists = []; | |||
int length = model?.length ?? 0; | |||
if (length == 0) { | |||
lists.add(Container()); | |||
} else { | |||
model.forEach((element) { | |||
lists.add(GestureDetector( | |||
onTap: () => _onClickListItem(element, dataModel), | |||
behavior: HitTestBehavior.opaque, | |||
child: Container( | |||
margin: const EdgeInsets.symmetric(vertical: 15), | |||
child: Row( | |||
mainAxisAlignment: MainAxisAlignment.spaceBetween, | |||
children: <Widget>[ | |||
Text( | |||
element?.name ?? '', | |||
style: TextStyle(color: HexColor.fromHex(element?.nameColor ?? '#333333'), fontSize: 13, fontWeight: FontWeight.bold), | |||
), | |||
Row( | |||
children: <Widget>[ | |||
Text( | |||
element?.descText ?? '', | |||
style: TextStyle(color: HexColor.fromHex(element?.descColor ?? '#999999'), fontSize: 13), | |||
), | |||
const SizedBox(width: 7.5), | |||
Icon( | |||
Icons.arrow_forward_ios, | |||
color: HexColor.fromHex(element?.descColor ?? '#999999'), | |||
size: 14, | |||
), | |||
], | |||
) | |||
], | |||
), | |||
), | |||
)); | |||
}); | |||
} | |||
return Column( | |||
children: lists, | |||
); | |||
} | |||
/// appBar | |||
Widget _buildAppBarWidget(PrivacySettingsModel model) { | |||
return AppBar( | |||
backgroundColor: HexColor.fromHex(model?.appBarBgColor ?? '#FFFFFF'), | |||
brightness: Brightness.light, | |||
leading: IconButton( | |||
icon: Icon( | |||
Icons.arrow_back_ios, | |||
size: 22, | |||
color: HexColor.fromHex('#333333'), | |||
), | |||
onPressed: () => Navigator.maybePop(context), | |||
), | |||
title: Text( | |||
model?.appBarName ?? '隐私设置', | |||
style: TextStyle(color: HexColor.fromHex(model?.appBarNameColor ?? '#333333'), fontSize: 15, fontWeight: FontWeight.bold), | |||
), | |||
centerTitle: true, | |||
elevation: 0, | |||
); | |||
} | |||
} |
@@ -0,0 +1,50 @@ | |||
import 'dart:async'; | |||
import 'package:bloc/bloc.dart'; | |||
import 'package:meta/meta.dart'; | |||
import 'package:zhiying_base_widget/pages/vip_center_page/bloc/vip_center_repository.dart'; | |||
import 'package:zhiying_base_widget/pages/vip_center_page/model/vip_center_data_model.dart'; | |||
import 'package:zhiying_base_widget/pages/vip_center_page/model/vip_center_style_model.dart'; | |||
import 'package:zhiying_comm/zhiying_comm.dart'; | |||
part 'vip_center_event.dart'; | |||
part 'vip_center_state.dart'; | |||
class VipCenterBloc extends Bloc<VipCenterEvent, VipCenterState> { | |||
// VipCenterBloc() : super(VipCenterInitial()); | |||
@override | |||
VipCenterState get initialState => VipCenterInitial(); | |||
VipCenterRepository repository; | |||
VipCenterBloc(this.repository); | |||
@override | |||
Stream<VipCenterState> mapEventToState( | |||
VipCenterEvent event, | |||
) async* { | |||
/// 初始化数据 | |||
if (event is VipCenterInitEvent) { | |||
yield* _mapInitEventToState(event); | |||
} | |||
} | |||
/// 初始化数据 | |||
Stream<VipCenterState> _mapInitEventToState(VipCenterInitEvent event) async* { | |||
var cacheStyle = await repository.fetchCachedStyle(); | |||
if (!EmptyUtil.isEmpty(cacheStyle)) { | |||
yield VipCenterLoadedState(dataModel: null, styleMode: cacheStyle); | |||
} | |||
var netStyle = await repository.fetchNetStyle(); | |||
if (!EmptyUtil.isEmpty(netStyle)) { | |||
yield VipCenterLoadedState(dataModel: null, styleMode: netStyle); | |||
} | |||
var result = await repository.fetchNetData(); | |||
if (!EmptyUtil.isEmpty(result) && (!EmptyUtil.isEmpty(cacheStyle) || !EmptyUtil.isEmpty(netStyle))) { | |||
yield VipCenterLoadedState(dataModel: result, styleMode: !EmptyUtil.isEmpty(netStyle) ? netStyle : cacheStyle); | |||
}else{ | |||
yield VipCenterErrorState(); | |||
} | |||
} | |||
} |
@@ -0,0 +1,9 @@ | |||
part of 'vip_center_bloc.dart'; | |||
@immutable | |||
abstract class VipCenterEvent {} | |||
/// 初始化数据 | |||
class VipCenterInitEvent extends VipCenterEvent{} | |||
@@ -0,0 +1,52 @@ | |||
import 'dart:convert'; | |||
import 'package:zhiying_base_widget/pages/vip_center_page/model/vip_center_data_model.dart'; | |||
import 'package:zhiying_base_widget/pages/vip_center_page/model/vip_center_style_model.dart'; | |||
import 'package:zhiying_comm/zhiying_comm.dart'; | |||
class VipCenterRepository { | |||
VipCenterStyleModel _styleModel; | |||
VipCenterDataModel _dataModel; | |||
/// 加载缓存Style数据 | |||
Future<dynamic> fetchCachedStyle() async { | |||
try { | |||
var result = await NetUtil.getRequestCachedData('/api/v1/mod/pub.flutter.vip_center'); | |||
if (!EmptyUtil.isEmpty(result)) { | |||
var modListData = result['mod_list'][0]['data']; | |||
if (!EmptyUtil.isEmpty(modListData)) { | |||
_styleModel = VipCenterStyleModel.fromJson(jsonDecode(modListData)); | |||
return _styleModel; | |||
} | |||
} | |||
} catch (e, s) { | |||
Logger.error(e, s); | |||
} | |||
return null; | |||
} | |||
/// 加载网络Style数据 | |||
Future<dynamic> fetchNetStyle() async { | |||
try { | |||
var result = await NetUtil.post('/api/v1/mod/pub.flutter.vip_center', method: NetMethod.GET, cache: true); | |||
if (NetUtil.isSuccess(result) && !EmptyUtil.isEmpty(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA])) { | |||
var modListData = result[GlobalConfig.HTTP_RESPONSE_KEY_DATA]['mod_list'][0]['data']; | |||
if (!EmptyUtil.isEmpty(modListData)) { | |||
_styleModel = VipCenterStyleModel.fromJson(jsonDecode(modListData)); | |||
return _styleModel; | |||
} | |||
} | |||
} catch (e, s) { | |||
Logger.error(e, s); | |||
} | |||
return null; | |||
} | |||
/// 加载网络Data数据 | |||
Future<dynamic> fetchNetData() async { | |||
try {} catch (e, s) { | |||
Logger.error(e, s); | |||
} | |||
return null; | |||
} | |||
} |
@@ -0,0 +1,21 @@ | |||
part of 'vip_center_bloc.dart'; | |||
@immutable | |||
abstract class VipCenterState {} | |||
class VipCenterInitial extends VipCenterState {} | |||
/// 数据加载完毕 | |||
class VipCenterLoadedState extends VipCenterState{ | |||
VipCenterStyleModel styleMode; | |||
VipCenterDataModel dataModel; | |||
VipCenterLoadedState({this.styleMode, this.dataModel}); | |||
} | |||
/// 初始化出错 | |||
class VipCenterInitErrorState extends VipCenterState{} | |||
/// 数据加载失败 | |||
class VipCenterErrorState extends VipCenterState{} |
@@ -0,0 +1,2 @@ | |||
class VipCenterDataModel{} |
@@ -0,0 +1,211 @@ | |||
class VipCenterStyleModel { | |||
String appBarName; | |||
String appBarNameColor; | |||
String appBarBgImg; | |||
String appBarBgColor; | |||
String appBarLeftBackupIcon; | |||
String appBarRightShareIcon; | |||
String bgColor; | |||
String bgImg; | |||
String avatarLvIcon; | |||
String avatarLvTextColor; | |||
String avatarUsernameColor; | |||
String entitlementsUpIcon; | |||
List<Entitlements> entitlements; | |||
MustToDoTaskListStyle mustToDoTaskListStyle; | |||
SelectedToDoTaskListStyle selectedToDoTaskListStyle; | |||
BottomBtn bottomBtn; | |||
VipCenterStyleModel({ | |||
this.appBarName, | |||
this.appBarNameColor, | |||
this.appBarBgImg, | |||
this.appBarBgColor, | |||
this.appBarLeftBackupIcon, | |||
this.appBarRightShareIcon, | |||
this.bgColor, | |||
this.bgImg, | |||
this.avatarLvIcon, | |||
this.avatarLvTextColor, | |||
this.avatarUsernameColor, | |||
this.entitlementsUpIcon, | |||
this.entitlements, | |||
this.mustToDoTaskListStyle, | |||
this.selectedToDoTaskListStyle, | |||
this.bottomBtn, | |||
}); | |||
VipCenterStyleModel.fromJson(Map<String, dynamic> json) { | |||
appBarName = json['app_bar_name']; | |||
appBarNameColor = json['app_bar_name_color']; | |||
appBarBgImg = json['app_bar_bg_img']; | |||
appBarBgColor = json['app_bar_bg_color']; | |||
appBarLeftBackupIcon = json['app_bar_left_backup_icon']; | |||
appBarRightShareIcon = json['app_bar_right_share_icon']; | |||
bgColor = json['bg_color']; | |||
bgImg = json['bg_img']; | |||
avatarLvIcon = json['avatar_lv_icon']; | |||
avatarLvTextColor = json['avatar_lv_text_color']; | |||
avatarUsernameColor = json['avatar_username_color']; | |||
entitlementsUpIcon = json['entitlements_up_icon']; | |||
if (json['entitlements'] != null) { | |||
entitlements = new List<Entitlements>(); | |||
json['entitlements'].forEach((v) { | |||
entitlements.add(new Entitlements.fromJson(v)); | |||
}); | |||
} | |||
mustToDoTaskListStyle = json['must_to_do_task_list_style'] != null ? new MustToDoTaskListStyle.fromJson(json['must_to_do_task_list_style']) : null; | |||
selectedToDoTaskListStyle = json['selected_to_do_task_list_style'] != null ? new SelectedToDoTaskListStyle.fromJson(json['selected_to_do_task_list_style']) : null; | |||
bottomBtn = json['bottom_btn'] != null ? new BottomBtn.fromJson(json['bottom_btn']) : null; | |||
} | |||
Map<String, dynamic> toJson() { | |||
final Map<String, dynamic> data = new Map<String, dynamic>(); | |||
data['app_bar_name'] = this.appBarName; | |||
data['app_bar_name_color'] = this.appBarNameColor; | |||
data['app_bar_bg_img'] = this.appBarBgImg; | |||
data['app_bar_bg_color'] = this.appBarBgColor; | |||
data['app_bar_left_backup_icon'] = this.appBarLeftBackupIcon; | |||
data['app_bar_right_share_icon'] = this.appBarRightShareIcon; | |||
data['bg_color'] = this.bgColor; | |||
data['bg_img'] = this.bgImg; | |||
data['avatar_lv_icon'] = this.avatarLvIcon; | |||
data['avatar_lv_text_color'] = this.avatarLvTextColor; | |||
data['avatar_username_color'] = this.avatarUsernameColor; | |||
data['entitlements_up_icon'] = this.entitlementsUpIcon; | |||
if (this.entitlements != null) { | |||
data['entitlements'] = this.entitlements.map((v) => v.toJson()).toList(); | |||
} | |||
if (this.mustToDoTaskListStyle != null) { | |||
data['must_to_do_task_list_style'] = this.mustToDoTaskListStyle.toJson(); | |||
} | |||
if (this.selectedToDoTaskListStyle != null) { | |||
data['selected_to_do_task_list_style'] = this.selectedToDoTaskListStyle.toJson(); | |||
} | |||
if (this.bottomBtn != null) { | |||
data['bottom_btn'] = this.bottomBtn.toJson(); | |||
} | |||
return data; | |||
} | |||
} | |||
class Entitlements { | |||
String type; | |||
String name; | |||
String nameColor; | |||
String icon; | |||
String requiredLogin; | |||
String requiredTaobaoAuth; | |||
String skipIdentifier; | |||
Entitlements({this.type, this.name, this.nameColor, this.icon, this.requiredLogin, this.requiredTaobaoAuth, this.skipIdentifier}); | |||
Entitlements.fromJson(Map<String, dynamic> json) { | |||
type = json['type']; | |||
name = json['name']; | |||
nameColor = json['name_color']; | |||
icon = json['icon']; | |||
requiredLogin = json['required_login']; | |||
requiredTaobaoAuth = json['required_taobao_auth']; | |||
skipIdentifier = json['skip_identifier']; | |||
} | |||
Map<String, dynamic> toJson() { | |||
final Map<String, dynamic> data = new Map<String, dynamic>(); | |||
data['type'] = this.type; | |||
data['name'] = this.name; | |||
data['name_color'] = this.nameColor; | |||
data['icon'] = this.icon; | |||
data['required_login'] = this.requiredLogin; | |||
data['required_taobao_auth'] = this.requiredTaobaoAuth; | |||
data['skip_identifier'] = this.skipIdentifier; | |||
return data; | |||
} | |||
} | |||
class MustToDoTaskListStyle { | |||
String name; | |||
String icon; | |||
String progressBgColor; | |||
String progressColor; | |||
String btnColor; | |||
String btnImg; | |||
String btnNameColor; | |||
MustToDoTaskListStyle({this.name, this.icon, this.progressBgColor, this.progressColor, this.btnColor, this.btnImg, this.btnNameColor}); | |||
MustToDoTaskListStyle.fromJson(Map<String, dynamic> json) { | |||
name = json['name']; | |||
icon = json['icon']; | |||
progressBgColor = json['progress_bg_color']; | |||
progressColor = json['progress_color']; | |||
btnColor = json['btn_color']; | |||
btnImg = json['btn_img']; | |||
btnNameColor = json['btn_name_color']; | |||
} | |||
Map<String, dynamic> toJson() { | |||
final Map<String, dynamic> data = new Map<String, dynamic>(); | |||
data['name'] = this.name; | |||
data['icon'] = this.icon; | |||
data['progress_bg_color'] = this.progressBgColor; | |||
data['progress_color'] = this.progressColor; | |||
data['btn_color'] = this.btnColor; | |||
data['btn_img'] = this.btnImg; | |||
data['btn_name_color'] = this.btnNameColor; | |||
return data; | |||
} | |||
} | |||
class SelectedToDoTaskListStyle { | |||
String name; | |||
String icon; | |||
String progressBgColor; | |||
String progressColor; | |||
String btnColor; | |||
String btnImg; | |||
SelectedToDoTaskListStyle({this.name, this.icon, this.progressBgColor, this.progressColor, this.btnColor, this.btnImg}); | |||
SelectedToDoTaskListStyle.fromJson(Map<String, dynamic> json) { | |||
name = json['name']; | |||
icon = json['icon']; | |||
progressBgColor = json['progress_bg_color']; | |||
progressColor = json['progress_color']; | |||
btnColor = json['btn_color']; | |||
btnImg = json['btn_img']; | |||
} | |||
Map<String, dynamic> toJson() { | |||
final Map<String, dynamic> data = new Map<String, dynamic>(); | |||
data['name'] = this.name; | |||
data['icon'] = this.icon; | |||
data['progress_bg_color'] = this.progressBgColor; | |||
data['progress_color'] = this.progressColor; | |||
data['btn_color'] = this.btnColor; | |||
data['btn_img'] = this.btnImg; | |||
return data; | |||
} | |||
} | |||
class BottomBtn { | |||
String icon; | |||
String name; | |||
String img; | |||
BottomBtn({this.icon, this.name, this.img}); | |||
BottomBtn.fromJson(Map<String, dynamic> json) { | |||
icon = json['icon']; | |||
name = json['name']; | |||
img = json['img']; | |||
} | |||
Map<String, dynamic> toJson() { | |||
final Map<String, dynamic> data = new Map<String, dynamic>(); | |||
data['icon'] = this.icon; | |||
data['name'] = this.name; | |||
data['img'] = this.img; | |||
return data; | |||
} | |||
} |
@@ -0,0 +1,428 @@ | |||
import 'package:flutter/cupertino.dart'; | |||
import 'package:flutter/material.dart'; | |||
import 'package:flutter_swiper/flutter_swiper.dart'; | |||
import 'package:zhiying_base_widget/pages/vip_center_page/bloc/vip_center_bloc.dart'; | |||
import 'package:zhiying_base_widget/pages/vip_center_page/bloc/vip_center_repository.dart'; | |||
import 'package:zhiying_base_widget/pages/vip_center_page/model/vip_center_style_model.dart'; | |||
import 'package:zhiying_base_widget/pages/vip_center_page/vip_center_tip_dialog_widget.dart'; | |||
import 'package:zhiying_base_widget/pages/vip_center_page/vip_center_upgrade_dialog_page.dart'; | |||
import 'package:zhiying_comm/zhiying_comm.dart'; | |||
import 'dart:ui'; | |||
import 'package:flutter_bloc/flutter_bloc.dart'; | |||
/// | |||
/// 会员中心 | |||
/// | |||
class VipCenterPage extends StatelessWidget { | |||
final Map<String, dynamic> data; | |||
VipCenterPage(this.data); | |||
@override | |||
Widget build(BuildContext context) { | |||
return BlocProvider<VipCenterBloc>( | |||
create: (_) => VipCenterBloc(VipCenterRepository())..add(VipCenterInitEvent()), | |||
child: _VipCenterPageContainer(), | |||
); | |||
} | |||
} | |||
class _VipCenterPageContainer extends StatefulWidget { | |||
@override | |||
__VipCenterPageContainerState createState() => __VipCenterPageContainerState(); | |||
} | |||
class __VipCenterPageContainerState extends State<_VipCenterPageContainer> { | |||
/// 分享 | |||
void _onShareClick() {} | |||
/// 点击子item任务 | |||
void _onClickItemTask() { | |||
// showDialog(context: context, child: VipCenterTipDialog()); | |||
showModalBottomSheet( | |||
backgroundColor: Colors.transparent, | |||
isScrollControlled: true, | |||
context: context, | |||
builder: (context) { | |||
return VipCenterUpgradeDialogPage(); | |||
}); | |||
} | |||
@override | |||
Widget build(BuildContext context) { | |||
return BlocConsumer<VipCenterBloc, VipCenterState>( | |||
listener: (context, state) {}, | |||
buildWhen: (prov, current) { | |||
if (current is VipCenterErrorState) { | |||
return false; | |||
} | |||
return true; | |||
}, | |||
builder: (context, state) { | |||
/// 数据加载成功 | |||
if (state is VipCenterLoadedState) { | |||
return _buildMainWidget(state?.styleMode); | |||
} | |||
/// 初始化出错 | |||
if (state is VipCenterInitErrorState) {} | |||
/// 加载骨架图 | |||
return Container(); | |||
}, | |||
); | |||
} | |||
/// 主视图 | |||
Widget _buildMainWidget(VipCenterStyleModel styleModel) { | |||
return MediaQuery.removePadding( | |||
context: context, | |||
removeBottom: true, | |||
child: Container( | |||
color: HexColor.fromHex(styleModel?.bgColor ?? '#F9F9F9'), | |||
child: Stack( | |||
children: <Widget>[ | |||
/// 背景图 | |||
Align( | |||
alignment: Alignment.topCenter, | |||
child: Container( | |||
width: double.infinity, | |||
height: 244 + MediaQueryData.fromWindow(window).padding.top, | |||
// color: HexColor.fromHex('#2A2A2A'), | |||
child: CachedNetworkImage( | |||
imageUrl: styleModel?.bgImg ?? '', | |||
fit: BoxFit.cover, | |||
), | |||
)), | |||
/// 内容 | |||
Scaffold( | |||
backgroundColor: Colors.transparent, | |||
appBar: _buildAppBarWidget(styleModel), | |||
body: ListView( | |||
children: <Widget>[ | |||
const SizedBox(height: 20), | |||
/// 会员中心 | |||
_buildVipInifoWidget(styleModel), | |||
const SizedBox(height: 30), | |||
/// 会员卡片 | |||
_buildVipCardWidget(), | |||
// const SizedBox(height: 12), | |||
/// 快速导航 | |||
_buildQuickWidget(), | |||
/// 任务 | |||
_buildTaskWidget(), | |||
], | |||
), | |||
), | |||
/// 升级按钮 | |||
Align(alignment: Alignment.bottomCenter, child: _buildUpgradeButtonWidget(styleModel)), | |||
], | |||
), | |||
), | |||
); | |||
} | |||
/// 头部Widget | |||
Widget _buildHeadWidget() { | |||
return Container( | |||
child: Stack( | |||
children: <Widget>[], | |||
), | |||
); | |||
} | |||
int _indexSelect = 0; | |||
/// 会员卡片 | |||
Widget _buildVipCardWidget() { | |||
return Container( | |||
width: double.infinity, | |||
height: 123, | |||
// color: HexColor.fromHex('#eeF0D199'), | |||
child: Swiper( | |||
itemCount: 4, | |||
itemBuilder: (context, index) { | |||
return Container( | |||
height: double.infinity, | |||
width: double.infinity, | |||
color: HexColor.fromHex('#eeF0D199'), | |||
); | |||
}, | |||
onIndexChanged: (index) => _indexSelect = index, | |||
scale: 0.85, | |||
viewportFraction: 0.81, | |||
loop: false, | |||
onTap: (index) => _onClickItemTask(), | |||
), | |||
); | |||
} | |||
/// 快速导航 | |||
Widget _buildQuickWidget() { | |||
return Container( | |||
margin: const EdgeInsets.only(left: 12.5, right: 12.5, top: 12), | |||
padding: const EdgeInsets.only(top: 12), | |||
width: double.infinity, | |||
decoration: BoxDecoration( | |||
color: HexColor.fromHex('#FFFFFF'), | |||
// borderRadius: BorderRadius.only(bottomLeft: Radius.circular(10), bottomRight: Radius.circular(10)) | |||
borderRadius: BorderRadius.circular(10)), | |||
child: GridView.builder( | |||
shrinkWrap: true, | |||
physics: NeverScrollableScrollPhysics(), | |||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( | |||
crossAxisCount: 4, | |||
), | |||
itemBuilder: (context, index) { | |||
return _QuickItemWidget(); | |||
}, | |||
itemCount: 12, | |||
), | |||
); | |||
} | |||
/// 任务视图 | |||
Widget _buildTaskWidget() { | |||
return Container( | |||
margin: const EdgeInsets.only(left: 12.5, right: 12.5, top: 10), | |||
padding: const EdgeInsets.only(left: 15.5, right: 13.5, top: 15, bottom: 100), | |||
decoration: BoxDecoration( | |||
color: HexColor.fromHex('#FFFFFF'), | |||
borderRadius: BorderRadius.only(topLeft: Radius.circular(10), topRight: Radius.circular(10)), | |||
), | |||
child: Column( | |||
children: <Widget>[ | |||
_TaskItemWidget(), | |||
_TaskItemWidget(), | |||
], | |||
), | |||
); | |||
} | |||
/// 会员信息 | |||
Widget _buildVipInifoWidget(VipCenterStyleModel styleModel) { | |||
return Column( | |||
children: <Widget>[ | |||
/// 会员头像 | |||
Container( | |||
width: 45, | |||
height: 45, | |||
// color: Colors.red, | |||
child: Stack( | |||
children: <Widget>[ | |||
Center( | |||
child: Container(height: double.infinity, width: double.infinity, decoration: BoxDecoration( | |||
borderRadius: BorderRadius.circular(45/2) | |||
),), | |||
), | |||
Align( | |||
alignment: Alignment.bottomRight, | |||
child: Transform.translate( | |||
offset: Offset(36/2, 18/2), | |||
child: CachedNetworkImage(imageUrl: styleModel?.avatarLvIcon, width: 36,)), | |||
), | |||
], | |||
), | |||
), | |||
const SizedBox(height: 13), | |||
/// 会员昵称 | |||
Text('我不猜', style: TextStyle(color: HexColor.fromHex(styleModel?.avatarUsernameColor ?? '#FFFFFF'), fontSize: 16)), | |||
], | |||
); | |||
} | |||
/// 升级按钮 | |||
Widget _buildUpgradeButtonWidget(VipCenterStyleModel styleModel) { | |||
return Container( | |||
height: 50, | |||
margin: const EdgeInsets.only(left: 15.5 + 12.5, right: 15.5 + 12.5, bottom: 24), | |||
decoration: BoxDecoration( | |||
borderRadius: BorderRadius.circular(50 / 2), | |||
image: DecorationImage( | |||
fit: BoxFit.fitWidth, | |||
image: CachedNetworkImageProvider( | |||
styleModel?.bottomBtn?.img ?? '', | |||
))), | |||
child: Row( | |||
mainAxisAlignment: MainAxisAlignment.center, | |||
crossAxisAlignment: CrossAxisAlignment.center, | |||
children: <Widget>[ | |||
/// vip 图标 | |||
CachedNetworkImage( | |||
imageUrl: styleModel?.bottomBtn?.icon, | |||
width: 18, | |||
), | |||
const SizedBox(width: 18), | |||
Text( | |||
styleModel?.bottomBtn?.name ?? '', | |||
style: TextStyle(color: HexColor.fromHex('#303030'), fontSize: 18, fontWeight: FontWeight.bold, decoration: TextDecoration.none), | |||
) | |||
], | |||
), | |||
); | |||
} | |||
/// appBar | |||
Widget _buildAppBarWidget(VipCenterStyleModel styleModel) { | |||
return AppBar( | |||
backgroundColor: Colors.transparent, | |||
leading: IconButton( | |||
icon: Icon( | |||
Icons.arrow_back_ios, | |||
size: 22, | |||
color: HexColor.fromHex('#FFFFFF'), | |||
), | |||
onPressed: () => Navigator.maybePop(context), | |||
), | |||
centerTitle: true, | |||
elevation: 0, | |||
title: Text(styleModel?.appBarName ?? '会员中心', style: TextStyle(fontSize: 18, color: HexColor.fromHex(styleModel?.appBarNameColor ?? '#FFFFFF'))), | |||
actions: <Widget>[ | |||
GestureDetector( | |||
onTap: () => _onShareClick(), | |||
behavior: HitTestBehavior.opaque, | |||
child: Center( | |||
child: Container( | |||
margin: const EdgeInsets.only(right: 12.5), | |||
width: 20, | |||
height: 20, | |||
child: CachedNetworkImage( | |||
imageUrl: styleModel?.appBarRightShareIcon ?? '', | |||
), | |||
), | |||
), | |||
) | |||
], | |||
); | |||
} | |||
} | |||
class _QuickItemWidget extends StatelessWidget { | |||
@override | |||
Widget build(BuildContext context) { | |||
return Column( | |||
children: <Widget>[ | |||
Container( | |||
width: 41, | |||
height: 40, | |||
color: Colors.yellowAccent, | |||
child: Stack( | |||
children: <Widget>[ | |||
/// icon | |||
Align( | |||
alignment: Alignment.topRight, | |||
child: Container( | |||
width: 11, | |||
height: 11, | |||
color: Colors.red, | |||
), | |||
) | |||
], | |||
), | |||
), | |||
const SizedBox(height: 5), | |||
Text( | |||
'自购分佣', | |||
style: TextStyle(color: HexColor.fromHex('#999990'), fontSize: 12), | |||
) | |||
], | |||
); | |||
} | |||
} | |||
class _TaskItemWidget extends StatelessWidget { | |||
@override | |||
Widget build(BuildContext context) { | |||
return Column( | |||
children: <Widget>[ | |||
/// title | |||
_buildTitleWidget(), | |||
const SizedBox(height: 15), | |||
/// data | |||
Column( | |||
children: <Widget>[ | |||
_buildDataWidget(), | |||
const SizedBox(height: 15.5), | |||
_buildDataWidget(), | |||
const SizedBox(height: 15.5), | |||
_buildDataWidget(), | |||
const SizedBox(height: 15.5), | |||
], | |||
), | |||
const SizedBox(height: 6) | |||
], | |||
); | |||
} | |||
/// 标题 | |||
Widget _buildTitleWidget() { | |||
return Row( | |||
mainAxisAlignment: MainAxisAlignment.start, | |||
crossAxisAlignment: CrossAxisAlignment.center, | |||
children: <Widget>[ | |||
Container( | |||
width: 18, | |||
height: 18, | |||
color: Colors.red, | |||
), | |||
const SizedBox(width: 10), | |||
Text( | |||
'必做任务', | |||
style: TextStyle(fontSize: 16, color: HexColor.fromHex('#333333'), fontWeight: FontWeight.bold), | |||
) | |||
], | |||
); | |||
} | |||
/// 元素 | |||
Widget _buildDataWidget() { | |||
return Row( | |||
mainAxisAlignment: MainAxisAlignment.spaceBetween, | |||
crossAxisAlignment: CrossAxisAlignment.end, | |||
children: <Widget>[ | |||
Column( | |||
crossAxisAlignment: CrossAxisAlignment.start, | |||
children: <Widget>[ | |||
Text( | |||
'邀请好友10人', | |||
style: TextStyle(color: HexColor.fromHex('#333333'), fontSize: 14), | |||
), | |||
const SizedBox(height: 4.5), | |||
/// 进度条 | |||
Row( | |||
mainAxisAlignment: MainAxisAlignment.start, | |||
children: <Widget>[ | |||
Container( | |||
height: 10, | |||
width: 140, | |||
color: Colors.red, | |||
), | |||
const SizedBox(width: 10), | |||
Text( | |||
'3/10', | |||
style: TextStyle(color: HexColor.fromHex('#666660'), fontSize: 14), | |||
) | |||
], | |||
) | |||
], | |||
), | |||
/// 完成的图片 | |||
Container( | |||
width: 65, | |||
height: 24, | |||
color: Colors.red, | |||
) | |||
], | |||
); | |||
} | |||
} |
@@ -0,0 +1,144 @@ | |||
import 'package:flutter/material.dart'; | |||
import 'package:zhiying_comm/zhiying_comm.dart'; | |||
class VipCenterTipDialog extends StatelessWidget { | |||
/// 点击了关闭 | |||
void _onClickClose(BuildContext context) { | |||
Navigator.pop(context); | |||
} | |||
/// 点击了继续完成任务 | |||
void _onClickContinue(){ | |||
Logger.log('continue ....'); | |||
} | |||
/// 我再想想 | |||
void _onClickGuess(){ | |||
Logger.log('我再想想'); | |||
} | |||
/// 立即成为会员 | |||
void _onClickBecome(){ | |||
Logger.log('立即成为'); | |||
} | |||
@override | |||
Widget build(BuildContext context) { | |||
return Scaffold( | |||
backgroundColor: Colors.transparent, | |||
body: Column( | |||
mainAxisAlignment: MainAxisAlignment.center, | |||
crossAxisAlignment: CrossAxisAlignment.center, | |||
children: <Widget>[ | |||
Container( | |||
width: double.infinity, | |||
margin: const EdgeInsets.only(left: 22.5, right: 22.5), | |||
padding: const EdgeInsets.only(top: 15, right: 15, left: 15, bottom: 20), | |||
decoration: BoxDecoration( | |||
borderRadius: BorderRadius.circular(10), | |||
color: HexColor.fromHex('#FFFFFF'), | |||
), | |||
child: Column( | |||
children: <Widget>[ | |||
/// 关闭按钮 | |||
Align( | |||
alignment: Alignment.topRight, | |||
child: GestureDetector(behavior: HitTestBehavior.opaque, onTap: () => _onClickClose(context), child: Container(height: 22, width: 22, color: Colors.red))), | |||
const SizedBox(height: 3), | |||
Text('升级会员提示', style: TextStyle(color: HexColor.fromHex('#333333'), fontSize: 18, fontWeight: FontWeight.bold)), | |||
const SizedBox(height: 15), | |||
Padding( | |||
padding: const EdgeInsets.only(left: 55 - 15.0, right: 55 - 15.0), | |||
child: Text( | |||
'由于您还未达到成免费条件,可以选择缴费成为会员,立即享受会员权益.', | |||
maxLines: 5, | |||
style: TextStyle( | |||
color: HexColor.fromHex('#666666'), | |||
fontSize: 16, | |||
), | |||
), | |||
), | |||
const SizedBox(height: 30), | |||
/// 继续完成的按钮 | |||
Visibility( | |||
visible: false, | |||
replacement: Row( | |||
children: <Widget>[ | |||
Flexible( | |||
flex: 1, | |||
child: _buildGuessButtonWidget(), | |||
), | |||
const SizedBox(width: 11), | |||
Flexible( | |||
flex: 1, | |||
child: _buildBecomeButtonWidget(), | |||
), | |||
], | |||
), | |||
child: _buildContinueButtonWidget(), | |||
), | |||
], | |||
), | |||
), | |||
], | |||
), | |||
); | |||
} | |||
/// 我再想想按钮 | |||
Widget _buildGuessButtonWidget(){ | |||
return _buildButtonWidget( | |||
text: '我再想想', | |||
textColor: '#999999', | |||
bgColor: null, | |||
marginLeft: 45.5-15, | |||
onTap:_onClickGuess, | |||
); | |||
} | |||
/// 立即成为会员按钮 | |||
Widget _buildBecomeButtonWidget(){ | |||
return _buildButtonWidget( | |||
text: '立即成为会员', | |||
textColor: '#FFFFFF', | |||
bgColor: null, | |||
marginRight: 36.5-15, | |||
onTap:_onClickBecome, | |||
); | |||
} | |||
/// 继续完成的按钮 | |||
Widget _buildContinueButtonWidget(){ | |||
return _buildButtonWidget( | |||
text: '继续完成任务', | |||
textColor: '#FFFFFF', | |||
bgColor: null, | |||
marginLeft: 42.5 - 15, | |||
marginRight: 34 - 15.0, | |||
onTap: _onClickContinue | |||
); | |||
} | |||
Widget _buildButtonWidget({String text, String textColor, String bgColor, GestureTapCallback onTap,final double marginLeft,final double marginRight}){ | |||
return GestureDetector( | |||
onTap: onTap, | |||
behavior: HitTestBehavior.opaque, | |||
child: Container( | |||
decoration: BoxDecoration( | |||
color: HexColor.fromHex(bgColor ?? '#FF4242'), | |||
borderRadius: BorderRadius.circular(45/2) | |||
), | |||
alignment: Alignment.center, | |||
width: double.infinity, | |||
height: 44.5, | |||
margin: EdgeInsets.only(left: marginLeft ?? 0 , right: marginRight ?? 0 ), | |||
child: Text(text ?? '', style: TextStyle(color: HexColor.fromHex(textColor ?? '#FFFFFF'), fontSize: 14,),), | |||
), | |||
); | |||
} | |||
} |
@@ -0,0 +1,193 @@ | |||
import 'package:flutter/cupertino.dart'; | |||
import 'package:flutter/material.dart'; | |||
import 'package:zhiying_comm/zhiying_comm.dart'; | |||
class VipCenterUpgradeDialogPage extends StatefulWidget { | |||
@override | |||
_VipCenterUpgradeDialogPageState createState() => _VipCenterUpgradeDialogPageState(); | |||
} | |||
class _VipCenterUpgradeDialogPageState extends State<VipCenterUpgradeDialogPage> { | |||
bool _agreeLicense = false; | |||
/// 关闭 | |||
void _onClickClose(BuildContext context) { | |||
Navigator.pop(context); | |||
} | |||
/// 点击同意协议 | |||
void _onClickAgreeLicense(){ | |||
setState(() { | |||
_agreeLicense = !_agreeLicense; | |||
}); | |||
} | |||
@override | |||
Widget build(BuildContext context) { | |||
return Column( | |||
crossAxisAlignment: CrossAxisAlignment.center, | |||
mainAxisAlignment: MainAxisAlignment.end, | |||
children: <Widget>[ | |||
Container( | |||
padding: const EdgeInsets.only(top: 50), | |||
width: double.infinity, | |||
child: Stack( | |||
children: <Widget>[ | |||
/// 主要视图 | |||
_buildMainWidget(context), | |||
/// 皇冠 | |||
Align(alignment: Alignment.topCenter, child: _buildCrownWidget()), | |||
], | |||
), | |||
), | |||
], | |||
); | |||
} | |||
/// 主视图 | |||
Widget _buildMainWidget(context) { | |||
return Container( | |||
padding: const EdgeInsets.only(bottom: 20), | |||
// height: 456, | |||
width: double.infinity, | |||
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.only(topRight: Radius.circular(10), topLeft: Radius.circular(10))), | |||
child: Column( | |||
children: <Widget>[ | |||
/// 关闭按钮 | |||
Padding(padding: const EdgeInsets.only(top: 15, right: 15), child: Align(alignment: Alignment.topRight, child: _buildCloseButtonWidget(context))), | |||
/// 会员升级 | |||
const SizedBox(height: 14), | |||
Text('会员升级', style: TextStyle(fontSize: 18, color: HexColor.fromHex('#333333'), fontWeight: FontWeight.bold)), | |||
/// 当前等级 | |||
const SizedBox(height: 10), | |||
RichText( | |||
text: TextSpan(children: [ | |||
TextSpan(text: '当前等级:', style: TextStyle(color: HexColor.fromHex('#666666'), fontSize: 16)), | |||
TextSpan(text: '普通会员', style: TextStyle(color: HexColor.fromHex('#666666'), fontSize: 16)) | |||
])), | |||
/// 会员等级 | |||
const SizedBox(height: 10), | |||
RichText( | |||
text: TextSpan(children: [ | |||
TextSpan(text: '升级为:', style: TextStyle(color: HexColor.fromHex('#666666'), fontSize: 16)), | |||
TextSpan(text: '初级会员', style: TextStyle(color: HexColor.fromHex('#666666'), fontSize: 16, fontWeight: FontWeight.bold)) | |||
]), | |||
), | |||
/// 套餐 | |||
const SizedBox(height: 30), | |||
Padding( | |||
padding: const EdgeInsets.only(left: 12.5), | |||
child: Align( | |||
alignment: Alignment.centerLeft, | |||
child: Text( | |||
'请选择适合您的会员套餐:', | |||
style: TextStyle(fontSize: 14, color: HexColor.fromHex('#999999')), | |||
))), | |||
/// 套餐列表 | |||
const SizedBox(height: 15), | |||
_buildDataWidget(), | |||
/// 协议提示 | |||
const SizedBox(height: 15), | |||
Padding(padding: const EdgeInsets.only(left: 12.5), child: Align(alignment: Alignment.centerLeft, child: _buildAutoTipWidget())), | |||
/// 确认按钮 | |||
const SizedBox(height: 30), | |||
_buildConfirmButtonWidget(), | |||
], | |||
), | |||
); | |||
} | |||
/// 套餐数据 | |||
Widget _buildDataWidget() { | |||
return Container( | |||
height: 120, | |||
width: double.infinity, | |||
child: ListView.builder( | |||
shrinkWrap: true, | |||
itemBuilder: (context, index) { | |||
return Container( | |||
margin: EdgeInsets.only(right: 15, left: index == 0 ? 12.5 :0), | |||
height: double.infinity, | |||
width: 85, | |||
color: Colors.red, | |||
); | |||
}, | |||
itemCount: 8, | |||
scrollDirection: Axis.horizontal, | |||
itemExtent: 120, | |||
), | |||
); | |||
} | |||
/// 皇冠 | |||
Widget _buildCrownWidget() { | |||
return Transform.translate( | |||
offset: Offset(0, -50), | |||
child: Container( | |||
width: 210, | |||
height: 90, | |||
color: HexColor.fromHex('#eeF0D199'), | |||
), | |||
); | |||
} | |||
/// 关闭按钮 | |||
Widget _buildCloseButtonWidget(context) { | |||
return GestureDetector( | |||
onTap: () => _onClickClose(context), | |||
behavior: HitTestBehavior.opaque, | |||
child: Container( | |||
width: 21, | |||
height: 21, | |||
color: Colors.red, | |||
), | |||
); | |||
} | |||
/// 同意自动续费提示 | |||
Widget _buildAutoTipWidget() { | |||
return GestureDetector( | |||
onTap: ()=> _onClickAgreeLicense(), | |||
child: Row( | |||
mainAxisAlignment: MainAxisAlignment.start, | |||
crossAxisAlignment: CrossAxisAlignment.center, | |||
children: <Widget>[ | |||
Container( | |||
width: 12, | |||
height: 12, | |||
color: !_agreeLicense ? Colors.yellowAccent: Colors.red, | |||
), | |||
const SizedBox(width: 4.5), | |||
Text( | |||
'同意《自动续费协议》开启自动续费', | |||
style: TextStyle(fontSize: 12, color: HexColor.fromHex('#999999')), | |||
), | |||
], | |||
), | |||
); | |||
} | |||
/// 立即享受会员特权按钮 | |||
Widget _buildConfirmButtonWidget() { | |||
return Container( | |||
height: 50, | |||
width: double.infinity, | |||
margin: const EdgeInsets.only(left: 47.5, right: 47.5), | |||
decoration: BoxDecoration( | |||
borderRadius: BorderRadius.circular(50 / 2), | |||
color: Colors.red, | |||
), | |||
); | |||
} | |||
} | |||
@@ -1,6 +1,8 @@ | |||
import 'package:sharesdk_plugin/sharesdk_interface.dart'; | |||
import 'package:sharesdk_plugin/sharesdk_register.dart'; | |||
import 'package:zhiying_base_widget/pages/bil_detail_page/bil_detail_page.dart'; | |||
import 'package:zhiying_base_widget/pages/about_us_page/about_us_page.dart'; | |||
import 'package:zhiying_base_widget/pages/feedback_page/feedback_page.dart'; | |||
import 'package:zhiying_base_widget/pages/goods_details_page/goods_details_page.dart'; | |||
import 'package:zhiying_base_widget/pages/home_page/home_page.dart'; | |||
@@ -8,6 +10,7 @@ import 'package:zhiying_base_widget/pages/hot_ranking_page/hot_ranking_page.dart | |||
import 'package:zhiying_base_widget/pages/invited_friends/invited_friends.dart'; | |||
import 'package:zhiying_base_widget/pages/launch_page/launch_page.dart'; | |||
import 'package:zhiying_base_widget/pages/main_page/main_page.dart'; | |||
import 'package:zhiying_base_widget/pages/message_settings_page/message_settings_page.dart'; | |||
import 'package:zhiying_base_widget/pages/mine_detail_page/mine_detail_page.dart'; | |||
import 'package:zhiying_base_widget/pages/orders_page/orders_page.dart'; | |||
import 'package:zhiying_base_widget/pages/search_page/item/search_item_page.dart'; | |||
@@ -55,6 +58,7 @@ import 'package:zhiying_comm/zhiying_comm.dart'; | |||
import 'pages/favorites_page/favorites_page.dart'; | |||
import 'pages/message_notice_page/message_notice_page.dart'; | |||
import 'pages/privacy_settings_page/privacy_settings_page.dart'; | |||
import 'pages/search_page/search_page.dart'; | |||
import 'pages/wallet_page/wallet_page.dart'; | |||
import 'widgets/goods_details/coupon/counpon_widget.dart'; | |||
@@ -88,10 +92,8 @@ class BaseWidgetRegister { | |||
Application.addMethod(() async { | |||
ShareSDKRegister register = ShareSDKRegister(); | |||
register.setupWechat("wx617c77c82218ea2c", | |||
"c7253e5289986cf4c4c74d1ccc185fb1", "https://www.sandslee.com/"); | |||
register.setupSinaWeibo("568898243", "38a4f8204cc784f81f9f0daaf31e02e3", | |||
"http://www.sharesdk.cn"); | |||
register.setupWechat("wx617c77c82218ea2c", "c7253e5289986cf4c4c74d1ccc185fb1", "https://www.sandslee.com/"); | |||
register.setupSinaWeibo("568898243", "38a4f8204cc784f81f9f0daaf31e02e3", "http://www.sharesdk.cn"); | |||
register.setupQQ("1111030588", "XoHKlrBybXy7ORBt"); | |||
SharesdkPlugin.regist(register); | |||
}); | |||
@@ -107,65 +109,54 @@ class BaseWidgetRegister { | |||
PageFactory.regist('homePage', (model) => HomePage()); | |||
PageFactory.regist('pub.flutter.index', (model) => MainPage(model)); | |||
PageFactory.regist('pub.flutter.profile', (model) => MainPage(model)); | |||
PageFactory.regist( | |||
'pub.flutter.hot_rank', (model) => HotRankingPage(model)); | |||
PageFactory.regist( | |||
'pub.flutter.my_wallet', (model) => WalletPage(data: model)); | |||
PageFactory.regist('pub.flutter.hot_rank', (model) => HotRankingPage(model)); | |||
PageFactory.regist('pub.flutter.my_wallet', (model) => WalletPage(data: model)); | |||
PageFactory.regist('goods_details', (model) => GoodsDetailsPage(model)); | |||
PageFactory.regist('search', (model) => SearchPage(model)); | |||
PageFactory.regist('search_item_page', (model) => SearchItemPage(model)); | |||
PageFactory.regist( | |||
'pub.flutter.search_index', (model) => SearchResultPage(model)); | |||
PageFactory.regist( | |||
'search_result_item', (model) => SearchResultItemPage(model)); | |||
PageFactory.regist('pub.flutter.search_index', (model) => SearchResultPage(model)); | |||
PageFactory.regist('search_result_item', (model) => SearchResultItemPage(model)); | |||
PageFactory.regist('pub.flutter.feedback', (model) => FeedbackPage()); | |||
PageFactory.regist( | |||
'pub.flutter.wechat_teacher', (model) => WechatTeacherPage()); | |||
PageFactory.regist('pub.flutter.wechat_teacher', (model) => WechatTeacherPage()); | |||
PageFactory.regist('pub.flutter.cash_out', (model) => WithdrawPage(model)); | |||
// webview | |||
PageFactory.regist('pub.flutter.url', (model) => BaseWebview(model)); | |||
PageFactory.regist( | |||
'pub.flutter.profile_settings', (model) => MineDetailPage()); | |||
PageFactory.regist('pub.flutter.profile_settings', (model) => MineDetailPage()); | |||
PageFactory.regist('pub.flutter.settings', (model) => SettingPage(model)); | |||
PageFactory.regist('pub.flutter.my_order', (model) => OrdersPage(model)); | |||
PageFactory.regist( | |||
'pub.flutter.account_security', (model) => SecurityPage(model)); | |||
PageFactory.regist('pub.flutter.account_security_alipay', | |||
(model) => SecurityBindAlipayPage(model)); | |||
PageFactory.regist('pub.flutter.account_security', (model) => SecurityPage(model)); | |||
PageFactory.regist('pub.flutter.account_security_alipay', (model) => SecurityBindAlipayPage(model)); | |||
// 登录密码 | |||
PageFactory.regist('pub.flutter.account_security_password', | |||
(model) => SecurityPassword(model)); | |||
PageFactory.regist('pub.flutter.account_security_password', (model) => SecurityPassword(model)); | |||
// 修改手机号 | |||
PageFactory.regist('pub.flutter.account_security_mobile', | |||
(model) => SecurityMobile(model)); | |||
PageFactory.regist('pub.flutter.account_security_mobile', (model) => SecurityMobile(model)); | |||
// 邀请好友 | |||
PageFactory.regist( | |||
'pub.flutter.invite_friends', (model) => InvitedFriendsPage(model)); | |||
PageFactory.regist('pub.flutter.invite_friends', (model) => InvitedFriendsPage(model)); | |||
/// 我的团队 | |||
PageFactory.regist('pub.flutter.my_team', (model) => TeamPage(model)); | |||
/// 用户详情 | |||
PageFactory.regist( | |||
'pub.flutter.my_fan_detail', (model) => TeamDetailsPage(model)); | |||
PageFactory.regist('pub.flutter.my_fan_detail', (model) => TeamDetailsPage(model)); | |||
/// 消息中心 | |||
PageFactory.regist( | |||
'pub.flutter.message_center', (model) => MessageNoticePage(model)); | |||
PageFactory.regist( | |||
'pub.flutter.message_notice', (model) => MessageNoticePage(model)); | |||
PageFactory.regist('pub.flutter.message_center', (model) => MessageNoticePage(model)); | |||
/// TODO 首页的消息中心标识和我的页面不一致,需要改 | |||
PageFactory.regist( | |||
'pub.flutter.message', (model) => MessageNoticePage(model)); | |||
/// 我的收藏 | |||
PageFactory.regist('pub.flutter.my_fav', (model) => FavoritesPage()); | |||
PageFactory.regist('pub.flutter.message', (model) => MessageNoticePage(model)); | |||
/// 我的收藏 | |||
PageFactory.regist('pub.flutter.my_fav', (model) => FavoritesPage(model)); | |||
/// 关于我们 | |||
PageFactory.regist('pub.flutter.about_us', (model) => AboutUsPage(model)); | |||
/// 隐私设置 | |||
PageFactory.regist('pub.flutter.privacy_settings', (model) => PrivacySettingsPage(model)); | |||
/// 消息设置 | |||
PageFactory.regist('pub.flutter.message_settings', (model) => MessageSettingsPage(model)); | |||
///钱包明细 | |||
PageFactory.regist('pub.flutter.my_bil', (model) => BilDetailPage(model)); | |||
} | |||
@@ -188,12 +179,10 @@ class BaseWidgetRegister { | |||
WidgetFactory.regist('index_recommend_list', GoodsListCreater()); | |||
/// 首页快速入口 | |||
WidgetFactory.regist( | |||
'multi_nav', DefaultWidgetCreater((model) => HomeQuickEntry(model))); | |||
WidgetFactory.regist('multi_nav', DefaultWidgetCreater((model) => HomeQuickEntry(model))); | |||
/// 滚动公告 | |||
WidgetFactory.regist('index_placard', | |||
DefaultWidgetCreater((model) => HomeNoticeWidget(model))); | |||
WidgetFactory.regist('index_placard', DefaultWidgetCreater((model) => HomeNoticeWidget(model))); | |||
/// 不可以滚动banner | |||
WidgetFactory.regist('index_banner_one', HomeBannerCreater()); | |||
@@ -204,111 +193,80 @@ class BaseWidgetRegister { | |||
// 搜索标题 | |||
// WidgetFactory.regist('search_index_app_bar', DefaultWidgetCreater((model) => SearchAppbarWidget(model))); | |||
// 搜索输入框 | |||
WidgetFactory.regist('search_index_input', | |||
DefaultWidgetCreater((model) => SearchInputWidget(model))); | |||
WidgetFactory.regist('search_index_input', DefaultWidgetCreater((model) => SearchInputWidget(model))); | |||
// // 搜索tabBar | |||
WidgetFactory.regist('search_index_icon_list', SearcchTabCreater()); | |||
// WidgetFactory.regist('search_index_icon_list', DefaultWidgetCreater((model) => SearchTabWidget(model))); | |||
// // 热门搜索标签 | |||
WidgetFactory.regist('search_index_host_keyword', | |||
DefaultWidgetCreater((model) => SearchHotTagWidget(model))); | |||
WidgetFactory.regist('search_index_host_keyword', DefaultWidgetCreater((model) => SearchHotTagWidget(model))); | |||
// // 历史搜索标签 | |||
WidgetFactory.regist('search_index_history', | |||
DefaultWidgetCreater((model) => SearchHistoryTagWidget(model))); | |||
WidgetFactory.regist('search_index_history', DefaultWidgetCreater((model) => SearchHistoryTagWidget(model))); | |||
/// ==================== 搜索结果页面 ==================== /// | |||
// 输入框 | |||
WidgetFactory.regist('search_result_input', | |||
DefaultWidgetCreater((model) => SearchResultInputWidget(model))); | |||
WidgetFactory.regist('search_result_input', DefaultWidgetCreater((model) => SearchResultInputWidget(model))); | |||
// tabbar | |||
WidgetFactory.regist('search_result_icon_list', SearchResultTabCreater()); | |||
// 搜索结果页筛选widget 淘宝 | |||
WidgetFactory.regist('search_result_taobao_sort', | |||
DefaultWidgetCreater((model) => SearchResultSortWidget(model))); | |||
WidgetFactory.regist('search_result_taobao_sort', DefaultWidgetCreater((model) => SearchResultSortWidget(model))); | |||
// 搜索结果的商品列表 淘宝 | |||
WidgetFactory.regist( | |||
'search_result_taobao_item', SearchResultGoodsListCreater()); | |||
WidgetFactory.regist('search_result_taobao_item', SearchResultGoodsListCreater()); | |||
// 搜索结果页筛选widget 京东 | |||
WidgetFactory.regist('search_result_jd_sort', | |||
DefaultWidgetCreater((model) => SearchResultSortWidget(model))); | |||
WidgetFactory.regist('search_result_jd_sort', DefaultWidgetCreater((model) => SearchResultSortWidget(model))); | |||
// 搜索结果的商品列表 京东 | |||
WidgetFactory.regist( | |||
'search_result_jd_item', SearchResultGoodsListCreater()); | |||
WidgetFactory.regist('search_result_jd_item', SearchResultGoodsListCreater()); | |||
// 搜索结果页筛选widget 苏宁 | |||
WidgetFactory.regist('search_result_suning_sort', | |||
DefaultWidgetCreater((model) => SearchResultSortWidget(model))); | |||
WidgetFactory.regist('search_result_suning_sort', DefaultWidgetCreater((model) => SearchResultSortWidget(model))); | |||
// 搜索结果的商品列表 苏宁 | |||
WidgetFactory.regist( | |||
'search_result_suning_item', SearchResultGoodsListCreater()); | |||
WidgetFactory.regist('search_result_suning_item', SearchResultGoodsListCreater()); | |||
// 搜索结果页筛选widget 拼多多 | |||
WidgetFactory.regist('search_result_pdd_sort', | |||
DefaultWidgetCreater((model) => SearchResultSortWidget(model))); | |||
WidgetFactory.regist('search_result_pdd_sort', DefaultWidgetCreater((model) => SearchResultSortWidget(model))); | |||
// 搜索结果的商品列表 拼多多 | |||
WidgetFactory.regist( | |||
'search_result_pdd_item', SearchResultGoodsListCreater()); | |||
WidgetFactory.regist('search_result_pdd_item', SearchResultGoodsListCreater()); | |||
// 搜索结果页筛选widget 唯品会 | |||
WidgetFactory.regist('search_result_vip_sort', | |||
DefaultWidgetCreater((model) => SearchResultSortWidget(model))); | |||
WidgetFactory.regist('search_result_vip_sort', DefaultWidgetCreater((model) => SearchResultSortWidget(model))); | |||
// 搜索结果的商品列表 唯品会 | |||
WidgetFactory.regist( | |||
'search_result_vip_item', SearchResultGoodsListCreater()); | |||
WidgetFactory.regist('search_result_vip_item', SearchResultGoodsListCreater()); | |||
// 搜索结果页筛选widget 考拉 | |||
WidgetFactory.regist('search_result_kaola_sort', | |||
DefaultWidgetCreater((model) => SearchResultSortWidget(model))); | |||
WidgetFactory.regist('search_result_kaola_sort', DefaultWidgetCreater((model) => SearchResultSortWidget(model))); | |||
// 搜索结果的商品列表 考拉 | |||
WidgetFactory.regist( | |||
'search_result_kaola_item', SearchResultGoodsListCreater()); | |||
WidgetFactory.regist('search_result_kaola_item', SearchResultGoodsListCreater()); | |||
/// ==================== 商品详情 ==================== /// | |||
// 商品详情轮播图 | |||
WidgetFactory.regist('product_detail_carousel', | |||
DefaultWidgetCreater((model) => GoodsDetailsSlideBannerWidget(model))); | |||
WidgetFactory.regist('product_detail_carousel', DefaultWidgetCreater((model) => GoodsDetailsSlideBannerWidget(model))); | |||
// 商品详情下载APP提示 | |||
WidgetFactory.regist('product_detail_download_tips', | |||
DefaultWidgetCreater((model) => UpgradeTipWidget(model))); | |||
WidgetFactory.regist('product_detail_download_tips', DefaultWidgetCreater((model) => UpgradeTipWidget(model))); | |||
// 商品详情价格显示 | |||
WidgetFactory.regist('product_detail_price', | |||
DefaultWidgetCreater((model) => GoodsDetailsPriceWidget(model))); | |||
WidgetFactory.regist('product_detail_price', DefaultWidgetCreater((model) => GoodsDetailsPriceWidget(model))); | |||
// 商品详情标题 | |||
WidgetFactory.regist('product_detail_title', | |||
DefaultWidgetCreater((model) => GoodsDetailsTitleWidget(model))); | |||
WidgetFactory.regist('product_detail_title', DefaultWidgetCreater((model) => GoodsDetailsTitleWidget(model))); | |||
// 商品详情优惠劵 | |||
WidgetFactory.regist('product_detail_coupon', | |||
DefaultWidgetCreater((model) => CounponWidget(model))); | |||
WidgetFactory.regist('product_detail_coupon', DefaultWidgetCreater((model) => CounponWidget(model))); | |||
// 商品详情店铺 | |||
WidgetFactory.regist('product_detail_shop', | |||
DefaultWidgetCreater((model) => StoreWidget(model))); | |||
WidgetFactory.regist('product_detail_shop', DefaultWidgetCreater((model) => StoreWidget(model))); | |||
// 商品详情宝贝评价 | |||
WidgetFactory.regist('product_detail_comment', | |||
DefaultWidgetCreater((model) => GoodsDetailsEvaluateWidget(model))); | |||
WidgetFactory.regist('product_detail_comment', DefaultWidgetCreater((model) => GoodsDetailsEvaluateWidget(model))); | |||
// 商品详情图片 | |||
WidgetFactory.regist('product_detail_img_list', | |||
DefaultWidgetCreater((model) => GoodsDetailsImgWidget(model))); | |||
WidgetFactory.regist('product_detail_img_list', DefaultWidgetCreater((model) => GoodsDetailsImgWidget(model))); | |||
// 商品详情底部推荐列表 | |||
WidgetFactory.regist( | |||
'product_detail_bottom_rec', GoodsDetailCommendCreater()); | |||
WidgetFactory.regist('product_detail_bottom_rec', GoodsDetailCommendCreater()); | |||
// 商品详情底部 | |||
WidgetFactory.regist('product_detail_bottom', | |||
DefaultWidgetCreater((model) => GoodsDetailsFooterWidget(model))); | |||
WidgetFactory.regist('product_detail_bottom', DefaultWidgetCreater((model) => GoodsDetailsFooterWidget(model))); | |||
// ==================== 个人中心 | |||
WidgetFactory.regist('profile_appbar', MineNavCreater()); | |||
WidgetFactory.regist('profile_background', | |||
DefaultWidgetCreater((model) => MineNavBg(model))); | |||
WidgetFactory.regist( | |||
'profile_header', DefaultWidgetCreater((model) => MineHeader(model))); | |||
WidgetFactory.regist( | |||
'profile_earning', DefaultWidgetCreater((model) => MineData(model))); | |||
WidgetFactory.regist('profile_functions', | |||
DefaultWidgetCreater((model) => MineQuickEntry(model))); | |||
WidgetFactory.regist('profile_my_functions', | |||
DefaultWidgetCreater((model) => MineQuickEntry(model))); | |||
WidgetFactory.regist('profile_background', DefaultWidgetCreater((model) => MineNavBg(model))); | |||
WidgetFactory.regist('profile_header', DefaultWidgetCreater((model) => MineHeader(model))); | |||
WidgetFactory.regist('profile_earning', DefaultWidgetCreater((model) => MineData(model))); | |||
WidgetFactory.regist('profile_functions', DefaultWidgetCreater((model) => MineQuickEntry(model))); | |||
WidgetFactory.regist('profile_my_functions', DefaultWidgetCreater((model) => MineQuickEntry(model))); | |||
// WidgetFactory.regist('profile_carousel', DefaultWidgetCreater((model) => HomeBannerWidget(model))); | |||
// WidgetFactory.regist('profile_carousel', HomeBannerCreater()); | |||
@@ -320,18 +278,14 @@ class BaseWidgetRegister { | |||
// ))); | |||
WidgetFactory.regist('my_wallet_appbar', NormalNavCreater()); | |||
WidgetFactory.regist( | |||
'my_wallet_header', DefaultWidgetCreater((model) => WalletData(model))); | |||
WidgetFactory.regist( | |||
'my_wallet_bil', DefaultWidgetCreater((model) => WalletBil(model))); | |||
WidgetFactory.regist('my_wallet_header', DefaultWidgetCreater((model) => WalletData(model))); | |||
WidgetFactory.regist('my_wallet_bil', DefaultWidgetCreater((model) => WalletBil(model))); | |||
// WidgetFactory.regist( | |||
// 'wallet_detail', DefaultWidgetCreater((model) => WalletDetail())); | |||
// WidgetFactory.regist('wallet_detail', HomeAuthCreater()); | |||
WidgetFactory.regist('my_wallet_providers', | |||
DefaultWidgetCreater((model) => WalletDetail(model))); | |||
WidgetFactory.regist('my_wallet_providers', DefaultWidgetCreater((model) => WalletDetail(model))); | |||
WidgetFactory.regist( | |||
'wallet_income', DefaultWidgetCreater((model) => WalletIncome())); | |||
WidgetFactory.regist('wallet_income', DefaultWidgetCreater((model) => WalletIncome())); | |||
//======================= 账单明细 | |||
WidgetFactory.regist( | |||
@@ -341,11 +295,8 @@ class BaseWidgetRegister { | |||
))); | |||
//======================== 热榜 | |||
WidgetFactory.regist('hot_rank_appbar', | |||
DefaultWidgetCreater((model) => HotRankingAppBar(model))); | |||
WidgetFactory.regist('hot_rank_tabs', | |||
DefaultWidgetCreater((model) => HotRankTableBar(model))); | |||
WidgetFactory.regist('hot_rank_tab_view', | |||
DefaultWidgetCreater((model) => HotRankingList(model))); | |||
WidgetFactory.regist('hot_rank_appbar', DefaultWidgetCreater((model) => HotRankingAppBar(model))); | |||
WidgetFactory.regist('hot_rank_tabs', DefaultWidgetCreater((model) => HotRankTableBar(model))); | |||
WidgetFactory.regist('hot_rank_tab_view', DefaultWidgetCreater((model) => HotRankingList(model))); | |||
} | |||
} |
@@ -102,12 +102,12 @@ class _MineHeaderContainerState extends State<MineHeaderContainer> { | |||
height: 12, | |||
margin: EdgeInsets.only(right: 2), | |||
child: CachedNetworkImage( | |||
imageUrl: profile.userLvIcon, | |||
imageUrl: profile?.userLvIcon?? '', | |||
fit: BoxFit.contain, | |||
), | |||
), | |||
Text( | |||
profile.userLvName, | |||
profile?.userLvName?? '', | |||
style: TextStyle( | |||
fontSize: 10, | |||
color: HexColor.fromHex( | |||