From b15a997e95d715c41df3a76aecbf58ec1141ab53 Mon Sep 17 00:00:00 2001
From: qiyunfeng-create <1940665526@qq.com>
Date: 星期四, 21 八月 2025 18:37:17 +0800
Subject: [PATCH] 个人中心-接口测试

---
 src/assets/images/personalCenter/notification.svg  |    1 
 src/views/classManage/jobDetail.vue                |  840 +++
 src/views/personalCenter/teacherCertification.vue  |  858 +++
 src/views/personalCenter/class.vue                 |  461 +
 src/views/personalCenter/course.vue                |  654 ++
 src/assets/js/config.js                            |   22 
 src/views/personalCenter/myCollection.vue          |  348 +
 package-lock.json                                  |   83 
 src/views/classManage/talkDetail.vue               |  481 +
 src/views/classManage/components/headerPage.vue    |  288 +
 src/views/personalCenter/myMessage.vue             |  205 
 src/assets/images/default-book-img.png             |    0 
 src/store/modules/breadcrumb.ts                    |   96 
 src/views/classManage/config.ts                    |  106 
 src/views/classManage/index.vue                    |  283 +
 src/views/classManage/classHome.vue                |  778 ++
 src/views/personalCenter/myBook.vue                |  328 +
 src/assets/main.css                                |   38 
 src/views/classManage/infoList.vue                 |  254 
 src/views/classManage/jobAnalysis.vue              |  331 +
 src/assets/images/personalCenter/collect-click.png |    0 
 src/store/modules/user.ts                          |  149 
 src/views/classManage/studentJob.vue               |  357 +
 src/views/classManage/jobManage.vue                | 1895 +++++++
 src/assets/js/middleGround/api/identity.js         |  171 
 src/router/index.js                                |  134 
 src/views/classManage/teachInteraction.vue         |  512 +
 src/store/index.ts                                 |    9 
 src/views/personalCenter/config.ts                 |    2 
 /dev/null                                          |   12 
 src/views/classManage/prepareLessons.vue           |   22 
 src/views/classManage/studentManage.vue            |  475 +
 src/assets/js/middleGround/api/edu.js              |   18 
 src/views/classManage/interactionDetail.vue        |  373 +
 src/views/classManage/teachingPlan.vue             |  855 +++
 src/views/personalCenter/userInfo.vue              |  687 +-
 src/views/classManage/components/questionDom.vue   |  420 +
 src/views/classManage/testManage.vue               |   22 
 src/views/courseManage/components/class.vue        |  502 +
 src/assets/base.css                                |  152 
 src/views/classManage/talkingPoint.vue             |  375 +
 src/views/personalCenter/activeCode.vue            |  398 +
 src/views/personalCenter/myApply.vue               |  317 +
 src/assets/images/personalCenter/book-cover.png    |    0 
 src/views/personalCenter/myOrder.vue               |  494 +
 package.json                                       |    1 
 src/views/courseManage/index.vue                   |  228 
 src/views/personalCenter/myCart.vue                |  598 ++
 48 files changed, 15,150 insertions(+), 483 deletions(-)

diff --git a/package-lock.json b/package-lock.json
index e86f843..6c62642 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -15,6 +15,7 @@
         "pinia": "^3.0.3",
         "spark-md5": "^3.0.2",
         "vue": "^3.5.18",
+        "vue-clipboard3": "^2.0.0",
         "vue-router": "^4.5.1"
       },
       "devDependencies": {
@@ -1740,6 +1741,16 @@
         }
       ]
     },
+    "node_modules/clipboard": {
+      "version": "2.0.11",
+      "resolved": "https://registry.npmmirror.com/clipboard/-/clipboard-2.0.11.tgz",
+      "integrity": "sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==",
+      "dependencies": {
+        "good-listener": "^1.2.2",
+        "select": "^1.1.2",
+        "tiny-emitter": "^2.0.0"
+      }
+    },
     "node_modules/combined-stream": {
       "version": "1.0.8",
       "resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz",
@@ -1862,6 +1873,11 @@
       "engines": {
         "node": ">=0.4.0"
       }
+    },
+    "node_modules/delegate": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmmirror.com/delegate/-/delegate-3.2.0.tgz",
+      "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw=="
     },
     "node_modules/dunder-proto": {
       "version": "1.0.1",
@@ -2225,6 +2241,14 @@
       },
       "funding": {
         "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/good-listener": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmmirror.com/good-listener/-/good-listener-1.2.2.tgz",
+      "integrity": "sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw==",
+      "dependencies": {
+        "delegate": "^3.1.2"
       }
     },
     "node_modules/gopd": {
@@ -2974,6 +2998,11 @@
       "license": "ISC",
       "optional": true
     },
+    "node_modules/select": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmmirror.com/select/-/select-1.1.2.tgz",
+      "integrity": "sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA=="
+    },
     "node_modules/semver": {
       "version": "6.3.1",
       "resolved": "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz",
@@ -3084,6 +3113,11 @@
       "engines": {
         "node": ">=16"
       }
+    },
+    "node_modules/tiny-emitter": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmmirror.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
+      "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q=="
     },
     "node_modules/tinyglobby": {
       "version": "0.2.14",
@@ -3390,6 +3424,14 @@
         "typescript": {
           "optional": true
         }
+      }
+    },
+    "node_modules/vue-clipboard3": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmmirror.com/vue-clipboard3/-/vue-clipboard3-2.0.0.tgz",
+      "integrity": "sha512-Q9S7dzWGax7LN5iiSPcu/K1GGm2gcBBlYwmMsUc5/16N6w90cbKow3FnPmPs95sungns4yvd9/+JhbAznECS2A==",
+      "dependencies": {
+        "clipboard": "^2.0.6"
       }
     },
     "node_modules/vue-router": {
@@ -4527,6 +4569,16 @@
       "integrity": "sha512-EV/laoX7Wq2J9TQlyIXRxTJqIw4sxfXS4OYgudGxBYRuTv0q7AM6yMEpU/Vo1I94thg9U6EZ2NfZx9GJq83u7w==",
       "dev": true
     },
+    "clipboard": {
+      "version": "2.0.11",
+      "resolved": "https://registry.npmmirror.com/clipboard/-/clipboard-2.0.11.tgz",
+      "integrity": "sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==",
+      "requires": {
+        "good-listener": "^1.2.2",
+        "select": "^1.1.2",
+        "tiny-emitter": "^2.0.0"
+      }
+    },
     "combined-stream": {
       "version": "1.0.8",
       "resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz",
@@ -4605,6 +4657,11 @@
       "version": "1.0.0",
       "resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz",
       "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
+    },
+    "delegate": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmmirror.com/delegate/-/delegate-3.2.0.tgz",
+      "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw=="
     },
     "dunder-proto": {
       "version": "1.0.1",
@@ -4848,6 +4905,14 @@
       "requires": {
         "@sec-ant/readable-stream": "^0.4.1",
         "is-stream": "^4.0.1"
+      }
+    },
+    "good-listener": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmmirror.com/good-listener/-/good-listener-1.2.2.tgz",
+      "integrity": "sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw==",
+      "requires": {
+        "delegate": "^3.1.2"
       }
     },
     "gopd": {
@@ -5323,6 +5388,11 @@
       "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==",
       "optional": true
     },
+    "select": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmmirror.com/select/-/select-1.1.2.tgz",
+      "integrity": "sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA=="
+    },
     "semver": {
       "version": "6.3.1",
       "resolved": "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz",
@@ -5395,6 +5465,11 @@
       "requires": {
         "copy-anything": "^3.0.2"
       }
+    },
+    "tiny-emitter": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmmirror.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
+      "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q=="
     },
     "tinyglobby": {
       "version": "0.2.14",
@@ -5562,6 +5637,14 @@
         "@vue/shared": "3.5.18"
       }
     },
+    "vue-clipboard3": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmmirror.com/vue-clipboard3/-/vue-clipboard3-2.0.0.tgz",
+      "integrity": "sha512-Q9S7dzWGax7LN5iiSPcu/K1GGm2gcBBlYwmMsUc5/16N6w90cbKow3FnPmPs95sungns4yvd9/+JhbAznECS2A==",
+      "requires": {
+        "clipboard": "^2.0.6"
+      }
+    },
     "vue-router": {
       "version": "4.5.1",
       "resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-4.5.1.tgz",
diff --git a/package.json b/package.json
index a25d83a..009ab8e 100644
--- a/package.json
+++ b/package.json
@@ -20,6 +20,7 @@
     "pinia": "^3.0.3",
     "spark-md5": "^3.0.2",
     "vue": "^3.5.18",
+    "vue-clipboard3": "^2.0.0",
     "vue-router": "^4.5.1"
   },
   "devDependencies": {
diff --git a/src/assets/base.css b/src/assets/base.css
index b64e9ba..20413dc 100644
--- a/src/assets/base.css
+++ b/src/assets/base.css
@@ -3,47 +3,129 @@
    License: none (public domain)
 */
 
-html, body, div, span, applet, object, iframe,
-h1, h2, h3, h4, h5, h6, p, blockquote, pre,
-a, abbr, acronym, address, big, cite, code,
-del, dfn, em, img, ins, kbd, q, s, samp,
-small, strike, strong, sub, sup, tt, var,
-b, u, i, center,
-dl, dt, dd, ol, ul, li,
-fieldset, form, label, legend,
-table, caption, tbody, tfoot, thead, tr, th, td,
-article, aside, canvas, details, embed, 
-figure, figcaption, footer, header, hgroup, 
-menu, nav, output, ruby, section, summary,
-time, mark, audio, video {
-	margin: 0;
-	padding: 0;
-	border: 0;
-	font-size: 100%;
-	font: inherit;
-	vertical-align: baseline;
+
+html,
+body,
+div,
+span,
+applet,
+object,
+iframe,
+h1,
+h2,
+h3,
+h4,
+h5,
+h6,
+p,
+blockquote,
+pre,
+a,
+abbr,
+acronym,
+address,
+big,
+cite,
+code,
+del,
+dfn,
+em,
+img,
+ins,
+kbd,
+q,
+s,
+samp,
+small,
+strike,
+strong,
+sub,
+sup,
+tt,
+var,
+b,
+u,
+i,
+center,
+dl,
+dt,
+dd,
+ol,
+ul,
+li,
+fieldset,
+form,
+label,
+legend,
+table,
+caption,
+tbody,
+tfoot,
+thead,
+tr,
+th,
+td,
+article,
+aside,
+canvas,
+details,
+embed,
+figure,
+figcaption,
+footer,
+header,
+hgroup,
+menu,
+nav,
+output,
+ruby,
+section,
+summary,
+time,
+mark,
+audio,
+video {
+  margin: 0;
+  padding: 0;
+  border: 0;
+  font-size: 100%;
+  font: inherit;
+  vertical-align: baseline;
 }
 /* HTML5 display-role reset for older browsers */
-article, aside, details, figcaption, figure, 
-footer, header, hgroup, menu, nav, section {
-	display: block;
+article,
+aside,
+details,
+figcaption,
+figure,
+footer,
+header,
+hgroup,
+menu,
+nav,
+section {
+  display: block;
 }
 body {
-	line-height: 1;
-	font-size: 14px;
+  line-height: 1;
+  font-size: 14px;
 }
-ol, ul {
-	list-style: none;
+ol,
+ul {
+  list-style: none;
 }
-blockquote, q {
-	quotes: none;
+blockquote,
+q {
+  quotes: none;
 }
-blockquote:before, blockquote:after,
-q:before, q:after {
-	content: '';
-	content: none;
+blockquote:before,
+blockquote:after,
+q:before,
+q:after {
+  content: '';
+  content: none;
 }
 table {
-	border-collapse: collapse;
-	border-spacing: 0;
-}
\ No newline at end of file
+  border-collapse: collapse;
+  border-spacing: 0;
+}
diff --git a/src/assets/images/default-book-img.png b/src/assets/images/default-book-img.png
index dba380b..54e4e5b 100644
--- a/src/assets/images/default-book-img.png
+++ b/src/assets/images/default-book-img.png
Binary files differ
diff --git a/src/assets/images/personalCenter/book-cover.png b/src/assets/images/personalCenter/book-cover.png
new file mode 100644
index 0000000..54e4e5b
--- /dev/null
+++ b/src/assets/images/personalCenter/book-cover.png
Binary files differ
diff --git a/src/assets/images/personalCenter/collect-click.png b/src/assets/images/personalCenter/collect-click.png
new file mode 100644
index 0000000..633b0a9
--- /dev/null
+++ b/src/assets/images/personalCenter/collect-click.png
Binary files differ
diff --git a/src/assets/images/personalCenter/notification.svg b/src/assets/images/personalCenter/notification.svg
new file mode 100644
index 0000000..055d95a
--- /dev/null
+++ b/src/assets/images/personalCenter/notification.svg
@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1755764010884" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7634" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"><path d="M580.205386 310.17543C577.496936 310.092291 576.262736 306.37798 573.580048 307.257377 573.585904 308.22928 573.590587 309.203526 573.59527 310.17543L580.205386 310.17543 580.205386 310.17543ZM657.335891 309.950603C620.414092 303.49974 586.829553 311.777314 556.109201 332.861768 528.873652 351.553933 506.245862 375.465104 482.403779 397.969943 453.357912 425.390505 423.285106 451.412932 387.851607 470.399011 355.473164 487.748077 321.502205 499.77392 284.133096 499.172043 279.79583 499.101785 278.890671 500.77744 279.498404 504.416808 279.992552 507.371162 280.274756 510.389918 281.069844 513.265816 286.38721 532.509507 298.574647 546.57752 314.402625 558.145515 320.29962 562.459362 326.251652 564.132676 333.211886 562.520252 341.734194 560.542487 350.440342 559.084632 358.708548 556.32583 399.432481 542.739085 431.48071 517.028136 458.226795 484.096997 486.517388 449.265377 515.366532 414.896289 548.303525 384.312941 582.077762 352.950899 617.321563 323.70948 664.584182 314.737522 665.46475 313.759763 665.474118 312.787859 664.56896 311.819469 662.161452 311.185975 659.783215 310.376836 657.335891 309.950603L657.335891 309.950603ZM761.314359 234.146805C744.82361 234.329476 731.125623 248.228868 731.360986 264.541627 731.597524 280.983192 745.549612 294.701084 761.827239 294.500849 778.284025 294.298271 791.911759 280.405904 791.723233 264.027572 791.527677 247.445492 777.809783 233.965305 761.314359 234.146805L761.314359 234.146805ZM512 0C229.231081 0 0 229.22991 0 512 0 794.768916 229.231081 1024 512 1024 794.768916 1024 1024 794.768916 1024 512 1024 229.231081 794.768916 0 512 0L512 0ZM453.397725 830.388599C445.68924 853.581967 429.74885 867.448573 406.048454 872.682803 398.503905 872.63245 390.959357 872.579755 383.417151 872.529408 360.844396 866.301024 344.659274 853.008193 338.015201 830.015065 331.017495 805.794755 337.720117 785.192742 355.767079 767.915104 359.020029 764.802669 361.357281 764.596579 365.087986 767.587232 391.534302 788.770051 419.481801 807.701094 450.22323 822.176604 454.503118 824.191836 454.688132 826.505667 453.397725 830.388599L453.397725 830.388599ZM822.448265 268.575613C820.650831 269.792248 822.666069 272.811005 821.094625 274.1342 814.626202 305.161344 797.209218 319.368701 758.139863 325.517455 760.587189 333.102988 763.447863 340.590158 765.423288 348.302155 778.817993 400.635067 771.239485 451.135414 751.131621 500.268069 734.028459 542.061096 708.461534 578.369308 676.907456 610.440956 656.386238 631.299413 642.929471 655.974056 634.379061 683.694387 625.959799 710.98497 620.9785 739.12802 613.415216 766.622358 610.289903 777.981918 606.786366 789.334453 599.64346 798.881355 585.05905 818.370956 563.733377 821.321796 541.70161 820.555981 503.900414 819.239813 470.101587 804.811141 438.020571 786.168156 380.617368 752.808441 332.734134 708.20978 289.594494 658.256272 260.649331 624.737307 235.78265 588.550876 218.529604 547.470969 211.226274 530.079749 206.863247 511.922715 203.241443 493.522121 202.918255 493.040853 202.606778 492.820712 202.310523 492.852328 201.952207 490.10992 203.033011 487.2188 201.509581 484.593489L201.509581 483.089965C202.715678 479.580573 202.715678 476.072353 201.509581 472.564133L201.509581 471.06061C202.917085 468.955208 202.023636 466.552381 202.291788 464.30061 202.585702 464.334567 202.892496 464.112084 203.210998 463.624961 203.606785 462.461019 204.188757 461.32635 204.37377 460.127278 207.716884 438.43275 219.102207 423.54506 240.238184 416.148054 259.717241 409.331848 279.967965 406.067188 300.041873 401.918448 326.748144 396.398504 353.488376 391.17013 378.651311 379.939374 400.265043 370.291767 415.909179 353.231931 433.159883 338.025738 474.861575 301.262021 521.378286 273.059251 576.003955 259.926842 600.232459 254.102446 624.749019 251.617651 649.744508 254.206662 667.245799 256.019321 683.975421 260.481881 700.822139 266.97607 702.652368 234.179592 718.561137 213.123242 750.256906 204.86089 752.001652 202.85268 755.679662 205.831623 757.253441 203.388983 761.779234 203.336289 766.303853 203.292963 770.829647 203.442847 795.110844 202.33511 823.773805 230.489872 822.448271 255.574353 822.448265 259.909277 822.448265 264.24186 822.448265 268.575613L822.448265 268.575613Z" fill="#1C9E3A" p-id="7635"></path></svg>
\ No newline at end of file
diff --git a/src/assets/js/config.js b/src/assets/js/config.js
index f100767..6565a7c 100644
--- a/src/assets/js/config.js
+++ b/src/assets/js/config.js
@@ -1,4 +1,4 @@
-export const requestCtx = 'http://182.92.203.7:5001' // 璇锋眰鍦板潃
+export const requestCtx = 'https://yxjy.pumcp.com/' // 璇锋眰鍦板潃
 // export const appId = 1051;
 
 // export const requestCtx = 'http://172.31.31.145' // 璇锋眰鍦板潃
@@ -6,15 +6,16 @@
 export const appId = 1
 
 export const requestTimeOut = 300000 // 璇锋眰瓒呮椂鏃堕棿
-export const tokenKey = 'jilin-token'
-export const userInfoKey = 'jilin-userInfo' // 鐢ㄦ埛淇℃伅key
-export const appRefCode = 'jilinWebsite'
+export const tokenKey = 'xiehe-token'
+export const userInfoKey = 'xiehe-userInfo' // 鐢ㄦ埛淇℃伅key
+export const appRefCode = 'PUMC'
 export const goodsStore = `defaultGoodsStore${appId}` // 榛樿鍟嗗搧搴�(涔﹀煄)
 export const publicStore = `defaultPublicStore${appId}` // 榛樿璧勬簮寮�鏀句粨鍌�
 export const publicRepository = `defaultPublicRepository${appId}` // 榛樿璧勬簮寮�鏀惧簱
 
 export const reg_tel =
   /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/ // 鐢佃瘽鍙锋鍒�
+export const reg_telphone = /^0\d{2}-\d{8}$|^0\d{3}-\d{7}$/ //搴ф満鍙锋鍒�
 
 // refcode
 const refCode = {
@@ -56,17 +57,17 @@
   newVideosStore: 'jilin_videosLibrary\\jilin_newVideosStore',
   newModelsStore: 'jilin_modelsLibrary\\jilin_newModelsStore',
   // 棣栭〉鎺ㄨ崘璧勬簮
-  recommendImgStore:'jilin_imgLibrary\\jilin_recommendedImage',
-  recommendAudioStore:'jilin_audiosLibrary\\jilin_recommendedAudio',
-  recommendVideoStore:'jilin_videosLibrary\\jilin_recommendedVideo',
-  recommendModelStore:'jilin_modelsLibrary\\jilin_recommendedModel',
+  recommendImgStore: 'jilin_imgLibrary\\jilin_recommendedImage',
+  recommendAudioStore: 'jilin_audiosLibrary\\jilin_recommendedAudio',
+  recommendVideoStore: 'jilin_videosLibrary\\jilin_recommendedVideo',
+  recommendModelStore: 'jilin_modelsLibrary\\jilin_recommendedModel',
 }
 
 const wxLogin = {
   appid: 'wx2b9d4a6308fd03d6',
   scope: 'snsapi_login',
   logInRedirectURL: encodeURIComponent(requestCtx + '/website'),
-  authenRedirectURL:encodeURIComponent(requestCtx + '/website/#/userInfo')
+  authenRedirectURL: encodeURIComponent(requestCtx + '/website/#/userInfo'),
 }
 
 const config = {
@@ -79,6 +80,7 @@
   reg_tel,
   appId,
   refCode,
-  wxLogin
+  wxLogin,
+  reg_telphone,
 }
 export default config
diff --git a/src/assets/js/middleGround/api/edu.js b/src/assets/js/middleGround/api/edu.js
index 1ed71f2..944d822 100644
--- a/src/assets/js/middleGround/api/edu.js
+++ b/src/assets/js/middleGround/api/edu.js
@@ -90,6 +90,24 @@
     })
   },
 
+  // 鑾峰彇鐝骇璇︽儏
+  getCourseClass(data) {
+    return request({
+      url: '/edu/api/ApiGetCourseClass',
+      method: 'post',
+      data,
+    })
+  },
+
+  // 鑾峰彇topic淇℃伅
+  getClassTopic(data) {
+    return request({
+      url: '/edu/api/ApiGetClassTopic',
+      method: 'post',
+      data,
+    })
+  },
+  
   //鍒涘缓璇剧▼璁㈠崟
   createCourseOrder(data) {
     return request({
diff --git a/src/assets/js/middleGround/api/identity.js b/src/assets/js/middleGround/api/identity.js
index bdd37e4..848d772 100644
--- a/src/assets/js/middleGround/api/identity.js
+++ b/src/assets/js/middleGround/api/identity.js
@@ -1,181 +1,224 @@
-import request from "@/plugin/axios/index.ts";
+import request from '@/plugin/axios/index.ts'
 const identityApi = {
   // 鑾峰彇鍥惧舰楠岃瘉鐮�
   getImgCode() {
     return request({
-      url: "/identity/NewCaptcha",
-      method: "post",
-    });
+      url: '/identity/NewCaptcha',
+      method: 'post',
+    })
   },
 
   // 楠岃瘉鍥惧舰楠岃瘉鐮�
   verificationImgCode(data) {
     return request({
-      url: "/identity/ValidCaptcha",
-      method: "post",
+      url: '/identity/ValidCaptcha',
+      method: 'post',
       data,
-    });
+    })
   },
 
   // 鑾峰彇鐭俊楠岃瘉鐮�
   getPhoneCode(data) {
     return request({
-      url: "/identity/NewSms",
-      method: "post",
+      url: '/identity/NewSms',
+      method: 'post',
       data,
-    });
+    })
   },
   // 楠岃瘉鐭俊楠岃瘉鐮�
   verificationPhoneCode(data) {
     return request({
-      url: "/identity/api/ApiValidMobilePhone",
-      method: "post",
+      url: '/identity/api/ApiValidMobilePhone',
+      method: 'post',
       data,
-    });
+    })
   },
 
   // 閫氳繃鎵嬫満鍙锋敞鍐岀敤鎴�
   registerAppUserWithPhone(data) {
     return request({
-      url: "/identity/api/RegisterAppUserWithPhone",
-      method: "post",
+      url: '/identity/api/RegisterAppUserWithPhone',
+      method: 'post',
       data,
-    });
+    })
   },
 
   // 璐﹀彿瀵嗙爜鐧诲綍
   loginByPassword(data) {
     return request({
-      url: "/identity/api/LoginByPassword",
-      method: "post",
+      url: '/identity/api/LoginByPassword',
+      method: 'post',
       data,
-    });
+    })
   },
 
   // 鐭俊楠岃瘉鐮佺櫥褰�
   loginByMobilePhone(data) {
     return request({
-      url: "/identity/api/LoginByMobilePhone",
-      method: "post",
+      url: '/identity/api/LoginByMobilePhone',
+      method: 'post',
       data,
-    });
+    })
   },
 
   // 璁剧疆鐢ㄦ埛key
   setUserKey(data) {
     return request({
-      url: "/identity/api/ApiAppUserSetKey",
-      method: "post",
+      url: '/identity/api/ApiAppUserSetKey',
+      method: 'post',
       data,
-    });
+    })
   },
 
   // 鑾峰彇鐢ㄦ埛key
   getUserKey(data) {
     return request({
-      url: "/identity/api/ApiGetAppUserKey",
-      method: "post",
+      url: '/identity/api/ApiGetAppUserKey',
+      method: 'post',
       data,
-    });
+    })
   },
 
   // 鍒犻櫎鐢ㄦ埛key
   delUserKey(data) {
     return request({
-      url: "/identity/api/ApiDelAppUserKey",
-      method: "post",
+      url: '/identity/api/ApiDelAppUserKey',
+      method: 'post',
       data,
-    });
+    })
   },
 
   // 鑾峰彇鍘诲綋鍓嶇敤鎴蜂俊鎭�
   getCurrentAppUser() {
     return request({
-      url: "/identity/api/GetCurrentAppUser",
-      method: "post",
-    });
+      url: '/identity/api/GetCurrentAppUser',
+      method: 'post',
+    })
   },
 
   // 娣诲姞鐢ㄦ埛淇℃伅
   setAppUserInfo(data) {
     return request({
-      url: "/identity/api/SetAppUserInfoRequest",
-      method: "post",
+      url: '/identity/api/SetAppUserInfoRequest',
+      method: 'post',
       data,
-    });
+    })
   },
 
   // 鐢ㄦ埛鏇存崲缁戝畾鎵嬫満鍙凤紝濡傛病鏈夌粦瀹氭墜鏈哄垯鑷姩鍒涘缓
   userSetPhoneNumber(data) {
     return request({
-      url: "/identity/api/ApiUserSetPhoneNumber",
-      method: "post",
+      url: '/identity/api/ApiUserSetPhoneNumber',
+      method: 'post',
       data,
-    });
+    })
   },
 
   // 妫�娴嬬敤鎴锋槸鍚︾粦瀹氬井淇�
   checkBuildingWeChat(data) {
     return request({
-      url: "/identity/api/ApiCheckBuildingWeChat",
-      method: "post",
+      url: '/identity/api/ApiCheckBuildingWeChat',
+      method: 'post',
       data,
-    });
+    })
   },
-
 
   // 閫氳繃鎵嬫満鍙烽噸缃瘑鐮�
   changePasswordByMobilePhone(data) {
     return request({
-      url: "/identity/api/ChangePasswordByMobilePhone",
-      method: "post",
+      url: '/identity/api/ChangePasswordByMobilePhone',
+      method: 'post',
       data,
-    });
+    })
   },
 
   // 寰俊寮�鏀惧钩鍙版壂鐮佺櫥褰�
   loginByWeChatOpenCode(data) {
     return request({
-      url: "/identity/api/LoginByWeChatOpenCode",
-      method: "post",
+      url: '/identity/api/LoginByWeChatOpenCode',
+      method: 'post',
       data,
-    });
+    })
   },
 
   // 鐢ㄦ埛缁戝畾寰俊鍙�
   bindingWeChat(data) {
     return request({
-      url: "/identity/api/ApiBindingWeChat",
-      method: "post",
+      url: '/identity/api/ApiBindingWeChat',
+      method: 'post',
       data,
-    });
+    })
   },
 
   // 璁剧疆鐧诲綍鐨勭敤鎴峰悕鍜屽瘑鐮侊紝鐢ㄦ埛鍚嶅拰瀵嗙爜鑷冲皯6浣�
   setLoginNameAndPassword(data) {
     return request({
-      url: "/identity/api/ApiUserSetLoginNameAndPassword",
-      method: "post",
+      url: '/identity/api/ApiUserSetLoginNameAndPassword',
+      method: 'post',
       data,
-    });
+    })
   },
 
   // 鑾峰彇閭楠岃瘉鐮�
   getEmailCode(data) {
     return request({
-      url: "/identity/api/SendVerifyEMail",
-      method: "post",
+      url: '/identity/api/SendVerifyEMail',
+      method: 'post',
       data,
-    });
+    })
   },
   // 鐢ㄦ埛缁戝畾閭
   bindingEmail(data) {
     return request({
-      url: "/identity/api/ApiBindEMail",
-      method: "post",
+      url: '/identity/api/ApiBindEMail',
+      method: 'post',
       data,
-    });
+    })
   },
-};
+  // 閫氳繃refcode鍔犲叆鐝骇/缁�
+  joinGroupByRefCode(data) {
+    return request({
+      url: '/identity/api/ApiJoinGroupByRefCode',
+      method: 'post',
+      data,
+    })
+  },
 
-export default identityApi;
\ No newline at end of file
+  // 鑾峰彇鍔犲叆缁勭殑鍒楄〃淇℃伅
+  joinedGroupByList(data) {
+    return request({
+      url: '/identity/api/ApiGetJoinedGroupByList',
+      method: 'post',
+      data,
+    })
+  },
+
+  // 鑾峰彇缁勬垨鐝骇鎴愬憳
+  getGroupUserList(data) {
+    return request({
+      url: '/identity/api/ApiGetGroupUserList',
+      method: 'post',
+      data,
+    })
+  },
+
+  // 鏇存柊缁勬垚鍛樻垨鐝骇鎴愬憳鐘舵��
+  updateAppUserGroupLink(data) {
+    return request({
+      url: '/identity/api/ApiUpdateAppUserGroupLink',
+      method: 'post',
+      data,
+    })
+  },
+
+  // 鍒犻櫎缁勬垚鍛樻垨鐝骇鎴愬憳鐘舵��
+  removeAppUserFromGroup(data) {
+    return request({
+      url: '/identity/api/ApiRemoveAppUserFromGroup',
+      method: 'post',
+      data,
+    })
+  },
+}
+
+export default identityApi
diff --git a/src/assets/main.css b/src/assets/main.css
index f39b43e..b873457 100644
--- a/src/assets/main.css
+++ b/src/assets/main.css
@@ -1,5 +1,14 @@
 @import './base.css';
 
+:root {
+  --el-color-primary: #019e58 !important;
+  --el-color-primary-light-3: #019e58 !important;
+  --el-color-primary-light-5: #019e58 !important;
+  --el-color-primary-light-7: #019e58 !important;
+  --el-color-primary-dark-2: #019e58 !important;
+  --el-color-primary-dark-3: #019e58 !important;
+}
+
 /* 灞呬腑甯冨眬 */
 .contentBox {
   width: 1200px;
@@ -99,7 +108,7 @@
 }
 
 .avatar-uploader .el-upload:hover {
-  border-color: #409eff;
+  border-color: #019e58;
 }
 
 .avatarCover {
@@ -169,16 +178,6 @@
 .el-input-group__prepend {
   vertical-align: initial !important;
 }
-.el-checkbox__inner {
-  border: 1px solid #000 !important;
-  width: 20px !important;
-  height: 20px !important;
-}
-
-.el-checkbox__inner::after {
-  left: 7px !important;
-  top: 4px !important;
-}
 
 /* 涓汉涓績椤甸潰鍏叡鏍峰紡 */
 .personalPage-title {
@@ -195,7 +194,7 @@
   border-radius: 4px 4px 0px 0px;
 }
 .personalPage-content {
-  padding: 20px 40px;
+  padding: 20px 20px;
 }
 
 /* 涓よ竟瀵归綈 */
@@ -207,3 +206,18 @@
   cursor: pointer;
   transition: all 0.2s;
 }
+
+.no {
+  color: #ee1818;
+}
+
+.yes {
+  color: #1fbc1f;
+}
+.wait,
+.main {
+  color: #ff6d00;
+}
+.grey {
+  color: #949494;
+}
diff --git a/src/router/index.js b/src/router/index.js
index 9369bbf..cbd45ea 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -45,7 +45,7 @@
               path: '/myBook',
               name: 'myBook',
               meta: {
-                name: '鍥句功',
+                name: '涔︽灦',
               },
               component: () => import('@/views/personalCenter/myBook.vue'),
             },
@@ -105,6 +105,138 @@
               },
               component: () => import('@/views/personalCenter/activeCode.vue'),
             },
+            {
+              path: '/courseDetail',
+              name: 'courseDetail',
+              meta: {
+                name: '璇剧▼璇︽儏',
+              },
+              component: () => import('@/views/courseManage/index.vue'),
+            },
+          ],
+        },
+        // 鐝骇
+        {
+          path: '/classManage',
+          name: 'classManage',
+          redirect: '/classHome',
+          meta: {
+            name: '鐝骇绠$悊',
+          },
+          component: () => import('../views/classManage/index.vue'),
+          children: [
+            {
+              path: '/classHome',
+              name: 'classHome',
+              meta: {
+                name: '鐝骇棣栭〉',
+              },
+              component: () => import('@/views/classManage/classHome.vue'),
+            },
+            {
+              path: '/studentManage',
+              name: 'studentManage',
+              meta: {
+                name: '瀛︾敓绠$悊',
+              },
+              component: () => import('@/views/classManage/studentManage.vue'),
+            },
+            {
+              path: '/teachingPlan',
+              name: 'teachingPlan',
+              meta: {
+                name: '鏁欏璁″垝',
+              },
+              component: () => import('@/views/classManage/teachingPlan.vue'),
+            },
+            {
+              path: '/prepareLessons',
+              name: 'prepareLessons',
+              meta: {
+                name: '澶囪',
+              },
+              component: () => import('@/views/classManage/prepareLessons.vue'),
+            },
+            {
+              path: '/jobManage',
+              name: 'jobManage',
+              meta: {
+                name: '浣滀笟绠$悊-鏁欏笀',
+              },
+              component: () => import('@/views/classManage/jobManage.vue'),
+            },
+            {
+              path: '/studentJob',
+              name: 'studentJob',
+              meta: {
+                name: '浣滀笟绠$悊-瀛︾敓',
+              },
+              component: () => import('@/views/classManage/studentJob.vue'),
+            },
+            {
+              path: '/jobDetail',
+              name: 'jobDetail',
+              meta: {
+                name: '浣滀笟绠$悊璇︽儏',
+              },
+              component: () => import('@/views/classManage/jobDetail.vue'),
+            },
+            {
+              path: '/testManage',
+              name: 'testManage',
+              meta: {
+                name: '娴嬭瘯绠$悊',
+              },
+              component: () => import('@/views/classManage/testManage.vue'),
+            },
+            {
+              path: '/jobAnalysis',
+              name: 'jobAnalysis',
+              meta: {
+                name: '浣滀笟鍒嗘瀽',
+              },
+              component: () => import('@/views/classManage/jobAnalysis.vue'),
+            },
+            {
+              path: '/teachInteraction',
+              name: 'teachInteraction',
+              meta: {
+                name: '鏁欏浜掑姩',
+              },
+              component: () => import('@/views/classManage/teachInteraction.vue'),
+            },
+            {
+              path: '/interactionDetail',
+              name: 'interactionDetail',
+              meta: {
+                name: '鏁欏浜掑姩-璇︽儏',
+              },
+              component: () => import('@/views/classManage/interactionDetail.vue'),
+            },
+            {
+              path: '/talkingPoint',
+              name: 'talkingPoint',
+              meta: {
+                name: '璇濋',
+              },
+              component: () => import('@/views/classManage/talkingPoint.vue'),
+            },
+            {
+              path: '/talkDetail',
+              name: 'talkDetail',
+              meta: {
+                name: '璇濋',
+              },
+              component: () => import('@/views/classManage/talkDetail.vue'),
+            },
+            {
+              path: '/info',
+              name: 'info',
+              meta: {
+                name: '鐝骇閫氱煡鍒楄〃',
+              },
+              component: () => import('@/views/classManage/infoList.vue'),
+            },
           ],
         },
       ],
diff --git a/src/store/counter.js b/src/store/counter.js
deleted file mode 100644
index b6757ba..0000000
--- a/src/store/counter.js
+++ /dev/null
@@ -1,12 +0,0 @@
-import { ref, computed } from 'vue'
-import { defineStore } from 'pinia'
-
-export const useCounterStore = defineStore('counter', () => {
-  const count = ref(0)
-  const doubleCount = computed(() => count.value * 2)
-  function increment() {
-    count.value++
-  }
-
-  return { count, doubleCount, increment }
-})
diff --git a/src/store/index.ts b/src/store/index.ts
new file mode 100644
index 0000000..9650225
--- /dev/null
+++ b/src/store/index.ts
@@ -0,0 +1,9 @@
+import { createPinia } from "pinia";
+
+// 鍒涘缓pinia瀹炰緥
+const pinia = createPinia()
+
+export default pinia
+
+export * from './modules/breadcrumb'
+export * from './modules/user'
\ No newline at end of file
diff --git a/src/store/modules/breadcrumb.ts b/src/store/modules/breadcrumb.ts
new file mode 100644
index 0000000..980b1ea
--- /dev/null
+++ b/src/store/modules/breadcrumb.ts
@@ -0,0 +1,96 @@
+// 闈㈠寘灞戞暟鎹�
+import { defineStore } from 'pinia'
+import tool from '@/assets/js/toolClass.js'
+export const useBreadcrumbStore = defineStore('breadcrumb', () => {
+  const crumbList = localStorage.getItem('crumbs')
+    ? JSON.parse(localStorage.getItem('crumbs'))
+    : {
+        home: {}, // 棣栭〉
+        bookService: {}, // 鍥句功鏈嶅姟
+        digitalCourse: {}, // 鏁板瓧璇剧▼
+        digitalBook: {}, // 鏁板瓧鏁欐潗
+        seminar: {}, // 鏁板瓧鏁欐潗
+        shoppingCart: {}, // 璐墿杞�
+        personalCenter: {}, //涓汉涓績
+        retrievalPage: {}, //鍏ㄥ眬妫�绱�
+        digitalCourses: {}, //鏁板瓧璇剧▼
+        digitalTextbooks: {} //鏁板瓧鏁欐潗
+      }
+  // 闈㈠寘灞�
+  const changeCrumbs = (data: any) => {
+    switch (data.type) {
+      case 'home':
+        data.data.unshift({
+          name: '棣栭〉',
+          // isCrumbs: true,
+          path: '/home'
+        })
+        break
+      case 'bookService':
+        data.data.unshift({
+          name: '鍥句功鏈嶅姟',
+          // isCrumbs: true,
+          path: '/bookService'
+        })
+        break
+      case 'personalCenter':
+        data.data.unshift({
+          name: '涓汉涓績',
+          // isCrumbs: true,
+          path: '/personalCenter'
+        })
+        break
+      case 'retrievalPage':
+        data.data.unshift({
+          name: '鍏ㄥ眬妫�绱�',
+          // isCrumbs: true,
+          path: '/retrievalPage'
+        })
+        break
+      case 'digitalCourses':
+        data.data.unshift({
+          name: '鏁板瓧璇剧▼',
+          // isCrumbs: true,
+          path: '/digitalCourses'
+        })
+        break
+      case 'digitalTextbooks':
+        data.data.unshift({
+          name: '鏁板瓧鏁欐潗',
+          // isCrumbs: true,
+          path: '/digitalTextbooks'
+        })
+        break
+      case 'shoppingCart':
+        data.data.unshift({
+          name: '璐墿杞�',
+          path: '/shoppingCart'
+        })
+    }
+    if (!crumbList[data.type].keys) {
+      crumbList[data.type].keys = []
+    }
+    crumbList[data.type].keys.push(data.cid)
+    crumbList[data.type][data.cid] = data.data
+    if (crumbList[data.type].keys.length > 20) {
+      const key = crumbList[data.type].keys[0]
+      delete crumbList[data.type][key]
+      crumbList[data.type].keys.splice(0, 1)
+    }
+    localStorage.setItem('crumbs', JSON.stringify(crumbList))
+  }
+
+  const setCrumbs = (data: any) => {
+    // 瀛樺偍闈㈠寘灞�
+    if (!data.cid) {
+      data.cid = tool.uuid(8)
+    }
+    changeCrumbs(data)
+    if (data.callback) data.callback(data.cid)
+  }
+
+  return {
+    crumbList,
+    setCrumbs
+  }
+})
diff --git a/src/store/modules/user.ts b/src/store/modules/user.ts
new file mode 100644
index 0000000..bad8a75
--- /dev/null
+++ b/src/store/modules/user.ts
@@ -0,0 +1,149 @@
+// 鐢ㄦ埛淇℃伅
+import { defineStore } from 'pinia'
+import config from '@/assets/js/config'
+import { ref } from 'vue'
+interface userInfo {
+  userName: string
+  userType: string
+  roleId?: any
+  role?: any
+  userId?: number
+  name?: string
+}
+
+export const useUserStore = defineStore('user', () => {
+  const token = localStorage.getItem(config.tokenKey)
+    ? ref<string>(localStorage.getItem(config.tokenKey) as string)
+    : ref<string>()
+  const userInfo = localStorage.getItem(config.userInfoKey)
+    ? ref<userInfo>(JSON.parse(localStorage.getItem(config.userInfoKey) as string))
+    : ref<userInfo>()
+  const setToken = (value: string) => {
+    token.value = value
+    localStorage.setItem(config.tokenKey, value)
+  }
+  const setUserInfo = (value: userInfo) => {
+    userInfo.value = value
+    localStorage.setItem(config.userInfoKey, JSON.stringify(value))
+  }
+  // 閫�鍑虹櫥褰�
+  const delteUserInfo = () => {
+    ;((token.vlaue = ''), (userInfo.value = { userName: '', userType: '' }))
+    localStorage.removeItem(config.tokenKey)
+    localStorage.removeItem(config.userInfoKey)
+    localStorage.removeItem('xiehe-isUserInfo')
+  }
+  // 璐墿杞︽暟閲�
+  let cartNum = ref<number>(1)
+  // 鏇存柊鍙充晶寮瑰嚭妗嗚喘鐗╄溅鐨勬暟閲�
+  const updateRightPop = () => {
+    cartNum.value += 1
+  }
+
+  // 璐墿杞﹀晢鍝乮d
+  const shoppingIds = ref<number[]>([])
+  const updateShoppingIds = (ids: number[]) => {
+    shoppingIds.value = ids
+  }
+
+  // 宸茶喘涔扮殑鍟嗗搧id
+  const buyIds = ref<number[]>([])
+  const updateBuyIds = (ids: number[]) => {
+    buyIds.value = ids
+  }
+
+  return {
+    token,
+    setToken,
+    userInfo,
+    setUserInfo,
+    delteUserInfo,
+    cartNum,
+    updateRightPop,
+    shoppingIds,
+    updateShoppingIds,
+    buyIds,
+    updateBuyIds,
+  }
+})
+
+export const applyBookStore = defineStore('applyBook', () => {
+  //鏍蜂功鐢宠
+  let electronicBookList = localStorage.getItem('electronicBookList')
+    ? ref(JSON.parse(localStorage.getItem('electronicBookList')))
+    : ref([])
+  let paperBookList = localStorage.getItem('paperBookList')
+    ? ref(JSON.parse(localStorage.getItem('paperBookList')))
+    : ref([])
+  //宸茬敵璇峰浘涔�
+  let alreadyPaperBook = localStorage.getItem('alreadyPaperBook')
+    ? ref(JSON.parse(localStorage.getItem('alreadyPaperBook')))
+    : ref([])
+  let alreadyElectronicBook = localStorage.getItem('alreadyElectronicBook')
+    ? ref(JSON.parse(localStorage.getItem('alreadyElectronicBook')))
+    : ref([])
+  // 娣诲姞鐢靛瓙鏍蜂功鍒楄〃
+  const appplyElectronicBook = (value: data) => {
+    electronicBookList.value.push(value)
+    localStorage.setItem('electronicBookList', JSON.stringify(electronicBookList.value))
+  }
+
+  //娣诲姞绾歌川鏍峰紡鍒楄〃
+  const appplyPaperBook = (value: data) => {
+    paperBookList.value.push(value)
+    localStorage.setItem('paperBookList', JSON.stringify(paperBookList.value))
+  }
+
+  //鍒犻櫎鐢靛瓙鏍蜂功鍒楄〃
+  const removeElectronicBook = (value: int) => {
+    electronicBookList.value.splice(value, 1)
+    localStorage.setItem('electronicBookList', JSON.stringify(electronicBookList.value))
+  }
+
+  //鍒犻櫎绾歌川鏍峰紡
+  const removePaperBook = (value: int) => {
+    paperBookList.value.splice(value, 1)
+    localStorage.setItem('paperBookList', JSON.stringify(paperBookList.value))
+  }
+  const emptyBookList = (value: data) => {
+    if (value && value.type == 'eBook') {
+      electronicBookList.value = []
+      localStorage.setItem('electronicBookList', JSON.stringify(electronicBookList.value))
+    } else if (value && value.type == 'paperBook') {
+      paperBookList.value = []
+      localStorage.setItem('paperBookList', JSON.stringify(paperBookList.value))
+    } else {
+      paperBookList.value = []
+      electronicBookList.value = []
+      alreadyPaperBook.value = []
+      alreadyElectronicBook.value = []
+      localStorage.removeItem('electronicBookList')
+      localStorage.removeItem('paperBookList')
+    }
+  }
+
+  //宸茬敵璇峰浘涔�
+  const alreadyPaperBookList = (value: data) => {
+    alreadyPaperBook.value = value.list
+    localStorage.setItem('alreadyPaperBook', JSON.stringify(alreadyPaperBook.value))
+  }
+
+  const alreadyElectronicBookList = (value: data) => {
+    alreadyElectronicBook.value = value.list
+    localStorage.setItem('alreadyElectronicBook', JSON.stringify(alreadyElectronicBook.value))
+  }
+
+  return {
+    electronicBookList,
+    paperBookList,
+    alreadyPaperBook,
+    alreadyElectronicBook,
+    appplyElectronicBook,
+    appplyPaperBook,
+    removeElectronicBook,
+    removePaperBook,
+    emptyBookList,
+    alreadyPaperBookList,
+    alreadyElectronicBookList,
+  }
+})
diff --git a/src/views/classManage/classHome.vue b/src/views/classManage/classHome.vue
new file mode 100644
index 0000000..bb843b8
--- /dev/null
+++ b/src/views/classManage/classHome.vue
@@ -0,0 +1,778 @@
+<template>
+  <div class="classManagePage-box">
+    <div class="classManagePage-nav" v-if="classInfo">
+      <el-breadcrumb :separator-icon="ArrowRight">
+        <el-breadcrumb-item>鎴戠殑鐝骇</el-breadcrumb-item>
+        <el-breadcrumb-item>{{ classInfo?.name }}</el-breadcrumb-item>
+        <el-breadcrumb-item>鐝骇棣栭〉</el-breadcrumb-item>
+      </el-breadcrumb>
+    </div>
+    <div class="classManagePage-content">
+      <div class="content-left fl">
+        <div class="classOverview mainBorder">
+          <div class="">
+            <div class="title mainbg">鐝骇姒傝</div>
+          </div>
+          <div class="bodyBox" v-if="currentClass?.name && !classLoading">
+            <div class="classInfo">
+              <div class="name">{{ currentClass?.name }}</div>
+              <!-- <div class="time">鎶ュ悕鏃堕棿:2024.7.30--2024-8.03</div> -->
+              <div class="time">寮�璇炬椂闂�: {{ currentClass?.classTime }}</div>
+            </div>
+            <div class="line"></div>
+            <div class="classInfoBox">
+              <div class="iconBox">
+                <img :src="currentClass?.bookIcon ? currentClass?.bookIcon : defaultImg" />
+              </div>
+              <div class="infoBox">
+                <div class="main">{{ currentClass?.bookName }}</div>
+                <div class="job">浣滆�咃細{{ classInfo?.author ?? '-' }}</div>
+                <div class="job">ISBN锛歿{ classInfo?.isbn ?? '-' }}</div>
+              </div>
+            </div>
+            <div class="line"></div>
+            <div class="classInfo">
+              <div class="name">鐝骇浜烘暟</div>
+              <div class="con">
+                <span class="main">{{ currentClass?.memberCount }}</span
+                >/{{ currentClass?.maxUserCount }}
+              </div>
+            </div>
+            <div class="line"></div>
+            <div class="classInfo">
+              <div class="name">浣滀笟娆℃暟</div>
+              <div class="con">
+                <span class="main">{{ homeworkCount }}</span>
+              </div>
+            </div>
+            <!-- <div class="line"></div>
+            <div class="classInfo">
+              <div class="name">鏁欏杩涘害</div>
+              <div class="con"><span class="main">0</span>/0</div>
+            </div> -->
+          </div>
+          <div
+            class="bodyBox"
+            style="display: flex; justify-content: center; align-items: center"
+            v-if="classLoading"
+          >
+            <div v-loading="classLoading"></div>
+          </div>
+          <div v-if="!currentClass && !classLoading">
+            <el-empty style="padding: 0" :image-size="100" />
+          </div>
+        </div>
+        <div class="classNotice">
+          <div class="titleBox">
+            <div class="border mainbg"></div>
+            <div class="title">
+              <span>鐝骇閫氱煡</span>
+              <el-icon
+                style="cursor: pointer"
+                color="#FF6D00"
+                v-if="noticeList.length > 0 && userInfo.role == 'Teacher'"
+                @click="toInfo"
+              >
+                <ArrowRightBold />
+              </el-icon>
+            </div>
+          </div>
+          <div class="noticeList" v-if="noticeList.length > 0 && !noticeLoading">
+            <div class="noticeItem" v-for="(item, index) in noticeList" :key="index">
+              <div class="noticeContent">
+                <span class="title">{{ item.name }}锛�</span>
+                <div class="contentText">{{ item.content }}</div>
+              </div>
+              <span class="time">{{ item.createDate }}</span>
+            </div>
+          </div>
+          <div v-if="noticeLoading" v-loading="noticeLoading"></div>
+          <div v-if="noticeList.length == 0 && !noticeLoading" class="notBox">
+            <el-empty :image-size="100" />
+          </div>
+        </div>
+        <div class="classTalk">
+          <div class="titleBox">
+            <div class="border mainbg"></div>
+            <div class="title">
+              <span>鐝粍璇濋</span>
+              <el-icon
+                style="cursor: pointer"
+                color="#FF6D00"
+                v-if="messageList.length > 0"
+                @click="toTalk"
+              >
+                <ArrowRightBold />
+              </el-icon>
+            </div>
+          </div>
+          <div class="noticeList" v-if="messageList.length > 0 && !messageLoading">
+            <div class="noticeItem" v-for="(item, index) in messageList" :key="index">
+              <div class="noticeContent">
+                <span class="title">{{ item.name }}</span>
+                <div class="content" v-if="item.publicText">
+                  <span>{{ item.publicText.publishRole }}锛�</span>
+                  <span>{{ item.publicText.publisher }}</span>
+                </div>
+                <span>鏈�杩戝洖澶嶏細{{ item.updateDate }}</span>
+              </div>
+              <span class="time">{{ item.createDate }}</span>
+            </div>
+          </div>
+          <div v-if="messageLoading" v-loading="messageLoading"></div>
+          <div v-if="messageList.length == 0 && !messageLoading" class="notBox">
+            <el-empty :image-size="100" />
+          </div>
+        </div>
+        <div class="classTask">
+          <div class="titleBox" style="margin-bottom: 5px">
+            <div class="border mainbg"></div>
+            <div class="title">
+              <span>鐝骇浣滀笟姒傝</span>
+              <!-- <el-icon
+                style="cursor: pointer"
+                color="#FF6D00"
+                v-if="tableData.length > 0"
+                @click="toWorkList"
+              >
+                <ArrowRightBold />
+              </el-icon> -->
+            </div>
+          </div>
+          <div class="tableWall">
+            <el-table :data="tableData" border style="width: 100%; font-size: 14px" size="small">
+              <el-table-column prop="name" label="鍚嶇О" />
+              <el-table-column prop="beginDate" label="寮�濮嬫椂闂�" />
+              <el-table-column prop="endDate" label="鎴鏃堕棿" />
+              <el-table-column prop="submitCount" label="瀹屾垚鎯呭喌(鎻愪氦浜烘暟)" width="180" />
+            </el-table>
+          </div>
+        </div>
+        <!-- <div class="classTask">
+          <div class="titleBox" style="margin-bottom: 5px">
+            <div class="border mainbg"></div>
+            <div class="title">
+              <span>鏁欏浜掑姩</span>
+              <el-icon
+                style="cursor: pointer"
+                color="#FF6D00"
+                v-if="tableData.length > 0"
+                @click="toTeaching"
+              >
+                <ArrowRightBold />
+              </el-icon>
+            </div>
+          </div>
+          <div class="tableWall">
+            <el-table :data="[]" border style="width: 100%; font-size: 14px" size="small">
+              <el-table-column prop="index" label="搴忓彿" />
+              <el-table-column prop="name" label="鏍囬" />
+              <el-table-column prop="beginDate" label="浜掑姩瀛︾敓鏁�(宸蹭簰鍔�/鍏ㄩ儴瀛︾敓)" />
+              <el-table-column prop="endDate" label="鏈�鍚庢彁浜ゆ椂闂�" />
+            </el-table>
+          </div>
+        </div> -->
+      </div>
+      <div class="content-right fr">
+        <div class="assistant">
+          <div class="titleBox">
+            <div class="border mainbg"></div>
+            <div class="title">鍔╂暀鍒楄〃</div>
+            <div class="options">
+              <!-- <div class="optionsItem">绉婚櫎</div> -->
+              <div class="copyIdBtn" @click="copy(currentClass)">澶嶅埗閭�璇风爜</div>
+            </div>
+          </div>
+          <div class="avatarList" style="max-height: 147px; overflow-y: auto">
+            <div class="avatarItem" v-for="(item, index) in teacherList" :key="index">
+              <el-avatar v-if="item.appUser?.icon" :size="35" :src="item.appUser?.icon" />
+              <el-avatar v-else :size="35" :icon="UserFilled" />
+              <el-tooltip :content="item.appUser?.name" placement="top" effect="light">
+                <span class="userName">{{ item.appUser?.name }}</span>
+              </el-tooltip>
+            </div>
+            <div class="nullBox" v-if="!Sloading && teacherList.length == 0">
+              <el-empty :image-size="100" />
+            </div>
+          </div>
+        </div>
+        <div class="student">
+          <div class="titleBox">
+            <div class="border mainbg"></div>
+            <div class="title">瀛︾敓鍒楄〃</div>
+            <div class="options">
+              <div class="copyIdBtn" @click="copy(currentClass)">澶嶅埗閭�璇风爜</div>
+            </div>
+          </div>
+          <div class="avatarList" style="max-height: 570px; overflow-y: auto">
+            <div class="avatarItem02" v-for="(item, index) in studentList" :key="index">
+              <el-avatar v-if="item.appUser?.icon" :size="35" :src="item.appUser?.icon" />
+              <el-avatar v-else :size="35" :icon="UserFilled" />
+              <el-tooltip :content="item.appUser?.name" placement="top" effect="light">
+                <span class="userName">{{ item.appUser?.name }}</span>
+              </el-tooltip>
+            </div>
+            <div class="nullBox" v-if="!Sloading && studentList.length == 0">
+              <el-empty :image-size="100" />
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { useRoute, useRouter } from 'vue-router'
+import { getPublicImage } from '@/assets/js/middleGround/tool.js'
+import useClipboard from 'vue-clipboard3'
+import { inject, onMounted, ref } from 'vue'
+import moment from 'moment'
+import { ElMessage } from 'element-plus'
+import { ArrowRight, UserFilled } from '@element-plus/icons-vue'
+import defaultImg from '@/assets/images/default-book-img.png'
+
+const { toClipboard } = useClipboard()
+const route: any = useRoute()
+const router: any = useRouter()
+const classInfo = JSON.parse(route.query.classInfo)
+const MG: any = inject('MG')
+const config: any = inject('config')
+const userInfo: any = ref()
+
+const currentClass = ref()
+const classLoading = ref(true)
+const messageTopicInfo = ref()
+const talkTopicInfo = ref()
+const noticeList: any = ref([])
+const noticeLoading = ref(true)
+const messageList: any = ref([])
+const messageLoading = ref(true)
+const tableData: any = ref([])
+const homeworkCount = ref(0)
+const studentList: any = ref([])
+const teacherList: any = ref([])
+const Sloading = ref(false)
+
+onMounted(() => {
+  const userCache: any = localStorage.getItem('jesk-userInfo')
+  if (userCache) {
+    userInfo.value = JSON.parse(userCache)
+  }
+  getData()
+  getStudentList()
+  getTaskList()
+})
+
+// 澶嶅埗
+const copy = async (val: any) => {
+  try {
+    await toClipboard(val.refCode)
+    ElMessage({
+      message: '澶嶅埗鎴愬姛',
+      type: 'success'
+    })
+  } catch (e) {
+    console.error(e)
+  }
+}
+
+// 鑾峰彇鐝骇
+const getData = () => {
+  MG.edu
+    .getCourseClass({
+      ClassIdOrRefCode: String(classInfo.id)
+    })
+    .then((res: any) => {
+      if (res) {
+        res.bookName = res.linkProductDto.product.name
+        res.bookIcon = getPublicImage(res.linkProductDto.product.icon, 100)
+        res.classTime =
+          moment(res.beginDate).format('YYYY.MM.DD') +
+          '--' +
+          moment(res.endDate).format('YYYY.MM.DD')
+      }
+      currentClass.value = res
+      classLoading.value = false
+      getTopicInfo()
+    })
+}
+
+// 鑾峰彇topic
+const getTopicInfo = () => {
+  const pramas = {
+    classId: classInfo.id,
+    refCodes: [config.refCodes.message, config.refCodes.talk]
+  }
+  MG.edu.getClassTopic(pramas).then((res: any) => {
+    const list = res
+    messageTopicInfo.value = list.find((item: any) => item.refCode == config.refCodes.message)
+    if (messageTopicInfo.value.id) {
+      sessionStorage.messageId = messageTopicInfo.value.id
+      noticeLoading.value = true
+      getNotice()
+    }
+    talkTopicInfo.value = list.find((item: any) => item.refCode == config.refCodes.talk)
+    if (talkTopicInfo.value.id) {
+      sessionStorage.talkId = talkTopicInfo.value.id
+      messageLoading.value = true
+      getMessage()
+    }
+  })
+}
+
+// 鑾峰彇鐝骇閫氱煡
+const getNotice = () => {
+  const data = {
+    start: 0,
+    size: 3,
+    appRefCode: config.appRefCode,
+    topicIdOrRefCode: String(messageTopicInfo.value.id),
+    sort: {
+      type: 'Desc',
+      field: 'CreateDate',
+      subSorts: []
+    }
+  }
+  MG.ugc.getTopicMessageList(data).then((res: any) => {
+    noticeLoading.value = false
+    const list = res.datas
+    noticeList.value = list.map((item: any) => {
+      return {
+        ...item,
+        createDate: moment(item.createDate).format('YYYY-MM-DD')
+      }
+    })
+  })
+}
+
+// 鑾峰彇鐝骇璇濋
+const getMessage = () => {
+  const data = {
+    start: 0,
+    size: 3,
+    appRefCode: config.appRefCode,
+    topicIdOrRefCode: String(talkTopicInfo.value.id),
+    sort: {
+      type: 'Desc',
+      field: 'CreateDate',
+      subSorts: []
+    }
+  }
+  MG.ugc.getTopicMessageList(data).then((res: any) => {
+    messageLoading.value = false
+    const list = res.datas
+    messageList.value = list.map((item: any, i: number) => {
+      const str = item.content.indexOf('publisher')
+      if (str > -1) {
+        item.publicText = JSON.parse(item.content)
+        if (item.publicText && item.publicText.publishRole) {
+          item.publicText.publishRole = item.publicText.publishRole == 'Teacher' ? '鍔╂暀' : '瀛︾敓'
+        }
+      }
+      return {
+        ...item,
+        index: i + 1,
+        createDate: moment(item.createDate).format('YYYY-MM-DD HH:mm:ss'),
+        updateDate: moment(item.updateDate).format('YYYY-MM-DD HH:mm:ss')
+      }
+    })
+  })
+}
+
+// 鑾峰彇鏁欏笀/瀛︾敓鍒楄〃
+const getStudentList = () => {
+  Sloading.value = true
+  const data = {
+    start: 0,
+    size: 999,
+    groupId: classInfo.id,
+    filterList: [
+      {
+        value: 'Normal',
+        field: 'State',
+        subFilters: []
+      }
+    ]
+  }
+  MG.identity.getGroupUserList(data).then((res: any) => {
+    const { datas } = res
+    Sloading.value = false
+    let list: any = []
+    if (datas.length > 0) {
+      list = datas.map((item: any, index: number) => {
+        if (item.linkType == 'Creator') {
+          const userInfo = item.appUser?.infoList?.find((citem: any) => 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: any) => citem.type == 'WeChat')
+          const defaultData = item.appUser?.infoList?.find((citem: any) => 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')
+        }
+      })
+    }
+    teacherList.value = list.filter((item: any) => item.linkType != 'RefCode')
+    studentList.value = list.filter((item: any) => item.linkType == 'RefCode')
+  })
+}
+
+// 鍓嶅線璇濋
+const toTalk = () => {
+  classInfo.index = 5
+  if (userInfo.value?.role != 'Teacher') {
+    classInfo.index = 3
+  }
+  router.push({
+    path: '/talkingPoint',
+    query: {
+      classInfo: JSON.stringify(classInfo)
+    }
+  })
+}
+
+// 鍓嶅線閫氱煡
+const toInfo = () => {
+  classInfo.index = 0
+  router.push({
+    path: '/info',
+    query: {
+      classInfo: JSON.stringify(classInfo)
+    }
+  })
+}
+
+// 鏁欏浜掑姩
+const toTeaching = () => {}
+
+// 鐝骇浣滀笟姒傝
+const getTaskList = () => {
+  const data = {
+    start: 0,
+    size: 3,
+    sort: {
+      type: 'Desc',
+      field: 'CreateDate',
+      subSorts: []
+    },
+    filterList: [
+      // {
+      //   value: 'Normal',
+      //   field: 'State',
+      //   subFilters: []
+      // },
+      {
+        value: config.taskType.homeWork,
+        field: 'Type',
+        subFilters: []
+      }
+    ],
+    groupId: classInfo?.id
+  }
+  MG.edu
+    .getTaskList(data)
+    .then((res: any) => {
+      let list: any = []
+      if (res.datas.length > 0) {
+        list = res.datas
+          ?.map((item: any) => {
+            return {
+              ...item,
+              beginDate: moment(item.beginDate).format('YYYY-MM-DD'),
+              endDate: moment(item.endDate).format('YYYY-MM-DD')
+            }
+          })
+          .slice(0, 3)
+      }
+      tableData.value = list
+      homeworkCount.value = res.totalSize
+    })
+    .catch((e: any) => {
+      console.log(e)
+    })
+}
+</script>
+
+<style lang="less" scoped>
+.nullBox {
+  width: 100%;
+  display: flex;
+  justify-content: center;
+}
+.classManagePage-box {
+  padding: 20px;
+  .classManagePage-nav {
+    padding-bottom: 20px;
+    border-bottom: 1px solid #e6e8ed;
+  }
+  .classManagePage-content {
+    display: flex;
+    justify-content: space-between;
+    .content-left {
+      width: 70%;
+      min-width: 950px;
+      .classOverview {
+        height: 190px;
+        margin-top: 30px;
+        border-radius: 10px;
+        .title {
+          width: 80px;
+          text-align: center;
+          padding: 7px;
+          border-radius: 8px 0 8px 0;
+        }
+        .bodyBox {
+          display: flex;
+          justify-content: space-between;
+          margin-top: 20px;
+          padding: 0 20px;
+          .classInfoBox {
+            padding: 0 20px;
+            display: flex;
+            .iconBox {
+              width: 90px;
+              height: 120px;
+              img {
+                width: 100%;
+                height: 100%;
+                object-fit: contain;
+              }
+            }
+            .infoBox {
+              flex: 1;
+              padding-left: 10px;
+              .main {
+                font-size: 16px;
+                line-height: 20px;
+              }
+              .job {
+                // padding:10px;
+                margin-top: 20px;
+              }
+            }
+          }
+          .line {
+            width: 1px;
+            height: 130px;
+            background: linear-gradient(
+              180deg,
+              rgba(255, 255, 255, 0) 0%,
+              #b7b7b7 51%,
+              rgba(255, 255, 255, 0) 100%
+            );
+          }
+          .classInfo {
+            padding: 0 20px;
+            font-size: 16px;
+            min-width: 120px;
+            .name {
+              font-weight: bold;
+              margin-bottom: 20px;
+              text-align: center;
+            }
+            .con {
+              margin-top: 40px;
+              font-size: 22px;
+              text-align: center;
+            }
+            .time {
+              line-height: 30px;
+            }
+          }
+        }
+      }
+      .classNotice {
+        height: 200px;
+        margin-top: 20px;
+        border-radius: 20px;
+        background: linear-gradient(180deg, #fffcf1 0%, #ffffff 100%);
+        border: 1px solid rgba(249, 200, 35, 0.2);
+      }
+      .classTalk {
+        height: 200px;
+        margin-top: 20px;
+        border-radius: 20px;
+        background: linear-gradient(180deg, #edf0ff 0%, #ffffff 100%);
+        border: 1px solid rgba(154, 171, 251, 0.2);
+      }
+      .classTask {
+        min-height: 200px;
+        margin-top: 20px;
+        border-radius: 20px;
+        border: 1px solid #e8ebf5;
+        .tableWall {
+          width: 100%;
+          padding: 10px 5px;
+          box-sizing: border-box;
+        }
+      }
+      .titleBox {
+        display: flex;
+        align-items: center;
+        margin: 20px 0;
+        font-size: 16px;
+        .title {
+          width: 100%;
+          display: flex;
+          justify-content: space-between;
+          align-items: center;
+          padding-right: 10px;
+        }
+        .border {
+          width: 4px;
+          height: 23px;
+          border-radius: 0px 10px 10px 0px;
+          margin-right: 10px;
+        }
+      }
+    }
+    .content-right {
+      width: 28%;
+      margin-left: 20px;
+      min-width: 270px;
+
+      .assistant {
+        min-height: 160px;
+        margin-top: 30px;
+        border-radius: 10px;
+        border: 1px solid #e8ebf5;
+        overflow: hidden;
+      }
+      .student {
+        height: 640px;
+        margin-top: 20px;
+        border-radius: 10px;
+        border: 1px solid #e8ebf5;
+        overflow: hidden;
+      }
+      .titleBox {
+        display: flex;
+        align-items: center;
+        margin: 10px 0;
+        .border {
+          width: 4px;
+          height: 23px;
+          border-radius: 0px 10px 10px 0px;
+          margin-right: 10px;
+        }
+      }
+    }
+    .notBox {
+      width: 100%;
+      height: 100px;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+    }
+  }
+  .options {
+    flex: 1;
+    display: flex;
+    align-items: center;
+    justify-content: flex-end;
+    padding-right: 10px;
+    .optionsItem {
+      color: #999;
+      margin-right: 10px;
+      cursor: pointer;
+    }
+    .copyIdBtn {
+      background-color: #fff;
+      color: #3b93fe;
+      padding: 0 6px;
+      border-radius: 50px;
+      overflow: hidden;
+      cursor: pointer;
+    }
+  }
+  .avatarList {
+    display: flex;
+    flex-wrap: wrap;
+    width: 100%;
+    padding: 0 20px;
+    box-sizing: border-box;
+    .avatarItem,
+    .avatarItem02 {
+      width: 68px;
+      max-height: 88px;
+      display: flex;
+      flex-direction: column;
+      align-items: center;
+      padding: 6px 4px;
+      position: relative;
+      margin-left: 1px;
+
+      .userName {
+        width: 100%;
+        margin: 3px 0;
+        white-space: nowrap;
+        text-overflow: ellipsis;
+        overflow: hidden;
+        text-align: center;
+        min-height: 30px;
+        line-height: 30px;
+        font-size: 12px;
+      }
+    }
+    // .avatarItem:hover {
+    //   background-image: url('@/assets/images/class/avabg.png');
+    //   background-size: 100% 100%;
+    //   background-position: center;
+    //   background-repeat: no-repeat;
+    //   cursor: pointer;
+    // }
+    .avatarItem:hover,
+    .avatarItem02:hover {
+      background: #eee;
+    }
+  }
+  .noticeList {
+    width: 100%;
+    height: calc(100% - 63px);
+    padding: 5px 25px;
+    overflow: auto;
+    .noticeItem {
+      display: flex;
+      justify-content: space-between;
+      font-family: PingFang SC;
+      font-weight: 400;
+      font-size: 14px;
+      line-height: 32px;
+      .noticeContent {
+        display: flex;
+        justify-content: space-between;
+        color: #000000;
+        max-width: 800px;
+        white-space: nowrap;
+        text-overflow: ellipsis;
+        overflow: hidden;
+        .title {
+          margin-right: 30px;
+        }
+        .content {
+          margin-right: 30px;
+        }
+      }
+      .time {
+        color: #b7b7b7;
+      }
+    }
+  }
+}
+</style>
diff --git a/src/views/classManage/components/headerPage.vue b/src/views/classManage/components/headerPage.vue
new file mode 100644
index 0000000..c8a4d19
--- /dev/null
+++ b/src/views/classManage/components/headerPage.vue
@@ -0,0 +1,288 @@
+<template>
+  <div class="pageHeader">
+    <div class="headerBox">
+      <div class="logoBox">
+        <el-image :src="logo" class="logo" @click="goHome" style="cursor: pointer" />
+        <div class="titleName"><img :src="titleName" /></div>
+      </div>
+      <div class="inputBox f1">
+        <div class="signIn">
+          <p v-if="!userStore.userInfo?.name" class="signInBox">
+            <span @click="loginBtn">娉ㄥ唽</span>
+            <span>|</span>
+            <span @click="signupBtn">鐧诲綍</span>
+          </p>
+          <!-- 鐢ㄦ埛鍚� -->
+          <el-dropdown trigger="click" v-else>
+            <p class="el-dropdown-link signInBox">
+              <span>{{ userStore.userInfo?.name }}</span>
+              <el-icon class="el-icon--right">
+                <CaretBottom />
+              </el-icon>
+            </p>
+            <template #dropdown>
+              <el-dropdown-menu>
+                <el-dropdown-item @click="router.push('/personalCenter')"
+                  >涓汉涓績</el-dropdown-item
+                >
+                <el-dropdown-item @click="logOut">閫�鍑虹櫥褰�</el-dropdown-item>
+              </el-dropdown-menu>
+            </template>
+          </el-dropdown>
+        </div>
+      </div>
+    </div>
+  </div>
+  <login ref="loginRef"></login>
+  <!-- 瀵艰埅鏍� -->
+
+  <!-- 娓╅Θ鎻愮ず寮圭獥 -->
+  <el-dialog v-model="tipsDialogState" width="420" align-center class="tipsDialog">
+    <template #title>娓╅Θ鎻愮ず</template>
+    <el-icon color="#e6a23c" size="24">
+      <WarningFilled />
+    </el-icon>
+    <p>
+      濡傛灉鎮ㄥ凡浣跨敤銆愪含甯堟櫤鏁欐壂涓�鎵�戞垨銆愪簯涓婁功鎴裤�� 寰俊娉ㄥ唽杩囷紝璇蜂娇鐢ㄥ井淇℃壂鐮佺櫥褰曪紱濡傛灉鎮ㄥ凡鍦ㄣ��
+      浜笀鏅烘暀銆慞C绔敞鍐岃繃锛岃浣跨敤鎵嬫満鍙风櫥褰曪紒缁х画娉ㄥ唽灏嗗垱寤哄叏鏂拌处鎴凤紒
+    </p>
+    <template #footer>
+      <el-button @click="goPhoneSignup">鎵嬫満鍙风櫥褰�</el-button>
+      <el-button @click="goWechatSignUp">寰俊鐧诲綍</el-button>
+      <el-button type="primary" @click="goLogin">缁х画娉ㄥ唽</el-button>
+    </template>
+  </el-dialog>
+</template>
+
+<script setup lang="ts">
+import login from '@/layout/components/login.vue'
+import { onMounted, ref, watchEffect, inject, watch } from 'vue'
+import { ElMessage, ElMessageBox, type FormInstance } from 'element-plus'
+import logo from '@/assets/images/header/logo.png'
+import titleName from '@/assets/images/header/titleName.png'
+import { useRouter } from 'vue-router'
+import { useUserStore, applyBookStore } from '@/store'
+const loginRef = ref()
+const router = useRouter()
+const userStore = useUserStore()
+const applyBook = applyBookStore()
+const MG = inject('MG')
+const config = inject('config')
+const tipsDialogState = ref<boolean>(false) // 娓╅Θ鎻愮ず寮圭獥鐘舵��
+const wechatTipsState = ref<boolean>(false)
+const localData = ref(localStorage.getItem('jsek-token'))
+onMounted(() => {
+  // 鍒ゆ柇鏄惁寰俊鎵爜鐧诲綍
+  var url = window.location.href
+  if (url.indexOf('WeChatScanningCodeLogin') > -1) {
+    var querys = url.substring(url.indexOf('?') + 1).split('&')
+    var result = {}
+    for (var i = 0; i < querys.length; i++) {
+      var temp = querys[i].split('=')
+      if (temp.length < 2) {
+        result[temp[0]] = ''
+      } else {
+        result[temp[0]] = temp[1]
+      }
+    }
+    if (result && result.code) {
+      MG.identity
+        .loginByWeChatOpenCode({
+          code: result.code,
+          appRefCode: config.appRefCode,
+          platform: 'PCWeb'
+        })
+        .then((res) => {
+          if (res && res.status == 'Ok') {
+            userStore.setToken(res.token)
+            loginRef.value.getUserInfo()
+            MG.app.creatUserBehavior({
+              refCode:"sign"
+            }).then(res => {
+              if(res){
+              console.log("浠婃棩宸茬Н鍒�")
+              }
+            });
+          }
+        })
+    }
+  }
+})
+watchEffect(() => {
+  localData.value = localStorage.getItem('jsek-token') || '0'
+})
+
+// 娉ㄥ唽鎸夐挳
+const loginBtn = () => {
+  tipsDialogState.value = true
+}
+// 鐧诲綍鎸夐挳
+const signupBtn = () => {
+  loginRef.value.logIn()
+}
+
+// 缁х画娉ㄥ唽
+const goLogin = () => {
+  tipsDialogState.value = false
+  loginRef.value.signUp()
+}
+// 鍘诲井淇$櫥褰�
+const goWechatSignUp = () => {
+  tipsDialogState.value = false
+  // loginRef.value.logIn()
+  loginRef.value.setWechatTipsState()
+}
+// 鍘绘墜鏈哄彿鐧诲綍
+const goPhoneSignup = () => {
+  tipsDialogState.value = false
+  loginRef.value.logIn()
+  loginRef.value.changeSignUp('authSignUp')
+}
+// 閫�鍑虹櫥褰�
+const logOut = () => {
+  router.push('/home')
+  userStore.delteUserInfo()
+  applyBook.emptyBookList()
+  sessionStorage.removeItem('cartNumber')
+  localStorage.removeItem('alreadyElectronicBook')
+  localStorage.removeItem('alreadyPaperBook')
+  ElMessage.success('閫�鍑烘垚鍔�')
+}
+
+// logo棣栭〉瀹氬悜
+const goHome = () => {
+  router.push('/home')
+}
+
+</script>
+
+<style lang="less">
+.tipsDialog {
+  .el-dialog__header {
+    font-size: 18px;
+  }
+
+  .el-dialog__body {
+    display: flex;
+    align-items: center;
+
+    p {
+      margin-left: 10px;
+      line-height: 24px;
+    }
+  }
+}
+</style>
+<style lang="less" scoped>
+.pageHeader {
+  width: 100%;
+  background: #fff;
+  // border-bottom:1px solid #C0C0C0;
+}
+
+.headerBox {
+  width: 1200px;
+  margin: 0 auto;
+  height: 60px;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  .logoBox {
+    display: flex;
+    align-items: center;
+    .titleName {
+      font-size: 24px;
+      padding: 0 10px;
+      margin-left: 15px;
+      border-left: 1px solid #C0C0C0;
+      color:#181818;
+      font-family: Microsoft YaHei, Microsoft YaHei;
+      font-weight: 400;
+    }
+    /deep/.el-image__inner {
+      height: 48px;
+      border: 0;
+      padding: 0;
+    }
+  }
+}
+
+/** 楠岃瘉鐮佸浘鐗� */
+.imgCode {
+  height: 40px;
+  margin-top: 5px;
+}
+
+/** 鐪嬩笉娓呮崲涓�寮� */
+.linkHight {
+  height: 20px;
+
+  /deep/ .el-link__inner {
+    height: 100%;
+  }
+}
+
+/** header鐧诲綍娉ㄥ唽鏂囧瓧 */
+.signIn {
+  height: 40px;
+  width: 95px;
+  min-width: 90px;
+  text-align: right;
+  margin-left: 80px;
+  font-weight: 400;
+  justify-content: space-around;
+  color: #000;
+  font-size: 14px;
+
+  span:first-child,
+  span:last-child {
+    cursor: pointer;
+  }
+
+  .signInBox {
+    height: 100%;
+    width: 100%;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+  }
+
+  span {
+    padding: 5px;
+  }
+
+  .el-dropdown {
+    width: 100%;
+    height: 100%;
+
+    span {
+      height: 40px;
+      line-height: 40px;
+      padding: 0;
+      display: block;
+      overflow: hidden;
+      text-overflow: ellipsis;
+      white-space: nowrap;
+    }
+  }
+}
+
+.selectPhone {
+  background: #fff;
+}
+
+.el-select {
+  width: 100px;
+  height: 40px;
+  color: red;
+
+  /deep/ .select-trigger {
+    height: 100%;
+
+    .el-input--suffix {
+      height: 100%;
+      background-color: #fff;
+    }
+  }
+}
+</style>
diff --git a/src/views/classManage/components/questionDom.vue b/src/views/classManage/components/questionDom.vue
new file mode 100644
index 0000000..a5dde61
--- /dev/null
+++ b/src/views/classManage/components/questionDom.vue
@@ -0,0 +1,420 @@
+<template>
+  <div class="questionDom">
+    <div class="list-item" v-for="(pitem, pindex) in questionList" :key="pindex">
+      <div class="list-item-title">
+        {{ pitem.name }}
+        <span v-if="isPreview">(鍏� {{ pitem.data.length }} 棰�)</span>
+      </div>
+      <div class="list-item-box" v-for="(item, index) in pitem.data" :key="index">
+        <div class="list-item-box-title-box">
+          <el-checkbox
+            v-if="noCheckbox"
+            v-model="item.isCheck"
+            @change="checkItems($event, item)"
+            size="large"
+          >
+            <template #default>
+              <i class="el-icon-check"></i>
+              <span
+                class="custom-checkbox"
+                v-html="index + 1 + '銆�' + item.questionStem?.stemTxt"
+              ></span>
+            </template>
+          </el-checkbox>
+          <div class="list-item-box-title" v-else>
+            <span>{{ index + 1 }}</span
+            >銆�
+            <span class="questionT" v-html="item.questionStem?.stemTxt"></span>
+            <span v-if="item.score > 0 && isPreview">锛坽{ item.score }} 鍒嗭級</span>
+            <el-icon v-if="isDelete" @click="deleteItem(item)" class="deletIcon">
+              <Delete />
+            </el-icon>
+          </div>
+        </div>
+        <div>
+          <div class="shortAnswer" v-if="item.questionType == 'shortAnswer' && !isJudge">
+            <div class="anSwer" v-if="!isPreview">
+              <div class="anSwerText" v-if="item.questionAnswer" style="margin: 15px 0">
+                <span style="min-width: 40px">绛旀锛�</span
+                ><span v-html="item.questionAnswer"></span>
+              </div>
+              <div :class="isPreview ? 'questionAnalysisCon' : ''" v-if="item.questionAnalysisCon">
+                鍒嗘瀽锛�<span v-html="item.questionAnalysisCon"></span>
+              </div>
+            </div>
+            <div v-else>
+              <!-- <el-input type="textarea" disabled :placeholder="item.userAnswer"></el-input> -->
+              <div v-html="item.userAnswer"></div>
+            </div>
+          </div>
+          <div class="discuss" v-else-if="item.questionType == 'discuss' && !isJudge">
+            <div class="anSwer" v-if="!isPreview">
+              <div class="anSwerText" v-if="item.questionAnswer" style="margin: 15px 0">
+                <span style="min-width: 40px">绛旀锛�</span
+                ><span v-html="item.questionAnswer"></span>
+              </div>
+              <div :class="isPreview ? 'questionAnalysisCon' : ''" v-if="item.questionAnalysisCon">
+                鍒嗘瀽锛�<span v-html="item.questionAnalysisCon"></span>
+              </div>
+            </div>
+            <div v-else>
+              <!-- <el-input type="textarea" disabled :placeholder="item.userAnswer"></el-input> -->
+              <div v-html="item.userAnswer"></div>
+            </div>
+          </div>
+          <div v-if="isJudge">
+            <div class="shortAnswer anSwerText" v-if="item.answer" style="margin: 15px 0">
+              <span v-html="item.answer"></span>
+            </div>
+            <div class="scoreData">
+              <span>寰楀垎锛�</span>
+              <el-input-number v-model="item.score" style="width: 100px" />
+            </div>
+          </div>
+        </div>
+        <div class="completion" v-if="item.questionType == 'completion'">
+          <div class="anSwer" v-if="!isPreview">
+            <div class="anSwerText" v-if="item.questionAnswer" style="margin: 15px 0">
+              <span style="min-width: 40px">绛旀锛�</span><span v-html="item.questionAnswer"></span>
+            </div>
+            <div :class="isPreview ? 'questionAnalysisCon' : ''" v-if="item.questionAnalysisCon">
+              鍒嗘瀽锛�<span v-html="item.questionAnalysisCon"></span>
+            </div>
+          </div>
+          <div v-else>
+            <el-input
+              style="width: 200px"
+              v-model="item.userAnswer"
+              disabled
+              placeholder="璇峰~鍐欑瓟妗�"
+            ></el-input>
+          </div>
+        </div>
+        <div class="classification" v-if="item.questionType == 'classification'">
+          <div class="class-item-box">
+            <span
+              class="class-item-box-span"
+              v-for="citem in item.questionOption"
+              :key="citem.index"
+            >
+              {{ citem.txt }}
+            </span>
+          </div>
+          <div class="anSwer" v-if="!isPreview">
+            <div class="anSwerText" v-if="item.questionAnswer" style="margin: 15px 0">
+              <span>绛旀锛�</span>
+              <div class="class-anSwer-box">
+                <div
+                  class="class-anSwer-box-item"
+                  v-for="aitem in item.questionAnswer"
+                  :key="aitem.key"
+                >
+                  <span>{{ aitem.name }}锛�</span>
+                  <div
+                    class="class-anSwer-box-item-box"
+                    v-for="citem in aitem.option"
+                    :key="citem.key"
+                  >
+                    <span>{{ citem.txt }}</span>
+                  </div>
+                </div>
+              </div>
+            </div>
+            <div :class="isPreview ? 'questionAnalysisCon' : ''" v-if="item.questionAnalysisCon">
+              鍒嗘瀽锛�<span v-html="item.questionAnalysisCon"></span>
+            </div>
+          </div>
+        </div>
+        <div class="judge" v-if="item.questionType == 'judge'">
+          <el-radio-group v-model="item.customAnswer">
+            <el-radio
+              v-for="ritem in item.questionOption"
+              :key="ritem.index"
+              :value="ritem.value"
+              :label="ritem.value"
+              size="large"
+              :disabled="!isPreview"
+            >
+              {{ ritem.value + '. ' + ritem.txt }}
+            </el-radio>
+          </el-radio-group>
+          <div class="anSwer" v-if="!isPreview">
+            <div v-if="item.questionAnswer" style="margin: 15px 0">
+              绛旀锛�<span v-html="item.questionAnswer"></span>
+            </div>
+            <div :class="isPreview ? 'questionAnalysisCon' : ''" v-if="item.questionAnalysisCon">
+              鍒嗘瀽锛�<span v-html="item.questionAnalysisCon"></span>
+            </div>
+          </div>
+        </div>
+        <div class="singleChoice" v-if="item.questionType == 'singleChoice'">
+          <el-radio-group v-if="!isInteraction" v-model="item.customAnswer">
+            <el-radio
+              v-for="ritem in item.questionOption"
+              :key="ritem.index"
+              :value="ritem.value"
+              :label="ritem.value"
+              size="large"
+              :disabled="!isPreview"
+            >
+              {{ ritem.value + '. ' + ritem.txt }}
+            </el-radio>
+          </el-radio-group>
+          <el-radio-group v-else v-model="item.userAnswer">
+            <el-radio
+              v-for="ritem in item.questionOption"
+              :key="ritem.index"
+              :value="ritem.value"
+              :label="ritem.value"
+              size="large"
+              :disabled="isInteraction"
+            >
+              {{ ritem.value + '. ' + ritem.txt }}
+            </el-radio>
+          </el-radio-group>
+          <div class="anSwer" v-if="!isPreview">
+            <div v-if="item.questionAnswer" style="margin: 15px 0">
+              绛旀锛�<span v-html="item.questionAnswer"></span>
+            </div>
+            <div :class="isPreview ? 'questionAnalysisCon' : ''" v-if="item.questionAnalysisCon">
+              鍒嗘瀽锛�<span v-html="item.questionAnalysisCon"></span>
+            </div>
+          </div>
+        </div>
+        <div class="multipleChoice" v-if="item.questionType == 'multipleChoice'">
+          <el-checkbox-group v-if="!isInteraction" v-model="item.customAnswer">
+            <el-checkbox
+              v-for="mitem in item.questionOption"
+              :key="mitem.index"
+              :value="mitem.value"
+              :label="mitem.value"
+              size="large"
+              :disabled="!isPreview"
+            >
+              {{ mitem.value + '. ' + mitem.txt }}
+            </el-checkbox>
+          </el-checkbox-group>
+          <el-checkbox-group v-else v-model="item.userAnswer">
+            <el-checkbox
+              v-for="mitem in item.questionOption"
+              :key="mitem.index"
+              :value="mitem.value"
+              :label="mitem.value"
+              size="large"
+              :disabled="isInteraction"
+            >
+              {{ mitem.value + '. ' + mitem.txt }}
+            </el-checkbox>
+          </el-checkbox-group>
+          <div class="anSwer" v-if="!isPreview">
+            <div v-if="item.questionAnswer" style="margin: 15px 0">
+              绛旀锛�<span v-html="item.questionAnswer"></span>
+            </div>
+            <div :class="isPreview ? 'questionAnalysisCon' : ''" v-if="item.questionAnalysisCon">
+              鍒嗘瀽锛�<span v-html="item.questionAnalysisCon"></span>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+    <div class="jugdeBtn" v-if="isJudge">
+      <el-button type="primary" @click="submitScore">鎻愪氦鍒嗘暟</el-button>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { defineProps, onMounted } from 'vue'
+
+const props = defineProps<{
+  questionList?: any
+  noCheckbox?: boolean
+  isDelete?: boolean
+  isPreview?: boolean
+  isJudge?: boolean
+  isInteraction?: boolean
+}>()
+
+const emit = defineEmits(['selectQuestion', 'deleteItem', 'judgeUpdate'])
+
+onMounted(() => {})
+
+const checkItems = (e: Event, item: any) => {
+  emit('selectQuestion', item)
+}
+
+const deleteItem = (item: any) => {
+  emit('deleteItem', item)
+}
+
+const submitScore = () => {
+  const list = [...props.questionList]
+  let data: any = []
+  list.forEach((item) => {
+    data.push(...item.data)
+  })
+  emit('judgeUpdate', JSON.stringify(data))
+}
+</script>
+<style lang="less" scoped>
+.questionDom {
+  width: 100%;
+  height: 100%;
+  overflow: auto;
+  padding: 10px;
+  box-sizing: border-box;
+  font-family: PingFang SC;
+  .questionT {
+    // display: flex;
+    flex-wrap: wrap;
+    align-items: baseline;
+  }
+  .jugdeBtn {
+    position: absolute;
+    bottom: -40px;
+    width: 100%;
+    display: flex;
+    justify-content: center;
+  }
+
+  .list-item {
+    width: 100%;
+    margin-bottom: 20px;
+    .list-item-title {
+      padding: 4px 0;
+      padding-left: 10px;
+      border-left: 4px solid #ff6c00;
+      color: #000;
+      margin: 15px 0;
+    }
+  }
+
+  .list-item-box {
+    margin-bottom: 20px;
+  }
+
+  ::v-deep(.list-item-box-title-box) {
+    margin-bottom: 10px;
+    .el-checkbox {
+      display: flex;
+      align-items: flex-start;
+    }
+    .el-checkbox__label {
+      line-height: 22px;
+      color: #000;
+    }
+    .el-checkbox__input {
+      margin-top: 3px;
+    }
+    .el-checkbox__input.is-checked + .el-checkbox__label {
+      color: #ff6c00;
+    }
+  }
+
+  .list-item-box-title {
+    font-weight: 400;
+    font-size: 13px;
+    color: #000000;
+    display: flex;
+    width: 100%;
+    align-items: baseline;
+    justify-content: flex-start;
+    line-height: 25px;
+    .deletIcon {
+      color: red;
+      margin-left: 10px;
+      font-size: 15px;
+      cursor: pointer;
+    }
+  }
+
+  .anSwer {
+    font-family: PingFang SC;
+    font-weight: 400;
+    font-size: 13px;
+    color: #000000;
+    line-height: 22px;
+    padding-left: 20px;
+    box-sizing: border-box;
+    .anSwerText {
+      display: flex;
+      justify-content: flex-start;
+
+      .class-anSwer-box {
+        margin-left: 10px;
+        .class-anSwer-box-item {
+          display: flex;
+          justify-content: flex-start;
+          align-items: center;
+          .class-anSwer-box-item-box span {
+            margin-left: 10px;
+            margin-right: 20px;
+          }
+        }
+      }
+    }
+    .questionAnalysisCon {
+      min-height: 40px;
+      padding: 10px;
+      background-color: #ff6a00a8;
+    }
+  }
+  .shortAnswer {
+    padding: 20px;
+    line-height: 22px;
+    border: 1px solid #eee;
+    border-radius: 5px;
+    margin: 10px 0;
+  }
+  ::v-deep(.judge),
+  ::v-deep(.singleChoice) {
+    width: 100%;
+    margin-bottom: 20px;
+    .el-radio-group {
+      display: flex;
+      flex-direction: column;
+      justify-content: center;
+      align-items: flex-start;
+      padding-left: 20px;
+      box-sizing: border-box;
+    }
+  }
+  ::v-deep(.multipleChoice) {
+    width: 100%;
+    margin-bottom: 20px;
+    .el-checkbox-group {
+      display: flex;
+      flex-direction: column;
+      justify-content: center;
+      align-items: flex-start;
+      padding-left: 20px;
+      box-sizing: border-box;
+    }
+  }
+  .class-item-box {
+    width: 100%;
+    display: flex;
+    align-items: center;
+    justify-content: flex-start;
+    flex-wrap: wrap;
+    .class-item-box-span {
+      margin-left: 50px;
+    }
+  }
+  .scoreData {
+    display: flex;
+    justify-content: flex-start;
+    align-items: center;
+    span {
+      white-space: nowrap;
+    }
+  }
+  ::v-deep(.custom-checkbox) {
+    display: inline-flex;
+    justify-content: flex-start;
+    p {
+      white-space: pre-line !important;
+    }
+  }
+}
+</style>
diff --git a/src/views/classManage/config.ts b/src/views/classManage/config.ts
new file mode 100644
index 0000000..b7af87f
--- /dev/null
+++ b/src/views/classManage/config.ts
@@ -0,0 +1,106 @@
+export const menu: any = [
+  {
+    label: '鐝骇棣栭〉',
+    key: '1',
+    path: 'classHome',
+    icon: `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16.002" viewBox="0 0 16 16.002">
+      <path class="a"
+        d="M62.384,58.423a1.166,1.166,0,0,1,1.469,0l6.818,5.5a1.22,1.22,0,0,1,.193,1.692,1.178,1.178,0,0,1-.644.423l-.063.014v6.164a1.937,1.937,0,0,1-1.748,1.941l-.081.006-.084,0H57.994A1.932,1.932,0,0,1,56.083,72.3V66.052l-.042-.008a1.2,1.2,0,0,1-.919-1.108l0-.068a1.216,1.216,0,0,1,.449-.945Zm.8.853a.1.1,0,0,0-.124,0l-6.811,5.509a.1.1,0,0,0-.038.08.1.1,0,0,0,.1.1h.321a.547.547,0,0,1,.541.552v6.75a.838.838,0,0,0,.828.8h10.28a.839.839,0,0,0,.786-.846V65.521a.547.547,0,0,1,.541-.553h.321a.1.1,0,0,0,.078-.038.106.106,0,0,0-.016-.144ZM65.535,68.9a.545.545,0,0,1-.064.769,3.18,3.18,0,0,1-4.343,0,.546.546,0,0,1,.705-.833,2.092,2.092,0,0,0,2.931,0,.545.545,0,0,1,.769.063Z"
+        transform="translate(-55.12 -58.163)" />
+    </svg>`
+
+  },
+  {
+    label: '鐝骇绠$悊',
+    key: '2',
+    path: 'studentManage',
+    icon: `<svg xmlns="http://www.w3.org/2000/svg" width="16.2" height="17.885" viewBox="0 0 16.2 17.885">
+  <g transform="translate(-106.5 -63.9)">
+    <path class="a"
+      d="M414.049,453.35a2.947,2.947,0,1,0-3.4,0,5.05,5.05,0,0,0-3.329,4.291.424.424,0,0,0,.42.464.413.413,0,0,0,.416-.369,4.21,4.21,0,0,1,8.388,0,.413.413,0,0,0,.416.369.423.423,0,0,0,.42-.464A5.05,5.05,0,0,0,414.049,453.35Zm-1.7-.3a2.106,2.106,0,1,1,2.106-2.106A2.109,2.109,0,0,1,412.348,453.052Z"
+      transform="translate(-294.781 -376.422)" />
+    <path class="a"
+      d="M121.759,64H107.443a.842.842,0,0,0-.843.843v16a.842.842,0,0,0,.843.843h2.947a.42.42,0,0,0,0-.841h-2.526a.421.421,0,0,1-.42-.42V65.263a.421.421,0,0,1,.42-.42h13.473a.421.421,0,0,1,.42.42v5.052a.42.42,0,0,0,.841,0V64.843a.839.839,0,0,0-.839-.843Z" />
+    <path class="a"
+      d="M256.42,235.541h9.262a.42.42,0,1,0,0-.841H256.42a.42.42,0,1,0,0,.841Zm0,2.526h3.369a.42.42,0,1,0,0-.841H256.42a.42.42,0,1,0,0,.841Z"
+      transform="translate(-146.451 -167.331)" />
+  </g>
+</svg>`
+  },
+  {
+    label: '鏁欏璁″垝',
+    key: '3',
+    path: 'teachingPlan',
+    icon: `<svg xmlns="http://www.w3.org/2000/svg" width="16.2" height="16.2" viewBox="0 0 16.2 16.2">
+  <path class="a"
+    d="M79.6,67.2a.4.4,0,0,0,.4-.4v-2a.8.8,0,0,0-.8-.8H64.8a.8.8,0,0,0-.8.8V79.2a.8.8,0,0,0,.8.8H79.2a.8.8,0,0,0,.8-.8V70a.4.4,0,1,0-.8,0v8.8a.4.4,0,0,1-.4.4H65.2a.4.4,0,0,1-.4-.4V65.2a.4.4,0,0,1,.4-.4H78.8a.4.4,0,0,1,.4.4v1.6A.4.4,0,0,0,79.6,67.2ZM76,72.8H68a.4.4,0,1,0,0,.8h8a.4.4,0,1,0,0-.8Zm0-3.2H73.959a2,2,0,0,0-3.918,0H68a.4.4,0,1,0,0,.8h2.8V70a1.2,1.2,0,1,1,2.4,0v.4H76a.4.4,0,1,0,0-.8Zm0,6H68a.4.4,0,1,0,0,.8h8a.4.4,0,0,0,0-.8Z"
+    transform="translate(-63.9 -63.9)" />
+</svg>`
+  },
+  // {
+  //   label: '澶囪',
+  //   key: '4',
+  //   path: 'prepareLessons',
+  //   icon: beike
+  // },
+  {
+    label: '浣滀笟绠$悊',
+    key: '5',
+    path: 'jobManage',
+    icon: `<svg xmlns="http://www.w3.org/2000/svg" width="16.326" height="16.2" viewBox="0 0 16.326 16.2">
+    <g transform="translate(-63.9 -63.9)">
+      <path class="a"
+        d="M485.31,298.51a2,2,0,0,0-2.829,0l-4.525,4.527a2,2,0,0,0-.254,2.518l-.311.311a.4.4,0,0,0,.566.566l.311-.311a2,2,0,0,0,2.518-.254l4.525-4.525A2.007,2.007,0,0,0,485.31,298.51Zm-5.091,6.789a1.2,1.2,0,0,1-1.7-1.7l2.263-2.263,1.7,1.7Zm4.525-4.525-1.7,1.7-1.7-1.7,1.7-1.7a1.2,1.2,0,1,1,1.7,1.7Z"
+        transform="translate(-405.895 -229.748)" />
+      <path class="a"
+        d="M76,78.8a.4.4,0,0,1-.4.4H65.2a.4.4,0,0,1-.4-.4V65.2a.4.4,0,0,1,.4-.4H75.6a.4.4,0,0,1,.4.4V68l.8-.8V64.8A.8.8,0,0,0,76,64H64.8a.8.8,0,0,0-.8.8V79.2a.8.8,0,0,0,.8.8H76a.8.8,0,0,0,.8-.8V76l-.8.8Z" />
+      <path class="a"
+        d="M204.8,266a.4.4,0,0,0-.4-.4h-5.6a.4.4,0,1,0,0,.8h5.6A.4.4,0,0,0,204.8,266Zm-6,2a.4.4,0,1,0,0,.8H202a.4.4,0,0,0,0-.8Z"
+        transform="translate(-132 -198)" />
+    </g>
+  </svg>`
+  },
+  // {
+  //   label: '娴嬭瘯绠$悊',
+  //   key: '6',
+  //   path: 'testManage',
+  //   icon: ceshi
+  // },
+  {
+    label: '浣滀笟鍒嗘瀽',
+    key: '7',
+    path: 'jobAnalysis',
+    icon: `<svg xmlns="http://www.w3.org/2000/svg" width="16.2" height="16.2" viewBox="0 0 16.2 16.2">
+    <path class="a"
+      d="M69.2,67.2a.4.4,0,0,0,.4-.4V64.4a.4.4,0,1,0-.8,0v2.4A.4.4,0,0,0,69.2,67.2Zm2.8,0a.4.4,0,0,0,.4-.4V64.4a.4.4,0,1,0-.8,0v2.4A.4.4,0,0,0,72,67.2Zm2.8,0a.4.4,0,0,0,.4-.4V64.4a.4.4,0,0,0-.8,0v2.4A.4.4,0,0,0,74.8,67.2Zm4.4-2H76.8a.4.4,0,1,0,0,.8h2a.4.4,0,0,1,.4.4v2.4H64.8V66.4a.4.4,0,0,1,.4-.4h2a.4.4,0,0,0,0-.8H64.8a.8.8,0,0,0-.8.8V79.2a.8.8,0,0,0,.8.8H79.2a.8.8,0,0,0,.8-.8V66A.8.8,0,0,0,79.2,65.2Zm0,13.6a.4.4,0,0,1-.4.4H65.2a.4.4,0,0,1-.4-.4V69.6H79.2Zm-11.466-2a.4.4,0,0,0,.282-.118l2.941-2.941,2.12,1.766a.4.4,0,0,0,.543-.029l2.934-3.034a.4.4,0,1,0-.575-.557L73.3,74.655l-2.114-1.762a.4.4,0,0,0-.539.025l-3.2,3.2a.4.4,0,0,0,0,.566A.4.4,0,0,0,67.734,76.8Z"
+      transform="translate(-63.9 -63.9)" />
+  </svg>`
+  },
+  {
+    label: '鏁欏浜掑姩',
+    key: '9',
+    path: 'teachInteraction',
+    icon: `<svg xmlns="http://www.w3.org/2000/svg" width="16.2" height="16.2" viewBox="0 0 1024 1024">
+  <path
+    d="M447.766594 480.256747H252.078775C126.599562 480.256747 24.274252 377.931437 24.274252 252.452225S125.852662 24.647702 252.078775 24.647702 479.883297 126.973012 479.883297 252.452225V448.140044c0 17.925602-14.191101 32.116703-32.116703 32.116703zM252.078775 88.134209c-90.374909 0-164.318016 73.943107-164.318016 164.318016s73.943107 164.318016 164.318016 164.318016h164.318016v-164.318016c0-90.374909-73.943107-164.318016-164.318016-164.318016zM251.331875 999.352298C125.852662 999.352298 23.527352 897.026988 23.527352 771.547775s102.32531-227.804522 227.804523-227.804522H447.766594c17.178702 0 32.116703 14.191101 32.116703 32.116703v196.434719c-0.7469 124.732312-103.07221 227.057622-228.551422 227.057623z m0-392.122539c-90.374909 0-164.318016 73.943107-164.318017 164.318016s73.943107 164.318016 164.318017 164.318016 164.318016-73.943107 164.318016-164.318016v-164.318016h-164.318016zM773.415026 999.352298c-125.479212 0-227.804522-102.32531-227.804523-227.804523V575.113056c0-17.178702 14.191101-32.116703 32.116703-32.116703h196.43472c125.479212 0 227.804522 102.32531 227.804522 227.804522 0 36.598104-8.962801 72.449307-25.394603 104.56601-8.215901 15.684902-26.888403 21.660102-42.573304 13.444202-15.684902-8.215901-21.660102-26.888403-13.444201-42.573304 11.950401-23.153902 18.672502-49.295405 18.672502-75.436908 0-90.374909-73.943107-164.318016-164.318016-164.318016h-164.318016v164.318016c0 90.374909 73.943107 164.318016 164.318016 164.318016 17.178702 0 34.357403-2.9876 50.042305-8.2159 16.431802-5.228301 34.357403 3.7345 39.585703 20.166301 5.228301 16.431802-3.7345 34.357403-20.166302 39.585704-23.900802 8.962801-47.054705 12.697301-70.955506 12.697302zM773.415026 480.256747H577.727206c-17.178702 0-32.116703-14.191101-32.116703-32.116703V252.452225c0-125.479212 102.32531-227.804522 227.804523-227.804523s227.804522 102.32531 227.804522 227.804523-102.32531 227.804522-227.804522 227.804522z m-164.318017-63.486506h164.318017c90.374909 0 164.318016-73.943107 164.318016-164.318016s-73.943107-164.318016-164.318016-164.318016-164.318016 73.943107-164.318017 164.318016v164.318016z" />
+</svg>`
+  },
+  {
+    label: '璇濋',
+    key: '8',
+    path: 'talkingPoint',
+    icon: `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="15.97" viewBox="0 0 16 15.97">
+    <g transform="translate(-58.026 -58.026)">
+      <path class="a"
+        d="M66.026,74a8.075,8.075,0,0,1-3.049-.6,7.7,7.7,0,0,1-1.3-.694,15.665,15.665,0,0,0-2.294.513.505.505,0,0,1-.453-.121.483.483,0,0,1-.121-.453,11.77,11.77,0,0,0,.513-2.294,6.444,6.444,0,0,1-.694-1.268,8,8,0,1,1,15.4-3.049,7.988,7.988,0,0,1-8,7.97Zm-4.317-2.2a.767.767,0,0,1,.362.091,6.09,6.09,0,0,0,1.238.664A7.093,7.093,0,1,0,66.026,58.9,7.125,7.125,0,0,0,58.932,66a7.109,7.109,0,0,0,1.208,3.955c.121.181.242.332-.242,2.2a8.636,8.636,0,0,1,1.811-.362Z" />
+      <path class="a" d="M332.766,395.146h-6.34a.453.453,0,0,1,0-.906h6.34a.453.453,0,0,1,0,.906Z"
+        transform="translate(-263.207 -330.267)" />
+      <path class="a"
+        d="M375.27,315.381h-.091a.426.426,0,0,1-.362-.513l1.087-6.249a.444.444,0,0,1,.875.151l-1.057,6.219A.433.433,0,0,1,375.27,315.381Zm2.657,0h-.091a.426.426,0,0,1-.362-.513l1.087-6.249a.444.444,0,0,1,.875.151l-1.087,6.249A.423.423,0,0,1,377.927,315.381Z"
+        transform="translate(-311.176 -245.793)" />
+      <path class="a" d="M290.1,569.226h-6.34a.453.453,0,1,1,0-.906h6.34a.453.453,0,0,1,0,.906Z"
+        transform="translate(-221.296 -501.268)" />
+    </g>
+  </svg>`
+  }
+]
diff --git a/src/views/classManage/index.vue b/src/views/classManage/index.vue
new file mode 100644
index 0000000..993f5a2
--- /dev/null
+++ b/src/views/classManage/index.vue
@@ -0,0 +1,283 @@
+<template>
+  <div class="layoutBox">
+    <Header class="header"></Header>
+    <div class="layoutContentBox clear">
+      <div class="classContentBox clear">
+        <div class="leftList fl">
+          <!-- <div class="main title" @click="goBack()"> -->
+          <div class="main title">
+            <!-- <el-icon><ArrowLeft /></el-icon> -->
+            <span>鎴戠殑鐝骇</span>
+          </div>
+          <div class="classInfo-box">
+            <div class="iconBox"><img :src="classIcon" /></div>
+            <div class="infoBox">
+              <div class="main">{{ classInfo?.name }}</div>
+              <div class="job" v-if="userData && userData.role == 'Teacher'">
+                <span class="mainbg">鍔╂暀</span>
+              </div>
+              <div class="job" v-else><span class="mainbg">瀛︾敓</span></div>
+            </div>
+          </div>
+          <div class="line"></div>
+          <ul class="menu">
+            <li
+              v-for="(item, index) in listMenu"
+              :key="index"
+              @click="goRouter(item, index)"
+              :class="activeIndex == index ? 'activeItem mainbg hover' : 'menuItem hover'"
+            >
+              <span
+                :style="{
+                  fill: activeIndex == index ? '#fff' : '#000'
+                }"
+                v-html="item.icon"
+              >
+              </span>
+              <span>{{ item.label }}</span>
+            </li>
+          </ul>
+        </div>
+        <div class="rightContent">
+          <div>
+            <!-- 璁╀富浣撳仛瀛愯矾鐢辩殑鏄剧ず -->
+            <router-view />
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { ref, watch, provide, onMounted, inject } from 'vue'
+import { useRoute, useRouter, onBeforeRouteUpdate } from 'vue-router'
+import Header from './components/headerPage.vue'
+import { menu } from './config'
+import { getPublicImage } from '@/assets/js/middleGround/tool.js'
+import defaultImg from '@/assets/images/default-book-img.png'
+
+const router: any = useRouter()
+const route: any = useRoute()
+const MG: any = inject('MG')
+const config: any = inject('config')
+const routerVal = router.currentRoute.value
+const path = ref(routerVal.path)
+const label = ref('')
+const classInfo: any = ref()
+const classIcon: any = ref()
+const listMenu = ref([])
+const activeIndex = ref(0)
+const userData = ref()
+
+watch(router.currentRoute, (val) => {
+  path.value = val.path
+  if (val.query.classInfo) {
+    const data: any = val.query.classInfo
+    const routerInfo: any = JSON.parse(data)
+    activeIndex.value = routerInfo.index
+  }
+})
+
+watch(classInfo, (val) => {
+  if (val) {
+    activeIndex.value = val.index
+  }
+  if (!val.index) {
+    activeIndex.value = 0
+  }
+})
+
+onBeforeRouteUpdate(async (to, from) => {
+  path.value = to.path
+})
+
+onMounted(() => {
+  classInfo.value = JSON.parse(route.query.classInfo)
+  classIcon.value = classInfo.value.icon ? getPublicImage(classInfo.value.icon, 200) : defaultImg
+  menu.forEach((item) => {
+    if ('/' + item.path === path.value) {
+      label.value = item.label
+    }
+  })
+  const userCache: any = localStorage.getItem('jesk-userInfo')
+  const userInfo = JSON.parse(userCache)
+  userData.value = userInfo
+  if (!userInfo) {
+    router.push({
+      path: '/'
+    })
+    return false
+  }
+  if (userInfo.role != 'Teacher') {
+    const data: any = menu.filter(
+      (item: any) => item.path != 'studentManage' && item.path != 'jobAnalysis'
+    )
+    listMenu.value = data
+  } else {
+    const data: any = menu
+    // if (!classInfo.bookRefCode) {
+    //   // 铻嶅獟浣撳浘涔︼紝鏃犳暟瀛楅槄璇伙紝鏃犳硶璺宠浆
+    //   const list: any = menu.filter((item: any) => item.path != 'teachingPlan')
+    //   listMenu.value = list;
+    //   return false
+    // }
+    listMenu.value = data
+  }
+})
+
+const goRouter = (item: any, index: number) => {
+  activeIndex.value = index
+  if (!localStorage.getItem('jsek-token') || localStorage.getItem('jsek-token') == null) {
+    router.push({
+      path: '/home',
+      query: {
+        showLogin: '1'
+      }
+    })
+  } else {
+    label.value = item.label
+    classInfo.value.index = index
+    if (item.key == 5) {
+      router.push({
+        path: userData.value.role != 'Teacher' ? '/studentJob' : '/jobManage',
+        query: {
+          classInfo: JSON.stringify(classInfo.value)
+        }
+      })
+    } else {
+      router.push({
+        path: item.path,
+        query: {
+          classInfo: JSON.stringify(classInfo.value)
+        }
+      })
+    }
+  }
+}
+
+const goBack = () => {
+  router.go(-1)
+}
+</script>
+
+<style lang="less" scoped>
+.layoutBox {
+  width: 100%;
+  height: 100vh;
+  display: flex;
+  flex-direction: column;
+  background-color: #fff;
+  .layoutContentBox {
+    flex: 1;
+    height: auto;
+  }
+  .classContentBox {
+    padding: 10px 40px;
+    display: flex;
+    height: 100%;
+    .leftList {
+      padding: 20px;
+      width: 280px;
+      min-width: 230px;
+      box-shadow: 0px 0px 20px 1px #ccc;
+      border-radius: 3px;
+      background-color: #fff;
+      .title {
+        font-size: 16px;
+        display: flex;
+        align-items: center;
+        cursor: pointer;
+        span {
+          margin-left: 10px;
+        }
+      }
+      .classInfo-box {
+        padding: 20px 10px;
+        margin-bottom: 10px;
+        display: flex;
+        .iconBox {
+          width: 90px;
+          height: 120px;
+          img {
+            width: 100%;
+            height: 100%;
+            object-fit: contain;
+          }
+        }
+        .infoBox {
+          flex: 1;
+          padding-left: 10px;
+          .main {
+            font-size: 16px;
+            line-height: 20px;
+          }
+          .job {
+            // padding:10px;
+            margin-top: 20px;
+            span {
+              padding: 5px 15px;
+              border-radius: 20px;
+            }
+          }
+        }
+      }
+      .line {
+        width: 100%;
+        height: 1px;
+        background: linear-gradient(63deg, #ffffff 0%, #e0f2ff 51%, #ffffff 100%);
+      }
+      .menu {
+        margin-top: 20px;
+        li {
+          height: 36px;
+          padding: 0 40px;
+          margin: 5px 0;
+          font-size: 16px;
+          display: flex;
+          align-items: center;
+          position: relative;
+
+          img {
+            width: 18px;
+            height: 18px;
+          }
+
+          span {
+            margin-left: 10px;
+            font-size: 15px;
+          }
+        }
+
+        .activeItem {
+          background-size: 100% 100%;
+        }
+      }
+    }
+
+    .rightContent {
+      flex: 1;
+      overflow: auto;
+      min-width: 800px;
+      margin-left: 15px;
+      box-shadow: 0px 0px 20px 1px #ccc;
+      border-radius: 3px;
+      background-color: #fff;
+    }
+  }
+
+  .header {
+    flex-shrink: 0;
+    width: 100%;
+  }
+}
+
+@media screen and (min-width: 1200px) {
+  .layoutContentBox {
+    flex: 1;
+    overflow: auto;
+    // display: flex;
+    // flex-direction: column;
+  }
+}
+</style>
diff --git a/src/views/classManage/infoList.vue b/src/views/classManage/infoList.vue
new file mode 100644
index 0000000..5e86ce5
--- /dev/null
+++ b/src/views/classManage/infoList.vue
@@ -0,0 +1,254 @@
+<template>
+  <div class="classManagePage-box">
+    <div class="classManagePage-nav">
+      <el-breadcrumb :separator-icon="ArrowRight">
+        <el-breadcrumb-item>鎴戠殑鐝骇</el-breadcrumb-item>
+        <el-breadcrumb-item>{{ classInfo?.name }}</el-breadcrumb-item>
+        <el-breadcrumb-item>鐝骇閫氱煡瀹℃牳</el-breadcrumb-item>
+      </el-breadcrumb>
+    </div>
+    <div class="classManagePage-content">
+      <div class="backBtn">
+        <el-button @click="goBack()" type="primary" link>
+          <el-icon style="margin-right: 5px"><ArrowLeftBold /></el-icon> 杩斿洖
+        </el-button>
+      </div>
+      <div class="contentBox">
+        <div class="titleOptions">
+          <span>鐝骇閫氱煡瀹℃牳鍒楄〃</span>
+        </div>
+        <div class="content-tab-box">
+          <div class="content-list-box">
+            <el-table
+              :header-cell-style="{ background: '#eee' }"
+              :data="dataList"
+              max-height="600px"
+              style="width: 100%"
+              v-loading="pages.loading"
+            >
+              <el-table-column prop="id" label="搴忓彿" width="70" />
+              <el-table-column prop="name" label="閫氱煡" width="500" />
+              <el-table-column prop="state" label="鐘舵��" #default="scope">
+                <span style="color: #ff6d00" v-if="scope.row.state == 'WaitAudit'">寰呭鏍�</span>
+                <span style="color: #67c23a" v-if="scope.row.state == 'Normal'">宸查�氳繃</span>
+                <span style="color: red" v-if="scope.row.state == 'Reject'">宸叉嫆缁�</span>
+              </el-table-column>
+              <el-table-column prop="createDate" label="鍒涘缓鏃堕棿" />
+              <el-table-column label="鎿嶄綔" #default="scope">
+                <el-button
+                  link
+                  v-if="scope.row.state != 'Normal'"
+                  type="success"
+                  size="small"
+                  @click="successMessage(scope.row)"
+                >
+                  鍙戝竷
+                </el-button>
+                <el-button link type="danger" size="small" @click="removeMessage(scope.row)">
+                  鍒犻櫎
+                </el-button>
+              </el-table-column>
+            </el-table>
+            <div class="pageBox">
+              <el-pagination
+                style="float: right"
+                v-model:current-page="pages.currentPage"
+                :page-size="pages.pageSize"
+                :size="'small'"
+                :disabled="pages.count <= 1"
+                layout="total, prev, pager, next"
+                :total="pages.count"
+                @size-change="handleSizeChange"
+                @current-change="handleCurrentChange"
+              />
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { useRoute, useRouter } from 'vue-router'
+import { inject, onMounted, reactive, ref } from 'vue'
+import { Search, UserFilled, ArrowRight } from '@element-plus/icons-vue'
+import { ElMessage } from 'element-plus'
+import moment from 'moment'
+
+const route: any = useRoute()
+const router = useRouter()
+const classInfo = JSON.parse(route.query.classInfo)
+const MG: any = inject('MG')
+const config: any = inject('config')
+const tool: any = inject('toolClass')
+
+let pages = reactive({
+  currentPage: 1,
+  page: 1,
+  pageSize: 15,
+  count: 0,
+  loading: true
+})
+
+const dataList: any = ref([])
+
+// 鑾峰彇鐝骇閫氱煡
+const getNotice = () => {
+  const data = {
+    start: (pages.page - 1) * pages.pageSize,
+    size: pages.pageSize,
+    appRefCode: config.appRefCode,
+    topicIdOrRefCode: String(sessionStorage.messageId),
+    sort: {
+      type: 'Desc',
+      field: 'CreateDate',
+      subSorts: []
+    }
+  }
+  MG.ugc
+    .getTopicMessageList(data)
+    .then((res: any) => {
+      pages.loading = false
+      pages.count = res.totalSize
+      const list = res.datas
+      dataList.value = list.map((item: any) => {
+        return {
+          ...item,
+          createDate: moment(item.createDate).format('YYYY-MM-DD')
+        }
+      })
+    })
+    .catch((err: any) => {
+      pages.loading = false
+      console.log(err)
+    })
+}
+
+// 閫氳繃
+const successMessage = (item: any) => {
+  const data = {
+    id: item.id,
+    name: item.name,
+    description: item.description,
+    icon: item.icon,
+    type: item.type,
+    state: 'Normal',
+    content: JSON.stringify(item.publicText),
+    newDataRequests: [],
+    updateDataRequests: []
+  }
+  MG.ugc
+    .updateTopicMessage(data)
+    .then((res: any) => {
+      if (res) {
+        ElMessage({
+          type: 'success',
+          message: '宸插彂甯�'
+        })
+        getNotice()
+      }
+    })
+    .catch((err: any) => {
+      console.log(err, '瀹℃牳璇濋')
+    })
+}
+
+// 鍒犻櫎
+const removeMessage = (item: any) => {
+  const data = {
+    messageIds: [item.id]
+  }
+  MG.ugc
+    .delTopicMessage(data)
+    .then((res: any) => {
+      if (res) {
+        ElMessage.success('宸插垹闄�')
+        getNotice()
+      }
+    })
+    .catch((err: any) => {
+      ElMessage.error('鍒犻櫎澶辫触锛岃绋嶅悗鍐嶈瘯')
+      console.log(err)
+    })
+}
+
+//  鍒嗛〉
+const handleSizeChange = (val: number) => {
+  pages.pageSize = val
+  getNotice()
+}
+
+const handleCurrentChange = (val: number) => {
+  pages.page = val
+  pages.currentPage = val
+  getNotice()
+}
+
+const goBack = () => {
+  router.go(-1)
+}
+
+onMounted(() => {
+  getNotice()
+})
+</script>
+
+<style lang="less" scoped>
+.classManagePage-box {
+  background: #fff;
+
+  .classManagePage-nav {
+    width: 100%;
+    padding: 0 20px;
+    height: 40px;
+    border-bottom: 1px solid #e6e8ed;
+    position: sticky;
+    top: 0;
+    z-index: 999;
+    display: flex;
+    align-items: center;
+    background: #fff;
+  }
+  .classManagePage-content {
+    width: 100%;
+    position: relative;
+    .backBtn {
+      width: 100%;
+      height: 45px;
+      margin-bottom: 10px;
+      padding: 0 20px;
+      display: flex;
+      align-items: center;
+      position: sticky;
+      top: 40px;
+      z-index: 99;
+      background: #fff;
+      box-shadow: 0px 0px 20px 1px #eeeeee83;
+    }
+    .contentBox {
+      width: 100%;
+      padding: 0 20px;
+      box-sizing: border-box;
+      .titleOptions {
+        width: 160px;
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        margin-bottom: 20px;
+        span {
+          height: 30px;
+          font-family: PingFang SC;
+          font-weight: bold;
+          font-size: 16px;
+          color: #333;
+          line-height: 30px;
+          text-align: left;
+          border-left: 6px solid #ff6c00;
+          padding-left: 10px;
+        }
+      }
+    }
+  }
+}
+</style>
diff --git a/src/views/classManage/interactionDetail.vue b/src/views/classManage/interactionDetail.vue
new file mode 100644
index 0000000..c0a0fd8
--- /dev/null
+++ b/src/views/classManage/interactionDetail.vue
@@ -0,0 +1,373 @@
+<template>
+  <div class="classManagePage-box">
+    <div class="classManagePage-nav">
+      <el-breadcrumb :separator-icon="ArrowRight">
+        <el-breadcrumb-item>鎴戠殑鐝骇</el-breadcrumb-item>
+        <el-breadcrumb-item>{{ classInfo?.name }}</el-breadcrumb-item>
+        <el-breadcrumb-item>浜掑姩瀛︾敓鍒楄〃</el-breadcrumb-item>
+      </el-breadcrumb>
+    </div>
+    <div class="classManagePage-content">
+      <div class="backBtn">
+        <el-button @click="goBack()" type="primary" link>
+          <el-icon style="margin-right: 5px"><ArrowLeftBold /></el-icon> 杩斿洖
+        </el-button>
+      </div>
+      <div class="contentBox">
+        <div class="titleOptions">
+          <span>浜掑姩瀛︾敓鍒楄〃</span>
+        </div>
+        <div class="content-tab-box">
+          <div class="content-list-box">
+            <el-table
+              :header-cell-style="{ background: '#eee' }"
+              :data="dataList"
+              max-height="600px"
+              style="width: 100%"
+              v-loading="pages.loading"
+            >
+              <el-table-column prop="index" label="搴忓彿" width="70" />
+              <el-table-column prop="userName" label="濮撳悕" width="500" />
+              <el-table-column label="鐘舵��">
+                <el-button link type="success">宸插畬鎴�</el-button>
+              </el-table-column>
+              <el-table-column prop="questionTime" label="绛旈鏃堕棿" />
+              <el-table-column label="鎿嶄綔" #default="scoped">
+                <el-button link type="primary" @click="getQuestions(scoped.row)">
+                  绛旈璇︽儏
+                </el-button>
+              </el-table-column>
+            </el-table>
+            <div class="pageBox">
+              <el-pagination
+                style="float: right"
+                v-model:current-page="pages.currentPage"
+                :page-size="pages.pageSize"
+                :size="'small'"
+                :disabled="pages.count <= 1"
+                layout="total, prev, pager, next"
+                :total="pages.count"
+                @size-change="handleSizeChange"
+                @current-change="handleCurrentChange"
+              />
+            </div>
+          </div>
+        </div>
+      </div>
+      <!-- 娴忚绛旈 -->
+      <el-dialog
+        class="customDialog"
+        title="娴忚绛旈"
+        v-model="visible"
+        destroy-on-close
+        width="1000"
+        align-center
+      >
+        <div class="pubContent" v-if="dialogList.length > 0 && !dialogLLoading">
+          <div v-for="(item, index) in dialogList" :key="index">
+            <span class="userName">绛旈浜猴細{{ item.userName ?? '-' }}</span>
+            <question-dom
+              v-if="item.questionTypeList.length > 0"
+              :questionList="item.questionTypeList"
+              :noCheckbox="false"
+              :is-preview="true"
+              :is-interaction="true"
+            />
+          </div>
+        </div>
+        <div class="pubContent" v-if="dialogLLoading" v-loading="dialogLLoading"></div>
+        <div class="pubContent noData" v-if="dialogList.length == 0 && !dialogLLoading">
+          <el-empty></el-empty>
+        </div>
+        <template #footer>
+          <div class="selectedFooter" style="padding: 0">
+            <el-button type="primary" @click="visible = false"> 鍏抽棴 </el-button>
+          </div>
+        </template>
+      </el-dialog>
+    </div>
+  </div>
+</template>
+<script setup lang="ts">
+import { useRoute, useRouter } from 'vue-router'
+import { inject, onMounted, reactive, ref } from 'vue'
+import { Search, UserFilled, ArrowRight } from '@element-plus/icons-vue'
+import { ElMessage } from 'element-plus'
+import moment from 'moment'
+import questionDom from './components/questionDom.vue'
+
+const route: any = useRoute()
+const router = useRouter()
+const classInfo = JSON.parse(route.query.classInfo)
+const MG: any = inject('MG')
+const config: any = inject('config')
+const tool: any = inject('toolClass')
+
+const dataList = ref([])
+let pages = reactive({
+  currentPage: 1,
+  page: 1,
+  pageSize: 15,
+  count: 0,
+  loading: false
+})
+
+const visible = ref(false)
+const dialogList: any = ref([])
+const dialogLLoading = ref(false)
+const defaultCmsPath = ref('')
+
+const handleDelete = (item: any) => {
+  const data = {
+    messageIds: [item.id]
+  }
+  MG.ugc.delTopicMessage(data).then((res: any) => {
+    ElMessage.success('鍒犻櫎鎴愬姛')
+    getMessage()
+  })
+}
+
+// 鑾峰彇褰撳墠璇濋
+const getMessage = () => {
+  pages.loading = true
+  const data = {
+    start: (pages.page - 1) * pages.pageSize,
+    size: pages.pageSize,
+    appRefCode: config.appRefCode,
+    topicIdOrRefCode: String(classInfo.teachInteractionId),
+    sort: {
+      type: 'Desc',
+      field: 'CreateDate'
+    },
+    searchList: [
+      {
+        keywords: classInfo.questionName,
+        field: 'Name',
+        compareType: 'Contains'
+      }
+    ]
+  }
+  MG.ugc.getTopicMessageList(data).then((res: any) => {
+    pages.loading = false
+    pages.count = res.totalSize
+    dataList.value = res.datas.map((item: any, i: number) => {
+      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')
+      }
+    })
+  })
+}
+
+//  鍒嗛〉
+const handleSizeChange = (val: number) => {
+  pages.pageSize = val
+  getMessage()
+}
+
+const handleCurrentChange = (val: number) => {
+  pages.page = val
+  pages.currentPage = val
+  getMessage()
+}
+
+onMounted(() => {
+  defaultCmsPath.value = classInfo.bookRefCode ? 'jsek_digitalTextbooks' : 'defaultGoodsStore3'
+  getMessage()
+})
+
+// 鑾峰彇棰樼洰鍒楄〃
+const getQuestions = (item: any) => {
+  visible.value = true
+  dialogLLoading.value = true
+  MG.store
+    .getProductDetail({
+      path: defaultCmsPath.value,
+      queryType: '*',
+      productId: classInfo.bookId,
+      storeInfo: defaultCmsPath.value,
+      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: any) => {
+      try {
+        let list = []
+        list = res.datas.cmsDatas[0]?.datas.map((item: any) => {
+          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)
+          }
+        })
+        dialogList.value = chageData([item], list)
+        dialogLLoading.value = false
+      } catch (error) {
+        dialogList.value = []
+        dialogLLoading.value = false
+      }
+    })
+}
+
+// 澶勭悊鏁版嵁缁撴瀯
+const chageData = (arr: any, zrr: any) => {
+  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 = JSON.parse(JSON.stringify(questionTypeList))
+    for (let j = 0; j < zrr.length; j++) {
+      const ele = zrr[j]
+      const qusObj = item.question.find((citem: any) => 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: any) => item.data.length > 0)
+    newData.push(item)
+  }
+  return newData.filter((item) => item.questionTypeList.length > 0)
+}
+
+const findIndexByValue = (res: any, type: string) => {
+  for (let i = 0; i < res.length; i++) {
+    if (res[i].value == type) {
+      return i
+    }
+  }
+  return -1 // 濡傛灉鏈壘鍒帮紝鍒欒繑鍥� -1
+}
+
+// 浣滀笟鎼滅储
+const searchData = () => {}
+
+const goBack = () => {
+  router.go(-1)
+}
+</script>
+<style lang="less" scoped>
+.classManagePage-box {
+  background: #fff;
+
+  .classManagePage-nav {
+    width: 100%;
+    padding: 0 20px;
+    height: 40px;
+    border-bottom: 1px solid #e6e8ed;
+    position: sticky;
+    top: 0;
+    z-index: 999;
+    display: flex;
+    align-items: center;
+    background: #fff;
+  }
+  .classManagePage-content {
+    width: 100%;
+    position: relative;
+    .backBtn {
+      width: 100%;
+      height: 45px;
+      margin-bottom: 10px;
+      padding: 0 20px;
+      display: flex;
+      align-items: center;
+      position: sticky;
+      top: 40px;
+      z-index: 99;
+      background: #fff;
+      box-shadow: 0px 0px 20px 1px #eeeeee83;
+    }
+    .contentBox {
+      width: 100%;
+      padding: 0 20px;
+      box-sizing: border-box;
+      .titleOptions {
+        width: 160px;
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        margin-bottom: 20px;
+        span {
+          height: 30px;
+          font-family: PingFang SC;
+          font-weight: bold;
+          font-size: 16px;
+          color: #333;
+          line-height: 30px;
+          text-align: left;
+          border-left: 6px solid #ff6c00;
+          padding-left: 10px;
+        }
+      }
+    }
+    .pubContent {
+      padding: 10px;
+      box-sizing: border-box;
+      min-height: 750px;
+      .userName {
+        color: #ff6d00;
+      }
+    }
+  }
+}
+</style>
diff --git a/src/views/classManage/jobAnalysis.vue b/src/views/classManage/jobAnalysis.vue
new file mode 100644
index 0000000..06d8e89
--- /dev/null
+++ b/src/views/classManage/jobAnalysis.vue
@@ -0,0 +1,331 @@
+<template>
+  <div class="classManagePage-box">
+    <el-breadcrumb :separator-icon="ArrowRight">
+      <el-breadcrumb-item>鎴戠殑鐝骇</el-breadcrumb-item>
+      <el-breadcrumb-item>{{ classInfo?.name }}</el-breadcrumb-item>
+      <el-breadcrumb-item>浣滀笟鍒嗘瀽</el-breadcrumb-item>
+    </el-breadcrumb>
+    <div class="classManagePage-content" v-loading="pageLoading">
+      <div class="staticBox">
+        <div class="pub_staticItem">
+          <img src="@/assets/images/class/zuoyecishu@2x.png" alt="" />
+          <div class="staticText">
+            <el-statistic title="浣滀笟娆℃暟" :value="outputValue" />
+          </div>
+        </div>
+        <!-- <div class="pub_staticItem">
+          <img src="@/assets/images/class/jinxing@2x.png" alt="" />
+          <div class="staticText">
+            <el-statistic title="杩涜涓�" :value="8" />
+          </div>
+        </div>
+        <div class="pub_staticItem">
+          <img src="@/assets/images/class/jieshu@2x.png" alt="" />
+          <div class="staticText">
+            <el-statistic title="宸茬粨鏉�" :value="8" />
+          </div>
+        </div> -->
+      </div>
+      <div class="chartsBox">
+        <div id="chartsContent" v-show="charstData.length > 0"></div>
+      </div>
+      <div v-if="charstData.length == 0 && !pageLoading">
+        <el-empty />
+      </div>
+      <div class="listContent" v-if="tabHeader.length > 0">
+        <div class="tableTitle">鐝骇鎴愮哗璇︽儏</div>
+        <div class="tableContent">
+          <el-table
+            v-loading="pages.loading"
+            :data="tableData"
+            border
+            style="width: 100%"
+            :cell-style="{ textAlign: 'center' }"
+            :header-cell-style="{ textAlign: 'center' }"
+            size="small"
+          >
+            <el-table-column prop="index" label="搴忓彿" width="70" />
+            <el-table-column label="濮撳悕" #default="scope">
+              <span>{{ scope.row.appUser?.userInfo?.name }}</span>
+            </el-table-column>
+            <el-table-column label="瀛﹀彿" #default="scope">
+              <span>{{ scope.row.appUser?.appUserId }}</span>
+            </el-table-column>
+            <el-table-column label="鐝骇浣滀笟寰楀垎" v-if="tabHeader.length > 0">
+              <el-table-column v-for="(item, index) in tabHeader" :key="index" :label="item">
+                <template #default="scope">
+                  <span v-if="scope.row.results[index]?.result >= 0">
+                    {{ scope.row.results[index]?.result }}
+                  </span>
+                  <span v-else> -- </span>
+                </template>
+              </el-table-column>
+            </el-table-column>
+          </el-table>
+          <el-pagination
+            style="float: right"
+            v-model:current-page="pages.page"
+            :page-size="pages.pageSize"
+            layout="total, prev, pager, next"
+            :total="pages.count"
+            @size-change="handleSizeChange"
+            @current-change="handleCurrentChange"
+          />
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import * as echarts from 'echarts'
+import { ArrowRight } from '@element-plus/icons-vue'
+import { useRoute } from 'vue-router'
+import { useTransition } from '@vueuse/core'
+import { inject, onMounted, onUnmounted, reactive, ref } from 'vue'
+const route: any = useRoute()
+const MG: any = inject('MG')
+const classInfo: any = JSON.parse(route.query.classInfo)
+var chartDom = null
+var myChart: any = {}
+var option = null
+
+const nameList: any = ref([])
+const charstData: any = ref([])
+const count = ref(0)
+const pageLoading = ref(true)
+const outputValue = useTransition(count, {
+  duration: 1000
+})
+const tabHeader: any = ref([])
+const tableData: any = ref([])
+
+let pages = reactive({
+  page: 1,
+  pageSize: 5,
+  count: 0,
+  loading: false
+})
+
+// 鍥捐〃鍒濆鍖�
+const initCharts = () => {
+  option = {
+    legend: {
+      bottom: 0
+    },
+    tooltip: {
+      trigger: 'axis',
+      showContent: true
+    },
+    toolbox: {
+      feature: {
+        saveAsImage: {},
+        magicType: {
+          type: ['bar']
+        },
+        restore: {}
+      }
+    },
+    title: {
+      text: '鐝骇鎴愮哗姒傝',
+      textStyle: {
+        fontFamily: 'PingFang SC',
+        color: '#000000',
+        fontWeight: 'bold',
+        fontSize: '16px'
+      }
+    },
+    dataset: {
+      source: charstData.value
+    },
+    xAxis: { type: 'category' },
+    yAxis: { gridIndex: 0 },
+    grid: {
+      left: '3%',
+      right: '4%',
+      containLabel: true
+    },
+    series: [
+      {
+        type: 'line',
+        smooth: true,
+        seriesLayoutBy: 'row',
+        emphasis: { focus: 'series' }
+      },
+      {
+        type: 'line',
+        smooth: true,
+        seriesLayoutBy: 'row',
+        emphasis: { focus: 'series' }
+      },
+      {
+        type: 'line',
+        smooth: true,
+        seriesLayoutBy: 'row',
+        emphasis: { focus: 'series' }
+      }
+    ]
+  }
+  option && myChart.setOption(option)
+}
+
+onMounted(() => {
+  getData()
+  getUserTaskList()
+})
+
+// 鑾峰彇缁熻鏁版嵁
+const getData = () => {
+  const data = {
+    classId: classInfo?.id
+  }
+  MG.edu
+    .getTaskStatistics(data)
+    .then((res: any) => {
+      count.value = res.length
+      if (res.length > 0) {
+        let dataX = res.map((item: any) => item.task.name)
+        dataX.unshift('homeWork')
+        nameList.value = dataX
+        let avg = ['鐝骇骞冲潎鍒�']
+        let max = ['鏈�楂樺垎']
+        let min = ['鏈�浣庡垎']
+        res.forEach((item: any) => {
+          avg.push(item.avgScore)
+          max.push(item.maxScore)
+          min.push(item.minScore)
+        })
+        charstData.value = [dataX, avg, max, min]
+      } else {
+        charstData.value = []
+        nameList.value = []
+      }
+      setTimeout(() => {
+        pageLoading.value = false
+        chartDom = document.getElementById('chartsContent')
+        myChart = echarts.init(chartDom)
+        initCharts()
+      }, 1000)
+    })
+    .catch((err: any) => {
+      pageLoading.value = false
+      console.log(err)
+    })
+}
+
+// 鑾峰彇鐝骇浣滀笟鎴愮哗璇︽儏
+const getUserTaskList = () => {
+  pages.loading = true
+  const data = {
+    start: (pages.page - 1) * pages.pageSize,
+    size: pages.pageSize,
+    classId: classInfo?.id
+  }
+  MG.edu
+    .getUserTaskList(data)
+    .then((res: any) => {
+      let headerList: any = []
+      pages.count = res.totalSize
+      if (res.datas.length > 0) {
+        res.datas.forEach((item: any, index: number) => {
+          item.index = index + 1
+          const hitem = item.results.map((citem: any) => citem.name)
+          headerList.push(...hitem)
+        })
+        tableData.value = res.datas
+        tabHeader.value = Array.from(new Set(headerList))
+      } else {
+        tableData.value = []
+        tabHeader.value = []
+      }
+      pages.loading = false
+    })
+    .catch((err: any) => {
+      pages.loading = false
+      console.log(err)
+    })
+}
+
+const handleSizeChange = (val: number) => {
+  pages.pageSize = val
+  getUserTaskList()
+}
+
+const handleCurrentChange = (val: number) => {
+  pages.page = val
+  getUserTaskList()
+}
+</script>
+
+<style lang="less" scoped>
+.classManagePage-box {
+  width: 100%;
+  padding: 20px;
+  .classManagePage-nav {
+    padding-bottom: 20px;
+    border-bottom: 1px solid #e6e8ed;
+  }
+  .classManagePage-content {
+    width: 100%;
+    padding: 30px 0;
+
+    .staticBox {
+      width: 100%;
+      height: 60px;
+      display: flex;
+      justify-content: flex-start;
+      align-items: center;
+      margin-bottom: 40px;
+
+      .pub_staticItem {
+        display: flex;
+
+        img {
+          width: 60px;
+          height: 60px;
+          background: #ebf4ff;
+          border-radius: 8px 8px 8px 8px;
+          margin-right: 15px;
+        }
+        .staticText {
+          display: flex;
+          flex-direction: column;
+          justify-content: space-between;
+
+          span:nth-child(1) {
+            font-family: PingFang SC;
+            font-weight: bold;
+            font-size: 14px;
+            color: #a5a7ab;
+          }
+
+          span:nth-child(2) {
+            font-family: DIN;
+            font-weight: 500;
+            font-size: 20px;
+            color: #000000;
+          }
+        }
+      }
+    }
+
+    .chartsBox {
+      margin-bottom: 40px;
+      #chartsContent {
+        height: 600px;
+      }
+    }
+
+    .listContent {
+      width: 100%;
+      .tableTitle {
+        font-family: PingFang SC;
+        font-weight: bold;
+        font-size: 16px;
+        color: #000000;
+        margin-bottom: 22px;
+      }
+    }
+  }
+}
+</style>
diff --git a/src/views/classManage/jobDetail.vue b/src/views/classManage/jobDetail.vue
new file mode 100644
index 0000000..b893184
--- /dev/null
+++ b/src/views/classManage/jobDetail.vue
@@ -0,0 +1,840 @@
+<template>
+  <div class="classManagePage-box">
+    <div class="classManagePage-nav">
+      <el-breadcrumb :separator-icon="ArrowRight">
+        <el-breadcrumb-item>鎴戠殑鐝骇</el-breadcrumb-item>
+        <el-breadcrumb-item>{{ classInfo?.name }}</el-breadcrumb-item>
+        <el-breadcrumb-item>浣滀笟绠$悊璇︽儏</el-breadcrumb-item>
+      </el-breadcrumb>
+    </div>
+    <div class="classManagePage-content">
+      <div class="backBtn">
+        <el-button @click="goBack()" type="primary" link>
+          <el-icon style="margin-right: 5px"><ArrowLeftBold /></el-icon> 杩斿洖
+        </el-button>
+      </div>
+      <div class="contentBox">
+        <div class="content-tab-box">
+          <div class="content-header">
+            <div class="selectState">
+              <span>鐘舵�侊細</span>
+              <el-select placeholder="鍏ㄩ儴" v-model="workState" @change="selectChangeState">
+                <el-option
+                  v-for="item in options"
+                  :key="item.value"
+                  :label="item.label"
+                  :value="item.value"
+                />
+              </el-select>
+            </div>
+            <div class="searchBox" v-if="workState != 'WaitSubmit'">
+              <!-- <el-input
+                v-model="searchKey"
+                clearable
+                @clear="searchData"
+                placeholder="璇疯緭鍏ュ叧閿瓧"
+              >
+                <template #append>
+                  <el-button type="primary" @click="searchData" class="searchBtn" :icon="Search" />
+                </template>
+              </el-input> -->
+            </div>
+          </div>
+          <div class="content-list-box">
+            <el-table
+              :data="tableData"
+              border
+              max-height="600px"
+              style="width: 100%"
+              :header-cell-class-name="'headerCellClassName'"
+              v-loading="tableLoading"
+              v-if="workState != 'WaitSubmit'"
+            >
+              <el-table-column label="搴忓彿" prop="id" width="60"> </el-table-column>
+              <el-table-column label="濮撳悕" #default="scope" width="150">
+                <span>{{ scope.row.appUser?.userInfo?.name }}</span>
+              </el-table-column>
+              <el-table-column label="鐘舵��" prop="state" #default="scope">
+                <span v-if="scope.row.state == 'WaitCheck'" style="color: #409eff">鏈壒鏀�</span>
+                <span v-if="scope.row.state == 'Normal'" style="color: #67c23a">宸叉壒鏀�</span>
+                <span v-if="scope.row.state == 'WaitSubmit'" style="color: red">鏈彁浜�</span>
+              </el-table-column>
+              <el-table-column label="寰楀垎" #default="scope">
+                <span v-if="scope.row.result > 0">{{ scope.row.result }}</span>
+                <span v-else>{{ scope.row.totalScore }}</span>
+              </el-table-column>
+              <el-table-column label="鍗曢�夐" v-if="singleChoiceLength > 0">
+                <el-table-column
+                  v-for="(item, index) in singleChoiceLength"
+                  :key="index"
+                  :label="item"
+                >
+                  <template #default="scope">
+                    <span v-if="scope.row.singleChoiceArr[index]?.score == 0" style="color: red">
+                      {{ scope.row.singleChoiceArr[index]?.answer }}
+                    </span>
+                    <span v-else style="color: #67c23a">
+                      {{ scope.row.singleChoiceArr[index]?.answer }}
+                    </span>
+                  </template>
+                </el-table-column>
+              </el-table-column>
+              <el-table-column label="澶氶�夐" v-if="multipleChoiceLength > 0">
+                <el-table-column
+                  v-for="(item, index) in multipleChoiceLength"
+                  :key="index"
+                  :label="item"
+                >
+                  <template #default="scope">
+                    <span v-if="scope.row.judgeArr[index]?.score == 0" style="color: red">
+                      {{ scope.row.multipleChoiceArr[index]?.answer.join(',') }}
+                    </span>
+                    <span v-else style="color: #67c23a">
+                      {{ scope.row.multipleChoiceArr[index]?.answer.join(',') }}
+                    </span>
+                  </template>
+                </el-table-column>
+              </el-table-column>
+              <el-table-column label="鍒ゆ柇棰�" v-if="judgeLength > 0">
+                <el-table-column v-for="(item, index) in judgeLength" :key="index" :label="item">
+                  <template #default="scope">
+                    <span v-if="scope.row.judgeArr[index]?.score == 0" style="color: red">
+                      {{ scope.row.judgeArr[index]?.answer }}
+                    </span>
+                    <span v-else style="color: #67c23a">
+                      {{ scope.row.judgeArr[index]?.answer }}
+                    </span>
+                  </template>
+                </el-table-column>
+              </el-table-column>
+              <el-table-column label="濉┖棰橈紙鍒嗭級" v-if="completionLength > 0">
+                <el-table-column
+                  v-for="(item, index) in completionLength"
+                  :key="index"
+                  :label="item"
+                >
+                  <template #default="scope">
+                    <span v-if="scope.row.completionArr[index]?.score == 0" style="color: red">
+                      {{ scope.row.completionArr[index]?.score }}
+                    </span>
+                    <span v-else style="color: #67c23a">
+                      {{ scope.row.completionArr[index]?.score }}
+                    </span>
+                  </template>
+                </el-table-column>
+              </el-table-column>
+              <el-table-column label="涓昏棰橈紙鍒嗭級" v-if="otherLength > 0">
+                <el-table-column v-for="(item, index) in otherLength" :key="index" :label="item">
+                  <template #default="scope">
+                    <span v-if="scope.row.otherArr[index]?.score == 0" style="color: red">
+                      {{ scope.row.otherArr[index]?.score }}
+                    </span>
+                    <span v-else style="color: #67c23a">
+                      {{ scope.row.otherArr[index]?.score }}
+                    </span>
+                  </template>
+                </el-table-column>
+              </el-table-column>
+              <el-table-column label="鎿嶄綔" width="150" #default="scope">
+                <el-button
+                  link
+                  v-if="scope.row.state != 'Normal'"
+                  style="color: #409eff"
+                  @click="openDialog(scope.row)"
+                >
+                  鍒ゆ柇涓昏棰�
+                </el-button>
+                <el-button link v-if="scope.row.state == 'Normal'"> -- </el-button>
+              </el-table-column>
+            </el-table>
+            <el-table
+              :data="dataList"
+              border
+              v-else
+              max-height="600px"
+              style="width: 100%"
+              :header-cell-class-name="'headerCellClassName'"
+              v-loading="pages.loading"
+            >
+              <el-table-column prop="index" label="搴忓彿" width="70" />
+              <el-table-column prop="appUserId" label="瀛﹀彿" width="150" />
+              <el-table-column label="濮撳悕" width="400">
+                <template #default="scope">
+                  <div class="userBox">
+                    <el-avatar
+                      style="margin-right: 10px"
+                      v-if="scope.row.appUser.icon"
+                      :size="35"
+                      :src="scope.row.appUser.icon"
+                    />
+                    <el-avatar
+                      style="margin-right: 10px"
+                      :size="35"
+                      v-if="!scope.row.appUser.icon"
+                      :icon="UserFilled"
+                    />
+                    <span v-if="scope.row.appUser.name">{{ scope.row.appUser.name }}</span>
+                  </div>
+                </template>
+              </el-table-column>
+              <el-table-column prop="createDate" label="鍔犲叆鐝骇鏃堕棿" />
+              <el-table-column label="鎿嶄綔" width="220" #default="scope">
+                <el-button link style="color: red" @click="remindWork(scope.row)">
+                  鍌氦浣滀笟
+                </el-button>
+              </el-table-column>
+            </el-table>
+            <div class="pageBox">
+              <el-pagination
+                v-model:current-page="pages.currentPage"
+                :page-size="pages.pageSize"
+                :size="'small'"
+                :disabled="pages.count <= 1"
+                layout="total, prev, pager, next"
+                :total="pages.count"
+                @size-change="handleSizeChange"
+                @current-change="handleCurrentChange"
+              />
+            </div>
+          </div>
+        </div>
+        <!-- 涓昏棰樺垽鏂� -->
+        <el-dialog
+          class="customDialog"
+          title="鍒ゆ柇涓昏棰�"
+          v-model="otherVisible"
+          destroy-on-close
+          width="800"
+          :before-close="close"
+        >
+          <div class="pubContent">
+            <questionDom
+              :question-list="otherQuestions"
+              :is-judge="true"
+              @judge-update="judgeUpdate"
+            />
+          </div>
+        </el-dialog>
+      </div>
+    </div>
+  </div>
+</template>
+<script setup lang="ts">
+import { useRoute, useRouter } from 'vue-router'
+import { inject, onMounted, reactive, ref } from 'vue'
+import { Search, UserFilled, ArrowRight } from '@element-plus/icons-vue'
+import { ElMessage } from 'element-plus'
+import questionDom from './components/questionDom.vue'
+import moment from 'moment'
+
+const route: any = useRoute()
+const router = useRouter()
+const classInfo = JSON.parse(route.query.classInfo)
+const MG: any = inject('MG')
+const config: any = inject('config')
+const tool: any = inject('toolClass')
+
+// 浣滀笟璇︽儏
+const workState = ref('all')
+const searchKey = ref('')
+const cmsDatas: any = ref([])
+const tableData: any = ref([])
+const tableLoading = ref(true)
+const singleChoiceLength = ref(0)
+const multipleChoiceLength = ref(0)
+const judgeLength = ref(0)
+const completionLength = ref(0)
+const otherLength = ref(0)
+const otherVisible = ref(false)
+const otherQuestions: any = ref([]) // 涓昏棰�
+const cacheDate: any = ref([])
+const currentWorkId = ref(null) // 褰撳墠浣滀笟id
+const dataList: any = ref([]) // 鏈彁浜ゅ垪琛�
+const options = ref([
+  {
+    label: '鍏ㄩ儴',
+    value: 'all'
+  },
+  {
+    label: '鏈壒鏀�',
+    value: 'WaitCheck'
+  },
+  {
+    label: '宸叉壒鏀�',
+    value: 'Normal'
+  },
+  {
+    label: '鏈彁浜�',
+    value: 'WaitSubmit'
+  }
+])
+
+let pages = reactive({
+  currentPage: 1,
+  page: 1,
+  pageSize: 15,
+  count: 0,
+  loading: true
+})
+
+const questionKey = [
+  'Name',
+  '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'
+]
+
+//  鍒嗛〉
+const handleSizeChange = (val: number) => {
+  pages.pageSize = val
+  if (workState.value != 'WaitSubmit') {
+    getTaskDetail()
+  } else {
+    getUnSubmitList()
+  }
+}
+
+const handleCurrentChange = (val: number) => {
+  pages.page = val
+  pages.currentPage = val
+  if (workState.value != 'WaitSubmit') {
+    getTaskDetail()
+  } else {
+    getUnSubmitList()
+  }
+}
+
+onMounted(() => {
+  getTaskCmsList()
+})
+
+// 鐘舵�佹敼鍙�
+const selectChangeState = (item: any) => {
+  workState.value = item
+  if (item == 'WaitSubmit') {
+    // const data = [{ field: 'State', value: 'Normal', subFilters: [] }]
+    getUnSubmitList()
+  } else {
+    const data = item != 'all' ? [{ field: 'State', value: item, subFilters: [] }] : []
+    getTaskDetail(data)
+  }
+}
+
+const openDialog = (item: any) => {
+  otherVisible.value = true
+  currentWorkId.value = item.id
+}
+
+// 鑾峰彇璇︽儏
+const getTaskDetail = (filter?: any, search?: any) => {
+  const filterList = filter ?? []
+  const searchList = search ?? []
+  tableLoading.value = true
+  const data = {
+    start: (pages.page - 1) * pages.pageSize,
+    size: pages.pageSize,
+    taskId: classInfo?.taskWorkId,
+    classId: classInfo?.id,
+    filterList,
+    searchList
+  }
+  MG.edu
+    .getTaskSubmitList(data)
+    .then((res: any) => {
+      pages.loading = false
+      pages.count = res.totalSize
+      cacheDate.value = []
+      // 棰樺簱棰樼洰绫诲瀷
+      const questionTypeList = [
+        { name: '绠�绛旈', totalScore: 0, value: 'shortAnswer', data: [] },
+        { name: '璁鸿堪棰�', totalScore: 0, value: 'discuss', data: [] },
+        { name: '杩炵嚎棰�', totalScore: 0, value: 'matching', data: [] },
+        { name: '鍒嗙被棰�', totalScore: 0, value: 'classification', data: [] }
+      ]
+      try {
+        let list: any = []
+        res.datas.forEach((item: any) => {
+          const parentData = {
+            feedBack: item.feedBack,
+            id: item.id,
+            result: item.result,
+            type: item.type,
+            state: item.state,
+            submit: item.submit,
+            updateTaskSubmitCmsItemRequests: []
+          }
+          item.singleChoiceName = '鍗曢�夐'
+          item.singleChoiceArr = []
+          item.multipleChoiceName = '澶氶�夐'
+          item.multipleChoiceArr = []
+          item.judgeName = '鍒ゆ柇棰�'
+          item.judgeArr = []
+          item.completionName = '濉┖棰�'
+          item.completionArr = []
+          item.otherName = '涓昏棰�'
+          item.otherArr = []
+          item.totalScore = 0
+          const submitData = deduplicateArray(item.submitAndCmsItemLinks, 'cmsItemId')
+          submitData.forEach((citem: any) => {
+            const obj = cmsDatas.value.find((i: any) => i.id == citem.cmsItemId)
+            item.totalScore += citem.score
+            if (citem.answer != '') {
+              if (obj.questionType == 'singleChoice') {
+                citem.answer = JSON.parse(citem.answer) ?? '-'
+                item.singleChoiceArr.push(citem)
+              } else if (obj.questionType == 'multipleChoice') {
+                citem.answer = JSON.parse(citem.answer) ?? '-'
+                item.multipleChoiceArr.push(citem)
+              } else if (obj.questionType == 'judge') {
+                citem.answer = JSON.parse(citem.answer) ?? '-'
+                item.judgeArr.push(citem)
+              } else if (obj.questionType == 'completion') {
+                citem.answer = JSON.parse(citem.answer) ?? '-'
+                item.completionArr.push(citem)
+              } else {
+                obj.score = citem.score
+                obj.answer = citem.answer
+                obj.updateId = citem.id
+                obj.parentId = item.id
+                item.otherArr.push(citem)
+                list.push(obj)
+              }
+            }
+          })
+          cacheDate.value.push(parentData)
+        })
+        list.forEach((item: any) => {
+          const index = findIndexByValue(questionTypeList, item.questionType)
+          if (index > -1) {
+            questionTypeList[index].data.push(item)
+            if (item.score) {
+              questionTypeList[index].totalScore += item.score
+            }
+          }
+        })
+        otherQuestions.value = questionTypeList.filter((item) => item.data.length > 0)
+        const lenghtArr = [...res.datas]
+        singleChoiceLength.value = lenghtArr.reduce(
+          (max: any, obj: any) => Math.max(max, obj.singleChoiceArr.length),
+          0
+        )
+        multipleChoiceLength.value = lenghtArr.reduce(
+          (max: any, obj: any) => Math.max(max, obj.multipleChoiceArr.length),
+          0
+        )
+        judgeLength.value = lenghtArr.reduce(
+          (max: any, obj: any) => Math.max(max, obj.judgeArr.length),
+          0
+        )
+        completionLength.value = lenghtArr.reduce(
+          (max: any, obj: any) => Math.max(max, obj.completionArr.length),
+          0
+        )
+        otherLength.value = lenghtArr.reduce(
+          (max: any, obj: any) => Math.max(max, obj.otherArr.length),
+          0
+        )
+        tableLoading.value = false
+        tableData.value = res.datas
+      } catch (err) {
+        tableLoading.value = false
+        console.log(err)
+      }
+    })
+    .catch((err: any) => {
+      console.log(err)
+    })
+}
+
+// 鑾峰彇浠诲姟涓嬬殑璧勬簮鍒楄〃
+const getTaskCmsList = () => {
+  tableLoading.value = true
+  const data = {
+    start: 0,
+    size: 999,
+    searchList: [],
+    taskId: classInfo?.taskWorkId, // taskData?.id
+    path: String(classInfo?.taskCmsId), //taskData?.rootCmsItemId
+    type: '*',
+    keys: questionKey
+  }
+  MG.edu
+    .getTaskCmsItem(data)
+    .then((res: any) => {
+      for (let i = 0; i < res.datas.length; i++) {
+        let item = res.datas[i]
+        item.index = i + 1
+        // 澶勭悊瀛楁
+        if (questionKey != null) {
+          for (let fieldKey of questionKey) {
+            if (item.datas[fieldKey]) {
+              const values = JSON.parse(item.datas[fieldKey])
+              if (values.length > 0) {
+                // 鐢ㄥ瓧娈靛悕澶勭悊杩斿洖鐨勫瓧娈靛��
+                if (values[0].Value) {
+                  item[fieldKey] = values[0].Value
+                } else if (values[0].Data) {
+                  item[fieldKey] = values[0].Data.Value
+                } else if (!values[0].Value && values[0].FileList?.length > 0) {
+                  item[fieldKey] = values[0].FileList
+                } else {
+                  item[fieldKey] = '-'
+                }
+              }
+            }
+          }
+        }
+      }
+      cmsDatas.value = changeQuestionData(res.datas)
+      tableLoading.value = false
+    })
+    .catch((e: any) => {
+      ElMessage({
+        message: '鍒楄〃鑾峰彇澶辫触',
+        type: 'error'
+      })
+      tableLoading.value = false
+      console.log(e)
+    })
+}
+
+// 澶勭悊棰樼洰鏁版嵁缁撴瀯
+const changeQuestionData = (res: any) => {
+  try {
+    let list = []
+    list = res?.map((item: any) => {
+      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)
+      }
+    })
+    getTaskDetail()
+    return list
+  } catch (error) {
+    console.log(error)
+    return []
+  }
+}
+
+const findIndexByValue = (res: any, type: string) => {
+  for (let i = 0; i < res.length; i++) {
+    if (res[i].value == type) {
+      return i
+    }
+  }
+  return -1 // 濡傛灉鏈壘鍒帮紝鍒欒繑鍥� -1
+}
+
+// 鑾峰彇鏈彁浜や换鍔″垪琛�
+const getUnSubmitList = (filter?: any, search?: any) => {
+  const filterList = filter ?? []
+  const searchList = search ?? []
+  const data = {
+    start: (pages.page - 1) * pages.pageSize,
+    size: pages.pageSize,
+    taskId: classInfo?.taskWorkId,
+    classId: classInfo?.id,
+    filterList,
+    searchList
+  }
+  MG.edu
+    .getUnSubmitList(data)
+    .then((res: any) => {
+      const { datas, totalSize } = res
+      pages.loading = false
+      pages.count = totalSize
+      if (datas.length > 0) {
+        dataList.value = datas.map((item: any, index: number) => {
+          const userInfo = item.appUser?.infoList[0] ?? null
+          item.appUser.name = userInfo.name
+          item.appUser.icon = userInfo.icon
+          return {
+            ...item,
+            index: index + 1,
+            createDate: moment(item.createDate).format('YYYY-MM-DD'),
+            appUserId: item.appUser.id
+          }
+        })
+        pages.count = totalSize
+      }
+    })
+    .catch((err: any) => {
+      console.log(err)
+    })
+}
+
+// 鍏抽棴
+const close = () => {
+  otherVisible.value = false
+}
+
+// 涓昏棰樻彁浜�
+const judgeUpdate = (item: any) => {
+  const listData = [...cacheDate.value]
+  let judgeScore = 0
+  if (item) {
+    const requestData = {
+      classId: classInfo?.id,
+      requests: []
+    }
+    const data = JSON.parse(item)
+    listData.forEach((citem: any) => {
+      const strData = data.find((i: any) => i.parentId == citem.id)
+      if (strData) {
+        citem.updateTaskSubmitCmsItemRequests = data.map((uitem: any) => {
+          judgeScore += uitem.score
+          return {
+            linkId: uitem.updateId,
+            score: uitem.score,
+            answer: uitem.answer,
+            state: 'Normal',
+            comments: 'judge'
+          }
+        })
+      }
+    })
+    let dataobj = null
+    dataobj = listData.find((litem) => litem.id == currentWorkId.value)
+    dataobj.state = 'Normal'
+    dataobj.result = dataobj.result + judgeScore
+    requestData.requests = [dataobj]
+    MG.edu
+      .updateTaskSubmit(requestData)
+      .then((res: any) => {
+        if (res) {
+          otherVisible.value = false
+          getTaskDetail()
+        }
+      })
+      .catch((err: any) => {
+        console.log(err)
+      })
+  }
+}
+
+//鏁扮粍鍘婚噸
+const deduplicateArray = (arr: any, idKey: string) => {
+  const seen: any = {}
+  const deduplicatedArray = arr.filter((item: any) => {
+    const id = item[idKey]
+    if (!seen[id]) {
+      seen[id] = true
+      return true
+    }
+    return false
+  })
+
+  return deduplicatedArray
+}
+
+// 鍌氦浣滀笟
+const remindWork = (item: any) => {
+  const content = classInfo?.name + '鐝�' + item.appUser.name + '鍚屽锛岃鍙婃椂鎻愪氦浣滀笟'
+  const data = {
+    description: '',
+    icon: '',
+    state: 'Normal',
+    topicIdOrRefCode: String(sessionStorage.messageId),
+    name: '鏈氦浣滀笟浜哄憳',
+    content,
+    type: 'Normal',
+    cmsTypeRefCode: '',
+    newDataListRequest: []
+  }
+  MG.ugc
+    .newTopicMessage(data)
+    .then((res: any) => {
+      if (res) {
+        ElMessage({
+          type: 'success',
+          message: '宸插偓浜�'
+        })
+      }
+    })
+    .catch((err: any) => {
+      console.log(err)
+    })
+}
+
+// 浣滀笟鎼滅储
+const searchData = () => {
+  const data = [
+    {
+      compareType: 'Contains',
+      keywords: searchKey.value,
+      field: 'Name'
+    }
+  ]
+  pages.page = 1
+  if (workState.value != 'WaitSubmit') {
+    getTaskDetail(undefined, searchKey.value ? data : [])
+  } else {
+    getUnSubmitList(undefined, searchKey.value ? data : [])
+  }
+}
+
+const goBack = () => {
+  router.go(-1)
+}
+</script>
+<style lang="less" scoped>
+.classManagePage-box {
+  background: #fff;
+
+  .classManagePage-nav {
+    width: 100%;
+    padding: 0 20px;
+    height: 40px;
+    border-bottom: 1px solid #e6e8ed;
+    position: sticky;
+    top: 0;
+    z-index: 999;
+    display: flex;
+    align-items: center;
+    background: #fff;
+  }
+  .classManagePage-content {
+    width: 100%;
+    position: relative;
+    .backBtn {
+      width: 100%;
+      height: 45px;
+      margin-bottom: 10px;
+      padding: 0 20px;
+      display: flex;
+      align-items: center;
+      position: sticky;
+      top: 40px;
+      z-index: 99;
+      background: #fff;
+      box-shadow: 0px 0px 20px 1px #eeeeee83;
+    }
+    .contentBox {
+      width: 100%;
+      padding: 0 20px;
+      box-sizing: border-box;
+      .content-title-box {
+        padding: 0 10px;
+        display: flex;
+        justify-content: flex-start;
+        align-items: center;
+        border-left: 4px solid #ff6d00;
+        span {
+          margin-right: 15px;
+        }
+      }
+      .content-user-box {
+        width: 100%;
+        padding: 10px 10px;
+        box-sizing: border-box;
+        display: flex;
+        overflow-x: auto;
+        .user-info-box {
+          width: auto;
+          display: flex;
+          align-items: center;
+          padding: 10px 15px;
+          .user-info-data-box {
+            flex: 1;
+            height: 100%;
+            display: flex;
+            flex-direction: column;
+            align-items: flex-start;
+            justify-content: space-between;
+            margin-left: 10px;
+            .user-name {
+              padding: 6px 0;
+            }
+            .user-num {
+              padding: 6px 0;
+              color: #666;
+              font-size: 12px;
+              white-space: nowrap;
+            }
+          }
+        }
+      }
+      .content-user-box::-webkit-scrollbar {
+        height: 3px;
+      }
+      .content-user-box::-webkit-scrollbar-thumb {
+        background-color: #ff6d00;
+        cursor: pointer;
+      }
+      .content-user-box::-webkit-scrollbar-track-piece {
+        background: #eee;
+      }
+      .content-tab-box {
+        .content-header {
+          display: flex;
+          align-items: center;
+          justify-content: space-between;
+          padding: 10px 0;
+          .searchBox {
+            width: 300px;
+            float: left;
+            padding: 10px 0;
+            .searchBtn {
+              background-color: var(--el-color-primary);
+              color: #fff;
+              border-top-left-radius: 0;
+              border-bottom-left-radius: 0;
+            }
+          }
+        }
+
+        .content-list-box {
+          .headerCellClassName {
+            .cell {
+              text-align: center;
+            }
+          }
+        }
+      }
+    }
+  }
+  ::v-deep(.customDialog) {
+    border-radius: 5px;
+    margin: 10px auto;
+    padding-bottom: 20px;
+    .pubContent {
+      position: relative;
+      height: 80vh;
+    }
+  }
+  .pageBox {
+    padding: 10px 0;
+    display: flex;
+    justify-content: flex-end;
+  }
+}
+</style>
diff --git a/src/views/classManage/jobManage.vue b/src/views/classManage/jobManage.vue
new file mode 100644
index 0000000..c2d8d25
--- /dev/null
+++ b/src/views/classManage/jobManage.vue
@@ -0,0 +1,1895 @@
+<template>
+  <div class="classManagePage-box">
+    <div class="classManagePage-nav">
+      <el-breadcrumb :separator-icon="ArrowRight">
+        <el-breadcrumb-item>鎴戠殑鐝骇</el-breadcrumb-item>
+        <el-breadcrumb-item>{{ classInfo?.name }}</el-breadcrumb-item>
+        <el-breadcrumb-item>浣滀笟绠$悊</el-breadcrumb-item>
+      </el-breadcrumb>
+    </div>
+    <div class="classManagePage-content">
+      <div class="cartClass">
+        <!-- <el-tabs v-model="jobState" @tab-click="tabCart">
+          <el-tab-pane label="鍏ㄩ儴" name="all"></el-tab-pane>
+          <el-tab-pane label="杩涜涓�" name="payment"></el-tab-pane>
+          <el-tab-pane label="宸茶繃鏈�" name="complete"></el-tab-pane>
+        </el-tabs> -->
+        <div class="titleOptions">
+          <span>浣滀笟绠$悊</span>
+        </div>
+      </div>
+      <div class="headerBox">
+        <div class="searchBox">
+          <el-input
+            v-model="searchKey"
+            clearable
+            @clear="searchTask"
+            @keydown.enter="searchTask"
+            placeholder="璇疯緭鍏ュ叧閿瓧"
+          >
+            <template #append>
+              <el-button type="primary" @click="searchTask" class="searchBtn" :icon="Search" />
+            </template>
+          </el-input>
+        </div>
+        <el-button
+          style="float: right"
+          v-if="userInfo?.role == 'Teacher'"
+          @click="openWork()"
+          type="primary"
+          round
+        >
+          <el-icon size="large" style="margin-right: 3px"><Document /></el-icon>
+          鏂板缓浣滀笟
+        </el-button>
+      </div>
+      <div class="listBox">
+        <el-table
+          :data="tableData"
+          :header-cell-style="{ background: '#eee' }"
+          max-height="600px"
+          style="width: 100%"
+          v-loading="pages.loading"
+        >
+          <el-table-column label="搴忓彿" prop="id" width="70"> </el-table-column>
+          <el-table-column label="鍚嶇О" prop="name"> </el-table-column>
+          <el-table-column label="浣滀笟寮�濮嬫棩鏈�" prop="beginDate"> </el-table-column>
+          <el-table-column label="浣滀笟缁撴潫鏃ユ湡" prop="endDate"> </el-table-column>
+          <el-table-column label="浣滀笟瀹屾垚鎯呭喌锛堜汉鏁帮級" prop="submitCount"></el-table-column>
+          <el-table-column label="鎿嶄綔" width="200" #default="scope">
+            <el-button
+              link
+              style="color: #409eff"
+              v-if="scope.row.state == 'Normal'"
+              @click="detail(scope.row)"
+              >璇︽儏</el-button
+            >
+            <!-- v-if="scope.row.state != 'Normal'" -->
+            <el-button
+              link
+              type="primary"
+              v-if="scope.row.state != 'Normal'"
+              @click="edit(scope.row)"
+              >缂栬緫</el-button
+            >
+            <el-button
+              link
+              style="color: #67c23a"
+              v-if="scope.row.state == 'Waiting'"
+              @click="releaseWork(scope.row)"
+              >鍙戝竷</el-button
+            >
+            <el-button link type="danger" @click="removeTaskItem(scope.row)">绉婚櫎</el-button>
+          </el-table-column>
+        </el-table>
+        <div class="pageBox">
+          <el-pagination
+            v-model:current-page="pages.currentPage"
+            :page-size="pages.pageSize"
+            :size="'small'"
+            :disabled="pages.count <= 1"
+            layout="total, prev, pager, next"
+            :total="pages.count"
+            @size-change="handleSizeChange"
+            @current-change="handleCurrentChange"
+          />
+        </div>
+      </div>
+      <!-- 鏂板缓浣滀笟 -->
+      <el-dialog
+        class="customDialog"
+        destroy-on-close
+        v-model="visible"
+        :title="visibleEdit ? '鏇存柊浣滀笟' : '鏂板缓浣滀笟'"
+        width="1650"
+        :before-close="close"
+        align-center
+      >
+        <div class="stepBox">
+          <el-steps
+            style="max-width: 600px; margin: auto"
+            :active="stepActive"
+            finish-status="success"
+            align-center
+          >
+            <el-step :title="visibleEdit ? '鏇存柊浣滀笟' : '鏂板缓浣滀笟'" />
+            <el-step title="娣诲姞棰樼洰" />
+            <el-step title="璁剧疆鍒嗘暟" />
+            <el-step title="瀹屾垚" />
+          </el-steps>
+        </div>
+        <div class="newTaskBox" v-if="stepActive == 0">
+          <el-row class="row-center">
+            <el-col :span="2" class="labelItem">
+              <div class="grid-content ep-bg-purple" />
+              鍚嶇О
+            </el-col>
+            <el-col :span="20">
+              <div class="grid-content ep-bg-purple-light" />
+              <el-input
+                v-model="taskItem.homeworkName"
+                placeholder="璇峰~鍐欏悕绉�"
+                size="large"
+                clearable
+                style="width: 600px"
+              />
+            </el-col>
+          </el-row>
+          <el-row class="row-center">
+            <el-col :span="2" class="labelItem">
+              <div class="grid-content ep-bg-purple" />
+              寮�濮嬫棩鏈�
+            </el-col>
+            <el-col :span="20">
+              <div class="grid-content ep-bg-purple-light" />
+              <!-- <el-input v-model="taskItem.beginDate" placeholder="璇烽�夋嫨寮�濮嬫棩鏈�" size="large" clearable /> -->
+              <el-date-picker
+                v-model="taskItem.homeworkStartingDate"
+                type="date"
+                placeholder="璇烽�夋嫨寮�濮嬫棩鏈�"
+                size="large"
+                style="width: 600px"
+              />
+            </el-col>
+          </el-row>
+          <el-row class="row-center">
+            <el-col :span="2" class="labelItem">
+              <div class="grid-content ep-bg-purple" />
+              缁撴潫鏃ユ湡
+            </el-col>
+            <el-col :span="20">
+              <div class="grid-content ep-bg-purple-light" />
+              <el-date-picker
+                v-model="taskItem.homeworkSubmissionDate"
+                type="date"
+                placeholder="璇烽�夋嫨缁撴潫鏃ユ湡"
+                size="large"
+                style="width: 600px"
+              />
+            </el-col>
+          </el-row>
+          <el-row>
+            <el-col :span="2" class="labelItem">
+              <div class="grid-content ep-bg-purple" />
+              鎻忚堪
+            </el-col>
+            <el-col :span="20">
+              <div class="grid-content ep-bg-purple-light" />
+              <el-input
+                v-model="taskItem.explain"
+                placeholder="璇峰~鍐欒鏄�"
+                type="textarea"
+                :rows="12"
+                size="large"
+                clearable
+                style="width: 600px"
+              />
+            </el-col>
+          </el-row>
+        </div>
+        <div class="workBox" v-if="stepActive == 1">
+          <div class="workLeft">
+            <el-tabs
+              v-model="activeTabs"
+              style="margin: auto"
+              class="demo-tabs"
+              @tab-change="handleClick"
+            >
+              <el-tab-pane label="绯荤粺" name="1"></el-tab-pane>
+              <!-- <el-tab-pane label="鏁欐潗" name="2"></el-tab-pane> -->
+            </el-tabs>
+            <div class="workList" v-if="workLeftList.length > 0 && !leftLoading">
+              <!-- <div class="searchBox" v-if="activeTabs == '1'">
+                <el-input v-model="sysWorkKey" clearable @clear="searchWork" placeholder="璇疯緭鍏ュ叧閿瓧">
+                  <template #append>
+                    <el-button type="primary" class="searchBtn" @click="searchWork" :icon="Search" />
+                  </template>
+                </el-input>
+              </div> -->
+              <div class="work-list-item" v-for="(item, index) in workLeftList" :key="index">
+                <el-tooltip :content="item.name" placement="bottom-end" effect="light">
+                  <p
+                    :class="
+                      index == sysIndex ? 'work-list-item-text leftBg' : 'work-list-item-text'
+                    "
+                    @click="clickRightItem(item, index)"
+                  >
+                    {{ item.name }}
+                  </p>
+                </el-tooltip>
+              </div>
+            </div>
+            <div
+              class="workList"
+              v-if="workLeftList.length == 0 && !leftLoading"
+              style="display: flex; align-items: center; justify-content: center"
+            >
+              <el-empty image-size="100px" />
+            </div>
+            <div
+              class="workList"
+              v-if="leftLoading"
+              style="
+                display: flex;
+                align-items: center;
+                justify-content: center;
+                background-color: none;
+              "
+              v-loading="leftLoading"
+            ></div>
+          </div>
+          <div class="workRight">
+            <div class="right-list-title">
+              <span>棰樼洰鍒楄〃</span>
+              <!-- <el-button type="primary" round size="small" icon="Plus">鏂板缓</el-button> -->
+            </div>
+            <div class="right-list-components">
+              <questionDom
+                v-if="workRightList.length > 0 && !rightLoading"
+                :questionList="workRightList"
+                @selectQuestion="selectQuestion"
+                :noCheckbox="true"
+              />
+              <div v-if="rightLoading" v-loading="rightLoading"></div>
+              <el-empty v-if="workRightList.length == 0 && !rightLoading" />
+            </div>
+          </div>
+        </div>
+        <div class="workBox" v-if="stepActive == 2">
+          <div class="workLeft" style="width: 230px">
+            <div class="scoreTitle">
+              <span>棰樼洰绫诲瀷</span>
+            </div>
+            <div class="workList" v-if="scoreLeftList.length > 0">
+              <div class="work-list-item" v-for="(item, index) in scoreLeftList" :key="index">
+                <p
+                  :class="
+                    index == scoreIndex ? 'work-list-item-text leftBg' : 'work-list-item-text'
+                  "
+                  @click="scoreItem(item, index)"
+                >
+                  {{ item.name }} ({{ item.data.length }})
+                </p>
+              </div>
+            </div>
+            <div
+              class="workList"
+              v-if="scoreLeftList.length == 0"
+              style="display: flex; align-items: center; justify-content: center"
+            >
+              <el-empty image-size="100px" />
+            </div>
+          </div>
+          <div class="workRight">
+            <div class="right-list-title">
+              <span>棰樼洰鍒楄〃</span>
+            </div>
+            <div class="right-score-components">
+              <div class="scoreBtn">
+                <!-- <el-button size="small">涓婄Щ</el-button>
+                <el-button size="small">涓嬬Щ</el-button> -->
+                <div class="setScore" v-if="scoreLeftList.length > 0">
+                  <span>鎵归噺璁剧疆鍒嗘暟锛�</span>
+                  <el-input-number
+                    v-model="scoreValue"
+                    :min="0"
+                    :max="100"
+                    controls-position="right"
+                    @change="changeScore"
+                  />
+                  <el-button v-if="scoreValue > 0" style="margin-left: 10px" @click="setScoreArr"
+                    >纭</el-button
+                  >
+                </div>
+              </div>
+              <el-table
+                :data="scoreDataList"
+                max-height="500px"
+                :header-cell-style="{ background: '#eee' }"
+                style="width: 100%"
+                v-loading="selectedLoading"
+              >
+                <el-table-column prop="index" label="搴忓彿" width="100" />
+                <el-table-column prop="name" label="棰樼洰">
+                  <template #default="scope">
+                    <span>{{ scope.row.questionStem.stemTxt }}</span>
+                  </template>
+                </el-table-column>
+                <el-table-column label="鍒嗘暟" width="120">
+                  <template #default="scope">
+                    <span style="color: #ff6c00">{{ scope.row.score }}</span>
+                  </template>
+                </el-table-column>
+                <el-table-column label="璁剧疆" width="260">
+                  <template #default="scope">
+                    <el-button
+                      link
+                      v-if="!scope.row.isInput"
+                      type="primary"
+                      size="small"
+                      @click="openSetScore(scope.row)"
+                      >璁剧疆鍒嗘暟</el-button
+                    >
+                    <el-input-number
+                      v-if="scope.row.isInput"
+                      v-model="scoreItemValue"
+                      :min="0"
+                      :max="100"
+                      :controls="false"
+                      size="small"
+                      @blur="setScore(scope.row)"
+                    />
+                  </template>
+                </el-table-column>
+              </el-table>
+            </div>
+          </div>
+        </div>
+        <div class="workBox" style="height: 720px" v-if="stepActive == 3">
+          <div class="finishBg">
+            <img src="@/assets//images/class/finish.png" alt="" />
+            <span>浣滀笟宸插垱寤哄畬鎴�</span>
+          </div>
+        </div>
+        <template #footer v-if="stepActive == 0">
+          <div style="width: 100%; display: flex; justify-content: flex-end">
+            <el-button @click="nextStep" v-if="visibleEdit"> 璺宠繃 </el-button>
+            <el-button type="primary" :loading="newLoading" @click="newTask"> 纭 </el-button>
+          </div>
+        </template>
+        <template #footer v-if="stepActive != 3 && stepActive != 0">
+          <div class="leftFooter" :style="{ width: stepActive == 2 ? '230px' : '' }"></div>
+          <div class="dialog-footer">
+            <div class="check-list-box" v-if="stepActive == 1">
+              <el-checkbox v-model="checkAll" @change="handleCheckAllChange"> 鍏ㄩ�� </el-checkbox>
+            </div>
+            <div class="btnGroup" v-if="stepActive == 1">
+              <el-button plain :disabled="checkData.length == 0" @click="addCmsitem">
+                鍔犲叆浣滀笟
+              </el-button>
+              <el-button plain @click="selectedData"> 鏌ョ湅宸查�� </el-button>
+              <el-button type="primary" @click="nextStep"> 涓嬩竴姝� </el-button>
+            </div>
+            <div class="btnGroup" v-if="stepActive == 2">
+              <el-button type="primary" plain @click="preStep"> 涓婁竴姝� </el-button>
+              <el-button plain @click="lookWork"> 棰勮浣滀笟 </el-button>
+              <el-button type="primary" @click="nextStep"> 涓嬩竴姝� </el-button>
+            </div>
+          </div>
+        </template>
+        <template #footer v-if="stepActive == 3">
+          <div style="width: 100%; display: flex; justify-content: flex-end">
+            <el-button type="primary" @click="close"> 瀹� 鎴� </el-button>
+          </div>
+        </template>
+      </el-dialog>
+      <!-- 鏌ョ湅宸查�� -->
+      <el-dialog
+        class="customDialog"
+        align-center
+        v-model="visibleView"
+        destroy-on-close
+        width="900"
+      >
+        <template #header>
+          <div class="viewTitle">宸查�夐鐩�</div>
+        </template>
+        <div class="viewContent">
+          <div class="workBox">
+            <div class="workLeft" style="width: 200px">
+              <div class="workList" style="height: 100%" v-if="selectedTypeList.length > 0">
+                <div class="work-list-item" v-for="(item, index) in selectedTypeList" :key="index">
+                  <p
+                    :class="
+                      index == selectedIndex ? 'work-list-item-text leftBg' : 'work-list-item-text'
+                    "
+                    @click="selectedItems(item, index)"
+                  >
+                    {{ item.name }}<span style="margin-left: 5px">({{ item.data.length }})</span>
+                  </p>
+                </div>
+              </div>
+              <div
+                class="workList"
+                v-if="selectedTypeList.length == 0"
+                style="display: flex; align-items: center; justify-content: center"
+              >
+                <el-empty image-size="100px" />
+              </div>
+            </div>
+            <div class="workRight">
+              <div class="right-list-components">
+                <questionDom
+                  v-if="selectedDataList.length > 0 && !selectedLoading"
+                  :questionList="selectedDataList"
+                  @selectQuestion="selectQuestion"
+                  @delete-item="deleteCmsItem"
+                  :noCheckbox="false"
+                  :isDelete="true"
+                />
+                <div v-if="selectedLoading" v-loading="selectedLoading"></div>
+                <el-empty v-if="selectedDataList.length == 0 && !selectedLoading" />
+              </div>
+            </div>
+          </div>
+        </div>
+        <template #footer>
+          <div class="selectedFooter">
+            <el-button type="primary" @click="visibleView = false"> 纭 </el-button>
+          </div>
+        </template>
+      </el-dialog>
+      <!-- 棰勮浣滀笟 -->
+      <el-dialog
+        class="customDialog"
+        align-center
+        v-model="visibleLook"
+        destroy-on-close
+        width="900"
+      >
+        <template #header>
+          <div class="viewTitle">棰勮浣滀笟</div>
+        </template>
+        <div class="viewContent">
+          <div class="workBox">
+            <div class="workLeft" style="width: 200px">
+              <div class="workList" style="height: 100%" v-if="lookLeftList.length > 0">
+                <div class="work-list-item" v-for="(item, index) in lookLeftList" :key="index">
+                  <p
+                    :class="
+                      index == lookIndex ? 'work-list-item-text leftBg' : 'work-list-item-text'
+                    "
+                    @click="lookItems(item, index)"
+                  >
+                    {{ item.name }}<span style="margin-left: 5px">({{ item.data.length }})</span>
+                  </p>
+                </div>
+              </div>
+              <div
+                class="workList"
+                v-if="lookLeftList.length == 0"
+                style="display: flex; align-items: center; justify-content: center"
+              >
+                <el-empty image-size="100px" />
+              </div>
+            </div>
+            <div class="workRight">
+              <div class="right-list-components">
+                <questionDom
+                  v-if="lookDataList.length > 0 && !selectedLoading"
+                  :questionList="lookDataList"
+                  @selectQuestion="selectQuestion"
+                  @delete-item="deleteCmsItem"
+                  :is-preview="visibleLook"
+                />
+                <div v-if="selectedLoading" v-loading="selectedLoading"></div>
+                <el-empty v-if="lookDataList.length == 0 && !selectedLoading" />
+              </div>
+            </div>
+          </div>
+        </div>
+        <template #footer>
+          <div class="selectedFooter">
+            <el-button type="primary" @click="visibleLook = false"> 纭 </el-button>
+          </div>
+        </template>
+      </el-dialog>
+      <!-- 鍙戝竷浣滀笟 -->
+      <el-dialog
+        class="customDialog"
+        title="鍙戝竷浣滀笟"
+        v-model="visiblePub"
+        destroy-on-close
+        width="500"
+        align-center
+        :before-close="close"
+      >
+        <div class="pubContent">
+          <span>鍙戝竷鏃ユ湡锛�</span>
+          <el-date-picker
+            v-model="pubValue"
+            type="daterange"
+            range-separator="--"
+            start-placeholder="寮�濮嬫棩鏈�"
+            end-placeholder="缁撴潫鏃ユ湡"
+            @change="selectPubDate"
+          />
+        </div>
+        <template #footer>
+          <div class="selectedFooter" style="padding: 0">
+            <el-button type="primary" @click="submitWork"> 纭 </el-button>
+          </div>
+        </template>
+      </el-dialog>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { reactive, ref, onMounted, inject, watch } from 'vue'
+import { Search, ArrowRight } from '@element-plus/icons-vue'
+import { useRoute, useRouter } from 'vue-router'
+import questionDom from './components/questionDom.vue'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import moment from 'moment'
+
+const route: any = useRoute()
+const router = useRouter()
+const MG: any = inject('MG')
+const config: any = inject('config')
+const tool: any = inject('toolClass')
+const classInfo = JSON.parse(route.query.classInfo)
+const jobState = ref('all')
+const searchKey = ref('')
+const dataList = ref([])
+const userInfo = ref()
+const defaultCmsPath = ref('')
+
+// 鑾峰彇task鍙傛暟
+const filterData = ref([
+  {
+    value: config.taskType.homeWork,
+    field: 'Type',
+    subFilters: []
+  }
+])
+// task
+const taskData = reactive({
+  id: '',
+  description: '',
+  rootCmsItemId: '',
+  name: '',
+  type: '',
+  state: '',
+  groupId: '',
+  beginDate: '',
+  endDate: ''
+})
+// question Key
+const questionKey = [
+  'Name',
+  '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'
+]
+// dialognew
+const visible = ref(false)
+const stepActive = ref(0)
+const activeTabs = ref('1')
+// 鏂板缓浣滀笟
+const newLoading = ref(false)
+const taskItem = reactive({
+  homeworkName: '',
+  homeworkStartingDate: '',
+  homeworkSubmissionDate: '',
+  explain: ''
+})
+let pages = reactive({
+  currentPage: 1,
+  page: 1,
+  pageSize: 15,
+  count: 0,
+  loading: false
+})
+// dialogedit
+const visibleEdit = ref(false)
+// dialogView
+const visibleView = ref(false)
+// dialogLook
+const visibleLook = ref(false)
+// left
+const workLeftList: any = ref([])
+const leftLoading = ref(false)
+const sysIndex = ref(0)
+// 鍒嗘暟
+const scoreValue = ref(0) // 鎵归噺
+const scoreItemValue = ref('') // 鍗曚竴
+const scoreLeftList: any = ref([])
+const scoreDataList: any = ref([])
+const scoreIndex = ref(0)
+const scoreData: any = ref([]) // 鑷瓨鍌ㄩ鐩垎鏁�
+const isSet = ref(false)
+// right
+const workRightList: any = ref([])
+const rightLoading = ref(false)
+const checkAll = ref(false)
+const selectCache: any = ref([])
+const checkData: any = ref([])
+// 浣滀笟鍒楄〃
+const tableData: any = ref([])
+// 宸查�変綔涓氳祫婧�
+const selectedTypeList: any = ref([])
+const selectedDataList: any = ref([])
+const selectedLoading = ref(false)
+const selectedIndex = ref(0)
+//棰勮浣滀笟
+const lookLeftList: any = ref([])
+const lookDataList: any = ref([])
+const lookIndex = ref(0)
+// 鍙戝竷浣滀笟
+const visiblePub = ref(false)
+const pubValue = ref(null)
+
+onMounted(() => {
+  const userCache: any = localStorage.getItem('jesk-userInfo')
+  if (userCache) {
+    userInfo.value = JSON.parse(userCache)
+  }
+  defaultCmsPath.value = classInfo.bookRefCode ? 'jsek_digitalTextbooks' : 'defaultGoodsStore3'
+  getTaskList()
+})
+
+// 鍙戝竷
+const selectPubDate = (item: any) => {
+  if (item.length > 0) {
+    taskItem.homeworkStartingDate = moment(item[0]).format('YYYY-MM-DDTHH:mm:ss')
+    taskItem.homeworkSubmissionDate = moment(item[1]).format('YYYY-MM-DDTHH:mm:ss')
+  }
+}
+
+//  鍒嗛〉
+const handleSizeChange = (val: number) => {
+  pages.pageSize = val
+  getTaskList()
+}
+
+const handleCurrentChange = (val: number) => {
+  pages.page = val
+  pages.currentPage = val
+  getTaskList()
+}
+
+// 鏂板缓浠诲姟{Waiting:鏈紑濮�,Normal:杩涜涓�,Ended:宸茬粨鏉焳
+const newTask = () => {
+  newLoading.value = true
+  if (!taskItem.homeworkName) {
+    ElMessage({
+      type: 'warning',
+      message: '璇峰~鍐欎綔涓氬悕绉� '
+    })
+    newLoading.value = false
+    return false
+  }
+  if (!taskItem.homeworkStartingDate) {
+    ElMessage({
+      type: 'warning',
+      message: '璇峰~鍐欎綔涓氬紑濮嬫椂闂� '
+    })
+    newLoading.value = false
+    return false
+  }
+  if (!taskItem.homeworkSubmissionDate) {
+    ElMessage({
+      type: 'warning',
+      message: '璇峰~鍐欎綔涓氱粨鏉熸椂闂�'
+    })
+    newLoading.value = false
+    return false
+  }
+  if (!visibleEdit.value) {
+    const data = {
+      name: taskItem.homeworkName,
+      description: taskItem.explain,
+      icon: '',
+      type: config.taskType.homeWork,
+      state: 'Waiting',
+      groupId: classInfo?.id,
+      order: 0,
+      beginDate: taskItem.homeworkStartingDate,
+      endDate: taskItem.homeworkSubmissionDate,
+      duration: 0,
+      config: JSON.stringify({ scoreData: [] })
+    }
+    MG.edu
+      .newTask(data)
+      .then((res: any) => {
+        taskData.id = res
+      })
+      .catch((e: any) => {
+        newLoading.value = false
+        console.log(e)
+      })
+  } else {
+    updateTask()
+  }
+  setTimeout(() => {
+    newLoading.value = false
+    stepActive.value++
+    getTaskList()
+  }, 600)
+}
+
+// 鏇存柊浠诲姟
+const updateTask = () => {
+  const data = {
+    id: taskData.id,
+    name: taskItem.homeworkName,
+    description: taskItem.explain,
+    icon: '',
+    type: taskData.type,
+    state: taskData.state,
+    order: 0,
+    beginDate: moment(taskItem.homeworkStartingDate).format('YYYY-MM-DDTHH:mm:ss'),
+    endDate: moment(taskItem.homeworkSubmissionDate).format('YYYY-MM-DDTHH:mm:ss'),
+    duration: 0,
+    config: JSON.stringify({ scoreData: scoreData.value })
+  }
+  MG.edu
+    .updateTask(data)
+    .then((res: any) => {
+      if (res) {
+        if (stepActive.value == 2) {
+          getTaskCmsList()
+        }
+        getTaskList()
+      }
+    })
+    .catch((err: any) => {
+      console.log(err, 'updateTask')
+    })
+}
+
+// 鑾峰彇浠诲姟鍒楄〃
+const getTaskList = (filter?: any[], search?: any[]) => {
+  const filterList = filter ?? filterData.value
+  const searchList = search ?? []
+  pages.loading = true
+  const data = {
+    start: (pages.page - 1) * pages.pageSize,
+    size: pages.pageSize,
+    sort: {
+      type: 'Desc',
+      field: 'CreateDate'
+    },
+    filterList,
+    searchList,
+    groupId: classInfo?.id
+  }
+  MG.edu
+    .getTaskList(data)
+    .then((res: any) => {
+      pages.count = res.totalSize
+      if (res.datas.length > 0) {
+        tableData.value = res.datas?.map((item: any) => {
+          //  const currTime = Number(sessionStorage.currentDate);
+          //  const taskTime = moment(item.endDate).valueOf()
+          //   if(taskTime < currTime){
+          //     console.log(taskTime,item.name,'7878')
+          //   }
+          return {
+            ...item,
+            beginDate: moment(item.beginDate).format('YYYY-MM-DD'),
+            endDate: moment(item.endDate).format('YYYY-MM-DD')
+          }
+        })
+        if (taskData.id) {
+          scoreData.value = []
+          const obj = res.datas.find((item: any) => item.id == taskData.id)
+          taskData.id = obj.id
+          taskData.rootCmsItemId = obj.rootCmsItemId
+          if (obj.config) {
+            scoreData.value = JSON.parse(obj.config).scoreData
+          }
+          taskData.name = obj.name
+          taskData.groupId = classInfo?.id
+          taskData.state = obj.state
+          taskData.type = obj.type
+          taskData.beginDate = moment(obj.beginDate).format('YYYY-MM-DDTHH:mm:ss')
+          taskData.endDate = moment(obj.endDate).format('YYYY-MM-DDTHH:mm:ss')
+        }
+      } else {
+        tableData.value = []
+      }
+      pages.loading = false
+    })
+    .catch((e: any) => {
+      pages.loading = false
+      console.log(e)
+    })
+}
+
+// 鎼滅储浠诲姟
+const searchTask = () => {
+  const data = [
+    {
+      compareType: 'Contains',
+      keywords: searchKey.value,
+      field: 'Name'
+    }
+  ]
+  pages.page = 1
+  pages.currentPage = 1
+  getTaskList(undefined, data)
+}
+
+// 鍒犻櫎璧勬簮
+const removeTaskItem = (item: any) => {
+  const data = {
+    ids: [item.id]
+  }
+  MG.edu
+    .delTask(data)
+    .then((res: any) => {
+      if (res) {
+        ElMessage({
+          message: '鍒犻櫎鎴愬姛',
+          type: 'success'
+        })
+        getTaskList()
+      }
+    })
+    .catch((e: any) => {
+      ElMessage({
+        message: '鍒犻櫎澶辫触',
+        type: 'error'
+      })
+    })
+}
+
+// 涓轰换鍔℃坊鍔犺祫婧�
+const addCmsitem = () => {
+  const data = {
+    taskId: taskData.id,
+    requests: checkData.value?.map((item: any) => {
+      return {
+        path: String(taskData.rootCmsItemId),
+        cmsItemId: item.id
+      }
+    })
+  }
+  MG.edu
+    .addTaskCmsItemList(data)
+    .then((res: any) => {
+      if (res) {
+        ElMessage({
+          message: '宸插姞鍏�',
+          type: 'success'
+        })
+        selectCache.value = []
+        checkData.value = []
+        checkAll.value = false
+        workRightList.value?.forEach((citem: any) => {
+          citem.data.forEach((titem: any) => (titem.isCheck = false))
+        })
+      }
+    })
+    .catch((e: any) => {
+      ElMessage({
+        message: '鍔犲叆澶辫触',
+        type: 'error'
+      })
+    })
+}
+
+// 鑾峰彇浠诲姟涓嬬殑璧勬簮鍒楄〃
+const getTaskCmsList = () => {
+  selectedLoading.value = true
+  const data = {
+    start: 0,
+    size: 999,
+    searchList: [],
+    taskId: taskData?.id, // taskData?.id
+    path: String(taskData?.rootCmsItemId), //taskData?.rootCmsItemId
+    type: '*',
+    keys: questionKey
+  }
+  MG.edu
+    .getTaskCmsItem(data)
+    .then((res: any) => {
+      selectedLoading.value = false
+      for (let i = 0; i < res.datas.length; i++) {
+        let item = res.datas[i]
+        item.index = i + 1
+        const scoreItem = scoreData.value.find((i: any) => i.id == item.id)
+        item.score = scoreItem?.score ?? 0
+        item.isInput = false
+        // 澶勭悊瀛楁
+        if (questionKey != null) {
+          for (let fieldKey of questionKey) {
+            if (item.datas[fieldKey]) {
+              const values = JSON.parse(item.datas[fieldKey])
+              if (values.length > 0) {
+                // 鐢ㄥ瓧娈靛悕澶勭悊杩斿洖鐨勫瓧娈靛��
+                if (values[0].Value) {
+                  item[fieldKey] = values[0].Value
+                } else if (values[0].Data) {
+                  item[fieldKey] = values[0].Data.Value
+                } else if (!values[0].Value && values[0].FileList?.length > 0) {
+                  item[fieldKey] = values[0].FileList
+                } else {
+                  item[fieldKey] = '-'
+                }
+              }
+            }
+          }
+        }
+      }
+      if (stepActive.value == 2) {
+        scoreDataList.value = []
+        scoreLeftList.value = changeQuestionData(res.datas)
+        if (scoreLeftList.value.length > 0) {
+          scoreDataList.value = scoreLeftList.value[scoreIndex.value].data
+        }
+        scoreValue.value = 0
+      } else {
+        selectedDataList.value = []
+        selectedTypeList.value = changeQuestionData(res.datas)
+        if (selectedTypeList.value.length > 0) {
+          selectedDataList.value = [selectedTypeList.value[0]]
+        }
+      }
+    })
+    .catch((e: any) => {
+      ElMessage({
+        message: '鍒楄〃鑾峰彇澶辫触',
+        type: 'error'
+      })
+      console.log(e)
+    })
+}
+
+// 鍒犻櫎宸查�夌殑棰樼洰
+const deleteCmsItem = (item: any) => {
+  ElMessageBox.confirm('鏄惁纭鍒犻櫎?', '鎻愮ず', {
+    confirmButtonText: '鏄�',
+    cancelButtonText: '鍚�',
+    type: 'warning'
+  }).then(() => {
+    const data = {
+      taskId: taskData.id,
+      requests: [
+        {
+          cmsItemId: item.id,
+          path: String(taskData.rootCmsItemId)
+        }
+      ]
+    }
+    MG.edu
+      .removeTaskCmsItemList(data)
+      .then((res: any) => {
+        if (res) {
+          ElMessage({
+            type: 'success',
+            message: '宸插垹闄�'
+          })
+          selectedIndex.value = 0
+          getTaskCmsList()
+        }
+      })
+      .catch((err: any) => {
+        ElMessage({
+          type: 'error',
+          message: '鍒犻櫎澶辫触锛岃绋嶅悗鍐嶈瘯'
+        })
+      })
+  })
+}
+
+// 棰樼洰鍒嗘暟鍒楄〃鍒囨崲
+const scoreItem = (item: any, index: number) => {
+  scoreIndex.value = index
+  scoreDataList.value = item.data
+}
+
+// 鎵撳紑璁剧疆鏂囨湰妗�
+const openSetScore = (item: any) => {
+  scoreItemValue.value = ''
+  item.isInput = true
+}
+
+// 棰勮浣滀笟
+const lookWork = () => {
+  visibleLook.value = true
+  lookIndex.value = 0
+  lookLeftList.value = [...scoreLeftList.value]
+  lookDataList.value = [lookLeftList.value[0]]
+}
+
+// 鎵归噺璁剧疆鍒嗘暟
+const changeScore = () => {
+  isSet.value = true
+}
+
+// 鎵归噺璁剧疆鍒嗘暟纭
+const setScoreArr = () => {
+  let data = [...scoreData.value]
+  let idsData = scoreDataList.value.map((item: any) => {
+    return { id: item.id, score: scoreValue.value }
+  })
+  if (data.length == 0) {
+    data = [...idsData]
+  } else {
+    data = updateArr(data, idsData)
+  }
+  scoreData.value = data
+  updateTask()
+  isSet.value = false
+}
+
+// 棰樼洰鍒嗘暟璁剧疆
+const setScore = (item: any) => {
+  item.score = Number(scoreItemValue.value)
+  const data = [...scoreData.value.filter((citem: any) => citem.id != item.id)]
+  data.push({ id: item.id, score: item.score })
+  scoreData.value = [...data]
+  item.isInput = false
+  updateTask()
+}
+
+//  lookItems
+const lookItems = (item: any, index: number) => {
+  lookIndex.value = index
+  lookDataList.value = [item]
+}
+
+// 宸查�夐鐩垏鎹�
+const selectedItems = (item: any, index: number) => {
+  selectedIndex.value = index
+  selectedDataList.value = [item]
+}
+
+// 琛ㄦ牸tab浜嬩欢{Waiting:鏈紑濮�,Normal:杩涜涓�,Ended:宸茬粨鏉焳
+const tabCart = (event: Event | any) => {
+  let queryFilter: any = []
+  jobState.value = event.props.name
+  pages.page = 1
+  dataList.value = []
+  if (jobState.value == 'all') {
+    queryFilter = [...filterData.value]
+  }
+  if (jobState.value == 'payment') {
+    queryFilter = [...filterData.value, { field: 'State', value: 'Normal', subFilters: [] }]
+  }
+  if (jobState.value == 'complete') {
+    queryFilter = [...filterData.value, { field: 'State', value: 'Ended', subFilters: [] }]
+  }
+  getTaskList(queryFilter)
+}
+
+// 棰樼洰tab浜嬩欢
+const handleClick = (val: any) => {
+  activeTabs.value = val
+  workLeftList.value = []
+  if (val == '1') {
+    getBookQuestionList()
+  } else {
+    workLeftList.value = []
+  }
+}
+
+// 涓嬩竴姝�
+const nextStep = () => {
+  if (stepActive.value++ > 2) stepActive.value = 0
+  if (stepActive.value == 2) getTaskCmsList()
+}
+
+// 涓婁竴姝�
+const preStep = () => {
+  if (stepActive.value-- == 0) stepActive.value = 0
+}
+
+// 閫夋嫨棰樼洰
+const selectQuestion = (item: any) => {
+  selectCache.value.push(item)
+  const list = selectCache.value.filter((citem: any) => citem.isCheck == true)
+  let dataT: any = []
+  workRightList.value?.forEach((citem: any) => {
+    const itemArr = citem.data
+    dataT.push(...itemArr)
+  })
+  checkData.value = [...new Set(list)]
+  if (dataT?.length > 0) {
+    checkAll.value = dataT.length == checkData.value.length
+  }
+}
+
+// 鍏ㄩ��
+const handleCheckAllChange = (val: boolean) => {
+  const data = workRightList.value
+  data.forEach((ele: any) => {
+    ele.data.forEach((item: any) => {
+      item.isCheck = val
+    })
+  })
+  let list: any = []
+  data.forEach((citem: any) => {
+    const itemArr = citem.data.filter((titem: any) => titem.isCheck == true)
+    list.push(...itemArr)
+  })
+  checkData.value = list
+}
+
+// 鏌ョ湅宸查��
+const selectedData = () => {
+  visibleView.value = true
+  getTaskCmsList()
+}
+
+// 鏂板缓浣滀笟鎵撳紑
+const openWork = () => {
+  visible.value = true
+  checkAll.value = false
+  activeTabs.value = '1'
+  stepActive.value = 0
+  selectCache.value = []
+  workRightList.value = []
+  checkData.value = []
+  getBookQuestionList()
+}
+
+// 鍏抽棴鏂板缓浣滀笟
+const close = () => {
+  taskItem.homeworkName = ''
+  taskItem.homeworkStartingDate = ''
+  taskItem.homeworkSubmissionDate = ''
+  taskItem.explain = ''
+  visible.value = false
+  visibleEdit.value = false
+  visiblePub.value = false
+  getTaskList()
+}
+
+// 鍙戝竷浣滀笟
+const releaseWork = (item: any) => {
+  visiblePub.value = true
+  taskData.id = item.id
+  taskData.rootCmsItemId = item.rootCmsItemId
+  if (item.config) {
+    scoreData.value = JSON.parse(item.config).scoreData
+  }
+  taskData.groupId = classInfo?.id
+  taskData.state = 'Normal'
+  taskData.type = item.type
+  taskItem.homeworkName = item.name
+  taskItem.explain = item.description
+}
+
+// 璇风‘璁ゅ彂甯�
+const submitWork = () => {
+  visiblePub.value = false
+  updateTask()
+  submitNewMessage()
+}
+
+// 鍙戝竷浣滀笟閫氱煡
+const submitNewMessage = () => {
+  const date = moment(taskItem.homeworkStartingDate).format('YYYY-MM-DD')
+  const content = date + '锛屽彂甯冧綔涓氾紝' + taskItem.homeworkName
+  const data = {
+    description: '',
+    icon: '',
+    state: 'Normal',
+    topicIdOrRefCode: String(sessionStorage.messageId),
+    name: '鑰佸笀鍙戝竷浣滀笟',
+    content,
+    type: 'Normal',
+    cmsTypeRefCode: '',
+    newDataListRequest: []
+  }
+  MG.ugc
+    .newTopicMessage(data)
+    .then((res: any) => {
+      if (res) {
+        ElMessage({
+          type: 'success',
+          message: '宸插彂甯�'
+        })
+      }
+    })
+    .catch((err: any) => {
+      console.log(err)
+    })
+}
+
+// 缂栬緫
+const edit = (item: any) => {
+  scoreData.value = []
+  visibleEdit.value = true
+  taskData.id = item.id
+  taskData.rootCmsItemId = item.rootCmsItemId
+  if (item.config) {
+    scoreData.value = JSON.parse(item.config).scoreData
+  }
+  taskData.groupId = classInfo?.id
+  taskData.state = item.state
+  taskData.type = item.type
+  taskItem.homeworkName = item.name
+  taskItem.homeworkStartingDate = item.beginDate
+  taskItem.homeworkSubmissionDate = item.endDate
+  taskItem.explain = item.description
+  openWork()
+}
+
+// 璇︽儏
+const detail = (item: any) => {
+  const obj = classInfo
+  obj.taskCmsId = item.rootCmsItemId
+  obj.taskWorkId = item.id
+  router.push({
+    path: '/jobDetail',
+    query: {
+      classInfo: JSON.stringify(obj)
+    }
+  })
+}
+
+// 浣滀笟閫変腑left
+const clickRightItem = (item: any, index: number) => {
+  workRightList.value = []
+  checkAll.value = false
+  sysIndex.value = index
+  getBookQuestionContentList(item.productLinkPath, item)
+}
+
+// 鎼滅储棰樺共
+const searchWork = () => {
+  workLeftList.value = []
+  getBookQuestionList()
+}
+
+// 鑾峰彇绯荤粺棰樺共鍒楄〃
+const getBookQuestionList = () => {
+  leftLoading.value = true
+  let query = {
+    path: defaultCmsPath.value,
+    queryType: '*',
+    productId: String(classInfo?.bookId),
+    storeInfo: defaultCmsPath.value,
+    cmsPath: classInfo?.rootCmsItemId
+  }
+  MG.store
+    .getProductDetail(query)
+    .then(async (res: any) => {
+      const { cmsDatas } = res.datas
+      leftLoading.value = false
+      const listQusetion = cmsDatas[0]?.datas
+      const obj = listQusetion?.find((item: any) => item.type == 'questionBankFolder')
+      if (obj && obj.productLinkPath) {
+        let query = {
+          path: defaultCmsPath.value,
+          queryType: '*',
+          productId: String(classInfo?.bookId),
+          storeInfo: defaultCmsPath.value,
+          cmsPath: obj.productLinkPath
+        }
+        MG.store
+          .getProductDetail(query)
+          .then(async (cres: any) => {
+            const { cmsDatas } = cres.datas
+            const list: any = cmsDatas[0]?.datas
+            workLeftList.value = list
+            if (list?.length > 0) {
+              const cmsPath = list[0].productLinkPath
+              getBookQuestionContentList(cmsPath, list[0])
+            }
+          })
+          .catch((err: any) => {
+            leftLoading.value = false
+            workLeftList.value = []
+            console.log(err)
+          })
+      }
+    })
+    .catch((err: any) => {
+      leftLoading.value = false
+      workLeftList.value = []
+      console.log(err)
+    })
+}
+
+// 閫掑綊鑾峰彇
+const getDataCms = async (res: any) => {
+  for (const item of res) {
+    const data = await MG.store.getProductDetail({
+      path: defaultCmsPath.value,
+      queryType: '*',
+      productId: String(classInfo?.bookId),
+      storeInfo: defaultCmsPath.value,
+      cmsPath: item.productLinkPath,
+      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: []
+      }
+    })
+    if (item.type == 'questionBankFolder' && item.childrenFolderCount == 0) {
+      return data.datas.cmsDatas
+    } else {
+      const { cmsDatas } = data.datas
+      if (cmsDatas?.length > 0) {
+        const list: any = await getDataCms(cmsDatas[0].datas)
+        return list
+      }
+    }
+  }
+}
+
+// 鑾峰彇绯荤粺棰樼洰鍒楄〃
+const getBookQuestionContentList = (cmsPath: string, item: any) => {
+  rightLoading.value = true
+  workRightList.value = []
+  if (item.type == 'questionBankFolder' && item.childrenFolderCount == 0) {
+    let query = {
+      path: defaultCmsPath.value,
+      queryType: '*',
+      productId: String(classInfo?.bookId),
+      storeInfo: defaultCmsPath.value,
+      cmsPath,
+      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: []
+      }
+    }
+    MG.store
+      .getProductDetail(query)
+      .then(async (cres: any) => {
+        rightLoading.value = false
+        const { cmsDatas } = cres.datas
+        const list: any = cmsDatas[0]?.datas
+        workRightList.value = changeQuestionData(list)
+        if (workRightList.value?.length > 0) {
+          const ids = workRightList.value.map((item: any) => item.id)
+          checkAll.value = getInclude3(checkData.value, ids)
+        }
+      })
+      .catch((err: any) => {
+        rightLoading.value = false
+        workRightList.value = []
+        console.log(err)
+      })
+  } else {
+    let query = {
+      path: defaultCmsPath.value,
+      queryType: '*',
+      productId: String(classInfo?.bookId),
+      storeInfo: defaultCmsPath.value,
+      cmsPath: item.productLinkPath
+    }
+    MG.store
+      .getProductDetail(query)
+      .then(async (res: any) => {
+        const { cmsDatas } = res.datas
+        const cmsList = await getDataCms(cmsDatas[0]?.datas)
+        const list = cmsList[0]?.datas
+        workRightList.value = changeQuestionData(list)
+        rightLoading.value = false
+        if (workRightList.value?.length > 0) {
+          const ids = workRightList.value.map((item: any) => item.id)
+          checkAll.value = getInclude3(checkData.value, ids)
+        }
+      })
+      .catch((err: any) => {
+        rightLoading.value = false
+        workRightList.value = []
+        console.log(err)
+      })
+  }
+}
+
+// // 鑾峰彇鏁欐潗棰樼洰绔犺妭
+// const getChapter = async () => {
+//   const url = config.questionUrl + classInfo?.bookRefCode + '/information.json'
+//   const { data } = await axios.get(url)
+//   let dataList: any = []
+//   if (data?.data?.length > 0) {
+//     dataList = data.data.map((item: any) => {
+//       return {
+//         ...item,
+//         name: item.label
+//       }
+//     })
+//   }
+//   workLeftList.value = dataList?.filter((item: any) => item.page != '')
+// }
+
+// // 鑾峰彇绔犺妭棰樼洰鍒楄〃
+// const getChapterQeustion = async (item: any) => {
+//   // 棰樺簱棰樼洰绫诲瀷
+//   const questionTypeList = [
+//     { name: '鍗曢�夐', totalScore: 0, value: 'singleChoice', data: [] },
+//     { name: '澶氶�夐', totalScore: 0, value: 'multipleChoice', data: [] },
+//     { name: '鍒ゆ柇棰�', totalScore: 0, value: 'judge', data: [] },
+//     { name: '绠�绛旈', totalScore: 0, value: 'shortAnswer', data: [] },
+//     { name: '璁鸿堪棰�', totalScore: 0, value: 'discuss', data: [] },
+//     { name: '濉┖棰�', totalScore: 0, value: 'completion', data: [] },
+//     { name: '杩炵嚎棰�', totalScore: 0, value: 'matching', data: [] },
+//     { name: '鍒嗙被棰�', totalScore: 0, value: 'classification', data: [] }
+//   ]
+//   try {
+//     let list: any = []
+//     const { data } = await axios.get(
+//       config.questionUrl + classInfo?.bookRefCode + '/question-' + item.chapter + '.json'
+//     )
+//     list = data.data.map((item: any) => {
+//       if (item.type == 'material') {
+//         item.questionType = 'shortAnswer'
+//       }
+//       return {
+//         ...item,
+//         analysisCon: item.Embedded_QuestionBank_AnalysisCon,
+//         questionAnswer: item.answer,
+//         questionStem: item.stem,
+//         questionOption: item.option,
+//         customAnswer: null
+//       }
+//     })
+//     console.log(list, 'list')
+//     list.forEach((item: any) => {
+//       const index = findIndexByValue(questionTypeList, item.questionType)
+//       if (index > -1) {
+//         questionTypeList[index].data.push(item)
+//         if (item.score) {
+//           questionTypeList[index].totalScore += item.score
+//         }
+//       }
+//     })
+//     console.log(questionTypeList)
+//   } catch (error) {
+//     console.log(error)
+//   }
+// }
+
+// 鏁扮粍涓槸鍚﹀寘鍚彟涓�涓暟缁�
+const getInclude3 = (arr1: any[], arr2: any[]) => {
+  let temp = []
+  temp = arr1.filter((item) => arr2.indexOf(item.id) > -1)
+  return temp.length ? true : false
+}
+
+// 澶勭悊棰樼洰鏁版嵁缁撴瀯
+const changeQuestionData = (res: any) => {
+  // 棰樺簱棰樼洰绫诲瀷
+  const questionTypeList = [
+    { name: '鍗曢�夐', totalScore: 0, value: 'singleChoice', data: [] },
+    { name: '澶氶�夐', totalScore: 0, value: 'multipleChoice', data: [] },
+    { name: '鍒ゆ柇棰�', totalScore: 0, value: 'judge', data: [] },
+    { name: '绠�绛旈', totalScore: 0, value: 'shortAnswer', data: [] },
+    { name: '璁鸿堪棰�', totalScore: 0, value: 'discuss', data: [] },
+    { name: '濉┖棰�', totalScore: 0, value: 'completion', data: [] },
+    { name: '杩炵嚎棰�', totalScore: 0, value: 'matching', data: [] },
+    { name: '鍒嗙被棰�', totalScore: 0, value: 'classification', data: [] }
+  ]
+  try {
+    let list = []
+    list = res?.map((item: any) => {
+      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)
+        }
+        const checkObj = checkData.value.find((citem: any) => citem.id == item.id)
+        item.isCheck = checkObj ? true : false
+        return {
+          ...item,
+          questionType: item.Embedded_QuestionBank_QuestionType,
+          questionAnalysisCon: item.Embedded_QuestionBank_AnalysisCon,
+          questionAnswer: item.Embedded_QuestionBank_Answer,
+          customAnswer: null
+        }
+      } catch (error) {
+        console.log(item)
+      }
+    })
+    list.forEach((item: any) => {
+      const index = findIndexByValue(questionTypeList, item.questionType)
+      if (index > -1) {
+        questionTypeList[index].data.push(item)
+        if (item.score) {
+          questionTypeList[index].totalScore += item.score
+        }
+      }
+    })
+    return questionTypeList.filter((item) => item.data.length > 0)
+  } catch (error) {
+    console.log(error)
+    return []
+  }
+}
+
+const findIndexByValue = (res: any, type: string) => {
+  for (let i = 0; i < res.length; i++) {
+    if (res[i].value == type) {
+      return i
+    }
+  }
+  return -1 // 濡傛灉鏈壘鍒帮紝鍒欒繑鍥� -1
+}
+
+// 鍚堝苟鏇存柊鏁扮粍
+const updateArr = (arr: any, brr: any) => {
+  // 浣跨敤 Map 鏉ュ瓨鍌ㄥ悎骞跺悗鐨勭粨鏋�
+  const mergedMap = new Map()
+
+  // 灏嗙涓�涓暟缁勭殑瀵硅薄鍔犲叆鍒� Map 涓�
+  arr.forEach((item: any) => {
+    mergedMap.set(item.id, { ...item })
+  })
+
+  // 閬嶅巻绗簩涓暟缁勶紝鏇存柊 Map 涓浉鍚� id 鐨勫璞$殑 score
+  brr.forEach((item: any) => {
+    if (mergedMap.has(item.id)) {
+      mergedMap.get(item.id).score = item.score
+    } else {
+      mergedMap.set(item.id, { ...item })
+    }
+  })
+
+  // 灏� Map 杞崲涓烘暟缁�
+  const mergedArray = Array.from(mergedMap.values())
+  return mergedArray
+}
+</script>
+
+<style lang="less" scoped>
+.classManagePage-box {
+  padding: 20px;
+  .classManagePage-nav {
+    padding-bottom: 20px;
+    border-bottom: 1px solid #e6e8ed;
+  }
+  .classManagePage-content {
+    .cartClass {
+      .titleOptions {
+        width: 160px;
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        span {
+          height: 30px;
+          font-weight: bold;
+          font-size: 16px;
+          color: #333;
+          line-height: 30px;
+          text-align: left;
+          border-left: 6px solid #ff6c00;
+          padding-left: 10px;
+        }
+      }
+      margin-top: 20px;
+      ::v-deep .el-tabs__nav-wrap::after {
+        background-color: #ff6d00;
+        height: 1px;
+      }
+
+      ::v-deep .el-tabs__item {
+        width: 100px;
+        padding: 0;
+        color: #545c63;
+      }
+
+      ::v-deep .is-active {
+        background-color: #ff6d00;
+        color: #fff;
+        border-radius: 3px 3px 0 0;
+      }
+    }
+    .headerBox {
+      padding: 20px 0;
+      overflow: hidden;
+      .searchBox {
+        width: 300px;
+        float: left;
+        .searchBtn {
+          background-color: var(--el-color-primary);
+          color: #fff;
+          border-top-left-radius: 0;
+          border-bottom-left-radius: 0;
+        }
+      }
+    }
+    ::v-deep(.customDialog) {
+      border-radius: 5px;
+      .stepBox {
+        padding: 15px 0;
+      }
+      padding-bottom: 20px;
+      .el-dialog__body {
+        padding: 0 20px;
+      }
+      .el-dialog__footer {
+        width: calc(100% - 40px);
+        margin: auto;
+        display: flex;
+        padding: 0;
+        .leftFooter {
+          height: 55px;
+          width: 286px;
+          border: 1px solid #f4f4f4;
+          background: #e0f2ff;
+          margin-right: 20px;
+        }
+        .dialog-footer {
+          flex: 1;
+          display: flex;
+          align-items: center;
+          justify-content: flex-start;
+          border: 1px solid #f4f4f4;
+          border-top: 0;
+          padding: 0 10px;
+          .check-list-box {
+            width: 220px;
+            display: flex;
+            justify-content: flex-start;
+          }
+          .btnGroup {
+            flex: 1;
+            display: flex;
+            align-items: center;
+            justify-content: flex-end;
+          }
+        }
+        .selectedFooter {
+          width: 100%;
+          display: flex;
+          justify-content: flex-end;
+          padding: 10px 0;
+        }
+      }
+      .viewTitle {
+        width: 100%;
+        text-align: center;
+        font-size: 16px;
+      }
+    }
+    .workTitle {
+      margin: 20px 0;
+      font-size: 16px;
+      color: #333;
+    }
+    .viewContent {
+      width: 100%;
+      .right-list-components {
+        height: calc(100% - 5px) !important;
+      }
+    }
+    .workBox {
+      width: 100%;
+      display: flex;
+      .workLeft {
+        width: 286px;
+        height: 700px;
+        border-radius: 10px 10px 0px 0px;
+        border: 1px solid #f4f4f4;
+        border-bottom: 0;
+        .scoreTitle {
+          display: flex;
+          align-items: center;
+          justify-content: flex-start;
+          line-height: 39px;
+          padding-left: 10px;
+          box-sizing: border-box;
+        }
+        ::v-deep(.demo-tabs) {
+          .el-tabs__header {
+            margin: 0;
+          }
+          .el-tabs__nav {
+            width: 100%;
+            justify-content: center;
+            padding: 8px 0;
+            .el-tabs__item {
+              flex: 1;
+              height: 0px;
+              padding: 12px 0;
+            }
+            .el-tabs__item {
+              border-right: 1px solid #eee;
+            }
+            .el-tabs__item:last-child {
+              border: 0;
+            }
+            .el-tabs__active-bar {
+              display: none;
+              // width: 60px !important;
+              // left: 40px !important;
+            }
+          }
+          .el-tabs__nav-wrap::after {
+            height: 0px !important;
+            background: none;
+          }
+        }
+        .workList {
+          width: 100%;
+          height: calc(100% - 39px);
+          background: #e0f2ff;
+          overflow: auto;
+          padding: 10px 18px;
+          .searchBox {
+            position: sticky;
+            top: -10px;
+            z-index: 9999999;
+          }
+          .work-list-item {
+            background: #ffffff;
+            border-radius: 5px 5px 5px 5px;
+            margin: 10px 0;
+            .work-list-item-text {
+              font-family: PingFang SC;
+              font-weight: 400;
+              font-size: 13px;
+              color: #000000;
+              line-height: 22px;
+              max-width: 248px;
+              white-space: nowrap;
+              text-overflow: ellipsis;
+              overflow: hidden;
+              padding: 6px 10px;
+            }
+            .work-list-item-text:hover {
+              cursor: pointer;
+            }
+          }
+        }
+      }
+      .workRight {
+        flex: 1;
+        height: 700px;
+        margin-left: 20px;
+        border-radius: 10px 10px 0px 0px;
+        border: 1px solid #f4f4f4;
+        .right-list-title {
+          display: flex;
+          justify-content: space-between;
+          align-items: center;
+          width: 100%;
+          height: 39px;
+          border-bottom: 1px solid #f4f4f4;
+          line-height: 39px;
+          padding: 0 10px;
+        }
+        .right-list-components {
+          width: 100%;
+          height: calc(100% - 40px);
+          display: flex;
+          align-items: center;
+          justify-content: center;
+        }
+        .right-score-components {
+          padding: 10px;
+          .scoreBtn {
+            margin-bottom: 20px;
+            display: flex;
+            justify-content: flex-start;
+            align-items: center;
+            // .setScore {
+            //   margin-left: 20px;
+            // }
+          }
+        }
+      }
+      .finishBg {
+        width: 100%;
+        height: 100%;
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+        align-items: center;
+        img {
+          width: 300px;
+          margin-bottom: 20px;
+        }
+        span {
+          font-family: PingFang SC;
+          font-weight: 500;
+          font-size: 18px;
+          color: #999999;
+        }
+      }
+    }
+    .newTaskBox {
+      width: 750px;
+      height: 700px;
+      font-family: PingFang SC;
+      font-weight: 400;
+      font-size: 14px;
+      color: #333333;
+      margin: auto;
+      padding-top: 60px;
+      display: flex;
+      flex-direction: column;
+      box-sizing: border-box;
+
+      .el-row {
+        margin-bottom: 20px;
+        display: flex;
+        align-items: flex-start;
+        .labelItem {
+          text-align: right;
+          margin-right: 10px;
+          padding-top: 2px;
+        }
+        .selectBox {
+          border: 1px solid #ddd;
+          border-radius: 5px;
+          padding: 20px 30px;
+        }
+        .selectMarBot {
+          margin-bottom: 10px;
+        }
+        .btngroup {
+          position: absolute;
+          top: 20px;
+          right: 27px;
+        }
+        .el-upload-list__item-name {
+          line-height: 22px;
+        }
+      }
+
+      .row-center {
+        align-items: center;
+      }
+    }
+    .leftBg {
+      background-color: rgba(255, 173, 65, 0.1);
+      border-radius: 5px 5px 5px 5px;
+      color: #ff6c00 !important;
+    }
+    .pageBox {
+      padding: 10px 0;
+      display: flex;
+      justify-content: flex-end;
+    }
+    .pubContent {
+      display: flex;
+      justify-content: center;
+      align-items: center;
+      padding: 20px 0;
+    }
+  }
+}
+</style>
diff --git a/src/views/classManage/prepareLessons.vue b/src/views/classManage/prepareLessons.vue
new file mode 100644
index 0000000..e2caa55
--- /dev/null
+++ b/src/views/classManage/prepareLessons.vue
@@ -0,0 +1,22 @@
+<template>
+  <div class="classManagePage-box">
+    <div class="classManagePage-nav">鎴戠殑鐝骇>{{ classInfo.name }}>澶囪</div>
+    <div class="classManagePage-content"></div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { useRoute } from 'vue-router'
+const route = useRoute()
+const classInfo = JSON.parse(route.query.classInfo)
+</script>
+
+<style lang="less" scoped>
+.classManagePage-box {
+  padding: 20px;
+  .classManagePage-nav {
+    padding-bottom: 20px;
+    border-bottom: 1px solid #e6e8ed;
+  }
+}
+</style>
diff --git a/src/views/classManage/studentJob.vue b/src/views/classManage/studentJob.vue
new file mode 100644
index 0000000..f9f3d7b
--- /dev/null
+++ b/src/views/classManage/studentJob.vue
@@ -0,0 +1,357 @@
+<template>
+  <div class="classManagePage-box">
+    <div class="classManagePage-nav">
+      <el-breadcrumb :separator-icon="ArrowRight">
+        <el-breadcrumb-item>鎴戠殑鐝骇</el-breadcrumb-item>
+        <el-breadcrumb-item>{{ classInfo?.name }}</el-breadcrumb-item>
+        <el-breadcrumb-item>浣滀笟绠$悊</el-breadcrumb-item>
+      </el-breadcrumb>
+    </div>
+    <div class="classManagePage-content">
+      <div class="cartClass">
+        <!-- <el-tabs v-model="jobState" @tab-click="tabCart">
+          <el-tab-pane label="鍏ㄩ儴" name="all"></el-tab-pane>
+          <el-tab-pane label="杩涜涓�" name="payment"></el-tab-pane>
+          <el-tab-pane label="宸茶繃鏈�" name="complete"></el-tab-pane>
+        </el-tabs> -->
+        <div class="titleOptions">
+          <span>浣滀笟绠$悊</span>
+        </div>
+      </div>
+      <div class="headerBox">
+        <div class="searchBox">
+          <el-input
+            v-model="searchKey"
+            clearable
+            @clear="searchTask"
+            @keydown.enter="searchTask"
+            placeholder="璇疯緭鍏ュ叧閿瓧"
+          >
+            <template #append>
+              <el-button type="primary" @click="searchTask" class="searchBtn" :icon="Search" />
+            </template>
+          </el-input>
+        </div>
+      </div>
+      <div class="listBox">
+        <el-table
+          :data="tableData"
+          :header-cell-style="{ background: '#eee' }"
+          max-height="600px"
+          style="width: 100%"
+          v-loading="pages.loading"
+        >
+          <el-table-column label="搴忓彿" prop="id" width="70"> </el-table-column>
+          <el-table-column label="鍚嶇О" prop="name"> </el-table-column>
+          <el-table-column label="浣滀笟瀹屾垚鎯呭喌" #default="scope">
+            <span v-if="scope.row.submitState == 'WaitCheck'" style="color: #ff6d00">寰呮壒鏀�</span>
+            <span v-if="scope.row.submitState == 'Normal'" style="color: #67c23a">宸叉壒鏀�</span>
+            <span v-if="!scope.row.submitState" style="color: red">鏈彁浜�</span>
+          </el-table-column>
+          <!-- <el-table-column label="鐘舵��" prop="state" #default="scope">
+            <span v-if="scope.row.state == 'Waiting'" style="color: red">鏈紑濮�</span>
+            <span v-if="scope.row.state == 'Normal'" style="color: #67c23a">杩涜涓�</span>
+            <span v-if="scope.row.state == 'Ended'" style="color: #999">宸茬粨鏉�</span>
+          </el-table-column> -->
+          <el-table-column label="浣滀笟寮�濮嬫棩鏈�" prop="beginDate"> </el-table-column>
+          <el-table-column label="浣滀笟缁撴潫鏃ユ湡" prop="endDate"> </el-table-column>
+          <el-table-column label="涓昏棰樺緱鍒�" prop="judgeScore"> </el-table-column>
+          <el-table-column label="瀹㈣棰樺緱鍒�" prop="otherScore"> </el-table-column>
+          <el-table-column label="鎬诲垎" prop="totalScore"> </el-table-column>
+          <el-table-column label="鎿嶄綔" width="200" #default="scope">
+            <el-button link style="color: #409eff" @click="preview(scope.row)">棰勮</el-button>
+            <el-button link v-if="!scope.row.submitState" type="primary" @click="answer(scope.row)">
+              绛旈
+            </el-button>
+          </el-table-column>
+        </el-table>
+        <div class="pageBox">
+          <el-pagination
+            v-model:current-page="pages.currentPage"
+            :page-size="pages.pageSize"
+            :size="'small'"
+            :disabled="pages.count <= 1"
+            layout="total, prev, pager, next"
+            :total="pages.count"
+            @size-change="handleSizeChange"
+            @current-change="handleCurrentChange"
+          />
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { reactive, ref, onMounted, inject, watch } from 'vue'
+import { Search, ArrowRight } from '@element-plus/icons-vue'
+import { useRoute, useRouter } from 'vue-router'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import moment from 'moment'
+
+const route: any = useRoute()
+const router = useRouter()
+const MG: any = inject('MG')
+const config: any = inject('config')
+const tool: any = inject('toolClass')
+const classInfo = JSON.parse(route.query.classInfo)
+const jobState = ref('all')
+const searchKey = ref('')
+const dataList = ref([])
+const userInfo = ref()
+
+// 鑾峰彇task鍙傛暟
+const filterData = ref([
+  {
+    value: config.taskType.homeWork,
+    field: 'Type',
+    subFilters: []
+  }
+])
+// task
+const taskData = reactive({
+  id: '',
+  description: '',
+  rootCmsItemId: '',
+  name: '',
+  type: '',
+  state: '',
+  groupId: '',
+  beginDate: '',
+  endDate: ''
+})
+
+const visiblePub = ref(false)
+const questionData: any = ref([])
+
+const scoreData: any = ref([])
+// question Key
+const questionKey = [
+  'Name',
+  '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'
+]
+
+let pages = reactive({
+  currentPage: 1,
+  page: 1,
+  pageSize: 15,
+  count: 0,
+  loading: false
+})
+// 浣滀笟鍒楄〃
+const tableData: any = ref([])
+
+onMounted(() => {
+  const userCache: any = localStorage.getItem('jesk-userInfo')
+  if (userCache) {
+    userInfo.value = JSON.parse(userCache)
+  }
+  getTaskList()
+})
+
+//  鍒嗛〉
+const handleSizeChange = (val: number) => {
+  pages.pageSize = val
+  getTaskList()
+}
+
+const handleCurrentChange = (val: number) => {
+  pages.page = val
+  pages.currentPage = val
+  getTaskList()
+}
+
+// 鑾峰彇浠诲姟鍒楄〃
+const getTaskList = (filter?: any[], search?: any[]) => {
+  const filterList = filter ?? filterData.value
+  const searchList = search ?? []
+  pages.loading = true
+  const data = {
+    start: (pages.page - 1) * pages.pageSize,
+    size: pages.pageSize,
+    sort: {
+      type: 'Desc',
+      field: 'CreateDate'
+    },
+    filterList,
+    searchList,
+    groupId: classInfo?.id
+  }
+  MG.edu
+    .getTaskList(data)
+    .then((res: any) => {
+      pages.count = res.totalSize
+      if (res.datas.length > 0) {
+        tableData.value = res.datas?.map((item: any) => {
+          item.judgeScore = 0
+          item.otherScore = 0
+          if (item.submit?.id) {
+            item.submit?.submitAndCmsItemLinks?.forEach((citem: any) => {
+              if (citem.comments == 'judge') {
+                item.judgeScore += citem.score
+              }
+              if (citem.comments != 'judge') {
+                item.otherScore += citem.score
+              }
+            })
+          }
+          return {
+            ...item,
+            totalScore: item.judgeScore + item.otherScore,
+            beginDate: moment(item.beginDate).format('YYYY-MM-DD'),
+            endDate: moment(item.endDate).format('YYYY-MM-DD')
+          }
+        })
+      } else {
+        tableData.value = []
+      }
+      pages.loading = false
+    })
+    .catch((e: any) => {
+      pages.loading = false
+      console.log(e)
+    })
+}
+
+// 鎼滅储浠诲姟
+const searchTask = () => {
+  const data = [
+    {
+      compareType: 'Contains',
+      keywords: searchKey.value,
+      field: 'Name'
+    }
+  ]
+  pages.page = 1
+  pages.currentPage = 1
+  getTaskList(undefined, data)
+}
+
+// 琛ㄦ牸tab浜嬩欢{Waiting:鏈紑濮�,Normal:杩涜涓�,Ended:宸茬粨鏉焳
+const tabCart = (event: Event | any) => {
+  let queryFilter: any = []
+  jobState.value = event.props.name
+  pages.page = 1
+  dataList.value = []
+  if (jobState.value == 'all') {
+    queryFilter = [...filterData.value]
+  }
+  if (jobState.value == 'payment') {
+    queryFilter = [...filterData.value, { field: 'State', value: 'Normal', subFilters: [] }]
+  }
+  if (jobState.value == 'complete') {
+    queryFilter = [...filterData.value, { field: 'State', value: 'Ended', subFilters: [] }]
+  }
+  getTaskList(queryFilter)
+}
+
+// 绛旈
+const answer = (item: any) => {
+  router.push({
+    path: '/bookService/details/answer',
+    query: {
+      answerTitle: item.name,
+      taskId: item.id,
+      groupId: classInfo?.id,
+      answerType: 'task'
+    }
+  })
+}
+
+// 棰勮
+const preview = (item: any) => {
+  router.push({
+    path: '/bookService/details/answer',
+    query: {
+      answerTitle: item.name,
+      taskId: item.id,
+      groupId: classInfo?.id,
+      answerType: 'task',
+      isPreview: 'true'
+    }
+  })
+}
+</script>
+
+<style lang="less" scoped>
+.classManagePage-box {
+  padding: 20px;
+  .classManagePage-nav {
+    padding-bottom: 20px;
+    border-bottom: 1px solid #e6e8ed;
+  }
+  .classManagePage-content {
+    .cartClass {
+      .titleOptions {
+        width: 160px;
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        span {
+          height: 30px;
+          font-weight: bold;
+          font-size: 16px;
+          color: #333;
+          line-height: 30px;
+          text-align: left;
+          border-left: 6px solid #ff6c00;
+          padding-left: 10px;
+        }
+      }
+      margin-top: 20px;
+      ::v-deep .el-tabs__nav-wrap::after {
+        background-color: #ff6d00;
+        height: 1px;
+      }
+
+      ::v-deep .el-tabs__item {
+        width: 100px;
+        padding: 0;
+        color: #545c63;
+      }
+
+      ::v-deep .is-active {
+        background-color: #ff6d00;
+        color: #fff;
+        border-radius: 3px 3px 0 0;
+      }
+    }
+    .headerBox {
+      padding: 20px 0;
+      overflow: hidden;
+      .searchBox {
+        width: 300px;
+        float: left;
+        .searchBtn {
+          background-color: var(--el-color-primary);
+          color: #fff;
+          border-top-left-radius: 0;
+          border-bottom-left-radius: 0;
+        }
+      }
+    }
+    ::v-deep(.customDialog) {
+      border-radius: 5px;
+      margin: 10px auto;
+      padding-bottom: 20px;
+      .pubContent {
+        height: 800px;
+      }
+    }
+    .pageBox {
+      padding: 10px 0;
+      display: flex;
+      justify-content: flex-end;
+    }
+  }
+}
+</style>
diff --git a/src/views/classManage/studentManage.vue b/src/views/classManage/studentManage.vue
new file mode 100644
index 0000000..f773819
--- /dev/null
+++ b/src/views/classManage/studentManage.vue
@@ -0,0 +1,475 @@
+<template>
+  <div class="classManagePage-box">
+    <div class="classManagePage-nav">
+      <el-breadcrumb :separator-icon="ArrowRight">
+        <el-breadcrumb-item>鎴戠殑鐝骇</el-breadcrumb-item>
+        <el-breadcrumb-item>{{ classInfo?.name }}</el-breadcrumb-item>
+        <el-breadcrumb-item>鐝骇绠$悊</el-breadcrumb-item>
+      </el-breadcrumb>
+    </div>
+    <div class="classManagePage-content">
+      <div class="headerBox">
+        <div class="btnBox">
+          <!-- 鎵归噺閫氳繃鎸夐挳 -->
+          <el-button
+            v-if="multipleSelection.length > 0"
+            type="success"
+            size="small"
+            @click="updateStateNormalDatas"
+            >鎵归噺閫氳繃</el-button
+          >
+          <!-- 鎵归噺绉婚櫎鎸夐挳 -->
+          <el-button
+            v-if="multipleSelection.length > 0"
+            type="danger"
+            size="small"
+            @click="removeStudentDatas"
+            >鎵归噺绉婚櫎</el-button
+          >
+          <!-- 鎵归噺鎷掔粷 -->
+          <el-button
+            v-if="multipleSelection.length > 0"
+            type="warning"
+            size="small"
+            @click="updateStateRejectDatas"
+            >鎵归噺鎷掔粷</el-button
+          >
+        </div>
+        <!-- <div class="searchBox">
+          <el-input v-model="searchKey" clearable @clear="searchData()" placeholder="璇疯緭鍏ュ叧閿瓧">
+            <template #append>
+              <el-button type="primary" @click="searchData()" class="searchBtn" :icon="Search" />
+            </template>
+          </el-input>
+        </div> -->
+      </div>
+      <div class="listBox">
+        <el-table
+          :header-cell-style="{ background: '#eee' }"
+          :data="dataList"
+          max-height="600px"
+          style="width: 100%"
+          v-loading="pages.loading"
+          @selection-change="handleSelectionChange"
+        >
+          <el-table-column type="selection" :selectable="selectable" width="55" />
+          <el-table-column prop="index" label="搴忓彿" width="70" />
+          <el-table-column label="濮撳悕" width="400">
+            <template #default="scope">
+              <div class="userBox">
+                <el-avatar
+                  style="margin-right: 10px"
+                  v-if="scope.row.appUser.icon"
+                  :size="35"
+                  :src="scope.row.appUser.icon"
+                />
+                <el-avatar
+                  style="margin-right: 10px"
+                  :size="35"
+                  v-if="!scope.row.appUser.icon"
+                  :icon="UserFilled"
+                />
+                <span v-if="scope.row.appUser.name">{{ scope.row.appUser.name }}</span>
+              </div>
+            </template>
+          </el-table-column>
+          <el-table-column prop="createDate" label="鍔犲叆鐝骇鏃堕棿" />
+          <el-table-column label="鐘舵��">
+            <template #default="scope">
+              <span v-if="scope.row.state == 'WaitValid'" style="color: #ef9f29"> 瀹℃牳涓� </span>
+              <span v-if="scope.row.state == 'Normal'" style="color: #1dbd11"> 宸查�氳繃 </span>
+              <span v-if="scope.row.state == 'Reject'" style="color: #fc425d"> 鏈�氳繃 </span>
+            </template>
+          </el-table-column>
+          <el-table-column label="鐝骇鎴愬憳韬唤">
+            <template #default="scope">
+              <span v-if="scope.row.linkType == 'RefCode'"> 瀛︾敓 </span>
+              <span v-if="scope.row.linkType == 'Teacher'"> 鍔╂暀 </span>
+              <span v-if="scope.row.linkType == 'Creator'"> 鍒涘缓浜� </span>
+            </template>
+          </el-table-column>
+          <el-table-column label="鎿嶄綔" width="200">
+            <template #default="scope">
+              <el-button
+                link
+                v-if="scope.row.linkType != 'Creator' && scope.row.state == 'Normal'"
+                type="danger"
+                size="small"
+                @click="removeStudent(scope.row)"
+              >
+                绉婚櫎
+              </el-button>
+              <el-button link v-if="scope.row.linkType == 'Creator'" type="info" size="small">
+                ---
+              </el-button>
+              <el-button
+                link
+                v-if="scope.row.state != 'Normal'"
+                type="success"
+                size="small"
+                @click="selectIdentity(scope.row)"
+              >
+                閫氳繃
+              </el-button>
+              <el-button
+                link
+                v-if="scope.row.state != 'Normal' && scope.row.state != 'Reject'"
+                type="warning"
+                size="small"
+                @click="updateStateReject(scope.row)"
+              >
+                鎷掔粷
+              </el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+        <el-pagination
+          style="float: right"
+          v-model:current-page="pages.page"
+          :page-size="pages.pageSize"
+          layout="total, prev, pager, next"
+          :total="pages.count"
+          @size-change="handleSizeChange"
+          @current-change="handleCurrentChange"
+        />
+        <el-dialog v-model="visible" title="閫夋嫨褰撳墠鎴愬憳韬唤" width="500" align-center>
+          <el-radio-group v-model="currentLinkType">
+            <el-radio label="RefCode" size="large" border>瀛︾敓</el-radio>
+            <el-radio label="Teacher" size="large" border>鍔╂暀</el-radio>
+          </el-radio-group>
+          <template #footer>
+            <div class="dialog-footer">
+              <el-button @click="cancleLinkType"> 鍙栨秷 </el-button>
+              <el-button type="primary" @click="updateStateNormal"> 纭 </el-button>
+            </div>
+          </template>
+        </el-dialog>
+        <el-dialog v-model="visibleReject" title="鎷掔粷鍘熷洜" width="500" align-center>
+          <div class="reasonStr">
+            <span style="width: 100px">鎷掔粷鍘熷洜锛�</span>
+            <el-input type="textarea" :rows="2" maxlength="100" v-model="reasonStr"></el-input>
+          </div>
+          <template #footer>
+            <div class="dialog-footer">
+              <el-button @click="cancleReject"> 鍙栨秷 </el-button>
+              <el-button type="primary" @click="updateStateReject"> 纭 </el-button>
+            </div>
+          </template>
+        </el-dialog>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { reactive, ref, onMounted, inject, watch } from 'vue'
+import type { TableInstance } from 'element-plus'
+import { useRoute } from 'vue-router'
+import { Search, ArrowRight, UserFilled } from '@element-plus/icons-vue'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import { getPublicImage } from '@/assets/js/middleGround/tool.js'
+import moment from 'moment'
+
+const route: any = useRoute()
+const MG: any = inject('MG')
+const classInfo = JSON.parse(route.query.classInfo)
+
+const searchKey = ref('')
+const reasonStr = ref('')
+const dataList = ref([])
+const visible = ref(false)
+const currentIdentity = ref()
+const currentLinkType = ref('RefCode')
+const visibleReject = ref(false)
+const rejectData: any = ref()
+let pages = reactive({
+  page: 1,
+  pageSize: 10,
+  count: 0,
+  loading: false
+})
+
+const multipleSelection = ref<any[]>([])
+
+const selectable = (row: any) => ![1].includes(row.index)
+
+onMounted(() => {
+  getStudentList() 
+})
+
+const handleSelectionChange = (val: any) => {
+  multipleSelection.value = val
+}
+
+const handleSizeChange = (val: number) => {
+  pages.pageSize = val
+  getStudentList()
+}
+
+const handleCurrentChange = (val: number) => {
+  pages.page = val
+  getStudentList()
+}
+
+const searchData = () => {
+  pages.page = 1
+  pages.pageSize = 10
+  getStudentList()
+}
+
+// 鑾峰彇瀛︾敓鍒楄〃
+const getStudentList = () => {
+  pages.loading = true
+  const data = {
+    start: (pages.page - 1) * pages.pageSize,
+    size: pages.pageSize,
+    groupId: classInfo.id
+  }
+  MG.identity.getGroupUserList(data).then((res: any) => {
+    const { datas } = res
+    pages.loading = false
+    if (datas.length > 0) {
+      dataList.value = datas.map((item: any, index: number) => {
+        if (item.linkType == 'Creator') {
+          const userInfo = item.appUser?.infoList?.find((citem: any) => 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: any) => citem.type == 'WeChat')
+          const defaultData = item.appUser?.infoList?.find((citem: any) => 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')
+        }
+      })
+      pages.count = dataList.value.length
+    }
+  })
+}
+
+// 绉婚櫎瀛︾敓
+const removeStudent = (item: any) => {
+  ElMessageBox.confirm('鏄惁绉婚櫎閫変腑鎴愬憳?')
+    .then(() => {
+      const data = {
+        groupId: classInfo.id,
+        appUserIds: [item.appUser.id]
+      }
+      MG.identity.removeAppUserFromGroup(data).then((res: any) => {
+        if (res) {
+          ElMessage({
+            message: '宸茬Щ闄�',
+            type: 'success'
+          })
+          getStudentList()
+        }
+      })
+    })
+    .catch(() => {
+      // catch error
+    })
+}
+
+// 鎵归噺绉婚櫎瀛︾敓
+const removeStudentDatas = () => {
+  ElMessageBox.confirm('鏄惁鎵归噺绉婚櫎閫変腑鎴愬憳?')
+    .then(() => {
+      const data = {
+        groupId: classInfo.id,
+        appUserIds: multipleSelection.value.map((item) => item.appUser.id)
+      }
+      MG.identity.removeAppUserFromGroup(data).then((res: any) => {
+        if (res) {
+          ElMessage({
+            message: '宸茬Щ闄�',
+            type: 'success'
+          })
+          getStudentList()
+        }
+      })
+    })
+    .catch(() => {
+      // catch error
+    })
+}
+
+const selectIdentity = (item: any) => {
+  visible.value = true
+  currentIdentity.value = item
+}
+
+const cancleLinkType = () => {
+  visible.value = false
+  currentIdentity.value = null
+  currentLinkType.value = 'RefCode'
+}
+
+// 鏇存柊鐘舵��
+const updateStateNormal = () => {
+  const data = {
+    groupId: classInfo.id,
+    requests: [
+      {
+        linkId: currentIdentity.value.linkId,
+        linkType: currentLinkType.value,
+        state: 'Normal',
+        groupState: 'Normal'
+      }
+    ]
+  }
+  MG.identity.updateAppUserGroupLink(data).then((res: any) => {
+    if (res) {
+      visible.value = false
+      ElMessage({
+        message: '宸查�氳繃',
+        type: 'success'
+      })
+      getStudentList()
+    }
+  })
+}
+
+// 鎵归噺閫氳繃
+const updateStateNormalDatas = () => {
+  const data = {
+    groupId: classInfo.id,
+    requests: multipleSelection.value.map((item) => {
+      return {
+        linkId: item.linkId,
+        linkType: item.linkType,
+        state: 'Normal',
+        groupState: 'Normal'
+      }
+    })
+  }
+  MG.identity.updateAppUserGroupLink(data).then((res: any) => {
+    if (res) {
+      ElMessage({
+        message: '宸查�氳繃',
+        type: 'success'
+      })
+      getStudentList()
+    }
+  })
+}
+
+// 鎵归噺鎷掔粷
+const updateStateRejectDatas = () => {
+  const data = {
+    groupId: classInfo.id,
+    requests:multipleSelection.value.map((item) => {
+      return {
+        linkId: item.linkId,
+        linkType: item.linkType,
+        state: 'Reject',
+        groupState: 'Reject'
+      }
+    })
+  }
+  MG.identity.updateAppUserGroupLink(data).then((res:any) => {
+    if (res) {
+      ElMessage({
+        message: '宸叉嫆缁�',
+        type: 'success'
+      })
+      getStudentList()
+    }
+  })
+}
+
+const rejectInfo = (item: any) => {
+  visibleReject.value = true
+  rejectData.value = item
+}
+
+const cancleReject = () => {
+  visibleReject.value = false
+  reasonStr.value = ''
+}
+
+// 鏇存柊鐘舵�� 鎷掔粷
+const updateStateReject = (item:any) => {
+  const data = {
+    groupId: classInfo.id,
+    requests: [
+      {
+        linkId: item.linkId,
+        linkType: item.linkType,
+        state: 'Reject',
+        groupState: 'Reject'
+      }
+    ]
+  }
+  MG.identity.updateAppUserGroupLink(data).then((res: any) => {
+    if (res) {
+      ElMessage({
+        message: '宸叉嫆缁�',
+        type: 'warning'
+      })
+      cancleReject()
+      getStudentList()
+    }
+  })
+}
+</script>
+
+<style lang="less" scoped>
+.classManagePage-box {
+  padding: 20px;
+  .classManagePage-nav {
+    padding-bottom: 20px;
+    border-bottom: 1px solid #e6e8ed;
+  }
+  .classManagePage-content {
+    .headerBox {
+      height: 50px;
+      line-height: 50px;
+      overflow: hidden;
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      .btnBox {
+        flex: 1;
+      }
+      .searchBox {
+        width: 300px;
+        float: right;
+        .searchBtn {
+          background-color: var(--el-color-primary);
+          color: #fff;
+          border-top-left-radius: 0;
+          border-bottom-left-radius: 0;
+        }
+      }
+    }
+    .listBox {
+      .el-radio.is-bordered.el-radio--large {
+        padding: 0px 100px 0 11px;
+      }
+      .userBox {
+        display: flex;
+        align-items: center;
+      }
+    }
+  }
+  .reasonStr {
+    display: flex;
+    justify-content: flex-start;
+    align-items: center;
+  }
+}
+</style>
diff --git a/src/views/classManage/talkDetail.vue b/src/views/classManage/talkDetail.vue
new file mode 100644
index 0000000..f38a29a
--- /dev/null
+++ b/src/views/classManage/talkDetail.vue
@@ -0,0 +1,481 @@
+<template>
+  <div class="classManagePage-box">
+    <div class="classManagePage-nav">
+      <el-breadcrumb :separator-icon="ArrowRight">
+        <el-breadcrumb-item>鎴戠殑鐝骇</el-breadcrumb-item>
+        <el-breadcrumb-item>{{ classInfo?.name }}</el-breadcrumb-item>
+        <el-breadcrumb-item>璇濋璇︽儏</el-breadcrumb-item>
+      </el-breadcrumb>
+    </div>
+    <div class="classManagePage-content">
+      <div class="backBtn">
+        <el-button @click="goBack()" type="primary" link>
+          <el-icon style="margin-right: 5px"><ArrowLeftBold /></el-icon> 杩斿洖
+        </el-button>
+      </div>
+      <div class="talkBox">
+        <div class="leftBox">
+          <div class="MessageCount">{{ dataList.length }} 鏉″洖澶�</div>
+          <div class="inputBox">
+            <el-input v-model="textarea" :rows="8" type="textarea" placeholder="璇疯緭鍏�" />
+            <el-button
+              class="submit"
+              :type="textarea.length > 0 ? 'primary' : 'info'"
+              :disabled="textarea.length == 0"
+              round
+              @click="submitText('1')"
+            >
+              鍥� 澶�
+            </el-button>
+          </div>
+          <div v-if="dataList.length > 0 && !childLoading">
+            <div class="MessageBox" v-for="(item, index) in dataList" :key="index">
+              <div class="MessageHeader">
+                <div class="userBox">
+                  <el-avatar
+                    :src="
+                      item.publicText?.icon ??
+                      'https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png'
+                    "
+                  />
+                  <el-text class="userName mx-1">{{ item.publicText?.publisher }}</el-text>
+                  <el-text class="mx-1">{{ item.createDate }}</el-text>
+                </div>
+                <div class="options">
+                  <!-- <el-button type="primary" link @click="openSubmit()"> 鍥炲 </el-button> -->
+                  <!-- <el-button
+                    type="success"
+                    link
+                    @click="pubTalk(item)"
+                    v-if="userInfo.role == 'Teacher' && item.state == 'WaitAudit'"
+                  >
+                    鍙戝竷
+                  </el-button> -->
+                  <el-button
+                    type="danger"
+                    v-if="userInfo.role == 'Teacher'"
+                    link
+                    @click="removeMessageItem(item)"
+                  >
+                    鍒犻櫎
+                  </el-button>
+                </div>
+                <!-- <el-dialog v-model="dialogVisible" title="鍥炲璇濋" width="800">
+                  <div class="talkWall">
+                    <div class="talKBox">
+                      <el-input
+                        style="flex: 1"
+                        v-model="talkContent"
+                        :autosize="{ minRows: 10, maxRows: 15 }"
+                        type="textarea"
+                        placeholder="璇疯緭鍏ュ唴瀹�"
+                      />
+                    </div>
+                  </div>
+                  <template #footer>
+                    <div class="dialog-footer">
+                      <el-button @click="dialogVisible = false"> 鍙栨秷 </el-button>
+                      <el-button type="primary" @click="submitText('2')"> 鍥炲 </el-button>
+                    </div>
+                  </template>
+                </el-dialog> -->
+              </div>
+              <div class="MessageContent" v-html="item.publicText?.content"></div>
+            </div>
+          </div>
+          <div v-if="childLoading" v-loading="childLoading" style="height: 100px"></div>
+        </div>
+        <div class="rightBox" v-if="ownData && !isLoading">
+          <div class="talkHeader">
+            <div class="talkUser">
+              <el-avatar
+                src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png"
+              />
+              <el-text class="userName mx-1">{{ ownData?.publicText?.publisher }}</el-text>
+            </div>
+            <el-text class="mx-1">{{ ownData?.updateDate }}</el-text>
+          </div>
+          <div class="talkContent">
+            <div class="contentTilte">{{ ownData?.name }}</div>
+            <div
+              v-if="ownData?.publicText"
+              class="contentText"
+              v-html="ownData?.publicText?.content"
+            ></div>
+            <div v-else class="contentText" v-html="ownData?.content"></div>
+          </div>
+        </div>
+        <div class="rightBox" v-if="isLoading" v-loading="isLoading"></div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { useRoute, useRouter } from 'vue-router'
+import { ArrowRight } from '@element-plus/icons-vue'
+import { inject, onMounted, ref } from 'vue'
+import moment from 'moment'
+import { ElMessage } from 'element-plus'
+import { getPublicImage } from '@/assets/js/middleGround/tool.js'
+
+const route: any = useRoute()
+const router = useRouter()
+const classInfo = JSON.parse(route.query.classInfo)
+const userInfo = ref()
+const textarea = ref('')
+const talkContent = ref('')
+const dialogVisible = ref(false)
+const MG: any = inject('MG')
+const config: any = inject('config')
+const talkTopicInfo = ref()
+const dataList: any = ref([])
+const ownData = ref()
+const isLoading = ref(false)
+const childLoading = ref(false)
+
+onMounted(() => {
+  const userCache: any = localStorage.getItem('jesk-userInfo')
+  if (userCache) {
+    userInfo.value = JSON.parse(userCache)
+  }
+  getTopicInfo()
+})
+
+const openSubmit = () => {
+  talkContent.value = ''
+  dialogVisible.value = true
+}
+
+const submitText = (val: string) => {
+  const userCache: any = localStorage.getItem('jesk-userInfo')
+  const userInfo = JSON.parse(userCache)
+  if (userInfo?.data) {
+    const iconData = JSON.parse(userInfo.data)
+    userInfo.icon = iconData?.relevantCertificates[0]?.md5 ?? ''
+  }
+  const textObj = {
+    content: val == '1' ? textarea.value : talkContent.value,
+    publisher: userInfo?.name ?? '',
+    publishRole: userInfo?.role ?? '',
+    icon: userInfo.icon ?? '',
+    type: userInfo.type ?? ''
+  }
+  const data = {
+    description: '',
+    icon: '',
+    state: 'Normal',
+    parentId: ownData?.value.id,
+    topicIdOrRefCode: String(talkTopicInfo.value.id),
+    name: userInfo?.name,
+    content: JSON.stringify(textObj),
+    type: 'Normal',
+    cmsTypeRefCode: '',
+    newDataListRequest: []
+  }
+  MG.ugc.newTopicMessage(data).then((res: any) => {
+    if (res) {
+      ElMessage({
+        message: '宸插洖澶�',
+        type: 'success'
+      })
+      dialogVisible.value = false
+      textarea.value = ''
+      getMessageChildren()
+    }
+  })
+}
+
+// 鑾峰彇璇濋topic
+const getTopicInfo = () => {
+  const pramas = {
+    classId: classInfo.id,
+    refCodes: [config.refCodes.talk]
+  }
+  MG.edu.getClassTopic(pramas).then((res: any) => {
+    const list = res
+    talkTopicInfo.value = list.find((item: any) => item.refCode == config.refCodes.talk)
+    if (talkTopicInfo.value.id) {
+      getMessage()
+    }
+  })
+}
+
+// 鑾峰彇褰撳墠璇濋
+const getMessage = () => {
+  isLoading.value = true
+  const data = {
+    start: 0,
+    size: 1,
+    searchList: [
+      {
+        keywords: classInfo.MessageName,
+        field: 'Name',
+        compareType: 'Contains'
+      }
+    ],
+    appRefCode: config.appRefCode,
+    topicIdOrRefCode: String(talkTopicInfo.value.id)
+  }
+  MG.ugc.getTopicMessageList(data).then((res: any) => {
+    const list = res.datas
+    isLoading.value = false
+    list.map((item: any) => {
+      const str = item.content.indexOf('publisher')
+      if (str > -1) {
+        item.publicText = JSON.parse(item.content)
+        if (item.publicText && item.publicText.publishRole) {
+          item.publicText.publishRole = item.publicText.publishRole == 'Teacher' ? '鍔╂暀' : '瀛︾敓'
+        }
+      }
+      item.createDate = moment(item.createDate).format('YYYY-MM-DD HH:mm:ss')
+      item.updateDate = moment(item.updateDate).format('YYYY-MM-DD HH:mm:ss')
+      return {
+        ...item
+      }
+    })
+    ownData.value = list[0]
+    getMessageChildren()
+  })
+}
+
+// 鑾峰彇褰撳墠璇濋鐨勫洖澶嶆秷鎭�
+const getMessageChildren = () => {
+  childLoading.value = true
+  const data = {
+    start: 0,
+    size: 999,
+    parentId: ownData?.value.id,
+    topicIdOrRefCode: String(talkTopicInfo.value.id)
+  }
+  MG.ugc.getTopicMessageSubList(data).then((res: any) => {
+    const list = res.datas
+    childLoading.value = false
+    dataList.value = list.map((item: any) => {
+      const str = item.content.indexOf('publisher')
+      if (str > -1) {
+        item.publicText = JSON.parse(item.content)
+        if (item.publicText && item.publicText.publishRole) {
+          item.publicText.publishRole = item.publicText.publishRole == 'Teacher' ? '鍔╂暀' : '瀛︾敓'
+        }
+        if (item.publicText?.icon && item.publicText?.type == 'teacherInfo') {
+          item.publicText.icon = getPublicImage(item.publicText?.icon, 60)
+        }
+      }
+      item.createDate = moment(item.createDate).format('YYYY-MM-DD HH:mm:ss')
+      item.updateDate = moment(item.updateDate).format('YYYY-MM-DD HH:mm:ss')
+      return {
+        ...item
+      }
+    })
+  })
+}
+
+// 鍒犻櫎鍥炲璇濋
+const removeMessageItem = (item: any) => {
+  const data = {
+    messageIds: [item.id]
+  }
+  MG.ugc.delTopicMessage(data).then((res: any) => {
+    if (res) {
+      ElMessage({
+        message: '宸插垹闄�',
+        type: 'success'
+      })
+    }
+    getMessage()
+  })
+}
+
+// 瀹℃牳璇濋
+const pubTalk = (item: any) => {
+  const data = {
+    id: item.id,
+    name: item.name,
+    description: item.description,
+    icon: item.icon,
+    type: item.type,
+    state: 'Normal',
+    content: JSON.stringify(item.publicText),
+    newDataRequests: [],
+    updateDataRequests: []
+  }
+  MG.ugc
+    .updateTopicMessage(data)
+    .then((res: any) => {
+      if (res) {
+        ElMessage({
+          type: 'success',
+          message: '宸插彂甯�'
+        })
+        getMessage()
+      }
+    })
+    .catch((err: any) => {
+      console.log(err, '瀹℃牳璇濋')
+    })
+}
+
+const goBack = () => {
+  router.go(-1)
+}
+</script>
+
+<style lang="less" scoped>
+.classManagePage-box {
+  // padding: 20px 0;
+  background: #fff;
+
+  .classManagePage-nav {
+    width: 100%;
+    padding: 0 20px;
+    height: 40px;
+    border-bottom: 1px solid #e6e8ed;
+    position: sticky;
+    top: 0;
+    z-index: 999;
+    display: flex;
+    align-items: center;
+    background: #fff;
+  }
+  .classManagePage-content {
+    width: 100%;
+    position: relative;
+    .backBtn {
+      width: 100%;
+      height: 45px;
+      margin-bottom: 10px;
+      padding: 0 20px;
+      display: flex;
+      align-items: center;
+      position: sticky;
+      top: 40px;
+      z-index: 99;
+      background: #fff;
+      box-shadow: 0px 0px 20px 1px #eee;
+    }
+    .talkBox {
+      width: 100%;
+      display: flex;
+      justify-content: space-between;
+      align-items: flex-start;
+      padding: 0 20px;
+      .leftBox {
+        flex: 1;
+        min-width: 500px;
+        min-height: 700px;
+        background: #ffffff;
+        box-shadow: 0px 0px 10px 1px rgba(0, 0, 0, 0.08);
+        border-radius: 5px 5px 5px 5px;
+        border: 1px solid #e7eaec;
+        margin-right: 20px;
+        .MessageCount {
+          padding: 0 30px;
+          width: 100%;
+          height: 60px;
+          border-bottom: 1px solid #e7eaec;
+          line-height: 60px;
+        }
+        :deep(.inputBox) {
+          padding: 20px 30px;
+          position: relative;
+
+          .el-textarea__inner {
+            padding: 15px;
+            padding-bottom: 45px;
+            box-sizing: border-box;
+          }
+
+          .submit {
+            position: absolute;
+            bottom: 30px;
+            right: 40px;
+          }
+        }
+        .MessageBox {
+          width: 100%;
+          padding: 0 30px;
+          .MessageHeader {
+            width: 100%;
+            display: flex;
+            justify-content: space-between;
+            align-items: center;
+            .userBox {
+              display: flex;
+              align-items: center;
+              .userName {
+                margin: 0 20px;
+              }
+            }
+          }
+          .MessageContent {
+            padding: 0 60px;
+            padding-bottom: 20px;
+            margin-bottom: 10px;
+            font-family: PingFang SC;
+            font-weight: 400;
+            font-size: 13px;
+            color: #333333;
+            line-height: 25px;
+            border-bottom: 1px solid #e7eaec;
+          }
+        }
+      }
+      .rightBox {
+        width: 650px;
+        min-width: 500px;
+        height: 650px;
+        background: #ffffff;
+        box-shadow: 0px 0px 10px 1px rgba(0, 0, 0, 0.08);
+        border-radius: 5px 5px 5px 5px;
+        border: 1px solid #e7eaec;
+        position: sticky;
+        top: 95px;
+        z-index: 99;
+        background: #fff;
+        .talkHeader {
+          width: 100%;
+          padding: 0 30px;
+          height: 60px;
+          display: flex;
+          justify-content: space-between;
+          align-items: center;
+          border-bottom: 1px solid #e7eaec;
+
+          .talkUser {
+            display: flex;
+            align-items: center;
+            .userName {
+              margin-left: 20px;
+            }
+          }
+        }
+        .talkContent {
+          width: 100%;
+          height: calc(100% - 60px);
+          overflow: auto;
+
+          padding: 20px 30px;
+          .contentTilte {
+            font-family: PingFang SC;
+            font-weight: bold;
+            font-size: 16px;
+            color: #333333;
+            margin-bottom: 20px;
+          }
+          .contentText {
+            font-family: PingFang SC;
+            font-weight: 400;
+            font-size: 13px;
+            color: #333333;
+            line-height: 30px;
+            text-align: left;
+            word-break: break-all;
+            word-wrap: break-word;
+          }
+        }
+      }
+    }
+  }
+}
+</style>
diff --git a/src/views/classManage/talkingPoint.vue b/src/views/classManage/talkingPoint.vue
new file mode 100644
index 0000000..a28c035
--- /dev/null
+++ b/src/views/classManage/talkingPoint.vue
@@ -0,0 +1,375 @@
+<template>
+  <div class="classManagePage-box">
+    <div class="classManagePage-nav">
+      <el-breadcrumb :separator-icon="ArrowRight">
+        <el-breadcrumb-item>鎴戠殑鐝骇</el-breadcrumb-item>
+        <el-breadcrumb-item>{{ classInfo?.name }}</el-breadcrumb-item>
+        <el-breadcrumb-item>璇濋</el-breadcrumb-item>
+      </el-breadcrumb>
+    </div>
+    <div class="classManagePage-content">
+      <div class="headerBox">
+        <div class="searchBox">
+          <el-input
+            v-model="searchKey"
+            @clear="searchData()"
+            @keydown.enter="searchData()"
+            clearable
+            placeholder="鎼滅储璇濋鍚嶇О"
+          >
+            <template #append>
+              <el-button type="primary" class="searchBtn" @click="searchData()" :icon="Search" />
+            </template>
+          </el-input>
+        </div>
+        <el-button @click="openTalk()" v-if="userInfo?.role == 'Teacher'" type="primary" round>
+          鏂板缓 <el-icon><Plus /></el-icon>
+        </el-button>
+      </div>
+      <div class="listBox">
+        <el-table
+          :header-cell-style="{ background: '#eee' }"
+          :data="dataList"
+          border
+          v-loading="isLoading"
+          style="width: 100%"
+        >
+          <el-table-column prop="index" label="搴忓彿" width="70" />
+          <el-table-column label="璇濋鍚嶇О" width="500">
+            <template #default="scope">
+              <span style="color: #ff6c00" v-if="scope.row.name">{{ scope.row.name }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column prop="createDate" label="鍙戣捣鏃ユ湡" />
+          <el-table-column label="鍙戣捣浜�">
+            <template #default="scope">
+              <span v-if="scope.row.publicText">{{ scope.row.publicText.publisher }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column label="鍙戣捣浜鸿鑹�">
+            <template #default="scope">
+              <span v-if="scope.row.publicText?.publishRole == 'Teacher'">鍔╂暀</span>
+              <span v-else>瀛︾敓</span>
+            </template>
+          </el-table-column>
+          <el-table-column prop="updateDate" label="鍙戣捣浜烘渶鍚庡洖澶嶆棩鏈�" />
+          <el-table-column label="鎿嶄綔" width="180px">
+            <template #default="scope">
+              <el-button
+                link
+                type="primary"
+                v-if="scope.row.state == 'Normal'"
+                @click="toDetail(scope.row)"
+                >璇︽儏</el-button
+              >
+              <el-button
+                link
+                type="success"
+                v-if="scope.row.state != 'Normal'"
+                @click="pubTalk(scope.row)"
+                >鍙戝竷</el-button
+              >
+              <el-button
+                link
+                type="danger"
+                v-if="userInfo.role == 'Teacher'"
+                @click="delMessageItem(scope.row)"
+                >鍒犻櫎</el-button
+              >
+            </template>
+          </el-table-column>
+        </el-table>
+        <el-pagination
+          style="float: right"
+          v-model:current-page="pages.page"
+          :page-size="pages.pageSize"
+          layout="total, prev, pager, next"
+          :total="pages.count"
+          @size-change="handleSizeChange"
+          @current-change="handleCurrentChange"
+        />
+      </div>
+      <el-dialog v-model="dialogVisible" title="鏂板缓璇濋" width="800">
+        <div class="talkWall">
+          <div class="talKBox">
+            <span>璇濋鏍囬锛�</span>
+            <el-input v-model="talkTitle" style="width: 440px" placeholder="璇疯緭鍏ユ爣棰�" />
+          </div>
+          <div class="talKBox">
+            <span>璇濋鍐呭锛�</span>
+            <el-input
+              style="flex: 1"
+              v-model="talkContent"
+              :autosize="{ minRows: 10, maxRows: 15 }"
+              type="textarea"
+              placeholder="璇疯緭鍏ュ唴瀹�"
+            />
+          </div>
+        </div>
+        <template #footer>
+          <div class="dialog-footer">
+            <el-button @click="dialogVisible = false"> 鍙栨秷 </el-button>
+            <el-button type="primary" @click="createMessage()"> 纭 </el-button>
+          </div>
+        </template>
+      </el-dialog>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { reactive, ref, onMounted, inject, watch } from 'vue'
+import { useRoute, useRouter } from 'vue-router'
+import { Search, ArrowRight } from '@element-plus/icons-vue'
+import { ElMessage } from 'element-plus'
+import moment from 'moment'
+const route: any = useRoute()
+const router = useRouter()
+const MG: any = inject('MG')
+const config: any = inject('config')
+const classInfo = JSON.parse(route.query.classInfo)
+const userInfo = ref()
+
+const searchKey = ref('')
+const talkTitle = ref('')
+const talkContent = ref('')
+const dialogVisible = ref(false)
+const talkTopicInfo = ref()
+const dataList = ref([])
+const isLoading = ref(false)
+let pages = reactive({
+  page: 1,
+  pageSize: 10,
+  count: 0,
+  loading: false
+})
+
+onMounted(() => {
+  const userCache: any = localStorage.getItem('jesk-userInfo')
+  if (userCache) {
+    userInfo.value = JSON.parse(userCache)
+  }
+  getTopicInfo()
+})
+
+const handleSizeChange = (val: number) => {
+  pages.pageSize = val
+  getMessage()
+}
+
+const handleCurrentChange = (val: number) => {
+  pages.page = val
+  getMessage()
+}
+
+const searchData = () => {
+  pages.page = 1
+  pages.pageSize = 10
+  getMessage()
+}
+
+// 鑾峰彇璇濋topic
+const getTopicInfo = () => {
+  const pramas = {
+    classId: classInfo.id,
+    refCodes: [config.refCodes.talk]
+  }
+  MG.edu.getClassTopic(pramas).then((res: any) => {
+    const list = res
+    talkTopicInfo.value = list.find((item: any) => item.refCode == config.refCodes.talk)
+    if (talkTopicInfo.value.id) {
+      getMessage()
+    }
+  })
+}
+
+//  鏂板缓璇濋
+const createMessage = () => {
+  if (talkTitle.value == '') {
+    ElMessage({
+      message: '璇峰~鍐欐爣棰�',
+      type: 'warning'
+    })
+    return false
+  }
+  if (talkContent.value == '') {
+    ElMessage({
+      message: '璇峰~鍐欏唴瀹�',
+      type: 'warning'
+    })
+    return false
+  }
+  newTalkMessage()
+}
+
+// 璇濋璇︽儏
+const toDetail = (item: any) => {
+  const obj = classInfo
+  obj.MessageName = item.name
+  router.push({
+    path: '/talkDetail',
+    query: {
+      classInfo: JSON.stringify(obj)
+    }
+  })
+}
+
+const newTalkMessage = () => {
+  const userCache: any = localStorage.getItem('jesk-userInfo')
+  const userInfo = JSON.parse(userCache)
+  const textObj = {
+    content: talkContent.value,
+    publisher: userInfo?.name ?? '',
+    publishRole: userInfo?.role ?? '',
+    icon: userInfo.icon ?? ''
+  }
+  const data = {
+    description: '',
+    icon: '',
+    state: 'Normal',
+    topicIdOrRefCode: String(talkTopicInfo.value.id),
+    name: talkTitle.value,
+    content: JSON.stringify(textObj),
+    type: 'Normal',
+    cmsTypeRefCode: '',
+    newDataListRequest: []
+  }
+  MG.ugc.newTopicMessage(data).then((res: any) => {
+    if (res) {
+      dialogVisible.value = false
+      getMessage()
+    }
+  })
+}
+
+// 鑾峰彇鐝骇璇濋
+const getMessage = () => {
+  isLoading.value = true
+  const data = {
+    start: (pages.page - 1) * pages.pageSize,
+    size: pages.pageSize,
+    appRefCode: config.appRefCode,
+    topicIdOrRefCode: String(talkTopicInfo.value.id),
+    searchList: searchKey.value
+      ? [
+          {
+            keywords: searchKey.value,
+            field: 'Name',
+            compareType: 'Contains'
+          }
+        ]
+      : []
+  }
+  MG.ugc.getTopicMessageList(data).then((res: any) => {
+    const list = res.datas
+    pages.count = res.totalSize
+    isLoading.value = false
+    dataList.value = list.map((item: any, i: number) => {
+      const str = item.content.indexOf('publisher')
+      if (str > -1) {
+        item.publicText = JSON.parse(item.content)
+      }
+      return {
+        ...item,
+        index: i + 1,
+        createDate: moment(item.createDate).format('YYYY-MM-DD HH:mm:ss'),
+        updateDate: moment(item.updateDate).format('YYYY-MM-DD HH:mm:ss')
+      }
+    })
+  })
+}
+
+// 鍒犻櫎璇濋
+const delMessageItem = (item: any) => {
+  const data = {
+    messageIds: [item.id]
+  }
+  MG.ugc
+    .delTopicMessage(data)
+    .then((res: any) => {
+      if (res) {
+        ElMessage.success('宸插垹闄�')
+        getTopicInfo()
+      }
+    })
+    .catch((err: any) => {
+      ElMessage.error('鍒犻櫎澶辫触锛岃绋嶅悗鍐嶈瘯')
+      console.log(err)
+    })
+}
+
+// 瀹℃牳璇濋
+const pubTalk = (item: any) => {
+  const data = {
+    id: item.id,
+    name: item.name,
+    description: item.description,
+    icon: item.icon,
+    type: item.type,
+    state: 'Normal',
+    content: JSON.stringify(item.publicText),
+    newDataRequests: [],
+    updateDataRequests: []
+  }
+  MG.ugc
+    .updateTopicMessage(data)
+    .then((res: any) => {
+      if (res) {
+        ElMessage({
+          type: 'success',
+          message: '宸插彂甯�'
+        })
+        getMessage()
+      }
+    })
+    .catch((err: any) => {
+      console.log(err, '瀹℃牳璇濋')
+    })
+}
+
+const openTalk = () => {
+  dialogVisible.value = true
+}
+</script>
+
+<style lang="less" scoped>
+.classManagePage-box {
+  padding: 20px;
+  .classManagePage-nav {
+    padding-bottom: 20px;
+    border-bottom: 1px solid #e6e8ed;
+  }
+  .classManagePage-content {
+    .headerBox {
+      padding: 20px 0;
+      overflow: hidden;
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+      .searchBox {
+        width: 300px;
+        float: left;
+        .searchBtn {
+          background-color: var(--el-color-primary);
+          color: #fff;
+          border-top-left-radius: 0;
+          border-bottom-left-radius: 0;
+        }
+      }
+    }
+  }
+}
+.headerCellClass {
+  background-color: red !important;
+}
+
+.talkWall {
+  width: 100%;
+  height: auto;
+  .talKBox {
+    display: flex;
+    align-items: baseline;
+    margin-bottom: 20px;
+  }
+}
+</style>
diff --git a/src/views/classManage/teachInteraction.vue b/src/views/classManage/teachInteraction.vue
new file mode 100644
index 0000000..95b8898
--- /dev/null
+++ b/src/views/classManage/teachInteraction.vue
@@ -0,0 +1,512 @@
+<template>
+  <div class="classManagePage-box">
+    <div class="classManagePage-nav">
+      <el-breadcrumb :separator-icon="ArrowRight">
+        <el-breadcrumb-item>鎴戠殑鐝骇</el-breadcrumb-item>
+        <el-breadcrumb-item>{{ classInfo?.name }}</el-breadcrumb-item>
+        <el-breadcrumb-item>鏁欏浜掑姩</el-breadcrumb-item>
+      </el-breadcrumb>
+    </div>
+    <div class="classManagePage-content">
+      <div class="teachPlaneBox">
+        <div class="titleBox">
+          <div class="titleOptions">
+            <span>鏁欏浜掑姩</span>
+          </div>
+          <div class="searchBox">
+            <el-input
+              v-model="searchKey"
+              clearable
+              @clear="searchData()"
+              placeholder="璇疯緭鍏ュ叧閿瓧"
+              @keydown.enter="searchData()"
+            >
+              <template #append>
+                <el-button type="primary" @click="searchData()" class="searchBtn" :icon="Search" />
+              </template>
+            </el-input>
+          </div>
+        </div>
+      </div>
+      <div class="listBox">
+        <el-table
+          :header-cell-style="{ background: '#eee' }"
+          :data="cmsDataList"
+          max-height="700px"
+          style="width: 100%"
+          v-loading="cmsLoading"
+        >
+          <el-table-column prop="id" label="搴忓彿" width="100" />
+          <el-table-column prop="name" label="鏍囬" width="500" />
+          <el-table-column prop="address" label="宸蹭簰鍔ㄥ鐢熸暟" #default="scoped">
+            <div>
+              <span style="color: #ff6d00">{{ scoped.row.subList.length }}</span>
+            </div>
+          </el-table-column>
+          <el-table-column prop="address" label="鏈�鍚庢彁浜ゆ椂闂�" #default="scoped">
+            <span v-if="scoped.row.updateDate"> {{ scoped.row.updateDate }} </span>
+            <span v-else> - </span>
+          </el-table-column>
+          <el-table-column prop="address" label="鎿嶄綔" #default="scoped">
+            <el-button link type="success" @click="toDetail(scoped.row)">鏌ョ湅璇︽儏</el-button>
+            <el-button link style="color: #409eff" @click="getQuestions(scoped.row)"
+              >娴忚绛旈</el-button
+            >
+          </el-table-column>
+        </el-table>
+        <!-- 娴忚绛旈 -->
+        <el-dialog
+          class="customDialog"
+          title="娴忚绛旈"
+          v-model="visible"
+          destroy-on-close
+          width="1000"
+          align-center
+          :before-close="close"
+        >
+          <div class="pubContent" v-if="dialogList.length > 0 && !dialogLLoading">
+            <div v-for="(item, index) in dialogList" :key="index">
+              <span class="userName">绛旈浜猴細{{ item.userName ?? '-' }}</span>
+              <question-dom
+                v-if="item.questionTypeList.length > 0"
+                :questionList="item.questionTypeList"
+                :noCheckbox="false"
+                :is-preview="true"
+                :is-interaction="true"
+              />
+            </div>
+          </div>
+          <div class="pubContent" v-if="dialogLLoading" v-loading="dialogLLoading"></div>
+          <div class="pubContent noData" v-if="dialogList.length == 0 && !dialogLLoading">
+            <el-empty></el-empty>
+          </div>
+          <template #footer>
+            <div class="selectedFooter" style="padding: 0">
+              <el-button type="primary" @click="visible = false"> 鍏抽棴 </el-button>
+            </div>
+          </template>
+        </el-dialog>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { Search, ArrowRight } from '@element-plus/icons-vue'
+import moment from 'moment'
+import { ref, onMounted, inject } from 'vue'
+import { useRoute, useRouter } from 'vue-router'
+import questionDom from './components/questionDom.vue'
+
+const route: any = useRoute()
+const router: any = useRouter()
+const MG: any = inject('MG')
+const config: any = inject('config')
+const classInfo = JSON.parse(route.query.classInfo)
+const userInfo = ref()
+
+const teachInteractionInfo: any = ref([])
+const searchKey = ref('')
+const dataList: any = ref([])
+const currentClass = ref()
+const cmsDataList: any = ref([])
+const cmsLoading = ref(true)
+
+const visible = ref(false)
+const dialogList: any = ref([])
+const dialogLLoading = ref(true)
+const defaultCmsPath = ref('')
+
+onMounted(() => {
+  const userCache: any = localStorage.getItem('jesk-userInfo')
+  if (userCache) {
+    userInfo.value = JSON.parse(userCache)
+  }
+  defaultCmsPath.value = classInfo.bookRefCode ? 'jsek_digitalTextbooks' : config.goodsStore
+  getData()
+})
+
+const searchData = () => {
+  const data = [...cmsDataList.value]
+  if (!searchKey.value) {
+    getCmsList()
+  } else {
+    const list = data.filter((item) => item.name.indexOf(searchKey.value) > -1)
+    cmsDataList.value = list
+  }
+}
+
+const close = () => {
+  visible.value = false
+}
+
+// 鑾峰彇鏁欏浜掑姩
+const getCmsList = () => {
+  cmsLoading.value = true
+  cmsDataList.value = []
+  try {
+    MG.store
+      .getProductDetail({
+        path: defaultCmsPath.value,
+        queryType: '*',
+        productId: classInfo.bookId,
+        storeInfo: defaultCmsPath.value,
+        cmsPath: classInfo.rootCmsItemId
+      })
+      .then((res: any) => {
+        try {
+          const data = res.datas?.cmsDatas[0]?.datas.find(
+            (item: any) => item.refCode == 'questionBank'
+          )
+          MG.store
+            .getProductDetail({
+              path: defaultCmsPath.value,
+              queryType: '*',
+              storeInfo: defaultCmsPath.value,
+              productId: classInfo.bookId,
+              cmsPath: data.productLinkPath
+            })
+            .then((res: any) => {
+              try {
+                const dataTeach = res.datas.cmsDatas[0]?.datas.find(
+                  (item: any) => item.refCode == 'jsek_interaction'
+                )
+                MG.store
+                  .getProductDetail({
+                    path: defaultCmsPath.value,
+                    queryType: '*',
+                    productId: classInfo.bookId,
+                    storeInfo: defaultCmsPath.value,
+                    cmsPath: dataTeach.productLinkPath
+                  })
+                  .then((res: any) => {
+                    let datas = res.datas.cmsDatas[0] ? res.datas.cmsDatas[0].datas : []
+                    if (datas?.length > 0) {
+                      datas.forEach((item: any) => {
+                        MG.store
+                          .getProductDetail({
+                            path: defaultCmsPath.value,
+                            queryType: '*',
+                            productId: classInfo.bookId,
+                            storeInfo: defaultCmsPath.value,
+                            cmsPath: item.productLinkPath,
+                            cmsSort: {
+                              ProductLinkOrder: 'Desc'
+                            }
+                          })
+                          .then(async (cmsRes: any) => {
+                            cmsLoading.value = false
+                            if (
+                              cmsRes.datas.cmsDatas[0].datas &&
+                              cmsRes.datas.cmsDatas[0].datas.length > 0
+                            ) {
+                              cmsRes.datas.cmsDatas[0].datas.forEach((item: any) => {
+                                item.subList = []
+                                if (dataList.value.length > 0) {
+                                  dataList.value.forEach((mitem: any) => {
+                                    if (mitem.name == item.name) {
+                                      item.updateDate = moment(dataList.value[0].updateDate).format(
+                                        'YYYY-MM-DD HH:mm:ss'
+                                      )
+                                      item.subList.push(mitem)
+                                    }
+                                  })
+                                }
+                                cmsDataList.value.push(item)
+                              })
+                            }
+                          })
+                      })
+                    }
+                  })
+              } catch (error) {
+                cmsLoading.value = false
+                cmsDataList.value = []
+              }
+            })
+        } catch (error) {
+          cmsLoading.value = false
+          cmsDataList.value = []
+        }
+      })
+  } catch (error) {
+    cmsLoading.value = false
+    cmsDataList.value = []
+  }
+}
+
+// 鑾峰彇Messsagetopic
+const getTopicInfo = () => {
+  const pramas = {
+    classId: classInfo.id,
+    refCodes: [config.refCodes.teachInteraction]
+  }
+  MG.edu.getClassTopic(pramas).then((res: any) => {
+    const list = res
+    teachInteractionInfo.value = list.find(
+      (item: any) => item.refCode == config.refCodes.teachInteraction
+    )
+    if (teachInteractionInfo.value.id) {
+      getMessage()
+    }
+  })
+}
+
+// 鑾峰彇褰撳墠MessageList
+const getMessage = () => {
+  const data = {
+    start: 0,
+    size: 999,
+    appRefCode: config.appRefCode,
+    topicIdOrRefCode: String(teachInteractionInfo.value.id),
+    sort: {
+      type: 'Desc',
+      field: 'CreateDate'
+    },
+    searchList: searchKey.value
+      ? [
+          {
+            keywords: searchKey.value,
+            field: 'Name',
+            compareType: 'Contains'
+          }
+        ]
+      : []
+  }
+  MG.ugc.getTopicMessageList(data).then((res: any) => {
+    dataList.value = res.datas.map((item: any) => {
+      item.question = []
+      item.bookId = null
+      item.path = ''
+      try {
+        const obj = JSON.parse(item.content)
+        if (obj.bookId) {
+          item.question = obj.content.map((citem: any) => {
+            return {
+              ...citem,
+              updateDate: moment(item.updateDate).format('YYYY-MM-DD HH:mm:ss'),
+              userId: item.appUserCreator.userId
+            }
+          })
+          item.bookId = obj.bookId
+          item.path = obj.path
+          item.userName = obj.userName
+        }
+      } catch (error) {
+        console.log(item)
+      }
+      return {
+        ...item
+      }
+    })
+    console.log(dataList.value, 'datal')
+    getCmsList()
+  })
+}
+
+// 鑾峰彇鐝骇
+const getData = () => {
+  MG.edu
+    .getCourseClass({
+      ClassIdOrRefCode: String(classInfo.id)
+    })
+    .then((res: any) => {
+      if (res) {
+        currentClass.value = res
+      }
+      getTopicInfo()
+    })
+}
+
+// 鑾峰彇棰樼洰鍒楄〃
+const getQuestions = (pitem: any) => {
+  visible.value = true
+  dialogLLoading.value = true
+  MG.store
+    .getProductDetail({
+      path: '*',
+      queryType: '*',
+      productId: classInfo.bookId,
+      cmsPath: pitem.productLinkPath,
+      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: any) => {
+      try {
+        let list = []
+        list = res.datas.cmsDatas[0]?.datas.map((item: any) => {
+          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,
+              updateDate: pitem.updateDate
+            }
+          } catch (error) {
+            console.log(item)
+          }
+        })
+        dialogList.value = chageData(pitem.subList, list)
+        dialogLLoading.value = false
+      } catch (error) {
+        dialogList.value = []
+        dialogLLoading.value = false
+      }
+    })
+}
+
+// 澶勭悊鏁版嵁缁撴瀯
+const chageData = (arr: any, zrr: any) => {
+  // 棰樺簱棰樼洰绫诲瀷
+  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 = JSON.parse(JSON.stringify(questionTypeList))
+    item.other = []
+    for (let j = 0; j < item.question.length; j++) {
+      const ele = item.question[j]
+      const data = zrr.find((sitem: any) => sitem.id == ele.cmsItemId)
+      const index = findIndexById(zrr, ele.cmsItemId)
+      if (index > -1) {
+        item.other[index] = { ...data, userAnswer: ele.answer }
+      }
+    }
+    if (item.other.length > 0) {
+      item.other.forEach((aitem: any) => {
+        const index = findIndexByValue(item.questionTypeList, aitem.questionType)
+        if (index > -1) {
+          item.questionTypeList[index].data.push(aitem)
+        }
+      })
+    }
+    item.questionTypeList = item.questionTypeList.filter((xitem: any) => xitem.data.length > 0)
+  }
+  return arr
+}
+
+const findIndexByValue = (res: any, type: string) => {
+  for (let i = 0; i < res.length; i++) {
+    if (res[i].value == type) {
+      return i
+    }
+  }
+  return -1 // 濡傛灉鏈壘鍒帮紝鍒欒繑鍥� -1
+}
+
+const findIndexById = (res: any, id: string) => {
+  for (let i = 0; i < res.length; i++) {
+    if (res[i].id == id) {
+      return i
+    }
+  }
+  return -1 // 濡傛灉鏈壘鍒帮紝鍒欒繑鍥� -1
+}
+
+// 鍘昏鎯�
+const toDetail = (item: any) => {
+  const obj = classInfo
+  obj.questionName = item.name
+  obj.teachInteractionId = teachInteractionInfo.value.id
+  router.push({
+    path: '/interactionDetail',
+    query: {
+      classInfo: JSON.stringify(obj)
+    }
+  })
+}
+</script>
+
+<style lang="less" scoped>
+.classManagePage-box {
+  padding: 20px;
+  .classManagePage-nav {
+    padding-bottom: 20px;
+    border-bottom: 1px solid #e6e8ed;
+    margin-bottom: 20px;
+  }
+  .classManagePage-content {
+    width: 100%;
+    .teachPlaneBox {
+      width: 100%;
+      .titleBox {
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        margin-bottom: 20px;
+        .titleOptions {
+          width: 160px;
+          display: flex;
+          justify-content: space-between;
+          align-items: center;
+          span {
+            height: 30px;
+            font-family: PingFang SC;
+            font-weight: bold;
+            font-size: 16px;
+            color: #333;
+            line-height: 30px;
+            text-align: left;
+            border-left: 6px solid #ff6c00;
+            padding-left: 10px;
+          }
+        }
+        .searchBox {
+          width: 300px;
+          float: left;
+          .searchBtn {
+            background-color: var(--el-color-primary);
+            color: #fff;
+            border-top-left-radius: 0;
+            border-bottom-left-radius: 0;
+          }
+        }
+      }
+    }
+    .pubContent {
+      height: 80vh;
+      padding: 10px;
+      box-sizing: border-box;
+      overflow-y: auto;
+      .userName {
+        color: #ff6d00;
+      }
+    }
+  }
+}
+</style>
diff --git a/src/views/classManage/teachingPlan.vue b/src/views/classManage/teachingPlan.vue
new file mode 100644
index 0000000..3c1f67b
--- /dev/null
+++ b/src/views/classManage/teachingPlan.vue
@@ -0,0 +1,855 @@
+<template>
+  <div class="classManagePage-box">
+    <div class="classManagePage-nav">
+      <el-breadcrumb :separator-icon="ArrowRight">
+        <el-breadcrumb-item>鎴戠殑鐝骇</el-breadcrumb-item>
+        <el-breadcrumb-item>{{ classInfo?.name }}</el-breadcrumb-item>
+        <el-breadcrumb-item>鏁欏璁″垝</el-breadcrumb-item>
+      </el-breadcrumb>
+    </div>
+    <div class="classManagePage-content">
+      <div class="teachPlaneBox">
+        <div class="titleBox">
+          <div class="titleOptions">
+            <span>鏁欏璁″垝</span>
+            <el-button v-if="userInfo?.role == 'Teacher'" @click="openPlan()" type="primary" round
+              >鏂板缓 <el-icon style="margin-left: 3px"><Plus /></el-icon
+            ></el-button>
+          </div>
+          <div class="searchBox">
+            <el-input
+              v-model="searchKey"
+              clearable
+              @clear="searchData()"
+              placeholder="璇疯緭鍏ュ叧閿瓧"
+              @keydown.enter="searchData()"
+            >
+              <template #append>
+                <el-button type="primary" @click="searchData()" class="searchBtn" :icon="Search" />
+              </template>
+            </el-input>
+          </div>
+        </div>
+        <div class="listBox">
+          <el-table
+            :header-cell-style="{ background: '#eee' }"
+            :data="tableData"
+            max-height="600px"
+            style="width: 100%"
+            v-loading="pages.loading"
+          >
+            <el-table-column label="搴忓彿" width="70">
+              <template #default="scope">
+                <span v-if="scope.row.datas.index">{{ scope.row.datas.index }}</span>
+              </template>
+            </el-table-column>
+            <el-table-column label="鍚嶇О" prop="name">
+              <template #default="scope">
+                <span v-if="scope.row.datas.Name">{{ scope.row.datas.Name }}</span>
+              </template>
+            </el-table-column>
+            <el-table-column label="瀛︿範绔犺妭" width="300">
+              <template #default="scope">
+                <div v-if="scope.row.datas.selectChapter?.length > 0">
+                  <div
+                    @click="toRead(item)"
+                    class="linkTitle"
+                    v-for="(item, index) in scope.row.datas.selectChapter"
+                    :key="index"
+                  >
+                    {{ item.parentName }}
+                  </div>
+                </div>
+              </template>
+            </el-table-column>
+            <el-table-column label="涓婁紶璧勬簮">
+              <template #default="scope">
+                <div v-if="scope.row.datas.uploadResources?.length > 0">
+                  <span
+                    @click="downloadRes(item)"
+                    class="linkTitle"
+                    v-for="(item, index) in scope.row.datas.uploadResources"
+                    :key="index"
+                  >
+                    {{ item.FileName + '.' + item.Extension }}
+                  </span>
+                </div>
+              </template>
+            </el-table-column>
+            <el-table-column label="鍙傝�冭祫鏂�" width="300">
+              <template #default="scope">
+                <span v-if="scope.row.datas.referenceMaterial">{{
+                  scope.row.datas.referenceMaterial
+                }}</span>
+              </template>
+            </el-table-column>
+            <el-table-column label="璇存槑" width="300">
+              <template #default="scope">
+                <span v-if="scope.row.datas.explain">{{ scope.row.datas.explain }}</span>
+              </template>
+            </el-table-column>
+            <el-table-column v-if="userInfo?.role == 'Teacher'" label="鎿嶄綔" width="150">
+              <template #default="scope">
+                <!-- <el-button
+                  v-if="scope.row"
+                  @click="editOpen(scope.row)"
+                  link
+                  type="primary"
+                  size="small"
+                >
+                  缂栬緫
+                </el-button> -->
+                <el-button
+                  v-if="scope.row"
+                  @click="removeTaskItem(scope.row)"
+                  link
+                  type="danger"
+                  size="small"
+                >
+                  绉婚櫎
+                </el-button>
+              </template>
+            </el-table-column>
+          </el-table>
+          <el-pagination
+            style="float: right"
+            v-model:current-page="pages.page"
+            :page-size="pages.pageSize"
+            layout="total, prev, pager, next"
+            :total="pages.count"
+            @size-change="handleSizeChange"
+            @current-change="handleCurrentChange"
+          />
+        </div>
+      </div>
+      <el-dialog v-model="visible" destroy-on-close title="鏂板缓鏁欏璁″垝" width="1000">
+        <div class="formBox">
+          <el-row>
+            <el-col :span="2" class="labelItem">
+              <div class="grid-content ep-bg-purple" />
+              鍚嶇О<span style="color: red">*</span>
+            </el-col>
+            <el-col :span="20">
+              <div class="grid-content ep-bg-purple-light" />
+              <el-input v-model="taskItem.title" placeholder="璇峰~鍐欏悕绉�" size="large" clearable />
+            </el-col>
+          </el-row>
+          <el-row>
+            <el-col :span="2" class="labelItem">
+              <div class="grid-content ep-bg-purple" />
+              閫夋嫨绔犺妭<span style="color: red">*</span>
+            </el-col>
+            <el-col :span="20" style="position: relative" v-if="classInfo?.bookRefCode">
+              <div class="grid-content ep-bg-purple-light" />
+              <div
+                :class="dynamicList.length > 1 ? 'selectBox selectMarBot' : 'selectBox'"
+                v-for="(item, index) in dynamicList"
+                :key="index"
+              >
+                <el-cascader
+                  size="large"
+                  style="width: 620px; margin-right: 10px"
+                  :options="chapterList"
+                  clearable
+                  @change="parentSelect($event, item)"
+                >
+                  <template #default="{ node, data }">
+                    <span>{{ data.label }}</span>
+                    <span v-if="!node.isLeaf"> ({{ data.children.length }}) </span>
+                  </template>
+                </el-cascader>
+              </div>
+              <div class="btngroup">
+                <el-button type="primary" @click="addGroup" style="height: 40px" :icon="Plus" />
+                <el-button
+                  type="warning"
+                  :disabled="dynamicList.length == 1"
+                  @click="reduceGroup"
+                  style="height: 40px"
+                  :icon="Minus"
+                />
+              </div>
+            </el-col>
+            <el-col :span="20" style="position: relative" v-else>
+              <div class="grid-content ep-bg-purple-light" />
+              <div
+                :class="dynamicList.length > 1 ? 'selectBox selectMarBot' : 'selectBox'"
+                v-for="(item, index) in dynamicList"
+                :key="index"
+              >
+                <div class="inputBox">
+                  <el-input
+                    type="text"
+                    placeholder="璇疯緭鍏ョ珷"
+                    style="width: 300px; margin-right: 15px"
+                    v-model="item.parentVal"
+                  ></el-input>
+                  <el-input
+                    type="text"
+                    placeholder="璇疯緭鍏ヨ妭"
+                    style="width: 300px"
+                    v-model="item.childVal"
+                  ></el-input>
+                </div>
+                <div class="btngroup">
+                  <el-button type="primary" @click="addGroup" style="height: 40px" :icon="Plus" />
+                  <el-button
+                    type="warning"
+                    :disabled="dynamicList.length == 1"
+                    @click="reduceGroup"
+                    style="height: 40px"
+                    :icon="Minus"
+                  />
+                </div>
+              </div>
+            </el-col>
+          </el-row>
+          <el-row>
+            <el-col :span="2" class="labelItem">
+              <div class="grid-content ep-bg-purple" />
+              涓婁紶璧勬簮<span style="color: red">*</span>
+            </el-col>
+            <el-col :span="20">
+              <div class="grid-content ep-bg-purple-light" />
+              <!-- <el-upload
+                class="upload"
+                :http-request="fileUpload"
+                :show-file-list="false"
+                :action="'#'"
+              >
+                <el-button type="primary" size="large"
+                  ><el-icon size="large" style="margin-right: 5px"><DocumentAdd /></el-icon
+                  >涓婁紶</el-button
+                >
+              </el-upload> -->
+              <el-upload class="upload" drag action="#" multiple :http-request="fileUpload">
+                <el-icon class="el-icon--upload"><upload-filled /></el-icon>
+                <div class="el-upload__text">鎷栨嫿鎴栫偣鍑绘枃浠朵笂浼�</div>
+              </el-upload>
+            </el-col>
+          </el-row>
+          <el-row>
+            <el-col :span="2" class="labelItem">
+              <div class="grid-content ep-bg-purple" />
+              鍙傝�冭祫鏂�
+            </el-col>
+            <el-col :span="20">
+              <div class="grid-content ep-bg-purple-light" />
+              <el-input
+                placeholder="璇峰~鍐欏弬鑰冭祫鏂�"
+                type="textarea"
+                :rows="8"
+                size="large"
+                clearable
+                v-model="taskItem.referenceMaterial"
+              />
+            </el-col>
+          </el-row>
+          <el-row>
+            <el-col :span="2" class="labelItem">
+              <div class="grid-content ep-bg-purple" />
+              璇存槑
+            </el-col>
+            <el-col :span="20">
+              <div class="grid-content ep-bg-purple-light" />
+              <el-input
+                v-model="taskItem.explain"
+                placeholder="璇峰~鍐欒鏄�"
+                type="textarea"
+                :rows="8"
+                size="large"
+                clearable
+              />
+            </el-col>
+          </el-row>
+        </div>
+        <template #footer>
+          <div class="dialog-footer">
+            <el-button type="primary" :loading="newLoading" @click="newTaskCmsItems">
+              纭
+            </el-button>
+          </div>
+        </template>
+      </el-dialog>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { Search, ArrowRight, Plus, Minus } from '@element-plus/icons-vue'
+import { ElMessage } from 'element-plus'
+import { reactive, ref, onMounted, inject, watch } from 'vue'
+import { useRoute } from 'vue-router'
+import axios from 'axios'
+
+const route: any = useRoute()
+const MG: any = inject('MG')
+const config: any = inject('config')
+const tool: any = inject('toolClass')
+const classInfo = JSON.parse(route.query.classInfo)
+const userInfo = ref()
+const searchKey = ref('')
+const visible = ref(false)
+const dynamicList: any = ref([])
+const tableData: any = ref([])
+const classItem = ref([])
+const fileList: any = ref([])
+const chapterList: any = ref([])
+const childrenList: any = ref([])
+const taskData: any = ref()
+// 鏂板缓鏁欏璁″垝闃叉姈
+const newLoading = ref(false)
+const teachPlanvalue = ref('')
+const taskItem = reactive({
+  title: '',
+  selectChapter: '',
+  referenceMaterial: '',
+  explain: '',
+  uploadResources: ''
+})
+let pages = reactive({
+  page: 1,
+  pageSize: 13,
+  count: 0,
+  loading: false
+})
+
+onMounted(() => {
+  const list = [{ key: 1, parentVal: '', childVal: '' }]
+  dynamicList.value = list
+  const userCache: any = localStorage.getItem('jesk-userInfo')
+  if (userCache) {
+    userInfo.value = JSON.parse(userCache)
+  }
+  pages.loading = true
+  getTaskList()
+})
+
+const searchData = () => {
+  pages.page = 1
+  getTaskCmsList()
+}
+
+const openPlan = () => {
+  visible.value = true
+  taskItem.title = ''
+  taskItem.selectChapter = ''
+  taskItem.referenceMaterial = ''
+  taskItem.explain = ''
+  taskItem.uploadResources = ''
+  dynamicList.value = [{ key: 1, parentVal: '', childVal: '' }]
+  fileList.value = []
+}
+
+const reduceGroup = () => {
+  dynamicList.value.pop()
+}
+
+const addGroup = () => {
+  const source = dynamicList.value[dynamicList.value.length - 1]
+  const obj = { key: source.key++, parentVal: '', childVal: '' }
+  dynamicList.value.push(obj)
+}
+
+const handleSizeChange = (val: number) => {
+  pages.pageSize = val
+  getTaskCmsList()
+}
+
+const handleCurrentChange = (val: number) => {
+  pages.page = val
+  getTaskCmsList()
+}
+
+// 鏂板缓浠诲姟
+const newTask = () => {
+  const data = {
+    name: classInfo?.name + '鏁欏璁″垝',
+    description: '',
+    icon: '',
+    type: config.taskType.teachingPlan,
+    state: 'Normal',
+    groupId: classInfo?.id,
+    order: 0,
+    beginDate: '2024-09-09T03:38:07.167Z',
+    endDate: '2024-09-09T03:38:07.167Z',
+    duration: 0
+  }
+  MG.edu
+    .newTask(data)
+    .then((res: any) => {})
+    .catch((e: any) => {
+      console.log(e)
+    })
+}
+
+// 鑾峰彇浠诲姟鍒楄〃
+const getTaskList = () => {
+  const data = {
+    start: 0,
+    size: 10,
+    filterList: [
+      {
+        value: config.taskType.teachingPlan,
+        field: 'Type',
+        subFilters: []
+      }
+    ],
+    searchList: [],
+    groupId: classInfo?.id
+  }
+  MG.edu
+    .getTaskList(data)
+    .then((res: any) => {
+      if (res.datas.length == 0 && userInfo.value.role == 'Teacher') {
+        newTask()
+      }
+      if (res.datas.length > 0) {
+        taskData.value = res.datas[0]
+        classInfo.taskId = taskData.value?.id
+        classInfo.rootTaskCmsId = taskData.value?.rootCmsItemId
+      }
+      getTypeByCode()
+      if (classInfo.bookRefCode) {
+        getCatalogueList()
+      }
+    })
+    .catch((e: any) => {
+      console.log(e)
+    })
+}
+
+// 鍓嶅線闃呰鍣�
+const toRead = (item: any) => {
+  // config.textReaderUrl
+  // 'http://192.168.3.132:8005/#/home'
+  if (classInfo.bookRefCode) {
+    const url =
+      config.textReaderUrl +
+      '?bookId=' +
+      classInfo?.bookRefCode +
+      '&token=' +
+      localStorage.getItem('jsek-token') +
+      '&chapter=' +
+      item.parentVal +
+      '&startPage=' +
+      item.childVal
+    window.open(url, '_blank')
+  } else {
+    ElMessage.warning('褰撳墠绔犺妭鏃犳硶璺宠浆')
+  }
+}
+
+// 涓嬭浇涓婁紶璧勬簮
+const downloadRes = (item: any) => {
+  const url = config.requestCtx + '/file/api/ApiDownload?md5=' + item.Md5
+  window.open(url, '_blank')
+}
+
+// 閫夋嫨鍣�
+const parentSelect = (val: any, item: any) => {
+  if (val?.length) {
+    const str = val[2]
+    const obj = findObj(chapterList.value, str)
+    item.parentVal = obj.chapter
+    item.childVal = obj.start
+  }
+}
+
+// 鏂囦欢涓婁紶
+const fileUpload = (file: any) => {
+  return new Promise((resolve, reject) => {
+    // const isJPG = file.file.type === 'image/jpeg' || file.file.type === 'image/png'
+    // const isLt2M = (0.3 * file.file.size) / 1024 / 1024 < 0.3
+    // if (!isJPG) {
+    //   ElMessage.error('涓婁紶鏂囦欢鍙兘鏄� jpg/png 鏍煎紡!')
+    //   return reject()
+    // }
+    // if (!isLt2M) {
+    //   ElMessage.error('涓婁紶鏂囦欢澶у皬涓嶈兘瓒呰繃 300KB!')
+    //   return reject()
+    // }
+    const FileName = file.file.name.split('.')[0]
+    const Extension = file.file.name.split('.')[1]
+    const FileType = file.file.type
+    let size = 1024
+    tool
+      .getFileMd5(file.file, size * 1024)
+      .then((e: string) => {
+        if (!fileList.value.find((item: any) => item.md5 == e)) {
+          const imgData = new FormData()
+          imgData.append('Md5', e)
+          imgData.append('FileName', FileName)
+          imgData.append('Extension', Extension)
+          imgData.append('FileType', FileType)
+          imgData.append('MetaData', null)
+          imgData.append('file', file.file)
+          MG.file.upload(imgData).then(() => {
+            fileList.value.push({
+              md5: e,
+              linkType: 'LinkFile',
+              linkProtectType: 'Public',
+              fileName: FileName,
+              extension: Extension,
+              url: config.requestCtx + `鈥�/file鈥�/api鈥�/ApiDownload?md5=` + e
+            })
+          })
+        } else {
+          ElMessage.warning('褰撳墠鏂囦欢宸蹭笂浼狅紝璇峰嬁閲嶅鎿嶄綔锛�')
+        }
+      })
+      .catch((e: any) => {
+        console.error(e)
+      })
+  })
+}
+
+// 鑾峰彇绔犺妭鐩綍
+const getCatalogueList = () => {
+  const url = config.requestCtx + '/books/resource/' + classInfo?.bookRefCode + '/information.json'
+  axios
+    .get(url)
+    .then((res) => {
+      if (res.data?.data.length > 0) {
+        const datas = res.data.data
+        const list = datas?.filter((item: any) => item.children?.length > 0)
+        chapterList.value = changeCascaderData(list)
+      }
+    })
+    .catch((e) => {
+      console.log(e)
+    })
+}
+
+// 閫掑綊鏇存暟缁�
+const changeCascaderData = (data: any) => {
+  for (const item of data) {
+    item.value = item.start
+    if (item.children?.length > 0) {
+      changeCascaderData(item.children)
+    }
+  }
+  return data
+}
+
+// 閫掑綊鏌ユ壘
+const findObj = (arr: any, val: any) => {
+  for (let i = 0; i < arr.length; i++) {
+    const obj = arr[i]
+    if (obj.start === val) {
+      return obj // 鎵惧埌鐩爣瀵硅薄锛岀洿鎺ヨ繑鍥�
+    }
+    if (obj.children && obj.children.length > 0) {
+      // 濡傛灉褰撳墠瀵硅薄鏈夊瓙瀵硅薄锛岄�掑綊鏌ユ壘瀛愬璞�
+      const found: any = findObj(obj.children, val)
+      if (found) {
+        return found // 鍦ㄥ瓙瀵硅薄涓壘鍒扮洰鏍囧璞★紝杩斿洖
+      }
+    }
+  }
+  return null
+}
+
+// 鑾峰彇绫诲瀷瀛楁
+const getTypeByCode = () => {
+  MG.resource
+    .getCmsTypeByRefCode({
+      refCodes: [config.refCodes.teachingPlan]
+    })
+    .then((res: any) => {
+      const data = res[0]?.cmsTypeLinks[0]?.children
+      if (data?.length) {
+        classItem.value = data
+      }
+      getTaskCmsList()
+    })
+    .catch((err: any) => {
+      console.log(err)
+    })
+}
+
+// 鑾峰彇浠诲姟涓嬬殑璧勬簮鍒楄〃
+const getTaskCmsList = () => {
+  const data = {
+    start: (pages.page - 1) * pages.pageSize,
+    size: pages.pageSize,
+    searchList: searchKey.value
+      ? [
+          {
+            keywords: searchKey.value,
+            field: 'Name',
+            compareType: 'Contains'
+          }
+        ]
+      : [],
+    taskId: classInfo?.taskId,
+    path: String(classInfo?.rootTaskCmsId),
+    type: '*',
+    keys: ['referenceMaterial', 'Name', 'selectChapter', 'uploadResources', 'explain']
+  }
+  MG.edu
+    .getTaskCmsItem(data)
+    .then((res: any) => {
+      pages.loading = false
+      pages.count = res.totalSize
+      for (let i = 0; i < res.datas.length; i++) {
+        const item = res.datas[i]
+        // 澶勭悊瀛楁
+        if (taskItem != null) {
+          for (let fieldKey in taskItem) {
+            if (item.datas[fieldKey]) {
+              const values = JSON.parse(item.datas[fieldKey])
+              if (values.length > 0) {
+                // 鐢ㄥ瓧娈靛悕澶勭悊杩斿洖鐨勫瓧娈靛��
+                if (values[0].Value) {
+                  item.datas[fieldKey] = values[0].Value
+                } else if (values[0].Data) {
+                  item.datas[fieldKey] = values[0].Data.Value
+                } else if (!values[0].Value && values[0].FileList?.length > 0) {
+                  item.datas[fieldKey] = values[0].FileList
+                } else {
+                  item.datas[fieldKey] = '-'
+                }
+                if (fieldKey == 'selectChapter' && values[0].Value) {
+                  const data = JSON.parse(values[0].Value)
+                  item.datas['selectChapter'] = data.map((citem: any) => {
+                    if (classInfo.bookRefCode) {
+                      const dataS = findObj(chapterList.value, citem.childVal)
+                      return {
+                        ...citem,
+                        parentName:
+                          chapterList.value.find((sitem: any) => sitem.chapter == citem.parentVal)
+                            ?.label +
+                          '---' +
+                          dataS?.label
+                      }
+                    } else {
+                      return {
+                        ...citem,
+                        parentName: citem.parentVal + '---' + citem.childVal
+                      }
+                    }
+                  })
+                }
+                if (fieldKey == 'selectChapter' && !values[0].Value) {
+                  item.datas['selectChapter'] = []
+                }
+              }
+              const index = i
+              item.datas['index'] = index + 1
+            }
+          }
+        }
+      }
+      tableData.value = res.datas
+    })
+    .catch((e: any) => {
+      ElMessage({
+        message: '鍒楄〃鑾峰彇澶辫触',
+        type: 'error'
+      })
+      console.log(e)
+    })
+}
+
+// 鍒犻櫎璧勬簮
+const removeTaskItem = (item: any) => {
+  const data = {
+    taskId: classInfo?.taskId,
+    requests: [
+      {
+        cmsItemId: item.id,
+        path: String(classInfo?.rootTaskCmsId)
+      }
+    ]
+  }
+  MG.edu
+    .removeTaskCmsItemList(data)
+    .then((res: any) => {
+      if (res) {
+        ElMessage({
+          message: '鍒犻櫎鎴愬姛',
+          type: 'success'
+        })
+        getTaskCmsList()
+      }
+    })
+    .catch((e: any) => {
+      ElMessage({
+        message: '鍒犻櫎澶辫触',
+        type: 'error'
+      })
+    })
+}
+
+// 涓轰换鍔℃柊寤鸿祫婧�
+const newTaskCmsItems = () => {
+  newLoading.value = true
+  taskItem.selectChapter = JSON.stringify(dynamicList.value)
+  if (!taskItem.title) {
+    ElMessage({
+      message: '璇峰~鍐欐暀瀛﹀悕绉�',
+      type: 'warning'
+    })
+    newLoading.value = false
+    return false
+  }
+  if (dynamicList.value[0]?.parentVal == '') {
+    ElMessage({
+      message: '璇烽�夋嫨鏁欏绔犺妭',
+      type: 'warning'
+    })
+    newLoading.value = false
+    return false
+  }
+  if (fileList.value.length == 0) {
+    ElMessage({
+      message: '璇蜂笂浼犳暀瀛︽枃浠�',
+      type: 'warning'
+    })
+    newLoading.value = false
+    return false
+  }
+  const data = {
+    groupId: classInfo?.id,
+    taskId: classInfo?.taskId,
+    accessPath: String(classInfo?.rootTaskCmsId),
+    newGroupCmsItemRequests: [
+      {
+        name: taskItem.title,
+        description: '',
+        icon: '',
+        type: config.refCodes.teachingPlan,
+        state: 'Normal',
+        order: 0,
+        newDataListRequest: tool.worksDataBytool(classItem.value, taskItem, fileList.value),
+        newCmsItemAndFileLinkListRequest: [],
+        newChildrenListRequest: []
+      }
+    ]
+  }
+  MG.edu.newTaskCmsItem(data).then((res: any) => {
+    newLoading.value = false
+    if (res) {
+      ElMessage({
+        message: '鏂板缓鎴愬姛',
+        type: 'success'
+      })
+      visible.value = false
+      getTaskCmsList()
+    }
+  })
+}
+
+// // 缂栬緫璧勬簮
+// const editOpen = (item: any) => {
+//   visible.value = true
+//   taskItem.title = item?.datas?.Name
+//   taskItem.explain = item?.datas?.explain
+//   taskItem.referenceMaterial = item?.datas?.referenceMaterial
+//   if (item?.datas?.selectChapter > 0) {
+//     dynamicList.value = item?.datas?.selectChapter
+//     chapterList.value?.forEach((item: any) => {
+//       if (dynamicList.value.find((citem: any) => citem.parentVal == item.chapter)) {
+//         childrenList.value.push(...item.children)
+//       }
+//     })
+//   }
+// }
+</script>
+
+<style lang="less" scoped>
+.classManagePage-box {
+  padding: 20px;
+  .classManagePage-nav {
+    padding-bottom: 20px;
+    border-bottom: 1px solid #e6e8ed;
+    margin-bottom: 30px;
+  }
+  .classManagePage-content {
+    width: 100%;
+    .teachPlaneBox {
+      width: 100%;
+      .titleBox {
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        margin-bottom: 10px;
+        .titleOptions {
+          width: 160px;
+          display: flex;
+          justify-content: space-between;
+          align-items: center;
+          span {
+            font-family: PingFang SC;
+            font-weight: bold;
+            font-size: 16px;
+            color: #333;
+            line-height: 0px;
+            text-align: left;
+          }
+        }
+        .searchBox {
+          width: 300px;
+          float: left;
+          .searchBtn {
+            background-color: var(--el-color-primary);
+            color: #fff;
+            border-top-left-radius: 0;
+            border-bottom-left-radius: 0;
+          }
+        }
+      }
+    }
+    .linkTitle {
+      color: #ff6c00;
+      cursor: pointer;
+    }
+    .linkTitle:hover {
+      text-decoration: underline;
+    }
+  }
+  .formBox {
+    width: 100%;
+    font-family: PingFang SC;
+    font-weight: 400;
+    font-size: 14px;
+    color: #333333;
+
+    .el-row {
+      margin-bottom: 20px;
+      display: flex;
+      align-items: flex-start;
+      .labelItem {
+        text-align: right;
+        margin-right: 15px;
+        padding-top: 2px;
+      }
+      .selectBox {
+        border: 1px solid #ddd;
+        border-radius: 5px;
+        padding: 20px 30px;
+        ::v-deep(.inputBox) {
+          display: flex;
+          align-items: center;
+          justify-content: flex-start;
+          .el-input__wrapper {
+            padding: 5px 11px;
+          }
+        }
+      }
+      .selectMarBot {
+        margin-bottom: 10px;
+      }
+      .btngroup {
+        position: absolute;
+        top: 20px;
+        right: 27px;
+      }
+      .el-upload-list__item-name {
+        line-height: 22px;
+      }
+    }
+  }
+}
+</style>
diff --git a/src/views/classManage/testManage.vue b/src/views/classManage/testManage.vue
new file mode 100644
index 0000000..7643d6c
--- /dev/null
+++ b/src/views/classManage/testManage.vue
@@ -0,0 +1,22 @@
+<template>
+  <div class="classManagePage-box">
+    <div class="classManagePage-nav">鎴戠殑鐝骇>{{ classInfo.name }}>浣滀笟绠$悊</div>
+    <div class="classManagePage-content"></div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { useRoute } from 'vue-router'
+const route = useRoute()
+const classInfo = JSON.parse(route.query.classInfo)
+</script>
+
+<style lang="less" scoped>
+.classManagePage-box {
+  padding: 20px;
+  .classManagePage-nav {
+    padding-bottom: 20px;
+    border-bottom: 1px solid #e6e8ed;
+  }
+}
+</style>
diff --git a/src/views/courseManage/components/class.vue b/src/views/courseManage/components/class.vue
new file mode 100644
index 0000000..442fd27
--- /dev/null
+++ b/src/views/courseManage/components/class.vue
@@ -0,0 +1,502 @@
+<template>
+  <div class="classPage">
+    <div class="headerBox">
+      <div class="searchBox">
+        <el-input v-model="searchKey" @clear="searchData()" clearable placeholder="璇疯緭鍏ュ叧閿瓧">
+          <template #append>
+            <el-button type="primary" class="searchBtn" :icon="Search" @click="searchData()" />
+          </template>
+        </el-input>
+      </div>
+      <el-button type="primary" class="applyStartClasses" @click="applyClass">鐢宠寮�鐝�</el-button>
+    </div>
+    <div class="classListBox" v-loading="pages.loading">
+      <div class="classItem" v-for="(item, index) in classList" :key="index">
+        <div class="itemHeader">
+          <div class="title">{{ item.name }}</div>
+          <div class="classId">锛圛D锛歿{ item.id }}锛�</div>
+          <div class="copyIdBtn" v-if="item.applyState == 'Normal'" @click="copy(item.refCode)">
+            澶嶅埗閭�璇风爜
+          </div>
+          <div
+            class="copyIdBtn"
+            style="background: transparent; padding: 0"
+            v-if="item.applyState == 'Reject'"
+          >
+            <el-icon @click="delClass(item)" style="color: red; font-size: 14px"
+              ><Delete
+            /></el-icon>
+          </div>
+        </div>
+        <div class="itemInfo" @click="groupDetail(item)">
+          <div class="infoBox">
+            <p>
+              鐘舵�侊細<span v-if="item.applyState == 'WaitAudit'" style="color: #ef9f29">
+                瀹℃牳涓� </span
+              ><span v-if="item.applyState == 'Normal'" style="color: #1dbd11"> 杩涜涓� </span
+              ><span v-if="item.applyState == 'Reject'" style="color: red"> 鏈�氳繃 </span>
+            </p>
+            <p v-if="item.applyState == 'Reject'">
+              鎷掔粷鍘熷洜锛�<span style="color: red">{{ item.reason != '' ? item.reason : '-' }}</span>
+            </p>
+            <p>鐝骇浜烘暟锛歿{ item.memberCount }} / {{ item.maxUserCount }}</p>
+            <p>
+              鏈夋晥鏈燂細{{ moment(item.beginDate).format('YYYY-MM-DD') }} -
+              {{ moment(item.endDate).format('YYYY-MM-DD') }}
+            </p>
+          </div>
+        </div>
+      </div>
+    </div>
+    <div class="pagination-box" v-if="classList.length > 0">
+      <el-pagination
+        v-model:current-page="pages.page"
+        v-model:page-size="pages.pageSize"
+        :background="false"
+        layout="total, prev, pager, next"
+        :total="pages.count"
+        @current-change="pageChange"
+        @size-change="handleSizeChange"
+      />
+    </div>
+    <div class="nullBox" v-if="!pages.loading && classList.length == 0">
+      <el-empty />
+    </div>
+    <!-- 鐢宠寮�鐝脊妗� -->
+    <el-dialog v-model="applyClassDialog" width="450" align-center>
+      <template #title>鐢宠寮�鐝�</template>
+      <el-form :model="formData" label-position="left" ref="dialogFormRef" label-width="100px">
+        <el-form-item
+          label="鐝骇鍚嶇О"
+          prop="name"
+          :rules="[{ required: true, message: '璇疯緭鍏ョ彮绾у悕绉�' }]"
+        >
+          <el-input v-model="formData.name" placeholder="璇疯緭鍏ョ彮绾у悕绉�" />
+        </el-form-item>
+        <el-form-item
+          label="鐝骇浜烘暟"
+          prop="num"
+          :rules="[{ required: true, message: '璇疯緭鍏ョ彮绾т汉鏁�' }]"
+        >
+          <el-input-number v-model="formData.num" :min="1" :step="1" :precision="0" />
+        </el-form-item>
+        <el-form-item
+          label="鐝骇鏈夋晥鏈�"
+          prop="date"
+          :rules="[{ required: true, message: '璇烽�夋嫨鐝骇鏈夋晥鏈�' }]"
+        >
+          <el-date-picker
+            v-model="formData.date"
+            type="daterange"
+            range-separator="-"
+            start-placeholder="寮�濮嬫椂闂�"
+            end-placeholder="缁撴潫鏃堕棿"
+          />
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button @click="applyClassDialog = false">鍙栨秷</el-button>
+          <el-button type="primary" @click="submit" :loading="submitLoading">鎻愪氦</el-button>
+        </div>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { defineProps, reactive, ref, onMounted, inject, watch } from 'vue'
+import { Search } from '@element-plus/icons-vue'
+import { ElMessage } from 'element-plus'
+import { getPublicImage } from '@/assets/js/middleGround/tool.js'
+import moment from 'moment'
+import { useRouter } from 'vue-router'
+import useClipboard from 'vue-clipboard3'
+
+const { toClipboard } = useClipboard()
+const uRouter = useRouter()
+const MG: any = inject('MG')
+const props = defineProps<{
+  courseId: number
+  bookInfo: any
+}>()
+
+const emit = defineEmits(['refreshParent'])
+
+// 鐢宠寮�鐝槻鎶杔oading
+const submitLoading = ref(false)
+
+const classList: any = ref([])
+
+onMounted(() => {
+  getData()
+})
+
+const searchKey = ref('')
+const pages = reactive({
+  page: 1,
+  pageSize: 6,
+  count: 0,
+  loading: true
+})
+
+const searchData = () => {
+  pages.page = 1
+  pages.pageSize = 10
+  getData()
+}
+
+// 鑾峰彇鐝骇
+const getData = () => {
+  pages.loading = true
+  MG.edu
+    .getCourseClassList({
+      courseId: props.courseId,
+      start: (pages.page - 1) * pages.pageSize,
+      size: pages.pageSize,
+      sort: {
+        type: 'Desc',
+        field: 'CreateDate'
+      },
+      filterList: [],
+      searchList: searchKey.value
+        ? [
+            {
+              keywords: searchKey.value,
+              field: 'Name',
+              compareType: 'Contains'
+            }
+          ]
+        : []
+    })
+    .then((res: any) => {
+      pages.loading = false
+      pages.count = res.totalSize;
+      classList.value = res.datas.map((item: any) => {
+        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 : ''
+        }
+      })
+      refreshParent()
+    })
+}
+
+// 鍔犲叆鐝骇
+const applyClass = () => {
+  formData.value = {
+    name: '',
+    num: '',
+    date: ''
+  }
+  applyClassDialog.value = true
+}
+
+// 鍒锋柊鐖剁粍浠舵暟鎹�
+const refreshParent = () => {
+  emit('refreshParent', 'del')
+}
+
+const applyClassDialog = ref(false)
+const formData = ref({
+  name: '',
+  num: '',
+  date: ''
+})
+
+const submit = () => {
+  submitLoading.value = true
+  MG.edu
+    .newCourseClass({
+      courseId: props.courseId,
+      name: formData.value.name,
+      description: '',
+      icon: '',
+      type: 'class',
+      beginDate: moment(formData.value.date[0]).format('YYYY-MM-DD'),
+      endDate: moment(formData.value.date[1]).format('YYYY-MM-DD'),
+      config: '',
+      price: 0,
+      maxUserCount: formData.value.num
+    })
+    .then((res: any) => {
+      if (res) {
+        setTimeout(() => {
+          submitLoading.value = false
+          ElMessage.success('寮�鐝凡鐢宠锛岀瓑寰呯鐞嗗憳瀹℃牳銆�')
+          applyClassDialog.value = false
+          getData()
+        }, 1000)
+      }
+    })
+    .catch((err: any) => {
+      ElMessage.error('寮�鐝敵璇峰嚭閿欙紝璇风◢鍚庡啀璇�')
+      setTimeout(() => {
+        submitLoading.value = false
+      }, 1000)
+    })
+}
+
+// 澶嶅埗
+const copy = async (text: string) => {
+  try {
+    await toClipboard(text)
+    ElMessage({
+      message: '澶嶅埗鎴愬姛',
+      type: 'success'
+    })
+  } catch (e) {
+    console.error(e)
+  }
+}
+
+// 鍒犻櫎鐝骇
+const delClass = (item: any) => {
+  const data = {
+    ids: [item.id]
+  }
+  MG.edu
+    .delCourseClass(data)
+    .then((res: any) => {
+      if (res) {
+        ElMessage({
+          message: '宸插垹闄�',
+          type: 'success'
+        })
+        getData()
+      }
+    })
+    .catch((err: any) => {
+      ElMessage({
+        message: '鍒犻櫎澶辫触',
+        type: 'error'
+      })
+      console.log(err)
+    })
+}
+
+// 鑾峰彇瀹℃牳閫氳繃鐨勮绋�
+const coursePages = reactive({
+  page: 1,
+  pageSize: 10,
+  count: 0,
+  loading: false
+})
+const courseListData = ref([])
+
+// const getCourse = () => {
+//   coursePages.loading = true
+//   const searchData = [
+//     {
+//       keywords: 'jsek_digitalTextbooks',
+//       field: 'ProductType'
+//     }
+//   ]
+//   const data = {
+//     Size: coursePages.pageSize,
+//     Start: coursePages.pageSize * coursePages.page - coursePages.pageSize,
+//     sort: {
+//       type: 'Desc',
+//       field: 'CreateDate'
+//     },
+//     searchList: searchData
+//   }
+//   MG.store
+//     .getPurchasedProductList(data)
+//     .then((res: any) => {
+//       coursePages.count = res.totalSize
+//       courseListData.value = res.datas.map((item: any) => {
+//         return {
+//           ...item,
+//           img: item.product.icon ? getPublicImage(item.product.icon, 80) : ''
+//         }
+//       })
+//       coursePages.loading = false
+//     })
+//     .catch(() => {
+//       coursePages.loading = false
+//     })
+// }
+
+const pageChange = (val: number) => {
+  pages.page = val
+  getData()
+}
+const handleSizeChange = (val: number) => {
+  pages.pageSize = val
+  getData()
+}
+
+const groupDetail = (item: any) => {
+  if (item.applyState == 'WaitAudit') {
+    ElMessage({
+      message: '姝e湪瀹℃牳涓�....',
+      type: 'warning'
+    })
+    return false
+  }
+  if (item.applyState == 'Reject') {
+    ElMessage({
+      message: '瀹℃牳鏈�氳繃',
+      type: 'warning'
+    })
+    return false
+  }
+  const bookData = item.linkProductDto.product
+  let classinfo: any = {
+    id: item.id,
+    name: item.name,
+    courseId: props.courseId,
+    icon: bookData.icon,
+    rootCmsItemId: bookData.rootCmsItemId,
+    bookId: bookData.id,
+    author: bookData.author,
+    isbn: bookData.isbn,
+    bookRefCode: bookData.refCode
+  }
+  let page = uRouter.resolve({
+    path: '/classManage',
+    query: {
+      classInfo: JSON.stringify(classinfo)
+    }
+  })
+  window.open(page.href, '_blank')
+}
+</script>
+
+<style lang="less" scoped>
+.classPage {
+  .headerBox {
+    margin-bottom: 10px;
+    overflow: hidden;
+    .searchBox {
+      width: 300px;
+      float: left;
+      .searchBtn {
+        background-color: var(--el-color-primary);
+        color: #fff;
+        border-top-left-radius: 0;
+        border-bottom-left-radius: 0;
+      }
+    }
+    .applyStartClasses {
+      float: right;
+    }
+  }
+  .classListBox {
+    overflow: hidden;
+    min-height: 200px;
+    .classItem {
+      float: left;
+      width: 49%;
+      margin-bottom: 16px;
+      margin-right: 1%;
+      border-radius: 8px;
+      border: 1px solid #efefef;
+      overflow: hidden;
+
+      &:nth-child(2n) {
+        margin-left: 1%;
+        margin-right: 0;
+      }
+      .itemHeader {
+        height: 40px;
+        line-height: 40px;
+        padding: 0 20px;
+        background-color: #f8f8f8;
+        div {
+          display: inline-block;
+        }
+        .classId {
+          margin-left: 6px;
+          font-size: 12px;
+          color: #999;
+        }
+        .copyIdBtn {
+          float: right;
+          height: 20px;
+          line-height: 20px;
+          margin-top: 10px;
+          font-size: 12px;
+          background-color: #fff;
+          color: #3b93fe;
+          padding: 0 6px;
+          border-radius: 50px;
+          overflow: hidden;
+          cursor: pointer;
+        }
+      }
+      .itemInfo {
+        height: 128px;
+        padding: 20px;
+        flex: 1;
+        display: flex;
+        cursor: pointer;
+        .infoBox {
+          flex: 1;
+          font-size: 12px;
+          p {
+            margin-bottom: 10px;
+          }
+        }
+      }
+    }
+  }
+}
+
+.courseList {
+  overflow: hidden;
+  margin-bottom: 20px;
+
+  .courseItem {
+    float: left;
+    width: 100px;
+    margin: 10px;
+    position: relative;
+
+    .checkBox {
+      position: absolute;
+      right: 0;
+      top: 0;
+      height: 14px;
+
+      ::v-deep {
+        .el-checkbox__inner {
+          border-color: #888;
+        }
+      }
+    }
+
+    .imgBox {
+      width: 100px;
+      height: 110px;
+      margin-bottom: 10px;
+    }
+
+    p {
+      line-height: 1.2;
+      display: -webkit-box;
+      -webkit-line-clamp: 2;
+      -webkit-box-orient: vertical;
+      overflow: hidden;
+    }
+  }
+}
+
+.pagination-box {
+  padding: 10px 0;
+  display: flex;
+  justify-content: center;
+}
+
+.nullBox {
+  text-align: center;
+  margin-top: 30px;
+  font-size: 20px;
+  color: #ccc;
+}
+</style>
diff --git a/src/views/courseManage/index.vue b/src/views/courseManage/index.vue
new file mode 100644
index 0000000..087f50e
--- /dev/null
+++ b/src/views/courseManage/index.vue
@@ -0,0 +1,228 @@
+<template>
+  <div class="courseManage" v-loading="loading">
+    <div class="backBox">
+      <span @click="router.back()">&lt; 杩斿洖</span>
+    </div>
+    <div class="courseName">
+      <div class="title" :title="detailData.name">{{ detailData.name }}</div>
+      <span class="courseId">ID锛歿{ detailData.id }}</span>
+    </div>
+    <div class="courseInfoBox">
+      <div class="desc" :title="detailData.description">
+        {{ detailData.description }}
+      </div>
+      <div class="textBookImg autoImgBox">
+        <img
+          v-if="detailData?.linkProduct?.icon != 'default'"
+          :src="
+            detailData.linkProduct?.icon ? getPublicImage(detailData.linkProduct.icon, 80) : defaultImg
+          "
+        />
+      </div>
+      <div class="textBookInfo">
+        <p class="title">{{ bookDetail?.name }}</p>
+        <p v-if="bookDetail?.author">浣滆�咃細 {{ bookDetail?.author }}</p>
+        <p>ISBN锛歿{ bookDetail?.isbn }}</p>
+      </div>
+      <div class="statisticsInfoBox">
+        <p class="title">鐝骇鏁伴噺<span>锛堣繘琛屼腑/鍏ㄩ儴锛�</span></p>
+        <!-- <p class="num">0 / 0</p> -->
+        <p class="num">{{ numClass }}</p>
+      </div>
+      <!-- <div class="statisticsInfoBox">
+        <p class="title">瀛︿範浜烘暟<span>锛堝涔犱腑/鍏ㄩ儴锛�</span></p>
+        <p class="num">0 / 0</p>
+      </div> -->
+      <!-- <div class="statisticsInfoBox">
+        <p class="title" style="margin-bottom: 40px">鏁欏澶х翰</p>
+        <p class="num">25</p>
+      </div> -->
+    </div>
+    <el-tabs style="margin-top: 20px">
+      <el-tab-pane label="鎴戠殑鐝骇">
+        <classManage
+          v-if="detailData.id"
+          :courseId="detailData.id"
+          :bookInfo="bookDetail"
+          @refreshParent="refreshParent"
+        />
+      </el-tab-pane>
+      <!-- <el-tab-pane label="鏁欏璁″垝">鏁欏璁″垝</el-tab-pane> -->
+    </el-tabs>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { reactive, ref, onMounted, inject, watch } from 'vue'
+import { useRouter, useRoute } from 'vue-router'
+import { Search } from '@element-plus/icons-vue'
+import { ElMessage } from 'element-plus'
+import { getPublicImage } from '@/assets/js/middleGround/tool.js'
+import classManage from './components/class.vue'
+import defaultImg from '@/assets/images/default-book-img.png'
+
+const MG: any = inject('MG')
+const router = useRouter()
+const route = useRoute()
+const query = route.query
+const bookDetail = ref()
+const numClass = ref(0)
+
+onMounted(() => {
+  getData()
+})
+
+const loading = ref(true)
+
+const detailData: any = ref({})
+
+// 鑾峰彇鐝骇
+const getDataClass = () => {
+  MG.edu
+    .getCourseClassList({
+      courseId: detailData.value.id,
+      start: 0,
+      size: 999,
+      sort: {
+        type: 'Desc',
+        field: 'CreateDate'
+      },
+      filterList: [],
+      searchList: []
+    })
+    .then((res: any) => {
+      numClass.value = res.datas.length
+    })
+}
+
+// 鑾峰彇璇剧▼淇℃伅
+const getData = () => {
+  MG.edu
+    .getCourseById({
+      courseId: query.courseId
+    })
+    .then((res: any) => {
+      detailData.value = res
+      loading.value = false
+      const shopId = res.linkProduct?.id
+      getBookDetail(shopId)
+      getDataClass()
+    })
+}
+
+// 鑾峰彇鏁欐潗璇︽儏
+const getBookDetail = (shopId: number) => {
+  let query = {
+    path: '*',
+    queryType: '*',
+    productId: String(shopId),
+    coverSize: {
+      height: 300,
+      width: 210
+    },
+    fields: {
+      seriesName: [],
+      author: [],
+      isbn: [],
+      publicationDate: []
+    }
+  }
+  MG.store.getProductDetail(query).then(async (res: any) => {
+    bookDetail.value = res.datas
+  })
+}
+
+const refreshParent = (str: string) => {
+  if (str == 'del') getData()
+}
+</script>
+
+<style lang="less" scoped>
+.courseManage {
+  padding: 0 20px;
+  .backBox {
+    border-bottom: 1px solid #efefef;
+    padding: 15px 0;
+    margin-bottom: 20px;
+    color: var(--el-color-primary);
+    span {
+      cursor: pointer;
+    }
+  }
+  .courseName {
+    margin-bottom: 20px;
+    font-size: 16px;
+    font-weight: bold;
+    display: flex;
+    justify-content: flex-start;
+    align-items: center;
+    .title {
+      max-width: 300px;
+      white-space: nowrap;
+      text-overflow: ellipsis;
+      overflow: hidden;
+      word-wrap: break-word;
+    }
+    .courseId {
+      margin-left: 40px;
+      font-size: 12px;
+      font-weight: normal;
+    }
+  }
+  .courseInfoBox {
+    font-size: 14px;
+    border: 1px solid #7ac1ec;
+    border-radius: 10px;
+    padding: 20px 10px;
+    display: flex;
+    background: #ebf7ff;
+    .desc {
+      width: 18%;
+      border-right: 1px solid #ccc;
+      padding-right: 20px;
+      margin-right: 20px;
+      font-size: 12px;
+      line-height: 30px;
+      display: -webkit-box;
+      -webkit-box-orient: vertical;
+      -webkit-line-clamp: 4;
+      overflow: hidden;
+      text-overflow: ellipsis;
+    }
+    .textBookImg {
+      width: 100px;
+      height: 120px;
+      margin-right: 10px;
+    }
+    .textBookInfo {
+      flex: 1.5;
+      overflow: hidden;
+      line-height: 18px;
+      p {
+        margin-bottom: 10px;
+      }
+    }
+    .statisticsInfoBox {
+      flex: 1;
+      overflow: hidden;
+      text-align: center;
+      p {
+        margin-bottom: 20px;
+      }
+      .num {
+        font-size: 16px;
+      }
+    }
+    .title {
+      font-weight: bold;
+      font-size: 14px;
+      span {
+        display: inline-block;
+        font-weight: normal;
+        font-size: 12px;
+        margin-top: 6px;
+      }
+    }
+  }
+}
+</style>
diff --git a/src/views/personalCenter/activeCode.vue b/src/views/personalCenter/activeCode.vue
index 3f523d5..6d4e8d0 100644
--- a/src/views/personalCenter/activeCode.vue
+++ b/src/views/personalCenter/activeCode.vue
@@ -1,3 +1,397 @@
 <template>
-    <div>婵�娲荤爜</div>
-</template>
\ No newline at end of file
+  <!-- <page> -->
+  <div class="personalPage-box">
+    <div class="personalPage-title">婵�娲诲晢鍝�</div>
+    <div class="personalPage-content">
+      <div class="activation flex">
+        <el-input class="inputBox" v-model="activateCode" placeholder="璇疯緭鍏ユ縺娲荤爜">
+          <template #append>
+            <el-button
+              style="background-color: #019e58; color: #fff"
+              @click="userActiveCodeGet"
+              :loading="loading"
+              >婵�娲�</el-button
+            >
+          </template>
+        </el-input>
+        <!-- <el-button class="buttonBox" type="primary" @click="userActiveCodeGet" :loading="loading"
+          >婵�娲诲晢鍝�</el-button
+        > -->
+      </div>
+      <div class="tipTitle">宸叉縺娲诲晢鍝�</div>
+      <div class="myCarTopPage">
+        <div class="cartContent">
+          <div class="list-box" v-loading="pages.loading">
+            <ul class="listTable" v-if="dataList.length > 0 && !pages.loading">
+              <li v-for="item in dataList" :key="item.index">
+                <div class="stateBox flex">
+                  <span class="flex1"
+                    >浣跨敤婵�娲荤爜锛�<span>{{ item.code }}</span></span
+                  >
+                  <span class="createDate flex1"
+                    >婵�娲绘棩鏈燂細{{ item.createDate ? item.createDate : "-" }}</span
+                  >
+                </div>
+                <div class="listItemBox flex">
+                  <div style="width: 100%" v-if="item.typeList.length > 0">
+                    <div
+                      v-for="pItem in item.typeList"
+                      :key="pItem.id"
+                      class="listItem"
+                      @click="
+                        goBookDetails(pItem.id, pItem.name, pItem.defaultSaleMethodId)
+                      "
+                    >
+                      <div class="cover">
+                        <img
+                          :src="
+                            pItem.icon ? getPublicImage(pItem.icon, '', '') : bookCover
+                          "
+                          alt=""
+                        />
+                        <!-- <div class="type" v-if="pItem.type">{{ pItem.type }}</div> -->
+                      </div>
+                      <div class="info">
+                        <div style="margin-bottom: 10px" v-if="pItem.type">
+                          {{ pItem.type }}
+                        </div>
+                        <span :title="pItem.name">{{ pItem.name }}</span>
+                      </div>
+                    </div>
+                  </div>
+                  <div v-else class="noProduct">
+                    <el-empty :image-size="80" description="鏃犳縺娲诲晢鍝�" />
+                  </div>
+                </div>
+              </li>
+            </ul>
+            <div v-if="dataList.length == 0 && !pages.loading">
+              <el-empty :image-size="200" />
+            </div>
+          </div>
+          <div class="pagination-box" v-if="dataList.length > 0 && !pages.loading">
+            <el-pagination
+              v-model:current-page="pages.page"
+              v-model:page-size="pages.pageSize"
+              layout="total, prev, pager, next"
+              :total="pages.count"
+              @current-change="handleCurrentChange"
+            />
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+  <!-- </page> -->
+</template>
+
+<script setup lang="ts">
+import { reactive, ref, onMounted, inject, watch } from "vue";
+import moment from "moment";
+import { getPublicImage } from "@/assets/js/middleGround/tool.js";
+import { ElMessage } from "element-plus";
+import { useBreadcrumbStore, useUserStore } from "@/store";
+import { useRouter } from "vue-router";
+import bookCover from "@/assets/images/personalCenter/book-cover.png";
+const router = useRouter();
+const crumbStore = useBreadcrumbStore();
+const userStore = useUserStore();
+const MG = inject("MG");
+const activateCode = ref("");
+const loading = ref(false);
+let dataList = ref([]);
+let pages = reactive({
+  page: 1,
+  pageSize: 5,
+  count: 0,
+  loading: false,
+});
+
+// 浣跨敤婵�娲荤爜
+const userActiveCodeGet = () => {
+  loading.value = true;
+  let lock = true;
+  if (activateCode.value == "") {
+    ElMessage({
+      type: "error",
+      message: "璇疯緭鍏ユ縺娲荤爜锛�",
+    });
+    loading.value = false;
+  } else {
+    if (lock) {
+      lock = false;
+      MG.store
+        .userActiveCode({
+          code: activateCode.value,
+        })
+        .then((res) => {
+          ElMessage({
+            type: res == "婵�娲绘垚鍔�" ? "success" : "error",
+            message: res,
+          });
+          activateCode.value = "";
+          loading.value = false;
+          getDataList();
+          lock = true;
+        });
+    }
+  }
+};
+
+function getDataList() {
+  pages.loading = true;
+  MG.store
+    .userActiveCodeList({
+      start: (pages.page - 1) * pages.pageSize,
+      size: pages.pageSize,
+      sort: {
+        type: "Desc",
+        field: "CreateDate",
+      },
+    })
+    .then((res) => {
+      let list: any[] = [];
+      res.datas.forEach((item) => {
+        item.createDate = moment(item.createDate).format("YYYY-MM-DD HH:mm:ss");
+        item.typeList = [];
+        item.saleMethodList.forEach(async (i) => {
+          const obj = {
+            icon: item.productList[0]?.icon,
+            id: item.productList[0]?.id,
+            name: item.productList[0]?.name,
+            type:
+              i.type == "defaultSaleMethod"
+                ? "鐢靛瓙涔�"
+                : i.name.includes("-")
+                ? i.name.split("-")[0]
+                : i.name,
+            defaultSaleMethodId: item.productList[0]?.defaultSaleMethodId,
+          };
+
+          let parentData = await MG.store.getProductBySaleMethod({ saleMethodId: i.id });
+          if (parentData.storeLinks[0].storeRefCode == "jsek_digitalCourses") {
+            obj.type = "鏁板瓧璇剧▼";
+          }
+          if (parentData.storeLinks[0].storeRefCode == "jsek_digitalTextbooks") {
+            obj.type = "鏁板瓧鏁欐潗";
+          }
+          item.typeList.push(obj);
+        });
+        list.push(item);
+      });
+      setTimeout(() => {
+        dataList.value = list;
+        pages.count = res.totalSize;
+        pages.loading = false;
+      }, 500);
+    })
+    .catch(() => {
+      pages.loading = false;
+    });
+}
+
+onMounted(() => {
+  getDataList();
+});
+
+// watch(
+//   () => userStore.token,
+//   () => {
+//     getDataList()
+//   }
+// )
+
+const handleCurrentChange = (val: number) => {
+  pages.page = val;
+  getDataList();
+};
+// 璺宠浆涔︽湰璇︽儏
+const goBookDetails = async (id: number, name: string, defaultSaleMethodId: number) => {
+  let parentData = await MG.store.getProductBySaleMethod({
+    saleMethodId: defaultSaleMethodId,
+  });
+  console.log(parentData, 123);
+  if (parentData.storeLinks[0].storeRefCode == "jsek_digitalCourses") {
+    let crumbs = [
+      {
+        name,
+        isCrumbs: true,
+        type: "digitalCourses",
+        path: "digitalCoursesDetails",
+      },
+    ];
+    // 鍦ㄥ叏灞�鏁版嵁涓缃潰鍖呭睉
+    crumbStore.setCrumbs({
+      type: "digitalCourses",
+      data: crumbs,
+      callback: (key: any) => {
+        router.push({
+          name: "digitalCoursesDetails",
+          query: {
+            crumbsKey: key,
+            bookId: parentData.id,
+            bookName: parentData.name,
+            type: "digitalCourses",
+          },
+        });
+      },
+    });
+  } else if (parentData.storeLinks[0].storeRefCode == "jsek_digitalTextbooks") {
+    let crumbs = [
+      {
+        name,
+        isCrumbs: true,
+        type: "digitalTextbooks",
+        path: "digitalTextbooksDetails",
+      },
+    ];
+    // 鍦ㄥ叏灞�鏁版嵁涓缃潰鍖呭睉
+    crumbStore.setCrumbs({
+      type: "digitalTextbooks",
+      data: crumbs,
+      callback: (key: any) => {
+        router.push({
+          name: "digitalTextbooksDetails",
+          query: {
+            crumbsKey: key,
+            bookId: parentData.id,
+            bookName: parentData.name,
+            type: "digitalTextbooks",
+          },
+        });
+      },
+    });
+  } else {
+    let crumbs = [
+      {
+        name,
+        isCrumbs: true,
+        type: "bookService",
+        path: "/bookService/details",
+      },
+    ];
+    // 鍦ㄥ叏灞�鏁版嵁涓缃潰鍖呭睉
+    crumbStore.setCrumbs({
+      type: "bookService",
+      data: crumbs,
+      callback: (key: any) => {
+        router.push({
+          name: "bookDetails",
+          query: {
+            crumbsKey: key,
+            bookId: id,
+            bookName: name,
+            type: "bookService",
+          },
+        });
+      },
+    });
+  }
+};
+</script>
+<style lang="less" scoped>
+::v-deep(.activation) {
+  margin-bottom: 30px;
+  .el-input__wrapper.is-focus {
+    border-color: none !important;
+  }
+}
+
+.inputBox {
+  width: 300px;
+  margin-right: 10px;
+}
+
+.tipTitle {
+  font-family: Microsoft YaHei UI, Microsoft YaHei UI;
+  font-weight: 400;
+  font-size: 16px;
+  color: #000000;
+  padding: 5px 20px;
+  box-sizing: border-box;
+  border-left: 3px solid #019e58;
+  margin-bottom: 20px;
+}
+
+.stateBox {
+  height: 47px;
+  line-height: 47px;
+  padding: 0 20px;
+  border: 1px solid #edecec;
+  background: #f3f3f3;
+}
+
+.listItemBox {
+  margin-top: 20px;
+}
+
+.listItem {
+  width: 130px;
+  cursor: pointer;
+  box-sizing: border-box;
+  float: left;
+  position: relative;
+  margin-right: 5%;
+
+  .cover {
+    width: 100%;
+    height: 180px;
+    box-shadow: 0px 0px 20px 1px #ccc;
+    position: relative;
+
+    img {
+      width: 100%;
+      height: 100%;
+      object-fit: contain;
+    }
+    .type {
+      width: 50px;
+      height: 26px;
+      text-align: center;
+      font-size: 12px;
+      line-height: 24px;
+      position: absolute;
+      top: 0;
+      right: 0;
+      background-color: #019e58;
+      color: #fff;
+      border-radius: 0px 0px 0px 5px;
+    }
+  }
+
+  .info {
+    height: 90px;
+    padding: 15px 0;
+    width: 100%;
+
+    span {
+      font-weight: bold;
+      height: 45px;
+      line-height: 22px;
+      display: -webkit-box;
+      margin-bottom: 5px;
+      -webkit-box-orient: vertical;
+      -webkit-line-clamp: 2;
+      overflow: hidden;
+      text-overflow: ellipsis;
+    }
+  }
+}
+
+.list-box {
+  min-height: 450px;
+}
+
+.createDate {
+  text-align: right;
+}
+.noProduct {
+  padding: 30px;
+  text-align: center;
+}
+
+.pagination-box {
+  display: flex;
+  justify-content: center;
+}
+</style>
diff --git a/src/views/personalCenter/class.vue b/src/views/personalCenter/class.vue
index 7293e29..c991c11 100644
--- a/src/views/personalCenter/class.vue
+++ b/src/views/personalCenter/class.vue
@@ -1,7 +1,462 @@
 <template>
-  <div class="myBook">
-    <div class="myBook_header">
-      <div class="myBook_header_title">鎴戠殑鐝骇</div>
+  <div class="coursePage">
+    <div class="personalPage-title">鎴戠殑鐝骇</div>
+    <div class="tabs">
+      <el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">
+        <el-tab-pane
+          :label="'褰撳墠鐝骇锛�' + calssList.length + '锛�'"
+          name="1"
+        ></el-tab-pane>
+        <!-- <el-tab-pane label="鍘嗗彶鐝骇(5)" name="2"></el-tab-pane> -->
+      </el-tabs>
+    </div>
+    <div class="headerBox">
+      <div class="searchBox">
+        <el-input
+          v-model="searchKey"
+          clearable
+          @clear="searchList()"
+          placeholder="璇疯緭鍏ュ叧閿瓧"
+        >
+          <template #append>
+            <el-button
+              type="primary"
+              class="searchBtn"
+              @click="searchList()"
+              :icon="Search"
+            />
+          </template>
+        </el-input>
+      </div>
+      <el-button type="primary" class="applyStartClasses" @click="openJoin()"
+        >鍔犲叆鐝骇</el-button
+      >
+      <el-dialog v-model="dialogVisible" title="鍔犲叆鐝骇" width="500">
+        <div class="codeContent">
+          <span>閭�璇风爜锛�</span>
+          <el-input style="width: 330px" v-model="codeText" placeholder="璇疯緭鍏ラ個璇风爜" />
+          <el-button type="primary" @click="getClassDetail">纭</el-button>
+        </div>
+        <div class="classInfo" v-if="classDetail?.name">
+          <div class="itemCon">
+            <span>鐝骇鍚嶇О锛�</span>
+            <span>{{ classDetail.name }}</span>
+          </div>
+          <div class="itemCon">
+            <span>鐝骇浜烘暟锛�</span>
+            <span>{{ classDetail.memberCount }} / {{ classDetail.maxUserCount }}</span>
+          </div>
+          <div class="itemCon">
+            <span>寮�璇炬椂闂达細</span>
+            <span
+              >{{ moment(classDetail.beginDate).format("YYYY-MM-DD") }} -
+              {{ moment(classDetail.endDate).format("YYYY-MM-DD") }}</span
+            >
+          </div>
+        </div>
+        <template #footer>
+          <div class="dialog-footer">
+            <el-button @click="dialogVisible = false"> 鍙栨秷 </el-button>
+            <el-button type="primary" @click="joinClass()"> 纭 </el-button>
+          </div>
+        </template>
+      </el-dialog>
+    </div>
+    <div class="courseListBox" v-if="calssList.length > 0 && !isLoading">
+      <div class="courseItem" v-for="(item, index) in calssList" :key="index">
+        <div class="itemHeader">
+          <div class="title">{{ item.name }}</div>
+          <div class="courseId">锛圛D锛歿{ item.id }}锛�</div>
+          <!-- <div class="copyIdBtn" @click="copy(item.refCode)">澶嶅埗閭�璇风爜</div> -->
+        </div>
+        <div class="itemInfo" @click="goClassManage(item)">
+          <div class="infoBox">
+            <p>
+              鐘舵�侊細<span v-if="item.userState == 'WaitValid'" style="color: #ef9f29">
+                瀹℃牳涓� </span
+              ><span v-if="item.userState == 'Normal'" style="color: #1dbd11">
+                杩涜涓� </span
+              ><span v-if="item.userState == 'Reject'" style="color: red"> 鏈�氳繃 </span>
+            </p>
+            <p>鐝骇浜烘暟锛歿{ item.memberCount }} / {{ item.maxUserCount }}</p>
+            <p>鏈夋晥鏈燂細{{ item.classTime }}</p>
+          </div>
+        </div>
+      </div>
+    </div>
+    <el-empty description="鏆傛棤鏁版嵁" v-if="calssList.length == 0 && !isLoading" />
+    <div style="min-height: 200px" v-if="isLoading" v-loading="isLoading"></div>
+    <div class="pageBox">
+      <el-pagination
+        v-model:current-page="pages.currentPage"
+        :page-size="pages.pageSize"
+        :size="'small'"
+        :disabled="pages.count <= 1"
+        layout="total, prev, pager, next"
+        :total="pages.count"
+        @size-change="handleSizeChange"
+        @current-change="handleCurrentChange"
+      />
     </div>
   </div>
 </template>
+
+<script setup lang="ts">
+import { reactive, ref, onMounted, inject, watch } from "vue";
+import { Search } from "@element-plus/icons-vue";
+import { useRouter } from "vue-router";
+import { ElMessage } from "element-plus";
+import { getPublicImage } from "@/assets/js/middleGround/tool.js";
+import moment from "moment";
+import useClipboard from "vue-clipboard3";
+
+const { toClipboard } = useClipboard();
+const MG: any = inject("MG");
+const config: any = inject("config");
+const router = useRouter();
+const activeName = ref("1");
+
+interface ClassItem {
+  id: string;
+  name: string;
+  memberCount: number;
+  maxUserCount: number;
+  userState: string;
+  beginDate: string;
+  endDate: string;
+  classTime: string;
+  linkProductDto: {
+    product: {
+      name: string;
+      icon: string;
+    };
+  };
+}
+
+const calssList = ref<ClassItem[]>([]);
+const searchKey = ref("");
+const codeText = ref("");
+const dialogVisible = ref(false);
+const classDetail = ref();
+const isLoading = ref(true);
+
+let pages = reactive({
+  currentPage: 1,
+  page: 1,
+  pageSize: 6,
+  count: 0,
+  loading: false,
+});
+
+onMounted(() => {
+  getCurrentClassList();
+});
+
+//  鍒嗛〉
+const handleSizeChange = (val: number) => {
+  pages.pageSize = val;
+  getCurrentClassList();
+};
+
+const handleCurrentChange = (val: number) => {
+  pages.page = val;
+  pages.currentPage = val;
+  getCurrentClassList();
+};
+
+const handleClick = (val: any) => {
+  activeName.value = val;
+};
+
+const openJoin = () => {
+  dialogVisible.value = true;
+  classDetail.value = null;
+  codeText.value = "";
+};
+
+// 鎼滅储
+const searchList = () => {
+  pages.page = 1;
+  pages.currentPage = 1;
+  getCurrentClassList();
+};
+
+// 澶嶅埗
+const copy = async (text: string) => {
+  try {
+    await toClipboard(text);
+    ElMessage({
+      message: "澶嶅埗鎴愬姛",
+      type: "success",
+    });
+  } catch (e) {
+    console.error(e);
+  }
+};
+
+// 鍔犲叆鐝骇
+const joinClass = () => {
+  if (!codeText.value) {
+    ElMessage({
+      message: "鏃犳晥鐨勯個璇风爜",
+      type: "error",
+    });
+    return false;
+  }
+  const data = { refCode: codeText.value };
+  MG.identity.joinGroupByRefCode(data).then((res: any) => {
+    if (res == "缁勪笉瀛樺湪") {
+      ElMessage({
+        message: "鏃犳晥鐨勭彮绾�",
+        type: "error",
+      });
+    }
+    if (res == "缁勬垚鍛樻暟閲忓凡鏈�澶�,涓嶈兘鍔犲叆") {
+      ElMessage({
+        message: "鐝骇鎴愬憳鏁伴噺宸叉渶澶э紝涓嶈兘鍔犲叆",
+        type: "error",
+      });
+    }
+    if (res == "宸茬粡鐢宠杩囧姞鍏ユ缁�") {
+      ElMessage({
+        message: "宸茬粡鐢宠杩囧姞鍏ユ鐝骇",
+        type: "error",
+      });
+    }
+    dialogVisible.value = false;
+    getCurrentClassList();
+  });
+};
+
+// 鑾峰彇褰撳墠鐝骇鍒楄〃
+const getCurrentClassList = () => {
+  isLoading.value = true;
+  const data = {
+    start: (pages.page - 1) * pages.pageSize,
+    size: pages.pageSize,
+    sort: {
+      type: "Desc",
+      field: "CreateDate",
+      subSorts: [],
+    },
+    filterList: [],
+    searchList: searchKey.value
+      ? [
+          {
+            keywords: searchKey.value,
+            field: "Name",
+            compareType: "Contains",
+          },
+        ]
+      : [],
+  };
+  MG.identity.joinedGroupByList(data).then((res: any) => {
+    isLoading.value = false;
+    pages.count = res.totalSize;
+    if (res.datas) {
+      calssList.value = res.datas.map((item: any) => {
+        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),
+        };
+      });
+    }
+  });
+};
+
+// 璺宠浆鐝骇绠$悊
+const goClassManage = async (item: any) => {
+  if (item.userState == "WaitValid") {
+    ElMessage({
+      message: "姝e湪瀹℃牳涓�....",
+      type: "warning",
+    });
+    return false;
+  }
+  if (item.userState == "Reject") {
+    ElMessage({
+      message: "瀹℃牳鏈�氳繃",
+      type: "warning",
+    });
+    return false;
+  }
+  const bookInfo = await getBookDetail(item.linkProductDto?.product);
+  let info = {
+    id: item.id,
+    name: item.name,
+    icon: bookInfo.icon,
+    rootCmsItemId: bookInfo.rootCmsItemId,
+    bookId: bookInfo.id,
+    author: bookInfo.author,
+    isbn: bookInfo.isbn,
+    bookRefCode: bookInfo.refCode,
+  };
+  let page = router.resolve({
+    path: "/classManage",
+    query: {
+      classInfo: JSON.stringify(info),
+    },
+  });
+  window.open(page.href, "_blank");
+  // router.push({
+  //   path: '/classManage',
+  //   query: {
+  //     classInfo: JSON.stringify(info)
+  //   }
+  // })
+};
+
+// 鑾峰彇鏁欐潗璇︽儏
+const getBookDetail = async (item: any) => {
+  const path = item.refCode ? "jsek_digitalTextbooks" : config.goodsStore;
+  let query = {
+    path,
+    queryType: "*",
+    productId: String(item.id),
+    storeInfo: path,
+    coverSize: {
+      height: 300,
+      width: 210,
+    },
+    fields: {
+      author: [],
+      isbn: [],
+    },
+  };
+  const res = await MG.store.getProductDetail(query);
+  return res.datas ?? null;
+};
+
+// 閫氳繃code鏌ヨ鐝骇
+const getClassDetail = () => {
+  if (codeText.value == "") {
+    ElMessage({
+      message: "璇疯緭鍏ラ個璇风爜",
+      type: "warning",
+    });
+    return false;
+  }
+  const data = {
+    classIdOrRefCode: codeText.value,
+  };
+  MG.edu
+    .getCourseClass(data)
+    .then((res: any) => {
+      classDetail.value = res;
+    })
+    .catch((err: any) => {
+      console.log(err);
+    });
+};
+</script>
+
+<style lang="less" scoped>
+.coursePage {
+  .tabs {
+    padding: 0 20px;
+  }
+  .headerBox {
+    padding: 5px 20px;
+    margin-bottom: 10px;
+    overflow: hidden;
+    .searchBox {
+      width: 300px;
+      float: left;
+      .searchBtn {
+        background-color: var(--el-color-primary);
+        color: #fff;
+        border-top-left-radius: 0;
+        border-bottom-left-radius: 0;
+      }
+    }
+    .applyStartClasses {
+      float: right;
+    }
+  }
+  .courseListBox {
+    overflow: hidden;
+    .courseItem {
+      float: left;
+      width: 46%;
+      margin: 0 2% 20px;
+      border-radius: 8px;
+      border: 1px solid #efefef;
+      overflow: hidden;
+      .itemHeader {
+        height: 40px;
+        line-height: 40px;
+        padding: 0 20px;
+        // color: #fff;
+        background-color: #f8f8f8;
+        .title {
+          font-weight: 600;
+        }
+        div {
+          display: inline-block;
+        }
+        .courseId {
+          margin-left: 6px;
+          font-size: 12px;
+          color: #999;
+        }
+        .copyIdBtn {
+          float: right;
+          height: 20px;
+          line-height: 20px;
+          margin-top: 10px;
+          font-size: 12px;
+          background-color: #fff;
+          color: #3b93fe;
+          padding: 0 6px;
+          border-radius: 50px;
+          overflow: hidden;
+          cursor: pointer;
+        }
+      }
+      .itemInfo {
+        padding: 20px;
+        flex: 1;
+        display: flex;
+        cursor: pointer;
+        .imgBox {
+          width: 90px;
+          height: 120px;
+          margin-right: 20px;
+        }
+        .infoBox {
+          flex: 1;
+          font-size: 12px;
+          p {
+            margin-bottom: 10px;
+          }
+        }
+      }
+    }
+  }
+  .codeContent {
+    width: 100%;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    padding-bottom: 30px;
+  }
+  .classInfo {
+    padding: 30px 0;
+    border-top: 2px dashed #ccc;
+
+    .itemCon {
+      margin-bottom: 20px;
+    }
+  }
+  .pageBox {
+    padding: 10px 0;
+    display: flex;
+    justify-content: center;
+  }
+}
+</style>
diff --git a/src/views/personalCenter/config.ts b/src/views/personalCenter/config.ts
index 83463de..3d72291 100644
--- a/src/views/personalCenter/config.ts
+++ b/src/views/personalCenter/config.ts
@@ -20,7 +20,7 @@
 </svg>`,
   },
   {
-    label: '鎴戠殑鍥句功',
+    label: '鎴戠殑涔︽灦',
     key: '3',
     path: 'myBook',
     icon: `<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
diff --git a/src/views/personalCenter/course.vue b/src/views/personalCenter/course.vue
index 68d9d97..9652dc9 100644
--- a/src/views/personalCenter/course.vue
+++ b/src/views/personalCenter/course.vue
@@ -1,7 +1,655 @@
 <template>
-  <div class="myBook">
-    <div class="myBook_header">
-      <div class="myBook_header_title">鎴戠殑璇剧▼</div>
+  <div class="coursePage">
+    <div class="personalPage-title">鎴戠殑璇剧▼</div>
+    <div class="headerBox">
+      <div class="searchBox">
+        <el-input
+          v-model="searchKey"
+          clearable
+          @clear="getData"
+          placeholder="璇疯緭鍏ュ叧閿瓧"
+        >
+          <template #append>
+            <el-button type="primary" class="searchBtn" :icon="Search" @click="getData" />
+          </template>
+        </el-input>
+      </div>
+      <el-button type="primary" class="applyStartClasses" @click="applyCourse"
+        >鐢宠寮�璇�</el-button
+      >
     </div>
+    <div class="courseListBox" v-loading="pages.loading">
+      <div
+        class="courseItem"
+        v-for="(item, index) in courseList"
+        :key="index"
+        @click="gotoDetail(item)"
+      >
+        <div class="itemHeader">
+          <div class="title" :title="item.name">{{ item.name }}</div>
+        </div>
+        <div class="reasonBox">
+          <el-tooltip placement="right-end" effect="light" class="box-item">
+            <template #content>
+              <div style="width: 300px" v-html="item.reason"></div>
+            </template>
+            <span v-if="item.applyState == 'Reject'" style="color: red">
+              鎷掔粷鍘熷洜锛歿{ item.reason != "" ? item.reason : "-" }}
+            </span>
+          </el-tooltip>
+          <el-button
+            v-if="item.applyState == 'Reject'"
+            type="primary"
+            size="small"
+            style="margin-left: 20px"
+            @click="reapplyCourse(item)"
+            >閲嶆柊鐢宠</el-button
+          >
+        </div>
+
+        <div class="itemInfo">
+          <div class="imgBox autoImgBox">
+            <div
+              class="stateIcon"
+              v-if="item.applyState == 'Normal'"
+              style="background-color: #1dbd11"
+            >
+              浣跨敤涓�
+            </div>
+            <div
+              class="stateIcon"
+              v-if="item.applyState == 'WaitAudit'"
+              style="background-color: #ef9f29"
+            >
+              瀹℃牳涓�
+            </div>
+            <div
+              class="stateIcon"
+              v-if="item.applyState == 'Reject'"
+              style="background-color: red"
+            >
+              鏈�氳繃
+            </div>
+            <img :src="item.icon" />
+          </div>
+          <div class="infoBox">
+            <p class="id">ID锛歿{ item.id }}</p>
+            <div class="introduction" :title="item.introduction">
+              {{ item.introduction }}
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+    <div class="pagination-box" v-if="courseList.length > 0">
+      <el-pagination
+        v-model:current-page="pages.page"
+        v-model:page-size="pages.pageSize"
+        :background="false"
+        layout="total, prev, pager, next"
+        :total="pages.count"
+        @current-change="pageChange"
+      />
+    </div>
+    <div class="nullBox" v-if="!pages.loading && courseList.length == 0">
+      <el-empty />
+    </div>
+    <!-- 鐢宠寮�璇惧脊妗� -->
+    <el-dialog v-model="applyCourseDialog" width="750" align-center>
+      <template #title>{{ editData ? "閲嶆柊鐢宠" : "鐢宠寮�璇�" }}</template>
+      <el-form
+        :model="formData"
+        label-position="left"
+        ref="dialogFormRef"
+        label-width="80px"
+      >
+        <el-form-item
+          label="璇剧▼鍚嶇О"
+          prop="name"
+          :rules="[{ required: true, message: '璇疯緭鍏ヨ绋嬪悕绉�' }]"
+        >
+          <el-input v-model="formData.name" placeholder="璇疯緭鍏ヨ绋嬪悕绉�" />
+        </el-form-item>
+        <el-form-item
+          v-if="!editData"
+          label="鍏宠仈鏁欐潗"
+          prop="bookName"
+          :rules="[{ required: true, message: '璇烽�夋嫨鏁欐潗' }]"
+        >
+          <div style="display: flex">
+            <el-input v-model="formData.bookName" disabled="true" style="width: 300px" />
+            <el-button style="margin-left: 10px" @click="selectBook">閫夋嫨鏁欐潗</el-button>
+          </div>
+        </el-form-item>
+        <el-form-item label="璇剧▼浠嬬粛">
+          <el-input
+            v-model="formData.desc"
+            type="textarea"
+            autocomplete="off"
+            maxlength="300"
+            show-word-limit
+            rows="7"
+            placeholder="璇疯緭鍏ヨ绋嬩粙缁�"
+          />
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button @click="applyCourseDialog = false">鍙栨秷</el-button>
+          <el-button type="primary" @click="submit" :loading="submitLoading"
+            >鎻愪氦</el-button
+          >
+        </div>
+      </template>
+    </el-dialog>
+    <!-- 閫夋嫨鏁欐潗寮规 -->
+    <el-dialog v-model="selectTextBookDialog" width="1000" align-center>
+      <template #title>閫夋嫨鏁欐潗</template>
+      <div class="textBookList" v-loading="textBookPages.loading">
+        <div class="headerBox" style="padding: 10px">
+          <div class="searchBox" style="float: right">
+            <el-input
+              v-model="selectName"
+              @clear="getTextBook"
+              clearable
+              placeholder="璇疯緭鍏ュ叧閿瓧"
+            >
+              <template #append>
+                <el-button
+                  type="primary"
+                  class="searchBtn"
+                  :icon="Search"
+                  @click="getTextBook"
+                />
+              </template>
+            </el-input>
+          </div>
+        </div>
+        <div style="min-height: 370px" v-if="textBookListData.length > 0">
+          <div
+            v-for="(item, index) in textBookListData"
+            :key="index"
+            class="textBookItem"
+          >
+            <el-checkbox
+              class="checkBox"
+              v-model="item.check"
+              @change="selectChange(item)"
+            />
+            <div class="imgBox autoImgBox">
+              <img :src="item.img" />
+            </div>
+            <p>{{ item.product.name }}</p>
+          </div>
+        </div>
+        <div
+          class="nullBox"
+          v-if="!textBookPages.loading && textBookListData.length == 0"
+        >
+          <el-empty />
+        </div>
+      </div>
+      <div class="pagination-box" v-if="textBookListData.length > 0">
+        <el-pagination
+          v-model:current-page="textBookPages.page"
+          v-model:page-size="textBookPages.pageSize"
+          :background="false"
+          layout="total, prev, pager, next"
+          :total="textBookPages.count"
+          @current-change="handleCurrentChange"
+        />
+      </div>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button @click="selectTextBookDialog = false">鍙栨秷</el-button>
+          <el-button type="primary" @click="selectTextBookSubmit">纭畾</el-button>
+        </div>
+      </template>
+    </el-dialog>
   </div>
 </template>
+
+<script setup lang="ts">
+import { reactive, ref, onMounted, inject, watch } from "vue";
+import { Search } from "@element-plus/icons-vue";
+import { useRouter, useRoute } from "vue-router";
+import { ElMessage } from "element-plus";
+// eslint-disable-next-line
+import { getPublicImage } from "@/assets/js/middleGround/tool.js";
+// eslint-disable-next-line
+import defaultImg from "@/assets/images/default-book-img.png";
+
+const router: any = useRouter();
+const route: any = useRoute();
+const MG: any = inject("MG");
+const selectName = ref("");
+
+// 鐢宠寮�璇鹃槻鎶杔oading
+const submitLoading = ref(false);
+
+const courseList: any = ref([]);
+
+onMounted(() => {
+  getData();
+});
+
+const searchKey = ref("");
+const pages = reactive({
+  page: 1,
+  pageSize: 6,
+  count: 0,
+  loading: true,
+});
+
+// 鑾峰彇璇剧▼
+const getData = () => {
+  pages.loading = true;
+  MG.edu
+    .getAppCourseList({
+      size: pages.pageSize,
+      start: pages.pageSize * pages.page - pages.pageSize,
+      sort: {
+        type: "Desc",
+        field: "CreateDate",
+      },
+      filterList: [],
+      searchList: searchKey.value
+        ? [
+            {
+              keywords: searchKey.value,
+              field: "Name",
+              compareType: "Contains",
+            },
+          ]
+        : [],
+    })
+    .then((res: any) => {
+      pages.loading = false;
+      pages.count = res.totalSize;
+      courseList.value = res.datas.map((item: any) => {
+        return {
+          ...item,
+          name: item.name,
+          id: item.id,
+          icon: item.icon != "default" ? getPublicImage(item.icon, 80) : defaultImg,
+          introduction: item.description,
+          reason: item.applyReturnMsg ? JSON.parse(item.applyReturnMsg).reason : "",
+        };
+      });
+    });
+};
+
+// 鐢宠寮�璇�
+const applyCourse = () => {
+  editData.value = null;
+  formData.value = {
+    name: "",
+    bookName: "",
+    bookId: "",
+    selectData: "",
+    desc: "",
+  };
+  applyCourseDialog.value = true;
+};
+
+const editData: any = ref(null);
+const reapplyCourse = (data: any) => {
+  editData.value = data;
+  formData.value = {
+    name: data.name,
+    bookName: data.linkProduct.name,
+    bookId: data.linkProduct.id,
+    selectData: "",
+    desc: data.description,
+  };
+  applyCourseDialog.value = true;
+};
+
+// 鐢宠鏁欐潗寮规
+const applyCourseDialog = ref(false);
+const selectTextBookDialog = ref(false);
+const formData = ref({
+  name: "",
+  bookName: "",
+  bookId: "",
+  selectData: "",
+  desc: "",
+});
+
+const selectChange = (select: any) => {
+  for (let i = 0; i < textBookListData.value.length; i++) {
+    const item: any = textBookListData.value[i];
+    if (item.id == select.id) {
+      item.check = true;
+    } else {
+      item.check = false;
+    }
+  }
+};
+
+const selectTextBookSubmit = () => {
+  const selectData: any = textBookListData.value.filter((item: any) => item.check)[0];
+  if (!selectData?.product?.id) {
+    ElMessage.warning("璇烽�夋嫨寮�璇炬暀鏉愶紒");
+    return false;
+  }
+  formData.value.bookId = selectData.product.id;
+  formData.value.bookName = selectData.product.name;
+  formData.value.selectData = selectData;
+  selectTextBookDialog.value = false;
+};
+
+const submit = () => {
+  submitLoading.value = true;
+  if (editData.value) {
+    MG.edu
+      .updateCourse({
+        courseId: editData.value.id,
+        name: formData.value.name,
+        description: formData.value.desc,
+      })
+      .then((res: any) => {
+        MG.edu
+          .updateCourseApply({
+            courseId: editData.value.id,
+            applyData: JSON.stringify({
+              textBookId: formData.value.bookId,
+              textBookName: formData.value.bookName,
+            }),
+          })
+          .then((ares: any) => {
+            ElMessage.success("璇剧▼宸查噸鏂扮敵璇凤紝绛夊緟绠$悊鍛樺鏍搞��");
+            applyCourseDialog.value = false;
+            getData();
+          });
+      });
+  } else {
+    if (formData.value.name == "") {
+      ElMessage({
+        type: "warning",
+        message: "璇峰~鍐欒绋嬪悕绉�",
+      });
+      submitLoading.value = false;
+      return false;
+    }
+    if (!formData.value.bookId) {
+      ElMessage({
+        type: "warning",
+        message: "璇烽�夋嫨鍏宠仈鏁欐潗",
+      });
+      submitLoading.value = false;
+      return false;
+    }
+    MG.edu
+      .applyNewCourse({
+        name: formData.value.name,
+        description: formData.value.desc,
+        content: "",
+        icon: formData.value.selectData.product.icon ?? "default",
+        type: "course",
+        config: "",
+        applyData: JSON.stringify({
+          textBookId: formData.value.bookId,
+          textBookName: formData.value.bookName,
+        }),
+        linkProductId: formData.value.bookId,
+        maxClassCount: 999,
+        payPrice: 0,
+      })
+      .then((res: any) => {
+        if (res) {
+          ElMessage.success("璇剧▼宸茬敵璇凤紝绛夊緟绠$悊鍛樺鏍搞��");
+          applyCourseDialog.value = false;
+          getData();
+        }
+      });
+  }
+  formData.value.selectData = "";
+  setTimeout(() => {
+    submitLoading.value = false;
+  }, 1000);
+};
+
+// 鑾峰彇宸茶喘涔扮殑鏁欐潗鍒楄〃
+const textBookPages = reactive({
+  page: 1,
+  pageSize: 12,
+  count: 0,
+  loading: false,
+});
+const textBookListData = ref([]);
+
+const getTextBook = () => {
+  textBookPages.loading = true;
+  const searchData = [
+    {
+      keywords: "jsek_digitalTextbooks",
+      field: "ProductType",
+    },
+    {
+      keywords: "jsek_mediaBook",
+      field: "ProductType",
+    },
+    {
+      keywords: selectName.value,
+      field: "ProductName",
+    },
+  ];
+  const data = {
+    Size: textBookPages.pageSize,
+    Start: textBookPages.pageSize * textBookPages.page - textBookPages.pageSize,
+    sort: {
+      type: "Desc",
+      field: "CreateDate",
+    },
+    searchList: searchData,
+  };
+  MG.store
+    .getPurchasedProductList(data)
+    .then((res: any) => {
+      textBookPages.count = res.totalSize;
+      textBookListData.value = res.datas.map((item: any) => {
+        return {
+          ...item,
+          img: item.product.icon ? getPublicImage(item.product.icon, 80) : defaultImg,
+        };
+      });
+      textBookPages.loading = false;
+    })
+    .catch(() => {
+      textBookPages.loading = false;
+    });
+};
+
+// 閫夋嫨鏁欐潗
+const selectBook = () => {
+  selectTextBookDialog.value = true;
+  textBookListData.value = [];
+  getTextBook();
+};
+
+const pageChange = (val: any) => {
+  pages.page = val;
+  getData();
+};
+const handleCurrentChange = (val: any) => {
+  textBookPages.page = val;
+  getTextBook();
+};
+
+const gotoDetail = (data: any) => {
+  if (data.applyState == "Normal") {
+    router.push({
+      name: "courseDetail",
+      query: {
+        courseId: data.id,
+      },
+    });
+  }
+};
+</script>
+
+<style lang="less" scoped>
+.coursePage {
+  .headerBox {
+    padding: 20px;
+    margin-bottom: 10px;
+    overflow: hidden;
+
+    .searchBox {
+      width: 300px;
+      float: left;
+
+      .searchBtn {
+        background-color: var(--el-color-primary);
+        color: #fff;
+        border-top-left-radius: 0;
+        border-bottom-left-radius: 0;
+      }
+    }
+
+    .applyStartClasses {
+      float: right;
+    }
+  }
+
+  .courseListBox {
+    overflow: hidden;
+    min-height: 200px;
+
+    .courseItem {
+      float: left;
+      width: 46%;
+      height: 210px;
+      margin: 0 2% 20px;
+      border-radius: 8px;
+      border: 1px solid #efefef;
+      overflow: hidden;
+      cursor: pointer;
+
+      .itemHeader {
+        height: 40px;
+        line-height: 40px;
+        padding: 0 20px;
+        background-color: #f8f8f8;
+        .title {
+          font-weight: 600;
+        }
+
+        div {
+          width: 100%;
+          white-space: nowrap;
+          overflow: hidden;
+          text-overflow: ellipsis;
+          word-break: break-all;
+        }
+      }
+
+      .reasonBox {
+        display: flex;
+        padding: 5px 20px;
+        cursor: default;
+        span {
+          font-size: 12px;
+          line-height: 24px;
+          white-space: nowrap;
+          overflow: hidden;
+          text-overflow: ellipsis;
+        }
+      }
+
+      .itemInfo {
+        padding: 10px 20px;
+        flex: 1;
+        display: flex;
+        .imgBox {
+          width: 90px;
+          height: 120px;
+          margin-right: 20px;
+        }
+        .infoBox {
+          flex: 1;
+          font-size: 14px;
+          p {
+            margin-bottom: 10px;
+          }
+          .introduction {
+            height: 88px;
+            line-height: 22px;
+            display: -webkit-box;
+            -webkit-box-orient: vertical;
+            -webkit-line-clamp: 4;
+            overflow: hidden;
+            text-overflow: ellipsis;
+            word-break: break-all;
+          }
+        }
+        .stateIcon {
+          position: absolute;
+          right: -6px;
+          top: -4px;
+          padding: 5px 8px;
+          color: #fff;
+          border-top-left-radius: 30px;
+          border-bottom-right-radius: 30px;
+          border-top-right-radius: 30px;
+          z-index: 99;
+        }
+      }
+    }
+  }
+}
+
+.textBookList {
+  overflow: hidden;
+  margin-bottom: 20px;
+  .textBookItem {
+    float: left;
+    width: 140px;
+    height: 200px;
+    margin: 10px;
+    position: relative;
+    border: 1px solid #eee;
+    padding: 20px;
+    box-sizing: border-box;
+    .checkBox {
+      position: absolute;
+      right: 0;
+      top: 0;
+      height: 14px;
+      ::v-deep {
+        .el-checkbox__inner {
+          border-color: #888;
+        }
+      }
+    }
+
+    .imgBox {
+      width: 100px;
+      height: 110px;
+      margin-bottom: 10px;
+    }
+
+    p {
+      line-height: 1.2;
+      display: -webkit-box;
+      -webkit-line-clamp: 2;
+      -webkit-box-orient: vertical;
+      overflow: hidden;
+    }
+  }
+}
+
+.pagination-box {
+  display: flex;
+  justify-content: center;
+  padding: 10px 0;
+}
+
+.nullBox {
+  text-align: center;
+  margin-top: 30px;
+  font-size: 20px;
+  color: #ccc;
+}
+</style>
diff --git a/src/views/personalCenter/myApply.vue b/src/views/personalCenter/myApply.vue
index 76ac409..2812c8e 100644
--- a/src/views/personalCenter/myApply.vue
+++ b/src/views/personalCenter/myApply.vue
@@ -1,3 +1,318 @@
+<!-- 鍩烘湰淇℃伅 -->
 <template>
-  <div>鎴戠殑鐢宠</div>
+  <div class="personalPage-box">
+    <div class="personalPage-title">鎴戠殑鐢宠</div>
+    <div class="personalPage-content">
+      <div class="tipsText">
+        <div>
+          濡傛偍鍦ㄦ暀鏉愯瘯鐢ㄧ敵璇疯繃绋嬩腑閬囧埌闂锛岃浜庡伐浣滄椂闂磋仈绯绘垜浠��<span class="phone">
+            QQ鍙凤細3565269931 / 鍜ㄨ鐢佃瘽010-65778403锛堝伐浣滄椂闂达細9:00锝�17:00锛�
+          </span>
+        </div>
+      </div>
+      <div class="stageBtm" v-for="(item, index) in listData" :key="index">
+        <div class="infor">
+          <div class="infoBox">
+            <div>
+              瀹℃牳鐘舵��:
+              <span
+                :class="{
+                  reviewstatus: true,
+                  reviewstatusRed: item.state == 'Reject',
+                  reviewstatusWait: item.state == 'WaitAudit',
+                }"
+                >{{
+                  item.state == "WaitAudit"
+                    ? "瀹℃牳涓�"
+                    : item.state == "Normal"
+                    ? "閫氳繃"
+                    : "鎷掔粷"
+                }}</span
+              >
+            </div>
+            <div
+              style="color: orangered"
+              v-if="item.state == 'Normal' && item.feedBack && !item.isExpiry"
+            >
+              璇曠敤鏈熼檺锛�<span>{{ item.updateDate }}</span> --
+              <span>{{ item.feedBack.endDate }}</span>
+            </div>
+            <div style="color: orangered" v-if="item.isExpiry">
+              闃呰鏈熼檺锛�<span>宸茶繃鏈�</span>
+            </div>
+            <div class="time">鐢宠鏃堕棿锛歿{ item.updateDate }}</div>
+          </div>
+          <div
+            class="reasonForFailure"
+            style="margin: 10px 0"
+            v-if="item.state == 'Reject'"
+          >
+            <div class="centerVertically">鏈�氳繃鍘熷洜:</div>
+            <div
+              style="flex: 1"
+              class="ellipsis-3"
+              :title="item.feedBack.reason ? item.feedBack.reason : ' - '"
+            >
+              {{ item.feedBack.reason ? item.feedBack.reason : " - " }}
+            </div>
+          </div>
+        </div>
+        <div class="contentInfoBox">
+          <div class="listImg">
+            <img @click.stop="toDetail(item.content)" :src="item.content.icon" alt="" />
+            <div class="name" :title="item.content.title">
+              {{ item.content.title }}
+            </div>
+            <el-button
+              size="mini"
+              v-if="item.state == 'Normal' && !item.isExpiry"
+              @click="read(item.content)"
+              >寮�濮嬮槄璇�</el-button
+            >
+          </div>
+        </div>
+      </div>
+      <div
+        style="min-height: 100px"
+        v-if="listData && listData.length > 0"
+        v-loading="loading"
+      ></div>
+    </div>
+    <div v-if="listData && listData.length == 0 && !loading">
+      <el-empty :image-size="200" description="鏆傛棤鍐呭"></el-empty>
+    </div>
+    <div class="pageBox" v-if="listData && listData.length > 0">
+      <!-- 鍒嗛〉 -->
+      <el-pagination
+        background
+        :current-page="paginationData.page - 0"
+        @size-change="handleSizeChange"
+        @current-change="handleCurrentChange"
+        :page-size="paginationData.limit"
+        layout="total, prev, pager, next, slot"
+        :total="paginationData.totalCount"
+      >
+        <div style="display: inline-block">
+          <span class="el-pagination__jump"
+            >鍓嶅線
+            <div class="el-input el-pagination__editor is-in-pagination">
+              <input
+                type="number"
+                autocomplete="off"
+                min="1"
+                :max="paginationData.totalPage"
+                v-model="inputPage"
+                class="el-input__inner"
+                @keyup.enter="jumpFun($event)"
+              />
+            </div>
+            椤�
+          </span>
+          <el-button type="primary" class="toBtn" @click="jumpFun">纭畾</el-button>
+        </div>
+      </el-pagination>
+    </div>
+  </div>
 </template>
+<script setup lang="ts">
+import { reactive, ref, onMounted, inject } from "vue";
+import { getPublicImage } from "@/assets/js/middleGround/tool";
+const MG: any = inject("MG");
+const config: any = inject("config");
+const crumbStore = inject("crumbStore");
+const router = inject("router");
+let listData = ref([]);
+let loading = ref(false);
+let paginationData = reactive({
+  page: 1,
+  limit: 10,
+  totalCount: 0,
+  totalPage: 0,
+});
+let inputPage = ref(1);
+
+const getTextBookList = () => {
+  loading.value = true;
+  let { page, limit } = paginationData;
+  const data = {
+    start: limit * page - limit,
+    size: limit,
+    topicIdOrRefCode: "applyDigitalBook",
+    appRefCode: config.appRefCode,
+    sort: {
+      type: "Desc",
+      field: "CreateDate",
+    },
+  };
+  MG.ugc.getTopicMessageList(data).then((res) => {
+    loading.value = false;
+    res.datas.forEach((item) => {
+      item.icon = item.icon ? item.icon : getPublicImage(null);
+      item.updateDate = item.updateDate.split("T")[0];
+      if (item.feedBack) {
+        item.feedBack = JSON.parse(item.feedBack);
+        if (item.feedBack.endDate) {
+          let times = new Date(item.feedBack.endDate + " 23:59:59").getTime();
+          if (times < sessionStorage.currentDate) {
+            item.isExpiry = true;
+          }
+        }
+      }
+      if (item.content) {
+        item.content = JSON.parse(item.content)[0] ?? {};
+        if (!item.content?.icon) {
+          item.content.icon = require("@/assets/images/default-book-img.png");
+        }
+      }
+    });
+    paginationData.totalCount = res.totalSize;
+    paginationData.totalPage = Math.ceil(res.totalSize / limit);
+    listData.value = res.datas;
+  });
+};
+onMounted(() => {
+  getTextBookList();
+});
+
+const toDetail = (item: any) => {
+  const thisCrumbs = [{ name: "涔︾睄璇︽儏", pathName: "digitalTextbooks-textbooksDetail" }];
+  MG.store.dispatch("setCrumbs", {
+    type: "textbooks",
+    data: thisCrumbs,
+    callback: (key: string) => {
+      MG.router.push({
+        name: "digitalTextbooks-textbooksDetail",
+        query: {
+          id: item.id,
+          rootCmsItemId: item.rootCmsItemId,
+          crumbsKey: key,
+        },
+      });
+    },
+  });
+};
+const read = (pItem: any) => {
+  let token = MG.tool.getCookie(config.tokenKey);
+  window.open(config.textReaderUrl + "?bookId=" + pItem.refCode + "&token=" + token);
+};
+const handleSizeChange = (val: number) => {
+  paginationData.limit = val;
+  getTextBookList();
+};
+const handleCurrentChange = (val: number) => {
+  paginationData.page = val;
+  getTextBookList();
+};
+const jumpFun = (event: any) => {
+  event.target.blur();
+  if (inputPage.value <= 0) {
+    inputPage.value = 1;
+  }
+  if (inputPage.value > paginationData.totalPage) {
+    inputPage.value = paginationData.totalPage;
+  }
+  paginationData.page = inputPage.value;
+  getTextBookList();
+};
+</script>
+<style scoped lang="less">
+.myCarTopPage {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 10px 15px;
+  box-sizing: border-box;
+  background-color: #fff;
+  border-bottom: 1px solid #dcdcdc;
+}
+.tipsText {
+  padding: 10px 15px;
+  line-height: 20px;
+  box-sizing: border-box;
+  border: 1px solid #ccc;
+  .phone {
+    color: #019e58;
+  }
+  margin-bottom: 10px;
+}
+
+.pageBox {
+  background-color: #fff;
+  margin-top: 50px;
+}
+.stageBtm {
+  border: 1px solid #dcdcdc;
+  .infor {
+    border-bottom: 1px solid #dcdcdc;
+    padding: 0 15px;
+    .infoBox {
+      line-height: 45px;
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      .time {
+        color: #999;
+      }
+    }
+    .reasonForFailure {
+      display: flex;
+      margin: 10px 0;
+      line-height: 1.5;
+      .centerVertically {
+        width: 80px;
+      }
+      /* 鍙岃鐪佺暐 */
+      .ellipsis-3 {
+        text-overflow: -o-ellipsis-lastline;
+        overflow: hidden;
+        text-overflow: ellipsis;
+        display: -webkit-box;
+        -webkit-line-clamp: 3;
+        line-clamp: 3;
+        -webkit-box-orient: vertical;
+      }
+    }
+  }
+  .contentInfoBox {
+    padding: 15px;
+    box-sizing: border-box;
+    .listImg {
+      display: inline-block;
+      margin-right: 60px;
+      width: 120px;
+      img {
+        width: 120px;
+        cursor: pointer;
+      }
+      .name {
+        line-height: 27px;
+        font-size: 15px;
+        color: #333;
+        overflow: hidden;
+        text-overflow: ellipsis;
+        white-space: nowrap;
+      }
+    }
+  }
+}
+
+.reviewstatus {
+  color: #0bc266;
+}
+.reviewstatusWait {
+  color: #ffbe00;
+}
+.reviewstatusRed {
+  color: red;
+}
+
+.timer {
+  color: rgb(240, 67, 67);
+}
+</style>
+<style>
+.el-pagination {
+  text-align: center;
+  margin-top: 15px;
+}
+</style>
diff --git a/src/views/personalCenter/myBook.vue b/src/views/personalCenter/myBook.vue
index 191e50d..7b08426 100644
--- a/src/views/personalCenter/myBook.vue
+++ b/src/views/personalCenter/myBook.vue
@@ -1,7 +1,329 @@
 <template>
-  <div class="myBook">
-    <div class="myBook_header">
-      <div class="myBook_header_title">鎴戠殑璁㈠崟</div>
+  <div class="personalPage-box">
+    <div class="personalPage-title">鎴戠殑涔︽灦</div>
+    <div class="personalPage-content">
+      <div class="pageBox cartPage" v-loading="isLoading">
+        <div class="myCarTopPage" v-if="collectList.length > 0">
+          <div
+            class="bookone"
+            v-for="(item, index) in collectList"
+            :key="index"
+            @click="goDetail(item)"
+          >
+            <div class="imgBox">
+              <img :src="item.product.icon" alt />
+            </div>
+            <div class="details">
+              <div class="text-flow" v-if="item.product.name">
+                {{ item.product.name || "-" }}
+              </div>
+              <div class="text-flow" :title="item.tourism_ISBN">
+                ISBN锛歿{ item.tourism_ISBN.length != 0 ? item.tourism_ISBN : "-" }}
+              </div>
+              <div class="text-flow">
+                浣滆�咃細{{ item.tourism_author.length != 0 ? item.tourism_author : "-" }}
+              </div>
+              <!-- <div class="text-flow" v-if="item.ExpiryDate">
+            鎴鏃ユ湡锛�<span style="color: #dd0000">{{ item.ExpiryDate }}</span>
+          </div> -->
+            </div>
+          </div>
+          <div class="pageCon">
+            <!-- 鍒嗛〉 -->
+            <el-pagination
+              background
+              :current-page="paginationData.page - 0"
+              @size-change="handleSizeChange"
+              @current-change="handleCurrentChange"
+              :page-size="paginationData.limit"
+              layout="total, prev, pager, next, slot"
+              :total="paginationData.totalCount"
+            >
+              <div style="display: inline-block">
+                <span class="el-pagination__jump"
+                  >鍓嶅線
+                  <div class="el-input el-pagination__editor is-in-pagination">
+                    <input
+                      type="number"
+                      autocomplete="off"
+                      min="1"
+                      :max="paginationData.totalPage"
+                      v-model="inputPage"
+                      class="el-input__inner"
+                      @keyup.enter="jumpFun($event)"
+                    />
+                  </div>
+                  椤�
+                </span>
+                <el-button type="primary" class="toBtn" @click="jumpFun">纭畾</el-button>
+              </div>
+            </el-pagination>
+          </div>
+        </div>
+        <div class="myCarTopPage" v-else>
+          <el-empty description="鎮ㄨ繕鏈喘涔颁换浣曞浘涔�" :image-size="200" />
+        </div>
+      </div>
     </div>
   </div>
 </template>
+
+<script lang="ts" setup>
+import { reactive, ref, onMounted, inject, watch } from "vue";
+import { useRouter } from "vue-router";
+import { useUserStore, useBreadcrumbStore } from "@/store";
+import tool from "@/assets/js/toolClass";
+const MG: any = inject("MG");
+const config: any = inject("config");
+const router = useRouter();
+const crumbStore = useBreadcrumbStore();
+let collectList = ref([]);
+let currentCollect = ref("book");
+let isLoading = ref(false);
+let pages = reactive({
+  page: 1,
+  pageSize: 10,
+  count: 0,
+  loading: false,
+});
+let linkType = ref("PurchasedProduct");
+let paginationData = reactive({
+  page: 1,
+  limit: 10,
+  totalCount: 0,
+  totalPage: 0,
+});
+let inputPage = ref(1);
+const loading = ref(false);
+const listData = ref([]);
+const keyQueryRequests = [
+  {
+    key: "author",
+  },
+  {
+    key: "isbn",
+  },
+];
+
+const getData = () => {
+  loading.value = true;
+  const searchData = [
+    {
+      keywords: "digitalTextbooks",
+      field: "ProductType",
+    },
+  ];
+  const data = {
+    Size: paginationData.limit,
+    Start: (paginationData.page - 1) * paginationData.limit,
+    sort: {
+      type: "Desc",
+      field: "CreateDate",
+    },
+    searchList: searchData,
+    keyQueryRequests: keyQueryRequests,
+  };
+  MG.store.getPurchasedProductList(data).then(async (response) => {
+    listData.value = handResultsChange(response.datas);
+    listData.value.forEach((item) => {
+      item.product.icon = tool.getPublicImage(item.product.icon);
+    });
+    // console.log(that.collectList);
+    // //褰撳墠椤甸潰
+    paginationData.totalCount = response.totalSize;
+    paginationData.totalPage =
+      response.totalSize % paginationData.limit === 0
+        ? response.totalSize / paginationData.limit
+        : Math.floor(response.totalSize / paginationData.limit) + 1;
+    loading.value = false;
+  });
+};
+onMounted(() => {
+  getData();
+});
+// 澶勭悊鏌ヨ缁撴灉
+const handResultsChange = (data) => {
+  let fieldsData = [];
+  for (let i = 0; i < data.length; i++) {
+    const item = data[i];
+    for (const val in keyQueryRequests) {
+      fieldsData.push(keyQueryRequests[val].key);
+    }
+    for (let i = 0; i < fieldsData.length; i++) {
+      const field = fieldsData[i];
+      item[field] = JSON.parse(item.datas[field]);
+      const datas = item[field];
+      if (datas.length > 0) {
+        if (datas[0].Value) {
+          item[field] = datas[0].Value;
+        } else if (datas[0].Data) {
+          item[field] = datas[0].Data.Value;
+        }
+      }
+    }
+  }
+  return data;
+};
+
+//鍒板浘涔﹁鎯�
+const goDetail = (item) => {
+  let crumbs = [
+    {
+      name: "鏁欐潗璇︽儏",
+    },
+  ];
+  crumbStore.dispatch("setCrumbs", {
+    type: "textbooks",
+    data: crumbs,
+    callback: (key) => {
+      router.push({
+        name: "digitalTextbooks-textbooksDetail",
+        query: {
+          id: item.product.id,
+          rootCmsItemId: item.product.rootCmsItemId,
+          crumbsKey: key,
+        },
+      });
+    },
+  });
+};
+
+//鍒嗛〉
+const handleSizeChange = (val) => {
+  paginationData.limit = val;
+  getData();
+};
+const handleCurrentChange = (val) => {
+  paginationData.page = val;
+  inputPage.value = val;
+  getData();
+};
+const jumpFun = (event) => {
+  event.target.blur();
+  var that = this;
+  if (inputPage.value <= 0) {
+    inputPage.value = 1;
+  }
+  if (inputPage.value > paginationData.totalPage) {
+    inputPage.value = paginationData.totalPage;
+  }
+  paginationData.page = inputPage.value;
+  getData();
+};
+</script>
+<style scoped>
+.pageCon {
+  width: 100%;
+  float: left;
+  margin-top: 20px;
+  display: flex;
+  justify-content: center;
+}
+.myCarTopPage {
+  box-sizing: border-box;
+  overflow: hidden;
+  padding-bottom: 20px;
+}
+.details div:first-child {
+  font-size: 16px;
+  color: #2b68cd;
+  margin-bottom: 11px;
+}
+
+.details div:nth-child(2) {
+  font-size: 14px;
+  color: #666;
+  margin: 15px 0;
+}
+
+.details div:nth-child(3) {
+  margin-bottom: 11px;
+  display: flex;
+  align-items: center;
+}
+.details div:last-child {
+  font-size: 14px;
+  color: #666666;
+}
+.resonBox {
+  display: flex;
+  line-height: 24px;
+}
+.resonTxt {
+  flex: 1;
+  overflow: hidden;
+  line-height: 24px;
+  text-overflow: ellipsis;
+  display: -webkit-box;
+  -webkit-line-clamp: 3;
+  flex-direction: column;
+}
+
+.bookoneTitle {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding-bottom: 10px;
+  border-bottom: 1px solid #ddd;
+}
+.bookone {
+  display: flex;
+  width: 478px;
+  min-height: 173px;
+  float: left;
+  cursor: pointer;
+  box-sizing: border-box;
+  margin: 20px 0px 0 20px;
+  padding: 10px 30px;
+  border: 1px solid #ddd;
+}
+.bookone:hover {
+  -moz-box-shadow: 4px 3px 6px rgba(0, 0, 0, 0.3);
+  -webkit-box-shadow: 4px 3px 6px rgba(0, 0, 0, 0.3);
+  box-shadow: 4px 3px 6px rgba(0, 0, 0, 0.3);
+}
+
+.bookone .imgBox {
+  position: relative;
+  width: 120px;
+  height: 160px;
+  background: #fff;
+}
+.newBookli .imgBox {
+  position: relative;
+  width: 105px;
+  height: 140px;
+}
+
+.imgBox img {
+  width: auto;
+  height: auto;
+  max-width: 100%;
+  max-height: 100%;
+  position: absolute;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  margin: auto;
+}
+
+.details {
+  flex: 1;
+  margin-left: 10px;
+  margin-top: 10px;
+  overflow: hidden;
+}
+.pageBox {
+  width: 100%;
+}
+.noDataTxt {
+  margin: 50px auto;
+  text-align: center;
+  font-size: 22px;
+  color: #999;
+}
+.el-pagination button {
+  margin-left: 10px;
+}
+</style>
diff --git a/src/views/personalCenter/myCart.vue b/src/views/personalCenter/myCart.vue
index 9e855f4..a726dfc 100644
--- a/src/views/personalCenter/myCart.vue
+++ b/src/views/personalCenter/myCart.vue
@@ -1,3 +1,599 @@
 <template>
-  <div>璐墿杞�</div>
+  <div class="personalPage-box">
+    <div class="personalPage-title">鎴戠殑璐墿杞�</div>
+    <div class="personalPage-content">
+      <div class="deleteBox">
+        <el-dialog
+          v-model="dialogVisible"
+          width="30%"
+          draggable
+          align-center
+          :modal="false"
+        >
+          <span>
+            <el-icon style="color: orange"> <Warning /> </el-icon
+            >纭瑕佸垹闄ら�変腑鐨勫晢鍝佸悧锛�</span
+          >
+          <template #footer>
+            <span class="dialog-footer">
+              <el-button @click="dialogVisible = false">鍙栨秷</el-button>
+              <el-button type="primary" @click="handleDelete"> 纭畾 </el-button>
+            </span>
+          </template>
+        </el-dialog>
+
+        <el-dialog v-model="showHide" width="30%" draggable align-center :modal="false">
+          <span
+            ><el-icon style="color: orange"> <Warning /> </el-icon
+            >纭瑕佸垹闄ら�変腑鐨勫晢鍝佸悧锛�</span
+          >
+          <template #footer>
+            <span class="dialog-footer">
+              <el-button @click="showHide = false">鍙栨秷</el-button>
+              <el-button type="primary" @click="confirmEvent"> 纭畾 </el-button>
+            </span>
+          </template>
+        </el-dialog>
+      </div>
+
+      <div class="breadcrumbsBox">
+        <p>
+          浣嶇疆锛� <span>璐墿杞�({{ total }})</span>
+        </p>
+      </div>
+      <div class="selectproduct">
+        <el-table
+          ref="multipleTableRef"
+          :data="shoppingCartData"
+          style="width: 100%"
+          @selection-change="handleSelectionChange"
+          :cell-style="cellStyle"
+          v-loading="loading"
+        >
+          <template v-slot:empty>
+            <el-empty class="noData" image-size="100" description="鏆傛棤鏁版嵁" />
+          </template>
+
+          <el-table-column type="selection" width="30" />
+
+          <el-table-column label="鍏ㄩ��" width="200">
+            <template #default="scope">
+              <div style="position: relative; width: 110px">
+                <el-image
+                  :src="scope.row.imgUrl ? scope.row.imgUrl : defaultImg"
+                  class="bookImg"
+                >
+                </el-image>
+                <div
+                  class="labelBox"
+                  :style="{
+                    background: scope.row.type == 'product' ? '#019e58 ' : '#5f92fd',
+                  }"
+                >
+                  <p>{{ scope.row.typeTxt }}</p>
+                </div>
+              </div>
+            </template>
+          </el-table-column>
+
+          <el-table-column
+            property="name"
+            label="鍟嗗搧淇℃伅"
+            width="300"
+            :cell-style="{ margin: '30px' }"
+          />
+          <el-table-column property="productType" label="鍟嗗搧绫诲瀷" width="300" />
+          <el-table-column label="浠锋牸">
+            <template #default="scope">楼{{ scope.row.unitprice.toFixed(2) }}</template>
+          </el-table-column>
+          <el-table-column label="鎿嶄綔">
+            <template #default="scope">
+              <span @click="dialog(scope.$index, scope.row)" class="deleteBtn">鍒犻櫎</span>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+    </div>
+    <div class="settlement">
+      <div class="box">
+        <div class="gaugeOutfit">
+          <div class="leftBox">
+            <el-checkbox
+              v-if="shoppingCartData.length"
+              class="checkbox"
+              v-model="selectAll"
+              label="鍏ㄩ��"
+              name="type"
+              @change="toggleAllSelection"
+            />
+            <el-checkbox
+              v-else
+              class="checkbox"
+              v-model="select"
+              disabled
+              label="鍏ㄩ��"
+              name="type"
+              @change="toggleAllSelection"
+            />
+            <el-button class="buttonBox" @click="batchDelete">鎵归噺鍒犻櫎</el-button>
+          </div>
+
+          <div class="rightBox">
+            <p>
+              宸查�夋嫨 <span>{{ selectedItemCount }}</span> 浠跺晢鍝�
+            </p>
+            <p>
+              鎬讳环锛�<span v-if="sumUnitprice">楼{{ sumUnitprice.toFixed(2) }}</span>
+              <span v-else>楼0.00</span>
+            </p>
+            <el-button class="button" type="warning" @click="goPaymentPage"
+              >缁撶畻</el-button
+            >
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
 </template>
+
+<script setup lang="ts">
+import { onMounted, ref, inject, watch } from "vue";
+import { ElTable, ElMessage } from "element-plus";
+import { reactive } from "vue";
+import { useRouter } from "vue-router";
+import { InfoFilled } from "@element-plus/icons-vue";
+import { useUserStore, useBreadcrumbStore } from "@/store";
+import { getPublicImage } from "@/assets/js/middleGround/tool.js";
+import defaultImg from "@/assets/images/default-book-img.png";
+const dialogVisible = ref(false);
+const crumbStore = useBreadcrumbStore();
+const router = useRouter();
+const userStore = useUserStore();
+const MG = inject("MG");
+const total = ref();
+const multipleTableRef = ref();
+const loading = ref(true);
+const selectAll = ref(false);
+const multipleSelection = ref([]);
+const orderNumber = ref();
+const select = ref(false);
+const showHide = ref(false);
+const selectedItemCount = ref(0); // 鏂板涓�涓彉閲忕敤浜庡瓨鍌ㄥ凡閫夊晢鍝佹暟閲�
+const sumUnitprice = ref();
+
+watch(multipleSelection, (newSelection) => {
+  // 褰� multipleSelection.value 鍙戠敓鍙樺寲鏃惰Е鍙戠殑鍥炶皟鍑芥暟
+  let sum = 0;
+  newSelection.forEach((item) => {
+    sum += item.unitprice;
+  });
+
+  sumUnitprice.value = sum;
+
+  selectedItemCount.value = newSelection.length;
+});
+
+onMounted(() => {
+  shoppingCartGet();
+  // totalPrice()
+});
+const batchDelete = (evt) => {
+  let target = evt.target;
+  if (target.nodeName == "SPAN") {
+    target = evt.target.parentNode;
+  }
+  target.blur();
+  if (multipleSelection.value.length === 0) {
+    // 濡傛灉娌℃湁閫夋嫨浠讳綍鍟嗗搧锛屽彲浠ュ湪姝ゅ缁欏嚭鎻愮ず鎴栬�呯洿鎺ヨ繑鍥�
+    ElMessage({
+      message: "鏈�夋嫨鍟嗗搧",
+      type: "warning",
+    });
+  } else {
+    showHide.value = true;
+    // showHide.value = false
+  }
+};
+
+const handleSelectionChange = (val) => {
+  // console.log(val);
+
+  multipleSelection.value = val;
+  // 鍒ゆ柇鏄惁鍏ㄩ儴閫夋嫨
+  if (!delShoppingSelec.value) {
+    if (val.length === shoppingCartData.length) {
+      selectAll.value = true;
+    } else {
+      selectAll.value = false;
+    }
+  }
+};
+
+// 鍒囨崲鎵�鏈夎閫変腑鐘舵�佺殑鏂规硶
+const toggleAllSelection = () => {
+  if (shoppingCartData.length === 0) {
+    selectAll.value = false;
+
+    ElMessage({
+      message: "娌℃湁鍙�夋嫨鐨勫晢鍝�",
+      type: "warning",
+    });
+  } else {
+    multipleTableRef.value.toggleAllSelection();
+  }
+};
+const selectedRow = ref();
+const dialog = (index, row) => {
+  dialogVisible.value = true;
+
+  // 灏嗗綋鍓嶈鏁版嵁瀛樺偍璧锋潵锛屼互澶囧垹闄ゆ椂浣跨敤
+  selectedRow.value = row;
+};
+
+const handleDelete = () => {
+  const row = selectedRow.value;
+  dialogVisible.value = false;
+  MG.store
+    .delShoppingCart({
+      ids: [row.id],
+    })
+    .then((res) => {
+      shoppingCartGet();
+      ElMessage({
+        message: "鍒犻櫎鎴愬姛",
+        type: "success",
+      });
+      //鏇存柊璐墿杞︽暟閲�
+      userStore.updateRightPop();
+    })
+    .catch((error) => {
+      ElMessage.error("鍒犻櫎澶辫触");
+    });
+};
+
+//琛ㄥ崟鐨勬牱寮�
+const cellStyle = ({ row, column, rowIndex, columnIndex }) => {
+  if (columnIndex === 4) {
+    return { color: "#FF6C00" };
+  }
+};
+
+const shoppingCartData = reactive([]);
+
+const shoppingCartGet = () => {
+  let query = {
+    start: 0,
+    size: 999,
+    filterList: [],
+    searchList: [],
+  };
+  MG.store.getShoppingCartProductList(query).then((res) => {
+    const newData = res.datas.map((item) => {
+      console.log(item.saleMethod.type, "item.saleMethod.type");
+      if (item.productMonWithLinkDto.links[0].storeRefCode == "jsek_digitalTextbooks") {
+        item.typeTxt = "鏁板瓧鏁欐潗";
+        item.productType = "鏁板瓧鏁欐潗";
+      } else if (
+        item.productMonWithLinkDto.links[0].storeRefCode == "jsek_digitalCourses"
+      ) {
+        item.typeTxt = "鏁板瓧璇剧▼";
+        item.productType = "鏁板瓧璇剧▼";
+      } else {
+        item.typeTxt = "鐢靛瓙涔�";
+        item.productType = "鍥句功鏈嶅姟-鐢靛瓙涔�";
+      }
+
+      // console.log(item.saleMethod.id);
+      console.log(item.saleMethod.type, "item.saleMethod.type");
+      return {
+        saleMethodId: item.saleMethod.id,
+        id: item.id,
+        name:
+          item.linkCmsItems.length && item.linkCmsItems[0].name
+            ? item.productMonWithLinkDto.product.name + "锛�" + item.linkCmsItems[0].name
+            : item.productMonWithLinkDto.product.name,
+        type: item.saleMethod.type == "createProductItemSaleMethod" ? "item" : "product",
+        typeTxt: item.typeTxt,
+        productType: item.productType,
+        imgUrl: getPublicImage(item.productMonWithLinkDto.product.icon, "", "160"),
+        unitprice: item.saleMethod.price,
+        expire:
+          new Date(item.saleMethod.endDate).getTime() < new Date().getTime() ||
+          new Date().getTime() < new Date(item.saleMethod.beginDate).getTime()
+            ? true
+            : false,
+      };
+    });
+
+    // 閲嶆柊璧嬪�� shoppingCartData.value
+    shoppingCartData.splice(0, shoppingCartData.length, ...newData);
+    loading.value = false;
+  });
+};
+
+//璺宠浆闈㈠寘灞�
+const goPaymentPage = async () => {
+  try {
+    // console.log(multipleSelection.value, 346588998)
+    let expire = multipleSelection.value.filter((item) => item.expire == true);
+    if (expire.length > 0) {
+      ElMessage({
+        message: "鎮ㄩ�夋嫨鐨勫晢鍝佹湁涓嶅湪鏈夋晥鏈熷唴鐨�,璇烽噸鏂伴�夋嫨鍙喘涔板晢鍝�!",
+        type: "warning",
+      });
+    } else {
+      const selectedIds = multipleSelection.value.map((item) => item.id);
+      const saleMethodId = multipleSelection.value.map((item) => item.saleMethodId);
+
+      console.log(saleMethodId, 789);
+
+      let queryCreateOrder = { linkIds: selectedIds };
+      const createOrderResult = await MG.store.shoppingCartCreateOrder(queryCreateOrder);
+      orderNumber.value = createOrderResult.orderNumber;
+
+      if (selectedIds.length) {
+        let crumbs = {
+          name: "璁㈠崟鏀粯", // 闈㈠寘灞戝悕绉�
+          pathName: "paymentPage", // 闈㈠寘灞戣烦杞矾鐢憋紝鍙紶閫� pathName 鎴� path
+          isCrumbs: true, // 闈㈠寘灞戠偣鍑昏烦杞椂鏄惁鍒涘缓鏂扮殑闈㈠寘灞戣褰�
+          type: "shoppingCart", // 濡傛灉闇�瑕佸垱寤烘柊鐨勯潰鍖呭睉璁板綍锛屽垱寤虹殑type
+        };
+        // 鍦ㄥ叏灞�鏁版嵁涓缃潰鍖呭睉
+        crumbStore.setCrumbs({
+          type: "shoppingCart",
+          data: [crumbs],
+          callback: (key) => {
+            router.push({
+              name: "paymentPage",
+              query: {
+                crumbsKey: key,
+                orderNumber: orderNumber.value,
+                // type: route.query.type,
+                type: "shoppingCart",
+                onNorderSaleMethod: saleMethodId,
+              },
+            });
+          },
+        });
+      } else {
+        ElMessage({
+          message: "璇烽�夋嫨鍟嗗搧",
+          type: "warning",
+        });
+      }
+    }
+  } catch (error) {
+    console.error(error);
+    // 閿欒澶勭悊閫昏緫
+  }
+};
+
+const delShoppingSelec = ref();
+
+const confirmEvent = () => {
+  showHide.value = false;
+  if (multipleSelection.value.length === 0) {
+    // 濡傛灉娌℃湁閫夋嫨浠讳綍鍟嗗搧锛屽彲浠ュ湪姝ゅ缁欏嚭鎻愮ず鎴栬�呯洿鎺ヨ繑鍥�
+    return;
+  } else {
+    const selectedIds = multipleSelection.value.map((item) => item.id);
+    MG.store
+      .delShoppingCart({ ids: selectedIds })
+      .then((res) => {
+        delShoppingSelec.value = res;
+        ElMessage({
+          message: "鎵归噺鍒犻櫎鎴愬姛",
+          type: "success",
+        });
+        selectAll.value = false;
+        // 鍒犻櫎鎴愬姛鍚庯紝鍒锋柊璐墿杞﹀垪琛�
+        shoppingCartGet();
+        //鏇存柊璐墿杞︽暟閲�
+        userStore.updateRightPop();
+      })
+      .catch((error) => {
+        console.error("鎵归噺鍒犻櫎澶辫触", error);
+        ElMessage.error("鎵归噺鍒犻櫎澶辫触");
+      });
+  }
+};
+</script>
+
+<style lang="less" scoped>
+.deleteBtn {
+  cursor: pointer;
+  color: #019e58;
+}
+
+page {
+  position: relative;
+  min-height: calc(100vh - 430px);
+}
+
+.bookImg {
+  box-shadow: 0px 3px 6px 1px rgba(0, 0, 0, 0.16);
+
+  /deep/ .el-image__inner {
+    object-fit: contain !important;
+  }
+}
+
+.settlement {
+  width: 100%;
+  box-shadow: 0px -2px 10px 1px rgba(0, 0, 0, 0.08);
+
+  position: sticky;
+
+  left: 0;
+  right: 0;
+  bottom: 0;
+  background-color: #fff;
+  z-index: 2;
+
+  .box {
+    position: relative;
+
+    .gaugeOutfit {
+      padding-left: 12px;
+      box-shadow: 0px -2px 5px 1px rgba(0, 0, 0, 0.02);
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      position: sticky;
+      top: 0;
+      left: 0;
+      right: 0;
+      bottom: 0;
+      z-index: 2;
+      background-color: #fff;
+      height: 60px;
+
+      .leftBox {
+        display: flex;
+        flex-direction: row;
+
+        .checkbox {
+          margin-right: 20px;
+        }
+
+        /deep/ .el-checkbox__input.is-checked + .el-checkbox__label {
+          color: #000 !important;
+        }
+      }
+
+      .rightBox {
+        display: flex;
+        flex-direction: row;
+        align-items: center;
+
+        p {
+          margin: 0 10px;
+          font-size: 14px;
+
+          span {
+            color: #019e58;
+            font-size: 18px;
+          }
+        }
+
+        .button {
+          margin-left: 50px;
+          background-color: #019e58;
+          width: 150px;
+          height: 50px;
+        }
+      }
+    }
+
+    .selected {
+      display: flex;
+      justify-content: center;
+      height: 200px;
+      min-width: 1370px;
+      width: 1370px;
+      margin: 0 auto;
+    }
+  }
+}
+
+.selectproduct {
+  margin-top: 30px;
+}
+
+::v-deep {
+  .el-checkbox__label {
+    margin-left: 6px;
+    color: #000;
+    font-weight: bold;
+  }
+
+  .el-table td.el-table__cell div {
+    margin-right: 20px;
+  }
+
+  .el-table th {
+    background-color: #f3f3f3;
+    color: #000;
+  }
+
+  .el-table td {
+    color: #333333;
+  }
+
+  .el-table--enable-row-transition .el-table__body td.el-table__cell {
+    height: 180px;
+  }
+
+  .el-checkbox__inner {
+    width: 16px;
+    height: 16px;
+  }
+
+  .el-image__inner {
+    box-shadow: 0px 0px 20px 1px #ccc;
+    object-fit: contain !important;
+    width: 110px;
+    height: 140px;
+  }
+
+  .el-icon {
+    margin-right: 10px;
+    font-size: 20px;
+    position: relative;
+    top: 3px;
+    left: 0px;
+  }
+
+  .deleteBox {
+    .el-dialog.is-align-center {
+      width: 350px;
+    }
+
+    .el-dialog__body {
+      display: flex;
+      justify-content: center;
+      font-size: 16px;
+    }
+  }
+
+  .el-table__inner-wrapper::before {
+    height: 0px;
+  }
+}
+
+.labelBox {
+  // width: 50px;
+  padding: 0 4px;
+  height: 25px;
+  color: #fff;
+  position: absolute;
+  top: 0;
+  right: 0;
+  margin: 0 !important;
+  border-radius: 0px 0px 0px 5px;
+
+  p {
+    display: flex;
+    justify-content: center;
+  }
+}
+
+.breadcrumbsBox {
+  height: 60px;
+  border-bottom: 1px solid #f5f5f5;
+
+  p {
+    line-height: 60px;
+    font-size: 14px;
+    color: #545c63;
+  }
+}
+
+.noData {
+  font-size: 26px;
+  font-weight: bold;
+  display: flex;
+  justify-content: center;
+  margin: 0 auto;
+}
+</style>
diff --git a/src/views/personalCenter/myCollection.vue b/src/views/personalCenter/myCollection.vue
index 20bd004..365cd76 100644
--- a/src/views/personalCenter/myCollection.vue
+++ b/src/views/personalCenter/myCollection.vue
@@ -1,3 +1,349 @@
 <template>
-  <div>鎴戠殑鏀惰棌</div>
+  <!-- <page> -->
+  <div class="personalPage-box">
+    <div class="personalPage-title">鎴戠殑鏀惰棌</div>
+    <div class="personalPage-content">
+      <div class="cartClass">
+        <el-tabs v-model="currentCollect" type="capsule" @tab-click="tabCart">
+          <el-tab-pane label="鏁板瓧鏁欐潗" name="textBooks"></el-tab-pane>
+        </el-tabs>
+      </div>
+      <div class="myCarTopPage">
+        <div class="list-box" v-loading="pages.loading">
+          <div
+            :class="
+              currentCollect == 'book' || currentCollect == 'textBooks'
+                ? 'bookCartContent cartContent'
+                : currentCollect == 'course'
+                ? 'courseCartContent cartContent'
+                : 'cartContent'
+            "
+          >
+            <div
+              class="collectList flex jc-sb clear"
+              v-if="collectList.length > 0 && !pages.loading"
+            >
+              <div
+                v-for="(item, index) in collectList"
+                :key="index"
+                class="collectList-item fl"
+              >
+                <div class="cover" @click="goBookDetails(item.id, item.name)">
+                  <img :src="item.icon" alt="" />
+                </div>
+                <div class="info" @click="goBookDetails(item.id, item.name)">
+                  <span>{{ item.name }}</span>
+                </div>
+                <div class="currentBtn hover" @click="setCoolect(item)">
+                  <img
+                    src="@/assets/images/personalCenter/collect-click.png"
+                    alt="star"
+                  />
+                </div>
+              </div>
+            </div>
+            <div v-if="collectList.length == 0 && !pages.loading">
+              <el-empty :image-size="200" description="鏆傛棤鏁版嵁" />
+            </div>
+          </div>
+          <div class="pagination-box">
+            <el-pagination
+              v-model:current-page="pages.page"
+              v-model:page-size="pages.pageSize"
+              :disabled="disabled"
+              :background="background"
+              layout="total, prev, pager, next"
+              :total="pages.count"
+              @current-change="handleCurrentChange"
+              v-if="collectList.length > 0 && !pages.loading"
+            />
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+  <!-- </page> -->
 </template>
+
+<script setup lang="ts">
+import { reactive, ref, onMounted, inject, watch } from "vue";
+import { ElMessage, ElMessageBox } from "element-plus";
+import { useBreadcrumbStore, useUserStore } from '@/store'
+import { useRouter } from "vue-router";
+const crumbStore = useBreadcrumbStore()
+const userStore = useUserStore()
+const router = useRouter();
+const MG: any = inject("MG");
+const config: any = inject("config");
+let currentCollect = ref("book");
+let collectList = ref([]);
+const background = ref(false);
+const disabled = ref(false);
+let pages = reactive({
+  page: 1,
+  pageSize: 10,
+  count: 0,
+  loading: false,
+});
+let linkType = ref("FavoriteTextBooks");
+
+const tabCart = (event: Event) => {
+  pages.page = 1;
+  pages.loading = true;
+  collectList.value = [];
+  currentCollect.value = event.props.name;
+  if (currentCollect.value == "textBooks") {
+    linkType.value = "FavoriteTextBooks";
+  }
+  getDataList();
+};
+
+function getDataList() {
+  pages.loading = true;
+  MG.store
+    .getProductList({
+      handelEBooK: true,
+      queryType: "AppUserProductLink",
+      linkType: linkType.value,
+      paging: {
+        start: pages.pageSize * pages.page - pages.pageSize,
+        size: pages.pageSize,
+      },
+    })
+    .then((res) => {
+      collectList.value = res.datas;
+      pages.count = res.total;
+      pages.loading = false;
+    })
+    .catch(() => {
+      pages.loading = false;
+    });
+}
+onMounted(() => {
+  getDataList();
+});
+
+// watch(
+//   () => userStore.token,
+//   () => {
+//     getDataList()
+//   }
+// )
+
+const handleCurrentChange = (val: number) => {
+  pages.page = val;
+  getDataList();
+};
+
+const setCoolect = (item) => {
+  ElMessageBox.confirm("纭畾瑕佸彇娑堟敹钘忓悧锛�", {
+    confirmButtonText: "纭畾",
+    cancelButtonText: "鍙栨秷",
+    autofocus: false,
+    type: "warning",
+  })
+    .then(() => {
+      MG.store
+        .delProductLink({
+          productIds: [item.id],
+          linkType: linkType.value,
+        })
+        .then(() => {
+          ElMessage({
+            message: "鏀惰棌宸插彇娑堬紒",
+            type: "success",
+          });
+          pages.page = 1;
+          getDataList();
+        });
+    })
+    .catch(() => {});
+};
+// 璺宠浆涔︽湰璇︽儏
+const goBookDetails = (id: number, name: string) => {
+  let crumbs = [
+    {
+      name,
+      isCrumbs: true,
+      type:
+        currentCollect.value == "book"
+          ? "bookService"
+          : currentCollect.value == "textBooks"
+          ? "digitalTextbooks"
+          : "digitalCourses",
+      path:
+        currentCollect.value == "book"
+          ? "/bookService/details"
+          : "/digitalCoursesDetails",
+    },
+  ];
+  // 鍦ㄥ叏灞�鏁版嵁涓缃潰鍖呭睉
+  crumbStore.setCrumbs({
+    type:
+      currentCollect.value == "book"
+        ? "bookService"
+        : currentCollect.value == "textBooks"
+        ? "digitalTextbooks"
+        : "digitalCourses",
+    data: crumbs,
+    callback: (key: any) => {
+      router.push({
+        name:
+          currentCollect.value == "book"
+            ? "bookDetails"
+            : currentCollect.value == "textBooks"
+            ? "digitalTextbooksDetails"
+            : "digitalCoursesDetails",
+        query: {
+          crumbsKey: key,
+          bookId: id,
+          bookName: name,
+          type:
+            currentCollect.value == "book"
+              ? "bookService"
+              : currentCollect.value == "textBooks"
+              ? "digitalTextbooks"
+              : "digitalCourses",
+        },
+      });
+    },
+  });
+};
+</script>
+<style lang="less" scoped>
+.cartClass {
+  ::v-deep .el-tabs__nav-wrap::after {
+    background-color: #019e58;
+    height: 1px;
+  }
+
+  ::v-deep .el-tabs__item {
+    width: 100px;
+    padding: 0;
+    color: #545c63;
+  }
+
+  ::v-deep .is-active {
+    background-color: #019e58;
+    color: #fff;
+    border-radius: 3px 3px 0 0;
+  }
+}
+
+.collectList {
+  // overflow: hidden;
+  justify-content: flex-start;
+  flex-wrap: wrap;
+}
+
+.bookCartContent {
+  .collectList-item {
+    width: 130px;
+    cursor: pointer;
+    box-sizing: border-box;
+    float: left;
+    position: relative;
+    margin-right: 38px;
+
+    .cover {
+      width: 100%;
+      height: 180px;
+      box-shadow: 0px 0px 20px 1px #ccc;
+
+      img {
+        width: 100%;
+        height: 100%;
+        object-fit: contain;
+      }
+    }
+
+    .info {
+      height: 90px;
+      padding: 15px 0;
+      width: 100%;
+
+      span {
+        font-weight: bold;
+        height: 45px;
+        line-height: 22px;
+        display: -webkit-box;
+        margin-bottom: 5px;
+        -webkit-box-orient: vertical;
+        -webkit-line-clamp: 2;
+        overflow: hidden;
+        text-overflow: ellipsis;
+      }
+    }
+  }
+
+  .collectList-item:nth-child(5),
+  :nth-child(10) {
+    margin-right: 0;
+  }
+}
+
+.courseCartContent {
+  .collectList-item {
+    width: 28%;
+    cursor: pointer;
+    box-sizing: border-box;
+    float: left;
+    margin-right: 5%;
+    box-shadow: 0px 0px 20px 1px #ccc;
+    position: relative;
+
+    .cover {
+      width: 100%;
+      height: 130px;
+
+      img {
+        width: 100%;
+        height: 100%;
+        object-fit: contain;
+      }
+    }
+
+    .info {
+      height: 70px;
+      padding: 15px;
+      width: 100%;
+
+      span {
+        font-weight: bold;
+        height: 45px;
+        line-height: 22px;
+        display: -webkit-box;
+        margin-bottom: 5px;
+        -webkit-box-orient: vertical;
+        -webkit-line-clamp: 2;
+        overflow: hidden;
+        text-overflow: ellipsis;
+      }
+    }
+  }
+}
+
+.currentBtn {
+  width: 20px;
+  height: 20px;
+  padding: 2px;
+  background-color: #fff;
+  position: absolute;
+  top: 10px;
+  right: 10px;
+
+  img {
+    width: 16px;
+    height: 16px;
+  }
+}
+
+.cartContent {
+  min-height: 495px;
+}
+
+.pagination-box {
+  display: flex;
+  justify-content: center;
+}
+</style>
diff --git a/src/views/personalCenter/myMessage.vue b/src/views/personalCenter/myMessage.vue
index ad630af..9d87747 100644
--- a/src/views/personalCenter/myMessage.vue
+++ b/src/views/personalCenter/myMessage.vue
@@ -1,3 +1,206 @@
 <template>
-  <div>鎴戠殑娑堟伅</div>
+  <!-- <page> -->
+  <div class="personalPage-box">
+    <div class="personalPage-title">鎴戠殑娑堟伅</div>
+    <div class="personalPage-content">
+      <div class="list-box" v-loading="pages.loading">
+        <ul class="listTable" v-if="dataList.length > 0 && !pages.loading">
+          <li v-for="(item, index) in dataList" :key="index" class="body flex">
+            <div class="icon">
+              <img src="@/assets/images/personalCenter/notification.svg" alt="star" />
+            </div>
+            <div class="flex1 ai-c">
+              <p class="title hover" :title="item.name" @click="viewDetail(item)">
+                {{ item.name }}
+              </p>
+              <p class="content" :title="item.description">{{ item.description }}</p>
+            </div>
+            <span class="createDate">{{ item.createDate }}</span>
+          </li>
+        </ul>
+        <div v-if="dataList.length == 0 && !pages.loading">
+          <el-empty :image-size="200" description="鏆傛棤鏁版嵁" />
+        </div>
+      </div>
+      <div class="pagination-box" v-if="dataList.length > 0 && !pages.loading">
+        <el-pagination
+          v-model:current-page="pages.page"
+          v-model:page-size="pages.pageSize"
+          layout="total, prev, pager, next"
+          :total="pages.count"
+          @current-change="handleCurrentChange"
+        />
+      </div>
+    </div>
+    <el-dialog align-center v-model="detailDialog" title="娑堟伅" class="messageDialog">
+      <div>
+        <div class="title">{{ dataInfo.name }}</div>
+        <div class="content" v-html="dataInfo.content"></div>
+      </div>
+    </el-dialog>
+  </div>
+  <!-- </page> -->
 </template>
+
+<script setup lang="ts">
+import { reactive, ref, onMounted, inject, watch } from "vue";
+import moment from "moment";
+import { useUserStore } from "@/store";
+const userStore = useUserStore();
+const MG: any = inject("MG");
+const config: any = inject("config");
+let dataList = ref([]);
+let pages = reactive({
+  page: 1,
+  pageSize: 10,
+  count: 0,
+  loading: false,
+});
+const detailDialog = ref(false);
+let dataInfo = reactive({
+  name: "",
+  content: "",
+});
+
+function getDataList() {
+  pages.loading = true;
+  MG.app
+    .getAppMessageList({
+      appRefCode: config.appRefCode,
+      start: (pages.page - 1) * pages.pageSize,
+      size: pages.pageSize,
+      sort: {
+        type: "Desc",
+        field: "CreateDate",
+      },
+    })
+    .then((res) => {
+      pages.count = res.totalSize;
+      res.datas.forEach((item) => {
+        item.createDate = moment(item.createDate).format("YYYY-MM-DD HH:mm:ss");
+      });
+      dataList.value = res.datas;
+      pages.loading = false;
+    })
+    .catch(() => {
+      pages.loading = false;
+    });
+}
+onMounted(() => {
+  getDataList();
+});
+
+watch(
+  () => userStore?.token,
+  () => {
+    getDataList();
+  }
+);
+
+const handleCurrentChange = (val: number) => {
+  pages.page = val;
+  getDataList();
+};
+
+function viewDetail(data) {
+  MG.app
+    .getMessage({
+      messageId: data.id,
+    })
+    .then((res) => {
+      if (res) {
+        dataInfo.name = res.name;
+        dataInfo.content = res.content;
+        detailDialog.value = true;
+      }
+    });
+}
+</script>
+<style lang="less" scoped>
+.listTable {
+  .body {
+    padding: 15px 0;
+    border-bottom: 1px solid #ededed;
+
+    .icon {
+      width: 36px;
+
+      img {
+        margin-top: 2px;
+        width: 22px;
+        height: 22px;
+      }
+    }
+
+    .title {
+      font-weight: bold;
+      line-height: 24px;
+      height: 24px;
+      display: -webkit-box;
+      -webkit-box-orient: vertical;
+      -webkit-line-clamp: 1;
+      overflow: hidden;
+      text-overflow: ellipsis;
+    }
+
+    .content {
+      height: 45px;
+      line-height: 24px;
+      display: -webkit-box;
+      margin: 5px 0;
+      -webkit-box-orient: vertical;
+      -webkit-line-clamp: 2;
+      overflow: hidden;
+      text-overflow: ellipsis;
+    }
+
+    .createDate {
+      line-height: 24px;
+      padding-left: 20px;
+      color: #949494;
+    }
+  }
+}
+
+.list-box {
+  min-height: 570px;
+}
+
+.pagination-box {
+  display: flex;
+  justify-content: center;
+}
+
+.messageDialog {
+  width: 600px;
+
+  .title {
+    line-height: 22px;
+    font-weight: bold;
+  }
+
+  .content {
+    margin-top: 10px;
+    line-height: 22px;
+  }
+}
+</style>
+<style lang="less">
+.messageDialog {
+  .el-dialog__header {
+    padding: 15px;
+    margin-right: 0;
+    border-bottom: 1px solid #f4f4f4;
+  }
+
+  .el-dialog__title {
+    font-weight: bold;
+    font-size: 16px;
+  }
+
+  .el-dialog__headerbtn {
+    top: 6px;
+    right: 6px;
+  }
+}
+</style>
diff --git a/src/views/personalCenter/myOrder.vue b/src/views/personalCenter/myOrder.vue
index 1002f5e..fa053cd 100644
--- a/src/views/personalCenter/myOrder.vue
+++ b/src/views/personalCenter/myOrder.vue
@@ -1,3 +1,495 @@
 <template>
-  <div>鎴戠殑璁㈠崟</div>
+  <!-- <page> -->
+  <div class="personalPage-box">
+    <div class="personalPage-title">鎴戠殑璁㈠崟</div>
+    <div class="personalPage-content">
+      <div class="cartClass">
+        <el-tabs v-model="order" type="capsule" @tab-click="tabCart">
+          <el-tab-pane label="鍏ㄩ儴" name="all"></el-tab-pane>
+          <el-tab-pane label="寰呮敮浠�" name="payment"></el-tab-pane>
+          <el-tab-pane label="宸插畬鎴�" name="complete"></el-tab-pane>
+          <el-tab-pane label="宸插彇娑�" name="cancellation"></el-tab-pane>
+        </el-tabs>
+      </div>
+      <div class="myCarTopPage">
+        <div class="cartContent" v-loading="pages.loading">
+          <div class="list-box">
+            <ul class="listTable" v-if="dataList.length > 0 && !pages.loading">
+              <li class="head flex">
+                <span class="index">搴忓彿</span>
+                <span class="clear flex1">鍟嗗搧淇℃伅</span>
+                <span class="state">鍟嗗搧绫诲瀷</span>
+                <span class="price">浠锋牸</span>
+              </li>
+              <li v-for="item in dataList" :key="item.index">
+                <div class="body flex ai-c">
+                  <div class="index">{{ item.index }}</div>
+                  <div class="list">
+                    <div
+                      v-for="pItem in item.productList"
+                      :key="pItem.id"
+                      class="listItem flex ai-c"
+                    >
+                      <div
+                        class="clear hover"
+                        @click="
+                          goBookDetails(
+                            pItem.orderSaleMethod.product.id,
+                            pItem.orderSaleMethod.product.name,
+                            pItem.orderSaleMethod.product.cmsTypeRefCode,
+                            item.remarks,
+                            pItem.orderSaleMethod.id
+                          )
+                        "
+                      >
+                        <div class="cover fl">
+                          <img
+                            :src="
+                              pItem.orderSaleMethod.product.icon
+                                ? getPublicImage(
+                                    pItem.orderSaleMethod.product.icon,
+                                    '',
+                                    ''
+                                  )
+                                : bookCover
+                            "
+                            alt=""
+                          />
+                        </div>
+                        <div class="title flex ai-c">
+                          {{
+                            pItem.orderSaleMethod.type === "defaultSaleMethod" ||
+                            pItem.orderSaleMethod.cmsItemList.length == 0
+                              ? pItem.orderSaleMethod.product.name
+                              : pItem.orderSaleMethod.product.name +
+                                "锛�" +
+                                pItem.orderSaleMethod.cmsItemList[0].name
+                          }}
+                        </div>
+                      </div>
+                      <span class="state">{{
+                        pItem.orderSaleMethod.product.cmsTypeRefCode ==
+                        "jsek_digitalTextbooks"
+                          ? "鏁板瓧鏁欐潗"
+                          : pItem.orderSaleMethod.product.cmsTypeRefCode ==
+                            "jsek_digitalCourses"
+                          ? "鏁板瓧璇剧▼"
+                          : pItem.orderSaleMethod.type == "defaultSaleMethod"
+                          ? "鍥句功鏈嶅姟-鐢靛瓙涔�"
+                          : pItem.orderSaleMethod.type == "createProductSaleMethod" &&
+                            pItem.orderSaleMethod.cmsItemList == 0
+                          ? "鍥句功鏈嶅姟-缁勫嵎"
+                          : pItem.orderSaleMethod.cmsItemList[0].type ==
+                            "questionBankFolder"
+                          ? "鍥句功鏈嶅姟-浜戞祴璇�"
+                          : "鍥句功鏈嶅姟-浜戝涔�"
+                      }}</span>
+                      <div class="price">
+                        <span>锟{ pItem.payPrice.toFixed(2) }}</span>
+                      </div>
+                    </div>
+                  </div>
+                </div>
+                <div class="count">
+                  <span>璁㈠崟鍙�: {{ item.orderNumber }}</span>
+                  <span v-if="item.createDate">
+                    鍒涘缓鏃堕棿锛�
+                    <span>{{ item.createDate.slice(0, 10) }}</span>
+                    <span style="margin-left: 5px">{{
+                      item.createDate.slice(11, 19)
+                    }}</span>
+                  </span>
+                  <span class="right">
+                    <span
+                      >鎬昏锛�<span class="main"
+                        >锟{ item.totalPrice.toFixed(2) }}</span
+                      ></span
+                    >
+                    <span class="status yes" v-if="item.state == 'Success'">宸插畬鎴�</span>
+                    <span class="status cancel" v-if="item.state == 'Cancel'"
+                      >宸插彇娑�</span
+                    >
+                    <span class="status cancel" v-if="item.state == 'ReFoundFinished'"
+                      >宸查��娆�</span
+                    >
+                    <span class="status" v-if="item.state == 'WaitPay'">
+                      <span class="main hover" @click="toPay(item.orderNumber)"
+                        >绔嬪嵆鏀粯</span
+                      >
+                      <span class="grey hover" @click="cancleOrder(item.orderNumber)"
+                        >鍙栨秷璁㈠崟</span
+                      >
+                    </span>
+                  </span>
+                </div>
+              </li>
+            </ul>
+            <div v-if="dataList.length == 0 && !pages.loading">
+              <el-empty :image-size="200" description="鏆傛棤鏁版嵁" />
+            </div>
+          </div>
+          <div class="pagination-box" v-if="dataList.length > 0 && !pages.loading">
+            <el-pagination
+              v-model:current-page="pages.page"
+              v-model:page-size="pages.pageSize"
+              layout="total, prev, pager, next"
+              :total="pages.count"
+              @current-change="handleCurrentChange"
+            />
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+  <!-- </page> -->
 </template>
+
+<script setup lang="ts">
+import { reactive, ref, onMounted, inject, watch } from "vue";
+import { ElMessage } from "element-plus";
+import { getPublicImage } from "@/assets/js/middleGround/tool.js";
+import { useRouter } from "vue-router";
+import { useBreadcrumbStore, useUserStore } from "@/store";
+import bookCover from "@/assets/images/personalCenter/book-cover.png";
+const router = useRouter();
+const crumbStore = useBreadcrumbStore();
+const userStore = useUserStore();
+const MG: any = inject("MG");
+let order = ref("all");
+let dataList = ref([]);
+let queryFilter = reactive([]);
+let pages = reactive({
+  page: 1,
+  pageSize: 5,
+  count: 0,
+  loading: false,
+});
+
+const tabCart = (event: Event) => {
+  order.value = event.props.name;
+  pages.page = 1;
+  dataList.value = [];
+  if (order.value == "all") {
+    queryFilter.value = [];
+  }
+  if (order.value == "payment") {
+    queryFilter.value = [{ field: "State", value: "WaitPay" }];
+  }
+  if (order.value == "complete") {
+    queryFilter.value = [{ field: "State", value: "Success" }];
+  }
+  if (order.value == "cancellation") {
+    queryFilter.value = [{ field: "State", value: "Cancel" }];
+  }
+  getDataList();
+};
+function getDataList() {
+  pages.loading = true;
+  const data = {
+    start: pages.pageSize * pages.page - pages.pageSize,
+    size: pages.pageSize,
+    filterList: queryFilter.value,
+    sort: {
+      type: "Desc",
+      field: "CreateDate",
+    },
+  };
+  MG.store
+    .getUserOrderList(data)
+    .then((res) => {
+      res.datas.forEach((item, index) => {
+        item.index =
+          pages.page == 1 ? index + 1 : pages.pageSize * (pages.page - 1) + (index + 1);
+        item.productList = item.saleMethodLinks;
+        item.time = item.createDate.slice(0, 10) + +item.createDate.slice(11, 20);
+      });
+      pages.count = res.totalSize;
+      dataList.value = [...res.datas];
+      console.log("璁㈠崟鍒楄〃", res.datas);
+      pages.loading = false;
+    })
+    .catch(() => {
+      pages.loading = false;
+    });
+}
+
+onMounted(() => {
+  getDataList();
+});
+
+// watch(
+//   () => userStore.token,
+//   () => {
+//     getDataList()
+//   }
+// )
+
+const handleCurrentChange = (val: number) => {
+  pages.page = val;
+  getDataList();
+};
+// 璺宠浆涔︽湰璇︽儏
+const goBookDetails = async (
+  id: number,
+  name: string,
+  refCode: string,
+  remarks: string,
+  orderSaleMethodId: string
+) => {
+  let parentData = null;
+  let bookId = id;
+  if (refCode == "digitalCourses") {
+    let crumbs = [
+      {
+        name,
+        isCrumbs: true,
+        type: "digitalCourses",
+        path: "digitalCoursesDetails",
+      },
+    ];
+    // 鍦ㄥ叏灞�鏁版嵁涓缃潰鍖呭睉
+    crumbStore.setCrumbs({
+      type: "digitalCourses",
+      data: crumbs,
+      callback: (key: any) => {
+        router.push({
+          name: "digitalCoursesDetails",
+          query: {
+            crumbsKey: key,
+            bookId: bookId,
+            bookName: name,
+            type: "digitalCourses",
+          },
+        });
+      },
+    });
+  } else if (refCode == "digitalTextbooks") {
+    let crumbs = [
+      {
+        name,
+        isCrumbs: true,
+        type: "digitalTextbooks",
+        path: "digitalTextbooksDetails",
+      },
+    ];
+    // 鍦ㄥ叏灞�鏁版嵁涓缃潰鍖呭睉
+    crumbStore.setCrumbs({
+      type: "digitalTextbooks",
+      data: crumbs,
+      callback: (key: any) => {
+        router.push({
+          name: "digitalTextbooksDetails",
+          query: {
+            crumbsKey: key,
+            bookId: bookId,
+            bookName: name,
+            type: "digitalTextbooks",
+          },
+        });
+      },
+    });
+  } else {
+    parentData = await MG.store.getProductBySaleMethod({
+      saleMethodId: orderSaleMethodId,
+    });
+    if (parentData.parentProduct.length > 0) {
+      bookId = parentData.parentProduct[parentData.parentProduct.length - 1].id;
+    }
+    console.log(bookId, "bookId");
+    let crumbs = [
+      {
+        name,
+        isCrumbs: true,
+        type: "bookService",
+        path: "/bookService/details",
+      },
+    ];
+    // 鍦ㄥ叏灞�鏁版嵁涓缃潰鍖呭睉
+    crumbStore.setCrumbs({
+      type: "bookService",
+      data: crumbs,
+      callback: (key: any) => {
+        router.push({
+          name: "bookDetails",
+          query: {
+            crumbsKey: key,
+            bookId: bookId,
+            bookName: name,
+            type: "bookService",
+          },
+        });
+      },
+    });
+  }
+};
+//绔嬪嵆鏀粯
+const toPay = (orderNo) => {
+  let crumbs: any[] = [
+    {
+      name: "鎴戠殑璁㈠崟", // 闈㈠寘灞戝悕绉�
+      pathName: "myOrder", // 闈㈠寘灞戣烦杞矾鐢憋紝鍙紶閫� pathName 鎴� path
+      isCrumbs: true, // 闈㈠寘灞戠偣鍑昏烦杞椂鏄惁鍒涘缓鏂扮殑闈㈠寘灞戣褰�
+      type: "personalCenter", // 濡傛灉闇�瑕佸垱寤烘柊鐨勯潰鍖呭睉璁板綍锛屽垱寤虹殑type
+      query: {
+        type: "personalCenter",
+      },
+    },
+  ];
+  crumbs.push({
+    name: "璁㈠崟璇︽儏",
+  });
+  // 鍦ㄥ叏灞�鏁版嵁涓缃潰鍖呭睉
+  crumbStore.setCrumbs({
+    type: "personalCenter",
+    data: crumbs,
+    callback: (key: any) => {
+      router.push({
+        path: "/paymentPage", //瑕佽烦杞殑椤甸潰
+        query: {
+          crumbsKey: key,
+          orderNum: orderNo,
+          type: "personalCenter",
+        },
+      });
+    },
+  });
+};
+
+//鍙栨秷璁㈠崟
+const cancleOrder = (orderNum) => {
+  MG.store.cancelOrder({ orderNum: orderNum }).then(() => {
+    ElMessage({
+      message: "璁㈠崟宸插彇娑�",
+      type: "success",
+    });
+    getDataList();
+  });
+};
+</script>
+<style lang="less" scoped>
+.cartClass {
+  ::v-deep .el-tabs__nav-wrap::after {
+    background-color: #019e58;
+    height: 1px;
+  }
+
+  ::v-deep .el-tabs__item {
+    width: 100px;
+    padding: 0;
+    color: #545c63;
+  }
+
+  ::v-deep .is-active {
+    background-color: #019e58;
+    color: #fff;
+    border-radius: 3px 3px 0 0;
+  }
+}
+
+.listTable {
+  .head {
+    font-weight: bold;
+    padding: 12px 10px;
+    background-color: #f3f3f3;
+
+    .flex1 {
+      padding: 0 50px;
+    }
+  }
+
+  .body {
+    padding: 15px 10px;
+  }
+
+  li {
+    line-height: 23px;
+    border-bottom: 1px solid #f4f4f4;
+
+    .index {
+      // padding: 0 20px;
+      text-align: center;
+      width: 80px;
+      flex-shrink: 0;
+    }
+
+    .list {
+      .listItem {
+        padding-bottom: 10px;
+
+        .clear {
+          width: 400px;
+          display: flex;
+          align-items: center;
+        }
+      }
+
+      :last-child {
+        padding-bottom: 0px;
+      }
+    }
+
+    .cover {
+      box-shadow: 0px 0px 20px 1px #ccc;
+      margin-right: 20px;
+      width: 130px;
+      height: 180px;
+
+      img {
+        width: 100%;
+        height: 100%;
+        object-fit: contain;
+      }
+    }
+
+    .title {
+      height: 180px;
+      line-height: 180px;
+    }
+
+    .state {
+      padding: 0 20px;
+      width: 230px;
+    }
+
+    .price {
+      text-align: right;
+      padding: 0 20px;
+      // width: 100px;
+      color: #019e58;
+    }
+
+    .count {
+      // text-align: right;
+      display: flex;
+      justify-content: space-between;
+      padding: 10px;
+      background: rgba(205, 207, 219, 0.14);
+
+      .right {
+        float: right;
+      }
+
+      .cancel {
+        color: #949494;
+      }
+
+      .status {
+        margin-left: 40px;
+
+        span {
+          padding: 0 10px;
+        }
+      }
+    }
+  }
+}
+
+.list-box {
+  min-height: 495px;
+}
+
+.pagination-box {
+  display: flex;
+  justify-content: center;
+}
+</style>
diff --git a/src/views/personalCenter/teacherCertification.vue b/src/views/personalCenter/teacherCertification.vue
new file mode 100644
index 0000000..65747f0
--- /dev/null
+++ b/src/views/personalCenter/teacherCertification.vue
@@ -0,0 +1,858 @@
+<template>
+  <div>
+    <el-dialog
+      align-center
+      destroy-on-close
+      :close-on-click-modal="false"
+      v-model="teacherDialog"
+      title="鏁欏笀璁よ瘉鐢宠"
+      class="myDialog"
+      @close="closeDialog(teacherFormRef)"
+    >
+      <div v-loading="loading" class="box">
+        <div class="body-box">
+          <div class="tipsBox">
+            <p class="main">娓╅Θ鎻愮ず</p>
+            <p>浠呴檺瀛︽牎鏈绋嬩换璇炬暀甯堢敵璇凤紱璇蜂笂浼犳湁鏁堝湪鑱屾暀甯堝伐浣滆瘉灏嗘湁鍔╀簬瀹℃牳銆�</p>
+          </div>
+          <el-form
+            ref="teacherFormRef"
+            :model="teacherInfo"
+            :rules="teacherRules"
+            label-width="140px"
+            class="teacherInfo"
+            status-icon
+          >
+            <el-form-item label="褰撳墠鐘舵�侊細">
+              <span class="wait" v-if="teacherInfo.state == 'WaitAudit'">绛夊緟瀹℃牳</span>
+              <span class="yes" v-else-if="teacherInfo.state == 'Normal'">宸茶璇�</span>
+              <span class="no" v-else-if="teacherInfo.state == 'Reject'"
+                ><span>宸查┏鍥�</span
+                ><span @click="lookReason()" class="wait hover" style="margin-left: 20px"
+                  >鏌ョ湅鍘熷洜</span
+                ></span
+              >
+              <span class="wait" v-else>寰呰璇�</span>
+            </el-form-item>
+            <el-form-item label="瀛︽牎锛�" prop="schoolName">
+              <span v-if="!editState">{{ teacherInfo.schoolName || "-" }}</span>
+              <el-input
+                v-else
+                v-model="teacherInfo.schoolName"
+                autocomplete="off"
+                placeholder="璇疯緭鍏ュ鏍�"
+              />
+            </el-form-item>
+            <el-form-item label="鐪熷疄濮撳悕锛�" prop="fullName">
+              <span v-if="!editState">{{ teacherInfo.fullName || "-" }}</span>
+              <el-input
+                v-else
+                v-model="teacherInfo.fullName"
+                autocomplete="off"
+                placeholder="璇疯緭鍏ョ湡瀹炲鍚�"
+              />
+            </el-form-item>
+            <el-form-item label="鑱岀О锛�">
+              <span v-if="!editState">{{ teacherInfo.positionalTitle || "-" }}</span>
+              <el-select
+                v-else
+                v-model="teacherInfo.positionalTitle"
+                placeholder="璇烽�夋嫨鑱岀О"
+              >
+                <el-option
+                  v-for="item in teachPosts"
+                  :key="item.value"
+                  :label="item.name"
+                  :value="item.name"
+                ></el-option>
+              </el-select>
+            </el-form-item>
+            <el-form-item label="浠绘暀璇剧▼锛�" prop="courseName">
+              <span v-if="!editState">{{ teacherInfo.courseName || "-" }}</span>
+              <el-input
+                v-else
+                v-model="teacherInfo.courseName"
+                autocomplete="off"
+                placeholder="璇疯緭鍏ヤ换鏁欒绋�"
+              />
+            </el-form-item>
+            <el-form-item label="鎵嬫満鍙凤細" prop="phone">
+              <span v-if="!editState">{{ teacherInfo.phone || "-" }}</span>
+              <el-input
+                v-else
+                v-model="teacherInfo.phone"
+                autocomplete="off"
+                placeholder="璇疯緭鍏ユ墜鏈哄彿"
+              />
+            </el-form-item>
+            <el-form-item label="搴ф満锛�" prop="telphone">
+              <span v-if="!editState">{{ teacherInfo.telphone || "-" }}</span>
+              <el-input
+                v-else
+                v-model="teacherInfo.telphone"
+                autocomplete="off"
+                placeholder="璇疯緭鍏ュ骇鏈�"
+              />
+            </el-form-item>
+            <el-form-item label="閭锛�" prop="email">
+              <span v-if="!editState">{{ teacherInfo.email || "-" }}</span>
+              <el-input
+                v-else
+                v-model="teacherInfo.email"
+                autocomplete="off"
+                placeholder="璇疯緭鍏ラ偖绠�"
+              />
+            </el-form-item>
+            <el-form-item label="璇︾粏鍦板潃锛�" prop="detailedAddress">
+              <span v-if="!editState">{{ teacherInfo.detailedAddress || "-" }}</span>
+              <el-input
+                v-else
+                v-model="teacherInfo.detailedAddress"
+                autocomplete="off"
+                placeholder="璇疯緭鍏ヨ缁嗗湴鍧�"
+              />
+            </el-form-item>
+            <el-form-item label="鍦ㄨ亴鏁欏笀宸ヤ綔璇侊細" prop="relevantCertificates">
+              <div class="uploadBox">
+                <div class="fileList">
+                  <div class="fileImgBox" v-for="(file, index) in fileList" :key="file">
+                    <el-image
+                      v-if="file.md5"
+                      style="width: 100%; height: 100%"
+                      :src="config?.requestCtx + `/file/GetPreViewImage?md5=` + file.md5"
+                      :zoom-rate="1.2"
+                      :max-scale="7"
+                      :min-scale="0.2"
+                      :hide-on-click-modal="true"
+                      :preview-src-list="showFileList"
+                      :initial-index="index"
+                      fit="contain"
+                    />
+                    <el-icon
+                      v-if="editState"
+                      @click="handleRemove(file)"
+                      color="#F56C6C"
+                      style="
+                        position: absolute;
+                        top: -10px;
+                        right: -10px;
+                        font-size: 20px;
+                        background: #fff;
+                        border-radius: 50%;
+                        cursor: pointer;
+                      "
+                      ><CircleCloseFilled
+                    /></el-icon>
+                  </div>
+                  <el-upload
+                    v-if="editState"
+                    class="upload"
+                    :http-request="fileUpload"
+                    :show-file-list="false"
+                    list-type="picture-card"
+                    :action="'#'"
+                  >
+                    <el-icon>
+                      <Plus />
+                    </el-icon>
+                  </el-upload>
+                </div>
+              </div>
+              <div class="grey" style="font-size: 12px">鏁欏姟澶勭洊绔犳枃浠躲�佹牎宸ュ崱鐨嗗彲</div>
+            </el-form-item>
+          </el-form>
+          <div class="agree-msg">
+            <!-- <input
+              :disabled="!editState ? true : false"
+              type="checkbox"
+              class="checkbox"
+              v-model="teacherInfo.agree"
+            /> -->
+            <el-checkbox
+              v-model="teacherInfo.agree"
+              :disabled="!editState ? true : false"
+            ></el-checkbox>
+            <span class="agree"
+              >鍚屾剰<span class="main hover" @click="dialogVisibleTecher = true"
+                >銆婃暀甯堣璇佹湇鍔℃潯娆俱��</span
+              ></span
+            >
+          </div>
+        </div>
+        <div class="footer-box">
+          <span class="myDialog-footer" v-if="!loading && editState">
+            <el-button @click="closeDialog(teacherFormRef)"> 鍙栨秷</el-button>
+            <el-button
+              type="primary"
+              @click="submitBtn(teacherFormRef)"
+              :loading="subLoading"
+            >
+              鎻愪氦</el-button
+            >
+          </span>
+        </div>
+      </div>
+    </el-dialog>
+    <!-- 鏁欏笀璁よ瘉鏈嶅姟鏉℃ -->
+    <el-dialog
+      title="銆婃暀甯堣璇佹湇鍔℃潯娆俱��"
+      v-model="dialogVisibleTecher"
+      :close-on-click-modal="false"
+      width="40%"
+    >
+      <div class="protocolBox" v-html="protocolTxt"></div>
+      <template #footer>
+        <span class="myDialog-footer" v-if="editState">
+          <el-button type="primary" class="btn" @click="dialogVisibleTecher = false"
+            >纭� 瀹�</el-button
+          >
+        </span>
+      </template>
+    </el-dialog>
+    <!-- 鏌ョ湅鍘熷洜 -->
+    <el-dialog
+      align-center
+      :close-on-click-modal="false"
+      v-model="dialogReason"
+      title="椹冲洖鍘熷洜"
+    >
+      <div class="reason" v-if="reasonTxt">
+        {{ reasonTxt }}
+      </div>
+      <div v-else>鏃�</div>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { reactive, ref, watch, defineEmits, inject, onMounted } from "vue";
+import type { FormInstance, FormRules } from "element-plus";
+import { ElMessage } from "element-plus";
+import tool from "@/assets/js/toolClass.js";
+import { getTopicMsgCmsItemFile } from "@/assets/js/middleGround/tool.js";
+import { useUserStore } from "@/store";
+const userStore = useUserStore();
+const MG: any = inject("MG");
+const config: any = inject("config");
+// 璇佷欢楠岃瘉
+const valiCertificate = (rule: any, value: any, callback: any) => {
+  if (fileList.value.length == 0) {
+    callback(new Error("璇蜂笂浼犵浉鍏宠瘉浠�"));
+  } else {
+    callback();
+  }
+};
+
+// const validateTelphone = (rule: any, value: any, callback: any) => {
+//   if (value !== "" && !config.reg_telphone.test(value)) {
+//     callback(new Error("璇疯緭鍏ユ纭牸寮忕殑搴ф満鍙�"));
+//   }
+//   callback();
+// };
+
+const validatePhone = (rule: any, value: any, callback: any) => {
+  if (value === "") {
+    callback(new Error("璇疯緭鍏ヨ仈绯荤數璇�"));
+  } else {
+    if (!config.reg_tel.test(value)) {
+      callback(new Error("璇疯緭鍏ユ纭牸寮忕殑鐢佃瘽"));
+    }
+    callback();
+  }
+};
+const validateEmail = (rule: any, value: any, callback: any) => {
+  let myreg = /^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.[a-zA-Z0-9]{2,6}$/;
+  if (value === "") {
+    callback(new Error("璇疯緭鍏ョ數瀛愰偖绠�"));
+  } else {
+    if (!myreg.test(value)) {
+      callback(new Error("璇疯緭鍏ユ纭牸寮忕殑鐢靛瓙閭"));
+    }
+    callback();
+  }
+};
+
+const props = defineProps({
+  isShow: Boolean,
+});
+
+let teacherDialog = ref(false); //寮圭獥
+let loading = ref(false);
+let subLoading = ref(false);
+const teachPosts = ref([]);
+const teacherInfo = reactive({
+  schoolName: "", //瀛︽牎鍚嶇О
+  fullName: "", //濮撳悕
+  positionalTitle: "", //鑱岀О
+  courseName: "", //浠昏鏁欑▼
+  phone: "", //鑱旂郴鐢佃瘽
+  telphone: "", //搴ф満
+  email: "", //鑱旂郴閭
+  detailedAddress: "", //閫氳鍦板潃
+  relevantCertificates: [], //鐩稿叧璇佷欢
+  state: "", //瀹℃牳鐘舵�侀粯璁ゅ緟瀹℃牳
+  agree: false,
+});
+const topicMessageList = ref([]);
+const topicId = ref();
+const worksInfo = ref([]);
+const userId = ref();
+const teacherFormRef = ref<FormInstance>();
+
+interface TeacherInfo {
+  schoolName: string;
+  fullName: string;
+  courseName: string;
+  telphone: string;
+  phone: string;
+  email: string;
+  detailedAddress: string;
+  relevantCertificates: string[];
+}
+const teacherRules = reactive<FormRules<TeacherInfo>>({
+  schoolName: [{ required: true, message: "瀛︽牎鍚嶇О涓嶈兘涓虹┖", trigger: "blur" }],
+  fullName: [{ required: true, message: "鐪熷疄濮撳悕涓嶈兘涓虹┖", trigger: "blur" }],
+  courseName: [{ required: true, message: "浠绘暀璇剧▼涓嶈兘涓虹┖", trigger: "blur" }],
+  // telphone: [{ validator: validateTelphone, trigger: "blur" }],
+  phone: [{ required: true, validator: validatePhone, trigger: "blur" }],
+  email: [{ required: true, validator: validateEmail, trigger: "blur" }],
+  detailedAddress: [{ required: true, message: "璇︾粏鍦板潃涓嶈兘涓虹┖", trigger: "blur" }],
+  relevantCertificates: [
+    { required: true, validator: valiCertificate, trigger: "change" },
+  ],
+});
+const fileList = ref([]);
+const editState = ref<boolean>(true);
+watch(props, (newValue) => {
+  // 缁熺洃鍚琾rops鐨勫�煎彉鍖栵紝鍔ㄦ�佷慨鏀筰sShow鐨勫��
+  teacherDialog.value = newValue.isShow;
+  if (teacherDialog.value) {
+    getpositionalTitle();
+    getAgreement();
+    if (localStorage.getItem(config.tokenKey)) {
+      getUserRole();
+    }
+  }
+});
+
+// 鑾峰彇鑱岀О
+function getpositionalTitle() {
+  const data = {
+    refCodes: ["positionalTitle"],
+  };
+  MG.store.getProductTypeField(data).then((res) => {
+    try {
+      const list = res[0];
+      const options = JSON.parse(list.config).option;
+      teachPosts.value = options;
+    } catch (error) {
+      teachPosts.value = [];
+    }
+  });
+}
+
+// 鑾峰彇鐧诲綍鐢ㄦ埛韬唤
+function getUserRole() {
+  loading.value = true;
+  MG.identity.getCurrentAppUser().then((res) => {
+    if (res) {
+      getType();
+      userId.value = res.userId;
+      let userInfo = res.infoList.find((item: any) => item.type == "userInfo");
+      let userTypeObj = res.infoList.find((item: any) => item.type == "userType");
+      const userData = {
+        userName: userInfo && userInfo.data ? JSON.parse(userInfo.data).name : "",
+        school: userInfo && userInfo.data ? JSON.parse(userInfo.data).school : "",
+        address: userInfo && userInfo.data ? JSON.parse(userInfo.data).address : "",
+        userType:
+          userTypeObj && userTypeObj.data ? JSON.parse(userTypeObj.data).userType : "",
+      };
+      let teacherRole = res.roleLinks.find((item) => item.role.refCode == "teacher");
+      let teacherInfos = res.infoList.find((item) => item.type == "teacherInfo");
+      let wechatInfo = res.infoList.find((item) => item.type == "WeChat");
+      let studentInfo = res.infoList.find((item) => item.type == "Default");
+      let phoneInfo = res.secretList.find((item) => item.type == "MobilePhone");
+      let emailInfo = res.secretList.find((item) => item.type == "EMail");
+      if (teacherRole && teacherInfos) {
+        userStore.setUserInfo({
+          ...userData,
+          ...teacherInfos,
+          phoneNumber: phoneInfo?.credential,
+          Email: emailInfo ? emailInfo.credential : JSON.parse(teacherInfos.data).email,
+          icon: wechatInfo?.icon,
+          role: "Teacher",
+          roleId: teacherRole.role.id,
+          userId: res.userId,
+        });
+      } else if (wechatInfo) {
+        userStore.setUserInfo({
+          ...userData,
+          ...wechatInfo,
+          phoneNumber: phoneInfo?.credential,
+          Email: emailInfo?.credential,
+          role: "Student",
+          userId: res.userId,
+        });
+      } else if (studentInfo) {
+        if (!studentInfo?.fullName) {
+          teacherInfo.fullName = userStore.userInfo!.userName;
+        }
+        userStore.setUserInfo({
+          ...userData,
+          ...studentInfo,
+          icon: wechatInfo?.icon,
+          phoneNumber: phoneInfo?.credential,
+          Email: emailInfo?.credential,
+          role: "Student",
+          userId: res.userId,
+        });
+      } else if (phoneInfo) {
+        userStore.setUserInfo({
+          ...userData,
+          ...phoneInfo,
+          name: phoneInfo?.credential,
+          icon: phoneInfo?.icon,
+          phoneNumber: phoneInfo?.credential,
+          role: "Student",
+          userId: res.userId,
+        });
+      }
+
+      teacherInfo.phone = userStore.userInfo!.phoneNumber;
+      teacherInfo.schoolName = userStore.userInfo!.school;
+      teacherInfo.detailedAddress = userStore.userInfo!.address;
+    }
+  });
+}
+
+function getType() {
+  const data = {
+    refCodes: ["teacherCertification"],
+  };
+  MG.resource.getCmsTypeByRefCode(data).then((res) => {
+    worksInfo.value = res[0].cmsTypeLinks[0].children;
+    newGetTeacherInfo();
+  });
+}
+
+// 鏂囦欢涓婁紶
+function fileUpload(file) {
+  console.log(file, 2);
+  return new Promise((resolve, reject) => {
+    const isJPG = file.file.type === "image/jpeg" || file.file.type === "image/png";
+    const isLt2M = (0.5 * file.file.size) / 1024 / 1024 < 0.5;
+    if (!isJPG) {
+      ElMessage.error("涓婁紶鏂囦欢鍙兘鏄� jpg/png 鏍煎紡!");
+      return reject();
+    }
+    if (!isLt2M) {
+      ElMessage.error("涓婁紶鏂囦欢澶у皬涓嶈兘瓒呰繃 500KB!");
+      return reject();
+    }
+    const FileName = file.file.name.split(".")[0];
+    const Extension = file.file.name.split(".")[1];
+    const FileType = file.file.type;
+    let size = 1024;
+    tool
+      .getFileMd5(file.file, size * 1024)
+      .then((e) => {
+        console.log(e, 2);
+        if (!fileList.value.find((item) => item.md5 == e)) {
+          const imgData = new FormData();
+          imgData.append("Md5", e);
+          imgData.append("FileName", FileName);
+          imgData.append("Extension", Extension);
+          imgData.append("FileType", FileType);
+          imgData.append("MetaData", null);
+          imgData.append("file", file.file);
+          MG.file.upload(imgData).then(() => {
+            fileList.value.push({
+              md5: e,
+              linkType: "LinkFile",
+              linkProtectType: "Public",
+              url: config.requestCtx + `/file/GetPreViewImage?md5=` + e,
+            });
+          });
+        } else {
+          ElMessage.error("褰撳墠鏂囦欢宸蹭笂浼狅紝璇峰嬁閲嶅鎿嶄綔锛�");
+        }
+      })
+      .catch((e) => {
+        console.error(e);
+      });
+  });
+}
+
+// 璇佷欢鍒犻櫎
+function handleRemove(file) {
+  for (let i = 0; i < fileList.value.length; i++) {
+    if (fileList.value[i].md5 == file.md5) {
+      fileList.value.splice(i, 1);
+    }
+  }
+}
+
+// 鐩戝惉鏂囦欢鍒楄〃鍙樺寲锛屽悓姝ヤ慨鏀瑰睍绀哄垪琛�
+const showFileList = ref([]);
+watch(
+  fileList,
+  (newValue) => {
+    showFileList.value = newValue.map(
+      (item) => config.requestCtx + `/file/GetPreViewImage?md5=` + item.md5
+    );
+  },
+  { immediate: true, deep: true }
+);
+
+// 鍏抽棴寮规锛屽洖璋冪埗灞傛柟娉�
+const emit = defineEmits(["dialogChange"]);
+const closeDialog = (formEl: FormInstance | undefined) => {
+  if (!formEl) return;
+  formEl.resetFields();
+  teacherDialog.value = false;
+  emit("dialogChange", teacherDialog.value);
+};
+
+// 鏁欏笀鍗忚
+const dialogVisibleTecher = ref(false);
+const protocolTxt = ref("");
+const getAgreement = () => {
+  let query = {
+    path: "protocol",
+    fields: {
+      content: [],
+    },
+  };
+  MG.resource.getItem(query).then((res) => {
+    try {
+      const data = res.datas.find(
+        (e) => e.refCode == "teacherCertificationAgreement"
+      );
+      protocolTxt.value = data ? data.content : "鏆傛棤鍗忚";
+    } catch (error) {
+      protocolTxt.value = "鏆傛棤鍗忚";
+    }
+  });
+};
+
+//鏁欏笀淇℃伅
+function newGetTeacherInfo() {
+  const data = {
+    start: 0,
+    size: 10,
+    topicIdOrRefCode: "teacherRoleApproval",
+    appRefCode: config.appRefCode,
+    sort: {
+      type: "Desc",
+      field: "CreateDate",
+    },
+  };
+  MG.ugc.getTopicMessageList(data).then((res) => {
+    try {
+      fileList.value = [];
+      const resData = res.datas.find((i) => i.appUserCreator.userId === userId.value);
+      if (resData) {
+        if (resData.state == "WaitAudit") {
+          editState.value = false;
+        } else {
+          editState.value = true;
+        }
+        let info = getTopicMsgCmsItemFile(worksInfo.value, resData.cmsItemDataList);
+        teacherInfo.fullName = info.fullName;
+        teacherInfo.schoolName = info.schoolName;
+        teacherInfo.positionalTitle = info.positionalTitle;
+        teacherInfo.courseName = info.courseName;
+        teacherInfo.phone = info.phone;
+        teacherInfo.telphone = info.telphone ? info.telphone : "";
+        teacherInfo.email = info.email;
+        teacherInfo.detailedAddress = info.detailedAddress ? info.detailedAddress : "";
+        teacherInfo.relevantCertificates = info.relevantCertificates;
+        teacherInfo.agree = true;
+        teacherInfo.state = resData.state;
+        topicId.value = resData.id;
+        topicMessageList.value = resData.cmsItemDataList;
+        if (resData.feedBack != null) {
+          reasonTxt.value = JSON.parse(resData.feedBack).reason;
+        }
+        if (teacherInfo.relevantCertificates.length > 0) {
+          if (typeof teacherInfo.relevantCertificates == "object") {
+            teacherInfo.relevantCertificates.forEach((ele) => {
+              let imgObj = {
+                md5: ele.file.md5,
+                linkType: "LinkFile",
+                linkProtectType: "Public",
+                url: config.requestCtx + `/file/GetPreViewImage?md5=` + ele.file.md5,
+              };
+              fileList.value.push(imgObj);
+            });
+          } else {
+            let imgObj = {
+              md5: teacherInfo.relevantCertificates,
+              linkType: "LinkFile",
+              linkProtectType: "Public",
+              url:
+                config.requestCtx +
+                `/file/GetPreViewImage?md5=` +
+                teacherInfo.relevantCertificates,
+            };
+            fileList.value.push(imgObj);
+          }
+        }
+        loading.value = false;
+      } else {
+        loading.value = false;
+      }
+    } catch (error) {
+      loading.value = false;
+    }
+  });
+}
+
+//鏁欏笀璁よ瘉鎻愪氦
+const submitBtn = async (formEl: FormInstance | undefined) => {
+  if (!formEl) return;
+  await formEl.validate((valid, fields) => {
+    if (valid) {
+      if (teacherInfo.agree) {
+        subLoading.value = true;
+        if (topicMessageList.value.length > 0) {
+          let dataRequests = tool.UpdateworksDataBytool(
+            worksInfo.value,
+            topicMessageList.value,
+            teacherInfo,
+            fileList.value
+          );
+          const data = {
+            description: "",
+            icon: "",
+            id: topicId.value,
+            topicIdOrRefCode: "teacherRoleApproval",
+            name: teacherInfo.fullName + "",
+            content: "",
+            state: "WaitAudit",
+            type: "teacherRegister",
+            newDataRequests: dataRequests.newData,
+            updateDataRequests: dataRequests.updateData,
+            delDataRequest: {
+              ids: [],
+            },
+          };
+          let basicInfo = JSON.parse(JSON.stringify(teacherInfo));
+          delete basicInfo.worksInfo;
+          delete basicInfo.state;
+          const userInfo = {
+            requests: [
+              {
+                data: JSON.stringify(basicInfo),
+                name: teacherInfo.fullName + "",
+                type: "newTeacherInfo",
+              },
+            ],
+          };
+          MG.identity.setAppUserInfo(userInfo).then((res) => {
+            if (res) {
+              MG.ugc.updateTopicMessage(data).then(() => {
+                if (res !== false) {
+                  ElMessage({
+                    message: "鎻愪氦鎴愬姛锛佽绛夊緟瀹℃牳...",
+                    type: "success",
+                  });
+                  teacherDialog.value = false;
+                  subLoading.value = false;
+                  newGetTeacherInfo();
+                } else {
+                  subLoading.value = false;
+                }
+              });
+            } else {
+              subLoading.value = true;
+            }
+          });
+        } else {
+          const data = {
+            topicIdOrRefCode: "teacherRoleApproval",
+            name: teacherInfo.fullName + "",
+            content: "",
+            state: "WaitAudit",
+            type: "teacherRegister",
+            cmsTypeRefCode: "teacherCertification",
+            newDataListRequest: tool.worksDataBytool(
+              worksInfo.value,
+              teacherInfo,
+              fileList.value
+            ),
+          };
+
+          let basicInfo = JSON.parse(JSON.stringify(teacherInfo));
+          delete basicInfo.worksInfo;
+          delete basicInfo.state;
+          const userInfo = {
+            requests: [
+              {
+                data: JSON.stringify(basicInfo),
+                name: teacherInfo.fullName + "",
+                type: "teacherInfo",
+              },
+            ],
+          };
+          MG.identity.setAppUserInfo(userInfo).then((res) => {
+            MG.ugc.newTopicMessage(data).then(() => {
+              if (res !== false) {
+                ElMessage({
+                  message: "鎻愪氦鎴愬姛锛佽绛夊緟瀹℃牳...",
+                  type: "success",
+                });
+                teacherDialog.value = false;
+                newGetTeacherInfo();
+                subLoading.value = false;
+              } else {
+                subLoading.value = false;
+              }
+            });
+          });
+        }
+      } else {
+        ElMessage({
+          message: "璇峰悓鎰忋�婃暀甯堣璇佹湇鍔℃潯娆俱�嬶紒",
+          type: "warning",
+        });
+      }
+    }
+  });
+};
+
+//鍘熷洜鏌ョ湅
+const dialogReason = ref(false);
+const reasonTxt = ref("");
+const lookReason = () => {
+  dialogReason.value = true;
+};
+defineExpose({ getUserRole });
+</script>
+<style lang="less">
+.myDialog {
+  width: 628px;
+  .el-dialog__body {
+    padding: 0;
+  }
+  .body-box {
+    padding: 10px 20px 40px;
+    height: 80vh;
+    overflow-y: auto;
+  }
+
+  .el-dialog__header {
+    padding: 15px;
+    margin-right: 0;
+    border-bottom: 1px solid #f4f4f4;
+  }
+  .el-dialog__title {
+    font-weight: bold;
+    font-size: 16px;
+  }
+
+  .el-dialog__headerbtn {
+    top: 6px;
+    right: 6px;
+  }
+
+  .footer-box {
+    padding: 15px;
+    border-top: 1px solid #f4f4f4;
+    text-align: right;
+    height: 63px;
+  }
+
+  .myDialog-footer {
+    .el-button {
+      padding: 0 20px;
+    }
+  }
+}
+</style>
+<style lang="less" scoped>
+.tipsBox {
+  line-height: 24px;
+  padding: 5px;
+  border: 1px solid #019e58;
+  background: rgba(116, 252, 188, 0.1);
+  color: #019e58;
+  text-align: center;
+  width: 86%;
+  margin: 0 auto 20px auto;
+
+  .main {
+    font-weight: bold;
+    text-align: center;
+  }
+}
+
+.teacherInfo {
+  .el-select {
+    width: 90%;
+    height: 38px;
+
+    /deep/.el-input__wrapper {
+      height: 38px;
+    }
+  }
+
+  .el-input {
+    width: 90%;
+    height: 38px;
+  }
+}
+
+.uploadBox {
+  padding: 10px 0 0 10px;
+  border: 1px solid #e9e9eb;
+  border-radius: 3px;
+  width: 330px;
+}
+
+.fileList .upload {
+  display: inline-block;
+  vertical-align: middle;
+  margin-right: 10px;
+  margin-bottom: 10px;
+}
+
+.fileImgBox {
+  display: inline-block;
+  position: relative;
+  width: 146px;
+  height: 146px;
+  border-radius: 6px;
+  background: #ddd;
+  margin-right: 10px;
+  margin-bottom: 10px;
+  vertical-align: middle;
+  border: 1px solid #c0ccda;
+}
+
+.fileList .fileImgBox:hover {
+  border-color: #019E58;
+}
+
+.agree-msg {
+  margin-left: 140px;
+  display: flex;
+  justify-content: flex-start;
+  align-items: center;
+
+  .agree {
+    margin-left: 5px;
+  }
+
+  .term {
+    color: #019E58;
+  }
+}
+.reason {
+  word-wrap: break-word;
+}
+.protocolBox {
+  height: 500px;
+  overflow-y: auto;
+}
+</style>
diff --git a/src/views/personalCenter/userInfo.vue b/src/views/personalCenter/userInfo.vue
index c4d4e9b..8378d15 100644
--- a/src/views/personalCenter/userInfo.vue
+++ b/src/views/personalCenter/userInfo.vue
@@ -8,7 +8,9 @@
           <div class="info-box flex">
             <span class="label">鐢ㄦ埛鍚嶏細</span>
             <span class="text">{{ userStore?.userInfo.name }}</span>
-            <span class="change-info hover" @click="changeUserInfo('password')">淇敼瀵嗙爜</span>
+            <span class="change-info hover" @click="changeUserInfo('password')"
+              >淇敼瀵嗙爜</span
+            >
           </div>
           <div class="info-box flex">
             <span class="label">寰俊璁よ瘉:</span>
@@ -25,16 +27,16 @@
             }}</span>
             <span class="text no" v-else>鏈粦瀹�</span>
             <span class="change-info hover" @click="changeUserInfo('phone')">{{
-              userStore?.userInfo?.phoneNumber ? '鏇存崲鎵嬫満鍙�' : '缁戝畾'
+              userStore?.userInfo?.phoneNumber ? "鏇存崲鎵嬫満鍙�" : "缁戝畾"
             }}</span>
           </div>
           <div class="info-box flex">
             <span class="label">閭锛�</span>
             <span class="text">{{
-              userStore?.userInfo?.Email ? userStore.userInfo?.Email : '--'
+              userStore?.userInfo?.Email ? userStore.userInfo?.Email : "--"
             }}</span>
             <span class="change-info hover" @click="changeUserInfo('email')">{{
-              userStore?.userInfo?.Email ? '鏇存崲閭' : '缁戝畾閭'
+              userStore?.userInfo?.Email ? "鏇存崲閭" : "缁戝畾閭"
             }}</span>
           </div>
         </div>
@@ -56,7 +58,10 @@
         <div class="item-title flex jc-sb">
           <span>鏁欏笀璁よ瘉</span>
           <div>
-            <span class="change-info hover" v-if="teacherState == ''" @click="showTeacherDialog()"
+            <span
+              class="change-info hover"
+              v-if="teacherState == ''"
+              @click="showTeacherDialog()"
               >璁よ瘉</span
             >
             <span
@@ -104,7 +109,11 @@
       destroy-on-close
       v-model="userInfoDialog"
       :title="
-        changeType == 'email' ? '鏇存崲閭' : changeType == 'password' ? '淇敼瀵嗙爜' : '鏇存崲鎵嬫満鍙�'
+        changeType == 'email'
+          ? '鏇存崲閭'
+          : changeType == 'password'
+          ? '淇敼瀵嗙爜'
+          : '鏇存崲鎵嬫満鍙�'
       "
       width="500"
       class="myDialogs"
@@ -154,10 +163,10 @@
               >
                 {{
                   countDown > 0
-                    ? '楠岃瘉鐮�(' + countDown + 's)'
-                    : changeType == 'email'
-                      ? '鑾峰彇閭楠岃瘉鐮�'
-                      : '鑾峰彇鐭俊楠岃瘉鐮�'
+                    ? "楠岃瘉鐮�(" + countDown + "s)"
+                    : changeType == "email"
+                    ? "鑾峰彇閭楠岃瘉鐮�"
+                    : "鑾峰彇鐭俊楠岃瘉鐮�"
                 }}
               </el-button>
             </div>
@@ -170,7 +179,11 @@
               placeholder="璇疯緭鍏�8-16浣嶆柊瀵嗙爜,涓斾笉鑳戒负绾暟瀛�"
             />
           </el-form-item>
-          <el-form-item label="纭瀵嗙爜锛�" prop="confirmPassword" v-if="changeType == 'password'">
+          <el-form-item
+            label="纭瀵嗙爜锛�"
+            prop="confirmPassword"
+            v-if="changeType == 'password'"
+          >
             <el-input
               type="password"
               v-model="userInfoForm.confirmPassword"
@@ -183,7 +196,11 @@
       <template #footer>
         <span class="myDialogs-footer">
           <el-button @click="closeUserInfoDialog(userFormRef)">鍙栨秷</el-button>
-          <el-button type="primary" @click="confirmInfo(userFormRef)" :loading="subLoading">
+          <el-button
+            type="primary"
+            @click="confirmInfo(userFormRef)"
+            :loading="subLoading"
+          >
             纭畾
           </el-button>
         </span>
@@ -244,9 +261,9 @@
           <li v-for="item in integralRecord.recordList" :key="item.key" class="body">
             <span class="label">{{ item.type }}</span>
             <span class="value" :class="item.value > 0 ? 'yes' : 'no'">{{
-              item.value > 0 ? '+' + item.value : item.value
+              item.value > 0 ? "+" + item.value : item.value
             }}</span>
-            <span>{{ item.createDate ? item.createDate : '-' }}</span>
+            <span>{{ item.createDate ? item.createDate : "-" }}</span>
           </li>
           <li class="total" v-if="integralRecord.recordList.length > 0">
             <span class="label">鎬昏</span>
@@ -271,260 +288,261 @@
 </template>
 
 <script setup lang="ts">
-import { reactive, ref, inject, onMounted, watch } from 'vue'
-import type { FormInstance, FormRules } from 'element-plus'
+import { reactive, ref, inject, onMounted, watch } from "vue";
+import type { FormInstance, FormRules } from "element-plus";
 // import verify from '@/components/sliderImg/component/verify.vue'
 // import '@/components/sliderImg/sliderImg.js'
 // import '@/components/sliderImg/sliderImg.css'
-import { ElMessage } from 'element-plus'
-import tool from '@/assets/js/toolClass.js'
-// import { useUserStore } from '@/store'
+import { ElMessage } from "element-plus";
+import tool from "@/assets/js/toolClass.js";
+import { useUserStore } from "@/store";
 // import wxlogin from 'vue-wxlogin'
-// import teacherCertification from '@/views/components/teacherCertification.vue'
+import teacherCertification from "./teacherCertification.vue";
 // import login from '@/layout/components/login.vue'
-// const userStore = useUserStore()
-import { useRoute } from 'vue-router'
-import moment from 'moment'
-const route = useRoute()
-const MG: any = inject('MG')
-const config: any = inject('config')
+const userStore = useUserStore();
+import { useRoute } from "vue-router";
+import moment from "moment";
+const route = useRoute();
+const MG: any = inject("MG");
+const config: any = inject("config");
 
 const validatePhone = (rule: any, value: any, callback: any) => {
-  if (value === '') {
-    callback(new Error('璇疯緭鍏ヨ仈绯荤數璇�'))
+  if (value === "") {
+    callback(new Error("璇疯緭鍏ヨ仈绯荤數璇�"));
   } else {
     if (!config.reg_tel.test(value)) {
-      callback(new Error('璇疯緭鍏ユ纭牸寮忕殑鐢佃瘽'))
+      callback(new Error("璇疯緭鍏ユ纭牸寮忕殑鐢佃瘽"));
     }
-    callback()
+    callback();
   }
-}
+};
 const validateEmail = (rule: any, value: any, callback: any) => {
-  let myreg = /^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.[a-zA-Z0-9]{2,6}$/
-  if (value === '') {
-    callback(new Error('璇疯緭鍏ョ數瀛愰偖绠�'))
+  let myreg = /^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.[a-zA-Z0-9]{2,6}$/;
+  if (value === "") {
+    callback(new Error("璇疯緭鍏ョ數瀛愰偖绠�"));
   } else {
     if (!myreg.test(value)) {
-      callback(new Error('璇疯緭鍏ユ纭牸寮忕殑鐢靛瓙閭'))
+      callback(new Error("璇疯緭鍏ユ纭牸寮忕殑鐢靛瓙閭"));
     }
-    callback()
+    callback();
   }
-}
+};
 
 const validatePassword = (rule: any, value: any, callback: any) => {
-  let myreg = /^(?!^\d+$)(?!^[a-zA-Z]+$)(?!^\W+$)[a-zA-Z\d\W]{8,16}$/
-  if (value === '') {
-    callback(new Error('璇疯緭鍏ュ瘑鐮�'))
+  let myreg = /^(?!^\d+$)(?!^[a-zA-Z]+$)(?!^\W+$)[a-zA-Z\d\W]{8,16}$/;
+  if (value === "") {
+    callback(new Error("璇疯緭鍏ュ瘑鐮�"));
   } else {
     if (!myreg.test(value)) {
-      callback(new Error('璇疯緭鍏ユ纭牸寮忕殑瀵嗙爜锛�8-16浣�,涓斾笉鑳戒负绾暟瀛�'))
+      callback(new Error("璇疯緭鍏ユ纭牸寮忕殑瀵嗙爜锛�8-16浣�,涓斾笉鑳戒负绾暟瀛�"));
     }
-    callback()
+    callback();
   }
-}
+};
 
-// onMounted(() => {
-//   getWechatAuthenticationState()
-//   getIntegral()
-//   if (localStorage.getItem(config.tokenKey)) {
-//     getUserRole()
-//   }
-// })
+onMounted(() => {
+  getWechatAuthenticationState();
+  getIntegral();
+  if (localStorage.getItem(config.tokenKey)) {
+    getUserRole();
+  }
+});
 
 // watch(route, () => {
 //   bindWeChat()
 // })
-let subLoading = ref(false)
+let subLoading = ref(false);
 //鐢ㄦ埛淇℃伅
-let weChatState = ref(false)
+let weChatState = ref(false);
 const userInfo = reactive({
-  userType: '',
+  userType: "",
   integral: 0,
-})
+});
 //鍩虹淇℃伅
-const userInfoDialog = ref(false)
-let changeType = ref('password')
-const imgCode = ref<string>() // 鍥惧舰楠岃瘉鐮乽rl
-let countDown = ref(0)
-// function changeUserInfo(type) {
-//   changeType.value = type
-//   if (type == 'password') {
-//     if (userStore.userInfo?.phoneNumber) {
-//       getImgCapcha()
-//       userInfoDialog.value = true
-//     } else {
-//       ElMessage({
-//         message: '淇敼瀵嗙爜闇�鐭俊楠岃瘉,璇风粦瀹氭墜鏈哄彿鍚庡啀淇敼瀵嗙爜锛�',
-//         type: 'warning'
-//       })
-//     }
-//   } else {
-//     getImgCapcha()
-//     userInfoDialog.value = true
-//   }
-// }
-// const getImgCapcha = () => {
-//   MG.identity.getImgCode().then((res) => {
-//     imgCode.value = 'data:image/png;base64,' + res
-//   })
-// }
+const userInfoDialog = ref(false);
+let changeType = ref("password");
+const imgCode = ref<string>(); // 鍥惧舰楠岃瘉鐮乽rl
+let countDown = ref(0);
 
-const userFormRef = ref<FormInstance>()
+const changeUserInfo = (type) => {
+  changeType.value = type;
+  if (type == "password") {
+    if (userStore.userInfo?.phoneNumber) {
+      getImgCapcha();
+      userInfoDialog.value = true;
+    } else {
+      ElMessage({
+        message: "淇敼瀵嗙爜闇�鐭俊楠岃瘉,璇风粦瀹氭墜鏈哄彿鍚庡啀淇敼瀵嗙爜锛�",
+        type: "warning",
+      });
+    }
+  } else {
+    getImgCapcha();
+    userInfoDialog.value = true;
+  }
+};
+const getImgCapcha = () => {
+  MG.identity.getImgCode().then((res) => {
+    imgCode.value = "data:image/png;base64," + res;
+  });
+};
+
+const userFormRef = ref<FormInstance>();
 const userInfoForm = reactive({
-  phone: '',
-  email: '',
-  captcha: '',
-  code: '',
-  password: '',
-  confirmPassword: '',
-})
-const formDisabled = ref(false)
+  phone: "",
+  email: "",
+  captcha: "",
+  code: "",
+  password: "",
+  confirmPassword: "",
+});
+const formDisabled = ref(false);
 const userFormRules = reactive<FormRules<userInfoForm>>({
-  phone: [{ required: true, validator: validatePhone, trigger: 'blur' }],
-  email: [{ required: true, validator: validateEmail, trigger: 'blur' }],
+  phone: [{ required: true, validator: validatePhone, trigger: "blur" }],
+  email: [{ required: true, validator: validateEmail, trigger: "blur" }],
   captcha: [
-    { required: true, message: '鍥惧舰楠岃瘉鐮佷笉鑳戒负绌�', trigger: 'blur' },
-    { min: 4, max: 4, message: '璇疯緭鍏� 4 浣嶉獙璇佺爜', trigger: 'blur' },
+    { required: true, message: "鍥惧舰楠岃瘉鐮佷笉鑳戒负绌�", trigger: "blur" },
+    { min: 4, max: 4, message: "璇疯緭鍏� 4 浣嶉獙璇佺爜", trigger: "blur" },
   ],
-  code: [{ required: true, message: '楠岃瘉鐮佷笉鑳戒负绌�', trigger: 'blur' }],
-  password: [{ required: true, validator: validatePassword, trigger: 'blur' }],
-  confirmPassword: [{ required: true, message: '纭瀵嗙爜涓嶈兘涓虹┖', trigger: 'blur' }],
-})
+  code: [{ required: true, message: "楠岃瘉鐮佷笉鑳戒负绌�", trigger: "blur" }],
+  password: [{ required: true, validator: validatePassword, trigger: "blur" }],
+  confirmPassword: [{ required: true, message: "纭瀵嗙爜涓嶈兘涓虹┖", trigger: "blur" }],
+});
 
 const getVerifyCode = async () => {
-  sliderImgDialogVisable.value = true
-}
+  sliderImgDialogVisable.value = true;
+};
 
 // 楠岃瘉鐮佸�掕鏃�
 function getSecond(time: number) {
-  let timer: ReturnType<typeof setInterval> | null = null
+  let timer: ReturnType<typeof setInterval> | null = null;
   if (!timer) {
-    countDown.value = time
+    countDown.value = time;
     timer = setInterval(() => {
-      countDown.value--
+      countDown.value--;
       if (countDown.value == 0) {
-        if (timer) clearInterval(timer)
-        timer = null
+        if (timer) clearInterval(timer);
+        timer = null;
       }
-    }, 1000)
+    }, 1000);
   }
 }
 
 const closeUserInfoDialog = (formEl: FormInstance | undefined) => {
-  if (!formEl) return
-  formEl.resetFields()
-  countDown.value = 0
-  userInfoDialog.value = false
-}
+  if (!formEl) return;
+  formEl.resetFields();
+  countDown.value = 0;
+  userInfoDialog.value = false;
+};
 const confirmInfo = async (formEl: FormInstance | undefined) => {
-  if (!formEl) return
+  if (!formEl) return;
   await formEl.validate((valid, fields) => {
     if (valid) {
-      subLoading.value = true
-      if (changeType.value == 'password') {
+      subLoading.value = true;
+      if (changeType.value == "password") {
         if (userInfoForm.password != userInfoForm.confirmPassword) {
           ElMessage({
-            message: '涓ゆ瀵嗙爜杈撳叆涓嶄竴鑷�',
-            type: 'warning',
-          })
-          return false
+            message: "涓ゆ瀵嗙爜杈撳叆涓嶄竴鑷�",
+            type: "warning",
+          });
+          return false;
         }
         let query = {
           phoneNumber: userInfoForm.phone,
           phoneCaptcha: userInfoForm.code,
           password: userInfoForm.password,
-        }
+        };
         MG.identity.changePasswordByMobilePhone(query).then((res) => {
           if (res) {
             ElMessage({
-              message: '瀵嗙爜閲嶇疆鎴愬姛锛�',
-              type: 'success',
-            })
-            userInfoDialog.value = false
+              message: "瀵嗙爜閲嶇疆鎴愬姛锛�",
+              type: "success",
+            });
+            userInfoDialog.value = false;
           } else {
             ElMessage({
-              message: '瀵嗙爜閲嶇疆澶辫触锛岃濉啓姝g‘鐨勯獙璇佺爜銆�',
-              type: 'error',
-            })
+              message: "瀵嗙爜閲嶇疆澶辫触锛岃濉啓姝g‘鐨勯獙璇佺爜銆�",
+              type: "error",
+            });
           }
-          subLoading.value = false
-        })
-      } else if (changeType.value == 'phone') {
+          subLoading.value = false;
+        });
+      } else if (changeType.value == "phone") {
         let query = {
           phoneNumber: userInfoForm.phone,
           phoneCaptcha: userInfoForm.code,
-        }
+        };
         MG.identity.userSetPhoneNumber(query).then((res) => {
-          if (res == '楠岃瘉鐮佽繃鏈熸垨閿欒') {
+          if (res == "楠岃瘉鐮佽繃鏈熸垨閿欒") {
             ElMessage({
-              message: res + ',璇风◢鍚庨噸璇�',
-              type: 'error',
-            })
-          } else if (res == '姝ゆ墜鏈哄彿鐮佸凡琚叾瀹冭处鍙风粦瀹�') {
+              message: res + ",璇风◢鍚庨噸璇�",
+              type: "error",
+            });
+          } else if (res == "姝ゆ墜鏈哄彿鐮佸凡琚叾瀹冭处鍙风粦瀹�") {
             ElMessage({
-              message: res + ',璇锋洿鎹㈠叾浠栨墜鏈哄彿銆�',
-              type: 'error',
-            })
+              message: res + ",璇锋洿鎹㈠叾浠栨墜鏈哄彿銆�",
+              type: "error",
+            });
           } else {
             ElMessage({
               message: res,
-              type: 'success',
-            })
+              type: "success",
+            });
             userStore.setUserInfo({
               ...userStore.userInfo,
               phoneNumber: userInfoForm.phone,
-            })
-            userInfoDialog.value = false
+            });
+            userInfoDialog.value = false;
           }
-          subLoading.value = false
-        })
-      } else if (changeType.value == 'email') {
+          subLoading.value = false;
+        });
+      } else if (changeType.value == "email") {
         let query = {
           eMail: userInfoForm.email,
           captcha: userInfoForm.code,
-        }
+        };
 
         MG.identity.bindingEmail(query).then((res) => {
-          if (res == '楠岃瘉鐮佽繃鏈�') {
+          if (res == "楠岃瘉鐮佽繃鏈�") {
             ElMessage({
-              message: res + ',璇风◢鍚庨噸璇�',
-              type: 'error',
-            })
-          } else if (res == '姝ら偖绠卞凡琚叾瀹冭处鍙风粦瀹�') {
+              message: res + ",璇风◢鍚庨噸璇�",
+              type: "error",
+            });
+          } else if (res == "姝ら偖绠卞凡琚叾瀹冭处鍙风粦瀹�") {
             ElMessage({
-              message: res + ',璇锋洿鎹㈠叾浠栭偖绠便��',
-              type: 'error',
-            })
-          } else if (res == '楠岃瘉鐮佹棤鏁�') {
+              message: res + ",璇锋洿鎹㈠叾浠栭偖绠便��",
+              type: "error",
+            });
+          } else if (res == "楠岃瘉鐮佹棤鏁�") {
             ElMessage({
               message: res,
-              type: 'error',
-            })
+              type: "error",
+            });
           } else {
             ElMessage({
               message: res,
-              type: 'success',
-            })
+              type: "success",
+            });
             userStore.setUserInfo({
               ...userStore.userInfo,
               Email: userInfoForm.email,
-            })
-            userInfoDialog.value = false
+            });
+            userInfoDialog.value = false;
           }
-          subLoading.value = false
-        })
+          subLoading.value = false;
+        });
       }
     } else {
-      subLoading.value = false
+      subLoading.value = false;
     }
-  })
-}
+  });
+};
 // 婊戝姩楠岃瘉
-const sliderImgDialogVisable = ref<boolean>(false)
+const sliderImgDialogVisable = ref<boolean>(false);
 const loginImgVerify = (code: string) => {
-  userInfoForm.captcha = code
-  sliderImgDialogVisable.value = false
-  if (changeType.value == 'phone' || changeType.value == 'password') {
+  userInfoForm.captcha = code;
+  sliderImgDialogVisable.value = false;
+  if (changeType.value == "phone" || changeType.value == "password") {
     MG.identity
       .getPhoneCode({
         phoneNumber: userInfoForm.phone,
@@ -532,21 +550,21 @@
         appRefCode: config.appRefCode,
       })
       .then((res: any) => {
-        if (res == '楠岃瘉鐮佸彂閫佹垚鍔�') {
+        if (res == "楠岃瘉鐮佸彂閫佹垚鍔�") {
           ElMessage({
             message: res,
-            type: 'success',
-          })
+            type: "success",
+          });
           // 寮�鍚煭淇¢獙璇佸�掕鏃�
-          getSecond(60)
+          getSecond(60);
         } else {
           ElMessage({
             message: res,
-            type: 'error',
-          })
+            type: "error",
+          });
         }
-      })
-  } else if (changeType.value == 'email') {
+      });
+  } else if (changeType.value == "email") {
     MG.identity
       .getEmailCode({
         sendEmail: userInfoForm.email,
@@ -556,50 +574,50 @@
       .then((res) => {
         if (res == true) {
           ElMessage({
-            message: '閭欢宸插彂閫�',
-            type: 'success',
-          })
+            message: "閭欢宸插彂閫�",
+            type: "success",
+          });
         } else {
           ElMessage({
-            message: '閭欢鍙戦�佸け璐�',
-            type: 'error',
-          })
+            message: "閭欢鍙戦�佸け璐�",
+            type: "error",
+          });
         }
-      })
+      });
   }
-}
+};
 //寰俊璁よ瘉
 let wxLogin = reactive({
-  appid: 'wx5cfe8b007a3c6f8c',
-  scope: 'snsapi_login',
-  redirectURL: encodeURIComponent(config.requestCtx + '/home/#/personalCenter'),
-})
+  appid: "wx5cfe8b007a3c6f8c",
+  scope: "snsapi_login",
+  redirectURL: encodeURIComponent(config.requestCtx + "/home/#/personalCenter"),
+});
 const getWechatAuthenticationState = () => {
   MG.identity.checkBuildingWeChat({}).then((res: any) => {
     if (res) {
-      weChatState.value = true
+      weChatState.value = true;
     } else {
-      weChatState.value = false
+      weChatState.value = false;
     }
-  })
-}
-const weChartDialog = ref(false)
+  });
+};
+const weChartDialog = ref(false);
 function goBindWeChat() {
-  window.location.href = `https://open.weixin.qq.com/connect/qrconnect?appid=${wxLogin.appid}&scope=${wxLogin.scope}&redirect_uri=${wxLogin.redirectURL}&state=WeChatScanningCodeBind`
+  window.location.href = `https://open.weixin.qq.com/connect/qrconnect?appid=${wxLogin.appid}&scope=${wxLogin.scope}&redirect_uri=${wxLogin.redirectURL}&state=WeChatScanningCodeBind`;
 }
 
 //缁戝畾寰俊
 const bindWeChat = () => {
-  var url = window.location.href
-  if (url.indexOf('WeChatScanningCodeBind') > -1) {
-    var querys = url.substring(url.indexOf('?') + 1).split('&')
-    var result = {}
+  var url = window.location.href;
+  if (url.indexOf("WeChatScanningCodeBind") > -1) {
+    var querys = url.substring(url.indexOf("?") + 1).split("&");
+    var result = {};
     for (var i = 0; i < querys.length; i++) {
-      var temp = querys[i].split('=')
+      var temp = querys[i].split("=");
       if (temp.length < 2) {
-        result[temp[0]] = ''
+        result[temp[0]] = "";
       } else {
-        result[temp[0]] = temp[1]
+        result[temp[0]] = temp[1];
       }
     }
     if (result && result.code) {
@@ -610,153 +628,162 @@
         .then((res) => {
           if (res) {
             ElMessage({
-              message: '缁戝畾鎴愬姛!',
-              type: 'success',
-            })
-            getWechatAuthenticationState()
-            weChartDialog.value = false
+              message: "缁戝畾鎴愬姛!",
+              type: "success",
+            });
+            getWechatAuthenticationState();
+            weChartDialog.value = false;
           } else {
             ElMessage({
-              message: '缁戝畾澶辫触锛岃寰俊宸茶缁戝畾锛�',
-              type: 'error',
-            })
+              message: "缁戝畾澶辫触锛岃寰俊宸茶缁戝畾锛�",
+              type: "error",
+            });
           }
-        })
+        });
     }
   }
-}
+};
 
 //鐢ㄦ埛绫诲瀷
-const loginRef = ref()
+const loginRef = ref();
 // const userTypeDialog = ref(false)
-const userTypeActive = ref('')
-const teacherType = ref('')
+const userTypeActive = ref("");
+const teacherType = ref("");
 const teacherList = ref([
   {
-    value: 'vocSchoolTeachers',
-    label: '涓亴鏁欏笀',
+    value: "vocSchoolTeachers",
+    label: "涓亴鏁欏笀",
   },
   {
-    value: 'vocCollegeTeachers',
-    label: '楂樿亴鏁欏笀',
+    value: "vocCollegeTeachers",
+    label: "楂樿亴鏁欏笀",
   },
   {
-    value: 'ordUniversityTeachers',
-    label: '鏈鏁欏笀',
+    value: "ordUniversityTeachers",
+    label: "鏈鏁欏笀",
   },
   {
-    value: 'primarySchoolTeachers',
-    label: '涓皬瀛︽暀甯�',
+    value: "primarySchoolTeachers",
+    label: "涓皬瀛︽暀甯�",
   },
   {
-    value: 'kindergarteTeachers',
-    label: '骞煎効鍥暀甯�',
+    value: "kindergarteTeachers",
+    label: "骞煎効鍥暀甯�",
   },
-])
+]);
 const userTypeList = ref([
   {
-    value: 'Teacher',
-    label: '鏁欏笀',
+    value: "Teacher",
+    label: "鏁欏笀",
     checked: false,
   },
   {
-    value: 'Student',
-    label: '瀛︾敓',
+    value: "Student",
+    label: "瀛︾敓",
     checked: false,
   },
   {
-    value: 'otherReaders',
-    label: '鍏朵粬璇昏��',
+    value: "otherReaders",
+    label: "鍏朵粬璇昏��",
     checked: false,
   },
-])
+]);
 
 // 淇敼鐢ㄦ埛绫诲瀷璋冪敤娉ㄥ唽鏃剁敤鎴蜂俊鎭~鍐欏脊绐�
 const updateUserInfo = () => {
-  loginRef.value.updateUserInfo()
-  loginRef.value.signUp()
-}
+  loginRef.value.updateUserInfo();
+  loginRef.value.signUp();
+};
 
 //鏁欏笀璁よ瘉
-let teacherDialog = ref(false) //寮圭獥
-let loading = ref(false)
-const teacherState = ref(null)
-const reasonTxt = ref('')
-const userId = ref()
+let teacherDialog = ref(false); //寮圭獥
+let loading = ref(false);
+const teacherState = ref(null);
+const reasonTxt = ref("");
+const userId = ref();
 
-const dialogReason = ref(false)
+const dialogReason = ref(false);
 //鏁欏笀璁よ瘉寮圭獥
 function showTeacherDialog() {
-  teacherDialog.value = true
+  teacherDialog.value = true;
 }
 
 const dialogChange = (val: any) => {
-  getTeacherInfo()
+  getTeacherInfo();
   if (val == false) {
-    teacherDialog.value = false
+    teacherDialog.value = false;
   } else {
-    teacherDialog.value = true
+    teacherDialog.value = true;
   }
-}
+};
 
 // 淇敼瀵嗙爜寮圭獥鎵撳紑
 const openChangePassword = () => {
-  if (changeType.value == 'password' && userStore.userInfo?.phoneNumber) {
-    userInfoForm.phone = userStore.userInfo?.phoneNumber
+  if (changeType.value == "password" && userStore.userInfo?.phoneNumber) {
+    userInfoForm.phone = userStore.userInfo?.phoneNumber;
   }
-}
+};
 
 // 鑾峰彇鐧诲綍鐢ㄦ埛韬唤
 function getUserRole() {
-  loading.value = true
+  loading.value = true;
   MG.identity.getCurrentAppUser().then((res: any) => {
     if (res) {
       if (res.lastLoginTime) {
-        localStorage.setItem('lastLoginTime', res.lastLoginTime)
+        localStorage.setItem("lastLoginTime", res.lastLoginTime);
       }
       //鑾峰彇鐢ㄦ埛绫诲瀷
-      let userTypeData = res.infoList.find((item: any) => item.type == 'userType')
+      let userTypeData = res.infoList.find((item: any) => item.type == "userType");
       if (userTypeData) {
-        userTypeActive.value = JSON.parse(userTypeData.data).userType
-        if (userTypeActive.value !== 'Student' && userTypeActive.value !== 'otherReaders') {
-          const index = userTypeList.value.findIndex((item) => item.value === 'Teacher')
+        userTypeActive.value = JSON.parse(userTypeData.data).userType;
+        if (
+          userTypeActive.value !== "Student" &&
+          userTypeActive.value !== "otherReaders"
+        ) {
+          const index = userTypeList.value.findIndex((item) => item.value === "Teacher");
           if (index !== -1) {
-            userTypeList.value[index].checked = true
-            teacherType.value = JSON.parse(userTypeData.data).userType
+            userTypeList.value[index].checked = true;
+            teacherType.value = JSON.parse(userTypeData.data).userType;
           }
           userInfo.userType =
-            teacherList.value.find((item) => item.value === userTypeActive.value)?.label ?? ''
+            teacherList.value.find((item) => item.value === userTypeActive.value)
+              ?.label ?? "";
         } else {
-          const index = userTypeList.value.findIndex((item) => item.value === userTypeActive.value)
+          const index = userTypeList.value.findIndex(
+            (item) => item.value === userTypeActive.value
+          );
           if (index !== -1) {
-            userTypeList.value[index].checked = true
+            userTypeList.value[index].checked = true;
           }
           userInfo.userType =
-            userTypeList.value.find((item) => item.value === userTypeActive.value)?.label ?? ''
+            userTypeList.value.find((item) => item.value === userTypeActive.value)
+              ?.label ?? "";
         }
       } else {
-        userInfo.userType = '-'
+        userInfo.userType = "-";
       }
-      getTeacherInfo()
-      userId.value = res.userId
-      let customUser = res.infoList.find((item: any) => item.type == 'userInfo')
-      let teacherRole = res.roleLinks.find((item: any) => item.role.refCode == 'teacher')
-      let teacherInfos = res.infoList.find((item: any) => item.type == 'teacherInfo')
-      let wechatInfo = res.infoList.find((item: any) => item.type == 'WeChat')
-      let studentInfo = res.infoList.find((item: any) => item.type == 'Default')
-      let phoneInfo = res.secretList.find((item: any) => item.type == 'MobilePhone')
-      let emailInfo = res.secretList.find((item: any) => item.type == 'EMail')
+      getTeacherInfo();
+      userId.value = res.userId;
+      let customUser = res.infoList.find((item: any) => item.type == "userInfo");
+      let teacherRole = res.roleLinks.find((item: any) => item.role.refCode == "teacher");
+      let teacherInfos = res.infoList.find((item: any) => item.type == "teacherInfo");
+      let wechatInfo = res.infoList.find((item: any) => item.type == "WeChat");
+      let studentInfo = res.infoList.find((item: any) => item.type == "Default");
+      let phoneInfo = res.secretList.find((item: any) => item.type == "MobilePhone");
+      let emailInfo = res.secretList.find((item: any) => item.type == "EMail");
       const userData = {
-        userName: customUser && customUser.data ? JSON.parse(customUser.data).name : '',
-        school: customUser && customUser.data ? JSON.parse(customUser.data).school : '',
-        cityCode: customUser && customUser.data ? JSON.parse(customUser.data).cityCode : '',
-        address: customUser && customUser.data ? JSON.parse(customUser.data).address : '',
-        userType: userTypeData && userTypeData.data ? JSON.parse(userTypeData.data).userType : '',
-      }
+        userName: customUser && customUser.data ? JSON.parse(customUser.data).name : "",
+        school: customUser && customUser.data ? JSON.parse(customUser.data).school : "",
+        cityCode:
+          customUser && customUser.data ? JSON.parse(customUser.data).cityCode : "",
+        address: customUser && customUser.data ? JSON.parse(customUser.data).address : "",
+        userType:
+          userTypeData && userTypeData.data ? JSON.parse(userTypeData.data).userType : "",
+      };
       if (teacherRole && teacherInfos) {
         if (JSON.parse(teacherInfos.data).email && !emailInfo) {
-          userInfoForm.email = JSON.parse(teacherInfos.data).email
-          formDisabled.value = true
+          userInfoForm.email = JSON.parse(teacherInfos.data).email;
+          formDisabled.value = true;
         }
         userStore.setUserInfo({
           ...userData,
@@ -764,19 +791,19 @@
           phoneNumber: phoneInfo?.credential,
           Email: emailInfo ? emailInfo.credential : JSON.parse(teacherInfos.data).email,
           icon: wechatInfo?.icon,
-          role: 'Teacher',
+          role: "Teacher",
           roleId: teacherRole.role.id,
           userId: res.userId,
-        })
+        });
       } else if (wechatInfo) {
         userStore.setUserInfo({
           ...userData,
           ...wechatInfo,
           phoneNumber: phoneInfo?.credential,
           Email: emailInfo?.credential,
-          role: 'Student',
+          role: "Student",
           userId: res.userId,
-        })
+        });
       } else if (studentInfo) {
         userStore.setUserInfo({
           ...userData,
@@ -784,12 +811,12 @@
           icon: wechatInfo?.icon,
           phoneNumber: phoneInfo?.credential,
           Email: emailInfo?.credential,
-          role: 'Student',
+          role: "Student",
           userId: res.userId,
-        })
+        });
       }
     }
-  })
+  });
 }
 
 //鏁欏笀淇℃伅
@@ -797,56 +824,56 @@
   const data = {
     start: 0,
     size: 10,
-    topicIdOrRefCode: 'teacherRoleApproval',
+    topicIdOrRefCode: "teacherRoleApproval",
     appRefCode: config.appRefCode,
     sort: {
-      type: 'Desc',
-      field: 'CreateDate',
+      type: "Desc",
+      field: "CreateDate",
     },
-  }
+  };
   MG.ugc.getTopicMessageList(data).then((res) => {
     try {
-      const resData = res.datas.find((i) => i.appUserCreator.userId == userId.value)
+      const resData = res.datas.find((i) => i.appUserCreator.userId == userId.value);
       if (resData) {
-        teacherState.value = resData.state
+        teacherState.value = resData.state;
         if (resData.feedBack != null) {
-          reasonTxt.value = JSON.parse(resData.feedBack).reason
+          reasonTxt.value = JSON.parse(resData.feedBack).reason;
         }
       } else {
-        teacherState.value = ''
+        teacherState.value = "";
       }
-      loading.value = false
+      loading.value = false;
     } catch (error) {
-      loading.value = false
+      loading.value = false;
     }
-  })
+  });
 }
 
 //鍘熷洜鏌ョ湅
 const lookReason = () => {
-  dialogReason.value = true
-}
+  dialogReason.value = true;
+};
 
 //绉垎
 function getIntegral() {
   MG.store
     .getUserWallet({
-      type: 'integral',
+      type: "integral",
     })
     .then((res) => {
-      userInfo.integral = res.balance
-    })
+      userInfo.integral = res.balance;
+    });
 }
 
 const integralRecord = reactive({
   recordDialog: false,
   recordList: [],
-})
+});
 
 // 绉垎璁板綍寮圭獥
 function recordDialog() {
-  integralRecord.recordDialog = true
-  getRecordList()
+  integralRecord.recordDialog = true;
+  getRecordList();
 }
 
 //鑾峰彇绉垎璁板綍
@@ -856,38 +883,38 @@
       Size: 999,
       Start: 0,
       sort: {
-        type: 'Desc',
-        field: 'CreateDate',
+        type: "Desc",
+        field: "CreateDate",
       },
-      type: 'integral',
+      type: "integral",
     })
     .then((res) => {
-      console.log(res, '绉垎璁板綍')
+      console.log(res, "绉垎璁板綍");
       if (res.datas.length > 0) {
         res.datas.forEach((element) => {
-          element.createDate = moment(element.createDate).format('YYYY-MM-DD HH:mm:ss')
-          if (element.refType == 'sign') {
-            element.type = '姣忔棩鐧诲綍'
+          element.createDate = moment(element.createDate).format("YYYY-MM-DD HH:mm:ss");
+          if (element.refType == "sign") {
+            element.type = "姣忔棩鐧诲綍";
           }
-          if (element.refType == 'Reward') {
-            element.type = '涓婁紶璧勬簮濂栧姳'
+          if (element.refType == "Reward") {
+            element.type = "涓婁紶璧勬簮濂栧姳";
           }
-          if (element.refType == 'OrderCoinBonus') {
-            element.type = '璁㈠崟鏀粯濂栧姳'
+          if (element.refType == "OrderCoinBonus") {
+            element.type = "璁㈠崟鏀粯濂栧姳";
           }
-          if (element.refType == 'Order' && element.value < 0) {
-            element.type = '璁㈠崟鏀粯鎶垫墸'
+          if (element.refType == "Order" && element.value < 0) {
+            element.type = "璁㈠崟鏀粯鎶垫墸";
           }
-          if (element.refType == 'Order' && element.value > 0) {
-            element.type = '璁㈠崟鍙栨秷閫�鍥�'
+          if (element.refType == "Order" && element.value > 0) {
+            element.type = "璁㈠崟鍙栨秷閫�鍥�";
           }
-          if (element.refType == 'AdminRecharge') {
-            element.type = '绠$悊鍛樺厖鍊�'
+          if (element.refType == "AdminRecharge") {
+            element.type = "绠$悊鍛樺厖鍊�";
           }
-        })
-        integralRecord.recordList = res.datas
+        });
+        integralRecord.recordList = res.datas;
       }
-    })
+    });
 }
 </script>
 <style lang="less" scoped>
@@ -896,9 +923,7 @@
     line-height: 20px;
     padding: 0 10px;
     border-left: 3px solid #019e58;
-    font-family:
-      Microsoft YaHei UI,
-      Microsoft YaHei UI;
+    font-family: Microsoft YaHei UI, Microsoft YaHei UI;
     font-weight: 400;
     font-size: 16px;
   }
@@ -908,9 +933,7 @@
 
     .info-box {
       padding: 10px 0;
-      font-family:
-        Microsoft YaHei UI,
-        Microsoft YaHei UI;
+      font-family: Microsoft YaHei UI, Microsoft YaHei UI;
       font-weight: 400;
       font-size: 14px;
       color: #333333;

--
Gitblit v1.9.1