dusenyao 4 rokov pred
rodič
commit
2428a332ef

+ 217 - 64
package-lock.json

@@ -1649,8 +1649,7 @@
     "@types/json-schema": {
       "version": "7.0.7",
       "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz",
-      "integrity": "sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==",
-      "dev": true
+      "integrity": "sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA=="
     },
     "@types/mdast": {
       "version": "3.0.3",
@@ -2927,16 +2926,6 @@
           "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
           "dev": true
         },
-        "ssri": {
-          "version": "7.1.0",
-          "resolved": "https://registry.npmjs.org/ssri/-/ssri-7.1.0.tgz",
-          "integrity": "sha512-77/WrDZUWocK0mvA5NTRQyveUf+wsrIc6vyrxpS8tVvYBcX215QbafrJR3KtkpskIzoFLqqNuuYQvxaMjXJ/0g==",
-          "dev": true,
-          "requires": {
-            "figgy-pudding": "^3.5.1",
-            "minipass": "^3.1.1"
-          }
-        },
         "supports-color": {
           "version": "7.2.0",
           "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
@@ -3414,8 +3403,7 @@
     "ajv-keywords": {
       "version": "3.5.2",
       "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
-      "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
-      "dev": true
+      "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ=="
     },
     "alphanum-sort": {
       "version": "1.0.2",
@@ -4263,6 +4251,11 @@
         "@babel/helper-define-polyfill-provider": "^0.2.0"
       }
     },
+    "babel-plugin-syntax-dynamic-import": {
+      "version": "6.18.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz",
+      "integrity": "sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo="
+    },
     "babel-plugin-transform-es2015-modules-commonjs": {
       "version": "6.26.2",
       "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz",
@@ -6653,9 +6646,9 @@
       "dev": true
     },
     "dns-packet": {
-      "version": "1.3.1",
-      "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.1.tgz",
-      "integrity": "sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg==",
+      "version": "1.3.4",
+      "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.4.tgz",
+      "integrity": "sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA==",
       "dev": true,
       "requires": {
         "ip": "^1.1.0",
@@ -9864,12 +9857,6 @@
             "tr46": "^1.0.1",
             "webidl-conversions": "^4.0.2"
           }
-        },
-        "ws": {
-          "version": "7.4.5",
-          "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.5.tgz",
-          "integrity": "sha512-xzyu3hFvomRfXKH8vOFMU3OguG6oOvhXMo3xsGy3xWExqaM2dxBbVxuD99O7m3ZUFMvvscsZDqxfgMaRr/Nr1g==",
-          "dev": true
         }
       }
     },
@@ -10239,7 +10226,6 @@
       "version": "2.2.0",
       "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz",
       "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==",
-      "dev": true,
       "requires": {
         "minimist": "^1.2.5"
       }
@@ -12165,6 +12151,11 @@
         "sha.js": "^2.4.8"
       }
     },
+    "pdfjs-dist": {
+      "version": "2.6.347",
+      "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-2.6.347.tgz",
+      "integrity": "sha512-QC+h7hG2su9v/nU1wEI3SnpPIrqJODL7GTDFvR74ANKGq1AFJW16PH8VWnhpiTi9YcLSFV9xLeWSgq+ckHLdVQ=="
+    },
     "performance-now": {
       "version": "2.1.0",
       "resolved": "https://registry.npm.taobao.org/performance-now/download/performance-now-2.1.0.tgz",
@@ -12256,9 +12247,9 @@
       "dev": true
     },
     "postcss": {
-      "version": "7.0.35",
-      "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz",
-      "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==",
+      "version": "7.0.36",
+      "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
+      "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
       "dev": true,
       "requires": {
         "chalk": "^2.4.2",
@@ -13295,6 +13286,37 @@
         "unpipe": "1.0.0"
       }
     },
+    "raw-loader": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-4.0.2.tgz",
+      "integrity": "sha512-ZnScIV3ag9A4wPX/ZayxL/jZH+euYb6FcUinPcgiQW0+UBtEv0O6Q3lGd3cqJ+GHH+rksEv3Pj99oxJ3u3VIKA==",
+      "requires": {
+        "loader-utils": "^2.0.0",
+        "schema-utils": "^3.0.0"
+      },
+      "dependencies": {
+        "loader-utils": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz",
+          "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==",
+          "requires": {
+            "big.js": "^5.2.2",
+            "emojis-list": "^3.0.0",
+            "json5": "^2.1.2"
+          }
+        },
+        "schema-utils": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz",
+          "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==",
+          "requires": {
+            "@types/json-schema": "^7.0.6",
+            "ajv": "^6.12.5",
+            "ajv-keywords": "^3.5.2"
+          }
+        }
+      }
+    },
     "react-is": {
       "version": "16.13.1",
       "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
@@ -13568,16 +13590,16 @@
       "dev": true
     },
     "renderkid": {
-      "version": "2.0.5",
-      "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.5.tgz",
-      "integrity": "sha512-ccqoLg+HLOHq1vdfYNm4TBeaCDIi1FLt3wGojTDSvdewUv65oTmI3cnT2E4hRjl1gzKZIPK+KZrXzlUYKnR+vQ==",
+      "version": "2.0.7",
+      "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.7.tgz",
+      "integrity": "sha512-oCcFyxaMrKsKcTY59qnCAtmDVSLfPbrv6A3tVbPdFMMrv5jaK10V6m40cKsoPNhAqN6rmHW9sswW4o3ruSrwUQ==",
       "dev": true,
       "requires": {
-        "css-select": "^2.0.2",
-        "dom-converter": "^0.2",
-        "htmlparser2": "^3.10.1",
-        "lodash": "^4.17.20",
-        "strip-ansi": "^3.0.0"
+        "css-select": "^4.1.3",
+        "dom-converter": "^0.2.0",
+        "htmlparser2": "^6.1.0",
+        "lodash": "^4.17.21",
+        "strip-ansi": "^3.0.1"
       },
       "dependencies": {
         "ansi-regex": {
@@ -13586,6 +13608,83 @@
           "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
           "dev": true
         },
+        "css-select": {
+          "version": "4.1.3",
+          "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.3.tgz",
+          "integrity": "sha512-gT3wBNd9Nj49rAbmtFHj1cljIAOLYSX1nZ8CB7TBO3INYckygm5B7LISU/szY//YmdiSLbJvDLOx9VnMVpMBxA==",
+          "dev": true,
+          "requires": {
+            "boolbase": "^1.0.0",
+            "css-what": "^5.0.0",
+            "domhandler": "^4.2.0",
+            "domutils": "^2.6.0",
+            "nth-check": "^2.0.0"
+          }
+        },
+        "css-what": {
+          "version": "5.0.1",
+          "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.0.1.tgz",
+          "integrity": "sha512-FYDTSHb/7KXsWICVsxdmiExPjCfRC4qRFBdVwv7Ax9hMnvMmEjP9RfxTEZ3qPZGmADDn2vAKSo9UcN1jKVYscg==",
+          "dev": true
+        },
+        "dom-serializer": {
+          "version": "1.3.2",
+          "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz",
+          "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==",
+          "dev": true,
+          "requires": {
+            "domelementtype": "^2.0.1",
+            "domhandler": "^4.2.0",
+            "entities": "^2.0.0"
+          }
+        },
+        "domelementtype": {
+          "version": "2.2.0",
+          "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz",
+          "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==",
+          "dev": true
+        },
+        "domhandler": {
+          "version": "4.2.0",
+          "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.0.tgz",
+          "integrity": "sha512-zk7sgt970kzPks2Bf+dwT/PLzghLnsivb9CcxkvR8Mzr66Olr0Ofd8neSbglHJHaHa2MadfoSdNlKYAaafmWfA==",
+          "dev": true,
+          "requires": {
+            "domelementtype": "^2.2.0"
+          }
+        },
+        "domutils": {
+          "version": "2.7.0",
+          "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.7.0.tgz",
+          "integrity": "sha512-8eaHa17IwJUPAiB+SoTYBo5mCdeMgdcAoXJ59m6DT1vw+5iLS3gNoqYaRowaBKtGVrOF1Jz4yDTgYKLK2kvfJg==",
+          "dev": true,
+          "requires": {
+            "dom-serializer": "^1.0.1",
+            "domelementtype": "^2.2.0",
+            "domhandler": "^4.2.0"
+          }
+        },
+        "htmlparser2": {
+          "version": "6.1.0",
+          "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz",
+          "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==",
+          "dev": true,
+          "requires": {
+            "domelementtype": "^2.0.1",
+            "domhandler": "^4.0.0",
+            "domutils": "^2.5.2",
+            "entities": "^2.0.0"
+          }
+        },
+        "nth-check": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.0.tgz",
+          "integrity": "sha512-i4sc/Kj8htBrAiH1viZ0TgU8Y5XqCaV/FziYK6TBczxmeKm3AEFWqqF3195yKudrarqy7Zu80Ra5dobFjn9X/Q==",
+          "dev": true,
+          "requires": {
+            "boolbase": "^1.0.0"
+          }
+        },
         "strip-ansi": {
           "version": "3.0.1",
           "resolved": "https://registry.npm.taobao.org/strip-ansi/download/strip-ansi-3.0.1.tgz",
@@ -14662,6 +14761,16 @@
         "tweetnacl": "~0.14.0"
       }
     },
+    "ssri": {
+      "version": "7.1.1",
+      "resolved": "https://registry.npmjs.org/ssri/-/ssri-7.1.1.tgz",
+      "integrity": "sha512-w+daCzXN89PseTL99MkA+fxJEcU3wfaE/ah0i0lnOlpG1CYLJ2ZjzEry68YBKfLs4JfoTShrTEsJkAZuNZ/stw==",
+      "dev": true,
+      "requires": {
+        "figgy-pudding": "^3.5.1",
+        "minipass": "^3.1.1"
+      }
+    },
     "stable": {
       "version": "0.1.8",
       "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz",
@@ -15315,9 +15424,9 @@
           }
         },
         "trim-newlines": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.0.tgz",
-          "integrity": "sha512-C4+gOpvmxaSMKuEf9Qc134F1ZuOHVXKRbtEflf4NTtuuJDEIJ9p5PXsalL8SkeRw+qit1Mo+yuvMPAKwWg/1hA==",
+          "version": "3.0.1",
+          "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz",
+          "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==",
           "dev": true
         },
         "type-fest": {
@@ -15737,15 +15846,15 @@
       "dev": true
     },
     "svgo": {
-      "version": "2.3.0",
-      "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.3.0.tgz",
-      "integrity": "sha512-fz4IKjNO6HDPgIQxu4IxwtubtbSfGEAJUq/IXyTPIkGhWck/faiiwfkvsB8LnBkKLvSoyNNIY6d13lZprJMc9Q==",
+      "version": "2.3.1",
+      "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.3.1.tgz",
+      "integrity": "sha512-riDDIQgXpEnn0BEl9Gvhh1LNLIyiusSpt64IR8upJu7MwxnzetmF/Y57pXQD2NMX2lVyMRzXt5f2M5rO4wG7Dw==",
       "dev": true,
       "requires": {
         "@trysound/sax": "0.1.1",
         "chalk": "^4.1.0",
         "commander": "^7.1.0",
-        "css-select": "^3.1.2",
+        "css-select": "^4.1.3",
         "css-tree": "^1.1.2",
         "csso": "^4.2.0",
         "stable": "^0.1.8"
@@ -15792,15 +15901,15 @@
           "dev": true
         },
         "css-select": {
-          "version": "3.1.2",
-          "resolved": "https://registry.npmjs.org/css-select/-/css-select-3.1.2.tgz",
-          "integrity": "sha512-qmss1EihSuBNWNNhHjxzxSfJoFBM/lERB/Q4EnsJQQC62R2evJDW481091oAdOr9uh46/0n4nrg0It5cAnj1RA==",
+          "version": "4.1.3",
+          "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.3.tgz",
+          "integrity": "sha512-gT3wBNd9Nj49rAbmtFHj1cljIAOLYSX1nZ8CB7TBO3INYckygm5B7LISU/szY//YmdiSLbJvDLOx9VnMVpMBxA==",
           "dev": true,
           "requires": {
             "boolbase": "^1.0.0",
-            "css-what": "^4.0.0",
-            "domhandler": "^4.0.0",
-            "domutils": "^2.4.3",
+            "css-what": "^5.0.0",
+            "domhandler": "^4.2.0",
+            "domutils": "^2.6.0",
             "nth-check": "^2.0.0"
           }
         },
@@ -15815,19 +15924,19 @@
           }
         },
         "css-what": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/css-what/-/css-what-4.0.0.tgz",
-          "integrity": "sha512-teijzG7kwYfNVsUh2H/YN62xW3KK9YhXEgSlbxMlcyjPNvdKJqFx5lrwlJgoFP1ZHlB89iGDlo/JyshKeRhv5A==",
+          "version": "5.0.1",
+          "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.0.1.tgz",
+          "integrity": "sha512-FYDTSHb/7KXsWICVsxdmiExPjCfRC4qRFBdVwv7Ax9hMnvMmEjP9RfxTEZ3qPZGmADDn2vAKSo9UcN1jKVYscg==",
           "dev": true
         },
         "dom-serializer": {
-          "version": "1.3.1",
-          "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.1.tgz",
-          "integrity": "sha512-Pv2ZluG5ife96udGgEDovOOOA5UELkltfJpnIExPrAk1LTvecolUGn6lIaoLh86d83GiB86CjzciMd9BuRB71Q==",
+          "version": "1.3.2",
+          "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz",
+          "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==",
           "dev": true,
           "requires": {
             "domelementtype": "^2.0.1",
-            "domhandler": "^4.0.0",
+            "domhandler": "^4.2.0",
             "entities": "^2.0.0"
           }
         },
@@ -15847,9 +15956,9 @@
           }
         },
         "domutils": {
-          "version": "2.6.0",
-          "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.6.0.tgz",
-          "integrity": "sha512-y0BezHuy4MDYxh6OvolXYsH+1EMGmFbwv5FKW7ovwMG6zTPWqNPq3WF9ayZssFq+UlKdffGLbOEaghNdaOm1WA==",
+          "version": "2.7.0",
+          "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.7.0.tgz",
+          "integrity": "sha512-8eaHa17IwJUPAiB+SoTYBo5mCdeMgdcAoXJ59m6DT1vw+5iLS3gNoqYaRowaBKtGVrOF1Jz4yDTgYKLK2kvfJg==",
           "dev": true,
           "requires": {
             "dom-serializer": "^1.0.1",
@@ -16978,6 +17087,24 @@
         }
       }
     },
+    "vue-pdf": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/vue-pdf/-/vue-pdf-4.3.0.tgz",
+      "integrity": "sha512-zd3lJj6CbtrawgaaDDciTDjkJMUKiLWtbEmBg5CvFn9Noe9oAO/GNy/fc5c59qGuFCJ14ibIV1baw4S07e5bSQ==",
+      "requires": {
+        "babel-plugin-syntax-dynamic-import": "^6.18.0",
+        "loader-utils": "^1.4.0",
+        "pdfjs-dist": "2.6.347",
+        "raw-loader": "^4.0.2",
+        "vue-resize-sensor": "^2.0.0",
+        "worker-loader": "^2.0.0"
+      }
+    },
+    "vue-resize-sensor": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/vue-resize-sensor/-/vue-resize-sensor-2.0.0.tgz",
+      "integrity": "sha512-W+y2EAI/BxS4Vlcca9scQv8ifeBFck56DRtSwWJ2H4Cw1GLNUYxiZxUHHkuzuI5JPW/cYtL1bPO5xPyEXx4LmQ=="
+    },
     "vue-router": {
       "version": "3.5.1",
       "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.5.1.tgz",
@@ -17284,9 +17411,9 @@
           "dev": true
         },
         "ws": {
-          "version": "6.2.1",
-          "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz",
-          "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==",
+          "version": "6.2.2",
+          "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz",
+          "integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==",
           "dev": true,
           "requires": {
             "async-limiter": "~1.0.0"
@@ -17511,9 +17638,9 @@
           }
         },
         "ws": {
-          "version": "6.2.1",
-          "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz",
-          "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==",
+          "version": "6.2.2",
+          "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz",
+          "integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==",
           "dev": true,
           "requires": {
             "async-limiter": "~1.0.0"
@@ -17836,6 +17963,26 @@
         "errno": "~0.1.7"
       }
     },
+    "worker-loader": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/worker-loader/-/worker-loader-2.0.0.tgz",
+      "integrity": "sha512-tnvNp4K3KQOpfRnD20m8xltE3eWh89Ye+5oj7wXEEHKac1P4oZ6p9oTj8/8ExqoSBnk9nu5Pr4nKfQ1hn2APJw==",
+      "requires": {
+        "loader-utils": "^1.0.0",
+        "schema-utils": "^0.4.0"
+      },
+      "dependencies": {
+        "schema-utils": {
+          "version": "0.4.7",
+          "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.7.tgz",
+          "integrity": "sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ==",
+          "requires": {
+            "ajv": "^6.1.0",
+            "ajv-keywords": "^3.1.0"
+          }
+        }
+      }
+    },
     "wrap-ansi": {
       "version": "5.1.0",
       "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
@@ -17892,6 +18039,12 @@
         "signal-exit": "^3.0.2"
       }
     },
+    "ws": {
+      "version": "7.5.1",
+      "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.1.tgz",
+      "integrity": "sha512-2c6faOUH/nhoQN6abwMloF7Iyl0ZS2E9HGtsiLrWn0zOOMWlhtDmdf/uihDt6jnuCxgtwGBNy6Onsoy2s2O2Ow==",
+      "dev": true
+    },
     "xml-name-validator": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz",

+ 2 - 1
package.json

@@ -20,6 +20,7 @@
     "nprogress": "^0.2.0",
     "vue": "^2.6.12",
     "vue-i18n": "^8.24.0",
+    "vue-pdf": "^4.3.0",
     "vue-router": "^3.5.1",
     "vuex": "^3.6.2",
     "wmjh-ui": "file:../wmjh-ui-0.1.0.tgz"
@@ -55,7 +56,7 @@
     "stylelint-scss": "^3.19.0",
     "stylelint-webpack-plugin": "^2.1.1",
     "svg-sprite-loader": "^6.0.5",
-    "svgo": "^2.3.0",
+    "svgo": "^2.3.1",
     "vue-loader": "^15.9.6",
     "vue-template-compiler": "^2.6.12"
   },

+ 16 - 0
src/api/app.js

@@ -45,6 +45,7 @@ export function fileUpload(SecurityLevel, file) {
   return request({
     method: 'post',
     url: '/GCLSFileServer/WebFileUpload',
+    timeout: 0,
     params,
     headers: {
       'Content-Type': 'multipart/form-data'
@@ -52,3 +53,18 @@ export function fileUpload(SecurityLevel, file) {
     data: formData
   });
 }
+
+/**
+ * 得到文件存储信息
+ * @param {Object} data { file_id 文件ID }
+ */
+export function GetFileStoreInfo(data) {
+  let params = getRequestParams('file_store_manager-GetFileStoreInfo');
+
+  return request({
+    method: 'post',
+    url: process.env.VUE_APP_FileServer,
+    params,
+    data
+  });
+}

+ 60 - 0
src/api/course.js

@@ -107,6 +107,36 @@ export function GetCSItemInfoBox(data) {
 }
 
 /**
+ * 得到课节
+ * @param {Object} data { id 课节ID }
+ */
+export function GetCSItem(data) {
+  let params = getRequestParams('teaching-cs_item_manager-GetCSItem');
+
+  return request({
+    method: 'post',
+    url: process.env.VUE_APP_LearnWebSI,
+    params,
+    data
+  });
+}
+
+/**
+ * 修改课节
+ * @param {Object} data
+ */
+export function UpdateCSItem(data) {
+  let params = getRequestParams('teaching-cs_item_manager-UpdateCSItem');
+
+  return request({
+    method: 'post',
+    url: process.env.VUE_APP_LearnWebSI,
+    params,
+    data
+  });
+}
+
+/**
  * 删除课节
  * @param {Object} data id 课次ID
  */
@@ -196,3 +226,33 @@ export function GetCoursewareContent_View(data) {
     data
   });
 }
+
+/**
+ * 得到任务信息
+ * @param {Object} data { id 任务 ID }
+ */
+export function GetTaskInfo(data) {
+  let params = getRequestParams('teaching-task_manager-GetTaskInfo');
+
+  return request({
+    method: 'post',
+    url: process.env.VUE_APP_LearnWebSI,
+    params,
+    data
+  });
+}
+
+/**
+ * 修改任务
+ * @param {Object} data
+ */
+export function UpdateTask(data) {
+  let params = getRequestParams('teaching-task_manager-UpdateTask');
+
+  return request({
+    method: 'post',
+    url: process.env.VUE_APP_LearnWebSI,
+    params,
+    data
+  });
+}

+ 46 - 0
src/api/live.js

@@ -16,6 +16,21 @@ export function CreateEnterLiveRoomSession(data) {
 }
 
 /**
+ * 关闭直播
+ * @param { Object } data { task_id 任务ID }
+ */
+export function CloseLiveRoom(data) {
+  let params = getRequestParams('live_room-live_room_dispatch-CloseLiveRoom');
+
+  return request({
+    method: 'post',
+    url: process.env.VUE_APP_LearnWebSI,
+    params,
+    data
+  });
+}
+
+/**
  * 得到直播间学员列表
  * @param {Object} data { task_id 任务ID }
  */
@@ -89,3 +104,34 @@ export function GetCurMaterialSent(data) {
     data
   });
 }
+
+/**
+ * 完成推送给我的资料
+ * @param { Object } data
+ * @returns
+ */
+export function FinishMyMaterial(data) {
+  let params = getRequestParams('live_room-live_room_dispatch-FinishMyMaterial');
+
+  return request({
+    method: 'post',
+    url: process.env.VUE_APP_LearnWebSI,
+    params,
+    data
+  });
+}
+
+/**
+ * 得到直播间信息
+ * @param {Object} data { task_id 任务ID }
+ */
+export function GetLiveRoomInfo(data) {
+  let params = getRequestParams('live_room-live_room_dispatch-GetLiveRoomInfo');
+
+  return request({
+    method: 'post',
+    url: process.env.VUE_APP_LearnWebSI,
+    params,
+    data
+  });
+}

+ 1 - 1
src/api/table.js

@@ -5,7 +5,7 @@ import { request, getRequestParams } from '@/utils/request';
  * @param {Object} data { date_stamp } 格式化后的时间 yyy-mm-dd
  */
 export function GetMyDayTaskList(data) {
-  let params = getRequestParams('teaching-task_manager-GetMyDayTaskList');
+  let params = getRequestParams('cominfo_query-task_query-GetMyDayTaskList');
 
   return request({
     method: 'post',

+ 103 - 3
src/components/live/CurMaterial.vue

@@ -6,20 +6,54 @@
     title="当前推送课件"
     @close="dialogMaterialClose"
   >
-    {{ materialName }}
-    <!-- <question :context="context" /> -->
+    <template v-if="materialType === 'COURSEWARE'">
+      <question :context="context" />
+    </template>
+    <template v-else>
+      <template v-if="fileType === 'pdf'">
+        <pdf v-for="i in numPages" :key="i" :src="pdfSrc" :page="i"></pdf>
+      </template>
+
+      <template v-else-if="isImage(fileType)">
+        <el-image fit="contain" :src="file_url_https" />
+      </template>
+
+      <template v-if="fileType !== 'pdf'">
+        <iframe
+          :src="'https://view.officeapps.live.com/op/view.aspx?src=' + `${file_url_https}`"
+          width="100%"
+          height="490px"
+          scrolling="no"
+        >
+        </iframe>
+      </template>
+    </template>
+
+    <div slot="footer">
+      <el-button type="primary" @click="finishMyMaterial">完成</el-button>
+    </div>
   </el-dialog>
 </template>
 
 <script>
+import pdf from 'vue-pdf';
 import { GetCoursewareContent_View } from '@/api/course';
+import { GetFileStoreInfo } from '@/api/app';
+import { FinishMyMaterial } from '@/api/live';
 
 export default {
+  components: {
+    pdf
+  },
   props: {
     dialogVisibleMaterial: {
       default: false,
       type: Boolean
     },
+    taskId: {
+      default: '',
+      type: String
+    },
     materialId: {
       default: '',
       type: String
@@ -39,13 +73,35 @@ export default {
   },
   data() {
     return {
-      context: null
+      context: null,
+      file_relative_path: '',
+      file_url_https: '',
+      pdfSrc: '',
+      numPages: 1
     };
   },
+  computed: {
+    fileType() {
+      return this.file_url_https.slice(
+        this.file_url_https.lastIndexOf('.') + 1,
+        this.file_url_https.length
+      );
+    }
+  },
+  watch: {
+    materialId() {
+      if (this.materialType === 'COURSEWARE') {
+        this.getCoursewareContent_View();
+      } else {
+        this.getFileStoreInfo();
+      }
+    }
+  },
   methods: {
     dialogMaterialClose() {
       this.$emit('dialogMaterialClose');
     },
+
     getCoursewareContent_View() {
       GetCoursewareContent_View({ id: this.materialId }).then(res => {
         if (res.content) {
@@ -59,6 +115,50 @@ export default {
           this.context = null;
         }
       });
+    },
+
+    getFileStoreInfo() {
+      GetFileStoreInfo({ file_id: this.materialId }).then(
+        ({ file_relative_path, file_url_https }) => {
+          this.file_relative_path = file_relative_path;
+          this.file_url_https = file_url_https;
+          let fileType = file_url_https.slice(
+            file_url_https.lastIndexOf('.') + 1,
+            file_url_https.length
+          );
+          if (fileType === 'pdf') {
+            this.getNumPages(file_url_https);
+          }
+        }
+      );
+    },
+
+    getNumPages(url) {
+      let loadingTask = pdf.createLoadingTask(url);
+      loadingTask.promise
+        .then(pdf => {
+          this.pdfSrc = loadingTask;
+          this.numPages = pdf.numPages;
+        })
+        .catch(err => {
+          console.error('pdf加载失败', err);
+          this.$message.error('pdf加载失败');
+        });
+    },
+
+    finishMyMaterial() {
+      FinishMyMaterial({
+        task_id: this.taskId,
+        material_id: this.materialId,
+        material_type: this.materialType
+      }).then(() => {
+        this.$message.success('完成推送资料成功');
+        this.$emit('dialogMaterialClose');
+      });
+    },
+
+    isImage(type) {
+      return ['jpeg', 'gif', 'jpg', 'png', 'bmp', 'pic', 'svg'].includes(type);
     }
   }
 };

+ 2 - 0
src/components/live/SelectMaterial.vue

@@ -19,6 +19,8 @@
           </div>
         </div>
       </div>
+
+      <div slot="footer"></div>
     </el-dialog>
   </div>
 </template>

+ 5 - 0
src/icons/svg/voice.svg

@@ -0,0 +1,5 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M23.5384 0.692383H1.38452V22.8462H23.5384V0.692383Z" fill="white" fill-opacity="0.01"/>
+<path d="M23.5384 0.692383H1.38452V22.8462H23.5384V0.692383Z" fill="white" fill-opacity="0.01"/>
+<path d="M8.01962 4.75098C8.35492 4.75098 8.66388 4.93285 8.82666 5.22602L9.95577 7.25993C10.1036 7.52624 10.1106 7.84835 9.97433 8.12079L8.88657 10.2963C8.88657 10.2963 9.2018 11.917 10.5211 13.2363C11.8404 14.5555 13.4556 14.8653 13.4556 14.8653L15.6308 13.7777C15.9034 13.6414 16.2257 13.6485 16.4921 13.7966L18.5318 14.9306C18.8247 15.0934 19.0064 15.4022 19.0064 15.7373V18.0789C19.0064 19.2714 17.8987 20.1327 16.7688 19.7514C14.4482 18.9684 10.8461 17.4776 8.56294 15.1944C6.27976 12.9112 4.78889 9.30907 4.00589 6.9885C3.62464 5.85861 4.48592 4.75098 5.67837 4.75098H8.01962Z" stroke="white" stroke-width="1.38462" stroke-linejoin="round"/>
+</svg>

+ 5 - 4
src/styles/mixin.scss

@@ -55,14 +55,15 @@
 
 @mixin dialog {
   .el-dialog {
+    &__title {
+      font-weight: 700;
+    }
+
     &__body {
       padding: 15px 20px 0;
       height: 55vh;
       color: $color;
-    }
-
-    &__title {
-      font-weight: 700;
+      overflow: auto;
     }
   }
 }

+ 1 - 1
src/utils/validate.js

@@ -1,6 +1,6 @@
 /**
  * @description 是否外链
- * @param {string} path
+ * @param {String} path
  * @returns {Boolean}
  */
 export function isExternal(path) {

+ 104 - 2
src/views/live/CompleteList.vue

@@ -6,14 +6,44 @@
     title="答题统计"
     @close="dialogCompleteClose"
   >
-    {{ material_name }}
+    <template v-if="material_type === 'COURSEWARE'">
+      <question :context="context" />
+    </template>
+    <template v-else>
+      <!-- pdf -->
+      <template v-if="fileType === 'pdf'">
+        <pdf v-for="i in numPages" :key="i" :src="pdfSrc" :page="i"></pdf>
+      </template>
+
+      <template v-else-if="isImage(fileType)">
+        <el-image fit="contain" :src="file_url_https" />
+      </template>
+
+      <template v-else-if="fileType !== 'pdf'">
+        <iframe
+          :src="'https://view.officeapps.live.com/op/view.aspx?src=' + `${file_url_https}`"
+          width="100%"
+          height="490px"
+          scrolling="no"
+        >
+        </iframe>
+      </template>
+    </template>
+
+    <div slot="footer"></div>
   </el-dialog>
 </template>
 
 <script>
+import pdf from 'vue-pdf';
 import { GetCurMaterialSent } from '@/api/live';
+import { GetCoursewareContent_View } from '@/api/course';
+import { GetFileStoreInfo } from '@/api/app';
 
 export default {
+  components: {
+    pdf
+  },
   props: {
     dialogVisibleComplete: {
       default: false,
@@ -29,14 +59,34 @@ export default {
       material_id: '',
       material_name: '',
       material_type: '',
-      material_picture_url: ''
+      material_picture_url: '',
+      context: null,
+      file_relative_path: '',
+      file_url_https: '',
+      pdfSrc: '',
+      numPages: 1
     };
   },
+  computed: {
+    fileType() {
+      return this.file_url_https.slice(
+        this.file_url_https.lastIndexOf('.') + 1,
+        this.file_url_https.length
+      );
+    }
+  },
   watch: {
     dialogVisibleComplete(newVal) {
       if (newVal) {
         this.getCurMaterialSent();
       }
+    },
+    material_id() {
+      if (this.material_type === 'COURSEWARE') {
+        this.getCoursewareContent_View();
+      } else {
+        this.getFileStoreInfo();
+      }
     }
   },
   methods: {
@@ -53,8 +103,55 @@ export default {
       );
     },
 
+    getCoursewareContent_View() {
+      GetCoursewareContent_View({ id: this.material_id }).then(res => {
+        if (res.content) {
+          this.context = {
+            id: this.currentCourse,
+            ui_type: JSON.parse(res.content).question.ui_type,
+            sort_number: 1,
+            content: JSON.parse(res.content)
+          };
+        } else {
+          this.context = null;
+        }
+      });
+    },
+
+    getFileStoreInfo() {
+      GetFileStoreInfo({ file_id: this.material_id }).then(
+        ({ file_relative_path, file_url_https }) => {
+          this.file_relative_path = file_relative_path;
+          this.file_url_https = file_url_https;
+          let fileType = file_url_https.slice(
+            file_url_https.lastIndexOf('.') + 1,
+            file_url_https.length
+          );
+          if (fileType === 'pdf') {
+            this.getNumPages(file_url_https);
+          }
+        }
+      );
+    },
+
+    getNumPages(url) {
+      let loadingTask = pdf.createLoadingTask(url);
+      loadingTask.promise
+        .then(pdf => {
+          this.pdfSrc = loadingTask;
+          this.numPages = pdf.numPages;
+        })
+        .catch(err => {
+          console.error('pdf加载失败', err);
+        });
+    },
+
     dialogCompleteClose() {
       this.$emit('dialogCompleteClose');
+    },
+
+    isImage(type) {
+      return ['jpeg', 'gif', 'jpg', 'png', 'bmp', 'pic', 'svg'].includes(type);
     }
   }
 };
@@ -65,5 +162,10 @@ export default {
 
 .complete-list {
   @include dialog;
+
+  .el-image {
+    width: 100%;
+    height: calc(100% - 4px);
+  }
 }
 </style>

+ 82 - 37
src/views/live/index.vue

@@ -9,15 +9,17 @@
           <span class="live-name">{{ roomData.name }}</span>
         </div>
         <div>
-          <el-button v-if="userType === 'TEACHER'" @click="startLive">开启直播</el-button>
-          <el-button v-if="userType === 'TEACHER'" @click="stopLive">结束直播</el-button>
-          <el-button v-if="userType === 'TEACHER'" @click="publishStream">推流</el-button>
+          <template v-if="userType === 'TEACHER'">
+            <el-button v-if="!liveStat" @click="startLive">开启直播</el-button>
+            <el-button v-if="liveStat" @click="closeLiveRoom">结束直播</el-button>
+            <el-button @click="publishStream">推流</el-button>
+          </template>
         </div>
       </div>
     </div>
     <!-- 主容器 -->
     <div class="live-container">
-      <!--左侧-->
+      <!-- 左侧 -->
       <div class="live-container-left">
         <div v-show="connection" id="student"></div>
         <div v-show="!connection" id="draw-parent">
@@ -41,22 +43,27 @@
         </div>
         <div class="button-group">
           <div class="button-group-left">
-            <span v-if="userType === 'TEACHER'" title="屏幕共享" @click="publishShareStream">
-              <svg-icon icon-class="share" />
-            </span>
-            <span v-if="userType === 'TEACHER'" title="白板" @click="showDrawSetting">
-              <svg-icon icon-class="draw" />
-            </span>
-            <span v-if="userType === 'TEACHER'" title="课件推送" @click="dialogVisible = true">
-              <svg-icon icon-class="push" />
-            </span>
+            <template v-if="userType === 'TEACHER'">
+              <span title="屏幕共享" @click="publishShareStream">
+                <svg-icon icon-class="share" />
+              </span>
+              <span title="白板" @click="showDrawSetting">
+                <svg-icon icon-class="draw" />
+              </span>
+              <span title="课件推送" @click="dialogVisible = true">
+                <svg-icon icon-class="push" />
+              </span>
+            </template>
           </div>
           <div class="button-group-right"></div>
         </div>
         <div class="live-container-left-chat">
           <div class="chat-top">
             <span>聊天</span>
-            <a @click="chatBans">禁言</a>
+            <label v-if="userType === 'TEACHER'" @click="chatBans">
+              <input v-model="roomData.allow_chat" type="checkbox" class="allow-chat" />
+              <span>禁言</span>
+            </label>
           </div>
           <div class="chat-window">
             <ul class="chat-window-ul">
@@ -78,7 +85,7 @@
           </div>
         </div>
       </div>
-      <!--右侧-->
+      <!-- 右侧 -->
       <div class="live-container-right">
         <div class="live-teacher-lens">
           <div id="live"></div>
@@ -91,14 +98,11 @@
                 <span class="name">{{ item.student_name }}</span>
               </div>
               <div class="student-list-right">
-                <svg-icon
-                  v-if="userType === 'TEACHER'"
-                  icon-class="video"
-                  @click="invite(item.room_user_id)"
-                />
-                <span v-if="userType === 'TEACHER'" @click="handsDown(item.room_user_id)">
-                  下麦
-                </span>
+                <template v-if="userType === 'TEACHER'">
+                  <svg-icon icon-class="video" @click="invite(item.room_user_id, 1)" />
+                  <svg-icon icon-class="voice" @click="invite(item.room_user_id, 2)" />
+                  <span @click="handsDown(item.room_user_id)"> 下麦 </span>
+                </template>
               </div>
             </li>
           </ul>
@@ -115,6 +119,7 @@
       @dialogPush="dialogPush"
     />
 
+    <!-- 教师查看当前完成列表 -->
     <complete-list
       v-if="userType === 'TEACHER'"
       :task-id="task_id"
@@ -122,8 +127,10 @@
       @dialogCompleteClose="dialogCompleteClose"
     />
 
+    <!-- 学员当前推送资料 -->
     <cur-material
       v-if="userType === 'STUDENT'"
+      :task-id="task_id"
       :dialog-visible-material="dialogVisibleMaterial"
       :material-id="material_id"
       :material-name="material_name"
@@ -135,7 +142,13 @@
 </template>
 
 <script>
-import { GetLiveRoomStudentList, StudentExitLiveRoom, GetCurMaterialSent } from '@/api/live';
+import {
+  GetLiveRoomStudentList,
+  StudentExitLiveRoom,
+  GetCurMaterialSent,
+  CloseLiveRoom,
+  GetLiveRoomInfo
+} from '@/api/live';
 import SelectMaterial from '@/components/live/SelectMaterial.vue';
 import CurMaterial from '@/components/live/CurMaterial.vue';
 import CompleteList from './CompleteList.vue';
@@ -187,7 +200,8 @@ export default {
       drawColorList: ['#FF4747', '#343434', '#628EFF', '#FFCA0E'],
       drawThicknessList: ['1', '3', '5'],
       // 直播间学员列表
-      student_list: []
+      student_list: [],
+      liveStat: false
     };
   },
   watch: {
@@ -292,10 +306,14 @@ export default {
       });
       const that = this;
       common.initListener(that); // 注册监听事件
+      this.getLiveStat();
     },
 
-    stopLive() {
-      common.stopLive();
+    closeLiveRoom() {
+      CloseLiveRoom({ task_id: this.task_id }).then(() => {
+        this.$message.success('关闭直播成功');
+        this.$router.push('/');
+      });
     },
 
     startLive() {
@@ -305,9 +323,10 @@ export default {
     getLiveStat() {
       common.getLiveStat({
         success: data => {
-          console.log('直播开启状态', data);
+          this.liveStat = data.started;
         },
         fail: str => {
+          this.liveStat = false;
           console.log('直播关闭状态或查询直播失败', str);
         }
       });
@@ -324,8 +343,24 @@ export default {
     },
 
     // 老师邀请学生上麦
-    invite(uid) {
-      common.invite(uid);
+    invite(uid, mode) {
+      GetLiveRoomInfo({ task_id: this.task_id }).then(({ video_mode }) => {
+        if (video_mode === mode) {
+          common.invite(uid);
+        } else {
+          common.roomUpdate({
+            video_mode: mode,
+            roomUpdateSuccess: function (data) {
+              console.log(data, '连麦音视频模式更新请求成功!');
+              common.invite(uid);
+            },
+            roomUpdateFailed: function (data) {
+              console.log(data, '连麦音视频模式更新请求失败! 请稍后再试!');
+              this.$message.error('连麦音视频模式更新请求失败! 请稍后再试!');
+            }
+          });
+        }
+      });
     },
 
     // 下麦
@@ -341,7 +376,7 @@ export default {
 
     chatBans() {
       common.roomUpdate({
-        allow_chat: false,
+        allow_chat: this.roomData.allow_chat,
         roomUpdateSuccess: function (data) {
           console.log(data, '房间模板配置更新请求成功!');
         },
@@ -396,8 +431,8 @@ export default {
 
     getCurMaterialSent() {
       const timer = setInterval(() => {
-        GetCurMaterialSent({ task_id: this.task_id }).then(
-          ({ material_id, material_name, material_type, material_picture_url }) => {
+        GetCurMaterialSent({ task_id: this.task_id })
+          .then(({ material_id, material_name, material_type, material_picture_url }) => {
             if (material_id !== undefined && material_id.length > 0) {
               this.dialogVisibleMaterial = true;
               this.material_id = material_id;
@@ -406,8 +441,10 @@ export default {
               this.material_picture_url = material_picture_url;
               clearInterval(timer);
             }
-          }
-        );
+          })
+          .catch(() => {
+            clearInterval(timer);
+          });
       }, 2000);
     }
   }
@@ -588,6 +625,14 @@ $live-bc: #3d3938;
           padding: 15px 15px 10px;
           border-bottom: 1px solid #e6e6e6;
           color: #959595;
+
+          label {
+            cursor: pointer;
+          }
+
+          .allow-chat {
+            margin-right: 12px;
+          }
         }
 
         .chat-window {
@@ -641,7 +686,7 @@ $live-bc: #3d3938;
           margin-bottom: 16px;
 
           .student-list-left {
-            flex: 8;
+            flex: 7;
 
             .name {
               vertical-align: super;
@@ -650,7 +695,7 @@ $live-bc: #3d3938;
           }
 
           .student-list-right {
-            flex: 2;
+            flex: 3;
 
             .svg-icon {
               font-size: 18px;

+ 42 - 39
src/views/live/live.js

@@ -1,5 +1,6 @@
 import { Message } from 'element-ui';
 import store from '@/store';
+import { GetLiveRoomInfo } from '@/api/live';
 
 /**
  * @description WebSDK 实例化对象
@@ -165,12 +166,15 @@ export function initListener(vue) {
     if (store.state.user.user_type === 'TEACHER') {
       createLocalStream();
     }
-    // createLocalStream();
+  });
+
+  rtc.on('conference_join_failed', err => {
+    // 加入房间失败  err为错误原因
+    console.log('加入房间失败', err);
   });
 
   // 新增订阅流事件
   rtc.on('allow_sub', function (stream) {
-    console.log('stream', stream);
     if (stream.isMixed()) {
       console.log('是混合流,不订阅');
     } else {
@@ -180,8 +184,8 @@ export function initListener(vue) {
         success: function (stream) {
           // 订阅流成功
           let streamType = stream.streamType();
-          console.log('订阅流成功', stream.id()); // 获取流id
-          stream.show(streamType === 0 ? 'live' : 'student', 'contain'); // 将流显示到id为 live 的盒子中
+          console.log('订阅流成功', streamType);
+          stream.show(store.state.user.user_type === 'STUDENT' ? 'live' : 'student', 'contain'); // 将流显示到id为 live 的盒子中
           if (streamType === 10 || streamType === 1) {
             vue.connection = true;
           }
@@ -193,11 +197,6 @@ export function initListener(vue) {
     }
   });
 
-  rtc.on('conference_join_failed', err => {
-    // 加入房间失败  err为错误原因
-    console.log('加入房间失败', err);
-  });
-
   // 直播未开始,不能推流
   rtc.on('not_live', function () {
     console.log('直播未开始,不能推流');
@@ -225,10 +224,12 @@ export function initListener(vue) {
 
   rtc.on('publish_stream', str => {
     console.log('直播已开启', str);
+    vue.liveStat = true;
   });
 
   rtc.on('end_stream', str => {
     console.log('直播已关闭', str);
+    vue.liveStat = false;
   });
 
   rtc.on('switch_user_settings', settingData => {
@@ -256,6 +257,12 @@ export function initListener(vue) {
     console.log('视频无法自动播放', data);
   });
 
+  // 用户退出房间通知其他人员事件
+  rtc.on('exit_room_user', function (data) {
+    console.log('用户退出房间通知其他人员事件', data);
+    vue.studentExitLiveRoom(data.id);
+  });
+
   // 监听通知移除流事件
   rtc.on('stream_removed', function (stream) {
     console.log('监听通知移除流事件');
@@ -264,12 +271,6 @@ export function initListener(vue) {
     }
   });
 
-  // 用户退出房间通知其他人员事件
-  rtc.on('exit_room_user', function (data) {
-    console.log('用户退出房间通知其他人员事件', data);
-    vue.studentExitLiveRoom(data.id);
-  });
-
   // 停止订阅流
   rtc.on('unSub', function (stream) {
     console.log('停止订阅流');
@@ -303,35 +304,37 @@ export function initListener(vue) {
   });
 
   rtc.on('mcDown', () => {
-    closeVideo('picture');
+    closeVideo('main');
     vue.connection = false;
   });
 
   rtc.on('createLocalStream', () => {
     // 创建本地流推流
-    console.log('创建本地流推流');
-    const createData = {
-      video: true,
-      audio: true
-    };
-    rtc.createLocalStream({
-      streamName: 'picture',
-      createData,
-      success: function (stream) {
-        vue.connection = true;
-        console.log('创建本地流成功', stream);
-        // 创建本地流成功,将流展示到id为 live 的dom元素盒子中
-        stream.show('student');
-        publishStream('picture'); // 如果需要立即推流,执行 publish 方法
-      },
-      fail: function (data) {
-        console.log('创建本地流失败,应用层处理', data);
-        // 创建本地流失败,应用层处理
-        Message({
-          type: 'error',
-          message: '创建本地流失败:' + data
-        });
-      }
+    GetLiveRoomInfo({ task_id: vue.task_id }).then(({ video_mode }) => {
+      console.log('创建本地流推流');
+      const createData = {
+        video: video_mode === 1,
+        audio: true
+      };
+      rtc.createLocalStream({
+        streamName: 'main',
+        createData,
+        success: function (stream) {
+          vue.connection = true;
+          console.log('创建本地流成功', stream);
+          // 创建本地流成功,将流展示到id为 student 的dom元素盒子中
+          stream.show('student');
+          publishStream('main'); // 如果需要立即推流,执行 publish 方法
+        },
+        fail: function (data) {
+          console.log('创建本地流失败,应用层处理', data);
+          // 创建本地流失败,应用层处理
+          Message({
+            type: 'error',
+            message: '创建本地流失败:' + data
+          });
+        }
+      });
     });
   });
 

+ 0 - 1
src/views/login/index.vue

@@ -31,7 +31,6 @@
           name="password"
           :placeholder="$t('password')"
           autocomplete="on"
-          @keyup.enter.native="handleLogin"
         />
       </el-form-item>
 

+ 153 - 0
src/views/teacher/create_course/step_table/AddItem.vue

@@ -0,0 +1,153 @@
+<template>
+  <el-dialog
+    v-loading="loading"
+    class="add-item"
+    :visible.sync="dialogVisible"
+    title="课节信息"
+    width="525px"
+    top="25vh"
+    :close-on-click-modal="false"
+    :show-close="false"
+    @close="dialogClose"
+  >
+    <el-form
+      ref="itemForm"
+      :model="itemForm"
+      :rules="itemRules"
+      label-width="90px"
+      label-position="left"
+    >
+      <el-form-item label="课节名称" prop="name">
+        <el-input v-model="itemForm.name" class="item-name" />
+      </el-form-item>
+      <el-form-item label="课节周期" prop="date">
+        <el-date-picker
+          v-model="itemForm.date"
+          type="datetimerange"
+          range-separator="~"
+          value-format="yyyy-MM-dd HH:mm:ss"
+          unlink-panels
+        />
+      </el-form-item>
+    </el-form>
+
+    <div slot="footer">
+      <el-button class="cancel" @click="dialogClose">取消</el-button>
+      <el-button type="primary" @click="addCSItem">确定</el-button>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import { AddCSItemToCourse, GetCSItem, UpdateCSItem } from '@/api/course';
+
+export default {
+  props: {
+    dialogVisible: {
+      default: false,
+      type: Boolean
+    },
+    courseId: {
+      default: '',
+      type: String
+    },
+    id: {
+      default: '',
+      type: String
+    },
+    type: {
+      default: 'add',
+      type: String
+    }
+  },
+  data() {
+    return {
+      loading: false,
+      itemForm: {
+        name: '',
+        date: []
+      },
+      itemRules: {
+        name: { required: true, message: '课节名称不能为空', trigger: 'blur' },
+        date: { required: true, message: '课节周期不能为空', trigger: 'blur' }
+      }
+    };
+  },
+  watch: {
+    type(newVal) {
+      if (newVal === 'edit') {
+        this.getCSItem();
+      } else {
+        this.itemForm = { name: '', date: [] };
+      }
+    }
+  },
+  methods: {
+    addCSItem() {
+      this.$refs.itemForm.validate(valid => {
+        if (!valid) return false;
+
+        let data = {
+          name: this.itemForm.name,
+          begin_time: this.itemForm.date[0],
+          end_time: this.itemForm.date[1]
+        };
+        this.loading = true;
+
+        if (this.type === 'add') {
+          data.course_id = this.courseId;
+          AddCSItemToCourse(data)
+            .then(() => {
+              this.loading = false;
+              this.$emit('dialogConfirm', this.type);
+            })
+            .catch(() => {
+              this.loading = false;
+            });
+        }
+
+        if (this.type === 'edit') {
+          data.id = this.id;
+          UpdateCSItem(data)
+            .then(() => {
+              this.loading = false;
+              this.$emit('dialogConfirm', this.type);
+            })
+            .catch(() => {
+              this.loading = false;
+            });
+        }
+      });
+    },
+
+    getCSItem() {
+      GetCSItem({ id: this.id }).then(({ begin_time, end_time, name }) => {
+        this.itemForm.name = name;
+        this.itemForm.date = [begin_time, end_time];
+      });
+    },
+
+    dialogClose() {
+      this.$emit('dialogClose');
+    }
+  }
+};
+</script>
+
+<style lang="scss">
+@import '~@/styles/mixin.scss';
+
+.add-item {
+  @include dialog;
+
+  .el-dialog {
+    &__body {
+      height: 100%;
+    }
+
+    .item-name {
+      width: 400px;
+    }
+  }
+}
+</style>

+ 131 - 108
src/views/teacher/create_course/step_table/CreateTask.vue

@@ -1,22 +1,22 @@
 <template>
   <div class="task">
     <step-bar :step-number="2" />
-    <!--课程基本信息-->
+    <!-- 课程基本信息 -->
     <div class="task-course-info">
-      <div class="cover"><el-image fit="fill" :src="picture_url" alt="封面" /></div>
+      <div class="cover"><el-image fit="contain" :src="picture_url" alt="封面" /></div>
       <div class="info">
         <div class="name">{{ name }}</div>
         <div class="date">{{ begin_date }}<span>-</span>{{ end_date }}</div>
       </div>
     </div>
-    <!--按钮-->
+    <!-- 按钮 -->
     <div class="task-button">
       <el-button class="prev-step" @click="preStep"><i class="el-icon-back" />选择教材</el-button>
       <el-button><router-link to="/create_course">关闭</router-link></el-button>
     </div>
-    <!--任务课节-->
+    <!-- 任务课节 -->
     <div class="task-item">
-      <!--课节列表-->
+      <!-- 课节列表 -->
       <div class="task-item-list">
         <template v-if="cs_item_list.length > 0">
           <div
@@ -26,10 +26,14 @@
             @click="curItemID = item.id"
           >
             <span>{{ item.name }}</span>
-            <el-dropdown placement="bottom" trigger="click" @command="deleteCSItem">
+            <!-- 课节下拉框 -->
+            <el-dropdown placement="bottom" trigger="click" @command="handleCSItem">
               <i class="el-icon-more"></i>
               <el-dropdown-menu slot="dropdown">
-                <el-dropdown-item class="delete-menu" :command="item.id">
+                <el-dropdown-item class="dropdown-menu" :command="{ id: item.id, type: 'edit' }">
+                  <span>编辑</span><svg-icon icon-class="edit" />
+                </el-dropdown-item>
+                <el-dropdown-item class="dropdown-menu" :command="{ id: item.id, type: 'delete ' }">
                   <span>删除</span><svg-icon icon-class="delete" />
                 </el-dropdown-item>
               </el-dropdown-menu>
@@ -41,7 +45,7 @@
           <svg-icon icon-class="create-white" /> 创建新课节
         </el-button>
       </div>
-      <!--课节信息-->
+      <!-- 课节信息 -->
       <div class="task-item-container">
         <div class="item-info">
           <div class="title">课节信息</div>
@@ -67,7 +71,7 @@
             <span>课节任务</span>
           </div>
           <div class="item-task-pre task-container">
-            <!--课前任务-->
+            <!-- 课前任务 -->
             <div class="item-task-pre-title">
               <span class="number-tag pre">{{ itemInfoBox.pre_task_list.length }}</span>
               <span>课前任务</span>
@@ -81,6 +85,18 @@
                         <div class="name">{{ i + 1 }}. {{ item.name }}</div>
                         <div class="info">
                           {{ item.time_space_view_txt }}
+                          <!-- 任务下拉框 -->
+                          <el-dropdown placement="bottom" @command="handleTask">
+                            <i class="el-icon-more"></i>
+                            <el-dropdown-menu slot="dropdown">
+                              <el-dropdown-item
+                                class="dropdown-menu"
+                                :command="{ id: item.id, type: 'edit', time_type: 0 }"
+                              >
+                                <span>编辑</span><svg-icon icon-class="edit" />
+                              </el-dropdown-item>
+                            </el-dropdown-menu>
+                          </el-dropdown>
                         </div>
                       </div>
                     </template>
@@ -119,7 +135,7 @@
               <el-button @click="newTask(0)"><i class="el-icon-plus" /> 新建任务</el-button>
             </div>
           </div>
-          <!--课中任务-->
+          <!-- 课中任务 -->
           <div class="item-task-mid task-container">
             <div class="item-task-mid-title">
               <span class="number-tag mid">{{ itemInfoBox.mid_task_list.length }}</span>
@@ -136,6 +152,17 @@
                         </div>
                         <div class="info">
                           {{ item.time_space_view_txt }}
+                          <el-dropdown placement="bottom" @command="handleTask">
+                            <i class="el-icon-more"></i>
+                            <el-dropdown-menu slot="dropdown">
+                              <el-dropdown-item
+                                class="dropdown-menu"
+                                :command="{ id: item.id, type: 'edit', time_type: 1 }"
+                              >
+                                <span>编辑</span><svg-icon icon-class="edit" />
+                              </el-dropdown-item>
+                            </el-dropdown-menu>
+                          </el-dropdown>
                         </div>
                       </div>
                     </template>
@@ -174,7 +201,7 @@
               <el-button @click="newTask(1)"><i class="el-icon-plus" /> 新建任务</el-button>
             </div>
           </div>
-          <!--课后任务-->
+          <!-- 课后任务 -->
           <div class="item-task-after task-container">
             <div class="item-task-after-title">
               <span class="number-tag after">{{ itemInfoBox.after_task_list.length }}</span>
@@ -196,6 +223,17 @@
                         </div>
                         <div class="info">
                           {{ item.time_space_view_txt }}
+                          <el-dropdown placement="bottom" @command="handleTask">
+                            <i class="el-icon-more"></i>
+                            <el-dropdown-menu slot="dropdown">
+                              <el-dropdown-item
+                                class="dropdown-menu"
+                                :command="{ id: item.id, type: 'edit', time_type: 2 }"
+                              >
+                                <span>编辑</span><svg-icon icon-class="edit" />
+                              </el-dropdown-item>
+                            </el-dropdown-menu>
+                          </el-dropdown>
                         </div>
                       </div>
                     </template>
@@ -244,57 +282,29 @@
       </div>
     </div>
 
-    <!--添加课节弹出页-->
-    <el-dialog
-      v-loading="loading"
-      :visible.sync="dialogVisible"
-      title="课节信息"
-      width="525px"
-      top="25vh"
-      :close-on-click-modal="false"
-      :show-close="false"
-    >
-      <el-form
-        ref="itemForm"
-        :model="itemForm"
-        :rules="itemRules"
-        label-width="90px"
-        label-position="left"
-      >
-        <el-form-item label="课节名称" prop="name">
-          <el-input v-model="itemForm.name" class="item-name" />
-        </el-form-item>
-        <el-form-item label="课节周期" prop="date">
-          <el-date-picker
-            v-model="itemForm.date"
-            type="datetimerange"
-            range-separator="~"
-            value-format="yyyy-MM-dd HH:mm:ss"
-            unlink-panels
-          />
-        </el-form-item>
-        <el-form-item>
-          <el-button class="cancel" @click="dialogVisible = false">取消</el-button>
-          <el-button type="primary" @click="addCSItem">确定</el-button>
-        </el-form-item>
-      </el-form>
-    </el-dialog>
+    <!-- 课节弹出页 -->
+    <add-item
+      :id="itemId"
+      :course-id="id"
+      :type="type"
+      :dialog-visible="dialogVisible"
+      @dialogClose="dialogClose"
+      @dialogConfirm="dialogConfirm"
+    />
   </div>
 </template>
 
 <script>
 import StepBar from '@/components/StepBar';
-import {
-  GetCourseInfo_ContainCSItem,
-  AddCSItemToCourse,
-  GetCSItemInfoBox,
-  DeleteCSItem
-} from '@/api/course';
+import AddItem from './AddItem.vue';
+
+import { GetCourseInfo_ContainCSItem, GetCSItemInfoBox, DeleteCSItem } from '@/api/course';
 
 export default {
   name: 'CreateTask',
   components: {
-    StepBar
+    StepBar,
+    AddItem
   },
   data() {
     return {
@@ -306,14 +316,8 @@ export default {
       cs_item_list: [],
       curItemID: '',
       dialogVisible: false,
-      itemForm: {
-        name: '',
-        date: []
-      },
-      itemRules: {
-        name: { required: true, message: '课节名称不能为空', trigger: 'blur' },
-        date: { required: true, message: '课节周期不能为空', trigger: 'blur' }
-      },
+      type: 'add',
+      itemId: '',
       itemInfoBox: {
         name: '',
         date: [],
@@ -321,8 +325,7 @@ export default {
         mid_task_list: [],
         after_task_list: [],
         learning_material_list: []
-      },
-      loading: false
+      }
     };
   },
   computed: {
@@ -357,35 +360,48 @@ export default {
         }
       );
     },
+
     preStep() {
       this.$router.push({ path: `/create_course_step_table/select_book/${this.id}` });
     },
-    addCSItem() {
-      this.$refs.itemForm.validate(valid => {
-        if (valid) {
-          let data = {
-            course_id: this.id,
-            name: this.itemForm.name,
-            begin_time: this.itemForm.date[0],
-            end_time: this.itemForm.date[1]
-          };
-          this.loading = true;
-          AddCSItemToCourse(data)
-            .then(() => {
-              this.dialogVisible = false;
-              this.loading = false;
-              this.getCourseInfo();
-              // 重置itemForm
-              this.itemForm = { name: '', date: [] };
-            })
-            .catch(() => {
-              this.loading = false;
-            });
-        } else {
-          return false;
-        }
-      });
+
+    // 课节处理
+    handleCSItem({ id, type }) {
+      if (type === 'delete') {
+        this.$confirm('您确定要删除该课节吗?', '提示', {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          type: 'warning'
+        }).then(() => {
+          DeleteCSItem({ id }).then(() => {
+            this.$message.success('删除课节成功!');
+            this.getCourseInfo();
+          });
+        });
+      }
+
+      if (type === 'edit') {
+        this.dialogVisible = true;
+        this.itemId = id;
+        this.type = 'edit';
+      }
     },
+
+    dialogConfirm(type) {
+      this.dialogVisible = false;
+      this.type = 'add';
+      if (type === 'add') {
+        this.getCourseInfo();
+      } else {
+        this.getCSItemInfoBox();
+      }
+    },
+
+    dialogClose() {
+      this.dialogVisible = false;
+      this.type = 'add';
+    },
+
     getCSItemInfoBox() {
       GetCSItemInfoBox({ id: this.curItemID }).then(
         ({ name, begin_time, end_time, pre_task_list, mid_task_list, after_task_list }) => {
@@ -397,22 +413,27 @@ export default {
         }
       );
     },
-    deleteCSItem(id) {
-      this.$confirm('您确定要删除该课节吗?', '提示', {
-        confirmButtonText: '确定',
-        cancelButtonText: '取消',
-        type: 'warning'
-      }).then(() => {
-        DeleteCSItem({ id }).then(() => {
-          this.$message.success('删除课节成功!');
-          this.getCourseInfo();
-        });
-      });
-    },
+
+    // 任务处理
     newTask(time_type) {
+      if (!this.curItemID) {
+        this.$message.warning('请先创建新课节');
+        return;
+      }
       this.$router.push({
         path: `/create_course_step_table/new_task/${time_type}/${this.id}/${this.curItemID}`
       });
+    },
+
+    handleTask({ id, type, time_type }) {
+      if (type === 'edit') {
+        this.$router.push({
+          path: `/create_course_step_table/new_task/${time_type}/${this.id}/${this.curItemID}`,
+          query: {
+            task_id: id
+          }
+        });
+      }
     }
   }
 };
@@ -587,7 +608,7 @@ export default {
               .card-title {
                 display: flex;
                 justify-content: space-between;
-                width: calc(100% - 36px);
+                width: 100%;
 
                 .name {
                   font-weight: 600;
@@ -595,6 +616,10 @@ export default {
 
                 .info {
                   color: #929292;
+
+                  .el-dropdown {
+                    margin-left: 16px;
+                  }
                 }
               }
             }
@@ -643,6 +668,10 @@ export default {
                 background-color: #f9f9f9;
                 border-bottom-width: 0;
 
+                .el-collapse-item__arrow {
+                  display: none;
+                }
+
                 &.focusing:focus:not(:hover) {
                   color: #000;
                 }
@@ -702,18 +731,12 @@ export default {
       }
     }
   }
-
-  .el-dialog {
-    .item-name {
-      width: 400px;
-    }
-  }
 }
 
 .el-dropdown-menu {
   padding: 1px;
 
-  .delete-menu {
+  .dropdown-menu {
     width: 128px;
     display: flex;
     justify-content: space-between;

+ 101 - 37
src/views/teacher/create_course/step_table/NewTask.vue

@@ -1,7 +1,9 @@
 <template>
   <div class="new-task">
     <div class="go-back">
-      <el-button @click="goBack"><svg-icon icon-class="go-back" /> 返回</el-button>
+      <el-button @click="goBack">
+        <div class="go-back-button"><svg-icon icon-class="go-back" /><span>返回</span></div>
+      </el-button>
     </div>
     <div class="new-task-container">
       <div class="title">新任务</div>
@@ -63,12 +65,12 @@
                 <div>
                   <el-tag
                     v-for="(item, i) in liveForm.coursewareInfo"
-                    :key="item.id"
+                    :key="item.courseware_id"
                     color="#fff"
                     closable
                     @close="closeCourse(i, 'live')"
                   >
-                    {{ item.name }}
+                    {{ item.courseware_name }}
                   </el-tag>
                 </div>
               </el-form-item>
@@ -95,17 +97,17 @@
               </el-form-item>
 
               <el-form-item label="可见性">
-                <el-radio v-model="liveForm.courseware_visible_mode" :label="true">
+                <el-radio v-model="liveForm.courseware_visible_mode" :label="21">
                   手动推送
                 </el-radio>
-                <el-radio v-model="liveForm.courseware_visible_mode" :label="false">
+                <el-radio v-model="liveForm.courseware_visible_mode" :label="22">
                   一直可见
                 </el-radio>
               </el-form-item>
 
               <el-form-item label="直播录制">
-                <el-radio v-model="liveForm.zhibo_record_mode" label="auto">自动开启</el-radio>
-                <el-radio v-model="liveForm.zhibo_record_mode" label="manual">手动开启</el-radio>
+                <el-radio v-model="liveForm.zhibo_record_mode" :label="31">自动开启</el-radio>
+                <el-radio v-model="liveForm.zhibo_record_mode" :label="32">手动开启</el-radio>
               </el-form-item>
             </el-form>
           </div>
@@ -119,12 +121,12 @@
                 <div>
                   <el-tag
                     v-for="(item, i) in courseForm.coursewareInfo"
-                    :key="item.id"
+                    :key="item.courseware_id"
                     color="#fff"
                     closable
                     @close="closeCourse(i, 'course')"
                   >
-                    {{ item.name }}
+                    {{ item.courseware_name }}
                   </el-tag>
                 </div>
               </el-form-item>
@@ -201,7 +203,12 @@
 <script>
 import SelectCourse from '@/components/select/SelectCourse.vue';
 import { GetTaskTeachingTypeList, GetTaskModeList, GetTeacherListByCourseID } from '@/api/select';
-import { AddTaskToCSItem, GetTreeNodeInfo_BookChapterStruct } from '@/api/course';
+import {
+  AddTaskToCSItem,
+  GetTreeNodeInfo_BookChapterStruct,
+  GetTaskInfo,
+  UpdateTask
+} from '@/api/course';
 import { fileUpload } from '@/api/app';
 
 export default {
@@ -210,6 +217,7 @@ export default {
   data() {
     return {
       id: this.$route.params.id,
+      task_id: this.$route.query.task_id,
       time_type: this.$route.params.time_type,
       cs_item_id: this.$route.params.cs_item_id,
       dialogVisible: false,
@@ -230,8 +238,8 @@ export default {
       liveForm: {
         coursewareInfo: [],
         file_info_list: [],
-        courseware_visible_mode: true,
-        zhibo_record_mode: 'auto'
+        courseware_visible_mode: 21,
+        zhibo_record_mode: 31
       },
       courseForm: {
         coursewareInfo: [],
@@ -246,16 +254,24 @@ export default {
     };
   },
   created() {
-    this.getTaskTeachingTypeList();
-    this.getTeacherListByCourseID();
-    this.getTaskModeList();
+    this.getPageNeedPage();
+    if (this.task_id) {
+      this.getTaskInfo();
+    }
   },
   methods: {
-    getTaskTeachingTypeList() {
+    getPageNeedPage() {
       GetTaskTeachingTypeList().then(({ type_list }) => {
         this.type_list = type_list;
       });
+      GetTeacherListByCourseID({ course_id: this.id }).then(({ teacher_list }) => {
+        this.teacher_list = teacher_list;
+      });
+      GetTaskModeList().then(({ mode_list }) => {
+        this.mode_list = mode_list;
+      });
     },
+
     addTaskToCSItem() {
       this.$refs.newTaskForm.validate(valid => {
         if (valid) {
@@ -275,7 +291,7 @@ export default {
           if (teaching_type === 10) {
             let courseware_id_list = [];
             this.liveForm.coursewareInfo.forEach(item => {
-              courseware_id_list.push(item.id);
+              courseware_id_list.push(item.courseware_id);
             });
             data['courseware_id_list'] = courseware_id_list;
             let file_info_list = [];
@@ -290,7 +306,7 @@ export default {
           if (teaching_type === 11) {
             let courseware_id_list = [];
             this.courseForm.coursewareInfo.forEach(item => {
-              courseware_id_list.push(item.id);
+              courseware_id_list.push(item.courseware_id);
             });
             data['courseware_id_list'] = courseware_id_list;
             data['task_mode'] = this.courseForm.task_mode;
@@ -306,30 +322,26 @@ export default {
             data['is_enable_homework'] = this.basicForm.is_enable_homework;
             data['is_enable_message'] = this.basicForm.is_enable_message;
           }
-
-          AddTaskToCSItem(data).then(({ status }) => {
-            if (status === 1) {
+          if (this.task_id) {
+            data['id'] = this.task_id;
+            UpdateTask(data).then(() => {
+              this.goBack();
+            });
+          } else {
+            AddTaskToCSItem(data).then(() => {
               this.goBack();
-            }
-          });
+            });
+          }
         } else {
           return false;
         }
       });
     },
-    getTaskModeList() {
-      GetTaskModeList().then(({ mode_list }) => {
-        this.mode_list = mode_list;
-      });
-    },
-    getTeacherListByCourseID() {
-      GetTeacherListByCourseID({ course_id: this.id }).then(({ teacher_list }) => {
-        this.teacher_list = teacher_list;
-      });
-    },
+
     goBack() {
       this.$router.push({ path: `/create_course_step_table/create_task/${this.id}` });
     },
+
     upload(file) {
       let type = this.form.teaching_type;
       fileUpload('Open', file).then(({ file_info_list }) => {
@@ -343,13 +355,16 @@ export default {
         }
       });
     },
+
     closeFile(i, arr) {
       arr.splice(i, 1);
     },
+
     // 选择课件
     dialogClose() {
       this.dialogVisible = false;
     },
+
     selectCourse(course_id) {
       let type = this.form.teaching_type;
       if (type === 10) {
@@ -361,20 +376,67 @@ export default {
       }
       this.dialogVisible = false;
     },
+
     getTreeNodeInfo_BookChapterStruct(id, type) {
       GetTreeNodeInfo_BookChapterStruct({ id }).then(({ name, id }) => {
         if (type === 'live') {
-          this.liveForm.coursewareInfo.push({ id, name });
+          this.liveForm.coursewareInfo.push({ courseware_id: id, courseware_name: name });
         }
         if (type === 'course') {
-          this.courseForm.coursewareInfo.push({ id, name });
+          this.courseForm.coursewareInfo.push({ courseware_id: id, courseware_name: name });
         }
       });
     },
+
     closeCourse(i, type) {
       let courseInfo =
         type === 'live' ? this.liveForm.coursewareInfo : this.courseForm.coursewareInfo;
       courseInfo.splice(i, 1);
+    },
+
+    getTaskInfo() {
+      GetTaskInfo({ id: this.task_id }).then(
+        ({
+          begin_time,
+          end_time,
+          time_type,
+          teaching_type,
+          name,
+          teacher_id,
+          content,
+          courseware_list,
+          accessory_list,
+          task_mode,
+          is_enable_homework,
+          is_enable_message,
+          courseware_visible_mode,
+          zhibo_record_mode
+        }) => {
+          this.form.date = [begin_time, end_time];
+          this.time_type = time_type;
+          this.form.teaching_type = teaching_type;
+          this.form.name = name;
+          this.form.teacher_id = teacher_id;
+          this.form.content = content;
+          if (teaching_type === 10) {
+            this.liveForm.coursewareInfo = courseware_list;
+            this.liveForm.file_info_list = accessory_list;
+            this.liveForm.courseware_visible_mode = courseware_visible_mode;
+            this.liveForm.zhibo_record_mode = zhibo_record_mode;
+          }
+
+          if (teaching_type === 11) {
+            this.courseForm.coursewareInfo = courseware_list;
+            this.courseForm.task_mode = task_mode;
+          }
+
+          if (teaching_type === 12) {
+            this.basicForm.file_info_list = accessory_list;
+            this.basicForm.is_enable_homework = is_enable_homework === 'true';
+            this.basicForm.is_enable_message = is_enable_message === 'true';
+          }
+        }
+      );
     }
   }
 };
@@ -389,8 +451,10 @@ export default {
   .go-back {
     margin-bottom: 16px;
 
-    .el-button {
-      width: 120px;
+    &-button {
+      width: 78px;
+      display: flex;
+      justify-content: space-between;
     }
   }
 

+ 1 - 1
src/views/teacher/create_course/step_table/SelectBook.vue

@@ -26,7 +26,7 @@
                 :class="['book-list-item-img', { selected: item.is_selected === 'true' }]"
                 @click="addOrRemoveBookToCourse($event, item.id)"
               >
-                <el-image :src="item.picture_url" />
+                <el-image fit="contain" :src="item.picture_url" />
               </div>
               <div class="book-list-item-name">{{ item.name }}</div>
             </div>