提交 cbc763f3 authored 作者: 王鹏飞's avatar 王鹏飞

merge...

...@@ -4,7 +4,8 @@ module.exports = { ...@@ -4,7 +4,8 @@ module.exports = {
apiBaseURL: 'https://learn-api.ezijing.com', apiBaseURL: 'https://learn-api.ezijing.com',
others: { others: {
url: '/app/learn/course', url: '/app/learn/course',
loginUrl: 'https://login.ezijing.com/seg/login/index' loginUrl: 'https://login.ezijing.com/seg/login/index',
messageBaseURL: 'https://test-microservices-message-service-api.ezijing.com'
}, },
webpack: { webpack: {
externals: { externals: {
......
...@@ -5,7 +5,8 @@ module.exports = { ...@@ -5,7 +5,8 @@ module.exports = {
// apiBaseURL: '/', // apiBaseURL: '/',
others: { others: {
url: '/app/learn/course', url: '/app/learn/course',
loginUrl: 'https://login.ezijing.com/seg/login/index' loginUrl: 'https://login.ezijing.com/seg/login/index',
messageBaseURL: ''
}, },
webpack: { webpack: {
externals: { externals: {
......
...@@ -5,7 +5,8 @@ module.exports = { ...@@ -5,7 +5,8 @@ module.exports = {
// apiBaseURL: '/', // apiBaseURL: '/',
others: { others: {
url: '/app/learn/course', url: '/app/learn/course',
loginUrl: 'https://login2.ezijing.com/seg/login/index' loginUrl: 'https://login2.ezijing.com/seg/login/index',
messageBaseURL: 'https://test-microservices-message-service-api.ezijing.com'
}, },
isUploadStatic: false, isUploadStatic: false,
webpack: { webpack: {
......
...@@ -9,17 +9,21 @@ ...@@ -9,17 +9,21 @@
"version": "3.0.14", "version": "3.0.14",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@ckeditor/ckeditor5-build-classic": "^24.0.0", "@ckeditor/ckeditor5-build-classic": "^27.0.0",
"@ckeditor/ckeditor5-build-decoupled-document": "^27.0.0",
"@ckeditor/ckeditor5-vue2": "^1.0.5", "@ckeditor/ckeditor5-vue2": "^1.0.5",
"axios": "^0.21.0", "@ezijing/web-message-sdk": "^0.2.1",
"core-js": "^3.8.1", "axios": "^0.21.1",
"core-js": "^3.9.0",
"cross-env": "^7.0.3", "cross-env": "^7.0.3",
"element-ui": "^2.14.1", "echarts": "^5.0.2",
"element-ui": "^2.15.1",
"js-cookie": "^2.2.1", "js-cookie": "^2.2.1",
"lodash": "^4.17.20", "lodash": "^4.17.21",
"qrcode.vue": "^1.7.0", "qrcode.vue": "^1.7.0",
"qs": "^6.9.4", "qs": "^6.9.6",
"vue": "^2.6.12", "vue": "^2.6.12",
"vue-echarts": "^6.0.0-rc.3",
"vue-i18n": "^8.22.2", "vue-i18n": "^8.22.2",
"vue-loader": "^15.9.5", "vue-loader": "^15.9.5",
"vue-meta": "^2.4.0", "vue-meta": "^2.4.0",
...@@ -35,6 +39,7 @@ ...@@ -35,6 +39,7 @@
"@babel/plugin-transform-runtime": "^7.11.5", "@babel/plugin-transform-runtime": "^7.11.5",
"@babel/preset-env": "^7.11.5", "@babel/preset-env": "^7.11.5",
"@babel/runtime-corejs3": "^7.11.2", "@babel/runtime-corejs3": "^7.11.2",
"@vue/composition-api": "^1.0.0-rc.5",
"acorn": "^7.1.1", "acorn": "^7.1.1",
"ali-oss": "^6.11.2", "ali-oss": "^6.11.2",
"autoprefixer": "^9.8.6", "autoprefixer": "^9.8.6",
...@@ -1263,10 +1268,465 @@ ...@@ -1263,10 +1268,465 @@
"to-fast-properties": "^2.0.0" "to-fast-properties": "^2.0.0"
} }
}, },
"node_modules/@ckeditor/ckeditor5-adapter-ckfinder": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-adapter-ckfinder/-/ckeditor5-adapter-ckfinder-27.0.0.tgz",
"integrity": "sha512-2JzedLntHRw2ChQ54tB9pk1XFH4VzFPJLMJXhE3CP2+ANiIKZZTHodcQ7R2BOosIpySQOEppjfi1emZ6AgcLRg==",
"dependencies": {
"ckeditor5": "^27.0.0"
},
"engines": {
"node": ">=12.0.0",
"npm": ">=5.7.1"
}
},
"node_modules/@ckeditor/ckeditor5-alignment": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-alignment/-/ckeditor5-alignment-27.0.0.tgz",
"integrity": "sha512-MEXslAyeLmRwbRicOhIKmdvfreXkorwYEYMTDhJaOO3gll/mqDBbn0ijNsCOm4QgXUT6qqK2sOhxGRL3cDuMcQ==",
"dependencies": {
"ckeditor5": "^27.0.0"
},
"engines": {
"node": ">=12.0.0",
"npm": ">=5.7.1"
}
},
"node_modules/@ckeditor/ckeditor5-autoformat": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-autoformat/-/ckeditor5-autoformat-27.0.0.tgz",
"integrity": "sha512-SirBT1Reu2I9yXSLrcL4IZDecux0pNLfYdZVfz1PIXr99LOYvF1iqyWdo0dLEj5xEGf77OPoiIIhnOQJA8fZzA==",
"dependencies": {
"ckeditor5": "^27.0.0"
},
"engines": {
"node": ">=12.0.0",
"npm": ">=5.7.1"
}
},
"node_modules/@ckeditor/ckeditor5-basic-styles": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-basic-styles/-/ckeditor5-basic-styles-27.0.0.tgz",
"integrity": "sha512-idmD5huRKDFRe1ToyIj5RrnVde00fnEteyVnUWLZPYZr+Y2aye1KFWthmycqKIdNhCXy60ydnhXjy0tVuwHlmw==",
"dependencies": {
"ckeditor5": "^27.0.0"
},
"engines": {
"node": ">=12.0.0",
"npm": ">=5.7.1"
}
},
"node_modules/@ckeditor/ckeditor5-block-quote": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-block-quote/-/ckeditor5-block-quote-27.0.0.tgz",
"integrity": "sha512-sUSkhEnKDeAjB8EXvrt3zI+pYdnUg228t2Uoe6A0VCeaSynHn+YF9bHL8XSdEMaD1UdDcdRhtNhJL+d+cEdOqA==",
"dependencies": {
"ckeditor5": "^27.0.0"
},
"engines": {
"node": ">=12.0.0",
"npm": ">=5.7.1"
}
},
"node_modules/@ckeditor/ckeditor5-build-classic": { "node_modules/@ckeditor/ckeditor5-build-classic": {
"version": "24.0.0", "version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-build-classic/-/ckeditor5-build-classic-24.0.0.tgz", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-build-classic/-/ckeditor5-build-classic-27.0.0.tgz",
"integrity": "sha512-659ZAYbuQbPj3ElqrTSV7aqPtW4vt30Th0PiheFei7adIgmu1bFTHgcM3hqm7XGRzGmBRV6C07xSwUptxn3cvQ==", "integrity": "sha512-ghqgz/wyvyjN/NwYes7onnxo/N8rsutzTbSXJRdxxDxycH3DYUNMQsDj4ehf0ACp8RkpVDLekybxsyx3gSk3Ww==",
"dependencies": {
"@ckeditor/ckeditor5-adapter-ckfinder": "^27.0.0",
"@ckeditor/ckeditor5-autoformat": "^27.0.0",
"@ckeditor/ckeditor5-basic-styles": "^27.0.0",
"@ckeditor/ckeditor5-block-quote": "^27.0.0",
"@ckeditor/ckeditor5-ckfinder": "^27.0.0",
"@ckeditor/ckeditor5-cloud-services": "^27.0.0",
"@ckeditor/ckeditor5-easy-image": "^27.0.0",
"@ckeditor/ckeditor5-editor-classic": "^27.0.0",
"@ckeditor/ckeditor5-essentials": "^27.0.0",
"@ckeditor/ckeditor5-heading": "^27.0.0",
"@ckeditor/ckeditor5-image": "^27.0.0",
"@ckeditor/ckeditor5-indent": "^27.0.0",
"@ckeditor/ckeditor5-link": "^27.0.0",
"@ckeditor/ckeditor5-list": "^27.0.0",
"@ckeditor/ckeditor5-media-embed": "^27.0.0",
"@ckeditor/ckeditor5-paragraph": "^27.0.0",
"@ckeditor/ckeditor5-paste-from-office": "^27.0.0",
"@ckeditor/ckeditor5-table": "^27.0.0",
"@ckeditor/ckeditor5-typing": "^27.0.0"
},
"engines": {
"node": ">=12.0.0",
"npm": ">=5.7.1"
}
},
"node_modules/@ckeditor/ckeditor5-build-decoupled-document": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-build-decoupled-document/-/ckeditor5-build-decoupled-document-27.0.0.tgz",
"integrity": "sha512-2xVXA1eZ99kMwjfrcWtXYLXGSDObmyQOaXWuzYXWaBgGY5mYL4xJtaFP4Jn/IZYShFqu9Wc43nnh3EjnxegfHw==",
"dependencies": {
"@ckeditor/ckeditor5-adapter-ckfinder": "^27.0.0",
"@ckeditor/ckeditor5-alignment": "^27.0.0",
"@ckeditor/ckeditor5-autoformat": "^27.0.0",
"@ckeditor/ckeditor5-basic-styles": "^27.0.0",
"@ckeditor/ckeditor5-block-quote": "^27.0.0",
"@ckeditor/ckeditor5-ckfinder": "^27.0.0",
"@ckeditor/ckeditor5-cloud-services": "^27.0.0",
"@ckeditor/ckeditor5-easy-image": "^27.0.0",
"@ckeditor/ckeditor5-editor-decoupled": "^27.0.0",
"@ckeditor/ckeditor5-essentials": "^27.0.0",
"@ckeditor/ckeditor5-font": "^27.0.0",
"@ckeditor/ckeditor5-heading": "^27.0.0",
"@ckeditor/ckeditor5-image": "^27.0.0",
"@ckeditor/ckeditor5-indent": "^27.0.0",
"@ckeditor/ckeditor5-link": "^27.0.0",
"@ckeditor/ckeditor5-list": "^27.0.0",
"@ckeditor/ckeditor5-media-embed": "^27.0.0",
"@ckeditor/ckeditor5-paragraph": "^27.0.0",
"@ckeditor/ckeditor5-paste-from-office": "^27.0.0",
"@ckeditor/ckeditor5-table": "^27.0.0",
"@ckeditor/ckeditor5-typing": "^27.0.0"
},
"engines": {
"node": ">=12.0.0",
"npm": ">=5.7.1"
}
},
"node_modules/@ckeditor/ckeditor5-ckfinder": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-ckfinder/-/ckeditor5-ckfinder-27.0.0.tgz",
"integrity": "sha512-TyuMYTUv4eiy5dbaxChgn3kaptZWFlnTWOx3CIUPcpURt+h40HFRSANfmOPeKag4COXJaF/0MnmRe/QPJvaNbw==",
"dependencies": {
"ckeditor5": "^27.0.0"
},
"engines": {
"node": ">=12.0.0",
"npm": ">=5.7.1"
}
},
"node_modules/@ckeditor/ckeditor5-clipboard": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-clipboard/-/ckeditor5-clipboard-27.0.0.tgz",
"integrity": "sha512-oNLLjPWFoTIqdf6BOtKBDu0qUQiIia5TM6acxi5DKx5YdXnwg1GozxYa4x590EhUVIDFe6i0JuZbkALQ2tBI5g==",
"dependencies": {
"@ckeditor/ckeditor5-core": "^27.0.0",
"@ckeditor/ckeditor5-engine": "^27.0.0",
"@ckeditor/ckeditor5-utils": "^27.0.0",
"@ckeditor/ckeditor5-widget": "^27.0.0",
"lodash-es": "^4.17.11"
},
"engines": {
"node": ">=12.0.0",
"npm": ">=5.7.1"
}
},
"node_modules/@ckeditor/ckeditor5-cloud-services": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-cloud-services/-/ckeditor5-cloud-services-27.0.0.tgz",
"integrity": "sha512-IXc8rOAZoITNyl5c46M9/eVusKQYWXsFojxBvI9WlpxtxIRhXCge2grDyEg/rOeLBt8eJxJxIkuNDbwqMXcAKA==",
"dependencies": {
"ckeditor5": "^27.0.0"
},
"engines": {
"node": ">=12.0.0",
"npm": ">=5.7.1"
}
},
"node_modules/@ckeditor/ckeditor5-core": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-core/-/ckeditor5-core-27.0.0.tgz",
"integrity": "sha512-0dtV2eREe3mh1vqG8x4cIYCwFthzA5aOvRdaIQSj6T6JuBR9lO2IiniOpR0CAsiIgpAM9vmggah+Knngbe2gEA==",
"dependencies": {
"@ckeditor/ckeditor5-engine": "^27.0.0",
"@ckeditor/ckeditor5-ui": "^27.0.0",
"@ckeditor/ckeditor5-utils": "^27.0.0",
"lodash-es": "^4.17.15"
},
"engines": {
"node": ">=12.0.0",
"npm": ">=5.7.1"
}
},
"node_modules/@ckeditor/ckeditor5-easy-image": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-easy-image/-/ckeditor5-easy-image-27.0.0.tgz",
"integrity": "sha512-RqPJI5pkqaSgDcSCEm47eokteTgniLZFD4j/Y7F7v5tTvUoinn5LaKGv8DttquA4OPiF9kq2h3ZadqRGTpUuYQ==",
"dependencies": {
"ckeditor5": "^27.0.0"
},
"engines": {
"node": ">=12.0.0",
"npm": ">=5.7.1"
}
},
"node_modules/@ckeditor/ckeditor5-editor-classic": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-classic/-/ckeditor5-editor-classic-27.0.0.tgz",
"integrity": "sha512-guRK+sxFTpkh3XPTk38V9+6dQ784soOExCZW80G6TKlfBM8aJoWsuRiENgZ11eZ8f4OKlhVHuAH5ivoxCB7BOA==",
"dependencies": {
"ckeditor5": "^27.0.0",
"lodash-es": "^4.17.15"
},
"engines": {
"node": ">=12.0.0",
"npm": ">=5.7.1"
}
},
"node_modules/@ckeditor/ckeditor5-editor-decoupled": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-decoupled/-/ckeditor5-editor-decoupled-27.0.0.tgz",
"integrity": "sha512-aOa2zM64cSyJoigoHeWqAVFyqtrgUey4vaTU7uAvCW/JiIaJwFKyrRUIyrMLRE355AJH7Y7vNWUCmgV+mXMN1w==",
"dependencies": {
"ckeditor5": "^27.0.0",
"lodash-es": "^4.17.15"
},
"engines": {
"node": ">=12.0.0",
"npm": ">=5.7.1"
}
},
"node_modules/@ckeditor/ckeditor5-engine": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-engine/-/ckeditor5-engine-27.0.0.tgz",
"integrity": "sha512-pOOf155t4HY9PFqZbXcEZf/M/foDze6ht60v9QNfBXQ62JNFCbfVm3R8EeFvJ7eQ1xuONx1CmvNbw3he/Ow2IQ==",
"dependencies": {
"@ckeditor/ckeditor5-utils": "^27.0.0",
"lodash-es": "^4.17.15"
},
"engines": {
"node": ">=12.0.0",
"npm": ">=5.7.1"
}
},
"node_modules/@ckeditor/ckeditor5-enter": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-enter/-/ckeditor5-enter-27.0.0.tgz",
"integrity": "sha512-SBfztQEvtpWBf9JZ51ERwjiHBjGfVosOzyMIxLz010HXwswuuPY9NA2nLkYf534Vyu4Y4iPhMv5lgy80XyP/TQ==",
"dependencies": {
"@ckeditor/ckeditor5-core": "^27.0.0",
"@ckeditor/ckeditor5-engine": "^27.0.0",
"@ckeditor/ckeditor5-utils": "^27.0.0"
},
"engines": {
"node": ">=12.0.0",
"npm": ">=5.7.1"
}
},
"node_modules/@ckeditor/ckeditor5-essentials": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-essentials/-/ckeditor5-essentials-27.0.0.tgz",
"integrity": "sha512-yKHiPrCq9t1KysPIoHgth84jYpI4eAeNPrW87/Maauve/Vxir4JyYAwK6hfO6yNmty6h0LAu4M06orABDMh9DA==",
"dependencies": {
"ckeditor5": "^27.0.0"
},
"engines": {
"node": ">=12.0.0",
"npm": ">=5.7.1"
}
},
"node_modules/@ckeditor/ckeditor5-font": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-font/-/ckeditor5-font-27.0.0.tgz",
"integrity": "sha512-VLmELvzjRMq/pDTfpzQ8dtDuIWmWYe6Y3PuUtHILWyq7BZy8/CKF4Pgd8bhateKVUXezcBFOSxZcIGSPoCGnoA==",
"dependencies": {
"ckeditor5": "^27.0.0"
},
"engines": {
"node": ">=12.0.0",
"npm": ">=5.7.1"
}
},
"node_modules/@ckeditor/ckeditor5-heading": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-heading/-/ckeditor5-heading-27.0.0.tgz",
"integrity": "sha512-f+tIYVc05GxM4Y4FIt6NicvkMpF3pfMCnEksYN2A5eir9p7Tpfn5yvgcdDyCBpD69WoHP9IPQNYuqbfVp/7jMA==",
"dependencies": {
"ckeditor5": "^27.0.0"
},
"engines": {
"node": ">=12.0.0",
"npm": ">=5.7.1"
}
},
"node_modules/@ckeditor/ckeditor5-image": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-image/-/ckeditor5-image-27.0.0.tgz",
"integrity": "sha512-N/t/UrGl4eFIpbgtzGIzZDDl1HDBWYpDRFrpieR34QH2A4ZHCN6pO2688pXQlWVfcIacFmJeaNwE0hj/6TZb2g==",
"dependencies": {
"@ckeditor/ckeditor5-ui": "^27.0.0",
"ckeditor5": "^27.0.0"
},
"engines": {
"node": ">=12.0.0",
"npm": ">=5.7.1"
}
},
"node_modules/@ckeditor/ckeditor5-indent": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-indent/-/ckeditor5-indent-27.0.0.tgz",
"integrity": "sha512-JKfuLis9zstH+w5tNbYrDe/4nOjZJOgzjjlrlHFLy4pk8I9trDS0mUga89FB9gGL/dBJvmmTU2s5skHlzHJLNA==",
"dependencies": {
"ckeditor5": "^27.0.0"
},
"engines": {
"node": ">=12.0.0",
"npm": ">=5.7.1"
}
},
"node_modules/@ckeditor/ckeditor5-link": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-link/-/ckeditor5-link-27.0.0.tgz",
"integrity": "sha512-KK9aRG0bjUGRc1sf5PA7j5xD19Gcr/miA2Zwv/SSNq35sJhPoHchfK9t+BOEZvJU/wY53IeUPcf4M6yZ2J6KLw==",
"dependencies": {
"@ckeditor/ckeditor5-ui": "^27.0.0",
"ckeditor5": "^27.0.0",
"lodash-es": "^4.17.15"
},
"engines": {
"node": ">=12.0.0",
"npm": ">=5.7.1"
}
},
"node_modules/@ckeditor/ckeditor5-list": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-list/-/ckeditor5-list-27.0.0.tgz",
"integrity": "sha512-mIU06LeVahGhQ93wYKwEZcxA+YP8a/OzA3hDBwluqR+9hWGPSttDeD0t+JDaX4HCefVj0f9BvZvkWwRBZeB4nw==",
"dependencies": {
"ckeditor5": "^27.0.0"
},
"engines": {
"node": ">=12.0.0",
"npm": ">=5.7.1"
}
},
"node_modules/@ckeditor/ckeditor5-media-embed": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-media-embed/-/ckeditor5-media-embed-27.0.0.tgz",
"integrity": "sha512-j1W0qKy/+v4E33z8nZgcAtBiftvxNQUWU9VlaJODNbX+qGV4ZucLHeA1FOzV3AQlwrZGcN7+mDQ91uuM5GUHcw==",
"dependencies": {
"@ckeditor/ckeditor5-ui": "^27.0.0",
"ckeditor5": "^27.0.0"
},
"engines": {
"node": ">=12.0.0",
"npm": ">=5.7.1"
}
},
"node_modules/@ckeditor/ckeditor5-paragraph": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-paragraph/-/ckeditor5-paragraph-27.0.0.tgz",
"integrity": "sha512-CzPSzYed4Hx7R7y8jXcaNUX0ZR8vAdPI3bNG625HaL084gA09cfLjprAEIRVXfFFYMRTUNMUrZesKCIhVS3E4w==",
"dependencies": {
"@ckeditor/ckeditor5-core": "^27.0.0",
"@ckeditor/ckeditor5-ui": "^27.0.0",
"@ckeditor/ckeditor5-utils": "^27.0.0"
},
"engines": {
"node": ">=12.0.0",
"npm": ">=5.7.1"
}
},
"node_modules/@ckeditor/ckeditor5-paste-from-office": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-paste-from-office/-/ckeditor5-paste-from-office-27.0.0.tgz",
"integrity": "sha512-ywvw9pJiLd3aYbnu/vPwmet9/dPa8B7kRljoxz9CiHBf/qN3QMXMd1vAtuVxN2ZtV4HIe36Opw4zINMcz7jiRQ==",
"dependencies": {
"ckeditor5": "^27.0.0"
},
"engines": {
"node": ">=12.0.0",
"npm": ">=5.7.1"
}
},
"node_modules/@ckeditor/ckeditor5-select-all": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-select-all/-/ckeditor5-select-all-27.0.0.tgz",
"integrity": "sha512-JhWQMZYX96sJcqBt1qf7nLUn1IPEgKgffXKeiwwtTlgcQJeMrWMEkolybtlff0bedk+yqzzDlm9MHPUiFZNyiw==",
"dependencies": {
"@ckeditor/ckeditor5-core": "^27.0.0",
"@ckeditor/ckeditor5-ui": "^27.0.0",
"@ckeditor/ckeditor5-utils": "^27.0.0"
},
"engines": {
"node": ">=12.0.0",
"npm": ">=5.7.1"
}
},
"node_modules/@ckeditor/ckeditor5-table": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-table/-/ckeditor5-table-27.0.0.tgz",
"integrity": "sha512-SM1hStls9vi72WYY2Dm6uP7h5Vbf2M42WtaY7ez2Pwp3+LhGDeBECE2nH9ZovWOiZIsGluV7d0v1WwdZBzr/rg==",
"dependencies": {
"ckeditor5": "^27.0.0",
"lodash-es": "^4.17.15"
},
"engines": {
"node": ">=12.0.0",
"npm": ">=5.7.1"
}
},
"node_modules/@ckeditor/ckeditor5-typing": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-typing/-/ckeditor5-typing-27.0.0.tgz",
"integrity": "sha512-VKM2eC0eINqpOSz8k6G9Qu0xwCUnhFaYyT9tG64XRifQSGm0+ED4ygkI0o++cwERYYXB8kLKMloC2rHNK9HnQQ==",
"dependencies": {
"@ckeditor/ckeditor5-core": "^27.0.0",
"@ckeditor/ckeditor5-engine": "^27.0.0",
"@ckeditor/ckeditor5-utils": "^27.0.0",
"lodash-es": "^4.17.15"
},
"engines": {
"node": ">=12.0.0",
"npm": ">=5.7.1"
}
},
"node_modules/@ckeditor/ckeditor5-ui": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-ui/-/ckeditor5-ui-27.0.0.tgz",
"integrity": "sha512-r+29zRUSBMEBUDRAN+rAxi/xPLxozEj9gLUHSvU0+uTiungq0X/hLj676J+JrIohiDe/DcuvZ/OwDi4n6v8i+g==",
"dependencies": {
"@ckeditor/ckeditor5-utils": "^27.0.0",
"ckeditor5": "^27.0.0",
"lodash-es": "^4.17.15"
},
"engines": {
"node": ">=12.0.0",
"npm": ">=5.7.1"
}
},
"node_modules/@ckeditor/ckeditor5-undo": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-undo/-/ckeditor5-undo-27.0.0.tgz",
"integrity": "sha512-FLe6MnC5j0L1BQIrRa4gob8W8GxUXQ8uMG+DvLik07TpaU5PXb/CzUIJz7vZgxhbj7tKd8L9AmfcGza9g0S3kA==",
"dependencies": {
"@ckeditor/ckeditor5-core": "^27.0.0",
"@ckeditor/ckeditor5-engine": "^27.0.0",
"@ckeditor/ckeditor5-ui": "^27.0.0"
},
"engines": {
"node": ">=12.0.0",
"npm": ">=5.7.1"
}
},
"node_modules/@ckeditor/ckeditor5-upload": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-upload/-/ckeditor5-upload-27.0.0.tgz",
"integrity": "sha512-ZlUpnK2jnMpcjYOz+TFsYQRG5WzXRjGgmsXDNG5gi0mCVwUovErvVFqzEHlXQR1TpKIsxgf5I0uPKPzMXpDOfg==",
"dependencies": {
"@ckeditor/ckeditor5-core": "^27.0.0",
"@ckeditor/ckeditor5-ui": "^27.0.0",
"@ckeditor/ckeditor5-utils": "^27.0.0"
},
"engines": {
"node": ">=12.0.0",
"npm": ">=5.7.1"
}
},
"node_modules/@ckeditor/ckeditor5-utils": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-utils/-/ckeditor5-utils-27.0.0.tgz",
"integrity": "sha512-GYscRP6M73og0DRASbUmelL6SHP77F7XaoI3rZrHIXA+ykOp83v9b6I/5CiJdSvB8t/oHVq/ZoJ6s6CrkVFMEQ==",
"dependencies": {
"lodash-es": "^4.17.15"
},
"engines": { "engines": {
"node": ">=12.0.0", "node": ">=12.0.0",
"npm": ">=5.7.1" "npm": ">=5.7.1"
...@@ -1281,6 +1741,37 @@ ...@@ -1281,6 +1741,37 @@
"npm": ">=5.7.1" "npm": ">=5.7.1"
} }
}, },
"node_modules/@ckeditor/ckeditor5-widget": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-widget/-/ckeditor5-widget-27.0.0.tgz",
"integrity": "sha512-kgu7EKO7jC4L27etNlbBpk76CKSZJqD9BgST0el+bPvF/cITItSOCVQttKgW/6peu0ROL6dWPjAhnLBjxNi3oA==",
"dependencies": {
"@ckeditor/ckeditor5-core": "^27.0.0",
"@ckeditor/ckeditor5-engine": "^27.0.0",
"@ckeditor/ckeditor5-enter": "^27.0.0",
"@ckeditor/ckeditor5-typing": "^27.0.0",
"@ckeditor/ckeditor5-ui": "^27.0.0",
"@ckeditor/ckeditor5-utils": "^27.0.0",
"lodash-es": "^4.17.15"
},
"engines": {
"node": ">=12.0.0",
"npm": ">=5.7.1"
}
},
"node_modules/@ezijing/web-message-sdk": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/@ezijing/web-message-sdk/-/web-message-sdk-0.2.1.tgz",
"integrity": "sha512-pkjX2jL3HLbpvwUo3cNWZnV7Sfl5EeH9O/vpL6PEUpV4f4m+fHVGoV0tyuPzrn8nuhEoMi0uOUCHkrsJqW6Ljw==",
"dependencies": {
"axios": "^0.21.1",
"blueimp-md5": "^2.18.0",
"core-js": "^3.9.0",
"element-ui": "^2.15.1",
"qs": "^6.9.6",
"vue": "^2.6.12"
}
},
"node_modules/@types/anymatch": { "node_modules/@types/anymatch": {
"version": "1.3.1", "version": "1.3.1",
"resolved": "https://registry.npmjs.org/@types/anymatch/-/anymatch-1.3.1.tgz", "resolved": "https://registry.npmjs.org/@types/anymatch/-/anymatch-1.3.1.tgz",
...@@ -1426,6 +1917,24 @@ ...@@ -1426,6 +1917,24 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/@vue/composition-api": {
"version": "1.0.0-rc.5",
"resolved": "https://registry.npmjs.org/@vue/composition-api/-/composition-api-1.0.0-rc.5.tgz",
"integrity": "sha512-sFBUDZxwi5YOQqH//VSGenO6WH0JuW94+CWo1eUsGSTRue8POfwD4oeduVqi/c6QcwXg2tJL/m6aOD2t/IR6zg==",
"devOptional": true,
"dependencies": {
"tslib": "^2.1.0"
},
"peerDependencies": {
"vue": ">= 2.5 < 3"
}
},
"node_modules/@vue/composition-api/node_modules/tslib": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz",
"integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==",
"devOptional": true
},
"node_modules/@webassemblyjs/ast": { "node_modules/@webassemblyjs/ast": {
"version": "1.9.0", "version": "1.9.0",
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz",
...@@ -2096,9 +2605,9 @@ ...@@ -2096,9 +2605,9 @@
"dev": true "dev": true
}, },
"node_modules/axios": { "node_modules/axios": {
"version": "0.21.0", "version": "0.21.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.0.tgz", "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
"integrity": "sha512-fmkJBknJKoZwem3/IKSSLpkdNXZeBu5Q7GA/aRsr2btgrptmSCxi2oFjZHqGdK9DoTil9PIHlPIZw2EcRJXRvw==", "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
"dependencies": { "dependencies": {
"follow-redirects": "^1.10.0" "follow-redirects": "^1.10.0"
} }
...@@ -2323,6 +2832,11 @@ ...@@ -2323,6 +2832,11 @@
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
"integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="
}, },
"node_modules/blueimp-md5": {
"version": "2.18.0",
"resolved": "https://registry.npmjs.org/blueimp-md5/-/blueimp-md5-2.18.0.tgz",
"integrity": "sha512-vE52okJvzsVWhcgUHOv+69OG3Mdg151xyn41aVQN/5W5S+S43qZhxECtYLAEHMSFWX6Mv5IZrzj3T5+JqXfj5Q=="
},
"node_modules/bn.js": { "node_modules/bn.js": {
"version": "5.1.3", "version": "5.1.3",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz",
...@@ -2848,6 +3362,29 @@ ...@@ -2848,6 +3362,29 @@
"safe-buffer": "^5.0.1" "safe-buffer": "^5.0.1"
} }
}, },
"node_modules/ckeditor5": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/ckeditor5/-/ckeditor5-27.0.0.tgz",
"integrity": "sha512-KjAjA/K5sNZ2UOaD3qxYiEv23TUdsZdNgDSMUiMjaFNv7bkoPZ4p8fEM4squzzB6VupLSjDw31WmTPF7Sf0KrA==",
"dependencies": {
"@ckeditor/ckeditor5-clipboard": "^27.0.0",
"@ckeditor/ckeditor5-core": "^27.0.0",
"@ckeditor/ckeditor5-engine": "^27.0.0",
"@ckeditor/ckeditor5-enter": "^27.0.0",
"@ckeditor/ckeditor5-paragraph": "^27.0.0",
"@ckeditor/ckeditor5-select-all": "^27.0.0",
"@ckeditor/ckeditor5-typing": "^27.0.0",
"@ckeditor/ckeditor5-ui": "^27.0.0",
"@ckeditor/ckeditor5-undo": "^27.0.0",
"@ckeditor/ckeditor5-upload": "^27.0.0",
"@ckeditor/ckeditor5-utils": "^27.0.0",
"@ckeditor/ckeditor5-widget": "^27.0.0"
},
"engines": {
"node": ">=12.0.0",
"npm": ">=5.7.1"
}
},
"node_modules/class-utils": { "node_modules/class-utils": {
"version": "0.3.6", "version": "0.3.6",
"resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz",
...@@ -3391,10 +3928,14 @@ ...@@ -3391,10 +3928,14 @@
} }
}, },
"node_modules/core-js": { "node_modules/core-js": {
"version": "3.8.1", "version": "3.9.0",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.8.1.tgz", "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.9.0.tgz",
"integrity": "sha512-9Id2xHY1W7m8hCl8NkhQn5CufmF/WuR30BTRewvCXc1aZd3kMECwNZ69ndLbekKfakw9Rf2Xyc+QR6E7Gg+obg==", "integrity": "sha512-PyFBJaLq93FlyYdsndE5VaueA9K5cNB7CGzeCj191YYLhkQM0gdZR2SKihM70oF0wdqKSKClv/tEBOpoRmdOVQ==",
"hasInstallScript": true "hasInstallScript": true,
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/core-js"
}
}, },
"node_modules/core-js-compat": { "node_modules/core-js-compat": {
"version": "3.6.5", "version": "3.6.5",
...@@ -4215,6 +4756,20 @@ ...@@ -4215,6 +4756,20 @@
"safer-buffer": "^2.1.0" "safer-buffer": "^2.1.0"
} }
}, },
"node_modules/echarts": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/echarts/-/echarts-5.0.2.tgz",
"integrity": "sha512-En0VYpc96nw2/2AZoBWPHsGi471zMublttj50kfFpYAeR4geup0Tj9iVgEXh7QYZFPnRiruDJEjcB5PXZ+BYzQ==",
"dependencies": {
"tslib": "2.0.3",
"zrender": "5.0.4"
}
},
"node_modules/echarts/node_modules/tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ=="
},
"node_modules/ee-first": { "node_modules/ee-first": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
...@@ -4228,9 +4783,9 @@ ...@@ -4228,9 +4783,9 @@
"dev": true "dev": true
}, },
"node_modules/element-ui": { "node_modules/element-ui": {
"version": "2.14.1", "version": "2.15.1",
"resolved": "https://registry.npmjs.org/element-ui/-/element-ui-2.14.1.tgz", "resolved": "https://registry.npmjs.org/element-ui/-/element-ui-2.15.1.tgz",
"integrity": "sha512-Uje0J12dBaXdyvt/EtuDA8diFbYTdO7uI4QCfl7zmEJmE1WxgCSVKhlRRoL8MDonO8pyNVhB4n0AFAR14g56nw==", "integrity": "sha512-TqlScAKGH97XndSScUDeEHIzL1x7yg7DvQdKPEOUdiDcyIz3y3FJJBlpHYaJT96FOn1xpIcUZb+I2FJeU9EcrQ==",
"dependencies": { "dependencies": {
"async-validator": "~1.8.1", "async-validator": "~1.8.1",
"babel-helper-vue-jsx-merge-props": "^2.0.0", "babel-helper-vue-jsx-merge-props": "^2.0.0",
...@@ -4238,6 +4793,9 @@ ...@@ -4238,6 +4793,9 @@
"normalize-wheel": "^1.0.1", "normalize-wheel": "^1.0.1",
"resize-observer-polyfill": "^1.5.0", "resize-observer-polyfill": "^1.5.0",
"throttle-debounce": "^1.0.1" "throttle-debounce": "^1.0.1"
},
"peerDependencies": {
"vue": "^2.5.17"
} }
}, },
"node_modules/elliptic": { "node_modules/elliptic": {
...@@ -7626,9 +8184,14 @@ ...@@ -7626,9 +8184,14 @@
} }
}, },
"node_modules/lodash": { "node_modules/lodash": {
"version": "4.17.20", "version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
},
"node_modules/lodash-es": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
}, },
"node_modules/loglevel": { "node_modules/loglevel": {
"version": "1.7.0", "version": "1.7.0",
...@@ -9524,11 +10087,14 @@ ...@@ -9524,11 +10087,14 @@
"integrity": "sha512-R7t6Y3fDDtcU7L4rtqwGUDP9xD64gJhIwpfjhRCTKmBoYF6SS49PIJHRJ048cse6OI7iwTwgyy2C46N9Ygoc6g==" "integrity": "sha512-R7t6Y3fDDtcU7L4rtqwGUDP9xD64gJhIwpfjhRCTKmBoYF6SS49PIJHRJ048cse6OI7iwTwgyy2C46N9Ygoc6g=="
}, },
"node_modules/qs": { "node_modules/qs": {
"version": "6.9.4", "version": "6.9.6",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.9.4.tgz", "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.6.tgz",
"integrity": "sha512-A1kFqHekCTM7cz0udomYUoYNWjBebHm/5wzU/XqrBRBNWectVH0QIiN+NEcZ0Dte5hvzHwbr8+XQmguPhJ6WdQ==", "integrity": "sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ==",
"engines": { "engines": {
"node": ">=0.6" "node": ">=0.6"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/query-string": { "node_modules/query-string": {
...@@ -9966,6 +10532,11 @@ ...@@ -9966,6 +10532,11 @@
"integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
"dev": true "dev": true
}, },
"node_modules/resize-detector": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/resize-detector/-/resize-detector-0.3.0.tgz",
"integrity": "sha512-R/tCuvuOHQ8o2boRP6vgx8hXCCy87H1eY9V5imBYeVNyNVpuL9ciReSccLj2gDcax9+2weXy3bc8Vv+NRXeEvQ=="
},
"node_modules/resize-observer-polyfill": { "node_modules/resize-observer-polyfill": {
"version": "1.5.1", "version": "1.5.1",
"resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz",
...@@ -12192,6 +12763,48 @@ ...@@ -12192,6 +12763,48 @@
"resolved": "https://registry.npmjs.org/vue/-/vue-2.6.12.tgz", "resolved": "https://registry.npmjs.org/vue/-/vue-2.6.12.tgz",
"integrity": "sha512-uhmLFETqPPNyuLLbsKz6ioJ4q7AZHzD8ZVFNATNyICSZouqP2Sz0rotWQC8UNBF6VGSCs5abnKJoStA6JbCbfg==" "integrity": "sha512-uhmLFETqPPNyuLLbsKz6ioJ4q7AZHzD8ZVFNATNyICSZouqP2Sz0rotWQC8UNBF6VGSCs5abnKJoStA6JbCbfg=="
}, },
"node_modules/vue-demi": {
"version": "0.7.3",
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.7.3.tgz",
"integrity": "sha512-vrzM26H4CZCXBf/eu4T8nks6o7qgziYM52myk8bg+atw4qYqpeWJf5c82W8VdmgGfSIdh9ulOOe9+GeLc3Z/8A==",
"hasInstallScript": true,
"bin": {
"vue-demi-fix": "bin/vue-demi-fix.js",
"vue-demi-switch": "bin/vue-demi-switch.js"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"@vue/composition-api": "^1.0.0-beta.1",
"vue": "^2.6.0 || >=3.0.0-rc.1"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
}
}
},
"node_modules/vue-echarts": {
"version": "6.0.0-rc.3",
"resolved": "https://registry.npmjs.org/vue-echarts/-/vue-echarts-6.0.0-rc.3.tgz",
"integrity": "sha512-B7xfwpHaOeM9+cjallrK3AW893oaeqT9Sjx7tHgwoyGdfPTq6cwDc2Hcdmjgrs/KEp+ZZXMIajXky30Wu4/TDw==",
"hasInstallScript": true,
"dependencies": {
"resize-detector": "^0.3.0",
"vue-demi": "^0.7.1"
},
"peerDependencies": {
"@vue/composition-api": "^1.0.0-rc.2",
"echarts": "^5.0.2",
"vue": "^2.6.12 || ^3.0.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
}
}
},
"node_modules/vue-eslint-parser": { "node_modules/vue-eslint-parser": {
"version": "7.1.1", "version": "7.1.1",
"resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-7.1.1.tgz", "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-7.1.1.tgz",
...@@ -13346,6 +13959,19 @@ ...@@ -13346,6 +13959,19 @@
"engines": { "engines": {
"node": ">=6" "node": ">=6"
} }
},
"node_modules/zrender": {
"version": "5.0.4",
"resolved": "https://registry.npmjs.org/zrender/-/zrender-5.0.4.tgz",
"integrity": "sha512-DJpy0yrHYY5CuH6vhb9IINWbjvBUe/56J8aH86Jb7O8rRPAYZ3M2E469Qf5B3EOIfM3o3aUrO5edRQfLJ+l1Qw==",
"dependencies": {
"tslib": "2.0.3"
}
},
"node_modules/zrender/node_modules/tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ=="
} }
}, },
"dependencies": { "dependencies": {
...@@ -14514,16 +15140,370 @@ ...@@ -14514,16 +15140,370 @@
"to-fast-properties": "^2.0.0" "to-fast-properties": "^2.0.0"
} }
}, },
"@ckeditor/ckeditor5-adapter-ckfinder": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-adapter-ckfinder/-/ckeditor5-adapter-ckfinder-27.0.0.tgz",
"integrity": "sha512-2JzedLntHRw2ChQ54tB9pk1XFH4VzFPJLMJXhE3CP2+ANiIKZZTHodcQ7R2BOosIpySQOEppjfi1emZ6AgcLRg==",
"requires": {
"ckeditor5": "^27.0.0"
}
},
"@ckeditor/ckeditor5-alignment": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-alignment/-/ckeditor5-alignment-27.0.0.tgz",
"integrity": "sha512-MEXslAyeLmRwbRicOhIKmdvfreXkorwYEYMTDhJaOO3gll/mqDBbn0ijNsCOm4QgXUT6qqK2sOhxGRL3cDuMcQ==",
"requires": {
"ckeditor5": "^27.0.0"
}
},
"@ckeditor/ckeditor5-autoformat": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-autoformat/-/ckeditor5-autoformat-27.0.0.tgz",
"integrity": "sha512-SirBT1Reu2I9yXSLrcL4IZDecux0pNLfYdZVfz1PIXr99LOYvF1iqyWdo0dLEj5xEGf77OPoiIIhnOQJA8fZzA==",
"requires": {
"ckeditor5": "^27.0.0"
}
},
"@ckeditor/ckeditor5-basic-styles": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-basic-styles/-/ckeditor5-basic-styles-27.0.0.tgz",
"integrity": "sha512-idmD5huRKDFRe1ToyIj5RrnVde00fnEteyVnUWLZPYZr+Y2aye1KFWthmycqKIdNhCXy60ydnhXjy0tVuwHlmw==",
"requires": {
"ckeditor5": "^27.0.0"
}
},
"@ckeditor/ckeditor5-block-quote": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-block-quote/-/ckeditor5-block-quote-27.0.0.tgz",
"integrity": "sha512-sUSkhEnKDeAjB8EXvrt3zI+pYdnUg228t2Uoe6A0VCeaSynHn+YF9bHL8XSdEMaD1UdDcdRhtNhJL+d+cEdOqA==",
"requires": {
"ckeditor5": "^27.0.0"
}
},
"@ckeditor/ckeditor5-build-classic": { "@ckeditor/ckeditor5-build-classic": {
"version": "24.0.0", "version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-build-classic/-/ckeditor5-build-classic-24.0.0.tgz", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-build-classic/-/ckeditor5-build-classic-27.0.0.tgz",
"integrity": "sha512-659ZAYbuQbPj3ElqrTSV7aqPtW4vt30Th0PiheFei7adIgmu1bFTHgcM3hqm7XGRzGmBRV6C07xSwUptxn3cvQ==" "integrity": "sha512-ghqgz/wyvyjN/NwYes7onnxo/N8rsutzTbSXJRdxxDxycH3DYUNMQsDj4ehf0ACp8RkpVDLekybxsyx3gSk3Ww==",
"requires": {
"@ckeditor/ckeditor5-adapter-ckfinder": "^27.0.0",
"@ckeditor/ckeditor5-autoformat": "^27.0.0",
"@ckeditor/ckeditor5-basic-styles": "^27.0.0",
"@ckeditor/ckeditor5-block-quote": "^27.0.0",
"@ckeditor/ckeditor5-ckfinder": "^27.0.0",
"@ckeditor/ckeditor5-cloud-services": "^27.0.0",
"@ckeditor/ckeditor5-easy-image": "^27.0.0",
"@ckeditor/ckeditor5-editor-classic": "^27.0.0",
"@ckeditor/ckeditor5-essentials": "^27.0.0",
"@ckeditor/ckeditor5-heading": "^27.0.0",
"@ckeditor/ckeditor5-image": "^27.0.0",
"@ckeditor/ckeditor5-indent": "^27.0.0",
"@ckeditor/ckeditor5-link": "^27.0.0",
"@ckeditor/ckeditor5-list": "^27.0.0",
"@ckeditor/ckeditor5-media-embed": "^27.0.0",
"@ckeditor/ckeditor5-paragraph": "^27.0.0",
"@ckeditor/ckeditor5-paste-from-office": "^27.0.0",
"@ckeditor/ckeditor5-table": "^27.0.0",
"@ckeditor/ckeditor5-typing": "^27.0.0"
}
},
"@ckeditor/ckeditor5-build-decoupled-document": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-build-decoupled-document/-/ckeditor5-build-decoupled-document-27.0.0.tgz",
"integrity": "sha512-2xVXA1eZ99kMwjfrcWtXYLXGSDObmyQOaXWuzYXWaBgGY5mYL4xJtaFP4Jn/IZYShFqu9Wc43nnh3EjnxegfHw==",
"requires": {
"@ckeditor/ckeditor5-adapter-ckfinder": "^27.0.0",
"@ckeditor/ckeditor5-alignment": "^27.0.0",
"@ckeditor/ckeditor5-autoformat": "^27.0.0",
"@ckeditor/ckeditor5-basic-styles": "^27.0.0",
"@ckeditor/ckeditor5-block-quote": "^27.0.0",
"@ckeditor/ckeditor5-ckfinder": "^27.0.0",
"@ckeditor/ckeditor5-cloud-services": "^27.0.0",
"@ckeditor/ckeditor5-easy-image": "^27.0.0",
"@ckeditor/ckeditor5-editor-decoupled": "^27.0.0",
"@ckeditor/ckeditor5-essentials": "^27.0.0",
"@ckeditor/ckeditor5-font": "^27.0.0",
"@ckeditor/ckeditor5-heading": "^27.0.0",
"@ckeditor/ckeditor5-image": "^27.0.0",
"@ckeditor/ckeditor5-indent": "^27.0.0",
"@ckeditor/ckeditor5-link": "^27.0.0",
"@ckeditor/ckeditor5-list": "^27.0.0",
"@ckeditor/ckeditor5-media-embed": "^27.0.0",
"@ckeditor/ckeditor5-paragraph": "^27.0.0",
"@ckeditor/ckeditor5-paste-from-office": "^27.0.0",
"@ckeditor/ckeditor5-table": "^27.0.0",
"@ckeditor/ckeditor5-typing": "^27.0.0"
}
},
"@ckeditor/ckeditor5-ckfinder": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-ckfinder/-/ckeditor5-ckfinder-27.0.0.tgz",
"integrity": "sha512-TyuMYTUv4eiy5dbaxChgn3kaptZWFlnTWOx3CIUPcpURt+h40HFRSANfmOPeKag4COXJaF/0MnmRe/QPJvaNbw==",
"requires": {
"ckeditor5": "^27.0.0"
}
},
"@ckeditor/ckeditor5-clipboard": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-clipboard/-/ckeditor5-clipboard-27.0.0.tgz",
"integrity": "sha512-oNLLjPWFoTIqdf6BOtKBDu0qUQiIia5TM6acxi5DKx5YdXnwg1GozxYa4x590EhUVIDFe6i0JuZbkALQ2tBI5g==",
"requires": {
"@ckeditor/ckeditor5-core": "^27.0.0",
"@ckeditor/ckeditor5-engine": "^27.0.0",
"@ckeditor/ckeditor5-utils": "^27.0.0",
"@ckeditor/ckeditor5-widget": "^27.0.0",
"lodash-es": "^4.17.11"
}
},
"@ckeditor/ckeditor5-cloud-services": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-cloud-services/-/ckeditor5-cloud-services-27.0.0.tgz",
"integrity": "sha512-IXc8rOAZoITNyl5c46M9/eVusKQYWXsFojxBvI9WlpxtxIRhXCge2grDyEg/rOeLBt8eJxJxIkuNDbwqMXcAKA==",
"requires": {
"ckeditor5": "^27.0.0"
}
},
"@ckeditor/ckeditor5-core": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-core/-/ckeditor5-core-27.0.0.tgz",
"integrity": "sha512-0dtV2eREe3mh1vqG8x4cIYCwFthzA5aOvRdaIQSj6T6JuBR9lO2IiniOpR0CAsiIgpAM9vmggah+Knngbe2gEA==",
"requires": {
"@ckeditor/ckeditor5-engine": "^27.0.0",
"@ckeditor/ckeditor5-ui": "^27.0.0",
"@ckeditor/ckeditor5-utils": "^27.0.0",
"lodash-es": "^4.17.15"
}
},
"@ckeditor/ckeditor5-easy-image": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-easy-image/-/ckeditor5-easy-image-27.0.0.tgz",
"integrity": "sha512-RqPJI5pkqaSgDcSCEm47eokteTgniLZFD4j/Y7F7v5tTvUoinn5LaKGv8DttquA4OPiF9kq2h3ZadqRGTpUuYQ==",
"requires": {
"ckeditor5": "^27.0.0"
}
},
"@ckeditor/ckeditor5-editor-classic": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-classic/-/ckeditor5-editor-classic-27.0.0.tgz",
"integrity": "sha512-guRK+sxFTpkh3XPTk38V9+6dQ784soOExCZW80G6TKlfBM8aJoWsuRiENgZ11eZ8f4OKlhVHuAH5ivoxCB7BOA==",
"requires": {
"ckeditor5": "^27.0.0",
"lodash-es": "^4.17.15"
}
},
"@ckeditor/ckeditor5-editor-decoupled": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-decoupled/-/ckeditor5-editor-decoupled-27.0.0.tgz",
"integrity": "sha512-aOa2zM64cSyJoigoHeWqAVFyqtrgUey4vaTU7uAvCW/JiIaJwFKyrRUIyrMLRE355AJH7Y7vNWUCmgV+mXMN1w==",
"requires": {
"ckeditor5": "^27.0.0",
"lodash-es": "^4.17.15"
}
},
"@ckeditor/ckeditor5-engine": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-engine/-/ckeditor5-engine-27.0.0.tgz",
"integrity": "sha512-pOOf155t4HY9PFqZbXcEZf/M/foDze6ht60v9QNfBXQ62JNFCbfVm3R8EeFvJ7eQ1xuONx1CmvNbw3he/Ow2IQ==",
"requires": {
"@ckeditor/ckeditor5-utils": "^27.0.0",
"lodash-es": "^4.17.15"
}
},
"@ckeditor/ckeditor5-enter": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-enter/-/ckeditor5-enter-27.0.0.tgz",
"integrity": "sha512-SBfztQEvtpWBf9JZ51ERwjiHBjGfVosOzyMIxLz010HXwswuuPY9NA2nLkYf534Vyu4Y4iPhMv5lgy80XyP/TQ==",
"requires": {
"@ckeditor/ckeditor5-core": "^27.0.0",
"@ckeditor/ckeditor5-engine": "^27.0.0",
"@ckeditor/ckeditor5-utils": "^27.0.0"
}
},
"@ckeditor/ckeditor5-essentials": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-essentials/-/ckeditor5-essentials-27.0.0.tgz",
"integrity": "sha512-yKHiPrCq9t1KysPIoHgth84jYpI4eAeNPrW87/Maauve/Vxir4JyYAwK6hfO6yNmty6h0LAu4M06orABDMh9DA==",
"requires": {
"ckeditor5": "^27.0.0"
}
},
"@ckeditor/ckeditor5-font": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-font/-/ckeditor5-font-27.0.0.tgz",
"integrity": "sha512-VLmELvzjRMq/pDTfpzQ8dtDuIWmWYe6Y3PuUtHILWyq7BZy8/CKF4Pgd8bhateKVUXezcBFOSxZcIGSPoCGnoA==",
"requires": {
"ckeditor5": "^27.0.0"
}
},
"@ckeditor/ckeditor5-heading": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-heading/-/ckeditor5-heading-27.0.0.tgz",
"integrity": "sha512-f+tIYVc05GxM4Y4FIt6NicvkMpF3pfMCnEksYN2A5eir9p7Tpfn5yvgcdDyCBpD69WoHP9IPQNYuqbfVp/7jMA==",
"requires": {
"ckeditor5": "^27.0.0"
}
},
"@ckeditor/ckeditor5-image": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-image/-/ckeditor5-image-27.0.0.tgz",
"integrity": "sha512-N/t/UrGl4eFIpbgtzGIzZDDl1HDBWYpDRFrpieR34QH2A4ZHCN6pO2688pXQlWVfcIacFmJeaNwE0hj/6TZb2g==",
"requires": {
"@ckeditor/ckeditor5-ui": "^27.0.0",
"ckeditor5": "^27.0.0"
}
},
"@ckeditor/ckeditor5-indent": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-indent/-/ckeditor5-indent-27.0.0.tgz",
"integrity": "sha512-JKfuLis9zstH+w5tNbYrDe/4nOjZJOgzjjlrlHFLy4pk8I9trDS0mUga89FB9gGL/dBJvmmTU2s5skHlzHJLNA==",
"requires": {
"ckeditor5": "^27.0.0"
}
},
"@ckeditor/ckeditor5-link": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-link/-/ckeditor5-link-27.0.0.tgz",
"integrity": "sha512-KK9aRG0bjUGRc1sf5PA7j5xD19Gcr/miA2Zwv/SSNq35sJhPoHchfK9t+BOEZvJU/wY53IeUPcf4M6yZ2J6KLw==",
"requires": {
"@ckeditor/ckeditor5-ui": "^27.0.0",
"ckeditor5": "^27.0.0",
"lodash-es": "^4.17.15"
}
},
"@ckeditor/ckeditor5-list": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-list/-/ckeditor5-list-27.0.0.tgz",
"integrity": "sha512-mIU06LeVahGhQ93wYKwEZcxA+YP8a/OzA3hDBwluqR+9hWGPSttDeD0t+JDaX4HCefVj0f9BvZvkWwRBZeB4nw==",
"requires": {
"ckeditor5": "^27.0.0"
}
},
"@ckeditor/ckeditor5-media-embed": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-media-embed/-/ckeditor5-media-embed-27.0.0.tgz",
"integrity": "sha512-j1W0qKy/+v4E33z8nZgcAtBiftvxNQUWU9VlaJODNbX+qGV4ZucLHeA1FOzV3AQlwrZGcN7+mDQ91uuM5GUHcw==",
"requires": {
"@ckeditor/ckeditor5-ui": "^27.0.0",
"ckeditor5": "^27.0.0"
}
},
"@ckeditor/ckeditor5-paragraph": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-paragraph/-/ckeditor5-paragraph-27.0.0.tgz",
"integrity": "sha512-CzPSzYed4Hx7R7y8jXcaNUX0ZR8vAdPI3bNG625HaL084gA09cfLjprAEIRVXfFFYMRTUNMUrZesKCIhVS3E4w==",
"requires": {
"@ckeditor/ckeditor5-core": "^27.0.0",
"@ckeditor/ckeditor5-ui": "^27.0.0",
"@ckeditor/ckeditor5-utils": "^27.0.0"
}
},
"@ckeditor/ckeditor5-paste-from-office": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-paste-from-office/-/ckeditor5-paste-from-office-27.0.0.tgz",
"integrity": "sha512-ywvw9pJiLd3aYbnu/vPwmet9/dPa8B7kRljoxz9CiHBf/qN3QMXMd1vAtuVxN2ZtV4HIe36Opw4zINMcz7jiRQ==",
"requires": {
"ckeditor5": "^27.0.0"
}
},
"@ckeditor/ckeditor5-select-all": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-select-all/-/ckeditor5-select-all-27.0.0.tgz",
"integrity": "sha512-JhWQMZYX96sJcqBt1qf7nLUn1IPEgKgffXKeiwwtTlgcQJeMrWMEkolybtlff0bedk+yqzzDlm9MHPUiFZNyiw==",
"requires": {
"@ckeditor/ckeditor5-core": "^27.0.0",
"@ckeditor/ckeditor5-ui": "^27.0.0",
"@ckeditor/ckeditor5-utils": "^27.0.0"
}
},
"@ckeditor/ckeditor5-table": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-table/-/ckeditor5-table-27.0.0.tgz",
"integrity": "sha512-SM1hStls9vi72WYY2Dm6uP7h5Vbf2M42WtaY7ez2Pwp3+LhGDeBECE2nH9ZovWOiZIsGluV7d0v1WwdZBzr/rg==",
"requires": {
"ckeditor5": "^27.0.0",
"lodash-es": "^4.17.15"
}
},
"@ckeditor/ckeditor5-typing": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-typing/-/ckeditor5-typing-27.0.0.tgz",
"integrity": "sha512-VKM2eC0eINqpOSz8k6G9Qu0xwCUnhFaYyT9tG64XRifQSGm0+ED4ygkI0o++cwERYYXB8kLKMloC2rHNK9HnQQ==",
"requires": {
"@ckeditor/ckeditor5-core": "^27.0.0",
"@ckeditor/ckeditor5-engine": "^27.0.0",
"@ckeditor/ckeditor5-utils": "^27.0.0",
"lodash-es": "^4.17.15"
}
},
"@ckeditor/ckeditor5-ui": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-ui/-/ckeditor5-ui-27.0.0.tgz",
"integrity": "sha512-r+29zRUSBMEBUDRAN+rAxi/xPLxozEj9gLUHSvU0+uTiungq0X/hLj676J+JrIohiDe/DcuvZ/OwDi4n6v8i+g==",
"requires": {
"@ckeditor/ckeditor5-utils": "^27.0.0",
"ckeditor5": "^27.0.0",
"lodash-es": "^4.17.15"
}
},
"@ckeditor/ckeditor5-undo": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-undo/-/ckeditor5-undo-27.0.0.tgz",
"integrity": "sha512-FLe6MnC5j0L1BQIrRa4gob8W8GxUXQ8uMG+DvLik07TpaU5PXb/CzUIJz7vZgxhbj7tKd8L9AmfcGza9g0S3kA==",
"requires": {
"@ckeditor/ckeditor5-core": "^27.0.0",
"@ckeditor/ckeditor5-engine": "^27.0.0",
"@ckeditor/ckeditor5-ui": "^27.0.0"
}
},
"@ckeditor/ckeditor5-upload": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-upload/-/ckeditor5-upload-27.0.0.tgz",
"integrity": "sha512-ZlUpnK2jnMpcjYOz+TFsYQRG5WzXRjGgmsXDNG5gi0mCVwUovErvVFqzEHlXQR1TpKIsxgf5I0uPKPzMXpDOfg==",
"requires": {
"@ckeditor/ckeditor5-core": "^27.0.0",
"@ckeditor/ckeditor5-ui": "^27.0.0",
"@ckeditor/ckeditor5-utils": "^27.0.0"
}
},
"@ckeditor/ckeditor5-utils": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-utils/-/ckeditor5-utils-27.0.0.tgz",
"integrity": "sha512-GYscRP6M73og0DRASbUmelL6SHP77F7XaoI3rZrHIXA+ykOp83v9b6I/5CiJdSvB8t/oHVq/ZoJ6s6CrkVFMEQ==",
"requires": {
"lodash-es": "^4.17.15"
}
}, },
"@ckeditor/ckeditor5-vue2": { "@ckeditor/ckeditor5-vue2": {
"version": "1.0.5", "version": "1.0.5",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-vue2/-/ckeditor5-vue2-1.0.5.tgz", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-vue2/-/ckeditor5-vue2-1.0.5.tgz",
"integrity": "sha512-snsNB/2oWfKw0drGJAmMGpTatmt//L1rQsOwkBw+1uKUuOJPKN3xwyUZVWT906VguIMXm4E9OHzquZ3bdkijiA==" "integrity": "sha512-snsNB/2oWfKw0drGJAmMGpTatmt//L1rQsOwkBw+1uKUuOJPKN3xwyUZVWT906VguIMXm4E9OHzquZ3bdkijiA=="
}, },
"@ckeditor/ckeditor5-widget": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-widget/-/ckeditor5-widget-27.0.0.tgz",
"integrity": "sha512-kgu7EKO7jC4L27etNlbBpk76CKSZJqD9BgST0el+bPvF/cITItSOCVQttKgW/6peu0ROL6dWPjAhnLBjxNi3oA==",
"requires": {
"@ckeditor/ckeditor5-core": "^27.0.0",
"@ckeditor/ckeditor5-engine": "^27.0.0",
"@ckeditor/ckeditor5-enter": "^27.0.0",
"@ckeditor/ckeditor5-typing": "^27.0.0",
"@ckeditor/ckeditor5-ui": "^27.0.0",
"@ckeditor/ckeditor5-utils": "^27.0.0",
"lodash-es": "^4.17.15"
}
},
"@ezijing/web-message-sdk": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/@ezijing/web-message-sdk/-/web-message-sdk-0.2.1.tgz",
"integrity": "sha512-pkjX2jL3HLbpvwUo3cNWZnV7Sfl5EeH9O/vpL6PEUpV4f4m+fHVGoV0tyuPzrn8nuhEoMi0uOUCHkrsJqW6Ljw==",
"requires": {
"axios": "^0.21.1",
"blueimp-md5": "^2.18.0",
"core-js": "^3.9.0",
"element-ui": "^2.15.1",
"qs": "^6.9.6",
"vue": "^2.6.12"
}
},
"@types/anymatch": { "@types/anymatch": {
"version": "1.3.1", "version": "1.3.1",
"resolved": "https://registry.npmjs.org/@types/anymatch/-/anymatch-1.3.1.tgz", "resolved": "https://registry.npmjs.org/@types/anymatch/-/anymatch-1.3.1.tgz",
...@@ -14663,6 +15643,23 @@ ...@@ -14663,6 +15643,23 @@
} }
} }
}, },
"@vue/composition-api": {
"version": "1.0.0-rc.5",
"resolved": "https://registry.npmjs.org/@vue/composition-api/-/composition-api-1.0.0-rc.5.tgz",
"integrity": "sha512-sFBUDZxwi5YOQqH//VSGenO6WH0JuW94+CWo1eUsGSTRue8POfwD4oeduVqi/c6QcwXg2tJL/m6aOD2t/IR6zg==",
"devOptional": true,
"requires": {
"tslib": "^2.1.0"
},
"dependencies": {
"tslib": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz",
"integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==",
"devOptional": true
}
}
},
"@webassemblyjs/ast": { "@webassemblyjs/ast": {
"version": "1.9.0", "version": "1.9.0",
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz",
...@@ -15248,9 +16245,9 @@ ...@@ -15248,9 +16245,9 @@
"dev": true "dev": true
}, },
"axios": { "axios": {
"version": "0.21.0", "version": "0.21.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.0.tgz", "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
"integrity": "sha512-fmkJBknJKoZwem3/IKSSLpkdNXZeBu5Q7GA/aRsr2btgrptmSCxi2oFjZHqGdK9DoTil9PIHlPIZw2EcRJXRvw==", "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
"requires": { "requires": {
"follow-redirects": "^1.10.0" "follow-redirects": "^1.10.0"
}, },
...@@ -15446,6 +16443,11 @@ ...@@ -15446,6 +16443,11 @@
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
"integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="
}, },
"blueimp-md5": {
"version": "2.18.0",
"resolved": "https://registry.npmjs.org/blueimp-md5/-/blueimp-md5-2.18.0.tgz",
"integrity": "sha512-vE52okJvzsVWhcgUHOv+69OG3Mdg151xyn41aVQN/5W5S+S43qZhxECtYLAEHMSFWX6Mv5IZrzj3T5+JqXfj5Q=="
},
"bn.js": { "bn.js": {
"version": "5.1.3", "version": "5.1.3",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz",
...@@ -15921,6 +16923,25 @@ ...@@ -15921,6 +16923,25 @@
"safe-buffer": "^5.0.1" "safe-buffer": "^5.0.1"
} }
}, },
"ckeditor5": {
"version": "27.0.0",
"resolved": "https://registry.npmjs.org/ckeditor5/-/ckeditor5-27.0.0.tgz",
"integrity": "sha512-KjAjA/K5sNZ2UOaD3qxYiEv23TUdsZdNgDSMUiMjaFNv7bkoPZ4p8fEM4squzzB6VupLSjDw31WmTPF7Sf0KrA==",
"requires": {
"@ckeditor/ckeditor5-clipboard": "^27.0.0",
"@ckeditor/ckeditor5-core": "^27.0.0",
"@ckeditor/ckeditor5-engine": "^27.0.0",
"@ckeditor/ckeditor5-enter": "^27.0.0",
"@ckeditor/ckeditor5-paragraph": "^27.0.0",
"@ckeditor/ckeditor5-select-all": "^27.0.0",
"@ckeditor/ckeditor5-typing": "^27.0.0",
"@ckeditor/ckeditor5-ui": "^27.0.0",
"@ckeditor/ckeditor5-undo": "^27.0.0",
"@ckeditor/ckeditor5-upload": "^27.0.0",
"@ckeditor/ckeditor5-utils": "^27.0.0",
"@ckeditor/ckeditor5-widget": "^27.0.0"
}
},
"class-utils": { "class-utils": {
"version": "0.3.6", "version": "0.3.6",
"resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz",
...@@ -16365,9 +17386,9 @@ ...@@ -16365,9 +17386,9 @@
} }
}, },
"core-js": { "core-js": {
"version": "3.8.1", "version": "3.9.0",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.8.1.tgz", "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.9.0.tgz",
"integrity": "sha512-9Id2xHY1W7m8hCl8NkhQn5CufmF/WuR30BTRewvCXc1aZd3kMECwNZ69ndLbekKfakw9Rf2Xyc+QR6E7Gg+obg==" "integrity": "sha512-PyFBJaLq93FlyYdsndE5VaueA9K5cNB7CGzeCj191YYLhkQM0gdZR2SKihM70oF0wdqKSKClv/tEBOpoRmdOVQ=="
}, },
"core-js-compat": { "core-js-compat": {
"version": "3.6.5", "version": "3.6.5",
...@@ -17067,6 +18088,22 @@ ...@@ -17067,6 +18088,22 @@
"safer-buffer": "^2.1.0" "safer-buffer": "^2.1.0"
} }
}, },
"echarts": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/echarts/-/echarts-5.0.2.tgz",
"integrity": "sha512-En0VYpc96nw2/2AZoBWPHsGi471zMublttj50kfFpYAeR4geup0Tj9iVgEXh7QYZFPnRiruDJEjcB5PXZ+BYzQ==",
"requires": {
"tslib": "2.0.3",
"zrender": "5.0.4"
},
"dependencies": {
"tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ=="
}
}
},
"ee-first": { "ee-first": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
...@@ -17080,9 +18117,9 @@ ...@@ -17080,9 +18117,9 @@
"dev": true "dev": true
}, },
"element-ui": { "element-ui": {
"version": "2.14.1", "version": "2.15.1",
"resolved": "https://registry.npmjs.org/element-ui/-/element-ui-2.14.1.tgz", "resolved": "https://registry.npmjs.org/element-ui/-/element-ui-2.15.1.tgz",
"integrity": "sha512-Uje0J12dBaXdyvt/EtuDA8diFbYTdO7uI4QCfl7zmEJmE1WxgCSVKhlRRoL8MDonO8pyNVhB4n0AFAR14g56nw==", "integrity": "sha512-TqlScAKGH97XndSScUDeEHIzL1x7yg7DvQdKPEOUdiDcyIz3y3FJJBlpHYaJT96FOn1xpIcUZb+I2FJeU9EcrQ==",
"requires": { "requires": {
"async-validator": "~1.8.1", "async-validator": "~1.8.1",
"babel-helper-vue-jsx-merge-props": "^2.0.0", "babel-helper-vue-jsx-merge-props": "^2.0.0",
...@@ -19863,9 +20900,14 @@ ...@@ -19863,9 +20900,14 @@
} }
}, },
"lodash": { "lodash": {
"version": "4.17.20", "version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
},
"lodash-es": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
}, },
"loglevel": { "loglevel": {
"version": "1.7.0", "version": "1.7.0",
...@@ -21462,9 +22504,9 @@ ...@@ -21462,9 +22504,9 @@
"integrity": "sha512-R7t6Y3fDDtcU7L4rtqwGUDP9xD64gJhIwpfjhRCTKmBoYF6SS49PIJHRJ048cse6OI7iwTwgyy2C46N9Ygoc6g==" "integrity": "sha512-R7t6Y3fDDtcU7L4rtqwGUDP9xD64gJhIwpfjhRCTKmBoYF6SS49PIJHRJ048cse6OI7iwTwgyy2C46N9Ygoc6g=="
}, },
"qs": { "qs": {
"version": "6.9.4", "version": "6.9.6",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.9.4.tgz", "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.6.tgz",
"integrity": "sha512-A1kFqHekCTM7cz0udomYUoYNWjBebHm/5wzU/XqrBRBNWectVH0QIiN+NEcZ0Dte5hvzHwbr8+XQmguPhJ6WdQ==" "integrity": "sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ=="
}, },
"query-string": { "query-string": {
"version": "4.3.4", "version": "4.3.4",
...@@ -21842,6 +22884,11 @@ ...@@ -21842,6 +22884,11 @@
"integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
"dev": true "dev": true
}, },
"resize-detector": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/resize-detector/-/resize-detector-0.3.0.tgz",
"integrity": "sha512-R/tCuvuOHQ8o2boRP6vgx8hXCCy87H1eY9V5imBYeVNyNVpuL9ciReSccLj2gDcax9+2weXy3bc8Vv+NRXeEvQ=="
},
"resize-observer-polyfill": { "resize-observer-polyfill": {
"version": "1.5.1", "version": "1.5.1",
"resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz",
...@@ -23725,6 +24772,21 @@ ...@@ -23725,6 +24772,21 @@
"resolved": "https://registry.npmjs.org/vue/-/vue-2.6.12.tgz", "resolved": "https://registry.npmjs.org/vue/-/vue-2.6.12.tgz",
"integrity": "sha512-uhmLFETqPPNyuLLbsKz6ioJ4q7AZHzD8ZVFNATNyICSZouqP2Sz0rotWQC8UNBF6VGSCs5abnKJoStA6JbCbfg==" "integrity": "sha512-uhmLFETqPPNyuLLbsKz6ioJ4q7AZHzD8ZVFNATNyICSZouqP2Sz0rotWQC8UNBF6VGSCs5abnKJoStA6JbCbfg=="
}, },
"vue-demi": {
"version": "0.7.3",
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.7.3.tgz",
"integrity": "sha512-vrzM26H4CZCXBf/eu4T8nks6o7qgziYM52myk8bg+atw4qYqpeWJf5c82W8VdmgGfSIdh9ulOOe9+GeLc3Z/8A==",
"requires": {}
},
"vue-echarts": {
"version": "6.0.0-rc.3",
"resolved": "https://registry.npmjs.org/vue-echarts/-/vue-echarts-6.0.0-rc.3.tgz",
"integrity": "sha512-B7xfwpHaOeM9+cjallrK3AW893oaeqT9Sjx7tHgwoyGdfPTq6cwDc2Hcdmjgrs/KEp+ZZXMIajXky30Wu4/TDw==",
"requires": {
"resize-detector": "^0.3.0",
"vue-demi": "^0.7.1"
}
},
"vue-eslint-parser": { "vue-eslint-parser": {
"version": "7.1.1", "version": "7.1.1",
"resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-7.1.1.tgz", "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-7.1.1.tgz",
...@@ -24678,6 +25740,21 @@ ...@@ -24678,6 +25740,21 @@
"camelcase": "^5.0.0", "camelcase": "^5.0.0",
"decamelize": "^1.2.0" "decamelize": "^1.2.0"
} }
},
"zrender": {
"version": "5.0.4",
"resolved": "https://registry.npmjs.org/zrender/-/zrender-5.0.4.tgz",
"integrity": "sha512-DJpy0yrHYY5CuH6vhb9IINWbjvBUe/56J8aH86Jb7O8rRPAYZ3M2E469Qf5B3EOIfM3o3aUrO5edRQfLJ+l1Qw==",
"requires": {
"tslib": "2.0.3"
},
"dependencies": {
"tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ=="
}
}
} }
} }
} }
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
"@babel/plugin-transform-runtime": "^7.11.5", "@babel/plugin-transform-runtime": "^7.11.5",
"@babel/preset-env": "^7.11.5", "@babel/preset-env": "^7.11.5",
"@babel/runtime-corejs3": "^7.11.2", "@babel/runtime-corejs3": "^7.11.2",
"@vue/composition-api": "^1.0.0-rc.5",
"acorn": "^7.1.1", "acorn": "^7.1.1",
"ali-oss": "^6.11.2", "ali-oss": "^6.11.2",
"autoprefixer": "^9.8.6", "autoprefixer": "^9.8.6",
...@@ -72,17 +73,21 @@ ...@@ -72,17 +73,21 @@
"webpack-merge": "^4.2.2" "webpack-merge": "^4.2.2"
}, },
"dependencies": { "dependencies": {
"@ckeditor/ckeditor5-build-classic": "^24.0.0", "@ckeditor/ckeditor5-build-classic": "^27.0.0",
"@ckeditor/ckeditor5-build-decoupled-document": "^27.0.0",
"@ckeditor/ckeditor5-vue2": "^1.0.5", "@ckeditor/ckeditor5-vue2": "^1.0.5",
"axios": "^0.21.0", "@ezijing/web-message-sdk": "^0.2.1",
"core-js": "^3.8.1", "axios": "^0.21.1",
"core-js": "^3.9.0",
"cross-env": "^7.0.3", "cross-env": "^7.0.3",
"element-ui": "^2.14.1", "echarts": "^5.0.2",
"element-ui": "^2.15.1",
"js-cookie": "^2.2.1", "js-cookie": "^2.2.1",
"lodash": "^4.17.20", "lodash": "^4.17.21",
"qrcode.vue": "^1.7.0", "qrcode.vue": "^1.7.0",
"qs": "^6.9.4", "qs": "^6.9.6",
"vue": "^2.6.12", "vue": "^2.6.12",
"vue-echarts": "^6.0.0-rc.3",
"vue-i18n": "^8.22.2", "vue-i18n": "^8.22.2",
"vue-loader": "^15.9.5", "vue-loader": "^15.9.5",
"vue-meta": "^2.4.0", "vue-meta": "^2.4.0",
......
...@@ -74,6 +74,7 @@ export default class CourseAction extends BaseACTION { ...@@ -74,6 +74,7 @@ export default class CourseAction extends BaseACTION {
: (_type === 2 ? _vIn.$t('action.courseAction.changeLearn') : (_type === 2 ? _vIn.$t('action.courseAction.changeLearn')
: (_type === 3 ? _vIn.$t('action.courseAction.repeatLearn') : '')) : (_type === 3 ? _vIn.$t('action.courseAction.repeatLearn') : ''))
const json = { const json = {
course_check_type: cur.course_check_type,
headerInfo: { headerInfo: {
isStart: !!cur.selected, // 是否为开始学习按钮 或者 选课按钮 isStart: !!cur.selected, // 是否为开始学习按钮 或者 选课按钮
id: cur.course_id, id: cur.course_id,
...@@ -183,7 +184,7 @@ export default class CourseAction extends BaseACTION { ...@@ -183,7 +184,7 @@ export default class CourseAction extends BaseACTION {
} }
}) })
} }
json.tabs1ChapterList.course.push({ cur.curriculum.curriculum_essay && json.tabs1ChapterList.course.push({
title: _vIn.$t('action.courseAction.courseWork'), title: _vIn.$t('action.courseAction.courseWork'),
isUp: true, isUp: true,
chapters: [], chapters: [],
...@@ -287,6 +288,7 @@ export default class CourseAction extends BaseACTION { ...@@ -287,6 +288,7 @@ export default class CourseAction extends BaseACTION {
}) })
} }
const json = { const json = {
raw: cur,
score: cur.course_score, score: cur.course_score,
duration: tool.convertTime.durationToTimeString(cur.course_duration || 0), duration: tool.convertTime.durationToTimeString(cur.course_duration || 0),
progress: cur.course_progress, progress: cur.course_progress,
......
...@@ -9,26 +9,7 @@ import { Grade } from '@api' ...@@ -9,26 +9,7 @@ import { Grade } from '@api'
export default class GradeAction extends BaseACTION { export default class GradeAction extends BaseACTION {
/* 获取我的学分信息 */ /* 获取我的学分信息 */
getCredit () { getCredit () { return Grade.getCredit() }
return Grade.getCredit().then(res => {
const _data = res
const json = {
total: _data.total_credits,
myTotal: _data.my_total_credits,
myTotalStr: (_data.total_credits && ((_data.my_total_credits * 1.0 / _data.total_credits * 100).toFixed(1) + '%')) || '0%',
must: _data.required_credits,
myMust: _data.my_required_credits,
myMustStr: (_data.required_credits && ((_data.my_required_credits * 1.0 / _data.required_credits * 100).toFixed(1) + '%')) || '0%',
unmust: _data.optional_credits,
myUnmust: _data.my_optional_credits,
myUnmustStr: (_data.optional_credits && ((_data.my_optional_credits * 1.0 / _data.optional_credits * 100).toFixed(1) + '%')) || '0%',
list: _data.lists
}
// callback(json) // 可以不使用callback 因为使用then
return json
})
}
/* 提交重修 */ /* 提交重修 */
rebuildSubmit (obj) { return Grade.submitRebuild(obj).then(res => res) } rebuildSubmit (obj) { return Grade.submitRebuild(obj).then(res => res) }
/* 意见反馈列表 */ /* 意见反馈列表 */
......
import BaseAPI from '@/api/base_api'
const httpRequest = new BaseAPI(webConf)
/**
* 获取课程详情
* @param {string} semesterId 学期ID
* @param {string} courseId 课程ID
*/
export function getCourse(semesterId, courseId) {
return httpRequest.get(`/api/lms/v2/education/courses/${semesterId}/${courseId}`)
}
/**
* 课程考核
* @param {string} semesterId 学期ID
* @param {string} courseId 课程ID
*/
export function getCourseAssess(semesterId, courseId) {
return httpRequest.get(`/api/lms/v2/analytics/courses/${semesterId}/${courseId}/evaluation`).then(res => {
// 视频数据组装
let videoList = Object.values(res.video_evaluation)
videoList = videoList.map(item => {
item.sections = Object.values(item.sections)
return item
})
res.video_evaluation = videoList
// 作业数据组装
let homeworkList = Object.values(res.homework_evaluation)
homeworkList = homeworkList.map(item => {
item.sections = Object.values(item.sections)
return item
})
res.homework_evaluation = homeworkList
return res
})
}
import BaseAPI from '@/api/base_api'
const httpRequest = new BaseAPI(webConf)
/**
* 获取课程详情
* @param {string} semesterId 学期ID
* @param {string} courseId 课程ID
*/
export function getCourse(semesterId, courseId) {
return httpRequest.get(`/api/lms/v2/education/courses/${semesterId}/${courseId}`)
}
/**
* 获取讨论题目列表,“我提出的问题”和“我参与的问题”信息
* dataJson.limit - 获取数量
* dataJson.offset - 偏移量
* @param {[string]} path
* @param {[object]} dataJson
*/
export function getDiscussList(qid, params) {
return httpRequest.get(`/api/lms/v2/qa/questions/${qid}`, params)
}
/**
* 获取讨论题目列表,“课程的问题”信息
* dataJson.limit - 获取数量
* dataJson.offset - 偏移量
* dataJson.sort - 排序类型
* @param {[string]} cid
* @param {[string]} sid
* @param {[object]} dataJson
*/
export function getCourseDiscussList(sid, cid, params) {
return httpRequest.get(`/api/lms/v2/qa/questions/course/${sid}/${cid}`, { params })
}
/**
* 获取问题详情
* @param {[string]} qid
*/
export function getDiscussDetail(qid) {
return httpRequest.get(`/api/lms/v2/qa/questions/${qid}`, {})
}
/**
* 删除提问
* @param {[string]} qid
*/
export function deleteDiscuss(qid) {
return httpRequest.delete(`/api/lms/v2/qa/questions/${qid}`, {})
}
/**
* 提出问题
* @param {[object]} param
*/
export function publishQues(param) {
return httpRequest.post('/api/lms/v2/qa/questions', param, { headers: { 'Content-Type': 'application/json' } })
}
/**
* 回答问题
* @param {[object]} param
*/
export function answerQues(param) {
return httpRequest.post('/api/lms/v2/qa/answers', param, { headers: { 'Content-Type': 'application/json' } })
}
/**
* 删除回答
* @param {[string]} aid
*/
export function deleteAnswer(aid) {
return httpRequest.delete(`/api/lms/v2/qa/answers/${aid}`, {})
}
/**
* 回复评论
* @param {[object]} param
*/
export function callbackComment(param) {
return httpRequest.post('/api/lms/v2/qa/comments', param, { headers: { 'Content-Type': 'application/json' } })
}
/**
* 删除评论
* @param {[string]} cid
*/
export function deleteComment(cid) {
return httpRequest.delete(`/api/lms/v2/qa/comments/${cid}`)
}
/**
* 点赞
* @param {[object]} param
*/
export function like(param) {
return httpRequest.post('/api/lms/v2/qa/tags', param, { headers: { 'Content-Type': 'application/json' } })
}
/**
* 取消点赞
* @param {[string]} tagid
*/
export function unlike(tagid) {
return httpRequest.delete(`/api/lms/v2/qa/tags/${tagid}`, {})
}
<template>
<div class="app-container">
<div class="app-container-hd" v-if="title">
<div class="app-container-hd__title">{{ title }}</div>
<div class="app-container-hd__right">
<slot name="header-right"></slot>
</div>
</div>
<div class="app-container-bd">
<slot></slot>
</div>
<slot name="footer"></slot>
</div>
</template>
<script>
export default {
name: 'AppContainer',
props: { title: { type: String } }
}
</script>
<style lang="scss">
.app-container {
clear: both;
}
.app-container-hd {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 30px;
margin-bottom: 20px;
border-bottom: 1px solid #ccc;
}
.app-container-hd__title {
font-size: 16px;
line-height: 45px;
}
.app-container-bd {
margin: 0.3rem;
}
.app-container-ft {
background-color: #fff;
position: sticky;
bottom: 0;
padding-top: 30px;
border-top: 1px solid #ccc;
}
</style>
...@@ -13,8 +13,13 @@ ...@@ -13,8 +13,13 @@
<script> <script>
import CKEditor from '@ckeditor/ckeditor5-vue2' import CKEditor from '@ckeditor/ckeditor5-vue2'
import ClassicEditor from '@ckeditor/ckeditor5-build-classic'
import '@ckeditor/ckeditor5-build-classic/build/translations/zh-cn' import DecoupledEditor from '@ckeditor/ckeditor5-build-decoupled-document'
import '@ckeditor/ckeditor5-build-decoupled-document/build/translations/zh-cn'
// import ClassicEditor from '@ckeditor/ckeditor5-build-classic'
// import '@ckeditor/ckeditor5-build-classic/build/translations/zh-cn'
import MyUploadAdapter from './MyUploadAdapter' import MyUploadAdapter from './MyUploadAdapter'
export default { export default {
...@@ -27,14 +32,20 @@ export default { ...@@ -27,14 +32,20 @@ export default {
}, },
data() { data() {
return { return {
editor: ClassicEditor, editor: DecoupledEditor,
editorConfig: { editorConfig: {
language: this.$i18n.locale.toLocaleLowerCase() language: this.$i18n.locale.toLocaleLowerCase(),
fontFamily: { options: ['default', '宋体', 'Times New Roman'] },
fontSize: { options: ['12px', '14px', '16px', '18px', '20px', '24px', '36px'] }
} }
} }
}, },
methods: { methods: {
onEditorReady(editor) { onEditorReady(editor) {
editor.ui
.getEditableElement()
.parentElement.insertBefore(editor.ui.view.toolbar.element, editor.ui.getEditableElement())
const FileRepository = editor.plugins.get('FileRepository') const FileRepository = editor.plugins.get('FileRepository')
// 自定义上传图片插件 // 自定义上传图片插件
FileRepository.createUploadAdapter = loader => { FileRepository.createUploadAdapter = loader => {
...@@ -43,6 +54,22 @@ export default { ...@@ -43,6 +54,22 @@ export default {
}, },
onEditorInput(value) { onEditorInput(value) {
this.$emit('input', value) this.$emit('input', value)
this.dispatch('ElFormItem', 'el.form.change', value)
},
dispatch(componentName, eventName, params) {
var parent = this.$parent || this.$root
var name = parent.$options.componentName
while (parent && (!name || name !== componentName)) {
parent = parent.$parent
if (parent) {
name = parent.$options.componentName
}
}
if (parent) {
parent.$emit.apply(parent, [eventName].concat(params))
}
} }
} }
} }
...@@ -53,6 +80,8 @@ export default { ...@@ -53,6 +80,8 @@ export default {
min-height: 300px; min-height: 300px;
max-height: 500px; max-height: 500px;
word-break: break-word; word-break: break-word;
background: var(--ck-color-base-background);
border: 1px solid var(--ck-color-toolbar-border) !important;
} }
.ck-sticky-panel__content { .ck-sticky-panel__content {
position: unset !important; position: unset !important;
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
<div class="text-title" @click="setStatus">{{ $t('components.learnSysLayout.navigation.title') }}</div> <div class="text-title" @click="setStatus">{{ $t('components.learnSysLayout.navigation.title') }}</div>
</div> </div>
<div class="nav-right"> <div class="nav-right">
<div class="nav-message"></div>
<div class="notify" @click="goNotify()"> <div class="notify" @click="goNotify()">
{{ $t('components.learnSysLayout.navigation.tip') }} {{ $t('components.learnSysLayout.navigation.tip') }}
<div class="num" v-if="this.$store.getters.myMsg != 0">{{ this.$store.getters.myMsg }}</div> <div class="num" v-if="this.$store.getters.myMsg != 0">{{ this.$store.getters.myMsg }}</div>
...@@ -17,7 +18,7 @@ ...@@ -17,7 +18,7 @@
<script> <script>
import LanguageSwitch from '@/components/languageSwitch/index.vue' import LanguageSwitch from '@/components/languageSwitch/index.vue'
import cAction from '../../action' import cAction from '../../action'
// import Message from '@ezijing/web-message-sdk'
export default { export default {
components: { LanguageSwitch }, components: { LanguageSwitch },
data() { data() {
...@@ -33,7 +34,8 @@ export default { ...@@ -33,7 +34,8 @@ export default {
.catch(e => { .catch(e => {
this.$message.error(e.message) this.$message.error(e.message)
}) })
.finally(() => {}) // 新版通知
// Message({ container: '.nav-message', source: 'SOFIA_WEB', baseURL: webConf.others.messageBaseURL })
}, },
methods: { methods: {
goNotify() { goNotify() {
......
<template>
<div>
<div ref="box" :class="classes">
<slot></slot>
</div>
<div class="block-control" @click="toggle" v-if="hasMore">
<template v-if="isOpen"> <i class="el-icon-caret-top"></i><span>收起</span> </template>
<template v-else> <i class="el-icon-caret-bottom"></i><span>展开</span> </template>
</div>
</div>
</template>
<script>
export default {
data() {
return {
max: 300,
hasMore: false,
isOpen: false
}
},
computed: {
classes() {
return {
'has-more': this.hasMore && !this.isOpen
}
}
},
methods: {
init() {
const height = this.$refs.box.offsetHeight
this.hasMore = height > this.max
},
toggle() {
this.isOpen = !this.isOpen
}
},
mounted() {
this.init()
}
}
</script>
<style lang="scss">
.block-control {
height: 20px;
display: flex;
align-items: center;
justify-content: center;
margin-top: 10px;
padding-top: 5px;
color: #d3dce6;
cursor: pointer;
border-top: 1px solid #eaeefb;
i {
font-size: 16px;
}
span {
display: none;
padding-left: 5px;
font-size: 12px;
}
&:hover {
color: #1f2f3d;
span {
display: block;
}
}
}
.has-more {
max-height: 300px;
overflow: hidden;
}
</style>
<template>
<editor v-bind="options" />
</template>
<script>
import Editor from '@tinymce/tinymce-vue'
export default {
components: {
editor: Editor
},
data() {
return {
options: {
init: {
min_height: 300,
max_height: 500,
menubar: false,
language: this.$i18n.locale.replace('-', '_'),
branding: false,
plugins: 'wordcount table autoresize charmap code fullscreen hr lists codesample',
toolbar:
'undo redo | removeformat formats | fontselect fontsizeselect lineheight bold italic underline strikethrough forecolor backcolor | link image | align indent outdent numlist bullist | charmap table blockquote hr codesample fullscreen',
fontsize_formats: '12px 14px 15px 16px 17px 18px 20px 24px',
lineheight_formats: '0.5 1 1.2 1.5 2'
}
}
}
}
}
</script>
...@@ -8,9 +8,7 @@ const httpRequest = new BaseAPI(webConf) ...@@ -8,9 +8,7 @@ const httpRequest = new BaseAPI(webConf)
* @param {string} courseId 课程ID * @param {string} courseId 课程ID
*/ */
export function getCourse(semesterId, courseId) { export function getCourse(semesterId, courseId) {
return httpRequest.get( return httpRequest.get(`/api/lms/v2/education/courses/${semesterId}/${courseId}`)
`/api/lms/v2/education/courses/${semesterId}/${courseId}`
)
} }
/** /**
...@@ -44,10 +42,7 @@ export function getChapterVideoAliyun(vid) { ...@@ -44,10 +42,7 @@ export function getChapterVideoAliyun(vid) {
* @param {Object} params * @param {Object} params
*/ */
export function getChapterVideoProgress(semesterId, resourseId, params) { export function getChapterVideoProgress(semesterId, resourseId, params) {
return httpRequest.get( return httpRequest.get(`/api/lms/v2/education/video/${semesterId}/${resourseId}/device`, params)
`/api/lms/v2/education/video/${semesterId}/${resourseId}/device`,
params
)
} }
/** /**
...@@ -65,9 +60,7 @@ export function updateChapterVideoProgress(params) { ...@@ -65,9 +60,7 @@ export function updateChapterVideoProgress(params) {
* @param {string} resourseId 章节的资源ID * @param {string} resourseId 章节的资源ID
*/ */
export function getChapterHomework(semesterId, courseId, resourseId) { export function getChapterHomework(semesterId, courseId, resourseId) {
return httpRequest.get( return httpRequest.get(`/api/lms/v2/education/homeworks/${semesterId}/${courseId}/${resourseId}`)
`/api/lms/v2/education/homeworks/${semesterId}/${courseId}/${resourseId}`
)
} }
/** /**
...@@ -77,9 +70,7 @@ export function getChapterHomework(semesterId, courseId, resourseId) { ...@@ -77,9 +70,7 @@ export function getChapterHomework(semesterId, courseId, resourseId) {
* @param {string} chapterId 章节ID * @param {string} chapterId 章节ID
*/ */
export function getChapterHomeworkDeadline(semesterId, courseId, chapterId) { export function getChapterHomeworkDeadline(semesterId, courseId, chapterId) {
return httpRequest.get( return httpRequest.get(`/api/lms/v2/education/homeworks/${semesterId}/${courseId}/${chapterId}/deadline`)
`/api/lms/v2/education/homeworks/${semesterId}/${courseId}/${chapterId}/deadline`
)
} }
/** /**
...@@ -106,9 +97,7 @@ export function uploadFile(data) { ...@@ -106,9 +97,7 @@ export function uploadFile(data) {
* @param {string} courseId 课程ID * @param {string} courseId 课程ID
*/ */
export function getCourseWork(semesterId, courseId) { export function getCourseWork(semesterId, courseId) {
return httpRequest.get( return httpRequest.get(`/api/lms/v2/education/courses/${semesterId}/${courseId}/essay`)
`/api/lms/v2/education/courses/${semesterId}/${courseId}/essay`
)
} }
/** /**
...@@ -117,11 +106,9 @@ export function getCourseWork(semesterId, courseId) { ...@@ -117,11 +106,9 @@ export function getCourseWork(semesterId, courseId) {
* @param {string} courseId 课程ID * @param {string} courseId 课程ID
*/ */
export function updateCourseWork(semesterId, courseId, data) { export function updateCourseWork(semesterId, courseId, data) {
return httpRequest.post( return httpRequest.post(`/api/lms/v2/education/courses/${semesterId}/${courseId}/essay`, data, {
`/api/lms/v2/education/courses/${semesterId}/${courseId}/essay`, headers: { 'Content-Type': 'multipart/form-data' }
data, })
{ headers: { 'Content-Type': 'multipart/form-data' } }
)
} }
/** /**
...@@ -130,9 +117,7 @@ export function updateCourseWork(semesterId, courseId, data) { ...@@ -130,9 +117,7 @@ export function updateCourseWork(semesterId, courseId, data) {
* @param {string} courseId 课程ID * @param {string} courseId 课程ID
*/ */
export function getCourseExam(semesterId, courseId) { export function getCourseExam(semesterId, courseId) {
return httpRequest.get( return httpRequest.get(`/api/lms/v2/education/${semesterId}/${courseId}/examination`)
`/api/lms/v2/education/${semesterId}/${courseId}/examination`
)
} }
/** /**
...@@ -142,9 +127,7 @@ export function getCourseExam(semesterId, courseId) { ...@@ -142,9 +127,7 @@ export function getCourseExam(semesterId, courseId) {
* @param {string} examId 试题ID * @param {string} examId 试题ID
*/ */
export function getCourseExamStatus(semesterId, courseId, examId) { export function getCourseExamStatus(semesterId, courseId, examId) {
return httpRequest.get( return httpRequest.get(`/api/lms/v2/education/${semesterId}/${courseId}/examination/${examId}/status`)
`/api/lms/v2/education/${semesterId}/${courseId}/examination/${examId}/status`
)
} }
/** /**
...@@ -154,11 +137,9 @@ export function getCourseExamStatus(semesterId, courseId, examId) { ...@@ -154,11 +137,9 @@ export function getCourseExamStatus(semesterId, courseId, examId) {
* @param {string} examId 试题ID * @param {string} examId 试题ID
*/ */
export function submitCourseExam(semesterId, courseId, examId, data) { export function submitCourseExam(semesterId, courseId, examId, data) {
return httpRequest.post( return httpRequest.post(`/api/lms/v2/education/${semesterId}/${courseId}/examination/${examId}/sheet`, data, {
`/api/lms/v2/education/${semesterId}/${courseId}/examination/${examId}/sheet`, headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
data, })
{ headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }
)
} }
/** /**
...@@ -168,8 +149,32 @@ export function submitCourseExam(semesterId, courseId, examId, data) { ...@@ -168,8 +149,32 @@ export function submitCourseExam(semesterId, courseId, examId, data) {
* @param {string} examId 试题ID * @param {string} examId 试题ID
*/ */
export function getCourseExamResult(semesterId, courseId, examId, params) { export function getCourseExamResult(semesterId, courseId, examId, params) {
return httpRequest.get( return httpRequest.get(`/api/lms/v2/education/${semesterId}/${courseId}/examination/${examId}/sheet`, params)
`/api/lms/v2/education/${semesterId}/${courseId}/examination/${examId}/sheet`, }
params
) /**
* 获取课后评论作业
* @param {string} semesterId 学期ID
* @param {string} courseId 课程ID
* @param {string} chapterId 章节ID
*/
export function getChapterHomeworkOther(semesterId, courseId, chapterId, params) {
return httpRequest.get(`/api/lms/v2/education/homeworks/other/${semesterId}/${courseId}/${chapterId}`, params)
}
/**
* 获取课后课业回答
* @param {string} semesterId 学期ID
* @param {string} courseId 课程ID
* @param {string} chapterId 章节ID
*/
export function getChapterHomeworkOtherAll(semesterId, courseId, chapterId, params) {
return httpRequest.get(`/api/lms/v2/education/homeworks/otherall/${semesterId}/${courseId}/${chapterId}`, params)
}
/**
* 提交作业互评
*/
export function addChapterHomeworkComment(data) {
return httpRequest.post('/api/lms/v2/education/homeworks/comment', data)
} }
...@@ -60,15 +60,15 @@ export default { ...@@ -60,15 +60,15 @@ export default {
if (data.type === 1) { if (data.type === 1) {
return return
} }
// zoom直播 // 5:CC直播; 6:腾讯会议; 8:Zoom
if (data.type === 8) {
const live = data.live const live = data.live
if ([6, 8].includes(data.type) && live) {
const hasRecordUrl = live.enable_record && live.record_url const hasRecordUrl = live.enable_record && live.record_url
if ([3, 5].includes(live.live_status) && !hasRecordUrl) { if ([3, 5].includes(live.live_status) && !hasRecordUrl) {
this.$message.error(this.$t('viewerMain.liveEnd')) this.$message.error(this.$t('viewerMain.liveEnd'))
return return
} }
window.open(live.record_url || live.join_url) window.open(live.record_url || live.join_url, '_blank')
return return
} }
// 课程大作业 // 课程大作业
......
<template> <template>
<div class="upload"> <div class="upload">
<el-upload action :disabled="disabled" :show-file-list="false" :http-request="httpRequest"> <el-upload action :disabled="disabled" :show-file-list="false" :http-request="httpRequest" v-bind="$attrs">
<slot></slot> <slot></slot>
<el-button type="text" icon="el-icon-upload">{{ $t('viewerWork.clickUpload') }}</el-button> <el-button type="text" icon="el-icon-upload">{{ $t('viewerWork.clickUpload') }}</el-button>
<template v-slot:tip> <template v-slot:tip>
......
<template> <template>
<container :title="chapter.name" v-loading="loading"> <div>
<container :title="chapter.name" v-loading="loading" id="work">
<template v-slot:header-aside v-if="isRevised">
<p v-if="hasScore">{{ $t('viewerWork.score') }}{{ detail.score }}{{ $t('viewerWork.fractionUnit') }}</p>
</template>
<div class="exam-form"> <div class="exam-form">
<el-form :disabled="disabled || !isWorkTime"> <template v-for="(item, index) in questions">
<el-form :disabled="disabled" :key="item.id" ref="form" :model="item.formModel" :rules="rules">
<el-form-item prop="user_answer">
<exam-item <exam-item
v-for="(item, index) in questions"
:index="index" :index="index"
:type="item.question_type" :type="item.question_type"
:data="item" :data="item"
:value="item.formModel" :value="item.formModel"
:disabled="disabled || !isWorkTime" :disabled="disabled"
:key="item.id" :hasUpload="hasUpload"
></exam-item> ></exam-item>
</el-form-item>
</el-form> </el-form>
</template>
</div> </div>
<p style="color: red" v-if="deadline">{{ $t('viewerWork.deadline', { deadline }) }}</p> <p style="color: red" v-if="deadline && detail.status !== 1">
{{ $t('viewerWork.deadline', { date: deadline }) }}
</p>
<!-- 驳回状态 --> <!-- 驳回状态 -->
<template v-if="detail && detail.status === 1"> <template v-if="detail.status === 8">
<div class="work-bottom"> <div class="work-bottom">
<div class="info"> <div class="info">
<div class="paper-check"> <div class="paper-check">
...@@ -32,12 +41,12 @@ ...@@ -32,12 +41,12 @@
</div> </div>
</div> </div>
<div class="buttons"> <div class="buttons">
<el-button type="primary" @click="onReEdit" :disabled="!isWorkTime">{{ $t('viewerWork.reEdit') }}</el-button> <el-button type="primary" @click="onReEdit">{{ $t('viewerWork.reEdit') }}</el-button>
</div> </div>
</template> </template>
<!-- 正常状态 --> <!-- 正常状态 -->
<template v-else> <template v-else>
<div class="work-bottom" v-if="detail"> <div class="work-bottom" v-if="detail.status !== 1">
<div class="info"> <div class="info">
<template v-if="isRevised"> <template v-if="isRevised">
<div class="paper-check"> <div class="paper-check">
...@@ -62,13 +71,49 @@ ...@@ -62,13 +71,49 @@
</div> </div>
<div class="buttons"> <div class="buttons">
<el-tooltip :content="$t('viewerWork.workSubmitButtonTips')" placement="right"> <el-tooltip :content="$t('viewerWork.workSubmitButtonTips')" placement="right">
<el-button type="primary" :disabled="disabled || !isWorkTime" :loading="submitLoading" @click="onSubmit">{{ <el-button type="primary" :disabled="disabled" :loading="submitLoading" @click="onSubmit">{{
submitText submitText
}}</el-button> }}</el-button>
</el-tooltip> </el-tooltip>
<!-- 驳回 -->
<template v-if="detail.status === 1">
<span>提交后不可修改,请检查好作业内容再做提交。</span>
</template>
<template v-else>
<span v-if="hasComment">{{ $t('viewerWork.commentTips') }}</span>
</template>
</div> </div>
</template> </template>
</container> </container>
<chapter-work-comment
:endDate="commentEndDate"
:status="detail.status2"
@update="getDetail"
v-if="showComment"
id="comment"
/>
<el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="500px">
<div class="paper-check-item">
<p>您本次的作业被老师驳回,请您重新编辑作业提交!</p>
</div>
<div class="paper-check-item">
<span>{{ $t('viewerWork.rejectTime') }}</span>
{{ detail.checker_time }}
</div>
<div class="paper-check-item">
<span>{{ $t('viewerWork.rejectContent') }}</span>
<div class="edit_html" v-html="detail.check_comments"></div>
</div>
<template #footer>
<div style="text-align: center">
<el-button type="primary" @click="onReEdit">重新编辑</el-button>
<p style="margin-top: 16px; color: #f00">注:重新提交后不可修改,请检查好作业内容再做提交。</p>
</div>
</template>
</el-dialog>
</div>
</template> </template>
<script> <script>
...@@ -77,13 +122,14 @@ import Base64 from 'Base64' ...@@ -77,13 +122,14 @@ import Base64 from 'Base64'
// componets // componets
import Container from '../common/container.vue' import Container from '../common/container.vue'
import ExamItem from './examItem.vue' import ExamItem from './examItem.vue'
import ChapterWorkComment from './chapterWorkComment.vue'
// api // api
import * as api from '../../api' import * as api from '../../api'
// 章节作业 // 章节作业
export default { export default {
name: 'ChapterWork', name: 'ChapterWork',
components: { Container, ExamItem }, components: { Container, ExamItem, ChapterWorkComment },
props: { props: {
// 当前选中的 // 当前选中的
chapter: { chapter: {
...@@ -103,13 +149,21 @@ export default { ...@@ -103,13 +149,21 @@ export default {
data() { data() {
return { return {
loading: false, loading: false,
detail: null, detail: {},
questions: [], // 问题列表 questions: [], // 问题列表
startTime: new Date().getTime(), // 进入时间 startTime: new Date().getTime(), // 进入时间
messageInstance: null, messageInstance: null,
deadline: '', // 截止时间 deadline: '', // 截止时间
disabled: false, submitLoading: false,
submitLoading: false hasUpload: true, // 是否可以上传
isAnonymous: false, // 是否匿名
hasComment: false, // 是否评论
commentEndDate: '',
rules: {
user_answer: [{ required: true, message: '请输入', trigger: 'change' }]
},
dialogVisible: false,
popoverVisible: false
} }
}, },
watch: { watch: {
...@@ -141,7 +195,7 @@ export default { ...@@ -141,7 +195,7 @@ export default {
}, },
// 是否批改 // 是否批改
isRevised() { isRevised() {
return this.detail ? this.detail.status === 0 : false return this.detail.status === 0
}, },
// 提交按钮文本 // 提交按钮文本
submitText() { submitText() {
...@@ -159,7 +213,31 @@ export default { ...@@ -159,7 +213,31 @@ export default {
}, },
hasScore() { hasScore() {
// allow_score 1 显示 2隐藏 // allow_score 1 显示 2隐藏
return this.detail.allow_score !== 2 return this.detail.allow_score !== 2 && this.detail.score
},
// 显示作业评论
showComment() {
const currentTime = new Date().getTime()
const endTime = +new Date(this.deadline)
return this.hasComment && currentTime > endTime
},
disabled() {
if (this.detail.status === 1) {
return false
}
// -1未处理 0已处理 1驳回
return this.detail.status === 0 || !this.isWorkTime
},
dialogTitle() {
if (this.detail.status === 1 && this.detail.status2 === 1) {
return '作业、互评作业驳回'
}
if (this.detail.status === 1) {
return '作业驳回'
}
if (this.detail.status2 === 1) {
return '互评作业驳回'
}
} }
}, },
methods: { methods: {
...@@ -167,6 +245,10 @@ export default { ...@@ -167,6 +245,10 @@ export default {
getDeadline() { getDeadline() {
api.getChapterHomeworkDeadline(this.sid, this.cid, this.pid).then(response => { api.getChapterHomeworkDeadline(this.sid, this.cid, this.pid).then(response => {
this.deadline = response.dead_line this.deadline = response.dead_line
this.hasUpload = !!response.pdf
this.isAnonymous = !!response.anonymous
this.hasComment = !!response.comment
this.commentEndDate = response.comment_end
}) })
}, },
// 获取详情 // 获取详情
...@@ -175,10 +257,14 @@ export default { ...@@ -175,10 +257,14 @@ export default {
api api
.getChapterHomework(this.sid, this.cid, this.resourceId) .getChapterHomework(this.sid, this.cid, this.resourceId)
.then(response => { .then(response => {
this.detail = Array.isArray(response) ? null : response this.detail = Array.isArray(response) ? {} : response
if (this.detail) { if (
// -1未处理 0已处理 1驳回 (this.detail.status === 1 || this.detail.status2 === 1) &&
this.disabled = [0, 1].includes(this.detail.status) !([-1, -2].includes(this.detail.status) || [-1, -2].includes(this.detail.status2))
) {
this.dialogVisible = true
}
if (this.detail.id) {
const parseAnswers = JSON.parse(this.detail.work_contents) const parseAnswers = JSON.parse(this.detail.work_contents)
// 设置答案 // 设置答案
this.questions = this.questions.map(item => { this.questions = this.questions.map(item => {
...@@ -236,14 +322,16 @@ export default { ...@@ -236,14 +322,16 @@ export default {
}, },
// 提交校验 // 提交校验
checkSubmit() { checkSubmit() {
const questions = this.questions let result = true
for (let i = 0; i < questions.length; i++) { for (let i = 0; i < this.questions.length; i++) {
const value = questions[i].formModel.user_answer this.$refs.form[i].validate(valid => {
if (Array.isArray(value) ? !value.length : !value) { if (!valid) {
return false result = valid
return result
} }
})
} }
return true return result
}, },
// 提交 // 提交
onSubmit() { onSubmit() {
...@@ -253,6 +341,18 @@ export default { ...@@ -253,6 +341,18 @@ export default {
this.messageInstance = this.$message.error(this.$t('viewerWork.examSubmitError')) this.messageInstance = this.$message.error(this.$t('viewerWork.examSubmitError'))
return return
} }
// 驳回提交
if (this.detail.status === 1) {
this.$confirm('本次作业提交后不可修改,您确认提交吗?', '提示', {
confirmButtonText: '确定提交',
type: 'warning'
}).then(this.handleSubmit)
} else {
// 正常提交
this.handleSubmit()
}
},
handleSubmit() {
// 计算答题时间 // 计算答题时间
const duration = Math.floor((new Date().getTime() - this.startTime) / 1000) const duration = Math.floor((new Date().getTime() - this.startTime) / 1000)
// 提交的答案数据 // 提交的答案数据
...@@ -299,8 +399,14 @@ export default { ...@@ -299,8 +399,14 @@ export default {
}, },
// 重新编辑 // 重新编辑
onReEdit() { onReEdit() {
this.disabled = false this.dialogVisible = false
this.detail.status = -1 if (this.detail.status === 1) {
window.location.hash = '#work'
return
}
if (this.detail.status2 === 1) {
window.location.hash = '#comment'
}
} }
}, },
beforeMount() { beforeMount() {
...@@ -333,8 +439,10 @@ export default { ...@@ -333,8 +439,10 @@ export default {
} }
} }
.paper-check-item { .paper-check-item {
padding: 5px 0;
display: flex; display: flex;
b { b,
span {
white-space: nowrap; white-space: nowrap;
} }
} }
......
<template>
<div class="chatper-work-answer-item">
<div class="chapter-work-answer-item-hd">{{ nickname }}:</div>
<div class="chapter-work-answer-item-bd">
<div class="item" v-for="item in workList" :key="item.question_id">
<show-more>
<div v-html="decode(item.descreption)"></div>
<a :href="item.file_url" target="_blank" class="file" v-if="item.file_url">
<i class="el-icon-document"></i>
{{ $t('viewerWork.downloadName') }}
</a>
</show-more>
</div>
</div>
<slot />
</div>
</template>
<script>
import Base64 from 'Base64'
import showMore from '@/components/showMore'
export default {
props: {
index: { type: Number, default: 0 },
data: { type: Object, default: () => ({}) }
},
components: { showMore },
data() {
return {}
},
computed: {
// 作业列表
workList() {
return this.data.work_contents ? JSON.parse(this.data.work_contents) : []
},
nickname() {
const name = this.data.personal_name
return name ? name + this.$t('viewerWork.student') : this.$t('viewerWork.student') + (this.index + 1)
}
},
methods: {
decode(value) {
return value ? Base64.decode(value) : ''
}
}
}
</script>
<style lang="scss">
.chatper-work-answer-item {
// padding-bottom: 10px;
// border-bottom: 1px solid #c9c9c97a;
margin-bottom: 20px;
.item {
padding: 10px;
border-radius: 8px;
background-color: #fff;
}
.item + .item {
margin-top: 10px;
}
.file {
display: inline-block;
margin-bottom: 10px;
text-decoration: none;
color: #333;
&:hover {
color: #b49441;
}
}
}
.chapter-work-answer-item-hd {
margin-bottom: 10px;
}
.chapter-work-answer-item-bd {
img {
max-width: 100%;
}
}
</style>
<template>
<container :title="$t('viewerWork.submittedAssignments')">
<chapter-work-answer-item v-for="(item, index) in list" :data="item" :key="item.id" :index="index" />
<el-pagination
background
layout="prev, pager, next"
:current-page.sync="page.currentPage"
:page-size="page.limit"
:total="page.total"
:hide-on-single-page="true"
@current-change="handleCurrentChange"
style="margin: 0 auto; padding: 40px 0; text-align: center"
></el-pagination>
</container>
</template>
<script>
// api
import * as api from '../../api'
// componets
import Container from '../common/container.vue'
import chapterWorkAnswerItem from './chapterWorkAnswerItem.vue'
export default {
components: { Container, chapterWorkAnswerItem },
data() {
return {
list: [],
page: {
offset: 0,
total: 0,
currentPage: 1,
limit: 10
}
}
},
computed: {
// 学期ID
sid() {
return this.$route.params.sid
},
// 课程ID
cid() {
return this.$route.params.cid
},
// 当前页面的ID
pid() {
return this.$route.params.id
}
},
methods: {
getList() {
const params = { offset: this.page.offset, limit: this.page.limit }
api.getChapterHomeworkOtherAll(this.sid, this.cid, this.pid, params).then(response => {
this.list = response.data
this.page.total = parseInt(response.count)
})
},
handleCurrentChange() {
this.page.offset = (this.page.currentPage - 1) * this.page.limit
this.getList()
}
},
beforeMount() {
this.getList()
}
}
</script>
<style lang="scss" scoped>
.more {
text-align: center;
padding-top: 40px;
}
</style>
<template>
<container :title="$t('viewerWork.commentTitle')">
<template v-for="(item, index) in list">
<el-form
label-position="top"
:disabled="disabled"
:model="item"
:rules="rules"
:hide-required-asterisk="true"
:key="item.id"
ref="form"
>
<el-form-item prop="comment">
<chapter-work-comment-item
:data="item"
:index="index"
:endDate="endDate"
:disabled="disabled"
:key="item.id"
/> </el-form-item
></el-form>
</template>
<div class="button">
<el-button type="primary" :disabled="disabled" @click="handleSubmit">{{
$t('viewerWork.commentSubmitText')
}}</el-button>
<p v-if="status === 1">注:重新提交后不可修改,请检查好作业内容再做提交。</p>
<p v-else>{{ $t('viewerWork.commentSubmitTips', { date: endDate }) }}</p>
</div>
<div class="more">
<router-link :to="`${$route.path}/answers`" target="_blank">
<el-button round>{{ $t('viewerWork.answerMoreButtonText') }}</el-button>
</router-link>
</div>
</container>
</template>
<script>
// api
import * as api from '../../api'
// componets
import Container from '../common/container.vue'
import ChapterWorkCommentItem from './chapterWorkCommentItem.vue'
export default {
components: { Container, ChapterWorkCommentItem },
props: { endDate: { type: String }, status: { type: Number } },
data() {
return {
list: [],
rules: {
comment: [{ required: true, message: '请输入评价内容', trigger: 'change' }]
},
popoverVisible: false
}
},
computed: {
// 学期ID
sid() {
return this.$route.params.sid
},
// 课程ID
cid() {
return this.$route.params.cid
},
// 当前页面的ID
pid() {
return this.$route.params.id
},
isSubmitTime() {
// 大于开始时间,小于结束时间
const endTime = +new Date(this.endDate)
const currentTime = new Date().getTime()
return currentTime < endTime
},
// 是否禁用
disabled() {
// -1未处理 0已处理 1驳回
if (this.status === 1) {
return false
}
return !this.isSubmitTime
}
},
methods: {
getList() {
api.getChapterHomeworkOther(this.sid, this.cid, this.pid).then(response => {
this.list = response
})
},
// 提交校验
checkSubmit() {
let result = true
for (let i = 0; i < this.list.length; i++) {
this.$refs.form[i].validate(valid => {
if (!valid) {
result = valid
return result
}
})
}
return result
},
// 提交评价
handleSubmit() {
// 校验
if (!this.checkSubmit()) {
this.messageInstance && this.messageInstance.close()
this.messageInstance = this.$message.error(this.$t('viewerWork.examSubmitError'))
return
}
// 驳回提交
if (this.status === 1) {
this.$confirm('本次作业提交后不可修改,您确认提交吗?', '提示', {
confirmButtonText: '确定提交',
type: 'warning'
}).then(this.handleSubmitReqeuest)
} else {
// 正常提交
this.handleSubmitReqeuest()
}
},
handleSubmitReqeuest() {
const params = this.list.map(({ id, comment }) => {
return { id, comment }
})
api
.addChapterHomeworkComment(params)
.then(response => {
this.$message({ type: 'success', message: response.message })
this.getList()
this.$emit('update')
})
.catch(error => {
this.$message({ type: 'error', message: error.message })
})
}
},
beforeMount() {
this.getList()
}
}
</script>
<style lang="scss" scoped>
.more {
text-align: center;
padding-top: 40px;
}
.button {
display: flex;
align-items: center;
p {
padding-left: 20px;
}
}
::v-deep .el-form-item__content {
line-height: 24px;
}
</style>
<template>
<chapter-work-answer-item :data="data" :key="data.id" v-bind="$attrs">
<h3 class="comment-title">{{ $t('viewerWork.commentMyTitle') }}</h3>
<v-editor v-model="data.comment" :disabled="disabled"></v-editor>
</chapter-work-answer-item>
</template>
<script>
// componets
import ChapterWorkAnswerItem from './chapterWorkAnswerItem.vue'
import VEditor from '@/components/ckeditor'
export default {
props: { endDate: { type: String }, data: { type: Object, default: () => ({}) }, disabled: { type: Boolean } },
components: { ChapterWorkAnswerItem, VEditor },
data() {
return {}
}
}
</script>
<style lang="scss">
.comment-title {
margin: 10px 0;
font-size: 14px;
font-weight: normal;
// padding: 10px 0;
}
</style>
<template>
<div></div>
</template>
<script>
export default {
data() {
return {}
}
}
</script>
...@@ -221,6 +221,9 @@ p { ...@@ -221,6 +221,9 @@ p {
padding: 20px 0 30px; padding: 20px 0 30px;
font-size: 14px; font-size: 14px;
} }
::v-deep .el-step__main {
overflow: hidden;
}
::v-deep .el-form-item__label { ::v-deep .el-form-item__label {
font-weight: bold; font-weight: bold;
line-height: 24px; line-height: 24px;
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
<!-- 简答题 --> <!-- 简答题 -->
<template v-if="type === 3"> <template v-if="type === 3">
<v-editor v-model="currentValue.user_answer" :disabled="disabled"></v-editor> <v-editor v-model="currentValue.user_answer" :disabled="disabled"></v-editor>
<v-upload :disabled="disabled" v-model="currentValue.attachments" <v-upload :disabled="disabled" v-model="currentValue.attachments" accept=".pdf" v-if="hasUpload"
>{{ $t('viewerWork.workUrl.label') }}</v-upload >{{ $t('viewerWork.workUrl.label') }}</v-upload
> >
</template> </template>
...@@ -98,7 +98,8 @@ export default { ...@@ -98,7 +98,8 @@ export default {
}, },
// 是否禁用,提交过的是禁用状态 // 是否禁用,提交过的是禁用状态
disabled: { type: Boolean, default: false }, disabled: { type: Boolean, default: false },
showResult: { type: Boolean, default: true } showResult: { type: Boolean, default: true },
hasUpload: { type: Boolean, default: true }
}, },
data() { data() {
return { return {
......
...@@ -104,17 +104,21 @@ export default { ...@@ -104,17 +104,21 @@ export default {
// 章节列表 // 章节列表
chapters() { chapters() {
const chapters = this.detail.chapters || [] const chapters = this.detail.chapters || []
if (!chapters.length) { // if (!chapters.length) {
return [] // return []
} // }
const customeChapter = { const customeChapter = {
name: this.$t('viewerMain.workData'), name: this.$t('viewerMain.workData'),
children: [ children: [
{ name: this.$t('viewerMain.courseWork'), id: 'course_work', type: 99 }, // { name: this.$t('viewerMain.courseWork'), id: 'course_work', type: 99 },
{ name: this.$t('viewerMain.courseData'), id: 'course_info', type: 100 } { name: this.$t('viewerMain.courseData'), id: 'course_info', type: 100 }
// { name: this.$t('viewerMain.teachingEvaluation'), id: 'teach_evaluation', type: 102 } // { name: this.$t('viewerMain.teachingEvaluation'), id: 'teach_evaluation', type: 102 }
] ]
} }
// 课程大作业
if (this.detail.curriculum && this.detail.curriculum.curriculum_essay) {
customeChapter.children.unshift({ name: this.$t('viewerMain.courseWork'), id: 'course_work', type: 99 })
}
// 课程考试 // 课程考试
if (this.detail.course_examination) { if (this.detail.course_examination) {
customeChapter.children.push({ customeChapter.children.push({
...@@ -235,13 +239,13 @@ export default { ...@@ -235,13 +239,13 @@ export default {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
padding: 40px 0; padding: 20px 0 40px;
// text-align: center; // text-align: center;
} }
.course-viewer-content-hd__title { .course-viewer-content-hd__title {
position: relative; position: relative;
display: inline-block; display: inline-block;
margin: 0 0 0 20px; margin: 0;
padding: 0 0 5px; padding: 0 0 5px;
font-size: 20px; font-size: 20px;
border-bottom: 3px solid #707070; border-bottom: 3px solid #707070;
......
...@@ -41,7 +41,7 @@ export default { ...@@ -41,7 +41,7 @@ export default {
anotherSubmitText: 'Take another test', anotherSubmitText: 'Take another test',
correctRate: 'Correct rate', correctRate: 'Correct rate',
revisedButtonText: 'Corrected', revisedButtonText: 'Corrected',
deadline: 'Please submit before the deadline {date}', deadline: 'Deadline: {date} Modifications can be made any time before deadline.',
rejectTips: 'The assignment is rejected, click the "re-edit" button to re-edit the content and submit again', rejectTips: 'The assignment is rejected, click the "re-edit" button to re-edit the content and submit again',
rejectTime: 'Rejection time', rejectTime: 'Rejection time',
rejectContent: 'Rejection instructions', rejectContent: 'Rejection instructions',
...@@ -59,17 +59,25 @@ export default { ...@@ -59,17 +59,25 @@ export default {
workStep3: 'Submit before the deadline', workStep3: 'Submit before the deadline',
workTheme: { label: 'Theme', placeholder: 'Theme', rule: 'Please enter Theme' }, workTheme: { label: 'Theme', placeholder: 'Theme', rule: 'Please enter Theme' },
workDescription: { label: 'Text', placeholder: 'Text', rule: 'Please enter the text' }, workDescription: { label: 'Text', placeholder: 'Text', rule: 'Please enter the text' },
workUrl: { label: 'Please upload the corresponding file attachment', rule: 'Please upload attachment' }, workUrl: { label: 'Upload Attachment', rule: 'Please upload attachment' },
studentAnswer: 'Student answer', studentAnswer: 'Student answer',
correctAnswer: 'Correct answer', correctAnswer: 'Correct answer',
analyze: 'Parsing', analyze: 'Parsing',
viewResolution: 'View resolution', viewResolution: 'View resolution',
singleChoice: 'Single Choice', singleChoice: 'Single Choice',
multipleChoice: 'Multiple Choice', multipleChoice: 'Multiple Choice',
clickUpload: 'Click upload', clickUpload: 'Click here to upload',
delete: 'Delete', delete: 'Delete',
download: 'Download', download: 'Download',
downloadName: 'Download attachment' downloadName: 'Download attachment',
commentTips: 'Please continue to finish comment assignments after the deadline.',
commentTitle: 'Comment on Other Student Assignments',
commentMyTitle: 'My Comment',
commentSubmitText: 'Submit Comment ',
commentSubmitTips: 'Deadline: {date} Modifications can be made any time before deadline.',
answerMoreButtonText: 'Check other students assignments',
submittedAssignments: 'Submitted Assignments',
student: 'student'
}, },
viewerExam: {}, viewerExam: {},
viewerRead: { viewerRead: {
......
...@@ -34,14 +34,14 @@ export default { ...@@ -34,14 +34,14 @@ export default {
examSubmitButtonTips: '提交之后就不能修改了哦', examSubmitButtonTips: '提交之后就不能修改了哦',
examStartButtonText: '开始考试', examStartButtonText: '开始考试',
examEndButtonText: '考试结束', examEndButtonText: '考试结束',
examSubmitError: '还有题目未做,不能提交', examSubmitError: '请检查输入内容是否正确',
examSubmitSuccess: '提交成功', examSubmitSuccess: '提交成功',
prevPapers: '上一套试卷', prevPapers: '上一套试卷',
nextPapers: '下一套试卷', nextPapers: '下一套试卷',
anotherSubmitText: '再考一次', anotherSubmitText: '再考一次',
correctRate: '正确率', correctRate: '正确率',
revisedButtonText: '已批改', revisedButtonText: '已批改',
deadline: '请于截止日期 {date} 前提交', deadline: '提交作业截止时间为: {date} ,截止时间前均可修改。',
rejectTips: '作业被驳回,点击“重新编辑”按钮重新编辑内容再次提交', rejectTips: '作业被驳回,点击“重新编辑”按钮重新编辑内容再次提交',
rejectTime: '驳回时间', rejectTime: '驳回时间',
rejectContent: '驳回说明', rejectContent: '驳回说明',
...@@ -68,7 +68,15 @@ export default { ...@@ -68,7 +68,15 @@ export default {
clickUpload: '点击上传', clickUpload: '点击上传',
delete: '删除', delete: '删除',
download: '下载', download: '下载',
downloadName: '附件下载' downloadName: '附件下载',
commentTips: '作业提交截止后,请继续完成评论作业。',
commentTitle: '评论同学作业',
commentSubmitTips: '提交评论截止时间为:{date},截止时间前均可修改。',
commentMyTitle: '我的评论',
commentSubmitText: '提交评价',
answerMoreButtonText: '去看其他同学作业',
submittedAssignments: '同学提交的作业',
student: '同学'
}, },
viewerRead: { viewerRead: {
download: '下载', download: '下载',
......
...@@ -9,5 +9,9 @@ export default [ ...@@ -9,5 +9,9 @@ export default [
component: () => import('./components/layout.vue') component: () => import('./components/layout.vue')
} }
] ]
},
{
path: '/viewer/:sid/:cid/:id/answers',
component: () => import('./components/work/chapterWorkAnswerList.vue')
} }
] ]
<template> <template>
<div> <div v-loading="loading">
<div class="con-title">{{ $t('pages.grade.credit.title') }}</div> <div class="con-title">{{ $t('pages.grade.credit.title') }}</div>
<div class="con-box"> <div class="con-box">
<div v-if="false">
<p>注:</p>
<p>1. 每一门课程达到77分及格通过,低于77分需要重修,重修费用按照每学分1000元进行缴纳。</p>
<p>2. 所有课程全部通过,且16门必修课平均分达到{{ detail.degree_score }}分,符合申请学位要求。</p>
</div>
<div class="total-core"> <div class="total-core">
<div class="title">{{ $t('pages.grade.credit.totalCredits') }}</div> <div class="title">{{ $t('pages.grade.credit.totalCredits') }}</div>
<div class="core">{{ score.total }}</div> <div class="core">{{ detail.total_credits }}(分)</div>
<el-progress <el-progress
ref="credit_total"
:text-inside="true" :text-inside="true"
:stroke-width="30" :stroke-width="30"
:percentage="percent1" :percentage="totalPercentage"
:format="progressFormat.bind(null, detail.my_total_credits)"
color="#df9d75" color="#df9d75"
></el-progress> ></el-progress>
</div> </div>
<div class="total-core" v-if="false">
<div class="title">综合必修平均分</div>
<div class="core">100(分)</div>
<div class="progress">
<div class="progress-baseline" :style="progressBasseLineStyle">
<span>{{ detail.degree_score }}(分)</span>
</div>
<el-progress
:text-inside="true"
:stroke-width="30"
:percentage="detail.average_score"
:format="progressFormat"
color="#8ca4cf"
>
</el-progress>
</div>
</div>
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12"> <el-col :span="12">
<div class="compulsory-core"> <div class="total-core">
<div class="title">{{ $t('pages.grade.credit.compCredits') }}</div> <div class="title">{{ $t('pages.grade.credit.compCredits') }}</div>
<div class="core">{{ score.must }}</div> <div class="core">{{ detail.required_credits }}(分)</div>
<el-progress <el-progress
ref="credit_must"
:text-inside="true" :text-inside="true"
:stroke-width="30" :stroke-width="30"
:percentage="percent2" :percentage="requiredPercentage"
color="#8ca4cf" :format="progressFormat.bind(null, detail.my_required_credits)"
></el-progress> color="#df9d75"
>234234234</el-progress
>
</div> </div>
</el-col> </el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12"> <el-col :span="12">
<div class="elective-core"> <div class="total-core">
<div class="title">{{ $t('pages.grade.credit.eleCredits') }}</div> <div class="title">{{ $t('pages.grade.credit.eleCredits') }}</div>
<div class="core">{{ score.unmust }}</div> <div class="core">{{ detail.optional_credits }}(分)</div>
<el-progress <el-progress
ref="credit_unmust"
:text-inside="true" :text-inside="true"
:stroke-width="30" :stroke-width="30"
:percentage="percent3" :percentage="optionalPercentage"
color="#66c6bd" :format="progressFormat.bind(null, detail.my_optional_credits)"
color="#df9d75"
></el-progress> ></el-progress>
</div> </div>
</el-col> </el-col>
...@@ -46,111 +69,112 @@ ...@@ -46,111 +69,112 @@
<div class="txt">{{ $t('pages.grade.credit.compCredits') }}</div> <div class="txt">{{ $t('pages.grade.credit.compCredits') }}</div>
<div class="color" style="background: #66c6bd"></div> <div class="color" style="background: #66c6bd"></div>
<div class="txt">{{ $t('pages.grade.credit.eleCredits') }}</div> <div class="txt">{{ $t('pages.grade.credit.eleCredits') }}</div>
<!-- <div class="color" style="background: #8ca4cf"></div>
<div class="txt">综合必修平均分</div> -->
<div class="color" style="background: #df9d75"></div> <div class="color" style="background: #df9d75"></div>
<div class="txt">{{ $t('pages.grade.credit.allCredits') }}</div> <div class="txt">{{ $t('pages.grade.credit.allCredits') }}</div>
</div> </div>
<m-page <table-list v-bind="tableOptions"></table-list>
:tableHead="tableHead"
:tableData="tableData"
:params="params"
:objFn="objFn"
:tableConfig="tableConfig"
/>
<div style="height: 0.3rem"></div>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import mPage from '@/components/comTable/mPage.vue' import mPage from '@/components/comTable/mPage.vue'
import cAction from '@action'
import TableList from '@/components/comTable/tableList'
export default { export default {
components: { mPage }, components: { mPage, TableList },
data() { data() {
return { return {
percent1: 0, loading: false,
percent2: 0, detail: {}
percent3: 0, }
score: {
total: 0,
myTotal: 0,
myTotalStr: '0%',
must: 0,
myMust: 0,
myMustStr: '0%',
unmust: 0,
myUnmust: 0,
myUnmustStr: '0%'
}, },
tableConfig: { border: '', size: '', selection: { has: false, sels: [], width: '50px', fix: 'left', align: '' } }, // 增加选择框,has设置为true computed: {
tableHead: [ tableOptions() {
{ prop: 'index', label: this.$t('pages.grade.credit.serialNumber'), width: '60px' }, return {
{ prop: 'semester_name', label: this.$t('pages.grade.credit.semester') }, columns: [
{ prop: 'class_name', label: this.$t('pages.grade.credit.class'), width: '200px' }, { prop: 'semester_name', label: this.$t('pages.grade.credit.semester'), attrs: { width: '160px' } },
{ prop: 'class_name', label: this.$t('pages.grade.credit.class'), attrs: { width: '120px' } },
{ prop: 'course_name', label: this.$t('pages.grade.credit.course') }, { prop: 'course_name', label: this.$t('pages.grade.credit.course') },
{ prop: 'course_credit', label: this.$t('pages.grade.credit.courseCredits'), width: '100px' }, { prop: 'course_credit', label: this.$t('pages.grade.credit.courseCredits'), attrs: { width: '100px' } },
{ prop: 'passed', label: this.$t('pages.grade.credit.status'), width: '100px' }, {
{ prop: 'credit', label: this.$t('pages.grade.credit.credit'), width: '100px' }, prop: 'passed',
{ prop: 'score', label: this.$t('pages.grade.credit.grade'), width: '100px' }, label: this.$t('pages.grade.credit.status'),
// { prop: '', label: this.$t('pages.grade.credit')'', minWidth: '', fix: false, goObj: { routerName: '', params: {} } }, // 点击跳转页面并传参数 attrs: { width: '100px' },
computed: value => {
const map = {
0: this.$t('pages.grade.credit.failed'),
1: this.$t('pages.grade.credit.passed'),
2: this.$t('pages.grade.credit.unpublished')
}
return map[value]
}
},
{ prop: 'credit', label: this.$t('pages.grade.credit.credit'), attrs: { width: '100px' } },
{ prop: 'score', label: this.$t('pages.grade.credit.grade'), attrs: { width: '100px' } },
{ {
prop: 'operate-x',
label: this.$t('pages.grade.credit.operate'), label: this.$t('pages.grade.credit.operate'),
width: '80px', attrs: { width: '100px' },
fix: false, buttons: [
commandArr: [ {
{ command: 're-start', name: '重修' }, label: '申请重修',
{ command: 're-start', name: '已申请' } isShow(row) {
return row.passed === 0
},
onClick: row => {
this.$router.push({ path: '/app/offices', query: { channel: 'retake' } })
}
}
] ]
} }
], ],
tableData: [], data: this.detail.lists
params: { keywords: '', curPage: 1, pageSize: 100, total: '' },
objFn: {
paramsFn: _this => {
return {}
},
nameAPI: 'getCredit',
actionClass: 'Grade',
// nameExcel: 'getStatSummaryExcel',
nameExcel: 'getExportExcel3_4_14',
callback: (_this, data) => {
this.score = data
this.percent1 = Math.floor((this.score.myTotal / this.score.total) * 100) || 0
this.percent2 = Math.floor((this.score.myMust / this.score.must) * 100) || 0
this.percent3 = Math.floor((this.score.myUnmust / (this.score.unmust ? this.score.unmust : 1)) * 100) || 0
// console.log(111, this.score, this.percent1, this.percent2, this.percent3)
this.$refs.credit_total.$el.children[0].children[0].children[0].children[0].innerHTML =
this.score.myTotal + '(分)'
this.$refs.credit_must.$el.children[0].children[0].children[0].children[0].innerHTML =
this.score.myMust + '(分)'
this.$refs.credit_unmust.$el.children[0].children[0].children[0].children[0].innerHTML =
this.score.myUnmust + '(分)'
_this.params.total = 100
data = data.list
data.forEach((elem, i) => {
elem.index = i + 1 + (_this.params.curPage - 1) * _this.params.pageSize
elem.passed =
elem.passed !== 0
? elem.passed === 2
? this.$t('pages.grade.credit.unpublished')
: this.$t('pages.grade.credit.passed')
: this.$t('pages.grade.credit.failed')
_this.tableData.push(elem)
})
} }
},
// 总计学分进度
totalPercentage() {
return (this.detail.my_total_credits / this.detail.total_credits) * 100 || 0
},
// 必修学分进度
requiredPercentage() {
return (this.detail.my_required_credits / this.detail.required_credits) * 100 || 0
},
// 选修学分进度
optionalPercentage() {
return (this.detail.my_optional_credits / this.detail.optional_credits) * 100 || 0
},
progressBasseLineStyle() {
return { left: `${this.detail.degree_score}%` }
} }
},
methods: {
getDetail() {
this.loading = true
cAction.Grade.getCredit()
.then(response => {
this.detail = response
})
.finally(() => {
this.loading = false
})
},
progressFormat(percentage) {
return `${percentage}(分)`
} }
}, },
beforeMount() {
this.getDetail()
},
mounted() { mounted() {
this.VueEvent.$off('command-tablelist-x').$on('command-tablelist-x', data => { // this.VueEvent.$off('command-tablelist-x').$on('command-tablelist-x', data => {
if (data.command.command === 're-start') { // if (data.command.command === 're-start') {
const _data = data.tableData[data.index - 1] // const _data = data.tableData[data.index - 1]
window.localStorage.setItem('rebuild', JSON.stringify(_data)) // window.localStorage.setItem('rebuild', JSON.stringify(_data))
this.$router.push({ path: '/app/grade/rebuild' }) // this.$router.push({ path: '/app/grade/rebuild' })
} // }
}) // })
} }
} }
</script> </script>
...@@ -173,8 +197,10 @@ export default { ...@@ -173,8 +197,10 @@ export default {
} }
} }
.color-box { .color-box {
padding: 0.1rem 0 0.2rem 0; display: flex;
text-align: right; justify-content: flex-end;
align-items: center;
padding: 10px 0;
.color { .color {
display: inline-block; display: inline-block;
vertical-align: text-bottom; vertical-align: text-bottom;
...@@ -183,9 +209,37 @@ export default { ...@@ -183,9 +209,37 @@ export default {
} }
.txt { .txt {
display: inline-block; display: inline-block;
padding: 0 0.2rem 0 0.1rem; padding: 0 10px;
font-size: 14px; font-size: 14px;
line-height: 36px; line-height: 36px;
} }
} }
.progress {
position: relative;
.progress-baseline {
position: absolute;
bottom: 30px;
display: inline-block;
span {
font-size: 12px;
display: block;
transform: translateX(-50%);
}
&::after {
position: absolute;
bottom: -30px;
content: '';
display: block;
width: 4px;
height: 36px;
background-color: #f56c6c;
margin-left: -2px;
z-index: 1;
}
}
::v-deep .el-progress-bar__innerText {
position: relative;
z-index: 1;
}
}
</style> </style>
<template>
<li class="course-list-item">
<div class="course-list-item-pic" @click="handleClick">
<img :src="data.src" v-if="data.src" />
<div class="no-img" v-else><i class="el-icon-self-13"></i></div>
</div>
<div class="course-list-item-main">
<div class="title" @click="handleClick">{{ data.title }}</div>
<div class="tags">
<template v-for="(item1, index) in data.arrTab">
<span v-bind:key="index">{{ item1 }}</span>
</template>
</div>
<div class="time">
{{ data.status }}<em>{{ data.time }}</em>
</div>
<div class="progress">
{{ $t('pages.learn.course.progress') }}
<el-progress :percentage="data.progress" color="#b49441"></el-progress>
</div>
</div>
<div class="course-list-item-aside">
<p>{{ data.myStatus }}</p>
<el-button type="primary" size="small" round @click="handleClick">
{{ $t('pages.learn.course.showCourse') }}
</el-button>
</div>
</li>
</template>
<script>
export default {
name: 'CourseListItem',
props: {
data: { type: Object, required: true },
showProgress: { type: Boolean, default: true }
},
data() {
return {}
},
methods: {
handleClick() {
this.$router.push({ path: `/app/learn/course-detail/${this.data.sid}/${this.data.id}` })
}
}
}
</script>
<style lang="scss">
.course-list-item {
display: flex;
padding: 0.2rem 0;
list-style: none;
}
.course-list-item + .course-list-item {
border-top: 1px solid #dcdcdc;
}
.course-list-item-pic {
position: relative;
width: 1.8rem;
height: 1rem;
cursor: pointer;
.no-img {
width: 100%;
height: 1rem;
text-align: center;
line-height: 1.1rem;
border: 1px solid #e2e2e2;
i {
font-size: 0.4rem;
color: #e2e2e2;
}
}
img {
display: block;
width: 100%;
height: 100%;
object-fit: cover;
}
}
.course-list-item-main {
flex: 1;
position: relative;
padding-left: 0.2rem;
.title {
width: 80%;
line-height: 1.5;
font-weight: 700;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
cursor: pointer;
}
.tags {
margin: 0.05rem 0;
font-size: 0.14rem;
span {
padding: 0 0.1rem;
margin: 0;
border-right: 1px solid #313131;
&:first-child {
padding-left: 0;
}
&:last-child {
border: none;
}
}
}
.time {
font-size: 0.12rem;
em {
font-style: normal;
color: #898989;
}
}
.progress {
margin-top: 0.05rem;
font-size: 14px;
.el-progress {
width: 50%;
display: inline-block;
vertical-align: text-bottom;
}
}
}
.course-list-item-aside {
display: flex;
flex-direction: column;
justify-content: space-between;
p {
padding: 0 0.1rem;
font-size: 0.14rem;
text-align: right;
}
}
</style>
<template>
<div class="detail">
<div class="detail-rich">
<div class="h1">一、最终成绩计算</div>
<div class="p">
<template v-for="(item, index) in checkList">
<span :key="index">{{ index ? '+' : '' }}{{ item.name }}得分*{{ item.percent }}%</span>
</template>
= 该门课程总得分,满分100分,低于{{ data.course_check_pass_score }}分为不及格,需重修此门课程。
</div>
<v-chart class="chart" :option="option" :autoresize="true" />
</div>
<div class="detail-rich">
<div class="h1">二、具体细则</div>
<template v-for="(item, index) in checkList">
<div :key="index">
<div class="h2">{{ `${item.name} 总分${item.score}分(占科目总成绩的${item.percent}%)` }}</div>
<template v-if="item.key === 'video'">
<div class="p">课程视频观看完成度:以后台数据统计为准,全部看完视频满分100分。</div>
<div class="em">
注:视频观看考核的是实际播放时长,不是进度条的显示状态,进度条满格并不一定表示观看完这个视频。以下方每日学习时长为准。
</div>
</template>
<template v-if="item.key === 'week_report'">
<div class="p">报告作业总分{{ item.score }}分,报告得分以老师批改的分数为准。</div>
<div class="p">课程反馈建设性问题老师可酌情加分,每周的课程提问加分以老师批改的分数为准。</div>
</template>
<div class="p" v-if="item.key === 'week_test'">
本课程所有测试的平均正确率*{{ item.score }}*占总成绩{{ item.percent }}%=此项得分
</div>
<div class="p" v-if="item.key === 'essay'">结业大作业满分为{{ item.score }}分,以老师批改的分数为准。</div>
<div class="p" v-if="item.key === 'attendance'">
互动课出勤满分{{ item.score }}分,以老师每次导出的参会记录进行打分。
</div>
<div class="p" v-if="item.key === 'question'">
课程提问满分{{ item.score }}分, 老师根据提问情况酌情给分。
</div>
</div>
</template>
</div>
</div>
</template>
<script>
import { use } from 'echarts/core'
import { CanvasRenderer } from 'echarts/renderers'
import { PieChart } from 'echarts/charts'
import { TitleComponent, TooltipComponent, LegendComponent } from 'echarts/components'
import VChart from 'vue-echarts'
use([CanvasRenderer, PieChart, TitleComponent, TooltipComponent, LegendComponent])
export default {
props: { data: { type: Object, default: () => {} } },
components: { VChart },
data() {
return {}
},
computed: {
checkList() {
return this.data.course_check.filter(item => parseInt(item.percent))
},
option() {
const data = this.checkList.map(item => {
return { name: item.name, value: item.percent }
})
return {
tooltip: { trigger: 'item', formatter: '{a} <br/>{b} 占比{c}%' },
series: [{ name: '课程考核', type: 'pie', data }]
}
}
}
}
</script>
<style scoped>
.chart {
height: 300px;
}
</style>
<template>
<div class="detail">
<div class="detail-rich">
<div class="h1">一、最终成绩计算</div>
<div class="p">美方课程最终成绩请参考每学期初教务邮箱老师发到大家邮箱中的课程考核大纲进行计算。</div>
<v-chart class="chart" :option="option" :autoresize="true" />
</div>
<div class="detail-rich">
<div class="h1">二、具体细则</div>
<template v-for="(item, index) in checkList">
<div :key="index">
<div class="h2">{{ `${item.name} 总分${item.score}分(占科目总成绩的${item.percent}%)` }}</div>
<template v-if="item.key === 'video'">
<div class="p">
课程视频观看完成度:以后台数据统计为准,全部看完视频满分100分。(实际视频观看分数以课程考核大纲为准)
</div>
<div class="em">
注:视频观看考核的是实际播放时长,不是进度条的显示状态,进度条满格并不一定表示观看完这个视频。以下方每日学习时长为准。
</div>
</template>
<template v-if="item.key === 'week_report'">
<div class="p">报告作业总分{{ item.score }}分,报告得分以老师批改的分数为准。</div>
<div class="p">课程反馈建设性问题老师可酌情加分,每周的课程提问加分以老师批改的分数为准。</div>
</template>
<div class="p" v-if="item.key === 'week_test'">
本课程所有测试的平均正确率*{{ item.score }}*占总成绩{{ item.percent }}%=此项得分。
(实际章节测试占比以课程考核大纲为准)。
</div>
<div class="p" v-if="item.key === 'essay'">结业大作业满分为{{ item.score }}分,以老师批改的分数为准。</div>
<div class="p" v-if="item.key === 'attendance'">
互动课出勤满分{{ item.score }}分,以老师每次导出的参会记录进行打分。
</div>
<div class="p" v-if="item.key === 'question'">
课程提问满分{{ item.score }}分, 老师根据提问情况酌情给分。
</div>
</div>
</template>
</div>
</div>
</template>
<script>
import { use } from 'echarts/core'
import { CanvasRenderer } from 'echarts/renderers'
import { PieChart } from 'echarts/charts'
import { TitleComponent, TooltipComponent, LegendComponent } from 'echarts/components'
import VChart from 'vue-echarts'
use([CanvasRenderer, PieChart, TitleComponent, TooltipComponent, LegendComponent])
export default {
props: { data: { type: Object, default: () => {} } },
components: { VChart },
data() {
return {}
},
computed: {
checkList() {
return this.data.course_check.filter(item => parseInt(item.percent))
},
option() {
const data = this.checkList.map(item => {
return { name: item.name, value: item.percent }
})
return {
tooltip: { trigger: 'item', formatter: '{a} <br/>{b} 占比{c}%' },
series: [{ name: '课程考核', type: 'pie', data }]
}
}
}
}
</script>
<style scoped>
.chart {
height: 300px;
}
</style>
<template> <template>
<div> <div>
<template v-if="newLiveMsg.live"> <!-- 最新直播 -->
<div class="live-msg"> <course-latest-live />
<div class="txt">{{ $t('pages.learn.course.title2') }}</div>
<div class="txt">
{{ $t('pages.learn.course.msg') }}{{ newLiveMsg.course_name }}{{ $t('pages.learn.course.msg1') }}
{{ newLiveMsg.live.start_time }}
{{ $t('pages.learn.course.msg2') }}
</div>
<el-button class="in-btn" type="primary" size="small" round @click="goLive">{{
$t('pages.learn.course.Enterlive')
}}</el-button>
</div>
</template>
<div class="con-title">{{ $t('pages.learn.course.title') }}</div> <div class="con-title">{{ $t('pages.learn.course.title') }}</div>
<!-- 筛选 -->
<div class="con-box"> <div class="con-box">
<template v-for="(item, index) in find"> <template v-for="(item, index) in find">
<ul v-bind:key="index" class="tabs-list"> <ul v-bind:key="index" class="tabs-list">
...@@ -37,76 +27,38 @@ ...@@ -37,76 +27,38 @@
</ul> </ul>
</template> </template>
</div> </div>
<!-- 排序 -->
<div class="switch-box"> <div class="switch-box">
<el-button type="info" size="medium" @click="studyEarlyUpdate" plain <el-button type="info" size="medium" plain @click="studyEarlyUpdate">
>{{ $t('pages.learn.course.lastLearn') {{ $t('pages.learn.course.lastLearn') }}
}}<i :class="['el-icon-caret-' + (filter.studyEarly == 'down' ? 'bottom' : 'top'), 'icon']"></i <i :class="['el-icon-caret-' + (filter.studyEarly == 'down' ? 'bottom' : 'top'), 'icon']"></i>
></el-button> </el-button>
<el-button type="info" size="medium" @click="selectTimeUpdate" plain <el-button type="info" size="medium" plain @click="selectTimeUpdate">
>{{ $t('pages.learn.course.updateTime') {{ $t('pages.learn.course.updateTime') }}
}}<i :class="['el-icon-caret-' + (filter.selectTime == 'down' ? 'bottom' : 'top'), 'icon']"></i <i :class="['el-icon-caret-' + (filter.selectTime == 'down' ? 'bottom' : 'top'), 'icon']"></i>
></el-button> </el-button>
<!-- <el-button class="rbtn" type="primary" size="medium" icon="el-icon-self-cc-book icon" @click="goCourseAll">{{ $t('pages.learn.course.changeCourse') }}</el-button> --> <!--
<el-button class="rbtn" type="primary" size="medium" icon="el-icon-self-cc-book icon" @click="goCourseAll">
{{ $t('pages.learn.course.changeCourse') }}
</el-button>
-->
</div> </div>
<!-- 课程列表 -->
<div class="con-box" v-loading="loading"> <div class="con-box" v-loading="loading">
<ul class="course-list"> <ul class="course-list" v-if="homeList.length">
<template v-for="(item, index) in homeList"> <course-list-item v-for="(item, index) in homeList" :data="item" :key="index"></course-list-item>
<li v-bind:key="index" class="item">
<div class="left-pic">
<template v-if="item.src">
<img :src="item.src" alt="" @click="goCourseContent" :data-cid="item.id" :data-sid="item.sid" />
</template>
<template v-else>
<div class="no-img"><i class="el-icon-self-13"></i></div>
</template>
</div>
<div class="right-bd">
<div class="title" @click="goCourseContent" :data-cid="item.id" :data-sid="item.sid">
{{ item.title }}
</div>
<div class="tags">
<template v-for="(item1, index) in item.arrTab">
<span v-bind:key="index">{{ item1 }}</span>
</template>
</div>
<div class="time">
{{ item.status }}&emsp;&emsp;<em>{{ item.time }}</em>
</div>
<div class="progress">
{{ $t('pages.learn.course.progress') }}&emsp;<el-progress
:percentage="item.progress > 99.5 ? 100 : item.progress"
color="#b49441"
></el-progress>
</div>
<div class="right-sel">{{ item.myStatus }}</div>
<el-button
class="in-btn"
type="primary"
size="small"
round
@click="goCourseContent"
:data-cid="item.id"
:data-sid="item.sid"
>{{ $t('pages.learn.course.showCourse') }}</el-button
>
</div>
</li>
</template>
<template v-if="!homeList.length">
<div class="no-data">{{ $t('pages.learn.course.noCourseStr') }}</div>
</template>
</ul> </ul>
<div class="no-data" v-else>{{ $t('pages.learn.course.noCourseStr') }}</div>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import cAction from '@action' import cAction from '@action'
import CourseLatestLive from './course/components/CourseLatestLive.vue'
import CourseListItem from './components/CourseListItem'
export default { export default {
components: {}, components: { CourseLatestLive, CourseListItem },
data() { data() {
return { return {
filter: { filter: {
...@@ -148,21 +100,10 @@ export default { ...@@ -148,21 +100,10 @@ export default {
], ],
homeList: [], // 从后台请求 homeList: [], // 从后台请求
param: {}, param: {},
timeInterval: null,
newLiveMsg: {},
loading: false loading: false
} }
}, },
mounted() { mounted() {
if (this.timeInterval) {
clearInterval(this.timeInterval)
this.timeInterval = null
}
// 获取最新直播
this.getLatestLive()
// 定时获取最新直播
this.timeInterval = setInterval(this.getLatestLive, 10000)
cAction.Course.getLearnFind() cAction.Course.getLearnFind()
.then(data => { .then(data => {
this.find[0].arrItem = data this.find[0].arrItem = data
...@@ -173,36 +114,17 @@ export default { ...@@ -173,36 +114,17 @@ export default {
}) })
.finally(() => {}) .finally(() => {})
}, },
destroyed() {
if (this.timeInterval) {
clearInterval(this.timeInterval)
this.timeInterval = null
}
},
methods: { methods: {
goCourseAll() { goCourseAll() {
this.$router.push({ this.$router.push({
path: '/app/learn/course-all' path: '/app/learn/course-all'
}) })
}, },
goCourseContent(e) {
const cid = e.currentTarget.dataset.cid
const sid = e.currentTarget.dataset.sid
this.$router.push({
path: `/app/learn/course-detail/${sid}/${cid}`
})
},
getAjaxList(bool, str) { getAjaxList(bool, str) {
this.loading = true this.loading = true
cAction.Course.getCourseList(bool, this.param) cAction.Course.getCourseList(bool, this.param)
.then(json => { .then(json => {
this.homeList = json this.homeList = json
if (!json.length) {
this.$message(str)
}
})
.catch(e => {
this.$message.error(e.message)
}) })
.finally(() => { .finally(() => {
this.loading = false this.loading = false
...@@ -254,57 +176,12 @@ export default { ...@@ -254,57 +176,12 @@ export default {
} }
this.getAjaxList(true, this.$t('pages.learn.course.goCourseAllStr')) this.getAjaxList(true, this.$t('pages.learn.course.goCourseAllStr'))
},
/* 直接进直播 */
goLive() {
const live = this.newLiveMsg.live
if (live.type === 8) {
window.open(live.record_url || live.join_url)
} else {
this.$router.push({
name: 'viewerCourseChapter',
params: {
sid: this.newLiveMsg.semester_id,
cid: this.newLiveMsg.course_id,
id: this.newLiveMsg.chapter_id
}
})
}
},
// 获取最新直播
getLatestLive() {
cAction.Player.getNewLiveMsg()
.then(json => {
if (json.status === 200) {
this.newLiveMsg = json.data
}
})
.catch(e => {
this.$message.error(e.message)
})
} }
} }
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.live-msg {
position: relative;
padding: 15px;
box-shadow: 0 1px 8px rgba(0, 0, 0, 0.1);
.txt {
padding-right: 100px;
}
.in-btn {
position: absolute;
right: 20px;
top: 50%;
transform: translateY(-50%);
}
}
/* 列表 筛选 */ /* 列表 筛选 */
ul.tabs-list { ul.tabs-list {
float: left; float: left;
...@@ -372,127 +249,10 @@ ul.course-list { ...@@ -372,127 +249,10 @@ ul.course-list {
padding: 0; padding: 0;
font-size: 0.18rem; font-size: 0.18rem;
color: #313131; color: #313131;
}
.no-data { .no-data {
text-align: center; text-align: center;
line-height: 2rem; line-height: 2rem;
}
li.item {
padding: 0.1rem 0;
list-style: none;
border-bottom: 1px solid #dcdcdc;
overflow: hidden;
&:first-child {
padding-top: 0;
}
&:last-child {
margin-bottom: 0.2rem;
}
.left-pic {
position: relative;
float: left;
width: 1.8rem;
// min-height: 1rem;
overflow: hidden;
.no-img {
width: 100%;
height: 1rem;
text-align: center;
line-height: 1.1rem;
border: 1px solid #e2e2e2;
i {
font-size: 0.4rem;
color: #e2e2e2;
}
}
img {
// position: absolute;
// top: 50%;
// left: 50%;
display: block;
width: 100%;
// height: 100%;
// transform: translate(-50%, -50%);
cursor: pointer;
}
}
.right-bd {
position: relative;
display: block;
margin-left: 2rem;
.title {
width: 80%;
line-height: 1.5;
font-weight: 700;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
cursor: pointer;
}
.tags {
margin: 0.05rem 0;
font-size: 0.14rem;
span {
padding: 0 0.1rem;
margin: 0;
border-right: 1px solid #313131;
&:first-child {
padding-left: 0;
}
&:last-child {
border: none;
}
}
}
.time {
font-size: 0.12rem;
em {
font-style: normal;
color: #898989;
}
}
.progress {
margin-top: 0.05rem;
font-size: 14px;
.el-progress {
width: 50%;
display: inline-block;
vertical-align: text-bottom;
}
}
.right-sel {
position: absolute;
right: 0;
top: 0;
font-size: 14px;
padding: 0 0.1rem;
}
.in-btn {
position: absolute;
right: 0;
bottom: 0;
}
}
}
} }
@media (max-width: 767px) { @media (max-width: 767px) {
......
<!--课程考核-->
<template>
<div class="course-assess" v-loading="loading">
<h1 class="title">
{{ $t('pages.learn.courseDetail.Finalresult') }}
<template v-if="data.course_score"> {{ data.course_score }}{{ $t('pages.learn.courseDetail.point') }} </template>
<template v-else>{{ $t('pages.learn.courseDetail.no') }}</template>
</h1>
<div class="detail">
<div class="subtitle">
<span>{{ $t('pages.learn.courseDetail.Courseassessmentstandard') }}</span>
</div>
<div class="h1">一、最终成绩计算</div>
<div class="p">
课程表现得分*30%+每章试题得分*30%+结业大作业得分*40%=该门课程总得分,满分100分,低于80分为不及格,需重修此门课程。84分以上方可申请学位。
</div>
<img
class="b1"
src="https://zws-imgs-pub.oss-cn-beijing.aliyuncs.com/static/build/www/course-check.png"
mode="aspectFill"
/>
<div class="h1">二、具体细则</div>
<div class="h2">课程表现:总分100分(占科目总成绩的30%)</div>
<div class="p">1、每个视频观看完成度50分:以后台数据统计为准,全部看完视频满分50分,其它酌情给分。</div>
<div class="em">
注:视频观看考核的是实际播放时长,不是进度条的显示状态,进度条满格并不一定表示观看完这个视频。以下方每日学习时长为准。
</div>
<div class="p">
2、课程反馈建设性问题及课程完成情况50分:反馈问题以教务老师统计为准,课程完成情况以后台数据为准,是否按时完成视频观看、测试、作业提交,满分50分,酌情给分。
</div>
<div class="h2">每章试题:总分100分(占科目总成绩的30%)</div>
<div class="p">
本课程所有试题的平均正确率*100分*占总成绩30%=此项得分。(比如正确度为80%,则此项得分:80%*100*30%=24分)
</div>
<div class="h2">结业大作业:总分100分(占科目总成绩的40%)</div>
<div class="p">结业大作业满分为100分,以助教老师给分为准。</div>
</div>
<!-- <course-assessment-standard :data="data" v-bind="$attrs" v-if="data.course_check" /> -->
<course-assessment-progress :data="data" />
</div>
</template>
<script>
import * as api from '@/api/course'
import CourseAssessmentStandard from './CourseAssessmentStandard'
import CourseAssessmentProgress from './CourseAssessmentProgress'
export default {
components: { CourseAssessmentStandard, CourseAssessmentProgress },
data() {
return {
loading: false,
data: {}
}
},
computed: {
sid() {
return this.$route.params.sid
},
cid() {
return this.$route.params.cid
}
},
methods: {
getData() {
this.loading = true
api
.getCourseAssess(this.sid, this.cid)
.then(res => {
this.data = res
})
.finally(() => {
this.loading = false
})
}
},
beforeMount() {
this.getData()
}
}
</script>
<style lang="scss">
.course-assess {
padding: 20px;
background-color: #fff;
.title {
font-size: 0.2rem;
text-align: center;
}
.subtitle {
position: relative;
width: 300px;
margin: 40px auto 20px;
text-align: center;
span {
padding: 0 20px;
position: relative;
display: inline-block;
background-color: #fff;
}
&::before {
position: absolute;
left: 0;
top: 50%;
right: 0;
content: '';
height: 1px;
background-color: #000;
transform: translateY(50%);
}
}
}
.course-assess .detail .h1 {
font-size: 0.16rem;
font-weight: 700;
color: #313131;
line-height: 0.38rem;
}
.course-assess .detail .h2 {
font-size: 0.14rem;
font-weight: 700;
color: #313131;
line-height: 0.3rem;
}
.course-assess .detail .p {
font-size: 0.14rem;
color: #313131;
line-height: 1.5;
text-align: justify;
}
.course-assess .detail .em {
font-size: 0.12rem;
color: #b49441;
line-height: 1.5;
text-align: justify;
}
</style>
<!--课程考核-学习进度及成绩-->
<template>
<div class="course-assess-progress">
<div class="subtitle">
<span>{{ $t('pages.learn.courseDetail.Learningprogressachievements') }}</span>
</div>
<!-- 视频 -->
<div class="item">
<div class="item-title">
{{ $t('pages.learn.courseDetail.title2') }}{{ formatDuration(data.course_duration)
}}{{ $t('pages.learn.courseDetail.Completionrate') }}{{ data.course_progress }}
</div>
<div class="table">
<div class="table-row table-row-th">
<div class="table-cell">{{ $t('pages.learn.courseDetail.chapter') }}</div>
<div class="table-cell w100">{{ $t('pages.learn.courseDetail.Lengthofstudy') }}</div>
<div class="table-cell w100">{{ $t('pages.learn.courseDetail.percent') }}</div>
</div>
<div class="table-row-group" v-for="(item, index) in videoList" :key="index">
<div class="table-row-group-th">{{ item.title }}</div>
<div class="table-row" v-for="(subItem, index) in item.sections" :key="index">
<div class="table-cell">{{ subItem.title }}</div>
<div class="table-cell w100">{{ formatDuration(subItem.duration) }}</div>
<div class="table-cell w100">{{ subItem.progress }}%</div>
</div>
</div>
<div class="empty-data" v-if="!videoList.length">{{ $t('pages.learn.courseDetail.Nodataavailable') }}</div>
</div>
</div>
<!-- 作业 -->
<div class="item">
<div class="item-title">
{{ $t('pages.learn.courseDetail.subjectivequestions') }}
</div>
<div class="table">
<div class="table-row table-row-th">
<div class="table-cell">{{ $t('pages.learn.courseDetail.chapter') }}</div>
<div class="table-cell w100">{{ $t('pages.learn.courseDetail.Submissiontime') }}</div>
<div class="table-cell w100">{{ $t('pages.learn.courseDetail.score') }}</div>
</div>
<div class="table-row-group" v-for="(item, index) in homeWorkList" :key="index">
<div class="table-row-group-th">{{ item.title }}</div>
<div class="table-row" v-for="(subItem, index) in item.sections" :key="index">
<div class="table-cell">{{ subItem.title }}</div>
<div class="table-cell w100">{{ subItem.created_time || '暂无提交' }}</div>
<div class="table-cell w100">{{ showCore(subItem.score) }}</div>
</div>
</div>
<div class="empty-data" v-if="!homeWorkList.length">{{ $t('pages.learn.courseDetail.Nodataavailable') }}</div>
</div>
</div>
<div class="item">
<div class="item-title">{{ $t('pages.learn.courseDetail.Bighomework') }}</div>
<div class="status-text">
{{ $t('pages.learn.courseDetail.Status') }}{{ essay.status || $t('action.courseAction.none') }}
</div>
<div class="status-text" v-if="essay.created_time">
{{ $t('pages.learn.courseDetail.Submissiontime') }}{{ essay.created_time }}
</div>
<div class="status-text">{{ $t('pages.learn.courseDetail.score2') }}{{ showCore(essay.score) }}</div>
</div>
</div>
</template>
<script>
export default {
props: { data: { type: Object, default: () => {} } },
computed: {
videoList() {
return this.data.video_evaluation || []
},
homeWorkList() {
return this.data.homework_evaluation || []
},
essay() {
return this.data.essay_evaluation || {}
}
},
methods: {
formatDuration(duration) {
const h = Math.floor(duration / 3600)
const m = Math.floor((duration - h * 3600) / 60)
const s = (duration - h * 3600 - m * 60) % 60
function tenify(a) {
return a >= 10 ? a : '0' + a
}
const to = { h: tenify(h), m: tenify(m), s: tenify(s) }
const format = 'h:m:s'
return format.replace(/h|m|s/g, k => to[k]).replace(/^00:/, '')
},
showCore(value) {
return value !== null ? value : this.$t('action.courseAction.none')
}
}
}
</script>
<style lang="scss">
.course-assess-progress {
.item {
padding: 0.1rem 0 0.2rem;
}
.item + .item {
border-top: 1px solid #c9c9c9;
}
.item-title {
padding: 0.1rem 0;
font-size: 0.16rem;
font-weight: 700;
color: #b49441;
}
.table {
margin: 10px 0;
}
.table-row {
display: flex;
}
.table-row-th {
font-weight: bold;
border-bottom: 1px solid #c9c9c9;
}
.table-row-group {
.table-row {
font-size: 12px;
&:hover {
background-color: #efefef;
}
}
}
.table-row-group-th {
font-weight: bold;
padding: 10px;
}
.table-cell {
padding: 5px 10px;
flex: 1;
&.w100 {
flex: 0 0 120px;
text-align: center;
}
}
.empty-data {
padding: 20px 0;
text-align: center;
}
.status-text {
padding-left: 0.1rem;
font-size: 0.14rem;
color: #000000;
line-height: 1.5;
}
}
</style>
<!--课程考核-->
<template>
<div class="course-assess-standard">
<div class="subtitle">
<span>{{ $t('pages.learn.courseDetail.Courseassessmentstandard') }}</span>
</div>
<div class="item">
<h2 class="item-title">一、最终成绩计算</h2>
<!-- 中方课程 -->
<p v-if="course.course_check_type === 1">
<template v-for="(item, index) in checkList">
<span :key="index">{{ index ? '+' : '' }}{{ item.name }}得分*{{ item.percent }}%</span>
</template>
= 该门课程总得分,满分100分,低于{{ data.course_check_pass_score }}分为不及格,需重修此门课程。
</p>
<!-- 美方课程 -->
<p v-else>美方课程最终成绩请参考每学期初教务邮箱老师发到大家邮箱中的课程考核大纲进行计算。</p>
<v-chart class="chart" :option="option" :autoresize="true" />
</div>
<div class="item">
<h2 class="item-title">二、具体细则</h2>
<div v-for="(item, index) in checkList" :key="index">
<div class="item-subtitle">{{ `${item.name} 总分${item.score}分(占科目总成绩的${item.percent}%)` }}</div>
<div v-html="item.content"></div>
</div>
</div>
</div>
</template>
<script>
import { use } from 'echarts/core'
import { CanvasRenderer } from 'echarts/renderers'
import { PieChart } from 'echarts/charts'
import { TitleComponent, TooltipComponent, LegendComponent } from 'echarts/components'
import VChart from 'vue-echarts'
use([CanvasRenderer, PieChart, TitleComponent, TooltipComponent, LegendComponent])
export default {
props: { course: { type: Object, default: () => {} }, data: { type: Object, default: () => {} } },
components: { VChart },
data() {
return {}
},
computed: {
checkList() {
return this.data.course_check.filter(item => parseInt(item.percent))
},
option() {
const data = this.checkList.map(item => {
return { name: item.name, value: item.percent }
})
return {
tooltip: { trigger: 'item', formatter: '{a} <br/>{b} 占比{c}%' },
series: [{ name: '课程考核', type: 'pie', data }]
}
}
}
}
</script>
<style lang="scss" scoped>
.chart {
height: 300px;
}
.course-assess-standard {
.item-title {
margin: 0;
font-size: 0.16rem;
font-weight: 700;
color: #313131;
line-height: 0.38rem;
}
.item-subtitle {
font-size: 0.14rem;
font-weight: 700;
color: #313131;
line-height: 0.3rem;
margin-top: 10px;
}
::v-deep p {
padding: 5px 0;
}
}
</style>
<template>
<div class="course-chapter">
<el-collapse v-model="activeNames">
<template v-for="item in chapters">
<el-collapse-item :title="item.name" :name="item.id" :key="item.id" v-if="item.children">
<ul>
<li v-for="subItem in item.children" :key="subItem.id" @click="handleClick(subItem)">
<div class="name">{{ subItem.name }}</div>
<div class="duration">
<!-- 视频 -->
<template v-if="subItem.video">{{ formatDuration(subItem.video.video_length) }}</template>
<!-- 直播 -->
<template v-if="subItem.live">
{{ subItem.live.start_time }}
{{ calcTimeText(subItem.live) }}
</template>
</div>
</li>
</ul>
</el-collapse-item>
<div class="el-collapse-item" :key="item.id" @click="handleClick(item)" v-else>
<div class="el-collapse-item__header">{{ item.name }}</div>
</div>
</template>
</el-collapse>
</div>
</template>
<script>
export default {
props: {
course: { type: Object, default: () => ({}) }
},
data() {
return {
activeNames: []
}
},
computed: {
sid() {
return this.$route.params.sid
},
cid() {
return this.$route.params.cid
},
// 章节列表
chapters() {
const chapters = this.course.chapters || []
const customeChapter = [
// { name: this.$t('viewerMain.courseWork'), id: 'course_work', type: 99 },
{ name: this.$t('viewerMain.courseData'), id: 'course_info', type: 100 }
// { name: this.$t('viewerMain.teachingEvaluation'), id: 'teach_evaluation', type: 102 }
]
// 课程大作业
if (this.course.curriculum && this.course.curriculum.curriculum_essay) {
customeChapter.unshift({ name: this.$t('viewerMain.courseWork'), id: 'course_work', type: 99 })
}
// 课程考试
if (this.course.course_examination) {
customeChapter.push({ name: this.$t('viewerMain.courseExam'), id: 'course_exam', type: 101 })
}
return chapters.concat(customeChapter)
}
},
methods: {
handleClick(data) {
// 直播
const live = data.live
if ([6, 8].includes(data.type) && live) {
const hasRecordUrl = live.enable_record && live.record_url
if ([3, 5].includes(live.live_status) && !hasRecordUrl) {
this.$message.error(this.$t('viewerMain.liveEnd'))
return
}
window.open(live.record_url || live.join_url, '_blank')
return
}
// 课程大作业
// if (data.id === 'course_work' && !this.course.survey) {
// this.$message(this.$t('viewerMain.teachingEvaluationTips'))
// return
// }
// 教学评估
if (data.id === 'teach_evaluation') {
const { sid, cid } = this.$route.params
this.$router.push({ name: 'survey', params: { sid, cid } })
return
}
this.$router.push({ name: 'viewerCourseChapter', params: { sid: this.sid, cid: this.cid, id: data.id } })
},
formatDuration(duration) {
const h = Math.floor(duration / 3600)
const m = Math.floor((duration - h * 3600) / 60)
const s = (duration - h * 3600 - m * 60) % 60
function tenify(a) {
return a >= 10 ? a : '0' + a
}
const to = { h: tenify(h), m: tenify(m), s: tenify(s) }
const format = 'h:m:s'
return format.replace(/h|m|s/g, k => to[k]).replace(/^00:/, '')
},
// 计算日期
calcTimeText(data) {
let { start_time: liveTime, live_status: liveStatus } = data
const map = {
1: this.$t('live.notStarted'),
2: this.$t('live.liveStreaming'),
3: this.$t('live.liveEnd'),
4: this.$t('live.start'),
5: this.$t('live.liveEnd')
}
let result = map[liveStatus] || liveTime
if (liveStatus === 1 && liveTime) {
liveTime = liveTime.replace(/-/g, '/')
const time = (new Date(liveTime).getTime() - new Date().getTime()) / 1000 || 0
if (time <= 5 * 60) {
result = this.$t('live.start')
} else if (time <= 1 * 60 * 60) {
result = this.$t('live.startInMinutes', {
minutes: parseInt(time / 60)
})
} else if (time <= 24 * 60 * 60) {
result = this.$t('live.startInHours', {
h: parseInt(time / (60 * 60)),
min: parseInt((time / 60) % 60)
})
} else {
result = this.$t('live.startInDay', {
day: parseInt(time / (24 * 60 * 60))
})
}
}
if (liveStatus === 3 && data.enable_record && data.record_url) {
result = this.$t('live.watchReplay')
}
return result
}
}
}
</script>
<style lang="scss" scoped>
.course-chapter {
padding: 0.2rem;
background-color: #fff;
}
.el-collapse {
border: 0;
}
::v-deep .el-collapse-item {
margin-bottom: 10px;
}
::v-deep .el-collapse-item__header {
font-size: 14px;
font-weight: 600;
color: #222;
background-color: #e5e5e5;
padding-left: 10px;
}
::v-deep .el-collapse-item__wrap {
border-bottom: 0;
}
::v-deep .el-collapse-item__content {
padding-bottom: 10px;
}
ul {
margin: 0;
padding: 0;
}
li {
display: flex;
padding: 10px;
cursor: pointer;
color: #666;
&:hover {
color: #c01540;
background-color: #f3f3f3;
}
.name {
flex: 1;
overflow: hidden;
}
.progress {
margin-left: 20px;
color: #999;
}
}
</style>
<!--课程讨论-->
<template>
<div>
<div class="publish" v-if="isPublicShow">
<div class="publish-header">
<el-button type="text" @click="gobackDiscuss">
{{ $t('pages.learn.courseDetail.Returntoquestionlist') }}
</el-button>
<div class="publish-title">
{{ $t('pages.learn.courseDetail.Releaseissues') }}
</div>
</div>
<el-form ref="setPublishform" :model="publish" :rules="publishRules" label-position="top">
<el-form-item :label="$t('pages.learn.courseDetail.title1')" prop="title">
<el-input
type="text"
:placeholder="$t('pages.learn.courseDetail.inputtitle1')"
v-model="publish.title"
></el-input>
</el-form-item>
<el-form-item :label="$t('pages.learn.courseDetail.Textcontent')" prop="contents">
<v-editor v-model="publish.contents"></v-editor>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmitPublish">{{
$t('pages.learn.courseDetail.Releaseissues')
}}</el-button>
</el-form-item>
</el-form>
</div>
<template v-else>
<div class="discuss-header">
<div class="discuss-btn" @click="isPublicShow = true">
<i class="el-icon-edit"></i>
{{ $t('pages.learn.courseDetail.Publishingissues') }}
</div>
<div class="aside">
<div class="discuss-btn" :class="{ 'is-active': sort === 'time' }" @click="handleSort('time')">
{{ $t('pages.learn.courseDetail.Sortbytime') }}
</div>
<div class="discuss-btn" :class="{ 'is-active': sort === 'tag' }" @click="handleSort('tag')">
{{ $t('pages.learn.courseDetail.Sortbyvote') }}
</div>
</div>
</div>
<div class="discuss-scroll">
<discuss :params="params"></discuss>
</div>
</template>
</div>
</template>
<script>
import * as api from '@/api/discuss'
import VEditor from '@/components/ckeditor'
export default {
components: { VEditor },
data() {
const { sid, cid } = this.$route.params
return {
sid,
cid,
isPublicShow: false,
publish: {
title: '',
contents: ''
},
publishRules: {
title: [{ required: true, message: this.$t('pages.learn.courseDetail.inputtitle1'), trigger: 'blur' }],
contents: [{ required: true, message: this.$t('pages.learn.courseDetail.inputTextcontent'), trigger: 'blur' }]
},
sort: '',
params: {
path: `/${sid}/${cid}`,
request: 'getCourseDiscussList',
dataJson: { limit: 10, offset: 0, sort: '' }
}
}
},
methods: {
/**
* 返回问题列表
*/
gobackDiscuss() {
this.isPublicShow = false
},
/**
* 问题发布 - 接口提交
*/
onSubmitPublish() {
this.$refs.setPublishform.validate(valid => {
if (valid) {
const params = Object.assign({}, this.publish, { course_id: this.cid, semester_id: this.sid })
api.publishQues(params).then(res => {
this.$message({ type: 'success', message: this.$t('pages.learn.courseDetail.publishSuccessTips') })
this.isPublicShow = false
this.$refs.setPublishform.resetFields()
})
}
})
},
/**
* 跳转到对应 问题详情页
*/
goDiscussDetail(e) {
const qid = e.currentTarget.dataset.id
this.$router.push({
path: `/app/learn/discuss-detail/${this.sid}/${this.cid}/${qid}`
})
},
/**
* 排序方式
*/
handleSort(sort) {
this.sort = this.sort === sort ? '' : sort
this.params = {
path: `/${this.sid}/${this.cid}`,
request: 'getCourseDiscussList',
dataJson: { limit: 10, offset: 0, sort: this.sort }
}
}
}
}
</script>
<style lang="scss">
/* 课程讨论 */
.discuss-header {
display: flex;
align-items: center;
justify-content: space-between;
.aside {
display: flex;
}
}
.discuss-btn {
padding: 0 0.3rem;
height: 0.42rem;
font-size: 0.2rem;
line-height: 0.42rem;
background: #fff;
border: 1rpx solid #dcdcdc;
cursor: pointer;
border-radius: 0.28rem;
white-space: nowrap;
&.is-active {
color: #fff;
background: #b49441;
}
}
.discuss-btn + .discuss-btn {
margin-left: 0.1rem;
}
// 发布
.publish {
padding: 0.3rem;
background-color: #f7f7f7;
}
.publish-header {
display: flex;
align-items: center;
justify-content: space-between;
}
.publish-title {
font-size: 0.2rem;
}
</style>
<!--课程列表最新直播-->
<template>
<div class="course-latest-live" v-if="data.live">
<div class="txt">{{ $t('pages.learn.course.title2') }}</div>
<div class="txt">
{{ $t('pages.learn.course.msg') }}{{ data.course_name }}{{ $t('pages.learn.course.msg1') }}
{{ data.live.start_time }}
{{ $t('pages.learn.course.msg2') }}
</div>
<el-button class="in-btn" type="primary" size="small" round @click="handleClick">
{{ $t('pages.learn.course.Enterlive') }}
</el-button>
</div>
</template>
<script>
import cAction from '@action'
export default {
data() {
return {
data: {},
timer: null
}
},
methods: {
// 进入直播
handleClick() {
// 5:CC直播; 6:腾讯会议; 8:Zoom
const live = this.data.live
if (live.type === 5) {
this.$router.push({
name: 'viewerCourseChapter',
params: { sid: this.data.semester_id, cid: this.data.course_id, id: this.data.chapter_id }
})
} else {
window.open(live.record_url || live.join_url)
}
},
// 获取最新直播
getLatestLive() {
cAction.Player.getNewLiveMsg().then(res => {
this.data = res.data
})
},
// 定时刷新直播列表
setTimer() {
this.timer = setInterval(this.getLatestLive, 10000)
},
// 清除定时刷新
clearTimer() {
this.timer && setInterval(this.timer)
}
},
mounted() {
this.getLatestLive()
// 定时刷新直播列表
// this.setTimer()
},
destroyed() {
this.clearTimer()
}
}
</script>
<style lang="scss">
.course-latest-live {
position: relative;
padding: 40px;
box-shadow: 0 1px 8px rgba(0, 0, 0, 0.1);
margin: 0.3rem;
background-color: #fff;
.txt {
font-size: 16px;
font-weight: bold;
padding-right: 100px;
}
.in-btn {
position: absolute;
right: 40px;
top: 50%;
transform: translateY(-50%);
background-color: #d21f28;
border-color: #d21f28;
}
}
</style>
<template>
<li class="course-list-item">
<div class="course-list-item-pic" @click="handleClick">
<img :src="data.src" v-if="data.src" />
<div class="no-img" v-else><i class="el-icon-self-13"></i></div>
</div>
<div class="course-list-item-main">
<div class="title" @click="handleClick">{{ data.title }}</div>
<div class="tags">
<template v-for="(item1, index) in data.arrTab">
<span v-bind:key="index">{{ item1 }}</span>
</template>
</div>
<div class="time">
{{ data.status }}<em>{{ data.time }}</em>
</div>
<div class="progress">
{{ $t('pages.learn.course.progress') }}
<el-progress :percentage="data.progress" color="#b49441"></el-progress>
</div>
</div>
<div class="course-list-item-aside">
<p>{{ data.myStatus }}</p>
<el-button type="primary" size="small" round @click="handleClick">
{{ $t('pages.learn.course.showCourse') }}
</el-button>
</div>
</li>
</template>
<script>
export default {
name: 'CourseListItem',
props: {
data: { type: Object, required: true },
showProgress: { type: Boolean, default: true }
},
data() {
return {}
},
methods: {
handleClick() {
this.$router.push({ path: `/app/learn/course-detail/${this.data.sid}/${this.data.id}` })
}
}
}
</script>
<style lang="scss">
.course-list-item {
display: flex;
padding: 0.2rem 0;
list-style: none;
}
.course-list-item + .course-list-item {
border-top: 1px solid #dcdcdc;
}
.course-list-item-pic {
position: relative;
width: 1.8rem;
height: 1rem;
cursor: pointer;
.no-img {
width: 100%;
height: 1rem;
text-align: center;
line-height: 1.1rem;
border: 1px solid #e2e2e2;
i {
font-size: 0.4rem;
color: #e2e2e2;
}
}
img {
display: block;
width: 100%;
height: 100%;
object-fit: cover;
}
}
.course-list-item-main {
flex: 1;
position: relative;
padding-left: 0.2rem;
.title {
width: 80%;
line-height: 1.5;
font-weight: 700;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
cursor: pointer;
}
.tags {
margin: 0.05rem 0;
font-size: 0.14rem;
span {
padding: 0 0.1rem;
margin: 0;
border-right: 1px solid #313131;
&:first-child {
padding-left: 0;
}
&:last-child {
border: none;
}
}
}
.time {
font-size: 0.12rem;
em {
font-style: normal;
color: #898989;
}
}
.progress {
margin-top: 0.05rem;
font-size: 14px;
.el-progress {
width: 50%;
display: inline-block;
vertical-align: text-bottom;
}
}
}
.course-list-item-aside {
display: flex;
flex-direction: column;
justify-content: space-between;
p {
padding: 0 0.1rem;
font-size: 0.14rem;
text-align: right;
}
}
</style>
<template>
<div class="course-live">
<template v-if="meetings.length">
<div class="course-live-item" v-for="item in meetings" :key="item.id" @click="handleClick(item)">
<div class="name"><i class="el-icon-video-play"></i>{{ item.topic }}</div>
<div class="aside">{{ item.start_time }} {{ calcTimeText(item) }}</div>
</div>
</template>
<div class="empty-data" v-else>暂无相关直播</div>
</div>
</template>
<script>
export default {
name: 'CourseLive',
props: { course: { type: Object, default: () => ({}) } },
data() {
return {}
},
computed: {
meetings() {
return this.course.meetings || []
}
},
methods: {
handleClick(live) {
// 直播
const hasRecordUrl = live.enable_record && live.record_url
if ([3, 5].includes(live.live_status) && !hasRecordUrl) {
this.$message.error(this.$t('viewerMain.liveEnd'))
return
}
window.open(live.record_url || live.join_url, '_blank')
},
// 计算日期
calcTimeText(data) {
let { start_time: liveTime, live_status: liveStatus } = data
const map = {
1: this.$t('live.notStarted'),
2: this.$t('live.liveStreaming'),
3: this.$t('live.liveEnd'),
4: this.$t('live.start'),
5: this.$t('live.liveEnd')
}
let result = map[liveStatus] || liveTime
if (liveStatus === 1 && liveTime) {
liveTime = liveTime.replace(/-/g, '/')
const time = (new Date(liveTime).getTime() - new Date().getTime()) / 1000 || 0
if (time <= 5 * 60) {
result = this.$t('live.start')
} else if (time <= 1 * 60 * 60) {
result = this.$t('live.startInMinutes', {
minutes: parseInt(time / 60)
})
} else if (time <= 24 * 60 * 60) {
result = this.$t('live.startInHours', {
h: parseInt(time / (60 * 60)),
min: parseInt((time / 60) % 60)
})
} else {
result = this.$t('live.startInDay', {
day: parseInt(time / (24 * 60 * 60))
})
}
}
if (liveStatus === 3 && data.enable_record && data.record_url) {
result = this.$t('live.watchReplay')
}
return result
}
}
}
</script>
<style lang="scss" scoped>
.course-live {
padding: 0.2rem;
background-color: #fff;
}
.course-live-item {
display: flex;
align-items: center;
justify-content: space-between;
cursor: pointer;
padding: 5px;
i {
margin-right: 0.05rem;
font-size: 0.2rem;
vertical-align: middle;
}
.name {
line-height: 0.3rem;
}
.aside {
color: #666;
}
&:hover {
color: #c01540;
background-color: #f3f3f3;
}
}
.course-live-item + .course-live-item {
margin-top: 10px;
}
.empty-data {
font-size: 0.24rem;
color: #112c42;
line-height: 1rem;
text-align: center;
}
</style>
<template>
<div class="teacher">
<div class="teacher-item" v-for="item in data" :key="item.id">
<img :src="item.lecturer_avatar" class="teacher-item-pic" />
<div class="teacher-item-content">
<p class="t1">{{ item.lecturer_name }}</p>
<p class="t2">{{ item.lecturer_education }}</p>
<p class="t2">{{ item.lecturer_office }}</p>
<p class="t2">{{ item.lecturer_title }}</p>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
data: { type: Array, default: () => [] }
}
}
</script>
<style lang="scss" scoped>
.teacher-item {
display: flex;
margin-bottom: 10px;
}
.teacher-item-pic {
width: 90px;
height: 110px;
object-fit: cover;
margin-right: 10px;
}
.teacher-item-content {
flex: 1;
.t1 {
font-weight: bold;
}
.t2 {
font-size: 13px;
margin-top: 5px;
color: #707070;
}
}
</style>
<template>
<app-container :title="$t('pages.learn.courseDetail.title')" v-loading="loading">
<div class="course-top">
<div class="course-top-hd">
<div class="course-top-hd-left">
<div class="course-top__title">{{ curriculum.curriculum_name }}</div>
<div class="course-top__text" v-html="topText"></div>
<div class="course-top__progress">
{{ $t('pages.learn.courseDetail.Videoviewingprogress') }}
<el-progress :percentage="detail.video_progress" color="#b49441"></el-progress>
</div>
</div>
<div class="course-top-hd-right">
<el-button type="primary" size="small" @click="onChapterClick(latestVideo)" v-if="latestVideo">
{{ buttonText }}
</el-button>
</div>
</div>
<div class="course-top-bd">
<div class="course-top__pic"><img :src="curriculum.curriculum_picture" /></div>
<div class="course-top__content" v-html="curriculum.curriculum_represent"></div>
</div>
</div>
<div class="course-bottom">
<div class="course-bottom-left">
<el-tabs v-model="tabActive">
<el-tab-pane lazy :label="$t('pages.learn.courseDetail.Coursecontent')">
<course-chapter :course="detail"></course-chapter>
</el-tab-pane>
<el-tab-pane lazy :label="$t('pages.learn.courseDetail.Coursediscussion')">
<course-discuss :course="detail"></course-discuss>
</el-tab-pane>
<el-tab-pane lazy :label="$t('pages.learn.courseDetail.Courseassessment')">
<course-assessment :course="detail"></course-assessment>
</el-tab-pane>
<el-tab-pane lazy label="课程直播">
<course-live :course="detail"></course-live>
</el-tab-pane>
</el-tabs>
</div>
<div class="course-bottom-right">
<el-tabs>
<el-tab-pane label="课程讲师">
<course-teacher :data="detail.lecturers"></course-teacher>
</el-tab-pane>
</el-tabs>
</div>
</div>
</app-container>
</template>
<script>
import AppContainer from '@/components/AppContainer'
import CourseChapter from './components/CourseChapter'
import CourseDiscuss from './components/CourseDiscuss'
import CourseAssessment from './components/CourseAssessment'
import CourseLive from './components/CourseLive'
import CourseTeacher from './components/CourseTeacher'
import * as api from '@/api/course'
export default {
components: { AppContainer, CourseChapter, CourseDiscuss, CourseAssessment, CourseLive, CourseTeacher },
data() {
return {
tabActive: '0',
loading: false,
detail: {
chapters: []
}
}
},
computed: {
sid() {
return this.$route.params.sid
},
cid() {
return this.$route.params.cid
},
curriculum() {
return this.detail.curriculum || {}
},
buttonText() {
return this.detail.latest_play
? this.$t('pages.learn.courseDetail.Keeplearning')
: this.$t('pages.learn.courseDetail.Startlearning')
},
// 扁平化章节数据
flatChapters() {
return this.detail.chapters.reduce((result, item) => {
return result.concat(item.children)
}, [])
},
// 最新的视频
latestVideo() {
if (this.detail.latest_play && this.flatChapters.length) {
return this.flatChapters.find(item => item.resource_id === this.detail.latest_play)
} else {
return this.flatChapters.length ? this.flatChapters[0] : null
}
},
courseType() {
const map = {
1: this.$t('action.courseAction.mustLearn'),
2: this.$t('action.courseAction.changeLearn'),
3: this.$t('action.courseAction.repeatLearn')
}
return map[this.detail.course_type]
},
topText() {
if (this.loading) {
return ''
}
// 学分
let output = `${this.curriculum.curriculum_credit}${this.$t('action.courseAction.credit')}`
// 课程
output += ` | ${this.courseType} | ${this.detail.semester_name} `
// 时间
if (this.detail.begin_date) {
output += this.detail.begin_date + this.$t('action.courseAction.to') + this.detail.end_date + ' '
}
// 发布状态
output += this.curriculum.is_enabled
? this.$t('action.courseAction.publish')
: this.$t('action.courseAction.noPublish')
return output
}
},
methods: {
// 课程学习
getCourse() {
this.loading = true
api
.getCourse(this.sid, this.cid)
.then(response => {
this.detail = response
})
.finally(() => {
this.loading = false
})
},
onChapterClick(data) {
this.$router.push({ name: 'viewerCourseChapter', params: { cid: this.cid, id: data.id } })
}
},
beforeMount() {
this.getCourse()
}
}
</script>
<style lang="scss" scoped>
.main-container {
height: 100%;
padding: 30px;
background-color: #fff;
border-radius: 8px;
box-sizing: border-box;
}
.course-top {
padding-bottom: 20px;
}
.course-top-hd {
display: flex;
justify-content: space-between;
padding-bottom: 10px;
}
.course-top-hd-left {
flex: 1;
}
.course-top__title {
font-size: 18px;
font-weight: bold;
line-height: 1;
}
.course-top__text {
margin-top: 10px;
}
.course-top__progress {
margin-top: 10px;
display: flex;
align-items: center;
.el-progress {
width: 50%;
margin: 0 10px;
}
}
.course-top-bd {
display: flex;
}
.course-top__pic {
width: 160px;
height: 100px;
margin-right: 20px;
border-radius: 2px;
overflow: hidden;
img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
.course-top__content {
flex: 1;
line-height: 24px;
overflow: hidden;
}
.course-bottom {
display: flex;
}
.course-bottom-left {
flex: 1;
overflow: hidden;
}
.course-bottom-right {
margin-left: 20px;
width: 300px;
}
</style>
<template>
<div>
<!-- 最新直播 -->
<course-latest-live />
<div class="con-title">{{ $t('pages.learn.course.title') }}</div>
<!-- 筛选 -->
<div class="con-box">
<template v-for="(item, index) in find">
<ul v-bind:key="index" class="tabs-list">
<template v-if="find[index].arrItem.length">
<li class="tabs-hd">{{ item.name }}</li>
<template v-for="(item1, index1) in item.arrItem">
<li v-bind:key="index1">
<div
:class="['tab', item.selectIndex == index1 ? 'on' : '']"
@click="selFindSelect"
:data-index="index1"
:data-i="index"
:data-key="item.key"
:data-val="item1.val"
>
{{ item1.name }}
</div>
</li>
</template>
</template>
</ul>
</template>
</div>
<!-- 排序 -->
<div class="switch-box">
<el-button type="info" size="medium" plain @click="studyEarlyUpdate">
{{ $t('pages.learn.course.lastLearn') }}
<i :class="['el-icon-caret-' + (filter.studyEarly == 'down' ? 'bottom' : 'top'), 'icon']"></i>
</el-button>
<el-button type="info" size="medium" plain @click="selectTimeUpdate">
{{ $t('pages.learn.course.updateTime') }}
<i :class="['el-icon-caret-' + (filter.selectTime == 'down' ? 'bottom' : 'top'), 'icon']"></i>
</el-button>
<!--
<el-button class="rbtn" type="primary" size="medium" icon="el-icon-self-cc-book icon" @click="goCourseAll">
{{ $t('pages.learn.course.changeCourse') }}
</el-button>
-->
</div>
<!-- 课程列表 -->
<div class="con-box" v-loading="loading">
<ul class="course-list" v-if="homeList.length">
<course-list-item v-for="(item, index) in homeList" :data="item" :key="index"></course-list-item>
</ul>
<div class="no-data" v-else>{{ $t('pages.learn.course.noCourseStr') }}</div>
</div>
</div>
</template>
<script>
import cAction from '@action'
import CourseLatestLive from './course/components/CourseLatestLive.vue'
import CourseListItem from './components/CourseListItem'
export default {
components: { CourseLatestLive, CourseListItem },
data() {
return {
filter: {
studyEarly: 'down',
selectTime: 'down'
},
find: [
{
name: this.$t('pages.learn.course.semeter'),
isShow: false,
selectIndex: 0,
key: 'semester_id',
arrItem: [] // 从后台请求
},
{
name: this.$t('pages.learn.course.courseType'),
isShow: false,
selectIndex: 0,
key: 'course_type',
arrItem: [
{
val: '-1',
name: this.$t('pages.learn.course.allLearn')
},
{
val: '1',
name: this.$t('pages.learn.course.mustLearn')
},
{
val: '2',
name: this.$t('pages.learn.course.changeLearn')
},
{
val: '3',
name: this.$t('pages.learn.course.repeatLearn')
}
]
}
],
homeList: [], // 从后台请求
param: {},
loading: false
}
},
mounted() {
cAction.Course.getLearnFind()
.then(data => {
this.find[0].arrItem = data
this.getAjaxList(true, this.$t('pages.learn.course.goCourseAllStr'))
})
.catch(e => {
this.$message.error(e.message)
})
.finally(() => {})
},
methods: {
goCourseAll() {
this.$router.push({
path: '/app/learn/course-all'
})
},
getAjaxList(bool, str) {
this.loading = true
cAction.Course.getCourseList(bool, this.param)
.then(json => {
this.homeList = json
})
.finally(() => {
this.loading = false
})
},
/**
* 分类选择 - 选中某一项
*/
selFindSelect(e) {
const _data = e.currentTarget.dataset
const index = _data.index
const json = this.find
const i = _data.i
json[i].selectIndex = index
json[i].isShow = false
if (_data.val === '-1') {
delete this.param[_data.key]
} else {
this.param[_data.key] = _data.val
}
/* 调用接口 */
this.getAjaxList(true, this.$t('pages.learn.course.noFitCourseStr'))
},
/**
* 筛选 - 最近学习顺序
*/
studyEarlyUpdate() {
const na = this.filter.studyEarly === 'up' ? 'down' : 'up'
this.filter.studyEarly = na
if (na === 'down') {
this.param.order_type = 'learn_time'
} else if (na === 'up') {
this.param.order_type = '-learn_time'
}
this.getAjaxList(true, this.$t('pages.learn.course.goCourseAllStr'))
},
/**
* 筛选 - 选修时间顺序
*/
selectTimeUpdate() {
const na = this.filter.selectTime === 'up' ? 'down' : 'up'
this.filter.selectTime = na
if (na === 'down') {
this.param.order_type = 'join_time'
} else if (na === 'up') {
this.param.order_type = '-join_time'
}
this.getAjaxList(true, this.$t('pages.learn.course.goCourseAllStr'))
}
}
}
</script>
<style lang="scss" scoped>
/* 列表 筛选 */
ul.tabs-list {
float: left;
width: 100%;
margin: 0 0 0.15rem 0;
padding: 0;
font-size: 0.16rem;
line-height: 1.5;
border-top: 1px solid #e8e8e8;
&:last-child {
margin-bottom: 0;
}
.tabs-hd {
display: inline-block;
color: #fff;
padding: 5px 0 9px;
margin-top: -5px;
width: 94px;
text-align: center;
background: url('~@/assets/images/type.png') no-repeat 0 0;
}
li {
float: left;
list-style: none;
padding: 0.1rem 0;
margin-right: 0.2rem;
.tab {
padding: 0 0.1rem;
cursor: pointer;
&.on {
background: #b49441;
color: #ffffff;
}
&:focus,
&:hover {
color: #b49441;
background: #eeeeee;
}
}
}
}
/* 筛选按钮 */
.switch-box {
margin: 0 0.3rem;
.icon {
margin-left: 0.1rem;
}
.rbtn {
float: right;
}
}
/* 课程列表 */
ul.course-list {
margin: 0;
padding: 0;
font-size: 0.18rem;
color: #313131;
}
.no-data {
text-align: center;
line-height: 2rem;
}
@media (max-width: 767px) {
.switch-box {
margin: 0;
}
}
</style>
...@@ -45,7 +45,7 @@ export default [ ...@@ -45,7 +45,7 @@ export default [
}, },
{ {
path: 'course-detail/:sid/:cid', path: 'course-detail/:sid/:cid',
component: () => import('../pages/learn/courseDetail.vue'), component: () => import('../pages/learn/course/detail.vue'),
props: true props: true
}, },
{ {
...@@ -211,5 +211,6 @@ export default [ ...@@ -211,5 +211,6 @@ export default [
props: true props: true
}, },
{ path: '/403', name: '403', component: () => import('@/pages/exception/403.vue') }, { path: '/403', name: '403', component: () => import('@/pages/exception/403.vue') },
{ path: '/browser', name: 'browser', component: () => import('@/pages/exception/browser.vue') } { path: '/browser', name: 'browser', component: () => import('@/pages/exception/browser.vue') },
{ path: '/editor', name: 'editor', component: () => import('@/components/ckeditor/index.vue') }
] ]
...@@ -12,7 +12,9 @@ body { ...@@ -12,7 +12,9 @@ body {
font-family: 'Source Han Sans CN', 'PingFang SC', -apple-system, 'Microsoft YaHei', 'Helvetica', 'Arial', Verdana, font-family: 'Source Han Sans CN', 'PingFang SC', -apple-system, 'Microsoft YaHei', 'Helvetica', 'Arial', Verdana,
'Hiragino Sans GB', 'Wenquanyi Micro Hei', sans-serif; 'Hiragino Sans GB', 'Wenquanyi Micro Hei', sans-serif;
} }
p {
margin: 0;
}
/* 公共标题 - 样式 /app/learn */ /* 公共标题 - 样式 /app/learn */
.con-title { .con-title {
padding: 0 30px; padding: 0 30px;
...@@ -71,6 +73,7 @@ body { ...@@ -71,6 +73,7 @@ body {
font-weight: 700; font-weight: 700;
color: #313131; color: #313131;
line-height: 0.3rem; line-height: 0.3rem;
margin-top: 10px;
} }
.course-assess .detail .p { .course-assess .detail .p {
font-size: 0.14rem; font-size: 0.14rem;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论