zsw
10 months ago
871 changed files with 58337 additions and 99698 deletions
@ -0,0 +1,28 @@
|
||||
# This file configures the analyzer, which statically analyzes Dart code to |
||||
# check for errors, warnings, and lints. |
||||
# |
||||
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled |
||||
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be |
||||
# invoked from the command line by running `flutter analyze`. |
||||
|
||||
# The following line activates a set of recommended lints for Flutter apps, |
||||
# packages, and plugins designed to encourage good coding practices. |
||||
include: package:flutter_lints/flutter.yaml |
||||
|
||||
linter: |
||||
# The lint rules applied to this project can be customized in the |
||||
# section below to disable rules from the `package:flutter_lints/flutter.yaml` |
||||
# included above or to enable additional rules. A list of all available lints |
||||
# and their documentation is published at https://dart.dev/lints. |
||||
# |
||||
# Instead of disabling a lint rule for the entire project in the |
||||
# section below, it can also be suppressed for a single line of code |
||||
# or a specific dart file by using the `// ignore: name_of_lint` and |
||||
# `// ignore_for_file: name_of_lint` syntax on the line or in the file |
||||
# producing the lint. |
||||
rules: |
||||
# avoid_print: false # Uncomment to disable the `avoid_print` rule |
||||
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule |
||||
|
||||
# Additional information about this file can be found at |
||||
# https://dart.dev/guides/language/analysis-options |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,7 +0,0 @@
|
||||
<hbuilder version="1.9.9.80110" debug="false" syncDebug="false"> |
||||
<apps> |
||||
<app appid="__UNI__ACD00DA" appver="1.0"/> |
||||
<app appid="__UNI__E60E056" appver="1.0"/> |
||||
</apps> |
||||
</hbuilder> |
||||
|
@ -1,92 +0,0 @@
|
||||
<!DOCTYPE html> |
||||
<html> |
||||
<head> |
||||
<meta charset="utf-8"/> |
||||
<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/> |
||||
<meta name="HandheldFriendly" content="true"/> |
||||
<meta name="MobileOptimized" content="320"/> |
||||
<title>Error</title> |
||||
<script type="text/javascript"> |
||||
// H5 plus事件处理 |
||||
var ws=null; |
||||
function plusReady(){ |
||||
// Android处理返回键 |
||||
plus.key.addEventListener('backbutton',function(){ |
||||
(history.length==1)&&ws.close(); |
||||
var c=setTimeout(function(){ |
||||
ws.close(); |
||||
},1000); |
||||
window.onbeforeunload=function(){ |
||||
clearTimeout(c); |
||||
} |
||||
history.go(-2); |
||||
},false); |
||||
ws=plus.webview.currentWebview(); |
||||
} |
||||
if(window.plus){ |
||||
plusReady(); |
||||
}else{ |
||||
document.addEventListener('plusready',plusReady,false); |
||||
} |
||||
document.addEventListener('touchstart',function(){ |
||||
return false; |
||||
},true); |
||||
// 禁止选择 |
||||
document.oncontextmenu=function(){ |
||||
return false; |
||||
}; |
||||
// 获取错误信息 |
||||
document.addEventListener("error",function(e){ |
||||
info.innerText="请求的页面("+e.url+")无法打开"; |
||||
console.log("请求的页面无法打开:"+e.href); |
||||
},false); |
||||
</script> |
||||
<style> |
||||
*{ |
||||
-webkit-user-select: none; |
||||
} |
||||
html,body{ |
||||
margin: 0px; |
||||
padding: 0px; |
||||
width: 100%; |
||||
height: 100%; |
||||
text-align: center; |
||||
word-break: break-all; |
||||
-webkit-touch-callout:none; |
||||
-webkit-tap-highlight-color:rgba(0,0,0,0); |
||||
} |
||||
.button{ |
||||
width: 50%; |
||||
font-size: 18px; |
||||
font-weight: normal; |
||||
text-decoration: none; |
||||
text-align: center; |
||||
padding: .5em 0em; |
||||
margin: .5em auto; |
||||
color: #333333; |
||||
background-color: #EEEEEE; |
||||
border: 1px solid #CCCCCC; |
||||
-webkit-border-radius: 5px; |
||||
border-radius: 5px; |
||||
} |
||||
.button:active{ |
||||
background-color: #CCCCCC; |
||||
} |
||||
</style> |
||||
</head> |
||||
<body> |
||||
<div style="width:100%;height:20%;"></div> |
||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 512 512" style="height:20%;width:30%"> |
||||
<g id="icomoon-ignore"> |
||||
<line stroke-width="1" x1="" y1="" x2="" y2="" stroke="#449FDB" opacity=""></line> |
||||
</g> |
||||
<path d="M256 0c-141.385 0-256 114.615-256 256s114.615 256 256 256 256-114.615 256-256-114.615-256-256-256zM352 128c17.673 0 32 14.327 32 32s-14.327 32-32 32-32-14.327-32-32 14.327-32 32-32zM160 128c17.673 0 32 14.327 32 32s-14.327 32-32 32-32-14.327-32-32 14.327-32 32-32zM352.049 390.37c-19.587-32.574-55.272-54.37-96.049-54.37s-76.462 21.796-96.049 54.37l-41.164-24.698c27.98-46.535 78.958-77.672 137.213-77.672s109.232 31.137 137.213 77.672l-41.164 24.698z" fill="#666666"></path> |
||||
</svg> |
||||
<p style="font-size:18px;font-weight:bolder;">We're sorry ...</p> |
||||
<p id="info" style="font-size:12px;"></p> |
||||
<!--<div class="button" onclick="history.back()">Retry</div>--> |
||||
<div class="button" onclick="if(history.length == 1){ws.close();}else{ws.back();ws.back();}">Back</div> |
||||
<div class="button" onclick="ws.close()">Close</div> |
||||
<div class="button" onclick="plus.runtime.restart()">Restart</div> |
||||
</body> |
||||
</html> |
@ -1,73 +0,0 @@
|
||||
<properties> |
||||
<features> |
||||
<feature name="Barcode" value="io.dcloud.feature.barcode2.BarcodeFeatureImpl"/> |
||||
<feature name="Speech" value="io.dcloud.feature.speech.SpeechFeatureImpl"> |
||||
<module name="iFly" value="io.dcloud.feature.speech.IflySpeechEngine"/> |
||||
<module name="baidu" value="io.dcloud.feature.speech.BaiduSpeechEngine"/> |
||||
</feature> |
||||
<feature name="Maps" value="io.dcloud.js.map.amap.JsMapPluginImpl"/> |
||||
<!--<feature name="Maps" value="io.dcloud.js.map.JsMapPluginImpl"/>--> |
||||
<feature name="Contacts" value="io.dcloud.feature.contacts.ContactsFeatureImpl"/> |
||||
<feature name="Messaging" value="io.dcloud.adapter.messaging.MessagingPluginImpl"/> |
||||
<feature name="Camera" value="io.dcloud.js.camera.CameraFeatureImpl"/> |
||||
<feature name="Console" value="io.dcloud.feature.pdr.LoggerFeatureImpl"/> |
||||
<feature name="Device" value="io.dcloud.feature.device.DeviceFeatureImpl"/> |
||||
<feature name="File" value="io.dcloud.js.file.FileFeatureImpl"/> |
||||
<feature name="Proximity" value="io.dcloud.feature.sensor.ProximityFeatureImpl"/> |
||||
<feature name="Storage" value="io.dcloud.feature.pdr.NStorageFeatureImpl"/> |
||||
<feature name="Cache" value="io.dcloud.feature.pdr.CoreCacheFeatureImpl"/> |
||||
<feature name="Invocation" value="io.dcloud.invocation.Invocation"/> |
||||
<feature name="Navigator" value="io.dcloud.feature.ui.navigator.NavigatorUIFeatureImpl"/> |
||||
<feature name="NativeUI" value="io.dcloud.feature.ui.nativeui.NativeUIFeatureImpl"/> |
||||
<feature name="UI" value="io.dcloud.feature.ui.UIFeatureImpl"> |
||||
<module name="Navigator" value="io.dcloud.feature.ui.NavView"/> |
||||
</feature> |
||||
<feature name="Gallery" value="io.dcloud.js.gallery.GalleryFeatureImpl"/> |
||||
<feature name="Downloader" value="io.dcloud.net.DownloaderFeatureImpl"/> |
||||
<feature name="Uploader" value="io.dcloud.net.UploadFeature"/> |
||||
<feature name="Push" value="io.dcloud.feature.aps.APSFeatureImpl"> |
||||
<module name="igexin" value="io.dcloud.feature.apsGt.GTPushService"/> |
||||
<!-- mkeypush --> |
||||
</feature> |
||||
<feature name="Zip" value="io.dcloud.feature.pdr.ZipFeature"/> |
||||
<feature name="Audio" value="io.dcloud.feature.audio.AudioFeatureImpl"/> |
||||
<feature name="Runtime" value="io.dcloud.feature.pdr.RuntimeFeatureImpl"/> |
||||
<feature name="VideoPlayer" value="io.dcloud.media.MediaFeatureImpl"/> |
||||
<feature name="LivePusher" value="io.dcloud.media.live.LiveMediaFeatureImpl"/> |
||||
<feature name="XMLHttpRequest" value="io.dcloud.net.XMLHttpRequestFeature"/> |
||||
<feature name="Statistic" value="io.dcloud.feature.statistics.StatisticsFeatureImpl"/> |
||||
<feature name="Accelerometer" value="io.dcloud.feature.sensor.AccelerometerFeatureImpl"/> |
||||
<feature name="Orientation" value="io.dcloud.feature.sensor.OrientationFeatureImpl"/> |
||||
<feature name="NativeObj" value="io.dcloud.feature.nativeObj.FeatureImpl"/> |
||||
<feature name="Geolocation" value="io.dcloud.js.geolocation.GeolocationFeatureImpl"/> |
||||
<feature name="Payment" value="io.dcloud.feature.payment.PaymentFeatureImpl"> |
||||
<module name="AliPay" value="io.dcloud.feature.payment.alipay.AliPay"/> |
||||
<module name="Payment-Weixin" value="io.dcloud.feature.payment.weixin.WeiXinPay"/> |
||||
<module name="Payment-Qihoo" value="io.dcloud.feature.payment.qihoopay.QihooPay"/> |
||||
</feature> |
||||
<feature name="Share" value="io.dcloud.share.ShareFeatureImpl"> |
||||
<module name="Sina" value="io.dcloud.share.sina.SinaWeiboApiManager"/> |
||||
<module name="Tencent" value="io.dcloud.share.tencent.TencentWeiboApiManager"/> |
||||
<module name="Weixin" value="io.dcloud.share.mm.WeiXinApiManager"/> |
||||
<module name="QQ" value="io.dcloud.share.qq.QQApiManager"/> |
||||
</feature> |
||||
<feature name="OAuth" value="io.dcloud.feature.oauth.OAuthFeatureImpl"> |
||||
<module name="OAuth-Weixin" value="io.dcloud.feature.oauth.weixin.WeiXinOAuthService"/> |
||||
<module name="OAuth-QQ" value="io.dcloud.feature.oauth.qq.QQOAuthService"/> |
||||
<module name="OAuth-Sina" value="io.dcloud.feature.oauth.sina.SinaOAuthService"/> |
||||
<module name="OAuth-Qihoo" value="io.dcloud.oauth.qihoo.QihooOAuthService"/> |
||||
<module name="OAuth-MiUi" value="io.dcloud.feature.oauth.miui.MiUiOAuthService"/> |
||||
</feature> |
||||
<feature name="Stream" value="io.dcloud.appstream.js.StreamAppFeatureImpl"/> |
||||
<feature name="Fingerprint" value="io.dcloud.feature.fingerprint.FingerPrintsImpl"/> |
||||
<feature name="iBeacon" value="io.dcloud.feature.iBeacon.WxBluetoothFeatureImpl"/> |
||||
<feature name="Bluetooth" value="io.dcloud.feature.bluetooth.BluetoothFeature"/> |
||||
</features> |
||||
|
||||
<services> |
||||
<service name="push" value="io.dcloud.feature.aps.APSFeatureImpl"/> |
||||
<service name="Statistic" value="io.dcloud.feature.statistics.StatisticsBootImpl"/> |
||||
<service name="Downloader" value="io.dcloud.net.DownloaderBootImpl"/> |
||||
<service name="Maps" value="io.dcloud.js.map.MapInitImpl"/> |
||||
</services> |
||||
</properties> |
File diff suppressed because one or more lines are too long
@ -1,55 +0,0 @@
|
||||
package com.zsw.huixiang |
||||
|
||||
import android.content.Context |
||||
import android.content.Intent |
||||
import android.net.Uri |
||||
import android.text.TextUtils |
||||
import android.util.Log |
||||
import io.flutter.embedding.engine.plugins.FlutterPlugin |
||||
import io.flutter.plugin.common.MethodCall |
||||
import io.flutter.plugin.common.MethodChannel |
||||
|
||||
class BridgePlugin : FlutterPlugin, MethodChannel.MethodCallHandler { |
||||
|
||||
var intentAction : Uri? = null |
||||
|
||||
private lateinit var channel : MethodChannel |
||||
private lateinit var context : Context; |
||||
|
||||
override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) { |
||||
context = binding.applicationContext; |
||||
channel = MethodChannel(binding.binaryMessenger, "bridge") |
||||
channel.setMethodCallHandler(this) |
||||
} |
||||
|
||||
override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) { |
||||
channel.setMethodCallHandler(null) |
||||
} |
||||
|
||||
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) { |
||||
if (call.method == "action") { |
||||
if (intentAction != null) { |
||||
val custom = intentAction?.getQueryParameter("custom") |
||||
Log.e("bridge", "bridge:$custom") |
||||
if (!TextUtils.isEmpty(custom)) { |
||||
result.success(custom) |
||||
intentAction = null |
||||
return |
||||
} |
||||
} |
||||
result.success("") |
||||
} else if (call.method == "toAppStore") { |
||||
try { |
||||
val intent = Intent(Intent.ACTION_VIEW); |
||||
intent.data = Uri.parse("market://search?q="+ context.packageName); |
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); |
||||
context.startActivity(intent); |
||||
result.success("") |
||||
} catch (e : Exception) { |
||||
result.success("0") |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
@ -1,16 +0,0 @@
|
||||
package com.zsw.huixiang |
||||
|
||||
import android.app.Application |
||||
import com.baidu.mapapi.base.BmfMapApplication |
||||
|
||||
class HxApplication : BmfMapApplication() { |
||||
|
||||
|
||||
override fun onCreate() { |
||||
super.onCreate() |
||||
|
||||
|
||||
} |
||||
|
||||
|
||||
} |
@ -1,42 +1,5 @@
|
||||
package com.zsw.huixiang |
||||
|
||||
import android.content.Intent |
||||
import android.os.Bundle |
||||
import android.util.Log |
||||
import io.dcloud.feature.sdk.DCUniMPSDK |
||||
import io.flutter.embedding.android.FlutterActivity |
||||
|
||||
|
||||
class MainActivity: FlutterActivity() { |
||||
|
||||
|
||||
lateinit var bridgePlugin : BridgePlugin |
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) { |
||||
super.onCreate(savedInstanceState) |
||||
|
||||
Log.e("intentUrl:", "url: ${intent.data}" ) |
||||
|
||||
flutterEngine?.plugins?.add(MinPlugin()) |
||||
|
||||
bridgePlugin = BridgePlugin() |
||||
if (intent.data != null) { |
||||
bridgePlugin.intentAction = intent.data |
||||
} |
||||
flutterEngine?.plugins?.add(bridgePlugin) |
||||
} |
||||
|
||||
override fun onNewIntent(intent: Intent) { |
||||
super.onNewIntent(intent) |
||||
Log.e("intentUrl:", "onNewIntent: ${intent.data}" ) |
||||
if (bridgePlugin != null && intent.data != null) { |
||||
bridgePlugin.intentAction = intent.data |
||||
} |
||||
} |
||||
|
||||
override fun onDestroy() { |
||||
super.onDestroy() |
||||
DCUniMPSDK.getInstance().closeCurrentApp() |
||||
} |
||||
|
||||
} |
||||
class MainActivity: FlutterActivity() |
||||
|
@ -1,129 +0,0 @@
|
||||
|
||||
|
||||
|
||||
package com.zsw.huixiang |
||||
|
||||
import android.content.Context |
||||
import androidx.annotation.NonNull |
||||
import io.dcloud.common.adapter.util.Logger |
||||
import io.dcloud.feature.sdk.DCSDKInitConfig |
||||
import io.dcloud.feature.sdk.DCUniMPSDK |
||||
import io.dcloud.feature.sdk.MenuActionSheetItem |
||||
import io.flutter.embedding.engine.plugins.FlutterPlugin |
||||
import io.flutter.plugin.common.MethodCall |
||||
import io.flutter.plugin.common.MethodChannel |
||||
import io.flutter.plugin.common.MethodChannel.MethodCallHandler |
||||
import io.flutter.plugin.common.MethodChannel.Result |
||||
import org.json.JSONObject |
||||
|
||||
|
||||
/** MinPlugin */ |
||||
class MinPlugin: FlutterPlugin, MethodCallHandler { |
||||
/// The MethodChannel that will the communication between Flutter and native Android |
||||
/// |
||||
/// This local reference serves to register the plugin with the Flutter Engine and unregister it |
||||
/// when the Flutter Engine is detached from the Activity |
||||
private lateinit var channel : MethodChannel |
||||
private lateinit var context : Context |
||||
|
||||
override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) { |
||||
context = flutterPluginBinding.applicationContext; |
||||
channel = MethodChannel(flutterPluginBinding.binaryMessenger, "min") |
||||
channel.setMethodCallHandler(this) |
||||
} |
||||
|
||||
override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) { |
||||
if (call.method == "initialize") { |
||||
if (!DCUniMPSDK.getInstance().isInitialize) { |
||||
val item = MenuActionSheetItem("退出", "tc"); |
||||
val sheetItems: MutableList<MenuActionSheetItem> = ArrayList() |
||||
sheetItems.add(item) |
||||
val config = DCSDKInitConfig.Builder() |
||||
.setCapsule(true) |
||||
.setMenuDefFontSize("16px") |
||||
.setMenuDefFontColor("#000000") |
||||
.setMenuDefFontWeight("normal") |
||||
.setMenuActionSheetItems(sheetItems) |
||||
.setEnableBackground(false) //后台运行 |
||||
.build() |
||||
DCUniMPSDK.getInstance().initialize(context, config) { |
||||
result.success(it) |
||||
} |
||||
DCUniMPSDK.getInstance().setDefMenuButtonClickCallBack { p0, p1 -> |
||||
Logger.e("p0: $p0 p1:$p1"); |
||||
when (p1) { |
||||
"tc" -> { |
||||
Logger.e("用户点击了退出"); |
||||
DCUniMPSDK.getInstance().closeCurrentApp() |
||||
} |
||||
} |
||||
} |
||||
DCUniMPSDK.getInstance().setUniMPOnCloseCallBack { |
||||
Logger.e("用户点击了退出 it: $it") |
||||
DCUniMPSDK.getInstance().closeCurrentApp() |
||||
} |
||||
} |
||||
} else if (call.method == "isInitialize") { |
||||
result.success(DCUniMPSDK.getInstance().isInitialize) |
||||
} else if (call.method == "isExistsApp") { |
||||
var appid = call.argument<String>("appid"); |
||||
result.success(DCUniMPSDK.getInstance().isExistsApp(appid)) |
||||
} else if (call.method == "getAppVersionInfo") { |
||||
var appid = call.argument<String>("appid"); |
||||
result.success(DCUniMPSDK.getInstance().getAppVersionInfo(appid)["name"]) |
||||
} else if (call.method == "closeCurrentApp") { |
||||
result.success(DCUniMPSDK.getInstance().closeCurrentApp()) |
||||
} else if (call.method == "getAppBasePath") { |
||||
result.success(DCUniMPSDK.getInstance().getAppBasePath(context)) |
||||
} else if (call.method == "runingAppid") { |
||||
result.success(DCUniMPSDK.getInstance().runingAppid) |
||||
} else if (call.method == "currentPageUrl") { |
||||
result.success(DCUniMPSDK.getInstance().currentPageUrl) |
||||
} else if (call.method == "startMin") { |
||||
try { |
||||
var appid = call.argument<String>("appid") |
||||
var hashMap = call.argument<HashMap<String, Object>>("json") |
||||
Logger.e("startMin_json: ${JSONObject(hashMap as Map<*, *>)}") |
||||
DCUniMPSDK.getInstance().startApp(context, appid, JSONObject(hashMap as Map<*, *>)) |
||||
} catch (e: Exception) { |
||||
e.printStackTrace() |
||||
} |
||||
result.success("") |
||||
} else if (call.method == "clickListener") { |
||||
DCUniMPSDK.getInstance().setDefMenuButtonClickCallBack { p0, p1 -> |
||||
Logger.e("p0: $p0 p1:$p1"); |
||||
when (p1) { |
||||
"tc" -> { |
||||
Logger.e("用户点击了退出"); |
||||
DCUniMPSDK.getInstance().closeCurrentApp() |
||||
} |
||||
} |
||||
} |
||||
DCUniMPSDK.getInstance().setUniMPOnCloseCallBack { |
||||
Logger.e("用户点击了退出 it: $it") |
||||
} |
||||
} else if (call.method == "reloadWgt") { |
||||
try { |
||||
var appid = call.argument<String>("appid"); |
||||
var wgtPath = call.argument<String>("wgtPath"); |
||||
DCUniMPSDK.getInstance().releaseWgtToRunPathFromePath(appid, wgtPath) { code, pArgs -> |
||||
if (code == 1) { //释放wgt完成 |
||||
result.success(true) |
||||
} else { |
||||
result.success(false) |
||||
} |
||||
null |
||||
} |
||||
} catch (e: Exception) { |
||||
e.printStackTrace() |
||||
} |
||||
} else { |
||||
result.notImplemented() |
||||
} |
||||
} |
||||
|
||||
override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) { |
||||
channel.setMethodCallHandler(null) |
||||
} |
||||
} |
||||
|
@ -1,67 +0,0 @@
|
||||
package com.zsw.huixiang.wxapi |
||||
|
||||
import android.content.Intent |
||||
import android.os.Bundle |
||||
import cn.sharesdk.wechat.utils.WechatHandlerActivity |
||||
import io.dcloud.feature.payment.weixin.AbsWXPayCallbackActivity |
||||
import io.flutter.Log |
||||
|
||||
class WXEntryActivity : WechatHandlerActivity() { |
||||
|
||||
|
||||
// IWXAPI 是第三方app和微信通信的openapi接口 |
||||
|
||||
public override fun onCreate(savedInstanceState: Bundle?) { |
||||
super.onCreate(savedInstanceState) |
||||
Log.e("wx:", "onCreate:") |
||||
|
||||
// try { |
||||
// if (!WXAPiHandler.wxApiRegistered) { |
||||
// var appInfo = packageManager.getApplicationInfo(packageName, PackageManager.GET_META_DATA) |
||||
// val wechatAppId = appInfo.metaData.getString("weChatAppId") |
||||
// if (wechatAppId != null ){ |
||||
// WXAPiHandler.setupWxApi(wechatAppId,this) |
||||
// WXAPiHandler.setCoolBool(true) |
||||
// Log.d("fluwx","weChatAppId:" + wechatAppId) |
||||
// }else { |
||||
// Log.e("fluwx","can't load meta-data weChatAppId") |
||||
// } |
||||
// } |
||||
// WXAPiHandler.wxApi?.handleIntent(intent, this) |
||||
// } catch (e: Exception) { |
||||
// e.printStackTrace() |
||||
// startSpecifiedActivity(defaultFlutterActivityAction()) |
||||
// finish() |
||||
// } |
||||
} |
||||
|
||||
// override fun onNewIntent(intent: Intent) { |
||||
// super.onNewIntent(intent) |
||||
// Log.e("wx:", "onNewIntent:") |
||||
|
||||
// setIntent(intent) |
||||
|
||||
// try { |
||||
// WXAPiHandler.wxApi?.handleIntent(intent, this) |
||||
// } catch (e: Exception) { |
||||
// e.printStackTrace() |
||||
// startSpecifiedActivity(defaultFlutterActivityAction()) |
||||
// finish() |
||||
// } |
||||
// } |
||||
|
||||
|
||||
// override fun onReq(baseReq: BaseReq) { |
||||
// Log.e("wx:", "onReq: ${baseReq.toString()}") |
||||
// FIXME: 可能是官方的Bug,从微信拉起APP的Intent类型不对,无法跳转回Flutter Activity |
||||
// 稳定复现场景:微信版本为7.0.5,小程序SDK为2.7.7 |
||||
// FluwxRequestHandler.onReq(baseReq,this) |
||||
// } |
||||
// 第三方应用发送到微信的请求处理后的响应结果,会回调到该方法 |
||||
// override fun onResp(resp: BaseResp) { |
||||
// Log.e("wx:", "onResp: ${resp.toString()}") |
||||
// FluwxResponseHandler.handleResponse(resp) |
||||
// finish() |
||||
// } |
||||
|
||||
} |
@ -1,86 +0,0 @@
|
||||
package com.zsw.huixiang.wxapi |
||||
|
||||
import android.content.Intent |
||||
import android.content.pm.PackageManager |
||||
import android.os.Bundle |
||||
import android.util.Log |
||||
import com.jarvan.fluwx.handlers.FluwxRequestHandler |
||||
import com.jarvan.fluwx.handlers.FluwxResponseHandler |
||||
import com.jarvan.fluwx.handlers.WXAPiHandler |
||||
import com.tencent.mm.opensdk.modelbase.BaseReq |
||||
import com.tencent.mm.opensdk.modelbase.BaseResp |
||||
import io.dcloud.feature.payment.weixin.AbsWXPayCallbackActivity |
||||
|
||||
|
||||
class WXPayEntryActivity : AbsWXPayCallbackActivity() { |
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) { |
||||
super.onCreate(savedInstanceState) |
||||
try { |
||||
if (!WXAPiHandler.wxApiRegistered) { |
||||
var appInfo = packageManager.getApplicationInfo(packageName, PackageManager.GET_META_DATA) |
||||
val wechatAppId = appInfo.metaData.getString("weChatAppId") |
||||
if (wechatAppId != null ){ |
||||
WXAPiHandler.setupWxApi(wechatAppId, this) |
||||
// WXAPiHandler.setCoolBool(true) |
||||
io.flutter.Log.d("fluwx", "weChatAppId:$wechatAppId") |
||||
}else { |
||||
io.flutter.Log.e("fluwx", "can't load meta-data weChatAppId") |
||||
} |
||||
} |
||||
WXAPiHandler.wxApi?.handleIntent(intent, this) |
||||
} catch (e: Exception) { |
||||
e.printStackTrace() |
||||
startSpecifiedActivity(defaultFlutterActivityAction()) |
||||
finish() |
||||
} |
||||
Log.e("WXPayEntryActivity", "onCreate") |
||||
} |
||||
|
||||
override fun onNewIntent(intent: Intent) { |
||||
super.onNewIntent(intent) |
||||
|
||||
setIntent(intent) |
||||
|
||||
try { |
||||
WXAPiHandler.wxApi?.handleIntent(intent, this) |
||||
} catch (e: Exception) { |
||||
e.printStackTrace() |
||||
startSpecifiedActivity(defaultFlutterActivityAction()) |
||||
finish() |
||||
} |
||||
} |
||||
|
||||
override fun onReq(req: BaseReq) { |
||||
super.onReq(req) |
||||
FluwxRequestHandler.onReq(req, this) |
||||
Log.e("WXPayEntryActivity", "req: $req") |
||||
|
||||
} |
||||
|
||||
override fun onResp(resp: BaseResp) { |
||||
FluwxResponseHandler.handleResponse(resp) |
||||
super.onResp(resp) |
||||
Log.e("WXPayEntryActivity", "resp: $resp") |
||||
} |
||||
|
||||
|
||||
|
||||
private fun startSpecifiedActivity(action: String, bundle: Bundle? = null, bundleKey: String? = null) { |
||||
Intent(action).run { |
||||
bundleKey?.let { |
||||
putExtra(bundleKey, bundle) |
||||
} |
||||
addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) |
||||
packageManager?.let { |
||||
resolveActivity(packageManager)?.also { |
||||
startActivity(this) |
||||
finish() |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
private fun defaultFlutterActivityAction(): String = "$packageName.FlutterActivity" |
||||
|
||||
} |
@ -1,7 +0,0 @@
|
||||
# frozen_string_literal: true |
||||
|
||||
source "https://rubygems.org" |
||||
|
||||
git_source(:github) {|repo_name| "https://github.com/#{repo_name}" } |
||||
|
||||
# gem "rails" |
File diff suppressed because it is too large
Load Diff
@ -1,6 +0,0 @@
|
||||
#import <Flutter/Flutter.h> |
||||
#import <UIKit/UIKit.h> |
||||
|
||||
@interface AppDelegate : FlutterAppDelegate |
||||
|
||||
@end |
@ -1,36 +0,0 @@
|
||||
#import "AppDelegate.h" |
||||
#import "GeneratedPluginRegistrant.h" |
||||
|
||||
|
||||
@implementation AppDelegate |
||||
|
||||
- (BOOL)application:(UIApplication *)application |
||||
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { |
||||
[GeneratedPluginRegistrant registerWithRegistry:self]; |
||||
// Override point for customization after application launch. |
||||
|
||||
FlutterViewController* controller = (FlutterViewController*)self.window.rootViewController; |
||||
__block NSDictionary *remoteNotification = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey]; |
||||
|
||||
FlutterMethodChannel* bridgeAppChannel = [FlutterMethodChannel methodChannelWithName:@"bridge" binaryMessenger:(NSObject<FlutterBinaryMessenger> *)controller]; |
||||
[bridgeAppChannel setMethodCallHandler:^(FlutterMethodCall * _Nonnull call, FlutterResult _Nonnull result) { |
||||
NSString * method = call.method; |
||||
if ([method isEqual:@"action"]) { |
||||
if (remoteNotification != NULL) { |
||||
result(remoteNotification[@"custom"]); |
||||
remoteNotification = nil; |
||||
} |
||||
result(@""); |
||||
} |
||||
if ([method isEqual:@"toAppStore"]) { |
||||
NSString *appURL = @"https://itunes.apple.com/cn/app/1575124838?action=write-review"; |
||||
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:appURL]]; |
||||
result(@""); |
||||
} |
||||
//result(FlutterMethodNotImplemented); |
||||
}]; |
||||
|
||||
return [super application:application didFinishLaunchingWithOptions:launchOptions]; |
||||
} |
||||
|
||||
@end |
@ -0,0 +1,13 @@
|
||||
import UIKit |
||||
import Flutter |
||||
|
||||
@UIApplicationMain |
||||
@objc class AppDelegate: FlutterAppDelegate { |
||||
override func application( |
||||
_ application: UIApplication, |
||||
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? |
||||
) -> Bool { |
||||
GeneratedPluginRegistrant.register(with: self) |
||||
return super.application(application, didFinishLaunchingWithOptions: launchOptions) |
||||
} |
||||
} |
@ -1,13 +0,0 @@
|
||||
// |
||||
// Bridge.swift |
||||
// Runner |
||||
// |
||||
// Created by 冯美坎 on 2021/8/9. |
||||
// |
||||
import Flutter |
||||
import UIKit |
||||
|
||||
class Bridge: NSObject, FlutterPlugin { |
||||
|
||||
|
||||
} |
@ -1,4 +1 @@
|
||||
//
|
||||
// Use this file to import your target's public headers that you would like to expose to Swift.
|
||||
//
|
||||
|
||||
#import "GeneratedPluginRegistrant.h" |
||||
|
Binary file not shown.
Binary file not shown.
@ -1,141 +0,0 @@
|
||||
//
|
||||
// BMKGeoFenceManager.h
|
||||
// BMKLocationKit
|
||||
//
|
||||
// Created by baidu on 2017/3/2.
|
||||
// Copyright © 2017年 baidu. All rights reserved.
|
||||
//
|
||||
|
||||
#import "BMKGeoFenceRegion.h" |
||||
|
||||
@protocol BMKGeoFenceManagerDelegate; |
||||
|
||||
///地理围栏监听状态类型
|
||||
typedef NS_OPTIONS(NSUInteger, BMKGeoFenceActiveAction) |
||||
{ |
||||
BMKGeoFenceActiveActionNone = 0, ///< 不进行监听
|
||||
BMKGeoFenceActiveActionInside = 1 << 0, ///< 在范围内
|
||||
BMKGeoFenceActiveActionOutside = 1 << 1, ///< 在范围外
|
||||
BMKGeoFenceActiveActionStayed = 1 << 2, ///< 停留(在范围内超过10分钟)
|
||||
}; |
||||
|
||||
///BMKGeoFence errorDomain
|
||||
FOUNDATION_EXPORT NSErrorDomain const _Nonnull BMKGeoFenceErrorDomain; |
||||
|
||||
///地理围栏错误码
|
||||
typedef NS_ENUM(NSInteger, BMKGeoFenceErrorCode) { |
||||
BMKGeoFenceErrorUnknown = 1, ///< 未知错误
|
||||
BMKGeoFenceErrorInvalidParameter = 2, ///< 参数错误
|
||||
BMKGeoFenceErrorFailureConnection = 3, ///< 网络连接异常
|
||||
BMKGeoFenceErrorFailureAuth = 4, ///< 鉴权失败
|
||||
BMKGeoFenceErrorNoValidFence = 5, ///< 无可用围栏
|
||||
BMKGeoFenceErroFailureLocating = 6, ///< 定位错误
|
||||
}; |
||||
|
||||
|
||||
///地理围栏管理类
|
||||
@interface BMKGeoFenceManager : NSObject |
||||
|
||||
|
||||
///实现了 BMKGeoFenceManagerDelegate 协议的类指针。
|
||||
@property (nonatomic, weak, nullable) id<BMKGeoFenceManagerDelegate> delegate; |
||||
|
||||
|
||||
///需要进行通知的行为,默认为BMKGeoFenceActiveActionInside。
|
||||
@property (nonatomic, assign) BMKGeoFenceActiveAction activeAction; |
||||
|
||||
|
||||
///指定定位是否会被系统自动暂停。默认为NO。
|
||||
@property (nonatomic, assign) BOOL pausesLocationUpdatesAutomatically; |
||||
|
||||
|
||||
///是否允许后台定位。默认为NO。只在iOS 9.0及之后起作用。设置为YES的时候必须保证 Background Modes 中的 Location updates 处于选中状态,否则会抛出异常。
|
||||
@property (nonatomic, assign) BOOL allowsBackgroundLocationUpdates; |
||||
|
||||
|
||||
/**
|
||||
* @brief 添加一个圆形围栏 |
||||
* @param center 围栏的中心点经纬度坐标 |
||||
* @param radius 围栏的半径,单位:米,要求大于0 |
||||
* @param type 围栏的坐标系类型 |
||||
* @param customID 用户自定义ID,可选,SDK原值返回 |
||||
*/ |
||||
- (void)addCircleRegionForMonitoringWithCenter:(CLLocationCoordinate2D)center radius:(CLLocationDistance)radius coorType:(BMKLocationCoordinateType)type customID:(NSString * _Nullable)customID; |
||||
|
||||
|
||||
/**
|
||||
* @brief 根据经纬度坐标数据添加一个闭合的多边形围栏,点与点之间按顺序尾部相连, 第一个点与最后一个点相连 |
||||
* @param coordinates 经纬度坐标点数据,coordinates对应的内存会拷贝,调用者负责该内存的释放 |
||||
* @param count 经纬度坐标点的个数,不可小于3个 |
||||
* @param type 围栏的坐标系类型 |
||||
* @param customID 用户自定义ID,可选,SDK原值返回 |
||||
*/ |
||||
- (void)addPolygonRegionForMonitoringWithCoordinates:(CLLocationCoordinate2D * _Nonnull)coordinates count:(NSInteger)count coorType:(BMKLocationCoordinateType)type customID:(NSString * _Nullable)customID; |
||||
|
||||
|
||||
/**
|
||||
* @brief 根据customID获得指定的围栏,如果customID传nil,则返回全部围栏 |
||||
* @param customID 用户执行添加围栏函数时传入的customID |
||||
* @return 获得的围栏构成的数组,如果没有结果,返回nil |
||||
*/ |
||||
- (NSArray * _Nullable)geoFenceRegionsWithCustomID:(NSString * _Nullable)customID; |
||||
|
||||
|
||||
/**
|
||||
* @brief 移除指定围栏 |
||||
* @param region 要停止监控的围栏 |
||||
*/ |
||||
- (void)removeTheGeoFenceRegion:(BMKGeoFenceRegion * _Nonnull)region; |
||||
|
||||
|
||||
/**
|
||||
* @brief 移除指定customID的围栏 |
||||
* @param customID 用户执行添加围栏函数时传入的customID |
||||
*/ |
||||
- (void)removeGeoFenceRegionsWithCustomID:(NSString * _Nullable)customID; |
||||
|
||||
|
||||
/**
|
||||
* @brief 移除所有围栏 |
||||
*/ |
||||
- (void)removeAllGeoFenceRegions; |
||||
|
||||
|
||||
@end |
||||
|
||||
|
||||
|
||||
///地理围栏代理协议,该协议定义了获取地理围栏相关回调方法,包括添加、状态改变等。
|
||||
@protocol BMKGeoFenceManagerDelegate <NSObject> |
||||
|
||||
@optional |
||||
|
||||
/**
|
||||
* @brief 为了适配app store关于新的后台定位的审核机制(app store要求如果开发者只配置了使用期间定位,则代码中不能出现申请后台定位的逻辑),当开发者在plist配置NSLocationAlwaysUsageDescription或者NSLocationAlwaysAndWhenInUseUsageDescription时,需要在该delegate中调用后台定位api:[locationManager requestAlwaysAuthorization]。开发者如果只配置了NSLocationWhenInUseUsageDescription,且只有使用期间的定位需求,则无需在delegate中实现逻辑。 |
||||
* @param manager 定位 BMKGeoFenceManager 类。 |
||||
* @param locationManager 系统 CLLocationManager 类 。 |
||||
* @since 1.7.0 |
||||
*/ |
||||
- (void)BMKGeoFenceManager:(BMKGeoFenceManager * _Nonnull)manager doRequestAlwaysAuthorization:(CLLocationManager * _Nonnull)locationManager; |
||||
|
||||
/**
|
||||
* @brief 添加地理围栏完成后的回调,成功与失败都会调用 |
||||
* @param manager 地理围栏管理类 |
||||
* @param regions 成功添加的一个或多个地理围栏构成的数组 |
||||
* @param customID 用户执行添加围栏函数时传入的customID |
||||
* @param error 添加失败的错误信息 |
||||
*/ |
||||
- (void)BMKGeoFenceManager:(BMKGeoFenceManager * _Nonnull)manager didAddRegionForMonitoringFinished:(NSArray <BMKGeoFenceRegion *> * _Nullable)regions customID:(NSString * _Nullable)customID error:(NSError * _Nullable)error; |
||||
|
||||
|
||||
/**
|
||||
* @brief 地理围栏状态改变时回调,当围栏状态的值发生改变,定位失败都会调用 |
||||
* @param manager 地理围栏管理类 |
||||
* @param region 状态改变的地理围栏 |
||||
* @param customID 用户执行添加围栏函数时传入的customID |
||||
* @param error 错误信息,如定位相关的错误 |
||||
*/ |
||||
- (void)BMKGeoFenceManager:(BMKGeoFenceManager * _Nonnull)manager didGeoFencesStatusChangedForRegion:(BMKGeoFenceRegion * _Nullable)region customID:(NSString * _Nullable)customID error:(NSError * _Nullable)error; |
||||
|
||||
@end |
||||
|
@ -1,114 +0,0 @@
|
||||
//
|
||||
// BMKGeoFenceRegion.h
|
||||
// BMKLocationKit
|
||||
//
|
||||
// Created by baidu on 2017/3/2.
|
||||
// Copyright © 2017年 baidu. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h> |
||||
#import <CoreLocation/CoreLocation.h> |
||||
#import "BMKLocationManager.h" |
||||
|
||||
///BMKGeoFence Region State
|
||||
typedef NS_ENUM(NSInteger, BMKGeoFenceRegionStatus) |
||||
{ |
||||
BMKGeoFenceRegionStatusUnknown = 0, ///< 未知
|
||||
BMKGeoFenceRegionStatusInside = 1, ///< 在范围内
|
||||
BMKGeoFenceRegionStatusOutside = 1 << 1, ///< 在范围外
|
||||
BMKGeoFenceRegionStatusStayed = 1 << 2, ///< 停留(在范围内超过10分钟)
|
||||
}; |
||||
|
||||
#pragma mark - BMKGeoFenceRegion |
||||
|
||||
|
||||
///地理围栏基类,不可直接使用
|
||||
@interface BMKGeoFenceRegion : NSObject<NSCopying> |
||||
|
||||
|
||||
///BMKGeoFenceRegion的唯一标识符
|
||||
@property (nonatomic, copy, readonly) NSString *identifier; |
||||
|
||||
|
||||
///用户自定义ID,可为nil。
|
||||
@property (nonatomic, copy, readonly) NSString *customID; |
||||
|
||||
|
||||
///坐标点和围栏的关系,比如用户的位置和围栏的关系
|
||||
@property (nonatomic, assign) BMKGeoFenceRegionStatus fenceStatus; |
||||
|
||||
///设定围栏坐标系类型。默认为 BMKLocationCoordinateTypeGCJ02。
|
||||
@property(nonatomic, readonly) BMKLocationCoordinateType coordinateType; |
||||
|
||||
///上次发生状态变化的时间
|
||||
@property(nonatomic, assign)NSTimeInterval lastEventTime; |
||||
|
||||
|
||||
/**
|
||||
* @brief 判断位置与围栏状态 |
||||
* @param CLLocationCoordinate2D 坐标值 |
||||
* @return 返回BMKGeoFenceRegionStatus状态 |
||||
*/ |
||||
-(BMKGeoFenceRegionStatus)judgeStatusWithCoor:(CLLocationCoordinate2D)coor; |
||||
|
||||
@end |
||||
|
||||
|
||||
#pragma mark - BMKLocationCircleRegion |
||||
|
||||
|
||||
///圆形地理围栏
|
||||
@interface BMKGeoFenceCircleRegion : BMKGeoFenceRegion |
||||
|
||||
|
||||
///中心点的经纬度坐标
|
||||
@property (nonatomic, readonly) CLLocationCoordinate2D center; |
||||
|
||||
|
||||
///半径,单位:米
|
||||
@property (nonatomic, readonly) CLLocationDistance radius; |
||||
|
||||
/**
|
||||
* @brief 构造圆形围栏 |
||||
* @param customid 用户自定义ID |
||||
* @param identityid 识别id |
||||
* @param center 中心坐标 |
||||
* @param radius 围栏半径 |
||||
* @param type 坐标系类型 |
||||
* @return BMKGeoFenceCircleRegion id |
||||
*/ |
||||
- (id)initWithCustomID:(NSString *)customid identityID:(NSString *)identityid center:(CLLocationCoordinate2D)center radius:(CLLocationDistance)radius coor:(BMKLocationCoordinateType)type; |
||||
|
||||
|
||||
|
||||
@end |
||||
|
||||
|
||||
#pragma mark -BMKGeoFencePolygonRegion |
||||
|
||||
|
||||
///多边形地理围栏
|
||||
@interface BMKGeoFencePolygonRegion : BMKGeoFenceRegion |
||||
|
||||
|
||||
///经纬度坐标点数据
|
||||
@property (nonatomic, readonly) CLLocationCoordinate2D *coordinates; |
||||
|
||||
|
||||
///经纬度坐标点的个数
|
||||
@property (nonatomic, readonly) NSInteger count; |
||||
|
||||
|
||||
/**
|
||||
* @brief 构造多边形围栏 |
||||
* @param customid 用户自定义ID |
||||
* @param identityid 识别id |
||||
* @param coor 多边形顶点 |
||||
* @param count 顶点个数 |
||||
* @param type 坐标系类型 |
||||
* @return BMKGeoFencePolygonRegion id |
||||
*/ |
||||
- (id)initWithCustomID:(NSString *)customid identityID:(NSString *)identityid coor:(CLLocationCoordinate2D *)coor count:(NSInteger)count coor:(BMKLocationCoordinateType)type; |
||||
|
||||
@end |
||||
|
@ -1,97 +0,0 @@
|
||||
//
|
||||
// BMKLocation.h
|
||||
// LocationComponent
|
||||
//
|
||||
// Created by baidu on 2017/8/16.
|
||||
// Copyright © 2017年 baidu. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef BMKLocation_h |
||||
#define BMKLocation_h |
||||
|
||||
#import <CoreLocation/CoreLocation.h> |
||||
#import "BMKLocationReGeocode.h" |
||||
|
||||
/**
|
||||
* BMKLocationProvider 位置数据来源,分iOS系统定位和其他定位服务结果两种,目前仅支持iOS系统定位服务 |
||||
* |
||||
*/ |
||||
typedef NS_ENUM(int, BMKLocationProvider) { |
||||
|
||||
BMKLocationProviderIOS = 0, //!<位置来源于iOS本身定位
|
||||
BMKLocationProviderOther //!<位置来源于其他定位服务
|
||||
|
||||
}; |
||||
|
||||
///描述百度iOS 定位数据
|
||||
@interface BMKLocation : NSObject |
||||
|
||||
///BMKLocation 位置数据
|
||||
@property(nonatomic, copy, readonly) CLLocation * _Nullable location; |
||||
|
||||
///BMKLocation 地址数据
|
||||
@property(nonatomic, copy) BMKLocationReGeocode * _Nullable rgcData; |
||||
|
||||
///BMKLocation 位置来源
|
||||
@property(nonatomic, assign) BMKLocationProvider provider; |
||||
|
||||
///BMKLocation 位置ID
|
||||
@property(nonatomic, retain) NSString * _Nullable locationID; |
||||
|
||||
/*
|
||||
* floorString |
||||
* |
||||
* Discussion: |
||||
* 室内定位成功时返回的楼层信息,ex:f1 |
||||
*/ |
||||
@property(readonly, nonatomic, copy, nullable) NSString *floorString; |
||||
|
||||
/*
|
||||
* buildingID |
||||
* |
||||
* Discussion: |
||||
* 室内定位成功时返回的百度建筑物ID |
||||
*/ |
||||
@property(readonly, nonatomic, copy, nullable) NSString *buildingID; |
||||
|
||||
/*
|
||||
* buildingName |
||||
* |
||||
* Discussion: |
||||
* 室内定位成功时返回的百度建筑物名称 |
||||
*/ |
||||
@property(readonly, nonatomic, copy, nullable) NSString *buildingName; |
||||
|
||||
|
||||
/*
|
||||
* extraInfo |
||||
* |
||||
* Discussion: |
||||
* 定位附加信息,如停车位code识别结果、停车位code示例、vdr推算结果置信度等 |
||||
*/ |
||||
@property(readonly, nonatomic, copy, nullable) NSDictionary * extraInfo; |
||||
|
||||
/**
|
||||
* @brief 初始化BMKLocation实例 |
||||
* @param loc CLLocation对象 |
||||
* @param rgc BMKLocationReGeocode对象 |
||||
* @return BMKLocation id |
||||
*/ |
||||
- (id _Nonnull)initWithLocation:(CLLocation * _Nullable)loc withRgcData:(BMKLocationReGeocode * _Nullable)rgc; |
||||
|
||||
/**
|
||||
* @brief 构造BMKLocation |
||||
* @param location CLLocation |
||||
* @param floorString 楼层字符串 |
||||
* @param buildingID 建筑物ID |
||||
* @param buildingName 建筑物名称 |
||||
* @param info 位置附加信息 |
||||
* @return BMKLocation id |
||||
*/ |
||||
-(id _Nonnull)initWithLocation:(CLLocation * _Nullable)location floorString:(NSString * _Nullable)floorString buildingID:(NSString * _Nullable)buildingID |
||||
buildingName:(NSString * _Nullable)buildingName extraInfo:(NSDictionary * _Nullable)info withRgcData:(BMKLocationReGeocode * _Nullable)rgc; |
||||
|
||||
|
||||
@end |
||||
|
||||
#endif /* BMKLocation_h */ |
@ -1,56 +0,0 @@
|
||||
//
|
||||
// BMKLocationAuth.h
|
||||
// LocationComponent
|
||||
//
|
||||
// Created by baidu on 2017/4/10.
|
||||
// Copyright © 2017年 baidu. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef BMKLocationAuth_h |
||||
#define BMKLocationAuth_h |
||||
|
||||
///定位鉴权错误码
|
||||
typedef NS_ENUM(NSInteger, BMKLocationAuthErrorCode) { |
||||
BMKLocationAuthErrorUnknown = -1, ///< 未知错误
|
||||
BMKLocationAuthErrorSuccess = 0, ///< 鉴权成功
|
||||
BMKLocationAuthErrorNetworkFailed = 1, ///< 因网络鉴权失败
|
||||
BMKLocationAuthErrorFailed = 2, ///< KEY非法鉴权失败
|
||||
|
||||
}; |
||||
///通知Delegate
|
||||
@protocol BMKLocationAuthDelegate <NSObject> |
||||
@optional |
||||
|
||||
/**
|
||||
*@brief 返回授权验证错误 |
||||
*@param iError 错误号 : 为0时验证通过,具体参加BMKLocationAuthErrorCode |
||||
*/ |
||||
- (void)onCheckPermissionState:(BMKLocationAuthErrorCode)iError; |
||||
@end |
||||
|
||||
|
||||
///BMKLocationAuth类。用于鉴权
|
||||
@interface BMKLocationAuth : NSObject |
||||
|
||||
///鉴权状态0:成功; 1:网络错误; 2:授权失败
|
||||
@property(nonatomic, readonly, assign) BMKLocationAuthErrorCode permisionState; |
||||
|
||||
/**
|
||||
* @brief 得到BMKLocationAuth的单例 |
||||
*/ |
||||
+ (BMKLocationAuth*)sharedInstance; |
||||
|
||||
|
||||
/**
|
||||
*@brief 启动引擎 |
||||
*@param key 申请的有效key |
||||
*@param delegate 回调是否鉴权成功 |
||||
*/ |
||||
-(void)checkPermisionWithKey:(NSString*)key authDelegate:(id<BMKLocationAuthDelegate>)delegate; |
||||
|
||||
|
||||
@end |
||||
|
||||
|
||||
|
||||
#endif /* BMKLocationAuth_h */ |
@ -1,16 +0,0 @@
|
||||
//
|
||||
// BMKLocationComponent.h
|
||||
// LocationComponent
|
||||
//
|
||||
// Created by Baidu on 3/31/14.
|
||||
// Copyright (c) 2014 baidu. All rights reserved.
|
||||
//
|
||||
|
||||
#import "BMKLocationManager.h" |
||||
#import "BMKLocationKitVersion.h" |
||||
#import "BMKLocationPoi.h" |
||||
#import "BMKLocation.h" |
||||
#import "BMKGeoFenceRegion.h" |
||||
#import "BMKGeoFenceManager.h" |
||||
#import "BMKLocationReGeocode.h" |
||||
#import "BMKLocationAuth.h" |
@ -1,30 +0,0 @@
|
||||
//
|
||||
// BMKLocationKitVersion.h
|
||||
// BMKLocationKit
|
||||
//
|
||||
// Created by baidu on 17/9/9.
|
||||
// Copyright © 2017年 baidu. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef BMKLocationKitVersion_h |
||||
#define BMKLocationKitVersion_h |
||||
|
||||
#import <UIKit/UIKit.h> |
||||
|
||||
/**
|
||||
*获取当前定位sdk 的版本号 |
||||
*当前定位sdk版本 : 2.0.0 |
||||
*@return 返回当前定位sdk 的版本号 |
||||
*/ |
||||
UIKIT_EXTERN NSString* BMKLocationKitVersion(); |
||||
|
||||
/**
|
||||
*获取当前定位sdk 的float版本号 |
||||
*当前定位sdk版本 : 2.0 |
||||
*@return 返回当前定位sdk 的float版本号 |
||||
*/ |
||||
UIKIT_EXTERN float BMKLocationKitFloatVersion(); |
||||
|
||||
|
||||
|
||||
#endif /* BMKLocationKitVersion_h */ |
@ -1,296 +0,0 @@
|
||||
//
|
||||
// BMKLocationManager.h
|
||||
// BMKLocationKit
|
||||
//
|
||||
// Created by baidu on 2017/3/2.
|
||||
// Copyright © 2017年 baidu. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Availability.h> |
||||
#import <Foundation/Foundation.h> |
||||
#import <CoreLocation/CoreLocation.h> |
||||
#import "BMKLocationReGeocode.h" |
||||
#import "BMKLocation.h" |
||||
|
||||
/** BMKLocationCoordinateType 枚举坐标系类型
|
||||
* |
||||
*/ |
||||
typedef NS_ENUM(NSUInteger, BMKLocationCoordinateType) |
||||
{ |
||||
BMKLocationCoordinateTypeBMK09LL = 0, ///<BMK09LL
|
||||
BMKLocationCoordinateTypeBMK09MC, ///<BMK09MC
|
||||
BMKLocationCoordinateTypeWGS84, ///<WGS84
|
||||
BMKLocationCoordinateTypeGCJ02 ///<GCJ02
|
||||
}; |
||||
|
||||
/** BMKLocationNetworkState 枚举识别网络状态类型
|
||||
* |
||||
*/ |
||||
typedef NS_ENUM(int, BMKLocationNetworkState) { |
||||
BMKLocationNetworkStateUnknown = 0, ///<网络状态未知
|
||||
BMKLocationNetworkStateWifi, ///<网络状态wifi
|
||||
BMKLocationNetworkStateWifiHotSpot, ///<网络状态连接WIFI移动热点
|
||||
BMKLocationNetworkStateMobile2G, ///<网络状态移动2G
|
||||
BMKLocationNetworkStateMobile3G, ///<网络状态移动3G
|
||||
BMKLocationNetworkStateMobile4G ///<网络状态移动4G
|
||||
|
||||
}; |
||||
|
||||
|
||||
///BMKLocation errorDomain
|
||||
|
||||
FOUNDATION_EXPORT NSErrorDomain const _Nonnull BMKLocationErrorDomain; |
||||
|
||||
///BMKLocation errorCode
|
||||
typedef NS_ENUM(NSInteger, BMKLocationErrorCode) |
||||
{ |
||||
BMKLocationErrorUnKnown = 0, ///<未知异常
|
||||
BMKLocationErrorLocFailed = 1, ///<位置未知,持续定位中
|
||||
BMKLocationErrorDenied = 2, ///<手机不允许定位,请确认用户授予定位权限或者手机是否打开定位开关
|
||||
BMKLocationErrorNetWork = 3, ///<因为网络原因导致系统定位失败
|
||||
BMKLocationErrorHeadingFailed = 4, ///<获取手机方向信息失败
|
||||
BMKLocationErrorGetExtraNetworkFailed = 5, ///<网络原因导致获取额外信息(地址、网络状态等信息)失败
|
||||
BMKLocationErrorGetExtraParseFailed = 6, ///<网络返回数据解析失败导致获取额外信息(地址、网络状态等信息)失败
|
||||
BMKLocationErrorFailureAuth = 7, ///<鉴权失败导致无法返回定位、地址等信息
|
||||
}; |
||||
|
||||
/** BMKLAccuracyAuthorization 枚举返回定位精度等级
|
||||
* |
||||
*/ |
||||
typedef NS_ENUM(NSInteger, BMKLAccuracyAuthorization) { |
||||
|
||||
BMKLAccuracyAuthorizationFullAccuracy, ///<全量定位精度等级,该等级下定位返回结果会尽可能精准
|
||||
BMKLAccuracyAuthorizationReducedAccuracy, ///<降级定位精度等级,该等级下定位会返回大概5km精度范围的点,定位频率、实时性上也会变慢,比如可能是20分钟之前的点,适用于那些只要求城市级别精度的app使用;ios14之后,该等级受用户控制,需要高等级权限的app需要对应做好适配工作
|
||||
}; |
||||
|
||||
|
||||
/**
|
||||
* @brief 单次定位返回Block |
||||
* @param location 定位信息,数据包括CLLocation 位置数据,BMKLocationReGeocode 地址信息,参考BMKLocation。 |
||||
* @param state 移动热点状态 |
||||
* @param error 错误信息,参考 BMKLocationErrorCode |
||||
*/ |
||||
typedef void (^BMKLocatingCompletionBlock)(BMKLocation * _Nullable location, BMKLocationNetworkState state , NSError * _Nullable error); |
||||
|
||||
|
||||
|
||||
@protocol BMKLocationManagerDelegate; |
||||
|
||||
#pragma mark - BMKLocationManager |
||||
|
||||
|
||||
///BMKLocationManager类。初始化之前请设置 BMKLocationAuth 中的APIKey,否则将无法正常使用服务.
|
||||
@interface BMKLocationManager : NSObject |
||||
|
||||
///实现了 BMKLocationManagerDelegate 协议的类指针。
|
||||
@property (nonatomic, weak, nullable) id<BMKLocationManagerDelegate> delegate; |
||||
|
||||
///设定定位的最小更新距离。默认为 kCLDistanceFilterNone。
|
||||
@property(nonatomic, assign) CLLocationDistance distanceFilter; |
||||
|
||||
///设定定位精度。默认为 kCLLocationAccuracyBest。
|
||||
@property(nonatomic, assign) CLLocationAccuracy desiredAccuracy; |
||||
|
||||
///设定定位类型。默认为 CLActivityTypeAutomotiveNavigation。
|
||||
@property(nonatomic, assign) CLActivityType activityType; |
||||
|
||||
///设定定位坐标系类型。默认为 BMKLocationCoordinateTypeGCJ02。
|
||||
@property(nonatomic, assign) BMKLocationCoordinateType coordinateType; |
||||
|
||||
///指定定位是否会被系统自动暂停。默认为NO。
|
||||
@property(nonatomic, assign) BOOL pausesLocationUpdatesAutomatically; |
||||
|
||||
|
||||
///是否允许后台定位。默认为NO。只在iOS 9.0及之后起作用。设置为YES的时候必须保证 Background Modes 中的 Location updates 处于选中状态,否则会抛出异常。由于iOS系统限制,需要在定位未开始之前或定位停止之后,修改该属性的值才会有效果。
|
||||
@property(nonatomic, assign) BOOL allowsBackgroundLocationUpdates; |
||||
|
||||
///指定单次定位超时时间,默认为10s。最小值是2s。注意单次定位请求前设置。注意: 单次定位超时时间从确定了定位权限(非kCLAuthorizationStatusNotDetermined状态)后开始计算。
|
||||
@property(nonatomic, assign) NSInteger locationTimeout; |
||||
|
||||
///指定单次定位逆地理超时时间,默认为10s。最小值是2s。注意单次定位请求前设置。
|
||||
@property(nonatomic, assign) NSInteger reGeocodeTimeout; |
||||
|
||||
///连续定位是否返回逆地理信息,默认YES。
|
||||
@property (nonatomic, assign) BOOL locatingWithReGeocode; |
||||
|
||||
///定位sdk-v1.3之后,开发者可以选择是否需要最新版本rgc数据,1.9之后默认是需要YES;YES的情况下,定位sdk会实时返回最新的rgc数据,如城市变更等数据都会实时更新
|
||||
@property (nonatomic, assign) BOOL isNeedNewVersionReGeocode; |
||||
|
||||
|
||||
///开发者可以指定该用户的id,用于后续统一识别用户,便于查找问题
|
||||
@property(nonatomic, copy, nullable) NSString * userID; |
||||
|
||||
///返回定位精度等级,IOS14之后用户可以直接控制返回定位的精度等级,开发者可以通过这个值适配不同定位等级下的产品逻辑
|
||||
@property (nonatomic, readonly) BMKLAccuracyAuthorization accuracyAuthorization; |
||||
|
||||
|
||||
/**
|
||||
* @brief 单次定位。如果当前正在连续定位,调用此方法将会失败,返回NO。\n该方法将会根据设定的 desiredAccuracy 去获取定位信息。如果获取的定位信息精确度低于 desiredAccuracy ,将会持续的等待定位信息,直到超时后通过completionBlock返回精度最高的定位信息。\n可以通过 stopUpdatingLocation 方法去取消正在进行的单次定位请求。 |
||||
* @param withReGeocode 是否带有逆地理信息(获取逆地理信息需要联网) |
||||
* @param withNetWorkState 是否带有移动热点识别状态(需要联网) |
||||
* @param completionBlock 单次定位完成后的Block |
||||
* @return 是否成功添加单次定位Request |
||||
*/ |
||||
- (BOOL)requestLocationWithReGeocode:(BOOL)withReGeocode withNetworkState:(BOOL)withNetWorkState completionBlock:(BMKLocatingCompletionBlock _Nonnull)completionBlock; |
||||
|
||||
/**
|
||||
* @brief 开始连续定位。调用此方法会cancel掉所有的单次定位请求。 |
||||
*/ |
||||
- (void)startUpdatingLocation; |
||||
|
||||
/**
|
||||
* @brief 停止连续定位。调用此方法会cancel掉所有的单次定位请求,可以用来取消单次定位。 |
||||
*/ |
||||
- (void)stopUpdatingLocation; |
||||
|
||||
/**
|
||||
* @brief 请求网络状态结果回调。 |
||||
*/ |
||||
- (void)requestNetworkState; |
||||
|
||||
|
||||
/**
|
||||
* @brief 该方法返回设备是否支持设备朝向事件回调。 |
||||
* @return 是否支持设备朝向事件回调 |
||||
*/ |
||||
+ (BOOL)headingAvailable; |
||||
|
||||
/**
|
||||
* @brief 该方法为BMKLocationManager开始设备朝向事件回调。 |
||||
*/ |
||||
- (void)startUpdatingHeading; |
||||
|
||||
/**
|
||||
* @brief 该方法为BMKLocationManager停止设备朝向事件回调。 |
||||
*/ |
||||
- (void)stopUpdatingHeading; |
||||
|
||||
/**
|
||||
* @brief 该方法为BMKLocationManager尝试使用高精度室内定位。在特定的室内场景下会有更高精度的定位回调,只在室内定位版本生效。 |
||||
*/ |
||||
- (void)tryIndoorLocation; |
||||
|
||||
/**
|
||||
* @brief 该方法为BMKLocationManager会关闭高精度室内定位,只在室内定位版本生效。 |
||||
*/ |
||||
- (void)stopIndoorLocation; |
||||
|
||||
|
||||
/**
|
||||
* @brief 转换为百度经纬度的坐标 |
||||
* @param coordinate 待转换的经纬度 |
||||
* @param srctype 待转换坐标系类型 |
||||
* @param destype 目标百度坐标系类型(bd09ll,bd09mc) |
||||
* @return 目标百度坐标系经纬度 |
||||
*/ |
||||
+ (CLLocationCoordinate2D) BMKLocationCoordinateConvert:(CLLocationCoordinate2D) coordinate SrcType:(BMKLocationCoordinateType)srctype DesType:(BMKLocationCoordinateType)destype; |
||||
|
||||
/**
|
||||
* @brief 判断目标经纬度是否在大陆以及港、澳地区。 |
||||
* @param coordinate 待判断的目标经纬度 |
||||
* @param coortype 待判断经纬度的坐标系类型 |
||||
* @return 是否在大陆以及港、澳地区 |
||||
*/ |
||||
+ (BOOL) BMKLocationDataAvailableForCoordinate:(CLLocationCoordinate2D)coordinate withCoorType:(BMKLocationCoordinateType)coortype; |
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief 返回当前定位权限 |
||||
* @return CLAuthorizationStatus 定位权限枚举类型 |
||||
*/ |
||||
- (CLAuthorizationStatus)authorizationStatus; |
||||
|
||||
|
||||
/**
|
||||
* @brief 如果你没有全量定位等级精度权限,利用该接口可以临时请求一次全量定位精度等级,系统会抛出弹框让用户确认是否授权app授予相应权限 |
||||
* @param purposeKey info.plist中NSLocationTemporaryUsageDescriptionDictionary定义的key,对应相应的value可以详细描述申请全量定位精度等级的原因 |
||||
* @param completion 回调是否 |
||||
* @return |
||||
*/ |
||||
- (void)requestTemporaryFullAccuracyAuthorizationWithPurposeKey:(NSString * _Nonnull)purposeKey completion:(void(^ _Nullable)(NSError * _Nullable))completion API_AVAILABLE(ios(14.0)); |
||||
|
||||
/**
|
||||
* @brief 请求一次全量定位精度等级 |
||||
* @param purposeKey info.plist中NSLocationTemporaryUsageDescriptionDictionary定义的key |
||||
* @return |
||||
*/ |
||||
- (void)requestTemporaryFullAccuracyAuthorizationWithPurposeKey:(NSString * _Nonnull)purposeKey API_AVAILABLE(ios(14.0)); |
||||
|
||||
|
||||
@end |
||||
|
||||
#pragma mark - BMKLocationManagerDelegate |
||||
|
||||
|
||||
///BMKLocationManagerDelegate 协议定义了发生错误时的错误回调方法,连续定位的回调方法等。
|
||||
@protocol BMKLocationManagerDelegate <NSObject> |
||||
|
||||
@optional |
||||
|
||||
/**
|
||||
* @brief 为了适配app store关于新的后台定位的审核机制(app store要求如果开发者只配置了使用期间定位,则代码中不能出现申请后台定位的逻辑),当开发者在plist配置NSLocationAlwaysUsageDescription或者NSLocationAlwaysAndWhenInUseUsageDescription时,需要在该delegate中调用后台定位api:[locationManager requestAlwaysAuthorization]。开发者如果只配置了NSLocationWhenInUseUsageDescription,且只有使用期间的定位需求,则无需在delegate中实现逻辑。 |
||||
* @param manager 定位 BMKLocationManager 类。 |
||||
* @param locationManager 系统 CLLocationManager 类 。 |
||||
* @since 1.6.0 |
||||
*/ |
||||
- (void)BMKLocationManager:(BMKLocationManager * _Nonnull)manager doRequestAlwaysAuthorization:(CLLocationManager * _Nonnull)locationManager; |
||||
|
||||
/**
|
||||
* @brief 当定位发生错误时,会调用代理的此方法。 |
||||
* @param manager 定位 BMKLocationManager 类。 |
||||
* @param error 返回的错误,参考 CLError 。 |
||||
*/ |
||||
- (void)BMKLocationManager:(BMKLocationManager * _Nonnull)manager didFailWithError:(NSError * _Nullable)error; |
||||
|
||||
|
||||
/**
|
||||
* @brief 连续定位回调函数。 |
||||
* @param manager 定位 BMKLocationManager 类。 |
||||
* @param location 定位结果,参考BMKLocation。 |
||||
* @param error 错误信息。 |
||||
*/ |
||||
- (void)BMKLocationManager:(BMKLocationManager * _Nonnull)manager didUpdateLocation:(BMKLocation * _Nullable)location orError:(NSError * _Nullable)error; |
||||
|
||||
/**
|
||||
* @brief 定位权限状态改变时回调函数 |
||||
* @param manager 定位 BMKLocationManager 类。 |
||||
* @param status 定位权限状态。 |
||||
*/ |
||||
- (void)BMKLocationManager:(BMKLocationManager * _Nonnull)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status API_DEPRECATED_WITH_REPLACEMENT("-BMKLocationManagerDidChangeAuthorization", ios(4.2, 14.0)); |
||||
|
||||
|
||||
/**
|
||||
* @brief authorizationStatus或者accuracyAuthorization有变化时回调函数 |
||||
* @param manager 定位 BMKLocationManager 类。 |
||||
*/ |
||||
- (void)BMKLocationManagerDidChangeAuthorization:(BMKLocationManager * _Nonnull)manager; |
||||
|
||||
|
||||
/**
|
||||
* @brief 该方法为BMKLocationManager提示需要设备校正回调方法。 |
||||
* @param manager 提供该定位结果的BMKLocationManager类的实例。 |
||||
*/ |
||||
- (BOOL)BMKLocationManagerShouldDisplayHeadingCalibration:(BMKLocationManager * _Nonnull)manager; |
||||
|
||||
/**
|
||||
* @brief 该方法为BMKLocationManager提供设备朝向的回调方法。 |
||||
* @param manager 提供该定位结果的BMKLocationManager类的实例 |
||||
* @param heading 设备的朝向结果 |
||||
*/ |
||||
- (void)BMKLocationManager:(BMKLocationManager * _Nonnull)manager |
||||
didUpdateHeading:(CLHeading * _Nullable)heading; |
||||
|
||||
/**
|
||||
* @brief 该方法为BMKLocationManager所在App系统网络状态改变的回调事件。 |
||||
* @param manager 提供该定位结果的BMKLocationManager类的实例 |
||||
* @param state 当前网络状态 |
||||
* @param error 错误信息 |
||||
*/ |
||||
- (void)BMKLocationManager:(BMKLocationManager * _Nonnull)manager |
||||
didUpdateNetworkState:(BMKLocationNetworkState)state orError:(NSError * _Nullable)error; |
||||
|
||||
|
||||
@end |
||||
|
||||
|
@ -1,42 +0,0 @@
|
||||
//
|
||||
// BMKLocationPoi.h
|
||||
// BMKLocationKit
|
||||
//
|
||||
// Created by baidu on 2017/3/2.
|
||||
// Copyright © 2017年 baidu. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
///描述Poi各属性
|
||||
@interface BMKLocationPoi : NSObject |
||||
|
||||
///BMKLocationPoi的id属性
|
||||
@property(nonatomic, copy, readonly) NSString *uid; |
||||
|
||||
///BMKLocationPoi的名字属性
|
||||
@property(nonatomic, copy, readonly) NSString *name; |
||||
|
||||
///BMKLocationPoi的标签属性
|
||||
@property(nonatomic, copy, readonly) NSString *tags; |
||||
|
||||
///BMKLocationPoi的地址属性
|
||||
@property(nonatomic, copy, readonly) NSString *addr; |
||||
|
||||
///BMKLocationPoi的可信度
|
||||
@property(nonatomic, assign, readonly) float relaiability; |
||||
|
||||
|
||||
/**
|
||||
* @brief 通过NSDictionary初始化方法一 |
||||
*/ |
||||
- (id)initWithDictionary:(NSDictionary *)dictionary; |
||||
|
||||
|
||||
/**
|
||||
* @brief 通过NSDictionary初始化方法二 |
||||
*/ |
||||
- (id)initWithTwoDictionary:(NSDictionary *)dictionary; |
||||
|
||||
@end |
||||
|
||||
|
@ -1,35 +0,0 @@
|
||||
//
|
||||
// BMKLocationPoiRegion.h
|
||||
// LocationComponent
|
||||
//
|
||||
// Created by Jiang,Fangsheng on 2019/9/4.
|
||||
// Copyright © 2019 baidu. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef BMKLocationPoiRegion_h |
||||
#define BMKLocationPoiRegion_h |
||||
|
||||
|
||||
///描述PoiRegion各属性
|
||||
@interface BMKLocationPoiRegion : NSObject |
||||
|
||||
///BMKLocationPoiRegion的方向属性,如『内』、『外』
|
||||
@property(nonatomic, copy, readonly) NSString *directionDesc; |
||||
|
||||
///BMKLocationPoiRegion的名字属性
|
||||
@property(nonatomic, copy, readonly) NSString *name; |
||||
|
||||
///BMKLocationPoiRegion的标签属性
|
||||
@property(nonatomic, copy, readonly) NSString *tags; |
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief 通过NSDictionary初始化方法一 |
||||
*/ |
||||
- (id)initWithDictionary:(NSDictionary *)dictionary; |
||||
|
||||
|
||||
@end |
||||
|
||||
#endif /* BMKLocationPoiRegion_h */ |
@ -1,67 +0,0 @@
|
||||
//
|
||||
// BMKLocationReGeocode.h
|
||||
// BMKLocationKit
|
||||
//
|
||||
// Created by baidu on 2017/3/2.
|
||||
// Copyright © 2017年 baidu. All rights reserved.
|
||||
//
|
||||
#import <Foundation/Foundation.h> |
||||
#import "BMKLocationPoi.h" |
||||
#import "BMKLocationPoiRegion.h" |
||||
|
||||
///BMKLocationReGeocode类。描述跟地址有关的信息.
|
||||
@interface BMKLocationReGeocode : NSObject |
||||
|
||||
///国家名字属性
|
||||
@property(nonatomic, copy, readonly) NSString *country; |
||||
|
||||
///国家编码属性
|
||||
@property(nonatomic, copy, readonly) NSString *countryCode; |
||||
|
||||
///省份名字属性
|
||||
@property(nonatomic, copy, readonly) NSString *province; |
||||
|
||||
///城市名字属性
|
||||
@property(nonatomic, copy, readonly) NSString *city; |
||||
|
||||
///区名字属性
|
||||
@property(nonatomic, copy, readonly) NSString *district; |
||||
|
||||
///乡镇名字属性
|
||||
@property(nonatomic, copy, readonly) NSString *town; |
||||
|
||||
///街道名字属性
|
||||
@property(nonatomic, copy, readonly) NSString *street; |
||||
|
||||
///街道号码属性
|
||||
@property(nonatomic, copy, readonly) NSString *streetNumber; |
||||
|
||||
///城市编码属性
|
||||
@property(nonatomic, copy, readonly) NSString *cityCode; |
||||
|
||||
///行政区划编码属性
|
||||
@property(nonatomic, copy, readonly) NSString *adCode; |
||||
|
||||
|
||||
///位置语义化结果的定位点在什么地方周围的描述信息
|
||||
@property(nonatomic, copy, readonly) NSString *locationDescribe; |
||||
|
||||
|
||||
///位置语义化结果的属性,该定位点周围的poi列表信息
|
||||
@property(nonatomic, retain, readonly) NSArray<BMKLocationPoi *> *poiList; |
||||
|
||||
///位置语义化结果的定位点在什么地方周围的描述信息
|
||||
@property(nonatomic, strong, readonly) BMKLocationPoiRegion *poiRegion; |
||||
|
||||
/**
|
||||
* @brief 通过NSData初始化方法 |
||||
*/ |
||||
- (id)initWithReGeocodeString:(NSData *)reGeocodeString; |
||||
|
||||
|
||||
/**
|
||||
* @brief 通过JSON初始化方法 |
||||
*/ |
||||
- (id)initWithJsonString:(NSData *)jsonString withHighAccuracy:(BOOL)highAcc; |
||||
|
||||
@end |
@ -1,11 +0,0 @@
|
||||
1、版本: |
||||
百度地图iOS定位SDK v2.0.0 |
||||
|
||||
2、是否带IDFA: |
||||
无 |
||||
|
||||
3、是否为Bitcode: |
||||
是 |
||||
|
||||
4、集成方法: |
||||
http://lbsyun.baidu.com/index.php?title=ios-locsdk |
@ -1,141 +0,0 @@
|
||||
//
|
||||
// BMKGeoFenceManager.h
|
||||
// BMKLocationKit
|
||||
//
|
||||
// Created by baidu on 2017/3/2.
|
||||
// Copyright © 2017年 baidu. All rights reserved.
|
||||
//
|
||||
|
||||
#import "BMKGeoFenceRegion.h" |
||||
|
||||
@protocol BMKGeoFenceManagerDelegate; |
||||
|
||||
///地理围栏监听状态类型
|
||||
typedef NS_OPTIONS(NSUInteger, BMKGeoFenceActiveAction) |
||||
{ |
||||
BMKGeoFenceActiveActionNone = 0, ///< 不进行监听
|
||||
BMKGeoFenceActiveActionInside = 1 << 0, ///< 在范围内
|
||||
BMKGeoFenceActiveActionOutside = 1 << 1, ///< 在范围外
|
||||
BMKGeoFenceActiveActionStayed = 1 << 2, ///< 停留(在范围内超过10分钟)
|
||||
}; |
||||
|
||||
///BMKGeoFence errorDomain
|
||||
FOUNDATION_EXPORT NSErrorDomain const _Nonnull BMKGeoFenceErrorDomain; |
||||
|
||||
///地理围栏错误码
|
||||
typedef NS_ENUM(NSInteger, BMKGeoFenceErrorCode) { |
||||
BMKGeoFenceErrorUnknown = 1, ///< 未知错误
|
||||
BMKGeoFenceErrorInvalidParameter = 2, ///< 参数错误
|
||||
BMKGeoFenceErrorFailureConnection = 3, ///< 网络连接异常
|
||||
BMKGeoFenceErrorFailureAuth = 4, ///< 鉴权失败
|
||||
BMKGeoFenceErrorNoValidFence = 5, ///< 无可用围栏
|
||||
BMKGeoFenceErroFailureLocating = 6, ///< 定位错误
|
||||
}; |
||||
|
||||
|
||||
///地理围栏管理类
|
||||
@interface BMKGeoFenceManager : NSObject |
||||
|
||||
|
||||
///实现了 BMKGeoFenceManagerDelegate 协议的类指针。
|
||||
@property (nonatomic, weak, nullable) id<BMKGeoFenceManagerDelegate> delegate; |
||||
|
||||
|
||||
///需要进行通知的行为,默认为BMKGeoFenceActiveActionInside。
|
||||
@property (nonatomic, assign) BMKGeoFenceActiveAction activeAction; |
||||
|
||||
|
||||
///指定定位是否会被系统自动暂停。默认为NO。
|
||||
@property (nonatomic, assign) BOOL pausesLocationUpdatesAutomatically; |
||||
|
||||
|
||||
///是否允许后台定位。默认为NO。只在iOS 9.0及之后起作用。设置为YES的时候必须保证 Background Modes 中的 Location updates 处于选中状态,否则会抛出异常。
|
||||
@property (nonatomic, assign) BOOL allowsBackgroundLocationUpdates; |
||||
|
||||
|
||||
/**
|
||||
* @brief 添加一个圆形围栏 |
||||
* @param center 围栏的中心点经纬度坐标 |
||||
* @param radius 围栏的半径,单位:米,要求大于0 |
||||
* @param type 围栏的坐标系类型 |
||||
* @param customID 用户自定义ID,可选,SDK原值返回 |
||||
*/ |
||||
- (void)addCircleRegionForMonitoringWithCenter:(CLLocationCoordinate2D)center radius:(CLLocationDistance)radius coorType:(BMKLocationCoordinateType)type customID:(NSString * _Nullable)customID; |
||||
|
||||
|
||||
/**
|
||||
* @brief 根据经纬度坐标数据添加一个闭合的多边形围栏,点与点之间按顺序尾部相连, 第一个点与最后一个点相连 |
||||
* @param coordinates 经纬度坐标点数据,coordinates对应的内存会拷贝,调用者负责该内存的释放 |
||||
* @param count 经纬度坐标点的个数,不可小于3个 |
||||
* @param type 围栏的坐标系类型 |
||||
* @param customID 用户自定义ID,可选,SDK原值返回 |
||||
*/ |
||||
- (void)addPolygonRegionForMonitoringWithCoordinates:(CLLocationCoordinate2D * _Nonnull)coordinates count:(NSInteger)count coorType:(BMKLocationCoordinateType)type customID:(NSString * _Nullable)customID; |
||||
|
||||
|
||||
/**
|
||||
* @brief 根据customID获得指定的围栏,如果customID传nil,则返回全部围栏 |
||||
* @param customID 用户执行添加围栏函数时传入的customID |
||||
* @return 获得的围栏构成的数组,如果没有结果,返回nil |
||||
*/ |
||||
- (NSArray * _Nullable)geoFenceRegionsWithCustomID:(NSString * _Nullable)customID; |
||||
|
||||
|
||||
/**
|
||||
* @brief 移除指定围栏 |
||||
* @param region 要停止监控的围栏 |
||||
*/ |
||||
- (void)removeTheGeoFenceRegion:(BMKGeoFenceRegion * _Nonnull)region; |
||||
|
||||
|
||||
/**
|
||||
* @brief 移除指定customID的围栏 |
||||
* @param customID 用户执行添加围栏函数时传入的customID |
||||
*/ |
||||
- (void)removeGeoFenceRegionsWithCustomID:(NSString * _Nullable)customID; |
||||
|
||||
|
||||
/**
|
||||
* @brief 移除所有围栏 |
||||
*/ |
||||
- (void)removeAllGeoFenceRegions; |
||||
|
||||
|
||||
@end |
||||
|
||||
|
||||
|
||||
///地理围栏代理协议,该协议定义了获取地理围栏相关回调方法,包括添加、状态改变等。
|
||||
@protocol BMKGeoFenceManagerDelegate <NSObject> |
||||
|
||||
@optional |
||||
|
||||
/**
|
||||
* @brief 为了适配app store关于新的后台定位的审核机制(app store要求如果开发者只配置了使用期间定位,则代码中不能出现申请后台定位的逻辑),当开发者在plist配置NSLocationAlwaysUsageDescription或者NSLocationAlwaysAndWhenInUseUsageDescription时,需要在该delegate中调用后台定位api:[locationManager requestAlwaysAuthorization]。开发者如果只配置了NSLocationWhenInUseUsageDescription,且只有使用期间的定位需求,则无需在delegate中实现逻辑。 |
||||
* @param manager 定位 BMKGeoFenceManager 类。 |
||||
* @param locationManager 系统 CLLocationManager 类 。 |
||||
* @since 1.7.0 |
||||
*/ |
||||
- (void)BMKGeoFenceManager:(BMKGeoFenceManager * _Nonnull)manager doRequestAlwaysAuthorization:(CLLocationManager * _Nonnull)locationManager; |
||||
|
||||
/**
|
||||
* @brief 添加地理围栏完成后的回调,成功与失败都会调用 |
||||
* @param manager 地理围栏管理类 |
||||
* @param regions 成功添加的一个或多个地理围栏构成的数组 |
||||
* @param customID 用户执行添加围栏函数时传入的customID |
||||
* @param error 添加失败的错误信息 |
||||
*/ |
||||
- (void)BMKGeoFenceManager:(BMKGeoFenceManager * _Nonnull)manager didAddRegionForMonitoringFinished:(NSArray <BMKGeoFenceRegion *> * _Nullable)regions customID:(NSString * _Nullable)customID error:(NSError * _Nullable)error; |
||||
|
||||
|
||||
/**
|
||||
* @brief 地理围栏状态改变时回调,当围栏状态的值发生改变,定位失败都会调用 |
||||
* @param manager 地理围栏管理类 |
||||
* @param region 状态改变的地理围栏 |
||||
* @param customID 用户执行添加围栏函数时传入的customID |
||||
* @param error 错误信息,如定位相关的错误 |
||||
*/ |
||||
- (void)BMKGeoFenceManager:(BMKGeoFenceManager * _Nonnull)manager didGeoFencesStatusChangedForRegion:(BMKGeoFenceRegion * _Nullable)region customID:(NSString * _Nullable)customID error:(NSError * _Nullable)error; |
||||
|
||||
@end |
||||
|
@ -1,114 +0,0 @@
|
||||
//
|
||||
// BMKGeoFenceRegion.h
|
||||
// BMKLocationKit
|
||||
//
|
||||
// Created by baidu on 2017/3/2.
|
||||
// Copyright © 2017年 baidu. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h> |
||||
#import <CoreLocation/CoreLocation.h> |
||||
#import "BMKLocationManager.h" |
||||
|
||||
///BMKGeoFence Region State
|
||||
typedef NS_ENUM(NSInteger, BMKGeoFenceRegionStatus) |
||||
{ |
||||
BMKGeoFenceRegionStatusUnknown = 0, ///< 未知
|
||||
BMKGeoFenceRegionStatusInside = 1, ///< 在范围内
|
||||
BMKGeoFenceRegionStatusOutside = 1 << 1, ///< 在范围外
|
||||
BMKGeoFenceRegionStatusStayed = 1 << 2, ///< 停留(在范围内超过10分钟)
|
||||
}; |
||||
|
||||
#pragma mark - BMKGeoFenceRegion |
||||
|
||||
|
||||
///地理围栏基类,不可直接使用
|
||||
@interface BMKGeoFenceRegion : NSObject<NSCopying> |
||||
|
||||
|
||||
///BMKGeoFenceRegion的唯一标识符
|
||||
@property (nonatomic, copy, readonly) NSString *identifier; |
||||
|
||||
|
||||
///用户自定义ID,可为nil。
|
||||
@property (nonatomic, copy, readonly) NSString *customID; |
||||
|
||||
|
||||
///坐标点和围栏的关系,比如用户的位置和围栏的关系
|
||||
@property (nonatomic, assign) BMKGeoFenceRegionStatus fenceStatus; |
||||
|
||||
///设定围栏坐标系类型。默认为 BMKLocationCoordinateTypeGCJ02。
|
||||
@property(nonatomic, readonly) BMKLocationCoordinateType coordinateType; |
||||
|
||||
///上次发生状态变化的时间
|
||||
@property(nonatomic, assign)NSTimeInterval lastEventTime; |
||||
|
||||
|
||||
/**
|
||||
* @brief 判断位置与围栏状态 |
||||
* @param CLLocationCoordinate2D 坐标值 |
||||
* @return 返回BMKGeoFenceRegionStatus状态 |
||||
*/ |
||||
-(BMKGeoFenceRegionStatus)judgeStatusWithCoor:(CLLocationCoordinate2D)coor; |
||||
|
||||
@end |
||||
|
||||
|
||||
#pragma mark - BMKLocationCircleRegion |
||||
|
||||
|
||||
///圆形地理围栏
|
||||
@interface BMKGeoFenceCircleRegion : BMKGeoFenceRegion |
||||
|
||||
|
||||
///中心点的经纬度坐标
|
||||
@property (nonatomic, readonly) CLLocationCoordinate2D center; |
||||
|
||||
|
||||
///半径,单位:米
|
||||
@property (nonatomic, readonly) CLLocationDistance radius; |
||||
|
||||
/**
|
||||
* @brief 构造圆形围栏 |
||||
* @param customid 用户自定义ID |
||||
* @param identityid 识别id |
||||
* @param center 中心坐标 |
||||
* @param radius 围栏半径 |
||||
* @param type 坐标系类型 |
||||
* @return BMKGeoFenceCircleRegion id |
||||
*/ |
||||
- (id)initWithCustomID:(NSString *)customid identityID:(NSString *)identityid center:(CLLocationCoordinate2D)center radius:(CLLocationDistance)radius coor:(BMKLocationCoordinateType)type; |
||||
|
||||
|
||||
|
||||
@end |
||||
|
||||
|
||||
#pragma mark -BMKGeoFencePolygonRegion |
||||
|
||||
|
||||
///多边形地理围栏
|
||||
@interface BMKGeoFencePolygonRegion : BMKGeoFenceRegion |
||||
|
||||
|
||||
///经纬度坐标点数据
|
||||
@property (nonatomic, readonly) CLLocationCoordinate2D *coordinates; |
||||
|
||||
|
||||
///经纬度坐标点的个数
|
||||
@property (nonatomic, readonly) NSInteger count; |
||||
|
||||
|
||||
/**
|
||||
* @brief 构造多边形围栏 |
||||
* @param customid 用户自定义ID |
||||
* @param identityid 识别id |
||||
* @param coor 多边形顶点 |
||||
* @param count 顶点个数 |
||||
* @param type 坐标系类型 |
||||
* @return BMKGeoFencePolygonRegion id |
||||
*/ |
||||
- (id)initWithCustomID:(NSString *)customid identityID:(NSString *)identityid coor:(CLLocationCoordinate2D *)coor count:(NSInteger)count coor:(BMKLocationCoordinateType)type; |
||||
|
||||
@end |
||||
|
@ -1,97 +0,0 @@
|
||||
//
|
||||
// BMKLocation.h
|
||||
// LocationComponent
|
||||
//
|
||||
// Created by baidu on 2017/8/16.
|
||||
// Copyright © 2017年 baidu. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef BMKLocation_h |
||||
#define BMKLocation_h |
||||
|
||||
#import <CoreLocation/CoreLocation.h> |
||||
#import "BMKLocationReGeocode.h" |
||||
|
||||
/**
|
||||
* BMKLocationProvider 位置数据来源,分iOS系统定位和其他定位服务结果两种,目前仅支持iOS系统定位服务 |
||||
* |
||||
*/ |
||||
typedef NS_ENUM(int, BMKLocationProvider) { |
||||
|
||||
BMKLocationProviderIOS = 0, //!<位置来源于iOS本身定位
|
||||
BMKLocationProviderOther //!<位置来源于其他定位服务
|
||||
|
||||
}; |
||||
|
||||
///描述百度iOS 定位数据
|
||||
@interface BMKLocation : NSObject |
||||
|
||||
///BMKLocation 位置数据
|
||||
@property(nonatomic, copy, readonly) CLLocation * _Nullable location; |
||||
|
||||
///BMKLocation 地址数据
|
||||
@property(nonatomic, copy) BMKLocationReGeocode * _Nullable rgcData; |
||||
|
||||
///BMKLocation 位置来源
|
||||
@property(nonatomic, assign) BMKLocationProvider provider; |
||||
|
||||
///BMKLocation 位置ID
|
||||
@property(nonatomic, retain) NSString * _Nullable locationID; |
||||
|
||||
/*
|
||||
* floorString |
||||
* |
||||
* Discussion: |
||||
* 室内定位成功时返回的楼层信息,ex:f1 |
||||
*/ |
||||
@property(readonly, nonatomic, copy, nullable) NSString *floorString; |
||||
|
||||
/*
|
||||
* buildingID |
||||
* |
||||
* Discussion: |
||||
* 室内定位成功时返回的百度建筑物ID |
||||
*/ |
||||
@property(readonly, nonatomic, copy, nullable) NSString *buildingID; |
||||
|
||||
/*
|
||||
* buildingName |
||||
* |
||||
* Discussion: |
||||
* 室内定位成功时返回的百度建筑物名称 |
||||
*/ |
||||
@property(readonly, nonatomic, copy, nullable) NSString *buildingName; |
||||
|
||||
|
||||
/*
|
||||
* extraInfo |
||||
* |
||||
* Discussion: |
||||
* 定位附加信息,如停车位code识别结果、停车位code示例、vdr推算结果置信度等 |
||||
*/ |
||||
@property(readonly, nonatomic, copy, nullable) NSDictionary * extraInfo; |
||||
|
||||
/**
|
||||
* @brief 初始化BMKLocation实例 |
||||
* @param loc CLLocation对象 |
||||
* @param rgc BMKLocationReGeocode对象 |
||||
* @return BMKLocation id |
||||
*/ |
||||
- (id _Nonnull)initWithLocation:(CLLocation * _Nullable)loc withRgcData:(BMKLocationReGeocode * _Nullable)rgc; |
||||
|
||||
/**
|
||||
* @brief 构造BMKLocation |
||||
* @param location CLLocation |
||||
* @param floorString 楼层字符串 |
||||
* @param buildingID 建筑物ID |
||||
* @param buildingName 建筑物名称 |
||||
* @param info 位置附加信息 |
||||
* @return BMKLocation id |
||||
*/ |
||||
-(id _Nonnull)initWithLocation:(CLLocation * _Nullable)location floorString:(NSString * _Nullable)floorString buildingID:(NSString * _Nullable)buildingID |
||||
buildingName:(NSString * _Nullable)buildingName extraInfo:(NSDictionary * _Nullable)info withRgcData:(BMKLocationReGeocode * _Nullable)rgc; |
||||
|
||||
|
||||
@end |
||||
|
||||
#endif /* BMKLocation_h */ |
@ -1,56 +0,0 @@
|
||||
//
|
||||
// BMKLocationAuth.h
|
||||
// LocationComponent
|
||||
//
|
||||
// Created by baidu on 2017/4/10.
|
||||
// Copyright © 2017年 baidu. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef BMKLocationAuth_h |
||||
#define BMKLocationAuth_h |
||||
|
||||
///定位鉴权错误码
|
||||
typedef NS_ENUM(NSInteger, BMKLocationAuthErrorCode) { |
||||
BMKLocationAuthErrorUnknown = -1, ///< 未知错误
|
||||
BMKLocationAuthErrorSuccess = 0, ///< 鉴权成功
|
||||
BMKLocationAuthErrorNetworkFailed = 1, ///< 因网络鉴权失败
|
||||
BMKLocationAuthErrorFailed = 2, ///< KEY非法鉴权失败
|
||||
|
||||
}; |
||||
///通知Delegate
|
||||
@protocol BMKLocationAuthDelegate <NSObject> |
||||
@optional |
||||
|
||||
/**
|
||||
*@brief 返回授权验证错误 |
||||
*@param iError 错误号 : 为0时验证通过,具体参加BMKLocationAuthErrorCode |
||||
*/ |
||||
- (void)onCheckPermissionState:(BMKLocationAuthErrorCode)iError; |
||||
@end |
||||
|
||||
|
||||
///BMKLocationAuth类。用于鉴权
|
||||
@interface BMKLocationAuth : NSObject |
||||
|
||||
///鉴权状态0:成功; 1:网络错误; 2:授权失败
|
||||
@property(nonatomic, readonly, assign) BMKLocationAuthErrorCode permisionState; |
||||
|
||||
/**
|
||||
* @brief 得到BMKLocationAuth的单例 |
||||
*/ |
||||
+ (BMKLocationAuth*)sharedInstance; |
||||
|
||||
|
||||
/**
|
||||
*@brief 启动引擎 |
||||
*@param key 申请的有效key |
||||
*@param delegate 回调是否鉴权成功 |
||||
*/ |
||||
-(void)checkPermisionWithKey:(NSString*)key authDelegate:(id<BMKLocationAuthDelegate>)delegate; |
||||
|
||||
|
||||
@end |
||||
|
||||
|
||||
|
||||
#endif /* BMKLocationAuth_h */ |
@ -1,16 +0,0 @@
|
||||
//
|
||||
// BMKLocationComponent.h
|
||||
// LocationComponent
|
||||
//
|
||||
// Created by Baidu on 3/31/14.
|
||||
// Copyright (c) 2014 baidu. All rights reserved.
|
||||
//
|
||||
|
||||
#import "BMKLocationManager.h" |
||||
#import "BMKLocationKitVersion.h" |
||||
#import "BMKLocationPoi.h" |
||||
#import "BMKLocation.h" |
||||
#import "BMKGeoFenceRegion.h" |
||||
#import "BMKGeoFenceManager.h" |
||||
#import "BMKLocationReGeocode.h" |
||||
#import "BMKLocationAuth.h" |
@ -1,30 +0,0 @@
|
||||
//
|
||||
// BMKLocationKitVersion.h
|
||||
// BMKLocationKit
|
||||
//
|
||||
// Created by baidu on 17/9/9.
|
||||
// Copyright © 2017年 baidu. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef BMKLocationKitVersion_h |
||||
#define BMKLocationKitVersion_h |
||||
|
||||
#import <UIKit/UIKit.h> |
||||
|
||||
/**
|
||||
*获取当前定位sdk 的版本号 |
||||
*当前定位sdk版本 : 2.0.0 |
||||
*@return 返回当前定位sdk 的版本号 |
||||
*/ |
||||
UIKIT_EXTERN NSString* BMKLocationKitVersion(); |
||||
|
||||
/**
|
||||
*获取当前定位sdk 的float版本号 |
||||
*当前定位sdk版本 : 2.0 |
||||
*@return 返回当前定位sdk 的float版本号 |
||||
*/ |
||||
UIKIT_EXTERN float BMKLocationKitFloatVersion(); |
||||
|
||||
|
||||
|
||||
#endif /* BMKLocationKitVersion_h */ |
@ -1,296 +0,0 @@
|
||||
//
|
||||
// BMKLocationManager.h
|
||||
// BMKLocationKit
|
||||
//
|
||||
// Created by baidu on 2017/3/2.
|
||||
// Copyright © 2017年 baidu. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Availability.h> |
||||
#import <Foundation/Foundation.h> |
||||
#import <CoreLocation/CoreLocation.h> |
||||
#import "BMKLocationReGeocode.h" |
||||
#import "BMKLocation.h" |
||||
|
||||
/** BMKLocationCoordinateType 枚举坐标系类型
|
||||
* |
||||
*/ |
||||
typedef NS_ENUM(NSUInteger, BMKLocationCoordinateType) |
||||
{ |
||||
BMKLocationCoordinateTypeBMK09LL = 0, ///<BMK09LL
|
||||
BMKLocationCoordinateTypeBMK09MC, ///<BMK09MC
|
||||
BMKLocationCoordinateTypeWGS84, ///<WGS84
|
||||
BMKLocationCoordinateTypeGCJ02 ///<GCJ02
|
||||
}; |
||||
|
||||
/** BMKLocationNetworkState 枚举识别网络状态类型
|
||||
* |
||||
*/ |
||||
typedef NS_ENUM(int, BMKLocationNetworkState) { |
||||
BMKLocationNetworkStateUnknown = 0, ///<网络状态未知
|
||||
BMKLocationNetworkStateWifi, ///<网络状态wifi
|
||||
BMKLocationNetworkStateWifiHotSpot, ///<网络状态连接WIFI移动热点
|
||||
BMKLocationNetworkStateMobile2G, ///<网络状态移动2G
|
||||
BMKLocationNetworkStateMobile3G, ///<网络状态移动3G
|
||||
BMKLocationNetworkStateMobile4G ///<网络状态移动4G
|
||||
|
||||
}; |
||||
|
||||
|
||||
///BMKLocation errorDomain
|
||||
|
||||
FOUNDATION_EXPORT NSErrorDomain const _Nonnull BMKLocationErrorDomain; |
||||
|
||||
///BMKLocation errorCode
|
||||
typedef NS_ENUM(NSInteger, BMKLocationErrorCode) |
||||
{ |
||||
BMKLocationErrorUnKnown = 0, ///<未知异常
|
||||
BMKLocationErrorLocFailed = 1, ///<位置未知,持续定位中
|
||||
BMKLocationErrorDenied = 2, ///<手机不允许定位,请确认用户授予定位权限或者手机是否打开定位开关
|
||||
BMKLocationErrorNetWork = 3, ///<因为网络原因导致系统定位失败
|
||||
BMKLocationErrorHeadingFailed = 4, ///<获取手机方向信息失败
|
||||
BMKLocationErrorGetExtraNetworkFailed = 5, ///<网络原因导致获取额外信息(地址、网络状态等信息)失败
|
||||
BMKLocationErrorGetExtraParseFailed = 6, ///<网络返回数据解析失败导致获取额外信息(地址、网络状态等信息)失败
|
||||
BMKLocationErrorFailureAuth = 7, ///<鉴权失败导致无法返回定位、地址等信息
|
||||
}; |
||||
|
||||
/** BMKLAccuracyAuthorization 枚举返回定位精度等级
|
||||
* |
||||
*/ |
||||
typedef NS_ENUM(NSInteger, BMKLAccuracyAuthorization) { |
||||
|
||||
BMKLAccuracyAuthorizationFullAccuracy, ///<全量定位精度等级,该等级下定位返回结果会尽可能精准
|
||||
BMKLAccuracyAuthorizationReducedAccuracy, ///<降级定位精度等级,该等级下定位会返回大概5km精度范围的点,定位频率、实时性上也会变慢,比如可能是20分钟之前的点,适用于那些只要求城市级别精度的app使用;ios14之后,该等级受用户控制,需要高等级权限的app需要对应做好适配工作
|
||||
}; |
||||
|
||||
|
||||
/**
|
||||
* @brief 单次定位返回Block |
||||
* @param location 定位信息,数据包括CLLocation 位置数据,BMKLocationReGeocode 地址信息,参考BMKLocation。 |
||||
* @param state 移动热点状态 |
||||
* @param error 错误信息,参考 BMKLocationErrorCode |
||||
*/ |
||||
typedef void (^BMKLocatingCompletionBlock)(BMKLocation * _Nullable location, BMKLocationNetworkState state , NSError * _Nullable error); |
||||
|
||||
|
||||
|
||||
@protocol BMKLocationManagerDelegate; |
||||
|
||||
#pragma mark - BMKLocationManager |
||||
|
||||
|
||||
///BMKLocationManager类。初始化之前请设置 BMKLocationAuth 中的APIKey,否则将无法正常使用服务.
|
||||
@interface BMKLocationManager : NSObject |
||||
|
||||
///实现了 BMKLocationManagerDelegate 协议的类指针。
|
||||
@property (nonatomic, weak, nullable) id<BMKLocationManagerDelegate> delegate; |
||||
|
||||
///设定定位的最小更新距离。默认为 kCLDistanceFilterNone。
|
||||
@property(nonatomic, assign) CLLocationDistance distanceFilter; |
||||
|
||||
///设定定位精度。默认为 kCLLocationAccuracyBest。
|
||||
@property(nonatomic, assign) CLLocationAccuracy desiredAccuracy; |
||||
|
||||
///设定定位类型。默认为 CLActivityTypeAutomotiveNavigation。
|
||||
@property(nonatomic, assign) CLActivityType activityType; |
||||
|
||||
///设定定位坐标系类型。默认为 BMKLocationCoordinateTypeGCJ02。
|
||||
@property(nonatomic, assign) BMKLocationCoordinateType coordinateType; |
||||
|
||||
///指定定位是否会被系统自动暂停。默认为NO。
|
||||
@property(nonatomic, assign) BOOL pausesLocationUpdatesAutomatically; |
||||
|
||||
|
||||
///是否允许后台定位。默认为NO。只在iOS 9.0及之后起作用。设置为YES的时候必须保证 Background Modes 中的 Location updates 处于选中状态,否则会抛出异常。由于iOS系统限制,需要在定位未开始之前或定位停止之后,修改该属性的值才会有效果。
|
||||
@property(nonatomic, assign) BOOL allowsBackgroundLocationUpdates; |
||||
|
||||
///指定单次定位超时时间,默认为10s。最小值是2s。注意单次定位请求前设置。注意: 单次定位超时时间从确定了定位权限(非kCLAuthorizationStatusNotDetermined状态)后开始计算。
|
||||
@property(nonatomic, assign) NSInteger locationTimeout; |
||||
|
||||
///指定单次定位逆地理超时时间,默认为10s。最小值是2s。注意单次定位请求前设置。
|
||||
@property(nonatomic, assign) NSInteger reGeocodeTimeout; |
||||
|
||||
///连续定位是否返回逆地理信息,默认YES。
|
||||
@property (nonatomic, assign) BOOL locatingWithReGeocode; |
||||
|
||||
///定位sdk-v1.3之后,开发者可以选择是否需要最新版本rgc数据,1.9之后默认是需要YES;YES的情况下,定位sdk会实时返回最新的rgc数据,如城市变更等数据都会实时更新
|
||||
@property (nonatomic, assign) BOOL isNeedNewVersionReGeocode; |
||||
|
||||
|
||||
///开发者可以指定该用户的id,用于后续统一识别用户,便于查找问题
|
||||
@property(nonatomic, copy, nullable) NSString * userID; |
||||
|
||||
///返回定位精度等级,IOS14之后用户可以直接控制返回定位的精度等级,开发者可以通过这个值适配不同定位等级下的产品逻辑
|
||||
@property (nonatomic, readonly) BMKLAccuracyAuthorization accuracyAuthorization; |
||||
|
||||
|
||||
/**
|
||||
* @brief 单次定位。如果当前正在连续定位,调用此方法将会失败,返回NO。\n该方法将会根据设定的 desiredAccuracy 去获取定位信息。如果获取的定位信息精确度低于 desiredAccuracy ,将会持续的等待定位信息,直到超时后通过completionBlock返回精度最高的定位信息。\n可以通过 stopUpdatingLocation 方法去取消正在进行的单次定位请求。 |
||||
* @param withReGeocode 是否带有逆地理信息(获取逆地理信息需要联网) |
||||
* @param withNetWorkState 是否带有移动热点识别状态(需要联网) |
||||
* @param completionBlock 单次定位完成后的Block |
||||
* @return 是否成功添加单次定位Request |
||||
*/ |
||||
- (BOOL)requestLocationWithReGeocode:(BOOL)withReGeocode withNetworkState:(BOOL)withNetWorkState completionBlock:(BMKLocatingCompletionBlock _Nonnull)completionBlock; |
||||
|
||||
/**
|
||||
* @brief 开始连续定位。调用此方法会cancel掉所有的单次定位请求。 |
||||
*/ |
||||
- (void)startUpdatingLocation; |
||||
|
||||
/**
|
||||
* @brief 停止连续定位。调用此方法会cancel掉所有的单次定位请求,可以用来取消单次定位。 |
||||
*/ |
||||
- (void)stopUpdatingLocation; |
||||
|
||||
/**
|
||||
* @brief 请求网络状态结果回调。 |
||||
*/ |
||||
- (void)requestNetworkState; |
||||
|
||||
|
||||
/**
|
||||
* @brief 该方法返回设备是否支持设备朝向事件回调。 |
||||
* @return 是否支持设备朝向事件回调 |
||||
*/ |
||||
+ (BOOL)headingAvailable; |
||||
|
||||
/**
|
||||
* @brief 该方法为BMKLocationManager开始设备朝向事件回调。 |
||||
*/ |
||||
- (void)startUpdatingHeading; |
||||
|
||||
/**
|
||||
* @brief 该方法为BMKLocationManager停止设备朝向事件回调。 |
||||
*/ |
||||
- (void)stopUpdatingHeading; |
||||
|
||||
/**
|
||||
* @brief 该方法为BMKLocationManager尝试使用高精度室内定位。在特定的室内场景下会有更高精度的定位回调,只在室内定位版本生效。 |
||||
*/ |
||||
- (void)tryIndoorLocation; |
||||
|
||||
/**
|
||||
* @brief 该方法为BMKLocationManager会关闭高精度室内定位,只在室内定位版本生效。 |
||||
*/ |
||||
- (void)stopIndoorLocation; |
||||
|
||||
|
||||
/**
|
||||
* @brief 转换为百度经纬度的坐标 |
||||
* @param coordinate 待转换的经纬度 |
||||
* @param srctype 待转换坐标系类型 |
||||
* @param destype 目标百度坐标系类型(bd09ll,bd09mc) |
||||
* @return 目标百度坐标系经纬度 |
||||
*/ |
||||
+ (CLLocationCoordinate2D) BMKLocationCoordinateConvert:(CLLocationCoordinate2D) coordinate SrcType:(BMKLocationCoordinateType)srctype DesType:(BMKLocationCoordinateType)destype; |
||||
|
||||
/**
|
||||
* @brief 判断目标经纬度是否在大陆以及港、澳地区。 |
||||
* @param coordinate 待判断的目标经纬度 |
||||
* @param coortype 待判断经纬度的坐标系类型 |
||||
* @return 是否在大陆以及港、澳地区 |
||||
*/ |
||||
+ (BOOL) BMKLocationDataAvailableForCoordinate:(CLLocationCoordinate2D)coordinate withCoorType:(BMKLocationCoordinateType)coortype; |
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief 返回当前定位权限 |
||||
* @return CLAuthorizationStatus 定位权限枚举类型 |
||||
*/ |
||||
- (CLAuthorizationStatus)authorizationStatus; |
||||
|
||||
|
||||
/**
|
||||
* @brief 如果你没有全量定位等级精度权限,利用该接口可以临时请求一次全量定位精度等级,系统会抛出弹框让用户确认是否授权app授予相应权限 |
||||
* @param purposeKey info.plist中NSLocationTemporaryUsageDescriptionDictionary定义的key,对应相应的value可以详细描述申请全量定位精度等级的原因 |
||||
* @param completion 回调是否 |
||||
* @return |
||||
*/ |
||||
- (void)requestTemporaryFullAccuracyAuthorizationWithPurposeKey:(NSString * _Nonnull)purposeKey completion:(void(^ _Nullable)(NSError * _Nullable))completion API_AVAILABLE(ios(14.0)); |
||||
|
||||
/**
|
||||
* @brief 请求一次全量定位精度等级 |
||||
* @param purposeKey info.plist中NSLocationTemporaryUsageDescriptionDictionary定义的key |
||||
* @return |
||||
*/ |
||||
- (void)requestTemporaryFullAccuracyAuthorizationWithPurposeKey:(NSString * _Nonnull)purposeKey API_AVAILABLE(ios(14.0)); |
||||
|
||||
|
||||
@end |
||||
|
||||
#pragma mark - BMKLocationManagerDelegate |
||||
|
||||
|
||||
///BMKLocationManagerDelegate 协议定义了发生错误时的错误回调方法,连续定位的回调方法等。
|
||||
@protocol BMKLocationManagerDelegate <NSObject> |
||||
|
||||
@optional |
||||
|
||||
/**
|
||||
* @brief 为了适配app store关于新的后台定位的审核机制(app store要求如果开发者只配置了使用期间定位,则代码中不能出现申请后台定位的逻辑),当开发者在plist配置NSLocationAlwaysUsageDescription或者NSLocationAlwaysAndWhenInUseUsageDescription时,需要在该delegate中调用后台定位api:[locationManager requestAlwaysAuthorization]。开发者如果只配置了NSLocationWhenInUseUsageDescription,且只有使用期间的定位需求,则无需在delegate中实现逻辑。 |
||||
* @param manager 定位 BMKLocationManager 类。 |
||||
* @param locationManager 系统 CLLocationManager 类 。 |
||||
* @since 1.6.0 |
||||
*/ |
||||
- (void)BMKLocationManager:(BMKLocationManager * _Nonnull)manager doRequestAlwaysAuthorization:(CLLocationManager * _Nonnull)locationManager; |
||||
|
||||
/**
|
||||
* @brief 当定位发生错误时,会调用代理的此方法。 |
||||
* @param manager 定位 BMKLocationManager 类。 |
||||
* @param error 返回的错误,参考 CLError 。 |
||||
*/ |
||||
- (void)BMKLocationManager:(BMKLocationManager * _Nonnull)manager didFailWithError:(NSError * _Nullable)error; |
||||
|
||||
|
||||
/**
|
||||
* @brief 连续定位回调函数。 |
||||
* @param manager 定位 BMKLocationManager 类。 |
||||
* @param location 定位结果,参考BMKLocation。 |
||||
* @param error 错误信息。 |
||||
*/ |
||||
- (void)BMKLocationManager:(BMKLocationManager * _Nonnull)manager didUpdateLocation:(BMKLocation * _Nullable)location orError:(NSError * _Nullable)error; |
||||
|
||||
/**
|
||||
* @brief 定位权限状态改变时回调函数 |
||||
* @param manager 定位 BMKLocationManager 类。 |
||||
* @param status 定位权限状态。 |
||||
*/ |
||||
- (void)BMKLocationManager:(BMKLocationManager * _Nonnull)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status API_DEPRECATED_WITH_REPLACEMENT("-BMKLocationManagerDidChangeAuthorization", ios(4.2, 14.0)); |
||||
|
||||
|
||||
/**
|
||||
* @brief authorizationStatus或者accuracyAuthorization有变化时回调函数 |
||||
* @param manager 定位 BMKLocationManager 类。 |
||||
*/ |
||||
- (void)BMKLocationManagerDidChangeAuthorization:(BMKLocationManager * _Nonnull)manager; |
||||
|
||||
|
||||
/**
|
||||
* @brief 该方法为BMKLocationManager提示需要设备校正回调方法。 |
||||
* @param manager 提供该定位结果的BMKLocationManager类的实例。 |
||||
*/ |
||||
- (BOOL)BMKLocationManagerShouldDisplayHeadingCalibration:(BMKLocationManager * _Nonnull)manager; |
||||
|
||||
/**
|
||||
* @brief 该方法为BMKLocationManager提供设备朝向的回调方法。 |
||||
* @param manager 提供该定位结果的BMKLocationManager类的实例 |
||||
* @param heading 设备的朝向结果 |
||||
*/ |
||||
- (void)BMKLocationManager:(BMKLocationManager * _Nonnull)manager |
||||
didUpdateHeading:(CLHeading * _Nullable)heading; |
||||
|
||||
/**
|
||||
* @brief 该方法为BMKLocationManager所在App系统网络状态改变的回调事件。 |
||||
* @param manager 提供该定位结果的BMKLocationManager类的实例 |
||||
* @param state 当前网络状态 |
||||
* @param error 错误信息 |
||||
*/ |
||||
- (void)BMKLocationManager:(BMKLocationManager * _Nonnull)manager |
||||
didUpdateNetworkState:(BMKLocationNetworkState)state orError:(NSError * _Nullable)error; |
||||
|
||||
|
||||
@end |
||||
|
||||
|
@ -1,42 +0,0 @@
|
||||
//
|
||||
// BMKLocationPoi.h
|
||||
// BMKLocationKit
|
||||
//
|
||||
// Created by baidu on 2017/3/2.
|
||||
// Copyright © 2017年 baidu. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
///描述Poi各属性
|
||||
@interface BMKLocationPoi : NSObject |
||||
|
||||
///BMKLocationPoi的id属性
|
||||
@property(nonatomic, copy, readonly) NSString *uid; |
||||
|
||||
///BMKLocationPoi的名字属性
|
||||
@property(nonatomic, copy, readonly) NSString *name; |
||||
|
||||
///BMKLocationPoi的标签属性
|
||||
@property(nonatomic, copy, readonly) NSString *tags; |
||||
|
||||
///BMKLocationPoi的地址属性
|
||||
@property(nonatomic, copy, readonly) NSString *addr; |
||||
|
||||
///BMKLocationPoi的可信度
|
||||
@property(nonatomic, assign, readonly) float relaiability; |
||||
|
||||
|
||||
/**
|
||||
* @brief 通过NSDictionary初始化方法一 |
||||
*/ |
||||
- (id)initWithDictionary:(NSDictionary *)dictionary; |
||||
|
||||
|
||||
/**
|
||||
* @brief 通过NSDictionary初始化方法二 |
||||
*/ |
||||
- (id)initWithTwoDictionary:(NSDictionary *)dictionary; |
||||
|
||||
@end |
||||
|
||||
|
@ -1,35 +0,0 @@
|
||||
//
|
||||
// BMKLocationPoiRegion.h
|
||||
// LocationComponent
|
||||
//
|
||||
// Created by Jiang,Fangsheng on 2019/9/4.
|
||||
// Copyright © 2019 baidu. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef BMKLocationPoiRegion_h |
||||
#define BMKLocationPoiRegion_h |
||||
|
||||
|
||||
///描述PoiRegion各属性
|
||||
@interface BMKLocationPoiRegion : NSObject |
||||
|
||||
///BMKLocationPoiRegion的方向属性,如『内』、『外』
|
||||
@property(nonatomic, copy, readonly) NSString *directionDesc; |
||||
|
||||
///BMKLocationPoiRegion的名字属性
|
||||
@property(nonatomic, copy, readonly) NSString *name; |
||||
|
||||
///BMKLocationPoiRegion的标签属性
|
||||
@property(nonatomic, copy, readonly) NSString *tags; |
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief 通过NSDictionary初始化方法一 |
||||
*/ |
||||
- (id)initWithDictionary:(NSDictionary *)dictionary; |
||||
|
||||
|
||||
@end |
||||
|
||||
#endif /* BMKLocationPoiRegion_h */ |
@ -1,67 +0,0 @@
|
||||
//
|
||||
// BMKLocationReGeocode.h
|
||||
// BMKLocationKit
|
||||
//
|
||||
// Created by baidu on 2017/3/2.
|
||||
// Copyright © 2017年 baidu. All rights reserved.
|
||||
//
|
||||
#import <Foundation/Foundation.h> |
||||
#import "BMKLocationPoi.h" |
||||
#import "BMKLocationPoiRegion.h" |
||||
|
||||
///BMKLocationReGeocode类。描述跟地址有关的信息.
|
||||
@interface BMKLocationReGeocode : NSObject |
||||
|
||||
///国家名字属性
|
||||
@property(nonatomic, copy, readonly) NSString *country; |
||||
|
||||
///国家编码属性
|
||||
@property(nonatomic, copy, readonly) NSString *countryCode; |
||||
|
||||
///省份名字属性
|
||||
@property(nonatomic, copy, readonly) NSString *province; |
||||
|
||||
///城市名字属性
|
||||
@property(nonatomic, copy, readonly) NSString *city; |
||||
|
||||
///区名字属性
|
||||
@property(nonatomic, copy, readonly) NSString *district; |
||||
|
||||
///乡镇名字属性
|
||||
@property(nonatomic, copy, readonly) NSString *town; |
||||
|
||||
///街道名字属性
|
||||
@property(nonatomic, copy, readonly) NSString *street; |
||||
|
||||
///街道号码属性
|
||||
@property(nonatomic, copy, readonly) NSString *streetNumber; |
||||
|
||||
///城市编码属性
|
||||
@property(nonatomic, copy, readonly) NSString *cityCode; |
||||
|
||||
///行政区划编码属性
|
||||
@property(nonatomic, copy, readonly) NSString *adCode; |
||||
|
||||
|
||||
///位置语义化结果的定位点在什么地方周围的描述信息
|
||||
@property(nonatomic, copy, readonly) NSString *locationDescribe; |
||||
|
||||
|
||||
///位置语义化结果的属性,该定位点周围的poi列表信息
|
||||
@property(nonatomic, retain, readonly) NSArray<BMKLocationPoi *> *poiList; |
||||
|
||||
///位置语义化结果的定位点在什么地方周围的描述信息
|
||||
@property(nonatomic, strong, readonly) BMKLocationPoiRegion *poiRegion; |
||||
|
||||
/**
|
||||
* @brief 通过NSData初始化方法 |
||||
*/ |
||||
- (id)initWithReGeocodeString:(NSData *)reGeocodeString; |
||||
|
||||
|
||||
/**
|
||||
* @brief 通过JSON初始化方法 |
||||
*/ |
||||
- (id)initWithJsonString:(NSData *)jsonString withHighAccuracy:(BOOL)highAcc; |
||||
|
||||
@end |
@ -1,9 +0,0 @@
|
||||
#import <Flutter/Flutter.h> |
||||
#import <UIKit/UIKit.h> |
||||
#import "AppDelegate.h" |
||||
|
||||
int main(int argc, char* argv[]) { |
||||
@autoreleasepool { |
||||
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); |
||||
} |
||||
} |
@ -1,12 +0,0 @@
|
||||
// |
||||
// test.swift |
||||
// Runner |
||||
// |
||||
// Created by f on 2021/8/6. |
||||
// |
||||
|
||||
import UIKit |
||||
|
||||
class test: NSObject { |
||||
|
||||
} |
@ -0,0 +1,12 @@
|
||||
import Flutter |
||||
import UIKit |
||||
import XCTest |
||||
|
||||
class RunnerTests: XCTestCase { |
||||
|
||||
func testExample() { |
||||
// If you add code to the Runner application, consider adding tests here. |
||||
// See https://developer.apple.com/documentation/xctest for more information about using XCTest. |
||||
} |
||||
|
||||
} |
@ -1,15 +0,0 @@
|
||||
/* |
||||
InfoPlist.strings |
||||
Runner |
||||
|
||||
Created by 冯美坎 on 2021/7/19. |
||||
|
||||
*/ |
||||
|
||||
CFBundleName="huixiang"; |
||||
CFBundleDisplayName="huixiang"; |
||||
NSCameraUsageDescription="您的相机权限将用于更新头像使用"; |
||||
NSPhotoLibraryUsageDescription="您的照片信息将用于更新头像使用"; |
||||
NSLocationWhenInUseUsageDescription="您的定位位置信息将用于查看周围的门店"; |
||||
NSLocationAlwaysAndWhenInUseUsageDescription="您的定位位置信息将用于查看周围的门店"; |
||||
NSLocationTemporaryUsageDescriptionDictionary="您的定位位置信息将用于查看周围的门店"; |
@ -1,16 +0,0 @@
|
||||
/* |
||||
InfoPlist.strings |
||||
Runner |
||||
|
||||
Created by 冯美坎 on 2021/7/19. |
||||
|
||||
*/ |
||||
|
||||
|
||||
CFBundleName="海峡姐妹"; |
||||
CFBundleDisplayName="海峡姐妹"; |
||||
NSCameraUsageDescription="您的相机权限将用于更新头像使用"; |
||||
NSPhotoLibraryUsageDescription="您的照片信息将用于更新头像使用"; |
||||
NSLocationWhenInUseUsageDescription="您的定位位置信息将用于查看周围的门店"; |
||||
NSLocationAlwaysAndWhenInUseUsageDescription="您的定位位置信息将用于查看周围的门店"; |
||||
NSLocationTemporaryUsageDescriptionDictionary="您的定位位置信息将用于查看周围的门店"; |
@ -1,15 +0,0 @@
|
||||
/* |
||||
InfoPlist.strings |
||||
Runner |
||||
|
||||
Created by 冯美坎 on 2021/7/19. |
||||
|
||||
*/ |
||||
|
||||
CFBundleName="迴響"; |
||||
CFBundleDisplayName="迴響"; |
||||
NSCameraUsageDescription="您的相機權限將用於投降更新使用"; |
||||
NSPhotoLibraryUsageDescription="您的照片信息將用於投降更新使用"; |
||||
NSLocationWhenInUseUsageDescription="您的定位位置信息將用於查看周圍的門店"; |
||||
NSLocationAlwaysAndWhenInUseUsageDescription="您的定位位置信息將用於查看周圍的門店"; |
||||
NSLocationTemporaryUsageDescriptionDictionary="您的定位位置信息將用於查看周圍的門店"; |
@ -1,250 +0,0 @@
|
||||
import 'dart:io'; |
||||
|
||||
import 'package:flutter/cupertino.dart'; |
||||
import 'package:flutter/material.dart'; |
||||
import 'package:huixiang/business_system/goods/business_goods_page.dart'; |
||||
import 'package:huixiang/business_system/mine/business_mine_page.dart'; |
||||
import 'package:huixiang/business_system/order/business_order_page.dart'; |
||||
import 'package:huixiang/utils/font_weight.dart'; |
||||
import 'package:flutter_screenutil/flutter_screenutil.dart'; |
||||
|
||||
import '../retrofit/data/business_login_info.dart'; |
||||
import 'home/business_home_page.dart'; |
||||
import 'home/home_view/home_sideslip_dialog.dart'; |
||||
|
||||
class BusinessPage extends StatefulWidget { |
||||
final arguments; |
||||
|
||||
BusinessPage({this.arguments}); |
||||
|
||||
@override |
||||
State<StatefulWidget> createState() { |
||||
return _BusinessPage(); |
||||
} |
||||
} |
||||
|
||||
class _BusinessPage extends State<BusinessPage> |
||||
with AutomaticKeepAliveClientMixin { |
||||
int choiceIndex = 0; |
||||
BusinessLoginInfo businessLoginInfo; |
||||
int selectStoreIndex = 0; |
||||
int switchStore = 0; |
||||
GlobalKey homePageKey = GlobalKey(); |
||||
GlobalKey orderPageKey = GlobalKey(); |
||||
GlobalKey goodsPageKey = GlobalKey(); |
||||
GlobalKey minePageKey = GlobalKey(); |
||||
var clickIndex = 0; |
||||
final PageController pageController = PageController(); |
||||
|
||||
@override |
||||
void initState() { |
||||
super.initState(); |
||||
businessLoginInfo = widget?.arguments["businessLoginInfo"]; |
||||
selectStoreIndex = widget.arguments["selectStoreIndex"] ?? 0; |
||||
} |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
super.build(context); |
||||
return Scaffold( |
||||
resizeToAvoidBottomInset: false, |
||||
body: Stack( |
||||
alignment: Alignment.bottomRight, |
||||
children: [ |
||||
Container( |
||||
child: PageView( |
||||
controller: pageController, |
||||
children: [ |
||||
BusinessHomePage( |
||||
homePageKey, businessLoginInfo, selectStoreIndex, showAlertDialog, |
||||
(index) { |
||||
setState(() { |
||||
pageController.jumpToPage(2); |
||||
}); |
||||
}), |
||||
BusinessOrderPage(orderPageKey, |
||||
businessLoginInfo?.storeList[selectStoreIndex]?.id ?? "0"), |
||||
BusinessGoodsPage(goodsPageKey, |
||||
businessLoginInfo?.storeList[selectStoreIndex]?.id ?? "0"), |
||||
BusinessMinePage(minePageKey, businessLoginInfo, |
||||
businessLoginInfo?.storeList[selectStoreIndex]?.id ?? "0"), |
||||
], |
||||
physics: NeverScrollableScrollPhysics(), |
||||
onPageChanged: (index) { |
||||
clickIndex = index; |
||||
setState(() {}); |
||||
}, |
||||
), |
||||
), |
||||
if (switchStore == 0) |
||||
GestureDetector( |
||||
onTap: () { |
||||
setState(() { |
||||
switchStore = 1; |
||||
showAlertDialog(); |
||||
}); |
||||
}, |
||||
child: Container( |
||||
width: 97.w, |
||||
decoration: BoxDecoration( |
||||
color: Color(0xFFEBEFF6), |
||||
borderRadius: BorderRadius.only( |
||||
topLeft: Radius.circular(111), |
||||
bottomLeft: Radius.circular(111), |
||||
), |
||||
), |
||||
padding: EdgeInsets.only(left: 12.w, top: 10.h, bottom: 10.h), |
||||
margin: EdgeInsets.only(bottom: 170.h), |
||||
child: Row( |
||||
children: [ |
||||
Padding( |
||||
padding: EdgeInsets.only(right: 4.w), |
||||
child: Image.asset( |
||||
"assets/image/bs_switch.webp", |
||||
width: 12.w, |
||||
height: 15.h, |
||||
)), |
||||
Text( |
||||
"切换门店", |
||||
textAlign: TextAlign.center, |
||||
style: TextStyle( |
||||
color: Color(0xFF30415B), |
||||
fontSize: 12.sp, |
||||
fontWeight: MyFontWeight.semi_bold, |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
extendBody: true, |
||||
bottomNavigationBar: Container( |
||||
alignment: Platform.isAndroid ? Alignment.center : Alignment.topCenter, |
||||
decoration: BoxDecoration( |
||||
color: Colors.white, |
||||
boxShadow: [ |
||||
BoxShadow( |
||||
color: Colors.black.withAlpha(12), |
||||
offset: Offset(0, 2), |
||||
blurRadius: 4, |
||||
spreadRadius: 0, |
||||
) |
||||
], |
||||
borderRadius: BorderRadius.vertical( |
||||
top: Radius.circular(4), |
||||
), |
||||
), |
||||
height: 82.h, |
||||
child: Row( |
||||
mainAxisAlignment: MainAxisAlignment.spaceAround, |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
bottomNavigationItem("首页", 0, "assets/image/business_home.webp", |
||||
"assets/image/business_ home_h.webp"), |
||||
bottomNavigationItem("订单", 1, "assets/image/business_order.webp", |
||||
"assets/image/business_order_h.webp"), |
||||
// bottomNavigationItem("", 2,"assets/image/business_scan_code.webp","assets/image/business_scan_code.webp"), |
||||
GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
Navigator.of(context) |
||||
.pushNamed('/router/scan_code_page', arguments: { |
||||
"storeId": |
||||
businessLoginInfo?.storeList[selectStoreIndex]?.id ?? "0" |
||||
}); |
||||
}, |
||||
child: Container( |
||||
padding: EdgeInsets.only(top: 10.h), |
||||
child: Image.asset( |
||||
"assets/image/business_scan_code.webp", |
||||
width: 52.h, |
||||
height: 52.h, |
||||
), |
||||
), |
||||
), |
||||
bottomNavigationItem("商品", 2, "assets/image/business_goods.webp", |
||||
"assets/image/business_goods_h.webp"), |
||||
bottomNavigationItem("我的", 3, "assets/image/business_mine.webp", |
||||
"assets/image/business_mine_h.webp"), |
||||
], |
||||
), |
||||
), |
||||
); |
||||
} |
||||
|
||||
Widget bottomNavigationItem(text, index, image, unImage) { |
||||
var isSelected = index == clickIndex; |
||||
return Expanded( |
||||
child: InkWell( |
||||
onTap: () { |
||||
setState(() { |
||||
clickIndex = index; |
||||
pageController.jumpToPage(clickIndex); |
||||
}); |
||||
}, |
||||
child: Container( |
||||
width: 45.w, |
||||
child: Column( |
||||
mainAxisAlignment: Platform.isAndroid |
||||
? MainAxisAlignment.center |
||||
: MainAxisAlignment.start, |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
children: [ |
||||
if (Platform.isIOS) |
||||
SizedBox( |
||||
height: 4.h, |
||||
), |
||||
Image.asset( |
||||
isSelected ? image : unImage, |
||||
width: 30.h, |
||||
height: 30.h, |
||||
), |
||||
Text( |
||||
text, |
||||
style: TextStyle( |
||||
fontSize: 10.sp, |
||||
fontWeight: MyFontWeight.semi_bold, |
||||
color: isSelected ? Color(0xFF4C4C4C) : Color(0xFFACACAC), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
), |
||||
flex: 1, |
||||
); |
||||
} |
||||
|
||||
///侧面弹窗 |
||||
showAlertDialog() async { |
||||
try { |
||||
int index = await showCupertinoModalPopup( |
||||
builder: (context) { |
||||
return HomeSideslipDialog(selectStoreIndex, businessLoginInfo); |
||||
}, |
||||
context: context); |
||||
if (index != null) { |
||||
if (index == -1) { |
||||
Navigator.of(context).pop(); |
||||
return; |
||||
} |
||||
setState(() { |
||||
selectStoreIndex = index; |
||||
homePageKey = GlobalKey(); |
||||
orderPageKey = GlobalKey(); |
||||
goodsPageKey = GlobalKey(); |
||||
minePageKey = GlobalKey(); |
||||
}); |
||||
} |
||||
} finally { |
||||
setState(() { |
||||
switchStore = 0; |
||||
}); |
||||
} |
||||
} |
||||
|
||||
@override |
||||
bool get wantKeepAlive => true; |
||||
} |
@ -1,90 +0,0 @@
|
||||
import 'package:flutter/cupertino.dart'; |
||||
import 'package:flutter/material.dart'; |
||||
import 'package:intl/intl.dart'; |
||||
import 'package:syncfusion_flutter_datepicker/datepicker.dart'; |
||||
|
||||
import '../../view_widget/my_appbar.dart'; |
||||
|
||||
class CustomPage extends StatefulWidget { |
||||
final Map<String, dynamic> arguments; |
||||
|
||||
CustomPage({this.arguments}); |
||||
|
||||
@override |
||||
State<StatefulWidget> createState() { |
||||
return _CustomPage(); |
||||
} |
||||
} |
||||
|
||||
class _CustomPage extends State<CustomPage>{ |
||||
String customDate = ''; |
||||
String endCustomDate = ''; |
||||
|
||||
void _onSelectionChanged(DateRangePickerSelectionChangedArgs args) { |
||||
setState(() { |
||||
if (args.value is PickerDateRange) { |
||||
customDate = |
||||
DateFormat('yyyy年MM月dd日 HH:mm:ss').format(args.value.startDate).toString() + |
||||
' 至 ' + |
||||
DateFormat('yyyy年MM月dd日 23:59:59') |
||||
.format(args.value.endDate ?? args.value.startDate) |
||||
.toString(); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return Scaffold( |
||||
appBar: MyAppBar( |
||||
title: "时间选择", |
||||
titleColor: Colors.black, |
||||
leadingColor: Colors.black, |
||||
background: Colors.white, |
||||
actions: [ |
||||
TextButton( |
||||
onPressed: () { |
||||
Navigator.pop(context, customDate,); |
||||
}, |
||||
child: Text( |
||||
"确定", |
||||
style: TextStyle( |
||||
color: Colors.black, |
||||
fontSize: 16, |
||||
), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
body: Stack( |
||||
children: <Widget>[ |
||||
Positioned( |
||||
left: 0, |
||||
top: 0, |
||||
right: 0, |
||||
bottom: 0, |
||||
child: (widget.arguments["beyondDateRange"]) == "1"?SfDateRangePicker( |
||||
onSelectionChanged: _onSelectionChanged, |
||||
selectionMode: DateRangePickerSelectionMode.range, |
||||
initialSelectedRange: PickerDateRange( |
||||
DateTime.now().subtract(const Duration(days: 4)), |
||||
DateTime.now().add(const Duration(days: 3)),), |
||||
startRangeSelectionColor: Color(0xFF30415B), |
||||
endRangeSelectionColor: Color(0xFF30415B), |
||||
todayHighlightColor: Color(0xFF30415B), |
||||
):SfDateRangePicker( |
||||
onSelectionChanged: _onSelectionChanged, |
||||
maxDate: DateTime.now(), |
||||
selectionMode: DateRangePickerSelectionMode.range, |
||||
initialSelectedRange: PickerDateRange( |
||||
DateTime.now().subtract(const Duration(days: 4)), |
||||
DateTime.now().add(const Duration(days: 3)),), |
||||
startRangeSelectionColor: Color(0xFF30415B), |
||||
endRangeSelectionColor: Color(0xFF30415B), |
||||
todayHighlightColor: Color(0xFF30415B), |
||||
), |
||||
) |
||||
], |
||||
)); |
||||
} |
||||
} |
@ -1,121 +0,0 @@
|
||||
import 'package:flutter/material.dart'; |
||||
import 'package:flutter_screenutil/flutter_screenutil.dart'; |
||||
import 'package:widgetpicker/widgetpicker.dart'; |
||||
|
||||
import '../../generated/l10n.dart'; |
||||
import '../../utils/font_weight.dart'; |
||||
|
||||
class DatePickerWidget extends StatelessWidget { |
||||
final _years = List.generate((DateTime.now().year - 2019 +1), (i) => "${i + 2019}年"); |
||||
final _months = List.generate(12, (i) => "${i + 1}月"); |
||||
final showChange; |
||||
|
||||
DatePickerWidget({this.showChange = true}); |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
bool monOn = true; |
||||
String _currentYear = "${DateTime.now().year.toString()}年"; |
||||
String _currentMonth = "${DateTime.now().month.toString()}月"; |
||||
String _currentTimeStr = |
||||
"${_currentYear.replaceAll("年", "")}-${_currentMonth.length == 2 ? "0${_currentMonth.replaceAll("月", "")}" : _currentMonth.replaceAll("月", "")}"; |
||||
return StatefulBuilder(builder: (context1, state) { |
||||
return Container( |
||||
height: 260.h, |
||||
decoration: BoxDecoration( |
||||
color: Colors.white, |
||||
borderRadius: BorderRadius.only( |
||||
topLeft: Radius.circular(8), |
||||
topRight: Radius.circular(8), |
||||
), |
||||
), |
||||
child: Column( |
||||
children: [ |
||||
Container( |
||||
height: 50.h, |
||||
child: Row( |
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween, |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
children: [ |
||||
InkWell( |
||||
onTap: () { |
||||
Navigator.of(context).pop(); |
||||
}, |
||||
child: Container( |
||||
child: Text( |
||||
S.of(context).quxiao, |
||||
style: TextStyle( |
||||
fontSize: 16, |
||||
fontWeight: MyFontWeight.semi_bold, |
||||
color: Colors.black), |
||||
), |
||||
margin: EdgeInsets.only(left: 6), |
||||
padding: EdgeInsets.all(10), |
||||
), |
||||
), |
||||
InkWell( |
||||
onTap: () { |
||||
Navigator.of(context).pop(_currentTimeStr); |
||||
}, |
||||
child: Container( |
||||
child: Text( |
||||
S.of(context).queren, |
||||
style: TextStyle( |
||||
fontSize: 16, |
||||
fontWeight: MyFontWeight.semi_bold, |
||||
color:Color(0xFF30415B)), |
||||
), |
||||
margin: EdgeInsets.only(left: 6), |
||||
padding: EdgeInsets.all(10), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
Container( |
||||
height: 2.h, |
||||
color: Color(0xFFF4F4F4), |
||||
), |
||||
Expanded(child: Container( |
||||
child: |
||||
Row( |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
WidgetPicker( |
||||
value: _currentYear, |
||||
options: _years, |
||||
textStyle: TextStyle( |
||||
fontSize: 16.sp, color: Color(0xFFDDDDDD),), |
||||
selectedTextStyle: |
||||
TextStyle(fontSize: 16.sp, color: Colors.black,fontWeight: MyFontWeight.medium), |
||||
onChanged: (value) => state(() => { |
||||
_currentYear = value, |
||||
_currentTimeStr = monOn |
||||
? "${_currentYear.replaceAll("年", "")}-${_currentMonth.length == 2 ? "0${_currentMonth.replaceAll("月", "")}" : _currentMonth.replaceAll("月", "")}" |
||||
: "${_currentYear.replaceAll("年", "")}" |
||||
}), |
||||
), |
||||
if (monOn) |
||||
WidgetPicker( |
||||
value: _currentMonth, |
||||
options: _months, |
||||
textStyle: TextStyle( |
||||
fontSize: 16.sp, color: Color(0xFFDDDDDD)), |
||||
selectedTextStyle: |
||||
TextStyle(fontSize: 16.sp, color: Colors.black,fontWeight: MyFontWeight.medium), |
||||
onChanged: (value) => state(() => { |
||||
_currentMonth = value, |
||||
_currentTimeStr = monOn |
||||
? "${_currentYear.replaceAll("年", "")}-${_currentMonth.length == 2 ? "0${_currentMonth.replaceAll("月", "")}" : _currentMonth.replaceAll("月", "")}" |
||||
: "${_currentYear.replaceAll("年", "")}" |
||||
}), |
||||
), |
||||
], |
||||
), |
||||
)), |
||||
], |
||||
), |
||||
); |
||||
}); |
||||
} |
||||
} |
@ -1,83 +0,0 @@
|
||||
import 'package:flutter/cupertino.dart'; |
||||
import 'package:flutter/material.dart'; |
||||
import 'package:intl/intl.dart'; |
||||
import 'package:syncfusion_flutter_datepicker/datepicker.dart'; |
||||
|
||||
import '../../view_widget/my_appbar.dart'; |
||||
|
||||
class DayReportPage extends StatefulWidget { |
||||
|
||||
@override |
||||
State<StatefulWidget> createState() { |
||||
return _DayReportPage(); |
||||
} |
||||
} |
||||
|
||||
class _DayReportPage extends State<DayReportPage>{ |
||||
String _selectedDate = ''; |
||||
String _range = ''; |
||||
|
||||
@override |
||||
void initState() { |
||||
super.initState(); |
||||
} |
||||
|
||||
void _onSelectionChanged(DateRangePickerSelectionChangedArgs args) { |
||||
setState(() { |
||||
if (args.value is PickerDateRange) { |
||||
_range = |
||||
DateFormat('dd/MM/yyyy').format(args.value.startDate).toString() + |
||||
' - ' + |
||||
DateFormat('dd/MM/yyyy') |
||||
.format(args.value.endDate ?? args.value.startDate) |
||||
.toString(); |
||||
} else if (args.value is DateTime) { |
||||
_selectedDate = args.value.toString().substring(0,10); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return Scaffold( |
||||
appBar: MyAppBar( |
||||
title: "时间选择", |
||||
titleColor: Colors.black, |
||||
leadingColor: Colors.black, |
||||
background: Colors.white, |
||||
actions: [ |
||||
TextButton( |
||||
onPressed: () { |
||||
Navigator.pop(context, _selectedDate); |
||||
}, |
||||
child: Text( |
||||
"确定", |
||||
style: TextStyle( |
||||
color: Colors.black, |
||||
fontSize: 16, |
||||
), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
body: Stack( |
||||
children: <Widget>[ |
||||
Positioned( |
||||
left: 0, |
||||
top: 0, |
||||
right: 0, |
||||
bottom: 0, |
||||
child: SfDateRangePicker( |
||||
onSelectionChanged: _onSelectionChanged, |
||||
maxDate: DateTime.now(), |
||||
selectionMode: DateRangePickerSelectionMode.single, |
||||
selectionColor: Color(0xFF30415B), |
||||
initialSelectedRange: PickerDateRange( |
||||
DateTime.now().subtract(const Duration(days: 4)), |
||||
DateTime.now().add(const Duration(days: 3))), |
||||
), |
||||
) |
||||
], |
||||
)); |
||||
} |
||||
} |
@ -1,69 +0,0 @@
|
||||
import 'package:flutter/material.dart'; |
||||
import 'package:syncfusion_flutter_datepicker/datepicker.dart'; |
||||
|
||||
import '../../view_widget/my_appbar.dart'; |
||||
|
||||
class MonthlyReportPage extends StatefulWidget { |
||||
|
||||
@override |
||||
State<StatefulWidget> createState() { |
||||
return _MonthlyReportPage(); |
||||
} |
||||
} |
||||
|
||||
class _MonthlyReportPage extends State<MonthlyReportPage>{ |
||||
String _monthlyDate = ''; |
||||
final DateRangePickerController _controller = DateRangePickerController(); |
||||
|
||||
void _onSelectionChanged(DateRangePickerSelectionChangedArgs args) { |
||||
setState(() { |
||||
if (args.value is DateTime) { |
||||
_monthlyDate = args.value.toString().substring(0,10); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return Scaffold( |
||||
appBar: MyAppBar( |
||||
title: "时间选择", |
||||
titleColor: Colors.black, |
||||
leadingColor: Colors.black, |
||||
background: Colors.white, |
||||
actions: [ |
||||
TextButton( |
||||
onPressed: () { |
||||
Navigator.pop(context, _monthlyDate); |
||||
}, |
||||
child: Text( |
||||
"确定", |
||||
style: TextStyle( |
||||
color: Colors.black, |
||||
fontSize: 16, |
||||
), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
body: Stack( |
||||
children: <Widget>[ |
||||
Positioned( |
||||
left: 0, |
||||
top: 0, |
||||
right: 0, |
||||
bottom: 0, |
||||
child: SfDateRangePicker( |
||||
onSelectionChanged: _onSelectionChanged, |
||||
maxDate: DateTime.now(), |
||||
selectionMode: DateRangePickerSelectionMode.single, |
||||
view: DateRangePickerView.year, |
||||
controller: _controller, |
||||
selectionColor: Color(0xFF30415B), |
||||
allowViewNavigation: false, |
||||
), |
||||
) |
||||
], |
||||
)); |
||||
} |
||||
} |
@ -1,92 +0,0 @@
|
||||
import 'package:flutter/cupertino.dart'; |
||||
import 'package:flutter/material.dart'; |
||||
import 'package:intl/intl.dart'; |
||||
import 'package:syncfusion_flutter_datepicker/datepicker.dart'; |
||||
|
||||
import '../../view_widget/my_appbar.dart'; |
||||
|
||||
class WeekReportPage extends StatefulWidget { |
||||
|
||||
@override |
||||
State<StatefulWidget> createState() { |
||||
return _WeekReportPage(); |
||||
} |
||||
} |
||||
|
||||
class _WeekReportPage extends State<WeekReportPage>{ |
||||
String _range = ''; |
||||
String _endRange = ''; |
||||
final DateRangePickerController _controller = DateRangePickerController(); |
||||
|
||||
void _onSelectionChanged(DateRangePickerSelectionChangedArgs args) { |
||||
setState(() { |
||||
if (args.value is PickerDateRange) { |
||||
final startDate = args.value.startDate; |
||||
final endDate = args.value.endDate; |
||||
if (endDate.difference(startDate).inDays > 6) { |
||||
_controller.selectedRange = PickerDateRange( |
||||
startDate.add(Duration(days: 6)), |
||||
endDate, |
||||
); |
||||
} else { |
||||
_range = DateFormat('yyyy年MM月dd日').format(args.value.startDate).toString() + |
||||
' 至 ' + |
||||
DateFormat('yyyy年MM月dd日') |
||||
.format(args.value.endDate ?? args.value.startDate) |
||||
.toString(); |
||||
_endRange = DateFormat('yyyy年MM月dd日').format(args.value.startDate).toString() + |
||||
' 至 ' + |
||||
DateFormat('yyyy年MM月dd日') |
||||
.format(args.value.endDate ?? args.value.startDate) |
||||
.toString(); |
||||
} |
||||
} |
||||
}); |
||||
} |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return Scaffold( |
||||
appBar: MyAppBar( |
||||
title: "时间选择", |
||||
titleColor: Colors.black, |
||||
leadingColor: Colors.black, |
||||
background: Colors.white, |
||||
actions: [ |
||||
TextButton( |
||||
onPressed: () { |
||||
Navigator.pop(context, _range,); |
||||
}, |
||||
child: Text( |
||||
"确定", |
||||
style: TextStyle( |
||||
color: Colors.black, |
||||
fontSize: 16, |
||||
), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
body: Stack( |
||||
children: <Widget>[ |
||||
Positioned( |
||||
left: 0, |
||||
top: 0, |
||||
right: 0, |
||||
bottom: 0, |
||||
child: SfDateRangePicker( |
||||
onSelectionChanged: _onSelectionChanged, |
||||
minDate: DateTime.now().subtract(const Duration(days: 361)), |
||||
controller: _controller, // 添加控制器 |
||||
// maxDate: DateTime.now().add(Duration(days: 365)), |
||||
maxDate: DateTime.now(), |
||||
selectionMode: DateRangePickerSelectionMode.range, |
||||
startRangeSelectionColor: Color(0xFF30415B), |
||||
endRangeSelectionColor: Color(0xFF30415B), |
||||
todayHighlightColor: Color(0xFF30415B), |
||||
), |
||||
) |
||||
], |
||||
)); |
||||
} |
||||
} |
File diff suppressed because it is too large
Load Diff
@ -1,837 +0,0 @@
|
||||
|
||||
|
||||
class Sku { |
||||
Sku({ |
||||
String applyPrice, |
||||
String autoRenewSkuStock, |
||||
String deliveries, |
||||
String id, |
||||
String isDelete, |
||||
List<dynamic> material, |
||||
String packagingFee, |
||||
String productId, |
||||
List<ProductSetMeals> productSetMeals, |
||||
String setMeal, |
||||
List<SetMealDtoList> setMealDTOList, |
||||
List<SkuAttrCodeDtoList> skuAttrCodeDTOList, |
||||
List<SkuAttrList> skuAttrList, |
||||
String skuCode, |
||||
String skuImg, |
||||
String skuNameStr, |
||||
String skuPrice, |
||||
String skuStock, |
||||
List<dynamic> skuTickets, |
||||
String sort, |
||||
String storeId, |
||||
List<dynamic> takeType, |
||||
String ticketDays, |
||||
TicketExpireTime ticketExpireTime, |
||||
String ticketStyle, |
||||
String ticketType, |
||||
String ticketWipedTimeTemplateId, |
||||
String version, |
||||
String vipPrice, |
||||
String volume, |
||||
String weight,}){ |
||||
_applyPrice = applyPrice; |
||||
_autoRenewSkuStock = autoRenewSkuStock; |
||||
_deliveries = deliveries; |
||||
_id = id; |
||||
_isDelete = isDelete; |
||||
_material = material; |
||||
_packagingFee = packagingFee; |
||||
_productId = productId; |
||||
_productSetMeals = productSetMeals; |
||||
_setMeal = setMeal; |
||||
_setMealDTOList = setMealDTOList; |
||||
_skuAttrCodeDTOList = skuAttrCodeDTOList; |
||||
_skuAttrList = skuAttrList; |
||||
_skuCode = skuCode; |
||||
_skuImg = skuImg; |
||||
_skuNameStr = skuNameStr; |
||||
_skuPrice = skuPrice; |
||||
_skuStock = skuStock; |
||||
_skuTickets = skuTickets; |
||||
_sort = sort; |
||||
_storeId = storeId; |
||||
_takeType = takeType; |
||||
_ticketDays = ticketDays; |
||||
_ticketExpireTime = ticketExpireTime; |
||||
_ticketStyle = ticketStyle; |
||||
_ticketType = ticketType; |
||||
_ticketWipedTimeTemplateId = ticketWipedTimeTemplateId; |
||||
_version = version; |
||||
_vipPrice = vipPrice; |
||||
_volume = volume; |
||||
_weight = weight; |
||||
} |
||||
|
||||
Sku.fromJson(dynamic json) { |
||||
_applyPrice = json['applyPrice']; |
||||
_autoRenewSkuStock = json['autoRenewSkuStock']; |
||||
_deliveries = json['deliveries']; |
||||
_id = json['id']; |
||||
_isDelete = json['isDelete']; |
||||
if (json['material'] != null) { |
||||
_material = []; |
||||
json['material'].forEach((v) { |
||||
_material.add(v); |
||||
}); |
||||
} |
||||
_packagingFee = json['packagingFee']; |
||||
_productId = json['productId']; |
||||
if (json['productSetMeals'] != null) { |
||||
_productSetMeals = []; |
||||
json['productSetMeals'].forEach((v) { |
||||
_productSetMeals.add(ProductSetMeals.fromJson(v)); |
||||
}); |
||||
} |
||||
_setMeal = json['setMeal']; |
||||
if (json['setMealDTOList'] != null) { |
||||
_setMealDTOList = []; |
||||
json['setMealDTOList'].forEach((v) { |
||||
_setMealDTOList.add(SetMealDtoList.fromJson(v)); |
||||
}); |
||||
} |
||||
if (json['skuAttrCodeDTOList'] != null) { |
||||
_skuAttrCodeDTOList = []; |
||||
json['skuAttrCodeDTOList'].forEach((v) { |
||||
_skuAttrCodeDTOList.add(SkuAttrCodeDtoList.fromJson(v)); |
||||
}); |
||||
} |
||||
if (json['skuAttrList'] != null) { |
||||
_skuAttrList = []; |
||||
json['skuAttrList'].forEach((v) { |
||||
_skuAttrList.add(SkuAttrList.fromJson(v)); |
||||
}); |
||||
} |
||||
_skuCode = json['skuCode']; |
||||
_skuImg = json['skuImg']; |
||||
_skuNameStr = json['skuNameStr']; |
||||
_skuPrice = json['skuPrice']; |
||||
_skuStock = json['skuStock']; |
||||
if (json['skuTickets'] != null) { |
||||
_skuTickets = []; |
||||
json['skuTickets'].forEach((v) { |
||||
_skuTickets.add(v); |
||||
}); |
||||
} |
||||
_sort = json['sort']; |
||||
_storeId = json['storeId']; |
||||
if (json['takeType'] != null) { |
||||
_takeType = []; |
||||
json['takeType'].forEach((v) { |
||||
_takeType.add(v); |
||||
}); |
||||
} |
||||
_ticketDays = json['ticketDays']; |
||||
_ticketExpireTime = json['ticketExpireTime'] != null ? TicketExpireTime.fromJson(json['ticketExpireTime']) : null; |
||||
_ticketStyle = json['ticketStyle']; |
||||
_ticketType = json['ticketType']; |
||||
_ticketWipedTimeTemplateId = json['ticketWipedTimeTemplateId']; |
||||
_version = json['version']; |
||||
_vipPrice = json['vipPrice']; |
||||
_volume = json['volume']; |
||||
_weight = json['weight']; |
||||
} |
||||
String _applyPrice; |
||||
String _autoRenewSkuStock; |
||||
String _deliveries; |
||||
String _id; |
||||
String _isDelete; |
||||
List<dynamic> _material; |
||||
String _packagingFee; |
||||
String _productId; |
||||
List<ProductSetMeals> _productSetMeals; |
||||
String _setMeal; |
||||
List<SetMealDtoList> _setMealDTOList; |
||||
List<SkuAttrCodeDtoList> _skuAttrCodeDTOList; |
||||
List<SkuAttrList> _skuAttrList; |
||||
String _skuCode; |
||||
String _skuImg; |
||||
String _skuNameStr; |
||||
String _skuPrice; |
||||
String _skuStock; |
||||
List<dynamic> _skuTickets; |
||||
String _sort; |
||||
String _storeId; |
||||
List<dynamic> _takeType; |
||||
String _ticketDays; |
||||
TicketExpireTime _ticketExpireTime; |
||||
String _ticketStyle; |
||||
String _ticketType; |
||||
String _ticketWipedTimeTemplateId; |
||||
String _version; |
||||
String _vipPrice; |
||||
String _volume; |
||||
String _weight; |
||||
|
||||
String get applyPrice => _applyPrice; |
||||
String get autoRenewSkuStock => _autoRenewSkuStock; |
||||
String get deliveries => _deliveries; |
||||
String get id => _id; |
||||
String get isDelete => _isDelete; |
||||
List<dynamic> get material => _material; |
||||
String get packagingFee => _packagingFee; |
||||
String get productId => _productId; |
||||
List<ProductSetMeals> get productSetMeals => _productSetMeals; |
||||
String get setMeal => _setMeal; |
||||
List<SetMealDtoList> get setMealDTOList => _setMealDTOList; |
||||
List<SkuAttrCodeDtoList> get skuAttrCodeDTOList => _skuAttrCodeDTOList; |
||||
List<SkuAttrList> get skuAttrList => _skuAttrList; |
||||
String get skuCode => _skuCode; |
||||
String get skuImg => _skuImg; |
||||
String get skuNameStr => _skuNameStr; |
||||
String get skuPrice => _skuPrice; |
||||
String get skuStock => _skuStock; |
||||
List<dynamic> get skuTickets => _skuTickets; |
||||
String get sort => _sort; |
||||
String get storeId => _storeId; |
||||
List<dynamic> get takeType => _takeType; |
||||
String get ticketDays => _ticketDays; |
||||
TicketExpireTime get ticketExpireTime => _ticketExpireTime; |
||||
String get ticketStyle => _ticketStyle; |
||||
String get ticketType => _ticketType; |
||||
String get ticketWipedTimeTemplateId => _ticketWipedTimeTemplateId; |
||||
String get version => _version; |
||||
String get vipPrice => _vipPrice; |
||||
String get volume => _volume; |
||||
String get weight => _weight; |
||||
|
||||
Map<String, dynamic> toJson() { |
||||
final map = <String, dynamic>{}; |
||||
map['applyPrice'] = _applyPrice; |
||||
map['autoRenewSkuStock'] = _autoRenewSkuStock; |
||||
map['deliveries'] = _deliveries; |
||||
map['id'] = _id; |
||||
map['isDelete'] = _isDelete; |
||||
if (_material != null) { |
||||
map['material'] = _material.map((v) => v.toJson()).toList(); |
||||
} |
||||
map['packagingFee'] = _packagingFee; |
||||
map['productId'] = _productId; |
||||
if (_productSetMeals != null) { |
||||
map['productSetMeals'] = _productSetMeals.map((v) => v.toJson()).toList(); |
||||
} |
||||
map['setMeal'] = _setMeal; |
||||
if (_setMealDTOList != null) { |
||||
map['setMealDTOList'] = _setMealDTOList.map((v) => v.toJson()).toList(); |
||||
} |
||||
if (_skuAttrCodeDTOList != null) { |
||||
map['skuAttrCodeDTOList'] = _skuAttrCodeDTOList.map((v) => v.toJson()).toList(); |
||||
} |
||||
if (_skuAttrList != null) { |
||||
map['skuAttrList'] = _skuAttrList.map((v) => v.toJson()).toList(); |
||||
} |
||||
map['skuCode'] = _skuCode; |
||||
map['skuImg'] = _skuImg; |
||||
map['skuNameStr'] = _skuNameStr; |
||||
map['skuPrice'] = _skuPrice; |
||||
map['skuStock'] = _skuStock; |
||||
if (_skuTickets != null) { |
||||
map['skuTickets'] = _skuTickets.map((v) => v.toJson()).toList(); |
||||
} |
||||
map['sort'] = _sort; |
||||
map['storeId'] = _storeId; |
||||
if (_takeType != null) { |
||||
map['takeType'] = _takeType.map((v) => v.toJson()).toList(); |
||||
} |
||||
map['ticketDays'] = _ticketDays; |
||||
if (_ticketExpireTime != null) { |
||||
map['ticketExpireTime'] = _ticketExpireTime.toJson(); |
||||
} |
||||
map['ticketStyle'] = _ticketStyle; |
||||
map['ticketType'] = _ticketType; |
||||
map['ticketWipedTimeTemplateId'] = _ticketWipedTimeTemplateId; |
||||
map['version'] = _version; |
||||
map['vipPrice'] = _vipPrice; |
||||
map['volume'] = _volume; |
||||
map['weight'] = _weight; |
||||
return map; |
||||
} |
||||
|
||||
} |
||||
|
||||
class TicketExpireTime { |
||||
TicketExpireTime({ |
||||
String hour, |
||||
String minute, |
||||
String nano, |
||||
String second,}){ |
||||
_hour = hour; |
||||
_minute = minute; |
||||
_nano = nano; |
||||
_second = second; |
||||
} |
||||
|
||||
TicketExpireTime.fromJson(dynamic json) { |
||||
_hour = json['hour']; |
||||
_minute = json['minute']; |
||||
_nano = json['nano']; |
||||
_second = json['second']; |
||||
} |
||||
String _hour; |
||||
String _minute; |
||||
String _nano; |
||||
String _second; |
||||
TicketExpireTime copyWith({ String hour, |
||||
String minute, |
||||
String nano, |
||||
String second, |
||||
}) => TicketExpireTime( hour: hour ?? _hour, |
||||
minute: minute ?? _minute, |
||||
nano: nano ?? _nano, |
||||
second: second ?? _second, |
||||
); |
||||
String get hour => _hour; |
||||
String get minute => _minute; |
||||
String get nano => _nano; |
||||
String get second => _second; |
||||
|
||||
Map<String, dynamic> toJson() { |
||||
final map = <String, dynamic>{}; |
||||
map['hour'] = _hour; |
||||
map['minute'] = _minute; |
||||
map['nano'] = _nano; |
||||
map['second'] = _second; |
||||
return map; |
||||
} |
||||
|
||||
} |
||||
|
||||
class SkuAttrList { |
||||
SkuAttrList({ |
||||
String attrId, |
||||
String attrValueId, |
||||
String id, |
||||
String isDelete, |
||||
String skuId, |
||||
String sortOrder,}){ |
||||
_attrId = attrId; |
||||
_attrValueId = attrValueId; |
||||
_id = id; |
||||
_isDelete = isDelete; |
||||
_skuId = skuId; |
||||
_sortOrder = sortOrder; |
||||
} |
||||
|
||||
SkuAttrList.fromJson(dynamic json) { |
||||
_attrId = json['attrId']; |
||||
_attrValueId = json['attrValueId']; |
||||
_id = json['id']; |
||||
_isDelete = json['isDelete']; |
||||
_skuId = json['skuId']; |
||||
_sortOrder = json['sortOrder']; |
||||
} |
||||
String _attrId; |
||||
String _attrValueId; |
||||
String _id; |
||||
String _isDelete; |
||||
String _skuId; |
||||
String _sortOrder; |
||||
SkuAttrList copyWith({ String attrId, |
||||
String attrValueId, |
||||
String id, |
||||
String isDelete, |
||||
String skuId, |
||||
String sortOrder, |
||||
}) => SkuAttrList( attrId: attrId ?? _attrId, |
||||
attrValueId: attrValueId ?? _attrValueId, |
||||
id: id ?? _id, |
||||
isDelete: isDelete ?? _isDelete, |
||||
skuId: skuId ?? _skuId, |
||||
sortOrder: sortOrder ?? _sortOrder, |
||||
); |
||||
String get attrId => _attrId; |
||||
String get attrValueId => _attrValueId; |
||||
String get id => _id; |
||||
String get isDelete => _isDelete; |
||||
String get skuId => _skuId; |
||||
String get sortOrder => _sortOrder; |
||||
|
||||
Map<String, dynamic> toJson() { |
||||
final map = <String, dynamic>{}; |
||||
map['attrId'] = _attrId; |
||||
map['attrValueId'] = _attrValueId; |
||||
map['id'] = _id; |
||||
map['isDelete'] = _isDelete; |
||||
map['skuId'] = _skuId; |
||||
map['sortOrder'] = _sortOrder; |
||||
return map; |
||||
} |
||||
|
||||
} |
||||
|
||||
class SkuAttrCodeDtoList { |
||||
SkuAttrCodeDtoList({ |
||||
String attrCode, |
||||
String attrValueCode,}){ |
||||
_attrCode = attrCode; |
||||
_attrValueCode = attrValueCode; |
||||
} |
||||
|
||||
SkuAttrCodeDtoList.fromJson(dynamic json) { |
||||
_attrCode = json['attrCode']; |
||||
_attrValueCode = json['attrValueCode']; |
||||
} |
||||
String _attrCode; |
||||
String _attrValueCode; |
||||
SkuAttrCodeDtoList copyWith({ String attrCode, |
||||
String attrValueCode, |
||||
}) => SkuAttrCodeDtoList( attrCode: attrCode ?? _attrCode, |
||||
attrValueCode: attrValueCode ?? _attrValueCode, |
||||
); |
||||
String get attrCode => _attrCode; |
||||
String get attrValueCode => _attrValueCode; |
||||
|
||||
Map<String, dynamic> toJson() { |
||||
final map = <String, dynamic>{}; |
||||
map['attrCode'] = _attrCode; |
||||
map['attrValueCode'] = _attrValueCode; |
||||
return map; |
||||
} |
||||
|
||||
} |
||||
|
||||
class SetMealDtoList { |
||||
SetMealDtoList({ |
||||
String buyNum, |
||||
String groupId, |
||||
String productId, |
||||
String productName, |
||||
String sellPrice, |
||||
String skuId, |
||||
String storeId,}){ |
||||
_buyNum = buyNum; |
||||
_groupId = groupId; |
||||
_productId = productId; |
||||
_productName = productName; |
||||
_sellPrice = sellPrice; |
||||
_skuId = skuId; |
||||
_storeId = storeId; |
||||
} |
||||
|
||||
SetMealDtoList.fromJson(dynamic json) { |
||||
_buyNum = json['buyNum']; |
||||
_groupId = json['groupId']; |
||||
_productId = json['productId']; |
||||
_productName = json['productName']; |
||||
_sellPrice = json['sellPrice']; |
||||
_skuId = json['skuId']; |
||||
_storeId = json['storeId']; |
||||
} |
||||
String _buyNum; |
||||
String _groupId; |
||||
String _productId; |
||||
String _productName; |
||||
String _sellPrice; |
||||
String _skuId; |
||||
String _storeId; |
||||
SetMealDtoList copyWith({ String buyNum, |
||||
String groupId, |
||||
String productId, |
||||
String productName, |
||||
String sellPrice, |
||||
String skuId, |
||||
String storeId, |
||||
}) => SetMealDtoList( buyNum: buyNum ?? _buyNum, |
||||
groupId: groupId ?? _groupId, |
||||
productId: productId ?? _productId, |
||||
productName: productName ?? _productName, |
||||
sellPrice: sellPrice ?? _sellPrice, |
||||
skuId: skuId ?? _skuId, |
||||
storeId: storeId ?? _storeId, |
||||
); |
||||
String get buyNum => _buyNum; |
||||
String get groupId => _groupId; |
||||
String get productId => _productId; |
||||
String get productName => _productName; |
||||
String get sellPrice => _sellPrice; |
||||
String get skuId => _skuId; |
||||
String get storeId => _storeId; |
||||
|
||||
Map<String, dynamic> toJson() { |
||||
final map = <String, dynamic>{}; |
||||
map['buyNum'] = _buyNum; |
||||
map['groupId'] = _groupId; |
||||
map['productId'] = _productId; |
||||
map['productName'] = _productName; |
||||
map['sellPrice'] = _sellPrice; |
||||
map['skuId'] = _skuId; |
||||
map['storeId'] = _storeId; |
||||
return map; |
||||
} |
||||
|
||||
} |
||||
|
||||
class ProductSetMeals { |
||||
ProductSetMeals({ |
||||
String groupName, |
||||
String optionalNumber, |
||||
List<ProductInfoList> productInfoList, |
||||
String totalNumber,}){ |
||||
_groupName = groupName; |
||||
_optionalNumber = optionalNumber; |
||||
_productInfoList = productInfoList; |
||||
_totalNumber = totalNumber; |
||||
} |
||||
|
||||
ProductSetMeals.fromJson(dynamic json) { |
||||
_groupName = json['groupName']; |
||||
_optionalNumber = json['optionalNumber']; |
||||
if (json['productInfoList'] != null) { |
||||
_productInfoList = []; |
||||
json['productInfoList'].forEach((v) { |
||||
_productInfoList.add(ProductInfoList.fromJson(v)); |
||||
}); |
||||
} |
||||
_totalNumber = json['totalNumber']; |
||||
} |
||||
String _groupName; |
||||
String _optionalNumber; |
||||
List<ProductInfoList> _productInfoList; |
||||
String _totalNumber; |
||||
ProductSetMeals copyWith({ String groupName, |
||||
String optionalNumber, |
||||
List<ProductInfoList> productInfoList, |
||||
String totalNumber, |
||||
}) => ProductSetMeals( groupName: groupName ?? _groupName, |
||||
optionalNumber: optionalNumber ?? _optionalNumber, |
||||
productInfoList: productInfoList ?? _productInfoList, |
||||
totalNumber: totalNumber ?? _totalNumber, |
||||
); |
||||
String get groupName => _groupName; |
||||
String get optionalNumber => _optionalNumber; |
||||
List<ProductInfoList> get productInfoList => _productInfoList; |
||||
String get totalNumber => _totalNumber; |
||||
|
||||
Map<String, dynamic> toJson() { |
||||
final map = <String, dynamic>{}; |
||||
map['groupName'] = _groupName; |
||||
map['optionalNumber'] = _optionalNumber; |
||||
if (_productInfoList != null) { |
||||
map['productInfoList'] = _productInfoList.map((v) => v.toJson()).toList(); |
||||
} |
||||
map['totalNumber'] = _totalNumber; |
||||
return map; |
||||
} |
||||
|
||||
} |
||||
|
||||
class ProductInfoList { |
||||
ProductInfoList({ |
||||
bool allSku, |
||||
bool markProductNone, |
||||
String number, |
||||
List<ProductAttrInfoList> productAttrInfoList, |
||||
String productId, |
||||
String productImg, |
||||
String productName, |
||||
List<SkuInfoList> skuInfoList, |
||||
String storeId,}){ |
||||
_allSku = allSku; |
||||
_markProductNone = markProductNone; |
||||
_number = number; |
||||
_productAttrInfoList = productAttrInfoList; |
||||
_productId = productId; |
||||
_productImg = productImg; |
||||
_productName = productName; |
||||
_skuInfoList = skuInfoList; |
||||
_storeId = storeId; |
||||
} |
||||
|
||||
ProductInfoList.fromJson(dynamic json) { |
||||
_allSku = json['allSku']; |
||||
_markProductNone = json['markProductNone']; |
||||
_number = json['number']; |
||||
if (json['productAttrInfoList'] != null) { |
||||
_productAttrInfoList = []; |
||||
json['productAttrInfoList'].forEach((v) { |
||||
_productAttrInfoList.add(ProductAttrInfoList.fromJson(v)); |
||||
}); |
||||
} |
||||
_productId = json['productId']; |
||||
_productImg = json['productImg']; |
||||
_productName = json['productName']; |
||||
if (json['skuInfoList'] != null) { |
||||
_skuInfoList = []; |
||||
json['skuInfoList'].forEach((v) { |
||||
_skuInfoList.add(SkuInfoList.fromJson(v)); |
||||
}); |
||||
} |
||||
_storeId = json['storeId']; |
||||
} |
||||
bool _allSku; |
||||
bool _markProductNone; |
||||
String _number; |
||||
List<ProductAttrInfoList> _productAttrInfoList; |
||||
String _productId; |
||||
String _productImg; |
||||
String _productName; |
||||
List<SkuInfoList> _skuInfoList; |
||||
String _storeId; |
||||
ProductInfoList copyWith({ bool allSku, |
||||
bool markProductNone, |
||||
String number, |
||||
List<ProductAttrInfoList> productAttrInfoList, |
||||
String productId, |
||||
String productImg, |
||||
String productName, |
||||
List<SkuInfoList> skuInfoList, |
||||
String storeId, |
||||
}) => ProductInfoList( allSku: allSku ?? _allSku, |
||||
markProductNone: markProductNone ?? _markProductNone, |
||||
number: number ?? _number, |
||||
productAttrInfoList: productAttrInfoList ?? _productAttrInfoList, |
||||
productId: productId ?? _productId, |
||||
productImg: productImg ?? _productImg, |
||||
productName: productName ?? _productName, |
||||
skuInfoList: skuInfoList ?? _skuInfoList, |
||||
storeId: storeId ?? _storeId, |
||||
); |
||||
bool get allSku => _allSku; |
||||
bool get markProductNone => _markProductNone; |
||||
String get number => _number; |
||||
List<ProductAttrInfoList> get productAttrInfoList => _productAttrInfoList; |
||||
String get productId => _productId; |
||||
String get productImg => _productImg; |
||||
String get productName => _productName; |
||||
List<SkuInfoList> get skuInfoList => _skuInfoList; |
||||
String get storeId => _storeId; |
||||
|
||||
Map<String, dynamic> toJson() { |
||||
final map = <String, dynamic>{}; |
||||
map['allSku'] = _allSku; |
||||
map['markProductNone'] = _markProductNone; |
||||
map['number'] = _number; |
||||
if (_productAttrInfoList != null) { |
||||
map['productAttrInfoList'] = _productAttrInfoList.map((v) => v.toJson()).toList(); |
||||
} |
||||
map['productId'] = _productId; |
||||
map['productImg'] = _productImg; |
||||
map['productName'] = _productName; |
||||
if (_skuInfoList != null) { |
||||
map['skuInfoList'] = _skuInfoList.map((v) => v.toJson()).toList(); |
||||
} |
||||
map['storeId'] = _storeId; |
||||
return map; |
||||
} |
||||
|
||||
} |
||||
|
||||
|
||||
class SkuInfoList { |
||||
SkuInfoList({ |
||||
String id, |
||||
List<ProductSkuAttrList> productSkuAttrList, |
||||
String skuName,}){ |
||||
_id = id; |
||||
_productSkuAttrList = productSkuAttrList; |
||||
_skuName = skuName; |
||||
} |
||||
|
||||
SkuInfoList.fromJson(dynamic json) { |
||||
_id = json['id']; |
||||
if (json['productSkuAttrList'] != null) { |
||||
_productSkuAttrList = []; |
||||
json['productSkuAttrList'].forEach((v) { |
||||
_productSkuAttrList.add(ProductSkuAttrList.fromJson(v)); |
||||
}); |
||||
} |
||||
_skuName = json['skuName']; |
||||
} |
||||
String _id; |
||||
List<ProductSkuAttrList> _productSkuAttrList; |
||||
String _skuName; |
||||
SkuInfoList copyWith({ String id, |
||||
List<ProductSkuAttrList> productSkuAttrList, |
||||
String skuName, |
||||
}) => SkuInfoList( id: id ?? _id, |
||||
productSkuAttrList: productSkuAttrList ?? _productSkuAttrList, |
||||
skuName: skuName ?? _skuName, |
||||
); |
||||
String get id => _id; |
||||
List<ProductSkuAttrList> get productSkuAttrList => _productSkuAttrList; |
||||
String get skuName => _skuName; |
||||
|
||||
Map<String, dynamic> toJson() { |
||||
final map = <String, dynamic>{}; |
||||
map['id'] = _id; |
||||
if (_productSkuAttrList != null) { |
||||
map['productSkuAttrList'] = _productSkuAttrList.map((v) => v.toJson()).toList(); |
||||
} |
||||
map['skuName'] = _skuName; |
||||
return map; |
||||
} |
||||
|
||||
} |
||||
|
||||
/// attrId : 0 |
||||
/// attrValueId : 0 |
||||
/// id : 0 |
||||
/// isDelete : 0 |
||||
/// skuId : 0 |
||||
/// sortOrder : 0 |
||||
|
||||
class ProductSkuAttrList { |
||||
ProductSkuAttrList({ |
||||
String attrId, |
||||
String attrValueId, |
||||
String id, |
||||
String isDelete, |
||||
String skuId, |
||||
String sortOrder,}){ |
||||
_attrId = attrId; |
||||
_attrValueId = attrValueId; |
||||
_id = id; |
||||
_isDelete = isDelete; |
||||
_skuId = skuId; |
||||
_sortOrder = sortOrder; |
||||
} |
||||
|
||||
ProductSkuAttrList.fromJson(dynamic json) { |
||||
_attrId = json['attrId']; |
||||
_attrValueId = json['attrValueId']; |
||||
_id = json['id']; |
||||
_isDelete = json['isDelete']; |
||||
_skuId = json['skuId']; |
||||
_sortOrder = json['sortOrder']; |
||||
} |
||||
String _attrId; |
||||
String _attrValueId; |
||||
String _id; |
||||
String _isDelete; |
||||
String _skuId; |
||||
String _sortOrder; |
||||
ProductSkuAttrList copyWith({ String attrId, |
||||
String attrValueId, |
||||
String id, |
||||
String isDelete, |
||||
String skuId, |
||||
String sortOrder, |
||||
}) => ProductSkuAttrList( attrId: attrId ?? _attrId, |
||||
attrValueId: attrValueId ?? _attrValueId, |
||||
id: id ?? _id, |
||||
isDelete: isDelete ?? _isDelete, |
||||
skuId: skuId ?? _skuId, |
||||
sortOrder: sortOrder ?? _sortOrder, |
||||
); |
||||
String get attrId => _attrId; |
||||
String get attrValueId => _attrValueId; |
||||
String get id => _id; |
||||
String get isDelete => _isDelete; |
||||
String get skuId => _skuId; |
||||
String get sortOrder => _sortOrder; |
||||
|
||||
Map<String, dynamic> toJson() { |
||||
final map = <String, dynamic>{}; |
||||
map['attrId'] = _attrId; |
||||
map['attrValueId'] = _attrValueId; |
||||
map['id'] = _id; |
||||
map['isDelete'] = _isDelete; |
||||
map['skuId'] = _skuId; |
||||
map['sortOrder'] = _sortOrder; |
||||
return map; |
||||
} |
||||
|
||||
} |
||||
|
||||
/// attrId : 0 |
||||
/// attrName : "" |
||||
/// attrValueList : [{"attrId":0,"attrName":"","attrValueList":[{}]}] |
||||
|
||||
class ProductAttrInfoList { |
||||
ProductAttrInfoList({ |
||||
String attrId, |
||||
String attrName, |
||||
List<AttrValueList> attrValueList,}){ |
||||
_attrId = attrId; |
||||
_attrName = attrName; |
||||
_attrValueList = attrValueList; |
||||
} |
||||
|
||||
ProductAttrInfoList.fromJson(dynamic json) { |
||||
_attrId = json['attrId']; |
||||
_attrName = json['attrName']; |
||||
if (json['attrValueList'] != null) { |
||||
_attrValueList = []; |
||||
json['attrValueList'].forEach((v) { |
||||
_attrValueList.add(AttrValueList.fromJson(v)); |
||||
}); |
||||
} |
||||
} |
||||
String _attrId; |
||||
String _attrName; |
||||
List<AttrValueList> _attrValueList; |
||||
ProductAttrInfoList copyWith({ String attrId, |
||||
String attrName, |
||||
List<AttrValueList> attrValueList, |
||||
}) => ProductAttrInfoList( attrId: attrId ?? _attrId, |
||||
attrName: attrName ?? _attrName, |
||||
attrValueList: attrValueList ?? _attrValueList, |
||||
); |
||||
String get attrId => _attrId; |
||||
String get attrName => _attrName; |
||||
List<AttrValueList> get attrValueList => _attrValueList; |
||||
|
||||
Map<String, dynamic> toJson() { |
||||
final map = <String, dynamic>{}; |
||||
map['attrId'] = _attrId; |
||||
map['attrName'] = _attrName; |
||||
if (_attrValueList != null) { |
||||
map['attrValueList'] = _attrValueList.map((v) => v.toJson()).toList(); |
||||
} |
||||
return map; |
||||
} |
||||
|
||||
} |
||||
|
||||
/// attrId : 0 |
||||
/// attrName : "" |
||||
/// attrValueList : [{}] |
||||
|
||||
class AttrValueList { |
||||
AttrValueList({ |
||||
String attrId, |
||||
String attrName, |
||||
List<dynamic> attrValueList,}){ |
||||
_attrId = attrId; |
||||
_attrName = attrName; |
||||
_attrValueList = attrValueList; |
||||
} |
||||
|
||||
AttrValueList.fromJson(dynamic json) { |
||||
_attrId = json['attrId']; |
||||
_attrName = json['attrName']; |
||||
if (json['attrValueList'] != null) { |
||||
_attrValueList = []; |
||||
json['attrValueList'].forEach((v) { |
||||
_attrValueList.add(v); |
||||
}); |
||||
} |
||||
} |
||||
String _attrId; |
||||
String _attrName; |
||||
List<dynamic> _attrValueList; |
||||
AttrValueList copyWith({ String attrId, |
||||
String attrName, |
||||
List<dynamic> attrValueList, |
||||
}) => AttrValueList( attrId: attrId ?? _attrId, |
||||
attrName: attrName ?? _attrName, |
||||
attrValueList: attrValueList ?? _attrValueList, |
||||
); |
||||
String get attrId => _attrId; |
||||
String get attrName => _attrName; |
||||
List<dynamic> get attrValueList => _attrValueList; |
||||
|
||||
Map<String, dynamic> toJson() { |
||||
final map = <String, dynamic>{}; |
||||
map['attrId'] = _attrId; |
||||
map['attrName'] = _attrName; |
||||
if (_attrValueList != null) { |
||||
map['attrValueList'] = _attrValueList.map((v) => v.toJson()).toList(); |
||||
} |
||||
return map; |
||||
} |
||||
|
||||
} |
@ -1,70 +0,0 @@
|
||||
|
||||
|
||||
import 'package:flutter/cupertino.dart'; |
||||
|
||||
|
||||
class ProductSkuAttr { |
||||
|
||||
TextEditingController _specsNameController; |
||||
|
||||
String attrCode; |
||||
String needImg; |
||||
|
||||
TextEditingController get specsNameController => _specsNameController; |
||||
|
||||
String get attrName => _attrName = specsNameController.text; |
||||
|
||||
String _attrName; |
||||
|
||||
List<ProductSkuAttrValue> attrValueList = []; |
||||
|
||||
ProductSkuAttr(){ |
||||
_specsNameController = TextEditingController(); |
||||
} |
||||
|
||||
Map<String, dynamic> toJson() { |
||||
final map = <String, dynamic>{}; |
||||
map['attrCode'] = attrCode; |
||||
map['needImg'] = needImg ?? false; |
||||
map['attrName'] = attrName; |
||||
if (attrValueList != null && attrValueList.isNotEmpty) { |
||||
map['attrValueList'] = attrValueList.map((e) => e.toJson()).toList(); |
||||
} |
||||
return map; |
||||
} |
||||
|
||||
@override |
||||
String toString() { |
||||
return 'ProductSkuAttr{attrCode: $attrCode, attrName: $attrName, needimg: $needImg, attrValueList: $attrValueList}'; |
||||
} |
||||
|
||||
} |
||||
|
||||
|
||||
class ProductSkuAttrValue { |
||||
|
||||
String attrValue; |
||||
String attrValueCode; |
||||
String attrValueImage; |
||||
|
||||
TextEditingController _specsValueNameController; |
||||
|
||||
TextEditingController get specsValueNameController => _specsValueNameController; |
||||
|
||||
ProductSkuAttrValue(){ |
||||
_specsValueNameController = TextEditingController(); |
||||
} |
||||
|
||||
Map<String, dynamic> toJson() { |
||||
final map = <String, dynamic>{}; |
||||
map['attrValue'] = attrValue; |
||||
map['attrValueCode'] = attrValueCode; |
||||
map['attrValueImage'] = attrValueImage; |
||||
return map; |
||||
} |
||||
|
||||
@override |
||||
String toString() { |
||||
return 'ProductSkuAttrValue{attrValue: $attrValue, attrValueCode: $attrValueCode, attrValueImage: $attrValueImage}'; |
||||
} |
||||
} |
@ -1,515 +0,0 @@
|
||||
import 'package:flutter/material.dart'; |
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; |
||||
import 'package:huixiang/view_widget/my_appbar.dart'; |
||||
import 'package:flutter_screenutil/flutter_screenutil.dart'; |
||||
import '../../../generated/l10n.dart'; |
||||
import '../../../retrofit/business_api.dart'; |
||||
import '../../../retrofit/data/edit_specs_detail_list.dart'; |
||||
import '../../../utils/font_weight.dart'; |
||||
import '../../../view_widget/settlement_tips_dialog.dart'; |
||||
import 'data/product_sku.dart'; |
||||
import 'data/product_sku_attr.dart'; |
||||
|
||||
class EditSpecsDetail extends StatefulWidget { |
||||
final Map<String, dynamic> arguments; |
||||
|
||||
EditSpecsDetail({this.arguments}); |
||||
|
||||
@override |
||||
State<StatefulWidget> createState() { |
||||
return _EditSpecsDetail(); |
||||
} |
||||
} |
||||
|
||||
class _EditSpecsDetail extends State<EditSpecsDetail> { |
||||
List<EditSpecsDetailList> editSpecsDetailList = []; |
||||
Map<String, List<String>> codeMap = {}; |
||||
bool isKeyBoardShow = false; |
||||
FocusNode _focusNode = FocusNode(); |
||||
BusinessApiService businessService; |
||||
|
||||
@override |
||||
void initState() { |
||||
super.initState(); |
||||
WidgetsBinding.instance.addPostFrameCallback((_) { |
||||
setState(() { |
||||
print("object: ${MediaQuery.of(context).viewInsets.bottom}"); |
||||
if (MediaQuery.of(context).viewInsets.bottom == 0) { |
||||
if (isKeyBoardShow) { |
||||
isKeyBoardShow = false; |
||||
//关闭键盘 软键盘关闭了, 清除输入控件的焦点, 否则重新进入页面会导致软键盘再弹出问题 |
||||
FocusScope.of(context).requestFocus(FocusNode()); |
||||
} |
||||
} else { |
||||
isKeyBoardShow = true; |
||||
} |
||||
}); |
||||
}); |
||||
List<ProductSkuAttr> skus = widget?.arguments["skus"] ?? []; |
||||
|
||||
List<String> skiStr = mergeAttrCode(skus); |
||||
|
||||
List<Sku> skuList = widget.arguments["skuList"] ?? []; |
||||
print("skuList: ${skuList.map((e) => e.toJson()).toList()}"); |
||||
|
||||
print("skiStr: $skiStr"); |
||||
skiStr.forEach((element) { |
||||
var edit = EditSpecsDetailList(element); |
||||
for (var e1 in skuList) { |
||||
if (e1.skuNameStr == element) { |
||||
edit.goodPriceController.text = "${e1.skuPrice}"; |
||||
edit.originalPriceController.text = "${e1.applyPrice}"; |
||||
edit.packagingFeeController.text = "${e1.packagingFee}"; |
||||
edit.specsWeightController.text = "${e1.weight}"; |
||||
edit.skuStockController.text = "${e1.skuStock}"; |
||||
break; |
||||
} |
||||
} |
||||
editSpecsDetailList.add(edit); |
||||
}); |
||||
} |
||||
|
||||
///sku计算 |
||||
List<String> mergeArr(List<List<String>> arr) { |
||||
var result = arr.removeAt(0); |
||||
while (arr.isNotEmpty) { |
||||
var curArr = arr.removeAt(0); |
||||
var lastArr = result; |
||||
result = []; |
||||
for (var lastVal in lastArr) { |
||||
for (var curVal in curArr) { |
||||
result.add("$lastVal $curVal"); |
||||
} |
||||
} |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
///sku计算 |
||||
List<String> mergeAttrCode(List<ProductSkuAttr> arr) { |
||||
List<String> attrValue = []; |
||||
|
||||
for (ProductSkuAttr skuAttr in arr) { |
||||
attrValue = mergeName(attrValue, skuAttr.attrValueList); |
||||
} |
||||
|
||||
codeMap = mergeCodeMap(codeMap, attrValue, arr); |
||||
|
||||
print("attrValue: $attrValue"); |
||||
print("codeMap: $codeMap"); |
||||
return attrValue; |
||||
} |
||||
|
||||
Map<String, List<String>> mergeCodeMap(Map<String, List<String>> resultMap, List<String> attrValue, List<ProductSkuAttr> skuAttr) { |
||||
for (String attrName in attrValue) { |
||||
for (ProductSkuAttr skuAttrValue in skuAttr) { |
||||
for (ProductSkuAttrValue skuAttrValue in skuAttrValue.attrValueList) { |
||||
if (attrName.contains("${skuAttrValue.attrValue}")) { |
||||
if (resultMap.containsKey(attrName)) { |
||||
resultMap[attrName].add(skuAttrValue.attrValueCode); |
||||
} else { |
||||
resultMap[attrName] = [skuAttrValue.attrValueCode]; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
return resultMap; |
||||
} |
||||
|
||||
List<String> mergeName(List<String> attrValues, List<ProductSkuAttrValue> values) { |
||||
if (attrValues.isEmpty) { |
||||
return values.map((e) => e.attrValue).toList(); |
||||
} |
||||
List<String> resultValue = []; |
||||
for (String rValue in attrValues) { |
||||
for (ProductSkuAttrValue iValue in values) { |
||||
resultValue.add("$rValue ${iValue.attrValue}"); |
||||
} |
||||
} |
||||
return resultValue; |
||||
} |
||||
|
||||
///离开页面记着销毁和清除 |
||||
@override |
||||
void dispose() { |
||||
_focusNode.unfocus(); |
||||
super.dispose(); |
||||
} |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return Scaffold( |
||||
resizeToAvoidBottomInset: false, |
||||
appBar: MyAppBar( |
||||
title: "编辑规格明细", |
||||
titleColor: Colors.black, |
||||
background: Colors.white, |
||||
leadingColor: Colors.black, |
||||
brightness: Brightness.dark, |
||||
), |
||||
body: Stack( |
||||
children: [ |
||||
Container( |
||||
margin: EdgeInsets.only(bottom: 120.h), |
||||
child: ListView.builder( |
||||
padding: EdgeInsets.zero, |
||||
itemCount: editSpecsDetailList.length, |
||||
scrollDirection: Axis.vertical, |
||||
shrinkWrap: true, |
||||
physics: BouncingScrollPhysics(), |
||||
itemBuilder: (context, position) { |
||||
return GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
setState(() { |
||||
FocusScope.of(context).unfocus(); |
||||
}); |
||||
}, |
||||
child: editSpecsItem(position)); |
||||
}, |
||||
), |
||||
), |
||||
|
||||
///确认 |
||||
Align( |
||||
alignment: Alignment.bottomCenter, |
||||
child: GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
bool flag = false; |
||||
String editType = ""; |
||||
List<Sku> skuList = []; |
||||
editSpecsDetailList.forEach((element) { |
||||
if (element.goodPriceController.text.trim() == "") { |
||||
flag = true; |
||||
editType = "请输入商品售价"; |
||||
return; |
||||
} else if (element.originalPriceController.text.trim() == "") { |
||||
flag = true; |
||||
editType = "请输入商品原价"; |
||||
return; |
||||
} |
||||
var productSku = Sku( |
||||
skuNameStr: element.specsDetailName, |
||||
skuPrice: element.goodPriceController.text.toString(), |
||||
applyPrice: element.originalPriceController.text == "" ? "0" : element.originalPriceController.text, |
||||
packagingFee: element.packagingFeeController.text == "" ? "0" : element.packagingFeeController.text, |
||||
weight: element.specsWeightController.text == "" ? "0" : element.specsWeightController.text, |
||||
skuStock: element.skuStockController.text == "" ? "0" : element.skuStockController.text, |
||||
skuAttrCodeDTOList: codeMap[element.specsDetailName].map((e) { |
||||
return SkuAttrCodeDtoList( |
||||
attrCode: e.substring(0, e.lastIndexOf("_value")), |
||||
attrValueCode: e, |
||||
); |
||||
}).toList(), |
||||
); |
||||
skuList.add(productSku); |
||||
}); |
||||
if (flag) { |
||||
SmartDialog.show( |
||||
clickBgDismissTemp: false, |
||||
widget: SettlementTips( |
||||
() {}, |
||||
text: editType, |
||||
color: Color(0xFF30415B), |
||||
)); |
||||
} else { |
||||
Navigator.of(context).pop(skuList); |
||||
} |
||||
}, |
||||
child: Container( |
||||
color: Colors.white, |
||||
width: double.infinity, |
||||
padding: EdgeInsets.only( |
||||
top: 10.h, left: 16.w, right: 16.w, bottom: 34.h), |
||||
child: Container( |
||||
alignment: Alignment.center, |
||||
height: 54.h, |
||||
decoration: BoxDecoration( |
||||
color: Color(0xFF30415B), |
||||
borderRadius: BorderRadius.circular(27), |
||||
), |
||||
child: Text( |
||||
S.of(context).baocun, |
||||
style: TextStyle( |
||||
color: Colors.white, |
||||
fontSize: 16.sp, |
||||
fontWeight: MyFontWeight.bold, |
||||
), |
||||
), |
||||
), |
||||
), |
||||
)) |
||||
], |
||||
), |
||||
); |
||||
} |
||||
|
||||
///编辑规格list |
||||
Widget editSpecsItem(index) { |
||||
return Container( |
||||
color: Colors.white, |
||||
margin: EdgeInsets.symmetric(vertical: 12.h), |
||||
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 20.h), |
||||
child: Column( |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Text( |
||||
editSpecsDetailList[index].specsDetailName ?? "", |
||||
style: TextStyle( |
||||
color: Color(0xD9000000), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.bold, |
||||
), |
||||
), |
||||
Container( |
||||
width: double.infinity, |
||||
height: 1.h, |
||||
margin: EdgeInsets.only(top: 20.h), |
||||
color: Color(0x14000000), |
||||
), |
||||
Row( |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
Expanded( |
||||
child: Text.rich( |
||||
TextSpan( |
||||
children: [ |
||||
TextSpan( |
||||
text: "*", |
||||
style: TextStyle( |
||||
color: Color(0xFFE02020), |
||||
fontSize: 14.sp, |
||||
fontWeight: FontWeight.w500, |
||||
), |
||||
), |
||||
TextSpan( |
||||
text: "商品售价", |
||||
style: TextStyle( |
||||
color: Color(0xD9000000), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
), |
||||
Expanded( |
||||
child: TextField( |
||||
controller: editSpecsDetailList[index].goodPriceController, |
||||
decoration: InputDecoration( |
||||
hintText: "请输入商品售卖价格", |
||||
hintTextDirection: TextDirection.rtl, |
||||
hintStyle: TextStyle( |
||||
color: Color(0xFF7A797F), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
border: InputBorder.none, |
||||
), |
||||
textAlign: TextAlign.right, |
||||
style: TextStyle( |
||||
color: Color(0xFF7A797F), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular), |
||||
), |
||||
flex: 2, |
||||
), |
||||
], |
||||
), |
||||
Container( |
||||
width: double.infinity, |
||||
height: 1.h, |
||||
color: Color(0x14000000), |
||||
), |
||||
Row( |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
Expanded( |
||||
child: Text.rich( |
||||
TextSpan( |
||||
children: [ |
||||
TextSpan( |
||||
text: "*", |
||||
style: TextStyle( |
||||
color: Color(0xFFE02020), |
||||
fontSize: 14.sp, |
||||
fontWeight: FontWeight.w500, |
||||
), |
||||
), |
||||
TextSpan( |
||||
text: "商品原价", |
||||
style: TextStyle( |
||||
color: Color(0xD9000000), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
), |
||||
Expanded( |
||||
child: TextField( |
||||
controller: |
||||
editSpecsDetailList[index].originalPriceController, |
||||
decoration: InputDecoration( |
||||
hintText: "请输入商品划线价格", |
||||
hintTextDirection: TextDirection.rtl, |
||||
hintStyle: TextStyle( |
||||
color: Color(0xFF7A797F), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
border: InputBorder.none, |
||||
), |
||||
textAlign: TextAlign.right, |
||||
style: TextStyle( |
||||
color: Color(0xFF7A797F), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular), |
||||
), |
||||
flex: 2, |
||||
), |
||||
], |
||||
), |
||||
Container( |
||||
width: double.infinity, |
||||
height: 1.h, |
||||
color: Color(0x14000000), |
||||
), |
||||
Row( |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
Expanded( |
||||
child: Text( |
||||
"商品打包费", |
||||
style: TextStyle( |
||||
color: Color(0xD9000000), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
), |
||||
), |
||||
Expanded( |
||||
child: TextField( |
||||
controller: editSpecsDetailList[index].packagingFeeController, |
||||
decoration: InputDecoration( |
||||
hintText: "请输入商品打包费", |
||||
hintTextDirection: TextDirection.rtl, |
||||
hintStyle: TextStyle( |
||||
color: Color(0xFF7A797F), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
border: InputBorder.none, |
||||
), |
||||
textAlign: TextAlign.right, |
||||
style: TextStyle( |
||||
color: Color(0xFF7A797F), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular), |
||||
), |
||||
flex: 2, |
||||
), |
||||
], |
||||
), |
||||
Container( |
||||
width: double.infinity, |
||||
height: 1.h, |
||||
color: Color(0x14000000), |
||||
), |
||||
Row( |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
Expanded( |
||||
child: Text( |
||||
"商品重量", |
||||
style: TextStyle( |
||||
color: Color(0xD9000000), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
), |
||||
), |
||||
Expanded( |
||||
child: TextField( |
||||
controller: editSpecsDetailList[index].specsWeightController, |
||||
decoration: InputDecoration( |
||||
hintText: "请输入商品重量(单位kg)", |
||||
hintTextDirection: TextDirection.rtl, |
||||
hintStyle: TextStyle( |
||||
color: Color(0xFF7A797F), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
border: InputBorder.none, |
||||
), |
||||
textAlign: TextAlign.right, |
||||
style: TextStyle( |
||||
color: Color(0xFF7A797F), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular), |
||||
), |
||||
flex: 2, |
||||
), |
||||
], |
||||
), |
||||
Container( |
||||
width: double.infinity, |
||||
height: 1.h, |
||||
color: Color(0x14000000), |
||||
), |
||||
Row( |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
Expanded( |
||||
child: Text( |
||||
"商品库存", |
||||
style: TextStyle( |
||||
color: Color(0xD9000000), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
), |
||||
), |
||||
Expanded( |
||||
child: TextField( |
||||
controller: editSpecsDetailList[index].skuStockController, |
||||
decoration: InputDecoration( |
||||
hintText: "请输入商品库存", |
||||
hintTextDirection: TextDirection.rtl, |
||||
hintStyle: TextStyle( |
||||
color: Color(0xFF7A797F), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
border: InputBorder.none, |
||||
), |
||||
textAlign: TextAlign.right, |
||||
style: TextStyle( |
||||
color: Color(0xFF7A797F), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular), |
||||
), |
||||
flex: 2, |
||||
), |
||||
], |
||||
), |
||||
Container( |
||||
width: double.infinity, |
||||
height: 1.h, |
||||
color: Color(0x14000000), |
||||
), |
||||
], |
||||
), |
||||
); |
||||
} |
||||
} |
@ -1,495 +0,0 @@
|
||||
import 'package:flutter/material.dart'; |
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; |
||||
import 'package:huixiang/business_system/goods/add_goods/data/product_sku_attr.dart'; |
||||
import 'package:huixiang/view_widget/my_appbar.dart'; |
||||
import 'package:flutter_screenutil/flutter_screenutil.dart'; |
||||
import '../../../retrofit/business_api.dart'; |
||||
import '../../../retrofit/data/set_specs_list.dart'; |
||||
import '../../../utils/font_weight.dart'; |
||||
import '../../../view_widget/settlement_tips_dialog.dart'; |
||||
import 'data/product_sku.dart'; |
||||
|
||||
class SetGoodsSpecs extends StatefulWidget { |
||||
final Map<String, dynamic> arguments; |
||||
|
||||
SetGoodsSpecs({this.arguments}); |
||||
|
||||
@override |
||||
State<StatefulWidget> createState() { |
||||
return _SetGoodsSpecs(); |
||||
} |
||||
} |
||||
|
||||
class _SetGoodsSpecs extends State<SetGoodsSpecs> { |
||||
List<ProductSkuAttr> skuAttrList = []; |
||||
List<Sku> skuList = []; |
||||
bool isKeyBoardShow = false; |
||||
FocusNode _focusNode = FocusNode(); |
||||
BusinessApiService businessService; |
||||
|
||||
@override |
||||
void initState() { |
||||
super.initState(); |
||||
WidgetsBinding.instance.addPostFrameCallback((_) { |
||||
setState(() { |
||||
print("object: ${MediaQuery.of(context).viewInsets.bottom}"); |
||||
if (MediaQuery.of(context).viewInsets.bottom == 0) { |
||||
if (isKeyBoardShow) { |
||||
isKeyBoardShow = false; |
||||
//关闭键盘 软键盘关闭了, 清除输入控件的焦点, 否则重新进入页面会导致软键盘再弹出问题 |
||||
FocusScope.of(context).requestFocus(FocusNode()); |
||||
} |
||||
} else { |
||||
isKeyBoardShow = true; |
||||
} |
||||
}); |
||||
}); |
||||
skuAttrList = widget?.arguments["skuAttrList"] ?? []; |
||||
skuList = widget?.arguments["skuList"] ?? []; |
||||
skuAttrList.forEach((element) { |
||||
element.specsNameController.text = element.attrName; |
||||
}); |
||||
} |
||||
|
||||
///离开页面记着销毁和清除 |
||||
@override |
||||
void dispose() { |
||||
_focusNode.unfocus(); |
||||
super.dispose(); |
||||
} |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
FocusScope.of(context).unfocus(); |
||||
}, |
||||
child: Scaffold( |
||||
resizeToAvoidBottomInset: false, |
||||
appBar: MyAppBar( |
||||
title: "设置商品规格", |
||||
titleColor: Colors.black, |
||||
background: Colors.white, |
||||
leadingColor: Colors.black, |
||||
brightness: Brightness.dark, |
||||
), |
||||
body: Stack( |
||||
children: [ |
||||
SingleChildScrollView( |
||||
physics: BouncingScrollPhysics(), |
||||
child: Container( |
||||
margin: EdgeInsets.only(bottom: 150.h), |
||||
child: Column( |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
ListView.builder( |
||||
padding: EdgeInsets.zero, |
||||
itemCount: skuAttrList.length, |
||||
scrollDirection: Axis.vertical, |
||||
shrinkWrap: true, |
||||
physics: BouncingScrollPhysics(), |
||||
itemBuilder: (context, position) { |
||||
return GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
FocusScope.of(context).unfocus(); |
||||
}, |
||||
child: specsText(position)); |
||||
}, |
||||
), |
||||
GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
setState(() { |
||||
ProductSkuAttr product = ProductSkuAttr(); |
||||
product.attrCode = "attr_code_${skuAttrList.length}"; |
||||
skuAttrList.add(product); |
||||
}); |
||||
}, |
||||
child: Container( |
||||
color: Colors.white, |
||||
padding: EdgeInsets.symmetric(vertical: 20.h), |
||||
child: Row( |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
Icon( |
||||
Icons.add_circle, |
||||
color: Color(0xFF30415B), |
||||
size: 20, |
||||
), |
||||
Padding( |
||||
padding: EdgeInsets.only(left: 7.w), |
||||
child: Text( |
||||
"添加规格", |
||||
style: TextStyle( |
||||
color: Color(0xD9000000), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.bold, |
||||
), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
), |
||||
if (skuAttrList.length > 0) |
||||
Padding( |
||||
padding: EdgeInsets.all(16), |
||||
child: Text( |
||||
"设置库存/价格等规格明细", |
||||
style: TextStyle( |
||||
color: Color(0xFF7A797F), |
||||
fontSize: 12.sp, |
||||
fontWeight: MyFontWeight.bold, |
||||
), |
||||
)), |
||||
if (skuAttrList.length > 0) |
||||
Container( |
||||
color: Colors.white, |
||||
padding: EdgeInsets.only( |
||||
top: 20.h, |
||||
bottom: 20.h, |
||||
left: 16.w, |
||||
right: 20.h), |
||||
child: Row( |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
Expanded( |
||||
child: Text( |
||||
"规格明细", |
||||
style: TextStyle( |
||||
color: Color(0xD9000000), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.bold, |
||||
), |
||||
)), |
||||
Expanded( |
||||
child: GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
bool flag = false; |
||||
String tipText = ""; |
||||
skuAttrList.forEach((element) { |
||||
if (element.specsNameController.text |
||||
.trim() == |
||||
"") { |
||||
flag = true; |
||||
tipText = "规格名称未输入,请先输入规格名称"; |
||||
return; |
||||
} else if (element.attrValueList.length == |
||||
0) { |
||||
flag = true; |
||||
tipText = "未添加规格值,请先添加规格值"; |
||||
return; |
||||
} |
||||
}); |
||||
|
||||
for (var value1 in skuAttrList) { |
||||
int index = skuAttrList.indexOf(value1); |
||||
value1.attrCode = "attr_code_$index"; |
||||
} |
||||
|
||||
if (flag) { |
||||
SmartDialog.show( |
||||
clickBgDismissTemp: false, |
||||
widget: SettlementTips( |
||||
() {}, |
||||
text: tipText, |
||||
color: Color(0xFF30415B), |
||||
)); |
||||
} else { |
||||
Navigator.of(context).pushNamed( |
||||
'/router/edit_specs_detail', |
||||
arguments: { |
||||
"skus": skuAttrList, |
||||
"skuList": skuList |
||||
}).then((value) { |
||||
if (value != null && value is List) { |
||||
skuList.clear(); |
||||
skuList.addAll(value.map((e) => e as Sku).toList()); |
||||
setState(() {}); |
||||
} |
||||
}); |
||||
} |
||||
}, |
||||
child: Row( |
||||
mainAxisAlignment: |
||||
MainAxisAlignment.end, |
||||
children: [ |
||||
Padding( |
||||
padding: |
||||
EdgeInsets.only(right: 5.w), |
||||
child: Text( |
||||
(skuList != null && |
||||
skuList.isNotEmpty) |
||||
? "已设置" |
||||
: "去设置", |
||||
style: TextStyle( |
||||
color: |
||||
(skuList != null && |
||||
skuList |
||||
.isNotEmpty) |
||||
? Color(0xA9000000) |
||||
: Color(0xD9000000), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.bold, |
||||
), |
||||
), |
||||
), |
||||
Image.asset( |
||||
"assets/image/bs_right.webp", |
||||
width: 16.h, |
||||
height: 16.h, |
||||
), |
||||
], |
||||
))) |
||||
], |
||||
), |
||||
), |
||||
], |
||||
), |
||||
)), |
||||
|
||||
///确认 |
||||
Align( |
||||
alignment: Alignment.bottomCenter, |
||||
child: GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
bool flag = false; |
||||
String tipText = ""; |
||||
List<ProductSkuAttr> skuAttrs = []; |
||||
skuAttrList.forEach((element) { |
||||
if (element.specsNameController.text.trim() == "") { |
||||
flag = true; |
||||
tipText = "规格名称未输入,请先输入规格名称"; |
||||
return; |
||||
} else if (element.attrValueList.length == 0) { |
||||
flag = true; |
||||
tipText = "未添加规格值,请先添加规格值"; |
||||
return; |
||||
} else if (skuList.length == 0) { |
||||
flag = true; |
||||
tipText = "请设置规格明细"; |
||||
return; |
||||
} |
||||
skuAttrs.add(element); |
||||
}); |
||||
if (flag) { |
||||
SmartDialog.show( |
||||
clickBgDismissTemp: false, |
||||
widget: SettlementTips( |
||||
() {}, |
||||
text: tipText, |
||||
color: Color(0xFF30415B), |
||||
)); |
||||
} else { |
||||
print("skuAttrs:$skuAttrs"); |
||||
skuList.forEach((element) { |
||||
print("skuList: ${element.toJson()}"); |
||||
}); |
||||
Navigator.of(context).pop({ |
||||
"skuAttrList": skuAttrs, |
||||
"skuList": skuList, |
||||
}); |
||||
} |
||||
}, |
||||
child: Container( |
||||
color: Colors.white, |
||||
width: double.infinity, |
||||
padding: EdgeInsets.only( |
||||
top: 10.h, left: 16.w, right: 16.w, bottom: 34.h), |
||||
child: Container( |
||||
alignment: Alignment.center, |
||||
height: 54.h, |
||||
decoration: BoxDecoration( |
||||
color: Color(0xFF30415B), |
||||
borderRadius: BorderRadius.circular(27), |
||||
), |
||||
child: Text( |
||||
"确认", |
||||
style: TextStyle( |
||||
color: Colors.white, |
||||
fontSize: 16.sp, |
||||
fontWeight: MyFontWeight.bold, |
||||
), |
||||
), |
||||
), |
||||
), |
||||
)) |
||||
], |
||||
), |
||||
)); |
||||
} |
||||
|
||||
///添加规格样式 |
||||
Widget specsText(index) { |
||||
return Container( |
||||
color: Colors.white, |
||||
margin: EdgeInsets.symmetric(vertical: 12.h), |
||||
padding: EdgeInsets.symmetric(horizontal: 16.w), |
||||
child: Column( |
||||
children: [ |
||||
Row( |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
Expanded( |
||||
child: Text( |
||||
"添加规格", |
||||
style: TextStyle( |
||||
color: Color(0xD9000000), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.bold, |
||||
), |
||||
), |
||||
), |
||||
Expanded( |
||||
child: TextField( |
||||
controller: skuAttrList[index].specsNameController, |
||||
decoration: InputDecoration( |
||||
hintText: "请输入规格名称", |
||||
hintTextDirection: TextDirection.rtl, |
||||
hintStyle: TextStyle( |
||||
color: Color(0xFF7A797F), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.bold, |
||||
), |
||||
border: InputBorder.none, |
||||
), |
||||
textAlign: TextAlign.right, |
||||
style: TextStyle( |
||||
color: Color(0xFF0D0D0D), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.bold), |
||||
), |
||||
flex: 2, |
||||
), |
||||
], |
||||
), |
||||
Container( |
||||
width: double.infinity, |
||||
height: 1.h, |
||||
color: Color(0x14000000), |
||||
), |
||||
Padding( |
||||
padding: EdgeInsets.symmetric(vertical: 16.h), |
||||
child: Row( |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
Expanded( |
||||
flex: 1, |
||||
child: Text( |
||||
"规格植", |
||||
style: TextStyle( |
||||
color: Color(0xD9000000), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.bold, |
||||
), |
||||
), |
||||
), |
||||
Expanded( |
||||
child: GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
Navigator.of(context).pushNamed( |
||||
'/router/set_goods_specs_value', |
||||
arguments: { |
||||
"storeId": "", |
||||
"attrCode": skuAttrList[index].attrCode, |
||||
"attrValues": skuAttrList[index].attrValueList |
||||
}).then((value) { |
||||
if (value != null && value is Map && value["attrValues"] is List<String>) { |
||||
String code = value["attrCode"]; |
||||
List<String> attrValues = value["attrValues"]; |
||||
print("value: $value"); |
||||
setState(() { |
||||
skuAttrList[index].attrValueList = attrValues.map((e) { |
||||
int index = attrValues.indexOf(e); |
||||
var product = ProductSkuAttrValue(); |
||||
product.attrValue = e; |
||||
product.attrValueCode = "${code}_value_$index"; |
||||
return product; |
||||
}).toList(); |
||||
}); |
||||
} |
||||
}); |
||||
}, |
||||
child: Row( |
||||
mainAxisAlignment: MainAxisAlignment.end, |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
children: [ |
||||
Expanded( |
||||
child: Text( |
||||
skuAttrList[index].attrValueList.length != 0 |
||||
? skuAttrList[index] |
||||
.attrValueList |
||||
.map((e) => e.attrValue) |
||||
.toString() |
||||
.replaceAll("(", "") |
||||
.replaceAll(")", "") |
||||
: "请添加规格值", |
||||
overflow: TextOverflow.ellipsis, |
||||
maxLines: 1, |
||||
textAlign: TextAlign.end, |
||||
style: TextStyle( |
||||
color: Color(0xFF7A797F), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.bold, |
||||
), |
||||
)), |
||||
Image.asset( |
||||
"assets/image/bs_right.webp", |
||||
width: 16.h, |
||||
height: 16.h, |
||||
), |
||||
], |
||||
), |
||||
), |
||||
flex: 2, |
||||
), |
||||
], |
||||
)), |
||||
Container( |
||||
width: double.infinity, |
||||
height: 1.h, |
||||
color: Color(0x14000000), |
||||
margin: EdgeInsets.only(bottom: 18.h), |
||||
), |
||||
GestureDetector( |
||||
onTap: () { |
||||
setState(() { |
||||
skuAttrList.removeAt(index); |
||||
}); |
||||
}, |
||||
child: Padding( |
||||
padding: EdgeInsets.only(bottom: 20.h), |
||||
child: Row( |
||||
mainAxisAlignment: MainAxisAlignment.end, |
||||
children: [ |
||||
Icon( |
||||
Icons.remove_circle, |
||||
color: Color(0xFFFA5151), |
||||
size: 24, |
||||
), |
||||
Padding( |
||||
padding: EdgeInsets.only(left: 7.w), |
||||
child: Text( |
||||
"删除", |
||||
style: TextStyle( |
||||
color: Color(0xD9000000), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.bold, |
||||
), |
||||
), |
||||
), |
||||
], |
||||
)), |
||||
) |
||||
], |
||||
), |
||||
); |
||||
} |
||||
} |
@ -1,252 +0,0 @@
|
||||
import 'package:flutter/material.dart'; |
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; |
||||
import 'package:huixiang/business_system/goods/add_goods/data/product_sku_attr.dart'; |
||||
import 'package:huixiang/view_widget/my_appbar.dart'; |
||||
import 'package:flutter_screenutil/flutter_screenutil.dart'; |
||||
import '../../../retrofit/business_api.dart'; |
||||
import '../../../retrofit/data/set_specs_list.dart'; |
||||
import '../../../retrofit/data/set_specs_value_list.dart'; |
||||
import '../../../utils/font_weight.dart'; |
||||
import '../../../view_widget/settlement_tips_dialog.dart'; |
||||
|
||||
/// 设置商品规格明细 |
||||
class SetGoodsSpecsValue extends StatefulWidget { |
||||
final Map<String, dynamic> arguments; |
||||
|
||||
SetGoodsSpecsValue({this.arguments}); |
||||
|
||||
@override |
||||
State<StatefulWidget> createState() { |
||||
return _SetGoodsSpecsValue(); |
||||
} |
||||
} |
||||
|
||||
class _SetGoodsSpecsValue extends State<SetGoodsSpecsValue> { |
||||
List<ProductSkuAttrValue> attrValues = []; |
||||
String attrCode; |
||||
bool isKeyBoardShow = false; |
||||
FocusNode _focusNode = FocusNode(); |
||||
BusinessApiService businessService; |
||||
|
||||
@override |
||||
void initState() { |
||||
super.initState(); |
||||
WidgetsBinding.instance.addPostFrameCallback((_) { |
||||
setState(() { |
||||
print("object: ${MediaQuery.of(context).viewInsets.bottom}"); |
||||
if (MediaQuery.of(context).viewInsets.bottom == 0) { |
||||
if (isKeyBoardShow) { |
||||
isKeyBoardShow = false; |
||||
//关闭键盘 软键盘关闭了, 清除输入控件的焦点, 否则重新进入页面会导致软键盘再弹出问题 |
||||
FocusScope.of(context).requestFocus(FocusNode()); |
||||
} |
||||
} else { |
||||
isKeyBoardShow = true; |
||||
} |
||||
}); |
||||
}); |
||||
attrValues = widget.arguments["attrValues"] ?? []; |
||||
attrCode = widget.arguments["attrCode"] ?? ""; |
||||
print("arguments: ${widget.arguments}"); |
||||
attrValues.forEach((element) { |
||||
element.specsValueNameController.text = element.attrValue; |
||||
}); |
||||
} |
||||
|
||||
///离开页面记着销毁和清除 |
||||
@override |
||||
void dispose() { |
||||
_focusNode.unfocus(); |
||||
super.dispose(); |
||||
} |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
FocusScope.of(context).unfocus(); |
||||
}, |
||||
child: Scaffold( |
||||
resizeToAvoidBottomInset: false, |
||||
appBar: MyAppBar( |
||||
title: "设置商品规格值", |
||||
titleColor: Colors.black, |
||||
background: Colors.white, |
||||
leadingColor: Colors.black, |
||||
brightness: Brightness.dark, |
||||
), |
||||
body: Stack( |
||||
children: [ |
||||
SingleChildScrollView( |
||||
physics: BouncingScrollPhysics(), |
||||
child: Container( |
||||
margin: EdgeInsets.only(bottom: 150.h), |
||||
child: Column( |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Container( |
||||
color: Colors.white, |
||||
child: ListView.builder( |
||||
padding: EdgeInsets.zero, |
||||
itemCount: attrValues.length, |
||||
scrollDirection: Axis.vertical, |
||||
shrinkWrap: true, |
||||
physics: BouncingScrollPhysics(), |
||||
itemBuilder: (context, position) { |
||||
return GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
setState(() {}); |
||||
}, |
||||
child: specsValueText(position)); |
||||
}, |
||||
)), |
||||
GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
setState(() { |
||||
attrValues.add(ProductSkuAttrValue()); |
||||
FocusScope.of(context).unfocus(); |
||||
}); |
||||
}, |
||||
child: Container( |
||||
color: Colors.white, |
||||
padding: EdgeInsets.symmetric(vertical: 20.h), |
||||
margin: EdgeInsets.only(top: 12.h), |
||||
child: Row( |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
Icon( |
||||
Icons.add_circle, |
||||
color: Color(0xFF30415B), |
||||
size: 20, |
||||
), |
||||
Padding( |
||||
padding: EdgeInsets.only(left: 7.w), |
||||
child: Text( |
||||
"添加规格值", |
||||
style: TextStyle( |
||||
color: Color(0xD9000000), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.bold, |
||||
), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
)), |
||||
|
||||
///确认 |
||||
Align( |
||||
alignment: Alignment.bottomCenter, |
||||
child: GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
if (attrValues.any((element) => element.specsValueNameController.text == "")) { |
||||
SmartDialog.show( |
||||
clickBgDismissTemp: false, |
||||
widget: SettlementTips( |
||||
() {}, |
||||
text: "还有规格未输入值,请输入完整", |
||||
color: Color(0xFF30415B), |
||||
)); |
||||
return; |
||||
} |
||||
List<String> values = attrValues.map((element) { |
||||
return element.specsValueNameController.text; |
||||
}).toList(); |
||||
Navigator.of(context).pop({ |
||||
"attrCode": attrCode, |
||||
"attrValues": values, |
||||
}); |
||||
}, |
||||
child: Container( |
||||
color: Colors.white, |
||||
width: double.infinity, |
||||
padding: EdgeInsets.only( |
||||
top: 10.h, left: 16.w, right: 16.w, bottom: 34.h), |
||||
child: Container( |
||||
alignment: Alignment.center, |
||||
height: 54.h, |
||||
decoration: BoxDecoration( |
||||
color: Color(0xFF30415B), |
||||
borderRadius: BorderRadius.circular(27), |
||||
), |
||||
child: Text( |
||||
"确认", |
||||
style: TextStyle( |
||||
color: Colors.white, |
||||
fontSize: 16.sp, |
||||
fontWeight: MyFontWeight.bold, |
||||
), |
||||
), |
||||
), |
||||
), |
||||
)) |
||||
], |
||||
), |
||||
)); |
||||
} |
||||
|
||||
///添加规格样式 |
||||
Widget specsValueText(index) { |
||||
return Container( |
||||
padding: EdgeInsets.symmetric(horizontal: 16.w), |
||||
child: Column( |
||||
children: [ |
||||
Row( |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
GestureDetector( |
||||
onTap: () { |
||||
setState(() { |
||||
attrValues.removeAt(index); |
||||
}); |
||||
}, |
||||
child: Container( |
||||
padding: EdgeInsets.only(right: 12.w), |
||||
child: Icon( |
||||
Icons.remove_circle, |
||||
color: Color(0xFFFA5151), |
||||
size: 24, |
||||
), |
||||
), |
||||
), |
||||
Expanded( |
||||
child: TextField( |
||||
controller: attrValues[index].specsValueNameController, |
||||
decoration: InputDecoration( |
||||
hintText: "请输入规格值名称", |
||||
hintStyle: TextStyle( |
||||
color: Color(0xFF7A797F), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
border: InputBorder.none, |
||||
), |
||||
style: TextStyle( |
||||
color: Color(0xFF0D0D0D), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.bold), |
||||
), |
||||
flex: 2, |
||||
), |
||||
], |
||||
), |
||||
if (attrValues.length - 1 > index) |
||||
Container( |
||||
width: double.infinity, |
||||
height: 1.h, |
||||
color: Color(0x14000000), |
||||
), |
||||
], |
||||
), |
||||
); |
||||
} |
||||
} |
@ -1,636 +0,0 @@
|
||||
import 'package:flutter/material.dart'; |
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; |
||||
import 'package:huixiang/view_widget/my_appbar.dart'; |
||||
import 'package:flutter_screenutil/flutter_screenutil.dart'; |
||||
import '../../../generated/l10n.dart'; |
||||
import '../../../retrofit/business_api.dart'; |
||||
import '../../../retrofit/data/set_specs_meal_list.dart'; |
||||
import '../../../utils/font_weight.dart'; |
||||
import '../../../view_widget/border_text.dart'; |
||||
import '../../../view_widget/round_button.dart'; |
||||
import '../../../view_widget/settlement_tips_dialog.dart'; |
||||
|
||||
class SetMeal extends StatefulWidget { |
||||
final Map<String, dynamic> arguments; |
||||
|
||||
SetMeal({this.arguments}); |
||||
|
||||
@override |
||||
State<StatefulWidget> createState() { |
||||
return _SetMeal(); |
||||
} |
||||
} |
||||
|
||||
class _SetMeal extends State<SetMeal> { |
||||
List<SetSpecsMealList> specsMeal = []; |
||||
bool isKeyBoardShow = false; |
||||
FocusNode _focusNode = FocusNode(); |
||||
BusinessApiService businessService; |
||||
|
||||
@override |
||||
void initState() { |
||||
super.initState(); |
||||
WidgetsBinding.instance.addPostFrameCallback((_) { |
||||
setState(() { |
||||
print("object: ${MediaQuery.of(context).viewInsets.bottom}"); |
||||
if (MediaQuery.of(context).viewInsets.bottom == 0) { |
||||
if (isKeyBoardShow) { |
||||
isKeyBoardShow = false; |
||||
//关闭键盘 软键盘关闭了, 清除输入控件的焦点, 否则重新进入页面会导致软键盘再弹出问题 |
||||
FocusScope.of(context).requestFocus(FocusNode()); |
||||
} |
||||
} else { |
||||
isKeyBoardShow = true; |
||||
} |
||||
}); |
||||
}); |
||||
List<dynamic> mealDetails = widget?.arguments["mealDetails"] ??[]; |
||||
mealDetails.forEach((element) { |
||||
var tempValue = SetSpecsMealList(); |
||||
tempValue.groupsNameController.text = element["groupName"]; |
||||
tempValue.groupsTotal = element["totalNumber"]; |
||||
tempValue.optionalNum = element["optionalNumber"]; |
||||
tempValue.goodsMeal = element["productInfoList"]; |
||||
specsMeal.add(tempValue); |
||||
}); |
||||
} |
||||
|
||||
///离开页面记着销毁和清除 |
||||
@override |
||||
void dispose() { |
||||
_focusNode.unfocus(); |
||||
super.dispose(); |
||||
} |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
FocusScope.of(context).unfocus(); |
||||
}, |
||||
child: Scaffold( |
||||
resizeToAvoidBottomInset: false, |
||||
appBar: MyAppBar( |
||||
title: "套餐选择", |
||||
titleColor: Colors.black, |
||||
background: Colors.white, |
||||
leadingColor: Colors.black, |
||||
brightness: Brightness.dark, |
||||
action: GestureDetector( |
||||
onTap: () { |
||||
bool flag = false; |
||||
String tipText = ""; |
||||
int index = 0; |
||||
List<dynamic> mealDetail = []; |
||||
if (specsMeal.length != 0) { |
||||
specsMeal.forEach((element) { |
||||
index += 1; |
||||
if (element.groupsNameController.text.trim() == "") { |
||||
flag = true; |
||||
tipText = "分组$index未填写分组名"; |
||||
return; |
||||
} else if (element.goodsMeal.length == 0 || |
||||
element.goodsMeal.length != element.groupsTotal) { |
||||
flag = true; |
||||
tipText = |
||||
"分组${element.groupsNameController.text}已选商品数量与设定分组总数不符,请修改"; |
||||
return; |
||||
} else if (element.optionalNum > element.groupsTotal) { |
||||
flag = true; |
||||
tipText = |
||||
"分组${element.groupsNameController.text}可选数量不可大于分组总数"; |
||||
return; |
||||
} |
||||
mealDetail.add({ |
||||
"groupName": element.groupsNameController.text, |
||||
"totalNumber":element.groupsTotal, |
||||
"optionalNumber":element.optionalNum, |
||||
"productInfoList":element.goodsMeal |
||||
}); |
||||
}); |
||||
if (flag) { |
||||
SmartDialog.show( |
||||
clickBgDismissTemp: false, |
||||
widget: SettlementTips( |
||||
() {}, |
||||
text: tipText, |
||||
color: Color(0xFF30415B), |
||||
)); |
||||
} else { |
||||
Navigator.of(context).pop(mealDetail); |
||||
} |
||||
} else { |
||||
SmartDialog.show( |
||||
clickBgDismissTemp: false, |
||||
widget: SettlementTips( |
||||
() {}, |
||||
text: "请添加设置分组后再点击确实按钮", |
||||
color: Color(0xFF30415B), |
||||
)); |
||||
} |
||||
}, |
||||
child: Text( |
||||
"确定", |
||||
style: TextStyle( |
||||
color: Color(0xFF30415B), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.bold, |
||||
), |
||||
), |
||||
), |
||||
), |
||||
body: Stack( |
||||
children: [ |
||||
SingleChildScrollView( |
||||
physics: BouncingScrollPhysics(), |
||||
child: Container( |
||||
margin: EdgeInsets.only(bottom: 150.h), |
||||
child: Column( |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
ListView.builder( |
||||
padding: EdgeInsets.zero, |
||||
itemCount: specsMeal.length, |
||||
scrollDirection: Axis.vertical, |
||||
shrinkWrap: true, |
||||
physics: BouncingScrollPhysics(), |
||||
itemBuilder: (context, position) { |
||||
return GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
FocusScope.of(context).unfocus(); |
||||
}, |
||||
child: mealText(position)); |
||||
}, |
||||
), |
||||
GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
setState(() { |
||||
specsMeal.add(SetSpecsMealList()); |
||||
}); |
||||
}, |
||||
child: Container( |
||||
color: Colors.white, |
||||
padding: EdgeInsets.symmetric(vertical: 20.h), |
||||
child: Row( |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
Icon( |
||||
Icons.add_circle, |
||||
color: Color(0xFF30415B), |
||||
size: 20, |
||||
), |
||||
Padding( |
||||
padding: EdgeInsets.only(left: 7.w), |
||||
child: Text( |
||||
"添加分组", |
||||
style: TextStyle( |
||||
color: Color(0xD9000000), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.bold, |
||||
), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
)), |
||||
], |
||||
), |
||||
)); |
||||
} |
||||
|
||||
///添加套餐分组样式 |
||||
Widget mealText(index) { |
||||
return Column( |
||||
children: [ |
||||
Container( |
||||
color: Colors.white, |
||||
margin: EdgeInsets.symmetric(vertical: 12.h), |
||||
padding: EdgeInsets.only(left: 16.w, right: 16.w, bottom: 12.h), |
||||
child: Column( |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Row( |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
Expanded( |
||||
child: Text( |
||||
"分组${index + 1}", |
||||
style: TextStyle( |
||||
color: Color(0xD9000000), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.bold, |
||||
), |
||||
), |
||||
), |
||||
Expanded( |
||||
child: TextField( |
||||
controller: specsMeal[index].groupsNameController, |
||||
decoration: InputDecoration( |
||||
hintText: "请输入分组名称", |
||||
hintTextDirection: TextDirection.rtl, |
||||
hintStyle: TextStyle( |
||||
color: Color(0xFF7A797F), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.bold, |
||||
), |
||||
border: InputBorder.none, |
||||
), |
||||
textAlign: TextAlign.right, |
||||
style: TextStyle( |
||||
color: Color(0xFF0D0D0D), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.bold), |
||||
), |
||||
flex: 2, |
||||
), |
||||
], |
||||
), |
||||
Container( |
||||
width: double.infinity, |
||||
height: 1.h, |
||||
color: Color(0x14000000), |
||||
), |
||||
Padding( |
||||
padding: EdgeInsets.symmetric(vertical: 14.h), |
||||
child: Row( |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
Expanded( |
||||
child: Text( |
||||
"分组总数", |
||||
style: TextStyle( |
||||
color: Color(0xD9000000), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.bold, |
||||
), |
||||
), |
||||
), |
||||
GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
setState(() { |
||||
if (specsMeal[index].groupsTotal <= 1) return; |
||||
specsMeal[index].groupsTotal = |
||||
specsMeal[index].groupsTotal - 1; |
||||
}); |
||||
}, |
||||
child: Container( |
||||
padding: EdgeInsets.symmetric(horizontal: 20.w), |
||||
child: Icon( |
||||
Icons.remove_circle_outline, |
||||
color: Color(0xFF30415B), |
||||
size: 24, |
||||
))), |
||||
Text( |
||||
specsMeal[index].groupsTotal.toString(), |
||||
style: TextStyle( |
||||
color: Color(0xD9000000), |
||||
fontSize: 20.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
), |
||||
GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
setState(() { |
||||
specsMeal[index].groupsTotal = |
||||
specsMeal[index].groupsTotal + 1; |
||||
}); |
||||
}, |
||||
child: Container( |
||||
padding: EdgeInsets.only(left: 20.w), |
||||
child: Icon( |
||||
Icons.add_circle, |
||||
color: Color(0xFF30415B), |
||||
size: 24, |
||||
)), |
||||
), |
||||
], |
||||
)), |
||||
Container( |
||||
width: double.infinity, |
||||
height: 1.h, |
||||
color: Color(0x14000000), |
||||
margin: EdgeInsets.only(bottom: 18.h), |
||||
), |
||||
Padding( |
||||
padding: EdgeInsets.only(bottom: 14.h), |
||||
child: Row( |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
Expanded( |
||||
child: Text( |
||||
"可选数量", |
||||
style: TextStyle( |
||||
color: Color(0xD9000000), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.bold, |
||||
), |
||||
), |
||||
), |
||||
GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
setState(() { |
||||
if (specsMeal[index].optionalNum <= 1) return; |
||||
specsMeal[index].optionalNum = |
||||
specsMeal[index].optionalNum - 1; |
||||
}); |
||||
}, |
||||
child: Container( |
||||
padding: EdgeInsets.symmetric(horizontal: 20.w), |
||||
child: Icon( |
||||
Icons.remove_circle_outline, |
||||
color: Color(0xFF30415B), |
||||
size: 24, |
||||
))), |
||||
Text( |
||||
specsMeal[index].optionalNum.toString(), |
||||
style: TextStyle( |
||||
color: Color(0xD9000000), |
||||
fontSize: 20.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
), |
||||
GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
setState(() { |
||||
specsMeal[index].optionalNum = |
||||
specsMeal[index].optionalNum + 1; |
||||
}); |
||||
}, |
||||
child: Container( |
||||
padding: EdgeInsets.only(left: 20.w), |
||||
child: Icon( |
||||
Icons.add_circle, |
||||
color: Color(0xFF30415B), |
||||
size: 24, |
||||
)), |
||||
), |
||||
], |
||||
)), |
||||
Container( |
||||
width: double.infinity, |
||||
height: 1.h, |
||||
color: Color(0x14000000), |
||||
margin: EdgeInsets.only(bottom: 18.h), |
||||
), |
||||
Padding( |
||||
padding: EdgeInsets.only(bottom: 12.h), |
||||
child: Row( |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
Navigator.of(context).pushNamed('/router/batch_shelf', |
||||
arguments: { |
||||
"storeId": widget.arguments["storeId"], |
||||
"titleName": "选择商品", |
||||
"groupNum": specsMeal[index].groupsTotal |
||||
}).then((value) { |
||||
if (value != null && value is List) { |
||||
if (specsMeal[index].goodsMeal == null) { |
||||
specsMeal[index].goodsMeal = []; |
||||
} |
||||
specsMeal[index].goodsMeal.clear(); |
||||
specsMeal[index].goodsMeal.addAll(value.map((e) => e as Map<String, dynamic>).toList()); |
||||
setState(() {}); |
||||
} |
||||
}); |
||||
}, |
||||
child: Container( |
||||
alignment: Alignment.center, |
||||
padding: EdgeInsets.only( |
||||
left: 8.w, right: 8.w, bottom: 3.h), |
||||
decoration: BoxDecoration( |
||||
color: Colors.white, |
||||
border: Border.all( |
||||
color: Color(0xFF2E3552), |
||||
width: 1, |
||||
), |
||||
borderRadius: BorderRadius.circular(100), |
||||
), |
||||
child: Text( |
||||
"+增加商品", |
||||
style: TextStyle( |
||||
color: Color(0xFF30415B), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
), |
||||
)), |
||||
Spacer(), |
||||
GestureDetector( |
||||
onTap: () { |
||||
deleteGroupsDialog(index); |
||||
}, |
||||
child: Row( |
||||
mainAxisAlignment: MainAxisAlignment.end, |
||||
children: [ |
||||
Icon( |
||||
Icons.remove_circle, |
||||
color: Color(0xFFFA5151), |
||||
size: 24, |
||||
), |
||||
Padding( |
||||
padding: EdgeInsets.only(left: 7.w), |
||||
child: Text( |
||||
"删除分组", |
||||
style: TextStyle( |
||||
color: Color(0xD9000000), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.bold, |
||||
), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
) |
||||
], |
||||
), |
||||
), |
||||
Text( |
||||
"*请添加或减少商品,直到达到分组总数", |
||||
style: TextStyle( |
||||
color: Color(0xFFFA5151), |
||||
fontSize: 12.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
ListView.builder( |
||||
itemCount: specsMeal[index]?.goodsMeal?.length ?? 0, |
||||
physics: BouncingScrollPhysics(), |
||||
shrinkWrap: true, |
||||
itemBuilder: (context, position) { |
||||
return GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () {}, |
||||
child: addGoodsItem(index, position), |
||||
); |
||||
}, |
||||
) |
||||
], |
||||
); |
||||
} |
||||
|
||||
///删除分组弹窗提示 |
||||
deleteGroupsDialog(index) { |
||||
showDialog( |
||||
context: context, |
||||
builder: (context) { |
||||
return AlertDialog( |
||||
content: Container( |
||||
width: MediaQuery.of(context).size.width - 84, |
||||
height: 139.h, |
||||
child: Column( |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
children: [ |
||||
Text( |
||||
"此操作将直接删除当前分组, 是否继续?", |
||||
style: TextStyle( |
||||
color: Color(0xFFF4524D), |
||||
fontSize: 16.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
), |
||||
SizedBox( |
||||
height: 35.h, |
||||
), |
||||
Row( |
||||
children: [ |
||||
Expanded( |
||||
child: InkWell( |
||||
child: BorderText( |
||||
text: S.of(context).quxiao, |
||||
textColor: Color(0xFF30415B), |
||||
fontSize: 16.sp, |
||||
fontWeight: FontWeight.bold, |
||||
borderColor: Color(0xFF30415B), |
||||
radius: 4, |
||||
padding: EdgeInsets.all(12), |
||||
borderWidth: 1, |
||||
), |
||||
onTap: () { |
||||
Navigator.of(context).pop(); |
||||
}, |
||||
), |
||||
flex: 1, |
||||
), |
||||
SizedBox( |
||||
width: 16.w, |
||||
), |
||||
Expanded( |
||||
child: InkWell( |
||||
child: RoundButton( |
||||
text: S.of(context).queren, |
||||
textColor: Colors.white, |
||||
radius: 4, |
||||
padding: EdgeInsets.all(12), |
||||
backgroup: Color(0xFF30415B), |
||||
fontSize: 16.sp, |
||||
fontWeight: FontWeight.bold, |
||||
), |
||||
onTap: () { |
||||
setState((){ |
||||
Navigator.of(context).pop(); |
||||
specsMeal.removeAt(index); |
||||
}); |
||||
}, |
||||
), |
||||
flex: 1, |
||||
), |
||||
], |
||||
) |
||||
], |
||||
), |
||||
), |
||||
); |
||||
}, |
||||
); |
||||
} |
||||
|
||||
///增加商品Item |
||||
Widget addGoodsItem(specsIndex, index) { |
||||
return Container( |
||||
color: Colors.white, |
||||
margin: EdgeInsets.symmetric(vertical: 8), |
||||
padding: EdgeInsets.only( |
||||
left: 16.w, |
||||
top: 20.h, |
||||
bottom: 20.h, |
||||
), |
||||
child: Row( |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
Expanded( |
||||
child: Text( |
||||
specsMeal[specsIndex]?.goodsMeal[index]["productName"] ?? "", |
||||
maxLines: 1, |
||||
overflow: TextOverflow.ellipsis, |
||||
style: TextStyle( |
||||
color: Color(0xFF000000), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
), |
||||
flex: 2, |
||||
), |
||||
Expanded( |
||||
child: Text( |
||||
"所有规格", |
||||
textAlign: TextAlign.center, |
||||
style: TextStyle( |
||||
color: Color(0xFF000000), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
), |
||||
), |
||||
Expanded( |
||||
child: Text( |
||||
specsMeal[specsIndex]?.goodsMeal[index]["number"] ?? "", |
||||
textAlign: TextAlign.center, |
||||
style: TextStyle( |
||||
color: Color(0xFF000000), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
)), |
||||
GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
setState(() { |
||||
specsMeal[specsIndex].goodsMeal.removeAt(index); |
||||
}); |
||||
}, |
||||
child: Container( |
||||
padding: EdgeInsets.only(right: 31.h), |
||||
child: Icon( |
||||
Icons.remove_circle, |
||||
color: Color(0xFFFA5151), |
||||
size: 20, |
||||
), |
||||
), |
||||
) |
||||
], |
||||
), |
||||
); |
||||
} |
||||
} |
@ -1,131 +0,0 @@
|
||||
import 'package:flutter/cupertino.dart'; |
||||
import 'package:flutter/material.dart'; |
||||
import 'package:pull_to_refresh/pull_to_refresh.dart'; |
||||
import 'package:flutter_screenutil/flutter_screenutil.dart'; |
||||
|
||||
import '../../utils/font_weight.dart'; |
||||
import '../../view_widget/my_appbar.dart'; |
||||
import '../../view_widget/my_tab.dart'; |
||||
import '../order/ticket/ticket_tab.dart'; |
||||
import 'off_shelf/off_shelf_page.dart'; |
||||
import 'on_sale/on_sale_page.dart'; |
||||
|
||||
class BusinessGoodsPage extends StatefulWidget { |
||||
final String storeId; |
||||
|
||||
BusinessGoodsPage(Key key,this.storeId): super(key: key); |
||||
|
||||
@override |
||||
State<StatefulWidget> createState() { |
||||
return _BusinessGoodsPage(); |
||||
} |
||||
} |
||||
|
||||
class _BusinessGoodsPage extends State<BusinessGoodsPage> { |
||||
final RefreshController refreshController = RefreshController(); |
||||
String offShelfTotal; |
||||
String onSaleTotal; |
||||
int goodsIndex = 0; |
||||
|
||||
@override |
||||
void initState() { |
||||
super.initState(); |
||||
} |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return Column( |
||||
children: [ |
||||
Expanded( |
||||
child: |
||||
DefaultTabController( |
||||
length: 3, |
||||
child: Scaffold( |
||||
appBar: MyAppBar( |
||||
title:"", |
||||
leading: false, |
||||
background: Colors.white, |
||||
toolbarHeight: MediaQuery.of(context).size.height >= 750 ? (kToolbarHeight + 15.h) : kToolbarHeight, |
||||
bottom: TabBar( |
||||
// isScrollable: true, //可滚动 |
||||
//去掉按钮阴影 |
||||
overlayColor: MaterialStateProperty.all(Colors.white), |
||||
indicatorColor: Color(0xFF30415B), |
||||
labelColor: Colors.black, |
||||
labelStyle: TextStyle( |
||||
fontSize: 15.sp, |
||||
fontWeight: FontWeight.bold, |
||||
), |
||||
unselectedLabelStyle: TextStyle( |
||||
fontSize: 15.sp, |
||||
fontWeight: FontWeight.normal, |
||||
color: Color(0xFF666666) |
||||
), |
||||
indicator: const TicketTab( |
||||
width: 33, |
||||
borderSide: BorderSide( |
||||
width: 2.0, color: Color(0xFF30415B))), |
||||
// controller: tabController, |
||||
//未选中文字颜色 |
||||
unselectedLabelColor: Color(0xffA29E9E), |
||||
indicatorSize: TabBarIndicatorSize.label, |
||||
//指示器与文字等宽 |
||||
tabs: <Widget>[ |
||||
MyTab(text:"在售中(${onSaleTotal ?? "0"})"), |
||||
MyTab(text: "已下架(${offShelfTotal ?? "0"})"), |
||||
GestureDetector( |
||||
onTap: (){ |
||||
Navigator.of(context).pushNamed( |
||||
'/router/add_goods_page', |
||||
arguments: { |
||||
"storeId":widget.storeId ?? "", |
||||
}); |
||||
}, |
||||
child:Row(children: [Padding( |
||||
padding: EdgeInsets.only(right: 5.w), |
||||
child: Text( |
||||
"新增商品", |
||||
textAlign: TextAlign.center, |
||||
style: TextStyle( |
||||
height: 1.5, |
||||
color: Color(0xFF2E3552), |
||||
fontSize: 16.sp, |
||||
fontWeight: MyFontWeight.bold, |
||||
), |
||||
)), Image.asset( |
||||
"assets/image/bus_goods_add.webp", |
||||
width: 14.w, |
||||
height: 15.h, |
||||
), |
||||
]), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
body: TabBarView( |
||||
physics: NeverScrollableScrollPhysics(), |
||||
children: [ |
||||
OnSalePage(widget.storeId,(value){ |
||||
setState((){ |
||||
onSaleTotal = value; |
||||
}); |
||||
}), |
||||
OffShelfPage(widget.storeId,(value){ |
||||
setState((){ |
||||
offShelfTotal = value; |
||||
}); |
||||
}), |
||||
Container() |
||||
], |
||||
), |
||||
), |
||||
), |
||||
), |
||||
SizedBox( |
||||
height: 76.h, |
||||
), |
||||
], |
||||
); |
||||
} |
||||
|
||||
} |
@ -1,680 +0,0 @@
|
||||
import 'package:dio/dio.dart'; |
||||
import 'package:flutter/material.dart'; |
||||
import 'package:flutter_easyloading/flutter_easyloading.dart'; |
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; |
||||
import 'package:huixiang/retrofit/data/findMiNiGroupList.dart'; |
||||
import 'package:huixiang/utils/font_weight.dart'; |
||||
import 'package:huixiang/view_widget/classic_header.dart'; |
||||
import 'package:flutter_screenutil/flutter_screenutil.dart'; |
||||
import 'package:pull_to_refresh/pull_to_refresh.dart'; |
||||
import 'package:shimmer/shimmer.dart'; |
||||
import '../../generated/l10n.dart'; |
||||
import '../../retrofit/business_api.dart'; |
||||
import '../../retrofit/data/base_data.dart'; |
||||
import '../../retrofit/data/business_goods.dart'; |
||||
import '../../utils/business_instance.dart'; |
||||
import '../../utils/flutter_utils.dart'; |
||||
import '../../view_widget/border_text.dart'; |
||||
import '../../view_widget/custom_image.dart'; |
||||
import '../../view_widget/my_appbar.dart'; |
||||
import '../../view_widget/my_footer.dart'; |
||||
import '../../view_widget/no_data_view.dart'; |
||||
import '../../view_widget/round_button.dart'; |
||||
|
||||
class GoodsSearchPage extends StatefulWidget { |
||||
final Map<String, dynamic> arguments; |
||||
|
||||
GoodsSearchPage({this.arguments}); |
||||
|
||||
@override |
||||
State<StatefulWidget> createState() { |
||||
return _GoodsSearchPage(); |
||||
} |
||||
} |
||||
|
||||
class _GoodsSearchPage extends State<GoodsSearchPage> |
||||
with WidgetsBindingObserver { |
||||
final TextEditingController editingController = TextEditingController(); |
||||
final RefreshController refreshController = RefreshController(); |
||||
final ScrollController scrollController = ScrollController(); |
||||
int optionIndex = 0; |
||||
bool isKeyBoardShow = false; |
||||
List<ProductListBean> productListBeans = []; |
||||
List<String> hotSearch = []; |
||||
List<String> historySearch = []; |
||||
FocusNode _focusNode = FocusNode(); |
||||
bool hasFocus = true; |
||||
int priceOrder = 0; |
||||
int _pageIndex = 1; |
||||
BusinessApiService businessService; |
||||
List<AdminProductVoList> adminProductVoList = []; |
||||
String networkError = ""; |
||||
int networkStatus = 0; |
||||
|
||||
@override |
||||
void didChangeMetrics() { |
||||
super.didChangeMetrics(); |
||||
WidgetsBinding.instance.addPostFrameCallback((_) { |
||||
setState(() { |
||||
print("object: ${MediaQuery.of(context).viewInsets.bottom}"); |
||||
if (MediaQuery.of(context).viewInsets.bottom == 0) { |
||||
if (isKeyBoardShow) { |
||||
isKeyBoardShow = false; |
||||
//关闭键盘 软键盘关闭了, 清除输入控件的焦点, 否则重新进入页面会导致软键盘再弹出问题 |
||||
FocusScope.of(context).requestFocus(FocusNode()); |
||||
} |
||||
} else { |
||||
isKeyBoardShow = true; |
||||
} |
||||
}); |
||||
}); |
||||
} |
||||
|
||||
///离开页面记着销毁和清除 |
||||
@override |
||||
void dispose() { |
||||
_focusNode.unfocus(); |
||||
super.dispose(); |
||||
} |
||||
|
||||
@override |
||||
void initState() { |
||||
super.initState(); |
||||
_focusNode.addListener(() { |
||||
setState(() { |
||||
hasFocus = _focusNode.hasFocus; |
||||
}); |
||||
}); |
||||
_onRefresh(); |
||||
} |
||||
|
||||
_onRefresh({bool isShowLoad = true}) async { |
||||
if (isShowLoad) |
||||
EasyLoading.show( |
||||
status: S.current.zhengzaijiazai, |
||||
maskType: EasyLoadingMaskType.black); |
||||
await queryGoodsList(); |
||||
EasyLoading.dismiss(); |
||||
if (!mounted) return; |
||||
if (refreshController.isRefresh) refreshController.refreshCompleted(); |
||||
setState(() {}); |
||||
} |
||||
|
||||
///商品列表 |
||||
queryGoodsList() async { |
||||
if (businessService == null) { |
||||
businessService = BusinessApiService(Dio(), |
||||
context: context, |
||||
token: BusinessInstance.instance.businessToken, |
||||
tenant: BusinessInstance.instance.businessTenant, |
||||
storeId: widget.arguments["storeId"]); |
||||
} |
||||
BaseData<BusinessGoods> baseData = |
||||
await businessService.findAdminProductLis({ |
||||
"groupId": "", |
||||
"hasStock": "", |
||||
"keyword": editingController?.text ?? "", |
||||
"pageIndex": _pageIndex, |
||||
"pageSize": 10, |
||||
"status": widget.arguments["onSaleStatus"], |
||||
}).catchError((error) { |
||||
networkError = AppUtils.dioErrorTypeToString(error.type); |
||||
networkStatus = -1; |
||||
setState(() {}); |
||||
refreshController.refreshFailed(); |
||||
refreshController.loadFailed(); |
||||
}); |
||||
if (!mounted) return; |
||||
if (baseData != null && baseData.isSuccess) { |
||||
adminProductVoList.addAll(baseData?.data?.adminProductVOList ?? []); |
||||
if ((baseData?.data?.adminProductVOList ?? []).isEmpty || |
||||
adminProductVoList.length == baseData.data.total) |
||||
refreshController.loadNoData(); |
||||
else |
||||
refreshController.loadComplete(); |
||||
networkStatus = 1; |
||||
} else { |
||||
SmartDialog.showToast(baseData.msg, alignment: Alignment.center); |
||||
} |
||||
} |
||||
|
||||
///商品下架 |
||||
queryGoodsUpdate(productId) async { |
||||
try { |
||||
EasyLoading.show( |
||||
status: S.current.zhengzaijiazai, |
||||
maskType: EasyLoadingMaskType.black); |
||||
if (businessService == null) { |
||||
businessService = BusinessApiService(Dio(), |
||||
context: context, |
||||
token: BusinessInstance.instance.businessToken, |
||||
tenant: BusinessInstance.instance.businessTenant, |
||||
storeId: widget.arguments["storeId"]); |
||||
} |
||||
BaseData baseData = await businessService.goodsUpdate({ |
||||
"productId": productId, |
||||
"sell": widget.arguments["onSaleStatus"] == "1" ? false : true, |
||||
}).catchError((error) {}); |
||||
if (baseData != null && baseData.isSuccess) { |
||||
_pageIndex = 1; |
||||
adminProductVoList.clear(); |
||||
await _onRefresh(isShowLoad: false); |
||||
SmartDialog.showToast( |
||||
widget.arguments["onSaleStatus"] == "1" ? "商品下架成功" : "商品上架成功", |
||||
alignment: Alignment.center); |
||||
} else { |
||||
SmartDialog.showToast(baseData.msg, alignment: Alignment.center); |
||||
} |
||||
} finally { |
||||
EasyLoading.dismiss(); |
||||
} |
||||
} |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return GestureDetector( |
||||
behavior: HitTestBehavior.translucent, |
||||
onTap: () { |
||||
FocusScope.of(context).requestFocus(FocusNode()); |
||||
}, |
||||
child: Scaffold( |
||||
appBar: MyAppBar( |
||||
title: "搜索", |
||||
titleColor: Colors.black, |
||||
leadingColor: Colors.black, |
||||
background: Colors.white, |
||||
), |
||||
body: Column( |
||||
children: [ |
||||
Container( |
||||
color: Colors.white, |
||||
margin: EdgeInsets.only(bottom: 16.h), |
||||
child: Container( |
||||
height: 40.h, |
||||
margin: EdgeInsets.fromLTRB(18.w, 17.h, 18.w, 10.h), |
||||
alignment: Alignment.center, |
||||
decoration: BoxDecoration( |
||||
color: Color(0xFFF7F8FA), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
child: TextField( |
||||
textInputAction: TextInputAction.search, |
||||
onEditingComplete: () { |
||||
FocusScope.of(context).requestFocus(FocusNode()); |
||||
_pageIndex = 1; |
||||
adminProductVoList.clear(); |
||||
_onRefresh(); |
||||
}, |
||||
controller: editingController, |
||||
style: TextStyle( |
||||
fontSize: 14.sp, |
||||
), |
||||
decoration: InputDecoration( |
||||
hintText: "请输入搜索内容", |
||||
hintStyle: TextStyle( |
||||
fontSize: 15.sp, |
||||
color: Color(0xFF808080), |
||||
fontWeight: MyFontWeight.regular), |
||||
isCollapsed: true, |
||||
prefixIcon: Padding( |
||||
padding: EdgeInsets.only(left: 5.w, right: 5.w), |
||||
child: Image.asset( |
||||
"assets/image/icon_search.webp", |
||||
width: 20.h, |
||||
height: 20.h, |
||||
), |
||||
), |
||||
prefixIconConstraints: BoxConstraints(), |
||||
border: InputBorder.none, |
||||
), |
||||
), |
||||
), |
||||
), |
||||
Expanded( |
||||
child: networkStatus == -1 |
||||
? noNetwork() |
||||
: Container( |
||||
child: SmartRefresher( |
||||
controller: refreshController, |
||||
enablePullDown: true, |
||||
enablePullUp: true, |
||||
physics: BouncingScrollPhysics(), |
||||
header: MyHeader( |
||||
color: Color(0xFF30415B), |
||||
), |
||||
footer: CustomFooter( |
||||
builder: (context, mode) { |
||||
return MyFooter(mode); |
||||
}, |
||||
), |
||||
onRefresh: () { |
||||
_pageIndex = 1; |
||||
adminProductVoList.clear(); |
||||
_onRefresh(isShowLoad: false); |
||||
}, |
||||
onLoading: () { |
||||
_pageIndex++; |
||||
_onRefresh(isShowLoad: false); |
||||
}, |
||||
child: networkStatus == 0 |
||||
? ListView.builder( |
||||
padding: EdgeInsets.zero, |
||||
itemCount: 10, |
||||
scrollDirection: Axis.vertical, |
||||
shrinkWrap: true, |
||||
physics: NeverScrollableScrollPhysics(), |
||||
itemBuilder: (context, position) { |
||||
return searchGoodsItemSm(); |
||||
}, |
||||
) |
||||
: ((adminProductVoList == null || |
||||
adminProductVoList.length == 0) |
||||
? NoDataView( |
||||
src: "assets/image/bs_no data_logo.webp", |
||||
isShowBtn: false, |
||||
text: "未搜索到相关数据", |
||||
fontSize: 16.sp, |
||||
margin: EdgeInsets.all(20.h), |
||||
) |
||||
: Container( |
||||
margin: EdgeInsets.only(bottom: 20.h), |
||||
child: ListView.builder( |
||||
padding: EdgeInsets.zero, |
||||
itemCount: |
||||
adminProductVoList?.length ?? 0, |
||||
scrollDirection: Axis.vertical, |
||||
shrinkWrap: true, |
||||
physics: NeverScrollableScrollPhysics(), |
||||
itemBuilder: (context, position) { |
||||
return searchGoodsItem( |
||||
adminProductVoList[position]); |
||||
}, |
||||
), |
||||
)), |
||||
), |
||||
), |
||||
) |
||||
], |
||||
), |
||||
), |
||||
); |
||||
} |
||||
|
||||
Widget searchGoodsItem(AdminProductVoList adminProductVoList) { |
||||
return Container( |
||||
decoration: BoxDecoration( |
||||
color: Colors.white, |
||||
borderRadius: BorderRadius.circular(8), |
||||
boxShadow: [ |
||||
BoxShadow( |
||||
color: Color(0x0F06152E).withAlpha(12), |
||||
offset: Offset(0, 2), |
||||
blurRadius: 4, |
||||
spreadRadius: 0, |
||||
) |
||||
], |
||||
), |
||||
margin: EdgeInsets.only(bottom: 12.h, left: 16.w, right: 16.w), |
||||
padding: |
||||
EdgeInsets.only(left: 12.w, top: 12.h, bottom: 12.h, right: 24.w), |
||||
child: Row( |
||||
children: [ |
||||
MImage( |
||||
adminProductVoList?.productImg ?? "", |
||||
width: 70.h, |
||||
height: 70.h, |
||||
fit: BoxFit.cover, |
||||
radius: BorderRadius.circular(4), |
||||
), |
||||
SizedBox( |
||||
width: 12.w, |
||||
), |
||||
Expanded( |
||||
child: Column( |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Padding( |
||||
padding: EdgeInsets.only(bottom: 11.h, top: 2.h), |
||||
child: Text( |
||||
adminProductVoList?.productName ?? "", |
||||
maxLines: 1, |
||||
overflow: TextOverflow.ellipsis, |
||||
style: TextStyle( |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.medium, |
||||
color: Color(0xFF000000), |
||||
), |
||||
), |
||||
), |
||||
Row( |
||||
children: [ |
||||
Text( |
||||
"库存${adminProductVoList?.stock ?? 0}", |
||||
style: TextStyle( |
||||
fontSize: 10.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
color: Color(0xFFA29E9E), |
||||
), |
||||
), |
||||
SizedBox( |
||||
width: 8.w, |
||||
), |
||||
Text( |
||||
"销量${adminProductVoList?.sellCount ?? 0}", |
||||
style: TextStyle( |
||||
fontSize: 10.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
color: Color(0xFF999999), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
SizedBox( |
||||
height: 7.h, |
||||
), |
||||
Row( |
||||
children: [ |
||||
Expanded( |
||||
child: Text.rich( |
||||
TextSpan( |
||||
children: [ |
||||
TextSpan( |
||||
text: "¥", |
||||
style: TextStyle( |
||||
fontSize: 12.sp, |
||||
fontWeight: MyFontWeight.medium, |
||||
color: Color(0xFFF4524D), |
||||
), |
||||
), |
||||
TextSpan( |
||||
text: adminProductVoList?.price ?? "", |
||||
style: TextStyle( |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.medium, |
||||
color: Color(0xFFF4524D), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
)), |
||||
GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
showGoodsStateDialog(adminProductVoList.id ?? ""); |
||||
}, |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Colors.white, |
||||
borderRadius: BorderRadius.circular(33), |
||||
border: Border.all( |
||||
color: Color(0xFF30415B), |
||||
width: 1, |
||||
), |
||||
), |
||||
padding: EdgeInsets.symmetric( |
||||
vertical: 2.h, horizontal: 12.w), |
||||
child: Text( |
||||
widget.arguments["onSaleStatus"] == "1" ? "下架" : "上架", |
||||
style: TextStyle( |
||||
fontSize: 12.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
color: Color(0xFF30415B), |
||||
), |
||||
), |
||||
)) |
||||
], |
||||
) |
||||
], |
||||
)), |
||||
], |
||||
), |
||||
); |
||||
} |
||||
|
||||
///商品上下架状态提示弹窗 |
||||
showGoodsStateDialog(productIds) { |
||||
showDialog( |
||||
context: context, |
||||
builder: (context) { |
||||
return AlertDialog( |
||||
content: Container( |
||||
width: MediaQuery.of(context).size.width - 84, |
||||
height: 139.h, |
||||
child: Column( |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
children: [ |
||||
Text( |
||||
"选中数据将被${widget.arguments["onSaleStatus"] == "1" ? "下架" : "上架"}, 是否继续?", |
||||
style: TextStyle( |
||||
color: Color(0xFFF4524D), |
||||
fontSize: 16.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
), |
||||
SizedBox( |
||||
height: 35.h, |
||||
), |
||||
Row( |
||||
children: [ |
||||
Expanded( |
||||
child: InkWell( |
||||
child: BorderText( |
||||
text: S.of(context).quxiao, |
||||
textColor: Color(0xFF30415B), |
||||
fontSize: 16.sp, |
||||
fontWeight: FontWeight.bold, |
||||
borderColor: Color(0xFF30415B), |
||||
radius: 4, |
||||
padding: EdgeInsets.all(12), |
||||
borderWidth: 1, |
||||
), |
||||
onTap: () { |
||||
Navigator.of(context).pop(); |
||||
}, |
||||
), |
||||
flex: 1, |
||||
), |
||||
SizedBox( |
||||
width: 16.w, |
||||
), |
||||
Expanded( |
||||
child: InkWell( |
||||
child: RoundButton( |
||||
text: S.of(context).queren, |
||||
textColor: Colors.white, |
||||
radius: 4, |
||||
padding: EdgeInsets.all(12), |
||||
backgroup: Color(0xFF30415B), |
||||
fontSize: 16.sp, |
||||
fontWeight: FontWeight.bold, |
||||
), |
||||
onTap: () { |
||||
Navigator.of(context).pop(); |
||||
queryGoodsUpdate(productIds ?? ""); |
||||
}, |
||||
), |
||||
flex: 1, |
||||
), |
||||
], |
||||
) |
||||
], |
||||
), |
||||
), |
||||
); |
||||
}, |
||||
); |
||||
} |
||||
|
||||
|
||||
Widget searchGoodsItemSm() { |
||||
return Container( |
||||
decoration: BoxDecoration( |
||||
color: Colors.white, |
||||
borderRadius: BorderRadius.circular(8), |
||||
boxShadow: [ |
||||
BoxShadow( |
||||
color: Color(0x0F06152E).withAlpha(12), |
||||
offset: Offset(0, 2), |
||||
blurRadius: 4, |
||||
spreadRadius: 0, |
||||
) |
||||
], |
||||
), |
||||
margin: EdgeInsets.only(bottom: 12.h, left: 16.w, right: 16.w), |
||||
padding: |
||||
EdgeInsets.only(left: 12.w, top: 12.h, bottom: 12.h, right: 24.w), |
||||
child: Row( |
||||
children: [ |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(4), |
||||
), |
||||
width: 70.h, |
||||
height: 70.h, |
||||
), |
||||
), |
||||
SizedBox( |
||||
width: 12.w, |
||||
), |
||||
Expanded( |
||||
child: Column( |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Padding( |
||||
padding: EdgeInsets.only(bottom: 11.h, top: 2.h), |
||||
child: Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 124.w, |
||||
height: 20.h, |
||||
), |
||||
), |
||||
), |
||||
Row( |
||||
children: [ |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 43.w, |
||||
height: 18.h, |
||||
), |
||||
), |
||||
SizedBox( |
||||
width: 8.w, |
||||
), |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 43.w, |
||||
height: 18.h, |
||||
), |
||||
), |
||||
], |
||||
), |
||||
SizedBox( |
||||
height: 7.h, |
||||
), |
||||
Row( |
||||
children: [ |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 28.w, |
||||
height: 20.h, |
||||
), |
||||
), |
||||
Spacer(), |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 24.w, |
||||
height: 18.h, |
||||
), |
||||
), |
||||
], |
||||
) |
||||
], |
||||
)), |
||||
], |
||||
), |
||||
); |
||||
} |
||||
|
||||
Widget noNetwork() { |
||||
return Container( |
||||
color: Colors.white, |
||||
width: double.infinity, |
||||
child: Column( |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
Text( |
||||
networkError.substring(0, networkError.indexOf(",")), |
||||
style: TextStyle( |
||||
fontSize: 14.sp, |
||||
color: Color(0xFF0D0D0D), |
||||
fontWeight: MyFontWeight.bold), |
||||
), |
||||
Padding( |
||||
padding: EdgeInsets.symmetric(vertical: 10.h), |
||||
child: Text( |
||||
"请检查网络设置或稍后重试", |
||||
style: TextStyle( |
||||
fontSize: 12.sp, |
||||
color: Color(0xFF7A797F), |
||||
fontWeight: MyFontWeight.regular), |
||||
), |
||||
), |
||||
GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
_onRefresh(); |
||||
}, |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0xFF30415B), |
||||
borderRadius: BorderRadius.circular(15), |
||||
), |
||||
padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 3.h), |
||||
child: Text( |
||||
"重试", |
||||
style: TextStyle( |
||||
fontSize: 14.sp, |
||||
color: Colors.white, |
||||
fontWeight: MyFontWeight.regular), |
||||
)), |
||||
) |
||||
], |
||||
), |
||||
); |
||||
} |
||||
} |
@ -1,736 +0,0 @@
|
||||
import 'package:dio/dio.dart'; |
||||
import 'package:flutter/cupertino.dart'; |
||||
import 'package:flutter/material.dart'; |
||||
import 'package:flutter_easyloading/flutter_easyloading.dart'; |
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; |
||||
import 'package:huixiang/view_widget/classic_header.dart'; |
||||
import 'package:huixiang/view_widget/my_footer.dart'; |
||||
import 'package:pull_to_refresh/pull_to_refresh.dart'; |
||||
import 'package:flutter_screenutil/flutter_screenutil.dart'; |
||||
import 'package:shimmer/shimmer.dart'; |
||||
|
||||
import '../../../generated/l10n.dart'; |
||||
import '../../../retrofit/business_api.dart'; |
||||
import '../../../retrofit/data/base_data.dart'; |
||||
import '../../../retrofit/data/business_goods.dart'; |
||||
import '../../../utils/business_instance.dart'; |
||||
import '../../../utils/flutter_utils.dart'; |
||||
import '../../../utils/font_weight.dart'; |
||||
import '../../../view_widget/border_text.dart'; |
||||
import '../../../view_widget/custom_image.dart'; |
||||
import '../../../view_widget/no_data_view.dart'; |
||||
import '../../../view_widget/round_button.dart'; |
||||
|
||||
class OffShelfPage extends StatefulWidget { |
||||
final String storeId; |
||||
final Function(String total) total; |
||||
|
||||
OffShelfPage(this.storeId, this.total); |
||||
|
||||
@override |
||||
State<StatefulWidget> createState() { |
||||
return _OffShelfPage(); |
||||
} |
||||
} |
||||
|
||||
class _OffShelfPage extends State<OffShelfPage> { |
||||
final RefreshController _refreshController = RefreshController(); |
||||
var checkStatus = false; |
||||
int _pageIndex = 1; |
||||
BusinessApiService businessService; |
||||
List<AdminProductVoList> adminProductVoList = []; |
||||
String networkError = ""; |
||||
int networkStatus = 0; |
||||
int dialogIndex = 0; |
||||
|
||||
@override |
||||
void dispose() { |
||||
super.dispose(); |
||||
_refreshController.dispose(); |
||||
} |
||||
|
||||
@override |
||||
void initState() { |
||||
super.initState(); |
||||
_onRefresh(); |
||||
} |
||||
|
||||
_onRefresh({bool isShowLoad = true}) async { |
||||
if (isShowLoad) |
||||
EasyLoading.show( |
||||
status: S.current.zhengzaijiazai, |
||||
maskType: EasyLoadingMaskType.black); |
||||
await queryGoodsList(); |
||||
EasyLoading.dismiss(); |
||||
if (!mounted) return; |
||||
if (_refreshController.isRefresh) _refreshController.refreshCompleted(); |
||||
setState(() {}); |
||||
} |
||||
|
||||
///下架商品列表 |
||||
queryGoodsList() async { |
||||
if (businessService == null) { |
||||
businessService = BusinessApiService(Dio(), |
||||
context: context, |
||||
token: BusinessInstance.instance.businessToken, |
||||
tenant: BusinessInstance.instance.businessTenant, |
||||
storeId: widget.storeId); |
||||
} |
||||
BaseData<BusinessGoods> baseData = |
||||
await businessService.findAdminProductLis({ |
||||
"groupId": "", |
||||
"hasStock": "", |
||||
"keyword": "", |
||||
"pageIndex": _pageIndex, |
||||
"pageSize": 10, |
||||
"status": "0" |
||||
}).catchError((error) { |
||||
networkError = AppUtils.dioErrorTypeToString(error.type); |
||||
networkStatus = -1; |
||||
setState(() {}); |
||||
_refreshController.refreshFailed(); |
||||
_refreshController.loadFailed(); |
||||
}); |
||||
if (!mounted) return; |
||||
if (baseData != null && baseData.isSuccess) { |
||||
adminProductVoList.addAll(baseData?.data?.adminProductVOList ?? []); |
||||
widget.total(baseData.data.total.toString()); |
||||
if ((baseData?.data?.adminProductVOList ?? []).isEmpty || |
||||
adminProductVoList.length == baseData.data.total) |
||||
_refreshController.loadNoData(); |
||||
else |
||||
_refreshController.loadComplete(); |
||||
networkStatus = 1; |
||||
} else { |
||||
SmartDialog.showToast(baseData.msg, alignment: Alignment.center); |
||||
} |
||||
} |
||||
|
||||
///批量上架 |
||||
queryGoodsUpdate(productIds) async { |
||||
EasyLoading.show( |
||||
status: S.current.zhengzaijiazai, maskType: EasyLoadingMaskType.black); |
||||
if (businessService == null) { |
||||
businessService = BusinessApiService(Dio(), |
||||
context: context, |
||||
token: BusinessInstance.instance.businessToken, |
||||
tenant: BusinessInstance.instance.businessTenant, |
||||
storeId: widget.storeId); |
||||
} |
||||
BaseData baseData = await businessService.goodsUpdate({ |
||||
"productId": 0, |
||||
"productIds": productIds ?? [], |
||||
"sell": true, |
||||
}).catchError((error) {}); |
||||
if (baseData != null && baseData.isSuccess) { |
||||
_pageIndex = 1; |
||||
adminProductVoList.clear(); |
||||
await _onRefresh(isShowLoad: false); |
||||
EasyLoading.dismiss(); |
||||
checkStatus = false; |
||||
SmartDialog.showToast("商品上架成功", alignment: Alignment.center); |
||||
} else { |
||||
EasyLoading.dismiss(); |
||||
SmartDialog.showToast(baseData.msg, alignment: Alignment.center); |
||||
} |
||||
} |
||||
|
||||
///批量删除 |
||||
queryDelProduct(productIds) async { |
||||
EasyLoading.show( |
||||
status: S.current.zhengzaijiazai, maskType: EasyLoadingMaskType.black); |
||||
if (businessService == null) { |
||||
businessService = BusinessApiService(Dio(), |
||||
context: context, |
||||
token: BusinessInstance.instance.businessToken, |
||||
tenant: BusinessInstance.instance.businessTenant, |
||||
storeId: widget.storeId); |
||||
} |
||||
BaseData baseData = await businessService.delProduct({ |
||||
"ids": productIds ?? [], |
||||
}).catchError((error) {}); |
||||
if (baseData != null && baseData.isSuccess) { |
||||
_pageIndex = 1; |
||||
adminProductVoList.clear(); |
||||
await _onRefresh(isShowLoad: false); |
||||
EasyLoading.dismiss(); |
||||
SmartDialog.showToast("商品删除成功", alignment: Alignment.center); |
||||
} else { |
||||
EasyLoading.dismiss(); |
||||
SmartDialog.showToast(baseData.msg, alignment: Alignment.center); |
||||
} |
||||
} |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return Scaffold( |
||||
backgroundColor: Colors.white, |
||||
body: Stack( |
||||
alignment: Alignment.bottomCenter, |
||||
children: [ |
||||
Column( |
||||
children: [ |
||||
goodsSearch(), |
||||
if (adminProductVoList.length != 0) |
||||
Padding( |
||||
padding: EdgeInsets.only(left: 5.w), |
||||
child: Row( |
||||
children: [ |
||||
Checkbox( |
||||
value: checkStatus, |
||||
onChanged: (bool isAllCheck) { |
||||
adminProductVoList.forEach((element) { |
||||
element.isSelect = isAllCheck; |
||||
}); |
||||
checkStatus = isAllCheck; |
||||
setState(() {}); |
||||
}, |
||||
shape: RoundedRectangleBorder( |
||||
borderRadius: BorderRadius.circular(2.0), |
||||
), |
||||
checkColor: Color(0xFFFFFFFF), |
||||
fillColor: MaterialStateProperty.all(Color(0xFF30415B)), |
||||
), |
||||
Text( |
||||
"全选", |
||||
style: TextStyle( |
||||
fontSize: 12.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
color: Color(0xFF000000), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
Expanded( |
||||
child: networkStatus == -1 |
||||
? noNetwork() |
||||
: Container( |
||||
child: SmartRefresher( |
||||
controller: _refreshController, |
||||
enablePullDown: true, |
||||
enablePullUp: true, |
||||
header: MyHeader( |
||||
color: Color(0xFF30415B), |
||||
), |
||||
physics: BouncingScrollPhysics(), |
||||
footer: CustomFooter( |
||||
builder: (context, mode) { |
||||
return MyFooter(mode); |
||||
}, |
||||
), |
||||
onRefresh: () { |
||||
_pageIndex = 1; |
||||
adminProductVoList.clear(); |
||||
_onRefresh(isShowLoad: false); |
||||
}, |
||||
onLoading: () { |
||||
_pageIndex++; |
||||
_onRefresh(isShowLoad: false); |
||||
}, |
||||
child: Container( |
||||
color: Colors.white, |
||||
child: networkStatus == 0 |
||||
? ListView.builder( |
||||
itemCount: 10, |
||||
physics: BouncingScrollPhysics(), |
||||
shrinkWrap: true, |
||||
itemBuilder: (context, position) { |
||||
return GestureDetector( |
||||
onTap: () {}, |
||||
child: shelfGoodsItemSm(), |
||||
); |
||||
}, |
||||
) |
||||
: ((adminProductVoList == null || |
||||
adminProductVoList.length == 0) |
||||
? NoDataView( |
||||
src: |
||||
"assets/image/bs_no data_logo.webp", |
||||
isShowBtn: false, |
||||
text: "暂无下架商品", |
||||
fontSize: 16.sp, |
||||
margin: EdgeInsets.all(20.h), |
||||
) |
||||
: ListView.builder( |
||||
itemCount: |
||||
adminProductVoList?.length ?? 0, |
||||
physics: BouncingScrollPhysics(), |
||||
shrinkWrap: true, |
||||
itemBuilder: (context, position) { |
||||
return GestureDetector( |
||||
onTap: () {}, |
||||
child: shelfGoodsItem( |
||||
adminProductVoList[ |
||||
position]), |
||||
); |
||||
}, |
||||
)))), |
||||
), |
||||
), |
||||
SizedBox( |
||||
height: 60.h, |
||||
) |
||||
], |
||||
), |
||||
Row( |
||||
children: [ |
||||
Expanded( |
||||
child: GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
List<dynamic> productIds = []; |
||||
adminProductVoList.forEach((element) { |
||||
if (element.isSelect) productIds.add(element.id); |
||||
}); |
||||
if (productIds.length == 0) { |
||||
SmartDialog.showToast("请选择要上架的商品", |
||||
alignment: Alignment.center); |
||||
return; |
||||
} else { |
||||
showDelGoodsDialog(productIds, 1); |
||||
} |
||||
}, |
||||
child: Container( |
||||
color: Color(0xFFEDEDED), |
||||
padding: EdgeInsets.only( |
||||
top: 21.h, |
||||
bottom: 24.h, |
||||
left: 44.w, |
||||
), |
||||
child: Text( |
||||
"批量上架", |
||||
style: TextStyle( |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.semi_bold, |
||||
color: Color(0xFF30415B), |
||||
), |
||||
), |
||||
), |
||||
), |
||||
), |
||||
Expanded( |
||||
child: GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
List<dynamic> productIds = []; |
||||
adminProductVoList.forEach((element) { |
||||
if (element.isSelect) productIds.add(element.id); |
||||
}); |
||||
if (productIds.length == 0) { |
||||
SmartDialog.showToast("请选择要删除的商品", |
||||
alignment: Alignment.center); |
||||
return; |
||||
} else { |
||||
showDelGoodsDialog(productIds, 2); |
||||
} |
||||
}, |
||||
child: Container( |
||||
color: Color(0xFFEDEDED), |
||||
padding: EdgeInsets.only( |
||||
top: 21.h, |
||||
bottom: 24.h, |
||||
right: 44.w, |
||||
), |
||||
child: Text( |
||||
"批量删除", |
||||
textAlign: TextAlign.right, |
||||
style: TextStyle( |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.semi_bold, |
||||
color: Color(0xFF30415B), |
||||
), |
||||
)))) |
||||
], |
||||
), |
||||
], |
||||
), |
||||
); |
||||
} |
||||
|
||||
/// 搜索框 |
||||
Widget goodsSearch() { |
||||
return GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
Navigator.of(context) |
||||
.pushNamed('/router/goods_search_page', arguments: { |
||||
"storeId": widget.storeId, |
||||
"onSaleStatus": "0", |
||||
}).then((value) => { |
||||
_pageIndex = 1, |
||||
adminProductVoList.clear(), |
||||
_onRefresh(isShowLoad: false), |
||||
}); |
||||
}, |
||||
child: Container( |
||||
height: 40.h, |
||||
margin: EdgeInsets.fromLTRB(18.w, 16.h, 18.w, 10.h), |
||||
padding: EdgeInsets.fromLTRB(12.w, 6.h, 0, 6.h), |
||||
decoration: BoxDecoration( |
||||
color: Color(0xFFF7F8FA), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
child: Row( |
||||
children: [ |
||||
Image.asset( |
||||
"assets/image/bs_goods_search.webp", |
||||
width: 20, |
||||
height: 20, |
||||
), |
||||
SizedBox( |
||||
width: 3.w, |
||||
), |
||||
Text( |
||||
"请输入搜索内容", |
||||
style: TextStyle( |
||||
fontSize: 15.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
color: Color(0xFF808080), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
); |
||||
} |
||||
|
||||
///删除商品/批量上架提示弹窗 |
||||
showDelGoodsDialog(productIds, index) { |
||||
showDialog( |
||||
context: context, |
||||
builder: (context) { |
||||
return AlertDialog( |
||||
content: Container( |
||||
width: MediaQuery.of(context).size.width - 84, |
||||
height: 139.h, |
||||
child: Column( |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
children: [ |
||||
Text( |
||||
"选中数据将被${index == 1 ? "上架" : "永久删除"}, 是否继续?", |
||||
style: TextStyle( |
||||
color: Color(0xFFF4524D), |
||||
fontSize: 16.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
), |
||||
SizedBox( |
||||
height: 35.h, |
||||
), |
||||
Row( |
||||
children: [ |
||||
Expanded( |
||||
child: InkWell( |
||||
child: BorderText( |
||||
text: S.of(context).quxiao, |
||||
textColor: Color(0xFF30415B), |
||||
fontSize: 16.sp, |
||||
fontWeight: FontWeight.bold, |
||||
borderColor: Color(0xFF30415B), |
||||
radius: 4, |
||||
padding: EdgeInsets.all(12), |
||||
borderWidth: 1, |
||||
), |
||||
onTap: () { |
||||
Navigator.of(context).pop(); |
||||
}, |
||||
), |
||||
flex: 1, |
||||
), |
||||
SizedBox( |
||||
width: 16.w, |
||||
), |
||||
Expanded( |
||||
child: InkWell( |
||||
child: RoundButton( |
||||
text: S.of(context).queren, |
||||
textColor: Colors.white, |
||||
radius: 4, |
||||
padding: EdgeInsets.all(12), |
||||
backgroup: Color(0xFF30415B), |
||||
fontSize: 16.sp, |
||||
fontWeight: FontWeight.bold, |
||||
), |
||||
onTap: () { |
||||
Navigator.of(context).pop(); |
||||
if (index == 1) |
||||
queryGoodsUpdate(productIds); |
||||
else |
||||
queryDelProduct(productIds); |
||||
}, |
||||
), |
||||
flex: 1, |
||||
), |
||||
], |
||||
) |
||||
], |
||||
), |
||||
), |
||||
); |
||||
}, |
||||
); |
||||
} |
||||
|
||||
///商品列表 |
||||
Widget shelfGoodsItem(AdminProductVoList adminProductVoList) { |
||||
return Container( |
||||
margin: EdgeInsets.only(bottom: 22.h), |
||||
padding: EdgeInsets.only( |
||||
left: 5.w, |
||||
), |
||||
child: Row( |
||||
children: [ |
||||
Checkbox( |
||||
value: adminProductVoList.isSelect, |
||||
onChanged: (a) { |
||||
setState(() { |
||||
adminProductVoList.isSelect = !adminProductVoList.isSelect; |
||||
}); |
||||
}, |
||||
shape: RoundedRectangleBorder( |
||||
borderRadius: BorderRadius.circular(2.0), |
||||
), |
||||
checkColor: Color(0xFFFFFFFF), |
||||
fillColor: MaterialStateProperty.all(Color(0xFF30415B)), |
||||
), |
||||
MImage( |
||||
adminProductVoList?.productImg ?? "", |
||||
width: 70.h, |
||||
height: 70.h, |
||||
fit: BoxFit.cover, |
||||
radius: BorderRadius.circular(4), |
||||
), |
||||
SizedBox( |
||||
width: 12.w, |
||||
), |
||||
Expanded( |
||||
child: Column( |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Padding( |
||||
padding: EdgeInsets.only(bottom: 11.h, top: 2.h), |
||||
child: Text( |
||||
adminProductVoList?.productName ?? "", |
||||
maxLines: 1, |
||||
overflow: TextOverflow.ellipsis, |
||||
style: TextStyle( |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.medium, |
||||
color: Color(0xFF000000), |
||||
), |
||||
), |
||||
), |
||||
Row( |
||||
children: [ |
||||
Text( |
||||
"库存${adminProductVoList?.stock ?? 0}", |
||||
style: TextStyle( |
||||
fontSize: 10.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
color: Color(0xFFA29E9E), |
||||
), |
||||
), |
||||
SizedBox( |
||||
width: 8.w, |
||||
), |
||||
Text( |
||||
"销量${adminProductVoList?.sellCount ?? 0}", |
||||
style: TextStyle( |
||||
fontSize: 10.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
color: Color(0xFF999999), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
SizedBox( |
||||
height: 7.h, |
||||
), |
||||
Text.rich( |
||||
TextSpan( |
||||
children: [ |
||||
TextSpan( |
||||
text: "¥", |
||||
style: TextStyle( |
||||
fontSize: 12.sp, |
||||
fontWeight: MyFontWeight.medium, |
||||
color: Color(0xFFF4524D), |
||||
), |
||||
), |
||||
TextSpan( |
||||
text: adminProductVoList?.price ?? "", |
||||
style: TextStyle( |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.medium, |
||||
color: Color(0xFFF4524D), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
) |
||||
], |
||||
)), |
||||
], |
||||
), |
||||
); |
||||
} |
||||
|
||||
Widget shelfGoodsItemSm() { |
||||
return Container( |
||||
margin: EdgeInsets.only(bottom: 22.h), |
||||
padding: EdgeInsets.only( |
||||
left: 5.w, |
||||
), |
||||
child: Row( |
||||
children: [ |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 16.h, |
||||
height: 16.h, |
||||
), |
||||
), |
||||
SizedBox( |
||||
width: 18.w, |
||||
), |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(4), |
||||
), |
||||
width: 70.h, |
||||
height: 70.h, |
||||
), |
||||
), |
||||
SizedBox( |
||||
width: 12.w, |
||||
), |
||||
Expanded( |
||||
child: Column( |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Padding( |
||||
padding: EdgeInsets.only(bottom: 11.h, top: 2.h), |
||||
child: Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 112.w, |
||||
height: 20.h, |
||||
), |
||||
), |
||||
), |
||||
Row( |
||||
children: [ |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 43.w, |
||||
height: 18.h, |
||||
), |
||||
), |
||||
SizedBox( |
||||
width: 8.w, |
||||
), |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 43.w, |
||||
height: 18.h, |
||||
), |
||||
), |
||||
], |
||||
), |
||||
SizedBox( |
||||
height: 7.h, |
||||
), |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 28.w, |
||||
height: 20.h, |
||||
), |
||||
), |
||||
], |
||||
)), |
||||
], |
||||
), |
||||
); |
||||
} |
||||
|
||||
Widget noNetwork() { |
||||
return Container( |
||||
color: Colors.white, |
||||
child: Column( |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
Text( |
||||
networkError.substring(0, networkError.indexOf(",")), |
||||
style: TextStyle( |
||||
fontSize: 14.sp, |
||||
color: Color(0xFF0D0D0D), |
||||
fontWeight: MyFontWeight.bold), |
||||
), |
||||
Padding( |
||||
padding: EdgeInsets.symmetric(vertical: 10.h), |
||||
child: Text( |
||||
"请检查网络设置或稍后重试", |
||||
style: TextStyle( |
||||
fontSize: 12.sp, |
||||
color: Color(0xFF7A797F), |
||||
fontWeight: MyFontWeight.regular), |
||||
), |
||||
), |
||||
GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
_onRefresh(); |
||||
}, |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0xFF30415B), |
||||
borderRadius: BorderRadius.circular(15), |
||||
), |
||||
padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 3.h), |
||||
child: Text( |
||||
"重试", |
||||
style: TextStyle( |
||||
fontSize: 14.sp, |
||||
color: Colors.white, |
||||
fontWeight: MyFontWeight.regular), |
||||
)), |
||||
) |
||||
], |
||||
), |
||||
); |
||||
} |
||||
} |
@ -1,310 +0,0 @@
|
||||
import 'package:dio/dio.dart'; |
||||
import 'package:flutter/material.dart'; |
||||
import 'package:flutter_easyloading/flutter_easyloading.dart'; |
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; |
||||
import 'package:huixiang/utils/font_weight.dart'; |
||||
import 'package:huixiang/view_widget/my_appbar.dart'; |
||||
import 'package:flutter_screenutil/flutter_screenutil.dart'; |
||||
|
||||
import '../../../generated/l10n.dart'; |
||||
import '../../../retrofit/business_api.dart'; |
||||
import '../../../retrofit/data/base_data.dart'; |
||||
import '../../../utils/business_instance.dart'; |
||||
import '../../../view_widget/round_button.dart'; |
||||
|
||||
class AddAssort extends StatefulWidget { |
||||
final Map<String, dynamic> arguments; |
||||
|
||||
AddAssort({this.arguments}); |
||||
|
||||
@override |
||||
State<StatefulWidget> createState() { |
||||
return _AddAssort(); |
||||
} |
||||
} |
||||
|
||||
class _AddAssort extends State<AddAssort> { |
||||
final TextEditingController editingSortController = TextEditingController(); |
||||
final TextEditingController editingNameController = TextEditingController(); |
||||
bool isKeyBoardShow = false; |
||||
FocusNode _focusNode = FocusNode(); |
||||
BusinessApiService businessService; |
||||
String name = ""; |
||||
|
||||
@override |
||||
void initState() { |
||||
super.initState(); |
||||
WidgetsBinding.instance.addPostFrameCallback((_) { |
||||
setState(() { |
||||
print("object: ${MediaQuery.of(context).viewInsets.bottom}"); |
||||
if (MediaQuery.of(context).viewInsets.bottom == 0) { |
||||
if (isKeyBoardShow) { |
||||
isKeyBoardShow = false; |
||||
//关闭键盘 软键盘关闭了, 清除输入控件的焦点, 否则重新进入页面会导致软键盘再弹出问题 |
||||
FocusScope.of(context).requestFocus(FocusNode()); |
||||
} |
||||
} else { |
||||
isKeyBoardShow = true; |
||||
} |
||||
}); |
||||
}); |
||||
name = widget.arguments["statusName"]; |
||||
} |
||||
|
||||
///离开页面记着销毁和清除 |
||||
@override |
||||
void dispose() { |
||||
_focusNode.unfocus(); |
||||
super.dispose(); |
||||
} |
||||
|
||||
///商品分类-新增分类/编辑分类 |
||||
querySaveProductGroup() async { |
||||
try{ |
||||
EasyLoading.show( |
||||
status: S.current.zhengzaijiazai, maskType: EasyLoadingMaskType.black); |
||||
if (businessService == null) { |
||||
businessService = BusinessApiService(Dio(), |
||||
context: context, |
||||
token: BusinessInstance.instance.businessToken, |
||||
tenant: BusinessInstance.instance.businessTenant, |
||||
storeId: widget.arguments["storeId"]); |
||||
} |
||||
BaseData baseData = await businessService.saveProductGroup({ |
||||
"groupName": editingNameController.text == "" |
||||
? widget.arguments["groupName"] |
||||
: editingNameController.text, |
||||
"storeId": widget.arguments["storeId"], |
||||
"id": name == "添加分类" ? "" : widget.arguments["id"], |
||||
"sort": |
||||
editingSortController.text == "" ? "1" : editingSortController.text, |
||||
}).catchError((error) {}); |
||||
if (baseData != null && baseData.isSuccess) { |
||||
Navigator.of(context).pop(); |
||||
if (name == "添加分类") |
||||
showProductTipDialog(); |
||||
else |
||||
SmartDialog.showToast(name == "添加分类" ? "分类添加成功" : "分类编辑成功", |
||||
alignment: Alignment.center); |
||||
} else { |
||||
SmartDialog.showToast(baseData.msg, alignment: Alignment.center); |
||||
}}finally{ |
||||
EasyLoading.dismiss(); |
||||
} |
||||
} |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return GestureDetector( |
||||
behavior: HitTestBehavior.translucent, |
||||
onTap: () { |
||||
FocusScope.of(context).unfocus(); |
||||
}, |
||||
child: Scaffold( |
||||
resizeToAvoidBottomInset: false, |
||||
backgroundColor: Colors.white, |
||||
appBar: MyAppBar( |
||||
title: name, |
||||
titleColor: Colors.black, |
||||
background: Colors.white, |
||||
leadingColor: Colors.black, |
||||
brightness: Brightness.dark, |
||||
), |
||||
body: Container( |
||||
margin: EdgeInsets.only(top: 24.h, left: 16.w, right: 16.w), |
||||
child: Column( |
||||
children: [ |
||||
Row( |
||||
children: [ |
||||
Expanded( |
||||
child: Text( |
||||
"分组排序", |
||||
style: TextStyle( |
||||
color: Color(0xFF30415B), |
||||
fontSize: 16.sp, |
||||
fontWeight: FontWeight.w500, |
||||
), |
||||
), |
||||
), |
||||
Expanded( |
||||
child: TextField( |
||||
controller: editingSortController, |
||||
decoration: InputDecoration( |
||||
hintText: widget?.arguments["sort"] ?? "数字越大排名越靠前", |
||||
hintTextDirection: TextDirection.rtl, |
||||
hintStyle: TextStyle( |
||||
color: Color(0xFF7A797F), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.semi_bold, |
||||
), |
||||
border: InputBorder.none, |
||||
contentPadding: EdgeInsets.only(left: 16.w), |
||||
), |
||||
textAlign: TextAlign.right, |
||||
style: TextStyle( |
||||
color: Color(0xFF7A797F), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.semi_bold), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
Container( |
||||
height: 1.h, |
||||
width: double.infinity, |
||||
color: Color(0xFFEBEBEB), |
||||
), |
||||
Row( |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
Expanded( |
||||
child: Text.rich( |
||||
TextSpan( |
||||
children: [ |
||||
TextSpan( |
||||
text: "*", |
||||
style: TextStyle( |
||||
color: Color(0xFFE02020), |
||||
fontSize: 16.sp, |
||||
fontWeight: FontWeight.w500, |
||||
), |
||||
), |
||||
TextSpan( |
||||
text: "分类名称", |
||||
style: TextStyle( |
||||
color: Color(0xFF30415B), |
||||
fontSize: 16.sp, |
||||
fontWeight: FontWeight.w500, |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
), |
||||
Expanded( |
||||
child: TextField( |
||||
controller: editingNameController, |
||||
decoration: InputDecoration( |
||||
hintText: widget?.arguments["groupName"] ?? "请输入分类名称", |
||||
hintTextDirection: TextDirection.rtl, |
||||
hintStyle: TextStyle( |
||||
color: Color(0xFF7A797F), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.semi_bold), |
||||
border: InputBorder.none, |
||||
contentPadding: EdgeInsets.only(left: 16.w), |
||||
), |
||||
textAlign: TextAlign.right, |
||||
style: TextStyle( |
||||
color: Color(0xFF7A797F), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.semi_bold), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
Container( |
||||
height: 1.h, |
||||
width: double.infinity, |
||||
color: Color(0xFFEBEBEB), |
||||
margin: EdgeInsets.only(bottom: 16.h), |
||||
), |
||||
Spacer(), |
||||
GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
if (name == "添加分类" && editingNameController.text == "") { |
||||
SmartDialog.showToast("请输入分类名称", |
||||
alignment: Alignment.center); |
||||
return; |
||||
} else { |
||||
querySaveProductGroup(); |
||||
} |
||||
}, |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
borderRadius: BorderRadius.circular(27), |
||||
color: Color(0xFF30415B), |
||||
), |
||||
width: double.infinity, |
||||
alignment: Alignment.center, |
||||
padding: EdgeInsets.symmetric(vertical: 16.h), |
||||
margin: EdgeInsets.only(bottom: 34.h), |
||||
child: Text( |
||||
S.of(context).baocun, |
||||
style: TextStyle( |
||||
color: Colors.white, |
||||
fontSize: 16.sp, |
||||
fontWeight: FontWeight.bold, |
||||
), |
||||
), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
), |
||||
); |
||||
} |
||||
|
||||
///新增分组提示 |
||||
showProductTipDialog() { |
||||
showDialog( |
||||
context: context, |
||||
barrierDismissible: false, |
||||
builder: (context) { |
||||
return AlertDialog( |
||||
content: Container( |
||||
width: MediaQuery.of(context).size.width - 84.w, |
||||
child: Column( |
||||
mainAxisSize: MainAxisSize.min, |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
children: [ |
||||
Text( |
||||
"提示", |
||||
style: TextStyle( |
||||
color: Color(0xFF0D0D0D), |
||||
fontSize: 16.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
), |
||||
SizedBox( |
||||
height: 15.h, |
||||
), |
||||
Text( |
||||
"注意:新增分组完成后,请配置打印机,否则无法打印票单!", |
||||
textAlign: TextAlign.center, |
||||
style: TextStyle( |
||||
color: Color(0xFFF4524D), |
||||
fontSize: 16.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
), |
||||
SizedBox( |
||||
height: 35.h, |
||||
), |
||||
InkWell( |
||||
child: RoundButton( |
||||
text: S.of(context).queren, |
||||
textColor: Colors.white, |
||||
radius: 4, |
||||
padding: EdgeInsets.all(12), |
||||
backgroup: Color(0xFF30415B), |
||||
fontSize: 16.sp, |
||||
fontWeight: FontWeight.bold, |
||||
), |
||||
onTap: () { |
||||
Navigator.of(context).pop(); |
||||
SmartDialog.showToast("分类添加成功", |
||||
alignment: Alignment.center); |
||||
}, |
||||
), |
||||
], |
||||
), |
||||
), |
||||
); |
||||
}, |
||||
); |
||||
} |
||||
} |
@ -1,801 +0,0 @@
|
||||
import 'dart:ffi'; |
||||
|
||||
import 'package:dio/dio.dart'; |
||||
import 'package:flutter/material.dart'; |
||||
import 'package:flutter_easyloading/flutter_easyloading.dart'; |
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; |
||||
import 'package:huixiang/view_widget/my_appbar.dart'; |
||||
import 'package:pull_to_refresh/pull_to_refresh.dart'; |
||||
import 'package:flutter_screenutil/flutter_screenutil.dart'; |
||||
import 'package:shared_preferences/shared_preferences.dart'; |
||||
import 'package:shimmer/shimmer.dart'; |
||||
|
||||
import '../../../generated/l10n.dart'; |
||||
import '../../../retrofit/business_api.dart'; |
||||
import '../../../retrofit/data/base_data.dart'; |
||||
import '../../../retrofit/data/business_goods.dart'; |
||||
import '../../../retrofit/data/product_group_list.dart'; |
||||
import '../../../utils/business_instance.dart'; |
||||
import '../../../utils/flutter_utils.dart'; |
||||
import '../../../utils/font_weight.dart'; |
||||
import '../../../view_widget/border_text.dart'; |
||||
import '../../../view_widget/classic_header.dart'; |
||||
import '../../../view_widget/custom_image.dart'; |
||||
import '../../../view_widget/my_footer.dart'; |
||||
import '../../../view_widget/no_data_view.dart'; |
||||
import '../../../view_widget/round_button.dart'; |
||||
|
||||
class BatchShelf extends StatefulWidget { |
||||
final Map<String, dynamic> arguments; |
||||
|
||||
BatchShelf({this.arguments}); |
||||
|
||||
@override |
||||
State<StatefulWidget> createState() { |
||||
return _BatchShelf(); |
||||
} |
||||
} |
||||
|
||||
class _BatchShelf extends State<BatchShelf> { |
||||
final RefreshController _refreshController = RefreshController(); |
||||
final ScrollController controller = ScrollController(); |
||||
BusinessApiService businessService; |
||||
ProductGroupList productGroupList; |
||||
List<AdminProductVoList> adminProductVoList = []; |
||||
List<AdminProductVoList> selectedProductVoList = []; |
||||
List<dynamic> productIds = []; |
||||
int _loadCount = 0; |
||||
int _pageIndex = 1; |
||||
int groupIndex = -1; |
||||
String networkError = ""; |
||||
int networkStatus = 0; |
||||
int groupNum = 1; |
||||
String titleName; |
||||
|
||||
@override |
||||
void initState() { |
||||
super.initState(); |
||||
_onRefresh(); |
||||
titleName = widget?.arguments["titleName"] ?? ""; |
||||
groupNum = widget?.arguments["groupNum"] ?? 1; |
||||
} |
||||
|
||||
@override |
||||
void dispose() { |
||||
super.dispose(); |
||||
_refreshController.dispose(); |
||||
} |
||||
|
||||
_onRefresh({isShowLoad = true}) async { |
||||
if (isShowLoad) |
||||
EasyLoading.show( |
||||
status: S.current.zhengzaijiazai, |
||||
maskType: EasyLoadingMaskType.black); |
||||
SharedPreferences.getInstance().then((value) { |
||||
businessService = BusinessApiService( |
||||
Dio(), |
||||
context: context, |
||||
token: BusinessInstance.instance.businessToken, |
||||
tenant: BusinessInstance.instance.businessTenant, |
||||
storeId: widget.arguments["storeId"], |
||||
); |
||||
queryProductGroupList(); |
||||
queryGoodsList( |
||||
groupIndex != -1 ? productGroupList.records[groupIndex].id : "", |
||||
isSing: false); |
||||
}); |
||||
} |
||||
|
||||
addLoadCount() { |
||||
_loadCount += 1; |
||||
if (_loadCount == 2) { |
||||
_loadCount = 0; |
||||
EasyLoading.dismiss(); |
||||
if (!mounted) return; |
||||
if (_refreshController.isRefresh) _refreshController.refreshCompleted(); |
||||
setState(() {}); |
||||
} |
||||
} |
||||
|
||||
///分组列表 |
||||
queryProductGroupList() async { |
||||
try { |
||||
BaseData<ProductGroupList> baseData = await businessService.productGroup({ |
||||
"current": 1, |
||||
"map": {}, |
||||
"model": {"groupImg": "", "groupName": "", "isDelete": 0}, |
||||
"order": "ascending", |
||||
"size": 100, |
||||
"sort": "sort" |
||||
}).catchError((error) {}); |
||||
if (!mounted) return; |
||||
if (baseData != null && baseData.isSuccess) { |
||||
productGroupList = baseData.data; |
||||
} else { |
||||
SmartDialog.showToast(baseData.msg, alignment: Alignment.center); |
||||
} |
||||
} finally { |
||||
addLoadCount(); |
||||
} |
||||
} |
||||
|
||||
///商品列表 |
||||
queryGoodsList(groupId, {isSing = true}) async { |
||||
try { |
||||
BaseData<BusinessGoods> baseData = |
||||
await businessService.findAdminProductLis({ |
||||
"groupId": groupId, |
||||
"hasStock": "", |
||||
"keyword": "", |
||||
"pageIndex": _pageIndex, |
||||
"pageSize": 10, |
||||
"status": "1" |
||||
}).catchError((error) { |
||||
networkError = AppUtils.dioErrorTypeToString(error.type); |
||||
networkStatus = -1; |
||||
_refreshController.refreshFailed(); |
||||
_refreshController.loadFailed(); |
||||
}); |
||||
if (!mounted) return; |
||||
if (baseData != null && baseData.isSuccess) { |
||||
adminProductVoList.addAll(baseData?.data?.adminProductVOList ?? []); |
||||
|
||||
// 判断新列表中是否又选中过的商品 |
||||
if (selectedProductVoList.isNotEmpty) { |
||||
adminProductVoList.forEach((element) { |
||||
element.isSelect = selectedProductVoList.any((e) => e.id == element.id); |
||||
}); |
||||
} |
||||
|
||||
if ((baseData?.data?.adminProductVOList ?? []).isEmpty || |
||||
adminProductVoList.length == baseData.data.total) { |
||||
_refreshController.loadNoData(); |
||||
} else { |
||||
_refreshController.loadComplete(); |
||||
} |
||||
networkStatus = 1; |
||||
} else { |
||||
SmartDialog.showToast(baseData.msg, alignment: Alignment.center); |
||||
} |
||||
} finally { |
||||
if (isSing) { |
||||
setState(() {}); |
||||
} else { |
||||
addLoadCount(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
queryGoodsUpdate() async { |
||||
try { |
||||
EasyLoading.show( |
||||
status: S.current.zhengzaijiazai, |
||||
maskType: EasyLoadingMaskType.black); |
||||
if (businessService == null) { |
||||
businessService = BusinessApiService(Dio(), |
||||
context: context, |
||||
token: BusinessInstance.instance.businessToken, |
||||
tenant: BusinessInstance.instance.businessTenant, |
||||
storeId: widget.arguments["storeId"]); |
||||
} |
||||
BaseData baseData = await businessService.goodsUpdate({ |
||||
"productId": 0, |
||||
"productIds": productIds ?? [], |
||||
"sell": false, |
||||
}).catchError((error) {}); |
||||
if (baseData != null && baseData.isSuccess) { |
||||
_pageIndex = 1; |
||||
adminProductVoList.clear(); |
||||
await queryGoodsList( |
||||
groupIndex == -1 |
||||
? "" |
||||
: productGroupList?.records[groupIndex]?.id ?? "", |
||||
isSing: false); |
||||
setState(() {}); |
||||
SmartDialog.showToast("商品下架成功", alignment: Alignment.center); |
||||
} else { |
||||
SmartDialog.showToast(baseData.msg, alignment: Alignment.center); |
||||
} |
||||
} finally { |
||||
EasyLoading.dismiss(); |
||||
} |
||||
} |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return Scaffold( |
||||
backgroundColor: Colors.white, |
||||
appBar: MyAppBar( |
||||
title: titleName, |
||||
titleColor: Colors.black, |
||||
background: Colors.white, |
||||
leadingColor: Colors.black, |
||||
brightness: Brightness.dark, |
||||
action: GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
List<Map<String, dynamic>> goodsMeal = []; |
||||
if (titleName == "批量下架") { |
||||
if (productIds.length != 0) productIds.clear(); |
||||
adminProductVoList.forEach((element) { |
||||
if (element.isSelect) productIds.add(element.id); |
||||
}); |
||||
if (productIds.length == 0) { |
||||
SmartDialog.showToast("请选择要下架的商品", alignment: Alignment.center); |
||||
return; |
||||
} else { |
||||
showGoodsStateDialog(); |
||||
} |
||||
} else { |
||||
if (goodsMeal.length != 0) goodsMeal.clear(); |
||||
if (groupNum != selectedProductVoList.length) { |
||||
SmartDialog.showToast("选择的商品与分组总数不一致", alignment: Alignment.center); |
||||
return; |
||||
} |
||||
goodsMeal = selectedProductVoList.map((e) => { |
||||
"productId": e.id, |
||||
"storeId": e.storeId, |
||||
"skuInfoList": e.productSkuVOList, |
||||
"productAttrInfoList": e.attrList, |
||||
"productName": e.productName, |
||||
"number": e.goodsNumber.toString() |
||||
}).toList(); |
||||
if (goodsMeal.length == 0) { |
||||
SmartDialog.showToast("请选择要增加的商品", alignment: Alignment.center); |
||||
return; |
||||
} |
||||
Navigator.of(context).pop(goodsMeal); |
||||
} |
||||
}, |
||||
child: Container( |
||||
alignment: Alignment.center, |
||||
child: Text( |
||||
"${S.of(context).queren}(${selectedProductVoList.length}/${groupNum})", |
||||
style: TextStyle( |
||||
color: Color(0xFF30415B), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.semi_bold, |
||||
), |
||||
), |
||||
), |
||||
), |
||||
), |
||||
body: networkStatus == -1 |
||||
? noNetwork() |
||||
: Row( |
||||
mainAxisAlignment: MainAxisAlignment.start, |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Container( |
||||
width: 100.w, |
||||
height: double.infinity, |
||||
padding: EdgeInsets.only(bottom: 70.h), |
||||
color: Color(0xFFFAFAFA), |
||||
child: networkStatus == 0 |
||||
? ListView.builder( |
||||
itemCount: 10, |
||||
physics: BouncingScrollPhysics(), |
||||
shrinkWrap: true, |
||||
itemBuilder: (context, position) { |
||||
return shelfLeftItemSm(); |
||||
}, |
||||
) |
||||
: ListView.builder( |
||||
itemCount: productGroupList?.records?.length ?? 0, |
||||
physics: BouncingScrollPhysics(), |
||||
shrinkWrap: true, |
||||
itemBuilder: (context, position) { |
||||
return GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
groupIndex = position; |
||||
_pageIndex = 1; |
||||
adminProductVoList.clear(); |
||||
queryGoodsList( |
||||
productGroupList?.records[position].id, |
||||
); |
||||
}, |
||||
child: shelfLeftItem( |
||||
productGroupList.records[position], position), |
||||
); |
||||
}, |
||||
), |
||||
), |
||||
Container( |
||||
width: MediaQuery.of(context).size.width - 100.w, |
||||
child: SmartRefresher( |
||||
controller: _refreshController, |
||||
enablePullDown: true, |
||||
enablePullUp: |
||||
adminProductVoList.length != 0 ? true : false, |
||||
header: MyHeader( |
||||
color: Color(0xFF30415B), |
||||
), |
||||
physics: BouncingScrollPhysics(), |
||||
footer: CustomFooter( |
||||
builder: (context, mode) { |
||||
return MyFooter(mode); |
||||
}, |
||||
), |
||||
onLoading: () { |
||||
_pageIndex++; |
||||
queryGoodsList(groupIndex == -1 |
||||
? "" |
||||
: productGroupList?.records[groupIndex].id); |
||||
}, |
||||
onRefresh: () { |
||||
_pageIndex = 1; |
||||
adminProductVoList.clear(); |
||||
_onRefresh(isShowLoad: false); |
||||
}, |
||||
child: Container( |
||||
color: Colors.white, |
||||
child: networkStatus == 0 |
||||
? ListView.builder( |
||||
itemCount: 10, |
||||
physics: BouncingScrollPhysics(), |
||||
shrinkWrap: true, |
||||
itemBuilder: (context, position) { |
||||
return shelfGoodsItemSm(); |
||||
}, |
||||
) |
||||
: ((adminProductVoList == null || |
||||
adminProductVoList.length == 0) |
||||
? NoDataView( |
||||
src: "assets/image/bs_no data_logo.webp", |
||||
isShowBtn: false, |
||||
text: "该分组暂无添加商品", |
||||
fontSize: 16.sp, |
||||
margin: EdgeInsets.all(20.h), |
||||
) |
||||
: ListView.builder( |
||||
itemCount: |
||||
adminProductVoList?.length ?? 0, |
||||
controller: controller, |
||||
physics: BouncingScrollPhysics(), |
||||
shrinkWrap: true, |
||||
itemBuilder: (context, position) { |
||||
return shelfGoodsItem( |
||||
adminProductVoList[position]); |
||||
}, |
||||
)))), |
||||
), |
||||
], |
||||
), |
||||
); |
||||
} |
||||
|
||||
///商品确认下架提示弹窗 |
||||
showGoodsStateDialog() { |
||||
showDialog( |
||||
context: context, |
||||
builder: (context) { |
||||
return AlertDialog( |
||||
content: Container( |
||||
width: MediaQuery.of(context).size.width - 84, |
||||
height: 139.h, |
||||
child: Column( |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
children: [ |
||||
Text( |
||||
"选中数据将被下架, 是否继续?", |
||||
style: TextStyle( |
||||
color: Color(0xFFF4524D), |
||||
fontSize: 16.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
), |
||||
SizedBox( |
||||
height: 35.h, |
||||
), |
||||
Row( |
||||
children: [ |
||||
Expanded( |
||||
child: InkWell( |
||||
child: BorderText( |
||||
text: S.of(context).quxiao, |
||||
textColor: Color(0xFF30415B), |
||||
fontSize: 16.sp, |
||||
fontWeight: FontWeight.bold, |
||||
borderColor: Color(0xFF30415B), |
||||
radius: 4, |
||||
padding: EdgeInsets.all(12), |
||||
borderWidth: 1, |
||||
), |
||||
onTap: () { |
||||
Navigator.of(context).pop(); |
||||
}, |
||||
), |
||||
flex: 1, |
||||
), |
||||
SizedBox( |
||||
width: 16.w, |
||||
), |
||||
Expanded( |
||||
child: InkWell( |
||||
child: RoundButton( |
||||
text: S.of(context).queren, |
||||
textColor: Colors.white, |
||||
radius: 4, |
||||
padding: EdgeInsets.all(12), |
||||
backgroup: Color(0xFF30415B), |
||||
fontSize: 16.sp, |
||||
fontWeight: FontWeight.bold, |
||||
), |
||||
onTap: () { |
||||
Navigator.of(context).pop(); |
||||
queryGoodsUpdate(); |
||||
}, |
||||
), |
||||
flex: 1, |
||||
), |
||||
], |
||||
) |
||||
], |
||||
), |
||||
), |
||||
); |
||||
}, |
||||
); |
||||
} |
||||
|
||||
///左边list |
||||
Widget shelfLeftItem(Records records, index) { |
||||
return Container( |
||||
color: groupIndex == index ? Colors.white : Color(0xFFFAFAFA), |
||||
alignment: Alignment.center, |
||||
padding: EdgeInsets.symmetric(vertical: 16.h, horizontal: 14.w), |
||||
child: Row( |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
children: [ |
||||
Expanded( |
||||
child: Text( |
||||
records?.groupName ?? "", |
||||
textAlign: TextAlign.center, |
||||
style: TextStyle( |
||||
color: |
||||
groupIndex == index ? Color(0xFF30415B) : Color(0xFF626264), |
||||
fontSize: 12.sp, |
||||
fontWeight: groupIndex == index |
||||
? MyFontWeight.semi_bold |
||||
: MyFontWeight.regular, |
||||
), |
||||
)), |
||||
], |
||||
), |
||||
); |
||||
} |
||||
|
||||
Widget shelfGoodsItem(AdminProductVoList adminProductVo) { |
||||
return Container( |
||||
margin: EdgeInsets.only(bottom: 21.h, left: 16.w), |
||||
child: Row( |
||||
children: [ |
||||
MImage( |
||||
adminProductVo?.productImg ?? "", |
||||
width: 77.h, |
||||
height: 77.h, |
||||
fit: BoxFit.cover, |
||||
radius: BorderRadius.circular(4), |
||||
), |
||||
SizedBox( |
||||
width: 12.w, |
||||
), |
||||
Expanded( |
||||
child: Column( |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Padding( |
||||
padding: EdgeInsets.only(top: 2.h), |
||||
child: Text( |
||||
adminProductVo?.productName ?? "", |
||||
maxLines: 1, |
||||
overflow: TextOverflow.ellipsis, |
||||
style: TextStyle( |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.medium, |
||||
color: Color(0xFF000000), |
||||
), |
||||
)), |
||||
Row( |
||||
children: [ |
||||
Text( |
||||
"库存${adminProductVo?.stock ?? 0}", |
||||
style: TextStyle( |
||||
fontSize: 10.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
color: Color(0xFFA29E9E), |
||||
), |
||||
), |
||||
SizedBox( |
||||
width: 8.w, |
||||
), |
||||
Expanded( |
||||
child: Text( |
||||
"销量${adminProductVo?.sellCount ?? 0}", |
||||
style: TextStyle( |
||||
fontSize: 10.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
color: Color(0xFF999999), |
||||
), |
||||
)), |
||||
Checkbox( |
||||
value: adminProductVo.isSelect, |
||||
onChanged: (a) { |
||||
if (!adminProductVo.isSelect) { |
||||
if (selectedProductVoList.length >= groupNum) { |
||||
SmartDialog.showToast("商品分组总数只有${groupNum}个,无法添加更多", alignment: Alignment.center); |
||||
return; |
||||
} |
||||
} |
||||
setState(() { |
||||
adminProductVo.isSelect = !adminProductVo.isSelect; |
||||
if (adminProductVo.isSelect) { |
||||
selectedProductVoList.add(adminProductVo); |
||||
} else { |
||||
selectedProductVoList.remove(adminProductVo); |
||||
} |
||||
}); |
||||
}, |
||||
shape: RoundedRectangleBorder( |
||||
borderRadius: BorderRadius.circular(2.0), |
||||
), |
||||
checkColor: Color(0xFFFFFFFF), |
||||
fillColor: MaterialStateProperty.all(Color(0xFF30415B)), |
||||
), |
||||
], |
||||
), |
||||
SizedBox( |
||||
height: 7.h, |
||||
), |
||||
Row( |
||||
children: [ |
||||
Expanded( |
||||
child: Text.rich( |
||||
TextSpan( |
||||
children: [ |
||||
TextSpan( |
||||
text: "¥", |
||||
style: TextStyle( |
||||
fontSize: 12.sp, |
||||
fontWeight: MyFontWeight.medium, |
||||
color: Color(0xFFF4524D), |
||||
), |
||||
), |
||||
TextSpan( |
||||
text: adminProductVo?.price ?? "", |
||||
style: TextStyle( |
||||
fontSize: 18.sp, |
||||
fontWeight: MyFontWeight.medium, |
||||
color: Color(0xFFF4524D), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
)), |
||||
if (titleName == "选择商品") |
||||
GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
setState(() { |
||||
if (adminProductVo.goodsNumber <= 1) return; |
||||
adminProductVo?.goodsNumber = |
||||
adminProductVo.goodsNumber - 1; |
||||
}); |
||||
}, |
||||
child: Container( |
||||
padding: EdgeInsets.symmetric(horizontal: 10.w), |
||||
child: Icon( |
||||
Icons.remove_circle_outline, |
||||
color: Color(0xFF30415B), |
||||
size: 24, |
||||
))), |
||||
if (titleName == "选择商品") |
||||
Text( |
||||
adminProductVo?.goodsNumber?.toString() ?? "", |
||||
style: TextStyle( |
||||
color: Color(0xD9000000), |
||||
fontSize: 20.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
), |
||||
if (titleName == "选择商品") |
||||
GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
setState(() { |
||||
adminProductVo.goodsNumber = |
||||
adminProductVo.goodsNumber + 1; |
||||
}); |
||||
}, |
||||
child: Container( |
||||
padding: EdgeInsets.symmetric(horizontal: 10.w), |
||||
child: Icon( |
||||
Icons.add_circle, |
||||
color: Color(0xFF30415B), |
||||
size: 24, |
||||
)), |
||||
), |
||||
], |
||||
), |
||||
], |
||||
)), |
||||
], |
||||
), |
||||
); |
||||
} |
||||
|
||||
Widget shelfLeftItemSm() { |
||||
return Container( |
||||
alignment: Alignment.center, |
||||
padding: EdgeInsets.symmetric(vertical: 16.h, horizontal: 14.w), |
||||
child: Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 48.w, |
||||
height: 30.h, |
||||
), |
||||
), |
||||
); |
||||
} |
||||
|
||||
Widget shelfGoodsItemSm() { |
||||
return Container( |
||||
margin: EdgeInsets.only(bottom: 21.h, left: 16.w, right: 16.w, top: 10.h), |
||||
child: Row( |
||||
children: [ |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(4), |
||||
), |
||||
width: 70.h, |
||||
height: 70.h, |
||||
), |
||||
), |
||||
SizedBox( |
||||
width: 12.w, |
||||
), |
||||
Expanded( |
||||
child: Column( |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Padding( |
||||
padding: EdgeInsets.only(bottom: 11.h, top: 2.h), |
||||
child: Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 124.w, |
||||
height: 20.h, |
||||
), |
||||
), |
||||
), |
||||
Row( |
||||
children: [ |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 43.w, |
||||
height: 18.h, |
||||
), |
||||
), |
||||
SizedBox( |
||||
width: 8.w, |
||||
), |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 43.w, |
||||
height: 18.h, |
||||
), |
||||
), |
||||
Spacer(), |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 16.h, |
||||
height: 16.h, |
||||
), |
||||
), |
||||
], |
||||
), |
||||
SizedBox( |
||||
height: 7.h, |
||||
), |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 28.w, |
||||
height: 20.h, |
||||
), |
||||
), |
||||
], |
||||
)), |
||||
], |
||||
), |
||||
); |
||||
} |
||||
|
||||
Widget noNetwork() { |
||||
return Container( |
||||
color: Colors.white, |
||||
width: double.infinity, |
||||
child: Column( |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
Text( |
||||
networkError.substring(0, networkError.indexOf(",")), |
||||
style: TextStyle( |
||||
fontSize: 14.sp, |
||||
color: Color(0xFF0D0D0D), |
||||
fontWeight: MyFontWeight.bold), |
||||
), |
||||
Padding( |
||||
padding: EdgeInsets.symmetric(vertical: 10.h), |
||||
child: Text( |
||||
"请检查网络设置或稍后重试", |
||||
style: TextStyle( |
||||
fontSize: 12.sp, |
||||
color: Color(0xFF7A797F), |
||||
fontWeight: MyFontWeight.regular), |
||||
), |
||||
), |
||||
GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
_onRefresh(); |
||||
}, |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0xFF30415B), |
||||
borderRadius: BorderRadius.circular(15), |
||||
), |
||||
padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 3.h), |
||||
child: Text( |
||||
"重试", |
||||
style: TextStyle( |
||||
fontSize: 14.sp, |
||||
color: Colors.white, |
||||
fontWeight: MyFontWeight.regular), |
||||
)), |
||||
) |
||||
], |
||||
), |
||||
); |
||||
} |
||||
} |
@ -1,488 +0,0 @@
|
||||
import 'package:dio/dio.dart'; |
||||
import 'package:flutter/material.dart'; |
||||
import 'package:flutter_easyloading/flutter_easyloading.dart'; |
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; |
||||
import 'package:huixiang/utils/font_weight.dart'; |
||||
import 'package:huixiang/view_widget/my_appbar.dart'; |
||||
import 'package:pull_to_refresh/pull_to_refresh.dart'; |
||||
import 'package:flutter_screenutil/flutter_screenutil.dart'; |
||||
import 'package:shimmer/shimmer.dart'; |
||||
|
||||
import '../../../generated/l10n.dart'; |
||||
import '../../../retrofit/business_api.dart'; |
||||
import '../../../retrofit/data/base_data.dart'; |
||||
import '../../../retrofit/data/product_group_list.dart'; |
||||
import '../../../utils/business_instance.dart'; |
||||
import '../../../utils/flutter_utils.dart'; |
||||
import '../../../view_widget/border_text.dart'; |
||||
import '../../../view_widget/classic_header.dart'; |
||||
import '../../../view_widget/my_footer.dart'; |
||||
import '../../../view_widget/no_data_view.dart'; |
||||
import '../../../view_widget/round_button.dart'; |
||||
import '../../../view_widget/settlement_tips_dialog.dart'; |
||||
|
||||
class GoodsAssort extends StatefulWidget { |
||||
final Map<String, dynamic> arguments; |
||||
|
||||
GoodsAssort({this.arguments}); |
||||
|
||||
@override |
||||
State<StatefulWidget> createState() { |
||||
return _GoodsAssort(); |
||||
} |
||||
} |
||||
|
||||
class _GoodsAssort extends State<GoodsAssort> { |
||||
final RefreshController refreshController = RefreshController(); |
||||
BusinessApiService businessService; |
||||
ProductGroupList productGroupList; |
||||
String networkError = ""; |
||||
int networkStatus = 0; |
||||
|
||||
@override |
||||
void initState() { |
||||
super.initState(); |
||||
_onRefresh(); |
||||
} |
||||
|
||||
_onRefresh({bool isShowLoad = true}) async { |
||||
if (isShowLoad) |
||||
EasyLoading.show( |
||||
status: S.current.zhengzaijiazai, |
||||
maskType: EasyLoadingMaskType.black); |
||||
await queryProductGroupList(); |
||||
EasyLoading.dismiss(); |
||||
if (refreshController.isRefresh) refreshController.refreshCompleted(); |
||||
if (mounted) |
||||
setState(() {}); |
||||
} |
||||
|
||||
///分组列表 |
||||
queryProductGroupList() async { |
||||
if (businessService == null) { |
||||
businessService = BusinessApiService(Dio(), |
||||
context: context, |
||||
token: BusinessInstance.instance.businessToken, |
||||
tenant: BusinessInstance.instance.businessTenant, |
||||
storeId: widget.arguments["storeId"]); |
||||
} |
||||
BaseData<ProductGroupList> baseData = await businessService.productGroup({ |
||||
"current": 1, |
||||
"map": {}, |
||||
"model": {"groupImg": "", "groupName": "", "isDelete": 0}, |
||||
"order": "ascending", |
||||
"size": 100, |
||||
"sort": "sort" |
||||
}).catchError((error) { |
||||
networkError = AppUtils.dioErrorTypeToString(error.type); |
||||
networkStatus = -1; |
||||
setState(() {}); |
||||
refreshController.refreshFailed(); |
||||
refreshController.loadFailed(); |
||||
}); |
||||
if (baseData != null && baseData.isSuccess) { |
||||
productGroupList = baseData.data; |
||||
networkStatus = 1; |
||||
} else { |
||||
SmartDialog.showToast(baseData.msg, alignment: Alignment.center); |
||||
} |
||||
} |
||||
|
||||
///删除分组分类 |
||||
queryDelGroup(id) async { |
||||
if (businessService == null) { |
||||
businessService = BusinessApiService(Dio(), |
||||
context: context, |
||||
token: BusinessInstance.instance.businessToken, |
||||
tenant: BusinessInstance.instance.businessTenant, |
||||
storeId: widget.arguments["storeId"]); |
||||
} |
||||
BaseData baseData = await businessService.delProductCategory({ |
||||
"id":id, |
||||
}).catchError((error) {}); |
||||
if (baseData != null && baseData.isSuccess) { |
||||
await _onRefresh(); |
||||
SmartDialog.showToast("分组删除成功", alignment: Alignment.center); |
||||
} else { |
||||
SmartDialog.showToast(baseData.msg, alignment: Alignment.center); |
||||
} |
||||
} |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return Scaffold( |
||||
backgroundColor: Colors.white, |
||||
appBar: MyAppBar( |
||||
title: "商品分类", |
||||
titleColor: Colors.black, |
||||
background: Colors.white, |
||||
leadingColor: Colors.black, |
||||
brightness: Brightness.dark, |
||||
), |
||||
body: networkStatus == -1?noNetwork():Container( |
||||
margin: EdgeInsets.only(top: 24.h, left: 16.w, right: 16.w), |
||||
child: Column( |
||||
children: [ |
||||
Expanded( |
||||
child: Container( |
||||
child: SmartRefresher( |
||||
controller: refreshController, |
||||
enablePullDown: true, |
||||
enablePullUp: false, |
||||
header: MyHeader( |
||||
color: Color(0xFF30415B), |
||||
), |
||||
footer: CustomFooter( |
||||
builder: (context, mode) { |
||||
return MyFooter(mode); |
||||
}, |
||||
), |
||||
onRefresh: () { |
||||
_onRefresh(isShowLoad: false); |
||||
}, |
||||
physics: BouncingScrollPhysics(), |
||||
scrollController: ScrollController(), |
||||
child: Container( |
||||
child: networkStatus == 0 ?ListView.builder( |
||||
itemCount: 10, |
||||
physics: BouncingScrollPhysics(), |
||||
shrinkWrap: true, |
||||
itemBuilder: (context, position) { |
||||
return GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () {}, |
||||
child: assortItemSm(), |
||||
); |
||||
}, |
||||
): |
||||
((productGroupList == null || |
||||
productGroupList.records.length == 0) |
||||
? NoDataView( |
||||
src: "assets/image/bs_no data_logo.webp", |
||||
isShowBtn: false, |
||||
text: "暂无商品分类", |
||||
fontSize: 16.sp, |
||||
margin: EdgeInsets.all(20.h), |
||||
) |
||||
: ListView.builder( |
||||
itemCount: productGroupList?.records?.length ?? 0, |
||||
physics: BouncingScrollPhysics(), |
||||
shrinkWrap: true, |
||||
itemBuilder: (context, position) { |
||||
return GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () {}, |
||||
child: assortItem(productGroupList.records[position]), |
||||
); |
||||
}, |
||||
)), |
||||
), |
||||
), |
||||
)), |
||||
GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
if(widget.arguments["storeId"] == "0"){ |
||||
SmartDialog.show( |
||||
widget: SettlementTips( |
||||
() { |
||||
}, |
||||
text: "当前为所有门店状态,新增分组时,请将门店切换至要新增的门店!", |
||||
color: Color(0xFF30415B), |
||||
)); |
||||
}else{ |
||||
Navigator.of(context).pushNamed('/router/add_assort', |
||||
arguments: {"storeId": widget.arguments["storeId"], |
||||
"statusName":"添加分类"}).then((value) => { |
||||
_onRefresh(isShowLoad: false), |
||||
}); |
||||
} |
||||
}, |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
borderRadius: BorderRadius.circular(27), |
||||
color: Color(0xFF30415B), |
||||
), |
||||
width: double.infinity, |
||||
alignment: Alignment.center, |
||||
padding: EdgeInsets.symmetric(vertical: 16.h), |
||||
margin: EdgeInsets.only(bottom: 34.h), |
||||
child: Text( |
||||
"添加分类", |
||||
style: TextStyle( |
||||
color: Colors.white, |
||||
fontSize: 16.sp, |
||||
fontWeight: FontWeight.bold, |
||||
), |
||||
), |
||||
)), |
||||
], |
||||
), |
||||
)); |
||||
} |
||||
|
||||
///分组列表 |
||||
Widget assortItem(Records records) { |
||||
return Container( |
||||
child: Column( |
||||
children: [ |
||||
Row( |
||||
children: [ |
||||
Expanded( |
||||
child: Text( |
||||
records?.groupName ?? "", |
||||
style: TextStyle( |
||||
color: Color(0xFF000000), |
||||
fontSize: 14.sp, |
||||
fontWeight: FontWeight.bold, |
||||
), |
||||
)), |
||||
GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
if(widget.arguments["storeId"] == "0"){ |
||||
SmartDialog.show( |
||||
widget: SettlementTips( |
||||
() { |
||||
}, |
||||
text: "当前为所有门店状态,新增分组时,请将门店切换至要新增的门店!", |
||||
color: Color(0xFF30415B), |
||||
)); |
||||
}else{ |
||||
Navigator.of(context).pushNamed('/router/add_assort', |
||||
arguments: {"storeId": widget.arguments["storeId"], |
||||
"statusName":"编辑分类", |
||||
"groupName":records?.groupName ?? "", |
||||
"sort":records.sort.toString(), |
||||
"id":records?.id ?? ""}).then((value) => { |
||||
_onRefresh(isShowLoad: false), |
||||
}); |
||||
} |
||||
}, |
||||
child: Padding( |
||||
padding: EdgeInsets.symmetric(horizontal: 17.w), |
||||
child: Text( |
||||
"编辑", |
||||
style: TextStyle( |
||||
color: Color(0xFF30415B), |
||||
fontSize: 14.sp, |
||||
fontWeight: FontWeight.bold, |
||||
), |
||||
), |
||||
), |
||||
), |
||||
GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
showDelGroupDialog(records?.id ?? ""); |
||||
}, |
||||
child: Padding( |
||||
padding: EdgeInsets.only(right: 16.w, left: 17.w), |
||||
child: Text( |
||||
S.of(context).shanchu, |
||||
style: TextStyle( |
||||
color: Color(0xFFF4524D), |
||||
fontSize: 14.sp, |
||||
fontWeight: FontWeight.bold, |
||||
), |
||||
), |
||||
), |
||||
) |
||||
], |
||||
), |
||||
Container( |
||||
margin: EdgeInsets.symmetric(vertical: 16.h), |
||||
color: Color(0xFFEBEBEB), |
||||
height: 1.h, |
||||
width: double.infinity, |
||||
) |
||||
], |
||||
), |
||||
); |
||||
} |
||||
|
||||
Widget assortItemSm() { |
||||
return Container( |
||||
child: Column( |
||||
children: [ |
||||
Row( |
||||
children: [ |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 112.w, |
||||
height: 20.h, |
||||
), |
||||
), |
||||
Spacer(), |
||||
Padding( |
||||
padding: EdgeInsets.symmetric(horizontal: 17.w), |
||||
child: Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 28.w, |
||||
height: 20.h, |
||||
), |
||||
), |
||||
), |
||||
Padding( |
||||
padding: EdgeInsets.only(right: 16.w, left: 17.w), |
||||
child: Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 28.w, |
||||
height: 20.h, |
||||
), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
Container( |
||||
margin: EdgeInsets.symmetric(vertical: 16.h), |
||||
color: Color(0xFFEBEBEB), |
||||
height: 1.h, |
||||
width: double.infinity, |
||||
) |
||||
], |
||||
), |
||||
); |
||||
} |
||||
|
||||
///删除分组提示弹窗 |
||||
showDelGroupDialog(id) { |
||||
showDialog( |
||||
context: context, |
||||
builder: (context) { |
||||
return AlertDialog( |
||||
content: Container( |
||||
width: MediaQuery.of(context).size.width - 84, |
||||
height: 139.h, |
||||
child: Column( |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
children: [ |
||||
Text( |
||||
"选中数据将被永久删除, 是否继续?", |
||||
style: TextStyle( |
||||
color: Color(0xFFF4524D), |
||||
fontSize: 16.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
), |
||||
SizedBox( |
||||
height: 35.h, |
||||
), |
||||
Row( |
||||
children: [ |
||||
Expanded( |
||||
child: InkWell( |
||||
child: BorderText( |
||||
text: S.of(context).quxiao, |
||||
textColor: Color(0xFF30415B), |
||||
fontSize: 16.sp, |
||||
fontWeight: FontWeight.bold, |
||||
borderColor: Color(0xFF30415B), |
||||
radius: 4, |
||||
padding: EdgeInsets.all(12), |
||||
borderWidth: 1, |
||||
), |
||||
onTap: () { |
||||
Navigator.of(context).pop(); |
||||
}, |
||||
), |
||||
flex: 1, |
||||
), |
||||
SizedBox( |
||||
width: 16.w, |
||||
), |
||||
Expanded( |
||||
child: InkWell( |
||||
child: RoundButton( |
||||
text: S.of(context).queren, |
||||
textColor: Colors.white, |
||||
radius: 4, |
||||
padding: EdgeInsets.all(12), |
||||
backgroup: Color(0xFF30415B), |
||||
fontSize: 16.sp, |
||||
fontWeight: FontWeight.bold, |
||||
), |
||||
onTap: () { |
||||
Navigator.of(context).pop(); |
||||
queryDelGroup(id); |
||||
}, |
||||
), |
||||
flex: 1, |
||||
), |
||||
], |
||||
) |
||||
], |
||||
), |
||||
), |
||||
); |
||||
}, |
||||
); |
||||
} |
||||
|
||||
Widget noNetwork() { |
||||
return Container( |
||||
color: Colors.white, |
||||
width: double.infinity, |
||||
child: Column( |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
Text( |
||||
networkError.substring(0, networkError.indexOf(",")), |
||||
style: TextStyle( |
||||
fontSize: 14.sp, |
||||
color: Color(0xFF0D0D0D), |
||||
fontWeight: MyFontWeight.bold), |
||||
), |
||||
Padding( |
||||
padding: EdgeInsets.symmetric(vertical: 10.h), |
||||
child: Text( |
||||
"请检查网络设置或稍后重试", |
||||
style: TextStyle( |
||||
fontSize: 12.sp, |
||||
color: Color(0xFF7A797F), |
||||
fontWeight: MyFontWeight.regular), |
||||
), |
||||
), |
||||
GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
_onRefresh(); |
||||
}, |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0xFF30415B), |
||||
borderRadius: BorderRadius.circular(15), |
||||
), |
||||
padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 3.h), |
||||
child: Text( |
||||
"重试", |
||||
style: TextStyle( |
||||
fontSize: 14.sp, |
||||
color: Colors.white, |
||||
fontWeight: MyFontWeight.regular), |
||||
)), |
||||
) |
||||
], |
||||
), |
||||
); |
||||
} |
||||
} |
@ -1,625 +0,0 @@
|
||||
import 'package:dio/dio.dart'; |
||||
import 'package:flutter/material.dart'; |
||||
import 'package:flutter_easyloading/flutter_easyloading.dart'; |
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; |
||||
import 'package:huixiang/view_widget/my_appbar.dart'; |
||||
import 'package:pull_to_refresh/pull_to_refresh.dart'; |
||||
import 'package:flutter_screenutil/flutter_screenutil.dart'; |
||||
import 'package:shared_preferences/shared_preferences.dart'; |
||||
import 'package:shimmer/shimmer.dart'; |
||||
|
||||
import '../../../generated/l10n.dart'; |
||||
import '../../../retrofit/business_api.dart'; |
||||
import '../../../retrofit/data/base_data.dart'; |
||||
import '../../../retrofit/data/business_goods.dart'; |
||||
import '../../../retrofit/data/product_group_list.dart'; |
||||
import '../../../utils/business_instance.dart'; |
||||
import '../../../utils/flutter_utils.dart'; |
||||
import '../../../utils/font_weight.dart'; |
||||
import '../../../view_widget/classic_header.dart'; |
||||
import '../../../view_widget/custom_image.dart'; |
||||
import '../../../view_widget/my_footer.dart'; |
||||
import '../../../view_widget/no_data_view.dart'; |
||||
import '../../../view_widget/settlement_tips_dialog.dart'; |
||||
|
||||
class GoodsSort extends StatefulWidget { |
||||
final Map<String, dynamic> arguments; |
||||
|
||||
GoodsSort({this.arguments}); |
||||
|
||||
@override |
||||
State<StatefulWidget> createState() { |
||||
return _GoodsSort(); |
||||
} |
||||
} |
||||
|
||||
class _GoodsSort extends State<GoodsSort> { |
||||
final RefreshController _refreshController = RefreshController(); |
||||
final ScrollController controller = ScrollController(); |
||||
BusinessApiService businessService; |
||||
ProductGroupList productGroupList; |
||||
List<AdminProductVoList> adminProductVoList = []; |
||||
int _loadCount = 0; |
||||
int _pageIndex = 1; |
||||
int groupIndex = -1; |
||||
String networkError = ""; |
||||
int networkStatus = 0; |
||||
|
||||
@override |
||||
void initState() { |
||||
super.initState(); |
||||
_onRefresh(); |
||||
} |
||||
|
||||
@override |
||||
void dispose() { |
||||
super.dispose(); |
||||
_refreshController.dispose(); |
||||
} |
||||
|
||||
_onRefresh({isShowLoad = true}) async { |
||||
if (isShowLoad) |
||||
EasyLoading.show( |
||||
status: S.current.zhengzaijiazai, |
||||
maskType: EasyLoadingMaskType.black); |
||||
SharedPreferences.getInstance().then((value) { |
||||
businessService = BusinessApiService( |
||||
Dio(), |
||||
context: context, |
||||
token: BusinessInstance.instance.businessToken, |
||||
tenant: BusinessInstance.instance.businessTenant, |
||||
storeId: widget.arguments["storeId"], |
||||
); |
||||
queryProductGroupList(); |
||||
queryGoodsList( |
||||
groupIndex != -1 ? productGroupList.records[groupIndex].id : "", |
||||
isSing: false); |
||||
}); |
||||
} |
||||
|
||||
addLoadCount() { |
||||
_loadCount += 1; |
||||
if (_loadCount == 2) { |
||||
_loadCount = 0; |
||||
EasyLoading.dismiss(); |
||||
if (!mounted) return; |
||||
if (_refreshController.isRefresh) _refreshController.refreshCompleted(); |
||||
setState(() {}); |
||||
} |
||||
} |
||||
|
||||
///分组列表 |
||||
queryProductGroupList() async { |
||||
try { |
||||
BaseData<ProductGroupList> baseData = await businessService.productGroup({ |
||||
"current": 1, |
||||
"map": {}, |
||||
"model": {"groupImg": "", "groupName": "", "isDelete": 0}, |
||||
"order": "ascending", |
||||
"size": 100, |
||||
"sort": "sort" |
||||
}).catchError((error) { |
||||
}); |
||||
if (!mounted) return; |
||||
if (baseData != null && baseData.isSuccess) { |
||||
productGroupList = baseData.data; |
||||
} else { |
||||
SmartDialog.showToast(baseData.msg, alignment: Alignment.center); |
||||
} |
||||
} finally { |
||||
addLoadCount(); |
||||
} |
||||
} |
||||
|
||||
///商品列表 |
||||
queryGoodsList(groupId, {isSing = true}) async { |
||||
try { |
||||
BaseData<BusinessGoods> baseData = |
||||
await businessService.findAdminProductLis({ |
||||
"groupId": groupId, |
||||
"hasStock": "", |
||||
"keyword": "", |
||||
"pageIndex": _pageIndex, |
||||
"pageSize": 10, |
||||
"status": "1" |
||||
}).catchError((error) { |
||||
networkStatus = -1; |
||||
networkError = AppUtils.dioErrorTypeToString(error.type); |
||||
_refreshController.refreshFailed(); |
||||
_refreshController.loadFailed(); |
||||
}); |
||||
if (!mounted) return; |
||||
if (baseData != null && baseData.isSuccess) { |
||||
adminProductVoList.addAll(baseData?.data?.adminProductVOList ?? []); |
||||
if ((baseData?.data?.adminProductVOList ?? []).isEmpty || |
||||
adminProductVoList.length == baseData.data.total) { |
||||
_refreshController.loadNoData(); |
||||
} else { |
||||
_refreshController.loadComplete(); |
||||
} |
||||
networkStatus = 1; |
||||
} else { |
||||
SmartDialog.showToast(baseData.msg, alignment: Alignment.center); |
||||
} |
||||
} finally { |
||||
if (isSing) { |
||||
setState(() {}); |
||||
} else { |
||||
addLoadCount(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
///商品排序/一键置顶 |
||||
goodsSortTop(id) async { |
||||
try{ |
||||
EasyLoading.show( |
||||
status: S.current.zhengzaijiazai, maskType: EasyLoadingMaskType.black); |
||||
if (businessService == null) { |
||||
businessService = BusinessApiService(Dio(), |
||||
context: context, |
||||
token: BusinessInstance.instance.businessToken, |
||||
tenant: BusinessInstance.instance.businessTenant, |
||||
storeId: widget.arguments["storeId"]); |
||||
} |
||||
BaseData baseData = await businessService.productSortTop({ |
||||
"id": id, |
||||
}).catchError((error) {}); |
||||
if (baseData != null && baseData.isSuccess) { |
||||
_pageIndex = 1; |
||||
adminProductVoList.clear(); |
||||
await queryGoodsList(groupIndex == -1 |
||||
? "" |
||||
: productGroupList?.records[groupIndex]?.id ?? "",isSing: false); |
||||
SmartDialog.showToast("商品置顶成功", alignment: Alignment.center); |
||||
setState(() {}); |
||||
} else { |
||||
SmartDialog.showToast(baseData.msg, alignment: Alignment.center); |
||||
} |
||||
}finally{ |
||||
EasyLoading.dismiss(); |
||||
} |
||||
} |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return Scaffold( |
||||
backgroundColor: Colors.white, |
||||
appBar: MyAppBar( |
||||
title: "商品排序", |
||||
titleColor: Colors.black, |
||||
background: Colors.white, |
||||
leadingColor: Colors.black, |
||||
brightness: Brightness.dark, |
||||
), |
||||
body: networkStatus == -1 ? noNetwork() : Row( |
||||
mainAxisAlignment: MainAxisAlignment.start, |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Container( |
||||
width: 100.w, |
||||
height: double.infinity, |
||||
padding: EdgeInsets.only(bottom: 70.h), |
||||
color: Color(0xFFFAFAFA), |
||||
child: networkStatus == 0 |
||||
? ListView.builder( |
||||
itemCount: 10, |
||||
physics: BouncingScrollPhysics(), |
||||
shrinkWrap: true, |
||||
itemBuilder: (context, position) { |
||||
return sortLeftItemSm(); |
||||
}, |
||||
) |
||||
: ListView.builder( |
||||
itemCount: productGroupList?.records?.length ?? 0, |
||||
physics: BouncingScrollPhysics(), |
||||
shrinkWrap: true, |
||||
itemBuilder: (context, position) { |
||||
return GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
groupIndex = position; |
||||
_pageIndex = 1; |
||||
adminProductVoList.clear(); |
||||
queryGoodsList( |
||||
productGroupList?.records[position].id, |
||||
); |
||||
}, |
||||
child: sortLeftItem( |
||||
productGroupList.records[position], position), |
||||
); |
||||
}, |
||||
), |
||||
), |
||||
Container( |
||||
width: MediaQuery.of(context).size.width - 100.w, |
||||
child: SmartRefresher( |
||||
controller: _refreshController, |
||||
enablePullDown: true, |
||||
enablePullUp: adminProductVoList.length != 0 ? true : false, |
||||
header: MyHeader( |
||||
color: Color(0xFF30415B), |
||||
), |
||||
physics: BouncingScrollPhysics(), |
||||
footer: CustomFooter( |
||||
builder: (context, mode) { |
||||
return MyFooter(mode); |
||||
}, |
||||
), |
||||
onLoading: () { |
||||
_pageIndex++; |
||||
queryGoodsList(groupIndex == -1 |
||||
? "" |
||||
: productGroupList?.records[groupIndex].id); |
||||
}, |
||||
onRefresh: () { |
||||
_pageIndex = 1; |
||||
adminProductVoList.clear(); |
||||
_onRefresh(isShowLoad: false); |
||||
}, |
||||
child: Container( |
||||
color: Colors.white, |
||||
child: networkStatus == 0 |
||||
? ListView.builder( |
||||
itemCount: 10, |
||||
physics: BouncingScrollPhysics(), |
||||
shrinkWrap: true, |
||||
itemBuilder: (context, position) { |
||||
return sortGoodsItemSm(); |
||||
}, |
||||
) |
||||
: ((adminProductVoList == null || |
||||
adminProductVoList.length == 0) |
||||
? NoDataView( |
||||
src: "assets/image/bs_no data_logo.webp", |
||||
isShowBtn: false, |
||||
text: "该分组暂无添加商品", |
||||
fontSize: 16.sp, |
||||
margin: EdgeInsets.all(20.h), |
||||
) |
||||
: ListView.builder( |
||||
itemCount: adminProductVoList?.length ?? 0, |
||||
controller: controller, |
||||
physics: BouncingScrollPhysics(), |
||||
shrinkWrap: true, |
||||
itemBuilder: (context, position) { |
||||
return sortGoodsItem( |
||||
adminProductVoList[position]); |
||||
}, |
||||
)))), |
||||
), |
||||
], |
||||
), |
||||
); |
||||
} |
||||
|
||||
///左边list |
||||
Widget sortLeftItem(Records records, index) { |
||||
return Container( |
||||
color: groupIndex == index ? Colors.white : Color(0xFFFAFAFA), |
||||
alignment: Alignment.center, |
||||
padding: EdgeInsets.symmetric(vertical: 16.h, horizontal: 14.w), |
||||
child: Row( |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
children: [ |
||||
Expanded( |
||||
child: Text( |
||||
records?.groupName ?? "", |
||||
textAlign: TextAlign.center, |
||||
style: TextStyle( |
||||
color: |
||||
groupIndex == index ? Color(0xFF30415B) : Color(0xFF626264), |
||||
fontSize: 12.sp, |
||||
fontWeight: groupIndex == index |
||||
? MyFontWeight.semi_bold |
||||
: MyFontWeight.regular, |
||||
), |
||||
)), |
||||
], |
||||
), |
||||
); |
||||
} |
||||
|
||||
///右边List |
||||
Widget sortGoodsItem(AdminProductVoList adminProductVoList) { |
||||
return Container( |
||||
margin: EdgeInsets.only(bottom: 21.h), |
||||
padding: EdgeInsets.only(left: 16.w, right: 14.w), |
||||
child: Row( |
||||
children: [ |
||||
MImage( |
||||
adminProductVoList?.productImg ?? "", |
||||
width: 77.h, |
||||
height: 77.h, |
||||
fit: BoxFit.cover, |
||||
radius: BorderRadius.circular(4), |
||||
), |
||||
SizedBox( |
||||
width: 12.w, |
||||
), |
||||
Expanded( |
||||
child: Column( |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Padding( |
||||
padding: EdgeInsets.only(bottom: 11.h, top: 2.h), |
||||
child: Row( |
||||
children: [ |
||||
Expanded( |
||||
child: Text( |
||||
adminProductVoList?.productName ?? "", |
||||
maxLines: 1, |
||||
overflow: TextOverflow.ellipsis, |
||||
style: TextStyle( |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.medium, |
||||
color: Color(0xFF000000), |
||||
), |
||||
)), |
||||
GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
if (widget.arguments["storeId"] == "0") { |
||||
SmartDialog.show( |
||||
widget: SettlementTips( |
||||
() {}, |
||||
text: "当前为所有门店状态,置顶商品时,请将门店切换至对应门店操作!", |
||||
color: Color(0xFF30415B), |
||||
)); |
||||
} else { |
||||
goodsSortTop(adminProductVoList.id); |
||||
} |
||||
}, |
||||
child: Padding( |
||||
padding: EdgeInsets.only(left:10.w,top: 2.h,bottom: 2.h), |
||||
child: Text( |
||||
"置顶", |
||||
style: TextStyle( |
||||
fontSize: 12.sp, |
||||
fontWeight: MyFontWeight.medium, |
||||
color: Color(0xFFF4524D), |
||||
), |
||||
), |
||||
)) |
||||
], |
||||
), |
||||
), |
||||
Row( |
||||
children: [ |
||||
Text( |
||||
"库存${adminProductVoList?.stock ?? 0}", |
||||
style: TextStyle( |
||||
fontSize: 10.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
color: Color(0xFFA29E9E), |
||||
), |
||||
), |
||||
SizedBox( |
||||
width: 8.w, |
||||
), |
||||
Text( |
||||
"销量${adminProductVoList?.sellCount ?? 0}", |
||||
style: TextStyle( |
||||
fontSize: 10.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
color: Color(0xFF999999), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
SizedBox( |
||||
height: 7.h, |
||||
), |
||||
Text.rich( |
||||
TextSpan( |
||||
children: [ |
||||
TextSpan( |
||||
text: "¥", |
||||
style: TextStyle( |
||||
fontSize: 12.sp, |
||||
fontWeight: MyFontWeight.medium, |
||||
color: Color(0xFFF4524D), |
||||
), |
||||
), |
||||
TextSpan( |
||||
text: adminProductVoList?.price ?? "", |
||||
style: TextStyle( |
||||
fontSize: 18.sp, |
||||
fontWeight: MyFontWeight.medium, |
||||
color: Color(0xFFF4524D), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
) |
||||
], |
||||
)), |
||||
], |
||||
), |
||||
); |
||||
} |
||||
|
||||
Widget sortLeftItemSm() { |
||||
return Container( |
||||
alignment: Alignment.center, |
||||
padding: EdgeInsets.symmetric(vertical: 16.h, horizontal: 14.w), |
||||
child: Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 48.w, |
||||
height: 30.h, |
||||
), |
||||
), |
||||
); |
||||
} |
||||
|
||||
Widget sortGoodsItemSm() { |
||||
return Container( |
||||
margin: EdgeInsets.only(bottom: 21.h, left: 16.w, right: 16.w, top: 10.h), |
||||
child: Row( |
||||
children: [ |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(4), |
||||
), |
||||
width: 70.h, |
||||
height: 70.h, |
||||
), |
||||
), |
||||
SizedBox( |
||||
width: 12.w, |
||||
), |
||||
Expanded( |
||||
child: Column( |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Padding( |
||||
padding: EdgeInsets.only(bottom: 11.h, top: 2.h), |
||||
child: Row( |
||||
children: [ |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 120.w, |
||||
height: 20.h, |
||||
), |
||||
), |
||||
SizedBox( |
||||
width: 10.w, |
||||
), |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 24.w, |
||||
height: 20.h, |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
Row( |
||||
children: [ |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 43.w, |
||||
height: 18.h, |
||||
), |
||||
), |
||||
SizedBox( |
||||
width: 8.w, |
||||
), |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 43.w, |
||||
height: 18.h, |
||||
), |
||||
), |
||||
], |
||||
), |
||||
SizedBox( |
||||
height: 7.h, |
||||
), |
||||
Row( |
||||
children: [ |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 28.w, |
||||
height: 20.h, |
||||
), |
||||
), |
||||
Spacer(), |
||||
], |
||||
) |
||||
], |
||||
)), |
||||
], |
||||
), |
||||
); |
||||
} |
||||
|
||||
Widget noNetwork() { |
||||
return Container( |
||||
color: Colors.white, |
||||
width: double.infinity, |
||||
child: Column( |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
Text( |
||||
networkError.substring(0, networkError.indexOf(",")), |
||||
style: TextStyle( |
||||
fontSize: 14.sp, |
||||
color: Color(0xFF0D0D0D), |
||||
fontWeight: MyFontWeight.bold), |
||||
), |
||||
Padding( |
||||
padding: EdgeInsets.symmetric(vertical: 10.h), |
||||
child: Text( |
||||
"请检查网络设置或稍后重试", |
||||
style: TextStyle( |
||||
fontSize: 12.sp, |
||||
color: Color(0xFF7A797F), |
||||
fontWeight: MyFontWeight.regular), |
||||
), |
||||
), |
||||
GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
_onRefresh(); |
||||
}, |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0xFF30415B), |
||||
borderRadius: BorderRadius.circular(15), |
||||
), |
||||
padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 3.h), |
||||
child: Text( |
||||
"重试", |
||||
style: TextStyle( |
||||
fontSize: 14.sp, |
||||
color: Colors.white, |
||||
fontWeight: MyFontWeight.regular), |
||||
)), |
||||
) |
||||
], |
||||
), |
||||
); |
||||
} |
||||
} |
@ -1,942 +0,0 @@
|
||||
import 'package:dio/dio.dart'; |
||||
import 'package:flutter/cupertino.dart'; |
||||
import 'package:flutter/material.dart'; |
||||
import 'package:flutter_easyloading/flutter_easyloading.dart'; |
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; |
||||
import 'package:huixiang/view_widget/classic_header.dart'; |
||||
import 'package:huixiang/view_widget/my_footer.dart'; |
||||
import 'package:pull_to_refresh/pull_to_refresh.dart'; |
||||
import 'package:flutter_screenutil/flutter_screenutil.dart'; |
||||
import 'package:shared_preferences/shared_preferences.dart'; |
||||
import 'package:shimmer/shimmer.dart'; |
||||
|
||||
import '../../../generated/l10n.dart'; |
||||
import '../../../retrofit/business_api.dart'; |
||||
import '../../../retrofit/data/base_data.dart'; |
||||
import '../../../retrofit/data/business_goods.dart'; |
||||
import '../../../retrofit/data/product_group_list.dart'; |
||||
import '../../../utils/business_instance.dart'; |
||||
import '../../../utils/flutter_utils.dart'; |
||||
import '../../../utils/font_weight.dart'; |
||||
import '../../../view_widget/border_text.dart'; |
||||
import '../../../view_widget/custom_image.dart'; |
||||
import '../../../view_widget/no_data_view.dart'; |
||||
import '../../../view_widget/round_button.dart'; |
||||
|
||||
class OnSalePage extends StatefulWidget { |
||||
final String storeId; |
||||
final Function(String total) total; |
||||
|
||||
OnSalePage(this.storeId, this.total); |
||||
|
||||
@override |
||||
State<StatefulWidget> createState() { |
||||
return _OnSalePage(); |
||||
} |
||||
} |
||||
|
||||
class _OnSalePage extends State<OnSalePage> { |
||||
final RefreshController _refreshController = RefreshController(); |
||||
final ScrollController controller = ScrollController(); |
||||
BusinessApiService businessService; |
||||
ProductGroupList productGroupList; |
||||
List<AdminProductVoList> adminProductVoList = []; |
||||
int _loadCount = 0; |
||||
int _pageIndex = 1; |
||||
int groupIndex = -1; |
||||
String networkError = ""; |
||||
int networkStatus = 0; |
||||
|
||||
@override |
||||
void dispose() { |
||||
super.dispose(); |
||||
_refreshController.dispose(); |
||||
} |
||||
|
||||
@override |
||||
void initState() { |
||||
super.initState(); |
||||
_onRefresh(); |
||||
} |
||||
|
||||
_onRefresh({isShowLoad = true}) async { |
||||
if (isShowLoad) |
||||
EasyLoading.show( |
||||
status: S.current.zhengzaijiazai, |
||||
maskType: EasyLoadingMaskType.black); |
||||
SharedPreferences.getInstance().then((value) { |
||||
businessService = BusinessApiService(Dio(), |
||||
context: context, |
||||
token: BusinessInstance.instance.businessToken, |
||||
tenant: BusinessInstance.instance.businessTenant, |
||||
storeId: widget.storeId); |
||||
queryProductGroupList(); |
||||
queryGoodsList( |
||||
groupIndex != -1 ? productGroupList.records[groupIndex].id : "", |
||||
isSing: false); |
||||
}); |
||||
} |
||||
|
||||
addLoadCount() { |
||||
_loadCount += 1; |
||||
if (_loadCount == 2) { |
||||
_loadCount = 0; |
||||
EasyLoading.dismiss(); |
||||
if (!mounted) return; |
||||
if (_refreshController.isRefresh) _refreshController.refreshCompleted(); |
||||
setState(() {}); |
||||
} |
||||
} |
||||
|
||||
///分组列表 |
||||
queryProductGroupList() async { |
||||
try { |
||||
BaseData<ProductGroupList> baseData = await businessService.productGroup({ |
||||
"current": 1, |
||||
"map": {}, |
||||
"model": {"groupImg": "", "groupName": "", "isDelete": 0}, |
||||
"order": "ascending", |
||||
"size": 100, |
||||
"sort": "sort" |
||||
}).catchError((error) {}); |
||||
if (!mounted) return; |
||||
if (baseData != null && baseData.isSuccess) { |
||||
productGroupList = baseData.data; |
||||
} else { |
||||
SmartDialog.showToast(baseData.msg, alignment: Alignment.center); |
||||
} |
||||
} finally { |
||||
addLoadCount(); |
||||
} |
||||
} |
||||
|
||||
///商品列表 |
||||
queryGoodsList(groupId, {isSing = true}) async { |
||||
try { |
||||
BaseData<BusinessGoods> baseData = |
||||
await businessService.findAdminProductLis({ |
||||
"groupId": groupId, |
||||
"hasStock": "", |
||||
"keyword": "", |
||||
"pageIndex": _pageIndex, |
||||
"pageSize": 10, |
||||
"status": "1" |
||||
}).catchError((error) { |
||||
networkError = AppUtils.dioErrorTypeToString(error.type); |
||||
networkStatus = -1; |
||||
_refreshController.refreshFailed(); |
||||
_refreshController.loadFailed(); |
||||
}); |
||||
if (!mounted) return; |
||||
if (baseData != null && baseData.isSuccess) { |
||||
adminProductVoList.addAll(baseData?.data?.adminProductVOList ?? []); |
||||
widget.total(baseData.data.total.toString()); |
||||
if ((baseData?.data?.adminProductVOList ?? []).isEmpty || |
||||
adminProductVoList.length == baseData.data.total) { |
||||
_refreshController.loadNoData(); |
||||
} else { |
||||
_refreshController.loadComplete(); |
||||
} |
||||
networkStatus = 1; |
||||
} else { |
||||
SmartDialog.showToast(baseData.msg, alignment: Alignment.center); |
||||
} |
||||
} finally { |
||||
if (isSing) { |
||||
setState(() {}); |
||||
} else { |
||||
addLoadCount(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
///商品下架 |
||||
queryGoodsUpdate(productId) async { |
||||
try { |
||||
EasyLoading.show( |
||||
status: S.current.zhengzaijiazai, |
||||
maskType: EasyLoadingMaskType.black); |
||||
if (businessService == null) { |
||||
businessService = BusinessApiService(Dio(), |
||||
context: context, |
||||
token: BusinessInstance.instance.businessToken, |
||||
tenant: BusinessInstance.instance.businessTenant, |
||||
storeId: widget.storeId); |
||||
} |
||||
BaseData baseData = await businessService.goodsUpdate({ |
||||
"productId": productId, |
||||
"sell": false, |
||||
}).catchError((error) {}); |
||||
if (baseData != null && baseData.isSuccess) { |
||||
_pageIndex = 1; |
||||
adminProductVoList.clear(); |
||||
await queryGoodsList( |
||||
groupIndex == -1 |
||||
? "" |
||||
: productGroupList?.records[groupIndex]?.id ?? "", |
||||
isSing: false); |
||||
SmartDialog.showToast("商品下架成功", alignment: Alignment.center); |
||||
} else { |
||||
SmartDialog.showToast(baseData.msg, alignment: Alignment.center); |
||||
} |
||||
} finally { |
||||
EasyLoading.dismiss(); |
||||
} |
||||
} |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return Scaffold( |
||||
backgroundColor: Colors.white, |
||||
body: Stack( |
||||
alignment: Alignment.bottomCenter, |
||||
children: [ |
||||
Column( |
||||
children: [ |
||||
goodsSearch(), |
||||
Container( |
||||
color: Color(0xFFEBEBEB), |
||||
height: 1.h, |
||||
width: double.infinity, |
||||
), |
||||
Expanded( |
||||
child: networkStatus == -1 |
||||
? noNetwork() |
||||
: Container( |
||||
child: Row( |
||||
mainAxisAlignment: MainAxisAlignment.start, |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Container( |
||||
width: 100.w, |
||||
height: double.infinity, |
||||
padding: EdgeInsets.only(bottom: 70.h), |
||||
color: Color(0xFFFAFAFA), |
||||
child: networkStatus == 0 |
||||
? ListView.builder( |
||||
itemCount: 10, |
||||
physics: BouncingScrollPhysics(), |
||||
shrinkWrap: true, |
||||
itemBuilder: (context, position) { |
||||
return leftItemSm(); |
||||
}, |
||||
) |
||||
: ListView.builder( |
||||
itemCount: |
||||
productGroupList?.records?.length ?? |
||||
0, |
||||
physics: BouncingScrollPhysics(), |
||||
shrinkWrap: true, |
||||
itemBuilder: (context, position) { |
||||
return GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
groupIndex = position; |
||||
_pageIndex = 1; |
||||
adminProductVoList.clear(); |
||||
queryGoodsList(productGroupList |
||||
?.records[position].id); |
||||
}, |
||||
child: leftItem( |
||||
productGroupList |
||||
.records[position], |
||||
position), |
||||
); |
||||
}, |
||||
), |
||||
), |
||||
Container( |
||||
width: MediaQuery.of(context).size.width - 100.w, |
||||
child: SmartRefresher( |
||||
controller: _refreshController, |
||||
enablePullDown: true, |
||||
enablePullUp: adminProductVoList.length != 0 |
||||
? true |
||||
: false, |
||||
header: MyHeader( |
||||
color: Color(0xFF30415B), |
||||
), |
||||
physics: BouncingScrollPhysics(), |
||||
footer: CustomFooter( |
||||
builder: (context, mode) { |
||||
return MyFooter(mode); |
||||
}, |
||||
), |
||||
onLoading: () { |
||||
_pageIndex++; |
||||
queryGoodsList(groupIndex == -1 |
||||
? "" |
||||
: productGroupList |
||||
?.records[groupIndex].id); |
||||
}, |
||||
onRefresh: () { |
||||
_pageIndex = 1; |
||||
adminProductVoList.clear(); |
||||
_onRefresh(isShowLoad: false); |
||||
}, |
||||
child: Container( |
||||
color: Colors.white, |
||||
child: networkStatus == 0 |
||||
? ListView.builder( |
||||
itemCount: 10, |
||||
physics: BouncingScrollPhysics(), |
||||
shrinkWrap: true, |
||||
itemBuilder: (context, position) { |
||||
return rightGoodsSm(); |
||||
}, |
||||
) |
||||
: ((adminProductVoList == null || |
||||
adminProductVoList.length == |
||||
0) |
||||
? NoDataView( |
||||
src: |
||||
"assets/image/bs_no data_logo.webp", |
||||
isShowBtn: false, |
||||
text: "该分组暂无添加商品", |
||||
fontSize: 16.sp, |
||||
margin: EdgeInsets.all(20.h), |
||||
) |
||||
: ListView.builder( |
||||
itemCount: adminProductVoList |
||||
?.length ?? |
||||
0, |
||||
controller: controller, |
||||
physics: |
||||
BouncingScrollPhysics(), |
||||
shrinkWrap: true, |
||||
itemBuilder: |
||||
(context, position) { |
||||
return rightGoodsItem( |
||||
adminProductVoList[ |
||||
position]); |
||||
}, |
||||
)))), |
||||
), |
||||
], |
||||
))), |
||||
], |
||||
), |
||||
Row( |
||||
children: [ |
||||
Expanded( |
||||
child: GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
Navigator.of(context).pushNamed('/router/goods_assort', |
||||
arguments: {"storeId": widget.storeId}).then((value) { |
||||
adminProductVoList.clear(); |
||||
_onRefresh(); |
||||
}); |
||||
}, |
||||
child: Container( |
||||
color: Color(0xFFEDEDED), |
||||
padding: EdgeInsets.only( |
||||
left: 16.w, |
||||
right: 16.w, |
||||
top: 21.h, |
||||
bottom: 24.h, |
||||
), |
||||
child: Row( |
||||
children: [ |
||||
Text( |
||||
"分类管理", |
||||
style: TextStyle( |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.semi_bold, |
||||
color: Color(0xFF30415B), |
||||
), |
||||
), |
||||
SizedBox( |
||||
width: 2.w, |
||||
), |
||||
Image.asset( |
||||
"assets/image/business.webp", |
||||
width: 18.h, |
||||
height: 18.h, |
||||
), |
||||
], |
||||
)), |
||||
), |
||||
), |
||||
Expanded( |
||||
child: GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
Navigator.of(context).pushNamed('/router/goods_sort', |
||||
arguments: {"storeId": widget.storeId}).then((value) { |
||||
adminProductVoList.clear(); |
||||
_onRefresh(); |
||||
}); |
||||
}, |
||||
child: Container( |
||||
color: Color(0xFFEDEDED), |
||||
padding: EdgeInsets.only( |
||||
left: 16.w, |
||||
right: 16.w, |
||||
top: 21.h, |
||||
bottom: 24.h, |
||||
), |
||||
child: Row( |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
Text( |
||||
"商品排序", |
||||
style: TextStyle( |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.semi_bold, |
||||
color: Color(0xFF30415B), |
||||
), |
||||
), |
||||
SizedBox( |
||||
width: 2.w, |
||||
), |
||||
Image.asset( |
||||
"assets/image/bs_px.webp", |
||||
width: 18.h, |
||||
height: 18.h, |
||||
), |
||||
], |
||||
))), |
||||
), |
||||
Expanded( |
||||
child: GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
Navigator.of(context).pushNamed('/router/batch_shelf', |
||||
arguments: {"storeId": widget.storeId,"titleName":"批量下架"}).then((value) { |
||||
adminProductVoList.clear(); |
||||
_onRefresh(); |
||||
}); |
||||
}, |
||||
child: Container( |
||||
color: Color(0xFFEDEDED), |
||||
padding: EdgeInsets.only( |
||||
left: 16.w, |
||||
right: 16.w, |
||||
top: 21.h, |
||||
bottom: 24.h, |
||||
), |
||||
child: Row( |
||||
mainAxisAlignment: MainAxisAlignment.end, |
||||
children: [ |
||||
Text( |
||||
"批量下架", |
||||
style: TextStyle( |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.semi_bold, |
||||
color: Color(0xFF30415B), |
||||
), |
||||
), |
||||
SizedBox( |
||||
width: 2.w, |
||||
), |
||||
Image.asset( |
||||
"assets/image/bs_xj.webp", |
||||
width: 18, |
||||
height: 18, |
||||
), |
||||
], |
||||
))), |
||||
), |
||||
], |
||||
), |
||||
], |
||||
), |
||||
); |
||||
} |
||||
|
||||
/// 搜索框 |
||||
Widget goodsSearch() { |
||||
return GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
Navigator.of(context) |
||||
.pushNamed('/router/goods_search_page', arguments: { |
||||
"storeId": widget.storeId, |
||||
"onSaleStatus": "1", |
||||
}).then((value) => { |
||||
_pageIndex = 1, |
||||
adminProductVoList.clear(), |
||||
queryGoodsList(groupIndex == -1 |
||||
? "" |
||||
: productGroupList?.records[groupIndex]?.id ?? "") |
||||
}); |
||||
}, |
||||
child: Container( |
||||
height: 40.h, |
||||
margin: EdgeInsets.fromLTRB(18.w, 16.h, 18.w, 10.h), |
||||
padding: EdgeInsets.fromLTRB(12.w, 6.h, 0, 6.h), |
||||
decoration: BoxDecoration( |
||||
color: Color(0xFFF7F8FA), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
child: Row( |
||||
children: [ |
||||
Image.asset( |
||||
"assets/image/bs_goods_search.webp", |
||||
width: 20, |
||||
height: 20, |
||||
), |
||||
SizedBox( |
||||
width: 3.w, |
||||
), |
||||
Text( |
||||
"请输入搜索内容", |
||||
style: TextStyle( |
||||
fontSize: 15.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
color: Color(0xFF808080), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
); |
||||
} |
||||
|
||||
///左边list |
||||
Widget leftItem(Records records, index) { |
||||
return Container( |
||||
color: groupIndex == index ? Colors.white : Color(0xFFFAFAFA), |
||||
alignment: Alignment.center, |
||||
padding: EdgeInsets.symmetric(vertical: 16.h, horizontal: 14.w), |
||||
child: Row( |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
children: [ |
||||
Expanded( |
||||
child: Text( |
||||
records?.groupName ?? "", |
||||
textAlign: TextAlign.center, |
||||
style: TextStyle( |
||||
color: |
||||
groupIndex == index ? Color(0xFF30415B) : Color(0xFF626264), |
||||
fontSize: 12.sp, |
||||
fontWeight: groupIndex == index |
||||
? MyFontWeight.semi_bold |
||||
: MyFontWeight.regular, |
||||
), |
||||
)), |
||||
], |
||||
), |
||||
); |
||||
} |
||||
|
||||
///确收扣款刷新 |
||||
suclear() { |
||||
_pageIndex = 1; |
||||
adminProductVoList.clear(); |
||||
queryGoodsList(groupIndex == -1 |
||||
? "" |
||||
: productGroupList?.records[groupIndex]?.id ?? ""); |
||||
} |
||||
|
||||
Widget rightGoodsItem(AdminProductVoList adminProductVoList) { |
||||
return Container( |
||||
margin: EdgeInsets.only(bottom: 21.h, left: 16.w, right: 16.w, top: 10.h), |
||||
child: Row( |
||||
crossAxisAlignment: CrossAxisAlignment.end, |
||||
children: [ |
||||
MImage( |
||||
adminProductVoList?.productImg ?? "", |
||||
width: 70.h, |
||||
height: 70.h, |
||||
fit: BoxFit.cover, |
||||
radius: BorderRadius.circular(4), |
||||
), |
||||
SizedBox( |
||||
width: 12.w, |
||||
), |
||||
Expanded( |
||||
flex: 2, |
||||
child: Column( |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Padding( |
||||
padding: EdgeInsets.only(bottom: 11.h, top: 2.h), |
||||
child: Text( |
||||
adminProductVoList?.productName ?? "", |
||||
maxLines: 1, |
||||
overflow: TextOverflow.ellipsis, |
||||
style: TextStyle( |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.medium, |
||||
color: Color(0xFF000000), |
||||
), |
||||
), |
||||
), |
||||
Row( |
||||
children: [ |
||||
Text( |
||||
"库存${adminProductVoList?.stock ?? 0}", |
||||
style: TextStyle( |
||||
fontSize: 10.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
color: Color(0xFFA29E9E), |
||||
), |
||||
), |
||||
SizedBox( |
||||
width: 8.w, |
||||
), |
||||
Text( |
||||
"销量${adminProductVoList?.sellCount ?? 0}", |
||||
style: TextStyle( |
||||
fontSize: 10.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
color: Color(0xFF999999), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
SizedBox( |
||||
height: 7.h, |
||||
), |
||||
Row( |
||||
children: [ |
||||
Expanded( |
||||
child: Text.rich( |
||||
TextSpan( |
||||
children: [ |
||||
TextSpan( |
||||
text: "¥", |
||||
style: TextStyle( |
||||
fontSize: 12.sp, |
||||
fontWeight: MyFontWeight.medium, |
||||
color: Color(0xFFF4524D), |
||||
), |
||||
), |
||||
TextSpan( |
||||
text: adminProductVoList?.price ?? "", |
||||
style: TextStyle( |
||||
fontSize: 18.sp, |
||||
fontWeight: MyFontWeight.medium, |
||||
color: Color(0xFFF4524D), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
)), |
||||
], |
||||
) |
||||
], |
||||
)), |
||||
Column( |
||||
crossAxisAlignment: CrossAxisAlignment.end, |
||||
children: [ |
||||
GestureDetector( |
||||
onTap: () { |
||||
Navigator.of(context) |
||||
.pushNamed('/router/reservation_page', arguments: { |
||||
"storeId": widget.storeId, |
||||
"shopId": adminProductVoList.productSkuVOList[0].storeId, |
||||
"productId": adminProductVoList.id, |
||||
"subscribeParam": adminProductVoList.subscribeParam |
||||
}).then((value) { |
||||
if (value == 1) |
||||
suclear(); |
||||
}); |
||||
}, |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Colors.white, |
||||
borderRadius: BorderRadius.circular(33), |
||||
border: Border.all( |
||||
color: Color(0x29000000), |
||||
width: 1, |
||||
), |
||||
), |
||||
margin: EdgeInsets.only(bottom: 12.h), |
||||
padding: |
||||
EdgeInsets.symmetric(vertical: 2.h, horizontal: 12.w), |
||||
child: Text( |
||||
"预售", |
||||
style: TextStyle( |
||||
fontSize: 12.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
color: Color(0x99000000), |
||||
), |
||||
), |
||||
), |
||||
), |
||||
GestureDetector( |
||||
onTap: () { |
||||
showOffShelfDialog(adminProductVoList.id ?? ""); |
||||
}, |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Colors.white, |
||||
borderRadius: BorderRadius.circular(33), |
||||
border: Border.all( |
||||
color: Color(0xFF30415B), |
||||
width: 1, |
||||
), |
||||
), |
||||
padding: |
||||
EdgeInsets.symmetric(vertical: 2.h, horizontal: 12.w), |
||||
child: Text( |
||||
"下架", |
||||
style: TextStyle( |
||||
fontSize: 12.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
color: Color(0xFF30415B), |
||||
), |
||||
), |
||||
), |
||||
) |
||||
], |
||||
) |
||||
], |
||||
), |
||||
); |
||||
} |
||||
|
||||
showOffShelfDialog(productIds) { |
||||
showDialog( |
||||
context: context, |
||||
builder: (context) { |
||||
return AlertDialog( |
||||
content: Container( |
||||
width: MediaQuery.of(context).size.width - 84, |
||||
height: 139.h, |
||||
child: Column( |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
children: [ |
||||
Text( |
||||
"选中数据将被下架, 是否继续?", |
||||
style: TextStyle( |
||||
color: Color(0xFFF4524D), |
||||
fontSize: 16.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
), |
||||
SizedBox( |
||||
height: 35.h, |
||||
), |
||||
Row( |
||||
children: [ |
||||
Expanded( |
||||
child: InkWell( |
||||
child: BorderText( |
||||
text: S.of(context).quxiao, |
||||
textColor: Color(0xFF30415B), |
||||
fontSize: 16.sp, |
||||
fontWeight: FontWeight.bold, |
||||
borderColor: Color(0xFF30415B), |
||||
radius: 4, |
||||
padding: EdgeInsets.all(12), |
||||
borderWidth: 1, |
||||
), |
||||
onTap: () { |
||||
Navigator.of(context).pop(); |
||||
}, |
||||
), |
||||
flex: 1, |
||||
), |
||||
SizedBox( |
||||
width: 16.w, |
||||
), |
||||
Expanded( |
||||
child: InkWell( |
||||
child: RoundButton( |
||||
text: S.of(context).queren, |
||||
textColor: Colors.white, |
||||
radius: 4, |
||||
padding: EdgeInsets.all(12), |
||||
backgroup: Color(0xFF30415B), |
||||
fontSize: 16.sp, |
||||
fontWeight: FontWeight.bold, |
||||
), |
||||
onTap: () { |
||||
Navigator.of(context).pop(); |
||||
queryGoodsUpdate(productIds ?? ""); |
||||
}, |
||||
), |
||||
flex: 1, |
||||
), |
||||
], |
||||
) |
||||
], |
||||
), |
||||
), |
||||
); |
||||
}, |
||||
); |
||||
} |
||||
|
||||
Widget leftItemSm() { |
||||
return Container( |
||||
alignment: Alignment.center, |
||||
padding: EdgeInsets.symmetric(vertical: 16.h, horizontal: 14.w), |
||||
child: Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 48.w, |
||||
height: 30.h, |
||||
), |
||||
), |
||||
); |
||||
} |
||||
|
||||
Widget rightGoodsSm() { |
||||
return Container( |
||||
margin: EdgeInsets.only(bottom: 21.h, left: 16.w, right: 16.w, top: 10.h), |
||||
child: Row( |
||||
children: [ |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(4), |
||||
), |
||||
width: 70.h, |
||||
height: 70.h, |
||||
), |
||||
), |
||||
SizedBox( |
||||
width: 12.w, |
||||
), |
||||
Expanded( |
||||
child: Column( |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Padding( |
||||
padding: EdgeInsets.only(bottom: 11.h, top: 2.h), |
||||
child: Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 124.w, |
||||
height: 20.h, |
||||
), |
||||
), |
||||
), |
||||
Row( |
||||
children: [ |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 43.w, |
||||
height: 18.h, |
||||
), |
||||
), |
||||
SizedBox( |
||||
width: 8.w, |
||||
), |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 43.w, |
||||
height: 18.h, |
||||
), |
||||
), |
||||
], |
||||
), |
||||
SizedBox( |
||||
height: 7.h, |
||||
), |
||||
Row( |
||||
children: [ |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 28.w, |
||||
height: 20.h, |
||||
), |
||||
), |
||||
Spacer(), |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 24.w, |
||||
height: 18.h, |
||||
), |
||||
), |
||||
], |
||||
) |
||||
], |
||||
)), |
||||
], |
||||
), |
||||
); |
||||
} |
||||
|
||||
Widget noNetwork() { |
||||
return Container( |
||||
color: Colors.white, |
||||
width: double.infinity, |
||||
child: Column( |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
Text( |
||||
networkError.substring(0, networkError.indexOf(",")), |
||||
style: TextStyle( |
||||
fontSize: 14.sp, |
||||
color: Color(0xFF0D0D0D), |
||||
fontWeight: MyFontWeight.bold), |
||||
), |
||||
Padding( |
||||
padding: EdgeInsets.symmetric(vertical: 10.h), |
||||
child: Text( |
||||
"请检查网络设置或稍后重试", |
||||
style: TextStyle( |
||||
fontSize: 12.sp, |
||||
color: Color(0xFF7A797F), |
||||
fontWeight: MyFontWeight.regular), |
||||
), |
||||
), |
||||
GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
_onRefresh(); |
||||
}, |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0xFF30415B), |
||||
borderRadius: BorderRadius.circular(15), |
||||
), |
||||
padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 3.h), |
||||
child: Text( |
||||
"重试", |
||||
style: TextStyle( |
||||
fontSize: 14.sp, |
||||
color: Colors.white, |
||||
fontWeight: MyFontWeight.regular), |
||||
)), |
||||
) |
||||
], |
||||
), |
||||
); |
||||
} |
||||
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue