feat: inventory and inout info develop
This commit is contained in:
parent
fc0187acf0
commit
cf51cd8ada
|
@ -1,99 +0,0 @@
|
|||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:sk_base_mobile/constants/global_url.dart';
|
||||
import 'package:sk_base_mobile/models/base_response.dart';
|
||||
import 'package:sk_base_mobile/models/dict_type.model.dart';
|
||||
import 'package:sk_base_mobile/services/dio.service.dart';
|
||||
import '../constants/constants.dart';
|
||||
|
||||
// 登录
|
||||
Future<Response> login(String username, String password) {
|
||||
return DioService.dio.post(
|
||||
Urls.login,
|
||||
data: {'username': username, 'password': password},
|
||||
);
|
||||
}
|
||||
|
||||
// 获取个人信息
|
||||
Future<Response> getUserInfo() {
|
||||
return DioService.dio.get(
|
||||
Urls.getUserInfo,
|
||||
);
|
||||
}
|
||||
|
||||
// 分页获取项目列表
|
||||
Future<Response<PaginationData>> getProjects(Map params) {
|
||||
return DioService.dio.get<PaginationData>(Urls.getProjects,
|
||||
queryParameters: {'page': 1, 'pageSize': 10, ...params});
|
||||
}
|
||||
|
||||
// 分页获取产品列表
|
||||
Future<Response<PaginationData>> getProducts(Map params) {
|
||||
return DioService.dio.get<PaginationData>(Urls.getProducts,
|
||||
queryParameters: {'page': 1, 'pageSize': 10, ...params});
|
||||
}
|
||||
|
||||
// 分页获取原材料出入库列表
|
||||
Future<Response<PaginationData>> getInventoryInout(Map params) {
|
||||
return DioService.dio.get<PaginationData>(Urls.inventoryInout,
|
||||
queryParameters: {'page': 1, 'pageSize': 10, ...(params)});
|
||||
}
|
||||
|
||||
// 创建出入库记录
|
||||
Future<Response> createInventoryInout(Map params) {
|
||||
return DioService.dio.post(Urls.inventoryInout, data: params);
|
||||
}
|
||||
|
||||
// 更新出入库记录
|
||||
Future<Response> updateInventoryInout(int id, Map params) {
|
||||
return DioService.dio.put('${Urls.inventoryInout}/$id', data: params);
|
||||
}
|
||||
|
||||
// 分页获取库存列表
|
||||
Future<Response<PaginationData>> getInventory(Map params) {
|
||||
return DioService.dio.get<PaginationData>(Urls.inventory,
|
||||
queryParameters: {'page': 1, 'pageSize': 10, ...(params)});
|
||||
}
|
||||
|
||||
// 一次性获取所有的字典类型(不分页)
|
||||
Future<Response> getDictTypeAll(Map params) {
|
||||
return DioService.dio.post(Urls.getDictType, data: params);
|
||||
}
|
||||
|
||||
Future<Response> logout() {
|
||||
return DioService.dio.post(
|
||||
Urls.logout,
|
||||
);
|
||||
}
|
||||
|
||||
Future<Response> deleteAccount() {
|
||||
return DioService.dio.post(
|
||||
Urls.deleteAccount,
|
||||
);
|
||||
}
|
||||
|
||||
Future<Response> getAppConfig() {
|
||||
Map<String, dynamic> query = {'ver': 0};
|
||||
return DioService.dio.get(Urls.getAppConfig, queryParameters: query);
|
||||
}
|
||||
|
||||
Future<Response> saveUserInfo(Map<String, dynamic> data) {
|
||||
return DioService.dio.post(Urls.saveUserInfo, data: data);
|
||||
}
|
||||
|
||||
Future<Response> uploadImg(File file,
|
||||
{String? bussinessModule, String? bussinessRecordId}) async {
|
||||
String fileName = file.path.split('/').last;
|
||||
final filePath = await MultipartFile.fromFile(file.path, filename: fileName);
|
||||
final formData = FormData.fromMap({
|
||||
'bussinessRecordId': bussinessRecordId,
|
||||
'bussinessModule': bussinessModule,
|
||||
'file': filePath,
|
||||
});
|
||||
return DioService.dio.post(Urls.uploadAttachemnt, data: formData);
|
||||
}
|
||||
|
||||
Future<Response> updateAvatar(String filename) {
|
||||
return DioService.dio.post(Urls.updateAvatar, data: {'avatarPath': filename});
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:sk_base_mobile/constants/global_url.dart';
|
||||
import 'package:sk_base_mobile/models/base_response.dart';
|
||||
import 'package:sk_base_mobile/models/dict_type.model.dart';
|
||||
import 'package:sk_base_mobile/services/dio.service.dart';
|
||||
import '../constants/constants.dart';
|
||||
|
||||
class Api {
|
||||
// 登录
|
||||
static Future<Response> login(String username, String password) {
|
||||
return DioService.dio.post(
|
||||
Urls.login,
|
||||
data: {'username': username, 'password': password},
|
||||
);
|
||||
}
|
||||
|
||||
// 获取个人信息
|
||||
static Future<Response> getUserInfo() {
|
||||
return DioService.dio.get(
|
||||
Urls.getUserInfo,
|
||||
);
|
||||
}
|
||||
|
||||
// 分页获取项目列表
|
||||
static Future<Response<PaginationData>> getProjects(Map params) {
|
||||
return DioService.dio.get<PaginationData>(Urls.projects,
|
||||
queryParameters: {'page': 1, 'pageSize': 10, ...params});
|
||||
}
|
||||
|
||||
// 分页获取产品列表
|
||||
static Future<Response<PaginationData>> getProducts(Map params) {
|
||||
return DioService.dio.get<PaginationData>(Urls.products,
|
||||
queryParameters: {'page': 1, 'pageSize': 10, ...params});
|
||||
}
|
||||
|
||||
// 分页获取原材料出入库列表
|
||||
static Future<Response<PaginationData>> getInventoryInout(Map params) {
|
||||
return DioService.dio.get<PaginationData>(Urls.inventoryInout,
|
||||
queryParameters: {'page': 1, 'pageSize': 10, ...(params)});
|
||||
}
|
||||
|
||||
// 获取原材料出入库详情
|
||||
static Future<Response> getInventoryInOutInfo(int id) {
|
||||
return DioService.dio.get(
|
||||
'${Urls.inventoryInout}/$id',
|
||||
);
|
||||
}
|
||||
|
||||
// 创建出入库记录
|
||||
static Future<Response> createInventoryInout(Map params) {
|
||||
return DioService.dio.post(Urls.inventoryInout, data: params);
|
||||
}
|
||||
|
||||
// 更新出入库记录
|
||||
static Future<Response> updateInventoryInout(int id, Map params) {
|
||||
return DioService.dio.put('${Urls.inventoryInout}/$id', data: params);
|
||||
}
|
||||
|
||||
// 分页获取库存列表
|
||||
static Future<Response<PaginationData>> getInventory(Map params) {
|
||||
return DioService.dio.get<PaginationData>(Urls.inventory,
|
||||
queryParameters: {'page': 1, 'pageSize': 10, ...(params)});
|
||||
}
|
||||
|
||||
// 一次性获取所有的字典类型(不分页)
|
||||
static Future<Response> getDictTypeAll(Map params) {
|
||||
return DioService.dio.post(Urls.getDictType, data: params);
|
||||
}
|
||||
|
||||
static Future<Response> logout() {
|
||||
return DioService.dio.post(
|
||||
Urls.logout,
|
||||
);
|
||||
}
|
||||
|
||||
static Future<Response> deleteAccount() {
|
||||
return DioService.dio.post(
|
||||
Urls.deleteAccount,
|
||||
);
|
||||
}
|
||||
|
||||
static Future<Response> getAppConfig() {
|
||||
Map<String, dynamic> query = {'ver': 0};
|
||||
return DioService.dio.get(Urls.getAppConfig, queryParameters: query);
|
||||
}
|
||||
|
||||
static Future<Response> saveUserInfo(Map<String, dynamic> data) {
|
||||
return DioService.dio.post(Urls.saveUserInfo, data: data);
|
||||
}
|
||||
|
||||
static Future<Response> uploadImg(File file,
|
||||
{String? bussinessModule, String? bussinessRecordId}) async {
|
||||
String fileName = file.path.split('/').last;
|
||||
final filePath =
|
||||
await MultipartFile.fromFile(file.path, filename: fileName);
|
||||
final formData = FormData.fromMap({
|
||||
'bussinessRecordId': bussinessRecordId,
|
||||
'bussinessModule': bussinessModule,
|
||||
'file': filePath,
|
||||
});
|
||||
return DioService.dio.post(Urls.uploadAttachemnt, data: formData);
|
||||
}
|
||||
|
||||
static Future<Response> updateAvatar(String filename) {
|
||||
return DioService.dio
|
||||
.post(Urls.updateAvatar, data: {'avatarPath': filename});
|
||||
}
|
||||
}
|
|
@ -6,8 +6,8 @@ class Urls {
|
|||
static String deleteAccount = 'user/deleteAccount';
|
||||
static String saveUserInfo = 'user/saveUserInfo';
|
||||
static String getUserInfo = 'account/profile';
|
||||
static String getProjects = 'project';
|
||||
static String getProducts = 'product';
|
||||
static String projects = 'project';
|
||||
static String products = 'product';
|
||||
static String inventoryInout = 'materials-in-out';
|
||||
static String inventory = 'materials-inventory';
|
||||
static String updateAvatar = 'user/updateAvatar';
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import 'package:sk_base_mobile/constants/enum.dart';
|
||||
import 'package:sk_base_mobile/models/file.model.dart';
|
||||
import 'package:sk_base_mobile/models/index.dart';
|
||||
import 'package:sk_base_mobile/models/inventory.model.dart';
|
||||
import 'package:sk_base_mobile/models/product.model.dart';
|
||||
import 'package:sk_base_mobile/models/project.model.dart';
|
||||
|
||||
|
@ -24,6 +25,7 @@ class InventoryInOutModel {
|
|||
required this.files,
|
||||
required this.project,
|
||||
required this.product,
|
||||
this.inventory,
|
||||
});
|
||||
|
||||
final int? id;
|
||||
|
@ -41,10 +43,10 @@ class InventoryInOutModel {
|
|||
final String? remark;
|
||||
final int? projectId;
|
||||
final int? isDelete;
|
||||
final List<FileModel?> files;
|
||||
final List<FileModel> files;
|
||||
final ProjectModel? project;
|
||||
final ProductModel? product;
|
||||
|
||||
final InventoryModel? inventory;
|
||||
factory InventoryInOutModel.fromJson(Map<String, dynamic> json) {
|
||||
return InventoryInOutModel(
|
||||
id: json["id"],
|
||||
|
@ -72,6 +74,9 @@ class InventoryInOutModel {
|
|||
product: json["product"] == null
|
||||
? null
|
||||
: ProductModel.fromJson(json["product"]),
|
||||
inventory: json['inventory'] == null
|
||||
? null
|
||||
: InventoryModel.fromJson(json["inventory"]),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -94,5 +99,6 @@ class InventoryInOutModel {
|
|||
"files": files.map((x) => x).toList(),
|
||||
"project": project?.toJson(),
|
||||
"product": product?.toJson(),
|
||||
"inventory": inventory?.toJson(),
|
||||
};
|
||||
}
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:sk_base_mobile/screens/new_inventory_inout/components/inventory_search.dart';
|
||||
|
||||
class InventoryPage extends StatelessWidget {
|
||||
const InventoryPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('库存管理')),
|
||||
body: InventorySearch(),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -16,7 +16,12 @@ class InventoryInoutCard extends StatelessWidget {
|
|||
final controller = Get.find<InventoryInoutController>();
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
return InkWell(
|
||||
onTap: () {
|
||||
controller
|
||||
.showInventoryInoutInfoDialog(controller.list[ind][index].id!);
|
||||
},
|
||||
child: Container(
|
||||
margin: EdgeInsets.symmetric(
|
||||
vertical: ScreenAdaper.height(15),
|
||||
horizontal: ScreenAdaper.width(15)),
|
||||
|
@ -149,6 +154,7 @@ class InventoryInoutCard extends StatelessWidget {
|
|||
// ),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -224,9 +230,8 @@ class InventoryInoutCard extends StatelessWidget {
|
|||
child: FadeInCacheImage(
|
||||
width: ScreenAdaper.width(100),
|
||||
height: ScreenAdaper.width(100),
|
||||
url: controller.list[ind][index].product?.files.isNotEmpty ??
|
||||
false
|
||||
? '${GloablConfig.OSS_URL}${controller.list[ind][index].product?.files[0].path}'
|
||||
url: controller.list[ind][index].files.isNotEmpty
|
||||
? '${GloablConfig.OSS_URL}${controller.list[ind][index].files[0]?.path}'
|
||||
: ''),
|
||||
));
|
||||
}
|
||||
|
|
|
@ -0,0 +1,190 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:loading_animation_widget/loading_animation_widget.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/constants/bg_color.dart';
|
||||
import 'package:sk_base_mobile/constants/constants.dart';
|
||||
import 'package:sk_base_mobile/models/index.dart';
|
||||
import 'package:sk_base_mobile/models/inventory.model.dart';
|
||||
import 'package:sk_base_mobile/util/date.util.dart';
|
||||
import 'package:sk_base_mobile/util/screen_adaper_util.dart';
|
||||
import 'package:sk_base_mobile/widgets/empty.dart';
|
||||
import 'package:sk_base_mobile/widgets/fade_in_cache_image.dart';
|
||||
import 'package:sk_base_mobile/widgets/image_preview.dart';
|
||||
import 'package:sk_base_mobile/widgets/loading_indicator.dart';
|
||||
|
||||
class InventoryInoutInfo extends StatelessWidget {
|
||||
late int inventoryInoutId;
|
||||
late InventoryInouInfoController controller;
|
||||
InventoryInoutInfo({Key? key, required this.inventoryInoutId})
|
||||
: controller = Get.put(InventoryInouInfoController(inventoryInoutId)),
|
||||
super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SizedBox(
|
||||
child: Column(children: [
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: ScreenAdaper.width(10),
|
||||
vertical: ScreenAdaper.height(15)),
|
||||
decoration: const BoxDecoration(color: AppTheme.primaryColor),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
'出入库详情',
|
||||
style: TextStyle(
|
||||
fontSize: ScreenAdaper.sp(25), color: AppTheme.nearlyWhite),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Obx(() => controller.inventoryInoutInfo.value == null
|
||||
? const Center(child: LoadingIndicator(common: true))
|
||||
: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
buildListItem(
|
||||
leading: '出入库类型',
|
||||
trailing: InventoryInOrOutEnum.In ==
|
||||
controller.inventoryInoutInfo.value?.inOrOut
|
||||
? '入库'
|
||||
: '出库'),
|
||||
customDivider(),
|
||||
if (InventoryInOrOutEnum.In ==
|
||||
controller.inventoryInoutInfo.value?.inOrOut) ...[
|
||||
buildListItem(
|
||||
leading: '存放位置',
|
||||
trailing: controller
|
||||
.inventoryInoutInfo.value?.inventory?.position),
|
||||
customDivider(),
|
||||
],
|
||||
buildListItem(
|
||||
leading: '出入库时间',
|
||||
trailing: DateUtil.format(
|
||||
controller.inventoryInoutInfo.value!.time!)),
|
||||
customDivider(),
|
||||
buildListItem(
|
||||
leading: '所属公司',
|
||||
trailing: controller.inventoryInoutInfo.value?.product
|
||||
?.company?.name),
|
||||
customDivider(),
|
||||
buildListItem(
|
||||
leading: '产品名称',
|
||||
trailing: controller
|
||||
.inventoryInoutInfo.value?.product?.name),
|
||||
customDivider(),
|
||||
buildListItem(
|
||||
leading: '产品规格',
|
||||
trailing: controller.inventoryInoutInfo.value?.product
|
||||
?.productSpecification),
|
||||
customDivider(),
|
||||
buildListItem(
|
||||
leading: '数量',
|
||||
trailing:
|
||||
'${controller.inventoryInoutInfo.value?.quantity}${controller.inventoryInoutInfo.value?.product?.unit?.label ?? ''}'),
|
||||
customDivider(),
|
||||
buildListItem(
|
||||
leading: '单价',
|
||||
trailing:
|
||||
'¥${double.parse('${controller.inventoryInoutInfo.value?.unitPrice ?? 0}')}'),
|
||||
customDivider(),
|
||||
buildListItem(
|
||||
leading: '操作人',
|
||||
trailing: controller.inventoryInoutInfo.value?.agent),
|
||||
customDivider(),
|
||||
buildListItem(
|
||||
leading: '备注',
|
||||
trailing:
|
||||
controller.inventoryInoutInfo.value?.remark),
|
||||
customDivider(),
|
||||
buildListItem(
|
||||
leading: '照片',
|
||||
),
|
||||
buildAttachmentsPreview()
|
||||
],
|
||||
))))
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildAttachmentsPreview() {
|
||||
return Container(
|
||||
padding: EdgeInsets.symmetric(vertical: ScreenAdaper.height(20)),
|
||||
child: Wrap(
|
||||
spacing: ScreenAdaper.width(10),
|
||||
runSpacing: ScreenAdaper.height(10),
|
||||
children: (controller.inventoryInoutInfo.value?.files ?? [])
|
||||
.map((e) => buildImage(e.path))
|
||||
.toList(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildImage(String? path) {
|
||||
return path == null
|
||||
? const SizedBox()
|
||||
: InkWell(
|
||||
onTap: () => {
|
||||
if (controller.inventoryInoutInfo.value!.files.isNotEmpty)
|
||||
{
|
||||
Get.dialog(ImagePreivew(
|
||||
galleryItems: controller.inventoryInoutInfo.value!.files,
|
||||
initialIndex: controller.inventoryInoutInfo.value!.files
|
||||
.indexWhere((element) => element.path == path)))
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
margin: EdgeInsets.only(
|
||||
right: ScreenAdaper.width(defaultPadding) / 2),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(ScreenAdaper.sp(15)),
|
||||
child: FadeInCacheImage(
|
||||
width: ScreenAdaper.width(300),
|
||||
height: ScreenAdaper.width(300),
|
||||
url: '${GloablConfig.OSS_URL}$path'),
|
||||
)),
|
||||
);
|
||||
}
|
||||
|
||||
Widget customDivider() {
|
||||
return Divider(
|
||||
height: ScreenAdaper.height(1),
|
||||
color: AppTheme.dividerColor,
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildListItem({String? leading, dynamic trailing}) {
|
||||
return ListTile(
|
||||
leading: Text(
|
||||
'${leading ?? ''}: ',
|
||||
style: TextStyle(fontSize: ScreenAdaper.sp(25)),
|
||||
),
|
||||
trailing: Text('${trailing ?? ''}',
|
||||
style: TextStyle(fontSize: ScreenAdaper.sp(25))));
|
||||
}
|
||||
}
|
||||
|
||||
class InventoryInouInfoController extends GetxController {
|
||||
final inventoryInoutInfo = Rx<InventoryInOutModel?>(null);
|
||||
int inventoryInoutId;
|
||||
InventoryInouInfoController(this.inventoryInoutId);
|
||||
|
||||
@override
|
||||
onReady() {
|
||||
getData();
|
||||
}
|
||||
|
||||
Future<void> getData() async {
|
||||
printInfo(info: '$inventoryInoutId');
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
final res = await Api.getInventoryInOutInfo(inventoryInoutId);
|
||||
if (res.data != null) {
|
||||
inventoryInoutInfo.value = InventoryInOutModel.fromJson(res.data);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,14 +1,15 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:sk_base_mobile/apis/index.dart';
|
||||
import 'package:sk_base_mobile/app_theme.dart';
|
||||
import 'package:sk_base_mobile/constants/enum.dart';
|
||||
import 'package:sk_base_mobile/db_helper/dbHelper.dart';
|
||||
import 'package:sk_base_mobile/screens/inventory_inout/components/inventory_inout_info.dart';
|
||||
import 'package:sk_base_mobile/screens/new_inventory_inout/new_inventory_inout.dart';
|
||||
import 'package:sk_base_mobile/util/date.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/apis/api.dart' as Api;
|
||||
import '../../models/index.dart';
|
||||
import 'components/responsive.dart';
|
||||
|
||||
|
@ -243,6 +244,14 @@ class InventoryInoutController extends GetxController {
|
|||
);
|
||||
}
|
||||
|
||||
Future showInventoryInoutInfoDialog(int id) async {
|
||||
ModalUtil.showGeneralDialog(
|
||||
width: ScreenAdaper.width(Get.width - 100),
|
||||
height: ScreenAdaper.height(Get.height - 100),
|
||||
content: InventoryInoutInfo(inventoryInoutId: id))
|
||||
.then((value) => {Get.delete<InventoryInouInfoController>()});
|
||||
}
|
||||
|
||||
Future<List<InventoryInOutModel>> getInoutHistory() async {
|
||||
final res = await Api.getInventoryInout({});
|
||||
printInfo(info: res.toString());
|
||||
|
|
|
@ -21,7 +21,9 @@ class LandingPage extends StatelessWidget {
|
|||
child: Obx(() => Scaffold(
|
||||
floatingActionButtonLocation:
|
||||
FloatingActionButtonLocation.centerDocked,
|
||||
floatingActionButton: controller.currentIndex.value == 0
|
||||
floatingActionButton: [0].indexWhere(
|
||||
(item) => item == controller.currentIndex.value) >
|
||||
-1
|
||||
? FloatingCreateButton()
|
||||
: null,
|
||||
bottomNavigationBar: BottomNavBar(),
|
||||
|
|
|
@ -2,7 +2,7 @@ import 'package:flutter/cupertino.dart';
|
|||
import 'package:get/get.dart';
|
||||
import 'package:sk_base_mobile/models/user_info.model.dart';
|
||||
import 'package:sk_base_mobile/store/auth.store.dart';
|
||||
import 'package:sk_base_mobile/apis/api.dart' as Api;
|
||||
import 'package:sk_base_mobile/apis/index.dart';
|
||||
|
||||
class UserInfoController extends GetxController {
|
||||
final nickNameController = TextEditingController(text: '');
|
||||
|
|
|
@ -3,13 +3,13 @@ import 'dart:async';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:pull_to_refresh/pull_to_refresh.dart';
|
||||
import 'package:sk_base_mobile/apis/index.dart';
|
||||
import 'package:sk_base_mobile/app_theme.dart';
|
||||
import 'package:sk_base_mobile/constants/bg_color.dart';
|
||||
import 'package:sk_base_mobile/models/index.dart';
|
||||
import 'package:sk_base_mobile/models/inventory.model.dart';
|
||||
import 'package:sk_base_mobile/util/debouncer.dart';
|
||||
import 'package:sk_base_mobile/util/screen_adaper_util.dart';
|
||||
import 'package:sk_base_mobile/apis/api.dart' as Api;
|
||||
|
||||
class InventorySearch extends StatelessWidget {
|
||||
Function(InventoryModel)? onInventorySelected;
|
||||
|
|
|
@ -3,12 +3,12 @@ import 'dart:async';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:pull_to_refresh/pull_to_refresh.dart';
|
||||
import 'package:sk_base_mobile/apis/index.dart';
|
||||
import 'package:sk_base_mobile/app_theme.dart';
|
||||
import 'package:sk_base_mobile/constants/bg_color.dart';
|
||||
import 'package:sk_base_mobile/models/index.dart';
|
||||
import 'package:sk_base_mobile/util/debouncer.dart';
|
||||
import 'package:sk_base_mobile/util/screen_adaper_util.dart';
|
||||
import 'package:sk_base_mobile/apis/api.dart' as Api;
|
||||
|
||||
class ProductSearch extends StatelessWidget {
|
||||
Function(ProductModel)? onProductSelected;
|
||||
|
|
|
@ -229,7 +229,8 @@ class NewInventoryInout extends StatelessWidget {
|
|||
controller.payload['productId'] = inventory.product?.id;
|
||||
},
|
||||
),
|
||||
width: Get.width - ScreenAdaper.width(50));
|
||||
width: Get.width - ScreenAdaper.width(50))
|
||||
.then((value) => Get.delete<InventorySearchController>());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -4,11 +4,11 @@ import 'package:decimal/decimal.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
import 'package:sk_base_mobile/apis/index.dart';
|
||||
import 'package:sk_base_mobile/constants/enum.dart';
|
||||
import 'package:sk_base_mobile/db_helper/dbHelper.dart';
|
||||
import 'package:sk_base_mobile/models/index.dart';
|
||||
import 'package:sk_base_mobile/screens/inventory_inout/inventory_inout_controller.dart';
|
||||
import 'package:sk_base_mobile/apis/api.dart' as Api;
|
||||
import 'package:sk_base_mobile/util/date.util.dart';
|
||||
import 'package:sk_base_mobile/util/logger_util.dart';
|
||||
import 'package:sk_base_mobile/util/media_util.dart';
|
||||
|
|
|
@ -7,8 +7,9 @@ import 'package:package_info/package_info.dart';
|
|||
import 'package:sk_base_mobile/app_theme.dart';
|
||||
import 'package:sk_base_mobile/models/app_bottom_nav_item.dart';
|
||||
import 'package:sk_base_mobile/models/app_config.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/apis/api.dart' as Api;
|
||||
import 'package:sk_base_mobile/apis/index.dart';
|
||||
import 'package:sk_base_mobile/screens/workbench/workbench.dart';
|
||||
import 'package:sk_base_mobile/services/service.dart';
|
||||
import 'package:sk_base_mobile/store/auth.store.dart';
|
||||
|
@ -36,7 +37,7 @@ class AppInfoService extends GetxService {
|
|||
icon: Icons.inventory_outlined,
|
||||
activeIcon: Icons.inventory_rounded,
|
||||
label: '库存',
|
||||
page: InvenotryInoutPage()),
|
||||
page: InventoryPage()),
|
||||
AppBottomNavItem(
|
||||
icon: Icons.widgets_outlined,
|
||||
activeIcon: Icons.widgets_rounded,
|
||||
|
|
|
@ -16,7 +16,7 @@ class DioService extends Get.GetxService {
|
|||
static late Dio _dio;
|
||||
List<String> whiteList = [Urls.login];
|
||||
BaseOptions dioBaseOptions = BaseOptions(
|
||||
connectTimeout: const Duration(seconds: 5),
|
||||
connectTimeout: const Duration(seconds: 20),
|
||||
baseUrl: '${GloablConfig.BASE_URL}',
|
||||
followRedirects: true);
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ import 'dart:convert';
|
|||
|
||||
import 'package:dio/dio.dart' as Dio;
|
||||
import 'package:get/get.dart';
|
||||
import 'package:sk_base_mobile/apis/api.dart' as Api;
|
||||
import 'package:sk_base_mobile/apis/index.dart';
|
||||
import 'package:sk_base_mobile/util/logger_util.dart';
|
||||
import 'package:sk_base_mobile/widgets/tap_to_dismiss_keyboard.dart';
|
||||
import 'package:sk_base_mobile/models/auth.dart';
|
||||
|
@ -53,7 +53,6 @@ class AuthStore extends GetxController {
|
|||
}
|
||||
|
||||
Future<void> logout({bool force = false}) async {
|
||||
LoadingUtil.to.show(status: 'Logout...');
|
||||
await StorageService.to.remove(CacheKeys.token, isWithUser: false);
|
||||
await StorageService.to.remove(CacheKeys.userInfo, isWithUser: false);
|
||||
try {
|
||||
|
|
|
@ -3,7 +3,7 @@ import 'package:get/get_state_manager/get_state_manager.dart';
|
|||
import 'package:sk_base_mobile/constants/dict_enum.dart';
|
||||
import 'package:sk_base_mobile/models/dict_item.model.dart';
|
||||
import 'package:sk_base_mobile/models/dict_type.model.dart';
|
||||
import 'package:sk_base_mobile/apis/api.dart' as Api;
|
||||
import 'package:sk_base_mobile/apis/index.dart';
|
||||
import 'package:sk_base_mobile/util/logger_util.dart';
|
||||
|
||||
const needCachedKey = [
|
||||
|
|
|
@ -4,9 +4,8 @@ import 'package:loading_animation_widget/loading_animation_widget.dart';
|
|||
import 'package:sk_base_mobile/app_theme.dart';
|
||||
import 'package:sk_base_mobile/util/screen_adaper_util.dart';
|
||||
|
||||
class LoadingUtil extends GetxController {
|
||||
class LoadingUtil extends GetxService {
|
||||
static LoadingUtil get to => Get.find();
|
||||
|
||||
OverlayEntry? _loadingOverlay;
|
||||
|
||||
Future<LoadingUtil> init() async {
|
||||
|
@ -53,9 +52,10 @@ class LoadingUtil extends GetxController {
|
|||
));
|
||||
},
|
||||
);
|
||||
|
||||
if (Get.overlayContext != null) {
|
||||
Overlay.of(Get.overlayContext!).insert(_loadingOverlay!);
|
||||
}
|
||||
}
|
||||
|
||||
hideLoading() {
|
||||
_loadingOverlay?.remove();
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import 'dart:io';
|
||||
import 'package:dio/dio.dart' as Dio;
|
||||
import 'package:sk_base_mobile/apis/api.dart' as Api;
|
||||
import 'package:sk_base_mobile/apis/index.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
import 'package:sk_base_mobile/models/upload_result.model.dart';
|
||||
import 'package:sk_base_mobile/services/service.dart';
|
||||
|
@ -15,7 +15,7 @@ class MediaUtil {
|
|||
}
|
||||
AppInfoService.to.isCameraing.value = true;
|
||||
pickedFile = await ImagePicker()
|
||||
.pickImage(source: ImageSource.camera, maxWidth: maxWidth ?? 400);
|
||||
.pickImage(source: ImageSource.camera, maxWidth: maxWidth ?? 2000);
|
||||
AppInfoService.to.isCameraing.value = false;
|
||||
} catch (e) {
|
||||
AppInfoService.to.isCameraing.value = false;
|
||||
|
|
|
@ -68,7 +68,7 @@ class ModalUtil {
|
|||
);
|
||||
|
||||
static Future<void> showGeneralDialog(
|
||||
{required Widget content, double? width}) {
|
||||
{required Widget content, double? width, double? height}) {
|
||||
return Get.generalDialog(
|
||||
barrierLabel: "productPicker",
|
||||
barrierDismissible: true,
|
||||
|
@ -79,7 +79,7 @@ class ModalUtil {
|
|||
borderRadius: BorderRadius.circular(ScreenAdaper.sp(30)),
|
||||
child: Material(
|
||||
child: SizedBox(
|
||||
height: Get.height - ScreenAdaper.height(150),
|
||||
height: height ?? Get.height - ScreenAdaper.height(150),
|
||||
width: width ?? Get.width - ScreenAdaper.width(150),
|
||||
child: content,
|
||||
))));
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:photo_view/photo_view.dart';
|
||||
import 'package:photo_view/photo_view_gallery.dart';
|
||||
import 'package:sk_base_mobile/config.dart';
|
||||
import 'package:sk_base_mobile/models/file.model.dart';
|
||||
import 'package:sk_base_mobile/util/screen_adaper_util.dart';
|
||||
import 'package:sk_base_mobile/widgets/fade_in_cache_image.dart';
|
||||
import 'package:sk_base_mobile/widgets/loading_indicator.dart';
|
||||
|
||||
class ImagePreivew extends StatefulWidget {
|
||||
ImagePreivew({
|
||||
super.key,
|
||||
required this.galleryItems,
|
||||
this.backgroundDecoration,
|
||||
this.minScale,
|
||||
this.maxScale,
|
||||
this.initialIndex = 0,
|
||||
this.scrollDirection = Axis.horizontal,
|
||||
}) : pageController = PageController(initialPage: initialIndex);
|
||||
final BoxDecoration? backgroundDecoration;
|
||||
final dynamic minScale;
|
||||
final dynamic maxScale;
|
||||
final int initialIndex;
|
||||
final PageController pageController;
|
||||
final List<FileModel> galleryItems;
|
||||
final Axis scrollDirection;
|
||||
@override
|
||||
State<ImagePreivew> createState() => _ImagePreivewState();
|
||||
}
|
||||
|
||||
class _ImagePreivewState extends State<ImagePreivew> {
|
||||
late int currentIndex = widget.initialIndex;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
decoration: widget.backgroundDecoration,
|
||||
constraints: BoxConstraints.expand(
|
||||
height: MediaQuery.of(context).size.height,
|
||||
),
|
||||
child: Stack(
|
||||
alignment: Alignment.bottomRight,
|
||||
children: <Widget>[
|
||||
PhotoViewGallery.builder(
|
||||
scrollPhysics: const BouncingScrollPhysics(),
|
||||
builder: _buildItem,
|
||||
itemCount: widget.galleryItems.length,
|
||||
loadingBuilder: (_, _1) => const LoadingIndicator(common: true),
|
||||
backgroundDecoration: widget.backgroundDecoration,
|
||||
pageController: widget.pageController,
|
||||
onPageChanged: onPageChanged,
|
||||
scrollDirection: widget.scrollDirection,
|
||||
),
|
||||
Container(
|
||||
padding: const EdgeInsets.all(20.0),
|
||||
child: Text(
|
||||
"照片 ${currentIndex + 1}",
|
||||
style: TextStyle(
|
||||
decoration: TextDecoration.none,
|
||||
color: Colors.white,
|
||||
fontSize: ScreenAdaper.sp(20),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
PhotoViewGalleryPageOptions _buildItem(BuildContext context, int index) {
|
||||
final FileModel item = widget.galleryItems[index];
|
||||
return PhotoViewGalleryPageOptions(
|
||||
onTapUp: (_, _1, _2) {
|
||||
Get.back();
|
||||
},
|
||||
imageProvider: Image.network('${GloablConfig.OSS_URL}${item.path}').image,
|
||||
initialScale: PhotoViewComputedScale.contained,
|
||||
minScale: PhotoViewComputedScale.contained * (0.5 + index / 10),
|
||||
maxScale: PhotoViewComputedScale.covered * 4.1,
|
||||
heroAttributes: PhotoViewHeroAttributes(tag: '${item.id}'),
|
||||
);
|
||||
// return item.isSvg
|
||||
// ? PhotoViewGalleryPageOptions.customChild(
|
||||
// child: Container(
|
||||
// width: 300,
|
||||
// height: 300,
|
||||
// child: SvgPicture.asset(
|
||||
// item.resource,
|
||||
// height: 200.0,
|
||||
// ),
|
||||
// ),
|
||||
// childSize: const Size(300, 300),
|
||||
// initialScale: PhotoViewComputedScale.contained,
|
||||
// minScale: PhotoViewComputedScale.contained * (0.5 + index / 10),
|
||||
// maxScale: PhotoViewComputedScale.covered * 4.1,
|
||||
// heroAttributes: PhotoViewHeroAttributes(tag: item.id),
|
||||
// )
|
||||
// : PhotoViewGalleryPageOptions(
|
||||
// imageProvider: AssetImage(item.resource),
|
||||
// initialScale: PhotoViewComputedScale.contained,
|
||||
// minScale: PhotoViewComputedScale.contained * (0.5 + index / 10),
|
||||
// maxScale: PhotoViewComputedScale.covered * 4.1,
|
||||
// heroAttributes: PhotoViewHeroAttributes(tag: item.id),
|
||||
// );
|
||||
}
|
||||
|
||||
void onPageChanged(int index) {
|
||||
setState(() {
|
||||
currentIndex = index;
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,14 +1,20 @@
|
|||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:loading_animation_widget/loading_animation_widget.dart';
|
||||
import 'package:sk_base_mobile/app_theme.dart';
|
||||
import 'package:sk_base_mobile/util/screen_adaper_util.dart';
|
||||
|
||||
class LoadingIndicator extends StatelessWidget {
|
||||
final bool animating;
|
||||
const LoadingIndicator({super.key, this.animating = true});
|
||||
final bool common;
|
||||
const LoadingIndicator(
|
||||
{super.key, this.animating = true, this.common = false});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return CupertinoActivityIndicator(
|
||||
return common
|
||||
? LoadingAnimationWidget.fourRotatingDots(
|
||||
color: AppTheme.primaryColorLight, size: ScreenAdaper.sp(40))
|
||||
: CupertinoActivityIndicator(
|
||||
animating: animating,
|
||||
color: AppTheme.primaryColor,
|
||||
radius: ScreenAdaper.sp(20),
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import 'dart:io';
|
||||
import 'package:sk_base_mobile/apis/api.dart' as Api;
|
||||
import 'package:sk_base_mobile/apis/index.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
|
|
16
pubspec.lock
16
pubspec.lock
|
@ -416,6 +416,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.1.7"
|
||||
image_gallery_saver:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: image_gallery_saver
|
||||
sha256: "0aba74216a4d9b0561510cb968015d56b701ba1bd94aace26aacdd8ae5761816"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.3"
|
||||
image_picker:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -680,6 +688,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.0.2"
|
||||
photo_view:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: photo_view
|
||||
sha256: "8036802a00bae2a78fc197af8a158e3e2f7b500561ed23b4c458107685e645bb"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.14.0"
|
||||
platform:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
@ -58,6 +58,8 @@ dependencies:
|
|||
path_provider: ^2.1.2
|
||||
flutter_typeahead: ^5.2.0
|
||||
decimal: ^2.3.3
|
||||
photo_view: ^0.14.0
|
||||
image_gallery_saver: ^2.0.3
|
||||
|
||||
|
||||
dev_dependencies:
|
||||
|
|
Loading…
Reference in New Issue