Переглянути джерело

Merge branch 'beta' into HK

lsc 1 рік тому
батько
коміт
3ffb1c5256
56 змінених файлів з 4958 додано та 679 видалено
  1. 4 0
      dist/index.html
  2. 1 0
      dist/static/css/app.43b117d7b99f4248b205ff56a2c23ee6.css
  3. 1 0
      dist/static/css/app.e899675c15336f0ce8e5499e31258581.css
  4. 0 0
      dist/static/css/app.e899675c15336f0ce8e5499e31258581.css.map
  5. BIN
      dist/static/img/404.11fde6e.png
  6. 30 0
      dist/static/img/aiWait2.c8d31c6.svg
  7. BIN
      dist/static/img/aibgImage.347e461.png
  8. 6 0
      dist/static/img/robot3.c50070a.svg
  9. 1 0
      dist/static/js/app.3e0b600c9a54f04936c0.js
  10. 1 0
      dist/static/js/app.3e0b600c9a54f04936c0.js.map
  11. 1 0
      dist/static/js/app.c9798b1e302d55bc4148.js
  12. 0 0
      dist/static/js/app.c9798b1e302d55bc4148.js.map
  13. 0 0
      dist/static/js/manifest.3ad1d5771e9b13dbdad2.js.map
  14. 0 0
      dist/static/js/vendor.7707b4b07bf11db2f61a.js
  15. 0 0
      dist/static/js/vendor.7707b4b07bf11db2f61a.js.map
  16. BIN
      src/assets/icon/course/404.png
  17. 5 0
      src/assets/icon/course/Countdown.svg
  18. 5 0
      src/assets/icon/course/Countdown2.svg
  19. BIN
      src/assets/icon/course/aiLogo.png
  20. 30 0
      src/assets/icon/course/aiWait2.svg
  21. BIN
      src/assets/icon/course/aibgImage.png
  22. 4 0
      src/assets/icon/course/brush.svg
  23. 3 0
      src/assets/icon/course/cancel_left.svg
  24. 3 0
      src/assets/icon/course/cancel_right.svg
  25. 9 0
      src/assets/icon/course/changeType.svg
  26. 1 0
      src/assets/icon/course/clearScreen.svg
  27. 5 0
      src/assets/icon/course/closeIcon.svg
  28. 6 0
      src/assets/icon/course/comment2.svg
  29. 1 0
      src/assets/icon/course/edit.svg
  30. 4 0
      src/assets/icon/course/edit2.svg
  31. 9 0
      src/assets/icon/course/edit3.svg
  32. 3 0
      src/assets/icon/course/eraser.svg
  33. 1 0
      src/assets/icon/course/left.svg
  34. 5 0
      src/assets/icon/course/music.svg
  35. 0 0
      src/assets/icon/course/phone.svg
  36. BIN
      src/assets/icon/course/practice.png
  37. 4 0
      src/assets/icon/course/record3.svg
  38. 4 0
      src/assets/icon/course/record4.svg
  39. 5 0
      src/assets/icon/course/reset.svg
  40. 4 0
      src/assets/icon/course/right.svg
  41. 6 0
      src/assets/icon/course/robot3.svg
  42. BIN
      src/assets/icon/course/stop1.png
  43. BIN
      src/assets/icon/course/stop2.png
  44. 1 0
      src/assets/icon/course/yes.svg
  45. BIN
      src/assets/icon/newIcons/rootImg.png
  46. 147 0
      src/components/classRoomHelper/component/AnnotationCanvas.vue
  47. 1527 0
      src/components/classRoomHelper/component/countdown.vue
  48. 693 0
      src/components/classRoomHelper/component/languageAssistant.vue
  49. 2 31
      src/components/classRoomHelper/component/levitatedSphere.vue
  50. 654 95
      src/components/classRoomHelper/component/searchArea.vue
  51. 608 435
      src/components/classRoomHelper/component/taskArea.vue
  52. 241 103
      src/components/classRoomHelper/index.vue
  53. 549 0
      src/components/easy2/commpont/markScore.vue
  54. 234 8
      src/components/easy2/studyStudent.vue
  55. 16 3
      src/components/easy3/studyStudent.vue
  56. 124 4
      src/components/studyStudent.vue

+ 4 - 0
dist/index.html

@@ -27,7 +27,11 @@
     html,
     body{
       font-family: '黑体';
+<<<<<<< HEAD
     }</style><link href=./static/css/app.43b117d7b99f4248b205ff56a2c23ee6.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=./static/js/manifest.3ad1d5771e9b13dbdad2.js></script><script type=text/javascript src=./static/js/vendor.0eb3ff1f4c979300a113.js></script><script type=text/javascript src=./static/js/app.c9798b1e302d55bc4148.js></script></body></html><script>function stopSafari() {
+=======
+    }</style><link href=./static/css/app.e899675c15336f0ce8e5499e31258581.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=./static/js/manifest.3ad1d5771e9b13dbdad2.js></script><script type=text/javascript src=./static/js/vendor.7707b4b07bf11db2f61a.js></script><script type=text/javascript src=./static/js/app.3e0b600c9a54f04936c0.js></script></body></html><script>function stopSafari() {
+>>>>>>> beta
     //阻止safari浏览器双击放大功能
     let lastTouchEnd = 0  //更新手指弹起的时间
     document.documentElement.addEventListener("touchstart", function (event) {

Різницю між файлами не показано, бо вона завелика
+ 1 - 0
dist/static/css/app.43b117d7b99f4248b205ff56a2c23ee6.css


Різницю між файлами не показано, бо вона завелика
+ 1 - 0
dist/static/css/app.e899675c15336f0ce8e5499e31258581.css


Різницю між файлами не показано, бо вона завелика
+ 0 - 0
dist/static/css/app.e899675c15336f0ce8e5499e31258581.css.map


BIN
dist/static/img/404.11fde6e.png


Різницю між файлами не показано, бо вона завелика
+ 30 - 0
dist/static/img/aiWait2.c8d31c6.svg


BIN
dist/static/img/aibgImage.347e461.png


Різницю між файлами не показано, бо вона завелика
+ 6 - 0
dist/static/img/robot3.c50070a.svg


Різницю між файлами не показано, бо вона завелика
+ 1 - 0
dist/static/js/app.3e0b600c9a54f04936c0.js


Різницю між файлами не показано, бо вона завелика
+ 1 - 0
dist/static/js/app.3e0b600c9a54f04936c0.js.map


Різницю між файлами не показано, бо вона завелика
+ 1 - 0
dist/static/js/app.c9798b1e302d55bc4148.js


Різницю між файлами не показано, бо вона завелика
+ 0 - 0
dist/static/js/app.c9798b1e302d55bc4148.js.map


Різницю між файлами не показано, бо вона завелика
+ 0 - 0
dist/static/js/manifest.3ad1d5771e9b13dbdad2.js.map


Різницю між файлами не показано, бо вона завелика
+ 0 - 0
dist/static/js/vendor.7707b4b07bf11db2f61a.js


Різницю між файлами не показано, бо вона завелика
+ 0 - 0
dist/static/js/vendor.7707b4b07bf11db2f61a.js.map


BIN
src/assets/icon/course/404.png


+ 5 - 0
src/assets/icon/course/Countdown.svg

@@ -0,0 +1,5 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M4.5 13.5C4.5 9.35786 7.85786 6 12 6C14.0783 6 15.958 6.84437 17.3172 8.21062C18.6671 9.56754 19.5 11.4358 19.5 13.5C19.5 17.6421 16.1421 21 12 21C7.85786 21 4.5 17.6421 4.5 13.5ZM12 4.5C7.02944 4.5 3 8.52944 3 13.5C3 18.4706 7.02944 22.5 12 22.5C16.9706 22.5 21 18.4706 21 13.5C21 11.4741 20.33 9.60378 19.2004 8.0998C19.2283 8.07884 19.255 8.05568 19.2803 8.03033L20.7803 6.53033C21.0732 6.23744 21.0732 5.76256 20.7803 5.46967C20.4874 5.17678 20.0126 5.17678 19.7197 5.46967L18.2197 6.96967C18.2154 6.97399 18.2111 6.97835 18.2069 6.98275C16.5928 5.44513 14.4061 4.5 12 4.5Z" fill="black" fill-opacity="0.9"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M9 2.25C9 1.83579 9.33579 1.5 9.75 1.5H14.25C14.6642 1.5 15 1.83579 15 2.25C15 2.66421 14.6642 3 14.25 3H9.75C9.33579 3 9 2.66421 9 2.25Z" fill="black" fill-opacity="0.9"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M12 9C12.4142 9 12.75 9.33579 12.75 9.75V13.5C12.75 13.9142 12.4142 14.25 12 14.25C11.5858 14.25 11.25 13.9142 11.25 13.5V9.75C11.25 9.33579 11.5858 9 12 9Z" fill="#3681FC"/>
+</svg>

+ 5 - 0
src/assets/icon/course/Countdown2.svg

@@ -0,0 +1,5 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M4.5 13.5C4.5 9.35786 7.85786 6 12 6C14.0783 6 15.958 6.84437 17.3172 8.21062C18.6671 9.56754 19.5 11.4358 19.5 13.5C19.5 17.6421 16.1421 21 12 21C7.85786 21 4.5 17.6421 4.5 13.5ZM12 4.5C7.02944 4.5 3 8.52944 3 13.5C3 18.4706 7.02944 22.5 12 22.5C16.9706 22.5 21 18.4706 21 13.5C21 11.4741 20.33 9.60378 19.2004 8.0998C19.2283 8.07884 19.255 8.05568 19.2803 8.03033L20.7803 6.53033C21.0732 6.23744 21.0732 5.76256 20.7803 5.46967C20.4874 5.17678 20.0126 5.17678 19.7197 5.46967L18.2197 6.96967C18.2154 6.97399 18.2111 6.97835 18.2069 6.98275C16.5928 5.44513 14.4061 4.5 12 4.5Z" fill="white" fill-opacity="0.9"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M9 2.25C9 1.83579 9.33579 1.5 9.75 1.5H14.25C14.6642 1.5 15 1.83579 15 2.25C15 2.66421 14.6642 3 14.25 3H9.75C9.33579 3 9 2.66421 9 2.25Z" fill="white" fill-opacity="0.9"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M12 9C12.4142 9 12.75 9.33579 12.75 9.75V13.5C12.75 13.9142 12.4142 14.25 12 14.25C11.5858 14.25 11.25 13.9142 11.25 13.5V9.75C11.25 9.33579 11.5858 9 12 9Z" fill="#A8EDC9"/>
+</svg>

BIN
src/assets/icon/course/aiLogo.png


Різницю між файлами не показано, бо вона завелика
+ 30 - 0
src/assets/icon/course/aiWait2.svg


BIN
src/assets/icon/course/aibgImage.png


+ 4 - 0
src/assets/icon/course/brush.svg

@@ -0,0 +1,4 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M12 6.75C12.2508 6.75 12.4849 6.87533 12.624 7.08397L15.624 11.584C15.7062 11.7072 15.75 11.8519 15.75 12V21C15.75 21.4142 15.4142 21.75 15 21.75C14.5858 21.75 14.25 21.4142 14.25 21V12.75H9.75V21C9.75 21.4142 9.41421 21.75 9 21.75C8.58579 21.75 8.25 21.4142 8.25 21V12C8.25 11.8519 8.29383 11.7072 8.37596 11.584L11.376 7.08397C11.5151 6.87533 11.7492 6.75 12 6.75ZM10.4014 11.25H13.5986L12 8.85208L10.4014 11.25Z" fill="#3681FC"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M12 21C16.9706 21 21 16.9706 21 12C21 7.02944 16.9706 3 12 3C7.02944 3 3 7.02944 3 12C3 16.9706 7.02944 21 12 21ZM12 22.5C17.799 22.5 22.5 17.799 22.5 12C22.5 6.20101 17.799 1.5 12 1.5C6.20101 1.5 1.5 6.20101 1.5 12C1.5 17.799 6.20101 22.5 12 22.5Z" fill="black" fill-opacity="0.9"/>
+</svg>

+ 3 - 0
src/assets/icon/course/cancel_left.svg

@@ -0,0 +1,3 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M11 6.61328L6 9.50003L11 12.3868V10H14.5C16.1569 10 17.5 11.3432 17.5 13C17.5 14.6569 16.1569 16 14.5 16H6C5.72386 16 5.5 16.2239 5.5 16.5C5.5 16.7762 5.72386 17 6 17H14.5C16.7091 17 18.5 15.2092 18.5 13C18.5 10.7909 16.7091 9.00003 14.5 9.00003H11V6.61328Z" fill="black" fill-opacity="0.9"/>
+</svg>

+ 3 - 0
src/assets/icon/course/cancel_right.svg

@@ -0,0 +1,3 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M13 6.61328L18 9.50003L13 12.3868V10H9.5C7.84315 10 6.5 11.3432 6.5 13C6.5 14.6569 7.84315 16 9.5 16H18C18.2761 16 18.5 16.2239 18.5 16.5C18.5 16.7762 18.2761 17 18 17H9.5C7.29086 17 5.5 15.2092 5.5 13C5.5 10.7909 7.29086 9.00003 9.5 9.00003H13V6.61328Z" fill="black" fill-opacity="0.9"/>
+</svg>

+ 9 - 0
src/assets/icon/course/changeType.svg

@@ -0,0 +1,9 @@
+<svg width="21" height="6" viewBox="0 0 21 6" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M1.05713 0.470583C1.80179 -0.155333 3.01121 -0.157081 3.75845 0.466679C5.4879 1.91035 7.86809 2.8 10.5 2.8C13.1319 2.8 15.5121 1.91035 17.2416 0.466679C17.9888 -0.157081 19.1982 -0.155333 19.9429 0.470583C20.6875 1.0965 20.6854 2.10956 19.9382 2.73332C17.5219 4.75032 14.1834 6 10.5 6C6.81664 6 3.47806 4.75032 1.06179 2.73332C0.314559 2.10956 0.312473 1.0965 1.05713 0.470583Z" fill="url(#paint0_linear_269_7318)"/>
+<defs>
+<linearGradient id="paint0_linear_269_7318" x1="0.5" y1="6" x2="20.5" y2="6" gradientUnits="userSpaceOnUse">
+<stop stop-color="#3673E8"/>
+<stop offset="1" stop-color="#AD88FD"/>
+</linearGradient>
+</defs>
+</svg>

Різницю між файлами не показано, бо вона завелика
+ 1 - 0
src/assets/icon/course/clearScreen.svg


+ 5 - 0
src/assets/icon/course/closeIcon.svg

@@ -0,0 +1,5 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<circle cx="12" cy="12" r="10" fill="#EE3E3E"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M9.1439 7.6929C9.29275 7.89983 9.24568 8.18824 9.03876 8.33709C7.75653 9.25949 6.92308 10.7631 6.92308 12.4615C6.92308 15.2654 9.19609 17.5384 12 17.5384C14.8039 17.5384 17.0769 15.2654 17.0769 12.4615C17.0769 10.7631 16.2435 9.25949 14.9612 8.33709C14.7543 8.18824 14.7073 7.89983 14.8561 7.6929C15.005 7.48598 15.2934 7.43891 15.5003 7.58776C17.0133 8.67615 18 10.4536 18 12.4615C18 15.7752 15.3137 18.4615 12 18.4615C8.68629 18.4615 6 15.7752 6 12.4615C6 10.4536 6.98673 8.67615 8.49971 7.58776C8.70663 7.43891 8.99504 7.48598 9.1439 7.6929Z" fill="white" fill-opacity="0.9"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M12 5.53845C12.2549 5.53845 12.4615 5.74509 12.4615 5.99999V11.5385C12.4615 11.7934 12.2549 12 12 12C11.7451 12 11.5385 11.7934 11.5385 11.5385V5.99999C11.5385 5.74509 11.7451 5.53845 12 5.53845Z" fill="white" fill-opacity="0.9"/>
+</svg>

+ 6 - 0
src/assets/icon/course/comment2.svg

@@ -0,0 +1,6 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M18.3451 3.59998H5.65487C4.85142 3.59991 4.08031 3.93214 3.50852 4.52471C2.93674 5.11727 2.6103 5.92243 2.59998 6.76584V15.8252C2.60185 16.2439 2.68245 16.6581 2.83711 17.044C2.99177 17.43 3.21747 17.7801 3.50128 18.0743C3.78508 18.3685 4.12139 18.6011 4.49095 18.7586C4.86051 18.916 5.25603 18.9954 5.65487 18.992H9.25104L10.7402 19.9974C11.1167 20.2506 11.5525 20.3897 11.9995 20.3996C12.4495 20.4085 12.8906 20.2677 13.2598 19.9974L14.7489 18.992H18.3451C19.1485 18.9916 19.9195 18.6591 20.4913 18.0664C21.063 17.4737 21.3894 16.6686 21.4 15.8252V6.76584C21.3894 5.92251 21.0629 5.11752 20.4912 4.52501C19.9195 3.93251 19.1485 3.60017 18.3451 3.59998ZM19.8725 15.8252C19.8711 16.0335 19.8305 16.2394 19.7527 16.4311C19.675 16.6227 19.5618 16.7963 19.4197 16.9417C19.2777 17.0871 19.1096 17.2015 18.9251 17.2782C18.7406 17.3549 18.5435 17.3924 18.3451 17.3885H14.52C14.3719 17.3855 14.226 17.427 14.0996 17.5082L12.4199 18.6714C12.3636 18.7262 12.2973 18.7685 12.2251 18.796C12.1529 18.8234 12.0762 18.8354 11.9995 18.8312C11.8515 18.8344 11.7058 18.7925 11.58 18.7106L9.90036 17.5484C9.77397 17.4672 9.62807 17.4257 9.47993 17.4287H5.65487C5.25609 17.4296 4.87287 17.2664 4.58733 16.9742C4.3018 16.682 4.13672 16.2839 4.12745 15.8654V6.76584C4.13672 6.34731 4.3018 5.94927 4.58733 5.65703C4.87287 5.36478 5.25609 5.20161 5.65487 5.20251H18.3451C18.7439 5.20161 19.1271 5.36478 19.4126 5.65703C19.6981 5.94927 19.8632 6.34731 19.8725 6.76584V15.8252Z" fill="black" fill-opacity="0.9"/>
+<path d="M11.9998 10.2115C11.695 10.2115 11.4027 10.3387 11.1872 10.5649C10.9717 10.7912 10.8506 11.098 10.8506 11.418C10.8386 11.5837 10.8592 11.7502 10.9113 11.9072C10.9634 12.0641 11.0458 12.208 11.1534 12.33C11.261 12.4519 11.3914 12.5491 11.5365 12.6157C11.6816 12.6822 11.8381 12.7165 11.9964 12.7165C12.1547 12.7165 12.3114 12.6822 12.4564 12.6157C12.6015 12.5491 12.7319 12.4519 12.8395 12.33C12.947 12.208 13.0295 12.0641 13.0816 11.9072C13.1337 11.7502 13.1544 11.5837 13.1423 11.418C13.1423 11.0992 13.0221 10.7934 12.8081 10.5674C12.594 10.3413 12.3034 10.2134 11.9998 10.2115Z" fill="black" fill-opacity="0.9"/>
+<path d="M8.18324 10.2115C7.95596 10.2115 7.73377 10.2823 7.54479 10.4149C7.35581 10.5475 7.20848 10.7359 7.1215 10.9563C7.03452 11.1767 7.01181 11.4194 7.05615 11.6534C7.10049 11.8874 7.2099 12.1023 7.37061 12.2711C7.53133 12.4398 7.73611 12.5547 7.95903 12.6012C8.18195 12.6478 8.41298 12.6239 8.62296 12.5326C8.83295 12.4413 9.01245 12.2867 9.13873 12.0883C9.265 11.8899 9.33237 11.6566 9.33237 11.418C9.33237 11.098 9.21133 10.7912 8.99582 10.5649C8.7803 10.3387 8.48802 10.2115 8.18324 10.2115Z" fill="black" fill-opacity="0.9"/>
+<path d="M15.8199 10.2115C15.669 10.2115 15.5195 10.2428 15.3801 10.3034C15.2407 10.364 15.114 10.4529 15.0073 10.5649C14.9006 10.677 14.8159 10.8099 14.7582 10.9563C14.7004 11.1027 14.6707 11.2596 14.6707 11.418C14.6586 11.5837 14.6793 11.7502 14.7314 11.9072C14.7835 12.0641 14.8659 12.208 14.9735 12.33C15.0811 12.4519 15.2115 12.5491 15.3566 12.6157C15.5016 12.6822 15.6582 12.7165 15.8165 12.7165C15.9748 12.7165 16.1314 12.6822 16.2765 12.6157C16.4216 12.5491 16.552 12.4519 16.6595 12.33C16.7671 12.208 16.8496 12.0641 16.9017 11.9072C16.9538 11.7502 16.9744 11.5837 16.9624 11.418C16.9624 11.0992 16.8422 10.7934 16.6281 10.5674C16.4141 10.3413 16.1235 10.2134 15.8199 10.2115Z" fill="black" fill-opacity="0.9"/>
+</svg>

+ 1 - 0
src/assets/icon/course/edit.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="1721093563614" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4275" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><path d="M469.333333 128a42.666667 42.666667 0 0 1 0 85.333333H213.333333v597.333334h597.333334v-256l0.298666-4.992A42.666667 42.666667 0 0 1 896 554.666667v256a85.333333 85.333333 0 0 1-85.333333 85.333333H213.333333a85.333333 85.333333 0 0 1-85.333333-85.333333V213.333333a85.333333 85.333333 0 0 1 85.333333-85.333333z m414.72 12.501333a42.666667 42.666667 0 0 1 0 60.330667L491.861333 593.066667a42.666667 42.666667 0 0 1-60.330666-60.330667l392.192-392.192a42.666667 42.666667 0 0 1 60.330666 0z" fill="#000000" p-id="4276"></path></svg>

+ 4 - 0
src/assets/icon/course/edit2.svg

@@ -0,0 +1,4 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M12 6.75C12.2508 6.75 12.4849 6.87533 12.624 7.08397L15.624 11.584C15.7062 11.7072 15.75 11.8519 15.75 12V21C15.75 21.4142 15.4142 21.75 15 21.75C14.5858 21.75 14.25 21.4142 14.25 21V12.75H9.75V21C9.75 21.4142 9.41421 21.75 9 21.75C8.58579 21.75 8.25 21.4142 8.25 21V12C8.25 11.8519 8.29383 11.7072 8.37596 11.584L11.376 7.08397C11.5151 6.87533 11.7492 6.75 12 6.75ZM10.4014 11.25H13.5986L12 8.85208L10.4014 11.25Z" fill="#3681FC"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M12 21C16.9706 21 21 16.9706 21 12C21 7.02944 16.9706 3 12 3C7.02944 3 3 7.02944 3 12C3 16.9706 7.02944 21 12 21ZM12 22.5C17.799 22.5 22.5 17.799 22.5 12C22.5 6.20101 17.799 1.5 12 1.5C6.20101 1.5 1.5 6.20101 1.5 12C1.5 17.799 6.20101 22.5 12 22.5Z" fill="black" fill-opacity="0.9"/>
+</svg>

+ 9 - 0
src/assets/icon/course/edit3.svg

@@ -0,0 +1,9 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M22.5 12C22.5 17.799 17.799 22.5 12 22.5C6.20101 22.5 1.5 17.799 1.5 12C1.5 6.20101 6.20101 1.5 12 1.5C17.799 1.5 22.5 6.20101 22.5 12Z" fill="#17C469"/>
+<mask id="mask0_447_20372" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="1" y="1" width="22" height="22">
+<path d="M22.5 12C22.5 17.799 17.799 22.5 12 22.5C6.20101 22.5 1.5 17.799 1.5 12C1.5 6.20101 6.20101 1.5 12 1.5C17.799 1.5 22.5 6.20101 22.5 12Z" fill="#17C469"/>
+</mask>
+<g mask="url(#mask0_447_20372)">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M12 6.75C12.2508 6.75 12.4849 6.87533 12.624 7.08397L15.624 11.584C15.7062 11.7072 15.75 11.8519 15.75 12V23C15.75 23.4142 15.4142 23.75 15 23.75C14.5858 23.75 14.25 23.4142 14.25 23V12.75H9.75V23C9.75 23.4142 9.41421 23.75 9 23.75C8.58579 23.75 8.25 23.4142 8.25 23V12C8.25 11.8519 8.29383 11.7072 8.37596 11.584L11.376 7.08397C11.5151 6.87533 11.7492 6.75 12 6.75ZM10.4014 11.25H13.5986L12 8.85208L10.4014 11.25Z" fill="white"/>
+</g>
+</svg>

+ 3 - 0
src/assets/icon/course/eraser.svg

@@ -0,0 +1,3 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M13.6464 6.14645C13.8417 5.95118 14.1583 5.95118 14.3536 6.14645L17.8536 9.64645C18.0488 9.84171 18.0488 10.1583 17.8536 10.3536L11.2071 17H17.5V18H10C9.86739 18 9.74021 17.9473 9.64645 17.8536L6.14645 14.3536C5.95118 14.1583 5.95118 13.8417 6.14645 13.6464L13.6464 6.14645ZM10 16.7929L7.20711 14L9 12.2071L11.7929 15L10 16.7929ZM12.5 14.2929L16.7929 10L14 7.20711L9.70711 11.5L12.5 14.2929Z" fill="black" fill-opacity="0.9"/>
+</svg>

+ 1 - 0
src/assets/icon/course/left.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="1720597362700" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5331" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><path d="M330.666667 512a35.84 35.84 0 0 0 11.52 26.453333l235.52 220.586667a35.84 35.84 0 1 0 49.066666-52.48L419.413333 512l207.36-194.56a35.84 35.84 0 1 0-49.066666-52.48L341.333333 484.266667a35.84 35.84 0 0 0-10.666666 27.733333zM512 0a512 512 0 1 0 512 512A512 512 0 0 0 512 0z m0 72.106667a439.466667 439.466667 0 0 1 170.666667 844.373333A439.466667 439.466667 0 0 1 200.533333 200.533333a438.613333 438.613333 0 0 1 311.04-128z" fill="#000000" p-id="5332"></path></svg>

+ 5 - 0
src/assets/icon/course/music.svg

@@ -0,0 +1,5 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M12.0001 3.18362C7.13095 3.18362 3.18374 7.13083 3.18374 11.9999C3.18374 16.4071 6.41825 20.0602 10.6428 20.7125C11.0848 20.7808 11.5381 20.8163 12.0001 20.8163C12.4058 20.8163 12.7348 21.1452 12.7348 21.551C12.7348 21.9567 12.4058 22.2857 12.0001 22.2857C11.4627 22.2857 10.9345 22.2444 10.4186 22.1647C5.48856 21.4035 1.71436 17.1431 1.71436 11.9999C1.71436 6.3193 6.31943 1.71423 12.0001 1.71423C16.5776 1.71423 20.4549 4.70396 21.7896 8.83532C22.1119 9.83321 22.2858 10.897 22.2858 11.9999C22.2858 12.4057 21.9569 12.7346 21.5511 12.7346C21.1453 12.7346 20.8164 12.4057 20.8164 11.9999C20.8164 11.0522 20.6671 10.1407 20.3913 9.28702C19.2469 5.74447 15.9216 3.18362 12.0001 3.18362Z" fill="black" fill-opacity="0.9"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M22.0162 13.8835C22.1871 14.0192 22.2856 14.2186 22.2856 14.4285V20.1428C22.2856 20.3322 22.2053 20.5139 22.0625 20.6479L21.3005 21.3622C21.003 21.6411 20.5206 21.6411 20.2231 21.3622C19.9255 21.0832 19.9255 20.631 20.2231 20.352L20.7618 19.8469V15.2717L17.7142 15.7479V20.8571C17.7142 21.0465 17.6339 21.2282 17.491 21.3622L16.7291 22.0765C16.4316 22.3554 15.9492 22.3554 15.6516 22.0765C15.3541 21.7975 15.3541 21.3452 15.6516 21.0663L16.1904 20.5612V15.1428C16.1904 14.7936 16.4596 14.4956 16.827 14.4382L21.3984 13.724C21.6194 13.6894 21.8453 13.7478 22.0162 13.8835Z" fill="#3681FC"/>
+<path d="M14.5713 12C14.5713 13.4202 13.4201 14.5714 11.9999 14.5714C10.5797 14.5714 9.42847 13.4202 9.42847 12C9.42847 10.5799 10.5797 9.42859 11.9999 9.42859C13.4201 9.42859 14.5713 10.5799 14.5713 12Z" fill="black" fill-opacity="0.9"/>
+</svg>

Різницю між файлами не показано, бо вона завелика
+ 0 - 0
src/assets/icon/course/phone.svg


BIN
src/assets/icon/course/practice.png


+ 4 - 0
src/assets/icon/course/record3.svg

@@ -0,0 +1,4 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M1.5 5.25C1.5 4.83579 1.83579 4.5 2.25 4.5H17.25C17.6642 4.5 18 4.83579 18 5.25V8.70943L21.5128 7.53849C21.7415 7.46225 21.993 7.5006 22.1885 7.64157C22.3841 7.78253 22.5 8.00892 22.5 8.25V15.75C22.5 15.9911 22.3841 16.2175 22.1885 16.3584C21.993 16.4994 21.7415 16.5378 21.5128 16.4615L18 15.2906V18.75C18 19.1642 17.6642 19.5 17.25 19.5H2.25C1.83579 19.5 1.5 19.1642 1.5 18.75V5.25ZM18 13.7094L21 14.7094V9.29057L18 10.2906V13.7094ZM3 6V18H16.5V6H3Z" fill="black" fill-opacity="0.9"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M4.5 15.75C4.5 15.3358 4.83579 15 5.25 15H11.25C11.6642 15 12 15.3358 12 15.75C12 16.1642 11.6642 16.5 11.25 16.5H5.25C4.83579 16.5 4.5 16.1642 4.5 15.75Z" fill="black" fill-opacity="0.9"/>
+</svg>

+ 4 - 0
src/assets/icon/course/record4.svg

@@ -0,0 +1,4 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M1.5 5.25C1.5 4.83579 1.83579 4.5 2.25 4.5H17.25C17.6642 4.5 18 4.83579 18 5.25V8.70943L21.5128 7.53849C21.7415 7.46225 21.993 7.5006 22.1885 7.64157C22.3841 7.78253 22.5 8.00892 22.5 8.25V15.75C22.5 15.9911 22.3841 16.2175 22.1885 16.3584C21.993 16.4994 21.7415 16.5378 21.5128 16.4615L18 15.2906V18.75C18 19.1642 17.6642 19.5 17.25 19.5H2.25C1.83579 19.5 1.5 19.1642 1.5 18.75V5.25ZM18 13.7094L21 14.7094V9.29057L18 10.2906V13.7094ZM3 6V18H16.5V6H3Z" fill="white" fill-opacity="0.9"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M4.5 15.75C4.5 15.3358 4.83579 15 5.25 15H11.25C11.6642 15 12 15.3358 12 15.75C12 16.1642 11.6642 16.5 11.25 16.5H5.25C4.83579 16.5 4.5 16.1642 4.5 15.75Z" fill="white" fill-opacity="0.9"/>
+</svg>

+ 5 - 0
src/assets/icon/course/reset.svg

@@ -0,0 +1,5 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M2.25 19.5C2.25 19.0858 2.58579 18.75 3 18.75H22.5C22.9142 18.75 23.25 19.0858 23.25 19.5C23.25 19.9142 22.9142 20.25 22.5 20.25H3C2.58579 20.25 2.25 19.9142 2.25 19.5Z" fill="black"/>
+<path d="M3 8.25L3.75 14.25L8.25 10.5L3 8.25Z" fill="black"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M6.88061 9.09714C8.37158 7.62191 10.4445 6.75 12.75 6.75C17.3064 6.75 21 10.4437 21 15C21 15.4142 21.3358 15.75 21.75 15.75C22.1643 15.75 22.5 15.4142 22.5 15C22.5 9.61522 18.1348 5.25 12.75 5.25C9.83406 5.25 7.20333 6.45088 5.41113 8.46737L3.29545 7.56065C3.04847 7.4548 2.76374 7.48917 2.54904 7.65074C2.33433 7.81231 2.22247 8.0764 2.2558 8.34303L3.0058 14.343C3.03982 14.6151 3.21963 14.847 3.47471 14.9477C3.7298 15.0483 4.01948 15.0017 4.23015 14.8262L8.73015 11.0762C8.93061 10.9091 9.02983 10.6499 8.99215 10.3917C8.95447 10.1335 8.78529 9.91343 8.54545 9.81065L6.88061 9.09714ZM4.48437 9.70214L3.9064 9.45443L4.03677 10.4974C4.17389 10.2236 4.32334 9.95829 4.48437 9.70214ZM4.91452 12.3033C5.14843 11.5796 5.47638 10.9088 5.884 10.302L6.82973 10.7073L4.91452 12.3033Z" fill="black"/>
+</svg>

+ 4 - 0
src/assets/icon/course/right.svg

@@ -0,0 +1,4 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M3.66782 3.1263C3.87421 2.94284 4.19025 2.96143 4.37371 3.16782L8.37371 7.66782C8.5421 7.85727 8.5421 8.14274 8.37371 8.33219L4.37371 12.8322C4.19025 13.0386 3.87421 13.0572 3.66782 12.8737C3.46143 12.6903 3.44284 12.3742 3.6263 12.1678L7.33103 8.00001L3.6263 3.83219C3.44284 3.6258 3.46143 3.30976 3.66782 3.1263Z" fill="black"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M7.66782 3.1263C7.87421 2.94284 8.19025 2.96143 8.37371 3.16782L12.3737 7.66782C12.5421 7.85727 12.5421 8.14274 12.3737 8.33219L8.37371 12.8322C8.19025 13.0386 7.87421 13.0572 7.66782 12.8737C7.46143 12.6903 7.44284 12.3742 7.6263 12.1678L11.331 8.00001L7.6263 3.83219C7.44284 3.6258 7.46143 3.30976 7.66782 3.1263Z" fill="black"/>
+</svg>

Різницю між файлами не показано, бо вона завелика
+ 6 - 0
src/assets/icon/course/robot3.svg


BIN
src/assets/icon/course/stop1.png


BIN
src/assets/icon/course/stop2.png


+ 1 - 0
src/assets/icon/course/yes.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="1720596520120" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4306" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><path d="M511.999994 0C229.205543 0 0.020822 229.226376 0.020822 512.020827c0 282.752797 229.184721 511.979173 511.979173 511.979173s511.979173-229.226376 511.979173-511.979173C1023.979167 229.226376 794.794446 0 511.999994 0zM815.371918 318.95082l-346.651263 461.201969c-10.830249 14.370907-27.32555 23.409999-45.27877 24.742952-1.582882 0.124964-3.12411 0.166619-4.665338 0.166619-16.328682 0-32.074198-6.373185-43.779197-17.911565l-192.903389-189.44604c-24.617988-24.20144-24.992881-63.731847-0.791441-88.349835 24.20144-24.659643 63.731847-24.951226 88.349835-0.833096l142.042875 139.501932 303.788472-404.2182c20.744091-27.575479 59.899605-33.115568 87.516739-12.413131C830.534266 252.219827 836.116009 291.375341 815.371918 318.95082z" fill="#1afa29" p-id="4307"></path></svg>

BIN
src/assets/icon/newIcons/rootImg.png


Різницю між файлами не показано, бо вона завелика
+ 147 - 0
src/components/classRoomHelper/component/AnnotationCanvas.vue


+ 1527 - 0
src/components/classRoomHelper/component/countdown.vue

@@ -0,0 +1,1527 @@
+<template>
+	<div class="countdown">
+		<div class="c_timeBox" v-if="showType == 0">
+			<div class="c_tb_top">
+				<div class="c_time">
+					<div class="c_t_item" v-if="type == 0">
+						<div class="c_t_i_card">
+							<div>
+								<span class="c_t_i_btnTop" v-if="!isCountdown"
+									><el-button class="c_t_i_btn" @click.stop="addTime(600)"
+										>+</el-button
+									></span
+								>
+								<div>{{ countdownTimeShow.m1 }}</div>
+								<span class="c_t_i_btnBottom" v-if="!isCountdown"
+									><el-button class="c_t_i_btn" @click.stop="reduceTime(600)"
+										>-</el-button
+									></span
+								>
+							</div>
+							<div>
+								<span class="c_t_i_btnTop" v-if="!isCountdown"
+									><el-button class="c_t_i_btn" @click.stop="addTime(60)"
+										>+</el-button
+									></span
+								>
+								<div>{{ countdownTimeShow.m2 }}</div>
+								<span class="c_t_i_btnBottom" v-if="!isCountdown"
+									><el-button class="c_t_i_btn" @click.stop="reduceTime(60)"
+										>-</el-button
+									></span
+								>
+							</div>
+							<span>分</span>
+						</div>
+						<div class="c_t_i_card">
+							<div>
+								<span class="c_t_i_btnTop" v-if="!isCountdown"
+									><el-button class="c_t_i_btn" @click.stop="addTime(10)"
+										>+</el-button
+									></span
+								>
+								<div>{{ countdownTimeShow.s1 }}</div>
+								<span class="c_t_i_btnBottom" v-if="!isCountdown"
+									><el-button class="c_t_i_btn" @click.stop="reduceTime(10)"
+										>-</el-button
+									></span
+								>
+							</div>
+							<div>
+								<span class="c_t_i_btnTop" v-if="!isCountdown"
+									><el-button class="c_t_i_btn" @click.stop="addTime(1)"
+										>+</el-button
+									></span
+								>
+								<div>{{ countdownTimeShow.s2 }}</div>
+								<span class="c_t_i_btnBottom" v-if="!isCountdown"
+									><el-button class="c_t_i_btn" @click.stop="reduceTime(1)"
+										>-</el-button
+									></span
+								>
+							</div>
+							<span>秒</span>
+						</div>
+					</div>
+					<div class="c_t_item" v-if="type == 1">
+						<div class="c_t_i_card">
+							<div>
+								<div>{{ keepTimeShow.m1 }}</div>
+							</div>
+							<div>
+								<div>{{ keepTimeShow.m2 }}</div>
+							</div>
+							<span>分</span>
+						</div>
+
+						<div class="c_t_i_card">
+							<div>
+								<div>{{ keepTimeShow.s1 }}</div>
+							</div>
+							<div>
+								<div>{{ keepTimeShow.s2 }}</div>
+							</div>
+							<span>秒</span>
+						</div>
+					</div>
+				</div>
+
+				<!-- <div class="c_choiceTime" v-if="type == 0">
+					<div class="c_title">
+						<span>倒计时长</span>
+					</div>
+					<div class="c_ct_box">
+						<span @click.stop="setCountdownTime(30)">30秒</span>
+						<span @click.stop="setCountdownTime(60)">1分钟</span>
+						<span @click.stop="setCountdownTime(120)">2分钟</span>
+						<span @click.stop="setCountdownTime(180)">3分钟</span>
+						<span @click.stop="setCountdownTime(300)">5分钟</span>
+						<span @click.stop="setCountdownTime(360)">6分钟</span>
+						<span @click.stop="setCountdownTime(480)">8分钟</span>
+						<span @click.stop="setCountdownTime(600)">10分钟</span>
+					</div>
+				</div> -->
+
+				<div class="c_behaviorTag">
+					<div class="c_title">
+						<span>行为标签</span>
+						<div class="c_t_btnArea">
+							<span
+								@click.stop="changeBehaviorTagType(0)"
+								:class="[behaviorTagType == 0 ? 'c_t_ba_active' : '']"
+								>常用</span
+							>
+							<span
+								@click.stop="changeBehaviorTagType(1)"
+								:class="[behaviorTagType == 1 ? 'c_t_ba_active' : '']"
+								>更多</span
+							>
+							<!-- <el-button-group>
+								<el-button
+									size="mini"
+									:disabled="isCountdown || isKeepTime"
+									:type="behaviorTagType == 0 ? 'primary' : 'info'"
+									@click.stop="changeBehaviorTagType(0)"
+								>
+									常用
+								</el-button>
+
+								<el-button
+									size="mini"
+									:disabled="isCountdown || isKeepTime"
+									:type="behaviorTagType == 1 ? 'primary' : 'info'"
+									@click.stop="changeBehaviorTagType(1)"
+								>
+									更多
+								</el-button>
+							</el-button-group> -->
+						</div>
+					</div>
+
+					<div
+						class="c_bt_box"
+						v-loading="behaviorTagMoreLoading && behaviorTagType == 1"
+					>
+						<span
+							v-if="behaviorTagType == 1"
+							:class="[choiceBehavior.includes(item) ? 'c_bt_b_active' : '']"
+							v-for="(item, index) in behaviorTagMore"
+							@click.stop="choiceBehaviorTag(item)"
+							:key="behaviorTagType + '-' + index"
+							>{{ item }}</span
+						>
+						<span
+							v-if="behaviorTagType == 0"
+							:class="[choiceBehavior.includes(item) ? 'c_bt_b_active' : '']"
+							v-for="(item, index) in behaviorTagCommon"
+							@click.stop="choiceBehaviorTag(item)"
+							:key="behaviorTagType + '-' + index"
+							>{{ item }}</span
+						>
+					</div>
+				</div>
+
+				<div class="c_btnArea">
+					<span @click.stop="music()">
+						<el-tooltip
+							class="item"
+							effect="light"
+							:content="sourceActive ? '关闭音乐' : '开启音乐'"
+							placement="top"
+						>
+							<svg
+								width="24"
+								height="24"
+								viewBox="0 0 24 24"
+								fill="none"
+								xmlns="http://www.w3.org/2000/svg"
+							>
+								<path
+									fill-rule="evenodd"
+									clip-rule="evenodd"
+									d="M12.0001 3.18362C7.13095 3.18362 3.18374 7.13083 3.18374 11.9999C3.18374 16.4071 6.41825 20.0602 10.6428 20.7125C11.0848 20.7808 11.5381 20.8163 12.0001 20.8163C12.4058 20.8163 12.7348 21.1452 12.7348 21.551C12.7348 21.9567 12.4058 22.2857 12.0001 22.2857C11.4627 22.2857 10.9345 22.2444 10.4186 22.1647C5.48856 21.4035 1.71436 17.1431 1.71436 11.9999C1.71436 6.3193 6.31943 1.71423 12.0001 1.71423C16.5776 1.71423 20.4549 4.70396 21.7896 8.83532C22.1119 9.83321 22.2858 10.897 22.2858 11.9999C22.2858 12.4057 21.9569 12.7346 21.5511 12.7346C21.1453 12.7346 20.8164 12.4057 20.8164 11.9999C20.8164 11.0522 20.6671 10.1407 20.3913 9.28702C19.2469 5.74447 15.9216 3.18362 12.0001 3.18362Z"
+									:fill="sourceActive ? '#E11E1E' : 'black'"
+									fill-opacity="0.9"
+								/>
+								<path
+									fill-rule="evenodd"
+									clip-rule="evenodd"
+									d="M22.0162 13.8835C22.1871 14.0192 22.2856 14.2186 22.2856 14.4285V20.1428C22.2856 20.3322 22.2053 20.5139 22.0625 20.6479L21.3005 21.3622C21.003 21.6411 20.5206 21.6411 20.2231 21.3622C19.9255 21.0832 19.9255 20.631 20.2231 20.352L20.7618 19.8469V15.2717L17.7142 15.7479V20.8571C17.7142 21.0465 17.6339 21.2282 17.491 21.3622L16.7291 22.0765C16.4316 22.3554 15.9492 22.3554 15.6516 22.0765C15.3541 21.7975 15.3541 21.3452 15.6516 21.0663L16.1904 20.5612V15.1428C16.1904 14.7936 16.4596 14.4956 16.827 14.4382L21.3984 13.724C21.6194 13.6894 21.8453 13.7478 22.0162 13.8835Z"
+									:fill="sourceActive ? '#E11E1E' : '#3681FC'"
+								/>
+								<path
+									d="M14.5713 12C14.5713 13.4202 13.4201 14.5714 11.9999 14.5714C10.5797 14.5714 9.42847 13.4202 9.42847 12C9.42847 10.5799 10.5797 9.42859 11.9999 9.42859C13.4201 9.42859 14.5713 10.5799 14.5713 12Z"
+									:fill="sourceActive ? '#E11E1E' : 'black'"
+									fill-opacity="0.9"
+								/>
+							</svg>
+						</el-tooltip>
+					</span>
+					<div class="c_ba_startArea">
+						<div
+							:class="[
+								!canStartCountdownTime
+									? 'c_ba_startType0'
+									: !isCountdown
+									? 'c_ba_startType'
+									: 'c_ba_startType2',
+							]"
+							v-if="type == 0"
+							style=""
+							@click.stop="countdownTimeFn()"
+						>
+							<svg
+								v-if="!isCountdown"
+								t="1721117381559"
+								viewBox="0 0 1024 1024"
+								version="1.1"
+								xmlns="http://www.w3.org/2000/svg"
+								p-id="12941"
+								width="64"
+								height="64"
+							>
+								<path
+									d="M161.2 839.9v-654c0-56.1 60.7-91.1 109.3-63.1l566.3 327c48.6 28 48.6 98.1 0 126.2L270.4 903c-48.5 28-109.2-7.1-109.2-63.1z"
+									p-id="12942"
+								></path>
+							</svg>
+							<svg
+								v-else
+								t="1721198913879"
+								class="icon"
+								viewBox="0 0 1024 1024"
+								version="1.1"
+								xmlns="http://www.w3.org/2000/svg"
+								p-id="4266"
+								width="64"
+								height="64"
+							>
+								<path
+									d="M426.666667 138.666667v746.666666a53.393333 53.393333 0 0 1-53.333334 53.333334H266.666667a53.393333 53.393333 0 0 1-53.333334-53.333334V138.666667a53.393333 53.393333 0 0 1 53.333334-53.333334h106.666666a53.393333 53.393333 0 0 1 53.333334 53.333334z m330.666666-53.333334H650.666667a53.393333 53.393333 0 0 0-53.333334 53.333334v746.666666a53.393333 53.393333 0 0 0 53.333334 53.333334h106.666666a53.393333 53.393333 0 0 0 53.333334-53.333334V138.666667a53.393333 53.393333 0 0 0-53.333334-53.333334z"
+									p-id="4267"
+								></path>
+							</svg>
+							<!-- <svg v-else t="1721117616634" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="13970" width="64" height="64"><path d="M128 128m53.333333 0l661.333334 0q53.333333 0 53.333333 53.333333l0 661.333334q0 53.333333-53.333333 53.333333l-661.333334 0q-53.333333 0-53.333333-53.333333l0-661.333334q0-53.333333 53.333333-53.333333Z" p-id="13971"></path></svg> -->
+						</div>
+						<div
+							:class="[!isKeepTime ? 'c_ba_startType' : 'c_ba_startType2']"
+							v-if="type == 1"
+							@click.stop="keepTimeFn()"
+						>
+							<svg
+								v-if="!isKeepTime"
+								t="1721117381559"
+								viewBox="0 0 1024 1024"
+								version="1.1"
+								xmlns="http://www.w3.org/2000/svg"
+								p-id="12941"
+								width="64"
+								height="64"
+							>
+								<path
+									d="M161.2 839.9v-654c0-56.1 60.7-91.1 109.3-63.1l566.3 327c48.6 28 48.6 98.1 0 126.2L270.4 903c-48.5 28-109.2-7.1-109.2-63.1z"
+									p-id="12942"
+								></path>
+							</svg>
+							<svg
+								v-else
+								t="1721198913879"
+								class="icon"
+								viewBox="0 0 1024 1024"
+								version="1.1"
+								xmlns="http://www.w3.org/2000/svg"
+								p-id="4266"
+								width="64"
+								height="64"
+							>
+								<path
+									d="M426.666667 138.666667v746.666666a53.393333 53.393333 0 0 1-53.333334 53.333334H266.666667a53.393333 53.393333 0 0 1-53.333334-53.333334V138.666667a53.393333 53.393333 0 0 1 53.333334-53.333334h106.666666a53.393333 53.393333 0 0 1 53.333334 53.333334z m330.666666-53.333334H650.666667a53.393333 53.393333 0 0 0-53.333334 53.333334v746.666666a53.393333 53.393333 0 0 0 53.333334 53.333334h106.666666a53.393333 53.393333 0 0 0 53.333334-53.333334V138.666667a53.393333 53.393333 0 0 0-53.333334-53.333334z"
+									p-id="4267"
+								></path>
+							</svg>
+							<!-- <svg v-else t="1721117616634" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="13970" width="64" height="64"><path d="M128 128m53.333333 0l661.333334 0q53.333333 0 53.333333 53.333333l0 661.333334q0 53.333333-53.333333 53.333333l-661.333334 0q-53.333333 0-53.333333-53.333333l0-661.333334q0-53.333333 53.333333-53.333333Z" p-id="13971"></path></svg> -->
+						</div>
+					</div>
+					<span @click.stop="reset()">
+						<el-tooltip
+							class="item"
+							effect="light"
+							content="重置"
+							placement="top"
+						>
+							<svg
+								width="24"
+								height="24"
+								viewBox="0 0 24 24"
+								fill="none"
+								xmlns="http://www.w3.org/2000/svg"
+							>
+								<path
+									fill-rule="evenodd"
+									clip-rule="evenodd"
+									d="M2.25 19.5C2.25 19.0858 2.58579 18.75 3 18.75H22.5C22.9142 18.75 23.25 19.0858 23.25 19.5C23.25 19.9142 22.9142 20.25 22.5 20.25H3C2.58579 20.25 2.25 19.9142 2.25 19.5Z"
+									fill="black"
+								/>
+								<path d="M3 8.25L3.75 14.25L8.25 10.5L3 8.25Z" fill="black" />
+								<path
+									fill-rule="evenodd"
+									clip-rule="evenodd"
+									d="M6.88061 9.09714C8.37158 7.62191 10.4445 6.75 12.75 6.75C17.3064 6.75 21 10.4437 21 15C21 15.4142 21.3358 15.75 21.75 15.75C22.1643 15.75 22.5 15.4142 22.5 15C22.5 9.61522 18.1348 5.25 12.75 5.25C9.83406 5.25 7.20333 6.45088 5.41113 8.46737L3.29545 7.56065C3.04847 7.4548 2.76374 7.48917 2.54904 7.65074C2.33433 7.81231 2.22247 8.0764 2.2558 8.34303L3.0058 14.343C3.03982 14.6151 3.21963 14.847 3.47471 14.9477C3.7298 15.0483 4.01948 15.0017 4.23015 14.8262L8.73015 11.0762C8.93061 10.9091 9.02983 10.6499 8.99215 10.3917C8.95447 10.1335 8.78529 9.91343 8.54545 9.81065L6.88061 9.09714ZM4.48437 9.70214L3.9064 9.45443L4.03677 10.4974C4.17389 10.2236 4.32334 9.95829 4.48437 9.70214ZM4.91452 12.3033C5.14843 11.5796 5.47638 10.9088 5.884 10.302L6.82973 10.7073L4.91452 12.3033Z"
+									fill="black"
+								/>
+							</svg>
+						</el-tooltip>
+					</span>
+				</div>
+
+				<div class="ActivityMemo">
+					<span @click.stop="changeShowType(1)">
+						教学活动备忘
+						<svg
+							width="16"
+							height="16"
+							viewBox="0 0 16 16"
+							fill="none"
+							xmlns="http://www.w3.org/2000/svg"
+						>
+							<path
+								fill-rule="evenodd"
+								clip-rule="evenodd"
+								d="M3.66782 3.1263C3.87421 2.94284 4.19025 2.96143 4.37371 3.16782L8.37371 7.66782C8.5421 7.85727 8.5421 8.14274 8.37371 8.33219L4.37371 12.8322C4.19025 13.0386 3.87421 13.0572 3.66782 12.8737C3.46143 12.6903 3.44284 12.3742 3.6263 12.1678L7.33103 8.00001L3.6263 3.83219C3.44284 3.6258 3.46143 3.30976 3.66782 3.1263Z"
+								fill="black"
+							/>
+							<path
+								fill-rule="evenodd"
+								clip-rule="evenodd"
+								d="M7.66782 3.1263C7.87421 2.94284 8.19025 2.96143 8.37371 3.16782L12.3737 7.66782C12.5421 7.85727 12.5421 8.14274 12.3737 8.33219L8.37371 12.8322C8.19025 13.0386 7.87421 13.0572 7.66782 12.8737C7.46143 12.6903 7.44284 12.3742 7.6263 12.1678L11.331 8.00001L7.6263 3.83219C7.44284 3.6258 7.46143 3.30976 7.66782 3.1263Z"
+								fill="black"
+							/>
+						</svg>
+					</span>
+				</div>
+			</div>
+
+			<div class="c_changeType">
+				<div class="c_ct_btn" @click.stop="changeType(0)">
+					<div>倒计时</div>
+					<span v-if="type == 0"></span>
+					<svg
+						width="21"
+						height="6"
+						viewBox="0 0 21 6"
+						fill="none"
+						xmlns="http://www.w3.org/2000/svg"
+						v-if="type == 0"
+					>
+						<path
+							fill-rule="evenodd"
+							clip-rule="evenodd"
+							d="M1.05713 0.470583C1.80179 -0.155333 3.01121 -0.157081 3.75845 0.466679C5.4879 1.91035 7.86809 2.8 10.5 2.8C13.1319 2.8 15.5121 1.91035 17.2416 0.466679C17.9888 -0.157081 19.1982 -0.155333 19.9429 0.470583C20.6875 1.0965 20.6854 2.10956 19.9382 2.73332C17.5219 4.75032 14.1834 6 10.5 6C6.81664 6 3.47806 4.75032 1.06179 2.73332C0.314559 2.10956 0.312473 1.0965 1.05713 0.470583Z"
+							fill="url(#paint0_linear_269_7318)"
+						/>
+						<defs>
+							<linearGradient
+								id="paint0_linear_269_7318"
+								x1="0.5"
+								y1="6"
+								x2="20.5"
+								y2="6"
+								gradientUnits="userSpaceOnUse"
+							>
+								<stop stop-color="#3673E8" />
+								<stop offset="1" stop-color="#AD88FD" />
+							</linearGradient>
+						</defs>
+					</svg>
+				</div>
+
+				<span></span>
+
+				<div class="c_ct_btn" @click.stop="changeType(1)">
+					<div>计时器</div>
+					<span v-if="type == 1"></span>
+					<svg
+						width="21"
+						height="6"
+						viewBox="0 0 21 6"
+						fill="none"
+						xmlns="http://www.w3.org/2000/svg"
+						v-if="type == 1"
+					>
+						<path
+							fill-rule="evenodd"
+							clip-rule="evenodd"
+							d="M1.05713 0.470583C1.80179 -0.155333 3.01121 -0.157081 3.75845 0.466679C5.4879 1.91035 7.86809 2.8 10.5 2.8C13.1319 2.8 15.5121 1.91035 17.2416 0.466679C17.9888 -0.157081 19.1982 -0.155333 19.9429 0.470583C20.6875 1.0965 20.6854 2.10956 19.9382 2.73332C17.5219 4.75032 14.1834 6 10.5 6C6.81664 6 3.47806 4.75032 1.06179 2.73332C0.314559 2.10956 0.312473 1.0965 1.05713 0.470583Z"
+							fill="url(#paint0_linear_269_7318)"
+						/>
+						<defs>
+							<linearGradient
+								id="paint0_linear_269_7318"
+								x1="0.5"
+								y1="6"
+								x2="20.5"
+								y2="6"
+								gradientUnits="userSpaceOnUse"
+							>
+								<stop stop-color="#3673E8" />
+								<stop offset="1" stop-color="#AD88FD" />
+							</linearGradient>
+						</defs>
+					</svg>
+				</div>
+				<!-- <el-button-group>
+        <el-button
+          :type="isCountdown ? 'danger' : type == 0 ? 'primary' : ''"
+          @click.stop="changeType(0)"
+          :disabled="isCountdown || isKeepTime"
+        >
+          倒计时
+        </el-button>
+
+        <el-button
+          :type="isKeepTime ? 'danger' : type == 1 ? 'primary' : ''"
+          @click.stop="changeType(1)"
+          :disabled="isCountdown || isKeepTime"
+        >
+          计时器
+        </el-button>
+      </el-button-group> -->
+			</div>
+		</div>
+
+		<div class="c_behavior" v-if="showType == 1">
+			<div class="behaviorBack">
+				<span
+					@click.stop="changeShowType(0)"
+					>
+					<svg
+							width="16"
+							height="16"
+							viewBox="0 0 16 16"
+							fill="none"
+							xmlns="http://www.w3.org/2000/svg"
+						>
+							<path
+								fill-rule="evenodd"
+								clip-rule="evenodd"
+								d="M3.66782 3.1263C3.87421 2.94284 4.19025 2.96143 4.37371 3.16782L8.37371 7.66782C8.5421 7.85727 8.5421 8.14274 8.37371 8.33219L4.37371 12.8322C4.19025 13.0386 3.87421 13.0572 3.66782 12.8737C3.46143 12.6903 3.44284 12.3742 3.6263 12.1678L7.33103 8.00001L3.6263 3.83219C3.44284 3.6258 3.46143 3.30976 3.66782 3.1263Z"
+								fill="black"
+							/>
+							<path
+								fill-rule="evenodd"
+								clip-rule="evenodd"
+								d="M7.66782 3.1263C7.87421 2.94284 8.19025 2.96143 8.37371 3.16782L12.3737 7.66782C12.5421 7.85727 12.5421 8.14274 12.3737 8.33219L8.37371 12.8322C8.19025 13.0386 7.87421 13.0572 7.66782 12.8737C7.46143 12.6903 7.44284 12.3742 7.6263 12.1678L11.331 8.00001L7.6263 3.83219C7.44284 3.6258 7.46143 3.30976 7.66782 3.1263Z"
+								fill="black"
+							/>
+						</svg>返回</span
+				>
+
+				<div class="c_step" ref="stepRef" v-loading="memorandumLoading">
+					<el-timeline>
+						<el-timeline-item
+							v-for="(item, index) in memorandumList"
+							:key="index"
+							:timestamp="item.time"
+						>
+							<div v-html="item.text"></div>
+							<!-- <span v-html="activity.content"></span> -->
+						</el-timeline-item>
+					</el-timeline>
+				</div>
+			</div>
+		</div>
+		<mini-audio
+			v-show="false"
+			ref="audioRef"
+			:loop="true"
+			:audio-source="sourceUrl"
+		></mini-audio>
+		<mini-audio
+			v-show="false"
+			ref="endSourceUrlRef"
+			:loop="false"
+			:audio-source="endSourceUrl"
+		></mini-audio>
+	</div>
+</template>
+
+<script>
+import { v4 as uuidv4 } from "uuid";
+export default {
+	props: {
+		courseDetail: {
+			type: Object,
+			default: () => {},
+		},
+		fileId: {
+			type: Array,
+			default: () => [],
+		},
+	},
+	data() {
+		return {
+			userid: this.$route.query.userid,
+			courseId: this.$route.query.courseId,
+			showType: 0,
+			sourceUrl:
+				"https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/%E5%80%92%E8%AE%A1%E6%97%B6%E9%9F%B3%E4%B9%901721355956636.mp3",
+			endSourceUrl:
+				"https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/%E5%80%92%E6%95%B010%E7%A7%92%E5%8F%A0%E5%8A%A0%E9%9F%B3%E6%95%881721638403882.MP3",
+			sourceActive: false,
+			type: 0, //0:倒计时   1:计时器
+			isCountdown: false,
+			isKeepTime: false,
+			countdownTime: 0,
+			countdownTimeDefault: 0,
+			countdownTimeTimer: null,
+			keepTime: 0,
+			keepTimeTimer: null,
+			startCountdownTime: 0,
+			behaviorTagType: 0, //0:常用  1:更多
+			behaviorTagMore: [], //更多
+			behaviorTagMoreLoading: false,
+			behaviorTagCommon: [
+				"小组讨论",
+				"小组汇报",
+				"动手实验",
+				"课堂游戏",
+				"自主学习",
+				"作品展示",
+				"学生演讲",
+				"学生分享",
+				"随堂练习",
+				"快速问答",
+				"阅读资料",
+				"观察记录",
+			], //常用
+			choiceBehavior: [],
+			memorandumList: [],
+			memorandumLoading: false,
+		};
+	},
+	computed: {
+		canStartCountdownTime() {
+			let _result = false;
+
+			if (this.countdownTime > 0) {
+				_result = true;
+			}
+			return _result;
+		},
+		countdownTimeShow() {
+			let _result = {
+				m1: 0,
+				m2: 0,
+				s1: 0,
+				s2: 0,
+			};
+
+			if (this.countdownTime <= 0) return _result;
+
+			let minutes = Math.floor(this.countdownTime / 60);
+			let seconds = this.countdownTime % 60;
+			if (minutes > 9) {
+				_result.m1 = Math.floor(minutes / 10);
+				_result.m2 = minutes % 10;
+			} else {
+				_result.m1 = 0;
+				_result.m2 = minutes;
+			}
+			if (seconds > 9) {
+				_result.s1 = Math.floor(seconds / 10);
+				_result.s2 = seconds % 10;
+			} else {
+				_result.s1 = 0;
+				_result.s2 = seconds;
+			}
+
+			return _result;
+		},
+		keepTimeShow() {
+			let _result = {
+				m1: 0,
+				m2: 0,
+				s1: 0,
+				s2: 0,
+			};
+
+			if (this.keepTime <= 0) return _result;
+
+			let minutes = Math.floor(this.keepTime / 60);
+			let seconds = this.keepTime % 60;
+			if (minutes > 9) {
+				_result.m1 = Math.floor(minutes / 10);
+				_result.m2 = minutes % 10;
+			} else {
+				_result.m1 = 0;
+				_result.m2 = minutes;
+			}
+			if (seconds > 9) {
+				_result.s1 = Math.floor(seconds / 10);
+				_result.s2 = seconds % 10;
+			} else {
+				_result.s1 = 0;
+				_result.s2 = seconds;
+			}
+
+			return _result;
+		},
+	},
+	watch: {
+		countdownTime(newValue) {
+			if (this.isCountdown && this.countdownTimeTimer && newValue == 0) {
+				this.countdownTimeFinish();
+			} else if (!this.isCountdown && !this.countdownTimeTimer) {
+				this.countdownTimeDefault = newValue;
+			}
+			if (this.$refs.audioRef.playing && this.sourceActive && newValue == 10) {
+				this.$refs.audioRef.stop();
+				this.$refs.endSourceUrlRef.play();
+				// this.$refs.audioRef.setVolume(newValue / 10);
+			}
+		},
+	},
+	methods: {
+		insertMemorandum(_html) {
+			return;
+			//保存行为操作
+			//variable
+			//btn
+			let params = [
+				{
+					uid: this.userid,
+					courseId: this.courseId,
+					content: _html,
+				},
+			];
+
+			this.ajax
+				.post(
+					this.$store.state.api + "insert_systemOperation_countdownBehavior",
+					params
+				)
+				.then((res) => {
+					if (res.data == 1) {
+						console.log("保存操作成功");
+					} else {
+						console.log("保存操作失败");
+					}
+				})
+				.catch((e) => {
+					console.log("保存操作失败");
+					console.log(e);
+				});
+		},
+		changeShowType(newType) {
+			this.showType = newType;
+			if (this.showType == 1) {
+				this.selectMemorandum();
+			}
+		},
+		changeType(newType) {
+			if (this.isCountdown || this.isKeepTime) return;
+			this.type = newType;
+		},
+		changeBehaviorTagType(newType) {
+			if (this.isCountdown) return this.$message.error("正在倒计时");
+			if (this.isKeepTime) return this.$message.error("正在计时");
+			if (this.behaviorTagType == newType) return;
+			this.choiceBehavior = [];
+			this.behaviorTagType = newType;
+			if (this.behaviorTagType == 1 && this.behaviorTagMore.length <= 0) {
+				this.getBehaviorTagMore();
+			}
+		},
+		setCountdownTime(newTime = 0) {
+			if (this.isCountdown) return this.$message.error("正在倒计时");
+			if (this.isKeepTime) return this.$message.error("正在计时");
+			this.countdownTime = newTime;
+		},
+		addTime(time = 0) {
+			if (this.isCountdown) return console.log("正在计时");
+			if (this.countdownTime >= 3600) {
+				return this.$message.error("倒计时最高一小时");
+			}
+			if (this.countdownTime + time > 3600) {
+				return (this.countdownTime = 3600);
+			}
+			this.countdownTime += time;
+		},
+		reduceTime(time = 0) {
+			if (this.isCountdown) return console.log("正在计时");
+			if (this.countdownTime - time < 0) return (this.countdownTime = 0);
+			this.countdownTime -= time;
+		},
+		choiceBehaviorTag(tag) {
+			if (this.isCountdown) return this.$message.error("正在倒计时");
+			if (this.isKeepTime) return this.$message.error("正在计时");
+			let _index = this.choiceBehavior.findIndex((i) => i == tag);
+			if (_index != -1) {
+				// 数组删除指定下标数据
+				this.choiceBehavior.splice(_index, 1);
+			} else {
+				this.choiceBehavior.push(tag);
+			}
+		},
+		countdownTimeFn() {
+			if (this.isCountdown) {
+				//取消
+				clearInterval(this.countdownTimeTimer);
+				this.countdownTimeTimer = null;
+				this.isCountdown = false;
+				if (this.$refs.audioRef.playing && this.sourceActive) {
+					this.$refs.audioRef.pause();
+				}
+				this.$message.success("已暂停倒计时");
+			} else {
+				//开始
+				if (this.countdownTime == 0)
+					return this.$message.error("请设置倒计时时间");
+				this.isCountdown = true;
+				this.$message.success("已开始倒计时");
+				if (this.sourceActive) {
+					this.$refs.audioRef.setVolume(0);
+					this.$refs.audioRef.play();
+				}
+				if (this.countdownTime >= 20 && this.sourceActive) {
+					let volume = 0;
+					let sourceTimer = setInterval(() => {
+						volume += 1;
+						if (volume >= 10) {
+							volume = 10;
+							clearInterval(sourceTimer);
+							sourceTimer = null;
+						}
+						this.$refs.audioRef.setVolume(volume / 10);
+					}, 1000);
+				} else if (
+					this.countdownTime <= 20 &&
+					this.countdownTime > 10 &&
+					this.sourceActive
+				) {
+					this.$refs.audioRef.setVolume(1);
+				} else if (this.countdownTime <= 10 && this.sourceActive) {
+					this.$refs.audioRef.stop();
+					this.$refs.endSourceUrlRef.setProgress(
+						(10 - this.countdownTime) / 10
+					);
+					this.$refs.endSourceUrlRef.play();
+				}
+				this.countdownTimeTimer = setInterval(() => {
+					this.isCountdown = true;
+					this.countdownTime -= 1;
+				}, 1000);
+				let timeShow = `${this.countdownTimeShow.m1}${this.countdownTimeShow.m2}分钟${this.countdownTimeShow.s1}${this.countdownTimeShow.s2}秒`;
+				this.insertMemorandum(
+					`设置<span class="variable"></span><span class="btn">倒计时${timeShow}</span>${
+						this.choiceBehavior.length > 0
+							? ",用于" +
+							  '<span class="btn">' +
+							  this.choiceBehavior.join("、") +
+							  "</span>"
+							: ""
+					}`
+				);
+			}
+		},
+		countdownTimeFinish() {
+			clearInterval(this.countdownTimeTimer);
+			this.countdownTimeTimer = null;
+			this.isCountdown = false;
+			this.$parent.type = 1;
+			this.$parent.itemType = 3;
+			this.changeShowType(0)
+			if (this.$refs.audioRef.playing && this.sourceActive) {
+				this.$refs.audioRef.pause();
+			}
+			let _data = {
+				type: "countdown",
+				time: this.countdownTimeDefault,
+				tag: this.choiceBehavior,
+			};
+			this.insertMemorandum(`<span class="btn">倒计时</span>结束`);
+			this.insertData(_data);
+		},
+		keepTimeFn() {
+			if (this.isKeepTime) {
+				this.isKeepTime = false;
+				clearInterval(this.keepTimeTimer);
+				this.keepTimeTimer = null;
+				if (this.$refs.audioRef.playing && this.sourceActive) {
+					this.$refs.audioRef.pause();
+				}
+				this.$message.success("已停止计时");
+			} else {
+				this.isKeepTime = true;
+				if (this.sourceActive) {
+					this.$refs.audioRef.setVolume(1);
+					this.$refs.audioRef.play();
+				}
+				this.keepTimeTimer = setInterval(() => {
+					this.keepTime += 1;
+				}, 1000);
+				this.$message.success("已开始计时");
+				this.insertMemorandum(
+					`使用<span class="btn">计时器</span>${
+						this.choiceBehavior.length > 0
+							? ",用于" +
+							  '<span class="btn">' +
+							  this.choiceBehavior.join("、") +
+							  "</span>"
+							: ""
+					}`
+				);
+			}
+		},
+		music() {
+			this.sourceActive = !this.sourceActive;
+			if (
+				(this.$refs.audioRef.playing || this.$refs.endSourceUrlRef.playing) &&
+				!this.sourceActive
+			) {
+				this.$refs.audioRef.pause();
+				this.$refs.endSourceUrlRef.stop();
+			} else if (this.sourceActive) {
+				if (this.isCountdown) {
+					if (this.countdownTime > 10) {
+						this.$refs.audioRef.play();
+					} else {
+						this.$refs.audioRef.stop();
+						this.$refs.endSourceUrlRef.setProgress(
+							(10 - this.countdownTime) / 10
+						);
+						this.$refs.endSourceUrlRef.play();
+					}
+				} else if (this.isKeepTime) {
+					this.$refs.audioRef.play();
+				}
+			}
+		},
+		reset() {
+			if (this.type == 0) {
+				if (this.isCountdown) {
+					this.$confirm("正在倒计时!确定重置倒计时吗?", "提醒", {
+						confirmButtonText: "确定",
+						cancelButtonText: "取消",
+						type: "warning",
+					})
+						.then((_) => {
+							clearInterval(this.countdownTimeTimer);
+							this.countdownTimeTimer = null;
+							// this.countdownTime = this.countdownTimeDefault;
+							this.countdownTime = 0;
+							this.isCountdown = false;
+							this.choiceBehavior = [];
+							this.$message.success("已重置");
+							if (this.$refs.audioRef.playing) {
+								this.$refs.audioRef.pause();
+							}
+						})
+						.catch((_) => {
+							console.log("取消重置");
+						});
+				} else {
+					this.$confirm("确定重置倒计时吗?", "提醒", {
+						confirmButtonText: "确定",
+						cancelButtonText: "取消",
+						type: "warning",
+					})
+						.then((_) => {
+							if (this.$refs.audioRef.playing) {
+								this.$refs.audioRef.pause();
+							}
+							// this.countdownTime = this.countdownTimeDefault;
+							this.countdownTime = 0;
+							this.isCountdown = false;
+							this.choiceBehavior = [];
+							this.$message.success("已重置");
+						})
+						.catch((_) => {
+							console.log("取消重置");
+						});
+				}
+			} else if (this.type == 1) {
+				if (this.isKeepTime) {
+					this.$confirm("正在计时!确定重置计时吗?", "提醒", {
+						confirmButtonText: "确定",
+						cancelButtonText: "取消",
+						type: "warning",
+					})
+						.then((_) => {
+							if (this.$refs.audioRef.playing) {
+								this.$refs.audioRef.pause();
+							}
+							clearInterval(this.keepTimeTimer);
+							this.keepTimeTimer = null;
+							let _data = {
+								type: "keepTime",
+								time: this.keepTime,
+								tag: this.choiceBehavior,
+							};
+							let timeShow = `${this.keepTimeShow.m1}${this.keepTimeShow.m2}分钟${this.keepTimeShow.s1}${this.keepTimeShow.s2}秒`;
+							this.insertMemorandum(
+								`结束计时器,<span class="btn">计时</span><span class="variable">${timeShow}</span>${
+									this.choiceBehavior.length > 0
+										? ",用于" +
+										  '<span class="btn">' +
+										  this.choiceBehavior.join("、") +
+										  "</span>"
+										: ""
+								}`
+							);
+							this.keepTime = 0;
+							this.isKeepTime = false;
+							this.insertData(_data);
+						})
+						.catch((_) => {
+							console.log("取消重置");
+						});
+				} else {
+					let _data = {
+						type: "keepTime",
+						time: this.keepTime,
+						tag: this.choiceBehavior,
+					};
+					if (this.$refs.audioRef.playing) {
+						this.$refs.audioRef.pause();
+					}
+					this.insertData(_data);
+					let timeShow = `${this.keepTimeShow.m1}${this.keepTimeShow.m2}分钟${this.keepTimeShow.s1}${this.keepTimeShow.s2}秒`;
+					this.insertMemorandum(
+						`结束计时器,<span class="btn">计时</span><span class="variable">${timeShow}</span>${
+							this.choiceBehavior.length > 0
+								? ",用于" +
+								  '<span class="btn">' +
+								  this.choiceBehavior.join("、") +
+								  "</span>"
+								: ""
+						}`
+					);
+					this.keepTime = 0;
+					this.isKeepTime = false;
+					// this.choiceBehavior = [];
+					this.$message.success("已重置");
+				}
+			}
+		},
+		getBehaviorTagMore() {
+			this.behaviorTagMoreLoading = true;
+			let _textData = `课程名称:${this.courseDetail.title}\n分类:${this.courseDetail.name}\n\n`;
+			let _chapters = JSON.parse(this.courseDetail.chapters);
+			_chapters.forEach((i1, index1) => {
+				if (i1.dyName) {
+					_textData += `阶段${index1 + 1}:${i1.dyName}\n`;
+				}
+				i1.chapterInfo[0].taskJson.forEach((i2, index2) => {
+					if (i2.task) {
+						_textData += `任务${index2 + 1}:${i2.task}\n`;
+						_textData += `${i2.taskDetail}\n`;
+					}
+				});
+				_textData += "\n";
+			});
+			let _msg = `Language: Please use the same language as the user requirement, if the user speaks Chinese, the specific text of your answer should also be in Chinese.
+ATTENTION: Use '##' to SPLIT SECTIONS, not '#'. Output format carefully referenced "Format example".
+Instruction: Based on the context, follow "Format example", write content
+
+#Context
+##任务
+在以下课堂中,如果老师设置一个倒计时,他可能想开展哪些教学活动?每个教学活动使用4个字,进行简洁精确的描述,请返回所有可能的行为名称,不需要额外的解释。请返回最有可能的12个活动类
+
+##Format example
+["小组讨论","小组汇报","动手实验","课堂游戏","自主学习","作品展示","学生演讲","学生分享","随堂练习","快速问答","阅读资料","观察记录"]
+
+##课堂内容
+${_textData}
+`;
+
+			this.behaviorTagMore = [];
+			let params = {
+				assistant_id: "6063369f-289a-11ef-8bf4-12e77c4cb76b",
+				userId: this.userid,
+				message: [{ type: "text", text: _msg }],
+				session_name: uuidv4(),
+				file_ids: this.fileId,
+			};
+			this.ajax
+				// .post("https://gpt4.cocorobo.cn/chat", params)
+				// .post("https://claude3.cocorobo.cn/chat", params)
+				.post("https://gpt4.cocorobo.cn/ai_agent_park_chat", params)
+				.then((res) => {
+					// console.log(res)
+					let _data = res.data.FunctionResponse.message;
+					_data = _data.replaceAll("```json", "").replaceAll("```", "");
+					const match = _data.match(/\[\s*[^]*\s*\]/);
+					let _result = JSON.parse(match[0]);
+					this.behaviorTagMore = _result;
+					this.behaviorTagMoreLoading = false;
+				})
+				.catch((e) => {
+					this.behaviorTagMoreLoading = false;
+					this.$message.error("获取更多行为标签失败");
+					this.behaviorTagType = 0;
+					this.behaviorTagMore = [];
+					console.log(e);
+				});
+		},
+		insertData(data = null) {
+			if (!data) return;
+			let params = [
+				{
+					uid: this.userid,
+					courseId: this.courseId,
+					content: JSON.stringify(data),
+				},
+			];
+			this.ajax
+				.post(
+					this.$store.state.api + "insert_systemOperation_classRoomHelper",
+					params
+				)
+				.then((res) => {
+					if (res.data == 1) {
+						console.log("保存成功");
+					} else {
+						console.log("保存失败");
+					}
+				})
+				.catch((e) => {
+					console.log("保存失败👇");
+					console.log(e);
+				});
+		},
+		selectMemorandum() {
+			return;
+			this.memorandumLoading = false;
+			let params = {
+				uid: this.userid,
+				courseId: this.courseId,
+			};
+			this.memorandumList = [];
+			this.ajax
+				.get(
+					this.$store.state.api + "select_systemOperation_countdownBehavior",
+					params
+				)
+				.then((res) => {
+					let _data = res.data[0];
+					if (_data.length) {
+						this.memorandumList = _data;
+					} else {
+						this.memorandumList = [];
+					}
+					this.memorandumLoading = false;
+					console.log(res);
+				})
+				.catch((err) => {
+					console.log(err);
+					this.memorandumLoading = false;
+					this.$message.error("获取行为备忘失败");
+				});
+		},
+	},
+};
+</script>
+
+<style scoped>
+.countdown {
+	width: 100%;
+	height: 100%;
+
+	/* display: flex;
+  flex-direction: column;
+  align-items: center; */
+	/* justify-content: center; */
+	/* padding: auto;
+  overflow: auto; */
+}
+
+.c_timeBox {
+	width: 100%;
+	height: 100%;
+	position: relative;
+	display: flex;
+	flex-direction: column;
+	justify-content: space-between;
+}
+
+.c_tb_top {
+	width: 100%;
+	max-height: calc(100% - 60px);
+	margin: auto;
+	overflow-x: hidden;
+}
+
+.c_behavior {
+	width: 100%;
+	height: 100%;
+}
+
+.c_changeType {
+	width: 100%;
+	height: 60px;
+	display: flex;
+	align-items: center;
+	justify-content: space-evenly;
+	border-top: solid 1px #e7e7e7;
+	box-sizing: border-box;
+}
+
+.c_changeType > span {
+	width: 2px;
+	height: 30px;
+	background-color: #e7e7e7;
+}
+
+.c_ct_btn {
+	width: 100px;
+	height: 90%;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	cursor: pointer;
+	position: relative;
+}
+
+.c_ct_btn > div {
+	font-size: 18px;
+	font-weight: bold;
+}
+
+.c_ct_btn > span {
+	position: absolute;
+	width: 60%;
+	height: 60%;
+	background: #6c8cff67;
+
+	filter: blur(20px);
+	border-radius: 50%;
+}
+
+.c_ct_btn > svg {
+	width: 30px;
+	height: 30px;
+	position: absolute;
+	margin-top: 30px;
+}
+
+.c_time {
+	width: 100%;
+	height: 200px;
+	display: flex;
+	align-items: center;
+	justify-content: center;
+}
+
+.c_t_item {
+	color: black;
+	display: flex;
+	align-items: center;
+	justify-content: center;
+}
+
+.c_t_i_card {
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	position: relative;
+	padding: 0px 30px;
+	background-color: #fff;
+	margin: 0 10px;
+	box-shadow: 0px 0px 5px 2px #1d398314;
+	/* box-shadow: 1px 1px 20px 4px #1d39830d; */
+	border-radius: 8px;
+}
+
+.c_t_i_card > span {
+	position: absolute;
+	bottom: 25px;
+	right: 10px;
+	font-size: 16px;
+}
+
+.c_t_i_card > div {
+	display: flex;
+	flex-direction: column;
+	align-items: center;
+	justify-content: space-between;
+}
+
+.c_t_i_card > div > div {
+	font-size: 5em;
+	font-weight: bold;
+	margin: 0 5px;
+}
+
+.c_t_i_card > div > span {
+	margin: 0;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	width: 25px;
+	height: 25px;
+	position: absolute;
+}
+
+.c_t_i_btnTop {
+	top: -30px;
+}
+
+.c_t_i_btnBottom {
+	bottom: -30px;
+}
+
+.c_t_i_btn {
+	font-size: 1.3em;
+	width: 25px;
+	height: 25px;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	padding: 0 !important;
+	background-color: #f0f2f5;
+}
+
+.c_choiceTime {
+	width: 100%;
+	height: auto;
+	box-sizing: border-box;
+	padding: 20px;
+}
+
+.c_title {
+	display: flex;
+	align-items: center;
+	justify-content: space-between;
+	width: 100%;
+}
+
+.c_title > span {
+	font-size: 20px;
+	font-weight: bold;
+}
+
+.c_t_btnArea {
+	margin-left: 20px;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+}
+
+.c_t_btnArea > span {
+	width: 40px;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	margin-left: 10px;
+	cursor: pointer;
+	color: #999999;
+	position: relative;
+	font-size: 14px;
+}
+
+.c_t_ba_active {
+	color: black !important;
+}
+
+.c_t_ba_active::after {
+	content: "";
+	width: 100%;
+	height: 3px;
+	background-color: #3681fc;
+	position: absolute;
+	bottom: -7px;
+	left: 1px;
+}
+
+.c_ct_box {
+	width: 100%;
+	height: auto;
+	display: flex;
+	align-items: center;
+	justify-content: space-around;
+	flex-wrap: wrap;
+	padding-top: 10px;
+}
+
+.c_ct_box > span {
+	width: 20%;
+	height: 30px;
+	border-radius: 20px;
+	box-sizing: border-box;
+	border: solid 1px #d0d0d0;
+	margin: 10px 2%;
+	background-color: #fff;
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	transition: 0.1s;
+	cursor: pointer;
+}
+
+.c_ct_box > span:hover {
+	background-color: #409eff;
+	border: solid 1px #409eff;
+	color: #fff;
+}
+
+.c_behaviorTag {
+	width: 100%;
+	height: auto;
+	box-sizing: border-box;
+	padding: 20px;
+}
+
+.c_bt_box {
+	width: 100%;
+	height: auto;
+	min-height: 100px;
+	display: flex;
+	align-items: flex-start;
+	justify-content: space-around;
+	flex-wrap: wrap;
+	overflow: auto;
+	margin-top: 10px;
+}
+
+.c_bt_box > span {
+	width: auto;
+	height: auto;
+	padding: 6px 10px;
+	border-radius: 50px;
+	border: 0.5px solid #e0eafb;
+	box-shadow: 0px 2px 5px 0px #1d398314;
+	box-shadow: 0.5px 0.5px 10px 2px #1d39830d;
+	margin: 10px 0;
+	background-color: #fff;
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	transition: 0.1s;
+	cursor: pointer;
+	font-size: 15px;
+}
+
+.c_bt_b_active {
+	background-color: #409eff !important;
+	border: solid 1px #409eff !important;
+	color: #fff;
+}
+
+.c_bt_box > span:hover {
+	background-color: #409eff !important;
+	border: solid 1px #409eff !important;
+	color: #fff !important;
+}
+
+.c_btnArea {
+	width: 100%;
+	height: 100px;
+	display: flex;
+	align-items: center;
+	justify-content: center;
+}
+
+.c_btnArea > span {
+	width: auto;
+	height: auto;
+	padding: 5px 10px;
+	/* border: solid 1px #d0d0d0;
+	background-color: #fff; */
+	/* border-radius: 20px; */
+	cursor: pointer;
+	transition: 0.2s;
+}
+
+.c_btnArea > span > svg {
+	width: 30px;
+	height: 30px;
+}
+
+/* .c_btnArea > span:hover {
+	border: solid 1px #409eff;
+	background-color: #409eff;
+	color: #fff;
+} */
+
+.c_ba_startArea {
+	width: 60px;
+	height: 60px;
+	margin: 0 40px;
+	display: flex;
+	align-items: center;
+	justify-content: center;
+}
+
+.c_ba_startType0 {
+	width: 60px;
+	height: 60px;
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	border-radius: 50%;
+	border: solid 8px #e0eafb;
+	color: #e0eafb;
+	cursor: pointer;
+	transition: 0.2s;
+}
+
+.c_ba_startType0 > svg {
+	fill: #afbff7;
+	height: 60%;
+	position: relative;
+	left: 3px;
+	transition: 0.2s;
+}
+
+.c_ba_startType {
+	width: 60px;
+	height: 60px;
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	border-radius: 50%;
+	border: solid 8px #3681fc;
+	color: #3681fc;
+	cursor: pointer;
+	transition: 0.2s;
+}
+
+.c_ba_startType > svg {
+	fill: #677bf0;
+	height: 60%;
+	position: relative;
+	left: 3px;
+	transition: 0.2s;
+}
+
+.c_ba_startType2 {
+	width: 60px;
+	height: 60px;
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	border-radius: 50%;
+	border: solid 8px #f5222d;
+	color: #f5222d;
+	cursor: pointer;
+	transition: 0.2s;
+}
+
+.c_ba_startType2 > svg {
+	fill: #f5222d;
+	height: 60%;
+	transition: 0.2s;
+}
+
+.sourceActive {
+	border: solid 1px #409eff !important;
+	background-color: #409eff !important;
+	color: #fff;
+}
+
+.c_step {
+	width: 100%;
+	height: calc(100% - 80px);
+	margin-top: 20px;
+	padding: 20px 50px;
+	box-sizing: border-box;
+	overflow: auto;
+}
+.c_s_item {
+	display: flex;
+	justify-content: center;
+	align-items: center;
+}
+
+.ActivityMemo{
+	width: 100%;
+	height: 30px;
+	display: flex;
+	align-items: center;
+	margin-top: 20px;
+	
+	box-sizing: border-box;
+	padding-left: 20px;
+}
+
+.ActivityMemo>span{
+	display: flex;
+	align-items: center;
+	cursor: pointer;
+}
+
+.ActivityMemo>span>svg{
+	margin-left: 5px;
+	position: relative;
+	top: 1px;
+	width:20px;
+	height:20px
+}
+
+.behaviorBack{
+	width: 100%;
+	height: 30px;
+	display: flex;
+	align-items: center;
+	margin-top: 20px;
+	box-sizing: border-box;
+	padding-left: 20px;
+}
+
+.behaviorBack>span{
+	display: flex;
+	align-items: center;
+	cursor: pointer;
+	width: 80px;
+}
+
+.behaviorBack>span>svg{
+	margin-right: 5px;
+	position: relative;
+	top: 1px;
+	width:20px;
+	height:20px;
+	transform: rotate(180deg);
+}
+</style>

+ 693 - 0
src/components/classRoomHelper/component/languageAssistant.vue

@@ -0,0 +1,693 @@
+<template>
+	<div class="languageAssistant">
+		<div class="la_coco">
+			<el-image
+				style="width: 105px; height: 105px"
+				v-show="showIndex == 2"
+				:src="require('../../../assets/icon/course/aiVanish.svg')"
+				fit="fill"
+			></el-image>
+			<el-image
+				style="width: 105px; height: 105px;transform: scale(1.7,1.7);"
+				v-show="showIndex == 0"
+				:src="require('../../../assets/icon/course/aiWait2.svg')"
+				fit="fill"
+			></el-image>
+			<el-image
+				style="width: 105px; height: 105px"
+				v-show="showIndex == 1"
+				:src="require('../../../assets/icon/course/aiTalk.svg')"
+				fit="fill"
+			></el-image>
+		</div>
+		<div
+			class="la_message"
+			:style="show ? '' : 'height:calc(100% - 170px - 200px - 40px)'"
+			ref="messageRef"
+		>
+			<div class="la_m_talk" v-if="show">
+				<div v-if="showTextIndex == 0" v-html="htmlContent(aiText)"></div>
+				<div v-if="showTextIndex == 1">{{ userText }}</div>
+				<div v-if="showTextIndex == 2">正在组织语言...</div>
+			</div>
+		</div>
+		<div class="la_btn">
+			<div class="la_b_noTel" v-if="!show">
+				<el-tooltip class="item" effect="light" content="通话" placement="top">
+					<span>
+						<svg
+							@click.stop="recordStart"
+							t="1721367811838"
+							viewBox="0 0 1024 1024"
+							version="1.1"
+							xmlns="http://www.w3.org/2000/svg"
+							p-id="4525"
+							width="64"
+							height="64"
+						>
+							<path
+								d="M65.771 502.182c0 246.632 199.937 446.566 446.57 446.565 246.613 0 446.549-199.934 446.551-446.565 0-246.633-199.936-446.549-446.55-446.55-246.635 0.001-446.57 199.917-446.571 446.55z m651.885-173.77c31.489 31.473 1.642 148.828-114.292 264.773C487.396 709.131 370.06 738.929 338.589 707.492c-27.278-27.315-74.96-60.574-12.892-110.423 62.087-49.886 79.429-25.343 107.582 2.772 19.674 19.711 69.436-21.368 112.394-64.328 42.94-42.996 83.986-92.719 64.368-112.43-28.155-28.153-52.679-45.511-2.792-107.562 49.904-62.049 83.125-14.405 110.406 12.891z"
+								p-id="4526"
+							></path>
+						</svg>
+					</span>
+				</el-tooltip>
+			</div>
+			<div class="la_b_isTel" v-else>
+				<el-tooltip
+					class="item"
+					effect="light"
+					content="暂停语音"
+					placement="top"
+					v-if="talkLoading"
+				>
+					<span @click.stop="stopTalk">
+						<img :src="require('../../../assets/icon/course/stop1.png')" />
+						<!-- <svg
+              @click.stop="recordStart"
+              t="1721367811838"
+              viewBox="0 0 1024 1024"
+              version="1.1"
+              xmlns="http://www.w3.org/2000/svg"
+              p-id="4525"
+              width="64"
+              height="64"
+            >
+              <path
+                d="M65.771 502.182c0 246.632 199.937 446.566 446.57 446.565 246.613 0 446.549-199.934 446.551-446.565 0-246.633-199.936-446.549-446.55-446.55-246.635 0.001-446.57 199.917-446.571 446.55z m651.885-173.77c31.489 31.473 1.642 148.828-114.292 264.773C487.396 709.131 370.06 738.929 338.589 707.492c-27.278-27.315-74.96-60.574-12.892-110.423 62.087-49.886 79.429-25.343 107.582 2.772 19.674 19.711 69.436-21.368 112.394-64.328 42.94-42.996 83.986-92.719 64.368-112.43-28.155-28.153-52.679-45.511-2.792-107.562 49.904-62.049 83.125-14.405 110.406 12.891z"
+                p-id="4526"
+              ></path>
+            </svg> -->
+					</span>
+				</el-tooltip>
+
+				<el-tooltip
+					class="item"
+					effect="light"
+					content="朗读"
+					placement="top"
+					v-else
+				>
+					<span class="readAloud" @click.stop="talkAllText">
+						<svg
+							t="1721117381559"
+							viewBox="0 0 1024 1024"
+							version="1.1"
+							xmlns="http://www.w3.org/2000/svg"
+							p-id="12941"
+							width="64"
+							height="64"
+						>
+							<path
+								d="M161.2 839.9v-654c0-56.1 60.7-91.1 109.3-63.1l566.3 327c48.6 28 48.6 98.1 0 126.2L270.4 903c-48.5 28-109.2-7.1-109.2-63.1z"
+								p-id="12942"
+							></path>
+						</svg>
+					</span>
+				</el-tooltip>
+
+				<el-tooltip class="item" effect="light" content="挂断" placement="top">
+					<svg
+						@click.stop="stopRecord"
+						t="1721367811838"
+						viewBox="0 0 1024 1024"
+						version="1.1"
+						xmlns="http://www.w3.org/2000/svg"
+						p-id="4525"
+						width="64"
+						height="64"
+					>
+						<path
+							d="M65.771 502.182c0 246.632 199.937 446.566 446.57 446.565 246.613 0 446.549-199.934 446.551-446.565 0-246.633-199.936-446.549-446.55-446.55-246.635 0.001-446.57 199.917-446.571 446.55z m651.885-173.77c31.489 31.473 1.642 148.828-114.292 264.773C487.396 709.131 370.06 738.929 338.589 707.492c-27.278-27.315-74.96-60.574-12.892-110.423 62.087-49.886 79.429-25.343 107.582 2.772 19.674 19.711 69.436-21.368 112.394-64.328 42.94-42.996 83.986-92.719 64.368-112.43-28.155-28.153-52.679-45.511-2.792-107.562 49.904-62.049 83.125-14.405 110.406 12.891z"
+							p-id="4526"
+						></path>
+					</svg>
+				</el-tooltip>
+				<el-tooltip class="item" effect="light" content="中断" placement="top">
+					<span @click.stop="interrupt">
+						<img :src="require('../../../assets/icon/course/stop2.png')" />
+						<!-- <svg
+              t="1721372012678"
+              class="icon"
+              viewBox="0 0 1024 1024"
+              version="1.1"
+              xmlns="http://www.w3.org/2000/svg"
+              p-id="5554"
+              width="64"
+              height="64"
+            >
+              <path
+                d="M885.6 413.8c-32.3 0-60.1 19.8-71.9 47.9h-18.1c-16.6 0-30 13.4-30 30s13.4 30 30 30h18.1c11.8 28.1 39.5 47.9 71.9 47.9 42.9 0 77.9-34.9 77.9-77.9 0-42.9-35-77.9-77.9-77.9zM690.4 461.7h-21.1c-16.6 0-30 13.4-30 30s13.4 30 30 30h21.1c16.6 0 30-13.4 30-30s-13.4-30-30-30zM564.1 461.7h-10c-16.6 0-30 13.4-30 30s13.4 30 30 30h10c16.6 0 30-13.4 30-30s-13.4-30-30-30zM709.7 115.7c-13.7-9.4-32.3-5.9-41.7 7.8L436.5 461.8c-0.8-0.1-1.6-0.1-2.3-0.1H212.5c-11.8-28.1-39.5-47.9-71.9-47.9-39.4 0-72.1 29.5-77.2 67.5-1.2 3.2-1.8 6.7-1.8 10.3 0 3.6 0.6 7.1 1.8 10.3 5.1 38.1 37.7 67.5 77.2 67.5 32.3 0 60.1-19.8 71.9-47.9h183l-240.1 351c-9.4 13.7-5.9 32.3 7.8 41.7 5.2 3.5 11.1 5.2 16.9 5.2 9.6 0 19-4.6 24.8-13.1l512.6-749c9.4-13.5 5.9-32.2-7.8-41.6z"
+                p-id="5555"
+              ></path>
+            </svg> -->
+					</span>
+				</el-tooltip>
+			</div>
+		</div>
+		<!-- 录音转文字 -->
+		<iframe
+			allow="camera *; microphone *;display-capture;midi;encrypted-media;"
+			src="https://beta.cloud.cocorobo.cn/browser/public/index.html"
+			ref="iiframe"
+			v-show="false"
+		></iframe>
+
+		<!-- 文字转语音-->
+		<iframe
+			allow="camera *; microphone *;display-capture;midi;encrypted-media;"
+			src="https://beta.cloud.cocorobo.cn/browser/public/index1.html"
+			ref="iiframe2"
+			v-show="false"
+		></iframe>
+	</div>
+</template>
+
+<script>
+import { v4 as uuidv4 } from "uuid";
+import MarkdownIt from "markdown-it";
+export default {
+	props: {},
+	data() {
+		return {
+			show: false,
+			showIndex: 2, //0 :在说话 1 : 接收 2:待命
+			aiStatus: 0,
+			aiText: "我是可可同学,我是个小小百事通,你有什么想和我聊一聊?",
+			userText: "",
+			showTextIndex: 0, //0:ai,1:用户, 2:组织语言  3: 无
+			timer: null,
+			isOpen: false,
+			userId: this.$route.query.userid,
+			chatLoading: false,
+			talkLoading: false,
+			source: null,
+			talkTextList: [],
+		};
+	},
+	computed: {
+		htmlContent() {
+			const md = new MarkdownIt();
+			return (_md) => {
+				return md.render(_md);
+			};
+		},
+	},
+	methods: {
+		scrollBottom() {
+			this.$nextTick(() => {
+				this.$refs.messageRef.scrollTop = this.$refs.messageRef.scrollHeight;
+			});
+		},
+		talkAllText() {
+			if (this.talkLoading && this.aiText == "") return;
+			let _resultText = this.removeMarkdown(this.aiText);
+			this.talkTextList.push(_resultText);
+			this.talkText();
+		},
+		recordStart(_text) {
+			// this.show = true;
+			// this.showIndex = 0;
+			// return
+			var OpenCC = require("opencc-js");
+			let converter = OpenCC.Converter({
+				from: "hk",
+				to: "cn",
+			});
+			if (this.isOpen)
+				return this.$message.info("已开启语音助手,无需重复开启");
+			let iiframe = this.$refs["iiframe"];
+			iiframe.contentWindow.window.document.getElementById(
+				"languageOptions"
+			).selectedIndex = 2; //普通话
+			iiframe.contentWindow.testdoContinuousPronunciationAssessment();
+			this.isOpen = true;
+			this.show = true;
+			this.aiText = "我是可可同学,我是个小小百事通,你有什么想和我聊一聊?";
+			iiframe.contentWindow.onRecognizedResult = (e) => {
+				let _msg = converter(e.privText);
+
+				console.log("👇");
+				console.log(_msg);
+				// _msg = converter(_msg)
+				if (!_msg) return console.log("输出为空");
+				if (this.show == true) {
+					if (
+						_msg.indexOf(converter("可可同学")) != -1 &&
+						_msg.indexOf(converter("停止")) != -1
+					) {
+						this.stopTalk();
+					} else if (
+						this.showTextIndex == 2 ||
+						this.chatLoading ||
+						this.talkLoading
+					) {
+						return console.log("组织语言中");
+						// }else if(_msg.indexOf('可可同学')!=-1 && _msg.indexOf("停止")!=-1){
+						// 	this.stopTalk();
+					} else {
+						this.showTextIndex = 1;
+						this.aiText = "";
+						this.userText += _msg;
+						this.scrollBottom();
+						this.aiStatus = 1;
+						if (this.timer) {
+							clearTimeout(this.timer);
+							this.timer = null;
+						}
+						this.timer = setTimeout(() => {
+							if (this.userText.indexOf(converter("关闭语音助手")) != -1) {
+								// return setTimeout(()=>{
+								this.show = false;
+								this.showTextIndex = 3;
+								this.aiStatus = 2;
+								this.aiText = "";
+								this.userText = "";
+								this.stopRecord();
+								return;
+								// },1000)
+							}
+							this.showTextIndex = 2;
+							this.aiText = "";
+							let regExp = new RegExp(
+								converter("计时") + "(.+)" + converter("分钟")
+							);
+							if (false && regExp.test(this.userText)) {
+								// setTimeout(() => {
+								// let _number = this.userText.match(regExp)[1];
+								// let _time = 0;
+								// if (!/^\d+$/.test(_number)) {
+								//   _time = this.chineseToNumber(_number) * 60;
+								// } else {
+								//   _time = parseInt(_numberList[1]) * 60;
+								// }
+								// this.$emit("startTime", _time);
+								// this.aiStatus = 0;
+								// this.showTextIndex = 0;
+								// this.aiText =
+								//   "好的,我已为您计时" +
+								//   this.userText.match(regExp)[1] +
+								//   "分钟。";
+								// this.userText = "";
+								// this.timer = setTimeout(() => {
+								//   this.showTextIndex = 3;
+								//   this.aiStatus = 2;
+								//   this.aiText = "";
+								//   this.userText = "";
+								// }, 3000);
+								// }, 2000);
+							} else {
+								this.chatLoading = true;
+								const _uuid = uuidv4();
+								let params = {
+									assistant_id: "f8e1ebb2-2e0d-11ef-8bf4-12e77c4cb76b",
+									userId: this.userId,
+									message: this.userText,
+									session_name: _uuid + "-qgt",
+									uid: _uuid,
+									file_ids: [],
+								};
+								this.ajax
+									// .post("https://claude3.cocorobo.cn/chat", params)
+									// .post("https://gpt4.cocorobo.cn/chat", params)
+									.post(
+										"https://gpt4.cocorobo.cn/ai_agent_park_chat_new",
+										params
+									)
+									.then((res) => {
+										if (
+											converter(res.data.FunctionResponse.result) ==
+											converter("发送成功")
+										) {
+											this.userText = "";
+										} else {
+											// this.$message.warning(res.data.FunctionResponse.result);
+											console.log(res.data.FunctionResponse.result);
+											this.chatLoading = false;
+											this.aiStatus = 0;
+											this.showTextIndex = 0;
+											this.aiText = "对不起,我无法理解您的问题,请重新提问";
+											// this.timer = setTimeout(() => {
+											//   this.showTextIndex = 3;
+											//   this.aiStatus = 2;
+											//   this.aiText = "";
+											//   this.userText = "";
+											// }, 3000);
+										}
+									})
+									.catch((e) => {
+										console.log(e);
+										this.chatLoading = false;
+										this.aiStatus = 0;
+										this.showTextIndex = 0;
+										this.aiText = "对不起,我无法理解您的问题,请重新提问";
+										// this.timer = setTimeout(() => {
+										//   this.showTextIndex = 3;
+										//   this.aiStatus = 2;
+										//   this.aiText = "";
+										//   this.userText = "";
+										// }, 3000);
+									});
+								// 通过流获取ai对话数据
+								this.getAtAuContent(_uuid);
+							}
+						}, 5000);
+					}
+				} else {
+					console.log("不响应");
+				}
+			};
+		},
+		stopRecord() {
+			// this.show = false;
+			// this.showIndex = 2;
+			// return
+			let iiframe = this.$refs["iiframe"];
+			iiframe.contentWindow.window.document
+				.getElementById("scenarioStopButton")
+				.click();
+			if (this.talkLoading) {
+				this.stopTalk();
+			}
+			// this.stopTalk();
+			// 录音借宿
+			iiframe.contentWindow.onSessionStopped = (s, e) => {
+				this.isOpen = false;
+				this.show = false;
+				this.showTextIndex = 3;
+				this.showIndex = 2;
+				this.$message.success("已关闭语音助手");
+				if (this.talkLoading) {
+					this.$refs.iiframe2.contentWindow.closesynthesizer();
+				}
+				this.userText = "";
+				this.aiText = "";
+			};
+		},
+		chineseToNumber(chinese) {
+			var OpenCC = require("opencc-js");
+			let converter = OpenCC.Converter({
+				from: "hk",
+				to: "cn",
+			});
+			chinese = converter(chinese);
+			const chineseNumbers = {
+				零: 0,
+				一: 1,
+				二: 2,
+				三: 3,
+				四: 4,
+				五: 5,
+				六: 6,
+				七: 7,
+				八: 8,
+				九: 9,
+				十: 10,
+				百: 100,
+				千: 1000,
+				万: 10000,
+				亿: 100000000,
+			};
+
+			let result = 0;
+			let tempNum = 0; // 用于累积处理
+			let sectionNum = 0; // 每个段的值
+
+			for (let i = 0; i < chinese.length; i++) {
+				const char = chinese[i];
+				const num = chineseNumbers[char];
+
+				if (num === undefined) {
+					throw new Error(`Unexpected character: ${char}`);
+				}
+
+				if (
+					num === 10 ||
+					num === 100 ||
+					num === 1000 ||
+					num === 10000 ||
+					num === 100000000
+				) {
+					if (tempNum === 0) tempNum = 1; // 如果前面没有数,默认是1
+					tempNum *= num;
+
+					if (num === 10000 || num === 100000000) {
+						sectionNum += tempNum;
+						result += sectionNum;
+						tempNum = 0;
+						sectionNum = 0;
+					}
+				} else {
+					tempNum += num;
+				}
+			}
+
+			result += sectionNum + tempNum;
+			return result;
+		},
+		removeMarkdown(text) {
+			return text
+				.replace(/[#*_~`>+\-]/g, "") // 移除 #、*、_、~、`、>、+、- 符号
+				.replace(/!\[.*?\]\(.*?\)/g, "") // 移除图片
+				.replace(/\[.*?\]\(.*?\)/g, "") // 移除链接
+				.replace(/```[\s\S]*?```/g, "") // 移除代码块(不使用 s 标志)
+				.replace(/`[^`]*`/g, "") // 移除行内代码
+				.replace(/\d+\./g, "") // 移除有序列表
+				.replace(/^\s*[-*+]\s+/gm, "") // 移除无序列表
+				.replace(/\s+/g, " ") // 将多个空白字符替换为一个空格
+				.trim(); // 去除字符串两端的空白字符
+		},
+		getAtAuContent(_uid) {
+			this.source = new EventSource(
+				`https://gpt4.cocorobo.cn/question/${_uid}`
+			);
+			//http://gpt4.cocorobo.cn:8011/question/   https://gpt4.cocorobo.cn/question/
+			let _allText = "";
+			let _mdText = "";
+			let _talkText = "";
+			// let _talkIndex = 0;
+			// const md = new MarkdownIt();
+			this.source.onmessage = (_e) => {
+				let _eData = JSON.parse(_e.data);
+				if (_eData.content.replace("'", "").replace("'", "") == "[DONE]") {
+					this.source.close();
+					this.source = null;
+					let _result = [];
+					if ("result" in _eData) {
+						_result = _eData.result;
+						for (let i = 0; i < _result.length; i++) {
+							_mdText = _mdText.replace(_result[i].text, _result[i].fileName);
+						}
+					}
+					_mdText = _mdText.replace("_", "");
+					this.aiText = _mdText;
+					this.scrollBottom();
+					if (_talkText != "") {
+						let _resultText = this.removeMarkdown(_talkText);
+						this.talkTextList.push(_resultText);
+						_talkText = "";
+						if (!this.talkLoading) this.talkText();
+					}
+					this.chatLoading = false;
+				} else {
+					// _talkIndex+=1;
+					let _text = _eData.content.replace("'", "").replace("'", "");
+					if (_allText == "") {
+						_allText = _text.replace(/^\n+/, ""); //去掉回复消息中偶尔开头就存在的连续换行符
+						_talkText += _text.replace(/^\n+/, "");
+					} else {
+						_allText += _text;
+						_talkText += _text;
+					}
+					`~`;
+					_mdText = _allText + "_";
+					_mdText = _mdText.replace(/\\n/g, "\n");
+					_mdText = _mdText.replace(/\\/g, "");
+					if (_allText.split("```").length % 2 == 0) _mdText += "\n```\n";
+					this.aiText = _mdText;
+					this.showTextIndex = 0;
+					this.scrollBottom();
+					if (/[,。:;?!)]/.test(_talkText)) {
+						let _resultText = this.removeMarkdown(_talkText);
+						this.talkTextList.push(_resultText);
+						_talkText = "";
+						if (!this.talkLoading) this.talkText();
+					}
+				}
+			};
+		},
+		talkText() {
+			let _text = this.talkTextList.shift();
+			let _talkTextIiframe2 = this.$refs.iiframe2;
+
+			if (_text) {
+				this.talkLoading = true;
+				if (this.timer) {
+					clearTimeout(this.timer);
+					this.timer = null;
+				}
+				console.log(`👉转语音:${_text}`);
+				_talkTextIiframe2.contentWindow.texttospeech(
+					_text,
+					this.talkText,
+					this.endTalk
+				);
+			} else {
+				_talkTextIiframe2.contentWindow.closesynthesizer();
+			}
+		},
+		endTalk() {
+			console.log("👉转语音结束👈");
+			this.talkLoading = false;
+		},
+		stopTalk() {
+			// return this.$message.info("停止")
+			this.talkTextList = [];
+			try {
+				let _talkTextIiframe2 = this.$refs.iiframe2;
+				_talkTextIiframe2.contentWindow.pausesynthesizer();
+				_talkTextIiframe2.contentWindow.closesynthesizer();
+				this.talkLoading = false;
+			} catch (error) {
+				this.talkLoading = false;
+			}
+		},
+		interrupt() {
+			// return this.$message.info("打断")
+			if (this.source) {
+				try {
+					this.source.close();
+				} catch (error) {
+					console.log(error);
+				}
+			}
+			this.stopTalk();
+		},
+	},
+};
+</script>
+
+<style scoped>
+.languageAssistant {
+	width: 100%;
+	height: 100%;
+	border-radius: 10px 0 0 10px;
+	/* background-image: linear-gradient(to top, #007adf 0%, #00ecbc 100%);
+	 */
+	background-image: url("../../../assets/icon/course/aibgImage.png");
+	background-repeat: no-repeat;
+	background-size: 100% 100%;
+	/* display: flex;
+  flex-direction: column;
+  align-items: center; */
+	/* justify-content: center; */
+	overflow: auto;
+	text-align: center;
+}
+
+.la_coco {
+	height: 170px;
+	width: 100%;
+	display: flex;
+	justify-content: center;
+	align-items: flex-end;
+}
+
+.la_message {
+	/* max-height: 400px; */
+	/* min-height: 400px; */
+	height: auto;
+	max-height: calc(100% - 170px - 200px - 40px);
+	width: 100%;
+	/* display: flex; */
+	padding: 10px;
+	box-sizing: border-box;
+	margin: 20px 0;
+	overflow: auto;
+}
+
+.la_m_talk {
+	/* width:100%; */
+	height: auto;
+	/* max-height: calc(100% - 170px - 200px - 40px); */
+	box-sizing: border-box;
+}
+
+.la_m_talk > div {
+	background: #bfbfbf;
+	padding: 10px;
+	box-sizing: border-box;
+	border-radius: 12px;
+	text-align: left;
+	background: #00000042;
+	color: #fff;
+}
+
+.la_btn {
+	height: 200px;
+	width: 100%;
+	display: flex;
+}
+
+.la_b_noTel {
+	width: 100%;
+	height: 100%;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+}
+
+.la_b_noTel > span > svg {
+	fill: #52c41a;
+	width: 80px;
+	height: 80px;
+	cursor: pointer;
+}
+
+.la_b_isTel {
+	width: 100%;
+	height: 100%;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+}
+
+.la_b_isTel > svg {
+	fill: #ff0e55;
+	width: 80px;
+	height: 80px;
+	cursor: pointer;
+	transform: rotate(-135deg);
+}
+
+.la_b_isTel > span > svg,
+img {
+	cursor: pointer;
+}
+
+.la_b_isTel > span {
+	width: 56px;
+	height: 56px;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	margin: 0 30px;
+}
+
+.readAloud {
+	border-radius: 100%;
+	background-color: #517291;
+	cursor: pointer;
+	box-shadow: 0px 2px 4px -1px #0000001f;
+
+	box-shadow: 0px 4px 5px 0px #00000014;
+
+	box-shadow: 0px 1px 10px 0px #0000000d;
+}
+
+.readAloud > svg {
+	width: 22px;
+	height: 22px;
+	fill: #fff;
+}
+</style>

+ 2 - 31
src/components/classRoomHelper/component/levitatedSphere.vue

@@ -14,9 +14,9 @@
         fit="fill"
       ></el-image>
       <el-image
-        style="width: 100%; height: 100%"
+        style="width: 100%; height: 100%;transform: scale(1.3,1.3);"
         v-show="aiStatus == 0"
-        :src="require('../../../assets/icon/course/aiWait.svg')"
+        :src="require('../../../assets/icon/course/aiWait2.svg')"
         fit="fill"
       ></el-image>
     </div>
@@ -405,12 +405,6 @@ export default {
             _talkText = "";
             if (!this.talkLoading) this.talkText();
           }
-          // if(_talkIndex==10){
-          // 	_talkIndex = 0;
-          // 	this.talkTextList.push(_talkText)
-          // 	_talkText = "";
-          // 	if(!this.talkLoading)this.talkText();
-          // }
         }
       };
     },
@@ -425,48 +419,25 @@ export default {
           this.timer = null;
         }
         console.log(`👉转语音:${_text}`);
-        // if(this.talkTextList.length==0){
-        // 	console.log("👉最后一个了,执行结束 👈")
-        // 	_talkTextIiframe2.contentWindow.closesynthesizer();
-        // }
-        // setTimeout(()=>{
-        // 	this.talkText();
-        // },2000)
         _talkTextIiframe2.contentWindow.texttospeech(
           _text,
           this.talkText,
           this.endTalk
         );
       } else {
-        // console.log("👉转语音结束👈");
         _talkTextIiframe2.contentWindow.closesynthesizer();
-        // this.talkLoading = false;
-        // this.timer = setTimeout(() => {
-        //   this.showTextIndex = 3;
-        //   this.aiStatus = 2;
-        //   this.aiText = "";
-        //   this.userText = "";
-        // 	this.time = null;
-        // }, 5000);
       }
     },
     endTalk() {
       console.log("👉转语音结束👈");
-      // let _talkTextIiframe2 = this.$refs.iiframe2;
-      // _talkTextIiframe2.contentWindow.closesynthesizer();
       this.talkLoading = false;
     },
     stopTalk() {
       this.talkTextList = [];
-
       let _talkTextIiframe2 = this.$refs.iiframe2;
       _talkTextIiframe2.contentWindow.closesynthesizer();
       _talkTextIiframe2.contentWindow.pausesynthesizer();
       this.talkLoading = false;
-      // this.talkLoading = false;
-      // this.talkLoading = false;
-      // let _talkTextIiframe2 = this.$refs.iiframe2;
-      // _talkTextIiframe2.contentWindow.closesynthesizer();
     }
   },
   mounted() {

+ 654 - 95
src/components/classRoomHelper/component/searchArea.vue

@@ -1,6 +1,6 @@
 <template>
   <div class="search">
-    <div class="s_top" ref="chatRef">
+    <div class="s_top" ref="chatRef" v-if="cardType == 0">
       <div class="s_t_chat" v-for="(item, index) in chatList" :key="index">
         <div
           class="s_t_c_user"
@@ -29,7 +29,8 @@
           "
         >
           <div class="s_t_c_a_left">
-            <span>Ai</span>
+            <el-avatar v-if="item.filename" :src="item.filename"></el-avatar>
+            <span v-else>Ai</span>
           </div>
           <div class="s_t_c_a_right">
             <div
@@ -55,6 +56,7 @@
                   style="width: 130px;height: 130px;object-fit: cover;"
                   :src="i.image"
                   alt=""
+									@error="setDefaultSrc"
                   @click="previewImg(i.image)"
                 />
 
@@ -97,9 +99,24 @@
                 src="../../../assets/icon/course/copyTxt.png"
                 alt=""
               />
-              <img @click.stop="aiTalkAll(item)" v-if="aiTalkUid==item.uid && aiIsTalk" style="width: 15px;margin-bottom:7px;" :src="require('../../../assets/icon/course/megaphone.svg')">
-							<img @click.stop="aiTalkAll(item)" v-else style="width: 15px;margin-bottom:7px;" :src="require('../../../assets/icon/course/megaphone3.svg')">
-							<img v-if="chatList.length-2 == index" @click.stop="refresh(item)" style="width: 15px;margin-bottom:7px;" :src="require('../../../assets/icon/course/refresh.svg')">
+              <img
+                @click.stop="aiTalkAll(item)"
+                v-if="aiTalkUid == item.uid && aiIsTalk"
+                style="width: 15px;margin-bottom:7px;"
+                :src="require('../../../assets/icon/course/megaphone.svg')"
+              />
+              <img
+                @click.stop="aiTalkAll(item)"
+                v-else
+                style="width: 15px;margin-bottom:7px;"
+                :src="require('../../../assets/icon/course/megaphone3.svg')"
+              />
+              <img
+                v-if="chatList.length - 2 == index"
+                @click.stop="refresh(item)"
+                style="width: 15px;margin-bottom:7px;"
+                :src="require('../../../assets/icon/course/refresh.svg')"
+              />
             </div>
             <!-- <div
               class="s_t_c_a_r_contentImage"
@@ -189,7 +206,7 @@
         </div>
       </div>
     </div>
-    <div class="s_bottom">
+    <div class="s_bottom" v-if="cardType == 0">
       <div class="s_b_btnAreaTop">
         <div class="s_b_bat_left">
           <el-tooltip
@@ -223,11 +240,19 @@
           </el-tooltip>
         </div>
         <div class="s_b_bat_right">
-					<!-- <img :src="require('../../../assets/icon/course/bulb.svg')"> -->
-					<img :src="require('../../../assets/icon/course/bulb2.svg')">
-				</div>
+          <!-- <img :src="require('../../../assets/icon/course/bulb.svg')"> -->
+          <img :src="require('../../../assets/icon/course/bulb2.svg')" />
+        </div>
       </div>
       <div class="s_b_btnArea">
+				<div class="s_b_ba-item" @click.stop="choiceRole()">
+          <img
+            style="width: 20px;"
+            src="../../../assets/icon/course/role.png"
+            alt=""
+          />
+          智能体
+        </div>
         <div
           :class="['s_b_ba-item', sendType == 3 ? 's_b_ba_active' : '']"
           @click="chooseType(3)"
@@ -252,13 +277,7 @@
 					<img src="../../../assets/icon/course/sRio2.png" style="margin-right: 5px;" alt="" v-else> -->
           搜索视频
         </div>
-        <!-- <div class="s_b_ba-item" @click="clear()" v-if="!openAtBox">
-          清空聊天记录
-        </div>
-
-				<div :class="['s_b_ba-item',recordType==1?'s_b_ba_active':'']" @click="$parent.startAssistant()" v-if="!openAtBox">
-          语音助手
-        </div> -->
+       
       </div>
 
       <div class="s_b_atBox" v-if="openAtBox" v-loading="loading">
@@ -579,6 +598,144 @@
           />
           <div v-else @click.stop="stopSend()">停止</div>
         </div>
+
+				<div class="s_b_btn2" @click.stop="openPhone">
+					<img
+            :src="require('../../../assets/icon/course/phone.svg')"
+          />
+				</div>
+      </div>
+    </div>
+
+    <div class="choiceTopArea" v-if="cardType == 1">
+      <div class="choiceTop">
+        <div class="choiceRoleHeader">
+					<div
+          class="s_t_c_ai"
+        >
+          <div class="s_t_c_a_left">
+            <el-avatar :src="require('../../../assets/icon/course/aiWait.svg')"></el-avatar>
+          </div>
+          <div class="s_t_c_a_right">
+            <div
+              class="s_t_c_a_r_content"
+            >选择您需要的智能体,开始对话</div>
+          </div>
+        </div>
+        </div>
+        
+        <div class="choiceSelect">
+					<div style="width:100%">
+						<div class="roleInput">						<el-input
+          placeholder="请输入内容"
+          v-model="roleText"
+          prefix-icon="el-icon-search"
+          clearable
+        >
+        </el-input></div>
+
+					<div class="roleBtn"> <el-button
+            class="option"
+            :style="{
+              background: sortOption == 0 ? '#36A9FC' : '',
+              color: sortOption == 0 ? '#fff' : ''
+            }"
+            @click="optBtn(0)"
+            plain
+            >我的</el-button
+          >
+          <el-button
+            class="option"
+            :style="{
+              background: sortOption == 1 ? '#36A9FC' : '',
+              color: sortOption == 1 ? '#fff' : ''
+            }"
+            @click="optBtn(1)"
+            plain
+            >社区</el-button
+          ></div>
+					</div>
+					<div class="roleListBox">
+						<div
+          class="characterBlock"
+          v-for="(item, index) in showRoleList"
+          :key="item.id"
+          @click.stop="choseRole(item)"
+        >
+          <div class="imgLeft">
+            <div class="img">
+              <img
+                style="width: 100%;height: 100%;"
+                :src="
+                  item.headUrl && item.headUrl != ''
+                    ? item.headUrl
+                    : require('../../../assets/icon/course/ai.png')
+                "
+              />
+            </div>
+          </div>
+          <div class="txtRight">
+						
+						<el-tooltip class="item" effect="dark" :content="item.assistantName" placement="top">
+							<div class="bir">{{ item.assistantName }}</div>
+    				</el-tooltip>
+            <div
+              :style="{
+                color: '#fff',
+                display:
+                  choseRoleItem &&
+                  choseRoleItem.assistant_id == item.assistant_id
+                    ? 'block'
+                    : 'none'
+              }"
+            >
+              已选择
+            </div>
+          </div>
+        </div>
+					</div>
+        </div>
+        <!-- <div
+          class="characterBlock"
+          v-if="sortOption == 0"
+          v-for="(item, index) in roleList"
+          :key="item.id"
+          @click.stop="choseRole(item)"
+        >
+          <div class="imgLeft">
+            <div class="img">
+              <img v-if="item.headUrl" style="width: 100%;height: 100%;" :src="item.headUrl" />
+							<img v-else style="width: 100%;height: 100%;" :src="require('../../../assets/icon/course/ai.png')">
+            </div>
+          </div>
+          <div class="txtRight">
+            <div class="bir">{{ item.assistantName }}</div>
+            <div
+              :style="{
+                color: '#fff',
+                display:
+									(choseRoleItem && choseRoleItem.assistant_id == item.assistant_id)
+                    ? 'block'
+                    : 'none'
+              }"
+            >
+              已选择
+            </div>
+          </div>
+        </div> -->
+       
+      </div>
+      <div class="choiceBottom">
+        <el-button class="cb_btn" size="mini" @click="noChangeRole()"
+          >取消</el-button
+        >
+        <el-button
+          class="cb_btn"
+          size="mini"
+          type="primary"
+          @click="changeRole()"
+          >确定</el-button
+        >
       </div>
     </div>
     <iframe
@@ -636,7 +793,7 @@ export default {
   },
   data() {
     return {
-      text: "村上春树",
+      text: "",
       ppage: 1,
       sendType: 0,
       sendFnType: 0,
@@ -699,10 +856,32 @@ export default {
       tools: JSON.parse(converter(JSON.stringify(tools))),
       aiTalkList: [],
       aiIsTalk: false,
-      aiTalkUid: ""
+      aiTalkUid: "",
+      choseRoleItem: null,
+      cardType: 0,
+      roleList: [],
+      roleList2: [],
+      sortOption: 0, //切换角色 0我的 1 社区
+      roleText: ""
     };
   },
   computed: {
+    showRoleList() {
+      let _result = [];
+
+      if (this.sortOption == 0) {
+        _result = this.roleList;
+      } else if (this.sortOption == 1) {
+        _result = this.roleList2;
+      }
+
+      if (this.roleText) {
+        _result = _result.filter(
+          i => i.assistantName.indexOf(this.roleText) != -1
+        );
+      }
+      return _result;
+    },
     openAtBox() {
       // return false;
       if (this.text.length == 0) return false;
@@ -808,6 +987,34 @@ export default {
     }
   },
   methods: {
+		insertMemorandum(_html){//保存行为操作
+			//variable
+			//btn
+			return;
+			let params = [{
+				uid:this.userid,
+				courseId:this.courseId,
+				content:_html
+			}]
+
+			this.ajax.post(this.$store.state.api+'insert_systemOperation_countdownBehavior',params).then(res=>{
+				if(res.data==1){
+					console.log('保存操作成功')
+				}else{
+					console.log('保存操作失败')
+				}
+			}).catch(e=>{
+				console.log('保存操作失败')
+				console.log(e)
+			})
+		},
+		openPhone(){
+			// this.$message.info("打开电话面板")
+			this.$parent.changeItemType(4)
+		},
+		setDefaultSrc(e){
+			e.target.src = require('../../../assets/icon/course/404.png')
+		},
     refresh(item) {
       this.send(item.content);
     },
@@ -823,16 +1030,15 @@ export default {
       }
     },
     talk() {
-      
-			let iiframe = this.$refs["iiframe"];
+      let iiframe = this.$refs["iiframe"];
       iiframe.contentWindow.window.document.getElementById(
         "languageOptions"
       ).selectedIndex = 2; //普通话
       iiframe.contentWindow.testdoContinuousPronunciationAssessment();
-			this.isTalk = true;
+      this.isTalk = true;
       iiframe.contentWindow.onRecognizedResult = e => {
         let _msg = e.privText;
-				console.log(_msg)
+        console.log(_msg);
         if (_msg) this.text += _msg;
       };
     },
@@ -935,7 +1141,34 @@ export default {
       this.$hevueImgPreview(url);
     },
     clear() {
-      this.chatList = [];
+      // this.chatList = [];
+      this.$confirm("确定清空聊天记录吗?", "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      })
+        .then(_ => {
+          this.loading = true;
+          let params = {
+            user_id: this.userid,
+            id: "602def61-005d-11ee-91d8-005056b8q12w",
+            session_name: `${this.courseId}-studyStudent-md`
+          };
+
+          this.ajax
+            .post("https://gpt4.cocorobo.cn/delete_park_session", params)
+            .then(res => {
+              this.chatList = [];
+              this.stopSend();
+              this.$message.success("清除聊天记录成功");
+              this.loading = false;
+            })
+            .catch(err => {
+              this.loading = false;
+              this.$message.error("清除聊天记录失败");
+            });
+        })
+        .catch(_ => {});
     },
     atTask(name, index, type, data) {
       let _result = name;
@@ -984,14 +1217,14 @@ export default {
         aiContent: "",
         oldContent: "",
         isShowSynchronization: false,
-        filename: "",
+        filename: this.choseRoleItem ? this.choseRoleItem.headUrl : "",
         index: this.chatList.length,
         is_mind_map: false,
         loading: true
       });
       this.scrollBottom();
-      console.log(this.sendType);
       if (this.sendType == 2 || _text.indexOf("视频") != -1) {
+				this.insertMemorandum(`<span class="btn">搜索视频</span>`)
         return this.ajax
           .post(`https://gpt4.cocorobo.cn/get_network_search`, {
             engine: "bilibili",
@@ -1019,11 +1252,14 @@ export default {
             this.chatLoading = false;
           });
       } else if (this.sendType == 3) {
+				this.insertMemorandum(`<span class="btn">生成图片</span>`)
         this.text = "";
         let params = {
-          page: this.ppage,
-          pagesize: 1,
-          query: _text
+          n: 1,
+          prompt: _text,
+          quality: "standard",
+          size: "1024x1024",
+          style: "natural"
         };
         // this.$message.info(_text);
         this.chatList.push({
@@ -1040,19 +1276,41 @@ export default {
           loading: true
         });
         this.ajax
-          .post("https://gpt.cocorobo.cn/search_image", params)
+          .post("https://gpt4.cocorobo.cn/getImage", params)
           .then(res => {
-            let data = res.data.FunctionResponse.result;
+            let data = res.data.FunctionResponse;
             // console.log('res',res.data.FunctionResponse.result);
+            let _result = [];
+            if (!data.image_url_list.length) {
+              this.chatLoading = false;
+              this.chatList.pop();
+              this.chatList.pop();
+              return this.$message.error("生成图片失败");
+            }
+            data.image_url_list.forEach(i => {
+              _result.push({
+                image: i
+              });
+            });
+
             this.chatList.find(i => i.uid == _uuid).aiContent = JSON.stringify(
-              data
+              _result
             );
             this.chatList.find(i => i.uid == _uuid).loading = false;
+            console.log(this.chatList.find(i => i.uid == _uuid).aiContent);
             this.chatLoading = false;
             this.insertChat(_uuid);
+            this.scrollBottom();
+          })
+          .catch(e => {
+            this.chatLoading = false;
+            this.chatList.pop();
+            this.chatList.pop();
+            this.$message.error("生成失败");
           });
         return;
       } else if (this.sendType == 1 || _text.indexOf("图片") != -1) {
+				this.insertMemorandum(`<span class="btn">搜索图片</span>`)
         // console.log("图片");
 
         this.text = "";
@@ -1083,6 +1341,8 @@ export default {
             this.chatList.find(i => i.uid == _uuid).aiContent = JSON.stringify(
               data
             );
+            console.log("👇");
+            console.log(this.chatList.find(i => i.uid == _uuid).aiContent);
             this.chatList.find(i => i.uid == _uuid).loading = false;
             this.chatLoading = false;
             this.insertChat(_uuid);
@@ -1097,30 +1357,6 @@ export default {
 
         return;
       }
-      //         num=0
-      //       	_msg = `
-      //         NOTICE
-      // Language: Please use the same language as the user requirement, if the user speaks Chinese, the specific text of your answer should also be in Chinese.
-      // ATTENTION: Use '##' to SPLIT SECTIONS, not '#'. Output format carefully referenced "Format example".
-      // Instruction: Based on the context, follow "Format example", write content.
-
-      // # Context
-      // ## 任务
-      // 你的任务是根据用户的请求,结合以下“课程信息”包含的子条目(“课程标题”,“主题”,“学科”以及“年级”),向用户输出相关的4张图片,将结果2*2的形式返回给用户。
-      // 课程信息
-      // 课程标题:${this.courseDetail.title}
-      // 分类:${this.courseDetail.name?this.courseDetail.name:"无"}
-      // 学生年级:${this.courseDetail.classname?this.courseDetail.classname:"无"}
-
-      // ## 规则
-      //     1. 输出内容应该与“课程信息”相关,避免提供无关的信息。
-      //     2. 当课程信息中的子条目内容为“无”时,无视这些条目进行输出即可。
-      //     3. 搜索建议的结果应该符合伦理规范。
-
-      // ## 输出格式
-      //     1. 以2*2的格式输出应包括4张相关的图片。
-      //       `
-      //       }
       let history = [];
       this.nowChatList.forEach(i => {
         if (i.content == "wanSearch") {
@@ -1156,7 +1392,9 @@ export default {
         history.push({ type: "text", text: _text });
       }
       let params = {
-        assistant_id: "f8e1ebb2-2e0d-11ef-8bf4-12e77c4cb76b",
+        assistant_id: this.choseRoleItem
+          ? this.choseRoleItem.assistant_id
+          : "f8e1ebb2-2e0d-11ef-8bf4-12e77c4cb76b",
         userId: this.userid,
         message: _text,
         session_name: `${this.courseId}-studyStudent-md`,
@@ -1186,7 +1424,6 @@ export default {
       //   model: "Claude 3 Sonnet" // Claude 3 Sonnet或者Claude 3 Haiku
       // };
       this.text = "";
-      // console.log('56465166541561616',params);
 
       this.ajax
         // .post("https://claude3.cocorobo.cn/chat", params)
@@ -1488,7 +1725,6 @@ ${_atList
           }
           _mdText = _mdText.replace("_", "");
           if (this.openMegaphone && this.aiTalkUid == _uid) {
-						this.aiTalkUid = "";
             if (_talkText != "") {
               let _resultText = this.removeMarkdown(_talkText);
               this.aiTalkList.push(_resultText);
@@ -1510,10 +1746,10 @@ ${_atList
           let _text = _eData.content.replace("'", "").replace("'", "");
           if (_allText == "") {
             _allText = _text.replace(/^\n+/, ""); //去掉回复消息中偶尔开头就存在的连续换行符
-						_talkText += _text.replace(/^\n+/, "");
+            _talkText += _text.replace(/^\n+/, "");
           } else {
             _allText += _text;
-						_talkText += _text;
+            _talkText += _text;
           }
           _mdText = _allText + "_";
           _mdText = _mdText.replace(/\\n/g, "\n");
@@ -1529,19 +1765,19 @@ ${_atList
             });
             _index = 0;
           }
-					if (this.openMegaphone && /[,。:;?!)]/.test(_talkText)) {
+          if (this.openMegaphone && /[,。:;?!)]/.test(_talkText)) {
             let _resultText = this.removeMarkdown(_talkText);
-						if(this.aiTalkUid!=_uid){
-							this.aiTalkList = [];
-						}
-						this.aiTalkList.push(_resultText);
+            if (this.aiTalkUid != _uid) {
+              this.aiTalkList = [];
+            }
+            this.aiTalkList.push(_resultText);
             _talkText = "";
-            if (this.aiTalkUid!=_uid){
-								this.aiTalkUid = _uid;
-								this.aiTalk(0)
-						}else if(!this.aiIsTalk){
-								this.aiTalk(1)
-						};
+            if (this.aiTalkUid != _uid) {
+              this.aiTalkUid = _uid;
+              this.aiTalk(0);
+            } else if (!this.aiIsTalk) {
+              this.aiTalk(1);
+            }
           }
           // 处理流数据
         }
@@ -1551,14 +1787,14 @@ ${_atList
       // this.source = new EventSource(
       //   `https://claude3.cocorobo.cn/streamChat/${_uid}`
       // );
-      this.source = new EventSource(
+      let source = new EventSource(
         `https://gpt4.cocorobo.cn/question/${_uid}`
       );
       // this.source = new EventSource(`https://gpt4.cocorobo.cn/stream/${_uid}`); //http://gpt4.cocorobo.cn:8011/stream/     https://gpt4.cocorobo.cn/stream/
       let _allText = "";
       let _mdText = "";
       this.scrollBottom();
-      this.source.onmessage = _e => {
+      source.onmessage = _e => {
         if (_e.data.replace("'", "").replace("'", "") == "[DONE]") {
           //对话已经完成
           _mdText = _mdText.replace("_", "");
@@ -1568,8 +1804,7 @@ ${_atList
           const regex = /\[\s*{[^]*}\s*\]/;
           const match = _mdText.match(regex);
           let _result = match[0];
-          this.source.close();
-          this.chatLoading = false;
+          source.close();
           this.chatList.find(i => i.uid == _uid).aiContent = JSON.parse(
             _result
           );
@@ -1675,7 +1910,6 @@ ${_atList
       this.send(text);
     },
     getWantSearch() {
-      this.chatLoading = true;
       let _uuid = uuidv4();
 
       let _msg = `
@@ -1758,12 +1992,12 @@ Instruction: Based on the context, follow "Format example", write content
         // .post("https://claude3.cocorobo.cn/chat", params)
         .post("https://gpt4.cocorobo.cn/ai_agent_park_chat", params)
         .then(res => {
-          console.log(res);
+          // console.log(res);
           let _data = res.data.FunctionResponse.message;
           _data = _data.replaceAll("```json", "").replaceAll("```", "");
           const match = _data.match(/\[\s*{[^]*}\s*\]/);
-          console.log(_data);
-          console.log(match);
+          // console.log(_data);
+          // console.log(match);
           this.chatList.find(i => i.uid == _uuid).aiContent = JSON.parse(
             match[0]
           );
@@ -1771,7 +2005,7 @@ Instruction: Based on the context, follow "Format example", write content
           this.chatList.find(i => i.uid == _uuid).isShowSynchronization = true;
           this.chatList.find(i => i.uid == _uuid).loading = false;
           this.scrollBottom();
-          this.chatLoading = false;
+          // this.chatLoading = false;
         })
         .catch(e => {
           this.chatLoading = false;
@@ -1872,10 +2106,11 @@ Instruction: Based on the context, follow "Format example", write content
         .then(res => {
           console.log(res);
           let _data = res.data.FunctionResponse.message;
-          console.log(_data);
+          
           _data = _data.replaceAll("```json", "").replaceAll("```", "");
-
-          this.chatList.find(i => i.uid == _uuid).aiContent = JSON.parse(_data);
+					const match = _data.match(/\[\s*{[^]*}\s*\]/);
+					console.log(match[0]);
+          this.chatList.find(i => i.uid == _uuid).aiContent = JSON.parse(match[0]);
           this.chatList.find(i => i.uid == _uuid).isalltext = true;
           this.chatList.find(i => i.uid == _uuid).isShowSynchronization = true;
           this.chatList.find(i => i.uid == _uuid).loading = false;
@@ -2391,12 +2626,12 @@ ${_wordData}
           _talkTextIiframe2.contentWindow.closesynthesizer();
           this.aiIsTalk = false;
           if (this.aiTalkList.length) this.aiTalk(0);
-					else this.aiTalkUid = ""
+          else this.aiTalkUid = "";
         } catch (error) {
           // console.log("error")
           this.aiIsTalk = false;
           if (this.aiTalkList.length) this.aiTalk(0);
-					else this.aiTalkUid = ""
+          else this.aiTalkUid = "";
         }
       } else {
         let _text = this.aiTalkList.shift();
@@ -2416,11 +2651,10 @@ ${_wordData}
           );
         } else {
           try {
-						_talkTextIiframe2.contentWindow.closesynthesizer();
-					} catch (error) {
-						return
-
-					}
+            _talkTextIiframe2.contentWindow.closesynthesizer();
+          } catch (error) {
+            return;
+          }
         }
       }
 
@@ -2428,8 +2662,8 @@ ${_wordData}
       // 	this.aiIsTalk = true;
       // }
     },
-		aiTalkAll(item){
-			if (this.aiTalkUid == item.uid && this.aiIsTalk) {
+    aiTalkAll(item) {
+      if (this.aiTalkUid == item.uid && this.aiIsTalk) {
         try {
           this.aiTalkList = [];
           let _talkTextIiframe2 = this.$refs.iiframe2;
@@ -2447,7 +2681,92 @@ ${_wordData}
         this.aiTalkList.push(_resultText);
         this.aiTalk(0);
       }
-		},
+    },
+    choseRole(item) {
+      this.choseRoleItem = item;
+      console.log("选择角色", this.choseRoleItem);
+      this.scrollBottom();
+    },
+    noChangeRole() {
+      this.cardType = 0;
+      this.choseRoleItem = null;
+      this.scrollBottom();
+    },
+    changeRole() {
+      this.cardType = 0;
+      if (this.choseRoleItem && this.choseRoleItem.assistant_id) {
+        // this.chatList = [];
+        this.nowChatList = [];
+        let _uuid = uuidv4();
+        this.chatList.push({
+          role: "user",
+          content: `您好,${this.choseRoleItem.assistantName}`,
+          uid: _uuid,
+          AI: "AI",
+          aiContent: this.choseRoleItem.prologue
+            ? this.choseRoleItem.prologue
+            : "您好,有什么需要我帮忙的吗?",
+          oldContent: "",
+          isShowSynchronization: false,
+          filename: this.choseRoleItem.headUrl,
+          index: this.chatList.length,
+          is_mind_map: false,
+          loading: false
+        });
+        this.scrollBottom();
+				this.insertMemorandum(`选择智能体<span class="variable">${this.choseRoleItem.assistantName}</span>`)
+      }
+    },
+    optBtn(val) {
+      this.sortOption = val;
+    },
+    getRoleList() {
+      this.roleList = [];
+      let params = {
+        userId: this.userid
+      };
+      this.ajax
+        .post("https://gpt4.cocorobo.cn/get_ai_agent_assistant_list", params)
+        .then(res => {
+          let _data = res.data.FunctionResponse.result;
+          if (_data.length == 0) return;
+          if (_data) {
+            this.roleList = JSON.parse(_data);
+          }
+        })
+        .catch(e => {
+          console.log("获取角色列表失败");
+          this.roleList = [];
+        });
+    },
+    getPublicRoleList() {
+      this.roleList2 = [];
+      let params = {
+        userId: this.userid,
+        // organizeid: this.org,
+        organizeid: "45facc0a-1211-11ec-80ad-005056b86db5"
+      };
+      this.ajax
+        .post(
+          "https://gpt4.cocorobo.cn/get_ai_agent_assistant_share_list",
+          params
+        )
+        .then(res => {
+          let _data = res.data.FunctionResponse.result;
+          if (_data.length == 0) return;
+          if (_data) {
+            this.roleList2 = JSON.parse(_data);
+          }
+        })
+        .catch(e => {
+          this.roleList2 = [];
+          console.log("获取公共角色失败", e);
+        });
+    },
+    choiceRole() {
+      if (this.loading) return this.$message.info("请稍等");
+      this.cardType = 1;
+    }
   },
   mounted() {
     this.getChatList().then(_ => {
@@ -2458,6 +2777,9 @@ ${_wordData}
     this.sendType = 0;
     this.initTaskList();
     this.getWorkData();
+    this.getPublicRoleList();
+    this.getRoleList();
+		this.insertMemorandum(`打开<span class="btn">任务</span>面板`)
   }
 };
 </script>
@@ -2686,6 +3008,12 @@ ${_wordData}
   margin-right: 5px;
 }
 
+.s_t_c_a_left > img {
+  width: 35px;
+  height: 35px;
+  border-radius: 50%;
+}
+
 .s_t_c_a_left > span {
   width: 32px;
   height: 32px;
@@ -2733,8 +3061,8 @@ ${_wordData}
   margin-right: 5px;
 }
 
-.s_b_bat_right{
-	width: auto;
+.s_b_bat_right {
+  width: auto;
   height: 100%;
   display: flex;
   align-items: flex-end;
@@ -2887,6 +3215,25 @@ ${_wordData}
   height: 30px;
 }
 
+.s_b_btn2 {
+  width: 40px;
+  height: 40px;
+  background-color: #fff;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  border-radius: 50%;
+  cursor: pointer;
+	box-sizing: 0 0 2px 2px gray;
+	margin-left:10px;
+}
+
+
+.s_b_btn2 > img {
+  width: 30px;
+  height: 30px;
+}
+
 .s_b_atBox {
   width: 95%;
   height: 450px;
@@ -3253,4 +3600,216 @@ ${_wordData}
   width: 100%;
   height: 100%;
 }
+
+.choiceTopArea {
+  width: 100%;
+  height: 100%;
+}
+
+.choiceTop {
+  width: 100%;
+  height: 95%;
+  overflow-x: hidden;
+  box-sizing: border-box;
+  padding: 10px;
+}
+
+.choiceBottom {
+  width: 100%;
+  height: 5%;
+  display: flex;
+  align-items: center;
+  justify-content: flex-end;
+}
+
+.cb_btn {
+  margin: 0 10px;
+}
+
+.choiceRoleHeader {
+  width: 100%;
+	height:100px;
+	display: flex;
+  /* margin: 10px; */
+}
+
+.choiceRoleHeader > div {
+	display: flex;
+}
+
+.choiceSelect {
+  width: 100%;
+	height:calc(100% - 100px);
+  display: flex;
+	flex-direction: column;
+  justify-content: flex-start;
+  align-items: center;
+  padding: 10px;
+	box-sizing: border-box;
+	border-radius: 10px;
+	background: #F2F2F2;
+}
+.choiceSelect > .option {
+  width: 80px;
+  height: 100%;
+  border-radius: 5px;
+  margin-right: 10px;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  cursor: pointer;
+}
+
+.roleInput{
+	width:100%;
+	height:50px;
+}
+
+.roleBtn{
+	width:100%;
+	height:50px;
+	margin: 5px 0;
+}
+
+.roleListBox{
+	width:100%;
+	height:calc(100% - 100px - 10px);
+	overflow-x: hidden;
+	display: flex;
+	flex-direction: column;
+  justify-content: flex-start;
+  align-items: center;
+  padding: 10px;
+	box-sizing: border-box;
+}
+.filterSubjects {
+  margin: 10px;
+  width: 100%;
+  height: auto;
+}
+
+.fs_box {
+  width: 100%;
+  display: flex;
+  flex-wrap: wrap;
+  margin-top: 10px;
+}
+
+.fs_b_item {
+  width: auto;
+  height: 35px;
+  font-size: 14px;
+  box-sizing: border-box;
+  padding: 0 9px;
+  background-color: #f3f7fd;
+  border: solid 1px #f3f7fd;
+  border-radius: 5px;
+  margin-right: 8px;
+  margin-bottom: 8px;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  cursor: pointer;
+}
+
+.fs_b_itemActive {
+  border: solid 1px #4d8ffc;
+  color: #4d8ffc;
+  background-color: #f3f7fd;
+}
+
+.roleList {
+  width: 100%;
+  height: auto;
+  margin: 10px;
+}
+
+.r_box {
+  width: 100%;
+  height: auto;
+  display: flex;
+  flex-wrap: wrap;
+}
+
+.r_b_item {
+  height: 40px;
+  font-size: 14px;
+  display: flex;
+  /* justify-content: center; */
+  align-items: center;
+  background-color: #f0f2f5;
+  border-radius: 5px;
+  margin: 5px;
+  cursor: pointer;
+  box-sizing: border-box;
+  padding: 0 4px;
+  border: solid 1px #f0f2f5;
+}
+
+.r_b_itemActive {
+  box-sizing: border-box;
+  border: solid 1px #aeccfe;
+  color: #4d8ffb;
+}
+
+.r_b_item > img {
+  min-width: 24px;
+  min-height: 24px;
+  width: 24px;
+  height: 24px;
+  border-radius: 50%;
+  margin-right: 10px;
+  /* margin-left: 10px; */
+}
+
+.characterBlock {
+  display: flex;
+  background: rgba(54, 169, 252, 1);
+  width: 100%;
+  height: auto;
+	padding:10px 0;
+  margin: 0 auto;
+  border-radius: 10px;
+  margin-bottom: 15px;
+  cursor: pointer;
+}
+.characterBlock > .imgLeft {
+  width: 100px;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+.characterBlock > .imgLeft > .img {
+  width: 60px;
+  height: 60px;
+  overflow: hidden;
+  border-radius: 50%;
+}
+.characterBlock > .imgLeft > .img2 {
+  width: 70px;
+  height: 70px;
+  overflow: hidden;
+  border-radius: 50%;
+}
+.characterBlock > .txtRight {
+  flex: 1;
+  display: flex;
+  justify-content: flex-start;
+  align-items: center;
+}
+.characterBlock > .txtRight > .bir {
+  width: 170px;
+  height: 35px;
+  display: flex;
+  align-items: center;
+  background-color: #fff;
+  border-radius: 10px;
+  box-sizing: border-box;
+  padding: 5px 10px;
+  box-shadow: 0px 4px 4px 0px rgba(0, 0, 0, 0.25);
+  margin-right: 10px;
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
+}
 </style>

Різницю між файлами не показано, бо вона завелика
+ 608 - 435
src/components/classRoomHelper/component/taskArea.vue


+ 241 - 103
src/components/classRoomHelper/index.vue

@@ -1,12 +1,12 @@
 <template>
   <div class="ch_box" ref="ch_box">
-    <div class="ch_content_box" v-if="type == 1">
+    <div class="ch_content_box" v-show="type == 1">
       <searchArea
         :courseDetail="courseDetail"
         ref="searchAreaRef"
         :navList="navList"
         :tcid="tcid"
-				:openMegaphone="openMegaphone"
+        :openMegaphone="openMegaphone"
         :fileId="fileId"
         :recordType="recordType"
         v-if="itemType == 1"
@@ -17,105 +17,80 @@
         :courseType="courseType"
         :taskCount="taskCount"
         :worksStudent="worksStudent"
-				:openMegaphone="openMegaphone"
+        :openMegaphone="openMegaphone"
         ref="taskAreaRef"
         :fileId="fileId"
         v-if="itemType == 2"
       />
-      <dialogArea
+      <countdown
+        ref="countdownRef"
+        :fileId="fileId"
+        :courseDetail="courseDetail"
+        v-show="itemType == 3"
+      />
+
+      <languageAssistant ref="languageAssistantRef" v-if="itemType == 4" />
+      <!-- <dialogArea
         :courseDetail="courseDetail"
 				:openMegaphone="openMegaphone"
         ref="dialogAreaRef"
         :fileId="fileId"
         v-if="itemType == 3"
-      />
+      /> -->
     </div>
     <div class="ch_nav_box">
       <div class="ch_nav_box_top">
-        <div @click="changeFold(!fold)">
-          <el-tooltip class="item" effect="dark" :content="fold?'折叠':'展开'" placement="top">
+        <div @click="changeFold(!fold)" ref="foldBtnRef">
+          <el-tooltip
+            class="item"
+            effect="dark"
+            :content="fold ? '折叠' : '展开'"
+            placement="top"
+          >
             <img
               :src="require('../../assets/icon/course/foldIcon.svg')"
               alt=""
-							:style="`${fold?'transform: rotate(90deg);':''}`"
+              :style="`${fold ? 'transform: rotate(90deg);' : ''}`"
             />
           </el-tooltip>
-          <div v-if="fold" class="itemFold">
-            <div @click="$emit('backPage')">
-              <el-tooltip
-                class="item"
-                effect="dark"
-                content="返回"
-                placement="top"
-              >
-                <img
-                  :src="require('../../assets/icon/course/return.png')"
-                  alt=""
-                />
-              </el-tooltip>
-            </div>
-
-            <div @click="$emit('refresh')">
-              <el-tooltip
-                class="item"
-                effect="dark"
-                content="刷新"
-                placement="top"
-              >
-                <img
-                  :src="require('../../assets/icon/course/refresh.png')"
-                  alt=""
-                />
-              </el-tooltip>
-            </div>
-
-            <div @click="$emit('authority')" v-if="tType == 1 || tType == 4">
-              <el-tooltip
-                class="item"
-                effect="dark"
-                content="权限"
-                placement="top"
-              >
-                <img
-                  :src="require('../../assets/icon/course/setting.png')"
-                  alt=""
-                />
-              </el-tooltip>
-            </div>
-          </div>
         </div>
 
         <div @click="$emit('review')" v-if="tType == 1">
           <el-tooltip class="item" effect="dark" content="评论" placement="top">
             <img
-              :src="require('../../assets/icon/course/comment.png')"
+              :src="require('../../assets/icon/course/comment2.svg')"
               alt=""
               style="width: 22px;height: 22px;"
             />
           </el-tooltip>
         </div>
 
-				<div @click="$emit('startRecording')" v-if="!videoStart && (tType == 1 || tType == 4)">
+        <div
+          @click="startRecording()"
+          v-if="!videoStart && (tType == 1 || tType == 4)"
+        >
           <el-tooltip class="item" effect="dark" content="录制" placement="top">
             <img
-              :src="require('../../assets/icon/course/record.svg')"
+              :src="require('../../assets/icon/course/record3.svg')"
               alt=""
               style="width: 22px;height: 22px;"
             />
           </el-tooltip>
         </div>
 
-				<div @click="$emit('stopRecording')" v-else-if="(tType == 1 || tType == 4)" style="background:#f63564">
+        <div
+          @click="$emit('stopRecording')"
+          v-else-if="tType == 1 || tType == 4"
+          style="background:#f63564"
+        >
           <el-tooltip class="item" effect="dark" content="下载" placement="top">
             <img
-              :src="require('../../assets/icon/course/record2.svg')"
+              :src="require('../../assets/icon/course/record4.svg')"
               alt=""
               style="width: 22px;height: 22px;"
             />
           </el-tooltip>
         </div>
-
-				
       </div>
       <div class="ch_nav_box_middle">
         <div
@@ -137,7 +112,7 @@
           <div>任务</div>
         </div>
 
-				<div
+        <div
           :class="[
             'ch_nav_box_middle_item',
             itemType == 1 ? 'ch_nav_box_middle_item_active' : ''
@@ -165,29 +140,55 @@
         >
           <img
             v-if="itemType == 3"
-            :src="require('../../assets/icon/course/dialog_active.png')"
+            :src="require('../../assets/icon/course/Countdown2.svg')"
           />
           <img
             v-if="itemType != 3"
-            :src="require('../../assets/icon/course/dialog.png')"
+            :src="require('../../assets/icon/course/Countdown.svg')"
           />
-          <!-- <span :style="`background:url(${itemType==3?require('../../assets/icon/course/dialog_active.png'):require('../../assets/icon/course/dialog.png')});`"></span> -->
-          <div>智能体</div>
+          <div>倒计时</div>
         </div>
       </div>
       <div class="ch_nav_box_bottom">
+        <div @click.stop="commentAndAnnotate()">
+          <el-tooltip class="item" effect="dark" content="批注" placement="top">
+            <img
+              :src="require('../../assets/icon/course/edit2.svg')"
+              v-if="!AnnotationCanvasShow"
+            />
+            <img :src="require('../../assets/icon/course/edit3.svg')" v-else />
+          </el-tooltip>
+        </div>
 
-				<div @click.stop="startAssistant()" :class="[recordType==1?'ch_nav_box_middle_item_active':'']">
+        <!-- <div @click.stop="changeItemType(4)" :class="[itemType == 4?'ch_nav_box_middle_item_active':'']">
 					<el-tooltip
             class="item"
             effect="dark"
-            :content="recordType==0?'开启语音助手':'关闭语音助手'"
+            :content="itemType != 4?'开启语音助手':'关闭语音助手'"
             placement="top"
           >
-            <img v-if="recordType!=1" :src="require('../../assets/icon/course/robot.svg')" />
+            <img v-if="itemType != 4" :src="require('../../assets/icon/course/robot.svg')" />
 						<img v-else :src="require('../../assets/icon/course/robot2.svg')" />
           </el-tooltip>
-				</div>
+				</div> -->
+
+        <div
+          @click.stop="startAssistant()"
+          :class="[recordType == 1 ? 'ch_nav_box_middle_item_active' : '']"
+        >
+          <el-tooltip
+            class="item"
+            effect="dark"
+            :content="recordType == 0 ? '开启语音助手' : '关闭语音助手'"
+            placement="top"
+          >
+            <img
+              v-if="recordType != 1"
+              :src="require('../../assets/icon/course/robot3.svg')"
+            />
+            <img v-else :src="require('../../assets/icon/course/robot3.svg')" />
+          </el-tooltip>
+        </div>
 
         <div @click.stop="$emit('goStep', 0)">
           <el-tooltip
@@ -223,25 +224,61 @@
         </div>
       </div>
     </div>
+    <div v-show="fold" class="itemFold" ref="itemFoldRef">
+      <div @click="$emit('backPage')">
+       
+          <img :src="require('../../assets/icon/course/return.png')" alt="" />
+				<span>返回</span>
+      </div>
+
+      <div @click="$emit('refresh')">
+          <img :src="require('../../assets/icon/course/refresh.png')" alt="" />
+					<span>刷新</span>
+      </div>
+
+      <div @click="$emit('authority')" v-if="tType == 1 || tType == 4">
+          <img :src="require('../../assets/icon/course/setting.png')" alt="" />
+					<span>权限</span>
+      </div>
+    </div>
     <levitatedSphere ref="levitatedSphereRef" @startTime="startTime" />
     <timepiece ref="timepieceRef" />
+    <AnnotationCanvas
+      ref="AnnotationCanvasRef"
+      @close="endCommentAndAnnotate"
+      @changeStatus="changeAnnotationCanvasShow"
+    />
   </div>
 </template>
 
 <script>
 import searchArea from "./component/searchArea.vue";
 import taskArea from "./component/taskArea.vue";
-import dialogArea from "./component/dialogArea.vue";
+// import dialogArea from "./component/dialogArea.vue";
 import levitatedSphere from "./component/levitatedSphere.vue";
 import timepiece from "./component/timepiece.vue";
+import countdown from "./component/countdown.vue";
+import AnnotationCanvas from "./component/AnnotationCanvas.vue";
+import languageAssistant from "./component/languageAssistant.vue";
 export default {
-  emits: ["refresh", "goStep", "backPage", "authority", "review","stopRecording","startRecording"],
+  emits: [
+    "refresh",
+    "goStep",
+    "backPage",
+    "authority",
+    "review",
+    "stopRecording",
+    "startRecording"
+  ],
   components: {
     searchArea,
     taskArea,
-    dialogArea,
+    // dialogArea,
     levitatedSphere,
-    timepiece
+    timepiece,
+    countdown,
+    AnnotationCanvas,
+    languageAssistant
   },
   props: {
     courseDetail: {
@@ -276,21 +313,24 @@ export default {
       type: Array,
       default: () => []
     },
-		videoStart:{
-			type:Boolean,
-			default:false,
-		},
+    videoStart: {
+      type: Boolean,
+      default: false
+    }
   },
   data() {
     return {
+      userid: this.$route.query.userid,
+      courseId: this.$route.query.courseId,
       type: 0,
       itemType: 0, //0--无  1-搜索  2-任务 3-对话
       fileId: [],
       recordType: 0,
-			recordLoading:false,
+      recordLoading: false,
       fold: false,
-			openMegaphone:false,//是否打开喇叭
-      getFileIdLoading: false
+      openMegaphone: false, //是否打开喇叭
+      getFileIdLoading: false,
+      AnnotationCanvasShow: false
     };
   },
   mounted() {
@@ -298,6 +338,42 @@ export default {
     this.getFileId();
   },
   methods: {
+    changeAnnotationCanvasShow(newValue) {
+      this.AnnotationCanvasShow = newValue;
+    },
+    startRecording() {
+      this.$emit("startRecording");
+      this.insertMemorandum(`使用<span class="btn">录制</span>功能,录制课堂`);
+    },
+    insertMemorandum(_html) {
+      //保存行为操作
+      //variable
+      //btn
+      let params = [
+        {
+          uid: this.userid,
+          courseId: this.courseId,
+          content: _html
+        }
+      ];
+
+      this.ajax
+        .post(
+          this.$store.state.api + "insert_systemOperation_countdownBehavior",
+          params
+        )
+        .then(res => {
+          if (res.data == 1) {
+            console.log("保存操作成功");
+          } else {
+            console.log("保存操作失败");
+          }
+        })
+        .catch(e => {
+          console.log("保存操作失败");
+          console.log(e);
+        });
+    },
     setWidth() {
       let w = this.$refs.ch_box;
       let w2 = w.offsetWidth + 30 + "px";
@@ -312,6 +388,7 @@ export default {
     changeItemType(type) {
       this.type = 0;
       this.openSetting();
+      // this.$message.info("切换到"+type)
       this.$nextTick(() => {
         // if (this.itemType == 1 && type != 1) {
         //   this.$refs.searchAreaRef.scrollBottom();
@@ -322,6 +399,14 @@ export default {
         //   this.$refs.dialogAreaRef.scrollBottom();
         // }
         this.itemType = type;
+        if (this.itemType == 4 && this.recordType == 1) {
+          //关闭悬浮语音助手
+          this.$refs.levitatedSphereRef.stopRecord();
+        }
+
+        if (this.itemType == 3) {
+          this.insertMemorandum(`打开<span class="btn">倒计时</span>面板`);
+        }
       });
     },
     //计时
@@ -368,34 +453,70 @@ export default {
       });
     },
     startAssistant() {
-			if(this.recordLoading)return this.$message.info("请稍等...")
-			this.recordLoading = true;
+      if (this.recordLoading) return this.$message.info("请稍等...");
+      this.recordLoading = true;
       if (this.recordType == 0) {
-			// this.$message.info("开启")
-				// this.changeRecordType(1)
+        if (this.itemType == 4) {
+          this.itemType = 0;
+          this.type = 0;
+        }
+        // this.$message.info("开启")
+        // this.changeRecordType(1)
         this.$refs.levitatedSphereRef.recordStart();
       } else if (this.recordType == 1) {
-				// this.$message.info("关闭")
-				// this.changeRecordType(0)
+        // this.$message.info("关闭")
+        // this.changeRecordType(0)
         this.$refs.levitatedSphereRef.stopRecord();
       }
     },
-		changeMegaphone(){
-			this.openMegaphone = !this.openMegaphone;
-			if(this.openMegaphone){
-				this.$message.success("已开启AI语音")
-			}else{
-				this.$message.success("已关闭AI语音")
-			}
-		},
+    changeMegaphone() {
+      this.openMegaphone = !this.openMegaphone;
+      if (this.openMegaphone) {
+        this.$message.success("已开启AI语音");
+      } else {
+        this.$message.success("已关闭AI语音");
+      }
+    },
     // 展开
     changeFold(newValue) {
       // this.$message.info("展开");
-			this.fold = newValue;
+      this.fold = newValue;
+			console.log(this.$refs.foldBtnRef)
+			let e1 = this.$refs.foldBtnRef.getBoundingClientRect();
+			let e2 = this.$refs.ch_box.getBoundingClientRect();
+
+			console.log('👇👇')
+			console.log(e1.top - e2.top)
+			this.$refs.itemFoldRef.style.top = e1.top - e2.top + "px";
+    },
+    // 收起
+    changeUnfold(newValue) {
+      // this.$message.info("收起");
+      this.fold = newValue;
+    },
+    insertMemorandum(text) {
+      this.$refs.MemorandumRef.insertMemorandum(text);
+    },
+    // 语音识别
+    startRecord() {
+      this.$refs.levitatedSphereRef.startRecord();
+    },
+    stopRecord() {
+      this.$refs.levitatedSphereRef.stopRecord();
+    },
+    // 语音合成
+    startSpeak() {
     },
     changeRecordType(type) {
-			this.recordLoading = false;
+      this.recordLoading = false;
       this.recordType = type;
+    },
+    commentAndAnnotate() {
+      this.$refs.AnnotationCanvasRef.open();
+      this.insertMemorandum(`开始使用<span class="btn">批注</span>功能`);
+    },
+    endCommentAndAnnotate() {
+      this.insertMemorandum(`结束使用<span class="btn">批注</span>功能`);
     }
   }
 };
@@ -421,8 +542,8 @@ export default {
   display: flex;
   flex-direction: column;
   align-items: center;
-  /* overflow-y: auto; */
-  overflow-x: visible; /* 确保横向溢出内容可见 */
+  overflow-y: auto !important; /* 上下溢出显示滚动条 */
+  overflow-x: hidden !important; /* 左右溢出正常溢出 */
   position: relative;
 }
 
@@ -488,6 +609,7 @@ export default {
 
 .ch_nav_box_top {
   width: 100%;
+  height: auto;
   margin-top: auto;
 }
 
@@ -504,33 +626,49 @@ export default {
 .ch_nav_box_top > div > img {
   width: 24px;
   height: 24px;
-	transition: .3s;
+  transition: 0.3s;
 }
 
 .itemFold {
   position: absolute;
-  width: 65px;
-	left:-65px;
-	top: 0;
+  width: 130px;
+  right: 65px;
+  top: 0;
   background: rgb(255, 255, 255);
   box-sizing: border-box;
   border: solid 1px #eaeaea;
-	/* border-top: solid 1px #eaeaea; */
+  /* border-top: solid 1px #eaeaea; */
   z-index: 1000; /* 确保二级菜单在主菜单上层 */
-	border-radius: 10px;
+  border-radius: 10px;
+	box-sizing: border-box;
+	padding:10px;
+	display:flex;
+	flex-direction: column;
+	justify-content: center;
+	align-items: center;
 }
 
 .itemFold > div {
   width: 100%;
-  height: 65px;
+  height: 45px;
   display: flex;
   justify-content: center;
   align-items: center;
   cursor: pointer;
+	margin: 5px 0;
+	border-radius: 10px;
+}
+
+.itemFold > div:hover{
+	background:#F3F7FD;
 }
 
 .itemFold > div > img {
   width: 24px;
   height: 24px;
 }
+
+.itemFold > div > span{
+	margin-left:10px;
+}
 </style>

+ 549 - 0
src/components/easy2/commpont/markScore.vue

@@ -0,0 +1,549 @@
+<template>
+  <div>
+    <div v-loading="loading">
+      <div class="scoreTit">
+        <div>任务得分</div>
+        <div>{{ totalScore ? totalScore : 0 }}分</div>
+      </div>
+      <div class="scoreStar">
+        <div v-for="(e, index) in scoTitList" :key="index">
+          <div class="scoreStarBack">
+            <el-tooltip
+              class="item"
+              effect="dark"
+              :content="e.value"
+              placement="top"
+            >
+              <div class="briefTit">{{ e.value }}</div>
+            </el-tooltip>
+
+            <el-rate v-model="e.cog"></el-rate>
+          </div>
+        </div>
+      </div>
+      <div style="width:100%;display:flex;justify-content: flex-end;">
+        <el-button size="mini" @click="reset">重置</el-button>
+        <el-button type="primary" size="mini" @click="submit">确认</el-button>
+        <el-button type="primary" size="mini" @click="AIsubmit"
+          >AI评分</el-button
+        >
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import { v4 as uuidv4 } from "uuid";
+
+export default {
+  name: "PblStudentTableMarkScore",
+  props: [
+    "scoTit",
+    "scoCon",
+    "task",
+    "stage",
+    "allData",
+    "loading",
+    "wIndex",
+    "toolIndex",
+    "toolDetail",
+    "refreshKey"
+  ],
+
+  data() {
+    return {
+      homeworkVal: [],
+      scoTitList: [],
+      markScoPopover: false,
+      id: this.$route.query.courseId,
+      stUid: this.scoCon.userid,
+      userid: this.$route.query.userid,
+      total: 0
+    };
+  },
+
+  computed: {
+    totalScore() {
+      let a = 0;
+      this.scoTitList.forEach(e => {
+        a += e.cog;
+      });
+      let data = 0;
+      data = (a / this.scoTit.length).toFixed(1);
+      this.$emit("updateDocSco", {
+        val: this.toolIndex,
+        val2: this.wIndex,
+        val3: data
+      });
+    
+      return data;
+    }
+  },
+
+  mounted() {
+    this.scoTitList = JSON.parse(JSON.stringify(this.scoTit));
+    this.getData();
+  },
+
+  methods: {
+    // 获取单个数据
+    getData() {
+      let params = {
+        uid: this.scoCon.userid,
+        cid: this.id
+      };
+      this.ajax
+        .get(this.$store.state.api + "selectWorksEvaScore", params)
+        .then(res => {
+          // console.log(res);
+          if (res.data[0].length > 0) {
+            let data2 = [];
+            res.data[0].forEach((val, index) => {
+              if (val.task == this.task) {
+                data2 = res.data[0][index];
+              }
+            });
+
+            let data = JSON.parse(data2.rate);
+
+            this.scoTitList.forEach((e, index) => {
+              e.cog = 0;
+              for (const key in data) {
+                if (e.value == key) {
+                  e.cog = data[key] * 1;
+                }
+              }
+            });
+
+            // console.log("this.scoTitList", this.scoTitList);
+          }
+        })
+        .catch(err => {
+          console.error(err);
+        });
+    },
+    // 重置
+    reset() {
+      console.log("this.scoTitList", this.scoTitList);
+      this.scoTitList.forEach(e => {
+        e.cog = 0;
+      });
+      // let data = this.scoTitList.map(e => {
+      //   return e.value + ":" + e.cog;
+      // });
+      // // console.log("data", data);
+      // const processedData = {};
+
+      // data.forEach(item => {
+      //   const [key, value] = item.split(":");
+      //   processedData[key] = 0;
+      // });
+      // processedData.content = "";
+      // this.scoTitList = processedData
+      // // return console.log(processedData);
+      // let params = {
+      //   cid: this.id,
+      //   s: this.stage,
+      //   t: this.task,
+      //   rate: JSON.stringify(processedData),
+      //   uid: this.stUid
+      // };
+      // // return console.log(params);
+      // this.ajax
+      //   .get(this.$store.state.api + "updateWorksEva", params)
+      //   .then(res => {
+      //     this.getData();
+      //   })
+      //   .catch(err => {
+      //     this.$message.error("重置失败");
+      //     console.error(err);
+      //   });
+    },
+    // 老师提交评分
+    submit() {
+      let data = this.scoTitList.map(e => {
+        return e.value + ":" + e.cog;
+      });
+      // console.log("data", data);
+      const processedData = {};
+
+      data.forEach(item => {
+        const [key, value] = item.split(":");
+        processedData[key] = Number(value);
+      });
+      processedData.content = "";
+      // console.log(processedData);
+      let params = {
+        cid: this.id,
+        s: this.stage,
+        t: this.task,
+        rate: JSON.stringify(processedData),
+        uid: this.stUid
+      };
+      // return console.log(params);
+      this.ajax
+        .get(this.$store.state.api + "updateWorksEva", params)
+        .then(res => {
+          this.$message({
+            message: "评价成功",
+            type: "success"
+          });
+        })
+        .catch(err => {
+          this.$message.error("评价失败");
+          console.error(err);
+        });
+    },
+
+    // ai评分
+    AIsubmit() {
+      let tit = this.scoTit;
+      let con = JSON.parse(this.scoCon.works);
+      // this.markScoPopover = true;
+      this.$emit("updateLoading", {
+        val: this.toolIndex,
+        val2: this.wIndex,
+        val3: true
+      });
+      let _text = "";
+      for (let i = 0; i < tit.length; i++) {
+        _text += `评价名称:${tit[i].value} 评价描述:${tit[i].detail} \n`;
+      }
+      // console.log(_text);
+      let msg = `NOTICE
+      Role: 你是一个专业的项目式学习导师,你要对学生的评价高度负责。你要根据“五级评价细则”给学生作品评分,并生成需要的JSON数据。
+      Language: Please use the same language as the user requirement, if the user speaks Chinese, the specific text of your answer should also be in Chinese.
+      ATTENTION: Use '##' to SPLIT SECTIONS, not '#'. Output format carefully referenced "Format example".
+      Instruction: Based on the context, follow "Format example", write content.
+
+      #Context
+      ##要求
+      根据<评价细则>和<作业内容>与<作业题目>的相关性评价作业,判断该作业属于五级中的哪个等级。
+      具体的评价标准分为5级——1级,2级,3级,4级,5级。
+      1 级,没有识别问题和需求;
+      2 级,问题或需求没有被清晰理解或准确识别;
+      3 级,问题或需求的一部分被识别;
+      4 级,问题或需求的大部分被识别;
+      5 级,问题或需求都被识别。
+      
+      ##评分资料
+      评价细则:${_text}
+      作业题目:${this.toolDetail}
+      作业内容:${con.text}
+
+      # Format example
+      [{'评价名称':'评价等级0-5(数字)'},{'评价名称':'评价等级0-5(数字)'},{'评价名称':'评价等级0-5(数字)'},{'评价名称':'评价等级0-5(数字)'}]
+      `;
+      // console.log(msg);
+      this.aiGet2(msg);
+    },
+    // ai打分
+    aiGet2(messages, callback) {
+      console.log(this.toolIndex,this.wIndex);
+      let _this = this;
+      // let parm = {
+      //   assistant_id: "6063369f-289a-11ef-8bf4-12e77c4cb76b",
+      //   message: [
+      //     {
+      //       type: "text",
+      //       text: messages.replaceAll("\n", " ").replaceAll("*", "")
+      //     }
+      //   ],
+      //   session_name: uuidv4(),
+      //   userId: this.userid,
+      //   file_ids: ""
+      // };
+      let params = {
+        // "model": "Chat",
+        model: "gpt-3.5-turbo",
+        temperature: 0,
+        max_tokens: 4096,
+        top_p: 1,
+        frequency_penalty: 0,
+        presence_penalty: 0,
+        messages: [
+          {
+            content: messages.replaceAll("\n", " ").replaceAll("*", ""),
+            role: "user"
+          }
+        ],
+        stream: false,
+        uid: this.userid,
+        mind_map_question: ""
+      };
+      this.ajax
+        .post("https://gpt4.cocorobo.cn/chat", params)
+        .then(response => {
+          let data = response.data.FunctionResponse;
+          // console.log("data", data);
+          if (data.choices && data.choices.length && data.choices[0].message) {
+            let dArray = {};
+            try {
+              dArray = JSON.parse(
+                data.choices[0].message.content
+                  .replaceAll("```json", "")
+                  .replaceAll("```", "")
+              );
+            } catch (error) {
+              console.log("error_________________" + error);
+              try {
+                let regex = new RegExp("(?<=```json)([\\s\\S]*?)(?=```)");
+                // console.log("dArray666", data.choices[0].message.content);
+
+                let match = data.choices[0].message.content.match(regex);
+                // console.log("dArray2", match);
+                dArray = JSON.parse(
+                  match[0]
+                    .replace(/\n/g, "")
+                    .replace(/\s{2,}/g, "")
+                    .replace(/\'/g, '"')
+                );
+                // dArray = data.choices[0].message.content
+              } catch (error) {
+                try {
+                  dArray = JSON.parse(
+                    data.choices[0].message.content
+                      .replaceAll("```json", "")
+                      .replaceAll("# Solution", "")
+                      .replaceAll("```", "")
+                      .replace(/\n/g, "")
+                      .replace(/\s{2,}/g, "")
+                      .replace(/\'/g, '"')
+                  );
+                } catch (error) {
+                  console.log("error_________________" + error);
+                }
+                console.log("error_________________" + error);
+              }
+            }
+            // console.log("dArray3", dArray);
+            // _this.submit2(dArray);
+            // 提交评分
+            // if (!dArray) {
+            //   _this.$emit("updateLoading", {val:_this.task,val2:_this.wIndex,val3:false});
+            // }
+            let processedData = {};
+
+            dArray.forEach(function(item) {
+              let key = Object.keys(item)[0];
+              let value = item[key];
+              processedData[key] = value;
+            });
+
+            for (const key in processedData) {
+              if (!Number.isFinite(processedData[key]*1)) {
+                processedData[key] = 0
+              }
+            }
+
+            processedData.content = "";
+
+            let params = {
+              cid: _this.id,
+              s: _this.stage,
+              t: _this.task,
+              rate: JSON.stringify(processedData),
+              uid: _this.stUid
+            };
+            // console.log(params);
+            _this.ajax
+              .get(_this.$store.state.api + "updateWorksEva", params)
+              .then(res => {
+                _this.$message({
+                  message: "评价成功",
+                  type: "success"
+                });
+                console.log(_this.wIndex, _this.task);
+                _this.$emit("updateLoading", {
+                  val: _this.toolIndex,
+                  val2: _this.wIndex,
+                  val3: false
+                });
+
+                _this.getData();
+                // _this.markScoPopover = false;
+                // _this.$emit("update:loading", false);
+              })
+              .catch(err => {
+                _this.$message.error("评价失败");
+                _this.$emit("updateLoading", {
+                  val: _this.toolIndex,
+                  val2: _this.wIndex,
+                  val3: false
+                });
+                console.error(err);
+              });
+          }
+          this.$forceUpdate();
+
+          callback ? callback() : "";
+        })
+        .catch(error => {
+          // _this.markScoPopover = false;
+          // _this.$emit("update:loading", false);
+          _this.$emit("updateLoading", {
+            val: _this.toolIndex,
+            val2: _this.wIndex,
+            val3: false
+          });
+          _this.$message.error("评价失败");
+
+          // _this.loading = false
+          console.log(error);
+        });
+    },
+    // ai循环评分
+    aiupdetaSco(messages, uid, stage, task, callback) {
+      let _this = this;
+
+      let params = {
+        // "model": "Chat",
+        model: "gpt-3.5-turbo",
+        temperature: 0,
+        max_tokens: 4096,
+        top_p: 1,
+        frequency_penalty: 0,
+        presence_penalty: 0,
+        messages: [
+          {
+            content: messages.replaceAll("\n", " ").replaceAll("*", ""),
+            role: "user"
+          }
+        ],
+        stream: false,
+        uid: this.userid,
+        mind_map_question: ""
+      };
+      return new Promise(resolve => {
+        this.ajax
+          .post("https://gpt4.cocorobo.cn/chat", params)
+          .then(response => {
+            let data = response.data.FunctionResponse;
+            // console.log(data);
+
+            if (
+              data.choices &&
+              data.choices.length &&
+              data.choices[0].message
+            ) {
+              let dArray = {};
+              try {
+                dArray = JSON.parse(
+                  data.choices[0].message.content
+                    .replaceAll("```json", "")
+                    .replaceAll("```", "")
+                );
+              } catch (error) {
+                console.log("error_________________" + error);
+                try {
+                  let regex = new RegExp("(?<=```json)([\\s\\S]*?)(?=```)");
+
+                  let match = data.choices[0].message.content.match(regex);
+                  // console.log("dArray2", match);
+                  dArray = JSON.parse(
+                    match[0]
+                      .replace(/\n/g, "")
+                      .replace(/\s{2,}/g, "")
+                      .replace(/\'/g, '"')
+                  );
+                  // dArray = data.choices[0].message.content
+                } catch (error) {
+                  try {
+                    dArray = JSON.parse(
+                      data.choices[0].message.content
+                        .replaceAll("```json", "")
+                        .replaceAll("# Solution", "")
+                        .replaceAll("```", "")
+                        .replace(/\n/g, "")
+                        .replace(/\s{2,}/g, "")
+                        .replace(/\'/g, '"')
+                    );
+                  } catch (error) {
+                    console.log("error_________________" + error);
+                  }
+                  console.log("error_________________" + error);
+                }
+              }
+              let processedData = {};
+
+              dArray.forEach(function(item) {
+                let key = Object.keys(item)[0];
+                let value = item[key];
+                processedData[key] = value;
+              });
+
+              for (const key in processedData) {
+                if (!Number.isFinite(processedData[key]*1)) {
+                  processedData[key] = 0
+                }
+              }
+
+
+
+              processedData.content = "";
+
+
+              let params = {
+                cid: _this.id,
+                s: stage,
+                t: task,
+                rate: JSON.stringify(processedData),
+                uid: uid
+              };
+              // console.log("params", params);
+              _this.ajax
+                .get(_this.$store.state.api + "updateWorksEva", params)
+                .then(res => {
+                  resolve(1);
+                  _this.$message({
+                    message: "评价成功",
+                    type: "success"
+                  });
+                })
+                .catch(err => {
+                  resolve(1);
+                  _this.$message.error("评价失败");
+                  console.error(err);
+                });
+            }
+            callback ? callback() : "";
+          })
+          .catch(error => {
+            resolve(1);
+            _this.$message.error("评价失败");
+            // _this.loading = false
+            console.log(error);
+          });
+      });
+    }
+  }
+};
+</script>
+<style scoped>
+.scoreTit {
+  font-size: 16px;
+  font-weight: 600;
+  display: flex;
+  justify-content: space-between;
+}
+.scoreStar {
+  background-color: #f3f7fd;
+  padding: 10px;
+  margin: 10px 0;
+  max-height: 100px;
+  min-height: 60px;
+  overflow: auto;
+}
+.scoreStarBack {
+  width: 100%;
+  display: flex;
+  justify-content: space-between;
+  margin-bottom: 10px;
+}
+.briefTit {
+  width: 150px;
+  text-overflow: ellipsis;
+  overflow: hidden;
+  white-space: nowrap;
+}
+</style>

+ 234 - 8
src/components/easy2/studyStudent.vue

@@ -227,7 +227,7 @@
       <div class="body_student" :style="{width: mlDialog ? 'calc(100% - '+classRoomHelperWidth+' - 20% - 40px)' : 'calc(100% - '+classRoomHelperWidth+' - 10px)', left: mlDialog ? 'calc(20% + 35px)' : '10px' }">
         <div class="new_topFixed" :style="{width: mlDialog ? 'calc(100% - '+classRoomHelperWidth+' - 20% - 40px)' : 'calc(100% - '+classRoomHelperWidth+' - 10px)', left: mlDialog ? 'calc(20% + 35px)' : '10px' }"></div>
         <div class="new_top" :style="{width: mlDialog ? 'calc(100% - '+classRoomHelperWidth+' - 20% - 40px)' : 'calc(100% - '+classRoomHelperWidth+' - 10px)', left: mlDialog ? 'calc(20% + 35px)' : '10px' }">
-          <div class="courseIndex" :style="{width: orgArray.includes(org) ? '100%' : 'calc(100% - 745px)'}">
+          <div class="courseIndex" :style="{width: (orgArray.includes(org) || oidArray.includes(oid)) ? '100%' : 'calc(100% - 745px)'}">
             <div>任务{{ taskCount + 1 }}</div>
             <el-tooltip
               effect="light"
@@ -6531,6 +6531,7 @@
                   >
                     <div
                       class="zuoyeYulan"
+                      style="display: flex;justify-content: space-between;align-items: center;"
                       v-if="
                         worksStudent.length &&
                         worksStudent[toolIndex].length > 0
@@ -6556,6 +6557,17 @@
                           展开
                         </div>
                       </div>
+                      <div v-if="courseDetail.userid == userid && chapInfoList[courseType].chapterInfo[0].taskJson[taskCount].eList && courseDetail.state == 5">
+                        <div class="ScoreBtn" v-if="!loopLoading[toolIndex].loading" @click="loopEva(worksStudent[toolIndex],chapInfoList[courseType].chapterInfo[0].taskJson[taskCount].eList,courseType,taskCount,toolIndex,tool.toolDetail,worksStudent)" >
+                          <img src="../../assets/icon/newIcons/rootImg.png" alt="">
+                          AI评分
+                        </div>
+                        <div class="ScoreBtn" v-else >
+                          <img src="../../assets/icon/newIcons/rootImg.png" alt="">
+                          正在评分
+                        </div>
+                        
+                      </div>
                       <!-- <el-button type="text" @click="jump()" v-if="tType == 2" class="buttonA">我的评价</el-button> -->
                     </div>
                     <div
@@ -6603,7 +6615,7 @@
                           <div
                             class="answerScore"
                             @click.stop="openScore(w)"
-                            v-else-if="courseDetail.userid == userid"
+                            v-else-if="courseDetail.userid == userid && courseDetail.state != 5 && !chapInfoList[courseType].chapterInfo[0].taskJson[taskCount].eList"
                             :class="{
                               rightW:
                                 w.userid == userid ||
@@ -6614,6 +6626,55 @@
                           >
                             评分
                           </div>
+
+                           
+                          <div v-else-if="courseDetail.userid == userid && courseDetail.state == 5">
+                            <el-popover
+                              placement="top"
+                              width="300"
+                              :disabled="AIloading[toolIndex][wIndex].loading"
+                              trigger="click"
+                              @show="handleShow(toolIndex,wIndex)"
+                              @hide="handleHide(toolIndex,wIndex,worksStudent)"
+                              >
+                            <markScore 
+                              :loading="AIloading[toolIndex][wIndex].loading" 
+                              :ref="`markSco${toolIndex}${wIndex}`"
+                              @updateLoading=updateLoading
+                              @updateDocSco=updateDocSco
+                              :wIndex="wIndex"
+                              :scoCon="w" 
+                              :TotalScore="AIloading[toolIndex][wIndex].sco"
+                              :toolIndex="toolIndex" 
+                              :key="refreshKey" 
+                              :refreshKey="refreshKey"
+                              :toolDetail="tool.toolDetail"
+                              :stage="courseType"
+                              :task="taskCount"  
+                              :scoTit="chapInfoList[courseType].chapterInfo[0].taskJson[taskCount].eList"
+                              >
+                            </markScore>
+                              <div
+                                class="answerScore"
+                                slot="reference"
+                                :class="{
+                                  rightW:
+                                    w.userid == userid ||
+                                    tType == 1 ||
+                                    tType == 4 ||
+                                    w.ateacher == userid,
+                                }"
+                              >
+                              <span v-if="AIloading[toolIndex][wIndex].sco && AIloading[toolIndex][wIndex].sco*1 != 0">
+                                {{ AIloading[toolIndex][wIndex].loading  ? '评分中' : AIloading[toolIndex][wIndex].sco + "分" }}
+                              </span>
+                              <span v-else>
+                                {{AIloading[toolIndex][wIndex].loading? '评分中' :'评分'}}{{w.Total}}
+                              </span>    
+                              </div>
+                            </el-popover>
+                          </div>
+
                           <img
                             class="deleteImg"
                             src="../../assets/deleteworks.png"
@@ -6624,7 +6685,6 @@
                             alt
                           />
                         </div>
-
                         <div class="comment" style="min-width: 200px">
                           <div class="worksName">
                             <div>{{ w.sName }}</div>
@@ -11944,6 +12004,7 @@ import correctText from '../components/correctText.vue'
 import scoreItem from '../scoreList/scoreItem.vue'
 import scoreZong from '../scoreZong/index.vue'
 import classRoomHelper from '../classRoomHelper/index.vue'
+import markScore from "./commpont/markScore";
 
 const getFile = (url) => {
   return new Promise((resolve, reject) => {
@@ -12019,7 +12080,8 @@ export default {
 		correctText,
 		scoreItem,
 		classRoomHelper,
-    scoreZong
+    scoreZong,
+    markScore
   },
   data() {
     return {
@@ -12385,11 +12447,134 @@ export default {
 				isScoreList:[],	
 			},
 			classRoomHelperWidth: '85px',
-			orgArray:['1973f6c7-1561-11ee-91d8-005056b86db5','777559d2-7239-11ee-b98c-005056b86db5','884c5665-a453-46f3-b7b6-01d575290aa9','0fec3a8a-ad04-11ed-b13d-005056b86db5'],
-      oidArray:['f297fbdc-f0a0-11ee-b534-005056b86db5','45facc0a-1211-11ec-80ad-005056b86db5']
+			orgArray:[],
+      oidArray:[],
+      refreshKey:0,
+      AIloading:[],
+      worksStudentCopy:[],
+      loopLoading:[],
     };
   },
   methods: {
+		getAIJ(){
+			this.ajax.get(this.$store.state.api+"getAIJ","").then(res=>{
+				let oid = res.data[0];
+				let org = res.data[1];
+				let oidArray = [];
+				let orgArray = [];
+				oid.forEach(i=>oidArray.push(i.oid))
+				org.forEach(i=>orgArray.push(i.oid))
+				this.orgArray = orgArray;
+				this.oidArray = oidArray;
+			})
+		},
+    async loopEva(con,tit,stage,task,toolIndex,toolDetail,worksStudent){
+        console.log(con,tit,stage,task,toolIndex,toolDetail);
+
+        let jude = false
+        this.AIloading.forEach((e,index)=>{
+          if(index == toolIndex){
+            e.forEach(k=>{
+              if(k.loading == true)
+                jude=true
+            })
+          }
+        })
+      if(jude) return this.$message.info('请勿同时间进行AI评分')
+
+      this.AIloading.forEach((e,index)=>{
+          if(index == toolIndex){
+            e.forEach(k=>{
+              k.loading=true
+            })
+          }
+        })
+
+      this.loopLoading[toolIndex].loading=true
+      // return console.log(this.loopLoading,this.AIloading);
+      
+      let _text = ''
+      for (let i = 0; i < tit.length; i++) {
+          _text += `评价名称:${tit[i].value} 评价描述:${tit[i].detail} \n`
+      }
+       for (let i = 0; i < con.length; i++) {
+        let msg = `NOTICE
+        Role: 你是一个专业的项目式学习导师,你要对学生的评价高度负责。你要根据“五级评价细则”给学生作品评分,并生成需要的JSON数据。
+        Language: Please use the same language as the user requirement, if the user speaks Chinese, the specific text of your answer should also be in Chinese.
+        ATTENTION: Use '##' to SPLIT SECTIONS, not '#'. Output format carefully referenced "Format example".
+        Instruction: Based on the context, follow "Format example", write content.
+
+        #Context
+        ##要求
+        根据<评价细则>和<作业内容>与<作业题目>的相关性评价作业,判断该作业属于五级中的哪个等级。
+        具体的评价标准分为5级——1级,2级,3级,4级,5级。
+        1 级,没有识别问题和需求;
+        2 级,问题或需求没有被清晰理解或准确识别;
+        3 级,问题或需求的一部分被识别;
+        4 级,问题或需求的大部分被识别;
+        5 级,问题或需求都被识别。
+
+        ##评分资料
+        评价细则:${_text}
+        作业题目:${toolDetail}
+        作业内容:${JSON.parse(con[i].works).text}
+
+        # Format example
+        [{'评价名称':'评价等级0-5(数字)'},{'评价名称':'评价等级0-5(数字)'},{'评价名称':'评价等级0-5(数字)'},{'评价名称':'评价等级0-5(数字)'}]
+        `
+        let mk = `markSco${toolIndex}${i}`
+
+        await this.$refs[mk][0].aiupdetaSco(msg,con[i].userid,stage,task)
+        // this.refreshKey++
+        this.$refs[mk][0].getData()
+
+        this.AIloading[toolIndex][i].loading=false
+      }
+      worksStudent.forEach((e,index)=>{
+          if(toolIndex != index){
+            e.forEach((i,inx)=>{
+              let mk = `markSco${index}${inx}`
+              this.$refs[mk][0].getData()
+            })
+          }
+        })
+      this.loopLoading[toolIndex].loading = false;
+
+    },
+
+    // 组件刷新
+    refreshAssembly(val){
+      this.refreshKey++
+      console.log(this.refreshKey)
+    },
+    updateLoading(payload){
+      this.AIloading[payload.val][payload.val2].loading=payload.val3
+    },
+    handleShow(toolIndex,val) {
+      let mk = `markSco${toolIndex}${val}`
+      // console.log(mk);
+      this.$refs[mk][0].getData()
+    },
+    handleHide(toolIndex,val,worksStudent) {
+      console.log(worksStudent)
+      let mk = `markSco${toolIndex}${val}`
+      this.$refs[mk][0].getData()
+
+      worksStudent.forEach((e,index)=>{
+        if(toolIndex != index){
+          e.forEach((i,inx)=>{
+            let mk = `markSco${index}${inx}`
+            this.$refs[mk][0].getData()
+          })
+        }
+      })
+
+
+    },
+    updateDocSco(payload){
+      // console.log(this.AIloading[payload.val][payload.val2].sco , payload.val3);
+      this.AIloading[payload.val][payload.val2].sco=payload.val3
+    },
     gx(){
       this.$forceUpdate();
     },
@@ -12641,6 +12826,7 @@ export default {
       }
     },
     jumpGj(i, j, k, l) {
+      this.refreshAssembly()
       for (var z = 0; z < this.navList.length; z++) {
         for (var q = 0; q < this.navList[z].task.length; q++) {
           for (var w = 0; w < this.navList[z].task[q].tool.length; w++) {
@@ -15378,6 +15564,19 @@ export default {
             this.joinGroup(gindex);
           }
           this.worksStudent = _worksStudent;
+          if( JSON.stringify(this.worksStudentCopy) != JSON.stringify(this.worksStudent)){
+            this.worksStudentCopy=this.worksStudent
+            this.AIloading=[]
+            this.loopLoading=[]
+
+            this.worksStudent.forEach((e,index)=>{
+              this.loopLoading.push({loading:false})
+              this.AIloading.push([])
+              e.forEach(k=>{
+                this.AIloading[index].push({loading:false,sco:0})
+              })
+            })
+          }
           this.selectWorksStudent();
           for (let ci = 0; ci < this.isCloseList.length; ci++) {
             this.$nextTick(()=>{
@@ -16145,6 +16344,7 @@ export default {
       this.$forceUpdate();
     },
     openTask(s, n, i) {
+      this.refreshAssembly()
       if (this.IsFollow && this.tType == 2) {
         this.$message.error("已经开启跟随模式,请认真跟堂听讲");
         return;
@@ -19944,6 +20144,7 @@ export default {
       unbind(el) {
         clearInterval(el.__vueSetInterval__);
       },
+      
     },
     autoHeight: {
       update(el, binding) {
@@ -19957,7 +20158,7 @@ export default {
       componentUpdated(el) {
         el.style.height = `${el.scrollHeight + 5}px`
       },
-    },
+    }
   },
   beforeDestroy() {
     window.onresize = null;
@@ -19967,6 +20168,12 @@ export default {
     this.opertimer = null;
   },
   computed: {
+    // getdocumentSco(){
+    //   return function (w,task,tooindex) {
+    //     console.log(w);
+    //     return task;
+    //   };
+    // },
     getHeight(){
       return document.querySelectorAll(".engUpTop")[0].offsetHeight;
     },
@@ -20125,6 +20332,7 @@ export default {
     this.selectCount();
     this.getHomeWork();
     this.selectUser();
+		this.getAIJ()
     this.contentDialog = true;
     this.setContent2(true);
     if (this.tType == 4) {
@@ -21995,7 +22203,9 @@ export default {
 .elist_input {
   /* width: 40%; */
   width: 45%;
-  margin: 20px;
+  padding: 20px; 
+  /* margin: 20px; */
+  box-sizing: border-box;
 }
 
 .elist_input .elist_input_box input {
@@ -24544,4 +24754,20 @@ ol {
   background: #409eff;
   color: #fff;
 }
+.ScoreBtn{
+  background: rgba(87, 159, 248, 1);
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  color: #fff;
+  font-size: 14px;
+  padding:8px 12px;
+  border-radius: 5px;
+  cursor: pointer;
+}
+.max-height-popover .el-popover {
+  min-height: 200px;
+  max-height: 400px; /* 设置最大高度 */
+  overflow: auto; /* 超出部分显示滚动条 */
+}
 </style>

+ 16 - 3
src/components/easy3/studyStudent.vue

@@ -227,7 +227,7 @@
       <div class="body_student" :style="{width: mlDialog ? 'calc(100% - '+classRoomHelperWidth+' - 20% - 40px)' : 'calc(100% - '+classRoomHelperWidth+' - 10px)', left: mlDialog ? 'calc(20% + 35px)' : '10px' }">
         <div class="new_topFixed" :style="{width: mlDialog ? 'calc(100% - '+classRoomHelperWidth+' - 20% - 40px)' : 'calc(100% - '+classRoomHelperWidth+' - 10px)', left: mlDialog ? 'calc(20% + 35px)' : '10px' }"></div>
         <div class="new_top" :style="{width: mlDialog ? 'calc(100% - '+classRoomHelperWidth+' - 20% - 40px)' : 'calc(100% - '+classRoomHelperWidth+' - 10px)', left: mlDialog ? 'calc(20% + 35px)' : '10px' }">
-          <div class="courseIndex" :style="{width: orgArray.includes(org) ? '100%' : 'calc(100% - 745px)'}">
+          <div class="courseIndex" :style="{width: (orgArray.includes(org) || oidArray.includes(oid)) ? '100%' : 'calc(100% - 745px)'}">
             <div>任务{{ taskCount + 1 }}</div>
             <el-tooltip
               effect="light"
@@ -12421,11 +12421,23 @@ export default {
 				isScoreList:[],	
 			},
 			classRoomHelperWidth: '85px',
-			orgArray:['1973f6c7-1561-11ee-91d8-005056b86db5','777559d2-7239-11ee-b98c-005056b86db5','884c5665-a453-46f3-b7b6-01d575290aa9','0fec3a8a-ad04-11ed-b13d-005056b86db5'],
-      oidArray:['f297fbdc-f0a0-11ee-b534-005056b86db5','45facc0a-1211-11ec-80ad-005056b86db5']
+			orgArray:[],
+      oidArray:[]
     };
   },
   methods: {
+		getAIJ(){
+			this.ajax.get(this.$store.state.api+"getAIJ","").then(res=>{
+				let oid = res.data[0];
+				let org = res.data[1];
+				let oidArray = [];
+				let orgArray = [];
+				oid.forEach(i=>oidArray.push(i.oid))
+				org.forEach(i=>orgArray.push(i.oid))
+				this.orgArray = orgArray;
+				this.oidArray = oidArray;
+			})
+		},
     gx(){
       this.$forceUpdate();
     },
@@ -20177,6 +20189,7 @@ export default {
     this.selectCount();
     this.getHomeWork();
     this.selectUser();
+		this.getAIJ();
     this.contentDialog = true;
     this.setContent2(true);
     if (this.tType == 4) {

+ 124 - 4
src/components/studyStudent.vue

@@ -228,6 +228,7 @@
                       <div v-if="t.tool == 26">课程设计</div>
                       <div v-if="t.tool == 62">交互视频</div>
                       <div v-if="t.tool == 71">AI智能体</div>
+											
                     </div>
                   </div>
                 </div>
@@ -240,7 +241,7 @@
       <div class="body_student" :style="{width: mlDialog ? 'calc(100% - '+classRoomHelperWidth+' - 20% - 40px)' : 'calc(100% - '+classRoomHelperWidth+' - 10px)', left: mlDialog ? 'calc(20% + 35px)' : '10px' }">
         <div class="new_topFixed" :style="{width: mlDialog ? 'calc(100% - '+classRoomHelperWidth+' - 20% - 40px)' : 'calc(100% - '+classRoomHelperWidth+' - 10px)', left: mlDialog ? 'calc(20% + 35px)' : '10px' }"></div>
         <div class="new_top" :style="{width: mlDialog ? 'calc(100% - '+classRoomHelperWidth+' - 20% - 40px)' : 'calc(100% - '+classRoomHelperWidth+' - 10px)', left: mlDialog ? 'calc(20% + 35px)' : '10px' }">
-          <div class="courseIndex" :style="{width: orgArray.includes(org) ? '100%' : 'calc(100% - 745px)'}">
+          <div class="courseIndex" :style="{width: (orgArray.includes(org) || oidArray.includes(oid)) ? '100%' : 'calc(100% - 745px)'}">
             <div>任务{{ taskCount + 1 }}</div>
             <el-tooltip
               effect="light"
@@ -8226,7 +8227,7 @@
 				<scoreItem v-for="item in scoreList.datalist" @refresh="getScoreList" :data="item" :isScore="scoreList.isScoreList.filter(i=>(i.userid==item.userid && i.courseid == item.courseId))" :key="item.courseId"/>
 			</div>
 			<div class="scoreList" v-if="commentTagShow==2" style="position: relative">
-        <scoreZong :courseid="id" :userid="userid"></scoreZong>
+        <scoreZong :courseid="id" :userid="userid" @insertMemorandum="insertMemorandum"></scoreZong>
 			</div>
     </div>
     <div
@@ -12358,11 +12359,84 @@ export default {
 				isScoreList:[],	
 			},
       classRoomHelperWidth: '85px',
-			orgArray:['1973f6c7-1561-11ee-91d8-005056b86db5','777559d2-7239-11ee-b98c-005056b86db5','884c5665-a453-46f3-b7b6-01d575290aa9','0fec3a8a-ad04-11ed-b13d-005056b86db5'],
-      oidArray:['f297fbdc-f0a0-11ee-b534-005056b86db5','45facc0a-1211-11ec-80ad-005056b86db5']
+			orgArray:[],
+      oidArray:[],
+			toolsList:{
+    58: "模拟驾驶",
+    59: "路径搜索",
+    60: "深度学习",
+    10: "倒计时",
+    65: "挑人",
+    7: "思维网格",
+    1: "电子白板",
+    52: "文档",
+    3: "思维导图",
+    48: "表格",
+    49: "学生分组",
+    4: "卷调查",
+    45: "选择题",
+    15: "问答",
+    16: "作业提交",
+    50: "批量上传",
+    41: "选择匹配",
+    47: "排序",
+    40: "个人评价",
+    18: "训练平台",
+    21: "AIoT Blockly",
+    23: "AI Python",
+    24: "AI Blockly",
+    32: "源码编辑",
+    57: "CocoPi",
+    63: "海龟编程",
+    28: "翻译",
+    31: "数字画板",
+    39: "GeoGebra",
+    66: "公式编辑",
+    67: "分子结构",
+    68: "时间轴",
+    69: "英语写作",
+    70: "英语口语",
+    25: "目标管理",
+    26: "课程设计",
+    62: "交互视频",
+    71: "AI智能体"
+}
     };
   },
   methods: {
+		getAIJ(){
+			this.ajax.get(this.$store.state.api+"getAIJ","").then(res=>{
+				let oid = res.data[0];
+				let org = res.data[1];
+				let oidArray = [];
+				let orgArray = [];
+				oid.forEach(i=>oidArray.push(i.oid))
+				org.forEach(i=>orgArray.push(i.oid))
+				this.orgArray = orgArray;
+				this.oidArray = oidArray;
+			})
+		},
+		insertMemorandum(_html){//保存行为操作
+			return;
+			//variable
+			//btn
+			let params = [{
+				uid:this.userid,
+				courseId:this.id,
+				content:_html
+			}]
+
+			this.ajax.post(this.$store.state.api+'insert_systemOperation_countdownBehavior',params).then(res=>{
+				if(res.data==1){
+					console.log('保存操作成功')
+				}else{
+					console.log('保存操作失败')
+				}
+			}).catch(e=>{
+				console.log('保存操作失败')
+				console.log(e)
+			})
+		},
     gx(){
       this.$forceUpdate();
     },
@@ -12633,10 +12707,21 @@ export default {
           a.scrollTop = a.scrollTop - 150;
         }, 0);
       }
+			let flag = this.courseType == i;
+			let flag2 = this.taskCount == j
       if (l) {
         this.courseType = i;
         // this.navId = l;
         this.taskCount = j;
+				if(flag){
+					if(flag2){
+						this.insertMemorandum(`选择<span class="variable">工具${w+1}:${this.toolsList[this.navList[i].task[j].tool[k].tool]}</span>`)
+					}else{
+						this.insertMemorandum(`选择<span class="variable">任务${this.taskCount+1}${this.navList[this.courseType].task[this.taskCount].taskName?':'+this.navList[this.courseType].task[this.taskCount].taskName:''}</span>→<span class="variable">工具${w+1}:${this.toolsList[this.navList[i].task[j].tool[k].tool]}</span>`)
+					}
+				}else{
+					this.insertMemorandum(`选择<span class="variable">阶段${this.courseType+1}${this.navList[this.courseType].dyName?':'+this.navList[this.courseType].dyName:''}</span>→<span class="variable">任务${this.taskCount+1}${this.navList[this.courseType].task[this.taskCount].taskName?':'+this.navList[this.courseType].task[this.taskCount].taskName:''}</span>→<span class="variable">工具${w+1}:${this.toolsList[this.navList[i].task[j].tool[k].tool]}</span>`)
+				}
         this.selectPz();
         this.getHomeWork();
         this.getCourseDetail(2);
@@ -12723,6 +12808,7 @@ export default {
       this.dialogVisibleMember = false;
     },
     previewImg(url) {
+			this.$message.info('查看作业-图片')
       this.$hevueImgPreview(url);
     },
     checkImg(list) {
@@ -14048,6 +14134,8 @@ export default {
         .catch(() => {});
     },
     async commentOther(w, toolIndex, wIndex, gindex, gid) {
+			this.$message.info("预览作业")
+			console.log(w,1)
       this.commentIndexJson = {
         toolIndex: toolIndex,
         wIndex: wIndex,
@@ -14100,6 +14188,8 @@ export default {
       }
     },
     async openScore(w, index) {
+			this.$message.info("预览作业")
+			console.log(w,2)
       this.wScore = 0;
       this.wScore = w.score ? JSON.parse(w.score).wScore : 0;
       this.scoreDetail = w.score ? JSON.parse(w.score).detail : "";
@@ -14229,6 +14319,8 @@ export default {
         });
     },
     openXz(w, i) {
+			this.$message.info("预览作业")
+			console.log(w,3)
       this.selectJson = this.chapInfoList[this.courseType].chapterInfo[0]
         .taskJson[this.taskCount].toolChoose[i].selectJson
         ? JSON.parse(
@@ -14248,11 +14340,15 @@ export default {
       this.dialogVisibleSelect = true;
     },
     openSen(w, i) {
+			this.$message.info("预览作业")
+			console.log(w,4)
       this.sentenceList1 = JSON.parse(w.works);
       this.sentenceList1.stuName = w.sName;
       this.dialogVisibleSentence1 = true;
     },
     openPj(w, toolindex) {
+			this.$message.info("预览作业")
+			console.log(w,5)
       this.isStar = true;
       this.eScore = JSON.parse(w);
       this.rateJson =
@@ -16117,7 +16213,9 @@ export default {
       this.getCourseDetail(2);
       this.$forceUpdate();
     },
+
     openTask(s, n, i,ctype) {
+			console.log(s, n, i,ctype)
       if (this.IsFollow && this.tType == 2) {
         this.$message.error("已经开启跟随模式,请认真跟堂听讲");
         return;
@@ -16163,9 +16261,19 @@ export default {
         this.navList[s].task[n].isOpen = !this.navList[s].task[n].isOpen;
         return;
       }
+			let flag = this.courseType==s;
+
+			
       this.courseType = s;
+			
       this.navId = i;
       this.taskCount = n;
+			if(flag){
+				this.insertMemorandum(`进入<span class="variable">任务${this.taskCount+1}${this.navList[this.courseType].task[this.taskCount].taskName?':'+this.navList[this.courseType].task[this.taskCount].taskName:''}</span>`)
+			}else{
+				this.insertMemorandum(`进入<span class="variable">阶段${this.courseType+1}${this.navList[this.courseType].dyName?':'+this.navList[this.courseType].dyName:''}</span>→<span class="variable">任务${this.taskCount+1}${this.navList[this.courseType].task[this.taskCount].taskName?':'+this.navList[this.courseType].task[this.taskCount].taskName:''}</span>`)
+			}
+			
       if(ctype == 2){
         this.navList[s].task[n].isOpen = true
       }else{
@@ -16859,6 +16967,7 @@ export default {
           this.$message.error("添加失败");
           console.error(err);
         });
+				this.insertMemorandum(`使用<span class="btn">评论</span>功能,添加评论`)
     },
     setReplyIndex(id, i) {
       this.replyIndex = i;
@@ -17351,6 +17460,7 @@ export default {
       // this.isClickNav = "video" + i;
       this.isClickNav = i;
       this.$forceUpdate();
+			this.insertMemorandum(`查看文件<span class="variable">任务${this.taskCount+1}:${this.vChapterData[this.taskCount].find(i=>i.url==u).name}</span>`)
     },
     lookText(i, t) {
       this.isClickNav = "";
@@ -17360,6 +17470,7 @@ export default {
       this.showType = 1;
       // this.isClickNav = "text" + t;
       this.isClickNav = t;
+			this.insertMemorandum(`查看文件<span class="variable">任务${this.taskCount+1}:${this.vChapterData[this.taskCount][t].name}.doc</span>`)
     },
     lookTools(i, t) {
       this.chapTools = this.chapToolList[i][t];
@@ -17388,10 +17499,14 @@ export default {
     openTable(f) {
       this.tableJson = JSON.parse(f.works);
       this.dialogVisibleTable2 = true;
+			this.insertMemorandum(`查看<span class="variable">${f.sName}的作业</span>`)
     },
     openWord(f) {
+			this.$message.info("预览作业")
+			console.log(f,7)
       this.tableJson = JSON.parse(f.works);
       this.dialogVisibleTable3 = true;
+	
     },
     doUrl(url, i) {
       this.isClickNav = "";
@@ -17414,6 +17529,7 @@ export default {
       this.pptImgUrl1 = f.url;
       this.isClickNav = i;
       this.$forceUpdate();
+			this.insertMemorandum(`查看文件<span class="variable">任务${this.taskCount+1}:${this.vChapterData[this.taskCount][i].name}</span>`)
     },
     async downFile(f, i) {
       this.isClickNav = "";
@@ -17448,6 +17564,7 @@ export default {
       }
       // this.isClickNav = "word" + i;
       this.isClickNav = i;
+			this.insertMemorandum(`查看文件<span class="variable">任务${this.taskCount+1}:${this.vChapterData[this.taskCount][i].name}</span>`)
     },
     downFileList(i) {
       window.open(this.noImgList[i].url);
@@ -18373,6 +18490,7 @@ export default {
           ].toolChoose[i].videoJson;
         this.dialogVisibleVideo = true;
       }
+			this.insertMemorandum(`点击工作区<span class="variable">工具${index+1}:${this.toolsList[t]}</span>`)
     },
     teacherWorkSubmit(t, i, index, s) {
       this.sStudent = s;
@@ -18916,6 +19034,7 @@ export default {
       x.send();
     },
     downloadFile(url) {
+			this.$message.info("查看作业-下载文件")
       var credentials = {
         accessKeyId: "AKIATLPEDU37QV5CHLMH",
         secretAccessKey: "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",
@@ -20096,6 +20215,7 @@ export default {
     this.selectCount();
     this.getHomeWork();
     this.selectUser();
+		this.getAIJ();
     this.contentDialog = true;
     this.setContent2(true);
     if (this.tType == 4) {

Деякі файли не було показано, через те що забагато файлів було змінено