mirror of
https://github.com/qinglong-app/qinglong_app.git
synced 2025-10-09 16:48:19 +08:00
Merge remote-tracking branch 'remotes/origin/dev'
This commit is contained in:
@@ -1,3 +1,8 @@
|
|||||||
|
## 1.0.3
|
||||||
|
|
||||||
|
* 解决2.10.12及以下版本无法登录的问题
|
||||||
|
* 适配最新版qinglong 相关接口字段
|
||||||
|
|
||||||
## 1.0.2
|
## 1.0.2
|
||||||
|
|
||||||
* 支持修改用户名密码(仅限使用用户名密码登录用户)
|
* 支持修改用户名密码(仅限使用用户名密码登录用户)
|
||||||
|
|||||||
@@ -24,7 +24,18 @@ class Api {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
static Future<HttpResponse<LoginBean>> loginOld(
|
||||||
|
String userName,
|
||||||
|
String passWord,
|
||||||
|
) async {
|
||||||
|
return await Http.post<LoginBean>(
|
||||||
|
Url.loginOld,
|
||||||
|
{
|
||||||
|
"username": userName,
|
||||||
|
"password": passWord,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
static Future<HttpResponse<LoginBean>> loginTwo(
|
static Future<HttpResponse<LoginBean>> loginTwo(
|
||||||
String userName,
|
String userName,
|
||||||
String passWord,
|
String passWord,
|
||||||
@@ -103,6 +114,7 @@ class Api {
|
|||||||
|
|
||||||
if (id != null) {
|
if (id != null) {
|
||||||
data["_id"] = id;
|
data["_id"] = id;
|
||||||
|
data["id"] = id;
|
||||||
return await Http.put<NullResponse>(
|
return await Http.put<NullResponse>(
|
||||||
Url.addTask,
|
Url.addTask,
|
||||||
data,
|
data,
|
||||||
@@ -207,6 +219,7 @@ class Api {
|
|||||||
|
|
||||||
if (id != null) {
|
if (id != null) {
|
||||||
data["_id"] = id;
|
data["_id"] = id;
|
||||||
|
data["id"] = id;
|
||||||
return await Http.put<NullResponse>(
|
return await Http.put<NullResponse>(
|
||||||
Url.addEnv,
|
Url.addEnv,
|
||||||
data,
|
data,
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import 'package:dio/dio.dart';
|
|||||||
import 'package:dio_log/dio_log.dart';
|
import 'package:dio_log/dio_log.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:qinglong_app/base/http/token_interceptor.dart';
|
import 'package:qinglong_app/base/http/token_interceptor.dart';
|
||||||
|
import 'package:qinglong_app/base/http/url.dart';
|
||||||
import 'package:qinglong_app/base/userinfo_viewmodel.dart';
|
import 'package:qinglong_app/base/userinfo_viewmodel.dart';
|
||||||
import 'package:qinglong_app/utils/extension.dart';
|
import 'package:qinglong_app/utils/extension.dart';
|
||||||
|
|
||||||
@@ -54,7 +55,7 @@ class Http {
|
|||||||
|
|
||||||
return decodeResponse<T>(response, serializationName, compute);
|
return decodeResponse<T>(response, serializationName, compute);
|
||||||
} on DioError catch (e) {
|
} on DioError catch (e) {
|
||||||
return exceptionHandler<T>(e);
|
return exceptionHandler<T>(e, uri);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,7 +75,7 @@ class Http {
|
|||||||
compute,
|
compute,
|
||||||
);
|
);
|
||||||
} on DioError catch (e) {
|
} on DioError catch (e) {
|
||||||
return exceptionHandler<T>(e);
|
return exceptionHandler<T>(e, uri);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,7 +95,7 @@ class Http {
|
|||||||
compute,
|
compute,
|
||||||
);
|
);
|
||||||
} on DioError catch (e) {
|
} on DioError catch (e) {
|
||||||
return exceptionHandler<T>(e);
|
return exceptionHandler<T>(e, uri);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,7 +114,7 @@ class Http {
|
|||||||
compute,
|
compute,
|
||||||
);
|
);
|
||||||
} on DioError catch (e) {
|
} on DioError catch (e) {
|
||||||
return exceptionHandler<T>(e);
|
return exceptionHandler<T>(e, uri);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,8 +126,8 @@ class Http {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static HttpResponse<T> exceptionHandler<T>(DioError e) {
|
static HttpResponse<T> exceptionHandler<T>(DioError e, String path) {
|
||||||
if (e.response?.statusCode == 401) {
|
if (e.response?.statusCode == 401 && !Url.inWhiteList(path)) {
|
||||||
if (!getIt<UserInfoViewModel>().useSecretLogined) {
|
if (!getIt<UserInfoViewModel>().useSecretLogined) {
|
||||||
exitLogin();
|
exitLogin();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,18 +7,18 @@ import '../userinfo_viewmodel.dart';
|
|||||||
class TokenInterceptor extends Interceptor {
|
class TokenInterceptor extends Interceptor {
|
||||||
@override
|
@override
|
||||||
void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
|
void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
|
||||||
if (getIt<UserInfoViewModel>().token != null &&
|
if (getIt<UserInfoViewModel>().token != null && getIt<UserInfoViewModel>().token!.isNotEmpty) {
|
||||||
getIt<UserInfoViewModel>().token!.isNotEmpty) {
|
options.headers["Authorization"] = "Bearer " + getIt<UserInfoViewModel>().token!;
|
||||||
options.headers["Authorization"] =
|
|
||||||
"Bearer " + getIt<UserInfoViewModel>().token!;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
options.headers["User-Agent"] = "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1";
|
options.headers["User-Agent"] =
|
||||||
|
"Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1";
|
||||||
|
|
||||||
options.headers["Content-Type"] = "application/json;charset=UTF-8";
|
options.headers["Content-Type"] = "application/json;charset=UTF-8";
|
||||||
if (options.path != Url.loginByClientId && options.path!= Url.loginTwo) {
|
|
||||||
options.queryParameters["t"] =
|
|
||||||
(DateTime.now().millisecondsSinceEpoch ~/ 1000).toString();
|
if (!Url.inWhiteList(options.path)) {
|
||||||
|
options.queryParameters["t"] = (DateTime.now().millisecondsSinceEpoch ~/ 1000).toString();
|
||||||
}
|
}
|
||||||
return handler.next(options);
|
return handler.next(options);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,9 @@ import '../userinfo_viewmodel.dart';
|
|||||||
|
|
||||||
class Url {
|
class Url {
|
||||||
static get login => "/api/user/login";
|
static get login => "/api/user/login";
|
||||||
|
|
||||||
|
static get loginOld => "/api/login";
|
||||||
|
|
||||||
static get loginTwo => "/api/user/two-factor/login";
|
static get loginTwo => "/api/user/two-factor/login";
|
||||||
static const loginByClientId = "/open/auth/token";
|
static const loginByClientId = "/open/auth/token";
|
||||||
static const user = "/api/user";
|
static const user = "/api/user";
|
||||||
@@ -50,6 +53,7 @@ class Url {
|
|||||||
static get taskLogDetail => getIt<UserInfoViewModel>().useSecretLogined ? "/open/logs/" : "/api/logs/";
|
static get taskLogDetail => getIt<UserInfoViewModel>().useSecretLogined ? "/open/logs/" : "/api/logs/";
|
||||||
|
|
||||||
static get scripts => getIt<UserInfoViewModel>().useSecretLogined ? "/open/scripts/files" : "/api/scripts/files";
|
static get scripts => getIt<UserInfoViewModel>().useSecretLogined ? "/open/scripts/files" : "/api/scripts/files";
|
||||||
|
|
||||||
static get scriptUpdate => getIt<UserInfoViewModel>().useSecretLogined ? "/open/scripts" : "/api/scripts";
|
static get scriptUpdate => getIt<UserInfoViewModel>().useSecretLogined ? "/open/scripts" : "/api/scripts";
|
||||||
|
|
||||||
static get scriptDetail => getIt<UserInfoViewModel>().useSecretLogined ? "/open/scripts/" : "/api/scripts/";
|
static get scriptDetail => getIt<UserInfoViewModel>().useSecretLogined ? "/open/scripts/" : "/api/scripts/";
|
||||||
@@ -58,9 +62,6 @@ class Url {
|
|||||||
|
|
||||||
static get dependencyReinstall => getIt<UserInfoViewModel>().useSecretLogined ? "/open/dependencies/reinstall" : "/api/dependencies/reinstall";
|
static get dependencyReinstall => getIt<UserInfoViewModel>().useSecretLogined ? "/open/dependencies/reinstall" : "/api/dependencies/reinstall";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static intimeLog(String cronId) {
|
static intimeLog(String cronId) {
|
||||||
return getIt<UserInfoViewModel>().useSecretLogined ? "/open/crons/$cronId/log" : "/api/crons/$cronId/log";
|
return getIt<UserInfoViewModel>().useSecretLogined ? "/open/crons/$cronId/log" : "/api/crons/$cronId/log";
|
||||||
}
|
}
|
||||||
@@ -68,4 +69,11 @@ class Url {
|
|||||||
static envMove(String envId) {
|
static envMove(String envId) {
|
||||||
return getIt<UserInfoViewModel>().useSecretLogined ? "/open/envs/$envId/move" : "/api/envs/$envId/move";
|
return getIt<UserInfoViewModel>().useSecretLogined ? "/open/envs/$envId/move" : "/api/envs/$envId/move";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool inWhiteList(String path) {
|
||||||
|
if (path == login || path == loginByClientId || path == loginTwo || path == loginOld) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
11
lib/module/env/env_bean.dart
vendored
11
lib/module/env/env_bean.dart
vendored
@@ -10,18 +10,11 @@ class EnvBean {
|
|||||||
String? name;
|
String? name;
|
||||||
String? remarks;
|
String? remarks;
|
||||||
|
|
||||||
EnvBean(
|
EnvBean({this.value, this.sId, this.created, this.status, this.timestamp, this.name, this.remarks});
|
||||||
{this.value,
|
|
||||||
this.sId,
|
|
||||||
this.created,
|
|
||||||
this.status,
|
|
||||||
this.timestamp,
|
|
||||||
this.name,
|
|
||||||
this.remarks});
|
|
||||||
|
|
||||||
EnvBean.fromJson(Map<String, dynamic> json) {
|
EnvBean.fromJson(Map<String, dynamic> json) {
|
||||||
value = json['value'];
|
value = json['value'];
|
||||||
sId = json['_id'];
|
sId = json.containsKey('_id') ? json['_id'].toString() : (json.containsKey('id') ? json['id'].toString() : "");
|
||||||
created = json['created'];
|
created = json['created'];
|
||||||
status = json['status'];
|
status = json['status'];
|
||||||
timestamp = json['timestamp'];
|
timestamp = json['timestamp'];
|
||||||
|
|||||||
@@ -94,42 +94,24 @@ class _LoginPageState extends ConsumerState<LoginPage> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: MediaQuery.of(context).size.height / 10,
|
height: MediaQuery.of(context).size.height / 8,
|
||||||
),
|
),
|
||||||
SizedBox(
|
Row(
|
||||||
height: 50,
|
children: [
|
||||||
width: MediaQuery.of(context).size.width,
|
Expanded(
|
||||||
child: Stack(
|
child: Align(
|
||||||
children: [
|
alignment: Alignment.centerLeft,
|
||||||
Positioned(
|
|
||||||
top: 0,
|
|
||||||
left: 0,
|
|
||||||
child: Image.asset(
|
child: Image.asset(
|
||||||
"assets/images/login_tip.png",
|
"assets/images/login_tip.png",
|
||||||
height: 45,
|
height: 45,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const Positioned(
|
),
|
||||||
top: 10,
|
Image.asset(
|
||||||
left: 0,
|
"assets/images/ql.png",
|
||||||
child: Text(
|
height: 45,
|
||||||
"登录",
|
),
|
||||||
style: TextStyle(
|
],
|
||||||
fontSize: 30,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Positioned(
|
|
||||||
top: 5,
|
|
||||||
right: 0,
|
|
||||||
child: Image.asset(
|
|
||||||
"assets/images/ql.png",
|
|
||||||
height: 45,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: MediaQuery.of(context).size.height / 15,
|
height: MediaQuery.of(context).size.height / 15,
|
||||||
@@ -276,7 +258,9 @@ class _LoginPageState extends ConsumerState<LoginPage> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 25,),
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 25,
|
||||||
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Checkbox(
|
Checkbox(
|
||||||
@@ -307,7 +291,9 @@ class _LoginPageState extends ConsumerState<LoginPage> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(width: 10,),
|
SizedBox(
|
||||||
|
width: 10,
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -316,7 +302,9 @@ class _LoginPageState extends ConsumerState<LoginPage> {
|
|||||||
),
|
),
|
||||||
Container(
|
Container(
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 40,),
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 40,
|
||||||
|
),
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
width: MediaQuery.of(context).size.width - 80,
|
width: MediaQuery.of(context).size.width - 80,
|
||||||
child: IgnorePointer(
|
child: IgnorePointer(
|
||||||
@@ -377,72 +365,26 @@ class _LoginPageState extends ConsumerState<LoginPage> {
|
|||||||
}
|
}
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
loginSuccess(response, userName, password);
|
loginSuccess(response, userName, password);
|
||||||
|
} else if (loginByUserName() && response.code == 401) {
|
||||||
|
//可能用户使用的是老版本qinglong
|
||||||
|
HttpResponse<LoginBean> oldResponse = await Api.loginOld(userName, password);
|
||||||
|
if (oldResponse.success) {
|
||||||
|
loginSuccess(oldResponse, userName, password);
|
||||||
|
} else {
|
||||||
|
(oldResponse.message ?? "请检查网络情况").toast();
|
||||||
|
if (oldResponse.code == 420) {
|
||||||
|
twoFact(userName, password);
|
||||||
|
} else {
|
||||||
|
isLoading = false;
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
print(response.code);
|
print(response.code);
|
||||||
(response.message ?? "请检查网络情况").toast();
|
(response.message ?? "请检查网络情况").toast();
|
||||||
//420代表需要2步验证
|
//420代表需要2步验证
|
||||||
if (response.code == 420) {
|
if (response.code == 420) {
|
||||||
String twoFact = "";
|
twoFact(userName, password);
|
||||||
showCupertinoDialog(
|
|
||||||
context: context,
|
|
||||||
builder: (_) => CupertinoAlertDialog(
|
|
||||||
title: const Text("两步验证"),
|
|
||||||
content: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
Material(
|
|
||||||
color: Colors.transparent,
|
|
||||||
child: TextField(
|
|
||||||
onChanged: (value) {
|
|
||||||
twoFact = value;
|
|
||||||
},
|
|
||||||
maxLines: 1,
|
|
||||||
keyboardType: TextInputType.number,
|
|
||||||
decoration: const InputDecoration(
|
|
||||||
contentPadding: EdgeInsets.fromLTRB(0, 5, 0, 5),
|
|
||||||
hintText: "请输入code",
|
|
||||||
),
|
|
||||||
autofocus: true,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
actions: [
|
|
||||||
CupertinoDialogAction(
|
|
||||||
child: const Text(
|
|
||||||
"取消",
|
|
||||||
style: TextStyle(
|
|
||||||
color: Color(0xff999999),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
onPressed: () {
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
CupertinoDialogAction(
|
|
||||||
child: Text(
|
|
||||||
"确定",
|
|
||||||
style: TextStyle(
|
|
||||||
color: primaryColor,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
onPressed: () async {
|
|
||||||
Navigator.of(context).pop(true);
|
|
||||||
HttpResponse<LoginBean> response = await Api.loginTwo(userName, password, twoFact);
|
|
||||||
if (response.success) {
|
|
||||||
loginSuccess(response, userName, password);
|
|
||||||
} else {
|
|
||||||
loginFailed(response);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)).then((value) {
|
|
||||||
if (value == null) {
|
|
||||||
isLoading = false;
|
|
||||||
setState(() {});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
isLoading = false;
|
isLoading = false;
|
||||||
setState(() {});
|
setState(() {});
|
||||||
@@ -475,4 +417,68 @@ class _LoginPageState extends ConsumerState<LoginPage> {
|
|||||||
return _userNameController.text.isNotEmpty && _passwordController.text.isNotEmpty;
|
return _userNameController.text.isNotEmpty && _passwordController.text.isNotEmpty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void twoFact(String userName, String password) {
|
||||||
|
String twoFact = "";
|
||||||
|
showCupertinoDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (_) => CupertinoAlertDialog(
|
||||||
|
title: const Text("两步验证"),
|
||||||
|
content: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Material(
|
||||||
|
color: Colors.transparent,
|
||||||
|
child: TextField(
|
||||||
|
onChanged: (value) {
|
||||||
|
twoFact = value;
|
||||||
|
},
|
||||||
|
maxLines: 1,
|
||||||
|
keyboardType: TextInputType.number,
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
contentPadding: EdgeInsets.fromLTRB(0, 5, 0, 5),
|
||||||
|
hintText: "请输入code",
|
||||||
|
),
|
||||||
|
autofocus: true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
CupertinoDialogAction(
|
||||||
|
child: const Text(
|
||||||
|
"取消",
|
||||||
|
style: TextStyle(
|
||||||
|
color: Color(0xff999999),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
CupertinoDialogAction(
|
||||||
|
child: Text(
|
||||||
|
"确定",
|
||||||
|
style: TextStyle(
|
||||||
|
color: primaryColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onPressed: () async {
|
||||||
|
Navigator.of(context).pop(true);
|
||||||
|
HttpResponse<LoginBean> response = await Api.loginTwo(userName, password, twoFact);
|
||||||
|
if (response.success) {
|
||||||
|
loginSuccess(response, userName, password);
|
||||||
|
} else {
|
||||||
|
loginFailed(response);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)).then((value) {
|
||||||
|
if (value == null) {
|
||||||
|
isLoading = false;
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,6 +66,21 @@ class _AboutPageState extends ConsumerState<AboutPage> {
|
|||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 15,
|
||||||
|
),
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
_launchURL("https://t.me/qinglongapp");
|
||||||
|
},
|
||||||
|
child: Text(
|
||||||
|
"Telegram频道",
|
||||||
|
style: TextStyle(
|
||||||
|
color: primaryColor,
|
||||||
|
fontSize: 16,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
|
|||||||
@@ -367,6 +367,9 @@ class _OtherPageState extends ConsumerState<OtherPage> {
|
|||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 30,
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ class TaskBean {
|
|||||||
command = json['command'].toString();
|
command = json['command'].toString();
|
||||||
schedule = json['schedule'].toString();
|
schedule = json['schedule'].toString();
|
||||||
saved = json['saved'];
|
saved = json['saved'];
|
||||||
sId = json['_id'].toString();
|
sId = json.containsKey('_id') ? json['_id'].toString() : (json.containsKey('id') ? json['id'].toString() : "");
|
||||||
created = json['created'];
|
created = json['created'];
|
||||||
status = json['status'];
|
status = json['status'];
|
||||||
timestamp = json['timestamp'].toString();
|
timestamp = json['timestamp'].toString();
|
||||||
|
|||||||
@@ -884,4 +884,4 @@ packages:
|
|||||||
version: "3.1.0"
|
version: "3.1.0"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=2.15.1 <3.0.0"
|
dart: ">=2.15.1 <3.0.0"
|
||||||
flutter: ">=2.5.0"
|
flutter: ">=2.8.1"
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
name: qinglong_app
|
name: qinglong_app
|
||||||
description: A new Flutter project.
|
description: A new Flutter project.
|
||||||
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
||||||
version: 1.0.2+3
|
version: 1.0.3+4
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=2.15.1 <3.0.0"
|
sdk: ">=2.15.1 <3.0.0"
|
||||||
|
flutter: ">=2.8.1"
|
||||||
|
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|||||||
Reference in New Issue
Block a user