| @@ -34,7 +34,7 @@ apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" | |||
| android { | |||
| compileSdkVersion 28 | |||
| compileSdkVersion 29 | |||
| lintOptions { | |||
| disable 'InvalidPackage' | |||
| @@ -44,7 +44,7 @@ android { | |||
| defaultConfig { | |||
| applicationId "cn.zhios.zhiying" | |||
| minSdkVersion 21 | |||
| targetSdkVersion 28 | |||
| targetSdkVersion 29 | |||
| versionCode 1 | |||
| versionName "1.0" | |||
| aaptOptions.cruncherEnabled = false | |||
| @@ -157,9 +157,33 @@ flutter { | |||
| } | |||
| dependencies { | |||
| implementation 'androidx.appcompat:appcompat:1.2.0' | |||
| implementation 'androidx.constraintlayout:constraintlayout:2.0.2' | |||
| testImplementation 'junit:junit:4.12' | |||
| androidTestImplementation 'androidx.test:runner:1.1.1' | |||
| androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' | |||
| //登陆 | |||
| implementation 'com.ali.auth.sdk:alibabauth_core:2.0.0.11@aar' | |||
| implementation 'com.ali.auth.sdk:alibabauth_ui:2.0.0.11@aar' | |||
| implementation 'com.ali.auth.sdk:alibabauth_ext:2.0.0.11@aar' | |||
| //安全组件 | |||
| implementation 'com.taobao.android:securityguardaar3:5.4.171@aar' | |||
| implementation 'com.taobao.android:securitybodyaar3:5.4.99@aar' | |||
| implementation 'com.taobao.android:avmpaar3:5.4.36@aar' | |||
| implementation 'com.taobao.android:sgmiddletieraar3:5.4.9@aar' | |||
| //Mtop | |||
| implementation 'com.taobao.android:mtopsdk_allinone_open:3.1.2.5@jar' | |||
| //applink | |||
| implementation 'com.alibaba.sdk.android:alibc_link_partner:4.1.15@aar' | |||
| //ut | |||
| implementation 'com.taobao.android:utdid4all:1.5.2' | |||
| implementation 'com.alibaba.mtl:app-monitor-sdk:2.6.4.5_for_bc' | |||
| // 电商基础组件 | |||
| implementation 'com.alibaba.sdk.android:AlibcTradeCommon:4.0.0.16@aar' | |||
| implementation 'com.alibaba.sdk.android:AlibcTradeBiz:4.0.0.16@aar' | |||
| implementation 'com.alibaba.sdk.android:nb_trade:4.0.0.16@aar' | |||
| implementation 'com.alibaba:fastjson:1.2.41@jar' | |||
| } | |||
| @@ -1,40 +1,51 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <manifest xmlns:android="http://schemas.android.com/apk/res/android" | |||
| xmlns:tools="http://schemas.android.com/tools" | |||
| package="cn.zhios.zhiying_base_widget_example"> | |||
| <!-- io.flutter.app.FlutterApplication is an android.app.Application that | |||
| calls FlutterMain.startInitialization(this); in its onCreate method. | |||
| In most cases you can leave this as-is, but you if you want to provide | |||
| additional functionality it is fine to subclass or reimplement | |||
| FlutterApplication and put your custom class here. --> | |||
| <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> | |||
| <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> | |||
| <uses-permission android:name="android.permission.INTERNET" /> | |||
| <application | |||
| android:name="io.flutter.app.FlutterApplication" | |||
| android:label="@string/app_name" | |||
| android:icon="@mipmap/ic_launcher" | |||
| android:label="@string/app_name" | |||
| android:usesCleartextTraffic="true" | |||
| tools:replace="android:name"> | |||
| <activity android:name=".WebActivity"></activity> | |||
| <activity | |||
| android:name=".TestActivity" | |||
| android:theme="@style/Theme.AppCompat.NoActionBar"> | |||
| <!-- <intent-filter>--> | |||
| <!-- <action android:name="android.intent.action.MAIN" />--> | |||
| <!-- <category android:name="android.intent.category.LAUNCHER" />--> | |||
| <!-- </intent-filter>--> | |||
| </activity> | |||
| <activity | |||
| android:name=".MainActivity" | |||
| android:launchMode="singleTop" | |||
| android:theme="@style/LaunchTheme" | |||
| android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" | |||
| android:hardwareAccelerated="true" | |||
| android:launchMode="singleTop" | |||
| android:theme="@style/LaunchTheme" | |||
| android:usesCleartextTraffic="true" | |||
| android:windowSoftInputMode="adjustResize"> | |||
| <intent-filter> | |||
| <action android:name="android.intent.action.MAIN" /> | |||
| <category android:name="android.intent.category.LAUNCHER" /> | |||
| </intent-filter> | |||
| <intent-filter> | |||
| <action android:name="android.intent.action.MAIN" /> | |||
| <category android:name="android.intent.category.LAUNCHER" /> | |||
| </intent-filter> | |||
| </activity> | |||
| <!-- Don't delete the meta-data below. | |||
| This is used by the Flutter tool to generate GeneratedPluginRegistrant.java --> | |||
| <!-- | |||
| Don't delete the meta-data below. | |||
| This is used by the Flutter tool to generate GeneratedPluginRegistrant.java | |||
| --> | |||
| <meta-data | |||
| android:name="flutterEmbedding" | |||
| android:value="2" /> | |||
| </application> | |||
| <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> | |||
| <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> | |||
| <uses-permission android:name="android.permission.INTERNET"/> | |||
| </manifest> | |||
| </manifest> | |||
| @@ -38,7 +38,8 @@ public class MainActivity extends FlutterActivity implements ZhiyingFlutterCommN | |||
| @Override | |||
| public Map getSetting() { | |||
| Map map = new HashMap(); | |||
| map.put("domain", "http://inapi.izhyin.cn"); //"http://120.76.175.204:8989"); | |||
| //map.put("domain", "http://inapi.izhyin.cn"); //"http://120.76.175.204:8989"); | |||
| map.put("domain", "http://192.168.0.113:5000"); | |||
| map.put("master_id", "123456"); | |||
| map.put("secret_key", "123456"); | |||
| // map.put("token", "123465"); | |||
| @@ -0,0 +1,108 @@ | |||
| package cn.zhios.zhiying_base_widget_example; | |||
| import androidx.appcompat.app.AppCompatActivity; | |||
| import android.app.Activity; | |||
| import android.content.Intent; | |||
| import android.os.Bundle; | |||
| import android.util.Log; | |||
| import android.view.View; | |||
| import android.webkit.WebChromeClient; | |||
| import android.webkit.WebView; | |||
| import android.webkit.WebViewClient; | |||
| import android.widget.TextView; | |||
| import android.widget.Toast; | |||
| import com.alibaba.baichuan.android.trade.AlibcTrade; | |||
| import com.alibaba.baichuan.android.trade.AlibcTradeSDK; | |||
| import com.alibaba.baichuan.android.trade.callback.AlibcTradeCallback; | |||
| import com.alibaba.baichuan.android.trade.callback.AlibcTradeInitCallback; | |||
| import com.alibaba.baichuan.android.trade.model.AlibcShowParams; | |||
| import com.alibaba.baichuan.trade.biz.context.AlibcTradeResult; | |||
| import com.alibaba.baichuan.trade.biz.core.taoke.AlibcTaokeParams; | |||
| import com.alibaba.baichuan.trade.biz.login.AlibcLogin; | |||
| import com.alibaba.baichuan.trade.biz.login.AlibcLoginCallback; | |||
| import com.alibaba.baichuan.trade.common.utils.AlibcLogger; | |||
| import java.util.HashMap; | |||
| public class TestActivity extends Activity { | |||
| @Override | |||
| protected void onCreate(Bundle savedInstanceState) { | |||
| super.onCreate(savedInstanceState); | |||
| setContentView(R.layout.activity_test); | |||
| TextView aliBcTV = findViewById(R.id.tv_aliBc); | |||
| AlibcTradeSDK.asyncInit(this.getApplication(), new AlibcTradeInitCallback() { | |||
| @Override | |||
| public void onSuccess() { | |||
| Toast.makeText(TestActivity.this, "阿里百川注册成功", Toast.LENGTH_LONG).show(); | |||
| } | |||
| @Override | |||
| public void onFailure(int i, String s) { | |||
| Toast.makeText(TestActivity.this, "阿里百川注册失败" + s, Toast.LENGTH_LONG).show(); | |||
| } | |||
| }); | |||
| aliBcTV.setOnClickListener(new View.OnClickListener() { | |||
| @Override | |||
| public void onClick(View v) { | |||
| AlibcLogin.getInstance().showLogin(new AlibcLoginCallback() { | |||
| @Override | |||
| public void onSuccess(int i, String s, String s1) { | |||
| Toast.makeText(TestActivity.this, "授权成功" + s, Toast.LENGTH_LONG).show(); | |||
| } | |||
| @Override | |||
| public void onFailure(int i, String s) { | |||
| Toast.makeText(TestActivity.this, "登陆失败" + s, Toast.LENGTH_LONG).show(); | |||
| } | |||
| }); | |||
| } | |||
| }); | |||
| findViewById(R.id.tv_open_detail).setOnClickListener(new View.OnClickListener() { | |||
| AlibcShowParams showParams = new AlibcShowParams(); | |||
| @Override | |||
| public void onClick(View v) { | |||
| // // 以显示传入url的方式打开页面(第二个参数是套件名称) | |||
| // AlibcTrade.openByUrl(TestActivity.this, "", "http://www.izhim.com/comm/tb_callback.php?_ctrl=domain&domain_state=MTI2&domain_return_url=aHR0cDovLzE5Mi4xNjguMC4xMTM6NTAwMC9hcGkvdjEvdGFvYmFvL2F1dGgvY2FsbGJhY2s%2FdGltZT0xNjAyNDk4MjA3", new WebView(TestActivity.this), | |||
| // new WebViewClient(), new WebChromeClient(), showParams, | |||
| // new AlibcTaokeParams("","",""), new HashMap<String,String>(), new AlibcTradeCallback() { | |||
| // @Override | |||
| // public void onTradeSuccess(AlibcTradeResult tradeResult) { | |||
| // AlibcLogger.i("", "request success"); | |||
| // } | |||
| // @Override | |||
| // public void onFailure(int code, String msg) { | |||
| // AlibcLogger.e("", "code=" + code + ", msg=" + msg); | |||
| // if (code == -1) { | |||
| // Toast.makeText(TestActivity.this, msg, Toast.LENGTH_SHORT).show(); | |||
| // } | |||
| // } | |||
| // }); | |||
| if (!AlibcLogin.getInstance().isLogin()) { | |||
| AlibcLogin.getInstance().showLogin(new AlibcLoginCallback() { | |||
| @Override | |||
| public void onSuccess(int i, String s, String s1) { | |||
| startActivity(new Intent(TestActivity.this,WebActivity.class)); | |||
| } | |||
| @Override | |||
| public void onFailure(int i, String s) { | |||
| Log.d("阿里百川授权失败",s); | |||
| } | |||
| }); | |||
| } else { | |||
| startActivity(new Intent(TestActivity.this,WebActivity.class)); | |||
| } | |||
| } | |||
| }); | |||
| } | |||
| } | |||
| @@ -0,0 +1,521 @@ | |||
| package cn.zhios.zhiying_base_widget_example; | |||
| import android.annotation.SuppressLint; | |||
| import android.app.Activity; | |||
| import android.content.ComponentName; | |||
| import android.content.Intent; | |||
| import android.graphics.Bitmap; | |||
| import android.net.Uri; | |||
| import android.net.http.SslError; | |||
| import android.os.Bundle; | |||
| import android.util.Log; | |||
| import android.util.Patterns; | |||
| import android.view.View; | |||
| import android.webkit.GeolocationPermissions; | |||
| import android.webkit.JavascriptInterface; | |||
| import android.webkit.SslErrorHandler; | |||
| import android.webkit.ValueCallback; | |||
| import android.webkit.WebChromeClient; | |||
| import android.webkit.WebResourceError; | |||
| import android.webkit.WebResourceRequest; | |||
| import android.webkit.WebSettings; | |||
| import android.webkit.WebView; | |||
| import android.webkit.WebViewClient; | |||
| import android.widget.Toast; | |||
| import com.alibaba.baichuan.android.trade.AlibcTrade; | |||
| import com.alibaba.baichuan.android.trade.callback.AlibcTradeCallback; | |||
| import com.alibaba.baichuan.android.trade.model.AlibcShowParams; | |||
| import com.alibaba.baichuan.trade.biz.context.AlibcTradeResult; | |||
| import com.alibaba.baichuan.trade.biz.core.taoke.AlibcTaokeParams; | |||
| import com.alibaba.baichuan.trade.biz.login.AlibcLogin; | |||
| import com.alibaba.baichuan.trade.biz.login.AlibcLoginCallback; | |||
| import java.util.HashMap; | |||
| import java.util.Map; | |||
| public class WebActivity extends Activity { | |||
| WebView mainWeb; | |||
| @Override | |||
| protected void onCreate(Bundle savedInstanceState) { | |||
| super.onCreate(savedInstanceState); | |||
| setContentView(R.layout.activity_web_bc); | |||
| mainWeb = findViewById(R.id.webview_main); | |||
| mainWeb.getSettings().setJavaScriptEnabled(true); | |||
| mainWeb.getSettings().setDomStorageEnabled(true); | |||
| mainWeb.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT); | |||
| mainWeb.getSettings().setLoadWithOverviewMode(true); | |||
| mainWeb.getSettings().setAllowFileAccess(true); | |||
| mainWeb.getSettings().setDatabaseEnabled(true); | |||
| MyWebClient myWebClient = new MyWebClient(); | |||
| MyWebChromeClient myWebChromeClient = new MyWebChromeClient(); | |||
| mainWeb.setWebViewClient(myWebClient); | |||
| mainWeb.setWebChromeClient(myWebChromeClient); | |||
| Map<String, String> exParams = new HashMap<>();//yhhpass参数 | |||
| // AlibcTaokeParams alibcTaokeParams = new AlibcTaokeParams("", "", ""); | |||
| // alibcTaokeParams.pid = SPUtils.getPrefString(mActivity, Pkey.pid, ""); | |||
| // alibcTaokeParams.adzoneid = SPUtils.getPrefString(mActivity, Pkey.APP_adzoneId, ""); | |||
| // alibcTaokeParams.extraParams = new HashMap<>(); | |||
| // alibcTaokeParams.extraParams.put("taokeAppkey", SPUtils.getPrefString(mActivity, Pkey.APP_alliance_appkey, "")); | |||
| AlibcShowParams showParams = new AlibcShowParams(); | |||
| showParams.setBackUrl("alisdk://"); | |||
| AlibcTrade.openByUrl(WebActivity.this, "", "http://www.izhim.com/comm/tb_callback.php?_ctrl=domain&domain_state=MTI2&domain_return_url=aHR0cDovLzE5Mi4xNjguMC4xMTM6NTAwMC9hcGkvdjEvdGFvYmFvL2F1dGgvY2FsbGJhY2s%2FdGltZT0xNjAyNDk4MjA3", | |||
| mainWeb, new MyBaichuanWebClient(), new MyWebChromeClient(), showParams, | |||
| new AlibcTaokeParams("", "", ""), exParams, new AlibcTradeCallback() { | |||
| @Override | |||
| public void onTradeSuccess(AlibcTradeResult alibcTradeResult) { | |||
| } | |||
| @Override | |||
| public void onFailure(int i, String s) { | |||
| } | |||
| }); | |||
| } | |||
| //用于百川授权的简化的WebClient | |||
| @SuppressLint("AddJavascriptInterface") | |||
| private class MyBaichuanWebClient extends WebViewClient { | |||
| @SuppressLint("AddJavascriptInterface") | |||
| @Override | |||
| public boolean shouldOverrideUrlLoading(WebView view, final String url) { | |||
| Log.d("百川拦截", url); | |||
| //绑定会员关系时获取网页内容关闭网页 | |||
| if (url.contains("comm/tbredirect.php") && !url.contains("oauth.m.taobao.com") && url.contains("track_id")) { | |||
| Log.d("百川系时获取网页内容关闭网页", url); | |||
| mainWeb.addJavascriptInterface(new InJavaScriptLocalObj(), "java_obj"); | |||
| } | |||
| if (url.contains("oauth.taobao.com/authorize") || url.contains("oauth.m.taobao.com/authorize")) { | |||
| //渠道授权改动测试 | |||
| Log.d("百川渠道授权改动测试", url); | |||
| Map<String, String> exParams = new HashMap<>();//yhhpass参数 | |||
| AlibcShowParams showParams = new AlibcShowParams(); | |||
| showParams.setBackUrl("alisdk://"); | |||
| AlibcTrade.openByUrl(WebActivity.this, "", url, | |||
| mainWeb, new MyBaichuanWebClient(), new MyWebChromeClient(), showParams, | |||
| new AlibcTaokeParams("", "", ""), exParams, new AlibcTradeCallback() { | |||
| @Override | |||
| public void onTradeSuccess(AlibcTradeResult alibcTradeResult) { | |||
| Log.d("cg", alibcTradeResult.toString()); | |||
| } | |||
| @Override | |||
| public void onFailure(int i, String s) { | |||
| Log.d("sb", s); | |||
| } | |||
| }); | |||
| } | |||
| return super.shouldOverrideUrlLoading(view, url); | |||
| } | |||
| @Override | |||
| public void onPageStarted(WebView view, String url, Bitmap favicon) { | |||
| // WebLoad.setVisibility(View.GONE); | |||
| mainWeb.setVisibility(View.GONE); | |||
| //开始加载设置为透明 | |||
| super.onPageStarted(view, url, favicon); | |||
| } | |||
| @Override | |||
| public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) { | |||
| super.onReceivedError(view, request, error); | |||
| } | |||
| @Override | |||
| public void onPageFinished(WebView view, String url) { | |||
| // WebLoad.setVisibility(View.GONE); | |||
| mainWeb.setVisibility(View.VISIBLE); | |||
| // 获取页面内容 | |||
| view.loadUrl("javascript:window.java_obj.showSource(" | |||
| + "document.documentElement.innerText);"); | |||
| // 获取解析<meta name="share-description" content="获取到的值"> | |||
| view.loadUrl("javascript:window.java_obj.showDescription(" | |||
| + "document.querySelector('meta[name=\"share-description\"]').getAttribute('content')" | |||
| + ");"); | |||
| // quanyikaText(); | |||
| super.onPageFinished(view, url); | |||
| } | |||
| //处理 [Android]用WebView访问证书有问题的SSL网页 | |||
| //http://blog.sina.com.cn/s/blog_4cd978f90102vrxk.html | |||
| @Override | |||
| public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { | |||
| handler.proceed(); | |||
| } | |||
| } | |||
| /** | |||
| * 绑定渠道 | |||
| */ | |||
| private final class InJavaScriptLocalObj { | |||
| @JavascriptInterface | |||
| public void showSource(final String html) { | |||
| //获取网页内容,用于判断是否成功绑定关系id | |||
| try { | |||
| if (html.contains("成功")) {//成功 | |||
| Toast.makeText(WebActivity.this, "授权成功", Toast.LENGTH_SHORT).show(); | |||
| finish(); | |||
| } else {//失败 | |||
| mainWeb.setAlpha(0); | |||
| } | |||
| } catch (Exception e) { | |||
| e.printStackTrace(); | |||
| } | |||
| } | |||
| @JavascriptInterface | |||
| public void showDescription(String str) { | |||
| } | |||
| } | |||
| public class MyWebChromeClient extends WebChromeClient { | |||
| private CustomViewCallback mCustomViewCallback; | |||
| // 横屏时,显示视频的view | |||
| private View mCustomView; | |||
| // 点击全屏按钮时,调用的方法 | |||
| @Override | |||
| public void onShowCustomView(View view, CustomViewCallback callback) { | |||
| super.onShowCustomView(view, callback); | |||
| //isFullPlayVedio = true; | |||
| //如果view 已经存在,则隐藏 | |||
| if (mCustomView != null) { | |||
| callback.onCustomViewHidden(); | |||
| return; | |||
| } | |||
| mCustomView = view; | |||
| mCustomView.setVisibility(View.VISIBLE); | |||
| mCustomViewCallback = callback; | |||
| } | |||
| // 取消全屏调用的方法 | |||
| @Override | |||
| public void onHideCustomView() { | |||
| super.onHideCustomView(); | |||
| if (mCustomView == null) { | |||
| return; | |||
| } | |||
| mCustomView.setVisibility(View.GONE); | |||
| mCustomView = null; | |||
| try { | |||
| mCustomViewCallback.onCustomViewHidden(); | |||
| } catch (Exception e) { | |||
| } | |||
| // setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);//竖屏 | |||
| } | |||
| @Override | |||
| public void onProgressChanged(WebView view, int newProgress) { | |||
| } | |||
| @Override | |||
| public void onReceivedTitle(WebView view, String title) { | |||
| super.onReceivedTitle(view, title); | |||
| // Logger.wtf("我的url" + view.getUrl()); | |||
| String url = view.getUrl(); | |||
| if (Patterns.WEB_URL.matcher(title).matches()) { | |||
| //网址不显示为标题 | |||
| } else { | |||
| //不是网址 | |||
| if (!url.contains("api.ejiayou.com/pages/platform/soulList/index.html")) { | |||
| } | |||
| } | |||
| } | |||
| @Override | |||
| public void onGeolocationPermissionsShowPrompt(final String origin, final GeolocationPermissions.Callback callback) { | |||
| super.onGeolocationPermissionsShowPrompt(origin, callback); | |||
| } | |||
| // For Android 3.0+ | |||
| public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) { | |||
| } | |||
| // For Android < 3.0 | |||
| public void openFileChooser(ValueCallback<Uri> uploadMsg) { | |||
| openFileChooser(uploadMsg, ""); | |||
| } | |||
| // For Android > 4.1.1 | |||
| public void openFileChooser(ValueCallback<Uri> uploadMsg, | |||
| String acceptType, String capture) { | |||
| openFileChooser(uploadMsg, acceptType); | |||
| } | |||
| // For Android > 5.0 | |||
| @Override | |||
| public boolean onShowFileChooser(WebView webView, | |||
| ValueCallback<Uri[]> filePathCallback, | |||
| FileChooserParams fileChooserParams) { | |||
| return true; | |||
| } | |||
| } | |||
| @SuppressLint("AddJavascriptInterface") | |||
| private class MyWebClient extends WebViewClient { | |||
| @SuppressLint("AddJavascriptInterface") | |||
| @Override | |||
| public boolean shouldOverrideUrlLoading(WebView view, final String url) { | |||
| if (url.startsWith("tel:")) { | |||
| startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); | |||
| return true; | |||
| } | |||
| if (url.startsWith("bdnetdisk:")) { | |||
| return true; | |||
| } | |||
| if (url.contains("tmast://")) { | |||
| try { | |||
| Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); | |||
| startActivity(intent); | |||
| } catch (Exception e) { | |||
| } | |||
| return true; | |||
| } | |||
| if (url.startsWith("http://ditu.amap.com") || | |||
| url.startsWith("https://ditu.amap.com")) { | |||
| return true; | |||
| } | |||
| if (url.contains("oauth.taobao.com/authorize") || url.contains("oauth.m.taobao.com/authorize")) { | |||
| // mainWeb.addJavascriptInterface(new InJavaScriptLocadeUpgralObj(), "java_obj"); | |||
| Map<String, String> exParams = new HashMap<>();//yhhpass参数 | |||
| // AlibcTaokeParams alibcTaokeParams = new AlibcTaokeParams("", "", ""); | |||
| // alibcTaokeParams.pid = SPUtils.getPrefString(mActivity, Pkey.pid, ""); | |||
| // alibcTaokeParams.adzoneid = SPUtils.getPrefString(mActivity, Pkey.APP_adzoneId, ""); | |||
| // alibcTaokeParams.extraParams = new HashMap<>(); | |||
| // alibcTaokeParams.extraParams.put("taokeAppkey", SPUtils.getPrefString(mActivity, Pkey.APP_alliance_appkey, "")); | |||
| AlibcShowParams showParams = new AlibcShowParams(); | |||
| showParams.setBackUrl("alisdk://"); | |||
| AlibcTrade.openByUrl(WebActivity.this, "", url, mainWeb, new MyBaichuanWebClient(), new MyWebChromeClient(), showParams, | |||
| new AlibcTaokeParams("", "", ""), exParams, new AlibcTradeCallback() { | |||
| @Override | |||
| public void onTradeSuccess(AlibcTradeResult alibcTradeResult) { | |||
| } | |||
| @Override | |||
| public void onFailure(int i, String s) { | |||
| } | |||
| }); | |||
| } | |||
| if (url.contains("tbopen://") || url.contains("tmall://") || url.contains("taobaotravel://")) { | |||
| return true; | |||
| } | |||
| if (url.contains("dianping://")) { | |||
| return true; | |||
| } | |||
| if (url.contains("aliim:")) { | |||
| return true; | |||
| } | |||
| if (url.contains("?mod=appapi&act=miandan_course&ctrl=close")) { | |||
| finish(); | |||
| return true; | |||
| } | |||
| if (url.contains("vipma.net/quickapp.html?")) { | |||
| return true; | |||
| } | |||
| // 如下方案可在非微信内部WebView的H5页面中调出微信支付 | |||
| if (url.startsWith("weixin://wap/pay?")) { | |||
| try { | |||
| Intent intent = new Intent(); | |||
| intent.setAction(Intent.ACTION_VIEW); | |||
| intent.setData(Uri.parse(url)); | |||
| startActivity(intent); | |||
| return true; | |||
| } catch (Exception e) { | |||
| e.printStackTrace(); | |||
| } | |||
| return true; | |||
| } | |||
| if (url.startsWith("weixin://")) { | |||
| try { | |||
| Intent intent = new Intent(); | |||
| intent.setAction(Intent.ACTION_VIEW); | |||
| intent.setData(Uri.parse(url)); | |||
| startActivity(intent); | |||
| return true; | |||
| } catch (Exception e) { | |||
| e.printStackTrace(); | |||
| } | |||
| return true; | |||
| } | |||
| if (url.endsWith("native://wechat")) { | |||
| Intent intent = new Intent(); | |||
| ComponentName cmp = new ComponentName("com.tencent.mm", "com.tencent.mm.ui.LauncherUI"); | |||
| intent.setAction(Intent.ACTION_MAIN); | |||
| intent.addCategory(Intent.CATEGORY_LAUNCHER); | |||
| intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); | |||
| intent.setComponent(cmp); | |||
| startActivity(intent); | |||
| return true; | |||
| } | |||
| if (url.contains("navite://save#")) { | |||
| } | |||
| //不拦截的话绑定淘宝关系id的时候会因为下面login.m.taobao.com的拦截而唤醒手淘授权之后导致不能切换帐号 | |||
| // if (url.contains("client_id") && url.contains("login.m.taobao.com/logout.htm?")) { | |||
| // view.loadUrl(url); | |||
| // return true; | |||
| // } | |||
| if (url.contains("client_id")) { | |||
| view.loadUrl(url); | |||
| return true; | |||
| } | |||
| // if (url.contains("login.m.taobao.com")) { | |||
| // if (!AlibcLogin.getInstance().isLogin()) { | |||
| // AlibcLogin.getInstance().showLogin(new AlibcLoginCallback() { | |||
| //// @Override | |||
| //// public void onSuccess(int i) { | |||
| //// } | |||
| // | |||
| // @Override | |||
| // public void onSuccess(int i, String s, String s1) { | |||
| // | |||
| // } | |||
| // | |||
| // @Override | |||
| // public void onFailure(int i, String s) { | |||
| // } | |||
| // }); | |||
| // } | |||
| // return true; | |||
| // } | |||
| if (url.contains("maliprod.alipay.com") && !url.contains("confirmGoods.do")) { | |||
| AlibcLogin.getInstance().showLogin(new AlibcLoginCallback() { | |||
| @Override | |||
| public void onSuccess(int i, String s, String s1) { | |||
| } | |||
| @Override | |||
| public void onFailure(int i, String s) { | |||
| } | |||
| }); | |||
| } | |||
| if (url.contains("intent://go/ju/webview?")) { | |||
| return true; | |||
| } | |||
| // if (url.contains("s.click.taobao.com")) { | |||
| // Logger.wtf(SPUtils.getPrefString(WebActivity.this, Pkey.IS_OPEN_TAOBAO, "")); | |||
| // if (SPUtils.getPrefString(WebActivity.this, Pkey.IS_OPEN_TAOBAO, "").equals("shoutao")) { | |||
| // if (!Token.isLogin()) { | |||
| // if (isFirst2Login) { | |||
| // ActivityJump.toLogin(WebActivity.this); | |||
| // } | |||
| // isFirst2Login = false; | |||
| // finish(); | |||
| // } else { | |||
| // if (isInstallTaoBao(WebActivity.this)) { | |||
| // jump2TaoBao(url); | |||
| // finish(); | |||
| // } else { | |||
| // view.loadUrl(url); | |||
| // } | |||
| // } | |||
| // return true; | |||
| // } | |||
| // } | |||
| // if (url.contains("kingcard.dgunicom.com") && url.contains("newMsg") && url.contains("fill.html")) { | |||
| // getItf(url); | |||
| // } | |||
| // else { | |||
| // Logger.wtf("123"); | |||
| // mainWeb.loadUrl(url); | |||
| // } | |||
| return super.shouldOverrideUrlLoading(view, url); | |||
| } | |||
| @Override | |||
| public void onPageStarted(WebView view, String url, Bitmap favicon) { | |||
| // WebLoad.setVisibility(View.GONE); | |||
| //开始加载设置为透明 | |||
| super.onPageStarted(view, url, favicon); | |||
| } | |||
| @Override | |||
| public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) { | |||
| super.onReceivedError(view, request, error); | |||
| } | |||
| @Override | |||
| public void onPageFinished(WebView view, String url) { | |||
| // WebLoad.setVisibility(View.GONE); | |||
| // // 获取页面内容 | |||
| view.loadUrl("javascript:window.java_obj.showSource(" | |||
| + "document.documentElement.innerText);"); | |||
| // 获取解析<meta name="share-description" content="获取到的值"> | |||
| view.loadUrl("javascript:window.java_obj.showDescription(" | |||
| + "document.querySelector('meta[name=\"share-description\"]').getAttribute('content')" | |||
| + ");"); | |||
| // quanyikaText(); | |||
| super.onPageFinished(view, url); | |||
| } | |||
| //处理 [Android]用WebView访问证书有问题的SSL网页 | |||
| //http://blog.sina.com.cn/s/blog_4cd978f90102vrxk.html | |||
| @Override | |||
| public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { | |||
| handler.proceed(); | |||
| } | |||
| } | |||
| } | |||
| @@ -1,12 +1,11 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <!-- Modify this file to customize your launch splash screen --> | |||
| <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> | |||
| <item android:drawable="@android:color/white" /> | |||
| <!-- <item android:drawable="@android:color/white" />--> | |||
| <!-- You can insert your own image assets here --> | |||
| <!-- <item> | |||
| <item> | |||
| <bitmap | |||
| android:gravity="center" | |||
| android:src="@mipmap/launch_image" /> | |||
| </item> --> | |||
| android:src="@drawable/bg_launcher" /> | |||
| </item> | |||
| </layer-list> | |||
| @@ -0,0 +1,26 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | |||
| android:layout_width="match_parent" | |||
| android:layout_height="match_parent"> | |||
| <TextView | |||
| android:id="@+id/tv_aliBc" | |||
| android:layout_width="wrap_content" | |||
| android:layout_height="wrap_content" | |||
| android:clickable="true" | |||
| android:text="登陆" | |||
| android:padding="12dp" | |||
| android:textColor="#FFFFFF" | |||
| android:focusable="true"> | |||
| </TextView> | |||
| <TextView | |||
| android:id="@+id/tv_open_detail" | |||
| android:layout_width="wrap_content" | |||
| android:layout_height="wrap_content" | |||
| android:focusable="true" | |||
| android:clickable="true" | |||
| android:text="打开淘宝详情" | |||
| /> | |||
| </LinearLayout> | |||
| @@ -0,0 +1,14 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | |||
| xmlns:app="http://schemas.android.com/apk/res-auto" | |||
| xmlns:tools="http://schemas.android.com/tools" | |||
| android:layout_width="match_parent" | |||
| android:layout_height="match_parent" | |||
| tools:context="cn.zhios.zhiying_base_widget_example.WebActivity"> | |||
| <WebView | |||
| android:id="@+id/webview_main" | |||
| android:layout_width="match_parent" | |||
| android:layout_height="match_parent"/> | |||
| </LinearLayout> | |||
| @@ -15,6 +15,10 @@ allprojects { | |||
| repositories { | |||
| google() | |||
| jcenter() | |||
| maven { | |||
| url "http://repo.baichuan-android.taobao.com/content/groups/BaichuanRepositories/" | |||
| } | |||
| } | |||
| } | |||
| @@ -13,6 +13,7 @@ import 'package:provider/provider.dart'; | |||
| import 'package:zhiying_comm/zhiying_comm.dart'; | |||
| import 'package:flutter_alibc/flutter_alibc.dart'; | |||
| import 'package:flutter_alibc/alibc_model.dart'; | |||
| import 'package:flutter_alibc/alibc_const_key.dart'; | |||
| class IntellectSearchGoodsDialog extends StatefulWidget { | |||
| final IntellectDialogDataModel model; | |||
| @@ -31,7 +32,6 @@ class _IntellectSearchGoodsDialogState | |||
| @override | |||
| void initState() { | |||
| requestStyle(); | |||
| super.initState(); | |||
| } | |||
| @@ -243,7 +243,10 @@ class _IntellectSearchGoodsDialogState | |||
| ), | |||
| ), | |||
| Text( | |||
| widget?.model?.price ?? "", | |||
| (num.tryParse(widget?.model?.price ?? "0") - | |||
| num.tryParse( | |||
| widget?.model?.couponPrice ?? "0")).toString() ?? | |||
| "", | |||
| style: TextStyle( | |||
| fontSize: 32.sp, | |||
| color: HexColor.fromHex( | |||
| @@ -281,12 +284,10 @@ class _IntellectSearchGoodsDialogState | |||
| child: Text( | |||
| (_styleModel?.moduleList?.saveBtn?.content ?? "") + | |||
| " ¥" + | |||
| ((double.tryParse( | |||
| widget?.model?.couponPrice ?? "0.0") ?? | |||
| ((num.tryParse(widget?.model?.couponPrice ?? "0") ?? | |||
| 0) + | |||
| double.tryParse( | |||
| num.tryParse( | |||
| widget?.model?.commission ?? '0')) | |||
| .toString() | |||
| .toString(), | |||
| style: TextStyle( | |||
| color: HexColor.fromHex( | |||
| @@ -353,17 +354,26 @@ class _IntellectSearchGoodsDialogState | |||
| RouterUtil.goLogin(context); | |||
| return; | |||
| } else { | |||
| print("平台"+widget?.model?.provider??""); | |||
| print("平台" + widget?.model?.provider ?? ""); | |||
| print("链接" + widget?.model?.couponUrl ?? ""); | |||
| if (widget?.model?.provider == 'taobao') { | |||
| TradeResult result = | |||
| await FlutterAlibc.openByUrl(url: widget?.model?.couponUrl??""); | |||
| TradeResult result = await FlutterAlibc.openByUrl( | |||
| url: widget?.model?.couponUrl ?? "", | |||
| openType: AlibcOpenType.AlibcOpenTypeNative, | |||
| backUrl: "alisdk://"); | |||
| Logger.debug('${result.errorCode} ${result.errorMessage} '); | |||
| print("链接"+widget?.model?.couponUrl??""); | |||
| print("错误码"+result.errorCode); | |||
| print("原因"+result.errorMessage); | |||
| print("链接" + widget?.model?.couponUrl ?? ""); | |||
| print("错误码" + result.errorCode); | |||
| print("原因" + result.errorMessage); | |||
| } else { | |||
| RouterUtil.openWebview(widget?.model?.couponUrl, context); | |||
| await FlutterAlibc.openByUrl( | |||
| url: widget?.model?.couponUrl, | |||
| openType: AlibcOpenType.AlibcOpenTypeNative); | |||
| } | |||
| ///关闭弹窗 | |||
| if (Navigator.canPop(context)) { | |||
| Navigator.pop(context); | |||
| } | |||
| } | |||
| } | |||
| @@ -10,6 +10,7 @@ class IntellectDialogDataModel { | |||
| String couponUrl; | |||
| String couponPrice; | |||
| IntellectDialogDataModel( | |||
| {this.itemId, | |||
| this.title, | |||
| @@ -0,0 +1,71 @@ | |||
| import 'package:flutter/material.dart'; | |||
| import 'package:zhiying_comm/zhiying_comm.dart'; | |||
| class TipDialog extends StatelessWidget { | |||
| String title; | |||
| TipDialog({this.title = "温馨提示", this.content}); | |||
| String content; | |||
| @override | |||
| Widget build(BuildContext context) { | |||
| return Scaffold( | |||
| backgroundColor: Colors.transparent, | |||
| body: Column( | |||
| mainAxisAlignment: MainAxisAlignment.center, | |||
| crossAxisAlignment: CrossAxisAlignment.center, | |||
| children: <Widget>[ | |||
| Container( | |||
| width: double.infinity, | |||
| decoration: BoxDecoration( | |||
| color: Colors.white, borderRadius: BorderRadius.circular(20)), | |||
| margin: EdgeInsets.only(left: 91.w, right: 91.w), | |||
| child: Column( | |||
| children: <Widget>[ | |||
| Padding( | |||
| padding: const EdgeInsets.only(top: 16), | |||
| child: Text( | |||
| title, | |||
| style: TextStyle(fontSize: 30.sp,fontWeight: FontWeight.w400), | |||
| ), | |||
| ), | |||
| Container( | |||
| margin: EdgeInsets.all(16), | |||
| constraints: BoxConstraints(minHeight: 100), | |||
| child: Text( | |||
| content, | |||
| style: TextStyle(fontSize: 26.sp), | |||
| ), | |||
| ), | |||
| Row( | |||
| children: <Widget>[ | |||
| Expanded( | |||
| child: Padding( | |||
| padding: const EdgeInsets.only( | |||
| left: 16, right: 16, bottom: 16), | |||
| child: FlatButton( | |||
| padding: EdgeInsets.only(top: 10, bottom: 10), | |||
| color: HexColor.fromHex("#FFFF4242"), | |||
| shape: RoundedRectangleBorder( | |||
| borderRadius: BorderRadius.circular(50)), | |||
| onPressed: () { | |||
| Navigator.pop(context); | |||
| }, | |||
| child: Text( | |||
| "知道了", | |||
| style: TextStyle( | |||
| color: HexColor.fromHex("#FFFFFF"), | |||
| fontSize: 26.sp), | |||
| )), | |||
| )) | |||
| ], | |||
| ) | |||
| ], | |||
| ), | |||
| ) | |||
| ], | |||
| ), | |||
| ); | |||
| } | |||
| } | |||
| @@ -1,6 +1,22 @@ | |||
| import 'dart:convert'; | |||
| import 'package:flutter/material.dart'; | |||
| import 'package:pull_to_refresh/pull_to_refresh.dart'; | |||
| import 'package:zhiying_base_widget/pages/hot_ranking_page/hot_ranking_page_sk.dart'; | |||
| import 'package:zhiying_base_widget/pages/main_page/notifier/main_page_bg_notifier.dart'; | |||
| import 'package:zhiying_base_widget/pages/main_page/notifier/main_page_notifier.dart'; | |||
| import 'package:zhiying_base_widget/utils/contants.dart'; | |||
| import 'package:zhiying_comm/util/base_bloc.dart'; | |||
| import 'package:zhiying_comm/zhiying_comm.dart'; | |||
| import 'package:provider/provider.dart'; | |||
| import 'hot_ranking_page_bloc.dart'; | |||
| class HotRankingPage extends StatefulWidget { | |||
| final Map<String, dynamic> data; | |||
| const HotRankingPage(this.data, {Key key}) : super(key: key); | |||
| @override | |||
| _HotRankingPageState createState() => _HotRankingPageState(); | |||
| } | |||
| @@ -10,7 +26,6 @@ class _HotRankingPageState extends State<HotRankingPage> { | |||
| Widget build(BuildContext context) { | |||
| print('hot_ranking_page build'); | |||
| // | |||
| // List<Widget> contentWidgets = tabs.map((item) { | |||
| // BaseTabModel model = BaseTabModel.fromJson(item); | |||
| @@ -19,6 +34,134 @@ class _HotRankingPageState extends State<HotRankingPage> { | |||
| // if (_currentIndex >= contentWidgets.length) { | |||
| // _currentIndex = 0; | |||
| // } | |||
| return Scaffold(); | |||
| return Scaffold( | |||
| backgroundColor: Color(0xfff9f9f9), | |||
| body: MultiProvider( | |||
| providers: [ | |||
| ChangeNotifierProvider.value(value: MainPageBgNotifier()), | |||
| ], | |||
| child: BlocProvider<HotRankingPageBloc>( | |||
| bloc: HotRankingPageBloc(), | |||
| child: _HotRankingPageContainer(data: widget.data), | |||
| ), | |||
| ), | |||
| ); | |||
| } | |||
| } | |||
| class _HotRankingPageContainer extends StatefulWidget { | |||
| final Map<String, dynamic> data; | |||
| const _HotRankingPageContainer({Key key, this.data}) : super(key: key); | |||
| @override | |||
| __HotRankingPageContainerState createState() => | |||
| __HotRankingPageContainerState(); | |||
| } | |||
| class __HotRankingPageContainerState extends State<_HotRankingPageContainer> { | |||
| HotRankingPageBloc _bloc; | |||
| RefreshController _refreshController; | |||
| String backgroundImage; | |||
| @override | |||
| void initState() { | |||
| _refreshController = RefreshController(); | |||
| _bloc = BlocProvider.of<HotRankingPageBloc>(context); | |||
| if (widget.data.containsKey(Constants.SkipIdentifierName)) { | |||
| _bloc.loadData(widget.data[Constants.SkipIdentifierName]); | |||
| } | |||
| super.initState(); | |||
| } | |||
| @override | |||
| Widget build(BuildContext context) { | |||
| return StreamBuilder( | |||
| stream: _bloc.outData, | |||
| builder: (context, asyncSnapshot) { | |||
| var model = asyncSnapshot.data; | |||
| if (model == null) { | |||
| return HotRankingPageSkeleton(); | |||
| } | |||
| for (var item in model) { | |||
| WidgetModel widgetModel = | |||
| WidgetModel.fromJson(Map<String, dynamic>.from(item)); | |||
| if (item.containsKey("mod_name") && | |||
| item['mod_name'] == "hot_rank_bg_img") { | |||
| _bloc.backgroundImage = json.decode(item['data'])['bg_img']; | |||
| break; | |||
| } | |||
| } | |||
| return Stack( | |||
| children: <Widget>[ | |||
| Container( | |||
| height: 293.h, | |||
| decoration: BoxDecoration( | |||
| image: DecorationImage( | |||
| image: CachedNetworkImageProvider( | |||
| _bloc.backgroundImage ?? ""), | |||
| fit: BoxFit.fill)), | |||
| ), | |||
| Column( | |||
| children: _createContent(context, model), | |||
| ) | |||
| ], | |||
| ); | |||
| }, | |||
| ); | |||
| } | |||
| //刷新 | |||
| void _onLoading() async {} | |||
| ///构建子模块 | |||
| _createContent(BuildContext context, List<Map<String, dynamic>> model) { | |||
| List<Widget> list = List(); | |||
| if (model == null) { | |||
| ///骨架图 | |||
| } else { | |||
| for (var item in model) { | |||
| WidgetModel widgetModel = | |||
| WidgetModel.fromJson(Map<String, dynamic>.from(item)); | |||
| if (item.containsKey("mod_name") && | |||
| item['mod_name'] == "hot_rank_tab_view") { | |||
| list.add(Expanded( | |||
| child: WidgetFactory.create(widgetModel.modName, | |||
| isSliver: false, model: item)[0])); | |||
| continue; | |||
| } | |||
| list.addAll(WidgetFactory.create(widgetModel.modName, | |||
| isSliver: false, model: item)); | |||
| } | |||
| } | |||
| return list; | |||
| } | |||
| } | |||
| class _SilverAppBarDelegate extends SliverPersistentHeaderDelegate { | |||
| _SilverAppBarDelegate(BuildContext context, this.child) { | |||
| this.context = context; | |||
| } | |||
| BuildContext context; | |||
| final Widget child; | |||
| @override | |||
| double get minExtent => MediaQuery.of(context).padding.top + 44; | |||
| @override | |||
| double get maxExtent => MediaQuery.of(context).padding.top + 44; | |||
| @override | |||
| Widget build( | |||
| BuildContext context, double shrinkOffset, bool overlapsContent) { | |||
| return child; | |||
| } | |||
| @override | |||
| bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) { | |||
| return false; | |||
| } | |||
| } | |||
| @@ -3,42 +3,49 @@ import 'dart:async'; | |||
| import 'package:zhiying_comm/util/base_bloc.dart'; | |||
| import 'package:zhiying_comm/zhiying_comm.dart'; | |||
| class HotRankingPage extends BlocBase { | |||
| class HotRankingPageBloc extends BlocBase { | |||
| List<Map<String, dynamic>> _pageData = List(); | |||
| StreamController<List<Map<String, dynamic>>> _dataController = | |||
| StreamController<List<Map<String, dynamic>>>(); | |||
| StreamController<List<Map<String, dynamic>>>(); | |||
| Stream<List<Map<String, dynamic>>> get outData => _dataController.stream; | |||
| StreamController<Map<String, dynamic>> _eventController = | |||
| StreamController.broadcast(); | |||
| Stream<Map<String, dynamic>> get event => _eventController.stream; | |||
| String backgroundImage; | |||
| @override | |||
| void dispose() { | |||
| _dataController.close(); | |||
| _eventController.close(); | |||
| _dataController = null; | |||
| _eventController.close(); | |||
| } | |||
| void loadData(int id) { | |||
| NetUtil.request('/api/v1/mod', | |||
| method: NetMethod.POST, | |||
| params: Map<String, dynamic>.from({ | |||
| 'ids': [id] | |||
| }), onCache: (data) { | |||
| _loadData(id, data); | |||
| }, onSuccess: (data) { | |||
| _loadData(id, data); | |||
| }); | |||
| loadData(String skipIdentifier) { | |||
| NetUtil.request('/api/v1/mod/${skipIdentifier}', method: NetMethod.GET, | |||
| onCache: (data) { | |||
| _loadData(data); | |||
| }, onSuccess: (data) { | |||
| print(data); | |||
| _loadData(data); | |||
| }); | |||
| } | |||
| void _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(); | |||
| } | |||
| void _loadData(dynamic data) { | |||
| print(data["mod_lis"]); | |||
| _pageData = List.from(data["mod_list"]).map((v) { | |||
| return Map<String, dynamic>.from(v); | |||
| }).toList(); | |||
| _dataController.add(_pageData); | |||
| } | |||
| void sendEvent(Map<String,dynamic> event){ | |||
| _eventController.add(event); | |||
| } | |||
| } | |||
| @@ -0,0 +1,91 @@ | |||
| import 'package:flutter/material.dart'; | |||
| import 'package:shimmer/shimmer.dart'; | |||
| class HotRankingPageSkeleton extends StatelessWidget { | |||
| @override | |||
| Widget build(BuildContext context) { | |||
| return Shimmer.fromColors( | |||
| baseColor: Colors.grey[300], | |||
| highlightColor: Colors.grey[100], | |||
| child: Column( | |||
| mainAxisSize: MainAxisSize.min, | |||
| children: <Widget>[ | |||
| Container( | |||
| color: Colors.white, | |||
| width: double.infinity, | |||
| height: 96, | |||
| ), | |||
| Container( | |||
| width: double.infinity, | |||
| margin: EdgeInsets.all(16), | |||
| height: 48, | |||
| child: Row( | |||
| children: _buildTopRow(), | |||
| )), | |||
| Expanded( | |||
| child: Container( | |||
| child: Column( | |||
| children: _buildBottomListItem(), | |||
| ), | |||
| )) | |||
| ], | |||
| ), | |||
| ); | |||
| } | |||
| _buildBottomListItem() { | |||
| List<Widget> listWidget = List(); | |||
| for (var index = 0; index < 3; index++) { | |||
| listWidget.add(Container( | |||
| margin: EdgeInsets.only(left: 16, top: 10, bottom: 10), | |||
| child: Row( | |||
| children: <Widget>[ | |||
| Container( | |||
| width: 127, | |||
| height: 127, | |||
| color: Colors.white, | |||
| ), | |||
| Container( | |||
| height: 127, | |||
| margin: EdgeInsets.only(left: 10), | |||
| child: Column( | |||
| mainAxisAlignment: MainAxisAlignment.spaceBetween, | |||
| crossAxisAlignment: CrossAxisAlignment.start, | |||
| children: <Widget>[ | |||
| Container( | |||
| height: 40, | |||
| width: 200, | |||
| color: Colors.white, | |||
| ), | |||
| Container( | |||
| height: 30, | |||
| width: 100, | |||
| color: Colors.grey, | |||
| ), | |||
| Container( | |||
| height: 30, | |||
| width: 200, | |||
| color: Colors.grey, | |||
| ) | |||
| ], | |||
| ), | |||
| ) | |||
| ], | |||
| ), | |||
| )); | |||
| } | |||
| return listWidget; | |||
| } | |||
| _buildTopRow() { | |||
| List<Widget> listWidget = List(); | |||
| for (var index = 0; index < 5; index++) { | |||
| listWidget.add(Container( | |||
| width: 50, | |||
| color: Colors.white, | |||
| margin: EdgeInsets.all(10), | |||
| )); | |||
| } | |||
| return listWidget; | |||
| } | |||
| } | |||
| @@ -6,13 +6,17 @@ import 'package:zhiying_base_widget/pages/main_page/notifier/main_page_bg_notifi | |||
| import 'package:zhiying_base_widget/pages/main_page/notifier/main_page_notifier.dart'; | |||
| import 'package:zhiying_base_widget/utils/contants.dart'; | |||
| import 'package:zhiying_base_widget/widgets/others/mine_header_bg_widget.dart'; | |||
| import 'package:zhiying_base_widget/widgets/wallet/wallet_appbar/wallet_appbar_sk.dart'; | |||
| import 'package:zhiying_base_widget/widgets/wallet/wallet_data/wallet_data_sk.dart'; | |||
| import 'package:zhiying_base_widget/widgets/wallet/wallet_detail/wallet_detail_sk.dart'; | |||
| import 'package:zhiying_base_widget/widgets/wallet/wallet_income/wallet_income_sk.dart'; | |||
| import 'package:zhiying_comm/zhiying_comm.dart'; | |||
| import 'package:zhiying_comm/util/base_bloc.dart'; | |||
| import 'package:zhiying_comm/util/custom_sliver_persistent_header_delegate.dart'; | |||
| import 'wallet_page_bloc.dart'; | |||
| import 'wallet_page_bloc.dart'; | |||
| ///钱包页面 | |||
| class WalletPage extends StatefulWidget { | |||
| final Map<String, dynamic> data; | |||
| @@ -77,8 +81,8 @@ class _WalletPageContainerState extends State<_WalletPageContainer> { | |||
| ScreenUtil.init(context, width: 750, height: 1334); | |||
| return SmartRefresher( | |||
| controller: _refreshController, | |||
| enablePullDown: false, | |||
| enablePullUp: false, | |||
| enablePullDown: true, | |||
| enablePullUp:true, | |||
| header: WaterDropHeader(), | |||
| onLoading: _onLoading, | |||
| child: Container( | |||
| @@ -86,15 +90,17 @@ class _WalletPageContainerState extends State<_WalletPageContainer> { | |||
| child: Stack( | |||
| fit: StackFit.passthrough, | |||
| children: <Widget>[ | |||
| MineHeaderBgWidget( | |||
| controller: _controller, | |||
| ), | |||
| StreamBuilder( | |||
| stream: _pageBloc.outData, | |||
| builder: (context, asyncSnapshot) { | |||
| var model = asyncSnapshot.data; | |||
| return CustomScrollView( | |||
| slivers: _createContent(context, model), | |||
| return Stack( | |||
| children: <Widget>[ | |||
| Container(height: 362.h, color: _pageBloc.backgroundColor), | |||
| CustomScrollView( | |||
| slivers: _createContent(context, model), | |||
| ) | |||
| ], | |||
| ); | |||
| }, | |||
| ) | |||
| @@ -108,37 +114,33 @@ class _WalletPageContainerState extends State<_WalletPageContainer> { | |||
| BuildContext context, List<Map<String, dynamic>> model) { | |||
| List<Widget> list = List(); | |||
| if (model == null) { | |||
| list.addAll(WidgetFactory.create( | |||
| 'normal_nav', | |||
| isSliver: true, | |||
| model: Map(), | |||
| ///骨架图 | |||
| list.add(SliverToBoxAdapter( | |||
| child: WalletAppbarSkeleton(), | |||
| )); | |||
| list.addAll(WidgetFactory.create( | |||
| 'wallet_data', | |||
| isSliver: true, | |||
| model: Map(), | |||
| list.add(SliverToBoxAdapter( | |||
| child: WalletDataSkeleton(), | |||
| )); | |||
| list.addAll(WidgetFactory.create( | |||
| 'wallet_detail', | |||
| isSliver: true, | |||
| model: Map(), | |||
| list.add(SliverToBoxAdapter( | |||
| child: WalletIncomeSkeleton(), | |||
| )); | |||
| list.addAll(WidgetFactory.create( | |||
| 'wallet_income', | |||
| isSliver: true, | |||
| model: Map(), | |||
| list.add(SliverToBoxAdapter( | |||
| child: WalletDetailSkeleton(), | |||
| )); | |||
| } else { | |||
| for (var item in model) { | |||
| WidgetModel widgetModel = | |||
| WidgetModel.fromJson(Map<String, dynamic>.from(item)); | |||
| if (item.containsKey("mod_name")&&item['mod_name']=="my_wallet_appbar") { | |||
| if (item.containsKey("mod_name") && | |||
| item['mod_name'] == "my_wallet_appbar") { | |||
| list.add(SliverPersistentHeader( | |||
| delegate: _SilverAppBarDelegate(context, | |||
| WidgetFactory.create(widgetModel.modName, | |||
| isSliver: false, model: item)[0]),pinned: true,)); | |||
| continue; | |||
| delegate: _SilverAppBarDelegate( | |||
| context, | |||
| WidgetFactory.create(widgetModel.modName, | |||
| isSliver: false, model: item)[0]), | |||
| pinned: true, | |||
| )); | |||
| continue; | |||
| } | |||
| list.addAll(WidgetFactory.create(widgetModel.modName, | |||
| isSliver: true, model: item)); | |||
| @@ -149,23 +151,23 @@ class _WalletPageContainerState extends State<_WalletPageContainer> { | |||
| } | |||
| class _SilverAppBarDelegate extends SliverPersistentHeaderDelegate { | |||
| _SilverAppBarDelegate(BuildContext context,this.child){ | |||
| this.context=context; | |||
| _SilverAppBarDelegate(BuildContext context, this.child) { | |||
| this.context = context; | |||
| } | |||
| BuildContext context; | |||
| final Widget child; | |||
| @override | |||
| double get minExtent => MediaQuery.of(context).padding.top+44; | |||
| double get minExtent => MediaQuery.of(context).padding.top + 44; | |||
| @override | |||
| double get maxExtent => MediaQuery.of(context).padding.top+44; | |||
| double get maxExtent => MediaQuery.of(context).padding.top + 44; | |||
| @override | |||
| Widget build( | |||
| BuildContext context, double shrinkOffset, bool overlapsContent) { | |||
| return child; | |||
| } | |||
| @override | |||
| @@ -1,16 +1,22 @@ | |||
| import 'dart:async'; | |||
| import 'dart:convert'; | |||
| import 'package:flutter/cupertino.dart'; | |||
| import 'package:flutter/material.dart'; | |||
| import 'package:zhiying_base_widget/utils/contants.dart'; | |||
| import 'package:zhiying_base_widget/widgets/wallet/wallet_appbar/model/WalletAppbarModel.dart'; | |||
| import 'package:zhiying_base_widget/widgets/wallet/wallet_data/model/wallet_header_model.dart'; | |||
| import 'package:zhiying_comm/util/base_bloc.dart'; | |||
| import 'package:zhiying_comm/zhiying_comm.dart'; | |||
| class WalletPageBloc extends BlocBase { | |||
| List<Map<String, dynamic>> _tabs = List(); | |||
| StreamController<List<Map<String, dynamic>>> _tabController = | |||
| StreamController<List<Map<String, dynamic>>>(); | |||
| Stream<List<Map<String, dynamic>>> get outData => _tabController.stream; | |||
| Color backgroundColor = Colors.transparent; | |||
| @override | |||
| void dispose() { | |||
| _tabController.close(); | |||
| @@ -34,6 +40,14 @@ class WalletPageBloc extends BlocBase { | |||
| var list = List.from(data["mod_list"]).map((v) { | |||
| return Map<String, dynamic>.from(v); | |||
| }).toList(); | |||
| for (var item in list) { | |||
| if (item['mod_name'] == "my_wallet_appbar") { | |||
| WalletAppbarModel walletAppbarModel = | |||
| WalletAppbarModel.fromJson(json.decode(item["data"])); | |||
| backgroundColor = HexColor.fromHex(walletAppbarModel.appBarBgColor); | |||
| break; | |||
| } | |||
| } | |||
| _tabController.add(list); | |||
| } | |||
| } | |||
| @@ -3,6 +3,7 @@ import 'package:sharesdk_plugin/sharesdk_register.dart'; | |||
| import 'package:zhiying_base_widget/pages/favorite_page/favorite_page.dart'; | |||
| import 'package:zhiying_base_widget/pages/goods_details_page/goods_details_page.dart'; | |||
| import 'package:zhiying_base_widget/pages/home_page/home_page.dart'; | |||
| import 'package:zhiying_base_widget/pages/hot_ranking_page/hot_ranking_page.dart'; | |||
| import 'package:zhiying_base_widget/pages/invited_friends/invited_friends.dart'; | |||
| import 'package:zhiying_base_widget/pages/launch_page/launch_page.dart'; | |||
| import 'package:zhiying_base_widget/pages/main_page/main_page.dart'; | |||
| @@ -29,6 +30,9 @@ import 'package:zhiying_base_widget/widgets/home/home_goods/home_goods_creater.d | |||
| import 'package:zhiying_base_widget/widgets/home/home_notice/home_notice_widget.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/hot_ranking/hot_ranking_appbar/hot_ranking_appbar.dart'; | |||
| import 'package:zhiying_base_widget/widgets/hot_ranking/hot_ranking_list/hot_ranking_list.dart'; | |||
| import 'package:zhiying_base_widget/widgets/hot_ranking/hot_tab_bar/hot_tab_bar.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'; | |||
| @@ -99,6 +103,8 @@ class BaseWidgetRegister { | |||
| PageFactory.regist('homePage', (model) => HomePage()); | |||
| PageFactory.regist('pub.flutter.index', (model) => MainPage(model)); | |||
| PageFactory.regist('pub.flutter.profile', (model) => MainPage(model)); | |||
| PageFactory.regist( | |||
| 'pub.flutter.hot_rank', (model) => HotRankingPage(model)); | |||
| PageFactory.regist( | |||
| 'pub.flutter.my_wallet', (model) => WalletPage(data: model)); | |||
| PageFactory.regist('goods_details', (model) => GoodsDetailsPage(model)); | |||
| @@ -304,5 +310,11 @@ class BaseWidgetRegister { | |||
| 'wallet_income', DefaultWidgetCreater((model) => WalletIncome())); | |||
| //======================= 账单明细 | |||
| //======================== 热榜 | |||
| WidgetFactory.regist('hot_rank_appbar', DefaultWidgetCreater((model)=>HotRankingAppBar(model))); | |||
| WidgetFactory.regist('hot_rank_tabs', DefaultWidgetCreater((model)=>HotRankTableBar(model))); | |||
| WidgetFactory.regist('hot_rank_tab_view', DefaultWidgetCreater((model)=>HotRankingList(model))); | |||
| } | |||
| } | |||
| @@ -99,7 +99,7 @@ class _GooddsDetailsFooterContainerState | |||
| return; | |||
| } | |||
| if (shopType == 'taobao') { | |||
| TradeResult result = await FlutterAlibc.openByUrl(url: url); | |||
| TradeResult result = await FlutterAlibc.openByUrl(url: url,backUrl: "alisdk://"); | |||
| Logger.debug('${result.errorCode} ${result.errorMessage} '); | |||
| } else { | |||
| RouterUtil.openWebview(url, context); | |||
| @@ -0,0 +1,49 @@ | |||
| import 'dart:convert'; | |||
| import 'package:flutter/material.dart'; | |||
| import 'package:zhiying_base_widget/widgets/hot_ranking/hot_ranking_appbar/model/hot_ranking_appbaar_model.dart'; | |||
| import 'package:zhiying_comm/util/extension/color.dart'; | |||
| import 'package:zhiying_comm/zhiying_comm.dart'; | |||
| class HotRankingAppBar extends StatelessWidget { | |||
| final Map<String, dynamic> data; | |||
| const HotRankingAppBar(this.data, {Key key}) : super(key: key); | |||
| @override | |||
| Widget build(BuildContext context) { | |||
| var model = HotRankingAppbarModel.fromJson(json.decode(data['data'])); | |||
| return Container( | |||
| height: MediaQuery.of(context).padding.top + 56, | |||
| child: AppBar( | |||
| elevation: 0, | |||
| leading: Navigator.canPop(context) | |||
| ? IconButton( | |||
| icon: Icon(Icons.arrow_back_ios), | |||
| onPressed: () { | |||
| Navigator.of(context).pop(); | |||
| }) | |||
| : Container(), | |||
| backgroundColor: HexColor.fromHex(model.appBarBgColor==""?"#00000000":model.appBarBgColor), | |||
| centerTitle: true, | |||
| title: Container( | |||
| child: Stack( | |||
| alignment: Alignment.center, | |||
| children: <Widget>[ | |||
| Text( | |||
| model.appBarName??"", | |||
| style: | |||
| TextStyle(color: HexColor.fromHex(model.appBarNameColor??"")), | |||
| ), | |||
| CachedNetworkImage( | |||
| height: 40.w, | |||
| width: 144.w, | |||
| imageUrl: model.appBarNameImg??"", | |||
| fit: BoxFit.fill, | |||
| ) | |||
| ], | |||
| ), | |||
| )), | |||
| ); | |||
| } | |||
| } | |||
| @@ -0,0 +1,32 @@ | |||
| class HotRankingAppbarModel { | |||
| String appBarName; | |||
| String appBarNameColor; | |||
| String appBarBgImg; | |||
| String appBarBgColor; | |||
| String appBarNameImg; | |||
| HotRankingAppbarModel( | |||
| {this.appBarName, | |||
| this.appBarNameColor, | |||
| this.appBarBgImg, | |||
| this.appBarBgColor, | |||
| this.appBarNameImg}); | |||
| HotRankingAppbarModel.fromJson(Map<String, dynamic> json) { | |||
| appBarName = json['app_bar_name']; | |||
| appBarNameColor = json['app_bar_name_color']; | |||
| appBarBgImg = json['app_bar_bg_img']; | |||
| appBarBgColor = json['app_bar_bg_color']; | |||
| appBarNameImg = json['app_bar_name_img']; | |||
| } | |||
| Map<String, dynamic> toJson() { | |||
| final Map<String, dynamic> data = new Map<String, dynamic>(); | |||
| data['app_bar_name'] = this.appBarName; | |||
| data['app_bar_name_color'] = this.appBarNameColor; | |||
| data['app_bar_bg_img'] = this.appBarBgImg; | |||
| data['app_bar_bg_color'] = this.appBarBgColor; | |||
| data['app_bar_name_img'] = this.appBarNameImg; | |||
| return data; | |||
| } | |||
| } | |||
| @@ -1,44 +0,0 @@ | |||
| import 'dart:async'; | |||
| import 'package:zhiying_comm/util/base_bloc.dart'; | |||
| import 'package:zhiying_comm/zhiying_comm.dart'; | |||
| class HotRankingBloc extends BlocBase { | |||
| List<Map<String, dynamic>> _pageData = List(); | |||
| StreamController<List<Map<String, dynamic>>> _dataController = | |||
| StreamController<List<Map<String, dynamic>>>(); | |||
| Stream<List<Map<String, dynamic>>> get outData => _dataController.stream; | |||
| @override | |||
| void dispose() { | |||
| _dataController.close(); | |||
| _dataController = null; | |||
| } | |||
| void loadData(int id) { | |||
| NetUtil.request('/api/v1/mod', | |||
| method: NetMethod.POST, | |||
| params: Map<String, dynamic>.from({ | |||
| 'ids': [id] | |||
| }), onCache: (data) { | |||
| _loadData(id, data); | |||
| }, onSuccess: (data) { | |||
| _loadData(id, data); | |||
| }); | |||
| } | |||
| void _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(); | |||
| } | |||
| _dataController.add(_pageData); | |||
| } | |||
| } | |||
| @@ -1,91 +0,0 @@ | |||
| import 'package:flutter/material.dart'; | |||
| import 'package:zhiying_base_widget/widgets/hot_ranking/hot_ranking_bloc.dart'; | |||
| import 'package:zhiying_base_widget/widgets/hot_ranking/hot_ranking_goods/hot_ranking_goods.dart'; | |||
| import 'package:zhiying_base_widget/widgets/hot_ranking/hot_ranking_sk.dart'; | |||
| class HotRankingContainer extends StatefulWidget { | |||
| final Map<String, dynamic> data; | |||
| const HotRankingContainer({Key key, this.data}) : super(key: key); | |||
| @override | |||
| _HotRankingState createState() => _HotRankingState(); | |||
| } | |||
| class _HotRankingState extends State<HotRankingContainer> | |||
| with TickerProviderStateMixin { | |||
| HotRankingBloc _bloc; | |||
| TabController _tabController; | |||
| @override | |||
| void initState() { | |||
| _bloc = HotRankingBloc(); | |||
| super.initState(); | |||
| } | |||
| _buildTabs() { | |||
| List<Widget> listWidget = List(); | |||
| for (int index = 0; index < 4; index++) { | |||
| listWidget.add(Tab( | |||
| text: "hahah", | |||
| )); | |||
| } | |||
| return listWidget; | |||
| } | |||
| @override | |||
| void dispose() { | |||
| _tabController.dispose(); | |||
| super.dispose(); | |||
| } | |||
| ///构建 | |||
| void createTabController() { | |||
| _tabController = TabController(length: 4, vsync: this); | |||
| } | |||
| ///构建TabView | |||
| _buildTabView() { | |||
| List<Widget> listWidget = List(); | |||
| for (var index = 0; index < 4; index++) { | |||
| listWidget.add(ListView.builder( | |||
| padding: EdgeInsets.all(0), | |||
| itemCount: 10, | |||
| itemBuilder: (context, index) { | |||
| return Container( | |||
| child: HotRankingGoods(), | |||
| ); | |||
| })); | |||
| } | |||
| return listWidget; | |||
| } | |||
| @override | |||
| Widget build(BuildContext context) { | |||
| return StreamBuilder( | |||
| stream: _bloc.outData, | |||
| builder: (context, snapshot) { | |||
| if (snapshot.data != null) { | |||
| return HotRankingSkeleton(); | |||
| } else { | |||
| createTabController(); | |||
| return Container( | |||
| child: Column( | |||
| children: <Widget>[ | |||
| TabBar( | |||
| controller: _tabController, | |||
| isScrollable: true, | |||
| tabs: _buildTabs(), | |||
| ), | |||
| Expanded( | |||
| child: TabBarView( | |||
| controller: _tabController, | |||
| children: _buildTabView())) | |||
| ], | |||
| ), | |||
| ); | |||
| } | |||
| }); | |||
| } | |||
| } | |||
| @@ -1,218 +1,290 @@ | |||
| import 'package:flutter/material.dart'; | |||
| import 'package:flutter_screenutil/flutter_screenutil.dart'; | |||
| import 'package:zhiying_base_widget/widgets/home/home_quick_entry/cached_network_image_util.dart'; | |||
| import 'package:zhiying_base_widget/widgets/hot_ranking/hot_ranking_list/model/hot_ranking_list_data_model.dart'; | |||
| import 'package:zhiying_base_widget/widgets/hot_ranking/hot_ranking_list/model/hot_ranking_list_model.dart'; | |||
| import 'package:zhiying_comm/zhiying_comm.dart'; | |||
| import 'package:cached_network_image/cached_network_image.dart'; | |||
| import 'package:zhiying_comm/zhiying_comm.dart'; | |||
| class HotRankingGoods extends StatelessWidget { | |||
| Good good; | |||
| HotRankingListModel styleModel; | |||
| int index; | |||
| HotRankingGoods({Key key, this.good, this.styleModel, this.index}) | |||
| : super(key: key); | |||
| @override | |||
| Widget build(BuildContext context) { | |||
| return Stack( | |||
| children: <Widget>[ | |||
| Container( | |||
| padding: EdgeInsets.all(15.w), | |||
| margin: | |||
| EdgeInsets.only(top: 8.w, bottom: 8.w, left: 25.w, right: 25.w), | |||
| decoration: BoxDecoration( | |||
| color: Colors.white, borderRadius: BorderRadius.circular(15.w)), | |||
| child: Row( | |||
| crossAxisAlignment: CrossAxisAlignment.start, | |||
| children: <Widget>[ | |||
| Container( | |||
| width: 254.w, | |||
| height: 254.w, | |||
| color: Colors.amber, | |||
| ), | |||
| Expanded( | |||
| child: Container( | |||
| margin: EdgeInsets.only(left: 20.w), | |||
| child: Column( | |||
| mainAxisSize: MainAxisSize.max, | |||
| children: <Widget>[ | |||
| Container( | |||
| height: 70.h, | |||
| child: Row( | |||
| children: <Widget>[ | |||
| Expanded( | |||
| child: RichText( | |||
| overflow: TextOverflow.ellipsis, | |||
| maxLines: 2, | |||
| text: TextSpan(children: <InlineSpan>[ | |||
| WidgetSpan( | |||
| child: Container( | |||
| decoration: BoxDecoration( | |||
| color: Colors.red, | |||
| borderRadius: | |||
| BorderRadius.circular(4)), | |||
| child: Padding( | |||
| padding: EdgeInsets.only( | |||
| left: 4.w, right: 4.w), | |||
| child: Text( | |||
| "京东", | |||
| var indexImage; | |||
| if (styleModel.hotRankIconList != null && | |||
| styleModel.hotRankIconList.length > 0 && | |||
| styleModel.hotRankIconList.length - 1 >= index) { | |||
| indexImage = styleModel.hotRankIconList[index]; | |||
| } | |||
| Providers providers = getProvider(good.provider); | |||
| return GestureDetector( | |||
| onTap: () { | |||
| RouterUtil.route(SkipModel(skipIdentifier: "goods_details"), | |||
| {"provider": good.provider, "good_id": good.goodId}, context); | |||
| }, | |||
| child: Stack( | |||
| children: <Widget>[ | |||
| Container( | |||
| padding: EdgeInsets.all(15.w), | |||
| margin: | |||
| EdgeInsets.only(top: 8.w, bottom: 8.w, left: 25.w, right: 25.w), | |||
| decoration: BoxDecoration( | |||
| color: Colors.white, borderRadius: BorderRadius.circular(15.w)), | |||
| child: Row( | |||
| crossAxisAlignment: CrossAxisAlignment.start, | |||
| children: <Widget>[ | |||
| Container( | |||
| width: 254.w, | |||
| height: 254.w, | |||
| decoration: BoxDecoration( | |||
| borderRadius: BorderRadius.circular(6), | |||
| image: DecorationImage( | |||
| image: CachedNetworkImageProvider(good.goodImage))), | |||
| ), | |||
| Expanded( | |||
| child: Container( | |||
| margin: EdgeInsets.only(left: 20.w), | |||
| child: Column( | |||
| mainAxisSize: MainAxisSize.max, | |||
| children: <Widget>[ | |||
| Container( | |||
| height: 70.h, | |||
| child: Row( | |||
| children: <Widget>[ | |||
| Expanded( | |||
| child: RichText( | |||
| overflow: TextOverflow.ellipsis, | |||
| maxLines: 2, | |||
| text: TextSpan(children: <InlineSpan>[ | |||
| WidgetSpan( | |||
| child: Container( | |||
| decoration: BoxDecoration( | |||
| color: HexColor.fromHex( | |||
| providers.providerBgColor), | |||
| borderRadius: | |||
| BorderRadius.circular(4)), | |||
| child: Padding( | |||
| padding: EdgeInsets.only( | |||
| left: 4.w, right: 4.w), | |||
| child: Text( | |||
| good.providerName ?? "", | |||
| style: TextStyle( | |||
| color: HexColor.fromHex( | |||
| providers.providerNameColor, | |||
| ), | |||
| fontSize: 18.sp), | |||
| ), | |||
| ), | |||
| )), | |||
| WidgetSpan( | |||
| child: SizedBox( | |||
| width: 4.h, | |||
| )), | |||
| TextSpan( | |||
| text: good.goodTitle, | |||
| style: TextStyle( | |||
| color: HexColor.fromHex( | |||
| "#FFFFFF", | |||
| ), | |||
| fontSize: 18.sp), | |||
| ), | |||
| ), | |||
| )), | |||
| WidgetSpan( | |||
| child: SizedBox( | |||
| width: 4.h, | |||
| )), | |||
| TextSpan( | |||
| text: | |||
| "Segway Ninebot mini Pro九号平衡车智能代步...", | |||
| style: TextStyle( | |||
| color: Colors.black, | |||
| fontSize: 30.sp)) | |||
| ]))) | |||
| styleModel.titleColor ?? ""), | |||
| fontSize: 30.sp)) | |||
| ]))) | |||
| ], | |||
| ), | |||
| ), | |||
| Row( | |||
| children: <Widget>[ | |||
| good.coupon == "" | |||
| ? Container() | |||
| : Container( | |||
| margin: EdgeInsets.only( | |||
| top: 4, bottom: 4, right: 15.w), | |||
| decoration: BoxDecoration( | |||
| color: HexColor.fromHex(styleModel | |||
| .couponCommission.left.couponBgColor), | |||
| image: DecorationImage( | |||
| image: CachedNetworkImageProvider( | |||
| styleModel.couponCommission.left | |||
| .couponBgImg))), | |||
| child: Padding( | |||
| padding: const EdgeInsets.only( | |||
| left: 8, right: 8, top: 2, bottom: 2), | |||
| child: Text( | |||
| (good.coupon ?? "") + | |||
| (styleModel.couponCommission.left | |||
| .couonText ?? | |||
| ""), | |||
| style: TextStyle( | |||
| color: HexColor.fromHex(styleModel | |||
| .couponCommission | |||
| .left | |||
| .couponFontColor), | |||
| fontSize: 22.sp), | |||
| ), | |||
| ), | |||
| ), | |||
| good.commission == "" | |||
| ? Container() | |||
| : Container( | |||
| margin: EdgeInsets.only(top: 4, bottom: 4), | |||
| decoration: BoxDecoration( | |||
| color: HexColor.fromHex(styleModel | |||
| .couponCommission | |||
| .right | |||
| .commissionBgColor ?? | |||
| ""), | |||
| image: DecorationImage( | |||
| image: CachedNetworkImageProvider( | |||
| styleModel.couponCommission.right | |||
| .commissionBgImg ?? | |||
| ""))), | |||
| child: Padding( | |||
| padding: const EdgeInsets.only( | |||
| left: 8, right: 8, top: 2, bottom: 2), | |||
| child: Text( | |||
| (styleModel.couponCommission.right | |||
| .commissionText ?? | |||
| "") + | |||
| (good.commission ?? ""), | |||
| style: TextStyle( | |||
| color: HexColor.fromHex(styleModel | |||
| .couponCommission | |||
| .right | |||
| .commissionFontColor), | |||
| fontSize: 22.sp), | |||
| ), | |||
| ), | |||
| ), | |||
| ], | |||
| ), | |||
| ), | |||
| Row( | |||
| children: <Widget>[ | |||
| Container( | |||
| margin: EdgeInsets.only(top: 4, bottom: 4), | |||
| decoration: BoxDecoration(color: Colors.red), | |||
| child: Padding( | |||
| padding: const EdgeInsets.only( | |||
| left: 8, right: 8, top: 2, bottom: 2), | |||
| child: Text( | |||
| "50元券", | |||
| style: TextStyle( | |||
| color: Colors.white, fontSize: 22.sp), | |||
| Padding( | |||
| padding: const EdgeInsets.only(top: 4, bottom: 4), | |||
| child: Row( | |||
| crossAxisAlignment: CrossAxisAlignment.end, | |||
| children: <Widget>[ | |||
| Padding( | |||
| padding: EdgeInsets.only(bottom: 6.sp), | |||
| child: Text( | |||
| "¥", | |||
| style: TextStyle( | |||
| color: HexColor.fromHex( | |||
| styleModel.currentPriceColor ?? ""), | |||
| fontSize: 20.sp), | |||
| ), | |||
| ), | |||
| ), | |||
| ), | |||
| SizedBox( | |||
| width: 10.sp, | |||
| ), | |||
| Container( | |||
| margin: EdgeInsets.only(top: 4, bottom: 4), | |||
| decoration: BoxDecoration(color: Colors.red), | |||
| child: Padding( | |||
| padding: const EdgeInsets.only( | |||
| left: 8, right: 8, top: 2, bottom: 2), | |||
| child: Text( | |||
| "50元券", | |||
| Text( | |||
| good.currentPrice ?? "", | |||
| style: TextStyle( | |||
| color: Colors.white, fontSize: 22.sp), | |||
| color: HexColor.fromHex( | |||
| styleModel.currentPriceColor ?? ""), | |||
| fontSize: 40.sp), | |||
| ), | |||
| ), | |||
| ) | |||
| ], | |||
| ), | |||
| Padding( | |||
| padding: const EdgeInsets.only(top: 4, bottom: 4), | |||
| child: Row( | |||
| crossAxisAlignment: CrossAxisAlignment.end, | |||
| children: <Widget>[ | |||
| Padding( | |||
| padding: EdgeInsets.only(bottom: 6.sp), | |||
| child: Text( | |||
| "¥", | |||
| style: | |||
| TextStyle(color: Colors.red, fontSize: 20.sp), | |||
| SizedBox( | |||
| width: 6, | |||
| ), | |||
| ), | |||
| Text( | |||
| "1409", | |||
| style: | |||
| TextStyle(color: Colors.red, fontSize: 40.sp), | |||
| ), | |||
| SizedBox( | |||
| width: 6, | |||
| ), | |||
| Padding( | |||
| padding: EdgeInsets.only(bottom: 4.sp), | |||
| child: Text( | |||
| "¥1409", | |||
| style: TextStyle( | |||
| color: Colors.red, | |||
| fontSize: 22.sp, | |||
| decoration: TextDecoration.lineThrough), | |||
| Padding( | |||
| padding: EdgeInsets.only(bottom: 4.sp), | |||
| child: Text( | |||
| "¥" + good.marketPrice ?? "", | |||
| style: TextStyle( | |||
| color: HexColor.fromHex( | |||
| styleModel.marketPriceColor ?? ""), | |||
| fontSize: 22.sp, | |||
| decoration: TextDecoration.lineThrough), | |||
| ), | |||
| ), | |||
| ), | |||
| ], | |||
| ], | |||
| ), | |||
| ), | |||
| ), | |||
| Row( | |||
| children: <Widget>[ | |||
| Expanded( | |||
| child: Stack( | |||
| alignment: Alignment.centerLeft, | |||
| children: <Widget>[ | |||
| Row( | |||
| children: <Widget>[ | |||
| Expanded( | |||
| child: Container( | |||
| height: 40.w, | |||
| padding: EdgeInsets.only( | |||
| left: 64.w, | |||
| ), | |||
| margin: EdgeInsets.only(right: 20), | |||
| color: Colors.red, | |||
| child: Text( | |||
| "热销1231.1万件", | |||
| style: TextStyle( | |||
| color: Colors.white, fontSize: 22.sp), | |||
| ), | |||
| )) | |||
| ], | |||
| ), | |||
| Container( | |||
| color: Colors.amber, | |||
| width: 48.w, | |||
| height: 48.w, | |||
| child: CachedNetworkImage( | |||
| imageUrl: "", | |||
| Row( | |||
| children: <Widget>[ | |||
| Expanded( | |||
| child: Stack( | |||
| alignment: Alignment.centerLeft, | |||
| children: <Widget>[ | |||
| Row( | |||
| children: <Widget>[ | |||
| Expanded( | |||
| child: Container( | |||
| height: 40.w, | |||
| padding: EdgeInsets.only( | |||
| left: 64.w, | |||
| ), | |||
| margin: | |||
| EdgeInsets.only(right: 20, left: 20.w), | |||
| color: HexColor.fromHex( | |||
| styleModel.hotRank.bgColor ?? ""), | |||
| child: Text( | |||
| "热销" + good.inorderCount + "件", | |||
| style: TextStyle( | |||
| color: Colors.white, fontSize: 22.sp), | |||
| ), | |||
| )) | |||
| ], | |||
| ), | |||
| Container( | |||
| width: 48.w, | |||
| height: 48.w, | |||
| placeholder: (context, _) => | |||
| Container(color: Colors.yellow), | |||
| fit: BoxFit.fill, | |||
| ), | |||
| ), | |||
| Align( | |||
| alignment: Alignment.centerRight, | |||
| child: Container( | |||
| decoration: BoxDecoration( | |||
| color: Colors.amber, | |||
| borderRadius: BorderRadius.circular(20)), | |||
| margin: EdgeInsets.only(right: 0), | |||
| child: Padding( | |||
| padding: EdgeInsets.only( | |||
| left: 16, right: 16, top: 4, bottom: 4), | |||
| child: Text( | |||
| "马上抢", | |||
| style: TextStyle( | |||
| color: Colors.white, fontSize: 26.sp), | |||
| ), | |||
| child: CachedNetworkImage( | |||
| imageUrl: styleModel.hotRank.hotSaleImg ?? "", | |||
| width: 48.w, | |||
| height: 48.w, | |||
| placeholder: (context, _) => | |||
| Container(color: Colors.yellow), | |||
| fit: BoxFit.fill, | |||
| ), | |||
| ), | |||
| ) | |||
| ], | |||
| )) | |||
| ], | |||
| ) | |||
| ], | |||
| ), | |||
| )) | |||
| ], | |||
| ), | |||
| ), | |||
| Align( | |||
| alignment: Alignment.topLeft, | |||
| child: Container( | |||
| margin: EdgeInsets.only(left: 40.w, top: 8.h), | |||
| color: Colors.red, | |||
| height: 60.w, | |||
| width: 60.w, | |||
| Align( | |||
| alignment: Alignment.centerRight, | |||
| child: Container( | |||
| height: 48.h, | |||
| width: 127.w, | |||
| decoration: BoxDecoration( | |||
| image: DecorationImage( | |||
| image: CachedNetworkImageProvider( | |||
| styleModel.hotRank.buyNowImg ?? | |||
| ""), | |||
| fit: BoxFit.fitWidth), | |||
| borderRadius: | |||
| BorderRadius.circular(20)), | |||
| margin: EdgeInsets.only(right: 0), | |||
| )) | |||
| ], | |||
| )) | |||
| ], | |||
| ) | |||
| ], | |||
| ), | |||
| )) | |||
| ], | |||
| ), | |||
| ), | |||
| ) | |||
| ], | |||
| Align( | |||
| alignment: Alignment.topLeft, | |||
| child: Container( | |||
| decoration: BoxDecoration( | |||
| image: DecorationImage( | |||
| image: CachedNetworkImageProvider(indexImage ?? ""))), | |||
| margin: EdgeInsets.only(left: 40.w, top: 8.h), | |||
| height: 60.w, | |||
| width: 60.w, | |||
| ), | |||
| ) | |||
| ], | |||
| ), | |||
| ); | |||
| } | |||
| Providers getProvider(String provider) { | |||
| for (var item in styleModel.providers) { | |||
| if (item.type == provider) { | |||
| return item; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,87 @@ | |||
| import 'dart:async'; | |||
| import 'dart:convert'; | |||
| import 'package:zhiying_base_widget/widgets/hot_ranking/hot_ranking_list/model/hot_ranking_list_data_model.dart'; | |||
| import 'package:zhiying_comm/util/base_bloc.dart'; | |||
| import 'package:zhiying_comm/zhiying_comm.dart'; | |||
| class HotRankingListBloc extends BlocBase { | |||
| HotRankingListDataModel _pageData; | |||
| StreamController<HotRankingListDataModel> _dataController = | |||
| StreamController<HotRankingListDataModel>(); | |||
| Stream<HotRankingListDataModel> get outData => _dataController.stream; | |||
| String currentTypeId; | |||
| int currentPage = 1; | |||
| bool isLoading = false; | |||
| @override | |||
| void dispose() { | |||
| _dataController.close(); | |||
| _dataController = null; | |||
| } | |||
| void loadData(String typeId, int page,Function complete) { | |||
| if (isLoading) { | |||
| complete(); | |||
| return; | |||
| } | |||
| isLoading = true; | |||
| currentTypeId = typeId; | |||
| NetUtil.request( | |||
| '/api/v1/rec/taobao?type_id=' + typeId + '&page=' + page.toString(), | |||
| method: NetMethod.GET, onSuccess: (data) { | |||
| complete(); | |||
| isLoading = false; | |||
| _loadData(data); | |||
| }, onError: (e) { | |||
| complete(); | |||
| isLoading = false; | |||
| }); | |||
| } | |||
| void loadMoreData(String typeId,Function complete) { | |||
| if (isLoading) { | |||
| complete(); | |||
| return; | |||
| } | |||
| currentPage++; | |||
| isLoading = true; | |||
| NetUtil.request( | |||
| '/api/v1/rec/taobao?type_id=' + | |||
| typeId + | |||
| '&page=' + | |||
| currentPage.toString(), | |||
| method: NetMethod.GET, onSuccess: (data) { | |||
| complete(); | |||
| isLoading = false; | |||
| _loadMoreData(data); | |||
| }, onError: (e) { | |||
| complete(); | |||
| isLoading = false; | |||
| }); | |||
| } | |||
| void _loadData(dynamic data) { | |||
| if (_pageData != null && _pageData.good != null) { | |||
| _pageData.good.clear(); | |||
| _pageData.good.addAll(HotRankingListDataModel.fromJson(data).good); | |||
| } else { | |||
| _pageData = HotRankingListDataModel.fromJson(data); | |||
| } | |||
| _dataController.add(_pageData); | |||
| } | |||
| void _loadMoreData(dynamic data) { | |||
| if (_pageData != null && _pageData.good != null) { | |||
| _pageData.good.addAll(HotRankingListDataModel.fromJson(data).good); | |||
| _dataController.add(_pageData); | |||
| } | |||
| } | |||
| } | |||
| // http://192.168.0.113:5000/api/v1/rec/taobao?page=1 | |||
| // http://192.168.0.113:5000/api/v1/rec/taobao?page=1 | |||
| @@ -0,0 +1,145 @@ | |||
| import 'dart:convert'; | |||
| import 'package:flutter/material.dart'; | |||
| import 'package:pull_to_refresh/pull_to_refresh.dart'; | |||
| import 'package:zhiying_base_widget/pages/hot_ranking_page/hot_ranking_page_bloc.dart'; | |||
| import 'package:zhiying_base_widget/widgets/hot_ranking/hot_ranking_goods/hot_ranking_goods.dart'; | |||
| import 'package:zhiying_base_widget/widgets/hot_ranking/hot_ranking_list/model/hot_ranking_list_data_model.dart'; | |||
| import 'package:zhiying_base_widget/widgets/hot_ranking/hot_ranking_list/model/hot_ranking_list_model.dart'; | |||
| import 'package:zhiying_comm/util/base_bloc.dart'; | |||
| import 'hot_ranking_bloc.dart'; | |||
| import 'hot_ranking_list_sk.dart'; | |||
| class HotRankingList extends StatefulWidget { | |||
| final Map<String, dynamic> data; | |||
| const HotRankingList(this.data, {Key key}) : super(key: key); | |||
| @override | |||
| _HotRankingState createState() => _HotRankingState(); | |||
| } | |||
| class _HotRankingState extends State<HotRankingList> | |||
| with TickerProviderStateMixin { | |||
| HotRankingListBloc _bloc; | |||
| TabController _tabController; | |||
| RefreshController _refreshController; | |||
| List<Good> goods; | |||
| HotRankingPageBloc _pageBloc; | |||
| ScrollController _scrollcontroller; | |||
| @override | |||
| void initState() { | |||
| _bloc = HotRankingListBloc(); | |||
| _refreshController = RefreshController(); | |||
| _pageBloc = BlocProvider.of<HotRankingPageBloc>(context); | |||
| _scrollcontroller=ScrollController(); | |||
| if (_pageBloc != null) { | |||
| _pageBloc.event.listen((event) { | |||
| if (event.containsKey('type') && event['type'] == "loadData") { | |||
| _bloc.currentPage=1; | |||
| _bloc.loadData(event['type_id'], _bloc.currentPage, () {}); | |||
| } | |||
| }); | |||
| } | |||
| super.initState(); | |||
| } | |||
| _buildTabs() { | |||
| List<Widget> listWidget = List(); | |||
| for (int index = 0; index < 4; index++) { | |||
| listWidget.add(Tab( | |||
| text: "hahah", | |||
| )); | |||
| } | |||
| return listWidget; | |||
| } | |||
| @override | |||
| void dispose() { | |||
| _tabController.dispose(); | |||
| super.dispose(); | |||
| } | |||
| ///构建 | |||
| void createTabController() { | |||
| _tabController = TabController(length: 4, vsync: this); | |||
| } | |||
| ///构建TabView | |||
| _buildTabView() { | |||
| List<Widget> listWidget = List(); | |||
| for (var index = 0; index < 4; index++) { | |||
| listWidget.add(ListView.builder( | |||
| padding: EdgeInsets.all(0), | |||
| itemCount: 10, | |||
| itemBuilder: (context, index) { | |||
| return Container( | |||
| child: HotRankingGoods(), | |||
| ); | |||
| })); | |||
| } | |||
| return listWidget; | |||
| } | |||
| @override | |||
| Widget build(BuildContext context) { | |||
| return StreamBuilder<HotRankingListDataModel>( | |||
| stream: _bloc.outData, | |||
| builder: (context, snapshot) { | |||
| if (snapshot.data == null) { | |||
| return HotRankingSkeleton(); | |||
| } else { | |||
| goods = snapshot.data.good; | |||
| if(_bloc.currentPage==1){ | |||
| Future.delayed(Duration(milliseconds: 100),(){ | |||
| _scrollcontroller.animateTo(0, duration: Duration(milliseconds: 100), curve: Curves.ease); | |||
| }); | |||
| } | |||
| return SmartRefresher( | |||
| controller: _refreshController, | |||
| enablePullDown: true, | |||
| enablePullUp: true, | |||
| onLoading: _onLoading, | |||
| onRefresh: _onRefresh, | |||
| child: CustomScrollView( | |||
| controller: _scrollcontroller, | |||
| slivers: <Widget>[ | |||
| SliverList( | |||
| delegate: SliverChildBuilderDelegate(_buildListItem, | |||
| childCount: goods.length)) | |||
| ], | |||
| ), | |||
| ); | |||
| } | |||
| }); | |||
| } | |||
| Future _onLoading() async { | |||
| _bloc.loadMoreData(_bloc.currentTypeId, () { | |||
| _refreshController.loadComplete(); | |||
| }); | |||
| return null; | |||
| } | |||
| Future _onRefresh() async { | |||
| _bloc.currentPage = 1; | |||
| _bloc.loadData(_bloc.currentTypeId, _bloc.currentPage, () { | |||
| _refreshController.refreshCompleted(); | |||
| }); | |||
| } | |||
| Widget _buildListItem(BuildContext context, int index) { | |||
| return HotRankingGoods( | |||
| styleModel: | |||
| HotRankingListModel.fromJson(json.decode(widget.data['data'])), | |||
| good: goods[index], | |||
| index: index, | |||
| ); | |||
| } | |||
| } | |||
| @@ -8,6 +8,7 @@ class HotRankingSkeleton extends StatelessWidget { | |||
| baseColor: Colors.grey[300], | |||
| highlightColor: Colors.grey[100], | |||
| child: Column( | |||
| mainAxisSize: MainAxisSize.min, | |||
| children: <Widget>[ | |||
| Container( | |||
| width: double.infinity, | |||
| @@ -0,0 +1,82 @@ | |||
| class HotRankingListDataModel { | |||
| String provider; | |||
| List<Good> good; | |||
| HotRankingListDataModel({this.provider, this.good}); | |||
| HotRankingListDataModel.fromJson(Map<String, dynamic> json) { | |||
| provider = json['provider']; | |||
| if (json['good'] != null) { | |||
| good = new List<Good>(); | |||
| json['good'].forEach((v) { | |||
| good.add(new Good.fromJson(v)); | |||
| }); | |||
| } | |||
| } | |||
| Map<String, dynamic> toJson() { | |||
| final Map<String, dynamic> data = new Map<String, dynamic>(); | |||
| data['provider'] = this.provider; | |||
| if (this.good != null) { | |||
| data['good'] = this.good.map((v) => v.toJson()).toList(); | |||
| } | |||
| return data; | |||
| } | |||
| } | |||
| class Good { | |||
| String provider; | |||
| String providerName; | |||
| String goodId; | |||
| String goodImage; | |||
| String goodTitle; | |||
| String shopName; | |||
| String coupon; | |||
| String commission; | |||
| String marketPrice; | |||
| String currentPrice; | |||
| String inorderCount; | |||
| Good( | |||
| {this.provider, | |||
| this.providerName, | |||
| this.goodId, | |||
| this.goodImage, | |||
| this.goodTitle, | |||
| this.shopName, | |||
| this.coupon, | |||
| this.commission, | |||
| this.marketPrice, | |||
| this.currentPrice, | |||
| this.inorderCount}); | |||
| Good.fromJson(Map<String, dynamic> json) { | |||
| provider = json['provider']; | |||
| providerName = json['provider_name']; | |||
| goodId = json['good_id']; | |||
| goodImage = json['good_image']; | |||
| goodTitle = json['good_title']; | |||
| shopName = json['shop_name']; | |||
| coupon = json['coupon']; | |||
| commission = json['commission']; | |||
| marketPrice = json['market_price']; | |||
| currentPrice = json['current_price']; | |||
| inorderCount = json['inorder_count']; | |||
| } | |||
| Map<String, dynamic> toJson() { | |||
| final Map<String, dynamic> data = new Map<String, dynamic>(); | |||
| data['provider'] = this.provider; | |||
| data['provider_name'] = this.providerName; | |||
| data['good_id'] = this.goodId; | |||
| data['good_image'] = this.goodImage; | |||
| data['good_title'] = this.goodTitle; | |||
| data['shop_name'] = this.shopName; | |||
| data['coupon'] = this.coupon; | |||
| data['commission'] = this.commission; | |||
| data['market_price'] = this.marketPrice; | |||
| data['current_price'] = this.currentPrice; | |||
| data['inorder_count'] = this.inorderCount; | |||
| return data; | |||
| } | |||
| } | |||
| @@ -0,0 +1,211 @@ | |||
| class HotRankingListModel { | |||
| List<String> hotRankIconList; | |||
| String topMargin; | |||
| String leftRighMargin; | |||
| List<Providers> providers; | |||
| String titleColor; | |||
| String currentPriceColor; | |||
| String marketPriceColor; | |||
| String shopNameColor; | |||
| String saleCountColor; | |||
| String shopIcon; | |||
| CouponCommission couponCommission; | |||
| HotRank hotRank; | |||
| HotRankingListModel( | |||
| {this.hotRankIconList, | |||
| this.topMargin, | |||
| this.leftRighMargin, | |||
| this.providers, | |||
| this.titleColor, | |||
| this.currentPriceColor, | |||
| this.marketPriceColor, | |||
| this.shopNameColor, | |||
| this.saleCountColor, | |||
| this.shopIcon, | |||
| this.couponCommission, | |||
| this.hotRank}); | |||
| HotRankingListModel.fromJson(Map<String, dynamic> json) { | |||
| hotRankIconList = json['hot_rank_icon_list'].cast<String>(); | |||
| topMargin = json['top_margin']; | |||
| leftRighMargin = json['left_righ_margin']; | |||
| if (json['providers'] != null) { | |||
| providers = new List<Providers>(); | |||
| json['providers'].forEach((v) { | |||
| providers.add(new Providers.fromJson(v)); | |||
| }); | |||
| } | |||
| titleColor = json['title_color']; | |||
| currentPriceColor = json['current_price_color']; | |||
| marketPriceColor = json['market_price_color']; | |||
| shopNameColor = json['shop_name_color']; | |||
| saleCountColor = json['sale_count_color']; | |||
| shopIcon = json['shop_icon']; | |||
| couponCommission = json['coupon_commission'] != null | |||
| ? new CouponCommission.fromJson(json['coupon_commission']) | |||
| : null; | |||
| hotRank = json['hot_rank'] != null | |||
| ? new HotRank.fromJson(json['hot_rank']) | |||
| : null; | |||
| } | |||
| Map<String, dynamic> toJson() { | |||
| final Map<String, dynamic> data = new Map<String, dynamic>(); | |||
| data['hot_rank_icon_list'] = this.hotRankIconList; | |||
| data['top_margin'] = this.topMargin; | |||
| data['left_righ_margin'] = this.leftRighMargin; | |||
| if (this.providers != null) { | |||
| data['providers'] = this.providers.map((v) => v.toJson()).toList(); | |||
| } | |||
| data['title_color'] = this.titleColor; | |||
| data['current_price_color'] = this.currentPriceColor; | |||
| data['market_price_color'] = this.marketPriceColor; | |||
| data['shop_name_color'] = this.shopNameColor; | |||
| data['sale_count_color'] = this.saleCountColor; | |||
| data['shop_icon'] = this.shopIcon; | |||
| if (this.couponCommission != null) { | |||
| data['coupon_commission'] = this.couponCommission.toJson(); | |||
| } | |||
| if (this.hotRank != null) { | |||
| data['hot_rank'] = this.hotRank.toJson(); | |||
| } | |||
| return data; | |||
| } | |||
| } | |||
| class Providers { | |||
| String type; | |||
| String providerNameColor; | |||
| String providerBgColor; | |||
| Providers({this.type, this.providerNameColor, this.providerBgColor}); | |||
| Providers.fromJson(Map<String, dynamic> json) { | |||
| type = json['type']; | |||
| providerNameColor = json['provider_name_color']; | |||
| providerBgColor = json['provider_bg_color']; | |||
| } | |||
| Map<String, dynamic> toJson() { | |||
| final Map<String, dynamic> data = new Map<String, dynamic>(); | |||
| data['type'] = this.type; | |||
| data['provider_name_color'] = this.providerNameColor; | |||
| data['provider_bg_color'] = this.providerBgColor; | |||
| return data; | |||
| } | |||
| } | |||
| class CouponCommission { | |||
| Left left; | |||
| Right right; | |||
| CouponCommission({this.left, this.right}); | |||
| CouponCommission.fromJson(Map<String, dynamic> json) { | |||
| left = json['left'] != null ? new Left.fromJson(json['left']) : null; | |||
| right = json['right'] != null ? new Right.fromJson(json['right']) : null; | |||
| } | |||
| Map<String, dynamic> toJson() { | |||
| final Map<String, dynamic> data = new Map<String, dynamic>(); | |||
| if (this.left != null) { | |||
| data['left'] = this.left.toJson(); | |||
| } | |||
| if (this.right != null) { | |||
| data['right'] = this.right.toJson(); | |||
| } | |||
| return data; | |||
| } | |||
| } | |||
| class Left { | |||
| String couonText; | |||
| String couponFontColor; | |||
| String couponBgColor; | |||
| String couponBgImg; | |||
| Left( | |||
| {this.couonText, | |||
| this.couponFontColor, | |||
| this.couponBgColor, | |||
| this.couponBgImg}); | |||
| Left.fromJson(Map<String, dynamic> json) { | |||
| couonText = json['couon_text']; | |||
| couponFontColor = json['coupon_font_color']; | |||
| couponBgColor = json['coupon_bg_color']; | |||
| couponBgImg = json['coupon_bg_img']; | |||
| } | |||
| Map<String, dynamic> toJson() { | |||
| final Map<String, dynamic> data = new Map<String, dynamic>(); | |||
| data['couon_text'] = this.couonText; | |||
| data['coupon_font_color'] = this.couponFontColor; | |||
| data['coupon_bg_color'] = this.couponBgColor; | |||
| data['coupon_bg_img'] = this.couponBgImg; | |||
| return data; | |||
| } | |||
| } | |||
| class Right { | |||
| String commissionText; | |||
| String commissionFontColor; | |||
| String commissionBgColor; | |||
| String commissionBgImg; | |||
| Right( | |||
| {this.commissionText, | |||
| this.commissionFontColor, | |||
| this.commissionBgColor, | |||
| this.commissionBgImg}); | |||
| Right.fromJson(Map<String, dynamic> json) { | |||
| commissionText = json['commission_text']; | |||
| commissionFontColor = json['commission_font_color']; | |||
| commissionBgColor = json['commission_bg_color']; | |||
| commissionBgImg = json['commission_bg_img']; | |||
| } | |||
| Map<String, dynamic> toJson() { | |||
| final Map<String, dynamic> data = new Map<String, dynamic>(); | |||
| data['commission_text'] = this.commissionText; | |||
| data['commission_font_color'] = this.commissionFontColor; | |||
| data['commission_bg_color'] = this.commissionBgColor; | |||
| data['commission_bg_img'] = this.commissionBgImg; | |||
| return data; | |||
| } | |||
| } | |||
| class HotRank { | |||
| String isOpen; | |||
| String bgColor; | |||
| String fontColor; | |||
| String hotSaleImg; | |||
| String buyNowImg; | |||
| HotRank( | |||
| {this.isOpen, | |||
| this.bgColor, | |||
| this.fontColor, | |||
| this.hotSaleImg, | |||
| this.buyNowImg}); | |||
| HotRank.fromJson(Map<String, dynamic> json) { | |||
| isOpen = json['is_open']; | |||
| bgColor = json['bg_color']; | |||
| fontColor = json['font_color']; | |||
| hotSaleImg = json['hot_sale_img']; | |||
| buyNowImg = json['buy_now_img']; | |||
| } | |||
| Map<String, dynamic> toJson() { | |||
| final Map<String, dynamic> data = new Map<String, dynamic>(); | |||
| data['is_open'] = this.isOpen; | |||
| data['bg_color'] = this.bgColor; | |||
| data['font_color'] = this.fontColor; | |||
| data['hot_sale_img'] = this.hotSaleImg; | |||
| data['buy_now_img'] = this.buyNowImg; | |||
| return data; | |||
| } | |||
| } | |||
| @@ -0,0 +1,99 @@ | |||
| import 'dart:async'; | |||
| import 'dart:convert'; | |||
| import 'package:flutter/material.dart'; | |||
| import 'package:zhiying_base_widget/pages/hot_ranking_page/hot_ranking_page_bloc.dart'; | |||
| import 'package:zhiying_comm/util/base_bloc.dart'; | |||
| import 'package:zhiying_comm/util/extension/color.dart'; | |||
| import 'package:zhiying_comm/zhiying_comm.dart'; | |||
| import 'model/hot_tabbar_model.dart'; | |||
| class HotRankTableBar extends StatefulWidget { | |||
| final Map<String, dynamic> data; | |||
| const HotRankTableBar(this.data, {Key key}) : super(key: key); | |||
| @override | |||
| _HotRankTableBarState createState() => _HotRankTableBarState(); | |||
| } | |||
| class _HotRankTableBarState extends State<HotRankTableBar> | |||
| with TickerProviderStateMixin { | |||
| TabController _tabController; | |||
| HotRankingTabBarModel _barModel; | |||
| HotRankingPageBloc _pageBloc; | |||
| @override | |||
| void initState() { | |||
| _barModel = | |||
| HotRankingTabBarModel.fromJson(json.decode(widget.data['data'])); | |||
| _tabController = | |||
| TabController(length: _barModel.tabList.length, vsync: this); | |||
| _pageBloc = BlocProvider.of<HotRankingPageBloc>(context); | |||
| ///待页面初始化后发送加载事件 | |||
| Timer(Duration(milliseconds: 100), () { | |||
| if (_barModel != null && | |||
| _barModel.tabList != null && | |||
| _barModel.tabList.length > 0) { | |||
| var params = { | |||
| "type": "loadData", | |||
| "type_id": _barModel.tabList[0].typeId | |||
| }; | |||
| _pageBloc.sendEvent(params); | |||
| } | |||
| }); | |||
| super.initState(); | |||
| } | |||
| @override | |||
| Widget build(BuildContext context) { | |||
| return Container( | |||
| margin: EdgeInsets.only(bottom: 10), | |||
| child: TabBar( | |||
| indicatorPadding: EdgeInsets.only(bottom: 0), | |||
| indicatorSize: TabBarIndicatorSize.label, | |||
| controller: _tabController, | |||
| indicatorColor: HexColor.fromHex( | |||
| _barModel.tabList[_tabController.index].nameSelectColor), | |||
| unselectedLabelColor: HexColor.fromHex( | |||
| _barModel.tabList[_tabController.index].nameNoSelectColor), | |||
| labelColor: HexColor.fromHex( | |||
| _barModel.tabList[_tabController.index].nameSelectColor), | |||
| isScrollable: true, | |||
| tabs: _buildTabs(), | |||
| onTap: (index) { | |||
| var params = { | |||
| "type": "loadData", | |||
| "type_id": _barModel.tabList[_tabController.index].typeId | |||
| }; | |||
| _pageBloc.sendEvent(params); | |||
| }, | |||
| ), | |||
| ); | |||
| } | |||
| _buildTabs() { | |||
| List<Widget> listWidget = List(); | |||
| for (int index = 0; index < _barModel.tabList.length; index++) { | |||
| var item = _barModel.tabList[index]; | |||
| listWidget.add(Container( | |||
| child: Padding( | |||
| padding: const EdgeInsets.only( | |||
| bottom: 2, | |||
| top: 0, | |||
| ), | |||
| child: Text( | |||
| item.name, | |||
| style: TextStyle(fontSize: 26.sp), | |||
| ), | |||
| ), | |||
| )); | |||
| } | |||
| return listWidget; | |||
| } | |||
| } | |||
| @@ -0,0 +1,51 @@ | |||
| class HotRankingTabBarModel { | |||
| String indicatorColor; | |||
| List<TabList> tabList; | |||
| HotRankingTabBarModel({this.indicatorColor, this.tabList}); | |||
| HotRankingTabBarModel.fromJson(Map<String, dynamic> json) { | |||
| indicatorColor = json['indicator_color']; | |||
| if (json['tab_list'] != null) { | |||
| tabList = new List<TabList>(); | |||
| json['tab_list'].forEach((v) { | |||
| tabList.add(new TabList.fromJson(v)); | |||
| }); | |||
| } | |||
| } | |||
| Map<String, dynamic> toJson() { | |||
| final Map<String, dynamic> data = new Map<String, dynamic>(); | |||
| data['indicator_color'] = this.indicatorColor; | |||
| if (this.tabList != null) { | |||
| data['tab_list'] = this.tabList.map((v) => v.toJson()).toList(); | |||
| } | |||
| return data; | |||
| } | |||
| } | |||
| class TabList { | |||
| String name; | |||
| String nameSelectColor; | |||
| String nameNoSelectColor; | |||
| String typeId; | |||
| TabList( | |||
| {this.name, this.nameSelectColor, this.nameNoSelectColor, this.typeId}); | |||
| TabList.fromJson(Map<String, dynamic> json) { | |||
| name = json['name']; | |||
| nameSelectColor = json['name_select_color']; | |||
| nameNoSelectColor = json['name_no_select_color']; | |||
| typeId = json['type_id']; | |||
| } | |||
| Map<String, dynamic> toJson() { | |||
| final Map<String, dynamic> data = new Map<String, dynamic>(); | |||
| data['name'] = this.name; | |||
| data['name_select_color'] = this.nameSelectColor; | |||
| data['name_no_select_color'] = this.nameNoSelectColor; | |||
| data['type_id'] = this.typeId; | |||
| return data; | |||
| } | |||
| } | |||
| @@ -1,8 +1,8 @@ | |||
| import 'package:flutter/material.dart'; | |||
| import 'package:zhiying_base_widget/widgets/hot_ranking/hot_ranking_container.dart'; | |||
| import 'package:zhiying_base_widget/widgets/hot_ranking/hot_ranking_sk.dart'; | |||
| import 'package:flutter_screenutil/flutter_screenutil.dart'; | |||
| import 'hot_ranking_list/hot_ranking_list.dart'; | |||
| class HotTest extends StatefulWidget { | |||
| @override | |||
| _HotTestState createState() => _HotTestState(); | |||
| @@ -14,7 +14,7 @@ class _HotTestState extends State<HotTest> { | |||
| // 屏幕适配初始化 | |||
| ScreenUtil.init(context, width: 750, height: 1334); | |||
| return Scaffold( | |||
| body: HotRankingContainer(), | |||
| body: HotRankingList(null), | |||
| ); | |||
| } | |||
| } | |||
| @@ -15,6 +15,7 @@ class WalletAppbar extends StatelessWidget { | |||
| return Container( | |||
| height: MediaQuery.of(context).padding.top + 56, | |||
| child: AppBar( | |||
| elevation: 0, | |||
| leading: Navigator.canPop(context) | |||
| ? IconButton( | |||
| icon: Icon(Icons.arrow_back_ios), | |||
| @@ -22,11 +23,11 @@ class WalletAppbar extends StatelessWidget { | |||
| Navigator.of(context).pop(); | |||
| }) | |||
| : Container(), | |||
| backgroundColor: HexColor.fromHex(model.appBarBgColor), | |||
| backgroundColor: HexColor.fromHex(model.appBarBgColor??""), | |||
| centerTitle: true, | |||
| title: Text( | |||
| model.appBarName, | |||
| style: TextStyle(color: HexColor.fromHex(model.appBarNameColor)), | |||
| model.appBarName??"", | |||
| style: TextStyle(color: HexColor.fromHex(model.appBarNameColor??"")), | |||
| ), | |||
| ), | |||
| ); | |||
| @@ -0,0 +1,20 @@ | |||
| import 'package:flutter/material.dart'; | |||
| import 'package:zhiying_comm/zhiying_comm.dart'; | |||
| import 'package:shimmer/shimmer.dart'; | |||
| class WalletAppbarSkeleton extends StatelessWidget { | |||
| @override | |||
| Widget build(BuildContext context) { | |||
| return Container( | |||
| child: Shimmer.fromColors( | |||
| baseColor: Colors.grey[300], | |||
| highlightColor: Colors.grey[100], | |||
| child: Container( | |||
| child: AppBar( | |||
| backgroundColor: Colors.white, | |||
| ), | |||
| ), | |||
| ), | |||
| ); | |||
| } | |||
| } | |||
| @@ -3,6 +3,7 @@ class WalletHeaderModel { | |||
| String headerAvatar; | |||
| String headerCashOutText; | |||
| String headerCashOutTextColor; | |||
| String headerCashOutKey; | |||
| String headerCashOutBtnImg; | |||
| List<HeaderBottomList> headerBottomList; | |||
| @@ -11,6 +12,7 @@ class WalletHeaderModel { | |||
| this.headerAvatar, | |||
| this.headerCashOutText, | |||
| this.headerCashOutTextColor, | |||
| this.headerCashOutKey, | |||
| this.headerCashOutBtnImg, | |||
| this.headerBottomList}); | |||
| @@ -19,6 +21,7 @@ class WalletHeaderModel { | |||
| headerAvatar = json['header_avatar']; | |||
| headerCashOutText = json['header_cash_out_text']; | |||
| headerCashOutTextColor = json['header_cash_out_text_color']; | |||
| headerCashOutKey = json['header_cash_out_key']; | |||
| headerCashOutBtnImg = json['header_cash_out_btn_img']; | |||
| if (json['header_bottom_list'] != null) { | |||
| headerBottomList = new List<HeaderBottomList>(); | |||
| @@ -34,6 +37,7 @@ class WalletHeaderModel { | |||
| data['header_avatar'] = this.headerAvatar; | |||
| data['header_cash_out_text'] = this.headerCashOutText; | |||
| data['header_cash_out_text_color'] = this.headerCashOutTextColor; | |||
| data['header_cash_out_key'] = this.headerCashOutKey; | |||
| data['header_cash_out_btn_img'] = this.headerCashOutBtnImg; | |||
| if (this.headerBottomList != null) { | |||
| data['header_bottom_list'] = | |||
| @@ -44,50 +48,26 @@ class WalletHeaderModel { | |||
| } | |||
| class HeaderBottomList { | |||
| String totalText; | |||
| String totalTextColor; | |||
| String totalValueColor; | |||
| String cashOutText; | |||
| String cashOutTextColor; | |||
| String cashOutValueColor; | |||
| String unfinalText; | |||
| String unfinalTextColor; | |||
| String unfinalValueColor; | |||
| String text; | |||
| String textColor; | |||
| String valueColor; | |||
| String valueKey; | |||
| HeaderBottomList( | |||
| {this.totalText, | |||
| this.totalTextColor, | |||
| this.totalValueColor, | |||
| this.cashOutText, | |||
| this.cashOutTextColor, | |||
| this.cashOutValueColor, | |||
| this.unfinalText, | |||
| this.unfinalTextColor, | |||
| this.unfinalValueColor}); | |||
| HeaderBottomList({this.text, this.textColor, this.valueColor, this.valueKey}); | |||
| HeaderBottomList.fromJson(Map<String, dynamic> json) { | |||
| totalText = json['total_text']; | |||
| totalTextColor = json['total_text_color']; | |||
| totalValueColor = json['total_value_color']; | |||
| cashOutText = json['cash_out_text']; | |||
| cashOutTextColor = json['cash_out_text_color']; | |||
| cashOutValueColor = json['cash_out_value_color']; | |||
| unfinalText = json['unfinal_text']; | |||
| unfinalTextColor = json['unfinal_text_color']; | |||
| unfinalValueColor = json['unfinal_value_color']; | |||
| text = json['text']; | |||
| textColor = json['text_color']; | |||
| valueColor = json['value_color']; | |||
| valueKey = json['value_key']; | |||
| } | |||
| Map<String, dynamic> toJson() { | |||
| final Map<String, dynamic> data = new Map<String, dynamic>(); | |||
| data['total_text'] = this.totalText; | |||
| data['total_text_color'] = this.totalTextColor; | |||
| data['total_value_color'] = this.totalValueColor; | |||
| data['cash_out_text'] = this.cashOutText; | |||
| data['cash_out_text_color'] = this.cashOutTextColor; | |||
| data['cash_out_value_color'] = this.cashOutValueColor; | |||
| data['unfinal_text'] = this.unfinalText; | |||
| data['unfinal_text_color'] = this.unfinalTextColor; | |||
| data['unfinal_value_color'] = this.unfinalValueColor; | |||
| data['text'] = this.text; | |||
| data['text_color'] = this.textColor; | |||
| data['value_color'] = this.valueColor; | |||
| data['value_key'] = this.valueKey; | |||
| return data; | |||
| } | |||
| } | |||
| @@ -2,118 +2,159 @@ import 'dart:convert'; | |||
| import 'package:flutter/cupertino.dart'; | |||
| import 'package:flutter/material.dart'; | |||
| import 'package:zhiying_base_widget/widgets/wallet/wallet_data/model/wallet_header_model.dart'; | |||
| import 'package:zhiying_base_widget/widgets/wallet/wallet_data/wallet_data_bloc.dart'; | |||
| import 'package:zhiying_base_widget/widgets/wallet/wallet_data/wallet_data_sk.dart'; | |||
| import 'package:cached_network_image/cached_network_image.dart'; | |||
| import 'package:zhiying_comm/zhiying_comm.dart'; | |||
| class WalletData extends StatelessWidget { | |||
| class WalletData extends StatefulWidget { | |||
| final Map<String, dynamic> data; | |||
| const WalletData(this.data, {Key key}) : super(key: key); | |||
| @override | |||
| Widget build(BuildContext context) { | |||
| _WalletDataState createState() => _WalletDataState(); | |||
| } | |||
| class _WalletDataState extends State<WalletData> { | |||
| Map<String, dynamic> data; | |||
| WalletDataBloc _bloc; | |||
| Map<String, dynamic> dataModel; | |||
| @override | |||
| void initState() { | |||
| data = widget.data; | |||
| _bloc = WalletDataBloc(); | |||
| _bloc.loadHeaderData(); | |||
| super.initState(); | |||
| } | |||
| @override | |||
| Widget build(BuildContext context) { | |||
| print(data); | |||
| Map<String, dynamic> temp = json.decode(data['data']); | |||
| var model = WalletHeaderModel.fromJson(temp); | |||
| return Container( | |||
| width: double.infinity, | |||
| child: data == null | |||
| ? WalletDataSkeleton() | |||
| : Container( | |||
| margin: EdgeInsets.only(left: 12.5, right: 12.5,top: 10), | |||
| padding: EdgeInsets.only(left: 36.w, right: 26.w), | |||
| decoration: BoxDecoration( | |||
| image: DecorationImage( | |||
| image: CachedNetworkImageProvider(model.headerImg),fit: BoxFit.fill)), | |||
| height: 290.h, | |||
| child: Column( | |||
| mainAxisAlignment: MainAxisAlignment.spaceEvenly, | |||
| children: <Widget>[ | |||
| Row( | |||
| mainAxisAlignment: MainAxisAlignment.spaceBetween, | |||
| children: <Widget>[ | |||
| Row( | |||
| children: <Widget>[ | |||
| CachedNetworkImage( | |||
| imageUrl: model.headerAvatar, | |||
| height: 66.h, | |||
| width: 52.w, | |||
| ), | |||
| Padding( | |||
| padding: const EdgeInsets.all(8.0), | |||
| child: Column( | |||
| crossAxisAlignment: CrossAxisAlignment.start, | |||
| WalletHeaderModel model; | |||
| return StreamBuilder( | |||
| stream: _bloc.outData, | |||
| builder: (context, asn) { | |||
| dataModel = asn.data; | |||
| if (data.containsKey('data')) { | |||
| Map<String, dynamic> temp = json.decode(data['data']); | |||
| model = WalletHeaderModel.fromJson(temp); | |||
| } else { | |||
| return WalletDataSkeleton(); | |||
| } | |||
| return Container( | |||
| width: double.infinity, | |||
| child: dataModel == null | |||
| ? WalletDataSkeleton() | |||
| : Container( | |||
| margin: EdgeInsets.only(left: 12.5, right: 12.5, top: 10), | |||
| padding: EdgeInsets.only(left: 36.w, right: 26.w), | |||
| decoration: BoxDecoration( | |||
| image: DecorationImage( | |||
| image: CachedNetworkImageProvider( | |||
| model?.headerImg ?? ""), | |||
| fit: BoxFit.fill)), | |||
| height: 290.h, | |||
| child: Column( | |||
| mainAxisAlignment: MainAxisAlignment.spaceEvenly, | |||
| children: <Widget>[ | |||
| Row( | |||
| mainAxisAlignment: MainAxisAlignment.spaceBetween, | |||
| children: <Widget>[ | |||
| Row( | |||
| children: <Widget>[ | |||
| Text( | |||
| model.headerCashOutText, | |||
| style: TextStyle( | |||
| fontSize: 25.sp, | |||
| color: HexColor.fromHex( | |||
| model.headerCashOutTextColor)), | |||
| ), | |||
| Text( | |||
| "没数据", | |||
| style: TextStyle( | |||
| fontSize: 25.sp, | |||
| color: HexColor.fromHex( | |||
| model.headerCashOutTextColor)), | |||
| CachedNetworkImage( | |||
| imageUrl: model?.headerAvatar ?? "", | |||
| height: 66.h, | |||
| width: 52.h, | |||
| fit: BoxFit.fill, | |||
| ), | |||
| Padding( | |||
| padding: const EdgeInsets.all(8.0), | |||
| child: Column( | |||
| crossAxisAlignment: | |||
| CrossAxisAlignment.start, | |||
| children: <Widget>[ | |||
| Text( | |||
| model?.headerCashOutText ?? "", | |||
| style: TextStyle( | |||
| fontSize: 25.sp, | |||
| color: HexColor.fromHex( | |||
| model?.headerCashOutTextColor ?? | |||
| "")), | |||
| ), | |||
| Text( | |||
| dataModel.containsKey( | |||
| model.headerCashOutKey) | |||
| ? dataModel[model.headerCashOutKey] | |||
| : "", | |||
| style: TextStyle( | |||
| fontSize: 40.sp, | |||
| color: HexColor.fromHex( | |||
| model.headerCashOutTextColor)), | |||
| ), | |||
| ], | |||
| ), | |||
| ) | |||
| ], | |||
| ), | |||
| ) | |||
| ], | |||
| ), | |||
| GestureDetector( | |||
| child: Container( | |||
| decoration: BoxDecoration( | |||
| color: Colors.red, | |||
| borderRadius: BorderRadius.circular(10), | |||
| image: DecorationImage( | |||
| image: CachedNetworkImageProvider(""), | |||
| fit: BoxFit.fill)), | |||
| child: Padding( | |||
| padding: EdgeInsets.only( | |||
| left: 29.w, | |||
| right: 29.w, | |||
| top: 20.w, | |||
| bottom: 20.w), | |||
| child: Text( | |||
| "提现", | |||
| style: TextStyle(color: Colors.white), | |||
| ), | |||
| ), | |||
| GestureDetector( | |||
| child: Container( | |||
| decoration: BoxDecoration( | |||
| color: Colors.red, | |||
| borderRadius: BorderRadius.circular(10), | |||
| image: DecorationImage( | |||
| image: CachedNetworkImageProvider(""), | |||
| fit: BoxFit.fill)), | |||
| child: Padding( | |||
| padding: EdgeInsets.only( | |||
| left: 29.w, | |||
| right: 29.w, | |||
| top: 20.w, | |||
| bottom: 20.w), | |||
| child: Text( | |||
| "提现", | |||
| style: TextStyle(color: Colors.white), | |||
| ), | |||
| ), | |||
| ), | |||
| ) | |||
| ], | |||
| ), | |||
| Divider( | |||
| height: 1, | |||
| ), | |||
| ) | |||
| ], | |||
| ), | |||
| Divider( | |||
| height: 1, | |||
| ), | |||
| Row( | |||
| mainAxisAlignment: MainAxisAlignment.spaceAround, | |||
| children: _buildTopListItem(model?.headerBottomList)) | |||
| ], | |||
| ), | |||
| ), | |||
| Row( | |||
| mainAxisAlignment: MainAxisAlignment.spaceAround, | |||
| children: _buildTopListItem(model)) | |||
| ], | |||
| ), | |||
| )); | |||
| }, | |||
| ); | |||
| } | |||
| ///构建顶部Item | |||
| _buildTopListItem(List<HeaderBottomList> list) { | |||
| _buildTopListItem(WalletHeaderModel model) { | |||
| List<Widget> listWidget = List(); | |||
| for (var item in list) { | |||
| for (var item in model.headerBottomList) { | |||
| listWidget.add(Column( | |||
| mainAxisSize: MainAxisSize.min, | |||
| children: <Widget>[ | |||
| Text( | |||
| "9999", | |||
| style: TextStyle(color: Colors.red, fontSize: 30.sp), | |||
| dataModel.containsKey(item.valueKey) | |||
| ? dataModel[item.valueKey] | |||
| : "", | |||
| style: TextStyle( | |||
| color: HexColor.fromHex(item.valueColor), fontSize: 30.sp), | |||
| ), | |||
| Text( | |||
| "累计到账(元)", | |||
| style: TextStyle(color: Colors.grey, fontSize: 22.sp), | |||
| item.text, | |||
| style: TextStyle( | |||
| color: HexColor.fromHex(item.textColor), fontSize: 22.sp), | |||
| ), | |||
| ], | |||
| )); | |||
| @@ -0,0 +1,29 @@ | |||
| import 'dart:async'; | |||
| import 'dart:convert'; | |||
| import 'package:zhiying_comm/util/base_bloc.dart'; | |||
| import 'package:zhiying_comm/zhiying_comm.dart'; | |||
| class WalletDataBloc extends BlocBase { | |||
| StreamController<Map<String, dynamic>> _dataController = | |||
| StreamController<Map<String, dynamic>>(); | |||
| Stream<Map<String, dynamic>> get outData => _dataController.stream; | |||
| @override | |||
| void dispose() { | |||
| _dataController.close(); | |||
| _dataController = null; | |||
| } | |||
| /// | |||
| /// 加载头部数据 | |||
| /// | |||
| loadHeaderData() async { | |||
| await NetUtil.request("/api/v1/user/wallet/header",onSuccess: (data){ | |||
| _dataController.add(data); | |||
| }); | |||
| } | |||
| } | |||
| @@ -1,7 +1,8 @@ | |||
| import 'package:flutter/material.dart'; | |||
| import 'package:zhiying_base_widget/widgets/wallet/wallet_data/wallet_data.dart'; | |||
| import 'package:zhiying_comm/zhiying_comm.dart'; | |||
| import 'wallet_data.dart'; | |||
| class WalletDataCreater extends WidgetCreater { | |||
| @override | |||
| List<Widget> createWidgets(Map<String, dynamic> model) { | |||
| @@ -0,0 +1,45 @@ | |||
| class WalletDetailDataModel { | |||
| String type; | |||
| String finish; | |||
| String selfbuyEstimatedIncome; | |||
| String selfbuyPayOrder; | |||
| String directPromoteEstimatedIncome; | |||
| String directPromotePayOrder; | |||
| String indirectPromoteEstimatedIncome; | |||
| String indirectPromotePayOrder; | |||
| WalletDetailDataModel( | |||
| {this.type, | |||
| this.finish, | |||
| this.selfbuyEstimatedIncome, | |||
| this.selfbuyPayOrder, | |||
| this.directPromoteEstimatedIncome, | |||
| this.directPromotePayOrder, | |||
| this.indirectPromoteEstimatedIncome, | |||
| this.indirectPromotePayOrder}); | |||
| WalletDetailDataModel.fromJson(Map<String, dynamic> json) { | |||
| type = json['type']; | |||
| finish = json['finish']; | |||
| selfbuyEstimatedIncome = json['selfbuy_estimated_income']; | |||
| selfbuyPayOrder = json['selfbuy_pay_order']; | |||
| directPromoteEstimatedIncome = json['direct_promote_estimated_income']; | |||
| directPromotePayOrder = json['direct_promote_pay_order']; | |||
| indirectPromoteEstimatedIncome = json['indirect_promote_estimated_income']; | |||
| indirectPromotePayOrder = json['indirect_promote_pay_order']; | |||
| } | |||
| Map<String, dynamic> toJson() { | |||
| final Map<String, dynamic> data = new Map<String, dynamic>(); | |||
| data['type'] = this.type; | |||
| data['finish'] = this.finish; | |||
| data['selfbuy_estimated_income'] = this.selfbuyEstimatedIncome; | |||
| data['selfbuy_pay_order'] = this.selfbuyPayOrder; | |||
| data['direct_promote_estimated_income'] = this.directPromoteEstimatedIncome; | |||
| data['direct_promote_pay_order'] = this.directPromotePayOrder; | |||
| data['indirect_promote_estimated_income'] = | |||
| this.indirectPromoteEstimatedIncome; | |||
| data['indirect_promote_pay_order'] = this.indirectPromotePayOrder; | |||
| return data; | |||
| } | |||
| } | |||
| @@ -72,27 +72,46 @@ class Providers { | |||
| } | |||
| class DateList { | |||
| String isDefault; | |||
| String text; | |||
| String type; | |||
| String textSelectColor; | |||
| String textUnselectColor; | |||
| String btnImg; | |||
| String btnNoColorImg; | |||
| String btnColorImg; | |||
| DateList( | |||
| {this.text, this.textSelectColor, this.textUnselectColor, this.btnImg}); | |||
| {this.isDefault, | |||
| this.text, | |||
| this.type, | |||
| this.textSelectColor, | |||
| this.textUnselectColor, | |||
| this.btnImg, | |||
| this.btnNoColorImg, | |||
| this.btnColorImg}); | |||
| DateList.fromJson(Map<String, dynamic> json) { | |||
| isDefault = json['is_default']; | |||
| text = json['text']; | |||
| type = json['type']; | |||
| textSelectColor = json['text_select_color']; | |||
| textUnselectColor = json['text_unselect_color']; | |||
| btnImg = json['btn_img']; | |||
| btnNoColorImg = json['btn_no_color_img']; | |||
| btnColorImg = json['btn_color_img']; | |||
| } | |||
| Map<String, dynamic> toJson() { | |||
| final Map<String, dynamic> data = new Map<String, dynamic>(); | |||
| data['is_default'] = this.isDefault; | |||
| data['text'] = this.text; | |||
| data['type'] = this.type; | |||
| data['text_select_color'] = this.textSelectColor; | |||
| data['text_unselect_color'] = this.textUnselectColor; | |||
| data['btn_img'] = this.btnImg; | |||
| data['btn_no_color_img'] = this.btnNoColorImg; | |||
| data['btn_color_img'] = this.btnColorImg; | |||
| return data; | |||
| } | |||
| } | |||
| @@ -139,49 +158,62 @@ class ProviderDashbord { | |||
| } | |||
| class Finish { | |||
| String isShow; | |||
| String text; | |||
| String textColor; | |||
| String valueColor; | |||
| String vauleKey; | |||
| String bgImg; | |||
| String tipIcon; | |||
| String tipText; | |||
| Finish({this.text, this.textColor, this.valueColor, this.bgImg}); | |||
| Finish( | |||
| {this.isShow, | |||
| this.text, | |||
| this.textColor, | |||
| this.valueColor, | |||
| this.vauleKey, | |||
| this.bgImg, | |||
| this.tipIcon, | |||
| this.tipText}); | |||
| Finish.fromJson(Map<String, dynamic> json) { | |||
| isShow = json['is_show']; | |||
| text = json['text']; | |||
| textColor = json['text_color']; | |||
| valueColor = json['value_color']; | |||
| vauleKey = json['vaule_key']; | |||
| bgImg = json['bg_img']; | |||
| tipIcon = json['tip_icon']; | |||
| tipText = json['tip_text']; | |||
| } | |||
| Map<String, dynamic> toJson() { | |||
| final Map<String, dynamic> data = new Map<String, dynamic>(); | |||
| data['is_show'] = this.isShow; | |||
| data['text'] = this.text; | |||
| data['text_color'] = this.textColor; | |||
| data['value_color'] = this.valueColor; | |||
| data['vaule_key'] = this.vauleKey; | |||
| data['bg_img'] = this.bgImg; | |||
| data['tip_icon'] = this.tipIcon; | |||
| data['tip_text'] = this.tipText; | |||
| return data; | |||
| } | |||
| } | |||
| class SelfBuy { | |||
| String isShow; | |||
| String title; | |||
| String titleColor; | |||
| String leftBgImg; | |||
| String rightBgImg; | |||
| List<ItemList> itemList; | |||
| SelfBuy( | |||
| {this.title, | |||
| this.titleColor, | |||
| this.leftBgImg, | |||
| this.rightBgImg, | |||
| this.itemList}); | |||
| SelfBuy({this.isShow, this.title, this.titleColor, this.itemList}); | |||
| SelfBuy.fromJson(Map<String, dynamic> json) { | |||
| isShow = json['is_show']; | |||
| title = json['title']; | |||
| titleColor = json['title_color']; | |||
| leftBgImg = json['left_bg_img']; | |||
| rightBgImg = json['right_bg_img']; | |||
| if (json['list'] != null) { | |||
| itemList = new List<ItemList>(); | |||
| json['list'].forEach((v) { | |||
| @@ -192,10 +224,9 @@ class SelfBuy { | |||
| Map<String, dynamic> toJson() { | |||
| final Map<String, dynamic> data = new Map<String, dynamic>(); | |||
| data['is_show'] = this.isShow; | |||
| data['title'] = this.title; | |||
| data['title_color'] = this.titleColor; | |||
| data['left_bg_img'] = this.leftBgImg; | |||
| data['right_bg_img'] = this.rightBgImg; | |||
| if (this.itemList != null) { | |||
| data['list'] = this.itemList.map((v) => v.toJson()).toList(); | |||
| } | |||
| @@ -204,23 +235,42 @@ class SelfBuy { | |||
| } | |||
| class ItemList { | |||
| String bgImg; | |||
| String text; | |||
| String textColor; | |||
| String vauleKey; | |||
| String valueColor; | |||
| String tipIcon; | |||
| String tipText; | |||
| ItemList({this.text, this.textColor, this.valueColor}); | |||
| ItemList( | |||
| {this.bgImg, | |||
| this.text, | |||
| this.textColor, | |||
| this.vauleKey, | |||
| this.valueColor, | |||
| this.tipIcon, | |||
| this.tipText}); | |||
| ItemList.fromJson(Map<String, dynamic> json) { | |||
| bgImg = json['bg_img']; | |||
| text = json['text']; | |||
| textColor = json['text_color']; | |||
| vauleKey = json['vaule_key']; | |||
| valueColor = json['value_color']; | |||
| tipIcon = json['tip_icon']; | |||
| tipText = json['tip_text']; | |||
| } | |||
| Map<String, dynamic> toJson() { | |||
| final Map<String, dynamic> data = new Map<String, dynamic>(); | |||
| data['bg_img'] = this.bgImg; | |||
| data['text'] = this.text; | |||
| data['text_color'] = this.textColor; | |||
| data['vaule_key'] = this.vauleKey; | |||
| data['value_color'] = this.valueColor; | |||
| data['tip_icon'] = this.tipIcon; | |||
| data['tip_text'] = this.tipText; | |||
| return data; | |||
| } | |||
| } | |||
| @@ -2,9 +2,12 @@ import 'dart:convert'; | |||
| import 'package:flutter/cupertino.dart'; | |||
| import 'package:flutter/material.dart'; | |||
| import 'package:zhiying_base_widget/dialog/tip_dialog/tip_dialog.dart'; | |||
| import 'package:zhiying_base_widget/pages/withdraw_page/withdraw_page.dart'; | |||
| import 'package:zhiying_base_widget/widgets/home/home_quick_entry/cached_network_image_util.dart'; | |||
| import 'package:zhiying_base_widget/widgets/wallet/wallet_detail/model/wallet_detail_data_model.dart'; | |||
| import 'package:zhiying_base_widget/widgets/wallet/wallet_detail/model/wallet_detail_model.dart'; | |||
| import 'package:zhiying_base_widget/widgets/wallet/wallet_detail/wallet_detail_bloc.dart'; | |||
| import 'package:zhiying_base_widget/widgets/wallet/wallet_detail/wallet_detail_sk.dart'; | |||
| import 'package:flutter_screenutil/flutter_screenutil.dart'; | |||
| import 'package:cached_network_image/cached_network_image.dart'; | |||
| @@ -25,7 +28,11 @@ class WalletDetail extends StatefulWidget { | |||
| class _WalletDetailState extends State<WalletDetail> | |||
| with TickerProviderStateMixin { | |||
| WalletDetailModel _model; | |||
| TabController _tabController; | |||
| WalletDetailBloc _bloc; | |||
| @override | |||
| void initState() { | |||
| if (widget.data != null) { | |||
| @@ -33,92 +40,139 @@ class _WalletDetailState extends State<WalletDetail> | |||
| _tabController = | |||
| TabController(length: _model.providers.length, vsync: this); | |||
| } | |||
| _bloc = new WalletDetailBloc(); | |||
| _bloc.loadData(_model.providers[0].type); | |||
| super.initState(); | |||
| } | |||
| @override | |||
| Widget build(BuildContext context) { | |||
| return Container( | |||
| margin: EdgeInsets.only(left: 12.5, right: 12.5), | |||
| child: Column( | |||
| children: <Widget>[ | |||
| Container( | |||
| child: TabBar( | |||
| // isScrollable: true, | |||
| controller: _tabController, | |||
| tabs: _buildTabs()), | |||
| ), | |||
| Container( | |||
| height: 75.h, | |||
| child: ListView.builder( | |||
| padding: EdgeInsets.only(top: 16), | |||
| itemCount: _model.dateList.length, | |||
| scrollDirection: Axis.horizontal, | |||
| itemBuilder: _buildTimeItem), | |||
| ), | |||
| Container( | |||
| height: 126.h, | |||
| margin: EdgeInsets.only(top: 16), | |||
| width: double.infinity, | |||
| decoration: BoxDecoration( | |||
| image: DecorationImage( | |||
| image: CachedNetworkImageProvider( | |||
| _model.providerDashbord.finish.bgImg), | |||
| fit: BoxFit.fill)), | |||
| child: Column( | |||
| mainAxisAlignment: MainAxisAlignment.center, | |||
| children: <Widget>[ | |||
| Row( | |||
| return StreamBuilder( | |||
| stream: _bloc.outData, | |||
| builder: (context, asyn) { | |||
| if (_bloc.listDataModel.length == 0) { | |||
| ///骨架图 | |||
| return WalletDetailSkeleton(); | |||
| } | |||
| return Container( | |||
| decoration: BoxDecoration( | |||
| color: Colors.white, borderRadius: BorderRadius.circular(8)), | |||
| margin: | |||
| EdgeInsets.only(left: 12.5, right: 12.5, top: 15.h, bottom: 15.h), | |||
| padding: EdgeInsets.only(bottom: 15.h), | |||
| child: Column( | |||
| children: <Widget>[ | |||
| Container( | |||
| child: TabBar( | |||
| isScrollable: true, | |||
| unselectedLabelColor: | |||
| HexColor.fromHex(_model.providers[0].unselectColor), | |||
| labelColor: | |||
| HexColor.fromHex(_model.providers[0].selectColor), | |||
| controller: _tabController, | |||
| indicatorColor: | |||
| HexColor.fromHex(_model.providers[0].selectColor), | |||
| indicatorSize: TabBarIndicatorSize.label, | |||
| onTap: (index) { | |||
| ///变更平台 | |||
| changeProvider(_model.providers[index].type); | |||
| }, | |||
| tabs: _buildTabs()), | |||
| ), | |||
| ///日期选择 | |||
| Container( | |||
| height: 75.h, | |||
| child: ListView.builder( | |||
| padding: EdgeInsets.only(top: 16,left: 16.w), | |||
| itemCount: _model.dateList.length, | |||
| scrollDirection: Axis.horizontal, | |||
| itemBuilder: _buildTimeItem), | |||
| ), | |||
| Container( | |||
| height: 126.h, | |||
| margin: EdgeInsets.only(top: 16, left: 30.w, right: 30.w), | |||
| width: double.infinity, | |||
| decoration: BoxDecoration( | |||
| image: DecorationImage( | |||
| image: CachedNetworkImageProvider( | |||
| _model.providerDashbord.finish.bgImg), | |||
| fit: BoxFit.fill)), | |||
| child: Column( | |||
| mainAxisAlignment: MainAxisAlignment.center, | |||
| children: <Widget>[ | |||
| Text( | |||
| "已结算", | |||
| style: TextStyle(color: Colors.black, fontSize: 22.sp), | |||
| ), | |||
| InkWell( | |||
| child: Padding( | |||
| padding: const EdgeInsets.all(8.0), | |||
| child: CachedNetworkImage( | |||
| imageUrl: "", | |||
| width: 20.h, | |||
| height: 20.h, | |||
| fit: BoxFit.fill, | |||
| _model.providerDashbord.finish.isShow == "1" | |||
| ? Container() | |||
| : Padding( | |||
| padding: const EdgeInsets.all(8.0), | |||
| child: Text( | |||
| _model.providerDashbord.finish.text, | |||
| style: TextStyle( | |||
| fontSize: 28.sp, | |||
| color: HexColor.fromHex(_model | |||
| .providerDashbord.finish.textColor)), | |||
| ), | |||
| ), | |||
| Row( | |||
| mainAxisAlignment: MainAxisAlignment.center, | |||
| children: <Widget>[ | |||
| Text( | |||
| _model.providerDashbord.finish.text ?? "", | |||
| style: | |||
| TextStyle(color: Colors.black, fontSize: 22.sp), | |||
| ), | |||
| onTap: () { | |||
| ///问好 | |||
| }) | |||
| InkWell( | |||
| child: Padding( | |||
| padding: const EdgeInsets.all(8.0), | |||
| child: CachedNetworkImage( | |||
| imageUrl: | |||
| _model.providerDashbord.finish.tipIcon ?? | |||
| "", | |||
| width: 20.h, | |||
| height: 20.h, | |||
| fit: BoxFit.fill, | |||
| ), | |||
| ), | |||
| onTap: () { | |||
| ///显示弹窗 | |||
| showTipDialog( | |||
| null, _model.providerDashbord.finish.tipText); | |||
| }) | |||
| ], | |||
| ), | |||
| Text( | |||
| _bloc.selectDateData.finish ?? "", | |||
| style: TextStyle(color: Colors.red, fontSize: 40.sp), | |||
| ) | |||
| ], | |||
| ), | |||
| Text( | |||
| "158", | |||
| style: TextStyle(color: Colors.red, fontSize: 40.sp), | |||
| ) | |||
| ], | |||
| ), | |||
| ), | |||
| Container( | |||
| child: ListView.builder( | |||
| padding: EdgeInsets.all(0), | |||
| itemCount: 3, | |||
| shrinkWrap: true, | |||
| physics: NeverScrollableScrollPhysics(), | |||
| itemBuilder: (context, index) { | |||
| return _buildBottomItem( | |||
| context, index, _model.providerDashbord); | |||
| }), | |||
| ) | |||
| ], | |||
| ), | |||
| Container( | |||
| child: ListView.builder( | |||
| itemCount: 3, | |||
| shrinkWrap: true, | |||
| physics: NeverScrollableScrollPhysics(), | |||
| itemBuilder: (context, index) { | |||
| return _buildBottomItem( | |||
| context, index, _model.providerDashbord); | |||
| }), | |||
| ) | |||
| ], | |||
| ), | |||
| ); | |||
| }, | |||
| ); | |||
| } | |||
| ///平台选择 | |||
| _buildTabs() { | |||
| List<Widget> listWidget = List(); | |||
| for (var item in _model.providers) { | |||
| listWidget.add(Tab( | |||
| child: Text( | |||
| item.name, | |||
| style: TextStyle(color: Colors.grey), | |||
| style: TextStyle(fontSize: 28.sp), | |||
| ), | |||
| )); | |||
| } | |||
| @@ -127,53 +181,173 @@ class _WalletDetailState extends State<WalletDetail> | |||
| Widget _buildTimeItem(BuildContext context, int index) { | |||
| var item = _model.dateList[index]; | |||
| return Container( | |||
| margin: EdgeInsets.only(top: 0, left: 8, right: 8), | |||
| decoration: BoxDecoration( | |||
| color: Colors.grey[200], borderRadius: BorderRadius.circular(50)), | |||
| child: Padding( | |||
| padding: const EdgeInsets.only(left: 16, right: 16), | |||
| child: Center( | |||
| child: Text( | |||
| item.text, | |||
| style: TextStyle(color: Colors.grey), | |||
| )), | |||
| return InkWell( | |||
| child: Container( | |||
| margin: EdgeInsets.only(top: 0, left: 8, right: 8), | |||
| decoration: BoxDecoration( | |||
| image: DecorationImage( | |||
| image: CachedNetworkImageProvider( | |||
| item.type == _bloc.selectDateData.type | |||
| ? item.btnImg ?? "" | |||
| : item.btnNoColorImg ?? ""), | |||
| fit: BoxFit.fitWidth), | |||
| ), | |||
| child: Padding( | |||
| padding: const EdgeInsets.only(left: 16, right: 16), | |||
| child: Center( | |||
| child: Text( | |||
| item.text, | |||
| style: TextStyle( | |||
| fontSize: 22.sp, | |||
| color: HexColor.fromHex(item.type == _bloc.selectDateData.type | |||
| ? item.textSelectColor | |||
| : item.textUnselectColor)), | |||
| )), | |||
| ), | |||
| ), | |||
| onTap: () { | |||
| for (var select in _bloc.listDataModel) { | |||
| if (select.type == item.type) { | |||
| _bloc.selectDay = item.type; | |||
| _bloc.refresh(); | |||
| return; | |||
| } | |||
| } | |||
| }, | |||
| ); | |||
| } | |||
| ///底部显示 | |||
| Widget _buildBottomItem( | |||
| BuildContext context, int index, ProviderDashbord dashbord) { | |||
| var item = dashbord.selfBuy; | |||
| SelfBuy item; | |||
| if (index == 0) { | |||
| item = dashbord.selfBuy; | |||
| } else if (index == 1) { | |||
| item = dashbord.directPromote; | |||
| } else { | |||
| item = dashbord.indirectPromote; | |||
| } | |||
| var dataMap = _bloc.selectDateData.toJson(); | |||
| return Container( | |||
| child: Column( | |||
| children: <Widget>[ | |||
| Text( | |||
| item.title, | |||
| style: TextStyle(color: HexColor.fromHex(item.titleColor)), | |||
| SizedBox( | |||
| height: 15.h, | |||
| ), | |||
| item.isShow == "0" | |||
| ? Container() | |||
| : Text( | |||
| item.title, | |||
| style: TextStyle( | |||
| color: HexColor.fromHex(item.titleColor), | |||
| fontSize: 28.sp), | |||
| ), | |||
| SizedBox( | |||
| height: 15.h, | |||
| ), | |||
| Row( | |||
| mainAxisAlignment: MainAxisAlignment.spaceBetween, | |||
| children: <Widget>[ | |||
| Expanded( | |||
| child: Container( | |||
| height: 123.h, | |||
| margin: EdgeInsets.only(right: 8), | |||
| decoration: BoxDecoration( | |||
| image: DecorationImage( | |||
| image: CachedNetworkImageProvider(item?.leftBgImg ?? ''), | |||
| fit: BoxFit.fill)), | |||
| child: Center(child: Text("ddd")), | |||
| ), | |||
| height: 123.h, | |||
| margin: EdgeInsets.only(right: 8, left: 30.w), | |||
| padding: EdgeInsets.only(left: 20.w), | |||
| decoration: BoxDecoration( | |||
| image: DecorationImage( | |||
| image: CachedNetworkImageProvider( | |||
| item.itemList[0].bgImg ?? ""), | |||
| fit: BoxFit.fill)), | |||
| child: Column( | |||
| mainAxisAlignment: MainAxisAlignment.center, | |||
| crossAxisAlignment: CrossAxisAlignment.start, | |||
| children: <Widget>[ | |||
| Row( | |||
| children: <Widget>[ | |||
| Text( | |||
| item.itemList[0].text ?? "", | |||
| style: TextStyle( | |||
| fontSize: 22.sp, | |||
| color: HexColor.fromHex( | |||
| item.itemList[0].textColor)), | |||
| ), | |||
| InkWell( | |||
| child: Padding( | |||
| padding: const EdgeInsets.all(8.0), | |||
| child: CachedNetworkImage( | |||
| imageUrl: item.itemList[0].tipIcon, | |||
| width: 20.h, | |||
| height: 20.h, | |||
| fit: BoxFit.fill, | |||
| ), | |||
| ), | |||
| onTap: () { | |||
| //弹窗 | |||
| showTipDialog(null, item.itemList[0].tipText); | |||
| }, | |||
| ) | |||
| ], | |||
| ), | |||
| Text(dataMap[item.itemList[0].vauleKey], | |||
| style: TextStyle( | |||
| fontSize: 34.sp, | |||
| color: | |||
| HexColor.fromHex(item.itemList[1].valueColor), | |||
| )) | |||
| ], | |||
| )), | |||
| ), | |||
| Expanded( | |||
| child: Container( | |||
| height: 123.h, | |||
| margin: EdgeInsets.only(left: 8), | |||
| height: 123.h, | |||
| margin: EdgeInsets.only(left: 8, right: 30.w), | |||
| padding: EdgeInsets.only(left: 20.w), | |||
| decoration: BoxDecoration( | |||
| image: DecorationImage( | |||
| image: CachedNetworkImageProvider(item?.rightBgImg ?? ''))), | |||
| child: Center(child: Text("dddd")), | |||
| image: CachedNetworkImageProvider( | |||
| item.itemList[1].bgImg ?? ""), | |||
| fit: BoxFit.fill)), | |||
| child: Column( | |||
| mainAxisAlignment: MainAxisAlignment.center, | |||
| crossAxisAlignment: CrossAxisAlignment.start, | |||
| children: <Widget>[ | |||
| Row( | |||
| children: <Widget>[ | |||
| Text( | |||
| item.itemList[1].text ?? "", | |||
| style: TextStyle( | |||
| fontSize: 22.sp, | |||
| color: | |||
| HexColor.fromHex(item.itemList[1].textColor)), | |||
| ), | |||
| InkWell( | |||
| child: Padding( | |||
| padding: const EdgeInsets.all(8.0), | |||
| child: CachedNetworkImage( | |||
| imageUrl: item.itemList[1].tipIcon, | |||
| width: 20.h, | |||
| height: 20.h, | |||
| fit: BoxFit.fill, | |||
| ), | |||
| ), | |||
| onTap: () { | |||
| //弹窗 | |||
| showTipDialog(null, item.itemList[1].tipText); | |||
| }, | |||
| ) | |||
| ], | |||
| ), | |||
| Text( | |||
| dataMap[item.itemList[1].vauleKey], | |||
| style: TextStyle( | |||
| fontSize: 34.sp, | |||
| color: HexColor.fromHex(item.itemList[1].valueColor)), | |||
| ) | |||
| ], | |||
| ), | |||
| )) | |||
| ], | |||
| ) | |||
| @@ -181,4 +355,14 @@ class _WalletDetailState extends State<WalletDetail> | |||
| ), | |||
| ); | |||
| } | |||
| ///变更平台 | |||
| void changeProvider(String type) { | |||
| _bloc.loadData(type); | |||
| } | |||
| ///显示提示框 | |||
| void showTipDialog(String title, String content) { | |||
| showDialog(context: context, child: TipDialog(content: content)); | |||
| } | |||
| } | |||
| @@ -0,0 +1,52 @@ | |||
| import 'dart:async'; | |||
| import 'dart:convert'; | |||
| import 'package:zhiying_comm/util/base_bloc.dart'; | |||
| import 'package:zhiying_comm/zhiying_comm.dart'; | |||
| import 'model/wallet_detail_data_model.dart'; | |||
| class WalletDetailBloc extends BlocBase { | |||
| StreamController<WalletDetailDataModel> _dataController = | |||
| StreamController<WalletDetailDataModel>(); | |||
| Stream<WalletDetailDataModel> get outData => _dataController.stream; | |||
| ///选中的某一时间的数据 | |||
| WalletDetailDataModel selectDateData; | |||
| String selectDay = "today"; | |||
| List<WalletDetailDataModel> listDataModel = new List(); | |||
| @override | |||
| void dispose() { | |||
| _dataController.close(); | |||
| _dataController = null; | |||
| } | |||
| /// | |||
| /// 加载头部数据 | |||
| /// | |||
| loadData(String type) async { | |||
| await NetUtil.request("/api/v1/user/wallet/" + type, onSuccess: (data) { | |||
| listDataModel.clear(); | |||
| listDataModel.addAll(List.from(data).map((v) { | |||
| return WalletDetailDataModel.fromJson(v); | |||
| }).toList()); | |||
| refresh(); | |||
| }); | |||
| } | |||
| ///刷新页面 | |||
| refresh() { | |||
| for (var item in listDataModel) { | |||
| if (selectDay == item.type) { | |||
| selectDateData = item; | |||
| _dataController.add(selectDateData); | |||
| return; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; | |||
| import 'package:shimmer/shimmer.dart'; | |||
| class WalletDetailSkeleton extends StatelessWidget { | |||
| @override | |||
| Widget build(BuildContext context) { | |||
| return Container( | |||
| @@ -12,23 +13,93 @@ class WalletDetailSkeleton extends StatelessWidget { | |||
| child: Shimmer.fromColors( | |||
| baseColor: Colors.grey[300], | |||
| highlightColor: Colors.grey[100], | |||
| child: Row( | |||
| child: Column( | |||
| children: <Widget>[ | |||
| Container( | |||
| width: 18, | |||
| height: 18, | |||
| decoration: BoxDecoration( | |||
| borderRadius: BorderRadius.circular(9), | |||
| color: Colors.white), | |||
| width: double.infinity, | |||
| child: _createTab(), | |||
| ), | |||
| Container( | |||
| margin: EdgeInsets.only(left: 8), | |||
| width: 120, | |||
| height: 14, | |||
| color: Colors.white, | |||
| margin: EdgeInsets.only(top: 6), | |||
| width: double.infinity, | |||
| child: _createTags(), | |||
| ), | |||
| Container( | |||
| margin: EdgeInsets.only(top: 6), | |||
| height: 64, | |||
| decoration: BoxDecoration( | |||
| borderRadius: BorderRadius.circular(7.5), | |||
| color: Colors.white), | |||
| ), | |||
| _createDataRow(), | |||
| _createDataRow(), | |||
| _createDataRow(), | |||
| ], | |||
| )), | |||
| ); | |||
| } | |||
| Widget _createTab() { | |||
| return Row( | |||
| children: List.generate(5, (index) { | |||
| return Expanded( | |||
| child: Container( | |||
| height: 14, | |||
| margin: EdgeInsets.only(left: 10, right: 10, top: 4, bottom: 4), | |||
| color: Colors.white, | |||
| ), | |||
| ); | |||
| }), | |||
| ); | |||
| } | |||
| Widget _createTags() { | |||
| return Row( | |||
| children: List.generate(5, (index) { | |||
| return Expanded( | |||
| child: Container( | |||
| height: 20, | |||
| margin: EdgeInsets.only(left: 10, right: 10, top: 4, bottom: 4), | |||
| decoration: BoxDecoration( | |||
| color: Colors.white, borderRadius: BorderRadius.circular(10)), | |||
| ), | |||
| ); | |||
| }), | |||
| ); | |||
| } | |||
| Widget _createDataRow() { | |||
| return Column( | |||
| children: <Widget>[ | |||
| Container( | |||
| margin: EdgeInsets.only(top: 8, bottom: 2), | |||
| width: 64, | |||
| height: 18, | |||
| color: Colors.white, | |||
| ), | |||
| Row( | |||
| children: <Widget>[ | |||
| Expanded( | |||
| child: Container( | |||
| margin: EdgeInsets.only(top: 6, right: 5), | |||
| height: 64, | |||
| decoration: BoxDecoration( | |||
| borderRadius: BorderRadius.circular(7.5), | |||
| color: Colors.white), | |||
| ), | |||
| ), | |||
| Expanded( | |||
| child: Container( | |||
| margin: EdgeInsets.only(top: 6, left: 5), | |||
| height: 64, | |||
| decoration: BoxDecoration( | |||
| borderRadius: BorderRadius.circular(7.5), | |||
| color: Colors.white), | |||
| ), | |||
| ) | |||
| ], | |||
| ) | |||
| ], | |||
| ); | |||
| } | |||
| } | |||
| @@ -12,93 +12,23 @@ class WalletIncomeSkeleton extends StatelessWidget { | |||
| child: Shimmer.fromColors( | |||
| baseColor: Colors.grey[300], | |||
| highlightColor: Colors.grey[100], | |||
| child: Column( | |||
| child: Row( | |||
| children: <Widget>[ | |||
| Container( | |||
| width: double.infinity, | |||
| child: _createTab(), | |||
| ), | |||
| Container( | |||
| margin: EdgeInsets.only(top: 6), | |||
| width: double.infinity, | |||
| child: _createTags(), | |||
| ), | |||
| Container( | |||
| margin: EdgeInsets.only(top: 6), | |||
| height: 64, | |||
| width: 18, | |||
| height: 18, | |||
| decoration: BoxDecoration( | |||
| borderRadius: BorderRadius.circular(7.5), | |||
| borderRadius: BorderRadius.circular(9), | |||
| color: Colors.white), | |||
| ), | |||
| _createDataRow(), | |||
| _createDataRow(), | |||
| _createDataRow(), | |||
| Container( | |||
| margin: EdgeInsets.only(left: 8), | |||
| width: 120, | |||
| height: 14, | |||
| color: Colors.white, | |||
| ), | |||
| ], | |||
| )), | |||
| ); | |||
| } | |||
| Widget _createTab() { | |||
| return Row( | |||
| children: List.generate(5, (index) { | |||
| return Expanded( | |||
| child: Container( | |||
| height: 14, | |||
| margin: EdgeInsets.only(left: 10, right: 10, top: 4, bottom: 4), | |||
| color: Colors.white, | |||
| ), | |||
| ); | |||
| }), | |||
| ); | |||
| } | |||
| Widget _createTags() { | |||
| return Row( | |||
| children: List.generate(5, (index) { | |||
| return Expanded( | |||
| child: Container( | |||
| height: 20, | |||
| margin: EdgeInsets.only(left: 10, right: 10, top: 4, bottom: 4), | |||
| decoration: BoxDecoration( | |||
| color: Colors.white, borderRadius: BorderRadius.circular(10)), | |||
| ), | |||
| ); | |||
| }), | |||
| ); | |||
| } | |||
| Widget _createDataRow() { | |||
| return Column( | |||
| children: <Widget>[ | |||
| Container( | |||
| margin: EdgeInsets.only(top: 8, bottom: 2), | |||
| width: 64, | |||
| height: 18, | |||
| color: Colors.white, | |||
| ), | |||
| Row( | |||
| children: <Widget>[ | |||
| Expanded( | |||
| child: Container( | |||
| margin: EdgeInsets.only(top: 6, right: 5), | |||
| height: 64, | |||
| decoration: BoxDecoration( | |||
| borderRadius: BorderRadius.circular(7.5), | |||
| color: Colors.white), | |||
| ), | |||
| ), | |||
| Expanded( | |||
| child: Container( | |||
| margin: EdgeInsets.only(top: 6, left: 5), | |||
| height: 64, | |||
| decoration: BoxDecoration( | |||
| borderRadius: BorderRadius.circular(7.5), | |||
| color: Colors.white), | |||
| ), | |||
| ) | |||
| ], | |||
| ) | |||
| ], | |||
| ); | |||
| } | |||
| } | |||