qr scanner
parent
d500e4daf7
commit
9b866298f5
|
|
@ -41,5 +41,9 @@
|
|||
</array>
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<false/>
|
||||
<key>NSCameraUsageDescription</key>
|
||||
<string>Требуется доступ к камере для сканирования QR-кодов и штрих-кодов</string>
|
||||
<key>io.flutter.embedded_views_preview</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
|||
|
|
@ -45,6 +45,27 @@ ThunkAction<AppState> authenticate(String email, String password) {
|
|||
};
|
||||
}
|
||||
|
||||
ThunkAction<AppState> authenticateByToken(String token) {
|
||||
return (Store<AppState> store) async {
|
||||
store.dispatch(SetUserStateAction(UserState(isLoading: true)));
|
||||
try {
|
||||
AuthResponse result = await _api.authorization(token);
|
||||
if ( result.operation!) {
|
||||
_api.token = result.token!;
|
||||
store.dispatch(SetUserStateAction(UserState(isLoading: false, auth: result)));
|
||||
_navigation.replace(MainViewRoute);
|
||||
_afterAuth(store);
|
||||
} else {
|
||||
_dialogService.showDialog(title: 'Внимание', buttonTitle: 'Ok', description: result.message!);
|
||||
}
|
||||
} catch (e) {
|
||||
print(e);
|
||||
} finally {
|
||||
store.dispatch(SetUserStateAction(UserState(isLoading: false)));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Future<void> auth(Store<AppState> store) async {
|
||||
store.dispatch(SetUserStateAction(UserState(isLoading: true)));
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -95,8 +95,8 @@ class Redux {
|
|||
serializer: JsonSerializer<AppState>(AppState.fromJson), // Or use other serializers
|
||||
);
|
||||
|
||||
final initialState = await persist.load();
|
||||
final userStateInitial = UserState.initial(initialState!.userState!);
|
||||
final AppState? initialState = await persist.load();
|
||||
final userStateInitial = UserState.initial(initialState?.userState);
|
||||
final navStateInitial = NavState.initial();
|
||||
final sellStateInitial = SellState.initial();
|
||||
|
||||
|
|
|
|||
|
|
@ -91,6 +91,22 @@ class DictionaryService extends BaseService {
|
|||
return list;
|
||||
}
|
||||
|
||||
Future<List<Good>> getGoodsByEan( String code ) async {
|
||||
List<Good> list = [];
|
||||
try {
|
||||
int? appCompanyId = Redux.store!.state.userState!.auth!.companyId;
|
||||
String where = '( $GoodColumnAppCompanyId = ? and $GoodColumnEan like ? ) ';
|
||||
List args = [appCompanyId, '%$code%'];
|
||||
List<Map<String, dynamic>> elements = await _db.queryRowsWithWhere(GoodTableName, where, args);
|
||||
elements.forEach((element) {
|
||||
list.add(Good.fromMap(element));
|
||||
});
|
||||
} catch (e, stack) {
|
||||
log.e("getGoodsByEan", e, stack);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
bool _isNumericInt(String str) {
|
||||
if(str == null) {
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ Route<dynamic> generateRoute(RouteSettings settings) {
|
|||
case AddByBarcodeViewRoute:
|
||||
return _getPageRoute(
|
||||
routeName: settings.name!,
|
||||
viewToShow: AddByBarcodeView(title: 'Scanner',),
|
||||
viewToShow: AddByBarcodeView(),
|
||||
);
|
||||
case SettingPrinterBluetoothViewRoute:
|
||||
return _getPageRoute(
|
||||
|
|
|
|||
|
|
@ -2,15 +2,13 @@ import 'dart:io';
|
|||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:satu/views/work/tabs/component/products_app_bar.dart';
|
||||
import 'package:satu/widgets/tools/app_barcode_scanner_widget.dart';
|
||||
|
||||
class AddByBarcodeView extends StatefulWidget {
|
||||
final String? title;
|
||||
final int? transactionId;
|
||||
|
||||
const AddByBarcodeView({
|
||||
Key? key,
|
||||
this.title,
|
||||
this.transactionId,
|
||||
Key? key
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
|
|
@ -18,19 +16,27 @@ class AddByBarcodeView extends StatefulWidget {
|
|||
}
|
||||
|
||||
class _AddByBarcodeViewState extends State<AddByBarcodeView> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
String _code = '';
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
print('barcode = image-${widget.transactionId}');
|
||||
return Container(
|
||||
child: Center(
|
||||
child: Hero(
|
||||
tag: 'text',
|
||||
child: Text(widget.title ?? '')),
|
||||
return Scaffold(
|
||||
appBar: ProductsAppBar(
|
||||
title: 'Сканер',
|
||||
),
|
||||
body: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: AppBarcodeScannerWidget.defaultStyle(
|
||||
resultCallback: (String code) {
|
||||
Navigator.pop(context, code);
|
||||
// print(code);
|
||||
// setState(() {
|
||||
// _code = code;
|
||||
// });
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,9 @@ import 'package:satu/core/redux/actions/user_actions.dart';
|
|||
import 'package:satu/core/redux/state/user_state.dart';
|
||||
import 'package:satu/core/redux/store.dart';
|
||||
import 'package:satu/core/services/dialog_service.dart';
|
||||
import 'package:satu/core/services/navigator_service.dart';
|
||||
import 'package:satu/core/utils/locator.dart';
|
||||
import 'package:satu/routes/route_names.dart';
|
||||
import 'package:satu/shared/app_colors.dart';
|
||||
import 'package:satu/shared/ui_helpers.dart';
|
||||
import 'package:satu/widgets/buttons/busy_button.dart';
|
||||
|
|
@ -102,6 +104,16 @@ class _LoginViewState extends State<LoginView> {
|
|||
}
|
||||
|
||||
Future<void> scan() async {
|
||||
|
||||
String? result = await locator<NavigatorService>().push(AddByBarcodeViewRoute);
|
||||
if(result != null) {
|
||||
if( result.length == 60 ) {
|
||||
Redux.store?.dispatch(authenticateByToken(result));
|
||||
} else {
|
||||
_dialogService.showDialog(description: 'Не верный формат QR кода');
|
||||
}
|
||||
}
|
||||
|
||||
// try {
|
||||
// var options = ScanOptions(strings: {
|
||||
// "cancel": 'Отмена',
|
||||
|
|
|
|||
|
|
@ -33,10 +33,7 @@ class _ProductListItemState extends State<ProductListItem> {
|
|||
|
||||
void _onItemTapped(BuildContext context) {
|
||||
Navigator.of(context).push(new MaterialPageRoute(
|
||||
builder: (BuildContext context) => new AddByBarcodeView(
|
||||
title: widget.name,
|
||||
transactionId: widget.transactionId,
|
||||
)));
|
||||
builder: (BuildContext context) => new AddByBarcodeView()));
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ class ProductsAppBar extends StatelessWidget implements PreferredSizeWidget {
|
|||
final int? childHeight;
|
||||
final double elevation;
|
||||
final Color? backgroundColor;
|
||||
final bool drawerShow;
|
||||
|
||||
const ProductsAppBar(
|
||||
{Key? key,
|
||||
|
|
@ -19,6 +20,7 @@ class ProductsAppBar extends StatelessWidget implements PreferredSizeWidget {
|
|||
this.child,
|
||||
this.childHeight = 0,
|
||||
this.elevation = 0.0,
|
||||
this.drawerShow = false,
|
||||
this.backgroundColor = Colors.transparent})
|
||||
: super(key: key);
|
||||
|
||||
|
|
@ -44,7 +46,7 @@ class ProductsAppBar extends StatelessWidget implements PreferredSizeWidget {
|
|||
centerTitle: true,
|
||||
backgroundColor: Colors.transparent,
|
||||
elevation: 0.0,
|
||||
leading: IconButton(
|
||||
leading: drawerShow ? IconButton(
|
||||
icon: Icon(
|
||||
Icons.menu,
|
||||
color: blackColor,
|
||||
|
|
@ -55,7 +57,7 @@ class ProductsAppBar extends StatelessWidget implements PreferredSizeWidget {
|
|||
.currentState!
|
||||
.openDrawer();
|
||||
},
|
||||
),
|
||||
) : null ,
|
||||
actions: actions,
|
||||
),
|
||||
if (child != null && childHeight! > 0) child!,
|
||||
|
|
|
|||
|
|
@ -2,10 +2,12 @@ import 'package:flutter/cupertino.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_redux/flutter_redux.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:satu/core/entity/Goods.dart';
|
||||
import 'package:satu/core/models/flow/product_dao.dart';
|
||||
import 'package:satu/core/redux/actions/sell_actions.dart';
|
||||
import 'package:satu/core/redux/state/sell_state.dart';
|
||||
import 'package:satu/core/redux/store.dart';
|
||||
import 'package:satu/core/services/dictionary_service.dart';
|
||||
import 'package:satu/core/services/navigator_service.dart';
|
||||
import 'package:satu/core/utils/locator.dart';
|
||||
import 'package:satu/routes/route_names.dart';
|
||||
|
|
@ -27,6 +29,7 @@ class SellView extends StatelessWidget {
|
|||
builder: (_, state) {
|
||||
return Scaffold(
|
||||
appBar: ProductsAppBar(
|
||||
drawerShow: true,
|
||||
title: 'Продажа',
|
||||
child: ProductHeaderBar(
|
||||
count: state.items!.length,
|
||||
|
|
@ -103,7 +106,15 @@ class SellView extends StatelessWidget {
|
|||
verticalSpaceMedium,
|
||||
FloatingActionButton(
|
||||
elevation: 2,
|
||||
onPressed: () => locator<NavigatorService>().push(AddByBarcodeViewRoute),
|
||||
onPressed: () async {
|
||||
String? result = await locator<NavigatorService>().push(AddByBarcodeViewRoute);
|
||||
if(result !=null) {
|
||||
List<Good> goods = await locator<DictionaryService>().getGoodsByEan(result);
|
||||
if(goods.isNotEmpty) {
|
||||
Redux.store?.dispatch(addSellItem( good: goods.first));
|
||||
}
|
||||
}
|
||||
},
|
||||
child: Icon(Icons.qr_code_rounded, size: 35.sp, color: whiteColor),
|
||||
),
|
||||
],
|
||||
|
|
|
|||
|
|
@ -0,0 +1,179 @@
|
|||
import 'package:ai_barcode/ai_barcode.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
|
||||
late String _label;
|
||||
late Function(String result) _resultCallback;
|
||||
|
||||
///
|
||||
/// AppBarcodeScannerWidget
|
||||
class AppBarcodeScannerWidget extends StatefulWidget {
|
||||
///
|
||||
///
|
||||
AppBarcodeScannerWidget.defaultStyle({
|
||||
Function(String result)? resultCallback,
|
||||
String label = 'Заголовок',
|
||||
}) {
|
||||
_resultCallback = resultCallback ?? (String result) {};
|
||||
_label = label;
|
||||
}
|
||||
|
||||
@override
|
||||
_AppBarcodeState createState() => _AppBarcodeState();
|
||||
}
|
||||
|
||||
class _AppBarcodeState extends State<AppBarcodeScannerWidget> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return _BarcodePermissionWidget();
|
||||
}
|
||||
}
|
||||
|
||||
class _BarcodePermissionWidget extends StatefulWidget {
|
||||
@override
|
||||
State<StatefulWidget> createState() {
|
||||
return _BarcodePermissionWidgetState();
|
||||
}
|
||||
}
|
||||
|
||||
class _BarcodePermissionWidgetState extends State<_BarcodePermissionWidget> {
|
||||
bool _isGranted = false;
|
||||
|
||||
bool _useCameraScan = true;
|
||||
|
||||
String _inputValue = "";
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
void _requestMobilePermission() async {
|
||||
if (await Permission.camera.request().isGranted) {
|
||||
setState(() {
|
||||
_isGranted = true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
TargetPlatform platform = Theme.of(context).platform;
|
||||
if (!kIsWeb) {
|
||||
if (platform == TargetPlatform.android ||
|
||||
platform == TargetPlatform.iOS) {
|
||||
_requestMobilePermission();
|
||||
} else {
|
||||
setState(() {
|
||||
_isGranted = true;
|
||||
});
|
||||
}
|
||||
} else {
|
||||
setState(() {
|
||||
_isGranted = true;
|
||||
});
|
||||
}
|
||||
|
||||
return Column(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: _isGranted
|
||||
? _BarcodeScannerWidget()
|
||||
: Center(
|
||||
child: OutlinedButton(
|
||||
onPressed: () {
|
||||
_requestMobilePermission();
|
||||
},
|
||||
child: Text("Запроса на разрешения"),
|
||||
),
|
||||
),
|
||||
),
|
||||
// _useCameraScan
|
||||
// ? OutlinedButton(
|
||||
// onPressed: () {
|
||||
// setState(() {
|
||||
// _useCameraScan = false;
|
||||
// });
|
||||
// },
|
||||
// child: Text("Использовать камеру $_label"),
|
||||
// )
|
||||
// : Row(
|
||||
// children: [
|
||||
// OutlineButton(
|
||||
// onPressed: () {
|
||||
// setState(() {
|
||||
// _useCameraScan = true;
|
||||
// });
|
||||
// },
|
||||
// child: Text("_useCameraScan = true $_label"),
|
||||
// ),
|
||||
// OutlineButton(
|
||||
// onPressed: () {
|
||||
// _resultCallback(_inputValue);
|
||||
// },
|
||||
// child: Text("_resultCallback"),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///ScannerWidget
|
||||
class _BarcodeScannerWidget extends StatefulWidget {
|
||||
@override
|
||||
State<StatefulWidget> createState() {
|
||||
return _AppBarcodeScannerWidgetState();
|
||||
}
|
||||
}
|
||||
|
||||
class _AppBarcodeScannerWidgetState extends State<_BarcodeScannerWidget> {
|
||||
late ScannerController _scannerController;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
_scannerController = ScannerController(scannerResult: (result) {
|
||||
_resultCallback(result);
|
||||
}, scannerViewCreated: () {
|
||||
TargetPlatform platform = Theme.of(context).platform;
|
||||
if (TargetPlatform.iOS == platform) {
|
||||
Future.delayed(Duration(seconds: 2), () {
|
||||
_scannerController.startCamera();
|
||||
_scannerController.startCameraPreview();
|
||||
});
|
||||
} else {
|
||||
_scannerController.startCamera();
|
||||
_scannerController.startCameraPreview();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
_scannerController.stopCameraPreview();
|
||||
_scannerController.stopCamera();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: _getScanWidgetByPlatform(),
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _getScanWidgetByPlatform() {
|
||||
return PlatformAiBarcodeScannerWidget(
|
||||
platformScannerController: _scannerController,
|
||||
);
|
||||
}
|
||||
}
|
||||
70
pubspec.lock
70
pubspec.lock
|
|
@ -1,6 +1,27 @@
|
|||
# Generated by pub
|
||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||
packages:
|
||||
ai_barcode:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: ai_barcode
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.0.1"
|
||||
ai_barcode_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: ai_barcode_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.0.0"
|
||||
ai_barcode_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: ai_barcode_web
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.0.0"
|
||||
async:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -64,6 +85,13 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.0.1"
|
||||
csslib:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: csslib
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.17.0"
|
||||
cupertino_icons:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
@ -149,6 +177,13 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "7.1.3"
|
||||
html:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: html
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.15.0"
|
||||
http:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
@ -282,6 +317,20 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.11.1"
|
||||
permission_handler:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: permission_handler
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "8.1.2"
|
||||
permission_handler_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.6.0"
|
||||
platform:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -476,6 +525,27 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.0"
|
||||
universal_html:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: universal_html
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.8"
|
||||
universal_io:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: universal_io
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.4"
|
||||
universal_platform:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: universal_platform
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.0+1"
|
||||
url_launcher:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
|
|||
|
|
@ -54,6 +54,8 @@ dependencies:
|
|||
implicitly_animated_reorderable_list: ^0.4.0
|
||||
uuid: ^3.0.4
|
||||
charset_converter: ^2.0.0
|
||||
ai_barcode: ^3.0.1
|
||||
permission_handler: ^8.1.2
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
|
|
|
|||
Loading…
Reference in New Issue