Commit f290316c by zhangleyuan

feat:解决合并代码后的冲突

parents 95206b5a 81173cbc
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: zhangleyuan * @Author: zhangleyuan
* @Date: 2020-12-15 19:58:31 * @Date: 2020-12-15 19:58:31
* @LastEditors: zhangleyuan * @LastEditors: zhangleyuan
* @LastEditTime: 2020-12-15 20:00:31 * @LastEditTime: 2021-01-04 20:10:06
* @Description: 描述一下 * @Description: 描述一下
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
--> -->
...@@ -13,3 +13,9 @@ ...@@ -13,3 +13,9 @@
+ 播种计划一期第一阶段初上线 + 播种计划一期第一阶段初上线
#### 1.0.1
`2020-01-04`
+ 播种计划一期第二阶段初上线
\ No newline at end of file
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
"@testing-library/jest-dom": "^4.2.4", "@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.3.2", "@testing-library/react": "^9.3.2",
"@testing-library/user-event": "^7.1.2", "@testing-library/user-event": "^7.1.2",
"@types/ali-oss": "^6.0.5",
"@types/qs": "^6.9.5", "@types/qs": "^6.9.5",
"@types/react": "^16.9.46", "@types/react": "^16.9.46",
"@types/react-dom": "^16.9.8", "@types/react-dom": "^16.9.8",
...@@ -18,7 +19,9 @@ ...@@ -18,7 +19,9 @@
"@types/underscore": "^1.10.22", "@types/underscore": "^1.10.22",
"@typescript-eslint/eslint-plugin": "^2.10.0", "@typescript-eslint/eslint-plugin": "^2.10.0",
"@typescript-eslint/parser": "^2.10.0", "@typescript-eslint/parser": "^2.10.0",
"antd": "^4.8.5", "ali-oss": "^6.12.0",
"antd": "^4.9.4",
"array-move": "^3.0.1",
"axios": "^0.20.0", "axios": "^0.20.0",
"babel-eslint": "10.1.0", "babel-eslint": "10.1.0",
"babel-jest": "^24.9.0", "babel-jest": "^24.9.0",
...@@ -28,6 +31,7 @@ ...@@ -28,6 +31,7 @@
"babel-preset-react-app": "^9.1.2", "babel-preset-react-app": "^9.1.2",
"camelcase": "^5.3.1", "camelcase": "^5.3.1",
"case-sensitive-paths-webpack-plugin": "2.3.0", "case-sensitive-paths-webpack-plugin": "2.3.0",
"classnames": "^2.2.6",
"cropper": "^3.1.4", "cropper": "^3.1.4",
"cross-env": "^7.0.2", "cross-env": "^7.0.2",
"css-loader": "3.4.2", "css-loader": "3.4.2",
...@@ -46,6 +50,7 @@ ...@@ -46,6 +50,7 @@
"file-loader": "4.3.0", "file-loader": "4.3.0",
"fs-extra": "^8.1.0", "fs-extra": "^8.1.0",
"html-webpack-plugin": "4.0.0-beta.11", "html-webpack-plugin": "4.0.0-beta.11",
"html2canvas": "^1.0.0-rc.7",
"husky": "^4.2.5", "husky": "^4.2.5",
"identity-obj-proxy": "3.0.0", "identity-obj-proxy": "3.0.0",
"jest": "24.9.0", "jest": "24.9.0",
...@@ -53,10 +58,13 @@ ...@@ -53,10 +58,13 @@
"jest-resolve": "24.9.0", "jest-resolve": "24.9.0",
"jest-watch-typeahead": "0.4.2", "jest-watch-typeahead": "0.4.2",
"jquery": "^3.4.1", "jquery": "^3.4.1",
"less": "^3.12.2",
"less-loader": "^6.2.0", "less-loader": "^6.2.0",
"microevent": "^1.0.0", "microevent": "^1.0.0",
"mini-css-extract-plugin": "0.9.0", "mini-css-extract-plugin": "0.9.0",
"moment": "^2.27.0",
"optimize-css-assets-webpack-plugin": "5.0.3", "optimize-css-assets-webpack-plugin": "5.0.3",
"photoclip": "^3.4.8",
"pnp-webpack-plugin": "1.6.4", "pnp-webpack-plugin": "1.6.4",
"postcss-flexbugs-fixes": "4.1.0", "postcss-flexbugs-fixes": "4.1.0",
"postcss-loader": "3.0.0", "postcss-loader": "3.0.0",
...@@ -70,7 +78,9 @@ ...@@ -70,7 +78,9 @@
"react-async-component": "^2.0.0", "react-async-component": "^2.0.0",
"react-dev-utils": "^10.2.1", "react-dev-utils": "^10.2.1",
"react-dom": "^16.13.1", "react-dom": "^16.13.1",
"react-infinite-scroller": "^1.2.4",
"react-router-dom": "^5.2.0", "react-router-dom": "^5.2.0",
"react-sortable-hoc": "^1.11.0",
"resolve": "1.15.0", "resolve": "1.15.0",
"resolve-url-loader": "3.1.1", "resolve-url-loader": "3.1.1",
"semver": "6.3.0", "semver": "6.3.0",
...@@ -80,10 +90,13 @@ ...@@ -80,10 +90,13 @@
"typescript": "^4.0.2", "typescript": "^4.0.2",
"underscore": "^1.10.2", "underscore": "^1.10.2",
"url-loader": "2.3.0", "url-loader": "2.3.0",
"video-react": "0.14.1",
"wangeditor": "^3.1.1",
"webpack": "4.42.0", "webpack": "4.42.0",
"webpack-dev-server": "3.11.0", "webpack-dev-server": "3.11.0",
"webpack-manifest-plugin": "2.2.0", "webpack-manifest-plugin": "2.2.0",
"workbox-webpack-plugin": "4.3.1" "workbox-webpack-plugin": "4.3.1",
"xiaomai-b-components": "1.4.4"
}, },
"scripts": { "scripts": {
"start": "node scripts/start.js", "start": "node scripts/start.js",
...@@ -116,8 +129,10 @@ ...@@ -116,8 +129,10 @@
"jsx-control-statements" "jsx-control-statements"
] ]
}, },
"devDependencies": { "devDependencies": {
"@types/jquery": "^3.5.4" "@types/ali-oss": "^6.0.5",
"@types/jquery": "^3.5.4",
"ali-oss": "^6.12.0",
"react-sortable-hoc": "^1.11.0"
} }
} }
.choose-container{
display: flex;
height: 417px;
.container-left{
width: 50%;
padding-right: 10px;
margin-left: 10px;
.container-left-header{
margin-bottom: 12px;
}
.container-left-body{
border: 1px solid #E9E9E9;
.ant-table-thead > tr > th {
font-weight:400!important;
}
.search{
width: 305px;
padding: 7px 7px;
}
.container-left-body-table{
width: 300px;
height: 330px;
.ant-table {
border: none;
min-height: 250px !important;
.ant-table-header{
margin-bottom: -7px !important;
>table > .ant-table-thead > tr > th {
background-color: #fff !important;
}
}
.ant-table-tbody{
>tr >td {
border-bottom: none;
background-color: #fff !important;
}
}
}
.ant-empty-normal {
margin: 100px 0 !important;
}
.avatar{
.avatar-img{
height: 23px;
width: 23px;
border-radius: 50%;
}
}
}
}
}
.container-right{
width: 50%;
.span-left{
margin-left: 10px;
.span-left-l{
color: #FD9A6A;
cursor: pointer;
}
}
.span-right{
float: right;
margin-right: 10px;
color:#5289FA;
.span-right-l{
color: #FD9A6A;
cursor: pointer;
}
}
.container-right-body{
border: 1px solid #E9E9E9;
margin: 10px;
.edit {
.edit-icon {
color:#999;
}
}
.edit-img{
width: 16px;
height: 16px;
}
.ant-table {
min-height: 378px !important;
}
.ant-table tbody tr:nth-child(even) {
background: transparent!important;
}
.ant-empty-normal {
margin: 130px 0 !important;
}
.avatar{
display: flex;
align-items: center;
.avatar-img{
height: 23px;
width: 23px;
border-radius: 50%;
margin-right: 15px;
}
}
.ant-table-tbody{
>tr >td {
border-bottom:none;
}
>tr .ant-table-selection-column{
width: 30px !important;
}
}
}
}
}
\ No newline at end of file
.copy-header{
margin-left: 34%;
}
.copy-body{
.bread-crumbs {
margin-bottom: 10px;
}
.bread:hover{
color: #5289FA;
}
}
.folder-list{
height: 100%;
border-top: 1px solid #E8E8E8;
border-top-left-radius:4px;
border-top-right-radius:4px;
border: 1px solid #E8E8E8;
overflow: auto;
.enable{
cursor: pointer;
}
.disable{
cursor: not-allowed;
opacity: 0.5;
}
.information{
display: flex;
height: 50px;
border-top: none;
padding-top: 12px;
padding-left: 25px;
position: relative;
border-bottom: 1px solid #E8E8E8;
&:last-child {
border-bottom: none;
}
.folderName{
padding-left: 15px;
}
.file-item__expend-icon{
position: absolute;
right: 20px;
.iconfont {
color: #BFBFBF;
}
}
.file-item__size{
position: absolute;
right: 20px;
}
}
}
.lottie-box {
border:1px solid #E8E8E8;
border-radius:4px;
}
.lottie-icon{
margin: 100px 0;
}
\ No newline at end of file
/*
* @Author: 吴文洁
* @Date: 2020-07-16 11:05:17
* @Last Modified by: 吴文洁
* @Last Modified time: 2020-07-17 16:17:10
* @Description: 添加直播-简介
*/
import React from 'react';
import { Input, message, Upload } from 'antd';
import _ from 'underscore';
import { randomString } from '@/domains/basic-domain/utils';
import Service from '@/common/js/service';
import EditorBox from '../components/EditorBox';
import './Introduction.less';
const { TextArea } = Input;
class Introduction extends React.Component {
constructor(props) {
super(props);
this.state = {
}
}
// 删除简介
handleDeleteIntro = (index) => {
const { liveCourseMediaRequests } = this.props.data;
liveCourseMediaRequests.splice(index, 1);
this.props.onChange('liveCourseMediaRequests', liveCourseMediaRequests);
}
// 上移简介
handleMoveUpIntro = (index) => {
const { liveCourseMediaRequests } = this.props.data;
const prevItem = liveCourseMediaRequests[index];
const nextItem = liveCourseMediaRequests[index + 1];
liveCourseMediaRequests.splice(index, 2, nextItem, prevItem);
this.props.onChange('liveCourseMediaRequests', liveCourseMediaRequests);
}
// 下移简介
handleMoveDownIntro = (index) => {
const { liveCourseMediaRequests } = this.props.data;
const prevItem = liveCourseMediaRequests[index - 1];
const nextItem = liveCourseMediaRequests[index];
liveCourseMediaRequests.splice(index - 1, 2, nextItem, prevItem);
this.props.onChange('liveCourseMediaRequests', liveCourseMediaRequests);
}
renderLittleIcon = (index) => {
const { liveCourseMediaRequests } = this.props.data;
return (
<div className="little-icon">
<span
className="icon iconfont close"
onClick={() => { this.handleDeleteIntro(index); }}
></span>
{
index > 0 &&
<span
className="icon iconfont"
onClick={() => { this.handleMoveDownIntro(index); }}
>&#xe6d1;</span>
}
{
index !== liveCourseMediaRequests.length - 1 &&
<span
className="icon iconfont"
onClick={() => { this.handleMoveUpIntro(index); }}
>&#xe6cf;</span>
}
</div>
)
}
handleChangeIntro = (index, value) => {
const { liveCourseMediaRequests } = this.props.data;
liveCourseMediaRequests[index].mediaContent = value;
this.props.onChange('liveCourseMediaRequests', liveCourseMediaRequests);
}
handleAddIntroText = () => {
const { liveCourseMediaRequests } = this.props.data;
liveCourseMediaRequests.push({
mediaType: 'TEXT',
mediaContent: '',
key: randomString(16)
});
this.props.onChange('liveCourseMediaRequests', liveCourseMediaRequests);
}
handleUpload = (Blob) => {
// 最多添加九图片
const { liveCourseMediaRequests } = this.props.data;
const list = _.filter(liveCourseMediaRequests, (item) => {
return item.mediaType === "PICTURE";
});
if (list.length > 8) {
message.warning("最多添加9张图片");
return;
}
const { instId } = window.currentUserInstInfo;
const { name, size } = Blob;
const resourceName = randomString(16) + name.slice(name.lastIndexOf('.'));
const params = {
resourceName,
accessTypeEnum: 'PUBLIC',
bizCode: 'LIVE_COURSE_MEDIA',
instId: instId,
}
Service.Hades("public/apollo/commonOssAuthority", params).then((res) => {
const { resourceId } = res.result;
const signInfo = res.result;
// 构建上传的表单
const xhr = new XMLHttpRequest();
const formData = new FormData();
formData.append("OSSAccessKeyId", signInfo.accessId);
formData.append("policy", signInfo.policy);
formData.append("callback", signInfo.callback);
formData.append("Signature", signInfo.signature);
formData.append("key", signInfo.key);
formData.append("file", Blob);
formData.append("success_action_status", 200);
xhr.open("POST", signInfo.host);
xhr.onload = () => {
liveCourseMediaRequests.push({
size,
mediaName: name,
mediaContent: resourceId,
mediaType: 'PICTURE',
mediaUrl: window.URL.createObjectURL(Blob),
});
this.props.onChange('liveCourseMediaRequests', liveCourseMediaRequests);
};
xhr.onerror = () => {
xhr.abort();
};
xhr.send(formData);
this.setState({ xhr })
});
}
componentWillUnmount() {
const { xhr } = this.state;
xhr && xhr.abort();
}
render() {
const {
iveScene,
data: {
introduction,
label = '直播课简介',
liveCourseMediaRequests = []
},
} = this.props;
// 是否是互动班课
const isInteractive = iveScene === 'interactive';
return (
<div className="add-live__intro-info">
<span className="lable">{label}</span>
<div className="content">
{
isInteractive &&
<TextArea
value={introduction}
placeholder="简单介绍下这次课吧"
maxLength={200}
style={{ width: 480 }}
onChange={(e) => { this.props.onChange('introduction', e.target.value) }}
/>
}
<If condition={!isInteractive}>
<div className="intro-list">
{
liveCourseMediaRequests.map((item, index) => {
if (item.mediaType === 'TEXT') {
return (
<div className="intro-list__item" key={item.key}>
<EditorBox
detail={{
content: item.mediaContent
}}
onChange={(val) => { this.handleChangeIntro(index, val)}}
/>
{ this.renderLittleIcon(index) }
</div>
)
}
if (item.mediaType === 'PICTURE') {
return (
<div className="intro-list__item picture" key={index}>
<div className="img__wrap">
<img src={item.mediaUrl} alt="introImg" />
</div>
{ this.renderLittleIcon(index) }
</div>
)
}
return item;
})
}
</div>
<div className="operate">
<div className="operate__item" onClick={this.handleAddIntroText}>
<span className="icon iconfont">&#xe760;</span>
<span className="text">文字</span>
</div>
<Upload
fileList={[]}
accept="image/jpeg, image/png, image/jpg, image/gif"
beforeUpload={(Blob) => {
this.handleUpload(Blob);
return false;
}}
>
<div className="operate__item">
<span className="icon iconfont">&#xe74a;</span>
<span className="text">图片</span>
</div>
</Upload>
</div>,
<div className="tips">
• 图片支持jpeg、jpg、png、gif格式
</div>
</If>
</div>
</div>
)
}
}
export default Introduction;
.add-live__intro-info {
display: flex ;
.label {
padding-top: 12px;
}
textarea.ant-input {
min-height: 80px;
}
.intro-list__item {
display: flex;
margin-bottom: 16px;
position: relative;
&.picture {
width: 550px;
padding: 16px;
border: 1px solid #EEE;
border-radius: 4px;
.img__wrap {
width: 299px;
height: 168px;
img {
width: 100%;
height: 100%;
object-fit: contain;
}
}
}
.little-icon {
display: flex;
flex-direction: column;
position: absolute;
top: 0;
right: -20px;
.iconfont {
width: 20px;
height: 20px;
line-height: 20px;
font-size: 20px;
color: #999;
margin-bottom: 4px;
cursor: pointer;
&.close {
margin-top: 8px;
background-image: url('https://image.xiaomaiketang.com/xm/eesMPhNP3e.png');
background-size: 100% 100%;
}
}
}
}
.operate {
display: flex;
align-items: center;
justify-content: center;
width: 550px;
height: 80px;
line-height: 80px;
padding: 16px;
margin-top: 16px;
border: 1px dashed #EBEBEB;
border-radius: 4px;
.ant-upload {
vertical-align: middle;
}
&__item {
display: flex;
flex-direction: column;
cursor: pointer;
&:not(:last-child) {
margin-right: 82px;
}
.iconfont {
font-size: 22px;
line-height: 22px;
color: #BFBFBF;
text-align: center;
}
.text {
color: #999;
line-height: 20px;
margin-top: 4px;
}
}
}
.tips {
color: #999;
margin-top: 16px;
}
}
\ No newline at end of file
.managing-header{
// width: 100%;
height: 30px;
.managing-left{
float: left;
.tool-tip-left{
cursor: pointer;
margin-left: 4px;
width: 14px;
height: 14px;
}
}
.managing-right{
float: right;
color: #FFB714;
cursor: pointer;
.tool-tip-right{
margin-right: 4px;
width: 16px;
height: 16px;
}
}
}
.managing-body{
height: 300px;
overflow: hidden;
border: 1px solid #E9E9E9;
border-radius: 4px;
.ant-table-tbody{
.ant-table-row{
background-color: #fff !important;
}
.ant-table-row:hover{
background-color: #E9E9E9;
}
}
.avatar{
.avatar-img{
height: 30px;
width: 30px;
border-radius: 50%;
}
}
.rights{
.img-type{
height: 18px;
width: 18px;
}
}
}
.menu-bottom{
font-size: 6px !important;
color: #AAAAAA !important;
}
.remove-modal{
font-size: 14px !important;
color: #AAAAAA !important;
height: 30px;
}
/*
* @Author: 吴文洁
* @Date: 2020-06-16 11:41:43
* @Last Modified by: 吴文洁
* @Last Modified time: 2020-07-06 17:33:47
* @Description: 文件超出大小的限制
*/
import React from 'react';
import { Modal } from 'antd';
import { DEFAULT_SIZE_UNIT } from "@/domains/resource-disk/constants";
import './NonCompliantFileModal.less';
class NonCompliantFileModal extends React.Component {
constructor(props) {
super(props);
this.state = {}
}
render() {
const { isOpen, fileList } = this.props;
return (
<Modal
title="文件超出可上传的大小限制"
visible={isOpen}
okText="继续上传"
cancelText="放弃上传"
onCancel={this.props.onClose}
onOk={this.props.onOk}
maskClosable={false}
className="prepare-lesson__non-compliant-file-modal"
>
<div className="file-list">
<div className="file-list__title">以下文件超出上传限制,无法上传,点击继续上传不会上传以下文件。</div>
<div className="file-list__content">
{
fileList.map((file, index) => {
let _size = `${(file.size / DEFAULT_SIZE_UNIT).toFixed(1)}M`;
if (file.size < 0.1 * DEFAULT_SIZE_UNIT) {
_size = `${(file.size / 1024).toFixed(1)}kb`;
}
return (
<div className="file-list__item" key={`file-list__item${index}`}>
<span className="file-name">{file.name}</span>
<span className="file-size">{_size}</span>
</div>
)
})
}
</div>
</div>
<div className="tips">
<span className="icon iconfont">&#xe6f2;</span>
<span className="tips__text">
支持上传:Word(100M以内)、Excel(10M以内)、PPT(100M以内)、PDF(100M以内)、图片(5M以内)、音频(20M以内)、视频(500M以内)
</span>
</div>
</Modal>
)
}
}
export default NonCompliantFileModal;
.prepare-lesson__non-compliant-file-modal {
.tips {
margin-top: 16px;
display: flex;
.iconfont {
margin-right: 4px;
font-size: 13px;
color: #FFB74C;
}
&__text {
color: #999;
}
}
.file-list {
&__title {
color: #666;
}
&__content {
max-height: 120px;
margin-top: 12px;
padding: 17px;
border: 1px solid #E8E8E8;
border-radius: 4px;
overflow: scroll;
.file-list__item span {
color: #333;
}
}
}
}
\ No newline at end of file
/*
* @Author: 吴文洁
* @Date: 2020-07-23 14:54:16
* @LastEditors: wufan
* @LastEditTime: 2020-12-22 20:29:39
* @Description: 大班直播课预览弹窗
* @Copyright: 杭州杰竞科技有限公司 版权所有
*/
import React from 'react';
import { Modal } from 'antd';
import moment from 'moment';
import './PreviewCourseModal.less';
class PreviewCourseModal extends React.Component {
constructor(props) {
super(props);
this.state = {
}
}
dealWithTime = (startTime, endTime) => {
const startDate = new Date(Number(startTime));
const endDate = new Date(Number(endTime));
const year = startDate.getFullYear();
const month = (startDate.getMonth() + 1) < 10 ? `0${startDate.getMonth() + 1}` : startDate.getMonth() + 1;
const day = startDate.getDate() < 10 ? `0${startDate.getDate()}` : startDate.getDate();
const startHour = startDate.getHours() < 10 ? `0${startDate.getHours()}` : startDate.getHours();
const startMinute = startDate.getMinutes() < 10 ? `0${startDate.getMinutes()}` : startDate.getMinutes();
const endHour = endDate.getHours() < 10 ? `0${endDate.getHours()}` : endDate.getHours();
const endMinute = endDate.getMinutes() < 10 ? `0${endDate.getMinutes()}` : endDate.getMinutes();
const liveDateStr = `${year}-${month}-${day}`;
const startTimeStr = `${startHour}:${startMinute}`;
const endTimeStr = `${endHour}:${endMinute}`;
return {
liveDateStr,
startTimeStr,
endTimeStr,
};
}
render() {
const { courseBasinInfo, courseClassInfo = {}, courseIntroInfo, type } = this.props;
const { coverUrl, courseName, scheduleVideoUrl } = courseBasinInfo;
const { liveDate, timeHorizonStart, timeHorizonEnd, nickname } = courseClassInfo;
const { liveCourseMediaRequests } = courseIntroInfo;
let liveDateStr, startTimeStr, endTimeStr;
if (liveDate) {
const _liveDate = moment(liveDate).format("YYYY-MM-DD");
const _timeHorizonStart = moment(timeHorizonStart).format('HH:mm');
const _timeHorizonEnd = moment(timeHorizonEnd).format('HH:mm');
const startTime = moment(_liveDate + ' ' + _timeHorizonStart).format('x');
const endTime = moment(_liveDate + ' ' + _timeHorizonEnd).format('x');
const {
liveDateStr: _liveDateStr,
startTimeStr: _startTimeStr,
endTimeStr: _endTimeStr
} = this.dealWithTime(startTime, endTime);
liveDateStr = _liveDateStr;
startTimeStr = _startTimeStr;
endTimeStr = _endTimeStr;
}
return (
<Modal
title="预览"
visible={true}
width={680}
onCancel={this.props.close}
footer={null}
maskClosable={false}
className="preview-live-course-modal"
>
<div className="container__wrap">
<div className="container">
<div className="container__header">
<Choose>
<When condition={type === 'videoCourse'}>
<video
controls
src={scheduleVideoUrl}
poster={coverUrl ? coverUrl : `${scheduleVideoUrl}?x-oss-process=video/snapshot,t_0,m_fast`}
className="course-url"
/>
</When>
<Otherwise>
<img src={coverUrl} className="course-cover" alt="course-cover" />
</Otherwise>
</Choose>
</div>
<Choose>
<When condition={type === 'videoCourse'}>
<div className="container__body">
<div className="title__name">{courseName}</div>
<div className="title__inst-name">{window.currentUserInstInfo.name}</div>
</div>
</When>
<Otherwise>
<div className="container__body">
<div className="container__body__title">
<div className="title__name">{courseName}</div>
<div className="title__state">待开课</div>
</div>
<div className="container__body__time">
<span className="time__label">上课时间:</span>
<span className="time__value">
{
liveDate && timeHorizonStart && timeHorizonEnd &&
[
<span>{liveDateStr}&nbsp;</span>,
<span>{startTimeStr}~{endTimeStr }</span>
]
}
</span>
</div>
<div className="container__body__teacher">
<span className="teacher__label">上课老师:</span>
<span className="teacher__value">{nickname}</span>
</div>
</div>
</Otherwise>
</Choose>
<div className="container__introduction">
<div className="container__introduction__title">直播简介</div>
<div className="container__introduction__list editor-box">
{
liveCourseMediaRequests.map((item, index) => {
if (item.mediaType === 'TEXT') {
return (
<div
className="intro-item text"
dangerouslySetInnerHTML={{
__html: item.mediaContent
}}
/>
)
}
if (item.mediaType === 'PICTURE') {
return (
<div className="intro-item picture">
<img src={item.mediaUrl} alt="intro-item__picture" />
</div>
)
}
return item;
})
}
</div>
</div>
</div>
</div>
</Modal>
)
}
}
export default PreviewCourseModal;
.preview-live-course-modal {
.ant-modal-body {
background-image: url('https://image.xiaomaiketang.com/xm/xZWdziTCAf.png');
background-size: 100% 100%;
}
.container__wrap {
width: 340px;
height: 618px;
padding: 67px 46px 48px 47px;
margin: auto;
background-image: url('https://image.xiaomaiketang.com/xm/DHMzHiGc2E.png');
background-size: 100% 100%;
}
.container {
overflow: scroll;
height: 100%;;
.course-cover, .course-url {
width: 100%;
height: 141px;
background: #000;
}
&__body {
background-color: #FFF;
padding: 7px 0 11px 0;;
.title__name {
color: #000;
}
.title__inst-name {
color: #666;
font-size: 12px;
margin-top: 4px;
}
&__title {
display: flex;
justify-content: space-between;
.title__name {
line-height: 20px;
color: #000;
font-weight: 500;
}
.title__state {
min-width: 40px;
height: 17px;
padding: 0 2px;
margin-left: 6px;
font-size: 12px;
color: #FFF;
background-color: #34B88B;
}
}
&__time, &__teacher {
display: flex;
align-items: center;
margin-top: 8px;
color: #999;
line-height: 17px;
span {
font-size: 12px;
}
}
&__teacher {
margin-top: 4px;
}
}
&__introduction {
margin-top: 10px;
padding: 12px 0;
position: relative;
&::before {
content: '';
position: absolute;
top: -12px;
left: 0;
width: 100%;
height: 10px;
background-color: #F4F6FA;
}
&__title {
font-size: 12px;
color: #333;
text-align: center;
line-height: 17px;
position: relative;
&::before,
&::after {
position: absolute;
content: "";
top: 8px;
width: 13px;
height: 1px;
background-color: #ccc;
}
&::before {
left: 32%;
}
&::after {
right: 32%;
}
}
&__list {
margin-top: 12px;
.intro-item:not(:first-child) {
margin-top: 13px;
}
.text {
color: #666;
line-height: 17px;
p {
font-size: 12px;
}
}
.picture {
img {
width: 100%;
}
}
}
}
}
}
\ No newline at end of file
<!--
* @Author: 吴文洁
* @Date: 2020-04-29 16:54:52
* @LastEditors: 吴文洁
* @LastEditTime: 2020-04-29 17:15:16
* @Description:
-->
### 业务组件,比如某几个页面公用的组件,和实际业务相关
**本目录的引用别名是 @/bu-components**
\ No newline at end of file
.select-prepare-file-modal {
.ant-upload-list {
display: none;
}
.lottie-icon {
margin: 12px 0 0 0;
border: 1px solid #E8E8E8;
border-radius: 4px;
padding: 100px 0;
.desc {
color: #999;
.upload-btn {
color: #FF7519;
margin: 0 4px;
cursor: pointer;
}
}
}
.radio-buttons {
text-align: center;
margin-bottom: 16px;
}
.file-path {
display: inline-block;
color: #333;
position: relative;
margin-bottom: 12px;
margin-right: 12px;
&:last-child {
color: #999;
}
&:not(:last-child) {
cursor: pointer;
&:hover {
color: #5289FA;
}
&::before {
content: '/';
position: absolute;
color: #CCC;
right: -8px;
}
}
}
.file-list {
border: 1px solid #E8E8E8;
border-radius: 4px;
.file-item {
display: flex;
align-items: center;
justify-content: space-between;
height: 48px;
padding: 12px 25px;
&:not(:last-child) {
border-bottom: 1px solid #E8E8E8;
}
&.enable {
cursor: pointer;
}
&.disable {
cursor: not-allowed;
opacity: 0.5;
}
&__cover {
min-width: 320px;
img {
margin-right: 8px;
}
}
&__size {
margin-left: 40px;
}
.iconfont {
color: #BFBFBF;
}
}
}
.ant-modal-footer {
display: flex;
align-items: center;
justify-content: space-between;
.prepare-lesson-upload.hidden {
visibility: hidden;
}
.prepare-lesson-upload.visible {
visibility: visible;
}
.footer__left {
color: #5289fa;
cursor: pointer;
}
}
}
\ No newline at end of file
/*
* @Author: 吴文洁
* @Date: 2020-07-20 19:12:49
* @Last Modified by: 吴文洁
* @Last Modified time: 2020-07-20 20:25:13
* @Description: 大班直播分享弹窗
*/
import React from 'react';
import { Modal, Button, message } from 'antd';
import html2canvas from 'html2canvas';
import QRCode from '@/lib/qrcode/qrcode';
import Service from '@/common/js/service';
import { copyText } from '@/domains/basic-domain/utils';
import './ShareLiveModal.less';
const { name } = window.currentUserInstInfo || {};
const DEFAULT_COVER = 'https://image.xiaomaiketang.com/xm/YNfi45JwFA.png';
class ShareLiveModal extends React.Component {
constructor(props) {
super(props);
this.state = {
shareUrl: 'https://xiaomai5.com/liveShare?courseId=12'
}
}
componentDidMount() {
// 获取短链接
this.handleConvertShortUrl();
}
handleConvertShortUrl = () => {
const { longUrl } = this.props.data;
// 发请求
Service.Sales('public/businessShow/convertShortUrls', {
urls: [longUrl]
}).then((res) => {
const { result = [] } = res;
this.setState({
shareUrl: result[0].shortUrl
}, () => {
const qrcodeWrapDom = document.querySelector('#qrcodeWrap');
const qrcodeNode = new QRCode({
text: this.state.shareUrl,
size: 98,
})
qrcodeWrapDom.appendChild(qrcodeNode);
});
})
}
componentWillUnmount() {
// 页面销毁之前清空定时器
clearTimeout(this.timer);
}
// 下载海报
handleDownloadPoster = () => {
const dom = document.querySelector('#poster');
html2canvas(dom, {
useCORS: true,
}).then(canvas => {
const downloadDOM = document.createElement('a');
const { courseName } = this.props.data;
const dataUrl = canvas.toDataURL('image/png');
downloadDOM.href = dataUrl;
downloadDOM.download = `${courseName}.png`;
downloadDOM.click();
});
}
// 复制分享链接
handleCopy = () => {
const textContent = document.getElementById('shareUrl').innerText;
copyText(textContent);
message.success('复制成功!');
}
render() {
const { needStr, data, type } = this.props;
const { courseName, coverUrl = DEFAULT_COVER, scheduleVideoUrl } = data;
const { shareUrl } = this.state;
// 判断是否是默认图, 默认图不需要在URL后面增加字符串
const isDefaultCover = coverUrl === DEFAULT_COVER;
const coverImgSrc = type === 'videoClass'
? (
// 如果是默认图, 显示视频的第一帧, 否则显示上传的视频封面
isDefaultCover
? `${scheduleVideoUrl}?x-oss-process=video/snapshot,t_0,m_fast&anystring`
: `${coverUrl}${!needStr ? '&anystring': ''}`
)
: `${coverUrl}${(!needStr && !isDefaultCover) ? '&anystring' : ''}`
return (
<Modal
title="分享直播课"
width={680}
visible={true}
footer={null}
maskClosable={false}
className="share-live-modal"
onCancel={this.props.close}
>
<div className="left" id="poster">
<div
className="course-name"
>{`【${courseName}】开课啦,快来学习!`}</div>
<img
src={coverImgSrc}
crossOrigin="*"
className="course-cover"
alt="course-cover"
/>
<div className="qrcode-wrap">
<div className="qrcode-wrap__left">
<div className="text">长按识别二维码进入观看</div>
<img
className="finger"
alt="finger"
src="https://image.xiaomaiketang.com/xm/thpkWDwJsC.png"
/>
</div>
<div className="qrcode-wrap__right" id="qrcodeWrap">
</div>
</div>
<div className="inst-name">
<span className="icon iconfont">&#xe7b1;</span>
<span className="text">{name}</span>
</div>
</div>
<div className="right">
<div className="share-url right__item">
<div className="title">① 链接分享</div>
<div className="sub-title">家长可通过微信打开链接,报名观看直播</div>
<div className="content">
<div className="share-url" id="shareUrl">{shareUrl}</div>
<Button
type="primary"
onClick={this.handleCopy}
>复制</Button>
</div>
</div>
<div className="share-poster right__item">
<div className="title">② 海报分享</div>
<div className="sub-title">家长可通过微信识别二维码,报名观看直播</div>
<div className="content" onClick={this.handleDownloadPoster}>下载海报</div>
</div>
</div>
</Modal>
)
}
}
export default ShareLiveModal;
.share-live-modal {
.ant-modal-body {
display: flex;
.left {
width: 303px;
padding: 20px;
margin: 0 32px 0 16px;
box-shadow:0px 2px 10px 0px rgba(0,0,0,0.05);
border-radius: 12px;
.course-name {
color: #333;
font-size: 16px;
font-weight: 500;
line-height: 20px;
}
.course-cover {
width: 263px;
height: 143px;
border-radius: 6px;
margin-top: 8px;
}
.qrcode-wrap {
padding: 0 16px;
display: flex;
align-items: center;
margin: 24px 0 16px 0;
&__left {
width: 98px;
text-align: center;
margin-right: 22px;
.text {
line-height: 20px;
}
.finger {
width: 40px;
height: 40px;
margin-top: 8px;
}
}
&__right {
width: 110px;
height: 110px;
padding: 6px
}
}
.inst-name {
background-color: #FAFAFA;
min-height: 36px;
border-radius: 9px;
padding: 8px 16px;
display: flex;
align-items: center;
.iconfont {
color: #999;
margin-right: 4px;
}
.text {
font-size: 12px;
color: #999;
}
}
}
.right {
.title {
color: #333;
font-weight: 500;
}
.sub-title {
color: #999;
margin-top: 16px;
}
.content {
display: flex;
align-items: center;
margin-top: 8px;
.share-url {
width: 212px;
overflow: hidden;
height: 32px;
line-height: 32px;
border-radius: 4px 0 0 4px;
padding-left: 12px;
white-space: nowrap;
color: #999999;
background: #EFEFEF;
}
.ant-btn {
margin-left: -2px;
}
}
.share-poster {
margin-top: 40px;
.content {
color: #FF7519;
cursor: pointer;
}
}
}
}
}
\ No newline at end of file
import React from 'react'
import './ShowTip.less'
function ShowTips(props) {
return (
<div className={`xm-show-tip xm-type-${props.type || 'defulat'}`} >
<span className="icon iconfont">&#xe6f2;</span>
<p>{props.message}</p>
</div>
)
}
export default ShowTips
\ No newline at end of file
.xm-show-tip {
position: relative;
min-height:32px;
background:#FFF4DD;
border-radius:4px;
display: flex;
justify-content: flex-start;
align-items: center;
padding: 0 12px;
span.icon {
color:#FF9D14;
line-height: 20px;
}
p {
color:#666666;
font-size: 14px;
line-height:20px;
margin-left: 12px;
}
}
.xm-type-default {
width: 100%;
}
.xm-type-info {
width: calc(~'100% - 190px');
}
\ No newline at end of file
.prepare-lesson-upload-progress-modal {
width: 448px;
position: fixed;
bottom: 32px;
right: 0;
box-shadow: 0px 4px 12px 0px rgba(0,0,0,0.1);
border-radius: 6px;
right: 48px;
background-color: #FFF;
z-index: 10;
&:visible {
display: block;
}
&.hidden {
display: none;
}
.modal-header {
display: flex;
align-items: center;
justify-content: space-between;
height: 50px;
line-height: 50px;
background-color: #9A9DA7;
border-radius: 6px;
padding: 0 24px;
color: #FFF;
&.no-radius {
border-radius: 6px 6px 0 0;
}
.over-all-progress span {
font-size: 16px;
}
.iconfont {
cursor: pointer;
font-size: 12px;
margin-left: 24px;
}
}
.modal-body {
max-height: 290px;
overflow: auto;
.file-item {
display: flex;
align-items: center;
height: 50px;
line-height: 50px;
padding: 0 24px;
position: relative;
&:not(:last-child) {
margin-bottom: 4px;
}
&__cover {
display: flex;
align-items: center;
img {
width: 24px;
margin-right: 8px;
}
.file-name {
min-width: 154px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
display: inline-block;
}
}
&__size {
margin: 0 24px;
min-width: 54px !important;
color:#999999;
}
&__status {
.iconfont {
color: #BFBFBF;
font-size: 12px;
&.succ {
color: #5DD333;
}
&.close, &.reupload {
position: absolute;
top: 1px;
right: 20px;
cursor: pointer;
}
&.fail {
color: rgba(255, 79, 79, 1);
}
}
}
&__progress {
height: 100%;
position: absolute;
height: 50px;
margin-left: -24px;
background-color: rgba(32,161,255,0.06);
}
}
}
}
\ No newline at end of file
/*
* @Author: louzhedong
* @Date: 2019-11-25 11:37:58
* @LastEditors: louzhedong
* @LastEditTime: 2019-11-25 11:37:58
* @Description:
*/
class XMEnum {
constructor(array) {
if (!Array.isArray(array)) {
throw 'array不是数组';
return;
}
array.map(item => {
this[item.name] = item;
})
}
}
export default XMEnum;
\ No newline at end of file
/*
* @Author: 吴文洁
* @Date: 2020-03-19 16:45:42
* @LastEditors: houyan
* @LastEditTime: 2020-06-24 11:24:54
* @Description:
*/
import XMEnum from './XMEnum';
export const HOME_WORK_TYPE = new XMEnum([
{
name: 'ONLY',
value: 'ONLY',
text: '单次(普通)',
},
{
name: 'EXAM',
value: 'EXAM',
text: '单次(测评)'
},
{
name: 'LOOP',
value: 'LOOP',
text: '连续(普通)'
}
])
export const RECORD_ERROR = new XMEnum([
{
name: 'NotAllowedError',
title: '请允许网页使用麦克风',
content: '麦克风已被禁用,请现在浏览器设置中允许当前望重使用你的麦克风'
},
{
name: 'PermissionDeniedError',
title: '请允许浏览器使用麦克风',
content: '麦克风已被禁用,请现在浏览器设置中允许使用麦克风'
},
{
name: 'NotFoundError',
title: '未找到麦克风设备',
content: '请确认麦克风是否可用'
},
{
name: 'DevicesNotFoundError',
title: '未找到麦克风设备',
content: '请确认麦克风是否可用'
},
{
name: 'NotSupportedError',
title: '设备不支持录音',
content: '该电脑暂不支持录音,请尝试使用其他设备'
}
]);
/*
* @Author: 吴文洁
* @Date: 2020-07-25 15:28:45
* @LastEditors: 吴文洁
* @LastEditTime: 2020-08-11 11:20:59
* @Description:
* @Copyright: 杭州杰竞科技有限公司 版权所有
*/
export const ORDER_TYPR_MAP = {
'CLASS': '上课扣费',
'RECORD': '录制扣费',
'RECHARGE': '充值',
'GIVE': '赠送',
'OTHER': '其他',
};
export const ORDER_DETAIL_TEXT_MAP = {
'RECORD': '录制扣费详情',
'CLASS': '上课扣费详情',
'RECHARGE': '充值详情',
'REFUND': '退款详情'
}
export const ORDER_STATUS_MAP = {
'PAY_UNDO': '待支付',
'PAY_SUCCESS': '已完成',
'PAY_CANCEL': '已失效'
}
export const ORDER_STATUS_COLOR_MAP = {
'PAY_SUCCESS': '#2FC83C',
'PAY_UNDO': '#FDBE31',
'PAY_CANCEL': '#CCCCCC',
}
export const PAT_TYPE_MAP = {
'ALI_PAY': '支付宝',
'WE_CHAT': '微信'
}
// 云课堂产品版本
export const CLOUD_CLASS_VERSION_MAP = {
'ULTIMATESELL': '旗舰版',
'PIP_TO_ULTIMATE': '标准版',
'HIGH_TO_ULTIMATE': '高级版'
}
export const LIVE_SHARE_MAP = {
dev: 'https://dev.xiaomai5.com/xiaomai-live-share/index.html#/',
rc: 'https://rc.xiaomai5.com/xiaomai-live-share/index.html#/',
gray: 'https://res.xiaomai5.com/xiaomai-live-share/gray/index.html#/',
prod: 'https://res.xiaomai5.com/xiaomai-live-share/index.html#/',
}
/*
* @Author: Michael
* @Date: 2020-02-10 10:08:39
* @Last Modified by: 吴文洁
* @Last Modified time: 2020-07-16 11:32:50
*/
const DEFAULT_SIZE_UNIT = 1024 * 1024; // 将B转换成M
const GIGABYTE_SIZE_UNIT = 1024 * 1024 * 1024; // 转换为G
const SupportFileType = [
"application/msword",
"text/csv",
"application/vnd.ms-excel",
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"application/vnd.ms-powerpoint",
"application/pdf",
"image/jpeg",
"image/png",
"audio/mpeg",
"audio/mp4",
"video/mp4",
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"application/vnd.openxmlformats-officedocument.presentationml.presentation",
"audio/mp3",
"application/wps-office.pdf",
"application/wps-office.xls"
];
const LocalFileType = [
"application/msword",
"application/vnd.ms-excel",
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"application/vnd.ms-powerpoint",
"application/pdf",
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"application/vnd.openxmlformats-officedocument.presentationml.presentation",
"application/wps-office.pdf",
"application/wps-office.xls"
]
const FileVerifyMap = {
"application/msword": {
type: "word",
maxSize: 100
},
"application/vnd.openxmlformats-officedocument.wordprocessingml.document": {
type: "word",
maxSize: 100
},
"text/csv": {
type: "Excel",
maxSize: 10
},
"application/vnd.ms-excel": {
type: "Excel",
maxSize: 10
},
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": {
type: "Excel",
maxSize: 10
},
"application/wps-office.xls": {
type: "Excel",
maxSize: 10
},
"application/vnd.ms-powerpoint": {
type: "PPT",
maxSize: 100
},
"application/vnd.openxmlformats-officedocument.presentationml.presentation": {
type: "PPT",
maxSize: 100
},
"application/pdf": {
type: "PDF",
maxSize: 100
},
"application/wps-office.pdf": {
type: "PDF",
maxSize: 100
},
"image/jpeg": {
type: "JPG",
maxSize: 5
},
"image/png": {
type: "JPG",
maxSize: 5
},
"image/jpg": {
type: "JPG",
maxSize: 5
},
"image/gif": {
type: "GIF",
maxSize: 5
},
"audio/mpeg": {
type: "MP3",
maxSize: 20
},
"audio/mp3": {
type: "MP3",
maxSize: 20
},
"audio/mp4": {
type: "MP4",
maxSize: 500
},
"video/mp4": {
type: "MP4",
maxSize: 500
}
};
const LessonFileTypeEnum = {
TEACH_PLAN: "教案",
COURSEWARE: "课件",
HOMEWORK: "作业"
};
const FileTypeIcon = {
word: "https://image.xiaomaiketang.com/xm/6biwHTSPe5.png",
DOCX: "https://image.xiaomaiketang.com/xm/6biwHTSPe5.png",
DOC: "https://image.xiaomaiketang.com/xm/6biwHTSPe5.png",
DOCX: "https://image.xiaomaiketang.com/xm/6biwHTSPe5.png",
// 第一期备后端返回的是长的文件类型,备课版改版之后后端返回的是短的文件类型,且大写,所以做个兼容,下面的EXCEl也是一样的
WORD: "https://image.xiaomaiketang.com/xm/6biwHTSPe5.png",
Excel: "https://image.xiaomaiketang.com/xm/h6a6eF882a.png",
EXCEL: "https://image.xiaomaiketang.com/xm/h6a6eF882a.png",
PPT: "https://image.xiaomaiketang.com/xm/847pFAdYGW.png",
PPTX: "https://image.xiaomaiketang.com/xm/847pFAdYGW.png",
PDF: "https://image.xiaomaiketang.com/xm/rrEJMNkhTG.png",
MP3: "https://image.xiaomaiketang.com/xm/ykjnSWDyQ6.png",
MP4: "https://image.xiaomaiketang.com/xm/whSYMTdR57.png",
JPG: "https://image.xiaomaiketang.com/xm/XRkX8JBTPs.png",
JPEG: "https://image.xiaomaiketang.com/xm/XRkX8JBTPs.png",
PNG: "https://image.xiaomaiketang.com/xm/XRkX8JBTPs.png",
GIF: "https://image.xiaomaiketang.com/xm/XRkX8JBTPs.png",
BMP: "https://image.xiaomaiketang.com/xm/XRkX8JBTPs.png",
};
const UploadIcon = "https://image.xiaomaiketang.com/xm/4DXNrZWWsd.png";
const FailIcon = "https://image.xiaomaiketang.com/xm/ZkWbrrbiRn.png";
const StorageColor = {
blue: "#58B7EF",
yellow: "linear-gradient(to right, #FBD140, #FFA201)",
red: "#EC4B35"
};
const suffixMap = {
'doc': 'application/msword',
'docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'ppt': 'application/vnd.ms-powerpoint',
'pptx': 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
'pdf': 'application/pdf',
'xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'xls': 'application/vnd.ms-excel'
}
const DISK_MAP = {
MYSELF: '我的文件',
COMMON: '公共文件',
EMPLOYEE: '员工文件'
}
const NonCompliantFileMap = {
'video': {
accept: 'video/mp4',
confirm: {
title: '文件过大,无法上传',
content: '为保障学员的观看体验,上传的视频大小不能超过100M',
},
tooltip: '格式支持mp4,大小不超过100M'
}
}
export {
DEFAULT_SIZE_UNIT,
FileVerifyMap,
FileTypeIcon,
LessonFileTypeEnum,
UploadIcon,
FailIcon,
StorageColor,
GIGABYTE_SIZE_UNIT,
SupportFileType,
suffixMap,
LocalFileType,
DISK_MAP,
NonCompliantFileMap
};
/*
* @Author: 吴文洁
* @Date: 2020-07-23 17:11:49
* @LastEditors: zhangleyuan
* @LastEditTime: 2020-12-18 17:54:36
* @Description:
* @Copyright: 杭州杰竞科技有限公司 版权所有
*/
const DEFAULT_SIZE_UNIT = 1024 * 1024; // 将B转换成M
const SupportFileType = [
"application/msword",
"application/vnd.ms-powerpoint",
"application/mspowerpoint",
"application/pdf",
"image/jpeg",
"audio/mpeg",
"audio/mp4",
"video/mp4",
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"application/vnd.openxmlformats-officedocument.presentationml.presentation",
"audio/mp3",
"application/wps-office.pdf",
"audio/x-mpeg",
"image/png",
];
const suffixType = {
ppt: 'application/vnd.ms-powerpoint',
pptx: 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
doc: 'application/msword',
docx: 'application/msword',
xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
xls: 'application/vnd.ms-excel',
pdf: 'application/pdf',
jpg: 'image/jpeg',
jpeg: 'image/jpeg',
png: 'image/png',
mp3: 'audio/mp3',
mp4: 'audio/mp4',
}
export {DEFAULT_SIZE_UNIT,SupportFileType,suffixType}
// export default {
// DEFAULT_SIZE_UNIT,
// SupportFileType,
// suffixType,
// };
export const DEAL_TYPE = {
'NO': '未超上',
'UN_DEAL': '超上未处理',
'MAKE_UP': '补扣',
'IGNORE': '标记不处理'
};
export const OVERSTEP_TYPE = {
'CLASS_HOUR_OWE': '点名超上',
'MONTH_OWE': '按月超上',
'IMPORT_HOUR_OWE': '导入超上'
};
# 营销线相关常量
\ No newline at end of file
/*
* @Author: louzhedong
* @Date: 2019-11-25 11:40:53
* @LastEditors: louzhedong
* @LastEditTime: 2019-11-25 11:41:47
* @Description: 电子表单fieldProperty枚举
*/
import XMEnum from '../XMEnum';
const fieldProperty = new XMEnum([
{name: 'CUSTOM', code: -1},
{name: 'NAME', code: 1},
{name: 'PHONE', code: 2},
{name: 'GENDER', code: 3},
{name: 'AGE', code: 4},
{name: 'BIRTHDAY', code: 5},
{name: 'SCHOOL', code: 6},
{name: 'GRADE', code: 7},
{name: 'ADDRESS', code: 8},
]);
export default fieldProperty;
\ No newline at end of file
/*
* @Author: 吴文洁
* @Date: 2019-11-08 10:31:08
* @Last Modified by: 吴文洁
* @Last Modified time: 2020-02-25 15:50:21
礼品集市常量
*/
import Enum from '@/core/enum';
const OrderStateEnum = new Enum([{
key: 'PAY_WAITING',
value: '待付款',
icon: 'https://xiaomai-image.oss-cn-hangzhou.aliyuncs.com/1573191434106.png?x-oss-process=image/resize,w_80,limit_0'
}, {
key: 'PAY_TIMEOUT',
value: '支付超时',
icon: 'https://xiaomai-image.oss-cn-hangzhou.aliyuncs.com/1573191455406.png?x-oss-process=image/resize,w_80,limit_0'
}, {
key: 'WATING_AUDIT',
value: '待受理',
desc: '订单正在受理中,请耐心等待',
icon: 'https://xiaomai-image.oss-cn-hangzhou.aliyuncs.com/1573191403102.png?x-oss-process=image/resize,w_80,limit_0'
}, {
key: 'PAY_SUCCESS',
value: '待受理',
desc: '订单正在受理中,请耐心等待',
icon: 'https://xiaomai-image.oss-cn-hangzhou.aliyuncs.com/1573191403102.png?x-oss-process=image/resize,w_80,limit_0'
}, {
key: 'AUDIT_FAILED',
value: '受理失败',
icon: 'https://xiaomai-image.oss-cn-hangzhou.aliyuncs.com/1574673840912.png?x-oss-process=image/resize,w_80,limit_0'
}, {
key: 'USER_CANCEL',
value: '已取消',
icon: 'https://xiaomai-image.oss-cn-hangzhou.aliyuncs.com/1573191455406.png?x-oss-process=image/resize,w_80,limit_0'
}, {
key: 'WATING_DELIVER',
value: '待发货',
desc: '商品待发出,请耐心等待',
icon: 'https://xiaomai-image.oss-cn-hangzhou.aliyuncs.com/1573191392327.png?x-oss-process=image/resize,w_80,limit_0'
}, {
key: 'FINISH_DELIVER',
value: '已发货',
desc: '商品已发出,正在快马加鞭的赶来~ ',
icon: 'https://xiaomai-image.oss-cn-hangzhou.aliyuncs.com/1573191392327.png?x-oss-process=image/resize,w_80,limit_0'
}, {
key: 'RECEIVED',
value: '已完成',
desc: '本次交易已完成!',
icon: 'https://xiaomai-image.oss-cn-hangzhou.aliyuncs.com/1573191420713.png?x-oss-process=image/resize,w_80,limit_0'
}]);
const RefundStateEnum = new Enum([{
key: 'WAITING_SURE',
value: '待确认',
}, {
key: 'REFUNDING',
value: '退款中',
}, {
key: 'REFUND_SUCCESS',
value: '退款成功',
}, {
key: 'REFUND_FAILED',
value: '退款失败',
}]);
const OrderStateMap = {
'PAY_WAITING': '待付款',
'USER_CANCEL': '已取消',
'WATING_DELIVER': '待发货',
'FINISH_DELIVER': '已发货',
'RECEIVED': '已完成',
'AUDIT_FAILED': '受理失败',
}
export {
OrderStateEnum,
RefundStateEnum,
OrderStateMap
}
\ No newline at end of file
/*
* @Author: 吴文洁
* @Date: 2019-09-25 18:07:33
* @Last Modified by: 吴文洁
* @Last Modified time: 2020-02-25 15:50:29
* @Descript: 会员宝相关常量
*/
import Enum from '@/core/enum';
const PointsExchangeStatus = new Enum([{
key: 'WATING_AUDIT',
id: 'WATING_AUDIT',
value: '待审核',
name: '待审核',
color: '#FF8534'
}, {
key: 'USER_CANCEL',
id: 'USER_CANCEL',
value: '已撤销',
name: '已撤销',
color: '#999'
}, {
key: 'WATING_DELIVER',
id: 'WATING_DELIVER',
value: '待发放',
name: '待发放',
color: '#58B7EF'
}, {
key: 'FINISH_DELIVER',
id: 'FINISH_DELIVER',
value: '已发放',
name: '已发放',
color: '#3BBDAA'
}]);
const orderStateMap = {
'WATING_AUDIT': '待审核',
'USER_CANCEL': '已撤销',
'WATING_DELIVER': '待发放',
'FINISH_DELIVER': '已发放'
}
export {
PointsExchangeStatus,
orderStateMap
}
\ No newline at end of file
/*
* @Author: 吴文洁
* @Date: 2020-02-25 15:56:03
* @Last Modified by: wufan
* @Last Modified time: 2020-07-09 12:07:14
微官网相关常量
*/
import XMEnum from '../XMEnum';
const marketingToolsTabNames = [{ type: 'show', name:'小麦秀' },{type: 'coupon',name:'优惠券'} ];
const TabNames = [
'brand', 'course', 'teacher', 'student',
'environment', 'activity', 'material', 'news'
];
const TextEnum = new XMEnum([
{
module: 'BRAND_INTRO',
name: 'brand',
tabLabel: '品牌介绍',
detailLabel: '机构详情',
placeholder: '请填写简介,30字以内',
coverUrl: 'https://xiaomai-image.oss-cn-hangzhou.aliyuncs.com/1583836090586.png'
},
{
module: 'CAMPUS_ENVIRON',
name: 'environment',
tabLabel: '校区环境',
detailLabel: '校区详情',
placeholder: '请填写简介,30字以内',
coverUrl: 'https://xiaomai-image.oss-cn-hangzhou.aliyuncs.com/1583836118436.png'
},
{
module: 'ACTIVITY_STYLE',
name: 'activity',
tabLabel: '活动风采',
nameLabel: '活动名称',
coverLabel: '活动封面',
detailLabel: '活动详情',
coverWidth: 156,
coverHeight: 80,
coverUrl: 'https://xiaomai-image.oss-cn-hangzhou.aliyuncs.com/1583824443588.png'
},
{
module: 'HOT_COURSE',
name: 'course',
tabLabel: '热门课程',
nameLabel: '课程名称',
introLabel: '课程简介',
coverLabel: '课程封面',
detailLabel: '课程详情',
placeholder: '请填写课程简介,例如:针对4~8岁的孩子,重点培养的基础绘画技能、激发艺术表现。30字以内',
coverUrl: 'https://xiaomai-image.oss-cn-hangzhou.aliyuncs.com/1583823404400.png'
},
{
module: 'FACULTY_TEAM',
name: 'teacher',
tabLabel: '师资团队',
nameLabel: '老师姓名',
introLabel: '老师简介',
coverLabel: '老师照片',
detailLabel: '老师详情',
placeholder: '请填写老师亮点,简短精炼,例如:5年教龄,名校毕业,平易近人。30字以内',
coverUrl: 'https://xiaomai-image.oss-cn-hangzhou.aliyuncs.com/1583823414781.png'
},
{
module: 'STAR_STUDENT',
name: 'student',
tabLabel: '明星学员',
nameLabel: '学员姓名',
introLabel: '学员简介',
coverLabel: '学员照片',
detailLabel: '学员详情',
placeholder: '请填写学员简介/宣言,例如: 持之以恒,必将有好的收获。闪亮之星小阮的学习之旅~。30字以内',
coverUrl: 'https://xiaomai-image.oss-cn-hangzhou.aliyuncs.com/1583823429407.png'
},
{
module: 'STUDY_MATERIALS',
name: 'material',
tabLabel: '学习资料',
nameLabel: '资料名称',
coverLabel: '资料封面',
detailLabel: '资料详情',
coverWidth: 156,
coverHeight: 80,
coverUrl: 'https://xiaomai-image.oss-cn-hangzhou.aliyuncs.com/1583823443748.png'
},
{
module: 'NEWS',
name: 'news',
tabLabel: '新闻动态',
nameLabel: '新闻标题',
coverLabel: '新闻封面',
detailLabel: '新闻详情',
coverUrl: 'https://xiaomai-image.oss-cn-hangzhou.aliyuncs.com/1583823455499.png'
},
])
export default TextEnum;
export {
TabNames,
marketingToolsTabNames
}
\ No newline at end of file
/*
* @Author: 吴文洁
* @Date: 2019-09-25 18:09:07
* @Last Modified by: wufan
* @Last Modified time: 2020-07-11 13:48:57
* @Description: 小麦秀相关常量
*/
const isRc = location.host.indexOf('rc') !== -1;
const isDev = location.host.indexOf('localhost') !== -1 || location.host.indexOf('dev.xiaomai5.com') !== -1;
const isGray = location.href.indexOf('gray') !== -1;
const isDev1 = location.href.indexOf('dev1') !== -1;
let host = 'https://dev.xiaomai5.com/show/';
let latestHost = 'https://dev.xiaomai5.com/xmshow/#/';
if (isDev) {
host = 'https://dev.xiaomai5.com/show/';
latestHost = 'https://dev.xiaomai5.com/xmshow/#/';
} else if (isDev1) {
host = 'https://dev1.xiaomai5.com/show/';
latestHost = 'https://dev1.xiaomai5.com/xmshow/#/';
} else if (isRc) {
host = 'https://rc.xiaomai5.com/show/';
latestHost = 'https://rc.xiaomai5.com/xmshow/#/';
} else if (isGray) {
host = 'https://res.xiaomai5.com/show/';
latestHost = 'https://res.xiaomai5.com/xmshow/gray/index.html#/';
} else {
host = 'https://res.xiaomai5.com/show/';
latestHost = 'https://res.xiaomai5.com/xmshow/index.html#/';
}
export const HOST = host;
export const LATESTHOST = latestHost;
export const IS_DEV = isDev;
export const IS_DEV1 = isDev1;
export const IS_RC = isRc;
export const IS_GRAY = isGray;
export const TEMPLATE_TYPE = {
'groupType': '团购',
'lessonType': '微传单',
'bargainType': '砍价',
'tyType': '集赞',
'solitaireType': '群接龙',
'redPackageType': '微游戏',
'rollType': '抽奖',
'voteType': '投票',
'gachaType':'扭蛋机',
'distributeType': '分销'
};
export const TAG_TYPE = {
'holiday': '节假日',
'spring': '春招',
'summer': '夏招',
'autumn': '秋招',
'winter': '冬招',
'keepClass': '续班',
'lesson': '体验课',
'other': '其他'
};
// 活动参与详情年级常量
export const GRADE = [
{ label: "学前", value: 1004 },
{ label: "小班", value: 1001 },
{ label: "中班", value: 1002 },
{ label: "大班", value: 1003 },
{ label: "小学", value: 7 },
{ label: "一年级", value: 1 },
{ label: "二年级", value: 2 },
{ label: "三年级", value: 3 },
{ label: "四年级", value: 4 },
{ label: "五年级", value: 5 },
{ label: "六年级", value: 6 },
{ label: "初中", value: 14 },
{ label: "初中一年级", value: 11 },
{ label: "初中二年级", value: 12 },
{ label: "初中三年级", value: 13 },
{ label: "高中", value: 104 },
{ label: "高中一年级", value: 101 },
{ label: "高中二年级", value: 102 },
{ label: "高中三年级", value: 103 }
];
// 活动参与详情性别常量
export const GENDER = [
{ label: "男", value: 1 },
{ label: "女", value: 2 }
];
export const SCENE_LIST = [
{
name: "全部",
val: "all",
active: true
},
{
name: "节假日",
val: "holiday"
},
{
name: "春招",
val: "spring"
},
{
name: "夏招",
val: "summer"
},
{
name: "秋招",
val: "autumn"
},
{
name: "冬招",
val: "winter"
},
{
name: "续班",
val: "keepClass"
},
{
name: "体验课",
val: "lesson"
},
{
name: "其他",
val: "other"
}
];
export const TYPE_LIST = [
{
name: "全部",
val: "all",
active: true
},
{
name: "微传单",
val: "lessonType"
},
{
name: "砍价",
val: "bargainType"
},
{
name: "团购",
val: "groupType"
},
{
name: "群接龙",
val: "solitaireType"
},
{
name: "集赞",
val: "tyType"
},
{
name: "微游戏",
val: "redPackageType"
},
{
name: "抽奖",
val: "rollType"
},
{
name: "投票",
val: "voteType"
},
{
name: "扭蛋机",
val: "gachaType"
},
{
name: '分销',
val: 'distributeType'
}
];
export const SHOW_STATUS = {
'IN_PROGRESS': {
status: 'IN_PROGRESS',
label: '进行中',
color:"rgba(47,200,60,1)"
},
'ENDED':{
status: 'ENDED',
label: '已结束',
color:"rgba(204,204,204,1)"
},
'IN_VALID': {
status: 'IN_VALID',
label: '已失效',
color:"rgba(204,204,204,1)"
},
'DELETED':{
status: 'DELETED',
label: '已删除',
color:"rgba(204,204,204,1)"
}
};
\ No newline at end of file
/*
* @Author: 陈剑宇
* @Date: 2020-10-28 14:27:07
* @LastEditTime: 2020-11-02 20:25:15
* @LastEditors: 陈剑宇
* @Description:
* @FilePath: /xiaomai-web-b/app/common/constants/punchClock/punchClock.js
* @symbol_custom_string_obkoro1: Copyright © 2020 杭州杰竞科技有限公司 版权所有
*/
export const DEFAULT_IMG_URL = 'https://image.xiaomaiketang.com/xm/2MWCKBNiya.png';
export const DEFAULT_CALENDAR_TEXT = '<p>亲爱的同学:</p><p>欢迎参加《麦麦教育0基础21天英语打卡活动》,大家都知道21天养成一个好习惯。在未来的21天里,老师将和同学们一起完成21个打卡任务,0基础锻炼口语发音能力,让听英语并且跟读英语成为生活中的一部分。</p><p>打卡时间:2020年6月1日-6月23日(共21天)</p><p>其中休息日:6月6日、6月7日</p><p>打卡任务:坚持21天英语打卡学习,并且分享至朋友圈</p><p>分享格式:麦麦教育0基础21天英语打卡+学生名字 +第X天 +坚持就是胜利!</p><p>打卡奖励:</p><p>①坚持完成“21天打卡”的宝贝可以获得精美小礼品!</p><p>②每天分享打卡任务到朋友圈的小宝贝,还可以获得一份大礼包哦~</p><p>老师有话说:小宝贝每天只可完成1个打卡任务,做到真正吃透后再进行下一个任务哦。</p>';
export const DEFAULT_PASS_TEXT = '<p>亲爱的同学:</p><p>欢迎参加《麦麦芭蕾形体初级课打卡活动》,我们将通过芭蕾的几个特性如开、绷、直等,使身体各部位发展均衡,宝贝们每天需学完当前课时并完成打卡,才能解锁下一个课时内容</p><p>打卡时间:2020年6月1日-6月21日(共21天)</p><p>关卡数:共15关</p><p>每日可解锁上限:2关</p><p>打卡任务:坚持初级课闯关打卡课程,并且分享至朋友圈</p><p>分享格式:麦麦芭蕾0基础形体课打卡+学生名字 +第X关 +坚持就是胜利!</p><p>打卡奖励:</p><p>①坚持完成“闯关打卡”的宝贝可以获得精美小礼品!</p><p>②每关都分享打卡任务到朋友圈的小宝贝,还可以获得一份大礼包哦~</p><p>老师有话说:小宝贝每天最多完成2个任务,做到真正吃透后再进行下一个任务哦</p>';
export const NUM_TO_WORD_MAP = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
// 日历打卡
export const CALENDAR_CLOCK = 'CALENDAR_CLOCK';
// 闯关打卡
export const PASS_GATE = 'PASS_GATE';
// 答题模式
export const ANSWER_THE_QUESTION = 'ANSWER_THE_QUESTION'
// 普通模式
export const ORDINARY = 'ORDINARY';
// 学生类型
export const STUDENT_TYPE = {
NORMAL: '在读学员',
POTENTIAL: '潜在学员',
HISTORY: '历史学员'
}
// 打卡情况
export const CLOCK_STATUS = {
CLOCKED: '已打卡',
NO_CLOCK: '未打卡',
NO_DATA: '从未打卡'
}
// 日签下载状况
export const DOWNLOAD_DAY_SIGN_STATUS = {
DOWNED: '已下载',
NO_DOWN: '未下载',
}
// 作业排序
export const ORDER_RULE_ENUM = [{
key: 'DEFAULT',
label: '默认排序'
},
{
key: 'SCORE',
label: '得分由高到低'
},
{
key: 'BE_LIKE_NUM',
label: '点赞数由高到低'
}
]
export const QUESTION_TYPE_MAP = [{
type: 'THE_RADIO',
title: '单选题',
componentType: 'Radio',
key: 'THE_RADIO',
icon: <React.Fragment>&#xe773;</React.Fragment>,
},
{
type: 'MULTI_SELECT',
title: '多选题',
componentType: 'Checkbox',
key: 'MULTI_SELECT',
icon: <React.Fragment>&#xe775;</React.Fragment>,
},
{
type: 'JUDGE',
title: '判断题',
componentType: 'Radio',
key: 'JUDGE',
icon: <React.Fragment>&#xe7bb;</React.Fragment>,
}
]
export const MODULE_MEDIA_MAP = [{
title: '文字',
icon: <React.Fragment>&#xe760;</React.Fragment>,
key: 'TEXT',
},
{
title: '图片',
icon: <React.Fragment>&#xe6ac;</React.Fragment>,
key: 'PICTURE',
},
{
title: '音频',
icon: <React.Fragment>&#xe75f;</React.Fragment>,
key: 'VOICE',
},
{
title: '视频',
icon: <React.Fragment>&#xe75e;</React.Fragment>,
key: 'VIDEO',
},
{
title: '文件',
icon: <React.Fragment>&#xe759;</React.Fragment>,
key: 'FILE',
}]
export const FILE_ACCEPT = {
PICTURE: 'image/jpg,image/jpeg,image/png,image/bmp,image/gif',
VIDEO: 'audio/mp4,video/mp4',
VOICE: 'audio/x-mpeg,audio/mp3,audio/mpeg,audio/wav,audio/x-m4a'
}
export const QUESTION_FILE_ACCEPT = {
PICTURE: 'image/jpg,image/jpeg,image/png,image/gif',
VIDEO: 'audio/mp4,video/mp4',
VOICE: 'audio/x-mpeg,audio/mp3,audio/mpeg'
}
export const MODE_ENUM_MAP = {
general: {
title: '普通模式',
enumType: 'ORDINARY',
example: [{
title: '普通模式',
img: 'https://image.xiaomaiketang.com/xm/jSQGeQQdkN.png'
}]
},
answer: {
title: '答题模式',
enumType: 'ANSWER_THE_QUESTION',
example: [{
title: '答题模式-答题首页',
img: 'https://image.xiaomaiketang.com/xm/Qb8WaDaNCM.png'
}, {
title: '答题模式-答题页',
img: 'https://image.xiaomaiketang.com/xm/ERkGNsRP4G.png'
}, {
title: '答题模式-答题报告',
img: 'https://image.xiaomaiketang.com/xm/HGyPthnCJx.png'
}]
}
}
export const MODE_MAP = [{
img: 'https://image.xiaomaiketang.com/xm/S6YYwZwitP.png',
title: '普通模式',
desc: '每一个任务内可加入文本、图片、音频、视频等内容,学员查看任务要求后直接提交打卡',
modeKey: 'general',
enumType: 'ORDINARY',
}, {
img: 'https://image.xiaomaiketang.com/xm/hPPwp8F2zT.png',
title: '答题模式',
desc: '可添加单选、多选、判断等类型题目,学生提交后系统将自动评分',
modeKey: 'answer',
enumType: 'ANSWER_THE_QUESTION',
}]
export const TRUE_OR_FALSE_MAP = [{
value: 'RIGHT_OR_WRONG',
label: ['对', '错']
},
{
value: 'T_F',
label: ['T', 'F'],
alias: ['True', 'False']
},
{
value: 'TICK',
label: ['✓', '×']
}
]
export const TRUE_OR_FALSE_KEY_MAP = {
RIGHT_OR_WRONG: ['对', '错'],
T_F: ['T', 'F'],
TICK: ['✓', '×']
}
export const MEDIA_DESC_MAP = {
VIDEO: '[视频]',
VOICE: '[音频]',
PICTURE: '[图片]'
}
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: 吴文洁 * @Author: 吴文洁
* @Date: 2020-08-31 09:34:31 * @Date: 2020-08-31 09:34:31
* @LastEditors: zhangleyuan * @LastEditors: zhangleyuan
* @LastEditTime: 2020-12-10 18:19:45 * @LastEditTime: 2020-12-22 15:24:03
* @Description: * @Description:
* @Copyright: 杭州杰竞科技有限公司 版权所有 * @Copyright: 杭州杰竞科技有限公司 版权所有
*/ */
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: 吴文洁 * @Author: 吴文洁
* @Date: 2020-08-31 09:34:51 * @Date: 2020-08-31 09:34:51
* @LastEditors: wufan * @LastEditors: wufan
* @LastEditTime: 2020-12-01 15:30:03 * @LastEditTime: 2020-12-17 14:14:43
* @Description: * @Description:
* @Copyright: 杭州杰竞科技有限公司 版权所有 * @Copyright: 杭州杰竞科技有限公司 版权所有
*/ */
...@@ -31,6 +31,10 @@ class Service { ...@@ -31,6 +31,10 @@ class Service {
return Axios.post('POST', url, params, option); return Axios.post('POST', url, params, option);
} }
static get(url: string, params: any, option?: any) {
return Axios.post('GET', url, params, option);
}
static MFS(url: string, params: any, option: any) { static MFS(url: string, params: any, option: any) {
return Axios.post('POST', `mfs/${url}`, params, option); return Axios.post('POST', `mfs/${url}`, params, option);
} }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: 吴文洁 * @Author: 吴文洁
* @Date: 2020-08-31 09:34:25 * @Date: 2020-08-31 09:34:25
* @LastEditors: wufan * @LastEditors: wufan
* @LastEditTime: 2020-12-08 15:31:43 * @LastEditTime: 2020-12-26 14:19:23
* @Description: * @Description:
* @Copyright: 杭州杰竞科技有限公司 版权所有 * @Copyright: 杭州杰竞科技有限公司 版权所有
*/ */
...@@ -27,6 +27,9 @@ class User { ...@@ -27,6 +27,9 @@ class User {
getUserId(){ getUserId(){
return Storage.get(`${PREFIX}_userId`) return Storage.get(`${PREFIX}_userId`)
} }
getUserRole(){
return Storage.get(`${PREFIX}_userRole`)
}
getToken() { getToken() {
return Storage.get(`${PREFIX}_token`); return Storage.get(`${PREFIX}_token`);
...@@ -48,6 +51,10 @@ class User { ...@@ -48,6 +51,10 @@ class User {
return Storage.set(`${PREFIX}_userId`,value) return Storage.set(`${PREFIX}_userId`,value)
} }
setUserRole(value:any){
return Storage.set(`${PREFIX}_userRole`,value)
}
setToken(value:any) { setToken(value:any) {
return Storage.set(`${PREFIX}_token`,value); return Storage.set(`${PREFIX}_token`,value);
} }
......
@font-face { @font-face {
font-family: 'iconfont'; /* project id 2223403 */ font-family: 'iconfont'; /* project id 2223403 */
src: url('//at.alicdn.com/t/font_2223403_uo63ciaamd.eot'); src: url('//at.alicdn.com/t/font_2223403_w7su9rdwngo.eot');
src: url('//at.alicdn.com/t/font_2223403_uo63ciaamd.eot?#iefix') format('embedded-opentype'), src: url('//at.alicdn.com/t/font_2223403_w7su9rdwngo.eot?#iefix') format('embedded-opentype'),
url('//at.alicdn.com/t/font_2223403_uo63ciaamd.woff2') format('woff2'), url('//at.alicdn.com/t/font_2223403_w7su9rdwngo.woff2') format('woff2'),
url('//at.alicdn.com/t/font_2223403_uo63ciaamd.woff') format('woff'), url('//at.alicdn.com/t/font_2223403_w7su9rdwngo.woff') format('woff'),
url('//at.alicdn.com/t/font_2223403_uo63ciaamd.ttf') format('truetype'), url('//at.alicdn.com/t/font_2223403_w7su9rdwngo.ttf') format('truetype'),
url('//at.alicdn.com/t/font_2223403_uo63ciaamd.svg#iconfont') format('svg'); url('//at.alicdn.com/t/font_2223403_w7su9rdwngo.svg#iconfont') format('svg');
} }
.iconfont{ .iconfont{
font-family:"iconfont" !important; font-family:"iconfont" !important;
font-size:16px; font-size:16px;
font-style:normal; font-style:normal;
} }
\ No newline at end of file
...@@ -10,4 +10,18 @@ ...@@ -10,4 +10,18 @@
background: #fff; background: #fff;
padding: 16px; padding: 16px;
margin-top: 16px; margin-top: 16px;
}
.row-dragging {
background: #fafafa;
border: 1px solid #ccc;
}
.row-dragging td {
padding: 16px;
visibility: hidden;
}
.row-dragging .drag-visible {
visibility: visible;
} }
\ No newline at end of file
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
.ant-breadcrumb{ .ant-breadcrumb{
display: inline-block; display: inline-block;
span{ span{
color: #989898; color: #333;
font-weight: 400; font-weight: 400;
} }
} }
......
...@@ -27,9 +27,10 @@ const Breadcrumbs = (props: BreadcrumbsProps) => { ...@@ -27,9 +27,10 @@ const Breadcrumbs = (props: BreadcrumbsProps) => {
const isArray = _.isArray(navList); const isArray = _.isArray(navList);
return ( return (
<div className="xm-breadCrumb"> <div className="xm-breadCrumb">
<span onClick={_onClick} className="back-btn" /> <span onClick={_onClick} className="back-btn">
<LeftOutlined/> <LeftOutlined/>
<span className="text ml5" >{text ? text : '返回'}</span> <span className="text ml5" >{text ? text : '返回'}</span>
</span>
<div className="divide"></div> <div className="divide"></div>
<Breadcrumb> <Breadcrumb>
{isString && <Breadcrumb.Item>{navList}</Breadcrumb.Item>} {isString && <Breadcrumb.Item>{navList}</Breadcrumb.Item>}
......
/*
* @Author: sunbingqing
* @Date: 2019-08-05 11:05:00
* @Last Modified by: zhujian
* @Last Modified time: 2020-05-26 19:50:20
*/
import React from 'react';
import { Spin, Select } from 'antd';
import _ from 'underscore';
import Service from '@/common/js/service';
class ClassSearchSelect extends React.Component {
constructor(props) {
super(props);
this.state = {
query: {
size: 10,
current: 1,
classNameLike: null,
status: ['INIT', 'STUDYING', 'END'],
},
dataSet: [],
isAll: false
}
}
componentWillMount() {
this.handleFetchClassList();
}
handleFetchClassList = (current = 1) => {
const { courseId } = this.props;
const _query = _.clone(this.state.query);
_query.courseId = courseId;
_query.current = current;
Service.Business('public/class/digestList', _query)
.then((res) => {
const { result = {} } = res || {};
const { records = [], hasNext = false } = result;
_.map(records, (item) => {
item.formatName = item.name;
return item;
});
this.setState({
isAll: !hasNext,
dataSet: current === 1 ? records : [...this.state.data, ...records]
});
})
}
handleClassSelect = (classId) => {
const { query } = this.state;
if (query.classNameLike) {
query.classNameLike = null;
this.setState({ query }, this.handleFetchClassList);
}
this.props.onSelect(classId);
}
handleFetchMore = (e) => {
const { isAll } = this.state;
const ulDom = e.currentTarget.getElementsByTagName("ul")[0];
if (ulDom.length <= 0) return;
const { scrollTop, clientHeight, scrollHeight } = ulDom;
if (scrollTop + clientHeight > scrollHeight - 30 && !isAll) {
this.handleFetchClassList();
}
}
render() {
const { label, defaultValue, placeholder } = this.props;
const { query, isAll, dataSet } = this.state;
return (
<div className={"common-select staticSelect"}>
{
!!label && <div className='label'> {label}:</div>
}
<Select
showSearch
allowClear
onSearch={(value) => {
query.classNameLike = value;
this.setState({ query }, this.handleFetchClassList)
}}
onPopupScroll={this.handleFetchMore}
placeholder={placeholder}
value={defaultValue}
onChange={this.handleClassSelect}
filterOption={(input, option) => option}
>
{
_.map(dataSet, (item, index) => {
return (
<Select.Option
id={`class_select_item_${index}` }
key={item.classId}
value={item.classId}
title={item.name}
>
{item.name}
</Select.Option>
);
})
}
{!isAll &&
<Select.Option
disabled
tyle={{ textAlign: 'center' }}
value="spin"
>
<Spin size="small" />
</Select.Option>
}
</Select>
</div>
)
}
}
export default ClassSearchSelect;
/*
* @Author: leehu
* @Date: 2017-09-04 11:52:25
* @Last Modified by: zhujian
* @Last Modified time: 2020-03-09 20:19:04
*/
import React from 'react';
import { Spin, Select } from 'antd';
import _ from 'underscore';
import classNames from 'classnames';
import Service from '@/common/js/service';
class CourseSelect extends React.Component {
constructor(props) {
super(props);
this.state = {
close: true,
dataSource: [],
query: {
current: 1,
size: 10000,
showNumber: 100,
courseNameLike: null,
},
dataSet: [],
visible: false,
loading: false,
selectedIds: [],
selected: props.selected || [],
}
}
componentWillMount() {
this.handleFetchCourseList();
}
handleQueryReset = () => {
this.setState({
query: {
current: 1,
size: 10000,
showNumber: 100,
courseNameLike: null,
}
}, () => {
this.handleFetchCourseList();
});
}
handleFetchCourseList(current = 1) {
this.setState({ loading: true });
let query = _.clone(this.state.query)
if (this.props.queryAll) {
delete query.status;
}
query.current = current;
Service.Business('public/course/digestList', query)
.then((res) => {
const { result = {} } = res || {};
let { records = [], total = 0, hasNext } = result;
records.map(function (item, index) {
item.title = item.name;
item.desc = item.name;
return item;
});
this.setState({
dataSet: current > 1 ? [...this.state.dataSet, ...records] : records,
isAll: !hasNext,
loading: false,
totalCount: Number(total),
});
}).finally((res) => {
this.setState({ loading: false });
});
}
handleCourseSelect = (course) => {
const { query } = this.state;
if (query.courseNameLike) {
query.courseNameLike = null;
this.setState({ query }, this.handleFetchCourseList);
}
this.props.onSelect(course);
}
render() {
const {
id,
style,
label,
defaultValue,
placeholder = '请选择'
} = this.props;
const { visible, query, dataSet, isAll } = this.state;
return (
<div
className={classNames("common-select staticSelect", {
'common-select-active': visible
})}
style={style}>
{
!!label && <div className='label'> {label}:</div>
}
<Select
id={id}
ref='course'
showSearch
allowClear
onSearch={(value) => {
query.courseNameLike = value
this.setState({ query }, this.handleFetchCourseList)
}}
onBlur={() => {
query.courseNameLike = null;
this.setState({ query }, this.handleFetchCourseList)
}}
placeholder={placeholder}
value={defaultValue}
onChange={this.handleCourseSelect}
filterOption={(input, option) => option}
>
{
_.map(dataSet, (item, index) => {
return <Select.Option id={'course_select_item_' + index} key={item.id} value={item.id} title={item.name}>
{item.name}
</Select.Option>
})
}
{!isAll &&
<Select.Option disabled style={{ textAlign: 'center' }} value="spin">
<Spin size="small" />
</Select.Option>
}
</Select>
</div>
)
}
}
export default CourseSelect;
\ No newline at end of file
...@@ -12,8 +12,8 @@ import $ from 'jquery'; ...@@ -12,8 +12,8 @@ import $ from 'jquery';
import '@/libs/cropper/cropper.min.css'; import '@/libs/cropper/cropper.min.css';
import 'cropper'; import 'cropper';
import Upload from '../core/upload'; import Upload from '../core/upload';
import baseImg from '@/common/images/xiaomai-IMG.png';
import './CropperModal.less'; import './CropperModal.less';
const baseImg ='https://image.xiaomaiketang.com/xm/rJeQaZxtc7.png'
interface CropperModalProps { interface CropperModalProps {
title?: string; title?: string;
...@@ -61,6 +61,7 @@ const CropperModal = (props: CropperModalProps) => { ...@@ -61,6 +61,7 @@ const CropperModal = (props: CropperModalProps) => {
}); });
}); });
} }
function _handleSave(): any { function _handleSave(): any {
if (clickStatus) { if (clickStatus) {
...@@ -99,6 +100,7 @@ const CropperModal = (props: CropperModalProps) => { ...@@ -99,6 +100,7 @@ const CropperModal = (props: CropperModalProps) => {
width={600} width={600}
title={title || '设置头像'} title={title || '设置头像'}
visible={true} visible={true}
maskClosable={false}
footer={[ footer={[
<Button <Button
id='cancel_avatar_btn' id='cancel_avatar_btn'
...@@ -109,7 +111,6 @@ const CropperModal = (props: CropperModalProps) => { ...@@ -109,7 +111,6 @@ const CropperModal = (props: CropperModalProps) => {
确定 确定
</Button>, </Button>,
]} ]}
maskClosable={false}
onCancel={close}> onCancel={close}>
<Row> <Row>
<Col span={14}> <Col span={14}>
......
import React from 'react'
import { Modal, Button } from "antd";
import "./DownloadLiveModal.less"
class DownloadLiveModal extends React.Component {
constructor(props) {
super(props);
this.state = {
image: 'https://image.xiaomaiketang.com/xm/K2sJJHG3pa.png',
tip: '直播上课需要使用客户端,请先下载并安装。',
text: '安装直播客户端',
type: 'pre',
}
}
downloadLiveClient(){
if (type === 'pre') {
const isMac = /macintosh|mac os x/i.test(navigator.userAgent);
if(isMac){
Modal.info({
title: "抱歉,暂不支持Mac版",
content: "Mac版正在开发中,敬请期待",
icon: <span className="icon iconfont default-confirm-icon">&#xe6f4;</span>,
okText: '我知道了'
});
return;
}
url && window.open(url);
this.setState({
image: 'https://image.xiaomaiketang.com/xm/wPwRdaa7MM.png',
tip: '安装完成后,再次打开即可开始直播。',
text: '我知道了',
type: 'finish',
})
} else {
this.props.onCancel();
}
}
render() {
const { url } = this.props;
const { image, tip, text, type } = this.state;
return <Modal
visible={true}
maskClosable={false}
title="下载客户端"
className="download-live-modal"
footer={null}
onCancel={() => {
this.props.onCancel();
}}
>
<img className="download-image" src={image} alt="" />
<p className="download-tip">{tip}</p>
<Button
type="primary"
className="download-button"
onClick={() => {
}}
>{text}</Button>
</Modal>
}
}
export default DownloadLiveModal;
\ No newline at end of file
.download-live-modal {
.ant-modal-body {
padding: 20px 24px 48px !important;
.download-image {
display: block;
width: 80px;
margin: 0 auto 8px;
}
.download-tip {
color: #666;
text-align: center;
margin-bottom: 32px;
}
.download-button {
display: block;
margin: 0 auto;
}
}
}
\ No newline at end of file
import React from 'react';
import E from 'wangeditor';
import { randomString } from '@/domains/basic-domain/utils';
import './EditorBox.less';
class EditorBox extends React.Component {
constructor(props) {
super(props)
this.state = {
editorId: randomString(16),
textLength: 0,
}
}
componentDidMount() {
this.renderEditor()
}
renderEditor() {
const { editorId } = this.state;
const { detail, onChange } = this.props;
const editorInt = new E(`#editor${editorId}`);
editorInt.customConfig.menus = [
'bold', // 粗体
'fontName', // 字体
'italic', // 斜体
'underline', // 下划线
'strikeThrough', // 删除线
'foreColor', // 文字颜色
'backColor', // 背景颜色
'list', // 列表
'justify', // 对齐方式
'emoticon', // 表情
]
editorInt.customConfig.emotions = [
{
title: 'emoji',
type: 'emoji',
content: ['😀', '😃', '😄', '😁', '😆', '😅', '😂', '😊', '🙂', '🙃', '😉', '😓', '😅', '😪', '🤔', '😬', '🤐']
}
]
editorInt.customConfig.zIndex = 999;
editorInt.customConfig.pasteFilterStyle = false;
editorInt.customConfig.pasteIgnoreImg = true;
// 自定义处理粘贴的文本内容
editorInt.customConfig.pasteTextHandle = function (content) {
if (content === '' && !content) return ''
var str = content
str = str.replace(/<xml>[\s\S]*?<\/xml>/ig, '')
str = str.replace(/<style>[\s\S]*?<\/style>/ig, '')
str = str.replace(/<\/?[^>]*>/g, '')
str = str.replace(/[ | ]*\n/g, '\n')
str = str.replace(/&nbsp;/ig, ' ')
return str
}
editorInt.customConfig.onchange = (html) => {
const textLength = editorInt.txt.text().replace(/&nbsp;/ig, ' ').length;
this.setState({ textLength }, () => {
onChange(html, this.state.textLength);
})
}
editorInt.create();
editorInt.txt.html(detail.content);
editorInt.change && editorInt.change();
}
render() {
const { editorId, textLength } = this.state;
const { limitLength = 1000 } = this.props;
return <div className="wang-editor-container ">
<div className="editor-box" id={`editor${editorId}`}></div>
{textLength > limitLength && <div className="editor-tips">超了{textLength - limitLength}个字</div>}
</div>
}
}
export default EditorBox;
.wang-editor-container {
border: 1px solid #E8E8E8;
border-radius: 4px;
width: 552px;
position: relative;
.w-e-text p,
.w-e-text h1,
.w-e-text h2,
.w-e-text h3,
.w-e-text h4,
.w-e-text h5,
.w-e-text table,
.w-e-text pre {
margin: 0;
}
.w-e-toolbar {
background-color: #fff !important;
border: none !important;
border-bottom: 1px solid #E8E8E8 !important;
}
.w-e-text-container {
border: none !important;
height: 88px !important;
}
.editor-tips {
position: absolute;
top: 5px;
right: 8px;
color: #f5222d;
}
}
\ No newline at end of file
import React from 'react';
import { Modal, Button } from 'antd';
import Service from '@/common/js/service';
import { randomString } from '@/domains/basic-domain/utils';
let cutFlag = false;
class ImgCutModal extends React.Component {
state = {
photoclip: null,
imgAddress: null
}
componentDidUpdate(prevProps) {
const {
visible,
cutWidth = 550,
cutHeight = 283,
imageFile,
bizCode = 'HOMEWORK_FILE'
} = this.props;
if (visible && imageFile) {
setTimeout(() => {
const { photoclip } = this.state;
const okBtnDom = document.querySelector('#clipBtn');
const options = {
size: [cutWidth, cutHeight],
rotateFree: false,
ok: okBtnDom,
maxZoom: 1,
style: {
jpgFillColor: 'transparent'
},
done: (dataUrl) => {
const { name } = imageFile;
const fileName = randomString(16) + name.slice(name.lastIndexOf('.'));
const { instId } = window.currentUserInstInfo;
const params = {
instId,
bizCode: bizCode,
accessTypeEnum: 'PUBLIC',
resourceName: fileName
}
const cutImage = this.convertBase64UrlToBlob(dataUrl);
Service.Hades("public/apollo/commonOssAuthority", params).then((res) => {
const { resourceId, accessId, policy, callback, signature,key, host } = res.result;
const localUrl = URL.createObjectURL(cutImage);
// 构建上传的表单
const xhr = new XMLHttpRequest();
const formData = new FormData();
formData.append("OSSAccessKeyId", accessId);
formData.append("policy", policy);
formData.append("callback", callback);
formData.append("Signature", signature);
formData.append("key", key);
formData.append("file", cutImage);
formData.append("success_action_status", 200);
xhr.open("POST", host);
xhr.onload = () => {
this.props.onOk(localUrl, resourceId);
setTimeout(() => {
cutFlag = false;
}, 2000)
};
xhr.send(formData);
this.setState({ xhr })
})
}
};
if (!photoclip) {
const _photoclip = new window.PhotoClip('#imgCutModalNew', options);
_photoclip.load(imageFile);
this.setState({ photoclip: _photoclip });
} else {
photoclip.clear();
photoclip.load(imageFile);
}
}, 0);
}
}
// base64转换成blob
convertBase64UrlToBlob(urlData) {
const bytes = window.atob(urlData.split(",")[1]);
const ab = new ArrayBuffer(bytes.length);
const ia = new Uint8Array(ab);
for (let i = 0; i < bytes.length; i++) {
ia[i] = bytes.charCodeAt(i);
}
return new Blob([ab], { type: "image/png" });
}
handleImgCutDone = () => {
if (!cutFlag) {
cutFlag = true;
this.refs.hiddenBtn.click();
}
}
render() {
const {
title,
visible,
onClose,
reUpload,
cutContentWidth,
cutContentHeight,
width = 550,
needReUpload = false,
} = this.props;
return (
<Modal
title={title}
width={width}
visible={visible}
onCancel={onClose}
maskClosable={false}
footer={[
<Choose>
<When condition={!needReUpload}>
<Button
key="back"
onClick={onClose}
>取消</Button>
</When>
<Otherwise>
<Button
key="back"
onClick={reUpload}
>重新上传</Button>
</Otherwise>
</Choose>,
<Button
key="submit"
type="primary"
onClick={this.handleImgCutDone}
>确定</Button>
]}>
<div
id="imgCutModalNew"
style={{
width: `${cutContentWidth || 620}px`,
height: `${cutContentHeight || 420}px`
}}
></div>
<div
id="clipBtn"
style={{ display: 'none' }}
ref="hiddenBtn"
/>
</Modal>
)
}
}
export default ImgCutModal;
\ No newline at end of file
import React from 'react';
import PropTypes from 'prop-types';
import { Modal, Button } from 'antd';
import Service from '@/common/js/service';
import User from '@/common/js/user';
let cutFlag = false;
class ImgCutModalNew extends React.Component {
state = {
photoclip: null,
imgAddress: null
}
componentDidUpdate(prevProps) {
const { visible, cutWidth, cutHeight, imageFile, width, bizCode = 'HOMEWORK_FILE', compress, compressSize = 1024 } = this.props;
if (visible && imageFile) {
setTimeout(() => {
const { photoclip } = this.state;
const okBtnDom = document.querySelector('#clipBtn');
const options = {
size: [cutWidth, cutHeight],
rotateFree: false,
ok: okBtnDom,
maxZoom: 1,
style: {
jpgFillColor: 'transparent'
},
done: async (dataUrl) => {
const { name } = imageFile;
const fileName = window.random_string(16) + name.slice(name.lastIndexOf('.'));
const params = {
bizCode: bizCode,
accessTypeEnum: 'PUBLIC',
instId: LS.get('instId'),
resourceName: fileName
}
// 压缩
if (compress) {
const compressSizeByte = compressSize * 1024;
dataUrl = this.getBase64Size(dataUrl) > compressSizeByte ? await this.handleCompressImg(dataUrl, compressSizeByte, cutWidth) : dataUrl;
}
const cutImage = this.convertBase64UrlToBlob(dataUrl);
Service.Hades('public/hades/commonOssAuthority', param).then((res) => {
const { resourceId, accessId, policy, callback, signature,key, host } = res.result;
const localUrl = URL.createObjectURL(cutImage);
// 构建上传的表单
const xhr = new XMLHttpRequest();
const formData = new FormData();
formData.append("OSSAccessKeyId", accessId);
formData.append("policy", policy);
formData.append("callback", callback);
formData.append("Signature", signature);
formData.append("key", key);
formData.append("file", cutImage);
formData.append("success_action_status", 200);
xhr.open("POST", host);
xhr.onload = () => {
this.props.onOk(localUrl, resourceId);
setTimeout(() => {
cutFlag = false;
}, 2000)
};
xhr.send(formData);
this.setState({ xhr })
})
}
};
if (!photoclip) {
const _photoclip = new PhotoClip('#imgCutModalNew', options);
_photoclip.load(imageFile);
this.setState({ photoclip: _photoclip });
} else {
photoclip.load(imageFile);
}
}, 0);
}
}
// 压缩图片
handleCompressImg(dataUrl, compressSize, cutWidth) {
const that = this;
return new Promise((resolve, reject) => {
const newImage = new Image();
newImage.src = dataUrl;
newImage.setAttribute("crossOrigin", 'Anonymous'); //url为外域时需要
newImage.onload = function () {
let imgWidth = this.width;
let imgHeight = this.height;
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
canvas.width = cutWidth;
canvas.height = cutWidth * imgHeight / imgWidth;
let quality = 0.92;//压缩系数0-1之间
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(this, 0, 0, canvas.width, canvas.height);
let base64 = canvas.toDataURL("image/jpeg", quality);
while (that.getBase64Size(base64) > compressSize) {
quality -= 0.01;
base64 = canvas.toDataURL("image/jpeg", quality);
}
resolve(base64);
}
})
}
// 获取base64文件大小
getBase64Size(baseStr) {
const eqTagIndex = baseStr.indexOf("=");
baseStr = eqTagIndex != -1 ? baseStr.substring(0, eqTagIndex) : baseStr;
const strLen = baseStr.length;
const fileSize = strLen - (strLen / 8) * 2;
return fileSize;
}
// base64转换成blol
convertBase64UrlToBlob(urlData) {
const bytes = window.atob(urlData.split(",")[1]);
const ab = new ArrayBuffer(bytes.length);
const ia = new Uint8Array(ab);
for (let i = 0; i < bytes.length; i++) {
ia[i] = bytes.charCodeAt(i);
}
return new Blob([ab], { type: "image/png" });
}
handleImgCutDone = () => {
if (!cutFlag) {
cutFlag = true;
this.refs.hiddenBtn.click();
}
}
render() {
const {
visible, onClose, needReUpload, reUpload,
title, width, cutWidth, cutHeight,
cutContentWidth, cutContentHeight
} = this.props;
return (
<Modal
title={title}
width={width}
visible={visible}
onCancel={onClose}
maskClosable={false}
footer={[
!needReUpload ?
<Button
key="back"
onClick={onClose}
>取消</Button> :
<Button
key="back"
onClick={reUpload}
>重新上传</Button>,
<Button
key="submit"
type="primary"
onClick={this.handleImgCutDone}
>确定</Button>
]}>
<div
id="imgCutModalNew"
style={{
width: `${cutContentWidth || 620}px`,
height: `${cutContentHeight || 420}px`
}}
></div>
<div
id="clipBtn"
style={{ display: 'none' }}
ref="hiddenBtn"
/>
</Modal>
)
}
}
ImgCutModalNew.propTypes = {
visible: PropTypes.bool,
needReUpload: PropTypes.bool, // 是否需要重新上传
title: PropTypes.string,
width: PropTypes.number,
cutWidth: PropTypes.number,
cutHeight: PropTypes.number,
imageFile: PropTypes.object
};
ImgCutModalNew.defaultProps = {
width: 550,
cutWidth: 502,
cutHeight: 283,
needReUpload: false,
};
export default ImgCutModalNew;
\ No newline at end of file
/**
* 多选日历
* Created by Gentean
* Mail: 4083189@qq.com
* Date: 2016/12/30
* Time: 下午2:32
*/
import React from 'react'
import { message } from "antd";
import moment from 'moment';
require("./MultipleDatePicker.less");
class MultipleDatePicker extends React.Component {
constructor(props) {
super(props);
this.state = {
calendar: "",
calendarDate: props.type ? moment(props.startTime):moment(),
detailList: [],
waitNoticeNumber: 0,
totalCount: 0,
selectDateList: props.selectDateList || [],
endTime: props.endTime || null,
startTime: props.startTime || null,
homeworkProcessEnum: props.homeworkProcessEnum || ''
};
}
componentWillReceiveProps(nextProps) {
this.setState({endTime : nextProps.endTime, startTime: nextProps.startTime, selectDateList: nextProps.selectDateList, homeworkProcessEnum:nextProps.homeworkProcessEnum},() => {
this.handleQuery();
});
}
componentDidMount() {
this.handleQuery();
}
handleQuery() {
var self = this;
self.setState({
calendar: self.renderCalendar(),
});
}
renderCalendar() {
var start = moment(this.state.calendarDate).startOf("month"),
startDay = start.dates(),
// 每月的第一天是星期几 [0-6] 6:日
startWeekOf = start.weekday();
var end = moment(this.state.calendarDate).endOf("month"),
endDay = end.dates(),
endWeekOf = end.weekday();
var dateElms = [];
// 上月余留的天
var prevMonthDays = moment(start).subtract("month", 1).endOf("month"),
prevMonthDaysNumber = prevMonthDays.dates();
for (
var j = prevMonthDaysNumber - startWeekOf + 1, i = 0;
i < startWeekOf;
i++, j++
) {
var time = moment(prevMonthDays).subtract("days", startWeekOf - 1 - i);
dateElms.push(
<li className={"disabled"} key={"before" + i}>
<span>{j}</span>
</li>
);
}
// 本月
for (var i = startDay; i <= endDay; i++) {
var time = moment(start).add("days", i - 1);
var className = "";
if(!this.props.canSelectTodayBefore && time.valueOf() < moment().valueOf() && time.format("YYYY-MM-DD") != moment().format("YYYY-MM-DD")) {
className = 'before-disabled'
}
// 今日待跟进
if (time.format("YYYY-MM-DD") == moment().format("YYYY-MM-DD")) {
className += " today";
}
if (this.state.selectDateList.indexOf(time.valueOf()) > -1) {
className += " active";
const today = moment().startOf('day').valueOf();
if(this.props.type && this.props.type == 'CALENDAR_CLOCK' && (time.valueOf() < today) && this.state.homeworkProcessEnum == 'ONGOING') {
className += " past";
}
}
if(this.state.startTime && this.state.endTime && (time.valueOf() > this.state.endTime.valueOf() || time.valueOf() < this.state.startTime.valueOf())) {
className += " disabled"
}
dateElms.push(
<li
className={className}
key={"curr" + i}
onClick={this.handleShowDetail.bind(this, time, className)}
>
<span>{i}</span>
</li>
);
}
// 下月预来的天
for (var j = 1, i = endWeekOf; i < 6; i++, j++) {
var time = moment(end).add("days", i);
dateElms.push(
<li className={"disabled"} key={"after" + i}>
<span>{j}</span>
</li>
);
}
return dateElms;
}
handleShowDetail(time, className) {
if(!this.props.canSelectTodayBefore && className === 'before-disabled') {
return
}
let date = time.valueOf();
const today = moment().startOf('day').valueOf();
if(this.props.type && this.props.type == 'CALENDAR_CLOCK' && (date < today)) {
return;
}
if(this.state.homeworkProcessEnum == 'ONGOING' && date == today) {
return;
}
if(this.props.type && this.props.type == 'CALENDAR_CLOCK' && this.state.startTime && this.state.endTime && (date > this.state.endTime.valueOf() || date < this.state.startTime.valueOf())) {
return;
}
let tempArr = this.state.selectDateList;
if (tempArr.indexOf(date) > -1) {
let index = tempArr.indexOf(date);
tempArr.splice(index, 1);
} else {
if (tempArr.length > 29 && !this.props.type) {
message.warning("最多选择30天");
return;
} else {
tempArr.push(date);
}
}
this.props.onSelect(tempArr);
this.setState(
{
selectDateList: tempArr,
},
() => {
this.handleQuery();
}
);
}
render() {
const self = this;
const {calendarDate, endTime,startTime } = this.state;
const { type} = this.props;
const prevMonth = startTime && calendarDate.subtract("month", 1).endOf('month').valueOf() < startTime.valueOf();
const nextMonth = !(endTime && calendarDate.add("month", 1).valueOf() < endTime.valueOf());
return (
<div
className={`multiple-calendar ${
type == "CALENDAR_CLOCK" ? "punch-calender" : ""
}`}
>
{type == "CALENDAR_CLOCK" ? (
<div className="punch-control">
<div className="punch-main">
<div
onClick={function () {
if(prevMonth){return}
this.state.calendarDate = this.state.calendarDate.subtract(
"month",
1
);
self.handleQuery();
}.bind(this)}
className={`prev-icon ${prevMonth?'disbled-icon':''}`}
>
<span className="icon iconfont">&#xe65f;</span>
</div>
<span className="month">{this.state.calendarDate.format("YYYY年MM月")}</span>
<div
className={`next-icon ${nextMonth?'disbled-icon':''}`}
onClick={function () {
if(nextMonth){return}
this.state.calendarDate = this.state.calendarDate.add(
"month",
1
);
self.handleQuery();
}.bind(this)}
>
<span className="icon iconfont">&#xe65e;</span>
</div>
</div>
<div
className="self"
onClick={function () {
this.state.calendarDate = moment(startTime);
self.handleQuery();
}.bind(this)}
>
回到起始月
</div>
</div>
) : (
<div className="t-control">
<div
className="prev"
onClick={function () {
this.state.calendarDate = this.state.calendarDate.subtract(
"month",
1
);
self.handleQuery();
}.bind(this)}
>
上月
</div>
<div className="loc">
{this.state.calendarDate.format("YYYY年MM月")}
</div>
<div
className="self"
onClick={function () {
this.state.calendarDate = moment();
self.handleQuery();
}.bind(this)}
>
本月
</div>
<div
className="next"
onClick={function () {
this.state.calendarDate = this.state.calendarDate.add('month', 1);
self.handleQuery()
}.bind(this)}
>
下月
</div>
</div>
)}
<ul className="week">
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
<ul className="calendar" id="multiCalendar">
{this.state.calendar}
</ul>
</div>
);
}
}
MultipleDatePicker.propTypes = {};
MultipleDatePicker.defaultProps = {
reEditUrl: "",
close: function () {},
canSelectTodayBefore: true // 支持选择今天之前的日期
};
export default MultipleDatePicker;
@import '@/core/variables.less';
.multiple-calendar {
width: 295px;
border: 1px solid #e8e8e8;
border-radius: 4px;
ul {
list-style: none;
}
.t-control {
display: flex;
> div {
padding: 2px 0;
text-align: center;
cursor: pointer;
&:hover {
background: #ececec;
}
}
.loc {
flex: 1;
cursor: default;
&:hover {
background: #FFFFFF;
border-radius: 4px;
}
}
.self {
width: 50px;
}
.prev, .next {
width: 50px;
}
}
.week {
font-size: 12px;
li {
display: inline-block;
width: 41px;
text-align: center;
cursor: pointer;
}
}
.calendar {
padding-bottom: 10px;
li {
display: inline-block;
width: 31px;
margin: 0 5px;
text-align: center;
height: 30px;
line-height: 30px;
cursor: pointer;
vertical-align: top;
&:hover {
background: #e8e8e8;
}
&.before-disabled {
color: #e8e8e8;
cursor: default;
&:hover {
background: none!important;
span{
color: #e8e8e8!important;
}
}
}
&.disabled{
color: #e8e8e8;
cursor: default;
&:hover {
background: none!important;
span{
color: #e8e8e8!important;
}
}
}
&.active {
background: @xm-color-primary;
color: #fff;
border-radius: 4px;
}
&.today {
border: 1px solid @xm-color-primary;
border-radius: 5px;
}
}
}
&.punch-calender {
width: 400px;
margin-top: 12px;
.punch-control {
border-bottom: 1px solid rgba(0,0,0,0.06);
position: relative;
.punch-main {
margin: 0 133px;
display: flex;
justify-content: space-between;
align-items: center;
.prev-icon,
.next-icon {
cursor: pointer;
}
.month {
color: #333333;
}
.icon {
color: rgba(0,0,0,0.45);
}
.disbled-icon {
cursor: not-allowed;
.icon {
color: #e8e8e8;
}
}
}
.self {
position: absolute;
right: 8px;
top: 0;
color: #FF7519;
cursor: pointer;
}
}
.week {
li {
width: 56px;
}
}
.calendar li {
width: 56px;
margin: 0 !important;
span {
width: 30px;
height: 30px;
}
&:hover {
background: transparent;
span {
background: transparent;
color: #FF7519;
}
}
&.active {
background: transparent;
color: #fff;
border-radius: none;
span {
background: @xm-color-primary;
border-radius: 4px;
}
&:hover {
span {
color: #fff;
}
}
}
&.today {
border: none;
border-radius: none;
span {
border: 1px solid @xm-color-primary;
border-radius: 5px;
}
}
&.past {
span {
background:rgba(255,133,52,0.1);
border-radius: 4px;
color:rgba(0,0,0,0.25);
}
}
}
}
}
import React from 'react'
import './ShowTips.less'
import {InfoCircleOutlined} from '@ant-design/icons';
function ShowTips(props) {
return (
<div className={`xm-show-tip xm-type-${props.type || 'defulat'}`} >
{/* <InfoCircleOutlined className="icon"/> */}
<span className="icon iconfont">&#xe6f2;</span>
<p>{props.message}</p>
</div>
)
}
export default ShowTips
.xm-show-tip {
position: relative;
min-height:32px;
background:#FFF4DD;
border-radius:4px;
display: flex;
justify-content: flex-start;
align-items: center;
padding: 0 12px;
.icon {
color:#FF9D14;
font-size:14px;
}
p {
color:#666666;
font-size: 14px;
line-height:20px;
margin-left:8px;
}
}
.xm-type-default {
width: 100%;
}
.xm-type-info {
width: calc(~'100% - 190px');
}
\ No newline at end of file
...@@ -9,10 +9,12 @@ import SearchBar from './SearchBar.tsx'; ...@@ -9,10 +9,12 @@ import SearchBar from './SearchBar.tsx';
import PageControl from './PageControl.tsx'; import PageControl from './PageControl.tsx';
import CheckBox from './CheckBox.tsx'; import CheckBox from './CheckBox.tsx';
import CropperModal from './CropperModal.tsx'; import CropperModal from './CropperModal.tsx';
import ImgCutModalNew from './ImgCutModalNew';
export { export {
SearchBar, SearchBar,
PageControl, PageControl,
CheckBox, CheckBox,
CropperModal CropperModal,
ImgCutModalNew
} }
\ No newline at end of file
...@@ -207,7 +207,6 @@ ...@@ -207,7 +207,6 @@
.ant-table-header>table,.ant-table-body>table { .ant-table-header>table,.ant-table-body>table {
border: none !important; border: none !important;
border-radius: 3px; border-radius: 3px;
.icon { .icon {
color: #bfbfbf; color: #bfbfbf;
} }
...@@ -628,4 +627,18 @@ mr0 { ...@@ -628,4 +627,18 @@ mr0 {
background:#FF4F4F !important; background:#FF4F4F !important;
color:#FFF !important; color:#FFF !important;
border:none !important; border:none !important;
}
.row-dragging {
background: #fafafa;
border: 1px solid #ccc;
}
.row-dragging td {
padding: 16px;
visibility: hidden;
}
.row-dragging .drag-visible {
visibility: visible;
} }
\ No newline at end of file
...@@ -1659,3 +1659,17 @@ input:focus { ...@@ -1659,3 +1659,17 @@ input:focus {
.ant-table-bordered .ant-table-content { .ant-table-bordered .ant-table-content {
border: 1px solid #e8e8e8 !important; border: 1px solid #e8e8e8 !important;
} }
.row-dragging {
background: #fafafa;
border: 1px solid #ccc;
}
.row-dragging td {
padding: 16px;
visibility: hidden;
}
.row-dragging .drag-visible {
visibility: visible;
}
...@@ -5,8 +5,8 @@ import { message } from 'antd'; ...@@ -5,8 +5,8 @@ import { message } from 'antd';
/* /*
* @Author: 吴文洁 * @Author: 吴文洁
* @Date: 2020-08-11 11:47:14 * @Date: 2020-08-11 11:47:14
* @LastEditors: zhangleyuan * @LastEditors: wufan
* @LastEditTime: 2020-12-15 17:57:31 * @LastEditTime: 2021-01-03 21:04:30
* @Description: * @Description:
* @Copyright: 杭州杰竞科技有限公司 版权所有 * @Copyright: 杭州杰竞科技有限公司 版权所有
*/ */
...@@ -23,7 +23,7 @@ class Upload { ...@@ -23,7 +23,7 @@ class Upload {
const signInfo = res.result; const signInfo = res.result;
const { fileUrl } = res.result const { fileUrl } = res.result
return this.uploadBlobToNewOSS(Blob, name, dir, signInfo.signatureVO || signInfo).then(() => { return this.uploadBlobToNewOSS(Blob, name, dir, signInfo.signatureVO || signInfo).then(() => {
console.log('url2222222'); console.log('url2222222',fileUrl);
return dataType === 'url' ? fileUrl : signInfo return dataType === 'url' ? fileUrl : signInfo
}); });
}) })
......
/*
* @Author: zhujian
* @Date: 2017-08-31 11:05:12
* @Last Modified by: 吴文洁
* @Last Modified time: 2020-07-16 11:33:21
*公共方法
*/
window.utils = {
isValidURL(url) {
if (!url) {
return false;
}
if (url.indexOf('http') !== -1) {
return true;
}
return false;
},
// 只截取两位数,多余的去掉,不足的补0
_fillTwo(str) {
const temArr = str.split("");
const newArr = [];
for (let i = 0; i < 2; i++) {
if (temArr[i]) {
newArr.push(temArr[i]);
} else {
newArr.push(0);
}
}
return newArr.join("");
},
limitFloatTwo(val, digit = 99) {
if (val === "") {
return "";
} else {
const regExp = new RegExp("(\\d+)\\.(\\d+)?$");
const result = regExp.exec(val);
let inter = ""; // 整数部分
let decimal = ""; // 小数部分
if (result) {
inter = result[1];
decimal = this._fillTwo(result[2] || '');
return `${inter.substr(0, digit)}.${decimal}`;
}
return val
}
},
filterNumber(value) {
let _value;
if (value != '' && value.substr(0, 1) === '.') {
return "";
}
_value = value.replace(/^0*(0\.|[1-9])/, '$1'); //解决 粘贴不生效
_value = _value.replace(/[^\d.]/g, ""); //清除“数字”和“.”以外的字符
_value = _value.replace(/\.{2,}/g, "."); //只保留第一个. 清除多余的
return _value;
},
// 限制7位整数和两位小数
limitNum(value) {
let _value = this.filterNumber(value);
_value = _value.replace(/(\d+)(\.\d*)?/, function ($1, $2, $3) {
if ($3) {
return $2.substr(0, 7) + $3.substr(0, 3);
}
return $2.substr(0, 7);
});
return _value;
},
/**
* 限制位数可配置, 比如限制n位整数和m位小数
* @param {*} 需要限制的数值
* @param {*} 需要限制的整数位数
* @param {*} 需要限制的小数位数
*/
setLimitNum(value, digit, decimal) {
let _value = this.filterNumber(value);
_value = _value.replace(/(\d+)(\.\d*)?/, function ($1, $2, $3) {
if ($3) {
return `${$2.substr(0, digit)}${$3.substr(0, decimal + 1)}`;
}
return $2.substr(0, digit);
});
return _value;
},
getNumRange(value, min, max) {
let _value = this.setLimitNum(value, 8, 2);
if (_value < min) {
return min;
} else if (_value > max) {
return max;
}
return getNumberFormat(_value);
},
// 数组去重
unique(arr, u_key) {
let map = new Map();
arr.forEach((item) => {
if (!map.has(item[u_key])) {
map.set(item[u_key], item)
}
});
return [...map.values()];
},
formatString(str, n) {
const string = str || '';
const numberList = string.replace(/./g, (item) => {
if (item.match(/[^\x00 -\xff]/)) {
return '2';
} else {
return '1';
}
});
let number = 0;
for (let i = 0; i < string.length; i++) {
number += parseInt(numberList[i], 10);
if (number >= n * 2) {
return string.substring(0, i + 1).trim() + '…'
}
}
return str;
},
removeSpecialCharacter(str) {
return (str || '').replace(/[^\u4e00-\u9fa5a-zA-Z0-9_\-—~\(\)\[\]\{\}+()【】「」《》,。,\.\*%#@\&::""''“”‘’\/ ]/g, '');
}
};
const isUndefined = (value) => {
return value === void 0 || value === null;
}
const randomString = (len = 32) => {
const chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678';
const maxPos = chars.length;
let pwd = '';
for (let i = 0; i < len; i++) {
pwd += chars.charAt(Math.floor(Math.random() * maxPos));
}
return pwd;
}
// 限制字数
const getEllipsText = (text, limitNum) => {
const limitText = text.replace(/\n/g, ' ');
if (limitText.length > limitNum) {
return `${limitText.substr(0, limitNum)}...`;
}
return limitText;
}
const shareTemplate = (str, place) => {
return str.replace(/\{\$(.*?)\}/g, (full, key) => {
return place[key] || full
})
}
const transformPhoneNumer = (phoneNum, hasPermission) => {
if (!phoneNum) return phoneNum;
if (hasPermission) return phoneNum;
const newPhoneArr = String(phoneNum).split('');
newPhoneArr.splice(3, 4, '****');
return newPhoneArr.join('');
}
export {
randomString,
isUndefined,
getEllipsText,
shareTemplate,
transformPhoneNumer
}
\ No newline at end of file
...@@ -56,7 +56,7 @@ ...@@ -56,7 +56,7 @@
//old //old
//color //color
@xm-color-primary: #FF7519; @xm-color-primary:#FFB714;
@xm-color-primary_active: #020201; @xm-color-primary_active: #020201;
@xm-color-primary-darker: #ff8534; @xm-color-primary-darker: #ff8534;
@xm-color-selected: #F58E2C; @xm-color-selected: #F58E2C;
......
...@@ -2,19 +2,24 @@ ...@@ -2,19 +2,24 @@
* @Author: wufan * @Author: wufan
* @Date: 2020-12-01 17:21:21 * @Date: 2020-12-01 17:21:21
* @LastEditors: zhangleyuan * @LastEditors: zhangleyuan
* @LastEditTime: 2020-12-11 11:53:13 * @LastEditTime: 2020-12-22 15:39:00
* @Description: Description * @Description: Description
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/ */
import Service from "@/common/js/service"; import Service from "@/common/js/service";
export function sendLoginAuthCode(params: object) {
return Service.Hades("anon/hades/sendLoginAuthCode", params);
}
export function login(params: object) {
return Service.Hades("anon/hades/login", params);
}
export function getUserStore(params: object) { export function getUserStore(params: object) {
return Service.Hades("public/hades/getUserStore", params); return Service.Hades("public/hades/getUserStore", params);
} }
export function getUserPermission(params: object) { export function getUserPermission(params: object) {
return Service.Hades("public/hades/getPermission", params); return Service.Hades("public/hades/getPermission", params);
} }
export function logout(params: object) { export function logout(params: object) {
return Service.Hades("public/hades/logout", params); return Service.Hades("public/hades/logout", params);
} }
...@@ -33,9 +38,19 @@ export function sendNewPhoneAuthCode(params: object) { ...@@ -33,9 +38,19 @@ export function sendNewPhoneAuthCode(params: object) {
export function editUserPhone(params: object) { export function editUserPhone(params: object) {
return Service.Hades("public/hades/editUserPhone", params); return Service.Hades("public/hades/editUserPhone", params);
} }
export function sendLoginAuthCode(params: object) { export const getOssClient = (
return Service.Hades("anon/hades/sendLoginAuthCode", params); data: object,
} instId: string,
export function login(params: object) { bizCode: string,
return Service.Hades("anon/hades/login", params); resourceName: string,
accessTypeEnum: string
) => {
return Service.postJSON('mfs/anon/mfs/multiPartUpload', {
data,
instId,
bizCode,
resourceName,
accessTypeEnum
});
} }
/*
* @Author: 吴文洁
* @Date: 2020-10-10 18:21:47
* @LastEditors: wufan
* @LastEditTime: 2020-12-09 16:05:24
* @Description:
* @Copyright: 杭州杰竞科技有限公司 版权所有
*/
import Service from '@/common/js/service';
export const getOssClient = (
data: object,
instId: string,
bizCode: string,
resourceName: string,
accessTypeEnum: string
) => {
return Service.postJSON('mfs/anon/mfs/multiPartUpload', {
data,
instId,
bizCode,
resourceName,
accessTypeEnum
});
}
\ No newline at end of file
/*
* @Author: wufan
* @Date: 2020-12-12 11:57:10
* @LastEditors: zhangleyuan
* @LastEditTime: 2020-12-16 16:14:42
* @Description: Description
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import Service from "@/common/js/service";
export function fetchLecturerData(params: object) {
return Service.Hades("public/courseCloud/queryTeacherVisitData", params);
}
export function fetchUserData(params: object) {
return Service.Hades("public/courseCloud/queryStudentVisitData", params);
}
export function createLiveCloudCourse(params: object) {
return Service.Hades("public/courseCloud/createLiveCloudCourse", params);
}
export function getLiveCloudCoursePage(params: object) {
return Service.Hades("public/courseCloud/getLiveCloudCoursePage", params);
}
export function exportStudentCourseData(params: object) {
return Service.Hades("public/courseCloud/exportCourseCloudVisitorAsync", params);
}
export function exportPlayBackCourseData(params: object) {
return Service.Hades("public/courseCloud/exportCourseCloudPlayBackSync", params);
}
export function fetchPlaybackList(params: object) {
return Service.Hades("public/courseCloud/getUserReplayRecordPage", params);
}
export function getLiveCloudCourseDetail(params: object) {
return Service.Hades("public/courseCloud/getLiveCloudCourseDetail", params);
}
export function updateLiveCloudCourse(params: object) {
return Service.Hades("public/courseCloud/updateLiveCloudCourse", params);
}
export function turnOnOrOffLiveCloudCourse(params: object) {
return Service.Hades("public/courseCloud/turnOnOrOffLiveCloudCourse", params);
}
export function delLiveCloudCourse(params: object) {
return Service.Hades("public/courseCloud/delLiveCloudCourse", params);
}
\ No newline at end of file
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: wufan * @Author: wufan
* @Date: 2020-11-25 18:25:02 * @Date: 2020-11-25 18:25:02
* @LastEditors: zhangleyuan * @LastEditors: zhangleyuan
* @LastEditTime: 2020-12-08 15:12:57 * @LastEditTime: 2020-12-23 16:52:56
* @Description: Description * @Description: Description
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/ */
...@@ -23,6 +23,18 @@ export function getUserList(params: object) { ...@@ -23,6 +23,18 @@ export function getUserList(params: object) {
export function getStoreDecorationList(params: object) { export function getStoreDecorationList(params: object) {
return Service.Hades("public/hades/getStoreBannerList", params); return Service.Hades("public/hades/getStoreBannerList", params);
} }
export function deleteStoreDecorationList(params: object) {
return Service.Hades("public/hades/delStoreBanner", params);
}
export function addStoreBanner(params: object) {
return Service.Hades("public/hades/addStoreBanner", params);
}
export function editStoreBanner(params: object) {
return Service.Hades("public/hades/editStoreBanner", params);
}
export function moveBannerSequence(params: object) {
return Service.Hades("public/hades/moveBannerSequence", params);
}
export function addEmployee(params: object) { export function addEmployee(params: object) {
return Service.Hades("public/hades/addStoreUser", params); return Service.Hades("public/hades/addStoreUser", params);
...@@ -53,3 +65,6 @@ export function editCourseCategory(params: object) { ...@@ -53,3 +65,6 @@ export function editCourseCategory(params: object) {
export function delCourseCategory(params: object) { export function delCourseCategory(params: object) {
return Service.Hades("public/hades/delCourseCategory", params); return Service.Hades("public/hades/delCourseCategory", params);
} }
export function getStoreUserBasicPage(params: object) {
return Service.Hades("public/hades/getStoreUserBasicPage", params);
}
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: wufan * @Author: wufan
* @Date: 2020-12-01 17:20:49 * @Date: 2020-12-01 17:20:49
* @LastEditors: zhangleyuan * @LastEditors: zhangleyuan
* @LastEditTime: 2020-12-11 11:50:17 * @LastEditTime: 2020-12-11 11:36:19
* @Description: Description * @Description: Description
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/ */
......
/* /*
* @Author: 陈剑宇 * @Author: 陈剑宇
* @Date: 2020-05-07 14:43:01 * @Date: 2020-05-07 14:43:01
* @LastEditTime: 2020-12-15 21:30:37 * @LastEditTime: 2021-01-04 20:14:06
* @LastEditors: wufan * @LastEditors: zhangleyuan
* @Description: * @Description:
* @FilePath: /wheat-web-demo/src/domains/basic-domain/constants.ts * @FilePath: /wheat-web-demo/src/domains/basic-domain/constants.ts
*/ */
......
/* /*
* @Author: 吴文洁 * @Author: 吴文洁
* @Date: 2020-08-20 09:20:43 * @Date: 2020-08-20 09:20:43
* @LastEditors: 吴文洁 * @LastEditors: wufan
* @LastEditTime: 2020-08-21 09:02:36 * @LastEditTime: 2020-12-09 14:51:33
* @Description: * @Description:
* @Copyright: 杭州杰竞科技有限公司 版权所有 * @Copyright: 杭州杰竞科技有限公司 版权所有
*/ */
...@@ -16,6 +16,59 @@ const getEllipsText = (text: string, limitNum: number) => { ...@@ -16,6 +16,59 @@ const getEllipsText = (text: string, limitNum: number) => {
return limitText; return limitText;
} }
// 随机生成32位字符串
const randomString = (strLen: number = 32) => {
const chars: string = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678'
const maxPos = chars.length;
let pwd: string = '';
for (let i: number = 0; i < strLen; i++) {
pwd += chars.charAt(Math.floor(Math.random() * maxPos))
}
return pwd;
}
const copyText = (textContent: string) => {
const inputDom = document.createElement('textarea')
inputDom.value = textContent
document.body.appendChild(inputDom)
inputDom.select()
document.execCommand('copy')
document.body.removeChild(inputDom)
}
const formatDate = (format: string, timestamp: string) => {
if (!timestamp) return;
const date = new Date(parseInt(timestamp))
let y: any = date.getFullYear(),
m: any = date.getMonth() + 1,
d: any = date.getDate(),
h: any = date.getHours(),
i: any = date.getMinutes(),
s: any = date.getSeconds(),
w: number = date.getDay(),
week: string[] = ['周日', '周一', '周二', '周三', '周四', '周五', '周六']
m = m < 10 ? '0' + m : m;
d = d < 10 ? '0' + d : d;
h = h < 10 ? '0' + h : h;
i = i < 10 ? '0' + i : i;
s = s < 10 ? '0' + s : s;
return format
.replace('YYYY', y)
.replace('MM', m)
.replace('DD', d)
.replace('H', h)
.replace('i', i)
.replace('s', s)
.replace('WW', week[w])
}
export { export {
getEllipsText getEllipsText,
randomString,
copyText,
formatDate
} }
\ No newline at end of file
/*
* @Author: wufan
* @Date: 2020-11-25 18:25:02
* @LastEditors: zhangleyuan
* @LastEditTime: 2020-12-16 16:15:15
* @Description: Description
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import { fetchLecturerData, fetchUserData, exportStudentCourseData,exportPlayBackCourseData, fetchPlaybackList,createLiveCloudCourse,getLiveCloudCoursePage,getLiveCloudCourseDetail,updateLiveCloudCourse,turnOnOrOffLiveCloudCourse,delLiveCloudCourse} from '@/data-source/course/request-api';
export default class courseService {
// 获取讲师上课数据
static fetchLecturerData(params: any) {
return fetchLecturerData(params);
}
// 获取用户上课数据
static fetchUserData(params: any) {
return fetchUserData(params);
}
static createLiveCloudCourse(params: any) {
return createLiveCloudCourse(params);
}
static getLiveCloudCoursePage(params: any) {
return getLiveCloudCoursePage(params);
}
// 导出学生上课数据
static exportStudentCourseData(params: any) {
return exportStudentCourseData(params);
}
// 导出回放数据
static exportPlayBackCourseData(params: any) {
return exportPlayBackCourseData(params);
}
// 获取回放数据
static fetchPlaybackList(params: any) {
return fetchPlaybackList(params);
}
static getLiveCloudCourseDetail(params: any) {
return getLiveCloudCourseDetail(params);
}
static updateLiveCloudCourse(params: any) {
return updateLiveCloudCourse(params);
}
static turnOnOrOffLiveCloudCourse(params: any) {
return turnOnOrOffLiveCloudCourse(params);
}
static delLiveCloudCourse(params: any) {
return delLiveCloudCourse(params);
}
}
\ No newline at end of file
/*
* @Author: 吴文洁
* @Date: 2020-08-20 09:21:40
* @LastEditors: wufan
* @LastEditTime: 2020-12-12 11:18:53
* @Description:
* @Copyright: 杭州杰竞科技有限公司 版权所有
*/
import { MapInterface } from '@/domains/basic-domain/interface'
const ENV: string = process.env.DEPLOY_ENV || 'dev';
const appIdMap: MapInterface = {
dev: 'wx3ea60e78ddfa277e',
dev1: 'wx3ea60e78ddfa277e',
rc: 'wx5c5a1fb71ecab7bc',
gray: "wxdd6b458500d4c224", // 小麦校讯通
prod: 'wxdd6b458500d4c224'
}
const shareUrlMap: MapInterface = {
'dev': 'https://dev.xiaomai5.com/share/show?appid=',
'dev1': 'https://dev.xiaomai5.com/share/show?appid=',
'rc': 'https://rc.xiaomai5.com/share/show?appid=',
'prod': 'https://prod.xiaomai5.com/share/show?appid=',
'gray': 'https://prod.xiaomai5.com/share/show?appid='
}
const LIVE_SHARE_MAP: MapInterface = {
dev: 'https://dev.xiaomai5.com/xiaomai-live-share/index.html#/',
dev1: 'https://dev.xiaomai5.com/xiaomai-live-share/index.html#/',
rc: 'https://rc.xiaomai5.com/xiaomai-live-share/index.html#/',
gray: 'https://res.xiaomai5.com/xiaomai-live-share/gray/index.html#/',
prod: 'https://res.xiaomai5.com/xiaomai-live-share/index.html#/',
}
export const appId: string = appIdMap[ENV];
export const shareUrl: string = shareUrlMap[ENV];
export const LIVE_SHARE: string = LIVE_SHARE_MAP[ENV];
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
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