Commit 732761b3 by yuananting

Merge branch 'master' into feature/yuananting/20210327/test-paper

parents bb146a01 b6a08b23
...@@ -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",
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
"babel-plugin-jsx-control-statements": "^4.1.0", "babel-plugin-jsx-control-statements": "^4.1.0",
"babel-plugin-named-asset-import": "^0.3.6", "babel-plugin-named-asset-import": "^0.3.6",
"babel-preset-react-app": "^9.1.2", "babel-preset-react-app": "^9.1.2",
"bizcharts": "^4.1.7", "bizcharts": "^3.3.0",
"camelcase": "^5.3.1", "camelcase": "^5.3.1",
"case-sensitive-paths-webpack-plugin": "2.3.0", "case-sensitive-paths-webpack-plugin": "2.3.0",
"classnames": "^2.2.6", "classnames": "^2.2.6",
......
@font-face { @font-face {
font-family: 'iconfont'; /* project id 2223403 */ font-family: 'iconfont'; /* project id 2223403 */
src: url('//at.alicdn.com/t/font_2223403_droqalespbg.eot'); src: url('//at.alicdn.com/t/font_2223403_vzf1rkr5ya.eot');
src: url('//at.alicdn.com/t/font_2223403_droqalespbg.eot?#iefix') format('embedded-opentype'), src: url('//at.alicdn.com/t/font_2223403_vzf1rkr5ya.eot?#iefix') format('embedded-opentype'),
url('//at.alicdn.com/t/font_2223403_droqalespbg.woff2') format('woff2'), url('//at.alicdn.com/t/font_2223403_vzf1rkr5ya.woff2') format('woff2'),
url('//at.alicdn.com/t/font_2223403_droqalespbg.woff') format('woff'), url('//at.alicdn.com/t/font_2223403_vzf1rkr5ya.woff') format('woff'),
url('//at.alicdn.com/t/font_2223403_droqalespbg.ttf') format('truetype'), url('//at.alicdn.com/t/font_2223403_vzf1rkr5ya.ttf') format('truetype'),
url('//at.alicdn.com/t/font_2223403_droqalespbg.svg#iconfont') format('svg'); url('//at.alicdn.com/t/font_2223403_vzf1rkr5ya.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;
...@@ -659,7 +659,7 @@ td.ant-table-column-sort{ ...@@ -659,7 +659,7 @@ td.ant-table-column-sort{
} }
&:focus, &:focus,
&:active{ &:active{
color:#C6C6C6 !important; color:#666 !important;
border:1px solid #C6C6C6 !important; border:1px solid #C6C6C6 !important;
} }
} }
......
/*
* @Author: wufan
* @Date: 2021-03-26 15:40:49
* @LastEditors: wufan
* @LastEditTime: 2021-03-26 16:27:52
* @Description: 阿里云埋点
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
window.WEBTRACING = (eventKey, eventName, content) => {
if (!window.logger) {
return
}
const { xmState } = window.ctx;
const {storeList = []} = xmState;
const {id:storeId, storeUserId, storeName, storeType} = storeList[0] || {};
logger.push("platform", "pc");
logger.push("event", eventKey);
logger.push("eventName", eventName);
logger.push("device", navigator.userAgent);
logger.push("storeId", storeId);
logger.push("storeName", storeName);
logger.push("storeType", storeType);
logger.push("storeUserId", storeUserId);
logger.push('env', process.env.DEPLOY_ENV || 'local'); // 哪个环境的埋点
const _content = Object.assign({}, content, {
店铺名称: storeName,
店铺类型: storeType,
storeId,
storeUserId,
});
logger.push("content", JSON.stringify(_content));
// 记录日志
logger.logger();
}
/* /*
* @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 杭州杰竞科技有限公司 版权所有
*/ */
...@@ -88,3 +88,9 @@ export function videoScheduleBasePage(params: object) { ...@@ -88,3 +88,9 @@ 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);
} }
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-30 09:51:00
* @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);
}
// 分页云盘资料查看记录
queryPageKnowledgeFolderWatchInfo = (params: object) => {
return Service.Hades("public/hades/queryPageKnowledgeFolderWatchInfo", params);
}
// 资料观看记录导出
exportFolderLearnSync = (params: object) => {
return Service.Hades("public/knowledge/exportFolderLearnSync", params);
}
// 直播观看记录导出
exportLiveLearnSync = (params: object) => {
return Service.Hades("public/knowledge/exportLiveLearnSync", params);
}
//图文课观看记录导出
exportPicLearnSync = (params: object) => {
return Service.Hades("public/knowledge/exportPicLearnSync", params);
}
// 视频课观看记录导出
exportVideoLearnSync = (params: object) => {
return Service.Hades("public/knowledge/exportVideoLearnSync", 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-31 18:26:22 * @LastEditTime: 2021-04-15 21:42:47
* @LastEditors: yuananting * @LastEditors: yuananting
* @Description: * @Description:
* @FilePath: /wheat-web-demo/src/domains/basic-domain/constants.ts * @FilePath: /wheat-web-demo/src/domains/basic-domain/constants.ts
......
/* /*
* @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: yuananting * @LastEditors: zangsuyun
* @LastEditTime: 2021-03-24 19:34:13 * @LastEditTime: 2021-04-02 14:58:57
* @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_vzf1rkr5ya.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: yuananting * @LastEditors: zangsuyun
* @LastEditTime: 2021-03-24 19:34:26 * @LastEditTime: 2021-04-02 14:59:11
* @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_vzf1rkr5ya.css">
<!-- <!--
Notice the use of %PUBLIC_URL% in the tags above. Notice the use of %PUBLIC_URL% in the tags above.
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
<script type="text/javascript" src="https://image.xiaomaiketang.com/xm/lrz.all.bundle.js"></script> <script type="text/javascript" src="https://image.xiaomaiketang.com/xm/lrz.all.bundle.js"></script>
<script type="text/javascript" src="https://image.xiaomaiketang.com/xm/PhotoClip.js"></script> <script type="text/javascript" src="https://image.xiaomaiketang.com/xm/PhotoClip.js"></script>
<script type="text/javascript" charset="utf-8" src="//g.alicdn.com/sd/ncpc/nc.js?t=2015052012"></script> <script type="text/javascript" charset="utf-8" src="//g.alicdn.com/sd/ncpc/nc.js?t=2015052012"></script>
<script type="text/javascript" src="https://xiaomai-js.oss-cn-hangzhou.aliyuncs.com/loghub-xm-0.0.1-beta.js"></script>
</head> </head>
<body> <body>
<noscript>You need to enable JavaScript to run this app.</noscript> <noscript>You need to enable JavaScript to run this app.</noscript>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: 吴文洁 * @Author: 吴文洁
* @Date: 2020-04-27 20:35:34 * @Date: 2020-04-27 20:35:34
* @LastEditors: wufan * @LastEditors: wufan
* @LastEditTime: 2020-12-23 19:38:35 * @LastEditTime: 2021-03-26 16:14:09
* @Description: * @Description:
*/ */
...@@ -18,6 +18,7 @@ import 'antd/dist/antd.less'; ...@@ -18,6 +18,7 @@ import 'antd/dist/antd.less';
import 'video-react/dist/video-react.css'; import 'video-react/dist/video-react.css';
import '@/common/less/index.less'; import '@/common/less/index.less';
import '@/core/function'; import '@/core/function';
import '@/core/xmTD';
import User from '@/common/js/user'; import User from '@/common/js/user';
import Service from "@/common/js/service"; import Service from "@/common/js/service";
......
/* /*
* @Author: 吴文洁 * @Author: 吴文洁
* @Date: 2020-07-15 17:29:12 * @Date: 2020-07-15 17:29:12
* @Last Modified by: 吴文洁 * @Last Modified by: chenshu
* @Last Modified time: 2020-07-15 18:16:05 * @Last Modified time: 2021-03-29 16:19:49
* @Description: 新建/编辑直播课-基本信息 * @Description: 新建/编辑直播课-基本信息
*/ */
...@@ -241,7 +241,7 @@ class AddLiveBasic extends React.Component { ...@@ -241,7 +241,7 @@ class AddLiveBasic extends React.Component {
className={`default-btn ${isDefaultCover ? 'disabled' : ''}`} className={`default-btn ${isDefaultCover ? 'disabled' : ''}`}
onClick={this.handleResetCoverUrl} onClick={this.handleResetCoverUrl}
>使用默认图</span> >使用默认图</span>
<div className="tips">建议尺寸1280*720像素,图片支持jpg、jpeg、png格式。</div> <div className="tips">建议尺寸1280*720px,图片支持jpg、jpeg、png格式。</div>
</div> </div>
</div> </div>
</div> </div>
......
...@@ -17,13 +17,13 @@ ...@@ -17,13 +17,13 @@
} }
.editor-box { .editor-box {
height: 100%; height: 100%;
width: 100%;
} }
.w-e-toolbar { .w-e-toolbar {
background-color: #fff !important; background-color: #fff !important;
border: none !important; border: none !important;
border-bottom: 1px solid #E8E8E8 !important; border-bottom: 1px solid #E8E8E8 !important;
max-width: 700px;
} }
.w-e-text-container { .w-e-text-container {
......
...@@ -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}
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: 吴文洁 * @Author: 吴文洁
* @Date: 2020-08-05 10:07:47 * @Date: 2020-08-05 10:07:47
* @LastEditors: zhangleyuan * @LastEditors: zhangleyuan
* @LastEditTime: 2021-03-04 10:26:07 * @LastEditTime: 2021-03-29 14:08:47
* @Description: 图文课新增/编辑页 * @Description: 图文课新增/编辑页
* @Copyright: 杭州杰竞科技有限公司 版权所有 * @Copyright: 杭州杰竞科技有限公司 版权所有
*/ */
...@@ -206,11 +206,15 @@ class AddGraphicsCourse extends React.Component { ...@@ -206,11 +206,15 @@ class AddGraphicsCourse extends React.Component {
cancelText: '留在本页', cancelText: '留在本页',
icon: <span className="icon iconfont default-confirm-icon">&#xe6f4;</span>, icon: <span className="icon iconfont default-confirm-icon">&#xe6f4;</span>,
onOk: () => { onOk: () => {
RCHistory.goBack(); window.RCHistory.push({
pathname: `/graphics-course`,
});
} }
}); });
}else{ }else{
RCHistory.goBack(); window.RCHistory.push({
pathname: `/graphics-course`,
});
} }
} }
...@@ -452,7 +456,9 @@ class AddGraphicsCourse extends React.Component { ...@@ -452,7 +456,9 @@ class AddGraphicsCourse extends React.Component {
Service.Hades('public/hades/createMediaCourse', commonParams).then((res) => { Service.Hades('public/hades/createMediaCourse', commonParams).then((res) => {
if (!res) return; if (!res) return;
message.success("新建成功"); message.success("新建成功");
window.RCHistory.goBack(); window.RCHistory.push({
pathname: `/graphics-course`,
});
}) })
} else { } else {
const editParams = { const editParams = {
...@@ -462,7 +468,9 @@ class AddGraphicsCourse extends React.Component { ...@@ -462,7 +468,9 @@ class AddGraphicsCourse extends React.Component {
Service.Hades('public/hades/editMediaCourse', editParams).then((res) => { Service.Hades('public/hades/editMediaCourse', editParams).then((res) => {
if (!res) return; if (!res) return;
message.success("保存成功"); message.success("保存成功");
window.RCHistory.goBack(); window.RCHistory.push({
pathname: `/graphics-course`,
});
}); });
} }
} }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: 吴文洁 * @Author: 吴文洁
* @Date: 2020-08-05 10:12:45 * @Date: 2020-08-05 10:12:45
* @LastEditors: zhangleyuan * @LastEditors: zhangleyuan
* @LastEditTime: 2021-02-01 16:34:11 * @LastEditTime: 2021-03-27 16:24:47
* @Description: 视频课-列表模块 * @Description: 视频课-列表模块
* @Copyright: 杭州杰竞科技有限公司 版权所有 * @Copyright: 杭州杰竞科技有限公司 版权所有
*/ */
...@@ -33,7 +33,9 @@ class GraphicsCourseList extends React.Component { ...@@ -33,7 +33,9 @@ class GraphicsCourseList extends React.Component {
super(props); super(props);
this.state = { this.state = {
id: '', // 视频课ID id: '', // 视频课ID
studentIds:[] studentIds:[],
RelatedPlanModalVisible:false,
selectPlanList:{}
} }
} }
...@@ -61,6 +63,17 @@ class GraphicsCourseList extends React.Component { ...@@ -61,6 +63,17 @@ class GraphicsCourseList extends React.Component {
this.setState({ watchDataModal }); this.setState({ watchDataModal });
} }
handlePlanName = (planArray)=>{
let planStr = "";
planArray.map((item,index)=>{
if(index < planArray.length-1){
planStr = planStr + item.planName + '、';
}else{
planStr = planStr + item.planName
}
})
return planStr
}
// 请求表头 // 请求表头
parseColumns = () => { parseColumns = () => {
const columns = [ const columns = [
...@@ -91,7 +104,7 @@ class GraphicsCourseList extends React.Component { ...@@ -91,7 +104,7 @@ class GraphicsCourseList extends React.Component {
title: '课程分类', title: '课程分类',
key: 'categoryName', key: 'categoryName',
dataIndex: 'categoryName', dataIndex: 'categoryName',
width: '20%', width: 120,
render: (val, record) => { render: (val, record) => {
return ( return (
<div className="record__item"> <div className="record__item">
...@@ -104,7 +117,7 @@ class GraphicsCourseList extends React.Component { ...@@ -104,7 +117,7 @@ class GraphicsCourseList extends React.Component {
title: '创建人', title: '创建人',
key: 'createName', key: 'createName',
dataIndex: 'createName', dataIndex: 'createName',
width: '10%', width: 100,
render: (val) => { render: (val) => {
return ( return (
<div> <div>
...@@ -126,7 +139,7 @@ class GraphicsCourseList extends React.Component { ...@@ -126,7 +139,7 @@ class GraphicsCourseList extends React.Component {
<span>店铺展示</span> <span>店铺展示</span>
<Tooltip title={<div>开启后,用户可在店铺内查看到此课程。若课程“未成功开课”,则系统会自动“关闭”店铺展示。<br/>关闭后,店铺内不再展示此课程,但用户仍可通过分享的海报/链接查看此课程。</div>}><i className="icon iconfont" style={{ marginLeft: '5px',cursor:'pointer',color:'#bfbfbf',fontSize:'14px'}}>&#xe61d;</i></Tooltip> <Tooltip title={<div>开启后,用户可在店铺内查看到此课程。若课程“未成功开课”,则系统会自动“关闭”店铺展示。<br/>关闭后,店铺内不再展示此课程,但用户仍可通过分享的海报/链接查看此课程。</div>}><i className="icon iconfont" style={{ marginLeft: '5px',cursor:'pointer',color:'#bfbfbf',fontSize:'14px'}}>&#xe61d;</i></Tooltip>
</span>, </span>,
width: '12%', width: 120,
dataIndex: "courseware", dataIndex: "courseware",
render: (val, item, index) => { render: (val, item, index) => {
return ( return (
...@@ -166,6 +179,28 @@ class GraphicsCourseList extends React.Component { ...@@ -166,6 +179,28 @@ class GraphicsCourseList extends React.Component {
} }
}, },
{ {
title: '关联项',
width: 200,
key: "planList",
dataIndex: "planList",
render: (val, record) => {
return (
<div className="related-task">
{ record.relatedPlanList ?
<Tooltip title={this.handlePlanName(record.relatedPlanList)} placement="top" arrowPointAtCenter>
{ record.relatedPlanList.map((item,index)=>{
return <span>{item.planName} { (index < record.relatedPlanList.length-1)&&(<span></span>)} </span>
})
}
</Tooltip>
:
<span></span>
}
</div>
)
}
},
{
title: '操作', title: '操作',
key: 'operate', key: 'operate',
dataIndex: 'operate', dataIndex: 'operate',
...@@ -236,7 +271,7 @@ class GraphicsCourseList extends React.Component { ...@@ -236,7 +271,7 @@ class GraphicsCourseList extends React.Component {
renderMoreOperate = (item) => { renderMoreOperate = (item) => {
return ( return (
<div className="live-course-more-menu"> <div className="live-course-more-menu">
{/* {(User.getUserRole() === "CloudManager" || User.getUserRole() === "StoreManager") && {(User.getUserRole() === "CloudManager" || User.getUserRole() === "StoreManager") &&
<div <div
className="operate__item" className="operate__item"
key="plan" key="plan"
...@@ -244,7 +279,7 @@ class GraphicsCourseList extends React.Component { ...@@ -244,7 +279,7 @@ class GraphicsCourseList extends React.Component {
this.handleRelatedModalShow(item); this.handleRelatedModalShow(item);
}} }}
>关联培训计划</div> >关联培训计划</div>
} */} }
<div <div
className="operate__item" className="operate__item"
key="edit" key="edit"
...@@ -362,7 +397,37 @@ class GraphicsCourseList extends React.Component { ...@@ -362,7 +397,37 @@ class GraphicsCourseList extends React.Component {
}; };
this.props.onChange(_query); this.props.onChange(_query);
} }
handleRelatedModalShow = (item)=>{
const selectPlanList = {};
if(item.relatedPlanList){
item.relatedPlanList.map((item,index)=>{
selectPlanList[item.planId] = {}
selectPlanList[item.planId].planId = item.planId;
selectPlanList[item.planId].taskBaseVOList = [{taskId:item.taskId}];
return item
})
}
this.setState({
RelatedPlanModalVisible:true,
selectCourseId:item.id,
selectPlanList:selectPlanList
})
}
closeRelatedPlanModalVisible = ()=>{
this.setState({
RelatedPlanModalVisible:false
})
}
onChangeSelectPlanList = (selectPlanList)=>{
this.setState({
selectPlanList:selectPlanList
})
}
onConfirmSelectPlanList = ()=>{
this.setState({
RelatedPlanModalVisible:false
},()=>{this.props.onChange();})
}
render() { render() {
const { RelatedPlanModalVisible, selectCourseId, selectPlanList } = this.state; const { RelatedPlanModalVisible, selectCourseId, selectPlanList } = this.state;
const { dataSource = [], totalCount, query } = this.props; const { dataSource = [], totalCount, query } = this.props;
...@@ -402,6 +467,16 @@ class GraphicsCourseList extends React.Component { ...@@ -402,6 +467,16 @@ class GraphicsCourseList extends React.Component {
onConfirm={this.onConfirmSelectPlanList} onConfirm={this.onConfirmSelectPlanList}
/> />
} }
{ RelatedPlanModalVisible &&
<RelatedPlanModal
onClose={this.closeRelatedPlanModalVisible}
visible={RelatedPlanModalVisible}
selectCourseId={selectCourseId}
selectPlanList={selectPlanList}
onChange={this.onChangeSelectPlanList}
onConfirm={this.onConfirmSelectPlanList}
/>
}
{ this.state.shareLiveModal } { this.state.shareLiveModal }
{ this.state.watchDataModal } { this.state.watchDataModal }
</div> </div>
......
import React from 'react'; import React from 'react';
import { Select, Tooltip } from 'antd'; import { Select, Tooltip } from 'antd';
import { Chart } from '@antv/g2'; import DataSet from "@antv/data-set";
import { Chart as G2Chart } from '@antv/g2';
import {
G2,
Chart,
Geom,
Axis,
Tooltip as G2Tooltip,
Coord,
Label,
Legend,
View,
Guide,
Shape,
Facet,
Util
} from "bizcharts";
import moment from 'moment' import moment from 'moment'
import Service from "@/common/js/service"; import Service from "@/common/js/service";
import User from '@/common/js/user'; import User from '@/common/js/user';
...@@ -21,8 +37,11 @@ class Home extends React.Component { ...@@ -21,8 +37,11 @@ class Home extends React.Component {
liveCourseNum: 0, liveCourseNum: 0,
totalCustomerNum: 0, totalCustomerNum: 0,
videoCourseNum: 0, videoCourseNum: 0,
pictureCourseNum: 0,
timeRange: '7', timeRange: '7',
studyTimeRange: '7', studyTimeRange: '7',
completeNum: 0,
unfinishedNum: 0,
} }
this._chart = null; this._chart = null;
} }
...@@ -31,6 +50,15 @@ class Home extends React.Component { ...@@ -31,6 +50,15 @@ class Home extends React.Component {
this.getPanelInfo(); this.getPanelInfo();
this.getStudyInfo(); this.getStudyInfo();
this.getHotCourse(); this.getHotCourse();
this.getTrainingInfo();
}
getTrainingInfo() {
Service.Hades('public/hades/planOverview', { storeId: User.getStoreId() }).then((res) => {
if (res.success) {
this.setState(res.result)
}
});
} }
getHotCourse() { getHotCourse() {
...@@ -74,10 +102,12 @@ class Home extends React.Component { ...@@ -74,10 +102,12 @@ class Home extends React.Component {
incLiveCourseNum: res.result.incLiveCourseNum, incLiveCourseNum: res.result.incLiveCourseNum,
incVideoCourseNum: res.result.incVideoCourseNum, incVideoCourseNum: res.result.incVideoCourseNum,
incPictureCourseNum: res.result.incPictureCourseNum, incPictureCourseNum: res.result.incPictureCourseNum,
incTrainingPlanNum: res.result.incTrainingPlanNum,
liveCourseNum: res.result.liveCourseNum, liveCourseNum: res.result.liveCourseNum,
totalCustomerNum: res.result.totalCustomerNum, totalCustomerNum: res.result.totalCustomerNum,
videoCourseNum: res.result.videoCourseNum, videoCourseNum: res.result.videoCourseNum,
pictureCourseNum: res.result.pictureCourseNum, pictureCourseNum: res.result.pictureCourseNum,
trainingPlanNum: res.result.trainingPlanNum,
}) })
} }
}) })
...@@ -99,7 +129,7 @@ class Home extends React.Component { ...@@ -99,7 +129,7 @@ class Home extends React.Component {
createChart = (data) => { createChart = (data) => {
if (!this._chart) { if (!this._chart) {
this._chart = new Chart({ this._chart = new G2Chart({
container: 'chart-id', container: 'chart-id',
forceFit: true, forceFit: true,
height: 290, height: 290,
...@@ -196,7 +226,39 @@ class Home extends React.Component { ...@@ -196,7 +226,39 @@ class Home extends React.Component {
timeRange, timeRange,
scheduleType, scheduleType,
studyTimeRange, studyTimeRange,
trainingPlanNum,
incTrainingPlanNum,
unfinishedNum,
completeNum,
planCustomerNum,
} = this.state; } = this.state;
const data = [
{
item: '已完成培训',
count: completeNum,
}, {
item: '未完成培训',
count: unfinishedNum,
}
];
const { DataView } = DataSet;
const { Html } = Guide;
const sum = data[0].count + data[1].count;
const dv = new DataView();
sum && dv.source(data).transform({
type: "percent",
field: "count",
dimension: "item",
as: "percent"
});
const cols = {
percent: {
formatter: val => {
val = val * 100 + "%";
return val;
}
}
};
return ( return (
<div className="home-page"> <div className="home-page">
<div className="home-title">数据概况</div> <div className="home-title">数据概况</div>
...@@ -273,13 +335,13 @@ class Home extends React.Component { ...@@ -273,13 +335,13 @@ class Home extends React.Component {
<img className="header-icon" src="https://image.xiaomaiketang.com/xm/jZf3GNY5tY.png" /> <img className="header-icon" src="https://image.xiaomaiketang.com/xm/jZf3GNY5tY.png" />
<span className="header-word">培训计划总数 (个)</span> <span className="header-word">培训计划总数 (个)</span>
</div> </div>
<div className="data-number">0</div> <div className="data-number">{trainingPlanNum}</div>
<div className="data-footer"> <div className="data-footer">
<span className="footer-word">本月新增</span> <span className="footer-word">本月新增</span>
{false && {incTrainingPlanNum > 0 &&
<span className="icon iconfont">&#xe635;</span> <span className="icon iconfont">&#xe635;</span>
} }
<span className="footer-number">0</span> <span className="footer-number">{incTrainingPlanNum}</span>
</div> </div>
</div> </div>
...@@ -363,24 +425,78 @@ class Home extends React.Component { ...@@ -363,24 +425,78 @@ class Home extends React.Component {
</Tooltip> </Tooltip>
<span className="tip">(本月)</span> <span className="tip">(本月)</span>
</div> </div>
<div className="circle-box"> {(unfinishedNum || completeNum) ?
<div
className="left-graph-container"
id="mountNode"
style={{ width: '100%', marginLeft: '-20%', marginTop: -30 }}
ref={e => e && (this.width = e.clientWidth)}
>
{this.width && <div>
<Chart
height={400}
width={this.width}
data={dv}
scale={cols}
padding={20}
>
<Coord type={"theta"} radius={0.75} innerRadius={0.6} />
<Axis name="percent" />
<G2Tooltip
showTitle={false}
itemTpl="<li><span style=&quot;background-color:{color};&quot; class=&quot;g2-tooltip-marker&quot;></span>{name}: {value}</li>"
/>
<Guide>
<Html
position={['50%', "50%"]}
html={`<div style="color:#8c8c8c;font-size:14px;text-align: center;width: ${this.width}px;"><span style="color:#333;font-size:20px">${planCustomerNum}人</span><br>新增培训人数</div>`}
alignX="middle"
alignY="middle"
/>
</Guide>
<Geom
type="intervalStack"
position="percent"
color={['item', ['#FDB513', '#5289FA']]}
tooltip={[
"item*percent",
(item, percent) => {
percent = Math.round(percent * 100) + "%";
return {
name: item,
value: percent,
};
}
]}
style={{
lineWidth: 1,
stroke: "#fff"
}}
>
</Geom>
</Chart>
</div>
}
</div>
: <div className="circle-box">
<div className="big-circle"> <div className="big-circle">
<div className="small-circle"> <div className="small-circle">
<div className="tip-box"> <div className="tip-box">
<div style={{ color: '#333', fontSize: '20px', marginBottom: 4 }}>0</div> <div style={{ color: '#333', fontSize: '20px', marginBottom: 4 }}>{planCustomerNum}</div>
<div style={{ color: '#999' }}>新增培训人数</div> <div style={{ color: '#999' }}>新增培训人数</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
}
<div className="circle-tip unfinished"> <div className="circle-tip unfinished">
<div className="spot"></div> <div className="spot"></div>
<div className="number">0</div> <div className="number">{unfinishedNum}</div>
<div className="word">未完成培训</div> <div className="word">未完成培训</div>
</div> </div>
<div className="circle-tip finished"> <div className="circle-tip finished">
<div className="spot"></div> <div className="spot"></div>
<div className="number">0</div> <div className="number">{completeNum}</div>
<div className="word">完成培训</div> <div className="word">完成培训</div>
</div> </div>
</div> </div>
...@@ -411,6 +527,10 @@ class Home extends React.Component { ...@@ -411,6 +527,10 @@ class Home extends React.Component {
<div>人均学习时长(分钟)</div> <div>人均学习时长(分钟)</div>
</div> </div>
<div id="chart-id"></div> <div id="chart-id"></div>
<div className="chart-bottom-tip">
<div className="tip-item" style={{ marginRight: 100 }}><span className="student-dot"></span>学习人数</div>
<div className="tip-item"><span className="time-dot"></span>人均学习时长</div>
</div>
</div> </div>
</div> </div>
) )
......
.home-page { .home-page {
padding: 0 16px 16px; padding: 0 16px 16px;
min-width: 1100px; min-width: 1100px;
.g2-tooltip-marker {
border-radius: 50% !important;
}
.home-title { .home-title {
height: 44px; height: 44px;
line-height: 44px; line-height: 44px;
...@@ -282,10 +285,11 @@ ...@@ -282,10 +285,11 @@
} }
.study-chart { .study-chart {
width: 100%; width: 100%;
height: 396px; height: 432px;
background: #fff; background: #fff;
padding: 16px; padding: 16px;
margin-top: 16px; margin-top: 16px;
padding-bottom: 32px;
.study-title { .study-title {
font-size: 16px; font-size: 16px;
color: #333; color: #333;
...@@ -315,6 +319,29 @@ ...@@ -315,6 +319,29 @@
} }
} }
} }
.chart-bottom-tip {
display: flex;
justify-content: center;
.tip-item {
display: flex;
align-items: center;
color: #666;
.student-dot {
background: #5289FA;
height: 8px;
width: 8px;
border-radius: 50%;
margin-right: 8px;
}
.time-dot {
background: #FEB613;
height: 8px;
width: 8px;
border-radius: 50%;
margin-right: 8px;
}
}
}
} }
} }
......
/*
* @Description:
* @Author: zangsuyun
* @Date: 2021-03-22 18:24:53
* @LastEditors: zangsuyun
* @LastEditTime: 2021-03-27 11:54:42
* @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-04-08 11:29:12
* @Copyright: © 2020 杭州杰竞科技有限公司 版权所有
*/
import React, { Component } from "react";
import { Input, Button, Tree } from "antd";
import "./Classification.less";
import User from "@/common/js/user";
import KnowledgeAPI 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();
}
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 = {
categoryName,
storeId: User.getStoreId(),
withCount: true,
};
KnowledgeAPI.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 === "未分类" ? (
<img
style={{
width: "24px",
height: "24px",
opacity:
!value || (value && item.categoryName.indexOf(value) > -1)
? 1
: 0.5,
}}
src="https://image.xiaomaiketang.com/xm/defaultCategory.png"
alt=""
/>
) : (
<img
style={{
width: "24px",
height: "24px",
opacity:
!value || (value && item.categoryName.indexOf(value) > -1)
? 1
: 0.5,
}}
src="https://image.xiaomaiketang.com/xm/hasCategory.png"
alt=""
/>
);
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);
}}
enterButton={<span className="icon iconfont">&#xe832;</span>}
/>
<div className="sider-btn">
<Button
onClick={() => {
window.RCHistory.push({
pathname: "/question-category-manage?from=knowledge",
});
}}
>
分类管理
</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;
}
}
}
}
.knowledge-base-filter {
position: relative;
.search-condition {
width: calc(100% - 80px);
display: flex;
align-items: center;
flex-wrap: wrap;
&__item {
width: 33%;
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-04-08 11:51:42
* @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, // 课程名称
type: null,
};
class KnowledgeBaseFilter extends React.Component {
constructor(props) {
super(props);
this.state = {
query: { ...DEFAULT_QUERY }, // 使用扩展运算符,避免浅拷贝
};
}
// 改变搜索条件
handleChangeQuery = (field, value, flag = true) => {
this.setState(
{
query: {
...this.state.query,
[field]: value,
current: 1,
},
},
() => {
this.props.onChange(this.state.query,flag);
}
);
};
// 重置搜索条件
handleReset = () => {
this.setState(
{
query: DEFAULT_QUERY,
},
() => {
this.props.onChange(this.state.query);
}
);
};
render() {
const {
query: { name, type },
} = 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={name}
placeholder="搜索课程名称"
onChange={(e) => {
this.handleChangeQuery("name", e.target.value, false);
}}
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={type}
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 key={item} 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;
.knowledge-base-list {
margin-top: 12px;
.knowledge-list-table{
tbody {
tr{
&:nth-child(even){
background: transparent !important;
td{
background:#FFF !important;
}
}
&:nth-child(odd){
background: #FAFAFA !important;
td{
background: #FAFAFA !important;
}
}
&:hover{
td{
background:#F3f6fa !important;
}
}
}
}
}
.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-04-10 11:23:08
* @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 KnowledgeAPI 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.getStoreUserId(),
type: "FOLDER",
};
KnowledgeAPI.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"
selectTypeList={["JPG", "JPEG", "PNG",'DOC','PDF','EXCEL','application/msword','application/vnd.ms-powerpoint']} // DOC 包含 .pptx,.docx,.xls.XLSX,WORD:DOC
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 KnowledgeAPI from "@/data-source/knowledge/request-api";
import User from '@/common/js/user';
const liveTypeMap = {
USER: "普通用户",
ANCHOR: "讲师",
ADMIN: "管理员(助教)",
GUEST: "游客"
};
class PlaybackData extends React.Component {
constructor(props) {
super(props);
const id = getParameterByName("id"); // 课程ID
this.state = {
playbackData: [],
current: 1,
size: 10,
total: 0,
id: id,
storeId: User.getStoreId()
}
}
componentDidMount() {
this.fetchPlaybackList();
}
fetchPlaybackList = (page = 1) => {
const { size, id } = this.state
const params = {
id,
current: page,
size
}
KnowledgeAPI.queryPageKnowledgeReplayRecordPage(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, id } = this.state;
KnowledgeAPI.exportLiveLearnSync({
knowledgeId: id,
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" id={id} type={type}/>
)}
</div>
</div>
);
}
}
export default withRouter(WatchData);
/*
* @Description:
* @Author: zangsuyun
* @Date: 2021-03-16 10:18:31
* @LastEditors: zangsuyun
* @LastEditTime: 2021-03-30 10:17:59
* @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, type } = this.props;
const params = {
...query,
size,
id,
storeId: User.getStoreId(),
};
type === "FOLDER"
? KnowledgeAPI.queryPageKnowledgeFolderWatchInfo(params).then((res) => {
const { result = {} } = res;
const { records = [], total = 0 } = result;
this.setState({
dataSource: records,
totalCount: Number(total),
});
})
: 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;
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: "progress",
dataIndex: "progress",
render: (val) => {
return val === 100 ? "已完成" : <span>{val + "%"}</span>;
},
});
}
return columns;
};
handleExportV5 = () => {
const { query } = this.state;
const { id, type } = this.props;
const params = {
...query,
knowledgeId: id,
storeId: User.getStoreId(),
};
switch (type) {
case "FOLDER":
KnowledgeAPI.exportFolderLearnSync(params).then((res) => {
if (res.result) {
window.open(res.result);
} else {
message.error("导出失败");
}
});
break;
case "VOICE":
KnowledgeAPI.exportVideoLearnSync(params).then((res) => {
if (res.result) {
window.open(res.result);
} else {
message.error("导出失败");
}
});
break;
case "PICTURE":
KnowledgeAPI.exportPicLearnSync(params).then((res) => {
if (res.result) {
window.open(res.result);
} else {
message.error("导出失败");
}
});
break;
default:
break;
}
};
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-04-10 16:39:30
* @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 = {},flag = true) => {
const query = {
...this.state.query,
..._query,
};
// 更新请求参数
this.setState({ query });
flag && 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: "rgb(238, 238, 238)", width: 0.5, margin: "1px 16px 1px 2px" }}
></div>
<div className="right" style={{ width: "calc(100% - 285px)" }}>
<KnowledgeBaseFilter onChange={this.handleFetchScheduleList} />
{/* 操作模块 */}
{categoryId != 0 && <KnowledgeBaseOpt
onChange={this.handleFetchScheduleList}
updateCategoryTree={this.updateCategoryTree}
categoryId={categoryId}
/>}
{/* 知识库列表模块 */}
<KnowledgeBaseList
query={query}
categoryId={categoryId}
dataSource={dataSource}
totalCount={totalCount}
onChange={this.handleFetchScheduleList}
updateCategoryTree={this.updateCategoryTree}
/>
</div>
</div>
</div>
);
}
}
/*
* @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,
};
}
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: #666666;
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;
flex:none !important
}
.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: 0.5px 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-04-01 11:58:46
* @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, // 视频课数据总条数
};
}
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 杭州杰竞科技有限公司 版权所有
*/ */
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: zhangleyuan * @Author: zhangleyuan
* @Date: 2021-02-20 16:13:39 * @Date: 2021-02-20 16:13:39
* @LastEditors: zhangleyuan * @LastEditors: zhangleyuan
* @LastEditTime: 2021-03-16 11:27:06 * @LastEditTime: 2021-03-30 18:07:11
* @Description: 描述一下 * @Description: 描述一下
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/ */
...@@ -28,6 +28,7 @@ const defaultBasicData = { ...@@ -28,6 +28,7 @@ const defaultBasicData = {
operateType:'All_Operate', operateType:'All_Operate',
percentCompleteLive:80, percentCompleteLive:80,
percentCompleteVideo:80, percentCompleteVideo:80,
percentCompletePicture:100
} }
const defaultTaskList = []; const defaultTaskList = [];
...@@ -64,6 +65,7 @@ function AddPlan() { ...@@ -64,6 +65,7 @@ function AddPlan() {
operateIds, operateIds,
percentCompleteLive, percentCompleteLive,
percentCompleteVideo, percentCompleteVideo,
percentCompletePicture,
courseMediaVOS, courseMediaVOS,
trainingTaskList trainingTaskList
} = res.result; } = res.result;
...@@ -102,7 +104,8 @@ function AddPlan() { ...@@ -102,7 +104,8 @@ function AddPlan() {
instro, instro,
operateType, operateType,
percentCompleteLive, percentCompleteLive,
percentCompleteVideo percentCompleteVideo,
percentCompletePicture
}) })
setHasGetDetail(true); setHasGetDetail(true);
}) })
...@@ -119,7 +122,7 @@ function AddPlan() { ...@@ -119,7 +122,7 @@ function AddPlan() {
} }
function submitInfo(){ function submitInfo(){
const {planName,enableState,selectOperatorList,instro,operateType,percentCompleteLive,percentCompleteVideo,coverId,coverUrl} = basicData; const {planName,enableState,selectOperatorList,instro,operateType,percentCompleteLive,percentCompleteVideo,percentCompletePicture,coverId,coverUrl} = basicData;
let input = /^[\s]*$/; let input = /^[\s]*$/;
if(!planName || input.test(planName)){ if(!planName || input.test(planName)){
message.warning('请输入的培训计划名称'); message.warning('请输入的培训计划名称');
...@@ -137,6 +140,10 @@ function AddPlan() { ...@@ -137,6 +140,10 @@ function AddPlan() {
message.warning('请输入完成标准'); message.warning('请输入完成标准');
return; return;
} }
if(!percentCompletePicture && percentCompletePicture !==0 ){
message.warning('请输入完成标准');
return;
}
if(taskList.length === 0){ if(taskList.length === 0){
message.warning('请输入培训计划内容'); message.warning('请输入培训计划内容');
return; return;
...@@ -183,6 +190,7 @@ function AddPlan() { ...@@ -183,6 +190,7 @@ function AddPlan() {
operateType, operateType,
percentCompleteLive, percentCompleteLive,
percentCompleteVideo, percentCompleteVideo,
percentCompletePicture,
planName, planName,
scheduleMediaRequests, scheduleMediaRequests,
storeId:User.getStoreId(), storeId:User.getStoreId(),
......
...@@ -77,7 +77,7 @@ class LearningData extends React.Component { ...@@ -77,7 +77,7 @@ class LearningData extends React.Component {
<div className="plan-info"> <div className="plan-info">
<div className="plan-intro"> <div className="plan-intro">
<div className="plan-img-con"> <div className="plan-img-con">
<img src="https://image.xiaomaiketang.com/xm/YNfi45JwFA.png"/> <img src={coverUrl} />
</div> </div>
<div> <div>
<div className="plan-name"> <div className="plan-name">
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: zhangleyuan * @Author: zhangleyuan
* @Date: 2021-02-20 16:45:51 * @Date: 2021-02-20 16:45:51
* @LastEditors: zhangleyuan * @LastEditors: zhangleyuan
* @LastEditTime: 2021-03-15 17:01:47 * @LastEditTime: 2021-03-27 11:20:27
* @Description: 描述一下 * @Description: 描述一下
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/ */
...@@ -210,7 +210,7 @@ class BasicInfo extends React.Component{ ...@@ -210,7 +210,7 @@ class BasicInfo extends React.Component{
render(){ render(){
const { operatorModalVisible ,showSelectFileModal,visible,hasImgReady,cutImageBlob} = this.state; const { operatorModalVisible ,showSelectFileModal,visible,hasImgReady,cutImageBlob} = this.state;
const { data} = this.props; const { data} = this.props;
const { planName,coverUrl,instro,enableState,operateType,selectOperatorList,percentCompleteLive,percentCompleteVideo} = data; const { planName,coverUrl,instro,enableState,operateType,selectOperatorList,percentCompleteLive,percentCompleteVideo,percentCompletePicture} = data;
// 当前是否使用的是默认图片 // 当前是否使用的是默认图片
const isDefaultCover = coverUrl === defaultCover; const isDefaultCover = coverUrl === defaultCover;
return ( return (
...@@ -337,6 +337,19 @@ class BasicInfo extends React.Component{ ...@@ -337,6 +337,19 @@ class BasicInfo extends React.Component{
%,即视为"已完成"学习 %,即视为"已完成"学习
</span> </span>
</div> </div>
<div className="live-standard-info">
<span className="icon iconfont">&#xe601;</span>
<span className="instro">图文课单个课程,用户学习进度达到
<Input
width="40"
value={percentCompletePicture}
onChange={(e) => { this.props.onChange('percentCompletePicture', e.target.value.replace(/\D/g,'')) }}
onBlur={(e)=>this.percentCompleteBlur(e,'percentCompletePicture')}
className="input-box"
/>
%,即视为"已完成"学习
</span>
</div>
{/* <div className="video-standard-info"> {/* <div className="video-standard-info">
<span className="icon iconfont">&#xe864;</span> <span className="icon iconfont">&#xe864;</span>
<span>图文课单个课程,用户学习进度达到 <span>图文课单个课程,用户学习进度达到
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: zhangleyuan * @Author: zhangleyuan
* @Date: 2021-02-20 16:45:51 * @Date: 2021-02-20 16:45:51
* @LastEditors: zhangleyuan * @LastEditors: zhangleyuan
* @LastEditTime: 2021-03-16 11:36:36 * @LastEditTime: 2021-03-27 14:43:17
* @Description: 描述一下 * @Description: 描述一下
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/ */
...@@ -25,6 +25,9 @@ const CourseType = { ...@@ -25,6 +25,9 @@ const CourseType = {
}, },
RECORD : { RECORD : {
text:'录播课' text:'录播课'
},
PICTURE:{
text:'图文课'
} }
}; };
const courseStateShow = { const courseStateShow = {
...@@ -218,6 +221,7 @@ class TrainingTask extends React.Component { ...@@ -218,6 +221,7 @@ class TrainingTask extends React.Component {
}) })
} }
confirmSelectCourse = (selectList) =>{ confirmSelectCourse = (selectList) =>{
console.log("selectList",selectList);
const {selectedTaskIndex}= this.state; const {selectedTaskIndex}= this.state;
const { dataSource } = this.state const { dataSource } = this.state
const newData=[...dataSource]; const newData=[...dataSource];
......
...@@ -16,6 +16,9 @@ const CourseType = { ...@@ -16,6 +16,9 @@ const CourseType = {
}, },
RECORD : { RECORD : {
text:'录播课' text:'录播课'
},
PICTURE:{
text:'图文课'
} }
}; };
const courseStateShow = { const courseStateShow = {
......
...@@ -60,6 +60,29 @@ class FolderList extends React.Component { ...@@ -60,6 +60,29 @@ class FolderList extends React.Component {
} }
} }
// 埋点
handleDataDot = (folderFormat) => {
switch (folderFormat) {
case 'PDF':
window.WEBTRACING('resource_disk_file_preview_pdf', '资料云盘_点击预览_pdf');
break;
case 'WORD':
case 'DOCX':
case 'DOC':
window.WEBTRACING('resource_disk_file_preview_word', '资料云盘_点击预览_word');
break;
case 'EXCEL':
window.WEBTRACING('resource_disk_file_preview_excel', '资料云盘_点击预览_excel');
break;
case 'PPT':
case 'PPTX':
window.WEBTRACING('resource_disk_file_preview_ppt', '资料云盘_点击预览_ppt');
break;
default:
break;
}
}
// 预览文件 // 预览文件
handleScanFile = (folder) => { handleScanFile = (folder) => {
const { folderFormat, folderSize, ossUrl } = folder; const { folderFormat, folderSize, ossUrl } = folder;
...@@ -119,6 +142,9 @@ class FolderList extends React.Component { ...@@ -119,6 +142,9 @@ class FolderList extends React.Component {
this.setState({ scanFileModal }); this.setState({ scanFileModal });
break; break;
} }
// 预览文件埋点
this.handleDataDot(folderFormat);
} }
// 选择文件夹 // 选择文件夹
......
...@@ -73,6 +73,29 @@ class FolderList extends React.Component { ...@@ -73,6 +73,29 @@ class FolderList extends React.Component {
} }
} }
// 埋点
handleDataDot = (folderFormat) => {
switch (folderFormat) {
case 'PDF':
window.WEBTRACING('resource_disk_file_preview_pdf', '资料云盘_点击预览_pdf');
break;
case 'WORD':
case 'DOCX':
case 'DOC':
window.WEBTRACING('resource_disk_file_preview_word', '资料云盘_点击预览_word');
break;
case 'EXCEL':
window.WEBTRACING('resource_disk_file_preview_excel', '资料云盘_点击预览_excel');
break;
case 'PPT':
case 'PPTX':
window.WEBTRACING('resource_disk_file_preview_ppt', '资料云盘_点击预览_ppt');
break;
default:
break;
}
}
// 预览文件 // 预览文件
handleScanFile = (folder) => { handleScanFile = (folder) => {
const { folderFormat, folderSize, ossUrl } = folder; const { folderFormat, folderSize, ossUrl } = folder;
...@@ -132,6 +155,9 @@ class FolderList extends React.Component { ...@@ -132,6 +155,9 @@ class FolderList extends React.Component {
this.setState({ scanFileModal }); this.setState({ scanFileModal });
break; break;
} }
// 预览文件埋点
this.handleDataDot(folderFormat);
} }
// 选择文件夹 // 选择文件夹
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: 吴文洁 * @Author: 吴文洁
* @Date: 2019-07-10 10:30:49 * @Date: 2019-07-10 10:30:49
* @LastEditors: wufan * @LastEditors: wufan
* @LastEditTime: 2021-03-11 17:22:01 * @LastEditTime: 2021-03-26 16:13:48
* @Description: * @Description:
*/ */
import React, { useContext, useEffect, useState } from 'react'; import React, { useContext, useEffect, useState } from 'react';
...@@ -17,6 +17,7 @@ import BaseService from "@/domains/basic-domain/baseService"; ...@@ -17,6 +17,7 @@ import BaseService from "@/domains/basic-domain/baseService";
import { XMContext } from '@/store/context'; import { XMContext } from '@/store/context';
import { setStoreGroupPermission, setStorePermission, setStoreGroupList, setStoreList } from '@/store/actions/index'; import { setStoreGroupPermission, setStorePermission, setStoreGroupList, setStoreList } from '@/store/actions/index';
import Bus from '@/core/tbus'; import Bus from '@/core/tbus';
declare var window: any; declare var window: any;
const App: React.FC = (props: any) => { const App: React.FC = (props: any) => {
...@@ -29,9 +30,11 @@ const App: React.FC = (props: any) => { ...@@ -29,9 +30,11 @@ const App: React.FC = (props: any) => {
useEffect(() => { useEffect(() => {
getStoreAndUserInfo(); getStoreAndUserInfo();
// window.RCHistory.push({ if (window.location.hash === "#/") {
// pathname: `/switch-route`, window.RCHistory.replace({
// }) pathname: '/home',
})
}
}, []) }, [])
async function getStoreAndUserInfo() { async function getStoreAndUserInfo() {
......
...@@ -377,7 +377,7 @@ class StoreH5Decoration extends React.Component { ...@@ -377,7 +377,7 @@ class StoreH5Decoration extends React.Component {
<div className="banner-setting"> <div className="banner-setting">
<div className="title">banner设置</div> <div className="title">banner设置</div>
<div className="tip"> <div className="tip">
图片支持bmp、jpeg、jpg、png、gif格式,最大5M,最多可添加5张,拖动可排序。建议尺寸750x252像素 图片支持bmp、jpeg、jpg、png、gif格式,最大5M,最多可添加5张,拖动可排序。建议尺寸750*252px
</div> </div>
</div> </div>
<Button <Button
......
...@@ -375,7 +375,7 @@ class StoreWebDecoration extends React.Component { ...@@ -375,7 +375,7 @@ class StoreWebDecoration extends React.Component {
<div className="banner-setting"> <div className="banner-setting">
<div className="title">banner设置</div> <div className="title">banner设置</div>
<div className="tip"> <div className="tip">
图片支持bmp、jpeg、jpg、png、gif格式,最大5M,最多可添加5张,拖动可排序。建议尺寸1232*212像素 图片支持bmp、jpeg、jpg、png、gif格式,最大5M,最多可添加5张,拖动可排序。建议尺寸1232*212px
</div> </div>
</div> </div>
<Button <Button
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: yuananting * @Author: yuananting
* @Date: 2021-02-23 18:28:50 * @Date: 2021-02-23 18:28:50
* @LastEditors: yuananting * @LastEditors: yuananting
* @LastEditTime: 2021-04-07 10:09:18 * @LastEditTime: 2021-04-15 21:43:35
* @Description: 助学工具-课程分类 * @Description: 助学工具-课程分类
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/ */
......
...@@ -2,21 +2,21 @@ ...@@ -2,21 +2,21 @@
* @Author: 吴文洁 * @Author: 吴文洁
* @Date: 2020-04-29 10:26:32 * @Date: 2020-04-29 10:26:32
* @LastEditors: yuananting * @LastEditors: yuananting
* @LastEditTime: 2021-04-07 10:13:06 * @LastEditTime: 2021-04-15 21:45:42
* @Description: 内容线路由配置 * @Description: 内容线路由配置
*/ */
import Home from '@/modules/home/Home'; import Home from "@/modules/home/Home";
import EmployeesManagePage from '@/modules/store-manage/EmployeesManagePage'; import EmployeesManagePage from "@/modules/store-manage/EmployeesManagePage";
import personalInfoPage from '@/modules/personalInfo'; import personalInfoPage from "@/modules/personalInfo";
import UserManagePage from '@/modules/store-manage/UserManagePage'; import UserManagePage from "@/modules/store-manage/UserManagePage";
import StoreDecorationPage from '@/modules/store-manage/StoreDecorationPage'; import StoreDecorationPage from "@/modules/store-manage/StoreDecorationPage";
import CourseCatalogPage from '@/modules/store-manage/CourseCatalogPage'; import CourseCatalogPage from "@/modules/store-manage/CourseCatalogPage";
import LiveCoursePage from '@/modules/course-manage/LiveCoursePage'; import LiveCoursePage from "@/modules/course-manage/LiveCoursePage";
import AddLivePage from '@/modules/course-manage/AddLive' import AddLivePage from "@/modules/course-manage/AddLive";
import VideoCoursePage from '@/modules/course-manage/video-course' import VideoCoursePage from "@/modules/course-manage/video-course";
import GraphicsCoursePage from '@/modules/course-manage/graphics-course' import GraphicsCoursePage from "@/modules/course-manage/graphics-course";
import AddVideoCoursePage from '@/modules/course-manage/video-course/AddVideoCourse' import AddVideoCoursePage from "@/modules/course-manage/video-course/AddVideoCourse";
import AddGraphicsCoursePage from '@/modules/course-manage/graphics-course/AddGraphicsCourse' import AddGraphicsCoursePage from "@/modules/course-manage/graphics-course/AddGraphicsCourse";
// import DataList from '@/modules/course-manage/DataList/DataList'; // import DataList from '@/modules/course-manage/DataList/DataList';
// import ClassBook from '@/modules/resource-disk'; // import ClassBook from '@/modules/resource-disk';
import ResourceDisk from '@/modules/resource-disk'; import ResourceDisk from '@/modules/resource-disk';
...@@ -27,76 +27,81 @@ import LearningDataPage from '@/modules/plan-manage/LearningData'; ...@@ -27,76 +27,81 @@ import LearningDataPage from '@/modules/plan-manage/LearningData';
import StoreInfoPage from '@/modules/store-manage/StoreInfo'; import StoreInfoPage from '@/modules/store-manage/StoreInfo';
import CourseCategoryManage from '@/modules/teach-tool/components/CourseCategoryManage'; import CourseCategoryManage from '@/modules/teach-tool/components/CourseCategoryManage';
import QuestionManageIndex from '@/modules/teach-tool/question-manage/Index'; import QuestionManageIndex from '@/modules/teach-tool/question-manage/Index';
import OperateQuestion from "@/modules/teach-tool/question-manage/OperateQuestion";
import PaperManageIndex from '@/modules/teach-tool/paper-manage/Index'; import PaperManageIndex from '@/modules/teach-tool/paper-manage/Index';
import OperatePaper from "@/modules/teach-tool/paper-manage/OperatePaper";
import ExaminationManagerIndex from '@/modules/teach-tool/examination-manager/Index'; import ExaminationManagerIndex from '@/modules/teach-tool/examination-manager/Index';
import KnowledgeBase from "@/modules/knowledge-base/index";
const mainRoutes = [ const mainRoutes = [
{ {
path: '/home', path: "/home",
component: Home, component: Home,
name: '中心首页' name: "中心首页",
}, },
{ {
path: '/employees-manage', path: "/employees-manage",
component: EmployeesManagePage, component: EmployeesManagePage,
name: '员工管理' name: "员工管理",
}, },
{ {
path: '/personal-info', path: "/personal-info",
component: personalInfoPage, component: personalInfoPage,
name: '个人信息' name: "个人信息",
}, },
{ {
path: '/user-manage', path: "/user-manage",
component: UserManagePage, component: UserManagePage,
name: '用户管理' name: "用户管理",
}, },
{ {
path: '/store-decoration', path: "/store-decoration",
component: StoreDecorationPage, component: StoreDecorationPage,
name: '店铺装修' name: "店铺装修",
}, },
// {
// path: "/course-catalog",
// component: CourseCatalogPage,
// name: "课程分类",
// },
{ {
path: '/course-catalog', path: "/live-course",
component:CourseCatalogPage, component: LiveCoursePage,
name: '课程分类' name: "直播课",
}, },
{ {
path: '/live-course', path: "/video-course",
component:LiveCoursePage, component: VideoCoursePage,
name: '直播课' name: "视频课",
}, },
{ {
path: '/video-course', path: "/graphics-course",
component:VideoCoursePage, component: GraphicsCoursePage,
name: '视频课' name: "图文课",
}, },
{ {
path: '/graphics-course', path: "/create-live-course",
component: GraphicsCoursePage, component: AddLivePage,
name: '图文课' name: "创建直播课",
}, },
{ {
path: '/create-live-course', path: "/create-video-course",
component:AddLivePage, component: AddVideoCoursePage,
name: '创建直播课' name: "创建视频课",
}, },
{ {
path: '/create-video-course', path: "/knowledge-base",
component:AddVideoCoursePage, // component:ResourceDisk,
name: '创建视频课' component: KnowledgeBase,
name: "知识库",
}, },
{ {
path: '/create-graphics-course', path: "/create-graphics-course",
component:AddGraphicsCoursePage, component: AddGraphicsCoursePage,
name: '创建图文课' name: "创建图文课",
}, },
{ {
path: '/resource-disk', path: "/resource-disk",
component:ResourceDisk, component: ResourceDisk,
name: '资料云盘' name: "资料云盘",
}, },
{ {
path: '/question-manage-index', path: '/question-manage-index',
...@@ -119,31 +124,30 @@ const mainRoutes = [ ...@@ -119,31 +124,30 @@ const mainRoutes = [
name: '分类管理' name: '分类管理'
}, },
{ {
path: '/switch-route', path: "/switch-route",
component: SwitchRoute, component: SwitchRoute,
name: '登录后跳转承载页' name: "登录后跳转承载页",
}, },
{ {
path:'/plan', path: "/plan",
component: PlanPage, component: PlanPage,
name: '培训计划' name: "培训计划",
}, },
{ {
path: '/create-plan', path: "/create-plan",
component:AddPlanPage, component: AddPlanPage,
name: '创建视频课' name: "创建视频课",
}, },
{ {
path: '/store-info', path: "/store-info",
component:StoreInfoPage, component: StoreInfoPage,
name: '店铺信息' name: "店铺信息",
}, },
{ {
path: '/learning-data', path: "/learning-data",
component:LearningDataPage, component: LearningDataPage,
name: '学习数据' name: "学习数据",
} },
];
]
export default mainRoutes; export default mainRoutes;
...@@ -36,6 +36,12 @@ export const menuList: any = [ ...@@ -36,6 +36,12 @@ export const menuList: any = [
] ]
}, },
{ {
groupName: "知识库",
groupCode: "CloudKnowledge",
icon: '&#xe840;',
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