From 1fa2461678d7f93b88f5666c4898e5b6c72080f3 Mon Sep 17 00:00:00 2001
From: 闫增涛 <1829501689@qq.com>
Date: 星期一, 16 十二月 2024 10:21:06 +0800
Subject: [PATCH] 个人中心,班级、课程模块

---
 packageBookService/pages/bookServices/examination/components/joinGroupDialog/index.wxss |  181 +
 packageCourse/pages/teachClass/detail/index.json                                        |   11 
 packageCourse/pages/course/index.wxml                                                   |  137 +
 packageCourse/pages/teachClass/index.js                                                 |  118 +
 packageBookService/pages/bookServices/examination/examination.json                      |    3 
 packageCourse/components/baseClass/index.json                                           |    9 
 packageCourse/pages/teachClass/index.json                                               |    8 
 packageCourse/components/baseClass/index.wxss                                           |  109 +
 packageBookService/pages/bookServices/examination/examination.js                        |  234 ++
 packageCourse/pages/course/index.js                                                     |  378 ++++
 packageCourse/components/questionDom/index.wxml                                         |   54 
 static/images/personal/class.png                                                        |    0 
 pages/personalCenter/index.js                                                           |   12 
 packageCourse/components/teaching/index.wxss                                            |   50 
 packageCourse/components/studentManage/index.wxss                                       |  132 +
 packageCourse/pages/course/detail/index.js                                              |  457 ++++
 packageCourse/pages/studentClass/index.js                                               |  296 +++
 packageBookService/pages/bookServices/examination/questionOptions/index.js              |    3 
 packageCourse/pages/studentClass/index.wxss                                             |  223 ++
 packageCourse/pages/teachClass/index.wxml                                               |   31 
 packageCourse/pages/course/detail/index.wxml                                            |  139 +
 packageCourse/pages/course/index.skeleton.wxss                                          |  140 +
 packageCourse/pages/teachClass/detail/index.wxml                                        |   42 
 packageCourse/components/questionDom/index.json                                         |   11 
 packageCourse/components/teaching/index.json                                            |    8 
 packageBookService/pages/bookServices/examination/components/joinGroupDialog/index.wxml |   46 
 packageCourse/pages/course/index.wxss                                                   |  335 +++
 packageCourse/components/baseClass/index.js                                             |  164 +
 packageBookService/pages/bookServices/examination/examination.wxml                      |    5 
 packageCourse/pages/course/detail/index.wxss                                            |  281 +++
 packageBookService/pages/bookServices/examination/questionOptions/index.wxml            |  175 +
 packageCourse/components/baseClass/index.wxml                                           |   52 
 packageCourse/pages/studentClass/index.json                                             |   16 
 packageBookService/pages/bookServices/examination/questionSchedule/index.wxml           |   12 
 pages/personalCenter/index.wxss                                                         |   10 
 packageCourse/components/questionDom/index.wxss                                         |   29 
 packageCourse/components/teaching/index.wxml                                            |   33 
 packageBookService/pages/bookServices/detail/index.js                                   |    7 
 packageCourse/components/studentManage/index.wxml                                       |   74 
 packageCourse/pages/course/detail/index.json                                            |   15 
 packageCourse/pages/course/index.json                                                   |   18 
 assets/js/middleGround/api/edu.js                                                       |    8 
 packageCourse/components/questionDom/index.js                                           |   46 
 packageCourse/pages/studentClass/index.wxml                                             |   95 +
 packageCourse/pages/teachClass/index.wxss                                               |   56 
 app.json                                                                                |   12 
 packageCourse/pages/course/index.skeleton.wxml                                          |  106 +
 packageBookService/pages/bookServices/examination/components/joinGroupDialog/index.json |   12 
 packageBookService/pages/bookServices/examination/components/joinGroupDialog/index.js   |   95 +
 packageCourse/components/teaching/index.js                                              |  296 +++
 packageCourse/pages/teachClass/detail/index.wxss                                        |   92 +
 assets/js/middleGround/api/identity.js                                                  |   19 
 packageCourse/components/studentManage/index.json                                       |   18 
 packageCourse/components/studentManage/index.js                                         |  257 ++
 packageCourse/pages/teachClass/detail/index.js                                          |  309 +++
 static/images/personal/course.png                                                       |    0 
 56 files changed, 5,416 insertions(+), 63 deletions(-)

diff --git a/app.json b/app.json
index 1adea5c..fb99c71 100644
--- a/app.json
+++ b/app.json
@@ -82,6 +82,18 @@
         "pages/bookServices/linkPage/index",
         "pages/psychologyAnswer/psychologyAnswer"
       ]
+    },
+    {
+      "root": "packageCourse",
+      "name": "packageCourse",
+      "pages": [
+        "pages/course/index",
+        "pages/course/detail/index",
+        "pages/teachClass/index",
+        "components/baseClass/index",
+        "pages/studentClass/index",
+        "pages/teachClass/detail/index"
+      ]
     }
   ],
   "tabBar": {
diff --git a/assets/js/middleGround/api/edu.js b/assets/js/middleGround/api/edu.js
index d22327d..70cfeff 100644
--- a/assets/js/middleGround/api/edu.js
+++ b/assets/js/middleGround/api/edu.js
@@ -161,6 +161,14 @@
       data,
     })
   },
+    // 鑾峰彇topic淇℃伅
+    getClassTopic(data) {
+      return request({
+        url: '/edu/api/ApiGetClassTopic',
+        method: 'post',
+        data
+      })
+    },
 }
 
 export default eduApi
diff --git a/assets/js/middleGround/api/identity.js b/assets/js/middleGround/api/identity.js
index f4a040a..ab59fa0 100644
--- a/assets/js/middleGround/api/identity.js
+++ b/assets/js/middleGround/api/identity.js
@@ -199,7 +199,24 @@
       method: "post",
       data,
     });
-  }
+  },
+  // 閫氳繃refcode鍔犲叆鐝骇/缁�
+  joinGroupByRefCode(data) {
+    return request({
+      url: '/identity/api/ApiJoinGroupByRefCode',
+      method: 'post',
+      data
+    })
+  },
+
+  // 鑾峰彇鍔犲叆缁勭殑鍒楄〃淇℃伅
+  joinedGroupByList(data) {
+    return request({
+      url: '/identity/api/ApiGetJoinedGroupByList',
+      method: 'post',
+      data
+    })
+  },
 };
 
 export default identityApi;
\ No newline at end of file
diff --git a/packageBookService/pages/bookServices/detail/index.js b/packageBookService/pages/bookServices/detail/index.js
index ef3187d..8c7fbf8 100644
--- a/packageBookService/pages/bookServices/detail/index.js
+++ b/packageBookService/pages/bookServices/detail/index.js
@@ -1166,10 +1166,9 @@
 
             if (isTSFW.length > 0) {
               data = res.datas.cmsDatas[0].datas.filter((item) => item.type == 'questionBankFolder' && (item.childrenFolderCount > 0 || item.childrenCount > 0) && (item.name !== '濉┖棰�' &&
-                  item.name !== '鍒ゆ柇棰�' &&
-                  item.name !== '澶氶�夐' &&
-                  item.name !== '绠�绛旈')) &&
-                item.refCode != 'jsek_interaction'
+                item.name !== '鍒ゆ柇棰�' &&
+                item.name !== '澶氶�夐' &&
+                item.name !== '绠�绛旈') && item.name !== '鍗曢�夐')
               that.setData({
                 jslx: false,
               });
diff --git a/packageBookService/pages/bookServices/examination/components/joinGroupDialog/index.js b/packageBookService/pages/bookServices/examination/components/joinGroupDialog/index.js
new file mode 100644
index 0000000..5bd6cdc
--- /dev/null
+++ b/packageBookService/pages/bookServices/examination/components/joinGroupDialog/index.js
@@ -0,0 +1,95 @@
+// components/popup/index.js
+const app = getApp()
+Component({
+  /**
+   * 缁勪欢鐨勫睘鎬у垪琛�
+   */
+  properties: {
+
+  },
+  ready() {
+    var that = this;
+    // 鍔ㄦ�佽幏鍙栧睆骞曢珮搴�
+    wx.getSystemInfo({
+      success: (result) => {
+        that.setData({
+          height: result.windowHeight
+        });
+      },
+    })
+  },
+  properties: {
+    visible: {
+      type: Boolean
+    },
+  },
+  /**
+   * 缁勪欢鐨勫垵濮嬫暟鎹�
+   */
+  data: {
+    inputStyle: 'border: 2rpx solid rgba(220,220,220,1);border-radius: 12rpx; padding: 0 0 0 16rpx;',
+    visible: false, //鎵撳紑寮圭獥鐨勫搴斾笅鏍�
+    height: '', //灞忓箷楂樺害
+    inputvalue: '',
+    joinGroup: '',
+    noTip: false,
+  },
+
+  /**
+   * 缁勪欢鐨勬柟娉曞垪琛�
+   */
+  methods: {
+    //鍏抽棴寮圭獥
+    closePopup() {
+      this.setData({
+        visible: false,
+        inputvalue: '',
+      })
+    },
+
+    // 杈撳叆妗嗘敼鍙�
+    inputChange(e) {
+      this.setData({
+        inputvalue: e.detail.value
+      })
+    },
+    // 鍗曢�夋鏀瑰彉
+    onChangeRadio(e) {
+      console.log(e)
+      this.setData({
+        joinGroup: e.currentTarget.dataset.value
+      })
+    },
+    // 纭畾
+    confirmSuggest() {
+      if (this.data.joinGroup) {
+        if (this.data.joinGroup == 1) {
+          if (!this.data.inputvalue.length) {
+            wx.showToast({
+              icon: "error",
+              title: '璇峰~鍐欒仈绯绘柟寮�',
+            })
+          } else {
+            // this.joinClass()
+            var myEventDetail = {
+              value: this.data.inputvalue
+            } // detail瀵硅薄锛屾彁渚涚粰浜嬩欢鐩戝惉鍑芥暟
+            var myEventOption = {
+              bubbles: true,
+              composed: true
+            } // 瑙﹀彂浜嬩欢鐨勯�夐」
+            this.triggerEvent('joinClass', myEventDetail, myEventOption)
+          }
+        } else {
+          this.closePopup()
+        }
+      } else {
+        wx.showToast({
+          icon: 'error',
+          title: '璇烽�夋嫨鍔犲叆鐝骇',
+        })
+      }
+    },
+
+  }
+})
\ No newline at end of file
diff --git a/packageBookService/pages/bookServices/examination/components/joinGroupDialog/index.json b/packageBookService/pages/bookServices/examination/components/joinGroupDialog/index.json
new file mode 100644
index 0000000..10c464d
--- /dev/null
+++ b/packageBookService/pages/bookServices/examination/components/joinGroupDialog/index.json
@@ -0,0 +1,12 @@
+{
+  "component": true,
+  "usingComponents": {
+    "t-input": "tdesign-miniprogram/input/input",
+    "t-textarea": "tdesign-miniprogram/textarea/textarea",
+    "t-button": "tdesign-miniprogram/button/button",
+    "t-icon": "tdesign-miniprogram/icon/icon",
+    "t-rate": "tdesign-miniprogram/rate/rate",
+    "t-radio": "tdesign-miniprogram/radio/radio",
+    "t-checkbox": "tdesign-miniprogram/checkbox/checkbox"
+  }
+}
\ No newline at end of file
diff --git a/packageBookService/pages/bookServices/examination/components/joinGroupDialog/index.wxml b/packageBookService/pages/bookServices/examination/components/joinGroupDialog/index.wxml
new file mode 100644
index 0000000..1c4542b
--- /dev/null
+++ b/packageBookService/pages/bookServices/examination/components/joinGroupDialog/index.wxml
@@ -0,0 +1,46 @@
+<!-- 涓棿寮圭獥 -->
+<view class="popup-box" wx:if="{{visible=='1'}}" bindtap="closePopup"></view>
+<view class="info-center" style="top:{{height*0.1}}px" wx:if="{{visible=='1'}}">
+  <view class="row-info">
+    <view class="popup-content">
+      <view class="warning-txt">
+        妫�娴嬪埌鎮ㄦ湭鍔犲叆鐝骇锛屽鎮ㄤ笉鍔犲叆鐝骇锛屾彁浜ょ殑绛旀灏嗕笉鑳芥彁浜ゅ埌鐝骇鑰佸笀澶勶細
+      </view>
+      <t-radio
+        allow-uncheck
+        icon="dot"
+        label="鍔犲叆鐝骇"
+        value="1"
+        data-value="1"
+        checked="{{joinGroup == 1}}"
+        bind:change="onChangeRadio"
+      />
+      <view class="phone-input">
+        <t-input
+          value="{{inputvalue}}"
+          placeholder="璇疯緭鍏ョ彮绾ч個璇风爜"
+          bind:change="inputChange"
+          type="number"
+          maxlength="{{11}}"
+          class="phone"
+          style="{{inputStyle}}"
+        />
+      </view>
+      <t-radio
+        allow-uncheck
+        icon="dot"
+        label="涓嶅姞鍏ョ彮绾�"
+        value="0"
+        data-value="2"
+        checked="{{joinGroup == 2}}"
+        bind:change="onChangeRadio"
+      />
+      <t-checkbox label="涓嶅啀鎻愮ず鍔犲叆鐝骇" icon="rectangle" value="{{noTip}}" />
+    </view>
+    <view class="submit-btn">
+      <t-button theme="primary" size="large" block bind:tap="confirmSuggest"
+        >纭</t-button
+      >
+    </view>
+  </view></view
+>
diff --git a/packageBookService/pages/bookServices/examination/components/joinGroupDialog/index.wxss b/packageBookService/pages/bookServices/examination/components/joinGroupDialog/index.wxss
new file mode 100644
index 0000000..da8f9c7
--- /dev/null
+++ b/packageBookService/pages/bookServices/examination/components/joinGroupDialog/index.wxss
@@ -0,0 +1,181 @@
+/* packageBookService/pages/bookServices/examination/components/joinGroupDialog/index.wxss */
+/* components/popup/index.wxss */
+/* 钂欏眰 */
+.popup-box {
+  position: absolute;
+  z-index: 99;
+  top: 0;
+  background-color: rgba(0, 0, 0, 0.5);
+  width: 100%;
+  height: 100%;
+}
+
+/* 涓� */
+.info-top {
+  position: fixed;
+  z-index: 999;
+  width: 100%;
+  top: 0;
+  background-color: white;
+  border-bottom-left-radius: 5rpx;
+  border-bottom-right-radius: 5rpx;
+}
+
+/* 涓� */
+.info-center {
+  position: relative;
+  /* background-image: linear-gradient(to bottom, #FFF8E5, #fffcf5); */
+  background-color: #fff;
+  position: fixed;
+  z-index: 999;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  border-radius: 10rpx;
+  width: 90%;
+  margin-left: 5%;
+  margin-right: 5%;
+}
+
+/* 涓� */
+.info-bottom {
+  position: fixed;
+  z-index: 999;
+  width: 100%;
+  bottom: 0;
+  background-color: white;
+  border-top-left-radius: 10rpx;
+  border-top-right-radius: 10rpx;
+}
+
+/* 宸� */
+.info-left {
+  position: fixed;
+  z-index: 999;
+  width: 50%;
+  height: 100%;
+  top: 0;
+  background-color: white;
+  border-top-right-radius: 10rpx;
+  border-bottom-right-radius: 10rpx;
+}
+
+/* 鍙� */
+.info-right {
+  position: fixed;
+  z-index: 999;
+  width: 50%;
+  height: 100%;
+  right: 0;
+  top: 0;
+  background-color: white;
+  border-top-left-radius: 10rpx;
+  border-bottom-left-radius: 10rpx;
+}
+
+/* 鑷畾涔夊唴瀹癸紙鏍规嵁鑷繁闇�姹傛洿鏀�,鍙垹闄わ級 */
+button {
+  margin: 15rpx 0;
+}
+
+.row-info {
+  width: 100%;
+  padding: 10rpx;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  margin: 15rpx;
+  font-size: 32rpx;
+}
+
+.phone-input view {
+  padding: 10rpx 0;
+}
+
+.line {
+  width: 100rpx;
+  height: 1rpx;
+}
+
+.left-line {
+  background-image: linear-gradient(to left, orange, white);
+}
+
+.right-line {
+  background-image: linear-gradient(to right, orange, white);
+}
+
+.row-author {
+  font-size: 24rpx;
+  color: gray;
+}
+
+.row-btn {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  border-top: 1rpx dashed #f1f1f1;
+}
+
+.row-btn view {
+  flex: 1;
+  text-align: center;
+  margin: 20rpx 10%;
+  padding: 12rpx 0;
+  font-size: 32rpx;
+  border-radius: 10rpx;
+}
+
+.left-btn {
+  background-color: #f1f1f1;
+  color: #33ccff;
+}
+
+.right-btn {
+  background-color: #33ccff;
+  color: white;
+}
+
+.fixed {
+  position: fixed;
+  bottom: 0;
+  width: 50%;
+}
+
+.popup-content {
+  width: 100%;
+  height: 680rpx;
+  display: flex;
+  flex-direction: column;
+}
+
+.phone {
+  --td-input-border-radius: 20rpx;
+  border-radius: 20rpx;
+}
+
+.phone-input {
+  width: 100%;
+  margin-bottom: 16rpx;
+}
+
+.submit-btn {
+  width: 200rpx;
+  /* padding: 40rpx; */
+  --td-button-border-radius: 20rpx;
+  --td-button-primary-bg-color: #ff6c00;
+  --td-button-primary-border-color: #ff6c00;
+  --td-button-primary-active-bg-color: #ff984d;
+  --td-button-primary-active-border-color: #ff984d;
+}
+
+.warning-txt {
+  color: #d8001b;
+  font-size: 28rpx;
+}
+
+/* .t-radio__border {
+  position: absolute;
+  height: 0;
+  background: unset;
+} */
\ No newline at end of file
diff --git a/packageBookService/pages/bookServices/examination/examination.js b/packageBookService/pages/bookServices/examination/examination.js
index 038bc76..4b751df 100644
--- a/packageBookService/pages/bookServices/examination/examination.js
+++ b/packageBookService/pages/bookServices/examination/examination.js
@@ -55,6 +55,9 @@
     showDialog: false, // 鏈彁浜ら��鍑烘嫤鎴脊绐�
     showId: '',
     isShowDialog: false, // 娴嬭瘯鎶ュ憡寮圭獥鏄惁鏄剧ず
+    joinGroup: false, // 鏄惁鍔犲叆鐝骇
+    visible: false, // 鍔犲叆鐝骇寮圭獥鏄惁鎵撳紑
+    classList: [] // 鐝骇鍒楄〃
   },
 
   /**
@@ -554,7 +557,8 @@
     if (
       this.data.answerType == "option" ||
       this.data.answerType == "errorQuestion" ||
-      this.data.answerType == "mock"
+      this.data.answerType == "mock" ||
+      this.data.answerType == 'interaction'
     ) {
       // 鍏堥亶鍘嗘墍鏈夐鐩紝灏嗘湭鎵规敼鐨勯鐩壒鏀�
       const qustionList = this.data.questionDataList;
@@ -617,6 +621,9 @@
       this.setData({
         isShowDialog: true
       })
+    } else if (this.data.answerType == 'interaction') {
+      this.toggleCountdown();
+      this.handleClassQuestion()
     }
     this.setData({
       loading: false,
@@ -639,6 +646,13 @@
       // 娴嬭瘯绛旈
       await this.getCollectIdList(); // 鑾峰彇鏀惰棌id鍒楄〃
       await this.getErrorList(); // 鑾峰彇閿欓id鍒楄〃
+    } else if (this.data.answerType == "interaction") {
+      this.setData({
+        countdownTime: 2 * 60 * 60 * 1000,
+      });
+      this.getCurrentClassList()
+      this.getinteractionInfo()
+      // 鏁欏浜掑姩
     } else if (this.data.answerType == "collectQuestion") {
       this.setData({
         submitStatus: true,
@@ -846,7 +860,6 @@
       let query = {
         path: "*",
         queryType: "*",
-
         productId: this.data.bookId,
         cmsPath: pathitem.productLinkPath,
         itemFields: {
@@ -880,9 +893,6 @@
           oldList = oldData.find(
             (item) => item.path == pathitem.productLinkPath
           ).infoList;
-          this.setData({
-            submitStatus: true,
-          });
         }
         res.datas.cmsDatas[0].datas.forEach((item, index) => {
           if (this.data.storeInfo || this.data.jslx) {
@@ -1079,15 +1089,16 @@
     // 鏈夐鐩啀寮�濮嬪�掕鏃�
     if (this.data.questionDataList.length) {
       this.startCountdown();
+      this.setData({
+        loading: false,
+        showId: this.data.questionDataList[0].id
+      })
     } else {
       this.setData({
-        noData: true
+        noData: true,
+        loading: false,
       })
     }
-    this.setData({
-      loading: false,
-      showId: this.data.questionDataList[0].id
-    });
   },
   // 鎵规敼棰樼洰 锛堢粌涔狅紝鎴戠殑閿欓锛屾垜鐨勬敹钘�,锛岀粍鍗凤級
   handleQuestion(index) {
@@ -2232,7 +2243,6 @@
 
   // 瀵屾枃鏈鐞�
   formatRichText(html) {
-    console.log(html);
     let newContent = html.replace(/<img[^>]*>/gi, function (match, capture) {
       match = match
         .replace(/style="[^"]+"/gi, "")
@@ -2266,4 +2276,206 @@
     );
     return newContent;
   },
+  // 鏁欏浜掑姩妯″紡鐩稿叧
+  // 鑾峰彇鐝骇鍒楄〃
+  getCurrentClassList() {
+    const query = {
+      start: 0,
+      size: 999,
+      filterList: [],
+    }
+    app.MG.identity.joinedGroupByList(query).then((res) => {
+      res.datas.forEach(async item => {
+        item.topicId = null
+        const data = await this.getTopicInfo(item.id)
+        if (data) {
+          item.topicId = data.id
+        }
+      })
+      if (res.datas.length) {
+        this.setData({
+          joinGroup: true,
+          classList: res.datas,
+        })
+      } else {
+        // 鏈姞鍏ョ彮绾э紝鍞よ捣鍔犲叆鐝骇寮圭獥
+        this.setData({
+          joinGroup: false,
+          visible: true
+        })
+      }
+    })
+  },
+  // 鍔犲叆鐝骇
+  joinClass(e) {
+    const data = {
+      refCode: e.detail.value
+    }
+    app.MG.identity.joinGroupByRefCode(data).then((res) => {
+      if (res == '缁勪笉瀛樺湪') {
+        wx.showToast({
+          icon: 'error',
+          title: '鏃犳晥鐨勭彮绾�',
+        })
+      } else if (res == '缁勬垚鍛樻暟閲忓凡鏈�澶�,涓嶈兘鍔犲叆') {
+        wx.showToast({
+          icon: 'error',
+          title: '鐝骇鎴愬憳鏁伴噺宸叉渶澶э紝涓嶈兘鍔犲叆',
+        })
+      } else if (res == '宸茬粡鐢宠杩囧姞鍏ユ缁�') {
+        wx.showToast({
+          icon: 'error',
+          title: '宸茬粡鐢宠杩囧姞鍏ユ鐝骇',
+        })
+      } else {
+        wx.showToast({
+          icon: "success",
+          title: '宸叉垚鍔燂紝绛夊緟瀹℃牳涓�...',
+        })
+        this.setData({
+          visible: false
+        })
+        this.getCurrentClassList()
+      }
+    })
+  },
+  // 鑾峰彇鐝骇topic
+  async getTopicInfo(classId) {
+    let query = {
+      classId,
+      refCodes: ["TeachInteraction"]
+    }
+    const res = await app.MG.edu.getClassTopic(query)
+    return res[0] ?? null
+  },
+  // 鑾峰彇鏃ф暀瀛︿簰鍔ㄧ瓟棰樻暟鎹�
+  getinteractionInfo() {
+    app.MG.identity
+      .getUserKey({
+        domain: "interactionData",
+        keys: [this.data.productLinkPath],
+      })
+      .then((res) => {
+        if (res.length) {
+          let value = JSON.parse(res[0].value);
+          this.setData({
+            submitStatus: value.submitStatus,
+            currentIndex: value.currentIndex,
+          });
+          // 鎼哄甫绛旈璁板綍 鑾峰彇棰樼洰
+          this.getQuestionList(value.dataList);
+        } else {
+          this.getQuestionList(); // 鑾峰彇棰樺簱棰樼洰
+          this.setData({
+            showDialog: true
+          })
+        }
+      });
+  },
+  // 鎻愪氦鏁欏浜掑姩绛旈鏁版嵁
+  setinteractionInfo(submitStatus) {
+    const list = []
+    this.data.cardList.forEach(item => {
+      list.push({
+        catalogName: item.catalogName,
+        path: item.path,
+        infoList: item.infoList.map((citem) => ({
+          id: citem.id,
+          userAnswer: citem.userAnswer
+        }))
+      })
+    })
+    console.log('鎻愪氦鏁版嵁', list);
+    app.MG.identity
+      .setUserKey({
+        setKeyRequests: [{
+          domain: "interactionData",
+          key: this.data.productLinkPath,
+          value: JSON.stringify({
+            submitStatus,
+            currentIndex: this.data.currentIndex,
+            dataList: list
+          }),
+        }, ],
+      })
+      .then((res) => {});
+  },
+  // 澶勭悊鏁欏浜掑姩绛旈 
+  handleClassQuestion() {
+    debugger
+    const flag = this.data.questionDataList.some(item => !item.userAnswer)
+    if (flag) {
+      // 娌″仛瀹岋紝淇濆瓨鍗冲彲
+      const isAnswer = this.data.questionDataList.some(item => item.userAnswer)
+      if (isAnswer) this.setinteractionInfo(false)
+    } else {
+      // 鍋氬畬浜嗭紝鎻愪氦鍒癿essage
+      this.setinteractionInfo(true)
+      if (this.data.classList.length) {
+        this.data.classList.forEach(item => {
+          this.newTopicMessage(item.topicId)
+        })
+      }
+    }
+    this.setData({
+      submitStatus: true
+    })
+  },
+
+  // 鏂板缓topicMessage
+  newTopicMessage(topicId) {
+    let content = []
+    for (let cindex = 0; cindex < this.data.questionDataList.length; cindex++) {
+      const citem = this.data.questionDataList[cindex];
+      content.push({
+        cmsItemId: citem.id,
+        answer: citem.userAnswer,
+        state: citem.questionType == 'shortAnswer' ? 'none' : citem.isRight,
+        type: citem.questionType
+      })
+    }
+    const data = {
+      description: '',
+      icon: '',
+      state: 'Normal',
+      topicIdOrRefCode: String(topicId),
+      name: this.data.answerTitle,
+      content: JSON.stringify({
+        bookId: this.data.bookId,
+        userName: JSON.parse(wx.getStorageSync(app.config.userInfoKey)).name,
+        path: this.data.productLinkPath,
+        content
+      }),
+      type: 'Normal',
+      cmsTypeRefCode: '',
+      newDataListRequest: []
+    }
+    app.MG.ugc.newTopicMessage(data).then((res) => {
+      if (res) {
+        this.setData({
+          isShowDialog: true
+        })
+      }
+    })
+  },
+  // 鏂板缓瀛恡opicMessage
+  // newTopicSubMessage(parentId,topicId) {
+  //   const data = {
+  //     description: '',
+  //     icon: '',
+  //     parentId,
+  //     state: 'Normal',
+  //     topicIdOrRefCode: String(topicId),
+  //     name: this.data.answerTitle,
+  //     content: '',
+  //     type: 'Normal',
+  //     cmsTypeRefCode: '',
+  //     newDataListRequest: []
+  //   }
+  //   MG.ugc.newTopicMessage(data).then((res) => {
+  //     if (res) {
+
+  //     }
+  //   })
+  // },
 });
\ No newline at end of file
diff --git a/packageBookService/pages/bookServices/examination/examination.json b/packageBookService/pages/bookServices/examination/examination.json
index dd31697..45dcb7f 100644
--- a/packageBookService/pages/bookServices/examination/examination.json
+++ b/packageBookService/pages/bookServices/examination/examination.json
@@ -6,7 +6,8 @@
     "t-icon": "tdesign-miniprogram/icon/icon",
     "t-image": "tdesign-miniprogram/image/image",
     "t-button": "tdesign-miniprogram/button/button",
-    "t-loading": "tdesign-miniprogram/loading/loading"
+    "t-loading": "tdesign-miniprogram/loading/loading",
+    "join-dialog": "./components/joinGroupDialog/index"
   },
   "disableScroll": true
 }
\ No newline at end of file
diff --git a/packageBookService/pages/bookServices/examination/examination.wxml b/packageBookService/pages/bookServices/examination/examination.wxml
index fffff18..cb4691c 100644
--- a/packageBookService/pages/bookServices/examination/examination.wxml
+++ b/packageBookService/pages/bookServices/examination/examination.wxml
@@ -78,3 +78,8 @@
   overlay="{{false}}"
   bind:beforeleave="beforeleave"
 ></page-container>
+
+<!-- 鍔犲叆鐝骇寮圭獥 -->
+<join-dialog visible="{{visible}}" bind:joinClass="joinClass">
+
+</join-dialog>
\ No newline at end of file
diff --git a/packageBookService/pages/bookServices/examination/questionOptions/index.js b/packageBookService/pages/bookServices/examination/questionOptions/index.js
index 7c7ab59..47cb7cf 100644
--- a/packageBookService/pages/bookServices/examination/questionOptions/index.js
+++ b/packageBookService/pages/bookServices/examination/questionOptions/index.js
@@ -258,7 +258,8 @@
         // wx.navigateBack();
       } else if (
         this.properties.answerType == "option" ||
-        this.properties.answerType == "mock"
+        this.properties.answerType == "mock" ||
+        this.properties.answerType == "interaction"
       ) {
         if (this.properties.submitStatus) return wx.navigateBack();
         this.properties.questionDataList.forEach((item) => {
diff --git a/packageBookService/pages/bookServices/examination/questionOptions/index.wxml b/packageBookService/pages/bookServices/examination/questionOptions/index.wxml
index e44c9b0..70bf3e4 100644
--- a/packageBookService/pages/bookServices/examination/questionOptions/index.wxml
+++ b/packageBookService/pages/bookServices/examination/questionOptions/index.wxml
@@ -1,48 +1,105 @@
 <!--pages/bookServices/examination/questionOptions/index.wxml-->
-<view class="page-bottom" style="color: {{isNight ? '#fff' : '#000'}}; background-color:{{isNight ? '#202020' : '#fff'}}">
-  <view class="li-option" bind:tap="setCollect" style="color: {{isNight ? '#fff' : '#000'}};">
-    <image src="{{ questionDataList[currentIndex].isCollect ? '/static/images/bookService/detail/collecting.png' : isNight ? '/static/images/bookService/examination/wodeshoucang-w.png' : '/static/images/bookService/examination/collect.png'}}" />
+<view
+  class="page-bottom"
+  style="color: {{isNight ? '#fff' : '#000'}}; background-color:{{isNight ? '#202020' : '#fff'}}"
+>
+  <view
+    class="li-option"
+    bind:tap="setCollect"
+    style="color: {{isNight ? '#fff' : '#000'}};"
+    wx:if="{{answerType !== 'interaction'}}"
+  >
+    <image
+      src="{{ questionDataList[currentIndex].isCollect ? '/static/images/bookService/detail/collecting.png' : isNight ? '/static/images/bookService/examination/wodeshoucang-w.png' : '/static/images/bookService/examination/collect.png'}}"
+    />
     鏀惰棌
   </view>
-  <view class="li-option" bind:tap="handlePopup" style="color: {{isNight ? '#fff' : '#000'}};">
-    <image src="{{isNight ? '/static/images/bookService/examination/datika-w.png' : '/static/images/bookService/examination/questionCard.png'}}" />
+  <view
+    class="li-option"
+    bind:tap="handlePopup"
+    style="color: {{isNight ? '#fff' : '#000'}};"
+  >
+    <image
+      src="{{isNight ? '/static/images/bookService/examination/datika-w.png' : '/static/images/bookService/examination/questionCard.png'}}"
+    />
     绛旈鍗�
   </view>
-  <view class="li-option" bind:tap="setUpBtn" style="color: {{isNight ? '#fff' : '#000'}};">
-    <image src="{{isNight ? '/static/images/bookService/examination/setting-w.png' : '/static/images/bookService/examination/setting.png'}}" />
+  <view
+    class="li-option"
+    bind:tap="setUpBtn"
+    style="color: {{isNight ? '#fff' : '#000'}};"
+  >
+    <image
+      src="{{isNight ? '/static/images/bookService/examination/setting-w.png' : '/static/images/bookService/examination/setting.png'}}"
+    />
     璁剧疆
   </view>
-  <view class="li-option" bind:tap="resterBtn" wx:if="{{answerType == 'option' || (answerType == 'mock' && !submitStatus)}}" style="color: {{isNight ? '#fff' : '#000'}};">
-    <image src="{{isNight ? '/static/images/bookService/examination/chongzuo-w.png' : '/static/images/bookService/examination/reset.png'}}" />
+  <view
+    class="li-option"
+    bind:tap="resterBtn"
+    wx:if="{{answerType == 'option' || (answerType == 'mock' && !submitStatus)}}"
+    style="color: {{isNight ? '#fff' : '#000'}};"
+  >
+    <image
+      src="{{isNight ? '/static/images/bookService/examination/chongzuo-w.png' : '/static/images/bookService/examination/reset.png'}}"
+    />
     閲嶅仛
   </view>
   <view class="bottom-submit">
-    <t-button theme="primary" size="large" style="{{btnStyle}}" bind:tap="submitBtn">{{(answerType == 'option' || answerType == 'mock') && !submitStatus ?
-      '鎻愪氦' : '閫�鍑�'}}</t-button>
+    <t-button
+      theme="primary"
+      size="large"
+      style="{{btnStyle}}"
+      bind:tap="submitBtn"
+      >{{(answerType == 'option' || answerType == 'mock' || answerType ==
+      'interaction') && !submitStatus ? '鎻愪氦' : '閫�鍑�'}}</t-button
+    >
   </view>
 </view>
 
 <!-- 绛旈鍗� -->
-<t-popup visible="{{questionCardState}}" bind:visible-change="onVisibleChange" placement="bottom">
+<t-popup
+  visible="{{questionCardState}}"
+  bind:visible-change="onVisibleChange"
+  placement="bottom"
+>
   <view class="popup-block">
     <view class="popup-header">
       <view class="popup-title">绛旈鍗�</view>
     </view>
     <view class="question-explain">
-      <view class="explain-answered" wx:if="{{answerType == 'collectQuestion' || answerType == 'errorQuestion' || (answerType == 'option' && !submitStatus) || (answerType == 'mock' && !submitStatus)}}">
+      <view
+        class="explain-answered"
+        wx:if="{{answerType == 'collectQuestion' || answerType == 'errorQuestion' || (answerType == 'option' && !submitStatus) || (answerType == 'mock' && !submitStatus)}}"
+      >
         <text class="answered explain-color-box"></text>
         <text>宸茬瓟</text>
       </view>
-      <view class="explain-un-answered" wx:if="{{answerType == 'collectQuestion' || answerType == 'errorQuestion' || (answerType == 'option' && !submitStatus) || (answerType == 'mock' && !submitStatus)}}">
+      <view
+        class="explain-un-answered"
+        wx:if="{{answerType == 'collectQuestion' || answerType == 'errorQuestion' || (answerType == 'option' && !submitStatus) || (answerType == 'mock' && !submitStatus)}}"
+      >
         <text class="un-answered explain-color-box"></text>
         <text>鏈瓟</text>
       </view>
-      <view class="error-box" wx:if="{{((answerType == 'option' || answerType == 'mock') && submitStatus) || answerType == 'collectQuestion' || answerType == 'errorQuestion'}}">
-        <text class="explain-color-box" style="background-color: #ee1818"></text>
+      <view
+        class="error-box"
+        wx:if="{{((answerType == 'option' || answerType == 'mock') && submitStatus) || answerType == 'collectQuestion' || answerType == 'errorQuestion'}}"
+      >
+        <text
+          class="explain-color-box"
+          style="background-color: #ee1818"
+        ></text>
         <text>閿欒</text>
       </view>
-      <view class="correct-box" wx:if="{{((answerType == 'option' || answerType == 'mock') && submitStatus) || answerType == 'collectQuestion' || answerType == 'errorQuestion'}}">
-        <text class="explain-color-box" style="background-color: #1fbc1f"></text>
+      <view
+        class="correct-box"
+        wx:if="{{((answerType == 'option' || answerType == 'mock') && submitStatus) || answerType == 'collectQuestion' || answerType == 'errorQuestion'}}"
+      >
+        <text
+          class="explain-color-box"
+          style="background-color: #1fbc1f"
+        ></text>
         <text>姝g‘</text>
       </view>
     </view>
@@ -54,7 +111,16 @@
           <text class="title-text">{{item.catalogName}}</text>
         </view>
         <view class="question-list">
-          <view bind:tap="goQuestion" data-id="{{citem.id}}" wx:for="{{item.infoList}}" wx:for-item="citem" wx:for-index="cindex" wx:key="cindex" style="border: {{showId == citem.id ? '1px solid #ff6c00' : ''}}" class="question-box {{ citem.isUserAnswer ? 'answered' : 'un-answered' }} {{ ( ((answerType == 'option' || answerType == 'mock') && submitStatus || answerType == 'collectQuestion' || answerType == 'errorQuestion')  && citem.questionType !== 'shortAnswer' )  ? citem.isRight && citem.isComplete ? 'correct-box-color' : citem.isComplete && !citem.isRight ?  'error-box-color' : '' :''}} ">
+          <view
+            bind:tap="goQuestion"
+            data-id="{{citem.id}}"
+            wx:for="{{item.infoList}}"
+            wx:for-item="citem"
+            wx:for-index="cindex"
+            wx:key="cindex"
+            style="border: {{showId == citem.id ? '1px solid #ff6c00' : ''}}"
+            class="question-box {{ citem.isUserAnswer ? 'answered' : 'un-answered' }} {{ ( ((answerType == 'option' || answerType == 'mock') && submitStatus || answerType == 'collectQuestion' || answerType == 'errorQuestion')  && citem.questionType !== 'shortAnswer' )  ? citem.isRight && citem.isComplete ? 'correct-box-color' : citem.isComplete && !citem.isRight ?  'error-box-color' : '' :''}} "
+          >
             {{citem.number}}
           </view>
         </view>
@@ -64,7 +130,11 @@
 </t-popup>
 
 <!-- 璁剧疆 -->
-<t-popup visible="{{setUpPopup}}" bind:visible-change="onSetUpChange" placement="bottom">
+<t-popup
+  visible="{{setUpPopup}}"
+  bind:visible-change="onSetUpChange"
+  placement="bottom"
+>
   <view class="popup-block set-up-popup">
     <view class="popup-header">
       <view class="popup-title">璁剧疆</view>
@@ -81,27 +151,48 @@
           step="{{7}}"
           bind:change="onChangeSlider"
         /> -->
-        <slider value="{{sliderValue}}" min="{{28}}" max="{{48}}" step="{{7}}" activeColor="#ff6c00" bind:change="onChangeSlider" />
+        <slider
+          value="{{sliderValue}}"
+          min="{{28}}"
+          max="{{48}}"
+          step="{{7}}"
+          activeColor="#ff6c00"
+          bind:change="onChangeSlider"
+        />
       </view>
 
       <text>A+</text>
     </view>
     <!-- 妯″紡 -->
     <view>
-      <t-radio-group class="test-radio" t-class="horizontal-box" value="{{radioItem}}" bind:change="onRadioChange" style="margin: 0px">
+      <t-radio-group
+        class="test-radio"
+        t-class="horizontal-box"
+        value="{{radioItem}}"
+        bind:change="onRadioChange"
+        style="margin: 0px"
+      >
         <view class="card {{radioItem == 'daytime' ? 'card--active' : ''}}">
           <t-radio value="daytime" icon="none" borderless style="height: 100%">
             <view class="radio-content" slot="content">
-              <image src="{{ radioItem == 'daytime' ? '/static/images/bookService/examination/rijian-click.png' : '/static/images/bookService/examination/rijian.png'}}" />
-              <text style="color: {{radioItem == 'daytime' ? '#fff':''}};">鏃ラ棿妯″紡</text>
+              <image
+                src="{{ radioItem == 'daytime' ? '/static/images/bookService/examination/rijian-click.png' : '/static/images/bookService/examination/rijian.png'}}"
+              />
+              <text style="color: {{radioItem == 'daytime' ? '#fff':''}};"
+                >鏃ラ棿妯″紡</text
+              >
             </view>
           </t-radio>
         </view>
         <view class="card {{radioItem == 'night' ? 'card--active' : ''}}">
           <t-radio value="night" icon="none" borderless style="height: 100%">
             <view class="radio-content" slot="content">
-              <image src="{{ radioItem == 'night' ? '/static/images/bookService/examination/yejian-click.png' : '/static/images/bookService/examination/yejian.png'}}" />
-              <text style="color: {{radioItem == 'night' ? '#fff':''}};">澶滈棿妯″紡</text>
+              <image
+                src="{{ radioItem == 'night' ? '/static/images/bookService/examination/yejian-click.png' : '/static/images/bookService/examination/yejian.png'}}"
+              />
+              <text style="color: {{radioItem == 'night' ? '#fff':''}};"
+                >澶滈棿妯″紡</text
+              >
             </view>
           </t-radio>
         </view>
@@ -112,7 +203,13 @@
 
 <!-- 娴嬭瘯鎶ュ憡 -->
 
-<t-dialog class="test-report" visible="{{testReportState}}" confirm-btn="{{null}}" title="娴嬭瘯鎶ュ憡" bind:close="closeTestReportDialog">
+<t-dialog
+  class="test-report"
+  visible="{{testReportState}}"
+  confirm-btn="{{null}}"
+  title="娴嬭瘯鎶ュ憡"
+  bind:close="closeTestReportDialog"
+>
   <view slot="content" class="test-report">
     <view class="report-content-top">
       <view class="report-li">
@@ -125,24 +222,34 @@
       </view>
       <view class="report-li">
         <view class="report-li-left">鍏朵腑瀹㈣棰橈細</view>
-        <view class="report-li-right">{{subjectiveTotal}}閬擄紝鍒嗗�納{subjectiveGrade}}鍒�</view>
+        <view class="report-li-right"
+          >{{subjectiveTotal}}閬擄紝鍒嗗�納{subjectiveGrade}}鍒�</view
+        >
       </view>
       <view class="report-li">
         <view class="report-li-left">绛斿锛�</view>
-        <view class="report-li-right"><text class="correct-color">{{correctNum}}</text> 閬�</view>
+        <view class="report-li-right"
+          ><text class="correct-color">{{correctNum}}</text> 閬�</view
+        >
       </view>
       <view class="report-li">
         <view class="report-li-left">绛旈敊锛�</view>
-        <view class="report-li-right"><text class="error-color">{{subjectiveTotal - correctNum}}</text>
-          閬�</view>
+        <view class="report-li-right"
+          ><text class="error-color">{{subjectiveTotal - correctNum}}</text>
+          閬�</view
+        >
       </view>
       <view class="report-li">
         <view class="report-li-left">瀹㈣棰樺緱鍒嗭細</view>
-        <view class="report-li-right"><text class="score-color">{{subjectiveNum}}</text> 鍒�</view>
+        <view class="report-li-right"
+          ><text class="score-color">{{subjectiveNum}}</text> 鍒�</view
+        >
       </view>
     </view>
     <view class="report-content-bottom">
-      <t-button theme="primary" bind:tap="viewAnswer" style="width: 560rpx">鏌ョ湅绛旀涓庤В鏋�</t-button>
+      <t-button theme="primary" bind:tap="viewAnswer" style="width: 560rpx"
+        >鏌ョ湅绛旀涓庤В鏋�</t-button
+      >
     </view>
   </view>
-</t-dialog>
\ No newline at end of file
+</t-dialog>
diff --git a/packageBookService/pages/bookServices/examination/questionSchedule/index.wxml b/packageBookService/pages/bookServices/examination/questionSchedule/index.wxml
index 54f3b66..8c19402 100644
--- a/packageBookService/pages/bookServices/examination/questionSchedule/index.wxml
+++ b/packageBookService/pages/bookServices/examination/questionSchedule/index.wxml
@@ -1,6 +1,6 @@
 <!--pages/bookServices/examination/questionSchedule/questionSchedule.wxml-->
 <view
-  wx:if="{{((answerType == 'option' || answerType == 'mock') && !submitStatus) || answerType == 'collectQuestion' || answerType =='errorQuestion'}}"
+  wx:if="{{((answerType == 'option' || answerType == 'mock' || answerType == 'interaction') && !submitStatus) || answerType == 'collectQuestion' || answerType =='errorQuestion'}}"
   class="schedule"
   id="schedule"
   style="background-color:{{isNight ? '#1a1a1a' : '#fff'}}"
@@ -10,16 +10,14 @@
     <view
       class="question-schedule"
       style="color: {{isNight ? '#fff' : '#000'}};"
-      >{{(answerType == 'option' || answerType == 'mock') ? '绛旈杩涘害' :
-      answerType == 'collectQuestion' ? '鏀惰棌鏁伴噺' : '閿欓鏁伴噺' }}<text
-        class="parimary-color question-num"
-        >{{ready}}</text
-      >
+      >{{(answerType == 'option' || answerType == 'mock' || answerType ==
+      'interaction') ? '绛旈杩涘害' : answerType == 'collectQuestion' ? '鏀惰棌鏁伴噺'
+      : '閿欓鏁伴噺' }}<text class="parimary-color question-num">{{ready}}</text>
       <text>/{{questionList.length}}</text>
     </view>
     <view
       class="remainder"
-      wx:if="{{!submitStatus && (answerType == 'option' || answerType == 'mock')}}"
+      wx:if="{{!submitStatus && (answerType == 'option' || answerType == 'mock' || answerType == 'interaction')}}"
       style="color:  {{isNight ? '#fff' : '#000'}};"
     >
       <view class="remainder-text">鍓╀綑鏃堕棿 </view>
diff --git a/packageCourse/components/baseClass/index.js b/packageCourse/components/baseClass/index.js
new file mode 100644
index 0000000..43b9f53
--- /dev/null
+++ b/packageCourse/components/baseClass/index.js
@@ -0,0 +1,164 @@
+// packageCourse/components/baseClass/index.js
+const app = getApp()
+import moment from "moment"
+import {
+  getPublicImage
+} from '../../../assets/js/middleGround/tool'
+Component({
+  /**
+   * 缁勪欢鐨勫睘鎬у垪琛�
+   */
+  properties: {
+    classId: {
+      type: Number,
+      default: 0
+    },
+    bookRefCode: {
+      type: String,
+      default: ''
+    }
+  },
+
+  /**
+   * 缁勪欢鐨勫垵濮嬫暟鎹�
+   */
+  data: {
+    noticeList: [],
+    detailInfo: null,
+    messageInfo: null,
+    homeworkCount: 0,
+    userData: null,
+    bookData: null,
+    defaultCmsPath: ''
+  },
+
+  ready() {
+    const data = wx.getStorageSync('website-front-userInfo')
+    if (data) {
+      this.setData({
+        userData: JSON.parse(data),
+        defaultCmsPath: this.properties.bookRefCode
+      })
+    }
+    this.getData()
+  },
+
+  /**
+   * 缁勪欢鐨勬柟娉曞垪琛�
+   */
+  methods: {
+    // 鑾峰彇鐝骇
+    getData() {
+      app.MG.edu
+        .getCourseClass({
+          ClassIdOrRefCode: String(this.properties.classId)
+        })
+        .then((res) => {
+          if (res) {
+            res.bookName = res.linkProductDto.product.name
+            res.bookId = res.linkProductDto.product.id
+            res.bookIcon = getPublicImage(res.linkProductDto.product.icon, 100)
+            res.classTime =
+              moment(res.beginDate).format('YYYY.MM.DD') +
+              '--' +
+              moment(res.endDate).format('YYYY.MM.DD')
+          }
+          this.setData({
+            detailInfo: res
+          })
+          this.getTopicInfo()
+          this.getBookDetail(res.bookId)
+        })
+    },
+
+    // 鑾峰彇鏁欐潗璇︽儏
+    getBookDetail(shopId) {
+      let query = {
+        path: this.data.defaultCmsPath,
+        queryType: '*',
+        productId: String(shopId),
+        storeInfo: this.data.defaultCmsPath,
+        coverSize: {
+          height: 300,
+          width: 210
+        },
+        fields: {
+          seriesName: [],
+          author: [],
+          isbn: [],
+          publicationDate: []
+        }
+      }
+      app.MG.store.getProductDetail(query).then(async (res) => {
+        if (res?.datas) {
+          if (!res.datas.author) {
+            res.datas.author = '-'
+          }
+          this.setData({
+            bookData: res.datas
+          })
+        }
+
+      })
+    },
+
+    // 鑾峰彇topic
+    getTopicInfo() {
+      const pramas = {
+        classId: this.properties.classId,
+        refCodes: [app.config.refCodes.message]
+      }
+      app.MG.edu.getClassTopic(pramas).then((res) => {
+        const data = res.find((item) => item.refCode == app.config.refCodes.message)
+        this.setData({
+          messageInfo: data
+        })
+        if (data.id) {
+          wx.setStorageSync('messageId', data.id)
+          this.getNotice()
+        }
+      })
+    },
+
+    // 鑾峰彇鐝骇閫氱煡
+    getNotice() {
+      const data = {
+        start: 0,
+        size: 3,
+        appRefCode: app.config.appRefCode,
+        topicIdOrRefCode: String(this.data.messageInfo.id),
+        sort: {
+          type: 'Desc',
+          field: 'CreateDate',
+          subSorts: []
+        }
+      }
+      app.MG.ugc.getTopicMessageList(data).then((res) => {
+        const list = res.datas.map((item) => {
+          return {
+            ...item,
+            createDate: moment(item.createDate).format('YYYY-MM-DD')
+          }
+        })
+        this.setData({
+          noticeList: list
+        })
+      })
+    },
+
+    //澶嶅埗
+    copyCode() {
+      wx.setClipboardData({
+        data: this.data.detailInfo.refCode,
+        success(res) {
+          wx.hideToast()
+          wx.showToast({
+            title: '閭�璇风爜宸插鍒�',
+            duration: 1000,
+            icon: 'none',
+          })
+        }
+      })
+    }
+  }
+})
\ No newline at end of file
diff --git a/packageCourse/components/baseClass/index.json b/packageCourse/components/baseClass/index.json
new file mode 100644
index 0000000..01073a9
--- /dev/null
+++ b/packageCourse/components/baseClass/index.json
@@ -0,0 +1,9 @@
+{
+  "component": true,
+  "navigationBarTitleText": "鍩烘湰淇℃伅",
+  "usingComponents": {
+    "t-avatar": "tdesign-miniprogram/avatar/avatar",
+    "t-button": "tdesign-miniprogram/button/button",
+    "empty": "/components/empty/index"
+  }
+}
\ No newline at end of file
diff --git a/packageCourse/components/baseClass/index.wxml b/packageCourse/components/baseClass/index.wxml
new file mode 100644
index 0000000..2f198cb
--- /dev/null
+++ b/packageCourse/components/baseClass/index.wxml
@@ -0,0 +1,52 @@
+<!--packageCourse/components/baseClass/index.wxml-->
+<view class="baseContent">
+  <view class="pubCss">
+    <view class="title">鐝骇姒傝</view>
+    <view class="statics">
+      <view class="classCout">
+        <text>鐝骇浜烘暟</text>
+        <text style="color: #ff6d00">{{ detailInfo.memberCount }} / {{ detailInfo.maxUserCount }}</text>
+      </view>
+      <view class="classCout">
+        <text>浣滀笟娆℃暟</text>
+        <text style="color: #ff6d00">{{homeworkCount}}</text>
+      </view>
+    </view>
+  </view>
+  <view class="pubCss">
+    <view class="roleInfo">
+      <text class="title" wx:if="{{userData.role == 'Teacher'}}">鐝骇鍔╂暀</text>
+      <text class="title" wx:else>鐝骇瀛︾敓</text>
+      <t-button style="margin: 0;" size="large" bindtap="copyCode" size="extra-small" variant="outline">閭�璇风爜</t-button>
+    </view>
+    <view class="userInfo">
+      <t-avatar wx:if="{{userData.icon}}" class="avatar-example" size="small" image="{{userData.icon}}" />
+      <text class="user">{{userData.name}}</text>
+    </view>
+  </view>
+  <view class="pubCss">
+    <view class="title">璇剧▼鏁欐潗</view>
+    <view class="bookData">
+      <view class="bookText">
+        <text>{{detailInfo.bookName}}</text>
+        <text>浣滆�咃細{{bookData.author}}</text>
+        <text>ISBN锛歿{bookData.isbn}}</text>
+      </view>
+      <image wx:if="{{detailInfo.bookIcon}}" class="bookIcon" src="{{detailInfo.bookIcon}}" mode="" />
+      <image wx:else class="bookIcon" src="/static/images/default-book-img.png" mode="" />
+    </view>
+  </view>
+  <view class="pubCss">
+    <view class="title">寮�璇炬椂闂�</view>
+    <view class="courseTime">{{detailInfo.classTime}}</view>
+  </view>
+  <view class="pubCss">
+    <view class="title">鐝骇閫氱煡</view>
+    <view class="notice" wx:if="{{noticeList.length > 0}}">
+      <view class="notice-title" wx:for="{{noticeList}}" wx:key="index">{{item.name}}</view>
+    </view>
+    <view class="noData" wx:else>
+      <empty />
+    </view>
+  </view>
+</view>
\ No newline at end of file
diff --git a/packageCourse/components/baseClass/index.wxss b/packageCourse/components/baseClass/index.wxss
new file mode 100644
index 0000000..6a149be
--- /dev/null
+++ b/packageCourse/components/baseClass/index.wxss
@@ -0,0 +1,109 @@
+/* packageCourse/components/baseClass/index.wxss */
+.baseContent {
+  width: 100%;
+  height: 100%;
+  font-size: 28rpx;
+  overflow: auto;
+}
+
+.title {
+  font-size: 28rpx;
+  font-weight: 700;
+  padding: 20rpx;
+  box-sizing: border-box;
+  background-color: #f8f8f8;
+  margin-bottom: 10rpx;
+}
+
+.statics {
+  width: 100%;
+  display: flex;
+  justify-content: space-around;
+  align-items: center;
+  padding: 20rpx;
+  box-sizing: border-box;
+}
+
+.statics .classCout {
+  width: 100px;
+  height: 60px;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: space-around;
+  border: 1rpx solid #999;
+  border-radius: 10rpx;
+}
+
+.pubCss {
+  width: 100%;
+  padding: 20rpx 0;
+  box-sizing: border-box;
+}
+
+.roleInfo {
+  display: flex;
+  justify-content: flex-start;
+  align-items: center;
+  background-color: #f8f8f8;
+}
+
+.userInfo {
+  display: flex;
+  justify-content: flex-start;
+  align-items: center;
+  padding: 20rpx 30rpx;
+  box-sizing: border-box;
+}
+
+.user {
+  margin-left: 20rpx;
+}
+
+.bookInfo {
+  width: 100%;
+  padding: 20rpx;
+  box-sizing: border-box;
+}
+
+.bookData {
+  width: 100%;
+  height: 200rpx;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 0 30rpx;
+  box-sizing: border-box;
+}
+
+.bookText {
+  flex: 1;
+  height: 100%;
+  display: flex;
+  flex-direction: column;
+  justify-content: space-around;
+  align-items: flex-start;
+  font-size: 26rpx;
+  overflow: hidden;
+}
+
+.bookIcon {
+  width: 180rpx;
+  height: 230rpx;
+}
+
+.courseTime {
+  padding: 20rpx 30rpx;
+  box-sizing: border-box;
+}
+
+.notice {
+  padding: 20rpx 30rpx;
+  box-sizing: border-box;
+  font-size: 26rpx;
+}
+
+.noData {
+  display: flex;
+  justify-content: center;
+}
\ No newline at end of file
diff --git a/packageCourse/components/questionDom/index.js b/packageCourse/components/questionDom/index.js
new file mode 100644
index 0000000..0066362
--- /dev/null
+++ b/packageCourse/components/questionDom/index.js
@@ -0,0 +1,46 @@
+// packageCourse/components/questionDom/index.js
+Component({
+  /**
+   * 缁勪欢鐨勫睘鎬у垪琛�
+   */
+  properties: {
+    questionList: {
+      type: Array,
+      default: []
+    },
+    noCheckbox: {
+      type: Boolean,
+      default: false
+    },
+    isDelete: {
+      type: Boolean,
+      default: false
+    },
+    isPreview: {
+      type: Boolean,
+      default: false
+    },
+    isJudge: {
+      type: Boolean,
+      default: false
+    },
+  },
+
+  /**
+   * 缁勪欢鐨勫垵濮嬫暟鎹�
+   */
+  data: {
+
+  },
+
+  ready() {
+    console.log(this.properties.questionList, 'tweuywteuwyteu')
+  },
+
+  /**
+   * 缁勪欢鐨勬柟娉曞垪琛�
+   */
+  methods: {
+
+  }
+})
\ No newline at end of file
diff --git a/packageCourse/components/questionDom/index.json b/packageCourse/components/questionDom/index.json
new file mode 100644
index 0000000..574539b
--- /dev/null
+++ b/packageCourse/components/questionDom/index.json
@@ -0,0 +1,11 @@
+{
+  "component": true,
+  "usingComponents": {
+    "t-checkbox": "tdesign-miniprogram/checkbox/checkbox",
+    "t-checkbox-group": "tdesign-miniprogram/checkbox-group/checkbox-group",
+    "t-input": "tdesign-miniprogram/input/input",
+    "t-textarea": "tdesign-miniprogram/textarea/textarea",
+    "t-radio": "tdesign-miniprogram/radio/radio",
+    "t-radio-group": "tdesign-miniprogram/radio-group/radio-group"
+  }
+}
\ No newline at end of file
diff --git a/packageCourse/components/questionDom/index.wxml b/packageCourse/components/questionDom/index.wxml
new file mode 100644
index 0000000..87bd64d
--- /dev/null
+++ b/packageCourse/components/questionDom/index.wxml
@@ -0,0 +1,54 @@
+<!--packageCourse/components/questionDom/index.wxml-->
+<view class="questionDom">
+  <view class="list-item" wx:for="{{questionList}}" wx:for-item="pitem" wx:key="pindex">
+    <view class="list-item-title">
+      {{ pitem.name }}
+      <text wx:if="isPreview">(鍏眥{ pitem.data.length }}棰�<text wx:if="{{pitem.totalScore>0}}">锛屾�诲垎锛歿{ pitem.totalScore }} 鍒�</text>)</text>
+    </view>
+    <view class="list-item-box" wx:for="{{pitem.data}}" wx:for-item="item" wx:key="index">
+      <view class="list-item-box-title-box">
+        <t-checkbox wx:if="{{noCheckbox}}" block="{{false}}" value="{{item.isCheck}}">
+          <view Slot='label'>
+            <rich-text nodes="{{item.questionStem.stemTxt}}"></rich-text>
+          </view>
+        </t-checkbox>
+        <view class="list-item-box-title" wx:else>
+          <p class="questionT">
+            <text>{{index+1}}銆�</text>
+            <rich-text nodes="{{item.questionStem.stemTxt}}"></rich-text>
+          </p>
+        </view>
+      </view>
+      <view class="questionData">
+        <view class="shortAnswer" wx:if="{{item.questionType == 'shortAnswer'}}">
+          <t-textarea disabled placeholder="{{item.userAnswer}}" />
+        </view>
+        <view class="discuss" wx:if="{{item.questionType == 'discuss'}}">
+          <t-textarea disabled placeholder="{{item.userAnswer}}" />
+        </view>
+        <view class="discuss" wx:if="{{item.questionType == 'completion'}}">
+          <t-textarea disabled placeholder="{{item.userAnswer}}" />
+        </view>
+        <view class="judge" wx:if="{{item.questionType == 'judge'}}">
+          <t-radio-group>
+            <t-radio block="{{false}}" wx:for="{{item.questionOption}}" wx:for-item="{{ritem}}" wx:index="{{ritem.index}}" label="{{ritem.value}}" value="{{ritem.value}}" />
+          </t-radio-group>
+        </view>
+        <view class="singleChoice" wx:if="{{item.questionType == 'singleChoice'}}">
+          <t-radio-group>
+            <t-radio block="{{false}}" wx:for="{{item.questionOption}}" wx:for-item="{{ritem}}" wx:index="{{ritem.index}}" label="{{ritem.value}}" value="{{ritem.value}}">
+              <text>{{ritem.value}}</text>. <text>{{ritem.txt}}</text>
+            </t-radio>
+          </t-radio-group>
+        </view>
+        <view class="multipleChoice" wx:if="{{item.questionType == 'multipleChoice'}}">
+          <t-checkbox-group>
+            <t-checkbox block="{{false}}" wx:for="{{item.questionOption}}" wx:for-item="{{mitem}}" wx:index="{{mitem.index}}" label="{{mitem.value}}" value="{{mitem.value}}">
+              <text>{{mitem.value}}</text>. <text>{{mitem.txt}}</text>
+            </t-checkbox>
+          </t-checkbox-group>
+        </view>
+      </view>
+    </view>
+  </view>
+</view>
\ No newline at end of file
diff --git a/packageCourse/components/questionDom/index.wxss b/packageCourse/components/questionDom/index.wxss
new file mode 100644
index 0000000..5f8f0cc
--- /dev/null
+++ b/packageCourse/components/questionDom/index.wxss
@@ -0,0 +1,29 @@
+/* packageCourse/components/questionDom/index.wxss */
+
+.questionDom {
+  padding: 10rpx 20rpx;
+  box-sizing: border-box;
+}
+
+.list-item-title {
+  margin-bottom: 20rpx;
+}
+
+.list-item-box-title-box {
+  margin-bottom: 20rpx;
+}
+
+.questionT {
+  display: flex;
+  align-items: flex-start;
+}
+
+.shortAnswer,
+.discuss {
+  padding: 20rpx;
+  line-height: 22px;
+  border: 1px solid #eee;
+  border-radius: 5px;
+  font-size: 28rpx;
+  box-sizing: border-box;
+}
\ No newline at end of file
diff --git a/packageCourse/components/studentManage/index.js b/packageCourse/components/studentManage/index.js
new file mode 100644
index 0000000..519a3c3
--- /dev/null
+++ b/packageCourse/components/studentManage/index.js
@@ -0,0 +1,257 @@
+// packageCourse/components/studentManage/index.js
+const app = getApp();
+import moment from "moment"
+import {
+  getPublicImage
+} from '../../../assets/js/middleGround/tool'
+Component({
+  /**
+   * 缁勪欢鐨勫睘鎬у垪琛�
+   */
+  properties: {
+    classId: {
+      type: Number,
+      default: 0
+    },
+  },
+
+  /**
+   * 缁勪欢鐨勫垵濮嬫暟鎹�
+   */
+  data: {
+    userList: [],
+    page: 1,
+    limit: 10,
+    total: 0,
+    searchKey: '',
+    currentIdentity: null,
+    showConfirm: false,
+    radioVal: 'RefCode',
+    roleList: [{
+      name: '瀛︾敓',
+      value: 'RefCode'
+    }, {
+      name: '鍔╂暀',
+      value: 'Teacher'
+    }],
+    // 鍔犺浇鍙傛暟
+    bottomLoading: false,
+    isMoreData: false,
+    // 杩斿洖椤堕儴
+    isBackTop: false,
+    setScrollValue: 0,
+    skeletonLoding: true
+  },
+
+  ready() {
+    this.getStudentList()
+  },
+  /**
+   * 缁勪欢鐨勬柟娉曞垪琛�
+   */
+  methods: {
+    // 鑾峰彇瀛︾敓鍒楄〃
+    getStudentList(isReachBottom) {
+      const data = {
+        start: (this.data.page - 1) * this.data.limit,
+        size: this.data.limit,
+        searchList: this.data.searchKey ? [{
+          keywords: this.data.searchKey,
+          field: 'Name',
+          compareType: 'Contains'
+        }] : [],
+        groupId: this.properties.classId
+      }
+      app.MG.identity.getGroupUserList(data).then((res) => {
+        const {
+          datas,
+          totalSize
+        } = res
+        if (datas.length > 0) {
+          let list = datas.map((item, index) => {
+            if (item.linkType == 'Creator') {
+              const userInfo = item.appUser?.infoList?.find((citem) => citem.type == 'teacherInfo')
+              item.appUser.name = userInfo.name
+              item.appUser.icon = userInfo.icon
+              if (userInfo?.data) {
+                const iconData = JSON.parse(userInfo.data)
+                item.appUser.icon = getPublicImage(iconData?.relevantCertificates[0]?.md5, 100) ?? ''
+              }
+            }
+            if (item.linkType == 'RefCode' || item.linkType == 'Teacher') {
+              let userInfo = null
+              const wechatData = item.appUser?.infoList?.find((citem) => citem.type == 'WeChat')
+              const defaultData = item.appUser?.infoList?.find((citem) => citem.type == 'Default')
+              userInfo = defaultData
+              if (wechatData?.name) {
+                userInfo = wechatData
+              }
+              item.appUser.name = userInfo.name
+              item.appUser.icon = userInfo.icon
+            }
+            return {
+              ...item,
+              index: index + 1,
+              createDate: moment(item.createDate).format('YYYY-MM-DD')
+            }
+          })
+          //瑙﹀簳鍔犺浇鏂版暟鎹苟淇濈暀鑰佹暟鎹�
+          if (isReachBottom) {
+            list = [...this.data.courseList, ...list] //灏嗘柊鏁版嵁鍔犲叆鑰佹暟鎹腑
+          }
+          this.setData({
+            userList: list,
+            total: res.totalSize,
+            skeletonLoding: false,
+            bottomLoading: false
+          })
+        }
+      })
+    },
+    /**
+     * 椤甸潰鐩稿叧浜嬩欢澶勭悊鍑芥暟--鐩戝惉鐢ㄦ埛涓嬫媺鍔ㄤ綔
+     */
+    onPullDownRefresh() {
+      if (this._freshing) return
+      this.setData({
+        page: 1,
+        bottomLoading: false,
+        isMoreData: false
+      })
+      setTimeout(() => {
+        this._freshing = true;
+        this.setData({
+          triggered: false,
+        })
+        this.getStudentList();
+        this._freshing = false
+      }, 500);
+    },
+    /**
+     * 椤甸潰涓婃媺瑙﹀簳浜嬩欢鐨勫鐞嗗嚱鏁�
+     */
+    onReachBottom() {
+      if (this.data.pageCourse.total > this.data.courseList.length) {
+        this.setData({
+          page: this.data.pageCourse.page + 1,
+          bottomLoading: true,
+          isMoreData: false
+        })
+      } else {
+        this.setData({
+          bottomLoading: false,
+          isMoreData: true
+        })
+        return false;
+      }
+      this.getStudentList(true);
+    },
+    // 鐩戝惉婊氬姩璺濈
+    onPageScroll(e) {
+      if (e && e.scrollTop >= 1000) {
+        this.setData({
+          isBackTop: true
+        })
+      } else {
+        this.setData({
+          isBackTop: false
+        })
+      }
+    },
+
+    selectIdentity(e) {
+      const {
+        item
+      } = e.currentTarget.dataset
+      this.setData({
+        showConfirm: true,
+        currentIdentity: item
+      })
+    },
+
+    onChangeVal(e) {
+      this.setData({
+        radioVal: e.detail.value
+      });
+    },
+
+    // 绉婚櫎瀛︾敓
+    removeStudent(e) {
+      const {
+        item
+      } = e.currentTarget.dataset
+      const data = {
+        groupId: this.properties.classId,
+        appUserIds: [item.appUser.id]
+      }
+      app.MG.identity.removeAppUserFromGroup(data).then((res) => {
+        if (res) {
+          wx.showToast({
+            title: '宸茬Щ闄�',
+            duration: 1000,
+            icon: 'none',
+          })
+          this.getStudentList()
+          this.newNotice(item, 'remove')
+        }
+      })
+    },
+
+    cancle() {
+      this.setData({
+        showConfirm: false,
+        radioVal: 'RefCode'
+      })
+    },
+
+    // 鏇存柊鐘舵��
+    updateStateNormal() {
+      const data = {
+        groupId: this.properties.classId,
+        requests: [{
+          linkId: this.data.currentIdentity.linkId,
+          linkType: this.data.radioVal,
+          state: 'Normal',
+          groupState: 'Normal'
+        }]
+      }
+      app.MG.identity.updateAppUserGroupLink(data).then((res) => {
+        if (res) {
+          wx.showToast({
+            title: '宸查�氳繃',
+            duration: 1000,
+            icon: 'success',
+          })
+          this.cancle()
+          this.getStudentList()
+          this.newNotice(this.data.currentIdentity, 'success')
+        }
+      })
+    },
+  },
+  // 鏂板缓閫氱煡
+  newNotice(item, type) {
+    const messageId = wx.getStorageSync('messageId')
+    const str = type == 'success' ? item.appUser.name + '--鍔犲叆鐝骇' : item.appUser.name + '--宸茶绉婚櫎鐝骇'
+    if (!messageId) {
+      return false
+    }
+    const data = {
+      description: '',
+      icon: '',
+      state: 'Normal',
+      topicIdOrRefCode: String(messageId),
+      name: str,
+      content: "",
+      type: 'Normal',
+      cmsTypeRefCode: '',
+      newDataListRequest: []
+    }
+    app.MG.ugc
+      .newTopicMessage(data)
+      .then()
+      .catch((err) => {
+        console.log(err)
+      })
+  }
+})
\ No newline at end of file
diff --git a/packageCourse/components/studentManage/index.json b/packageCourse/components/studentManage/index.json
new file mode 100644
index 0000000..4c3b9c4
--- /dev/null
+++ b/packageCourse/components/studentManage/index.json
@@ -0,0 +1,18 @@
+{
+  "component": true,
+  "navigationBarTitleText": "瀛︾敓绠$悊",
+  "usingComponents": {
+    "t-search": "tdesign-miniprogram/search/search",
+    "t-input": "tdesign-miniprogram/input/input",
+    "empty": "/components/empty/index",
+    "t-skeleton": "tdesign-miniprogram/skeleton/skeleton",
+    "t-back-top": "tdesign-miniprogram/back-top/back-top",
+    "t-avatar": "tdesign-miniprogram/avatar/avatar",
+    "t-button": "tdesign-miniprogram/button/button",
+    "t-loading": "tdesign-miniprogram/loading/loading",
+    "t-popup": "tdesign-miniprogram/popup/popup",
+    "t-icon": "tdesign-miniprogram/icon/icon",
+    "t-radio": "tdesign-miniprogram/radio/radio",
+    "t-radio-group": "tdesign-miniprogram/radio-group/radio-group"
+  }
+}
\ No newline at end of file
diff --git a/packageCourse/components/studentManage/index.wxml b/packageCourse/components/studentManage/index.wxml
new file mode 100644
index 0000000..8d9f419
--- /dev/null
+++ b/packageCourse/components/studentManage/index.wxml
@@ -0,0 +1,74 @@
+<!--packageCourse/pages/course/index.wxml-->
+<view class="contentBox" wx:if="{{!skeletonLoding}}">
+  <view class="header">
+    <t-search style="flex:1" value="{{searchKey}}" bind:clear="changeHandle" bind:submit="changeHandle" placeholder="鎼滅储鍚嶇О" clearable />
+  </view>
+  <view class="contentList" wx:if="{{userList.length > 0}}">
+    <scroll-view class="scroll" class="content" bind:scroll="onPageScroll" model:scroll-top="{{setScrollValue}}" scroll-y refresher-enabled="{{true}}" lower-threshold="{{80}}" refresher-threshold="{{80}}" refresher-default-style="none" refresher-triggered="{{triggered}}" bindrefresherpulling="{{refresh.onPulling}}" bindrefresherrefresh="onPullDownRefresh" bindscrolltolower="onReachBottom">
+      <view slot="refresher" class="refresh-container">
+        <view class="loading">
+          <t-loading theme="circular" size="40rpx" text="姝e湪鍒锋柊..." class="wrapper" />
+        </view>
+      </view>
+      <view class="userList" wx:for="{{userList}}" wx:key="index">
+        <view class="userInfo">
+          <t-avatar class="avatar-example" size="small" image="{{item.appUser.icon}}" />
+          <text class="user">{{item.appUser.name}}</text>
+        </view>
+        <view>
+          <t-button bindtap="selectIdentity" data-item="{{item}}" style="margin: 0;color: green;" size="extra-small" wx:if="{{item.state != 'Normal' && item.linkType != 'Creator'}}" variant="text">閫氳繃</t-button>
+          <t-button bindtap="removeStudent" data-item="{{item}}" style="margin: 0;color: red;" size="extra-small" wx:if="{{item.linkType != 'Creator' }}" variant="text">绉婚櫎</t-button>
+          <text style="color: #ff6d00;" wx:if="{{item.linkType == 'Creator'}}">鍒涘缓浜�</text>
+        </view>
+      </view>
+      <view class="bottom-loading" wx:if="{{bottomLoading}}">
+        <t-loading theme="circular" size="40rpx" text="鍔犺浇涓�..." class="wrapper" />
+      </view>
+      <view class="bottom-loading" style="color: #ccc;font-size: 28rpx;" wx:if="{{isMoreData}}">
+        <text>娌℃湁鏇村浜�</text>
+      </view>
+    </scroll-view>
+  </view>
+  <view class="content" wx:if="{{userList.length == 0}}">
+    <empty />
+  </view>
+</view>
+<t-popup visible="{{showConfirm}}" usingCustomNavbar bind:visible-change="onVisibleChange" placement="center">
+  <view class="block--select">
+    <view class="block-select-title">璁剧疆鐢ㄦ埛瑙掕壊</view>
+    <view class="block-select-radio">
+      <t-radio-group class="groupRadio" value="{{radioVal}}" borderless t-class="box" bind:change='onChangeVal'>
+        <view wx:for="{{roleList}}" wx:key="index">
+          <t-radio class="radioItem" style="font-size: 30rpx;" block="{{false}}" label="{{item.name}}" value="{{item.value}}" />
+        </view>
+      </t-radio-group>
+    </view>
+    <view class="block-select-confirm">
+      <t-button style="padding: 0 25px; margin:0 15px;" size="small" bindtap="cancle" variant="outline">鍙栨秷</t-button>
+      <t-button style="padding: 0 25px; margin:0;" size="small" bindtap="updateStateNormal">纭</t-button>
+    </view>
+  </view>
+</t-popup>
+
+<!-- 楠ㄦ灦灞� -->
+<view wx:if="{{skeletonLoding}}">
+  <view class="group" wx:for="{{10}}" wx:key="index">
+    <t-skeleton class="group-avatar" rowCol="{{[{ size: '96rpx', type: 'circle' }]}}" loading></t-skeleton>
+    <t-skeleton class="group-content" rowCol="{{[{ width: '50%' }, { width: '100%' }]}}" loading></t-skeleton>
+  </view>
+</view>
+
+
+<wxs module="refresh">
+  module.exports = {
+    onPulling: function (evt, instance) {
+      var p = Math.min(evt.detail.dy / 80, 1)
+      var view = instance.selectComponent('.refresh-container')
+      view.setStyle({
+        opacity: p,
+        transform: "scale(" + p + ")"
+      })
+    }
+  }
+
+</wxs>
\ No newline at end of file
diff --git a/packageCourse/components/studentManage/index.wxss b/packageCourse/components/studentManage/index.wxss
new file mode 100644
index 0000000..33a1628
--- /dev/null
+++ b/packageCourse/components/studentManage/index.wxss
@@ -0,0 +1,132 @@
+/* packageCourse/pages/course/index.wxss */
+
+.demo-section__content {
+  margin-top: 32rpx;
+  margin-bottom: 48rpx;
+}
+
+.contentBox {
+  width: 100%;
+  height: calc(100vh - env(safe-area-inset-bottom));
+  background-color: #eee;
+  font-size: 28rpx;
+}
+
+.refresh-container {
+  display: block;
+  width: 100vw;
+}
+
+.loading {
+  display: block;
+  width: 100%;
+  height: 180rpx;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+
+.bottom-loading {
+  width: 100vw;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  height: 100rpx;
+  padding-bottom: env(safe-area-inset-bottom);
+}
+
+.header {
+  width: 100%;
+  height: 55px;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 20rpx;
+  box-sizing: border-box;
+  border-top: 1rpx solid #eee;
+  border-bottom: 1rpx solid #eee;
+  background-color: #fff;
+}
+
+.header .t-search__input-box {
+  height: 70rpx !important;
+  font-size: 28rpx;
+}
+
+.contentList {
+  width: 100%;
+  height: calc(100% - 55px);
+  background-color: #fff;
+}
+
+.content {
+  height: 100%;
+}
+
+.userList {
+  padding: 20rpx;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  box-sizing: border-box;
+  border-bottom: 1rpx solid #eee;
+}
+
+.userInfo {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.user {
+  margin-left: 20rpx;
+}
+
+.block--select {
+  width: 85vw;
+  height: 180px;
+  border-radius: 10rpx;
+}
+
+.block-select-title {
+  font-size: 30rpx;
+  padding: 20rpx;
+  box-sizing: border-box;
+  border-bottom: 1px solid #eee;
+}
+
+.block-select-radio .groupRadio {
+  display: flex;
+  justify-content: flex-start;
+  align-items: center;
+  padding: 70rpx 20rpx;
+  box-sizing: border-box;
+}
+
+.block-select-radio .radioItem {
+  margin: 0 20rpx;
+}
+
+.block-select-confirm {
+  display: flex;
+  justify-content: flex-end;
+  align-items: center;
+  padding: 0 20rpx;
+}
+
+
+/* gujia */
+.group {
+  display: flex;
+  align-items: center;
+  margin-top: 32rpx;
+  margin-bottom: 30rpx;
+}
+
+.group-avatar {
+  margin-right: 24rpx;
+}
+
+.group-content {
+  width: 566rpx;
+}
\ No newline at end of file
diff --git a/packageCourse/components/teaching/index.js b/packageCourse/components/teaching/index.js
new file mode 100644
index 0000000..876032f
--- /dev/null
+++ b/packageCourse/components/teaching/index.js
@@ -0,0 +1,296 @@
+// packageCourse/components/teaching/index.js
+const app = getApp()
+import moment from 'moment'
+Component({
+  /**
+   * 缁勪欢鐨勫睘鎬у垪琛�
+   */
+  properties: {
+    classId: {
+      type: Number,
+      default: 0
+    },
+    bookId: {
+      type: Number,
+      default: 0
+    },
+    rootCmsItemId: {
+      type: Number,
+      default: 0
+    },
+  },
+
+  /**
+   * 缁勪欢鐨勫垵濮嬫暟鎹�
+   */
+  data: {
+    searchKey: '',
+    cmsDataList: [],
+    teachInteractionInfo: null,
+    dataList: [],
+    loading: true
+  },
+
+  ready() {
+    this.getData()
+  },
+  /**
+   * 缁勪欢鐨勬柟娉曞垪琛�
+   */
+  methods: {
+    // 鎼滅储
+    changeHandle(e) {
+      const {
+        value
+      } = e.detail;
+      let cmsList = this.data.cmsDataList
+      this.setData({
+        cmsDataList: []
+      })
+      if (value) {
+        const data = cmsList.filter(item => item.name.indexOf(value) > -1);
+        this.setData({
+          cmsDataList: data
+        })
+      }
+      if (value == '') {
+        this.setData({
+          cmsDataList: [],
+          loading: true
+        })
+        this.getCmsList()
+      }
+    },
+    // 鑾峰彇鐝骇
+    getData() {
+      app.MG.edu
+        .getCourseClass({
+          ClassIdOrRefCode: String(this.properties.classId)
+        })
+        .then((res) => {
+          if (res) {
+            this.setData({
+              currentClass: res
+            })
+          }
+          this.getTopicInfo()
+        })
+    },
+    // 鑾峰彇鏁欏浜掑姩
+    getCmsList() {
+      app.MG.store
+        .getProductDetail({
+          path: '*',
+          queryType: '*',
+          productId: this.properties.bookId,
+          cmsPath: this.properties.rootCmsItemId
+        })
+        .then((res) => {
+          try {
+            const data = res.datas.cmsDatas[0]?.datas.find((item) => item.refCode == 'questionBank')
+            app.MG.store
+              .getProductDetail({
+                path: '*',
+                queryType: '*',
+                productId: this.properties.bookId,
+                cmsPath: data.productLinkPath
+              })
+              .then((res) => {
+                const dataTeach = res.datas.cmsDatas[0]?.datas.find(
+                  (item) => item.refCode == 'jsek_interaction'
+                )
+                app.MG.store
+                  .getProductDetail({
+                    path: '*',
+                    queryType: '*',
+                    productId: this.properties.bookId,
+                    cmsPath: dataTeach.productLinkPath
+                  })
+                  .then((res) => {
+                    let datas = res.datas.cmsDatas[0] ? res.datas.cmsDatas[0].datas : []
+                    const dataRes = []
+                    if (datas?.length > 0) {
+                      datas.forEach(async (item) => {
+                        const cmsRes = await app.MG.store
+                          .getProductDetail({
+                            path: '*',
+                            queryType: '*',
+                            productId: this.properties.bookId,
+                            cmsPath: item.productLinkPath
+                          })
+                        if (
+                          cmsRes.datas.cmsDatas[0].datas &&
+                          cmsRes.datas.cmsDatas[0].datas.length > 0
+                        ) {
+                          cmsRes.datas.cmsDatas[0].datas.forEach((item, i) => {
+                            item.subList = []
+                            item.updateDate = '-'
+                            if (this.data.dataList.length > 0) {
+                              this.data.dataList.forEach((mitem) => {
+                                if (mitem.name == item.name) {
+                                  item.updateDate = moment(mitem.updateDate).format(
+                                    'YYYY-MM-DD HH:mm:ss'
+                                  )
+                                  item.subList.push(mitem)
+                                }
+                              })
+                            }
+                            dataRes.push(item)
+                          })
+                        }
+                        const resList = dataRes.sort((a, b) => b.subList.length - a.subList.length)
+                        this.setData({
+                          cmsDataList: resList,
+                          loading: false
+                        })
+                      })
+                    }
+                  })
+              })
+          } catch (error) {
+            this.setData({
+              cmsDataList: [],
+              loading: false
+            })
+          }
+        })
+    },
+    // 鑾峰彇Messsagetopic
+    getTopicInfo() {
+      const pramas = {
+        classId: this.properties.classId,
+        refCodes: [app.config.refCodes.teachInteraction]
+      }
+      app.MG.edu.getClassTopic(pramas).then((res) => {
+        const list = res
+        const data = list.find(
+          (item) => item.refCode == app.config.refCodes.teachInteraction
+        )
+        if (data.id) {
+          this.setData({
+            teachInteractionInfo: data
+          })
+          this.getMessage()
+        }
+      })
+    },
+    // 鑾峰彇褰撳墠MessageList
+    getMessage() {
+      const data = {
+        start: 0,
+        size: 999,
+        appRefCode: app.config.appRefCode,
+        topicIdOrRefCode: String(this.data.teachInteractionInfo.id),
+        sort: {
+          type: 'Desc',
+          field: 'CreateDate'
+        },
+      }
+      app.MG.ugc.getTopicMessageList(data).then((res) => {
+        const data = res.datas.map((item) => {
+          item.question = []
+          item.bookId = null
+          item.path = ''
+          try {
+            const obj = JSON.parse(item.content)
+            if (obj.bookId) {
+              item.question = obj.content
+              item.bookId = obj.bookId
+              item.path = obj.path
+              item.userName = obj.userName
+            }
+          } catch (error) {
+            console.log(item)
+          }
+          return {
+            ...item
+          }
+        })
+        this.setData({
+          dataList: data
+        })
+        this.getCmsList()
+      })
+    },
+    // 澶勭悊鏁版嵁缁撴瀯
+    chageData(arr, zrr) {
+      let newData = []
+      // 棰樺簱棰樼洰绫诲瀷
+      const questionTypeList = [{
+          name: '鍗曢�夐',
+          value: 'singleChoice',
+          data: []
+        },
+        {
+          name: '澶氶�夐',
+          value: 'multipleChoice',
+          data: []
+        },
+        {
+          name: '鍒ゆ柇棰�',
+          value: 'judge',
+          data: []
+        },
+        {
+          name: '绠�绛旈',
+          value: 'shortAnswer',
+          data: []
+        },
+        {
+          name: '璁鸿堪棰�',
+          value: 'discuss',
+          data: []
+        },
+        {
+          name: '濉┖棰�',
+          value: 'completion',
+          data: []
+        },
+        {
+          name: '杩炵嚎棰�',
+          value: 'matching',
+          data: []
+        },
+        {
+          name: '鍒嗙被棰�',
+          value: 'classification',
+          data: []
+        }
+      ]
+      for (let i = 0; i < arr.length; i++) {
+        const item = arr[i]
+        item.questionTypeList = questionTypeList
+        for (let j = 0; j < zrr.length; j++) {
+          const ele = zrr[j]
+          const qusObj = item.question.find((citem) => citem.cmsItemId == ele.id)
+          if (qusObj?.cmsItemId) {
+            ele.userAnswer = qusObj.answer
+            const index = findIndexByValue(questionTypeList, ele.questionType)
+            if (index > -1) {
+              item.questionTypeList[index].data.push(ele)
+            }
+          }
+        }
+        item.questionTypeList = item.questionTypeList.filter((item) => item.data.length > 0)
+        newData.push(item)
+      }
+      return newData.filter((item) => item.questionTypeList.length > 0)
+    },
+    findIndexByValue(res, type) {
+      for (let i = 0; i < res.length; i++) {
+        if (res[i].value == type) {
+          return i
+        }
+      }
+      return -1 // 濡傛灉鏈壘鍒帮紝鍒欒繑鍥� -1
+    },
+    toDetail(e) {
+      const {
+        item
+      } = e.currentTarget.dataset
+      wx.navigateTo({
+        url: '/packageCourse/pages/teachClass/detail/index?questionName=' + item.name + '&teachInteractionId=' + this.data.teachInteractionInfo.id + '&bookId=' + this.properties.bookId + '&questionId=' + item.id,
+      })
+    }
+  }
+})
\ No newline at end of file
diff --git a/packageCourse/components/teaching/index.json b/packageCourse/components/teaching/index.json
new file mode 100644
index 0000000..a4422f6
--- /dev/null
+++ b/packageCourse/components/teaching/index.json
@@ -0,0 +1,8 @@
+{
+  "component": true,
+  "usingComponents": {
+    "t-search": "tdesign-miniprogram/search/search",
+    "t-skeleton": "tdesign-miniprogram/skeleton/skeleton",
+    "empty": "/components/empty/index"
+  }
+}
\ No newline at end of file
diff --git a/packageCourse/components/teaching/index.wxml b/packageCourse/components/teaching/index.wxml
new file mode 100644
index 0000000..7d11dd6
--- /dev/null
+++ b/packageCourse/components/teaching/index.wxml
@@ -0,0 +1,33 @@
+<!--packageCourse/components/teaching/index.wxml-->
+<view class="teachBoxContent">
+  <view class="header">
+    <t-search style="flex:1" value="{{searchKey}}" bind:clear="changeHandle" bind:submit="changeHandle" placeholder="鎼滅储鍚嶇О" clearable />
+  </view>
+  <view class="count">鍏辫 <text style="color: #ff6d00;">{{cmsDataList.length}}</text> 濂楅</view>
+  <view class="teachContent" wx:if="{{cmsDataList.length > 0 && !loading}}">
+    <view class="list" wx:for="{{cmsDataList}}" wx:key="index" bindtap="toDetail" data-item="{{item}}">
+      <view class="questionName">{{item.name}}</view>
+      <view class="questionInfo">
+        <view class="questionCount">
+          <text style="color: #ff6d00">{{ item.subList.length }}</text>
+          <text> /</text>
+          <text style="color: #67c23a"> {{ currentClass.memberCount }}</text>
+          <text style="margin-left: 20rpx;color: #999;font-size:24rpx">(宸茬瓟/鍏ㄩ儴)</text>
+        </view>
+        <view class="questionDate">
+          {{item.updateDate}}
+        </view>
+      </view>
+    </view>
+  </view>
+  <view class="she" wx:if="{{loading}}">
+    <view wx:for="{{10}}" wx:for-item="themeItem" wx:key="index">
+      <view class="demo-section__content">
+        <t-skeleton theme="text"></t-skeleton>
+      </view>
+    </view>
+  </view>
+  <view class="she" wx:if="{{cmsDataList.length == 0 && !loading}}">
+    <empty />
+  </view>
+</view>
\ No newline at end of file
diff --git a/packageCourse/components/teaching/index.wxss b/packageCourse/components/teaching/index.wxss
new file mode 100644
index 0000000..6db857a
--- /dev/null
+++ b/packageCourse/components/teaching/index.wxss
@@ -0,0 +1,50 @@
+/* packageCourse/components/teaching/index.wxss */
+.teachBoxContent {
+  width: 100%;
+  height: 100%;
+  font-size: 28rpx;
+}
+
+.header {
+  width: 100%;
+  padding: 0 20rpx;
+  box-sizing: border-box;
+}
+
+.teachContent {
+  width: 100%;
+  height: calc(100% - 82px);
+  padding: 20rpx;
+  box-sizing: border-box;
+  overflow: auto;
+}
+
+.teachBoxContent .count {
+  width: 100%;
+  padding: 20rpx;
+  box-sizing: border-box;
+  border-bottom: 1rpx solid #eee;
+}
+
+.teachContent .questionInfo {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.teachContent .questionName {
+  margin-bottom: 10rpx;
+}
+
+.teachContent .list {
+  width: 100%;
+  margin-bottom: 20rpx;
+  border-bottom: 1px solid #eee;
+  padding: 20rpx 0;
+  box-sizing: border-box;
+}
+
+.demo-section__content {
+  margin-top: 32rpx;
+  margin-bottom: 48rpx;
+}
\ No newline at end of file
diff --git a/packageCourse/pages/course/detail/index.js b/packageCourse/pages/course/detail/index.js
new file mode 100644
index 0000000..4a2f495
--- /dev/null
+++ b/packageCourse/pages/course/detail/index.js
@@ -0,0 +1,457 @@
+// packageCourse/pages/course/detail/index.js
+const app = getApp()
+import moment from 'moment'
+
+Page({
+  data: {
+    detail: null,
+    bookData: null,
+    courseId: null,
+    classCount: 0,
+    tabVal: 'base',
+    visible: false,
+    visibleStart: false,
+    visibleEnd: false,
+    startTime: '',
+    endTime: '',
+    className: '',
+    count: null,
+    classList: [],
+    searchKey: '',
+    defaultCmsPath: '',
+    pageClass: {
+      page: 1,
+      limit: 10,
+      total: 0
+    },
+    courseLoading: true,
+    classLoading: false,
+    // 鍔犺浇鍙傛暟
+    bottomLoading: false,
+    isMoreData: false,
+    // 杩斿洖椤堕儴
+    isBackTop: false,
+    setScrollValue: 0,
+    skeletonLoding: false
+  },
+
+  /**
+   * 鐢熷懡鍛ㄦ湡鍑芥暟--鐩戝惉椤甸潰鍔犺浇
+   */
+  onLoad(options) {
+    if (options.courseId) {
+      this.setData({
+        courseId: options.courseId,
+        defaultCmsPath: options.bookRefCode != '' ? 'jsek_digitalTextbooks' : 'defaultGoodsStore3'
+      })
+    }
+    wx.setNavigationBarTitle({
+      title: '鍩烘湰淇℃伅',
+    })
+    this.getData()
+  },
+
+  // 鑾峰彇璇剧▼淇℃伅
+  getData() {
+    app.MG.edu
+      .getCourseById({
+        courseId: this.data.courseId
+      })
+      .then((res) => {
+        setTimeout(() => {
+          this.setData({
+            detail: res,
+            courseLoading: false
+          })
+          const shopId = res.linkProduct?.id
+          this.getBookDetail(shopId)
+          this.getClassTotal()
+        }, 1000);
+      })
+  },
+
+  // 鑾峰彇鐝骇鏁伴噺
+  getClassTotal() {
+    app.MG.edu
+      .getCourseClassList({
+        courseId: this.data.courseId,
+      })
+      .then((res) => {
+        this.setData({
+          classCount: res.totalSize
+        })
+      })
+  },
+
+  // 鑾峰彇鏁欐潗璇︽儏
+  getBookDetail(shopId) {
+    let query = {
+      path: this.data.defaultCmsPath,
+      queryType: '*',
+      productId: String(shopId),
+      storeInfo: this.data.defaultCmsPath,
+      coverSize: {
+        height: 300,
+        width: 210
+      },
+      fields: {
+        seriesName: [],
+        author: [],
+        isbn: [],
+        publicationDate: []
+      }
+    }
+    app.MG.store.getProductDetail(query).then(async (res) => {
+      if (res?.datas) {
+        if (!res.datas.author) {
+          res.datas.author = '-'
+        }
+        this.setData({
+          bookData: res.datas
+        })
+      }
+    })
+  },
+
+  // tab鍒囨崲
+  tabActive(e) {
+    const {
+      str
+    } = e.currentTarget.dataset
+    this.setData({
+      tabVal: str,
+      courseLoading: true,
+      classLoading: true
+    })
+    if (str == 'base') {
+      wx.setNavigationBarTitle({
+        title: '鍩烘湰淇℃伅',
+      })
+      this.getData()
+    }
+    if (str == 'class') {
+      wx.setNavigationBarTitle({
+        title: '鐝骇绠$悊',
+      })
+      this.getClassList()
+    }
+  },
+
+  // 鎵撳紑鏂板缓鐝骇
+  newClass() {
+    this.setData({
+      visible: true,
+    })
+  },
+
+  onCourseNameInput(e) {
+    this.setData({
+      className: e.detail.value
+    })
+  },
+
+  onCourseDescInput(e) {
+    this.setData({
+      count: e.detail.value
+    })
+  },
+
+  // 鎵撳紑閫夋嫨鏃ユ湡
+  openDateStart() {
+    this.setData({
+      visibleStart: true
+    })
+  },
+
+  openDateEnd() {
+    this.setData({
+      visibleEnd: true
+    })
+  },
+
+  // 閫夋嫨鏃ユ湡
+  handleConfirmStart(e) {
+    const {
+      value
+    } = e.detail;
+    const dateStr = moment(value).format('YYYY-MM-DD')
+    this.setData({
+      startTime: dateStr,
+    });
+  },
+
+  handleConfirmEnd(e) {
+    const {
+      value
+    } = e.detail;
+    const dateStr = moment(value).format('YYYY-MM-DD')
+    this.setData({
+      endTime: dateStr,
+    });
+  },
+
+  // 鍏抽棴鐢宠
+  cancle() {
+    this.setData({
+      visible: false
+    })
+  },
+
+  // 鐢宠鎻愪氦鐝骇
+  submitClass() {
+    if (!this.data.className) {
+      wx.showToast({
+        title: '璇峰~鍐欒绋嬪悕绉�',
+        duration: 1000,
+        icon: 'none',
+      })
+      return false
+    }
+    if (!this.data.count) {
+      wx.showToast({
+        title: '璇烽�夋嫨鍏宠仈鏁欐潗',
+        duration: 1000,
+        icon: 'none',
+      })
+      return false
+    }
+    if (!this.data.startTime || !this.data.endTime) {
+      wx.showToast({
+        title: '璇烽�夋嫨鐝骇鏈夋晥鏈�',
+        duration: 1000,
+        icon: 'none',
+      })
+      return false
+    }
+    app.MG.edu
+      .newCourseClass({
+        courseId: this.data.courseId,
+        name: this.data.className,
+        description: '',
+        icon: '',
+        type: 'class',
+        beginDate: this.data.startTime,
+        endDate: this.data.endTime,
+        config: '',
+        price: 0,
+        maxUserCount: this.data.count
+      })
+      .then((res) => {
+        if (res) {
+          wx.showToast({
+            title: '宸茬敵璇峰紑鐝�',
+            duration: 1000,
+            icon: 'success',
+          })
+          this.setData({
+            visible: false
+          })
+          this.getClassList()
+        }
+      })
+      .catch((err) => {
+        wx.showToast({
+          title: '鐢宠寮�鐝嚭閿�',
+          duration: 1000,
+          icon: 'err',
+        })
+        this.setData({
+          visible: false
+        })
+      })
+  },
+
+  // 鎼滅储鐝骇
+  changeHandle(e) {
+    const {
+      value
+    } = e.detail;
+    this.setData({
+      searchKey: value,
+      'pageClass.page': 1
+    });
+    this.getClassList()
+  },
+
+  // 鑾峰彇鐝骇鍒楄〃
+  getClassList(isReachBottom) {
+    app.MG.edu
+      .getCourseClassList({
+        courseId: this.data.courseId,
+        start: (this.data.pageClass.page - 1) * this.data.pageClass.limit,
+        size: this.data.pageClass.limit,
+        sort: {
+          type: 'Desc',
+          field: 'CreateDate'
+        },
+        filterList: [],
+        searchList: this.data.searchKey ? [{
+          keywords: this.data.searchKey,
+          field: 'Name',
+          compareType: 'Contains'
+        }] : []
+      })
+      .then((res) => {
+        let list = res.datas.map((item) => {
+          return {
+            ...item,
+            name: item.name,
+            id: item.id,
+            icon: item.icon ? getPublicImage(item.icon, 80) : '',
+            introduction: item.description,
+            reason: item.applyReturnMsg ? JSON.parse(item.applyReturnMsg).reason : '',
+            beginDate: moment(item.beginDate).format('YYYY-MM-DD') ?? '-',
+            endDate: moment(item.endDate).format('YYYY-MM-DD') ?? '-'
+          }
+        })
+        //瑙﹀簳鍔犺浇鏂版暟鎹苟淇濈暀鑰佹暟鎹�
+        if (isReachBottom) {
+          list = [...this.data.classList, ...list] //灏嗘柊鏁版嵁鍔犲叆鑰佹暟鎹腑
+        }
+        this.setData({
+          classList: list,
+          'pageClass.total': res.totalSize,
+          skeletonLoding: false,
+          classLoading: false,
+          bottomLoading: false
+        })
+      })
+  },
+
+  // 鍒犻櫎璇剧▼
+  delClass(e) {
+    const {
+      delId
+    } = e.currentTarget.dataset
+    const data = {
+      ids: [delId]
+    }
+    app.MG.edu
+      .delCourseClass(data)
+      .then((res) => {
+        if (res) {
+          wx.showToast({
+            title: '宸插垹闄�',
+            duration: 1000,
+            icon: 'success',
+          })
+          this.getClassList()
+        }
+      })
+      .catch((err) => {
+        wx.showToast({
+          title: '鍒犻櫎澶辫触',
+          duration: 1000,
+          icon: 'error',
+        })
+        console.log(err)
+      })
+  },
+
+  // 鐝骇璇︽儏
+  todetail(e) {
+    const {
+      classId,
+      item
+    } = e.currentTarget.dataset
+    if (item.applyState == 'WaitAudit' || item.applyState == 'Reject') {
+      wx.showToast({
+        title: item.applyState == 'WaitAudit' ? '瀹℃牳涓�' : '鏈�氳繃',
+        duration: 1000,
+        icon: 'none',
+      })
+      return false
+    }
+    wx.navigateTo({
+      url: '/packageCourse/pages/teachClass/index?classId=' + classId + '&courseId=' + this.data.courseId + '&author=' + this.data.bookData.author + '&isbn=' + this.data.bookData.isbn + '&bookId=' + this.data.bookData.id + '&rootCmsItemId=' + this.data.bookData.rootCmsItemId + "&bookRefCode=" + this.data.defaultCmsPath,
+    })
+  },
+
+  /**
+   * 椤甸潰鐩稿叧浜嬩欢澶勭悊鍑芥暟--鐩戝惉鐢ㄦ埛涓嬫媺鍔ㄤ綔
+   */
+  onPullDownRefresh() {
+    if (this._freshing) return
+    this.setData({
+      'pageClass.page': 1,
+      bottomLoading: false,
+      isMoreData: false
+    })
+    setTimeout(() => {
+      this._freshing = true;
+      this.setData({
+        triggered: false,
+      })
+      this.getClassList();
+      this._freshing = false
+    }, 500);
+  },
+  /**
+   * 椤甸潰涓婃媺瑙﹀簳浜嬩欢鐨勫鐞嗗嚱鏁�
+   */
+  onReachBottom() {
+    if (this.data.pageClass.total > this.data.classList.length) {
+      this.setData({
+        'pageClass.page': this.data.pageClass.page + 1,
+        bottomLoading: true,
+        isMoreData: false
+      })
+    } else {
+      this.setData({
+        bottomLoading: false,
+        isMoreData: true
+      })
+      return false;
+    }
+    this.getClassList(true);
+  },
+
+  // 鐩戝惉婊氬姩璺濈
+  onPageScroll(e) {
+    if (e && e.scrollTop >= 1000) {
+      this.setData({
+        isBackTop: true
+      })
+    } else {
+      this.setData({
+        isBackTop: false
+      })
+    }
+  },
+
+  /**
+   * 鐢熷懡鍛ㄦ湡鍑芥暟--鐩戝惉椤甸潰鍒濇娓叉煋瀹屾垚
+   */
+  onReady() {
+
+  },
+
+  /**
+   * 鐢熷懡鍛ㄦ湡鍑芥暟--鐩戝惉椤甸潰鏄剧ず
+   */
+  onShow() {
+
+  },
+
+  /**
+   * 鐢熷懡鍛ㄦ湡鍑芥暟--鐩戝惉椤甸潰闅愯棌
+   */
+  onHide() {
+
+  },
+
+  /**
+   * 鐢熷懡鍛ㄦ湡鍑芥暟--鐩戝惉椤甸潰鍗歌浇
+   */
+  onUnload() {
+
+  },
+
+
+  /**
+   * 鐢ㄦ埛鐐瑰嚮鍙充笂瑙掑垎浜�
+   */
+  onShareAppMessage() {
+
+  }
+})
\ No newline at end of file
diff --git a/packageCourse/pages/course/detail/index.json b/packageCourse/pages/course/detail/index.json
new file mode 100644
index 0000000..3a73cdf
--- /dev/null
+++ b/packageCourse/pages/course/detail/index.json
@@ -0,0 +1,15 @@
+{
+  "usingComponents": {
+    "t-button": "tdesign-miniprogram/button/button",
+    "t-popup": "tdesign-miniprogram/popup/popup",
+    "t-input": "tdesign-miniprogram/input/input",
+    "t-search": "tdesign-miniprogram/search/search",
+    "t-tag": "tdesign-miniprogram/tag/tag",
+    "t-icon": "tdesign-miniprogram/icon/icon",
+    "t-calendar": "tdesign-miniprogram/calendar/calendar",
+    "t-back-top": "tdesign-miniprogram/back-top/back-top",
+    "empty": "/components/empty/index",
+    "t-skeleton": "tdesign-miniprogram/skeleton/skeleton",
+    "t-loading": "tdesign-miniprogram/loading/loading"
+  }
+}
\ No newline at end of file
diff --git a/packageCourse/pages/course/detail/index.wxml b/packageCourse/pages/course/detail/index.wxml
new file mode 100644
index 0000000..26859a8
--- /dev/null
+++ b/packageCourse/pages/course/detail/index.wxml
@@ -0,0 +1,139 @@
+<!--packageCourse/pages/course/detail/index.wxml-->
+<view class="contentTabBox">
+  <view class="showInfo">
+    <!-- 鍩烘湰淇℃伅 -->
+    <view class="baseInfoBox" wx:if="{{tabVal == 'base'}}">
+      <view wx:if="{{!courseLoading}}">
+        <view class="ID-State">
+          <text class="ID">ID: {{detail.id}}</text>
+          <t-tag class="margin-16" size='large' wx:if="{{detail.applyState == 'WaitAudit'}}" variant="light" theme="warning">瀹℃牳涓�</t-tag>
+          <t-tag class="margin-16" size='large' wx:if="{{detail.applyState == 'Reject'}}" variant="light" theme="danger">鏈�氳繃</t-tag>
+          <t-tag class="margin-16" size='large' wx:if="{{detail.applyState == 'Normal'}}" variant="light" theme="success">浣跨敤涓�</t-tag>
+        </view>
+        <view class="statics">
+          <view class="classCout">
+            <text>鐝骇鎬婚噺</text>
+            <text style="color: #ff6d00">{{classCount}}</text>
+          </view>
+        </view>
+        <view class="courseInfo">
+          <view class="intro">
+            <view class="descTitle">璇剧▼绠�浠�</view>
+            <view class="descCon">{{detail.description}}</view>
+          </view>
+          <view class="bookInfo">
+            <view class="title">璇剧▼鏁欐潗</view>
+            <view class="bookData">
+              <view class="bookText">
+                <text>{{bookData.name}}</text>
+                <text>浣滆�咃細{{bookData.author}}</text>
+                <text>ISBN锛歿{bookData.isbn}}</text>
+              </view>
+              <image wx:if="{{bookData.icon}}" class="bookIcon" src="{{bookData.icon}}" mode="" />
+              <image wx:else class="bookIcon" src="/static/images/default-book-img.png" mode="" />
+            </view>
+          </view>
+        </view>
+      </view>
+      <view class="block" wx:if="{{courseLoading}}">
+        <view wx:for="{{4}}" wx:for-item="themeItem" wx:key="index">
+          <view class="demo-section__content">
+            <t-skeleton animation="gradient" theme="text"></t-skeleton>
+            <t-skeleton animation="gradient" theme="paragraph"></t-skeleton>
+          </view>
+        </view>
+      </view>
+    </view>
+    <!-- 鐝骇绠$悊 -->
+    <view class="classBox" wx:else>
+      <view class="header">
+        <t-search style="flex:1" value="{{searchKey}}" bind:clear="changeHandle" bind:submit="changeHandle" placeholder="鎼滅储鐝骇鍚嶇О" clearable />
+        <t-button bindtap="newClass" size="small" style="margin-left: 15rpx;">寮�鐝�</t-button>
+      </view>
+      <view class="contentList" wx:if="{{classList.length > 0 && !classLoading}}">
+        <scroll-view class="scroll" class="content" bind:scroll="onPageScroll" model:scroll-top="{{setScrollValue}}" scroll-y refresher-enabled="{{true}}" lower-threshold="{{80}}" refresher-threshold="{{80}}" refresher-default-style="none" refresher-triggered="{{triggered}}" bindrefresherpulling="{{refresh.onPulling}}" bindrefresherrefresh="onPullDownRefresh" bindscrolltolower="onReachBottom">
+          <view slot="refresher" class="refresh-container">
+            <view class="loading">
+              <t-loading theme="circular" size="40rpx" text="姝e湪鍒锋柊..." class="wrapper" />
+            </view>
+          </view>
+          <view class="listClass" wx:for="{{classList}}" wx:key="index" data-class-id="{{item.id}}" data-item="{{item}}" bindtap="todetail">
+            <view class="titleBox">
+              <text class="className">{{item.name}}</text>
+              <text class="classId" style="color: #999; font-size: 12px;"> ID: {{item.id}}</text>
+            </view>
+            <view class="infoBox">
+              <text class="classTag" wx:if="{{item.applyState == 'WaitAudit'}}" style="color: #ef9f29">鐘舵��: 瀹℃牳涓�</text>
+              <text class="classTag" wx:if="{{item.applyState == 'Normal'}}" style="color: #1dbd11">鐘舵��: 杩涜涓�</text>
+              <text class="classTag" wx:if="{{item.applyState == 'Reject'}}" style="color: red">鐘舵��: 鏈�氳繃</text>
+              <t-icon bindtap="delClass" data-del-id="{{item.id}}" class="delete" wx:if="{{item.applyState == 'Reject'}}" name="delete" color="red" size='18px' />
+              <text class="classTag" wx:if="{{item.applyState == 'Reject'}}" style="color: red">鎷掔粷鍘熷洜锛歿{ item.reason != '' ? item.reason : '-' }}</text>
+              <text class="classTag">鐝骇浜烘暟: {{ item.memberCount }} / {{ item.maxUserCount }}</text>
+              <text class="classTag">鏈夋晥鏈燂細{{ item.beginDate }} - {{ item.endDate }}</text>
+            </view>
+          </view>
+          <view class="bottom-loading" wx:if="{{bottomLoading}}">
+            <t-loading theme="circular" size="40rpx" text="鍔犺浇涓�..." class="wrapper" />
+          </view>
+          <view class="bottom-loading" style="color: #ccc;font-size: 28rpx;" wx:if="{{isMoreData}}">
+            <text>娌℃湁鏇村浜�</text>
+          </view>
+        </scroll-view>
+      </view>
+      <view class="content" wx:if="{{classList.length == 0 && !classLoading}}">
+        <empty />
+      </view>
+      <view class="block" wx:if="{{classLoading}}">
+        <view wx:for="{{4}}" wx:for-item="themeItem" wx:key="index">
+          <view class="demo-section__content">
+            <t-skeleton animation="gradient" theme="text"></t-skeleton>
+            <t-skeleton animation="gradient" theme="paragraph"></t-skeleton>
+          </view>
+        </view>
+      </view>
+      <t-popup visible="{{visible}}" usingCustomNavbar placement="bottom">
+        <view class="block-title">鐢宠寮�鐝�</view>
+        <view class="block">
+          <view class="classInfo">
+            <view class="c-name">
+              <text>鐝骇鍚嶇О</text>
+              <t-input value="{{className}}" bindchange="onCourseNameInput" borderless clearable placeholder="璇疯緭鍏ョ彮绾у悕绉�" />
+            </view>
+            <view class="c-desc">
+              <text>鐝骇浜烘暟</text>
+              <t-input value="{{count}}" bindchange="onCourseDescInput" borderless placeholder="璇疯緭鍏ョ彮绾т汉鏁�" />
+            </view>
+            <view class="c-date">
+              <text>鐝骇鏈夋晥鏈�</text>
+              <view class="dateBox">
+                <view>
+                  <t-input value="{{startTime}}" readonly borderless bindtap="openDateStart" placeholder="璇烽�夋嫨寮�濮嬫椂闂�" />
+                  <t-calendar visible="{{visibleStart}}" bind:confirm="handleConfirmStart" />
+                </view>
+                <view>~</view>
+                <view>
+                  <t-input value="{{endTime}}" readonly borderless bindtap="openDateEnd" placeholder="璇烽�夋嫨缁撴潫鏃堕棿" />
+                  <t-calendar visible="{{visibleEnd}}" bind:confirm="handleConfirmEnd" />
+                </view>
+              </view>
+            </view>
+          </view>
+          <view class="classSubmit">
+            <t-button style="padding: 0 25px; margin:0 15px;" size="small" bindtap="cancle" variant="outline">鍙栨秷</t-button>
+            <t-button style="padding: 0 25px; margin:0;" size="small" bindtap="submitClass">纭</t-button>
+          </view>
+        </view>
+      </t-popup>
+    </view>
+  </view>
+  <view class="tabbar-bottom">
+    <view class="{{tabVal == 'base'?'tab-pubItem activeTab':'tab-pubItem'}}" data-str="base" bindtap="tabActive">
+      <t-icon class="tabIcon" name="home-filled" size="24px" />
+      <text class="text">鍩烘湰淇℃伅</text>
+    </view>
+    <view class="{{tabVal == 'class'?'tab-pubItem activeTab':'tab-pubItem'}}" data-str="class" bindtap="tabActive">
+      <t-icon class="tabIcon" name="file-setting-filled" size="24px" />
+      <text class="text">鐝骇绠$悊</text>
+    </view>
+  </view>
+</view>
\ No newline at end of file
diff --git a/packageCourse/pages/course/detail/index.wxss b/packageCourse/pages/course/detail/index.wxss
new file mode 100644
index 0000000..ea0891d
--- /dev/null
+++ b/packageCourse/pages/course/detail/index.wxss
@@ -0,0 +1,281 @@
+/* packageCourse/pages/course/detail/index.wxss */
+
+
+.demo-section__content {
+  margin-top: 32rpx;
+  margin-bottom: 48rpx;
+}
+
+.contentTabBox {
+  width: 100%;
+  height: calc(100vh - env(safe-area-inset-bottom));
+  font-size: 28rpx;
+  position: relative;
+}
+
+.showInfo {
+  width: 100%;
+  height: calc(100% - 60px);
+  overflow: hidden;
+}
+
+.refresh-container {
+  display: block;
+  width: 100vw;
+}
+
+.loading {
+  display: block;
+  width: 100%;
+  height: 180rpx;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+
+.bottom-loading {
+  width: 100vw;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  height: 100rpx;
+  padding-bottom: env(safe-area-inset-bottom);
+}
+
+.baseInfoBox {
+  width: 100%;
+  height: 100%;
+  overflow-y: auto;
+  padding: 10rpx 20rpx;
+  box-sizing: border-box;
+}
+
+.classBox {
+  height: 100%;
+}
+
+.contentList {
+  width: 100%;
+  height: calc(100% - 55px);
+  padding: 5px 20rpx;
+  box-sizing: border-box;
+}
+
+.content {
+  height: 100%;
+}
+
+.listClass {
+  border: 1rpx solid #efefef;
+  margin-bottom: 20rpx;
+  border-radius: 10rpx;
+}
+
+.listClass .titleBox {
+  width: 100%;
+  height: 60rpx;
+  display: flex;
+  padding: 5rpx 20rpx;
+  justify-content: space-between;
+  align-items: center;
+  background-color: #f8f8f8;
+  font-size: 30rpx;
+  box-sizing: border-box;
+}
+
+.listClass .infoBox {
+  display: flex;
+  flex-direction: column;
+  padding: 20rpx;
+  box-sizing: border-box;
+  position: relative;
+  font-size: 24rpx;
+}
+
+.classTag {
+  margin-bottom: 20rpx;
+}
+
+.className {
+  width: 250px;
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  margin-right: 20rpx;
+}
+
+.delete {
+  position: absolute;
+  right: 20rpx;
+}
+
+.ID-State {
+  width: 100%;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  height: 40px;
+  margin-bottom: 20rpx;
+}
+
+.ID {
+  font-weight: 700;
+}
+
+.statics {
+  width: 100%;
+  margin-bottom: 40rpx;
+}
+
+.statics .classCout {
+  width: 100px;
+  height: 60px;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: space-around;
+  border: 1rpx solid #666;
+  border-radius: 10rpx;
+}
+
+/* .intro {
+  min-height: 500px;
+} */
+
+.intro .descTitle,
+.bookInfo .title {
+  font-size: 28rpx;
+  font-weight: 700;
+  padding: 20rpx 0;
+  border-bottom: 1rpx solid #eee;
+}
+
+.intro .descCon {
+  padding: 20rpx 0;
+  line-height: 44rpx;
+  word-break: break-all;
+}
+
+.bookData {
+  width: 100%;
+  height: 200rpx;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 20rpx 0;
+}
+
+.bookText {
+  flex: 1;
+  height: 100%;
+  display: flex;
+  flex-direction: column;
+  justify-content: space-around;
+  align-items: flex-start;
+}
+
+.bookIcon {
+  width: 180rpx;
+  height: 230rpx;
+}
+
+.tabbar-bottom {
+  width: 100%;
+  height: 60px;
+  display: flex;
+  justify-content: space-around;
+  align-items: center;
+  border-top: 1rpx solid #eee;
+  position: absolute;
+  bottom: 0;
+  left: 0;
+}
+
+.tab-pubItem {
+  color: #999;
+}
+
+.tabbar-bottom .tabIcon {
+  margin-bottom: 10rpx;
+}
+
+.tabbar-bottom .text {
+  font-size: 24rpx;
+}
+
+.activeTab {
+  color: #ff6d00;
+}
+
+.contentList {
+  width: 100%;
+  height: calc(100% - 55px);
+}
+
+.header {
+  width: 100%;
+  height: 55px;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 20rpx;
+  box-sizing: border-box;
+  border-top: 1rpx solid #eee;
+  border-bottom: 1rpx solid #eee;
+  background-color: #fff;
+}
+
+.header .t-search__input-box {
+  height: 70rpx !important;
+  font-size: 28rpx;
+}
+
+.classInfo {
+  width: 100%;
+  border: 1rpx solid #eee;
+  padding: 35rpx;
+  box-sizing: border-box;
+  border-radius: 10rpx;
+  margin-bottom: 20rpx;
+}
+
+.classInfo .t-input,
+.classInfo .t-textarea {
+  padding: 10rpx 20rpx !important;
+  border: 1px solid #eee;
+  border-radius: 5px;
+  margin: 10px 0;
+}
+
+.classInfo .t-input__wrap .t-input__content,
+.classInfo .t-input__placeholder,
+.classInfo .t-textarea__placeholder,
+.classInfo .t-textarea__wrapper-inner {
+  font-size: 28rpx !important;
+}
+
+.classInfo .dateBox {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.classSubmit {
+  width: 100%;
+  display: flex;
+  justify-content: flex-end;
+  align-items: center;
+  margin-bottom: 20rpx;
+  padding: 0 20px;
+  box-sizing: border-box;
+}
+
+.classBox .t-overlay {
+  top: 55px !important
+}
+
+.block-title {
+  padding: 30rpx 20rpx;
+  font-size: 30rpx;
+  color: #ff6d00;
+}
\ No newline at end of file
diff --git a/packageCourse/pages/course/index.js b/packageCourse/pages/course/index.js
new file mode 100644
index 0000000..0dce37f
--- /dev/null
+++ b/packageCourse/pages/course/index.js
@@ -0,0 +1,378 @@
+// packageCourse/pages/course/index.js
+import {
+  getPublicImage
+} from '../../../assets/js/middleGround/tool'
+const app = getApp()
+Page({
+
+  /**
+   * 椤甸潰鐨勫垵濮嬫暟鎹�
+   */
+  data: {
+    visible: false,
+    visibleCart: false,
+    searchKey: '',
+    courseList: [],
+    courseName: '',
+    courseDesc: '',
+    cartList: [],
+    radioVal: 0,
+    selectName: '',
+    selectedBook: null,
+    pageCourse: {
+      page: 1,
+      limit: 10,
+      total: 0,
+      loading: false
+    },
+    pageBook: {
+      page: 1,
+      limit: 10,
+      total: 999,
+      loading: false
+    },
+    // 鍔犺浇鍙傛暟
+    bottomLoading: false,
+    isMoreData: false,
+    // 杩斿洖椤堕儴
+    isBackTop: false,
+    setScrollValue: 0,
+    skeletonLoding: true
+  },
+
+  /**
+   * 鐢熷懡鍛ㄦ湡鍑芥暟--鐩戝惉椤甸潰鍔犺浇
+   */
+  onLoad(options) {
+    this.getData()
+  },
+
+  // 璇剧▼璇︽儏
+  todetail(e) {
+    const {
+      courseId,
+      item
+    } = e.currentTarget.dataset
+    const refCode = item.linkProduct.refCode ? item.linkProduct.refCode : ''
+    if (item.applyState == 'WaitAudit' || item.applyState == 'Reject') {
+      wx.showToast({
+        title: item.applyState == 'WaitAudit' ? '瀹℃牳涓�' : '鏈�氳繃',
+        duration: 1000,
+        icon: 'none',
+      })
+      return false
+    }
+    wx.navigateTo({
+      url: '/packageCourse/pages/course/detail/index?courseId=' + courseId + "&bookRefCode=" + refCode,
+    })
+  },
+
+  // 鎼滅储璇剧▼
+  changeHandle(e) {
+    const {
+      value
+    } = e.detail;
+    this.setData({
+      searchKey: value,
+      'pageCourse.page': 1
+    });
+    this.getData()
+  },
+
+  // 鎼滅储鏁欐潗
+  changeHandleBook(e) {
+    const {
+      value
+    } = e.detail;
+    this.setData({
+      selectName: value,
+      'pageBook.page': 1
+    });
+    this.getTextBook()
+  },
+
+  // 鑾峰彇璇剧▼
+  getData(isReachBottom) {
+    app.MG.edu
+      .getAppCourseList({
+        start: (this.data.pageCourse.page - 1) * this.data.pageCourse.limit,
+        size: this.data.pageCourse.limit,
+        sort: {
+          type: 'Desc',
+          field: 'CreateDate'
+        },
+        filterList: [],
+        searchList: this.data.searchKey ? [{
+          keywords: this.data.searchKey,
+          field: 'Name',
+          compareType: 'Contains'
+        }] : []
+      })
+      .then((res) => {
+        let list = res.datas.map((item) => {
+          return {
+            ...item,
+            name: item.name,
+            id: item.id,
+            icon: item.icon && item.icon != 'default' ? getPublicImage(item.icon, 80) : '',
+            introduction: item.description,
+            reason: item.applyReturnMsg ? JSON.parse(item.applyReturnMsg).reason : '-'
+          }
+        })
+        //瑙﹀簳鍔犺浇鏂版暟鎹苟淇濈暀鑰佹暟鎹�
+        if (isReachBottom) {
+          list = [...this.data.courseList, ...list] //灏嗘柊鏁版嵁鍔犲叆鑰佹暟鎹腑
+        }
+        this.setData({
+          courseList: list,
+          'pageCourse.total': res.totalSize,
+          skeletonLoding: false,
+          bottomLoading: false
+        })
+      })
+  },
+
+  // 鑾峰彇宸茶喘涔扮殑鏁欐潗鍒楄〃
+  getTextBook() {
+    const searchData = [{
+        keywords: 'jsek_digitalTextbooks',
+        field: 'ProductType'
+      },
+      {
+        keywords: 'jsek_mediaBook',
+        field: 'ProductType'
+      },
+      {
+        keywords: this.data.selectName,
+        field: 'ProductName'
+      }
+    ]
+    const data = {
+      Size: this.data.pageBook.limit,
+      Start: (this.data.pageBook.page - 1) * this.data.pageBook.limit,
+      sort: {
+        type: 'Desc',
+        field: 'CreateDate'
+      },
+      searchList: searchData
+    }
+    app.MG.store
+      .getPurchasedProductList(data)
+      .then((res) => {
+        const list = res.datas.map((item) => {
+          return {
+            ...item,
+            icon: item.product.icon ? getPublicImage(item.product.icon, 80) : ''
+          }
+        })
+        this.setData({
+          cartList: list,
+        })
+      })
+      .catch((err) => {
+        this.setData({
+          cartList: [],
+          'pageBook.loading': false
+        })
+        console.log(err)
+      })
+  },
+
+  // 鏂板缓璇剧▼
+  newCourse() {
+    this.setData({
+      visible: true,
+      'pageBook.loading': true
+    })
+    this.getTextBook()
+  },
+
+  // 閫夋嫨璇剧▼
+  selectedBook() {
+    this.setData({
+      visibleCart: true
+    })
+  },
+
+  // 鍏抽棴
+  cancle() {
+    this.setData({
+      visible: false
+    })
+  },
+
+  radioCancle() {
+    this.setData({
+      visibleCart: false
+    })
+  },
+
+  // 鍗曢�夐�夋嫨璇炬湰
+  onChange(e) {
+    this.setData({
+      radioVal: e.detail.value
+    });
+  },
+
+  // 鍗曢�夎鏈彁浜�
+  radioSubmit() {
+    const data = this.data.cartList[this.data.radioVal]
+    if (!data.icon) {
+      data.product.icon = 'default'
+    }
+    this.setData({
+      selectedBook: data,
+      visibleCart: false
+    });
+  },
+
+  onCourseNameInput(e) {
+    this.setData({
+      courseName: e.detail.value
+    })
+  },
+
+  onCourseDescInput(e) {
+    this.setData({
+      courseDesc: e.detail.value
+    })
+  },
+
+  // 鏂板缓璇剧▼
+  submitCourse() {
+    if (!this.data.courseName) {
+      wx.showToast({
+        title: '璇峰~鍐欒绋嬪悕绉�',
+        duration: 1000,
+        icon: 'none',
+      })
+      return false
+    }
+    if (!this.data.selectedBook) {
+      wx.showToast({
+        title: '璇烽�夋嫨鍏宠仈鏁欐潗',
+        duration: 1000,
+        icon: 'none',
+      })
+      return false
+    }
+    app.MG.edu
+      .applyNewCourse({
+        name: this.data.courseName,
+        description: this.data.courseDesc,
+        content: '',
+        icon: this.data.selectedBook.product.icon,
+        type: 'course',
+        config: '',
+        applyData: JSON.stringify({
+          textBookId: this.data.selectedBook.product.id,
+          textBookName: this.data.selectedBook.product.name
+        }),
+        linkProductId: this.data.selectedBook.product.id,
+        maxClassCount: 999,
+        payPrice: 0
+      })
+      .then((res) => {
+        if (res) {
+          this.setData({
+            visible: false
+          })
+          this.getData()
+        }
+      })
+  },
+
+  // 杩斿洖椤堕儴 
+  onToTop() {
+    this.setData({
+      setScrollValue: 0
+    })
+  },
+
+  /**
+   * 鐢熷懡鍛ㄦ湡鍑芥暟--鐩戝惉椤甸潰鍒濇娓叉煋瀹屾垚
+   */
+  onReady() {
+
+  },
+
+  /**
+   * 鐢熷懡鍛ㄦ湡鍑芥暟--鐩戝惉椤甸潰鏄剧ず
+   */
+  onShow() {
+
+  },
+
+  /**
+   * 鐢熷懡鍛ㄦ湡鍑芥暟--鐩戝惉椤甸潰闅愯棌
+   */
+  onHide() {
+
+  },
+
+  /**
+   * 鐢熷懡鍛ㄦ湡鍑芥暟--鐩戝惉椤甸潰鍗歌浇
+   */
+  onUnload() {
+
+  },
+
+  /**
+   * 椤甸潰鐩稿叧浜嬩欢澶勭悊鍑芥暟--鐩戝惉鐢ㄦ埛涓嬫媺鍔ㄤ綔
+   */
+  onPullDownRefresh() {
+    if (this._freshing) return
+    this.setData({
+      'pageCourse.page': 1,
+      bottomLoading: false,
+      isMoreData: false
+    })
+    setTimeout(() => {
+      this._freshing = true;
+      this.setData({
+        triggered: false,
+      })
+      this.getData();
+      this._freshing = false
+    }, 500);
+  },
+  /**
+   * 椤甸潰涓婃媺瑙﹀簳浜嬩欢鐨勫鐞嗗嚱鏁�
+   */
+  onReachBottom() {
+    if (this.data.pageCourse.total > this.data.courseList.length) {
+      this.setData({
+        'pageCourse.page': this.data.pageCourse.page + 1,
+        bottomLoading: true,
+        isMoreData: false
+      })
+    } else {
+      this.setData({
+        bottomLoading: false,
+        isMoreData: true
+      })
+      return false;
+    }
+    this.getData(true);
+  },
+
+  // 鐩戝惉婊氬姩璺濈
+  onPageScroll(e) {
+    if (e && e.scrollTop >= 1000) {
+      this.setData({
+        isBackTop: true
+      })
+    } else {
+      this.setData({
+        isBackTop: false
+      })
+    }
+  },
+
+  /**
+   * 鐢ㄦ埛鐐瑰嚮鍙充笂瑙掑垎浜�
+   */
+  onShareAppMessage() {
+
+  }
+})
\ No newline at end of file
diff --git a/packageCourse/pages/course/index.json b/packageCourse/pages/course/index.json
new file mode 100644
index 0000000..0065610
--- /dev/null
+++ b/packageCourse/pages/course/index.json
@@ -0,0 +1,18 @@
+{
+  "navigationBarTitleText": "鎴戠殑璇剧▼",
+  "usingComponents": {
+    "t-search": "tdesign-miniprogram/search/search",
+    "t-button": "tdesign-miniprogram/button/button",
+    "t-popup": "tdesign-miniprogram/popup/popup",
+    "t-input": "tdesign-miniprogram/input/input",
+    "t-textarea": "tdesign-miniprogram/textarea/textarea",
+    "empty": "/components/empty/index",
+    "t-skeleton": "tdesign-miniprogram/skeleton/skeleton",
+    "t-radio": "tdesign-miniprogram/radio/radio",
+    "t-radio-group": "tdesign-miniprogram/radio-group/radio-group",
+    "t-icon": "tdesign-miniprogram/icon/icon",
+    "t-back-top": "tdesign-miniprogram/back-top/back-top",
+    "t-tag": "tdesign-miniprogram/tag/tag",
+    "t-loading": "tdesign-miniprogram/loading/loading"
+  }
+}
\ No newline at end of file
diff --git a/packageCourse/pages/course/index.skeleton.wxml b/packageCourse/pages/course/index.skeleton.wxml
new file mode 100644
index 0000000..30b5c8f
--- /dev/null
+++ b/packageCourse/pages/course/index.skeleton.wxml
@@ -0,0 +1,106 @@
+<!--
+姝ゆ枃浠朵负寮�鍙戣�呭伐鍏风敓鎴愶紝鐢熸垚鏃堕棿: 2024/11/29涓嬪崍6:56:02
+浣跨敤鏂规硶锛�
+鍦� D:\灏忕▼搴廫jsek-app\jsek-applet\packageCourse\pages\course\index.wxml 寮曞叆妯℃澘
+
+```
+<import src="index.skeleton.wxml"/>
+<template is="skeleton" wx:if="{{loading}}" />
+```
+
+鍦� D:\灏忕▼搴廫jsek-app\jsek-applet\packageCourse\pages\course\index.wxss 涓紩鍏ユ牱寮�
+```
+@import "./index.skeleton.wxss";
+```
+
+鏇村璇︾粏淇℃伅鍙互鍙傝�冩枃妗o細https://developers.weixin.qq.com/miniprogram/dev/devtools/skeleton.html
+-->
+<template name="skeleton">
+  <view class="sk-container">
+    <view class="contentBox">
+      <view class="header">
+        <view class=" t-search search--t-search " style="flex:1;">
+          <view class="t-search__input-box search--t-search__input-box t-not-focused search--t-not-focused t-search__input-box-- search--t-search__input-box-- t-search__input-box--square search--t-search__input-box--square ">
+            <view class="t-icon icon--t-icon search--t-icon  " style="true">
+              <label class="t-icon-search icon--t-icon-search t-icon-base icon--t-icon-base sk-pseudo sk-pseudo-circle"></label>
+            </view>
+            <view class="t-input__keyword search--t-input__keyword sk-image" cursor="0" maxlength="-1" name="input" placeholder="鎼滅储璇剧▼鍚嶇О" placeholder-class="input-placeholder t-search__placeholder t-search__placeholder--normal" placeholder-style="true" selection-end="-1" selection-start="-1" type="text" value="true"></view>
+          </view>
+        </view>
+        <button app-parameter="true" data-custom="null" form-type="true" hover-class="t-button--hover" hover-start-time="20" hover-stay-time="70" lang="true" open-type="true" send-message-img="鎴浘" send-message-path="褰撳墠鍒嗕韩璺緞" send-message-title="褰撳墠鏍囬" session-from="true" style="margin-left: 7px;" class="t-button button--t-button t-button--base button--t-button--base t-button--primary button--t-button--primary t-button--rectangle button--t-button--rectangle t-button--size-small button--t-button--size-small sk-button sk-pseudo sk-pseudo-circle">
+          <view class="t-button__content button--t-button__content sk-transparent sk-text-28-1250-12 sk-text" style="background-position-x: 50%;">鏂板缓</view>
+        </button>
+      </view>
+      <view class="contentList">
+        <scroll-view scroll-y="true" class="content" lower-threshold="80" scroll-top="0" refresher-default-style="none" refresher-enabled="true" refresher-threshold="80">
+          <view class="listCourse">
+            <image class="courseIcon sk-image" mode="aspectFit"></image>
+            <view class="courseInfo">
+              <view class="title">
+                <text class="sk-transparent sk-text-14-2857-454 sk-text">2121</text>
+              </view>
+              <view class="courseId">
+                <text class="sk-transparent sk-text-14-2857-247 sk-text">ID: 31</text>
+                <view class="t-tag tag--t-tag t-tag--warning tag--t-tag--warning t-tag--light tag--t-tag--light t-tag--medium tag--t-tag--medium t-tag--square tag--t-tag--square margin-16 " style="true">
+                  <view class="t-tag__icon tag--t-tag__icon"></view>
+                  <view class="t-tag__text tag--t-tag__text sk-transparent sk-text-25-0000-591 sk-text">瀹℃牳涓�</view>
+                </view>
+              </view>
+              <view class="desc sk-transparent sk-text-20-0000-310 sk-text">鎻忚堪锛氭湰璇剧▼涓撲负鑱屽満鏂版墜鍜屽笇鏈涙彁鍗囪亴鍦鸿嫳璇按骞崇殑瀛﹀憳璁捐锛屾棬鍦ㄥ府鍔╂偍鎺屾彙鍦ㄧ幇浠e晢涓氱幆澧冧腑蹇呭鐨勮嫳璇妧鑳姐��
+              </view>
+            </view>
+          </view>
+          <view class="listCourse">
+            <image class="courseIcon sk-image" mode="aspectFit"></image>
+            <view class="courseInfo">
+              <view class="title">
+                <text class="sk-transparent sk-text-14-2857-789 sk-text">333</text>
+              </view>
+              <view class="courseId">
+                <text class="sk-transparent sk-text-14-2857-930 sk-text">ID: 30</text>
+                <view class="t-tag tag--t-tag t-tag--warning tag--t-tag--warning t-tag--light tag--t-tag--light t-tag--medium tag--t-tag--medium t-tag--square tag--t-tag--square margin-16 " style="true">
+                  <view class="t-tag__icon tag--t-tag__icon"></view>
+                  <view class="t-tag__text tag--t-tag__text sk-transparent sk-text-25-0000-24 sk-text">瀹℃牳涓�</view>
+                </view>
+              </view>
+              <view class="desc sk-transparent sk-text-20-0000-641 sk-text">鎻忚堪锛氭湰璇剧▼涓撲负鑱屽満鏂版墜鍜屽笇鏈涙彁鍗囪亴鍦鸿嫳璇按骞崇殑瀛﹀憳璁捐锛屾棬鍦ㄥ府鍔╂偍鎺屾彙鍦ㄧ幇浠e晢涓氱幆澧冧腑蹇呭鐨勮嫳璇妧鑳姐��
+              </view>
+            </view>
+          </view>
+          <view class="listCourse">
+            <image class="courseIcon sk-image" mode="aspectFit"></image>
+            <view class="courseInfo">
+              <view class="title">
+                <text class="sk-transparent sk-text-14-2857-70 sk-text">123</text>
+              </view>
+              <view class="courseId">
+                <text class="sk-transparent sk-text-14-2857-970 sk-text">ID: 29</text>
+                <view class="t-tag tag--t-tag t-tag--warning tag--t-tag--warning t-tag--light tag--t-tag--light t-tag--medium tag--t-tag--medium t-tag--square tag--t-tag--square margin-16 " style="true">
+                  <view class="t-tag__icon tag--t-tag__icon"></view>
+                  <view class="t-tag__text tag--t-tag__text sk-transparent sk-text-25-0000-807 sk-text">瀹℃牳涓�</view>
+                </view>
+              </view>
+              <view class="desc sk-transparent sk-text-20-0000-381 sk-text">鎻忚堪锛氭湰璇剧▼涓撲负鑱屽満鏂版墜鍜屽笇鏈涙彁鍗囪亴鍦鸿嫳璇按骞崇殑瀛﹀憳璁捐锛屾棬鍦ㄥ府鍔╂偍鎺屾彙鍦ㄧ幇浠e晢涓氱幆澧冧腑蹇呭鐨勮嫳璇妧鑳姐��</view>
+            </view>
+          </view>
+          <view class="listCourse">
+            <image class="courseIcon sk-image" mode="aspectFit"></image>
+            <view class="courseInfo">
+              <view class="title">
+                <text class="sk-transparent sk-text-14-2857-709 sk-text">娴嬭瘯璇剧▼</text>
+              </view>
+              <view class="courseId">
+                <text class="sk-transparent sk-text-14-2857-927 sk-text">ID: 28</text>
+                <view class="t-tag tag--t-tag t-tag--warning tag--t-tag--warning t-tag--light tag--t-tag--light t-tag--medium tag--t-tag--medium t-tag--square tag--t-tag--square margin-16 " style="true">
+                  <view class="t-tag__icon tag--t-tag__icon"></view>
+                  <view class="t-tag__text tag--t-tag__text sk-transparent sk-text-25-0000-600 sk-text">瀹℃牳涓�</view>
+                </view>
+              </view>
+              <view class="desc sk-transparent sk-text-20-0000-251 sk-text">鎻忚堪锛氬ぇ閮ㄥ垎鍥炬爣鍦� 1.8.0 鐗堟湰涓柊澧烇紝濡傛灉鍙戠幇寮曞叆缁勪欢搴撳悗锛岄儴鍒嗗浘鏍囨棤娉曚娇鐢紝璇锋鏌ュ畨瑁呯殑缁勪欢搴撱��</view>
+            </view>
+          </view>
+        </scroll-view>
+      </view>
+    </view>
+  </view>
+</template>
\ No newline at end of file
diff --git a/packageCourse/pages/course/index.skeleton.wxss b/packageCourse/pages/course/index.skeleton.wxss
new file mode 100644
index 0000000..258dc9f
--- /dev/null
+++ b/packageCourse/pages/course/index.skeleton.wxss
@@ -0,0 +1,140 @@
+/*
+姝ゆ枃浠朵负寮�鍙戣�呭伐鍏风敓鎴愶紝鐢熸垚鏃堕棿: 2024/11/29涓嬪崍6:56:02
+
+鍦� D:\灏忕▼搴廫jsek-app\jsek-applet\packageCourse\pages\course\index.wxss 涓紩鍏ユ牱寮�
+```
+@import "./index.skeleton.wxss";
+```
+
+鏇村璇︾粏淇℃伅鍙互鍙傝�冩枃妗o細https://developers.weixin.qq.com/miniprogram/dev/devtools/skeleton.html
+*/
+.sk-transparent {
+    color: transparent !important;
+  }
+.sk-text-28-1250-12 {
+    background-image: linear-gradient(transparent 28.1250%, #EEEEEE 0%, #EEEEEE 71.8750%, transparent 0%) !important;
+    background-size: 100% 64.0000rpx;
+    position: relative !important;
+  }
+.sk-text {
+    background-origin: content-box !important;
+    background-clip: content-box !important;
+    background-color: transparent !important;
+    color: transparent !important;
+    background-repeat: repeat-y !important;
+  }
+.sk-text-20-0000-985 {
+    background-image: linear-gradient(transparent 20.0000%, #EEEEEE 0%, #EEEEEE 80.0000%, transparent 0%) !important;
+    background-size: 100% 40.0000rpx;
+    position: relative !important;
+  }
+.sk-text-14-2857-454 {
+    background-image: linear-gradient(transparent 14.2857%, #EEEEEE 0%, #EEEEEE 85.7143%, transparent 0%) !important;
+    background-size: 100% 42.0000rpx;
+    position: relative !important;
+  }
+.sk-text-14-2857-247 {
+    background-image: linear-gradient(transparent 14.2857%, #EEEEEE 0%, #EEEEEE 85.7143%, transparent 0%) !important;
+    background-size: 100% 36.4000rpx;
+    position: relative !important;
+  }
+.sk-text-25-0000-591 {
+    background-image: linear-gradient(transparent 25.0000%, #EEEEEE 0%, #EEEEEE 75.0000%, transparent 0%) !important;
+    background-size: 100% 48.0000rpx;
+    position: relative !important;
+  }
+.sk-text-20-0000-310 {
+    background-image: linear-gradient(transparent 20.0000%, #EEEEEE 0%, #EEEEEE 80.0000%, transparent 0%) !important;
+    background-size: 100% 40.0000rpx;
+    position: relative !important;
+  }
+.sk-text-14-2857-789 {
+    background-image: linear-gradient(transparent 14.2857%, #EEEEEE 0%, #EEEEEE 85.7143%, transparent 0%) !important;
+    background-size: 100% 42.0000rpx;
+    position: relative !important;
+  }
+.sk-text-14-2857-930 {
+    background-image: linear-gradient(transparent 14.2857%, #EEEEEE 0%, #EEEEEE 85.7143%, transparent 0%) !important;
+    background-size: 100% 36.4000rpx;
+    position: relative !important;
+  }
+.sk-text-25-0000-24 {
+    background-image: linear-gradient(transparent 25.0000%, #EEEEEE 0%, #EEEEEE 75.0000%, transparent 0%) !important;
+    background-size: 100% 48.0000rpx;
+    position: relative !important;
+  }
+.sk-text-20-0000-641 {
+    background-image: linear-gradient(transparent 20.0000%, #EEEEEE 0%, #EEEEEE 80.0000%, transparent 0%) !important;
+    background-size: 100% 40.0000rpx;
+    position: relative !important;
+  }
+.sk-text-14-2857-70 {
+    background-image: linear-gradient(transparent 14.2857%, #EEEEEE 0%, #EEEEEE 85.7143%, transparent 0%) !important;
+    background-size: 100% 42.0000rpx;
+    position: relative !important;
+  }
+.sk-text-14-2857-970 {
+    background-image: linear-gradient(transparent 14.2857%, #EEEEEE 0%, #EEEEEE 85.7143%, transparent 0%) !important;
+    background-size: 100% 36.4000rpx;
+    position: relative !important;
+  }
+.sk-text-25-0000-807 {
+    background-image: linear-gradient(transparent 25.0000%, #EEEEEE 0%, #EEEEEE 75.0000%, transparent 0%) !important;
+    background-size: 100% 48.0000rpx;
+    position: relative !important;
+  }
+.sk-text-20-0000-381 {
+    background-image: linear-gradient(transparent 20.0000%, #EEEEEE 0%, #EEEEEE 80.0000%, transparent 0%) !important;
+    background-size: 100% 40.0000rpx;
+    position: relative !important;
+  }
+.sk-text-14-2857-709 {
+    background-image: linear-gradient(transparent 14.2857%, #EEEEEE 0%, #EEEEEE 85.7143%, transparent 0%) !important;
+    background-size: 100% 42.0000rpx;
+    position: relative !important;
+  }
+.sk-text-14-2857-927 {
+    background-image: linear-gradient(transparent 14.2857%, #EEEEEE 0%, #EEEEEE 85.7143%, transparent 0%) !important;
+    background-size: 100% 36.4000rpx;
+    position: relative !important;
+  }
+.sk-text-25-0000-600 {
+    background-image: linear-gradient(transparent 25.0000%, #EEEEEE 0%, #EEEEEE 75.0000%, transparent 0%) !important;
+    background-size: 100% 48.0000rpx;
+    position: relative !important;
+  }
+.sk-text-20-0000-251 {
+    background-image: linear-gradient(transparent 20.0000%, #EEEEEE 0%, #EEEEEE 80.0000%, transparent 0%) !important;
+    background-size: 100% 40.0000rpx;
+    position: relative !important;
+  }
+.sk-button {
+    color: #EFEFEF !important;
+    background: #EFEFEF !important;
+    border: none !important;
+    box-shadow: none !important;
+  }
+.sk-image {
+    background: #EFEFEF !important;
+  }
+.sk-pseudo::before, .sk-pseudo::after {
+      background: #EFEFEF !important;
+      background-image: none !important;
+      color: transparent !important;
+      border-color: transparent !important;
+    }
+.sk-pseudo-rect::before, .sk-pseudo-rect::after {
+      border-radius: 0 !important;
+    }
+.sk-pseudo-circle::before, .sk-pseudo-circle::after {
+      border-radius: 50% !important;
+    }
+.sk-container {
+    position: absolute;
+    left: 0;
+    top: 0;
+    width: 100%;
+    height: 100%;
+    overflow: hidden;
+    background-color: transparent;
+  }
diff --git a/packageCourse/pages/course/index.wxml b/packageCourse/pages/course/index.wxml
new file mode 100644
index 0000000..52194d1
--- /dev/null
+++ b/packageCourse/pages/course/index.wxml
@@ -0,0 +1,137 @@
+<!--packageCourse/pages/course/index.wxml-->
+<view class="contentBox" wx:if="{{!skeletonLoding}}">
+  <view class="header">
+    <t-search style="flex:1" value="{{searchKey}}" bind:clear="changeHandle" bind:submit="changeHandle" placeholder="鎼滅储璇剧▼鍚嶇О" clearable />
+    <t-button bindtap="newCourse" size="small" style="margin-left: 15rpx;">鏂板缓</t-button>
+  </view>
+  <view class="contentList" wx:if="{{courseList.length > 0}}">
+    <scroll-view class="scroll" class="content" bind:scroll="onPageScroll" model:scroll-top="{{setScrollValue}}" scroll-y refresher-enabled="{{true}}" lower-threshold="{{80}}" refresher-threshold="{{80}}" refresher-default-style="none" refresher-triggered="{{triggered}}" bindrefresherpulling="{{refresh.onPulling}}" bindrefresherrefresh="onPullDownRefresh" bindscrolltolower="onReachBottom">
+      <view slot="refresher" class="refresh-container">
+        <view class="loading">
+          <t-loading theme="circular" size="40rpx" text="姝e湪鍒锋柊..." class="wrapper" />
+        </view>
+      </view>
+      <view class="listCourse" wx:for="{{courseList}}" wx:key="index" data-item="{{item}}" data-course-id="{{item.id}}" bindtap="todetail">
+        <image wx:if="{{item.icon}}" class="courseIcon" src="{{item.icon}}" mode="aspectFit" />
+        <image wx:else class="courseIcon" src="/static/images/default-book-img.png" mode="aspectFit" />
+        <view class="courseInfo">
+          <view class="title">
+            <text>{{item.name}}</text>
+            <!-- <t-icon wx:if="{{item.applyState == 'Reject'}}" name="delete" color="red" size='18px' /> -->
+          </view>
+          <view class="courseId">
+            <text>ID: {{item.id}}</text>
+            <t-tag class="margin-16" wx:if="{{item.applyState == 'WaitAudit'}}" variant="light" theme="warning">瀹℃牳涓�</t-tag>
+            <t-tag class="margin-16" wx:if="{{item.applyState == 'Reject'}}" variant="light" theme="danger">鏈�氳繃</t-tag>
+            <t-tag class="margin-16" wx:if="{{item.applyState == 'Normal'}}" variant="light" theme="success">浣跨敤涓�</t-tag>
+          </view>
+          <view wx:if="{{item.applyState == 'Reject'}}" class="reason">鎷掔粷鍘熷洜: {{item.reason}}</view>
+          <view class="desc">鎻忚堪锛歿{item.description}}</view>
+        </view>
+      </view>
+      <view class="bottom-loading" wx:if="{{bottomLoading}}">
+        <t-loading theme="circular" size="40rpx" text="鍔犺浇涓�..." class="wrapper" />
+      </view>
+      <view class="bottom-loading" style="color: #ccc;font-size: 28rpx;" wx:if="{{isMoreData}}">
+        <text>娌℃湁鏇村浜�</text>
+      </view>
+    </scroll-view>
+  </view>
+  <view class="content" wx:if="{{courseList.length == 0}}">
+    <empty />
+  </view>
+  <t-popup visible="{{visible}}" style="top: 55px;" usingCustomNavbar placement="bottom">
+    <view class="block">
+      <view class="courseData">
+        <view class="c-name">
+          <text>璇剧▼鍚嶇О</text>
+          <t-input value="{{courseName}}" bindchange="onCourseNameInput" borderless clearable placeholder="璇疯緭鍏ユ枃瀛�" />
+        </view>
+        <view class="c-desc">
+          <text>璇剧▼鎻忚堪</text>
+          <t-textarea value="{{courseDesc}}" bindchange="onCourseDescInput" bordered maxlength="50" indicator autosize placeholder="璇疯緭鍏ユ枃瀛�" />
+        </view>
+      </view>
+      <view class="courseBook">
+        <view class="selectBox">
+          <text>閫夋嫨鏁欐潗</text>
+          <t-button style="margin: 0;" bindtap="selectedBook" icon="add" content="閫夋嫨鏁欐潗" size="extra-small"></t-button>
+          <t-popup visible="{{visibleCart}}" style="top: 0;" usingCustomNavbar show-overlay="{{true}}" placement="right">
+            <view class="cartTilte">
+              <text class="cartText">閫夋嫨鏁欐潗</text>
+              <t-search value="{{selectName}}" bind:clear="changeHandleBook" bind:submit="changeHandleBook" placeholder="鎼滅储鏁欐潗鍚嶇О" clearable />
+            </view>
+            <view class="cartBox">
+              <view class="cartList" wx:if="{{cartList.length > 0}}">
+                <t-radio-group t-class="theme-card" value="{{radioVal}}" allow-uncheck bind:change="onChange">
+                  <view wx:for="{{cartList}}" wx:key="index" class="card {{radioVal == index ? 'card--active' : ''}}">
+                    <t-icon wx:if="{{radioVal == index}}" name="check" t-class="card__icon" />
+                    <t-radio value="{{index}}" label="{{item.product.name}}" icon="none" borderless>
+                      <view class="radioCon" slot='content'>
+                        <image wx:if="{{item.icon}}" class="radioIcon" src="{{item.icon}}" mode="widthFix" />
+                        <image wx:else class="radioIcon" src="/static/images/default-book-img.png" mode="widthFix" />
+                      </view>
+                    </t-radio>
+                  </view>
+                </t-radio-group>
+              </view>
+              <view wx:else>
+                <empty />
+              </view>
+            </view>
+            <view class="radioSubmit">
+              <t-button style="margin: 0;" size="extra-small" bindtap="radioCancle" variant="outline">鍏抽棴</t-button>
+              <t-button style="margin: 0 16px;" size="extra-small" bindtap="radioSubmit">纭</t-button>
+            </view>
+          </t-popup>
+        </view>
+        <view class="selectedBook">
+          <view class="selectTitle">宸查�夋暀鏉�</view>
+          <view class="selectItem" wx:if="{{selectedBook}}">
+            <image wx:if="{{item.icon}}" class="selectedIcon" src="{{selectedBook.icon}}" mode="heightFix" />
+            <image wx:else class="selectedIcon" src="/static/images/default-book-img.png" mode="heightFix" />
+            <view class="selectedItem">
+              <text class="name">{{selectedBook.product.name}}</text>
+            </view>
+          </view>
+          <view class="selectItemNot" wx:else>
+            <image class="not-icon" src="/static/images/empty.png" mode="heightFix"></image>
+            <view class="text">鏆傛棤鏁版嵁</view>
+          </view>
+        </view>
+      </view>
+      <view class="courseSubmit">
+        <t-button style="margin: 0 15px;" size="small" bindtap="cancle" variant="outline">鍙栨秷</t-button>
+        <t-button style="margin: 0;" size="small" bindtap="submitCourse">纭</t-button>
+      </view>
+    </view>
+    <view class="block" wx:if="{{pageBook.loading}}">
+      <view wx:for="{{3}}" wx:for-item="themeItem" wx:key="index">
+        <view class="demo-section__content">
+          <t-skeleton animation="gradient" theme="text"></t-skeleton>
+          <t-skeleton animation="gradient" theme="paragraph"></t-skeleton>
+        </view>
+      </view>
+    </view>
+    <t-toast id="t-toast" />
+  </t-popup>
+</view>
+
+<!-- 楠ㄦ灦灞� -->
+<import src="./index.skeleton.wxml" />
+<template is="skeleton" wx:if="{{skeletonLoding}}"></template>
+
+
+<wxs module="refresh">
+  module.exports = {
+    onPulling: function (evt, instance) {
+      var p = Math.min(evt.detail.dy / 80, 1)
+      var view = instance.selectComponent('.refresh-container')
+      view.setStyle({
+        opacity: p,
+        transform: "scale(" + p + ")"
+      })
+    }
+  }
+
+</wxs>
\ No newline at end of file
diff --git a/packageCourse/pages/course/index.wxss b/packageCourse/pages/course/index.wxss
new file mode 100644
index 0000000..e33de71
--- /dev/null
+++ b/packageCourse/pages/course/index.wxss
@@ -0,0 +1,335 @@
+/* packageCourse/pages/course/index.wxss */
+@import "./index.skeleton.wxss";
+
+
+.demo-section__content {
+  margin-top: 32rpx;
+  margin-bottom: 48rpx;
+}
+
+.contentBox {
+  width: 100%;
+  height: calc(100vh - env(safe-area-inset-bottom));
+  background-color: #eee;
+  font-size: 28rpx;
+}
+
+.refresh-container {
+  display: block;
+  width: 100vw;
+}
+
+.loading {
+  display: block;
+  width: 100%;
+  height: 180rpx;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+
+.bottom-loading {
+  width: 100vw;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  height: 100rpx;
+  padding-bottom: env(safe-area-inset-bottom);
+}
+
+.header {
+  width: 100%;
+  height: 55px;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 20rpx;
+  box-sizing: border-box;
+  border-top: 1rpx solid #eee;
+  border-bottom: 1rpx solid #eee;
+  background-color: #fff;
+}
+
+.header .t-search__input-box {
+  height: 70rpx !important;
+  font-size: 28rpx;
+}
+
+.contentList {
+  width: 100%;
+  height: calc(100% - 55px);
+  background-color: #fff;
+}
+
+.content {
+  height: 100%;
+}
+
+.listCourse {
+  padding: 20rpx;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  box-sizing: border-box;
+  height: 300rpx;
+  border-bottom: 1rpx solid #eee;
+}
+
+.courseIcon {
+  width: 200rpx;
+  height: 280rpx;
+  margin-right: 20rpx;
+}
+
+.courseInfo {
+  flex: 1;
+  display: flex;
+  flex-direction: column;
+  justify-content: flex-start;
+  height: 100%;
+}
+
+.courseInfo .title {
+  font-size: 30rpx;
+  margin-bottom: 20rpx;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.courseInfo .courseId {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  font-size: 26rpx;
+  margin-bottom: 20rpx;
+}
+
+.courseInfo .reason {
+  font-size: 24rpx;
+  color: red;
+}
+
+.courseInfo .desc {
+  font-size: 26rpx;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  display: -webkit-box;
+  -webkit-line-clamp: 2;
+  -webkit-box-orient: vertical;
+  color: #999;
+  line-height: 40rpx;
+  font-size: 24rpx;
+  width: 245px;
+  word-break: break-all;
+}
+
+.block {
+  width: 100%;
+  height: calc(100vh - env(safe-area-inset-bottom) - 60px);
+  display: flex;
+  flex-direction: column;
+  justify-content: space-between;
+  padding: 40rpx 20rpx;
+  box-sizing: border-box;
+  overflow: auto;
+}
+
+.courseData,
+.courseBook {
+  width: 100%;
+  border: 1rpx solid #f8f8f8;
+  padding: 35rpx;
+  box-sizing: border-box;
+  border-radius: 10rpx;
+  margin-bottom: 20rpx;
+}
+
+.courseData .t-input,
+.courseData .t-textarea {
+  padding: 10rpx 20rpx !important;
+  border: 1px solid #f8f8f8;
+  border-radius: 5px;
+  margin: 10px 0;
+}
+
+.courseData .t-input__wrap .t-input__content,
+.courseData .t-input__placeholder,
+.courseData .t-textarea__placeholder,
+.courseData .t-textarea__wrapper-inner {
+  font-size: 28rpx !important;
+}
+
+.selectBox {
+  width: 100%;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 10rpx 20rpx;
+  border: 1px solid #f8f8f8;
+  border-radius: 5px;
+  margin: 10px 0;
+  box-sizing: border-box;
+}
+
+.selectedBook {
+  padding: 10rpx 20rpx;
+  border: 1px solid #f8f8f8;
+  border-radius: 5px;
+  margin: 10px 0;
+  box-sizing: border-box;
+}
+
+.selectedBook .selectTitle {
+  border-bottom: 1px solid #f8f8f8;
+  padding: 10rpx 0;
+  box-sizing: border-box;
+}
+
+.selectedBook .selectItem {
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  align-items: center;
+  padding: 20rpx 10rpx;
+  box-sizing: border-box;
+}
+
+.selectItemNot {
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  align-items: center;
+  padding: 20rpx;
+  box-sizing: border-box;
+  color: #666;
+}
+
+.selectItemNot .not-icon {
+  height: 150rpx;
+  margin-bottom: 10rpx;
+}
+
+.selectItemNot .text {
+  font-size: 24rpx;
+}
+
+.selectedItem .name {
+  font-size: 26rpx;
+  margin-left: 20rpx;
+}
+
+.selectedIcon {
+  height: 200rpx;
+}
+
+.cartBox {
+  width: 85vw;
+  height: calc(100vh - env(safe-area-inset-bottom) - 80px);
+  border: 1px solid #f8f8f8;
+  overflow: auto;
+  padding: 0 20rpx;
+  box-sizing: border-box;
+}
+
+.cartBox .card--active {
+  border-color: #ff6d00 !important;
+}
+
+.cartBox .card--active::after {
+  content: '';
+  display: block;
+  position: absolute;
+  left: 0;
+  top: 0;
+  width: 0;
+  border-width: 28px 28px 28px 0;
+  border-style: solid;
+  border-color: var(--td-brand-color, #ff6d00) transparent transparent transparent;
+}
+
+.radioSubmit {
+  height: 40px;
+  border-bottom: 1rpx solid #f8f8f8;
+  display: flex;
+  justify-content: flex-end;
+  align-items: center;
+}
+
+.cartTilte {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  border: 1px solid #f8f8f8;
+  border-bottom: 0;
+  height: 40px;
+  padding: 20rpx;
+  box-sizing: border-box;
+}
+
+.cartText {
+  margin-right: 20px;
+}
+
+.cartTilte .t-search__input-box {
+  width: 330rpx !important;
+  height: 50rpx !important;
+  padding: 15rpx 10rpx;
+}
+
+.cartTilte .t-search__input-box .t-input__keyword {
+  font-size: 28rpx !important;
+}
+
+.cartTilte .t-search__input-box .t-icon {
+  font-size: 36rpx !important;
+}
+
+.card {
+  position: relative;
+  margin: 32rpx;
+  border-radius: 12rpx;
+  overflow: hidden;
+  box-sizing: border-box;
+  border: 3rpx solid var(--td-bg-color-container, #eee);
+}
+
+.card--active {
+  border-color: var(--td-brand-color, #0052d9);
+}
+
+.card--active::after {
+  content: '';
+  display: block;
+  position: absolute;
+  left: 0;
+  top: 0;
+  width: 0;
+  border-width: 28px 28px 28px 0;
+  border-style: solid;
+  border-color: var(--td-brand-color, #0052d9) transparent transparent transparent;
+}
+
+.card__icon {
+  color: var(--td-bg-color-container, #fff);
+  position: absolute;
+  left: 1.5px;
+  top: 1.5px;
+  z-index: 1;
+}
+
+.courseBook .t-radio {
+  font-size: 26rpx !important;
+}
+
+.radioIcon {
+  width: 180rpx;
+  height: 210rpx;
+}
+
+.courseSubmit {
+  width: 100%;
+  display: flex;
+  justify-content: flex-end;
+  align-items: center;
+}
\ No newline at end of file
diff --git a/packageCourse/pages/studentClass/index.js b/packageCourse/pages/studentClass/index.js
new file mode 100644
index 0000000..7ad0e99
--- /dev/null
+++ b/packageCourse/pages/studentClass/index.js
@@ -0,0 +1,296 @@
+// packageCourse/pages/studentClass/index.js
+import {
+  getPublicImage
+} from '../../../assets/js/middleGround/tool'
+import moment from 'moment'
+const app = getApp()
+Page({
+
+  /**
+   * 椤甸潰鐨勫垵濮嬫暟鎹�
+   */
+  data: {
+    searchKey: '',
+    visible: false,
+    refCode: '',
+    classDetail: null,
+    classList: [],
+    page: 1,
+    pageSize: 10,
+    totalSize: 0,
+    // 鍔犺浇鍙傛暟
+    bottomLoading: false,
+    isMoreData: false,
+    // 杩斿洖椤堕儴
+    isBackTop: false,
+    setScrollValue: 0,
+    skeletonLoding: true
+  },
+
+  /**
+   * 鐢熷懡鍛ㄦ湡鍑芥暟--鐩戝惉椤甸潰鍔犺浇
+   */
+  onLoad(options) {
+    this.getCurrentClassList()
+  },
+
+  onCourseNameInput(e) {
+    this.setData({
+      refCode: e.detail.value
+    })
+  },
+
+  // 閫氳繃code鏌ヨ鐝骇
+  getClassDetail() {
+    if (this.data.refCode == '') {
+      wx.showToast({
+        title: '璇疯緭鍏ラ個璇风爜',
+        duration: 1000,
+        icon: "none",
+      })
+      return false
+    }
+    const data = {
+      classIdOrRefCode: this.data.refCode
+    }
+    app.MG.edu
+      .getCourseClass(data)
+      .then(res => {
+        if (res) {
+          res.classTime = moment(res.beginDate).format('YYYY-MM-DD') + '--' + moment(res.endDate).format('YYYY-MM-DD')
+          this.setData({
+            classDetail: res
+          })
+        }
+      })
+      .catch(err => {
+        console.log(err)
+      })
+  },
+
+  // 鎵撳紑鏂板缓鐝骇
+  newClass() {
+    this.setData({
+      visible: true,
+    })
+  },
+
+  // 鍏抽棴鐢宠
+  cancle() {
+    this.setData({
+      visible: false
+    })
+  },
+
+  // 鐢宠鎻愪氦鐝骇
+  submitClass() {
+    if (!this.data.refCode) {
+      wx.showToast({
+        title: '璇疯緭鍏ラ個璇风爜',
+        duration: 1000,
+        icon: "none",
+      })
+      return false
+    }
+    const data = {
+      refCode: this.data.refCode
+    }
+    app.MG.identity.joinGroupByRefCode(data).then(res => {
+      if (res == '缁勪笉瀛樺湪') {
+        wx.showToast({
+          title: '鐝骇涓嶅瓨鍦�',
+          duration: 1000,
+          icon: "none",
+        })
+      }
+      if (res == '缁勬垚鍛樻暟閲忓凡鏈�澶�,涓嶈兘鍔犲叆') {
+        wx.showToast({
+          title: '宸叉弧鍛�',
+          duration: 1000,
+          icon: "none",
+        })
+      }
+      if (res == '宸茬粡鐢宠杩囧姞鍏ユ缁�') {
+        wx.showToast({
+          title: '宸茬敵璇�',
+          duration: 1000,
+          icon: "none",
+        })
+      }
+      this.getCurrentClassList()
+    })
+  },
+
+  // 鑾峰彇褰撳墠鐝骇鍒楄〃
+  getCurrentClassList(isReachBottom) {
+    const data = {
+      start: (this.data.page - 1) * this.data.pageSize,
+      size: this.data.pageSize,
+      sort: {
+        type: 'Desc',
+        field: 'CreateDate',
+        subSorts: []
+      },
+      filterList: [],
+      searchList: this.data.searchKey ? [{
+        keywords: this.data.searchKey,
+        field: 'Name',
+        compareType: 'Contains'
+      }] : []
+    }
+    app.MG.identity.joinedGroupByList(data).then(res => {
+      const {
+        datas,
+        totalSize
+      } = res
+      if (datas) {
+        let list = res.datas.map(item => {
+          return {
+            ...item,
+            classTime: moment(item.beginDate).format('YYYY.MM.DD') +
+              '--' +
+              moment(item.endDate).format('YYYY.MM.DD'),
+            bookName: item.linkProductDto.product.name,
+            bookIcon: getPublicImage(item.linkProductDto.product.icon, 100)
+          }
+        }) //瑙﹀簳鍔犺浇鏂版暟鎹苟淇濈暀鑰佹暟鎹�
+        if (isReachBottom) {
+          list = [...this.data.classList, ...list] //灏嗘柊鏁版嵁鍔犲叆鑰佹暟鎹腑
+        }
+        this.setData({
+          classList: list,
+          totalSize: totalSize,
+          visible: false,
+          skeletonLoding: false,
+          bottomLoading: false
+        })
+      }
+    })
+  },
+
+  // 鑾峰彇鏁欐潗璇︽儏
+  async getBookDetail(shopId) {
+    let query = {
+      path: 'jsek_digitalTextbooks',
+      queryType: '*',
+      productId: String(shopId),
+      storeInfo: 'jsek_digitalTextbooks',
+      coverSize: {
+        height: 300,
+        width: 210
+      },
+      fields: {
+        author: [],
+        isbn: []
+      }
+    }
+    const res = await app.MG.store.getProductDetail(query)
+    return res.datas ?? null
+  },
+
+  // 鐝骇璇︽儏
+  async todetail(e) {
+    const {
+      classId,
+      item
+    } = e.currentTarget.dataset
+    const bookData = await this.getBookDetail(item.linkProductDto?.product?.id)
+    if (item.userState == 'WaitValid' || item.userState == 'Reject') {
+      wx.showToast({
+        title: item.userState == 'WaitValid' ? '瀹℃牳涓�' : '鏈�氳繃',
+        duration: 1000,
+        icon: 'none',
+      })
+      return false
+    }
+    wx.navigateTo({
+      url: '/packageCourse/pages/teachClass/index?classId=' + classId + '&bookId=' + bookData.id + '&author=' + bookData.author + '&isbn=' + bookData.isbn + '&rootCmsItemId=' + bookData.rootCmsItemId,
+    })
+  },
+
+  /**
+   * 椤甸潰鐩稿叧浜嬩欢澶勭悊鍑芥暟--鐩戝惉鐢ㄦ埛涓嬫媺鍔ㄤ綔
+   */
+  onPullDownRefresh() {
+    if (this._freshing) return
+    this.setData({
+      page: 1,
+      bottomLoading: false,
+      isMoreData: false
+    })
+    setTimeout(() => {
+      this._freshing = true;
+      this.setData({
+        triggered: false,
+      })
+      this.getCurrentClassList();
+      this._freshing = false
+    }, 500);
+  },
+  /**
+   * 椤甸潰涓婃媺瑙﹀簳浜嬩欢鐨勫鐞嗗嚱鏁�
+   */
+  onReachBottom() {
+    if (this.data.totalSize > this.data.classList.length) {
+      this.setData({
+        page: this.data.page + 1,
+        bottomLoading: true,
+        isMoreData: false
+      })
+    } else {
+      this.setData({
+        bottomLoading: false,
+        isMoreData: true
+      })
+      return false;
+    }
+    this.getCurrentClassList(true);
+  },
+
+  // 鐩戝惉婊氬姩璺濈
+  onPageScroll(e) {
+    if (e && e.scrollTop >= 1000) {
+      this.setData({
+        isBackTop: true
+      })
+    } else {
+      this.setData({
+        isBackTop: false
+      })
+    }
+  },
+
+  /**
+   * 鐢熷懡鍛ㄦ湡鍑芥暟--鐩戝惉椤甸潰鍒濇娓叉煋瀹屾垚
+   */
+  onReady() {
+
+  },
+
+  /**
+   * 鐢熷懡鍛ㄦ湡鍑芥暟--鐩戝惉椤甸潰鏄剧ず
+   */
+  onShow() {
+
+  },
+
+  /**
+   * 鐢熷懡鍛ㄦ湡鍑芥暟--鐩戝惉椤甸潰闅愯棌
+   */
+  onHide() {
+
+  },
+
+  /**
+   * 鐢熷懡鍛ㄦ湡鍑芥暟--鐩戝惉椤甸潰鍗歌浇
+   */
+  onUnload() {
+
+  },
+  /**
+   * 鐢ㄦ埛鐐瑰嚮鍙充笂瑙掑垎浜�
+   */
+  onShareAppMessage() {
+
+  }
+})
\ No newline at end of file
diff --git a/packageCourse/pages/studentClass/index.json b/packageCourse/pages/studentClass/index.json
new file mode 100644
index 0000000..1709646
--- /dev/null
+++ b/packageCourse/pages/studentClass/index.json
@@ -0,0 +1,16 @@
+{
+  "navigationBarTitleText": "鎴戠殑鐝骇",
+  "usingComponents": {
+    "t-button": "tdesign-miniprogram/button/button",
+    "t-popup": "tdesign-miniprogram/popup/popup",
+    "t-input": "tdesign-miniprogram/input/input",
+    "t-search": "tdesign-miniprogram/search/search",
+    "t-tag": "tdesign-miniprogram/tag/tag",
+    "t-icon": "tdesign-miniprogram/icon/icon",
+    "t-calendar": "tdesign-miniprogram/calendar/calendar",
+    "t-back-top": "tdesign-miniprogram/back-top/back-top",
+    "empty": "/components/empty/index",
+    "t-skeleton": "tdesign-miniprogram/skeleton/skeleton",
+    "t-loading": "tdesign-miniprogram/loading/loading"
+  }
+}
\ No newline at end of file
diff --git a/packageCourse/pages/studentClass/index.wxml b/packageCourse/pages/studentClass/index.wxml
new file mode 100644
index 0000000..86e9e32
--- /dev/null
+++ b/packageCourse/pages/studentClass/index.wxml
@@ -0,0 +1,95 @@
+<view class="classBox">
+  <view class="header">
+    <t-search style="flex:1" value="{{searchKey}}" bind:clear="changeHandle" bind:submit="changeHandle" placeholder="鎼滅储鐝骇鍚嶇О" clearable />
+    <t-button bindtap="newClass" size="small" style="margin-left: 15rpx;">鍔犲叆鐝骇</t-button>
+  </view>
+  <view class="contentList" wx:if="{{classList.length > 0 && !classLoading}}">
+    <scroll-view class="scroll" class="content" bind:scroll="onPageScroll" model:scroll-top="{{setScrollValue}}" scroll-y refresher-enabled="{{true}}" lower-threshold="{{80}}" refresher-threshold="{{80}}" refresher-default-style="none" refresher-triggered="{{triggered}}" bindrefresherpulling="{{refresh.onPulling}}" bindrefresherrefresh="onPullDownRefresh" bindscrolltolower="onReachBottom">
+      <view slot="refresher" class="refresh-container">
+        <view class="loading">
+          <t-loading theme="circular" size="40rpx" text="姝e湪鍒锋柊..." class="wrapper" />
+        </view>
+      </view>
+      <view class="listItem">
+        <view class="listClass" wx:for="{{classList}}" wx:key="index" data-class-id="{{item.id}}" data-item="{{item}}" bindtap="todetail">
+          <view class="titleBox">
+            <text class="className">{{item.name}}</text>
+            <text class="classId" style="color: #999; font-size: 12px;"> ID: {{item.id}}</text>
+          </view>
+          <view class="infoBox">
+            <text class="classTag" wx:if="{{item.userState == 'WaitValid'}}" style="color: #ef9f29">鐘舵�� : 瀹℃牳涓�</text>
+            <text class="classTag" wx:if="{{item.userState == 'Normal'}}" style="color: #1dbd11">鐘舵�� : 杩涜涓�</text>
+            <text class="classTag" wx:if="{{item.userState == 'Reject'}}" style="color: red">鐘舵�� : 鏈�氳繃</text>
+            <t-icon bindtap="delClass" data-del-id="{{item.id}}" class="delete" wx:if="{{item.userState == 'Reject'}}" name="delete" color="red" size='18px' />
+            <text class="classTag" wx:if="{{item.userState == 'Reject'}}" style="color: red">鎷掔粷鍘熷洜锛歿{ item.reason != '' ? item.reason : '-' }}</text>
+            <text class="classTag">鐝骇浜烘暟 : {{ item.memberCount }} / {{ item.maxUserCount }}</text>
+            <text class="classTag">鏈夋晥鏈� 锛歿{ item.classTime }}</text>
+          </view>
+        </view>
+
+      </view>
+      <view class="bottom-loading" wx:if="{{bottomLoading}}">
+        <t-loading theme="circular" size="40rpx" text="鍔犺浇涓�..." class="wrapper" />
+      </view>
+      <view class="bottom-loading" style="color: #ccc;font-size: 28rpx;" wx:if="{{isMoreData}}">
+        <text>娌℃湁鏇村浜�</text>
+      </view>
+    </scroll-view>
+  </view>
+  <view class="content" wx:if="{{classList.length == 0 && !classLoading}}">
+    <empty />
+  </view>
+  <view class="block" wx:if="{{classLoading}}">
+    <view wx:for="{{4}}" wx:for-item="themeItem" wx:key="index">
+      <view class="demo-section__content">
+        <t-skeleton animation="gradient" theme="text"></t-skeleton>
+        <t-skeleton animation="gradient" theme="paragraph"></t-skeleton>
+      </view>
+    </view>
+  </view>
+  <t-popup visible="{{visible}}" usingCustomNavbar placement="bottom">
+    <view class="block-title">鐢宠鍏ョ彮</view>
+    <view class="block">
+      <view class="classInfo">
+        <view class="c-name">
+          <text>閭�璇风爜锛� </text>
+          <view class="c-name-option">
+            <t-input value="{{refCode}}" bindchange="onCourseNameInput" borderless clearable placeholder="璇疯緭鍏ラ個璇风爜" />
+            <t-button bindtap="getClassDetail" size="small" style="margin-left: 15rpx;">鏌ョ湅鐝骇</t-button>
+          </view>
+        </view>
+        <view class="c-desc">
+          <view class="c-desc-title">鐝骇淇℃伅锛�</view>
+          <view class="classData" wx:if="{{classDetail}}">
+            <view>鐝骇鍚嶇О锛歿{ classDetail.name }}</view>
+            <view>鐝骇浜烘暟锛歿{ classDetail.memberCount }} / {{ classDetail.maxUserCount }}</view>
+            <view>寮�璇炬椂闂达細{{classDetail.classTime}}</view>
+          </view>
+          <view class="classData" wx:else>
+            <view>鐝骇鍚嶇О锛�-</view>
+            <view>鐝骇浜烘暟锛�-</view>
+            <view>寮�璇炬椂闂达細-</view>
+          </view>
+        </view>
+      </view>
+      <view class="classSubmit">
+        <t-button style="padding: 0 25px; margin:0 15px;" size="small" bindtap="cancle" variant="outline">鍙栨秷</t-button>
+        <t-button style="padding: 0 25px; margin:0;" size="small" bindtap="submitClass">鍔犲叆</t-button>
+      </view>
+    </view>
+  </t-popup>
+</view>
+
+<wxs module="refresh">
+  module.exports = {
+    onPulling: function (evt, instance) {
+      var p = Math.min(evt.detail.dy / 80, 1)
+      var view = instance.selectComponent('.refresh-container')
+      view.setStyle({
+        opacity: p,
+        transform: "scale(" + p + ")"
+      })
+    }
+  }
+
+</wxs>
\ No newline at end of file
diff --git a/packageCourse/pages/studentClass/index.wxss b/packageCourse/pages/studentClass/index.wxss
new file mode 100644
index 0000000..f2dcebf
--- /dev/null
+++ b/packageCourse/pages/studentClass/index.wxss
@@ -0,0 +1,223 @@
+/* packageCourse/pages/course/detail/index.wxss */
+
+
+.demo-section__content {
+  margin-top: 32rpx;
+  margin-bottom: 48rpx;
+}
+
+.contentTabBox {
+  width: 100%;
+  height: calc(100vh - env(safe-area-inset-bottom));
+  font-size: 28rpx;
+  position: relative;
+}
+
+.refresh-container {
+  display: block;
+  width: 100vw;
+}
+
+.loading {
+  display: block;
+  width: 100%;
+  height: 180rpx;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+
+.bottom-loading {
+  width: 100vw;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  height: 100rpx;
+  padding-bottom: env(safe-area-inset-bottom);
+}
+
+.classBox {
+  height: 100%;
+}
+
+.contentList {
+  width: 100%;
+  height: calc(100% - 55px);
+}
+
+.content {
+  height: 100%;
+}
+
+.listItem {
+  width: 100%;
+  height: 100%;
+  padding: 5px 20rpx;
+  box-sizing: border-box;
+}
+
+.listClass {
+  border: 1rpx solid #efefef;
+  margin-bottom: 20rpx;
+  border-radius: 10rpx;
+}
+
+.listClass .titleBox {
+  width: 100%;
+  height: 60rpx;
+  display: flex;
+  padding: 5rpx 20rpx;
+  justify-content: space-between;
+  align-items: center;
+  background-color: #f8f8f8;
+  font-size: 30rpx;
+  box-sizing: border-box;
+}
+
+.listClass .infoBox {
+  display: flex;
+  flex-direction: column;
+  padding: 20rpx;
+  box-sizing: border-box;
+  position: relative;
+  font-size: 24rpx;
+}
+
+.classTag {
+  margin-bottom: 20rpx;
+}
+
+.className {
+  width: 250px;
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  margin-right: 20rpx;
+}
+
+.delete {
+  position: absolute;
+  right: 20rpx;
+}
+
+
+.tabbar-bottom {
+  width: 100%;
+  height: 60px;
+  display: flex;
+  justify-content: space-around;
+  align-items: center;
+  border-top: 1rpx solid #eee;
+  position: absolute;
+  bottom: 0;
+  left: 0;
+}
+
+.tab-pubItem {
+  color: #999;
+}
+
+.tabbar-bottom .tabIcon {
+  margin-bottom: 10rpx;
+}
+
+.tabbar-bottom .text {
+  font-size: 24rpx;
+}
+
+.activeTab {
+  color: #ff6d00;
+}
+
+.header {
+  width: 100%;
+  height: 55px;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 20rpx;
+  box-sizing: border-box;
+  border-top: 1rpx solid #eee;
+  border-bottom: 1rpx solid #eee;
+  background-color: #fff;
+}
+
+.header .t-search__input-box {
+  height: 70rpx !important;
+  font-size: 28rpx;
+}
+
+.classInfo {
+  width: 100%;
+  border: 1rpx solid #eee;
+  padding: 35rpx;
+  box-sizing: border-box;
+  border-radius: 10rpx;
+  margin-bottom: 20rpx;
+  font-size: 26rpx;
+}
+
+.classInfo .t-input,
+.classInfo .t-textarea {
+  padding: 10rpx 20rpx !important;
+  border: 1px solid #eee;
+  border-radius: 5px;
+  margin: 10px 0;
+}
+
+.classInfo .t-input__wrap .t-input__content,
+.classInfo .t-input__placeholder,
+.classInfo .t-textarea__placeholder,
+.classInfo .t-textarea__wrapper-inner {
+  font-size: 26rpx !important;
+}
+
+.classInfo .dateBox {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.classSubmit {
+  width: 100%;
+  display: flex;
+  justify-content: flex-end;
+  align-items: center;
+  margin-bottom: 20rpx;
+  padding: 0 20px;
+  box-sizing: border-box;
+}
+
+.c-name-option {
+  display: flex;
+  justify-content: flex-end;
+  align-items: center;
+}
+
+.c-desc-title {
+  margin-bottom: 10rpx;
+}
+
+.classData {
+  width: 100%;
+  height: 180rpx;
+  border: 1px solid #eee;
+  padding: 20rpx;
+  box-sizing: border-box;
+  border-radius: 10rpx;
+  display: flex;
+  flex-direction: column;
+  justify-content: space-around;
+  align-items: flex-start;
+  color: #666666;
+}
+
+.classBox .t-overlay {
+  top: 55px !important
+}
+
+.block-title {
+  padding: 30rpx 20rpx;
+  font-size: 30rpx;
+  color: #ff6d00;
+}
\ No newline at end of file
diff --git a/packageCourse/pages/teachClass/detail/index.js b/packageCourse/pages/teachClass/detail/index.js
new file mode 100644
index 0000000..00cea8e
--- /dev/null
+++ b/packageCourse/pages/teachClass/detail/index.js
@@ -0,0 +1,309 @@
+// packageCourse/components/teaching/detail/index.js.js
+const app = getApp()
+import moment from 'moment'
+Page({
+
+  /**
+   * 椤甸潰鐨勫垵濮嬫暟鎹�
+   */
+  data: {
+    teachInteractionId: null,
+    dialogLLoading: false,
+    dialogList: [],
+    visible: false,
+    bookId: null,
+    questionId: null,
+    dataList: [],
+    searchKey: ''
+  },
+
+  /**
+   * 鐢熷懡鍛ㄦ湡鍑芥暟--鐩戝惉椤甸潰鍔犺浇
+   */
+  onLoad(options) {
+    if (options) {
+      this.setData({
+        teachInteractionId: options.teachInteractionId,
+        questionName: options.questionName,
+        bookId: options.bookId,
+        questionId: options.questionId
+      })
+    }
+    wx.setNavigationBarTitle({
+      title: '浜掑姩瀛︾敓鍒楄〃',
+    })
+    this.getMessage()
+  },
+
+  openLook(e) {
+    const {
+      item
+    } = e.currentTarget.dataset
+    this.setData({
+      visible: true
+    })
+    this.getQuestions(item)
+  },
+
+  close() {
+    this.setData({
+      visible: false
+    })
+  },
+
+  // 鎼滅储
+  changeHandle(e) {
+    const {
+      value
+    } = e.detail;
+    let cmsList = this.data.dataList
+    this.setData({
+      dataList: []
+    })
+    if (value) {
+      const data = cmsList.filter(item => item.userName.indexOf(value) > -1);
+      this.setData({
+        dataList: data
+      })
+    }
+    if (value == '') {
+      this.setData({
+        dataList: [],
+        loading: true
+      })
+      this.getMessage()
+    }
+  },
+
+  // 鑾峰彇褰撳墠璇濋
+  getMessage() {
+    const data = {
+      start: 0,
+      size: 999,
+      appRefCode: app.config.appRefCode,
+      topicIdOrRefCode: String(this.data.teachInteractionId),
+      sort: {
+        type: 'Desc',
+        field: 'CreateDate'
+      },
+      searchList: [{
+        keywords: this.data.questionName,
+        field: 'Name',
+        compareType: 'Contains'
+      }]
+    }
+    app.MG.ugc.getTopicMessageList(data).then((res) => {
+      const list = res.datas.map((item, i) => {
+        item.question = []
+        item.bookId = null
+        item.path = ''
+        item.index = i + 1
+        try {
+          const obj = JSON.parse(item.content)
+          if (obj.bookId) {
+            item.question = obj.content
+            item.bookId = obj.bookId
+            item.path = obj.path
+            item.userName = obj.userName ?? '-'
+          }
+        } catch (error) {
+          console.log(item)
+        }
+        return {
+          ...item,
+          questionTime: moment(item.updateDate).format('YYYY-MM-DD HH:mm:ss')
+        }
+      })
+      this.setData({
+        dataList: list,
+        loading: false
+      })
+    })
+  },
+
+  // 鑾峰彇棰樼洰鍒楄〃
+  getQuestions(item) {
+    app.MG.store
+      .getProductDetail({
+        path: '*',
+        queryType: '*',
+        productId: this.data.bookId,
+        cmsPath: item.path,
+        itemFields: {
+          Embedded_QuestionBank_AnalysisCon: [],
+          Embedded_QuestionBank_Answer: [],
+          Embedded_QuestionBank_Difficulty: [],
+          Embedded_QuestionBank_KnowledgePoint: [],
+          Embedded_QuestionBank_Option: [],
+          Embedded_QuestionBank_OptionStyle: [],
+          Embedded_QuestionBank_QuestionType: [],
+          Embedded_QuestionBank_Score: [],
+          Embedded_QuestionBank_Stem: [],
+          Embedded_QuestionBank_StemStyle: []
+        }
+      })
+      .then((res) => {
+        try {
+          let list = []
+          list = res.datas.cmsDatas[0]?.datas.map((item) => {
+            try {
+              if (item.Embedded_QuestionBank_Stem) {
+                item.questionStem = JSON.parse(item.Embedded_QuestionBank_Stem)
+              }
+              if (
+                item.Embedded_QuestionBank_Option &&
+                item.Embedded_QuestionBank_Option.indexOf('[') > -1
+              ) {
+                item.questionOption = JSON.parse(item.Embedded_QuestionBank_Option)
+              }
+              if (
+                item.Embedded_QuestionBank_Answer &&
+                item.Embedded_QuestionBank_Answer.indexOf('[') > -1
+              ) {
+                item.Embedded_QuestionBank_Answer = JSON.parse(item.Embedded_QuestionBank_Answer)
+              }
+              return {
+                ...item,
+                questionType: item.Embedded_QuestionBank_QuestionType,
+                questionAnalysisCon: item.Embedded_QuestionBank_AnalysisCon,
+                questionAnswer: item.Embedded_QuestionBank_Answer,
+                customAnswer: null
+              }
+            } catch (error) {
+              console.log(item)
+            }
+          })
+          const data = this.chageData([item], list)
+          this.setData({
+            dialogList: data
+          })
+        } catch (error) {
+          this.setData({
+            dialogList: []
+          })
+        }
+      })
+  },
+  // 澶勭悊鏁版嵁缁撴瀯
+  chageData(arr, zrr) {
+    let newData = []
+    // 棰樺簱棰樼洰绫诲瀷
+    const questionTypeList = [{
+        name: '鍗曢�夐',
+        value: 'singleChoice',
+        data: []
+      },
+      {
+        name: '澶氶�夐',
+        value: 'multipleChoice',
+        data: []
+      },
+      {
+        name: '鍒ゆ柇棰�',
+        value: 'judge',
+        data: []
+      },
+      {
+        name: '绠�绛旈',
+        value: 'shortAnswer',
+        data: []
+      },
+      {
+        name: '璁鸿堪棰�',
+        value: 'discuss',
+        data: []
+      },
+      {
+        name: '濉┖棰�',
+        value: 'completion',
+        data: []
+      },
+      {
+        name: '杩炵嚎棰�',
+        value: 'matching',
+        data: []
+      },
+      {
+        name: '鍒嗙被棰�',
+        value: 'classification',
+        data: []
+      }
+    ]
+    for (let i = 0; i < arr.length; i++) {
+      const item = arr[i]
+      item.questionTypeList = questionTypeList
+      for (let j = 0; j < zrr.length; j++) {
+        const ele = zrr[j]
+        const qusObj = item.question.find((citem) => citem.cmsItemId == ele.id)
+        if (qusObj?.cmsItemId) {
+          ele.userAnswer = qusObj.answer
+          const index = this.findIndexByValue(questionTypeList, ele.questionType)
+          if (index > -1) {
+            item.questionTypeList[index].data.push(ele)
+          }
+        }
+      }
+      item.questionTypeList = item.questionTypeList.filter((item) => item.data.length > 0)
+      newData.push(item)
+    }
+    return newData.filter((item) => item.questionTypeList.length > 0)
+  },
+
+  findIndexByValue(res, type) {
+    for (let i = 0; i < res.length; i++) {
+      if (res[i].value == type) {
+        return i
+      }
+    }
+    return -1 // 濡傛灉鏈壘鍒帮紝鍒欒繑鍥� -1
+  },
+
+  /**
+   * 鐢熷懡鍛ㄦ湡鍑芥暟--鐩戝惉椤甸潰鍒濇娓叉煋瀹屾垚
+   */
+  onReady() {
+
+  },
+
+  /**
+   * 鐢熷懡鍛ㄦ湡鍑芥暟--鐩戝惉椤甸潰鏄剧ず
+   */
+  onShow() {
+
+  },
+
+  /**
+   * 鐢熷懡鍛ㄦ湡鍑芥暟--鐩戝惉椤甸潰闅愯棌
+   */
+  onHide() {
+
+  },
+
+  /**
+   * 鐢熷懡鍛ㄦ湡鍑芥暟--鐩戝惉椤甸潰鍗歌浇
+   */
+  onUnload() {
+
+  },
+
+  /**
+   * 椤甸潰鐩稿叧浜嬩欢澶勭悊鍑芥暟--鐩戝惉鐢ㄦ埛涓嬫媺鍔ㄤ綔
+   */
+  onPullDownRefresh() {
+
+  },
+
+  /**
+   * 椤甸潰涓婃媺瑙﹀簳浜嬩欢鐨勫鐞嗗嚱鏁�
+   */
+  onReachBottom() {
+
+  },
+
+  /**
+   * 鐢ㄦ埛鐐瑰嚮鍙充笂瑙掑垎浜�
+   */
+  onShareAppMessage() {
+
+  }
+})
\ No newline at end of file
diff --git a/packageCourse/pages/teachClass/detail/index.json b/packageCourse/pages/teachClass/detail/index.json
new file mode 100644
index 0000000..473542f
--- /dev/null
+++ b/packageCourse/pages/teachClass/detail/index.json
@@ -0,0 +1,11 @@
+{
+  "component": true,
+  "usingComponents": {
+    "t-search": "tdesign-miniprogram/search/search",
+    "t-skeleton": "tdesign-miniprogram/skeleton/skeleton",
+    "empty": "/components/empty/index",
+    "t-icon": "tdesign-miniprogram/icon/icon",
+    "t-popup": "tdesign-miniprogram/popup/popup",
+    "questionDom": "/packageCourse/components/questionDom/index"
+  }
+}
\ No newline at end of file
diff --git a/packageCourse/pages/teachClass/detail/index.wxml b/packageCourse/pages/teachClass/detail/index.wxml
new file mode 100644
index 0000000..cd31e34
--- /dev/null
+++ b/packageCourse/pages/teachClass/detail/index.wxml
@@ -0,0 +1,42 @@
+<!--packageCourse/components/teaching/index.wxml-->
+<view class="teachBox">
+  <view class="header">
+    <t-search style="flex:1" value="{{searchKey}}" bind:clear="changeHandle" bind:submit="changeHandle" placeholder="鎼滅储鐢ㄦ埛鍚嶇О" clearable />
+  </view>
+  <view class="count">鍏辫 <text style="color: #ff6d00;">{{dataList.length}}</text> 浜虹瓟棰�</view>
+  <view class="teachContent" wx:if="{{dataList.length > 0 && !loading}}">
+    <view class="list" wx:for="{{dataList}}" wx:key="index" bindtap="openLook" data-item="{{item}}">
+      <view class="questionName">鐢ㄦ埛鍚嶏細<text style="color: #ff6d00;">{{item.userName}}</text></view>
+      <view class="questionInfo">
+        <view class="questionCount">
+          <text style="color: #67c23a"> 宸茬瓟瀹�</text>
+        </view>
+        <view class="questionDate">
+          {{item.questionTime}}
+        </view>
+      </view>
+    </view>
+  </view>
+  <view class="she" wx:if="{{loading}}">
+    <view wx:for="{{10}}" wx:for-item="themeItem" wx:key="index">
+      <view class="demo-section__content">
+        <t-skeleton theme="text"></t-skeleton>
+      </view>
+    </view>
+  </view>
+  <view class="she" wx:if="{{dataList.length == 0 && !loading}}">
+    <empty />
+  </view>
+  <t-popup visible="{{visible}}" usingCustomNavbar placement="bottom">
+    <view class="block-question-title">
+      <text class="block-question-title-text">绛旈娴忚</text>
+      <t-icon size="22px" bindtap="close" color="#999" name="close"></t-icon>
+    </view>
+    <view class="block-question">
+      <view class="block-question-list" wx:for="{{dialogList}}" wx:key="index">
+        <view class="block-question-user">绛旈浜猴細{{ item.userNme }}</view>
+        <questionDom wx:if="{{item.questionTypeList.length > 0}}" questionList="{{item.questionTypeList}}" noCheckbox="{{false}}" is-preview="{{true}}" />
+      </view>
+    </view>
+  </t-popup>
+</view>
\ No newline at end of file
diff --git a/packageCourse/pages/teachClass/detail/index.wxss b/packageCourse/pages/teachClass/detail/index.wxss
new file mode 100644
index 0000000..f2e4be5
--- /dev/null
+++ b/packageCourse/pages/teachClass/detail/index.wxss
@@ -0,0 +1,92 @@
+/* packageCourse/components/teaching/index.wxss */
+.teachBox {
+  width: 100%;
+  height: 100%;
+  font-size: 28rpx;
+}
+
+.teachBox .t-overlay {
+  top: 85rpx !important
+}
+
+.header {
+  width: 100%;
+  padding: 0 20rpx;
+  box-sizing: border-box;
+}
+
+.teachContent {
+  width: 100%;
+  padding: 20rpx;
+  box-sizing: border-box;
+}
+
+.teachBox .count {
+  width: 100%;
+  padding: 20rpx;
+  box-sizing: border-box;
+  border-bottom: 1rpx solid #eee;
+}
+
+.teachContent .questionInfo {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.teachContent .questionName {
+  margin-bottom: 10rpx;
+}
+
+.teachContent .list {
+  width: 100%;
+  margin-bottom: 20rpx;
+  border-bottom: 1px solid #eee;
+  padding: 20rpx 0;
+  box-sizing: border-box;
+}
+
+.block-question-title {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  height: 40px;
+  padding: 0 20rpx;
+  font-size: 30rpx;
+  border-bottom: 1rpx solid #eee;
+}
+
+.block-question {
+  height: calc(100vh - 80px - 40px - 40px);
+  padding: 20rpx;
+  box-sizing: border-box;
+  overflow-y: auto;
+}
+
+.block-question-title-text {
+  color: #ff6d00;
+}
+
+.block-question-user {
+  margin-bottom: 20rpx;
+  color: #ff6d00;
+}
+
+
+.demo-section__content {
+  margin-top: 32rpx;
+  margin-bottom: 48rpx;
+}
+
+.block-question .t-textarea {
+  padding: 0 !important;
+}
+
+.block-question .t-textarea__wrapper-inner {
+  font-size: 26rpx !important;
+}
+
+.block-question .t-input__placeholder,
+.block-question .t-textarea__placeholder {
+  font-size: 26rpx !important;
+}
\ No newline at end of file
diff --git a/packageCourse/pages/teachClass/index.js b/packageCourse/pages/teachClass/index.js
new file mode 100644
index 0000000..5277bdc
--- /dev/null
+++ b/packageCourse/pages/teachClass/index.js
@@ -0,0 +1,118 @@
+// packageCourse/pages/class/index.js
+Page({
+
+  /**
+   * 椤甸潰鐨勫垵濮嬫暟鎹�
+   */
+  data: {
+    tabVal: 'base',
+    classId: null,
+    bookId: null,
+    rootCmsItemId: null,
+    courseData: null,
+    userData: null,
+    defaultCmsPath: ''
+  },
+
+  /**
+   * 鐢熷懡鍛ㄦ湡鍑芥暟--鐩戝惉椤甸潰鍔犺浇
+   */
+  onLoad(options) {
+    if (options) {
+      this.setData({
+        classId: options.classId,
+        bookId: options.bookId,
+        rootCmsItemId: options.rootCmsItemId,
+        courseData: {
+          courseId: options.courseId,
+          author: options.author,
+          isbn: options.isbn
+        },
+        defaultCmsPath: options.bookRefCode
+      })
+    }
+    const data = wx.getStorageSync('website-front-userInfo')
+    if (data) {
+      this.setData({
+        userData: JSON.parse(data)
+      })
+    }
+    wx.setNavigationBarTitle({
+      title: '鍩烘湰淇℃伅',
+    })
+  },
+
+  // tab鍒囨崲
+  tabActive(e) {
+    const {
+      str
+    } = e.currentTarget.dataset
+    this.setData({
+      tabVal: str,
+    })
+    if (str == 'base') {
+      wx.setNavigationBarTitle({
+        title: '鍩烘湰淇℃伅',
+      })
+    }
+    if (str == 'studentManage') {
+      wx.setNavigationBarTitle({
+        title: '瀛︾敓绠$悊',
+      })
+    }
+    if (str == 'teach') {
+      wx.setNavigationBarTitle({
+        title: '鏁欏浜掑姩',
+      })
+    }
+  },
+
+  /**
+   * 鐢熷懡鍛ㄦ湡鍑芥暟--鐩戝惉椤甸潰鍒濇娓叉煋瀹屾垚
+   */
+  onReady() {
+
+  },
+
+  /**
+   * 鐢熷懡鍛ㄦ湡鍑芥暟--鐩戝惉椤甸潰鏄剧ず
+   */
+  onShow() {
+
+  },
+
+  /**
+   * 鐢熷懡鍛ㄦ湡鍑芥暟--鐩戝惉椤甸潰闅愯棌
+   */
+  onHide() {
+
+  },
+
+  /**
+   * 鐢熷懡鍛ㄦ湡鍑芥暟--鐩戝惉椤甸潰鍗歌浇
+   */
+  onUnload() {
+
+  },
+
+  /**
+   * 椤甸潰鐩稿叧浜嬩欢澶勭悊鍑芥暟--鐩戝惉鐢ㄦ埛涓嬫媺鍔ㄤ綔
+   */
+  onPullDownRefresh() {
+
+  },
+
+  /**
+   * 椤甸潰涓婃媺瑙﹀簳浜嬩欢鐨勫鐞嗗嚱鏁�
+   */
+  onReachBottom() {
+
+  },
+
+  /**
+   * 鐢ㄦ埛鐐瑰嚮鍙充笂瑙掑垎浜�
+   */
+  onShareAppMessage() {
+
+  }
+})
\ No newline at end of file
diff --git a/packageCourse/pages/teachClass/index.json b/packageCourse/pages/teachClass/index.json
new file mode 100644
index 0000000..e5fb553
--- /dev/null
+++ b/packageCourse/pages/teachClass/index.json
@@ -0,0 +1,8 @@
+{
+  "usingComponents": {
+    "t-icon": "tdesign-miniprogram/icon/icon",
+    "base": "/packageCourse/components/baseClass/index",
+    "studentManage": "/packageCourse/components/studentManage/index",
+    "Teach": "/packageCourse/components/teaching"
+  }
+}
\ No newline at end of file
diff --git a/packageCourse/pages/teachClass/index.wxml b/packageCourse/pages/teachClass/index.wxml
new file mode 100644
index 0000000..d3d9e02
--- /dev/null
+++ b/packageCourse/pages/teachClass/index.wxml
@@ -0,0 +1,31 @@
+<!--packageCourse/pages/class/index.wxml-->
+<view class="contentTabBox">
+  <view class="showInfo">
+    <!-- 鍩烘湰淇℃伅 -->
+    <view class="baseInfoBox" wx:if="{{tabVal == 'base'}}">
+      <base classId="{{classId}}" courseData="{{courseData}}" bookRefCode="{{defaultCmsPath}}" />
+    </view>
+    <!-- 瀛︾敓绠$悊 -->
+    <view class="classBox" wx:if="{{tabVal == 'studentManage' && userData.role == 'Teacher'}}">
+      <studentManage classId="{{classId}}" bookRefCode="{{defaultCmsPath}}" />
+    </view>
+    <!-- 鏁欏浜掑姩 -->
+    <view class="teachBox" wx:if="{{tabVal == 'teach'}}">
+      <Teach classId="{{classId}}" bookId="{{bookId}}" rootCmsItemId="{{rootCmsItemId}}" />
+    </view>
+  </view>
+  <view class="tabbar-bottom">
+    <view class="{{tabVal == 'base'?'tab-pubItem activeTab':'tab-pubItem'}}" data-str="base" bindtap="tabActive">
+      <t-icon class="tabIcon" name="home-filled" size="24px" />
+      <text class="text">鍩烘湰淇℃伅</text>
+    </view>
+    <view wx:if="{{ userData.role == 'Teacher'}}" class="{{tabVal == 'studentManage'?'tab-pubItem activeTab':'tab-pubItem'}}" data-str="studentManage" bindtap="tabActive">
+      <t-icon class="tabIcon" name="file-setting-filled" size="24px" />
+      <text class="text">瀛︾敓绠$悊</text>
+    </view>
+    <view class="{{tabVal == 'teach'?'tab-pubItem activeTab':'tab-pubItem'}}" data-str="teach" bindtap="tabActive">
+      <t-icon class="tabIcon" name="system-setting" size="24px" />
+      <text class="text">鏁欏浜掑姩</text>
+    </view>
+  </view>
+</view>
\ No newline at end of file
diff --git a/packageCourse/pages/teachClass/index.wxss b/packageCourse/pages/teachClass/index.wxss
new file mode 100644
index 0000000..6355bc2
--- /dev/null
+++ b/packageCourse/pages/teachClass/index.wxss
@@ -0,0 +1,56 @@
+/* packageCourse/pages/class/index.wxss */
+.contentTabBox {
+  width: 100%;
+  height: calc(100vh - env(safe-area-inset-bottom));
+  font-size: 28rpx;
+  position: relative;
+}
+
+.showInfo {
+  width: 100%;
+  height: calc(100% - 60px);
+  overflow: hidden;
+}
+
+.baseInfoBox,
+.classBox,
+.teachBox {
+  width: 100%;
+  height: 100%;
+}
+
+.contentTabBox .t-overlay {
+  top: 55px !important
+}
+
+.contentTabBox .t-radio__icon--checked {
+  color: #ff6d00 !important;
+}
+
+.tabbar-bottom {
+  width: 100%;
+  height: 60px;
+  display: flex;
+  justify-content: space-around;
+  align-items: center;
+  border-top: 1rpx solid #eee;
+  position: absolute;
+  bottom: 0;
+  left: 0;
+}
+
+.tab-pubItem {
+  color: #999;
+}
+
+.activeTab {
+  color: #ff6d00;
+}
+
+.tabbar-bottom .tabIcon {
+  margin-bottom: 10rpx;
+}
+
+.tabbar-bottom .text {
+  font-size: 24rpx;
+}
\ No newline at end of file
diff --git a/pages/personalCenter/index.js b/pages/personalCenter/index.js
index 6199b78..dc75193 100644
--- a/pages/personalCenter/index.js
+++ b/pages/personalCenter/index.js
@@ -53,6 +53,18 @@
     // url: '',
     url: '/packagePersonal/pages/publishBooks/index',
     type: 'publishBooks',
+  },
+  {
+    title: '鎴戠殑璇剧▼',
+    icon: '/static/images/personal/course.png',
+    url: '/packageCourse/pages/course/index',
+    type: 'course',
+  },
+  {
+    title: '鎴戠殑鐝骇',
+    icon: '/static/images/personal/class.png',
+    url: '/packageCourse/pages/studentClass/index',
+    type: 'class',
   }
 ];
 const moreMenu = [{
diff --git a/pages/personalCenter/index.wxss b/pages/personalCenter/index.wxss
index cbd2c65..11f0acd 100644
--- a/pages/personalCenter/index.wxss
+++ b/pages/personalCenter/index.wxss
@@ -105,7 +105,9 @@
   width: 100%;
   display: flex;
   flex-wrap: wrap;
-  justify-content: center;
+  justify-content: flex-start;
+  padding: 15rpx 25rpx;
+  box-sizing: border-box;
 }
 
 .domainList1 {
@@ -125,15 +127,15 @@
   width: 160rpx;
   min-width: 160rpx;
   flex-shrink: 0;
-  padding: 40rpx 0;
+  padding: 20rpx 0;
 }
 
-.listItem:nth-child(5),
+/* .listItem:nth-child(5),
 .listItem:nth-child(6),
 .listItem:nth-child(7),
 .listItem:nth-child(8) {
   padding-top: 10rpx !important;
-}
+} */
 
 .listItem .icon {
   width: 48rpx;
diff --git a/static/images/personal/class.png b/static/images/personal/class.png
new file mode 100644
index 0000000..d0cca8c
--- /dev/null
+++ b/static/images/personal/class.png
Binary files differ
diff --git a/static/images/personal/course.png b/static/images/personal/course.png
new file mode 100644
index 0000000..0e70fdb
--- /dev/null
+++ b/static/images/personal/course.png
Binary files differ

--
Gitblit v1.9.1