Browse Source

Merge branch 'master' of http://192.168.0.138:3000/FnuoOS_ZhiYing/zhiying_base_widget

# Conflicts:
#	.dart_tool/package_config.json
#	lib/register.dart
tags/0.0.1
Weller 4 years ago
parent
commit
f16c73a107
66 changed files with 2781 additions and 184 deletions
  1. +1
    -1
      .dart_tool/package_config.json
  2. +0
    -6
      .idea/runConfigurations/example_lib_main_dart.xml
  3. +0
    -13
      .idea/saveactions_settings.xml
  4. BIN
     
  5. +160
    -0
      android/gradlew
  6. +90
    -0
      android/gradlew.bat
  7. +39
    -0
      lib/pages/goods_details_page/bloc/goods_details_page_bloc.dart
  8. +15
    -0
      lib/pages/goods_details_page/bloc/goods_details_page_event.dart
  9. +40
    -0
      lib/pages/goods_details_page/bloc/goods_details_page_repository.dart
  10. +24
    -0
      lib/pages/goods_details_page/bloc/goods_details_page_state.dart
  11. +193
    -0
      lib/pages/goods_details_page/goods_details_page.dart
  12. +16
    -0
      lib/pages/goods_details_page/notifier/goods_details_page_notifier.dart
  13. +64
    -26
      lib/register.dart
  14. +61
    -0
      lib/widgets/goods_details/counpon_description/counpon_description_widget.dart
  15. +3
    -0
      lib/widgets/goods_details/coupon/bloc/bloc.dart
  16. +30
    -0
      lib/widgets/goods_details/coupon/bloc/counpon_bloc.dart
  17. +15
    -0
      lib/widgets/goods_details/coupon/bloc/counpon_event.dart
  18. +11
    -0
      lib/widgets/goods_details/coupon/bloc/counpon_repository.dart
  19. +25
    -0
      lib/widgets/goods_details/coupon/bloc/counpon_state.dart
  20. +26
    -0
      lib/widgets/goods_details/coupon/counpon_sk.dart
  21. +104
    -0
      lib/widgets/goods_details/coupon/counpon_widget.dart
  22. +2
    -0
      lib/widgets/goods_details/coupon/model/counpon_model.dart
  23. +27
    -0
      lib/widgets/goods_details/evaluate/godds_details_evaluate_sk.dart
  24. +38
    -0
      lib/widgets/goods_details/evaluate/goods_details_evaluate_widget.dart
  25. +38
    -0
      lib/widgets/goods_details/footer/goods_details_footer_sk.dart
  26. +169
    -0
      lib/widgets/goods_details/footer/goods_details_footer_widget.dart
  27. +83
    -0
      lib/widgets/goods_details/price/goods_details_price_widget.dart
  28. +46
    -0
      lib/widgets/goods_details/slide_banner/bloc/goods_details_slide_banner_bloc.dart
  29. +15
    -0
      lib/widgets/goods_details/slide_banner/bloc/goods_details_slide_banner_event.dart
  30. +21
    -0
      lib/widgets/goods_details/slide_banner/bloc/goods_details_slide_banner_repository.dart
  31. +26
    -0
      lib/widgets/goods_details/slide_banner/bloc/goods_details_slide_banner_state.dart
  32. +19
    -0
      lib/widgets/goods_details/slide_banner/goods_details_slide_banner_creater.dart
  33. +21
    -0
      lib/widgets/goods_details/slide_banner/goods_details_slide_banner_sk.dart
  34. +172
    -0
      lib/widgets/goods_details/slide_banner/goods_details_slide_banner_widget.dart
  35. +61
    -0
      lib/widgets/goods_details/slide_banner/model/goods_details_silde_banner_model.dart
  36. +4
    -0
      lib/widgets/goods_details/store/bloc/bloc.dart
  37. +43
    -0
      lib/widgets/goods_details/store/bloc/store_bloc.dart
  38. +11
    -0
      lib/widgets/goods_details/store/bloc/store_event.dart
  39. +10
    -0
      lib/widgets/goods_details/store/bloc/store_repository.dart
  40. +27
    -0
      lib/widgets/goods_details/store/bloc/store_state.dart
  41. +3
    -0
      lib/widgets/goods_details/store/model/store_model.dart
  42. +44
    -0
      lib/widgets/goods_details/store/store_sk.dart
  43. +147
    -0
      lib/widgets/goods_details/store/store_widget.dart
  44. +48
    -0
      lib/widgets/goods_details/title/goods_details_title_widget.dart
  45. +3
    -0
      lib/widgets/goods_details/upgrade_tip/model/upgrade_tip_model.dart
  46. +27
    -0
      lib/widgets/goods_details/upgrade_tip/upgrade_tip_sk.dart
  47. +57
    -0
      lib/widgets/goods_details/upgrade_tip/upgrade_tip_widget.dart
  48. +9
    -0
      lib/widgets/home/home_ai_dialog/home_ai_dialog.dart
  49. +1
    -0
      lib/widgets/home/home_banner/home_banner_widget.dart
  50. +3
    -0
      lib/widgets/home/home_notice/bloc/bloc.dart
  51. +32
    -0
      lib/widgets/home/home_notice/bloc/home_notice_bloc.dart
  52. +16
    -0
      lib/widgets/home/home_notice/bloc/home_notice_event.dart
  53. +18
    -0
      lib/widgets/home/home_notice/bloc/home_notice_repository.dart
  54. +30
    -0
      lib/widgets/home/home_notice/bloc/home_notice_state.dart
  55. +28
    -0
      lib/widgets/home/home_notice/home_notice_sk.dart
  56. +203
    -0
      lib/widgets/home/home_notice/home_notice_widget.dart
  57. +58
    -0
      lib/widgets/home/home_notice/model/home_notice_model.dart
  58. +4
    -2
      lib/widgets/home/home_quick_entry/home_quick_entry.dart
  59. +9
    -8
      lib/widgets/home/home_slide_banner/bloc/home_slide_banner_bloc.dart
  60. +20
    -9
      lib/widgets/home/home_slide_banner/bloc/home_slide_banner_repository.dart
  61. +3
    -4
      lib/widgets/home/home_slide_banner/bloc/home_slide_banner_state.dart
  62. +59
    -11
      lib/widgets/home/home_slide_banner/home_slide_banner.dart
  63. +47
    -104
      lib/widgets/home/home_slide_banner/model/home_slide_banner_model.dart
  64. +22
    -0
      lib/widgets/home/home_sreach/home_sreach_creater.dart
  65. +21
    -0
      lib/widgets/home/home_sreach/home_sreach_sk.dart
  66. +119
    -0
      lib/widgets/home/home_sreach/home_sreach_widget.dart

+ 1
- 1
.dart_tool/package_config.json View File

@@ -770,7 +770,7 @@
"languageVersion": "2.1"
}
],
"generated": "2020-09-19T06:19:07.938950Z",
"generated": "2020-09-21T02:27:30.928433Z",
"generator": "pub",
"generatorVersion": "2.7.2"
}

+ 0
- 6
.idea/runConfigurations/example_lib_main_dart.xml View File

@@ -1,6 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="example/lib/main.dart" type="FlutterRunConfigurationType" factoryName="Flutter">
<option name="filePath" value="$PROJECT_DIR$/example/lib/main.dart" />
<method />
</configuration>
</component>

+ 0
- 13
.idea/saveactions_settings.xml View File

@@ -1,13 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="SaveActionSettings">
<option name="actions">
<set>
<option value="activate" />
<option value="organizeImports" />
<option value="reformat" />
</set>
</option>
<option name="configurationPath" value="" />
</component>
</project>

BIN
View File


+ 160
- 0
android/gradlew View File

@@ -0,0 +1,160 @@
#!/usr/bin/env bash

##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################

# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""

APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`

# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"

warn ( ) {
echo "$*"
}

die ( ) {
echo
echo "$*"
echo
exit 1
}

# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac

# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null

CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar

# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME

Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.

Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi

# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi

# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi

# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`

# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option

if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi

# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"

exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"

+ 90
- 0
android/gradlew.bat View File

@@ -0,0 +1,90 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################

@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal

@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=

set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%

@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome

set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init

echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.

goto fail

:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe

if exist "%JAVA_EXE%" goto init

echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.

goto fail

:init
@rem Get command-line arguments, handling Windowz variants

if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args

:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2

:win9xME_args_slurp
if "x%~1" == "x" goto execute

set CMD_LINE_ARGS=%*
goto execute

:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$

:execute
@rem Setup the command line

set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar

@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%

:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd

:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1

:mainEnd
if "%OS%"=="Windows_NT" endlocal

:omega

+ 39
- 0
lib/pages/goods_details_page/bloc/goods_details_page_bloc.dart View File

@@ -0,0 +1,39 @@
import 'dart:async';

import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter/cupertino.dart';
import 'package:zhiying_base_widget/pages/goods_details_page/bloc/goods_details_page_repository.dart';
import 'package:zhiying_comm/util/empty_util.dart';

part 'goods_details_page_event.dart';

part 'goods_details_page_state.dart';

class GoodsDetailsPageBloc extends Bloc<GoodsDetailsPageEvent, GoodsDetailsPageState> {
// GoodsDetailsPageBloc() : super(GoodsDetailsPageInitial());

@override
GoodsDetailsPageState get initialState => GoodsDetailsPageInitial();

GoodsDetailsPageRepository repository;

GoodsDetailsPageBloc({@required this.repository});

@override
Stream<GoodsDetailsPageState> mapEventToState(
GoodsDetailsPageEvent event,
) async* {
if (event is GoodsDetailsPageInitEvent) {
yield* _mapInitEventToState(event);
}
}

Stream<GoodsDetailsPageState> _mapInitEventToState(GoodsDetailsPageInitEvent event) async* {
var result = await repository.fetchInitData(event.model);
if (!EmptyUtil.isEmpty(result))
yield GoodsDetailsPageLoadedState(model: result);
else
yield GoodsDetailsPageErrorState();
}
}

+ 15
- 0
lib/pages/goods_details_page/bloc/goods_details_page_event.dart View File

@@ -0,0 +1,15 @@
part of 'goods_details_page_bloc.dart';

abstract class GoodsDetailsPageEvent extends Equatable {
const GoodsDetailsPageEvent();
}

/// 初始化
class GoodsDetailsPageInitEvent extends GoodsDetailsPageEvent {
final Map<String, dynamic> model;

const GoodsDetailsPageInitEvent({this.model});

@override
List<Object> get props => [this.model];
}

+ 40
- 0
lib/pages/goods_details_page/bloc/goods_details_page_repository.dart View File

@@ -0,0 +1,40 @@
import 'package:zhiying_comm/zhiying_comm.dart';

class GoodsDetailsPageRepository {
List<Map<String, dynamic>> _pageData = [];

/// 初始化
Future<List<Map<String, dynamic>>> fetchInitData(Map<String, dynamic> model) async {
int id = 13;
var result = await NetUtil.post('/api/v1/mod',
method: NetMethod.POST,
params: Map<String, dynamic>.from({
'ids': [id]
}));
try {
if(NetUtil.isSuccess(result) && !EmptyUtil.isEmpty(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA])) {
return _loadData(id, result[GlobalConfig.HTTP_RESPONSE_KEY_DATA]);
}
} catch (e) {
Logger.log(e);
}
return null;
}

/// 处理数据
List<Map<String, dynamic>> _loadData(int id, dynamic data) {
String key = id.toString();
Map<String, dynamic> json = Map<String, dynamic>.from(data);
if (json.containsKey(key)) {
List<dynamic> list = json[key];
_pageData = list.map((item) {
return Map<String, dynamic>.from(item);
}).toList();
return _pageData;
}
return null;
}

/// 获取缓存数据?

}

+ 24
- 0
lib/pages/goods_details_page/bloc/goods_details_page_state.dart View File

@@ -0,0 +1,24 @@
part of 'goods_details_page_bloc.dart';

abstract class GoodsDetailsPageState extends Equatable {
const GoodsDetailsPageState();

@override
List<Object> get props => [];
}

/// 初始化状态
class GoodsDetailsPageInitial extends GoodsDetailsPageState {}

/// 数据加载完毕状态
class GoodsDetailsPageLoadedState extends GoodsDetailsPageState {
final List<Map<String, dynamic>> model;

const GoodsDetailsPageLoadedState({this.model});

@override
List<Object> get props => [this.model];
}

/// 数据加载出错
class GoodsDetailsPageErrorState extends GoodsDetailsPageState {}

+ 193
- 0
lib/pages/goods_details_page/goods_details_page.dart View File

@@ -0,0 +1,193 @@
import 'package:flutter/material.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';
import 'package:zhiying_base_widget/pages/goods_details_page/bloc/goods_details_page_bloc.dart';
import 'package:zhiying_base_widget/pages/goods_details_page/bloc/goods_details_page_repository.dart';
import 'package:zhiying_base_widget/pages/goods_details_page/notifier/goods_details_page_notifier.dart';
import 'package:zhiying_base_widget/widgets/goods_details/footer/goods_details_footer_widget.dart';
import 'package:zhiying_comm/zhiying_comm.dart';
import 'package:provider/provider.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'dart:ui';

class GoodsDetailsPage extends StatefulWidget {
final Map<String, dynamic> data;

GoodsDetailsPage(this.data, {Key key}) : super(key: key);

@override
_GoodsDetailsPageState createState() => _GoodsDetailsPageState();
}

class _GoodsDetailsPageState extends State<GoodsDetailsPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: HexColor.fromHex('#FFF1F1F1'),
body: MultiProvider(
providers: [
/// 滑动通知
ChangeNotifierProvider.value(value: GoodsDetailsPageNotifier()),
],
child: BlocProvider<GoodsDetailsPageBloc>(
create: (_) => GoodsDetailsPageBloc(repository: GoodsDetailsPageRepository())..add(GoodsDetailsPageInitEvent(model: widget?.data)),
child: GoodsDetailsContainer(widget?.data),
),
),
);
}
}

class GoodsDetailsContainer extends StatefulWidget {
final Map<String, dynamic> data;

const GoodsDetailsContainer(this.data);

@override
_GoodsDetailsContainerState createState() => _GoodsDetailsContainerState();
}

class _GoodsDetailsContainerState extends State<GoodsDetailsContainer> {
bool _isEnded = false;
ScrollController _controller = ScrollController();
RefreshController _refreshController = RefreshController(initialRefresh: false);

void _onLoading() async {
// await Future.delayed(Duration(milliseconds: 1000));
// if (mounted) setState(() {});
// _refreshController.loadComplete();
}

/// 返回上一页
void _openPop() {
print('返回上一页');

Navigator.maybePop(context);
}

@override
void dispose() {
_controller.dispose();
super.dispose();
}

@override
void initState() {
_controller.addListener(() {
// print('${_controller.offset} ${_controller.position.maxScrollExtent}');
if (_controller.offset >= _controller.position.maxScrollExtent && !_isEnded) {
// 滑动到底部
_isEnded = true;
Provider.of<GoodsDetailsPageNotifier>(context, listen: false).loadMore();
} else if (_controller.offset < _controller.position.maxScrollExtent && _isEnded) {
_isEnded = false;
Provider.of<GoodsDetailsPageNotifier>(context, listen: false).reset();
}
});
super.initState();
}

@override
Widget build(BuildContext context) {
return MediaQuery.removePadding(
removeTop: true,
context: context,
child: Container(
width: double.infinity,
child: BlocConsumer<GoodsDetailsPageBloc, GoodsDetailsPageState>(
listener: (BuildContext context, GoodsDetailsPageState state) {
if (state is GoodsDetailsPageErrorState) {
print('数据加载出错');
}
},
buildWhen: (previous, current) {
/// 数据加载出错不进行build
if (current is GoodsDetailsPageErrorState) {
return false;
}
return true;
},
builder: (context, state) {
print('currente state = $state');
if (state is GoodsDetailsPageLoadedState) {
return _getMainWidget(state?.model);
}
return _getMainWidget(null);
},
),
),
);
}

/// 主视图
Widget _getMainWidget(List<Map<String, dynamic>> datas) {
return Stack(
fit: StackFit.passthrough,
children: <Widget>[
/// 主体布局
SmartRefresher(
enablePullDown: true,
enablePullUp: false,
header: WaterDropHeader(),
controller: _refreshController,
onLoading: _onLoading,
child: CustomScrollView(
controller: _controller,
slivers: _createContent(context, datas ?? []),
),
),
/// appBar
Align(
alignment: Alignment.topCenter,
child: _getAppBarWidget()),
/// 底部
Align(alignment: Alignment.bottomCenter, child: GoodsDetailsFooterWidget(null))
],
);
}

List<Widget> _createContent(BuildContext context, List<Map<String, dynamic>> datas) {
List<Widget> list = List();
for (int i = 0; i < datas.length; i++) {
WidgetModel item = WidgetModel.fromJson(Map<String, dynamic>.from(datas[i]));

print('item.modName ${item.modName}');
list.addAll(WidgetFactory.create(
item.modName,
isSliver: true,
model: datas[i],
));
}
if (list.length <= 0) {
list.add(SliverToBoxAdapter(
child: Container(
height: 200,
child: Center(
child: Text('暂时无数据哦~'),
),
),
));
}
return list;
}

/// appBar
Widget _getAppBarWidget() {
return Container(
width: double.infinity,
height: 40,
margin: EdgeInsets.only(top: MediaQueryData.fromWindow(window).padding.top),
child: AppBar(
backgroundColor: Colors.transparent,
elevation: 0,
leading: IconButton(
icon: Icon(
Icons.arrow_back_ios,
size: 22,
color: HexColor.fromHex('#FFFFFF'),
),
onPressed: () => _openPop(),
),
),
);
}
}

+ 16
- 0
lib/pages/goods_details_page/notifier/goods_details_page_notifier.dart View File

@@ -0,0 +1,16 @@
import 'package:flutter/material.dart';

class GoodsDetailsPageNotifier with ChangeNotifier {
bool scrollEnd = false;

// 加载更多数据
void loadMore() {
scrollEnd = true;
notifyListeners();
}

void reset() {
scrollEnd = false;
notifyListeners();
}
}

+ 64
- 26
lib/register.dart View File

@@ -1,3 +1,5 @@
import 'package:flutter/cupertino.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';
import 'package:zhiying_base_widget/pages/main_page/main_page.dart';
import 'package:zhiying_base_widget/pages/mine_detail_page/mine_detail_page.dart';
@@ -5,10 +7,19 @@ import 'package:zhiying_base_widget/pages/orders_page/orders_page.dart';
import 'package:zhiying_base_widget/pages/setting_page/setting_page.dart';
import 'package:zhiying_base_widget/pages/wallet_page/wallet_page.dart';
import 'package:zhiying_base_widget/widgets/home/home_auth/home_auth_creater.dart';
import 'package:zhiying_base_widget/widgets/goods_details/footer/goods_details_footer_widget.dart';
import 'package:zhiying_base_widget/widgets/goods_details/price/goods_details_price_widget.dart';
import 'package:zhiying_base_widget/widgets/goods_details/slide_banner/goods_details_slide_banner_widget.dart';
import 'package:zhiying_base_widget/widgets/goods_details/store/store_widget.dart';
import 'package:zhiying_base_widget/widgets/goods_details/upgrade_tip/upgrade_tip_widget.dart';
import 'package:zhiying_base_widget/widgets/home/home_banner/home_banner_creater.dart';
import 'package:zhiying_base_widget/widgets/home/home_banner/home_banner_widget.dart';
import 'package:zhiying_base_widget/widgets/home/home_goods/home_goods_creater.dart';
import 'package:zhiying_base_widget/widgets/home/home_notice/home_notice_widget.dart';
import 'package:zhiying_base_widget/widgets/home/home_notice/model/home_notice_model.dart';
import 'package:zhiying_base_widget/widgets/home/home_slide_banner/home_slide_banner_creater.dart';
import 'package:zhiying_base_widget/widgets/home/home_sreach/home_sreach_creater.dart';
import 'package:zhiying_base_widget/widgets/home/home_sreach/home_sreach_widget.dart';
import 'package:zhiying_base_widget/widgets/mine/mine_data/mine_data.dart';
import 'package:zhiying_base_widget/widgets/mine/mine_header/mine_header.dart';
import 'package:zhiying_base_widget/widgets/mine/mine_nav/mine_nav_bg.dart';
@@ -16,10 +27,14 @@ import 'package:zhiying_base_widget/widgets/mine/mine_nav/mine_nav_creater.dart'
import 'package:zhiying_base_widget/widgets/mine/mine_quick_entry/mine_quick_entry.dart';
import 'package:zhiying_base_widget/widgets/others/normal_nav/normal_nav_creater.dart';
import 'package:zhiying_base_widget/widgets/wallet/wallet_data/wallet_data.dart';
import 'package:zhiying_base_widget/widgets/wallet/wallet_detail/wallet_detail.dart';
import 'package:zhiying_base_widget/widgets/wallet/wallet_income/wallet_income.dart';
import 'package:zhiying_comm/util/defalut_widget_creater.dart';
import 'package:zhiying_comm/zhiying_comm.dart';

import 'widgets/goods_details/coupon/counpon_widget.dart';
import 'widgets/goods_details/evaluate/goods_details_evaluate_widget.dart';
import 'widgets/goods_details/title/goods_details_title_widget.dart';
import 'widgets/home/home_quick_entry/home_quick_entry.dart';

class BaseWidgetRegister {
@@ -35,15 +50,17 @@ class BaseWidgetRegister {
PageFactory.regist('index', (model) => MainPage(model));
PageFactory.regist('profile', (model) => MainPage(model));
PageFactory.regist('category', (model) => WalletPage());
PageFactory.regist('goods_details', (model) => GoodsDetailsPage(model));
// PageFactory.regist('login', (model) => LoginPage(model));
// PageFactory.regist('login_quick', (model) => LoginQuickPage(model));
// PageFactory.regist('login_account', (model) => LoginAccountPage(model));
// PageFactory.regist('login_invite', (model) => LoginInvitePage());

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_orders', (model) => OrdersPage(model));

}

// 注册控件
@@ -53,36 +70,56 @@ class BaseWidgetRegister {
WidgetFactory.regist('normal_nav', NormalNavCreater());

// ==================== 首页
// WidgetFactory.regist('index_title', NormalNavCreater());
// WidgetFactory.regist(
// 'index_search', DefaultWidgetCreater((model) => MineData()));
// /// 可滚动banner
// WidgetFactory.regist('index_title', NormalNavCreater());
/// 首页搜索栏
// WidgetFactory.regist('index_search', HomeSreachCreater());
// WidgetFactory.regist('index_search', DefaultWidgetCreater((model) => HomeSreachWidget(model)));
/// 可滚动banner
WidgetFactory.regist('index_carousel', HomeSlideBannerCreater());
WidgetFactory.regist('index_recommend_list', GoodsListCreater());
// /// 首页快速入口
WidgetFactory.regist(
'multi_nav', DefaultWidgetCreater((model) => HomeQuickEntry(model)));
//
// /// 不可以滚动banner

/// 首页快速入口
WidgetFactory.regist('multi_nav', DefaultWidgetCreater((model) => HomeQuickEntry(model)));

/// 滚动公告
WidgetFactory.regist('index_placard', DefaultWidgetCreater((model) => HomeNoticeWidget(model)));

/// 不可以滚动banner
WidgetFactory.regist('index_banner_one', HomeBannerCreater());
WidgetFactory.regist('index_banner_two', HomeBannerCreater());
WidgetFactory.regist('index_taobao_auth_tip', HomeAuthCreater());

/// ==================== 商品详情 ==================== ///
// 商品详情轮播图
WidgetFactory.regist('product_detail_carousel', DefaultWidgetCreater((model) => GoodsDetailsSlideBannerWidget(model)));
// 商品详情下载APP提示
WidgetFactory.regist('product_detail_download_tips', DefaultWidgetCreater((model) => UpgradeTipWidget(model)));
// 商品详情价格显示
WidgetFactory.regist('product_detail_price', DefaultWidgetCreater((model) => GoodsDetailsPriceWidget(model)));
// 商品详情标题
WidgetFactory.regist('product_detail_title', DefaultWidgetCreater((model) => GoodsDetailsTitleWidget(model)));
// 商品详情优惠劵
WidgetFactory.regist('product_detail_coupon', DefaultWidgetCreater((model) => CounponWidget(model)));
// 商品详情店铺
WidgetFactory.regist('product_detail_shop', DefaultWidgetCreater((model) => StoreWidget(model)));
// 商品详情宝贝评价
WidgetFactory.regist('product_detail_comment', DefaultWidgetCreater((model) => GoodsDetailsEvaluateWidget(model)));
// 商品详情图片
// WidgetFactory.regist('product_detail_img_list', MineNavCreater());
// 商品详情底部推荐列表
// WidgetFactory.regist('product_detail_bottom_rec', DefaultWidgetCreater((model) => GoodsDetailsEvaluateWidget(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_carousel',
DefaultWidgetCreater((model) => HomeBannerWidget(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(
@@ -90,8 +127,9 @@ class BaseWidgetRegister {
// WidgetFactory.regist(
// 'wallet_detail', DefaultWidgetCreater((model) => WalletDetail()));
WidgetFactory.regist('wallet_detail', HomeAuthCreater());
WidgetFactory.regist('wallet_data', DefaultWidgetCreater((model) => WalletData()));
WidgetFactory.regist('wallet_detail', DefaultWidgetCreater((model) => WalletDetail()));

WidgetFactory.regist(
'wallet_income', DefaultWidgetCreater((model) => WalletIncome()));
WidgetFactory.regist('wallet_income', DefaultWidgetCreater((model) => WalletIncome()));
}
}

+ 61
- 0
lib/widgets/goods_details/counpon_description/counpon_description_widget.dart View File

@@ -0,0 +1,61 @@
import 'package:flutter/material.dart';
import 'package:zhiying_comm/zhiying_comm.dart';

///
/// 优惠券说明
///
class CounponDescriptionWidget extends StatelessWidget {
final Map<String, dynamic> model;

const CounponDescriptionWidget(this.model);

@override
Widget build(BuildContext context) {
return Container(
margin: const EdgeInsets.symmetric(horizontal: 12.5),
width: double.infinity,
child:_getMainWidget(),
);
}

/// 主widget
Widget _getMainWidget() {
return Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[

/// 领券立减
Padding(padding: const EdgeInsets.only(right: 5), child: _getButtom1Widget()),


/// 收货后返现
Padding(padding: const EdgeInsets.only(right: 5), child: _getButtom2Widget()),


],
);
}

/// 领券立减
Widget _getButtom1Widget() {
return Container(
decoration: BoxDecoration(
color: HexColor.fromHex('#FFE0E0'),
borderRadius: BorderRadius.circular(50),
),
padding: const EdgeInsets.only(left: 14, right: 14, top: 3, bottom: 3),
child: Text('领券立减100元', style: TextStyle(color: HexColor.fromHex('#FF4242'), fontSize: 11)));
}


/// 收货后返现
Widget _getButtom2Widget() {
return Container(
decoration: BoxDecoration(
color: HexColor.fromHex('#FFEFDA'),
borderRadius: BorderRadius.circular(50),
),
padding: const EdgeInsets.only(left: 14, right: 14, top: 3, bottom: 3),
child: Text('收货后返现5.5元', style: TextStyle(color: HexColor.fromHex('#B78107'), fontSize: 11)));
}
}

+ 3
- 0
lib/widgets/goods_details/coupon/bloc/bloc.dart View File

@@ -0,0 +1,3 @@
export 'counpon_bloc.dart';
export 'counpon_event.dart';
export 'counpon_state.dart';

+ 30
- 0
lib/widgets/goods_details/coupon/bloc/counpon_bloc.dart View File

@@ -0,0 +1,30 @@
import 'dart:async';
import 'dart:math';

import 'package:bloc/bloc.dart';
import 'package:zhiying_base_widget/widgets/goods_details/coupon/bloc/counpon_repository.dart';
import 'bloc.dart';

class CounponBloc extends Bloc<CounponEvent, CounponState> {
@override
CounponState get initialState => CounponInitial();

CounponRepository repository;

CounponBloc({this.repository});

@override
Stream<CounponState> mapEventToState(
CounponEvent event,
) async* {
if (event is CounponInitEvent) {
yield* _mapInitEnvetTostate(event);
}
}

/// 获取数据
Stream<CounponState> _mapInitEnvetTostate(CounponInitEvent event) async* {
var result = await repository.fetchParentData(event);
yield CounponLoadedState(model: result);
}
}

+ 15
- 0
lib/widgets/goods_details/coupon/bloc/counpon_event.dart View File

@@ -0,0 +1,15 @@
import 'package:equatable/equatable.dart';

abstract class CounponEvent extends Equatable {
const CounponEvent();
}

/// 初始化请求
class CounponInitEvent extends CounponEvent {
final Map<String, dynamic> model;

const CounponInitEvent({this.model});

@override
List<Object> get props => [this.model];
}

+ 11
- 0
lib/widgets/goods_details/coupon/bloc/counpon_repository.dart View File

@@ -0,0 +1,11 @@
import 'package:zhiying_base_widget/widgets/goods_details/coupon/bloc/bloc.dart';
import 'package:zhiying_base_widget/widgets/goods_details/coupon/model/counpon_model.dart';

class CounponRepository {

/// 获取父页面传进来的数据
Future<CounponModel> fetchParentData(CounponInitEvent event) async{
return null;
}

}

+ 25
- 0
lib/widgets/goods_details/coupon/bloc/counpon_state.dart View File

@@ -0,0 +1,25 @@
import 'package:equatable/equatable.dart';
import 'package:zhiying_base_widget/widgets/goods_details/coupon/model/counpon_model.dart';

abstract class CounponState extends Equatable {
const CounponState();
}

class CounponInitial extends CounponState {
@override
List<Object> get props => [];
}

class CounponLoadedState extends CounponState {
CounponModel model;

CounponLoadedState({this.model});

@override
List<Object> get props => [this.model];
}

class CounponErrorState extends CounponState {
@override
List<Object> get props => [];
}

+ 26
- 0
lib/widgets/goods_details/coupon/counpon_sk.dart View File

@@ -0,0 +1,26 @@
import 'package:shimmer/shimmer.dart';
import 'package:flutter/material.dart';

class CounponSkeleton extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
margin: const EdgeInsets.only(left: 12.5, right: 12.5),
width: double.infinity,
height: 70,
child: _shimmerWidget(width: double.infinity, height: 65, radius: 7.5),
);
}

Widget _shimmerWidget({double width, double height, double radius = 0}) {
return Shimmer.fromColors(
baseColor: Colors.grey[300],
highlightColor: Colors.grey[100],
child: Container(
width: width,
height: height,
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(radius)),
),
);
}
}

+ 104
- 0
lib/widgets/goods_details/coupon/counpon_widget.dart View File

@@ -0,0 +1,104 @@
import 'package:flutter/material.dart';
import 'package:zhiying_base_widget/widgets/goods_details/coupon/bloc/bloc.dart';
import 'package:zhiying_base_widget/widgets/goods_details/coupon/bloc/counpon_repository.dart';
import 'package:zhiying_base_widget/widgets/goods_details/coupon/counpon_sk.dart';
import 'package:zhiying_base_widget/widgets/goods_details/coupon/model/counpon_model.dart';
import 'package:zhiying_comm/zhiying_comm.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

///
/// 优惠券widget
///
class CounponWidget extends StatelessWidget {
final Map<String, dynamic> model;

const CounponWidget(this.model);

@override
Widget build(BuildContext context) {
return Container();
// return BlocProvider<CounponBloc>(
// create: (_) => CounponBloc(repository: CounponRepository())..add(CounponInitEvent(model: model)),
// child: CounponContainer(),
// );
}
}

class CounponContainer extends StatefulWidget {
@override
_CounponContainerState createState() => _CounponContainerState();
}

class _CounponContainerState extends State<CounponContainer> {
/// 点击领取
void _onJump(CounponModel model) {}

@override
Widget build(BuildContext context) {
BlocConsumer<CounponBloc, CounponState>(
listener: (context, state) {},
buildWhen: (prev, current) {
if (current is CounponErrorState) {
return false;
}
return true;
},
builder: (context, state) {
if (state is CounponLoadedState) {
// return _getMainWdiget(state.model);
}
// return CounponSkeleton();
return Container();
},
);
}

/// 主视图
Widget _getMainWdiget(CounponModel model) {
return GestureDetector(
onTap: () => _onJump(model),
behavior: HitTestBehavior.opaque,
child: Container(
width: double.infinity,
margin: const EdgeInsets.only(left: 12.5, right: 12.5),
padding: const EdgeInsets.only(left: 18.5),
alignment: Alignment.centerLeft,
child: Row(
children: <Widget>[
/// 价格
_getPriceWidget(model),
const SizedBox(width: 7.5),
/// 有效期
_getTimeWidget(model)
],
),
),
);
}

/// 价格
Widget _getPriceWidget(CounponModel model) {
return Row(
children: <Widget>[
/// 价格类型
Text('¥', style: TextStyle(fontSize: 15, color: HexColor.fromHex('#FFFFFF'))),

/// 价格
Text('100', style: TextStyle(fontSize: 30, color: HexColor.fromHex('#FFFFFF'))),
],
);
}

/// 名称与有效期
Widget _getTimeWidget(CounponModel model) {
return Column(
children: <Widget>[
/// 标题
Text('优惠券', style: TextStyle(fontSize: 17, color: HexColor.fromHex('#FFFFFF'))),

/// 到期时间
Text('有效期至2020-10-01', style: TextStyle(fontSize: 10, color: HexColor.fromHex('#FFFFFF')))
],
);
}
}

+ 2
- 0
lib/widgets/goods_details/coupon/model/counpon_model.dart View File

@@ -0,0 +1,2 @@

class CounponModel{}

+ 27
- 0
lib/widgets/goods_details/evaluate/godds_details_evaluate_sk.dart View File

@@ -0,0 +1,27 @@
import 'package:shimmer/shimmer.dart';
import 'package:flutter/material.dart';

///
/// 商品详情评论骨架屏幕
///
class GoodsDetailsEvaluateSkeleton extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container();
}


Widget _shimmerWidget({double width, double height, double radius = 0}) {
return Shimmer.fromColors(
baseColor: Colors.grey[300],
highlightColor: Colors.grey[100],
child: Container(
width: width,
height: height,
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(radius)),
),
);
}
}



+ 38
- 0
lib/widgets/goods_details/evaluate/goods_details_evaluate_widget.dart View File

@@ -0,0 +1,38 @@
import 'package:flutter/material.dart';
import 'package:zhiying_comm/zhiying_comm.dart';

///
/// 商品详情评价Widget
///
class GoodsDetailsEvaluateWidget extends StatelessWidget {
final Map<String, dynamic> model;

const GoodsDetailsEvaluateWidget(this.model);

/// 点击查看更多
void _openLookMore() {}

@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () => _openLookMore(),
behavior: HitTestBehavior.opaque,
child: Container(
width: double.infinity,
padding: const EdgeInsets.only(top: 15, bottom: 15, left: 12.5, right: 12.5),
child: getMainWidget(),
),
);
}

/// 评价以及查看更多
Widget getMainWidget() {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text('宝贝评价', style: TextStyle(color: HexColor.fromHex('#333333'), fontSize: 12)),
Text('查看更多 >', style: TextStyle(color: HexColor.fromHex('#999999'), fontSize: 11)),
],
);
}
}

+ 38
- 0
lib/widgets/goods_details/footer/goods_details_footer_sk.dart View File

@@ -0,0 +1,38 @@
import 'package:shimmer/shimmer.dart';
import 'package:flutter/material.dart';

class GoodsDetailsFooterSkeleton extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
width: double.infinity,
padding: const EdgeInsets.only(left: 21, right: 12.5, top: 12.5, bottom: 12.5),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Row(
children: <Widget>[
_shimmerWidget(width: 30, height: 30,),
const SizedBox(width: 35),
_shimmerWidget(width: 30, height: 30,),
],
),

_shimmerWidget( height: 44, width: 230, radius: 22),
],
),
);
}

Widget _shimmerWidget({double width, double height, double radius = 0}) {
return Shimmer.fromColors(
baseColor: Colors.grey[300],
highlightColor: Colors.grey[100],
child: Container(
width: width,
height: height,
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(radius)),
),
);
}
}

+ 169
- 0
lib/widgets/goods_details/footer/goods_details_footer_widget.dart View File

@@ -0,0 +1,169 @@
import 'package:flutter/material.dart';
import 'package:zhiying_comm/zhiying_comm.dart';

///
/// 商品详情底部Widget
///
class GoodsDetailsFooterWidget extends StatelessWidget {

final Map<String, dynamic> model;

const GoodsDetailsFooterWidget(this.model);

@override
Widget build(BuildContext context) {
return GooddsDetailsFooterContainer();
}
}

class GooddsDetailsFooterContainer extends StatefulWidget {
@override
_GooddsDetailsFooterContainerState createState() => _GooddsDetailsFooterContainerState();
}

class _GooddsDetailsFooterContainerState extends State<GooddsDetailsFooterContainer> {
/// 打开首页
void _openHome() {}

/// 收藏
void _collectOnClick() {}

/// 分享
void _shareOnClick() {}

/// 自购省
void _savemoneyOnClick() {}

@override
Widget build(BuildContext context) {
return Container(
height: 70,
width: double.infinity,
padding: const EdgeInsets.only(bottom: 10, top: 12.5, left: 21, right: 12.5),
decoration: BoxDecoration(
boxShadow:[
BoxShadow(color: Colors.grey[300], offset: Offset(0.0, 0.0), blurRadius: 5.0, spreadRadius: 2.0),
BoxShadow(color: Colors.grey[300], offset: Offset(0.0, 0.0)),
],
color: Colors.white
),
child: _getMainWidet(),
);
}

/// 主Widget
Widget _getMainWidet() {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
/// 首页与收藏
_getLeftWidget(),

/// 分享赚与自购省
_getRightWidget(),
],
);
}

/// 首页 和 收藏
Widget _getLeftWidget() {
return Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () => _openHome(),
child: Padding(
padding: const EdgeInsets.only(right: 35),
child: _getCustomWidget('首页', '999999', null),
)),
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () => _collectOnClick(),
child: Padding(padding: const EdgeInsets.only(right: 0), child: _getCustomWidget('收藏', '999999', null)))
],
);
}

/// 分享赚与自购省
Widget _getRightWidget() {
return Row(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[_getFxzButton(), _getZgsButton()],
);
}

/// 分享赚,
Widget _getFxzButton() {
return GestureDetector(
onTap: () => _shareOnClick(),
child: Container(
alignment: Alignment.center,
padding: const EdgeInsets.only(left: 30, right: 30, top: 5, bottom: 5),
decoration: BoxDecoration(
gradient: LinearGradient(colors: [HexColor.fromHex('#FFCA66'), HexColor.fromHex('#FFD961')], begin: Alignment.centerLeft, end: Alignment.centerRight),
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(25),
topLeft: Radius.circular(25)
)
),
child: Column(
children: <Widget>[
RichText(
text: TextSpan(text: '¥', style: TextStyle(fontSize: 12, color: HexColor.fromHex('FFFFFF')), children: [
TextSpan(text: '3.10', style: TextStyle(fontSize: 15, color: HexColor.fromHex('#FFFFFF'))),
]),
),
Text('分享赚', style: TextStyle(color: HexColor.fromHex('#FFFFFF'), fontSize: 15))
],
),
),
);
}

/// 自购省
Widget _getZgsButton() {
return GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () => _savemoneyOnClick(),
child: Container(
alignment: Alignment.center,
padding: const EdgeInsets.only(left: 30, right: 30, top: 5, bottom: 5),
decoration: BoxDecoration(
gradient: LinearGradient(colors: [HexColor.fromHex('#FF6969'), HexColor.fromHex('#FF4646')], begin: Alignment.centerLeft, end: Alignment.centerRight),
borderRadius: BorderRadius.only(
bottomRight: Radius.circular(25),
topRight: Radius.circular(25)
)
),
child: Column(
children: <Widget>[
RichText(
text: TextSpan(text: '¥', style: TextStyle(fontSize: 12, color: HexColor.fromHex('FFFFFF')), children: [
TextSpan(text: '23.10', style: TextStyle(fontSize: 15, color: HexColor.fromHex('#FFFFFF'))),
]),
),
Text('自购省', style: TextStyle(color: HexColor.fromHex('#FFFFFF'), fontSize: 15))
],
),
),
);
}

Widget _getCustomWidget(String text, String textColor, String icon) {
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
/// 图标
Container(height: 25, width: 25, color: Colors.red, margin: const EdgeInsets.only(bottom: 3)),

/// 图片
Text(text, style: TextStyle(color: HexColor.fromHex(textColor), fontSize: 11))
],
);
}
}

+ 83
- 0
lib/widgets/goods_details/price/goods_details_price_widget.dart View File

@@ -0,0 +1,83 @@
import 'package:flutter/material.dart';
import 'package:zhiying_comm/zhiying_comm.dart';

///
/// 商品详情价格widget
///
class GoodsDetailsPriceWidget extends StatelessWidget {
final Map<String, dynamic> model;

const GoodsDetailsPriceWidget(this.model);

@override
Widget build(BuildContext context) {
return Container(margin: const EdgeInsets.symmetric(horizontal: 12.5), child: _getMainWidget());
}

/// 主体视图
Widget _getMainWidget() {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
_getLeftWidget(),

/// 右边widget
_getBuyNumberWidget(),
],
);
}

/// 左边的wiget 包括价格等
Widget _getLeftWidget() {
return Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
/// 价格
_getPriceWidget(),
const SizedBox(width: 5),

/// 券后
_getQhPriceWidget(),
const SizedBox(width: 5),

/// 积分
_getPointsWidget()
],
);
}

/// 价格
Widget _getPriceWidget() {
return Row(
children: <Widget>[
Text('¥', style: TextStyle(color: HexColor.fromHex('#FF4242'), fontSize: 15)),
Text('99', style: TextStyle(color: HexColor.fromHex('#FF4242'), fontSize: 30)),
],
);
}

/// 积分
Widget _getPointsWidget() {
return Container(
decoration: BoxDecoration(color: HexColor.fromHex('#FFEFDA'), borderRadius: BorderRadius.circular(5)),
padding: const EdgeInsets.only(left: 4, right: 7.5, top: 4, bottom: 4),
child: Text('', style: TextStyle(color: HexColor.fromHex('#B78107'), fontSize: 9)),
);
}

/// 券后价格
Widget _getQhPriceWidget() {
return Column(
children: <Widget>[
Text('券后', style: TextStyle(color: HexColor.fromHex('#FF4242'), fontSize: 11)),
Text('¥ 199', style: TextStyle(color: HexColor.fromHex('#FF4242'), fontSize: 10)),
],
);
}

/// 购买人数
Widget _getBuyNumberWidget() {
return Text('99999人已购买', style: TextStyle(color: HexColor.fromHex('#999999'), fontSize: 12.5));
}
}

+ 46
- 0
lib/widgets/goods_details/slide_banner/bloc/goods_details_slide_banner_bloc.dart View File

@@ -0,0 +1,46 @@
import 'dart:async';
import 'dart:math';

import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter/cupertino.dart';
import 'package:zhiying_base_widget/widgets/goods_details/slide_banner/bloc/goods_details_slide_banner_repository.dart';
import 'package:zhiying_base_widget/widgets/goods_details/slide_banner/model/goods_details_silde_banner_model.dart';
import 'package:zhiying_comm/util/empty_util.dart';

part 'goods_details_slide_banner_event.dart';

part 'goods_details_slide_banner_state.dart';

class GoodsDetailsSlideBannerBloc extends Bloc<GoodsDetailsSlideBannerEvent, GoodsDetailsSlideBannerState> {
GoodsDetailsSlideBannerRepository repository;

GoodsDetailsSlideBannerBloc({@required this.repository});

@override
GoodsDetailsSlideBannerState get initialState => GoodsDetailsSlideBannerInitial();

@override
Stream<GoodsDetailsSlideBannerState> mapEventToState(
GoodsDetailsSlideBannerEvent event,
) async* {
/// 初始化
if (event is GoodsDetailsSlideBannerInitEvent) {
yield* _mapInitEventToState(event);
}
}

/// 初始化
Stream<GoodsDetailsSlideBannerState> _mapInitEventToState(GoodsDetailsSlideBannerInitEvent event) async* {
var parentData = await repository.fetchParentData(event.model);
if (!EmptyUtil.isEmpty(parentData)) {
yield GoodsDetailsSlideBannerLoadedState(model: parentData);
return;
}
var netData = await repository.fetchNetData(event.model);
if (!EmptyUtil.isEmpty(netData))
yield GoodsDetailsSlideBannerLoadedState(model: parentData);
else
yield GoodsDetailsSlideBannerErrorState();
}
}

+ 15
- 0
lib/widgets/goods_details/slide_banner/bloc/goods_details_slide_banner_event.dart View File

@@ -0,0 +1,15 @@
part of 'goods_details_slide_banner_bloc.dart';

abstract class GoodsDetailsSlideBannerEvent extends Equatable {
const GoodsDetailsSlideBannerEvent();
}

/// 初始化事件
class GoodsDetailsSlideBannerInitEvent extends GoodsDetailsSlideBannerEvent {
final Map<String, dynamic> model;

const GoodsDetailsSlideBannerInitEvent({@required this.model});

@override
List<Object> get props => [this.model];
}

+ 21
- 0
lib/widgets/goods_details/slide_banner/bloc/goods_details_slide_banner_repository.dart View File

@@ -0,0 +1,21 @@
import 'package:zhiying_base_widget/widgets/goods_details/slide_banner/model/goods_details_silde_banner_model.dart';
import 'package:zhiying_comm/zhiying_comm.dart';

class GoodsDetailsSlideBannerRepository {
/// 加载父页面数据
Future<GoodsDetailsSlideBannerModel> fetchParentData(final Map<String, dynamic> model) async {
if (!EmptyUtil.isEmpty(model)) {
try {
return GoodsDetailsSlideBannerModel.fromJson(model['data']);
} catch (e) {
Logger.log(e);
}
}
return null;
}

/// 加载网络数据
Future<GoodsDetailsSlideBannerModel> fetchNetData(final Map<String, dynamic> model) async {
return null;
}
}

+ 26
- 0
lib/widgets/goods_details/slide_banner/bloc/goods_details_slide_banner_state.dart View File

@@ -0,0 +1,26 @@
part of 'goods_details_slide_banner_bloc.dart';

abstract class GoodsDetailsSlideBannerState extends Equatable {
const GoodsDetailsSlideBannerState();
}

class GoodsDetailsSlideBannerInitial extends GoodsDetailsSlideBannerState {
@override
List<Object> get props => [];
}

/// 数据加载成功
class GoodsDetailsSlideBannerLoadedState extends GoodsDetailsSlideBannerState {
GoodsDetailsSlideBannerModel model;

GoodsDetailsSlideBannerLoadedState({this.model});

@override
List<Object> get props => [this.model];
}

/// 数据加载失败
class GoodsDetailsSlideBannerErrorState extends GoodsDetailsSlideBannerState {
@override
List<Object> get props => [];
}

+ 19
- 0
lib/widgets/goods_details/slide_banner/goods_details_slide_banner_creater.dart View File

@@ -0,0 +1,19 @@
import 'package:flutter/material.dart';
import 'package:zhiying_base_widget/widgets/goods_details/slide_banner/goods_details_slide_banner_sk.dart';
import 'package:zhiying_base_widget/widgets/goods_details/slide_banner/goods_details_slide_banner_widget.dart';
import 'package:zhiying_comm/zhiying_comm.dart';

///
/// 可以滚动Banner
///
class HomeSlideBannerCreater extends WidgetCreater {
@override
List<Widget> createSkeleton(Map<String, dynamic> model) {
return [GoodsDetailsSlideBannerSkeleton()];
}

@override
List<Widget> createWidgets(Map<String, dynamic> model) {
return [GoodsDetailsSlideBannerWidget(model)];
}
}

+ 21
- 0
lib/widgets/goods_details/slide_banner/goods_details_slide_banner_sk.dart View File

@@ -0,0 +1,21 @@
import 'package:flutter/material.dart';
import 'package:shimmer/shimmer.dart';

class GoodsDetailsSlideBannerSkeleton extends StatelessWidget {
@override
Widget build(BuildContext context) {
return _shimmerWidget(width: double.infinity, height: 375);
}

Widget _shimmerWidget({double width, double height, double radius = 0}) {
return Shimmer.fromColors(
baseColor: Colors.grey[300],
highlightColor: Colors.grey[100],
child: Container(
width: width,
height: height,
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(radius)),
),
);
}
}

+ 172
- 0
lib/widgets/goods_details/slide_banner/goods_details_slide_banner_widget.dart View File

@@ -0,0 +1,172 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_swiper/flutter_swiper.dart';
import 'package:zhiying_base_widget/widgets/goods_details/slide_banner/bloc/goods_details_slide_banner_bloc.dart';
import 'package:zhiying_base_widget/widgets/goods_details/slide_banner/bloc/goods_details_slide_banner_repository.dart';
import 'package:zhiying_base_widget/widgets/goods_details/slide_banner/goods_details_slide_banner_sk.dart';
import 'package:zhiying_base_widget/widgets/goods_details/slide_banner/model/goods_details_silde_banner_model.dart';
import 'package:zhiying_comm/zhiying_comm.dart';
import 'package:cached_network_image/cached_network_image.dart';

///
/// 商品详情轮播图
///
class GoodsDetailsSlideBannerWidget extends StatelessWidget {
final Map<String, dynamic> model;

const GoodsDetailsSlideBannerWidget(this.model, {Key key}) : super(key: key);

@override
Widget build(BuildContext context) {
return BlocProvider<GoodsDetailsSlideBannerBloc>(
create: (_) => GoodsDetailsSlideBannerBloc(repository: GoodsDetailsSlideBannerRepository())..add(GoodsDetailsSlideBannerInitEvent(model: model)),
child: GoodsDetailsSlideBannerContainer(model),
);
}
}

class GoodsDetailsSlideBannerContainer extends StatefulWidget {
final Map<String, dynamic> model;

const GoodsDetailsSlideBannerContainer(this.model, {Key key}) : super(key: key);

@override
_GoodsDetailsSlideBannerContainerState createState() => _GoodsDetailsSlideBannerContainerState();
}

class _GoodsDetailsSlideBannerContainerState extends State<GoodsDetailsSlideBannerContainer> {
/// 子元素点击事件
void _itemOnClick(IndexCarousel model) {
print('点击了 $model');
}

@override
Widget build(BuildContext context) {
return BlocConsumer<GoodsDetailsSlideBannerBloc, GoodsDetailsSlideBannerState>(
listener: (BuildContext context, GoodsDetailsSlideBannerState state) {
if (state is GoodsDetailsSlideBannerErrorState) {
print('数据加载出错');
}
},
buildWhen: (previous, current) {
/// 数据加载出错不进行build
if (current is GoodsDetailsSlideBannerErrorState) {
return false;
}
return true;
},
builder: (context, state) {
print('currente state = $state');
if (state is GoodsDetailsSlideBannerLoadedState) {
if (!EmptyUtil.isEmpty(state.model) && !EmptyUtil.isEmpty(state.model.index_carousel_list)) {
return _getMainWidget(state.model);
}
}
// 骨架屏
return GoodsDetailsSlideBannerSkeleton();
},
);
}

/// 页面
Widget _getMainWidget(GoodsDetailsSlideBannerModel datas) {
return Container(
width: double.infinity,
height: 375,
child: Swiper(
itemBuilder: (BuildContext context, int index) {
IndexCarousel items = datas.index_carousel_list[index];
return Container(
width: double.infinity,
child: CachedNetworkImage(imageUrl: items?.img ?? '', fit: BoxFit.cover),
);
},
itemCount: datas?.index_carousel_list?.length ?? 0,
loop: true,
autoplay: true,
onTap: (index) => _itemOnClick(datas.index_carousel_list[index]),
pagination: _getSwiperStyleByType(datas, datas?.index_carousel_list?.length ?? 0),
),
);
}

/// 获取进度样式
SwiperPlugin _getSwiperStyleByType(GoodsDetailsSlideBannerModel model, int pageCount) {
if ('1' != model.pagination_open) {
return null;
}

if ('type_number' == model.pagination) {
return _getNumswiperPlugin(pageCount, model.pagination_select_color, model.pagination_unselect_color);
}
if ('type_point' == model.pagination) {
return _swiperCustomPaginationDito(pageCount, model.pagination_select_color, model.pagination_unselect_color);
}
if ('type_bar' == model.pagination) {
return _swiperCustomPagination(pageCount, model.pagination_select_color, model.pagination_unselect_color);
}
return null;
}

/// 数字样式
SwiperPlugin _getNumswiperPlugin(int pageCount, String selectColor, String unselectColor) {
return SwiperCustomPagination(builder: (BuildContext context, SwiperPluginConfig config) {
return Align(
alignment: Alignment(0.0, 0.9),
child: Container(
padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 18),
decoration: BoxDecoration(borderRadius: BorderRadius.circular(13), color: HexColor.fromHex('#4D000000')),
child: RichText(
text: TextSpan(text: '${config.activeIndex + 1}', style: TextStyle(fontSize: 12, color: HexColor.fromHex(selectColor)), children: [
TextSpan(text: '/', style: TextStyle(fontSize: 12, color: HexColor.fromHex(unselectColor))),
TextSpan(text: '$pageCount', style: TextStyle(fontSize: 12, color: HexColor.fromHex(unselectColor))),
]),
)),
);
});
}

/// 自定义进度条
SwiperPlugin _swiperCustomPagination(int pageCount, String selectColor, String unselectColor) {
List list = [];
for (int i = 0; i < pageCount; i++) {
list.add(i);
}

return SwiperCustomPagination(builder: (BuildContext context, SwiperPluginConfig config) {
return Align(
alignment: Alignment(0.0, 0.9),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: list.map((index) {
var borderRadius;
if (index == 0) {
borderRadius = BorderRadius.only(topLeft: Radius.circular(2), bottomLeft: Radius.circular(2));
}
if (index == list.length - 1) {
borderRadius = BorderRadius.only(topRight: Radius.circular(2), bottomRight: Radius.circular(2));
}

if (index == config.activeIndex) {
borderRadius = BorderRadius.all(Radius.circular(2));
}

return Container(
height: 4,
width: 25,
decoration: BoxDecoration(borderRadius: borderRadius, color: index == config.activeIndex ? HexColor.fromHex(selectColor) : HexColor.fromHex(unselectColor)),
);
}).toList(),
),
);
});
}

/// 圆形进度条
SwiperPlugin _swiperCustomPaginationDito(int pageCount, String selectColor, String unselectColor) {
return SwiperPagination(
margin: const EdgeInsets.only(),
builder: DotSwiperPaginationBuilder(color: HexColor.fromHex(unselectColor), activeColor: HexColor.fromHex(selectColor), size: 8, activeSize: 8));
}
}

+ 61
- 0
lib/widgets/goods_details/slide_banner/model/goods_details_silde_banner_model.dart View File

@@ -0,0 +1,61 @@


class GoodsDetailsSlideBannerModel {
String pagination;
String pagination_open;
List<String> pagination_options;
List<IndexCarousel> index_carousel_list;
String pagination_select_color;
String pagination_unselect_color;

GoodsDetailsSlideBannerModel({this.pagination, this.pagination_open, this.pagination_options, this.pagination_select_color, this.pagination_unselect_color, this.index_carousel_list});

factory GoodsDetailsSlideBannerModel.fromJson(Map<String, dynamic> json) {
return GoodsDetailsSlideBannerModel(
pagination: json['pagination'],
pagination_open: json['pagination_open'],
pagination_options: json['pagination_options'] != null ? new List<String>.from(json['pagination_options']) : null,
index_carousel_list: json['index_carousel_list'] != null ? (json['index_carousel_list'] as List).map((i) => IndexCarousel.fromJson(i)).toList() : null,
pagination_select_color: json['pagination_select_color'],
pagination_unselect_color: json['pagination_unselect_color'],

);
}

Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['pagination'] = this.pagination;
data['pagination_open'] = this.pagination_open;
data['pagination_select_color'] = this.pagination_select_color;
data['pagination_unselect_color'] = this.pagination_unselect_color;
if (this.pagination_options != null) {
data['pagination_options'] = this.pagination_options;
}
if (this.index_carousel_list != null) {
data['index_carousel_list'] = this.index_carousel_list.map((v) => v.toJson()).toList();
}
return data;
}
}


class IndexCarousel {
String img;
String skip_identifier;

IndexCarousel({this.img, this.skip_identifier});

factory IndexCarousel.fromJson(Map<String, dynamic> json) {
return IndexCarousel(
img: json['img'],
skip_identifier: json['skip_identifier'],
);
}

Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['img'] = this.img;
data['skip_identifier'] = this.skip_identifier;
return data;
}
}

+ 4
- 0
lib/widgets/goods_details/store/bloc/bloc.dart View File

@@ -0,0 +1,4 @@

export 'store_bloc.dart';
export 'store_event.dart';
export 'store_state.dart';

+ 43
- 0
lib/widgets/goods_details/store/bloc/store_bloc.dart View File

@@ -0,0 +1,43 @@
import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:zhiying_base_widget/widgets/goods_details/store/bloc/store_repository.dart';
import 'package:zhiying_comm/util/empty_util.dart'
'';

import 'bloc.dart';

class StoreBloc extends Bloc<StoreEvent, StoreState> {
StoreRepository repository;

StoreBloc({this.repository});

@override
StoreState get initialState => StoreInitial();

@override
Stream<StoreState> mapEventToState(
StoreEvent event,
) async* {

/// 初始化
if(event is StoreInitEvent){
yield* _mapInitEventToState(event);
}
}


/// 获取数据
Stream<StoreState> _mapInitEventToState(StoreInitEvent event) async*{
var result = await repository.fetchParentData(event);
if(!EmptyUtil.isEmpty(result)){
yield StoreLoadedState(model: result);
return;
}
var net = await repository.fetchNetData(event);
if(!EmptyUtil.isEmpty(net))
yield StoreLoadedState(model: result);
else
yield StoreErrorState();
}

}

+ 11
- 0
lib/widgets/goods_details/store/bloc/store_event.dart View File

@@ -0,0 +1,11 @@
import 'package:equatable/equatable.dart';

abstract class StoreEvent extends Equatable {
const StoreEvent();
}

/// 初始化事件
class StoreInitEvent extends StoreEvent {
@override
List<Object> get props => [];
}

+ 10
- 0
lib/widgets/goods_details/store/bloc/store_repository.dart View File

@@ -0,0 +1,10 @@
import 'package:zhiying_base_widget/widgets/goods_details/store/bloc/bloc.dart';
import 'package:zhiying_base_widget/widgets/goods_details/store/model/store_model.dart';

class StoreRepository {
/// 获取上级数据
Future<StoreModel> fetchParentData(StoreInitEvent event) async {}

/// 网络数据
Future<StoreModel> fetchNetData(StoreInitEvent event) async {}
}

+ 27
- 0
lib/widgets/goods_details/store/bloc/store_state.dart View File

@@ -0,0 +1,27 @@
import 'package:equatable/equatable.dart';
import 'package:zhiying_base_widget/widgets/goods_details/store/model/store_model.dart';

abstract class StoreState extends Equatable {
const StoreState();
}

class StoreInitial extends StoreState {
@override
List<Object> get props => [];
}

/// 数据加载完毕
class StoreLoadedState extends StoreState {

final StoreModel model;
const StoreLoadedState({this.model});

@override
List<Object> get props => [];
}

/// 数据加载出错
class StoreErrorState extends StoreState {
@override
List<Object> get props => [];
}

+ 3
- 0
lib/widgets/goods_details/store/model/store_model.dart View File

@@ -0,0 +1,3 @@


class StoreModel{}

+ 44
- 0
lib/widgets/goods_details/store/store_sk.dart View File

@@ -0,0 +1,44 @@
import 'package:shimmer/shimmer.dart';
import 'package:flutter/material.dart';

class StoreSkeleton extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
height: 50,
width: double.infinity,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[

/// 图片
_shimmerWidget(width: 50, height: 50),

///
Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[

_shimmerWidget(width: 150, height: 20),
_shimmerWidget(width: 50, height: 15)

],
),

],
),
);
}

Widget _shimmerWidget({double width, double height, double radius = 0}) {
return Shimmer.fromColors(
baseColor: Colors.grey[300],
highlightColor: Colors.grey[100],
child: Container(
width: width,
height: height,
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(radius)),
),
);
}
}

+ 147
- 0
lib/widgets/goods_details/store/store_widget.dart View File

@@ -0,0 +1,147 @@
import 'package:flutter/material.dart';
import 'package:zhiying_base_widget/widgets/goods_details/store/bloc/bloc.dart';
import 'package:zhiying_base_widget/widgets/goods_details/store/bloc/store_repository.dart';
import 'package:zhiying_base_widget/widgets/goods_details/store/model/store_model.dart';
import 'package:zhiying_comm/zhiying_comm.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

import 'store_sk.dart';

///
/// 商家widget
///
class StoreWidget extends StatelessWidget {
final Map<String, dynamic> model;

const StoreWidget(this.model);

@override
Widget build(BuildContext context) {
return BlocProvider<StoreBloc>(
create: (_) => StoreBloc(repository: StoreRepository())..add(StoreInitEvent()),
child: StoreContainer(),
);
}
}

class StoreContainer extends StatefulWidget {
@override
_StoreContainerState createState() => _StoreContainerState();
}

class _StoreContainerState extends State<StoreContainer> {

/// 点击更多
void _onMoreClick(){

}

/// 点击商家
void _onStoreClick(){

}

@override
Widget build(BuildContext context) {
return BlocConsumer<StoreBloc, StoreState>(
listener: (context, state) {},
buildWhen: (prev, current) {
if (current is StoreErrorState) {
return false;
}
return true;
},
builder: (context, state) {
if (state is StoreLoadedState) {
return _getMianWidget(state.model);
}
return StoreSkeleton();
},
);
}

/// 主视图
Widget _getMianWidget(StoreModel model) {
return Container(
margin: const EdgeInsets.only(left: 12.5, right: 12.5),
child: Row(
children: <Widget>[
/// 商家图片
_getStoreImgWidget(model),

Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
/// 商店名称与更多
_getStoreNameWidget(model),

/// 评分描述
_getEvaluateWidget(model),
],
),
),
],
),
);
}

/// 商家图片
Widget _getStoreImgWidget(StoreModel model) {
return Container(
width: 50,
height: 50,
color: Colors.red,
);
}

/// 商店名称
Widget _getStoreNameWidget(StoreModel model) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
/// 商店名称
Text(
'品胜京东自营旗舰店',
style: TextStyle(color: HexColor.fromHex('#333333'), fontSize: 13),
),

/// 更多
Text(
'更多店铺优惠 >',
style: TextStyle(color: HexColor.fromHex('#FF4242'), fontSize: 11),
),
],
);
}

/// 评分描述
Widget _getEvaluateWidget(StoreModel model) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
/// 宝贝描述 5.0
_getCoustomWidet('宝贝描述 5.0', '#999999', ''),

/// 物流服务 5.0
_getCoustomWidet('宝贝描述 5.0', '#999999', ''),

/// 服务态度 1.0
_getCoustomWidet('宝贝描述 5.0', '#999999', ''),
],
);
}

Widget _getCoustomWidet(String text, String textColor, String icon) {
return Row(
children: <Widget>[
Text(text, style: TextStyle(fontSize: 11, color: HexColor.fromHex(textColor))),
Container(
width: 12,
height: 12,
color: Colors.red,
),
],
);
}
}

+ 48
- 0
lib/widgets/goods_details/title/goods_details_title_widget.dart View File

@@ -0,0 +1,48 @@
import 'package:flutter/material.dart';
import 'package:zhiying_comm/zhiying_comm.dart';

///
/// 商品详情标题
///
class GoodsDetailsTitleWidget extends StatelessWidget {
final Map<String, dynamic> model;

const GoodsDetailsTitleWidget(this.model);

@override
Widget build(BuildContext context) {
return Container(
width: double.infinity,
margin: const EdgeInsets.only(left: 12.5, right: 12.5),
child: _getMaiWidget(),
);
}

/// 主widget
Widget _getMaiWidget() {
return RichText(
maxLines: 2,
overflow: TextOverflow.ellipsis,
text: TextSpan(children: [
WidgetSpan(
child: _getGoodsTypeIcon(),
),
_getGoodsTitle(),
]),
);
}

/// 商品类型图标
Widget _getGoodsTypeIcon() {
return Container(
height: 15,
width: 32,
color: Colors.red,
);
}

/// 商品标题
InlineSpan _getGoodsTitle() {
return TextSpan(text: '品胜(PISEN)苹果数据线1.5米 适用于苹果手机所有机型 MFI认证安全稳定一年换新1.5米2米', style: TextStyle(fontSize: 14, color: HexColor.fromHex('#FF333333')));
}
}

+ 3
- 0
lib/widgets/goods_details/upgrade_tip/model/upgrade_tip_model.dart View File

@@ -0,0 +1,3 @@

class UpgradeTipModel{}


+ 27
- 0
lib/widgets/goods_details/upgrade_tip/upgrade_tip_sk.dart View File

@@ -0,0 +1,27 @@

import 'package:shimmer/shimmer.dart';
import 'package:flutter/material.dart';

class UpgradeTipSkeleton extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
margin: const EdgeInsets.symmetric(horizontal: 12.5),
height: 35,
child: _shimmerWidget(width: double.infinity, height: double.infinity, radius: 20),
);
}

Widget _shimmerWidget({double width, double height, double radius = 0}) {
return Shimmer.fromColors(
baseColor: Colors.grey[300],
highlightColor: Colors.grey[100],
child: Container(
width: width,
height: height,
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(radius)),
),
);
}
}


+ 57
- 0
lib/widgets/goods_details/upgrade_tip/upgrade_tip_widget.dart View File

@@ -0,0 +1,57 @@
import 'package:flutter/material.dart';
import 'package:zhiying_base_widget/widgets/goods_details/upgrade_tip/model/upgrade_tip_model.dart';
import 'package:zhiying_comm/zhiying_comm.dart';

///
/// 更新提示widget
///
class UpgradeTipWidget extends StatelessWidget {
final Map<String, dynamic> model;

const UpgradeTipWidget(this.model);

@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
color: HexColor.fromHex('#FFEFDA'),
borderRadius: BorderRadius.circular(30),
),
padding: const EdgeInsets.only(left: 10, right: 13, top: 10, bottom: 10),
margin: const EdgeInsets.symmetric(horizontal: 12.5),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
_geLeftWidget(null),
_getRightWidget(null),
],
),
);
}

/// 左边的视图
Widget _geLeftWidget(UpgradeTipModel model) {
return Row(
children: <Widget>[
/// 图标
Container(width: 15, height: 15, color: Colors.red),

const SizedBox(width: 7.5),

/// 文字
Text('下载APP升级运营商,享受更多收益', style: TextStyle(color: HexColor.fromHex('#C09023'), fontSize: 11))
],
);
}

/// 右边的视图
Widget _getRightWidget(UpgradeTipModel model) {
return Row(
children: <Widget>[
Text('前往下载', style: TextStyle(color: HexColor.fromHex('#C09023'), fontSize: 11)),
const SizedBox(width: 4),
Text('》', style: TextStyle(color: HexColor.fromHex('#C09023'), fontSize: 11))
],
);
}
}

+ 9
- 0
lib/widgets/home/home_ai_dialog/home_ai_dialog.dart View File

@@ -0,0 +1,9 @@
import 'package:flutter/material.dart';


class HomeAiDialog extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container();
}
}

+ 1
- 0
lib/widgets/home/home_banner/home_banner_widget.dart View File

@@ -45,6 +45,7 @@ class _HomeBannerContainerState extends State<HomeBannerContainer> {
/// 点击事件
void _itemOnClick(HomeBannerListItemModel model){
print('${model?.skip_identifier}');
RouterUtil.route(model.toJson(), context);
}

@override


+ 3
- 0
lib/widgets/home/home_notice/bloc/bloc.dart View File

@@ -0,0 +1,3 @@
export 'home_notice_bloc.dart';
export 'home_notice_event.dart';
export 'home_notice_state.dart';

+ 32
- 0
lib/widgets/home/home_notice/bloc/home_notice_bloc.dart View File

@@ -0,0 +1,32 @@
import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:zhiying_base_widget/widgets/home/home_notice/bloc/home_notice_repository.dart';
import 'package:zhiying_comm/util/empty_util.dart';
import 'bloc.dart';

class HomeNoticeBloc extends Bloc<HomeNoticeEvent, HomeNoticeState> {
HomeNoticeRepository repository;

HomeNoticeBloc({this.repository});

@override
HomeNoticeState get initialState => HomeNoticeInitial();

@override
Stream<HomeNoticeState> mapEventToState(
HomeNoticeEvent event,
) async* {
if(event is HomeNoticeInitEvent){
yield* _mapInitEventToState(event);
}
}

/// 初始化
Stream<HomeNoticeState> _mapInitEventToState(HomeNoticeInitEvent event) async* {
var parentData = await repository.fetchParentData(event);
if(!EmptyUtil.isEmpty(parentData))
yield HomeNoticeLoadedState(model: parentData);
else
yield HomeNoticeErrorState();
}
}

+ 16
- 0
lib/widgets/home/home_notice/bloc/home_notice_event.dart View File

@@ -0,0 +1,16 @@
import 'package:equatable/equatable.dart';
import 'bloc.dart';

abstract class HomeNoticeEvent extends Equatable {
const HomeNoticeEvent();
@override
List<Object> get props => [];
}

/// 初始化事件
class HomeNoticeInitEvent extends HomeNoticeEvent{
final Map<String, dynamic> model;
const HomeNoticeInitEvent({this.model});
@override
List<Object> get props => [this.model];
}

+ 18
- 0
lib/widgets/home/home_notice/bloc/home_notice_repository.dart View File

@@ -0,0 +1,18 @@
import 'dart:convert';

import 'package:zhiying_base_widget/widgets/home/home_notice/bloc/bloc.dart';
import 'package:zhiying_base_widget/widgets/home/home_notice/model/home_notice_model.dart';
import 'package:zhiying_comm/zhiying_comm.dart';

class HomeNoticeRepository {
/// 获取父页面的数据
Future<HomeNoticeModel> fetchParentData(HomeNoticeInitEvent event) async {
try {
String jsonStr = event.model['data'];
return HomeNoticeModel.fromJson(jsonDecode(jsonStr));
} catch (e) {
Logger.log(e);
}
return null;
}
}

+ 30
- 0
lib/widgets/home/home_notice/bloc/home_notice_state.dart View File

@@ -0,0 +1,30 @@
import 'package:equatable/equatable.dart';
import 'package:zhiying_base_widget/widgets/home/home_notice/model/home_notice_model.dart';
import 'bloc.dart';

abstract class HomeNoticeState extends Equatable {
const HomeNoticeState();
@override
List<Object> get props => [];
}

/// 初始化事件
class HomeNoticeInitial extends HomeNoticeState {
@override
List<Object> get props => [];
}

/// 数据加载完毕
class HomeNoticeLoadedState extends HomeNoticeState {
final HomeNoticeModel model;

const HomeNoticeLoadedState({this.model});

@override
List<Object> get props => [this.model];
}

/// 数据加载出错
class HomeNoticeErrorState extends HomeNoticeState{

}

+ 28
- 0
lib/widgets/home/home_notice/home_notice_sk.dart View File

@@ -0,0 +1,28 @@
import 'package:shimmer/shimmer.dart';
import 'package:flutter/material.dart';

///
/// 公告的骨架屏
///
class HomeNoticeSkeleton extends StatelessWidget {
final Map<String, dynamic> map;

const HomeNoticeSkeleton({this.map});

@override
Widget build(BuildContext context) {
return Container(padding: const EdgeInsets.symmetric(horizontal: 12.5), child: _shimmerWidget(width: double.infinity, height: 30, radius: 8));
}

Widget _shimmerWidget({double width, double height, double radius = 0}) {
return Shimmer.fromColors(
baseColor: Colors.grey[300],
highlightColor: Colors.grey[100],
child: Container(
width: width,
height: height,
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(radius)),
),
);
}
}

+ 203
- 0
lib/widgets/home/home_notice/home_notice_widget.dart View File

@@ -0,0 +1,203 @@
import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:zhiying_base_widget/widgets/home/home_notice/bloc/home_notice_repository.dart';
import 'package:zhiying_base_widget/widgets/home/home_notice/home_notice_sk.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:zhiying_comm/zhiying_comm.dart';
import 'package:zhiying_base_widget/widgets/home/home_notice/model/home_notice_model.dart';
import 'bloc/bloc.dart';

///
/// 公告滚动widget
///
class HomeNoticeWidget extends StatelessWidget {
final Map<String, dynamic> model;

const HomeNoticeWidget(this.model);

@override
Widget build(BuildContext context) {
return BlocProvider<HomeNoticeBloc>(
create: (_) => HomeNoticeBloc(repository: HomeNoticeRepository())..add(HomeNoticeInitEvent(model: model)),
child: HomeNoticeWidgetContianer(),
);
}
}

class HomeNoticeWidgetContianer extends StatefulWidget {
@override
_HomeNoticeWidgetContianerState createState() => _HomeNoticeWidgetContianerState();
}

class _HomeNoticeWidgetContianerState extends State<HomeNoticeWidgetContianer> {

/// 子item点击事件
void _itemOnClick(HomeNoticeModel model) {
if(pageIndex == model.notices.length){
pageIndex = 0;
}
print('===== $pageIndex');
HomeNoticeNoticesModel item = model.notices[pageIndex];
_itemJump(item);
}

/// 子item跳转
void _itemJump(HomeNoticeNoticesModel model){
print('${model?.skip_identifier}');
RouterUtil.route(model.toJson(), context);
}

@override
Widget build(BuildContext context) {
return BlocConsumer<HomeNoticeBloc, HomeNoticeState>(
listener: (context, state) {},
buildWhen: (prev, current) {
return true;
},
builder: (context, state) {
if (state is HomeNoticeLoadedState) {
return _getMainWidget(state?.model);
}
return HomeNoticeSkeleton();
},
);
}

/// 主体页面
Widget _getMainWidget(HomeNoticeModel model) {
return Container(
width: double.infinity,
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.only(bottomLeft: Radius.circular(7.5), bottomRight: Radius.circular(7.5))),
padding: const EdgeInsets.only(bottom: 7.5),
child: Container(
decoration: BoxDecoration(borderRadius: BorderRadius.circular(7.5), color: HexColor.fromHex(model?.bg_color)),
// color: Colors.cyan),
margin: const EdgeInsets.only(left: 12.5, right: 12.5),
padding: const EdgeInsets.only(top: 8, bottom: 8, left: 12, right: 8),
// height: 30,
width: double.infinity,
child: _getChildWidget(model),
),
);
}

var pageIndex = 0;

Widget _getChildWidget(HomeNoticeModel model) {
return GestureDetector(
onTap: () => _itemOnClick(model),
behavior: HitTestBehavior.opaque,
child: Row(
children: <Widget>[
/// 图片
// Container(width: 52, height: 13, color: Colors.red),
CachedNetworkImage(
imageUrl: model?.logo_img ?? '',
width: 52,
),
const SizedBox(width: 14),

/// 文字
Expanded(
child: Container(
width: double.infinity,
height: 15,
alignment: Alignment.centerLeft,
// color: Colors.yellowAccent,
child: MarqueeWidget(
model?.notices?.length ?? 0,
(BuildContext context, int index) {
HomeNoticeNoticesModel item = model.notices[index];
return Align(alignment: Alignment.centerLeft, child: Text('${item?.notice_text}' , style: TextStyle(color: HexColor.fromHex(model?.text_color), fontSize: 12)));
},
onPageChanged: (index) => pageIndex = index,
),
),
),
const SizedBox(width: 14),

/// 图片
CachedNetworkImage(imageUrl: model?.jump_img ?? '', height: 18),
// Container(
// width: 18,
// height: 18,
// color: Colors.red,
// ),
],
),
);
}
}

// 上下滚动的消息轮播
class MarqueeWidget extends StatefulWidget {
int count; // 子视图数量
IndexedWidgetBuilder itemBuilder; // 子视图构造器
final ValueChanged<int> onPageChanged;

MarqueeWidget(this.count, this.itemBuilder, {this.onPageChanged});

@override
_MarqueeWidgetState createState() => _MarqueeWidgetState();
}

class _MarqueeWidgetState extends State<MarqueeWidget> {
PageController _controller;
Timer _timer;

@override
void initState() {
super.initState();

if (widget.count > 1) {
_controller = PageController();
_timer = Timer.periodic(Duration(seconds: 5), (timer) {
// 如果当前位于最后一页,则直接跳转到第一页,两者内容相同,跳转时视觉上无感知
if (_controller.page.round() >= widget.count) {
_controller.jumpToPage(0);
}
_controller.nextPage(duration: Duration(seconds: 1), curve: Curves.linear);
});
}
}

@override
Widget build(BuildContext context) {
// return PageView.builder(
// scrollDirection: Axis.vertical,
// controller: _controller,
// itemBuilder: (buildContext, index) {
// if (index < widget.count) {
// return widget.itemBuilder(buildContext, index);
// } else {
// return widget.itemBuilder(buildContext, 0);
// }
// },
// itemCount: widget.count + 1, // 在原数据末尾添加一笔数据(即第一笔数据),用于实现无限循环滚动效果
// );
// }

return PageView.custom(
physics: NeverScrollableScrollPhysics(),
childrenDelegate: SliverChildBuilderDelegate((context, index) {
if (index < widget.count) {
return widget.itemBuilder(context, index);
} else {
return widget.itemBuilder(context, 0);
}
}, childCount: widget.count + 1),
scrollDirection: Axis.vertical,
controller: _controller,
onPageChanged: widget?.onPageChanged,
);
}

@override
void dispose() {
super.dispose();
_controller?.dispose();
_timer?.cancel();
}
}

+ 58
- 0
lib/widgets/home/home_notice/model/home_notice_model.dart View File

@@ -0,0 +1,58 @@
class HomeNoticeModel {
String logo_img;
String jump_img;
String bg_color;
String text_color;
String duration_time;

List<HomeNoticeNoticesModel> notices;

HomeNoticeModel({this.notices, this.logo_img, this.jump_img, this.bg_color, this.text_color, this.duration_time});

factory HomeNoticeModel.fromJson(Map<String, dynamic> json) {
return HomeNoticeModel(
logo_img: json['logo_img']?.toString(),
jump_img: json['jump_img']?.toString(),
bg_color: json['bg_color']?.toString(),
text_color: json['text_color']?.toString(),
duration_time: json['duration_time']?.toString(),
notices: json['notices'] != null ? (json['notices'] as List).map((i) => HomeNoticeNoticesModel.fromJson(i)).toList() : null,
);
}

Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();

data['duration_time'] = this.duration_time;
data['text_color'] = this.text_color;
data['bg_color'] = this.bg_color;
data['jump_img'] = this.jump_img;
data['logo_img'] = this.logo_img;

if (this.notices != null) {
data['notices'] = this.notices.map((v) => v.toJson()).toList();
}
return data;
}
}

class HomeNoticeNoticesModel {
String notice_text;
String skip_identifier;

HomeNoticeNoticesModel({this.notice_text, this.skip_identifier});

factory HomeNoticeNoticesModel.fromJson(Map<String, dynamic> json) {
return HomeNoticeNoticesModel(
notice_text: json['notice_text']?.toString(),
skip_identifier: json['skip_identifier']?.toString(),
);
}

Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['img'] = this.notice_text;
data['skip_identifier'] = this.skip_identifier;
return data;
}
}

+ 4
- 2
lib/widgets/home/home_quick_entry/home_quick_entry.dart View File

@@ -32,8 +32,9 @@ class HomeQuickEntryContianer extends StatefulWidget {
class _HomeQuickEntryContianerState extends State<HomeQuickEntryContianer> {

/// Icon点击事件
void _itemIconClick(TypeNormal item){
print("item type = ${item.skip_identifier}");
void _itemIconClick(TypeNormal model){
print("item type = ${model.skip_identifier}");
RouterUtil.route(model.toJson(), context);
}

@override
@@ -250,6 +251,7 @@ class _HomeQuickEntryContianerState extends State<HomeQuickEntryContianer> {
SwiperPagination _swiperPaginationDot(HomeQuickEntryModel model){
return SwiperPagination(margin: const EdgeInsets.only(), builder: DotSwiperPaginationBuilder( color: HexColor.fromHex(model?.pagination_unselect_color), activeColor: HexColor.fromHex(model?.pagination_select_color), size: 8, activeSize: 8));
}

// 自定义进度条 条形
SwiperPlugin _swiperCustomPagination(int pageCount) {
List list = [];


+ 9
- 8
lib/widgets/home/home_slide_banner/bloc/home_slide_banner_bloc.dart View File

@@ -9,8 +9,7 @@ import 'package:zhiying_comm/util/empty_util.dart';

import './bloc.dart';

class HomeSlideBannerBloc
extends Bloc<HomeSlideBannerEvent, HomeSlideBannerState> {
class HomeSlideBannerBloc extends Bloc<HomeSlideBannerEvent, HomeSlideBannerState> {
HomeSlideBannerRepository repository;

HomeSlideBannerBloc({@required this.repository});
@@ -19,8 +18,7 @@ class HomeSlideBannerBloc
HomeSlideBannerState get initialState => InitialHomeSlideBannerState();

@override
Stream<HomeSlideBannerState> mapEventToState(
HomeSlideBannerEvent event) async* {
Stream<HomeSlideBannerState> mapEventToState(HomeSlideBannerEvent event) async* {
final currentState = state;

/// 初始化
@@ -31,11 +29,14 @@ class HomeSlideBannerBloc
}

/// 初始化
Stream<HomeSlideBannerState> _mapInitEventToState(
HomeBannerInitEvent event) async* {
Stream<HomeSlideBannerState> _mapInitEventToState(HomeBannerInitEvent event) async* {
var parent = await repository.fetchPreantData(event.model);
if(!EmptyUtil.isEmpty(parent)){
yield HomeSlideBannerLoadedState(datas: parent);
return;
}
var cached = await repository.fetchCachedDate(id: event.model['mod_id']);
if (!EmptyUtil.isEmpty(cached))
yield HomeSlideBannerCachedState(datas: cached);
if (!EmptyUtil.isEmpty(cached)) yield HomeSlideBannerCachedState(datas: cached);
var param = await repository.fetchData(id: event.model['mod_id']);
if (!EmptyUtil.isEmpty(param))
yield HomeSlideBannerLoadedState(datas: param);


+ 20
- 9
lib/widgets/home/home_slide_banner/bloc/home_slide_banner_repository.dart View File

@@ -1,3 +1,5 @@
import 'dart:convert';

import 'package:flutter/cupertino.dart';
import 'package:zhiying_base_widget/widgets/home/home_slide_banner/model/home_slide_banner_model.dart';
import 'package:zhiying_comm/util/empty_util.dart';
@@ -6,33 +8,42 @@ import 'package:zhiying_comm/util/net_util.dart';

class HomeSlideBannerRepository {
/// 获取缓存数据
Future<List<HomeSlideBannerModelItems>> fetchCachedDate({@required int id}) async {
Future<HomeSlideBannerModel> fetchCachedDate({@required int id}) async {
var cached = await NetUtil.getRequestCachedData('/api/v1/mod', params: {
'ids': [id]
});
if (!EmptyUtil.isEmpty(cached)) {
HomeSlideBannerModel model = HomeSlideBannerModel.fromJson(cached);
if (null != model && !EmptyUtil.isEmpty(model.items)) {
return model.items;
try {
return HomeSlideBannerModel.fromJson(cached);
}catch(e){
}

}
return null;
}

/// 获取父页面传进来的数据

Future<HomeSlideBannerModel> fetchPreantData(@required Map<String, dynamic> model) async{
try{
if(!EmptyUtil.isEmpty(model)){
return HomeSlideBannerModel.fromJson(jsonDecode(model['data']));
}
}catch(e){
}
return null;
}

/// 获取数据
Future<List<HomeSlideBannerModelItems>> fetchData({@required int id}) async {
Future<HomeSlideBannerModel> fetchData({@required int id}) async {
var params = await NetUtil.post('/api/v1/mod',
params: {
'ids': [id]
},
cache: true);
if (NetUtil.isSuccess(params) && !EmptyUtil.isEmpty(params[GlobalConfig.HTTP_RESPONSE_KEY_DATA])) {
HomeSlideBannerModel model = HomeSlideBannerModel.fromJson(params[GlobalConfig.HTTP_RESPONSE_KEY_DATA]);
if (null != model && !EmptyUtil.isEmpty(model.items)) {
return model.items;
try{
return HomeSlideBannerModel.fromJson(params[GlobalConfig.HTTP_RESPONSE_KEY_DATA]);
}catch(e){
}
}
return null;


+ 3
- 4
lib/widgets/home/home_slide_banner/bloc/home_slide_banner_state.dart View File

@@ -16,7 +16,7 @@ class InitialHomeSlideBannerState extends HomeSlideBannerState {

/// 缓存数据
class HomeSlideBannerCachedState extends HomeSlideBannerState {
List<HomeSlideBannerModelItems> datas;
HomeSlideBannerModel datas;

HomeSlideBannerCachedState({this.datas});

@@ -26,12 +26,11 @@ class HomeSlideBannerCachedState extends HomeSlideBannerState {

/// 数据加载完毕状态
class HomeSlideBannerLoadedState extends HomeSlideBannerState {
List<HomeSlideBannerModelItems> datas;
HomeSlideBannerModel datas;

HomeSlideBannerLoadedState({this.datas});

HomeSlideBannerLoadedState copyWith(
{List<HomeSlideBannerModelItems> newData}) {
HomeSlideBannerLoadedState copyWith({HomeSlideBannerModel newData}) {
return HomeSlideBannerLoadedState(
datas: newData ?? datas,
);


+ 59
- 11
lib/widgets/home/home_slide_banner/home_slide_banner.dart View File

@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_swiper/flutter_swiper.dart';
import 'package:provider/provider.dart';
import 'package:zhiying_base_widget/pages/goods_details_page/goods_details_page.dart';
import 'package:zhiying_base_widget/pages/main_page/notifier/main_page_bg_notifier.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:zhiying_comm/zhiying_comm.dart';
@@ -39,9 +40,14 @@ class HomeSlideBannerContainer extends StatefulWidget {
}

class _HomeSlideBannerContainerState extends State<HomeSlideBannerContainer> {

/// 子元素点击事件
void _itemOnClick(HomeSlideBannerModelItems items) {
print('点击了 $items');
void _itemOnClick(IndexCarousel model) {
print('点击了 $model');
// RouterUtil.route(model.toJson(), context);
Navigator.push(context, MaterialPageRoute(
builder: (_) => PageFactory.create('goods_details', null)
));
}

@override
@@ -73,26 +79,26 @@ class _HomeSlideBannerContainerState extends State<HomeSlideBannerContainer> {
);
}

Widget _getMainWidget(List<HomeSlideBannerModelItems> datas) {
Widget _getMainWidget(HomeSlideBannerModel datas) {
return Container(
width: double.infinity,
height: 140,
child: Swiper(
itemBuilder: (BuildContext context, int index) {
HomeSlideBannerModelItems items = datas[index];
IndexCarousel items = datas.index_carousel_list[index];
return Container(
// color: Colors.primaries[index % Colors.primaries.length],
width: double.infinity,
child: CachedNetworkImage(
imageUrl: items?.img?? '',
imageUrl: items?.img ?? '',
fit: BoxFit.cover,
),
);
},
itemCount: datas?.length ?? 0,
itemCount: datas?.index_carousel_list?.length ?? 0,
loop: true,
onTap: (index) => _itemOnClick(datas[index]),
pagination: _SwiperCustomPagination(datas?.length ?? 0),
autoplay: true,
onTap: (index) => _itemOnClick(datas.index_carousel_list[index]),
pagination: _getSwiperStyleByType(datas, datas?.index_carousel_list?.length ?? 0),
onIndexChanged: (index) {
print('切换下一页');
Provider.of<MainPageBgNotifier>(context, listen: false).switchBg(Container(
@@ -105,8 +111,45 @@ class _HomeSlideBannerContainerState extends State<HomeSlideBannerContainer> {
);
}

/// 获取进度样式
SwiperPlugin _getSwiperStyleByType(HomeSlideBannerModel model, int pageCount) {

if('1' != model.pagination_open){
return null;
}

if ('type_number' == model.pagination) {
return _getNumswiperPlugin(pageCount, model.pagination_select_color, model.pagination_unselect_color);
}
if ('type_point' == model.pagination) {
return _swiperCustomPaginationDito(pageCount, model.pagination_select_color, model.pagination_unselect_color);
}
if ('type_bar' == model.pagination) {
return _swiperCustomPagination(pageCount, model.pagination_select_color, model.pagination_unselect_color);
}
return null;
}

/// 数字样式
SwiperPlugin _getNumswiperPlugin(int pageCount, String selectColor, String unselectColor) {
return SwiperCustomPagination(builder: (BuildContext context, SwiperPluginConfig config) {
return Align(
alignment: Alignment(0.0, 0.9),
child: Container(
padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 18),
decoration: BoxDecoration(borderRadius: BorderRadius.circular(13), color: HexColor.fromHex('#4D000000')),
child: RichText(
text: TextSpan(text: '${config.activeIndex + 1}', style: TextStyle(fontSize: 12, color: HexColor.fromHex(selectColor)), children: [
TextSpan(text: '/', style: TextStyle(fontSize: 12, color: HexColor.fromHex(unselectColor))),
TextSpan(text: '$pageCount', style: TextStyle(fontSize: 12, color: HexColor.fromHex(unselectColor))),
]),
)),
);
});
}

/// 自定义进度条
SwiperPlugin _SwiperCustomPagination(int pageCount) {
SwiperPlugin _swiperCustomPagination(int pageCount, String selectColor, String unselectColor) {
List list = [];
for (int i = 0; i < pageCount; i++) {
list.add(i);
@@ -134,11 +177,16 @@ class _HomeSlideBannerContainerState extends State<HomeSlideBannerContainer> {
return Container(
height: 4,
width: 25,
decoration: BoxDecoration(borderRadius: borderRadius, color: index == config.activeIndex ? HexColor.fromHex('#FF4242') : HexColor.fromHex('#FFFFFF')),
decoration: BoxDecoration(borderRadius: borderRadius, color: index == config.activeIndex ? HexColor.fromHex(selectColor) : HexColor.fromHex(unselectColor)),
);
}).toList(),
),
);
});
}

/// 圆形进度条
SwiperPlugin _swiperCustomPaginationDito(int pageCount, String selectColor, String unselectColor) {
return SwiperPagination(margin: const EdgeInsets.only(), builder: DotSwiperPaginationBuilder( color: HexColor.fromHex(unselectColor), activeColor: HexColor.fromHex(selectColor), size: 8, activeSize: 8));
}
}

+ 47
- 104
lib/widgets/home/home_slide_banner/model/home_slide_banner_model.dart View File

@@ -1,115 +1,58 @@

class HomeSlideBannerModel {
List<HomeSlideBannerModelItems> items;
List<IndexCarousel> index_carousel_list;
String pagination;
String pagination_open;
List<String> pagination_options;
String pagination_select_color;
String pagination_unselect_color;

HomeSlideBannerModel({this.items});
HomeSlideBannerModel({this.index_carousel_list, this.pagination, this.pagination_open, this.pagination_options, this.pagination_select_color, this.pagination_unselect_color});

HomeSlideBannerModel.fromJson(Map<String, dynamic> json) {
if (json['6'] != null) {
items = new List<HomeSlideBannerModelItems>();
json['6'].forEach((v) {
items.add(new HomeSlideBannerModelItems.fromJson(v));
});
factory HomeSlideBannerModel.fromJson(Map<String, dynamic> json) {
return HomeSlideBannerModel(
index_carousel_list: json['index_carousel_list'] != null ? (json['index_carousel_list'] as List).map((i) => IndexCarousel.fromJson(i)).toList() : null,
pagination: json['pagination'],
pagination_open: json['pagination_open'],
pagination_options: json['pagination_options'] != null ? new List<String>.from(json['pagination_options']) : null,
pagination_select_color: json['pagination_select_color'],
pagination_unselect_color: json['pagination_unselect_color'],
);
}
}

Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.items != null) {
data['6'] = this.items.map((v) => v.toJson()).toList();
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['pagination'] = this.pagination;
data['pagination_open'] = this.pagination_open;
data['pagination_select_color'] = this.pagination_select_color;
data['pagination_unselect_color'] = this.pagination_unselect_color;
if (this.index_carousel_list != null) {
data['index_carousel_list'] = this.index_carousel_list.map((v) => v.toJson()).toList();
}
if (this.pagination_options != null) {
data['pagination_options'] = this.pagination_options;
}
return data;
}
return data;
}
}

class HomeSlideBannerModelItems {
String modId;
String modPid;
String modName;
String position;
String title;
String subtitle;
String url;
String margin;
String aspectRatio;
String icon;
String img;
String fontColor;
String bgImg;
String bgColor;
String bgColorT;
String badge;
String path;
String data;
String sort;
String isGlobal;
class IndexCarousel {
String img;
String skip_identifier;

HomeSlideBannerModelItems(
{this.modId,
this.modPid,
this.modName,
this.position,
this.title,
this.subtitle,
this.url,
this.margin,
this.aspectRatio,
this.icon,
this.img,
this.fontColor,
this.bgImg,
this.bgColor,
this.bgColorT,
this.badge,
this.path,
this.data,
this.sort,
this.isGlobal});
IndexCarousel({this.img, this.skip_identifier});

HomeSlideBannerModelItems.fromJson(Map<String, dynamic> json) {
modId = json['mod_id']?.toString();
modPid = json['mod_pid']?.toString();
modName = json['mod_name']?.toString();
position = json['position']?.toString();
title = json['title']?.toString();
subtitle = json['subtitle']?.toString();
url = json['url']?.toString();
margin = json['margin']?.toString();
aspectRatio = json['aspect_ratio']?.toString();
icon = json['icon']?.toString();
img = json['img']?.toString();
fontColor = json['font_color']?.toString();
bgImg = json['bg_img']?.toString();
bgColor = json['bg_color']?.toString();
bgColorT = json['bg_color_t']?.toString();
badge = json['badge']?.toString();
path = json['path']?.toString();
data = json['data']?.toString();
sort = json['sort']?.toString();
isGlobal = json['is_global']?.toString();
}
factory IndexCarousel.fromJson(Map<String, dynamic> json) {
return IndexCarousel(
img: json['img'],
skip_identifier: json['skip_identifier'],
);
}

Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['mod_id'] = this.modId;
data['mod_pid'] = this.modPid;
data['mod_name'] = this.modName;
data['position'] = this.position;
data['title'] = this.title;
data['subtitle'] = this.subtitle;
data['url'] = this.url;
data['margin'] = this.margin;
data['aspect_ratio'] = this.aspectRatio;
data['icon'] = this.icon;
data['img'] = this.img;
data['font_color'] = this.fontColor;
data['bg_img'] = this.bgImg;
data['bg_color'] = this.bgColor;
data['bg_color_t'] = this.bgColorT;
data['badge'] = this.badge;
data['path'] = this.path;
data['data'] = this.data;
data['sort'] = this.sort;
data['is_global'] = this.isGlobal;
return data;
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['img'] = this.img;
data['skip_identifier'] = this.skip_identifier;
return data;
}
}

+ 22
- 0
lib/widgets/home/home_sreach/home_sreach_creater.dart View File

@@ -0,0 +1,22 @@
import 'package:flutter/material.dart';
import 'package:zhiying_base_widget/widgets/home/home_sreach/home_sreach_widget.dart';
import 'package:zhiying_base_widget/widgets/others/normal_nav/normal_nav.dart';
import 'package:zhiying_comm/zhiying_comm.dart';

class HomeSreachCreater extends WidgetCreater {
@override
List<Widget> createWidgets(Map<String, dynamic> model) {
return [
SliverPersistentHeader(
pinned: false,
floating: false,
delegate: HomeSreachDeleagater(),
),
];
}

@override
bool isSliverChild() {
return true;
}
}

+ 21
- 0
lib/widgets/home/home_sreach/home_sreach_sk.dart View File

@@ -0,0 +1,21 @@
import 'package:shimmer/shimmer.dart';
import 'package:flutter/material.dart';

class HomeSreachSkeleton extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container();
}

Widget _shimmerWidget({double width, double height, double radius = 0}) {
return Shimmer.fromColors(
baseColor: Colors.grey[300],
highlightColor: Colors.grey[100],
child: Container(
width: width,
height: height,
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(radius)),
),
);
}
}

+ 119
- 0
lib/widgets/home/home_sreach/home_sreach_widget.dart View File

@@ -0,0 +1,119 @@
import 'package:zhiying_comm/zhiying_comm.dart';
import 'package:flutter/material.dart';
import 'dart:ui';

class HomeSreachDeleagater extends SliverPersistentHeaderDelegate{

double _height;

HomeSreachDeleagater() : super() {
_height = MediaQueryData.fromWindow(window).padding.top + 44;
}

@override
Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
print('${shrinkOffset.toString()}');
double percent = shrinkOffset / _height;
print('${percent.toString()}');
return HomeSreachWidget(null);
}

@override
double get maxExtent => _height;

@override
double get minExtent => _height;

@override
bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) {
return false;
}

}


///
/// 首页搜索框
///
class HomeSreachWidget extends StatelessWidget {
final Map<String, dynamic> model;

const HomeSreachWidget(this.model);

@override
Widget build(BuildContext context) {
return HomeSreachContainer();
}
}

class HomeSreachContainer extends StatefulWidget {
@override
_HomeSreachContainerState createState() => _HomeSreachContainerState();
}

class _HomeSreachContainerState extends State<HomeSreachContainer> {
@override
Widget build(BuildContext context) {
return _getMainWidget();
}

/// 主视图
Widget _getMainWidget() {
return Container(
color: Colors.transparent,
height: 30,
width: double.infinity,
margin: EdgeInsets.only(left: 12.5, right: 12.5, bottom: 10, top: MediaQueryData.fromWindow(window).padding.top + 10),
child: Row(
children: <Widget>[
/// 搜索框
Expanded(
child: _getSreachWidget(),
),
const SizedBox(width: 10),

/// 消息
_getMessageWidget(),
],
),
);
}

/// 搜索栏
Widget _getSreachWidget() {
return Container(
height: 30,
width: double.infinity,
child: TextField(
autofocus: false,
style: TextStyle(color: HexColor.fromHex('#FFFFFF'), fontSize: 14),
readOnly: true,
decoration: InputDecoration(
hintText: '输入搜索内容,领券省钱',
hintStyle: TextStyle(
color: Colors.white,
fontSize: 14,
),
contentPadding: EdgeInsets.zero,
prefixIcon: Icon(
Icons.search,
color: Colors.white,
),
filled: true,
fillColor: Color(0x50cccccc),
focusedBorder: OutlineInputBorder(borderSide: BorderSide(color: Color(0x00000000)), borderRadius: BorderRadius.all(Radius.circular(30))),
enabledBorder: OutlineInputBorder(borderSide: BorderSide(color: Color(0x00000000)), borderRadius: BorderRadius.all(Radius.circular(30))),
),
),
);
}

/// 消息widget
Widget _getMessageWidget() {
return Container(
width: 30,
height: 30,
color: Colors.red,
);
}
}

Loading…
Cancel
Save