diff --git a/package-lock.json b/package-lock.json
index 09515f5..a62610d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1111,7 +1111,6 @@
"version": "7.16.3",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.16.3.tgz",
"integrity": "sha512-WBwekcqacdY2e9AF/Q7WLFUWmdJGJTkbjqTjoMDgXkVZ3ZRUvOPsLb5KdwISoQVsbP+DQzVZW4Zhci0DvpbNTQ==",
- "dev": true,
"requires": {
"regenerator-runtime": "^0.13.4"
}
@@ -1425,6 +1424,12 @@
"integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==",
"dev": true
},
+ "@types/raf": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/@types/raf/-/raf-3.4.0.tgz",
+ "integrity": "sha512-taW5/WYqo36N7V39oYyHP9Ipfd5pNFvGTIQsNGj86xV88YQ7GnI30/yMfKDF7Zgin0m3e+ikX88FvImnK4RjGw==",
+ "optional": true
+ },
"@types/range-parser": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz",
@@ -2769,6 +2774,11 @@
}
}
},
+ "base64-arraybuffer": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz",
+ "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ=="
+ },
"base64-js": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
@@ -3053,6 +3063,11 @@
"picocolors": "^1.0.0"
}
},
+ "btoa": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/btoa/-/btoa-1.2.1.tgz",
+ "integrity": "sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g=="
+ },
"buffer": {
"version": "4.9.2",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz",
@@ -3158,7 +3173,6 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
"integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
- "dev": true,
"requires": {
"function-bind": "^1.1.1",
"get-intrinsic": "^1.0.2"
@@ -3246,6 +3260,22 @@
"integrity": "sha512-zaEMRH6xg8ESMi2eQ3R4eZ5qw/hJiVsO/HlLwniIwErij0JDr9P+8V4dtx1l+kLq6j3yy8l8W4fst1lBnat5wQ==",
"dev": true
},
+ "canvg": {
+ "version": "3.0.10",
+ "resolved": "https://registry.npmjs.org/canvg/-/canvg-3.0.10.tgz",
+ "integrity": "sha512-qwR2FRNO9NlzTeKIPIKpnTY6fqwuYSequ8Ru8c0YkYU7U0oW+hLUvWadLvAu1Rl72OMNiFhoLu4f8eUjQ7l/+Q==",
+ "optional": true,
+ "requires": {
+ "@babel/runtime": "^7.12.5",
+ "@types/raf": "^3.4.0",
+ "core-js": "^3.8.3",
+ "raf": "^3.4.1",
+ "regenerator-runtime": "^0.13.7",
+ "rgbcolor": "^1.0.1",
+ "stackblur-canvas": "^2.0.0",
+ "svg-pathdata": "^6.0.3"
+ }
+ },
"case-sensitive-paths-webpack-plugin": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz",
@@ -4101,6 +4131,14 @@
"timsort": "^0.3.0"
}
},
+ "css-line-break": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz",
+ "integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==",
+ "requires": {
+ "utrie": "^1.0.2"
+ }
+ },
"css-loader": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.6.0.tgz",
@@ -4399,7 +4437,6 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz",
"integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==",
- "dev": true,
"requires": {
"is-arguments": "^1.0.4",
"is-date-object": "^1.0.1",
@@ -4542,7 +4579,6 @@
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
"integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
- "dev": true,
"requires": {
"object-keys": "^1.0.12"
}
@@ -4785,6 +4821,12 @@
}
}
},
+ "dompurify": {
+ "version": "2.4.3",
+ "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.4.3.tgz",
+ "integrity": "sha512-q6QaLcakcRjebxjg8/+NP+h0rPfatOgOzc46Fst9VAA3jF2ApfKBNKMzdP4DYTqtUMXSCd5pRS/8Po/OmoCHZQ==",
+ "optional": true
+ },
"domutils": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz",
@@ -5359,6 +5401,11 @@
"integrity": "sha1-VFFFB3xQFJHjOxXsQIwpQ3bpSuQ=",
"dev": true
},
+ "fast-diff": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.1.2.tgz",
+ "integrity": "sha512-KaJUt+M9t1qaIteSvjc6P3RbMdXsNhK61GRftR6SNxqmhthcd9MGIi4T+o0jD8LUSpSnSKXE20nLtJ3fOHxQig=="
+ },
"fast-glob": {
"version": "2.2.7",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz",
@@ -5411,6 +5458,11 @@
"websocket-driver": ">=0.5.1"
}
},
+ "fflate": {
+ "version": "0.4.8",
+ "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.4.8.tgz",
+ "integrity": "sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA=="
+ },
"figgy-pudding": {
"version": "3.5.2",
"resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz",
@@ -5633,8 +5685,7 @@
"function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
- "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
- "dev": true
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
},
"gauge": {
"version": "2.7.4",
@@ -5714,7 +5765,6 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz",
"integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==",
- "dev": true,
"requires": {
"function-bind": "^1.1.1",
"has": "^1.0.3",
@@ -5901,7 +5951,6 @@
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
- "dev": true,
"requires": {
"function-bind": "^1.1.1"
}
@@ -5935,14 +5984,12 @@
"has-symbols": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz",
- "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==",
- "dev": true
+ "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw=="
},
"has-tostringtag": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
"integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
- "dev": true,
"requires": {
"has-symbols": "^1.0.2"
}
@@ -6188,6 +6235,15 @@
}
}
},
+ "html2canvas": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz",
+ "integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==",
+ "requires": {
+ "css-line-break": "^2.1.0",
+ "text-segmentation": "^1.0.3"
+ }
+ },
"htmlparser2": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz",
@@ -6559,7 +6615,6 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz",
"integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==",
- "dev": true,
"requires": {
"call-bind": "^1.0.2",
"has-tostringtag": "^1.0.0"
@@ -6659,7 +6714,6 @@
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz",
"integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
- "dev": true,
"requires": {
"has-tostringtag": "^1.0.0"
}
@@ -6812,7 +6866,6 @@
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
"integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
- "dev": true,
"requires": {
"call-bind": "^1.0.2",
"has-tostringtag": "^1.0.0"
@@ -7037,6 +7090,21 @@
"graceful-fs": "^4.1.6"
}
},
+ "jspdf": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/jspdf/-/jspdf-2.5.1.tgz",
+ "integrity": "sha512-hXObxz7ZqoyhxET78+XR34Xu2qFGrJJ2I2bE5w4SM8eFaFEkW2xcGRVUss360fYelwRSid/jT078kbNvmoW0QA==",
+ "requires": {
+ "@babel/runtime": "^7.14.0",
+ "atob": "^2.1.2",
+ "btoa": "^1.2.1",
+ "canvg": "^3.0.6",
+ "core-js": "^3.6.0",
+ "dompurify": "^2.2.0",
+ "fflate": "^0.4.8",
+ "html2canvas": "^1.0.0-rc.5"
+ }
+ },
"jsprim": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
@@ -8002,7 +8070,6 @@
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz",
"integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==",
- "dev": true,
"requires": {
"call-bind": "^1.0.2",
"define-properties": "^1.1.3"
@@ -8011,8 +8078,7 @@
"object-keys": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
- "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
- "dev": true
+ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="
},
"object-visit": {
"version": "1.0.1",
@@ -8261,6 +8327,11 @@
"no-case": "^2.2.0"
}
},
+ "parchment": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/parchment/-/parchment-1.1.4.tgz",
+ "integrity": "sha512-J5FBQt/pM2inLzg4hEWmzQx/8h8D0CiDxaG3vyp9rKrQRSDgBlhjdP5jQGgosEajXPSQouXGHOmVdgo7QmJuOg=="
+ },
"parse-asn1": {
"version": "5.1.6",
"resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz",
@@ -8401,8 +8472,7 @@
"performance-now": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
- "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=",
- "dev": true
+ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
},
"picocolors": {
"version": "1.0.0",
@@ -9477,6 +9547,50 @@
"integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==",
"dev": true
},
+ "quill": {
+ "version": "1.3.7",
+ "resolved": "https://registry.npmjs.org/quill/-/quill-1.3.7.tgz",
+ "integrity": "sha512-hG/DVzh/TiknWtE6QmWAF/pxoZKYxfe3J/d/+ShUWkDvvkZQVTPeVmUJVu1uE6DDooC4fWTiCLh84ul89oNz5g==",
+ "requires": {
+ "clone": "^2.1.1",
+ "deep-equal": "^1.0.1",
+ "eventemitter3": "^2.0.3",
+ "extend": "^3.0.2",
+ "parchment": "^1.1.4",
+ "quill-delta": "^3.6.2"
+ },
+ "dependencies": {
+ "clone": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
+ "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w=="
+ },
+ "eventemitter3": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-2.0.3.tgz",
+ "integrity": "sha512-jLN68Dx5kyFHaePoXWPsCGW5qdyZQtLYHkxkg02/Mz6g0kYpDx4FyP6XfArhQdlOC4b8Mv+EMxPo/8La7Tzghg=="
+ }
+ }
+ },
+ "quill-delta": {
+ "version": "3.6.3",
+ "resolved": "https://registry.npmjs.org/quill-delta/-/quill-delta-3.6.3.tgz",
+ "integrity": "sha512-wdIGBlcX13tCHOXGMVnnTVFtGRLoP0imqxM696fIPwIf5ODIYUHIvHbZcyvGlZFiFhK5XzDC2lpjbxRhnM05Tg==",
+ "requires": {
+ "deep-equal": "^1.0.1",
+ "extend": "^3.0.2",
+ "fast-diff": "1.1.2"
+ }
+ },
+ "raf": {
+ "version": "3.4.1",
+ "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz",
+ "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==",
+ "optional": true,
+ "requires": {
+ "performance-now": "^2.1.0"
+ }
+ },
"randombytes": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
@@ -9649,8 +9763,7 @@
"regenerator-runtime": {
"version": "0.13.9",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz",
- "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==",
- "dev": true
+ "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA=="
},
"regenerator-transform": {
"version": "0.14.5",
@@ -9675,7 +9788,6 @@
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz",
"integrity": "sha512-JiBdRBq91WlY7uRJ0ds7R+dU02i6LKi8r3BuQhNXn+kmeLN+EfHhfjqMRis1zJxnlu88hq/4dx0P2OP3APRTOA==",
- "dev": true,
"requires": {
"call-bind": "^1.0.2",
"define-properties": "^1.1.3"
@@ -9958,6 +10070,12 @@
"integrity": "sha1-QzdOLiyglosO8VI0YLfXMP8i7rM=",
"dev": true
},
+ "rgbcolor": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/rgbcolor/-/rgbcolor-1.0.1.tgz",
+ "integrity": "sha512-9aZLIrhRaD97sgVhtJOW6ckOEh6/GnvQtdVNfdZ6s67+3/XwLS9lBcQYzEEhYVeUowN7pRzMLsyGhK2i/xvWbw==",
+ "optional": true
+ },
"rimraf": {
"version": "2.7.1",
"resolved": "https://registry.npm.taobao.org/rimraf/download/rimraf-2.7.1.tgz",
@@ -10784,6 +10902,12 @@
"integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==",
"dev": true
},
+ "stackblur-canvas": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/stackblur-canvas/-/stackblur-canvas-2.5.0.tgz",
+ "integrity": "sha512-EeNzTVfj+1In7aSLPKDD03F/ly4RxEuF/EX0YcOG0cKoPXs+SLZxDawQbexQDBzwROs4VKLWTOaZQlZkGBFEIQ==",
+ "optional": true
+ },
"stackframe": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.2.0.tgz",
@@ -11006,6 +11130,12 @@
"has-flag": "^3.0.0"
}
},
+ "svg-pathdata": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/svg-pathdata/-/svg-pathdata-6.0.3.tgz",
+ "integrity": "sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw==",
+ "optional": true
+ },
"svg-tags": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz",
@@ -11135,6 +11265,14 @@
}
}
},
+ "text-segmentation": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz",
+ "integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==",
+ "requires": {
+ "utrie": "^1.0.2"
+ }
+ },
"thenify": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
@@ -11633,6 +11771,14 @@
"integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=",
"dev": true
},
+ "utrie": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz",
+ "integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==",
+ "requires": {
+ "base64-arraybuffer": "^1.0.2"
+ }
+ },
"uuid": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
diff --git a/package.json b/package.json
index de839a9..a304a6d 100644
--- a/package.json
+++ b/package.json
@@ -13,12 +13,15 @@
"core-js": "^3.19.3",
"element-ui": "^2.15.6",
"file-saver": "^2.0.5",
+ "html2canvas": "^1.4.1",
"jquery": "^3.6.0",
"js-cookie": "^3.0.1",
+ "jspdf": "^2.5.1",
"lib-flexible": "^0.3.2",
"postcss-px2rem": "^0.3.0",
"postcss-pxtorem": "^5.1.1",
"px2rem-loader": "^0.1.9",
+ "quill": "^1.3.7",
"vue": "^2.6.14",
"vue-codemirror": "^4.0.6",
"vue-draggable-resizable": "^2.3.0",
diff --git a/src/api/index.js b/src/api/index.js
index bc960fc..251d7f5 100644
--- a/src/api/index.js
+++ b/src/api/index.js
@@ -28,5 +28,8 @@ export default {
lookExcel: `occupationlab/occupationlab/python/file/data/lookExcel`,
lookOver: `occupationlab/occupationlab/python/file/data/lookOver`,
batchDeletion: `occupationlab/occupationlab/python/file/data/batchDeletion`,
- myData: `occupationlab/occupationlab/python/file/data/myData`
+ myData: `occupationlab/occupationlab/python/file/data/myData`,
+ updateReport: `occupationlab/occupationlab/achievement/updateReport`,
+ exportLabReport: `occupationlab/occupationlab/achievement/exportLabReport`,
+ reportDetail: `occupationlab/occupationlab/achievement/reportDetail`,
}
\ No newline at end of file
diff --git a/src/assets/images/point.png b/src/assets/images/point.png
new file mode 100644
index 0000000..6f6692f
Binary files /dev/null and b/src/assets/images/point.png differ
diff --git a/src/assets/images/report1.png b/src/assets/images/report1.png
new file mode 100644
index 0000000..5849896
Binary files /dev/null and b/src/assets/images/report1.png differ
diff --git a/src/assets/images/report2.png b/src/assets/images/report2.png
new file mode 100644
index 0000000..323c0dc
Binary files /dev/null and b/src/assets/images/report2.png differ
diff --git a/src/assets/images/report3.png b/src/assets/images/report3.png
new file mode 100644
index 0000000..51a142d
Binary files /dev/null and b/src/assets/images/report3.png differ
diff --git a/src/assets/images/report4.png b/src/assets/images/report4.png
new file mode 100644
index 0000000..196b2da
Binary files /dev/null and b/src/assets/images/report4.png differ
diff --git a/src/assets/images/report5.png b/src/assets/images/report5.png
new file mode 100644
index 0000000..f49ce2a
Binary files /dev/null and b/src/assets/images/report5.png differ
diff --git a/src/components/TestPanel.vue b/src/components/TestPanel.vue
index d1db4ad..f455d1a 100644
--- a/src/components/TestPanel.vue
+++ b/src/components/TestPanel.vue
@@ -35,13 +35,14 @@
{{seconds}}秒
-
+
+ 查看实验报告
重新开始
提交
@@ -71,25 +72,30 @@
-
-
-
-
-
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+ {{ competitionId ? '-' : scope.row.examScore }}
-
-
-
-
- {{ scope.row.examScore }}
-
-
+
+
@@ -145,6 +151,11 @@ export default {
courseId: Cookie.get('admin-courseId'),
projectId: Cookie.get('admin-projectId') ? Number(Cookie.get('admin-projectId')) : '',
assessmentId: Cookie.get('admin-assessmentId'),
+ competitionId: Cookie.get('admin-competitionId'),
+ stageId: Cookie.get('admin-stageId'),
+ teamId: Cookie.get('admin-teamId'),
+ resultsDetails: Cookie.get('admin-resultsDetails'),
+ resultAnnouncementTime: Cookie.get('admin-resultAnnouncementTime'),
curriculumName: Cookie.get('admin-curriculumName') ? unescape(Cookie.get('admin-curriculumName')) : 'python', // 课程名称
curSystemId: 1,
projectPermissions: 0, // 项目权限(0、练习 1、考核 2、竞赛)
@@ -171,11 +182,17 @@ export default {
taskList: [], // 实验任务列表
pannelTab: 'first', // 面板信息切换值
isSelected: false, // 是否选择过项目的标识,选择了会置为true
- statusTimer: null // 查询考核状态定时器
+ statusTimer: null, // 查询考核状态定时器
+ reportId: ''
};
},
mounted() {
- this.projectPermissions = this.assessmentId ? 1 : 0 // 1:考核,0:练习
+ // 2:竞赛,1:考核,0:练习
+ this.projectPermissions = this.assessmentId ?
+ 1 :
+ this.competitionId ?
+ 2 :
+ 0
if(this.assessmentId){ // 考核(考核才会从外面带进来assessmentId,练习是默认显示第一个项目)
this.getAssList()
}else{ // 练习
@@ -197,7 +214,7 @@ export default {
let data = {
systemId: this.systemId,
cId: this.courseId, // 课程id
- permissions: this.projectPermissions // 练习/考核
+ permissions: this.projectPermissions // 练习/考核/竞赛
}
return new Promise((resolve, reject) => {
this.$get(`${this.api.queryTestProject}`,data).then(res => {
@@ -259,9 +276,9 @@ export default {
this.experimentHint = project.experimentHint
this.hintOpen = !res.projectManage.hintOpen // 0显示,1不显示
this.$emit('tell', projectId, systemId, this.points)
- const isAss = this.projectPermissions == 1 // 是否是考核
- this.text = isAss ? '剩余' : '已用'
- this.countVal = isAss ? (new Date(this.endTime).getTime() - Date.now()) / 1000 : 0 // 如果是考核,取考核的结束时间减去当前时间去做倒计时,练习则直接给0做计时
+ const isPrac = this.projectPermissions == 0 // 是否是练习
+ this.text = isPrac ? '已用' : '剩余'
+ this.countVal = isPrac ? 0 : (new Date(this.endTime).getTime() - Date.now()) / 1000 // 如果是考核,取考核的结束时间减去当前时间去做倒计时,练习则直接给0做计时
this.startCount()
resolve()
}).catch(err => {
@@ -326,7 +343,7 @@ export default {
}
// 如果是没有代码的缓存,则只需要恢复项目,否则,就调接口查询缓存代码
if (cache && cache.empty && list.find(e => e.projectId === projectId) && !Cookie.get('admin-projectId')) {
- if (Cookie.get('admin-projectId')) {
+ if (Cookie.get('admin-projectId') && !this.competitionId) {
Cookie.remove('admin-projectId')
} else {
this.projectId = projectId
@@ -335,7 +352,7 @@ export default {
this.closeLoad()
localStorage.removeItem('codeCache')
} else {
- if (Cookie.get('admin-projectId')) {
+ if (Cookie.get('admin-projectId') && !this.competitionId) {
Cookie.remove('admin-projectId')
}
let newJudgmentId = '' // 要恢复到第一个有代码的判分规则,因为有代码的规则可能不是第一个,所以要判断如果这个为空,才把索引赋给该变量
@@ -438,6 +455,10 @@ export default {
this.$emit('recoveryCode') // 切换实训项目后回到第一个判分点
newmain.$emit('isSubmit', this.isSubmit) // 选择项目后把提交状态重置为未提交
},
+ // 查看实验报告
+ toReport() {
+ this.$router.push(`/report?reportId=${this.reportId}`)
+ },
//重新开始
reload() {
this.reloadCount()
@@ -520,14 +541,18 @@ export default {
totalScore: 100, // 判分点总分固定为100
systemId: this.curSystemId,
purpose: this.experimentTarget, // 实验目的
- attributesReqList
+ attributesReqList,
+ competitionId: this.competitionId,
+ stageId: this.stageId,
+ teamId: this.teamId,
}
- this.$post(this.api.submit, data).then(res => {
+
+ this.$post(this.api.submit, data).then(({ retInfo, reportId }) => {
localStorage.removeItem('codeCache')
this.isSubmit = true
newmain.$emit('isSubmit', this.isSubmit)
clearInterval(this.statusTimer)
- let list = res.retInfo
+ let list = retInfo
let taskList = this.taskList
let score = 0
// 给判分列表添加分数和运行结果
@@ -541,8 +566,16 @@ export default {
}
score += e.examScore // 计算总分
})
- this.grade = util.handleZero(score) // 前置加0
- this.editReport(res.reportId)
+ this.grade = util.handleZero(score) // 前置加0(竞赛不显示分数)
+ this.reportId = reportId
+ this.editReport(reportId)
+ // 如果是竞赛,并且勾选了公布成绩详情的选项,则弹框提示
+ this.competitionId && this.resultsDetails == 0 && this.$alert('提交成功,成绩将在' + this.resultAnnouncementTime + '小时后发布,请去参赛信息模块查看', '提示', {
+ confirmButtonText: '确定',
+ callback: action => {
+ this.$parent.back()
+ }
+ })
}).catch(err => {})
},
// 编辑实验报告
diff --git a/src/components/codemirror.vue b/src/components/codemirror.vue
index b7efade..e71db62 100644
--- a/src/components/codemirror.vue
+++ b/src/components/codemirror.vue
@@ -52,7 +52,7 @@
-
+
@@ -136,6 +136,7 @@ export default {
return {
token: Cookie.get('admin-token'),
assessmentId: Cookie.get('admin-assessmentId'), // 考核id
+ fromManager: Cookie.get('admin-fromManager'), // 是否是从教师端进入
courseId: Cookie.get('admin-courseId'), // 课程id
showTips: false, // 显示隐藏提示按钮
answer: '', // 正确答案
@@ -672,6 +673,9 @@ export default {
color:#fff;
}
/deep/.answer-wrap{
+ &.client {
+ // user-select: none;
+ }
pre{
width: 100%;
white-space: pre-wrap;
diff --git a/src/components/quill/index.vue b/src/components/quill/index.vue
new file mode 100644
index 0000000..b46b6d2
--- /dev/null
+++ b/src/components/quill/index.vue
@@ -0,0 +1,251 @@
+
+
+
+
+
+
diff --git a/src/components/quill/options.js b/src/components/quill/options.js
new file mode 100644
index 0000000..b368bcb
--- /dev/null
+++ b/src/components/quill/options.js
@@ -0,0 +1,16 @@
+export default [
+ ["bold", "italic", "underline", "strike"],
+ ["blockquote", "code-block"],
+ [{ "header": 1 }, { "header": 2 }],
+ [{ "list": "ordered" }, { "list": "bullet" }],
+ [{ "script": "sub" }, { "script": "super" }],
+ [{ "indent": "-1" }, { "indent": "+1" }],
+ [{ "direction": "rtl" }],
+ [{ "size": ["small", false, "large", "huge"] }],
+ [{ "header": [1, 2, 3, 4, 5, 6, false] }],
+ [{ "color": [] }, { "background": [] }],
+ [{ "font": [] }],
+ [{ "align": [] }],
+ ["clean"],
+ ["link", "image", "video"]
+];
\ No newline at end of file
diff --git a/src/router/index.js b/src/router/index.js
index 166344c..65be01e 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -23,7 +23,14 @@ const routes = [{
meta: {
title: 'excel预览'
},
- }
+ },
+ {
+ path: '/report',
+ component: resolve => require(['../views/Report'], resolve),
+ meta: {
+ title: '实验报告'
+ },
+ },
];
const router = new VueRouter({
diff --git a/src/util/index.js b/src/util/index.js
index c9c0aec..d28a1eb 100644
--- a/src/util/index.js
+++ b/src/util/index.js
@@ -68,6 +68,21 @@ export default {
}
x.send()
},
+ // 传入文件名和数据,下载文件
+ downloadFileDirect(fileName,data) {
+ if ('download' in document.createElement('a')) { // 非IE下载
+ const elink = document.createElement('a')
+ elink.download = fileName
+ elink.style.display = 'none'
+ elink.href = URL.createObjectURL(data)
+ document.body.appendChild(elink)
+ elink.click()
+ URL.revokeObjectURL(elink.href) // 释放URL 对象
+ document.body.removeChild(elink)
+ } else { // IE10+下载
+ navigator.msSaveBlob(data, fileName)
+ }
+ },
// 小于0前面加上0
handleZero (num) {
return num < 10 ? '0' + num : num
diff --git a/src/views/Home.vue b/src/views/Home.vue
index 16f16a0..96cc102 100644
--- a/src/views/Home.vue
+++ b/src/views/Home.vue
@@ -66,6 +66,7 @@ export default {
return {
loaded: false, // 页面是否加载完的标识,页面默认隐藏,一进来先显示加载条,接口加载完后再显示页面,不然一开始会一闪而过没有样式的页面
loadIns: null, // loading实例
+ competitionId: Cookie.get('admin-competitionId'),
fromManager: Cookie.get('admin-fromManager'), // 是否是从教师端进入
courseId: Cookie.get('admin-courseId'), // 课程id
curriculumName: Cookie.get('admin-curriculumName') ? unescape(Cookie.get('admin-curriculumName')) : 'python', // 课程名称
@@ -179,6 +180,9 @@ export default {
// 考核
if (this.assessmentId) {
href += `ass/list`
+ } else if (this.competitionId) {
+ // 竞赛
+ href += `match/list`
} else {
// 练习
href += `station/preview?courseId=${this.courseId}&curriculumName=${this.curriculumName}`
diff --git a/src/views/Report.vue b/src/views/Report.vue
new file mode 100644
index 0000000..b63622b
--- /dev/null
+++ b/src/views/Report.vue
@@ -0,0 +1,399 @@
+
+
+
+
+
+
+
+ {{ editing ? "保存" : "编辑" }}
+
+ 导出报告
+
+
标准实验报告
+
+
+
+ 基本信息
+
+
+ -
+
+
+ {{ infoData.userName }}
+
+ -
+
+
+ {{ infoData.workNumber }}
+
+ -
+
+
+ {{ infoData.submitTime }}
+
+ -
+
+
+
+
{{ infoData.score }}
+
+
+
+ -
+
+
+ {{ infoData.className }}
+
+ -
+
+
+ {{ infoData.instructor }}
+
+ -
+
+
+ {{ infoData.period }}
+
+
+
+
+
+ 实验项目名称
+
+
+
+
+
+
+
+ 实验目的
+
+
+
+
+
+
+
+ 实验数据
+
+
+
+
+ {{ scope.$index + 1 }}
+
+
+
+
+
+
+
+ {{index+1}}. {{item.name}}
+
+
+
+
+
+
+
+
+
+ {{index+1}}. {{item.ruleAnswer}}
+
+
+
+
+
+
+
+
+
+
+
+ {{index+1}}. {{item.userAnswer}}
+
+
+ {{index+1}}. 未填写
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 实验总结与体会
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file