Commit 3a2890ee by yuananting

Merge branch 'feature/yuananting/20210801/task-center' of…

Merge branch 'feature/yuananting/20210801/task-center' of ssh://xmgit.ixm5.cn:10022/xiaomai-cloud-class/xiaomai-cloud-class-web into feature/yuananting/20210801/task-center
parents 6871c062 fe9144b4
......@@ -2,10 +2,14 @@ import React, { useEffect, useState } from 'react';
import { Empty, ConfigProvider, Table } from 'antd';
import Lottie from 'react-lottie';
import * as nodata from '../modules/lottie/nodata/data.json';
import college from '@/common/lottie/college';
function XMTable(props) {
const [empty, setEmpty] = useState(props.renderEmpty || {});
const [data, setData] = useState({});
const imgType = {
college
}
useEffect(() => {
setEmpty(props.renderEmpty || {})
......@@ -17,7 +21,7 @@ function XMTable(props) {
const defaultOptions = {
loop: true,
autoplay: true,
animationData: empty.image || nodata,
animationData: empty.image || imgType[props?.renderEmpty?.type] || nodata,
rendererSettings: {
preserveAspectRatio: 'xMidYMid slice'
}
......
......@@ -1699,3 +1699,22 @@ input:focus {
.ant-tag-blue{
background: transparent !important;
}
.xm_search_item {
padding-right: 24px;
width: 100%;
display: flex;
align-items: center;
flex-wrap: wrap;
box-sizing: border-box;
.label{
margin-right: 8px;
flex-shrink: 0;
// height: 36px;
// line-height: 36px;
}
.search{
flex: 1;
}
}
\ No newline at end of file
......@@ -22,7 +22,7 @@
z-index: 102;
overflow: auto;
margin: 0 16px;
min-height: auto;
.box {
&:first-child {
margin-bottom: 8px;
......
declare module 'jquery'
declare module 'cropper'
declare module 'ExamShareModal'
declare module 'college'
declare module '@/common/lottie/college'
// declare var this: any
\ No newline at end of file
......@@ -71,8 +71,10 @@ class FolderList extends React.Component {
handleSelect = (folder) => {
// 只有文件才有预览功能
if (folder.folderType === 'FOLDER') {
console.log(1)
this.handleSelectFolder(folder)
} else {
console.log(2)
this.handleScanFile(folder)
}
}
......
import React, { useEffect, useState } from 'react';
import { withRouter } from "react-router-dom";
import { Tabs } from 'antd';
import Service from '@/common/js/service';
import Breadcrumbs from "@/components/Breadcrumbs";
import DataInfo from './components/DataInfo'
import CourseTable from './components/CourseTable';
import ExamTable from './components/ExamTable';
import StudyTable from './components/StudyTable';
import './index.less'
const { TabPane } = Tabs;
export default function DataCenter(){
function DataCenter(props: any) {
const { match: { params: { planId } } } = props;
const [info, setInfo] = useState<any>({})
const [tabKey, setTabKey] = useState<any>('')
const tabList = [
{
name: '课程目录',
key: 'course',
compoment: CourseTable,
},
{
name: '学习详情',
key: 'study',
compoment: StudyTable,
},
{
name: '考试详情',
key: 'exam',
compoment: ExamTable,
},
]
useEffect(() => {
getInfo()
}, [])
function getInfo() {
Service.Hades('public/hades/getTrainingPlanDetail', { planId }).then((res: any) => {
res.result.trainingTaskList.map((item: any) => {
item.open = true
})
setInfo(res.result)
})
}
return <div className="page train-data-center">
<Breadcrumbs
navList="培训任务详情"
goBack={() => {
props.history.goBack();
}}
/>
<div className="content">
<DataInfo info={info} />
<Tabs defaultActiveKey={'study'} onChange={() => { }}>
{
tabList.map((item: any) => {
return <TabPane tab={item.name} key={item.key}>
{
<item.compoment info={info} />
}
</TabPane>
})
}
</Tabs>
</div>
return <div className="page">
eweew
</div>
}
export default withRouter(DataCenter)
import React, { useEffect, useState } from 'react';
import { withRouter } from "react-router-dom";
function DataInfo(props: any) {
return <div className="info_banner">
</div>
}
export default withRouter(DataInfo)
\ No newline at end of file
import React, { useEffect, useState } from 'react';
import { withRouter } from "react-router-dom";
import moment from 'moment';
import ENUM from '../../emun';
import './course.less'
function CourseTable(props: any) {
const IndexText = ['一', '二', '三', '四', '五', '六', '七', '八', '九', '十']
const [list, setList] = useState<any[]>([]);
useEffect(() => {
setList(props.info.trainingTaskList || [])
}, [props.info.trainingTaskList])
return <div className="courseTabContent">
<div className="tips">{`培训目的:${'djkhdsjksdhdsj'}`}</div>
<div className="coursecontent">
{
list?.map((item: any, index: number) => {
return <div className="task">
<div className="title" onClick={() => {
const _list = [...list];
_list[index].open = !_list[index].open;
setList(_list)
}}>
{
item.open ? <span className="icon iconfont open">&#xe614;</span> : <span className="icon iconfont">&#xe614;</span>
}
{
`${IndexText[index]}、 `
}
{item.taskName}
</div>
{
item.open && <div className="taskItemList">
{
item.courseList.map((_item: any, _index: number) => {
return <div className={_index == item.courseList.length - 1 ? "item noBorder" : "item"}>
<div className="name">
<span style={{ marginRight: 4 }}> {`${index + 1}.${_index + 1}`}</span>
{
_item.courseName
}
{
(_item.courseType == 'LIVE') && <span className='desc'>{ENUM.courseStateShow[_item.courseState].title}</span>
}
{
_item.courseType == 'VOICE' && <span className='desc'>{`(共${_item.courseChapterNum}节)`}</span>
}
</div>
</div>
})
}
</div>
}
</div>
})
}
</div>
<div className="expired">
<div className="title">失效课程</div>
<p className="desc">为了不影响学员学习,「未成功开课」的课程已从任务中移出,具体课程如下所示:</p>
<div className="list">
{
list.map((item: any) => {
return <div className="item">
<div className="text">
<span className="icon iconfont" style={{ color: 'rgba(255, 79, 79, 1)' ,marginRight:4}}>&#xe80b;</span>
<span style={{marginRight:24}}>未成功开课</span>
<span className='na'>阶段一</span>
<span className='na'>2.1 入门培训任务</span>
<span >张老师 </span>
<span>|</span>
<span>{moment().format('YYYY-MM-DD HH:mm')}</span>
</div>
<div className="ope">删除记录</div>
</div>
})
}
</div>
</div>
</div>
}
export default withRouter(CourseTable)
\ No newline at end of file
import React, { useEffect, useState } from 'react';
import { withRouter } from "react-router-dom";
import { Progress } from 'antd';
import ENUM from '../../emun'
const defaultCover = 'https://image.xiaomaiketang.com/xm/rEAetaTEh3.png';
function DataInfo(props: any) {
return <div className="infoBox">
<div className="left">
<div className="banner">
<img src={props.info.coverUrl || defaultCover} alt="" />
</div>
<div className="textBox">
<div className="nameBox">
<div className="name">{props.info.planName}</div>
<div className="status" style={{ color: ENUM.trainStatus[props.info.status || 'UN_START'].color, background: ENUM.trainStatus[props.info.status || 'UN_START'].background }}>{ENUM.trainStatus[props.info.status || 'UN_START'].text}</div>
</div>
<div className="info">
<span> {`创建人: 文小白 `}</span>
<span style={{ marginLeft: 24 }}> {`培训时间:2021-07-01 00:00 至 2021-08-17 00:00`}</span>
</div>
<div className="info">
<div className="item">{`任务数: 98`}</div>
<div className="item"><span className="icon iconfont" style={{color:'rgba(41, 102, 255, 1)'}}>&#xe617;</span>{`课程:98`}</div>
<div className="item"><span className="icon iconfont" style={{color:'rgba(255, 105, 0, 1)'}} >&#xe61c;</span>{`作业:4`}</div>
<div className="item"><span className="icon iconfont" style={{color:'rgba(255, 79, 79, 1)'}} >&#xe619;</span>{`考试:4`}</div>
</div>
</div>
</div>
<div className="right">
<div className="prog">
<Progress type="circle" width={85} percent={75} strokeWidth={10} format={percent => <div className='wcl'>{`${percent}% `} <div>完成率</div></div>} />
</div>
<div className="num">
<div className="item"> {`指派人数:${12}`}</div>
<div className="item">{`学习人数:${12}`}</div>
<div className="item">{`完成人数:${12}`}</div>
</div>
</div>
</div>
}
export default withRouter(DataInfo)
\ No newline at end of file
import React, { useEffect, useState } from 'react';
import { withRouter } from "react-router-dom";
function CourseTable(props: any) {
return <div className="info_banner">
</div>
}
export default withRouter(CourseTable)
\ No newline at end of file
import React, { useEffect, useState } from 'react';
import { withRouter } from "react-router-dom";
import { Row, Input, Select, Tooltip, Col } from 'antd';
import RangePicker from '@/modules/common/DateRangePicker';
import { PageControl, XMTable } from '@/components';
import ENUM from '../../emun';
import moment from 'moment';
const { Search } = Input;
const { Option } = Select;
declare var formatDate: any;
function StudyTable(props: any) {
const [query, setQuery] = useState<any>({ current: 1, size: 10 });
const [list,setList] = useState<any[]>([]);
const [total,setTotal] = useState<any>(0);
const columns = [
{
title: '学员',
key: 'storeCustomerName',
dataIndex: 'storeCustomerName',
render: (val: any, record: any) => {
return <div>{val}</div>;
},
},
{
title: '部门',
key: 'learnState2',
dataIndex: 'learnState2',
},
{
title: '岗位',
key: 'learnState1',
dataIndex: 'learnState1',
},
{
title: '学习状态',
key: 'learnState',
dataIndex: 'learnState',
render: (val: any, record: any) => {
return <div>{ENUM.LearnState[val].text}</div>;
},
},
{
title: '学习进度',
key: 'learnState',
dataIndex: 'learnState',
render: (val: any, record: any) => {
return <div>{ENUM.LearnState[val].text}</div>;
},
},
{
title: '最近学习时间',
key: 'latelyLearnTime',
dataIndex: 'latelyLearnTime',
sorter: true,
width: 240,
render: (val: any, record: any) => {
return `${formatDate('YYYY-MM-DD H:i', parseInt(record.latelyLearnTime))}`;
},
},
{
title: '开始学习时间',
key: 'startLearnTime',
dataIndex: 'startLearnTime',
width: 240,
sorter: true,
render: (val: any, record: any) => {
return <div>{formatDate('YYYY-MM-DD H:i', val)}</div>;
},
},
{
title: '操作',
key: 'operate',
dataIndex: 'operate',
render: (val: any, record: any) => {
return (
<div className='operate-area'>
<span className='operate-item' onClick={() => { }}>
查看数据
</span>
</div>
);
},
},
];
return <div className="study_Table">
<div className="filter">
<Row>
<Col span={7}>
<div className='xm_search_item'>
<span className='label'>学员:</span>
<div className="search">
<Search
value={query.customerName}
placeholder='搜索学员名称'
onChange={(e) => {
}}
onSearch={() => {
}}
enterButton={<span className='icon iconfont'>&#xe832;</span>}
/>
</div>
</div>
</Col>
<Col span={7}>
<div className='xm_search_item'>
<span className='label '>学习状态:</span>
<div className="search">
<Select
style={{ width: '100%' }}
placeholder='请选择当前状态'
allowClear={true}
value={query.learnState}
onChange={(value) => {
}}
suffixIcon={
<span className='icon iconfont' style={{ fontSize: '12px', color: '#BFBFBF' }}>
&#xe835;
</span>
}>
<Option value='UN_PLAY'>未开始</Option>
<Option value='UNDER_WAY'>进行中</Option>
<Option value='FINISH'>已完成</Option>
</Select>
</div>
</div>
</Col>
<Col span={7}>
<div className='xm_search_item'>
<span className='label'>最近学习日期:</span>
<div className="search">
<RangePicker
style={{ width: '100%' }}
id='course_date_picker'
allowClear={false}
value={query.startTime ? [moment(query.startTime), moment(query.endTime)] : null}
format={'YYYY-MM-DD'}
onChange={(dates: any) => {
}}
/>
</div>
</div>
</Col>
<Col offset={2} span={1} >
<Tooltip title='清空筛选'>
<span className='resetBtn iconfont icon' onClick={() => { }}>
&#xe61b;{' '}
</span>
</Tooltip>
</Col>
</Row>
</div>
<div style={{marginTop:12}}>
<XMTable
renderEmpty={{
type: 'college',
description: '暂无数据',
}}
rowKey={(record:any) => record.storeCustomerId}
dataSource={list}
columns={columns}
pagination={false}
className='user-learning-table'
onChange={()=>{}}
showSorterTooltip={false}
bordered
/>
{list.length > 0 && (
<div className='box-footer'>
<PageControl
current={query.current - 1}
pageSize={query.size}
total={total}
toPage={(page:any) => {
}}
/>
</div>
)}
</div>
</div>
}
export default withRouter(StudyTable)
\ No newline at end of file
.courseTabContent{
padding-bottom: 24px;
.tips{
height: 48px;
background: #F7F8F9;
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #666666;
line-height: 20px;
padding: 14px 16px;
}
.coursecontent{
margin-top: 16px;
margin-bottom: 16px;
.title{
padding: 14px 16px;
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #333333;
line-height: 20px;
background: #F7F8F9;
border-radius: 2px;
cursor: pointer;
.icon{
color: rgba(153, 153, 153, 1);
transform: scale(0.8);
display: inline-block;
transform-origin: 50% 50%;
margin-right: 4px;
&.open{
transform:rotate(180deg) scale(0.8);
}
}
}
.taskItemList{
margin-left: 64px;
.item{
padding: 16px 0px 16px 32px;
border-bottom: 1px dashed #E8E8E8;
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #333333;
line-height: 20px;
&.noBorder{
border:none;
}
.desc{
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #999999;
line-height: 20px;
margin-left: 8px;
}
}
}
}
.expired{
.title{
font-size: 16px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #333333;
line-height: 22px;
}
.desc{
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #999999;
line-height: 20px;
margin: 12px 0;
}
.list{
.item{
display: flex;
justify-content: space-between;
background: #F7F8F9;
border-radius: 2px;
padding: 16px;
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #999999;
line-height: 20px;
span{
margin-right: 12px;
}
.na{
color: #333333;
}
.ope{
color: rgba(41, 102, 255, 1);
cursor: pointer;
}
}
}
}
}
.study_Table{
}
\ No newline at end of file
.train-data-center{
.content{
margin: 0 16px;
}
.infoBox{
background: #FFFFFF;
box-shadow: 0px 10px 20px 0px rgba(0, 0, 0, 0.05);
border-radius: 2px;
display: flex;
height: 141px;
justify-content: space-between;
margin: 0 0px 16px;
.left{
display: flex;
.banner{
margin-right: 16px;
img{
height: 141px;
}
}
.textBox{
padding-top: 1px;
.nameBox{
margin-top: 12px;
margin-bottom: 34px;
display: flex;
.name{
font-size: 18px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #333333;
line-height: 25px;
}
.status{
width: 42px;
height: 20px;
font-size: 14px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #999999;
line-height: 20px;
text-align: center;
margin-left: 24px;
}
}
.info{
margin-bottom: 12px;
span,.item{
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #666666;
line-height: 20px;
display: inline-block;
}
.item{
margin-right: 24px;
}
}
}
}
.right{
display: flex;
margin-right: 32px;
.prog{
width: 85px;
margin-top: 27px;
margin-right: 24px;
.wcl{
font-size: 16px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #666666;
line-height: 22px;
text-align: center;
}
}
.num{
margin-top: 27px;
.item{
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #666666;
line-height: 20px;
margin-bottom: 12px;
}
}
}
}
}
\ No newline at end of file
const ENUM: any = {
trainStatus: {
UN_START: {
text: "未开始",
color: "rgba(255, 178, 0, 1)",
background: "rgba(255, 178, 0, 0.1)",
},
STARTING: {
text: "进行中",
color: "rgba(41, 102, 255, 1)",
background: "rgba(41, 102, 255, 0.1)",
},
FINISH: {
text: "已结束",
color: "rgba(153, 153, 153, 1)",
background: "rgba(153, 153, 153, 0.1)",
},
},
courseStateShow: {
UN_START: {
title: '待开播',
},
STARTING: {
title: '直播中',
},
FINISH: {
title: '回放',
},
EXPIRED: {
title: '未成功开课',
},
},
LearnState: {
UN_PLAY: {
text: '未开始',
},
UNDER_WAY: {
text: '进行中',
},
FINISH: {
text: '已完成',
},
}
}
export default ENUM
\ No newline at end of file
......@@ -53,7 +53,7 @@ function TrainTaskPage(props) {
<TrainFilter onChange={queryChange} />
<TrainList trainListData={trainListData} query={query} totalCount={totalCount} onChange={queryChange} />
</div>
<Route path={`${match.url}/data`} component={DataCenter} />
<Route path={`${match.url}/data/:planId`} component={DataCenter} />
</div>
);
}
......
......@@ -17,6 +17,7 @@ function TrainList(props) {
const {
query: { issueState, myAssist, current, size },
totalCount,
match
} = props;
function renderMoreOperate(item) {
......@@ -160,7 +161,9 @@ function TrainList(props) {
render: (val, record) => {
return (
<div className='operate'>
<div className='operate__item' onClick={() => toLearningDataPage(record)}>
<div className='operate__item' onClick={() => {
props.history.push(`${match.path}/data/${record.planId}`)
}}>
数据
</div>
<span className='split'> | </span>
......
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