Commit 84e7111d by chenshu

fix:修复管理端部分问题

parent fd9b2ba8
import React from 'react';
import { Tooltip, Input, Radio, Table } from 'antd';
import { Tooltip, Input, Radio, Table, Checkbox } from 'antd';
import moment from 'moment';
import _ from 'underscore';
import Breadcrumbs from "@/components/Breadcrumbs";
......@@ -21,8 +21,6 @@ export default class OfflineCourseData extends React.Component {
current: 1,
courseId,
storeId: User.getStoreId(),
joinInState: 'YES',
joinOutState: 'YES',
},
loading: false,
data: [],
......@@ -58,6 +56,8 @@ export default class OfflineCourseData extends React.Component {
calendarTime,
currentDate,
offlineCourseType: result.offlineCourseType,
whetherSetSignIn: result.whetherSetSignIn,
whetherSetSignOut: result.whetherSetSignOut,
whetherSetSignInOut: result.whetherSetSignInOut,
whetherSetApply: result.whetherSetApply,
}, () => this.getDateDetail());
......@@ -89,6 +89,7 @@ export default class OfflineCourseData extends React.Component {
}
getColumns = () => {
const { whetherSetSignIn, whetherSetSignOut } = this.state;
const columns = [
{
title: '用户姓名',
......@@ -118,30 +119,45 @@ export default class OfflineCourseData extends React.Component {
return <div>{formatDate('YYYY-MM-DD H:i', item.joinTime)}</div>
}
},
{
title: '签到时间',
key: 'joinInTime',
dataIndex: 'joinInTime',
sorter: true,
render: (val) => {
return formatDate('YYYY-MM-DD H:i', val)
}
},
{
title: '签退时间',
key: 'joinOutTime',
dataIndex: 'joinOutTime',
sorter: true,
render: (val) => {
return formatDate('YYYY-MM-DD H:i', val)
}
},
];
whetherSetSignIn === 'YES' && columns.push({
title: '签到时间',
key: 'joinInTime',
dataIndex: 'joinInTime',
sorter: true,
render: (val) => {
return val ? formatDate('YYYY-MM-DD H:i', val) : '-';
}
})
whetherSetSignOut === 'YES' && columns.push({
title: '签退时间',
key: 'joinOutTime',
dataIndex: 'joinOutTime',
sorter: true,
render: (val) => {
return val ? formatDate('YYYY-MM-DD H:i', val) : '-';
}
})
return columns;
}
handleChangeTable = () => {
const { columnKey, order } = sorter;
const { query } = this.props;
let orderEnum;
// 按创建时间升序排序
if (columnKey === 'joinInTime' && order === 'ascend') { orderEnum = 'JOIN_IN_DESC'; }
if (columnKey === 'joinOutTime' && order === 'ascend') { orderEnum = 'JOIN_IN_ASC'; }
// 按创建时间降序排序
if (columnKey === 'joinInTime' && order === 'descend') { orderEnum = 'JOIN_OUT_DESC';;}
if (columnKey === 'joinOutTime' && order === 'descend') { orderEnum = 'JOIN_OUT_ASC';;}
const _query = {
...query,
orderEnum,
};
this.setState({ query: _query }, () => {
this.getDateDetail(query.current);
})
}
render() {
......@@ -162,6 +178,8 @@ export default class OfflineCourseData extends React.Component {
joinOutNum,
offlineCourseType,
whetherSetApply,
whetherSetSignIn,
whetherSetSignOut,
whetherSetSignInOut,
} = this.state;
const calendarLength = calendarTime.length;
......@@ -232,12 +250,12 @@ export default class OfflineCourseData extends React.Component {
<div className="detail-data">
{offlineCourseType !== 'ALL_DAY_OFFLINE' && <span className="icon iconfont">&#xe89f;</span>}
{offlineCourseType !== 'ALL_DAY_OFFLINE' && whetherSetApply === 'YES' && <span className="data-text">报名人数:{joinNum}</span>}
<span className="icon iconfont">&#xe89e;</span>
<span className="data-text">完成考勤数<Tooltip title="当日在规定时间内完成签到和签退的用户数"><span className="icon iconfont">&#xe7c4;</span></Tooltip>{fullJoinNum}</span>
<span className="icon iconfont">&#xe8a0;</span>
<span className="data-text">签到人数:{joinInNum}</span>
<span className="icon iconfont">&#xe89d;</span>
<span className="data-text">签退人数:{joinOutNum}</span>
{whetherSetSignInOut === 'YES' && <span className="icon iconfont">&#xe89e;</span>}
{whetherSetSignInOut === 'YES' && <span className="data-text">完成考勤数<Tooltip title="当日在规定时间内完成签到和签退的用户数"><span className="icon iconfont">&#xe7c4;</span></Tooltip>{fullJoinNum}</span>}
{whetherSetSignIn === 'YES' && <span className="icon iconfont">&#xe8a0;</span>}
{whetherSetSignIn === 'YES' && <span className="data-text">签到人数:{joinInNum}</span>}
{whetherSetSignOut === 'YES' && <span className="icon iconfont">&#xe89d;</span>}
{whetherSetSignOut === 'YES' && <span className="data-text">签退人数:{joinOutNum}</span>}
</div>
<div className="detail-filter">
<Search
......@@ -262,27 +280,53 @@ export default class OfflineCourseData extends React.Component {
/>
<div className="filter-box">
<span className="label">签到情况:</span>
<Radio.Group
value={query.joinInState}
<Checkbox
checked={query.joinInState === 'YES'}
onChange={(e) => {
this.setState({ query: { ...query, joinInState: e.target.value } }, () => this.getDateDetail());
if (e.target.checked) {
this.setState({ query: { ...query, joinInState: 'YES' } }, () => this.getDateDetail());
} else {
delete query.joinInState;
this.setState({ query }, () => this.getDateDetail())
}
}}
>
<Radio value="YES">已签到</Radio>
<Radio value="NO">未签到</Radio>
</Radio.Group>
>已签到</Checkbox>
<Checkbox
checked={query.joinInState === 'NO'}
onChange={(e) => {
if (e.target.checked) {
this.setState({ query: { ...query, joinInState: 'NO' } }, () => this.getDateDetail());
} else {
delete query.joinInState;
this.setState({ query }, () => this.getDateDetail())
}
}}
>未签到</Checkbox>
</div>
<div className="filter-box">
<span className="label">签退情况:</span>
<Radio.Group
value={query.joinOutState}
<Checkbox
checked={query.joinOutState === 'YES'}
onChange={(e) => {
if (e.target.checked) {
this.setState({ query: { ...query, joinOutState: 'YES' } }, () => this.getDateDetail());
} else {
delete query.joinOutState;
this.setState({ query }, () => this.getDateDetail())
}
}}
>已签退</Checkbox>
<Checkbox
checked={query.joinOutState === 'NO'}
onChange={(e) => {
this.setState({ query: { ...query, joinOutState: e.target.value } }, () => this.getDateDetail());
if (e.target.checked) {
this.setState({ query: { ...query, joinOutState: 'NO' } }, () => this.getDateDetail());
} else {
delete query.joinOutState;
this.setState({ query }, () => this.getDateDetail())
}
}}
>
<Radio value="YES">已签退</Radio>
<Radio value="NO">未签退</Radio>
</Radio.Group>
>未签退</Checkbox>
</div>
</div>
<Table
......@@ -300,7 +344,7 @@ export default class OfflineCourseData extends React.Component {
pageSize={query.size}
total={total}
toPage={(page) => {
this.getDateDetail(page);
this.getDateDetail(page + 1);
}}
/>
</div>
......
......@@ -72,7 +72,7 @@ class OfflineCourseList extends React.Component {
return (
<div className="record__item">
<img className="course-cover" src={coverUrl || defaultCoverUrl} />
<div style={{ width: 200 }}>
<div style={{ width: 175 }}>
<Tooltip title={courseName}>
<div className="course-name">{courseName}</div>
</Tooltip>
......@@ -149,7 +149,21 @@ class OfflineCourseList extends React.Component {
dataIndex: 'apply',
sorter: true,
render: (val, item) => {
return item.startTimeApply ? `${formatDate('MM-DD H:i', item.startTimeApply)} ~ ${formatDate('MM-DD H:i', item.endTimeApply)}` : '-'
return <div>
{item.startTimeApply ? `${formatDate('MM-DD H:i', item.startTimeApply)} ~ ${formatDate('MM-DD H:i', item.endTimeApply)}` : '-'}
{item.whetherApplyFull === 'YES' &&
<span
style={{
marginLeft: 4,
color: '#FF4F4F',
background: 'rgba(255, 79, 79, 0.1)',
padding: '0 8px',
fontSize: '12px',
height: '18px',
lineHeight: '18px',
}}>已报满</span>
}
</div>
}
},
{
......@@ -233,7 +247,7 @@ class OfflineCourseList extends React.Component {
this.handleDeleteOfflineCourse(item.courseId);
}}
>取消课程</div>}
{item.courseState === 'UN_START' && <div
{item.courseState === 'UN_START' && window.ctx.xmState.storeUserPermissionList.includes('EditOfflineClass') && <div
className="operate__item"
key="edit"
onClick={() => {
......@@ -249,7 +263,11 @@ class OfflineCourseList extends React.Component {
)
}
//改变上架状态
changeShelfState = (item) =>{
changeShelfState = (item) => {
if (!window.ctx.xmState.storeUserPermissionList.includes('EditOfflineClass')) {
message.warning('无【编辑线下课】权限,请联系管理员')
return;
}
let _shelfState = item.shelfState
if(_shelfState==='NO'){
_shelfState = "YES";
......@@ -321,7 +339,8 @@ class OfflineCourseList extends React.Component {
const _appId = appId;
const htmlUrl = `${LIVE_SHARE}offline_detail/${courseId}?id=${User.getStoreId()}`;
const longUrl = htmlUrl;
const { coverUrl, courseName } = record;
const { courseName, courseMediaVOS } = record;
const coverUrl = (_.find(courseMediaVOS, data => data.contentType === 'COVER') || {}).mediaUrl;
const shareData = {
longUrl,
coverUrl,
......
......@@ -65,7 +65,6 @@
.course-name {
color: #333;
max-width: ~'calc(100% - 32px)';
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
......@@ -76,7 +75,6 @@
.course-text {
color: #666;
max-width: ~'calc(100% - 32px)';
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
......
......@@ -4,6 +4,7 @@ import moment from 'moment';
import $ from 'jquery';
import Service from "@/common/js/service";
import './PreviewOfflineModal.less';
import ENUM from '@/modules/knowledge-base/ENUM';
const defaultCoverUrl = 'https://image.xiaomaiketang.com/xm/YNfi45JwFA.png';
......@@ -64,6 +65,8 @@ class PreviewOfflineModal extends React.Component {
const {
coverUrl,
courseName,
teacherName,
courseState,
categoryName,
introduce,
startTime,
......@@ -110,6 +113,8 @@ class PreviewOfflineModal extends React.Component {
<div className="container">
<div className="container__header">
<img src={coverUrl || defaultCoverUrl} className="course-cover" />
<span className="cover-teacher">主讲人:{teacherName}</span>
<span className="cover-state" style={{ background: (ENUM.offlineStateShow[courseState] || {}).color }}>{(ENUM.offlineStateShow[courseState] || {}).title}</span>
</div>
<div className="container__body">
<div className="title__name">{courseName}</div>
......
......@@ -15,11 +15,31 @@
.container {
overflow: scroll;
height: 100%;;
.course-cover, .course-url {
width: 100%;
height: 141px;
background: #000;
&__header {
position: relative;
.course-cover, .course-url {
width: 100%;
height: 141px;
background: #000;
}
.cover-teacher {
position: absolute;
bottom: 8px;
left: 16px;
font-size: 12px;
color: #fff;
}
.cover-state {
position: absolute;
bottom: 8px;
right: 16px;
font-size: 12px;
height: 18px;
line-height: 18px;
padding: 0 8px;
color: #fff;
border-radius: 9px;
}
}
&__body {
......
......@@ -6,6 +6,7 @@ import { LIVE_SHARE } from "@/domains/course-domain/constants";
import QRCode from '../../../../libs/qrcode/qrcode';
import User from '@/common/js/user';
import Service from "@/common/js/service";
import ScanFileModal from '../../../resource-disk/modal/ScanFileModal';
import './QRCodeModal.less';
const { Option } = Select;
......@@ -16,60 +17,54 @@ export default class QRCodeModal extends React.Component {
this.state = {
selectedDate: '',
data: {},
imgUrl1: '',
imgUrl2: '',
showPreviewModal: false,
}
}
componentWillReceiveProps(nextProps) {
componentDidUpdate(preProps) {
const { visible } = this.props;
if (nextProps.visible && !visible) {
this.getCourseDetail(nextProps);
if (!preProps.visible && visible) {
this.getCourseDetail();
}
}
getQrcode = () => {
const { selectedDate, data } = this.state;
if (data.whetherSetSignIn === 'YES') {
const qrcodeWrapDom = document.querySelector('#qrcodeWrap1');
let list = [];
const qrcodeWrapDom1 = document.querySelector('#qrcodeWrap1');
const qrcodeWrapDom2 = document.querySelector('#qrcodeWrap2');
if (data.whetherSetSignIn === 'YES') {
const htmlUrl = `${LIVE_SHARE}sign_in?id=${User.getStoreId()}&calendar=${selectedDate}&courseId=${data.courseId}&from=work_weixin`;
Service.Sales('public/businessShow/convertShortUrls', {
urls: [htmlUrl]
}).then((res) => {
const { result = [] } = res;
this.setState({
shareUrl: result[0].shortUrl
}, () => {
const qrcodeNode = new QRCode({
text: this.state.shareUrl,
size: 170,
})
qrcodeWrapDom.childNodes[0] && qrcodeWrapDom.removeChild(qrcodeWrapDom.childNodes[0]);
qrcodeWrapDom.appendChild(qrcodeNode);
})
})
list.push(htmlUrl);
}
if (data.whetherSetSignIn === 'YES') {
const qrcodeWrapDom = document.querySelector('#qrcodeWrap2');
const htmlUrl = `${LIVE_SHARE}sign_out?id=${User.getStoreId()}&calendar=${selectedDate}&courseId=${data.courseId}&from=work_weixin`;
Service.Sales('public/businessShow/convertShortUrls', {
urls: [htmlUrl]
}).then((res) => {
const { result = [] } = res;
this.setState({
shareUrl: result[0].shortUrl
}, () => {
const qrcodeNode = new QRCode({
text: this.state.shareUrl,
size: 170,
})
qrcodeWrapDom.childNodes[0] && qrcodeWrapDom.removeChild(qrcodeWrapDom.childNodes[0]);
qrcodeWrapDom.appendChild(qrcodeNode);
})
})
list.push(htmlUrl);
}
Service.Sales('public/businessShow/convertShortUrls', {
urls: list
}).then((res) => {
const { result = [] } = res;
const qrcodeNode1 = new QRCode({
text: result[0].shortUrl,
size: 170,
});
const qrcodeNode2 = result[1] && new QRCode({
text: result[1].shortUrl,
size: 170,
});
qrcodeWrapDom1 && qrcodeWrapDom1.childNodes[0] && qrcodeWrapDom1.removeChild(qrcodeWrapDom1.childNodes[0]);
qrcodeWrapDom1 && qrcodeWrapDom1.appendChild(qrcodeNode1);
qrcodeWrapDom2 && qrcodeWrapDom2.childNodes[0] && qrcodeWrapDom2.removeChild(qrcodeWrapDom2.childNodes[0]);
qrcodeWrapDom2 && qrcodeWrapDom2.appendChild(qrcodeNode2);
this.initQRCode();
})
}
getCourseDetail = (props) => {
const { courseId } = props.data;
getCourseDetail = () => {
const { courseId } = this.props.data;
Service.Hades('public/hades/getOfflineCourseDetail',{
courseId
}).then((res) => {
......@@ -79,27 +74,29 @@ export default class QRCodeModal extends React.Component {
});
}
downloadQRCode = () => {
initQRCode = () => {
const domList = document.querySelectorAll('.image-box');
for (let index = 0; index < domList.length; index++) {
const dom = domList[index];
html2canvas(dom, {
useCORS: true,
}).then(canvas => {
this.downloadImg(canvas, '二维码');
const dataUrl = canvas.toDataURL('image/png');
this.setState({ [`imgUrl${index + 1}`]: dataUrl });
});
}
}
downloadImg = (canvas, type) => {
const dataUrl = canvas.toDataURL('image/png');
const fileName = `${type}.png`;
window.downloadFile(dataUrl, fileName);
downloadImg = () => {
const { imgUrl1, imgUrl2 } = this.state;
const fileName = '二维码.png';
imgUrl1 && window.downloadFile(imgUrl1, fileName);
imgUrl2 && window.downloadFile(imgUrl2, fileName);
}
render() {
const { visible, onCancel } = this.props;
const { selectedDate, data = {} } = this.state;
const { selectedDate, data = {}, imgUrl1, imgUrl2, imgUrl, showPreviewModal } = this.state;
const { courseName, whetherSetSignIn, whetherSetSignOut } = data;
const date = moment(selectedDate).format('YYYY-MM-DD');
const unit = (data.signInTimeUnit || '').toLocaleLowerCase() + 's';
......@@ -142,24 +139,39 @@ export default class QRCodeModal extends React.Component {
type="primary"
style={{ marginLeft: 8 }}
onClick={() => {
this.downloadQRCode();
this.downloadImg();
}}
>下载二维码</Button>
</div>
{whetherSetSignIn === 'YES' && <div className="image-box" key="1">
{whetherSetSignIn === 'YES' && <div
className="image-box"
key="1"
onClick={() => this.setState({ showPreviewModal: true, imgUrl: imgUrl1 })}
>
<img src="https://image.xiaomaiketang.com/xm/xYSpX2y6ri.png" className="image" />
<div className="title">签到二维码</div>
<div className="name">{courseName}</div>
<div className="qrcodeWrap" id="qrcodeWrap1"></div>
<div className="time">签到时间:{signInTime}</div>
</div>}
{whetherSetSignOut === 'YES' && <div className="image-box" key="2">
{whetherSetSignOut === 'YES' && <div
className="image-box"
key="2"
onClick={() => this.setState({ showPreviewModal: true, imgUrl: imgUrl2 })}
>
<img src="https://image.xiaomaiketang.com/xm/xYSpX2y6ri.png" className="image" />
<div className="title">签退二维码</div>
<div className="name">{courseName}</div>
<div className="qrcodeWrap" id="qrcodeWrap2"></div>
<div className="time">签退时间:{signOutTime}</div>
</div>}
{showPreviewModal &&
<ScanFileModal
fileType="JPG"
item={{ ossUrl: imgUrl }}
close={() => this.setState({ showPreviewModal: false })}
/>
}
</Modal>
)
}
......
......@@ -22,7 +22,7 @@
font-size: 14px;
color: #fff;
position: absolute;
top: 60px;
top: 58px;
left: 50%;
transform: translateX(-50%);
width: 286px;
......
......@@ -102,11 +102,13 @@ class Home extends React.Component {
incLiveCourseNum: res.result.incLiveCourseNum,
incVideoCourseNum: res.result.incVideoCourseNum,
incPictureCourseNum: res.result.incPictureCourseNum,
incOfflineCourseNum: res.result.incOfflineCourseNum,
incTrainingPlanNum: res.result.incTrainingPlanNum,
liveCourseNum: res.result.liveCourseNum,
totalCustomerNum: res.result.totalCustomerNum,
videoCourseNum: res.result.videoCourseNum,
pictureCourseNum: res.result.pictureCourseNum,
offlineCourseNum: res.result.offlineCourseNum,
trainingPlanNum: res.result.trainingPlanNum,
})
}
......@@ -231,6 +233,8 @@ class Home extends React.Component {
unfinishedNum,
completeNum,
planCustomerNum,
incOfflineCourseNum,
offlineCourseNum,
} = this.state;
const data = [
{
......@@ -320,12 +324,12 @@ class Home extends React.Component {
<div className="course-item">
<div className="course-title">线下课</div>
<div className="data">
<span className="course-number">0</span>
<span className="course-number">{offlineCourseNum}</span>
<span className="course-word">本月新增</span>
{false &&
{incOfflineCourseNum > 0 &&
<span className="icon iconfont">&#xe635;</span>
}
<span className="add-number">0</span>
<span className="add-number">{incOfflineCourseNum}</span>
</div>
</div>
</div>
......
......@@ -52,6 +52,10 @@ class ExamShareModal extends React.Component {
const dom = document.querySelector('#poster');
html2canvas(dom, {
useCORS: true,
scale: 2,
logging: false,
background: '#FFF',
allowTaint: true,
}).then(canvas => {
const downloadDOM = document.createElement('a');
const { courseName } = this.props.data;
......
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