Commit 8eb4c61c by yuananting

feat:学员学习进度详情接口联调

parent 8b780628
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: yuananting * @Author: yuananting
* @Date: 2021-08-06 17:35:35 * @Date: 2021-08-06 17:35:35
* @LastEditors: yuananting * @LastEditors: yuananting
* @LastEditTime: 2021-08-10 15:28:07 * @LastEditTime: 2021-08-12 16:03:58
* @Description: 任务中心接口 * @Description: 任务中心接口
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
...@@ -40,3 +40,7 @@ export function getTrainingTaskDetail(params: object) { ...@@ -40,3 +40,7 @@ export function getTrainingTaskDetail(params: object) {
export function updateTrainingTask(params: object) { export function updateTrainingTask(params: object) {
return Service.Hades('public/hades/updateTrainingTask', params); return Service.Hades('public/hades/updateTrainingTask', params);
} }
export function getTaskCustomerDetail(params: object) {
return Service.Hades('public/hades/getTaskCustomerDetail', params);
}
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: yuananting * @Author: yuananting
* @Date: 2021-08-06 17:32:41 * @Date: 2021-08-06 17:32:41
* @LastEditors: yuananting * @LastEditors: yuananting
* @LastEditTime: 2021-08-10 15:28:39 * @LastEditTime: 2021-08-12 16:04:42
* @Description: 任务中心-培训任务接口 * @Description: 任务中心-培训任务接口
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
...@@ -16,6 +16,7 @@ import { ...@@ -16,6 +16,7 @@ import {
deleteTrainingTask, deleteTrainingTask,
getTrainingTaskDetail, getTrainingTaskDetail,
updateTrainingTask, updateTrainingTask,
getTaskCustomerDetail,
} from '@/data-source/taskCenter/request-apis'; } from '@/data-source/taskCenter/request-apis';
export default class TaskCenterService { export default class TaskCenterService {
...@@ -58,4 +59,9 @@ export default class TaskCenterService { ...@@ -58,4 +59,9 @@ export default class TaskCenterService {
static updateTrainingTask(params: any) { static updateTrainingTask(params: any) {
return updateTrainingTask(params); return updateTrainingTask(params);
} }
// 获取单个任务单个学员的学习进度详情
static getTaskCustomerDetail(params: any) {
return getTaskCustomerDetail(params);
}
} }
/* /*
* @Author: yuananting * @Author: yuananting
* @Date: 2021-08-05 10:55:49 * @Date: 2021-08-05 10:55:49
* @LastEditors: wufan * @LastEditors: yuananting
* @LastEditTime: 2021-08-09 15:49:31 * @LastEditTime: 2021-08-12 19:23:56
* @Description: 个人学习详情 * @Description: 个人学习详情
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/ */
import React from 'react'; import React, { useEffect, useState } from 'react';
import { Progress, Space, Tabs } from 'antd'; import { Tabs } from 'antd';
import Breadcrumbs from '@/components/Breadcrumbs'; import Breadcrumbs from '@/components/Breadcrumbs';
import WholeData from './components/WholeData'; import WholeData from './components/WholeData';
import ENUM from '../enum'; import { withRouter } from 'react-router-dom';
import TestLinkTaskData from './components/TestLinkTaskData'; import TestLinkTaskData from './components/TestLinkTaskData';
import CustomerLearnBasicInfo from './components/CustomerLearnBasicInfo';
import User from '@/common/js/user';
import TaskCenterService from '@/domains/task-center-domain/TaskCenterService';
import './UserLearningData.less'; import './UserLearningData.less';
const { TabPane } = Tabs; const { TabPane } = Tabs;
function UserLearningData(props) { function UserLearningData(props) {
const taskId = props.taskId;
const storeCustomerId = props.match.params.storeCustomerId.replace(/\?.+/, '');
const tabList = [ const tabList = [
{ {
name: '全部', name: '全部',
...@@ -31,6 +36,23 @@ function UserLearningData(props) { ...@@ -31,6 +36,23 @@ function UserLearningData(props) {
compoment: TestLinkTaskData, // todo compoment: TestLinkTaskData, // todo
}, },
]; ];
const [detail, setDetail] = useState({});
useEffect(() => {
getTaskCustomerDetail();
}, []);
function getTaskCustomerDetail() {
const params = {
storeCustomerId,
storeId: User.getStoreId(),
taskId,
};
TaskCenterService.getTaskCustomerDetail(params).then((res) => {
const { result = {} } = res;
setDetail(result);
});
}
return ( return (
<div className='page user-learning-data'> <div className='page user-learning-data'>
...@@ -40,35 +62,14 @@ function UserLearningData(props) { ...@@ -40,35 +62,14 @@ function UserLearningData(props) {
props.history.goBack(); props.history.goBack();
}} }}
/> />
<div className='header'> <CustomerLearnBasicInfo detail={detail} />
<div className='train-title'>培训任务全新版本上线啦~🐹🐹</div>
<div className='data-info'>
<div className='user-name'>学员:{'文小小'}</div>
<div className='complete-progress'>
任务完成率:
<div style={{ width: 120 }}>
<Progress size={120} strokeColor='#2966FF' trailColor='#EAEAEA' percent={30} size='small' />
</div>
</div>
<Space size={24}>
<div>
<img src={ENUM.LearningContentIcon['COURSE']} />
课程:{'15/98'}
</div>
<div>
<img src={ENUM.LearningContentIcon['EXAM']} />
考试:{'15/98'}
</div>
</Space>
</div>
</div>
<div className='gap-line'></div> <div className='gap-line'></div>
<div className='content'> <div className='content'>
<Tabs defaultActiveKey={'whole'} onChange={() => {}}> <Tabs defaultActiveKey={'whole'} onChange={() => {}}>
{tabList.map((item) => { {tabList.map((item) => {
return ( return (
<TabPane tab={item.name} key={item.key}> <TabPane tab={item.name} key={item.key}>
{<item.compoment />} {<item.compoment detail={detail} />}
</TabPane> </TabPane>
); );
})} })}
...@@ -78,4 +79,4 @@ function UserLearningData(props) { ...@@ -78,4 +79,4 @@ function UserLearningData(props) {
); );
} }
export default UserLearningData; export default withRouter(UserLearningData);
/*
* @Author: yuananting
* @Date: 2021-08-12 18:08:59
* @LastEditors: yuananting
* @LastEditTime: 2021-08-12 18:17:19
* @Description: 描述一下咯
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import React from 'react';
import { Progress, Space } from 'antd';
import ENUM from '../../enum';
function CustomerLearnBasicInfo(props) {
return (
<div className='header'>
<div className='train-title'>{props.detail.taskName}</div>
<div className='data-info'>
<div className='user-name'>学员:{props.detail.storeCustomerName}</div>
<div className='complete-progress'>
任务完成率:
<div style={{ width: 120 }}>
<Progress size={120} strokeColor='#2966FF' trailColor='#EAEAEA' percent={props.detail.learnFinishPercentage} size='small' />
</div>
</div>
<Space size={24}>
<div>
<img src={ENUM.LearningContentIcon['COURSE']} />
课程:{props.detail.courseFinishNum || 0}/{props.detail.courseAllNum || 0}
</div>
<div>
<img src={ENUM.LearningContentIcon['EXAM']} />
考试:{props.detail.examFinishNum || 0}/{props.detail.examAllNum || 0}
</div>
</Space>
</div>
</div>
);
}
export default CustomerLearnBasicInfo;
...@@ -115,12 +115,16 @@ function StudyTable(props: any) { ...@@ -115,12 +115,16 @@ function StudyTable(props: any) {
dataIndex: 'operate', dataIndex: 'operate',
render: (val: any, record: any) => { render: (val: any, record: any) => {
return ( return (
<div className='operate-area'> <div className='operate-area'>
<span className='operate-item' style={{ color: 'rgba(41, 102, 255, 1)', cursor: 'pointer' }} onClick={() => { console.log(props.match); props.history.push(`${props.match.url}/user-learning-data`); }}> <span
查看数据 className='operate-item'
</span> style={{ color: 'rgba(41, 102, 255, 1)', cursor: 'pointer' }}
onClick={() => {
</div> props.history.push(`${props.match.url}/user-learning-data/${record.storeCustomerId}`);
}}>
查看数据
</span>
</div>
); );
}, },
}, },
...@@ -265,7 +269,7 @@ function StudyTable(props: any) { ...@@ -265,7 +269,7 @@ function StudyTable(props: any) {
</div> </div>
)} )}
</div> </div>
<Route path={`${props.match.url}/user-learning-data`} component={UserLearningData} /> <Route path={`${props.match.url}/user-learning-data/:storeCustomerId`} render={() => <UserLearningData taskId={props.taskId} />} />
</div> </div>
} }
......
...@@ -2,76 +2,20 @@ ...@@ -2,76 +2,20 @@
* @Author: yuananting * @Author: yuananting
* @Date: 2021-08-05 11:26:25 * @Date: 2021-08-05 11:26:25
* @LastEditors: yuananting * @LastEditors: yuananting
* @LastEditTime: 2021-08-05 16:20:07 * @LastEditTime: 2021-08-12 21:12:08
* @Description: 个人学习详情-全部tab页 * @Description: 个人学习详情-全部tab页
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/ */
import React from 'react'; import React, { useState, useEffect } from 'react';
import { Collapse, Progress } from 'antd'; import { Collapse, Progress } from 'antd';
import './WholeData.less'; import './WholeData.less';
import ENUM from '../../enum'; import ENUM from '../../enum';
const { Panel } = Collapse; const { Panel } = Collapse;
function WholeData() { function WholeData(props) {
const SortConvert = ['一', '二', '三', '四', '五', '六', '七', '八', '九', '十']; const SortConvert = ['一', '二', '三', '四', '五', '六', '七', '八', '九', '十'];
const stageList = [
{
stageName: '新手阶段',
finishedCount: 1,
contentSum: 4,
contentList: [
{
contentType: 'LIVE',
contentName: '入门培训任务',
courseState: 'UN_START',
percent: 75,
},
{
contentType: 'LIVE',
contentName: '普通培训任务',
courseState: 'FINISH',
percent: 0,
},
{
contentType: 'VOICE',
contentName: '困难培训任务',
courseChapterNum: 4,
percent: 100,
},
{
contentType: 'PICTURE',
contentName: '困难培训任务',
percent: 23,
},
],
},
{
stageName: '老手阶段',
finishedCount: 3,
contentSum: 5,
contentList: [
{
contentType: 'LIVE',
contentName: '入门培训任务',
courseState: 'UN_START',
percent: 15,
},
{
contentType: 'EXAM',
contentName: '入门考试',
percent: 70,
},
{
contentType: 'EXAM',
contentName: '入门二段考试',
percent: 100,
},
],
},
];
const courseStateShow = { const courseStateShow = {
UN_START: { UN_START: {
title: '待开播', title: '待开播',
...@@ -87,6 +31,12 @@ function WholeData() { ...@@ -87,6 +31,12 @@ function WholeData() {
}, },
}; };
const [stageCustomerList, setStageCustomerList] = useState([]);
useEffect(() => {
setStageCustomerList(props.detail.stageCustomerVOList);
}, [props]);
// 渲染阶段信息 // 渲染阶段信息
function renderStageInfo(item, index) { function renderStageInfo(item, index) {
return ( return (
...@@ -95,7 +45,7 @@ function WholeData() { ...@@ -95,7 +45,7 @@ function WholeData() {
{SortConvert[index]}{item.stageName} {SortConvert[index]}{item.stageName}
</span> </span>
<span className='extra-info'> <span className='extra-info'>
{item.finishedCount}/{item.contentSum} {item.learnFinishNum}/{item.learnAllNum}
</span> </span>
</div> </div>
); );
...@@ -104,7 +54,7 @@ function WholeData() { ...@@ -104,7 +54,7 @@ function WholeData() {
// 渲染学习内容信息 // 渲染学习内容信息
function renderContentInfo(contentItem, contentIndex, index) { function renderContentInfo(contentItem, contentIndex, index) {
const { contentName, contentType, courseChapterNum, courseState, percent } = contentItem; const { contentName, contentType, courseChapterNum, courseState, learnFinishPercentage } = contentItem;
return ( return (
<div className='content-info__item'> <div className='content-info__item'>
<div className='basic-info'> <div className='basic-info'>
...@@ -116,7 +66,7 @@ function WholeData() { ...@@ -116,7 +66,7 @@ function WholeData() {
{contentType === 'VOICE' && <span className='extra-info'>(共{courseChapterNum || 1}小节)</span>} {contentType === 'VOICE' && <span className='extra-info'>(共{courseChapterNum || 1}小节)</span>}
</div> </div>
<div className='percent-info'> <div className='percent-info'>
{percent === 100 ? ( {learnFinishPercentage === 100 ? (
<span className='icon iconfont'>&#xe621;</span> <span className='icon iconfont'>&#xe621;</span>
) : ( ) : (
<Progress <Progress
...@@ -128,10 +78,10 @@ function WholeData() { ...@@ -128,10 +78,10 @@ function WholeData() {
'0%': '#38B7F3', '0%': '#38B7F3',
'100%': '#1A80E2', '100%': '#1A80E2',
}} }}
percent={percent} percent={learnFinishPercentage}
/> />
)} )}
<span className='text'>{percent === 100 ? '已完成' : `${percent}%`}</span> <span className='text'>{learnFinishPercentage === 100 ? '已完成' : `${learnFinishPercentage}%`}</span>
</div> </div>
</div> </div>
); );
...@@ -140,15 +90,16 @@ function WholeData() { ...@@ -140,15 +90,16 @@ function WholeData() {
return ( return (
<div className='whole-data-container'> <div className='whole-data-container'>
<Collapse ghost> <Collapse ghost>
{stageList.map((item, index) => { {stageCustomerList?.length > 0 &&
return ( stageCustomerList.map((item, index) => {
<Panel header={renderStageInfo(item, index)} key={index}> return (
{item.contentList.map((contentItem, contentIndex) => { <Panel header={renderStageInfo(item, index)} key={index}>
{/* {item.courseVOList.map((contentItem, contentIndex) => {
return renderContentInfo(contentItem, contentIndex, index); return renderContentInfo(contentItem, contentIndex, index);
})} })} */}
</Panel> </Panel>
); );
})} })}
</Collapse> </Collapse>
</div> </div>
); );
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: yuananting * @Author: yuananting
* @Date: 2021-08-05 17:09:36 * @Date: 2021-08-05 17:09:36
* @LastEditors: yuananting * @LastEditors: yuananting
* @LastEditTime: 2021-08-12 14:32:20 * @LastEditTime: 2021-08-12 19:37:35
* @Description: 新建培训任务-选择指派对象 * @Description: 新建培训任务-选择指派对象
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
...@@ -61,7 +61,7 @@ function ChooseAssignorModal(props) { ...@@ -61,7 +61,7 @@ function ChooseAssignorModal(props) {
function handleStructureData(dataArray) { function handleStructureData(dataArray) {
const _dataArray = dataArray.map((item, index) => { const _dataArray = dataArray.map((item, index) => {
item.title = ''; item.title = '';
item.checkedId = [0, 1].includes(item.depLevel) ? item.id : item.userId; item.checkedId = [0, 1].includes(item.depLevel) ? item.id : item.storeCustomerId;
item.key = item.checkedId; item.key = item.checkedId;
item.children = []; item.children = [];
if (activeKey !== 'departMentTab' && item.depLevel === 0) { if (activeKey !== 'departMentTab' && item.depLevel === 0) {
...@@ -304,15 +304,15 @@ function ChooseAssignorModal(props) { ...@@ -304,15 +304,15 @@ function ChooseAssignorModal(props) {
<div className='node-title-div'> <div className='node-title-div'>
{[0, 1].includes(nodeData.depLevel) ? ( {[0, 1].includes(nodeData.depLevel) ? (
<div> <div>
<span className='icon iconfont item-icon'>&#xe604;</span> <span className='icon iconfont title-icon'>&#xe604;</span>
<span className='item-name'> <span className='title-name'>
<WWOpenDataCom type='departmentName' openid={nodeData.name} /> <WWOpenDataCom type='departmentName' openid={nodeData.name} />
</span> </span>
</div> </div>
) : ( ) : (
<div> <div>
<span className='icon iconfont item-icon'>&#xe603;</span> <span className='icon iconfont title-icon'>&#xe603;</span>
<span> <span className='title-name'>
<WWOpenDataCom type='userName' openid={nodeData.userName} /> <WWOpenDataCom type='userName' openid={nodeData.userName} />
</span> </span>
</div> </div>
...@@ -348,7 +348,7 @@ function ChooseAssignorModal(props) { ...@@ -348,7 +348,7 @@ function ChooseAssignorModal(props) {
) : ( ) : (
<div> <div>
<span className='icon iconfont title-icon'>&#xe604;</span> <span className='icon iconfont title-icon'>&#xe604;</span>
<Tooltip title={<WWOpenDataCom type='departmentName' openid={item.userName} />}> <Tooltip title={<WWOpenDataCom type='departmentName' openid={item.name} />}>
<span className='title-name'> <span className='title-name'>
<WWOpenDataCom type='departmentName' openid={item.name} /> <WWOpenDataCom type='departmentName' openid={item.name} />
</span> </span>
......
...@@ -27,11 +27,11 @@ ...@@ -27,11 +27,11 @@
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
white-space: nowrap; white-space: nowrap;
.item-icon { .title-icon {
margin-right: 6px; margin-right: 6px;
color: #999999; color: #999999;
} }
.item-name { .title-name {
position: absolute; position: absolute;
overflow: hidden; overflow: hidden;
white-space: nowrap; white-space: nowrap;
......
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