From 4b358e2215a993d918d5c9b57b259ae67d913b5e Mon Sep 17 00:00:00 2001 From: lcy <2503978335@qq.com> Date: Tue, 20 Jun 2023 20:19:44 +0800 Subject: [PATCH] feat:调整文件结构 --- lib/common/request/exception.dart | 1 - lib/home/bloc/home_bloc.dart | 14 -------------- lib/home/bloc/home_event.dart | 4 ---- lib/home/bloc/home_state.dart | 6 ------ lib/home/home_page.dart | 122 -------------------------------------------------------------------------------------------------------------------------- lib/home/widgets/home_lesson_item_widget.dart | 25 ------------------------- lib/home/widgets/home_tab_header_widget.dart | 131 ----------------------------------------------------------------------------------------------------------------------------------- lib/lessons/bloc/lesson_bloc.dart | 33 --------------------------------- lib/lessons/bloc/lesson_event.dart | 9 --------- lib/lessons/bloc/lesson_state.dart | 8 -------- lib/lessons/lesson_page.dart | 220 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- lib/lessons/widgets/lesson_item_widget.dart | 57 --------------------------------------------------------- lib/listen/bloc/listen_bloc.dart | 14 -------------- lib/listen/bloc/listen_event.dart | 4 ---- lib/listen/bloc/listen_state.dart | 6 ------ lib/listen/listen_page.dart | 51 --------------------------------------------------- lib/listen/widgets/listen_item_widget.dart | 80 -------------------------------------------------------------------------------- lib/login/forgetpwd/bloc/forget_pwd_home_bloc.dart | 71 ----------------------------------------------------------------------- lib/login/forgetpwd/bloc/forget_pwd_home_event.dart | 12 ------------ lib/login/forgetpwd/bloc/forget_pwd_home_state.dart | 12 ------------ lib/login/forgetpwd/forget_password_home_page.dart | 169 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- lib/login/loginpage/bloc/login_bloc.dart | 171 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- lib/login/loginpage/bloc/login_event.dart | 16 ---------------- lib/login/loginpage/bloc/login_state.dart | 23 ----------------------- lib/login/loginpage/login_page.dart | 313 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- lib/login/loginpage/time_widget.dart | 93 --------------------------------------------------------------------------------------------- lib/login/setpwd/bloc/set_pwd_bloc.dart | 121 ------------------------------------------------------------------------------------------------------------------------- lib/login/setpwd/bloc/set_pwd_event.dart | 11 ----------- lib/login/setpwd/bloc/set_pwd_state.dart | 18 ------------------ lib/login/setpwd/set_pwd_page.dart | 196 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- lib/pages/home/bloc/home_bloc.dart | 14 ++++++++++++++ lib/pages/home/bloc/home_event.dart | 4 ++++ lib/pages/home/bloc/home_state.dart | 6 ++++++ lib/pages/home/home_page.dart | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/pages/home/widgets/home_lesson_item_widget.dart | 25 +++++++++++++++++++++++++ lib/pages/home/widgets/home_tab_header_widget.dart | 131 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/pages/lessons/bloc/lesson_bloc.dart | 33 +++++++++++++++++++++++++++++++++ lib/pages/lessons/bloc/lesson_event.dart | 9 +++++++++ lib/pages/lessons/bloc/lesson_state.dart | 8 ++++++++ lib/pages/lessons/lesson_page.dart | 221 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/pages/lessons/widgets/lesson_item_widget.dart | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/pages/listen/bloc/listen_bloc.dart | 14 ++++++++++++++ lib/pages/listen/bloc/listen_event.dart | 4 ++++ lib/pages/listen/bloc/listen_state.dart | 6 ++++++ lib/pages/listen/listen_page.dart | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/pages/listen/widgets/listen_item_widget.dart | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/pages/login/forgetpwd/bloc/forget_pwd_home_bloc.dart | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/pages/login/forgetpwd/bloc/forget_pwd_home_event.dart | 12 ++++++++++++ lib/pages/login/forgetpwd/bloc/forget_pwd_home_state.dart | 12 ++++++++++++ lib/pages/login/forgetpwd/forget_password_home_page.dart | 170 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/pages/login/loginpage/bloc/login_bloc.dart | 171 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/pages/login/loginpage/bloc/login_event.dart | 16 ++++++++++++++++ lib/pages/login/loginpage/bloc/login_state.dart | 23 +++++++++++++++++++++++ lib/pages/login/loginpage/login_page.dart | 314 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/pages/login/loginpage/time_widget.dart | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/pages/login/setpwd/bloc/set_pwd_bloc.dart | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/pages/login/setpwd/bloc/set_pwd_event.dart | 11 +++++++++++ lib/pages/login/setpwd/bloc/set_pwd_state.dart | 18 ++++++++++++++++++ lib/pages/login/setpwd/set_pwd_page.dart | 197 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/pages/practice/chosetopic/topicpicture/bloc/topic_picture_bloc.dart | 41 +++++++++++++++++++++++++++++++++++++++++ lib/pages/practice/chosetopic/topicpicture/bloc/topic_picture_event.dart | 14 ++++++++++++++ lib/pages/practice/chosetopic/topicpicture/bloc/topic_picture_state.dart | 10 ++++++++++ lib/pages/practice/chosetopic/topicpicture/topic_picture_page.dart | 141 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/pages/practice/chosetopic/topicword/bloc/topic_word_bloc.dart | 41 +++++++++++++++++++++++++++++++++++++++++ lib/pages/practice/chosetopic/topicword/bloc/topic_word_event.dart | 14 ++++++++++++++ lib/pages/practice/chosetopic/topicword/bloc/topic_word_state.dart | 10 ++++++++++ lib/pages/practice/chosetopic/topicword/topic_word_page.dart | 163 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/pages/practice/voicetopic/voicepicture/bloc/voice_pic_bloc.dart | 39 +++++++++++++++++++++++++++++++++++++++ lib/pages/practice/voicetopic/voicepicture/bloc/voice_pic_event.dart | 14 ++++++++++++++ lib/pages/practice/voicetopic/voicepicture/bloc/voice_pic_state.dart | 10 ++++++++++ lib/pages/practice/voicetopic/voicepicture/voice_pic_page.dart | 151 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/pages/practice/voicetopic/voiceword/bloc/voice_word_bloc.dart | 41 +++++++++++++++++++++++++++++++++++++++++ lib/pages/practice/voicetopic/voiceword/bloc/voice_word_event.dart | 14 ++++++++++++++ lib/pages/practice/voicetopic/voiceword/bloc/voice_word_state.dart | 10 ++++++++++ lib/pages/practice/voicetopic/voiceword/voice_word_page.dart | 160 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/pages/practice/widgets/practice_header_widget.dart | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/pages/repeatafter/bloc/repeat_after_bloc.dart | 23 +++++++++++++++++++++++ lib/pages/repeatafter/bloc/repeat_after_event.dart | 4 ++++ lib/pages/repeatafter/bloc/repeat_after_state.dart | 8 ++++++++ lib/pages/repeatafter/repeat_after_page.dart | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/pages/repeatafter/widgets/repeat_after_item.dart | 137 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/pages/shop/exchane/bloc/exchange_lesson_bloc.dart | 37 +++++++++++++++++++++++++++++++++++++ lib/pages/shop/exchane/bloc/exchange_lesson_event.dart | 8 ++++++++ lib/pages/shop/exchane/bloc/exchange_lesson_state.dart | 13 +++++++++++++ lib/pages/shop/exchane/exchange_lesson_page.dart | 133 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/pages/shop/exchangelist/bloc/exchange_list_bloc.dart | 15 +++++++++++++++ lib/pages/shop/exchangelist/bloc/exchange_list_event.dart | 4 ++++ lib/pages/shop/exchangelist/bloc/exchange_list_state.dart | 6 ++++++ lib/pages/shop/exchangelist/exchange_lesson_list_page.dart | 47 +++++++++++++++++++++++++++++++++++++++++++++++ lib/pages/shop/exchangelist/widgets/exchange_list_item.dart | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/pages/shop/home/bloc/shop_home_bloc.dart | 15 +++++++++++++++ lib/pages/shop/home/bloc/shop_home_event.dart | 4 ++++ lib/pages/shop/home/bloc/shop_home_state.dart | 6 ++++++ lib/pages/shop/home/shop_home_page.dart | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/pages/shop/home/widgets/lesson_card_item.dart | 111 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/pages/tab/blocs/tab_bloc.dart | 18 ++++++++++++++++++ lib/pages/tab/blocs/tab_event.dart | 11 +++++++++++ lib/pages/tab/blocs/tab_state.dart | 9 +++++++++ lib/pages/tab/tab_page.dart | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/pages/user/bloc/user_bloc.dart | 13 +++++++++++++ lib/pages/user/bloc/user_event.dart | 4 ++++ lib/pages/user/bloc/user_state.dart | 6 ++++++ lib/pages/user/user_page.dart | 18 ++++++++++++++++++ lib/pages/video/lookvideo/bloc/look_video_bloc.dart | 17 +++++++++++++++++ lib/pages/video/lookvideo/bloc/look_video_event.dart | 4 ++++ lib/pages/video/lookvideo/bloc/look_video_state.dart | 8 ++++++++ lib/pages/video/lookvideo/look_video_page.dart | 40 ++++++++++++++++++++++++++++++++++++++++ lib/pages/video/lookvideo/widgets/video_opera_widget.dart | 184 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/pages/video/lookvideo/widgets/video_widget.dart | 196 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/pages/voiceanswer/bloc/voice_answer_bloc.dart | 13 +++++++++++++ lib/pages/voiceanswer/bloc/voice_answer_event.dart | 4 ++++ lib/pages/voiceanswer/bloc/voice_answer_state.dart | 6 ++++++ lib/pages/voiceanswer/voice_answer_page.dart | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/practice/chosetopic/topicpicture/bloc/topic_picture_bloc.dart | 41 ----------------------------------------- lib/practice/chosetopic/topicpicture/bloc/topic_picture_event.dart | 14 -------------- lib/practice/chosetopic/topicpicture/bloc/topic_picture_state.dart | 10 ---------- lib/practice/chosetopic/topicpicture/topic_picture_page.dart | 141 --------------------------------------------------------------------------------------------------------------------------------------------- lib/practice/chosetopic/topicword/bloc/topic_word_bloc.dart | 41 ----------------------------------------- lib/practice/chosetopic/topicword/bloc/topic_word_event.dart | 14 -------------- lib/practice/chosetopic/topicword/bloc/topic_word_state.dart | 10 ---------- lib/practice/chosetopic/topicword/topic_word_page.dart | 162 ------------------------------------------------------------------------------------------------------------------------------------------------------------------ lib/practice/voicetopic/voicepicture/bloc/voice_pic_bloc.dart | 39 --------------------------------------- lib/practice/voicetopic/voicepicture/bloc/voice_pic_event.dart | 14 -------------- lib/practice/voicetopic/voicepicture/bloc/voice_pic_state.dart | 10 ---------- lib/practice/voicetopic/voicepicture/voice_pic_page.dart | 150 ------------------------------------------------------------------------------------------------------------------------------------------------------ lib/practice/voicetopic/voiceword/bloc/voice_word_bloc.dart | 41 ----------------------------------------- lib/practice/voicetopic/voiceword/bloc/voice_word_event.dart | 14 -------------- lib/practice/voicetopic/voiceword/bloc/voice_word_state.dart | 10 ---------- lib/practice/voicetopic/voiceword/voice_word_page.dart | 159 --------------------------------------------------------------------------------------------------------------------------------------------------------------- lib/practice/widgets/practice_header_widget.dart | 59 ----------------------------------------------------------- lib/repeatafter/bloc/repeat_after_bloc.dart | 23 ----------------------- lib/repeatafter/bloc/repeat_after_event.dart | 4 ---- lib/repeatafter/bloc/repeat_after_state.dart | 8 -------- lib/repeatafter/repeat_after_page.dart | 65 ----------------------------------------------------------------- lib/repeatafter/widgets/repeat_after_item.dart | 137 ----------------------------------------------------------------------------------------------------------------------------------------- lib/route/route.dart | 37 +++++++++++++++++++------------------ lib/shop/exchane/bloc/exchange_lesson_bloc.dart | 37 ------------------------------------- lib/shop/exchane/bloc/exchange_lesson_event.dart | 8 -------- lib/shop/exchane/bloc/exchange_lesson_state.dart | 13 ------------- lib/shop/exchane/exchange_lesson_page.dart | 133 ------------------------------------------------------------------------------------------------------------------------------------- lib/shop/exchangelist/bloc/exchange_list_bloc.dart | 15 --------------- lib/shop/exchangelist/bloc/exchange_list_event.dart | 4 ---- lib/shop/exchangelist/bloc/exchange_list_state.dart | 6 ------ lib/shop/exchangelist/exchange_lesson_list_page.dart | 47 ----------------------------------------------- lib/shop/exchangelist/widgets/exchange_list_item.dart | 124 ---------------------------------------------------------------------------------------------------------------------------- lib/shop/home/bloc/shop_home_bloc.dart | 15 --------------- lib/shop/home/bloc/shop_home_event.dart | 4 ---- lib/shop/home/bloc/shop_home_state.dart | 6 ------ lib/shop/home/shop_home_page.dart | 81 --------------------------------------------------------------------------------- lib/shop/home/widgets/lesson_card_item.dart | 111 --------------------------------------------------------------------------------------------------------------- lib/tab/blocs/tab_bloc.dart | 18 ------------------ lib/tab/blocs/tab_event.dart | 11 ----------- lib/tab/blocs/tab_state.dart | 9 --------- lib/tab/tab_page.dart | 65 ----------------------------------------------------------------- lib/user/bloc/user_bloc.dart | 13 ------------- lib/user/bloc/user_event.dart | 4 ---- lib/user/bloc/user_state.dart | 6 ------ lib/user/user_page.dart | 18 ------------------ lib/video/lookvideo/bloc/look_video_bloc.dart | 17 ----------------- lib/video/lookvideo/bloc/look_video_event.dart | 4 ---- lib/video/lookvideo/bloc/look_video_state.dart | 8 -------- lib/video/lookvideo/look_video_page.dart | 39 --------------------------------------- lib/video/lookvideo/widgets/video_opera_widget.dart | 184 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- lib/video/lookvideo/widgets/video_widget.dart | 195 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- lib/voiceanswer/bloc/voice_answer_bloc.dart | 13 ------------- lib/voiceanswer/bloc/voice_answer_event.dart | 4 ---- lib/voiceanswer/bloc/voice_answer_state.dart | 6 ------ lib/voiceanswer/voice_answer_page.dart | 94 ---------------------------------------------------------------------------------------------- 168 files changed, 4521 insertions(+), 4507 deletions(-) delete mode 100644 lib/home/bloc/home_bloc.dart delete mode 100644 lib/home/bloc/home_event.dart delete mode 100644 lib/home/bloc/home_state.dart delete mode 100644 lib/home/home_page.dart delete mode 100644 lib/home/widgets/home_lesson_item_widget.dart delete mode 100644 lib/home/widgets/home_tab_header_widget.dart delete mode 100644 lib/lessons/bloc/lesson_bloc.dart delete mode 100644 lib/lessons/bloc/lesson_event.dart delete mode 100644 lib/lessons/bloc/lesson_state.dart delete mode 100644 lib/lessons/lesson_page.dart delete mode 100644 lib/lessons/widgets/lesson_item_widget.dart delete mode 100644 lib/listen/bloc/listen_bloc.dart delete mode 100644 lib/listen/bloc/listen_event.dart delete mode 100644 lib/listen/bloc/listen_state.dart delete mode 100644 lib/listen/listen_page.dart delete mode 100644 lib/listen/widgets/listen_item_widget.dart delete mode 100644 lib/login/forgetpwd/bloc/forget_pwd_home_bloc.dart delete mode 100644 lib/login/forgetpwd/bloc/forget_pwd_home_event.dart delete mode 100644 lib/login/forgetpwd/bloc/forget_pwd_home_state.dart delete mode 100644 lib/login/forgetpwd/forget_password_home_page.dart delete mode 100644 lib/login/loginpage/bloc/login_bloc.dart delete mode 100644 lib/login/loginpage/bloc/login_event.dart delete mode 100644 lib/login/loginpage/bloc/login_state.dart delete mode 100644 lib/login/loginpage/login_page.dart delete mode 100644 lib/login/loginpage/time_widget.dart delete mode 100644 lib/login/setpwd/bloc/set_pwd_bloc.dart delete mode 100644 lib/login/setpwd/bloc/set_pwd_event.dart delete mode 100644 lib/login/setpwd/bloc/set_pwd_state.dart delete mode 100644 lib/login/setpwd/set_pwd_page.dart create mode 100644 lib/pages/home/bloc/home_bloc.dart create mode 100644 lib/pages/home/bloc/home_event.dart create mode 100644 lib/pages/home/bloc/home_state.dart create mode 100644 lib/pages/home/home_page.dart create mode 100644 lib/pages/home/widgets/home_lesson_item_widget.dart create mode 100644 lib/pages/home/widgets/home_tab_header_widget.dart create mode 100644 lib/pages/lessons/bloc/lesson_bloc.dart create mode 100644 lib/pages/lessons/bloc/lesson_event.dart create mode 100644 lib/pages/lessons/bloc/lesson_state.dart create mode 100644 lib/pages/lessons/lesson_page.dart create mode 100644 lib/pages/lessons/widgets/lesson_item_widget.dart create mode 100644 lib/pages/listen/bloc/listen_bloc.dart create mode 100644 lib/pages/listen/bloc/listen_event.dart create mode 100644 lib/pages/listen/bloc/listen_state.dart create mode 100644 lib/pages/listen/listen_page.dart create mode 100644 lib/pages/listen/widgets/listen_item_widget.dart create mode 100644 lib/pages/login/forgetpwd/bloc/forget_pwd_home_bloc.dart create mode 100644 lib/pages/login/forgetpwd/bloc/forget_pwd_home_event.dart create mode 100644 lib/pages/login/forgetpwd/bloc/forget_pwd_home_state.dart create mode 100644 lib/pages/login/forgetpwd/forget_password_home_page.dart create mode 100644 lib/pages/login/loginpage/bloc/login_bloc.dart create mode 100644 lib/pages/login/loginpage/bloc/login_event.dart create mode 100644 lib/pages/login/loginpage/bloc/login_state.dart create mode 100644 lib/pages/login/loginpage/login_page.dart create mode 100644 lib/pages/login/loginpage/time_widget.dart create mode 100644 lib/pages/login/setpwd/bloc/set_pwd_bloc.dart create mode 100644 lib/pages/login/setpwd/bloc/set_pwd_event.dart create mode 100644 lib/pages/login/setpwd/bloc/set_pwd_state.dart create mode 100644 lib/pages/login/setpwd/set_pwd_page.dart create mode 100644 lib/pages/practice/chosetopic/topicpicture/bloc/topic_picture_bloc.dart create mode 100644 lib/pages/practice/chosetopic/topicpicture/bloc/topic_picture_event.dart create mode 100644 lib/pages/practice/chosetopic/topicpicture/bloc/topic_picture_state.dart create mode 100644 lib/pages/practice/chosetopic/topicpicture/topic_picture_page.dart create mode 100644 lib/pages/practice/chosetopic/topicword/bloc/topic_word_bloc.dart create mode 100644 lib/pages/practice/chosetopic/topicword/bloc/topic_word_event.dart create mode 100644 lib/pages/practice/chosetopic/topicword/bloc/topic_word_state.dart create mode 100644 lib/pages/practice/chosetopic/topicword/topic_word_page.dart create mode 100644 lib/pages/practice/voicetopic/voicepicture/bloc/voice_pic_bloc.dart create mode 100644 lib/pages/practice/voicetopic/voicepicture/bloc/voice_pic_event.dart create mode 100644 lib/pages/practice/voicetopic/voicepicture/bloc/voice_pic_state.dart create mode 100644 lib/pages/practice/voicetopic/voicepicture/voice_pic_page.dart create mode 100644 lib/pages/practice/voicetopic/voiceword/bloc/voice_word_bloc.dart create mode 100644 lib/pages/practice/voicetopic/voiceword/bloc/voice_word_event.dart create mode 100644 lib/pages/practice/voicetopic/voiceword/bloc/voice_word_state.dart create mode 100644 lib/pages/practice/voicetopic/voiceword/voice_word_page.dart create mode 100644 lib/pages/practice/widgets/practice_header_widget.dart create mode 100644 lib/pages/repeatafter/bloc/repeat_after_bloc.dart create mode 100644 lib/pages/repeatafter/bloc/repeat_after_event.dart create mode 100644 lib/pages/repeatafter/bloc/repeat_after_state.dart create mode 100644 lib/pages/repeatafter/repeat_after_page.dart create mode 100644 lib/pages/repeatafter/widgets/repeat_after_item.dart create mode 100644 lib/pages/shop/exchane/bloc/exchange_lesson_bloc.dart create mode 100644 lib/pages/shop/exchane/bloc/exchange_lesson_event.dart create mode 100644 lib/pages/shop/exchane/bloc/exchange_lesson_state.dart create mode 100644 lib/pages/shop/exchane/exchange_lesson_page.dart create mode 100644 lib/pages/shop/exchangelist/bloc/exchange_list_bloc.dart create mode 100644 lib/pages/shop/exchangelist/bloc/exchange_list_event.dart create mode 100644 lib/pages/shop/exchangelist/bloc/exchange_list_state.dart create mode 100644 lib/pages/shop/exchangelist/exchange_lesson_list_page.dart create mode 100644 lib/pages/shop/exchangelist/widgets/exchange_list_item.dart create mode 100644 lib/pages/shop/home/bloc/shop_home_bloc.dart create mode 100644 lib/pages/shop/home/bloc/shop_home_event.dart create mode 100644 lib/pages/shop/home/bloc/shop_home_state.dart create mode 100644 lib/pages/shop/home/shop_home_page.dart create mode 100644 lib/pages/shop/home/widgets/lesson_card_item.dart create mode 100644 lib/pages/tab/blocs/tab_bloc.dart create mode 100644 lib/pages/tab/blocs/tab_event.dart create mode 100644 lib/pages/tab/blocs/tab_state.dart create mode 100644 lib/pages/tab/tab_page.dart create mode 100644 lib/pages/user/bloc/user_bloc.dart create mode 100644 lib/pages/user/bloc/user_event.dart create mode 100644 lib/pages/user/bloc/user_state.dart create mode 100644 lib/pages/user/user_page.dart create mode 100644 lib/pages/video/lookvideo/bloc/look_video_bloc.dart create mode 100644 lib/pages/video/lookvideo/bloc/look_video_event.dart create mode 100644 lib/pages/video/lookvideo/bloc/look_video_state.dart create mode 100644 lib/pages/video/lookvideo/look_video_page.dart create mode 100644 lib/pages/video/lookvideo/widgets/video_opera_widget.dart create mode 100644 lib/pages/video/lookvideo/widgets/video_widget.dart create mode 100644 lib/pages/voiceanswer/bloc/voice_answer_bloc.dart create mode 100644 lib/pages/voiceanswer/bloc/voice_answer_event.dart create mode 100644 lib/pages/voiceanswer/bloc/voice_answer_state.dart create mode 100644 lib/pages/voiceanswer/voice_answer_page.dart delete mode 100644 lib/practice/chosetopic/topicpicture/bloc/topic_picture_bloc.dart delete mode 100644 lib/practice/chosetopic/topicpicture/bloc/topic_picture_event.dart delete mode 100644 lib/practice/chosetopic/topicpicture/bloc/topic_picture_state.dart delete mode 100644 lib/practice/chosetopic/topicpicture/topic_picture_page.dart delete mode 100644 lib/practice/chosetopic/topicword/bloc/topic_word_bloc.dart delete mode 100644 lib/practice/chosetopic/topicword/bloc/topic_word_event.dart delete mode 100644 lib/practice/chosetopic/topicword/bloc/topic_word_state.dart delete mode 100644 lib/practice/chosetopic/topicword/topic_word_page.dart delete mode 100644 lib/practice/voicetopic/voicepicture/bloc/voice_pic_bloc.dart delete mode 100644 lib/practice/voicetopic/voicepicture/bloc/voice_pic_event.dart delete mode 100644 lib/practice/voicetopic/voicepicture/bloc/voice_pic_state.dart delete mode 100644 lib/practice/voicetopic/voicepicture/voice_pic_page.dart delete mode 100644 lib/practice/voicetopic/voiceword/bloc/voice_word_bloc.dart delete mode 100644 lib/practice/voicetopic/voiceword/bloc/voice_word_event.dart delete mode 100644 lib/practice/voicetopic/voiceword/bloc/voice_word_state.dart delete mode 100644 lib/practice/voicetopic/voiceword/voice_word_page.dart delete mode 100644 lib/practice/widgets/practice_header_widget.dart delete mode 100644 lib/repeatafter/bloc/repeat_after_bloc.dart delete mode 100644 lib/repeatafter/bloc/repeat_after_event.dart delete mode 100644 lib/repeatafter/bloc/repeat_after_state.dart delete mode 100644 lib/repeatafter/repeat_after_page.dart delete mode 100644 lib/repeatafter/widgets/repeat_after_item.dart delete mode 100644 lib/shop/exchane/bloc/exchange_lesson_bloc.dart delete mode 100644 lib/shop/exchane/bloc/exchange_lesson_event.dart delete mode 100644 lib/shop/exchane/bloc/exchange_lesson_state.dart delete mode 100644 lib/shop/exchane/exchange_lesson_page.dart delete mode 100644 lib/shop/exchangelist/bloc/exchange_list_bloc.dart delete mode 100644 lib/shop/exchangelist/bloc/exchange_list_event.dart delete mode 100644 lib/shop/exchangelist/bloc/exchange_list_state.dart delete mode 100644 lib/shop/exchangelist/exchange_lesson_list_page.dart delete mode 100644 lib/shop/exchangelist/widgets/exchange_list_item.dart delete mode 100644 lib/shop/home/bloc/shop_home_bloc.dart delete mode 100644 lib/shop/home/bloc/shop_home_event.dart delete mode 100644 lib/shop/home/bloc/shop_home_state.dart delete mode 100644 lib/shop/home/shop_home_page.dart delete mode 100644 lib/shop/home/widgets/lesson_card_item.dart delete mode 100644 lib/tab/blocs/tab_bloc.dart delete mode 100644 lib/tab/blocs/tab_event.dart delete mode 100644 lib/tab/blocs/tab_state.dart delete mode 100644 lib/tab/tab_page.dart delete mode 100644 lib/user/bloc/user_bloc.dart delete mode 100644 lib/user/bloc/user_event.dart delete mode 100644 lib/user/bloc/user_state.dart delete mode 100644 lib/user/user_page.dart delete mode 100644 lib/video/lookvideo/bloc/look_video_bloc.dart delete mode 100644 lib/video/lookvideo/bloc/look_video_event.dart delete mode 100644 lib/video/lookvideo/bloc/look_video_state.dart delete mode 100644 lib/video/lookvideo/look_video_page.dart delete mode 100644 lib/video/lookvideo/widgets/video_opera_widget.dart delete mode 100644 lib/video/lookvideo/widgets/video_widget.dart delete mode 100644 lib/voiceanswer/bloc/voice_answer_bloc.dart delete mode 100644 lib/voiceanswer/bloc/voice_answer_event.dart delete mode 100644 lib/voiceanswer/bloc/voice_answer_state.dart delete mode 100644 lib/voiceanswer/voice_answer_page.dart diff --git a/lib/common/request/exception.dart b/lib/common/request/exception.dart index a23c76a..6798503 100644 --- a/lib/common/request/exception.dart +++ b/lib/common/request/exception.dart @@ -1,5 +1,4 @@ import 'package:dio/dio.dart'; - import 'api_response/api_response_entity.dart'; class ApiException implements Exception { diff --git a/lib/home/bloc/home_bloc.dart b/lib/home/bloc/home_bloc.dart deleted file mode 100644 index d70e546..0000000 --- a/lib/home/bloc/home_bloc.dart +++ /dev/null @@ -1,14 +0,0 @@ -import 'package:flutter/cupertino.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; - -part 'home_event.dart'; -part 'home_state.dart'; - -class HomeBloc extends Bloc { - final PageController pageController; - HomeBloc(this.pageController) : super(HomeInitial()) { - on((event, emit) { - // TODO: implement event handler - }); - } -} diff --git a/lib/home/bloc/home_event.dart b/lib/home/bloc/home_event.dart deleted file mode 100644 index 33589ea..0000000 --- a/lib/home/bloc/home_event.dart +++ /dev/null @@ -1,4 +0,0 @@ -part of 'home_bloc.dart'; - -@immutable -abstract class HomeEvent {} diff --git a/lib/home/bloc/home_state.dart b/lib/home/bloc/home_state.dart deleted file mode 100644 index 423dfab..0000000 --- a/lib/home/bloc/home_state.dart +++ /dev/null @@ -1,6 +0,0 @@ -part of 'home_bloc.dart'; - -@immutable -abstract class HomeState {} - -class HomeInitial extends HomeState {} diff --git a/lib/home/home_page.dart b/lib/home/home_page.dart deleted file mode 100644 index 5ed4328..0000000 --- a/lib/home/home_page.dart +++ /dev/null @@ -1,122 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:flutter_easyloading/flutter_easyloading.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:wow_english/common/extension/string_extension.dart'; -import 'package:wow_english/home/bloc/home_bloc.dart'; -import 'package:wow_english/home/widgets/home_lesson_item_widget.dart'; -import 'package:wow_english/home/widgets/home_tab_header_widget.dart'; -import 'package:wow_english/route/route.dart'; - -class HomePage extends StatelessWidget { - const HomePage({super.key}); - - @override - Widget build(BuildContext context) { - return BlocProvider( - create: (context) => HomeBloc(PageController( - initialPage: 0, - )), - child: _HomePageView(), - ); - } -} - -class _HomePageView extends StatelessWidget { - void _headerActionEvent(HeaderActionType type) { - if (type == HeaderActionType.video) { - Navigator.of(AppRouter.context).pushNamed(AppRouteName.reAfter); - } else if (type == HeaderActionType.phase) { - Navigator.of(AppRouter.context).pushNamed(AppRouteName.lesson); - } else if (type == HeaderActionType.listen) { - Navigator.of(AppRouter.context).pushNamed(AppRouteName.listen); - } else if (type == HeaderActionType.shop) { - Navigator.of(AppRouter.context).pushNamed(AppRouteName.shop); - } else if (type == HeaderActionType.user) { - Navigator.of(AppRouter.context).pushNamed(AppRouteName.user); - } else { - // Navigator.of(AppRouter.context).pushNamed(AppRouteName.topicPic); - // Navigator.of(AppRouter.context).pushNamed(AppRouteName.topicWord); - // Navigator.of(AppRouter.context).pushNamed(AppRouteName.lookVideo); - // Navigator.of(AppRouter.context).pushNamed(AppRouteName.voicePic); - // Navigator.of(AppRouter.context).pushNamed(AppRouteName.voiceWord); - Navigator.of(AppRouter.context).pushNamed(AppRouteName.voiceAnswer); - } - } - - @override - Widget build(BuildContext context) { - return BlocListener( - listener: (context, state){}, - child: _homeView(), - ); - } - - Widget _homeView() => BlocBuilder( - builder: (context, state){ - final bloc = BlocProvider.of(context); - return Scaffold( - body: Container( - color: Colors.white, - child: Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - HomeTabHeaderWidget( - actionTap: (HeaderActionType type) { - _headerActionEvent(type); - }, - ), - Expanded( - child: PageView.builder( - itemCount: 10, - controller: bloc.pageController, - pageSnapping: false, - onPageChanged: (int index) { - EasyLoading.showToast(index.toString()); - }, - itemBuilder: (BuildContext context,int index){ - return const HomeLessonItem(); - }) - , - ), - SafeArea( - child: Padding( - padding: EdgeInsets.symmetric(horizontal: 13.w), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - SizedBox( - height: 47.h, - width: 80.w, - ), - Container( - decoration: BoxDecoration( - color: Colors.blue, - borderRadius: BorderRadius.circular(14.5.r), - ), - padding: EdgeInsets.symmetric(vertical: 8.h,horizontal: 24.w), - child: Text( - '3/67', - style: TextStyle( - color: Colors.white, - fontSize: 12.sp - ), - ), - ), - Image.asset( - 'blue-positive'.assetPng, - height: 47.h, - width: 80.w, - ), - ], - ), - ), - ) - ], - ), - ), - ), - ); - }); -} diff --git a/lib/home/widgets/home_lesson_item_widget.dart b/lib/home/widgets/home_lesson_item_widget.dart deleted file mode 100644 index 9bf3a85..0000000 --- a/lib/home/widgets/home_lesson_item_widget.dart +++ /dev/null @@ -1,25 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; - -class HomeLessonItem extends StatelessWidget { - const HomeLessonItem({super.key}); - - @override - Widget build(BuildContext context) { - return SizedBox( - width: double.infinity, - child: ListView.builder( - itemCount: 5, - scrollDirection: Axis.horizontal, - physics: const NeverScrollableScrollPhysics(), - itemBuilder: (BuildContext context,int index){ - return Padding( - padding: EdgeInsets.symmetric(horizontal: 4.w), - child: Image.network( - 'https://img.liblibai.com/web/648331d5a2cb5.png?image_process=format,webp&x-oss-process=image/resize,w_2980,m_lfit/format,webp', - ), - ); - }), - ); - } -} \ No newline at end of file diff --git a/lib/home/widgets/home_tab_header_widget.dart b/lib/home/widgets/home_tab_header_widget.dart deleted file mode 100644 index 53eaedf..0000000 --- a/lib/home/widgets/home_tab_header_widget.dart +++ /dev/null @@ -1,131 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:wow_english/common/extension/string_extension.dart'; - -enum HeaderActionType { - //视频跟读 - video, - //阶段选择 - phase, - //磨耳朵 - listen, - //购买 - shop, - //个人信息 - user -} - -class HomeTabHeaderWidget extends StatelessWidget { - - const HomeTabHeaderWidget({super.key, this.actionTap}); - - final Function(HeaderActionType type)? actionTap; - - @override - Widget build(BuildContext context) { - return Container( - height: 45, - width: double.infinity, - color: Colors.purple, - padding: EdgeInsets.symmetric(horizontal: 9.5.w), - child: Row( - children: [ - ScreenUtil().bottomBarHeight.horizontalSpace, - GestureDetector( - onTap: () { - if(actionTap != null) { - actionTap!(HeaderActionType.user); - } - }, - child: Container( - decoration: BoxDecoration( - border: Border.all( - width: 1.0, - color: const Color(0xFF140C10), - ), - borderRadius: BorderRadius.circular(21), - ), - child: const CircleAvatar( - radius: 21, - backgroundImage: NetworkImage( - 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fsafe-img.xhscdn.com%2Fbw1%2Faa1c2213-820a-4223-8757-5f8cee318a28%3FimageView2%2F2%2Fw%2F1080%2Fformat%2Fjpg&refer=http%3A%2F%2Fsafe-img.xhscdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1688713226&t=192b18a613683bcdc5bd76f65c9ff032' - ), - ), - ), - ), - GestureDetector( - onTap: () { - if(actionTap != null) { - actionTap!(HeaderActionType.user); - } - }, - child: Container( - margin: const EdgeInsets.only(left: 7), - padding: const EdgeInsets.all(4.0), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(2), - border: Border.all( - width: 1.0, - color: const Color(0xFF140C10), - style: BorderStyle.solid - ), - ), - child: Text( - 'franky', - style: TextStyle( - color: const Color(0xFF333333), - fontSize: 16.sp - ), - ), - ), - ), - 20.horizontalSpace, - const Expanded( - child:Text( - 'learn wow!yellow', - textAlign:TextAlign.left, - style: TextStyle( - color: Colors.white, - fontSize: 30.0 - ), - ) - ), - IconButton( - onPressed: (){ - if(actionTap != null) { - actionTap!(HeaderActionType.video); - } - }, - icon: Image.asset('video'.assetPng) - ), - IconButton( - onPressed: (){ - if(actionTap != null) { - actionTap!(HeaderActionType.phase); - } - }, - icon: Image.asset('home'.assetPng) - ), - IconButton( - onPressed: (){ - if(actionTap != null) { - actionTap!(HeaderActionType.listen); - } - }, - icon: Image.asset('listen'.assetPng) - ), - IconButton( - onPressed: (){ - if(actionTap != null) { - actionTap!(HeaderActionType.shop); - } - }, - icon: Image.asset('shop'.assetPng) - ), - ScreenUtil().bottomBarHeight.horizontalSpace, - ], - ), - ); - } -} diff --git a/lib/lessons/bloc/lesson_bloc.dart b/lib/lessons/bloc/lesson_bloc.dart deleted file mode 100644 index 91c603f..0000000 --- a/lib/lessons/bloc/lesson_bloc.dart +++ /dev/null @@ -1,33 +0,0 @@ - -import 'package:flutter/cupertino.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; - -part 'lesson_event.dart'; -part 'lesson_state.dart'; - -class LessonBloc extends Bloc { - - final int pageIndex; - - final PageController pageController; - - int _currentPageIndex = 0; - - int get currentPageIndex => _currentPageIndex; - - LessonBloc(this.pageIndex,this.pageController) : super(LessonInitial()) { - _currentPageIndex = pageIndex; - on(_pageIndexChange); - } - - void _pageIndexChange(PageViewChangeIndexEvent event,Emitter emitter) async { - _currentPageIndex = event.index; - emitter(PageIndexChangeState()); - } - - @override - Future close() { - pageController.dispose(); - return super.close(); - } -} diff --git a/lib/lessons/bloc/lesson_event.dart b/lib/lessons/bloc/lesson_event.dart deleted file mode 100644 index 13338d6..0000000 --- a/lib/lessons/bloc/lesson_event.dart +++ /dev/null @@ -1,9 +0,0 @@ -part of 'lesson_bloc.dart'; - -@immutable -abstract class LessonEvent {} - -class PageViewChangeIndexEvent extends LessonEvent { - final int index; - PageViewChangeIndexEvent(this.index); -} diff --git a/lib/lessons/bloc/lesson_state.dart b/lib/lessons/bloc/lesson_state.dart deleted file mode 100644 index 5c21ecb..0000000 --- a/lib/lessons/bloc/lesson_state.dart +++ /dev/null @@ -1,8 +0,0 @@ -part of 'lesson_bloc.dart'; - -@immutable -abstract class LessonState {} - -class LessonInitial extends LessonState {} - -class PageIndexChangeState extends LessonState {} diff --git a/lib/lessons/lesson_page.dart b/lib/lessons/lesson_page.dart deleted file mode 100644 index 73766dd..0000000 --- a/lib/lessons/lesson_page.dart +++ /dev/null @@ -1,220 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:flutter_easyloading/flutter_easyloading.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:wow_english/common/extension/string_extension.dart'; -import 'package:wow_english/common/widgets/we_app_bar.dart'; -import 'package:wow_english/lessons/bloc/lesson_bloc.dart'; -import 'package:wow_english/lessons/widgets/lesson_item_widget.dart'; - -class LessonPage extends StatelessWidget { - const LessonPage({super.key, this.starPageIndex}); - - final int? starPageIndex; - - @override - Widget build(BuildContext context) { - return BlocProvider( - create: (context) => LessonBloc( - starPageIndex??0, - PageController( - initialPage: starPageIndex??0, - viewportFraction: 0.3 - ),), - child: _LessonPageView(), - ); - } -} - -class _LessonPageView extends StatelessWidget { - - final double _cardHeight = 240.h; - - final double _numItemHeight = 32.0; - - final double _scale = 0.8; - - @override - Widget build(BuildContext context) { - return BlocListener( - listener: (context, state){}, - child: Scaffold( - appBar: WEAppBar( - leading: IconButton( - onPressed: (){ - Navigator.pop(context); - }, - icon: Image.asset( - 'back'.assetPng, - height: 43, - width: 43, - ) - ), - actions: [ - IconButton( - icon: Image.asset('shop'.assetPng), - color: Colors.white, - onPressed: () { - EasyLoading.showToast('购买'); - }, - ) - ], - ), - body: _lessViewWidget(), - ), - ); - } - - Widget _lessViewWidget() => BlocBuilder( - builder: (context, state){ - final bloc = BlocProvider.of(context); - return Center( - child: SafeArea( - child: Column( - children: [ - SizedBox( - height: _cardHeight, - child: PageView.builder( - itemCount: 10, - controller: bloc.pageController, - onPageChanged: (int index) { - bloc.add(PageViewChangeIndexEvent(index)); - }, - itemBuilder: (context,index) => _itemTransCard(index) - ), - ), - 32.verticalSpace, - SizedBox( - height: 32.h, - width: 660.w, - child: ListView.builder( - itemCount: 10, - scrollDirection: Axis.horizontal, - itemBuilder: (BuildContext context,int index){ - return Container( - height: 32.h, - width: 66.w, - padding: const EdgeInsets.symmetric(horizontal: 5), - child: GestureDetector( - onTap: () { - if (index == bloc.currentPageIndex) { - return; - } - int mill = (index - bloc.currentPageIndex) > 0 ? 100 * (index - bloc.currentPageIndex):100 * (bloc.currentPageIndex-index); - bloc.pageController.animateToPage(index, duration: Duration(milliseconds: mill), curve: Curves.ease); - }, - child: Container( - height: bloc.currentPageIndex == index ? 32:20, - decoration: BoxDecoration( - color: bloc.currentPageIndex == index ? Colors.red:Colors.white, - border: Border.all( - width: 0.5, - color: Colors.black, - ), - ), - alignment: Alignment.center, - child: Text( - (index+1).toString(), - style: TextStyle( - color: bloc.currentPageIndex == index ? Colors.white:Colors.black - ), - ), - ), - ), - ); - }), - // child: PageView.builder( - // itemCount: 10, - // controller: bloc.pageController, - // onPageChanged: (int index) { - // bloc.add(PageViewChangeIndexEvent(index)); - // }, - // itemBuilder: (context,index) => _itemNumCard(index) - // ), - ) - ], - ), - ), - ); - }); - - Widget _itemTransCard(int index) => BlocBuilder( - builder: (context, state) { - final bloc = BlocProvider.of(context); - Matrix4 matrix4 = Matrix4.identity(); - if (index == bloc.currentPageIndex.floor()) { - //当前的item - double currScale = (1 - (bloc.currentPageIndex - index) * (1 - _scale)).toDouble(); - var currTrans = _cardHeight * (1 - currScale) / 2; - - matrix4 = Matrix4.diagonal3Values(1.0, currScale, 1.0) - ..setTranslationRaw(0.0, currTrans, 0.0); - } else if (index == bloc.currentPageIndex.floor() + 1) { - //右边的item - var currScale = _scale + (bloc.currentPageIndex - index + 1) * (1 - _scale); - var currTrans = _cardHeight * (1 - currScale) / 2; - - matrix4 = Matrix4.diagonal3Values(1.0, currScale, 1.0) - ..setTranslationRaw(0.0, currTrans, 0.0); - } else if (index == bloc.currentPageIndex - 1) { - //左边 - var currScale = (1 - (bloc.currentPageIndex - index) * (1 - _scale)).toDouble(); - var currTrans = _cardHeight * (1 - currScale) / 2; - - matrix4 = Matrix4.diagonal3Values(1.0, currScale, 1.0) - ..setTranslationRaw(0.0, currTrans, 0.0); - } else { - //其他,不在屏幕显示的item - matrix4 = Matrix4.diagonal3Values(1.0, _scale, 1.0) - ..setTranslationRaw(0.0, _cardHeight * (1 - _scale) / 2, 0.0); - } - - return Transform( - transform: matrix4, - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 10), - child: LessonItemWidget(isSelected: bloc.currentPageIndex == index), - ), - ); - }); - - Widget _itemNumCard(int index) => BlocBuilder( - builder: (context, state) { - final bloc = BlocProvider.of(context); - bool isSelected = bloc.currentPageIndex.floor() == index; - Matrix4 matrix4 = Matrix4.identity(); - if (index == bloc.currentPageIndex.floor()) { - //当前的item - double currScale = (1 - (bloc.currentPageIndex - index) * (1 - _scale)).toDouble(); - var currTrans = _numItemHeight * (1 - currScale) / 2; - - matrix4 = Matrix4.diagonal3Values(1.0, currScale, 1.0) - ..setTranslationRaw(0.0, currTrans, 0.0); - } else if (index == bloc.currentPageIndex.floor() + 1) { - //右边的item - var currScale = _scale + (bloc.currentPageIndex - index + 1) * (1 - _scale); - var currTrans = _numItemHeight * (1 - currScale) / 2; - - matrix4 = Matrix4.diagonal3Values(1.0, currScale, 1.0) - ..setTranslationRaw(0.0, currTrans, 0.0); - } else if (index == bloc.currentPageIndex - 1) { - //左边 - var currScale = (1 - (bloc.currentPageIndex - index) * (1 - _scale)).toDouble(); - var currTrans = _numItemHeight * (1 - currScale) / 2; - - matrix4 = Matrix4.diagonal3Values(1.0, currScale, 1.0) - ..setTranslationRaw(0.0, currTrans, 0.0); - } else { - //其他,不在屏幕显示的item - matrix4 = Matrix4.diagonal3Values(1.0, _scale, 1.0) - ..setTranslationRaw(0.0, _numItemHeight * (1 - _scale) / 2, 0.0); - } - - return Transform( - transform: matrix4, - child: Container( - color: isSelected?Colors.red:Colors.yellow, - ), - ); - }); -} \ No newline at end of file diff --git a/lib/lessons/widgets/lesson_item_widget.dart b/lib/lessons/widgets/lesson_item_widget.dart deleted file mode 100644 index f75319c..0000000 --- a/lib/lessons/widgets/lesson_item_widget.dart +++ /dev/null @@ -1,57 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; - -class LessonItemWidget extends StatelessWidget { - const LessonItemWidget({super.key, required this.isSelected}); - ///是否被选中 - final bool isSelected; - - @override - Widget build(BuildContext context) { - return isSelected?_selectWidget():_unSelectWidget(); - } - - Widget _unSelectWidget() { - return Container( - decoration: const BoxDecoration( - image: DecorationImage( - image: NetworkImage('https://img.liblibai.com/web/648331d033b41.png?image_process=format,webp&x-oss-process=image/resize,w_2980,m_lfit/format,webp'), - ) - ), - ); - } - - Widget _selectWidget() { - return Container( - padding: const EdgeInsets.all(10), - decoration: BoxDecoration( - border: Border.all( - width: 2.0, - color: Colors.red, - style: BorderStyle.solid - ), - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: Image.network( - 'https://img.liblibai.com/web/648331d5a2cb5.png?image_process=format,webp&x-oss-process=image/resize,w_2980,m_lfit/format,webp', - ), - ), - 10.verticalSpace, - Container( - color: Colors.red, - width: double.infinity, - child: const Column( - children: [ - Text('red'), - Text('第三段') - ], - ), - ) - ], - ), - ); - } -} \ No newline at end of file diff --git a/lib/listen/bloc/listen_bloc.dart b/lib/listen/bloc/listen_bloc.dart deleted file mode 100644 index cf2c7b6..0000000 --- a/lib/listen/bloc/listen_bloc.dart +++ /dev/null @@ -1,14 +0,0 @@ - -import 'package:flutter/cupertino.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; - -part 'listen_event.dart'; -part 'listen_state.dart'; - -class ListenBloc extends Bloc { - ListenBloc() : super(ListenInitial()) { - on((event, emit) { - // TODO: implement event handler - }); - } -} diff --git a/lib/listen/bloc/listen_event.dart b/lib/listen/bloc/listen_event.dart deleted file mode 100644 index 84f8d1c..0000000 --- a/lib/listen/bloc/listen_event.dart +++ /dev/null @@ -1,4 +0,0 @@ -part of 'listen_bloc.dart'; - -@immutable -abstract class ListenEvent {} diff --git a/lib/listen/bloc/listen_state.dart b/lib/listen/bloc/listen_state.dart deleted file mode 100644 index dfb830f..0000000 --- a/lib/listen/bloc/listen_state.dart +++ /dev/null @@ -1,6 +0,0 @@ -part of 'listen_bloc.dart'; - -@immutable -abstract class ListenState {} - -class ListenInitial extends ListenState {} diff --git a/lib/listen/listen_page.dart b/lib/listen/listen_page.dart deleted file mode 100644 index c23bc55..0000000 --- a/lib/listen/listen_page.dart +++ /dev/null @@ -1,51 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:wow_english/common/widgets/we_app_bar.dart'; -import 'package:wow_english/listen/bloc/listen_bloc.dart'; -import 'package:wow_english/listen/widgets/listen_item_widget.dart'; - -class ListenPage extends StatelessWidget { - const ListenPage({super.key}); - - @override - Widget build(BuildContext context) { - return BlocProvider( - create: (context) => ListenBloc(), - child: _ListenPageView(), - ); - } -} - -class _ListenPageView extends StatelessWidget { - @override - Widget build(BuildContext context) { - return BlocListener( - listener: (context, state) { - - }, - child: Scaffold( - appBar: const WEAppBar( - titleText: '磨耳朵', - centerTitle: false, - ), - body: _listenView(), - ), - ); - } - - Widget _listenView() => BlocBuilder( - builder: (context, state) { - return ListView.builder( - itemCount: 10, - scrollDirection: Axis.horizontal, - padding: EdgeInsets.symmetric(horizontal: 30.w,vertical: 36.h), - itemBuilder: (BuildContext context,int index){ - return ListenItemWidget( - isLock: (index < 5), - clickEvent: (){ - - }); - }); - }); -} \ No newline at end of file diff --git a/lib/listen/widgets/listen_item_widget.dart b/lib/listen/widgets/listen_item_widget.dart deleted file mode 100644 index 3f73252..0000000 --- a/lib/listen/widgets/listen_item_widget.dart +++ /dev/null @@ -1,80 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:wow_english/common/extension/string_extension.dart'; - -class ListenItemWidget extends StatelessWidget { - const ListenItemWidget({super.key, this.isLock = false, required this.clickEvent}); - - final Function() clickEvent; - - final bool isLock; - - @override - Widget build(BuildContext context) { - return Padding( - padding: EdgeInsets.symmetric(horizontal: 8.5.w), - child: Column( - children: [ - GestureDetector( - onTap: () { - if (!isLock) { - clickEvent(); - } - }, - child: ClipRRect( - borderRadius:BorderRadius.circular(90.r), - child: Stack( - alignment:Alignment.center, - children: [ - Image.network( - 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fsafe-img.xhscdn.com%2Fbw1%2Faa1c2213-820a-4223-8757-5f8cee318a28%3FimageView2%2F2%2Fw%2F1080%2Fformat%2Fjpg&refer=http%3A%2F%2Fsafe-img.xhscdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1688713226&t=192b18a613683bcdc5bd76f65c9ff032', - height: 180.h, - width: 180.h, - fit: BoxFit.fill, - ), - Offstage( - offstage: isLock, - child: Container( - height: 180.h, - width: 180.h, - color: const Color.fromRGBO(1, 1, 0, 0.5), - ), - ), - Offstage( - offstage: isLock, - child: Image.asset( - 'listen_lock'.assetPng, - height: 36.h, - width: 41.w, - ), - ) - ], - ), - ), - ), - 23.verticalSpace, - Container( - height: 40.h, - padding: EdgeInsets.symmetric(horizontal: 22.w), - decoration: BoxDecoration( - color: const Color(0xFFFFCC00), - borderRadius: BorderRadius.circular(20.r), - border: Border.all( - width: 1.0, - color: const Color(0xFF333333), - ), - ), - alignment: Alignment.center, - child: Text( - 'listen title', - style: TextStyle( - fontSize: 20.sp, - color: const Color(0xFF333333) - ), - ), - ) - ], - ), - ); - } -} \ No newline at end of file diff --git a/lib/login/forgetpwd/bloc/forget_pwd_home_bloc.dart b/lib/login/forgetpwd/bloc/forget_pwd_home_bloc.dart deleted file mode 100644 index 74999e1..0000000 --- a/lib/login/forgetpwd/bloc/forget_pwd_home_bloc.dart +++ /dev/null @@ -1,71 +0,0 @@ -import 'package:flutter/cupertino.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:common_utils/common_utils.dart'; -import 'package:flutter_easyloading/flutter_easyloading.dart'; - -part 'forget_pwd_home_event.dart'; -part 'forget_pwd_home_state.dart'; - -class ForgetPwdHomeBloc extends Bloc { - - ///是否可以发送验证码 - bool _canSendSms = false; - bool _canSetPwd = false; - - bool get canSendSms => _canSendSms; - bool get canSetPwd => _canSetPwd; - - final TextEditingController phoneNumController = TextEditingController(); - final TextEditingController checkNumController = TextEditingController(); - - ForgetPwdHomeBloc() : super(ForgetPwdHomeInitial()) { - on(_changePhoneNumber); - on(_changeCodeNumber); - on(_setPassWord); - on(_sendSmsCode); - } - - void _changePhoneNumber(PhoneNumChangeEvent event, Emitter emitter) async { - if (phoneNumController.text.isNotEmpty) { - if (!_canSendSms) { - _canSendSms = true; - emitter(SendSmsCodeTypeChangeState()); - emitter(SetPwdTypeChangeState()); - } - } else { - if (_canSendSms) { - _canSendSms = false; - emitter(SendSmsCodeTypeChangeState()); - emitter(SetPwdTypeChangeState()); - } - } - } - - void _changeCodeNumber(CheckCodeChangeEvent event, Emitter emitter) async { - if (checkNumController.text.isNotEmpty) { - if (!_canSetPwd) { - _canSetPwd = true; - emitter(SendSmsCodeTypeChangeState()); - emitter(SetPwdTypeChangeState()); - } - } else { - if (_canSetPwd) { - _canSetPwd = false; - emitter(SendSmsCodeTypeChangeState()); - emitter(SetPwdTypeChangeState()); - } - } - } - - void _setPassWord(SetPassWordEvent event,Emitter emitter) async { - if(!RegexUtil.isMobileExact(phoneNumController.text)) { - EasyLoading.showToast('手机号不正确!'); - return; - } - emitter(SetPwdCheckCodeState()); - } - - void _sendSmsCode(SendSmsCodeEvent event,Emitter emitter) async { - - } -} diff --git a/lib/login/forgetpwd/bloc/forget_pwd_home_event.dart b/lib/login/forgetpwd/bloc/forget_pwd_home_event.dart deleted file mode 100644 index 0be0181..0000000 --- a/lib/login/forgetpwd/bloc/forget_pwd_home_event.dart +++ /dev/null @@ -1,12 +0,0 @@ -part of 'forget_pwd_home_bloc.dart'; - -@immutable -abstract class ForgetPwdHomeEvent {} - -class PhoneNumChangeEvent extends ForgetPwdHomeEvent {} - -class CheckCodeChangeEvent extends ForgetPwdHomeEvent {} - -class SetPassWordEvent extends ForgetPwdHomeEvent {} - -class SendSmsCodeEvent extends ForgetPwdHomeEvent {} diff --git a/lib/login/forgetpwd/bloc/forget_pwd_home_state.dart b/lib/login/forgetpwd/bloc/forget_pwd_home_state.dart deleted file mode 100644 index cbe7bfa..0000000 --- a/lib/login/forgetpwd/bloc/forget_pwd_home_state.dart +++ /dev/null @@ -1,12 +0,0 @@ -part of 'forget_pwd_home_bloc.dart'; - -@immutable -abstract class ForgetPwdHomeState {} - -class ForgetPwdHomeInitial extends ForgetPwdHomeState {} -///是否能发送验证码 -class SendSmsCodeTypeChangeState extends ForgetPwdHomeState {} -///是否能设置密码 -class SetPwdTypeChangeState extends ForgetPwdHomeState {} -///验证码验证是否成功 -class SetPwdCheckCodeState extends ForgetPwdHomeState {} diff --git a/lib/login/forgetpwd/forget_password_home_page.dart b/lib/login/forgetpwd/forget_password_home_page.dart deleted file mode 100644 index ebfe5a9..0000000 --- a/lib/login/forgetpwd/forget_password_home_page.dart +++ /dev/null @@ -1,169 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:wow_english/common/extension/string_extension.dart'; -import 'package:wow_english/common/widgets/textfield_customer_widget.dart'; -import 'package:wow_english/login/forgetpwd/bloc/forget_pwd_home_bloc.dart'; -import 'package:wow_english/login/loginpage/time_widget.dart'; -import 'package:wow_english/route/route.dart'; - -class ForgetPasswordHomePage extends StatelessWidget { - const ForgetPasswordHomePage({super.key}); - - @override - Widget build(BuildContext context) { - return BlocProvider( - create: (context) => ForgetPwdHomeBloc(), - child: _ForgetPasswordHomePageView(), - ); - } -} - -class _ForgetPasswordHomePageView extends StatelessWidget { - @override - Widget build(BuildContext context) { - return BlocListener( - listener: (context, state) { - if (state is SetPwdCheckCodeState) { - Navigator.of(context).pushNamed(AppRouteName.setPwd,arguments: {'phoneNumber':context.read().phoneNumController.text}); - } - }, - child: _buildForgetPwdView(), - ); - } - - Widget _buildForgetPwdView() => BlocBuilder( - builder: (context, state) { - final bloc = BlocProvider.of(context); - return Scaffold( - body: Container( - color: Colors.white, - child: SafeArea( - child: ListView( - children: [ - Padding( - padding: EdgeInsets.only(left: 49.w,right: 10.w), - child: Column( - children: [ - 34.verticalSpace, - Row( - children: [ - Image.asset( - 'wow_logo'.assetPng, - height: 49.w, - width: 83.5.h, - ), - 12.5.horizontalSpace, - Text( - '修改密码\n请输入您的手机号和验证码吧', - style: TextStyle( - fontSize: 16.sp, - color: const Color(0xFF666666) - ), - ) - ], - ), - Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - child: Column( - children: [ - 44.5.verticalSpace, - Row( - children: [ - Image.asset( - 'phone'.assetPng, - height: 45.h, - width: 35.w, - ), - 15.horizontalSpace, - Expanded( - child: TextFieldCustomerWidget( - height: 50.h, - hitText: '请输入当前手机号', - textInputType: TextInputType.phone, - bgImageName: 'Input_layer_up', - onChangeValue: (String value) { - bloc.add(PhoneNumChangeEvent()); - }, - controller: bloc.phoneNumController, - ) - ) - ], - ), - 11.5.verticalSpace, - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Image.asset( - 'lock'.assetPng, - height: 34.h, - width: 31.w, - ), - 18.5.horizontalSpace, - Expanded( - child: TextFieldCustomerWidget( - hitText: '请输入验证码', - bgImageName: 'Input_layer_down', - onChangeValue: (String value) { - bloc.add(CheckCodeChangeEvent()); - }, - textInputType: TextInputType.emailAddress, - controller: bloc.checkNumController, - ) - ), - 16.5.horizontalSpace, - TimerWidget(canSendSms: bloc.canSendSms) - ], - ) - ], - ) - ), - 2.verticalSpace, - Image.asset( - 'steven_bride'.assetPng, - height: 173.h, - width: 157.w, - ) - ], - ), - GestureDetector( - onTap: () { - if (bloc.canSetPwd) { - bloc.add(SetPassWordEvent()); - } - }, - child: Container( - decoration: BoxDecoration( - image: DecorationImage( - image: AssetImage( - bloc.canSetPwd?'login_enter'.assetPng:'login_enter_dis'.assetPng - ), - fit: BoxFit.fill - ), - ), - padding: EdgeInsets.symmetric( - horizontal: 28.w, - vertical: 14.h - ), - child: Text( - '确定', - style: TextStyle( - fontSize: 16.sp, - color: Colors.white - ), - ), - ), - ) - ], - ), - ) - ], - ), - ), - ), - ); - } - ); -} \ No newline at end of file diff --git a/lib/login/loginpage/bloc/login_bloc.dart b/lib/login/loginpage/bloc/login_bloc.dart deleted file mode 100644 index 6f9fa63..0000000 --- a/lib/login/loginpage/bloc/login_bloc.dart +++ /dev/null @@ -1,171 +0,0 @@ -import 'package:flutter/cupertino.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:flutter_easyloading/flutter_easyloading.dart'; - -import '../../../common/request/api_response/api_response_entity.dart'; -import '../../../common/request/apis.dart'; -import '../../../common/request/request.dart'; -import '../../../common/request/request_client.dart'; -import '../../../models/user_entity.dart'; - -part 'login_event.dart'; -part 'login_state.dart'; - -enum LoginType { - ///密码登陆 - pwd, - - ///验证码登陆 - sms, -} - -class LoginBloc extends Bloc { - bool _canLogin = false; - - ///是否可以发送验证码 - bool _canSendSms = false; - - ///是否阅读协议 - bool _agreement = false; - - ///登陆方式 - //LoginType _loginType = LoginType.sms; - bool _isSmsLoginType = true; - - final TextEditingController phoneNumController = TextEditingController(); - final TextEditingController checkNumController = TextEditingController(); - - bool get canLogin => _canLogin; - - bool get agreement => _agreement; - - //LoginType get loginType => _loginType; - - bool get isSmsLoginType => _isSmsLoginType; - - bool get canSendSms => _canSendSms; - - LoginBloc() : super(LoginInitial()) { - on(_requestLoginApi); - on(_changeLoginType); - on(_changePhoneNumber); - on(_agreementTypeChange); - on(_checkFiledChange); - on(_requestSmsCodeApi); - } - - ///请求登陆 - void _requestLoginApi(RequestLoginEvent event, Emitter emitter) async { - var phoneNumber = phoneNumController.text; - if (phoneNumber.isEmpty) { - EasyLoading.showToast('号码不能为空'); - return; - } - - var checkNumber = checkNumController.text; - if (checkNumber.isEmpty) { - var text = _isSmsLoginType ? '密码' : '验证码'; - EasyLoading.showToast('$text不能为空'); - return; - } - var checkKey = _isSmsLoginType ? 'smsCode' : 'password'; - var type = _isSmsLoginType ? 'sms_code' : 'pwd'; - - request(() async { - var params = {'phoneNum': phoneNumber, 'type': type, checkKey: checkNumber}; - await requestClient.post( - Apis.login, - data: params, - onResponse: (ApiResponse response) { - print('response=$response'); - // todo 持久化用户对象 - // todo 写入全局对象 - //emitter.call(LoginResultChangeState()); - }, - onError: (e) { - EasyLoading.showToast('登陆失败:${e.message}'); - return true; - }, - ); - }); - } - - ///请求验证码 - void _requestSmsCodeApi(RequestSmsCodeEvent event, Emitter emitter) async { - - } - - ///切换登陆方式 - void _changeLoginType(ChangeLoginTypeEvent event, Emitter emitter) async { - if (_isSmsLoginType) { - _isSmsLoginType = false; - } else { - _isSmsLoginType = true; - } - checkNumController.clear(); - if (_loginStateChange()) { - emitter(LoginEventChangeState()); - } - emitter(LoginTypeChangeState()); - } - - ///手机号输入 - void _changePhoneNumber(PhoneNumChangeEvent event, Emitter emitter) async { - if (phoneNumController.text.isNotEmpty) { - if (!_canSendSms) { - _canSendSms = true; - emitter(SmsSendTypeChangeState()); - } - if (_loginStateChange()) { - emitter(LoginEventChangeState()); - } - } else { - if (_canSendSms) { - _canSendSms = false; - emitter(SmsSendTypeChangeState()); - } - if (_loginStateChange()) { - emitter(LoginEventChangeState()); - } - } - } - - ///验证码/密码输入变化 - void _checkFiledChange(CheckFieldChangeEvent event, Emitter emitter) async { - if (_loginStateChange()) { - emitter(LoginEventChangeState()); - } - } - - ///是否阅读协议 - void _agreementTypeChange(AgreementChangeEvent event, Emitter emitter) async { - _agreement = !_agreement; - emitter(AgreementTypeChangeState()); - if (_loginStateChange()) { - emitter(LoginEventChangeState()); - } - } - - ///登陆状态判断 - bool _loginStateChange() { - if (_agreement) { - if (phoneNumController.text.isNotEmpty && checkNumController.text.isNotEmpty) { - if (!_canLogin) { - _canLogin = true; - return true; - } - } else { - if (_canLogin) { - _canLogin = false; - return true; - } - } - } else { - if (_canLogin) { - _canLogin = false; - return true; - } - } - return false; - } -} diff --git a/lib/login/loginpage/bloc/login_event.dart b/lib/login/loginpage/bloc/login_event.dart deleted file mode 100644 index c68ec2a..0000000 --- a/lib/login/loginpage/bloc/login_event.dart +++ /dev/null @@ -1,16 +0,0 @@ -part of 'login_bloc.dart'; - -@immutable -abstract class LoginEvent {} -///切换登陆方式 -class ChangeLoginTypeEvent extends LoginEvent {} -///输入手机号 -class PhoneNumChangeEvent extends LoginEvent {} -///输入验证码/密码 -class CheckFieldChangeEvent extends LoginEvent {} -///隐私协议点击 -class AgreementChangeEvent extends LoginEvent {} -///发送验证码 -class RequestSmsCodeEvent extends LoginEvent {} -///请求登陆 -class RequestLoginEvent extends LoginEvent {} diff --git a/lib/login/loginpage/bloc/login_state.dart b/lib/login/loginpage/bloc/login_state.dart deleted file mode 100644 index 191c310..0000000 --- a/lib/login/loginpage/bloc/login_state.dart +++ /dev/null @@ -1,23 +0,0 @@ -part of 'login_bloc.dart'; - -@immutable -abstract class LoginState {} - -class LoginInitial extends LoginState {} - -///登陆按钮状态 -class LoginEventChangeState extends LoginState {} - -///切换登陆方式 -class LoginTypeChangeState extends LoginState {} - -///发送验证码按钮状态 -class SmsSendTypeChangeState extends LoginState {} - -///是否同意协议 -class AgreementTypeChangeState extends LoginState {} -///获取验证码 -class SmsCodeRequestState extends LoginState {} - -///登陆请求结果 -class LoginResultChangeState extends LoginState {} diff --git a/lib/login/loginpage/login_page.dart b/lib/login/loginpage/login_page.dart deleted file mode 100644 index 2b59b64..0000000 --- a/lib/login/loginpage/login_page.dart +++ /dev/null @@ -1,313 +0,0 @@ -import 'package:flutter/gestures.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:wow_english/common/extension/string_extension.dart'; -import 'package:wow_english/common/widgets/textfield_customer_widget.dart'; -import 'package:wow_english/login/loginpage/bloc/login_bloc.dart'; -import 'package:wow_english/login/loginpage/time_widget.dart'; -import 'package:wow_english/route/route.dart'; - -class LoginPage extends StatelessWidget { - const LoginPage({super.key}); - - @override - Widget build(BuildContext context) { - return BlocProvider( - create: (context) => LoginBloc(), - child: _LoginPageView(), - ); - } -} - -class _LoginPageView extends StatelessWidget { - @override - Widget build(BuildContext context) { - return BlocListener( - listener: (context, state){ - if (state is LoginResultChangeState) { - Navigator.of(context).pushNamed(AppRouteName.home); - } - }, - child: _buildLoginViewWidget(), - ); - } - - Widget _buildLoginViewWidget() => BlocBuilder ( - builder: (context, state) { - final bloc = BlocProvider.of(context); - return Scaffold( - body: SafeArea( - child: ListView( - children: [ - Container( - padding: EdgeInsets.only(top: 25.h), - child: Stack( - children: [ - Positioned( - right: 29.w, - child: GestureDetector( - onTap: () => bloc.add(ChangeLoginTypeEvent()), - child: Container( - decoration: BoxDecoration( - image: DecorationImage( - image: AssetImage( - 'login_logo'.assetPng - ), - fit: BoxFit.fill - ), - ), - padding: EdgeInsets.symmetric(horizontal: 18.w,vertical: 5.h), - child: Text( - bloc.isSmsLoginType?'密码登陆':'验证码密码', - style: TextStyle( - fontSize: 16.sp - ), - ), - ), - ) - ), - Center( - child: Column( - children: [ - Image.asset( - 'wow_logo'.assetPng, - height: 81.h, - width: 131.w, - ), - Offstage( - offstage: !bloc.isSmsLoginType, - child: _buildSmsViewWidget(), - ), - Offstage( - offstage: bloc.isSmsLoginType, - child: _buildPwdViewWidget(), - ), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - GestureDetector( - onTap: () => bloc.add(AgreementChangeEvent()), - child: Icon( - bloc.agreement ? Icons.check_circle_outlined:Icons.circle_outlined, - color:bloc.agreement ? Colors.green:Colors.black), - ), - 6.horizontalSpace, - RichText( - text: TextSpan( - children:[ - TextSpan( - text: '我已阅读并同意', - style: TextStyle( - fontSize: 12.sp, - color: const Color(0xFF333333), - ) - ), - TextSpan( - text: '《用户隐私协议》', - style: TextStyle( - fontSize: 12.sp, - color: const Color(0xFF333333), - ), - recognizer: TapGestureRecognizer()..onTap = (){ - Navigator.of(context).pushNamed( - AppRouteName.webView, - arguments: { - 'urlStr':'https://www.zhihu.com', - 'webViewTitle':'用户隐私协议' - }); - }), - TextSpan( - text: ',', - style: TextStyle( - fontSize: 12.sp, - color: const Color(0xFF333333) - ) - ), - TextSpan( - text: '《儿童隐私政策》', - style: TextStyle( - fontSize: 12.sp, - color: const Color(0xFF333333) - ), - recognizer: TapGestureRecognizer()..onTap = (){ - Navigator.of(context).pushNamed( - AppRouteName.webView, - arguments: { - 'urlStr':'https://www.zhihu.com', - 'webViewTitle':'儿童隐私协议' - }); - }) - ] - ), - ) - ], - ), - GestureDetector( - onTap: () { - if (bloc.canLogin) { - bloc.add(RequestLoginEvent()); - } - }, - child: Container( - decoration: BoxDecoration( - image: DecorationImage( - image: AssetImage( - bloc.canLogin?'login_enter'.assetPng:'login_enter_dis'.assetPng - ), - fit: BoxFit.fill - ), - ), - padding: EdgeInsets.symmetric( - horizontal: 28.w, - vertical: 14.h - ), - child: Text( - '登录', - style: TextStyle( - fontSize: 16.sp - ), - ), - ), - ) - ], - ), - ) - ], - ), - ) - ], - ), - ), - ); - }, - ); - - Widget _buildSmsViewWidget()=> BlocBuilder( - builder: (context,state) { - final bloc = BlocProvider.of(context); - return Padding( - padding: EdgeInsets.symmetric(horizontal: 135.w), - child: Column( - children: [ - 15.verticalSpace, - TextFieldCustomerWidget( - height: 55.h, - hitText: '请输入手机号', - textInputType: TextInputType.phone, - bgImageName: 'Input_layer_up', - onChangeValue: (String value) { - bloc.add(PhoneNumChangeEvent()); - }, - controller: bloc.phoneNumController, - ), - 6.5.verticalSpace, - Text('未注册用户登录默认注册', - style: TextStyle( - fontSize: 12.sp, - color: const Color(0xFF999999) - ),), - 4.5.verticalSpace, - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: TextFieldCustomerWidget( - height: 50.h, - hitText: '请输入验证码', - textInputType: TextInputType.number, - bgImageName: 'Input_layer_down', - onChangeValue: (String value) { - bloc.add(CheckFieldChangeEvent()); - }, - controller: bloc.checkNumController, - ) - ), - TimerWidget(canSendSms: bloc.canSendSms) - ], - ) - ], - ), - ); - }); - - Widget _buildPwdViewWidget()=> BlocBuilder( - builder: (context,state){ - final bloc = BlocProvider.of(context); - return Padding( - padding: EdgeInsets.symmetric(horizontal: 90.w), - child: Column( - children: [ - 15.verticalSpace, - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Image.asset( - 'phone'.assetPng, - height: 45.h, - width: 35.w, - ), - 10.5.horizontalSpace, - Expanded( - child: TextFieldCustomerWidget( - height: 50.h, - hitText: '请输入手机号', - textInputType: TextInputType.phone, - bgImageName: 'Input_layer_up', - onChangeValue: (String value) { - bloc.add(PhoneNumChangeEvent()); - }, - controller: bloc.phoneNumController, - ) - ), - 5.horizontalSpace, - SizedBox( - width: 100.w, - height: 55.h, - ) - ], - ), - 12.verticalSpace, - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Image.asset( - 'lock'.assetPng, - height: 34.h, - width: 31.w, - ), - 10.5.horizontalSpace, - Expanded( - child: TextFieldCustomerWidget( - hitText: '请输入密码', - bgImageName: 'Input_layer_down', - onChangeValue: (String value) { - bloc.add(CheckFieldChangeEvent()); - }, - controller: bloc.checkNumController, - ) - ), - 5.horizontalSpace, - GestureDetector( - onTap: () { - Navigator.of(context).pushNamed(AppRouteName.fogPwd); - }, - child: Container( - width: 100.w, - height: 55.h, - alignment: Alignment.centerLeft, - child: Text( - '忘记密码 ?', - style: TextStyle( - fontSize: 12.sp - ), - ), - ), - ) - ], - ) - ], - ), - ); - }); -} diff --git a/lib/login/loginpage/time_widget.dart b/lib/login/loginpage/time_widget.dart deleted file mode 100644 index cbe5069..0000000 --- a/lib/login/loginpage/time_widget.dart +++ /dev/null @@ -1,93 +0,0 @@ -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:wow_english/common/blocs/timerbloc/timer_bloc.dart'; -import 'package:wow_english/common/extension/string_extension.dart'; -import 'package:wow_english/common/widgets/timer_ticker.dart'; - -class TimerWidget extends StatelessWidget { - const TimerWidget({super.key, required this.canSendSms}); - - final bool canSendSms; - - @override - Widget build(BuildContext context) { - return BlocProvider( - create: (_) => TimerBloc(ticker: const TimerTicker()), - child: TimerWidgetView(canSendSms: canSendSms,), - ); - } -} - -class TimerWidgetView extends StatelessWidget { - final bool canSendSms; - final Function()? sendSmsEvent; - const TimerWidgetView({super.key, required this.canSendSms,this.sendSmsEvent}); - - @override - Widget build(BuildContext context) { - return BlocListener( - listener: (context, s) { - if (s is FinishedState) { - ///重置计时器 - context.read().add(ResetEvent()); - } - }, - child: _buildCountdownWidget(), - ); - } - - Widget _buildCountdownWidget() => BlocBuilder( - buildWhen: (prev, state) => prev.runtimeType != state.runtimeType, - builder: (context,state) { - final bloc = BlocProvider.of(context); - return GestureDetector( - onTap: () { - if (canSendSms && !bloc.isCountTimer ) { - bloc.add(StartEvent(duration: state.duration)); - } - }, - child: Container( - decoration: BoxDecoration( - image: DecorationImage( - image: AssetImage( - canSendSms && !bloc.isCountTimer ? 'securitycode'.assetPng:'securitycode_dis'.assetPng - ), - fit: BoxFit.fill - ), - ), - padding: EdgeInsets.symmetric(horizontal:12.w,vertical: 15.h), - child: Row( - children: [ - if (state is RunningState)...[ - const TimerText() - ] else ...[ - Text('获取验证码', - style: TextStyle( - fontSize: 12.sp - ),) - ] - ], - ), - ), - ); - }, - ); -} - -class TimerText extends StatelessWidget { - const TimerText({super.key}); - - @override - Widget build(BuildContext context) { - final duration = context.select((TimerBloc bloc) => bloc.state.duration); - final secondsStr = duration.toString().padLeft(2, '0'); - return Text( - '${secondsStr}s后再次获取', - style: TextStyle( - fontSize: 12.sp - ), - ); - } -} diff --git a/lib/login/setpwd/bloc/set_pwd_bloc.dart b/lib/login/setpwd/bloc/set_pwd_bloc.dart deleted file mode 100644 index 50747c3..0000000 --- a/lib/login/setpwd/bloc/set_pwd_bloc.dart +++ /dev/null @@ -1,121 +0,0 @@ -import 'package:flutter/cupertino.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; - -part 'set_pwd_event.dart'; -part 'set_pwd_state.dart'; - -class SetPwdBloc extends Bloc { - - final String? phoneNumber; - - final TextEditingController passWordFirstController = TextEditingController(); - final TextEditingController passWordSecondController = TextEditingController(); - ///密码是否符合规则(第一个输入框) - bool _passwordEnsure = false; - ///密码是否超过16位(第一个输入框) - bool _passwordLarger = false; - ///是否显示Icon(第一个输入框) - bool _showPwdIcon = false; - ///是否显示Icon(第二个输入框) - bool _showCheckPwdIcon = false; - ///密码是否一致 - bool _passwordCheck = true; - - bool get passwordEnsure => _passwordEnsure; - - bool get passwordCheck => _passwordCheck; - - bool get passwordLarger => _passwordLarger; - - bool get showPwdIcon => _showPwdIcon; - - bool get showCheckPwdIcon => _showCheckPwdIcon; - - bool get ensure => _passwordCheck && _passwordEnsure; - - SetPwdBloc(this.phoneNumber) : super(SetPwdInitial()) { - on(_pwdEnsureTextChange); - on(_pwdCheckTextChange); - on(_setPassword); - } - - void _pwdCheckTextChange(PwdCheckEvent event,Emitter emitter) async { - if(passWordSecondController.text.isEmpty) { - _showCheckPwdIcon = false; - emitter(PasswordCheckIconShowState()); - } else { - if (!_showCheckPwdIcon) { - _showCheckPwdIcon = true; - emitter(PasswordCheckIconShowState()); - } - } - if(passWordFirstController.text == passWordSecondController.text) { - _passwordCheck = true; - emitter(SetCheckPwdState()); - } else { - _passwordCheck = false; - emitter(SetCheckPwdState()); - } - } - - void _pwdEnsureTextChange(PwdEnsureEvent event,Emitter emitter) async { - if (passWordFirstController.text.isEmpty) { - if (_showPwdIcon) { - _showPwdIcon = false; - emitter(PasswordIconShowState()); - } - } else { - if (!_showPwdIcon) { - _showPwdIcon = true; - emitter(PasswordIconShowState()); - } - if(passWordSecondController.text.isNotEmpty) { - if (passWordFirstController.text == passWordSecondController.text) { - _passwordCheck = true; - - } else { - _passwordCheck = false; - } - emitter(SetCheckPwdState()); - } - if (passWordFirstController.text.length >= 8 && passWordFirstController.text.length <=16) { - ///符合密码要求 - if(!_passwordEnsure) { - _passwordEnsure = true; - emitter(SetEnsurePwdState()); - } - if(passWordSecondController.text.isNotEmpty) { - if (passWordFirstController.text == passWordSecondController.text) { - - } - } - if (_passwordLarger) { - _passwordLarger = false; - emitter(PasswordLargeState()); - } - } else { - if(passWordFirstController.text.length > 16) { - ///超过十六位 - if (!_passwordLarger) { - _passwordLarger = true; - emitter(PasswordLargeState()); - } - } else { - if (_passwordLarger) { - _passwordLarger = false; - emitter(PasswordLargeState()); - } - } - ///密码不符合要求 - if(_passwordEnsure) { - _passwordEnsure = false; - emitter(SetEnsurePwdState()); - } - } - } - } - - void _setPassword(SetPasswordEvent event,Emitter emitter) async { - emitter(PasswordSetSuccessState()); - } -} diff --git a/lib/login/setpwd/bloc/set_pwd_event.dart b/lib/login/setpwd/bloc/set_pwd_event.dart deleted file mode 100644 index 20e78f9..0000000 --- a/lib/login/setpwd/bloc/set_pwd_event.dart +++ /dev/null @@ -1,11 +0,0 @@ -part of 'set_pwd_bloc.dart'; - -@immutable -abstract class SetPwdEvent {} - -///密码是否符合规则 -class PwdEnsureEvent extends SetPwdEvent {} -///密码是否一致 -class PwdCheckEvent extends SetPwdEvent {} -///设置密码 -class SetPasswordEvent extends SetPwdEvent {} diff --git a/lib/login/setpwd/bloc/set_pwd_state.dart b/lib/login/setpwd/bloc/set_pwd_state.dart deleted file mode 100644 index a9f5c1e..0000000 --- a/lib/login/setpwd/bloc/set_pwd_state.dart +++ /dev/null @@ -1,18 +0,0 @@ -part of 'set_pwd_bloc.dart'; - -@immutable -abstract class SetPwdState {} - -class SetPwdInitial extends SetPwdState {} - -class SetEnsurePwdState extends SetPwdState {} - -class SetCheckPwdState extends SetPwdState {} - -class PasswordLargeState extends SetPwdState {} - -class PasswordIconShowState extends SetPwdState {} - -class PasswordCheckIconShowState extends SetPwdState {} - -class PasswordSetSuccessState extends SetPwdState {} diff --git a/lib/login/setpwd/set_pwd_page.dart b/lib/login/setpwd/set_pwd_page.dart deleted file mode 100644 index a250db7..0000000 --- a/lib/login/setpwd/set_pwd_page.dart +++ /dev/null @@ -1,196 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:wow_english/common/extension/string_extension.dart'; -import 'package:wow_english/login/setpwd/bloc/set_pwd_bloc.dart'; -import 'package:wow_english/route/route.dart'; - -import '../../common/widgets/textfield_customer_widget.dart'; - -class SetPassWordPage extends StatelessWidget { - const SetPassWordPage({super.key, this.phoneNum}); - final String? phoneNum; - - @override - Widget build(BuildContext context) { - return BlocProvider( - create: (context) => SetPwdBloc(phoneNum), - child: _SetPassWordPageView(), - ); - } -} - -class _SetPassWordPageView extends StatelessWidget { - @override - Widget build(BuildContext context) { - return BlocListener( - listener: (context, s){ - if (s is PasswordSetSuccessState) { - Navigator.of(context).pushNamedAndRemoveUntil(AppRouteName.home, (route) => false); - } - }, - child: _buildSetPwdView(), - ); - } - - Widget _buildSetPwdView() => BlocBuilder( - builder: (context, state) { - final bloc = BlocProvider.of(context); - return Scaffold( - body: Container( - color: Colors.white, - child: SafeArea( - child: ListView( - children: [ - Padding( - padding: EdgeInsets.symmetric(horizontal: 40.w), - child: Column( - children: [ - 34.verticalSpace, - Row( - children: [ - Image.asset( - 'wow_logo'.assetPng, - height: 49.w, - width: 83.5.h, - ), - 12.5.horizontalSpace, - Text( - '欢迎登录wow english\n接下来请设置一下您的密码吧!', - style: TextStyle( - fontSize: 16.5.sp, - color: const Color(0xFF666666) - ), - ) - ], - ), - Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - 43.verticalSpace, - Row( - children: [ - Expanded( - child: TextFieldCustomerWidget( - height: 55.h, - hitText: '请输入八位以上密码', - bgImageName: 'Input_layer_up', - controller: bloc.passWordFirstController, - obscureText: true, - textInputType: TextInputType.emailAddress, - onChangeValue: (String value) => bloc.add(PwdEnsureEvent()), - ) - ), - 10.horizontalSpace, - Opacity( - opacity: bloc.showPwdIcon?1:0, - child: Image.asset( - bloc.passwordEnsure?'login_pass'.assetPng:'login_error'.assetPng, - height: 30, - width: 30, - ), - ) - ], - ), - 9.verticalSpace, - Offstage( - offstage: !bloc.passwordLarger, - child: const Text('您已达到密码最大输入数,请妥善调整密码'), - ), - 9.verticalSpace, - Row( - children: [ - Expanded( - child: TextFieldCustomerWidget( - height: 55.h, - hitText: '请再次输入相同密码', - bgImageName: 'Input_layer_up', - obscureText: true, - textInputType: TextInputType.emailAddress, - controller: bloc.passWordSecondController, - onChangeValue: (String value) => bloc.add(PwdCheckEvent()), - ) - ), - 10.horizontalSpace, - Opacity( - opacity: bloc.showCheckPwdIcon?1:0, - child: Image.asset( - bloc.passwordCheck?'login_pass'.assetPng:'login_error'.assetPng, - height: 30, - width: 30, - ), - ) - ], - ), - 9.verticalSpace, - Offstage( - offstage: bloc.passwordCheck, - child: Text( - '请确认两次输入的密码是否一致', - style: TextStyle( - fontSize: 16.sp, - color: const Color(0xFF333333) - ), - ), - ), - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - GestureDetector( - onTap: () { - if (!bloc.ensure) { - return; - } - bloc.add(SetPasswordEvent()); - }, - child: Container( - decoration: BoxDecoration( - image: DecorationImage( - image: AssetImage( - bloc.ensure?'login_enter'.assetPng:'login_enter_dis'.assetPng - ), - fit: BoxFit.fill - ), - ), - padding: EdgeInsets.symmetric( - horizontal: 28.w, - vertical: 14.h - ), - child: Text( - '确定', - style: TextStyle( - color: Colors.white, - fontSize: 16.sp - ), - ), - ), - ), - 50.horizontalSpace - ], - ) - ], - ), - ), - 30.horizontalSpace, - Image.asset( - 'steven'.assetPng, - height: 254.h, - width: 100.w, - ) - ], - ), - ], - ), - ) - ], - ), - ), - ), - ); - } - ); -} \ No newline at end of file diff --git a/lib/pages/home/bloc/home_bloc.dart b/lib/pages/home/bloc/home_bloc.dart new file mode 100644 index 0000000..d70e546 --- /dev/null +++ b/lib/pages/home/bloc/home_bloc.dart @@ -0,0 +1,14 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +part 'home_event.dart'; +part 'home_state.dart'; + +class HomeBloc extends Bloc { + final PageController pageController; + HomeBloc(this.pageController) : super(HomeInitial()) { + on((event, emit) { + // TODO: implement event handler + }); + } +} diff --git a/lib/pages/home/bloc/home_event.dart b/lib/pages/home/bloc/home_event.dart new file mode 100644 index 0000000..33589ea --- /dev/null +++ b/lib/pages/home/bloc/home_event.dart @@ -0,0 +1,4 @@ +part of 'home_bloc.dart'; + +@immutable +abstract class HomeEvent {} diff --git a/lib/pages/home/bloc/home_state.dart b/lib/pages/home/bloc/home_state.dart new file mode 100644 index 0000000..423dfab --- /dev/null +++ b/lib/pages/home/bloc/home_state.dart @@ -0,0 +1,6 @@ +part of 'home_bloc.dart'; + +@immutable +abstract class HomeState {} + +class HomeInitial extends HomeState {} diff --git a/lib/pages/home/home_page.dart b/lib/pages/home/home_page.dart new file mode 100644 index 0000000..8a9055e --- /dev/null +++ b/lib/pages/home/home_page.dart @@ -0,0 +1,123 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:wow_english/common/extension/string_extension.dart'; +import 'package:wow_english/pages/home/widgets/home_lesson_item_widget.dart'; +import 'package:wow_english/pages/home/widgets/home_tab_header_widget.dart'; +import 'package:wow_english/route/route.dart'; + +import 'bloc/home_bloc.dart'; + +class HomePage extends StatelessWidget { + const HomePage({super.key}); + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (context) => HomeBloc(PageController( + initialPage: 0, + )), + child: _HomePageView(), + ); + } +} + +class _HomePageView extends StatelessWidget { + void _headerActionEvent(HeaderActionType type) { + if (type == HeaderActionType.video) { + Navigator.of(AppRouter.context).pushNamed(AppRouteName.reAfter); + } else if (type == HeaderActionType.phase) { + Navigator.of(AppRouter.context).pushNamed(AppRouteName.lesson); + } else if (type == HeaderActionType.listen) { + Navigator.of(AppRouter.context).pushNamed(AppRouteName.listen); + } else if (type == HeaderActionType.shop) { + Navigator.of(AppRouter.context).pushNamed(AppRouteName.shop); + } else if (type == HeaderActionType.user) { + Navigator.of(AppRouter.context).pushNamed(AppRouteName.user); + } else { + // Navigator.of(AppRouter.context).pushNamed(AppRouteName.topicPic); + // Navigator.of(AppRouter.context).pushNamed(AppRouteName.topicWord); + // Navigator.of(AppRouter.context).pushNamed(AppRouteName.lookVideo); + // Navigator.of(AppRouter.context).pushNamed(AppRouteName.voicePic); + // Navigator.of(AppRouter.context).pushNamed(AppRouteName.voiceWord); + Navigator.of(AppRouter.context).pushNamed(AppRouteName.voiceAnswer); + } + } + + @override + Widget build(BuildContext context) { + return BlocListener( + listener: (context, state){}, + child: _homeView(), + ); + } + + Widget _homeView() => BlocBuilder( + builder: (context, state){ + final bloc = BlocProvider.of(context); + return Scaffold( + body: Container( + color: Colors.white, + child: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + HomeTabHeaderWidget( + actionTap: (HeaderActionType type) { + _headerActionEvent(type); + }, + ), + Expanded( + child: PageView.builder( + itemCount: 10, + controller: bloc.pageController, + pageSnapping: false, + onPageChanged: (int index) { + EasyLoading.showToast(index.toString()); + }, + itemBuilder: (BuildContext context,int index){ + return const HomeLessonItem(); + }) + , + ), + SafeArea( + child: Padding( + padding: EdgeInsets.symmetric(horizontal: 13.w), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + SizedBox( + height: 47.h, + width: 80.w, + ), + Container( + decoration: BoxDecoration( + color: Colors.blue, + borderRadius: BorderRadius.circular(14.5.r), + ), + padding: EdgeInsets.symmetric(vertical: 8.h,horizontal: 24.w), + child: Text( + '3/67', + style: TextStyle( + color: Colors.white, + fontSize: 12.sp + ), + ), + ), + Image.asset( + 'blue-positive'.assetPng, + height: 47.h, + width: 80.w, + ), + ], + ), + ), + ) + ], + ), + ), + ), + ); + }); +} diff --git a/lib/pages/home/widgets/home_lesson_item_widget.dart b/lib/pages/home/widgets/home_lesson_item_widget.dart new file mode 100644 index 0000000..9bf3a85 --- /dev/null +++ b/lib/pages/home/widgets/home_lesson_item_widget.dart @@ -0,0 +1,25 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; + +class HomeLessonItem extends StatelessWidget { + const HomeLessonItem({super.key}); + + @override + Widget build(BuildContext context) { + return SizedBox( + width: double.infinity, + child: ListView.builder( + itemCount: 5, + scrollDirection: Axis.horizontal, + physics: const NeverScrollableScrollPhysics(), + itemBuilder: (BuildContext context,int index){ + return Padding( + padding: EdgeInsets.symmetric(horizontal: 4.w), + child: Image.network( + 'https://img.liblibai.com/web/648331d5a2cb5.png?image_process=format,webp&x-oss-process=image/resize,w_2980,m_lfit/format,webp', + ), + ); + }), + ); + } +} \ No newline at end of file diff --git a/lib/pages/home/widgets/home_tab_header_widget.dart b/lib/pages/home/widgets/home_tab_header_widget.dart new file mode 100644 index 0000000..53eaedf --- /dev/null +++ b/lib/pages/home/widgets/home_tab_header_widget.dart @@ -0,0 +1,131 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:wow_english/common/extension/string_extension.dart'; + +enum HeaderActionType { + //视频跟读 + video, + //阶段选择 + phase, + //磨耳朵 + listen, + //购买 + shop, + //个人信息 + user +} + +class HomeTabHeaderWidget extends StatelessWidget { + + const HomeTabHeaderWidget({super.key, this.actionTap}); + + final Function(HeaderActionType type)? actionTap; + + @override + Widget build(BuildContext context) { + return Container( + height: 45, + width: double.infinity, + color: Colors.purple, + padding: EdgeInsets.symmetric(horizontal: 9.5.w), + child: Row( + children: [ + ScreenUtil().bottomBarHeight.horizontalSpace, + GestureDetector( + onTap: () { + if(actionTap != null) { + actionTap!(HeaderActionType.user); + } + }, + child: Container( + decoration: BoxDecoration( + border: Border.all( + width: 1.0, + color: const Color(0xFF140C10), + ), + borderRadius: BorderRadius.circular(21), + ), + child: const CircleAvatar( + radius: 21, + backgroundImage: NetworkImage( + 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fsafe-img.xhscdn.com%2Fbw1%2Faa1c2213-820a-4223-8757-5f8cee318a28%3FimageView2%2F2%2Fw%2F1080%2Fformat%2Fjpg&refer=http%3A%2F%2Fsafe-img.xhscdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1688713226&t=192b18a613683bcdc5bd76f65c9ff032' + ), + ), + ), + ), + GestureDetector( + onTap: () { + if(actionTap != null) { + actionTap!(HeaderActionType.user); + } + }, + child: Container( + margin: const EdgeInsets.only(left: 7), + padding: const EdgeInsets.all(4.0), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(2), + border: Border.all( + width: 1.0, + color: const Color(0xFF140C10), + style: BorderStyle.solid + ), + ), + child: Text( + 'franky', + style: TextStyle( + color: const Color(0xFF333333), + fontSize: 16.sp + ), + ), + ), + ), + 20.horizontalSpace, + const Expanded( + child:Text( + 'learn wow!yellow', + textAlign:TextAlign.left, + style: TextStyle( + color: Colors.white, + fontSize: 30.0 + ), + ) + ), + IconButton( + onPressed: (){ + if(actionTap != null) { + actionTap!(HeaderActionType.video); + } + }, + icon: Image.asset('video'.assetPng) + ), + IconButton( + onPressed: (){ + if(actionTap != null) { + actionTap!(HeaderActionType.phase); + } + }, + icon: Image.asset('home'.assetPng) + ), + IconButton( + onPressed: (){ + if(actionTap != null) { + actionTap!(HeaderActionType.listen); + } + }, + icon: Image.asset('listen'.assetPng) + ), + IconButton( + onPressed: (){ + if(actionTap != null) { + actionTap!(HeaderActionType.shop); + } + }, + icon: Image.asset('shop'.assetPng) + ), + ScreenUtil().bottomBarHeight.horizontalSpace, + ], + ), + ); + } +} diff --git a/lib/pages/lessons/bloc/lesson_bloc.dart b/lib/pages/lessons/bloc/lesson_bloc.dart new file mode 100644 index 0000000..91c603f --- /dev/null +++ b/lib/pages/lessons/bloc/lesson_bloc.dart @@ -0,0 +1,33 @@ + +import 'package:flutter/cupertino.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +part 'lesson_event.dart'; +part 'lesson_state.dart'; + +class LessonBloc extends Bloc { + + final int pageIndex; + + final PageController pageController; + + int _currentPageIndex = 0; + + int get currentPageIndex => _currentPageIndex; + + LessonBloc(this.pageIndex,this.pageController) : super(LessonInitial()) { + _currentPageIndex = pageIndex; + on(_pageIndexChange); + } + + void _pageIndexChange(PageViewChangeIndexEvent event,Emitter emitter) async { + _currentPageIndex = event.index; + emitter(PageIndexChangeState()); + } + + @override + Future close() { + pageController.dispose(); + return super.close(); + } +} diff --git a/lib/pages/lessons/bloc/lesson_event.dart b/lib/pages/lessons/bloc/lesson_event.dart new file mode 100644 index 0000000..13338d6 --- /dev/null +++ b/lib/pages/lessons/bloc/lesson_event.dart @@ -0,0 +1,9 @@ +part of 'lesson_bloc.dart'; + +@immutable +abstract class LessonEvent {} + +class PageViewChangeIndexEvent extends LessonEvent { + final int index; + PageViewChangeIndexEvent(this.index); +} diff --git a/lib/pages/lessons/bloc/lesson_state.dart b/lib/pages/lessons/bloc/lesson_state.dart new file mode 100644 index 0000000..5c21ecb --- /dev/null +++ b/lib/pages/lessons/bloc/lesson_state.dart @@ -0,0 +1,8 @@ +part of 'lesson_bloc.dart'; + +@immutable +abstract class LessonState {} + +class LessonInitial extends LessonState {} + +class PageIndexChangeState extends LessonState {} diff --git a/lib/pages/lessons/lesson_page.dart b/lib/pages/lessons/lesson_page.dart new file mode 100644 index 0000000..6b1d5e6 --- /dev/null +++ b/lib/pages/lessons/lesson_page.dart @@ -0,0 +1,221 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:wow_english/common/extension/string_extension.dart'; +import 'package:wow_english/common/widgets/we_app_bar.dart'; + +import 'bloc/lesson_bloc.dart'; +import 'widgets/lesson_item_widget.dart'; + +class LessonPage extends StatelessWidget { + const LessonPage({super.key, this.starPageIndex}); + + final int? starPageIndex; + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (context) => LessonBloc( + starPageIndex??0, + PageController( + initialPage: starPageIndex??0, + viewportFraction: 0.3 + ),), + child: _LessonPageView(), + ); + } +} + +class _LessonPageView extends StatelessWidget { + + final double _cardHeight = 240.h; + + final double _numItemHeight = 32.0; + + final double _scale = 0.8; + + @override + Widget build(BuildContext context) { + return BlocListener( + listener: (context, state){}, + child: Scaffold( + appBar: WEAppBar( + leading: IconButton( + onPressed: (){ + Navigator.pop(context); + }, + icon: Image.asset( + 'back'.assetPng, + height: 43, + width: 43, + ) + ), + actions: [ + IconButton( + icon: Image.asset('shop'.assetPng), + color: Colors.white, + onPressed: () { + EasyLoading.showToast('购买'); + }, + ) + ], + ), + body: _lessViewWidget(), + ), + ); + } + + Widget _lessViewWidget() => BlocBuilder( + builder: (context, state){ + final bloc = BlocProvider.of(context); + return Center( + child: SafeArea( + child: Column( + children: [ + SizedBox( + height: _cardHeight, + child: PageView.builder( + itemCount: 10, + controller: bloc.pageController, + onPageChanged: (int index) { + bloc.add(PageViewChangeIndexEvent(index)); + }, + itemBuilder: (context,index) => _itemTransCard(index) + ), + ), + 32.verticalSpace, + SizedBox( + height: 32.h, + width: 660.w, + child: ListView.builder( + itemCount: 10, + scrollDirection: Axis.horizontal, + itemBuilder: (BuildContext context,int index){ + return Container( + height: 32.h, + width: 66.w, + padding: const EdgeInsets.symmetric(horizontal: 5), + child: GestureDetector( + onTap: () { + if (index == bloc.currentPageIndex) { + return; + } + int mill = (index - bloc.currentPageIndex) > 0 ? 100 * (index - bloc.currentPageIndex):100 * (bloc.currentPageIndex-index); + bloc.pageController.animateToPage(index, duration: Duration(milliseconds: mill), curve: Curves.ease); + }, + child: Container( + height: bloc.currentPageIndex == index ? 32:20, + decoration: BoxDecoration( + color: bloc.currentPageIndex == index ? Colors.red:Colors.white, + border: Border.all( + width: 0.5, + color: Colors.black, + ), + ), + alignment: Alignment.center, + child: Text( + (index+1).toString(), + style: TextStyle( + color: bloc.currentPageIndex == index ? Colors.white:Colors.black + ), + ), + ), + ), + ); + }), + // child: PageView.builder( + // itemCount: 10, + // controller: bloc.pageController, + // onPageChanged: (int index) { + // bloc.add(PageViewChangeIndexEvent(index)); + // }, + // itemBuilder: (context,index) => _itemNumCard(index) + // ), + ) + ], + ), + ), + ); + }); + + Widget _itemTransCard(int index) => BlocBuilder( + builder: (context, state) { + final bloc = BlocProvider.of(context); + Matrix4 matrix4 = Matrix4.identity(); + if (index == bloc.currentPageIndex.floor()) { + //当前的item + double currScale = (1 - (bloc.currentPageIndex - index) * (1 - _scale)).toDouble(); + var currTrans = _cardHeight * (1 - currScale) / 2; + + matrix4 = Matrix4.diagonal3Values(1.0, currScale, 1.0) + ..setTranslationRaw(0.0, currTrans, 0.0); + } else if (index == bloc.currentPageIndex.floor() + 1) { + //右边的item + var currScale = _scale + (bloc.currentPageIndex - index + 1) * (1 - _scale); + var currTrans = _cardHeight * (1 - currScale) / 2; + + matrix4 = Matrix4.diagonal3Values(1.0, currScale, 1.0) + ..setTranslationRaw(0.0, currTrans, 0.0); + } else if (index == bloc.currentPageIndex - 1) { + //左边 + var currScale = (1 - (bloc.currentPageIndex - index) * (1 - _scale)).toDouble(); + var currTrans = _cardHeight * (1 - currScale) / 2; + + matrix4 = Matrix4.diagonal3Values(1.0, currScale, 1.0) + ..setTranslationRaw(0.0, currTrans, 0.0); + } else { + //其他,不在屏幕显示的item + matrix4 = Matrix4.diagonal3Values(1.0, _scale, 1.0) + ..setTranslationRaw(0.0, _cardHeight * (1 - _scale) / 2, 0.0); + } + + return Transform( + transform: matrix4, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 10), + child: LessonItemWidget(isSelected: bloc.currentPageIndex == index), + ), + ); + }); + + Widget _itemNumCard(int index) => BlocBuilder( + builder: (context, state) { + final bloc = BlocProvider.of(context); + bool isSelected = bloc.currentPageIndex.floor() == index; + Matrix4 matrix4 = Matrix4.identity(); + if (index == bloc.currentPageIndex.floor()) { + //当前的item + double currScale = (1 - (bloc.currentPageIndex - index) * (1 - _scale)).toDouble(); + var currTrans = _numItemHeight * (1 - currScale) / 2; + + matrix4 = Matrix4.diagonal3Values(1.0, currScale, 1.0) + ..setTranslationRaw(0.0, currTrans, 0.0); + } else if (index == bloc.currentPageIndex.floor() + 1) { + //右边的item + var currScale = _scale + (bloc.currentPageIndex - index + 1) * (1 - _scale); + var currTrans = _numItemHeight * (1 - currScale) / 2; + + matrix4 = Matrix4.diagonal3Values(1.0, currScale, 1.0) + ..setTranslationRaw(0.0, currTrans, 0.0); + } else if (index == bloc.currentPageIndex - 1) { + //左边 + var currScale = (1 - (bloc.currentPageIndex - index) * (1 - _scale)).toDouble(); + var currTrans = _numItemHeight * (1 - currScale) / 2; + + matrix4 = Matrix4.diagonal3Values(1.0, currScale, 1.0) + ..setTranslationRaw(0.0, currTrans, 0.0); + } else { + //其他,不在屏幕显示的item + matrix4 = Matrix4.diagonal3Values(1.0, _scale, 1.0) + ..setTranslationRaw(0.0, _numItemHeight * (1 - _scale) / 2, 0.0); + } + + return Transform( + transform: matrix4, + child: Container( + color: isSelected?Colors.red:Colors.yellow, + ), + ); + }); +} \ No newline at end of file diff --git a/lib/pages/lessons/widgets/lesson_item_widget.dart b/lib/pages/lessons/widgets/lesson_item_widget.dart new file mode 100644 index 0000000..f75319c --- /dev/null +++ b/lib/pages/lessons/widgets/lesson_item_widget.dart @@ -0,0 +1,57 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; + +class LessonItemWidget extends StatelessWidget { + const LessonItemWidget({super.key, required this.isSelected}); + ///是否被选中 + final bool isSelected; + + @override + Widget build(BuildContext context) { + return isSelected?_selectWidget():_unSelectWidget(); + } + + Widget _unSelectWidget() { + return Container( + decoration: const BoxDecoration( + image: DecorationImage( + image: NetworkImage('https://img.liblibai.com/web/648331d033b41.png?image_process=format,webp&x-oss-process=image/resize,w_2980,m_lfit/format,webp'), + ) + ), + ); + } + + Widget _selectWidget() { + return Container( + padding: const EdgeInsets.all(10), + decoration: BoxDecoration( + border: Border.all( + width: 2.0, + color: Colors.red, + style: BorderStyle.solid + ), + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Image.network( + 'https://img.liblibai.com/web/648331d5a2cb5.png?image_process=format,webp&x-oss-process=image/resize,w_2980,m_lfit/format,webp', + ), + ), + 10.verticalSpace, + Container( + color: Colors.red, + width: double.infinity, + child: const Column( + children: [ + Text('red'), + Text('第三段') + ], + ), + ) + ], + ), + ); + } +} \ No newline at end of file diff --git a/lib/pages/listen/bloc/listen_bloc.dart b/lib/pages/listen/bloc/listen_bloc.dart new file mode 100644 index 0000000..cf2c7b6 --- /dev/null +++ b/lib/pages/listen/bloc/listen_bloc.dart @@ -0,0 +1,14 @@ + +import 'package:flutter/cupertino.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +part 'listen_event.dart'; +part 'listen_state.dart'; + +class ListenBloc extends Bloc { + ListenBloc() : super(ListenInitial()) { + on((event, emit) { + // TODO: implement event handler + }); + } +} diff --git a/lib/pages/listen/bloc/listen_event.dart b/lib/pages/listen/bloc/listen_event.dart new file mode 100644 index 0000000..84f8d1c --- /dev/null +++ b/lib/pages/listen/bloc/listen_event.dart @@ -0,0 +1,4 @@ +part of 'listen_bloc.dart'; + +@immutable +abstract class ListenEvent {} diff --git a/lib/pages/listen/bloc/listen_state.dart b/lib/pages/listen/bloc/listen_state.dart new file mode 100644 index 0000000..dfb830f --- /dev/null +++ b/lib/pages/listen/bloc/listen_state.dart @@ -0,0 +1,6 @@ +part of 'listen_bloc.dart'; + +@immutable +abstract class ListenState {} + +class ListenInitial extends ListenState {} diff --git a/lib/pages/listen/listen_page.dart b/lib/pages/listen/listen_page.dart new file mode 100644 index 0000000..e57725b --- /dev/null +++ b/lib/pages/listen/listen_page.dart @@ -0,0 +1,52 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:wow_english/common/widgets/we_app_bar.dart'; + +import 'bloc/listen_bloc.dart'; +import 'widgets/listen_item_widget.dart'; + +class ListenPage extends StatelessWidget { + const ListenPage({super.key}); + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (context) => ListenBloc(), + child: _ListenPageView(), + ); + } +} + +class _ListenPageView extends StatelessWidget { + @override + Widget build(BuildContext context) { + return BlocListener( + listener: (context, state) { + + }, + child: Scaffold( + appBar: const WEAppBar( + titleText: '磨耳朵', + centerTitle: false, + ), + body: _listenView(), + ), + ); + } + + Widget _listenView() => BlocBuilder( + builder: (context, state) { + return ListView.builder( + itemCount: 10, + scrollDirection: Axis.horizontal, + padding: EdgeInsets.symmetric(horizontal: 30.w,vertical: 36.h), + itemBuilder: (BuildContext context,int index){ + return ListenItemWidget( + isLock: (index < 5), + clickEvent: (){ + + }); + }); + }); +} \ No newline at end of file diff --git a/lib/pages/listen/widgets/listen_item_widget.dart b/lib/pages/listen/widgets/listen_item_widget.dart new file mode 100644 index 0000000..3f73252 --- /dev/null +++ b/lib/pages/listen/widgets/listen_item_widget.dart @@ -0,0 +1,80 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:wow_english/common/extension/string_extension.dart'; + +class ListenItemWidget extends StatelessWidget { + const ListenItemWidget({super.key, this.isLock = false, required this.clickEvent}); + + final Function() clickEvent; + + final bool isLock; + + @override + Widget build(BuildContext context) { + return Padding( + padding: EdgeInsets.symmetric(horizontal: 8.5.w), + child: Column( + children: [ + GestureDetector( + onTap: () { + if (!isLock) { + clickEvent(); + } + }, + child: ClipRRect( + borderRadius:BorderRadius.circular(90.r), + child: Stack( + alignment:Alignment.center, + children: [ + Image.network( + 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fsafe-img.xhscdn.com%2Fbw1%2Faa1c2213-820a-4223-8757-5f8cee318a28%3FimageView2%2F2%2Fw%2F1080%2Fformat%2Fjpg&refer=http%3A%2F%2Fsafe-img.xhscdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1688713226&t=192b18a613683bcdc5bd76f65c9ff032', + height: 180.h, + width: 180.h, + fit: BoxFit.fill, + ), + Offstage( + offstage: isLock, + child: Container( + height: 180.h, + width: 180.h, + color: const Color.fromRGBO(1, 1, 0, 0.5), + ), + ), + Offstage( + offstage: isLock, + child: Image.asset( + 'listen_lock'.assetPng, + height: 36.h, + width: 41.w, + ), + ) + ], + ), + ), + ), + 23.verticalSpace, + Container( + height: 40.h, + padding: EdgeInsets.symmetric(horizontal: 22.w), + decoration: BoxDecoration( + color: const Color(0xFFFFCC00), + borderRadius: BorderRadius.circular(20.r), + border: Border.all( + width: 1.0, + color: const Color(0xFF333333), + ), + ), + alignment: Alignment.center, + child: Text( + 'listen title', + style: TextStyle( + fontSize: 20.sp, + color: const Color(0xFF333333) + ), + ), + ) + ], + ), + ); + } +} \ No newline at end of file diff --git a/lib/pages/login/forgetpwd/bloc/forget_pwd_home_bloc.dart b/lib/pages/login/forgetpwd/bloc/forget_pwd_home_bloc.dart new file mode 100644 index 0000000..74999e1 --- /dev/null +++ b/lib/pages/login/forgetpwd/bloc/forget_pwd_home_bloc.dart @@ -0,0 +1,71 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:common_utils/common_utils.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; + +part 'forget_pwd_home_event.dart'; +part 'forget_pwd_home_state.dart'; + +class ForgetPwdHomeBloc extends Bloc { + + ///是否可以发送验证码 + bool _canSendSms = false; + bool _canSetPwd = false; + + bool get canSendSms => _canSendSms; + bool get canSetPwd => _canSetPwd; + + final TextEditingController phoneNumController = TextEditingController(); + final TextEditingController checkNumController = TextEditingController(); + + ForgetPwdHomeBloc() : super(ForgetPwdHomeInitial()) { + on(_changePhoneNumber); + on(_changeCodeNumber); + on(_setPassWord); + on(_sendSmsCode); + } + + void _changePhoneNumber(PhoneNumChangeEvent event, Emitter emitter) async { + if (phoneNumController.text.isNotEmpty) { + if (!_canSendSms) { + _canSendSms = true; + emitter(SendSmsCodeTypeChangeState()); + emitter(SetPwdTypeChangeState()); + } + } else { + if (_canSendSms) { + _canSendSms = false; + emitter(SendSmsCodeTypeChangeState()); + emitter(SetPwdTypeChangeState()); + } + } + } + + void _changeCodeNumber(CheckCodeChangeEvent event, Emitter emitter) async { + if (checkNumController.text.isNotEmpty) { + if (!_canSetPwd) { + _canSetPwd = true; + emitter(SendSmsCodeTypeChangeState()); + emitter(SetPwdTypeChangeState()); + } + } else { + if (_canSetPwd) { + _canSetPwd = false; + emitter(SendSmsCodeTypeChangeState()); + emitter(SetPwdTypeChangeState()); + } + } + } + + void _setPassWord(SetPassWordEvent event,Emitter emitter) async { + if(!RegexUtil.isMobileExact(phoneNumController.text)) { + EasyLoading.showToast('手机号不正确!'); + return; + } + emitter(SetPwdCheckCodeState()); + } + + void _sendSmsCode(SendSmsCodeEvent event,Emitter emitter) async { + + } +} diff --git a/lib/pages/login/forgetpwd/bloc/forget_pwd_home_event.dart b/lib/pages/login/forgetpwd/bloc/forget_pwd_home_event.dart new file mode 100644 index 0000000..0be0181 --- /dev/null +++ b/lib/pages/login/forgetpwd/bloc/forget_pwd_home_event.dart @@ -0,0 +1,12 @@ +part of 'forget_pwd_home_bloc.dart'; + +@immutable +abstract class ForgetPwdHomeEvent {} + +class PhoneNumChangeEvent extends ForgetPwdHomeEvent {} + +class CheckCodeChangeEvent extends ForgetPwdHomeEvent {} + +class SetPassWordEvent extends ForgetPwdHomeEvent {} + +class SendSmsCodeEvent extends ForgetPwdHomeEvent {} diff --git a/lib/pages/login/forgetpwd/bloc/forget_pwd_home_state.dart b/lib/pages/login/forgetpwd/bloc/forget_pwd_home_state.dart new file mode 100644 index 0000000..cbe7bfa --- /dev/null +++ b/lib/pages/login/forgetpwd/bloc/forget_pwd_home_state.dart @@ -0,0 +1,12 @@ +part of 'forget_pwd_home_bloc.dart'; + +@immutable +abstract class ForgetPwdHomeState {} + +class ForgetPwdHomeInitial extends ForgetPwdHomeState {} +///是否能发送验证码 +class SendSmsCodeTypeChangeState extends ForgetPwdHomeState {} +///是否能设置密码 +class SetPwdTypeChangeState extends ForgetPwdHomeState {} +///验证码验证是否成功 +class SetPwdCheckCodeState extends ForgetPwdHomeState {} diff --git a/lib/pages/login/forgetpwd/forget_password_home_page.dart b/lib/pages/login/forgetpwd/forget_password_home_page.dart new file mode 100644 index 0000000..aede945 --- /dev/null +++ b/lib/pages/login/forgetpwd/forget_password_home_page.dart @@ -0,0 +1,170 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:wow_english/common/extension/string_extension.dart'; +import 'package:wow_english/common/widgets/textfield_customer_widget.dart'; +import 'package:wow_english/pages/login/loginpage/time_widget.dart'; +import 'package:wow_english/route/route.dart'; + +import 'bloc/forget_pwd_home_bloc.dart'; + +class ForgetPasswordHomePage extends StatelessWidget { + const ForgetPasswordHomePage({super.key}); + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (context) => ForgetPwdHomeBloc(), + child: _ForgetPasswordHomePageView(), + ); + } +} + +class _ForgetPasswordHomePageView extends StatelessWidget { + @override + Widget build(BuildContext context) { + return BlocListener( + listener: (context, state) { + if (state is SetPwdCheckCodeState) { + Navigator.of(context).pushNamed(AppRouteName.setPwd,arguments: {'phoneNumber':context.read().phoneNumController.text}); + } + }, + child: _buildForgetPwdView(), + ); + } + + Widget _buildForgetPwdView() => BlocBuilder( + builder: (context, state) { + final bloc = BlocProvider.of(context); + return Scaffold( + body: Container( + color: Colors.white, + child: SafeArea( + child: ListView( + children: [ + Padding( + padding: EdgeInsets.only(left: 49.w,right: 10.w), + child: Column( + children: [ + 34.verticalSpace, + Row( + children: [ + Image.asset( + 'wow_logo'.assetPng, + height: 49.w, + width: 83.5.h, + ), + 12.5.horizontalSpace, + Text( + '修改密码\n请输入您的手机号和验证码吧', + style: TextStyle( + fontSize: 16.sp, + color: const Color(0xFF666666) + ), + ) + ], + ), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: Column( + children: [ + 44.5.verticalSpace, + Row( + children: [ + Image.asset( + 'phone'.assetPng, + height: 45.h, + width: 35.w, + ), + 15.horizontalSpace, + Expanded( + child: TextFieldCustomerWidget( + height: 50.h, + hitText: '请输入当前手机号', + textInputType: TextInputType.phone, + bgImageName: 'Input_layer_up', + onChangeValue: (String value) { + bloc.add(PhoneNumChangeEvent()); + }, + controller: bloc.phoneNumController, + ) + ) + ], + ), + 11.5.verticalSpace, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Image.asset( + 'lock'.assetPng, + height: 34.h, + width: 31.w, + ), + 18.5.horizontalSpace, + Expanded( + child: TextFieldCustomerWidget( + hitText: '请输入验证码', + bgImageName: 'Input_layer_down', + onChangeValue: (String value) { + bloc.add(CheckCodeChangeEvent()); + }, + textInputType: TextInputType.emailAddress, + controller: bloc.checkNumController, + ) + ), + 16.5.horizontalSpace, + TimerWidget(canSendSms: bloc.canSendSms) + ], + ) + ], + ) + ), + 2.verticalSpace, + Image.asset( + 'steven_bride'.assetPng, + height: 173.h, + width: 157.w, + ) + ], + ), + GestureDetector( + onTap: () { + if (bloc.canSetPwd) { + bloc.add(SetPassWordEvent()); + } + }, + child: Container( + decoration: BoxDecoration( + image: DecorationImage( + image: AssetImage( + bloc.canSetPwd?'login_enter'.assetPng:'login_enter_dis'.assetPng + ), + fit: BoxFit.fill + ), + ), + padding: EdgeInsets.symmetric( + horizontal: 28.w, + vertical: 14.h + ), + child: Text( + '确定', + style: TextStyle( + fontSize: 16.sp, + color: Colors.white + ), + ), + ), + ) + ], + ), + ) + ], + ), + ), + ), + ); + } + ); +} \ No newline at end of file diff --git a/lib/pages/login/loginpage/bloc/login_bloc.dart b/lib/pages/login/loginpage/bloc/login_bloc.dart new file mode 100644 index 0000000..87bc0fc --- /dev/null +++ b/lib/pages/login/loginpage/bloc/login_bloc.dart @@ -0,0 +1,171 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; + +import '../../../../common/request/api_response/api_response_entity.dart'; +import '../../../../common/request/apis.dart'; +import '../../../../common/request/request.dart'; +import '../../../../common/request/request_client.dart'; +import '../../../../models/user_entity.dart'; + +part 'login_event.dart'; +part 'login_state.dart'; + +enum LoginType { + ///密码登陆 + pwd, + + ///验证码登陆 + sms, +} + +class LoginBloc extends Bloc { + bool _canLogin = false; + + ///是否可以发送验证码 + bool _canSendSms = false; + + ///是否阅读协议 + bool _agreement = false; + + ///登陆方式 + //LoginType _loginType = LoginType.sms; + bool _isSmsLoginType = true; + + final TextEditingController phoneNumController = TextEditingController(); + final TextEditingController checkNumController = TextEditingController(); + + bool get canLogin => _canLogin; + + bool get agreement => _agreement; + + //LoginType get loginType => _loginType; + + bool get isSmsLoginType => _isSmsLoginType; + + bool get canSendSms => _canSendSms; + + LoginBloc() : super(LoginInitial()) { + on(_requestLoginApi); + on(_changeLoginType); + on(_changePhoneNumber); + on(_agreementTypeChange); + on(_checkFiledChange); + on(_requestSmsCodeApi); + } + + ///请求登陆 + void _requestLoginApi(RequestLoginEvent event, Emitter emitter) async { + var phoneNumber = phoneNumController.text; + if (phoneNumber.isEmpty) { + EasyLoading.showToast('号码不能为空'); + return; + } + + var checkNumber = checkNumController.text; + if (checkNumber.isEmpty) { + var text = _isSmsLoginType ? '密码' : '验证码'; + EasyLoading.showToast('$text不能为空'); + return; + } + var checkKey = _isSmsLoginType ? 'smsCode' : 'password'; + var type = _isSmsLoginType ? 'sms_code' : 'pwd'; + + request(() async { + var params = {'phoneNum': phoneNumber, 'type': type, checkKey: checkNumber}; + await requestClient.post( + Apis.login, + data: params, + onResponse: (ApiResponse response) { + print('response=$response'); + // todo 持久化用户对象 + // todo 写入全局对象 + //emitter.call(LoginResultChangeState()); + }, + onError: (e) { + EasyLoading.showToast('登陆失败:${e.message}'); + return true; + }, + ); + }); + } + + ///请求验证码 + void _requestSmsCodeApi(RequestSmsCodeEvent event, Emitter emitter) async { + + } + + ///切换登陆方式 + void _changeLoginType(ChangeLoginTypeEvent event, Emitter emitter) async { + if (_isSmsLoginType) { + _isSmsLoginType = false; + } else { + _isSmsLoginType = true; + } + checkNumController.clear(); + if (_loginStateChange()) { + emitter(LoginEventChangeState()); + } + emitter(LoginTypeChangeState()); + } + + ///手机号输入 + void _changePhoneNumber(PhoneNumChangeEvent event, Emitter emitter) async { + if (phoneNumController.text.isNotEmpty) { + if (!_canSendSms) { + _canSendSms = true; + emitter(SmsSendTypeChangeState()); + } + if (_loginStateChange()) { + emitter(LoginEventChangeState()); + } + } else { + if (_canSendSms) { + _canSendSms = false; + emitter(SmsSendTypeChangeState()); + } + if (_loginStateChange()) { + emitter(LoginEventChangeState()); + } + } + } + + ///验证码/密码输入变化 + void _checkFiledChange(CheckFieldChangeEvent event, Emitter emitter) async { + if (_loginStateChange()) { + emitter(LoginEventChangeState()); + } + } + + ///是否阅读协议 + void _agreementTypeChange(AgreementChangeEvent event, Emitter emitter) async { + _agreement = !_agreement; + emitter(AgreementTypeChangeState()); + if (_loginStateChange()) { + emitter(LoginEventChangeState()); + } + } + + ///登陆状态判断 + bool _loginStateChange() { + if (_agreement) { + if (phoneNumController.text.isNotEmpty && checkNumController.text.isNotEmpty) { + if (!_canLogin) { + _canLogin = true; + return true; + } + } else { + if (_canLogin) { + _canLogin = false; + return true; + } + } + } else { + if (_canLogin) { + _canLogin = false; + return true; + } + } + return false; + } +} diff --git a/lib/pages/login/loginpage/bloc/login_event.dart b/lib/pages/login/loginpage/bloc/login_event.dart new file mode 100644 index 0000000..c68ec2a --- /dev/null +++ b/lib/pages/login/loginpage/bloc/login_event.dart @@ -0,0 +1,16 @@ +part of 'login_bloc.dart'; + +@immutable +abstract class LoginEvent {} +///切换登陆方式 +class ChangeLoginTypeEvent extends LoginEvent {} +///输入手机号 +class PhoneNumChangeEvent extends LoginEvent {} +///输入验证码/密码 +class CheckFieldChangeEvent extends LoginEvent {} +///隐私协议点击 +class AgreementChangeEvent extends LoginEvent {} +///发送验证码 +class RequestSmsCodeEvent extends LoginEvent {} +///请求登陆 +class RequestLoginEvent extends LoginEvent {} diff --git a/lib/pages/login/loginpage/bloc/login_state.dart b/lib/pages/login/loginpage/bloc/login_state.dart new file mode 100644 index 0000000..191c310 --- /dev/null +++ b/lib/pages/login/loginpage/bloc/login_state.dart @@ -0,0 +1,23 @@ +part of 'login_bloc.dart'; + +@immutable +abstract class LoginState {} + +class LoginInitial extends LoginState {} + +///登陆按钮状态 +class LoginEventChangeState extends LoginState {} + +///切换登陆方式 +class LoginTypeChangeState extends LoginState {} + +///发送验证码按钮状态 +class SmsSendTypeChangeState extends LoginState {} + +///是否同意协议 +class AgreementTypeChangeState extends LoginState {} +///获取验证码 +class SmsCodeRequestState extends LoginState {} + +///登陆请求结果 +class LoginResultChangeState extends LoginState {} diff --git a/lib/pages/login/loginpage/login_page.dart b/lib/pages/login/loginpage/login_page.dart new file mode 100644 index 0000000..23c7666 --- /dev/null +++ b/lib/pages/login/loginpage/login_page.dart @@ -0,0 +1,314 @@ +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:wow_english/common/extension/string_extension.dart'; +import 'package:wow_english/common/widgets/textfield_customer_widget.dart'; +import 'package:wow_english/pages/login/loginpage/time_widget.dart'; +import 'package:wow_english/route/route.dart'; + +import 'bloc/login_bloc.dart'; + +class LoginPage extends StatelessWidget { + const LoginPage({super.key}); + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (context) => LoginBloc(), + child: _LoginPageView(), + ); + } +} + +class _LoginPageView extends StatelessWidget { + @override + Widget build(BuildContext context) { + return BlocListener( + listener: (context, state){ + if (state is LoginResultChangeState) { + Navigator.of(context).pushNamed(AppRouteName.home); + } + }, + child: _buildLoginViewWidget(), + ); + } + + Widget _buildLoginViewWidget() => BlocBuilder ( + builder: (context, state) { + final bloc = BlocProvider.of(context); + return Scaffold( + body: SafeArea( + child: ListView( + children: [ + Container( + padding: EdgeInsets.only(top: 25.h), + child: Stack( + children: [ + Positioned( + right: 29.w, + child: GestureDetector( + onTap: () => bloc.add(ChangeLoginTypeEvent()), + child: Container( + decoration: BoxDecoration( + image: DecorationImage( + image: AssetImage( + 'login_logo'.assetPng + ), + fit: BoxFit.fill + ), + ), + padding: EdgeInsets.symmetric(horizontal: 18.w,vertical: 5.h), + child: Text( + bloc.isSmsLoginType?'密码登陆':'验证码密码', + style: TextStyle( + fontSize: 16.sp + ), + ), + ), + ) + ), + Center( + child: Column( + children: [ + Image.asset( + 'wow_logo'.assetPng, + height: 81.h, + width: 131.w, + ), + Offstage( + offstage: !bloc.isSmsLoginType, + child: _buildSmsViewWidget(), + ), + Offstage( + offstage: bloc.isSmsLoginType, + child: _buildPwdViewWidget(), + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + GestureDetector( + onTap: () => bloc.add(AgreementChangeEvent()), + child: Icon( + bloc.agreement ? Icons.check_circle_outlined:Icons.circle_outlined, + color:bloc.agreement ? Colors.green:Colors.black), + ), + 6.horizontalSpace, + RichText( + text: TextSpan( + children:[ + TextSpan( + text: '我已阅读并同意', + style: TextStyle( + fontSize: 12.sp, + color: const Color(0xFF333333), + ) + ), + TextSpan( + text: '《用户隐私协议》', + style: TextStyle( + fontSize: 12.sp, + color: const Color(0xFF333333), + ), + recognizer: TapGestureRecognizer()..onTap = (){ + Navigator.of(context).pushNamed( + AppRouteName.webView, + arguments: { + 'urlStr':'https://www.zhihu.com', + 'webViewTitle':'用户隐私协议' + }); + }), + TextSpan( + text: ',', + style: TextStyle( + fontSize: 12.sp, + color: const Color(0xFF333333) + ) + ), + TextSpan( + text: '《儿童隐私政策》', + style: TextStyle( + fontSize: 12.sp, + color: const Color(0xFF333333) + ), + recognizer: TapGestureRecognizer()..onTap = (){ + Navigator.of(context).pushNamed( + AppRouteName.webView, + arguments: { + 'urlStr':'https://www.zhihu.com', + 'webViewTitle':'儿童隐私协议' + }); + }) + ] + ), + ) + ], + ), + GestureDetector( + onTap: () { + if (bloc.canLogin) { + bloc.add(RequestLoginEvent()); + } + }, + child: Container( + decoration: BoxDecoration( + image: DecorationImage( + image: AssetImage( + bloc.canLogin?'login_enter'.assetPng:'login_enter_dis'.assetPng + ), + fit: BoxFit.fill + ), + ), + padding: EdgeInsets.symmetric( + horizontal: 28.w, + vertical: 14.h + ), + child: Text( + '登录', + style: TextStyle( + fontSize: 16.sp + ), + ), + ), + ) + ], + ), + ) + ], + ), + ) + ], + ), + ), + ); + }, + ); + + Widget _buildSmsViewWidget()=> BlocBuilder( + builder: (context,state) { + final bloc = BlocProvider.of(context); + return Padding( + padding: EdgeInsets.symmetric(horizontal: 135.w), + child: Column( + children: [ + 15.verticalSpace, + TextFieldCustomerWidget( + height: 55.h, + hitText: '请输入手机号', + textInputType: TextInputType.phone, + bgImageName: 'Input_layer_up', + onChangeValue: (String value) { + bloc.add(PhoneNumChangeEvent()); + }, + controller: bloc.phoneNumController, + ), + 6.5.verticalSpace, + Text('未注册用户登录默认注册', + style: TextStyle( + fontSize: 12.sp, + color: const Color(0xFF999999) + ),), + 4.5.verticalSpace, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: TextFieldCustomerWidget( + height: 50.h, + hitText: '请输入验证码', + textInputType: TextInputType.number, + bgImageName: 'Input_layer_down', + onChangeValue: (String value) { + bloc.add(CheckFieldChangeEvent()); + }, + controller: bloc.checkNumController, + ) + ), + TimerWidget(canSendSms: bloc.canSendSms) + ], + ) + ], + ), + ); + }); + + Widget _buildPwdViewWidget()=> BlocBuilder( + builder: (context,state){ + final bloc = BlocProvider.of(context); + return Padding( + padding: EdgeInsets.symmetric(horizontal: 90.w), + child: Column( + children: [ + 15.verticalSpace, + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image.asset( + 'phone'.assetPng, + height: 45.h, + width: 35.w, + ), + 10.5.horizontalSpace, + Expanded( + child: TextFieldCustomerWidget( + height: 50.h, + hitText: '请输入手机号', + textInputType: TextInputType.phone, + bgImageName: 'Input_layer_up', + onChangeValue: (String value) { + bloc.add(PhoneNumChangeEvent()); + }, + controller: bloc.phoneNumController, + ) + ), + 5.horizontalSpace, + SizedBox( + width: 100.w, + height: 55.h, + ) + ], + ), + 12.verticalSpace, + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image.asset( + 'lock'.assetPng, + height: 34.h, + width: 31.w, + ), + 10.5.horizontalSpace, + Expanded( + child: TextFieldCustomerWidget( + hitText: '请输入密码', + bgImageName: 'Input_layer_down', + onChangeValue: (String value) { + bloc.add(CheckFieldChangeEvent()); + }, + controller: bloc.checkNumController, + ) + ), + 5.horizontalSpace, + GestureDetector( + onTap: () { + Navigator.of(context).pushNamed(AppRouteName.fogPwd); + }, + child: Container( + width: 100.w, + height: 55.h, + alignment: Alignment.centerLeft, + child: Text( + '忘记密码 ?', + style: TextStyle( + fontSize: 12.sp + ), + ), + ), + ) + ], + ) + ], + ), + ); + }); +} diff --git a/lib/pages/login/loginpage/time_widget.dart b/lib/pages/login/loginpage/time_widget.dart new file mode 100644 index 0000000..cbe5069 --- /dev/null +++ b/lib/pages/login/loginpage/time_widget.dart @@ -0,0 +1,93 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:wow_english/common/blocs/timerbloc/timer_bloc.dart'; +import 'package:wow_english/common/extension/string_extension.dart'; +import 'package:wow_english/common/widgets/timer_ticker.dart'; + +class TimerWidget extends StatelessWidget { + const TimerWidget({super.key, required this.canSendSms}); + + final bool canSendSms; + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (_) => TimerBloc(ticker: const TimerTicker()), + child: TimerWidgetView(canSendSms: canSendSms,), + ); + } +} + +class TimerWidgetView extends StatelessWidget { + final bool canSendSms; + final Function()? sendSmsEvent; + const TimerWidgetView({super.key, required this.canSendSms,this.sendSmsEvent}); + + @override + Widget build(BuildContext context) { + return BlocListener( + listener: (context, s) { + if (s is FinishedState) { + ///重置计时器 + context.read().add(ResetEvent()); + } + }, + child: _buildCountdownWidget(), + ); + } + + Widget _buildCountdownWidget() => BlocBuilder( + buildWhen: (prev, state) => prev.runtimeType != state.runtimeType, + builder: (context,state) { + final bloc = BlocProvider.of(context); + return GestureDetector( + onTap: () { + if (canSendSms && !bloc.isCountTimer ) { + bloc.add(StartEvent(duration: state.duration)); + } + }, + child: Container( + decoration: BoxDecoration( + image: DecorationImage( + image: AssetImage( + canSendSms && !bloc.isCountTimer ? 'securitycode'.assetPng:'securitycode_dis'.assetPng + ), + fit: BoxFit.fill + ), + ), + padding: EdgeInsets.symmetric(horizontal:12.w,vertical: 15.h), + child: Row( + children: [ + if (state is RunningState)...[ + const TimerText() + ] else ...[ + Text('获取验证码', + style: TextStyle( + fontSize: 12.sp + ),) + ] + ], + ), + ), + ); + }, + ); +} + +class TimerText extends StatelessWidget { + const TimerText({super.key}); + + @override + Widget build(BuildContext context) { + final duration = context.select((TimerBloc bloc) => bloc.state.duration); + final secondsStr = duration.toString().padLeft(2, '0'); + return Text( + '${secondsStr}s后再次获取', + style: TextStyle( + fontSize: 12.sp + ), + ); + } +} diff --git a/lib/pages/login/setpwd/bloc/set_pwd_bloc.dart b/lib/pages/login/setpwd/bloc/set_pwd_bloc.dart new file mode 100644 index 0000000..50747c3 --- /dev/null +++ b/lib/pages/login/setpwd/bloc/set_pwd_bloc.dart @@ -0,0 +1,121 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +part 'set_pwd_event.dart'; +part 'set_pwd_state.dart'; + +class SetPwdBloc extends Bloc { + + final String? phoneNumber; + + final TextEditingController passWordFirstController = TextEditingController(); + final TextEditingController passWordSecondController = TextEditingController(); + ///密码是否符合规则(第一个输入框) + bool _passwordEnsure = false; + ///密码是否超过16位(第一个输入框) + bool _passwordLarger = false; + ///是否显示Icon(第一个输入框) + bool _showPwdIcon = false; + ///是否显示Icon(第二个输入框) + bool _showCheckPwdIcon = false; + ///密码是否一致 + bool _passwordCheck = true; + + bool get passwordEnsure => _passwordEnsure; + + bool get passwordCheck => _passwordCheck; + + bool get passwordLarger => _passwordLarger; + + bool get showPwdIcon => _showPwdIcon; + + bool get showCheckPwdIcon => _showCheckPwdIcon; + + bool get ensure => _passwordCheck && _passwordEnsure; + + SetPwdBloc(this.phoneNumber) : super(SetPwdInitial()) { + on(_pwdEnsureTextChange); + on(_pwdCheckTextChange); + on(_setPassword); + } + + void _pwdCheckTextChange(PwdCheckEvent event,Emitter emitter) async { + if(passWordSecondController.text.isEmpty) { + _showCheckPwdIcon = false; + emitter(PasswordCheckIconShowState()); + } else { + if (!_showCheckPwdIcon) { + _showCheckPwdIcon = true; + emitter(PasswordCheckIconShowState()); + } + } + if(passWordFirstController.text == passWordSecondController.text) { + _passwordCheck = true; + emitter(SetCheckPwdState()); + } else { + _passwordCheck = false; + emitter(SetCheckPwdState()); + } + } + + void _pwdEnsureTextChange(PwdEnsureEvent event,Emitter emitter) async { + if (passWordFirstController.text.isEmpty) { + if (_showPwdIcon) { + _showPwdIcon = false; + emitter(PasswordIconShowState()); + } + } else { + if (!_showPwdIcon) { + _showPwdIcon = true; + emitter(PasswordIconShowState()); + } + if(passWordSecondController.text.isNotEmpty) { + if (passWordFirstController.text == passWordSecondController.text) { + _passwordCheck = true; + + } else { + _passwordCheck = false; + } + emitter(SetCheckPwdState()); + } + if (passWordFirstController.text.length >= 8 && passWordFirstController.text.length <=16) { + ///符合密码要求 + if(!_passwordEnsure) { + _passwordEnsure = true; + emitter(SetEnsurePwdState()); + } + if(passWordSecondController.text.isNotEmpty) { + if (passWordFirstController.text == passWordSecondController.text) { + + } + } + if (_passwordLarger) { + _passwordLarger = false; + emitter(PasswordLargeState()); + } + } else { + if(passWordFirstController.text.length > 16) { + ///超过十六位 + if (!_passwordLarger) { + _passwordLarger = true; + emitter(PasswordLargeState()); + } + } else { + if (_passwordLarger) { + _passwordLarger = false; + emitter(PasswordLargeState()); + } + } + ///密码不符合要求 + if(_passwordEnsure) { + _passwordEnsure = false; + emitter(SetEnsurePwdState()); + } + } + } + } + + void _setPassword(SetPasswordEvent event,Emitter emitter) async { + emitter(PasswordSetSuccessState()); + } +} diff --git a/lib/pages/login/setpwd/bloc/set_pwd_event.dart b/lib/pages/login/setpwd/bloc/set_pwd_event.dart new file mode 100644 index 0000000..20e78f9 --- /dev/null +++ b/lib/pages/login/setpwd/bloc/set_pwd_event.dart @@ -0,0 +1,11 @@ +part of 'set_pwd_bloc.dart'; + +@immutable +abstract class SetPwdEvent {} + +///密码是否符合规则 +class PwdEnsureEvent extends SetPwdEvent {} +///密码是否一致 +class PwdCheckEvent extends SetPwdEvent {} +///设置密码 +class SetPasswordEvent extends SetPwdEvent {} diff --git a/lib/pages/login/setpwd/bloc/set_pwd_state.dart b/lib/pages/login/setpwd/bloc/set_pwd_state.dart new file mode 100644 index 0000000..a9f5c1e --- /dev/null +++ b/lib/pages/login/setpwd/bloc/set_pwd_state.dart @@ -0,0 +1,18 @@ +part of 'set_pwd_bloc.dart'; + +@immutable +abstract class SetPwdState {} + +class SetPwdInitial extends SetPwdState {} + +class SetEnsurePwdState extends SetPwdState {} + +class SetCheckPwdState extends SetPwdState {} + +class PasswordLargeState extends SetPwdState {} + +class PasswordIconShowState extends SetPwdState {} + +class PasswordCheckIconShowState extends SetPwdState {} + +class PasswordSetSuccessState extends SetPwdState {} diff --git a/lib/pages/login/setpwd/set_pwd_page.dart b/lib/pages/login/setpwd/set_pwd_page.dart new file mode 100644 index 0000000..c8ac59d --- /dev/null +++ b/lib/pages/login/setpwd/set_pwd_page.dart @@ -0,0 +1,197 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:wow_english/common/extension/string_extension.dart'; +import 'package:wow_english/common/widgets/textfield_customer_widget.dart'; +import 'package:wow_english/route/route.dart'; + +import 'bloc/set_pwd_bloc.dart'; + + +class SetPassWordPage extends StatelessWidget { + const SetPassWordPage({super.key, this.phoneNum}); + final String? phoneNum; + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (context) => SetPwdBloc(phoneNum), + child: _SetPassWordPageView(), + ); + } +} + +class _SetPassWordPageView extends StatelessWidget { + @override + Widget build(BuildContext context) { + return BlocListener( + listener: (context, s){ + if (s is PasswordSetSuccessState) { + Navigator.of(context).pushNamedAndRemoveUntil(AppRouteName.home, (route) => false); + } + }, + child: _buildSetPwdView(), + ); + } + + Widget _buildSetPwdView() => BlocBuilder( + builder: (context, state) { + final bloc = BlocProvider.of(context); + return Scaffold( + body: Container( + color: Colors.white, + child: SafeArea( + child: ListView( + children: [ + Padding( + padding: EdgeInsets.symmetric(horizontal: 40.w), + child: Column( + children: [ + 34.verticalSpace, + Row( + children: [ + Image.asset( + 'wow_logo'.assetPng, + height: 49.w, + width: 83.5.h, + ), + 12.5.horizontalSpace, + Text( + '欢迎登录wow english\n接下来请设置一下您的密码吧!', + style: TextStyle( + fontSize: 16.5.sp, + color: const Color(0xFF666666) + ), + ) + ], + ), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + 43.verticalSpace, + Row( + children: [ + Expanded( + child: TextFieldCustomerWidget( + height: 55.h, + hitText: '请输入八位以上密码', + bgImageName: 'Input_layer_up', + controller: bloc.passWordFirstController, + obscureText: true, + textInputType: TextInputType.emailAddress, + onChangeValue: (String value) => bloc.add(PwdEnsureEvent()), + ) + ), + 10.horizontalSpace, + Opacity( + opacity: bloc.showPwdIcon?1:0, + child: Image.asset( + bloc.passwordEnsure?'login_pass'.assetPng:'login_error'.assetPng, + height: 30, + width: 30, + ), + ) + ], + ), + 9.verticalSpace, + Offstage( + offstage: !bloc.passwordLarger, + child: const Text('您已达到密码最大输入数,请妥善调整密码'), + ), + 9.verticalSpace, + Row( + children: [ + Expanded( + child: TextFieldCustomerWidget( + height: 55.h, + hitText: '请再次输入相同密码', + bgImageName: 'Input_layer_up', + obscureText: true, + textInputType: TextInputType.emailAddress, + controller: bloc.passWordSecondController, + onChangeValue: (String value) => bloc.add(PwdCheckEvent()), + ) + ), + 10.horizontalSpace, + Opacity( + opacity: bloc.showCheckPwdIcon?1:0, + child: Image.asset( + bloc.passwordCheck?'login_pass'.assetPng:'login_error'.assetPng, + height: 30, + width: 30, + ), + ) + ], + ), + 9.verticalSpace, + Offstage( + offstage: bloc.passwordCheck, + child: Text( + '请确认两次输入的密码是否一致', + style: TextStyle( + fontSize: 16.sp, + color: const Color(0xFF333333) + ), + ), + ), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + GestureDetector( + onTap: () { + if (!bloc.ensure) { + return; + } + bloc.add(SetPasswordEvent()); + }, + child: Container( + decoration: BoxDecoration( + image: DecorationImage( + image: AssetImage( + bloc.ensure?'login_enter'.assetPng:'login_enter_dis'.assetPng + ), + fit: BoxFit.fill + ), + ), + padding: EdgeInsets.symmetric( + horizontal: 28.w, + vertical: 14.h + ), + child: Text( + '确定', + style: TextStyle( + color: Colors.white, + fontSize: 16.sp + ), + ), + ), + ), + 50.horizontalSpace + ], + ) + ], + ), + ), + 30.horizontalSpace, + Image.asset( + 'steven'.assetPng, + height: 254.h, + width: 100.w, + ) + ], + ), + ], + ), + ) + ], + ), + ), + ), + ); + } + ); +} \ No newline at end of file diff --git a/lib/pages/practice/chosetopic/topicpicture/bloc/topic_picture_bloc.dart b/lib/pages/practice/chosetopic/topicpicture/bloc/topic_picture_bloc.dart new file mode 100644 index 0000000..1248801 --- /dev/null +++ b/lib/pages/practice/chosetopic/topicpicture/bloc/topic_picture_bloc.dart @@ -0,0 +1,41 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +part 'topic_picture_event.dart'; +part 'topic_picture_state.dart'; + +class TopicPictureBloc extends Bloc { + + final PageController pageController; + + final int modelCount; + + int _currentPage = 0; + + int _selectItem = 0; + + int get currentPage => _currentPage + 1; + + int get selectItem => _selectItem; + + TopicPictureBloc(this.pageController, this.modelCount) : super(TopicPictureInitial()) { + on(_pageControllerChange); + on(_selectItemLoad); + } + + @override + Future close() { + pageController.dispose(); + return super.close(); + } + + void _pageControllerChange(CurrentPageIndexChangeEvent event,Emitter emitter) async { + _currentPage = event.pageIndex; + emitter(CurrentPageIndexState()); + } + + void _selectItemLoad(SelectItemEvent event,Emitter emitter) async { + _selectItem = event.selectIndex; + emitter(SelectItemChangeState()); + } +} diff --git a/lib/pages/practice/chosetopic/topicpicture/bloc/topic_picture_event.dart b/lib/pages/practice/chosetopic/topicpicture/bloc/topic_picture_event.dart new file mode 100644 index 0000000..781f545 --- /dev/null +++ b/lib/pages/practice/chosetopic/topicpicture/bloc/topic_picture_event.dart @@ -0,0 +1,14 @@ +part of 'topic_picture_bloc.dart'; + +@immutable +abstract class TopicPictureEvent {} + +class CurrentPageIndexChangeEvent extends TopicPictureEvent { + final int pageIndex; + CurrentPageIndexChangeEvent(this.pageIndex); +} + +class SelectItemEvent extends TopicPictureEvent { + final int selectIndex; + SelectItemEvent(this.selectIndex); +} \ No newline at end of file diff --git a/lib/pages/practice/chosetopic/topicpicture/bloc/topic_picture_state.dart b/lib/pages/practice/chosetopic/topicpicture/bloc/topic_picture_state.dart new file mode 100644 index 0000000..af0e103 --- /dev/null +++ b/lib/pages/practice/chosetopic/topicpicture/bloc/topic_picture_state.dart @@ -0,0 +1,10 @@ +part of 'topic_picture_bloc.dart'; + +@immutable +abstract class TopicPictureState {} + +class TopicPictureInitial extends TopicPictureState {} + +class CurrentPageIndexState extends TopicPictureState {} + +class SelectItemChangeState extends TopicPictureState {} diff --git a/lib/pages/practice/chosetopic/topicpicture/topic_picture_page.dart b/lib/pages/practice/chosetopic/topicpicture/topic_picture_page.dart new file mode 100644 index 0000000..995a5e8 --- /dev/null +++ b/lib/pages/practice/chosetopic/topicpicture/topic_picture_page.dart @@ -0,0 +1,141 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:wow_english/common/extension/string_extension.dart'; + +import '../../widgets/practice_header_widget.dart'; +import 'bloc/topic_picture_bloc.dart'; + +class TopicPicturePage extends StatelessWidget { + const TopicPicturePage({super.key}); + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (context) => TopicPictureBloc(PageController(),3), + child: _TopicPicturePage(), + ); + } +} + +class _TopicPicturePage extends StatelessWidget { + @override + Widget build(BuildContext context) { + return BlocListener( + listener: (context, state){}, + child: _topicPictureView(), + ); + } + + Widget _topicPictureView() => BlocBuilder( + buildWhen: (_,s) => s is CurrentPageIndexState, + builder: (context,state){ + final bloc = BlocProvider.of(context); + return Container( + color: Colors.white, + child: Stack( + children: [ + Column( + children: [ + PracticeHeaderWidget( + title: '${bloc.currentPage}/8', + onTap: (){Navigator.pop(context);}, + ), + Expanded( + child: PageView.builder( + itemCount: 8, + scrollDirection: Axis.horizontal, + controller: bloc.pageController, + onPageChanged: (int index) { + bloc.add(CurrentPageIndexChangeEvent(index)); + }, + itemBuilder: (BuildContext context,int index){ + return _pageViewItemWidget(); + }), + ) + ], + ), + Positioned( + left: 0, + right: 0, + bottom: 0, + child: Image.asset('bottom_grass'.assetPng) + ) + ], + ), + ); + }); + + Widget _pageViewItemWidget() => BlocBuilder( + builder: (context, state){ + final bloc = BlocProvider.of(context); + return SafeArea( + child: Column( + children: [ + Text( + 'What to do when the sentence question is very long and needs a line break', + softWrap: true, + style: TextStyle( + fontSize: 21.sp, + color: const Color(0xFF333333) + ) + ), + 26.verticalSpace, + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Offstage( + offstage: (bloc.modelCount < 1), + child: _decodeImageWidget(1), + ), + Offstage( + offstage: (bloc.modelCount < 2), + child: _decodeImageWidget(2), + ), + Offstage( + offstage: (bloc.modelCount < 3), + child: _decodeImageWidget(3), + ), + Offstage( + offstage: (bloc.modelCount < 4), + child: _decodeImageWidget(4), + ) + ], + ) + ], + ), + ); + }); + + Widget _decodeImageWidget(int index) => BlocBuilder( + buildWhen: (_, s) => s is SelectItemChangeState, + builder: (context,state){ + final bloc = BlocProvider.of(context); + return GestureDetector( + onTap: () => bloc.add(SelectItemEvent(index)), + child: Container( + padding: const EdgeInsets.all(4.5), + decoration: BoxDecoration( + color: bloc.selectItem == index?const Color(0xFF00B6F1):Colors.white, + borderRadius: BorderRadius.circular(15), + ), + height: 143.h, + width: 143.w, + child: Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(15), + border: Border.all( + width: 1.0, + color: const Color(0xFF140C10) + ), + image: const DecorationImage( + fit: BoxFit.fitWidth, + image: NetworkImage('https://img1.baidu.com/it/u=3392591833,1640391553&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=714') + ) + ), + ), + ), + ); + }); +} \ No newline at end of file diff --git a/lib/pages/practice/chosetopic/topicword/bloc/topic_word_bloc.dart b/lib/pages/practice/chosetopic/topicword/bloc/topic_word_bloc.dart new file mode 100644 index 0000000..3197025 --- /dev/null +++ b/lib/pages/practice/chosetopic/topicword/bloc/topic_word_bloc.dart @@ -0,0 +1,41 @@ + +import 'package:flutter/cupertino.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +part 'topic_word_event.dart'; +part 'topic_word_state.dart'; + +class TopicWordBloc extends Bloc { + final PageController pageController; + + final int modelCount; + + int _currentPage = 0; + + int _selectItem = 0; + + int get currentPage => _currentPage + 1; + + int get selectItem => _selectItem; + + TopicWordBloc(this.pageController, this.modelCount) : super(TopicWordInitial()) { + on(_pageControllerChange); + on(_selectItemLoad); + } + + @override + Future close() { + pageController.dispose(); + return super.close(); + } + + void _pageControllerChange(CurrentPageIndexChangeEvent event,Emitter emitter) async { + _currentPage = event.pageIndex; + emitter(CurrentPageIndexState()); + } + + void _selectItemLoad(SelectItemEvent event,Emitter emitter) async { + _selectItem = event.selectIndex; + emitter(SelectItemChangeState()); + } +} diff --git a/lib/pages/practice/chosetopic/topicword/bloc/topic_word_event.dart b/lib/pages/practice/chosetopic/topicword/bloc/topic_word_event.dart new file mode 100644 index 0000000..3decdf5 --- /dev/null +++ b/lib/pages/practice/chosetopic/topicword/bloc/topic_word_event.dart @@ -0,0 +1,14 @@ +part of 'topic_word_bloc.dart'; + +@immutable +abstract class TopicWordEvent {} + +class CurrentPageIndexChangeEvent extends TopicWordEvent { + final int pageIndex; + CurrentPageIndexChangeEvent(this.pageIndex); +} + +class SelectItemEvent extends TopicWordEvent { + final int selectIndex; + SelectItemEvent(this.selectIndex); +} \ No newline at end of file diff --git a/lib/pages/practice/chosetopic/topicword/bloc/topic_word_state.dart b/lib/pages/practice/chosetopic/topicword/bloc/topic_word_state.dart new file mode 100644 index 0000000..a27770f --- /dev/null +++ b/lib/pages/practice/chosetopic/topicword/bloc/topic_word_state.dart @@ -0,0 +1,10 @@ +part of 'topic_word_bloc.dart'; + +@immutable +abstract class TopicWordState {} + +class TopicWordInitial extends TopicWordState {} + +class CurrentPageIndexState extends TopicWordState {} + +class SelectItemChangeState extends TopicWordState {} \ No newline at end of file diff --git a/lib/pages/practice/chosetopic/topicword/topic_word_page.dart b/lib/pages/practice/chosetopic/topicword/topic_word_page.dart new file mode 100644 index 0000000..d18dbc4 --- /dev/null +++ b/lib/pages/practice/chosetopic/topicword/topic_word_page.dart @@ -0,0 +1,163 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:wow_english/common/extension/string_extension.dart'; +import 'package:wow_english/pages/practice/widgets/practice_header_widget.dart'; + +import 'bloc/topic_word_bloc.dart'; + +class TopicWordPage extends StatelessWidget { + const TopicWordPage({super.key}); + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (context) => TopicWordBloc(PageController(), 4), + child: _TopicWordPage(), + ); + } +} + +class _TopicWordPage extends StatelessWidget { + @override + Widget build(BuildContext context) { + return BlocListener( + listener: (context, state) { + + }, + child: _topicWordView(), + ); + } + + Widget _topicWordView() => BlocBuilder( + builder: (context,state){ + final bloc = BlocProvider.of(context); + return Container( + color: Colors.white, + child: Stack( + children: [ + Positioned( + left: 0, + right: 0, + bottom: 0, + child: Image.asset('background_grass'.assetPng,fit: BoxFit.fitWidth,) + ), + Column( + children: [ + PracticeHeaderWidget( + title: '${bloc.currentPage}/8', + onTap: (){Navigator.pop(context);}, + ), + Expanded( + child: PageView.builder( + itemCount: 8, + scrollDirection: Axis.horizontal, + controller: bloc.pageController, + onPageChanged: (int index) { + bloc.add(CurrentPageIndexChangeEvent(index)); + }, + itemBuilder: (BuildContext context,int index){ + return _pageViewItemWidget(); + }), + ) + ], + ), + ], + ), + ); + }); + + Widget _pageViewItemWidget() => BlocBuilder( + builder: (context, state){ + final bloc = BlocProvider.of(context); + return SafeArea( + child: Column( + children: [ + Text( + 'What to do when the sentence question is very long and needs a line break', + softWrap: true, + style: TextStyle( + fontSize: 21.sp, + color: const Color(0xFF333333) + ) + ), + 26.verticalSpace, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Offstage( + offstage: (bloc.modelCount < 1), + child: _decodeImageWidget(1), + ), + Offstage( + offstage: (bloc.modelCount < 2), + child: _decodeImageWidget(2), + ), + Offstage( + offstage: (bloc.modelCount < 3), + child: _decodeImageWidget(3), + ), + Offstage( + offstage: (bloc.modelCount < 4), + child: _decodeImageWidget(4), + ) + ], + ) + ], + ), + ); + }); + + Widget _decodeImageWidget(int index) => BlocBuilder( + buildWhen: (_, s) => s is SelectItemChangeState, + builder: (context,state){ + final bloc = BlocProvider.of(context); + return GestureDetector( + onTap: () => bloc.add(SelectItemEvent(index)), + child: Container( + width: 143.w, + height: 143.h, + padding: EdgeInsets.only(left: 13.w,right: 13.w,top: 13.h,bottom: 13.h), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(15), + border: Border.all( + width: 1.0, + color: const Color(0xFF140C10) + ), + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Expanded( + child: Container( + alignment: Alignment.center, + child: Text( + 'yellow', + style: TextStyle( + fontSize: 20.sp, + color: const Color(0xFF333333) + ) + ), + ), + ), + Container( + height: 30.h, + width: double.infinity, + decoration: BoxDecoration( + color: bloc.selectItem == index?const Color(0xFF00B6F1):Colors.white, + borderRadius: BorderRadius.circular(15.r), + border: Border.all( + width: 1.5, + color: const Color(0xFF140C10) + ), + ), + alignment: Alignment.center, + child: Image.asset('choose'.assetPng), + ) + ], + ), + ), + ); + }); +} \ No newline at end of file diff --git a/lib/pages/practice/voicetopic/voicepicture/bloc/voice_pic_bloc.dart b/lib/pages/practice/voicetopic/voicepicture/bloc/voice_pic_bloc.dart new file mode 100644 index 0000000..073782d --- /dev/null +++ b/lib/pages/practice/voicetopic/voicepicture/bloc/voice_pic_bloc.dart @@ -0,0 +1,39 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +part 'voice_pic_event.dart'; +part 'voice_pic_state.dart'; + +class VoicePicBloc extends Bloc { + final PageController pageController; + + final int modelCount; + + int _currentPage = 0; + + int _selectItem = 0; + + int get currentPage => _currentPage + 1; + + int get selectItem => _selectItem; + VoicePicBloc(this.pageController, this.modelCount) : super(VoicePicInitial()) { + on(_pageControllerChange); + on(_selectItemLoad); + } + + @override + Future close() { + pageController.dispose(); + return super.close(); + } + + void _pageControllerChange(CurrentPageIndexChangeEvent event,Emitter emitter) async { + _currentPage = event.pageIndex; + emitter(CurrentPageIndexState()); + } + + void _selectItemLoad(SelectItemEvent event,Emitter emitter) async { + _selectItem = event.selectIndex; + emitter(SelectItemChangeState()); + } +} diff --git a/lib/pages/practice/voicetopic/voicepicture/bloc/voice_pic_event.dart b/lib/pages/practice/voicetopic/voicepicture/bloc/voice_pic_event.dart new file mode 100644 index 0000000..c60b951 --- /dev/null +++ b/lib/pages/practice/voicetopic/voicepicture/bloc/voice_pic_event.dart @@ -0,0 +1,14 @@ +part of 'voice_pic_bloc.dart'; + +@immutable +abstract class VoicePicEvent {} + +class CurrentPageIndexChangeEvent extends VoicePicEvent { + final int pageIndex; + CurrentPageIndexChangeEvent(this.pageIndex); +} + +class SelectItemEvent extends VoicePicEvent { + final int selectIndex; + SelectItemEvent(this.selectIndex); +} \ No newline at end of file diff --git a/lib/pages/practice/voicetopic/voicepicture/bloc/voice_pic_state.dart b/lib/pages/practice/voicetopic/voicepicture/bloc/voice_pic_state.dart new file mode 100644 index 0000000..cd05460 --- /dev/null +++ b/lib/pages/practice/voicetopic/voicepicture/bloc/voice_pic_state.dart @@ -0,0 +1,10 @@ +part of 'voice_pic_bloc.dart'; + +@immutable +abstract class VoicePicState {} + +class VoicePicInitial extends VoicePicState {} + +class CurrentPageIndexState extends VoicePicState {} + +class SelectItemChangeState extends VoicePicState {} \ No newline at end of file diff --git a/lib/pages/practice/voicetopic/voicepicture/voice_pic_page.dart b/lib/pages/practice/voicetopic/voicepicture/voice_pic_page.dart new file mode 100644 index 0000000..d0ef1f9 --- /dev/null +++ b/lib/pages/practice/voicetopic/voicepicture/voice_pic_page.dart @@ -0,0 +1,151 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:wow_english/common/extension/string_extension.dart'; +import 'package:wow_english/pages/practice/widgets/practice_header_widget.dart'; + +import 'bloc/voice_pic_bloc.dart'; + +class VoicePicPage extends StatelessWidget { + const VoicePicPage({super.key}); + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (context) => VoicePicBloc(PageController(),4), + child: _VoicePicPage(), + ); + } +} + +class _VoicePicPage extends StatelessWidget { + @override + Widget build(BuildContext context) { + return BlocListener( + listener: (context, state){}, + child: _voicePicView(), + ); + } + + Widget _voicePicView() => BlocBuilder( + builder: (context, state){ + return _voicePictureView(); + }); + + Widget _voicePictureView() => BlocBuilder( + buildWhen: (_,s) => s is CurrentPageIndexState, + builder: (context,state){ + final bloc = BlocProvider.of(context); + return Container( + color: Colors.white, + child: Stack( + children: [ + Image.asset( + 'road_bg'.assetPng, + height: double.infinity, + width: double.infinity + ), + Column( + children: [ + PracticeHeaderWidget( + title: '${bloc.currentPage}/8', + onTap: (){Navigator.pop(context);}, + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image.asset('voice'.assetPng,height: 33.h,width: 30.w,), + 10.horizontalSpace, + Text( + 'yellow', + style: TextStyle( + fontSize: 20.sp, + color: const Color(0xFF333333) + ) + ) + ], + ), + 26.verticalSpace, + Expanded( + child: PageView.builder( + itemCount: 8, + scrollDirection: Axis.horizontal, + controller: bloc.pageController, + onPageChanged: (int index) { + bloc.add(CurrentPageIndexChangeEvent(index)); + }, + itemBuilder: (BuildContext context,int index){ + return _pageViewItemWidget(); + }), + ) + ], + ) + ], + ), + ); + }); + + Widget _pageViewItemWidget() => BlocBuilder( + builder: (context, state){ + final bloc = BlocProvider.of(context); + return SafeArea( + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Offstage( + offstage: (bloc.modelCount < 1), + child: _decodeImageWidget(1), + ), + Offstage( + offstage: (bloc.modelCount < 2), + child: _decodeImageWidget(2), + ), + Offstage( + offstage: (bloc.modelCount < 3), + child: _decodeImageWidget(3), + ), + Offstage( + offstage: (bloc.modelCount < 4), + child: _decodeImageWidget(4), + ) + ], + ) + ], + ), + ); + }); + + Widget _decodeImageWidget(int index) => BlocBuilder( + buildWhen: (_, s) => s is SelectItemChangeState, + builder: (context,state){ + final bloc = BlocProvider.of(context); + return GestureDetector( + onTap: () => bloc.add(SelectItemEvent(index)), + child: Container( + padding: const EdgeInsets.all(4.5), + decoration: BoxDecoration( + color: bloc.selectItem == index?const Color(0xFF00B6F1):Colors.white, + borderRadius: BorderRadius.circular(15), + ), + height: 143.h, + width: 143.w, + child: Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(15), + border: Border.all( + width: 1.0, + color: const Color(0xFF140C10) + ), + image: const DecorationImage( + fit: BoxFit.fitWidth, + image: NetworkImage('https://img1.baidu.com/it/u=3392591833,1640391553&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=714') + ) + ), + ), + ), + ); + }); +} \ No newline at end of file diff --git a/lib/pages/practice/voicetopic/voiceword/bloc/voice_word_bloc.dart b/lib/pages/practice/voicetopic/voiceword/bloc/voice_word_bloc.dart new file mode 100644 index 0000000..c768bd4 --- /dev/null +++ b/lib/pages/practice/voicetopic/voiceword/bloc/voice_word_bloc.dart @@ -0,0 +1,41 @@ + +import 'package:flutter/cupertino.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +part 'voice_word_event.dart'; +part 'voice_word_state.dart'; + +class VoiceWordBloc extends Bloc { + final PageController pageController; + + final int modelCount; + + int _currentPage = 0; + + int _selectItem = 0; + + int get currentPage => _currentPage + 1; + + int get selectItem => _selectItem; + VoiceWordBloc(this.pageController, this.modelCount) : super(VoiceWordInitial()) { + on(_pageControllerChange); + on(_selectItemLoad); + } + + @override + Future close() { + pageController.dispose(); + return super.close(); + } + + void _pageControllerChange(CurrentPageIndexChangeEvent event,Emitter emitter) async { + _currentPage = event.pageIndex; + emitter(CurrentPageIndexState()); + } + + void _selectItemLoad(SelectItemEvent event,Emitter emitter) async { + _selectItem = event.selectIndex; + emitter(SelectItemChangeState()); + } +} + diff --git a/lib/pages/practice/voicetopic/voiceword/bloc/voice_word_event.dart b/lib/pages/practice/voicetopic/voiceword/bloc/voice_word_event.dart new file mode 100644 index 0000000..1d556a2 --- /dev/null +++ b/lib/pages/practice/voicetopic/voiceword/bloc/voice_word_event.dart @@ -0,0 +1,14 @@ +part of 'voice_word_bloc.dart'; + +@immutable +abstract class VoiceWordEvent {} + +class CurrentPageIndexChangeEvent extends VoiceWordEvent { + final int pageIndex; + CurrentPageIndexChangeEvent(this.pageIndex); +} + +class SelectItemEvent extends VoiceWordEvent { + final int selectIndex; + SelectItemEvent(this.selectIndex); +} \ No newline at end of file diff --git a/lib/pages/practice/voicetopic/voiceword/bloc/voice_word_state.dart b/lib/pages/practice/voicetopic/voiceword/bloc/voice_word_state.dart new file mode 100644 index 0000000..81993db --- /dev/null +++ b/lib/pages/practice/voicetopic/voiceword/bloc/voice_word_state.dart @@ -0,0 +1,10 @@ +part of 'voice_word_bloc.dart'; + +@immutable +abstract class VoiceWordState {} + +class VoiceWordInitial extends VoiceWordState {} + +class CurrentPageIndexState extends VoiceWordState {} + +class SelectItemChangeState extends VoiceWordState {} diff --git a/lib/pages/practice/voicetopic/voiceword/voice_word_page.dart b/lib/pages/practice/voicetopic/voiceword/voice_word_page.dart new file mode 100644 index 0000000..144bd47 --- /dev/null +++ b/lib/pages/practice/voicetopic/voiceword/voice_word_page.dart @@ -0,0 +1,160 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:wow_english/common/extension/string_extension.dart'; +import 'package:wow_english/pages/practice/widgets/practice_header_widget.dart'; + +import 'bloc/voice_word_bloc.dart'; + +class VoiceWordPage extends StatelessWidget { + const VoiceWordPage({super.key}); + + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (context) => VoiceWordBloc(PageController(),4), + child: _VoiceWordPage(), + ); + } +} + +class _VoiceWordPage extends StatelessWidget { + @override + Widget build(BuildContext context) { + return BlocListener( + listener: (context, state){}, + child: _voiceWorView(), + ); + } + + Widget _voiceWorView() => BlocBuilder( + builder: (context, state){ + return _voiceWordView(); + }); + + Widget _voiceWordView() => BlocBuilder( + buildWhen: (_,s) => s is CurrentPageIndexState, + builder: (context,state){ + final bloc = BlocProvider.of(context); + return Container( + color: Colors.white, + child: Stack( + children: [ + Image.asset( + 'road_bg'.assetPng, + height: double.infinity, + width: double.infinity + ), + Column( + children: [ + PracticeHeaderWidget( + title: '${bloc.currentPage}/8', + onTap: (){Navigator.pop(context);}, + ), + Image.asset('voice'.assetPng,height: 33.h,width: 30.w,), + 26.verticalSpace, + Expanded( + child: PageView.builder( + itemCount: 8, + scrollDirection: Axis.horizontal, + controller: bloc.pageController, + onPageChanged: (int index) { + bloc.add(CurrentPageIndexChangeEvent(index)); + }, + itemBuilder: (BuildContext context,int index){ + return _pageViewItemWidget(); + }), + ) + ], + ) + ], + ), + ); + }); + + Widget _pageViewItemWidget() => BlocBuilder( + builder: (context, state){ + final bloc = BlocProvider.of(context); + return SafeArea( + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Offstage( + offstage: (bloc.modelCount < 1), + child: _decodeImageWidget(1), + ), + Offstage( + offstage: (bloc.modelCount < 2), + child: _decodeImageWidget(2), + ), + Offstage( + offstage: (bloc.modelCount < 3), + child: _decodeImageWidget(3), + ), + Offstage( + offstage: (bloc.modelCount < 4), + child: _decodeImageWidget(4), + ) + ], + ) + ], + ), + ); + }); + + Widget _decodeImageWidget(int index) => BlocBuilder( + buildWhen: (_, s) => s is SelectItemChangeState, + builder: (context,state){ + final bloc = BlocProvider.of(context); + return GestureDetector( + onTap: () => bloc.add(SelectItemEvent(index)), + child: Container( + width: 143.w, + height: 143.h, + padding: EdgeInsets.only(left: 13.w,right: 13.w,top: 13.h,bottom: 13.h), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(15), + border: Border.all( + width: 1.0, + color: const Color(0xFF140C10) + ), + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Expanded( + child: Container( + alignment: Alignment.center, + child: Text( + 'yellow', + style: TextStyle( + fontSize: 20.sp, + color: const Color(0xFF333333) + ) + ), + ), + ), + Container( + height: 30.h, + width: double.infinity, + decoration: BoxDecoration( + color: bloc.selectItem == index?const Color(0xFF00B6F1):Colors.white, + borderRadius: BorderRadius.circular(15.r), + border: Border.all( + width: 1.5, + color: const Color(0xFF140C10) + ), + ), + alignment: Alignment.center, + child: Image.asset('choose'.assetPng), + ) + ], + ), + ), + ); + }); +} \ No newline at end of file diff --git a/lib/pages/practice/widgets/practice_header_widget.dart b/lib/pages/practice/widgets/practice_header_widget.dart new file mode 100644 index 0000000..456f314 --- /dev/null +++ b/lib/pages/practice/widgets/practice_header_widget.dart @@ -0,0 +1,59 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:wow_english/common/extension/string_extension.dart'; + +class PracticeHeaderWidget extends StatelessWidget { + const PracticeHeaderWidget({super.key, required this.onTap,this.title = ''}); + + final Function() onTap; + + final String title; + + @override + Widget build(BuildContext context) { + return Container( + color: Colors.white, + height: 60.h, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: EdgeInsets.only( + left: ScreenUtil().bottomBarHeight + ), + child: IconButton( + onPressed: (){ + onTap(); + }, + icon: Image.asset( + 'back_around'.assetPng, + width: 40, + height: 40, + )), + ), + Container( + height: 40.h, + padding: EdgeInsets.symmetric(horizontal: 27.w), + decoration: BoxDecoration( + color: const Color(0xFF00B6F1), + borderRadius: BorderRadius.circular(20.r), + border: Border.all( + width: 1.0, + color: const Color(0xFF333333), + ), + ), + alignment: Alignment.center, + child: Text( + title, + style: TextStyle( + fontSize: 20.sp, + color: Colors.white + ), + ), + ), + ScreenUtil().bottomBarHeight.horizontalSpace, + ], + ), + ); + } +} \ No newline at end of file diff --git a/lib/pages/repeatafter/bloc/repeat_after_bloc.dart b/lib/pages/repeatafter/bloc/repeat_after_bloc.dart new file mode 100644 index 0000000..1d42860 --- /dev/null +++ b/lib/pages/repeatafter/bloc/repeat_after_bloc.dart @@ -0,0 +1,23 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; + +part 'repeat_after_event.dart'; +part 'repeat_after_state.dart'; + +class RepeatAfterBloc extends Bloc { + RepeatAfterBloc() : super(RepeatAfterInitial()) { + on((event, emit) { + // TODO: implement event handler + }); + } + + + Future requestData() async { + EasyLoading.show(); + Future.delayed(const Duration(milliseconds: 2000),(){ + EasyLoading.dismiss(); + emit(RequestDataState()); + }); + } +} diff --git a/lib/pages/repeatafter/bloc/repeat_after_event.dart b/lib/pages/repeatafter/bloc/repeat_after_event.dart new file mode 100644 index 0000000..3a46031 --- /dev/null +++ b/lib/pages/repeatafter/bloc/repeat_after_event.dart @@ -0,0 +1,4 @@ +part of 'repeat_after_bloc.dart'; + +@immutable +abstract class RepeatAfterEvent {} diff --git a/lib/pages/repeatafter/bloc/repeat_after_state.dart b/lib/pages/repeatafter/bloc/repeat_after_state.dart new file mode 100644 index 0000000..e8c710f --- /dev/null +++ b/lib/pages/repeatafter/bloc/repeat_after_state.dart @@ -0,0 +1,8 @@ +part of 'repeat_after_bloc.dart'; + +@immutable +abstract class RepeatAfterState {} + +class RepeatAfterInitial extends RepeatAfterState {} + +class RequestDataState extends RepeatAfterState {} diff --git a/lib/pages/repeatafter/repeat_after_page.dart b/lib/pages/repeatafter/repeat_after_page.dart new file mode 100644 index 0000000..818d290 --- /dev/null +++ b/lib/pages/repeatafter/repeat_after_page.dart @@ -0,0 +1,65 @@ +import 'dart:math'; + +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; +import 'package:wow_english/common/widgets/we_app_bar.dart'; +import 'package:wow_english/pages/repeatafter/widgets/repeat_after_item.dart'; + +import 'bloc/repeat_after_bloc.dart'; + +class RepeatAfterPage extends StatelessWidget { + const RepeatAfterPage({super.key}); + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (context) => RepeatAfterBloc()..requestData(), + child: _RepeatAfterPageView(), + ); + } +} + +class _RepeatAfterPageView extends StatelessWidget { + @override + Widget build(BuildContext context) { + return BlocListener( + listener: (context, state) { + if (state is RequestDataState) { + EasyLoading.showToast('网络请求结束'); + } + }, + child: _repeatAfterView(), + ); + } + + Widget _repeatAfterView() => BlocBuilder( + builder: (context, state) { + return Scaffold( + appBar: const WEAppBar( + titleText: '视频跟读', + centerTitle: false, + ), + body: SafeArea( + child: Container( + alignment: Alignment.center, + child: ListView.builder( + itemCount: 10, + scrollDirection: Axis.horizontal, + itemBuilder: (BuildContext context,int index){ + bool unLock = index%3==0; + return RepeatAfterItem( + unLock: unLock, + tapEvent: () { + + }, + starNumber: !unLock?0:Random().nextInt(5) + ); + }), + ), + ), + ); + }, + ); +} + diff --git a/lib/pages/repeatafter/widgets/repeat_after_item.dart b/lib/pages/repeatafter/widgets/repeat_after_item.dart new file mode 100644 index 0000000..c898b48 --- /dev/null +++ b/lib/pages/repeatafter/widgets/repeat_after_item.dart @@ -0,0 +1,137 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:wow_english/common/extension/string_extension.dart'; + +class RepeatAfterItem extends StatelessWidget { + const RepeatAfterItem({super.key, required this.starNumber, required this.unLock, required this.tapEvent}); + //分数 + final int starNumber; + //是否解锁 + final bool unLock; + + final Function() tapEvent; + + @override + Widget build(BuildContext context) { + return Padding( + padding: EdgeInsets.symmetric( + horizontal: 10.w + ), + child: GestureDetector( + onTap: (){ + if(unLock) { + tapEvent(); + } + }, + child: Stack( + children: [ + _modelInfoWidget(context), + _lockWidget() + ], + ), + ), + ); + } + + Widget _modelInfoWidget(BuildContext context) { + return Container( + width: 162.w, + height: 235.h, + decoration: BoxDecoration( + image: DecorationImage( + image: AssetImage( + 'gendubeij'.assetPng + ), + fit: BoxFit.fill + ) + ), + padding: EdgeInsets.symmetric(horizontal: 11.w,vertical: 13.h), + alignment: Alignment.center, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Image.network( + 'https://img.liblibai.com/web/648331d033b41.png?image_process=format,webp&x-oss-process=image/resize,w_2980,m_lfit/format,webp', + height: 100.h, + width: 140.w, + fit: BoxFit.fitWidth, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Image.asset( + starNumber >= 1 ? 'star_light'.assetPng:'star_dark'.assetPng, + width: 23.w, + height: 21.h, + ), + Image.asset( + starNumber >= 2 ? 'star_light'.assetPng:'star_dark'.assetPng, + width: 23.w, + height: 21.h, + ), + Image.asset( + starNumber >= 3 ? 'star_light'.assetPng:'star_dark'.assetPng, + width: 23.w, + height: 21.h, + ), + Image.asset( + starNumber >= 4 ? 'star_light'.assetPng:'star_dark'.assetPng, + width: 23.w, + height: 21.h, + ), + Image.asset( + starNumber >= 5 ? 'star_light'.assetPng:'star_dark'.assetPng, + width: 23.w, + height: 21.h, + ), + ], + ), + Container( + height: 35.h, + width: double.infinity, + decoration: BoxDecoration( + color: const Color(0xFFFFCC00), + borderRadius: BorderRadius.circular(5.r), + border: Border.all( + width: 1.0, + color: const Color(0xFF333333), + ), + ), + alignment: Alignment.center, + child: Text( + 'video title', + style: TextStyle( + fontSize: 16.sp, + color: const Color(0xFF333333) + ), + ), + ) + ], + ), + ); + } + + Widget _lockWidget() { + return Offstage( + offstage: unLock, + child: Container( + width: 162.w, + height: 235.h, + decoration: BoxDecoration( + image: DecorationImage( + image: AssetImage( + 'gendubeij_mengban'.assetPng + ), + fit: BoxFit.fill + ) + ), + alignment: Alignment.center, + child: Image.asset( + 'listen_lock'.assetPng, + height: 36.h, + width: 41.w, + ), + ), + ); + } +} \ No newline at end of file diff --git a/lib/pages/shop/exchane/bloc/exchange_lesson_bloc.dart b/lib/pages/shop/exchane/bloc/exchange_lesson_bloc.dart new file mode 100644 index 0000000..27dc483 --- /dev/null +++ b/lib/pages/shop/exchane/bloc/exchange_lesson_bloc.dart @@ -0,0 +1,37 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +part 'exchange_lesson_event.dart'; +part 'exchange_lesson_state.dart'; + +class ExchangeLessonBloc extends Bloc { + + final TextEditingController codeNumberController = TextEditingController(); + + bool _checkCode = false; + + bool get checkCode => _checkCode; + + ExchangeLessonBloc() : super(ExchangeLessonInitial()) { + on(_codeNumberChange); + on(_requestCheckCode); + } + + _codeNumberChange(CodeNumberChangeEvent event,Emitter emitter) async { + if(codeNumberController.text.isNotEmpty) { + if (!_checkCode) { + _checkCode = true; + emitter(CheckCodeTypeChangeState()); + } + } else { + if (_checkCode) { + _checkCode = false; + emitter(CheckCodeTypeChangeState()); + } + } + } + + _requestCheckCode(CheckCodeEvent event, Emitter emitter) async { + emitter(CheckCodeResultState(false)); + } +} diff --git a/lib/pages/shop/exchane/bloc/exchange_lesson_event.dart b/lib/pages/shop/exchane/bloc/exchange_lesson_event.dart new file mode 100644 index 0000000..7a5d7d9 --- /dev/null +++ b/lib/pages/shop/exchane/bloc/exchange_lesson_event.dart @@ -0,0 +1,8 @@ +part of 'exchange_lesson_bloc.dart'; + +@immutable +abstract class ExchangeLessonEvent {} +//输入兑换码 +class CodeNumberChangeEvent extends ExchangeLessonEvent {} +//验证兑换码 +class CheckCodeEvent extends ExchangeLessonEvent {} diff --git a/lib/pages/shop/exchane/bloc/exchange_lesson_state.dart b/lib/pages/shop/exchane/bloc/exchange_lesson_state.dart new file mode 100644 index 0000000..71ddfe1 --- /dev/null +++ b/lib/pages/shop/exchane/bloc/exchange_lesson_state.dart @@ -0,0 +1,13 @@ +part of 'exchange_lesson_bloc.dart'; + +@immutable +abstract class ExchangeLessonState {} + +class ExchangeLessonInitial extends ExchangeLessonState {} +//输入兑换码状态 +class CheckCodeTypeChangeState extends ExchangeLessonState {} +//验证兑换码结果 +class CheckCodeResultState extends ExchangeLessonState { + final bool result; + CheckCodeResultState(this.result); +} diff --git a/lib/pages/shop/exchane/exchange_lesson_page.dart b/lib/pages/shop/exchane/exchange_lesson_page.dart new file mode 100644 index 0000000..e026b83 --- /dev/null +++ b/lib/pages/shop/exchane/exchange_lesson_page.dart @@ -0,0 +1,133 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:wow_english/common/extension/string_extension.dart'; +import 'package:wow_english/common/widgets/textfield_customer_widget.dart'; +import 'package:wow_english/route/route.dart'; + +import 'bloc/exchange_lesson_bloc.dart'; + +class ExchangeLessonPage extends StatelessWidget { + const ExchangeLessonPage({super.key}); + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (context) => ExchangeLessonBloc(), + child: _ExchangeLessonPage(), + ); + } +} + +class _ExchangeLessonPage extends StatelessWidget { + @override + Widget build(BuildContext context) { + return BlocListener( + listener: (context, state){ + if (state is CheckCodeResultState) { + String title = state.result?'兑换成功':'兑换失败'; + EasyLoading.showToast(title); + Navigator.of(context).pushNamed(AppRouteName.exList); + } + }, + child: _exchangeLessonPageView(), + ); + } + + Widget _exchangeLessonPageView() => BlocBuilder( + builder: (context, state){ + final bloc = BlocProvider.of(context); + return Scaffold( + resizeToAvoidBottomInset: false, + body: Container( + color: Colors.white, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + 10.5.verticalSpace, + Padding( + padding: EdgeInsets.symmetric( + horizontal: 15.w + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + IconButton( + icon: Image.asset( + 'back_around'.assetPng, + width: 40, + height: 40, + ), + color: Colors.white, + onPressed: () { + Navigator.pop(context); + }, + ), + Image.asset( + 'wow_ex_lesson'.assetPng, + width: 139.w, + height: 81.h, + ), + SizedBox.fromSize( + size: const Size(40.0, 40.0) + ) + ], + ), + ), + Expanded( + child: Padding( + padding: EdgeInsets.symmetric(horizontal: 135.w), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + TextFieldCustomerWidget( + height: 55.h, + hitText: '请输入兑换码', + bgImageName: 'Input_layer_up', + textInputType: TextInputType.emailAddress, + controller: bloc.codeNumberController, + onChangeValue: (String value) { + bloc.add(CodeNumberChangeEvent()); + }, + ), + 21.5.verticalSpace, + GestureDetector( + onTap: () { + if (bloc.checkCode) { + bloc.add(CheckCodeEvent()); + } + }, + child: Container( + decoration: BoxDecoration( + image: DecorationImage( + image: AssetImage( + bloc.checkCode ? 'ex_sure'.assetPng:'ex_dis'.assetPng + ), + fit: BoxFit.fill + ), + ), + padding: EdgeInsets.symmetric(horizontal:27.w,vertical: 14.h), + child: Text( + '兑换', + style: TextStyle( + fontSize: 16.sp, + color: Colors.white + ), + ), + ), + ) + ], + ), + ), + ), + Image.asset( + 'bottom_grass'.assetPng, + ), + ], + ), + ), + ); + }); +} \ No newline at end of file diff --git a/lib/pages/shop/exchangelist/bloc/exchange_list_bloc.dart b/lib/pages/shop/exchangelist/bloc/exchange_list_bloc.dart new file mode 100644 index 0000000..bccf206 --- /dev/null +++ b/lib/pages/shop/exchangelist/bloc/exchange_list_bloc.dart @@ -0,0 +1,15 @@ +import 'dart:async'; + +import 'package:bloc/bloc.dart'; +import 'package:meta/meta.dart'; + +part 'exchange_list_event.dart'; +part 'exchange_list_state.dart'; + +class ExchangeListBloc extends Bloc { + ExchangeListBloc() : super(ExchangeListInitial()) { + on((event, emit) { + // TODO: implement event handler + }); + } +} diff --git a/lib/pages/shop/exchangelist/bloc/exchange_list_event.dart b/lib/pages/shop/exchangelist/bloc/exchange_list_event.dart new file mode 100644 index 0000000..ae28d88 --- /dev/null +++ b/lib/pages/shop/exchangelist/bloc/exchange_list_event.dart @@ -0,0 +1,4 @@ +part of 'exchange_list_bloc.dart'; + +@immutable +abstract class ExchangeListEvent {} diff --git a/lib/pages/shop/exchangelist/bloc/exchange_list_state.dart b/lib/pages/shop/exchangelist/bloc/exchange_list_state.dart new file mode 100644 index 0000000..80e9f94 --- /dev/null +++ b/lib/pages/shop/exchangelist/bloc/exchange_list_state.dart @@ -0,0 +1,6 @@ +part of 'exchange_list_bloc.dart'; + +@immutable +abstract class ExchangeListState {} + +class ExchangeListInitial extends ExchangeListState {} diff --git a/lib/pages/shop/exchangelist/exchange_lesson_list_page.dart b/lib/pages/shop/exchangelist/exchange_lesson_list_page.dart new file mode 100644 index 0000000..c300421 --- /dev/null +++ b/lib/pages/shop/exchangelist/exchange_lesson_list_page.dart @@ -0,0 +1,47 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:wow_english/common/widgets/we_app_bar.dart'; +import 'package:wow_english/pages/shop/exchangelist/widgets/exchange_list_item.dart'; + +import 'bloc/exchange_list_bloc.dart'; + +class ExchangeLessonListPage extends StatelessWidget { + const ExchangeLessonListPage({super.key}); + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (context) => ExchangeListBloc(), + child: _ExchangeLessonListPageView(), + ); + } +} + +class _ExchangeLessonListPageView extends StatelessWidget { + @override + Widget build(BuildContext context) { + return BlocListener( + listener: (context,state){}, + child: _exchangeLessonListView(), + ); + } + + Widget _exchangeLessonListView() => BlocBuilder( + builder: (context, state){ + return Scaffold( + appBar: const WEAppBar( + titleText: '购买记录', + ), + body: SafeArea( + child: ListView.builder( + itemCount: 10, + itemBuilder: (BuildContext context,int index){ + return ExchangeListItem( + isCheck: index%3==0, + ); + }), + ), + ); + } + ); +} \ No newline at end of file diff --git a/lib/pages/shop/exchangelist/widgets/exchange_list_item.dart b/lib/pages/shop/exchangelist/widgets/exchange_list_item.dart new file mode 100644 index 0000000..5c78876 --- /dev/null +++ b/lib/pages/shop/exchangelist/widgets/exchange_list_item.dart @@ -0,0 +1,124 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:wow_english/common/extension/string_extension.dart'; + +class ExchangeListItem extends StatelessWidget { + const ExchangeListItem({super.key, required this.isCheck}); + + final bool isCheck; + + @override + Widget build(BuildContext context) { + return SizedBox( + height: 127.h, + width: double.infinity, + child: Padding( + padding: EdgeInsets.only(left: 32.w,right: 32.w,bottom:13.h), + child: GestureDetector( + onTap: () { + + }, + child: Container( + decoration: BoxDecoration( + image: DecorationImage( + image: AssetImage( + 'listback'.assetPng, + ), + fit: BoxFit.fill + ) + ), + padding: EdgeInsets.symmetric(horizontal: 12.w), + child: Row( + children: [ + Container( + width: 70.w, + height: 70.h, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(5.r), + border: Border.all( + width: 1.0, + color: const Color(0xFF333333), + ), + image: const DecorationImage( + image: NetworkImage('https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fsafe-img.xhscdn.com%2Fbw1%2Faa1c2213-820a-4223-8757-5f8cee318a28%3FimageView2%2F2%2Fw%2F1080%2Fformat%2Fjpg&refer=http%3A%2F%2Fsafe-img.xhscdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1688713226&t=192b18a613683bcdc5bd76f65c9ff032'), + ), + ), + ), + 17.horizontalSpace, + Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + Row( + children: [ + Expanded( + child: Text( + '标题:wow english课程永久使用卡', + textAlign: TextAlign.left, + style: TextStyle( + fontSize: 20.sp, + color: const Color(0xFF333333) + ), + ), + ), + Offstage( + offstage: isCheck, + child: Image.asset( + 'checked_logo'.assetPng, + width: 33.w, + height: 35.h + ), + ) + ], + ), + Padding( + padding: EdgeInsets.only(right: 35.w), + child: Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Expanded( + child: Text( + '兑换日期:2022-03-08 12:22:33', + textAlign: TextAlign.left, + style: TextStyle( + fontSize: 12.sp, + color: const Color(0xFF333333) + ), + ), + ), + Column( + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + '生效日期:2023-01-03', + textAlign: TextAlign.left, + style: TextStyle( + fontSize: 12.sp, + color: const Color(0xFF333333) + ), + ), + Text( + '有效期至:永久有效', + textAlign: TextAlign.left, + style: TextStyle( + fontSize: 12.sp, + color: const Color(0xFF333333) + ), + ) + ], + ) + ], + ), + ) + ], + ), + ) + ], + ), + ), + ), + ), + ); + } +} \ No newline at end of file diff --git a/lib/pages/shop/home/bloc/shop_home_bloc.dart b/lib/pages/shop/home/bloc/shop_home_bloc.dart new file mode 100644 index 0000000..bd765c2 --- /dev/null +++ b/lib/pages/shop/home/bloc/shop_home_bloc.dart @@ -0,0 +1,15 @@ +import 'dart:async'; + +import 'package:bloc/bloc.dart'; +import 'package:meta/meta.dart'; + +part 'shop_home_event.dart'; +part 'shop_home_state.dart'; + +class ShopHomeBloc extends Bloc { + ShopHomeBloc() : super(ShopHomeInitial()) { + on((event, emit) { + // TODO: implement event handler + }); + } +} diff --git a/lib/pages/shop/home/bloc/shop_home_event.dart b/lib/pages/shop/home/bloc/shop_home_event.dart new file mode 100644 index 0000000..f35f8fd --- /dev/null +++ b/lib/pages/shop/home/bloc/shop_home_event.dart @@ -0,0 +1,4 @@ +part of 'shop_home_bloc.dart'; + +@immutable +abstract class ShopHomeEvent {} diff --git a/lib/pages/shop/home/bloc/shop_home_state.dart b/lib/pages/shop/home/bloc/shop_home_state.dart new file mode 100644 index 0000000..d0b3c17 --- /dev/null +++ b/lib/pages/shop/home/bloc/shop_home_state.dart @@ -0,0 +1,6 @@ +part of 'shop_home_bloc.dart'; + +@immutable +abstract class ShopHomeState {} + +class ShopHomeInitial extends ShopHomeState {} diff --git a/lib/pages/shop/home/shop_home_page.dart b/lib/pages/shop/home/shop_home_page.dart new file mode 100644 index 0000000..fb1d46e --- /dev/null +++ b/lib/pages/shop/home/shop_home_page.dart @@ -0,0 +1,82 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:wow_english/common/extension/string_extension.dart'; +import 'package:wow_english/common/widgets/we_app_bar.dart'; +import 'package:wow_english/pages/shop/home/widgets/lesson_card_item.dart'; +import 'package:wow_english/route/route.dart'; + +import 'bloc/shop_home_bloc.dart'; + +class ShopHomePage extends StatelessWidget { + const ShopHomePage({super.key}); + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (context) => ShopHomeBloc(), + child: _ShopHomeView(), + ); + } +} + +class _ShopHomeView extends StatelessWidget { + @override + Widget build(BuildContext context) { + return BlocListener( + listener: (context, state) {}, + child: _shopHomeWidget(), + ); + } + + Widget _shopHomeWidget() => BlocBuilder(builder: (context, state){ + return Scaffold( + appBar: WEAppBar( + actions: [ + IconButton( + icon: Image.asset( + 'check_lesson'.assetPng, + width: 40, + height: 40, + ), + color: Colors.white, + onPressed: () { + Navigator.of(context).pushNamed(AppRouteName.exLesson); + }, + ), + IconButton( + icon: Image.asset( + 'shop'.assetPng, + width: 40, + height: 40, + ), + color: Colors.white, + onPressed: () { + EasyLoading.showToast('购前须知'); + }, + ) + ], + ), + body: Center( + child: Padding( + padding: EdgeInsets.symmetric(vertical: 25.h,horizontal: 25.w), + child: GridView.builder( + itemCount: 4, + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, + childAspectRatio: 2, + mainAxisSpacing: 14.h, + crossAxisSpacing : 4.5.w, + ), + itemBuilder: (BuildContext context,int index){ + return LessonCardItem( + onTap: (){ + EasyLoading.showToast('购买'); + }); + }), + ), + ), + ); + }); +} \ No newline at end of file diff --git a/lib/pages/shop/home/widgets/lesson_card_item.dart b/lib/pages/shop/home/widgets/lesson_card_item.dart new file mode 100644 index 0000000..8e42403 --- /dev/null +++ b/lib/pages/shop/home/widgets/lesson_card_item.dart @@ -0,0 +1,111 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; + +class LessonCardItem extends StatelessWidget { + const LessonCardItem({super.key, required this.onTap}); + + final Function() onTap; + + @override + Widget build(BuildContext context) { + return Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10.r), + color: Colors.blue, + border: Border.all( + width: 1.0, + color: Colors.black + ) + // image: DecorationImage( + // image: AssetImage( + // ''.assetPng, + // ), + // fit: BoxFit.fill + // ) + ), + padding: EdgeInsets.symmetric(horizontal: 16.w,vertical: 16.h), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + width: 124.w, + decoration: BoxDecoration( + border: Border.all( + width: 1.0, + color: const Color(0xFF333333), + ), + image: const DecorationImage( + fit: BoxFit.fill, + image: NetworkImage('https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fsafe-img.xhscdn.com%2Fbw1%2Faa1c2213-820a-4223-8757-5f8cee318a28%3FimageView2%2F2%2Fw%2F1080%2Fformat%2Fjpg&refer=http%3A%2F%2Fsafe-img.xhscdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1688713226&t=192b18a613683bcdc5bd76f65c9ff032'), + ) + ), + ), + 21.5.horizontalSpace, + Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text( + 'Wow English 课程年卡', + softWrap: true, + textAlign: TextAlign.left, + style: TextStyle( + fontSize: 12.sp, + color: const Color(0xFF333333) + ), + ), + RichText( + text: TextSpan( + children:[ + TextSpan( + text: '¥', + style: TextStyle( + fontSize: 21.sp, + color: const Color(0xFFF51A1A), + ) + ), + TextSpan( + text: '998', + style: TextStyle( + fontSize: 40.sp, + color: const Color(0xFFF51A1A), + ), + ) + ] + ), + ), + GestureDetector( + onTap: () { + onTap(); + }, + child: Container( + decoration: BoxDecoration( + color: const Color(0xFFF5C51F), + borderRadius: BorderRadius.circular(5.r), + border: Border.all( + color: const Color(0xFF333333), + width: 1.0, + ) + ), + padding: EdgeInsets.symmetric( + vertical: 1.h, + horizontal: 26.5.w, + ), + child: Text( + '立即购买', + style: TextStyle( + fontSize: 10.sp, + color: const Color(0xFF333333) + ), + ), + ), + ) + ], + ), + ) + ], + ), + ); + } +} \ No newline at end of file diff --git a/lib/pages/tab/blocs/tab_bloc.dart b/lib/pages/tab/blocs/tab_bloc.dart new file mode 100644 index 0000000..bbd9a3b --- /dev/null +++ b/lib/pages/tab/blocs/tab_bloc.dart @@ -0,0 +1,18 @@ +import 'dart:async'; + +import 'package:bloc/bloc.dart'; +import 'package:meta/meta.dart'; + +part 'tab_event.dart'; +part 'tab_state.dart'; + +class TabBloc extends Bloc { + TabBloc() : super(const TabState()) { + on(_onUpdateTabIndex); + } + + void _onUpdateTabIndex( + UpdateTabIndexEvent event, Emitter emitter) async { + emitter(state.copyWith(index: event.index)); + } +} diff --git a/lib/pages/tab/blocs/tab_event.dart b/lib/pages/tab/blocs/tab_event.dart new file mode 100644 index 0000000..de244c4 --- /dev/null +++ b/lib/pages/tab/blocs/tab_event.dart @@ -0,0 +1,11 @@ +part of 'tab_bloc.dart'; + +@immutable +abstract class TabEvent { + const TabEvent(); +} + +class UpdateTabIndexEvent extends TabEvent { + final int index; + const UpdateTabIndexEvent(this.index); +} diff --git a/lib/pages/tab/blocs/tab_state.dart b/lib/pages/tab/blocs/tab_state.dart new file mode 100644 index 0000000..28ac36d --- /dev/null +++ b/lib/pages/tab/blocs/tab_state.dart @@ -0,0 +1,9 @@ +part of 'tab_bloc.dart'; + +@immutable +class TabState { + final int index; + const TabState({this.index = 0}); + TabState copyWith({int? index}) => TabState(index: index ?? this.index); +} + diff --git a/lib/pages/tab/tab_page.dart b/lib/pages/tab/tab_page.dart new file mode 100644 index 0000000..143d8f3 --- /dev/null +++ b/lib/pages/tab/tab_page.dart @@ -0,0 +1,66 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:wow_english/pages/home/home_page.dart'; +import 'package:wow_english/pages/lessons/lesson_page.dart'; + +import 'blocs/tab_bloc.dart'; + +class TabPage extends StatelessWidget { + const TabPage({super.key}); + + final _pages =const [ + HomePage(), + LessonPage() + ]; + + final _tabIcons = const [ + Icon(Icons.ac_unit), + Icon(Icons.ac_unit_outlined) + ]; + + final _tabTexts = const [ + '页面1', + '页面2' + ]; + + @override + Widget build(BuildContext context) { + return Scaffold( + body: _buildIndexedStack(), + bottomNavigationBar: _buildBottomNavBars(), + ); + } + + Widget _buildIndexedStack() => BlocBuilder( + builder: (context, state) => IndexedStack( + index: state.index, + children: _pages, + ) + ); + + Widget _buildBottomNavBars() => BlocBuilder( + builder: (context, state) => Container( + decoration: BoxDecoration( + boxShadow: [ + BoxShadow( + color: Theme.of(context).dividerColor, + blurRadius: .1 + ) + ] + ), + child: BottomNavigationBar( + currentIndex: state.index, + items: _buildBottomNavBarItems(context), + onTap: (value) => context.read().add(UpdateTabIndexEvent(value)), + ), + ) + ); + + List _buildBottomNavBarItems(BuildContext context) => _tabIcons.map((e) { + final index = _tabIcons.indexOf(e); + return BottomNavigationBarItem( + label: _tabTexts[index], + activeIcon: _tabIcons[index], + icon: _tabIcons[index] + );}).toList(); +} diff --git a/lib/pages/user/bloc/user_bloc.dart b/lib/pages/user/bloc/user_bloc.dart new file mode 100644 index 0000000..377b2aa --- /dev/null +++ b/lib/pages/user/bloc/user_bloc.dart @@ -0,0 +1,13 @@ +import 'package:bloc/bloc.dart'; +import 'package:meta/meta.dart'; + +part 'user_event.dart'; +part 'user_state.dart'; + +class UserBloc extends Bloc { + UserBloc() : super(UserInitial()) { + on((event, emit) { + // TODO: implement event handler + }); + } +} diff --git a/lib/pages/user/bloc/user_event.dart b/lib/pages/user/bloc/user_event.dart new file mode 100644 index 0000000..3dd7c37 --- /dev/null +++ b/lib/pages/user/bloc/user_event.dart @@ -0,0 +1,4 @@ +part of 'user_bloc.dart'; + +@immutable +abstract class UserEvent {} diff --git a/lib/pages/user/bloc/user_state.dart b/lib/pages/user/bloc/user_state.dart new file mode 100644 index 0000000..a2a6220 --- /dev/null +++ b/lib/pages/user/bloc/user_state.dart @@ -0,0 +1,6 @@ +part of 'user_bloc.dart'; + +@immutable +abstract class UserState {} + +class UserInitial extends UserState {} diff --git a/lib/pages/user/user_page.dart b/lib/pages/user/user_page.dart new file mode 100644 index 0000000..c29a825 --- /dev/null +++ b/lib/pages/user/user_page.dart @@ -0,0 +1,18 @@ +import 'package:flutter/material.dart'; +import 'package:wow_english/common/widgets/we_app_bar.dart'; + + +class UserPage extends StatelessWidget { + const UserPage({super.key}); + + @override + Widget build(BuildContext context) { + return const Scaffold( + backgroundColor: Colors.white, + appBar: WEAppBar( + titleText: '1', + ), + body: Row(), + ); + } +} diff --git a/lib/pages/video/lookvideo/bloc/look_video_bloc.dart b/lib/pages/video/lookvideo/bloc/look_video_bloc.dart new file mode 100644 index 0000000..9c10502 --- /dev/null +++ b/lib/pages/video/lookvideo/bloc/look_video_bloc.dart @@ -0,0 +1,17 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:video_player/video_player.dart'; + +part 'look_video_event.dart'; +part 'look_video_state.dart'; + +class LookVideoBloc extends Bloc { + + VideoPlayerController? _controller; + + LookVideoBloc() : super(LookVideoInitial()) { + on((event, emit) { + // TODO: implement event handler + }); + } +} diff --git a/lib/pages/video/lookvideo/bloc/look_video_event.dart b/lib/pages/video/lookvideo/bloc/look_video_event.dart new file mode 100644 index 0000000..95bd813 --- /dev/null +++ b/lib/pages/video/lookvideo/bloc/look_video_event.dart @@ -0,0 +1,4 @@ +part of 'look_video_bloc.dart'; + +@immutable +abstract class LookVideoEvent {} diff --git a/lib/pages/video/lookvideo/bloc/look_video_state.dart b/lib/pages/video/lookvideo/bloc/look_video_state.dart new file mode 100644 index 0000000..9d7102f --- /dev/null +++ b/lib/pages/video/lookvideo/bloc/look_video_state.dart @@ -0,0 +1,8 @@ +part of 'look_video_bloc.dart'; + +@immutable +abstract class LookVideoState {} + +class LookVideoInitial extends LookVideoState {} + +class VideoStarState extends LookVideoState {} diff --git a/lib/pages/video/lookvideo/look_video_page.dart b/lib/pages/video/lookvideo/look_video_page.dart new file mode 100644 index 0000000..44fc455 --- /dev/null +++ b/lib/pages/video/lookvideo/look_video_page.dart @@ -0,0 +1,40 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:wow_english/pages/video/lookvideo/widgets/video_widget.dart'; + +import 'bloc/look_video_bloc.dart'; + +class LookVideoPage extends StatefulWidget { + const LookVideoPage({super.key}); + + @override + State createState() { + return _LookVideoPageState(); + } +} + +class _LookVideoPageState extends State { + @override + Widget build(BuildContext context) { + return const VideoWidget( + videoUrl: 'https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/7194236f31b2e1e3da0fe06cfed4ba2b.mp4', + ); + } +} + +class _LookVideoPage extends StatelessWidget { + @override + Widget build(BuildContext context) { + return BlocListener( + listener: (context,state){}, + child: _lookVideoView(), + ); + } + + Widget _lookVideoView() => BlocBuilder( + builder: (context,state){ + return const VideoWidget( + videoUrl: 'https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/7194236f31b2e1e3da0fe06cfed4ba2b.mp4', + ); + }); +} \ No newline at end of file diff --git a/lib/pages/video/lookvideo/widgets/video_opera_widget.dart b/lib/pages/video/lookvideo/widgets/video_opera_widget.dart new file mode 100644 index 0000000..af07ec4 --- /dev/null +++ b/lib/pages/video/lookvideo/widgets/video_opera_widget.dart @@ -0,0 +1,184 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:wow_english/common/extension/string_extension.dart'; + +enum OperationType { + //返回 + back, + //字幕 + subtitlesState, + //静音 + audioState, + //暂停/播放 + playState, +} + +class VideoOperaWidget extends StatefulWidget { + const VideoOperaWidget({super.key, + this.currentTime = '00:00', + this.totalTime = '00:00', + this.degree = 0.0, + this.actionEvent, + this.sliderChangeEvent, + this.isPlay = true + }); + //当前播放时间 + final String currentTime; + //总时间 + final String totalTime; + final double degree; + final bool isPlay; + final Function(OperationType type)? actionEvent; + final Function(double degree)? sliderChangeEvent; + + @override + State createState() { + return _VideoOperaWidgetState(); + } +} + +class _VideoOperaWidgetState extends State { + + //是否在滑动 + late bool isSlider; + late double sliderValue; + + @override + void initState() { + super.initState(); + isSlider = false; + sliderValue = 0.0; + } + + @override + Widget build(BuildContext context) { + return SizedBox( + width: double.infinity, + height: double.infinity, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + SafeArea( + child: Padding( + padding: EdgeInsets.only(top: 11.h), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + GestureDetector( + onTap: (){ + widget.actionEvent?.call(OperationType.back); + }, + child: Image.asset( + 'back_around'.assetPng, + height: 40, + width: 40 + ), + ), + 18.horizontalSpace, + Container( + height: 40.h, + alignment: Alignment.center, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(6.r), + border: Border.all( + width: 1.5, + color: const Color(0xFF140C10) + ) + ), + padding: EdgeInsets.symmetric(horizontal: 10.w), + child: Text( + 'song', + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 20.sp, + color: const Color(0xFF333333), + ), + ), + ) + ], + ), + GestureDetector( + onTap: () { + widget.actionEvent?.call(OperationType.subtitlesState); + }, + child: Container( + height: 40.h, + alignment: Alignment.center, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(6.r), + border: Border.all( + width: 1.5, + color: const Color(0xFF140C10) + ) + ), + padding: EdgeInsets.symmetric(horizontal: 10.w), + child: Text( + '中/英', + style: TextStyle( + fontSize: 20.sp, + color: const Color(0xFF333333), + ), + ), + ), + ) + ], + ), + ), + ), + Container( + color: Colors.white10, + height: 47.h+ScreenUtil().bottomBarHeight, + padding: EdgeInsets.symmetric(horizontal: 11.w), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Row( + children: [ + IconButton(onPressed: (){ + widget.actionEvent?.call(OperationType.playState); + }, icon: widget.isPlay?const Icon(Icons.pause,color: Colors.white,):const Icon(Icons.play_arrow,color: Colors.white),), + Expanded( + child: Slider( + activeColor: Colors.blue, + inactiveColor: Colors.white, + value: isSlider?sliderValue:widget.degree, + onChangeStart: (value) { + setState(() { + isSlider = true; + sliderValue = value; + }); + }, + onChangeEnd: (value) { + setState(() { + isSlider = false; + }); + widget.sliderChangeEvent?.call(value); + }, + onChanged: (value) { + setState(() { + sliderValue = value; + }); + }, + ), + ), + Text( + '${widget.currentTime}/${widget.totalTime}', + style: TextStyle( + color: Colors.white, + fontSize: 12.sp + ), + ) + ], + ), + ], + ), + ) + ], + ), + ); + } +} \ No newline at end of file diff --git a/lib/pages/video/lookvideo/widgets/video_widget.dart b/lib/pages/video/lookvideo/widgets/video_widget.dart new file mode 100644 index 0000000..8238703 --- /dev/null +++ b/lib/pages/video/lookvideo/widgets/video_widget.dart @@ -0,0 +1,196 @@ +import 'package:common_utils/common_utils.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:video_player/video_player.dart'; +import 'package:wow_english/common/extension/string_extension.dart'; + +import 'video_opera_widget.dart'; + +class VideoWidget extends StatefulWidget { + const VideoWidget({super.key, this.videoUrl = ''}); + + final String videoUrl; + + @override + State createState() { + return _VideoWidgetState(); + } +} + +class _VideoWidgetState extends State { + VideoPlayerController? _controller; + String _currentTime = '00:00'; + String _totalTime = '00:00'; + double _playDegree = 0.0; + bool _hiddenTipView = false; + TimerUtil? timerUtil; + + String formatDuration(Duration duration) { + String hours = duration.inHours.toString().padLeft(2, '0'); + String minutes = duration.inMinutes.remainder(60).toString().padLeft(2, '0'); + String seconds = duration.inSeconds.remainder(60).toString().padLeft(2, '0'); + return "$hours:$minutes:$seconds"; + } + + void _addListener() { + _controller!.addListener(() { + if(_controller!.value.isInitialized) { + if (_controller!.value.isPlaying) { + setState(() { + double currentSecond = (_controller!.value.position.inMinutes.remainder(60)*60+_controller!.value.position.inSeconds.remainder(60)).toDouble(); + int totalSecond = _controller!.value.duration.inMinutes.remainder(60)*60+_controller!.value.duration.inSeconds.remainder(60); + _currentTime = formatDuration(_controller!.value.position); + _playDegree = currentSecond/totalSecond; + }); + } + } + }); + } + + //开始倒计时 + void startTimer() { + if(timerUtil == null) { + timerUtil = TimerUtil(mInterval: 1000,mTotalTime: 1000*10); + timerUtil!.setOnTimerTickCallback((int tick) { + double currentTick = tick / 1000; + if (kDebugMode) { + print(currentTick); + } + if (currentTick.toInt() == 0) {//倒计时结束 + setState(() { + _hiddenTipView = true; + }); + timerUtil!.cancel(); + timerUtil = null; + } + }); + timerUtil!.startCountDown(); + } + } + + //取消倒计时 + void cancelTimer() { + timerUtil!.cancel(); + timerUtil = null; + } + + void actionType(OperationType type) async { + if (type == OperationType.back) { + Navigator.pop(context); + } else if (type == OperationType.playState) { + if (_controller!.value.isPlaying) { + _controller!.pause(); + } else { + _controller!.play(); + } + setState(() { + + }); + } + } + + @override + void initState() { + super.initState(); + _controller = VideoPlayerController.network(widget.videoUrl) + ..initialize().then((_){ + startTimer(); + setState(() { + _currentTime = formatDuration(_controller!.value.position); + _totalTime = formatDuration(_controller!.value.duration); + _controller!.setLooping(true); + _controller!.setVolume(100); + _controller!.play(); + }); + _addListener(); + }); + } + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: () { + setState(() { + _hiddenTipView = !_hiddenTipView; + if(!_hiddenTipView) { + startTimer(); + } else { + if (timerUtil!.isActive()) { + cancelTimer(); + } + } + }); + }, + onDoubleTap: () { + if(_controller!.value.isInitialized) { + if (_controller!.value.isPlaying) { + _controller!.pause(); + } else { + _controller!.play(); + } + setState(() { + + }); + } + }, + child: Center( + child: _controller!.value.isInitialized ? Stack( + alignment: Alignment.center, + children: [ + SizedBox( + height: double.infinity, + width: double.infinity, + child: AspectRatio( + aspectRatio: _controller!.value.aspectRatio, + child: VideoPlayer(_controller!), + ), + ), + Offstage( + offstage: _hiddenTipView, + child: VideoOperaWidget( + currentTime: _currentTime, + totalTime: _totalTime, + degree: _playDegree, + isPlay: _controller!.value.isPlaying, + actionEvent: (OperationType type) { + actionType(type); + }, + sliderChangeEvent: (double degree) { + int totalSecond = _controller!.value.duration.inMinutes.remainder(60)*60+_controller!.value.duration.inSeconds.remainder(60); + int positionSecond = (totalSecond * degree).toInt(); + _controller!.seekTo(Duration(seconds: positionSecond)); + }, + ), + ), + Offstage( + offstage: _controller!.value.isPlaying, + child: IconButton( + onPressed: () { + _controller!.play(); + }, + icon: Image.asset( + 'video_stop'.assetPng, + width: 70, + height: 70, + ), + ), + ) + ], + ): Container( + color: Colors.white, + ), + ), + ); + } + + @override + void dispose() { + _controller?.dispose(); + _controller?.removeListener(() {}); + if (timerUtil != null) { + timerUtil!.cancel(); + timerUtil = null; + } + super.dispose(); + } +} diff --git a/lib/pages/voiceanswer/bloc/voice_answer_bloc.dart b/lib/pages/voiceanswer/bloc/voice_answer_bloc.dart new file mode 100644 index 0000000..745bb16 --- /dev/null +++ b/lib/pages/voiceanswer/bloc/voice_answer_bloc.dart @@ -0,0 +1,13 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +part 'voice_answer_event.dart'; +part 'voice_answer_state.dart'; + +class VoiceAnswerBloc extends Bloc { + VoiceAnswerBloc() : super(VoiceAnswerInitial()) { + on((event, emit) { + // TODO: implement event handler + }); + } +} diff --git a/lib/pages/voiceanswer/bloc/voice_answer_event.dart b/lib/pages/voiceanswer/bloc/voice_answer_event.dart new file mode 100644 index 0000000..e18461e --- /dev/null +++ b/lib/pages/voiceanswer/bloc/voice_answer_event.dart @@ -0,0 +1,4 @@ +part of 'voice_answer_bloc.dart'; + +@immutable +abstract class VoiceAnswerEvent {} diff --git a/lib/pages/voiceanswer/bloc/voice_answer_state.dart b/lib/pages/voiceanswer/bloc/voice_answer_state.dart new file mode 100644 index 0000000..07b6716 --- /dev/null +++ b/lib/pages/voiceanswer/bloc/voice_answer_state.dart @@ -0,0 +1,6 @@ +part of 'voice_answer_bloc.dart'; + +@immutable +abstract class VoiceAnswerState {} + +class VoiceAnswerInitial extends VoiceAnswerState {} diff --git a/lib/pages/voiceanswer/voice_answer_page.dart b/lib/pages/voiceanswer/voice_answer_page.dart new file mode 100644 index 0000000..d7b347f --- /dev/null +++ b/lib/pages/voiceanswer/voice_answer_page.dart @@ -0,0 +1,95 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:wow_english/common/extension/string_extension.dart'; +import 'package:wow_english/pages/practice/widgets/practice_header_widget.dart'; + +import 'bloc/voice_answer_bloc.dart'; + +class VoiceAnswerPage extends StatelessWidget { + const VoiceAnswerPage({super.key}); + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (_) => VoiceAnswerBloc(), + child: _VoiceAnswerPage(), + ); + } +} + +class _VoiceAnswerPage extends StatelessWidget { + @override + Widget build(BuildContext context) { + return BlocListener( + listener: (context, state) {}, + child: _voiceAnswerView(), + ); + } + + Widget _voiceAnswerView() => BlocBuilder( + builder: (context, state) { + final bloc = BlocProvider.of(context); + return Container( + color: Colors.white, + child: Stack( + children: [ + Positioned( + left: 0, + right: 0, + bottom: 0, + child: Image.asset( + 'bottom_grass'.assetPng, + fit: BoxFit.fitWidth, + )), + Column( + children: [ + PracticeHeaderWidget( + title: '1/8', + onTap: () { + Navigator.pop(context); + }, + ), + Expanded( + child: PageView.builder( + itemCount: 10, + itemBuilder: (context, int index) { + return _voiceAnswerItem(); + })) + ], + ) + ], + ), + ); + }); + + Widget _voiceAnswerItem() => BlocBuilder(builder: (context, state) { + return Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image.network( + 'https://img.liblibai.com/web/648331d5a2cb5.png?image_process=format,webp&x-oss-process=image/resize,w_2980,m_lfit/format,webp', + height: 186.h, + width: 186.w, + ), + 160.horizontalSpace, + Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image.asset( + 'voice'.assetPng, + height: 52.h, + width: 46.w, + ), + 70.verticalSpace, + Image.asset( + 'micro_phone'.assetPng, + height: 75.w, + width: 75.w, + ) + ], + ) + ], + ); + }); +} diff --git a/lib/practice/chosetopic/topicpicture/bloc/topic_picture_bloc.dart b/lib/practice/chosetopic/topicpicture/bloc/topic_picture_bloc.dart deleted file mode 100644 index 1248801..0000000 --- a/lib/practice/chosetopic/topicpicture/bloc/topic_picture_bloc.dart +++ /dev/null @@ -1,41 +0,0 @@ -import 'package:flutter/cupertino.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; - -part 'topic_picture_event.dart'; -part 'topic_picture_state.dart'; - -class TopicPictureBloc extends Bloc { - - final PageController pageController; - - final int modelCount; - - int _currentPage = 0; - - int _selectItem = 0; - - int get currentPage => _currentPage + 1; - - int get selectItem => _selectItem; - - TopicPictureBloc(this.pageController, this.modelCount) : super(TopicPictureInitial()) { - on(_pageControllerChange); - on(_selectItemLoad); - } - - @override - Future close() { - pageController.dispose(); - return super.close(); - } - - void _pageControllerChange(CurrentPageIndexChangeEvent event,Emitter emitter) async { - _currentPage = event.pageIndex; - emitter(CurrentPageIndexState()); - } - - void _selectItemLoad(SelectItemEvent event,Emitter emitter) async { - _selectItem = event.selectIndex; - emitter(SelectItemChangeState()); - } -} diff --git a/lib/practice/chosetopic/topicpicture/bloc/topic_picture_event.dart b/lib/practice/chosetopic/topicpicture/bloc/topic_picture_event.dart deleted file mode 100644 index 781f545..0000000 --- a/lib/practice/chosetopic/topicpicture/bloc/topic_picture_event.dart +++ /dev/null @@ -1,14 +0,0 @@ -part of 'topic_picture_bloc.dart'; - -@immutable -abstract class TopicPictureEvent {} - -class CurrentPageIndexChangeEvent extends TopicPictureEvent { - final int pageIndex; - CurrentPageIndexChangeEvent(this.pageIndex); -} - -class SelectItemEvent extends TopicPictureEvent { - final int selectIndex; - SelectItemEvent(this.selectIndex); -} \ No newline at end of file diff --git a/lib/practice/chosetopic/topicpicture/bloc/topic_picture_state.dart b/lib/practice/chosetopic/topicpicture/bloc/topic_picture_state.dart deleted file mode 100644 index af0e103..0000000 --- a/lib/practice/chosetopic/topicpicture/bloc/topic_picture_state.dart +++ /dev/null @@ -1,10 +0,0 @@ -part of 'topic_picture_bloc.dart'; - -@immutable -abstract class TopicPictureState {} - -class TopicPictureInitial extends TopicPictureState {} - -class CurrentPageIndexState extends TopicPictureState {} - -class SelectItemChangeState extends TopicPictureState {} diff --git a/lib/practice/chosetopic/topicpicture/topic_picture_page.dart b/lib/practice/chosetopic/topicpicture/topic_picture_page.dart deleted file mode 100644 index 6c5135b..0000000 --- a/lib/practice/chosetopic/topicpicture/topic_picture_page.dart +++ /dev/null @@ -1,141 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:wow_english/common/extension/string_extension.dart'; -import 'package:wow_english/practice/chosetopic/topicpicture/bloc/topic_picture_bloc.dart'; - -import '../../widgets/practice_header_widget.dart'; - -class TopicPicturePage extends StatelessWidget { - const TopicPicturePage({super.key}); - - @override - Widget build(BuildContext context) { - return BlocProvider( - create: (context) => TopicPictureBloc(PageController(),3), - child: _TopicPicturePage(), - ); - } -} - -class _TopicPicturePage extends StatelessWidget { - @override - Widget build(BuildContext context) { - return BlocListener( - listener: (context, state){}, - child: _topicPictureView(), - ); - } - - Widget _topicPictureView() => BlocBuilder( - buildWhen: (_,s) => s is CurrentPageIndexState, - builder: (context,state){ - final bloc = BlocProvider.of(context); - return Container( - color: Colors.white, - child: Stack( - children: [ - Column( - children: [ - PracticeHeaderWidget( - title: '${bloc.currentPage}/8', - onTap: (){Navigator.pop(context);}, - ), - Expanded( - child: PageView.builder( - itemCount: 8, - scrollDirection: Axis.horizontal, - controller: bloc.pageController, - onPageChanged: (int index) { - bloc.add(CurrentPageIndexChangeEvent(index)); - }, - itemBuilder: (BuildContext context,int index){ - return _pageViewItemWidget(); - }), - ) - ], - ), - Positioned( - left: 0, - right: 0, - bottom: 0, - child: Image.asset('bottom_grass'.assetPng) - ) - ], - ), - ); - }); - - Widget _pageViewItemWidget() => BlocBuilder( - builder: (context, state){ - final bloc = BlocProvider.of(context); - return SafeArea( - child: Column( - children: [ - Text( - 'What to do when the sentence question is very long and needs a line break', - softWrap: true, - style: TextStyle( - fontSize: 21.sp, - color: const Color(0xFF333333) - ) - ), - 26.verticalSpace, - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Offstage( - offstage: (bloc.modelCount < 1), - child: _decodeImageWidget(1), - ), - Offstage( - offstage: (bloc.modelCount < 2), - child: _decodeImageWidget(2), - ), - Offstage( - offstage: (bloc.modelCount < 3), - child: _decodeImageWidget(3), - ), - Offstage( - offstage: (bloc.modelCount < 4), - child: _decodeImageWidget(4), - ) - ], - ) - ], - ), - ); - }); - - Widget _decodeImageWidget(int index) => BlocBuilder( - buildWhen: (_, s) => s is SelectItemChangeState, - builder: (context,state){ - final bloc = BlocProvider.of(context); - return GestureDetector( - onTap: () => bloc.add(SelectItemEvent(index)), - child: Container( - padding: const EdgeInsets.all(4.5), - decoration: BoxDecoration( - color: bloc.selectItem == index?const Color(0xFF00B6F1):Colors.white, - borderRadius: BorderRadius.circular(15), - ), - height: 143.h, - width: 143.w, - child: Container( - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(15), - border: Border.all( - width: 1.0, - color: const Color(0xFF140C10) - ), - image: const DecorationImage( - fit: BoxFit.fitWidth, - image: NetworkImage('https://img1.baidu.com/it/u=3392591833,1640391553&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=714') - ) - ), - ), - ), - ); - }); -} \ No newline at end of file diff --git a/lib/practice/chosetopic/topicword/bloc/topic_word_bloc.dart b/lib/practice/chosetopic/topicword/bloc/topic_word_bloc.dart deleted file mode 100644 index 3197025..0000000 --- a/lib/practice/chosetopic/topicword/bloc/topic_word_bloc.dart +++ /dev/null @@ -1,41 +0,0 @@ - -import 'package:flutter/cupertino.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; - -part 'topic_word_event.dart'; -part 'topic_word_state.dart'; - -class TopicWordBloc extends Bloc { - final PageController pageController; - - final int modelCount; - - int _currentPage = 0; - - int _selectItem = 0; - - int get currentPage => _currentPage + 1; - - int get selectItem => _selectItem; - - TopicWordBloc(this.pageController, this.modelCount) : super(TopicWordInitial()) { - on(_pageControllerChange); - on(_selectItemLoad); - } - - @override - Future close() { - pageController.dispose(); - return super.close(); - } - - void _pageControllerChange(CurrentPageIndexChangeEvent event,Emitter emitter) async { - _currentPage = event.pageIndex; - emitter(CurrentPageIndexState()); - } - - void _selectItemLoad(SelectItemEvent event,Emitter emitter) async { - _selectItem = event.selectIndex; - emitter(SelectItemChangeState()); - } -} diff --git a/lib/practice/chosetopic/topicword/bloc/topic_word_event.dart b/lib/practice/chosetopic/topicword/bloc/topic_word_event.dart deleted file mode 100644 index 3decdf5..0000000 --- a/lib/practice/chosetopic/topicword/bloc/topic_word_event.dart +++ /dev/null @@ -1,14 +0,0 @@ -part of 'topic_word_bloc.dart'; - -@immutable -abstract class TopicWordEvent {} - -class CurrentPageIndexChangeEvent extends TopicWordEvent { - final int pageIndex; - CurrentPageIndexChangeEvent(this.pageIndex); -} - -class SelectItemEvent extends TopicWordEvent { - final int selectIndex; - SelectItemEvent(this.selectIndex); -} \ No newline at end of file diff --git a/lib/practice/chosetopic/topicword/bloc/topic_word_state.dart b/lib/practice/chosetopic/topicword/bloc/topic_word_state.dart deleted file mode 100644 index a27770f..0000000 --- a/lib/practice/chosetopic/topicword/bloc/topic_word_state.dart +++ /dev/null @@ -1,10 +0,0 @@ -part of 'topic_word_bloc.dart'; - -@immutable -abstract class TopicWordState {} - -class TopicWordInitial extends TopicWordState {} - -class CurrentPageIndexState extends TopicWordState {} - -class SelectItemChangeState extends TopicWordState {} \ No newline at end of file diff --git a/lib/practice/chosetopic/topicword/topic_word_page.dart b/lib/practice/chosetopic/topicword/topic_word_page.dart deleted file mode 100644 index b8f7c8c..0000000 --- a/lib/practice/chosetopic/topicword/topic_word_page.dart +++ /dev/null @@ -1,162 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:wow_english/common/extension/string_extension.dart'; -import 'package:wow_english/practice/chosetopic/topicword/bloc/topic_word_bloc.dart'; -import 'package:wow_english/practice/widgets/practice_header_widget.dart'; - -class TopicWordPage extends StatelessWidget { - const TopicWordPage({super.key}); - - @override - Widget build(BuildContext context) { - return BlocProvider( - create: (context) => TopicWordBloc(PageController(), 4), - child: _TopicWordPage(), - ); - } -} - -class _TopicWordPage extends StatelessWidget { - @override - Widget build(BuildContext context) { - return BlocListener( - listener: (context, state) { - - }, - child: _topicWordView(), - ); - } - - Widget _topicWordView() => BlocBuilder( - builder: (context,state){ - final bloc = BlocProvider.of(context); - return Container( - color: Colors.white, - child: Stack( - children: [ - Positioned( - left: 0, - right: 0, - bottom: 0, - child: Image.asset('background_grass'.assetPng,fit: BoxFit.fitWidth,) - ), - Column( - children: [ - PracticeHeaderWidget( - title: '${bloc.currentPage}/8', - onTap: (){Navigator.pop(context);}, - ), - Expanded( - child: PageView.builder( - itemCount: 8, - scrollDirection: Axis.horizontal, - controller: bloc.pageController, - onPageChanged: (int index) { - bloc.add(CurrentPageIndexChangeEvent(index)); - }, - itemBuilder: (BuildContext context,int index){ - return _pageViewItemWidget(); - }), - ) - ], - ), - ], - ), - ); - }); - - Widget _pageViewItemWidget() => BlocBuilder( - builder: (context, state){ - final bloc = BlocProvider.of(context); - return SafeArea( - child: Column( - children: [ - Text( - 'What to do when the sentence question is very long and needs a line break', - softWrap: true, - style: TextStyle( - fontSize: 21.sp, - color: const Color(0xFF333333) - ) - ), - 26.verticalSpace, - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Offstage( - offstage: (bloc.modelCount < 1), - child: _decodeImageWidget(1), - ), - Offstage( - offstage: (bloc.modelCount < 2), - child: _decodeImageWidget(2), - ), - Offstage( - offstage: (bloc.modelCount < 3), - child: _decodeImageWidget(3), - ), - Offstage( - offstage: (bloc.modelCount < 4), - child: _decodeImageWidget(4), - ) - ], - ) - ], - ), - ); - }); - - Widget _decodeImageWidget(int index) => BlocBuilder( - buildWhen: (_, s) => s is SelectItemChangeState, - builder: (context,state){ - final bloc = BlocProvider.of(context); - return GestureDetector( - onTap: () => bloc.add(SelectItemEvent(index)), - child: Container( - width: 143.w, - height: 143.h, - padding: EdgeInsets.only(left: 13.w,right: 13.w,top: 13.h,bottom: 13.h), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(15), - border: Border.all( - width: 1.0, - color: const Color(0xFF140C10) - ), - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Expanded( - child: Container( - alignment: Alignment.center, - child: Text( - 'yellow', - style: TextStyle( - fontSize: 20.sp, - color: const Color(0xFF333333) - ) - ), - ), - ), - Container( - height: 30.h, - width: double.infinity, - decoration: BoxDecoration( - color: bloc.selectItem == index?const Color(0xFF00B6F1):Colors.white, - borderRadius: BorderRadius.circular(15.r), - border: Border.all( - width: 1.5, - color: const Color(0xFF140C10) - ), - ), - alignment: Alignment.center, - child: Image.asset('choose'.assetPng), - ) - ], - ), - ), - ); - }); -} \ No newline at end of file diff --git a/lib/practice/voicetopic/voicepicture/bloc/voice_pic_bloc.dart b/lib/practice/voicetopic/voicepicture/bloc/voice_pic_bloc.dart deleted file mode 100644 index 073782d..0000000 --- a/lib/practice/voicetopic/voicepicture/bloc/voice_pic_bloc.dart +++ /dev/null @@ -1,39 +0,0 @@ -import 'package:flutter/cupertino.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; - -part 'voice_pic_event.dart'; -part 'voice_pic_state.dart'; - -class VoicePicBloc extends Bloc { - final PageController pageController; - - final int modelCount; - - int _currentPage = 0; - - int _selectItem = 0; - - int get currentPage => _currentPage + 1; - - int get selectItem => _selectItem; - VoicePicBloc(this.pageController, this.modelCount) : super(VoicePicInitial()) { - on(_pageControllerChange); - on(_selectItemLoad); - } - - @override - Future close() { - pageController.dispose(); - return super.close(); - } - - void _pageControllerChange(CurrentPageIndexChangeEvent event,Emitter emitter) async { - _currentPage = event.pageIndex; - emitter(CurrentPageIndexState()); - } - - void _selectItemLoad(SelectItemEvent event,Emitter emitter) async { - _selectItem = event.selectIndex; - emitter(SelectItemChangeState()); - } -} diff --git a/lib/practice/voicetopic/voicepicture/bloc/voice_pic_event.dart b/lib/practice/voicetopic/voicepicture/bloc/voice_pic_event.dart deleted file mode 100644 index c60b951..0000000 --- a/lib/practice/voicetopic/voicepicture/bloc/voice_pic_event.dart +++ /dev/null @@ -1,14 +0,0 @@ -part of 'voice_pic_bloc.dart'; - -@immutable -abstract class VoicePicEvent {} - -class CurrentPageIndexChangeEvent extends VoicePicEvent { - final int pageIndex; - CurrentPageIndexChangeEvent(this.pageIndex); -} - -class SelectItemEvent extends VoicePicEvent { - final int selectIndex; - SelectItemEvent(this.selectIndex); -} \ No newline at end of file diff --git a/lib/practice/voicetopic/voicepicture/bloc/voice_pic_state.dart b/lib/practice/voicetopic/voicepicture/bloc/voice_pic_state.dart deleted file mode 100644 index cd05460..0000000 --- a/lib/practice/voicetopic/voicepicture/bloc/voice_pic_state.dart +++ /dev/null @@ -1,10 +0,0 @@ -part of 'voice_pic_bloc.dart'; - -@immutable -abstract class VoicePicState {} - -class VoicePicInitial extends VoicePicState {} - -class CurrentPageIndexState extends VoicePicState {} - -class SelectItemChangeState extends VoicePicState {} \ No newline at end of file diff --git a/lib/practice/voicetopic/voicepicture/voice_pic_page.dart b/lib/practice/voicetopic/voicepicture/voice_pic_page.dart deleted file mode 100644 index b62d285..0000000 --- a/lib/practice/voicetopic/voicepicture/voice_pic_page.dart +++ /dev/null @@ -1,150 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:wow_english/common/extension/string_extension.dart'; -import 'package:wow_english/practice/voicetopic/voicepicture/bloc/voice_pic_bloc.dart'; -import 'package:wow_english/practice/widgets/practice_header_widget.dart'; - -class VoicePicPage extends StatelessWidget { - const VoicePicPage({super.key}); - - @override - Widget build(BuildContext context) { - return BlocProvider( - create: (context) => VoicePicBloc(PageController(),4), - child: _VoicePicPage(), - ); - } -} - -class _VoicePicPage extends StatelessWidget { - @override - Widget build(BuildContext context) { - return BlocListener( - listener: (context, state){}, - child: _voicePicView(), - ); - } - - Widget _voicePicView() => BlocBuilder( - builder: (context, state){ - return _voicePictureView(); - }); - - Widget _voicePictureView() => BlocBuilder( - buildWhen: (_,s) => s is CurrentPageIndexState, - builder: (context,state){ - final bloc = BlocProvider.of(context); - return Container( - color: Colors.white, - child: Stack( - children: [ - Image.asset( - 'road_bg'.assetPng, - height: double.infinity, - width: double.infinity - ), - Column( - children: [ - PracticeHeaderWidget( - title: '${bloc.currentPage}/8', - onTap: (){Navigator.pop(context);}, - ), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Image.asset('voice'.assetPng,height: 33.h,width: 30.w,), - 10.horizontalSpace, - Text( - 'yellow', - style: TextStyle( - fontSize: 20.sp, - color: const Color(0xFF333333) - ) - ) - ], - ), - 26.verticalSpace, - Expanded( - child: PageView.builder( - itemCount: 8, - scrollDirection: Axis.horizontal, - controller: bloc.pageController, - onPageChanged: (int index) { - bloc.add(CurrentPageIndexChangeEvent(index)); - }, - itemBuilder: (BuildContext context,int index){ - return _pageViewItemWidget(); - }), - ) - ], - ) - ], - ), - ); - }); - - Widget _pageViewItemWidget() => BlocBuilder( - builder: (context, state){ - final bloc = BlocProvider.of(context); - return SafeArea( - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Offstage( - offstage: (bloc.modelCount < 1), - child: _decodeImageWidget(1), - ), - Offstage( - offstage: (bloc.modelCount < 2), - child: _decodeImageWidget(2), - ), - Offstage( - offstage: (bloc.modelCount < 3), - child: _decodeImageWidget(3), - ), - Offstage( - offstage: (bloc.modelCount < 4), - child: _decodeImageWidget(4), - ) - ], - ) - ], - ), - ); - }); - - Widget _decodeImageWidget(int index) => BlocBuilder( - buildWhen: (_, s) => s is SelectItemChangeState, - builder: (context,state){ - final bloc = BlocProvider.of(context); - return GestureDetector( - onTap: () => bloc.add(SelectItemEvent(index)), - child: Container( - padding: const EdgeInsets.all(4.5), - decoration: BoxDecoration( - color: bloc.selectItem == index?const Color(0xFF00B6F1):Colors.white, - borderRadius: BorderRadius.circular(15), - ), - height: 143.h, - width: 143.w, - child: Container( - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(15), - border: Border.all( - width: 1.0, - color: const Color(0xFF140C10) - ), - image: const DecorationImage( - fit: BoxFit.fitWidth, - image: NetworkImage('https://img1.baidu.com/it/u=3392591833,1640391553&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=714') - ) - ), - ), - ), - ); - }); -} \ No newline at end of file diff --git a/lib/practice/voicetopic/voiceword/bloc/voice_word_bloc.dart b/lib/practice/voicetopic/voiceword/bloc/voice_word_bloc.dart deleted file mode 100644 index c768bd4..0000000 --- a/lib/practice/voicetopic/voiceword/bloc/voice_word_bloc.dart +++ /dev/null @@ -1,41 +0,0 @@ - -import 'package:flutter/cupertino.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; - -part 'voice_word_event.dart'; -part 'voice_word_state.dart'; - -class VoiceWordBloc extends Bloc { - final PageController pageController; - - final int modelCount; - - int _currentPage = 0; - - int _selectItem = 0; - - int get currentPage => _currentPage + 1; - - int get selectItem => _selectItem; - VoiceWordBloc(this.pageController, this.modelCount) : super(VoiceWordInitial()) { - on(_pageControllerChange); - on(_selectItemLoad); - } - - @override - Future close() { - pageController.dispose(); - return super.close(); - } - - void _pageControllerChange(CurrentPageIndexChangeEvent event,Emitter emitter) async { - _currentPage = event.pageIndex; - emitter(CurrentPageIndexState()); - } - - void _selectItemLoad(SelectItemEvent event,Emitter emitter) async { - _selectItem = event.selectIndex; - emitter(SelectItemChangeState()); - } -} - diff --git a/lib/practice/voicetopic/voiceword/bloc/voice_word_event.dart b/lib/practice/voicetopic/voiceword/bloc/voice_word_event.dart deleted file mode 100644 index 1d556a2..0000000 --- a/lib/practice/voicetopic/voiceword/bloc/voice_word_event.dart +++ /dev/null @@ -1,14 +0,0 @@ -part of 'voice_word_bloc.dart'; - -@immutable -abstract class VoiceWordEvent {} - -class CurrentPageIndexChangeEvent extends VoiceWordEvent { - final int pageIndex; - CurrentPageIndexChangeEvent(this.pageIndex); -} - -class SelectItemEvent extends VoiceWordEvent { - final int selectIndex; - SelectItemEvent(this.selectIndex); -} \ No newline at end of file diff --git a/lib/practice/voicetopic/voiceword/bloc/voice_word_state.dart b/lib/practice/voicetopic/voiceword/bloc/voice_word_state.dart deleted file mode 100644 index 81993db..0000000 --- a/lib/practice/voicetopic/voiceword/bloc/voice_word_state.dart +++ /dev/null @@ -1,10 +0,0 @@ -part of 'voice_word_bloc.dart'; - -@immutable -abstract class VoiceWordState {} - -class VoiceWordInitial extends VoiceWordState {} - -class CurrentPageIndexState extends VoiceWordState {} - -class SelectItemChangeState extends VoiceWordState {} diff --git a/lib/practice/voicetopic/voiceword/voice_word_page.dart b/lib/practice/voicetopic/voiceword/voice_word_page.dart deleted file mode 100644 index 55bdbfc..0000000 --- a/lib/practice/voicetopic/voiceword/voice_word_page.dart +++ /dev/null @@ -1,159 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:wow_english/common/extension/string_extension.dart'; -import 'package:wow_english/practice/voicetopic/voiceword/bloc/voice_word_bloc.dart'; -import 'package:wow_english/practice/widgets/practice_header_widget.dart'; - -class VoiceWordPage extends StatelessWidget { - const VoiceWordPage({super.key}); - - - @override - Widget build(BuildContext context) { - return BlocProvider( - create: (context) => VoiceWordBloc(PageController(),4), - child: _VoiceWordPage(), - ); - } -} - -class _VoiceWordPage extends StatelessWidget { - @override - Widget build(BuildContext context) { - return BlocListener( - listener: (context, state){}, - child: _voiceWorView(), - ); - } - - Widget _voiceWorView() => BlocBuilder( - builder: (context, state){ - return _voiceWordView(); - }); - - Widget _voiceWordView() => BlocBuilder( - buildWhen: (_,s) => s is CurrentPageIndexState, - builder: (context,state){ - final bloc = BlocProvider.of(context); - return Container( - color: Colors.white, - child: Stack( - children: [ - Image.asset( - 'road_bg'.assetPng, - height: double.infinity, - width: double.infinity - ), - Column( - children: [ - PracticeHeaderWidget( - title: '${bloc.currentPage}/8', - onTap: (){Navigator.pop(context);}, - ), - Image.asset('voice'.assetPng,height: 33.h,width: 30.w,), - 26.verticalSpace, - Expanded( - child: PageView.builder( - itemCount: 8, - scrollDirection: Axis.horizontal, - controller: bloc.pageController, - onPageChanged: (int index) { - bloc.add(CurrentPageIndexChangeEvent(index)); - }, - itemBuilder: (BuildContext context,int index){ - return _pageViewItemWidget(); - }), - ) - ], - ) - ], - ), - ); - }); - - Widget _pageViewItemWidget() => BlocBuilder( - builder: (context, state){ - final bloc = BlocProvider.of(context); - return SafeArea( - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Offstage( - offstage: (bloc.modelCount < 1), - child: _decodeImageWidget(1), - ), - Offstage( - offstage: (bloc.modelCount < 2), - child: _decodeImageWidget(2), - ), - Offstage( - offstage: (bloc.modelCount < 3), - child: _decodeImageWidget(3), - ), - Offstage( - offstage: (bloc.modelCount < 4), - child: _decodeImageWidget(4), - ) - ], - ) - ], - ), - ); - }); - - Widget _decodeImageWidget(int index) => BlocBuilder( - buildWhen: (_, s) => s is SelectItemChangeState, - builder: (context,state){ - final bloc = BlocProvider.of(context); - return GestureDetector( - onTap: () => bloc.add(SelectItemEvent(index)), - child: Container( - width: 143.w, - height: 143.h, - padding: EdgeInsets.only(left: 13.w,right: 13.w,top: 13.h,bottom: 13.h), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(15), - border: Border.all( - width: 1.0, - color: const Color(0xFF140C10) - ), - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Expanded( - child: Container( - alignment: Alignment.center, - child: Text( - 'yellow', - style: TextStyle( - fontSize: 20.sp, - color: const Color(0xFF333333) - ) - ), - ), - ), - Container( - height: 30.h, - width: double.infinity, - decoration: BoxDecoration( - color: bloc.selectItem == index?const Color(0xFF00B6F1):Colors.white, - borderRadius: BorderRadius.circular(15.r), - border: Border.all( - width: 1.5, - color: const Color(0xFF140C10) - ), - ), - alignment: Alignment.center, - child: Image.asset('choose'.assetPng), - ) - ], - ), - ), - ); - }); -} \ No newline at end of file diff --git a/lib/practice/widgets/practice_header_widget.dart b/lib/practice/widgets/practice_header_widget.dart deleted file mode 100644 index 456f314..0000000 --- a/lib/practice/widgets/practice_header_widget.dart +++ /dev/null @@ -1,59 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:wow_english/common/extension/string_extension.dart'; - -class PracticeHeaderWidget extends StatelessWidget { - const PracticeHeaderWidget({super.key, required this.onTap,this.title = ''}); - - final Function() onTap; - - final String title; - - @override - Widget build(BuildContext context) { - return Container( - color: Colors.white, - height: 60.h, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Padding( - padding: EdgeInsets.only( - left: ScreenUtil().bottomBarHeight - ), - child: IconButton( - onPressed: (){ - onTap(); - }, - icon: Image.asset( - 'back_around'.assetPng, - width: 40, - height: 40, - )), - ), - Container( - height: 40.h, - padding: EdgeInsets.symmetric(horizontal: 27.w), - decoration: BoxDecoration( - color: const Color(0xFF00B6F1), - borderRadius: BorderRadius.circular(20.r), - border: Border.all( - width: 1.0, - color: const Color(0xFF333333), - ), - ), - alignment: Alignment.center, - child: Text( - title, - style: TextStyle( - fontSize: 20.sp, - color: Colors.white - ), - ), - ), - ScreenUtil().bottomBarHeight.horizontalSpace, - ], - ), - ); - } -} \ No newline at end of file diff --git a/lib/repeatafter/bloc/repeat_after_bloc.dart b/lib/repeatafter/bloc/repeat_after_bloc.dart deleted file mode 100644 index 1d42860..0000000 --- a/lib/repeatafter/bloc/repeat_after_bloc.dart +++ /dev/null @@ -1,23 +0,0 @@ -import 'package:flutter/cupertino.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:flutter_easyloading/flutter_easyloading.dart'; - -part 'repeat_after_event.dart'; -part 'repeat_after_state.dart'; - -class RepeatAfterBloc extends Bloc { - RepeatAfterBloc() : super(RepeatAfterInitial()) { - on((event, emit) { - // TODO: implement event handler - }); - } - - - Future requestData() async { - EasyLoading.show(); - Future.delayed(const Duration(milliseconds: 2000),(){ - EasyLoading.dismiss(); - emit(RequestDataState()); - }); - } -} diff --git a/lib/repeatafter/bloc/repeat_after_event.dart b/lib/repeatafter/bloc/repeat_after_event.dart deleted file mode 100644 index 3a46031..0000000 --- a/lib/repeatafter/bloc/repeat_after_event.dart +++ /dev/null @@ -1,4 +0,0 @@ -part of 'repeat_after_bloc.dart'; - -@immutable -abstract class RepeatAfterEvent {} diff --git a/lib/repeatafter/bloc/repeat_after_state.dart b/lib/repeatafter/bloc/repeat_after_state.dart deleted file mode 100644 index e8c710f..0000000 --- a/lib/repeatafter/bloc/repeat_after_state.dart +++ /dev/null @@ -1,8 +0,0 @@ -part of 'repeat_after_bloc.dart'; - -@immutable -abstract class RepeatAfterState {} - -class RepeatAfterInitial extends RepeatAfterState {} - -class RequestDataState extends RepeatAfterState {} diff --git a/lib/repeatafter/repeat_after_page.dart b/lib/repeatafter/repeat_after_page.dart deleted file mode 100644 index 0dc36ca..0000000 --- a/lib/repeatafter/repeat_after_page.dart +++ /dev/null @@ -1,65 +0,0 @@ -import 'dart:math'; - -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:flutter_easyloading/flutter_easyloading.dart'; -import 'package:wow_english/common/widgets/we_app_bar.dart'; -import 'package:wow_english/repeatafter/widgets/repeat_after_item.dart'; - -import 'bloc/repeat_after_bloc.dart'; - -class RepeatAfterPage extends StatelessWidget { - const RepeatAfterPage({super.key}); - - @override - Widget build(BuildContext context) { - return BlocProvider( - create: (context) => RepeatAfterBloc()..requestData(), - child: _RepeatAfterPageView(), - ); - } -} - -class _RepeatAfterPageView extends StatelessWidget { - @override - Widget build(BuildContext context) { - return BlocListener( - listener: (context, state) { - if (state is RequestDataState) { - EasyLoading.showToast('网络请求结束'); - } - }, - child: _repeatAfterView(), - ); - } - - Widget _repeatAfterView() => BlocBuilder( - builder: (context, state) { - return Scaffold( - appBar: const WEAppBar( - titleText: '视频跟读', - centerTitle: false, - ), - body: SafeArea( - child: Container( - alignment: Alignment.center, - child: ListView.builder( - itemCount: 10, - scrollDirection: Axis.horizontal, - itemBuilder: (BuildContext context,int index){ - bool unLock = index%3==0; - return RepeatAfterItem( - unLock: unLock, - tapEvent: () { - - }, - starNumber: !unLock?0:Random().nextInt(5) - ); - }), - ), - ), - ); - }, - ); -} - diff --git a/lib/repeatafter/widgets/repeat_after_item.dart b/lib/repeatafter/widgets/repeat_after_item.dart deleted file mode 100644 index c898b48..0000000 --- a/lib/repeatafter/widgets/repeat_after_item.dart +++ /dev/null @@ -1,137 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:wow_english/common/extension/string_extension.dart'; - -class RepeatAfterItem extends StatelessWidget { - const RepeatAfterItem({super.key, required this.starNumber, required this.unLock, required this.tapEvent}); - //分数 - final int starNumber; - //是否解锁 - final bool unLock; - - final Function() tapEvent; - - @override - Widget build(BuildContext context) { - return Padding( - padding: EdgeInsets.symmetric( - horizontal: 10.w - ), - child: GestureDetector( - onTap: (){ - if(unLock) { - tapEvent(); - } - }, - child: Stack( - children: [ - _modelInfoWidget(context), - _lockWidget() - ], - ), - ), - ); - } - - Widget _modelInfoWidget(BuildContext context) { - return Container( - width: 162.w, - height: 235.h, - decoration: BoxDecoration( - image: DecorationImage( - image: AssetImage( - 'gendubeij'.assetPng - ), - fit: BoxFit.fill - ) - ), - padding: EdgeInsets.symmetric(horizontal: 11.w,vertical: 13.h), - alignment: Alignment.center, - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Image.network( - 'https://img.liblibai.com/web/648331d033b41.png?image_process=format,webp&x-oss-process=image/resize,w_2980,m_lfit/format,webp', - height: 100.h, - width: 140.w, - fit: BoxFit.fitWidth, - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Image.asset( - starNumber >= 1 ? 'star_light'.assetPng:'star_dark'.assetPng, - width: 23.w, - height: 21.h, - ), - Image.asset( - starNumber >= 2 ? 'star_light'.assetPng:'star_dark'.assetPng, - width: 23.w, - height: 21.h, - ), - Image.asset( - starNumber >= 3 ? 'star_light'.assetPng:'star_dark'.assetPng, - width: 23.w, - height: 21.h, - ), - Image.asset( - starNumber >= 4 ? 'star_light'.assetPng:'star_dark'.assetPng, - width: 23.w, - height: 21.h, - ), - Image.asset( - starNumber >= 5 ? 'star_light'.assetPng:'star_dark'.assetPng, - width: 23.w, - height: 21.h, - ), - ], - ), - Container( - height: 35.h, - width: double.infinity, - decoration: BoxDecoration( - color: const Color(0xFFFFCC00), - borderRadius: BorderRadius.circular(5.r), - border: Border.all( - width: 1.0, - color: const Color(0xFF333333), - ), - ), - alignment: Alignment.center, - child: Text( - 'video title', - style: TextStyle( - fontSize: 16.sp, - color: const Color(0xFF333333) - ), - ), - ) - ], - ), - ); - } - - Widget _lockWidget() { - return Offstage( - offstage: unLock, - child: Container( - width: 162.w, - height: 235.h, - decoration: BoxDecoration( - image: DecorationImage( - image: AssetImage( - 'gendubeij_mengban'.assetPng - ), - fit: BoxFit.fill - ) - ), - alignment: Alignment.center, - child: Image.asset( - 'listen_lock'.assetPng, - height: 36.h, - width: 41.w, - ), - ), - ); - } -} \ No newline at end of file diff --git a/lib/route/route.dart b/lib/route/route.dart index 6fa7707..7033394 100644 --- a/lib/route/route.dart +++ b/lib/route/route.dart @@ -2,24 +2,25 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:wow_english/app/splash_page.dart'; import 'package:wow_english/common/pages/wow_web_page.dart'; -import 'package:wow_english/home/home_page.dart'; -import 'package:wow_english/lessons/lesson_page.dart'; -import 'package:wow_english/listen/listen_page.dart'; -import 'package:wow_english/login/forgetpwd/forget_password_home_page.dart'; -import 'package:wow_english/login/loginpage/login_page.dart'; -import 'package:wow_english/login/setpwd/set_pwd_page.dart'; -import 'package:wow_english/practice/chosetopic/topicpicture/topic_picture_page.dart'; -import 'package:wow_english/practice/chosetopic/topicword/topic_word_page.dart'; -import 'package:wow_english/practice/voicetopic/voicepicture/voice_pic_page.dart'; -import 'package:wow_english/practice/voicetopic/voiceword/voice_word_page.dart'; -import 'package:wow_english/repeatafter/repeat_after_page.dart'; -import 'package:wow_english/shop/exchane/exchange_lesson_page.dart'; -import 'package:wow_english/shop/exchangelist/exchange_lesson_list_page.dart'; -import 'package:wow_english/shop/home/shop_home_page.dart'; -import 'package:wow_english/tab/tab_page.dart'; -import 'package:wow_english/user/user_page.dart'; -import 'package:wow_english/video/lookvideo/look_video_page.dart'; -import 'package:wow_english/voiceanswer/voice_answer_page.dart'; +import 'package:wow_english/pages/home/home_page.dart'; +import 'package:wow_english/pages/lessons/lesson_page.dart'; +import 'package:wow_english/pages/listen/listen_page.dart'; +import 'package:wow_english/pages/login/forgetpwd/forget_password_home_page.dart'; +import 'package:wow_english/pages/login/loginpage/login_page.dart'; +import 'package:wow_english/pages/login/setpwd/set_pwd_page.dart'; +import 'package:wow_english/pages/practice/chosetopic/topicpicture/topic_picture_page.dart'; +import 'package:wow_english/pages/practice/chosetopic/topicword/topic_word_page.dart'; +import 'package:wow_english/pages/practice/voicetopic/voicepicture/voice_pic_page.dart'; +import 'package:wow_english/pages/practice/voicetopic/voiceword/voice_word_page.dart'; +import 'package:wow_english/pages/repeatafter/repeat_after_page.dart'; +import 'package:wow_english/pages/shop/exchane/exchange_lesson_page.dart'; +import 'package:wow_english/pages/shop/exchangelist/exchange_lesson_list_page.dart'; +import 'package:wow_english/pages/shop/home/shop_home_page.dart'; +import 'package:wow_english/pages/tab/tab_page.dart'; +import 'package:wow_english/pages/user/user_page.dart'; +import 'package:wow_english/pages/video/lookvideo/look_video_page.dart'; +import 'package:wow_english/pages/voiceanswer/voice_answer_page.dart'; + class AppRouteName { diff --git a/lib/shop/exchane/bloc/exchange_lesson_bloc.dart b/lib/shop/exchane/bloc/exchange_lesson_bloc.dart deleted file mode 100644 index 27dc483..0000000 --- a/lib/shop/exchane/bloc/exchange_lesson_bloc.dart +++ /dev/null @@ -1,37 +0,0 @@ -import 'package:flutter/cupertino.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; - -part 'exchange_lesson_event.dart'; -part 'exchange_lesson_state.dart'; - -class ExchangeLessonBloc extends Bloc { - - final TextEditingController codeNumberController = TextEditingController(); - - bool _checkCode = false; - - bool get checkCode => _checkCode; - - ExchangeLessonBloc() : super(ExchangeLessonInitial()) { - on(_codeNumberChange); - on(_requestCheckCode); - } - - _codeNumberChange(CodeNumberChangeEvent event,Emitter emitter) async { - if(codeNumberController.text.isNotEmpty) { - if (!_checkCode) { - _checkCode = true; - emitter(CheckCodeTypeChangeState()); - } - } else { - if (_checkCode) { - _checkCode = false; - emitter(CheckCodeTypeChangeState()); - } - } - } - - _requestCheckCode(CheckCodeEvent event, Emitter emitter) async { - emitter(CheckCodeResultState(false)); - } -} diff --git a/lib/shop/exchane/bloc/exchange_lesson_event.dart b/lib/shop/exchane/bloc/exchange_lesson_event.dart deleted file mode 100644 index 7a5d7d9..0000000 --- a/lib/shop/exchane/bloc/exchange_lesson_event.dart +++ /dev/null @@ -1,8 +0,0 @@ -part of 'exchange_lesson_bloc.dart'; - -@immutable -abstract class ExchangeLessonEvent {} -//输入兑换码 -class CodeNumberChangeEvent extends ExchangeLessonEvent {} -//验证兑换码 -class CheckCodeEvent extends ExchangeLessonEvent {} diff --git a/lib/shop/exchane/bloc/exchange_lesson_state.dart b/lib/shop/exchane/bloc/exchange_lesson_state.dart deleted file mode 100644 index 71ddfe1..0000000 --- a/lib/shop/exchane/bloc/exchange_lesson_state.dart +++ /dev/null @@ -1,13 +0,0 @@ -part of 'exchange_lesson_bloc.dart'; - -@immutable -abstract class ExchangeLessonState {} - -class ExchangeLessonInitial extends ExchangeLessonState {} -//输入兑换码状态 -class CheckCodeTypeChangeState extends ExchangeLessonState {} -//验证兑换码结果 -class CheckCodeResultState extends ExchangeLessonState { - final bool result; - CheckCodeResultState(this.result); -} diff --git a/lib/shop/exchane/exchange_lesson_page.dart b/lib/shop/exchane/exchange_lesson_page.dart deleted file mode 100644 index e026b83..0000000 --- a/lib/shop/exchane/exchange_lesson_page.dart +++ /dev/null @@ -1,133 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:flutter_easyloading/flutter_easyloading.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:wow_english/common/extension/string_extension.dart'; -import 'package:wow_english/common/widgets/textfield_customer_widget.dart'; -import 'package:wow_english/route/route.dart'; - -import 'bloc/exchange_lesson_bloc.dart'; - -class ExchangeLessonPage extends StatelessWidget { - const ExchangeLessonPage({super.key}); - - @override - Widget build(BuildContext context) { - return BlocProvider( - create: (context) => ExchangeLessonBloc(), - child: _ExchangeLessonPage(), - ); - } -} - -class _ExchangeLessonPage extends StatelessWidget { - @override - Widget build(BuildContext context) { - return BlocListener( - listener: (context, state){ - if (state is CheckCodeResultState) { - String title = state.result?'兑换成功':'兑换失败'; - EasyLoading.showToast(title); - Navigator.of(context).pushNamed(AppRouteName.exList); - } - }, - child: _exchangeLessonPageView(), - ); - } - - Widget _exchangeLessonPageView() => BlocBuilder( - builder: (context, state){ - final bloc = BlocProvider.of(context); - return Scaffold( - resizeToAvoidBottomInset: false, - body: Container( - color: Colors.white, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - 10.5.verticalSpace, - Padding( - padding: EdgeInsets.symmetric( - horizontal: 15.w - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - IconButton( - icon: Image.asset( - 'back_around'.assetPng, - width: 40, - height: 40, - ), - color: Colors.white, - onPressed: () { - Navigator.pop(context); - }, - ), - Image.asset( - 'wow_ex_lesson'.assetPng, - width: 139.w, - height: 81.h, - ), - SizedBox.fromSize( - size: const Size(40.0, 40.0) - ) - ], - ), - ), - Expanded( - child: Padding( - padding: EdgeInsets.symmetric(horizontal: 135.w), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - TextFieldCustomerWidget( - height: 55.h, - hitText: '请输入兑换码', - bgImageName: 'Input_layer_up', - textInputType: TextInputType.emailAddress, - controller: bloc.codeNumberController, - onChangeValue: (String value) { - bloc.add(CodeNumberChangeEvent()); - }, - ), - 21.5.verticalSpace, - GestureDetector( - onTap: () { - if (bloc.checkCode) { - bloc.add(CheckCodeEvent()); - } - }, - child: Container( - decoration: BoxDecoration( - image: DecorationImage( - image: AssetImage( - bloc.checkCode ? 'ex_sure'.assetPng:'ex_dis'.assetPng - ), - fit: BoxFit.fill - ), - ), - padding: EdgeInsets.symmetric(horizontal:27.w,vertical: 14.h), - child: Text( - '兑换', - style: TextStyle( - fontSize: 16.sp, - color: Colors.white - ), - ), - ), - ) - ], - ), - ), - ), - Image.asset( - 'bottom_grass'.assetPng, - ), - ], - ), - ), - ); - }); -} \ No newline at end of file diff --git a/lib/shop/exchangelist/bloc/exchange_list_bloc.dart b/lib/shop/exchangelist/bloc/exchange_list_bloc.dart deleted file mode 100644 index bccf206..0000000 --- a/lib/shop/exchangelist/bloc/exchange_list_bloc.dart +++ /dev/null @@ -1,15 +0,0 @@ -import 'dart:async'; - -import 'package:bloc/bloc.dart'; -import 'package:meta/meta.dart'; - -part 'exchange_list_event.dart'; -part 'exchange_list_state.dart'; - -class ExchangeListBloc extends Bloc { - ExchangeListBloc() : super(ExchangeListInitial()) { - on((event, emit) { - // TODO: implement event handler - }); - } -} diff --git a/lib/shop/exchangelist/bloc/exchange_list_event.dart b/lib/shop/exchangelist/bloc/exchange_list_event.dart deleted file mode 100644 index ae28d88..0000000 --- a/lib/shop/exchangelist/bloc/exchange_list_event.dart +++ /dev/null @@ -1,4 +0,0 @@ -part of 'exchange_list_bloc.dart'; - -@immutable -abstract class ExchangeListEvent {} diff --git a/lib/shop/exchangelist/bloc/exchange_list_state.dart b/lib/shop/exchangelist/bloc/exchange_list_state.dart deleted file mode 100644 index 80e9f94..0000000 --- a/lib/shop/exchangelist/bloc/exchange_list_state.dart +++ /dev/null @@ -1,6 +0,0 @@ -part of 'exchange_list_bloc.dart'; - -@immutable -abstract class ExchangeListState {} - -class ExchangeListInitial extends ExchangeListState {} diff --git a/lib/shop/exchangelist/exchange_lesson_list_page.dart b/lib/shop/exchangelist/exchange_lesson_list_page.dart deleted file mode 100644 index deb6035..0000000 --- a/lib/shop/exchangelist/exchange_lesson_list_page.dart +++ /dev/null @@ -1,47 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:wow_english/common/widgets/we_app_bar.dart'; -import 'package:wow_english/shop/exchangelist/widgets/exchange_list_item.dart'; - -import 'bloc/exchange_list_bloc.dart'; - -class ExchangeLessonListPage extends StatelessWidget { - const ExchangeLessonListPage({super.key}); - - @override - Widget build(BuildContext context) { - return BlocProvider( - create: (context) => ExchangeListBloc(), - child: _ExchangeLessonListPageView(), - ); - } -} - -class _ExchangeLessonListPageView extends StatelessWidget { - @override - Widget build(BuildContext context) { - return BlocListener( - listener: (context,state){}, - child: _exchangeLessonListView(), - ); - } - - Widget _exchangeLessonListView() => BlocBuilder( - builder: (context, state){ - return Scaffold( - appBar: const WEAppBar( - titleText: '购买记录', - ), - body: SafeArea( - child: ListView.builder( - itemCount: 10, - itemBuilder: (BuildContext context,int index){ - return ExchangeListItem( - isCheck: index%3==0, - ); - }), - ), - ); - } - ); -} \ No newline at end of file diff --git a/lib/shop/exchangelist/widgets/exchange_list_item.dart b/lib/shop/exchangelist/widgets/exchange_list_item.dart deleted file mode 100644 index 5c78876..0000000 --- a/lib/shop/exchangelist/widgets/exchange_list_item.dart +++ /dev/null @@ -1,124 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:wow_english/common/extension/string_extension.dart'; - -class ExchangeListItem extends StatelessWidget { - const ExchangeListItem({super.key, required this.isCheck}); - - final bool isCheck; - - @override - Widget build(BuildContext context) { - return SizedBox( - height: 127.h, - width: double.infinity, - child: Padding( - padding: EdgeInsets.only(left: 32.w,right: 32.w,bottom:13.h), - child: GestureDetector( - onTap: () { - - }, - child: Container( - decoration: BoxDecoration( - image: DecorationImage( - image: AssetImage( - 'listback'.assetPng, - ), - fit: BoxFit.fill - ) - ), - padding: EdgeInsets.symmetric(horizontal: 12.w), - child: Row( - children: [ - Container( - width: 70.w, - height: 70.h, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(5.r), - border: Border.all( - width: 1.0, - color: const Color(0xFF333333), - ), - image: const DecorationImage( - image: NetworkImage('https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fsafe-img.xhscdn.com%2Fbw1%2Faa1c2213-820a-4223-8757-5f8cee318a28%3FimageView2%2F2%2Fw%2F1080%2Fformat%2Fjpg&refer=http%3A%2F%2Fsafe-img.xhscdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1688713226&t=192b18a613683bcdc5bd76f65c9ff032'), - ), - ), - ), - 17.horizontalSpace, - Expanded( - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - Row( - children: [ - Expanded( - child: Text( - '标题:wow english课程永久使用卡', - textAlign: TextAlign.left, - style: TextStyle( - fontSize: 20.sp, - color: const Color(0xFF333333) - ), - ), - ), - Offstage( - offstage: isCheck, - child: Image.asset( - 'checked_logo'.assetPng, - width: 33.w, - height: 35.h - ), - ) - ], - ), - Padding( - padding: EdgeInsets.only(right: 35.w), - child: Row( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Expanded( - child: Text( - '兑换日期:2022-03-08 12:22:33', - textAlign: TextAlign.left, - style: TextStyle( - fontSize: 12.sp, - color: const Color(0xFF333333) - ), - ), - ), - Column( - mainAxisAlignment: MainAxisAlignment.end, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - '生效日期:2023-01-03', - textAlign: TextAlign.left, - style: TextStyle( - fontSize: 12.sp, - color: const Color(0xFF333333) - ), - ), - Text( - '有效期至:永久有效', - textAlign: TextAlign.left, - style: TextStyle( - fontSize: 12.sp, - color: const Color(0xFF333333) - ), - ) - ], - ) - ], - ), - ) - ], - ), - ) - ], - ), - ), - ), - ), - ); - } -} \ No newline at end of file diff --git a/lib/shop/home/bloc/shop_home_bloc.dart b/lib/shop/home/bloc/shop_home_bloc.dart deleted file mode 100644 index bd765c2..0000000 --- a/lib/shop/home/bloc/shop_home_bloc.dart +++ /dev/null @@ -1,15 +0,0 @@ -import 'dart:async'; - -import 'package:bloc/bloc.dart'; -import 'package:meta/meta.dart'; - -part 'shop_home_event.dart'; -part 'shop_home_state.dart'; - -class ShopHomeBloc extends Bloc { - ShopHomeBloc() : super(ShopHomeInitial()) { - on((event, emit) { - // TODO: implement event handler - }); - } -} diff --git a/lib/shop/home/bloc/shop_home_event.dart b/lib/shop/home/bloc/shop_home_event.dart deleted file mode 100644 index f35f8fd..0000000 --- a/lib/shop/home/bloc/shop_home_event.dart +++ /dev/null @@ -1,4 +0,0 @@ -part of 'shop_home_bloc.dart'; - -@immutable -abstract class ShopHomeEvent {} diff --git a/lib/shop/home/bloc/shop_home_state.dart b/lib/shop/home/bloc/shop_home_state.dart deleted file mode 100644 index d0b3c17..0000000 --- a/lib/shop/home/bloc/shop_home_state.dart +++ /dev/null @@ -1,6 +0,0 @@ -part of 'shop_home_bloc.dart'; - -@immutable -abstract class ShopHomeState {} - -class ShopHomeInitial extends ShopHomeState {} diff --git a/lib/shop/home/shop_home_page.dart b/lib/shop/home/shop_home_page.dart deleted file mode 100644 index 6a29df9..0000000 --- a/lib/shop/home/shop_home_page.dart +++ /dev/null @@ -1,81 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:flutter_easyloading/flutter_easyloading.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:wow_english/common/extension/string_extension.dart'; -import 'package:wow_english/common/widgets/we_app_bar.dart'; -import 'package:wow_english/route/route.dart'; -import 'package:wow_english/shop/home/bloc/shop_home_bloc.dart'; -import 'package:wow_english/shop/home/widgets/lesson_card_item.dart'; - -class ShopHomePage extends StatelessWidget { - const ShopHomePage({super.key}); - - @override - Widget build(BuildContext context) { - return BlocProvider( - create: (context) => ShopHomeBloc(), - child: _ShopHomeView(), - ); - } -} - -class _ShopHomeView extends StatelessWidget { - @override - Widget build(BuildContext context) { - return BlocListener( - listener: (context, state) {}, - child: _shopHomeWidget(), - ); - } - - Widget _shopHomeWidget() => BlocBuilder(builder: (context, state){ - return Scaffold( - appBar: WEAppBar( - actions: [ - IconButton( - icon: Image.asset( - 'check_lesson'.assetPng, - width: 40, - height: 40, - ), - color: Colors.white, - onPressed: () { - Navigator.of(context).pushNamed(AppRouteName.exLesson); - }, - ), - IconButton( - icon: Image.asset( - 'shop'.assetPng, - width: 40, - height: 40, - ), - color: Colors.white, - onPressed: () { - EasyLoading.showToast('购前须知'); - }, - ) - ], - ), - body: Center( - child: Padding( - padding: EdgeInsets.symmetric(vertical: 25.h,horizontal: 25.w), - child: GridView.builder( - itemCount: 4, - gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 2, - childAspectRatio: 2, - mainAxisSpacing: 14.h, - crossAxisSpacing : 4.5.w, - ), - itemBuilder: (BuildContext context,int index){ - return LessonCardItem( - onTap: (){ - EasyLoading.showToast('购买'); - }); - }), - ), - ), - ); - }); -} \ No newline at end of file diff --git a/lib/shop/home/widgets/lesson_card_item.dart b/lib/shop/home/widgets/lesson_card_item.dart deleted file mode 100644 index 8e42403..0000000 --- a/lib/shop/home/widgets/lesson_card_item.dart +++ /dev/null @@ -1,111 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; - -class LessonCardItem extends StatelessWidget { - const LessonCardItem({super.key, required this.onTap}); - - final Function() onTap; - - @override - Widget build(BuildContext context) { - return Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(10.r), - color: Colors.blue, - border: Border.all( - width: 1.0, - color: Colors.black - ) - // image: DecorationImage( - // image: AssetImage( - // ''.assetPng, - // ), - // fit: BoxFit.fill - // ) - ), - padding: EdgeInsets.symmetric(horizontal: 16.w,vertical: 16.h), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Container( - width: 124.w, - decoration: BoxDecoration( - border: Border.all( - width: 1.0, - color: const Color(0xFF333333), - ), - image: const DecorationImage( - fit: BoxFit.fill, - image: NetworkImage('https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fsafe-img.xhscdn.com%2Fbw1%2Faa1c2213-820a-4223-8757-5f8cee318a28%3FimageView2%2F2%2Fw%2F1080%2Fformat%2Fjpg&refer=http%3A%2F%2Fsafe-img.xhscdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1688713226&t=192b18a613683bcdc5bd76f65c9ff032'), - ) - ), - ), - 21.5.horizontalSpace, - Expanded( - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Text( - 'Wow English 课程年卡', - softWrap: true, - textAlign: TextAlign.left, - style: TextStyle( - fontSize: 12.sp, - color: const Color(0xFF333333) - ), - ), - RichText( - text: TextSpan( - children:[ - TextSpan( - text: '¥', - style: TextStyle( - fontSize: 21.sp, - color: const Color(0xFFF51A1A), - ) - ), - TextSpan( - text: '998', - style: TextStyle( - fontSize: 40.sp, - color: const Color(0xFFF51A1A), - ), - ) - ] - ), - ), - GestureDetector( - onTap: () { - onTap(); - }, - child: Container( - decoration: BoxDecoration( - color: const Color(0xFFF5C51F), - borderRadius: BorderRadius.circular(5.r), - border: Border.all( - color: const Color(0xFF333333), - width: 1.0, - ) - ), - padding: EdgeInsets.symmetric( - vertical: 1.h, - horizontal: 26.5.w, - ), - child: Text( - '立即购买', - style: TextStyle( - fontSize: 10.sp, - color: const Color(0xFF333333) - ), - ), - ), - ) - ], - ), - ) - ], - ), - ); - } -} \ No newline at end of file diff --git a/lib/tab/blocs/tab_bloc.dart b/lib/tab/blocs/tab_bloc.dart deleted file mode 100644 index bbd9a3b..0000000 --- a/lib/tab/blocs/tab_bloc.dart +++ /dev/null @@ -1,18 +0,0 @@ -import 'dart:async'; - -import 'package:bloc/bloc.dart'; -import 'package:meta/meta.dart'; - -part 'tab_event.dart'; -part 'tab_state.dart'; - -class TabBloc extends Bloc { - TabBloc() : super(const TabState()) { - on(_onUpdateTabIndex); - } - - void _onUpdateTabIndex( - UpdateTabIndexEvent event, Emitter emitter) async { - emitter(state.copyWith(index: event.index)); - } -} diff --git a/lib/tab/blocs/tab_event.dart b/lib/tab/blocs/tab_event.dart deleted file mode 100644 index de244c4..0000000 --- a/lib/tab/blocs/tab_event.dart +++ /dev/null @@ -1,11 +0,0 @@ -part of 'tab_bloc.dart'; - -@immutable -abstract class TabEvent { - const TabEvent(); -} - -class UpdateTabIndexEvent extends TabEvent { - final int index; - const UpdateTabIndexEvent(this.index); -} diff --git a/lib/tab/blocs/tab_state.dart b/lib/tab/blocs/tab_state.dart deleted file mode 100644 index 28ac36d..0000000 --- a/lib/tab/blocs/tab_state.dart +++ /dev/null @@ -1,9 +0,0 @@ -part of 'tab_bloc.dart'; - -@immutable -class TabState { - final int index; - const TabState({this.index = 0}); - TabState copyWith({int? index}) => TabState(index: index ?? this.index); -} - diff --git a/lib/tab/tab_page.dart b/lib/tab/tab_page.dart deleted file mode 100644 index ea9035c..0000000 --- a/lib/tab/tab_page.dart +++ /dev/null @@ -1,65 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:wow_english/home/home_page.dart'; -import 'package:wow_english/lessons/lesson_page.dart'; -import 'package:wow_english/tab/blocs/tab_bloc.dart'; - -class TabPage extends StatelessWidget { - const TabPage({super.key}); - - final _pages =const [ - HomePage(), - LessonPage() - ]; - - final _tabIcons = const [ - Icon(Icons.ac_unit), - Icon(Icons.ac_unit_outlined) - ]; - - final _tabTexts = const [ - '页面1', - '页面2' - ]; - - @override - Widget build(BuildContext context) { - return Scaffold( - body: _buildIndexedStack(), - bottomNavigationBar: _buildBottomNavBars(), - ); - } - - Widget _buildIndexedStack() => BlocBuilder( - builder: (context, state) => IndexedStack( - index: state.index, - children: _pages, - ) - ); - - Widget _buildBottomNavBars() => BlocBuilder( - builder: (context, state) => Container( - decoration: BoxDecoration( - boxShadow: [ - BoxShadow( - color: Theme.of(context).dividerColor, - blurRadius: .1 - ) - ] - ), - child: BottomNavigationBar( - currentIndex: state.index, - items: _buildBottomNavBarItems(context), - onTap: (value) => context.read().add(UpdateTabIndexEvent(value)), - ), - ) - ); - - List _buildBottomNavBarItems(BuildContext context) => _tabIcons.map((e) { - final index = _tabIcons.indexOf(e); - return BottomNavigationBarItem( - label: _tabTexts[index], - activeIcon: _tabIcons[index], - icon: _tabIcons[index] - );}).toList(); -} diff --git a/lib/user/bloc/user_bloc.dart b/lib/user/bloc/user_bloc.dart deleted file mode 100644 index 377b2aa..0000000 --- a/lib/user/bloc/user_bloc.dart +++ /dev/null @@ -1,13 +0,0 @@ -import 'package:bloc/bloc.dart'; -import 'package:meta/meta.dart'; - -part 'user_event.dart'; -part 'user_state.dart'; - -class UserBloc extends Bloc { - UserBloc() : super(UserInitial()) { - on((event, emit) { - // TODO: implement event handler - }); - } -} diff --git a/lib/user/bloc/user_event.dart b/lib/user/bloc/user_event.dart deleted file mode 100644 index 3dd7c37..0000000 --- a/lib/user/bloc/user_event.dart +++ /dev/null @@ -1,4 +0,0 @@ -part of 'user_bloc.dart'; - -@immutable -abstract class UserEvent {} diff --git a/lib/user/bloc/user_state.dart b/lib/user/bloc/user_state.dart deleted file mode 100644 index a2a6220..0000000 --- a/lib/user/bloc/user_state.dart +++ /dev/null @@ -1,6 +0,0 @@ -part of 'user_bloc.dart'; - -@immutable -abstract class UserState {} - -class UserInitial extends UserState {} diff --git a/lib/user/user_page.dart b/lib/user/user_page.dart deleted file mode 100644 index 6d1e600..0000000 --- a/lib/user/user_page.dart +++ /dev/null @@ -1,18 +0,0 @@ -import 'package:flutter/material.dart'; - -import '../common/widgets/we_app_bar.dart'; - -class UserPage extends StatelessWidget { - const UserPage({super.key}); - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: Colors.white, - appBar: WEAppBar( - titleText: '1', - ), - body: Row(), - ); - } -} diff --git a/lib/video/lookvideo/bloc/look_video_bloc.dart b/lib/video/lookvideo/bloc/look_video_bloc.dart deleted file mode 100644 index 9c10502..0000000 --- a/lib/video/lookvideo/bloc/look_video_bloc.dart +++ /dev/null @@ -1,17 +0,0 @@ -import 'package:flutter/cupertino.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:video_player/video_player.dart'; - -part 'look_video_event.dart'; -part 'look_video_state.dart'; - -class LookVideoBloc extends Bloc { - - VideoPlayerController? _controller; - - LookVideoBloc() : super(LookVideoInitial()) { - on((event, emit) { - // TODO: implement event handler - }); - } -} diff --git a/lib/video/lookvideo/bloc/look_video_event.dart b/lib/video/lookvideo/bloc/look_video_event.dart deleted file mode 100644 index 95bd813..0000000 --- a/lib/video/lookvideo/bloc/look_video_event.dart +++ /dev/null @@ -1,4 +0,0 @@ -part of 'look_video_bloc.dart'; - -@immutable -abstract class LookVideoEvent {} diff --git a/lib/video/lookvideo/bloc/look_video_state.dart b/lib/video/lookvideo/bloc/look_video_state.dart deleted file mode 100644 index 9d7102f..0000000 --- a/lib/video/lookvideo/bloc/look_video_state.dart +++ /dev/null @@ -1,8 +0,0 @@ -part of 'look_video_bloc.dart'; - -@immutable -abstract class LookVideoState {} - -class LookVideoInitial extends LookVideoState {} - -class VideoStarState extends LookVideoState {} diff --git a/lib/video/lookvideo/look_video_page.dart b/lib/video/lookvideo/look_video_page.dart deleted file mode 100644 index 9cba9a6..0000000 --- a/lib/video/lookvideo/look_video_page.dart +++ /dev/null @@ -1,39 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:wow_english/video/lookvideo/bloc/look_video_bloc.dart'; -import 'package:wow_english/video/lookvideo/widgets/video_widget.dart'; - -class LookVideoPage extends StatefulWidget { - const LookVideoPage({super.key}); - - @override - State createState() { - return _LookVideoPageState(); - } -} - -class _LookVideoPageState extends State { - @override - Widget build(BuildContext context) { - return const VideoWidget( - videoUrl: 'https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/7194236f31b2e1e3da0fe06cfed4ba2b.mp4', - ); - } -} - -class _LookVideoPage extends StatelessWidget { - @override - Widget build(BuildContext context) { - return BlocListener( - listener: (context,state){}, - child: _lookVideoView(), - ); - } - - Widget _lookVideoView() => BlocBuilder( - builder: (context,state){ - return const VideoWidget( - videoUrl: 'https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/7194236f31b2e1e3da0fe06cfed4ba2b.mp4', - ); - }); -} \ No newline at end of file diff --git a/lib/video/lookvideo/widgets/video_opera_widget.dart b/lib/video/lookvideo/widgets/video_opera_widget.dart deleted file mode 100644 index af07ec4..0000000 --- a/lib/video/lookvideo/widgets/video_opera_widget.dart +++ /dev/null @@ -1,184 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:wow_english/common/extension/string_extension.dart'; - -enum OperationType { - //返回 - back, - //字幕 - subtitlesState, - //静音 - audioState, - //暂停/播放 - playState, -} - -class VideoOperaWidget extends StatefulWidget { - const VideoOperaWidget({super.key, - this.currentTime = '00:00', - this.totalTime = '00:00', - this.degree = 0.0, - this.actionEvent, - this.sliderChangeEvent, - this.isPlay = true - }); - //当前播放时间 - final String currentTime; - //总时间 - final String totalTime; - final double degree; - final bool isPlay; - final Function(OperationType type)? actionEvent; - final Function(double degree)? sliderChangeEvent; - - @override - State createState() { - return _VideoOperaWidgetState(); - } -} - -class _VideoOperaWidgetState extends State { - - //是否在滑动 - late bool isSlider; - late double sliderValue; - - @override - void initState() { - super.initState(); - isSlider = false; - sliderValue = 0.0; - } - - @override - Widget build(BuildContext context) { - return SizedBox( - width: double.infinity, - height: double.infinity, - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - SafeArea( - child: Padding( - padding: EdgeInsets.only(top: 11.h), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - GestureDetector( - onTap: (){ - widget.actionEvent?.call(OperationType.back); - }, - child: Image.asset( - 'back_around'.assetPng, - height: 40, - width: 40 - ), - ), - 18.horizontalSpace, - Container( - height: 40.h, - alignment: Alignment.center, - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(6.r), - border: Border.all( - width: 1.5, - color: const Color(0xFF140C10) - ) - ), - padding: EdgeInsets.symmetric(horizontal: 10.w), - child: Text( - 'song', - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 20.sp, - color: const Color(0xFF333333), - ), - ), - ) - ], - ), - GestureDetector( - onTap: () { - widget.actionEvent?.call(OperationType.subtitlesState); - }, - child: Container( - height: 40.h, - alignment: Alignment.center, - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(6.r), - border: Border.all( - width: 1.5, - color: const Color(0xFF140C10) - ) - ), - padding: EdgeInsets.symmetric(horizontal: 10.w), - child: Text( - '中/英', - style: TextStyle( - fontSize: 20.sp, - color: const Color(0xFF333333), - ), - ), - ), - ) - ], - ), - ), - ), - Container( - color: Colors.white10, - height: 47.h+ScreenUtil().bottomBarHeight, - padding: EdgeInsets.symmetric(horizontal: 11.w), - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Row( - children: [ - IconButton(onPressed: (){ - widget.actionEvent?.call(OperationType.playState); - }, icon: widget.isPlay?const Icon(Icons.pause,color: Colors.white,):const Icon(Icons.play_arrow,color: Colors.white),), - Expanded( - child: Slider( - activeColor: Colors.blue, - inactiveColor: Colors.white, - value: isSlider?sliderValue:widget.degree, - onChangeStart: (value) { - setState(() { - isSlider = true; - sliderValue = value; - }); - }, - onChangeEnd: (value) { - setState(() { - isSlider = false; - }); - widget.sliderChangeEvent?.call(value); - }, - onChanged: (value) { - setState(() { - sliderValue = value; - }); - }, - ), - ), - Text( - '${widget.currentTime}/${widget.totalTime}', - style: TextStyle( - color: Colors.white, - fontSize: 12.sp - ), - ) - ], - ), - ], - ), - ) - ], - ), - ); - } -} \ No newline at end of file diff --git a/lib/video/lookvideo/widgets/video_widget.dart b/lib/video/lookvideo/widgets/video_widget.dart deleted file mode 100644 index 1fa1642..0000000 --- a/lib/video/lookvideo/widgets/video_widget.dart +++ /dev/null @@ -1,195 +0,0 @@ -import 'package:common_utils/common_utils.dart'; -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; -import 'package:video_player/video_player.dart'; -import 'package:wow_english/common/extension/string_extension.dart'; -import 'package:wow_english/video/lookvideo/widgets/video_opera_widget.dart'; - -class VideoWidget extends StatefulWidget { - const VideoWidget({super.key, this.videoUrl = ''}); - - final String videoUrl; - - @override - State createState() { - return _VideoWidgetState(); - } -} - -class _VideoWidgetState extends State { - VideoPlayerController? _controller; - String _currentTime = '00:00'; - String _totalTime = '00:00'; - double _playDegree = 0.0; - bool _hiddenTipView = false; - TimerUtil? timerUtil; - - String formatDuration(Duration duration) { - String hours = duration.inHours.toString().padLeft(2, '0'); - String minutes = duration.inMinutes.remainder(60).toString().padLeft(2, '0'); - String seconds = duration.inSeconds.remainder(60).toString().padLeft(2, '0'); - return "$hours:$minutes:$seconds"; - } - - void _addListener() { - _controller!.addListener(() { - if(_controller!.value.isInitialized) { - if (_controller!.value.isPlaying) { - setState(() { - double currentSecond = (_controller!.value.position.inMinutes.remainder(60)*60+_controller!.value.position.inSeconds.remainder(60)).toDouble(); - int totalSecond = _controller!.value.duration.inMinutes.remainder(60)*60+_controller!.value.duration.inSeconds.remainder(60); - _currentTime = formatDuration(_controller!.value.position); - _playDegree = currentSecond/totalSecond; - }); - } - } - }); - } - - //开始倒计时 - void startTimer() { - if(timerUtil == null) { - timerUtil = TimerUtil(mInterval: 1000,mTotalTime: 1000*10); - timerUtil!.setOnTimerTickCallback((int tick) { - double currentTick = tick / 1000; - if (kDebugMode) { - print(currentTick); - } - if (currentTick.toInt() == 0) {//倒计时结束 - setState(() { - _hiddenTipView = true; - }); - timerUtil!.cancel(); - timerUtil = null; - } - }); - timerUtil!.startCountDown(); - } - } - - //取消倒计时 - void cancelTimer() { - timerUtil!.cancel(); - timerUtil = null; - } - - void actionType(OperationType type) async { - if (type == OperationType.back) { - Navigator.pop(context); - } else if (type == OperationType.playState) { - if (_controller!.value.isPlaying) { - _controller!.pause(); - } else { - _controller!.play(); - } - setState(() { - - }); - } - } - - @override - void initState() { - super.initState(); - _controller = VideoPlayerController.network(widget.videoUrl) - ..initialize().then((_){ - startTimer(); - setState(() { - _currentTime = formatDuration(_controller!.value.position); - _totalTime = formatDuration(_controller!.value.duration); - _controller!.setLooping(true); - _controller!.setVolume(100); - _controller!.play(); - }); - _addListener(); - }); - } - - @override - Widget build(BuildContext context) { - return GestureDetector( - onTap: () { - setState(() { - _hiddenTipView = !_hiddenTipView; - if(!_hiddenTipView) { - startTimer(); - } else { - if (timerUtil!.isActive()) { - cancelTimer(); - } - } - }); - }, - onDoubleTap: () { - if(_controller!.value.isInitialized) { - if (_controller!.value.isPlaying) { - _controller!.pause(); - } else { - _controller!.play(); - } - setState(() { - - }); - } - }, - child: Center( - child: _controller!.value.isInitialized ? Stack( - alignment: Alignment.center, - children: [ - SizedBox( - height: double.infinity, - width: double.infinity, - child: AspectRatio( - aspectRatio: _controller!.value.aspectRatio, - child: VideoPlayer(_controller!), - ), - ), - Offstage( - offstage: _hiddenTipView, - child: VideoOperaWidget( - currentTime: _currentTime, - totalTime: _totalTime, - degree: _playDegree, - isPlay: _controller!.value.isPlaying, - actionEvent: (OperationType type) { - actionType(type); - }, - sliderChangeEvent: (double degree) { - int totalSecond = _controller!.value.duration.inMinutes.remainder(60)*60+_controller!.value.duration.inSeconds.remainder(60); - int positionSecond = (totalSecond * degree).toInt(); - _controller!.seekTo(Duration(seconds: positionSecond)); - }, - ), - ), - Offstage( - offstage: _controller!.value.isPlaying, - child: IconButton( - onPressed: () { - _controller!.play(); - }, - icon: Image.asset( - 'video_stop'.assetPng, - width: 70, - height: 70, - ), - ), - ) - ], - ): Container( - color: Colors.white, - ), - ), - ); - } - - @override - void dispose() { - _controller?.dispose(); - _controller?.removeListener(() {}); - if (timerUtil != null) { - timerUtil!.cancel(); - timerUtil = null; - } - super.dispose(); - } -} diff --git a/lib/voiceanswer/bloc/voice_answer_bloc.dart b/lib/voiceanswer/bloc/voice_answer_bloc.dart deleted file mode 100644 index 745bb16..0000000 --- a/lib/voiceanswer/bloc/voice_answer_bloc.dart +++ /dev/null @@ -1,13 +0,0 @@ -import 'package:flutter/cupertino.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; - -part 'voice_answer_event.dart'; -part 'voice_answer_state.dart'; - -class VoiceAnswerBloc extends Bloc { - VoiceAnswerBloc() : super(VoiceAnswerInitial()) { - on((event, emit) { - // TODO: implement event handler - }); - } -} diff --git a/lib/voiceanswer/bloc/voice_answer_event.dart b/lib/voiceanswer/bloc/voice_answer_event.dart deleted file mode 100644 index e18461e..0000000 --- a/lib/voiceanswer/bloc/voice_answer_event.dart +++ /dev/null @@ -1,4 +0,0 @@ -part of 'voice_answer_bloc.dart'; - -@immutable -abstract class VoiceAnswerEvent {} diff --git a/lib/voiceanswer/bloc/voice_answer_state.dart b/lib/voiceanswer/bloc/voice_answer_state.dart deleted file mode 100644 index 07b6716..0000000 --- a/lib/voiceanswer/bloc/voice_answer_state.dart +++ /dev/null @@ -1,6 +0,0 @@ -part of 'voice_answer_bloc.dart'; - -@immutable -abstract class VoiceAnswerState {} - -class VoiceAnswerInitial extends VoiceAnswerState {} diff --git a/lib/voiceanswer/voice_answer_page.dart b/lib/voiceanswer/voice_answer_page.dart deleted file mode 100644 index 246f3b3..0000000 --- a/lib/voiceanswer/voice_answer_page.dart +++ /dev/null @@ -1,94 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:wow_english/common/extension/string_extension.dart'; -import 'package:wow_english/practice/widgets/practice_header_widget.dart'; -import 'package:wow_english/voiceanswer/bloc/voice_answer_bloc.dart'; - -class VoiceAnswerPage extends StatelessWidget { - const VoiceAnswerPage({super.key}); - - @override - Widget build(BuildContext context) { - return BlocProvider( - create: (_) => VoiceAnswerBloc(), - child: _VoiceAnswerPage(), - ); - } -} - -class _VoiceAnswerPage extends StatelessWidget { - @override - Widget build(BuildContext context) { - return BlocListener( - listener: (context, state) {}, - child: _voiceAnswerView(), - ); - } - - Widget _voiceAnswerView() => BlocBuilder( - builder: (context, state) { - final bloc = BlocProvider.of(context); - return Container( - color: Colors.white, - child: Stack( - children: [ - Positioned( - left: 0, - right: 0, - bottom: 0, - child: Image.asset( - 'bottom_grass'.assetPng, - fit: BoxFit.fitWidth, - )), - Column( - children: [ - PracticeHeaderWidget( - title: '1/8', - onTap: () { - Navigator.pop(context); - }, - ), - Expanded( - child: PageView.builder( - itemCount: 10, - itemBuilder: (context, int index) { - return _voiceAnswerItem(); - })) - ], - ) - ], - ), - ); - }); - - Widget _voiceAnswerItem() => BlocBuilder(builder: (context, state) { - return Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Image.network( - 'https://img.liblibai.com/web/648331d5a2cb5.png?image_process=format,webp&x-oss-process=image/resize,w_2980,m_lfit/format,webp', - height: 186.h, - width: 186.w, - ), - 160.horizontalSpace, - Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Image.asset( - 'voice'.assetPng, - height: 52.h, - width: 46.w, - ), - 70.verticalSpace, - Image.asset( - 'micro_phone'.assetPng, - height: 75.w, - width: 75.w, - ) - ], - ) - ], - ); - }); -} -- libgit2 0.22.2