Commit 6f173dcd by guomingpang
parents aef0f0eb a399adb7
......@@ -98,7 +98,6 @@ class UploadProgressModal extends React.Component {
// 开始上传之前初始化OssClient
this.initOssClient(id, resourceName).then((result) => {
const { ossClient, resourceId, callBack, callbackBody, ossUri } = result;
console.log('type',type);
ossClient.multipartUpload(ossUri, fileContent, {
callback: {
url: callBack,
......
......@@ -2,7 +2,7 @@
* @Author: 吴文洁
* @Date: 2020-08-31 09:34:25
* @LastEditors: Please set LastEditors
* @LastEditTime: 2021-06-23 16:08:50
* @LastEditTime: 2021-07-20 17:21:16
* @Description:
* @Copyright: 杭州杰竞科技有限公司 版权所有
*/
......@@ -48,6 +48,10 @@ class User {
return window.currentStoreUserInfo.userId || Storage.get(`${PREFIX}_userId`);
}
getAvatar(){
return Storage.get(`${PREFIX}_avatar`);
}
getUserRole() {
return Storage.get(`${PREFIX}_userRole`);
}
......@@ -96,6 +100,10 @@ class User {
return Storage.set(`${PREFIX}_userId`, value);
}
setAvatar(value: any) {
return Storage.set(`${PREFIX}_avatar`, value);
}
setUserRole(value: any) {
return Storage.set(`${PREFIX}_userRole`, value);
}
......
import PropTypes from 'prop-types';
import React from 'react';
import { DatePicker } from 'antd';
import { ConfigProvider, DatePicker } from 'antd';
import moment from 'moment';
import 'moment/locale/zh-cn';
import locale from 'antd/lib/locale/zh_CN';
const { RangePicker } = DatePicker;
class DateRangePicker extends React.Component {
constructor(props) {
super(props);
......@@ -15,20 +19,23 @@ class DateRangePicker extends React.Component {
render() {
const showTime = { showTime: false }
return (
<RangePicker
format={this.props.format || 'YYYY-MM-DD'}
allowClear={this.props.allowClear}
onChange={(date) => {
if (!_.isEmpty(date)) {
date[0] = date[0].startOf('day')
date[1] = date[1].endOf('day')
}
this.props.onChange(date)
}}
{...showTime}
suffixIcon={<span className="icon iconfont">&#xe838;</span>}
{...this.props}
/>
<ConfigProvider locale={locale}>
<RangePicker
format={this.props.format || 'YYYY-MM-DD'}
allowClear={this.props.allowClear}
onChange={(date) => {
if (!_.isEmpty(date)) {
date[0] = date[0].startOf('day')
date[1] = date[1].endOf('day')
}
this.props.onChange(date)
}}
{...showTime}
suffixIcon={<span className="icon iconfont">&#xe838;</span>}
{...this.props}
/>
</ConfigProvider>
)
}
......
......@@ -2,7 +2,7 @@
* @Author: 吴文洁
* @Date: 2020-08-05 10:07:47
* @LastEditors: yuananting
* @LastEditTime: 2021-07-15 14:24:02
* @LastEditTime: 2021-07-22 18:31:21
* @Description: 线下课新增/编辑页
* @Copyright: 杭州杰竞科技有限公司 版权所有
*/
......@@ -841,7 +841,7 @@ class AddOfflineCourse extends React.Component {
);
}}
getPopupContainer={() => document.getElementById('teacher')}>
{_.map(teacherList, (item, index) => {
{_.map(teacherList, (item) => {
return (
<Option value={item.id} key={item.id}>
{item.nickName}
......@@ -953,7 +953,7 @@ class AddOfflineCourse extends React.Component {
startTimeApply: undefined,
endTimeApply: undefined,
quota: null,
whetherVisitorsJoin: whetherSetApply !== 'YES' ? whetherVisitorsJoin : false
whetherVisitorsJoin: value ? whetherVisitorsJoin : 'YES'
});
}}
/>
......
/*
* @Author: 吴文洁
* @Date: 2020-08-05 10:07:47
* @LastEditors: yuananting
* @LastEditTime: 2021-07-15 18:12:59
* @LastEditors: Please set LastEditors
* @LastEditTime: 2021-07-18 11:54:53
* @Description: 线上课新增/编辑页
* @Copyright: 杭州杰竞科技有限公司 版权所有
*/
......@@ -45,7 +45,14 @@ const defaultScheduleMedia = [
]
const whetherVisitorsJoin = 'NO'
let cutFlag = false
let cutFlag = false;
const SUPPORT_WORD_PDF = [
"application/msword",
"application/wps-writer",
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"application/pdf",
"application/wps-office.pdf"
];
class AddVideoCourse extends React.Component {
constructor(props) {
super(props)
......@@ -317,10 +324,11 @@ class AddVideoCourse extends React.Component {
return;
}
selectedFileList.map((file,index) => {
console.log('')
const { ossUrl, resourceId, folderName, folderFormat, folderSize } = file;
const _mediaName =folderName.replace(`.${_.last(folderName.split('.')).toLowerCase()}`,'')
console.log('folderFormat',folderFormat);
if(folderFormat === 'MP4'){
if(folderFormat === 'MP4' || folderFormat === 'video/mp4'){
const videoDom = document.createElement('video')
videoDom.src = ossUrl
videoDom.onloadedmetadata = () => {
......@@ -328,7 +336,7 @@ class AddVideoCourse extends React.Component {
mediaContent: resourceId,
contentType: 'SCHEDULE',
mediaType: "VIDEO",
mediaName: folderName.replace('.mp4',''),
mediaName: _mediaName,
videoDuration: videoDom.duration,
resourceId,
mediaUrl: ossUrl,
......@@ -338,13 +346,7 @@ class AddVideoCourse extends React.Component {
courseChapterList: _courseChapterList
})
}
}else{
let _mediaName = folderName;
if(folderFormat === 'PDF'){
_mediaName = folderName.replace('.pdf','')
}else{
_mediaName = folderName.replace('.doc','').replace('.docx','')
}
}else if( folderFormat==="WORD" || folderFormat==="PDF" || SUPPORT_WORD_PDF.indexOf(folderFormat)>-1){
const suffix = _.last(folderName.split('.')).toUpperCase();
_courseChapterList.push({
mediaContent: resourceId,
......@@ -679,6 +681,14 @@ class AddVideoCourse extends React.Component {
})
}
}
renderToolTipTitle = ()=> {
return (<div>
<p>视频支持mp4格式,大小不超过2G;</p>
<p>文件支持PDF、docx、doc格式,大小不超过100M</p>
</div>)
}
render() {
const {
pageType,
......@@ -732,7 +742,7 @@ class AddVideoCourse extends React.Component {
<div className='upload-video mt16'>
<div className='content flex'>
<span className='label required'>上传课节:</span>
<span className='label required upload-chapter'>上传课节:</span>
</div>
<div className='sub-content'>
<div className="btn-wrap">
......@@ -755,7 +765,7 @@ class AddVideoCourse extends React.Component {
</div>
<div className='tips'>
课节数量限制20个,文件规格说明
<Tooltip title="视频支持mp4格式,大小不超过2G;文件支持PDF、docx、doc格式,大小不超过100M">
<Tooltip title={this.renderToolTipTitle()} overlayClassName="my-chapter-tooltip">
<i className='icon iconfont' style={{ cursor: 'pointer', color: '#bfbfbf', fontSize: '14px'}}> &#xe61d;</i>
</Tooltip>
</div>
......@@ -815,7 +825,7 @@ class AddVideoCourse extends React.Component {
</If>
<div className='cover-url flex mt16'>
<div className='label'>封面图:</div>
<div className='label cover'>封面图:</div>
<div className='cover-url__wrap'>
<div className='opt-btns'>
<div>
......
......@@ -32,6 +32,12 @@
display:inline-block;
text-align:right;
width:85px;
&.upload-chapter {
margin-top: 6px;
}
&.cover {
margin-top: 2px;
}
}
.required {
position: relative;
......@@ -172,10 +178,9 @@
}
.course-chapter-list {
max-height: 245px;
min-height: 130px;
overflow-y: auto ;
border-radius: 4px;
padding: 16px;
padding: 12px 16px 16px 16px;
.course-ware {
display: flex;
align-items: center;
......@@ -257,4 +262,27 @@
.ant-form-item-explain {
min-height: 0;
}
}
.course-chapter-title-popover {
.tag-title {
color: #333333;
margin-bottom: 8px;
width: 318px;
}
.chapter-btns {
margin-top: 16px;
display: flex;
justify-content: flex-end;
.confirm {
margin-left: 8px;
}
}
.ant-form-item {
margin-bottom: 0 !important;
}
}
.my-chapter-tooltip {
max-width: 600px!important;
}
\ No newline at end of file
......@@ -154,7 +154,7 @@ class AddVideoIntro extends React.Component {
<div className="content">
<div className="intro-list">
<div className="intro-list__item introduce-editor">
{(!id || loadintroduce) &&
{(!id || loadintroduce) &&
<GraphicsEditor
maxLimit={1000}
id="intro"
......
import React from 'react';
import './ChapterList.less';
import { FileTypeIcon } from '@/common/constants/academic/lessonEnum'
const FileTypeIconMap = FileTypeIcon;
function ChapterList(props){
const { courseChapterList } = props;
......@@ -9,7 +12,8 @@ function ChapterList(props){
{
_.map(courseChapterList,(item,index) => {
return <div className='course-ware'>
<div className='course-ware__index'>{index < 9 ? `0${index + 1 } ` : `${index + 1 } `}</div>
<img className='course-ware__img' src={FileTypeIconMap[item.mediaType]} alt='' />
<div className='course-ware__index'>{index < 9 ? `0${index + 1 }` : `${index + 1 }`}</div>
<div className="course-ware__detail">
<div className='course-ware__detail__name'>{item.mediaName}</div>
{ item.mediaType === 'VIDEO' &&
......
......@@ -14,18 +14,24 @@
font-weight: 500;
color: #999999;
line-height: 18px;
white-space: nowrap;
margin-left: 8px;
margin-right: 6px;
line-height: 20px;
}
&__img {
width: 20px;
height: 20px;
}
&__detail {
display: flex;
flex-direction: column;
width: calc(~'100% - 18px');
&__name {
width: 267px;
font-size: 13px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #333333;
line-height: 21px;
line-height: 20px;
margin-bottom: 4px;
}
&__duration {
......
......@@ -2,7 +2,7 @@
* @Author: zhangleyuan
* @Date: 2021-02-20 16:13:39
* @LastEditors: yuananting
* @LastEditTime: 2021-07-08 10:52:05
* @LastEditTime: 2021-07-20 17:17:12
* @Description: 描述一下
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
......@@ -65,6 +65,7 @@ function AddPlan() {
planId: id,
}).then((res) => {
const {
planId,
planName,
enableState,
operateType,
......@@ -78,6 +79,7 @@ function AddPlan() {
let coverId;
let coverUrl;
let instro;
let hasIntro = false;
courseMediaVOS.map((item) => {
switch (item.contentType) {
case 'COVER':
......@@ -85,6 +87,7 @@ function AddPlan() {
coverUrl = item.mediaUrl;
break;
case 'INTRO':
hasIntro = true;
instro = item.mediaContent;
break;
default:
......@@ -102,6 +105,7 @@ function AddPlan() {
}
setTaskList(trainingTaskList);
setBasicData({
planId,
planName,
coverUrl: coverUrl || defaultCover,
coverId,
......
......@@ -2,19 +2,11 @@
* @Author: yuananting
* @Date: 2021-07-05 10:48:08
* @LastEditors: yuananting
* @LastEditTime: 2021-07-15 14:20:15
* @LastEditTime: 2021-07-21 14:00:44
* @Description: 描述一下咯
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
/*
* @Author: zhangleyuan
* @Date: 2021-02-20 16:45:51
* @LastEditors: Please set LastEditors
* @LastEditTime: 2021-07-06 14:48:54
* @Description: 描述一下
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import React from 'react';
import { Button, Input, Switch, Radio, Row, Col, message, Tooltip } from 'antd';
import { withRouter } from 'react-router-dom';
......@@ -133,14 +125,10 @@ class BasicInfo extends React.Component {
this.props.onChange(field, _percentCompleteLive);
};
changeIntro = (value) => {
this.props.onChange('introduce', value);
};
render() {
const { operatorModalVisible, showSelectFileModal, visible, imageFile } = this.state;
const { data } = this.props;
const { planName, coverUrl, introduce, enableState, operateType, selectOperatorList, percentCompleteLive, percentCompleteVideo, percentCompletePicture } =
const { planName, coverUrl, instro, enableState, operateType, selectOperatorList, percentCompleteLive, percentCompleteVideo, percentCompletePicture } =
data;
// 当前是否使用的是默认图片
const isDefaultCover = coverUrl === defaultCover;
......@@ -183,24 +171,13 @@ class BasicInfo extends React.Component {
</div>
<div className='introduction'>
<span className='label'>简介:</span>
{/* <TextArea
<TextArea
placeholder='请输入培训计划简介'
maxLength={200}
style={{ width: '552px', height: '110px' }}
className='instro-textarea'
value={instro}
onChange={(e) => this.props.onChange('instro', e.target.value)}
/> */}
<GraphicsEditor
id='intro'
isIntro={true}
maxLimit={1000}
detail={{
content: introduce,
}}
onChange={(val) => {
this.changeIntro(val);
}}
/>
</div>
<div className='wether-use'>
......
......@@ -89,6 +89,7 @@
}
.choose-business {
margin-top: 12px;
margin-left: 24px;
.ant-btn {
margin-right: 12px;
}
......
/*
* @Author: zhangleyuan
* @Date: 2021-02-20 16:46:46
* @LastEditors: fusanqiasng
* @LastEditTime: 2021-06-01 11:45:34
* @LastEditors: wufan
* @LastEditTime: 2021-07-16 11:29:13
* @Description: 描述一下
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
......@@ -52,7 +52,6 @@ function PlanList(props) {
title: '课程总数量',
key: 'courseNum',
dataIndex: 'courseNum',
width: 110,
render: (val, record) => {
return <div className='course-number'>{val}</div>;
},
......
.plan-list {
margin-top: 12px;
.course-number {
text-align: right;
margin-right: 45px;
}
......
/*
* @Author: yuananting
* @Date: 2021-07-05 10:50:10
* @LastEditors: yuananting
* @LastEditTime: 2021-07-13 19:55:29
* @LastEditors: Please set LastEditors
* @LastEditTime: 2021-07-18 10:47:02
* @Description: 描述一下咯
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import React from 'react';
import _ from 'underscore';
import { Table, Radio, Tabs, Modal, Input, message, Button, Tooltip } from 'antd';
import { Radio, Tabs, Modal, Input, message, Button, Tooltip } from 'antd';
import { PageControl } from '@/components';
import { PageControl, XMTable } from '@/components';
import college from '@/common/lottie/college';
import CourseService from '@/domains/course-domain/CourseService';
import User from '@/common/js/user';
......@@ -732,7 +733,11 @@ class SelectOperatorModal extends React.Component {
</div>
</div>
<div>
<Table
<XMTable
renderEmpty={{
image: college,
description: '暂无数据',
}}
rowKey={(record) => record.liveCourseId}
dataSource={liveDataSource}
columns={this.parseLiveColumns()}
......@@ -824,7 +829,11 @@ class SelectOperatorModal extends React.Component {
</div>
</div>
<div>
<Table
<XMTable
renderEmpty={{
image: college,
description: '暂无数据',
}}
rowKey={(record) => record.id}
dataSource={videoDataSource[videoCourseDivision]}
columns={this.parseVideoColumns()}
......@@ -929,7 +938,11 @@ class SelectOperatorModal extends React.Component {
</div>
</div>
<div>
<Table
<XMTable
renderEmpty={{
image: college,
description: '暂无数据',
}}
rowKey={(record) => record.id}
dataSource={pictureDataSource}
columns={this.parsePictureColumns()}
......
......@@ -290,7 +290,8 @@ class SelectPrepareFileModal extends React.Component {
const { fileListRef } = this.refs;
// const hasReachBottom = fileListRef.scrollTop + fileListRef.clientHeight === fileListRef.scrollHeight;
const hasReachBottom = fileListRef.scrollTop + fileListRef.clientHeight > fileListRef.scrollHeight - 1;
const hasReachBottom = fileListRef.scrollTop + fileListRef.clientHeight > fileListRef.scrollHeight - 10;
console.log("fileListRef.scrollTop + fileListRef.clientHeight",hasReachBottom,fileListRef.scrollTop , fileListRef.clientHeight,fileListRef.scrollHeight)
if (!hasReachBottom || !hasMore) return;
const currentFolder = folderPathList[folderPathList.length - 1];
......@@ -325,14 +326,12 @@ class SelectPrepareFileModal extends React.Component {
// 上传文件
handleUpload = (event) => {
const { selectType } = this.props;
const fileList = event.target.files;
// 判断文件的大小是否超出了限制
const nonCompliantFileList = [];
const _fileList = [...fileList];
_fileList.map((file, index) => {
console.log('file',file);
let { size, type, name } = file;
if (!type) {
type = getFileTypeByName(name);
......@@ -573,8 +572,9 @@ class SelectPrepareFileModal extends React.Component {
}
</div>
{
!_.isEmpty(folderList) ?
<div>
<Choose>
<When condition={!_.isEmpty(folderList)}>
<div>
<div className="file-list"
onScrollCapture={() => this.handleScrollEvent()}
style={{ height: '320px', overflowY: 'auto' }}
......@@ -611,8 +611,7 @@ class SelectPrepareFileModal extends React.Component {
// 文件禁止点击的情况(移动、直播场景下文件为Excel、文件已经被关联了、文件不合法)
const disabled = hiddenVideo || (!isFolder && operateType === 'move') || (scene === 'liveCourse' && folder.folderFormat === 'EXCEL') || !!hasRelation || (!isFolder && !FILE_SUFFIX_LIST.includes(suffix));
// console.log('currentFile',currentFile);
// console.log('folder',folder);
let currentFileCheck = false;
if(currentFile){
currentFileCheck = (currentFile.id===folder.id)
......@@ -660,12 +659,16 @@ class SelectPrepareFileModal extends React.Component {
})
}
</div>
</div> :
<LottieIcon
</div>
</When>
<Otherwise>
<LottieIcon
title={<span className="desc">这个文件夹是空的</span>}
type="college"
size={150}
/>
</Otherwise>
</Choose>
}
<UploadProgressModal
......
......@@ -7,11 +7,11 @@
*/
import React, { useContext, useEffect, useState } from 'react';
import { withRouter } from 'react-router-dom';
import { ConfigProvider, message, Layout } from 'antd';
import { ConfigProvider, message, Layout, DatePicker } from 'antd';
import Header from './Header'
import Menu from './Menu'
import Main from './Main'
import zhCN from 'antd/es/locale/zh_CN'
import zhCN from 'antd/lib/locale/zh_CN'
import User from '@/common/js/user';
import BaseService from "@/domains/basic-domain/baseService";
import moment from 'moment';
......
......@@ -158,7 +158,10 @@ export default class CreateCollege extends React.Component {
<Button
className="button"
type="primary"
onClick={() => this.submit()}
onClick={_.debounce(() => this.submit(), 3000, {
leading: true,
trailing: false
})}
>确定创建</Button>
</div>
<input
......
/*
* @Author: 吴文洁
* @Date: 2019-09-10 18:26:03
* @LastEditors: Please set LastEditors
* @LastEditTime: 2021-07-14 14:16:50
* @LastEditors: yuananting
* @LastEditTime: 2021-07-21 14:03:30
* @Description:
*/
import React, { useRef, useContext, useEffect, useState } from 'react';
......@@ -79,6 +79,7 @@ function Header(props) {
setNickName(nickName);
setPhone(phone);
setAvatar(res.result.avatar);
User.setAvatar(res.result.avatar);
});
}
......@@ -336,7 +337,7 @@ function Header(props) {
<div
className='url-link'
onClick={() => {
window.open(htmlUrl);
window.open(`${LIVE_SHARE}store/index?id=${window.currentStoreUserInfo.storeId||User.getStoreId()}&userId=${window.currentStoreUserInfo.userId||User.getUserId()}&enterpriseId=${window.currentStoreUserInfo.enterpriseId||User.getEnterpriseId()}&from=admin&avatar=${avatar}`);
}}>
{'立即前往 >'}
</div>
......
......@@ -85,9 +85,8 @@ function AddExam(props: any) {
source: 0,
}
Service.Hades('public/hades/queryExamPageList', param).then(res=> {
console.log(res)
const { result = {} } = res;
setExamList(result.records)
setExamList(result.records || [])
})
}
......@@ -277,7 +276,7 @@ function AddExam(props: any) {
// 校验考试名称是否存在
function checkExist(examName: any) {
var result:any = null;
examList.forEach((item:any) => {
examList.length > 0 && examList.forEach((item:any) => {
if (result != null) {
return result;
}
......@@ -454,24 +453,25 @@ function AddExam(props: any) {
<div className="title" style={{ marginTop: 40 }}>考试设置</div>
<Form.Item label="身份验证" required>
<div style={{ display: 'flex', marginLeft: 4, }}>
<Switch style={{ position: 'relative', top: 6 }}
<Switch
checked={needPhone == 'NEED_PHONE_VERIFY'}
onChange={(val) => { setNeedPhone(val ? 'NEED_PHONE_VERIFY' : 'DO_NOT_NEED_PHONE_VERIFY') }}
></Switch>
<div style={{ position: 'relative', top: 3, left: 8, color: "#999" }}><p>开启:需要绑定手机号的学员才能参加考试</p>
<p>关闭:微信/企业微信登陆直接参加考试</p></div>
<div style={{ position: 'relative', left: 8, color: "#999" }}>
{needPhone == 'NEED_PHONE_VERIFY' ? '已开启,学员需绑定手机号才可参与考试' : '已关闭,学员无需绑定手机号即可参与考试'}
</div>
</div>
</Form.Item>
<Form.Item label="选项乱序" required>
<div style={{ display: 'flex', marginLeft: 4, }}>
<Switch style={{ position: 'relative', top: 6 }}
<Switch
checked={needOptionDisorder == 'OPTION_RANDOM'}
onChange={(val) => { setNeedOptionDisorder(val ? 'OPTION_RANDOM' : 'OPTION_SORT') }}
></Switch>
<div style={{ position: 'relative', top: 3, left: 8, color: "#999" }}><p>开启:选择题的选项随机排序</p>
<p>关闭:选择题按题目原有顺序展示</p></div>
<div style={{ position: 'relative', left: 8, color: "#999" }}>
{needOptionDisorder == 'OPTION_RANDOM' ? '已开启,选项随机排序' : '已关闭,选项按设置顺序排序'}
</div>
</div>
</Form.Item>
......
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