Browse Source

Merge branch 'beta'

lsc 11 months ago
parent
commit
fa6d085298
60 changed files with 4716 additions and 2994 deletions
  1. 1 1
      dist/index.html
  2. 0 0
      dist/static/css/app.2b5d26585cec8c72398d534cabb52fbc.css
  3. 0 0
      dist/static/css/app.2b5d26585cec8c72398d534cabb52fbc.css.map
  4. 0 0
      dist/static/css/app.f704ede10b054bd3f59580da1aaa7ff8.css
  5. BIN
      dist/static/img/KekeLoading.5a4818f.gif
  6. 0 0
      dist/static/js/0.4f3b05586c3acc102a54.js
  7. 0 0
      dist/static/js/0.4f3b05586c3acc102a54.js.map
  8. 0 0
      dist/static/js/0.7da288988865a9378b49.js.map
  9. 0 0
      dist/static/js/app.c8c9c5693bab676481f2.js
  10. 0 0
      dist/static/js/app.c8c9c5693bab676481f2.js.map
  11. 2 2
      dist/static/js/manifest.161e82026ac2ae03ab6f.js
  12. 0 0
      dist/static/js/manifest.161e82026ac2ae03ab6f.js.map
  13. 0 0
      dist/static/js/vendor.de15001ce66f032e9274.js
  14. 0 0
      dist/static/js/vendor.de15001ce66f032e9274.js.map
  15. BIN
      src/assets/KekeLoading.gif
  16. 10 1
      src/assets/css/button.css
  17. 1 0
      src/assets/icon/course/download.svg
  18. BIN
      src/assets/icon/test/test_bianji.png
  19. BIN
      src/assets/icon/test/test_delete.png
  20. BIN
      src/assets/icon/test/test_delete_active.png
  21. BIN
      src/assets/icon/test/test_rename.png
  22. BIN
      src/assets/icon/test/test_rename_active.png
  23. BIN
      src/assets/icon/test/type_sweep_icon.png
  24. 395 252
      src/components/pages/aiAddCourse/addCourse.vue
  25. 3 0
      src/components/pages/aiAddCourse/evaList.vue
  26. 92 63
      src/components/pages/aiEasy/addCourse.vue
  27. 1 1
      src/components/pages/aiEasy/evaList.vue
  28. 274 58
      src/components/pages/appStore/dialog/addAppDialog.vue
  29. 152 0
      src/components/pages/appStore/dialog/saveCard.vue
  30. 15 579
      src/components/pages/appStore/index.vue
  31. 924 0
      src/components/pages/appStore/views/appManagement.vue
  32. 119 0
      src/components/pages/appStore/views/workSpace.vue
  33. 4 4
      src/components/pages/components/exjsmind.vue
  34. 387 391
      src/components/pages/components/exportDataDialog.vue
  35. 276 285
      src/components/pages/components/exportWorksDialog.vue
  36. 6 6
      src/components/pages/components/lookReport.vue
  37. 7 7
      src/components/pages/components/lookWork.vue
  38. 444 381
      src/components/pages/components/report.vue
  39. 1 1
      src/components/pages/components/studentWorksDetail.vue
  40. 2 2
      src/components/pages/components/worksDetail2.vue
  41. 49 3
      src/components/pages/inviteLoginST/inviteLogin.vue
  42. 6 5
      src/components/pages/test/add/components/GapFilling/gap.vue
  43. 2 1
      src/components/pages/test/add/components/addCheckPopover.vue
  44. 36 10
      src/components/pages/test/add/components/checkOrder.vue
  45. 1 0
      src/components/pages/test/add/components/choice/choice.vue
  46. 3 3
      src/components/pages/test/add/components/file/file.vue
  47. 166 0
      src/components/pages/test/add/components/sweep/index.vue
  48. 16 4
      src/components/pages/test/add/edit/check/index.vue
  49. 261 0
      src/components/pages/test/add/edit/check/sweep.vue
  50. 36 13
      src/components/pages/test/add/edit/edit/index.vue
  51. 1 0
      src/components/pages/test/add/edit/edit/indexJ.vue
  52. 23 10
      src/components/pages/test/add/edit/index.vue
  53. 4 0
      src/components/pages/test/add/global_styles.css
  54. 11 6
      src/components/pages/test/add/minxins/minxin.js
  55. 38 7
      src/components/pages/test/check/index.vue
  56. 53 763
      src/components/pages/test/checkAi/aiLeader.vue
  57. 65 64
      src/components/pages/test/choseCheck/csvTableView.vue
  58. 542 67
      src/components/pages/test/smarter.vue
  59. 266 0
      src/components/pages/testStudent/view/component/sweep.vue
  60. 21 4
      src/components/pages/testStudent/view/component/topic.vue

+ 1 - 1
dist/index.html

@@ -32,7 +32,7 @@
       width: 100%;
       background: #e6eaf0;
       font-family: '黑体';
-    }</style><link href=./static/css/app.f704ede10b054bd3f59580da1aaa7ff8.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=./static/js/manifest.3eade43afd174522bb8a.js></script><script type=text/javascript src=./static/js/vendor.6bffbf9058a42e825dbc.js></script><script type=text/javascript src=./static/js/app.8aed90a4b921b9f8e45e.js></script></body></html><script>function stopSafari() {
+    }</style><link href=./static/css/app.2b5d26585cec8c72398d534cabb52fbc.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=./static/js/manifest.161e82026ac2ae03ab6f.js></script><script type=text/javascript src=./static/js/vendor.de15001ce66f032e9274.js></script><script type=text/javascript src=./static/js/app.c8c9c5693bab676481f2.js></script></body></html><script>function stopSafari() {
     //阻止safari浏览器双击放大功能
     let lastTouchEnd = 0  //更新手指弹起的时间
     document.documentElement.addEventListener("touchstart", function (event) {

File diff suppressed because it is too large
+ 0 - 0
dist/static/css/app.2b5d26585cec8c72398d534cabb52fbc.css


File diff suppressed because it is too large
+ 0 - 0
dist/static/css/app.2b5d26585cec8c72398d534cabb52fbc.css.map


File diff suppressed because it is too large
+ 0 - 0
dist/static/css/app.f704ede10b054bd3f59580da1aaa7ff8.css


BIN
dist/static/img/KekeLoading.5a4818f.gif


File diff suppressed because it is too large
+ 0 - 0
dist/static/js/0.4f3b05586c3acc102a54.js


File diff suppressed because it is too large
+ 0 - 0
dist/static/js/0.4f3b05586c3acc102a54.js.map


File diff suppressed because it is too large
+ 0 - 0
dist/static/js/0.7da288988865a9378b49.js.map


File diff suppressed because it is too large
+ 0 - 0
dist/static/js/app.c8c9c5693bab676481f2.js


File diff suppressed because it is too large
+ 0 - 0
dist/static/js/app.c8c9c5693bab676481f2.js.map


+ 2 - 2
dist/static/js/manifest.3eade43afd174522bb8a.js → dist/static/js/manifest.161e82026ac2ae03ab6f.js

@@ -1,2 +1,2 @@
-!function(e){var n=window.webpackJsonp;window.webpackJsonp=function(r,a,c){for(var i,u,f,s=0,l=[];s<r.length;s++)u=r[s],t[u]&&l.push(t[u][0]),t[u]=0;for(i in a)Object.prototype.hasOwnProperty.call(a,i)&&(e[i]=a[i]);for(n&&n(r,a,c);l.length;)l.shift()();if(c)for(s=0;s<c.length;s++)f=o(o.s=c[s]);return f};var r={},t={6:0};function o(n){if(r[n])return r[n].exports;var t=r[n]={i:n,l:!1,exports:{}};return e[n].call(t.exports,t,t.exports,o),t.l=!0,t.exports}o.e=function(e){var n=t[e];if(0===n)return new Promise(function(e){e()});if(n)return n[2];var r=new Promise(function(r,o){n=t[e]=[r,o]});n[2]=r;var a=document.getElementsByTagName("head")[0],c=document.createElement("script");c.type="text/javascript",c.charset="utf-8",c.async=!0,c.timeout=12e4,o.nc&&c.setAttribute("nonce",o.nc),c.src=o.p+"static/js/"+e+"."+{0:"7da288988865a9378b49",1:"14e8e8c7e44fc858e4a6",2:"94e1427bfc7ef0b4c685",3:"3a9f53a78da16650e6b8"}[e]+".js";var i=setTimeout(u,12e4);function u(){c.onerror=c.onload=null,clearTimeout(i);var n=t[e];0!==n&&(n&&n[1](new Error("Loading chunk "+e+" failed.")),t[e]=void 0)}return c.onerror=c.onload=u,a.appendChild(c),r},o.m=e,o.c=r,o.d=function(e,n,r){o.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},o.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return o.d(n,"a",n),n},o.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},o.p="./",o.oe=function(e){throw console.error(e),e}}([]);
-//# sourceMappingURL=manifest.3eade43afd174522bb8a.js.map
+!function(e){var n=window.webpackJsonp;window.webpackJsonp=function(r,c,a){for(var i,u,f,s=0,l=[];s<r.length;s++)u=r[s],t[u]&&l.push(t[u][0]),t[u]=0;for(i in c)Object.prototype.hasOwnProperty.call(c,i)&&(e[i]=c[i]);for(n&&n(r,c,a);l.length;)l.shift()();if(a)for(s=0;s<a.length;s++)f=o(o.s=a[s]);return f};var r={},t={6:0};function o(n){if(r[n])return r[n].exports;var t=r[n]={i:n,l:!1,exports:{}};return e[n].call(t.exports,t,t.exports,o),t.l=!0,t.exports}o.e=function(e){var n=t[e];if(0===n)return new Promise(function(e){e()});if(n)return n[2];var r=new Promise(function(r,o){n=t[e]=[r,o]});n[2]=r;var c=document.getElementsByTagName("head")[0],a=document.createElement("script");a.type="text/javascript",a.charset="utf-8",a.async=!0,a.timeout=12e4,o.nc&&a.setAttribute("nonce",o.nc),a.src=o.p+"static/js/"+e+"."+{0:"4f3b05586c3acc102a54",1:"14e8e8c7e44fc858e4a6",2:"94e1427bfc7ef0b4c685",3:"3a9f53a78da16650e6b8"}[e]+".js";var i=setTimeout(u,12e4);function u(){a.onerror=a.onload=null,clearTimeout(i);var n=t[e];0!==n&&(n&&n[1](new Error("Loading chunk "+e+" failed.")),t[e]=void 0)}return a.onerror=a.onload=u,c.appendChild(a),r},o.m=e,o.c=r,o.d=function(e,n,r){o.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},o.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return o.d(n,"a",n),n},o.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},o.p="./",o.oe=function(e){throw console.error(e),e}}([]);
+//# sourceMappingURL=manifest.161e82026ac2ae03ab6f.js.map

File diff suppressed because it is too large
+ 0 - 0
dist/static/js/manifest.161e82026ac2ae03ab6f.js.map


File diff suppressed because it is too large
+ 0 - 0
dist/static/js/vendor.de15001ce66f032e9274.js


File diff suppressed because it is too large
+ 0 - 0
dist/static/js/vendor.de15001ce66f032e9274.js.map


BIN
src/assets/KekeLoading.gif


+ 10 - 1
src/assets/css/button.css

@@ -355,7 +355,8 @@
 .pub_test_btn_course::before,
 .pub_test_btn_eva::before,
 .pub_test_btn_time::before,
-.pub_test_btn_file::before {
+.pub_test_btn_file::before,
+.pub_test_btn_sweep::before {
   content: "";
   width: 18px;
   height: 18px;
@@ -395,6 +396,10 @@
   background-image: url(../icon/test/type_time_icon.png);
 }
 
+.pub_test_btn_sweep::before{
+	background-image: url(../icon/test/type_sweep_icon.png);
+}
+
 .test_icon{
   display: inline-block;
   width: 18px;
@@ -428,6 +433,10 @@
   background-image: url('../icon/test/type_time_icon.png');
 }
 
+.test_icon_sweep{
+  background-image: url('../icon/test/type_sweep_icon.png');
+}
+
 .dataBoard_check_box {
   display: flex;
   align-items: center;

+ 1 - 0
src/assets/icon/course/download.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1733817765595" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4411" width="128" height="128" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M833.841473 336.403925c-29.237791-149.914232-160.920736-263.309448-321.841473-263.309448S219.452762 186.489692 190.158527 336.403925C80.48859 365.641715 0 468.030427 0 585.038033c0 142.633006 113.395216 256.028222 255.971778 256.028222h36.57546v-73.15092h-36.57546c-102.388711 0-182.877301-80.432146-182.877301-182.877302 0-102.388711 80.432146-182.877301 182.877301-182.877301 0-142.633006 113.395216-255.971778 255.971778-255.971778 142.633006 0 256.028222 113.395216 256.028222 255.971778 102.388711 0 182.877301 80.432146 182.877301 182.877301 0 102.388711-80.432146 182.877301-182.877301 182.877302h-36.57546v73.15092h36.57546c142.633006 0 255.971778-113.395216 255.971778-256.028222 0.056444-117.007607-80.432146-219.396318-190.102083-248.634108z" p-id="4412" fill="#4f4f4f"></path><path d="M599.769816 782.53423l-43.856686 40.244295V511.943556c0-21.956565-18.28773-36.57546-36.575461-36.57546-21.956565 0-36.57546 18.28773-36.57546 36.57546v310.834969l-43.91313-40.244295c-14.618895-14.618895-40.244295-14.618895-54.86319 0-14.618895 14.618895-14.618895 36.57546 0 51.194356l109.726381 106.057546c3.668835 3.668835 7.337669 7.337669 10.950061 7.337669 14.618895 7.337669 29.237791 3.668835 40.244295-7.337669l106.057546-106.057546c14.618895-14.618895 14.618895-36.57546 0-51.194356-10.950061-14.618895-36.57546-14.618895-51.194356 0z" p-id="4413" fill="#4f4f4f"></path></svg>

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


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


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


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


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


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


File diff suppressed because it is too large
+ 395 - 252
src/components/pages/aiAddCourse/addCourse.vue


+ 3 - 0
src/components/pages/aiAddCourse/evaList.vue

@@ -393,6 +393,9 @@ Language: ${this.getLang()}
 
                     console.log(elist);
                     _this.eList = elist
+                    setTimeout(() => {
+                        _this.$emit('addAppendixEva', _this.itemTaskIndex, _this.toolIndex)
+                    }, 100);
                     _this.$forceUpdate()
                 }
                 _this.cancelToken = null

+ 92 - 63
src/components/pages/aiEasy/addCourse.vue

@@ -28,7 +28,8 @@
         <!-- <div style="display: flex; margin-top: 20px; position: relative"> -->
         <!-- @mouseenter="stepDisplay(true)"
               @mouseleave="stepDisplay(false)" -->
-        <div ref="stepBox" class="stepBox" :style="{overflow:istemplate == 1 ? 'auto' : 'auto'}"  @scroll="scrollChange">
+        <div ref="stepBox" class="stepBox" :style="{overflow:istemplate == 1 ? 'auto' : 'auto', height: steps > 2 ? 'calc(100% - 75px)' : '100%'}"  @scroll="scrollChange">
+          <!-- <button class="c_pub_button_confirm confirmBtn" :style="{ right: (isDialog == 1 && chatid && isDisplay) ? (newWidth + 65) + 'px' : '45px'}" v-if="steps > 2 && istemplate != 1" @click="nextSteps">确认上传</button>  -->
           <div class="stepBg" v-if="false">
             <div :class="{ stepTop: isStepDisplay, stepTop2: !isStepDisplay }">
               <div v-if="steps > 0 && isStepDisplay" class="first" @click="navSteps(1)">
@@ -469,59 +470,27 @@
                                 </div>
                               </div>
                               <div class="chapter_upload_n" :class="{dataTips: !item1.fileid}">
-                                <input readonly="true" v-if="
+                                <div v-if="
                                   item1.type == 2 ||
                                   item1.type == 3 ||
                                   item1.type == 12 ||
                                   item1.type == 13 ||
                                   item1.type == 7
-                                " :placeholder="item1.name" @click="
+                                " @click="
                                   updataVideoT(
                                     $event,
                                     unitIndex,
                                     0,
                                     index1
                                   )
-                                  " style="
-                                        border: none;
-                                        outline: none;
-                                        max-width: 100%;
-                                        z-index: 99;
-                                        font-size: 14px;
-                                        white-space: nowrap;
-                                        overflow: hidden;
-                                        text-overflow: ellipsis;
-                                      " />
-                                <input :placeholder="item1.name" v-if="item1.type == 6" style="
-                                        border: none;
-                                        outline: none;
-                                        max-width: 100%;
-                                        white-space: nowrap;
-                                        overflow: hidden;
-                                        text-overflow: ellipsis;
-                                      " readonly="true" @click="
+                                  " class="chapter_upload_box" >{{ item1.name }}</div>
+                                <div v-if="item1.type == 6" class="chapter_upload_box" @click="
                                         selectAttText(0, index1)
-                                        " />
-                                <input :placeholder="item1.title ? item1.title : '链接'
-                                  " v-if="item1.type == 8" style="
-                                        border: none;
-                                        outline: none;
-                                        max-width: 100%;
-                                        white-space: nowrap;
-                                        overflow: hidden;
-                                        text-overflow: ellipsis;
-                                      " readonly="true" @click="selectLine(0, index1)" />
-                                <input :placeholder="item1.title ? item1.title : '链接'
-                                  " v-if="item1.type == 14" style="
-                                        border: none;
-                                        outline: none;
-                                        max-width: 100%;
-                                        white-space: nowrap;
-                                        overflow: hidden;
-                                        text-overflow: ellipsis;
-                                      " readonly="true" @click="
+                                        " >{{ item1.name }}</div>
+                                <div v-if="item1.type == 8" class="chapter_upload_box" @click="selectLine(0, index1)" >{{ item1.title ? item1.title : '链接' }}</div>
+                                <div v-if="item1.type == 14" class="chapter_upload_box" @click="
                                         openUpdateSource(0, index1)
-                                        " />
+                                        " >{{ item1.title ? item1.title : '链接' }}</div>
                               </div>
                               <div class="chapter_upload_ic">
                                 <div class="chapter_upload_noSee" v-if="item1.type == 12"></div>
@@ -1743,9 +1712,9 @@
                   </div>
                   <div style="width: calc(100%);height: 100%" class='op_task_box' :class="{inter_Detailbox: !courseTextB && interPan}">
                     <textarea style="height: 500px" class="binfo_input binfo_textarea" cols v-model="courseTextE"
-                      placeholder="请输入学习任务内容" v-if="courseTextB && interPan" @change="textAreaChange('courseText')"></textarea>
+                      placeholder="请输入学习任务内容" v-if="courseTextB && interPan" @change="textAreaChange('courseTextE')"></textarea>
                     <textarea v-autoHeight="68" rows="2" class="binfo_input binfo_textarea" cols v-model="courseTextE"
-                      placeholder="请输入学习任务内容" v-else-if="courseTextB && !interPan" @change="textAreaChange('courseText')"></textarea>
+                      placeholder="请输入学习任务内容" v-else-if="courseTextB && !interPan" @change="textAreaChange('courseTextE')"></textarea>
                     <div class="markBox vditor-reset" style="white-space:pre-wrap;" v-text="courseTextE" :style="{height: interPan ? '500px' : 'auto', overflowY:'auto'}" v-else-if="textLoading"></div>
                     <div class="markBox vditor-reset" :style="{height: interPan ? '500px' : 'auto', overflowY:'auto'}" v-html="MarkdownT(courseTextE)" v-else></div>
                       <div class="op_box" :class="{op_box_isquote: isQuote['courseTextE']}">
@@ -2374,7 +2343,7 @@
           }">
             <div class="rb_c_box">
               <div class="rb_c_box_left" v-if="(steps == 3 || istemplate == 1)" :style="{width: stepShow ? '270px' : '0',minWidth: stepShow ? '270px' : '0',height: stepShow ? '100%' : '0',marginRight: stepShow ? '10px' : '0'}">
-                <div class="rb_c_box_left stepsBottom2" :style="{width: stepShow ? '270px' : '0',minWidth: stepShow ? '270px' : '0',height: stepShow ? '100%' : '0',marginRight: stepShow ? '0' : '0'}">
+                <div class="rb_c_box_left stepsBottom2" :style="{width: stepShow ? '270px' : '0',minWidth: stepShow ? '270px' : '0',height: stepShow ? 'calc(100% - 120px)' : '0',marginRight: stepShow ? '0' : '0'}">
                   <div></div>
                   <div class="close_btn" @click="stepShow = !stepShow" :class="!stepShow ? 'close_btn_voice' : ''" style="left: 0;right: unset;top: 5px;transform: rotate(180deg);">
                     <img src="../../../assets/icon/course/arrow.svg" >
@@ -2385,7 +2354,7 @@
                     <!-- <span class="button-toggle" @click="stepShow = !stepShow">{{ stepShow ? '收缩' : '展开' }}</span> -->
                   </div>
                   <div class="stepsBottom" v-if="stepsNav == 1" :style="{
-                    height:istemplate == 1 ? 'calc(100vh - 300px)' : 'calc(100% - 55px)',
+                    height:istemplate == 1 ? 'calc(100vh - 300px)' : 'calc(100% - 55px - 60px)',
                     position: istemplate == 1 ? 'sticky' : 'unset',
                     top: istemplate == 1 ? '0' : 'unset'
                   }">
@@ -2585,6 +2554,7 @@
                     <span>一键生成</span>
                     <div class="buttonBox">
                       <div @click="openAiDialog(2, 'aiTaskName'), addCourseBehavior('courseBehavior2', `点击学历案-生成所有任务名`)" v-if="panTaskName() == 0">生成所有任务名</div>
+                      <div @click="openAiDialog2(2, 'aiTaskName'), addCourseBehavior('courseBehavior2', `点击学历案-生成所有任务名`)" v-else>重新生成所有任务名</div>
                       <div @click="openAiDialog2(2, 'aiTask3','all', ''), addCourseBehavior('courseBehavior2', `点击学历案-重新生成所有任务`)" v-if="panTaskName() > 0 && panTask() > 0">重新生成所有任务</div>
                       <div @click="openAiDialog(2, 'aiTask3','all', ''), addCourseBehavior('courseBehavior2', `点击学历案-生成所有任务按钮`)" v-else-if="panTaskName() > 0">生成所有任务</div>
                       <div @click="openAiDialog(2, 'aiTaskG2', 'all'), addCourseBehavior('courseBehavior2', `点击学历案-一键生成所有工具按钮`)" v-if="panTask() > 0 && panTool() == 0">一键生成所有工具</div>
@@ -2597,9 +2567,7 @@
                   <!-- <button class="c_pub_button_confirm3" style="margin: 0 0 0 10px;" @click="openAiDialog(2, 'aiTaskG2', 'all'), addCourseBehavior('courseBehavior2', `点击学历案-一键生成所有工具按钮`)" v-if="panTool() == 0">一键生成所有工具</button> -->
                   <!-- <button class="c_pub_button_confirm3" style="margin: 0 0 0 10px;" @click="allEvaCan(), addCourseBehavior('courseBehavior2', `点击学历案-一键生成所有评价按钮`)" v-if="panTool() > 0 && panTaskElist() == 0 && panEvaCont() == 0">一键生成所有评价</button> -->
                   <!-- <button class="c_pub_button_confirm3" style="margin: 0 0 0 10px;" @click="exportTaskEA(), addCourseBehavior('courseBehavior2', `点击学历案-导出评价和学历案按钮`)">导出评价和学历案</button> -->
-                  <button class="c_pub_button_confirm" style="margin: 0 0 0 10px;" v-if="steps < 4 && istemplate != 1" @click="nextSteps">
-                    {{ steps == 3 ? "确认上传" : "下一步" }}
-                  </button> 
+                  <button class="c_pub_button_confirm" style="margin: 0 0 0 10px;" v-if="steps < 4 && istemplate != 1" @click="nextSteps">确认上传</button> 
                 </div>
                 <div class="basic_box" ref="unitBox" @scroll="taskScroll">
                   <div v-if="false" style="
@@ -5398,6 +5366,9 @@
             </button>
           </div>
         </div>
+        <div class="info_btnBox3" v-show="steps > 2" style="width: calc(100% - 40px)">
+          <button class="c_pub_button_confirm pub_btn_finish_img" @click="nextSteps">确认上传</button>
+        </div>
       </div>
       <div class="leftBar" style="height: calc(100% - 36px - 20px);margin-top: 36px;" v-if="istemplate == 1">
         <!-- <aiTips ttitle="基础资料" title="提取摘要" :detail="aiJson.aiAbstract" pan="aiAbstract" @setAiJson="setAiJson" v-if="!yiKeTemplateArray.includes(templateid)"/> -->
@@ -5420,7 +5391,7 @@
           @setAiJson="setAiJson" /> -->
         <!-- <aiTips ttitle="生成教案" title="教案描述优化" :detail="aiJson.teacherDetail2" pan="teacherDetail2"
           @setAiJson="setAiJson" /> -->
-        <aiTips ttitle="生成教案" title="生成任务按钮" :detail="aiJson.aiTask" pan="aiTask" @setAiJson="setAiJson" />
+        <!-- <aiTips ttitle="生成教案" title="生成任务按钮" :detail="aiJson.aiTask" pan="aiTask" @setAiJson="setAiJson" /> -->
         <aiTips ttitle="任务详情" title="生成任务" :detail="aiJson.aiTaskName" pan="aiTaskName" @setAiJson="setAiJson" />
         <aiTips ttitle="任务详情" title="任务描述" :detail="aiJson.aiTaskG1" pan="aiTaskG1" @setAiJson="setAiJson" />
         <aiTips ttitle="任务详情" title="工具列表" :detail="aiJson.aiTaskG2" pan="aiTaskG2" @setAiJson="setAiJson" />
@@ -7577,7 +7548,8 @@ export default {
       course_info: "",
       stepShow: true,
       anLoading: [],
-      heightPx: '100%'
+      heightPx: '100%',
+      newWidth: 350,
     };
   },
   directives: {
@@ -11803,6 +11775,9 @@ ${_this.unitJson[0].chapterInfo[0].taskJson[index].taskDetail3.replaceAll('#',''
           type: "warning",
         })
         .then(() => {
+          if(_this.unitJson[i].chapterInfo[j].taskJson[taskI].chapterData[ic].fileid && _this.knowFileids.indexOf(_this.unitJson[i].chapterInfo[j].taskJson[taskI].chapterData[ic].fileid) != -1){
+            _this.knowFileids.splice(_this.knowFileids.indexOf(_this.unitJson[i].chapterInfo[j].taskJson[taskI].chapterData[ic].fileid), 1)
+          }
           _this.unitJson[i].chapterInfo[j].taskJson[taskI].chapterData.splice(
             ic,
             1
@@ -14927,7 +14902,7 @@ ${_this.unitJson[0].chapterInfo[0].taskJson[index].taskDetail3.replaceAll('#',''
               }
             }
 
-            if(this.courseText){
+            if(this.courseText || this.courseTextE){
               this.courseTextB = false
             }
             if(this.teacherCourseText){
@@ -16068,8 +16043,10 @@ ${_this.unitJson[0].chapterInfo[0].taskJson[index].taskDetail3.replaceAll('#',''
       // if (this.unitJson[this.unitIndex].chapterInfo[0].taskJson[i].toolOpen) {
       //   this.unitJson[this.unitIndex].chapterInfo[0].taskJson[i].toolOpen = false
       // } else {
-      document.querySelectorAll(".basic_box")[0].scrollTop =
-        document.querySelectorAll(".taskBorder")[i].offsetTop - 100;
+      // document.querySelectorAll(".basic_box")[0].scrollTop =
+      //   document.querySelectorAll(".taskBorder")[i].offsetTop - 100;
+      document.querySelectorAll(".stepBox")[0].scrollTop =
+      $('.rightBox')[0].offsetHeight + document.querySelectorAll(".taskBorder")[i].offsetTop + 30;
       this.isClickColor = i + 1;
       this.unitJson[this.unitIndex].chapterInfo[0].taskJson[i].toolOpen = true;
       // }
@@ -16550,16 +16527,21 @@ ${_this.unitJson[0].chapterInfo[0].taskJson[index].taskDetail3.replaceAll('#',''
       if(confirm_next_step){
         this.courseTextE += turndownService.turndown(confirm_next_step)
         iframe.contentWindow.confirm_next_step = ''
+        this.courseTextB = false
       }
       if(work_area_text && work_area_text.aiContent){
         this.courseTextE += turndownService.turndown(work_area_text.aiContent)
         iframe.contentWindow.work_area_text = ''
+        this.courseTextB = false
       }
     },
     textAreaChange(type, index){
       if(type == 'courseText'){
         this.addCourseBehavior('courseBehavior2', `手动修改课程概况信息-${this.courseText}`)
       }
+      if(type == 'courseTextE'){
+        this.addCourseBehavior('courseBehavior2', `手动修改课程学习任务内容-${this.courseText}`)
+      }
       if(type == 'targetCourseText2'){
         this.addCourseBehavior('courseBehavior2', `手动修改课程目标信息-${this.targetCourseText2}`)
       }
@@ -17622,7 +17604,7 @@ ${_this.unitJson[0].chapterInfo[0].taskJson[index].taskDetail3.replaceAll('#',''
             let _fileid = await this.createFileid(this.infoData[i].url)
             if(_fileid){
               this.infoData[i].fileid = _fileid == 1 ? '' : _fileid
-              _this.$forceUpdate();
+              this.$forceUpdate();
               if(_fileid != 1){
                 fileid.push(_fileid)
               }
@@ -17743,6 +17725,8 @@ ${_this.unitJson[0].chapterInfo[0].taskJson[index].taskDetail3.replaceAll('#',''
           })
           return;
         }
+        this.$message.success("正在生成中...")
+
         this.aitype = type
         this.aiText = this.aiJson.aiTaskG1
         this.aiText2 = this.aiJson.aiTaskG2
@@ -17760,6 +17744,8 @@ ${_this.unitJson[0].chapterInfo[0].taskJson[index].taskDetail3.replaceAll('#',''
           this.$message.error("请生成学习任务后再生成任务");
           return;
         }
+        this.$message.success("正在生成中...")
+
         this.aitype = type
         this.aiText = this.aiJson.aiTaskName
         this.aiCallBack = callback
@@ -17789,6 +17775,8 @@ ${_this.unitJson[0].chapterInfo[0].taskJson[index].taskDetail3.replaceAll('#',''
         //   });
         //   return;
         // }
+        this.$message.success("正在生成中...")
+
         this.aitype = type
         this.aiText = this.aiJson.aiTaskG2
         this.aiCallBack = callback
@@ -18335,6 +18323,7 @@ ${(this.templateid == "4480d65a-1e48-11ef-bee5-005056b86db5" || this.templateid
           let _this = this
           function processNext() {
             if (ij < _this.unitJson[0].chapterInfo[0].taskJson.length) {
+              let _task = _this.unitJson[0].chapterInfo[0].taskJson[ij]
               if(!_this.taskGLoading[ij][0]){
                 ij++;
                 processNext();
@@ -18351,6 +18340,7 @@ ${msg}
 
 ## 参考资料
 学习任务内容:${_this.courseTextE}
+你所在的活动:教学活动${ij+1}:${_task.task} 活动描述:${_task.taskDetail}
 
 # 输出格式与要求
 任务描述(告诉学生他们需要做什么):
@@ -18376,6 +18366,8 @@ ${msg}
           this.aiCallBack[1] ? this.aiCallBack[1]() : ''
 
         }else{
+          let _task = _this.unitJson[0].chapterInfo[0].taskJson[this.aiCallBack[0]]
+
           let message1 = `NOTICE
 Role: 你是一名教师,你正在使用一个在线学习平台来教授学生,你已经完成了教案,你现在需要将教案变为学生上课用的任务单(work sheet)。该在线学习平台为每个任务提供了资源区(视频,ppt,阅读资料将放在这里),多种互动工具(学生点击工具即可上传他们的作业或者回答,这些互动工具类似kahoot一样允许教师轻松收集,统计,追踪学生作业),以及和任务绑定的目标和评价系统。
 Language: ${this.getLang()}
@@ -18387,6 +18379,7 @@ ${msg}
 
 ## 参考资料
 学习任务内容:${this.courseTextE}
+你所在的活动:教学活动${this.aiCallBack[0]+1}:${_task.task} 活动描述:${_task.taskDetail}
 
 # 输出格式与要求
 任务描述(告诉学生他们需要做什么):
@@ -18451,6 +18444,8 @@ ${msg3}
           let _this = this
           function processNext() {
             if (ij < _this.unitJson[0].chapterInfo[0].taskJson.length) {
+              let _task = _this.unitJson[0].chapterInfo[0].taskJson[ij]
+              
               if(!_this.taskGLoading[ij][1]){
                 _this.taskGLoading[ij][1] = false
                 ij++;
@@ -18470,6 +18465,7 @@ ${msg2}
 
 ## 参考资料
 学习任务内容:${_this.courseTextE}
+你所在的活动:教学活动${ij+1}:${_task.task} 活动描述:${_task.taskDetail}
 
 # 输出格式与要求
 互动工具列表
@@ -18499,7 +18495,7 @@ ${_this.languageSetting == 2 ? '还有以下工具:Mind Map Tool、Spreadsheet
 
 
         }else{
-
+          let _task = _this.unitJson[0].chapterInfo[0].taskJson[this.aiCallBack]
 let message2 = `NOTICE
 Role: 你是一名教师,你正在使用一个在线学习平台来教授学生,你已经完成了教案,你现在需要将教案变为学生上课用的任务单(work sheet)。该在线学习平台为每个任务提供了资源区(视频,ppt,阅读资料将放在这里),多种互动工具(学生点击工具即可上传他们的作业或者回答,这些互动工具类似kahoot一样允许教师轻松收集,统计,追踪学生作业),以及和任务绑定的目标和评价系统。
 Language: ${this.getLang()}
@@ -18513,6 +18509,7 @@ ${msg2}
 
 ## 参考资料
 学习任务内容:${this.courseTextE}
+你所在的活动:教学活动${this.aiCallBack+1}:${_task.task} 活动描述:${_task.taskDetail}
 
 # 输出格式与要求
 互动工具列表
@@ -18556,7 +18553,7 @@ ${msg}
 学习任务内容:${this.courseTextE}
 
 # Format example
-[{"task": "任务1的名字"}, {"task": "任务2的名字"}, {"task": "任务3的名字"}, {"task": "任务n的名字"}]`
+[{"task":"活动名/任务名/环节名","taskDetail":"活动描述/任务描述/环节描述"},{"task":"活动名/任务名/环节名","taskDetail":"活动描述/任务描述/环节描述"},{"task":"活动名/任务名/环节名","taskDetail":"活动描述/任务描述/环节描述"},{"task":"活动名/任务名/环节名","taskDetail":"活动描述/任务描述/环节描述"}]`
         this.loading = true
         this.aiGetTaskName(message, this.aiCallBack)
       } else if (this.aitype == "aiDetail1") {
@@ -20359,16 +20356,20 @@ ${this.courseText && this.aiCallBack[0] == 2 ? '注意,优化原有的<参考
 
             for(var i = 0; i < _this.unitJson[0].chapterInfo[0].taskJson.length; i++){
               _this.unitJson[0].chapterInfo[0].taskJson[i].task = ""
+              _this.unitJson[0].chapterInfo[0].taskJson[i].taskDetail = ""
             }
             for (var i = 0; i < dArray.length; i++) {
               let _task = dArray[i]
               if(_this.unitJson[0].chapterInfo[0].taskJson[i]){
-                _this.unitJson[0].chapterInfo[0].taskJson[i].task = _task.task.replaceAll('任务'+(i+1),'').replaceAll('任务'+_this.numberToChinese(i+1),'').replaceAll(':','').replaceAll(':','')
+                _this.unitJson[0].chapterInfo[0].taskJson[i].task = _task.task
+                _this.unitJson[0].chapterInfo[0].taskJson[i].taskDetail = _task.taskDetail
+                // .replaceAll('任务'+(i+1),'').replaceAll('任务'+_this.numberToChinese(i+1),'').replaceAll(':','').replaceAll(':','')
                 _this.unitJson[0].chapterInfo[0].taskJson[i].isFold = 0
               }else {
                 _this.unitJson[0].chapterInfo[0].taskJson.push({
-                  task: _task.task.replaceAll('任务'+(i+1),'').replaceAll('任务'+_this.numberToChinese(i+1),'').replaceAll(':','').replaceAll(':',''),
-                  taskDetail: "",
+                  task: _task.task,
+                  // .replaceAll('任务'+(i+1),'').replaceAll('任务'+_this.numberToChinese(i+1),'').replaceAll(':','').replaceAll(':',''),
+                  taskDetail: _task.taskDetail,
                   taskDetail2: "",
                   taskDetail3: "",
                   chapterData: [],
@@ -20629,7 +20630,7 @@ ${this.courseText && this.aiCallBack[0] == 2 ? '注意,优化原有的<参考
                 return el
               })
               _this.unitJson[0].chapterInfo[0].taskJson[index].eList = _task.elist
-              _this.unitJson[0].chapterInfo[0].taskJson[index].chapterData = []
+              // _this.unitJson[0].chapterInfo[0].taskJson[index].chapterData = []
               if(!_task.toolChoose || (_task.detail && _task.detail.length < 20) || !_task.detail){
                 console.log("error_________________JSON不对重新生成");
                 _this.$message.error('哎呀,网络波动了...小可正在为您重新生成中...')
@@ -20753,7 +20754,7 @@ ${this.courseText && this.aiCallBack[0] == 2 ? '注意,优化原有的<参考
             }
             console.log(data.message);
             _this.unitJson[0].chapterInfo[0].taskJson[index].taskDetail = tArray.detail
-            _this.unitJson[0].chapterInfo[0].taskJson[index].chapterData = []
+            // _this.unitJson[0].chapterInfo[0].taskJson[index].chapterData = []
             // _this.unitJson2 = JSON.parse(JSON.stringify(_this.unitJson))
             _this.$forceUpdate();
             _this.createTeacherAn(index);
@@ -20866,7 +20867,7 @@ ${this.courseText && this.aiCallBack[0] == 2 ? '注意,优化原有的<参考
           this.isTaskCancelSource1[index].close();
           this.isTaskCancelSource1[index] = null;
           this.unitJson[0].chapterInfo[0].taskJson[index].taskDetail = _mdText;
-          this.unitJson[0].chapterInfo[0].taskJson[index].chapterData = []
+          // this.unitJson[0].chapterInfo[0].taskJson[index].chapterData = []
           // this.createTeacherAn(index);
           this.taskGLoading[index][0] = false
           this.ttaskGLoading[index][0] = false
@@ -25284,6 +25285,7 @@ ${msg}
       const newWidth = startWidth + dx;
       if (newWidth >= 350 && newWidth <= maxWidth) {
         resizable.style.minWidth = `${newWidth}px`;
+        this.newWidth = newWidth;
       }
     };
 
@@ -25310,6 +25312,7 @@ ${msg}
       const newWidth = startWidth + dx;
       if (newWidth >= 350 && newWidth <= maxWidth2) {
         resizable.style.minWidth = `${newWidth}px`;
+        this.newWidth = newWidth;
       }
     };
 
@@ -25343,6 +25346,7 @@ ${msg}
     // this.selectType();
     this.selectEva();
     if(this.istemplate == 1){
+      this.steps = 3
       this.isOutline = true
       this.isOutline2 = true
       this.courseTextBool = true
@@ -26553,6 +26557,8 @@ ${msg}
   margin: 0 15px 0px auto;
   display: flex;
   align-items: center;
+  min-width: 175px;
+  justify-content: flex-end;
 }
 
 .chapter_upload_ic_l {
@@ -26619,13 +26625,25 @@ ${msg}
   text-overflow: ellipsis;
   white-space: nowrap;
   overflow: hidden;
-  width: 55%;
+  width: 100%;
   margin-left: 10px;
   cursor: pointer;
   margin-top: 2px;
   align-items: center;
 }
 
+.chapter_upload_n > .chapter_upload_box{
+  border: none;
+  outline: none;
+  max-width: 100%;
+  z-index: 99;
+  font-size: 14px;
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  color: #757575;
+}
+
 .chapter_upload_l_i2,
 .chapter_upload_l_i3,
 .chapter_upload_l_i8,
@@ -30123,4 +30141,15 @@ ol {
   font-size: 13px;
   color: #898989;
 }
+
+.stepBox {
+  position: relative; /* 确保子元素可以绝对定位 */
+}
+
+.confirmBtn{
+  z-index: 1000;
+  position: fixed;
+  /* right: 45px; */
+  bottom: 20px;
+}
 </style>

+ 1 - 1
src/components/pages/aiEasy/evaList.vue

@@ -224,7 +224,7 @@ export default {
         aiElist() {
             let _this = this
             if(!_this.knowFileids.length){
-                _this.$message.error(`请上传参考标准后,再生成评价`)
+                _this.$message.error(`请上传您已有的教案和PPT,再生成评价`)
                 return
             }
             _this.loading = true

+ 274 - 58
src/components/pages/appStore/dialog/addAppDialog.vue

@@ -13,30 +13,83 @@
           <div v-else>修改应用</div>
         </div>
         <div class="a-d-t-right">
-          <span @click.stop="close()">×</span>
+          <span @click="close()">×</span>
         </div>
       </div>
       <div class="bfd_box" v-loading="loading" label-position="top">
         <el-form :model="form" :rules="rules" ref="ruleForm">
-          <el-form-item label="应用名称" prop="nname">
+          <div
+            style="display: flex;width: 100%;justify-content: space-between;align-items: center;"
+          >
+            <el-form-item label="应用图标" prop="icon">
+              <el-input
+                v-model="form.json.icon"
+                placeholder="请输入应用图标(可直接粘贴svg或者点击右侧图标上传图片)"
+                style="width: 500px;"
+              ></el-input>
+            </el-form-item>
+
+            <div
+              class="bfd_icon"
+              v-loading="uploadIconLoading"
+              @click="uploadIcon()"
+            >
+              <!-- svg -->
+              <span
+                v-html="form.json.icon"
+                v-if="isImageOrSvg(form.json.icon) === 1"
+              ></span>
+              <!-- 默认图标 -->
+              <svg
+                v-if="isImageOrSvg(form.json.icon) === 0"
+                t="1732605901531"
+                class="icon"
+                viewBox="0 0 1024 1024"
+                version="1.1"
+                xmlns="http://www.w3.org/2000/svg"
+                p-id="4275"
+                width="200"
+                height="200"
+              >
+                <path
+                  d="M179.2 153.6a51.2 51.2 0 0 0-51.2 51.2v128a51.2 51.2 0 0 0 51.2 51.2h128a51.2 51.2 0 0 0 51.2-51.2V204.8a51.2 51.2 0 0 0-51.2-51.2H179.2z m0-102.4h128a153.6 153.6 0 0 1 153.6 153.6v128a153.6 153.6 0 0 1-153.6 153.6H179.2a153.6 153.6 0 0 1-153.6-153.6V204.8a153.6 153.6 0 0 1 153.6-153.6z m0 614.4a51.2 51.2 0 0 0-51.2 51.2v128a51.2 51.2 0 0 0 51.2 51.2h128a51.2 51.2 0 0 0 51.2-51.2V716.8a51.2 51.2 0 0 0-51.2-51.2H179.2z m0-102.4h128a153.6 153.6 0 0 1 153.6 153.6v128a153.6 153.6 0 0 1-153.6 153.6H179.2a153.6 153.6 0 0 1-153.6-153.6V716.8a153.6 153.6 0 0 1 153.6-153.6z m611.84-403.4048a51.2 51.2 0 0 0-72.3968 0L646.144 232.2432a51.2 51.2 0 0 0 0 72.3968l72.448 72.3968a51.2 51.2 0 0 0 72.3968 0l72.3968-72.3968a51.2 51.2 0 0 0 0-72.3968L791.04 159.744z m72.3968-72.3968l72.3968 72.3968a153.6 153.6 0 0 1 0 217.2416l-72.3968 72.3968a153.6 153.6 0 0 1-217.2416 0l-72.3968-72.3968a153.6 153.6 0 0 1 0-217.2416l72.3968-72.3968a153.6 153.6 0 0 1 217.2416 0zM699.7504 896a51.2 51.2 0 0 1 0 102.4A162.1504 162.1504 0 0 1 537.6 836.2496v-110.8992A162.1504 162.1504 0 0 1 699.7504 563.2h110.8992a162.1504 162.1504 0 0 1 162.1504 162.1504v8.448a51.2 51.2 0 0 1-102.4 0v-8.448c0-33.024-26.7264-59.7504-59.7504-59.7504h-110.8992c-33.024 0-59.7504 26.7264-59.7504 59.7504v110.8992c0 33.024 26.7264 59.7504 59.7504 59.7504z"
+                  fill="#2C6DD2"
+                  p-id="4276"
+                ></path>
+                <path
+                  d="M791.4496 160a51.2 51.2 0 0 0-72.3968 0l-72.448 72.3968a51.2 51.2 0 0 0 0 72.3968l72.448 72.3968a51.2 51.2 0 0 0 72.3968 0l72.3968-72.3968a51.2 51.2 0 0 0 0-72.3968l-72.3968-72.3968z"
+                  fill="#20C997"
+                  p-id="4277"
+                ></path>
+              </svg>
+              <!-- 网络图片 -->
+              <el-image
+                v-if="isImageOrSvg(form.json.icon) === 2"
+                style="width: 100%; height: 100%"
+                :src="form.json.icon"
+                fit="cover"
+              ></el-image>
+            </div>
+          </div>
+          <el-form-item label="应用名称" prop="name">
             <el-input
-              v-model="form.nname"
+              v-model="form.name"
               placeholder="请输入应用名称"
             ></el-input>
           </el-form-item>
           <div
             style="display: flex;width: 100%;justify-content: space-between;"
           >
-            <el-form-item label="应用标签" prop="nlabel">
+            <el-form-item label="应用标签" prop="label">
               <el-input
-                v-model="form.nlabel"
+                v-model="form.label"
                 placeholder="请输入应用标签"
                 style="width: 300px;"
               ></el-input>
             </el-form-item>
-            <el-form-item label="应用类型" prop="ntype">
+            <el-form-item label="应用类型" prop="type">
               <el-select
-                v-model="form.ntype"
+                v-model="form.type"
                 placeholder="请选择应用类型"
                 style="width: 300px;"
               >
@@ -50,16 +103,16 @@
               </el-select>
             </el-form-item>
           </div>
-          <el-form-item label="应用链接" prop="nurl">
+          <el-form-item label="应用链接" prop="url">
             <el-input
-              v-model="form.nurl"
+              v-model="form.url"
               placeholder="请输入应用链接"
             ></el-input>
           </el-form-item>
-          <el-form-item label="应用简介" prop="ndetail">
+          <el-form-item label="应用简介" prop="detail">
             <el-input
               type="textarea"
-              v-model="form.ndetail"
+              v-model="form.detail"
               style="width: 100%;"
               :rows="3"
               resize="none"
@@ -67,38 +120,47 @@
             ></el-input>
           </el-form-item>
           <el-form-item
-            label="权限管理"
+            label="可见范围"
             style="display: flex;flex-direction: column;align-items: flex-start;"
           >
-            <el-radio-group v-model="form.njuri">
+            <el-radio-group v-model="form.juri">
               <el-radio label="1">私有</el-radio>
               <el-radio label="2">公开组织</el-radio>
               <el-radio label="3">公开所有人</el-radio>
             </el-radio-group>
           </el-form-item>
+
+
+					<el-form-item label="权限设置"  style="display: flex;flex-direction: column;align-items: flex-start;">
+						<el-radio-group v-model="form.json.copy" style="display: flex;flex-direction: column;">
+              <el-radio label="0" class="radioItem">仅体验(用户仅能使用,不可查看设置内容)</el-radio>
+              <el-radio label="1" class="radioItem">允许其他用户复制并进行二次创作</el-radio>
+            </el-radio-group>
+          </el-form-item>
         </el-form>
       </div>
       <div class="bfd_bottom">
         <el-button @click="close()">取消</el-button>
-        <el-button type="primary" @click="submitBtn('ruleForm')">保存</el-button>
+        <el-button type="primary" @click="submitBtn('ruleForm')"
+          >保存</el-button
+        >
       </div>
     </el-dialog>
   </div>
 </template>
 
 <script>
-
 let validUrl = (rule, value, callback) => {
-	if (value) {
-		// 验证链接是否有效
-		try {
-			new URL(value);
-			callback();
-		} catch (error) {
-			return callback(new Error("请输入有效的链接"));
-		}
-	}
-}
+  if (value) {
+    // 验证链接是否有效
+    try {
+      new URL(value);
+      callback();
+    } catch (error) {
+      return callback(new Error("请输入有效的链接"));
+    }
+  }
+};
 export default {
   props: {
     typeList: {
@@ -112,50 +174,113 @@ export default {
     return {
       loading: false,
       show: false,
+      uploadIconLoading: false,
       type: 1, //1添加,2编辑
       form: {
-        nname: "",
-        nlabel: "",
-        ndetail: "",
-        nurl: "",
-        ntype: "",
-        njuri: "1",
-        nstand: "cn",
-        njson: ""
+        name: "",
+        label: "",
+        detail: "",
+        url: "",
+        type: "",
+        juri: "1",
+        stand: "cn",
+        json: {
+          icon: "",
+          copy: "0"
+        }
       },
       rules: {
-        nname: [{ required: true, message: "请输入应用名称", trigger: "blur" }],
-        nurl: [{ required: true, message: "请输入应用链接", trigger: "blur" }],
-        nlabel: [
-          { required: true, message: "请输入应用标签", trigger: "blur" }
-        ],
-        ntype: [{ required: true, message: "请选择应用类型", trigger: "blur" }],
+        name: [{ required: true, message: "请输入应用名称", trigger: "blur" }],
+        url: [{ required: true, message: "请输入应用链接", trigger: "blur" }],
+        // nlabel: [
+        //   { required: true, message: "请输入应用标签", trigger: "blur" }
+        // ],
+        // ntype: [{ required: true, message: "请选择应用类型", trigger: "blur" }],
         // ndetail:[{required:true,message:"请输入应用简介",trigger:"blur"}],
-        njuri: [{ required: true, message: "请选择权限管理", trigger: "blur" }],
-				nurl: [{ required: true, message: "请输入应用链接", trigger: "blur" },{ validator: validUrl, trigger: "blur" }]
+        juri: [{ required: true, message: "请选择权限管理", trigger: "blur" }],
+        url: [
+          { required: true, message: "请输入应用链接", trigger: "blur" },
+          { validator: validUrl, trigger: "blur" }
+        ]
       }
     };
   },
+  computed: {
+    isImageOrSvg() {
+      return value => {
+        let _result = 0; //啥也不是
+        if (value) {
+          const svgPattern = /<svg.*<\/svg>/;
+          const imagePattern = /\.(jpeg|jpg|gif|png|svg|bmp|webp)$/i; // 图片链接的正则表达式
+          const urlPattern = /^(http|https):\/\/[^ "]+$/; // 网络地址的正则表达式
+
+          if (svgPattern.test(value)) {
+            _result = 1;
+          } else if (urlPattern.test(value) && imagePattern.test(value)) {
+            _result = 2;
+          }
+        }
+        return _result;
+      };
+    }
+  },
   methods: {
     open(data) {
       if (data && data.type === 2) {
+        if (!data.form.json) {
+          data.form.json = { icon: "", copy: "0" };
+        }
+				if(!data.form.json.icon){
+					data.form.json.icon = ""
+				}
+				if(!data.form.json.copy){
+					data.form.json.copy = "0"
+				}
+
         this.form = data.form;
         this.type = data.type;
       } else {
         this.form = {
-          nname: "",
-          nlabel: "",
-          ndetail: "",
-          nurl: "",
-          ntype: "",
-          njuri: "1",
-          nstand: "cn",
-          njson: ""
+          name: "",
+          label: "",
+          detail: "",
+          url: "",
+          type: "",
+          juri: "1",
+          stand: "cn",
+          json: {
+            icon: "",
+            copy: "0"
+          }
         };
       }
       this.loading = false;
+      this.uploadIconLoading = false;
       this.show = true;
     },
+    uploadIcon() {
+      if (this.uploadIconLoading) return this.$message.info("请稍等...");
+      const input = document.createElement("input");
+      input.type = "file";
+      input.accept =
+        "image/jpeg, image/jpg, image/gif, image/png, image/svg+xml";
+      input.onchange = async event => {
+        const file = event.target.files[0];
+        this.uploadIconLoading = true;
+        const validImageTypes = /\.(jpeg|jpg|gif|png|svg)$/i; // 定义有效的图片类型正则表达式
+
+        if (validImageTypes.test(file.name)) {
+          let url = await this.uploadFile(file);
+          if (url) {
+            this.form.json.icon = url;
+          }
+          this.uploadIconLoading = false;
+        } else {
+          this.$message.error("请上传有效的图片文件!(jpeg|jpg|gif|png|svg)"); // 提示用户上传有效的图片
+        }
+      };
+      input.click();
+    },
     close(flag = false) {
       if (this.loading && !flag) return this.$message.info("请稍等...");
       this.show = false;
@@ -163,14 +288,17 @@ export default {
     },
     init() {
       this.form = {
-        nname: "",
-        nlabel: "",
-        ndetail: "",
-        nurl: "",
-        ntype: "",
-        njuri: "1",
-        nstand: "cn",
-        njson: ""
+        name: "",
+        label: "",
+        detail: "",
+        url: "",
+        type: "",
+        juri: "1",
+        stand: "cn",
+        json: {
+          icon: "",
+          copy: "0"
+        }
       };
       this.loading = false;
     },
@@ -182,6 +310,54 @@ export default {
           this.$emit("success", this.form, this.type);
         }
       });
+    },
+    uploadFile(file) {
+      return new Promise(resolve => {
+        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) {
+          // this.loading = true;
+          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) {
+              //这里可以写进度条
+              // _this.progressData.value = parseInt((evt.loaded * 100) / evt.total);
+              // console.log("Uploaded : " + parseInt((evt.loaded * 80) / evt.total) + '%');
+            })
+            .send(function(err, data) {
+              if (err) {
+                _this.$message.error("上传失败");
+                resolve(0);
+              } else {
+                resolve(data.Location);
+              }
+            });
+        }
+      });
     }
   }
 };
@@ -191,7 +367,8 @@ export default {
 .addNewAppDialog >>> .el-dialog {
   min-width: 700px;
 
-  height: 680px;
+  height: 900px;
+	/* height: 780px; */
   box-shadow: 0px 0 8px 0px #555555;
   border-radius: 8px;
   background-color: #fff;
@@ -257,4 +434,43 @@ export default {
   display: flex;
   justify-content: flex-end;
 }
+
+.bfd_icon {
+  width: 70px;
+  height: 70px;
+  box-sizing: border-box;
+  padding: 5px;
+  margin-right: 40px;
+  cursor: pointer;
+}
+
+.bfd_icon > svg {
+  width: 100%;
+  height: 100%;
+}
+
+.bfd_icon > span {
+  width: 100%;
+  height: 100%;
+
+  display: block;
+}
+
+.bfd_icon > span >>> svg {
+  width: 100%;
+  height: 100%;
+}
+
+.switchForm{
+	display: flex;
+	align-items: center;
+}
+
+.switchForm>span{
+	margin-left: 10px;
+}
+
+.radioItem{
+	margin-bottom: 10px;
+}
 </style>

+ 152 - 0
src/components/pages/appStore/dialog/saveCard.vue

@@ -0,0 +1,152 @@
+<template>
+  <div class="saveCard">
+    <span>{{ title }}</span>
+    <div class="s_box">
+      <div v-for="(item,index) in data" :key="item.sid" @click="openAppUrl(item)" v-if="data.length>0 && item.id">
+        <div>
+          <svg
+            v-if="isImageOrSvg(typeof item.json =='object'?item.json.icon:'') === 0"
+            t="1732605901531"
+            class="icon"
+            viewBox="0 0 1024 1024"
+            version="1.1"
+            xmlns="http://www.w3.org/2000/svg"
+            p-id="4275"
+            width="200"
+            height="200"
+          >
+            <path
+              d="M179.2 153.6a51.2 51.2 0 0 0-51.2 51.2v128a51.2 51.2 0 0 0 51.2 51.2h128a51.2 51.2 0 0 0 51.2-51.2V204.8a51.2 51.2 0 0 0-51.2-51.2H179.2z m0-102.4h128a153.6 153.6 0 0 1 153.6 153.6v128a153.6 153.6 0 0 1-153.6 153.6H179.2a153.6 153.6 0 0 1-153.6-153.6V204.8a153.6 153.6 0 0 1 153.6-153.6z m0 614.4a51.2 51.2 0 0 0-51.2 51.2v128a51.2 51.2 0 0 0 51.2 51.2h128a51.2 51.2 0 0 0 51.2-51.2V716.8a51.2 51.2 0 0 0-51.2-51.2H179.2z m0-102.4h128a153.6 153.6 0 0 1 153.6 153.6v128a153.6 153.6 0 0 1-153.6 153.6H179.2a153.6 153.6 0 0 1-153.6-153.6V716.8a153.6 153.6 0 0 1 153.6-153.6z m611.84-403.4048a51.2 51.2 0 0 0-72.3968 0L646.144 232.2432a51.2 51.2 0 0 0 0 72.3968l72.448 72.3968a51.2 51.2 0 0 0 72.3968 0l72.3968-72.3968a51.2 51.2 0 0 0 0-72.3968L791.04 159.744z m72.3968-72.3968l72.3968 72.3968a153.6 153.6 0 0 1 0 217.2416l-72.3968 72.3968a153.6 153.6 0 0 1-217.2416 0l-72.3968-72.3968a153.6 153.6 0 0 1 0-217.2416l72.3968-72.3968a153.6 153.6 0 0 1 217.2416 0zM699.7504 896a51.2 51.2 0 0 1 0 102.4A162.1504 162.1504 0 0 1 537.6 836.2496v-110.8992A162.1504 162.1504 0 0 1 699.7504 563.2h110.8992a162.1504 162.1504 0 0 1 162.1504 162.1504v8.448a51.2 51.2 0 0 1-102.4 0v-8.448c0-33.024-26.7264-59.7504-59.7504-59.7504h-110.8992c-33.024 0-59.7504 26.7264-59.7504 59.7504v110.8992c0 33.024 26.7264 59.7504 59.7504 59.7504z"
+              fill="#2C6DD2"
+              p-id="4276"
+            ></path>
+            <path
+              d="M791.4496 160a51.2 51.2 0 0 0-72.3968 0l-72.448 72.3968a51.2 51.2 0 0 0 0 72.3968l72.448 72.3968a51.2 51.2 0 0 0 72.3968 0l72.3968-72.3968a51.2 51.2 0 0 0 0-72.3968l-72.3968-72.3968z"
+              fill="#20C997"
+              p-id="4277"
+            ></path>
+          </svg>
+          <span
+            v-if="isImageOrSvg(typeof item.json =='object'?item.json.icon:'') === 1"
+            v-html="item.json.icon"
+          ></span>
+          <el-image
+            v-if="isImageOrSvg(typeof item.json =='object'?item.json.icon:'') === 2"
+            style="width: 100%; height: 100%"
+            :src="item.json.icon"
+            fit="cover"
+          ></el-image>
+        </div>
+        <span>{{item.name}}</span>
+      </div>
+			<span v-if="data.length==0">暂无数据...</span>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  props: {
+    title: {
+      type: String,
+      default: "标题"
+    },
+    data: {
+      type: Array,
+      default: () => []
+    }
+  },
+  data() {
+    return {};
+  },
+  computed: {
+    isImageOrSvg() {
+      return value => {
+        let _result = 0; //啥也不是
+        if (value) {
+          const svgPattern = /<svg.*<\/svg>/;
+          const imagePattern = /\.(jpeg|jpg|gif|png|svg|bmp|webp)$/i; // 图片链接的正则表达式
+          const urlPattern = /^(http|https):\/\/[^ "]+$/; // 网络地址的正则表达式
+
+          if (svgPattern.test(value)) {
+            _result = 1;
+          } else if (urlPattern.test(value) && imagePattern.test(value)) {
+            _result = 2;
+          }
+        }
+        return _result;
+      };
+    }
+  },
+	methods: {
+		openAppUrl(item){
+			window.open(item.url, "_blank");
+		}
+	},
+};
+</script>
+
+<style scoped>
+.saveCard {
+  width: 100%;
+  height: auto;
+  margin-bottom: 20px;
+  box-sizing: border-box;
+  padding: 10px;
+}
+
+.saveCard > span {
+  font-size: 1.1em;
+  font-weight: bold;
+}
+
+.s_box {
+  width: 100%;
+  height: auto;
+	padding-top: 15px;
+}
+
+.s_box>div{
+	width: 100%;
+	height: 30px;
+	margin-bottom: 15px;
+	display: flex;
+	align-items: center;
+	border-radius: 5px;
+	cursor: pointer;
+	transition: .1s;
+}
+
+.s_box>div:hover{
+	background-color: aliceblue;
+}
+
+.s_box>div>div{
+	width: 30px;
+	height: 30px;
+	box-sizing: border-box;
+	padding: 5px;
+}
+
+.s_box>div>div>svg{
+	width: 100%;
+	height: 100%;
+}
+
+.s_box>div>div>span>>>svg{
+	width: 100%;
+	height: 100%;
+}
+
+
+.s_box>div>span{
+	max-width: calc(100% - 30px);
+	overflow: hidden;
+	text-overflow: ellipsis;
+	white-space: nowrap;
+}
+
+.s_box>span{
+	font-size: .8em;
+}
+</style>

+ 15 - 579
src/components/pages/appStore/index.vue

@@ -1,331 +1,29 @@
 <template>
   <div class="appCenter">
-    <div class="ac_header">
-      <div class="ac_h_top">
-        <span>应用管理</span>
-
-        <el-button
-          type="primary"
-          size="small"
-          icon="el-icon-plus"
-          style="position: absolute;right: 15px;"
-          @click="addApp"
-          >添加应用</el-button
-        >
-      </div>
-      <div class="ac_h_bottom">
-        <div class="ac_h_b_selectList">
-          <el-input
-            v-model="searchText"
-            style="width: 200px;"
-            placeholder="请输入应用名称"
-            @keyup.enter.native="getData"
-          />
-          <el-select
-            v-model="selectJuri"
-            placeholder="请选择"
-            @change="changeSelectType"
-          >
-            <el-option
-              v-for="item in selectList"
-              :key="item.index"
-              :label="item.label"
-              :value="item.index"
-            ></el-option>
-          </el-select>
-          <el-button
-            type="primary"
-            style="margin-left: 10px;"
-            icon="el-icon-search"
-            @click="getData"
-          ></el-button>
-          <el-button type="primary" @click="resetData">重置</el-button>
-        </div>
-
-        <div class="ac_h_b_typeList">
-          <span
-            :class="{ ac_h_b_typeList_active: showType === '' }"
-            @click="changeType('')"
-            >全部</span
-          >
-          <span
-            v-for="item in typeList"
-            :key="item.id"
-            :class="{ ac_h_b_typeList_active: showType === item.id }"
-            @click="changeType(item.id)"
-            >{{ item.name }}</span
-          >
-        </div>
-      </div>
-    </div>
-
-    <div class="ac_content">
-      <div class="ac_c_item" v-for="(item, index) in dataList" :key="item.id">
-        <div class="ac_c_i_top">
-          <div class="ac_c_i_t_left">
-            <svg
-              t="1732605901531"
-              class="icon"
-              viewBox="0 0 1024 1024"
-              version="1.1"
-              xmlns="http://www.w3.org/2000/svg"
-              p-id="4275"
-              width="200"
-              height="200"
-            >
-              <path
-                d="M179.2 153.6a51.2 51.2 0 0 0-51.2 51.2v128a51.2 51.2 0 0 0 51.2 51.2h128a51.2 51.2 0 0 0 51.2-51.2V204.8a51.2 51.2 0 0 0-51.2-51.2H179.2z m0-102.4h128a153.6 153.6 0 0 1 153.6 153.6v128a153.6 153.6 0 0 1-153.6 153.6H179.2a153.6 153.6 0 0 1-153.6-153.6V204.8a153.6 153.6 0 0 1 153.6-153.6z m0 614.4a51.2 51.2 0 0 0-51.2 51.2v128a51.2 51.2 0 0 0 51.2 51.2h128a51.2 51.2 0 0 0 51.2-51.2V716.8a51.2 51.2 0 0 0-51.2-51.2H179.2z m0-102.4h128a153.6 153.6 0 0 1 153.6 153.6v128a153.6 153.6 0 0 1-153.6 153.6H179.2a153.6 153.6 0 0 1-153.6-153.6V716.8a153.6 153.6 0 0 1 153.6-153.6z m611.84-403.4048a51.2 51.2 0 0 0-72.3968 0L646.144 232.2432a51.2 51.2 0 0 0 0 72.3968l72.448 72.3968a51.2 51.2 0 0 0 72.3968 0l72.3968-72.3968a51.2 51.2 0 0 0 0-72.3968L791.04 159.744z m72.3968-72.3968l72.3968 72.3968a153.6 153.6 0 0 1 0 217.2416l-72.3968 72.3968a153.6 153.6 0 0 1-217.2416 0l-72.3968-72.3968a153.6 153.6 0 0 1 0-217.2416l72.3968-72.3968a153.6 153.6 0 0 1 217.2416 0zM699.7504 896a51.2 51.2 0 0 1 0 102.4A162.1504 162.1504 0 0 1 537.6 836.2496v-110.8992A162.1504 162.1504 0 0 1 699.7504 563.2h110.8992a162.1504 162.1504 0 0 1 162.1504 162.1504v8.448a51.2 51.2 0 0 1-102.4 0v-8.448c0-33.024-26.7264-59.7504-59.7504-59.7504h-110.8992c-33.024 0-59.7504 26.7264-59.7504 59.7504v110.8992c0 33.024 26.7264 59.7504 59.7504 59.7504z"
-                fill="#2C6DD2"
-                p-id="4276"
-              ></path>
-              <path
-                d="M791.4496 160a51.2 51.2 0 0 0-72.3968 0l-72.448 72.3968a51.2 51.2 0 0 0 0 72.3968l72.448 72.3968a51.2 51.2 0 0 0 72.3968 0l72.3968-72.3968a51.2 51.2 0 0 0 0-72.3968l-72.3968-72.3968z"
-                fill="#20C997"
-                p-id="4277"
-              ></path>
-            </svg>
-          </div>
-          <div class="ac_c_i_t_right">
-            <div>{{ item.name }}</div>
-            <span>{{ item.label }}</span>
-          </div>
-					<div class="ac_c_i_t_popover" v-if="item.userid == userId">
-						<div class="ac_c_i_t_p_box" v-if="editAppCard === item.id" v-click-outside="handleBlur">
-							<div @click="updateApp(item)">修改</div>
-						</div>
-						<svg t="1732786015570" @click.stop="updateCard(item.id)" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9199" width="200" height="200"><path d="M192 443.733333c-38.4 0-68.266667 29.866667-68.266667 68.266667 0 38.4 29.866667 68.266667 68.266667 68.266667s68.266667-29.866667 68.266667-68.266667c0-38.4-29.866667-68.266667-68.266667-68.266667zM512 443.733333c-38.4 0-68.266667 29.866667-68.266667 68.266667 0 38.4 29.866667 68.266667 68.266667 68.266667s68.266667-29.866667 68.266667-68.266667c0-38.4-29.866667-68.266667-68.266667-68.266667zM832 443.733333c-38.4 0-68.266667 29.866667-68.266667 68.266667 0 38.4 29.866667 68.266667 68.266667 68.266667s68.266667-29.866667 68.266667-68.266667c0-38.4-34.133333-68.266667-68.266667-68.266667z" fill="#111111" p-id="9200"></path></svg>
-					</div>
-
-					
-        </div>
-        <div class="ac_c_i_bottom">
-          <div>{{ item.detail }}</div>
-          <span @click="openApp(item.url)">{{ item.url }}</span>
-        </div>
-      </div>
-      <div class="ac_c_empty" v-if="dataList.length === 0">
-        <span>暂无数据...</span>
-      </div>
-    </div>
-    <addAppDialog
-      ref="addAppDialogRef"
-      :typeList="typeList"
-      @success="addAppSuccess"
-    />
+    <appManagement v-show="showCard === 0" ref="appManagementRef" @changeShowCard="changeShowCard"/>
+		<workSpace v-show="showCard === 1" ref="workSpaceRef" @changeShowCard="changeShowCard"/>
   </div>
 </template>
 
 <script>
-const clickOutside = {
-  bind(el, binding) {
-    // 在元素上绑定一个点击事件监听器
-    el.clickOutsideEvent = function(event) {
-      // 检查点击事件是否发生在元素的内部
-      if (!(el === event.target || el.contains(event.target))) {
-        // 如果点击事件发生在元素的外部,则触发指令绑定的方法,将点击的event数据传过去
-        binding.value(event);
-      }
-    };
-    // 在文档上添加点击事件监听器
-    document.addEventListener("click", el.clickOutsideEvent);
-  },
-  unbind(el) {
-    // 在元素上解除点击事件监听器
-    document.removeEventListener("click", el.clickOutsideEvent);
-  }
-};
-import addAppDialog from "./dialog/addAppDialog.vue";
+import appManagement from './views/appManagement.vue';
+import workSpace from './views/workSpace.vue';
 export default {
   components: {
-    addAppDialog
-  },
-	directives: {
-    "click-outside": clickOutside // 注册自定义指令
+		appManagement,
+		workSpace
   },
-  data() {
-    return {
-      showType: "",
-      searchText: "",
-      selectJuri: 1,
-      typeList: [],
-      selectList: [
-        { index: 1, label: "我的" },
-        { index: 2, label: "组织" },
-        { index: 3, label: "所有人" }
-      ],
-      userId: this.$route.query["userid"],
-      org: this.$route.query["org"],
-      oid: this.$route.query["oid"],
-      getDataLoading: false,
-      dataList: [],
-			editAppCard:null
-    };
-  },
-  methods: {
-    changeType(newIndex) {
-      let flag = this.showType === newIndex;
-      this.showType = newIndex;
-      if (!flag) {
-        this.getData();
-      }
-    },
-    changeSelectType() {
-      this.getData();
-    },
-    getData() {
-      this.getDataLoading = true;
-      let params = {
-        uid: this.userId,
-        name: this.searchText,
-        label: "",
-        type: this.showType,
-        juri: this.selectJuri,
-        stand: "cn"
-      };
-
-      this.ajax
-        .get(this.$store.state.api + "select_appStore", params)
-        .then(res => {
-          this.getDataLoading = false;
-          let _data = res.data[0];
-          if (_data.length > 0) {
-            this.dataList = _data;
-          } else {
-            this.dataList = [];
-          }
-        })
-        .catch(err => {
-          this.getDataLoading = false;
-          console.log(err);
-          this.$message.error("获取应用失败");
-        });
-    },
-    addApp() {
-      this.$refs.addAppDialogRef.open({ type: 1 });
-    },
-    updateApp(data) {
-      this.$refs.addAppDialogRef.open({
-        type: 2,
-        form: {
-          id: data.id,
-          nname: data.name,
-          nlabel: data.label,
-          ndetail: data.detail,
-          nurl: data.url,
-          ntype: data.type,
-          njuri: data.juri,
-          nstand: data.stand,
-          njson: data.json
-        }
-      });
-    },
-		updateCard(id){
-			if(this.editAppCard === id)return this.editAppCard = null;
-			this.editAppCard = id;
-		},
-		handleBlur(){
-			this.updateCard(null);
-		},
-    addAppSuccess(data, type) {
-      if (type === 1) {
-        //添加
-        let params = [
-          {
-            nname: data.nname, //app名称
-            nuserid: this.userId, //创建的用户ID
-            nlabel: data.nlabel, //app标签
-            ndetail: data.ndetail, //app简介
-            nurl: data.nurl, //app链接
-            ntype: data.ntype, //app类型
-            njuri: data.njuri, //app权限 1:我的 2:组织 3:所有人
-            nstand: "cn", //语言
-            njson: "" //其他信息
-          }
-        ];
-        this.ajax
-          .post(this.$store.state.api + "insert_appStore", params)
-          .then(res => {
-            if (res.data == 1) {
-              this.$message.success("添加成功");
-              this.$refs.addAppDialogRef.close(true);
-              this.getData();
-            } else {
-              this.$message.error("添加失败");
-              this.$refs.addAppDialogRef.loading = false;
-            }
-          })
-          .catch(err => {
-            console.log(err);
-            this.$message.error("添加失败");
-          });
-      } else if (type === 2) {
-				let params = [
-					{
-						aid: data.id,
-						nname: data.nname, //app名称
-            nuserid: this.userId, //创建的用户ID
-            nlabel: data.nlabel, //app标签
-            ndetail: data.ndetail, //app简介
-            nurl: data.nurl, //app链接
-            ntype: data.ntype, //app类型
-            njuri: data.njuri, //app权限 1:我的 2:组织 3:所有人
-            nstand: "cn", //语言
-            njson: data.njson //其他信息
-					}
-				]
-				this.ajax
-          .post(this.$store.state.api + "update_appStore", params)
-          .then(res => {
-            if (res.data == 1) {
-              this.$message.success("修改成功");
-              this.$refs.addAppDialogRef.close(true);
-              this.getData();
-            } else {
-              this.$message.error("修改失败");
-              this.$refs.addAppDialogRef.loading = false;
-            }
-          })
-          .catch(err => {
-            console.log(err);
-            this.$message.error("修改失败");
-          });
-      }
-    },
-    getTypeList() {
-      let params = {
-        suserid: this.userId,
-        sorg: this.org,
-        soid: this.oid,
-        sstand: "cn"
-      };
 
-      this.ajax
-        .get(this.$store.state.api + "select_appStoreType", params)
-        .then(res => {
-          let data = res.data[0];
-          if (data.length > 0) {
-            this.typeList = data;
-          }
-        })
-        .catch(err => {
-          console.log(err);
-          this.$message.error("获取应用类型失败");
-        });
-    },
-    openApp(url) {
-      window.open(url, "_blank");
-    },
-    resetData() {
-      this.searchText = "";
-      this.selectJuri = 1;
-      this.showType = "";
-      this.getData();
-    }
+  data() {
+		return{
+			showCard:0,//0 应用中心  1:工作空间
+		}
   },
-  mounted() {
-    this.getTypeList();
-    this.getData();
-  }
+	methods: {
+		changeShowCard(newValue){
+			this.showCard = newValue;
+		}
+	},
 };
 </script>
 
@@ -334,268 +32,6 @@ export default {
   width: 100vw;
   height: 100vh;
   background-color: #f2f4f7;
-  margin: 0;
-  overflow: auto;
-  box-sizing: border-box;
-  padding: 20px;
-  display: flex;
-  flex-direction: column;
-}
-
-.ac_header {
-  width: 100%;
-  height: auto;
-  border-radius: 5px;
-  background-color: #fff;
-}
-
-.ac_h_top {
-  width: 100%;
-  height: 50px;
-  display: flex;
-  align-items: center;
-  box-sizing: border-box;
-  padding: 0 15px;
-  border-bottom: 1px solid #eeeeee;
-  position: relative;
-}
-
-.ac_h_top > span {
-  font-size: 26px;
-}
-
-.ac_h_bottom {
-  width: 100%;
-  height: auto;
-  padding: 10px 0 20px 0;
-}
-
-.ac_h_b_typeList {
-  width: 100%;
-  height: auto;
-  display: flex;
-  flex-wrap: wrap;
-  box-sizing: border-box;
-  padding: 0 15px;
-}
-
-.ac_h_b_typeList > span {
-  font-size: 18px;
-  margin-right: 20px;
-  margin-top: 10px;
-  margin-bottom: 5px;
-  cursor: pointer;
-}
-
-.ac_h_b_typeList_active {
-  color: #007aff;
-}
-
-.ac_h_b_selectList {
-  margin-left: 15px;
-  margin-bottom: 10px;
-}
-
-.ac_content {
-  width: 100%;
-  flex: 1;
-  height: auto;
-  margin-top: 20px;
   overflow: auto;
 }
-
-.ac_c_item {
-  width: calc(100% / 5 - (15px * 4) / 5);
-  height: 250px;
-  background-color: #fff;
-  border-radius: 10px;
-  box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.1);
-  box-sizing: border-box;
-  padding: 15px;
-  margin-right: 15px;
-  margin-bottom: 15px;
-  float: left;
-}
-
-@media screen and (min-width: 1400px) {
-  .ac_c_item {
-    width: calc(100% / 5 - (15px * 4) / 5) !important;
-  }
-  .ac_c_item:nth-child(5n) {
-    margin-right: 0px !important;
-    /* background-color: red; */
-  }
-}
-
-@media screen and (max-width: 1380px) {
-  .ac_c_item {
-    width: calc(100% / 4 - (15px * 3) / 4) !important;
-  }
-
-  .ac_c_item:nth-child(4n) {
-    margin-right: 0px !important;
-  }
-
-  /* .ac_c_item:nth-child(5n) {
-    margin-right: 0 !important;
-  } */
-}
-
-@media screen and (max-width: 1080px) {
-  .ac_c_item {
-    width: calc(100% / 3 - (15px * 2) / 3) !important;
-  }
-
-  .ac_c_item:nth-child(5n) {
-    margin-right: 15px !important;
-  }
-
-  .ac_c_item:nth-of-type(4n) {
-    margin-right: 15px !important;
-  }
-
-  .ac_c_item:nth-child(3n) {
-    margin-right: 0 !important;
-  }
-}
-
-.ac_c_empty {
-  width: 100%;
-  height: 40%;
-  display: flex;
-  box-sizing: border-box;
-  padding-top: 2%;
-  justify-content: center;
-  /* align-items: center; */
-}
-
-.ac_c_i_top {
-  width: 100%;
-  height: 50px;
-  display: flex;
-	position: relative;
-  /* flex-direction: column; */
-  /* justify-content: space-evenly; */
-  /* background-color: red */
-}
-
-.ac_c_i_t_popover{
-	width: 30px;
-	height: 30px;
-	position: absolute;
-	right: 0;
-	top: 0;
-}
-
-.ac_c_i_t_popover svg{
-	width: 25px;
-	height: 25px;
-	cursor: pointer;
-}
-
-.ac_c_i_t_p_box{
-	position: absolute;
-	height: auto;
-	top: 100%;
-	right: 0;
-	padding: 8px;
-	border-radius: 8px 0 8px 8px;
-	background-color: #fff;
-	box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.1);
-	width: auto;
-}
-
-.ac_c_i_t_p_box > div{
-	width: 80px;
-	height: 30px;
-	cursor: pointer;
-	transition: .3s;
-	font-weight: bold;
-	font-size: 14px;
-	border-radius: 5px;
-	display: flex;
-	justify-content: center;
-	align-items: center;
-	position: relative;
-	box-sizing: border-box;
-}
-
-.ac_c_i_t_p_box > div:hover{
-	background-color: #f2f4f7;
-}
-
-.ac_c_i_t_left {
-  width: 50px;
-  height: 50px;
-  border-radius: 8px;
-  margin-right: 10px;
-  box-sizing: border-box;
-  padding: 5px;
-}
-
-.ac_c_i_t_left > svg {
-  width: 100%;
-  height: 100%;
-}
-
-.ac_c_i_t_right {
-  width: calc(100% - 60px);
-  height: 100%;
-  display: flex;
-  flex-direction: column;
-  justify-content: space-evenly;
-}
-
-.ac_c_i_t_right > div {
-  font-size: 22px;
-  font-weight: bold;
-  max-width: 100%;
-  overflow: hidden;
-  text-overflow: ellipsis;
-  white-space: nowrap;
-}
-
-.ac_c_i_t_right > span {
-  font-size: 16px;
-  font-weight: bold;
-  color: #8991a1;
-  display: block;
-  max-width: 100%;
-  overflow: hidden;
-  text-overflow: ellipsis;
-  white-space: nowrap;
-}
-
-.ac_c_i_bottom {
-  width: 100%;
-  height: calc(100% - 60px);
-  margin-top: 15px;
-}
-
-.ac_c_i_bottom > div {
-  font-size: 20px;
-  color: #8991a1;
-  width: 100%;
-  height: calc(100% - 30px);
-  /* 第四行溢出显示... */
-  display: -webkit-box;
-  display: block;
-  overflow: hidden;
-  text-overflow: ellipsis;
-  -webkit-line-clamp: 4;
-  -webkit-box-orient: vertical;
-}
-
-.ac_c_i_bottom > span {
-  margin-top: 5px;
-  font-size: 16px;
-  color: #409eff;
-  overflow: hidden;
-  display: block;
-  text-overflow: ellipsis;
-  white-space: nowrap;
-  cursor: pointer;
-}
-
-
 </style>

+ 924 - 0
src/components/pages/appStore/views/appManagement.vue

@@ -0,0 +1,924 @@
+<template>
+  <div class="appManagement">
+    <div class="ac_left">
+			<!-- <recentUseCard/>
+			<collectCard/> -->
+			<saveCard title="最近使用" :data="recentUse"/>
+			<saveCard title="收藏" :data="collect"/>
+		</div>
+    <div class="ac_right">
+      <div class="ac_header">
+        <div class="ac_h_top">
+					<span>应用管理</span>
+          <!-- <span class="ac_h_t_active">应用管理</span>
+          <span @click="changeShowPage(1)">工作空间</span> -->
+          <el-button
+            type="primary"
+            size="small"
+            icon="el-icon-plus"
+            style="position: absolute;right: 15px;"
+            @click="addApp"
+            >添加应用</el-button
+          >
+        </div>
+				<!-- <div class="ac_h_banner">
+					<img src="https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/default%2Fae42534d-ee90-4bb1-8ef9-d344ee27b8241733733277828.jpg" alt="banner图">
+				</div> -->
+        <div class="ac_h_bottom">
+          <div class="ac_h_b_typeList">
+            <span
+              :class="{ ac_h_b_typeList_active: showType === '' }"
+              @click="changeType('')"
+              >全部</span
+            >
+            <span
+              v-for="item in typeList"
+              :key="item.id"
+              :class="{ ac_h_b_typeList_active: showType === item.id }"
+              @click="changeType(item.id)"
+              >{{ item.name }}</span
+            >
+          </div>
+					<div class="ac_h_b_selectList">
+            <el-input
+              v-model="searchText"
+              style="width: 200px;margin-right: 10px;"
+              placeholder="请输入应用名称"
+              @keyup.enter.native="getData"
+            />
+            <el-select
+              v-model="selectJuri"
+              placeholder="请选择"
+              @change="changeSelectType"
+            >
+              <el-option
+                v-for="item in selectList"
+                :key="item.index"
+                :label="item.label"
+                :value="item.index"
+              ></el-option>
+            </el-select>
+            <el-button
+              type="primary"
+              style="margin-left: 10px;"
+              icon="el-icon-search"
+              @click="getData"
+            ></el-button>
+            <el-button type="primary" @click="resetData">重置</el-button>
+          </div>
+        </div>
+      </div>
+
+      <div class="ac_content">
+        <div
+          class="ac_c_item"
+          v-for="(item, index) in dataList"
+          :key="item.id"
+          @click="openApp(item)"
+        >
+          <div class="ac_c_i_top">
+            <div class="ac_c_i_t_left">
+              <svg
+                v-if="isImageOrSvg(typeof item.json =='object'?item.json.icon:'') === 0"
+                t="1732605901531"
+                class="icon"
+                viewBox="0 0 1024 1024"
+                version="1.1"
+                xmlns="http://www.w3.org/2000/svg"
+                p-id="4275"
+                width="200"
+                height="200"
+              >
+                <path
+                  d="M179.2 153.6a51.2 51.2 0 0 0-51.2 51.2v128a51.2 51.2 0 0 0 51.2 51.2h128a51.2 51.2 0 0 0 51.2-51.2V204.8a51.2 51.2 0 0 0-51.2-51.2H179.2z m0-102.4h128a153.6 153.6 0 0 1 153.6 153.6v128a153.6 153.6 0 0 1-153.6 153.6H179.2a153.6 153.6 0 0 1-153.6-153.6V204.8a153.6 153.6 0 0 1 153.6-153.6z m0 614.4a51.2 51.2 0 0 0-51.2 51.2v128a51.2 51.2 0 0 0 51.2 51.2h128a51.2 51.2 0 0 0 51.2-51.2V716.8a51.2 51.2 0 0 0-51.2-51.2H179.2z m0-102.4h128a153.6 153.6 0 0 1 153.6 153.6v128a153.6 153.6 0 0 1-153.6 153.6H179.2a153.6 153.6 0 0 1-153.6-153.6V716.8a153.6 153.6 0 0 1 153.6-153.6z m611.84-403.4048a51.2 51.2 0 0 0-72.3968 0L646.144 232.2432a51.2 51.2 0 0 0 0 72.3968l72.448 72.3968a51.2 51.2 0 0 0 72.3968 0l72.3968-72.3968a51.2 51.2 0 0 0 0-72.3968L791.04 159.744z m72.3968-72.3968l72.3968 72.3968a153.6 153.6 0 0 1 0 217.2416l-72.3968 72.3968a153.6 153.6 0 0 1-217.2416 0l-72.3968-72.3968a153.6 153.6 0 0 1 0-217.2416l72.3968-72.3968a153.6 153.6 0 0 1 217.2416 0zM699.7504 896a51.2 51.2 0 0 1 0 102.4A162.1504 162.1504 0 0 1 537.6 836.2496v-110.8992A162.1504 162.1504 0 0 1 699.7504 563.2h110.8992a162.1504 162.1504 0 0 1 162.1504 162.1504v8.448a51.2 51.2 0 0 1-102.4 0v-8.448c0-33.024-26.7264-59.7504-59.7504-59.7504h-110.8992c-33.024 0-59.7504 26.7264-59.7504 59.7504v110.8992c0 33.024 26.7264 59.7504 59.7504 59.7504z"
+                  fill="#2C6DD2"
+                  p-id="4276"
+                ></path>
+                <path
+                  d="M791.4496 160a51.2 51.2 0 0 0-72.3968 0l-72.448 72.3968a51.2 51.2 0 0 0 0 72.3968l72.448 72.3968a51.2 51.2 0 0 0 72.3968 0l72.3968-72.3968a51.2 51.2 0 0 0 0-72.3968l-72.3968-72.3968z"
+                  fill="#20C997"
+                  p-id="4277"
+                ></path>
+              </svg>
+              <span
+                v-if="isImageOrSvg(typeof item.json =='object'?item.json.icon:'') === 1"
+                v-html="item.json.icon"
+              ></span>
+              <el-image
+                v-if="isImageOrSvg(typeof item.json =='object'?item.json.icon:'') === 2"
+                style="width: 100%; height: 100%"
+                :src="item.json.icon"
+                fit="cover"
+              ></el-image>
+            </div>
+            <div class="ac_c_i_t_right">
+              <div>{{ item.name }}</div>
+              <span>{{ item.label }}</span>
+            </div>
+            <div class="ac_c_i_t_popover">
+              <div
+                class="ac_c_i_t_p_box"
+                v-if="editAppCard === item.id"
+                v-click-outside="handleBlur"
+              >
+                
+								<div @click.stop="cancelCollectApp(item)"  v-if="collect.map(i=>i.id).includes(item.id)">取消收藏</div>
+                <div @click.stop="collectApp(item)" v-else>收藏</div>
+								<div @click.stop="copyApp(item)" v-if="item.json && item.json.copy==='1'">复制</div>
+								<div @click.stop="updateApp(item)" v-if="item.userid === userId">修改</div>
+								<div @click.stop="delApp(item)" v-if="item.userid === userId">删除</div>
+              </div>
+              <svg
+                t="1732786015570"
+                @click.stop="updateCard(item.id)"
+                class="icon"
+                viewBox="0 0 1024 1024"
+                version="1.1"
+                xmlns="http://www.w3.org/2000/svg"
+                p-id="9199"
+                width="200"
+                height="200"
+              >
+                <path
+                  d="M192 443.733333c-38.4 0-68.266667 29.866667-68.266667 68.266667 0 38.4 29.866667 68.266667 68.266667 68.266667s68.266667-29.866667 68.266667-68.266667c0-38.4-29.866667-68.266667-68.266667-68.266667zM512 443.733333c-38.4 0-68.266667 29.866667-68.266667 68.266667 0 38.4 29.866667 68.266667 68.266667 68.266667s68.266667-29.866667 68.266667-68.266667c0-38.4-29.866667-68.266667-68.266667-68.266667zM832 443.733333c-38.4 0-68.266667 29.866667-68.266667 68.266667 0 38.4 29.866667 68.266667 68.266667 68.266667s68.266667-29.866667 68.266667-68.266667c0-38.4-34.133333-68.266667-68.266667-68.266667z"
+                  fill="#111111"
+                  p-id="9200"
+                ></path>
+              </svg>
+            </div>
+          </div>
+          <div class="ac_c_i_bottom">
+            <div>{{ item.detail }}</div>
+            <!-- <span @click="openApp(item.url)">{{ item.url }}</span> -->
+          </div>
+        </div>
+        <div class="ac_c_empty" v-if="dataList.length === 0">
+          <span>暂无数据...</span>
+        </div>
+      </div>
+    </div>
+    <addAppDialog
+      ref="addAppDialogRef"
+      :typeList="typeList"
+      @success="addAppSuccess"
+    />
+  </div>
+</template>
+
+<script>
+const clickOutside = {
+  bind(el, binding) {
+    // 在元素上绑定一个点击事件监听器
+    el.clickOutsideEvent = function(event) {
+      // 检查点击事件是否发生在元素的内部
+      if (!(el === event.target || el.contains(event.target))) {
+        // 如果点击事件发生在元素的外部,则触发指令绑定的方法,将点击的event数据传过去
+        binding.value(event);
+      }
+    };
+    // 在文档上添加点击事件监听器
+    document.addEventListener("click", el.clickOutsideEvent);
+  },
+  unbind(el) {
+    // 在元素上解除点击事件监听器
+    document.removeEventListener("click", el.clickOutsideEvent);
+  }
+};
+import addAppDialog from "../dialog/addAppDialog.vue";
+import saveCard from "../dialog/saveCard.vue";
+// import collectCard from "./dialog/collectCard.vue";
+// import recentUseCard from "./dialog/recentUseCard.vue";
+export default {
+  components: {
+    addAppDialog,
+		saveCard
+		// collectCard,
+		// recentUseCard
+  },
+  directives: {
+    "click-outside": clickOutside // 注册自定义指令
+  },
+  data() {
+    return {
+      showType: "",
+      searchText: "",
+      selectJuri: 3,
+      typeList: [],
+      selectList: [
+        { index: 1, label: "我的" },
+        { index: 2, label: "组织" },
+        { index: 3, label: "所有人" }
+      ],
+      userId: this.$route.query["userid"],
+      org: this.$route.query["org"],
+      oid: this.$route.query["oid"],
+      getDataLoading: false,
+      dataList: [],
+      recentUse: [],
+      collect: [],
+      editAppCard: null
+    };
+  },
+  computed: {
+    isImageOrSvg() {
+      return value => {
+        let _result = 0; //啥也不是
+        if (value) {
+          const svgPattern = /<svg.*<\/svg>/;
+          const imagePattern = /\.(jpeg|jpg|gif|png|svg|bmp|webp)$/i; // 图片链接的正则表达式
+          const urlPattern = /^(http|https):\/\/[^ "]+$/; // 网络地址的正则表达式
+
+          if (svgPattern.test(value)) {
+            _result = 1;
+          } else if (urlPattern.test(value) && imagePattern.test(value)) {
+            _result = 2;
+          }
+        }
+        return _result;
+      };
+    }
+  },
+  methods: {
+    changeType(newIndex) {
+      let flag = this.showType === newIndex;
+      this.showType = newIndex;
+      if (!flag) {
+        this.getData();
+      }
+    },
+    changeSelectType() {
+      this.getData();
+    },
+    getData() {
+      this.getDataLoading = true;
+      let params = {
+        uid: this.userId, //用户ID
+        name: this.searchText, //应用名称搜索
+        label: "", //应用的标签搜索
+        type: this.showType, //应用的类型
+        juri: this.selectJuri, //应用权限 1:我的  2:组织内  3:所有人
+        stand: "cn" //cn站还是hk站
+      };
+
+      this.ajax
+        .get(this.$store.state.api + "select_appStore", params)
+        .then(res => {
+          this.getDataLoading = false;
+          let _data = res.data[0];
+          if (_data.length > 0) {
+            _data.forEach(i => {
+              if (i.json) {
+                i.json = JSON.parse(i.json);
+              }
+            });
+            this.dataList = _data;
+          } else {
+            this.dataList = [];
+          }
+        })
+        .catch(err => {
+          this.getDataLoading = false;
+          console.log(err);
+          this.$message.error("获取应用失败");
+        });
+    },
+    addApp() {
+      this.$refs.addAppDialogRef.open({ type: 1 });
+    },
+    updateApp(data) {
+      this.$refs.addAppDialogRef.open({
+        type: 2,
+        form: {
+          id: data.id,
+          name: data.name,
+          label: data.label,
+          detail: data.detail,
+          url: data.url,
+          type: data.type,
+          juri: data.juri,
+          stand: data.stand,
+          json: data.json
+        }
+      });
+    },
+    // 收藏APP
+    collectApp(item) {
+			this.editAppCard = null;
+			this.insertSave(item,0)
+		},
+		//复制app
+		copyApp(item){
+			this.$confirm(`确定复制《${item.name}》这个应用吗?`,"复制",{
+				confirmButtonText:"确定",
+				cancelButtonText:"取消",
+				type:"warning"
+			}).then(()=>{
+				let params = [
+          {
+            name: `${item.name}_copy`, //app名称
+            userid: this.userId, //创建的用户ID
+            label: item.label, //app标签
+            detail: item.detail, //app简介
+            url: item.url, //app链接
+            type: item.type, //app类型
+            juri: "1", //app权限 1:我的 2:组织 3:所有人
+            stand: "cn", //语言
+            json: JSON.stringify(item.json) //其他信息
+          }
+        ];
+				this.ajax
+          .post(this.$store.state.api + "insert_appStore", params)
+          .then(res => {
+            if (res.data == 1) {
+              this.$message.success("复制成功");
+              this.getData();
+            } else {
+              this.$message.error("复制失败");
+            }
+          })
+          .catch(err => {
+            console.log(err);
+            this.$message.error("复制失败");
+          });
+			}).catch(_=>{
+				console.log("取消复制")
+			})
+		},
+		// 取消收藏
+		cancelCollectApp(item){
+			this.editAppCard = null;
+			let _data = this.collect.find(i=>i.id===item.id);
+			if(_data){
+				let params = [{
+					sid:_data.sid
+				}]
+				this.ajax.post(this.$store.state.api+"delete_appStoreSave",params).then(res=>{
+					if(res.data){
+						this.$message.success("取消收藏成功")
+					}
+					this.getCollect();
+				}).catch(e=>{
+					console.log(e)
+					this.$message.error("取消收藏失败")
+					this.getCollect();
+				})
+			}else{
+				this.$message.error("取消收藏失败");
+				this.getCollect();
+			}
+			
+		},
+    updateCard(id) {
+      if (this.editAppCard === id) return (this.editAppCard = null);
+      this.editAppCard = id;
+    },
+    handleBlur() {
+      this.updateCard(null);
+    },
+    addAppSuccess(data, type) {
+      if (type === 1) {
+        //添加
+        let params = [
+          {
+            name: data.name, //app名称
+            userid: this.userId, //创建的用户ID
+            label: data.label, //app标签
+            detail: data.detail, //app简介
+            url: data.url, //app链接
+            type: data.type, //app类型
+            juri: data.juri, //app权限 1:我的 2:组织 3:所有人
+            stand: "cn", //语言
+            json: JSON.stringify(data.json) //其他信息
+          }
+        ];
+        this.ajax
+          .post(this.$store.state.api + "insert_appStore", params)
+          .then(res => {
+            if (res.data == 1) {
+              this.$message.success("添加成功");
+              this.$refs.addAppDialogRef.close(true);
+              this.getData();
+            } else {
+              this.$message.error("添加失败");
+              this.$refs.addAppDialogRef.loading = false;
+            }
+          })
+          .catch(err => {
+            console.log(err);
+            this.$message.error("添加失败");
+          });
+      } else if (type === 2) {
+        let params = [
+          {
+            aid: data.id,
+            name: data.name, //app名称
+            userid: this.userId, //创建的用户ID
+            label: data.label, //app标签
+            detail: data.detail, //app简介
+            url: data.url, //app链接
+            type: data.type, //app类型
+            juri: data.juri, //app权限 1:我的 2:组织 3:所有人
+            stand: "cn", //语言
+            json: JSON.stringify(data.json) //其他信息
+          }
+        ];
+        this.ajax
+          .post(this.$store.state.api + "update_appStore", params)
+          .then(res => {
+            if (res.data == 1) {
+              this.$message.success("修改成功");
+              this.$refs.addAppDialogRef.close(true);
+              this.getData();
+            } else {
+              this.$message.error("修改失败");
+              this.$refs.addAppDialogRef.loading = false;
+            }
+          })
+          .catch(err => {
+            console.log(err);
+            this.$message.error("修改失败");
+          });
+      }
+    },
+    getTypeList() {
+      let params = {
+        suserid: this.userId, //用户ID
+        sorg: this.org,
+        soid: this.oid,
+        sstand: "cn"
+      };
+
+      this.ajax
+        .get(this.$store.state.api + "select_appStoreType", params)
+        .then(res => {
+          let data = res.data[0];
+          if (data.length > 0) {
+            this.typeList = data;
+          }
+        })
+        .catch(err => {
+          console.log(err);
+          this.$message.error("获取应用类型失败");
+        });
+    },
+    openApp(item) {
+      window.open(item.url, "_blank");
+			if (!(this.recentUse.length > 0 && item.id === this.recentUse[0].id)) {
+				this.insertSave(item,1);
+			}
+			
+    },
+    resetData() {
+      this.searchText = "";
+      this.selectJuri = 3;
+      this.showType = "";
+      this.getData();
+    },
+		getRecentUse(){
+			let params = {
+				uid:this.userId,
+				type:1,
+				limit:10,
+			}
+
+			this.ajax.get(this.$store.state.api+"select_appStoreSave",params).then(res=>{
+				let data = res.data[0];
+				if(data.length>0){
+					data.forEach(i => {
+            if (i.json) {
+              i.json = JSON.parse(i.json);
+            }
+          });
+					this.recentUse = data;
+				}else{
+					this.recentUse = [];
+				}
+			}).catch(err=>{
+				console.log(err)
+				console.log("获取最近使用失败")
+				// this.$message.error("获取收藏应用失败")
+			})
+
+		},
+		getCollect(){
+			let params = {
+				uid:this.userId,
+				type:0,
+				limit:0,
+			}
+			this.ajax.get(this.$store.state.api+"select_appStoreSave",params).then(res=>{
+				let data = res.data[0];
+				if(data.length>0){
+					data.forEach(i => {
+            if (i.json) {
+              i.json = JSON.parse(i.json);
+            }
+          });
+					this.collect = data;
+				}else{
+					this.collect = [];
+				}
+			}).catch(err=>{
+				console.log(err)
+				this.$message.error("获取收藏应用失败")
+			})
+		},
+		insertSave(item,type){
+			let params = [{
+				uid:this.userId,
+				type:type,
+				aid:item.id,
+				json:"",
+			}]
+
+			this.ajax.post(this.$store.state.api+"insert_appStoreSave",params).then(res=>{
+				if(res.data){
+					if(type===0){
+						this.$message.success("收藏成功")
+						this.getCollect();
+					}else if(type===1){
+						this.getRecentUse();
+					}
+				}
+			}).catch(err=>{
+				console.log(err)
+				if(type===0)this.$message.error("收藏失败")
+			})
+
+		},
+		delApp(item){
+			this.$confirm(`确定要删除《${item.name}》这个应用吗,删除后无法找回!`, `确定删除应用`, {
+				confirmButtonText: '确定',
+				cancelButtonText: '取消',
+				type: 'warning'
+			}).then(() => {
+				let params = [{
+					uid: this.userId,
+					aid: item.id
+				}];
+				this.ajax.post(this.$store.state.api + "delete_appStore", params).then(res => {
+					if (res.data) {
+						this.$message.success("删除成功");
+						this.getData();
+					} else {
+						this.$message.error("删除失败");
+					}
+				}).catch(err => {
+					console.log(err);
+					this.$message.error("删除失败");
+				});
+			}).catch(() => {
+				console.log("取消删除");
+			});
+		},
+		changeShowPage(newPage){
+			this.$emit("changeShowCard",newPage)
+		}
+  },
+  mounted() {
+    this.getTypeList();
+    this.getData();
+		this.getCollect();
+		this.getRecentUse();
+  }
+};
+</script>
+
+<style scoped>
+.appManagement {
+  width: 100vw;
+  height: 100vh;
+  background-color: #f2f4f7;
+  margin: 0;
+  overflow: auto;
+  box-sizing: border-box;
+  padding: 20px;
+  display: flex;
+  justify-content: space-between;
+}
+
+.ac_left {
+	width: 280px;
+  min-width: 280px;
+  margin-right: 20px;
+  height: 100%;
+  border-radius: 5px;
+  background-color: #fff;
+  box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.1);
+	box-sizing: border-box;
+	padding: 10px;
+	overflow: auto;
+}
+
+.ac_right {
+  width: calc(100% - 280px);
+  min-width: 800px;
+  height: 100%;
+  overflow-y: hidden;
+  display: flex;
+  flex-direction: column;
+}
+
+.ac_header {
+  width: 100%;
+  height: auto;
+  border-radius: 5px;
+  background-color: #fff;
+  box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.1);
+}
+
+.ac_h_top {
+  width: 100%;
+  height: 50px;
+  display: flex;
+  align-items: center;
+  box-sizing: border-box;
+  padding: 0 15px;
+  border-bottom: 1px solid #eeeeee;
+  position: relative;
+}
+
+.ac_h_top > span {
+  font-size: 26px;
+	position: relative;
+	margin-right: 25px;
+	cursor: pointer;
+}
+
+.ac_h_t_active::after{
+	content: "";
+	position: absolute;
+	width: 100%;
+	height: 3px;
+	border-radius: 4px;
+	background-color: #409EFF;
+	left: 0;
+	bottom: -5px;
+}
+
+.ac_h_banner{
+	width: 100%;
+	height: 200px;
+	border-radius: 5px;
+	overflow: hidden;
+	box-sizing: border-box;
+	padding: 10px;
+}
+
+.ac_h_banner>img{
+	width: 100%;
+	height: 100%;
+	object-fit:cover;
+	border-radius: 5px;
+}
+
+.ac_h_bottom {
+  width: 100%;
+  height: auto;
+  padding: 10px 15px 10px 15px;
+	box-sizing: border-box;
+	display: flex;
+	justify-content: space-between;
+	align-items: center;
+}
+
+.ac_h_b_typeList {
+  width: calc(100% - 400px);
+  height: auto;
+  display: flex;
+  flex-wrap: wrap;
+  box-sizing: border-box;
+}
+
+.ac_h_b_typeList > span {
+  font-size: 18px;
+  margin-right: 20px;
+  margin-top: 10px;
+  margin-bottom: 5px;
+  cursor: pointer;
+}
+
+.ac_h_b_typeList_active {
+  color: #007aff;
+}
+
+.ac_h_b_selectList {
+  margin-left: 15px;
+  margin-bottom: 10px;
+	display: flex;
+	align-items: center;
+}
+
+.ac_content {
+  width: 100%;
+  flex: 1;
+  height: auto;
+  margin-top: 20px;
+  overflow: auto;
+}
+
+.ac_c_item {
+  width: calc(100% / 5 - (15px * 4) / 5);
+  height: 250px;
+  background-color: #fff;
+  border-radius: 10px;
+  box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.1);
+  box-sizing: border-box;
+  padding: 15px;
+  margin-right: 15px;
+  margin-bottom: 15px;
+  float: left;
+  cursor: pointer;
+}
+
+@media screen and (min-width: 1400px) {
+  .ac_c_item {
+    width: calc(100% / 5 - (15px * 4) / 5) !important;
+  }
+  .ac_c_item:nth-child(5n) {
+    margin-right: 0px !important;
+    /* background-color: red; */
+  }
+}
+
+@media screen and (max-width: 1380px) {
+  .ac_c_item {
+    width: calc(100% / 4 - (15px * 3) / 4) !important;
+  }
+
+  .ac_c_item:nth-child(4n) {
+    margin-right: 0px !important;
+  }
+
+  /* .ac_c_item:nth-child(5n) {
+    margin-right: 0 !important;
+  } */
+}
+
+@media screen and (max-width: 1080px) {
+  .ac_c_item {
+    width: calc(100% / 3 - (15px * 2) / 3) !important;
+  }
+
+  .ac_c_item:nth-child(5n) {
+    margin-right: 15px !important;
+  }
+
+  .ac_c_item:nth-of-type(4n) {
+    margin-right: 15px !important;
+  }
+
+  .ac_c_item:nth-child(3n) {
+    margin-right: 0 !important;
+  }
+}
+
+.ac_c_empty {
+  width: 100%;
+  height: 40%;
+  display: flex;
+  box-sizing: border-box;
+  padding-top: 2%;
+  justify-content: center;
+  /* align-items: center; */
+}
+
+.ac_c_i_top {
+  width: 100%;
+  height: 50px;
+  display: flex;
+  position: relative;
+  /* flex-direction: column; */
+  /* justify-content: space-evenly; */
+  /* background-color: red */
+}
+
+.ac_c_i_t_popover {
+  width: 30px;
+  height: 30px;
+  position: absolute;
+  right: 0;
+  top: 0;
+}
+
+.ac_c_i_t_popover svg {
+  width: 25px;
+  height: 25px;
+  cursor: pointer;
+}
+
+.ac_c_i_t_p_box {
+  position: absolute;
+  height: auto;
+  top: 100%;
+  right: 0;
+  padding: 8px;
+  border-radius: 8px 0 8px 8px;
+  background-color: #fff;
+  box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.1);
+  width: auto;
+}
+
+.ac_c_i_t_p_box > div {
+  width: 80px;
+  height: 30px;
+  cursor: pointer;
+  transition: 0.3s;
+  font-weight: bold;
+  font-size: .9em;
+  border-radius: 5px;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  position: relative;
+  box-sizing: border-box;
+}
+
+.ac_c_i_t_p_box > div:hover {
+  background-color: #f2f4f7;
+}
+
+.ac_c_i_t_left {
+  width: 50px;
+  height: 50px;
+  border-radius: 8px;
+  margin-right: 10px;
+  box-sizing: border-box;
+  padding: 5px;
+}
+
+.ac_c_i_t_left > svg {
+  width: 100%;
+  height: 100%;
+}
+
+.ac_c_i_t_left >span{
+	width: 100%;
+	height: 100%;
+	display: block;
+}
+
+.ac_c_i_t_left >span>>>svg{
+	width: 100%;
+	height: 100%;
+}
+
+.ac_c_i_t_right {
+  width: calc(100% - 60px);
+  height: 100%;
+  display: flex;
+  flex-direction: column;
+  justify-content: space-evenly;
+}
+
+.ac_c_i_t_right > div {
+  font-size: 22px;
+  font-weight: bold;
+  max-width: 100%;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
+.ac_c_i_t_right > span {
+  font-size: 1.1em;
+  font-weight: bold;
+  color: #8991a1;
+  display: block;
+  max-width: 100%;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
+.ac_c_i_bottom {
+  width: 100%;
+  height: calc(100% - 60px);
+  margin-top: 15px;
+}
+
+.ac_c_i_bottom > div {
+  font-size: 1em;
+  color: #8991a1;
+  width: 100%;
+  height: calc(100%);
+  /* 第四行溢出显示... */
+  display: -webkit-box;
+  display: block;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  -webkit-line-clamp: 8;
+  -webkit-box-orient: vertical;
+}
+
+.ac_c_i_bottom > span {
+  margin-top: 5px;
+  font-size: 1em;
+  color: #409eff;
+  overflow: hidden;
+  display: block;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+  cursor: pointer;
+}
+</style>

+ 119 - 0
src/components/pages/appStore/views/workSpace.vue

@@ -0,0 +1,119 @@
+<template>
+  <div class="workSpace">
+    <div class="ac_header">
+      <div class="ac_h_top">
+        <span @click="changeShowPage(0)">应用管理</span>
+				<span class="ac_h_t_active">工作空间</span>
+      </div>
+    </div>
+		<div class="ac_content">
+
+		</div>
+  </div>
+</template>
+
+<script>
+export default {
+	data(){
+		return{
+
+		}
+	},
+	methods:{
+		changeShowPage(newPage){
+			this.$emit("changeShowCard",newPage)
+		}
+	}
+};
+</script>
+
+<style scoped>
+.workSpace {
+  width: 100vw;
+  height: 100vh;
+  background-color: #f2f4f7;
+  margin: 0;
+  overflow: auto;
+  box-sizing: border-box;
+  padding: 20px;
+  display: flex;
+  justify-content: space-between;
+}
+.ac_header {
+  width: 100%;
+  height: auto;
+  border-radius: 5px;
+  background-color: #fff;
+  box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.1);
+}
+
+.ac_h_top {
+  width: 100%;
+  height: 50px;
+  display: flex;
+  align-items: center;
+  box-sizing: border-box;
+  padding: 0 15px;
+  border-bottom: 1px solid #eeeeee;
+  position: relative;
+	padding-left: 315px;
+}
+
+.ac_h_top > span {
+  font-size: 26px;
+	position: relative;
+	margin-right: 25px;
+	cursor: pointer;
+}
+
+.ac_h_t_active::after{
+	content: "";
+	position: absolute;
+	width: 100%;
+	height: 3px;
+	border-radius: 4px;
+	background-color: #409EFF;
+	left: 0;
+	bottom: -5px;
+}
+
+.ac_h_bottom {
+  width: 100%;
+  height: auto;
+  padding: 10px 0 20px 0;
+}
+
+.ac_h_b_typeList {
+  width: 100%;
+  height: auto;
+  display: flex;
+  flex-wrap: wrap;
+  box-sizing: border-box;
+  padding: 0 15px;
+}
+
+.ac_h_b_typeList > span {
+  font-size: 18px;
+  margin-right: 20px;
+  margin-top: 10px;
+  margin-bottom: 5px;
+  cursor: pointer;
+}
+
+.ac_h_b_typeList_active {
+  color: #007aff;
+}
+
+.ac_h_b_selectList {
+  margin-left: 15px;
+  margin-bottom: 10px;
+}
+
+.ac_content{
+	width: 100%;
+  flex: 1;
+  height: auto;
+  margin-top: 20px;
+  overflow: auto;
+}
+</style>

+ 4 - 4
src/components/pages/components/exjsmind.vue

@@ -69,7 +69,7 @@ export default {
 
       let elements = this.$refs.jsm.getElementsByClassName("jsmind-inner")[0];
 
-      let sw = (815 / jm.view.size.w).toFixed(2);
+      let sw = (715 / jm.view.size.w).toFixed(2);
 
       elements.style.height = `${jm.view.size.h * sw}px`;
 
@@ -90,9 +90,9 @@ export default {
   /* align-items: center; */
   /* justify-content: center; */
   /* min-width: 20px; */
-  max-width: 250px;
-  overflow: hidden;
-  letter-spacing: 3px;
+  /* max-width: 250px; */
+  /* overflow: hidden; */
+  letter-spacing: 5px;
   font-size: 12px !important;
   /* flex-wrap: wrap; */
   /* white-space: wrap; */

File diff suppressed because it is too large
+ 387 - 391
src/components/pages/components/exportDataDialog.vue


+ 276 - 285
src/components/pages/components/exportWorksDialog.vue

@@ -88,7 +88,7 @@
           v-if="isStage(i.taskList)"
           class="stageCon"
         >
-          <div v-if="CState != 5" class="stageTit">
+          <div v-if="CState != 5 && CState != 6" class="stageTit">
             第{{ i.id * 1 + 1 }}阶段<span v-if="i.name">:{{ i.name }}</span>
           </div>
           <div
@@ -280,51 +280,90 @@
                   </div>
                 </div>
                 <div v-if="l.tool[0] == 45">
-                    <div class="toolBlk">
-                      <img
-                        src="../../../assets/icon/thirdToolList/choose.png"
-                        alt=""
-                      />
-                      <div class="toolTit">
-                        <div>工具{{ lind + 1 }}:选择题</div>
-                        <div>
-                          根据前期的了解与实地调研对于项目的了解,进行思考与讨论提出问题。
-                        </div>
+                  <div class="toolBlk">
+                    <img
+                      src="../../../assets/icon/thirdToolList/choose.png"
+                      alt=""
+                    />
+                    <div class="toolTit">
+                      <div>工具{{ lind + 1 }}:选择题</div>
+                      <div>
+                        根据前期的了解与实地调研对于项目的了解,进行思考与讨论提出问题。
                       </div>
                     </div>
+                  </div>
+                  <div
+                    v-for="(i, index) in l.content[0].testJson"
+                    :key="index + 'm'"
+                  >
+                    <div>
+                      题目:{{ i.teststitle }}
+                      <span
+                        v-if="
+                          JSON.stringify(l.content[0].radio[index]) ==
+                            JSON.stringify(i.answer)
+                        "
+                        style="color: #868ce4"
+                        >回答正确</span
+                      >
+                      <span v-else style="color: red">回答错误</span>
+                    </div>
                     <div
-                      v-for="(i, index) in l.content[0].testJson"
-                      :key="index + 'm'"
+                      v-if="i.type == 1"
+                      style="display: flex; flex-direction: column"
                     >
-                      <div>
-                        题目:{{ i.teststitle }}
-                        <span
-                          v-if="
-                            JSON.stringify(l.content[0].radio[index]) ==
-                              JSON.stringify(i.answer)
-                          "
-                          style="color: #868ce4"
-                          >回答正确</span
-                        >
-                        <span v-else style="color: red">回答错误</span>
-                      </div>
-                      <div
-                        v-if="i.type == 1"
-                        style="display: flex; flex-direction: column"
-                      >
-                        <el-radio-group v-model="l.content[0].radio[index]">
-                          <div class="radioBox">
-                            <el-radio
-                              v-for="(item2, checkIndex) in i.checkList"
-                              :key="checkIndex + 'b'"
-                              :label="checkIndex"
-                              disabled
-                              :class="[
-                                i.answer == checkIndex
-                                  ? 'redioStyle5'
-                                  : 'redioStyle2'
-                              ]"
+                      <el-radio-group v-model="l.content[0].radio[index]">
+                        <div class="radioBox">
+                          <el-radio
+                            v-for="(item2, checkIndex) in i.checkList"
+                            :key="checkIndex + 'b'"
+                            :label="checkIndex"
+                            disabled
+                            :class="[
+                              i.answer == checkIndex
+                                ? 'redioStyle5'
+                                : 'redioStyle2'
+                            ]"
+                          >
+                            <div
+                              v-if="
+                                item2 && item2.imgType && item2.imgType == 1
+                              "
                             >
+                              <div
+                                class="inImg"
+                                @click.stop="previewImg(item2.src)"
+                              >
+                                <img
+                                  style="display: block"
+                                  :src="item2.src"
+                                  alt=""
+                                />
+                              </div>
+                            </div>
+                            <span v-else v-html="item2"></span>
+                          </el-radio>
+                        </div>
+                      </el-radio-group>
+                    </div>
+                    <div class="radioBox">
+                      <el-checkbox-group
+                        v-model="l.content[0].radio[index]"
+                        v-if="i.type == '2'"
+                      >
+                        <div class="radioBox">
+                          <el-checkbox
+                            v-for="(item2, checkIndex) in i.checkList"
+                            :key="checkIndex + 'c'"
+                            :label="checkIndex"
+                            disabled
+                            :class="[
+                              i.answer.includes(checkIndex)
+                                ? 'redioStyle3'
+                                : 'redioStyle4'
+                            ]"
+                          >
+                            <div style="display: flex">
                               <div
                                 v-if="
                                   item2 && item2.imgType && item2.imgType == 1
@@ -342,115 +381,74 @@
                                 </div>
                               </div>
                               <span v-else v-html="item2"></span>
-                            </el-radio>
-                          </div>
-                        </el-radio-group>
-                      </div>
-                      <div class="radioBox">
-                        <el-checkbox-group
-                          v-model="l.content[0].radio[index]"
-                          v-if="i.type == '2'"
-                        >
-                          <div class="radioBox">
-                            <el-checkbox
-                              v-for="(item2, checkIndex) in i.checkList"
-                              :key="checkIndex + 'c'"
-                              :label="checkIndex"
-                              disabled
-                              :class="[
-                                i.answer.includes(checkIndex)
-                                  ? 'redioStyle3'
-                                  : 'redioStyle4'
-                              ]"
-                            >
-                              <div style="display: flex">
-                                <div
-                                  v-if="
-                                    item2 && item2.imgType && item2.imgType == 1
-                                  "
-                                >
-                                  <div
-                                    class="inImg"
-                                    @click.stop="previewImg(item2.src)"
-                                  >
-                                    <img
-                                      style="display: block"
-                                      :src="item2.src"
-                                      alt=""
-                                    />
-                                  </div>
-                                </div>
-                                <span v-else v-html="item2"></span>
-                              </div>
-                            </el-checkbox>
-                          </div>
-                        </el-checkbox-group>
-                      </div>
-                    </div>
-                  </div>
-                  <!-- 选择匹配 -->
-                  <div v-if="l.tool[0] == 41">
-                    <div class="toolBlk">
-                      <img
-                        class="toolImg"
-                        src="../../../assets/icon/thirdToolList/select.png"
-                        alt=""
-                      />
-                      <div class="toolTit">
-                        <div>工具{{ lind + 1 }}:选择匹配</div>
-                        <div>
-                          根据前期的了解与实地调研对于项目的了解,进行思考与讨论提出问题。
+                            </div>
+                          </el-checkbox>
                         </div>
-                      </div>
+                      </el-checkbox-group>
                     </div>
+                  </div>
+                </div>
+                <!-- 选择匹配 -->
+                <div v-if="l.tool[0] == 41">
+                  <div class="toolBlk">
                     <img
-                      @click.stop="previewImg(l.selectJson.url)"
-                      style="max-width: 200px"
-                      :src="l.selectJson.url"
+                      class="toolImg"
+                      src="../../../assets/icon/thirdToolList/select.png"
                       alt=""
                     />
-                    <div>
-                      <span style="margin-right: 10px">选项:</span
-                      ><span
-                        style="margin-right: 10px"
-                        v-for="(item, itInd) in l.selectJson.select"
-                        :key="itInd"
-                        >{{ item }}</span
-                      >
-                    </div>
-                    <div style="margin: 10px 0;">
-                      <span style="margin-right: 10px">回答:</span>
-
-                      <div
-                        style="margin-right: 10px"
-                        v-for="(item, itInd) in l.content[0]"
-                        :key="itInd"
-                      >
-                        选项{{ itInd + 1 }}:{{ l.selectJson.select[item] }}
-                        <span
-                          v-if="
-                            l.selectJson.answer[itInd] == l.content[0][itInd]
-                          "
-                          style="color: #868ce4"
-                          >回答正确</span
-                        >
-                        <span v-else style="color: red">回答错误</span>
+                    <div class="toolTit">
+                      <div>工具{{ lind + 1 }}:选择匹配</div>
+                      <div>
+                        根据前期的了解与实地调研对于项目的了解,进行思考与讨论提出问题。
                       </div>
                     </div>
-                    <div>
-                      <span style="margin-right: 10px">答案:</span>
+                  </div>
+                  <img
+                    @click.stop="previewImg(l.selectJson.url)"
+                    style="max-width: 200px"
+                    :src="l.selectJson.url"
+                    alt=""
+                  />
+                  <div>
+                    <span style="margin-right: 10px">选项:</span
+                    ><span
+                      style="margin-right: 10px"
+                      v-for="(item, itInd) in l.selectJson.select"
+                      :key="itInd"
+                      >{{ item }}</span
+                    >
+                  </div>
+                  <div style="margin: 10px 0;">
+                    <span style="margin-right: 10px">回答:</span>
 
+                    <div
+                      style="margin-right: 10px"
+                      v-for="(item, itInd) in l.content[0]"
+                      :key="itInd"
+                    >
+                      选项{{ itInd + 1 }}:{{ l.selectJson.select[item] }}
                       <span
-                        style="margin-right: 10px"
-                        v-for="(item, itInd) in l.selectJson.answer"
-                        :key="itInd"
-                        >选项{{ itInd + 1 }}:{{
-                          l.selectJson.select[item]
-                        }}</span
+                        v-if="l.selectJson.answer[itInd] == l.content[0][itInd]"
+                        style="color: #868ce4"
+                        >回答正确</span
                       >
+                      <span v-else style="color: red">回答错误</span>
                     </div>
                   </div>
-                  <!-- <div v-if="l.tool[0] == 41">
+                  <div>
+                    <span style="margin-right: 10px">答案:</span>
+
+                    <span
+                      style="margin-right: 10px"
+                      v-for="(item, itInd) in l.selectJson.answer"
+                      :key="itInd"
+                      >选项{{ itInd + 1 }}:{{
+                        l.selectJson.select[item]
+                      }}</span
+                    >
+                  </div>
+                </div>
+                <!-- <div v-if="l.tool[0] == 41">
                     <div class="toolBlk">
                       <img
                         src="../../../assets/icon/thirdToolList/select.png"
@@ -489,76 +487,76 @@
                     </div>
                   </div> -->
 
-                  <!-- 排序 -->
-                  <div v-if="l.tool[0] == 47">
-                    <div class="toolBlk">
-                      <img
-                        src="../../../assets/icon/fourthToolList/conSentences.png"
-                        alt=""
-                      />
-                      <div class="toolTit">
-                        <div>工具{{ lind + 1 }}:排序</div>
-                        <div>
-                          根据前期的了解与实地调研对于项目的了解,进行思考与讨论提出问题。
-                        </div>
+                <!-- 排序 -->
+                <div v-if="l.tool[0] == 47">
+                  <div class="toolBlk">
+                    <img
+                      src="../../../assets/icon/fourthToolList/conSentences.png"
+                      alt=""
+                    />
+                    <div class="toolTit">
+                      <div>工具{{ lind + 1 }}:排序</div>
+                      <div>
+                        根据前期的了解与实地调研对于项目的了解,进行思考与讨论提出问题。
                       </div>
                     </div>
+                  </div>
+                  <div
+                    v-for="(i, index) in l.content[0]"
+                    :key="index"
+                    style="margin-bottom: 10px"
+                  >
                     <div
-                      v-for="(i, index) in l.content[0]"
-                      :key="index"
-                      style="margin-bottom: 10px"
-                    >
-                      <div
-                        style="
+                      style="
                             height: 20px;
                             display: flex;
                             align-items: center;
                             flex-wrap: wrap;
                           "
+                    >
+                      题目:
+                      <div
+                        class="sortTool"
+                        v-for="(i, index) in i.addSentence"
+                        :key="index"
                       >
-                        题目:
-                        <div
-                          class="sortTool"
-                          v-for="(i, index) in i.addSentence"
-                          :key="index"
-                        >
-                          {{ i }}
-                        </div>
-                        <span
-                          v-if="
-                            JSON.stringify(i.chooseSenList) ==
-                              JSON.stringify(i.addSentence)
-                          "
-                          style="color: #868ce4"
-                          >回答正确</span
-                        >
-                        <span v-else style="color: red">回答错误</span>
+                        {{ i }}
                       </div>
-                      <div
-                        style="
+                      <span
+                        v-if="
+                          JSON.stringify(i.chooseSenList) ==
+                            JSON.stringify(i.addSentence)
+                        "
+                        style="color: #868ce4"
+                        >回答正确</span
+                      >
+                      <span v-else style="color: red">回答错误</span>
+                    </div>
+                    <div
+                      style="
                             margin: 10px 0;
                             display: flex;
                             align-items: center;
                             flex-wrap: wrap;
                           "
+                    >
+                      学生回答:
+                      <div
+                        class="sortTool"
+                        v-for="(i, index) in i.chooseSenList"
+                        :key="index"
                       >
-                        学生回答:
-                        <div
-                          class="sortTool"
-                          v-for="(i, index) in i.chooseSenList"
-                          :key="index"
-                        >
-                          {{ i }}
-                        </div>
-                      </div>
-                      <div>
-                        答案:
-                        <span style="margin: 0 5px">{{
-                          i.addSentence.join(",")
-                        }}</span>
+                        {{ i }}
                       </div>
                     </div>
+                    <div>
+                      答案:
+                      <span style="margin: 0 5px">{{
+                        i.addSentence.join(",")
+                      }}</span>
+                    </div>
                   </div>
+                </div>
               </div>
 
               <!-- ai作业得分  -->
@@ -568,7 +566,7 @@
                     l.content.length &&
                     l.eList &&
                     l.eList.length &&
-                    CState == 5
+                    (CState == 5 || CState == 6)
                 "
                 class="taskSco"
               >
@@ -586,7 +584,7 @@
                 <div class="taskScoCon">
                   <!-- 分数详情与素养 -->
                   <div style="flex: 1; display: flex; flex-wrap: wrap">
-                    <div style="width: 375px; margin:0 20px 10px 0">
+                    <div style="width: 315px; margin:0 20px 10px 0">
                       <div class="taskScoConTit">分数详情</div>
                       <div
                         v-for="(wItem, ind) in l.eList"
@@ -622,16 +620,16 @@
                       <div class="taskScoConTit">素养</div>
                       <div class="WorkConSY">
                         <div v-for="(wItem, ind) in l.eList" :key="ind + 's'">
-                          <el-tooltip
+                          <!-- <el-tooltip
                             class="item"
                             effect="dark"
-                            :content="wItem.detail"
+                            :content="wItem.target"
                             placement="top-start"
-                          >
+                          > -->
                             <div class="RootImgBlockSy">
                               {{ wItem.target }}
                             </div>
-                          </el-tooltip>
+                          <!-- </el-tooltip> -->
                         </div>
                       </div>
                     </div>
@@ -655,13 +653,14 @@
                   </div>
                 </div>
               </div>
-             
+
               <!-- 阶段  -->
               <div
                 v-if="
-                    l.eList &&
+                  l.eList &&
                     l.eList.length &&
-                    CState != 5 && 
+                    CState != 5 &&
+                    CState != 6 &&
                     lind == k.toolEList.length - 1
                 "
                 class="taskSco"
@@ -680,7 +679,7 @@
                 <div class="taskScoCon">
                   <!-- 分数详情与素养 -->
                   <div style="flex: 1; display: flex; flex-wrap: wrap">
-                    <div style="width: 375px; margin:0 20px 10px 0">
+                    <div style="width: 315px; margin:0 20px 10px 0">
                       <div class="taskScoConTit">分数详情</div>
                       <div
                         v-for="(wItem, ind) in l.eList"
@@ -722,10 +721,12 @@
                             :content="wItem.target[wItem.target.length - 1]"
                             placement="top-start"
                           > -->
-                            <div class="RootImgBlockSy">
-                              <span v-if="wItem.target && wItem.target.length"> {{ wItem.target[wItem.target.length - 1] }}</span>
-                              <span v-else> {{ wItem.target }}</span>
-                            </div>
+                          <div class="RootImgBlockSy">
+                            <span v-if="wItem.target && wItem.target.length">
+                              {{ wItem.target[wItem.target.length - 1] }}</span
+                            >
+                            <span v-else> {{ wItem.target }}</span>
+                          </div>
                           <!-- </el-tooltip> -->
                         </div>
                       </div>
@@ -750,16 +751,15 @@
                   </div>
                 </div>
               </div>
-
             </div>
-          
+
             <!-- 思维导图 -->
-            <div v-if="CState == 5" class="taskTitInd">
+            <div v-if="CState == 5 || CState == 6" class="taskTitInd">
               <div></div>
               <span>任务评价体系</span>
             </div>
             <exjsmind
-              v-if="CState == 5"
+              v-if="CState == 5 || CState == 6"
               :treeData="k.treeData"
               :keyL="k.task.toString()"
             ></exjsmind>
@@ -859,15 +859,15 @@ export default {
     totalScore() {
       return function(val) {
         let valT = JSON.parse(JSON.stringify(val));
-        
+
         if (!valT) return "0.0";
 
         delete valT.content;
         delete valT.comment;
-        console.log('valT',JSON.parse(JSON.stringify(val)));
+        console.log("valT", JSON.parse(JSON.stringify(val)));
 
         let data = Object.values(valT);
-        console.log('data',JSON.parse(JSON.stringify(data)));
+        console.log("data", JSON.parse(JSON.stringify(data)));
 
         let new1 = data.reduce(function(pre, next, index) {
           return pre + next * 1;
@@ -878,22 +878,21 @@ export default {
         return (new1 / data.length).toFixed(1);
       };
     },
-    workTime(){
+    workTime() {
       return function(val) {
-        if (!val.length) return ''
-        let TimeList = []
-        val.forEach(e=>{
+        if (!val.length) return "";
+        let TimeList = [];
+        val.forEach(e => {
           if (e.time) {
             const timestamp = new Date(e.time).getTime();
-            TimeList.push(timestamp)
+            TimeList.push(timestamp);
           }
-        })
-
-        console.log('TimeList',TimeList);
-        TimeList.sort(function(a,b){
-          return a-b;//从小到大排序
-        })
+        });
 
+        console.log("TimeList", TimeList);
+        TimeList.sort(function(a, b) {
+          return a - b; //从小到大排序
+        });
 
         return this.convertToTimestamp(TimeList[0]);
       };
@@ -901,52 +900,43 @@ export default {
   },
 
   methods: {
-      // 时间戳转时间
-      convertToTimestamp(val) {
+    // 时间戳转时间
+    convertToTimestamp(val) {
       const date = new Date(val);
 
       // 使用Date对象的方法获取年、月、日、时、分、秒
       const year = date.getFullYear();
-      const month = String(date.getMonth() + 1).padStart(2, '0'); // 月份从0开始,需要加1
-      const day = String(date.getDate()).padStart(2, '0');
-      const hours = String(date.getHours()).padStart(2, '0');
-      const minutes = String(date.getMinutes()).padStart(2, '0');
-      const seconds = String(date.getSeconds()).padStart(2, '0');
+      const month = String(date.getMonth() + 1).padStart(2, "0"); // 月份从0开始,需要加1
+      const day = String(date.getDate()).padStart(2, "0");
+      const hours = String(date.getHours()).padStart(2, "0");
+      const minutes = String(date.getMinutes()).padStart(2, "0");
+      const seconds = String(date.getSeconds()).padStart(2, "0");
 
       // 格式化后的日期时间字符串
       const formattedDateTime = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
-      
-      return formattedDateTime
+
+      return formattedDateTime;
     },
     // 下载pdf文件
     getPdf() {
       const content = this.$refs.reportPdf;
-
-      html2canvas(content).then(canvas => {
-
+      const dpi = 300;
+      html2canvas(content, {
+        dpi: dpi, // 设置截图的分辨率
+        scale: dpi / 96 // 设置截图缩放比例,以适应pdf的dpi
+      }).then(canvas => {
         var contentWidth = canvas.width;
         var contentHeight = canvas.height;
 
-      
-          //a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高
-          var imgWidth = 595.28;
-          var imgHeight = (592.28 / contentWidth) * contentHeight;
-
-          var imgData = canvas.toDataURL("image/jpeg", 1.0);
-
-        const pdf = new jspdf("p", "pt", [
-            imgWidth,
-            imgHeight
-        ]);
-
-        pdf.addImage(
-          imgData,
-          "PNG",
-          0,
-          0,
-          imgWidth,
-          imgHeight
-        );
+        //a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高
+        var imgWidth = 595.28;
+        var imgHeight = (592.28 / contentWidth) * contentHeight;
+
+        var imgData = canvas.toDataURL("image/jpeg", 1.0);
+
+        const pdf = new jspdf("p", "pt", [imgWidth, imgHeight]);
+
+        pdf.addImage(imgData, "PNG", 0, 0, imgWidth, imgHeight);
         pdf.save(
           this.worksDialogCon2.course +
             "-作业集-" +
@@ -954,42 +944,31 @@ export default {
             ".pdf"
         );
       });
-
-  
     },
 
     // 压缩pdf
     async getPdf2() {
-  
       const content = this.$refs.reportPdf;
 
       return new Promise((resolve, reject) => {
-        html2canvas(content)
+        const dpi = 300;
+        html2canvas(content, {
+          dpi: dpi, // 设置截图的分辨率
+          scale: dpi / 96 // 设置截图缩放比例,以适应pdf的dpi
+        })
           .then(canvas => {
-
             var contentWidth = canvas.width;
             var contentHeight = canvas.height;
 
-      
             //a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高
             var imgWidth = 595.28;
             var imgHeight = (592.28 / contentWidth) * contentHeight;
 
             var imgData = canvas.toDataURL("image/jpeg", 1.0);
-          
-            const pdf = new jspdf("p", "pt", [
-              imgWidth,
-              imgHeight
-            ]);
-
-            pdf.addImage(
-              imgData,
-              "PNG",
-              0,
-              0,
-              imgWidth,
-              imgHeight
-            );
+
+            const pdf = new jspdf("p", "pt", [imgWidth, imgHeight]);
+
+            pdf.addImage(imgData, "PNG", 0, 0, imgWidth, imgHeight);
             var pdfData = {
               pdfName:
                 this.worksDialogCon2.course +
@@ -1161,16 +1140,27 @@ export default {
                     }
                   });
                   // 将没有提交作业,但是有评分标准的数据填上数据,防止报错
-                  if (!l.rate && l.eList && l.eList.length && this.CState == 5) {
+                  if (
+                    !l.rate &&
+                    l.eList &&
+                    l.eList.length &&
+                    (this.CState == 5 || this.CState == 6)
+                  ) {
                     l.rate = { content: "" };
                     l.eList.forEach(elp => {
                       l.rate[elp.detail] = 0;
                     });
-                  }else if ((!l.rate && l.eList && l.eList.length && this.CState != 5)) {
-                      l.rate = { content: "" };
-                      l.eList.forEach(elp => {
-                        l.rate[elp.value] = 0;
-                      });
+                  } else if (
+                    !l.rate &&
+                    l.eList &&
+                    l.eList.length &&
+                    this.CState != 5 &&
+                    this.CState != 6
+                  ) {
+                    l.rate = { content: "" };
+                    l.eList.forEach(elp => {
+                      l.rate[elp.value] = 0;
+                    });
                   }
                   // 将素养添加进treeData中
                   if (l.eList && l.eList.length) {
@@ -1210,7 +1200,7 @@ export default {
                               children: [
                                 {
                                   id: kind + "+" + elind + "+" + stind + "b",
-                                  topic: `工具${elind}`
+                                  topic: `工具${elind * 1 + 1}`
                                 }
                               ]
                             });
@@ -1219,7 +1209,7 @@ export default {
                               if (lc.topic == st.detail) {
                                 lc.children.push({
                                   id: kind + "+" + elind + "+" + stind + "b",
-                                  topic: `工具${elind}`
+                                  topic: `工具${elind * 1 + 1}`
                                 });
                               }
                             });
@@ -1383,7 +1373,7 @@ export default {
   position: relative;
 }
 .pdfCon {
-  width: 810pt;
+  width: 220mm;
   margin: auto;
   position: relative;
 }
@@ -1419,8 +1409,9 @@ export default {
 }
 .coverPage {
   /* height: 840pt; */
-  padding: 185px 8% 0;
+  padding: 150px 8% 0;
   background-color: #ccc;
+  box-sizing: border-box;
   position: relative;
   background-image: url("../../../assets/icon/exportPdfworks/bcg1.svg"),
     url("../../../assets/icon/exportPdfworks/bcg2.svg");
@@ -1461,7 +1452,7 @@ export default {
   border-radius: 16px;
   background-color: #fff;
   padding: 40px 32px;
-  width: 77%;
+  width: 70%;
   font-family: PingFang SC;
   margin: 8px 0;
   color: rgba(35, 99, 205, 1);
@@ -1493,7 +1484,7 @@ export default {
   background-color: #e3edfe;
   display: flex;
   flex-direction: column;
-  padding: 0 110px;
+  padding: 0 60px;
   padding-bottom: 100px;
   box-sizing: border-box;
   font-family: PingFang SC;

+ 6 - 6
src/components/pages/components/lookReport.vue

@@ -28,14 +28,14 @@
       </div>
       <div class="JsonTitBtn">
         <el-button
-          v-if="checkCourse.state == 5"
+          v-if="checkCourse.state == 5 || checkCourse.state == 6"
           @click="exportWorkPdf"
           type="primary"
           size="small"
           >一键导出</el-button
         >
         <el-button
-          v-if="checkCourse.state == 5"
+          v-if="checkCourse.state == 5 || checkCourse.state == 6"
           @click="batchExportPdf"
           :type="multipleSelection.length < 2 ? 'info' : 'primary'"
           :disabled="multipleSelection.length < 2"
@@ -112,7 +112,7 @@
         @selection-change="handleSelectionChange"
       >
         <el-table-column
-          v-if="checkCourse.state == 5"
+          v-if="checkCourse.state == 5 || checkCourse.state == 6"
           key="1"
           type="selection"
           width="55"
@@ -139,7 +139,7 @@
         <el-table-column align="center" label="操作" min-width="20">
           <template slot-scope="scope">
             <el-button
-              v-if="checkCourse.state == 5"
+              v-if="checkCourse.state == 5 || checkCourse.state == 6"
               type="primary"
               size="small"
               @click="lookPdf(scope.row)"
@@ -153,7 +153,7 @@
               >查看报告</el-button
             >
             <el-button
-              v-if="checkCourse.state == 5"
+              v-if="checkCourse.state == 5 || checkCourse.state == 6"
               type="primary"
               size="small"
               @click="getPdf(scope.row)"
@@ -192,7 +192,7 @@
         </div>
       </div>
       <exportDataDialog
-        v-if="checkCourse.state == 5"
+        v-if="checkCourse.state == 5 || checkCourse.state == 6"
         :key="exportW"
         :digNum="digNum"
         :oid="oid"

+ 7 - 7
src/components/pages/components/lookWork.vue

@@ -86,7 +86,7 @@
             v-if="isStage(i.taskList)"
             class="stageCon"
           >
-            <div v-if="CState != 5" class="stageTit">
+            <div v-if="CState != 5 && CState != 6" class="stageTit">
               阶段{{ i.id + 1 }}:{{ i.name }}
             </div>
 
@@ -587,7 +587,7 @@
                 <!-- ai作业得分  -->
                 <div
                   class="taskSco"
-                  v-if="l.content && l.content.length && l.eList && CState == 5"
+                  v-if="l.content && l.content.length && l.eList && (CState == 5 || CState == 6)"
                 >
                   <div class="taskScoTit">
                     <div>
@@ -662,7 +662,7 @@
                 <div
                   class="taskSco"
                   v-if="
-                    l.eList && CState != 5 && lind == k.toolEList.length - 1
+                    l.eList && CState != 5 && CState != 6 && lind == k.toolEList.length - 1
                   "
                 >
                   <div class="taskScoTit">
@@ -935,7 +935,7 @@ export default {
       let elist = this.workList[stage].taskList[task].toolEList[tool].eList;
 
       elist.forEach(e => {
-        if (this.CState == 5) {
+        if (this.CState == 5 ||this.CState == 6) {
           processedData[e.detail] = 0;
         } else {
           processedData[e.value] = 0;
@@ -1190,8 +1190,8 @@ export default {
                     !l.rate &&
                     l.eList &&
                     l.eList.length &&
-                    this.CState == 5
-                  ) {
+                    (this.CState == 5 || this.CState == 6)
+                  ) {                    
                     l.rate = { content: "" };
                     l.eList.forEach(elp => {
                       l.rate[elp.detail] = 0;
@@ -1200,7 +1200,7 @@ export default {
                     !l.rate &&
                     l.eList &&
                     l.eList.length &&
-                    this.CState != 5
+                    (this.CState != 5 && this.CState != 6)
                   ) {
                     l.rate = { content: "" };
                     l.eList.forEach(elp => {

File diff suppressed because it is too large
+ 444 - 381
src/components/pages/components/report.vue


+ 1 - 1
src/components/pages/components/studentWorksDetail.vue

@@ -1472,7 +1472,7 @@
     <div class="report_box" v-if="reportVisible">
 
     <el-dialog
-      v-if="exportData.state == 5"
+      v-if="exportData.state == 5 || exportData.state == 6"
       :visible.sync="reportVisible"
       :before-close="handleClose"
       class="worksDialogCSSExp"

+ 2 - 2
src/components/pages/components/worksDetail2.vue

@@ -34,7 +34,7 @@
         <el-button @click="customizeExport" 
           type="primary" 
           size="small"
-          >{{ DState == 5 ? '按任务导出' : '自定义导出' }}</el-button
+          >{{ (DState == 5 || DState == 6) ? '按任务导出' : '自定义导出' }}</el-button
         >
         <el-button style="margin-left: 20px;" @click="retPage" type="primary" size="small">返回</el-button>
       </div>
@@ -1586,7 +1586,7 @@
 
 <!-- 自定义导出作业筛选弹框 -->
     <el-dialog
-      :title="dataJson.state == 5 ? '按任务导出作业' : '自定义导出作业'"
+      :title="(dataJson.state == 5 || dataJson.state == 6) ? '按任务导出作业' : '自定义导出作业'"
       :visible.sync="dialogVisibleBao"
       :append-to-body="true"
       width="550px"

+ 49 - 3
src/components/pages/inviteLoginST/inviteLogin.vue

@@ -1,5 +1,8 @@
 <template>
     <div class="container" v-loading="loading">
+				<div class="loginOut" v-show="showLoadingOut">
+					<span @click="loginOut">退出登录</span>
+				</div>
 				<div class="c-box">
 					<div class="c-b-left"></div>
 					<div class="c-b-right">
@@ -41,7 +44,8 @@ export default {
             classJuri: [],
             code: this.$route.query.code,
             courseId:"",
-						chooseData:{}
+						chooseData:{},
+						showLoadingOut:false,
         }
     },
     methods: {
@@ -62,8 +66,32 @@ export default {
               "*"
           );
 				}
-			}
-		}
+			},
+			loginOut(){
+				window.parent.postMessage({
+					tools:"logout"
+				},"*")
+			},
+		},
+		mounted() {
+			setInterval(() => {
+				window.parent.postMessage({
+					tools:"getLogin"
+				},"*")
+				console.log("获取getLogin")
+			}, 2000);
+			window.addEventListener("message",(e)=>{
+				let data = e.data;
+				console.log("message",e)
+				if(data.tools && data.tools=='getLogin'){
+					if(data.type===2){
+						this.showLoadingOut = false;
+					}else if(data.type===1){
+						this.showLoadingOut = true;
+					}
+				}
+			})
+		},
 }
 </script>
 
@@ -80,6 +108,24 @@ export default {
 		position: relative;
 }
 
+.loginOut{
+	position: absolute;
+	right: 30px;
+	top: 30px;
+	width: auto;
+	height: auto;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+}
+
+.loginOut>span{
+	font-size: 24px;
+	color: #fff;
+	font-weight: bold;
+	cursor: pointer;
+}
+
 .c-box{
 	width: 75%;
 	height: 75%;

+ 6 - 5
src/components/pages/test/add/components/GapFilling/gap.vue

@@ -8,12 +8,13 @@
       <!-- <div class="title"><div>{{ `(${option[cJson.type].name})` }}</div><div v-html="cJson.title"></div></div> -->
       <div class="title">
         <div style="display: flex;">
-          <span @click.stop="updateTitle()" style="min-width:fit-content">{{
+          <!-- <span @click.stop="updateTitle()" style="min-width:fit-content">{{
             `(${option[cJson.type].name})`
-          }}</span>
+          }}</span> -->
           <span v-if="!updateList.title" @click.stop="updateTitle()">{{
-            cJson.title
+            cJson.title ? cJson.title : "请填写标题"
           }}</span>
+					<!-- <span v-if="!cJson.title && !updateList.title" class="t_empty" @click.stop="updateTitle()">请填写标题</span> -->
           <input
             v-if="updateList.title"
             ref="titleRef"
@@ -30,7 +31,7 @@
         <span
           style="color: #efa030;display: flex;margin-top: 5px;line-height: 18px;"
         >
-          <span
+          <!-- <span
             style="min-width: fit-content;"
             @click.stop="updateAnswer()"
             v-if="!cJson.answer && !updateList.answer"
@@ -43,7 +44,7 @@
             <span v-if="!updateList.answer" @click.stop="updateAnswer()">{{
               cJson.answer
             }}</span>
-          </span>
+          </span> -->
 
           <input
             v-if="updateList.answer"

+ 2 - 1
src/components/pages/test/add/components/addCheckPopover.vue

@@ -25,7 +25,8 @@
                   pub_test_btn_course: item.value == 6,
                   pub_test_btn_eva: item.value == 7,
                   pub_test_btn_time: item.value == 8,
-                  pub_test_btn_choose2: item.value == 9
+                  pub_test_btn_choose2: item.value == 9,
+									pub_test_btn_sweep: item.value == 12,
                 }"
               >
                 {{ item.label }}

+ 36 - 10
src/components/pages/test/add/components/checkOrder.vue

@@ -8,7 +8,7 @@
                 dragOverBottom: newIndex === index1 && typeIndex == 'drag-' + index1 && (oldIndex < index1 || !(!(newIndex2 || newIndex2 === 0) || !(newIndex3 || newIndex3 === 0))),
             }" @click.stop="checkTitle(`${index1}`, 1, item1)" @dragstart="dragStart(item1, index1, `${index1}`)"
             @dragover.prevent="dragOver(index1)" @dragend="dragEnd()">
-            <div class="title" :style="{ fontSize: etype == 'order' && '16px' }">
+            <div class="title" :style="{ fontSize: etype == 'order' && '16px' }"  :ref="`x${index1}`">
                 <div class="drag" @mousedown="setDrag(`${index1}`)" @mouseup="isdrag = ''"></div>
                 <span class="content" v-html="selectType(item1, index1)" v-if="etype == 'edit' || item1.ttype != 1"></span>
                 <el-tooltip :content="selectType2(item1, index1)" placement="top" effect="dark" v-else>
@@ -36,7 +36,7 @@
                     }" @click.stop="checkTitle(`${index1}-${index2}`, 2, item2)"
                     @dragstart="dragStart2(item2, index1, index2, `${index1}-${index2}`)"
                     @dragover.prevent="dragOver2(index1, index2)" @dragend="dragEnd2()">
-                    <div class="title" :style="{ fontSize: etype == 'order' && '16px' }">
+                    <div class="title" :style="{ fontSize: etype == 'order' && '16px' }" :ref="`x${index1}-${index2}`">
                         <div class="drag" @mousedown="setDrag(`${index1}-${index2}`)" @mouseup="isdrag = ''"></div>
                         <span class="content" v-html="selectType(item2, index2)"
                             v-if="etype == 'edit' || item2.ttype != 1"></span>
@@ -62,7 +62,7 @@
                             }" @click.stop="checkTitle(`${index1}-${index2}-${index3}`, 3, item3)"
                             @dragstart="dragStart3(item3, index1, index2, index3, `${index1}-${index2}-${index3}`)"
                             @dragover.prevent="dragOver3(index1, index2, index3)" @dragend="dragEnd3()">
-                            <div class="title" :style="{ fontSize: etype == 'order' && '16px' }">
+                            <div class="title" :style="{ fontSize: etype == 'order' && '16px' }" :ref="`x${index1}-${index2}-${index3}`">
                                 <div class="drag" @mousedown="setDrag(`${index1}-${index2}-${index3}`)"
                                     @mouseup="isdrag = ''"></div>
                                 <span class="content" v-html="selectType(item3, index3)"
@@ -79,13 +79,13 @@
                             <div v-if="item3.ttype == 1 && canEdit.indexOf(item3.type) !== -1 && etype == 'edit'"
                                 class="edit_box">
                                 <div v-if="item3.type == 1">
-                                    <choiceX :cJson="item3.json" :cJson2="cJson" @setJson="setJson" :index="`x${index1}-${index2}-${index3}`" :isOpen="item3.type == 1 && checkC === `x${index1}-${index2}-${index3}`"></choiceX>
+                                    <choiceX :cJson="item3.json" :cJson2="cJson" @setJson="setJson"  :index="`x${index1}-${index2}-${index3}`" :isOpen="item3.type == 1 && checkC === `x${index1}-${index2}-${index3}`"></choiceX>
                                     <!-- <choiceDialog v-if="item3.type == 1 && checkC === `x${index1}-${index2}-${index3}`"
                                         :cJson="cJson" @setJson="setJson">
                                     </choiceDialog> -->
                                 </div>
                                 <div v-if="item3.type == 3">
-                                    <gapX :cJson="item3.json" :cJson2="cJson" @setJson="setJson" :index="`x${index1}-${index2}-${index3}`" :isOpen="item3.type == 3 && checkC === `x${index1}-${index2}-${index3}`"></gapX>
+                                    <gapX :cJson="item3.json" :cJson2="cJson" @setJson="setJson"  :index="`x${index1}-${index2}-${index3}`" :isOpen="item3.type == 3 && checkC === `x${index1}-${index2}-${index3}`"></gapX>
                                     <!-- <gapDialog v-if="item3.type == 3 && checkC === `x${index1}-${index2}-${index3}`"
                                         :cJson="cJson" @setJson="setJson">
                                     </gapDialog> -->
@@ -120,13 +120,16 @@
                                         :cJson="cJson" @setJson="setJson">
                                     </courseDialog2>-->
                                 </div>
+																<div v-if="item3.type == 12">
+																	<sweep :cJson="item3.json" :cJson2="cJson" @setJson="setJson" :index="`x${index1}-${index2}-${index3}`" :isOpen="item3.type == 12 && checkC === `x${index1}-${index2}-${index3}`"/>
+																</div>
                             </div>
 														<div class="addCheckBox" v-if="checkC === `x${index1}-${index2}-${index3}` && etype==='edit'" @click.stop="">
 															<addCheckPopover @addCheck="addCheck" @addQtype="addQtype"/>
 														</div>
                         </div>
                     </div>
-                    <div v-else-if="item2.ttype == 1 && canEdit.indexOf(item2.type) !== -1 && etype == 'edit'"
+                    <div v-else-if="item2.ttype == 1 && canEdit.indexOf(item2.type) !== -1 && etype == 'edit'" 
                         class="edit_box">
                         <div v-if="item2.type == 1">
                             <choiceX :cJson="item2.json" :cJson2="cJson" @setJson="setJson" :index="`x${index1}-${index2}`" :isOpen="item2.type == 1 && checkC === `x${index1}-${index2}`"></choiceX>
@@ -163,6 +166,9 @@
                             <!-- <courseDialog2 v-if="item2.type == 11 && checkC === `x${index1}-${index2}`" :cJson="cJson"
                                 @setJson="setJson"></courseDialog2> -->
                         </div>
+												<div v-else-if="item2.type == 12">
+													<sweep :cJson="item2.json" :cJson2="cJson" @setJson="setJson" :index="`x${index1}-${index2}`" :isOpen="item2.type == 12 && checkC === `x${index1}-${index2}`"/>
+												</div>
                     </div>
 										<div class="addCheckBox" v-if="checkC === `x${index1}-${index2}` && etype==='edit'" @click.stop="">
 											<addCheckPopover @addCheck="addCheck" @addQtype="addQtype"/>
@@ -206,6 +212,9 @@
                     <!-- <courseDialog2 v-if="item1.type == 11 && checkC === `x${index1}`" :cJson="cJson" @setJson="setJson">
                     </courseDialog2> -->
                 </div>
+								<div v-else-if="item1.type == 12">
+									<sweep :cJson="item1.json" :cJson2="cJson" @setJson="setJson" :index="`x${index1}`" :isOpen="item1.type == 12 && checkC === `x${index1}`"/>
+								</div>
             </div>
 						<div class="addCheckBox" v-if="checkC === `x${index1}` && etype==='edit'" @click.stop="">
 							<addCheckPopover @addCheck="addCheck" @addQtype="addQtype"/>
@@ -249,6 +258,7 @@ import timeX from './timeBox/time.vue'
 import courseDialog2 from './course2/index.vue'
 import courseX2 from './course2/course.vue'
 import addCheckPopover from './addCheckPopover.vue'
+import sweep from './sweep/index'
 export default {
     mixins: [minxinVue],
     components: {
@@ -266,7 +276,8 @@ export default {
         timeX,
         courseDialog2,
         courseX2,
-				addCheckPopover
+				addCheckPopover,
+				sweep
     },
     props: {
         checkJson: {
@@ -287,7 +298,7 @@ export default {
         return {
             manualJson: [],
             isdrag: "",
-            canEdit: [1, 3, 5, 6, 7, 8, 11],
+            canEdit: [1, 3, 5, 6, 7, 8, 11,12],
             ctype: "",
             dragType: "",
             oldIndex: "",
@@ -322,7 +333,9 @@ export default {
                         className += " test_eva_file"
                     } else if (item.type == 8) {
                         className += " test_icon_time"
-                    }
+                    }else if (item.type == 12){
+												className += " test_icon_sweep"
+										}
 										let itemType = item.type;
 										if(itemType===1){
 											if(item.json.type===1){
@@ -395,7 +408,10 @@ export default {
                 this.$emit("update:checkC", "")
             } else {
                 this.$emit("update:checkC", 'x' + index)
-            }
+								if(this.etype==='order'){
+									this.$emit("scrollPage",'x' + index)
+								}
+							}
             this.$forceUpdate();
             // console.log(this.cJson);
             this.$emit("update:cJson", cJson)
@@ -688,6 +704,16 @@ export default {
 				},
 				addQtype(type){
 					this.$emit('addQtype',type)
+				},
+				scrollPage(index){
+					let scrollEl = this.$parent.$refs['eContentRef']
+					let moveEl = this.$refs[index]
+					if(scrollEl && moveEl){
+						scrollEl.scrollTo({
+							top:moveEl[0].offsetTop - 100,
+							behavior:"smooth"
+						})
+					}
 				}
     },
     mounted() {

+ 1 - 0
src/components/pages/test/add/components/choice/choice.vue

@@ -184,6 +184,7 @@ export default {
       }
     },
     updateAnswer(index) {
+			return;
       if (this.cJson.type == 1) {
         if (this.checkJson.answer.indexOf(index) == -1) {
           this.checkJson.answer = [index];

+ 3 - 3
src/components/pages/test/add/components/file/file.vue

@@ -10,11 +10,11 @@
     <div v-else class="choice_box">
       <!-- <div class="title"><div>{{ `(${option[cJson.type].name})` }}</div><div v-html="cJson.title"></div></div> -->
       <div class="title" style="display: flex;">
-        <span @click.stop="updateTitle()" style="min-width:fit-content">{{
+        <!-- <span @click.stop="updateTitle()" style="min-width:fit-content">{{
           `(${option[cJson.type].name})`
-        }}</span>
+        }}</span> -->
         <span @click.stop="updateTitle()" v-if="!updateList.title">{{
-          cJson.title
+          cJson.title ? cJson.title : "请填写标题"
         }}</span>
         <input
           v-if="updateList.title"

+ 166 - 0
src/components/pages/test/add/components/sweep/index.vue

@@ -0,0 +1,166 @@
+<template>
+  <div class="c_box">
+    <div class="mask" v-if="!isOpen"></div>
+    <!-- <div v-if="!cJson">暂未设置题目</div> -->
+    <div class="choice_box">
+      <div class="title" style="display: flex;">
+        <span v-if="!updateList.title" @click.stop="updateTitle()">{{ cJson.title?cJson.title:"请填写标题" }}</span>
+				<input
+            v-if="updateList.title"
+            ref="titleRef"
+            class="editInput"
+            v-model="checkJson.title"
+            @blur="save"
+            @keyup.enter="save"
+            placeholder="请填写标题"
+          />
+      </div>
+      <div class="detail" v-if="!updateList.detail" @click.stop="updateDetail()">{{ cJson.detail?cJson.detail:"暂无描述" }}</div>
+			<input
+        v-if="updateList.detail"
+        ref="detailRef"
+        class="editInput"
+        v-model="checkJson.detail"
+        @blur="save"
+        style="margin-top: 10px;color: rgb(136, 139, 146);"
+        @keyup.enter="save"
+        placeholder="请填写描述"
+      />
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  props: {
+    cJson: {
+      type: Object
+    },
+		cJson2:{
+			type:Object
+		},
+    isOpen: {
+      type: Boolean,
+      default: false
+    },
+    index: {
+      type: String,
+      default: ""
+    }
+  },
+  data() {
+    return {
+      option: {
+        1: { name: "附件" }
+        // 2: { name: '多选题' }
+      },
+      checkJson: {},
+			updateList: {
+        title: false,
+        detail: false,
+      }
+    };
+  },
+  watch: {
+    checkJson: {
+      handler(newVal) {
+        this.$emit("setJson", newVal,this.index);
+      },
+      deep: true
+    },
+		isOpen(newValue) {
+      if (newValue) {
+        if (!this.cJson2 || Object.keys(this.cJson2).length == 0) {
+          this.checkJson = {
+            title: "标题",
+            type: 1,
+            answer: ""
+          };
+        } else {
+          this.checkJson = this.depthCopy(this.cJson2);
+        }
+      }
+    }
+  },
+  methods: {
+    depthCopy(s) {
+      return JSON.parse(JSON.stringify(s));
+    },
+		save() {
+      for (let key in this.updateList) {
+        this.updateList[key] = false;
+      }
+    },
+		updateTitle(){
+			this.updateList.title = true;
+			this.$nextTick(()=>{
+				this.$refs["titleRef"].focus();
+			})
+		},
+		updateDetail(){
+			this.updateList.detail = true;
+			this.$nextTick(()=>{
+				this.$refs["detailRef"].focus();
+			})
+		}
+  },	
+  mounted() {
+    // if (!this.cJson || Object.keys(this.cJson).length == 0) {
+    //   this.checkJson = {
+    //     title: "标题",
+    //     detail: ""
+    //   };
+    // } else {
+    //   this.checkJson = this.depthCopy(this.cJson2);
+    //   this.courses = this.checkJson.courses;
+    // }
+  }
+};
+</script>
+
+<style scoped>
+@import "../../global_styles.css";
+
+.choice_box > .detail {
+  width: 100%;
+  word-break: break-all;
+  color: rgb(136, 139, 146);
+  margin: 10px 0 0;
+}
+
+.choice_box > .choices {
+  margin-top: 10px;
+}
+
+.binfo_input {
+  width: 100%;
+  margin: 0;
+  padding: 10px;
+  display: block;
+  min-width: 0;
+  outline: none;
+  box-sizing: border-box;
+  background: none;
+  border: none;
+  border-radius: 5px;
+  background: #fff;
+  font-size: 16px;
+  resize: none;
+  font-family: "Microsoft YaHei";
+  min-height: 120px;
+  /* border: 1px solid #3682fc00; */
+  border: 1.5px solid #e0e0e0;
+}
+
+.binfo_input > div {
+  border: 1.5px dashed #dfdfdf;
+  height: 120px;
+  width: 100%;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  background: rgb(249, 250, 251);
+  color: rgb(124, 124, 124);
+  border-radius: 5px;
+}
+</style>

+ 16 - 4
src/components/pages/test/add/edit/check/index.vue

@@ -14,6 +14,7 @@
             <evaV :tindex="index" :cJson.sync="item.json" v-if="item.type == 7"></evaV>
             <timeV :tindex="index" :cJson.sync="item.json" v-if="item.type == 8"></timeV>
             <courseV2 :tindex="index" :cJson.sync="item.json" v-if="item.type == 11"></courseV2>
+						<sweep :tindex="index" :cJson.sync="item.json" v-if="item.type == 12"/>
             <!-- <span v-else>暂未设置题目</span> -->
           </div>
           <div v-for="(item2, index2) in item.array" :key="`${index}-${index2}`" class="check_box_xia">
@@ -26,6 +27,7 @@
               <evaV :tindex="index2" :cJson.sync="item2.json" v-if="item2.type == 7"></evaV>
               <timeV :tindex="index2" :cJson.sync="item2.json" v-if="item2.type == 8"></timeV>
               <courseV2 :tindex="index2" :cJson.sync="item2.json" v-if="item2.type == 11"></courseV2>
+							<sweep :tindex="index2" :cJson.sync="item2.json" v-if="item2.type == 12"></sweep>
               <!-- <span v-else>暂未设置题目</span> -->
             </div>
           </div>
@@ -42,6 +44,7 @@
             <evaV :tindex="index" :cJson.sync="item.json" v-if="item.type == 7"></evaV>
             <timeV :tindex="index" :cJson.sync="item.json" v-if="item.type == 8"></timeV>
             <courseV2 :tindex="index" :cJson.sync="item.json" v-if="item.type == 11"></courseV2>
+						<sweep :tindex="index" :cJson.sync="item.json" v-if="item.type == 12"></sweep>
             <!-- <span v-else>暂未设置题目</span> -->
           </div>
           <div v-for="(item2, index2) in item.array" :key="`${index}-${index2}`" class="check_box_xia">
@@ -54,6 +57,7 @@
               <evaV :tindex="index2" :cJson.sync="item2.json" v-if="item2.type == 7"></evaV>
               <timeV :tindex="index2" :cJson.sync="item2.json" v-if="item2.type == 8"></timeV>
               <courseV2 :tindex="index2" :cJson.sync="item2.json" v-if="item2.type == 11"></courseV2>
+							<sweep :tindex="index2" :cJson.sync="item2.json" v-if="item2.type == 12"></sweep>
               <!-- <span v-else>暂未设置题目</span> -->
             </div>
           </div>
@@ -78,6 +82,7 @@ import courseV from './course.vue';
 import evaV from './eva.vue';
 import timeV from './time.vue';
 import courseV2 from './course2.vue';
+import sweep from './sweep.vue'
 export default {
   props: {
     cJson: {
@@ -94,7 +99,8 @@ export default {
     courseV,
     evaV,
     timeV,
-    courseV2
+    courseV2,
+		sweep
   },
   data() {
     return {
@@ -181,7 +187,7 @@ export default {
         let checkArray = _json.filter(item => {
           if (item.array) {
             item.array = item.array.filter((item2) => {
-              if (item2.ttype == 1 && item2.json && !item2.json.answer2 && item2.type != 6 && item.type != 7 && item.type != 8) {
+              if (item2.ttype == 1 && item2.json && !item2.json.answer2 && item2.type != 6 && item.type != 7 && item.type != 8 && item.type != 12) {
                 item2.json.answer2 = [];
               } else if (item2.ttype == 1 && item2.json && !item2.json.answer2 && item2.type == 6) {
                 item2.json.answer2 = item2.json.courses[0];
@@ -189,10 +195,12 @@ export default {
                 item2.json.answer2 = '';
               } else if (item2.ttype == 1 && item2.json && !item2.json.answer2 && item2.type == 8) {
                 item2.json.answer2 = '';
+              }else if (item2.ttype == 1 && item2.json && !item2.json.answer2 && item2.type == 12) {
+                item2.json.answer2 = '';
               }
               if (item2.array) {
                 item2.array = item2.array.filter((item3) => {
-                  if (item3.ttype == 1 && item3.json && !item3.json.answer2 && item3.type != 6 && item3.type != 7 && item3.type != 8) {
+                  if (item3.ttype == 1 && item3.json && !item3.json.answer2 && item3.type != 6 && item3.type != 7 && item3.type != 8 && item3.type != 12) {
                     item3.json.answer2 = [];
                   } else if (item3.ttype == 1 && item3.json && !item3.json.answer2 && item3.type == 6) {
                     item3.json.answer2 = item3.json.courses[0];
@@ -200,6 +208,8 @@ export default {
                     item3.json.answer2 = '';
                   } else if (item3.ttype == 1 && item3.json && !item3.json.answer2 && item3.type == 8) {
                     item3.json.answer2 = '';
+                  }else if (item3.ttype == 1 && item3.json && !item3.json.answer2 && item3.type == 12) {
+                    item3.json.answer2 = '';
                   }
                   return item3;
                 });
@@ -209,7 +219,7 @@ export default {
               );
             });
           }
-          if (item.ttype == 1 && item.json && !item.json.answer2 && item.type != 6 && item.type != 7 && item.type != 8) {
+          if (item.ttype == 1 && item.json && !item.json.answer2 && item.type != 6 && item.type != 7 && item.type != 8 && item.type != 12) {
             item.json.answer2 = [];
           } else if (item.ttype == 1 && item.json && !item.json.answer2 && item.type == 6) {
             item.json.answer2 = item.json.courses[0];
@@ -217,6 +227,8 @@ export default {
             item.json.answer2 = '';
           } else if (item.ttype == 1 && item.json && !item.json.answer2 && item.type == 8) {
             item.json.answer2 = '';
+          }else if (item.ttype == 1 && item.json && !item.json.answer2 && item.type == 12) {
+            item.json.answer2 = '';
           }
           console.log(item.array);
           return (item.ttype != 1 && item.array.length > 0) || item.ttype == 1;

+ 261 - 0
src/components/pages/test/add/edit/check/sweep.vue

@@ -0,0 +1,261 @@
+<template>
+  <div class="c_box">
+    <div class="choice_box">
+      <div class="title" style="display: flex;align-items: center;">
+        <span class="g_t_index" style="min-width: fit-content;">{{
+          tindex + 1
+        }}</span>
+        <span>{{ checkJson.title }}</span>
+      </div>
+      <div
+        class="detail"
+        v-if="checkJson.detail"
+        v-html="checkJson.detail"
+        style="color: #00000066;margin-top: 5px;"
+      ></div>
+			<div
+        class="detail"
+         v-if="checkJson.answer2 && typeof checkJson.answer2=='string'"
+        v-html="checkJson.answer2"
+        style="color: #000000;margin-top: 5px;"
+      ></div>
+			<el-button style="margin-top: 10px;" type="primary" size="mini" @click="sweepBtn">扫一扫</el-button>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  props: {
+    tindex: {
+      type: Number
+    },
+    cJson: {
+      type: Object
+    },
+    checktype: {
+      type: Number,
+      default: 1
+    },
+    see: {
+      type: Boolean,
+      default: false
+    }
+  },
+  data() {
+    return {
+      option: {
+        1: { name: "附件" }
+      },
+      userid: this.$route.query.userid,
+      checkJson: undefined,
+      courseDetail: [],
+    };
+  },
+  computed: {},
+  watch: {
+    checkJson: {
+      handler(newValue) {
+        this.$emit("update:cJson", newValue);
+      },
+      deep: true
+    }
+  },
+  methods: {
+    depthCopy(s) {
+      return JSON.parse(JSON.stringify(s));
+    },
+		sweepBtn(){
+			this.$message.error("请到手机端内扫码")
+		}
+  },
+  mounted() {
+    this.checkJson = this.cJson ? this.depthCopy(this.cJson) : undefined;
+  }
+};
+</script>
+
+<style scoped>
+.c_box {
+  width: 100%;
+  position: relative;
+  padding-left: 45px;
+  overflow: visible;
+}
+
+/* .mask {
+    position: absolute;
+    height: 100%;
+    width: 100%;
+    z-index: 2;
+} */
+
+.choice_box {
+  white-space: pre-line;
+}
+
+.choice_box > .title {
+  font-weight: bold;
+  width: 100%;
+  word-break: break-all;
+}
+
+.choice_box > .choices {
+  margin-top: 10px;
+}
+
+.choices > .page {
+  margin-top: 10px;
+  display: flex;
+  align-items: center;
+}
+
+.p_page {
+  margin: 0 10px;
+}
+
+.course {
+  display: flex;
+  align-items: center;
+  cursor: pointer;
+}
+
+.course + .course {
+  margin-top: 10px;
+}
+
+.course > .banner {
+  width: 200px;
+  height: 120px;
+  border-radius: 5px;
+  overflow: hidden;
+  border: 1px solid #3896fc;
+  box-sizing: border-box;
+  padding: 5px;
+  margin-right: 15px;
+}
+.course > .banner > img {
+  width: 100%;
+  height: 100%;
+  object-fit: cover;
+}
+.course > .content {
+}
+.course > .content > .c_c {
+}
+.course > .content > .c_c + .c_c {
+  margin-top: 5px;
+}
+.course > .content > .c_c span:nth-child(1) {
+}
+.course > .content > .c_c span:nth-child(2) {
+}
+
+.g_t_index {
+  color: #3681fc;
+  font-size: 28px;
+  font-weight: bold;
+  position: relative;
+  margin-right: 30px;
+  margin-left: -40px;
+}
+
+.g_t_index + span {
+  font-weight: bold;
+  font-size: 18px;
+}
+
+.g_t_index::after {
+  content: "";
+  width: 18px;
+  height: 2px;
+  position: absolute;
+  right: -18px;
+  top: 50%;
+  transform: translateY(-50%);
+  background: #3681fc;
+}
+
+.g_t_index::before {
+  content: "";
+  width: 6px;
+  height: 6px;
+  border-right: 2px solid #3681fc;
+  border-top: 2px solid #3681fc;
+  position: absolute;
+  right: -15px;
+  top: 50%;
+  transform: rotate(45deg) translateY(-5px);
+}
+
+.c_list {
+  width: calc(100% - 10px);
+  min-height: 200px;
+  height: auto;
+  border: 1px solid #e7e7e7;
+  border-radius: 5px;
+  box-sizing: border-box;
+  padding: 10px;
+  display: flex;
+  flex-wrap: wrap;
+  /* overflow: auto; */
+}
+
+.c_l_add1 {
+  width: 100%;
+  height: 200px;
+  background-color: #F9FAFB;
+	border: 1.5px dashed #dfdfdf;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  color: #00000066;
+  border-radius: 5px;
+  font-size: 18px;
+  cursor: pointer;
+}
+
+.c_l_add2{
+	width: 230px;
+  height: 200px;
+	background-color: #F9FAFB;
+	border: 1.5px dashed #dfdfdf;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  color: #00000066;
+  border-radius: 5px;
+  font-size: 18px;
+  cursor: pointer;
+}
+
+.c_l_item {
+  width: 230px;
+  height: 200px;
+  margin-right: 10px;
+  box-sizing: border-box;
+  border: solid 1px #3896FC;
+  border-radius: 5px;
+	cursor: pointer;
+	box-sizing: border-box;
+	padding: 5px;
+}
+
+.c_l_item > img {
+  width: 100%;
+  height: 110px;
+  object-fit: cover;
+	margin-bottom: 5px;
+}
+
+.c_l_item > div {
+  width: 210px;
+  display: block;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+  font-size: 14px; /* 设置字体大小 */
+  color: #333; /* 设置字体颜色 */
+	box-sizing: border-box;
+}
+</style>

+ 36 - 13
src/components/pages/test/add/edit/edit/index.vue

@@ -45,7 +45,8 @@
                   pub_test_btn_course: item.value == 6,
                   pub_test_btn_eva: item.value == 7,
                   pub_test_btn_time: item.value == 8,
-                  pub_test_btn_choose2: item.value == 9
+                  pub_test_btn_choose2: item.value == 9,
+                  pub_test_btn_sweep: item.value == 12
                 }"
               >
                 {{ item.label }}
@@ -126,10 +127,11 @@
     <div
       class="e_content"
       :style="
-        `margin-right:${showRightMenu ? '20px' : '0'	};margin-left:${
+        `margin-right:${showRightMenu ? '20px' : '0'};margin-left:${
           showLeftMenu ? '20px' : '0'
         };`
       "
+			ref="eContentRef"
     >
       <div v-if="!isEditing" class="title" @click="editTitle">
         {{ title ? title : "请填写表单标题" }}
@@ -157,22 +159,26 @@
       />
       <div class="e_order_box">
         <checkOrder
+					ref="checkOrderEditRef"
           :checkC.sync="checkC"
           :checkJson="manualJson"
           @changeJson="changeJson"
           etype="edit"
           :cJson.sync="cJson"
-					@addCheck="addCheck"
-					@addQtype="addQtype"
+          @addCheck="addCheck"
+          @addQtype="addQtype"
         >
         </checkOrder>
-				<addCheckPopover v-if="manualJson.length==0 || checkC==''" @addCheck="addCheck" @addQtype="addQtype"/>
-
+        <addCheckPopover
+          v-if="manualJson.length == 0 || checkC == ''"
+          @addCheck="addCheck"
+          @addQtype="addQtype"
+        />
       </div>
     </div>
     <div class="e_order" v-show="showRightMenu">
       <div class="title">
-        题目排序
+        大纲
         <span style="font-size: 14px; color: #373737">总分:{{ score }}分</span>
       </div>
       <span
@@ -202,6 +208,7 @@
           :checkJson="manualJson"
           @changeJson="changeJson"
           etype="order"
+					@scrollPage="scrollPage"
           :cJson.sync="cJson"
         >
         </checkOrder>
@@ -260,6 +267,7 @@
 import checkOrder from "../../components/checkOrder.vue";
 import minxinVue from "../../minxins/minxin";
 import addCheckPopover from "../../../add/components/addCheckPopover.vue";
+import { ref } from "vue-demi";
 export default {
   components: {
     checkOrder,
@@ -473,6 +481,11 @@ export default {
             title: "标题",
             detail: ""
           };
+        } else if (topicType == 12) {
+          json.json = {
+            title: "标题",
+            detail: ""
+          };
         }
         if (_json.array) {
           if (type == 3 && _check.length == 2) {
@@ -524,6 +537,7 @@ export default {
             ttype: 1,
             type: _topicType
           };
+					console.log("👉",topicType)
 
           if (topicType == 1) {
             json1.json = {
@@ -590,6 +604,11 @@ export default {
               title: "标题",
               detail: ""
             };
+          } else if (topicType == 12) {
+            json1.json = {
+              title: "标题",
+              detail: ""
+            };
           }
           this.manualJson.push(json1);
           this.$forceUpdate();
@@ -703,7 +722,10 @@ export default {
         }
       }
       this.$emit("changeJson", this.manualJson);
-    }
+    },
+		scrollPage(index){
+			this.$refs.checkOrderEditRef.scrollPage(index)
+		}
   },
   mounted() {
     this.manualJson = this.depthCopy(this.checkJson);
@@ -798,7 +820,8 @@ export default {
 
 .e_add > .title,
 .e_order > .title {
-  text-align: center;
+  /* text-align: center; */
+	text-indent: 1.1em;
   font-size: 20px;
 }
 
@@ -897,9 +920,9 @@ export default {
   overflow-y: hidden;
 }
 
-.e_addBox{
-	width: 400px;
-	height: 300px;
-	background-color: red;
+.e_addBox {
+  width: 400px;
+  height: 300px;
+  background-color: red;
 }
 </style>

+ 1 - 0
src/components/pages/test/add/edit/edit/indexJ.vue

@@ -25,6 +25,7 @@
                   pub_test_btn_eva: item.value == 7,
                   pub_test_btn_time: item.value == 8,
                   pub_test_btn_choose2: item.value == 9,
+									pub_test_btn_sweep:item.value==12
                 }"
               >
                 {{ item.label }} 

+ 23 - 10
src/components/pages/test/add/edit/index.vue

@@ -6,12 +6,12 @@
     <div class="edit_top">
       <div class="e_t_left">
         <el-button type="primary" size="small" @click="useAiBtn()"
-          >按文档创建</el-button
+          >按文档创建</el-button
         >
 
-				<el-button :type="viewFile?'primary':''" size="small" v-if="fileData" @click="viewUploadFile()"
+				<!-- <el-button :type="viewFile?'primary':''" size="small" v-if="fileData" @click="viewUploadFile()"
           >预览</el-button
-        >
+        > -->
       </div>
       <div class="edit_btn">
         <span class="edit" :class="{ active: type == 1 }" @click="type = 1"
@@ -43,8 +43,10 @@
       ></editBox>
       <checkBox v-if="type == 2" :cJson="checkJson" :title="title"></checkBox>
     </div>
-		<div class="ajaxCancel" v-if="loading && ajaxCancelToken">
-			 <el-button type="primary" @click.stop="cancelAjax">停止生成</el-button>
+		<div class="ajaxCancel" v-if="loading">
+				<img src="../../../../../assets/KekeLoading.gif">
+				<span>小可正在努力生成中...</span>
+			 <el-button type="primary" @click.stop="cancelAjax" size="small" v-if="ajaxCancelToken">停止生成</el-button>
 		</div>
   </div>
 </template>
@@ -298,9 +300,9 @@ Instruction: Based on the context, follow "Format example", write content
 说明:文档中的总标题下的说明性文字
 
 ##题目格式
-问答题:{"ttype":1,"type":3,"json":{"title":"标题","type":1,"answer":""}}
-单选:{"ttype":1,"type":1,"json":{"title":"标题","type":1,"array":[{"option":"选项1","img":""}, {"option":"选项2","img":""}],"answer":""}}
-多选:{"ttype":1,"type":1,"json":{"title":"标题","type":2,"array":[{"option":"选项1","img":""},{"option":"选项2","img":""}],"answer":""}}
+文本:{"ttype":1,"type":3,"json":{"title":"标题","type":1,"answer":""}}
+单选:{"ttype":1,"type":1,"json":{"title":"标题","type":1,"array":[{"option":"选项1","img":""}, {"option":"选项2","img":""}],"answer":""}}
+多选:{"ttype":1,"type":1,"json":{"title":"标题","type":2,"array":[{"option":"选项1","img":""},{"option":"选项2","img":""}],"answer":""}}
 
 标题和说明:{"formName":"标题","illustrate":"说明"}
 
@@ -502,17 +504,28 @@ Instruction: Based on the context, follow "Format example", write content
 
 .ajaxCancel{
 	position: fixed;
-	top: calc(50vh + 100px);
+	top: calc(50vh + 20px);
 	left: 50vw;
 	transform: translate(-50%,-50%);
 	z-index: 9999;
 	width: 150px;
 	height: 80px;
-	background: #fff;
 	border-radius: 5px;
 	display: flex;
 	flex-direction: column;
 	align-items: center;
 	justify-content: center;
 }
+
+.ajaxCancel>span{
+	margin-bottom: 10px;
+	color: #3681FC;
+	white-space: nowrap;
+}
+
+.ajaxCancel>img{
+	width: 200px;
+	height: 200px;
+	margin-bottom: -50px;
+}
 </style>

+ 4 - 0
src/components/pages/test/add/global_styles.css

@@ -100,3 +100,7 @@
 	border: 1px solid #409EFF !important;
 	color: #fff !important;
 }
+
+.t_empty{
+	color: #757575;
+}

+ 11 - 6
src/components/pages/test/add/minxins/minxin.js

@@ -19,7 +19,7 @@ const minxin = {
         // },
         {
           value: 3,
-          label: "问答题"
+          label: "文本"
         },
         // {
         //   value: 4,
@@ -43,12 +43,16 @@ const minxin = {
         },
         {
           value: 9,
-          label: "单选"
+          label: "单选"
         },
         {
           value: 10,
-          label: "多选"
+          label: "多选"
         },
+				{
+					value:12,
+					label:"扫一扫"
+				}
       ]))),
       optionsPin:JSON.parse(converter(JSON.stringify([
        {
@@ -63,15 +67,16 @@ const minxin = {
       options2: JSON.parse(converter(JSON.stringify({
         1: "选择题",
         // 2: "问答题",
-        3: "问答题",
+        3: "文本",
         4: "添加文档",
         5: "附件",
         6: "课程",
         7: "评分",
         8: "日期",
-        9: "单选",
-        10: "多选",
+        9: "单选",
+        10: "多选",
         11: "课程",
+				12:"扫一扫"
       }))),
       buttonOptions: JSON.parse(converter(JSON.stringify([
         { name: "分组", type: 1 },

+ 38 - 7
src/components/pages/test/check/index.vue

@@ -592,10 +592,10 @@
 								</template>
               </el-table-column>
               <el-table-column v-for="(item, index) in chapters" :key="index" :label="item.json.title"
-                :min-width="item.type == 5 ? 200 : 150" align="left" :filters="item.type == 1 ? item.nameFilters : (item.type ==  6 || item.type ==  11)? item.nameFilters : null"
-                :filter-method="item.type == 1 ? (value, row) => { return filterName(value, row, index) } : (item.type == 6 || item.type == 11)?(value, row) => { return filterCourse(value, row, index)}:null"
-                :filter-placement="item.type == 1 || item.type ==6|| item.type ==11 ? filterPlacement : null">
-
+                :min-width="item.type == 5 ? 200 : 150" align="left" 
+								:filters="item.type == 1 ? item.nameFilters : (item.type ==  6 || item.type ==  11)? item.nameFilters : item.type==8?getTimeFilterText(item,index):null"
+                :filter-method="item.type == 1 ? (value, row) => { return filterName(value, row, index) } : (item.type == 6 || item.type == 11)?(value, row) => { return filterCourse(value, row, index)}:item.type==8?(value,row)=>{return filterTime(value,row,index)}:null"
+                :filter-placement="item.type == 8 ||item.type == 1 || item.type ==6|| item.type ==11 ? filterPlacement : null">
                 <template slot-scope="scope">
                   <div v-if="scope.row.array[index].type == 1" style="display: flex; flex-wrap: wrap;">
                     <span class="answer_type" v-for="(answer2, index2) in scope.row.array[index].json.answer2"
@@ -633,12 +633,12 @@
                   </div>
                 </template>
               </el-table-column>
-              <el-table-column label="操作" width="370px" fixed="right" v-if="isN!=1">
+              <el-table-column label="操作" width="200px" fixed="right" v-if="isN!=1">
 
                 <template slot-scope="scope">
                   <el-button @click="getTest(scope.row)" type="primary" size="small">查看</el-button>
-                  <el-button @click="setWordHtml(scope.row)" type="primary" size="small">导出答题信息</el-button>
-									<el-button @click="setWordTemplate(scope.row)" type="primary" size="small">word导出</el-button>
+                  <!-- <el-button @click="setWordHtml(scope.row)" type="primary" size="small">导出答题信息</el-button>
+									<el-button @click="setWordTemplate(scope.row)" type="primary" size="small">word导出</el-button> -->
                   <el-button @click="deleteTest(scope.row.id)" type="primary" size="small">删除</el-button>
                 </template>
               </el-table-column>
@@ -1122,6 +1122,32 @@ export default {
 				_result = _sum ? (_result/_sum).toFixed(2) : 0
 				return _result ? _result : 0;
 			}
+		},
+		getTimeFilterText(){
+			return (item,index)=>{
+				let _result = [];
+				if(item.type==8){
+					let array = []
+					this.worksArray.forEach(i=>{
+						if(i.array[index].type == 8){
+							let _data = i.array[index].json.answer2;
+							if(!array.map(r=>r.value).includes(_data)){
+								array.push({text:_data,value:_data})
+							}
+						}
+					})
+					array.sort((a, b) =>{
+
+						const dateA = new Date((a.value.replace(/年|月/g, '-')).replace(/日/g,""));
+    				const dateB = new Date((b.value.replace(/年|月/g, '-')).replace(/日/g,""));
+						return dateB - dateA; // 从小到大排序
+					});
+
+					console.log("👉排序:",array)
+					_result=array;
+				}
+				return _result;
+			}
 		}
   },
   methods: {
@@ -1191,6 +1217,10 @@ export default {
 		filterCourse(value, row, index) {
 			return row.array[index].json.answer2.indexOf(value) != -1;
     },
+		//筛选日期
+		filterTime(value, row, index){
+			return row.array[index].json.answer2.indexOf(value)!=-1;
+		},
     wordClickHandler(name, value) {
       //  this.$notify({
       //   title: name,
@@ -1681,6 +1711,7 @@ export default {
             item.nameFilters.push({ text: item.json.array[i].option, value: item.json.array[i].option })
           }
         }
+
         array.push(item)
         return item;
       });

File diff suppressed because it is too large
+ 53 - 763
src/components/pages/test/checkAi/aiLeader.vue


+ 65 - 64
src/components/pages/test/choseCheck/csvTableView.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="txtView" v-loading="loading">
 		<el-table :data="tableData" border style="width: 100%;height: 100%;" :header-cell-style="{ background: '#f1f1f1', fontSize: '16px' }" :fit="true" >
-			<el-table-column  :fixed="[].includes(index)" :label="item.label" :prop="item.label" v-for="(item,index) in columnList" :key="item.label+'_'+'index'"></el-table-column>
+			<el-table-column  :fixed="[].includes(index)" :label="item.label" :prop="item.prop" v-for="(item,index) in columnList" :key="item.label+'_'+index"></el-table-column>
 		</el-table>
 		<!-- <div class="tv_content" v-text="content"></div> -->
 	</div>
@@ -54,44 +54,45 @@ export default {
     url: {
       type: String,
       default: ""
-    },
+    }
   },
-	data(){
-		return{
-			content:"",
-			loading:true,
-			tableData:[],
-			columnList:[],
-		}
-	},
-	methods: {
-		getTxtContent() {
-			if(!this.url)return;
-			this.loading = true;
-			getFile(this.url).then(res=>{
-				this.loading = false;
-				let tableDataObj = this.formatCSVToTable(res.data);
-				this.tableData = tableDataObj;
-				let column = [];
-				for(let i in tableDataObj[0]){
-				  column.push({
-						label:i,
-						prop:i
+  data() {
+    return {
+      content: "",
+      loading: true,
+      tableData: [],
+      columnList: []
+    };
+  },
+  methods: {
+    getTxtContent() {
+      if (!this.url) return;
+      this.loading = true;
+      getFile(this.url).then(res => {
+        this.loading = false;
+        let tableDataObj = this.formatCSVToTable(res.data);
+				console.log(tableDataObj)
+        this.tableData = tableDataObj.result;
+        let column = [];
+				tableDataObj.header.forEach((item,index)=>{
+					column.push({
+						label:item,
+						prop: `header_${index}`
 					})
-				}
-				this.columnList = column;
-				this.content = res.data;
-			})
-		},
-		formatCSVToTable(str){
+				})
+        this.columnList = column;
+        this.content = res.data;
+      });
+    },
+    formatCSVToTable(str) {
       const result = [];
       const jsonObj = str.split("\n");
       let arrHeader = [];
       for (const i in jsonObj) {
-        if (typeof jsonObj[i] === 'string' && jsonObj[i].length > 0) {
+        if (typeof jsonObj[i] === "string" && jsonObj[i].length > 0) {
           const row = `${jsonObj[i]}`;
           if (row.trim().length > 0) {
-            const kv = jsonObj[i].split(',');
+            const kv = jsonObj[i].split(",");
             if (i == 0) {
               // 获取column表头
               arrHeader = kv;
@@ -99,17 +100,17 @@ export default {
               const obj = {};
               for (let index = 0; index < arrHeader.length; index++) {
                 // 组装表格数据
-                const name = String(arrHeader[index]);
-                if (!arrHeader[index]) continue
+                const name = `header_${index}`
+                if (!arrHeader[index]) continue;
                 if (!obj[name]) {
                   try {
                     if (kv[index]) {
                       obj[name] = String(kv[index]);
                     } else {
-                      obj[name] = '';
+                      obj[name] = "";
                     }
                   } catch (err) {
-                    obj[name] = '';
+                    obj[name] = "";
                   }
                 }
               }
@@ -118,41 +119,41 @@ export default {
           }
         }
       }
-      return result
+      return {result:result,header:arrHeader};
+    },
+  },
+  watch: {
+    url(newVal, oldVal) {
+      if (newVal !== oldVal) {
+        this.getTxtContent();
+      }
     }
-	},
-	watch:{
-		url(newVal,oldVal){
-			if(newVal!==oldVal){
-				this.getTxtContent();
-			}
-		}
-	},
-	mounted(){
-		this.getTxtContent();
-	}
+  },
+  mounted() {
+    this.getTxtContent();
+  }
 };
 </script>
 
 <style scoped>
-.txtView{
-	width: 100%;
-	height: 100%;
-	box-sizing: border-box;
-	background-color: #ececec;
-	padding: 0px 0px;
+.txtView {
+  width: 100%;
+  height: 100%;
+  box-sizing: border-box;
+  background-color: #ececec;
+  padding: 0px 0px;
 }
 
-.tv_content{
-	width: 100%;
-	height: 100%;
-	box-sizing: border-box;
-	background-color: #fff;
-	overflow: auto;
-	word-wrap: break-word;
-	border-radius: 3px;
-	white-space: pre;
-	box-sizing: border-box;
-	padding: 10px;
+.tv_content {
+  width: 100%;
+  height: 100%;
+  box-sizing: border-box;
+  background-color: #fff;
+  overflow: auto;
+  word-wrap: break-word;
+  border-radius: 3px;
+  white-space: pre;
+  box-sizing: border-box;
+  padding: 10px;
 }
 </style>

+ 542 - 67
src/components/pages/test/smarter.vue

@@ -16,7 +16,7 @@
                         )
                         ">表单管理</span>
                     <!-- v-show="oid == '4c686762-1d0a-11ed-8c78-005056b86db5'" -->
-                    <span class="subClick"  @click="
+                    <span class="subClick" @click="
                         goTo(
                             '/trainCourse?userid=' +
                             userid +
@@ -42,7 +42,7 @@
                         ">数据看板</span>
                     <span class="sub_head">智能助手</span>
                 </div>
-                <div class="pb_head_t_right">
+                <!-- <div class="pb_head_t_right">
                     <el-tooltip class="item" effect="dark" content="预览" placement="bottom">
                         <span class="preview_icon"></span>
                     </el-tooltip>
@@ -52,58 +52,154 @@
                     <el-tooltip class="item" effect="dark" content="问题" placement="bottom">
                         <span class="problem_icon"></span>
                     </el-tooltip>
-                </div>
+                </div> -->
             </div>
         </div>
         <div class="cc_bottom">
-            <smartMenu></smartMenu>
-            <div class="cc_b_middle">
-                <div  style="width:100%;height: 100%;">
-                    <aiLeader :courseId="aiBoxRightCid" :worksArray="courseInfoList" ref="aiChat"
-                        @pushFileData="pushFileData" @clearFileData="clearFileData"></aiLeader>
+            <div class="cc_b_left">
+                <div class="menu_container">
+                    <div :class="['cc_b_l_menu', { active: activeMenu === 1 }]" @click="activeMenu = 1">
+                        <span :class="['session_icon', { active: activeMenu === 1 }]"></span>
+                        <div style="margin-left: 10px;margin-top: 1px;font-size: 15px;">当前会话</div>
+                    </div>
+                    <div :class="['cc_b_l_menu', { active: activeMenu === 2 }]" @click="activeMenu = 2">
+                        <span :class="['history_icon', { active: activeMenu === 2 }]"></span>
+                        <div style="margin-left: 10px;margin-top: 1px;font-size: 15px;">历史会话</div>
+                    </div>
+                    <!--<div :class="['cc_b_l_menu', { active: activeMenu === 3 }]" @click="activeMenu = 3">
+                            <span :class="['mysql_icon', { active: activeMenu === 3 }]"></span>
+                            <div style="margin-left: 10px;margin-top: 1px;font-size: 15px;">数据库管理</div>
+                        </div> -->
+                </div>
+                <div class="fold_btn">
+                    <span class="more_icon"></span>
                 </div>
             </div>
-            <div class="cc_b_right">
-                <div v-if="showFileUrl">
-                    <div class="cc_b_r_menu">
-                        <div v-for="(item, index) in menuList" @click="changeMenuIndex(index)" :key="index"
-                            :class="{ 'cc_b_r_menu_active': menuIndex == index }">
-                            <el-tooltip class="item" effect="dark" :content="item.name" placement="top">
-                                <span>{{ item.name }}</span>
-                            </el-tooltip>
-                            <!-- <div class="cc_b_r_btn"> -->
-                                <span class="close_icon" :class="{ active: menuIndex == index }" @click="deleteMenuItem(index)"></span>
-                            <!-- </div> -->
+            <div v-show="activeMenu == 1" style="width:100%;display: flex;">
+                <div class="cc_b_middle">
+                    <div style="width:100%;height: 100%;">
+                        <aiLeader :courseId="aiBoxRightCid" :worksArray="courseInfoList" :formList="menuList" ref="aiChat"
+                            @pushFileData="pushFileData" @clearFileData="clearFileData"></aiLeader>
+                    </div>
+                </div>
+                <div class="cc_b_right">
+                    <div v-if="showFileUrl">
+                        <!-- <div style="display: flex;">
+                            <div :class="['preview_file', { active: fileMenu === 1 }]" @click="fileMenu = 1">文档预览</div>
+                            <div :class="['bianji_file', { active: fileMenu === 2 }]" @click="fileMenu = 2">文档编辑</div>
+                        </div> -->
+                        <!-- <div v-if="fileMenu == 1" style="margin:10px;"> -->
+                        <div class="cc_b_r_menu">
+                            <div v-for="(item, index) in menuList" @click="changeMenuIndex(index)" :key="index"
+                                :class="{ 'cc_b_r_menu_active': menuIndex == index }">
+                                <el-tooltip class="item" effect="dark" :content="item.name" placement="top">
+                                    <span>{{ item.name }}</span>
+                                </el-tooltip>
+                                <!-- <div class="cc_b_r_btn"> -->
+                                <span class="close_icon" :class="{ active: menuIndex == index }"
+                                    @click="deleteMenuItem(index)"></span>
+                                <!-- </div> -->
+                            </div>
+                        </div>
+                        <div class="cc_b_r_content">
+                            <csvTableView v-if="showFileUrl" :url="showFileUrl" />
                         </div>
+                        <!-- </div> -->
+                        <!-- <div v-if="fileMenu == 2">
+                            <div class="bianji_area">
+                                <span></span>
+                            </div>
+
+                        </div> -->
                     </div>
-                    <div class="cc_b_r_content">
-                        <csvTableView v-if="showFileUrl" :url="showFileUrl" />
+                    <div v-else style="margin: 40px 0px 0px 20px">
+                        <div>--官方能力演示--</div>
+                        <div class="b_r_menu">
+                            <div class="b_r_menu_content">
+                                <div class="m_c_title">数据处理</div>
+                                <div class="m_c_item">缺失值处理</div>
+                                <div class="m_c_item">无效样本处理</div>
+                                <div class="m_c_item">数据降维</div>
+                            </div>
+                            <div class="b_r_menu_content">
+                                <div class="m_c_title">数据分析</div>
+                                <div class="m_c_item">线性回归</div>
+                                <div class="m_c_item">相关性分析</div>
+                                <div class="m_c_item">关联分心</div>
+                            </div>
+                            <div class="b_r_menu_content">
+                                <div class="m_c_title">图标生成</div>
+                                <div class="m_c_item">箱线图</div>
+                                <div class="m_c_item">雷达图</div>
+                            </div>
+                        </div>
                     </div>
                 </div>
-                <div v-else  style="margin: 40px 0px 0px 20px">
-                    <div>--官方能力演示--</div>
-                    <div class="b_r_menu">
-                        <div class="b_r_menu_content">
-                            <div class="m_c_title">数据处理</div>
-                            <div class="m_c_item">缺失值处理</div>
-                            <div class="m_c_item">无效样本处理</div>
-                            <div class="m_c_item">数据降维</div>
-                        </div>
-                        <div class="b_r_menu_content">
-                            <div class="m_c_title">数据分析</div>
-                            <div class="m_c_item">线性回归</div>
-                            <div class="m_c_item">相关性分析</div>
-                            <div class="m_c_item">关联分心</div>
+            </div>
+            <div v-show="activeMenu == 2" style="width:100%;">
+                <div class="history_talk">
+                    <div class="h_t_head">
+                        <div class="t_h_left">
+                            <span style="font-weight: bold;font-size: 18px;">历史回溯</span>
+                            <span>共计{{ tableData.length }}个会话</span>
                         </div>
-                        <div class="b_r_menu_content">
-                            <div class="m_c_title">图标生成</div>
-                            <div class="m_c_item">箱线图</div>
-                            <div class="m_c_item">雷达图</div>
+                        <div class="t_h_right">
+                            <div style="margin-right: 10px;position: relative;">
+                                <el-input v-model="talkName" class="student_input" placeholder="检索会话名称"></el-input>
+                                <span class="serach_icon" @click="historyTalk()"></span>
+                            </div>
                         </div>
                     </div>
+                    <div class="h_t_table">
+                        <el-table :data="tableData" style="width: 100%;cursor: pointer" @row-click="handleRowClick">
+                            <el-table-column prop="name" label="会话名称" width="180">
+                            </el-table-column>
+                            <el-table-column prop="create_at" label="创建时间" width="180">
+                            </el-table-column>
+                            <el-table-column prop="update_at" label="更新时间">
+                            </el-table-column>
+                            <el-table-column prop="control" label="操作">
+                                <template slot-scope="scope">
+                                    <div style="display: flex;">
+                                        <div class="bianji">
+                                            <i class="el-icon-edit"></i>
+                                            <span @click.stop="openUpdate(scope.row.name, scope.row.id)">重命名</span>
+                                        </div>
+                                        <div class="bianji">
+                                            <i class="el-icon-delete"></i>
+                                            <span @click.stop="delete_talk(scope.row.id)">删除</span>
+                                        </div>
+                                    </div>
+                                </template>
+                            </el-table-column>
+                        </el-table>
+                    </div>
+                    <div class="h_t_bottom">
+                        <span>共{{ tableData.length }}条</span>
+                        <el-pagination background layout="prev, pager, next" :page-size="pageSize" :current-page="page"
+                            :total="total" @current-change="handleCurrentChange"></el-pagination>
+                        <!-- <el-select v-model="value" placeholder="请选择页数" size="mini" class="el_select">
+                            <el-option v-for="item in options" :key="item.value" :label="item.label"
+                                :value="item.value">
+                            </el-option>
+                        </el-select> -->
+                    </div>
+
                 </div>
             </div>
         </div>
+        <el-dialog title="修改会话名称" :visible.sync="dialogVisibleUpdate" :append-to-body="true" :before-close="handleClose"
+            class="dialog_diy">
+            <el-form>
+                <el-form-item label="会话名称" :label-width="formLabelWidth">
+                    <el-input v-model="talkName1" auto-complete="off" placeholder="请输入会话名称..."></el-input>
+                </el-form-item>
+            </el-form>
+            <span class="rename_btn">
+                <el-button @click="dialogVisibleUpdate = false">取 消</el-button>
+                <el-button type="primary" @click="UpdateTalkName()">确 定</el-button>
+            </span>
+        </el-dialog>
     </div>
 </template>
 
@@ -119,7 +215,7 @@ import radarTeacher from "./dataCom/radarTeacher.vue";
 import aiLeader from "./checkAi/aiLeader.vue";
 import txtView from "./choseCheck/txtView.vue";
 import Cascader from "./dataCom/cascader.vue";
-import smartMenu from "./smartBox/smartMenu.vue";
+// import smartMenu from "./smartBox/smartMenu.vue";
 import csvTableView from "./choseCheck/csvTableView.vue";
 
 
@@ -127,7 +223,7 @@ export default {
     name: 'smarter',
     components: {
         radarZong, radarTeacher, Cascader,
-        aiLeader, txtView, smartMenu, csvTableView
+        aiLeader, txtView, csvTableView
     },
     data() {
         return {
@@ -138,14 +234,118 @@ export default {
             role: this.$route.query.role,
             cid: this.$route.query.cid,
             menuList: [],
+            aiContentArea: [],
             menuIndex: 0,
             courseInfoList: [],
+            page: 1,
+            total: 0,
+            talkName: '',
+            talkName1: '',
+            chatId: '',
+            formLabelWidth: "100px",
+            pageSize: 8,
             loading: true,
             activeMenu: 1, // 默认激活第一个
-            examineData:[]
+            fileMenu: 1,
+            cutNumber: 1,
+            dialogVisibleUpdate: false,
+            examineData: [],
+            tableData: [],
+            options: [{
+                value: '1',
+                label: '20条/页'
+            }, {
+                value: '2',
+                label: '双皮奶'
+            }],
+            value: '1'
+
         };
     },
     methods: {
+        handleRowClick(row, column, event) {
+            this.activeMenu = 1;
+            console.log(JSON.stringify(row))
+            this.$nextTick(() => {
+                // 调试输出
+                console.log(this.$refs.aiChat);
+                if (this.$refs.aiChat) {
+                    this.$refs.aiChat.getChatList(row.chatid);
+                    let obj = JSON.parse(row.json)
+                    this.menuList = obj;
+                    this.$refs.aiChat.fileList = obj.map(i=>i.url)
+                } else {
+                    console.error('aiChat ref is not available');
+                }
+            });
+        },
+        openUpdate(name, id) {
+            this.talkName1 = name;
+            this.chatId = id;
+            this.dialogVisibleUpdate = true;
+        },
+        UpdateTalkName() {
+            const j = this.menuList.map(i => i.url).join(",")
+            let params = [{
+                id: this.chatId,
+                name: this.talkName1,
+                j:j
+            }];
+            this.ajax
+                .post(this.$store.state.api + "updateChat", params)
+                .then(res => {
+                    if (this.talkName1 == '') {
+                        this.$message({
+                            message: "不能为空",
+                            type: "error",
+                        });
+                    } else {
+                        this.$message({
+                            message: "修改成功",
+                            type: "success",
+                        });
+                        this.dialogVisibleUpdate = false;
+                        this.historyTalk();
+                        this.talkName1 = '';
+                    }
+                })
+                .catch((err) => {
+                    console.error(err);
+                })
+        },
+        delete_talk(id) {
+            let params = [{
+                id: id
+            }]
+            this.$confirm("确定删除此会话吗?", "提示", {
+                confirmButtonText: "确定",
+                cancelButtonText: "取消",
+                type: "warning",
+            })
+                .then(() => {
+                    this.ajax
+                        .post(this.$store.state.api + "deleteChat", params)
+                        .then((res) => {
+                            this.$message({
+                                message: "删除成功",
+                                type: "success",
+                            });
+                            this.historyTalk();
+                        })
+                        .catch((err) => {
+                            this.$message.error("删除失败");
+                            console.error(err);
+                        });
+                })
+                .catch(() => { });
+        },
+        handleCurrentChange(newPage) {
+            this.page = newPage;
+            this.historyTalk();
+        },
+        handleClose(done) {
+            done();
+        },
         // 获取基础页面数据
         getPageBase() {
             let params = {
@@ -157,11 +357,11 @@ export default {
             this.ajax
                 .get(this.$store.state.api + "selectTestExamineBase", params)
                 .then(res => {
-                    console.log('selectTestExamineBase',res.data[0]);
-                    this.examineData=res.data[0]
+                    console.log('selectTestExamineBase', res.data[0]);
+                    this.examineData = res.data[0]
                 })
                 .catch(error => {
-                console.log(error);
+                    console.log(error);
                 });
         },
         deleteMenuItem(index) {
@@ -169,14 +369,41 @@ export default {
             this.menuIndex = 0
             this.$refs.aiChat.delFileList(index)
             this.$forceUpdate()
-            console.log('menuList',this.menuList);
-            
+            console.log('menuList', this.menuList);
+
+        },
+
+        historyTalk() {
+            let params = {
+                uid: this.userid,
+                n: this.talkName,
+                page: this.page,
+                num: this.pageSize
+            };
+            this.ajax
+                .get(this.$store.state.api + "getChatHistory", params)
+                .then((res) => {
+                    this.tableData = res.data[0]
+                    console.log("tableData", this.tableData);
+                    this.total = res.data[0].length > 0 ? res.data[0][0].num : 0;
+                    console.log("111111", this.total);
+
+
+                })
+                .catch((err) => {
+                    console.error(err);
+                });
         },
         pushFileData(data) {
             this.menuList.push(data)
             console.log("menuList", this.menuList);
 
         },
+        // pushAiContent(data){
+        //     this.aiContentArea.push(...data),
+        //     console.log("aiContentArea",this.aiContentArea);
+
+        // },
         clearFileData() {
             this.menuList = []
         },
@@ -195,10 +422,13 @@ export default {
                     promiseList.push(this.getCourseData(el))
                 })
                 Promise.all(promiseList).then(res => {
-                    console.log("courseInfoList", this.courseInfoList)
                     this.courseInfoList = res
+                    console.log("courseInfoList", this.courseInfoList)
                     this.loading = false
-                })
+                }).catch(err => {
+                    console.error("Error occurred:", err);
+                    this.loading = false;  // 如果有错误,也要停止loading
+                });
             }
         },
         getCourseData(courseId) {
@@ -294,13 +524,14 @@ export default {
                     });
             })
         },
+
     },
     computed: {
         showFileUrl() {
             if (this.menuList.length) {
                 return this.menuList[this.menuIndex].url
             } else {
-                return ""
+                return "";
             }
         },
         aiBoxRightCid() {
@@ -311,15 +542,27 @@ export default {
                 _cidList.sort((a, b) => parseInt(b) - parseInt(a));
                 _result = _cidList.join(',');
             }
+            console.log("我是cid", _result);
 
             return _result
         }
     },
     mounted() {
         this.getData();
-        this.getPageBase()
+        this.getPageBase();
+        this.historyTalk();
+
+    },
+    watch: {
+        activeMenu(newValue) {
+            if (newValue === 2) {
+                console.log("HelloWorld");
+                this.historyTalk();
+            }
+        },
     }
 
+
 };
 </script>
 
@@ -531,6 +774,31 @@ export default {
     -moz-osx-font-smoothing: grayscale;
 }
 
+.dialog_diy>>>.el-dialog__header {
+    background: #3d67bc !important;
+    padding: 15px 20px;
+}
+
+.dialog_diy>>>.el-dialog__title {
+    color: #fff;
+}
+
+.student_table>>>.el-table--border td {
+    border-right: 0px !important;
+}
+
+.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;
+}
+
 .cc_bottom {
     width: 100%;
     height: calc(100% - 66px - 10px);
@@ -551,12 +819,125 @@ export default {
     height: 100%;
 }
 
+.cc_b_left {
+    border-right: 1px solid #E4E7ED;
+    display: flex;
+    flex-direction: column;
+    justify-content: space-between;
+    height: 100%;
+    width: 13%;
+}
+
+.menu_container {
+    flex: 1;
+    /* 占据除折叠按钮外的所有空间 */
+}
+
+.cc_b_l_menu {
+    padding: 10px;
+    margin: 17px;
+    border-radius: 7px;
+    color: #828282;
+    cursor: pointer;
+    display: flex;
+}
+
+.cc_b_l_menu.active {
+    background-color: #3681fc;
+    color: #fff;
+
+}
+
+.session_icon {
+    background: url('../../../assets/icon/test/test_session.png') no-repeat;
+    width: 18px;
+    height: 18px;
+    display: inline-block;
+    background-size: contain;
+}
+
+.session_icon.active {
+    background: url('../../../assets/icon/test/test_session_active.png') no-repeat;
+    width: 18px;
+    height: 18px;
+    display: inline-block;
+    background-size: contain;
+}
+
+.history_icon {
+    background: url('../../../assets/icon/test/test_history.png') no-repeat;
+    width: 18px;
+    height: 18px;
+    display: inline-block;
+    background-size: contain;
+}
+
+.history_icon.active {
+    background: url('../../../assets/icon/test/test_history_active.png') no-repeat;
+    width: 18px;
+    height: 18px;
+    display: inline-block;
+    background-size: contain;
+}
+
+/* .mysql_icon{
+    background:url('../../../../assets/icon/test/test_mysql.png') no-repeat;
+    width: 18px;
+    height: 18px;
+    display: inline-block;
+    background-size: contain;
+}
+.mysql_icon.active{
+    background:url('../../../../assets/icon/test/test_mysql_active.png') no-repeat;
+    width: 18px;
+    height: 18px;
+    display: inline-block;
+    background-size: contain;
+} */
+.fold_btn {
+    padding: 27px 20px;
+    cursor: pointer;
+    border-top: 1px solid #E4E7ED;
+    margin-top: auto;
+    /* 确保折叠按钮在底部 */
+}
+
+.more_icon {
+    background: url('../../../assets/icon/test/test_more.png') no-repeat;
+    width: 14px;
+    height: 14px;
+    display: inline-block;
+    background-size: contain;
+    cursor: pointer;
+}
+
 .cc_b_right {
     width: 50%;
     height: 100%;
     box-sizing: border-box;
 }
 
+.preview_file,
+.bianji_file {
+    margin: 10px;
+    width: 65px;
+    cursor: pointer;
+}
+
+.preview_file.active {
+    border-bottom: 2px solid blue;
+}
+
+.bianji_file.active {
+    border-bottom: 2px solid blue;
+}
+
+.bianji_area {
+    background-color: #e5e4e4;
+    height: 600px;
+    margin: 10px;
+}
+
 .cc_b_r_menu {
     width: 100%;
     height: 50px;
@@ -569,15 +950,15 @@ export default {
 
 .cc_b_r_menu>div {
     height: 100%;
-	max-width: 100px;
-	padding: 0 15px;
-	display: flex;
-	text-align: center;
-	/* justify-content: center; */
-	align-items: center;
-	cursor: pointer;
-	transition: all 0.3s;
-	/* text-overflow: ellipsis;
+    max-width: 100px;
+    padding: 0 15px;
+    display: flex;
+    text-align: center;
+    /* justify-content: center; */
+    align-items: center;
+    cursor: pointer;
+    transition: all 0.3s;
+    /* text-overflow: ellipsis;
 	overflow: hidden;
 	white-space: nowrap; */
 }
@@ -601,19 +982,25 @@ export default {
 .cc_b_r_content {
     width: 100%;
     height: calc(100% - 50px);
+    max-height: 700px;
+    overflow-y: auto;
+    max-height: 83vh;
 }
-.cc_b_r_btn{
+
+.cc_b_r_btn {
     display: flex;
     align-items: center;
 }
-.close_icon{
+
+.close_icon {
     width: 0 !important;
     height: 22px;
     display: inline-block;
     background-size: contain;
     cursor: pointer;
 }
-.close_icon.active{
+
+.close_icon.active {
     background: url('../../../assets/icon/test/test_close_active.png') no-repeat;
     width: 40px !important;
     height: 22px;
@@ -621,11 +1008,13 @@ export default {
     background-size: contain;
     cursor: pointer;
 }
-.b_r_menu{
+
+.b_r_menu {
     display: flex;
     justify-content: space-around;
 }
-.b_r_menu_content{
+
+.b_r_menu_content {
     display: flex;
     flex-direction: column;
     background: linear-gradient(to bottom, #dfeaff, #ffffff, #f6f9ff);
@@ -634,15 +1023,101 @@ export default {
     width: 50%;
     margin-right: 14px
 }
-.m_c_title{
+
+.m_c_title {
     margin: 10px 7px 7px 21px;
     font-size: 16px;
     font-weight: bold;
 }
-.m_c_item{
+
+.m_c_item {
     border-radius: 5px;
     padding: 8px 8px 8px 13px;
     margin: 7px;
     border: 1px solid #E4E7ED;
 }
+
+.history_talk {
+    background: linear-gradient(to bottom, #dfeaff, #ffffff, #f6f9ff);
+    margin: 13px;
+    padding: 10px;
+}
+
+.h_t_head {
+    display: flex;
+    justify-content: space-between;
+}
+
+.t_h_left {
+    margin-left: 13px;
+    font-size: 13px;
+}
+
+.h_t_table {
+    margin: 10px;
+    box-shadow: 0px 0px 12px rgb(190 193 199);
+}
+
+.h_t_table>>>.el-table td,
+.el-table th {
+    padding: 9px 0;
+}
+
+.bianji {
+    display: flex;
+    align-items: center;
+    margin-right: 10px;
+}
+
+.bianji:hover {
+    color: rgb(14, 173, 236);
+    cursor: pointer;
+}
+
+.rename_btn {
+    display: flex;
+    justify-content: flex-end;
+}
+
+.h_t_bottom {
+    display: flex;
+    justify-content: flex-end;
+    align-items: center;
+    margin-right: 9px;
+}
+
+.el_select {
+    width: 89px;
+}
+
+
+.table_title {
+    background-color: gray;
+}
+
+.student_input>>>.el-input__inner {
+    height: 30px;
+    width: 179px;
+    font-size: 13px;
+    padding: 0 10px;
+}
+
+.serach_icon {
+    position: absolute;
+    right: 12px;
+    top: 50%;
+    transform: translateY(-50%);
+    width: 13px;
+    height: 13px;
+    background: url("../../../assets/icon/test/test_search.png") no-repeat;
+    background-size: 100% 100%;
+    cursor: pointer;
+}
+
+.el-input {
+    position: relative;
+    font-size: 14px;
+    display: inline-block;
+    width: 100%;
+}
 </style>

+ 266 - 0
src/components/pages/testStudent/view/component/sweep.vue

@@ -0,0 +1,266 @@
+<template>
+  <div class="c_box">
+    <div class="choice_box">
+      <div class="title" style="display: flex;align-items: center;">
+        <span class="g_t_index" style="min-width: fit-content;">{{
+          tindex + 1
+        }}</span>
+        <span>{{ checkJson.title }}</span>
+      </div>
+      <div
+        class="detail"
+        v-if="checkJson.detail"
+        v-html="checkJson.detail"
+        style="color: #00000066;margin-top: 5px;"
+      ></div>
+
+			<div
+        class="detail"
+        v-if="checkJson.answer2 && typeof checkJson.answer2=='string'"
+        v-html="checkJson.answer2"
+        style="color: #000000;margin-top: 5px;"
+      ></div>
+			<el-button @click="sweepBtn" type="primary" size="mini" style="margin-top: 10px;">扫一扫</el-button>
+    </div>
+
+  </div>
+</template>
+
+<script>
+
+export default {
+  props: {
+    tindex: {
+      type: Number
+    },
+    cJson: {
+      type: Object
+    },
+    checktype: {
+      type: Number,
+      default: 1
+    },
+    see: {
+      type: Boolean,
+      default: false
+    }
+  },
+  data() {
+    return {
+      option: {
+        1: { name: "附件" }
+      },
+      userid: this.$route.query.userid,
+      checkJson: {
+				title:"",
+				detail:""
+			},
+    };
+  },
+  watch: {
+    checkJson: {
+      handler(newValue) {
+        this.$emit("update:cJson", newValue);
+      },
+      deep: true
+    }
+  },
+  methods: {
+
+    depthCopy(s) {
+      return JSON.parse(JSON.stringify(s));
+    },
+
+		sweepBtn(){
+			this.$message.error("请到手机端内扫码")
+		}
+  },
+  mounted() {
+    this.checkJson = this.cJson ? this.depthCopy(this.cJson) : undefined;
+  }
+};
+</script>
+
+<style scoped>
+.c_box {
+  width: 100%;
+  position: relative;
+	padding-left: 45px;
+}
+
+/* .mask {
+    position: absolute;
+    height: 100%;
+    width: 100%;
+    z-index: 2;
+} */
+
+.choice_box {
+  white-space: pre-line;
+}
+
+.choice_box > .title {
+  font-weight: bold;
+  width: 100%;
+  word-break: break-all;
+}
+
+.choice_box > .choices {
+  margin-top: 10px;
+}
+
+.choices > .page {
+  margin-top: 10px;
+  display: flex;
+  align-items: center;
+}
+
+.p_page {
+  margin: 0 10px;
+}
+
+.course {
+  display: flex;
+  align-items: center;
+  cursor: pointer;
+}
+
+.course + .course {
+  margin-top: 10px;
+}
+
+.course > .banner {
+  width: 200px;
+  height: 120px;
+  border-radius: 5px;
+  overflow: hidden;
+  border: 1px solid #3896fc;
+  box-sizing: border-box;
+  padding: 5px;
+  margin-right: 15px;
+}
+.course > .banner > img {
+  width: 100%;
+  height: 100%;
+  object-fit: cover;
+}
+.course > .content {
+}
+.course > .content > .c_c {
+}
+.course > .content > .c_c + .c_c {
+  margin-top: 5px;
+}
+.course > .content > .c_c span:nth-child(1) {
+}
+.course > .content > .c_c span:nth-child(2) {
+}
+
+.g_t_index {
+  color: #3681fc;
+  font-size: 28px;
+  font-weight: bold;
+  position: relative;
+  margin-right: 30px;
+  margin-left: -40px;
+}
+
+.g_t_index + span {
+  font-weight: bold;
+  font-size: 18px;
+}
+
+.g_t_index::after {
+  content: "";
+  width: 18px;
+  height: 2px;
+  position: absolute;
+  right: -18px;
+  top: 50%;
+  transform: translateY(-50%);
+  background: #3681fc;
+}
+
+.g_t_index::before {
+  content: "";
+  width: 6px;
+  height: 6px;
+  border-right: 2px solid #3681fc;
+  border-top: 2px solid #3681fc;
+  position: absolute;
+  right: -15px;
+  top: 50%;
+  transform: rotate(45deg) translateY(-5px);
+}
+
+.c_list {
+  width: calc(100% - 10px);
+  min-height: 200px;
+  height: auto;
+  border: 1px solid #e7e7e7;
+  border-radius: 5px;
+  box-sizing: border-box;
+  padding: 10px;
+  display: flex;
+  flex-wrap: wrap;
+  /* overflow: auto; */
+}
+
+.c_l_add1 {
+  width: 100%;
+  height: 200px;
+  background-color: #F9FAFB;
+	border: 1.5px dashed #dfdfdf;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  color: #00000066;
+  border-radius: 5px;
+  font-size: 18px;
+  cursor: pointer;
+}
+
+.c_l_add2{
+	width: 230px;
+  height: 200px;
+	background-color: #F9FAFB;
+	border: 1.5px dashed #dfdfdf;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  color: #00000066;
+  border-radius: 5px;
+  font-size: 18px;
+  cursor: pointer;
+}
+
+.c_l_item {
+  width: 230px;
+  height: 200px;
+  margin-right: 10px;
+  box-sizing: border-box;
+  border: solid 1px #3896FC;
+  border-radius: 5px;
+	cursor: pointer;
+	box-sizing: border-box;
+	padding: 5px;
+}
+
+.c_l_item > img {
+  width: 100%;
+  height: 110px;
+  object-fit: cover;
+	margin-bottom: 5px;
+}
+
+.c_l_item > div {
+  width: 210px;
+  display: block;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+  font-size: 14px; /* 设置字体大小 */
+  color: #333; /* 设置字体颜色 */
+	box-sizing: border-box;
+}
+</style>

+ 21 - 4
src/components/pages/testStudent/view/component/topic.vue

@@ -27,6 +27,8 @@
               :isTeacher="isTeacher"></timeV>
             <courseV2 :tindex="index" :cJson.sync="item.json" :checktype="checktype" v-else-if="item.type == 11"
               :see="see" :isTeacher="isTeacher" @getTestWorkByCid="getTestWorkByCid" @publish2="publish2" :issetPage.sync="issetPage" :tid="tid"></courseV2>
+							<sweep :tindex="index" :cJson.sync="item.json" :checktype="checktype" v-else-if="item.type == 12"
+							:see="see" :isTeacher="isTeacher"></sweep>
             <!-- <span v-else>暂未设置题目</span> -->
           </div>
           <div v-for="(item2, index2) in item.array" :key="`${index}-${index2}`" class="check_box_xia">
@@ -45,6 +47,8 @@
                 :see="see" :isTeacher="isTeacher"></evaV>
               <timeV :tindex="index2" :cJson.sync="item2.json" :checktype="checktype" v-else-if="item2.type == 8"
                 :see="see" :isTeacher="isTeacher"></timeV>
+								<sweep :tindex="index2" :cJson.sync="item2.json" :checktype="checktype" v-else-if="item2.type == 12"
+								:see="see" :isTeacher="isTeacher"></sweep>
               <!-- <span v-else>暂未设置题目</span> -->
             </div>
           </div>
@@ -69,6 +73,8 @@
               :isTeacher="isTeacher"></timeV>
             <courseV2 :tindex="index" :cJson.sync="item.json" :checktype="checktype" v-else-if="item.type == 11"
               :see="see" :isTeacher="isTeacher" @getTestWorkByCid="getTestWorkByCid" @publish2="publish2" :issetPage.sync="issetPage" :tid="tid"></courseV2>
+							<sweep :tindex="index" :cJson.sync="item.json" :checktype="checktype" v-else-if="item.type == 12"
+               :see="see" :isTeacher="isTeacher"></sweep>
             <!-- <span v-else>暂未设置题目</span> -->
           </div>
           <div v-for="(item2, index2) in item.array" :key="`${index}-${index2}`" class="check_box_xia">
@@ -89,6 +95,8 @@
                 :see="see" :isTeacher="isTeacher"></timeV>
               <courseV2 :tindex="index2" :cJson.sync="item2.json" :checktype="checktype" v-else-if="item2.type == 11"
                 :see="see" :isTeacher="isTeacher" @getTestWorkByCid="getTestWorkByCid" @publish2="publish2" :issetPage.sync="issetPage" :tid="tid"></courseV2>
+							<sweep :tindex="index2" :cJson.sync="item2.json" :checktype="checktype" v-else-if="item2.type == 12"
+               :see="see" :isTeacher="isTeacher"></sweep>
               <!-- <span v-else>暂未设置题目</span> -->
             </div>
           </div>
@@ -115,6 +123,7 @@ import courseV from './course.vue';
 import evaV from './eva.vue';
 import timeV from './time.vue';
 import courseV2 from './course2.vue';
+import sweep from './sweep'
 export default {
   props: {
     cJson: {
@@ -159,6 +168,7 @@ export default {
     evaV,
     timeV,
     courseV2,
+		sweep,
   },
   data() {
     return {
@@ -270,18 +280,20 @@ export default {
         let checkArray = _json.filter((item) => {
           if (item.array) {
             item.array = item.array.filter((item2) => {
-              if (item2.ttype == 1 && item2.json && !item2.json.answer2 && item2.type != 6 && item2.type != 7 && item2.type != 8) {
+              if (item2.ttype == 1 && item2.json && !item2.json.answer2 && item2.type != 6 && item2.type != 7 && item2.type != 8 && item2.type != 12) {
                 item2.json.answer2 = [];
               } else if (item2.ttype == 1 && item2.json && !item2.json.answer2 && item2.type == 6) {
                 item2.json.answer2 = this.gcourseid ? this.gcourseid : item2.json.courses[0];
               } else if (item2.ttype == 1 && item2.json && !item2.json.answer2 && item2.json.answer2 !== 0 && item2.type == 7) {
                 item2.json.answer2 = '';
-              } else if (item2.ttype == 1 && item2.json && !item2.json.answer2 && item2.json.answer2 !== 0 && item2.type == 8) {
+              } else if (item2.ttype == 1 && item2.json && !item2.json.answer2 && item2.json.answer2 !== 0 && item2.type == 8 ) {
+                item2.json.answer2 = '';
+              }else if (item2.ttype == 1 && item2.json && !item2.json.answer2 && item2.json.answer2 !== 0 && item2.type == 12 ) {
                 item2.json.answer2 = '';
               }
               if (item2.array) {
                 item2.array = item2.array.filter((item3) => {
-                  if (item3.ttype == 1 && item3.json && !item3.json.answer2 && item3.type != 6 && item3.type != 7 && item3.type != 8) {
+                  if (item3.ttype == 1 && item3.json && !item3.json.answer2 && item3.type != 6 && item3.type != 7 && item3.type != 8 && item3.type != 12) {
                     item3.json.answer2 = [];
                   } else if (item3.ttype == 1 && item3.json && !item3.json.answer2 && item3.type == 6) {
                     item3.json.answer2 = this.gcourseid ? this.gcourseid : item3.json.courses[0];
@@ -289,7 +301,10 @@ export default {
                     item3.json.answer2 = '';
                   } else if (item3.ttype == 1 && item3.json && !item3.json.answer2 && item3.json.answer2 !== 0 && item3.type == 8) {
                     item3.json.answer2 = '';
+                  }else if (item3.ttype == 1 && item3.json && !item3.json.answer2 && item3.json.answer2 !== 0 && item3.type == 12) {
+                    item3.json.answer2 = '';
                   }
+
                   return item3;
                 });
               }
@@ -298,7 +313,7 @@ export default {
               );
             });
           }
-          if (item.ttype == 1 && item.json && !item.json.answer2 && item.type != 6 && item.type != 7 && item.type != 8) {
+          if (item.ttype == 1 && item.json && !item.json.answer2 && item.type != 6 && item.type != 7 && item.type != 8 && item.type != 12) {
             item.json.answer2 = [];
           } else if (item.ttype == 1 && item.json && !item.json.answer2 && item.type == 6) {
             item.json.answer2 = this.gcourseid ? this.gcourseid : item.json.courses[0];
@@ -306,6 +321,8 @@ export default {
             item.json.answer2 = '';
           } else if (item.ttype == 1 && item.json && !item.json.answer2 && item.json.answer2 !== 0 && item.type == 8) {
             item.json.answer2 = '';
+          }else if (item.ttype == 1 && item.json && !item.json.answer2 && item.json.answer2 !== 0 && item.type == 12) {
+            item.json.answer2 = '';
           }
           console.log(item.array);
           return (item.ttype != 1 && item.array.length > 0) || item.ttype == 1;

Some files were not shown because too many files changed in this diff