feat: upgrade apk.

This commit is contained in:
louis 2024-04-07 17:32:46 +08:00
parent 10145b3af7
commit 1befdcb786
40 changed files with 719 additions and 229 deletions

View File

@ -43,6 +43,7 @@
android:name="android.permission.CAMERA" /> android:name="android.permission.CAMERA" />
<uses-permission <uses-permission
android:name="android.permission.READ_EXTERNAL_STORAGE" /> android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
</manifest> </manifest>

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
assets/images/rocket.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 807 KiB

BIN
assets/images/rocket.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

View File

@ -7,7 +7,7 @@ import 'package:sk_base_mobile/services/dio.service.dart';
import '../constants/constants.dart'; import '../constants/constants.dart';
class Api { class Api {
// ///
static Future<Response> login(String username, String password) { static Future<Response> login(String username, String password) {
return DioService.dio.post( return DioService.dio.post(
Urls.login, Urls.login,
@ -15,6 +15,13 @@ class Api {
); );
} }
/// By key
static Future<Response> getSystemParamConfigByCode(String code) {
return DioService.dio.get(
'${Urls.systemParamConfig}/key/$code',
);
}
// //
static Future<Response> getUserInfo() { static Future<Response> getUserInfo() {
return DioService.dio.get( return DioService.dio.get(

View File

@ -28,6 +28,7 @@ class AppTheme {
} }
final theme = ThemeData( final theme = ThemeData(
platform: TargetPlatform.iOS,
primarySwatch: MaterialColor(AppTheme.primaryColor.value, const { primarySwatch: MaterialColor(AppTheme.primaryColor.value, const {
50: AppTheme.primaryColorLight, 50: AppTheme.primaryColorLight,
100: AppTheme.primaryColorLight, 100: AppTheme.primaryColorLight,

View File

@ -2,11 +2,11 @@
// Global config // Global config
class GloablConfig { class GloablConfig {
static const BASE_URL = "http://10.0.2.2:8001/api/"; // static const BASE_URL = "http://10.0.2.2:8001/api/";
static const OSS_URL = "http://10.0.2.2:8001"; // static const OSS_URL = "http://10.0.2.2:8001";
// static const BASE_URL = "http://144.123.43.138:3001/api/"; static const BASE_URL = "http://144.123.43.138:3001/api/";
// static const OSS_URL = "http://144.123.43.138:3001"; static const OSS_URL = "http://144.123.43.138:3001";
// static const BASE_URL = "http://192.168.60.220:8001/api/"; // static const BASE_URL = "http://192.168.60.220:8001/api/";
// static const OSS_URL = "http://192.168.60.220:8001"; // static const OSS_URL = "http://192.168.60.220:8001";
static const DOMAIN_NAME = "山矿通"; static const DOMAIN_NAME = "山矿通";

View File

@ -6,3 +6,4 @@ export 'global_url.dart';
export 'cache_key.dart'; export 'cache_key.dart';
export 'router.dart'; export 'router.dart';
export 'text_enum.dart'; export 'text_enum.dart';
export 'system_param_config.dart';

View File

@ -13,4 +13,6 @@ class Urls {
static String updateAvatar = 'user/updateAvatar'; static String updateAvatar = 'user/updateAvatar';
static String getDictType = 'system/dict-type/all'; static String getDictType = 'system/dict-type/all';
static String uploadAttachemnt = 'tools/upload'; static String uploadAttachemnt = 'tools/upload';
static String systemParamConfig = 'system/param-config';
static String accountMenus = 'account/menus';
} }

View File

@ -0,0 +1,4 @@
class SystemParamConfig {
static const String appVersion = "app_version";
static const String isForceUpgrade = "is_app_force_upgrade";
}

View File

@ -7,7 +7,7 @@ class InventoryInOutModel {
required this.id, required this.id,
required this.createdAt, required this.createdAt,
required this.updatedAt, required this.updatedAt,
required this.inventoryNumber, required this.inventoryInOutNumber,
required this.productId, required this.productId,
required this.inOrOut, required this.inOrOut,
required this.time, required this.time,
@ -28,7 +28,7 @@ class InventoryInOutModel {
final int? id; final int? id;
final DateTime? createdAt; final DateTime? createdAt;
final DateTime? updatedAt; final DateTime? updatedAt;
final String? inventoryNumber; final String? inventoryInOutNumber;
final int? productId; final int? productId;
final int? inOrOut; final int? inOrOut;
final DateTime? time; final DateTime? time;
@ -47,12 +47,12 @@ class InventoryInOutModel {
factory InventoryInOutModel.fromJson(Map<String, dynamic> json) { factory InventoryInOutModel.fromJson(Map<String, dynamic> json) {
return InventoryInOutModel( return InventoryInOutModel(
id: json["id"], id: json["id"],
createdAt: DateTime.tryParse(json["createdAt"] ?? ""), createdAt: DateTime.tryParse(json["createdAt"] ?? "")?.toLocal(),
updatedAt: DateTime.tryParse(json["updatedAt"] ?? ""), updatedAt: DateTime.tryParse(json["updatedAt"] ?? "")?.toLocal(),
inventoryNumber: json["inventoryNumber"], inventoryInOutNumber: json["inventoryInOutNumber"],
productId: json["productId"], productId: json["productId"],
inOrOut: json["inOrOut"], inOrOut: json["inOrOut"],
time: DateTime.tryParse(json["time"] ?? ""), time: DateTime.tryParse(json["time"] ?? "")?.toLocal(),
quantity: json["quantity"], quantity: json["quantity"],
unitPrice: json["unitPrice"], unitPrice: json["unitPrice"],
amount: json["amount"], amount: json["amount"],
@ -81,7 +81,7 @@ class InventoryInOutModel {
"id": id, "id": id,
"createdAt": createdAt?.toIso8601String(), "createdAt": createdAt?.toIso8601String(),
"updatedAt": updatedAt?.toIso8601String(), "updatedAt": updatedAt?.toIso8601String(),
"inventoryNumber": inventoryNumber, "inventoryInOutNumber": inventoryInOutNumber,
"productId": productId, "productId": productId,
"inOrOut": inOrOut, "inOrOut": inOrOut,
"time": time, "time": time,

View File

@ -3,12 +3,13 @@ import 'package:sk_base_mobile/screens/new_inventory_inout/components/inventory_
import 'package:sk_base_mobile/widgets/sk_appbar.dart'; import 'package:sk_base_mobile/widgets/sk_appbar.dart';
class InventoryPage extends StatelessWidget { class InventoryPage extends StatelessWidget {
const InventoryPage({super.key}); final bool isPage;
const InventoryPage({super.key, this.isPage = false});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: const SkAppbar(title: '库存管理'), appBar: SkAppbar(title: '库存管理', hideLeading: isPage),
body: InventorySearch(), body: InventorySearch(),
); );
} }

View File

@ -109,7 +109,11 @@ class InventoryInoutCard extends StatelessWidget {
), ),
), ),
Text( Text(
controller.list[ind][index].agent ?? '-', '${DateUtil.format(controller.list[ind][index].time!, formats: [
'HH',
':',
"nn"
])} ${controller.list[ind][index].agent ?? '-'}',
style: TextStyle( style: TextStyle(
fontSize: ScreenAdaper.height(20), fontSize: ScreenAdaper.height(20),
fontWeight: FontWeight.w600), fontWeight: FontWeight.w600),

View File

@ -63,7 +63,19 @@ class InventoryInoutInfo extends StatelessWidget {
buildListItem( buildListItem(
leading: '出入库时间', leading: '出入库时间',
trailing: DateUtil.format( trailing: DateUtil.format(
controller.inventoryInoutInfo.value!.time!)), controller.inventoryInoutInfo.value!.time!,
formats: [
'yyyy',
'-',
'mm',
'-',
'dd',
" ",
'HH',
":",
"nn"
]),
),
customDivider(), customDivider(),
buildListItem( buildListItem(
leading: '所属公司', leading: '所属公司',
@ -99,6 +111,16 @@ class InventoryInoutInfo extends StatelessWidget {
trailing: trailing:
controller.inventoryInoutInfo.value?.remark), controller.inventoryInoutInfo.value?.remark),
customDivider(), customDivider(),
buildListItem(
leading: '出入库单号',
trailing: controller
.inventoryInoutInfo.value?.inventoryInOutNumber),
customDivider(),
buildListItem(
leading: '库存编号',
trailing: controller.inventoryInoutInfo.value
?.inventory?.inventoryNumber),
customDivider(),
buildListItem( buildListItem(
leading: '照片', leading: '照片',
), ),
@ -156,14 +178,31 @@ class InventoryInoutInfo extends StatelessWidget {
} }
Widget buildListItem({String? leading, dynamic trailing}) { Widget buildListItem({String? leading, dynamic trailing}) {
return ListTile( return Container(
leading: Text( padding: EdgeInsets.symmetric(
vertical: ScreenAdaper.height(20),
horizontal: ScreenAdaper.width(20)),
child: Row(
children: [
Text(
'${leading ?? ''}: ', '${leading ?? ''}: ',
style: TextStyle( style: TextStyle(
fontSize: ScreenAdaper.height(25), fontWeight: FontWeight.w600), fontSize: ScreenAdaper.height(30), fontWeight: FontWeight.w600),
), ),
trailing: Text('${trailing ?? ''}', Spacer(),
style: TextStyle(fontSize: ScreenAdaper.height(25)))); Text('${trailing ?? ''}',
style: TextStyle(fontSize: ScreenAdaper.height(30)))
],
),
);
// return ListTile(
// leading: Text(
// '${leading ?? ''}: ',
// style: TextStyle(
// fontSize: ScreenAdaper.height(25), fontWeight: FontWeight.w600),
// ),
// trailing: Text('${trailing ?? ''}',
// style: TextStyle(fontSize: ScreenAdaper.height(25))));
} }
} }

View File

@ -6,7 +6,9 @@ import 'package:sk_base_mobile/app_theme.dart';
import 'package:sk_base_mobile/constants/enum.dart'; import 'package:sk_base_mobile/constants/enum.dart';
import 'package:sk_base_mobile/db_helper/db_help.dart'; import 'package:sk_base_mobile/db_helper/db_help.dart';
import 'package:sk_base_mobile/screens/inventory_inout/components/inventory_inout_info.dart'; import 'package:sk_base_mobile/screens/inventory_inout/components/inventory_inout_info.dart';
import 'package:sk_base_mobile/screens/landing/landing_controller.dart';
import 'package:sk_base_mobile/screens/new_inventory_inout/new_inventory_inout.dart'; import 'package:sk_base_mobile/screens/new_inventory_inout/new_inventory_inout.dart';
import 'package:sk_base_mobile/services/app_info.service.dart';
import 'package:sk_base_mobile/util/date.util.dart'; import 'package:sk_base_mobile/util/date.util.dart';
import 'package:sk_base_mobile/util/modal.util.dart'; import 'package:sk_base_mobile/util/modal.util.dart';
import 'package:sk_base_mobile/util/screen_adaper_util.dart'; import 'package:sk_base_mobile/util/screen_adaper_util.dart';
@ -236,7 +238,7 @@ class InventoryInoutController extends GetxController {
Future showInventoryInoutInfoDialog(int id) async { Future showInventoryInoutInfoDialog(int id) async {
ModalUtil.showGeneralDialog( ModalUtil.showGeneralDialog(
width: ScreenAdaper.screenShortDistance() - ScreenAdaper.width(100), width: ScreenAdaper.screenShortDistance() - ScreenAdaper.width(100),
height: ScreenAdaper.height(Get.height - 100), height: Get.height - 100 < 400 ? 400 : Get.height - 100,
content: InventoryInoutInfo(inventoryInoutId: id), content: InventoryInoutInfo(inventoryInoutId: id),
offset: const Offset(0, -1)) offset: const Offset(0, -1))
.then((value) => {Get.delete<InventoryInouInfoController>()}); .then((value) => {Get.delete<InventoryInouInfoController>()});
@ -258,6 +260,7 @@ class InventoryInoutController extends GetxController {
} }
return []; return [];
} catch (e) { } catch (e) {
print(e);
return []; return [];
} finally { } finally {
loading.value = false; loading.value = false;
@ -335,7 +338,7 @@ class InventoryInoutController extends GetxController {
// } // }
// case 2: // case 2:
// { // {
// ModalUtil.confirm( // ModalUtil.alert(
// 'Delete Task', 'Are you want to sure to remove', 'Confirm', () { // 'Delete Task', 'Are you want to sure to remove', 'Confirm', () {
// list[ind].remove(list[ind][index]); // list[ind].remove(list[ind][index]);
// db.delete( // db.delete(

View File

@ -1,10 +1,16 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:sk_base_mobile/apis/index.dart';
import 'package:sk_base_mobile/models/app_bottom_nav_item.dart'; import 'package:sk_base_mobile/models/app_bottom_nav_item.dart';
import 'package:sk_base_mobile/screens/inventory/inventory.dart'; import 'package:sk_base_mobile/screens/inventory/inventory.dart';
import 'package:sk_base_mobile/screens/inventory_inout/inventory_inout.dart'; import 'package:sk_base_mobile/screens/inventory_inout/inventory_inout.dart';
import 'package:sk_base_mobile/screens/mine/mine.dart'; import 'package:sk_base_mobile/screens/mine/mine.dart';
import 'package:sk_base_mobile/screens/workbench/workbench.dart'; import 'package:sk_base_mobile/screens/workbench/workbench.dart';
import 'package:sk_base_mobile/services/app_info.service.dart';
import 'package:sk_base_mobile/util/device.util.dart';
import 'package:sk_base_mobile/util/modal.util.dart';
import '../../constants/constants.dart';
class LandingController extends GetxController { class LandingController extends GetxController {
RxInt currentIndex = 0.obs; RxInt currentIndex = 0.obs;
@ -20,7 +26,7 @@ class LandingController extends GetxController {
icon: Icons.inventory_outlined, icon: Icons.inventory_outlined,
activeIcon: Icons.inventory_rounded, activeIcon: Icons.inventory_rounded,
label: '库存', label: '库存',
page: const InventoryPage()), page: const InventoryPage(isPage: true)),
AppBottomNavItem( AppBottomNavItem(
icon: Icons.widgets_outlined, icon: Icons.widgets_outlined,
activeIcon: Icons.widgets_rounded, activeIcon: Icons.widgets_rounded,
@ -36,5 +42,6 @@ class LandingController extends GetxController {
onInit() { onInit() {
super.onInit(); super.onInit();
pages = bottomNavItems!.map((e) => e.page!).toList(); pages = bottomNavItems!.map((e) => e.page!).toList();
AppInfoService.to.checkVersion();
} }
} }

View File

@ -1,6 +1,9 @@
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:sk_base_mobile/apis/index.dart';
import 'package:sk_base_mobile/util/device.util.dart';
import 'package:sk_base_mobile/util/snack_bar.util.dart'; import 'package:sk_base_mobile/util/snack_bar.util.dart';
import '../../constants/constants.dart';
import '../../store/auth.store.dart'; import '../../store/auth.store.dart';
// import 'package:sentry/sentry.dart'; // import 'package:sentry/sentry.dart';

View File

@ -35,11 +35,14 @@ class _MinePageState extends State<MinePage>
Widget _buildBody() { Widget _buildBody() {
return Column(children: [ return Column(children: [
Container( Container(
height: ScreenAdaper.height(300), height: ScreenAdaper.height(350),
decoration: const BoxDecoration( decoration: BoxDecoration(
image: DecorationImage( gradient: LinearGradient(
fit: BoxFit.cover, colors: [AppTheme.primaryColorLight, AppTheme.primaryColor])
image: AssetImage('assets/images/yeyazhijia_bg.jpg'))), // image: DecorationImage(
// fit: BoxFit.cover,
// image: AssetImage('assets/images/yeyazhijia_bg.jpg'))
),
// decoration: BoxDecoration( // decoration: BoxDecoration(
// gradient: LinearGradient( // gradient: LinearGradient(
// colors: [AppTheme.primaryColorLight, AppTheme.primaryColor])), // colors: [AppTheme.primaryColorLight, AppTheme.primaryColor])),
@ -49,7 +52,7 @@ class _MinePageState extends State<MinePage>
vertical: ScreenAdaper.height(20)), vertical: ScreenAdaper.height(20)),
child: Column(children: [ child: Column(children: [
SizedBox( SizedBox(
height: ScreenAdaper.height(80), height: ScreenAdaper.height(100),
), ),
Row( Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
@ -69,7 +72,7 @@ class _MinePageState extends State<MinePage>
AuthStore.to.userInfo.value.nickname ?? '', AuthStore.to.userInfo.value.nickname ?? '',
style: TextStyle( style: TextStyle(
letterSpacing: ScreenAdaper.width(5), letterSpacing: ScreenAdaper.width(5),
fontSize: ScreenAdaper.height(30), fontSize: ScreenAdaper.height(35),
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
foreground: Paint() foreground: Paint()
..style = PaintingStyle.stroke ..style = PaintingStyle.stroke
@ -81,7 +84,7 @@ class _MinePageState extends State<MinePage>
style: TextStyle( style: TextStyle(
letterSpacing: ScreenAdaper.width(5), letterSpacing: ScreenAdaper.width(5),
color: Colors.white, color: Colors.white,
fontSize: ScreenAdaper.height(30), fontSize: ScreenAdaper.height(35),
fontWeight: FontWeight.bold), fontWeight: FontWeight.bold),
), ),
], ],

View File

@ -1,6 +1,9 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:sk_base_mobile/app_theme.dart'; import 'package:sk_base_mobile/app_theme.dart';
import 'package:sk_base_mobile/constants/bg_color.dart';
import 'package:sk_base_mobile/services/app_info.service.dart';
import 'package:sk_base_mobile/store/auth.store.dart'; import 'package:sk_base_mobile/store/auth.store.dart';
import 'package:sk_base_mobile/util/device.util.dart';
import 'package:sk_base_mobile/util/screen_adaper_util.dart'; import 'package:sk_base_mobile/util/screen_adaper_util.dart';
class MineSettingsPage extends StatelessWidget { class MineSettingsPage extends StatelessWidget {
@ -18,7 +21,7 @@ class MineSettingsPage extends StatelessWidget {
border: Border.all(), border: Border.all(),
borderRadius: BorderRadius.circular(15), borderRadius: BorderRadius.circular(15),
color: AppTheme.nearlyWhite), color: AppTheme.nearlyWhite),
width: ScreenAdaper.width(400), width: ScreenAdaper.width(600),
padding: padding:
EdgeInsets.symmetric(vertical: ScreenAdaper.width(10)), EdgeInsets.symmetric(vertical: ScreenAdaper.width(10)),
child: InkWell( child: InkWell(
@ -35,7 +38,44 @@ class MineSettingsPage extends StatelessWidget {
Text( Text(
'退出登录', '退出登录',
style: TextStyle( style: TextStyle(
fontSize: ScreenAdaper.height(20), fontSize: ScreenAdaper.height(30),
fontWeight: FontWeight.w600),
),
],
)))),
SizedBox(
height: ScreenAdaper.height(defaultPadding),
),
Container(
decoration: BoxDecoration(
border: Border.all(),
borderRadius: BorderRadius.circular(15),
color: AppTheme.nearlyWhite),
width: ScreenAdaper.width(600),
padding:
EdgeInsets.symmetric(vertical: ScreenAdaper.width(10)),
child: InkWell(
onTap: () async {
await AppInfoService.to.checkVersion();
},
child: Container(
padding: EdgeInsets.symmetric(
horizontal: ScreenAdaper.width(20),
vertical: ScreenAdaper.width(20)),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text(
'v${AppInfoService.to.versionNumber}',
style: TextStyle(
fontSize: ScreenAdaper.height(25),
fontWeight: FontWeight.w400),
),
const Spacer(),
Text(
'检查更新',
style: TextStyle(
fontSize: ScreenAdaper.height(30),
fontWeight: FontWeight.w600), fontWeight: FontWeight.w600),
), ),
], ],

View File

@ -84,10 +84,10 @@ class NewInventoryInout extends StatelessWidget {
SizedBox( SizedBox(
height: ScreenAdaper.height(formVerticalGap), height: ScreenAdaper.height(formVerticalGap),
), ),
buildDatePicker(), // buildDatePicker(),
SizedBox( // SizedBox(
height: ScreenAdaper.height(formVerticalGap), // height: ScreenAdaper.height(formVerticalGap),
), // ),
buildAgent(), buildAgent(),
SizedBox( SizedBox(
height: ScreenAdaper.height(formVerticalGap), height: ScreenAdaper.height(formVerticalGap),

View File

@ -128,13 +128,29 @@ class NewInventoryInoutController extends GetxController {
); );
return; return;
} }
if (payload['time'] == null) { //
SnackBarUtil().error( // if (payload['time'] == null) {
'时间不能为空', // SnackBarUtil().error(
); // '时间不能为空',
return; // );
} // return;
// }
payload['time'] = DateUtil.format(DateTime.now(), formats: [
'yyyy',
'-',
'mm',
'-',
'dd',
' ',
'HH',
':',
'nn',
":",
'ss'
]);
payload['quantity'] = quantityTextController.text; payload['quantity'] = quantityTextController.text;
if (payload['quantity'].isEmpty || payload['quantity'] == '0') { if (payload['quantity'].isEmpty || payload['quantity'] == '0') {
SnackBarUtil().error( SnackBarUtil().error(
'数量必须大于1', '数量必须大于1',

View File

@ -8,9 +8,7 @@ import 'package:sk_base_mobile/models/base_search_more_controller.dart';
import 'package:sk_base_mobile/models/sale_quotation.model.dart'; import 'package:sk_base_mobile/models/sale_quotation.model.dart';
import 'package:sk_base_mobile/screens/sale_quotation/components/sale_quotation_group_search.dart'; import 'package:sk_base_mobile/screens/sale_quotation/components/sale_quotation_group_search.dart';
import 'package:sk_base_mobile/services/storage.service.dart'; import 'package:sk_base_mobile/services/storage.service.dart';
import 'package:sk_base_mobile/util/snack_bar.util.dart';
import 'package:sk_base_mobile/widgets/core/sk_muti_search_more.dart'; import 'package:sk_base_mobile/widgets/core/sk_muti_search_more.dart';
import 'package:sk_base_mobile/widgets/core/sk_single_search_more.dart';
import 'package:sk_base_mobile/util/modal.util.dart'; import 'package:sk_base_mobile/util/modal.util.dart';
import 'package:sk_base_mobile/util/screen_adaper_util.dart'; import 'package:sk_base_mobile/util/screen_adaper_util.dart';
import 'package:pinyin/pinyin.dart'; import 'package:pinyin/pinyin.dart';
@ -20,19 +18,25 @@ class SaleQuotationController extends GetxController {
final RxList editingcell = RxList([null, null, null]); final RxList editingcell = RxList([null, null, null]);
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>(); final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
RxList<SaleQuotationItemModel> products = RxList([ RxList<SaleQuotationItemModel> products = RxList([
SaleQuotationItemModel(name: '矿用本安型支架控制器', unit: '', spec: 'ZDYZ-Z'), SaleQuotationItemModel(
SaleQuotationItemModel(name: '矿用本安型电磁阀驱动器'), name: '矿用本安型支架控制器', unit: '', spec: 'ZDYZ-Z', cost: 4700),
SaleQuotationItemModel(name: '矿用隔爆兼本安型电源'), SaleQuotationItemModel(name: '矿用本安型电磁阀驱动器', cost: 1200),
SaleQuotationItemModel(name: '矿用本安型隔离耦合器'), SaleQuotationItemModel(name: '矿用隔爆兼本安型电源', cost: 5700),
SaleQuotationItemModel(name: '钢丝编织橡胶护套连接器'), SaleQuotationItemModel(name: '矿用本安型隔离耦合器', cost: 1200),
SaleQuotationItemModel(name: '钢丝编织橡胶护套连接器', remark: '控制器-控制器'), SaleQuotationItemModel(name: '钢丝编织橡胶护套连接器', cost: 600),
SaleQuotationItemModel(name: '钢丝编织橡胶护套连接器', remark: '控制器-驱动器'), SaleQuotationItemModel(name: '钢丝编织橡胶护套连接器', remark: '控制器-控制器', cost: 400),
SaleQuotationItemModel(name: '钢丝编织橡胶护套连接器', remark: '控制器-隔离耦合器'), SaleQuotationItemModel(name: '钢丝编织橡胶护套连接器', remark: '控制器-驱动器', cost: 500),
SaleQuotationItemModel(name: '矿用本安型支架无线遥控器'), SaleQuotationItemModel(
SaleQuotationItemModel(name: '矿用隔爆兼本安型电源'), name: '钢丝编织橡胶护套连接器', remark: '控制器-隔离耦合器', cost: 2000),
SaleQuotationItemModel(name: '电液换向阀(10功能10接口)', remark: '中间过渡架主阀组'), SaleQuotationItemModel(name: '矿用本安型支架控制器', cost: 4700),
SaleQuotationItemModel(name: '电液换向阀(20功能20接口)', remark: '端头架主阀组'), SaleQuotationItemModel(name: '矿用本安型电磁阀驱动器', cost: 1200),
SaleQuotationItemModel(name: '自动反冲洗过滤装置', remark: '流量:900L/min,过滤精度25μm'), SaleQuotationItemModel(name: '矿用隔爆兼本安型电源', cost: 5700),
SaleQuotationItemModel(
name: '电液换向阀(10功能10接口)', remark: '中间过渡架主阀组', cost: 13200),
SaleQuotationItemModel(
name: '电液换向阀(20功能20接口)', remark: '端头架主阀组', cost: 26500),
SaleQuotationItemModel(
name: '自动反冲洗过滤装置', remark: '流量:900L/min,过滤精度25μm', cost: 2000),
SaleQuotationItemModel(name: '全自动反冲洗过滤器电缆', remark: '控制器-自动反冲洗'), SaleQuotationItemModel(name: '全自动反冲洗过滤器电缆', remark: '控制器-自动反冲洗'),
SaleQuotationItemModel(name: '矿用本安型位移传感器'), SaleQuotationItemModel(name: '矿用本安型位移传感器'),
SaleQuotationItemModel(name: '矿用本安型压力传感器'), SaleQuotationItemModel(name: '矿用本安型压力传感器'),
@ -190,15 +194,51 @@ class SaleQuotationController extends GetxController {
padding: EdgeInsets.symmetric( padding: EdgeInsets.symmetric(
horizontal: ScreenAdaper.width(5), horizontal: ScreenAdaper.width(5),
vertical: ScreenAdaper.height(10)), vertical: ScreenAdaper.height(10)),
child: Row( child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [ children: [
Text( Text(
controller.list[index].name, controller.list[index].name,
style: TextStyle(fontSize: ScreenAdaper.height(25)), style: TextStyle(
fontSize: ScreenAdaper.height(30)),
), ),
], ],
), ),
); if (controller.list[index].spec != null)
Row(
children: [
Text(
'型号:${controller.list[index].spec ?? ''}',
textAlign: TextAlign.start,
style: TextStyle(
fontSize: ScreenAdaper.height(25)),
),
],
),
Row(
children: [
Text(
'单价:¥${controller.list[index].cost}',
textAlign: TextAlign.start,
style: TextStyle(
fontSize: ScreenAdaper.height(25)),
),
],
),
if (controller.list[index].remark != null)
Row(
children: [
Text(
'备注:${controller.list[index].remark ?? ''}',
textAlign: TextAlign.start,
style: TextStyle(
fontSize: ScreenAdaper.height(25)),
),
],
),
]));
}, },
), ),
width: Get.width - ScreenAdaper.width(50)) width: Get.width - ScreenAdaper.width(50))
@ -239,19 +279,25 @@ class ItemSearchMoreController extends GetxController
@override @override
Future<List<SaleQuotationItemModel>> getData({bool isRefresh = false}) async { Future<List<SaleQuotationItemModel>> getData({bool isRefresh = false}) async {
List<SaleQuotationItemModel> newList = [ List<SaleQuotationItemModel> newList = [
SaleQuotationItemModel(name: '矿用本安型支架控制器', unit: '', spec: 'ZDYZ-Z'), SaleQuotationItemModel(
SaleQuotationItemModel(name: '矿用本安型电磁阀驱动器'), name: '矿用本安型支架控制器', unit: '', spec: 'ZDYZ-Z', cost: 4700),
SaleQuotationItemModel(name: '矿用隔爆兼本安型电源'), SaleQuotationItemModel(name: '矿用本安型电磁阀驱动器', cost: 1200),
SaleQuotationItemModel(name: '矿用本安型隔离耦合器'), SaleQuotationItemModel(name: '矿用隔爆兼本安型电源', cost: 5700),
SaleQuotationItemModel(name: '钢丝编织橡胶护套连接器'), SaleQuotationItemModel(name: '矿用本安型隔离耦合器', cost: 1200),
SaleQuotationItemModel(name: '钢丝编织橡胶护套连接器', remark: '控制器-控制器'), SaleQuotationItemModel(name: '钢丝编织橡胶护套连接器', cost: 600),
SaleQuotationItemModel(name: '钢丝编织橡胶护套连接器', remark: '控制器-驱动器'), SaleQuotationItemModel(name: '钢丝编织橡胶护套连接器', remark: '控制器-控制器', cost: 400),
SaleQuotationItemModel(name: '钢丝编织橡胶护套连接器', remark: '控制器-隔离耦合器'), SaleQuotationItemModel(name: '钢丝编织橡胶护套连接器', remark: '控制器-驱动器', cost: 500),
SaleQuotationItemModel(name: '矿用本安型支架无线遥控器'), SaleQuotationItemModel(
SaleQuotationItemModel(name: '矿用隔爆兼本安型电源'), name: '钢丝编织橡胶护套连接器', remark: '控制器-隔离耦合器', cost: 2000),
SaleQuotationItemModel(name: '电液换向阀(10功能10接口)', remark: '中间过渡架主阀组'), SaleQuotationItemModel(name: '矿用本安型支架控制器', cost: 4700),
SaleQuotationItemModel(name: '电液换向阀(20功能20接口)', remark: '端头架主阀组'), SaleQuotationItemModel(name: '矿用本安型电磁阀驱动器', cost: 1200),
SaleQuotationItemModel(name: '自动反冲洗过滤装置', remark: '流量:900L/min,过滤精度25μm'), SaleQuotationItemModel(name: '矿用隔爆兼本安型电源', cost: 5700),
SaleQuotationItemModel(
name: '电液换向阀(10功能10接口)', remark: '中间过渡架主阀组', cost: 13200),
SaleQuotationItemModel(
name: '电液换向阀(20功能20接口)', remark: '端头架主阀组', cost: 26500),
SaleQuotationItemModel(
name: '自动反冲洗过滤装置', remark: '流量:900L/min,过滤精度25μm', cost: 2000),
SaleQuotationItemModel(name: '全自动反冲洗过滤器电缆', remark: '控制器-自动反冲洗'), SaleQuotationItemModel(name: '全自动反冲洗过滤器电缆', remark: '控制器-自动反冲洗'),
SaleQuotationItemModel(name: '矿用本安型位移传感器'), SaleQuotationItemModel(name: '矿用本安型位移传感器'),
SaleQuotationItemModel(name: '矿用本安型压力传感器'), SaleQuotationItemModel(name: '矿用本安型压力传感器'),

View File

@ -35,7 +35,7 @@ class SaleQuotationPage extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
key: controller.scaffoldKey, key: controller.scaffoldKey,
endDrawer: Drawer( endDrawer: const Drawer(
// //
child: SaleQuotationEndDrawer(), child: SaleQuotationEndDrawer(),
), ),
@ -47,7 +47,23 @@ class SaleQuotationPage extends StatelessWidget {
controller.scaffoldKey.currentState?.openEndDrawer(); controller.scaffoldKey.currentState?.openEndDrawer();
}, },
icon: const Icon(Icons.more_horiz_outlined, color: AppTheme.white), icon: const Icon(Icons.more_horiz_outlined, color: AppTheme.white),
),
Container(
padding: EdgeInsets.symmetric(
vertical: ScreenAdaper.height(10),
horizontal: ScreenAdaper.width(20)),
child: Row(mainAxisAlignment: MainAxisAlignment.end, children: [
GestureDetector(
onTap: () {
controller.addGroup();
},
child: Icon(
Icons.add,
size: ScreenAdaper.height(40),
),
) )
]),
),
], ],
), ),
body: SafeArea( body: SafeArea(
@ -65,6 +81,8 @@ class SaleQuotationPage extends StatelessWidget {
(index, e) => buildBody(index)) (index, e) => buildBody(index))
.toList(), .toList(),
))), ))),
//
SizedBox( SizedBox(
height: ScreenAdaper.height(100), height: ScreenAdaper.height(100),
child: buildTotalCostRow(), child: buildTotalCostRow(),
@ -76,7 +94,7 @@ class SaleQuotationPage extends StatelessWidget {
], ],
), ),
// Positioned( // Positioned(
// bottom: ScreenAdaper.height(10), // bottom: ScreenAdaper.height(220),
// right: ScreenAdaper.height(10), // right: ScreenAdaper.height(10),
// child: IconButton( // child: IconButton(
// padding: EdgeInsets.all(ScreenAdaper.height(20)), // padding: EdgeInsets.all(ScreenAdaper.height(20)),
@ -339,8 +357,8 @@ class SaleQuotationPage extends StatelessWidget {
const Spacer(), const Spacer(),
IconButton( IconButton(
onPressed: () { onPressed: () {
ModalUtil.confirm( ModalUtil.alert(
title: '确定要删除此组吗?', contentText: '确定要删除此组吗?',
onConfirm: () { onConfirm: () {
controller.removeGroup(groupIndex); controller.removeGroup(groupIndex);
}); });
@ -464,7 +482,7 @@ class SaleQuotationPage extends StatelessWidget {
], ],
), ),
), ),
VerticalDivider(), const VerticalDivider(),
buildEditCell<int>( buildEditCell<int>(
Container( Container(
alignment: Alignment.center, alignment: Alignment.center,

View File

@ -7,6 +7,7 @@ import 'package:sk_base_mobile/constants/router.dart';
import 'package:sk_base_mobile/screens/workbench/workbench_controller.dart'; import 'package:sk_base_mobile/screens/workbench/workbench_controller.dart';
import 'package:sk_base_mobile/util/screen_adaper_util.dart'; import 'package:sk_base_mobile/util/screen_adaper_util.dart';
import 'package:sk_base_mobile/util/snack_bar.util.dart'; import 'package:sk_base_mobile/util/snack_bar.util.dart';
import 'package:sk_base_mobile/widgets/sk_appbar.dart';
class WorkBenchPage extends StatelessWidget { class WorkBenchPage extends StatelessWidget {
WorkBenchPage({super.key}); WorkBenchPage({super.key});
@ -15,31 +16,8 @@ class WorkBenchPage extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: const SkAppbar(title: '工作台', hideLeading: true),
leading: const SizedBox(), body: buildList());
title: const Text(
'工作台',
),
),
body: buildList()
// Container(
// padding: EdgeInsets.all(ScreenAdaper.width(20)),
// child: GridView.builder(
// shrinkWrap: true,
// physics: const NeverScrollableScrollPhysics(),
// itemCount: works.length,
// gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
// crossAxisCount: Get.width > 800 ? 5 : 3,
// crossAxisSpacing: ScreenAdaper.width(20),
// mainAxisSpacing: ScreenAdaper.height(20),
// childAspectRatio: 1.0),
// itemBuilder: (BuildContext context, int index) {
// return buildCard(index);
// },
// ),
// )
);
} }
Widget buildList() { Widget buildList() {

View File

@ -3,7 +3,6 @@ import 'package:get/get.dart';
import 'package:sk_base_mobile/models/workbench.model.dart'; import 'package:sk_base_mobile/models/workbench.model.dart';
class WorkBenchController extends GetxController { class WorkBenchController extends GetxController {
late final AnimationController animationController;
final List<WorkBenchModel> menus = [ final List<WorkBenchModel> menus = [
WorkBenchModel(title: '库存', route: '/inventory', icon: 'inventory.svg'), WorkBenchModel(title: '库存', route: '/inventory', icon: 'inventory.svg'),
WorkBenchModel(title: '产品', route: '/product', icon: 'product.svg'), WorkBenchModel(title: '产品', route: '/product', icon: 'product.svg'),
@ -15,9 +14,4 @@ class WorkBenchController extends GetxController {
WorkBenchModel( WorkBenchModel(
title: '报价计算', route: '/sale_quotation', icon: 'sale_quotation.svg'), title: '报价计算', route: '/sale_quotation', icon: 'sale_quotation.svg'),
]; ];
@override
void onClose() {
animationController.dispose();
super.onClose();
}
} }

View File

@ -1,9 +1,26 @@
import 'dart:io';
import 'package:decimal/decimal.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:install_plugin/install_plugin.dart';
import 'package:package_info/package_info.dart'; import 'package:package_info/package_info.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:sk_base_mobile/apis/index.dart';
import 'package:sk_base_mobile/app_theme.dart';
import 'package:sk_base_mobile/config.dart';
import 'package:sk_base_mobile/models/app_config.dart'; import 'package:sk_base_mobile/models/app_config.dart';
import 'package:sk_base_mobile/services/service.dart'; import 'package:sk_base_mobile/services/service.dart';
import 'package:sk_base_mobile/util/device.util.dart';
import 'package:sk_base_mobile/util/logger_util.dart'; import 'package:sk_base_mobile/util/logger_util.dart';
import 'package:sk_base_mobile/util/modal.util.dart';
import 'package:sk_base_mobile/util/screen_adaper_util.dart';
import 'package:sk_base_mobile/util/snack_bar.util.dart';
import 'package:sk_base_mobile/widgets/upgrade_confirm.dart';
import '../constants/constants.dart'; import '../constants/constants.dart';
import 'package:dio/dio.dart';
import 'package:path_provider/path_provider.dart';
class AppInfoService extends GetxService { class AppInfoService extends GetxService {
static AppInfoService get to => Get.find(); static AppInfoService get to => Get.find();
@ -12,14 +29,16 @@ class AppInfoService extends GetxService {
final scale = RxDouble(1.0); final scale = RxDouble(1.0);
final isLarge = RxBool(false); final isLarge = RxBool(false);
final isCameraing = RxBool(false); final isCameraing = RxBool(false);
final downloadProgress = RxDouble(0.0);
Future<AppInfoService> init() async { Future<AppInfoService> init() async {
LoggerUtil() LoggerUtil()
.info("[service-appInfo] Register app-related information service"); .info("[service-appInfo] Register app-related information service");
try { try {
// await Future.wait( await Future.wait([
// [getDeviceInfo(), getPackageInfo(), getAppConfig(), getossPolicy()]); getDeviceInfo(),
getPackageInfo() /* , getAppConfig(), getossPolicy() */
]);
requestPermission(); requestPermission();
} catch (e) { } catch (e) {
LoggerUtil().error(e); LoggerUtil().error(e);
@ -93,6 +112,125 @@ class AppInfoService extends GetxService {
// } // }
// } // }
} }
Future<void> checkVersion() async {
final res = await Future.wait([
Api.getSystemParamConfigByCode(SystemParamConfig.appVersion),
Api.getSystemParamConfigByCode(SystemParamConfig.isForceUpgrade)
]);
final newVersion = res[0].data;
final isForceUpgrade = res[1].data;
if (newVersion != null) {
final currentVersion = await DeviceUtil.getAppVersion();
if (newVersion != currentVersion) {
ModalUtil.alert(
// title: '有新版本',
builder: (_) => UpgradeConfirm(
onConfirm: () {
upgradeApp(newVersion);
},
forceUpgrade: isForceUpgrade == '1',
),
// contentText: isForceUpgrade == '1' ? '此版本非常重要,强制更新' : '请更新',
);
}
}
}
Future<void> upgradeApp(String version) async {
if (await checkPermission()) {
///
String url = '${GloablConfig.OSS_URL}/upload/shankuangtong_v$version.apk';
///
Directory? storageDir = await getExternalStorageDirectory();
if (storageDir != null) {
String storagePath = storageDir.path;
File file = File('$storagePath/shankuangtong_v${version}.apk');
if (!file.existsSync()) {
file.createSync();
}
try {
///
downloadProgress.value = 0;
Get.back();
ModalUtil.alert(
barrierDismissible: false,
contentPadding: EdgeInsets.symmetric(vertical: 0),
showActions: false,
content:
//
Obx(
() => Stack(
children: [
Container(
height: ScreenAdaper.height(40),
child: LinearProgressIndicator(
value: downloadProgress.value,
),
),
Positioned(
left: 0,
right: 0,
child: Text(
'${downloadProgress.value * 100}%',
textAlign: TextAlign.center,
style: TextStyle(fontSize: ScreenAdaper.height(30)),
))
],
),
));
await DioService.dio.download(url, file.path,
onReceiveProgress: (num received, num total) =>
onReceiveProgress(received, total),
options: Options(
responseType: ResponseType.bytes,
followRedirects: false,
));
Get.back();
InstallPlugin.install(
file.path,
).then((result) {}).catchError((error) {});
} catch (e) {
SnackBarUtil().warning('暂时无法更新,请重新下载安装, 或者请联系管理员');
}
}
}
}
///
void onReceiveProgress(num received, num total) {
if (total != -1) {
downloadProgress.value =
Decimal.parse((received / total).toStringAsFixed(2))
.toDouble()
.toPrecision(2);
}
}
///
Future<bool> checkPermission() async {
if (await DeviceUtil.getPlatForm() == 'android') {
// storage权限
if (await Permission.storage.request().isGranted) {
return true;
// PermissionStatus permission = await PermissionHandler()
// .checkPermissionStatus(PermissionGroup.storage);
// if (permission != PermissionStatus.granted) {
// Map<PermissionGroup, PermissionStatus> permissions =
// await PermissionHandler()
// .requestPermissions([PermissionGroup.storage]);
// if (permissions[PermissionGroup.storage] == PermissionStatus.granted) {
// return true;
// }
} else {
return false;
}
}
return false;
}
T getConfigByCode<T>(String code) { T getConfigByCode<T>(String code) {
List<AppConfigItem> items = appConfig.items!; List<AppConfigItem> items = appConfig.items!;

View File

@ -64,7 +64,9 @@ class DioService extends get_package.GetxService {
} else if (e.response?.statusCode == 401) { } else if (e.response?.statusCode == 401) {
// dio.lock(); // dio.lock();
LoggerUtil().error('[Service-dio] logout:${e.response}'); LoggerUtil().error('[Service-dio] logout:${e.response}');
await AuthStore().logout(force: true); Future.delayed(Duration(seconds: 1), () {
AuthStore().logout(force: true);
});
SnackBarUtil().error('请重新登录'); SnackBarUtil().error('请重新登录');
} else if (e.response?.statusCode == 403) { } else if (e.response?.statusCode == 403) {
await SnackBarUtil().error( await SnackBarUtil().error(
@ -126,6 +128,7 @@ class DioService extends get_package.GetxService {
void onResponse(Response response, ResponseInterceptorHandler handler) async { void onResponse(Response response, ResponseInterceptorHandler handler) async {
/* LoggerUtil().info('[Service-dio] ${response.data}'); */ /* LoggerUtil().info('[Service-dio] ${response.data}'); */
if (whiteList.contains(response.requestOptions.path)) { if (whiteList.contains(response.requestOptions.path)) {
handler.next(response); handler.next(response);
return; return;

View File

@ -1,6 +1,7 @@
import 'dart:convert'; import 'dart:convert';
import 'package:dio/dio.dart' as dio_package; import 'package:dio/dio.dart' as dio_package;
import 'package:flutter/widgets.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:sk_base_mobile/apis/index.dart'; import 'package:sk_base_mobile/apis/index.dart';
import 'package:sk_base_mobile/store/dict.store.dart'; import 'package:sk_base_mobile/store/dict.store.dart';
@ -57,9 +58,11 @@ class AuthStore extends GetxService {
await StorageService.to.remove(CacheKeys.userInfo, isWithUser: false); await StorageService.to.remove(CacheKeys.userInfo, isWithUser: false);
LoggerUtil().info('[Store-Auth] Logout succeed.'); LoggerUtil().info('[Store-Auth] Logout succeed.');
// login界面 // login界面
// Get已经注册
if (Get.currentRoute != RouteConfig.login) { if (Get.currentRoute != RouteConfig.login) {
Get.offAllNamed(RouteConfig.login); Get.offAllNamed(RouteConfig.login);
} }
// getx跳转登录页
} }
Future<void> login( Future<void> login(
@ -72,7 +75,7 @@ class AuthStore extends GetxService {
// return; // return;
// } // }
LoadingUtil.to.show(); await LoadingUtil.to.show();
TapToDismissKeyboard.dismissOf(context: Get.context!); TapToDismissKeyboard.dismissOf(context: Get.context!);
try { try {
await Future.delayed(const Duration(seconds: 1)); await Future.delayed(const Duration(seconds: 1));
@ -89,7 +92,7 @@ class AuthStore extends GetxService {
Get.offNamed(RouteConfig.home); Get.offNamed(RouteConfig.home);
} }
} catch (e) { } catch (e) {
await SnackBarUtil().error('账号密码错误$e'); await SnackBarUtil().error('账号密码错误');
LoggerUtil().error(e); LoggerUtil().error(e);
} finally { } finally {
LoadingUtil.to.dismiss(); LoadingUtil.to.dismiss();

View File

@ -3,7 +3,7 @@ import 'package:date_format/date_format.dart';
class DateUtil { class DateUtil {
/// YYYY-MM-DD /// YYYY-MM-DD
static String format(DateTime date, {List<String>? formats}) { static String format(DateTime date, {List<String>? formats}) {
return formatDate(date, formats ?? ['yyyy', '-', 'mm', '-', 'dd']); return formatDate(date, formats ?? ['yyyy', '-', 'MM', '-', 'dd']);
} }
/// ///

19
lib/util/device.util.dart Normal file
View File

@ -0,0 +1,19 @@
import 'dart:io';
import 'package:package_info/package_info.dart';
class DeviceUtil {
///
static Future<String> getAppVersion() async {
PackageInfo packageInfo = await PackageInfo.fromPlatform();
return packageInfo.version;
}
///
static Future<String> getPlatForm() async {
if (Platform.isAndroid) {
return 'android';
} else {
return 'ios';
}
}
}

View File

@ -6,12 +6,23 @@ import 'package:sk_base_mobile/util/screen_adaper_util.dart';
import 'package:sk_base_mobile/widgets/core/sk_bottomsheet_picker.dart'; import 'package:sk_base_mobile/widgets/core/sk_bottomsheet_picker.dart';
class ModalUtil { class ModalUtil {
static Future<bool> confirm( static Future<bool> alert(
{String? title, String? button, VoidCallback? onConfirm}) async { {String? title,
String? contentText,
String? confirmText,
Widget? content,
VoidCallback? onConfirm,
Widget Function(BuildContext)? builder,
EdgeInsetsGeometry? contentPadding,
bool showActions = true,
bool barrierDismissible = true,
bool showCancel = true}) async {
bool confirmed = false; bool confirmed = false;
await showDialog( await showDialog(
context: Get.overlayContext!, context: Get.overlayContext!,
builder: (context) { barrierDismissible: barrierDismissible,
builder: builder ??
(context) {
return AlertDialog( return AlertDialog(
clipBehavior: Clip.hardEdge, clipBehavior: Clip.hardEdge,
backgroundColor: AppTheme.nearlyWhite, backgroundColor: AppTheme.nearlyWhite,
@ -20,17 +31,19 @@ class ModalUtil {
), ),
actionsPadding: EdgeInsets.zero, actionsPadding: EdgeInsets.zero,
titlePadding: EdgeInsets.zero, titlePadding: EdgeInsets.zero,
contentPadding: contentPadding ??
EdgeInsets.symmetric(
vertical: ScreenAdaper.height(10),
),
title: title != null title: title != null
? Container( ? Container(
padding: EdgeInsets.symmetric( padding: EdgeInsets.symmetric(
vertical: ScreenAdaper.height(30), vertical: ScreenAdaper.height(20),
horizontal: ScreenAdaper.width(30)), ),
decoration: BoxDecoration( decoration: const BoxDecoration(
border: Border( border: Border(
bottom: BorderSide( bottom:
color: AppTheme.dividerColor, BorderSide(color: AppTheme.dividerColor))),
width: ScreenAdaper.height(2)))),
alignment: Alignment.center,
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
@ -43,16 +56,43 @@ class ModalUtil {
), ),
Text( Text(
title, title,
textAlign: TextAlign.center,
style: TextStyle(
fontWeight: FontWeight.w500,
fontSize: ScreenAdaper.height(30),
color: AppTheme.black,
),
)
],
),
)
: null,
content: content ??
(contentText != null
? Container(
padding: EdgeInsets.symmetric(
vertical: ScreenAdaper.height(20),
),
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
color: AppTheme.dividerColor,
width: ScreenAdaper.height(2)))),
child: Text(
// '${title}${title}${title}${title}${title}${title}${title}${title}${title}${title}${title}${title}${title}${title}${title}${title}${title}${title} ${title}${title}${title}${title}',
contentText,
textAlign: TextAlign.center,
style: TextStyle( style: TextStyle(
fontSize: ScreenAdaper.height(30), fontSize: ScreenAdaper.height(30),
fontWeight: FontWeight.w500), fontWeight: FontWeight.w500),
) ))
]), : null),
) actions: !showActions
: null, ? null
actions: [ : [
Row( Row(
children: [ children: [
if (showCancel)
Expanded( Expanded(
child: InkWell( child: InkWell(
onTap: () { onTap: () {
@ -70,7 +110,6 @@ class ModalUtil {
fontSize: ScreenAdaper.height(30)), fontSize: ScreenAdaper.height(30)),
)), )),
)), )),
const VerticalDivider(),
Expanded( Expanded(
child: InkWell( child: InkWell(
onTap: () { onTap: () {
@ -79,11 +118,11 @@ class ModalUtil {
confirmed = true; confirmed = true;
}, },
child: Container( child: Container(
padding: padding: EdgeInsets.symmetric(
EdgeInsets.symmetric(vertical: ScreenAdaper.height(15)), vertical: ScreenAdaper.height(15)),
alignment: Alignment.center, alignment: Alignment.center,
child: Text( child: Text(
'确定', confirmText ?? '确定',
style: TextStyle( style: TextStyle(
color: Colors.black, color: Colors.black,
fontSize: ScreenAdaper.height(30)), fontSize: ScreenAdaper.height(30)),

View File

@ -59,6 +59,7 @@ class SkMutilSearchMore<T extends BaseSearchMoreModel> extends StatelessWidget {
if (isDialog) { if (isDialog) {
Get.back(); Get.back();
} }
controller.selectedIndex.clear();
}, },
buttonText: '确定', buttonText: '确定',
) )

View File

@ -2,7 +2,6 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:sk_base_mobile/app_theme.dart'; import 'package:sk_base_mobile/app_theme.dart';
import 'package:sk_base_mobile/util/screen_adaper_util.dart'; import 'package:sk_base_mobile/util/screen_adaper_util.dart';
import 'package:sk_base_mobile/util/snack_bar.util.dart';
class SkNumberInput<T> extends StatefulWidget { class SkNumberInput<T> extends StatefulWidget {
final TextEditingController textController; final TextEditingController textController;
@ -17,8 +16,8 @@ class SkNumberInput<T> extends StatefulWidget {
final bool isRequired; final bool isRequired;
final String labelText; final String labelText;
final String? hint; final String? hint;
ValueChanged<int>? onFieldSubmitted; final ValueChanged<int>? onFieldSubmitted;
SkNumberInput( const SkNumberInput(
{super.key, {super.key,
required this.textController, required this.textController,
this.onTap, this.onTap,

View File

@ -15,8 +15,8 @@ class SkTextInput extends StatefulWidget {
final String? Function(String?)? validator; final String? Function(String?)? validator;
final EdgeInsetsGeometry? contentPadding; final EdgeInsetsGeometry? contentPadding;
final bool autoFocus; final bool autoFocus;
ValueChanged<String>? onFieldSubmitted; final ValueChanged<String>? onFieldSubmitted;
SkTextInput( const SkTextInput(
{super.key, {super.key,
required this.textController, required this.textController,
this.onTap, this.onTap,

View File

@ -30,7 +30,7 @@ class GradientButton extends StatelessWidget {
Size(double.infinity, ScreenAdaper.height(80))), Size(double.infinity, ScreenAdaper.height(80))),
shape: MaterialStateProperty.all<RoundedRectangleBorder>( shape: MaterialStateProperty.all<RoundedRectangleBorder>(
RoundedRectangleBorder( RoundedRectangleBorder(
borderRadius: BorderRadius.circular(0), borderRadius: BorderRadius.circular(10),
), ),
), ),
), ),

View File

@ -22,8 +22,8 @@ class MyAvatarWidget extends StatelessWidget {
border: Border.all( border: Border.all(
color: AppTheme.white, width: ScreenAdaper.sp(2)), color: AppTheme.white, width: ScreenAdaper.sp(2)),
borderRadius: BorderRadius.circular(50)), borderRadius: BorderRadius.circular(50)),
height: ScreenAdaper.width(120), height: ScreenAdaper.width(150),
width: ScreenAdaper.width(120), width: ScreenAdaper.width(150),
child: const SizedBox(), child: const SizedBox(),
)), )),
Positioned( Positioned(

View File

@ -0,0 +1,111 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:get/get.dart';
import 'package:sk_base_mobile/app_theme.dart';
import 'package:sk_base_mobile/services/app_info.service.dart';
import 'package:sk_base_mobile/util/screen_adaper_util.dart';
import 'package:sk_base_mobile/widgets/gradient_button.dart';
class UpgradeConfirm extends StatelessWidget {
void Function()? onConfirm;
bool forceUpgrade;
UpgradeConfirm({super.key, this.onConfirm, this.forceUpgrade = true});
@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(ScreenAdaper.radius(30))),
margin: EdgeInsets.only(bottom: ScreenAdaper.height(30)),
alignment: Alignment.center,
child: Stack(
children: [
Container(
height: ScreenAdaper.height(600),
constraints: BoxConstraints(maxHeight: ScreenAdaper.height(600)),
width: ScreenAdaper.width(800),
margin: EdgeInsets.only(
top: ScreenAdaper.height(100),
),
padding: EdgeInsets.only(
top: ScreenAdaper.height(50), bottom: ScreenAdaper.height(30)),
decoration: BoxDecoration(
color: AppTheme.nearlyWhite,
borderRadius: BorderRadius.circular(ScreenAdaper.radius(30))),
child: Column(
children: [
Text(
'有新的版本更新啦',
style: TextStyle(
decoration: TextDecoration.none,
fontSize: ScreenAdaper.height(35),
color: AppTheme.nearlyBlack,
),
),
SizedBox(
height: ScreenAdaper.height(30),
),
Expanded(
child: SingleChildScrollView(
child: Column(
children: [
Text('1.修复bug',
style: TextStyle(
decoration: TextDecoration.none,
fontSize: ScreenAdaper.height(30),
color: AppTheme.grey,
fontWeight: FontWeight.w400)),
Text('2.优化体验',
style: TextStyle(
decoration: TextDecoration.none,
fontSize: ScreenAdaper.height(30),
color: AppTheme.grey,
fontWeight: FontWeight.w400)),
],
))),
SizedBox(
height: ScreenAdaper.height(30),
),
Container(
width: ScreenAdaper.height(400),
child: GradientButton(
buttonText: '去更新',
onPressed: () {
if (onConfirm != null) onConfirm!();
},
),
)
],
),
),
if (!forceUpgrade)
Positioned(
right: 0,
top: ScreenAdaper.height(100),
child: //
IconButton(
onPressed: () {
Get.back();
},
icon: const Icon(Icons.close)),
),
//
Positioned(
left: 0,
right: 0,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image(
image: const AssetImage('assets/images/rocket.png'),
height: ScreenAdaper.height(150),
)
],
),
),
],
),
);
}
}

View File

@ -520,6 +520,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.2.1+1" version: "0.2.1+1"
install_plugin:
dependency: "direct main"
description:
name: install_plugin
sha256: "6fb67ba0781e75de4f2f2266ed25e835bfd277c5bfc2ed034af52774355857c6"
url: "https://pub.dev"
source: hosted
version: "2.1.0"
intl: intl:
dependency: transitive dependency: transitive
description: description:

View File

@ -66,6 +66,7 @@ dependencies:
flutter_slidable: ^3.1.0 flutter_slidable: ^3.1.0
pinyin: ^3.2.0 pinyin: ^3.2.0
math_expressions: ^2.4.0 math_expressions: ^2.4.0
install_plugin: ^2.1.0
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
sdk: flutter sdk: flutter