Explorar el Código

Merge branch 'beta' into HK

lsc hace 1 año
padre
commit
a7bfc3b6b8
Se han modificado 100 ficheros con 3591 adiciones y 106 borrados
  1. 4 0
      dist/index.html
  2. 0 0
      dist/static/css/app.8ab6e42101205c72fd5a0c43a1999174.css
  3. 0 0
      dist/static/css/app.8ab6e42101205c72fd5a0c43a1999174.css.map
  4. BIN
      dist/static/img/bz_icon_data.1882026.png
  5. BIN
      dist/static/img/bz_icon_data_active.6254a5a.png
  6. BIN
      dist/static/img/data_title.04e28c7.png
  7. BIN
      dist/static/img/delete_test_icon.55a19de.png
  8. BIN
      dist/static/img/englishVoice.802b608.png
  9. BIN
      dist/static/img/hx_icon_data.be59b10.png
  10. BIN
      dist/static/img/hx_icon_data_active.3816a5e.png
  11. BIN
      dist/static/img/paste-icon.2ee0df0.png
  12. BIN
      dist/static/img/share_test_icon.a1c590b.png
  13. 1 0
      dist/static/js/app.4547dc6dbc2a01daa436.js
  14. 1 0
      dist/static/js/app.4547dc6dbc2a01daa436.js.map
  15. 1 0
      dist/static/js/app.96313b092df5a14aa3dd.js
  16. 0 0
      dist/static/js/app.96313b092df5a14aa3dd.js.map
  17. 0 0
      dist/static/js/manifest.f583576dfec9dfc9a295.js.map
  18. 0 0
      dist/static/js/vendor.920758910306febc0621.js
  19. 1 0
      dist/static/js/vendor.920758910306febc0621.js.map
  20. 0 0
      dist/static/js/vendor.a5bf03ccc49c8f7897e1.js
  21. 0 0
      dist/static/js/vendor.a5bf03ccc49c8f7897e1.js.map
  22. 339 3
      package-lock.json
  23. 3 0
      package.json
  24. 18 0
      src/App.vue
  25. 119 0
      src/assets/css/button.css
  26. BIN
      src/assets/icon/courseEvaTemplate/add.png
  27. BIN
      src/assets/icon/courseEvaTemplate/delete.png
  28. BIN
      src/assets/icon/courseEvaTemplate/deleteHover.png
  29. BIN
      src/assets/icon/courseEvaTemplate/grouping.png
  30. BIN
      src/assets/icon/courseEvaTemplate/groupingHover.png
  31. BIN
      src/assets/icon/courseEvaTemplate/one.png
  32. BIN
      src/assets/icon/courseEvaTemplate/reName.png
  33. BIN
      src/assets/icon/courseEvaTemplate/reNameHover.png
  34. BIN
      src/assets/icon/courseEvaTemplate/share.png
  35. BIN
      src/assets/icon/courseEvaTemplate/shareHover.png
  36. BIN
      src/assets/icon/courseEvaTemplate/three.png
  37. BIN
      src/assets/icon/courseEvaTemplate/two.png
  38. BIN
      src/assets/icon/dataCheck/bz_icon_data.png
  39. BIN
      src/assets/icon/dataCheck/bz_icon_data_active.png
  40. BIN
      src/assets/icon/dataCheck/djzz_icon_data.png
  41. BIN
      src/assets/icon/dataCheck/djzz_icon_data_active.png
  42. BIN
      src/assets/icon/dataCheck/hx_icon_data.png
  43. BIN
      src/assets/icon/dataCheck/hx_icon_data_active.png
  44. BIN
      src/assets/icon/dataCheck/ld_icon_data.png
  45. BIN
      src/assets/icon/dataCheck/ld_icon_data_active.png
  46. BIN
      src/assets/icon/dataCheck/rl_icon_data.png
  47. BIN
      src/assets/icon/dataCheck/rl_icon_data_active.png
  48. BIN
      src/assets/icon/dataCheck/sd_icon_data.png
  49. BIN
      src/assets/icon/dataCheck/sd_icon_data_active.png
  50. BIN
      src/assets/icon/dataCheck/yb_icon_data.png
  51. BIN
      src/assets/icon/dataCheck/yb_icon_data_active.png
  52. BIN
      src/assets/icon/dataCheck/zz_icon_data.png
  53. BIN
      src/assets/icon/dataCheck/zz_icon_data2.png
  54. BIN
      src/assets/icon/dataCheck/zz_icon_data2_active.png
  55. BIN
      src/assets/icon/dataCheck/zz_icon_data_active.png
  56. BIN
      src/assets/icon/englishVoice/icon_delete.png
  57. BIN
      src/assets/icon/englishVoice/icon_delete2.png
  58. BIN
      src/assets/icon/englishVoice/icon_picture.png
  59. BIN
      src/assets/icon/englishVoice/icon_portal.png
  60. BIN
      src/assets/icon/englishVoice/icon_voice.png
  61. BIN
      src/assets/icon/new/allScreen.png
  62. BIN
      src/assets/icon/studentEva/diary.png
  63. BIN
      src/assets/icon/studentEva/img_1.png
  64. BIN
      src/assets/icon/studentEva/img_2.png
  65. BIN
      src/assets/icon/studentEva/img_3.png
  66. BIN
      src/assets/icon/studentEva/img_4.png
  67. BIN
      src/assets/icon/studentEva/img_5.png
  68. BIN
      src/assets/icon/studentEva/isDiary.png
  69. BIN
      src/assets/icon/studentEva/isReport.png
  70. BIN
      src/assets/icon/studentEva/isScore.png
  71. BIN
      src/assets/icon/studentEva/report.png
  72. BIN
      src/assets/icon/studentEva/score.png
  73. BIN
      src/assets/icon/studentEva/star-no.png
  74. BIN
      src/assets/icon/studentEva/star.png
  75. BIN
      src/assets/icon/test/data_title.png
  76. BIN
      src/assets/icon/test/data_title_icon.png
  77. BIN
      src/assets/icon/test/delete_test_icon.png
  78. BIN
      src/assets/icon/test/icon_share.png
  79. BIN
      src/assets/icon/test/paste-icon.png
  80. BIN
      src/assets/icon/test/share_test_icon.png
  81. BIN
      src/assets/icon/test/test_list.png
  82. BIN
      src/assets/icon/test/test_list_active.png
  83. BIN
      src/assets/icon/test/test_search.png
  84. BIN
      src/assets/icon/test/test_table.png
  85. BIN
      src/assets/icon/test/test_table_active.png
  86. BIN
      src/assets/icon/test/type_checkO_icon.png
  87. 1 1
      src/common/axios.config.js
  88. 1 0
      src/common/tools.js
  89. 49 30
      src/components/pages/EnglishVoice/component/check.vue
  90. 292 0
      src/components/pages/EnglishVoice/component/component/createRole.vue
  91. 207 0
      src/components/pages/EnglishVoice/component/component/gptImg.vue
  92. 149 0
      src/components/pages/EnglishVoice/component/component/minxins/minxin.js
  93. 275 0
      src/components/pages/EnglishVoice/component/component/qa2.vue
  94. 275 0
      src/components/pages/EnglishVoice/component/component/sentence.vue
  95. 528 0
      src/components/pages/EnglishVoice/component/component/testRole.vue
  96. 298 0
      src/components/pages/EnglishVoice/component/component/theme.vue
  97. 274 0
      src/components/pages/EnglishVoice/component/component/word.vue
  98. 308 12
      src/components/pages/EnglishVoice/component/order.vue
  99. 149 38
      src/components/pages/EnglishVoice/index.vue
  100. 298 22
      src/components/pages/addCourse.vue

+ 4 - 0
dist/index.html

@@ -25,7 +25,11 @@
       height: 100%;
       width: 100%;
       background: #e6eaf0;
+<<<<<<< HEAD
     }</style><link href=./static/css/app.66e5b46fad8cea2ed30763f03f5e12a2.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=./static/js/manifest.f583576dfec9dfc9a295.js></script><script type=text/javascript src=./static/js/vendor.a5bf03ccc49c8f7897e1.js></script><script type=text/javascript src=./static/js/app.96313b092df5a14aa3dd.js></script></body></html><script>function stopSafari() {
+=======
+    }</style><link href=./static/css/app.8ab6e42101205c72fd5a0c43a1999174.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=./static/js/manifest.3512a67a6213c2df4180.js></script><script type=text/javascript src=./static/js/vendor.920758910306febc0621.js></script><script type=text/javascript src=./static/js/app.4547dc6dbc2a01daa436.js></script></body></html><script>function stopSafari() {
+>>>>>>> beta
     //阻止safari浏览器双击放大功能
     let lastTouchEnd = 0  //更新手指弹起的时间
     document.documentElement.addEventListener("touchstart", function (event) {

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
dist/static/css/app.8ab6e42101205c72fd5a0c43a1999174.css


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
dist/static/css/app.8ab6e42101205c72fd5a0c43a1999174.css.map


BIN
dist/static/img/bz_icon_data.1882026.png


BIN
dist/static/img/bz_icon_data_active.6254a5a.png


BIN
dist/static/img/data_title.04e28c7.png


BIN
dist/static/img/delete_test_icon.55a19de.png


BIN
dist/static/img/englishVoice.802b608.png


BIN
dist/static/img/hx_icon_data.be59b10.png


BIN
dist/static/img/hx_icon_data_active.3816a5e.png


BIN
dist/static/img/paste-icon.2ee0df0.png


BIN
dist/static/img/share_test_icon.a1c590b.png


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1 - 0
dist/static/js/app.4547dc6dbc2a01daa436.js


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1 - 0
dist/static/js/app.4547dc6dbc2a01daa436.js.map


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1 - 0
dist/static/js/app.96313b092df5a14aa3dd.js


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
dist/static/js/app.96313b092df5a14aa3dd.js.map


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
dist/static/js/manifest.f583576dfec9dfc9a295.js.map


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
dist/static/js/vendor.920758910306febc0621.js


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1 - 0
dist/static/js/vendor.920758910306febc0621.js.map


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
dist/static/js/vendor.a5bf03ccc49c8f7897e1.js


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
dist/static/js/vendor.a5bf03ccc49c8f7897e1.js.map


+ 339 - 3
package-lock.json

@@ -2732,6 +2732,11 @@
         }
       }
     },
+    "css-element-queries": {
+      "version": "1.2.3",
+      "resolved": "https://registry.npmmirror.com/css-element-queries/-/css-element-queries-1.2.3.tgz",
+      "integrity": "sha512-QK9uovYmKTsV2GXWQiMOByVNrLn2qz6m3P7vWpOR4IdD6I3iXoDw5qtgJEN3Xq7gIbdHVKvzHjdAtcl+4Arc4Q=="
+    },
     "css-line-break": {
       "version": "2.1.0",
       "resolved": "https://registry.npmmirror.com/css-line-break/-/css-line-break-2.1.0.tgz",
@@ -3640,6 +3645,278 @@
         "type": "^1.0.1"
       }
     },
+    "d3": {
+      "version": "4.13.0",
+      "resolved": "https://registry.npmmirror.com/d3/-/d3-4.13.0.tgz",
+      "integrity": "sha512-l8c4+0SldjVKLaE2WG++EQlqD7mh/dmQjvi2L2lKPadAVC+TbJC4ci7Uk9bRi+To0+ansgsS0iWfPjD7DBy+FQ==",
+      "requires": {
+        "d3-array": "1.2.1",
+        "d3-axis": "1.0.8",
+        "d3-brush": "1.0.4",
+        "d3-chord": "1.0.4",
+        "d3-collection": "1.0.4",
+        "d3-color": "1.0.3",
+        "d3-dispatch": "1.0.3",
+        "d3-drag": "1.2.1",
+        "d3-dsv": "1.0.8",
+        "d3-ease": "1.0.3",
+        "d3-force": "1.1.0",
+        "d3-format": "1.2.2",
+        "d3-geo": "1.9.1",
+        "d3-hierarchy": "1.1.5",
+        "d3-interpolate": "1.1.6",
+        "d3-path": "1.0.5",
+        "d3-polygon": "1.0.3",
+        "d3-quadtree": "1.0.3",
+        "d3-queue": "3.0.7",
+        "d3-random": "1.1.0",
+        "d3-request": "1.0.6",
+        "d3-scale": "1.0.7",
+        "d3-selection": "1.3.0",
+        "d3-shape": "1.2.0",
+        "d3-time": "1.0.8",
+        "d3-time-format": "2.1.1",
+        "d3-timer": "1.0.7",
+        "d3-transition": "1.1.1",
+        "d3-voronoi": "1.1.2",
+        "d3-zoom": "1.7.1"
+      }
+    },
+    "d3-array": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmmirror.com/d3-array/-/d3-array-1.2.1.tgz",
+      "integrity": "sha512-CyINJQ0SOUHojDdFDH4JEM0552vCR1utGyLHegJHyYH0JyCpSeTPxi4OBqHMA2jJZq4NH782LtaJWBImqI/HBw=="
+    },
+    "d3-axis": {
+      "version": "1.0.8",
+      "resolved": "https://registry.npmmirror.com/d3-axis/-/d3-axis-1.0.8.tgz",
+      "integrity": "sha512-K0djTb26iQ6AsuD2d6Ka08wBHf4V30awIxV4XFuB/iLzYtTqqJlE/nIN0DBJJCX7lbOqbt2/oeX3r+sU5k2veg=="
+    },
+    "d3-brush": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmmirror.com/d3-brush/-/d3-brush-1.0.4.tgz",
+      "integrity": "sha512-nUFueDzOlvwFvuOBynGSyJM7Wt1H9fKgJeoWFSg3ScS4c7FJBch92FKUJKum4xtgPYHdgH2C3bRg3GzSVltCJQ==",
+      "requires": {
+        "d3-dispatch": "1",
+        "d3-drag": "1",
+        "d3-interpolate": "1",
+        "d3-selection": "1",
+        "d3-transition": "1"
+      }
+    },
+    "d3-chord": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmmirror.com/d3-chord/-/d3-chord-1.0.4.tgz",
+      "integrity": "sha512-o0ExexkK1N0KikUakKrQwttP5Flu8AYD6iBUh3AdPJqnTh6xlvcX5wFRuuo29sLOAr9+T4yZPUH1S3CCQJ1SlQ==",
+      "requires": {
+        "d3-array": "1",
+        "d3-path": "1"
+      }
+    },
+    "d3-cloud": {
+      "version": "1.2.7",
+      "resolved": "https://registry.npmmirror.com/d3-cloud/-/d3-cloud-1.2.7.tgz",
+      "integrity": "sha512-8TrgcgwRIpoZYQp7s3fGB7tATWfhckRb8KcVd1bOgqkNdkJRDGWfdSf4HkHHzZxSczwQJdSxvfPudwir5IAJ3w==",
+      "requires": {
+        "d3-dispatch": "^1.0.3"
+      }
+    },
+    "d3-collection": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmmirror.com/d3-collection/-/d3-collection-1.0.4.tgz",
+      "integrity": "sha512-+TPxaBFzbzfpLF3Hjz8JPeuStNmJnyWAufu8VUfpDCDn5RieIgY+OQDjhKMDorf2naLgAjjZXLUQN7XFp/kgog=="
+    },
+    "d3-color": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmmirror.com/d3-color/-/d3-color-1.0.3.tgz",
+      "integrity": "sha512-t+rSOrshj6m2AUOe8kHvTwfUQ5TFoInEkBfmsHHAHPof58dmbRXNpicB7XAyPbMQbcC7i09p2BxeCEdgBd8xmw=="
+    },
+    "d3-dispatch": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmmirror.com/d3-dispatch/-/d3-dispatch-1.0.3.tgz",
+      "integrity": "sha512-Qh2DR3neW3lq/ug4oymXHYoIsA91nYt47ERb+fPKjRg6zLij06aP7KqHHl2NyziK9ASxrR3GLkHCtZvXe/jMVg=="
+    },
+    "d3-drag": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmmirror.com/d3-drag/-/d3-drag-1.2.1.tgz",
+      "integrity": "sha512-Cg8/K2rTtzxzrb0fmnYOUeZHvwa4PHzwXOLZZPwtEs2SKLLKLXeYwZKBB+DlOxUvFmarOnmt//cU4+3US2lyyQ==",
+      "requires": {
+        "d3-dispatch": "1",
+        "d3-selection": "1"
+      }
+    },
+    "d3-dsv": {
+      "version": "1.0.8",
+      "resolved": "https://registry.npmmirror.com/d3-dsv/-/d3-dsv-1.0.8.tgz",
+      "integrity": "sha512-IVCJpQ+YGe3qu6odkPQI0KPqfxkhbP/oM1XhhE/DFiYmcXKfCRub4KXyiuehV1d4drjWVXHUWx4gHqhdZb6n/A==",
+      "requires": {
+        "commander": "2",
+        "iconv-lite": "0.4",
+        "rw": "1"
+      }
+    },
+    "d3-ease": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmmirror.com/d3-ease/-/d3-ease-1.0.3.tgz",
+      "integrity": "sha512-io3QwOJwVPAxRF2UXpKpCdz2wm/7VLFCQQ1yy+GzX6YCtt3vi2BGnimI8agSF5jyUrHsADyF303d2S+ps7zU8w=="
+    },
+    "d3-force": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmmirror.com/d3-force/-/d3-force-1.1.0.tgz",
+      "integrity": "sha512-2HVQz3/VCQs0QeRNZTYb7GxoUCeb6bOzMp/cGcLa87awY9ZsPvXOGeZm0iaGBjXic6I1ysKwMn+g+5jSAdzwcg==",
+      "requires": {
+        "d3-collection": "1",
+        "d3-dispatch": "1",
+        "d3-quadtree": "1",
+        "d3-timer": "1"
+      }
+    },
+    "d3-format": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmmirror.com/d3-format/-/d3-format-1.2.2.tgz",
+      "integrity": "sha512-zH9CfF/3C8zUI47nsiKfD0+AGDEuM8LwBIP7pBVpyR4l/sKkZqITmMtxRp04rwBrlshIZ17XeFAaovN3++wzkw=="
+    },
+    "d3-geo": {
+      "version": "1.9.1",
+      "resolved": "https://registry.npmmirror.com/d3-geo/-/d3-geo-1.9.1.tgz",
+      "integrity": "sha512-l9wL/cEQkyZQYXw3xbmLsH3eQ5ij+icNfo4r0GrLa5rOCZR/e/3am45IQ0FvQ5uMsv+77zBRunLc9ufTWSQYFA==",
+      "requires": {
+        "d3-array": "1"
+      }
+    },
+    "d3-hierarchy": {
+      "version": "1.1.5",
+      "resolved": "https://registry.npmmirror.com/d3-hierarchy/-/d3-hierarchy-1.1.5.tgz",
+      "integrity": "sha512-PcsLIhThc60mWnxlojIOH7Sc0tQ2DgLWfEwEAyzCtej5f3H9wSsRmrg5pEhKZLrwiJnI2zyw/pznJxL9a/Eugw=="
+    },
+    "d3-interpolate": {
+      "version": "1.1.6",
+      "resolved": "https://registry.npmmirror.com/d3-interpolate/-/d3-interpolate-1.1.6.tgz",
+      "integrity": "sha512-mOnv5a+pZzkNIHtw/V6I+w9Lqm9L5bG3OTXPM5A+QO0yyVMQ4W1uZhR+VOJmazaOZXri2ppbiZ5BUNWT0pFM9A==",
+      "requires": {
+        "d3-color": "1"
+      }
+    },
+    "d3-path": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmmirror.com/d3-path/-/d3-path-1.0.5.tgz",
+      "integrity": "sha512-eD76prgnTKYkLzHlY2UMyOEZXTpC+WOanCr1BLxo38w4fPPPq/LgCFqRQvqFU3AJngfZmmKR7rgKPZ4EGJ9Atw=="
+    },
+    "d3-polygon": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmmirror.com/d3-polygon/-/d3-polygon-1.0.3.tgz",
+      "integrity": "sha512-2zP7GOvf4XOWTeQouK7fCO534yQxyhYYTw6GTqcXifIalHgA6qV/es+4GRQii9m6XxEPFcht4loobD/o2iEo1A=="
+    },
+    "d3-quadtree": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmmirror.com/d3-quadtree/-/d3-quadtree-1.0.3.tgz",
+      "integrity": "sha512-U2Jc3jF3JOBGXIOnvWY9C4ekRwRX9hEVpMMmeduJyaxAwPmoe7t84iZFTLn1RwYOyrXxJF55H/Hrg186TFQQdw=="
+    },
+    "d3-queue": {
+      "version": "3.0.7",
+      "resolved": "https://registry.npmmirror.com/d3-queue/-/d3-queue-3.0.7.tgz",
+      "integrity": "sha512-2rs+6pNFKkrJhqe1rg5znw7dKJ7KZr62j9aLZfhondkrnz6U7VRmJj1UGcbD8MRc46c7H8m4SWhab8EalBQrkw=="
+    },
+    "d3-random": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmmirror.com/d3-random/-/d3-random-1.1.0.tgz",
+      "integrity": "sha512-XuMbjx3Jq4EWfJP4g6nR7zns/bZfaVbWHWfR8auDkEiWCzVbWifmasfszV1ZRN3xXK3nY4RUFL2nTIhceGZSFQ=="
+    },
+    "d3-request": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmmirror.com/d3-request/-/d3-request-1.0.6.tgz",
+      "integrity": "sha512-FJj8ySY6GYuAJHZMaCQ83xEYE4KbkPkmxZ3Hu6zA1xxG2GD+z6P+Lyp+zjdsHf0xEbp2xcluDI50rCS855EQ6w==",
+      "requires": {
+        "d3-collection": "1",
+        "d3-dispatch": "1",
+        "d3-dsv": "1",
+        "xmlhttprequest": "1"
+      }
+    },
+    "d3-scale": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmmirror.com/d3-scale/-/d3-scale-1.0.7.tgz",
+      "integrity": "sha512-KvU92czp2/qse5tUfGms6Kjig0AhHOwkzXG0+PqIJB3ke0WUv088AHMZI0OssO9NCkXt4RP8yju9rpH8aGB7Lw==",
+      "requires": {
+        "d3-array": "^1.2.0",
+        "d3-collection": "1",
+        "d3-color": "1",
+        "d3-format": "1",
+        "d3-interpolate": "1",
+        "d3-time": "1",
+        "d3-time-format": "2"
+      }
+    },
+    "d3-scale-chromatic": {
+      "version": "1.5.0",
+      "resolved": "https://registry.npmmirror.com/d3-scale-chromatic/-/d3-scale-chromatic-1.5.0.tgz",
+      "integrity": "sha512-ACcL46DYImpRFMBcpk9HhtIyC7bTBR4fNOPxwVSl0LfulDAwyiHyPOTqcDG1+t5d4P9W7t/2NAuWu59aKko/cg==",
+      "requires": {
+        "d3-color": "1",
+        "d3-interpolate": "1"
+      }
+    },
+    "d3-selection": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmmirror.com/d3-selection/-/d3-selection-1.3.0.tgz",
+      "integrity": "sha512-qgpUOg9tl5CirdqESUAu0t9MU/t3O9klYfGfyKsXEmhyxyzLpzpeh08gaxBUTQw1uXIOkr/30Ut2YRjSSxlmHA=="
+    },
+    "d3-shape": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmmirror.com/d3-shape/-/d3-shape-1.2.0.tgz",
+      "integrity": "sha512-LP48zJ9ykPKjCdd0vSu5k2l4s8v1vI6vvdDeJtmgtTa+L6Ery0lzvOaV7pMunFuLv11hwSRZQnSnlhFl801aiw==",
+      "requires": {
+        "d3-path": "1"
+      }
+    },
+    "d3-time": {
+      "version": "1.0.8",
+      "resolved": "https://registry.npmmirror.com/d3-time/-/d3-time-1.0.8.tgz",
+      "integrity": "sha512-YRZkNhphZh3KcnBfitvF3c6E0JOFGikHZ4YqD+Lzv83ZHn1/u6yGenRU1m+KAk9J1GnZMnKcrtfvSktlA1DXNQ=="
+    },
+    "d3-time-format": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmmirror.com/d3-time-format/-/d3-time-format-2.1.1.tgz",
+      "integrity": "sha512-8kAkymq2WMfzW7e+s/IUNAtN/y3gZXGRrdGfo6R8NKPAA85UBTxZg5E61bR6nLwjPjj4d3zywSQe1CkYLPFyrw==",
+      "requires": {
+        "d3-time": "1"
+      }
+    },
+    "d3-timer": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmmirror.com/d3-timer/-/d3-timer-1.0.7.tgz",
+      "integrity": "sha512-vMZXR88XujmG/L5oB96NNKH5lCWwiLM/S2HyyAQLcjWJCloK5shxta4CwOFYLZoY3AWX73v8Lgv4cCAdWtRmOA=="
+    },
+    "d3-transition": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmmirror.com/d3-transition/-/d3-transition-1.1.1.tgz",
+      "integrity": "sha512-xeg8oggyQ+y5eb4J13iDgKIjUcEfIOZs2BqV/eEmXm2twx80wTzJ4tB4vaZ5BKfz7XsI/DFmQL5me6O27/5ykQ==",
+      "requires": {
+        "d3-color": "1",
+        "d3-dispatch": "1",
+        "d3-ease": "1",
+        "d3-interpolate": "1",
+        "d3-selection": "^1.1.0",
+        "d3-timer": "1"
+      }
+    },
+    "d3-voronoi": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmmirror.com/d3-voronoi/-/d3-voronoi-1.1.2.tgz",
+      "integrity": "sha512-RhGS1u2vavcO7ay7ZNAPo4xeDh/VYeGof3x5ZLJBQgYhLegxr3s5IykvWmJ94FTU6mcbtp4sloqZ54mP6R4Utw=="
+    },
+    "d3-zoom": {
+      "version": "1.7.1",
+      "resolved": "https://registry.npmmirror.com/d3-zoom/-/d3-zoom-1.7.1.tgz",
+      "integrity": "sha512-sZHQ55DGq5BZBFGnRshUT8tm2sfhPHFnOlmPbbwTkAoPeVdRTkB4Xsf9GCY0TSHrTD8PeJPZGmP/TpGicwJDJQ==",
+      "requires": {
+        "d3-dispatch": "1",
+        "d3-drag": "1",
+        "d3-interpolate": "1",
+        "d3-selection": "1",
+        "d3-transition": "1"
+      }
+    },
     "dashdash": {
       "version": "1.14.1",
       "resolved": "https://registry.npmmirror.com/dashdash/-/dashdash-1.14.1.tgz",
@@ -5361,6 +5638,11 @@
       "integrity": "sha1-dTm9S8Hg4KiVgVouAmJCCxKFhIg=",
       "dev": true
     },
+    "howler": {
+      "version": "2.2.4",
+      "resolved": "https://registry.npmmirror.com/howler/-/howler-2.2.4.tgz",
+      "integrity": "sha512-iARIBPgcQrwtEr+tALF+rapJ8qSc+Set2GJQl7xT1MQzWaVkFebdJhR3alVlSiUf5U7nAANKuj3aWpwerocD5w=="
+    },
     "hpack.js": {
       "version": "2.1.6",
       "resolved": "https://registry.npm.taobao.org/hpack.js/download/hpack.js-2.1.6.tgz",
@@ -5651,7 +5933,6 @@
       "version": "0.4.24",
       "resolved": "https://registry.npm.taobao.org/iconv-lite/download/iconv-lite-0.4.24.tgz?cache=0&sync_timestamp=1594184264130&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ficonv-lite%2Fdownload%2Ficonv-lite-0.4.24.tgz",
       "integrity": "sha1-ICK0sl+93CHS9SSXSkdKr+czkIs=",
-      "dev": true,
       "requires": {
         "safer-buffer": ">= 2.1.2 < 3"
       }
@@ -5791,6 +6072,11 @@
       "integrity": "sha1-Zlq4vE2iendKQFhOgS4+D6RbGh4=",
       "dev": true
     },
+    "intersection-observer": {
+      "version": "0.5.1",
+      "resolved": "https://registry.npmmirror.com/intersection-observer/-/intersection-observer-0.5.1.tgz",
+      "integrity": "sha512-Zd7Plneq82kiXFixs7bX62YnuZ0BMRci9br7io88LwDyF3V43cQMI+G5IiTlTNTt+LsDUppl19J/M2Fp9UkH6g=="
+    },
     "invariant": {
       "version": "2.2.4",
       "resolved": "https://registry.npm.taobao.org/invariant/download/invariant-2.2.4.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Finvariant%2Fdownload%2Finvariant-2.2.4.tgz",
@@ -6455,6 +6741,11 @@
       "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=",
       "dev": true
     },
+    "lodash.debounce": {
+      "version": "4.0.8",
+      "resolved": "https://registry.npmmirror.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
+      "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow=="
+    },
     "lodash.escape": {
       "version": "3.2.0",
       "resolved": "https://registry.npmmirror.com/lodash.escape/-/lodash.escape-3.2.0.tgz",
@@ -11731,6 +12022,11 @@
         "individual": "^2.0.0"
       }
     },
+    "rw": {
+      "version": "1.3.3",
+      "resolved": "https://registry.npmmirror.com/rw/-/rw-1.3.3.tgz",
+      "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ=="
+    },
     "safe-buffer": {
       "version": "5.1.2",
       "resolved": "https://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.1.2.tgz",
@@ -11756,8 +12052,7 @@
     "safer-buffer": {
       "version": "2.1.2",
       "resolved": "https://registry.npm.taobao.org/safer-buffer/download/safer-buffer-2.1.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsafer-buffer%2Fdownload%2Fsafer-buffer-2.1.2.tgz",
-      "integrity": "sha1-RPoWGwGHuVSd2Eu5GAL5vYOFzWo=",
-      "dev": true
+      "integrity": "sha1-RPoWGwGHuVSd2Eu5GAL5vYOFzWo="
     },
     "sass-graph": {
       "version": "4.0.0",
@@ -13618,6 +13913,15 @@
       "resolved": "https://registry.npm.taobao.org/vue/download/vue-2.6.12.tgz?cache=0&sync_timestamp=1614614707443&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvue%2Fdownload%2Fvue-2.6.12.tgz",
       "integrity": "sha1-9evU+mvShpQD4pqJau1JBEVskSM="
     },
+    "vue-audio-better": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmmirror.com/vue-audio-better/-/vue-audio-better-3.0.1.tgz",
+      "integrity": "sha512-rr0cItOgMHYOLy7VvIHowWGqm+qLcCpj4BZ+4saAHQCSwGcV8TTCefLyGpdIjlJtqL8ytBjjtObft6WSkQoAKQ==",
+      "requires": {
+        "howler": "^2.1.2",
+        "vue": "^2.6.10"
+      }
+    },
     "vue-class-component": {
       "version": "7.2.6",
       "resolved": "https://registry.npmmirror.com/vue-class-component/-/vue-class-component-7.2.6.tgz",
@@ -13862,6 +14166,16 @@
         "vue-class-component": "^7.1.0"
       }
     },
+    "vue-resize-directive": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmmirror.com/vue-resize-directive/-/vue-resize-directive-1.2.0.tgz",
+      "integrity": "sha512-LmpFexQcl1XYyz3DQrTrq3Efgj50MKEON60nR9MMAq1D2ZtXFg1WDcy1wy1T0SeduNtIu9hos2aLTsJUplvjlQ==",
+      "requires": {
+        "css-element-queries": "^1.0.2",
+        "intersection-observer": "^0.5.0",
+        "lodash.debounce": "^4.0.8"
+      }
+    },
     "vue-resize-sensor": {
       "version": "2.0.0",
       "resolved": "https://registry.npmmirror.com/vue-resize-sensor/-/vue-resize-sensor-2.0.0.tgz",
@@ -13934,6 +14248,18 @@
         "videojs-hotkeys": "^0.2.20"
       }
     },
+    "vue-wordcloud": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmmirror.com/vue-wordcloud/-/vue-wordcloud-1.1.1.tgz",
+      "integrity": "sha512-Gs78q+mmQbI21OolpZY2b7YYdbb7wGHvIZCP+zsomxOsWICaInKTVqJADXdNtjGdBHH9JB3X9NEqBMgBVnvaUQ==",
+      "requires": {
+        "d3": "^4.10.0",
+        "d3-cloud": "^1.2.4",
+        "d3-scale-chromatic": "^1.3.3",
+        "vue": "^2.3.3",
+        "vue-resize-directive": "^1.0.0"
+      }
+    },
     "vuedraggable": {
       "version": "2.24.3",
       "resolved": "https://registry.npmmirror.com/vuedraggable/-/vuedraggable-2.24.3.tgz",
@@ -14151,6 +14477,11 @@
         }
       }
     },
+    "wav-encoder": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmmirror.com/wav-encoder/-/wav-encoder-1.3.0.tgz",
+      "integrity": "sha512-FXJdEu2qDOI+wbVYZpu21CS1vPEg5NaxNskBr4SaULpOJMrLE6xkH8dECa7PiS+ZoeyvP7GllWUAxPN3AvFSEw=="
+    },
     "wbuf": {
       "version": "1.7.3",
       "resolved": "https://registry.npm.taobao.org/wbuf/download/wbuf-1.7.3.tgz",
@@ -14877,6 +15208,11 @@
         "word": "~0.3.0"
       }
     },
+    "xmlhttprequest": {
+      "version": "1.8.0",
+      "resolved": "https://registry.npmmirror.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz",
+      "integrity": "sha512-58Im/U0mlVBLM38NdZjHyhuMtCqa61469k2YP/AaPbvCoV9aQGUpbJBj1QRm2ytRiVQBD/fsw7L2bJGDVQswBA=="
+    },
     "xtend": {
       "version": "4.0.2",
       "resolved": "https://registry.npm.taobao.org/xtend/download/xtend-4.0.2.tgz",

+ 3 - 0
package.json

@@ -38,13 +38,16 @@
     "v-viewer": "^1.6.4",
     "vant": "^2.12.10",
     "vue": "^2.5.2",
+    "vue-audio-better": "^3.0.1",
     "vue-cookies": "^1.7.4",
     "vue-pdf": "^4.2.0",
     "vue-router": "^3.0.1",
     "vue-video-player": "^5.0.2",
+    "vue-wordcloud": "^1.1.1",
     "vuedraggable": "^2.24.3",
     "vuex": "^3.6.2",
     "wangeditor": "^4.6.14",
+    "wav-encoder": "^1.3.0",
     "xlsx": "^0.16.9"
   },
   "devDependencies": {

+ 18 - 0
src/App.vue

@@ -12,6 +12,7 @@
         $route.path != '/courseGM' &&
         $route.path != '/course/addCourseGM' &&
         $route.path != '/dataGM',
+      testBg: $route.path == '/test'
     }"
   >
     <!-- <div class="app_head" :class="{stuWidth:$route.path == '/student'}"> -->
@@ -399,6 +400,10 @@ html::-webkit-scrollbar-thumb {
   background: rgb(184, 181, 202) !important;
 }
 
+.testBg{
+  background: #f0f2f5;
+}
+
 .cancelbtnGM:focus,
 .cancelbtnGM:hover {
   color: rgb(92, 84, 159) !important;
@@ -499,4 +504,17 @@ html::-webkit-scrollbar-thumb {
     color: #FFF !important;
 }
 
+.tooltip {
+  position: absolute; /* 确保tooltip处于正确的定位 */
+  top: 0;
+}
+
+.el-table-filter__checkbox-group label.el-checkbox {
+  display: flex !important;
+}
+
+.el-table-filter__bottom{
+  display: flex;
+  justify-content: flex-end;
+}
 </style>

+ 119 - 0
src/assets/css/button.css

@@ -321,9 +321,128 @@
 .test_icon_check{
   background-image: url('../icon/test/type_check_icon.png');
 }
+.test_icon_checkO{
+  background-image: url('../icon/test/type_checkO_icon.png');
+}
 .test_icon_gap{
   background-image: url('../icon/test/type_text_icon.png');
 }
 .test_icon_file{
   background-image: url('../icon/test/type_file_icon.png');
 }
+
+
+
+.dataBoard_check_box {
+  display: flex;
+  align-items: center;
+  margin: 5px auto;
+  width: fit-content;
+  height: 35px;
+  background: #FFFFFF8C;
+  border-radius: 3px;
+  font-size: 14px;
+  padding: 5px;
+  box-sizing: border-box;
+}
+
+.dataBoard_check_box>div {
+  height: 100%;
+  display: flex;
+  align-items: center;
+  padding: 0 12px;
+  cursor: pointer;
+  color: #00000099;
+}
+
+.dataBoard_check_box>.active {
+  background: #fff;
+}
+
+.dataBoard_check_box>.active>span {
+  background-image: linear-gradient(90deg, #3673E8 0%, #AD88FD 100%);
+  -webkit-background-clip: text;
+  -webkit-text-fill-color: transparent;
+}
+
+.dataBoard_check_box>.icon::before {
+  content: '';
+  width: 16px;
+  height: 16px;
+  background-size: 100% 100%;
+  margin-right: 5px;
+}
+
+.dataBoard_check_box>.rl_icon::before {
+  background-image: url('../icon/dataCheck/rl_icon_data.png');
+}
+
+.dataBoard_check_box>.yb_icon::before {
+  background-image: url('../icon/dataCheck/yb_icon_data.png');
+}
+
+.dataBoard_check_box>.zz_icon::before {
+  background-image: url('../icon/dataCheck/zz_icon_data.png');
+}
+
+.dataBoard_check_box>.zz_icon2::before {
+  background-image: url('../icon/dataCheck/zz_icon_data2.png');
+}
+
+.dataBoard_check_box>.sd_icon::before {
+  background-image: url('../icon/dataCheck/sd_icon_data.png');
+}
+
+.dataBoard_check_box>.ld_icon::before {
+  background-image: url('../icon/dataCheck/ld_icon_data.png');
+}
+
+.dataBoard_check_box>.djzz_icon::before {
+  background-image: url('../icon/dataCheck/djzz_icon_data.png');
+}
+
+.dataBoard_check_box>.hx_icon::before {
+  background-image: url('../icon/dataCheck/hx_icon_data.png');
+}
+
+.dataBoard_check_box>.bz_icon::before {
+  background-image: url('../icon/dataCheck/bz_icon_data.png');
+}
+
+
+
+.dataBoard_check_box>.active.rl_icon::before {
+  background-image: url('../icon/dataCheck/rl_icon_data_active.png');
+}
+
+.dataBoard_check_box>.active.yb_icon::before {
+  background-image: url('../icon/dataCheck/yb_icon_data_active.png');
+}
+
+.dataBoard_check_box>.active.zz_icon::before {
+  background-image: url('../icon/dataCheck/zz_icon_data_active.png');
+}
+
+.dataBoard_check_box>.active.zz_icon2::before {
+  background-image: url('../icon/dataCheck/zz_icon_data2_active.png');
+}
+
+.dataBoard_check_box>.active.sd_icon::before {
+  background-image: url('../icon/dataCheck/sd_icon_data_active.png');
+}
+
+.dataBoard_check_box>.active.ld_icon::before {
+  background-image: url('../icon/dataCheck/ld_icon_data_active.png');
+}
+
+.dataBoard_check_box>.active.djzz_icon::before {
+  background-image: url('../icon/dataCheck/djzz_icon_data_active.png');
+}
+
+.dataBoard_check_box>.active.hx_icon::before {
+  background-image: url('../icon/dataCheck/hx_icon_data_active.png');
+}
+
+.dataBoard_check_box>.active.bz_icon::before {
+  background-image: url('../icon/dataCheck/bz_icon_data_active.png');
+}

BIN
src/assets/icon/courseEvaTemplate/add.png


BIN
src/assets/icon/courseEvaTemplate/delete.png


BIN
src/assets/icon/courseEvaTemplate/deleteHover.png


BIN
src/assets/icon/courseEvaTemplate/grouping.png


BIN
src/assets/icon/courseEvaTemplate/groupingHover.png


BIN
src/assets/icon/courseEvaTemplate/one.png


BIN
src/assets/icon/courseEvaTemplate/reName.png


BIN
src/assets/icon/courseEvaTemplate/reNameHover.png


BIN
src/assets/icon/courseEvaTemplate/share.png


BIN
src/assets/icon/courseEvaTemplate/shareHover.png


BIN
src/assets/icon/courseEvaTemplate/three.png


BIN
src/assets/icon/courseEvaTemplate/two.png


BIN
src/assets/icon/dataCheck/bz_icon_data.png


BIN
src/assets/icon/dataCheck/bz_icon_data_active.png


BIN
src/assets/icon/dataCheck/djzz_icon_data.png


BIN
src/assets/icon/dataCheck/djzz_icon_data_active.png


BIN
src/assets/icon/dataCheck/hx_icon_data.png


BIN
src/assets/icon/dataCheck/hx_icon_data_active.png


BIN
src/assets/icon/dataCheck/ld_icon_data.png


BIN
src/assets/icon/dataCheck/ld_icon_data_active.png


BIN
src/assets/icon/dataCheck/rl_icon_data.png


BIN
src/assets/icon/dataCheck/rl_icon_data_active.png


BIN
src/assets/icon/dataCheck/sd_icon_data.png


BIN
src/assets/icon/dataCheck/sd_icon_data_active.png


BIN
src/assets/icon/dataCheck/yb_icon_data.png


BIN
src/assets/icon/dataCheck/yb_icon_data_active.png


BIN
src/assets/icon/dataCheck/zz_icon_data.png


BIN
src/assets/icon/dataCheck/zz_icon_data2.png


BIN
src/assets/icon/dataCheck/zz_icon_data2_active.png


BIN
src/assets/icon/dataCheck/zz_icon_data_active.png


BIN
src/assets/icon/englishVoice/icon_delete.png


BIN
src/assets/icon/englishVoice/icon_delete2.png


BIN
src/assets/icon/englishVoice/icon_picture.png


BIN
src/assets/icon/englishVoice/icon_portal.png


BIN
src/assets/icon/englishVoice/icon_voice.png


BIN
src/assets/icon/new/allScreen.png


BIN
src/assets/icon/studentEva/diary.png


BIN
src/assets/icon/studentEva/img_1.png


BIN
src/assets/icon/studentEva/img_2.png


BIN
src/assets/icon/studentEva/img_3.png


BIN
src/assets/icon/studentEva/img_4.png


BIN
src/assets/icon/studentEva/img_5.png


BIN
src/assets/icon/studentEva/isDiary.png


BIN
src/assets/icon/studentEva/isReport.png


BIN
src/assets/icon/studentEva/isScore.png


BIN
src/assets/icon/studentEva/report.png


BIN
src/assets/icon/studentEva/score.png


BIN
src/assets/icon/studentEva/star-no.png


BIN
src/assets/icon/studentEva/star.png


BIN
src/assets/icon/test/data_title.png


BIN
src/assets/icon/test/data_title_icon.png


BIN
src/assets/icon/test/delete_test_icon.png


BIN
src/assets/icon/test/icon_share.png


BIN
src/assets/icon/test/paste-icon.png


BIN
src/assets/icon/test/share_test_icon.png


BIN
src/assets/icon/test/test_list.png


BIN
src/assets/icon/test/test_list_active.png


BIN
src/assets/icon/test/test_search.png


BIN
src/assets/icon/test/test_table.png


BIN
src/assets/icon/test/test_table_active.png


BIN
src/assets/icon/test/type_checkO_icon.png


+ 1 - 1
src/common/axios.config.js

@@ -21,7 +21,7 @@ axios.interceptors.request.use((config) => {
     // } else if (config.method === 'post') {
     //     config.data = qs.stringify(config.data)//序列化post 参数
     // }
-    if(config.url === 'https://gpt.cocorobo.cn/search_image' || config.url === 'https://gpt.cocorobo.cn/chat') {
+    if(config.url === 'https://gpt.cocorobo.cn/search_image' || config.url === 'https://gpt.cocorobo.cn/chat' || config.url === 'https://gpt4.cocorobo.cn/create_free_assistants' || config.url === 'https://gpt4.cocorobo.cn/assistants_completion_response') {
         config.data = config.data//序列化post 参数
     } else if (config.data && config.data[0].post == '1' && config.method === 'post') {
         config.data = 'mode=' + (Object.values(config.data[0]).join(','))//序列化post 参数

+ 1 - 0
src/common/tools.js

@@ -32,6 +32,7 @@ export const tools = {
     67: { name: "分子结构" },
     68: { name: "时间轴" },
     69: { name: "英语写作" },
+    70: { name: "英语口语" },
     25: { name: "目标管理" },
     26: { name: "课程设计" },
     62: { name: "交互视频" }

+ 49 - 30
src/components/pages/EnglishVoice/component/check.vue

@@ -63,28 +63,28 @@ export default {
                         }
                     ]
                 },
-                // {
-                //     name:'对话',
-                //     open: false,
-                //     children:[
-                //         {
-                //             icon:icon_check_addUser,
-                //             name:'创建角色',
-                //             type:'createRole'
-                //         }
-                //     ]
-                // },
-                // {
-                //     name:'主题陈述',
-                //     open: false,
-                //     children:[
-                //         {
-                //             icon:icon_check_theme,
-                //             name:'新建主题',
-                //             type:'theme'
-                //         }
-                //     ]
-                // }
+                {
+                    name:'对话',
+                    open: true,
+                    children:[
+                        {
+                            icon:icon_check_addUser,
+                            name:'创建角色',
+                            type:'createRole'
+                        }
+                    ]
+                },
+                {
+                    name:'主题陈述',
+                    open: true,
+                    children:[
+                        {
+                            icon:icon_check_theme,
+                            name:'新建主题',
+                            type:'theme'
+                        }
+                    ]
+                }
             ],
             checkArray:[]
         }
@@ -100,21 +100,40 @@ export default {
                     type:'word',
                     title:'',
                     img:'',
-                    content:'单词/词组'  
+                    content:'' //单词/词组  
                 })
             }else if(item.type == 'sentence'){
                 this.checkArray.push({
                     type:'sentence',
                     title:'',
                     img:'',
-                    content:'句子/短文'  
+                    content:''  //句子/短文
                 })
             }else if(item.type == 'QA'){
                 this.checkArray.push({
                     type:'QA',
                     title:'',
                     img:'',
-                    content:'题目'  
+                    content:''   //题目
+                })
+            }else if(item.type == 'theme'){
+                this.checkArray.push({
+                    type:'theme',
+                    title:'', 
+                    img:'',
+                    content:'' ,  //题目
+                    content2:'',   //内容
+                    rTime: 1,   //准备时间
+                    oTime: 1,   //演讲时间
+                })
+            }else if(item.type == 'createRole'){
+                this.checkArray.push({
+                    type:'createRole',
+                    title:'', 
+                    img:'',
+                    content:'' ,  //人名
+                    content2:'',   //角色定义
+                    content3:'',   //角色问候
                 })
             }
             this.$forceUpdate()
@@ -123,11 +142,11 @@ export default {
     },
     watch: {
         checkJson: {
-        handler: function (newVal, oldVal) {
-            this.checkArray = this.depthCopy(newVal);
-        },
-        deep: true,
-        },
+            handler: function (newVal, oldVal) {
+                this.checkArray = this.depthCopy(newVal);
+            },
+            deep: true,
+        }
     },
     mounted(){
         this.checkArray = this.depthCopy(this.checkJson);

+ 292 - 0
src/components/pages/EnglishVoice/component/component/createRole.vue

@@ -0,0 +1,292 @@
+<template>
+    <div class="o_box">
+        <div class="o_content">
+            <span>角色名字</span>
+            <textarea v-autoHeight="38" rows="1" class="binfo_input binfo_textarea" cols v-model="checkJson.content"
+                placeholder="创建角色" @change="setJson"></textarea>
+        </div>
+        <div class="o_content">
+            <span>添加图片</span>
+            <div class="o_uploadbox_img" v-if="checkJson.img">
+                <div class="pic_mask">
+                    <span @click="checkImg(checkJson.img)">查看</span>
+                    <span @click="deleteImg()">删除</span>
+                </div>
+                <img :src="checkJson.img" alt="">
+            </div>
+            <div class="o_uploadbox" v-if="!checkJson.img" @click="getImg()">智能获取</div>
+            <div class="o_uploadbox" style="padding: 0 6px;" @click="addImg($event)" v-if="!checkJson.img">
+                <span class="icon_pic"></span>
+                <input type="file" accept="image/*" style="display: none" @change="beforeUpload($event)" />
+            </div>
+        </div>
+        <div class="o_content">
+            <span>角色定义</span>
+            <textarea v-autoHeight="38" rows="1" class="binfo_input binfo_textarea" cols v-model="checkJson.content2"
+                placeholder="请输入对改角色的定义" @change="setJson"></textarea>
+        </div>
+        <div class="o_content">
+            <span>角色问候</span>
+            <textarea v-autoHeight="38" rows="1" class="binfo_input binfo_textarea" cols v-model="checkJson.content3"
+                placeholder="请输入对改角色的问候话语" @change="setJson"></textarea>
+        </div>
+        <div class="o_content">
+            <span></span>
+            <button class="c_pub_button_add" @click="openTest">角色测试</button>
+        </div>
+        <div v-if="proVisible" class="mask">
+            <div class="progressBox">
+                <div class="lbox">
+                    <img src="../../../../../assets/loading.gif" />上传中,请稍后
+                </div>
+                <div style="margin-bottom: 10px">
+                    <span>{{
+                        isFinishSize
+                    }}M</span>
+                    /
+                    <span>{{
+                        isAllSize
+                    }}M</span>
+                </div>
+                <el-progress :text-inside="true" :stroke-width="20" :percentage="progress
+                    ? progress
+                    : 0
+                    " style="width: 80%"></el-progress>
+            </div>
+        </div>
+        <gpt-img :sysPicVisible.sync="sysPicVisible" :value="checkJson.content" @setImg="setImg"></gpt-img>
+    </div>
+</template>
+
+<script>
+import minxin from './minxins/minxin';
+export default {
+    mixins: [minxin],
+    props: {
+        cjson: {
+            type: Object,
+        },
+    },
+    data() {
+        return {
+            checkJson: {}
+        }
+    },
+    methods: {
+        setJson() {
+            this.$emit('setJson', this.checkJson)
+        },
+        setImg(url) {
+            this.checkJson.img = url
+            this.$emit('setJson', this.checkJson)
+        },
+        openTest(){
+            this.$emit('openTest', this.checkJson)
+        }
+    },
+    watch: {
+        cjson: {
+            handler: function (newVal, oldVal) {
+                this.checkJson = this.depthCopy(newVal);
+            },
+            deep: true,
+        },
+        imgUrl: {
+            handler: function (newVal, oldVal) {
+                this.checkJson.img = newVal
+                this.$forceUpdate()
+                this.$emit('setJson', this.checkJson)
+            },
+            deep: true,
+        },
+    },
+    mounted() {
+        this.checkJson = this.depthCopy(this.cjson);
+    }
+}
+</script>
+
+<style scoped>
+.o_box {
+    width: 100%;
+    box-sizing: border-box;
+    padding: 12px 16px 12px 48px;
+    background: #f5f6f7;
+    position: relative;
+}
+
+.binfo_input {
+    width: 100%;
+    margin: 0;
+    padding: 8px;
+    display: block;
+    min-width: 0;
+    outline: none;
+    box-sizing: border-box;
+    background: none;
+    border: none;
+    border-radius: 4px;
+    background: #fff;
+    font-size: 16px;
+    resize: none;
+    font-family: 'Microsoft YaHei';
+    min-height: 38px;
+    /* border: 1px solid #3682fc00; */
+    border: 1.5px solid #CAD1DC;
+}
+
+.binfo_textarea {
+    border: 1.5px solid #CAD1DC;
+    font-size: 14px;
+    resize: none;
+    /* background: #f6f6f6; */
+    font-family: 'Microsoft YaHei';
+}
+
+.binfo_input:focus-visible {
+    border: 1.5px solid #3681FC !important;
+}
+
+.o_content {
+    display: flex;
+    color: #000;
+    font-size: 14px;
+}
+
+.o_content+.o_content {
+    margin-top: 10px;
+}
+
+.o_content>span {
+    min-width: 57px;
+    margin-right: 12px;
+    line-height: 38px;
+}
+
+.o_uploadbox {
+    height: 32px;
+    padding: 0 8px;
+    background: #eee;
+    line-height: 32px;
+    margin-top: 3px;
+    font-size: 14px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    cursor: pointer;
+}
+
+.o_uploadbox+.o_uploadbox {
+    margin-left: 12px;
+}
+
+.icon_pic {
+    width: 20px;
+    height: 20px;
+    background-image: url('../../../../../assets/icon/englishVoice/icon_picture.png');
+    background-size: 100% 100%;
+    display: block;
+}
+
+.mask {
+    background-color: rgb(0 0 0 / 30%);
+    /* position: fixed; */
+    position: absolute;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 100%;
+    z-index: 90;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+}
+
+.progressBox {
+    width: 300px;
+    height: 150px;
+    background: #fff;
+    border-radius: 10px;
+    box-shadow: 0 0 6px 1px #bfbfbf;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    flex-direction: column;
+    position: relative;
+    color: #6c6c6c;
+}
+
+.progressBox>>>.el-progress-bar__outer {
+    background-color: #d1dfff !important;
+}
+
+.progressBox .lbox {
+    height: 50px;
+    font-size: 19px;
+    display: flex;
+    align-items: center;
+    color: #747474;
+}
+
+.progressBox .lbox img {
+    width: 40px;
+    margin-right: 20px;
+}
+
+.closeCss {
+    position: absolute;
+    top: 8px;
+    right: 8px;
+    cursor: pointer;
+    width: 20px;
+    height: 20px;
+}
+
+.closeCss>img {
+    width: 100%;
+    height: 100%;
+}
+
+
+.o_uploadbox_img {
+    width: 100px;
+    height: 100px;
+    border-radius: 5px;
+    position: relative;
+    overflow: hidden;
+}
+
+.o_uploadbox_img>img {
+    width: 100%;
+    height: 100%;
+    object-fit: cover;
+}
+
+.o_uploadbox_img:hover .pic_mask {
+    display: flex;
+}
+
+.pic_mask {
+    position: absolute;
+    width: 100%;
+    height: 100%;
+    background: rgba(0, 0, 0, .3);
+    flex-direction: column;
+    justify-content: center;
+    align-items: center;
+    top: 0;
+    left: 0;
+    color: #458dff;
+    display: none;
+    border-radius: 5px;
+}
+
+.pic_mask>span {
+    cursor: pointer;
+    font-size: 14px;
+    color: #fff;
+}
+
+.pic_mask>span+span {
+    margin-top: 10px;
+}</style>

+ 207 - 0
src/components/pages/EnglishVoice/component/component/gptImg.vue

@@ -0,0 +1,207 @@
+<template>
+    <el-dialog title="智能获取" :visible.sync="sysPicVisible" :append-to-body="true" width="710px" :before-close="handleClose"
+        class="dialog_diy">
+        <div>
+            <div class="people_top_right" style="display: flex;align-items: center;">
+                <div style="position: relative; width: 100%;">
+                    <el-input style="height: 100%" placeholder="搜索图片关键字" v-model="searchImageValue"
+                        @keyup.enter.native="resetImage()"></el-input>
+                    <div class="search_img" @click="resetImage" style="right: 10px;">
+                        <img src="../../../../../assets/icon/search.png" alt />
+                    </div>
+                </div>
+                <el-button type="primary" size="default" style="margin-left: 10px;" @click="changePicture">换一组</el-button>
+            </div>
+            <div class="sysPicBox" v-loading="imageloading">
+                <div class="picNone" v-if="!imageList.length">请输入关键词搜索图片</div>
+                <div v-for="(sys, sysIndex) in imageList" :key="sysIndex" class="sysPic">
+                    <img :src="sys.url" alt="" @click="chooseSysPic2(sys.url)" />
+                </div>
+            </div>
+        </div>
+    </el-dialog>
+</template>
+
+<script>
+export default {
+    props: {
+        sysPicVisible: {
+            type: Boolean,
+        },
+        value: {
+            type: String,
+            default: '' 
+        }
+    },
+    data() {
+        return {
+            searchImageValue: "",
+            imageloading: false,
+            imageList: [],
+            ppage: 1,
+        }
+    },
+    methods: {
+        handleClose(done) {
+            this.close();
+            done();
+        },
+        close() {
+            this.$emit("update:sysPicVisible", false);
+        },
+        resetImage() {
+            this.ppage = 1
+            this.searchImage()
+        },
+        changePicture() {
+            this.ppage++
+            this.searchImage()
+        },
+        searchImage() {
+            var _this = this;
+            if (_this.searchImageValue == "") {
+                _this.$message.error("请输入关键词");
+                return
+            }
+            _this.imageList = []
+            _this.imageloading = true
+            _this.ajax.post('https://gpt.cocorobo.cn/search_image', {
+                page: _this.ppage,
+                pagesize: 9,
+                query: _this.searchImageValue
+            }).then(function (response) {
+                // console.log(response.data.data);
+                var data = response.data.FunctionResponse.result;
+                for (var i = 0; i < data.length; i++) {
+                    _this.imageList.push({ url: data[i].thumbnail })
+                }
+                _this.imageloading = false
+            }).catch(function (error) {
+                console.log(error);
+            });
+        },
+        chooseSysPic2(url){
+            this.$emit("setImg", url);
+            this.close();
+        }
+    },
+    watch: {
+        sysPicVisible(newValue, oldValue) {
+            if (newValue) {
+                this.searchImageValue = JSON.parse(JSON.stringify(this.value));
+                this.ppage = 1
+                this.searchImage()
+            }
+        },
+        value: {
+            handler: function (newVal, oldVal) {
+                this.searchImageValue = JSON.parse(JSON.stringify(newVal));
+            },
+            deep: true,
+        },
+    },
+    mounted() {
+        this.searchImageValue = JSON.parse(JSON.stringify(this.value));
+    },
+}
+</script>
+
+<style scoped>
+.dialog_diy>>>.el-dialog__header {
+    background: #3c3c3c !important;
+    padding: 15px 20px;
+}
+
+.dialog_diy>>>.el-dialog__title {
+    color: #fff;
+}
+
+.dialog_diy>>>.el-dialog__headerbtn {
+    top: 19px;
+}
+
+.dialog_diy>>>.el-dialog__headerbtn .el-dialog__close {
+    color: #fff;
+}
+
+.dialog_diy>>>.el-dialog__headerbtn .el-dialog__close:hover {
+    color: #fff;
+}
+
+.dialog_diy>>>.el-dialog__body,
+.dialog_diy>>>.el-dialog__footer {
+    background: #fafafa;
+}
+
+.dialog_diy3>>>.el-dialog__body,
+.dialog_diy3>>>.el-dialog__footer {
+    background: #eee !important;
+}
+
+.dialog_diy3>>>.el-dialog__body {
+    padding: 20px 20px;
+}
+
+.dialog_diyStage>>>.el-dialog__body {
+    padding: 10px;
+}
+
+.people_top_right {
+    height: 40px;
+    margin-bottom: 10px;
+}
+
+.search_img {
+    width: 20px;
+    height: 20px;
+    position: absolute;
+    right: 10px;
+    top: 50%;
+    transform: translateY(-50%);
+}
+
+.search_img>img {
+    width: 100%;
+    height: 100%;
+}
+
+.sysPicBox {
+    display: flex;
+    flex-direction: row;
+    flex-wrap: wrap;
+    align-content: flex-start;
+    height: 435px;
+    overflow: auto;
+    position: relative;
+}
+
+.picNone {
+    position: absolute;
+    left: 50%;
+    top: 45%;
+    transform: translate(-50%, -50%);
+    width: fit-content;
+    color: #9c9c9c;
+}
+
+.sysPic {
+    width: 200px;
+    height: 115px;
+    margin: 0 20px 20px 0;
+    cursor: pointer;
+}
+
+.sysPic>img,
+.isSysPic>img,
+.deletePic>img {
+    width: 100%;
+    height: 100%;
+    object-fit: cover;
+}
+
+.isSysPic {
+    width: 200px;
+    height: 115px;
+    position: relative;
+}
+</style>

+ 149 - 0
src/components/pages/EnglishVoice/component/component/minxins/minxin.js

@@ -0,0 +1,149 @@
+import "../../../../../../common/aws-sdk-2.235.1.min.js";
+import gptImg from '../gptImg.vue'
+
+const minxin = {
+  components: {
+    gptImg,
+  },
+  data() {
+    return {
+      options2: {
+        word: "单词/词组",
+        sentence: "句子/短文",
+        QA: "题目",
+        createRole: "创建角色",
+        theme: "新建主题"
+      },
+      progress: 0,
+      isFinishSize: 0,
+      proVisible: false,
+      isAllSize: 0,
+      imgUrl: "",
+      sysPicVisible:false
+    };
+  },
+  directives: {
+    autoHeight: {
+      update(el, binding) {
+        const { value } = binding;
+        if (value && typeof value === "number") {
+          el.style.height = `${value}px`;
+        } else {
+          el.style.height = "auto";
+        }
+      },
+      componentUpdated(el) {
+        el.style.height = `${el.scrollHeight + 5}px`;
+      }
+    }
+  },
+  computed: {},
+  mounted() {},
+  activated() {},
+  methods: {
+    getImg(){
+      this.sysPicVisible = true
+    },
+    depthCopy(s) {
+      return s ? JSON.parse(JSON.stringify(s)) : "";
+    },
+    addImg(e) {
+        var el = e.currentTarget;
+        el.getElementsByTagName("input")[0].click();
+        e.target.value = "";
+    },
+    beforeUpload(event, type) {
+      // const loading = this.openLoading();
+      var file = event.target.files[0];
+      var credentials = {
+        accessKeyId: "AKIATLPEDU37QV5CHLMH",
+        secretAccessKey: "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"
+      }; //秘钥形式的登录上传
+      window.AWS.config.update(credentials);
+      window.AWS.config.region = "cn-northwest-1"; //设置区域
+
+      var bucket = new window.AWS.S3({ params: { Bucket: "ccrb" } }); //选择桶
+      var _this = this;
+      var imgA = [
+        "png",
+        "jpg",
+        "jpeg",
+        "bmp",
+        "gif",
+        "webp",
+        "psd",
+        "svg",
+        "tiff"
+      ];
+      if(imgA.indexOf(file.name.split(".")[file.name.split(".").length - 1]) == -1){
+        this.$message.error("请上传图片格式文件");
+        return
+      }
+      _this.progress = 0;
+      _this.proVisible = true;
+      _this.isFinishSize = 0;
+      _this.isAllSize = (file.size / 1024 / 1024).toFixed(2);
+      _this.$forceUpdate();
+      if (file) {
+        var params = {
+          Key:
+            file.name.split(".")[0] +
+            new Date().getTime() +
+            "." +
+            file.name.split(".")[file.name.split(".").length - 1],
+          ContentType: file.type,
+          Body: file,
+          "Access-Control-Allow-Credentials": "*",
+          ACL: "public-read"
+        }; //key可以设置为桶的相抵路径,Body为文件, ACL最好要设置
+        var options = {
+          partSize: 2048 * 1024 * 1024,
+          queueSize: 2,
+          leavePartsOnError: true
+        };
+        bucket
+          .upload(params, options)
+          .on("httpUploadProgress", function(evt) {
+            //这里可以写进度条
+            // console.log("Uploaded : " + parseInt((evt.loaded * 80) / evt.total) + '%');
+            _this.progress = parseInt((evt.loaded / evt.total) * 100);
+            _this.isFinishSize = (evt.loaded / 1024 / 1024).toFixed(2);
+            _this.$forceUpdate();
+          })
+          .send(function(err, data) {
+            _this.progress = 100;
+            _this.isFinishSize = _this.isAllSize;
+            _this.$forceUpdate();
+            setTimeout(() => {
+              _this.proVisible = false;
+              _this.$forceUpdate();
+            }, 1000);
+            // loading.close();
+            if (err) {
+              _this.$message.error("上传失败");
+            } else {
+              _this.imgUrl = data.Location;
+              console.log(data.Location);
+            }
+          });
+      }
+    },
+    checkImg(img){
+      this.$hevueImgPreview(img);
+    },
+    deleteImg(){
+      this.$confirm('确认删除该图片吗?', "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning",
+      })
+        .then(() => {
+          this.checkJson.img = ''
+          this.$emit('setJson',this.checkJson)
+        })
+        .catch(() => { });
+    },
+  }
+};
+
+export default minxin;

+ 275 - 0
src/components/pages/EnglishVoice/component/component/qa2.vue

@@ -0,0 +1,275 @@
+<template>
+  <div class="o_box">
+    <div class="o_content">
+      <span>输入内容</span>
+      <textarea v-autoHeight="38" rows="1" class="binfo_input binfo_textarea" cols v-model="checkJson.content"
+        placeholder="问题" @change="setJson"></textarea>
+    </div>
+    <div class="o_content">
+      <span>添加图片</span>
+      <div class="o_uploadbox_img" v-if="checkJson.img">
+        <div class="pic_mask">
+          <span @click="checkImg(checkJson.img)">查看</span>
+          <span @click="deleteImg()">删除</span>
+        </div>
+        <img :src="checkJson.img" alt="">
+      </div>
+      <div class="o_uploadbox" v-if="!checkJson.img" @click="getImg()">智能获取</div>
+      <div class="o_uploadbox" style="padding: 0 6px;" @click="addImg($event)" v-if="!checkJson.img">
+        <span class="icon_pic"></span>
+        <input type="file" accept="image/*" style="display: none" @change="beforeUpload($event)" />
+      </div>
+    </div>
+    <div v-if="proVisible" class="mask">
+      <div class="progressBox">
+        <div class="lbox">
+          <img src="../../../../../assets/loading.gif" />上传中,请稍后
+        </div>
+        <div style="margin-bottom: 10px">
+          <span>{{
+            isFinishSize
+          }}M</span>
+          /
+          <span>{{
+            isAllSize
+          }}M</span>
+        </div>
+        <el-progress :text-inside="true" :stroke-width="20" :percentage="progress
+          ? progress
+          : 0
+          " style="width: 80%"></el-progress>
+      </div>
+    </div>
+    <gpt-img :sysPicVisible.sync="sysPicVisible" :value="checkJson.content" @setImg="setImg"></gpt-img>
+  </div>
+</template>
+
+<script>
+import minxin from './minxins/minxin';
+export default {
+  mixins: [minxin],
+  props: {
+    cjson: {
+      type: Object,
+    },
+  },
+  data() {
+    return {
+      checkJson: {}
+    }
+  },
+  methods: {
+    setJson() {
+      this.$emit('setJson', this.checkJson)
+    },
+    setImg(url) {
+      this.checkJson.img = url
+      this.$emit('setJson', this.checkJson)
+    }
+  },
+  watch: {
+    cjson: {
+      handler: function (newVal, oldVal) {
+        this.checkJson = this.depthCopy(newVal);
+      },
+      deep: true,
+    },
+    imgUrl: {
+      handler: function (newVal, oldVal) {
+        this.checkJson.img = newVal
+        this.$forceUpdate()
+        this.$emit('setJson', this.checkJson)
+      },
+      deep: true,
+    },
+  },
+  mounted() {
+    this.checkJson = this.depthCopy(this.cjson);
+  }
+}
+</script>
+
+<style scoped>
+.o_box {
+  width: 100%;
+  box-sizing: border-box;
+  padding: 12px 16px 12px 48px;
+  background: #f5f6f7;
+  position: relative;
+}
+
+.binfo_input {
+  width: 100%;
+  margin: 0;
+  padding: 8px;
+  display: block;
+  min-width: 0;
+  outline: none;
+  box-sizing: border-box;
+  background: none;
+  border: none;
+  border-radius: 4px;
+  background: #fff;
+  font-size: 16px;
+  resize: none;
+  font-family: 'Microsoft YaHei';
+  min-height: 38px;
+  /* border: 1px solid #3682fc00; */
+  border: 1.5px solid #CAD1DC;
+}
+
+.binfo_textarea {
+  border: 1.5px solid #CAD1DC;
+  font-size: 14px;
+  resize: none;
+  /* background: #f6f6f6; */
+  font-family: 'Microsoft YaHei';
+}
+
+.binfo_input:focus-visible {
+  border: 1.5px solid #3681FC !important;
+}
+
+.o_content {
+  display: flex;
+  color: #000;
+  font-size: 14px;
+}
+
+.o_content+.o_content {
+  margin-top: 10px;
+}
+
+.o_content>span {
+  min-width: fit-content;
+  margin-right: 12px;
+  line-height: 38px;
+}
+
+.o_uploadbox {
+  height: 32px;
+  padding: 0 8px;
+  background: #eee;
+  line-height: 32px;
+  margin-top: 3px;
+  font-size: 14px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  cursor: pointer;
+}
+
+.o_uploadbox+.o_uploadbox {
+  margin-left: 12px;
+}
+
+.icon_pic {
+  width: 20px;
+  height: 20px;
+  background-image: url('../../../../../assets/icon/englishVoice/icon_picture.png');
+  background-size: 100% 100%;
+  display: block;
+}
+
+.mask {
+  background-color: rgb(0 0 0 / 30%);
+  /* position: fixed; */
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  z-index: 90;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+
+.progressBox {
+  width: 300px;
+  height: 150px;
+  background: #fff;
+  border-radius: 10px;
+  box-shadow: 0 0 6px 1px #bfbfbf;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  flex-direction: column;
+  position: relative;
+  color: #6c6c6c;
+}
+
+.progressBox>>>.el-progress-bar__outer {
+  background-color: #d1dfff !important;
+}
+
+.progressBox .lbox {
+  height: 50px;
+  font-size: 19px;
+  display: flex;
+  align-items: center;
+  color: #747474;
+}
+
+.progressBox .lbox img {
+  width: 40px;
+  margin-right: 20px;
+}
+
+.closeCss {
+  position: absolute;
+  top: 8px;
+  right: 8px;
+  cursor: pointer;
+  width: 20px;
+  height: 20px;
+}
+
+.closeCss>img {
+  width: 100%;
+  height: 100%;
+}
+
+.o_uploadbox_img {
+  width: 100px;
+  height: 100px;
+  border-radius: 5px;
+  position: relative;
+  overflow: hidden;
+}
+
+.o_uploadbox_img>img {
+  width: 100%;
+  height: 100%;
+  object-fit: cover;
+}
+
+.o_uploadbox_img:hover .pic_mask {
+  display: flex;
+}
+
+.pic_mask {
+  position: absolute;
+  width: 100%;
+  height: 100%;
+  background: rgba(0, 0, 0, .3);
+  flex-direction: column;
+  justify-content: center;
+  align-items: center;
+  top: 0;
+  left: 0;
+  color: #458dff;
+  display: none;
+  border-radius: 5px;
+}
+
+.pic_mask>span {
+  cursor: pointer;
+  font-size: 14px;
+  color: #fff;
+}
+
+.pic_mask>span+span {
+  margin-top: 10px;
+}
+</style>

+ 275 - 0
src/components/pages/EnglishVoice/component/component/sentence.vue

@@ -0,0 +1,275 @@
+<template>
+    <div class="o_box">
+        <div class="o_content">
+            <span>输入内容</span>
+            <textarea v-autoHeight="38" rows="1" class="binfo_input binfo_textarea" cols v-model="checkJson.content"
+                placeholder="句子/短文" @change="setJson"></textarea>
+        </div>
+        <div class="o_content">
+            <span>添加图片</span>
+            <div class="o_uploadbox_img" v-if="checkJson.img">
+                <div class="pic_mask">
+                    <span @click="checkImg(checkJson.img)">查看</span>
+                    <span @click="deleteImg()">删除</span>
+                </div>
+                <img :src="checkJson.img" alt="">
+            </div>
+            <div class="o_uploadbox" v-if="!checkJson.img" @click="getImg()">智能获取</div>
+            <div class="o_uploadbox" style="padding: 0 6px;" @click="addImg($event)" v-if="!checkJson.img">
+                <span class="icon_pic"></span>
+                <input type="file" accept="image/*" style="display: none" @change="beforeUpload($event)" />
+            </div>
+        </div>
+        <div v-if="proVisible" class="mask">
+            <div class="progressBox">
+                <div class="lbox">
+                    <img src="../../../../../assets/loading.gif" />上传中,请稍后
+                </div>
+                <div style="margin-bottom: 10px">
+                    <span>{{
+                        isFinishSize
+                    }}M</span>
+                    /
+                    <span>{{
+                        isAllSize
+                    }}M</span>
+                </div>
+                <el-progress :text-inside="true" :stroke-width="20" :percentage="progress
+                    ? progress
+                    : 0
+                    " style="width: 80%"></el-progress>
+            </div>
+        </div>
+        <gpt-img :sysPicVisible.sync="sysPicVisible" :value="checkJson.content" @setImg="setImg"></gpt-img>
+    </div>
+</template>
+
+<script>
+import minxin from './minxins/minxin';
+export default {
+    mixins: [minxin],
+    props: {
+        cjson: {
+            type: Object,
+        },
+    },
+    data() {
+        return {
+            checkJson: {}
+        }
+    },
+    methods: {
+        setJson() {
+            this.$emit('setJson', this.checkJson)
+        },
+        setImg(url) {
+            this.checkJson.img = url
+            this.$emit('setJson', this.checkJson)
+        }
+    },
+    watch: {
+        cjson: {
+            handler: function (newVal, oldVal) {
+                this.checkJson = this.depthCopy(newVal);
+            },
+            deep: true,
+        },
+        imgUrl: {
+            handler: function (newVal, oldVal) {
+                this.checkJson.img = newVal
+                this.$forceUpdate()
+                this.$emit('setJson', this.checkJson)
+            },
+            deep: true,
+        },
+    },
+    mounted() {
+        this.checkJson = this.depthCopy(this.cjson);
+    }
+}
+</script>
+
+<style scoped>
+.o_box {
+    width: 100%;
+    box-sizing: border-box;
+    padding: 12px 16px 12px 48px;
+    background: #f5f6f7;
+    position: relative;
+}
+
+.binfo_input {
+    width: 100%;
+    margin: 0;
+    padding: 8px;
+    display: block;
+    min-width: 0;
+    outline: none;
+    box-sizing: border-box;
+    background: none;
+    border: none;
+    border-radius: 4px;
+    background: #fff;
+    font-size: 16px;
+    resize: none;
+    font-family: 'Microsoft YaHei';
+    min-height: 38px;
+    /* border: 1px solid #3682fc00; */
+    border: 1.5px solid #CAD1DC;
+}
+
+.binfo_textarea {
+    border: 1.5px solid #CAD1DC;
+    font-size: 14px;
+    resize: none;
+    /* background: #f6f6f6; */
+    font-family: 'Microsoft YaHei';
+}
+
+.binfo_input:focus-visible {
+    border: 1.5px solid #3681FC !important;
+}
+
+.o_content {
+    display: flex;
+    color: #000;
+    font-size: 14px;
+}
+
+.o_content+.o_content {
+    margin-top: 10px;
+}
+
+.o_content>span {
+    min-width: fit-content;
+    margin-right: 12px;
+    line-height: 38px;
+}
+
+.o_uploadbox {
+    height: 32px;
+    padding: 0 8px;
+    background: #eee;
+    line-height: 32px;
+    margin-top: 3px;
+    font-size: 14px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    cursor: pointer;
+}
+
+.o_uploadbox+.o_uploadbox {
+    margin-left: 12px;
+}
+
+.icon_pic {
+    width: 20px;
+    height: 20px;
+    background-image: url('../../../../../assets/icon/englishVoice/icon_picture.png');
+    background-size: 100% 100%;
+    display: block;
+}
+
+.mask {
+    background-color: rgb(0 0 0 / 30%);
+    /* position: fixed; */
+    position: absolute;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 100%;
+    z-index: 90;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+}
+
+.progressBox {
+    width: 300px;
+    height: 150px;
+    background: #fff;
+    border-radius: 10px;
+    box-shadow: 0 0 6px 1px #bfbfbf;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    flex-direction: column;
+    position: relative;
+    color: #6c6c6c;
+}
+
+.progressBox>>>.el-progress-bar__outer {
+    background-color: #d1dfff !important;
+}
+
+.progressBox .lbox {
+    height: 50px;
+    font-size: 19px;
+    display: flex;
+    align-items: center;
+    color: #747474;
+}
+
+.progressBox .lbox img {
+    width: 40px;
+    margin-right: 20px;
+}
+
+.closeCss {
+    position: absolute;
+    top: 8px;
+    right: 8px;
+    cursor: pointer;
+    width: 20px;
+    height: 20px;
+}
+
+.closeCss>img {
+    width: 100%;
+    height: 100%;
+}
+
+
+.o_uploadbox_img {
+    width: 100px;
+    height: 100px;
+    border-radius: 5px;
+    position: relative;
+    overflow: hidden;
+}
+
+.o_uploadbox_img>img {
+    width: 100%;
+    height: 100%;
+    object-fit: cover;
+}
+
+.o_uploadbox_img:hover .pic_mask {
+    display: flex;
+}
+
+.pic_mask {
+    position: absolute;
+    width: 100%;
+    height: 100%;
+    background: rgba(0, 0, 0, .3);
+    flex-direction: column;
+    justify-content: center;
+    align-items: center;
+    top: 0;
+    left: 0;
+    color: #458dff;
+    display: none;
+    border-radius: 5px;
+}
+
+.pic_mask>span {
+    cursor: pointer;
+    font-size: 14px;
+    color: #fff;
+}
+
+.pic_mask>span+span {
+    margin-top: 10px;
+}</style>

+ 528 - 0
src/components/pages/EnglishVoice/component/component/testRole.vue

@@ -0,0 +1,528 @@
+<template>
+    <el-dialog title="对话测试" width="400px" :visible.sync="dataDialog" :append-to-body="true" :before-close="handleClose"
+        class="dialog_diy">
+        <div>
+            <div class="dialog_content">
+                <div class="dialog" v-for="(item, index) in answerArray" :key="index" :class="{ dialog_right: item.isY }">
+                    <div class="d_img">
+                        <img :src="item.img ? item.img : require('../../../../../assets/icon/englishVoice/icon_portal.png')"
+                            alt="">
+                    </div>
+                    <div class="d_content">
+                        <div class="d_name" v-if="item.name">{{ item.name }}</div>
+                        <div class="d_voice" v-if="item.voice">
+                            <mini-audio :audio-source="item.voice" class="audio_class"></mini-audio>
+                        </div>
+                        <div class="d_log" v-if="item.content">{{ item.content }}</div>
+                    </div>
+                </div>
+            </div>
+            <div class="dialog_answer" v-loading="isloading">
+                <span v-if="isRecord">正在录音中,再次点击话筒停止录音...</span>
+                <!-- -->
+                <img src="../../../../../assets/icon/englishVoice/icon_voice.png" alt=""  @click="startRecorder">
+                <input type="file" style="display: none;" @change="fileChange">
+            </div>
+            <iframe allow="camera *; microphone *;display-capture;midi;encrypted-media;"
+                src="https://beta.cloud.cocorobo.cn/browser/public/index.html" ref="iiframe" style="display: none;"></iframe>
+        </div>
+    </el-dialog>
+</template>
+    
+<script>
+import Recorder from "js-audio-recorder";
+const lamejs = require("lamejs");
+
+const recorder = new Recorder({
+    sampleBits: 16, // 采样位数,支持 8 或 16,默认是16
+    sampleRate: 48000, // 采样率,支持 11025、16000、22050、24000、44100、48000,根据浏览器默认值,我的chrome是48000
+    numChannels: 1 // 声道,支持 1 或 2, 默认是1
+    // compiling: false,(0.x版本中生效,1.x增加中) // 是否边录边转换,默认是false
+});
+
+// 绑定事件-打印的是当前录音数据
+recorder.onprogress = function (params) {
+    // console.log('--------------START---------------')
+    // console.log('录音时长(秒)', params.duration);
+    // console.log('录音大小(字节)', params.fileSize);
+    // console.log('录音音量百分比(%)', params.vol);
+    // console.log('当前录音的总数据([DataView, DataView...])', params.data);
+    // console.log('--------------END---------------')
+};
+export default {
+    components: {
+    },
+    props: {
+        dataDialog: {
+            type: Boolean,
+            default: false
+        },
+        checkJson: {
+            type: Object,
+        }
+    },
+    data() {
+        return {
+            json: [],
+            answerArray: [],
+            isRecord: false,
+            isPlayerRecord: false,
+            isloading: false,
+            id: this.guid()
+        };
+    },
+    methods: {
+        handleClose(done) {
+            this.close();
+            done();
+        },
+        close() {
+            this.$emit("update:dataDialog", false);
+        },
+        close2() {
+            this.$emit("update:dataDialog", false);
+        },
+        confirm() {
+            this.close2();
+        },
+        setVoiceJson(val) {
+            let a = JSON.parse(JSON.stringify(val));
+            this.json = a;
+            this.answerArray = []
+            this.answerArray.push(
+                {
+                    isY: false,
+                    content: a.content3,
+                    name: a.content,
+                    img: a.img
+                }
+            )
+            // let iiframe = this.$refs['iiframe']
+            // .doPronunciationAssessmentOnceAsync()
+            // console.log(iiframe);
+            // this.answerArray.push(
+            //     {
+            //         isY: true,
+            //         content: a.content3,
+            //         name: a.content,
+            //     }
+            // )
+            if(this.dataDialog){
+                this.createRole(a.content2, a.content)
+            }
+        },
+        answerCode(msg) {
+            var _this = this;
+            _this.ajax.post('https://gpt4.cocorobo.cn/assistants_completion_response', {
+                uid: _this.id,
+                message: msg,
+            }).then(function (response) {
+                console.log(response);
+                _this.answerArray.push(
+                    {
+                        isY: false,
+                        content: response.data.FunctionResponse,
+                        name: _this.answerArray[0].name,
+                        img: _this.answerArray[0].img
+                    }
+                )
+                _this.isloading = false
+            }).catch(function (error) {
+                _this.isloading = false
+                console.log(error);
+            });
+        },
+        // 开始录音
+        startRecorder() {
+            let _this = this;
+            if (!_this.isRecord) {
+                recorder.destroy(); // 销毁录音
+                _this.isRecord = true;
+                recorder.start().then(
+                    () => { },
+                    (error) => {
+                        _this.isRecord = false;
+                        // _this.$message.error(`${error.name} : ${error.message}`);
+                        _this.$message.error(`没有找到可使用的麦克风,或者您没有允许此网页使用麦克风`);
+                        // 出错了
+                        console.log(`${error.name} : ${error.message}`);
+                    }
+                );
+
+            } else {
+                _this.isRecord = false;
+                recorder.stop(); // 结束录音
+                this.getMp3Data()
+            }
+        },
+
+        // 录音播放
+        playRecorder() {
+            if (!recorder.fileSize) {
+                return;
+            }
+            if (!this.isPlayerRecord) {
+                this.isPlayerRecord = true;
+                recorder.play();
+            } else {
+                this.isPlayerRecord = false;
+                recorder.stopPlay(); // 停止录音播放
+            }
+            recorder.onplayend = () => {
+                this.isPlayerRecord = false;
+                console.log("onplayend");
+            };
+        },
+        addImg(e) {
+            var el = e.currentTarget.parentElement;
+            el.getElementsByTagName("input")[0].click();
+            e.target.value = "";
+        },
+        fileChange(event) {
+            let audioFile = event.target
+            console.log(audioFile.files[0]);
+            let iiframe = this.$refs['iiframe']
+            // iiframe.contentWindow.doPronunciationAssessmentOnceAsync('', { files: [audioFile] })
+            let _this = this
+            window.onRecognizedResult = function (e) {
+                console.log('onRecognizedResult', e);
+                let privText = e.privText
+                // e.privText 
+                // JSON.parse(e.privJson).NBest[0].PronunciationAssessment
+
+                _this.beforeUpload1(audioFile.files[0], 3, privText);
+            }
+            iiframe.contentWindow.doContinuousPronunciationAssessment('', audioFile)
+        },
+        /**
+         * 文件格式转换 wav-map3
+         * */
+        getMp3Data() {
+            if (!recorder.fileSize) {
+                this.$message.error("请录音后在上传语音");
+                return;
+            }
+            
+            const mp3Blob = recorder.getWAVBlob();
+            // const mp3Blob = this.convertToMp3(recorder.getWAV());
+            let audioFile = this.dataURLtoAudio(mp3Blob, "name.wav");
+            console.log(audioFile);
+            let iiframe = this.$refs['iiframe']
+            // iiframe.contentWindow.doPronunciationAssessmentOnceAsync('', { files: [audioFile] })
+            let _this = this
+            window.onRecognizedResult = function (e) {
+                console.log('onRecognizedResult', e);
+                let privText = e.privText
+                // e.privText 
+                // JSON.parse(e.privJson).NBest[0].PronunciationAssessment
+
+                _this.beforeUpload1(audioFile, 3, privText);
+            }
+            iiframe.contentWindow.doContinuousPronunciationAssessment('', { files: [audioFile] })
+            
+            _this.isloading = true
+
+            // recorder.download(mp3Blob, "recorder", "mp3");
+        },
+        convertToMp3(wavDataView) {
+            // 获取wav头信息
+            const wav = lamejs.WavHeader.readHeader(wavDataView); // 此处其实可以不用去读wav头信息,毕竟有对应的config配置
+            const { channels, sampleRate } = wav;
+            const mp3enc = new lamejs.Mp3Encoder(channels, sampleRate, 128);
+            // 获取左右通道数据
+            const result = recorder.getChannelData();
+            const buffer = [];
+            const leftData =
+                result.left &&
+                new Int16Array(result.left.buffer, 0, result.left.byteLength / 2);
+            const rightData =
+                result.right &&
+                new Int16Array(result.right.buffer, 0, result.right.byteLength / 2);
+            const remaining = leftData.length + (rightData ? rightData.length : 0);
+            const maxSamples = 1152;
+            for (let i = 0; i < remaining; i += maxSamples) {
+                const left = leftData.subarray(i, i + maxSamples);
+                let right = null;
+                let mp3buf = null;
+                if (channels === 2) {
+                    right = rightData.subarray(i, i + maxSamples);
+                    mp3buf = mp3enc.encodeBuffer(left, right);
+                } else {
+                    mp3buf = mp3enc.encodeBuffer(left);
+                }
+                if (mp3buf.length > 0) {
+                    buffer.push(mp3buf);
+                }
+            }
+
+            const enc = mp3enc.flush();
+            if (enc.length > 0) {
+                buffer.push(enc);
+            }
+            return new Blob(buffer, { type: "audio/wav" });
+        },
+        dataURLtoAudio(blob, filename) {
+            return new File([blob], filename, { type: "audio/wav" });
+        },
+        beforeUpload1(event, type, privText) {
+            var file;
+            if (type == 3) {
+                file = event;
+            } else {
+                file = event.target.files[0];
+            }
+            var credentials = {
+                accessKeyId: "AKIATLPEDU37QV5CHLMH",
+                secretAccessKey: "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",
+            }; //秘钥形式的登录上传
+            window.AWS.config.update(credentials);
+            window.AWS.config.region = "cn-northwest-1"; //设置区域
+
+            var bucket = new window.AWS.S3({ params: { Bucket: "ccrb" } }); //选择桶
+            var _this = this;
+
+            if (file) {
+                var params = {
+                    Key:
+                        file.name.split(".")[0] +
+                        new Date().getTime() +
+                        "." +
+                        file.name.split(".")[file.name.split(".").length - 1],
+                    ContentType: file.type,
+                    Body: file,
+                    "Access-Control-Allow-Credentials": "*",
+                    ACL: "public-read",
+                }; //key可以设置为桶的相抵路径,Body为文件, ACL最好要设置
+                var options = {
+                    partSize: 2048 * 1024 * 1024,
+                    queueSize: 2,
+                    leavePartsOnError: true,
+                };
+                bucket
+                    .upload(params, options)
+                    .on("httpUploadProgress", function (evt) {
+                        //这里可以写进度条
+                        // console.log("Uploaded : " + parseInt((evt.loaded * 80) / evt.total) + '%');
+                        // _this.progress = parseInt((evt.loaded * 80) / evt.total);
+                    })
+                    .send(function (err, data) {
+                        // _this.progress = 100;
+                        if (err) {
+                            // var a = _this.$refs.upload1.uploadFiles;
+                            // a.splice(a.length - 1, a.length);
+                            _this.$message.error("上传失败");
+                        } else {
+                            if (type == 3) {
+                                // _this.LuAudioUrl = data.Location;
+                                _this.answerArray.push(
+                                    {
+                                        isY: true,
+                                        content: privText,
+                                        voice: data.Location,
+                                        name: '',
+                                        img: ''
+                                    }
+                                )
+                                _this.answerCode(privText)
+                            }
+                            console.log(data.Location);
+                        }
+                    });
+            }
+        },
+        guid() {
+            var _num,
+                i,
+                _guid = "";
+            for (i = 0; i < 32; i++) {
+                _guid += Math.floor(Math.random() * 16).toString(16); //随机0  - 16 的数字 转变为16进制的字符串
+                _num = Math.floor((i - 7) / 4); //计算 (i-7)除4
+                if (_num > -1 && _num < 4 && i == 7 + 4 * _num) {
+                    //会使guid中间加 "-"   形式为xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+                    _guid += "-";
+                }
+            }
+            return _guid;
+        },
+        createRole(content, name) {
+            var _this = this;
+            _this.ajax.post('https://gpt4.cocorobo.cn/create_free_assistants', {
+                fileName: [],
+                url: [],
+                uid: _this.id,
+                instructions: content,
+                assistantName: name
+            }).then(function (response) {
+                console.log(response);
+            }).catch(function (error) {
+                console.log(error);
+            });
+        }
+    },
+    watch: {
+        dataDialog: {
+            handler: function (newVal, oldVal) {
+                if (newVal) {
+                    this.setVoiceJson(this.checkJson);
+                }
+            },
+            deep: true
+        }
+    },
+    mounted() {
+        this.setVoiceJson(this.checkJson);
+    }
+};
+</script>
+    
+<style scoped>
+.dialog_diy>>>.el-dialog {
+    /* width: 100%; */
+    /* max-width: 1000px; */
+    /* height: 100%; */
+    /* margin: 0vh auto !important; */
+}
+
+.dialog_diy>>>.el-dialog__header {
+    background: #454545 !important;
+    padding: 15px;
+}
+
+.dialog_diy>>>.el-dialog__body {
+    /* height: calc(100% - 54px); */
+    box-sizing: border-box;
+    padding: 15px;
+}
+
+.dialog_diy>>>.el-dialog__title {
+    color: #fff;
+}
+
+.dialog_diy>>>.el-dialog__headerbtn {
+    top: 19px;
+}
+
+.dialog_diy>>>.el-dialog__headerbtn .el-dialog__close {
+    color: #fff;
+}
+
+.dialog_diy>>>.el-dialog__headerbtn .el-dialog__close:hover {
+    color: #fff;
+}
+
+.dialog_diy>>>.el-dialog__body,
+.dialog_diy>>>.el-dialog__footer {
+    background: #f0f4fa;
+    overflow: hidden;
+}
+
+
+.dialog_content {
+    height: 500px;
+    background: #fff;
+    width: 100%;
+    padding: 10px;
+    box-sizing: border-box;
+    border-radius: 4px;
+    overflow: auto;
+}
+
+.dialog_answer {
+    height: 45px;
+    background: #fff;
+    width: 100%;
+    padding: 10px;
+    box-sizing: border-box;
+    margin-top: 10px;
+    display: flex;
+    align-items: center;
+    border-radius: 4px;
+}
+
+.dialog_answer>img {
+    height: 100%;
+    margin-left: auto;
+    cursor: pointer;
+}
+
+
+.dialog {
+    display: flex;
+}
+
+.dialog+.dialog {
+    margin-top: 15px;
+}
+
+.dialog_right {
+    flex-direction: row-reverse;
+}
+
+.dialog>.d_img {
+    width: 35px;
+    height: 35px;
+    min-width: 35px;
+    overflow: hidden;
+    border-radius: 50%;
+    margin-right: 5px;
+}
+
+.dialog>.d_img>img {
+    width: 100%;
+    height: 100%;
+    object-fit: cover;
+}
+
+.dialog_right>.d_img {
+    margin-right: 0;
+    margin-left: 5px;
+}
+
+.dialog>.d_content {
+    width: 100%;
+}
+
+.dialog>.d_content>.d_name {
+    color: #7C7C7C;
+    font-size: 12px;
+    margin-bottom: 5px;
+}
+
+.dialog_right>.d_content>.d_name {
+    text-align: right;
+}
+
+.dialog>.d_content>.d_log {
+    color: #000;
+    font-size: 14px;
+    padding: 5px;
+    background: #d9e7fe;
+    border-radius: 4px;
+}
+
+.dialog>.d_content>.d_voice {
+    width: 100%;
+}
+.dialog>.d_content>.d_voice + .d_log{
+    margin-top: 10px;
+}
+.audio_class {
+    background: #3680fb !important;
+    margin: 0 !important;
+    width: 100% !important;
+    box-sizing: border-box !important;
+}
+
+.d_voice>>>.vueAudioBetter span:before {
+    color: #fff;
+}
+
+.audio_class>>>.slider .process {
+    background: #000;
+}
+
+.d_voice>>>.vueAudioBetter .iconfont:active {
+    position: unset !important;
+}
+</style>
+    

+ 298 - 0
src/components/pages/EnglishVoice/component/component/theme.vue

@@ -0,0 +1,298 @@
+<template>
+    <div class="o_box">
+        <div class="o_content">
+            <span>输入题目</span>
+            <textarea v-autoHeight="38" rows="1" class="binfo_input binfo_textarea" cols v-model="checkJson.content"
+                placeholder="主题陈述" @change="setJson"></textarea>
+        </div>
+        <div class="o_content">
+            <span>输入要点</span>
+            <textarea v-autoHeight="38" rows="1" class="binfo_input binfo_textarea" cols v-model="checkJson.content2"
+                placeholder="请输入对该问题得要点" @change="setJson"></textarea>
+        </div>
+        <!-- <div class="o_content">
+            <span>准备时间</span>
+            <el-input v-model="checkJson.rTime" placeholder="请输入准备时间" style="width: 150px"  @change="numberPan('rTime')"></el-input>
+            <span style="margin-left: 10px;">min</span>
+        </div> -->
+        <div class="o_content">
+            <span>演讲时间</span>
+            <el-input v-model="checkJson.oTime" placeholder="请输入演讲时间" style="width: 150px"  @change="numberPan('oTime')"></el-input>
+            <span style="margin-left: 10px;">min</span>
+            <!-- <textarea v-autoHeight="38" rows="1" class="binfo_input binfo_textarea" cols v-model="checkJson.content2"
+                placeholder="请输入演讲时间" @change="setJson"></textarea> -->
+        </div>
+        <!-- <div class="o_content">
+            <span>添加图片</span>
+            <div class="o_uploadbox_img" v-if="checkJson.img">
+              <div class="pic_mask">
+                <span @click="checkImg(checkJson.img)">查看</span>
+                <span @click="deleteImg()">删除</span>
+              </div>
+              <img :src="checkJson.img" alt="">
+            </div>
+            <div class="o_uploadbox" v-if="!checkJson.img" @click="getImg()">智能获取</div>
+            <div class="o_uploadbox" style="padding: 0 6px;" @click="addImg($event)" v-if="!checkJson.img">
+                <span class="icon_pic"></span>
+                <input type="file" accept="image/*" style="display: none" @change="beforeUpload($event)" />
+            </div>
+        </div>
+        <div v-if="proVisible" class="mask">
+            <div class="progressBox">
+                <div class="lbox">
+                    <img src="../../../../../assets/loading.gif" />上传中,请稍后
+                </div>
+                <div style="margin-bottom: 10px">
+                    <span>{{
+                        isFinishSize
+                    }}M</span>
+                    /
+                    <span>{{
+                        isAllSize
+                    }}M</span>
+                </div>
+                <el-progress :text-inside="true" :stroke-width="20" :percentage="progress
+                    ? progress
+                    : 0
+                    " style="width: 80%"></el-progress>
+            </div>
+        </div>
+        <gpt-img :sysPicVisible.sync="sysPicVisible" :value="checkJson.content"></gpt-img> -->
+    </div>
+</template>
+
+<script>
+import minxin from './minxins/minxin';
+export default {
+    mixins: [minxin],
+    props: {
+        cjson: {
+            type: Object,
+        },
+    },
+    data() {
+        return {
+            checkJson: {}
+        }
+    },
+    methods: {
+        setJson() {
+            this.$emit('setJson', this.checkJson)
+        },
+        numberPan(time) {
+            if (!(/^-?\d+(\.\d+)?$/.test(this.checkJson[time])) || this.checkJson[time] <= 0) {
+                this.$message.error('请输入大于0的数字')
+                this.checkJson[time] = 1
+            }else if(!this.checkJson[time]){
+                this.$message.error('请输入大于0的数字')
+                this.checkJson[time] = 1
+            }
+            this.$emit('setJson', this.checkJson)
+        },
+    },
+    watch: {
+        cjson: {
+            handler: function (newVal, oldVal) {
+                this.checkJson = this.depthCopy(newVal);
+            },
+            deep: true,
+        },
+        imgUrl: {
+            handler: function (newVal, oldVal) {
+                this.checkJson.img = newVal
+                this.$forceUpdate()
+                this.$emit('setJson', this.checkJson)
+            },
+            deep: true,
+        },
+    },
+    mounted() {
+        this.checkJson = this.depthCopy(this.cjson);
+    }
+}
+</script>
+
+<style scoped>
+.o_box {
+    width: 100%;
+    box-sizing: border-box;
+    padding: 12px 16px 12px 48px;
+    background: #f5f6f7;
+    position: relative;
+}
+
+.binfo_input {
+    width: 100%;
+    margin: 0;
+    padding: 8px;
+    display: block;
+    min-width: 0;
+    outline: none;
+    box-sizing: border-box;
+    background: none;
+    border: none;
+    border-radius: 4px;
+    background: #fff;
+    font-size: 16px;
+    resize: none;
+    font-family: 'Microsoft YaHei';
+    min-height: 38px;
+    /* border: 1px solid #3682fc00; */
+    border: 1.5px solid #CAD1DC;
+}
+
+.binfo_textarea {
+    border: 1.5px solid #CAD1DC;
+    font-size: 14px;
+    resize: none;
+    /* background: #f6f6f6; */
+    font-family: 'Microsoft YaHei';
+}
+
+.binfo_input:focus-visible {
+    border: 1.5px solid #3681FC !important;
+}
+
+.o_content {
+    display: flex;
+    color: #000;
+    font-size: 14px;
+}
+
+.o_content+.o_content {
+    margin-top: 10px;
+}
+
+.o_content>span {
+    min-width: fit-content;
+    margin-right: 12px;
+    line-height: 38px;
+}
+
+.o_uploadbox {
+    height: 32px;
+    padding: 0 8px;
+    background: #eee;
+    line-height: 32px;
+    margin-top: 3px;
+    font-size: 14px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    cursor: pointer;
+}
+
+.o_uploadbox+.o_uploadbox {
+    margin-left: 12px;
+}
+
+.icon_pic {
+    width: 20px;
+    height: 20px;
+    background-image: url('../../../../../assets/icon/englishVoice/icon_picture.png');
+    background-size: 100% 100%;
+    display: block;
+}
+
+.mask {
+    background-color: rgb(0 0 0 / 30%);
+    /* position: fixed; */
+    position: absolute;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 100%;
+    z-index: 90;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+}
+
+.progressBox {
+    width: 300px;
+    height: 150px;
+    background: #fff;
+    border-radius: 10px;
+    box-shadow: 0 0 6px 1px #bfbfbf;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    flex-direction: column;
+    position: relative;
+    color: #6c6c6c;
+}
+
+.progressBox>>>.el-progress-bar__outer {
+    background-color: #d1dfff !important;
+}
+
+.progressBox .lbox {
+    height: 50px;
+    font-size: 19px;
+    display: flex;
+    align-items: center;
+    color: #747474;
+}
+
+.progressBox .lbox img {
+    width: 40px;
+    margin-right: 20px;
+}
+
+.closeCss {
+    position: absolute;
+    top: 8px;
+    right: 8px;
+    cursor: pointer;
+    width: 20px;
+    height: 20px;
+}
+
+.closeCss>img {
+    width: 100%;
+    height: 100%;
+}
+
+
+.o_uploadbox_img {
+    width: 100px;
+    height: 100px;
+    border-radius: 5px;
+    position: relative;
+    overflow: hidden;
+}
+
+.o_uploadbox_img>img {
+    width: 100%;
+    height: 100%;
+    object-fit: cover;
+}
+
+.o_uploadbox_img:hover .pic_mask {
+    display: flex;
+}
+
+.pic_mask {
+    position: absolute;
+    width: 100%;
+    height: 100%;
+    background: rgba(0, 0, 0, .3);
+    flex-direction: column;
+    justify-content: center;
+    align-items: center;
+    top: 0;
+    left: 0;
+    color: #458dff;
+    display: none;
+    border-radius: 5px;
+}
+
+.pic_mask>span {
+    cursor: pointer;
+    font-size: 14px;
+    color: #fff;
+}
+
+.pic_mask>span+span {
+    margin-top: 10px;
+}</style>

+ 274 - 0
src/components/pages/EnglishVoice/component/component/word.vue

@@ -0,0 +1,274 @@
+<template>
+    <div class="o_box">
+        <div class="o_content">
+            <span>输入内容</span>
+            <textarea v-autoHeight="38" rows="1" class="binfo_input binfo_textarea" cols v-model="checkJson.content"
+                placeholder="单词/词组" @change="setJson"></textarea>
+        </div>
+        <div class="o_content">
+            <span>添加图片</span>
+            <div class="o_uploadbox_img" v-if="checkJson.img">
+                <div class="pic_mask">
+                    <span @click="checkImg(checkJson.img)">查看</span>
+                    <span @click="deleteImg()">删除</span>
+                </div>
+                <img :src="checkJson.img" alt="">
+            </div>
+            <div class="o_uploadbox" v-if="!checkJson.img" @click="getImg()">智能获取</div>
+            <div class="o_uploadbox" style="padding: 0 6px;" @click="addImg($event)" v-if="!checkJson.img">
+                <span class="icon_pic"></span>
+                <input type="file" accept="image/*" style="display: none" @change="beforeUpload($event)" />
+            </div>
+        </div>
+        <div v-if="proVisible" class="mask">
+            <div class="progressBox">
+                <div class="lbox">
+                    <img src="../../../../../assets/loading.gif" />上传中,请稍后
+                </div>
+                <div style="margin-bottom: 10px">
+                    <span>{{
+                        isFinishSize
+                    }}M</span>
+                    /
+                    <span>{{
+                        isAllSize
+                    }}M</span>
+                </div>
+                <el-progress :text-inside="true" :stroke-width="20" :percentage="progress
+                    ? progress
+                    : 0
+                    " style="width: 80%"></el-progress>
+            </div>
+        </div>
+        <gpt-img :sysPicVisible.sync="sysPicVisible" :value="checkJson.content" @setImg="setImg"></gpt-img>
+    </div>
+</template>
+
+<script>
+import minxin from './minxins/minxin';
+export default {
+    mixins: [minxin],
+    props: {
+        cjson: {
+            type: Object,
+        },
+    },
+    data() {
+        return {
+            checkJson: {},
+        }
+    },
+    methods: {
+        setJson() {
+            this.$emit('setJson', this.checkJson)
+        },
+        setImg(url){
+            this.checkJson.img = url
+            this.$emit('setJson', this.checkJson)
+        }
+    },
+    watch: {
+        cjson: {
+            handler: function (newVal, oldVal) {
+                this.checkJson = this.depthCopy(newVal);
+            },
+            deep: true,
+        },
+        imgUrl: {
+            handler: function (newVal, oldVal) {
+                this.checkJson.img = newVal
+                this.$forceUpdate()
+                this.$emit('setJson', this.checkJson)
+            },
+            deep: true,
+        },
+    },
+    mounted() {
+        this.checkJson = this.depthCopy(this.cjson);
+    }
+}
+</script>
+
+<style scoped>
+.o_box {
+    width: 100%;
+    box-sizing: border-box;
+    padding: 12px 16px 12px 48px;
+    background: #f5f6f7;
+    position: relative;
+}
+
+.binfo_input {
+    width: 100%;
+    margin: 0;
+    padding: 8px;
+    display: block;
+    min-width: 0;
+    outline: none;
+    box-sizing: border-box;
+    background: none;
+    border: none;
+    border-radius: 4px;
+    background: #fff;
+    font-size: 16px;
+    resize: none;
+    font-family: 'Microsoft YaHei';
+    min-height: 38px;
+    /* border: 1px solid #3682fc00; */
+    border: 1.5px solid #CAD1DC;
+}
+
+.binfo_textarea {
+    border: 1.5px solid #CAD1DC;
+    font-size: 14px;
+    resize: none;
+    /* background: #f6f6f6; */
+    font-family: 'Microsoft YaHei';
+}
+
+.binfo_input:focus-visible {
+    border: 1.5px solid #3681FC !important;
+}
+
+.o_content {
+    display: flex;
+    color: #000;
+    font-size: 14px;
+}
+
+.o_content+.o_content {
+    margin-top: 10px;
+}
+
+.o_content>span {
+    min-width: fit-content;
+    margin-right: 12px;
+    line-height: 38px;
+}
+
+.o_uploadbox {
+    height: 32px;
+    padding: 0 8px;
+    background: #eee;
+    line-height: 32px;
+    margin-top: 3px;
+    font-size: 14px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    cursor: pointer;
+}
+
+.o_uploadbox+.o_uploadbox {
+    margin-left: 12px;
+}
+
+.icon_pic {
+    width: 20px;
+    height: 20px;
+    background-image: url('../../../../../assets/icon/englishVoice/icon_picture.png');
+    background-size: 100% 100%;
+    display: block;
+}
+
+.mask {
+    background-color: rgb(0 0 0 / 30%);
+    /* position: fixed; */
+    position: absolute;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 100%;
+    z-index: 90;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+}
+
+.progressBox {
+    width: 300px;
+    height: 150px;
+    background: #fff;
+    border-radius: 10px;
+    box-shadow: 0 0 6px 1px #bfbfbf;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    flex-direction: column;
+    position: relative;
+    color: #6c6c6c;
+}
+
+.progressBox>>>.el-progress-bar__outer {
+    background-color: #d1dfff !important;
+}
+
+.progressBox .lbox {
+    height: 50px;
+    font-size: 19px;
+    display: flex;
+    align-items: center;
+    color: #747474;
+}
+
+.progressBox .lbox img {
+    width: 40px;
+    margin-right: 20px;
+}
+
+.closeCss {
+    position: absolute;
+    top: 8px;
+    right: 8px;
+    cursor: pointer;
+    width: 20px;
+    height: 20px;
+}
+
+.closeCss>img {
+    width: 100%;
+    height: 100%;
+}
+
+.o_uploadbox_img {
+    width: 100px;
+    height: 100px;
+    border-radius: 5px;
+    position: relative;
+    overflow: hidden;
+}
+
+.o_uploadbox_img>img {
+    width: 100%;
+    height: 100%;
+    object-fit: cover;
+}
+
+.o_uploadbox_img:hover .pic_mask {
+    display: flex;
+}
+
+.pic_mask {
+    position: absolute;
+    width: 100%;
+    height: 100%;
+    background: rgba(0, 0, 0, .3);
+    flex-direction: column;
+    justify-content: center;
+    align-items: center;
+    top: 0;
+    left: 0;
+    color: #458dff;
+    display: none;
+    border-radius: 5px;
+}
+
+.pic_mask>span {
+    cursor: pointer;
+    font-size: 14px;
+    color: #fff;
+}
+
+.pic_mask>span+span {
+    margin-top: 10px;
+}</style>

+ 308 - 12
src/components/pages/EnglishVoice/component/order.vue

@@ -6,35 +6,125 @@
     </div>
     <div class="o_check_box" v-else>
       <div class="o_child" v-for="(item, index) in checkArray" :key="index">
-        <div class="o_child_title">
-          <span class="drag"></span>
-          <span class="title">{{item.content}}</span>
+        <div class="o_child_title" :class="{ active: checkType == index }" @click.stop="setCheckType(index)">
+          <span class="drag" v-if="editType == 2"></span>
+          <span class="order" v-else>{{ index + 1 }}、</span>
+          <el-tooltip :content="getType(item)" placement="top" effect="dark">
+            <!-- content to trigger tooltip here -->
+            <span class="icon"
+            :class="{ icon_word: item.type == 'word', icon_sentence: item.type == 'sentence', icon_QA: item.type == 'QA', icon_theme: item.type == 'theme', icon_createRole: item.type == 'createRole' }"></span>
+          </el-tooltip>
+          <span class="title">{{ getTitle(item) }}</span>
           <div class="edit_btn">
-            <span class="edit"></span>
-            <span class="delete"></span>
+            <button class="c_pub_button_add" @click.stop="openTest(item)" style="margin-right: 15px;"
+              v-if="editType == 2 && item.type == 'createRole' && checkType != index">角色测试</button>
+            <div class="pic" v-if="editType == 2 && item.img && checkType != index">
+              <div class="pic_mask">
+                <span class="delete" @click.stop="deleteImg(index)"></span>
+              </div>
+              <img :src="item.img" alt="">
+            </div>
+            <span class="edit" v-if="editType == 2 && checkType != index"></span>
+            <span :class="{ delete: editType == 2, delete2: editType == 1 }" @click.stop="deleteJ(index)"></span>
           </div>
         </div>
+        <div class="o_edit_box" v-if="checkType == index && editType == 2">
+          <qa :cjson="item" v-if="item.type == 'QA'" @setJson="setJson"></qa>
+          <sentence :cjson="item" v-if="item.type == 'sentence'" @setJson="setJson"></sentence>
+          <word :cjson="item" v-if="item.type == 'word'" @setJson="setJson"></word>
+          <theme :cjson="item" v-if="item.type == 'theme'" @setJson="setJson"></theme>
+          <createRole :cjson="item" v-if="item.type == 'createRole'" @setJson="setJson" @openTest="openTest"></createRole>
+        </div>
       </div>
     </div>
+    <testRole :dataDialog.sync="dataDialog" :checkJson="Json"></testRole>
   </div>
 </template>
 
 <script>
 import minxin from '../minxins/minxin'
+import qa from './component/qa2.vue'
+import sentence from './component/sentence.vue'
+import word from './component/word.vue'
+import theme from './component/theme.vue'
+import createRole from './component/createRole.vue'
+import testRole from './component/testRole.vue'
 export default {
   mixins: [minxin],
+  components: {
+    qa,
+    sentence,
+    word,
+    theme,
+    createRole,
+    testRole
+  },
   props: {
     checkJson: {
       type: Array,
     },
-    editType:{
+    editType: {
       type: Number,
       default: 1
+    },
+    checkType: {
+      type: Number
     }
   },
   data() {
     return {
-      checkArray: []
+      checkArray: [],
+      dataDialog: false,
+      Json: {}
+    }
+  },
+  computed: {
+    // selectType() {
+    //   return function (item) {
+    //     if (item.ttype == 1) {
+    //       let className = "icon"
+    //       if (item.type == 'word') {
+    //         className += " icon_word"
+    //       } else if (item.type == 'sentence') {
+    //         className += " icon_sentence"
+    //       } else if (item.type == 'QA') {
+    //         className += " icon_QA"
+    //       }
+    //       return index + 1 + "、" + (this.editType != '2' ? `<span class='${className}'></span>` : `<span class='${className}'></span>` + item.content);
+    //     }
+    //   };
+    // },
+    getType(){
+      return function (item) {
+        if (item.type == 'word') {
+          return '单词/词组'
+        } else if (item.type == 'sentence') {
+          return '句子/短文'
+        } else if (item.type == 'QA') {
+          return '问题'
+        } else if (item.type == 'theme') {
+          return '主题陈述'
+        } else if (item.type == 'createRole') {
+          return '角色对话'
+        }
+      }
+    },
+    getTitle() {
+      return function (item) {
+        if (item.type == 'word' && !item.content) {
+          return '单词/词组'
+        } else if (item.type == 'sentence' && !item.content) {
+          return '句子/短文'
+        } else if (item.type == 'QA' && !item.content) {
+          return '问题'
+        } else if (item.type == 'theme' && !item.content) {
+          return '主题陈述'
+        } else if (item.type == 'createRole' && !item.content) {
+          return '角色对话'
+        } else {
+          return item.content
+        }
+      }
     }
   },
   watch: {
@@ -45,7 +135,66 @@ export default {
       deep: true,
     },
   },
-  mounted(){
+  methods: {
+    setCheckType(index) {
+      console.log(index);
+      let _index = index
+      if (this.checkType == index) {
+        _index = -1
+      }
+      this.$emit('update:checkType', _index);
+    },
+    setJson(val) {
+      this.checkArray[this.checkType] = val
+      this.$forceUpdate()
+      this.$emit('setJson', this.checkArray)
+    },
+    deleteJ(index) {
+      this.$confirm('确定删除该题目吗?', "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning",
+      })
+        .then(() => {
+          this.checkArray.splice(index, 1)
+          this.$forceUpdate()
+          this.$emit('setJson', this.checkArray)
+        })
+        .catch(() => { });
+    },
+    deleteImg(index) {
+      this.$confirm('确定删除该题目的图片吗?', "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning",
+      })
+        .then(() => {
+          this.checkArray[index].img = ''
+          this.$forceUpdate()
+          this.$emit('setJson', this.checkArray)
+        })
+    },
+    openTest(json) {
+      if (json.content == '') {
+        this.$message.error(`请输入角色名字`);
+        type = 2
+        return;
+      }
+      if (json.content2 == '') {
+        this.$message.error(`请输入角色定义`);
+        type = 2
+        return;
+      }
+      if (json.content3 == '') {
+        this.$message.error(`请输入角色问候`);
+        type = 2
+        return;
+      }
+      this.dataDialog = true
+      this.Json = json
+    }
+  },
+  mounted() {
     this.checkArray = this.depthCopy(this.checkJson);
   }
 }
@@ -57,7 +206,7 @@ export default {
   height: auto;
 }
 
-.o_none_box{
+.o_none_box {
   width: 100%;
   height: 500px;
   background: #fff;
@@ -67,16 +216,163 @@ export default {
   flex-direction: column;
 }
 
-.o_none_box > img{
+.o_none_box>img {
   width: 120px;
   height: 120px;
   object-fit: contain;
 }
 
-.o_none_box > span{
+.o_none_box>span {
   font-size: 12px;
   color: #00000066;
   margin-top: 15px;
 }
 
-</style>
+.o_check_box {
+  width: 100%;
+}
+
+.o_child {
+  width: 100%;
+}
+
+.o_child_title {
+  width: 100%;
+  display: flex;
+  height: 38px;
+  align-items: center;
+  padding: 0 16px;
+  box-sizing: border-box;
+  cursor: pointer;
+}
+
+.o_child_title.active {
+  background: #EFF0F1;
+}
+
+.o_child_title>.drag {
+  display: block;
+  background-image: url('../../../../assets/icon/test/drag_icon.png');
+  background-size: 100% 100%;
+  min-width: 16px;
+  min-height: 16px;
+  margin-right: 15px;
+  cursor: pointer;
+}
+
+.o_child_title.active>.drag {
+  background-image: url('../../../../assets/icon/test/drag_icon_active.png');
+}
+
+.o_child_title>.title {
+  width: 100%;
+  overflow: hidden;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+  max-width: 200px;
+}
+
+.o_child_title>.order {
+  line-height: 38px;
+}
+
+.o_child_title>.icon {
+  display: block;
+  background-size: 100% 100%;
+  min-width: 16px;
+  min-height: 16px;
+  margin-right: 8px;
+}
+
+.o_child_title>.icon.icon_word {
+  background-image: url('../../../../assets/icon/englishVoice/icon_check_word.png');
+}
+
+.o_child_title>.icon.icon_sentence {
+  background-image: url('../../../../assets/icon/englishVoice/icon_check_sentence.png');
+}
+
+.o_child_title>.icon.icon_QA {
+  background-image: url('../../../../assets/icon/englishVoice/icon_check_qa.png');
+}
+
+.o_child_title>.icon.icon_theme {
+  background-image: url('../../../../assets/icon/englishVoice/icon_check_theme.png');
+}
+
+.o_child_title>.icon.icon_createRole {
+  background-image: url('../../../../assets/icon/englishVoice/icon_check_addUser.png');
+}
+
+.o_child_title>.edit_btn {
+  margin-left: auto;
+  display: flex;
+  align-items: center;
+}
+
+.o_child_title>.edit_btn>.delete,
+.o_child_title>.edit_btn>.delete2,
+.o_child_title>.edit_btn>.edit {
+  display: block;
+  background-size: 100% 100%;
+  min-width: 16px;
+  min-height: 16px;
+  cursor: pointer;
+  /* margin-right: 8px; */
+}
+
+.o_child_title>.edit_btn>.edit {
+  background-image: url('../../../../assets/icon/test/add_edit_icon.png');
+  margin-right: 15px;
+}
+
+.o_child_title>.edit_btn>.delete {
+  background-image: url('../../../../assets/icon/englishVoice/icon_delete.png');
+}
+
+.o_child_title>.edit_btn>.delete2 {
+  background-image: url('../../../../assets/icon/test/delete_test_icon2.png');
+}
+
+.o_child_title>.edit_btn>.pic {
+  width: 50px;
+  overflow: hidden;
+  height: 32px;
+  margin-right: 15px;
+  border-radius: 5px;
+  cursor: pointer;
+  position: relative;
+}
+
+.o_child_title>.edit_btn>.pic>img {
+  width: 100%;
+  height: 100%;
+  object-fit: cover;
+}
+
+.o_child_title>.edit_btn>.pic>.pic_mask {
+  position: absolute;
+  width: 100%;
+  height: 100%;
+  background: rgba(0, 0, 0, .3);
+  justify-content: center;
+  align-items: center;
+  top: 0;
+  left: 0;
+  color: #458dff;
+  display: none;
+  border-radius: 5px;
+}
+
+.o_child_title>.edit_btn>.pic:hover>.pic_mask {
+  display: flex;
+}
+
+.o_child_title>.edit_btn>.pic>.pic_mask>.delete {
+  width: 15px;
+  height: 15px;
+  background-image: url('../../../../assets/icon/englishVoice/icon_delete2.png');
+  background-size: 100% 100%;
+  display: block;
+  cursor: pointer;
+}</style>

+ 149 - 38
src/components/pages/EnglishVoice/index.vue

@@ -1,17 +1,17 @@
 <template>
-      <el-dialog title="英语口语" :visible.sync="EnglishVoiceDialog" :append-to-body="true" width="100%"
+    <el-dialog title="英语口语" :visible.sync="EnglishVoiceDialog" :append-to-body="true" width="100%"
         :before-close="handleClose" class="dialog_diy">
         <div class="ev_box">
             <div class="ev_info_box">
                 <div class="title">设置英语口语信息</div>
                 <div class="ev_info_input_box">
-                    <div class="box"> 
+                    <div class="box">
                         <span class="title bi">标题</span>
-                        <el-input v-model="title" placeholder="请输入标题" class="input"/>
+                        <el-input v-model="title" placeholder="请输入标题" class="input" />
                     </div>
-                    <div class="box"> 
+                    <div class="box">
                         <span class="title">说明</span>
-                        <el-input v-model="detail" placeholder="请输入对该问题的描述" class="input"/>
+                        <el-input v-model="detail" placeholder="请输入对该问题的描述" class="input" />
                     </div>
                 </div>
             </div>
@@ -24,11 +24,11 @@
                     </div>
                     <div class="center">
                         <div class="title">评测题目</div>
-                        <order :checkJson="checkJson" @setJson="setJson" :editType="2"></order>
+                        <order :checkJson="checkJson" @setJson="setJson" :editType="2" :checkType.sync="checkType"></order>
                     </div>
                     <div class="right">
                         <div class="title">评测大纲</div>
-                        <order :checkJson="checkJson" @setJson="setJson" :editType="1"></order>
+                        <order :checkJson="checkJson" @setJson="setJson" :editType="1" :checkType.sync="checkType"></order>
                     </div>
                 </div>
             </div>
@@ -55,13 +55,18 @@ export default {
         },
         oid: {
             type: String
-        }
+        },
+        englishVoiceJson: {
+            type: Object
+        },
     },
     data() {
         return {
             checkJson: [],
-            title:'',
-            detail:'',
+            checkJson2: {},
+            title: '',
+            detail: '',
+            checkType: -1,
         }
     },
     methods: {
@@ -70,17 +75,110 @@ export default {
             done();
         },
         close() {
+            let a = {
+                title: this.title,
+                detail: this.detail,
+                array: this.checkJson
+            }
+            if (JSON.stringify(a) == JSON.stringify(this.englishVoiceJson)) {
+                this.$emit("update:EnglishVoiceDialog", false);
+            } else {
+                this
+                    .$confirm("是否保存已编辑内容?", "提示", {
+                        confirmButtonText: "保存",
+                        cancelButtonText: "不保存",
+                        type: "warning",
+                    })
+                    .then(() => {
+                        this.confirm();
+                    })
+                    .catch(() => {
+                        this.$emit("update:EnglishVoiceDialog", false);
+                    });
+            }
+        },
+        close2() {
             this.$emit("update:EnglishVoiceDialog", false);
         },
         confirm() {
-            this.close();
+            if(!this.title){
+                this.$message.error("请输入标题");
+                return;
+            }
+            if(!this.checkJson.length){
+                this.$message.error("请至少添加一道口语题目");
+                return
+            }
+            let type = 1
+            for(let i=0;i<this.checkJson.length;i++){
+                if(this.checkJson[i].content == '' && this.checkJson[i].type != 'createRole' && this.checkJson[i].type != 'theme'){
+                    this.$message.error(`第${i + 1}题请输入内容`);
+                    type = 2
+                    break;
+                }
+
+                if(this.checkJson[i].content == '' && this.checkJson[i].type == 'theme'){
+                    this.$message.error(`第${i + 1}题请输入题目`);
+                    type = 2
+                    break;
+                }
+                if(this.checkJson[i].content2 == '' && this.checkJson[i].type == 'theme'){
+                    this.$message.error(`第${i + 1}题请输入要点`);
+                    type = 2
+                    break;
+                }
+
+                if(this.checkJson[i].content == '' && this.checkJson[i].type == 'createRole'){
+                    this.$message.error(`第${i + 1}题请输入角色名字`);
+                    type = 2
+                    break;
+                }
+                if(this.checkJson[i].content2 == '' && this.checkJson[i].type == 'createRole'){
+                    this.$message.error(`第${i + 1}题请输入角色定义`);
+                    type = 2
+                    break;
+                }
+                if(this.checkJson[i].content3 == '' && this.checkJson[i].type == 'createRole'){
+                    this.$message.error(`第${i + 1}题请输入角色问候`);
+                    type = 2
+                    break;
+                }
+            }
+            if(type == 2) return
+            let a = {
+                title: this.title,
+                detail: this.detail,
+                array: this.checkJson
+            }
+            this.$emit("setEnglishVoiceJson", JSON.parse(JSON.stringify(a)));
+            this.close2();
         },
-        setJson(val){
-            debugger
+        setJson(val) {
             this.checkJson = val;
             this.$forceUpdate()
+        },
+        setVoiceJson(val) {
+            let a = JSON.parse(JSON.stringify(val));
+            this.checkJson2 = JSON.parse(JSON.stringify(a));
+            this.title = a.title;
+            this.detail = a.detail;
+            this.checkJson = a.array
+            this.checkType = -1
         }
     },
+    watch: {
+        EnglishVoiceDialog: {
+            handler: function (newVal, oldVal) {
+                if (newVal) {
+                    this.setVoiceJson(this.englishVoiceJson);
+                }
+            },
+            deep: true,
+        },
+    },
+    mounted() {
+        this.setVoiceJson(this.englishVoiceJson);
+    },
 }
 </script>
 
@@ -123,7 +221,7 @@ export default {
     overflow: hidden;
 }
 
-.ev_box{
+.ev_box {
     width: calc(100% - 20px);
     height: calc(100% - 20px);
     overflow: auto;
@@ -132,13 +230,13 @@ export default {
     border-radius: 5px;
 }
 
-.ev_info_box{
-    
-}
-.ev_info_box + .ev_info_box{
+.ev_info_box {}
+
+.ev_info_box+.ev_info_box {
     margin-top: 14px;
 }
-.ev_info_box > .title {
+
+.ev_info_box>.title {
     padding: 15px 0 15px 0;
     font-size: 16px;
     font-weight: bold;
@@ -150,7 +248,7 @@ export default {
     color: #000;
 }
 
-.ev_info_box > .title::before {
+.ev_info_box>.title::before {
     content: '';
     display: block;
     width: 3px;
@@ -160,25 +258,29 @@ export default {
     margin: 0 5px 0 0;
 }
 
-.ev_info_input_box{
+.ev_info_input_box {
     width: 100%;
     box-sizing: border-box;
     padding: 0 20px;
 }
-.ev_info_input_box > .box{
+
+.ev_info_input_box>.box {
     display: flex;
     align-items: center;
 }
-.ev_info_input_box > .box + .box{
+
+.ev_info_input_box>.box+.box {
     margin-top: 12px;
 }
-.ev_info_input_box > .box > .title{
+
+.ev_info_input_box>.box>.title {
     min-width: fit-content;
     font-size: 14px;
-    margin:0 10px;
+    margin: 0 10px;
     position: relative;
 }
-.ev_info_input_box > .box > .title.bi::before{
+
+.ev_info_input_box>.box>.title.bi::before {
     content: '*';
     color: rgb(238, 62, 62);
     display: block;
@@ -186,12 +288,13 @@ export default {
     position: absolute;
     left: -10px;
 }
-.ev_info_input_box > .box > .input{
+
+.ev_info_input_box>.box>.input {
     width: 100%;
     max-width: 750px;
 }
 
-.ev_create_box{
+.ev_create_box {
     width: 100%;
     width: calc(100% - 40px);
     border-radius: 5px;
@@ -201,41 +304,49 @@ export default {
     justify-content: space-between;
     min-height: 500px;
 }
-.ev_create_box > .left{
+
+.ev_create_box>.left {
     width: 250px;
     border-right: 1px solid #e7e7e7;
     box-sizing: border-box;
     padding: 0 16px;
 }
-.ev_create_box > .center{
+
+.ev_create_box>.center {
     width: calc(100% - 500px);
 }
-.ev_create_box > .right{
+
+.ev_create_box>.right {
     width: 250px;
     border-left: 1px solid #e7e7e7;
     box-sizing: border-box;
-    padding: 0 16px;
+    /* padding: 0 16px; */
 }
 
-.ev_create_box > .left > .title{
+.ev_create_box>.left>.title {
     font-size: 16px;
     font-weight: 700;
     color: #000;
     text-align: center;
-    margin: 20px 0;
+    height: 60px;
+    line-height: 60px;
 }
-.ev_create_box > .center > .title{
+
+.ev_create_box>.center>.title {
     font-size: 24px;
     font-weight: 700;
     color: #000;
     text-align: center;
-    margin: 16px 0;
+    height: 60px;
+    line-height: 60px;
 }
-.ev_create_box > .right > .title{
+
+.ev_create_box>.right>.title {
     font-size: 16px;
     font-weight: 700;
     color: #000;
     text-align: center;
-    margin: 20px 0;
+    height: 60px;
+    line-height: 60px;
 }
 </style>

+ 298 - 22
src/components/pages/addCourse.vue

@@ -2085,7 +2085,7 @@
                                       </div>
                                     </div> -->
                                   </div>
-                                  <!-- <div class="tool" :class="{ isToolChoose: itemTool.tool.indexOf(70) != -1 }"
+                                  <div class="tool" :class="{ isToolChoose: itemTool.tool.indexOf(70) != -1 }"
                                     @click="addTools(70, itemTaskIndex, toolIndex)">
                                     <div class="whiteBIcon" @click.stop="openTools(itemTaskIndex, 70, toolIndex)">
                                       <img src="../../assets/icon/thirdToolList/englishVoice.png" alt />
@@ -2094,7 +2094,7 @@
                                     <div class="noCTool"><img src="../../assets/icon/new/isToolC.png" alt="" /></div>
                                     <div class="isCTool" v-if="itemTool.tool.indexOf(70) != -1"><img
                                         src="../../assets/icon/new/isToolC.png" alt="" /></div>
-                                  </div> -->
+                                  </div>
                                   <!-- <div class="tool">
                                   <div class="whiteBIcon" @click="addTools(28, itemTaskIndex, toolIndex)">
                                     <img src="../../assets/icon/secondToolList/translation.png" alt />
@@ -2490,9 +2490,9 @@
                             <div class="pjCss" :style="{width:itemTask.isEvaFold?'calc(100% - 55%)':'calc(100% - 120px)'}">
                               <div v-if="itemTask.eList && itemTask.eList.length" class="elist_input">
                                 <div v-for="(eItem, eIndex) in itemTask.eList" :key="eIndex" class="elist_input_box">
-                                  <span>评价名称:</span>
-                                  <!-- <el-tooltip effect="dark" :content="itemTask.eList[eIndex].value || '填写评价名称'" placement="top" popper-class="text_tooltip2"> -->
-                                    <input type="input" v-model="itemTask.eList[eIndex].value" placeholder="填写评价名称" />
+                                  <span>评价维度:</span>
+                                  <!-- <el-tooltip effect="dark" :content="itemTask.eList[eIndex].value || '填写评价维度'" placement="top" popper-class="text_tooltip2"> -->
+                                    <input type="input" v-model="itemTask.eList[eIndex].value" placeholder="填写评价维度" />
                                   <!-- </el-tooltip> -->
                                   <!-- <span>评星等级:</span>
                                   <el-rate v-model="itemTask.eList[eIndex].score" @change="setEListStar()"
@@ -2501,14 +2501,14 @@
                                     deletEList(unitIndex, itemTaskIndex, eIndex)
                                     "></div>
                                   <div class="elist_inptu_text">
-                                    <span>评价描述:</span>
-                                    <!-- <el-tooltip effect="dark" :content="itemTask.eList[eIndex].detail || '填写评价描述'" placement="top" popper-class="text_tooltip2"> -->
-                                      <input type="input" v-model="itemTask.eList[eIndex].detail" placeholder="填写评价描述" />
+                                    <span>维度描述:</span>
+                                    <!-- <el-tooltip effect="dark" :content="itemTask.eList[eIndex].detail || '填写维度描述'" placement="top" popper-class="text_tooltip2"> -->
+                                      <input type="input" v-model="itemTask.eList[eIndex].detail" placeholder="填写维度描述" />
                                     <!-- </el-tooltip> -->
                                   </div>
                                   <div class="elist_inptu_text" v-if="evalua">
                                     <span>目标:</span>
-                                    <!-- <input type="input" v-model="itemTask.eList[eIndex].target" placeholder="填写评价描述" /> -->
+                                    <!-- <input type="input" v-model="itemTask.eList[eIndex].target" placeholder="填写维度描述" /> -->
                                     <!-- <el-select v-model="itemTask.eList[eIndex].target" placeholder="请选择目标"
                                 @change="forceUpdate()">
                                 <el-option v-for="(e, eIndex) in targetArray" :key="eIndex" :label="e.name"
@@ -2528,11 +2528,16 @@
                                 <div>添加</div>
                               </div> -->
                               <div class="eva_btn_box">
-                                <button class="c_pub_button_add pub_btn_eval_img" @click="addEList(unitIndex, itemTaskIndex)">
+                                <div class="eva_btn_left_box">
+                                  <button class="c_pub_button_add pub_btn_eval_img" @click="addEList(unitIndex, itemTaskIndex)">
                                     添加
-                                </button>
-                                <button class="c_pub_button_add pub_btn_eval_source_img" @click="openEList(unitIndex, itemTaskIndex)">
+                                  </button>
+                                  <button class="c_pub_button_add pub_btn_eval_source_img" @click="openEList(unitIndex, itemTaskIndex)">
                                     资源
+                                  </button>
+                                </div>
+                                <button class="c_pub_button_add" @click="addCET(unitIndex, itemTaskIndex)"  v-if="itemTask.eList && itemTask.eList.length">
+                                    添加资源模板
                                 </button>
                               </div>
                             </div>
@@ -3516,7 +3521,7 @@
           <div v-if="rateJson.length" class="elist_input" style="height: 360px; overflow: auto">
             <div v-for="(eItem, eIndex) in rateJson" :key="eIndex" class="elist_input_box">
               <span style="min-width: 100px; text-align: right">个人评价指标:</span>
-              <input type="input" v-model="eItem.value" placeholder="填写评价名称" />
+              <input type="input" v-model="eItem.value" placeholder="填写评价维度" />
               <div class="remove" @click="deletRateList(eIndex)"></div>
               <div style="width: 100%; display: flex">
                 <span style="min-width: 100px; text-align: right">评星等级:</span>
@@ -3524,7 +3529,7 @@
               </div>
               <div class="elist_inptu_text" style="align-items: flex-start">
                 <span style="min-width: 100px; text-align: right">描述:</span>
-                <textarea class="rate_textarea" :rows="3" v-model="eItem.detail" placeholder="填写评价描述"></textarea>
+                <textarea class="rate_textarea" :rows="3" v-model="eItem.detail" placeholder="填写维度描述"></textarea>
               </div>
             </div>
           </div>
@@ -3907,8 +3912,56 @@
         <el-button type="primary" @click="updateChange">确定</el-button>
       </span>
     </el-dialog>
-    <evaBox :oid='oid' :org="org" :dialogVisibleEva.sync="evaBoxDialog" @updateEvaJson="updateEvaJson"></evaBox>
-    <EnglishVoice :oid='oid' :org="org" :EnglishVoiceDialog.sync="EnglishVoiceDialog"></EnglishVoice>
+    <el-dialog
+      title="添加资源模板"
+      :visible.sync="cetBoxDialog"
+      :append-to-body="true"
+      width="400px"
+      :before-close="handleClose"
+      class="dialog_diy"
+    >
+      <div class="addTypeChoose" style="justify-content: center">
+        <div style="min-width: 100px">模板名称:</div>
+        <el-input v-model="templateName" style="width: 200px"></el-input>
+      </div>
+      <div class="addTypeBox">
+        <div class="addTypeChoose">
+          <div style="min-width: 100px">选择一级分类:</div>
+          <el-select
+            v-model="setTypeJson.one"
+            placeholder="请选择"
+            @change="getTwoType(setTypeJson.one)"
+            style="width: 200px;"
+          >
+            <el-option
+              v-for="(item, index) in oneJson"
+              :key="index"
+              :label="item.name"
+              :value="item.id"
+            >
+            </el-option>
+          </el-select>
+        </div>
+        <div class="addTypeChoose" v-if="setTypeJson.one != ''">
+          <div style="min-width: 100px">选择二级分类:</div>
+          <el-select v-model="setTypeJson.two" placeholder="请选择" style="width: 200px;">
+            <el-option
+              v-for="(item1, index1) in twoJson"
+              :key="index1"
+              :label="item1.name"
+              :value="item1.id"
+            >
+            </el-option>
+          </el-select>
+        </div>
+      </div>
+      <span slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="addCETemplate()">确 认</el-button>
+        <el-button @click="close()">关 闭</el-button>
+      </span>
+    </el-dialog>
+    <evaBox :userid="userid" :oid='oid' :org="org" :dialogVisibleEva.sync="evaBoxDialog" @updateEvaJson="updateEvaJson"></evaBox>
+    <EnglishVoice :oid='oid' :org="org" :EnglishVoiceDialog.sync="EnglishVoiceDialog" :englishVoiceJson="englishVoiceJson" @setEnglishVoiceJson="setEnglishVoiceJson"></EnglishVoice>
 </div>
 </template>
 
@@ -4126,9 +4179,12 @@ export default {
       AttTextIndex: 0,
       cTemplate: "",
       CourseType: [],
+      CourseType1: [],
       CourseType2: [],
       CourseTypeJson: {},
+      CourseTypeJson1: {},
       courseTypeId: [],
+      courseTypeId1: [],
       courseTypeSon: [],
       clearArray: [],
       pTypeCheck: [],
@@ -4214,6 +4270,17 @@ export default {
         evatIndex: '',
         evaBoxDialog: false,
         EnglishVoiceDialog: false,
+        englishVoiceJson:{},
+        cetIndex: '',
+        cettIndex: '',
+        cetBoxDialog: false,
+        templateName: '',
+        setTypeJson: {
+          one: "",
+          two: "",
+        },
+        twoJson: [],
+        oneJson: [],
     };
   },
   directives: {
@@ -4484,6 +4551,12 @@ export default {
         return "";
       }
     },
+    close(){
+      this.cetIndex = '';
+      this.cettIndex = '';
+      this.templateName = '';
+      this.cetBoxDialog = false;
+    },
     openAI() {
       top.postMessage({ tools: "64" }, "*");
     },
@@ -7700,10 +7773,36 @@ export default {
         this.$forceUpdate();
         this.englishDialogVisible = true;
       }else if(i == 70){
+        this.englishVoiceJson = {};
+        this.englishVoiceJson = this.unitJson[this.unitIndex].chapterInfo[0].taskJson[
+          itemTaskIndex
+        ].toolChoose[toolIndex].englishVoiceJson
+          ? JSON.parse(
+            JSON.stringify(
+              this.unitJson[this.unitIndex].chapterInfo[0].taskJson[
+                itemTaskIndex
+              ].toolChoose[toolIndex].englishVoiceJson
+            )
+          )
+          : { 
+            title:'',
+            detail:'',
+            array:[]
+           };
         this.$forceUpdate();
         this.EnglishVoiceDialog = true;
       }
     },
+    setEnglishVoiceJson(val){
+      this.unitJson[this.unitIndex].chapterInfo[0].taskJson[this.taskCount].toolChoose[this.toolIndex].englishVoiceJson = JSON.parse(JSON.stringify(val))
+      this.$forceUpdate();
+      if (
+        this.unitJson[this.unitIndex].chapterInfo[0].taskJson[this.taskCount]
+          .toolChoose[this.toolIndex].tool != 70
+      ) {
+        this.addTools(70, this.taskCount, this.toolIndex);
+      }
+    },
     chapAddTools(i) {
       if (this.chapTools[0].tools.length == 0) {
         this.chapTools[0].tools.push(i);
@@ -7826,13 +7925,13 @@ export default {
         }
       }
       if(i == 70){
-        // if (
-        //   !this.unitJson[this.unitIndex].chapterInfo[0].taskJson[itemTaskIndex]
-        //     .toolChoose[toolIndex].englishList
-        // ) {
+        if (
+          !this.unitJson[this.unitIndex].chapterInfo[0].taskJson[itemTaskIndex]
+            .toolChoose[toolIndex].englishVoiceJson
+        ) {
           this.openTools(itemTaskIndex, 70, toolIndex);
           return;
-        // }
+        }
       }
       // if (i == 48) {
       //   if (
@@ -9361,6 +9460,77 @@ export default {
       this.evatIndex = tIndex
       this.evaBoxDialog = true
     },
+    addCET(index,tIndex){
+      this.cetIndex = index;
+      this.cettIndex = tIndex;
+      this.selectAllType1();
+    },
+    addCETemplate(){
+      var array = this.unitJson[this.cetIndex].chapterInfo[0].taskJson[this.cettIndex].eList;
+      let params = [
+        {
+          uid: this.userid,
+          n: this.templateName,
+          json: JSON.stringify(array),
+          t: 1,
+          oid: this.oid,
+        },
+      ];
+      this.ajax
+        .post(this.$store.state.api + "addCETShare", params)
+        .then((res) => {
+          this.addTypeByCET(res.data[0][0].id);
+        })
+        .catch((err) => {
+          this.$message.error("网络不佳");
+          console.error(err);
+        });
+    },
+    addTypeByCET(id) {
+      if (this.setTypeJson.two == "") {
+        this.$message.warning("请选择二级分类,如没有二级分类请前往添加!");
+        return;
+      }
+      let params = {
+        cid: id,
+      };
+      this.ajax
+        .get(this.$store.state.api + "deleteCETLabel", params)
+        .then((res) => {
+          for (var i = 0; i < 2; i++) {
+            let tid = "";
+            if (i == 0) {
+              tid = this.setTypeJson.one;
+            } else {
+              tid = this.setTypeJson.two;
+            }
+            let params = [
+              {
+                cid: id,
+                tid: tid,
+                uid: this.userid,
+              },
+            ];
+            this.ajax
+              .post(this.$store.state.api + "addCETLabel", params)
+              .then((res) => {
+                this.$message({
+                  message: "添加成功",
+                  type: "success",
+                });
+                this.close();
+              })
+              .catch((err) => {
+                this.$message.error("网络不佳");
+                console.error(err);
+              });
+          }
+        })
+        .catch((err) => {
+          this.$message.error("网络不佳");
+          console.error(err);
+        });
+    },
     updateEvaJson(array){
       this.unitJson[this.evaIndex].chapterInfo[0].taskJson[this.evatIndex].eList = array
     },
@@ -10338,7 +10508,78 @@ export default {
           });
       });
       
-    }
+    },
+    getTwoType(id) {
+      this.twoJson = [];
+      var array = this.CourseTypeJson1[
+        "3f8eed32-aba9-11ee-b534-005056b86db5"
+      ].filter((e) => {
+        return e.ppid == id;
+      });
+      this.twoJson = array;
+      this.$forceUpdate();
+    },
+    ctype(){
+      this.oneJson =  this.CourseTypeJson1["3c73702a-aba9-11ee-b534-005056b86db5"];
+    },
+    selectAllType1() {
+      this.CourseType1 = [];
+      this.CourseTypeJson1 = {};
+      this.courseTypeId1 = {};
+      this.$forceUpdate();
+      let params = {
+        org: this.org && this.org != "" ? this.org : "",
+        oid: this.oid && this.oid != "" ? this.oid : "",
+      };
+      this.ajax
+        .get(this.$store.state.api + "selectAllEvaType", params)
+        .then((res) => {
+          this.CourseType1 = res.data;
+          for (var i = 0; i < res.data[0].length; i++) {
+            if (res.data[0][i].id == "3c73702a-aba9-11ee-b534-005056b86db5") {
+              res.data[0][i].name = "一级分类";
+            } else if (
+              res.data[0][i].id == "3f8eed32-aba9-11ee-b534-005056b86db5"
+            ) {
+              res.data[0][i].name = "二级分类";
+            }
+            if (!this.cid) {
+              this.courseTypeId1[res.data[0][i].id] = [];
+            }
+            if (!this.CourseTypeJson1[res.data[0][i].id]) {
+              this.CourseTypeJson1[res.data[0][i].id] = [];
+            }
+
+            // if (res.data[2].length == 0 && res.data[3].length == 0) {
+            for (var j = 0; j < res.data[1].length; j++) {
+              if (res.data[0][i].id == res.data[1][j].pid) {
+                this.CourseTypeJson1[res.data[0][i].id].push(res.data[1][j]); // 去除公共分类
+              }
+            }
+            // } else {
+            if (res.data[2].length > 0) {
+              for (var j = 0; j < res.data[2].length; j++) {
+                if (res.data[0][i].id == res.data[2][j].pid) {
+                  this.CourseTypeJson1[res.data[0][i].id].push(res.data[2][j]); // 去除公共分类
+                }
+              }
+            }
+            if (res.data[3].length > 0) {
+              for (var j = 0; j < res.data[3].length; j++) {
+                if (res.data[0][i].id == res.data[3][j].pid) {
+                  this.CourseTypeJson1[res.data[0][i].id].push(res.data[3][j]); // 去除公共分类
+                }
+              }
+            }
+            // }
+          }
+          this.ctype();
+          this.cetBoxDialog = true;
+        })
+        .catch((err) => {
+          console.error(err);
+        });
+    },
   },
   beforeDestroy() {
     clearTimeout(this.timer);
@@ -14443,5 +14684,40 @@ ol {
 .eva_btn_box{
   margin: 20px 0px 0 0;
   display: flex;
+  flex-direction: row;
+  flex-wrap: nowrap;
+  align-items: center;
+  justify-content: space-between;
+  width: 100%;
+}
+
+.eva_btn_left_box{
+  display: flex;
+  flex-direction: row;
+  flex-wrap: nowrap;
+  align-items: center;
+}
+
+.addTypeChoose {
+  display: flex;
+  flex-direction: row;
+  flex-wrap: nowrap;
+  align-items: center;
+  margin: 15px 0;
+}
+
+.addTypeBox {
+  display: flex;
+  flex-direction: column;
+  flex-wrap: nowrap;
+  align-items: center;
+}
+
+.addTypeChoose {
+  display: flex;
+  flex-direction: row;
+  flex-wrap: nowrap;
+  align-items: center;
+  margin: 15px 0;
 }
 </style>

Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio