feat: 增加首页抽屉的团队列表、创建团队、加入团队页面

This commit is contained in:
liyi 2025-09-11 14:13:25 +08:00
parent 9a7bd2663f
commit 90b95cb1d7
31 changed files with 892 additions and 242 deletions

View File

@ -1,8 +1,10 @@
import 'package:dio/dio.dart' as dioAlias;
import 'package:dio/dio.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:starwork_flutter/api/api_response.dart';
import 'package:starwork_flutter/base/app_logger.dart';
import 'package:starwork_flutter/common/constant/app_toast_messages.dart';
import 'package:starwork_flutter/common/constant/cache_keys.dart';
import 'package:starwork_flutter/common/constant/http_constant.dart';
import 'package:starwork_flutter/common/utils/shared_preferences_utils.dart';
@ -46,6 +48,7 @@ class BaseApiService {
dynamic data,
Map<String, dynamic>? queryParameters,
required T Function(dynamic) fromJson,
showLoading = true,
}) async {
try {
// 🔍
@ -59,7 +62,7 @@ class BaseApiService {
}
dioAlias.Response response;
EasyLoading.show(status: AppToastMessages.loading);
switch (method.toUpperCase()) {
case HttpConstant.get:
response = await dio.get(path, queryParameters: queryParameters);
@ -140,6 +143,8 @@ class BaseApiService {
debugPrint('🟥 Unexpected Error: $e');
}
return ApiResponse.error('Unexpected error: $e');
} finally {
EasyLoading.dismiss();
}
}
}

View File

@ -63,8 +63,8 @@ class AppInitialization {
]);
}
static void initEasyLoading() {
EasyLoading.instance
static void initEasyLoading() async {
await EasyLoading.instance
..displayDuration = const Duration(milliseconds: 1000)
..indicatorType = EasyLoadingIndicatorType.wanderingCubes
..loadingStyle = EasyLoadingStyle.dark

View File

@ -1,20 +0,0 @@
import 'package:get/get.dart';
import 'package:starwork_flutter/flavors.dart';
class BaseApiProvider extends GetConnect {
@override
void onInit() {
httpClient.baseUrl = F.apiHost;
//
httpClient.addRequestModifier<void>((request) {
request.headers['Authorization'] = '12345678';
return request;
});
//
httpClient.addResponseModifier((request, response) {
return response;
});
}
}

View File

@ -1,6 +1,12 @@
import 'package:get/get.dart';
class AppToastMessages {
static String loading = '加载中...'.tr;
static String notLocationPermission = '蓝牙权限被拒绝,请在应用设置页面开启蓝牙权限'.tr;
static String notBluetoothPermissions = '蓝牙权限被拒绝,请在应用设置页面开启蓝牙权限'.tr;
static String notInputTeamCode = '请先输入团队码'.tr;
static String notInputName = '请先输入您的姓名'.tr;
static String notSelectUseCase = '请先选择使用场景'.tr;
static String notInputTeamName = '请先输入团队名称'.tr;
}

View File

@ -0,0 +1,51 @@
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
class CustomAppBarWidget extends StatelessWidget implements PreferredSizeWidget {
final String title;
final List<Widget>? actions;
final VoidCallback? onBack;
final Color? backgroundColor;
const CustomAppBarWidget({
Key? key,
required this.title,
this.actions,
this.onBack,
this.backgroundColor,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return AppBar(
backgroundColor: backgroundColor ?? Colors.white,
elevation: 0,
surfaceTintColor: Colors.transparent,
shadowColor: Colors.transparent,
scrolledUnderElevation: 0,
leading: IconButton(
icon: const Icon(Icons.arrow_back_ios_new_rounded),
onPressed: onBack ?? () {
Navigator.of(context).pop();
},
),
title: Row(
children: [
Text(
title.tr,
style: TextStyle(
fontSize: 18.sp,
fontWeight: FontWeight.w500,
color: Colors.black87,
),
),
],
),
actions: actions,
);
}
@override
Size get preferredSize => const Size.fromHeight(kToolbarHeight);
}

View File

@ -0,0 +1,28 @@
import 'dart:async';
import 'dart:ui';
//
extension DebounceExtension on VoidCallback {
VoidCallback debounce([Duration? duration]) {
Timer? timer;
return () {
timer?.cancel();
timer = Timer(duration ?? const Duration(milliseconds: 200), this);
};
}
}
//
extension ThrottleExtension on VoidCallback {
VoidCallback throttle([Duration? duration]) {
bool isThrottled = false;
return () {
if (isThrottled) return;
this(); //
isThrottled = true;
Timer(duration ?? const Duration(seconds: 1000), () {
isThrottled = false;
});
};
}
}

View File

@ -16,14 +16,18 @@ import 'package:starwork_flutter/views/login/login_binding.dart';
import 'package:starwork_flutter/views/login/login_view.dart';
import 'package:starwork_flutter/views/main/main_binding.dart';
import 'package:starwork_flutter/views/main/main_view.dart';
import 'package:starwork_flutter/views/main/teamNotice/teamNoticeDetails/team_notice_details_binding.dart';
import 'package:starwork_flutter/views/main/teamNotice/teamNoticeDetails/team_notice_details_view.dart';
import 'package:starwork_flutter/views/main/teamNotice/team_notice_binding.dart';
import 'package:starwork_flutter/views/main/teamNotice/team_notice_view.dart';
import 'package:starwork_flutter/views/team/joinTeam/join_team_binding.dart';
import 'package:starwork_flutter/views/team/joinTeam/join_team_view.dart';
import 'package:starwork_flutter/views/team/teamNotice/teamNoticeDetails/team_notice_details_binding.dart';
import 'package:starwork_flutter/views/messages/messages_binding.dart';
import 'package:starwork_flutter/views/messages/messages_view.dart';
import 'package:starwork_flutter/views/mine/mine_binding.dart';
import 'package:starwork_flutter/views/mine/mine_view.dart';
import 'package:starwork_flutter/views/team/createTeam/create_team_binding.dart';
import 'package:starwork_flutter/views/team/createTeam/create_team_view.dart';
import 'package:starwork_flutter/views/team/teamNotice/teamNoticeDetails/team_notice_details_view.dart';
import 'package:starwork_flutter/views/team/teamNotice/team_notice_binding.dart';
import 'package:starwork_flutter/views/team/teamNotice/team_notice_view.dart';
import 'package:starwork_flutter/views/team/useCaseSetting/use_case_setting_binding.dart';
import 'package:starwork_flutter/views/team/useCaseSetting/use_case_setting_view.dart';
@ -92,8 +96,18 @@ class AppPages {
),
GetPage(
name: AppRoutes.teamUseCaseSetting,
page: () => UseCaseSettingView(),
page: () => UseCaseSettingView(),
binding: UseCaseSettingBinding(),
),
GetPage(
name: AppRoutes.teamCreateTeam,
page: () => CreateTeamView(),
binding: CreateTeamBinding(),
),
GetPage(
name: AppRoutes.teamJoinTeam,
page: () => JoinTeamView(),
binding: JoinTeamBinding(),
),
];
}
}

View File

@ -13,4 +13,6 @@ class AppRoutes{
static const String teamNotice = '/team/teamNotice';
static const String teamNoticeDetails = '/team/teamNoticeDetails';
static const String teamUseCaseSetting = '/team/useCaseSetting';
static const String teamCreateTeam = '/team/createTeam';
static const String teamJoinTeam = '/team/joinTeam';
}

View File

@ -39,13 +39,6 @@ class SearchDeviceController extends BaseController {
super.onInit();
//
// await _initializePermissions();
}
@override
void onReady() {
super.onReady();
//
_initializePermissions();
}
@ -77,10 +70,7 @@ class SearchDeviceController extends BaseController {
AppLogger.highlight('🎉 所有权限已就绪,准备开始搜索');
//
await _startBluetoothSearch();
//
await _startBluetoothSearch();
_startBluetoothSearch();
} catch (e, stackTrace) {
AppLogger.error('权限初始化失败', error: e, stackTrace: stackTrace);
showToast('权限初始化失败,请重试');
@ -141,7 +131,6 @@ class SearchDeviceController extends BaseController {
/// 3.
void connectingDevices(StarCloudScanResult device) async {
showLoading();
try {
var cacheStarCloudUserName = await SharedPreferencesUtils.getString(CacheKeys.starCloudUserName);
var cacheStarCloudPassword = await SharedPreferencesUtils.getString(CacheKeys.starCloudPassword);
@ -150,6 +139,7 @@ class SearchDeviceController extends BaseController {
await StarCloudSDK.instance.createCloudUser(
onError: (err) {
AppLogger.error('err:${err}');
hideLoading();
},
onSuccess: (userInfo) {
SharedPreferencesUtils.setString(CacheKeys.starCloudUserName, userInfo.username);
@ -170,16 +160,19 @@ class SearchDeviceController extends BaseController {
await StarCloudSDK.instance.pairDevice(
onError: (err) {
AppLogger.error('err:${err}');
hideLoading();
},
onSuccess: (StarCloudLock lockInfo) {
AppLogger.highlight('lockInfo:${lockInfo.toString()}');
//
showSuccess(message: '设备添加成功'.tr);
Get.back();
},
scanResult: device,
);
} catch (e, stackTrace) {
AppLogger.error('连接设备失败', error: e, stackTrace: stackTrace);
showToast('连接失败,请重试');
} finally {
hideLoading();
}
}

View File

@ -12,9 +12,10 @@ import 'package:starwork_flutter/views/main/main_controller.dart';
class HomeController extends BaseController {
final mainController = Get.find<MainController>();
final teamApi = Get.find<TeamApiService>();
final isOpenNotificationPermission = false.obs;
var carouselCurrentIndex = 0.obs;
//
@ -43,8 +44,7 @@ class HomeController extends BaseController {
void _initializeData() async {
showLoading();
///
requestAllTeamInfoList();
//
isOpenNotificationPermission.value = await AppPermission.checkPermission(
permission: Permission.notification,
@ -52,20 +52,7 @@ class HomeController extends BaseController {
hideLoading();
}
///
void requestAllTeamInfoList() async {
var teamList = await teamApi.requestAllTeamInfoList();
if (teamList.isSuccess) {
//
List<TeamInfoResponse> myTeamList = teamList.data?.myTeam ?? [];
//
List<TeamInfoResponse> pendTeamList = teamList.data?.pendTeam ?? [];
if (myTeamList.isEmpty) {
// 使
Get.toNamed(AppRoutes.teamUseCaseSetting);
}
}
}
//
void updateGradientColor(int index) {

View File

@ -83,7 +83,7 @@ class HomeView extends GetView<HomeController> {
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'19104656的互联',
controller.mainController.selectedTeam.value.teamName ?? '----------------',
style: TextStyle(
fontSize: 18.sp,
fontWeight: FontWeight.w500,
@ -92,7 +92,7 @@ class HomeView extends GetView<HomeController> {
Icon(
Icons.arrow_right_rounded,
size: 22.sp,
)
),
],
),
SuperTooltip(
@ -236,8 +236,8 @@ class HomeView extends GetView<HomeController> {
HomeNotDeviceArea(),
HomeTeamNoticeRowWidget(),
HomeStatisticsRowWidget(
personCount: 12,
deviceCount: 1,
personCount: 0,
deviceCount: 0,
),
SizedBox(height: 10.h),
HomeFunctionListAreaWidget(),

View File

@ -37,14 +37,14 @@ class _HomeNotDeviceAreaState extends State<HomeNotDeviceArea> {
'签勤全天候为您守护'.tr,
style: TextStyle(
color: Colors.black,
fontSize: 14.sp,
fontSize: 18.sp,
fontWeight: FontWeight.w500,
),
),
Text(
'快点新增设备,开始指挥互联吧'.tr,
style: TextStyle(
color: Colors.black,
color: Colors.grey,
fontSize: 12.sp,
fontWeight: FontWeight.w400,
),

View File

@ -1,17 +1,24 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:starwork_flutter/api/model/team/response/team_info_response.dart';
import 'package:starwork_flutter/api/service/team_api_service.dart';
import 'package:starwork_flutter/base/base_controller.dart';
import 'package:starwork_flutter/common/constant/app_images.dart';
import 'package:starwork_flutter/routes/app_routes.dart';
import 'package:starwork_flutter/views/home/home_controller.dart';
import 'package:starwork_flutter/views/home/home_view.dart';
import 'package:starwork_flutter/views/messages/messages_view.dart';
import 'package:starwork_flutter/views/mine/mine_view.dart';
class MainController extends BaseController {
final teamApi = Get.find<TeamApiService>();
GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
GlobalKey<ScaffoldState> scaffoldKey =
GlobalKey<ScaffoldState>();
//
var currentIndex = 0.obs;
@ -22,6 +29,19 @@ class MainController extends BaseController {
MineView(),
];
//
final myTeamList = <TeamInfoResponse>[].obs;
//
var selectedTeam = TeamInfoResponse().obs;
@override
void onInit() {
///
requestAllTeamInfoList();
super.onInit();
}
//
void changeIndex(int index) {
currentIndex.value = index;
@ -78,4 +98,21 @@ class MainController extends BaseController {
print('Error closing drawer: $e');
}
}
///
void requestAllTeamInfoList() async {
var teamList = await teamApi.requestAllTeamInfoList();
if (teamList.isSuccess) {
//
myTeamList.value = teamList.data?.myTeam ?? [];
myTeamList.refresh();
//
List<TeamInfoResponse> pendTeamList = teamList.data?.pendTeam ?? [];
if (myTeamList.isEmpty) {
// 使
Get.toNamed(AppRoutes.teamUseCaseSetting);
}
selectedTeam.value = myTeamList.first;
}
}
}

View File

@ -1,6 +1,9 @@
import 'dart:ffi';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:starwork_flutter/base/app_logger.dart';
import 'package:starwork_flutter/views/main/widget/main_left_drawer_widget.dart';
import 'main_controller.dart';
@ -30,8 +33,18 @@ class MainView extends GetView<MainController> {
unselectedFontSize: 12.sp,
),
),
drawer: MainLeftDrawerWidget(
teamList: ['家庭群组', '测试团队1', '测试团队2'],
drawer: Obx(
() => MainLeftDrawerWidget(
teamList: controller.myTeamList,
selectedTeam: controller.selectedTeam.value,
onTeamSelected: (team) {
controller.selectedTeam.value = team;
AppLogger.highlight('message:${team}');
},
onRefreshList: () {
controller.requestAllTeamInfoList();
},
),
),
);
}

View File

@ -1,6 +1,10 @@
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:starwork_flutter/api/model/team/response/team_info_response.dart';
import 'package:starwork_flutter/base/app_logger.dart';
import 'package:starwork_flutter/routes/app_routes.dart';
class MainLeftDrawerWidget extends StatefulWidget {
MainLeftDrawerWidget({
@ -8,11 +12,13 @@ class MainLeftDrawerWidget extends StatefulWidget {
required this.teamList,
this.selectedTeam,
this.onTeamSelected,
this.onRefreshList,
});
final List<String> teamList;
final String? selectedTeam;
final Function(String)? onTeamSelected;
final RxList<TeamInfoResponse> teamList;
final TeamInfoResponse? selectedTeam;
final Function(TeamInfoResponse)? onTeamSelected;
final Function()? onRefreshList;
@override
State<MainLeftDrawerWidget> createState() => _MainLeftDrawerWidgetState();
@ -47,7 +53,9 @@ class _MainLeftDrawerWidgetState extends State<MainLeftDrawerWidget> {
),
GestureDetector(
onTap: () {
Navigator.pop(context);
if (widget.onRefreshList != null) {
widget.onRefreshList!();
}
},
child: Container(
width: 28.w,
@ -69,118 +77,105 @@ class _MainLeftDrawerWidgetState extends State<MainLeftDrawerWidget> {
//
Expanded(
child: Container(
margin: EdgeInsets.symmetric(horizontal: 16.w),
child: ListView.builder(
itemCount: widget.teamList.length,
itemBuilder: (context, index) {
final team = widget.teamList[index];
final isSelected = team == widget.selectedTeam;
return Container(
margin: EdgeInsets.only(bottom: 8.h),
padding: EdgeInsets.all(16.w),
decoration: BoxDecoration(
color: isSelected
? const Color(0xFFE3F2FD) //
: Colors.white, //
borderRadius: BorderRadius.circular(12.r),
border: isSelected
? Border.all(color: const Color(0xFF2196F3), width: 1)
: Border.all(color: Colors.grey[200]!, width: 1),
),
child: GestureDetector(
child: Obx(
() => Container(
margin: EdgeInsets.symmetric(horizontal: 16.w),
child: ListView.builder(
itemCount: widget.teamList.length,
itemBuilder: (context, index) {
final team = widget.teamList[index];
final isSelected = team == widget.selectedTeam;
return GestureDetector(
onTap: () {
//
if (widget.onTeamSelected != null) {
widget.onTeamSelected!(team);
}
},
child: Row(
children: [
//
Container(
width: 40.w,
height: 40.w,
decoration: BoxDecoration(
color: isSelected
? const Color(0xFF2196F3)
: Colors.grey[400],
borderRadius: BorderRadius.circular(8.r),
),
child: Icon(
Icons.person,
color: Colors.white,
size: 24.sp,
),
),
SizedBox(width: 12.w),
//
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
team, // 使teamList中的元素作为团队昵称
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w500,
color: isSelected
? const Color(0xFF2196F3)
: Colors.black,
),
),
SizedBox(height: 4.h),
Row(
children: [
Icon(
isSelected
? Icons.check_circle
: Icons.check_circle_outline,
size: 14.sp,
color: isSelected
? const Color(0xFF2196F3)
: Colors.grey[400],
),
SizedBox(width: 4.w),
Text(
isSelected ? '已选中' : '未选中',
style: TextStyle(
fontSize: 12.sp,
color: isSelected
? const Color(0xFF2196F3)
: Colors.grey[600],
),
),
],
),
],
),
),
//
GestureDetector(
onTap: () {
//
Navigator.pop(context);
},
child: Container(
padding: EdgeInsets.all(8.w),
child: Container(
margin: EdgeInsets.only(bottom: 8.h),
padding: EdgeInsets.all(16.w),
decoration: BoxDecoration(
color: isSelected
? const Color(0xFFE3F2FD) //
: Colors.white, //
borderRadius: BorderRadius.circular(12.r),
border: isSelected
? Border.all(color: const Color(0xFF2196F3), width: 1)
: Border.all(color: Colors.grey[200]!, width: 1),
),
child: Row(
children: [
//
Container(
width: 40.w,
height: 40.w,
decoration: BoxDecoration(
color: isSelected ? const Color(0xFF2196F3) : Colors.grey[400],
borderRadius: BorderRadius.circular(8.r),
),
child: Icon(
Icons.settings,
size: 20.sp,
color: isSelected
? const Color(0xFF2196F3)
: Colors.grey[600],
Icons.group_rounded,
color: Colors.white,
size: 24.sp,
),
),
),
],
SizedBox(width: 12.w),
//
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
team.teamName ?? '',
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w500,
color: isSelected ? const Color(0xFF2196F3) : Colors.black,
),
),
SizedBox(height: 4.h),
Row(
children: [
Icon(
isSelected ? Icons.check_circle : Icons.check_circle_outline,
size: 14.sp,
color: isSelected ? const Color(0xFF2196F3) : Colors.grey[400],
),
SizedBox(width: 4.w),
Text(
isSelected ? '已选中' : '未选中',
style: TextStyle(
fontSize: 12.sp,
color: isSelected ? const Color(0xFF2196F3) : Colors.grey[600],
),
),
],
),
],
),
),
//
GestureDetector(
onTap: () {},
child: Container(
padding: EdgeInsets.all(8.w),
child: Icon(
Icons.settings,
size: 20.sp,
color: isSelected ? const Color(0xFF2196F3) : Colors.grey[600],
),
),
),
],
),
),
),
);
},
);
},
),
),
),
),
@ -196,8 +191,11 @@ class _MainLeftDrawerWidgetState extends State<MainLeftDrawerWidget> {
Expanded(
child: GestureDetector(
onTap: () {
//
Navigator.pop(context);
Get.toNamed(AppRoutes.teamCreateTeam)?.then((result) {
if (result != null && result is Map && result['created'] == true) {
widget.onRefreshList?.call();
}
});
},
child: Container(
padding: EdgeInsets.symmetric(vertical: 12.h),
@ -223,8 +221,11 @@ class _MainLeftDrawerWidgetState extends State<MainLeftDrawerWidget> {
Expanded(
child: GestureDetector(
onTap: () {
//
Navigator.pop(context);
Get.toNamed(AppRoutes.teamJoinTeam)?.then((result) {
if (result != null && result is Map && result['joinResult'] == true) {
widget.onRefreshList?.call();
}
});
},
child: Container(
padding: EdgeInsets.symmetric(vertical: 12.h),
@ -241,33 +242,6 @@ class _MainLeftDrawerWidgetState extends State<MainLeftDrawerWidget> {
),
],
),
// 线
Container(
margin: EdgeInsets.symmetric(vertical: 8.h),
height: 0.5,
color: Colors.grey[300],
),
//
GestureDetector(
onTap: () {
//
Navigator.pop(context);
},
child: Container(
width: double.infinity,
padding: EdgeInsets.symmetric(vertical: 12.h),
child: Text(
'快捷添加我的设备',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 16.sp,
color: Colors.black87,
),
),
),
),
],
),
),

View File

@ -0,0 +1,9 @@
import 'package:get/get.dart';
import 'package:starwork_flutter/views/team/createTeam/create_team_controller.dart';
class CreateTeamBinding extends Bindings {
@override
void dependencies() {
Get.lazyPut(() => CreateTeamController());
}
}

View File

@ -0,0 +1,55 @@
import 'package:flutter/widgets.dart';
import 'package:get/get.dart';
import 'package:starwork_flutter/api/model/team/request/create_team_request.dart';
import 'package:starwork_flutter/api/model/team/response/scene_info_response.dart';
import 'package:starwork_flutter/api/service/team_api_service.dart';
import 'package:starwork_flutter/base/base_controller.dart';
class CreateTeamController extends BaseController {
TextEditingController teamNameInputController = TextEditingController();
final teamApi = Get.find<TeamApiService>();
// 使
final selectedUseCase = Rx<SceneInfoResponse?>(null);
//
final useCases = <SceneInfoResponse>[].obs;
@override
void onInit() {
super.onInit();
requestAllSceneInfoList();
}
/// 使
void requestAllSceneInfoList() async {
showLoading();
var sceneList = await teamApi.requestAllSceneInfoList();
if (sceneList.isSuccess) {
// 使
useCases.value = sceneList.data?.list ?? [];
useCases.refresh();
}
hideLoading();
}
void requestCreateTeam() async {
showLoading();
var createTeamResponse = await teamApi.requestCreateTeam(
request: CreateTeamRequest(
teamName: teamNameInputController.text,
scene: selectedUseCase.value?.id ?? 0,
),
);
if (createTeamResponse.isSuccess) {
// 使 Get.back(result: true)
showSuccess();
//
Get.back(result: {'created': true});
} else {
//
showError(message: createTeamResponse.errorMsg!);
}
}
}

View File

@ -0,0 +1,281 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:starwork_flutter/common/constant/app_colors.dart';
import 'package:starwork_flutter/extension/function_extension.dart';
import 'package:starwork_flutter/views/team/createTeam/create_team_controller.dart';
class CreateTeamView extends GetView<CreateTeamController> {
const CreateTeamView({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
//
FocusScope.of(context).requestFocus(FocusNode());
},
child: Scaffold(
backgroundColor: AppColors.scaffoldBackgroundColor,
appBar: AppBar(
backgroundColor: Colors.white,
elevation: 0,
surfaceTintColor: Colors.transparent,
shadowColor: Colors.transparent,
scrolledUnderElevation: 0,
leading: IconButton(
icon: const Icon(Icons.arrow_back_ios_new_rounded), //
onPressed: () {
// 退
Navigator.of(context).pop();
},
),
title: Text(
'创建新团队'.tr,
style: TextStyle(
fontSize: 18.sp,
fontWeight: FontWeight.w500,
color: Colors.black87,
),
),
),
body: Padding(
padding: EdgeInsets.symmetric(
horizontal: 10.w,
vertical: 10.h,
),
child: Column(
children: [
Container(
height: 38.h,
padding: EdgeInsets.symmetric(
horizontal: 10.w,
),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8.r),
),
child: Row(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
'*',
style: TextStyle(
fontSize: 14.sp,
fontWeight: FontWeight.w500,
color: Colors.red,
),
),
Text(
'团队名称',
style: TextStyle(
fontSize: 14.sp,
fontWeight: FontWeight.w500,
),
),
],
),
Expanded(
// 使Expanded来确保TextField可以正确填充剩余空间
child: TextField(
controller: controller.teamNameInputController,
keyboardType: TextInputType.text,
textInputAction: TextInputAction.done,
textAlign: TextAlign.end,
decoration: InputDecoration(
hintText: '请输入团队/家庭名称'.tr,
//
border: InputBorder.none,
//
focusedBorder: InputBorder.none,
enabledBorder: InputBorder.none,
),
),
),
],
),
),
SizedBox(height: 10.h),
GestureDetector(
onTap: () {
_showBottomSheet(context);
},
child: Container(
height: 38.h,
padding: EdgeInsets.symmetric(
horizontal: 10.w,
),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8.r),
),
child: Row(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
'*',
style: TextStyle(
fontSize: 14.sp,
fontWeight: FontWeight.w500,
color: Colors.red,
),
),
Text(
'使用场景',
style: TextStyle(
fontSize: 14.sp,
fontWeight: FontWeight.w500,
),
),
],
),
Expanded(
// 使Expanded来确保TextField可以正确填充剩余空间
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Obx(
() => Text(
controller.selectedUseCase.value?.name ?? '',
style: TextStyle(
fontSize: 14.sp,
fontWeight: FontWeight.w500,
color: Colors.grey,
),
),
),
Icon(
Icons.arrow_forward_ios_rounded,
size: 16.sp,
color: Colors.grey,
)
],
),
),
],
),
),
),
SizedBox(height: 10.h),
Expanded(
child: Align(
alignment: Alignment.bottomCenter,
child: SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: () {
if (controller.teamNameInputController.text.isEmpty) {
controller.showToast('请先输入团队名称'.tr);
return;
}
if (controller.selectedUseCase.value == null) {
controller.showToast('请先选择使用场景'.tr);
return;
}
controller.requestCreateTeam();
}.debounce(),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blue,
padding: EdgeInsets.symmetric(vertical: 12.h),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.r)),
),
child: Text(
'确定'.tr,
style: TextStyle(
fontSize: 16.sp,
color: Colors.white,
fontWeight: FontWeight.w500,
),
),
),
),
),
),
SizedBox(height: 10.h),
],
),
),
),
);
}
void _showBottomSheet(BuildContext context) {
showModalBottomSheet(
context: context,
backgroundColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.zero,
),
builder: (context) {
return Container(
height: 448.h,
padding: EdgeInsets.symmetric(
horizontal: 10.w,
vertical: 10.h,
),
child: Column(
children: [
Text(
'请选择使用场景',
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w400,
),
),
SizedBox(height: 10.h),
Expanded(
child: Obx(
() => GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: 3,
crossAxisSpacing: 10.h,
mainAxisSpacing: 10.w,
),
itemCount: controller.useCases.length,
itemBuilder: (context, index) {
return GestureDetector(
onTap: () {
controller.selectedUseCase.value = controller.useCases[index];
Navigator.pop(context);
},
child: Container(
decoration: BoxDecoration(
color: controller.selectedUseCase.value == controller.useCases[index]
? Colors.blue.withOpacity(0.2)
: Colors.grey[200],
borderRadius: BorderRadius.circular(8.r),
border: controller.selectedUseCase.value == controller.useCases[index]
? Border.all(color: Colors.blue, width: 1.5)
: null,
),
alignment: Alignment.center,
child: Text(
controller.useCases[index].name ?? '',
style: TextStyle(
color: controller.selectedUseCase.value == controller.useCases[index]
? Colors.blue
: Colors.grey[700],
fontSize: 14.sp,
),
),
),
);
},
),
),
),
],
),
);
},
);
}
}

View File

@ -0,0 +1,9 @@
import 'package:get/get.dart';
import 'package:starwork_flutter/views/team/joinTeam/join_team_controller.dart';
class JoinTeamBinding extends Bindings {
@override
void dependencies() {
Get.lazyPut<JoinTeamController>(() => JoinTeamController());
}
}

View File

@ -0,0 +1,10 @@
import 'package:flutter/widgets.dart';
import 'package:get/get.dart';
import 'package:starwork_flutter/base/base_controller.dart';
class JoinTeamController extends BaseController {
TextEditingController nameInputController = TextEditingController();
final teamCode = ''.obs;
void joinTeam() {}
}

View File

@ -0,0 +1,205 @@
import 'package:flutter/material.dart';
import 'package:flutter/src/widgets/framework.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:pinput/pinput.dart';
import 'package:starwork_flutter/base/app_logger.dart';
import 'package:starwork_flutter/common/constant/app_colors.dart';
import 'package:starwork_flutter/common/constant/app_toast_messages.dart';
import 'package:starwork_flutter/common/widgets/custom_app_bar_widget.dart';
import 'package:starwork_flutter/extension/function_extension.dart';
import 'package:starwork_flutter/views/team/joinTeam/join_team_controller.dart';
class JoinTeamView extends GetView<JoinTeamController> {
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
FocusScope.of(context).unfocus();
},
child: Scaffold(
backgroundColor: AppColors.scaffoldBackgroundColor,
appBar: CustomAppBarWidget(
title: '加入团队'.tr,
),
body: Padding(
padding: EdgeInsets.symmetric(
horizontal: 10.w,
vertical: 10.h,
),
child: Column(
children: [
Row(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'输入团队码',
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w600,
),
),
SizedBox(height: 4.h),
Text(
'团队码是一个由字母组成的8位编码可通过管理员获取',
style: TextStyle(
fontSize: 12.sp,
fontWeight: FontWeight.w400,
color: Colors.grey,
),
),
],
)
],
),
SizedBox(height: 10.h),
Container(
padding: EdgeInsets.symmetric(
horizontal: 10.w,
vertical: 10.h,
),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8.r),
),
child: Column(
children: [
Pinput(
length: 8,
obscureText: false,
autofocus: false,
defaultPinTheme: PinTheme(
width: 50.w,
height: 34.h,
textStyle: TextStyle(
fontSize: 20.sp,
color: Colors.black,
),
decoration: BoxDecoration(
color: Colors.grey[100],
borderRadius: BorderRadius.circular(4.r),
),
),
validator: (value) {
if (value!.isEmpty) return '请输入团队码';
if (value.length != 8) return '验证码需8位';
return null;
},
onCompleted: (pin) {},
onChanged: (value) {
controller.teamCode.value = value;
},
),
SizedBox(height: 10.h),
TextField(
controller: controller.nameInputController,
keyboardType: TextInputType.text,
textInputAction: TextInputAction.done,
onChanged: (value) {
// /
},
decoration: InputDecoration(
counterText: '',
hintText: '请输入您的姓名',
//
border: InputBorder.none,
//
filled: true,
fillColor: Colors.grey[100],
contentPadding: EdgeInsets.symmetric(
horizontal: 16.w,
vertical: 12.h,
),
suffixIcon: controller.nameInputController.text.isNotEmpty
? IconButton(
icon: const Icon(Icons.clear, color: Colors.grey),
onPressed: () {
controller.nameInputController.clear(); //
},
)
: null,
// ,
//
focusedBorder: OutlineInputBorder(
borderSide: const BorderSide(
color: Colors.blue,
width: 1.5,
),
borderRadius: BorderRadius.circular(8.0.r),
),
enabledBorder: OutlineInputBorder(
borderSide: const BorderSide(color: Colors.transparent),
borderRadius: BorderRadius.circular(8.0.r),
),
),
),
],
),
),
SizedBox(height: 10.h),
SizedBox(
width: double.infinity,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, //
children: [
// Expanded(
// // 使Expanded来让按钮根据内容扩展
// child: ElevatedButton(
// onPressed: () {}.debounce(),
// style: ElevatedButton.styleFrom(
// backgroundColor: Colors.white,
// padding: EdgeInsets.symmetric(vertical: 12.h),
// shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.r)),
// ),
// child: Text(
// '扫描二维码加入'.tr,
// style: TextStyle(
// fontSize: 16.sp,
// color: Colors.blue,
// fontWeight: FontWeight.w500,
// ),
// ),
// ),
// ),
SizedBox(width: 10.w), //
Expanded(
// 使Expanded来让按钮根据内容扩展
child: ElevatedButton(
onPressed: () {
if (controller.teamCode.value.isEmpty) {
controller.showToast(AppToastMessages.notInputTeamCode);
return;
}
if (controller.nameInputController.text.isEmpty) {
controller.showToast(AppToastMessages.notInputName);
return;
}
controller.joinTeam();
}.debounce(),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blue,
padding: EdgeInsets.symmetric(vertical: 12.h),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.r)),
),
child: Text(
'申请加入'.tr,
style: TextStyle(
fontSize: 16.sp,
color: Colors.white,
fontWeight: FontWeight.w500,
),
),
),
)
],
),
),
],
),
),
),
);
}
}

View File

@ -1,5 +1,5 @@
import 'package:get/get.dart';
import 'package:starwork_flutter/views/main/teamNotice/teamNoticeDetails/team_notice_details_controller.dart';
import 'package:starwork_flutter/views/team/teamNotice/teamNoticeDetails/team_notice_details_controller.dart';
class TeamNoticeDetailsBinding extends Bindings{
@override

View File

@ -1,6 +1,6 @@
import 'package:flutter/src/widgets/framework.dart';
import 'package:get/get.dart';
import 'package:starwork_flutter/views/main/teamNotice/teamNoticeDetails/team_notice_details_controller.dart';
import 'package:starwork_flutter/views/team/teamNotice/teamNoticeDetails/team_notice_details_controller.dart';
class TeamNoticeDetailsView extends GetView<TeamNoticeDetailsController> {
const TeamNoticeDetailsView({super.key});

View File

@ -1,5 +1,5 @@
import 'package:get/get.dart';
import 'package:starwork_flutter/views/main/teamNotice/team_notice_controller.dart';
import 'package:starwork_flutter/views/team/teamNotice/team_notice_controller.dart';
class TeamNoticeBinding extends Bindings {
@override

View File

@ -3,7 +3,8 @@ import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:starwork_flutter/common/constant/app_colors.dart';
import 'package:starwork_flutter/views/main/teamNotice/team_notice_controller.dart';
import 'package:starwork_flutter/common/widgets/custom_app_bar_widget.dart';
import 'package:starwork_flutter/views/team/teamNotice/team_notice_controller.dart';
class TeamNoticeView extends GetView<TeamNoticeController> {
const TeamNoticeView({super.key});
@ -11,26 +12,8 @@ class TeamNoticeView extends GetView<TeamNoticeController> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
elevation: 0,
surfaceTintColor: Colors.transparent,
shadowColor: Colors.transparent,
scrolledUnderElevation: 0,
leading: null,
automaticallyImplyLeading: false,
title: Row(
children: [
Text(
'公告'.tr,
style: TextStyle(
fontSize: 18.sp,
fontWeight: FontWeight.w500,
color: Colors.black87,
),
),
],
),
appBar: CustomAppBarWidget(
title: '公告'.tr,
),
body: Column(
children: [
@ -56,9 +39,7 @@ class TeamNoticeView extends GetView<TeamNoticeController> {
indicatorSize: TabBarIndicatorSize.tab,
// tab让指示器占满每个选项卡宽度
dividerColor: Colors.transparent,
tabs: controller.functionOptionList
.map((title) => Tab(text: title))
.toList(),
tabs: controller.functionOptionList.map((title) => Tab(text: title)).toList(),
),
Expanded(
child: TabBarView(

View File

@ -23,11 +23,11 @@ class UseCaseSettingController extends BaseController {
void onInit() {
super.onInit();
_generateRandomNumber();
requestAllTeamInfoList();
requestAllSceneInfoList();
}
///
void requestAllTeamInfoList() async {
/// 使
void requestAllSceneInfoList() async {
showLoading();
var sceneList = await teamApi.requestAllSceneInfoList();

View File

@ -4,6 +4,8 @@ import 'package:flutter/src/widgets/framework.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:starwork_flutter/base/app_logger.dart';
import 'package:starwork_flutter/common/constant/app_toast_messages.dart';
import 'package:starwork_flutter/extension/function_extension.dart';
import 'package:starwork_flutter/views/team/useCaseSetting/use_case_setting_controller.dart';
class UseCaseSettingView extends GetView<UseCaseSettingController> {
@ -24,12 +26,16 @@ class UseCaseSettingView extends GetView<UseCaseSettingController> {
IconButton(
icon: const Icon(Icons.close),
onPressed: () {
if (controller.teamNameInputController.text.isEmpty) {
controller.showToast('请先输入团队名称'.tr);
return;
}
if (controller.selectedUseCase.value == null) {
controller.showToast('请先选择使用场景'.tr);
return;
}
controller.requestCreateTeam();
},
}.debounce(),
),
],
),
@ -173,12 +179,16 @@ class UseCaseSettingView extends GetView<UseCaseSettingController> {
width: double.infinity,
child: ElevatedButton(
onPressed: () {
if (controller.teamNameInputController.text.isEmpty) {
controller.showToast(AppToastMessages.notInputTeamName);
return;
}
if (controller.selectedUseCase.value == null) {
controller.showToast('请先选择使用场景'.tr);
controller.showToast(AppToastMessages.notSelectUseCase);
return;
}
controller.requestCreateTeam();
},
}.debounce(),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blue,
padding: EdgeInsets.symmetric(vertical: 12.h),

View File

@ -82,7 +82,7 @@ packages:
source: hosted
version: "1.18.0"
crypto:
dependency: "direct main"
dependency: transitive
description:
name: crypto
sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab

View File

@ -39,8 +39,8 @@ dependencies:
# 星云sdk
starcloud:
path: ../starcloud-sdk-flutter
# 加解密库
crypto: ^3.0.3
dev_dependencies: