diff --git a/lib/modules/meeting/controllers/meeting_controller.dart b/lib/modules/meeting/controllers/meeting_controller.dart index a2f13f89d..779f52a79 100644 --- a/lib/modules/meeting/controllers/meeting_controller.dart +++ b/lib/modules/meeting/controllers/meeting_controller.dart @@ -33,7 +33,11 @@ class MeetingController extends GetxController { List files = []; TextEditingController titleController = TextEditingController(); // 录音标题 String titleCSuffix = ""; // 录音标题后缀 + + List originalDataList = []; RxList dataList = [].obs; + RxString filtrateType = ''.obs; + bool isAsc = false; // 蓝牙服务 final bleManager = Get.find(); @@ -74,7 +78,8 @@ class MeetingController extends GetxController { // 请求本地数据 void _getDataList() async { List list = await SqfliteApi.getMeetingList(); - dataList.value = List.from(list); + originalDataList = List.from(list); + dataList.value = originalDataList; } // 请求存储权限 @@ -207,12 +212,22 @@ class MeetingController extends GetxController { // 上传OSS meetingUploadService.addUpload(meetingId, newPath, 'LocalAudio'); - // 更新UI数据 - dataList.insert(0, { + originalDataList.insert(0, { 'id': meetingId, - 'taskid': '', ...data, }); + // 更新UI数据 + if (isAsc) { + dataList.add({ + 'id': meetingId, + ...data, + }); + } else { + dataList.insert(0, { + 'id': meetingId, + ...data, + }); + } // 移动文件 await file.copy(newPath); @@ -254,11 +269,21 @@ class MeetingController extends GetxController { if (meetingId != null) { meetingUploadService.addUpload(meetingId, filePath, 'TranslatAudio'); - dataList.insert(0, { + originalDataList.insert(0, { 'id': meetingId, - 'taskid': '', ...data, }); + if (isAsc) { + dataList.add({ + 'id': meetingId, + ...data, + }); + } else { + dataList.insert(0, { + 'id': meetingId, + ...data, + }); + } } } catch (e) { Logger.error('导入文件失败: $filePath, error: $e'); @@ -315,12 +340,21 @@ class MeetingController extends GetxController { final meetingId = await SqfliteApi.insertMeeting(data); if (meetingId != null) { meetingUploadService.addUpload(meetingId, filePath, 'ExternalAudio'); - - dataList.insert(0, { + originalDataList.insert(0, { 'id': meetingId, - 'taskid': '', ...data, }); + if (isAsc) { + dataList.add({ + 'id': meetingId, + ...data, + }); + } else { + dataList.insert(0, { + 'id': meetingId, + ...data, + }); + } } return meetingId; } @@ -342,7 +376,15 @@ class MeetingController extends GetxController { if (titleController.text.isNotEmpty) { String title = titleController.text + titleCSuffix; SqfliteApi.editMeetingTitle(id, {'title': title}); + int originalIndex = + originalDataList.indexWhere((item) => item['id'] == id); int index = dataList.indexWhere((item) => item['id'] == id); + if (originalIndex != -1) { + final dataMap = + Map.from(originalDataList[originalIndex]); + dataMap['title'] = title; + originalDataList[originalIndex] = dataMap; + } if (index != -1) { final dataMap = Map.from(dataList[index]); dataMap['title'] = title; @@ -354,6 +396,7 @@ class MeetingController extends GetxController { // 删除数据 void deleteMeeting(int id, String filepath) async { + originalDataList.removeWhere((item) => item['id'] == id); dataList.removeWhere((item) => item['id'] == id); // 删除数据库中的记录 SqfliteApi.deleteMeeting(id); diff --git a/lib/modules/meeting/views/bottomSheet/ai_bottom_sheet.dart b/lib/modules/meeting/views/bottomSheet/ai_bottom_sheet.dart index 06977d83f..cdbb8633c 100644 --- a/lib/modules/meeting/views/bottomSheet/ai_bottom_sheet.dart +++ b/lib/modules/meeting/views/bottomSheet/ai_bottom_sheet.dart @@ -320,7 +320,6 @@ class _AIBottomSheetState extends State { isDense: true, fillColor: Colors.transparent, border: InputBorder.none, - contentPadding: EdgeInsets.zero, ), onSubmitted: _sendMessage, ), diff --git a/lib/modules/meeting/views/bottomSheet/edit_title_bottom_sheet.dart b/lib/modules/meeting/views/bottomSheet/edit_title_bottom_sheet.dart index dc964d23e..51e0d9bf0 100644 --- a/lib/modules/meeting/views/bottomSheet/edit_title_bottom_sheet.dart +++ b/lib/modules/meeting/views/bottomSheet/edit_title_bottom_sheet.dart @@ -53,7 +53,6 @@ class EditTitleBottomSheet extends GetView { color: Colors.grey[300], ), Container( - height: 48.w, margin: EdgeInsets.symmetric(vertical: 20.w), alignment: Alignment.center, decoration: BoxDecoration( @@ -79,9 +78,10 @@ class EditTitleBottomSheet extends GetView { color: Colors.black54, fontSize: 16.sp, ), + isDense: true, fillColor: Colors.transparent, border: InputBorder.none, - contentPadding: EdgeInsets.symmetric(horizontal: 10.w), + contentPadding: EdgeInsets.all(10.w), ), ), ), diff --git a/lib/modules/meeting/views/bottomSheet/filtrate_drawer.dart b/lib/modules/meeting/views/bottomSheet/filtrate_drawer.dart index bb843c478..6f3058b2d 100644 --- a/lib/modules/meeting/views/bottomSheet/filtrate_drawer.dart +++ b/lib/modules/meeting/views/bottomSheet/filtrate_drawer.dart @@ -1,74 +1,218 @@ import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:get/get.dart'; -class FiltrateDrawer extends StatelessWidget { - const FiltrateDrawer({super.key}); +import '../../controllers/meeting_controller.dart'; + +class FiltrateDrawer extends StatefulWidget { + final GlobalKey scaffoldKey; + + const FiltrateDrawer(this.scaffoldKey, {super.key}); + + @override + State createState() => _FiltrateDrawerState(); +} + +class _FiltrateDrawerState extends State { + final _controller = Get.find(); @override Widget build(BuildContext context) { return SafeArea( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: EdgeInsets.all(20.w), - child: TextField( - decoration: InputDecoration( - hintText: '在所有文件中搜索', - prefixIcon: Icon(Icons.search), - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(12.w), - borderSide: BorderSide.none, + child: Padding( + padding: EdgeInsets.symmetric(horizontal: 12.w), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + padding: EdgeInsets.symmetric(horizontal: 10.w), + margin: EdgeInsets.symmetric(vertical: 15.w), + alignment: Alignment.center, + decoration: BoxDecoration( + color: Colors.grey[200], + borderRadius: BorderRadius.circular(12.w), + ), + child: Row( + children: [ + Icon( + Icons.search, + color: Colors.black87, + size: 20.w, + ), + Expanded( + child: TextField( + controller: _controller.titleController, + style: TextStyle( + color: Colors.black87, + fontSize: 14.sp, + ), + decoration: InputDecoration( + hintText: '在所有文件中搜索', + hintStyle: TextStyle( + color: Colors.black54, + fontSize: 14.sp, + ), + isDense: true, + fillColor: Colors.transparent, + border: InputBorder.none, + contentPadding: EdgeInsets.symmetric(vertical: 10.w), + ), + ), + ), + ], + ), + ), + GestureDetector( + onTap: () { + _filtrateDataList(''); + }, + behavior: HitTestBehavior.translucent, + child: Container( + padding: EdgeInsets.symmetric(horizontal: 10.w, vertical: 10.w), + decoration: _controller.filtrateType.value == '' + ? BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(12.w), + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.06), + blurRadius: 10, + offset: const Offset(0, 2), + ), + ], + ) + : null, + child: Row( + children: [ + Icon( + Icons.folder, + color: Colors.red, + size: 20.w, + ), + 6.horizontalSpace, + Text( + '全部文件(${_controller.originalDataList.length})', + style: TextStyle( + color: Colors.black87, + fontSize: 14.sp, + ), + ), + ], ), - filled: true, - fillColor: Colors.grey[100], - contentPadding: EdgeInsets.zero, ), ), - ), - ListTile( - leading: Icon(Icons.folder, color: Colors.red), - title: - Text('全部文件(4)', style: TextStyle(fontWeight: FontWeight.bold)), - onTap: () {}, - ), - ListTile( - leading: Icon(Icons.category, color: Colors.blue), - title: Text('未分类(4)'), - onTap: () {}, - ), - ListTile( - leading: Icon(Icons.delete, color: Colors.teal), - title: Text('回收站'), - onTap: () {}, - ), - Divider(), - Padding( - padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 8.w), - child: Text('文件夹', style: TextStyle(color: Colors.grey)), - ), - ...['NOTE', 'CALL', 'NotePin', 'Import', 'Desktop'] - .map((name) => ListTile( - title: Text(name), - onTap: () {}, - )), - Divider(), - Padding( - padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 8.w), - child: Text('排序方式', style: TextStyle(color: Colors.grey)), - ), - ListTile( - title: Text('创建时间'), - trailing: Icon(Icons.arrow_upward), - onTap: () {}, - ), - ListTile( - title: Text('修改时间'), - trailing: Icon(Icons.arrow_upward), - onTap: () {}, - ), - ], + Padding( + padding: EdgeInsetsGeometry.symmetric(vertical: 15.w), + child: Divider( + height: 1, + color: Colors.grey[300], + ), + ), + Padding( + padding: EdgeInsets.only(bottom: 10.w), + child: Text( + '来自', + style: TextStyle( + color: Colors.grey, + fontSize: 14.sp, + fontWeight: FontWeight.bold, + ), + ), + ), + ...['IMPORT', 'TRANSLAT', 'LOCAL'].map( + (name) => GestureDetector( + onTap: () { + _filtrateDataList(name); + }, + behavior: HitTestBehavior.translucent, + child: Container( + width: double.infinity, + padding: + EdgeInsets.symmetric(horizontal: 10.w, vertical: 10.w), + margin: EdgeInsets.symmetric(vertical: 2.w), + decoration: _controller.filtrateType.value == name + ? BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(12.w), + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.06), + blurRadius: 10, + offset: const Offset(0, 2), + ), + ], + ) + : null, + child: Text( + name, + style: TextStyle( + color: Colors.black87, + fontSize: 14.sp, + ), + ), + ), + ), + ), + Padding( + padding: EdgeInsets.symmetric(vertical: 10.w), + child: Text( + '排序方式', + style: TextStyle( + color: Colors.grey, + fontSize: 14.sp, + fontWeight: FontWeight.bold, + ), + ), + ), + GestureDetector( + onTap: () { + widget.scaffoldKey.currentState?.closeDrawer(); + _controller.isAsc = !_controller.isAsc; + _controller.dataList.value = + _controller.dataList.reversed.toList(); + }, + behavior: HitTestBehavior.translucent, + child: Container( + padding: EdgeInsets.symmetric(vertical: 10.w), + margin: EdgeInsets.symmetric(vertical: 2.w), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + '创建时间', + style: TextStyle( + color: Colors.black87, + fontSize: 14.sp, + ), + ), + Icon( + _controller.isAsc + ? Icons.keyboard_double_arrow_up + : Icons.keyboard_double_arrow_down, + color: Colors.grey, + size: 20.w, + ), + ], + ), + ), + ), + ], + ), ), ); } + + void _filtrateDataList(String type) { + widget.scaffoldKey.currentState?.closeDrawer(); + _controller.filtrateType.value = type; + if (type.isNotEmpty) { + _controller.dataList.value = + _controller.originalDataList.where((i) => i['type'] == type).toList(); + } else { + _controller.dataList.value = _controller.originalDataList; + } + if (_controller.isAsc) { + _controller.dataList.value = _controller.dataList.reversed.toList(); + } + } } diff --git a/lib/modules/meeting/views/meeting_view.dart b/lib/modules/meeting/views/meeting_view.dart index 3ca043534..94207f2aa 100644 --- a/lib/modules/meeting/views/meeting_view.dart +++ b/lib/modules/meeting/views/meeting_view.dart @@ -28,7 +28,8 @@ class MeetingView extends GetView { appBar: _buildAppBar(isDarkMode), drawer: Drawer( width: 260.w, - child: const FiltrateDrawer(), + backgroundColor: Colors.grey[50], + child: FiltrateDrawer(scaffoldKey), ), drawerEnableOpenDragGesture: false, body: Column( @@ -37,15 +38,7 @@ class MeetingView extends GetView { Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - IconButton( - icon: Icon( - Icons.folder_open, - color: isDarkMode ? Colors.white : Colors.black, - ), - onPressed: () { - scaffoldKey.currentState?.openDrawer(); - }, - ), + _buildFiltrate(scaffoldKey, isDarkMode), _buildConnect(isDarkMode), ], ), @@ -74,6 +67,56 @@ class MeetingView extends GetView { ); } + Widget _buildFiltrate(GlobalKey scaffoldKey, bool isDarkMode) { + return GestureDetector( + onTap: () { + scaffoldKey.currentState?.openDrawer(); + }, + behavior: HitTestBehavior.translucent, + child: Row( + children: [ + 12.horizontalSpace, + Container( + width: 32.w, + height: 32.w, + margin: EdgeInsets.symmetric( + vertical: 10.w, + ), + decoration: BoxDecoration( + color: isDarkMode ? Colors.white.withOpacity(0.05) : Colors.white, + borderRadius: BorderRadius.circular(12.w), + boxShadow: [ + BoxShadow( + color: isDarkMode + ? Colors.black.withOpacity(0.2) + : Colors.black.withOpacity(0.05), + blurRadius: 10, + offset: const Offset(0, 2), + ), + ], + ), + child: Icon( + Icons.format_list_bulleted, + color: isDarkMode ? Colors.white : Colors.black87, + size: 20.sp, + ), + ), + 5.horizontalSpace, + Obx( + () => Text( + '${controller.filtrateType.value.isNotEmpty ? controller.filtrateType : '全部文件'}(${controller.dataList.length})', + style: TextStyle( + color: isDarkMode ? Colors.white : Colors.black87, + fontSize: 16.sp, + fontWeight: FontWeight.bold, + ), + ), + ), + ], + ), + ); + } + Widget _buildConnect(bool isDarkMode) { return GestureDetector( onTap: () { diff --git a/lib/modules/meeting/views/tabs/speech_tab.dart b/lib/modules/meeting/views/tabs/speech_tab.dart index 37bd4373e..a2c730c9f 100644 --- a/lib/modules/meeting/views/tabs/speech_tab.dart +++ b/lib/modules/meeting/views/tabs/speech_tab.dart @@ -134,7 +134,6 @@ class SpeechTab extends GetView { () => Container( padding: EdgeInsets.symmetric( horizontal: 14.w, - vertical: 5.w, ), decoration: BoxDecoration( color: @@ -173,11 +172,12 @@ class SpeechTab extends GetView { style: textStyle, minLines: 1, maxLines: 100, - decoration: const InputDecoration( + decoration: InputDecoration( isDense: true, fillColor: Colors.transparent, border: InputBorder.none, - contentPadding: EdgeInsets.zero, + contentPadding: + EdgeInsets.symmetric(vertical: 5.w), ), onChanged: (String value) { controller.editSpeakerTextChange = value; diff --git a/lib/modules/ota_upgrade/controllers/ota_upgrade_controller.dart b/lib/modules/ota_upgrade/controllers/ota_upgrade_controller.dart index 0df0f9d40..ef9bc97e8 100644 --- a/lib/modules/ota_upgrade/controllers/ota_upgrade_controller.dart +++ b/lib/modules/ota_upgrade/controllers/ota_upgrade_controller.dart @@ -181,12 +181,6 @@ class OtaUpgradeController extends GetxController { _address = connectedDevices.first.address; } - await _bleManager.setEnterOta(true); - - await Future.delayed(const Duration(seconds: 2)); - - jlota.init(); - // API请求 final response = await Api.getproduct({ "id": deviceInfo.firmwareProductId, @@ -204,7 +198,15 @@ class OtaUpgradeController extends GetxController { updatepackageaddress = resp.updatepackageaddress!; // 版本检查 - isUpdateAvailable.value = _isNewVersionAvailable(resp.systemversion!); + bool isUpdate = _isNewVersionAvailable(resp.systemversion!); + + if (isUpdate) { + await _bleManager.setEnterOta(true); + await Future.delayed(const Duration(seconds: 2)); + jlota.init(); + } + + isUpdateAvailable.value = isUpdate; } catch (e) { // 统一错误处理 errorMessage.value = e.toString();