Commit f8d9b028 by zangsuyun

feat:知识库

parent 3d5c4f30
...@@ -42,6 +42,107 @@ ...@@ -42,6 +42,107 @@
"resize-observer-polyfill": "^1.5.0" "resize-observer-polyfill": "^1.5.0"
} }
}, },
"@antv/adjust": {
"version": "0.1.1",
"resolved": "http://npm.ixm5.cn:4873/@antv%2fadjust/-/adjust-0.1.1.tgz",
"integrity": "sha512-9FaMOyBlM4AgoRL0b5o0VhEKAYkexBNUrxV8XmpHU/9NBPJONBOB/NZUlQDqxtLItrt91tCfbAuMQmF529UX2Q==",
"requires": {
"@antv/util": "~1.3.1"
}
},
"@antv/attr": {
"version": "0.1.2",
"resolved": "http://npm.ixm5.cn:4873/@antv%2fattr/-/attr-0.1.2.tgz",
"integrity": "sha512-QXjP+T2I+pJQcwZx1oCA4tipG43vgeCeKcGGKahlcxb71OBAzjJZm1QbF4frKXcnOqRkxVXtCr70X9TRair3Ew==",
"requires": {
"@antv/util": "~1.3.1"
}
},
"@antv/component": {
"version": "0.3.9",
"resolved": "http://npm.ixm5.cn:4873/@antv%2fcomponent/-/component-0.3.9.tgz",
"integrity": "sha512-Knh/Nq0S8UkTfZj4SL7XizagTfXYqjFAYIqFtOmUaKpRMgccUi7p1oA7fJdNPGktkndljy6fUmCWocEeBXRS2g==",
"requires": {
"@antv/attr": "~0.1.2",
"@antv/g": "~3.3.5",
"@antv/util": "~1.3.1",
"wolfy87-eventemitter": "~5.1.0"
},
"dependencies": {
"@antv/g": {
"version": "3.3.6",
"resolved": "http://npm.ixm5.cn:4873/@antv%2fg/-/g-3.3.6.tgz",
"integrity": "sha512-2GtyTz++s0BbN6s0ZL2/nrqGYCkd52pVoNH92YkrTdTOvpO6Z4DNoo6jGVgZdPX6Nzwli6yduC8MinVAhE8X6g==",
"requires": {
"@antv/gl-matrix": "~2.7.1",
"@antv/util": "~1.3.1",
"d3-ease": "~1.0.3",
"d3-interpolate": "~1.1.5",
"d3-timer": "~1.0.6",
"wolfy87-eventemitter": "~5.1.0"
}
}
}
},
"@antv/coord": {
"version": "0.1.0",
"resolved": "http://npm.ixm5.cn:4873/@antv%2fcoord/-/coord-0.1.0.tgz",
"integrity": "sha512-W1R8h3Jfb3AfMBVfCreFPMVetgEYuwHBIGn0+d3EgYXe2ckOF8XWjkpGF1fZhOMHREMr+Gt27NGiQh8yBdLUgg==",
"requires": {
"@antv/util": "~1.3.1"
}
},
"@antv/g": {
"version": "3.4.10",
"resolved": "http://npm.ixm5.cn:4873/@antv%2fg/-/g-3.4.10.tgz",
"integrity": "sha512-pKy/L1SyRBsXuujdkggqrdBA0/ciAgHiArYBdIJsxHRxCneUP01wGwHdGfDayh2+S0gcSBHynjhoEahsaZaLkw==",
"requires": {
"@antv/gl-matrix": "~2.7.1",
"@antv/util": "~1.3.1",
"d3-ease": "~1.0.3",
"d3-interpolate": "~1.1.5",
"d3-timer": "~1.0.6",
"detect-browser": "^5.1.0"
}
},
"@antv/g2": {
"version": "3.5.17",
"resolved": "http://npm.ixm5.cn:4873/@antv%2fg2/-/g2-3.5.17.tgz",
"integrity": "sha512-gOjfA6pwXYEC5mrLbvg1kA3jZI5J5T2kQeGse+iBBsNc1Vje7zs9G+BleUaI4MLXSnqwhsj/ohfkP7d+h4ArNg==",
"requires": {
"@antv/adjust": "~0.1.0",
"@antv/attr": "~0.1.2",
"@antv/component": "~0.3.3",
"@antv/coord": "~0.1.0",
"@antv/g": "~3.4.10",
"@antv/scale": "~0.1.1",
"@antv/util": "~1.3.1",
"venn.js": "~0.2.20",
"wolfy87-eventemitter": "~5.1.0"
}
},
"@antv/gl-matrix": {
"version": "2.7.1",
"resolved": "http://npm.ixm5.cn:4873/@antv%2fgl-matrix/-/gl-matrix-2.7.1.tgz",
"integrity": "sha512-oOWcVNlpELIKi9x+Mm1Vwbz8pXfkbJKykoCIOJ/dNK79hSIANbpXJ5d3Rra9/wZqK6MC961B7sybFhPlLraT3Q=="
},
"@antv/scale": {
"version": "0.1.5",
"resolved": "http://npm.ixm5.cn:4873/@antv%2fscale/-/scale-0.1.5.tgz",
"integrity": "sha512-7RAu4iH5+Hk21h6+aBMiDTfmLf4IibK2SWjx/+E4f4AXRpqucO+8u7IbZdFkakAWxvqhJtN3oePJuTKqOMcmlg==",
"requires": {
"@antv/util": "~1.3.1",
"fecha": "~2.3.3"
}
},
"@antv/util": {
"version": "1.3.1",
"resolved": "http://npm.ixm5.cn:4873/@antv%2futil/-/util-1.3.1.tgz",
"integrity": "sha512-cbUta0hIJrKEaW3eKoGarz3Ita+9qUPF2YzTj8A6wds/nNiy20G26ztIWHU+5ThLc13B1n5Ik52LbaCaeg9enA==",
"requires": {
"@antv/gl-matrix": "^2.7.1"
}
},
"@babel/code-frame": { "@babel/code-frame": {
"version": "7.12.11", "version": "7.12.11",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz",
...@@ -2363,11 +2464,26 @@ ...@@ -2363,11 +2464,26 @@
} }
} }
}, },
"align-text": {
"version": "0.1.4",
"resolved": "http://npm.ixm5.cn:4873/align-text/-/align-text-0.1.4.tgz",
"integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=",
"requires": {
"kind-of": "^3.0.2",
"longest": "^1.0.1",
"repeat-string": "^1.5.2"
}
},
"alphanum-sort": { "alphanum-sort": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz", "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz",
"integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=" "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM="
}, },
"amdefine": {
"version": "1.0.1",
"resolved": "http://npm.ixm5.cn:4873/amdefine/-/amdefine-1.0.1.tgz",
"integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU="
},
"ansi-colors": { "ansi-colors": {
"version": "3.2.4", "version": "3.2.4",
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz",
...@@ -3689,6 +3805,15 @@ ...@@ -3689,6 +3805,15 @@
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
"integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
}, },
"center-align": {
"version": "0.1.3",
"resolved": "http://npm.ixm5.cn:4873/center-align/-/center-align-0.1.3.tgz",
"integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=",
"requires": {
"align-text": "^0.1.3",
"lazy-cache": "^1.0.3"
}
},
"chalk": { "chalk": {
"version": "2.4.2", "version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
...@@ -4112,6 +4237,11 @@ ...@@ -4112,6 +4237,11 @@
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
"integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
}, },
"contour_plot": {
"version": "0.0.1",
"resolved": "http://npm.ixm5.cn:4873/contour_plot/-/contour_plot-0.0.1.tgz",
"integrity": "sha1-R1hw8DK44zhBKqX8UHiA8L9JXHc="
},
"convert-source-map": { "convert-source-map": {
"version": "1.7.0", "version": "1.7.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz",
...@@ -4632,6 +4762,52 @@ ...@@ -4632,6 +4762,52 @@
"type": "^1.0.1" "type": "^1.0.1"
} }
}, },
"d3-color": {
"version": "1.4.1",
"resolved": "http://npm.ixm5.cn:4873/d3-color/-/d3-color-1.4.1.tgz",
"integrity": "sha512-p2sTHSLCJI2QKunbGb7ocOh7DgTAn8IrLx21QRc/BSnodXM4sv6aLQlnfpvehFMLZEfBc6g9pH9SWQccFYfJ9Q=="
},
"d3-dispatch": {
"version": "1.0.6",
"resolved": "http://npm.ixm5.cn:4873/d3-dispatch/-/d3-dispatch-1.0.6.tgz",
"integrity": "sha512-fVjoElzjhCEy+Hbn8KygnmMS7Or0a9sI2UzGwoB7cCtvI1XpVN9GpoYlnb3xt2YV66oXYb1fLJ8GMvP4hdU1RA=="
},
"d3-ease": {
"version": "1.0.7",
"resolved": "http://npm.ixm5.cn:4873/d3-ease/-/d3-ease-1.0.7.tgz",
"integrity": "sha512-lx14ZPYkhNx0s/2HX5sLFUI3mbasHjSSpwO/KaaNACweVwxUruKyWVcb293wMv1RqTPZyZ8kSZ2NogUZNcLOFQ=="
},
"d3-interpolate": {
"version": "1.1.6",
"resolved": "http://npm.ixm5.cn:4873/d3-interpolate/-/d3-interpolate-1.1.6.tgz",
"integrity": "sha512-mOnv5a+pZzkNIHtw/V6I+w9Lqm9L5bG3OTXPM5A+QO0yyVMQ4W1uZhR+VOJmazaOZXri2ppbiZ5BUNWT0pFM9A==",
"requires": {
"d3-color": "1"
}
},
"d3-selection": {
"version": "1.4.2",
"resolved": "http://npm.ixm5.cn:4873/d3-selection/-/d3-selection-1.4.2.tgz",
"integrity": "sha512-SJ0BqYihzOjDnnlfyeHT0e30k0K1+5sR3d5fNueCNeuhZTnGw4M4o8mqJchSwgKMXCNFo+e2VTChiSJ0vYtXkg=="
},
"d3-timer": {
"version": "1.0.10",
"resolved": "http://npm.ixm5.cn:4873/d3-timer/-/d3-timer-1.0.10.tgz",
"integrity": "sha512-B1JDm0XDaQC+uvo4DT79H0XmBskgS3l6Ve+1SBCfxgmtIb1AVrPIoqd+nPSv+loMX8szQ0sVUhGngL7D5QPiXw=="
},
"d3-transition": {
"version": "1.3.2",
"resolved": "http://npm.ixm5.cn:4873/d3-transition/-/d3-transition-1.3.2.tgz",
"integrity": "sha512-sc0gRU4PFqZ47lPVHloMn9tlPcv8jxgOQg+0zjhfZXMQuvppjG6YuwdMBE0TuqCZjeJkLecku/l9R0JPcRhaDA==",
"requires": {
"d3-color": "1",
"d3-dispatch": "1",
"d3-ease": "1",
"d3-interpolate": "1",
"d3-selection": "^1.1.0",
"d3-timer": "1"
}
},
"damerau-levenshtein": { "damerau-levenshtein": {
"version": "1.0.6", "version": "1.0.6",
"resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.6.tgz", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.6.tgz",
...@@ -4790,6 +4966,11 @@ ...@@ -4790,6 +4966,11 @@
} }
} }
}, },
"defined": {
"version": "1.0.0",
"resolved": "http://npm.ixm5.cn:4873/defined/-/defined-1.0.0.tgz",
"integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM="
},
"degenerator": { "degenerator": {
"version": "1.0.4", "version": "1.0.4",
"resolved": "https://registry.npmjs.org/degenerator/-/degenerator-1.0.4.tgz", "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-1.0.4.tgz",
...@@ -4876,6 +5057,11 @@ ...@@ -4876,6 +5057,11 @@
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
"integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
}, },
"detect-browser": {
"version": "5.2.0",
"resolved": "http://npm.ixm5.cn:4873/detect-browser/-/detect-browser-5.2.0.tgz",
"integrity": "sha512-tr7XntDAu50BVENgQfajMLzacmSe34D+qZc4zjnniz0ZVuw/TZcLcyxHQjYpJTM36sGEkZZlYLnIM1hH7alTMA=="
},
"detect-newline": { "detect-newline": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz",
...@@ -5097,6 +5283,14 @@ ...@@ -5097,6 +5283,14 @@
"resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz",
"integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==" "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA=="
}, },
"dotignore": {
"version": "0.1.2",
"resolved": "http://npm.ixm5.cn:4873/dotignore/-/dotignore-0.1.2.tgz",
"integrity": "sha512-UGGGWfSauusaVJC+8fgV+NVvBXkCTmVv7sk6nojDZZvuOUNGUy0Zk4UpHQD6EDjS0jpBwcACvH4eofvyzBcRDw==",
"requires": {
"minimatch": "^3.0.4"
}
},
"duplexer": { "duplexer": {
"version": "0.1.2", "version": "0.1.2",
"resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz",
...@@ -6166,6 +6360,11 @@ ...@@ -6166,6 +6360,11 @@
"bser": "2.1.1" "bser": "2.1.1"
} }
}, },
"fecha": {
"version": "2.3.3",
"resolved": "http://npm.ixm5.cn:4873/fecha/-/fecha-2.3.3.tgz",
"integrity": "sha512-lUGBnIamTAwk4znq5BcqsDaxSmZ9nDVJaij6NvRt/Tg4R69gERA+otPKbS86ROw9nxVMw2/mp1fnaiWqbs6Sdg=="
},
"figgy-pudding": { "figgy-pudding": {
"version": "3.5.2", "version": "3.5.2",
"resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz",
...@@ -6311,11 +6510,31 @@ ...@@ -6311,11 +6510,31 @@
"readable-stream": "^2.3.6" "readable-stream": "^2.3.6"
} }
}, },
"fmin": {
"version": "0.0.2",
"resolved": "http://npm.ixm5.cn:4873/fmin/-/fmin-0.0.2.tgz",
"integrity": "sha1-Wbu0DUP/3ByUzQClaMQflfGXMBc=",
"requires": {
"contour_plot": "^0.0.1",
"json2module": "^0.0.3",
"rollup": "^0.25.8",
"tape": "^4.5.1",
"uglify-js": "^2.6.2"
}
},
"follow-redirects": { "follow-redirects": {
"version": "1.13.1", "version": "1.13.1",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.1.tgz", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.1.tgz",
"integrity": "sha512-SSG5xmZh1mkPGyKzjZP8zLjltIfpW32Y5QpdNJyjcfGxK3qo3NDDkZOZSFiGn1A6SclQxY9GzEwAHQ3dmYRWpg==" "integrity": "sha512-SSG5xmZh1mkPGyKzjZP8zLjltIfpW32Y5QpdNJyjcfGxK3qo3NDDkZOZSFiGn1A6SclQxY9GzEwAHQ3dmYRWpg=="
}, },
"for-each": {
"version": "0.3.3",
"resolved": "http://npm.ixm5.cn:4873/for-each/-/for-each-0.3.3.tgz",
"integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
"requires": {
"is-callable": "^1.1.3"
}
},
"for-in": { "for-in": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
...@@ -6772,6 +6991,11 @@ ...@@ -6772,6 +6991,11 @@
} }
} }
}, },
"has-bigints": {
"version": "1.0.1",
"resolved": "http://npm.ixm5.cn:4873/has-bigints/-/has-bigints-1.0.1.tgz",
"integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA=="
},
"has-flag": { "has-flag": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
...@@ -7573,6 +7797,11 @@ ...@@ -7573,6 +7797,11 @@
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
"integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0="
}, },
"is-bigint": {
"version": "1.0.1",
"resolved": "http://npm.ixm5.cn:4873/is-bigint/-/is-bigint-1.0.1.tgz",
"integrity": "sha512-J0ELF4yHFxHy0cmSxZuheDOz2luOdVvqjwmEcj8H/L1JHeuEDSDbeRP+Dk9kFVk5RTFzbucJ2Kb9F7ixY2QaCg=="
},
"is-binary-path": { "is-binary-path": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
...@@ -7581,6 +7810,14 @@ ...@@ -7581,6 +7810,14 @@
"binary-extensions": "^2.0.0" "binary-extensions": "^2.0.0"
} }
}, },
"is-boolean-object": {
"version": "1.1.0",
"resolved": "http://npm.ixm5.cn:4873/is-boolean-object/-/is-boolean-object-1.1.0.tgz",
"integrity": "sha512-a7Uprx8UtD+HWdyYwnD1+ExtTgqQtD2k/1yJgtXP6wnMm8byhkoTZRl+95LLThpzNZJ5aEvi46cdH+ayMFRwmA==",
"requires": {
"call-bind": "^1.0.0"
}
},
"is-buffer": { "is-buffer": {
"version": "1.1.6", "version": "1.1.6",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
...@@ -7706,6 +7943,11 @@ ...@@ -7706,6 +7943,11 @@
"kind-of": "^3.0.2" "kind-of": "^3.0.2"
} }
}, },
"is-number-object": {
"version": "1.0.4",
"resolved": "http://npm.ixm5.cn:4873/is-number-object/-/is-number-object-1.0.4.tgz",
"integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw=="
},
"is-obj": { "is-obj": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz",
...@@ -8540,6 +8782,14 @@ ...@@ -8540,6 +8782,14 @@
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
"integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
}, },
"json2module": {
"version": "0.0.3",
"resolved": "http://npm.ixm5.cn:4873/json2module/-/json2module-0.0.3.tgz",
"integrity": "sha1-APtfSpt638PwZHwpyxe80Zeb6bI=",
"requires": {
"rw": "^1.3.2"
}
},
"json2mq": { "json2mq": {
"version": "0.2.0", "version": "0.2.0",
"resolved": "https://registry.npmjs.org/json2mq/-/json2mq-0.2.0.tgz", "resolved": "https://registry.npmjs.org/json2mq/-/json2mq-0.2.0.tgz",
...@@ -8867,6 +9117,11 @@ ...@@ -8867,6 +9117,11 @@
"resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.1.tgz", "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.1.tgz",
"integrity": "sha512-Hesni4s5UkWkwCGJMQGAh71PaLUmKFM60dHvq0zi/vDhhrzuk+4GgNbTXJ12YYQJn6ZKBDNIjYcuQGKudvqrIw==" "integrity": "sha512-Hesni4s5UkWkwCGJMQGAh71PaLUmKFM60dHvq0zi/vDhhrzuk+4GgNbTXJ12YYQJn6ZKBDNIjYcuQGKudvqrIw=="
}, },
"longest": {
"version": "1.0.1",
"resolved": "http://npm.ixm5.cn:4873/longest/-/longest-1.0.1.tgz",
"integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc="
},
"loose-envify": { "loose-envify": {
"version": "1.4.0", "version": "1.4.0",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
...@@ -9309,6 +9564,12 @@ ...@@ -9309,6 +9564,12 @@
"resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz",
"integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=" "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE="
}, },
"mutation-observer": {
"version": "1.0.3",
"resolved": "http://npm.ixm5.cn:4873/mutation-observer/-/mutation-observer-1.0.3.tgz",
"integrity": "sha512-M/O/4rF2h776hV7qGMZUH3utZLO/jK7p8rnNgGkjKUw8zCGjRQPxB8z6+5l8+VjRUQ3dNYu4vjqXYLr+U8ZVNA==",
"dev": true
},
"mute-stream": { "mute-stream": {
"version": "0.0.8", "version": "0.0.8",
"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
...@@ -12500,6 +12761,14 @@ ...@@ -12500,6 +12761,14 @@
"signal-exit": "^3.0.2" "signal-exit": "^3.0.2"
} }
}, },
"resumer": {
"version": "0.0.0",
"resolved": "http://npm.ixm5.cn:4873/resumer/-/resumer-0.0.0.tgz",
"integrity": "sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k=",
"requires": {
"through": "~2.3.4"
}
},
"ret": { "ret": {
"version": "0.1.15", "version": "0.1.15",
"resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
...@@ -12541,6 +12810,14 @@ ...@@ -12541,6 +12810,14 @@
"resolved": "https://registry.npmjs.org/rgba-regex/-/rgba-regex-1.0.0.tgz", "resolved": "https://registry.npmjs.org/rgba-regex/-/rgba-regex-1.0.0.tgz",
"integrity": "sha1-QzdOLiyglosO8VI0YLfXMP8i7rM=" "integrity": "sha1-QzdOLiyglosO8VI0YLfXMP8i7rM="
}, },
"right-align": {
"version": "0.1.3",
"resolved": "http://npm.ixm5.cn:4873/right-align/-/right-align-0.1.3.tgz",
"integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=",
"requires": {
"align-text": "^0.1.1"
}
},
"rimraf": { "rimraf": {
"version": "2.7.1", "version": "2.7.1",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
...@@ -12558,6 +12835,69 @@ ...@@ -12558,6 +12835,69 @@
"inherits": "^2.0.1" "inherits": "^2.0.1"
} }
}, },
"rollup": {
"version": "0.25.8",
"resolved": "http://npm.ixm5.cn:4873/rollup/-/rollup-0.25.8.tgz",
"integrity": "sha1-v2zoO4dRDRY0Ru6qV37WpvxYNeA=",
"requires": {
"chalk": "^1.1.1",
"minimist": "^1.2.0",
"source-map-support": "^0.3.2"
},
"dependencies": {
"ansi-regex": {
"version": "2.1.1",
"resolved": "http://npm.ixm5.cn:4873/ansi-regex/-/ansi-regex-2.1.1.tgz",
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
},
"ansi-styles": {
"version": "2.2.1",
"resolved": "http://npm.ixm5.cn:4873/ansi-styles/-/ansi-styles-2.2.1.tgz",
"integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4="
},
"chalk": {
"version": "1.1.3",
"resolved": "http://npm.ixm5.cn:4873/chalk/-/chalk-1.1.3.tgz",
"integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
"requires": {
"ansi-styles": "^2.2.1",
"escape-string-regexp": "^1.0.2",
"has-ansi": "^2.0.0",
"strip-ansi": "^3.0.0",
"supports-color": "^2.0.0"
}
},
"source-map": {
"version": "0.1.32",
"resolved": "http://npm.ixm5.cn:4873/source-map/-/source-map-0.1.32.tgz",
"integrity": "sha1-yLbBZ3l7pHQKjqMyUhYv8IWRsmY=",
"requires": {
"amdefine": ">=0.0.4"
}
},
"source-map-support": {
"version": "0.3.3",
"resolved": "http://npm.ixm5.cn:4873/source-map-support/-/source-map-support-0.3.3.tgz",
"integrity": "sha1-NJAJd9W6PwfHdX7nLnO7GptTdU8=",
"requires": {
"source-map": "0.1.32"
}
},
"strip-ansi": {
"version": "3.0.1",
"resolved": "http://npm.ixm5.cn:4873/strip-ansi/-/strip-ansi-3.0.1.tgz",
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
"requires": {
"ansi-regex": "^2.0.0"
}
},
"supports-color": {
"version": "2.0.0",
"resolved": "http://npm.ixm5.cn:4873/supports-color/-/supports-color-2.0.0.tgz",
"integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
}
}
},
"rsvp": { "rsvp": {
"version": "4.8.5", "version": "4.8.5",
"resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz", "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz",
...@@ -12576,6 +12916,11 @@ ...@@ -12576,6 +12916,11 @@
"aproba": "^1.1.1" "aproba": "^1.1.1"
} }
}, },
"rw": {
"version": "1.3.3",
"resolved": "http://npm.ixm5.cn:4873/rw/-/rw-1.3.3.tgz",
"integrity": "sha1-P4Yt+pGrdmsUiF700BEkv9oHT7Q="
},
"rxjs": { "rxjs": {
"version": "6.6.3", "version": "6.6.3",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz",
...@@ -13498,6 +13843,88 @@ ...@@ -13498,6 +13843,88 @@
"side-channel": "^1.0.3" "side-channel": "^1.0.3"
} }
}, },
"string.prototype.trim": {
"version": "1.2.4",
"resolved": "http://npm.ixm5.cn:4873/string.prototype.trim/-/string.prototype.trim-1.2.4.tgz",
"integrity": "sha512-hWCk/iqf7lp0/AgTF7/ddO1IWtSNPASjlzCicV5irAVdE1grjsneK26YG6xACMBEdCvO8fUST0UzDMh/2Qy+9Q==",
"requires": {
"call-bind": "^1.0.2",
"define-properties": "^1.1.3",
"es-abstract": "^1.18.0-next.2"
},
"dependencies": {
"es-abstract": {
"version": "1.18.0",
"resolved": "http://npm.ixm5.cn:4873/es-abstract/-/es-abstract-1.18.0.tgz",
"integrity": "sha512-LJzK7MrQa8TS0ja2w3YNLzUgJCGPdPOV1yVvezjNnS89D+VR08+Szt2mz3YB2Dck/+w5tfIq/RoUAFqJJGM2yw==",
"requires": {
"call-bind": "^1.0.2",
"es-to-primitive": "^1.2.1",
"function-bind": "^1.1.1",
"get-intrinsic": "^1.1.1",
"has": "^1.0.3",
"has-symbols": "^1.0.2",
"is-callable": "^1.2.3",
"is-negative-zero": "^2.0.1",
"is-regex": "^1.1.2",
"is-string": "^1.0.5",
"object-inspect": "^1.9.0",
"object-keys": "^1.1.1",
"object.assign": "^4.1.2",
"string.prototype.trimend": "^1.0.4",
"string.prototype.trimstart": "^1.0.4",
"unbox-primitive": "^1.0.0"
}
},
"get-intrinsic": {
"version": "1.1.1",
"resolved": "http://npm.ixm5.cn:4873/get-intrinsic/-/get-intrinsic-1.1.1.tgz",
"integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==",
"requires": {
"function-bind": "^1.1.1",
"has": "^1.0.3",
"has-symbols": "^1.0.1"
}
},
"has-symbols": {
"version": "1.0.2",
"resolved": "http://npm.ixm5.cn:4873/has-symbols/-/has-symbols-1.0.2.tgz",
"integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw=="
},
"is-callable": {
"version": "1.2.3",
"resolved": "http://npm.ixm5.cn:4873/is-callable/-/is-callable-1.2.3.tgz",
"integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ=="
},
"is-regex": {
"version": "1.1.2",
"resolved": "http://npm.ixm5.cn:4873/is-regex/-/is-regex-1.1.2.tgz",
"integrity": "sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg==",
"requires": {
"call-bind": "^1.0.2",
"has-symbols": "^1.0.1"
}
},
"string.prototype.trimend": {
"version": "1.0.4",
"resolved": "http://npm.ixm5.cn:4873/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz",
"integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==",
"requires": {
"call-bind": "^1.0.2",
"define-properties": "^1.1.3"
}
},
"string.prototype.trimstart": {
"version": "1.0.4",
"resolved": "http://npm.ixm5.cn:4873/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz",
"integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==",
"requires": {
"call-bind": "^1.0.2",
"define-properties": "^1.1.3"
}
}
}
},
"string.prototype.trimend": { "string.prototype.trimend": {
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.3.tgz", "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.3.tgz",
...@@ -13705,6 +14132,51 @@ ...@@ -13705,6 +14132,51 @@
"resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz",
"integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==" "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA=="
}, },
"tape": {
"version": "4.13.3",
"resolved": "http://npm.ixm5.cn:4873/tape/-/tape-4.13.3.tgz",
"integrity": "sha512-0/Y20PwRIUkQcTCSi4AASs+OANZZwqPKaipGCEwp10dQMipVvSZwUUCi01Y/OklIGyHKFhIcjock+DKnBfLAFw==",
"requires": {
"deep-equal": "~1.1.1",
"defined": "~1.0.0",
"dotignore": "~0.1.2",
"for-each": "~0.3.3",
"function-bind": "~1.1.1",
"glob": "~7.1.6",
"has": "~1.0.3",
"inherits": "~2.0.4",
"is-regex": "~1.0.5",
"minimist": "~1.2.5",
"object-inspect": "~1.7.0",
"resolve": "~1.17.0",
"resumer": "~0.0.0",
"string.prototype.trim": "~1.2.1",
"through": "~2.3.8"
},
"dependencies": {
"is-regex": {
"version": "1.0.5",
"resolved": "http://npm.ixm5.cn:4873/is-regex/-/is-regex-1.0.5.tgz",
"integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==",
"requires": {
"has": "^1.0.3"
}
},
"object-inspect": {
"version": "1.7.0",
"resolved": "http://npm.ixm5.cn:4873/object-inspect/-/object-inspect-1.7.0.tgz",
"integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw=="
},
"resolve": {
"version": "1.17.0",
"resolved": "http://npm.ixm5.cn:4873/resolve/-/resolve-1.17.0.tgz",
"integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==",
"requires": {
"path-parse": "^1.0.6"
}
}
}
},
"terser": { "terser": {
"version": "4.8.0", "version": "4.8.0",
"resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz",
...@@ -14004,6 +14476,12 @@ ...@@ -14004,6 +14476,12 @@
"punycode": "^2.1.0" "punycode": "^2.1.0"
} }
}, },
"transitionEnd": {
"version": "1.0.2",
"resolved": "http://npm.ixm5.cn:4873/transitionEnd/-/transitionEnd-1.0.2.tgz",
"integrity": "sha1-GRTbW0Wn79w0oBr2koWjppOHFjM=",
"dev": true
},
"ts-pnp": { "ts-pnp": {
"version": "1.1.6", "version": "1.1.6",
"resolved": "https://registry.npmjs.org/ts-pnp/-/ts-pnp-1.1.6.tgz", "resolved": "https://registry.npmjs.org/ts-pnp/-/ts-pnp-1.1.6.tgz",
...@@ -14077,6 +14555,61 @@ ...@@ -14077,6 +14555,61 @@
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.3.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.3.tgz",
"integrity": "sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg==" "integrity": "sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg=="
}, },
"uglify-js": {
"version": "2.8.29",
"resolved": "http://npm.ixm5.cn:4873/uglify-js/-/uglify-js-2.8.29.tgz",
"integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=",
"requires": {
"source-map": "~0.5.1",
"uglify-to-browserify": "~1.0.0",
"yargs": "~3.10.0"
},
"dependencies": {
"camelcase": {
"version": "1.2.1",
"resolved": "http://npm.ixm5.cn:4873/camelcase/-/camelcase-1.2.1.tgz",
"integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk="
},
"cliui": {
"version": "2.1.0",
"resolved": "http://npm.ixm5.cn:4873/cliui/-/cliui-2.1.0.tgz",
"integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=",
"requires": {
"center-align": "^0.1.1",
"right-align": "^0.1.1",
"wordwrap": "0.0.2"
}
},
"yargs": {
"version": "3.10.0",
"resolved": "http://npm.ixm5.cn:4873/yargs/-/yargs-3.10.0.tgz",
"integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=",
"requires": {
"camelcase": "^1.0.2",
"cliui": "^2.1.0",
"decamelize": "^1.0.0",
"window-size": "0.1.0"
}
}
}
},
"uglify-to-browserify": {
"version": "1.0.2",
"resolved": "http://npm.ixm5.cn:4873/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz",
"integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=",
"optional": true
},
"unbox-primitive": {
"version": "1.0.0",
"resolved": "http://npm.ixm5.cn:4873/unbox-primitive/-/unbox-primitive-1.0.0.tgz",
"integrity": "sha512-P/51NX+JXyxK/aigg1/ZgyccdAxm5K1+n8+tvqSntjOivPt19gvm1VC49RWYetsiub8WViUchdxl/KWHHB0kzA==",
"requires": {
"function-bind": "^1.1.1",
"has-bigints": "^1.0.0",
"has-symbols": "^1.0.0",
"which-boxed-primitive": "^1.0.1"
}
},
"underscore": { "underscore": {
"version": "1.12.0", "version": "1.12.0",
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.0.tgz", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.0.tgz",
...@@ -14407,11 +14940,40 @@ ...@@ -14407,11 +14940,40 @@
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
"integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
}, },
"vconsole": {
"version": "3.4.0",
"resolved": "http://npm.ixm5.cn:4873/vconsole/-/vconsole-3.4.0.tgz",
"integrity": "sha512-N9py7Ch9M9nzsigYf8T/WHIOood7jq2MNtUWDqicnrCsPsOZj8Z3NsmFgBmDA3bPKwnzace11HXHxYKPfwV32A==",
"dev": true,
"requires": {
"mutation-observer": "^1.0.3",
"transitionEnd": "^1.0.2"
}
},
"vconsole-webpack-plugin": {
"version": "1.5.2",
"resolved": "http://npm.ixm5.cn:4873/vconsole-webpack-plugin/-/vconsole-webpack-plugin-1.5.2.tgz",
"integrity": "sha512-v3goAnjsurFUy+qUmJCGjW+tzeKzlkrlbY8YnctSbhbrKiyC40hDeVFdGJvv7Drvd+w4xCQ1hJFZa5ESadmljQ==",
"dev": true,
"requires": {
"vconsole": "^3.3.4"
}
},
"vendors": { "vendors": {
"version": "1.0.4", "version": "1.0.4",
"resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.4.tgz", "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.4.tgz",
"integrity": "sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w==" "integrity": "sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w=="
}, },
"venn.js": {
"version": "0.2.20",
"resolved": "http://npm.ixm5.cn:4873/venn.js/-/venn.js-0.2.20.tgz",
"integrity": "sha512-bb5SYq/wamY9fvcuErb9a0FJkgIFHJjkLZWonQ+DoKKuDX3WPH2B4ouI1ce4K2iejBklQy6r1ly8nOGIyOCO6w==",
"requires": {
"d3-selection": "^1.0.2",
"d3-transition": "^1.0.1",
"fmin": "0.0.2"
}
},
"verror": { "verror": {
"version": "1.10.0", "version": "1.10.0",
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
...@@ -14981,6 +15543,18 @@ ...@@ -14981,6 +15543,18 @@
"isexe": "^2.0.0" "isexe": "^2.0.0"
} }
}, },
"which-boxed-primitive": {
"version": "1.0.2",
"resolved": "http://npm.ixm5.cn:4873/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
"integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
"requires": {
"is-bigint": "^1.0.1",
"is-boolean-object": "^1.1.0",
"is-number-object": "^1.0.4",
"is-string": "^1.0.5",
"is-symbol": "^1.0.3"
}
},
"which-module": { "which-module": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
...@@ -15006,11 +15580,26 @@ ...@@ -15006,11 +15580,26 @@
} }
} }
}, },
"window-size": {
"version": "0.1.0",
"resolved": "http://npm.ixm5.cn:4873/window-size/-/window-size-0.1.0.tgz",
"integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0="
},
"wolfy87-eventemitter": {
"version": "5.1.0",
"resolved": "http://npm.ixm5.cn:4873/wolfy87-eventemitter/-/wolfy87-eventemitter-5.1.0.tgz",
"integrity": "sha1-NcGsDdGsDBXjXZgVCPwiCEoToBE="
},
"word-wrap": { "word-wrap": {
"version": "1.2.3", "version": "1.2.3",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
"integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==" "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ=="
}, },
"wordwrap": {
"version": "0.0.2",
"resolved": "http://npm.ixm5.cn:4873/wordwrap/-/wordwrap-0.0.2.tgz",
"integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8="
},
"workbox-background-sync": { "workbox-background-sync": {
"version": "4.3.1", "version": "4.3.1",
"resolved": "https://registry.npmjs.org/workbox-background-sync/-/workbox-background-sync-4.3.1.tgz", "resolved": "https://registry.npmjs.org/workbox-background-sync/-/workbox-background-sync-4.3.1.tgz",
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
"homepage": "./", "homepage": "./",
"dependencies": { "dependencies": {
"@antv/data-set": "^0.11.8", "@antv/data-set": "^0.11.8",
"@antv/g2": "^3.5.13", "@antv/g2": "^3.5.17",
"@babel/core": "7.9.0", "@babel/core": "7.9.0",
"@babel/plugin-transform-typescript": "^7.11.0", "@babel/plugin-transform-typescript": "^7.11.0",
"@babel/preset-typescript": "^7.10.4", "@babel/preset-typescript": "^7.10.4",
......
@font-face { @font-face {
font-family: 'iconfont'; /* project id 2223403 */ font-family: 'iconfont'; /* project id 2223403 */
src: url('//at.alicdn.com/t/font_2223403_325yz7wxu2d.eot'); src: url('//at.alicdn.com/t/font_2223403_3mmvxuy22i4.eot');
src: url('//at.alicdn.com/t/font_2223403_325yz7wxu2d.eot?#iefix') format('embedded-opentype'), src: url('//at.alicdn.com/t/font_2223403_3mmvxuy22i4.eot?#iefix') format('embedded-opentype'),
url('//at.alicdn.com/t/font_2223403_325yz7wxu2d.woff2') format('woff2'), url('//at.alicdn.com/t/font_2223403_3mmvxuy22i4.woff2') format('woff2'),
url('//at.alicdn.com/t/font_2223403_325yz7wxu2d.woff') format('woff'), url('//at.alicdn.com/t/font_2223403_3mmvxuy22i4.woff') format('woff'),
url('//at.alicdn.com/t/font_2223403_325yz7wxu2d.ttf') format('truetype'), url('//at.alicdn.com/t/font_2223403_3mmvxuy22i4.ttf') format('truetype'),
url('//at.alicdn.com/t/font_2223403_325yz7wxu2d.svg#iconfont') format('svg'); url('//at.alicdn.com/t/font_2223403_3mmvxuy22i4.svg#iconfont') format('svg');
} }
.iconfont{ .iconfont{
font-family:"iconfont" !important; font-family:"iconfont" !important;
......
/*
* @Description:
* @Author: zangsuyun
* @Date: 2021-03-13 10:57:14
* @LastEditors: zangsuyun
* @LastEditTime: 2021-03-13 17:16:44
* @Copyright: © 2020 杭州杰竞科技有限公司 版权所有
*/
import PropTypes from 'prop-types';
import React from 'react'
// import { Modal } from 'antd';
import './TableSelectedData.less';
class TableSelectedData extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div className={this.props.className+' selected-data-box'}>
<span className="icon iconfont">&#xe61d;</span>
<span className="selected-text">{'已选择'+this.props.selectedNum+'项'}</span>
<span className="click-clear" onClick={this.props.clearSelectedData}>清空</span>
</div>
)
}
}
TableSelectedData.propTypes = {
className: PropTypes.string, // class
selectedNum: PropTypes.number, // 已选择人数
clearSelectedData: PropTypes.func, // 取消全部选择
};
TableSelectedData.defaultProps = {
className: '',
selectedNum: 0,
clearSelectedData: function () {
}
}
export default TableSelectedData
\ No newline at end of file
.selected-data-box {
display: inline-block;
min-width: 186px;
height: 32px;
line-height: 32px;
background: #FFF4DD;
padding: 0px 16px;
border-radius:4px;
margin: 16px 10px 13px 0;
.iconfont {
color: #FF9D14;
}
.selected-text {
margin-left: 10px;
margin-right: 20px;
}
.click-clear {
float: right;
cursor: pointer;
color: #5289FA;
&:hover {
color: rgba(85, 168, 253, 0.8);
}
}
}
\ No newline at end of file
.header-box {
padding: 30px 16px;
margin: 0 16px 16px;
margin-bottom: 8px;
background: #ffffff;
.course-type {
display: inline-block;
border-radius: 2px;
padding: 0 8px;
font-size: 14px;
font-weight: 400;
line-height: 20px;
}
.course-name {
font-size: 16px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #333333;
line-height: 22px;
margin-left: 8px;
}
}
import React from "react";
import { Tag } from 'antd'
import "./WatchDataHeader.less";
interface WatchDataHeaderProps {
type: string;
color?: string;
courseName?: string;
className?: string;
}
const WatchDataHeader = (props: WatchDataHeaderProps) => {
const { type, color , className ,courseName} = props;
return (
<div className={className + " header-box"}>
<span className="course-type" style={{color:color,border:`1px solid ${color}`}}>{type}</span>
<span className='course-name'>{courseName}</span>
</div>
);
};
export default WatchDataHeader;
/* /*
* @Author: wufan * @Author: wufan
* @Date: 2020-12-12 11:57:10 * @Date: 2020-12-12 11:57:10
* @LastEditors: zhangleyuan * @LastEditors: zangsuyun
* @LastEditTime: 2021-03-05 17:20:29 * @LastEditTime: 2021-03-22 13:54:20
* @Description: Description * @Description: Description
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/ */
...@@ -87,4 +87,10 @@ export function videoScheduleBasePage(params: object) { ...@@ -87,4 +87,10 @@ export function videoScheduleBasePage(params: object) {
} }
export function relatedCourseToPlan(params: object) { export function relatedCourseToPlan(params: object) {
return Service.Hades("public/hades/relatedCourseToPlan", params); return Service.Hades("public/hades/relatedCourseToPlan", params);
} }
\ No newline at end of file export function knowledgeMediaCoursePage(params: object) {
return Service.Hades("public/hades/knowledgeMediaCoursePage", params);
}
export function getCategoryTree(params: object) {
return Service.Hades("public/hades/queryKnowledgeCategoryTree", params);
}
/*
* @Description:
* @Author: zangsuyun
* @Date: 2021-03-19 18:09:35
* @LastEditors: zangsuyun
* @LastEditTime: 2021-03-25 13:42:33
* @Copyright: © 2020 杭州杰竞科技有限公司 版权所有
*/
import Service from "@/common/js/service";
class KnowledgeAPI {
// 媒体课列表(视频/图文)
knowledgeMediaCoursePage = (params: object) => {
return Service.Hades("public/hades/knowledgeMediaCoursePage", params);
}
// 直播课列表
knowledgeLiveCoursePage = (params: object) => {
return Service.Hades("public/hades/knowledgeLiveCoursePage", params);
}
// 知识库分类树
getCategoryTree = (params: object) => {
return Service.Hades("public/hades/queryKnowledgeCategoryTree", params);
}
// 查询题目分类树
queryQuestionCategoryTree = (params: object) => {
return Service.Hades("public/hades/queryQuestionCategoryTree", params);
}
// 新增知识
addKnowledge = (params: object) => {
return Service.Hades("public/hades/batchAddKnowledge", params);
}
// 不同类型一起新增知识
addDifTypeKnowledge = (params: object) => {
return Service.Hades("public/hades/batchAddDifTypeKnowledge", params);
}
// 删除知识
delKnowledge = (params: object) => {
return Service.Hades("public/hades/delKnowledge", params);
}
// 移动知识
moveKnowledge = (params: object) => {
return Service.Hades("public/hades/moveKnowledge", params);
}
// 知识库列表
queryPageKnowledgeForManager = (params: object) => {
return Service.Hades("public/hades/queryPageKnowledgeForManager", params);
}
// 直播课学生观看记录
queryPageKnowledgeLiveStudentVisitData = (params: object) => {
return Service.Hades("public/hades/queryPageKnowledgeLiveStudentVisitData", params);
}
// 直播课老师观看记录
queryPageKnowledgeLiveTeacherVisitData = (params: object) => {
return Service.Hades("public/hades/queryPageKnowledgeLiveTeacherVisitData", params);
}
// 分页图文课观看记录
queryPageKnowledgeMediaCourseWatchInfo = (params: object) => {
return Service.Hades("public/hades/queryPageKnowledgeMediaCourseWatchInfo", params);
}
// 直播课回放学生观看记录
queryPageKnowledgeReplayRecordPage = (params: object) => {
return Service.Hades("public/hades/queryPageKnowledgeReplayRecordPage", params);
}
// 分页获取知识库包括(子分类)
queryPageKnowledgeInclude = (params: object) => {
return Service.Hades("anon/customerHades/queryPageKnowledgeInclude", params);
}
}
export default new KnowledgeAPI()
\ No newline at end of file
/* /*
* @Author: 陈剑宇 * @Author: 陈剑宇
* @Date: 2020-05-07 14:43:01 * @Date: 2020-05-07 14:43:01
* @LastEditTime: 2021-03-01 10:09:42 * @LastEditTime: 2021-03-22 13:54:27
* @LastEditors: zhangleyuan * @LastEditors: zangsuyun
* @Description: * @Description:
* @FilePath: /wheat-web-demo/src/domains/basic-domain/constants.ts * @FilePath: /wheat-web-demo/src/domains/basic-domain/constants.ts
*/ */
import { MapInterface } from '@/domains/basic-domain/interface' import { MapInterface } from '@/domains/basic-domain/interface'
// 默认是 dev 环境 // 默认是 dev 环境
const ENV: string = process.env.DEPLOY_ENV || 'dev'; const ENV: string = process.env.DEPLOY_ENV || 'dev1';
console.log("process.env.DEPLOY_ENV",process) console.log("process.env.DEPLOY_ENV",process)
const BASIC_HOST_MAP: MapInterface = { const BASIC_HOST_MAP: MapInterface = {
dev: 'https://dev-heimdall.xiaomai5.com/', dev: 'https://dev-heimdall.xiaomai5.com/',
......
/* /*
* @Author: wufan * @Author: wufan
* @Date: 2020-11-25 18:25:02 * @Date: 2020-11-25 18:25:02
* @LastEditors: zhangleyuan * @LastEditors: zangsuyun
* @LastEditTime: 2021-03-05 17:20:56 * @LastEditTime: 2021-03-22 13:58:04
* @Description: Description * @Description: Description
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/ */
import { import {
fetchLecturerData, fetchUserData, exportStudentCourseData, exportPlayBackCourseData, fetchPlaybackList, createLiveCloudCourse, getLiveCloudCoursePage, fetchLecturerData, getCategoryTree, knowledgeMediaCoursePage, fetchUserData, exportStudentCourseData, exportPlayBackCourseData, fetchPlaybackList, createLiveCloudCourse, getLiveCloudCoursePage,
getLiveCloudCourseDetail, updateLiveCloudCourse, turnOnOrOffLiveCloudCourse, delLiveCloudCourse, changeVideoShelfState, createVideoSchedule, delVideoSchedule, getLiveCloudCourseDetail, updateLiveCloudCourse, turnOnOrOffLiveCloudCourse, delLiveCloudCourse, changeVideoShelfState, createVideoSchedule, delVideoSchedule,
editVideoSchedule, userWatchInfo, videoSchedulePage, videoScheduleDetail, videoWatchInfo, getQrcode,getLiveCloudCourseBasePage,videoScheduleBasePage,relatedCourseToPlan editVideoSchedule, userWatchInfo, videoSchedulePage, videoScheduleDetail, videoWatchInfo, getQrcode, getLiveCloudCourseBasePage, videoScheduleBasePage, relatedCourseToPlan
} from '@/data-source/course/request-api'; } from '@/data-source/course/request-api';
export default class courseService { export default class courseService {
...@@ -85,13 +85,20 @@ export default class courseService { ...@@ -85,13 +85,20 @@ export default class courseService {
static videoWatchInfo(params: any) { static videoWatchInfo(params: any) {
return videoWatchInfo(params); return videoWatchInfo(params);
} }
static getLiveCloudCourseBasePage(params: any){ static getLiveCloudCourseBasePage(params: any) {
return getLiveCloudCourseBasePage(params); return getLiveCloudCourseBasePage(params);
} }
static videoScheduleBasePage(params: any){ static videoScheduleBasePage(params: any) {
return videoScheduleBasePage(params); return videoScheduleBasePage(params);
} }
static relatedCourseToPlan(params: any){ static relatedCourseToPlan(params: any) {
return relatedCourseToPlan(params); return relatedCourseToPlan(params);
} }
static knowledgeMediaCoursePage(params: any) {
return knowledgeMediaCoursePage(params);
}
static getCategoryTree(params: any) {
return getCategoryTree(params);
}
} }
\ No newline at end of file
<!-- <!--
* @Author: 吴文洁 * @Author: 吴文洁
* @Date: 2020-08-24 12:20:57 * @Date: 2020-08-24 12:20:57
* @LastEditors: zhangleyuan * @LastEditors: zangsuyun
* @LastEditTime: 2021-03-17 19:42:47 * @LastEditTime: 2021-03-25 12:21:52
* @Description: * @Description:
* @Copyright: 杭州杰竞科技有限公司 版权所有 * @Copyright: 杭州杰竞科技有限公司 版权所有
--> -->
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/ user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
--> -->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" /> <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<link rel="stylesheet" href="//at.alicdn.com/t/font_2223403_325yz7wxu2d.css"> <link rel="stylesheet" href="//at.alicdn.com/t/font_2223403_1zfzctj7oe5.css">
<!-- <!--
Notice the use of %PUBLIC_URL% in the tags above. Notice the use of %PUBLIC_URL% in the tags above.
......
<!-- <!--
* @Author: 吴文洁 * @Author: 吴文洁
* @Date: 2020-08-24 12:20:57 * @Date: 2020-08-24 12:20:57
* @LastEditors: zhangleyuan * @LastEditors: zangsuyun
* @LastEditTime: 2021-03-11 15:28:14 * @LastEditTime: 2021-03-25 12:20:14
* @Description: * @Description:
* @Copyright: 杭州杰竞科技有限公司 版权所有 * @Copyright: 杭州杰竞科技有限公司 版权所有
--> -->
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/ user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
--> -->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" /> <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<link rel="stylesheet" href="//at.alicdn.com/t/font_2223403_325yz7wxu2d.css"> <link rel="stylesheet" href="//at.alicdn.com/t/font_2223403_1zfzctj7oe5.js">
<!-- <!--
Notice the use of %PUBLIC_URL% in the tags above. Notice the use of %PUBLIC_URL% in the tags above.
......
...@@ -185,7 +185,7 @@ class LiveCourseFilter extends React.Component { ...@@ -185,7 +185,7 @@ class LiveCourseFilter extends React.Component {
<span>讲师:</span> <span>讲师:</span>
<Select <Select
placeholder="请选择讲师" placeholder="请选择讲师"
style={{ width: 240}} style={{ width: "calc(100% - 70px)"}}
showSearch showSearch
allowClear allowClear
filterOption={(input, option) => option} filterOption={(input, option) => option}
......
/*
* @Description:
* @Author: zangsuyun
* @Date: 2021-03-22 18:24:53
* @LastEditors: zangsuyun
* @LastEditTime: 2021-03-24 10:10:45
* @Copyright: © 2020 杭州杰竞科技有限公司 版权所有
*/
const ENUM = {
courseStateShow: {
UN_START: {
code: 1,
title: "待开课",
color: "#FFB714",
},
STARTING: {
code: 2,
title: "上课中",
color: "#238FFF",
},
FINISH: {
code: 3,
title: "已完成",
color: "#3BBDAA",
},
EXPIRED: {
code: 4,
title: "未成功开课",
color: "#999",
},
},
CourseTypeEnum: {
LIVE: "直播课",
VOICE: "视频课",
PICTURE: "图文课",
FOLDER: "图文资料",
},
};
export default ENUM
\ No newline at end of file
/*
* @Description:
* @Author: zangsuyun
* @Date: 2021-03-19 18:05:23
* @LastEditors: zangsuyun
* @LastEditTime: 2021-03-26 11:30:26
* @Copyright: © 2020 杭州杰竞科技有限公司 版权所有
*/
import React, { Component } from "react";
import { Input, Button, Tree } from "antd";
import "./Classification.less";
import User from "@/common/js/user";
import KnowledgeAPL from "@/data-source/knowledge/request-api";
const { Search } = Input;
const { DirectoryTree } = Tree;
class Classification extends Component {
constructor(props) {
super(props);
this.state = {
selectedKeys: props.selectedKeys ? [props.selectedKeys] : ["0"],
searchValue: null,
NewEditQuestionBankCategory: null, //新增或编辑分类模态框
ImportCourseCategory: null, // 引用课程分类模态框
treeData: this.props.treeData || [],
autoExpandParent: false,
};
}
componentDidMount() {
this.queryCategoryTree();
// this.props.getSelectedCategoryId(
// getParameterByName("categoryId")
// ? [getParameterByName("categoryId")]
// : 0
// );
}
shouldComponentUpdate = (nextProps, nextState) => {
const { updateCategoryFlag } = nextProps;
if (this.props.updateCategoryFlag !== updateCategoryFlag) {
this.queryCategoryTree();
}
return true;
};
/** 获取树状第一级key 设置默认展开第一项 */
getFirstLevelKeys = (data) => {
let firstLevelKeys = [];
data.forEach((item) => {
if (item.categoryLevel === 0) {
firstLevelKeys.push(item.key);
}
});
return firstLevelKeys;
};
/** 树状展开事件 */
onExpand = (expandedKeys) => {
this.setState({ expandedKeys });
};
/** 树状选中事件 */
onSelect = (selectedKeys) => {
this.setState({ selectedKeys });
console.log(selectedKeys);
this.props.getSelectedCategoryId(selectedKeys[0]);
};
// 查询分类树
queryCategoryTree = (categoryName) => {
let query = {
// source: 0,
// categoryName,
storeId: User.getStoreId(),
withCount: true,
};
// let query = {
// source: 0,
// categoryName,
// userId: User.getStoreUserId(),
// tenantId: User.getStoreId(),
// };
KnowledgeAPL.getCategoryTree(query).then((res) => {
const { categoryList = [], noCategoryCnt = 0 } = res.result;
let str = "未分类";
if (categoryName) {
this.setState({ autoExpandParent: true });
if (str.indexOf(categoryName) < 0) {
this.setState({
treeData: this.renderTreeNodes(categoryList, categoryName),
});
let nodeId = [];
Object.keys(this.state.treeMap).forEach((item) => {
nodeId.push(item);
});
this.setState({ expandedKeys: nodeId });
} else {
const defaultNode = {
id: "0",
categoryName: "未分类",
categoryCount: noCategoryCnt,
};
categoryList.unshift(defaultNode);
this.setState({
treeData: this.renderTreeNodes(categoryList, categoryName),
});
let nodeId = [];
Object.keys(this.state.treeMap).forEach((item) => {
nodeId.push(item);
});
this.setState({ expandedKeys: nodeId });
}
} else {
this.setState({ autoExpandParent: false });
const defaultNode = {
id: "0",
categoryName: "未分类",
categoryCount: noCategoryCnt,
};
categoryList.unshift(defaultNode);
this.setState({
treeData: this.renderTreeNodes(categoryList, categoryName),
});
this.setState({ expandedKeys: [] });
}
});
};
getTreeMap = (data, map) => {
data.forEach((item) => {
map[item.id] = item;
if (item.sonCategoryList && item.sonCategoryList.length > 0) {
this.getTreeMap(item.sonCategoryList, map);
}
});
return map;
};
renderTreeNodes = (data, value) => {
let newTreeData = data.map((item) => {
item.title = item.categoryName;
item.key = item.id;
item.title =
!value || (value && item.categoryName.indexOf(value) > -1) ? (
<span>
{item.categoryName}{item.categoryCount}
</span>
) : (
<span style={{ opacity: 0.5 }}>
{item.categoryName}{item.categoryCount}
</span>
);
item.icon =
item.categoryName === "未分类" ? (
<span className="icon iconfont" style={{ color: "#FBD140" }}>
&#xe7f6;
</span>
) : (
<span className="icon iconfont" style={{ color: "#FBD140" }}>
&#xe7f1;
</span>
);
if (item.sonCategoryList) {
item.children = this.renderTreeNodes(item.sonCategoryList, value);
}
return item;
});
let map = {};
this.setState({ treeMap: this.getTreeMap(data, map) });
return newTreeData;
};
render() {
const {
treeData,
expandedKeys,
selectedKeys,
autoExpandParent,
} = this.state;
return (
<div className="question-bank-sider">
<div className="sider-title">知识分类</div>
<Search
className="sider-search"
placeholder="搜索名称分类"
onSearch={(value) => {
// TODO 调用查询分类接口
this.queryCategoryTree(value);
}}
/>
<div className="sider-btn">
<Button
onClick={() => {
window.RCHistory.push({
pathname: "/course-catalog",
});
}}
>
分类管理
</Button>
</div>
<div className="sider-tree">
<DirectoryTree
expandedKeys={expandedKeys}
autoExpandParent={autoExpandParent}
onExpand={this.onExpand}
selectedKeys={selectedKeys}
onSelect={this.onSelect}
showIcon
treeData={treeData}
/>
</div>
{this.state.NewEditQuestionBankCategory}
{this.state.ImportCourseCategory}
</div>
);
}
}
export default Classification;
/*
* @Description:
* @Author: zangsuyun
* @Date: 2021-03-19 18:16:58
* @LastEditors: zangsuyun
* @LastEditTime: 2021-03-25 19:13:06
* @Copyright: © 2020 杭州杰竞科技有限公司 版权所有
*/
.question-bank-sider {
position: relative;
.sider-title {
height: 22px;
font-size: 16px;
font-weight: 500;
color: #000000;
line-height: 22px;
margin-bottom: 16px;
}
.sider-search {
margin-bottom: 16px;
}
.sider-btn {
margin-bottom: 16px;
}
.sider-tree {
width: 266px;
overflow: scroll;
height: ~'calc(100vh - 300px)';
.empty-tree-tip {
text-align: center;
margin-top: 100%;
.empty-tree-btn {
color: #ffb714;
cursor: pointer;
}
}
.ant-tree.ant-tree-directory {
font-size: 14px;
font-weight: 400;
color: #666666;
width: 260px;
.anticon {
color: #666666;
}
.ant-tree-treenode {
height: 44px;
padding: 0;
span {
line-height: 44px;
white-space: nowrap;
}
.ant-tree-node-content-wrapper.ant-tree-node-selected {
color: #666666;
}
}
.ant-tree-treenode-selected:hover::before,
.ant-tree-treenode-selected::before {
background: #fffbf1;
}
}
}
}
/*
* @Description:
* @Author: zangsuyun
* @Date: 2021-03-15 16:51:40
* @LastEditors: zangsuyun
* @LastEditTime: 2021-03-25 11:17:15
* @Copyright: © 2020 杭州杰竞科技有限公司 版权所有
*/
import React from "react";
import { withRouter } from "react-router-dom";
import { Table, Popover, message, Button, Spin } from "antd";
import dealTimeDuration from "../../course-manage/utils/dealTimeDuration";
import { PageControl } from "@/components";
import CourseService from "@/domains/course-domain/CourseService";
import KnowledgeAPI from "@/data-source/knowledge/request-api";
import User from "@/common/js/user";
// import "./DataList.less";
class CourseData extends React.Component {
constructor(props) {
super(props);
const courseId = getParameterByName("id"); // 课程ID
const type = getParameterByName("type"); // 来源: 大班直播 large 互动班课 interactive
this.state = {
type,
teacherData: [], // 老师上课数据
studentData: [], // 学员上课数据
current: 1,
size: 10, // 添加扣课时学员弹窗回填所需 当前接口返回全部列表
total: 0,
loading: true,
id: courseId,
storeId: User.getStoreId(),
};
}
componentDidMount() {
this.fetchLecturerData();
this.fetchUserData();
}
// 获取学员上课数据
fetchUserData = (current = 1) => {
this.setState({ loading: true });
const { id, size } = this.state;
const params = {
id,
current,
size,
};
KnowledgeAPI.queryPageKnowledgeLiveStudentVisitData(params).then((res) => {
if (res.result) {
const { records = [], current, size, total } = res.result;
this.setState({
studentData: records,
current,
size,
total,
loading: false,
});
}
});
};
// 获取老师上课数据
fetchLecturerData = () => {
const { id } = this.state;
KnowledgeAPI.queryPageKnowledgeLiveTeacherVisitData({ id }).then((res) => {
if (res.result) {
this.setState({
teacherData: res.result,
});
}
});
};
// 进入直播次数列表
getVisiterColumns() {
const columns = [
{
title: "序号",
dataIndex: "index",
width: 50,
render: (text, record, index) => {
return <span>{index + 1}</span>;
},
},
{
title: "进入时间",
dataIndex: "entryTime",
width: 150,
render: (text) => (
<span>{formatDate("YYYY-MM-DD H:i", parseInt(text))}</span>
),
},
{
title: "离开时间",
dataIndex: "leaveTime",
width: 150,
render: (text) => (
<span>{formatDate("YYYY-MM-DD H:i", parseInt(text))}</span>
),
},
{
title: "在线时长",
dataIndex: "lookingDuration",
render: (text, record) => {
return <span>{text ? dealTimeDuration(text) : "-"}</span>;
},
},
];
return columns;
}
// 学员上课数据列表
getStudentColumns() {
const columns = [
{
title: "用户姓名",
dataIndex: "userName",
},
{
title: "手机号",
dataIndex: "phone",
render: (text, record) => {
const { phone = "", bindingWeChat } = record;
return <div>{phone}</div>;
},
},
{
title: "观看次数",
dataIndex: "entryNum",
render: (text, record) => {
if (text > 0) {
if (
record.visitorInfoVOList &&
record.visitorInfoVOList.length > 0
) {
const table = (
<Table
columns={this.getVisiterColumns()}
dataSource={record.visitorInfoVOList}
scroll={{ y: 75 }}
size={"small"}
style={{ width: 450 }}
pagination={false}
/>
);
return (
<Popover content={table} trigger="click">
<span className="handel-btn">{text}</span>
</Popover>
);
} else {
return <div className="live-table--empty">暂无观看数据</div>;
}
} else {
return <span>{text}</span>;
}
},
},
{
title: "累计在线时长",
dataIndex: "totalDuration",
sorter: (a, b) => a.totalDuration - b.totalDuration,
sortDirections: ["descend", "ascend"],
render: (text, record) => {
//如无离开时间,就置空
return <span>{text ? dealTimeDuration(text) : "00:00:00"}</span>;
},
},
];
return columns;
}
// 学员导出5.0
handleExportV5 = () => {
const { id, storeId } = this.state;
CourseService.exportStudentCourseData({
id: id,
exportLiveType: "VISITOR",
storeId,
}).then((res) => {
const link = res.result;
this.setState({
link
});
document.getElementById("loadExcel").click();
if (res.success) {
message.success("导出成功!");
}
});
};
handleCheckEnterTimes = () => {
const { teacherData } = this.state;
if (teacherData.entryNum > 0) {
if (
teacherData.visitorInfoVOList &&
teacherData.visitorInfoVOList.length > 0
) {
const table = (
<Table
columns={this.getVisiterColumns()}
dataSource={teacherData.visitorInfoVOList}
scroll={{ y: 75 }}
size={"small"}
style={{ width: 450 }}
pagination={false}
/>
);
return (
<Popover content={table} trigger="click">
<span className="times-num">{teacherData.entryNum}</span>
</Popover>
);
} else {
return <div className="live-table--empty">暂无观看数据</div>;
}
} else {
return <span>{teacherData.entryNum}</span>;
}
};
showTable = () => {
return (
<Table
columns={this.getVisiterColumns()}
dataSource={this.state.teacherData.visitorInfoVOList}
scroll={{ y: 80 }}
size={"small"}
style={{ width: 450 }}
pagination={false}
className="visitor-num-table"
/>
);
};
onShowSizeChange = (current, size) => {
if (current == size) {
return;
}
this.setState({ size }, this.fetchUserData)
}
render() {
const {
teacherData,
studentData,
current,
size,
total,
loading,
link
} = this.state;
return (
<Spin spinning={loading}>
<a
href={link}
target="_blank"
download
id="loadExcel"
style={{ position: "absolute", left: "-10000px" }}
>
111
</a>
{/* 讲师上课数据 */}
<div className="courseData-teacher">
<p className="title">讲师上课数据</p>
<div className="teacher-course-data">
<div className="avatar-name-phone item-block">
<img
src={
teacherData.avatar ||
"https://image.xiaomaiketang.com/xm/rJeQaZxtc7.png"
}
alt=""
className="avatar"
/>
<div className="right">
<div className="name">{teacherData.userName}</div>
<div className="phone">
{teacherData.phone}
</div>
</div>
</div>
<div className="times item-block">
<div
className={`times-num ${
Number(teacherData.entryNum) > 0 ? "can-click" : ""
}`}
>{
Number(teacherData.entryNum) > 0 ?
<Popover content={this.showTable()} trigger="click">
<span className="times-num">{teacherData.entryNum || 0}</span>
</Popover>:
<span className="times-num">{0}</span>
}
</div>
<div className="text">进入直播间次数</div>
</div>
<div className="online-duration item-block">
<div className="duration">
{teacherData.totalDuration
? dealTimeDuration(teacherData.totalDuration)
: "00:00:00"}
</div>
<div className="text">累计在线时长</div>
</div>
</div>
</div>
{/* 用户上课数据 */}
<div className="courseData-student">
<p className="title">用户上课数据</p>
<div className="filter-wrap">
<div className="filter">
<Button
style={{ height: 32}}
onClick={_.debounce(
() => {
if (!studentData.length) {
message.warning("暂无数据可导出");
return;
}
this.handleExportV5();
},
500,
true
)}
>
导出
</Button>
</div>
</div>
<Table
bordered
size="small"
scroll={{ y: 600 }}
columns={this.getStudentColumns()}
dataSource={studentData}
pagination={false}
style={{ margin: "16px 0" }}
/>
{ total > 0 &&
<PageControl
size="small"
current={current - 1}
pageSize={size}
total={total}
onShowSizeChange={this.onShowSizeChange}
toPage={(page) => {
this.fetchUserData(page + 1);
}}
/>
}
</div>
</Spin>
);
}
}
export default withRouter(CourseData);
.knowledge-base-filter {
position: relative;
.search-condition {
width: calc(100% - 80px);
display: flex;
align-items: center;
flex-wrap: wrap;
&__item {
width: 45%;
max-width: 600px;
margin-right: 3%;
margin-bottom: 12px;
.search-name{
vertical-align: middle;
line-height: 30px;
}
.shelf-status{
width:84px;
display:inline-block;
text-align:right;
}
}
}
.reset-fold-area {
position: absolute;
right: 12px;
}
.resetBtn {
color: #999999;
font-size: 18px;
margin-right: 8px;
}
.fold-btn {
font-size: 14px;
color: #666666;
line-height: 20px;
.fold-icon {
font-size: 12px;
margin-left:4px;
}
}
}
.data-icon {
cursor: pointer;
}
/*
* @Description:
* @Author: zangsuyun
* @Date: 2021-03-12 11:16:38
* @LastEditors: zangsuyun
* @LastEditTime: 2021-03-25 14:21:44
* @Copyright: © 2020 杭州杰竞科技有限公司 版权所有
*/
import React from "react";
import { Row, Input, Select, Tooltip } from "antd";
import "./KnowledgeBase.less";
import ENUM from "../ENUM.js";
const { Search } = Input;
const { Option } = Select;
const DEFAULT_QUERY = {
name: null, // 课程名称
// operatorId: null, // 创建人
// beginTime: null, // 开始日期
// endTime: null, // 结束日期
type: null,
};
class KnowledgeBaseFilter extends React.Component {
constructor(props) {
super(props);
this.state = {
query: { ...DEFAULT_QUERY }, // 使用扩展运算符,避免浅拷贝
};
}
// 改变搜索条件
handleChangeQuery = (field, value) => {
this.setState(
{
query: {
...this.state.query,
[field]: value,
current: 1,
},
},
() => {
this.props.onChange(this.state.query);
}
);
};
// 重置搜索条件
handleReset = () => {
this.setState(
{
query: DEFAULT_QUERY,
},
() => {
this.props.onChange(this.state.query);
}
);
};
render() {
const {
query: {
courseName,
courseType,
},
} = this.state;
return (
<div className="knowledge-base-filter">
<Row type="flex" justify="space-between" align="top">
<div className="search-condition">
<div className="search-condition__item">
<span className="search-name">课程名称:</span>
<Search
value={courseName}
placeholder="搜索课程名称"
// onChange={(e) => {
// this.handleChangeQuery("name", e.target.value);
// }}
onSearch={(value) => {
this.handleChangeQuery("name", value);
}}
style={{ width: "calc(100% - 84px)" }}
enterButton={<span className="icon iconfont">&#xe832;</span>}
/>
</div>
<div className="search-condition__item">
<span className="shelf-status">课程类型:</span>
<Select
style={{ width: "calc(100% - 84px)" }}
placeholder="请选择课程类型"
allowClear={true}
value={courseType}
onChange={(value) => {
this.handleChangeQuery("type", value);
}}
suffixIcon={
<span
className="icon iconfont"
style={{ fontSize: "12px", color: "#BFBFBF" }}
>
&#xe835;
</span>
}
>
{Reflect.ownKeys(ENUM.CourseTypeEnum).map((item) => {
return (
<Option value={item}>{ENUM.CourseTypeEnum[item]}</Option>
);
})}
</Select>
</div>
</div>
<div className="reset-fold-area">
<Tooltip title="清空筛选">
<span
className="resetBtn iconfont icon"
onClick={this.handleReset}
>
&#xe61b;{" "}
</span>
</Tooltip>
</div>
</Row>
</div>
);
}
}
export default KnowledgeBaseFilter;
/*
* @Description:
* @Author: zangsuyun
* @Date: 2021-03-12 14:49:40
* @LastEditors: zangsuyun
* @LastEditTime: 2021-03-25 17:54:33
* @Copyright: © 2020 杭州杰竞科技有限公司 版权所有
*/
import React from "react";
import { Table, Modal, message, Tooltip, Switch, Dropdown } from "antd";
import { Route, withRouter } from "react-router-dom";
import { PageControl } from "@/components";
import { LIVE_SHARE_MAP } from "@/common/constants/academic/cloudClass";
import { appId, shareUrl, LIVE_SHARE } from "@/domains/course-domain/constants";
import WatchData from "./WatchData";
import KnowledgeAPI from "@/data-source/knowledge/request-api";
import ENUM from "../ENUM.js";
import "./KnowledgeBaseList.less";
const { confirm } = Modal;
const ENV = process.env.DEPLOY_ENV || "dev";
class KnowledgeBaseList extends React.Component {
constructor(props) {
super(props);
this.state = {
id: "", // 视频课ID
studentIds: [],
};
}
handleAdminName = (adminArray) => {
let adminStr = "";
adminArray.map((item, index) => {
if (index < adminArray.length - 1) {
adminStr = adminStr + item.adminName + "、";
} else {
adminStr = adminStr + item.adminName;
}
});
return adminStr;
};
handleUp = (index, record) => {
if (index === 0) {
return;
}
const params = {
direction: "UP",
id: record.id,
storeId: record.storeId,
};
KnowledgeAPI.moveKnowledge(params).then((res) => {
if (res.success) {
message.success("更新成功");
this.props.onChange();
}
});
};
handleDown = (record, index) => {
const { query, totalCount } = this.props;
const { current, size } = query;
if (
index === query.size - 1 ||
totalCount === size * (current - 1) + index + 1
) {
return;
}
const params = {
direction: "DOWN",
id: record.id,
storeId: record.storeId,
};
KnowledgeAPI.moveKnowledge(params).then((res) => {
if (res.success) {
message.success("更新成功");
this.props.onChange();
}
});
};
// 请求表头
parseColumns = () => {
const { query, totalCount } = this.props;
const { current, size } = query;
const columns = [
{
title: "课程名称",
key: "name",
dataIndex: "name",
width: 371,
// fixed: "left",
render: (val, record) => {
const { coverUrl, mediaCourseUrl } = record.source;
let hasCover = false;
const type = record.type;
return (
<div>
{type === "LIVE" && (
<div className="record__item">
{record.source &&
record.source.courseMediaVOS.map((item, index) => {
if (item.contentType === "COVER") {
hasCover = true;
return (
<img className="course-cover" src={item.mediaUrl} />
);
}
})}
{!hasCover && (
<img
className="course-cover"
src={"https://image.xiaomaiketang.com/xm/YNfi45JwFA.png"}
/>
)}
<div>
{val.length > 17 ? (
<Tooltip title={val}>
<div className="course-name">{val}</div>
</Tooltip>
) : (
<div className="course-name">{val}</div>
)}
<div>
<span className="course-time">
{formatDate(
"YYYY-MM-DD H:i",
parseInt(record.source.startTime)
)}
~{formatDate("H:i", parseInt(record.source.endTime))}
</span>
<span
className="course-status"
style={{
color:
ENUM.courseStateShow[record.source.courseState]
.color,
border: `1px solid ${
ENUM.courseStateShow[record.source.courseState]
.color
}`,
}}
>
{ENUM.courseStateShow[record.source.courseState].title}
</span>
</div>
<div className="teacher-assistant">
{record.source.teacherName.length > 4 ? (
<Tooltip title={record.source.teacherName}>
<span className="teacher">
讲师:{record.source.teacherName}
</span>
</Tooltip>
) : (
<span className="teacher">
讲师:{record.source.teacherName}
</span>
)}
{record.source.admins.length > 0 && (
<>
<span className="split"> | </span>
{this.handleAdminName(record.source.admins).length >
4 ? (
<Tooltip
title={this.handleAdminName(record.source.admins)}
>
<span className="assistant">
助教:
{record.source.admins.map((item, index) => {
return (
<span>
{item.adminName}{" "}
{index <
record.source.admins.length - 1 && (
<span></span>
)}{" "}
</span>
);
})}
</span>
</Tooltip>
) : (
<span className="assistant">
助教:
{record.source.admins.map((item, index) => {
return (
<span>
{item.adminName}{" "}
{index <
record.source.admins.length - 1 && (
<span></span>
)}{" "}
</span>
);
})}
</span>
)}
</>
)}
</div>
</div>
</div>
)}
{type === "VOICE" && (
<div className="record__item">
{/* 上传了封面的话就用上传的封面, 没有的话就取视频的第一帧 */}
<img
className="course-cover"
src={
coverUrl ||
`${mediaCourseUrl}?x-oss-process=video/snapshot,t_0,m_fast`
}
/>
{val.length > 25 ? (
<Tooltip title={val}>
<div className="course-name clamp">{val}</div>
</Tooltip>
) : (
<div className="course-name clamp">{val}</div>
)}
</div>
)}
{type === "PICTURE" && (
<div className="record__item">
<img
className="course-cover"
src={
coverUrl ||
"https://image.xiaomaiketang.com/xm/YNfi45JwFA.png"
}
/>
{val.length > 25 ? (
<Tooltip title={val}>
<div className="course-name clamp">{val}</div>
</Tooltip>
) : (
<div className="course-name clamp">{val}</div>
)}
</div>
)}
{type === "FOLDER" && (
<div className="record__item">
<div
className={`folder-type ${
record.source && record.source.folderFormat
}`}
/>
{val.length > 25 ? (
<Tooltip title={val}>
<div className="course-name clamp">{val}</div>
</Tooltip>
) : (
<div className="course-name clamp">{val}</div>
)}
</div>
)}
</div>
);
},
},
{
title: "课程类型",
key: "type",
dataIndex: "type",
// width: 100,
render: (val, record) => {
return (
<div className="record__item">
{val ? ENUM.CourseTypeEnum[val] : "-"}
</div>
);
},
},
{
title: "创建人",
key: "createName",
dataIndex: "createName",
// width: 100,
render: (val) => {
return (
<div>
{val && (
<Tooltip title={val}>
<div>{val.length > 4 ? `${val.slice(0, 4)}...` : val}</div>
</Tooltip>
)}
</div>
);
},
},
{
title: "观看数据",
// width: 100,
key: "watchUserCount",
dataIndex: "watchUserCount",
render: (val, item) => {
return val ? (
<div
className="operate"
onClick={() => this.handleLinkToClassData(item)}
>
<span className="operate__item">{val}</span>
</div>
) : (
0
);
},
},
{
title: "操作",
key: "operate",
dataIndex: "operate",
width: 160,
// fixed: "right",
render: (val, record, index) => {
return (
<div className="operate">
<div
className={
index === 0 ? "operate__item disable" : "operate__item"
}
onClick={() => this.handleUp(index, record)}
>
上移
</div>
<span className="operate__item split"> | </span>
<div
className={
index === size - 1 ||
totalCount === size * (current - 1) + index + 1
? "operate__item disable"
: "operate__item"
}
onClick={() => this.handleDown(record, index)}
>
下移
</div>
<span className="operate__item split"> | </span>
<div
className="operate__item"
onClick={() => this.handleDelete(record)}
>
移除
</div>
</div>
);
},
},
];
return columns;
};
handleDelete = (record) => {
return confirm({
title: "移除知识",
content: "确定将分类中此知识移除吗?",
icon: (
<span className="icon iconfont default-confirm-icon">&#xe839; </span>
),
okText: "删除",
okType: "danger",
cancelText: "取消",
width: 440,
height: 188,
onOk: () => {
this.deleteConfirm(record);
},
});
};
// 前往上课数据页面
handleLinkToClassData = (item) => {
const { match } = this.props;
console.log(item);
localStorage.setItem("WatchData_CourseName", item.name);
window.RCHistory.push({
// pathname: `${match.url}/course-data?type=${item.courseType}&id=${item.liveCourseId}`,
pathname: `${match.url}/course-data?type=${item.type}&id=${item.id}`,
});
};
deleteConfirm = (item) => {
const params = {
id: item.id,
storeId: item.storeId,
};
KnowledgeAPI.delKnowledge(params).then((res) => {
if (res.success) {
message.success("移除成功");
this.props.onChange();
this.props.updateCategoryTree();
}
});
};
onShowSizeChange = (current, size) => {
if (current == size) {
return;
}
let _query = this.props.query;
_query.size = size;
this.props.onChange(_query);
};
render() {
const { dataSource = [], totalCount, query, match } = this.props;
const { current, size } = query;
return (
<div className="knowledge-base-list">
<Table
rowKey={(record) => record.id}
size="middle"
dataSource={dataSource}
columns={this.parseColumns()}
pagination={false}
// scroll={{ x: 1500 }}
bordered
className="video-list-table"
/>
<div className="box-footer">
{totalCount > 0 && (
<PageControl
current={current - 1}
pageSize={size}
total={totalCount}
toPage={(page) => {
const _query = { ...query, current: page + 1 };
this.props.onChange(_query);
}}
onShowSizeChange={this.onShowSizeChange}
/>
)}
</div>
<Route path={`${match.url}/course-data`} component={WatchData} />
</div>
);
}
}
export default withRouter(KnowledgeBaseList);
.knowledge-base-list {
margin-top: 12px;
.categoryName {
font-size: 14px;
color: #666666;
line-height: 20px;
}
.courseware {
font-size: 14px;
color: #5289fa;
line-height: 20px;
text-align: right;
cursor: pointer;
}
.quota-icon {
color: #5289fa;
cursor: pointer;
}
.operate {
display: flex;
align-items: center;
flex-wrap: wrap;
.operate__item {
color: #5289fa;
cursor: pointer;
&.split {
margin: 0 8px;
color: #bfbfbf;
}
&.disable {
cursor: auto;
color: #cccccc;
}
}
}
.operate-text {
color: #5289fa;
cursor: pointer;
}
.course-start-end {
margin-left: 16px;
width: 78px;
height: 20px;
border-radius: 2px;
border: 1px solid rgba(204, 204, 204, 1);
display: flex;
align-items: center;
cursor: pointer;
white-space: nowrap;
.start-icon {
color: #3296fa;
font-size: 12px;
transform: scale(0.8);
margin: 0 5px;
}
.end-icon {
color: #00d700;
font-size: 12px;
transform: scale(0.8);
margin: 0 5px;
}
.start-end-text {
font-size: 12px;
}
}
}
.live-course-more-menu {
background: white;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
border-radius: 4px;
div {
line-height: 30px;
padding: 0 15px;
cursor: pointer;
&:hover {
background: #f3f6fa;
}
}
}
.tipTitle {
.type {
font-weight: 700;
}
}
.knowledge-base-list {
.record__item {
display: flex;
// align-items: center;
.course-cover {
min-width: 107px;
max-width: 90px;
height: 60px;
border-radius: 6px;
margin-right: 8px;
}
.folder-type {
min-width: 107px;
max-width: 90px;
height: 60px;
border-radius: 6px;
margin-right: 8px;
background-image: url("https://image.xiaomaiketang.com/xm/YNfi45JwFA.png");
background-size: cover;
&.JPG,&.PNG,&.JPEG {
background-image: url("https://image.xiaomaiketang.com/xm/AdpWiMHMet.png");
}
&.PPT {
background-image: url("https://image.xiaomaiketang.com/xm/eDDEZiDwMt.png");
}
&.WORD {
background-image: url("https://image.xiaomaiketang.com/xm/JGeWiiZ7YE.png");
}
&.EXCEL {
background-image: url("https://image.xiaomaiketang.com/xm/p3fDEy63Mc.png");
}
&.PDF {
background-image: url("https://image.xiaomaiketang.com/xm/2W5QAbRQfZ.png");
}
}
.course-name {
font-size: 14px;
font-weight: 500;
color: #333333;
line-height: 20px;
font-weight: bold;
font-family: PingFangSC-Medium, PingFang SC;
max-width: 244px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
height: 20px;
&.clamp {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
white-space: normal;
height: 40px;
}
}
.course-time {
font-size: 12px;
font-weight: 400;
color: #666666;
line-height: 20px;
}
.course-status {
font-size: 12px;
line-height: 18px;
display: inline-block;
border-radius: 2px;
padding: 0 8px;
margin-left: 4px;
}
.teacher-assistant {
display: flex;
.teacher {
font-size: 12px;
color: #666666;
max-width: 96px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
display: inline-block;
padding-top: 2px;
}
.assistant {
font-size: 12px;
color: #666666;
max-width: 96px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
display: inline-block;
padding-top: 2px;
}
.split {
margin: 0 4px;
color: #bfbfbf;
display: inline-blcok;
}
}
}
}
/*
* @Description:
* @Author: zangsuyun
* @Date: 2021-03-12 14:25:52
* @LastEditors: zangsuyun
* @LastEditTime: 2021-03-24 15:18:26
* @Copyright: © 2020 杭州杰竞科技有限公司 版权所有
*/
import React, { useState, useEffect } from "react";
import { Button, Menu, Dropdown,message } from "antd";
import SelectPrepareFileModal from "@/modules/prepare-lesson/modal/SelectPrepareFileModal";
import { DownOutlined } from "@ant-design/icons";
import AddCourse from "../modal/AddCourse";
import User from "@/common/js/user";
import KnowledgeAPL from "@/data-source/knowledge/request-api";
export default function KnowledgeBaseOpt({
categoryId,
updateCategoryTree,
onChange,
}) {
const [modal, setModal] = useState(null);
const menu = (
<Menu>
<Menu.Item key="1" style={{ textAlign: "center" }}>
<span onClick={handAddCourse}>新增课程</span>
</Menu.Item>
<Menu.Item key="2" style={{ textAlign: "center" }}>
<span onClick={handleAddFile}>新增资料</span>
</Menu.Item>
</Menu>
);
function handAddCourse() {
let modal = (
<AddCourse
onClose={() => {
setModal(null);
}}
onChange={onChange}
categoryId={categoryId}
updateCategoryTree={updateCategoryTree}
></AddCourse>
);
setModal(modal);
}
function handUpload(refIds) {
const params = {
categoryId: categoryId,
refIds,
storeId: User.getStoreId(),
createId: User.getUserId(),
type: "FOLDER",
};
KnowledgeAPL.addKnowledge(params).then(({ success }) => {
if (success) {
message.success("新增成功");
onChange();
updateCategoryTree();
setModal(null);
}
});
setModal(null);
}
function handleAddFile() {
let modal = (
<SelectPrepareFileModal
multiple={true}
scene="knowledge"
operateType="select"
isOpen={true}
accept=".ppt,.pptx,.doc,.docx,.pdf,.jpg,.jpeg,.png,.xlsx,.xls"
tooltip="支持文件类型:ppt、word、excel、pdf、jpg、jpeg、png"
onClose={() => {
setModal(null);
}}
onSelect={handUpload}
/>
);
setModal(modal);
}
return (
<div className="video-course-opt">
<Dropdown overlay={menu}>
<Button type="primary" className="mr12">
新增知识
<DownOutlined />
</Button>
</Dropdown>
{modal}
</div>
);
}
import React from 'react';
import { withRouter } from "react-router-dom";
import { Table, Button, Modal, message } from 'antd';
import dealTimeDuration from "../../course-manage/utils/dealTimeDuration";
import { PageControl } from "@/components";
// import './DataList.less';
import CourseService from "@/domains/course-domain/CourseService";
import User from '@/common/js/user';
const liveTypeMap = {
USER: "普通用户",
ANCHOR: "讲师",
ADMIN: "管理员(助教)",
GUEST: "游客"
};
class PlaybackData extends React.Component {
constructor(props) {
super(props);
const courseId = getParameterByName("id"); // 课程ID
this.state = {
playbackData: [],
current: 1,
size: 10,
total: 0,
liveCourseId: courseId,
storeId: User.getStoreId()
}
}
componentDidMount() {
this.fetchPlaybackList();
}
fetchPlaybackList = (page = 1) => {
const { size, liveCourseId } = this.state
const params = {
liveCourseId,
current: page,
size
}
CourseService.fetchPlaybackList(params).then((res) => {
if (res.result) {
const { records = [], current, size, total } = res.result;
this.setState({
playbackData: records,
current,
size,
total
});
}
});
};
getPlaybackColumns() {
const columns = [
{
title: "观看用户",
dataIndex: "userName",
},
{
title: "手机号",
dataIndex: "phone"
},
{
title: "观看者类型",
dataIndex: "userRole",
render: (text) => <span>{liveTypeMap[text]}</span>,
},
{
title: "开始观看时间",
dataIndex: "entryTime",
render: (text) => (
<span>{text ? formatDate("YYYY-MM-DD H:i", parseInt(text)) : '-'}</span>
),
},
{
title: "观看时长",
dataIndex: "lookingDuration",
render: (text) => {
return <span>{text ? dealTimeDuration(text) : '-'}</span>;
},
},
];
return columns;
}
// 导出
handleplaybackExport() {
const { storeId, liveCourseId } = this.state;
CourseService.exportPlayBackCourseData({
liveCourseId,
exportLiveType: "PLAY_BACK",
storeId
}).then((res) => {
const link = res.result;
this.setState({
link
});
document.getElementById("load-play-back-excel").click();
if(res.success){
message.success("导出成功!")
}
})
}
onShowSizeChange = (current, size) => {
if (current == size) {
return;
}
this.setState({ size }, this.fetchUserData)
}
render() {
const { playbackData, total, current, size, link} = this.state
return (
<div>
<a
href={link}
target="_blank"
download
id="load-play-back-excel"
style={{ position: "absolute", left: "-10000px" }}
>
111
</a>
<Button onClick={() => {this.handleplaybackExport()}}>导出</Button>
<Table
bordered
size="small"
columns={this.getPlaybackColumns()}
dataSource={playbackData}
pagination={false}
style={{ margin: '16px 0' }}>
</Table>
{ total > 0 &&
<PageControl
size="small"
current={current - 1}
pageSize={size}
total={total}
onShowSizeChange={this.onShowSizeChange}
toPage={(page) => {
this.fetchPlaybackList(page + 1);
}}
/>
}
</div>
)
}
}
export default withRouter(PlaybackData);
\ No newline at end of file
import React from "react";
import { withRouter } from "react-router-dom";
import { Tabs } from "antd";
import Breadcrumbs from "@/components/Breadcrumbs";
import WatchDataHeader from "@/components/WatchDataHeader";
import CourseData from "./CourseData";
import PlaybackData from "./PlayBackData";
import WatchDataModal from "./WatchDataModal";
// import './WatchData.less';
import ENUM from '../ENUM'
class WatchData extends React.Component {
constructor(props) {
super(props);
const type = getParameterByName("type");
const id = getParameterByName("id");
this.state = {
title: type === 'LIVE' ? "上课数据" : '观看数据',
type,
id
};
}
handChangeTitle = (title) => {
this.setState({
title,
});
};
render() {
const { type, title, id } = this.state;
return (
<div className="page data-list">
<Breadcrumbs
navList={title}
goBack={() => {
RCHistory.goBack();
}}
/>
<WatchDataHeader
type={ENUM.CourseTypeEnum[type]}
courseName={localStorage.getItem("WatchData_CourseName")}
color="#FFB714"
/>
<div className="box">
{type === "LIVE" && (
<Tabs defaultActiveKey="上课记录" onChange={this.handChangeTitle}>
<Tabs.TabPane tab="上课记录" key="上课记录">
<CourseData></CourseData>
</Tabs.TabPane>
<Tabs.TabPane tab="回放记录" key="观看数据">
<PlaybackData></PlaybackData>
</Tabs.TabPane>
</Tabs>
)}
{type !== "LIVE" && (
<WatchDataModal type="videoCourseList" data={id} type={type}/>
)}
</div>
</div>
);
}
}
export default withRouter(WatchData);
/*
* @Description:
* @Author: zangsuyun
* @Date: 2021-03-16 10:18:31
* @LastEditors: zangsuyun
* @LastEditTime: 2021-03-25 10:57:14
* @Copyright: © 2020 杭州杰竞科技有限公司 版权所有
*/
import React from "react";
import { Table, message, Input, Button } from "antd";
import { PageControl } from "@/components";
import CourseService from "@/domains/course-domain/CourseService";
import User from "@/common/js/user";
// import './WatchDataModal.less';
import dealTimeDuration from "../../course-manage/utils/dealTimeDuration";
import KnowledgeAPI from "@/data-source/knowledge/request-api";
const { Search } = Input;
class WatchDataModal extends React.Component {
constructor(props) {
super(props);
this.state = {
dataSource: [],
size: 10,
query: {
current: 1,
},
totalCount: 0,
};
}
componentDidMount() {
this.handleFetchDataList();
}
// 获取观看视频数据列表
handleFetchDataList = () => {
const { query, size, totalCount } = this.state;
const id = this.props.data;
const params = {
...query,
size,
id,
storeId: User.getStoreId(),
};
KnowledgeAPI.queryPageKnowledgeMediaCourseWatchInfo(params).then((res) => {
const { result = {} } = res;
const { records = [], total = 0 } = result;
this.setState({
dataSource: records,
totalCount: Number(total),
});
});
};
handleChangNickname = (value) => {
const isPhone = (value || "").match(/^\d+$/);
const { query } = this.state;
if (isPhone) {
query.phone = value;
query.nickName = null;
} else {
query.nickName = value;
query.phone = null;
}
query.current = 1;
this.setState({
query,
});
};
onShowSizeChange = (current, size) => {
if (current == size) {
return;
}
this.setState(
{
size,
},
() => {
this.handleFetchDataList();
}
);
};
// 请求表头
parseColumns = () => {
const { type } = this.props;
console.log(type);
const columns = [
{
title: "观看用户",
key: "name",
dataIndex: "name",
},
{
title: "手机号",
key: "phone",
dataIndex: "phone",
},
{
title: "观看者类型",
key: "userRole",
dataIndex: "userRole",
},
{
title: "首次观看时间",
key: "firstWatch",
dataIndex: "firstWatch",
render: (val) => {
return formatDate("YYYY-MM-DD H:i", val);
},
},
];
if (type === "VOICE" || type === 'PICTURE') {
columns.push({
title: "观看时长",
key: "watchDuration",
dataIndex: "watchDuration",
render: (val) => {
return <span>{val ? dealTimeDuration(val) : "00:00:00"}</span>;
},
});
}
if(type === 'PICTURE'){
columns.push({
title: "学习进度",
key: "watchDuration",
dataIndex: "watchDuration",
render: (val) => {
return <span>{val}</span>;
},
});
}
return columns;
};
handleExportV5 = () => {
// const { liveCourseId, storeId } = this.state;
// CourseService.exportStudentCourseData({
// liveCourseId: liveCourseId,
// exportLiveType: "VISITOR",
// storeId,
// }).then((res) => {
// const link = res.result;
// this.setState({
// link
// });
// document.getElementById("loadExcel").click();
// if (res.success) {
message.success("导出成功!");
// }
// });
};
render() {
const { size, dataSource, totalCount, query } = this.state;
return (
<div className="watch-data">
<div className="search-container">
<Search
placeholder="搜索用户姓名/手机号"
style={{ width: 200 }}
onChange={(e) => {
this.handleChangNickname(e.target.value);
}}
onSearch={() => {
this.handleFetchDataList();
}}
enterButton={<span className="icon iconfont">&#xe832;</span>}
/>
</div>
<div className="filter">
<Button
style={{ height: 32, margin: "16px auto 13px 0" }}
onClick={_.debounce(
() => {
if (!dataSource.length) {
message.warning("暂无数据可导出");
return;
}
this.handleExportV5();
},
500,
true
)}
>
导出
</Button>
</div>
<div>
<Table
rowKey={(record) => record.id}
dataSource={dataSource}
columns={this.parseColumns()}
pagination={false}
bordered
/>
{dataSource.length > 0 && (
<div className="box-footer">
<PageControl
current={query.current - 1}
pageSize={size}
total={totalCount}
size="small"
toPage={(page) => {
const _query = { ...query, current: page + 1 };
this.setState(
{
query: _query,
},
() => {
this.handleFetchDataList();
}
);
}}
onShowSizeChange={this.onShowSizeChange}
/>
</div>
)}
</div>
</div>
);
}
}
export default WatchDataModal;
/*
* @Description:
* @Author: zangsuyun
* @Date: 2021-03-12 10:43:10
* @LastEditors: zangsuyun
* @LastEditTime: 2021-03-25 13:45:55
* @Copyright: © 2020 杭州杰竞科技有限公司 版权所有
*/
import React from "react";
import KnowledgeBaseFilter from "./components/KnowledgeBaseFilter";
import KnowledgeBaseOpt from "./components/KnowledgeBaseOpt";
import KnowledgeBaseList from "./components/KnowledgeBaseList";
import Classification from "./components/Classification";
import KnowledgeAPI from "@/data-source/knowledge/request-api";
import User from "@/common/js/user";
export default class KnowledgeBase extends React.Component {
constructor(props) {
super(props);
this.state = {
query: {
size: 10,
current: 1,
storeId: User.getStoreId(),
categoryId: 0,
},
dataSource: [], // 知识库列表
totalCount: 0, // 知识库数据总条数
categoryId: 0,
updateCategoryFlag: false,
};
}
componentWillMount() {
// 获取知识库列表
this.handleFetchScheduleList();
// this.getCategoryTree()
}
getSelectedCategoryId = (categoryId) => {
this.setState({
categoryId,
});
this.handleFetchScheduleList({ categoryId,current:1 });
};
// 更新分类树
updateCategoryTree = () => {
this.setState({
updateCategoryFlag: !this.state.updateCategoryFlag,
});
};
// 获取知识库列表
handleFetchScheduleList = (_query = {}) => {
const query = {
...this.state.query,
..._query,
};
// 更新请求参数
this.setState({ query });
KnowledgeAPI.queryPageKnowledgeForManager(query).then((res) => {
// KnowledgeAPI.videoSchedulePage(query).then((res) => {
const { result = {} } = res || {};
const { records = [], total = 0 } = result;
this.setState({
dataSource: records,
totalCount: Number(total),
});
});
};
render() {
const {
dataSource,
totalCount,
query,
categoryId,
updateCategoryFlag,
} = this.state;
return (
<div className="page">
<div className="content-header">知识库</div>
<div className="box" style={{ display: "flex" }}>
{/* 搜索模块 */}
<div className="left" style={{ width: 245 }}>
<Classification
updateCategoryFlag={updateCategoryFlag}
categoryId={categoryId}
getSelectedCategoryId={this.getSelectedCategoryId}
/>
</div>
<div
className="liner"
style={{ backgroundColor: "#ddd", width: 1, margin: "1px 20px" }}
></div>
<div className="right" style={{ width: "calc(100% - 285px)" }}>
<KnowledgeBaseFilter onChange={this.handleFetchScheduleList} />
{/* 操作模块 */}
<KnowledgeBaseOpt
onChange={this.handleFetchScheduleList}
updateCategoryTree={this.updateCategoryTree}
categoryId={categoryId}
/>
{/* 知识库列表模块 */}
<KnowledgeBaseList
query={query}
dataSource={dataSource}
totalCount={totalCount}
onChange={this.handleFetchScheduleList}
updateCategoryTree={this.updateCategoryTree}
/>
</div>
</div>
</div>
);
}
}
/*
* @Description:
* @Author: zangsuyun
* @Date: 2021-03-13 09:54:26
* @LastEditors: zangsuyun
* @LastEditTime: 2021-03-24 11:53:09
* @Copyright: © 2020 杭州杰竞科技有限公司 版权所有
*/
import React from "react";
import {
Row,
Modal,
Button,
message,
Table,
Select,
Radio,
Input,
Tabs,
Tooltip,
} from "antd";
import { PageControl } from "@/components";
import TableSelectedData from "@/components/TableSelectedData";
import CourseService from "@/domains/course-domain/CourseService";
import KnowledgeAPI from "@/data-source/knowledge/request-api";
import User from "@/common/js/user";
import "./LiveList.less";
import _ from "underscore";
import dealTimeDuration from "../../course-manage/utils/dealTimeDuration";
const { Search } = Input;
const { TabPane } = Tabs;
const courseStateShow = {
UN_START: {
code: 1,
title: "待开课",
color: "#FFB714",
},
STARTING: {
code: 2,
title: "上课中",
color: "#238FFF",
},
FINISH: {
code: 3,
title: "已完成",
color: "#3BBDAA",
},
EXPIRED: {
code: 4,
title: "未成功开课",
color: "#999",
},
};
class AddCourse extends React.Component {
constructor(props) {
super(props);
this.state = {
liveDataSource: [],
liveSize: 10,
liveQuery: {
current: 1,
excludeUsed: true,
courseType: "LIVE",
storeId: User.getStoreId(),
},
liveTotalCount: 0,
selectLive: [], //弹窗内已选择的直播课程
videoDataSource: [],
videoSize: 10,
videoQuery: {
current: 1,
courseType: "VOICE",
excludeUsed: true,
storeId: User.getStoreId(),
},
videoTotalCount: 0,
selectVideo: [], //弹窗内已选择的视频课程
pictureDataSource: [],
pictureSize: 10,
pictureQuery: {
current: 1,
excludeUsed: true,
courseType: "PICTURE",
storeId: User.getStoreId(),
},
pictureTotalCount: 0,
selectPicture: [], //弹窗内已选择的图文课程
};
}
componentDidMount() {
this.handleFetchLiveList();
this.handleFetchVideoList();
this.handleFetchPictureList();
}
// 获取直播课列表
handleFetchLiveList = () => {
const { liveQuery, liveSize } = this.state;
const params = {
...liveQuery,
size: liveSize,
};
// CourseService.getLiveCloudCoursePage(params).then((res) => {
KnowledgeAPI.knowledgeLiveCoursePage(params).then((res) => {
const { result = {} } = res;
const { records = [], total = 0 } = result;
this.setState({
liveDataSource: records,
liveTotalCount: Number(total),
});
});
};
// 获取视频课列表
handleFetchVideoList = () => {
const { videoQuery, videoSize } = this.state;
const params = {
...videoQuery,
size: videoSize,
};
// CourseService.videoSchedulePage(query).then((res) => {
KnowledgeAPI.knowledgeMediaCoursePage(params).then((res) => {
const { result = {} } = res || {};
const { records = [], total = 0 } = result;
this.setState({
videoDataSource: records,
videoTotalCount: Number(total),
});
});
};
// 获取图文课列表
handleFetchPictureList = () => {
const { pictureQuery, pictureSize } = this.state;
const params = {
...pictureQuery,
size: pictureSize,
};
// CourseService.pictureSchedulePage(query).then((res) => {
KnowledgeAPI.knowledgeMediaCoursePage(params).then((res) => {
const { result = {} } = res || {};
const { records = [], total = 0 } = result;
this.setState({
pictureDataSource: records,
pictureTotalCount: Number(total),
});
});
};
onShowLiveSizeChange = (current, size) => {
if (current == size) {
return;
}
this.setState(
{
liveSize: size,
},
() => {
this.handleFetchLiveList();
}
);
};
onShowVideoSizeChange = (current, size) => {
if (current == size) {
return;
}
this.setState(
{
videoSize: size,
},
() => {
this.handleFetchVideoList();
}
);
};
onShowPictureSizeChange = (current, size) => {
if (current == size) {
return;
}
this.setState(
{
pictureSize: size,
},
() => {
this.handleFetchPictureList();
}
);
};
liveColumns = () => {
const columns = [
{
title: (
<span>
<span>课程信息</span>
<Tooltip
title={<div>已加入该分类的课程不支持重复选择,因此不显示。</div>}
>
<i
className="icon iconfont"
style={{
marginLeft: "5px",
cursor: "pointer",
color: "#bfbfbf",
fontSize: "14px",
}}
>
&#xe61d;
</i>
</Tooltip>
</span>
),
width: 371,
key: "course",
dataIndex: "courseName",
render: (val, record) => {
let hasCover = false;
return (
<div className="record__item">
{record.courseMediaVOS.map((item, index) => {
if (item.contentType === "COVER") {
hasCover = true;
return <img className="course-cover" src={item.mediaUrl} />;
}
})}
{!hasCover && (
<img
className="course-cover"
src={"https://image.xiaomaiketang.com/xm/YNfi45JwFA.png"}
/>
)}
<div>
{record.courseName.length > 17 ? (
<Tooltip title={record.courseName}>
<div className="course-name">{record.courseName}</div>
</Tooltip>
) : (
<div className="course-name">{record.courseName}</div>
)}
<div>
<span
className="course-status"
style={{
color: courseStateShow[record.courseState].color,
border: `1px solid ${
courseStateShow[record.courseState].color
}`,
}}
>
{courseStateShow[record.courseState].title}
</span>
</div>
</div>
</div>
);
},
},
{
title: "上课时间",
width: 110,
key: "couseCatalog",
dataIndex: "couseCatalog",
render: (val, item) => {
return (
<span className="course-time">
{formatDate("YYYY-MM-DD", parseInt(item.startTime))} <br></br>
{formatDate("H:i", parseInt(item.startTime))}~
{formatDate("H:i", parseInt(item.endTime))}
</span>
);
},
},
{
title: "课程分类",
// width: "10%",
key: "couseCatalog",
dataIndex: "couseCatalog",
render: (val, record) => {
return (
<div className="categoryName">
{record.categoryOneName}
{record.categoryTwoName ? `-${record.categoryTwoName}` : ""}
</div>
);
},
},
];
return columns;
};
videoColumns = () => {
const columns = [
{
title: (
<span>
<span>课程信息</span>
<Tooltip
title={<div>已加入该分类的课程不支持重复选择,因此不显示。</div>}
>
<i
className="icon iconfont"
style={{
marginLeft: "5px",
cursor: "pointer",
color: "#bfbfbf",
fontSize: "14px",
}}
>
&#xe61d;
</i>
</Tooltip>
</span>
),
key: "scheduleName",
dataIndex: "scheduleName",
width: 371,
render: (val, record) => {
const { coverUrl, mediaCourseUrl } = record;
return (
<div className="record__item">
{/* 上传了封面的话就用上传的封面, 没有的话就取视频的第一帧 */}
<img
className="course-cover"
src={
coverUrl ||
`${mediaCourseUrl}?x-oss-process=video/snapshot,t_0,m_fast`
}
/>
{record.courseName.length > 25 ? (
<Tooltip title={record.courseName}>
<div className="course-name">{record.courseName}</div>
</Tooltip>
) : (
<div className="course-name">{record.courseName}</div>
)}
</div>
);
},
},
{
title: "课程时长",
key: "videoDuration",
dataIndex: "videoDuration",
render: (text, item) => {
return <span>{text ? dealTimeDuration(text) : "-"}</span>;
},
},
{
title: "课程分类",
key: "categoryName",
dataIndex: "categoryName",
render: (val, record) => {
return (
<div className="record__item">
{record.categoryOneName}
{record.categoryTwoName ? `-${record.categoryTwoName}` : ""}
</div>
);
},
},
];
return columns;
};
pictureColumns = () => {
const columns = [
{
title: (
<span>
<span>课程信息</span>
<Tooltip
title={<div>已加入该分类的课程不支持重复选择,因此不显示。</div>}
>
<i
className="icon iconfont"
style={{
marginLeft: "5px",
cursor: "pointer",
color: "#bfbfbf",
fontSize: "14px",
}}
>
&#xe61d;
</i>
</Tooltip>
</span>
),
key: "scheduleName",
dataIndex: "scheduleName",
width: 371,
render: (val, record) => {
const { coverUrl } = record;
return (
<div className="record__item">
{/* 上传了封面的话就用上传的封面, 没有的话就取视频的第一帧 */}
<img
className="course-cover"
src={
coverUrl ||
"https://image.xiaomaiketang.com/xm/YNfi45JwFA.png"
}
/>
{record.courseName.length > 25 ? (
<Tooltip title={record.courseName}>
<div className="course-name">{record.courseName}</div>
</Tooltip>
) : (
<div className="course-name">{record.courseName}</div>
)}
</div>
);
},
},
{
title: "课程分类",
key: "categoryName",
dataIndex: "categoryName",
render: (val, record) => {
return (
<div className="record__item">
{record.categoryOneName}
{record.categoryTwoName ? `-${record.categoryTwoName}` : ""}
</div>
);
},
},
];
return columns;
};
selectLiveList = (record, selected) => {
let { selectLive } = this.state;
let _list = [];
if (
selected ||
!_.find(selectLive, (item) => item.liveCourseId == record.liveCourseId)
) {
_list = _.uniq(
selectLive.concat([record]),
false,
(item) => item.liveCourseId
);
} else {
_list = _.reject(
selectLive,
(item) => item.liveCourseId === record.liveCourseId
);
}
this.setState({ selectLive: _list });
};
selectVideoList = (record, selected) => {
console.log(record);
let { selectVideo } = this.state;
let _list = [];
if (selected || !_.find(selectVideo, (item) => item.id == record.id)) {
_list = _.uniq(selectVideo.concat([record]), false, (item) => item.id);
} else {
_list = _.reject(selectVideo, (item) => item.id === record.id);
}
this.setState({ selectVideo: _list });
};
selectPictureList = (record, selected) => {
console.log(record);
let { selectPicture } = this.state;
let _list = [];
if (selected || !_.find(selectPicture, (item) => item.id == record.id)) {
_list = _.uniq(selectPicture.concat([record]), false, (item) => item.id);
} else {
_list = _.reject(selectPicture, (item) => item.id === record.id);
}
this.setState({ selectPicture: _list });
};
callback(key) {
console.log(key);
}
handleChangVideoFilter = (key, value) => {
const { videoQuery } = this.state;
videoQuery[key] = value;
videoQuery.current = 1;
this.setState(
{
videoQuery,
},
() => {
this.handleFetchVideoList();
}
);
};
handleChangLiveFilter = (key, value) => {
const { liveQuery } = this.state;
liveQuery[key] = value;
liveQuery.current = 1;
this.setState(
{
liveQuery,
},
() => {
this.handleFetchLiveList();
}
);
};
handleChangPictureFilter = (key, value) => {
const { pictureQuery } = this.state;
pictureQuery[key] = value;
pictureQuery.current = 1;
this.setState(
{
pictureQuery,
},
() => {
this.handleFetchPictureList();
}
);
};
handAddCourse = () => {
const { selectVideo, selectLive, selectPicture } = this.state;
const batchAddList = [];
if (selectVideo.length) {
batchAddList.push({
categoryId: this.props.categoryId,
refIds: _.pluck(selectVideo, "id"),
storeId: User.getStoreId(),
type: "VOICE",
createId: User.getUserId(),
});
}
if (selectLive.length) {
batchAddList.push({
categoryId: this.props.categoryId,
refIds: _.pluck(selectLive, "liveCourseId"),
storeId: User.getStoreId(),
type: "LIVE",
createId: User.getUserId(),
});
}
if (selectPicture.length) {
batchAddList.push({
categoryId: this.props.categoryId,
refIds: _.pluck(selectPicture, "id"),
storeId: User.getStoreId(),
type: "PICTURE",
createId: User.getUserId(),
});
}
KnowledgeAPI.addDifTypeKnowledge({ batchAddList }).then(({ success }) => {
if (success) {
message.success("新增成功");
this.props.onClose();
this.props.onChange();
this.props.updateCategoryTree();
}
});
};
render() {
const {
liveDataSource,
liveSize,
liveQuery,
liveTotalCount,
selectLive,
videoDataSource,
videoSize,
videoQuery,
videoTotalCount,
selectVideo,
pictureDataSource,
pictureSize,
pictureQuery,
pictureTotalCount,
selectPicture,
} = this.state;
const LiveSelection = {
selectedRowKeys: _.pluck(selectLive, "liveCourseId"),
onSelect: this.selectLiveList,
onSelectAll: (selected, _selectedRows, changeRows) => {
let _list = [];
if (selected) {
_list = _.uniq(
selectLive.concat(changeRows),
false,
(item) => item.liveCourseId
);
} else {
_list = _.reject(selectLive, (item) =>
_.find(
changeRows,
(data) => data.liveCourseId === item.liveCourseId
)
);
}
this.setState({ selectLive: _list });
},
};
const VideoSelection = {
selectedRowKeys: _.pluck(selectVideo, "id"),
onSelect: this.selectVideoList,
onSelectAll: (selected, _selectedRows, changeRows) => {
let _list = [];
if (selected) {
_list = _.uniq(
selectVideo.concat(changeRows),
false,
(item) => item.id
);
} else {
_list = _.reject(selectVideo, (item) =>
_.find(changeRows, (data) => data.id === item.id)
);
}
this.setState({ selectVideo: _list });
},
};
const PictureSelection = {
selectedRowKeys: _.pluck(selectPicture, "id"),
onSelect: this.selectPictureList,
onSelectAll: (selected, _selectedRows, changeRows) => {
console.log(changeRows);
let _list = [];
if (selected) {
_list = _.uniq(
selectPicture.concat(changeRows),
false,
(item) => item.id
);
} else {
_list = _.reject(selectPicture, (item) =>
_.find(changeRows, (data) => data.id === item.id)
);
}
this.setState({ selectPicture: _list });
},
};
return (
<Modal
visible={true}
width={720}
title="新增课程"
onCancel={this.props.onClose}
onOk={this.handAddCourse}
className="add-course-modal"
>
<Tabs defaultActiveKey="VIDEO" onChange={this.callback} centered>
<TabPane tab="视频课" key="VIDEO">
<div className="live-list">
<div>
<Row type="flex" justify="space-between" align="top">
<div>
<span style={{ lineHeight: "32px" }}>课程名称:</span>
<Search
// value={courseName}
style={{ width: "calc(100% - 75px)" }}
placeholder="搜索课程名称"
onSearch={(value) => {
this.handleChangVideoFilter("courseName", value);
}}
enterButton={
<span className="icon iconfont">&#xe832;</span>
}
/>
</div>
<div style={{ width: "50%" }}>
<span className="shelf-status">课程分类:</span>
<Select
// value={courseType}
style={{ width: "calc(100% - 75px)" }}
placeholder="请选择课程类型"
allowClear={true}
onChange={(value) => {
setCourseType(value);
}}
suffixIcon={
<span
className="icon iconfont"
style={{ fontSize: "12px", color: "#BFBFBF" }}
>
&#xe835;
</span>
}
>
<Option value="LIVE">直播课</Option>
<Option value="VOICE">视频课</Option>
<Option value="PICTURE">图文课</Option>
<Option value="knowledge">学习资料</Option>
</Select>
</div>
</Row>
</div>
<TableSelectedData
selectedNum={
selectVideo.length + selectLive.length + selectPicture.length
}
clearSelectedData={() => {
this.setState({
selectVideo: [],
selectLive: [],
selectPicture: [],
});
}}
/>
<Table
rowKey={(record) => record.id}
dataSource={videoDataSource}
columns={this.videoColumns()}
size="middle"
rowSelection={VideoSelection}
pagination={false}
bordered
className="video-list-table"
style={{ maxHeight: 359, overflow: "scroll" }}
/>
<div className="box-footer">
{videoTotalCount > 0 && (
<PageControl
current={videoQuery.current - 1}
pageSize={videoSize}
total={videoTotalCount}
toPage={(page) => {
const _query = { ...videoQuery, current: page + 1 };
this.setState(
{
videoQuery: _query,
},
() => {
this.handleFetchVideoList();
}
);
}}
onShowSizeChange={this.onShowVideoSizeChange}
/>
)}
</div>
</div>
</TabPane>
<TabPane tab="直播课" key="LIVE">
<div className="live-list">
<div>
<Row type="flex" justify="space-between" align="top">
<div>
<span style={{ lineHeight: "32px" }}>课程名称:</span>
<Search
// value={courseName}
style={{ width: "calc(100% - 75px)" }}
placeholder="搜索课程名称"
// onChange={(e) => {
// this.handleChangLiveFilter(
// "courseName",
// e.target.value
// );
// }}
onSearch={(value) => {
this.handleChangLiveFilter("courseName", value);
}}
enterButton={
<span className="icon iconfont">&#xe832;</span>
}
/>
</div>
<div style={{ width: "50%" }}>
<span className="shelf-status">课程分类:</span>
<Select
// value={courseType}
style={{ width: "calc(100% - 75px)" }}
placeholder="请选择课程类型"
allowClear={true}
onChange={(value) => {
setCourseType(value);
}}
suffixIcon={
<span
className="icon iconfont"
style={{ fontSize: "12px", color: "#BFBFBF" }}
>
&#xe835;
</span>
}
>
<Option value="LIVE">直播课</Option>
<Option value="VOICE">视频课</Option>
<Option value="PICTURE">图文课</Option>
<Option value="knowledge">学习资料</Option>
</Select>
</div>
</Row>
</div>
<TableSelectedData
selectedNum={
selectVideo.length + selectLive.length + selectPicture.length
}
clearSelectedData={() => {
this.setState({
selectVideo: [],
selectLive: [],
selectPicture: [],
});
}}
/>
<Table
bordered
size="middle"
pagination={false}
columns={this.liveColumns()}
rowSelection={LiveSelection}
// loading={loading}
dataSource={liveDataSource}
style={{ maxHeight: 359, overflow: "scroll" }}
rowKey={(row) => row.liveCourseId}
/>
{liveTotalCount > 0 && (
<div className="box-footer">
<PageControl
current={liveQuery.current - 1}
pageSize={liveSize}
total={parseInt(liveTotalCount)}
toPage={(page) => {
const _query = { ...liveQuery, current: page + 1 };
this.setState(
{
liveQuery: _query,
},
() => {
this.handleFetchLiveList();
}
);
}}
onShowSizeChange={this.onShowLiveSizeChange}
/>
</div>
)}
</div>
</TabPane>
<TabPane tab="图文课" key="PICTURE">
<div className="live-list">
<div>
<Row type="flex" justify="space-between" align="top">
<div>
<span style={{ lineHeight: "32px" }}>课程名称:</span>
<Search
// value={courseName}
style={{ width: "calc(100% - 75px)" }}
placeholder="搜索课程名称"
// onChange={(e) => {
// this.handleChangLiveFilter(
// "courseName",
// e.target.value
// );
// }}
onSearch={(value) => {
this.handleChangPictureFilter("courseName", value);
}}
enterButton={
<span className="icon iconfont">&#xe832;</span>
}
/>
</div>
<div style={{ width: "50%" }}>
<span className="shelf-status">课程分类:</span>
<Select
// value={courseType}
style={{ width: "calc(100% - 75px)" }}
placeholder="请选择课程类型"
allowClear={true}
onChange={(value) => {
setCourseType(value);
}}
suffixIcon={
<span
className="icon iconfont"
style={{ fontSize: "12px", color: "#BFBFBF" }}
>
&#xe835;
</span>
}
>
<Option value="LIVE">直播课</Option>
<Option value="VOICE">视频课</Option>
<Option value="PICTURE">图文课</Option>
<Option value="knowledge">学习资料</Option>
</Select>
</div>
</Row>
</div>
<TableSelectedData
selectedNum={
selectVideo.length + selectLive.length + selectPicture.length
}
clearSelectedData={() => {
this.setState({
selectVideo: [],
selectLive: [],
selectPicture: [],
});
}}
/>
<Table
bordered
size="middle"
pagination={false}
columns={this.pictureColumns()}
rowSelection={PictureSelection}
// loading={loading}
dataSource={pictureDataSource}
style={{ maxHeight: 359, overflow: "scroll" }}
rowKey={(row) => row.id}
/>
{pictureTotalCount > 0 && (
<div className="box-footer">
<PageControl
current={pictureQuery.current - 1}
pageSize={pictureSize}
total={parseInt(pictureTotalCount)}
toPage={(page) => {
const _query = { ...pictureQuery, current: page + 1 };
this.setState(
{
pictureQuery: _query,
},
() => {
this.handleFetchPictureList();
}
);
}}
onShowSizeChange={this.onShowPictureSizeChange}
/>
</div>
)}
</div>
</TabPane>
</Tabs>
</Modal>
);
}
}
export default AddCourse;
/*
* @Description:
* @Author: zangsuyun
* @Date: 2021-03-13 14:38:49
* @LastEditors: zangsuyun
* @LastEditTime: 2021-03-16 15:20:51
* @Copyright: © 2020 杭州杰竞科技有限公司 版权所有
*/
import React from "react";
import { Table, Modal, message, Dropdown, Button, Switch, Tooltip } from "antd";
import { Route, withRouter } from "react-router-dom";
import { PageControl } from "@/components";
import "./LiveList.less";
import TableSelectedData from "@/components/TableSelectedData";
import CourseService from "@/domains/course-domain/CourseService";
import User from "@/common/js/user";
import _ from "underscore";
const { confirm } = Modal;
const courseStateShow = {
UN_START: {
code: 1,
title: "待开课",
color: "#FFB714",
},
STARTING: {
code: 2,
title: "上课中",
color: "#238FFF",
},
FINISH: {
code: 3,
title: "已完成",
color: "#3BBDAA",
},
EXPIRED: {
code: 4,
title: "未成功开课",
color: "#999",
},
};
class LiveList extends React.Component {
constructor(props) {
super(props);
this.state = {
columns: [],
courseList: [], // 直播课列表
selectedRowKeys: [],
query: {
current: 1,
size: 10,
},
total: 0,
};
}
// static getDerivedStateFromProps(props, state) {
// //在getDerivedStateFromProps里不能使用this
// console.log(props);
// return props;
// }
componentDidUpdate(prevProps, prevState) {
//必须写在if里面并且重新进行一次this.props !== prevProps的判断
if (
this.props.courseName !== prevProps.courseName ||
this.props.courseType !== prevProps.courseType
) {
this.handleFetchLiveList(this.props);
}
}
componentWillMount() {
this.handleFetchLiveList(this.state.query);
this.parseColumns();
}
// 获取直播课列表
handleFetchLiveList = (_query) => {
const { query } = this.state;
const params = {
...query,
..._query,
storeId: User.getStoreId(),
};
this.setState({ query: params });
CourseService.getLiveCloudCoursePage(params).then((res) => {
const {
result: { records = [], total },
} = res;
this.setState({
total,
courseList: records,
});
});
};
parseColumns = () => {
let columns;
columns = [
{
title: (
<span>
<span>课程信息</span>
<Tooltip
title={<div>已加入该分类的课程不支持重复选择,因此不显示。</div>}
>
<i
className="icon iconfont"
style={{
marginLeft: "5px",
cursor: "pointer",
color: "#bfbfbf",
fontSize: "14px",
}}
>
&#xe61d;
</i>
</Tooltip>
</span>
),
width: 371,
key: "course",
dataIndex: "courseName",
render: (val, record) => {
let hasCover = false;
return (
<div className="record__item">
{record.courseMediaVOS.map((item, index) => {
if (item.contentType === "COVER") {
hasCover = true;
return <img className="course-cover" src={item.mediaUrl} />;
}
})}
{!hasCover && (
<img
className="course-cover"
src={"https://image.xiaomaiketang.com/xm/YNfi45JwFA.png"}
/>
)}
<div>
{record.courseName.length > 17 ? (
<Tooltip title={record.courseName}>
<div className="course-name">{record.courseName}</div>
</Tooltip>
) : (
<div className="course-name">{record.courseName}</div>
)}
<div>
<span
className="course-status"
style={{
color: courseStateShow[record.courseState].color,
border: `1px solid ${
courseStateShow[record.courseState].color
}`,
}}
>
{courseStateShow[record.courseState].title}
</span>
</div>
</div>
</div>
);
},
},
{
title: "上课时间",
// width: "10%",
key: "couseCatalog",
dataIndex: "couseCatalog",
render: (val, item) => {
return (
<span className="course-time">
{formatDate("YYYY-MM-DD", parseInt(item.startTime))} <br></br>
{formatDate("H:i", parseInt(item.startTime))}~
{formatDate("H:i", parseInt(item.endTime))}
</span>
);
},
},
{
title: "课程分类",
// width: "10%",
key: "couseCatalog",
dataIndex: "couseCatalog",
render: (val, item) => {
return <div className="categoryName">{item.categoryName}</div>;
},
},
];
this.setState({ columns });
};
onShowSizeChange = (current, size) => {
if (current == size) {
return;
}
let _query = this.state.query;
_query.size = size;
this.handleFetchLiveList(_query);
};
selectVideoList = (record, selected) => {
let { selectedRowKeys } = this.state;
let _list = [];
if (
selected ||
!_.find(
selectedRowKeys,
(item) => item.liveCourseId == record.liveCourseId
)
) {
_list = _.uniq(
selectedRowKeys.concat([record]),
false,
(item) => item.liveCourseId
);
} else {
_list = _.reject(
selectedRowKeys,
(item) => item.liveCourseId === record.liveCourseId
);
}
this.setState({ selectedRowKeys: _list });
};
render() {
const {
columns,
total,
query,
courseList,
loading,
selectedRowKeys,
} = this.state;
const { current, size } = query;
const rowSelection = {
selectedRowKeys: _.pluck(selectedRowKeys, "liveCourseId"),
onSelect: this.selectVideoList,
onSelectAll: (selected, _selectedRows, changeRows) => {
let _list = [];
if (selected) {
_list = _.uniq(
selectedRowKeys.concat(changeRows),
false,
(item) => item.liveCourseId
);
} else {
_list = _.reject(selectedRowKeys, (item) =>
_.find(
changeRows,
(data) => data.liveCourseId === item.liveCourseId
)
);
}
this.setState({ selectedRowKeys: _list });
},
};
return (
<div className="live-list">
<TableSelectedData
selectedNum={selectedRowKeys.length}
clearSelectedData={() => {
this.setState({
selectedRowKeys: [],
});
}}
/>
<Table
bordered
size="middle"
pagination={false}
columns={columns}
rowSelection={rowSelection}
loading={loading}
dataSource={courseList}
rowKey={(row) => row.liveCourseId}
/>
{total > 0 && (
<div className="box-footer">
<PageControl
current={current - 1}
pageSize={size}
total={parseInt(total)}
toPage={(page) => {
const _query = { ...query, current: page + 1 };
this.handleFetchLiveList(_query);
}}
onShowSizeChange={this.onShowSizeChange}
/>
</div>
)}
</div>
);
}
}
export default withRouter(LiveList);
.live-list {
.record__item {
display: flex;
align-items: center;
.course-cover {
min-width: 107px;
max-width: 107px;
height: 60px;
border-radius: 6px;
margin-right: 8px;
}
.course-name {
font-size: 14px;
font-weight: 400;
color: #333333;
font-family: PingFangSC-Regular, PingFang SC;
line-height: 20px;
max-width: 244px;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
}
.course-time {
font-size: 12px;
font-weight: 400;
color: #666666;
line-height: 20px;
}
.course-status {
font-size: 12px;
line-height: 17px;
display: inline-block;
border-radius: 2px;
padding: 0 8px;
}
.teacher-assistant {
display: flex;
.teacher {
font-size: 12px;
color: #666666;
max-width: 96px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
display: inline-block;
padding-top: 2px;
}
.assistant {
font-size: 12px;
color: #666666;
max-width: 96px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
display: inline-block;
padding-top: 2px;
}
.split {
margin: 0 4px;
color: #bfbfbf;
display: inline-blcok;
}
}
}
.categoryName {
font-size: 14px;
color: #666666;
line-height: 20px;
}
.courseware {
font-size: 14px;
color: #5289fa;
line-height: 20px;
text-align: right;
cursor: pointer;
}
.quota-icon {
color: #5289fa;
cursor: pointer;
}
.operate {
display: flex;
align-items: center;
flex-wrap: wrap;
.operate__item {
color: #5289fa;
cursor: pointer;
&.split {
margin: 0 8px;
color: #bfbfbf;
}
}
}
.operate-text {
color: #5289fa;
cursor: pointer;
}
.course-start-end {
margin-left: 16px;
width: 78px;
height: 20px;
border-radius: 2px;
border: 1px solid rgba(204, 204, 204, 1);
display: flex;
align-items: center;
cursor: pointer;
white-space: nowrap;
.start-icon {
color: #3296fa;
font-size: 12px;
transform: scale(0.8);
margin: 0 5px;
}
.end-icon {
color: #00d700;
font-size: 12px;
transform: scale(0.8);
margin: 0 5px;
}
.start-end-text {
font-size: 12px;
}
}
}
.add-course-modal {
.ant-tabs-top > .ant-tabs-nav::before {
border-bottom: 0px;
}
.ant-tabs-nav-list {
margin: 0 auto;
}
.ant-tabs-tab.ant-tabs-tab-active .ant-tabs-tab-btn {
font-weight: normal;
border-bottom: 0px;
}
.ant-tabs-nav .ant-tabs-tab {
padding: 6px 12px !important;
margin: 0;
border: 1px solid #e8e8e8;
font-size: 14px !important;
color: #999;
&:nth-child(1) {
border-radius: 4px 0px 0px 4px;
}
&:nth-child(3) {
border-radius: 0px 4px 4px 0px;
}
}
.ant-tabs-nav .ant-tabs-tab-active {
border: 1px solid #ffb714;
color: #ffb714;
}
.ant-tabs-top .ant-tabs-ink-bar-animated:after {
height: 0;
}
.ant-modal-content tr > td{
padding:12px 8px !important;
}
}
/*
* @Description:
* @Author: zangsuyun
* @Date: 2021-03-13 11:48:24
* @LastEditors: zangsuyun
* @LastEditTime: 2021-03-16 15:35:47
* @Copyright: © 2020 杭州杰竞科技有限公司 版权所有
*/
import React from "react";
import { Table, Modal, message, Tooltip, Switch, Dropdown } from "antd";
import { PageControl } from "@/components";
import _ from "underscore";
import { LIVE_SHARE_MAP } from "@/common/constants/academic/cloudClass";
import { appId, shareUrl, LIVE_SHARE } from "@/domains/course-domain/constants";
import TableSelectedData from "@/components/TableSelectedData";
import "./LiveList.less";
import CourseService from "@/domains/course-domain/CourseService";
import User from "@/common/js/user";
const ENV = process.env.DEPLOY_ENV || "dev";
class VideoList extends React.Component {
constructor(props) {
super(props);
this.state = {
id: "", // 视频课ID
studentIds: [],
selectedRowKeys: [],
query: {
size: 10,
current: 1,
storeId: User.getStoreId(),
},
dataSource: [], // 视频课列表
totalCount: 0, // 视频课数据总条数
};
}
// static getDerivedStateFromProps(props, state) {
// //在getDerivedStateFromProps里不能使用this
// console.log(props);
// return props;
// }
componentDidUpdate(prevProps, prevState) {
//必须写在if里面并且重新进行一次this.props !== prevProps的判断
if (
((this.props.courseName || this.props.courseType) &&
this.props.courseName !== prevProps.courseName) ||
this.props.courseType !== prevProps.courseType
) {
this.handleFetchScheduleList(this.props);
}
}
componentWillMount() {
// 获取视频课列表
this.handleFetchScheduleList();
}
// 获取视频课列表
handleFetchScheduleList = (_query = {}) => {
const query = {
...this.state.query,
..._query,
};
// 更新请求参数
this.setState({ query });
CourseService.videoSchedulePage(query).then((res) => {
const { result = {} } = res || {};
const { records = [], total = 0 } = result;
this.setState({
dataSource: records,
totalCount: Number(total),
});
});
};
dealTimeDuration = (time) => {
const diff = Math.floor(time % 3600);
let hours = Math.floor(time / 3600);
let mins = Math.floor(diff / 60);
let seconds = Math.floor(time % 60);
hours = hours < 10 ? "0" + hours : hours;
mins = mins < 10 ? "0" + mins : mins;
seconds = seconds < 10 ? "0" + seconds : seconds;
return hours + ":" + mins + ":" + seconds;
};
// 请求表头
parseColumns = () => {
const columns = [
{
title: (
<span>
<span>课程信息</span>
<Tooltip
title={
<div>
已加入该分类的课程不支持重复选择,因此不显示。
</div>
}
>
<i
className="icon iconfont"
style={{
marginLeft: "5px",
cursor: "pointer",
color: "#bfbfbf",
fontSize: "14px",
}}
>
&#xe61d;
</i>
</Tooltip>
</span>
),
key: "scheduleName",
dataIndex: "scheduleName",
width: 371,
render: (val, record) => {
const { coverUrl, scheduleVideoUrl } = record;
return (
<div className="record__item">
{/* 上传了封面的话就用上传的封面, 没有的话就取视频的第一帧 */}
<img
className="course-cover"
src={
coverUrl ||
`${scheduleVideoUrl}?x-oss-process=video/snapshot,t_0,m_fast`
}
/>
{record.courseName.length > 25 ? (
<Tooltip title={record.courseName}>
<div className="course-name">{record.courseName}</div>
</Tooltip>
) : (
<div className="course-name">{record.courseName}</div>
)}
</div>
);
},
},
{
title: "课程时长",
key: "videoDuration",
dataIndex: "videoDuration",
render: (text, item) => {
return <span>{text ? this.dealTimeDuration(text) : "-"}</span>;
},
},
{
title: "课程分类",
key: "categoryName",
dataIndex: "categoryName",
render: (val, record) => {
return (
<div className="record__item">
{record.categoryOneName}
{record.categoryTwoName ? `-${record.categoryTwoName}` : ""}
</div>
);
},
},
];
return columns;
};
selectLiveList = (record, selected) => {
let { selectedRowKeys } = this.state;
let _list = [];
if (selected || !_.find(selectedRowKeys, (item) => item.id == record.id)) {
_list = _.uniq(
selectedRowKeys.concat([record]),
false,
(item) => item.id
);
} else {
_list = _.reject(selectedRowKeys, (item) => item.id === record.id);
}
this.setState({ selectedRowKeys: _list });
};
render() {
const { dataSource = [], totalCount, query, selectedRowKeys } = this.state;
const { current, size } = query;
const rowSelection = {
selectedRowKeys: _.pluck(selectedRowKeys, "id"),
onSelect: this.selectLiveList,
onSelectAll: (selected, _selectedRows, changeRows) => {
let _list = [];
if (selected) {
_list = _.uniq(
selectedRowKeys.concat(changeRows),
false,
(item) => item.id
);
} else {
_list = _.reject(selectedRowKeys, (item) =>
_.find(changeRows, (data) => data.id === item.id)
);
}
this.setState({ selectedRowKeys: _list });
},
};
return (
<div className="live-list">
<TableSelectedData
selectedNum={selectedRowKeys.length}
clearSelectedData={() => {
this.setState({
selectedRowKeys: [],
});
}}
/>
<Table
rowKey={(record) => record.id}
dataSource={dataSource}
columns={this.parseColumns()}
size="middle"
rowSelection={rowSelection}
pagination={false}
bordered
className="video-list-table"
/>
<div className="box-footer">
{totalCount > 0 && (
<PageControl
current={current - 1}
pageSize={size}
total={totalCount}
toPage={(page) => {
const _query = { ...query, current: page + 1 };
this.handleFetchScheduleList(_query);
}}
/>
)}
</div>
</div>
);
}
}
export default VideoList;
/* /*
* @Author: zhangleyuan * @Author: zhangleyuan
* @Date: 2020-11-27 15:06:31 * @Date: 2020-11-27 15:06:31
* @LastEditors: zhangleyuan * @LastEditors: zangsuyun
* @LastEditTime: 2021-03-09 14:22:10 * @LastEditTime: 2021-03-22 13:55:24
* @Description: 描述一下 * @Description: 描述一下
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/ */
......
/* /*
* @Author: 吴文洁 * @Author: 吴文洁
* @Date: 2020-04-29 10:26:32 * @Date: 2020-04-29 10:26:32
* @LastEditors: zhangleyuan * @LastEditors: zangsuyun
* @LastEditTime: 2021-03-02 15:56:22 * @LastEditTime: 2021-03-22 13:55:36
* @Description: 内容线路由配置 * @Description: 内容线路由配置
*/ */
import Home from '@/modules/home/Home'; import Home from '@/modules/home/Home';
...@@ -24,6 +24,7 @@ import PlanPage from '@/modules/plan-manage/PlanPage'; ...@@ -24,6 +24,7 @@ import PlanPage from '@/modules/plan-manage/PlanPage';
import AddPlanPage from '@/modules/plan-manage/AddPlan'; import AddPlanPage from '@/modules/plan-manage/AddPlan';
import LearningDataPage from '@/modules/plan-manage/LearningData'; import LearningDataPage from '@/modules/plan-manage/LearningData';
import StoreInfoPage from '@/modules/store-manage/StoreInfo'; import StoreInfoPage from '@/modules/store-manage/StoreInfo';
import KnowledgeBase from '@/modules/knowledge-base';
const mainRoutes = [ const mainRoutes = [
{ {
...@@ -77,6 +78,12 @@ const mainRoutes = [ ...@@ -77,6 +78,12 @@ const mainRoutes = [
name: '创建视频课' name: '创建视频课'
}, },
{ {
path: '/knowledge-base',
// component:ResourceDisk,
component:KnowledgeBase,
name: '知识库'
},
{
path: '/resource-disk', path: '/resource-disk',
component:ResourceDisk, component:ResourceDisk,
name: '资料云盘' name: '资料云盘'
......
/* /*
* @Author: zhangleyuan * @Description:
* @Date: 2021-01-19 11:27:56 * @Author: zangsuyun
* @LastEditors: zhangleyuan * @Date: 2021-03-04 12:56:04
* @LastEditTime: 2021-03-02 15:18:12 * @LastEditors: zangsuyun
* @Description: 描述一下 * @LastEditTime: 2021-03-25 12:31:18
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @Copyright: © 2020 杭州杰竞科技有限公司 版权所有
*/ */
export const menuList: any = [ export const menuList: any = [
{ {
...@@ -31,6 +31,12 @@ export const menuList: any = [ ...@@ -31,6 +31,12 @@ export const menuList: any = [
] ]
}, },
{ {
groupName: "知识库",
groupCode: "CloudDisk",
icon: '&#xe827;',
link: '/knowledge-base'
},
{
groupName: "资料云盘", groupName: "资料云盘",
groupCode: "CloudDisk", groupCode: "CloudDisk",
icon: '&#xe83b;', icon: '&#xe83b;',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment