@@ -24,7 +24,7 @@ class UserInfoModel { | |||||
mobile = json['mobile']; | mobile = json['mobile']; | ||||
perms = json['perms']?.cast<String>(); | perms = json['perms']?.cast<String>(); | ||||
registerInviteCodeEnable = json['register_invite_code_enable']; | registerInviteCodeEnable = json['register_invite_code_enable']; | ||||
isTBAuth = json['isTBAuth']; | |||||
isTBAuth = json['isTBAuth'] ?? false; | |||||
} | } | ||||
Map<String, dynamic> toJson() { | Map<String, dynamic> toJson() { | ||||
@@ -0,0 +1,43 @@ | |||||
import 'package:flutter/material.dart'; | |||||
import 'package:zhiying_comm/zhiying_comm.dart'; | |||||
import 'loading_dialog.dart'; | |||||
// loading弹窗 | |||||
class Loading { | |||||
static OverlayEntry _overlayEntry; | |||||
static Future show( | |||||
BuildContext context, { | |||||
String msg, | |||||
}) async { | |||||
dismiss(); | |||||
_overlayEntry = new OverlayEntry(builder: (context) { | |||||
return GestureDetector( | |||||
onTap: dismiss, | |||||
child: Container( | |||||
color: Colors.black.withOpacity(0.3), | |||||
child: LoadingDialog( | |||||
message: msg, | |||||
), | |||||
), | |||||
); | |||||
}); | |||||
try { | |||||
//插入到 Overlay中显示 OverlayEntry | |||||
Overlay.of(context).insert(_overlayEntry); | |||||
}catch(e, s){ | |||||
Logger.error(e, s); | |||||
} | |||||
} | |||||
static dismiss() { | |||||
try { | |||||
_overlayEntry?.remove(); | |||||
_overlayEntry = null; | |||||
}catch(e, s){ | |||||
Logger.error(e, s); | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,54 @@ | |||||
import 'package:flutter/material.dart'; | |||||
import 'package:loading_indicator/loading_indicator.dart'; | |||||
import 'loading.dart'; | |||||
class LoadingDialog extends StatelessWidget { | |||||
final String message; | |||||
const LoadingDialog({Key key, this.message}) : super(key: key); | |||||
@override | |||||
Widget build(BuildContext context) { | |||||
return GestureDetector( | |||||
onTap: () { | |||||
Loading.dismiss(); | |||||
}, | |||||
child: Scaffold( | |||||
backgroundColor: Colors.transparent, | |||||
body: Center( | |||||
child: UnconstrainedBox( | |||||
child: Container( | |||||
padding: EdgeInsets.all(10), | |||||
decoration: BoxDecoration( | |||||
color: Colors.transparent, borderRadius: BorderRadius.circular(8)), | |||||
child: Column( | |||||
crossAxisAlignment: CrossAxisAlignment.center, | |||||
mainAxisAlignment: MainAxisAlignment.center, | |||||
children: <Widget>[ | |||||
Container( | |||||
width: 40, | |||||
height: 40, | |||||
child: LoadingIndicator( | |||||
indicatorType: Indicator.ballSpinFadeLoader, | |||||
color: Colors.white, | |||||
), | |||||
), | |||||
message == null || message == '' | |||||
? Container() | |||||
: Container( | |||||
margin: EdgeInsets.only(top: 8), | |||||
child: Text( | |||||
message, | |||||
style: TextStyle(fontSize: 14), | |||||
), | |||||
), | |||||
], | |||||
), | |||||
), | |||||
), | |||||
), | |||||
), | |||||
); | |||||
} | |||||
} |
@@ -11,13 +11,13 @@ class GlobalConfig { | |||||
static final String SKIP_IDENTIFIER = 'skip_identifier'; | static final String SKIP_IDENTIFIER = 'skip_identifier'; | ||||
/// ====================== 各个渠道的key ====================== /// | /// ====================== 各个渠道的key ====================== /// | ||||
static final String PROVIDER_TB = 'taobao'; // 淘宝 | |||||
static final String PROVIDER_TM = 'tianmao'; // 天猫 | |||||
static final String PROVIDER_JD = 'jd'; // 京东 | |||||
static final String PROVIDER_KL = 'kaola'; // 考拉 | |||||
static final String PROVIDER_VIP = 'vip'; // 唯品会 | |||||
static final String PROVIDER_SN = 'suning'; // 苏宁 | |||||
static final String PROVIDER_PDD = 'pdd'; // 拼多多 | |||||
static const String PROVIDER_TB = 'taobao'; // 淘宝 | |||||
static const String PROVIDER_TM = 'tianmao'; // 天猫 | |||||
static const String PROVIDER_JD = 'jd'; // 京东 | |||||
static const String PROVIDER_KL = 'kaola'; // 考拉 | |||||
static const String PROVIDER_VIP = 'vip'; // 唯品会 | |||||
static const String PROVIDER_SN = 'suning'; // 苏宁 | |||||
static const String PROVIDER_PDD = 'pdd'; // 拼多多 | |||||
/// ====================== Shared_prefe_key ====================== /// | /// ====================== Shared_prefe_key ====================== /// | ||||
/// 用户token | /// 用户token | ||||
@@ -8,54 +8,67 @@ typedef Widget CreatePage(Map<String, dynamic> model); | |||||
class PageFactory { | class PageFactory { | ||||
static Map<String, CreatePage> pageCreater = Map(); | static Map<String, CreatePage> pageCreater = Map(); | ||||
/** | |||||
* @description: 注册路由 | |||||
/** | |||||
* @description: 注册路由 | |||||
* @param {name} SkipUIIdentifier | * @param {name} SkipUIIdentifier | ||||
* @return: | |||||
* @return: | |||||
*/ | */ | ||||
static void regist(String name, CreatePage creater) { | static void regist(String name, CreatePage creater) { | ||||
if (pageCreater.containsKey(name)) { | if (pageCreater.containsKey(name)) { | ||||
return; | return; | ||||
} | } | ||||
pageCreater[name] = creater; | pageCreater[name] = creater; | ||||
} | } | ||||
/** | /** | ||||
* @description: 创建页面 | * @description: 创建页面 | ||||
* @param {String} name注册的SkipUIIdentifier | * @param {String} name注册的SkipUIIdentifier | ||||
* @return: | |||||
* @return: | |||||
*/ | */ | ||||
static Widget create(String name, Map<String, dynamic> model) { | static Widget create(String name, Map<String, dynamic> model) { | ||||
if (pageCreater.containsKey(name)) { | if (pageCreater.containsKey(name)) { | ||||
return pageCreater[name](model); | return pageCreater[name](model); | ||||
} | } | ||||
// ⚠️ 由于使用了跳转标志带有后缀,所以需要判断是否带有后缀,如果带有并且是数字,则清除后缀获取page | |||||
String tempName = _getSkipSuffix(name); | |||||
if (!EmptyUtil.isEmpty(tempName) && pageCreater.containsKey(tempName)) { | |||||
return pageCreater[tempName](model); | |||||
} | |||||
return EmptyPage(); | |||||
} | |||||
// ⚠️ 由于使用了跳转标志带有后缀,所以需要判断是否带有后缀,如果带有并且是数字,则清除后缀获取page | |||||
static String _getSkipSuffix(String name) { | |||||
String tempName; | String tempName; | ||||
try{ | |||||
try { | |||||
String suffixStr = name.substring(name.lastIndexOf('.') + 1, name.length); | String suffixStr = name.substring(name.lastIndexOf('.') + 1, name.length); | ||||
tempName = name.substring(0, name.lastIndexOf('.')); | tempName = name.substring(0, name.lastIndexOf('.')); | ||||
Logger.log('sufix = $suffixStr , prefix = $tempName'); | Logger.log('sufix = $suffixStr , prefix = $tempName'); | ||||
int suffixNum = int.parse(suffixStr); | int suffixNum = int.parse(suffixStr); | ||||
Logger.log('suffixNum = $suffixNum}'); | Logger.log('suffixNum = $suffixNum}'); | ||||
}catch(e){ | |||||
} catch (e) { | |||||
tempName = null; | tempName = null; | ||||
Logger.debug(e); | Logger.debug(e); | ||||
} | } | ||||
if(!EmptyUtil.isEmpty(tempName) && pageCreater.containsKey(tempName)){ | |||||
return pageCreater[tempName](model); | |||||
} | |||||
return EmptyPage(); | |||||
return tempName; | |||||
} | } | ||||
/** | |||||
/** | |||||
* @description: 是否注册页面 | * @description: 是否注册页面 | ||||
* @param {bool} | |||||
* @return: | |||||
* @param {bool} | |||||
* @return: | |||||
*/ | */ | ||||
static bool hasRegisted(String name) { | static bool hasRegisted(String name) { | ||||
return pageCreater.containsKey(name); | |||||
if (pageCreater.containsKey(name)) { | |||||
return true; | |||||
} | |||||
String tempName = _getSkipSuffix(name); | |||||
if (pageCreater.containsKey(tempName)) { | |||||
return true; | |||||
} | |||||
return false; | |||||
} | } | ||||
} | } |
@@ -0,0 +1,150 @@ | |||||
import 'dart:io'; | |||||
import 'package:flutter/cupertino.dart'; | |||||
import 'package:flutter_alibc/alibc_model.dart'; | |||||
import 'package:flutter_alibc/flutter_alibc.dart'; | |||||
import 'package:jdsdk/jdsdk.dart'; | |||||
import 'package:url_launcher/url_launcher.dart'; | |||||
import 'package:zhiying_comm/models/user/user_info_model.dart'; | |||||
import 'package:zhiying_comm/util/dialog/loading/loading.dart'; | |||||
import 'package:zhiying_comm/util/empty_util.dart'; | |||||
import 'package:zhiying_comm/util/global_config.dart'; | |||||
import 'package:zhiying_comm/util/log/let_log.dart'; | |||||
import 'package:zhiying_comm/util/net_util.dart'; | |||||
import 'package:zhiying_comm/util/taobao/taobao_auth.dart'; | |||||
import 'package:fluttertoast/fluttertoast.dart'; | |||||
import '../router_util.dart'; | |||||
class TurnChainUtil { | |||||
/// | |||||
/// 跳转app或者打开url进行领券 | |||||
/// userInfoModel: 用户登陆的带有token 与 淘宝是否授权的 model类 | |||||
/// provider: 商品的渠道 | |||||
/// data: 转链需要的请求参数 | |||||
/// | |||||
static Future<void> openReceiveCoupon(BuildContext context, UserInfoModel userInfoModel, String provider, Map<String, dynamic> data) async { | |||||
/// 1、先判断是否登陆 | |||||
if (EmptyUtil.isEmpty(userInfoModel) || EmptyUtil.isEmpty(userInfoModel?.token)) { | |||||
RouterUtil.goLogin(context); | |||||
return; | |||||
} | |||||
/// 2、如果是淘宝,判断是否授权 | |||||
if (provider == GlobalConfig.PROVIDER_TB && !userInfoModel.isTBAuth) { | |||||
TaobaoAuth.auth(context); | |||||
return; | |||||
} | |||||
/// 3、获取转链,进行跳转 | |||||
Map<String, dynamic> result = await getTurnChainResult(context, provider, data, isShare: false); | |||||
if (!EmptyUtil.isEmpty(result)) { | |||||
String openAppUrl = result['open_app_url']; | |||||
String appUrl = result['app_url']; | |||||
String webUrl = result['no_open_app_url']; | |||||
/// 4、根据渠道进行不同的跳转 | |||||
switch (provider) { | |||||
case GlobalConfig.PROVIDER_TB: | |||||
case GlobalConfig.PROVIDER_TM: | |||||
if (!EmptyUtil.isEmpty(openAppUrl)) { | |||||
TradeResult tradeResult; | |||||
if (Platform.isAndroid) { | |||||
tradeResult = await FlutterAlibc.openByUrl(url: openAppUrl, backUrl: "alisdk://"); | |||||
} else if (Platform.isIOS) { | |||||
tradeResult = await FlutterAlibc.openByUrl(url: openAppUrl); | |||||
} | |||||
Logger.debug('taobao result = ${tradeResult.errorCode} ${tradeResult.errorMessage} '); | |||||
} else if (!EmptyUtil.isEmpty(webUrl)) { | |||||
RouterUtil.openWebview(webUrl, context); | |||||
} else { | |||||
Fluttertoast.showToast(msg: '购买链接不存在'); | |||||
} | |||||
break; | |||||
case GlobalConfig.PROVIDER_JD: | |||||
if (!EmptyUtil.isEmpty(openAppUrl) && !EmptyUtil.isEmpty(appUrl) && await canLaunch(appUrl)) { | |||||
Jdsdk.openUrl(url: openAppUrl); | |||||
} else if (!EmptyUtil.isEmpty(webUrl)) { | |||||
RouterUtil.openWebview(webUrl, context); | |||||
} else { | |||||
Fluttertoast.showToast(msg: '购买链接不存在'); | |||||
} | |||||
break; | |||||
case GlobalConfig.PROVIDER_KL: | |||||
case GlobalConfig.PROVIDER_PDD: | |||||
case GlobalConfig.PROVIDER_SN: | |||||
case GlobalConfig.PROVIDER_VIP: | |||||
if (!EmptyUtil.isEmpty(appUrl) && await canLaunch(appUrl)) { | |||||
Logger.log('打开${provider} app, url = ${appUrl}'); | |||||
launch(appUrl); | |||||
} else if (!EmptyUtil.isEmpty(webUrl)) { | |||||
Logger.log('打开${provider} webUrl, url = ${webUrl}'); | |||||
RouterUtil.openWebview(webUrl, context); | |||||
} else { | |||||
Fluttertoast.showToast(msg: '购买链接不存在'); | |||||
} | |||||
break; | |||||
} | |||||
} else { | |||||
Fluttertoast.showToast(msg: '购买链接不存在'); | |||||
} | |||||
} | |||||
/// | |||||
/// 获取分享的转链 | |||||
/// userInfoModel: 用户登陆的带有token 与 淘宝是否授权的 model类 | |||||
/// provider: 商品的渠道 | |||||
/// data: 转链需要的请求参数 | |||||
/// | |||||
/// 返回参数: 只需要获取返回结果的 open_app_url 值即可。 | |||||
/// 例如: Map<String, dynamic> result = await getShareTurnChain(context, _user, provider, data); | |||||
/// String buyUrl = result['open_app_url'] | |||||
/// | |||||
static Future<Map<String, dynamic>> getShareTurnChain(BuildContext context, UserInfoModel userInfoModel, String provider, Map<String, dynamic> data) async { | |||||
/// 1、先判断是否登陆 | |||||
if (EmptyUtil.isEmpty(userInfoModel) || EmptyUtil.isEmpty(userInfoModel?.token)) { | |||||
RouterUtil.goLogin(context); | |||||
return null; | |||||
} | |||||
/// 2、如果是淘宝,判断是否授权 | |||||
if (provider == GlobalConfig.PROVIDER_TB && !userInfoModel.isTBAuth) { | |||||
TaobaoAuth.auth(context); | |||||
return null; | |||||
} | |||||
/// 3、获取转链的结果 | |||||
Map<String, dynamic> result = await getTurnChainResult(context, provider, data, isShare: true); | |||||
if (!EmptyUtil.isEmpty(result) && !EmptyUtil.isEmpty(result['open_app_url'])) { | |||||
return result; | |||||
} | |||||
Fluttertoast.showToast(msg: '购买链接不存在'); | |||||
return null; | |||||
} | |||||
/// | |||||
/// 接口文档:https://www.showdoc.com.cn/1003739271891029?page_id=5760575662067820 | |||||
/// 根据商品id等信息,获取领券或者分享的转链接 | |||||
/// | |||||
/// | |||||
static Future<Map<String, dynamic>> getTurnChainResult(BuildContext context, String provider, Map<String, dynamic> data, {bool isShare = false}) async { | |||||
try { | |||||
if (!EmptyUtil.isEmpty(context) && !EmptyUtil.isEmpty(provider) && !EmptyUtil.isEmpty(data) && !EmptyUtil.isEmpty('gid')) { | |||||
// 设置是否分享还是转链 | |||||
data['is_share'] = isShare ? '1' : '0'; | |||||
// 开启loading | |||||
Loading.show(context); | |||||
var result = await NetUtil.post('/api/v1/convert/$provider', params: data, method: NetMethod.POST); | |||||
// 关闭loading | |||||
Loading.dismiss(); | |||||
if (NetUtil.isSuccess(result) && !EmptyUtil.isEmpty(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA])) { | |||||
return result[GlobalConfig.HTTP_RESPONSE_KEY_DATA]; | |||||
} | |||||
} | |||||
} catch (e, s) { | |||||
Logger.error(e, s); | |||||
} | |||||
return null; | |||||
} | |||||
} |
@@ -44,6 +44,7 @@ dependencies: | |||||
ref: 0.0.3 | ref: 0.0.3 | ||||
url: http://192.168.0.138:3000/FnuoOS_ZhiYing/zhiying_flutter_alibc.git | url: http://192.168.0.138:3000/FnuoOS_ZhiYing/zhiying_flutter_alibc.git | ||||
url_launcher: ^5.6.0 | url_launcher: ^5.6.0 | ||||
loading_indicator: ^1.2.0 | |||||
dev_dependencies: | dev_dependencies: | ||||