Browse Source

增加老师端琴房课课程组详情

Pq 7 tháng trước cách đây
mục cha
commit
c9ecee2ba6
21 tập tin đã thay đổi với 2138 bổ sung7 xóa
  1. 1 0
      BaseLibrary/src/main/java/com/cooleshow/base/router/RouterPath.kt
  2. 6 0
      teacher/src/main/AndroidManifest.xml
  3. 11 0
      teacher/src/main/java/com/cooleshow/teacher/adapter/MineCoursePageAdapter.java
  4. 92 0
      teacher/src/main/java/com/cooleshow/teacher/adapter/PianoCourseGroupCourseListAdapter.java
  5. 48 0
      teacher/src/main/java/com/cooleshow/teacher/adapter/PianoCourseGroupStudentListAdapter.java
  6. 11 0
      teacher/src/main/java/com/cooleshow/teacher/api/APIService.java
  7. 247 0
      teacher/src/main/java/com/cooleshow/teacher/bean/PianoCourseGroupCourseListBean.java
  8. 99 0
      teacher/src/main/java/com/cooleshow/teacher/bean/PianoCourseGroupStudentListBean.java
  9. 32 0
      teacher/src/main/java/com/cooleshow/teacher/contract/PianoCourseGroupDetailContract.java
  10. 123 0
      teacher/src/main/java/com/cooleshow/teacher/presenter/course/PianoCourseGroupDetailPresenter.java
  11. 338 0
      teacher/src/main/java/com/cooleshow/teacher/ui/course/PianoCourseGroupDetailActivity.java
  12. 312 0
      teacher/src/main/java/com/cooleshow/teacher/ui/course/PianoCourseGroupDetailFragment.java
  13. 69 0
      teacher/src/main/java/com/cooleshow/teacher/ui/course/PianoCourseGroupDetailStudentFragment.java
  14. 9 0
      teacher/src/main/java/com/cooleshow/teacher/ui/course/PianoCourseGroupFragment.java
  15. 339 0
      teacher/src/main/res/layout/ac_piano_course_group_detail_layout.xml
  16. 118 0
      teacher/src/main/res/layout/fg_piano_course_group_detail_layout.xml
  17. 13 0
      teacher/src/main/res/layout/fg_piano_course_group_detail_student_list_layout.xml
  18. 178 0
      teacher/src/main/res/layout/item_piano_course_group_course_layout.xml
  19. 75 0
      teacher/src/main/res/layout/item_piano_course_group_student_layout.xml
  20. 15 7
      teacher/src/main/res/layout/item_vip_course_group_layout.xml
  21. 2 0
      teacher/src/main/res/values/strings.xml

+ 1 - 0
BaseLibrary/src/main/java/com/cooleshow/base/router/RouterPath.kt

@@ -98,6 +98,7 @@ object RouterPath {
             const val SPARRING_EVALUATE_TEACHER = "/teacher/ui/course/EvaluateTeacherActivity"
             const val VIP_COURSE_SETTING = "/teacher/ui/course/VIPCourseSettingActivity"
             const val VIP_COURSE_GROUP_DETAIL = "/teacher/ui/course/VIPOrInterestCourseGroupDetailActivity"
+            const val PIANO_COURSE_GROUP_DETAIL = "/teacher/ui/course/PianoCourseGroupDetailActivity"
 
         }
     }

+ 6 - 0
teacher/src/main/AndroidManifest.xml

@@ -383,6 +383,12 @@
             android:windowSoftInputMode="adjustPan" />
 
         <activity
+            android:name=".ui.course.PianoCourseGroupDetailActivity"
+            android:configChanges="orientation|screenSize|keyboardHidden|fontScale|smallestScreenSize|screenLayout|uiMode"
+            android:screenOrientation="portrait"
+            android:windowSoftInputMode="adjustPan" />
+
+        <activity
             android:name="com.tencent.tauth.AuthActivity"
             android:launchMode="singleTask"
             android:noHistory="true">

+ 11 - 0
teacher/src/main/java/com/cooleshow/teacher/adapter/MineCoursePageAdapter.java

@@ -32,4 +32,15 @@ public class MineCoursePageAdapter extends FragmentStateAdapter {
     public int getItemCount() {
         return mFragments != null ? mFragments.size() : 0;
     }
+
+    @Override
+    public long getItemId(int position) {
+        Fragment fragment = mFragments.get(position);
+        return fragment != null ? fragment.hashCode() : super.getItemId(position);
+    }
+
+    @Override
+    public boolean containsItem(long itemId) {
+        return super.containsItem(itemId);
+    }
 }

+ 92 - 0
teacher/src/main/java/com/cooleshow/teacher/adapter/PianoCourseGroupCourseListAdapter.java

@@ -0,0 +1,92 @@
+package com.cooleshow.teacher.adapter;
+
+import android.text.TextUtils;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.chad.library.adapter.base.BaseQuickAdapter;
+import com.chad.library.adapter.base.viewholder.BaseViewHolder;
+import com.cooleshow.base.utils.GlideUtils;
+import com.cooleshow.base.utils.UiUtils;
+import com.cooleshow.teacher.R;
+import com.cooleshow.teacher.bean.PianoCourseGroupCourseListBean;
+import com.cooleshow.teacher.bean.VIPCourseGroupDetailListBean;
+import com.cooleshow.teacher.constants.CourseConstants;
+
+import java.util.ArrayList;
+
+import androidx.annotation.NonNull;
+
+/**
+ * Author by pq, Date on 2024/11/25.
+ */
+public class PianoCourseGroupCourseListAdapter extends BaseQuickAdapter<VIPCourseGroupDetailListBean, BaseViewHolder> {
+    public PianoCourseGroupCourseListAdapter() {
+        super(R.layout.item_piano_course_group_course_layout);
+        addChildClickViewIds(R.id.tv_go_start);
+    }
+
+    @Override
+    protected void convert(@NonNull BaseViewHolder holder, VIPCourseGroupDetailListBean data) {
+        //时间
+        holder.setText(R.id.tv_time, UiUtils.getCourseTimeString(data.getStartTime(), data.getEndTime()));
+
+        TextView tv_course_status = holder.getView(R.id.tv_course_status);
+
+        holder.setText(R.id.tv_title, data.getCourseGroupName());
+
+        ImageView iv_attendance_status = holder.getView(R.id.iv_attendance_status);
+
+        holder.setText(R.id.tv_name, getStudentNames(data.getCourseStudentVos()));
+
+        holder.setText(R.id.tv_course_name, data.getSubjectName());
+
+        TextView tv_go_start = holder.getView(R.id.tv_go_start);
+        if (TextUtils.equals(CourseConstants.COURSE_STATUS_NOT_START, data.getStatus())) {
+            //未开始
+            iv_attendance_status.setVisibility(View.GONE);
+            tv_go_start.setVisibility(View.GONE);
+            tv_course_status.setVisibility(View.VISIBLE);
+            tv_course_status.setText("未开始");
+            tv_course_status.setTextColor(getContext().getResources().getColor(com.cooleshow.base.R.color.color_ff802c));
+        }
+
+        if (TextUtils.equals(CourseConstants.COURSE_STATUS_ING, data.getStatus())) {
+            //进行中
+            iv_attendance_status.setVisibility(View.GONE);
+            tv_go_start.setVisibility(View.VISIBLE);
+            tv_course_status.setVisibility(View.GONE);
+            tv_course_status.setText("进行中");
+            tv_course_status.setTextColor(getContext().getResources().getColor(com.cooleshow.base.R.color.color_2dc7aa));
+        }
+
+        if (TextUtils.equals(CourseConstants.COURSE_STATUS_COMPLETE, data.getStatus())) {
+            //已结束
+            iv_attendance_status.setVisibility(View.VISIBLE);
+            tv_go_start.setVisibility(View.GONE);
+            tv_course_status.setVisibility(View.VISIBLE);
+            iv_attendance_status.setImageResource(data.isAttendanceStatus() ? R.drawable.icon_course_attendance_arrive : R.drawable.icon_course_attendance_truancy);
+            tv_course_status.setText("已结束");
+            tv_course_status.setTextColor(getContext().getResources().getColor(com.cooleshow.base.R.color.color_999999));
+        }
+    }
+
+    private String getStudentNames(ArrayList<VIPCourseGroupDetailListBean.CourseStudentVosBean> list) {
+        if (list == null || list.size() == 0) {
+            return "";
+        }
+        StringBuilder stringBuilder = new StringBuilder();
+        if (list.size() > 1) {
+            stringBuilder.append(list.get(0).getUserName())
+                    .append("、")
+                    .append(list.get(1).getUserName())
+                    .append("等")
+                    .append(list.size())
+                    .append("人");
+        } else {
+            stringBuilder.append(list.get(0).getUserName());
+        }
+        return stringBuilder.toString();
+    }
+}

+ 48 - 0
teacher/src/main/java/com/cooleshow/teacher/adapter/PianoCourseGroupStudentListAdapter.java

@@ -0,0 +1,48 @@
+package com.cooleshow.teacher.adapter;
+
+import android.graphics.Color;
+import android.view.View;
+import android.widget.ImageView;
+
+import com.chad.library.adapter.base.BaseQuickAdapter;
+import com.chad.library.adapter.base.viewholder.BaseViewHolder;
+import com.cooleshow.base.utils.GlideUtils;
+import com.cooleshow.teacher.R;
+import com.cooleshow.teacher.bean.PianoCourseGroupStudentListBean;
+
+import androidx.annotation.NonNull;
+
+/**
+ * Author by pq, Date on 2024/11/25.
+ */
+public class PianoCourseGroupStudentListAdapter extends BaseQuickAdapter<PianoCourseGroupStudentListBean, BaseViewHolder> {
+    public PianoCourseGroupStudentListAdapter() {
+        super(R.layout.item_piano_course_group_student_layout);
+        addChildClickViewIds(R.id.iv_go_chat);
+    }
+
+    @Override
+    protected void convert(@NonNull BaseViewHolder holder, PianoCourseGroupStudentListBean bean) {
+        ImageView iv_avatar = holder.getView(R.id.iv_avatar);
+        GlideUtils.INSTANCE.loadImage(getContext(), bean.getAvatar(), iv_avatar, R.drawable.icon_teacher_default_head);
+
+        holder.setText(R.id.tv_title, bean.getStudentName());
+        holder.setText(R.id.tv_course_name, bean.getSubjectName());
+
+        View csRoot = holder.getView(R.id.cs_root);
+        setBackGroupResources(csRoot, holder);
+    }
+
+    private void setBackGroupResources(View csRoot, BaseViewHolder holder) {
+        int pos = holder.getLayoutPosition();
+        if (pos == 0) {
+            csRoot.setBackgroundResource(com.cooleshow.base.R.drawable.bg_white_top_10dp);
+            return;
+        }
+        if (pos == getData().size() - 1) {
+            csRoot.setBackgroundResource(com.cooleshow.base.R.drawable.bg_white_bottom_10dp);
+            return;
+        }
+        csRoot.setBackgroundColor(Color.WHITE);
+    }
+}

+ 11 - 0
teacher/src/main/java/com/cooleshow/teacher/api/APIService.java

@@ -15,6 +15,7 @@ import com.cooleshow.teacher.bean.HomeMenuBean;
 import com.cooleshow.teacher.bean.LiveListBean;
 import com.cooleshow.teacher.bean.LivePlayBackDataBean;
 import com.cooleshow.base.bean.StudentPageListBean;
+import com.cooleshow.teacher.bean.PianoCourseGroupStudentListBean;
 import com.cooleshow.teacher.bean.SysParamConfigBean;
 import com.cooleshow.teacher.bean.TeacherPromoteIncomeBean;
 import com.cooleshow.teacher.bean.UnBindTenantDetailBean;
@@ -932,4 +933,14 @@ public interface APIService {
     @FormUrlEncoded
     @POST(TEACHER_GROUP + "courseGroup/updateCoursePlan")
     Observable<BaseResponse<Object>> updateCoursePlan(@FieldMap Map<String, String> map);
+
+    /**
+     *
+     *
+     * @param
+     * @return
+     */
+    @FormUrlEncoded
+    @POST(TEACHER_GROUP + "courseGroup/queryStudentByGroupId")
+    Observable<BaseResponse<ArrayList<PianoCourseGroupStudentListBean>>> getCourseGroupStudents(@FieldMap Map<String, String> map);
 }

+ 247 - 0
teacher/src/main/java/com/cooleshow/teacher/bean/PianoCourseGroupCourseListBean.java

@@ -0,0 +1,247 @@
+package com.cooleshow.teacher.bean;
+
+import java.util.ArrayList;
+
+/**
+ * Author by pq, Date on 2024/11/25.
+ */
+public class PianoCourseGroupCourseListBean {
+
+    private boolean attendanceStatus;
+    private String avatar;
+    private String classDate;
+    private String courseGoupId;
+    private String courseGroupName;
+    private String courseId;
+    private boolean delFlag;
+    private String endTime;
+    private String id;
+    private String imUserId;
+    private String realName;
+    private String signInTime;
+    private String startTime;
+    private String status;
+    private String studentReplied;
+    private String subjectId;
+    private String subjectName;
+    private String teacherReplied;
+    private String userId;
+    private String userName;
+    private ArrayList<VIPCourseGroupDetailListBean.CourseStudentVosBean> courseStudentVos;
+
+    public ArrayList<VIPCourseGroupDetailListBean.CourseStudentVosBean> getCourseStudentVos() {
+        return courseStudentVos;
+    }
+
+    public void setCourseStudentVos(ArrayList<VIPCourseGroupDetailListBean.CourseStudentVosBean> courseStudentVos) {
+        this.courseStudentVos = courseStudentVos;
+    }
+
+    public boolean isAttendanceStatus() {
+        return attendanceStatus;
+    }
+
+    public void setAttendanceStatus(boolean attendanceStatus) {
+        this.attendanceStatus = attendanceStatus;
+    }
+
+    public String getAvatar() {
+        return avatar;
+    }
+
+    public void setAvatar(String avatar) {
+        this.avatar = avatar;
+    }
+
+    public String getClassDate() {
+        return classDate;
+    }
+
+    public void setClassDate(String classDate) {
+        this.classDate = classDate;
+    }
+
+    public String getCourseGoupId() {
+        return courseGoupId;
+    }
+
+    public void setCourseGoupId(String courseGoupId) {
+        this.courseGoupId = courseGoupId;
+    }
+
+    public String getCourseGroupName() {
+        return courseGroupName;
+    }
+
+    public void setCourseGroupName(String courseGroupName) {
+        this.courseGroupName = courseGroupName;
+    }
+
+    public String getCourseId() {
+        return courseId;
+    }
+
+    public void setCourseId(String courseId) {
+        this.courseId = courseId;
+    }
+
+    public boolean isDelFlag() {
+        return delFlag;
+    }
+
+    public void setDelFlag(boolean delFlag) {
+        this.delFlag = delFlag;
+    }
+
+    public String getEndTime() {
+        return endTime;
+    }
+
+    public void setEndTime(String endTime) {
+        this.endTime = endTime;
+    }
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getImUserId() {
+        return imUserId;
+    }
+
+    public void setImUserId(String imUserId) {
+        this.imUserId = imUserId;
+    }
+
+    public String getRealName() {
+        return realName;
+    }
+
+    public void setRealName(String realName) {
+        this.realName = realName;
+    }
+
+    public String getSignInTime() {
+        return signInTime;
+    }
+
+    public void setSignInTime(String signInTime) {
+        this.signInTime = signInTime;
+    }
+
+    public String getStartTime() {
+        return startTime;
+    }
+
+    public void setStartTime(String startTime) {
+        this.startTime = startTime;
+    }
+
+    public String getStatus() {
+        return status;
+    }
+
+    public void setStatus(String status) {
+        this.status = status;
+    }
+
+    public String getStudentReplied() {
+        return studentReplied;
+    }
+
+    public void setStudentReplied(String studentReplied) {
+        this.studentReplied = studentReplied;
+    }
+
+    public String getSubjectId() {
+        return subjectId;
+    }
+
+    public void setSubjectId(String subjectId) {
+        this.subjectId = subjectId;
+    }
+
+    public String getSubjectName() {
+        return subjectName;
+    }
+
+    public void setSubjectName(String subjectName) {
+        this.subjectName = subjectName;
+    }
+
+    public String getTeacherReplied() {
+        return teacherReplied;
+    }
+
+    public void setTeacherReplied(String teacherReplied) {
+        this.teacherReplied = teacherReplied;
+    }
+
+    public String getUserId() {
+        return userId;
+    }
+
+    public void setUserId(String userId) {
+        this.userId = userId;
+    }
+
+    public String getUserName() {
+        return userName;
+    }
+
+    public void setUserName(String userName) {
+        this.userName = userName;
+    }
+
+
+    public static class CourseStudentVosBean{
+
+        /**
+         * avatar : https://oss.dayaedu.com/klx/user/android/2024-11/2250318_1732179712792.jpeg
+         * imUserId : CLX_2250318_STUDENT
+         * userId : 2250318
+         * userName : 游客哈哈哈哈哈哈哈哈哈哈
+         */
+
+        private String avatar;
+        private String imUserId;
+        private String userId;
+        private String userName;
+
+        public String getAvatar() {
+            return avatar;
+        }
+
+        public void setAvatar(String avatar) {
+            this.avatar = avatar;
+        }
+
+        public String getImUserId() {
+            return imUserId;
+        }
+
+        public void setImUserId(String imUserId) {
+            this.imUserId = imUserId;
+        }
+
+        public String getUserId() {
+            return userId;
+        }
+
+        public void setUserId(String userId) {
+            this.userId = userId;
+        }
+
+        public String getUserName() {
+            return userName;
+        }
+
+        public void setUserName(String userName) {
+            this.userName = userName;
+        }
+    }
+}

+ 99 - 0
teacher/src/main/java/com/cooleshow/teacher/bean/PianoCourseGroupStudentListBean.java

@@ -0,0 +1,99 @@
+package com.cooleshow.teacher.bean;
+
+/**
+ * Author by pq, Date on 2024/11/25.
+ */
+public class PianoCourseGroupStudentListBean {
+
+    /**
+     * avatar :
+     * lastEndClass : 0
+     * phone :
+     * realName :
+     * subjectName :
+     * userId :
+     * userName :
+     */
+
+    private String avatar;
+    private String lastEndClass;
+    private String phone;
+    private String realName;
+    private String subjectName;
+    private String userId;
+    private String userName;
+    private String imUserId;
+    private String studentName;
+
+    public String getStudentName() {
+        return studentName;
+    }
+
+    public void setStudentName(String studentName) {
+        this.studentName = studentName;
+    }
+
+    public String getImUserId() {
+        return imUserId;
+    }
+
+    public void setImUserId(String imUserId) {
+        this.imUserId = imUserId;
+    }
+
+    public String getAvatar() {
+        return avatar;
+    }
+
+    public void setAvatar(String avatar) {
+        this.avatar = avatar;
+    }
+
+    public String getLastEndClass() {
+        return lastEndClass;
+    }
+
+    public void setLastEndClass(String lastEndClass) {
+        this.lastEndClass = lastEndClass;
+    }
+
+    public String getPhone() {
+        return phone;
+    }
+
+    public void setPhone(String phone) {
+        this.phone = phone;
+    }
+
+    public String getRealName() {
+        return realName;
+    }
+
+    public void setRealName(String realName) {
+        this.realName = realName;
+    }
+
+    public String getSubjectName() {
+        return subjectName;
+    }
+
+    public void setSubjectName(String subjectName) {
+        this.subjectName = subjectName;
+    }
+
+    public String getUserId() {
+        return userId;
+    }
+
+    public void setUserId(String userId) {
+        this.userId = userId;
+    }
+
+    public String getUserName() {
+        return userName;
+    }
+
+    public void setUserName(String userName) {
+        this.userName = userName;
+    }
+}

+ 32 - 0
teacher/src/main/java/com/cooleshow/teacher/contract/PianoCourseGroupDetailContract.java

@@ -0,0 +1,32 @@
+package com.cooleshow.teacher.contract;
+
+import com.cooleshow.base.bean.CommonCourseConfigBean;
+import com.cooleshow.base.presenter.view.BaseView;
+import com.cooleshow.teacher.bean.PianoCourseGroupStudentListBean;
+import com.cooleshow.teacher.bean.VIPCourseGroupDetailBean;
+import com.cooleshow.teacher.bean.VIPCourseGroupDetailListBean;
+
+import java.util.ArrayList;
+
+/**
+ * Author by pq, Date on 2022/4/20.
+ */
+public interface PianoCourseGroupDetailContract {
+
+    interface View extends BaseView {
+        void getDetailSuccess(VIPCourseGroupDetailBean data);
+
+        void getCourseListSuccess(ArrayList<VIPCourseGroupDetailListBean> data);
+
+
+        void getCourseConfigSuccess(CommonCourseConfigBean data);
+
+        void updateCoursePlanSuccess();
+
+        void getGroupStudentSuccess(ArrayList<PianoCourseGroupStudentListBean> data);
+
+    }
+
+    interface Presenter {
+    }
+}

+ 123 - 0
teacher/src/main/java/com/cooleshow/teacher/presenter/course/PianoCourseGroupDetailPresenter.java

@@ -0,0 +1,123 @@
+package com.cooleshow.teacher.presenter.course;
+
+import android.text.TextUtils;
+
+import com.cooleshow.base.bean.CommonCourseConfigBean;
+import com.cooleshow.base.constanst.CourseAttendanceStatusType;
+import com.cooleshow.base.presenter.BasePresenter;
+import com.cooleshow.base.rx.BaseObserver;
+import com.cooleshow.base.utils.RequestBodyUtil;
+import com.cooleshow.teacher.api.APIService;
+import com.cooleshow.teacher.bean.PianoCourseGroupStudentListBean;
+import com.cooleshow.teacher.bean.VIPCourseGroupDetailBean;
+import com.cooleshow.teacher.bean.VIPCourseGroupDetailListBean;
+import com.cooleshow.teacher.contract.PianoCourseGroupDetailContract;
+import com.cooleshow.teacher.contract.VIPCourseGroupDetailContract;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+/**
+ * 陪练课presenter
+ * Author by pq, Date on 2022/4/20.
+ */
+public class PianoCourseGroupDetailPresenter extends BasePresenter<PianoCourseGroupDetailContract.View> implements PianoCourseGroupDetailContract.Presenter {
+
+    public void queryDetail(boolean isShowLoading, String courseGroupId) {
+        if (isShowLoading && getView() != null) {
+            getView().showLoading();
+        }
+        HashMap<String,String> hashMap =new HashMap();
+        hashMap.put("courseGroupId", courseGroupId);
+        addSubscribe(create(APIService.class).getCourseGroupDetail(hashMap), new BaseObserver<VIPCourseGroupDetailBean>(getView()) {
+            @Override
+            protected void onSuccess(VIPCourseGroupDetailBean data) {
+                if (getView() != null) {
+                    getView().getDetailSuccess(data);
+                }
+            }
+
+        });
+    }
+
+    public void queryCourseList(boolean isShowLoading, String courseGroupId, String classMonth, String status, String attendanceStatus) {
+        if (isShowLoading && getView() != null) {
+            getView().showLoading();
+        }
+        JSONObject jsonObject = new JSONObject();
+        try {
+            jsonObject.putOpt("courseGroupId", courseGroupId);
+            if (!TextUtils.isEmpty(classMonth)) {
+                jsonObject.putOpt("classMonth", classMonth);
+            }
+            if (!TextUtils.isEmpty(status)) {
+                jsonObject.putOpt("status", status);
+            }
+            if (!TextUtils.isEmpty(attendanceStatus)) {
+                boolean attendanceStatusFlag = false;
+                if(TextUtils.equals(attendanceStatus, CourseAttendanceStatusType.ARRIVE_FOR_CLASS.getId())){
+                    attendanceStatusFlag = true;
+                }
+                jsonObject.putOpt("attendanceStatus", attendanceStatusFlag);
+            }
+        } catch (JSONException e) {
+            e.printStackTrace();
+        }
+        addSubscribe(create(APIService.class).getCourseGroupCourseList(RequestBodyUtil.convertToRequestBodyJson(jsonObject.toString())), new BaseObserver<ArrayList<VIPCourseGroupDetailListBean>>(getView()) {
+            @Override
+            protected void onSuccess(ArrayList<VIPCourseGroupDetailListBean> data) {
+                if (getView() != null) {
+                    getView().getCourseListSuccess(data);
+                }
+            }
+
+        });
+    }
+
+    public void getCourseConfig() {
+        addSubscribe(create(APIService.class).getCourseConfig(), new BaseObserver<CommonCourseConfigBean>(getView()) {
+            @Override
+            protected void onSuccess(CommonCourseConfigBean data) {
+                if (getView() != null) {
+                    getView().getCourseConfigSuccess(data);
+                }
+            }
+        });
+    }
+
+    public void updateCoursePlan(String groupId, String coursePlan) {
+        if (getView() != null) {
+            getView().showLoading();
+        }
+        HashMap<String, String> map = new HashMap<>();
+        map.put("groupId", groupId);
+        map.put("coursePlan", coursePlan);
+        addSubscribe(create(APIService.class).updateCoursePlan(map), new BaseObserver<Object>(getView()) {
+            @Override
+            protected void onSuccess(Object data) {
+                if (getView() != null) {
+                    getView().updateCoursePlanSuccess();
+                }
+            }
+        });
+    }
+
+    public void getCourseGroupStudents(String groupId) {
+        if (getView() != null) {
+            getView().showLoading();
+        }
+        HashMap<String, String> map = new HashMap<>();
+        map.put("groupId", groupId);
+        addSubscribe(create(APIService.class).getCourseGroupStudents(map), new BaseObserver<ArrayList<PianoCourseGroupStudentListBean>>(getView()) {
+            @Override
+            protected void onSuccess(ArrayList<PianoCourseGroupStudentListBean> data) {
+                if (getView() != null) {
+                    getView().getGroupStudentSuccess(data);
+                }
+            }
+        });
+    }
+}

+ 338 - 0
teacher/src/main/java/com/cooleshow/teacher/ui/course/PianoCourseGroupDetailActivity.java

@@ -0,0 +1,338 @@
+package com.cooleshow.teacher.ui.course;
+
+import android.content.DialogInterface;
+import android.graphics.Color;
+import android.graphics.Typeface;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.TextView;
+
+import com.alibaba.android.arouter.facade.annotation.Route;
+import com.alibaba.android.arouter.launcher.ARouter;
+import com.bigkoo.pickerview.builder.TimePickerBuilder;
+import com.bigkoo.pickerview.listener.CustomListener;
+import com.bigkoo.pickerview.listener.OnDismissListener;
+import com.bigkoo.pickerview.view.TimePickerView;
+import com.chad.library.adapter.base.BaseQuickAdapter;
+import com.chad.library.adapter.base.listener.OnItemChildClickListener;
+import com.chad.library.adapter.base.listener.OnItemClickListener;
+import com.cooleshow.base.bean.CommonCourseConfigBean;
+import com.cooleshow.base.constanst.Constants;
+import com.cooleshow.base.constanst.CourseAttendanceStatusType;
+import com.cooleshow.base.constanst.CourseGroupStatusType;
+import com.cooleshow.base.interfaces.IFilterViewData;
+import com.cooleshow.base.router.RouterPath;
+import com.cooleshow.base.ui.activity.BaseMVPActivity;
+import com.cooleshow.base.utils.GlideUtils;
+import com.cooleshow.base.utils.TimeUtils;
+import com.cooleshow.base.utils.ToastUtil;
+import com.cooleshow.base.utils.UiUtils;
+import com.cooleshow.base.utils.helper.QMUIStatusBarHelper;
+import com.cooleshow.base.widgets.EmptyViewLayout;
+import com.cooleshow.base.widgets.dialog.CommonFilterDialog;
+import com.cooleshow.teacher.R;
+import com.cooleshow.teacher.adapter.MineCoursePageAdapter;
+import com.cooleshow.teacher.adapter.VIPCourseGroupDetailAdapter;
+import com.cooleshow.teacher.bean.PianoCourseGroupStudentListBean;
+import com.cooleshow.teacher.bean.VIPCourseGroupDetailBean;
+import com.cooleshow.teacher.bean.VIPCourseGroupDetailListBean;
+import com.cooleshow.teacher.constants.CourseConstants;
+import com.cooleshow.teacher.contract.PianoCourseGroupDetailContract;
+import com.cooleshow.teacher.contract.VIPCourseGroupDetailContract;
+import com.cooleshow.teacher.databinding.AcPianoCourseGroupDetailLayoutBinding;
+import com.cooleshow.teacher.databinding.AcVipOrInterestCourseGroupDetailLayoutBinding;
+import com.cooleshow.teacher.presenter.course.PianoCourseGroupDetailPresenter;
+import com.cooleshow.teacher.presenter.course.VIPOrInterestCourseGroupDetailPresenter;
+import com.cooleshow.teacher.widgets.AppBarLayoutStateChangeListener;
+import com.cooleshow.teacher.widgets.dialog.AddCourseGroupPlanDialog;
+import com.dayayuemeng.classroom.helper.OpenClassRoomHelper;
+import com.google.android.material.appbar.AppBarLayout;
+import com.google.android.material.tabs.TabLayout;
+import com.google.android.material.tabs.TabLayoutMediator;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
+import androidx.recyclerview.widget.LinearLayoutManager;
+
+/**
+ * Author by pq, Date on 2024/11/22.
+ */
+@Route(path = RouterPath.CourseCenter.PIANO_COURSE_GROUP_DETAIL)
+public class PianoCourseGroupDetailActivity extends BaseMVPActivity<AcPianoCourseGroupDetailLayoutBinding, PianoCourseGroupDetailPresenter> implements PianoCourseGroupDetailContract.View, View.OnClickListener {
+    private int titleStyleMode = 1;//根据折叠展开状态控制title样式
+    public static final int EXPAND_MODE = 1;
+    public static final int COLLAP_MODE = 2;
+    private AppBarLayoutStateChangeListener.State lastState = AppBarLayoutStateChangeListener.State.EXPANDED;
+    private String courseGroupId;
+    private CommonCourseConfigBean mConfigBean;
+    private VIPCourseGroupDetailBean mDetailBean;
+    private List<String> titles = new ArrayList<String>(Arrays.asList("课程列表", "上课学生"));
+    private PianoCourseGroupDetailStudentFragment mStudentFragment;
+    private PianoCourseGroupDetailFragment mCourseListFragment;
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        QMUIStatusBarHelper.setStatusBarLightMode(PianoCourseGroupDetailActivity.this);
+    }
+
+    @Override
+    protected void initView() {
+        initMidTitleToolBar(viewBinding.toolbarInclude.toolbar, "琴房课详情");
+        viewBinding.toolbarInclude.toolbar.setBackgroundColor(Color.TRANSPARENT);
+        viewBinding.appBarLayout.addOnOffsetChangedListener(new AppBarLayoutStateChangeListener() {
+
+            @Override
+            public void onStateChanged(AppBarLayout appBarLayout, State state) {
+                switch (state) {
+                    case EXPANDED:    //展开
+                        switchTitleStyle(EXPAND_MODE);
+                        break;
+                    case COLLAPSED:    //折叠
+                        switchTitleStyle(COLLAP_MODE);
+                        break;
+                    case INTERMEDIATE: //中间状态
+                        if (lastState == State.COLLAPSED) {
+                            switchTitleStyle(EXPAND_MODE);
+                        }
+                        break;
+                }
+                lastState = state;
+            }
+        });
+    }
+
+    @Override
+    public void initData() {
+        super.initData();
+        courseGroupId = getIntent().getStringExtra(CourseConstants.COURSE_GROUP_ID);
+        if (TextUtils.isEmpty(courseGroupId)) {
+            finish();
+            return;
+        }
+        initListener();
+        TabLayoutMediator tabLayoutMediator = new TabLayoutMediator(viewBinding.tablayout, viewBinding.viewPager, (tab, position) -> {
+            //这里需要根据position修改tab的样式和文字等
+            createTab(tab, titles.get(position));
+        });
+        mCourseListFragment = new PianoCourseGroupDetailFragment();
+        Bundle bundle = new Bundle();
+        bundle.putString(CourseConstants.COURSE_GROUP_ID, courseGroupId);
+        mCourseListFragment.setArguments(bundle);
+        mStudentFragment = new PianoCourseGroupDetailStudentFragment();
+        ArrayList<Fragment> mFragments = new ArrayList<>();
+        mFragments.add(mCourseListFragment);
+        mFragments.add(mStudentFragment);
+        MineCoursePageAdapter adapter = new MineCoursePageAdapter(this);
+        adapter.setFragments(mFragments);
+        viewBinding.viewPager.setAdapter(adapter);
+        viewBinding.viewPager.setOffscreenPageLimit(mFragments.size());
+        tabLayoutMediator.attach();
+    }
+
+
+    private void initListener() {
+        viewBinding.viewAddPlan.setOnClickListener(this);
+        viewBinding.tvEditPlan.setOnClickListener(this);
+        viewBinding.tablayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
+            @Override
+            public void onTabSelected(TabLayout.Tab tab) {
+                if (tab != null && tab.getCustomView() != null) {
+                    View customView = tab.getCustomView();
+                    TextView tv_text = customView.findViewById(com.cooleshow.chatmodule.R.id.tv_text);
+                    tv_text.setTextSize(16);
+                    tv_text.setTextColor(getResources().getColor(com.cooleshow.base.R.color.color_131415));
+                    tv_text.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));
+                }
+            }
+
+            @Override
+            public void onTabUnselected(TabLayout.Tab tab) {
+                if (tab != null && tab.getCustomView() != null) {
+                    View customView = tab.getCustomView();
+                    TextView tv_text = customView.findViewById(com.cooleshow.chatmodule.R.id.tv_text);
+                    tv_text.setTextSize(16);
+                    tv_text.setTextColor(getResources().getColor(com.cooleshow.base.R.color.color_80000000));
+                    tv_text.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));
+                }
+            }
+
+            @Override
+            public void onTabReselected(TabLayout.Tab tab) {
+
+            }
+        });
+    }
+
+    private TabLayout.Tab createTab(TabLayout.Tab tab, String text) {
+        View view = LayoutInflater.from(this).inflate(R.layout.view_mine_course_tab_layout, null);
+        TextView tv_text = view.findViewById(R.id.tv_text);
+        tv_text.setText(text);
+        tab.setCustomView(view);
+        return tab;
+    }
+
+
+    private void switchTitleStyle(int mode) {
+        if (titleStyleMode == mode) {
+            return;
+        }
+        titleStyleMode = mode;
+        mCourseListFragment.refreshTabBg(mode ==1);
+        if (mode == 1) {
+            viewBinding.collapsingToolbarLayout.setContentScrimColor(Color.TRANSPARENT);
+            viewBinding.collapsingToolbarLayout.setStatusBarScrimColor(Color.TRANSPARENT);
+            viewBinding.toolbarInclude.toolbar.setBackgroundColor(Color.TRANSPARENT);
+            viewBinding.flTab.setBackgroundColor(Color.TRANSPARENT);
+        } else {
+            viewBinding.collapsingToolbarLayout.setContentScrimColor(Color.WHITE);
+            viewBinding.collapsingToolbarLayout.setStatusBarScrimColor(Color.WHITE);
+            viewBinding.toolbarInclude.toolbar.setBackgroundColor(Color.WHITE);
+            viewBinding.flTab.setBackgroundColor(Color.WHITE);
+        }
+    }
+
+    @Override
+    protected AcPianoCourseGroupDetailLayoutBinding getLayoutView() {
+        return AcPianoCourseGroupDetailLayoutBinding.inflate(getLayoutInflater());
+    }
+
+    @Override
+    protected PianoCourseGroupDetailPresenter createPresenter() {
+        return new PianoCourseGroupDetailPresenter();
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        refresh();
+    }
+
+    private void refresh() {
+        presenter.queryDetail(true, courseGroupId);
+        presenter.getCourseGroupStudents(courseGroupId);
+    }
+
+
+    @Override
+    public void getDetailSuccess(VIPCourseGroupDetailBean bean) {
+        if (!checkActivityExist()) {
+            return;
+        }
+        this.mDetailBean = bean;
+
+        viewBinding.tvCourseGroupTitle.setText(bean.getCourseGroupName());
+        viewBinding.tvName.setText(bean.getStudentName());
+        viewBinding.tvCourseCompletedValue.setText(bean.getCompleteCourseNum());
+        viewBinding.tvCourseTotalValue.setText(bean.getCourseNum());
+        viewBinding.tvCourseName.setText(bean.getSubjectName());
+
+        TextView tv_status = viewBinding.tvStatus;
+        String status = bean.getStatus();
+        if (TextUtils.equals(status, CourseGroupStatusType.ING.getId())) {
+            //进行中
+            tv_status.setText(CourseGroupStatusType.ING.getValue());
+            tv_status.setTextColor(getResources().getColor(com.cooleshow.base.R.color.color_2dc7aa));
+        } else if (TextUtils.equals(status, CourseGroupStatusType.NOT_START.getId())) {
+            //未开始
+            tv_status.setText(CourseGroupStatusType.NOT_START.getValue());
+            tv_status.setTextColor(getResources().getColor(com.cooleshow.base.R.color.color_ff802c));
+        } else if (TextUtils.equals(status, CourseGroupStatusType.COMPLETE.getId())) {
+            //已结课
+            tv_status.setText(CourseGroupStatusType.COMPLETE.getValue());
+            tv_status.setTextColor(getResources().getColor(com.cooleshow.base.R.color.color_999999));
+        } else if (TextUtils.equals(status, CourseGroupStatusType.CANCEL.getId())) {
+            //已取消
+            tv_status.setText(CourseGroupStatusType.CANCEL.getValue());
+            tv_status.setTextColor(getResources().getColor(com.cooleshow.base.R.color.color_999999));
+        }
+
+        String coursePlan = bean.getCoursePlan();
+        boolean hasPlan = !TextUtils.isEmpty(coursePlan);
+        viewBinding.tvPlanContent.setText(coursePlan);
+        viewBinding.groupAddCoursePlan.setVisibility(hasPlan ? View.GONE : View.VISIBLE);
+        viewBinding.csCoursePlan.setVisibility(hasPlan ? View.VISIBLE : View.GONE);
+    }
+
+    @Override
+    public void getCourseListSuccess(ArrayList<VIPCourseGroupDetailListBean> data) {
+        if (!checkActivityExist()) {
+            return;
+        }
+    }
+
+    @Override
+    public void getCourseConfigSuccess(CommonCourseConfigBean data) {
+        if (!checkActivityExist()) {
+            return;
+        }
+        this.mConfigBean = data;
+    }
+
+    @Override
+    public void updateCoursePlanSuccess() {
+        if (!checkActivityExist()) {
+            return;
+        }
+        refresh();
+    }
+
+    @Override
+    public void getGroupStudentSuccess(ArrayList<PianoCourseGroupStudentListBean> data) {
+        if (!checkActivityExist()) {
+            return;
+        }
+        if (mStudentFragment != null) {
+            mStudentFragment.setData(data);
+        }
+    }
+
+    private void showAddPlanDialog(String content) {
+        if (UiUtils.isFastClick()) {
+            return;
+        }
+        AddCourseGroupPlanDialog courseGroupPlanDialog = new AddCourseGroupPlanDialog(this);
+        courseGroupPlanDialog.show();
+        courseGroupPlanDialog.setOnEventListener(new AddCourseGroupPlanDialog.OnEventListener() {
+            @Override
+            public void onResult(String content) {
+                courseGroupPlanDialog.dismiss();
+                presenter.updateCoursePlan(courseGroupId, content);
+            }
+        });
+        if (!TextUtils.isEmpty(content)) {
+            courseGroupPlanDialog.setContentText(content);
+        }
+    }
+
+    @Override
+    public void onClick(View v) {
+        int id = v.getId();
+        if (id == R.id.view_add_plan) {
+            showAddPlanDialog("");
+            return;
+        }
+        if (id == R.id.tv_edit_plan) {
+            if (mDetailBean != null) {
+                showAddPlanDialog(mDetailBean.getCoursePlan());
+            }
+            return;
+        }
+
+    }
+
+
+    private void showTimeSelectPicker() {
+    }
+
+
+}

+ 312 - 0
teacher/src/main/java/com/cooleshow/teacher/ui/course/PianoCourseGroupDetailFragment.java

@@ -0,0 +1,312 @@
+package com.cooleshow.teacher.ui.course;
+
+import android.content.DialogInterface;
+import android.graphics.Color;
+import android.text.TextUtils;
+import android.view.View;
+import android.widget.TextView;
+
+import com.bigkoo.pickerview.builder.TimePickerBuilder;
+import com.bigkoo.pickerview.listener.CustomListener;
+import com.bigkoo.pickerview.listener.OnDismissListener;
+import com.bigkoo.pickerview.view.TimePickerView;
+import com.chad.library.adapter.base.BaseQuickAdapter;
+import com.cooleshow.base.bean.CommonCourseConfigBean;
+import com.cooleshow.base.constanst.Constants;
+import com.cooleshow.base.constanst.CourseAttendanceStatusType;
+import com.cooleshow.base.constanst.CourseGroupStatusType;
+import com.cooleshow.base.interfaces.IFilterViewData;
+import com.cooleshow.base.ui.fragment.BaseFragment;
+import com.cooleshow.base.ui.fragment.BaseMVPFragment;
+import com.cooleshow.base.utils.TimeUtils;
+import com.cooleshow.base.utils.UiUtils;
+import com.cooleshow.base.widgets.EmptyViewLayout;
+import com.cooleshow.base.widgets.dialog.CommonFilterDialog;
+import com.cooleshow.teacher.R;
+import com.cooleshow.teacher.adapter.PianoCourseGroupCourseListAdapter;
+import com.cooleshow.teacher.adapter.VIPCourseGroupDetailAdapter;
+import com.cooleshow.teacher.bean.PianoCourseGroupStudentListBean;
+import com.cooleshow.teacher.bean.VIPCourseGroupDetailBean;
+import com.cooleshow.teacher.bean.VIPCourseGroupDetailListBean;
+import com.cooleshow.teacher.constants.CourseConstants;
+import com.cooleshow.teacher.contract.PianoCourseGroupDetailContract;
+import com.cooleshow.teacher.databinding.FgPianoCourseGroupDetailLayoutBinding;
+import com.cooleshow.teacher.presenter.course.PianoCourseGroupDetailPresenter;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+
+import androidx.recyclerview.widget.LinearLayoutManager;
+
+/**
+ * Author by pq, Date on 2024/11/25.
+ */
+public class PianoCourseGroupDetailFragment extends BaseMVPFragment<FgPianoCourseGroupDetailLayoutBinding, PianoCourseGroupDetailPresenter> implements PianoCourseGroupDetailContract.View, View.OnClickListener {
+
+    private PianoCourseGroupCourseListAdapter mAdapter;
+    private String courseGroupId;
+    private String classMonth;
+    private Date currentSelectDate;
+    private String courseStatus = CourseGroupStatusType.ALL.getId();
+    private String currentAttendanceStatus;
+    private TimePickerView pvTime;
+    private List<IFilterViewData> statusList;//状态筛选
+    private List<IFilterViewData> attendanceStatusList;//考勤状态筛选
+    private int currentSelectStatusPosition = 0;
+    private int currentSelectAttendancePosition = 0;
+    private CommonFilterDialog mAttendanceStatusFilterDialog;
+    private CommonFilterDialog mStatusFilterDialog;
+
+    @Override
+    protected FgPianoCourseGroupDetailLayoutBinding getLayoutView() {
+        return FgPianoCourseGroupDetailLayoutBinding.inflate(getLayoutInflater());
+    }
+
+    @Override
+    protected PianoCourseGroupDetailPresenter createPresenter() {
+        return new PianoCourseGroupDetailPresenter();
+    }
+
+    @Override
+    protected void initView(View rootView) {
+        if (getArguments() != null) {
+            courseGroupId = getArguments().getString(CourseConstants.COURSE_GROUP_ID);
+        }
+    }
+
+    @Override
+    protected void initData() {
+        initListener();
+        initFilterData();
+        EmptyViewLayout emptyViewLayout = new EmptyViewLayout(getContext());
+        emptyViewLayout.setContent(com.cooleshow.base.R.drawable.icon_empty_course, "暂无课程");
+        mAdapter = new PianoCourseGroupCourseListAdapter();
+        mAdapter.setEmptyView(emptyViewLayout);
+        mViewBinding.recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
+        mViewBinding.recyclerView.setAdapter(mAdapter);
+    }
+
+    private void initFilterData() {
+        CourseGroupStatusType[] values = CourseGroupStatusType.values();
+        List<CourseGroupStatusType> courseGroupStatusTypes = Arrays.asList(values);
+        statusList = new ArrayList<IFilterViewData>(courseGroupStatusTypes);
+
+        CourseAttendanceStatusType[] attendanceStatuValues = CourseAttendanceStatusType.values();
+        List<CourseAttendanceStatusType> attendanceStatus = Arrays.asList(attendanceStatuValues);
+        attendanceStatusList = new ArrayList<>(attendanceStatus);
+    }
+
+    private void initListener() {
+        mViewBinding.flTime.setOnClickListener(this);
+        mViewBinding.flStatus.setOnClickListener(this);
+        mViewBinding.flAttendance.setOnClickListener(this);
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        refresh();
+    }
+
+    public void refreshTabBg(boolean isExpandMode) {
+        mViewBinding.viewTabBg.setBackgroundColor(isExpandMode ? Color.TRANSPARENT : Color.WHITE);
+    }
+
+    private void refresh() {
+        presenter.getCourseConfig();
+        reBuildFilter(currentSelectDate, courseStatus, currentAttendanceStatus);
+    }
+
+    private void reBuildFilter(Date date, String status, String attendanceStatus) {
+        currentSelectDate = date != null ? date : TimeUtils.getNowDate();
+        String targetDateTimeStr = TimeUtils.date2String(currentSelectDate, TimeUtils.getSafeDateFormat("yyyy-MM"));
+        classMonth = targetDateTimeStr;
+        courseStatus = !TextUtils.isEmpty(status) ? status : CourseGroupStatusType.ALL.getId();
+        currentAttendanceStatus = !TextUtils.isEmpty(attendanceStatus) ? attendanceStatus : CourseAttendanceStatusType.ALL.getId();
+        if (mViewBinding != null) {
+            mViewBinding.tvTime.setText(classMonth);
+        }
+        refreshCourseList(false);
+    }
+
+    private void refreshCourseList(boolean isShowLoading) {
+        if (TextUtils.isEmpty(courseGroupId)) {
+            return;
+        }
+        presenter.queryCourseList(isShowLoading, courseGroupId, classMonth, courseStatus, currentAttendanceStatus);
+    }
+
+    @Override
+    public void getDetailSuccess(VIPCourseGroupDetailBean data) {
+        //do nothing
+    }
+
+    @Override
+    public void getCourseListSuccess(ArrayList<VIPCourseGroupDetailListBean> data) {
+        if (isDetached()) {
+            return;
+        }
+        if (mAdapter != null) {
+            mAdapter.setList(data);
+        }
+    }
+
+    @Override
+    public void getCourseConfigSuccess(CommonCourseConfigBean data) {
+
+    }
+
+    @Override
+    public void updateCoursePlanSuccess() {
+        //do nothing
+    }
+
+    @Override
+    public void getGroupStudentSuccess(ArrayList<PianoCourseGroupStudentListBean> data) {
+        //do nothing
+    }
+
+    @Override
+    public void onClick(View v) {
+        int id = v.getId();
+        if (id == R.id.fl_time) {
+            showTimeSelectPicker();
+            return;
+        }
+        if (id == R.id.fl_status) {
+            selectCourseStatus();
+            return;
+        }
+
+        if (id == R.id.fl_attendance) {
+            selectAttendanceStatus();
+            return;
+        }
+    }
+
+    private void showTimeSelectPicker() {
+        if (pvTime == null) {
+            pvTime = new TimePickerBuilder(getContext(), (date, v) -> {//选中事件回调
+                reBuildFilter(date, courseStatus, currentAttendanceStatus);
+            }).setLayoutRes(com.cooleshow.base.R.layout.pickerview_default_layout, new CustomListener() {
+                        @Override
+                        public void customLayout(View v) {
+                            //自定义布局中的控件初始化及事件处理
+                            final TextView tvSubmit = (TextView) v.findViewById(com.cooleshow.base.R.id.tv_finish);
+                            TextView ivCancel = (TextView) v.findViewById(com.cooleshow.base.R.id.tv_cancel);
+                            tvSubmit.setOnClickListener(new View.OnClickListener() {
+                                @Override
+                                public void onClick(View v) {
+                                    pvTime.returnData();
+                                    pvTime.dismiss();
+                                }
+                            });
+                            ivCancel.setOnClickListener(new View.OnClickListener() {
+                                @Override
+                                public void onClick(View v) {
+                                    pvTime.dismiss();
+                                }
+                            });
+
+                        }
+                    })
+                    .setTextColorOut(getResources().getColor(com.cooleshow.base.R.color.color_aaaaaa))
+                    .setDividerColor(Color.TRANSPARENT)
+                    .setBgColor(Color.TRANSPARENT)
+                    .setLineSpacingMultiplier(2.5f)
+                    .setType(new boolean[]{true, true, false, false, false, false})// 默认全部显示
+                    .setTextColorCenter(getResources().getColor(com.cooleshow.base.R.color.color_1a1a1a))//设置选中项的颜色
+                    .isDialog(false)//是否显示为对话框样式
+                    .setLabel("年", "月", "", "", "", "")
+                    .build();
+
+            pvTime.setOnDismissListener(new OnDismissListener() {
+                @Override
+                public void onDismiss(Object o) {
+                    UiUtils.refreshFilterTextStyle2(false, mViewBinding.tvTime);
+                }
+
+                @Override
+                public void onShow() {
+                    UiUtils.refreshFilterTextStyle2(true, mViewBinding.tvTime);
+                }
+            });
+        }
+        Calendar calendar = Calendar.getInstance();
+        if (currentSelectDate == null) {
+            currentSelectDate = TimeUtils.getNowDate();
+        }
+        calendar.setTime(currentSelectDate);
+        pvTime.setDate(calendar);
+        if (!pvTime.isShowing()) {
+            pvTime.show();
+        }
+    }
+
+    private void selectCourseStatus() {
+        if (mStatusFilterDialog == null) {
+            mStatusFilterDialog = new CommonFilterDialog<IFilterViewData>(getContext());
+            mStatusFilterDialog.setOnEventListener(new CommonFilterDialog.OnEventListener() {
+                @Override
+                public void onItemClickListener(BaseQuickAdapter baseQuickAdapter, int pos) {
+                    if (statusList != null && pos < statusList.size()) {
+                        PianoCourseGroupDetailFragment.this.currentSelectStatusPosition = pos;
+                        IFilterViewData iFilterViewData = statusList.get(pos);
+                        courseStatus = iFilterViewData.getDataId();
+                        mViewBinding.tvCourseStatus.setText(!TextUtils.isEmpty(courseStatus) ? iFilterViewData.getShowName() : "全部状态");
+                        reBuildFilter(currentSelectDate, courseStatus, currentAttendanceStatus);
+                    }
+                }
+            });
+
+            mStatusFilterDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
+                @Override
+                public void onDismiss(DialogInterface dialog) {
+                    UiUtils.refreshFilterTextStyle(false, mViewBinding.tvCourseStatus);
+                }
+            });
+        }
+        if (!mStatusFilterDialog.isShowing()) {
+            mStatusFilterDialog.show();
+            UiUtils.refreshFilterTextStyle(true, mViewBinding.tvCourseStatus);
+        }
+        mStatusFilterDialog.setSelectPos(currentSelectStatusPosition);
+        mStatusFilterDialog.setData(statusList);
+
+    }
+
+
+    private void selectAttendanceStatus() {
+        if (mAttendanceStatusFilterDialog == null) {
+            mAttendanceStatusFilterDialog = new CommonFilterDialog<IFilterViewData>(getContext());
+            mAttendanceStatusFilterDialog.setOnEventListener(new CommonFilterDialog.OnEventListener() {
+                @Override
+                public void onItemClickListener(BaseQuickAdapter baseQuickAdapter, int pos) {
+                    if (attendanceStatusList != null && pos < attendanceStatusList.size()) {
+                        PianoCourseGroupDetailFragment.this.currentSelectAttendancePosition = pos;
+                        IFilterViewData iFilterViewData = attendanceStatusList.get(pos);
+                        currentAttendanceStatus = iFilterViewData.getDataId();
+                        mViewBinding.tvAttendanceStatus.setText(iFilterViewData.getShowName());
+                        reBuildFilter(currentSelectDate, courseStatus, currentAttendanceStatus);
+                    }
+                }
+            });
+
+            mAttendanceStatusFilterDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
+                @Override
+                public void onDismiss(DialogInterface dialog) {
+                    UiUtils.refreshFilterTextStyle(false, mViewBinding.tvAttendanceStatus);
+                }
+            });
+        }
+        if (!mAttendanceStatusFilterDialog.isShowing()) {
+            mAttendanceStatusFilterDialog.show();
+            UiUtils.refreshFilterTextStyle(true, mViewBinding.tvAttendanceStatus);
+        }
+        mAttendanceStatusFilterDialog.setSelectPos(currentSelectAttendancePosition);
+        mAttendanceStatusFilterDialog.setData(attendanceStatusList);
+    }
+}

+ 69 - 0
teacher/src/main/java/com/cooleshow/teacher/ui/course/PianoCourseGroupDetailStudentFragment.java

@@ -0,0 +1,69 @@
+package com.cooleshow.teacher.ui.course;
+
+import android.view.View;
+
+import com.chad.library.adapter.base.BaseQuickAdapter;
+import com.chad.library.adapter.base.listener.OnItemChildClickListener;
+import com.cooleshow.base.ui.fragment.BaseFragment;
+import com.cooleshow.base.widgets.EmptyViewLayout;
+import com.cooleshow.chatmodule.utils.helper.ChatHelper;
+import com.cooleshow.teacher.R;
+import com.cooleshow.teacher.adapter.PianoCourseGroupStudentListAdapter;
+import com.cooleshow.teacher.bean.PianoCourseGroupStudentListBean;
+import com.cooleshow.teacher.databinding.FgPianoCourseGroupDetailLayoutBinding;
+import com.cooleshow.teacher.databinding.FgPianoCourseGroupDetailStudentListLayoutBinding;
+
+import java.util.List;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.LinearLayoutManager;
+
+/**
+ * Author by pq, Date on 2024/11/25.
+ */
+public class PianoCourseGroupDetailStudentFragment extends BaseFragment<FgPianoCourseGroupDetailStudentListLayoutBinding> {
+
+    private PianoCourseGroupStudentListAdapter mAdapter;
+
+    @Override
+    protected FgPianoCourseGroupDetailStudentListLayoutBinding getLayoutView() {
+        return FgPianoCourseGroupDetailStudentListLayoutBinding.inflate(getLayoutInflater());
+    }
+
+    @Override
+    protected void initView(View rootView) {
+
+    }
+
+    @Override
+    protected void initData() {
+        mAdapter = new PianoCourseGroupStudentListAdapter();
+        EmptyViewLayout emptyViewLayout = new EmptyViewLayout(getContext());
+        emptyViewLayout.setContent(R.drawable.icon_empty_content, "暂无学员");
+        mAdapter.setEmptyView(emptyViewLayout);
+        mViewBinding.recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
+        mViewBinding.recyclerView.setAdapter(mAdapter);
+    }
+
+    private void initListener() {
+        mAdapter.setOnItemChildClickListener(new OnItemChildClickListener() {
+            @Override
+            public void onItemChildClick(@NonNull BaseQuickAdapter<?, ?> adapter, @NonNull View view, int position) {
+                int id = view.getId();
+                if (id == R.id.iv_go_chat) {
+                    if (position < mAdapter.getData().size()) {
+                        PianoCourseGroupStudentListBean pianoCourseGroupStudentListBean = mAdapter.getData().get(position);
+                        ChatHelper.getInstance().goChat(pianoCourseGroupStudentListBean.getImUserId(), pianoCourseGroupStudentListBean.getStudentName());
+                    }
+                    return;
+                }
+            }
+        });
+    }
+
+    public void setData(List<PianoCourseGroupStudentListBean> data) {
+        if (mAdapter != null) {
+            mAdapter.setList(data);
+        }
+    }
+}

+ 9 - 0
teacher/src/main/java/com/cooleshow/teacher/ui/course/PianoCourseGroupFragment.java

@@ -4,11 +4,13 @@ import android.view.View;
 import android.view.ViewGroup;
 import android.widget.PopupWindow;
 
+import com.alibaba.android.arouter.launcher.ARouter;
 import com.chad.library.adapter.base.BaseQuickAdapter;
 import com.chad.library.adapter.base.listener.OnItemClickListener;
 import com.cooleshow.base.constanst.Constants;
 import com.cooleshow.base.constanst.CourseGroupStatusType;
 import com.cooleshow.base.interfaces.IFilterViewData;
+import com.cooleshow.base.router.RouterPath;
 import com.cooleshow.base.ui.fragment.BaseMVPFragment;
 import com.cooleshow.base.utils.LOG;
 import com.cooleshow.base.utils.PopupUtil;
@@ -20,6 +22,7 @@ import com.cooleshow.teacher.adapter.PianoCourseGroupAdapter;
 import com.cooleshow.teacher.adapter.VIPCourseAdapter;
 import com.cooleshow.teacher.bean.QuerySubjectBean;
 import com.cooleshow.teacher.bean.VIPCourseGroupListBean;
+import com.cooleshow.teacher.constants.CourseConstants;
 import com.cooleshow.teacher.contract.InterestCourseGroupContract;
 import com.cooleshow.teacher.contract.PianoCourseGroupContract;
 import com.cooleshow.teacher.databinding.FgInterestCourseLayoutBinding;
@@ -105,6 +108,12 @@ public class PianoCourseGroupFragment extends BaseMVPFragment<FgPianoCourseGroup
             @Override
             public void onItemClick(@NonNull BaseQuickAdapter<?, ?> adapter, @NonNull View view, int position) {
                 //课程详情页
+                if (position < mAdapter.getData().size()) {
+                    VIPCourseGroupListBean.RowsBean rowsBean = mAdapter.getData().get(position);
+                    ARouter.getInstance().build(RouterPath.CourseCenter.PIANO_COURSE_GROUP_DETAIL)
+                            .withString(CourseConstants.COURSE_GROUP_ID, rowsBean.getCourseGroupId())
+                            .navigation();
+                }
             }
         });
     }

+ 339 - 0
teacher/src/main/res/layout/ac_piano_course_group_detail_layout.xml

@@ -0,0 +1,339 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <ImageView
+        android:id="@+id/iv_top_bg"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:adjustViewBounds="true"
+        android:src="@drawable/bg_course_group_detail_top"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <include
+        android:id="@+id/toolbar_include"
+        layout="@layout/common_toolbar_layout" />
+
+    <androidx.coordinatorlayout.widget.CoordinatorLayout
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:fitsSystemWindows="true"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintTop_toBottomOf="@+id/toolbar_include">
+
+        <com.google.android.material.appbar.AppBarLayout
+            android:id="@+id/app_bar_layout"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:background="@color/transparent"
+            android:fitsSystemWindows="true"
+            android:theme="@style/AppTheme.AppBarOverlay">
+
+            <com.google.android.material.appbar.CollapsingToolbarLayout
+                android:id="@+id/collapsing_toolbar_layout"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:fitsSystemWindows="true"
+                android:paddingBottom="0dp"
+                app:contentScrim="@color/transparent"
+                app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
+                app:scrimAnimationDuration="10"
+                app:statusBarScrim="@color/transparent"
+                app:titleEnabled="false">
+
+                <androidx.constraintlayout.widget.ConstraintLayout
+                    android:layout_width="match_parent"
+                    android:layout_height="match_parent"
+                    android:layout_marginTop="12dp"
+                    android:paddingStart="14dp"
+                    android:paddingEnd="14dp"
+                    app:layout_collapseMode="none">
+
+                    <androidx.constraintlayout.widget.ConstraintLayout
+                        android:id="@+id/cs_header"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:background="@drawable/bg_white_10dp"
+                        android:padding="12dp"
+                        app:layout_constraintLeft_toLeftOf="parent"
+                        app:layout_constraintTop_toTopOf="parent">
+
+                        <TextView
+                            android:id="@+id/tv_course_group_title"
+                            android:layout_width="0dp"
+                            android:layout_height="wrap_content"
+                            android:ellipsize="end"
+                            android:maxLines="1"
+                            android:textColor="@color/color_131415"
+                            android:textSize="@dimen/sp_16"
+                            android:textStyle="bold"
+                            app:layout_constraintLeft_toLeftOf="parent"
+                            app:layout_constraintRight_toLeftOf="@+id/tv_status"
+                            app:layout_constraintTop_toTopOf="parent"
+                            tools:text="VIP定制课-张涵宇" />
+
+                        <TextView
+                            android:id="@+id/tv_status"
+                            android:layout_width="wrap_content"
+                            android:layout_height="wrap_content"
+                            android:includeFontPadding="false"
+                            android:textColor="@color/color_999999"
+                            android:textSize="@dimen/sp_14"
+                            app:layout_constraintBottom_toBottomOf="@+id/tv_course_group_title"
+                            app:layout_constraintRight_toRightOf="parent"
+                            app:layout_constraintTop_toTopOf="@+id/tv_course_group_title"
+                            tools:text="已结课" />
+
+                        <ImageView
+                            android:id="@+id/iv_avatar"
+                            android:layout_width="40dp"
+                            android:layout_height="40dp"
+                            android:layout_marginTop="8dp"
+                            android:src="@drawable/icon_piano_room_course"
+                            app:layout_constraintLeft_toLeftOf="parent"
+                            app:layout_constraintTop_toBottomOf="@+id/tv_course_group_title" />
+
+                        <TextView
+                            android:id="@+id/tv_name"
+                            android:layout_width="0dp"
+                            android:layout_height="wrap_content"
+                            android:layout_marginStart="10dp"
+                            android:layout_marginEnd="5dp"
+                            android:ellipsize="end"
+                            android:includeFontPadding="false"
+                            android:maxLines="1"
+                            android:textColor="@color/color_333333"
+                            android:textSize="@dimen/sp_13"
+                            app:layout_constraintBottom_toTopOf="@+id/tv_course_completed_title"
+                            app:layout_constraintHorizontal_bias="0"
+                            app:layout_constraintHorizontal_chainStyle="packed"
+                            app:layout_constraintLeft_toRightOf="@+id/iv_avatar"
+                            app:layout_constraintRight_toLeftOf="@+id/tv_course_name"
+                            app:layout_constraintTop_toTopOf="@+id/iv_avatar"
+                            app:layout_constraintVertical_chainStyle="packed"
+                            app:layout_constraintWidth_default="wrap"
+                            tools:text="张涵宇" />
+
+
+                        <TextView
+                            android:id="@+id/tv_course_name"
+                            android:layout_width="wrap_content"
+                            android:layout_height="wrap_content"
+                            android:layout_marginStart="5dp"
+                            android:background="@drawable/shape_couse_type_text_bg"
+                            android:gravity="center"
+                            android:includeFontPadding="false"
+                            android:paddingStart="4dp"
+                            android:paddingTop="2dp"
+                            android:paddingEnd="4dp"
+                            android:paddingBottom="2dp"
+                            android:textColor="@color/color_ff8c00"
+                            android:textSize="@dimen/sp_10"
+                            app:layout_constraintBottom_toBottomOf="@+id/tv_name"
+                            app:layout_constraintLeft_toRightOf="@+id/tv_name"
+                            app:layout_constraintRight_toRightOf="parent"
+                            app:layout_constraintTop_toTopOf="@+id/tv_name"
+                            tools:text="单簧管" />
+
+                        <ImageView
+                            android:id="@+id/iv_course_tag"
+                            android:layout_width="wrap_content"
+                            android:layout_height="wrap_content"
+                            android:src="@drawable/icon_course_completed_tag"
+                            app:layout_constraintBottom_toBottomOf="@+id/tv_course_completed_title"
+                            app:layout_constraintLeft_toLeftOf="@+id/tv_name"
+                            app:layout_constraintTop_toTopOf="@+id/tv_course_completed_title" />
+
+                        <TextView
+                            android:id="@+id/tv_course_completed_title"
+                            android:layout_width="wrap_content"
+                            android:layout_height="wrap_content"
+                            android:layout_marginStart="4dp"
+                            android:layout_marginTop="6dp"
+                            android:includeFontPadding="false"
+                            android:text="已上课时"
+                            android:textColor="@color/color_999999"
+                            android:textSize="@dimen/sp_12"
+                            app:layout_constraintBottom_toBottomOf="@+id/iv_avatar"
+                            app:layout_constraintLeft_toRightOf="@+id/iv_course_tag"
+                            app:layout_constraintTop_toBottomOf="@+id/tv_name" />
+
+
+                        <TextView
+                            android:id="@+id/tv_course_completed_value"
+                            android:layout_width="wrap_content"
+                            android:layout_height="wrap_content"
+                            android:includeFontPadding="false"
+                            android:paddingStart="3dp"
+                            android:paddingEnd="3dp"
+                            android:text="0"
+                            android:textColor="@color/color_2dc7aa"
+                            android:textSize="@dimen/sp_12"
+                            android:textStyle="bold"
+                            app:layout_constraintBaseline_toBaselineOf="@+id/tv_course_completed_title"
+                            app:layout_constraintLeft_toRightOf="@+id/tv_course_completed_title" />
+
+                        <TextView
+                            android:id="@+id/tv_course_total_title"
+                            android:layout_width="wrap_content"
+                            android:layout_height="wrap_content"
+                            android:includeFontPadding="false"
+                            android:text="/总课时"
+                            android:textColor="@color/color_999999"
+                            android:textSize="@dimen/sp_12"
+                            app:layout_constraintBaseline_toBaselineOf="@+id/tv_course_completed_value"
+                            app:layout_constraintLeft_toRightOf="@+id/tv_course_completed_value" />
+
+
+                        <TextView
+                            android:id="@+id/tv_course_total_value"
+                            android:layout_width="wrap_content"
+                            android:layout_height="wrap_content"
+                            android:includeFontPadding="false"
+                            android:paddingStart="3dp"
+                            android:paddingEnd="3dp"
+                            android:text="0"
+                            android:textColor="@color/color_333333"
+                            android:textSize="@dimen/sp_12"
+                            android:textStyle="bold"
+                            app:layout_constraintBaseline_toBaselineOf="@+id/tv_course_total_title"
+                            app:layout_constraintLeft_toRightOf="@+id/tv_course_total_title" />
+
+                        <View
+                            android:id="@+id/view_add_plan"
+                            android:layout_width="match_parent"
+                            android:layout_height="36dp"
+                            android:layout_marginTop="24dp"
+                            android:background="@drawable/shape_add_course_plan_bg"
+                            app:layout_constraintLeft_toLeftOf="parent"
+                            app:layout_constraintRight_toRightOf="parent"
+                            app:layout_constraintTop_toBottomOf="@+id/iv_avatar" />
+
+                        <TextView
+                            android:id="@+id/tv_add_course_plan"
+                            android:layout_width="wrap_content"
+                            android:layout_height="wrap_content"
+                            android:drawableStart="@drawable/icon_add_course_group_plan_tag"
+                            android:drawablePadding="2dp"
+                            android:gravity="center"
+                            android:includeFontPadding="false"
+                            android:text="添加课程规划"
+                            android:textColor="@color/color_333333"
+                            android:textSize="@dimen/sp_15"
+                            app:layout_constraintBottom_toBottomOf="@+id/view_add_plan"
+                            app:layout_constraintLeft_toLeftOf="@+id/view_add_plan"
+                            app:layout_constraintRight_toRightOf="@+id/view_add_plan"
+                            app:layout_constraintTop_toTopOf="@+id/view_add_plan" />
+
+                        <androidx.constraintlayout.widget.Group
+                            android:id="@+id/group_add_course_plan"
+                            android:layout_width="wrap_content"
+                            android:layout_height="wrap_content"
+                            android:visibility="gone"
+                            app:constraint_referenced_ids="view_add_plan,tv_add_course_plan" />
+                    </androidx.constraintlayout.widget.ConstraintLayout>
+
+                    <androidx.constraintlayout.widget.ConstraintLayout
+                        android:id="@+id/cs_course_plan"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:layout_marginTop="12dp"
+                        android:background="@drawable/bg_white_10dp"
+                        android:padding="12dp"
+                        android:visibility="gone"
+                        app:layout_constraintLeft_toLeftOf="parent"
+                        app:layout_constraintTop_toBottomOf="@+id/cs_header">
+
+                        <TextView
+                            android:id="@+id/tv_plan_title"
+                            android:layout_width="wrap_content"
+                            android:layout_height="wrap_content"
+                            android:drawableStart="@drawable/icon_course_group_plan_tag"
+                            android:drawablePadding="6dp"
+                            android:gravity="center"
+                            android:includeFontPadding="false"
+                            android:text="课程规划"
+                            android:textColor="@color/color_333333"
+                            android:textSize="@dimen/sp_15"
+                            app:layout_constraintLeft_toLeftOf="parent"
+                            app:layout_constraintTop_toTopOf="parent" />
+
+                        <TextView
+                            android:id="@+id/tv_edit_plan"
+                            android:layout_width="wrap_content"
+                            android:layout_height="wrap_content"
+                            android:drawableStart="@drawable/icon_course_group_edit_plan"
+                            android:drawablePadding="2dp"
+                            android:gravity="center"
+                            android:includeFontPadding="false"
+                            android:text="修改"
+                            android:textColor="@color/color_777777"
+                            android:textSize="@dimen/sp_13"
+                            app:layout_constraintRight_toRightOf="parent"
+                            app:layout_constraintTop_toTopOf="@+id/tv_plan_title" />
+
+                        <TextView
+                            android:id="@+id/tv_plan_content"
+                            android:layout_width="0dp"
+                            android:layout_height="wrap_content"
+                            android:layout_marginTop="12dp"
+                            android:ellipsize="end"
+                            android:includeFontPadding="false"
+                            android:maxLines="4"
+                            android:textColor="@color/color_777777"
+                            android:textSize="@dimen/sp_13"
+                            app:layout_constraintLeft_toLeftOf="parent"
+                            app:layout_constraintRight_toRightOf="parent"
+                            app:layout_constraintTop_toBottomOf="@+id/tv_plan_title"
+                            tools:text="中国院长笛四级考级曲目教学中国院长笛四级考级曲目" />
+
+                    </androidx.constraintlayout.widget.ConstraintLayout>
+                </androidx.constraintlayout.widget.ConstraintLayout>
+            </com.google.android.material.appbar.CollapsingToolbarLayout>
+
+            <FrameLayout
+                android:id="@+id/fl_tab"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content">
+
+                <com.google.android.material.tabs.TabLayout
+                    android:id="@+id/tablayout"
+                    android:layout_width="wrap_content"
+                    android:layout_height="@dimen/dp_44"
+                    android:layout_gravity="center_horizontal"
+                    android:scrollbars="none"
+                    app:layout_constraintLeft_toLeftOf="parent"
+                    app:layout_constraintRight_toRightOf="parent"
+                    app:layout_constraintTop_toBottomOf="@+id/toolbar_include"
+                    app:tabBackground="@null"
+                    app:tabGravity="fill"
+                    app:tabIndicator="@drawable/tab_indicator"
+                    app:tabIndicatorColor="@color/color_2dc7aa"
+                    app:tabIndicatorFullWidth="false"
+                    app:tabIndicatorHeight="4dp"
+                    app:tabMode="scrollable"
+                    app:tabPaddingEnd="0dp"
+                    app:tabPaddingStart="0dp"
+                    app:tabRippleColor="@null"
+                    app:tabSelectedTextColor="@color/black_333"
+                    app:tabTextAppearance="@style/tab_layout_style"
+                    app:tabTextColor="@color/color_666666" />
+            </FrameLayout>
+        </com.google.android.material.appbar.AppBarLayout>
+
+        <androidx.viewpager2.widget.ViewPager2
+            android:id="@+id/view_pager"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:overScrollMode="never"
+            android:scrollbars="none"
+            app:layout_behavior="@string/appbar_scrolling_view_behavior"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintTop_toBottomOf="@+id/tab_layout" />
+
+    </androidx.coordinatorlayout.widget.CoordinatorLayout>
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 118 - 0
teacher/src/main/res/layout/fg_piano_course_group_detail_layout.xml

@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <View
+        android:id="@+id/view_tab_bg"
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        app:layout_constraintBottom_toTopOf="@+id/recyclerView"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <LinearLayout
+        android:id="@+id/ll_filter"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="21dp"
+        android:layout_marginTop="12dp"
+        android:layout_marginEnd="21dp"
+        android:orientation="horizontal"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintTop_toTopOf="parent">
+
+        <FrameLayout
+            android:id="@+id/fl_time"
+            android:layout_width="0dp"
+            android:layout_height="22dp"
+            android:layout_marginEnd="11dp"
+            android:layout_weight="0.4"
+            android:background="@drawable/bg_white_10dp">
+
+            <TextView
+                android:id="@+id/tv_time"
+                android:layout_width="wrap_content"
+                android:layout_height="match_parent"
+                android:layout_gravity="center"
+                android:drawableRight="@drawable/icon_arrow_down"
+                android:drawablePadding="4dp"
+                android:ellipsize="end"
+                android:gravity="center"
+                android:includeFontPadding="false"
+                android:maxLines="1"
+                android:text="@string/all_attendance_str"
+                android:textColor="@color/color_131415"
+                android:textSize="@dimen/sp_14"
+                tools:text="2024年10月" />
+        </FrameLayout>
+
+        <FrameLayout
+            android:id="@+id/fl_status"
+            android:layout_width="0dp"
+            android:layout_height="22dp"
+            android:layout_marginEnd="11dp"
+            android:layout_weight="0.3"
+            android:background="@drawable/bg_white_10dp">
+
+            <TextView
+                android:id="@+id/tv_course_status"
+                android:layout_width="wrap_content"
+                android:layout_height="match_parent"
+                android:layout_gravity="center"
+                android:background="@drawable/bg_white_10dp"
+                android:drawableRight="@drawable/icon_arrow_down"
+                android:drawablePadding="4dp"
+                android:ellipsize="end"
+                android:gravity="center"
+                android:includeFontPadding="false"
+                android:maxLines="1"
+                android:text="@string/all_course_status_str"
+                android:textColor="@color/color_131415"
+                android:textSize="@dimen/sp_14"
+                tools:text="全部考勤" />
+
+        </FrameLayout>
+
+        <FrameLayout
+            android:id="@+id/fl_attendance"
+            android:layout_width="0dp"
+            android:layout_height="22dp"
+            android:layout_weight="0.3"
+            android:background="@drawable/bg_white_10dp">
+
+            <TextView
+                android:id="@+id/tv_attendance_status"
+                android:layout_width="wrap_content"
+                android:layout_height="match_parent"
+                android:layout_gravity="center"
+                android:background="@drawable/bg_white_10dp"
+                android:drawableRight="@drawable/icon_arrow_down"
+                android:drawablePadding="4dp"
+                android:ellipsize="end"
+                android:gravity="center"
+                android:includeFontPadding="false"
+                android:maxLines="1"
+                android:text="@string/all_attendance_str"
+                android:textColor="@color/color_131415"
+                android:textSize="@dimen/sp_14"
+                tools:text="全部考勤" />
+        </FrameLayout>
+    </LinearLayout>
+
+    <androidx.recyclerview.widget.RecyclerView
+        android:id="@+id/recyclerView"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_marginTop="12dp"
+        android:overScrollMode="never"
+        android:paddingStart="14dp"
+        android:paddingEnd="14dp"
+        android:scrollbars="none"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintTop_toBottomOf="@+id/ll_filter" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 13 - 0
teacher/src/main/res/layout/fg_piano_course_group_detail_student_list_layout.xml

@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:paddingTop="12dp"
+    android:layout_height="match_parent">
+
+    <androidx.recyclerview.widget.RecyclerView
+        android:id="@+id/recyclerView"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:overScrollMode="never"
+        android:scrollbars="none" />
+</FrameLayout>

+ 178 - 0
teacher/src/main/res/layout/item_piano_course_group_course_layout.xml

@@ -0,0 +1,178 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:layout_marginStart="14dp"
+    android:layout_marginEnd="14dp"
+    android:layout_marginBottom="12dp"
+    android:background="@drawable/bg_white_10dp"
+    android:paddingStart="12dp"
+    android:paddingEnd="12dp"
+    android:paddingBottom="12dp">
+
+    <ImageView
+        android:id="@+id/iv_clock_icon"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="15dp"
+        android:src="@drawable/icon_clock"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <TextView
+        android:id="@+id/tv_time"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="6dp"
+        android:includeFontPadding="false"
+        android:textColor="@color/color_666666"
+        android:textSize="@dimen/sp_13"
+        app:layout_constraintBottom_toBottomOf="@+id/iv_clock_icon"
+        app:layout_constraintLeft_toRightOf="@+id/iv_clock_icon"
+        app:layout_constraintTop_toTopOf="@+id/iv_clock_icon"
+        tools:text="2021/09/17 14:00~14:25" />
+
+    <View
+        android:id="@+id/view_line"
+        android:layout_width="0dp"
+        android:layout_height="1dp"
+        android:layout_marginTop="15dp"
+        android:background="@color/color_f2f2f2"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintTop_toBottomOf="@+id/iv_clock_icon" />
+
+    <ImageView
+        android:id="@+id/iv_avatar"
+        android:layout_width="40dp"
+        android:layout_height="40dp"
+        android:layout_marginTop="12dp"
+        android:src="@drawable/icon_piano_room_course"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintTop_toBottomOf="@+id/view_line"
+        app:qmui_corner_radius="5dp" />
+
+    <TextView
+        android:id="@+id/tv_title"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="10dp"
+        android:ellipsize="end"
+        android:includeFontPadding="false"
+        android:maxLines="1"
+        android:textColor="@color/color_1a1a1a"
+        android:textSize="@dimen/sp_15"
+        app:layout_constraintBottom_toTopOf="@+id/tv_name"
+        app:layout_constraintHorizontal_bias="0"
+        app:layout_constraintHorizontal_chainStyle="packed"
+        app:layout_constraintLeft_toRightOf="@+id/iv_avatar"
+        app:layout_constraintRight_toLeftOf="@+id/iv_attendance_status"
+        app:layout_constraintTop_toTopOf="@+id/iv_avatar"
+        app:layout_constraintVertical_chainStyle="packed"
+        app:layout_constraintWidth_default="wrap"
+        tools:text="VIP定制课-张豆豆VIP定制课-张豆豆" />
+
+    <ImageView
+        android:id="@+id/iv_attendance_status"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="5dp"
+        android:layout_marginEnd="5dp"
+        android:src="@drawable/icon_course_attendance_truancy"
+        android:visibility="gone"
+        app:layout_constraintBottom_toBottomOf="@+id/tv_title"
+        app:layout_constraintLeft_toRightOf="@+id/tv_title"
+        app:layout_constraintRight_toLeftOf="@+id/iv_arrow"
+        app:layout_constraintTop_toTopOf="@+id/tv_title" />
+
+    <TextView
+        android:id="@+id/tv_name"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="4dp"
+        android:ellipsize="middle"
+        android:includeFontPadding="false"
+        android:singleLine="true"
+        android:textColor="@color/color_999999"
+        android:textSize="@dimen/sp_13"
+        app:layout_constraintBottom_toBottomOf="@+id/iv_avatar"
+        app:layout_constraintHorizontal_bias="0"
+        app:layout_constraintHorizontal_chainStyle="packed"
+        app:layout_constraintLeft_toLeftOf="@+id/tv_title"
+        app:layout_constraintRight_toLeftOf="@+id/tv_course_name"
+        app:layout_constraintTop_toBottomOf="@+id/tv_title"
+        app:layout_constraintWidth_default="wrap"
+        tools:text="张豆豆张豆豆张豆豆张豆豆张豆豆张豆豆张豆豆张豆豆张豆豆张豆豆张豆豆张豆豆" />
+
+    <ImageView
+        android:id="@+id/iv_go_chat"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="5dp"
+        android:src="@drawable/icon_chat_small"
+        android:visibility="gone"
+        app:layout_constraintBottom_toBottomOf="@+id/tv_title"
+        app:layout_constraintLeft_toRightOf="@+id/tv_title"
+        app:layout_constraintTop_toTopOf="@+id/tv_title" />
+
+    <TextView
+        android:id="@+id/tv_course_name"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="5dp"
+        android:layout_marginEnd="5dp"
+        android:background="@drawable/shape_couse_type_text_bg"
+        android:gravity="center"
+        android:includeFontPadding="false"
+        android:paddingStart="4dp"
+        android:paddingTop="2dp"
+        android:paddingEnd="4dp"
+        android:paddingBottom="2dp"
+        android:textColor="@color/color_ff8c00"
+        android:textSize="@dimen/sp_11"
+        app:layout_constraintBottom_toBottomOf="@+id/tv_name"
+        app:layout_constraintLeft_toRightOf="@+id/tv_name"
+        app:layout_constraintRight_toLeftOf="@+id/iv_arrow"
+        app:layout_constraintTop_toTopOf="@+id/tv_name"
+        tools:text="单簧管" />
+
+
+    <TextView
+        android:id="@+id/tv_course_status"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:textColor="@color/color_999999"
+        android:textSize="@dimen/sp_14"
+        app:layout_constraintBottom_toTopOf="@+id/view_line"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        tools:text="未开始" />
+
+    <TextView
+        android:id="@+id/tv_go_start"
+        android:layout_width="wrap_content"
+        android:layout_height="22dp"
+        android:background="@drawable/shape_2dc7aa_11dp"
+        android:gravity="center"
+        android:paddingStart="8dp"
+        android:paddingEnd="8dp"
+        android:text="开始上课"
+        android:textColor="@color/white"
+        android:textSize="@dimen/sp_12"
+        android:visibility="gone"
+        app:layout_constraintBottom_toTopOf="@+id/view_line"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        tools:text="开始上课" />
+
+    <ImageView
+        android:id="@+id/iv_arrow"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:src="@drawable/icon_arrow_right"
+        app:layout_constraintBottom_toBottomOf="@+id/iv_avatar"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintTop_toTopOf="@+id/iv_avatar" />
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 75 - 0
teacher/src/main/res/layout/item_piano_course_group_student_layout.xml

@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/cs_root"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:layout_marginStart="14dp"
+    android:layout_marginEnd="14dp"
+    android:background="@drawable/bg_white_10dp"
+    android:paddingStart="12dp"
+    android:paddingTop="12dp"
+    android:paddingEnd="12dp"
+    android:paddingBottom="12dp">
+
+    <de.hdodenhof.circleimageview.CircleImageView
+        android:id="@+id/iv_avatar"
+        android:layout_width="40dp"
+        android:layout_height="40dp"
+        android:src="@drawable/icon_default_head"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        app:qmui_corner_radius="5dp" />
+
+    <TextView
+        android:id="@+id/tv_title"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="10dp"
+        android:layout_marginEnd="5dp"
+        android:ellipsize="end"
+        android:includeFontPadding="false"
+        android:maxLines="1"
+        android:textColor="@color/color_333333"
+        android:textSize="@dimen/sp_14"
+        app:layout_constraintBottom_toTopOf="@+id/tv_course_name"
+        app:layout_constraintLeft_toRightOf="@+id/iv_avatar"
+        app:layout_constraintRight_toLeftOf="@+id/iv_go_chat"
+        app:layout_constraintTop_toTopOf="@+id/iv_avatar"
+        app:layout_constraintVertical_chainStyle="packed"
+        tools:text="VIP定制课-张豆豆VIP定制课-张豆豆" />
+
+
+    <TextView
+        android:id="@+id/tv_course_name"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="3dp"
+        android:background="@drawable/shape_couse_type_text_bg"
+        android:gravity="center"
+        android:includeFontPadding="false"
+        android:paddingStart="4dp"
+        android:paddingTop="2dp"
+        android:paddingEnd="4dp"
+        android:paddingBottom="2dp"
+        android:textColor="@color/color_ff8c00"
+        android:textSize="@dimen/sp_11"
+        app:layout_constraintBottom_toBottomOf="@+id/iv_avatar"
+        app:layout_constraintLeft_toLeftOf="@+id/tv_title"
+        app:layout_constraintTop_toBottomOf="@+id/tv_title"
+        tools:text="单簧管" />
+
+    <ImageView
+        android:id="@+id/iv_go_chat"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="5dp"
+        android:src="@drawable/icon_chat_small"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 15 - 7
teacher/src/main/res/layout/item_vip_course_group_layout.xml

@@ -88,34 +88,41 @@
         android:layout_height="wrap_content"/>
 
     <TextView
-        android:layout_marginTop="4dp"
-        app:layout_constraintBottom_toBottomOf="@+id/iv_avatar"
         android:id="@+id/tv_name"
-        android:layout_width="wrap_content"
+        android:layout_width="0dp"
         android:layout_height="wrap_content"
+        android:layout_marginTop="4dp"
+        android:ellipsize="middle"
         android:includeFontPadding="false"
+        android:singleLine="true"
         android:textColor="@color/color_999999"
         android:textSize="@dimen/sp_13"
+        app:layout_constraintBottom_toBottomOf="@+id/iv_avatar"
+        app:layout_constraintHorizontal_bias="0"
+        app:layout_constraintHorizontal_chainStyle="packed"
         app:layout_constraintLeft_toLeftOf="@+id/tv_title"
+        app:layout_constraintRight_toLeftOf="@+id/tv_course_name"
         app:layout_constraintTop_toBottomOf="@+id/tv_title"
-        tools:text="张豆豆" />
+        app:layout_constraintWidth_default="wrap"
+        tools:text="张豆豆张豆豆张豆豆张豆豆张豆豆张豆豆张豆豆张豆豆张豆豆张豆豆张豆豆张豆豆" />
 
     <ImageView
-        android:visibility="gone"
         android:id="@+id/iv_go_chat"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_marginStart="5dp"
         android:src="@drawable/icon_chat_small"
+        android:visibility="gone"
         app:layout_constraintBottom_toBottomOf="@+id/tv_title"
         app:layout_constraintLeft_toRightOf="@+id/tv_title"
         app:layout_constraintTop_toTopOf="@+id/tv_title" />
 
     <TextView
-        android:layout_marginStart="5dp"
         android:id="@+id/tv_course_name"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
+        android:layout_marginStart="5dp"
+        android:layout_marginEnd="5dp"
         android:background="@drawable/shape_couse_type_text_bg"
         android:gravity="center"
         android:includeFontPadding="false"
@@ -127,7 +134,8 @@
         android:textSize="@dimen/sp_11"
         app:layout_constraintBottom_toBottomOf="@+id/tv_name"
         app:layout_constraintLeft_toRightOf="@+id/tv_name"
-        app:layout_constraintTop_toBottomOf="@+id/tv_name"
+        app:layout_constraintRight_toLeftOf="@+id/iv_arrow"
+        app:layout_constraintTop_toTopOf="@+id/tv_name"
         tools:text="单簧管" />
 
 

+ 2 - 0
teacher/src/main/res/values/strings.xml

@@ -70,4 +70,6 @@
     <string name="vip_setting_str2">元/节</string>
     <string name="vip_setting_str3">实际课程收入按学生实际付款金额计算\n您的课程收入将在课程结束</string>
     <string name="vip_setting_str4">天后结算到您的账户</string>
+    <string name="all_attendance_str">全部考勤</string>
+    <string name="all_course_status_str">全部状态</string>
 </resources>