Commit 64f4b1f6 by guomingpang
parents b23fca45 7638b279
...@@ -12,7 +12,6 @@ npm-shrinkwrap.json ...@@ -12,7 +12,6 @@ npm-shrinkwrap.json
.DS_Store .DS_Store
.AppleDouble .AppleDouble
.LSOverride .LSOverride
yarn.lock
yarn-error.lock yarn-error.lock
# IntelliJ project files # IntelliJ project files
...@@ -57,7 +56,6 @@ npm-debug.log ...@@ -57,7 +56,6 @@ npm-debug.log
*.zip *.zip
build/vendor.js.map build/vendor.js.map
package-lock.json
.vscode/* .vscode/*
demo.js demo.js
debug.log debug.log
This source diff could not be displayed because it is too large. You can view the blob instead.
import User from '@/common/js/user';
import college from '@/common/lottie/college';
import { PageControl, XMTable } from '@/components';
import CourseService from '@/domains/course-domain/CourseService';
import { Button, message } from 'antd';
import React from 'react'; import React from 'react';
import { withRouter } from "react-router-dom"; import { withRouter } from 'react-router-dom';
import { Table, Button, Modal, message } from 'antd';
import dealTimeDuration from '../utils/dealTimeDuration'; import dealTimeDuration from '../utils/dealTimeDuration';
import { PageControl } from "@/components";
import './DataList.less'; import './DataList.less';
import CourseService from "@/domains/course-domain/CourseService";
import User from '@/common/js/user';
const liveTypeMap = { const liveTypeMap = {
USER: "普通用户", USER: '普通用户',
ANCHOR: "讲师", ANCHOR: '讲师',
ADMIN: "管理员(助教)", ADMIN: '管理员(助教)',
GUEST: "游客" GUEST: '游客',
}; };
class PlaybackData extends React.Component { class PlaybackData extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
const courseId = getParameterByName("id"); // 课程ID const courseId = getParameterByName('id'); // 课程ID
this.state = { this.state = {
playbackData: [], playbackData: [],
...@@ -24,8 +25,8 @@ class PlaybackData extends React.Component { ...@@ -24,8 +25,8 @@ class PlaybackData extends React.Component {
size: 10, size: 10,
total: 0, total: 0,
liveCourseId: courseId, liveCourseId: courseId,
storeId: User.getStoreId() storeId: User.getStoreId(),
} };
} }
componentDidMount() { componentDidMount() {
...@@ -33,12 +34,12 @@ class PlaybackData extends React.Component { ...@@ -33,12 +34,12 @@ class PlaybackData extends React.Component {
} }
fetchPlaybackList = (page = 1) => { fetchPlaybackList = (page = 1) => {
const { size, liveCourseId } = this.state const { size, liveCourseId } = this.state;
const params = { const params = {
liveCourseId, liveCourseId,
current: page, current: page,
size size,
} };
CourseService.fetchPlaybackList(params).then((res) => { CourseService.fetchPlaybackList(params).then((res) => {
if (res.result) { if (res.result) {
...@@ -47,38 +48,35 @@ class PlaybackData extends React.Component { ...@@ -47,38 +48,35 @@ class PlaybackData extends React.Component {
playbackData: records, playbackData: records,
current, current,
size, size,
total total,
}); });
} }
}); });
}; };
getPlaybackColumns() { getPlaybackColumns() {
const columns = [ const columns = [
{ {
title: "观看学员", title: '观看学员',
dataIndex: "userName", dataIndex: 'userName',
}, },
{ {
title: "手机号", title: '手机号',
dataIndex: "phone" dataIndex: 'phone',
}, },
{ {
title: "观看者类型", title: '观看者类型',
dataIndex: "userRole", dataIndex: 'userRole',
render: (text) => <span>{liveTypeMap[text]}</span>, render: (text) => <span>{liveTypeMap[text]}</span>,
}, },
{ {
title: "开始观看时间", title: '开始观看时间',
dataIndex: "entryTime", dataIndex: 'entryTime',
render: (text) => ( render: (text) => <span>{text ? formatDate('YYYY-MM-DD H:i', parseInt(text)) : '-'}</span>,
<span>{text ? formatDate("YYYY-MM-DD H:i", parseInt(text)) : '-'}</span>
),
}, },
{ {
title: "观看时长", title: '观看时长',
dataIndex: "lookingDuration", dataIndex: 'lookingDuration',
render: (text) => { render: (text) => {
return <span>{text ? dealTimeDuration(text) : '-'}</span>; return <span>{text ? dealTimeDuration(text) : '-'}</span>;
}, },
...@@ -92,53 +90,55 @@ class PlaybackData extends React.Component { ...@@ -92,53 +90,55 @@ class PlaybackData extends React.Component {
CourseService.exportPlayBackCourseData({ CourseService.exportPlayBackCourseData({
liveCourseId, liveCourseId,
exportLiveType: "PLAY_BACK", exportLiveType: 'PLAY_BACK',
storeId storeId,
}).then((res) => { }).then((res) => {
const link = res.result; const link = res.result;
this.setState({ this.setState({
link link,
}); });
document.getElementById("load-play-back-excel").click(); document.getElementById('load-play-back-excel').click();
if(res.success){ if (res.success) {
message.success("导出成功!") message.success('导出成功!');
} }
}) });
} }
onShowSizeChange = (current, size) => { onShowSizeChange = (current, size) => {
if (current == size) { if (current == size) {
return; return;
} }
this.setState({ size }, this.fetchUserData) this.setState({ size }, this.fetchUserData);
} };
render() { render() {
const { playbackData, total, current, size, link} = this.state const { playbackData, total, current, size, link } = this.state;
return ( return (
<div> <div>
<a <a href={link} target='_blank' download id='load-play-back-excel' style={{ position: 'absolute', left: '-10000px' }}>
href={link}
target="_blank"
download
id="load-play-back-excel"
style={{ position: "absolute", left: "-10000px" }}
>
111 111
</a> </a>
<Button onClick={() => {this.handleplaybackExport()}}>导出</Button> <Button
<Table onClick={() => {
this.handleplaybackExport();
}}>
导出
</Button>
<XMTable
renderEmpty={{
image: college,
description: '暂无数据',
}}
bordered bordered
size="small" size='small'
columns={this.getPlaybackColumns()} columns={this.getPlaybackColumns()}
dataSource={playbackData} dataSource={playbackData}
pagination={false} pagination={false}
style={{ margin: '16px 0' }}> style={{ margin: '16px 0' }}></XMTable>
</Table> {total > 0 && (
{ total > 0 &&
<PageControl <PageControl
size="small" size='small'
current={current - 1} current={current - 1}
pageSize={size} pageSize={size}
total={total} total={total}
...@@ -147,9 +147,9 @@ class PlaybackData extends React.Component { ...@@ -147,9 +147,9 @@ class PlaybackData extends React.Component {
this.fetchPlaybackList(page + 1); this.fetchPlaybackList(page + 1);
}} }}
/> />
} )}
</div> </div>
) );
} }
} }
......
...@@ -6,24 +6,23 @@ ...@@ -6,24 +6,23 @@
* @Description: 大班直播、互动班课的直播课列表 * @Description: 大班直播、互动班课的直播课列表
*/ */
import User from '@/common/js/user';
import college from '@/common/lottie/college';
import { PageControl, XMTable } from '@/components';
import DownloadLiveModal from '@/components/DownloadLiveModal';
import BaseService from '@/domains/basic-domain/baseService';
import { appId, LIVE_SHARE } from '@/domains/course-domain/constants';
import CourseService from '@/domains/course-domain/CourseService';
import { QuestionCircleOutlined } from '@ant-design/icons';
import { Dropdown, message, Modal, Switch, Tooltip } from 'antd';
import React from 'react'; import React from 'react';
import { Table, Modal, message, Dropdown, Switch, Tooltip } from 'antd';
import { Route, withRouter } from 'react-router-dom'; import { Route, withRouter } from 'react-router-dom';
import { PageControl } from '@/components'; import _ from 'underscore';
import DownloadLiveModal from '@/components/DownloadLiveModal'; import DataList from '../DataList/DataList';
import ManageCoursewareModal from '../modal/ManageCoursewareModal'; import ManageCoursewareModal from '../modal/ManageCoursewareModal';
import ShareLiveModal from '../modal/ShareLiveModal';
import RelatedPlanModal from '../modal/RelatedPlanModal'; import RelatedPlanModal from '../modal/RelatedPlanModal';
import ShareLiveModal from '../modal/ShareLiveModal';
import './LiveCourseList.less'; import './LiveCourseList.less';
import { QuestionCircleOutlined } from '@ant-design/icons';
import { appId, LIVE_SHARE } from '@/domains/course-domain/constants';
import CourseService from '@/domains/course-domain/CourseService';
import BaseService from '@/domains/basic-domain/baseService';
import DataList from '../DataList/DataList';
import User from '@/common/js/user';
import _ from 'underscore';
const { confirm } = Modal; const { confirm } = Modal;
const courseStateShow = { const courseStateShow = {
...@@ -785,7 +784,11 @@ class LiveCourseList extends React.Component { ...@@ -785,7 +784,11 @@ class LiveCourseList extends React.Component {
return ( return (
<div className='live-course-list'> <div className='live-course-list'>
<Table <XMTable
renderEmpty={{
image: college,
description: '暂无数据',
}}
bordered bordered
size='middle' size='middle'
pagination={false} pagination={false}
......
...@@ -6,79 +6,85 @@ ...@@ -6,79 +6,85 @@
* @Description 余额异常弹窗 * @Description 余额异常弹窗
*/ */
import React from 'react'; import React from 'react';
import {Table, Modal,Input} from 'antd'; import { Modal, Input } from 'antd';
import { PageControl } from "@/components"; import college from '@/common/lottie/college';
import Service from "@/common/js/service"; import { PageControl, XMTable } from '@/components';
import User from '@/common/js/user' import Service from '@/common/js/service';
import User from '@/common/js/user';
import './WatchDataModal.less'; import './WatchDataModal.less';
import dealTimeDuration from "../../utils/dealTimeDuration"; import dealTimeDuration from '../../utils/dealTimeDuration';
const { Search } = Input; const { Search } = Input;
class WatchDataModal extends React.Component { class WatchDataModal extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
visible:true, visible: true,
dataSource:[], dataSource: [],
size:10, size: 10,
query: { query: {
current: 1, current: 1,
}, },
totalCount:0 totalCount: 0,
}; };
} }
componentDidMount() { componentDidMount() {
this.handleFetchDataList(); this.handleFetchDataList();
} }
onClose = () =>{ onClose = () => {
this.props.close(); this.props.close();
} };
// 获取观看视频数据列表 // 获取观看视频数据列表
handleFetchDataList = () => { handleFetchDataList = () => {
const {query,size,totalCount} = this.state const { query, size, totalCount } = this.state;
const { id } = this.props.data; const { id } = this.props.data;
const params ={ const params = {
...query, ...query,
size, size,
courseId:id, courseId: id,
storeId:User.getStoreId() storeId: User.getStoreId(),
} };
Service.Hades('public/hades/mediaCourseWatchInfo', params).then((res) => { Service.Hades('public/hades/mediaCourseWatchInfo', params).then((res) => {
const { result = {} } = res ; const { result = {} } = res;
const { records = [], total = 0 } = result; const { records = [], total = 0 } = result;
this.setState({ this.setState({
dataSource: records, dataSource: records,
totalCount: Number(total) totalCount: Number(total),
}); });
}); });
} };
handleChangNickname = (value)=>{ handleChangNickname = (value) => {
const isPhone = (value || '').match(/^\d+$/); const isPhone = (value || '').match(/^\d+$/);
const { query } = this.state; const { query } = this.state;
if(isPhone){ if (isPhone) {
query.phone = value; query.phone = value;
query.nickName = null; query.nickName = null;
}else{ } else {
query.nickName = value; query.nickName = value;
query.phone = null; query.phone = null;
} }
query.current = 1; query.current = 1;
this.setState({ this.setState({
query query,
}) });
} };
onShowSizeChange = (current, size) => { onShowSizeChange = (current, size) => {
if (current == size) { if (current == size) {
return return;
} }
this.setState({ this.setState(
size {
},()=>{this.handleFetchDataList()}) size,
},
() => {
this.handleFetchDataList();
} }
);
};
// 请求表头 // 请求表头
parseColumns = () => { parseColumns = () => {
...@@ -86,91 +92,109 @@ class WatchDataModal extends React.Component { ...@@ -86,91 +92,109 @@ class WatchDataModal extends React.Component {
{ {
title: '观看学员', title: '观看学员',
key: 'name', key: 'name',
dataIndex: 'name' dataIndex: 'name',
}, },
{ {
title: '手机号', title: '手机号',
key: 'phone', key: 'phone',
dataIndex: 'phone' dataIndex: 'phone',
}, },
{ {
title: '观看者类型', title: '观看者类型',
key: 'userRole', key: 'userRole',
dataIndex: 'userRole' dataIndex: 'userRole',
}, },
{ {
title: '首次观看时间', title: '首次观看时间',
key: 'firstWatch', key: 'firstWatch',
dataIndex: 'firstWatch', dataIndex: 'firstWatch',
render: (val) => { render: (val) => {
return formatDate('YYYY-MM-DD H:i', val) return formatDate('YYYY-MM-DD H:i', val);
} },
}, },
{ {
title: '观看总时长', title: '观看总时长',
key: 'watchDuration', key: 'watchDuration',
dataIndex: 'watchDuration', dataIndex: 'watchDuration',
render: (val) => { render: (val) => {
return <span>{val ? dealTimeDuration(val) : "00:00:00" }</span> return <span>{val ? dealTimeDuration(val) : '00:00:00'}</span>;
} },
}, },
{ {
title: '学习进度', title: '学习进度',
key: 'progress', key: 'progress',
dataIndex: 'progress', dataIndex: 'progress',
render: (val) => { render: (val) => {
return <span>{val === 100 ? '已完成' : `${val || 0}%`}</span> return <span>{val === 100 ? '已完成' : `${val || 0}%`}</span>;
} },
} },
]; ];
return columns; return columns;
} };
render() { render() {
const { visible,size,dataSource,totalCount,query} = this.state; const { visible, size, dataSource, totalCount, query } = this.state;
return ( return (
<Modal <Modal
title="图文课观看数据" title='图文课观看数据'
visible={visible} visible={visible}
footer={null} footer={null}
onCancel={this.onClose} onCancel={this.onClose}
maskClosable={false} maskClosable={false}
className="watch-data-modal" className='watch-data-modal'
closable={true} closable={true}
width={800} width={800}
closeIcon={<span className="icon iconfont modal-close-icon">&#xe6ef;</span>} closeIcon={<span className='icon iconfont modal-close-icon'>&#xe6ef;</span>}>
> <div className='search-container'>
<div className="search-container"> <Search
<Search placeholder="搜索学员姓名/手机号" style={{ width: 200 }} onChange={(e) => { this.handleChangNickname(e.target.value)}} onSearch={ () => { this.handleFetchDataList()}} enterButton={<span className="icon iconfont">&#xe832;</span>}/> placeholder='搜索学员姓名/手机号'
style={{ width: 200 }}
onChange={(e) => {
this.handleChangNickname(e.target.value);
}}
onSearch={() => {
this.handleFetchDataList();
}}
enterButton={<span className='icon iconfont'>&#xe832;</span>}
/>
</div> </div>
<div> <div>
<Table <XMTable
rowKey={record => record.id} renderEmpty={{
image: college,
description: '暂无数据',
}}
rowKey={(record) => record.id}
dataSource={dataSource} dataSource={dataSource}
columns={this.parseColumns()} columns={this.parseColumns()}
pagination={false} pagination={false}
bordered bordered
/> />
{dataSource.length >0 && {dataSource.length > 0 && (
<div className="box-footer"> <div className='box-footer'>
<PageControl <PageControl
current={query.current - 1} current={query.current - 1}
pageSize={size} pageSize={size}
total={totalCount} total={totalCount}
size="small" size='small'
toPage={(page) => { toPage={(page) => {
const _query = {...query, current: page + 1}; const _query = { ...query, current: page + 1 };
this.setState({ this.setState(
query:_query {
},()=>{ this.handleFetchDataList()}) query: _query,
},
() => {
this.handleFetchDataList();
}
);
}} }}
onShowSizeChange={this.onShowSizeChange} onShowSizeChange={this.onShowSizeChange}
/> />
</div> </div>
} )}
</div> </div>
</Modal> </Modal>
) );
} }
} }
......
import college from '@/common/lottie/college';
import { XMTable } from '@/components';
import { Modal } from 'antd';
import React from 'react'; import React from 'react';
import { Modal, Table } from "antd"; import './AccountChargeModal.less';
import ChargeArgeement from "./ChargeArgeement"; import ChargeArgeement from './ChargeArgeement';
import "./AccountChargeModal.less"; class AccountChargeRecords extends React.Component {
class AccountChargeRecords extends React.Component{
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
...@@ -15,9 +17,7 @@ class AccountChargeRecords extends React.Component{ ...@@ -15,9 +17,7 @@ class AccountChargeRecords extends React.Component{
getList = () => { getList = () => {
const { instId } = window.currentUserInstInfo; const { instId } = window.currentUserInstInfo;
axios axios.Business('public/liveAssets/rechargeProtocol', { instId }).then((res) => {
.Business("public/liveAssets/rechargeProtocol", { instId })
.then((res) => {
const list = res.result; const list = res.result;
this.setState({ this.setState({
list, list,
...@@ -42,29 +42,28 @@ class AccountChargeRecords extends React.Component{ ...@@ -42,29 +42,28 @@ class AccountChargeRecords extends React.Component{
render() { render() {
const columns = [ const columns = [
{ {
title: "签订人", title: '签订人',
dataIndex: "operatorName", dataIndex: 'operatorName',
width: 140 width: 140,
}, },
{ title: "关联订单ID", dataIndex: "orderId" }, { title: '关联订单ID', dataIndex: 'orderId' },
{ {
title: "签订时间", title: '签订时间',
dataIndex: "createTime", dataIndex: 'createTime',
render: (text, record) => { render: (text, record) => {
return <span>{formatDate("YYYY-MM-DD H:i", parseInt(text))}</span>; return <span>{formatDate('YYYY-MM-DD H:i', parseInt(text))}</span>;
}, },
}, },
{ {
title: "签订协议", title: '签订协议',
dataIndex: "operate", dataIndex: 'operate',
render: (text, record) => { render: (text, record) => {
return ( return (
<div <div
style={{ cursor: "pointer", color: "#FC9C6B" }} style={{ cursor: 'pointer', color: '#FC9C6B' }}
onClick={() => { onClick={() => {
this.handleProtcol(record.protocolId); this.handleProtcol(record.protocolId);
}} }}>
>
《服务协议》 《服务协议》
</div> </div>
); );
...@@ -74,29 +73,31 @@ class AccountChargeRecords extends React.Component{ ...@@ -74,29 +73,31 @@ class AccountChargeRecords extends React.Component{
const { list } = this.state; const { list } = this.state;
return ( return (
<Modal <Modal
title="服务协议签订记录" title='服务协议签订记录'
visible={true} visible={true}
width={680} width={680}
footer={null} footer={null}
maskClosable={false} maskClosable={false}
closeIcon={<span className="icon iconfont modal-close-icon">&#xe6ef;</span>} closeIcon={<span className='icon iconfont modal-close-icon'>&#xe6ef;</span>}
onCancel={() => { onCancel={() => {
this.props.close(); this.props.close();
}} }}>
>
<div> <div>
<div <div
style={{ style={{
fontSize: "14px", fontSize: '14px',
color: "#666666", color: '#666666',
lineHeight: "20px", lineHeight: '20px',
marginBottom: 16, marginBottom: 16,
}} }}>
>
以下是本校区自助充值时签订协议的记录 以下是本校区自助充值时签订协议的记录
</div> </div>
<Table <XMTable
size="middle" renderEmpty={{
image: college,
description: '暂无数据',
}}
size='middle'
columns={columns} columns={columns}
dataSource={list} dataSource={list}
pagination={false} pagination={false}
......
import college from '@/common/lottie/college';
import { PageControl, XMTable } from '@/components';
import { Modal, Tooltip } from 'antd';
import React from 'react'; import React from 'react';
import { Modal, Table, Tooltip } from "antd"; import './AccountChargeModal.less';
import { ShowTips, PageControl } from "@/components";
import "./AccountChargeModal.less";
class ChargingDetailModal extends React.Component { class ChargingDetailModal extends React.Component {
constructor(props) { constructor(props) {
...@@ -25,9 +26,7 @@ class ChargingDetailModal extends React.Component { ...@@ -25,9 +26,7 @@ class ChargingDetailModal extends React.Component {
handleToPage = (page = 1) => { handleToPage = (page = 1) => {
const params = _.clone(this.state.query); const params = _.clone(this.state.query);
params.current = page; params.current = page;
axios axios.Apollo('public/businessLive/queryStudentVisitData', params).then((res) => {
.Apollo("public/businessLive/queryStudentVisitData", params)
.then((res) => {
if (res.result) { if (res.result) {
const { records = [], total } = res.result; const { records = [], total } = res.result;
this.setState({ this.setState({
...@@ -40,7 +39,7 @@ class ChargingDetailModal extends React.Component { ...@@ -40,7 +39,7 @@ class ChargingDetailModal extends React.Component {
}; };
getTeacherData = () => { getTeacherData = () => {
window.axios window.axios
.Apollo("public/businessLive/queryTeacherVisitData", { .Apollo('public/businessLive/queryTeacherVisitData', {
liveCourseId: this.props.liveCourseId, liveCourseId: this.props.liveCourseId,
}) })
.then((res) => { .then((res) => {
...@@ -57,27 +56,27 @@ class ChargingDetailModal extends React.Component { ...@@ -57,27 +56,27 @@ class ChargingDetailModal extends React.Component {
let hours = Math.floor(time / 3600); let hours = Math.floor(time / 3600);
let mins = Math.floor(diff / 60); let mins = Math.floor(diff / 60);
let seconds = Math.floor(time % 60); let seconds = Math.floor(time % 60);
hours = hours < 10 ? "0" + hours : hours; hours = hours < 10 ? '0' + hours : hours;
mins = mins < 10 ? "0" + mins : mins; mins = mins < 10 ? '0' + mins : mins;
seconds = seconds < 10 ? "0" + seconds : seconds; seconds = seconds < 10 ? '0' + seconds : seconds;
return hours + ":" + mins + ":" + seconds; return hours + ':' + mins + ':' + seconds;
}; };
getColumns = (type) => { getColumns = (type) => {
const columns = [ const columns = [
{ {
title: type == "student" ? "学生姓名" : "老师姓名", title: type == 'student' ? '学生姓名' : '老师姓名',
dataIndex: "userName", dataIndex: 'userName',
}, },
{ {
title: "手机号", title: '手机号',
dataIndex: "phone", dataIndex: 'phone',
render: (text, record) => { render: (text, record) => {
return <p>{text}</p>; return <p>{text}</p>;
}, },
}, },
{ {
title: "累计在线时长", title: '累计在线时长',
dataIndex: "totalDuration", dataIndex: 'totalDuration',
render: (text, record) => { render: (text, record) => {
return <span>{text ? this.dealTimeDuration(text) : '-'}</span>; return <span>{text ? this.dealTimeDuration(text) : '-'}</span>;
}, },
...@@ -86,14 +85,14 @@ class ChargingDetailModal extends React.Component { ...@@ -86,14 +85,14 @@ class ChargingDetailModal extends React.Component {
title: ( title: (
<span> <span>
是否计费&nbsp; 是否计费&nbsp;
<Tooltip title="仅对累计在线时长≥10分钟的老师或学员计费"> <Tooltip title='仅对累计在线时长≥10分钟的老师或学员计费'>
<span className="icon iconfont">&#xe6f2;</span> <span className='icon iconfont'>&#xe6f2;</span>
</Tooltip> </Tooltip>
</span> </span>
), ),
dataIndex: "type", dataIndex: 'type',
render: (text, record) => { render: (text, record) => {
return <span>{record.totalDuration > 600 ? "计费" : "不计费"}</span>; //大于十分钟的计费 return <span>{record.totalDuration > 600 ? '计费' : '不计费'}</span>; //大于十分钟的计费
}, },
}, },
]; ];
...@@ -103,38 +102,45 @@ class ChargingDetailModal extends React.Component { ...@@ -103,38 +102,45 @@ class ChargingDetailModal extends React.Component {
const { list, query, totalCount, teacherList } = this.state; const { list, query, totalCount, teacherList } = this.state;
return ( return (
<Modal <Modal
title="计费人数详情" title='计费人数详情'
visible={true} visible={true}
width={680} width={680}
maskClosable={false} maskClosable={false}
closeIcon={<span className="icon iconfont modal-close-icon">&#xe6ef;</span>} closeIcon={<span className='icon iconfont modal-close-icon'>&#xe6ef;</span>}
className="charging-detail-modal" className='charging-detail-modal'
footer={null} footer={null}
onCancel={() => { onCancel={() => {
this.props.close(); this.props.close();
}} }}>
>
<div> <div>
<div style={{ marginBottom: 16 }}> <div style={{ marginBottom: 16 }}>
<div className="detail-title">老师详情</div> <div className='detail-title'>老师详情</div>
<Table <XMTable
size="middle" renderEmpty={{
columns={this.getColumns("teacher")} image: college,
description: '暂无数据',
}}
size='middle'
columns={this.getColumns('teacher')}
dataSource={teacherList} dataSource={teacherList}
pagination={false} pagination={false}
bordered bordered
/> />
</div> </div>
<div className="detail-title">学生详情</div> <div className='detail-title'>学生详情</div>
<Table <XMTable
size="middle" renderEmpty={{
columns={this.getColumns("student")} image: college,
description: '暂无数据',
}}
size='middle'
columns={this.getColumns('student')}
dataSource={list} dataSource={list}
pagination={false} pagination={false}
bordered bordered
/> />
<PageControl <PageControl
size="small" size='small'
current={query.current - 1} current={query.current - 1}
pageSize={query.size} pageSize={query.size}
total={totalCount} total={totalCount}
......
...@@ -6,21 +6,19 @@ ...@@ -6,21 +6,19 @@
* @LastEditTime: 2021-02-01 14:00:36 * @LastEditTime: 2021-02-01 14:00:36
*/ */
import React, { useState, useEffect } from "react"; import college from '@/common/lottie/college';
import { Modal, Table, Button, message } from "antd"; import { PageControl, XMTable } from '@/components';
import Bus from '@/core/bus'; import Bus from '@/core/bus';
import { PageControl } from "@/components"; import { Button, message, Modal } from 'antd';
import React from 'react';
import hasExportPermission from '../utils/hasExportPermission';
import dealTimeDuration from '../utils/dealTimeDuration'; import dealTimeDuration from '../utils/dealTimeDuration';
import hasExportPermission from '../utils/hasExportPermission';
import "./ClassRecordModal.less"; import './ClassRecordModal.less';
const liveTypeMap = { const liveTypeMap = {
USER: "学生", USER: '学生',
ANCHOR: "老师", ANCHOR: '老师',
ADMIN: "助教", ADMIN: '助教',
}; };
class PlayBackRecordModal extends React.Component { class PlayBackRecordModal extends React.Component {
...@@ -46,9 +44,7 @@ class PlayBackRecordModal extends React.Component { ...@@ -46,9 +44,7 @@ class PlayBackRecordModal extends React.Component {
fetchPlayBackList = (page = 1) => { fetchPlayBackList = (page = 1) => {
const params = _.clone(this.state.query); const params = _.clone(this.state.query);
params.current = page; params.current = page;
window.axios window.axios.Apollo('public/businessLive/queryUserReplayRecordPage', params).then((res) => {
.Apollo("public/businessLive/queryUserReplayRecordPage", params)
.then((res) => {
const { records = [], total } = res.result; const { records = [], total } = res.result;
this.setState({ this.setState({
query: params, query: params,
...@@ -61,7 +57,7 @@ class PlayBackRecordModal extends React.Component { ...@@ -61,7 +57,7 @@ class PlayBackRecordModal extends React.Component {
fetchAllStatistics = () => { fetchAllStatistics = () => {
const { liveCourseId } = this.props.liveItem; const { liveCourseId } = this.props.liveItem;
window.axios window.axios
.Apollo("public/businessLive/queryReplayStatistics", { .Apollo('public/businessLive/queryReplayStatistics', {
liveCourseId, liveCourseId,
}) })
.then((res) => { .then((res) => {
...@@ -80,7 +76,7 @@ class PlayBackRecordModal extends React.Component { ...@@ -80,7 +76,7 @@ class PlayBackRecordModal extends React.Component {
const hours = Math.floor(time / 3600); const hours = Math.floor(time / 3600);
const mins = Math.floor(diff / 60); const mins = Math.floor(diff / 60);
const seconds = Math.floor(time % 60); const seconds = Math.floor(time % 60);
return hours + "小时" + mins + "分"; return hours + '小时' + mins + '分';
}; };
// 导出 // 导出
...@@ -88,10 +84,12 @@ class PlayBackRecordModal extends React.Component { ...@@ -88,10 +84,12 @@ class PlayBackRecordModal extends React.Component {
const { liveItem, type } = this.props; const { liveItem, type } = this.props;
const { liveCourseId } = liveItem; const { liveCourseId } = liveItem;
const url = !type ? 'api-b/b/lesson/exportLargeClassLiveAsync' : 'api-b/b/lesson/exportClassInteractionLiveSync'; const url = !type ? 'api-b/b/lesson/exportLargeClassLiveAsync' : 'api-b/b/lesson/exportClassInteractionLiveSync';
window.axios.post(url, { window.axios
.post(url, {
liveCourseId, liveCourseId,
exportLiveType: 0 exportLiveType: 0,
}).then((res) => { })
.then((res) => {
Bus.trigger('get_download_count'); Bus.trigger('get_download_count');
Modal.success({ Modal.success({
title: '导出任务提交成功', title: '导出任务提交成功',
...@@ -99,16 +97,18 @@ class PlayBackRecordModal extends React.Component { ...@@ -99,16 +97,18 @@ class PlayBackRecordModal extends React.Component {
okText: '我知道了', okText: '我知道了',
}); });
}); });
} };
handleExportV5 = () => { handleExportV5 = () => {
const { liveItem, type } = this.props; const { liveItem, type } = this.props;
const { liveCourseId } = liveItem; const { liveCourseId } = liveItem;
const url = !type ? 'public/businessLive/exportLargeClassLiveAsync' : 'public/businessLive/exportClassInteractionLiveSync'; const url = !type ? 'public/businessLive/exportLargeClassLiveAsync' : 'public/businessLive/exportClassInteractionLiveSync';
window.axios.Apollo(url, { window.axios
.Apollo(url, {
liveCourseId, liveCourseId,
exportLiveType: 'PLAY_BACK' exportLiveType: 'PLAY_BACK',
}).then((res) => { })
.then((res) => {
Bus.trigger('get_download_count'); Bus.trigger('get_download_count');
Modal.success({ Modal.success({
title: '导出任务提交成功', title: '导出任务提交成功',
...@@ -116,78 +116,67 @@ class PlayBackRecordModal extends React.Component { ...@@ -116,78 +116,67 @@ class PlayBackRecordModal extends React.Component {
okText: '我知道了', okText: '我知道了',
}); });
}); });
} };
render() { render() {
const columns = [ const columns = [
{ {
title: "观看者姓名", title: '观看者姓名',
dataIndex: "userName", dataIndex: 'userName',
}, },
{ {
title: "观看者手机号", title: '观看者手机号',
dataIndex: "phone", dataIndex: 'phone',
render: (text, record) => { render: (text, record) => {
return ( return (
<p> <p>
{!( {!((!window.NewVersion && !window.currentUserInstInfo.teacherId) || (window.NewVersion && Permission.hasEduStudentPhone()))
(!window.NewVersion && !window.currentUserInstInfo.teacherId) || ? (text || '').replace(/(\d{3})(\d{4})(\d{4})/, '$1****$3')
(window.NewVersion && Permission.hasEduStudentPhone())
)
? (text || "").replace(/(\d{3})(\d{4})(\d{4})/, "$1****$3")
: text} : text}
</p> </p>
); );
}, },
}, },
{ {
title: "观看者类型", title: '观看者类型',
dataIndex: "liveRole", dataIndex: 'liveRole',
key: "liveRole", key: 'liveRole',
render: (text) => <span>{liveTypeMap[text]}</span>, render: (text) => <span>{liveTypeMap[text]}</span>,
}, },
{ {
title: "开始观看时间", title: '开始观看时间',
dataIndex: "entryTime", dataIndex: 'entryTime',
key: "entryTime", key: 'entryTime',
render: (text) => ( render: (text) => <span>{text ? formatDate('YYYY-MM-DD H:i', parseInt(text)) : '-'}</span>,
<span>{text ? formatDate("YYYY-MM-DD H:i", parseInt(text)) : '-'}</span>
),
}, },
{ {
title: "观看时长", title: '观看时长',
dataIndex: "lookingDuration", dataIndex: 'lookingDuration',
key: "lookingDuration", key: 'lookingDuration',
render: (text) => { render: (text) => {
return <span>{text ? dealTimeDuration(text) : '-'}</span>; return <span>{text ? dealTimeDuration(text) : '-'}</span>;
}, },
}, },
]; ];
const { const { query, total, playBackList, totalWatchNum, recordDuration } = this.state;
query,
total,
playBackList,
totalWatchNum,
recordDuration,
} = this.state;
const { type } = this.props; const { type } = this.props;
return ( return (
<Modal <Modal
title="回放记录" title='回放记录'
className="play-back-modal" className='play-back-modal'
width={680} width={680}
visible={true} visible={true}
maskClosable={false} maskClosable={false}
closeIcon={<span className="icon iconfont modal-close-icon">&#xe6ef;</span>} closeIcon={<span className='icon iconfont modal-close-icon'>&#xe6ef;</span>}
footer={null} footer={null}
onCancel={() => { onCancel={() => {
this.props.close(); this.props.close();
}} }}>
> {hasExportPermission(type) && (
{ <Button
hasExportPermission(type) && onClick={_.debounce(
<Button onClick={_.debounce(() => { () => {
if (!playBackList.length) { if (!playBackList.length) {
message.warning('暂无数据可导出'); message.warning('暂无数据可导出');
return; return;
...@@ -197,17 +186,26 @@ class PlayBackRecordModal extends React.Component { ...@@ -197,17 +186,26 @@ class PlayBackRecordModal extends React.Component {
} else { } else {
this.handleExport(); this.handleExport();
} }
}, 500, true)}>导出</Button> },
} 500,
<Table true
size="small" )}>
导出
</Button>
)}
<XMTable
renderEmpty={{
image: college,
description: '暂无数据',
}}
size='small'
columns={columns} columns={columns}
dataSource={playBackList} dataSource={playBackList}
pagination={false} pagination={false}
className="table-no-scrollbar" className='table-no-scrollbar'
/> />
<PageControl <PageControl
size="small" size='small'
current={query.current - 1} current={query.current - 1}
pageSize={query.size} pageSize={query.size}
total={total} total={total}
......
...@@ -109,13 +109,8 @@ class ShareLiveModal extends React.Component { ...@@ -109,13 +109,8 @@ class ShareLiveModal extends React.Component {
switch (type) { switch (type) {
case 'liveClass': // 直播课 case 'liveClass': // 直播课
if (courseMediaVOS && courseMediaVOS.length > 0) { if (courseMediaVOS && courseMediaVOS.length > 0) {
data.courseMediaVOS.map((item, index) => { const coverItem = courseMediaVOS.filter((item) => item.contentType === 'COVER');
if (item.contentType === 'COVER') { coverImgSrc = coverItem.length === 0 ? 'https://image.xiaomaiketang.com/xm/Yip2YtFDwH.png' : coverItem[0].mediaUrl;
coverImgSrc = item.mediaUrl;
} else {
coverImgSrc = 'https://image.xiaomaiketang.com/xm/Yip2YtFDwH.png';
}
});
} else { } else {
coverImgSrc = 'https://image.xiaomaiketang.com/xm/Yip2YtFDwH.png'; coverImgSrc = 'https://image.xiaomaiketang.com/xm/Yip2YtFDwH.png';
} }
......
...@@ -5,80 +5,86 @@ ...@@ -5,80 +5,86 @@
* @Last Modified time: 2020-05-25 16:50:47 * @Last Modified time: 2020-05-25 16:50:47
* @Description 余额异常弹窗 * @Description 余额异常弹窗
*/ */
import User from '@/common/js/user';
import { PageControl, XMTable } from '@/components';
import CourseService from '@/domains/course-domain/CourseService';
import { Input, Modal } from 'antd';
import college from '@/common/lottie/college';
import React from 'react'; import React from 'react';
import {Table, Modal,Input} from 'antd'; import dealTimeDuration from '../../utils/dealTimeDuration';
import { PageControl } from "@/components";
import CourseService from "@/domains/course-domain/CourseService";
import User from '@/common/js/user'
import './WatchDataModal.less'; import './WatchDataModal.less';
import dealTimeDuration from "../../utils/dealTimeDuration";
const { Search } = Input; const { Search } = Input;
class WatchDataModal extends React.Component { class WatchDataModal extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
visible:true, visible: true,
dataSource:[], dataSource: [],
size:10, size: 10,
query: { query: {
current: 1, current: 1,
}, },
totalCount:0 totalCount: 0,
}; };
} }
componentDidMount() { componentDidMount() {
this.handleFetchDataList(); this.handleFetchDataList();
} }
onClose = () =>{ onClose = () => {
this.props.close(); this.props.close();
} };
// 获取观看视频数据列表 // 获取观看视频数据列表
handleFetchDataList = () => { handleFetchDataList = () => {
const {query,size,totalCount} = this.state const { query, size, totalCount } = this.state;
const { id } = this.props.data; const { id } = this.props.data;
const params ={ const params = {
...query, ...query,
size, size,
courseId:id, courseId: id,
storeId:User.getStoreId() storeId: User.getStoreId(),
} };
CourseService.videoWatchInfo(params).then((res) => { CourseService.videoWatchInfo(params).then((res) => {
const { result = {} } = res ; const { result = {} } = res;
const { records = [], total = 0 } = result; const { records = [], total = 0 } = result;
this.setState({ this.setState({
dataSource: records, dataSource: records,
totalCount: Number(total) totalCount: Number(total),
}); });
}); });
} };
handleChangNickname = (value)=>{ handleChangNickname = (value) => {
const isPhone = (value || '').match(/^\d+$/); const isPhone = (value || '').match(/^\d+$/);
const { query } = this.state; const { query } = this.state;
if(isPhone){ if (isPhone) {
query.phone = value; query.phone = value;
query.nickName = null; query.nickName = null;
}else{ } else {
query.nickName = value; query.nickName = value;
query.phone = null; query.phone = null;
} }
query.current = 1; query.current = 1;
this.setState({ this.setState({
query query,
}) });
} };
onShowSizeChange = (current, size) => { onShowSizeChange = (current, size) => {
if (current == size) { if (current == size) {
return return;
} }
this.setState({ this.setState(
size {
},()=>{this.handleFetchDataList()}) size,
},
() => {
this.handleFetchDataList();
} }
);
};
// 请求表头 // 请求表头
parseColumns = () => { parseColumns = () => {
...@@ -86,83 +92,101 @@ class WatchDataModal extends React.Component { ...@@ -86,83 +92,101 @@ class WatchDataModal extends React.Component {
{ {
title: '观看学员', title: '观看学员',
key: 'name', key: 'name',
dataIndex: 'name' dataIndex: 'name',
}, },
{ {
title: '手机号', title: '手机号',
key: 'phone', key: 'phone',
dataIndex: 'phone' dataIndex: 'phone',
}, },
{ {
title: '观看者类型', title: '观看者类型',
key: 'userRole', key: 'userRole',
dataIndex: 'userRole' dataIndex: 'userRole',
}, },
{ {
title: '首次观看时间', title: '首次观看时间',
key: 'firstWatch', key: 'firstWatch',
dataIndex: 'firstWatch', dataIndex: 'firstWatch',
render: (val) => { render: (val) => {
return formatDate('YYYY-MM-DD H:i', val) return formatDate('YYYY-MM-DD H:i', val);
} },
}, },
{ {
title: '观看时长', title: '观看时长',
key: 'watchDuration', key: 'watchDuration',
dataIndex: 'watchDuration', dataIndex: 'watchDuration',
render: (val) => { render: (val) => {
return <span>{val ? dealTimeDuration(val) : "00:00:00" }</span> return <span>{val ? dealTimeDuration(val) : '00:00:00'}</span>;
} },
} },
]; ];
return columns; return columns;
} };
render() { render() {
const { visible,size,dataSource,totalCount,query} = this.state; const { visible, size, dataSource, totalCount, query } = this.state;
return ( return (
<Modal <Modal
title="视频课观看数据" title='视频课观看数据'
visible={visible} visible={visible}
footer={null} footer={null}
onCancel={this.onClose} onCancel={this.onClose}
maskClosable={false} maskClosable={false}
className="watch-data-modal" className='watch-data-modal'
closable={true} closable={true}
width={800} width={800}
closeIcon={<span className="icon iconfont modal-close-icon">&#xe6ef;</span>} closeIcon={<span className='icon iconfont modal-close-icon'>&#xe6ef;</span>}>
> <div className='search-container'>
<div className="search-container"> <Search
<Search placeholder="搜索学员姓名/手机号" style={{ width: 200 }} onChange={(e) => { this.handleChangNickname(e.target.value)}} onSearch={ () => { this.handleFetchDataList()}} enterButton={<span className="icon iconfont">&#xe832;</span>}/> placeholder='搜索学员姓名/手机号'
style={{ width: 200 }}
onChange={(e) => {
this.handleChangNickname(e.target.value);
}}
onSearch={() => {
this.handleFetchDataList();
}}
enterButton={<span className='icon iconfont'>&#xe832;</span>}
/>
</div> </div>
<div> <div>
<Table <XMTable
rowKey={record => record.id} renderEmpty={{
image: college,
description: '暂无数据',
}}
rowKey={(record) => record.id}
dataSource={dataSource} dataSource={dataSource}
columns={this.parseColumns()} columns={this.parseColumns()}
pagination={false} pagination={false}
bordered bordered
/> />
{dataSource.length >0 && {dataSource.length > 0 && (
<div className="box-footer"> <div className='box-footer'>
<PageControl <PageControl
current={query.current - 1} current={query.current - 1}
pageSize={size} pageSize={size}
total={totalCount} total={totalCount}
size="small" size='small'
toPage={(page) => { toPage={(page) => {
const _query = {...query, current: page + 1}; const _query = { ...query, current: page + 1 };
this.setState({ this.setState(
query:_query {
},()=>{ this.handleFetchDataList()}) query: _query,
},
() => {
this.handleFetchDataList();
}
);
}} }}
onShowSizeChange={this.onShowSizeChange} onShowSizeChange={this.onShowSizeChange}
/> />
</div> </div>
} )}
</div> </div>
</Modal> </Modal>
) );
} }
} }
......
@import '../../core/variables.less'; @import '../../core/variables.less';
@top-height: 0px; @top-height: 0px;
@menu-bakg: #FFF; @menu-bakg: #fff;
@active-color: #2966FF; @active-color: #2966ff;
.left-container { .left-container {
position: absolute; position: absolute;
z-index: 2; z-index: 2;
...@@ -24,12 +24,12 @@ ...@@ -24,12 +24,12 @@
margin: 15px 0 15px 8px; margin: 15px 0 15px 8px;
} }
} }
.menu-type-icon{ .menu-type-icon {
margin: 8px 14px 0px 4px; margin: 8px 14px 0px 4px;
cursor: pointer; cursor: pointer;
.icon{ .icon {
font-size:14px; font-size: 14px;
color:#5E606A; color: #5e606a;
} }
} }
} }
...@@ -37,7 +37,10 @@ ...@@ -37,7 +37,10 @@
.ant-menu { .ant-menu {
padding-left: 0 !important; padding-left: 0 !important;
color: #333; color: #333;
background: #FFF !important; background: #fff !important;
.ant-menu-title-content {
margin-left: 0 !important;
}
} }
.left { .left {
-webkit-user-select: none; -webkit-user-select: none;
...@@ -59,78 +62,88 @@ ...@@ -59,78 +62,88 @@
display: none; display: none;
} }
.icon { .icon {
margin-right: 20px margin-right: 20px;
}
.icon-img-box {
// display: flex;
display: inline-block;
width: 40px;
height: 40px;
.icon-img {
margin-left: 12px;
} }
.icon-img{ margin-right: 0 !important;
width:18px; }
height:18px; .icon-img-title {
margin-right:6px; margin-left: 0 !important;
}
.icon-img {
width: 18px;
height: 18px;
} }
.listType { .listType {
width: 5px; width: 5px;
height: 5px; height: 5px;
background: #9A9DA7; background: #9a9da7;
border-radius: 50%; border-radius: 50%;
top: 18px; top: 18px;
left: 38px; left: 38px;
position: absolute; position: absolute;
} }
.ant-menu-item{ .ant-menu-item {
padding-left: 13px !important; padding-left: 0 !important;
padding-right: 0px; padding-right: 0px;
margin: 6px 8px; margin: 6px 8px;
width: calc(100% - 15px); width: calc(100% - 15px);
&:hover{ &:hover {
background: #F3F6FA; background: #f3f6fa;
border-radius: 2px; border-radius: 2px;
color:#333; color: #333;
} }
} }
.ant-menu-item-selected{ .ant-menu-item-selected {
background-color:@active-color; background-color: @active-color;
color:#FFF; color: #fff;
border-radius:2px; border-radius: 2px;
&:hover{ &:hover {
color:#FFF; color: #fff;
} }
} }
.ant-menu-submenu{ .ant-menu-submenu {
.ant-menu-submenu-title{ .ant-menu-submenu-title {
margin:6px 8px; margin: 6px 8px;
padding-left:13px !important; padding-left: 0 !important;
} }
.ant-menu-item{ .ant-menu-item {
padding-left:46px !important; padding-left: 46px !important;
} }
} }
.ant-menu-submenu-selected{ .ant-menu-submenu-selected {
color:@active-color; color: @active-color;
.ant-menu-item-selected{ .ant-menu-item-selected {
color:#FFF; color: #fff;
.listType { .listType {
background: @active-color; background: @active-color;
} }
} }
} }
.ant-menu-submenu-arrow{ .ant-menu-submenu-arrow {
right:22px; right: 22px;
color:#5E606A; color: #5e606a;
} }
} }
} }
&.left-container-vertical { &.left-container-vertical {
width: 56px; width: 56px;
.menu-type-icon{ .menu-type-icon {
margin:4px 0 0px 22px; margin: 4px 0 0px 22px;
} }
.left { .left {
.ant-menu-submenu-arrow{ .ant-menu-submenu-arrow {
display:none !important; display: none !important;
} }
} }
} }
...@@ -144,15 +157,17 @@ ...@@ -144,15 +157,17 @@
// } // }
} }
.ant-menu:not(.ant-menu-horizontal) .ant-menu-item-selected { .ant-menu:not(.ant-menu-horizontal) .ant-menu-item-selected {
background:@active-color !important; background: @active-color !important;
} }
.ant-menu.ant-menu-dark, .ant-menu-dark .ant-menu-sub, .ant-menu.ant-menu-dark .ant-menu-sub{ .ant-menu.ant-menu-dark,
.ant-menu-dark .ant-menu-sub,
.ant-menu.ant-menu-dark .ant-menu-sub {
background: @menu-bakg !important; background: @menu-bakg !important;
} }
.ant-menu-submenu-popup{ .ant-menu-submenu-popup {
left:67px !important; left: 67px !important;
} }
.ant-menu-submenu-popup>.ant-menu { .ant-menu-submenu-popup > .ant-menu {
background: @menu-bakg !important; background: @menu-bakg !important;
color: #333; color: #333;
width: 132px; width: 132px;
...@@ -160,18 +175,18 @@ ...@@ -160,18 +175,18 @@
li { li {
width: calc(100% - 16px); width: calc(100% - 16px);
padding-left: 20px; padding-left: 20px;
margin:12px 8px !important; margin: 12px 8px !important;
&:hover{ &:hover {
background: #F3F6FA; background: #f3f6fa;
border-radius: 2px; border-radius: 2px;
color:#333 !important; color: #333 !important;
} }
} }
.ant-menu-item-selected { .ant-menu-item-selected {
background: @active-color; background: @active-color;
color: #fff; color: #fff;
&:hover{ &:hover {
color: #fff !important; color: #fff !important;
} }
} }
......
import React, { Key, useContext, useEffect, useRef, useState, useMemo } from 'react'; import User from '@/common/js/user';
import { import StoreService from '@/domains/store-domain/storeService';
withRouter,
} from 'react-router-dom';
import { Menu } from 'antd'; import { Menu } from 'antd';
import { menuList } from '../../routes//config/menuList' import React, { Key, useContext, useEffect, useMemo, useState } from 'react';
import { XMContext } from '../../store/context'; import { withRouter } from 'react-router-dom';
import Service from "@/common/js/service";
import StoreService from "@/domains/store-domain/storeService";
import User from "@/common/js/user";
import _ from 'underscore'; import _ from 'underscore';
import "./Menu.less"; import { menuList } from '../../routes//config/menuList';
import { XMContext } from '../../store/context';
import './Menu.less';
const { SubMenu } = Menu; const { SubMenu } = Menu;
function Aside(props: any) { function Aside(props: any) {
const { menuType, handleMenuType } = props const { menuType, handleMenuType } = props;
const ctx: any = useContext(XMContext); const ctx: any = useContext(XMContext);
const [selectKey, setSelectKey] = useState(); const [selectKey, setSelectKey] = useState();
const [selectKeyParent, setSelectKeyParent] = useState();
const [openKeys, setOpenKeys] = useState(['']); const [openKeys, setOpenKeys] = useState(['']);
const [topLogoUrl, setTopLogoUrl] = useState("") const [topLogoUrl, setTopLogoUrl] = useState('');
const [collapsed, setCollapsed] = useState(false) const [collapsed, setCollapsed] = useState(false);
const rootSubmenuKeys = _.pluck(menuList, 'groupCode'); const rootSubmenuKeys = _.pluck(menuList, 'groupCode');
useEffect(() => { useEffect(() => {
...@@ -26,44 +24,46 @@ function Aside(props: any) { ...@@ -26,44 +24,46 @@ function Aside(props: any) {
menuList.map((item: any, index: any) => { menuList.map((item: any, index: any) => {
if (link.indexOf(item.link) !== -1) { if (link.indexOf(item.link) !== -1) {
setSelectKey(item.groupCode); setSelectKey(item.groupCode);
setOpenKeys([]) setSelectKeyParent(item.groupCode);
setOpenKeys([]);
} else if (item.children) { } else if (item.children) {
item.children.map((_item: any, _index: any) => { item.children.map((_item: any, _index: any) => {
if (link.indexOf(_item.link) !== -1) { if (link.indexOf(_item.link) !== -1) {
setSelectKeyParent(item.groupCode);
setSelectKey(_item.groupCode + index + _index); setSelectKey(_item.groupCode + index + _index);
} }
}) });
} }
return item; return item;
}) });
}, [props.location.pathname]) }, [props.location.pathname]);
useEffect(() => { useEffect(() => {
getTopLeftLogo() getTopLeftLogo();
}, []) }, []);
function getTopLeftLogo() { function getTopLeftLogo() {
if (User.getToken()) { if (User.getToken()) {
StoreService.getStoreDetail({ storeId: User.getStoreId() }) StoreService.getStoreDetail({ storeId: User.getStoreId() }).then((res) => {
.then(res => {
if (_.isEmpty(res.result.logo)) { if (_.isEmpty(res.result.logo)) {
setTopLogoUrl("https://image.xiaomaiketang.com/xm/fe4NCjr7XF.png") setTopLogoUrl('https://image.xiaomaiketang.com/xm/fe4NCjr7XF.png');
} else { } else {
setTopLogoUrl(res.result.logo) setTopLogoUrl(res.result.logo);
} }
});
})
} }
} }
function toggleMenu(item: any) { function toggleMenu(item: any, selectKey: any) {
window.RCHistory.push(item.link) console.log('item', item, selectKey);
setSelectKeyParent(selectKey);
window.RCHistory.push(item.link);
if (!menuType) { if (!menuType) {
setOpenKeys([]) setOpenKeys([]);
} }
} }
function onOpenChange(key: Key[]) { function onOpenChange(key: Key[]) {
if (typeof key === "string") { if (typeof key === 'string') {
if (openKeys.includes(key)) { if (openKeys.includes(key)) {
setOpenKeys([]); setOpenKeys([]);
} else { } else {
...@@ -74,9 +74,9 @@ function Aside(props: any) { ...@@ -74,9 +74,9 @@ function Aside(props: any) {
function onOpenChangeForHover(key: Key[]) { function onOpenChangeForHover(key: Key[]) {
if (menuType) { if (menuType) {
return return;
} }
if (typeof key === "string") { if (typeof key === 'string') {
if (openKeys.includes(key)) { if (openKeys.includes(key)) {
setOpenKeys([]); setOpenKeys([]);
} else { } else {
...@@ -87,94 +87,95 @@ function Aside(props: any) { ...@@ -87,94 +87,95 @@ function Aside(props: any) {
function handleMenu() { function handleMenu() {
handleMenuType(); handleMenuType();
setCollapsed(!collapsed) setCollapsed(!collapsed);
} }
const openKeysConstrol = useMemo(() => { const openKeysConstrol = useMemo(() => {
return { return {
[menuType ? 'openKeys' : 'defaultOpenKeys']: openKeys [menuType ? 'openKeys' : 'defaultOpenKeys']: openKeys,
}; };
}, [menuType, openKeys]) }, [menuType, openKeys]);
return ( return (
<div <div id='left-container' className={menuType ? 'left-container' : 'left-container left-container-vertical'}>
id="left-container" <div className='top-ctrl'>
className={ <div className='topLogo'>{menuType && <img src={topLogoUrl} alt='' className='img1'></img>}</div>
menuType <div className='menu-type-icon' onClick={handleMenu}>
? "left-container" {menuType ? <span className='icon iconfont'>&#xe83d;</span> : <span className='icon iconfont'>&#xe615;</span>}
: "left-container left-container-vertical"
}
>
<div className="top-ctrl">
<div className="topLogo">
{menuType && <img src={topLogoUrl} alt="" className="img1"></img>}
</div>
<div className="menu-type-icon" onClick={handleMenu}>
{menuType ? (
<span
className="icon iconfont"
>
&#xe83d;
</span>
) : (
<span
className="icon iconfont"
>
&#xe615;
</span>
)}
</div> </div>
</div> </div>
<div className="left"> <div className='left'>
<div className="nav"> <div className='nav'>
<Menu <Menu
{...openKeysConstrol} {...openKeysConstrol}
style={menuType ? { minHeight: "100%", background: '#0E1935' } : { minHeight: "100%", background: '#0E1935', width: "56px" }} style={menuType ? { minHeight: '100%', background: '#0E1935' } : { minHeight: '100%', background: '#0E1935', width: '56px' }}
selectedKeys={selectKey} selectedKeys={selectKey}
onOpenChange={onOpenChange} onOpenChange={onOpenChange}
inlineCollapsed={collapsed} inlineCollapsed={collapsed}
mode={menuType ? "inline" : "vertical"} mode={menuType ? 'inline' : 'vertical'}>
> {menuList.map((item: any, index: any) => {
{
menuList.map((item: any, index: any) => {
if (ctx.xmState.storeUserPermissionList.indexOf(item.groupCode) === -1) { if (ctx.xmState.storeUserPermissionList.indexOf(item.groupCode) === -1) {
return null; return null;
} }
if (item.children) { if (item.children) {
return <SubMenu return (
<SubMenu
key={item.groupCode} key={item.groupCode}
style={{ marginTop: 0 }} style={{ marginTop: 0 }}
icon={<img src={item.img} className="icon-img"></img>} icon={
title={menuType ? <span>{item.groupName}</span> : ""} !menuType && item.groupCode === selectKeyParent ? (
onTitleClick={() => onOpenChange(item.groupCode)} <div className='icon-img-box' style={{ backgroundColor: '#2966FF', width: '40px', height: '40px' }}>
> <img src={item.selectImg} className='icon-img' />
{ </div>
item.children.map((_item: any, _index: any) => { ) : (
<div className='icon-img-box' style={{ backgroundColor: '#fff', width: '40px', height: '40px', display: 'inline-block' }}>
<img src={item.img} className='icon-img' />
</div>
)
}
title={menuType ? <span className='icon-img-title'>{item.groupName}</span> : ''}
onTitleClick={() => onOpenChange(item.groupCode)}>
{item.children.map((_item: any, _index: any) => {
if (ctx.xmState.storeUserPermissionList.indexOf(_item.groupCode) === -1) { if (ctx.xmState.storeUserPermissionList.indexOf(_item.groupCode) === -1) {
return null; return null;
} }
return <Menu.Item onClick={() => { toggleMenu(_item) }} style={{ marginTop: 0 }} key={_item.groupCode + index + _index} > return (
<span className="name">{_item.groupName}</span> <Menu.Item
onClick={() => {
toggleMenu(_item, item.groupCode);
}}
style={{ marginTop: 0 }}
key={_item.groupCode + index + _index}>
<span className='name'>{_item.groupName}</span>
</Menu.Item> </Menu.Item>
);
}) })}
}
</SubMenu> </SubMenu>
);
} else { } else {
return <Menu.Item return (
onClick={() => { toggleMenu(item) }} <Menu.Item
onClick={() => {
toggleMenu(item, item.groupCode);
}}
key={item.groupCode} key={item.groupCode}
icon={<img src={selectKey === item.groupCode ? item.selectImg : item.img} className="icon-img"></img>} icon={
> !menuType && item.groupCode === selectKeyParent ? (
{menuType ? item.groupName : ""} <div className='icon-img-box' style={{ backgroundColor: '#2966FF' }}>
<img src={item.selectImg} className='icon-img' />
</div>
) : (
<div className='icon-img-box'>
<img src={selectKey === item.groupCode ? item.selectImg : item.img} className='icon-img' />
</div>
)
}>
{menuType ? <span className='icon-img-title'>{item.groupName}</span> : ''}
</Menu.Item> </Menu.Item>
);
} }
}) })}
}
</Menu> </Menu>
</div> </div>
</div> </div>
......
...@@ -8,142 +8,147 @@ ...@@ -8,142 +8,147 @@
*/ */
export const menuList: any = [ export const menuList: any = [
{ {
groupName: "中心首页", groupName: '中心首页',
groupCode: "CloudPage", groupCode: 'CloudPage',
icon: '&#xe8a7;', icon: '&#xe8a7;',
link: '/home', link: '/home',
img:'https://image.xiaomaiketang.com/xm/ni3BFJDT3a.png', img: 'https://image.xiaomaiketang.com/xm/ni3BFJDT3a.png',
selectImg:'https://image.xiaomaiketang.com/xm/GRDztTAWaM.png' selectImg: 'https://image.xiaomaiketang.com/xm/GRDztTAWaM.png',
}, },
{ {
groupName: "课程管理", groupName: '课程管理',
groupCode: "CloudCourse", groupCode: 'CloudCourse',
icon: '&#xe8a5;', icon: '&#xe8a5;',
img:'https://image.xiaomaiketang.com/xm/jBGrGjM7HQ.png', img: 'https://image.xiaomaiketang.com/xm/jBGrGjM7HQ.png',
selectImg: 'https://image.xiaomaiketang.com/xm/TTBGBpf3BJ.png',
children: [ children: [
{ {
groupName: "直播课", groupName: '直播课',
groupCode: "CourseLiveClass", groupCode: 'CourseLiveClass',
link: '/live-course' link: '/live-course',
}, },
{ {
groupName: "视频课", groupName: '视频课',
groupCode: "CourseVideoClass", groupCode: 'CourseVideoClass',
link: '/video-course' link: '/video-course',
}, },
{ {
groupName: "图文课", groupName: '图文课',
groupCode: "GraphicLesson", groupCode: 'GraphicLesson',
link: '/graphics-course' link: '/graphics-course',
}, },
{ {
groupName: "线下课", groupName: '线下课',
groupCode: "OfflineClass", groupCode: 'OfflineClass',
link: '/offline-course' link: '/offline-course',
}, },
] ],
}, },
{ {
groupName: "培训管理", groupName: '培训管理',
groupCode: "TrainManage", groupCode: 'TrainManage',
icon: '&#xe8a6;', icon: '&#xe8a6;',
img:'https://image.xiaomaiketang.com/xm/Yy6pZ6G6kS.png', img: 'https://image.xiaomaiketang.com/xm/Yy6pZ6G6kS.png',
selectImg: 'https://image.xiaomaiketang.com/xm/Z8G6NMQhaH.png',
children: [ children: [
{ {
groupName: "培训计划", groupName: '培训计划',
groupCode: "TrainPlan", groupCode: 'TrainPlan',
link: '/plan' link: '/plan',
} },
], ],
}, },
{ {
groupName: "助学工具", groupName: '助学工具',
groupCode: "AidTool", groupCode: 'AidTool',
icon: '&#xe8a9;', icon: '&#xe8a9;',
img:'https://image.xiaomaiketang.com/xm/xsma4hx3b3.png', img: 'https://image.xiaomaiketang.com/xm/xsma4hx3b3.png',
selectImg: 'https://image.xiaomaiketang.com/xm/3QZkdFMCS7.png',
children: [ children: [
{ {
groupName: "题库", groupName: '题库',
groupCode: "QuestionBank", groupCode: 'QuestionBank',
link: '/question-manage-index' link: '/question-manage-index',
}, },
{ {
groupName: "试卷", groupName: '试卷',
groupCode: "ExamPaper", groupCode: 'ExamPaper',
link: '/paper-manage-index' link: '/paper-manage-index',
}, },
{ {
groupName: "考试", groupName: '考试',
groupCode: "CloudExam", groupCode: 'CloudExam',
link: '/examination-manage-index' link: '/examination-manage-index',
}, },
] ],
}, },
{ {
groupName: "知识库", groupName: '知识库',
groupCode: "CloudKnowledge", groupCode: 'CloudKnowledge',
icon: '&#xe8a8;', icon: '&#xe8a8;',
link: '/knowledge-base', link: '/knowledge-base',
img:'https://image.xiaomaiketang.com/xm/8sbP5rGQWh.png', img: 'https://image.xiaomaiketang.com/xm/8sbP5rGQWh.png',
selectImg:'https://image.xiaomaiketang.com/xm/hJKCfibC22.png' selectImg: 'https://image.xiaomaiketang.com/xm/hJKCfibC22.png',
}, },
{ {
groupName: "资料云盘", groupName: '资料云盘',
groupCode: "CloudDisk", groupCode: 'CloudDisk',
icon: '&#xe8aa;', icon: '&#xe8aa;',
link: '/resource-disk', link: '/resource-disk',
img:'https://image.xiaomaiketang.com/xm/zGKbXJPzXx.png', img: 'https://image.xiaomaiketang.com/xm/zGKbXJPzXx.png',
selectImg:'https://image.xiaomaiketang.com/xm/5sN4MzjxYc.png', selectImg: 'https://image.xiaomaiketang.com/xm/5sN4MzjxYc.png',
}, },
{ {
groupName: "人员管理", groupName: '人员管理',
groupCode: "PersonManage", groupCode: 'PersonManage',
icon: '&#xe8a4;', icon: '&#xe8a4;',
img:'https://image.xiaomaiketang.com/xm/PRCnrt35y8.png', img: 'https://image.xiaomaiketang.com/xm/PRCnrt35y8.png',
selectImg: 'https://image.xiaomaiketang.com/xm/GhkwbdpwfK.png',
children: [ children: [
{ {
groupName: "员工管理", groupName: '员工管理',
groupCode: "ShopStaff", groupCode: 'ShopStaff',
link: '/college-employee' link: '/college-employee',
}, },
{ {
groupName: "学员管理", groupName: '学员管理',
groupCode: "ShopUser", groupCode: 'ShopUser',
link: '/college-user' link: '/college-user',
} },
] ],
}, },
{ {
groupName: "学院管理", groupName: '学院管理',
groupCode: "CloudShop", groupCode: 'CloudShop',
icon: '&#xe8a4;', icon: '&#xe8a4;',
img:'https://image.xiaomaiketang.com/xm/Q8i5RSMKNc.png', img: 'https://image.xiaomaiketang.com/xm/Q8i5RSMKNc.png',
selectImg: 'https://image.xiaomaiketang.com/xm/pFFF3Wcy3t.png',
children: [ children: [
{ {
groupName: "学院信息", groupName: '学院信息',
groupCode: "ShopInfo", groupCode: 'ShopInfo',
link: '/college-info' link: '/college-info',
}, },
{ {
groupName: "学院装修", groupName: '学院装修',
groupCode: "ShopDecoration", groupCode: 'ShopDecoration',
link: '/store-decoration' link: '/store-decoration',
}, },
{ {
groupName: "分类管理", groupName: '分类管理',
groupCode: "CourseCategory", groupCode: 'CourseCategory',
link: '/course-category-manage' link: '/course-category-manage',
}, },
{ {
groupName: "H5学院", groupName: 'H5学院',
groupCode: "ShopDecorationH5", groupCode: 'ShopDecorationH5',
link: '/store-decoration/h5' link: '/store-decoration/h5',
}, },
{ {
groupName: "网页端学院", groupName: '网页端学院',
groupCode: "ShopDecorationWeb", groupCode: 'ShopDecorationWeb',
link: '/store-decoration/web' link: '/store-decoration/web',
} },
] ],
}, },
] ];
\ No newline at end of file
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