提交 1277c36a authored 作者: yueweilu's avatar yueweilu

修改笔记 以及语音播放

上级 f5f637c7
...@@ -431,5 +431,34 @@ abstract class MineAPI { ...@@ -431,5 +431,34 @@ abstract class MineAPI {
return false; return false;
} }
/// 25、修改笔记、高亮、划线的内容
static Future<bool> editNotes({
required String content,
required String notesId,
required String bookId,
required String noteContent,
String isOpen = '0',
String positioning = '',
String color= '#FF0000',
}) async {
final result = await HttpService.to.post(
'/v1/book/Information/editNotes',
params: {
'notes_id': notesId,
'book_id':bookId,
'note_content':noteContent,
'positioning':positioning,
'is_open':isOpen,
'color': color,
'content':content
},
showLoading: true
);
if (result.data is Map && result.data['is_success'] == 1) {
return true;
}
return false;
}
} }
...@@ -22,10 +22,10 @@ void main() { ...@@ -22,10 +22,10 @@ void main() {
Future.wait([ Future.wait([
UserStore.to.profile(), UserStore.to.profile(),
]).whenComplete(() { ]).whenComplete(() {
String name = EncryptUtil.aesEncrypt('我是谁'); // String name = EncryptUtil.aesEncrypt('我是谁');
print('2222222---------$name'); // print('2222222---------$name');
final result = EncryptUtil.aesDecrypt(name); // final result = EncryptUtil.aesDecrypt(name);
Console.log('解密--------------------------$result'); // Console.log('解密--------------------------$result');
runApp(const MyApp()); runApp(const MyApp());
//FlutterNativeSplash.remove(); //FlutterNativeSplash.remove();
}); });
......
...@@ -349,7 +349,7 @@ class NoteModel { ...@@ -349,7 +349,7 @@ class NoteModel {
}); });
NoteModel.fromJson(dynamic json) { NoteModel.fromJson(dynamic json) {
types = json['notes_id']; notesId = json['notes_id'];
types = json['types']; types = json['types'];
chapterId = json['chapter_id']; chapterId = json['chapter_id'];
content = json['content']; content = json['content'];
...@@ -412,6 +412,8 @@ class MediaModel { ...@@ -412,6 +412,8 @@ class MediaModel {
this.content, this.content,
this.id, this.id,
this.duration = '', this.duration = '',
this.path = '',
this.currentDuration = '0:00:00'
}); });
MediaModel.fromJson(dynamic json) { MediaModel.fromJson(dynamic json) {
...@@ -419,15 +421,22 @@ class MediaModel { ...@@ -419,15 +421,22 @@ class MediaModel {
content = json['content']; content = json['content'];
id = json['id']; id = json['id'];
duration = ''; duration = '';
path = '';
currentDuration = '0:00:00';
} }
num? privacyStatus; num? privacyStatus;
String? content; String? content;
late String path;
num? id; num? id;
late String duration; late String duration;
MediaModel copyWith({ num? privacyStatus, late String currentDuration;
MediaModel copyWith({
num? privacyStatus,
String? content, String? content,
num? id, num? id,
}) => MediaModel( privacyStatus: privacyStatus ?? this.privacyStatus, String path = '',
}) => MediaModel(
privacyStatus: privacyStatus ?? this.privacyStatus,
content: content ?? this.content, content: content ?? this.content,
id: id ?? this.id, id: id ?? this.id,
); );
......
...@@ -60,7 +60,10 @@ class BookPayController extends GetxController { ...@@ -60,7 +60,10 @@ class BookPayController extends GetxController {
/// 支付方式 默认第一个 /// 支付方式 默认第一个
late PayModel _payModel = pays.first; late PayModel _payModel = pays.first;
PayModel get payModel => _payModel; PayModel get payModel {
_payModel.selected = true;
return _payModel;
}
/// 选择积分状态 /// 选择积分状态
void show(){ void show(){
......
...@@ -86,15 +86,15 @@ class CourseController extends GetxController { ...@@ -86,15 +86,15 @@ class CourseController extends GetxController {
} }
} }
void logout(BuildContext context) async { // void logout(BuildContext context) async {
final result = await AccountAPI.logout(); // final result = await AccountAPI.logout();
if (result){ // if (result){
CustomToast.success('退出成功'); // CustomToast.success('退出成功');
await UserStore.to.logout(); // await UserStore.to.logout();
if(context.mounted){ // if(context.mounted){
context.goNamed(Routes.main); // context.goNamed(Routes.main);
} // }
} // }
} // }
} }
\ No newline at end of file
...@@ -42,7 +42,6 @@ class _CoursePageState extends State<CoursePage> { ...@@ -42,7 +42,6 @@ class _CoursePageState extends State<CoursePage> {
if (result == true) { if (result == true) {
controller.getNums(); controller.getNums();
} }
// controller.logout(context);
}, },
child: badges.Badge( child: badges.Badge(
position: badges.BadgePosition.topEnd(top: -5.w, end: 0), position: badges.BadgePosition.topEnd(top: -5.w, end: 0),
......
...@@ -142,8 +142,8 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide ...@@ -142,8 +142,8 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide
// 开启录音 // 开启录音
void record() async { void record() async {
startRecording = true; startRecording = true;
String filePath = await _getDirectory(); String filePath = await Tools.getDirectory();
String fileName = generateVoiceFileName(); String fileName = Tools.generateVoiceFileName();
_mRecorder.startRecorder( _mRecorder.startRecorder(
toFile: '$filePath/$fileName', toFile: '$filePath/$fileName',
......
...@@ -14,10 +14,8 @@ import 'package:flutter_book/theme.dart'; ...@@ -14,10 +14,8 @@ import 'package:flutter_book/theme.dart';
import 'package:flutter_cache_manager/flutter_cache_manager.dart'; import 'package:flutter_cache_manager/flutter_cache_manager.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart'; import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:flutter_book/utils/index.dart'; import 'package:flutter_book/utils/index.dart';
import 'package:flutter_oss_aliyun/flutter_oss_aliyun.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_sound/public/flutter_sound_recorder.dart'; import 'package:flutter_sound/public/flutter_sound_recorder.dart';
import 'package:flutter_sound/public/util/flutter_sound_helper.dart';
import 'package:flutter_sound_platform_interface/flutter_sound_platform_interface.dart'; import 'package:flutter_sound_platform_interface/flutter_sound_platform_interface.dart';
import 'package:flutter_sound_platform_interface/flutter_sound_recorder_platform_interface.dart'; import 'package:flutter_sound_platform_interface/flutter_sound_recorder_platform_interface.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
......
...@@ -73,6 +73,10 @@ class _ReadPageState extends State<ReadPage> { ...@@ -73,6 +73,10 @@ class _ReadPageState extends State<ReadPage> {
onWebViewCreated: (InAppWebViewController controller){ onWebViewCreated: (InAppWebViewController controller){
readController.webViewController = controller; readController.webViewController = controller;
}, },
onConsoleMessage: (controller, consoleMessage) {
// 接收从 WebView 发送的消息
print("Received message from WebView: ${consoleMessage.message}");
},
onLoadStop: (controller, url) { onLoadStop: (controller, url) {
// flutter 主动给 js 传参数 // flutter 主动给 js 传参数
Map<String, dynamic> param = { Map<String, dynamic> param = {
...@@ -80,6 +84,7 @@ class _ReadPageState extends State<ReadPage> { ...@@ -80,6 +84,7 @@ class _ReadPageState extends State<ReadPage> {
'chapter_id': readController.chapterId, 'chapter_id': readController.chapterId,
'token':UserStore.to.token 'token':UserStore.to.token
}; };
Console.log('param--------------------------------$param');
controller.evaluateJavascript(source: 'callbackInFlutterComponent("$param");'); controller.evaluateJavascript(source: 'callbackInFlutterComponent("$param");');
// 添加单击事件 // 添加单击事件
......
...@@ -106,7 +106,7 @@ class _ReadInputDiscussState extends State<ReadInputDiscuss> { ...@@ -106,7 +106,7 @@ class _ReadInputDiscussState extends State<ReadInputDiscuss> {
onTap: (){ onTap: (){
widget.controller.delDiscussInputImages(widget.controller.discussInputImages[index]); widget.controller.delDiscussInputImages(widget.controller.discussInputImages[index]);
}, },
child: Image.asset('assets/images/del_close.png',width: 12.w,height: 12.w,) child: Image.asset('assets/images/media_del.png',width: 12.w,height: 12.w,)
) )
) )
], ],
......
...@@ -10,7 +10,7 @@ class UserCouponController extends GetxController { ...@@ -10,7 +10,7 @@ class UserCouponController extends GetxController {
// 优惠券 // 优惠券
List <CouponModel> coupons = []; List <CouponModel> coupons = [];
late int type = 1; late int type = 2;
final int _limit = 10; final int _limit = 10;
int _page = 1; int _page = 1;
...@@ -27,7 +27,7 @@ class UserCouponController extends GetxController { ...@@ -27,7 +27,7 @@ class UserCouponController extends GetxController {
void getOverCoupons() { void getOverCoupons() {
_noMore = true; _noMore = true;
_page = 1; _page = 1;
type = 2; type = 1;
_getCoupon(); _getCoupon();
} }
......
...@@ -2,21 +2,227 @@ part of user_edit_note; ...@@ -2,21 +2,227 @@ part of user_edit_note;
class UserEditNoteController extends GetxController { class UserEditNoteController extends GetxController {
final NoteModel model;
final String bookId;
late TextEditingController contentInput;
UserEditNoteController(this.model,this.bookId){
_setDuration();
contentInput = TextEditingController(text: model.noteContent?.text?.content);
}
// 录音
final FlutterSoundRecorder _mRecorder = FlutterSoundRecorder();
just_audio.AudioPlayer audioPlayer = just_audio.AudioPlayer();
// 录音开始 // 录音开始
bool startRecording = false; bool startRecording = false;
// 笔记是否公开 // 笔记是否公开
bool isPublic = false; bool isPublic = false;
bool initRecorder = false;
String currentDuration = '';
late MediaModel currentPlayMediaModel = MediaModel();
@override
void onInit() {
super.onInit();
}
@override
void onClose() {
contentInput.dispose();
audioPlayer.dispose();
super.onClose();
}
// 设置笔记是否公开 // 设置笔记是否公开
void setIsPublic(){ void setIsPublic(){
isPublic = !isPublic; isPublic = !isPublic;
update(); update();
} }
// 配置音频时长
void _setDuration() async {
for(MediaModel mediaModel in model.noteContent!.audio!){
Duration? duration = await just_audio.AudioPlayer().setUrl(mediaModel.content??'');
mediaModel.duration = Tools.formatDuration(duration!);
}
update();
}
// 删除图片
void delImage(MediaModel mediaModel){
model.noteContent!.image!.remove(mediaModel);
update();
}
// 删除音频
void delAudio(MediaModel mediaModel){
model.noteContent!.audio!.remove(mediaModel);
// 新加的录音 如果删除要删除源文件
if(mediaModel.id == 0){
}
update();
}
// 添加音频
void addAudio(String path,String duration){
MediaModel mediaModel = MediaModel(path: path,id: 0,duration: duration);
model.noteContent!.audio!.add(mediaModel);
update();
}
// 添加图片
void addImage(String path){
MediaModel mediaModel = MediaModel(path: path,id: 0);
model.noteContent!.image!.add(mediaModel);
update();
}
// 初始化录音组件
Future<void> openTheRecorder() async {
if(!initRecorder){
// 获取权限
if(await Access.microphone()){
await _mRecorder.openRecorder();
final session = await AudioSession.instance;
await session.configure(AudioSessionConfiguration(
avAudioSessionCategory: AVAudioSessionCategory.playAndRecord,
avAudioSessionCategoryOptions:
AVAudioSessionCategoryOptions.allowBluetooth |
AVAudioSessionCategoryOptions.defaultToSpeaker,
avAudioSessionMode: AVAudioSessionMode.spokenAudio,
avAudioSessionRouteSharingPolicy:
AVAudioSessionRouteSharingPolicy.defaultPolicy,
avAudioSessionSetActiveOptions: AVAudioSessionSetActiveOptions.none,
androidAudioAttributes: const AndroidAudioAttributes(
contentType: AndroidAudioContentType.speech,
flags: AndroidAudioFlags.none,
usage: AndroidAudioUsage.voiceCommunication,
),
androidAudioFocusGainType: AndroidAudioFocusGainType.gain,
androidWillPauseWhenDucked: true,
));
}
// 没有权限
else {
}
}
initRecorder = true;
}
// 开启录音
void record() async {
openTheRecorder();
update();
startRecording = true;
String filePath = await Tools.getDirectory();
String fileName = Tools.generateVoiceFileName();
_mRecorder.startRecorder(
toFile: '$filePath/$fileName',
audioSource: sound_recorder_platform.AudioSource.microphone,
codec: Codec.aacMP4,
);
}
// 停止录音
void stopRecorder() async{
startRecording = false;
final path = await _mRecorder.stopRecorder();
var duration = await audioPlayer.setFilePath(path!);
print('-----duration---------------------$duration------');
// 添加到数组
addAudio(path, Tools.formatDuration(duration!));
}
// 播放音频
void playAudio(MediaModel mediaModel){
if(audioPlayer.playerState.playing){
audioPlayer.stop();
mediaModel.currentDuration = '0:00:00';
// if(currentPlayMediaModel.id == mediaModel.id){
// return;
// }
}
// 本地音频
if (mediaModel.id == 0){
audioPlayer.setFilePath(mediaModel.path);
}
// 远程音频
else {
audioPlayer.setUrl(mediaModel.content??'');
}
audioPlayer.play();
audioPlayer.positionStream.listen((position) {
String temp = Tools.formatDuration(position);
Console.log('播放时间---------------------$temp');
mediaModel.currentDuration = temp;
update();
});
// currentPlayMediaModel = mediaModel;
}
// 上传文件
Future<String> upload({
required String path
}) async {
// String result = await CommonAPI.upload(path:path,fileTypes: 'comment');
// return result;
OssTool tool = OssTool('zxts-comment-file');
final response = await tool.putObjectFile(path);
print('------response--------------------------${response.realUri}');
return response.realUri.toString();
}
// 提交
Future<bool> submit() async { Future<bool> submit() async {
return true; // 循环上传图片获取地址
for(MediaModel mediaModel in model.noteContent!.image!){
if (mediaModel.id == 0){
final url = await upload(path: mediaModel.path);
mediaModel.content = url;
}
}
// 循环上传音频获取地址
for(MediaModel mediaModel in model.noteContent!.audio!){
if (mediaModel.id == 0){
final url = await upload(path: mediaModel.path);
mediaModel.content = url;
}
}
// 组织图片
List<Map> images = [];
for(MediaModel mediaModel in model.noteContent!.image!){
images.add( mediaModel.toJson());
}
// 组织音频
List<Map> audios = [];
for(MediaModel mediaModel in model.noteContent!.audio!){
audios.add( mediaModel.toJson());
} }
model.noteContent!.text!.content = contentInput.text;
Map<String,dynamic> contentMap = {
'text':model.noteContent!.text!.toJson(),
'audio':audios,
'image':images
};
final result = MineAPI.editNotes(
content: model.content??'',
notesId: model.notesId.toString(),
bookId: bookId,
noteContent: jsonEncode(contentMap)
);
return result;
}
} }
\ No newline at end of file
library user_edit_note; library user_edit_note;
import 'dart:convert';
import 'package:audio_session/audio_session.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_book/apis/index.dart';
import 'package:flutter_book/theme.dart';
import 'package:flutter_book/utils/index.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_sound/public/flutter_sound_recorder.dart';
import 'package:flutter_sound_platform_interface/flutter_sound_platform_interface.dart';
import 'package:flutter_sound_platform_interface/flutter_sound_recorder_platform_interface.dart' as sound_recorder_platform;
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:go_router/go_router.dart';
import 'package:just_audio/just_audio.dart' as just_audio;
import 'package:just_audio/just_audio.dart';
import 'dart:async';
import '../../models/index.dart';
import '../../theme.dart'; import '../../theme.dart';
import '../../utils/index.dart'; import '../../utils/index.dart';
import '../../widgets/index.dart'; import '../../widgets/index.dart';
......
part of user_edit_note; part of user_edit_note;
class UserEditNotePage extends StatefulWidget { class UserEditNotePage extends StatefulWidget {
const UserEditNotePage({Key? key}) : super(key: key); final NoteModel model;
final String bookId;
const UserEditNotePage({
Key? key,
required this.model,
required this.bookId,
}) : super(key: key);
@override @override
State<UserEditNotePage> createState() => _UserEditNotePageState(); State<UserEditNotePage> createState() => _UserEditNotePageState();
...@@ -11,7 +17,7 @@ class _UserEditNotePageState extends State<UserEditNotePage> { ...@@ -11,7 +17,7 @@ class _UserEditNotePageState extends State<UserEditNotePage> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return GetBuilder<UserEditNoteController>( return GetBuilder<UserEditNoteController>(
init: UserEditNoteController(), init: UserEditNoteController(widget.model,widget.bookId),
builder:(controller)=> Scaffold( builder:(controller)=> Scaffold(
appBar: AppBar( appBar: AppBar(
title: const Text('笔记编辑'), title: const Text('笔记编辑'),
...@@ -19,13 +25,11 @@ class _UserEditNotePageState extends State<UserEditNotePage> { ...@@ -19,13 +25,11 @@ class _UserEditNotePageState extends State<UserEditNotePage> {
), ),
body: Container( body: Container(
color: Colors.white, color: Colors.white,
margin: EdgeInsets.symmetric(horizontal: 15.w), margin: EdgeInsets.symmetric(horizontal: 10.w),
child: Column( child: Stack(
children: [ children: [
ClipRRect( Container(
borderRadius: BorderRadius.circular(4.w), // color: Colours.cF8,
child: Container(
color: Colours.cF8,
constraints: BoxConstraints( constraints: BoxConstraints(
minHeight: 100.w minHeight: 100.w
), ),
...@@ -33,9 +37,9 @@ class _UserEditNotePageState extends State<UserEditNotePage> { ...@@ -33,9 +37,9 @@ class _UserEditNotePageState extends State<UserEditNotePage> {
children: [ children: [
TextField( TextField(
// focusNode: widget.controller.discussContentFocusNode, // focusNode: widget.controller.discussContentFocusNode,
// maxLines: null, maxLines: null,
// autofocus: widget.controller.chatType ==0?false:true, autofocus: true,
// controller: widget.controller.contentInput, controller: controller.contentInput,
decoration: InputDecoration( decoration: InputDecoration(
border: InputBorder.none, border: InputBorder.none,
enabledBorder: InputBorder.none, enabledBorder: InputBorder.none,
...@@ -43,7 +47,7 @@ class _UserEditNotePageState extends State<UserEditNotePage> { ...@@ -43,7 +47,7 @@ class _UserEditNotePageState extends State<UserEditNotePage> {
hintText: '请输入内容', hintText: '请输入内容',
hintStyle:TextStyle(fontSize: 12.w,height: 1.5,color: Colours.c9,), hintStyle:TextStyle(fontSize: 12.w,height: 1.5,color: Colours.c9,),
filled: true, filled: true,
fillColor: Colours.cF8, // fillColor: Colours.cF8,
), ),
), ),
Column( Column(
...@@ -53,12 +57,13 @@ class _UserEditNotePageState extends State<UserEditNotePage> { ...@@ -53,12 +57,13 @@ class _UserEditNotePageState extends State<UserEditNotePage> {
physics: const NeverScrollableScrollPhysics(), physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true, shrinkWrap: true,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 6, crossAxisCount: 3,
crossAxisSpacing: 2.w, crossAxisSpacing: 2.w,
mainAxisSpacing: 2.w, mainAxisSpacing: 2.w,
childAspectRatio: 1 childAspectRatio: 1
), ),
itemBuilder: (BuildContext context, int index) { itemBuilder: (BuildContext context, int index) {
MediaModel mediaModel = controller.model.noteContent!.image![index];
return Stack( return Stack(
children: [ children: [
Positioned( Positioned(
...@@ -66,24 +71,25 @@ class _UserEditNotePageState extends State<UserEditNotePage> { ...@@ -66,24 +71,25 @@ class _UserEditNotePageState extends State<UserEditNotePage> {
right: 0, right: 0,
top:0, top:0,
bottom: 0, bottom: 0,
child: Container() child: mediaModel.id == 0?CustomImage.file(url:mediaModel.path): CustomImage.network(url: mediaModel.content??'')
), ),
Positioned( Positioned(
right: 5.w, right: 0.w,
top: 5.w, top: 0.w,
child: GestureDetector( child: GestureDetector(
onTap: (){ onTap: (){
controller.delImage(mediaModel);
}, },
child: Image.asset('assets/images/del_close.png',width: 12.w,height: 12.w,) child: Image.asset('assets/images/media_del.png',width: 17.w,height: 17.w,)
) )
) )
], ],
); );
}, },
itemCount: 3, itemCount: controller.model.noteContent?.image?.length,
), ),
Container( Container(
color: Colors.red, // color: Colors.red,
child: MediaQuery.removePadding( child: MediaQuery.removePadding(
context: context, context: context,
removeTop: true, removeTop: true,
...@@ -91,28 +97,49 @@ class _UserEditNotePageState extends State<UserEditNotePage> { ...@@ -91,28 +97,49 @@ class _UserEditNotePageState extends State<UserEditNotePage> {
physics: const NeverScrollableScrollPhysics(), physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true, shrinkWrap: true,
itemBuilder: (BuildContext context, int index){ itemBuilder: (BuildContext context, int index){
MediaModel mediaModel = controller.model.noteContent!.audio![index];
return Container( return Container(
height: 20.w, // height: 20.w,
margin: EdgeInsets.only(right: 130.w), margin: EdgeInsets.only(right: 130.w,),
child: Container( child: Stack(
margin: EdgeInsets.only(top: 5.w), children: [
padding: EdgeInsets.only(right:20.w,left: 10.w), Container(
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10.w), borderRadius: BorderRadius.circular(10.w),
color: Colours.cF9, color: Colours.cF9,
), ),
padding: EdgeInsets.only(right:20.w,left: 10.w),
margin: EdgeInsets.only(top: 10.w,right: 10.w),
height: 20,
child: Row( child: Row(
// mainAxisSize: MainAxisSize.min, // mainAxisSize: MainAxisSize.min,
mainAxisAlignment:MainAxisAlignment.spaceBetween, mainAxisAlignment:MainAxisAlignment.spaceBetween,
children: [ children: [
Image.asset('assets/images/audio.png'), GestureDetector(
Text('0:00/1:52',style: TextStyle(fontSize: 10.w,height: 1.4,color: Colours.c9),) onTap:(){
controller.playAudio(mediaModel);
},
child: Image.asset('assets/images/audio.png')
),
Text('${mediaModel.currentDuration}/${mediaModel.duration}',style: TextStyle(fontSize: 10.w,height: 1.4,color: Colours.c9),)
], ],
), ),
), ),
Positioned(
right: 6,
top: 6,
child: GestureDetector(
onTap: (){
controller.delAudio(mediaModel);
},
child: Image.asset('assets/images/media_del.png',width: 12.w,height: 12.w,)
)
)
],
),
); );
}, },
itemCount: 3, itemCount: controller.model.noteContent?.audio?.length,
), ),
), ),
) )
...@@ -121,8 +148,13 @@ class _UserEditNotePageState extends State<UserEditNotePage> { ...@@ -121,8 +148,13 @@ class _UserEditNotePageState extends State<UserEditNotePage> {
], ],
), ),
), ),
), Visibility(
Container( visible: true,
child: Positioned(
left: 10,
right: 10,
bottom: 0,
child: Container(
padding: EdgeInsets.symmetric(vertical: 10.w), padding: EdgeInsets.symmetric(vertical: 10.w),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
...@@ -131,23 +163,23 @@ class _UserEditNotePageState extends State<UserEditNotePage> { ...@@ -131,23 +163,23 @@ class _UserEditNotePageState extends State<UserEditNotePage> {
Row( Row(
children: [ children: [
GestureDetector( GestureDetector(
// onTap: () async{ onTap: () async{
// final assets = await AssetsPicker.image( final assets = await AssetsPicker.image(
// context: context, context: context,
// ); );
// widget.controller.addDiscussInputImages(assets!.path); controller.addImage(assets!.path);
// }, },
child: Image.asset('assets/images/read_add_img.png')), child: Image.asset('assets/images/read_add_img.png')),
Gaps.hGaps10, Gaps.hGaps10,
GestureDetector( GestureDetector(
onTap: () async { onTap: () async {
// if(widget.controller.startRecording){ if(controller.startRecording){
// widget.controller.stopRecorder(); controller.stopRecorder();
// } }
// else { else {
// widget.controller.record(); controller.record();
//
// } }
}, },
child: Image.asset(controller.startRecording?'assets/images/stop.png':'assets/images/read_add_audio.png') child: Image.asset(controller.startRecording?'assets/images/stop.png':'assets/images/read_add_audio.png')
), ),
...@@ -168,8 +200,13 @@ class _UserEditNotePageState extends State<UserEditNotePage> { ...@@ -168,8 +200,13 @@ class _UserEditNotePageState extends State<UserEditNotePage> {
], ],
), ),
GestureDetector( GestureDetector(
onTap: (){ onTap: () async{
controller.submit(); final result = await controller.submit();
if (result){
Tools.unfocus();
Toast.show('修改成功');
context.pop();
}
}, },
child: Container( child: Container(
decoration: BoxDecoration( decoration: BoxDecoration(
...@@ -187,6 +224,8 @@ class _UserEditNotePageState extends State<UserEditNotePage> { ...@@ -187,6 +224,8 @@ class _UserEditNotePageState extends State<UserEditNotePage> {
) )
], ],
), ),
),
),
) )
], ],
) )
......
...@@ -11,6 +11,8 @@ class UserNotesDesController extends GetxController { ...@@ -11,6 +11,8 @@ class UserNotesDesController extends GetxController {
controlFinishRefresh: true, controlFinishRefresh: true,
); );
just_audio.AudioPlayer audioPlayer = just_audio.AudioPlayer();
final int _limit = 10; final int _limit = 10;
int _page = 1; int _page = 1;
bool _noMore = false; bool _noMore = false;
...@@ -25,12 +27,41 @@ class UserNotesDesController extends GetxController { ...@@ -25,12 +27,41 @@ class UserNotesDesController extends GetxController {
@override @override
void onClose() { void onClose() {
refreshController.dispose(); refreshController.dispose();
audioPlayer.dispose();
super.onClose(); super.onClose();
} }
// 播放音频
void playAudio(MediaModel mediaModel){
if(audioPlayer.playerState.playing){
audioPlayer.stop();
mediaModel.currentDuration = '0:00:00';
// if(currentPlayMediaModel.id == mediaModel.id){
// return;
// }
}
// 本地音频
if (mediaModel.id == 0){
audioPlayer.setFilePath(mediaModel.path);
}
// 远程音频
else {
audioPlayer.setUrl(mediaModel.content??'');
}
audioPlayer.play();
audioPlayer.positionStream.listen((position) {
String temp = Tools.formatDuration(position);
Console.log('播放时间---------------------$temp');
mediaModel.currentDuration = temp;
update();
});
// currentPlayMediaModel = mediaModel;
}
void delNotes({required String notesId,required String bookId}) async { void delNotes({required String notesId,required String bookId}) async {
final result = await MineAPI.delNotes(notesId: notesId, bookId: bookId); final result = await MineAPI.delNotes(notesId: notesId, bookId: bookId);
if (result){ if (result){
Toast.show('删除笔记成功');
onRefresh(); onRefresh();
} }
} }
......
...@@ -46,15 +46,17 @@ class _BuildListPageState extends State<BuildListPage> with AutomaticKeepAliveCl ...@@ -46,15 +46,17 @@ class _BuildListPageState extends State<BuildListPage> with AutomaticKeepAliveCl
else if(model.types == 3){ else if(model.types == 3){
return BuildNote(model: model, return BuildNote(model: model,
onTapDel: (){ onTapDel: (){
print('---------删除--------');
controller.delNotes(notesId: model.notesId.toString(), bookId:widget.model.bookId.toString()); controller.delNotes(notesId: model.notesId.toString(), bookId:widget.model.bookId.toString());
}, },
onTapEdit: (){ onTapEdit: (){
print('---------编辑--------'); context.pushNamed(Routes.editNote,extra: model,queryParameters: {'book_id':widget.model.bookId.toString()});
context.pushNamed(Routes.editNote); },
onTapAudio: (mediaModel){
controller.playAudio(mediaModel);
}, },
); );
} }
return null;
}, },
itemCount: controller.notes.length, itemCount: controller.notes.length,
), ),
......
...@@ -4,11 +4,13 @@ class BuildNote extends StatelessWidget { ...@@ -4,11 +4,13 @@ class BuildNote extends StatelessWidget {
final NoteModel model; final NoteModel model;
final void Function()? onTapDel; final void Function()? onTapDel;
final void Function()? onTapEdit; final void Function()? onTapEdit;
final void Function(MediaModel mediaModel)? onTapAudio;
const BuildNote({ const BuildNote({
Key? key, Key? key,
required this.model, required this.model,
this.onTapDel, this.onTapDel,
this.onTapEdit this.onTapEdit,
this.onTapAudio
}) : super(key: key); }) : super(key: key);
@override @override
...@@ -35,7 +37,6 @@ class BuildNote extends StatelessWidget { ...@@ -35,7 +37,6 @@ class BuildNote extends StatelessWidget {
SlidableAction( SlidableAction(
// An action can be bigger than the others. // An action can be bigger than the others.
onPressed: (BuildContext context){ onPressed: (BuildContext context){
print('---------编辑1--------');
if (onTapEdit !=null) onTapEdit!(); if (onTapEdit !=null) onTapEdit!();
}, },
...@@ -47,7 +48,6 @@ class BuildNote extends StatelessWidget { ...@@ -47,7 +48,6 @@ class BuildNote extends StatelessWidget {
SlidableAction( SlidableAction(
// An action can be bigger than the others. // An action can be bigger than the others.
onPressed: (BuildContext context){ onPressed: (BuildContext context){
print('---------删除1--------');
if (onTapDel !=null) onTapDel!(); if (onTapDel !=null) onTapDel!();
}, },
backgroundColor: const Color(0xFFAE1414), backgroundColor: const Color(0xFFAE1414),
...@@ -96,7 +96,7 @@ class BuildNote extends StatelessWidget { ...@@ -96,7 +96,7 @@ class BuildNote extends StatelessWidget {
Widget _buildImageGridView(){ Widget _buildImageGridView(){
return GridView.builder( return GridView.builder(
// padding: const EdgeInsets.only(left: 13,top: 10), // padding: const EdgeInsets.only(left: 13,top: 10),
physics: NeverScrollableScrollPhysics(), physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true, shrinkWrap: true,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 6, crossAxisCount: 6,
...@@ -105,10 +105,7 @@ class BuildNote extends StatelessWidget { ...@@ -105,10 +105,7 @@ class BuildNote extends StatelessWidget {
childAspectRatio: 1 childAspectRatio: 1
), ),
itemBuilder: (BuildContext context, int index) { itemBuilder: (BuildContext context, int index) {
return Container( return CustomImage.network(url: model.noteContent!.image![index].content??'',fit: BoxFit.cover,);
// color: Colors.red,
child: CustomImage.network(url: model.noteContent!.image![index].content??'',fit: BoxFit.cover,),
);
}, },
itemCount: model.noteContent?.image?.length, itemCount: model.noteContent?.image?.length,
); );
...@@ -134,7 +131,12 @@ class BuildNote extends StatelessWidget { ...@@ -134,7 +131,12 @@ class BuildNote extends StatelessWidget {
// mainAxisSize: MainAxisSize.min, // mainAxisSize: MainAxisSize.min,
mainAxisAlignment:MainAxisAlignment.spaceBetween, mainAxisAlignment:MainAxisAlignment.spaceBetween,
children: [ children: [
Image.asset('assets/images/audio.png'), GestureDetector(
onTap: (){
if (onTapAudio !=null) onTapAudio!(mediaModel);
},
child: Image.asset('assets/images/audio.png')
),
Text('0:00/${mediaModel.duration}',style: TextStyle(fontSize: 10.w,height: 1.4,color: Colours.c9),) Text('0:00/${mediaModel.duration}',style: TextStyle(fontSize: 10.w,height: 1.4,color: Colours.c9),)
], ],
), ),
......
...@@ -560,7 +560,7 @@ abstract class Routes { ...@@ -560,7 +560,7 @@ abstract class Routes {
pageBuilder: (context, state) =>CupertinoPage( pageBuilder: (context, state) =>CupertinoPage(
name: state.uri.toString(), name: state.uri.toString(),
key: state.pageKey, key: state.pageKey,
child: const UserEditNotePage() child: UserEditNotePage(model: state.extra as NoteModel,bookId: state.uri.queryParameters['book_id'].toString(),)
) )
), ),
] ]
......
...@@ -103,7 +103,7 @@ class HttpService extends GetxService { ...@@ -103,7 +103,7 @@ class HttpService extends GetxService {
// 如果启用缓存,将cacheEnabled参数添加到请求选项中 // 如果启用缓存,将cacheEnabled参数添加到请求选项中
if(cacheEnabled){ if(cacheEnabled){
requestOptions.extra ??= {}; requestOptions.extra ??= {};
requestOptions.extra!['cacheEnabled'] = true; requestOptions.extra!['cacheEnabled'] = false;
} }
final response = await _dio.post( final response = await _dio.post(
url, url,
...@@ -275,15 +275,15 @@ class _RequestInterceptor extends Interceptor { ...@@ -275,15 +275,15 @@ class _RequestInterceptor extends Interceptor {
break; break;
case 404: case 404:
msg = '$statusCode - Server not found'; msg = '$statusCode - Server not found';
CustomToast.fail(msg); // CustomToast.fail(msg);
break; break;
case 500: case 500:
msg = '$statusCode - Server error'; msg = '$statusCode - Server error';
CustomToast.fail(msg); // CustomToast.fail(msg);
break; break;
case 502: case 502:
msg = '$statusCode - Bad gateway'; msg = '$statusCode - Bad gateway';
CustomToast.fail(msg); // CustomToast.fail(msg);
break; break;
default: default:
// if (code == 901) UserStore.to.logout(); // if (code == 901) UserStore.to.logout();
...@@ -311,7 +311,7 @@ class _RequestInterceptor extends Interceptor { ...@@ -311,7 +311,7 @@ class _RequestInterceptor extends Interceptor {
final result = await HttpService.to.post( final result = await HttpService.to.post(
'/v1/members/login/getToken', '/v1/members/login/getToken',
params: { params: {
'access_token':UserStore.to.accessToken 'access_token':StorageService.to.getString(kLocalAccessToken)
} }
); );
if (result.data is Map) { if (result.data is Map) {
...@@ -366,7 +366,7 @@ class _CacheInterceptor extends Interceptor { ...@@ -366,7 +366,7 @@ class _CacheInterceptor extends Interceptor {
final requestBody = response.requestOptions.data.toString(); final requestBody = response.requestOptions.data.toString();
// 将 GET 请求的参数和请求体参数拼接成缓存的键 // 将 GET 请求的参数和请求体参数拼接成缓存的键
final cacheKey = requestBody.isEmpty ? url : '$url?$requestBody'; final cacheKey = requestBody.isEmpty ? url : '$url?$requestBody';
Console.log('----------cacheKey-----------------------$cacheKey'); // Console.log('----------cacheKey-----------------------$cacheKey');
// 将响应数据转换为字符串,并将其编码为字节列表 // 将响应数据转换为字符串,并将其编码为字节列表
List<int> bytes = utf8.encode(jsonEncode(response.data)); List<int> bytes = utf8.encode(jsonEncode(response.data));
Uint8List uint8List = Uint8List.fromList(bytes); Uint8List uint8List = Uint8List.fromList(bytes);
......
...@@ -35,6 +35,19 @@ abstract class Tools { ...@@ -35,6 +35,19 @@ abstract class Tools {
String twoDigitSeconds = twoDigits(duration.inSeconds.remainder(60)); String twoDigitSeconds = twoDigits(duration.inSeconds.remainder(60));
return "${duration.inHours}:$twoDigitMinutes:$twoDigitSeconds"; return "${duration.inHours}:$twoDigitMinutes:$twoDigitSeconds";
} }
static Future<String> getDirectory() async {
// getTemporaryDirectory
final directory = await getExternalStorageDirectory();
return directory!.path;
}
// 语音文件名称
static String generateVoiceFileName(){
DateTime now = DateTime.now();
String formattedDate = DateFormat('yyyyMMddHHmmss').format(now);
return 'voice_$formattedDate.mp4';
}
} }
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论