Commit e0eafc54 by guomingpang

docs:线下课重命名线下活动,资源云盘变更为素材库

parent 64195835
......@@ -19,7 +19,7 @@
/>
<meta
name="keywords"
content="小麦企学院,企业培训,员工培训,企业大学,企业内训,企业外训,培训计划,培训素材,企培,企训,资料云盘,培训课程,培训任务,直播课,线上课,图文课,线下课,知识库,作业,考试,排行榜,培训类别管理,定制培训计划,管理数据,学习数据,企学院,资料共享,培训数字化,数字化培训,培训工具,在线培训,线上培训,培训saas,培训管理,企业微信培训,对客培训,客户培训,直播培训,互联网培训,新员工培训,管理培训,管理者培训,工人培训,制造业培训,餐饮培训,服务业培训,零售培训,门店培训,工厂培训,车间培训,培训补贴,人事培训,财务培训,职场培训,企业学院平台,教育企业学院,教育企业平台,教育平台学院,企业学习,酷学院,小鹅通,企业学院,云学堂,时代光华,云课堂,魔学院,云大学,米知云,授课学堂"
content="小麦企学院,企业培训,员工培训,企业大学,企业内训,企业外训,培训计划,培训素材,企培,企训,素材库,培训课程,培训任务,直播课,线上课,图文课,线下活动,知识库,作业,考试,排行榜,培训类别管理,定制培训计划,管理数据,学习数据,企学院,资料共享,培训数字化,数字化培训,培训工具,在线培训,线上培训,培训saas,培训管理,企业微信培训,对客培训,客户培训,直播培训,互联网培训,新员工培训,管理培训,管理者培训,工人培训,制造业培训,餐饮培训,服务业培训,零售培训,门店培训,工厂培训,车间培训,培训补贴,人事培训,财务培训,职场培训,企业学院平台,教育企业学院,教育企业平台,教育平台学院,企业学习,酷学院,小鹅通,企业学院,云学堂,时代光华,云课堂,魔学院,云大学,米知云,授课学堂"
/>
<!-- <link rel="apple-touch-icon" href="../src/common/images/logo.png" /> -->
<link rel="shortcut icon" href="https://image.xiaomaiketang.com/xm/c4KiP2epBP.png" />
......@@ -62,6 +62,5 @@
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>
......@@ -101,12 +101,7 @@ class GraphicsCourseList extends React.Component {
dataIndex: 'categoryName',
width: 120,
render: (val, record) => {
return (
<div className='record__item'>
{record.categoryOneName}
{record.categoryTwoName ? `-${record.categoryTwoName}` : ''}
</div>
)
return <div className='record__item'>{record.categoryName}</div>
},
},
{
......
......@@ -6,66 +6,54 @@
* @LastEditTime: 2020-12-22 20:30:54
*/
import React from 'react'
import { Modal, Button, Table } from "antd";
import "./AccountChargeModal";
import { Modal, Button, Table } from 'antd'
import './AccountChargeModal'
const data = [
{ person: "上台人数1v1", price: "3元/人/小时" },
{ person: "上台人数1v2", price: "3元/人/小时" },
{ person: "上台人数1v3", price: "3元/人/小时" },
{ person: "上台人数1v4", price: "3元/人/小时" },
{ person: "上台人数1v5", price: "3元/人/小时" },
{ person: "上台人数1v6", price: "3元/人/小时" },
{ person: "上台人数1v7", price: "4元/人/小时" },
{ person: "上台人数1v8", price: "4元/人/小时" },
{ person: "上台人数1v9", price: "8元/人/小时" },
{ person: "上台人数1v10", price: "8元/人/小时" },
{ person: "上台人数1v11", price: "8元/人/小时" },
{ person: "上台人数1v12", price: "8元/人/小时" },
];
{ person: '上台人数1v1', price: '3元/人/小时' },
{ person: '上台人数1v2', price: '3元/人/小时' },
{ person: '上台人数1v3', price: '3元/人/小时' },
{ person: '上台人数1v4', price: '3元/人/小时' },
{ person: '上台人数1v5', price: '3元/人/小时' },
{ person: '上台人数1v6', price: '3元/人/小时' },
{ person: '上台人数1v7', price: '4元/人/小时' },
{ person: '上台人数1v8', price: '4元/人/小时' },
{ person: '上台人数1v9', price: '8元/人/小时' },
{ person: '上台人数1v10', price: '8元/人/小时' },
{ person: '上台人数1v11', price: '8元/人/小时' },
{ person: '上台人数1v12', price: '8元/人/小时' },
]
function ChargeExplainModal(props) {
return (
<Modal
title="计费说明"
title='计费说明'
visible={true}
className="charge-explain-modal"
className='charge-explain-modal'
width={880}
maskClosable={false}
closeIcon={<span className="icon iconfont modal-close-icon">&#xe6ef;</span>}
closeIcon={<span className='icon iconfont modal-close-icon'>&#xe6ef;</span>}
onCancel={() => {
props.close();
props.close()
}}
footer={[
<Button
type="primary"
type='primary'
onClick={() => {
props.close();
}}
>
props.close()
}}>
关闭
</Button>,
]}
>
]}>
<div>
<div className="explain-title">1)直播课时费</div>
<p className="main-explain-block">
每节课上课费用 = 上台人数单价 × 有效出勤学生和老师人数 × 排课时长
</p>
<div className='explain-title'>1)直播课时费</div>
<p className='main-explain-block'>每节课上课费用 = 上台人数单价 × 有效出勤学生和老师人数 × 排课时长</p>
<ul>
<li>
1. 上课老师、学生和助教在教室中的累计时长满10分钟即为有效出勤;
</li>
<li>
2.
排课时长指创建课节设置的课节时长,最小计费单位为0.5小时,不足0.5小时按0.5小时计算;
</li>
<li>
3.
上台人数单价:以排课时设定的上台人数上限为准,不同直播教室类型的课时单价不同。
</li>
<li>1. 上课老师、学生和助教在教室中的累计时长满10分钟即为有效出勤;</li>
<li>2. 排课时长指创建课节设置的课节时长,最小计费单位为0.5小时,不足0.5小时按0.5小时计算;</li>
<li>3. 上台人数单价:以排课时设定的上台人数上限为准,不同直播教室类型的课时单价不同。</li>
</ul>
<p className="main-explain-text" style={{marginTop: 16,marginBottom: 8}}>
<p className='main-explain-text' style={{ marginTop: 16, marginBottom: 8 }}>
温馨提醒:上台人数1vN,1为授课老师,N为同时与老师视频互动学生数;直播课时费将在老师下课后立即结算。
</p>
<table style={{ width: 333 }}>
......@@ -82,47 +70,43 @@ function ChargeExplainModal(props) {
<td>{item.person}</td>
<td>{item.price}</td>
</tr>
);
)
})}
</tbody>
</table>
<p className="main-explain-text">
<p className='main-explain-text'>
示例:王老师排了一节45分钟的课程,选择的直播教室类型为5人上台,安排了1位助教、12位学生。那么,排课时长45分钟记为1小时;全员累计在线时长≥10min,老师+助教+学生共计1+1+12=14人;课时单价3元/人/小时。所以,此节课的直播课时费=1x14x3=42元
</p>
<div className="explain-title mt16">2)录制费</div>
<p className="main-explain-block">录制费 = 录课单价 × 回放视频时长</p>
<div className='explain-title mt16'>2)录制费</div>
<p className='main-explain-block'>录制费 = 录课单价 × 回放视频时长</p>
<ul>
<li>1. 结算时间:从回放视频生成后立即结算</li>
<li> 2. 回放视频时长:0.5h起收,不足0.5h的按0.5h结算</li>
<li> 3. 单价:2元/小时</li>
</ul>
<p className="main-explain-text">
示例:生成了49分26秒的回放视频,不足1h按1h计算,总费用=1(h)*2元/h=2元
</p>
<div className="explain-title mt16">3)流量费</div>
<p className="main-explain-block">
观看回放视频流量费 = 流量单价 × 回放流量
</p>
<p className="main-explain-text">
<p className='main-explain-text'>示例:生成了49分26秒的回放视频,不足1h按1h计算,总费用=1(h)*2元/h=2元</p>
<div className='explain-title mt16'>3)流量费</div>
<p className='main-explain-block'>观看回放视频流量费 = 流量单价 × 回放流量</p>
<p className='main-explain-text'>
目前收费报价:0元(限时免费)
<br /> 若后续变更收费,将提前30日通告收费方式及价格标准
</p>
<div className="explain-title mt16">4)存储费</div>
<p className="main-explain-block">存储实际扣费 = 存储单价 × 存储文件大小</p>
<p className="main-explain-text">
<div className='explain-title mt16'>4)存储费</div>
<p className='main-explain-block'>存储实际扣费 = 存储单价 × 存储文件大小</p>
<p className='main-explain-text'>
目前收费报价:0元(限时免费)
<br />
若后续变更收费,将提前30日通告收费方式及价格标准
</p>
<div className="explain-title mt16">5)其他说明</div>
<div className="main-explain-text">
余额不足时将限制使用创建直播课、老师和学生进入直播间、老师和学生观看回放视频、在资料云盘或直播间上传文件等功能,请注意及时充值。(余额<300元时将发送短信提醒,请注意查看。)
<div className='explain-title mt16'>5)其他说明</div>
<div className='main-explain-text'>
余额不足时将限制使用创建直播课、老师和学生进入直播间、老师和学生观看回放视频、在素材库或直播间上传文件等功能,请注意及时充值。(余额<300元时将发送短信提醒,请注意查看。)
</div>
</div>
</Modal>
);
)
}
export default ChargeExplainModal;
export default ChargeExplainModal
......@@ -3,7 +3,7 @@
* @Date: 2020-08-05 10:07:47
* @LastEditors: yuananting
* @LastEditTime: 2021-07-22 18:29:55
* @Description: 线下新增/编辑页
* @Description: 线下活动新增/编辑页
* @Copyright: 杭州杰竞科技有限公司 版权所有
*/
......@@ -44,14 +44,14 @@ class AddOfflineCourse extends React.Component {
const pageType = window.getParameterByName('type')
this.state = {
courseId, // 线下ID,编辑的时候从URL上带过来
courseId, // 线下活动ID,编辑的时候从URL上带过来
pageType, // 页面类型: add->新建 edit->编辑
imageFile: null, // 需要被截取的图片
courseName: null, // 线下名称
courseName: null, // 线下活动名称
courseMedia: '',
introduce: '',
coverId: null, // 线下封面的recourceId
coverUrl: defaultCoverUrl, // 线下封面
coverUrl: defaultCoverUrl, // 线下活动封面
studentList: [], // 上课学员列表
diskList: [], // 机构可见磁盘目录
selectedFileList: [], // 已经从资料云盘中勾选的文件
......@@ -149,7 +149,7 @@ class AddOfflineCourse extends React.Component {
})
}
// 获取线下详情
// 获取线下活动详情
handleFetchScheudleDetail = (courseId) => {
return Service.Hades('public/hades/getOfflineCourseDetail', {
courseId,
......@@ -707,7 +707,7 @@ class AddOfflineCourse extends React.Component {
const isDefaultCover = coverUrl === defaultCoverUrl
return (
<div className='page add-offline-course-page'>
<Breadcrumbs navList={pageType === 'add' ? '新建线下课' : '编辑线下课'} goBack={this.handleGoBack} />
<Breadcrumbs navList={pageType === 'add' ? '新建线下活动' : '编辑线下活动'} goBack={this.handleGoBack} />
<div className='box'>
<div className='show-tips'>
......@@ -723,7 +723,7 @@ class AddOfflineCourse extends React.Component {
</span>
<Input
value={courseName}
placeholder='请输入线下的名称(40字以内)'
placeholder='请输入线下活动的名称(40字以内)'
maxLength={40}
style={{ width: 240 }}
onChange={(e) => {
......@@ -1075,7 +1075,7 @@ class AddOfflineCourse extends React.Component {
<div className='content'>
<Switch checked={whetherVisitorsJoin === 'NO' ? true : false} onChange={this.whetherVisitorsJoinChange} />
<div className='desc'>
{whetherVisitorsJoin === 'NO' ? '已开启,仅限绑定了手机号的学员报名线下课' : '已关闭,允许未绑定手机号的学员报名线下课'}
{whetherVisitorsJoin === 'NO' ? '已开启,仅限绑定了手机号的学员报名线下活动' : '已关闭,允许未绑定手机号的学员报名线下活动'}
</div>
</div>
</div>
......
......@@ -136,10 +136,10 @@ class OfflineCourseFilter extends React.Component {
<Row type='flex' justify='space-between' align='top'>
<div className='search-condition'>
<div className='search-condition__item'>
<span className='search-name'>线下名称:</span>
<span className='search-name'>线下活动名称:</span>
<Search
value={courseName}
placeholder='搜索线下名称'
placeholder='搜索线下活动名称'
onChange={(e) => {
this.handleChangeQuery('courseName', e.target.value)
}}
......
......@@ -6,77 +6,77 @@
* @Description: 线上课-列表模块
* @Copyright: 杭州杰竞科技有限公司 版权所有
*/
import Service from '@/common/js/service';
import User from '@/common/js/user';
import college from '@/common/lottie/college';
import { PageControl, XMTable } from '@/components';
import { LIVE_SHARE } from '@/domains/course-domain/constants';
import CourseService from '@/domains/course-domain/CourseService';
import ShareLiveModal from '@/modules/course-manage/modal/ShareLiveModal';
import OfflineCourseData from '@/modules/course-manage/offline-course/OfflineCourseData';
import { Dropdown, message, Modal, Switch, Tooltip } from 'antd';
import moment from 'moment';
import React from 'react';
import { find, reduce, last } from 'underscore';
import { Route, withRouter } from 'react-router-dom';
import ENUM from '../../../knowledge-base/ENUM.js';
import PreviewOfflineModal from '../modal/PreviewOfflineModal';
import QRCodeModal from '../modal/QRCodeModal';
import './OfflineCourseList.less';
import Service from '@/common/js/service'
import User from '@/common/js/user'
import college from '@/common/lottie/college'
import { PageControl, XMTable } from '@/components'
import { LIVE_SHARE } from '@/domains/course-domain/constants'
import CourseService from '@/domains/course-domain/CourseService'
import ShareLiveModal from '@/modules/course-manage/modal/ShareLiveModal'
import OfflineCourseData from '@/modules/course-manage/offline-course/OfflineCourseData'
import { Dropdown, message, Modal, Switch, Tooltip } from 'antd'
import moment from 'moment'
import React from 'react'
import { find, reduce, last } from 'underscore'
import { Route, withRouter } from 'react-router-dom'
import ENUM from '../../../knowledge-base/ENUM.js'
import PreviewOfflineModal from '../modal/PreviewOfflineModal'
import QRCodeModal from '../modal/QRCodeModal'
import './OfflineCourseList.less'
const defaultCoverUrl = 'https://image.xiaomaiketang.com/xm/pxbWKsYA87.png';
const defaultCoverUrl = 'https://image.xiaomaiketang.com/xm/pxbWKsYA87.png'
class OfflineCourseList extends React.Component {
constructor(props) {
super(props);
super(props)
this.state = {
id: '', // 线上课ID
studentIds: [],
};
}
}
componentDidMount() {
const videoCourseItem = localStorage.getItem('videoCourseItem');
const videoCourseItem = localStorage.getItem('videoCourseItem')
if (videoCourseItem) {
const _videoCourseItem = JSON.parse(videoCourseItem);
this.handleShowShareModal(_videoCourseItem, true);
const _videoCourseItem = JSON.parse(videoCourseItem)
this.handleShowShareModal(_videoCourseItem, true)
}
}
handlePlanName = (planArray) => {
let planStr = '';
let planStr = ''
planArray.forEach((item, index) => {
if (index < planArray.length - 1) {
planStr = planStr + item.planName + '、';
planStr = planStr + item.planName + '、'
} else {
planStr = planStr + item.planName;
planStr = planStr + item.planName
}
})
return planStr
}
});
return planStr;
};
// 请求表头
parseColumns = () => {
const columns = [
{
title: '线下',
title: '线下活动',
key: 'scheduleName',
dataIndex: 'scheduleName',
width: 321,
fixed: 'left',
render: (val, record) => {
const { courseMediaVOS, courseName, offlinePlace, calendarTime, startTime, endTime } = record;
const coverUrl = (find(courseMediaVOS, (data) => data.contentType === 'COVER') || {}).mediaUrl;
let isContinue = calendarTime.length > 1;
const { courseMediaVOS, courseName, offlinePlace, calendarTime, startTime, endTime } = record
const coverUrl = (find(courseMediaVOS, (data) => data.contentType === 'COVER') || {}).mediaUrl
let isContinue = calendarTime.length > 1
reduce(calendarTime, (a, b) => {
isContinue = isContinue && b - a === 86400000;
return b;
});
const lastTime = last(calendarTime);
isContinue = isContinue && b - a === 86400000
return b
})
const lastTime = last(calendarTime)
const time = `${
!isContinue
? calendarTime.map((item) => moment(item).format('MM-DD')).join('、')
: `${moment(calendarTime[0]).format('MM-DD')}~${moment(lastTime).format('MM-DD')}`
} ${moment(startTime).format('HH:mm')} ~ ${moment(endTime).format('HH:mm')}`;
} ${moment(startTime).format('HH:mm')} ~ ${moment(endTime).format('HH:mm')}`
return (
<div className='record__item'>
<img className='course-cover' src={coverUrl || defaultCoverUrl} alt='' />
......@@ -92,7 +92,7 @@ class OfflineCourseList extends React.Component {
</Tooltip>
</div>
</div>
);
)
},
},
{
......@@ -106,7 +106,7 @@ class OfflineCourseList extends React.Component {
<div style={{ width: 6, height: 6, borderRadius: '50%', background: ENUM.offlineStateShow[val].color, marginRight: 8 }}></div>
{ENUM.offlineStateShow[val].title}
</div>
);
)
},
},
{
......@@ -115,7 +115,7 @@ class OfflineCourseList extends React.Component {
dataIndex: 'categoryName',
width: 120,
render: (val, record) => {
return <div className='record__item'>{record.categorySonName}</div>;
return <div className='record__item'>{record.categoryName}</div>
},
},
{
......@@ -141,7 +141,7 @@ class OfflineCourseList extends React.Component {
render: (val, item, index) => {
return (
<Switch size='small' disabled={item.courseState === 'EXPIRED'} checked={item.shelfState === 'YES'} onChange={() => this.changeShelfState(item)} />
);
)
},
},
{
......@@ -150,7 +150,7 @@ class OfflineCourseList extends React.Component {
key: 'teacher',
dataIndex: 'teacher',
render: (val, item) => {
return <div>{item.teacherName}</div>;
return <div>{item.teacherName}</div>
},
},
{
......@@ -178,7 +178,7 @@ class OfflineCourseList extends React.Component {
</span>
)}
</div>
);
)
},
},
{
......@@ -188,7 +188,7 @@ class OfflineCourseList extends React.Component {
dataIndex: 'created',
sorter: true,
render: (val) => {
return <span style={{ whiteSpace: 'nowrap' }}>{window.formatDate('YYYY-MM-DD H:i', val)}</span>;
return <span style={{ whiteSpace: 'nowrap' }}>{window.formatDate('YYYY-MM-DD H:i', val)}</span>
},
},
{
......@@ -219,12 +219,12 @@ class OfflineCourseList extends React.Component {
</span>
</Dropdown>
</div>
);
)
},
},
];
return columns;
};
]
return columns
}
// 显示预览弹窗
handleShowPreviewModal = (courseId) => {
......@@ -234,12 +234,12 @@ class OfflineCourseList extends React.Component {
close={() => {
this.setState({
previewOfflineModal: null,
});
})
}}
/>
);
this.setState({ previewOfflineModal });
};
)
this.setState({ previewOfflineModal })
}
renderMoreOperate = (item) => {
return (
......@@ -249,7 +249,7 @@ class OfflineCourseList extends React.Component {
className='operate__item'
key='qrcode'
onClick={() => {
this.setState({ openQRCodeModal: true, qrcodeData: item });
this.setState({ openQRCodeModal: true, qrcodeData: item })
}}>
考勤二维码
</div>
......@@ -258,7 +258,7 @@ class OfflineCourseList extends React.Component {
className='operate__item'
key='preview'
onClick={() => {
this.handleShowPreviewModal(item.courseId);
this.handleShowPreviewModal(item.courseId)
}}>
预览
</div>
......@@ -268,7 +268,7 @@ class OfflineCourseList extends React.Component {
className='operate__item'
key='cancel'
onClick={() => {
this.handleDeleteOfflineCourse(item.courseId);
this.handleDeleteOfflineCourse(item.courseId)
}}>
取消课程
</div>
......@@ -278,7 +278,7 @@ class OfflineCourseList extends React.Component {
className='operate__item'
key='edit'
onClick={() => {
RCHistory.push(`/create-offline-course?type=edit&id=${item.courseId}`);
RCHistory.push(`/create-offline-course?type=edit&id=${item.courseId}`)
}}>
编辑
</div>
......@@ -289,37 +289,37 @@ class OfflineCourseList extends React.Component {
</div>
)}
</div>
);
};
)
}
//改变上架状态
changeShelfState = (item) => {
if (!window.ctx.xmState.storeUserPermissionList.includes('EditOfflineClass')) {
message.warning('无【编辑线下课】权限,请联系管理员');
return;
message.warning('无【编辑线下活动】权限,请联系管理员')
return
}
let _shelfState = item.shelfState;
let _shelfState = item.shelfState
if (_shelfState === 'NO') {
_shelfState = 'YES';
item.shelfState = 'YES';
_shelfState = 'YES'
item.shelfState = 'YES'
} else {
_shelfState = 'NO';
item.shelfState = 'NO';
_shelfState = 'NO'
item.shelfState = 'NO'
}
const params = {
courseId: item.courseId,
shelfState: _shelfState,
};
}
CourseService.changeVideoShelfState(params).then((res) => {
if (res.success) {
if (_shelfState === 'YES') {
message.success('已开启展示');
message.success('已开启展示')
} else {
message.success('已取消展示');
message.success('已取消展示')
}
this.props.onChange()
}
this.props.onChange();
})
}
});
};
// 删除视频课
handleDeleteOfflineCourse = (courseId, isDelete) => {
if (isDelete) {
......@@ -333,13 +333,13 @@ class OfflineCourseList extends React.Component {
onOk: () => {
const param = {
courseId: courseId,
};
}
Service.Hades('public/hades/delOfflineCourse', param).then(() => {
message.success('删除成功');
this.props.onChange();
});
message.success('删除成功')
this.props.onChange()
})
},
});
})
} else {
Modal.confirm({
title: '取消课程',
......@@ -350,82 +350,82 @@ class OfflineCourseList extends React.Component {
onOk: () => {
const param = {
courseId: courseId,
};
}
Service.Hades('public/hades/cancelOfflineCourse', param).then(() => {
message.success('取消成功');
this.props.onChange();
});
message.success('取消成功')
this.props.onChange()
})
},
});
})
}
}
};
// 显示分享弹窗
handleShowShareModal = (record, needStr = false) => {
const { courseId } = record;
const htmlUrl = `${LIVE_SHARE}offline_detail/${courseId}?id=${User.getStoreId()}`;
const longUrl = htmlUrl;
const { courseName, courseMediaVOS } = record;
const coverUrl = (_.find(courseMediaVOS, (data) => data.contentType === 'COVER') || {}).mediaUrl;
const { courseId } = record
const htmlUrl = `${LIVE_SHARE}offline_detail/${courseId}?id=${User.getStoreId()}`
const longUrl = htmlUrl
const { courseName, courseMediaVOS } = record
const coverUrl = (_.find(courseMediaVOS, (data) => data.contentType === 'COVER') || {}).mediaUrl
const shareData = {
longUrl,
coverUrl,
courseName,
};
}
const shareLiveModal = (
<ShareLiveModal
needStr={needStr}
data={shareData}
type='offlineClass'
title='线下'
title='线下活动'
close={() => {
this.setState({
shareLiveModal: null,
});
localStorage.setItem('videoCourseItem', '');
})
localStorage.setItem('videoCourseItem', '')
}}
/>
);
)
this.setState({ shareLiveModal });
};
this.setState({ shareLiveModal })
}
handleChangeTable = (pagination, filters, sorter) => {
const { columnKey, order } = sorter;
const { query } = this.props;
let _columnKey;
let _order;
const { columnKey, order } = sorter
const { query } = this.props
let _columnKey
let _order
// 按创建时间升序排序
if (columnKey === 'apply' && order === 'ascend') {
_columnKey = 'START_APPLY_DESC';
_order = 'SORT_ASC';
_columnKey = 'START_APPLY_DESC'
_order = 'SORT_ASC'
}
if (columnKey === 'created' && order === 'ascend') {
_columnKey = 'CREATED';
_order = 'SORT_ASC';
_columnKey = 'CREATED'
_order = 'SORT_ASC'
}
// 按创建时间降序排序
if (columnKey === 'apply' && order === 'descend') {
_columnKey = 'START_APPLY_DESC';
_order = 'SORT_DESC';
_columnKey = 'START_APPLY_DESC'
_order = 'SORT_DESC'
}
if (columnKey === 'created' && order === 'descend') {
_columnKey = 'CREATED';
_order = 'SORT_DESC';
_columnKey = 'CREATED'
_order = 'SORT_DESC'
}
const _query = {
...query,
sortMap: {},
};
_query.sortMap[_columnKey] = _order;
this.props.onChange(_query);
};
}
_query.sortMap[_columnKey] = _order
this.props.onChange(_query)
}
render() {
const { openQRCodeModal, qrcodeData } = this.state;
const { dataSource = [], totalCount, query, match } = this.props;
const { current, size } = query;
const { openQRCodeModal, qrcodeData } = this.state
const { dataSource = [], totalCount, query, match } = this.props
const { current, size } = query
return (
<div className='offline-course-list'>
<XMTable
......@@ -449,8 +449,8 @@ class OfflineCourseList extends React.Component {
pageSize={size}
total={totalCount}
toPage={(page) => {
const _query = { ...query, current: page + 1 };
this.props.onChange(_query);
const _query = { ...query, current: page + 1 }
this.props.onChange(_query)
}}
/>
</div>
......@@ -460,13 +460,13 @@ class OfflineCourseList extends React.Component {
visible={openQRCodeModal}
data={qrcodeData}
onCancel={() => {
this.setState({ openQRCodeModal: false });
this.setState({ openQRCodeModal: false })
}}
/>
<Route path={`${match.url}/data`} component={OfflineCourseData} />
</div>
);
)
}
}
export default withRouter(OfflineCourseList);
export default withRouter(OfflineCourseList)
......@@ -7,22 +7,22 @@
* @Copyright: 杭州杰竞科技有限公司 版权所有
*/
import React from 'react';
import { Button } from 'antd';
import React from 'react'
import { Button } from 'antd'
import './OfflineCourseOpt.less';
import './OfflineCourseOpt.less'
export default function OfflineCourseOpt() {
return (
<div className="video-course-opt">
<div className='video-course-opt'>
<Button
type="primary"
type='primary'
onClick={() => {
RCHistory.push('/create-offline-course?type=add');
RCHistory.push('/create-offline-course?type=add')
}}
className="mr12"
>新建线下课</Button>
className='mr12'>
新建线下活动
</Button>
</div>
);
)
}
import React from 'react';
import React from 'react'
import OfflineCourseFilter from './components/OfflineCourseFilter';
import OfflineCourseOpt from './components/OfflineCourseOpt';
import OfflineCourseList from './components/OfflineCourseList';
import Service from '@/common/js/service';
import OfflineCourseFilter from './components/OfflineCourseFilter'
import OfflineCourseOpt from './components/OfflineCourseOpt'
import OfflineCourseList from './components/OfflineCourseList'
import Service from '@/common/js/service'
import User from '@/common/js/user'
class OfflineCoursePage extends React.Component {
constructor(props) {
super(props);
super(props)
this.state = {
query: {
size: 10,
current: 1,
storeId:User.getStoreId()
storeId: User.getStoreId(),
},
dataSource: [], // 线下课列表
totalCount: 0, // 线下课数据总条数
......@@ -23,54 +22,47 @@ class OfflineCoursePage extends React.Component {
componentWillMount() {
// 获取线下课列表
this.handleFetchScheduleList();
this.handleFetchScheduleList()
}
// 获取线下课列表
handleFetchScheduleList = (_query = {}) => {
const query = {
...this.state.query,
..._query
};
..._query,
}
// 更新请求参数
this.setState({ query });
this.setState({ query })
Service.Hades('public/hades/getOfflineCoursePage', query).then((res) => {
const { result = {} } = res || {};
const { records = [], total = 0 } = result;
const { result = {} } = res || {}
const { records = [], total = 0 } = result
this.setState({
dataSource: records,
totalCount: Number(total)
});
totalCount: Number(total),
})
})
}
render() {
const { dataSource, totalCount, query } = this.state;
const { dataSource, totalCount, query } = this.state
return (
<div className="page video-course-page">
<div className="content-header">线下课</div>
<div className='page video-course-page'>
<div className='content-header'>线下活动</div>
<div className="box">
<div className='box'>
{/* 搜索模块 */}
<OfflineCourseFilter
onChange={this.handleFetchScheduleList}
/>
<OfflineCourseFilter onChange={this.handleFetchScheduleList} />
{/* 操作模块 */}
{window.ctx.xmState.storeUserPermissionList.includes('AddOfflineClass') && <OfflineCourseOpt />}
{/* 线下课列表模块 */}
<OfflineCourseList
query={query}
dataSource={dataSource}
totalCount={totalCount}
onChange={this.handleFetchScheduleList}
/>
<OfflineCourseList query={query} dataSource={dataSource} totalCount={totalCount} onChange={this.handleFetchScheduleList} />
</div>
</div>
)
}
}
export default OfflineCoursePage;
export default OfflineCoursePage
import React from 'react';
import { Modal } from 'antd';
import moment from 'moment';
import $ from 'jquery';
import Service from "@/common/js/service";
import './PreviewOfflineModal.less';
import ENUM from '@/modules/knowledge-base/ENUM';
import React from 'react'
import { Modal } from 'antd'
import moment from 'moment'
import $ from 'jquery'
import Service from '@/common/js/service'
import './PreviewOfflineModal.less'
import ENUM from '@/modules/knowledge-base/ENUM'
const defaultCoverUrl = 'https://image.xiaomaiketang.com/xm/pxbWKsYA87.png';
const defaultCoverUrl = 'https://image.xiaomaiketang.com/xm/pxbWKsYA87.png'
class PreviewOfflineModal extends React.Component {
constructor(props) {
super(props);
this.state = {
}
super(props)
this.state = {}
}
componentDidMount() {
const { data } = this.props;
_.isEmpty(data) ? this.getCourseDetail() : this.setState({ ...data });
const { data } = this.props
_.isEmpty(data) ? this.getCourseDetail() : this.setState({ ...data })
}
getCourseDetail = () => {
......@@ -26,20 +24,20 @@ class PreviewOfflineModal extends React.Component {
courseId: this.props.courseId,
}).then((res) => {
if (res.success) {
const { result } = res;
let coverUrl = '';
const { result } = res
let coverUrl = ''
result.courseMediaVOS.map((item) => {
switch (item.contentType){
case "COVER":
coverUrl = item.mediaUrl;
break;
case "INTRO":
this.getTextDetail('introduce', item.mediaUrl);
break;
switch (item.contentType) {
case 'COVER':
coverUrl = item.mediaUrl
break
case 'INTRO':
this.getTextDetail('introduce', item.mediaUrl)
break
default:
break;
break
}
return item;
return item
})
this.setState({
...result,
......@@ -54,10 +52,10 @@ class PreviewOfflineModal extends React.Component {
data: {},
type: 'GET',
url,
contentType:'application/x-www-form-urlencoded; charset=UTF-8',
contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
success: (res) => {
this.setState({ [key]: res, [`load${key}`]: true });
}
this.setState({ [key]: res, [`load${key}`]: true })
},
})
}
......@@ -85,79 +83,82 @@ class PreviewOfflineModal extends React.Component {
signOutStartTimeUnit,
signOutEndTimeNum,
signOutEndTimeUnit,
} = this.state;
const unit = (signInTimeUnit || '').toLocaleLowerCase() + 's';
const time = (signInType === 'START_AGO' ? startTime : endTime) && moment(signInType === 'START_AGO' ? startTime : endTime).subtract(signInTimeNum, unit);
const signInTime = (time && signInTimeNum) && `${moment(time).format('HH:mm')} ~ ${moment(signInType === 'START_AGO' ? startTime : endTime).format('HH:mm')}`;
const endUnit = (signOutEndTimeUnit || '').toLocaleLowerCase() + 's';
const end = (endTime && signOutEndTimeNum) && moment(endTime).add(signOutEndTimeNum, endUnit);
let startUnit = '';
let start = '';
} = this.state
const unit = (signInTimeUnit || '').toLocaleLowerCase() + 's'
const time = (signInType === 'START_AGO' ? startTime : endTime) && moment(signInType === 'START_AGO' ? startTime : endTime).subtract(signInTimeNum, unit)
const signInTime = time && signInTimeNum && `${moment(time).format('HH:mm')} ~ ${moment(signInType === 'START_AGO' ? startTime : endTime).format('HH:mm')}`
const endUnit = (signOutEndTimeUnit || '').toLocaleLowerCase() + 's'
const end = endTime && signOutEndTimeNum && moment(endTime).add(signOutEndTimeNum, endUnit)
let startUnit = ''
let start = ''
if (signOutType === 'START_LATER') {
startUnit = (signOutStartTimeUnit || '').toLocaleLowerCase() + 's';
start = (startTime && signOutStartTimeNum) && moment(startTime).add(signOutStartTimeNum, startUnit);
startUnit = (signOutStartTimeUnit || '').toLocaleLowerCase() + 's'
start = startTime && signOutStartTimeNum && moment(startTime).add(signOutStartTimeNum, startUnit)
}
console.log(start, end, startTime, endTime, 666666)
const signOutTime = (start || end) && (signOutType === 'START_LATER' ? `${moment(start).format('HH:mm')} ~ ${moment(end).format('HH:mm')}` : `${moment(endTime).format('HH:mm')} ~ ${moment(end).format('HH:mm')}`);
const signOutTime =
(start || end) &&
(signOutType === 'START_LATER'
? `${moment(start).format('HH:mm')} ~ ${moment(end).format('HH:mm')}`
: `${moment(endTime).format('HH:mm')} ~ ${moment(end).format('HH:mm')}`)
return (
<Modal
title="预览"
title='预览'
visible={true}
width={680}
onCancel={this.props.close}
footer={null}
maskClosable={false}
closeIcon={<span className="icon iconfont modal-close-icon">&#xe6ef;</span>}
className="preview-offline-modal"
>
<div className="container__wrap">
<div className="container">
<div className="container__header">
<div className="cover"></div>
<img src={coverUrl || defaultCoverUrl} className="course-cover" />
<span className="cover-teacher">主讲人:{teacherName}</span>
<span className="cover-state" style={{ background: (ENUM.offlineStateShow[courseState] || {}).color }}>{(ENUM.offlineStateShow[courseState] || {}).title}</span>
closeIcon={<span className='icon iconfont modal-close-icon'>&#xe6ef;</span>}
className='preview-offline-modal'>
<div className='container__wrap'>
<div className='container'>
<div className='container__header'>
<div className='cover'></div>
<img src={coverUrl || defaultCoverUrl} className='course-cover' />
<span className='cover-teacher'>主讲人:{teacherName}</span>
<span className='cover-state' style={{ background: (ENUM.offlineStateShow[courseState] || {}).color }}>
{(ENUM.offlineStateShow[courseState] || {}).title}
</span>
</div>
<div className="container__body">
<div className="title__name">{courseName}</div>
<div className="title__categery">
<img className="item-icon" src="https://image.xiaomaiketang.com/xm/cDMwz3jzaX.png" />
<div className='container__body'>
<div className='title__name'>{courseName}</div>
<div className='title__categery'>
<img className='item-icon' src='https://image.xiaomaiketang.com/xm/cDMwz3jzaX.png' />
课程分类:{categoryName}
</div>
<div className="title__categery">
<img className="item-icon" src="https://image.xiaomaiketang.com/xm/BfTBK3dGda.png" />
<div className='title__categery'>
<img className='item-icon' src='https://image.xiaomaiketang.com/xm/BfTBK3dGda.png' />
上课时间:{startTime ? moment(startTime).format('HH:mm') : ''}~{endTime ? moment(endTime).format('HH:mm') : ''}
</div>
<div className="title__categery">
<img className="item-icon" src="https://image.xiaomaiketang.com/xm/KhFNBTtAKR.png" />
<div className='title__categery'>
<img className='item-icon' src='https://image.xiaomaiketang.com/xm/KhFNBTtAKR.png' />
上课地点:{offlinePlace}
</div>
</div>
<div className="container__introduction">
<div className="title">线下课简介</div>
<div className="container__introduction__list editor-box">
{whetherSetApply === 'YES' && <div className="course-time">
<div className="time-title">报名时间</div>
<div className="time-text">{startTimeApply && moment(startTimeApply).format('MM-DD HH:mm')} ~ {endTimeApply && moment(endTimeApply).format('MM-DD HH:mm')}</div>
</div>}
{(whetherSetSignIn === 'YES' || whetherSetSignOut === 'YES') && <div className="course-time">
<div className="time-title">考勤时间</div>
{whetherSetSignIn === 'YES' &&
<div className="time-text">
签到:{signInTime}
<div className='container__introduction'>
<div className='title'>线下活动简介</div>
<div className='container__introduction__list editor-box'>
{whetherSetApply === 'YES' && (
<div className='course-time'>
<div className='time-title'>报名时间</div>
<div className='time-text'>
{startTimeApply && moment(startTimeApply).format('MM-DD HH:mm')} ~ {endTimeApply && moment(endTimeApply).format('MM-DD HH:mm')}
</div>
}
{whetherSetSignOut === 'YES' &&
<div className="time-text">
签退:{signOutTime}
</div>
}
</div>}
)}
{(whetherSetSignIn === 'YES' || whetherSetSignOut === 'YES') && (
<div className='course-time'>
<div className='time-title'>考勤时间</div>
{whetherSetSignIn === 'YES' && <div className='time-text'>签到:{signInTime}</div>}
{whetherSetSignOut === 'YES' && <div className='time-text'>签退:{signOutTime}</div>}
</div>
)}
<div
className="intro-item text"
className='intro-item text'
dangerouslySetInnerHTML={{
__html: introduce
__html: introduce,
}}
/>
</div>
......@@ -169,4 +170,4 @@ class PreviewOfflineModal extends React.Component {
}
}
export default PreviewOfflineModal;
export default PreviewOfflineModal
......@@ -757,7 +757,7 @@ class AddVideoCourse extends React.Component {
<Button>选择文件</Button>
</Dropdown>
</div>
<div className='course-ware--empty'>资料云盘中选择视频</div>
<div className='course-ware--empty'>素材库中选择视频</div>
</div>
<div className='tips'>
课节数量限制20个,文件规格说明
......
import React from "react"
import { Modal, message, Tooltip, Switch, Dropdown } from "antd"
import _ from "underscore"
import { PageControl } from "@/components"
import { LIVE_SHARE } from "@/domains/course-domain/constants"
import { Route, withRouter } from 'react-router-dom';
import ShareLiveModal from "@/modules/course-manage/modal/ShareLiveModal"
import CourseService from "@/domains/course-domain/CourseService"
import RelatedPlanModal from "../../modal/RelatedPlanModal"
import User from "@/common/js/user"
import VideoCourseDetail from '../VideoCourseDetail';
import WatchData from "./WatchData";
import { XMTable } from '@/components';
import college from '@/common/lottie/college';
import "./VideoCourseList.less"
import React from 'react'
import { Modal, message, Tooltip, Switch, Dropdown } from 'antd'
import _ from 'underscore'
import { PageControl } from '@/components'
import { LIVE_SHARE } from '@/domains/course-domain/constants'
import { Route, withRouter } from 'react-router-dom'
import ShareLiveModal from '@/modules/course-manage/modal/ShareLiveModal'
import CourseService from '@/domains/course-domain/CourseService'
import RelatedPlanModal from '../../modal/RelatedPlanModal'
import User from '@/common/js/user'
import VideoCourseDetail from '../VideoCourseDetail'
import WatchData from './WatchData'
import { XMTable } from '@/components'
import college from '@/common/lottie/college'
import './VideoCourseList.less'
class VideoCourseList extends React.Component {
constructor(props) {
super(props);
super(props)
this.state = {
id: '', // 视频课ID
studentIds: [],
......@@ -24,54 +24,48 @@ class VideoCourseList extends React.Component {
selectPlanList: {},
ShelfLoading: false,
// dataSource: [],
};
}
}
componentDidMount() {
const videoCourseItem = localStorage.getItem('videoCourseItem');
const videoCourseItem = localStorage.getItem('videoCourseItem')
if (videoCourseItem) {
const _videoCourseItem = JSON.parse(videoCourseItem);
this.handleShowShareModal(_videoCourseItem, true);
const _videoCourseItem = JSON.parse(videoCourseItem)
this.handleShowShareModal(_videoCourseItem, true)
}
}
// 跳转课程详情页
handleLinkToCourseDetail = (courseId) => {
const { match } = this.props;
const { match } = this.props
window.RCHistory.push(`${match.url}/video-course-detail?courseId=${courseId}`)
}
// 观看数据弹窗
handleShowWatchDataModal = (item) => {
const { match } = this.props;
const { match } = this.props
window.RCHistory.push({
pathname: `${match.url}/course-data?courseName=${item.courseName}&courseId=${item.id}`
pathname: `${match.url}/course-data?courseName=${item.courseName}&courseId=${item.id}`,
})
}
// 请求表头
parseColumns = () => {
const { type } = this.props;
const { ShelfLoading } = this.state;
const { type } = this.props
const { ShelfLoading } = this.state
const columns = [
{
title: "线上课",
key: "scheduleName",
dataIndex: "scheduleName",
title: '线上课',
key: 'scheduleName',
dataIndex: 'scheduleName',
width: 321,
fixed: 'left',
render: (val, record) => {
const { coverUrl } = record;
const { coverUrl } = record
return (
<div className='record__item'>
<img
className='course-cover'
src={
coverUrl || 'https://image.xiaomaiketang.com/xm/TwtGPQGE4K.png'
}
alt='封面图'
/>
<img className='course-cover' src={coverUrl || 'https://image.xiaomaiketang.com/xm/TwtGPQGE4K.png'} alt='封面图' />
<Choose>
<When condition={record.courseName.length > 25}>
<Tooltip title={record.courseName}>
......@@ -83,7 +77,7 @@ class VideoCourseList extends React.Component {
</Otherwise>
</Choose>
</div>
);
)
},
},
{
......@@ -99,35 +93,23 @@ class VideoCourseList extends React.Component {
</If>
</span>
),
key: "categoryName",
dataIndex: "categoryName",
key: 'categoryName',
dataIndex: 'categoryName',
width: 150,
render: (val, record) => {
return (
<Choose>
<When condition={type === 'internal'}>
<div className='record__item'>
{record.categoryOneName}
{record.categoryTwoName ? `-${record.categoryTwoName}` : ''}
</div>
</When>
<Otherwise>
<div className='record__item'>{record.categorySonName}</div>
</Otherwise>
</Choose>
);
return <div className='record__item'>{record.categoryName}</div>
},
},
{
title: '课节数',
key: 'chapterNum',
dataIndex: 'chapterNum',
className: "chapterNum",
className: 'chapterNum',
width: 100,
align: 'right',
render: (val,item) => {
return <div onClick={()=>this.handleLinkToCourseDetail(item.id)}>{val || 1}</div>
}
render: (val, item) => {
return <div onClick={() => this.handleLinkToCourseDetail(item.id)}>{val || 1}</div>
},
},
{
title: (
......@@ -158,26 +140,30 @@ class VideoCourseList extends React.Component {
checked={item.shelfState === 'YES'}
defaultChecked={item.shelfState}
onClick={(checked) => {
this.changeShelfState(checked, item, index);
this.changeShelfState(checked, item, index)
}}
/>
);
)
},
},
{
title: "观看学员数",
title: '观看学员数',
width: 150,
key: "watchUserCount",
dataIndex: "watchUserCount",
key: 'watchUserCount',
dataIndex: 'watchUserCount',
align: 'right',
render: (val, item) => {
return <div className='watchUserCount' onClick={() => this.handleShowWatchDataModal(item)}>{val || 0}</div>
}
return (
<div className='watchUserCount' onClick={() => this.handleShowWatchDataModal(item)}>
{val || 0}
</div>
)
},
},
{
title: "创建人",
key: "createName",
dataIndex: "createName",
title: '创建人',
key: 'createName',
dataIndex: 'createName',
width: 100,
render: (val) => {
return (
......@@ -189,7 +175,7 @@ class VideoCourseList extends React.Component {
)}
</div>
)
}
},
},
{
title: '创建时间',
......@@ -198,7 +184,7 @@ class VideoCourseList extends React.Component {
dataIndex: 'created',
sorter: true,
render: (val) => {
return window.formatDate('YYYY-MM-DD H:i', val);
return window.formatDate('YYYY-MM-DD H:i', val)
},
},
{
......@@ -208,7 +194,7 @@ class VideoCourseList extends React.Component {
dataIndex: 'updated',
sorter: true,
render: (val) => {
return window.formatDate('YYYY-MM-DD H:i', val);
return window.formatDate('YYYY-MM-DD H:i', val)
},
},
{
......@@ -227,7 +213,7 @@ class VideoCourseList extends React.Component {
<span key={item.planId}>
{item.planName} {index < record.relatedPlanList.length - 1 && <span></span>}
</span>
);
)
})}
</Tooltip>
</When>
......@@ -236,7 +222,7 @@ class VideoCourseList extends React.Component {
</Otherwise>
</Choose>
</div>
);
)
},
},
{
......@@ -248,7 +234,7 @@ class VideoCourseList extends React.Component {
render: (val, record) => {
return (
<div className='operate'>
<If condition={type === "internal"}>
<If condition={type === 'internal'}>
<div className='operate__item' onClick={() => this.handleShowShareModal(record)}>
分享
</div>
......@@ -263,17 +249,17 @@ class VideoCourseList extends React.Component {
</span>
</Dropdown>
</div>
);
)
},
},
];
]
type !== 'internal' && columns.splice(5, 1);
return columns;
};
type !== 'internal' && columns.splice(5, 1)
return columns
}
renderMoreOperate = (item) => {
const { type } = this.props;
const { type } = this.props
return (
<div className='live-course-more-menu'>
<If condition={type !== 'internal'}>
......@@ -290,7 +276,7 @@ class VideoCourseList extends React.Component {
<div
className='operate__item'
onClick={() => {
window.RCHistory.push(`/create-video-course?type=edit&id=${item.id}`);
window.RCHistory.push(`/create-video-course?type=edit&id=${item.id}`)
}}>
编辑
</div>
......@@ -299,41 +285,41 @@ class VideoCourseList extends React.Component {
</div>
</If>
</div>
);
};
)
}
handlePlanName = (planArray) => {
let planStr = '';
let planStr = ''
planArray.forEach((item, index) => {
if (index < planArray.length - 1) {
planStr = planStr + item.planName + '、';
planStr = planStr + item.planName + '、'
} else {
planStr = planStr + item.planName;
planStr = planStr + item.planName
}
})
return planStr
}
});
return planStr;
};
//改变上架状态
changeShelfState = (checked, item, index) => {
let _shelfState = checked ? 'YES' : 'NO';
let _shelfState = checked ? 'YES' : 'NO'
if (checked) {
_shelfState = 'YES';
_shelfState = 'YES'
} else {
_shelfState = 'NO';
_shelfState = 'NO'
}
const params = {
courseId: item.id,
shelfState: _shelfState,
};
}
CourseService.changeVideoShelfState(params).then(() => {
if (_shelfState === 'YES') {
message.success('已开启展示');
message.success('已开启展示')
} else {
message.success('已取消展示');
message.success('已取消展示')
}
this.props.changeShelfState(index, _shelfState)
})
}
this.props.changeShelfState(index, _shelfState);
});
};
// 删除线上课
handleDeleteVideoCourse = (scheduleId) => {
......@@ -348,28 +334,28 @@ class VideoCourseList extends React.Component {
const param = {
courseId: scheduleId,
storeId: User.getStoreId(),
};
}
CourseService.delVideoSchedule(param).then(() => {
message.success('删除成功');
this.props.onChange();
});
message.success('删除成功')
this.props.onChange()
})
},
});
};
})
}
// 显示分享弹窗
handleShowShareModal = (record, needStr = false) => {
const { type } = this.props;
const { id, scheduleVideoUrl } = record;
const htmlUrl = `${LIVE_SHARE}video_detail/${id}?id=${User.getStoreId()}`;
const longUrl = htmlUrl;
const { coverUrl, courseName } = record;
const { type } = this.props
const { id, scheduleVideoUrl } = record
const htmlUrl = `${LIVE_SHARE}video_detail/${id}?id=${User.getStoreId()}`
const longUrl = htmlUrl
const { coverUrl, courseName } = record
const shareData = {
longUrl,
coverUrl,
scheduleVideoUrl,
courseName,
};
}
const shareLiveModal = (
<ShareLiveModal
......@@ -381,82 +367,82 @@ class VideoCourseList extends React.Component {
close={() => {
this.setState({
shareLiveModal: null,
});
localStorage.setItem('videoCourseItem', '');
})
localStorage.setItem('videoCourseItem', '')
}}
/>
);
)
this.setState({ shareLiveModal });
};
this.setState({ shareLiveModal })
}
handleChangeTable = (pagination, filters, sorter) => {
const { columnKey, order } = sorter;
const { query } = this.props;
let { order: _order } = query;
const { columnKey, order } = sorter
const { query } = this.props
let { order: _order } = query
// 按创建时间升序排序
if (columnKey === 'created' && order === 'ascend') {
_order = 'CREATED_ASC';
_order = 'CREATED_ASC'
}
// 按创建时间降序排序
if (columnKey === 'created' && order === 'descend') {
_order = 'CREATED_DESC';
_order = 'CREATED_DESC'
}
// 按更新时间升序排序
if (columnKey === 'updated' && order === 'ascend') {
_order = 'UPDATED_ASC';
_order = 'UPDATED_ASC'
}
// 按更新时间降序排序
if (columnKey === 'updated' && order === 'descend') {
_order = 'UPDATED_DESC';
_order = 'UPDATED_DESC'
}
const _query = {
...query,
orderEnum: _order,
};
this.props.onChange(_query);
};
}
this.props.onChange(_query)
}
handleRelatedModalShow = (item) => {
const selectPlanList = {};
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;
});
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();
this.props.onChange()
}
)
}
);
};
render() {
const { dataSource = [], totalCount, query, type, match } = this.props;
const { current, size } = query;
const { RelatedPlanModalVisible, selectPlanList, selectCourseId } = this.state;
const { dataSource = [], totalCount, query, type, match } = this.props
const { current, size } = query
const { RelatedPlanModalVisible, selectPlanList, selectCourseId } = this.state
return (
<div className={`video-course-list ${type !== 'internal' ? 'video-course-list-mt' : ''}`}>
<XMTable
......@@ -480,8 +466,8 @@ class VideoCourseList extends React.Component {
pageSize={size}
total={totalCount}
toPage={(page) => {
const _query = { ...query, current: page + 1 };
this.props.onChange(_query);
const _query = { ...query, current: page + 1 }
this.props.onChange(_query)
}}
/>
</div>
......@@ -500,8 +486,8 @@ class VideoCourseList extends React.Component {
<Route path={`${match.url}/video-course-detail`} component={VideoCourseDetail} />
<Route path={`${match.url}/course-data`} component={WatchData} />
</div>
);
)
}
}
export default withRouter(VideoCourseList);
export default withRouter(VideoCourseList)
import React, { useEffect, useState } from 'react';
import { Select, Tooltip, Carousel, Popover } from 'antd';
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 React, { useEffect, useState } from 'react'
import { Select, Tooltip, Carousel, Popover } from 'antd'
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 Service from "@/common/js/service";
import User from '@/common/js/user';
import Service from '@/common/js/service'
import User from '@/common/js/user'
import HomeTip from './HomeTip';
import './Home.less';
import HomeTip from './HomeTip'
import './Home.less'
const Option = Select.Option;
const Option = Select.Option
class Home extends React.Component {
constructor(props) {
super(props);
super(props)
this.state = {
scheduleType: 'LIVE',
list: [],
......@@ -48,54 +34,54 @@ class Home extends React.Component {
incWeekVisitCustomerNum: 0,
courseNum: 0, //课程总数
inCourseNum: 0, //本月新增课程总数
};
this._chart = null;
}
this._chart = null
}
componentDidMount() {
this.getPanelInfo();
this.getStudyInfo();
this.getHotCourse();
this.getTrainingInfo();
this.getPanelInfo()
this.getStudyInfo()
this.getHotCourse()
this.getTrainingInfo()
}
getTrainingInfo() {
Service.Hades('public/hades/planOverview', { storeId: User.getStoreId() }).then((res) => {
if (res.success) {
this.setState(res.result);
this.setState(res.result)
}
});
})
}
getHotCourse() {
const { timeRange, scheduleType } = this.state;
const { timeRange, scheduleType } = this.state
const data = {
hotNum: 5,
scheduleType,
storeId: User.getStoreId(),
timeRange,
};
}
Service.Hades('public/courseCloud/hotCourse', data).then((res) => {
if (res.success) {
this.setState({
list: res.result,
});
})
}
});
})
}
getStudyInfo() {
const { studyTimeRange } = this.state;
const { studyTimeRange } = this.state
Service.Hades('public/hades/studyInfo', { storeId: User.getStoreId(), timeRange: studyTimeRange }).then((res) => {
if (res.success) {
const dataList = res.result.map((item) => ({
time: moment(item.dateline).format('MM-DD'),
studyNum: item.studyNum,
studyTime: Math.round(item.studyTime / 6) / 10,
}));
this.createChart(dataList);
}))
this.createChart(dataList)
}
});
})
}
getPanelInfo() {
......@@ -120,22 +106,22 @@ class Home extends React.Component {
incWeekVisitCustomerNum: res.result.incWeekVisitCustomerNum,
courseNum: res.result.videoCourseNum + res.result.liveCourseNum + res.result.pictureCourseNum + res.result.offlineCourseNum,
inCourseNum: res.result.incLiveCourseNum + res.result.incVideoCourseNum + res.result.incPictureCourseNum + res.result.incOfflineCourseNum,
});
})
}
});
})
}
showNumber(index) {
switch (index) {
case 0:
return 'https://image.xiaomaiketang.com/xm/D64QhNn74S.png';
return 'https://image.xiaomaiketang.com/xm/D64QhNn74S.png'
case 1:
return 'https://image.xiaomaiketang.com/xm/Qfib4mnGJT.png';
return 'https://image.xiaomaiketang.com/xm/Qfib4mnGJT.png'
case 2:
return 'https://image.xiaomaiketang.com/xm/8jKXHyrDaG.png';
return 'https://image.xiaomaiketang.com/xm/8jKXHyrDaG.png'
default:
return 'https://image.xiaomaiketang.com/xm/D64QhNn74S.png';
return 'https://image.xiaomaiketang.com/xm/D64QhNn74S.png'
}
}
......@@ -146,28 +132,28 @@ class Home extends React.Component {
forceFit: true,
height: 290,
padding: [48, 64],
});
})
}
this._chart.clear();
this._chart.clear()
this._chart.source(data, {
studyTime: {
formatter: (val) => {
return val;
return val
},
tickCount: 5,
},
time: {
formatter: (val) => {
return `${val}`;
return `${val}`
},
},
studyNum: {
formatter: (val) => {
return val;
return val
},
tickCount: 5,
},
});
})
this._chart.axis('time', {
label: {
offset: 20,
......@@ -182,7 +168,7 @@ class Home extends React.Component {
tickLine: {
stroke: '#E8E8E8',
},
});
})
this._chart.axis('submitCount', {
label: {
textStyle: {
......@@ -190,7 +176,7 @@ class Home extends React.Component {
fontSize: 14,
},
},
});
})
this._chart.axis('studyTime', {
label: {
textStyle: {
......@@ -198,7 +184,7 @@ class Home extends React.Component {
fontSize: 14,
},
},
});
})
this._chart
.line()
.position('time*studyNum')
......@@ -207,8 +193,8 @@ class Home extends React.Component {
return {
name: '学习人数',
value: studyNum + '人',
};
});
}
})
this._chart
.line()
.position('time*studyTime')
......@@ -217,10 +203,10 @@ class Home extends React.Component {
return {
name: '人均学习时长',
value: studyTime + '分钟',
};
});
}
})
this._chart.legend(false);
this._chart.legend(false)
this._chart.tooltip({
containerTpl:
'<div class="g2-tooltip" style="background: #fff !important;">' +
......@@ -228,9 +214,9 @@ class Home extends React.Component {
'<ul class="g2-tooltip-list"></ul></div>', // tooltip 容器模板
itemTpl:
'<li data-index={index}><span style="background-color:{color};width:8px;height:8px;border-radius:50%;display:inline-block;margin-right:8px;"></span>{name}<span style="display: inline-block; float: right; margin-left: 30px;">{value}</span></li>', // tooltip 每项记录的默认模板
});
this._chart.render();
};
})
this._chart.render()
}
render() {
const {
......@@ -259,7 +245,7 @@ class Home extends React.Component {
offlineCourseNum,
weekVisitCustomerNum,
incWeekVisitCustomerNum,
} = this.state;
} = this.state
const data = [
{
item: '已完成培训',
......@@ -269,26 +255,26 @@ class Home extends React.Component {
item: '未完成培训',
count: unfinishedNum,
},
];
const { DataView } = DataSet;
const { Html } = Guide;
const sum = data[0].count + data[1].count;
const dv = new DataView();
]
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;
val = val * 100 + '%'
return val
},
},
};
}
return (
<div className='home-page'>
<HomeTip />
......@@ -359,7 +345,7 @@ class Home extends React.Component {
</div>
</div>
<div className='course-item'>
<div className='course-title'>线下</div>
<div className='course-title'>线下活动</div>
<div className='data'>
<span className='course-number'>{offlineCourseNum}</span>
{incOfflineCourseNum > 0 && <span className='icon iconfont'>&#xe635;</span>}
......@@ -409,8 +395,9 @@ class Home extends React.Component {
</span>
<span
className={`tab${scheduleType === 'VOICE' ? ' selected' : ''}`}
onClick={() => this.setState({ scheduleType: 'VOICE' }, () => this.getHotCourse())}
>线上课</span>
onClick={() => this.setState({ scheduleType: 'VOICE' }, () => this.getHotCourse())}>
线上课
</span>
<span
className={`tab${scheduleType === 'PICTURE' ? ' selected' : ''}`}
onClick={() => this.setState({ scheduleType: 'PICTURE' }, () => this.getHotCourse())}>
......@@ -429,7 +416,7 @@ class Home extends React.Component {
style={{ width: 88 }}
value={timeRange}
onChange={(value) => {
this.setState({ timeRange: value }, () => this.getHotCourse());
this.setState({ timeRange: value }, () => this.getHotCourse())
}}>
<Option value='7'>近7天</Option>
<Option value='15'>近15天</Option>
......@@ -509,11 +496,11 @@ class Home extends React.Component {
tooltip={[
'item*percent',
(item, percent) => {
percent = Math.round(percent * 100) + '%';
percent = Math.round(percent * 100) + '%'
return {
name: item,
value: percent,
};
}
},
]}
style={{
......@@ -567,7 +554,7 @@ class Home extends React.Component {
style={{ width: 88 }}
value={studyTimeRange}
onChange={(value) => {
this.setState({ studyTimeRange: value }, () => this.getStudyInfo());
this.setState({ studyTimeRange: value }, () => this.getStudyInfo())
}}>
<Option value='7'>近7天</Option>
<Option value='15'>近15天</Option>
......@@ -595,8 +582,8 @@ class Home extends React.Component {
</div>
</div>
</div>
);
)
}
}
export default Home;
export default Home
......@@ -5,57 +5,43 @@
* @Last Modified time: 2020-06-23 14:54:14
* @Description: 网络磁盘(我的文件、公共文件、员工文件)
*/
import React from 'react';
import React from 'react'
import { DISK_MAP } from "@/common/constants/academic/lessonEnum";
import { DISK_MAP } from '@/common/constants/academic/lessonEnum'
function DiskList(props) {
const { diskList, currentRootDisk } = props;
const { diskList, currentRootDisk } = props
return (
<div className="disk-list__wrap">
<div className="disk-list">
{
diskList.map((item) => {
const isActive = item.disk === currentRootDisk.disk;
<div className='disk-list__wrap'>
<div className='disk-list'>
{diskList.map((item) => {
const isActive = item.disk === currentRootDisk.disk
return (
<div
key={item.disk}
className={`item ${isActive ? 'active' : ''}`}
onClick={() => { props.onChange(item)}}
>
{
item.disk === 'MYSELF' &&
<span className="icon iconfont">&#xe7a5;</span>
}
{
item.disk === 'COMMON' &&
<span className="icon iconfont">&#xe79d;</span>
}
{
item.disk === 'EMPLOYEE' &&
<span className="icon iconfont">&#xe7a3;</span>
}
<span className="disk-name">{ item.folderName }</span>
onClick={() => {
props.onChange(item)
}}>
{item.disk === 'MYSELF' && <span className='icon iconfont'>&#xe7a5;</span>}
{item.disk === 'COMMON' && <span className='icon iconfont'>&#xe79d;</span>}
{item.disk === 'EMPLOYEE' && <span className='icon iconfont'>&#xe7a3;</span>}
<span className='disk-name'>{item.folderName}</span>
</div>
)
})
}
})}
</div>
<a
className="guide-href"
className='guide-href'
href={window.NewVersion ? 'https://mp.weixin.qq.com/s/s0XN0Gk4Xul192SmTd6znw' : 'https://mp.weixin.qq.com/s/2EMWaaa3LQwkJd59bmy8pA'}
target="_blank"
>
进一步了解资料云盘
target='_blank'>
进一步了解素材库
</a>
</div>
)
};
}
export default DiskList;
\ No newline at end of file
export default DiskList
import React from 'react';
import { withRouter } from 'react-router-dom';
import { Modal, Button } from 'antd';
import React from 'react'
import { withRouter } from 'react-router-dom'
import { Modal, Button } from 'antd'
import User from '@/common/js/user';
import User from '@/common/js/user'
import FolderManage from './components/FolderManage';
import DiskList from './components/DiskList';
import { DISK_MAP } from "@/common/constants/academic/lessonEnum";
import FolderManage from './components/FolderManage'
import DiskList from './components/DiskList'
import { DISK_MAP } from '@/common/constants/academic/lessonEnum'
import './index.less';
import './index.less'
const { teacherId, gmtCreate } = window.currentUserInstInfo;
const { teacherId, gmtCreate } = window.currentUserInstInfo
// 判断是否是5.0或4.0T端
const isTeacher = !!teacherId;
const isTeacher = !!teacherId
// 判断是新用户还是老用户(gmtCreate小于上线日期的话就是老用户)
const onlineDate = +new Date('2020-07-17 00:00:00');
const isOldUser = gmtCreate <= onlineDate;
const onlineDate = +new Date('2020-07-17 00:00:00')
const isOldUser = gmtCreate <= onlineDate
const defaultRootDisk = {
folderName: '我的文件',
disk: 'MYSELF',
uploadPower: false
uploadPower: false,
}
class PrepareLessonPage extends React.Component {
constructor(props) {
super(props);
const prepareLessonTips = localStorage.getItem('prepare_lesson_tips');
super(props)
const prepareLessonTips = localStorage.getItem('prepare_lesson_tips')
this.state = {
prepareLessonTips,
diskList: [], // 可见磁盘目录
currentRootDisk: defaultRootDisk
currentRootDisk: defaultRootDisk,
}
}
componentWillMount() {
this.handleFetchDiskList();
this.handleFetchDiskList()
}
handleFetchDiskList = async () => {
const res = await axios.Apollo('public/apollo/getUserDisk', {});
const { result = [] } = res;
const res = await axios.Apollo('public/apollo/getUserDisk', {})
const { result = [] } = res
const diskList = result.map((item) => {
return {
...item,
folderName: DISK_MAP[item.disk]
folderName: DISK_MAP[item.disk],
}
});
})
this.setState({
diskList,
currentRootDisk: diskList[0] || defaultRootDisk
});
currentRootDisk: diskList[0] || defaultRootDisk,
})
}
handleChangeDisk = (disk) => {
this.setState({
currentRootDisk: disk
});
currentRootDisk: disk,
})
}
render() {
const { currentRootDisk, prepareLessonTips, diskList } = this.state;
const { currentRootDisk, prepareLessonTips, diskList } = this.state
return (
<div className="prepare-lesson-page page">
<div className="content-header">资料云盘</div>
<div className="box content-body">
<DiskList
diskList={diskList}
currentRootDisk={currentRootDisk}
onChange={this.handleChangeDisk}
/>
<FolderManage
currentRootDisk={currentRootDisk}
/>
<div className='prepare-lesson-page page'>
<div className='content-header'>素材库</div>
<div className='box content-body'>
<DiskList diskList={diskList} currentRootDisk={currentRootDisk} onChange={this.handleChangeDisk} />
<FolderManage currentRootDisk={currentRootDisk} />
</div>
{/* 老用户显示弹窗提示 */}
<Modal
title="备课本改版"
title='备课本改版'
visible={!prepareLessonTips && isOldUser}
footer={null}
width={680}
maskClosable={false}
closeIcon={<span className="icon iconfont modal-close-icon">&#xe6ef;</span>}
className="prepare-lesson-upgrade-modal"
closeIcon={<span className='icon iconfont modal-close-icon'>&#xe6ef;</span>}
className='prepare-lesson-upgrade-modal'
onCancel={() => {
this.setState({
prepareLessonTips: true
prepareLessonTips: true,
})
}}
>
<div className="title">“备课本” 升级为 “资料云盘” 了!</div>
<div className="upgrade-list">
<div className="upgrade-list__item">
<img src="https://xiaomai-image.oss-cn-hangzhou.aliyuncs.com/1594780611301.png" alt=""/>
<div className="item-title">存储更便捷</div>
<div className="item-sub-title">讲次关联模式升级文件夹模式,存储不再受讲次限制</div>
}}>
<div className='title'>“备课本” 升级为 “素材库” 了!</div>
<div className='upgrade-list'>
<div className='upgrade-list__item'>
<img src='https://xiaomai-image.oss-cn-hangzhou.aliyuncs.com/1594780611301.png' alt='' />
<div className='item-title'>存储更便捷</div>
<div className='item-sub-title'>讲次关联模式升级文件夹模式,存储不再受讲次限制</div>
</div>
<div className="upgrade-list__item">
<img src="https://xiaomai-image.oss-cn-hangzhou.aliyuncs.com/1594780629259.png" alt=""/>
<div className="item-title">结构更清晰</div>
<div className="item-sub-title">新增“我的文件”“公共文件”“员工文件”,满足机构存储需求</div>
<div className='upgrade-list__item'>
<img src='https://xiaomai-image.oss-cn-hangzhou.aliyuncs.com/1594780629259.png' alt='' />
<div className='item-title'>结构更清晰</div>
<div className='item-sub-title'>新增“我的文件”“公共文件”“员工文件”,满足机构存储需求</div>
</div>
<div className="upgrade-list__item">
<img src="https://xiaomai-image.oss-cn-hangzhou.aliyuncs.com/1594780641665.png" alt=""/>
<div className="item-title">同步更方便</div>
<div className="item-sub-title">支持主管直接查看员工文件,优质资料一目了然</div>
<div className='upgrade-list__item'>
<img src='https://xiaomai-image.oss-cn-hangzhou.aliyuncs.com/1594780641665.png' alt='' />
<div className='item-title'>同步更方便</div>
<div className='item-sub-title'>支持主管直接查看员工文件,优质资料一目了然</div>
</div>
</div>
<div
className="footer"
className='footer'
onClick={() => {
this.setState({ prepareLessonTips: true });
localStorage.setItem('prepare_lesson_tips', true);
}}
>我知道了</div>
this.setState({ prepareLessonTips: true })
localStorage.setItem('prepare_lesson_tips', true)
}}>
我知道了
</div>
</Modal>
</div>
)
}
}
export default PrepareLessonPage;
\ No newline at end of file
export default PrepareLessonPage
......@@ -6,44 +6,43 @@
* @Description: 文件夹列表
*/
import React from 'react';
import { Table, Menu, Dropdown, Modal, message,Tooltip } from 'antd';
import _ from 'underscore';
import { PageControl } from 'xiaomai-b-components';
import { XMTable } from '@/components';
import Service from '@/common/js/service';
import { formatDate } from '@/domains/basic-domain/utils';
import { FILE_TYPE_ICON_MAP, SUPPORT_FILE_TYPE_MAP, DEFAULT_SIZE_UNIT } from '@/domains/resource-disk/constants';
import { getFileTypeByName } from '@/domains/resource-disk/utils';
import addData from '../../lottie/addData/data.json';
import search from '../../lottie/search/data.json';
import UploadProgressModal from '@/bu-components/UploadProgressModal';
import SelectPrepareFileModal from '@/bu-components/SelectPrepareFileModal';
import CopyFileModal from '@/bu-components/CopyFileModal';
import ManagingMembersModal from '@/bu-components/ManagingMembersModal';
import PreviewFileModal from '@/bu-components/PreviewFileModal';
import {YZ_APPId,YZ_PREVIEW_URL,OFFICE_PREVIEW_URL} from '@/domains/basic-domain/constants';
import BaseService from "@/domains/basic-domain/baseService";
import ScanFileModal from '../modal/ScanFileModal';
import CreateFolderModal from '../modal/CreateFolderModal';
import User from '@/common/js/user';
import axios from 'axios';
const appId = "yozoqvpO2Hvz8346";
import React from 'react'
import { Table, Menu, Dropdown, Modal, message, Tooltip } from 'antd'
import _ from 'underscore'
import { PageControl } from 'xiaomai-b-components'
import { XMTable } from '@/components'
import Service from '@/common/js/service'
import { formatDate } from '@/domains/basic-domain/utils'
import { FILE_TYPE_ICON_MAP, SUPPORT_FILE_TYPE_MAP, DEFAULT_SIZE_UNIT } from '@/domains/resource-disk/constants'
import { getFileTypeByName } from '@/domains/resource-disk/utils'
import addData from '../../lottie/addData/data.json'
import search from '../../lottie/search/data.json'
import UploadProgressModal from '@/bu-components/UploadProgressModal'
import SelectPrepareFileModal from '@/bu-components/SelectPrepareFileModal'
import CopyFileModal from '@/bu-components/CopyFileModal'
import ManagingMembersModal from '@/bu-components/ManagingMembersModal'
import PreviewFileModal from '@/bu-components/PreviewFileModal'
import { YZ_APPId, YZ_PREVIEW_URL, OFFICE_PREVIEW_URL } from '@/domains/basic-domain/constants'
import BaseService from '@/domains/basic-domain/baseService'
import ScanFileModal from '../modal/ScanFileModal'
import CreateFolderModal from '../modal/CreateFolderModal'
import User from '@/common/js/user'
import axios from 'axios'
const appId = 'yozoqvpO2Hvz8346'
const DEL_FOLDER_URL_MAP = {
'MYSELF': 'public/hadesStore/delFolder',
'COMMON': 'public/hadesStore/delFolder'
MYSELF: 'public/hadesStore/delFolder',
COMMON: 'public/hadesStore/delFolder',
}
// 支持本地上传的文件类型
const loaclFileType = SUPPORT_FILE_TYPE_MAP.join(',');
const loaclFileType = SUPPORT_FILE_TYPE_MAP.join(',')
let count = 0;
let count = 0
class FolderList extends React.Component {
constructor(props) {
super(props);
super(props)
this.state = {
localFileList: [], // 本地文件列表(待上传)
currentFolder: {}, // 当前文件/文件夹(操作列表中的文件/文件夹的时候需要用到)
......@@ -55,26 +54,26 @@ class FolderList extends React.Component {
showManagingModal: false, // 管理文件查看编辑权限
nonCompliantFileList: [], // 不符合上限的文件列表
parentRights: '', // 继承父级文件夹权限
showPreviewModal:false, //是否显示loading
previewing:false, //是否正在预览
previewStatus:'UPLOAD' //预览文件的生成状态
showPreviewModal: false, //是否显示loading
previewing: false, //是否正在预览
previewStatus: 'UPLOAD', //预览文件的生成状态
}
}
componentWillReceiveProps(nextProps) {
const { folderPathList } = nextProps
const currentFolder = folderPathList[folderPathList.length - 1];
const currentFolder = folderPathList[folderPathList.length - 1]
this.setState({
currentFolder
currentFolder,
})
}
//预览文件
handleSelect = (folder) => {
// 只有文件才有预览功能
if (folder.folderType === 'FOLDER') {
this.handleSelectFolder(folder);
this.handleSelectFolder(folder)
} else {
this.handleScanFile(folder);
this.handleScanFile(folder)
}
}
......@@ -82,52 +81,52 @@ class FolderList extends React.Component {
handleDataDot = (folderFormat) => {
switch (folderFormat) {
case 'PDF':
window.WEBTRACING('resource_disk_file_preview_pdf', '资料云盘_点击预览_pdf');
break;
window.WEBTRACING('resource_disk_file_preview_pdf', '资料云盘_点击预览_pdf')
break
case 'WORD':
case 'DOCX':
case 'DOC':
window.WEBTRACING('resource_disk_file_preview_word', '资料云盘_点击预览_word');
break;
window.WEBTRACING('resource_disk_file_preview_word', '资料云盘_点击预览_word')
break
case 'EXCEL':
window.WEBTRACING('resource_disk_file_preview_excel', '资料云盘_点击预览_excel');
break;
window.WEBTRACING('resource_disk_file_preview_excel', '资料云盘_点击预览_excel')
break
case 'PPT':
case 'PPTX':
window.WEBTRACING('resource_disk_file_preview_ppt', '资料云盘_点击预览_ppt');
break;
window.WEBTRACING('resource_disk_file_preview_ppt', '资料云盘_点击预览_ppt')
break
default:
break;
break
}
}
handleYZPreviewDataDot =(folderFormat) => {
handleYZPreviewDataDot = (folderFormat) => {
switch (folderFormat) {
case 'PDF':
window.WEBTRACING('resource_disk_yz_file_preview_pdf', '资料云盘_点击永中预览_pdf');
break;
window.WEBTRACING('resource_disk_yz_file_preview_pdf', '资料云盘_点击永中预览_pdf')
break
case 'WORD':
case 'DOCX':
case 'DOC':
window.WEBTRACING('resource_disk_yz_file_preview_word', '资料云盘_点击永中预览_word');
break;
window.WEBTRACING('resource_disk_yz_file_preview_word', '资料云盘_点击永中预览_word')
break
case 'EXCEL':
window.WEBTRACING('resource_disk_yz_file_preview_excel', '资料云盘_点击永中预览_excel');
break;
window.WEBTRACING('resource_disk_yz_file_preview_excel', '资料云盘_点击永中预览_excel')
break
case 'PPT':
case 'PPTX':
window.WEBTRACING('resource_disk_yz_file_preview_ppt', '资料云盘_点击永中预览_ppt');
break;
window.WEBTRACING('resource_disk_yz_file_preview_ppt', '资料云盘_点击永中预览_ppt')
break
default:
break;
break
}
}
// 预览文件
handleScanFile = async (folder) => {
const { folderFormat, folderSize, ossUrl,rights,fileVersionId,id,folderName} = folder;
const {currentRootDisk } = this.props;
const { folderFormat, folderSize, ossUrl, rights, fileVersionId, id, folderName } = folder
const { currentRootDisk } = this.props
//如果是公共文件且只有查看的权限的用户的预览对接的三方是永中
const that = this;
if(currentRootDisk.disk==="COMMON" && rights==="LOOK"){
const that = this
if (currentRootDisk.disk === 'COMMON' && rights === 'LOOK') {
switch (folderFormat) {
case 'PDF':
case 'WORD':
......@@ -136,155 +135,160 @@ class FolderList extends React.Component {
case 'EXCEL':
case 'PPT':
case 'PPTX':
that.handleYZPreviewDataDot(folderFormat);
if(!fileVersionId){
this.setState({
previewing:true,
showPreviewModal:true,
previewStatus:'UPLOAD'
},async ()=>{
const uploadParams ={
fileUrl:ossUrl,
instId:User.getStoreId(),
yoZoTypeEnum:'UPLOAD'
}
const uploadSign = await BaseService.getYoZoSign(uploadParams);
BaseService.yoZoUpload(ossUrl,YZ_APPId,uploadSign).then(async function (response){
const saveParams ={
fileVersionId:response.data.data.fileVersionId,
folderId:id,
instId:User.getStoreId(),
}
BaseService.saveYoZoFileVersionId(saveParams);
const { previewing } = that.state;
if(previewing){
const previewParams ={
fileVersionId:response.data.data.fileVersionId,
instId:User.getStoreId(),
yoZoTypeEnum:'VIEW',
htmlTitle:folderName
}
const previewSign = await BaseService.getYoZoSign(previewParams);
that.handleYZPreviewDataDot(folderFormat)
if (!fileVersionId) {
this.setState(
{
previewing: true,
showPreviewModal: true,
previewStatus: 'UPLOAD',
},
async () => {
const uploadParams = {
fileUrl: ossUrl,
instId: User.getStoreId(),
yoZoTypeEnum: 'UPLOAD',
}
const uploadSign = await BaseService.getYoZoSign(uploadParams)
BaseService.yoZoUpload(ossUrl, YZ_APPId, uploadSign).then(async function (response) {
const saveParams = {
fileVersionId: response.data.data.fileVersionId,
folderId: id,
instId: User.getStoreId(),
}
BaseService.saveYoZoFileVersionId(saveParams)
const { previewing } = that.state
if (previewing) {
const previewParams = {
fileVersionId: response.data.data.fileVersionId,
instId: User.getStoreId(),
yoZoTypeEnum: 'VIEW',
htmlTitle: folderName,
}
const previewSign = await BaseService.getYoZoSign(previewParams)
const url = `${YZ_PREVIEW_URL}?fileVersionId=${response.data.data.fileVersionId}&appId=${YZ_APPId}&sign=${previewSign}&htmlTitle=${folderName}`
that.setState({
previewStatus:'UPLOAD_SUCCESS',
url
previewStatus: 'UPLOAD_SUCCESS',
url,
})
}
})
})
}else{
const previewParams ={
}
)
} else {
const previewParams = {
fileVersionId,
instId:User.getStoreId(),
yoZoTypeEnum:'VIEW',
htmlTitle:folderName
instId: User.getStoreId(),
yoZoTypeEnum: 'VIEW',
htmlTitle: folderName,
}
const previewSign = await BaseService.getYoZoSign(previewParams);
const previewSign = await BaseService.getYoZoSign(previewParams)
const url = `${YZ_PREVIEW_URL}?fileVersionId=${fileVersionId}&appId=${YZ_APPId}&sign=${previewSign}&htmlTitle=${folderName}`
const a = document.createElement('a');
document.body.appendChild(a);
a.setAttribute('href', url);
a.setAttribute('target', '_blank');
a.click();
const a = document.createElement('a')
document.body.appendChild(a)
a.setAttribute('href', url)
a.setAttribute('target', '_blank')
a.click()
document.body.removeChild(a)
}
break;
break
default:
const scanFileModal = (
<ScanFileModal
fileType={folderFormat}
item={folder}
close={() => {
this.setState({ scanFileModal: null });
this.setState({ scanFileModal: null })
}}
/>
);
this.setState({ scanFileModal });
break;
)
this.setState({ scanFileModal })
break
}
}else{
} else {
switch (folderFormat) {
case 'PDF':
window.open(ossUrl, "_blank");
break;
case "WORD":
case "DOCX":
case "DOC":
case "EXCEL":
case "PPT":
case "PPTX":
case "PDF":
if ((folderFormat === 'PPT' || folderFormat === 'PPTX' ||
folderFormat === 'DOCX' || folderFormat === 'WORD' ||
folderFormat === 'DOC') && folderSize > 10 * DEFAULT_SIZE_UNIT) {
window.open(ossUrl, '_blank')
break
case 'WORD':
case 'DOCX':
case 'DOC':
case 'EXCEL':
case 'PPT':
case 'PPTX':
case 'PDF':
if (
(folderFormat === 'PPT' || folderFormat === 'PPTX' || folderFormat === 'DOCX' || folderFormat === 'WORD' || folderFormat === 'DOC') &&
folderSize > 10 * DEFAULT_SIZE_UNIT
) {
Modal.confirm({
title: '抱歉,不能在线预览',
content: '由于文件较大,不支持在线预览,请下载后再查看',
okText: "下载",
okText: '下载',
onOk: () => {
const a = document.createElement('a');
a.href = ossUrl;
a.click();
}
});
break;
const a = document.createElement('a')
a.href = ossUrl
a.click()
},
})
break
}
const prefixUrl = `${OFFICE_PREVIEW_URL}?src=`;
const prefixUrl = `${OFFICE_PREVIEW_URL}?src=`
const scanUrl = `${prefixUrl}${encodeURIComponent(ossUrl)}`
window.open(scanUrl, "_blank");
break;
window.open(scanUrl, '_blank')
break
default:
const scanFileModal = <ScanFileModal
const scanFileModal = (
<ScanFileModal
fileType={folderFormat}
item={folder}
close={() => {
this.setState({ scanFileModal: null })
}}
/>
this.setState({ scanFileModal });
break;
)
this.setState({ scanFileModal })
break
}
}
// 预览文件埋点
this.handleDataDot(folderFormat);
this.handleDataDot(folderFormat)
}
cancelPreview = ()=>{
cancelPreview = () => {
this.setState({
previewing:false,
showPreviewModal:false,
previewStatus:'UPLOAD'
previewing: false,
showPreviewModal: false,
previewStatus: 'UPLOAD',
})
}
// 选择文件夹
handleSelectFolder = (folder) => {
const { folderPathList, showResultPage, currentRootDisk } = this.props;
const { folderPathList, showResultPage, currentRootDisk } = this.props
// 判断是否是员工文件的根目录
const employeeDisk = currentRootDisk.disk === 'EMPLOYEE' && folderPathList.length === 1;
const employeeDisk = currentRootDisk.disk === 'EMPLOYEE' && folderPathList.length === 1
if (showResultPage) {
folderPathList.pop();
folderPathList.pop()
}
folderPathList.push({
id: folder.id,
folderName: folder.folderName
});
folderName: folder.folderName,
})
this.setState({
parentRights: folder.rights,
})
this.props.onChangeFolderPath(folderPathList);
this.props.onChangeFolderPath(folderPathList)
this.props.onRefresh({
parentId: folder.id,
parentRights: folder.rights,
folderIdType: employeeDisk ? 'USER' : 'FOLDER'
});
folderIdType: employeeDisk ? 'USER' : 'FOLDER',
})
}
// 修改文件路径
handleChangeFolderPath = (folder) => {
const { instId } = window.currentUserInstInfo;
const { id } = folder;
const { currentRootDisk } = this.props;
const { instId } = window.currentUserInstInfo
const { id } = folder
const { currentRootDisk } = this.props
const params = {
id,
instId,
......@@ -292,16 +296,16 @@ class FolderList extends React.Component {
}
Service.Hades('public/hadesStore/folderPath', params).then((res) => {
const { result = [] } = res;
this.props.onChangeFolderPath(result, false);
const { result = [] } = res
this.props.onChangeFolderPath(result, false)
})
}
parseColumns = () => {
const { currentRootDisk, showResultPage, folderPathList } = this.props;
const hasManagementAuthority = currentRootDisk.uploadPower;
const { currentRootDisk, showResultPage, folderPathList } = this.props
const hasManagementAuthority = currentRootDisk.uploadPower
// 判断是否是员工文件的根目录
const employeeDisk = currentRootDisk.disk === 'EMPLOYEE' && folderPathList.length === 1;
const employeeDisk = currentRootDisk.disk === 'EMPLOYEE' && folderPathList.length === 1
const columns = [
{
......@@ -309,81 +313,66 @@ class FolderList extends React.Component {
key: 'folderName',
dataIndex: 'folderName',
width: '28%',
sorter: (employeeDisk || !hasManagementAuthority) ? false : true,
sorter: employeeDisk || !hasManagementAuthority ? false : true,
render: (value, record) => {
const { folderType, folderFormat } = record;
const isFolder = folderType === 'FOLDER';
let imgSrc = !isFolder ?
FILE_TYPE_ICON_MAP[folderFormat] :
'https://xiaomai-image.oss-cn-hangzhou.aliyuncs.com/1594871430788.png';
const { folderType, folderFormat } = record
const isFolder = folderType === 'FOLDER'
let imgSrc = !isFolder ? FILE_TYPE_ICON_MAP[folderFormat] : 'https://xiaomai-image.oss-cn-hangzhou.aliyuncs.com/1594871430788.png'
if (employeeDisk) {
imgSrc = 'https://xiaomai-image.oss-cn-hangzhou.aliyuncs.com/1594871440736.png'
}
return (
<div
className="file-name"
onClick={() => this.handleSelect(record)}
>
{
<img
alt="img-src"
className="file-name__icon"
src={imgSrc}
/>
}
<span
className={`file-name__text ${!isFolder ? 'highlight' : ''}`}
>
{value}
</span>
<div className='file-name' onClick={() => this.handleSelect(record)}>
{<img alt='img-src' className='file-name__icon' src={imgSrc} />}
<span className={`file-name__text ${!isFolder ? 'highlight' : ''}`}>{value}</span>
</div>
)
}
},
},
{
title: '更新时间',
key: 'updated',
dataIndex: 'updated',
sorter: (employeeDisk || !hasManagementAuthority) ? false : true,
sorter: employeeDisk || !hasManagementAuthority ? false : true,
render: (value) => {
return <span>{formatDate('YYYY-MM-DD H:i', value)}</span>
}
},
},
{
title: '大小',
key: 'folderSize',
dataIndex: 'folderSize',
width: '10%',
sorter: (employeeDisk || !hasManagementAuthority) ? false : true,
sorter: employeeDisk || !hasManagementAuthority ? false : true,
render: (value, record) => {
const { folderType } = record;
const _fileSize = Number(value);
let _size = `${(_fileSize / DEFAULT_SIZE_UNIT).toFixed(1)}M`;
const { folderType } = record
const _fileSize = Number(value)
let _size = `${(_fileSize / DEFAULT_SIZE_UNIT).toFixed(1)}M`
if (_fileSize < 0.1 * DEFAULT_SIZE_UNIT) {
_size = `${(_fileSize / 1024).toFixed(1)}kb`;
}
return (
<span>{folderType === 'FILE' ? _size : '-'}</span>
)
_size = `${(_fileSize / 1024).toFixed(1)}kb`
}
return <span>{folderType === 'FILE' ? _size : '-'}</span>
},
},
{
title: '操作',
key: 'operate',
render: (value, record) => {
if ((!(currentRootDisk.disk === 'COMMON' && (folderPathList.length === 1 || record.folderType === 'FOLDER')) ||
hasManagementAuthority) && !(record.rights==="LOOK") ){
if (
(!(currentRootDisk.disk === 'COMMON' && (folderPathList.length === 1 || record.folderType === 'FOLDER')) || hasManagementAuthority) &&
!(record.rights === 'LOOK')
) {
return (
<Dropdown overlay={this.renderMenu(record)} trigger={['hover']}>
<span className="icon iconfont">&#xe62c;</span>
<span className='icon iconfont'>&#xe62c;</span>
</Dropdown>
)
}
return <span>-</span>
}
}
},
},
]
// 公共文件需要显示创建者
......@@ -391,8 +380,8 @@ class FolderList extends React.Component {
columns.splice(1, 0, {
title: '创建者',
key: 'createName',
dataIndex: 'createName'
});
dataIndex: 'createName',
})
}
// 搜索结果需要显示所在目录
......@@ -402,38 +391,39 @@ class FolderList extends React.Component {
key: 'parentName',
dataIndex: 'parentName',
render: (value, record) => {
return <span
className="file-path"
onClick={() => this.handleChangeFolderPath(record)}
>
return (
<span className='file-path' onClick={() => this.handleChangeFolderPath(record)}>
{value || currentRootDisk.folderName}
</span>
}
)
},
})
}
return columns;
return columns
}
// 删除文件
handleDeleteFolder = (folder) => {
const { currentRootDisk: { disk } } = this.props;
const {
currentRootDisk: { disk },
} = this.props
Modal.confirm({
title: '确认删除所选的文件吗?',
content: '删除后,数据将无法恢复。',
icon:<span className="icon iconfont default-confirm-icon">&#xe839; </span>,
icon: <span className='icon iconfont default-confirm-icon'>&#xe839; </span>,
okType: 'danger',
onOk: () => {
const { currentFolder } = this.state;
const { currentFolder } = this.state
Service.Hades(DEL_FOLDER_URL_MAP[disk], {
operatorId: User.getUserId(),
storeId: User.getStoreId(),
ids: [folder.id],
}).then(() => {
message.success('删除成功');
this.props.onRefresh({ parentId: currentFolder.id || null });
message.success('删除成功')
this.props.onRefresh({ parentId: currentFolder.id || null })
})
},
})
}
});
}
// 重命名
......@@ -443,90 +433,90 @@ class FolderList extends React.Component {
visible: true,
id: folder.id,
folderName: folder.folderName,
}
});
},
})
}
// 重命名完成或者取消重命名之后隐藏重命名弹窗
handleRenameDone = (folderName) => {
return new Promise((resolve) => {
const { renameModalData, currentFolder } = this.state;
const { folderPathList } = this.props;
const { renameModalData, currentFolder } = this.state
const { folderPathList } = this.props
// 名称未修改不发送请求
if (folderName === renameModalData.folderName) {
this.setState({ renameModalData: {} });
return;
this.setState({ renameModalData: {} })
return
}
// 判断是否有同名文件
this.handleGetSameNameFiles(folderName).then((res) => {
if ((!!res) || (res && Object.keys(res).length)) {
if (!!res || (res && Object.keys(res).length)) {
if (!res.isLook && folderPathList.length === 1) {
message.warning('此目录下已存在同名文件,有疑问请联系机构校长');
message.warning('此目录下已存在同名文件,有疑问请联系机构校长')
} else {
message.warning('此目录下已存在同名文件');
message.warning('此目录下已存在同名文件')
}
return;
return
}
Service.Hades('public/hadesStore/renameFolder', {
id: renameModalData.id,
name: folderName
}).then(res2 => {
name: folderName,
}).then((res2) => {
if (!res2.success) {
const errorMessage = '此目录下已存在同名文件';
message.warning(errorMessage);
return;
const errorMessage = '此目录下已存在同名文件'
message.warning(errorMessage)
return
} else {
message.success('重命名成功');
this.setState({ renameModalData: {} });
this.props.onRefresh({ parentId: currentFolder.id || null });
message.success('重命名成功')
this.setState({ renameModalData: {} })
this.props.onRefresh({ parentId: currentFolder.id || null })
}
});
});
})
})
})
}
// 获取同名文件
handleGetSameNameFiles = async (folderName) => {
const { currentRootDisk, folderPathList } = this.props;
const currentFolder = folderPathList[folderPathList.length - 1];
const { instId } = window.currentUserInstInfo;
const { currentRootDisk, folderPathList } = this.props
const currentFolder = folderPathList[folderPathList.length - 1]
const { instId } = window.currentUserInstInfo
const params = {
createId:User.getUserId(),
createId: User.getUserId(),
name: folderName,
disk: currentRootDisk.disk,
parentId: currentFolder.id,
folderType: 'FOLDER',
}
const res = await Service.Hades('public/hadesStore/sameNameFile', params);
const { result } = res;
return result;
const res = await Service.Hades('public/hadesStore/sameNameFile', params)
const { result } = res
return result
}
// 显示移动文件弹窗
handleShowSelectFileModal = (file) => {
this.setState({
currentFile: file,
showSelectFileModal: true
});
showSelectFileModal: true,
})
}
// 显示复制文件弹窗
handleShowCopyFileModal = (file) => {
this.setState({
currentFile: file,
showCopyFileModal: true
});
showCopyFileModal: true,
})
}
// 显示管理成员弹窗
handleShowManagingModal = (file) => {
this.setState({
currentFile: file,
showManagingModal: true
});
showManagingModal: true,
})
}
getBlob = (url) => {
......@@ -584,40 +574,40 @@ class FolderList extends React.Component {
// return;
// }
const dom = document.querySelector('#detailFileInput');
dom.click();
const dom = document.querySelector('#detailFileInput')
dom.click()
}
// 准备上传
handleUpload = (event) => {
const fileList = event.target.files;
const fileList = event.target.files
// 判断文件的大小是否超出了限制
const nonCompliantFileList = [];
const _fileList = [...fileList];
const nonCompliantFileList = []
const _fileList = [...fileList]
_fileList.map((file, index) => {
let { size, type, name } = file;
let { size, type, name } = file
if (!type) {
type = getFileTypeByName(name);
type = getFileTypeByName(name)
}
if (type.indexOf('image') > -1 && size > 50 * DEFAULT_SIZE_UNIT) {
nonCompliantFileList.push(file);
_fileList.splice(index, 1);
nonCompliantFileList.push(file)
_fileList.splice(index, 1)
}
if (type.indexOf('audio') > -1 && size > 50 * DEFAULT_SIZE_UNIT) {
nonCompliantFileList.push(file);
_fileList.splice(index, 1);
nonCompliantFileList.push(file)
_fileList.splice(index, 1)
}
if (type.indexOf('video') > -1 && size > 2000 * DEFAULT_SIZE_UNIT) {
nonCompliantFileList.push(file);
_fileList.splice(index, 1);
nonCompliantFileList.push(file)
_fileList.splice(index, 1)
}
if (loaclFileType.indexOf(type) > -1 && size > 100 * DEFAULT_SIZE_UNIT) {
nonCompliantFileList.push(file);
_fileList.splice(index, 1);
nonCompliantFileList.push(file)
_fileList.splice(index, 1)
}
file.key = count++;
return file;
});
file.key = count++
return file
})
// 不符合规则的文件列表
if (nonCompliantFileList.length > 0) {
this.setState({
......@@ -625,38 +615,38 @@ class FolderList extends React.Component {
showNonCompliantFileModal: true,
})
} else {
this.handleShowUploadModal(_fileList);
this.handleShowUploadModal(_fileList)
}
// 清空文件,防止第二次无法上传同一个文件
const dom = document.querySelector('#detailFileInput');
dom.value = '';
const dom = document.querySelector('#detailFileInput')
dom.value = ''
}
// 显示上传进度弹窗
handleShowUploadModal = (fileList) => {
// 保存当前路径
const { folderPathList } = this.props;
const { folderPathList } = this.props
if (fileList.length) {
this.setState({
showUploadModal: true,
localFileList: fileList,
uploadFolderPath: folderPathList[folderPathList.length - 1]
});
uploadFolderPath: folderPathList[folderPathList.length - 1],
})
}
}
// 上传成功
handleUploadDone = (file, resourceId) => {
this.props.onCreate(file, resourceId);
this.props.onCreate(file, resourceId)
}
// 取消上传
handleHiddenUploadModal = () => {
this.setState({
showUploadModal: false,
localFileList: []
});
localFileList: [],
})
}
// 余额欠费提示弹窗
......@@ -664,111 +654,123 @@ class FolderList extends React.Component {
Modal.info({
title: '无法继续操作',
content: '直播系统已升级,请联系运营老师。',
icon: <span className="icon iconfont default-confirm-icon">&#xe6f4;</span>
icon: <span className='icon iconfont default-confirm-icon'>&#xe6f4;</span>,
})
}
// 排序
handleChangeTable = (pagination, filters, sorter) => {
const { columnKey, order } = sorter;
let sort = null;
if (columnKey === 'folderName' && order === 'ascend') { sort = 'NAME_ASC'; }
if (columnKey === 'folderName' && order === 'descend') { sort = 'NAME_DESC'; }
if (columnKey === 'folderSize' && order === 'ascend') { sort = 'SIZE_ASC'; }
if (columnKey === 'folderSize' && order === 'descend') { sort = 'SIZE_DESC'; }
if (columnKey === 'updated' && order === 'ascend') { sort = 'UPDATE_ASC'; }
if (columnKey === 'updated' && order === 'descend') { sort = 'UPDATE_DESC'; }
const { columnKey, order } = sorter
let sort = null
if (columnKey === 'folderName' && order === 'ascend') {
sort = 'NAME_ASC'
}
if (columnKey === 'folderName' && order === 'descend') {
sort = 'NAME_DESC'
}
if (columnKey === 'folderSize' && order === 'ascend') {
sort = 'SIZE_ASC'
}
if (columnKey === 'folderSize' && order === 'descend') {
sort = 'SIZE_DESC'
}
if (columnKey === 'updated' && order === 'ascend') {
sort = 'UPDATE_ASC'
}
if (columnKey === 'updated' && order === 'descend') {
sort = 'UPDATE_DESC'
}
const { currentFolder } = this.state;
const { currentFolder } = this.state
this.props.onRefresh({
sort,
parentId: currentFolder.id || null
});
parentId: currentFolder.id || null,
})
}
// 操作选项
renderMenu = (record) => {
const { currentRootDisk } = this.props;
const { currentRootDisk } = this.props
// 是否有编辑权限
const hasManagementAuthority = currentRootDisk.uploadPower;
const hasManagementAuthority = currentRootDisk.uploadPower
// 公共文件权限和复制权限
const { folderType, rights } = record;
const { folderType, rights } = record
const menu = (
<Menu>
{
rights === "EDIT" && !record.parentId &&
[
<Menu.Item key="administration">
{rights === 'EDIT' &&
!record.parentId && [
<Menu.Item key='administration'>
<span onClick={() => this.handleShowManagingModal(record)}>权限管理</span>
</Menu.Item>,
<Menu.Divider key="administration-bottom"/>
]
}
{(folderType === 'FILE' && (rights === "LOOK_DOWNLOAD" || rights === 'EDIT') ) &&
<Menu.Item key="download">
<span onClick={() => { this.handleDownload(record) }}>下载</span>
<Menu.Divider key='administration-bottom' />,
]}
{folderType === 'FILE' && (rights === 'LOOK_DOWNLOAD' || rights === 'EDIT') && (
<Menu.Item key='download'>
<span
onClick={() => {
this.handleDownload(record)
}}>
下载
</span>
</Menu.Item>
}
{(rights === "LOOK_DOWNLOAD" || rights === 'EDIT') &&
<Menu.Item key="copy">
)}
{(rights === 'LOOK_DOWNLOAD' || rights === 'EDIT') && (
<Menu.Item key='copy'>
<span onClick={() => this.handleShowCopyFileModal(record)}>复制到</span>
</Menu.Item>
}
{
hasManagementAuthority && rights === "EDIT" &&
[
<Menu.Item key="move">
)}
{hasManagementAuthority &&
rights === 'EDIT' && [
<Menu.Item key='move'>
<span onClick={() => this.handleShowSelectFileModal(record)}>移动到</span>
</Menu.Item>,
<Menu.Item key="rename">
<Menu.Item key='rename'>
<span onClick={() => this.handleRename(record)}>重命名</span>
</Menu.Item>,
<Menu.Divider key="administration-top"/>,
<Menu.Item key="delete">
<Menu.Divider key='administration-top' />,
<Menu.Item key='delete'>
<span onClick={() => this.handleDeleteFolder(record)}>删除</span>
</Menu.Item>
]
}
</Menu.Item>,
]}
</Menu>
);
return menu;
)
return menu
}
render() {
const {
currentFolder, currentFile, renameModalData, showSelectFileModal,
showUploadModal, localFileList, showCopyFileModal, showManagingModal,
showPreviewModal, previewStatus,url
} = this.state;
const {
selectedFileIds, folderList, showResultPage,
currentRootDisk, query, totalCount, folderPathList
} = this.props;
const _disk = folderPathList[0].disk;
currentFolder,
currentFile,
renameModalData,
showSelectFileModal,
showUploadModal,
localFileList,
showCopyFileModal,
showManagingModal,
showPreviewModal,
previewStatus,
url,
} = this.state
const { selectedFileIds, folderList, showResultPage, currentRootDisk, query, totalCount, folderPathList } = this.props
const _disk = folderPathList[0].disk
// 是否有编辑权限
const hasManagementAuthority = currentRootDisk.uploadPower;
const hasManagementAuthority = currentRootDisk.uploadPower
return (
<div className="file-list">
<div className='file-list'>
<Choose>
<When condition={!_.isEmpty(folderList)}>
<Table
key="table"
key='table'
rowKey={(record) => record.id}
columns={this.parseColumns()}
showSorterTooltip={false}
dataSource={folderList}
rowSelection={
{
rowSelection={{
selectedRowKeys: selectedFileIds,
onChange: this.props.onChangeRow
}
}
onChange: this.props.onChangeRow,
}}
pagination={false}
onChange={this.handleChangeTable}
/>
......@@ -778,42 +780,43 @@ class FolderList extends React.Component {
total={totalCount}
showSizeChanger={true}
toPage={(page) => {
this.props.onChangePage('current', page + 1);
this.props.onChangePage('current', page + 1)
}}
onShowSizeChange={(current, size) => {
const that = this;
setTimeout(()=>{
const that = this
setTimeout(() => {
this.props.onChangePage('size', size)
},1000)
}, 1000)
}}
/>
</When>
<Otherwise>
<XMTable
className="add-empty"
className='add-empty'
renderEmpty={{
image: !showResultPage ? addData : search,
description: <Choose>
description: (
<Choose>
<When condition={!showResultPage}>
<input
multiple
type="file"
type='file'
style={{ display: 'none' }}
id="detailFileInput"
accept=".ppt,.pptx,.doc,.docx,.pdf,.jpg,.jpeg,.png,.mp3,.mp4,.xlsx,.xls"
id='detailFileInput'
accept='.ppt,.pptx,.doc,.docx,.pdf,.jpg,.jpeg,.png,.mp3,.mp4,.xlsx,.xls'
onChange={(e) => this.handleUpload(e)}
/>
{
<Choose>
<When condition={hasManagementAuthority}>
<div className="lottie-icon-title">你还没有上传文件,点击
<Tooltip title="支持文件类型:ppt、word、excel、pdf、jpg、mp3、mp4,上传后默认私密,可邀请其他成员协作,支持批量上传文件">
<span
className="upload-btn"
onClick={this.handleChooseFile}
>上传文件</span>
<div className='lottie-icon-title'>
你还没有上传文件,点击
<Tooltip title='支持文件类型:ppt、word、excel、pdf、jpg、mp3、mp4,上传后默认私密,可邀请其他成员协作,支持批量上传文件'>
<span className='upload-btn' onClick={this.handleChooseFile}>
上传文件
</span>
</Tooltip>
按钮
</div>
......@@ -825,9 +828,10 @@ class FolderList extends React.Component {
}
</When>
<Otherwise>
<div className="desc">搜索无结果</div>
<div className='desc'>搜索无结果</div>
</Otherwise>
</Choose>
),
}}
/>
</Otherwise>
......@@ -839,12 +843,11 @@ class FolderList extends React.Component {
folderPathList={folderPathList}
isOpen={renameModalData.visible}
onClose={() => {
this.setState({ renameModalData: {} });
this.setState({ renameModalData: {} })
}}
onOk={this.handleRenameDone}
/>
<UploadProgressModal
isOpen={showUploadModal}
currentFolder={currentFolder}
......@@ -857,43 +860,39 @@ class FolderList extends React.Component {
isOpen={showSelectFileModal}
currentRootDisk={currentRootDisk}
onClose={() => {
this.setState({ showSelectFileModal: false });
this.setState({ showSelectFileModal: false })
}}
onMove={(query) => {
this.setState({ showSelectFileModal: false });
this.props.onMove(query, [currentFile.id],[currentFile.folderType]);
this.setState({ showSelectFileModal: false })
this.props.onMove(query, [currentFile.id], [currentFile.folderType])
}}
/>
{
showCopyFileModal &&
{showCopyFileModal && (
<CopyFileModal
isOpen={showCopyFileModal}
dataInfo={currentFile}
currentRootDisk={currentRootDisk}
onClose={() => {
this.setState({ showCopyFileModal: false });
this.setState({ showCopyFileModal: false })
}}
/>
}
{
showManagingModal &&
)}
{showManagingModal && (
<ManagingMembersModal
isOpen={showManagingModal}
dataInfo={currentFile}
disk={_disk}
onClose={() => {
this.setState({ showManagingModal: false });
this.setState({ showManagingModal: false })
}}
/>
}
{ showPreviewModal &&
<PreviewFileModal onCancel={()=>this.cancelPreview()} previewStatus={previewStatus} url={url}/>
}
{ this.state.scanFileModal }
{ this.state.chargeModal }
)}
{showPreviewModal && <PreviewFileModal onCancel={() => this.cancelPreview()} previewStatus={previewStatus} url={url} />}
{this.state.scanFileModal}
{this.state.chargeModal}
</div>
)
}
}
export default FolderList;
\ No newline at end of file
export default FolderList
import React from 'react';
import Service from '@/common/js/service';
import { DISK_MAP } from '@/domains/resource-disk/constants';
import FolderManage from './components/FolderManage';
import DiskList from './components/DiskList';
import './index.less';
import React from 'react'
import Service from '@/common/js/service'
import { DISK_MAP } from '@/domains/resource-disk/constants'
import FolderManage from './components/FolderManage'
import DiskList from './components/DiskList'
import './index.less'
const defaultRootDisk = {
folderName: '公共文件',
disk: 'COMMON',
uploadPower: true
uploadPower: true,
}
class PrepareLessonPage extends React.Component {
constructor(props) {
super(props);
super(props)
this.state = {
// 目前只有公共文件,先由前端定义
diskList: [
{
folderName: '公共文件',
disk: 'COMMON',
uploadPower: true
}
uploadPower: true,
},
], // 可见磁盘目录
currentRootDisk: defaultRootDisk
currentRootDisk: defaultRootDisk,
}
}
handleChangeDisk = (disk) => {
this.setState({
currentRootDisk: disk
});
currentRootDisk: disk,
})
}
render() {
const { currentRootDisk, diskList } = this.state;
console.log('currentRootDisk',currentRootDisk);
const { currentRootDisk, diskList } = this.state
console.log('currentRootDisk', currentRootDisk)
return (
<div className="prepare-lesson-page page">
<div className="content-header">资料云盘</div>
<div className="box content-body">
<DiskList
diskList={diskList}
currentRootDisk={currentRootDisk}
onChange={this.handleChangeDisk}
/>
<FolderManage
currentRootDisk={currentRootDisk}
/>
<div className='prepare-lesson-page page'>
<div className='content-header'>素材库</div>
<div className='box content-body'>
<DiskList diskList={diskList} currentRootDisk={currentRootDisk} onChange={this.handleChangeDisk} />
<FolderManage currentRootDisk={currentRootDisk} />
</div>
</div>
)
}
}
export default PrepareLessonPage;
\ No newline at end of file
export default PrepareLessonPage
......@@ -5,37 +5,37 @@
* @LastEditTime: 2021-05-13 16:39:51
* @Description: 内容线路由配置
*/
import Home from '@/modules/home/Home';
import EmployeesManagePage from '@/modules/store-manage/EmployeesManagePage';
import EmployeeManage from '@/modules/college-manage/EmployeeManage';
import personalInfoPage from '@/modules/personalInfo';
import UserManagePage from '@/modules/store-manage/UserManagePage';
import UserManage from '@/modules/college-manage/UserManagePage';
import StoreDecorationPage from '@/modules/store-manage/StoreDecorationPage';
import CourseCatalogPage from '@/modules/store-manage/CourseCatalogPage';
import LiveCoursePage from '@/modules/course-manage/LiveCoursePage';
import AddLivePage from '@/modules/course-manage/AddLive';
import VideoCoursePage from '@/modules/course-manage/video-course';
import GraphicsCoursePage from '@/modules/course-manage/graphics-course';
import OfflineCoursePage from '@/modules/course-manage/offline-course';
import AddVideoCoursePage from '@/modules/course-manage/video-course/AddVideoCourse';
import AddGraphicsCoursePage from '@/modules/course-manage/graphics-course/AddGraphicsCourse';
import AddOfflineCoursePage from '@/modules/course-manage/offline-course/AddOfflineCourse';
import Home from '@/modules/home/Home'
import EmployeesManagePage from '@/modules/store-manage/EmployeesManagePage'
import EmployeeManage from '@/modules/college-manage/EmployeeManage'
import personalInfoPage from '@/modules/personalInfo'
import UserManagePage from '@/modules/store-manage/UserManagePage'
import UserManage from '@/modules/college-manage/UserManagePage'
import StoreDecorationPage from '@/modules/store-manage/StoreDecorationPage'
import CourseCatalogPage from '@/modules/store-manage/CourseCatalogPage'
import LiveCoursePage from '@/modules/course-manage/LiveCoursePage'
import AddLivePage from '@/modules/course-manage/AddLive'
import VideoCoursePage from '@/modules/course-manage/video-course'
import GraphicsCoursePage from '@/modules/course-manage/graphics-course'
import OfflineCoursePage from '@/modules/course-manage/offline-course'
import AddVideoCoursePage from '@/modules/course-manage/video-course/AddVideoCourse'
import AddGraphicsCoursePage from '@/modules/course-manage/graphics-course/AddGraphicsCourse'
import AddOfflineCoursePage from '@/modules/course-manage/offline-course/AddOfflineCourse'
// import DataList from '@/modules/course-manage/DataList/DataList';
// import ClassBook from '@/modules/resource-disk';
import ResourceDisk from '@/modules/resource-disk';
import SwitchRoute from '@/modules/root/SwitchRoute';
import PlanPage from '@/modules/plan-manage/PlanPage';
import AddPlanPage from '@/modules/plan-manage/AddPlan';
import LearningDataPage from '@/modules/plan-manage/LearningData';
import StoreInfoPage from '@/modules/store-manage/StoreInfo';
import CourseCategoryManage from '@/modules/teach-tool/components/CourseCategoryManage';
import QuestionManageIndex from '@/modules/teach-tool/question-manage/Index';
import PaperManageIndex from '@/modules/teach-tool/paper-manage/Index';
import ExaminationManagerIndex from '@/modules/teach-tool/examination-manager/Index';
import ExaminationManagerTestDetail from '@/modules/teach-tool/examination-manager/TestDetailPage';
import KnowledgeBase from '@/modules/knowledge-base/index';
import CollegeInfoPage from '@/modules/college-manage/CollegeInfoPage';
import ResourceDisk from '@/modules/resource-disk'
import SwitchRoute from '@/modules/root/SwitchRoute'
import PlanPage from '@/modules/plan-manage/PlanPage'
import AddPlanPage from '@/modules/plan-manage/AddPlan'
import LearningDataPage from '@/modules/plan-manage/LearningData'
import StoreInfoPage from '@/modules/store-manage/StoreInfo'
import CourseCategoryManage from '@/modules/teach-tool/components/CourseCategoryManage'
import QuestionManageIndex from '@/modules/teach-tool/question-manage/Index'
import PaperManageIndex from '@/modules/teach-tool/paper-manage/Index'
import ExaminationManagerIndex from '@/modules/teach-tool/examination-manager/Index'
import ExaminationManagerTestDetail from '@/modules/teach-tool/examination-manager/TestDetailPage'
import KnowledgeBase from '@/modules/knowledge-base/index'
import CollegeInfoPage from '@/modules/college-manage/CollegeInfoPage'
const mainRoutes = [
{
......@@ -91,7 +91,7 @@ const mainRoutes = [
{
path: '/offline-course',
component: OfflineCoursePage,
name: '线下',
name: '线下活动',
},
{
path: '/create-live-course',
......@@ -117,12 +117,12 @@ const mainRoutes = [
{
path: '/create-offline-course',
component: AddOfflineCoursePage,
name: '创建线下',
name: '创建线下活动',
},
{
path: '/resource-disk',
component: ResourceDisk,
name: '资料云盘',
name: '素材库',
},
{
path: '/question-manage-index',
......@@ -180,6 +180,6 @@ const mainRoutes = [
component: LearningDataPage,
name: '学习数据',
},
];
]
export default mainRoutes;
export default mainRoutes
......@@ -28,8 +28,8 @@ export const menuList: any = [
link: '/live-course',
},
{
groupName: "线上课",
groupCode: "CourseVideoClass",
groupName: '线上课',
groupCode: 'CourseVideoClass',
link: '/video-course',
},
{
......@@ -38,7 +38,7 @@ export const menuList: any = [
link: '/graphics-course',
},
{
groupName: '线下',
groupName: '线下活动',
groupCode: 'OfflineClass',
link: '/offline-course',
},
......@@ -91,7 +91,7 @@ export const menuList: any = [
selectImg: 'https://image.xiaomaiketang.com/xm/hJKCfibC22.png',
},
{
groupName: '资料云盘',
groupName: '素材库',
groupCode: 'CloudDisk',
icon: '&#xe8aa;',
link: '/resource-disk',
......@@ -151,4 +151,4 @@ export const menuList: any = [
},
],
},
];
]
import LiveCoursePage from "@/modules/course-manage/LiveCoursePage";
import ResourceDisk from "@/modules/resource-disk";
import LiveCoursePage from '@/modules/course-manage/LiveCoursePage'
import ResourceDisk from '@/modules/resource-disk'
const redirectRoutes = [
{
path: "/redirect-to-live-course",
path: '/redirect-to-live-course',
component: LiveCoursePage,
name: "课程管理",
name: '课程管理',
},
{
path: "/redirect-to-resource-disk",
path: '/redirect-to-resource-disk',
component: ResourceDisk,
name: "资料云盘",
name: '素材库',
},
];
]
export default redirectRoutes;
export default redirectRoutes
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