Commit 8c1e94a8 by zhangleyuan

feat:处理学习数据页面

parent 2d3a9245
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: zhangleyuan * @Author: zhangleyuan
* @Date: 2021-02-21 16:08:38 * @Date: 2021-02-21 16:08:38
* @LastEditors: zhangleyuan * @LastEditors: zhangleyuan
* @LastEditTime: 2021-03-02 13:49:32 * @LastEditTime: 2021-03-03 14:07:46
* @Description: 描述一下 * @Description: 描述一下
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/ */
...@@ -23,3 +23,12 @@ export function getTrainingPlanDetail(params: object) { ...@@ -23,3 +23,12 @@ export function getTrainingPlanDetail(params: object) {
export function updateTrainingPlan(params: object) { export function updateTrainingPlan(params: object) {
return Service.Hades("public/hades/updateTrainingPlan", params); return Service.Hades("public/hades/updateTrainingPlan", params);
} }
export function deleteTrainingPlan(params: object) {
return Service.Hades("public/hades/deleteTrainingPlan", params);
}
export function getPlanUserRecordPage(params: object) {
return Service.Hades("public/hades/getPlanUserRecordPage", params);
}
export function getPlanCustomerRecordPage(params: object) {
return Service.Hades("public/hades/getPlanCustomerRecordPage", params);
}
...@@ -2,11 +2,11 @@ ...@@ -2,11 +2,11 @@
* @Author: zhangleyuan * @Author: zhangleyuan
* @Date: 2021-02-21 16:15:38 * @Date: 2021-02-21 16:15:38
* @LastEditors: zhangleyuan * @LastEditors: zhangleyuan
* @LastEditTime: 2021-03-02 13:50:18 * @LastEditTime: 2021-03-03 14:11:27
* @Description: 描述一下 * @Description: 描述一下
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/ */
import {getTrainingPlanPage,createTrainingPlan,updateStateTrainingPlan,getTrainingPlanDetail,updateTrainingPlan} from '@/data-source/plan/request-apis'; import {getTrainingPlanPage,createTrainingPlan,updateStateTrainingPlan,getTrainingPlanDetail,updateTrainingPlan,deleteTrainingPlan,getPlanUserRecordPage,getPlanCustomerRecordPage} from '@/data-source/plan/request-apis';
export default class PlanService { export default class PlanService {
// 获取员工列表 // 获取员工列表
static getTrainingPlanPage(params: any) { static getTrainingPlanPage(params: any) {
...@@ -24,4 +24,13 @@ export default class PlanService { ...@@ -24,4 +24,13 @@ export default class PlanService {
static updateTrainingPlan(params: any) { static updateTrainingPlan(params: any) {
return updateTrainingPlan(params); return updateTrainingPlan(params);
} }
static deleteTrainingPlan(params: any) {
return deleteTrainingPlan(params);
}
static getPlanUserRecordPage(params: any) {
return getPlanUserRecordPage(params);
}
static getPlanCustomerRecordPage(params: any) {
return getPlanCustomerRecordPage(params);
}
} }
\ No newline at end of file
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: zhangleyuan * @Author: zhangleyuan
* @Date: 2021-02-20 16:13:39 * @Date: 2021-02-20 16:13:39
* @LastEditors: zhangleyuan * @LastEditors: zhangleyuan
* @LastEditTime: 2021-03-02 20:11:09 * @LastEditTime: 2021-03-03 10:29:13
* @Description: 描述一下 * @Description: 描述一下
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/ */
...@@ -73,7 +73,7 @@ function AddPlan() { ...@@ -73,7 +73,7 @@ function AddPlan() {
}) })
setBasicData({ setBasicData({
planName, planName,
coverUrl, coverUrl:coverUrl || defaultCover,
coverId, coverId,
enableState, enableState,
selectOperatorList:operateIds || [], selectOperatorList:operateIds || [],
...@@ -135,7 +135,7 @@ function AddPlan() { ...@@ -135,7 +135,7 @@ function AddPlan() {
planName, planName,
scheduleMediaRequests, scheduleMediaRequests,
storeId:User.getStoreId(), storeId:User.getStoreId(),
trainingTaskList:taskList trainingTaskList:handleSubmitTaskData(taskList)
} }
if (type === 'add') { if (type === 'add') {
PlanService.createTrainingPlan(params).then((res) => { PlanService.createTrainingPlan(params).then((res) => {
...@@ -157,7 +157,21 @@ function AddPlan() { ...@@ -157,7 +157,21 @@ function AddPlan() {
}); });
} }
} }
function handleSubmitTaskData(taskData){
return taskData.map((item,index)=>{
let _item = {};
_item.taskId = item.taskId;
_item.taskName =item.taskName;
_item.courseList = item.courseList.map((childItem,index)=>{
let _childItem = {}
_childItem.courseId = childItem.courseId;
_childItem.courseName = childItem.courseName;
_childItem.courseType = childItem.courseType;
return _childItem;
});
return _item;
})
}
// 取消编辑并返回上一级路由 // 取消编辑并返回上一级路由
function handleGoBack (){ function handleGoBack (){
if (!_.isEqual(basicData, defaultBasicData) || !_.isEqual(taskList, defaultTaskList) if (!_.isEqual(basicData, defaultBasicData) || !_.isEqual(taskList, defaultTaskList)
......
...@@ -4,17 +4,60 @@ import { Tabs } from 'antd'; ...@@ -4,17 +4,60 @@ import { Tabs } from 'antd';
import Breadcrumbs from "@/components/Breadcrumbs"; import Breadcrumbs from "@/components/Breadcrumbs";
import EmployeeShareData from './components/EmployeeShareData'; import EmployeeShareData from './components/EmployeeShareData';
import UserLearningData from './components/UserLearningData'; import UserLearningData from './components/UserLearningData';
import PlanService from '@/domains/plan-domain/planService';
import Bus from '@/core/bus';
import './LearningData.less'; import './LearningData.less';
const defaultCover = 'https://image.xiaomaiketang.com/xm/YNfi45JwFA.png';
class LearningData extends React.Component { class LearningData extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
const id = getParameterByName("id");
this.state = { this.state = {
id,
planName:"",
coverUrl:defaultCover,
courseNum:0,
created:"",
cultureCustomerNum:0,
activeKey:"employeeShareData"
} }
} }
componentDidMount(){
this.getPlanDetail();
Bus.bind('watchDataView',() =>{this.setState({activeKey:"userLearningData"}) })
}
getPlanDetail = ()=>{
const { id } = this.state;
PlanService.getTrainingPlanDetail({
planId: id
}).then((res) => {
const {
planName,
courseMediaVOS,
courseNum,
created,
cultureCustomerNum
} = res.result;
let coverUrl;
courseMediaVOS.map((item) => {
if(item.contentType === "COVER"){
coverUrl = item.mediaUrl;
}
return item;
})
this.setState({
planName,
coverUrl: coverUrl || defaultCover,
courseNum,
created,
cultureCustomerNum:0
})
})
}
render() { render() {
const {planName,coverUrl,courseNum,created,cultureCustomerNum,activeKey} = this.state;
return ( return (
<div className="page plan-learn-data-list"> <div className="page plan-learn-data-list">
<Breadcrumbs <Breadcrumbs
...@@ -30,23 +73,23 @@ class LearningData extends React.Component { ...@@ -30,23 +73,23 @@ class LearningData extends React.Component {
</div> </div>
<div> <div>
<div className="plan-name"> <div className="plan-name">
六年级数学精品公开课快来参加二十个字展示 {planName}
</div> </div>
<div className="create-course"> <div className="create-course">
<span className="createUser">创建人:张老师</span> <span className="createUser">创建人:张老师</span>
<span className="split">|</span> <span className="split">|</span>
<span className="course-total">课程总数量:88</span> <span className="course-total">课程总数量:{courseNum}</span>
</div> </div>
<div className="create-time">创建时间:2020-01-01 09:00</div> <div className="create-time">创建时间:{formatDate('YYYY-MM-DD H:i', created)} </div>
</div> </div>
</div> </div>
<div className="join"> <div className="join">
<div className="number">1999</div> <div className="number">{cultureCustomerNum}</div>
<div className="text">参培人数</div> <div className="text">参培人数</div>
</div> </div>
</div> </div>
<div className="box"> <div className="box">
<Tabs defaultActiveKey="employeeShareData"> <Tabs activeKey={activeKey} onChange={(activeKey)=>{this.setState({activeKey})}}>
<Tabs.TabPane tab="员工分享数据" key="employeeShareData"> <Tabs.TabPane tab="员工分享数据" key="employeeShareData">
<EmployeeShareData/> <EmployeeShareData/>
</Tabs.TabPane> </Tabs.TabPane>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: zhangleyuan * @Author: zhangleyuan
* @Date: 2021-02-20 16:45:51 * @Date: 2021-02-20 16:45:51
* @LastEditors: zhangleyuan * @LastEditors: zhangleyuan
* @LastEditTime: 2021-03-02 13:47:09 * @LastEditTime: 2021-03-03 10:53:36
* @Description: 描述一下 * @Description: 描述一下
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/ */
...@@ -259,7 +259,7 @@ class BasicInfo extends React.Component{ ...@@ -259,7 +259,7 @@ class BasicInfo extends React.Component{
</Row> </Row>
<Row> <Row>
<Col span={8}> <Col span={8}>
<Radio value="Assign_Operate "> <Radio value="Assign_Operate">
指定运营师 指定运营师
<span className="playback__text">仅被选择的运营师有权限可见</span> <span className="playback__text">仅被选择的运营师有权限可见</span>
</Radio> </Radio>
......
...@@ -2,27 +2,33 @@ import React from 'react'; ...@@ -2,27 +2,33 @@ import React from 'react';
import { withRouter } from "react-router-dom"; import { withRouter } from "react-router-dom";
import {Table, Modal,Input,message} from 'antd'; import {Table, Modal,Input,message} from 'antd';
import { PageControl } from "@/components"; import { PageControl } from "@/components";
import PlanService from '@/domains/plan-domain/planService'
import User from '@/common/js/user';
import Bus from '@/core/bus';
import './EmployeeShareData.less'; import './EmployeeShareData.less';
const { Search } = Input; const { Search } = Input;
const UserRole = { const UserRole = {
StoreManager: { Store_Manager: {
name: "店铺管理员" text: "店铺管理员"
}, },
CloudManager: { Cloud_Manager: {
name:"管理员" text:"管理员"
}, },
CloudOperator: { Cloud_Operator: {
name:'运营师' text:'运营师'
}, },
CloudLecturer: { Cloud_Lecture: {
name:"讲师" text:"讲师"
}, },
}; };
class EmployeeShareData extends React.Component { class EmployeeShareData extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
const id = getParameterByName("id");
this.state = { this.state = {
id,
dataSource:[], dataSource:[],
size:10, size:10,
query: { query: {
...@@ -31,11 +37,77 @@ class EmployeeShareData extends React.Component { ...@@ -31,11 +37,77 @@ class EmployeeShareData extends React.Component {
totalCount:0, totalCount:0,
} }
} }
componentDidMount(){
this.handleFetchDataList();
}
handleFetchDataList = ()=>{ handleFetchDataList = ()=>{
const { query ,size,id} = this.state;
const params ={
...query,
size,
planId:id,
storeId:User.getStoreId(),
}
PlanService.getPlanUserRecordPage(params).then((res) => {
const { result = {} } = res ;
const { records = [], total = 0 } = result;
this.setState({
dataSource: records,
totalCount: Number(total)
});
});
}
onShowSizeChange = (current, size) => {
if (current == size) {
return
}
this.setState({
size
},()=>{this.handleFetchDataList()})
} }
// 请求表头 handleChangeTable = (pagination, filters, sorter)=> {
const { columnKey, order } = sorter;
const { query } = this.state;
let _columnKey;
let _order;
if (columnKey === 'learnNum' && order === 'ascend') { _columnKey="LEARN_NUM"; _order = 'SORT_ASC'; }
if (columnKey === 'learnNum' && order === 'descend') { _columnKey="LEARN_NUM"; _order = 'SORT_DESC'; }
if (columnKey === 'learnFinishNum' && order === 'ascend') { _columnKey="FINISH_NUM"; _order = 'SORT_ASC'; }
if (columnKey === 'learnFinishNum' && order === 'descend') { _columnKey="FINISH_NUM"; _order = 'SORT_DESC'; }
if (columnKey === 'learnNoFinishNum' && order === 'ascend') { _columnKey="NOT_NUM"; _order = 'SORT_ASC'; }
if (columnKey === 'learnNoFinishNum' && order === 'descend') { _columnKey="NOT_NUM"; _order = 'SORT_DESC'; }
const _query = {
...query,
sortMap:{}
};
_query.sortMap[_columnKey]=_order;
this.setState({
query:_query
},()=>this.handleFetchDataList())
}
handleChangNickname = (value)=>{
const isPhone = (value || '').match(/^\d+$/);
const { query } = this.state;
if(isPhone){
query.userPhone = value;
query.userName = null;
}else{
query.userName = value;
query.userPhone = null;
}
query.current = 1;
this.setState({
query
})
}
watchDataView = (record)=>{
Bus.trigger('watchDataView',record.storeUserId);
}
// 请求表头
parselumns = () => { parselumns = () => {
const columns = [ const columns = [
{ {
...@@ -57,7 +129,7 @@ class EmployeeShareData extends React.Component { ...@@ -57,7 +129,7 @@ class EmployeeShareData extends React.Component {
render: (val, record) => { render: (val, record) => {
return ( return (
<div> <div>
{UserRole[val].name} {UserRole[record.roleEnum].text}
</div> </div>
) )
} }
...@@ -78,7 +150,6 @@ class EmployeeShareData extends React.Component { ...@@ -78,7 +150,6 @@ class EmployeeShareData extends React.Component {
title: '最近分享成功时间', title: '最近分享成功时间',
key: 'recentlyForwardTime', key: 'recentlyForwardTime',
dataIndex: 'recentlyForwardTime', dataIndex: 'recentlyForwardTime',
sorter:true,
render: (val, record) => { render: (val, record) => {
return ( return (
<div> <div>
...@@ -132,7 +203,7 @@ class EmployeeShareData extends React.Component { ...@@ -132,7 +203,7 @@ class EmployeeShareData extends React.Component {
dataIndex: 'operate', dataIndex: 'operate',
render: (val, record) => { render: (val, record) => {
return ( return (
<span>数据详情</span> <span className="operate-item" onClick={()=>this.watchDataView(record)}>数据详情</span>
) )
} }
} }
...@@ -145,7 +216,7 @@ class EmployeeShareData extends React.Component { ...@@ -145,7 +216,7 @@ class EmployeeShareData extends React.Component {
return ( return (
<div className="employee-share-data"> <div className="employee-share-data">
<div className="search-container"> <div className="search-container">
<Search placeholder="搜索员工姓名手机号" style={{ width: 200 }} enterButton={<span className="icon iconfont">&#xe832;</span>}/> <Search placeholder="搜索员工姓名手机号" onChange={(e) => { this.handleChangNickname(e.target.value)}} onSearch={ () => { this.handleFetchDataList()}} style={{ width: 200 }} enterButton={<span className="icon iconfont">&#xe832;</span>}/>
</div> </div>
<div> <div>
<Table <Table
...@@ -153,6 +224,7 @@ class EmployeeShareData extends React.Component { ...@@ -153,6 +224,7 @@ class EmployeeShareData extends React.Component {
dataSource={dataSource} dataSource={dataSource}
columns={this.parselumns()} columns={this.parselumns()}
pagination={false} pagination={false}
onChange={this.handleChangeTable}
/> />
{dataSource.length >0 && {dataSource.length >0 &&
<div className="box-footer"> <div className="box-footer">
...@@ -166,6 +238,7 @@ class EmployeeShareData extends React.Component { ...@@ -166,6 +238,7 @@ class EmployeeShareData extends React.Component {
query:_query query:_query
},()=>{ this.handleFetchDataList()}) },()=>{ this.handleFetchDataList()})
}} }}
onShowSizeChange={this.onShowSizeChange}
/> />
</div> </div>
} }
......
...@@ -2,4 +2,9 @@ ...@@ -2,4 +2,9 @@
.search-container{ .search-container{
margin-bottom:12px; margin-bottom:12px;
} }
.operate-item{
font-size:14px;
color:#5289FA;
cursor: pointer;
}
} }
\ No newline at end of file
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: zhangleyuan * @Author: zhangleyuan
* @Date: 2021-02-20 16:46:46 * @Date: 2021-02-20 16:46:46
* @LastEditors: zhangleyuan * @LastEditors: zhangleyuan
* @LastEditTime: 2021-03-02 15:55:04 * @LastEditTime: 2021-03-03 14:18:59
* @Description: 描述一下 * @Description: 描述一下
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/ */
...@@ -56,7 +56,7 @@ function PlanList(props) { ...@@ -56,7 +56,7 @@ function PlanList(props) {
dataIndex: "status", dataIndex: "status",
render: (val, item, index) => { render: (val, item, index) => {
return ( return (
<Switch defaultChecked={item.enableState==="YES"? true:false} onChange={()=>changeEnableState(item)} disabled={(userRole === "CloudManager" || userRole === "StoreManager")?false:true}/> <Switch defaultChecked={item.enableState==="NO"? false:true} onChange={()=>changeEnableState(item)} disabled={(userRole === "CloudManager" || userRole === "StoreManager")?false:true}/>
) )
}, },
}, },
...@@ -147,7 +147,7 @@ function PlanList(props) { ...@@ -147,7 +147,7 @@ function PlanList(props) {
onClick={()=>toEditPlanPage(item)} onClick={()=>toEditPlanPage(item)}
>编辑</div> >编辑</div>
<div <div
className="operate__item" className="operate__item" onClick={()=>handleDelete(item)}
>删除</div> >删除</div>
</div> </div>
) )
...@@ -195,50 +195,72 @@ function PlanList(props) { ...@@ -195,50 +195,72 @@ function PlanList(props) {
setSharePlanModal(sharePlanModal) setSharePlanModal(sharePlanModal)
} }
//改变上架状态 //改变上架状态
function changeEnableState(record){ function changeEnableState(item){
let _enableState = record.enableState let _enableState = item.enableState
if(_enableState==='NO'){ if(_enableState==='NO'){
// _enableState = "YES"; _enableState = "YES";
const params={ item.enableState = "YES"
"planId": record.planId, }else{
"enableState":"YES" _enableState = "NO"
} item.enableState = "NO"
PlanService.updateStateTrainingPlan(params).then((res)=>{ }
if(res.success){ const params={
// if(_enableState === "YES"){ "planId": item.planId,
record.enableState = "YES"; "enableState":_enableState
message.success("已启用此计划"); }
// } PlanService.updateStateTrainingPlan(params).then((res)=>{
} if(res.success){
}) if(_enableState === "YES"){
}else{ message.success("已启用此计划");
// _enableState = "NO"; }else{
// item.enableState = "YES"; message.success("已禁用此计划");
return confirm({ }
title: "确定要禁用培训计划吗?", props.onChange();
content: "禁用后,培训计划不再支持新用户加入,已参与培训的用户可继续培训",
icon: (
<span className="icon iconfont default-confirm-icon">&#xe839; </span>
),
okText: "确定",
okType: "danger",
cancelText: "取消",
onOk: () => {
const params={
"planId": record.planId,
"enableState":"NO"
}
PlanService.updateStateTrainingPlan(params).then((res)=>{
if(res.success){
// if(_enableState === "NO"){
record.enableState = "NO";
message.success("已禁用此计划");
// }
}
})
},
});
} }
})
// let _enableState = record.enableState
// if(_enableState==='NO'){
// // _enableState = "YES";
// const params={
// "planId": record.planId,
// "enableState":"YES"
// }
// PlanService.updateStateTrainingPlan(params).then((res)=>{
// if(res.success){
// // if(_enableState === "YES"){
// record.enableState = "YES";
// message.success("已启用此计划");
// // }
// }
// })
// }else{
// // _enableState = "NO";
// // item.enableState = "YES";
// return confirm({
// title: "确定要禁用培训计划吗?",
// content: "禁用后,培训计划不再支持新用户加入,已参与培训的用户可继续培训",
// icon: (
// <span className="icon iconfont default-confirm-icon">&#xe839; </span>
// ),
// okText: "确定",
// okType: "danger",
// cancelText: "取消",
// onOk: () => {
// const params={
// "planId": record.planId,
// "enableState":"NO"
// }
// PlanService.updateStateTrainingPlan(params).then((res)=>{
// if(res.success){
// // if(_enableState === "NO"){
// record.enableState = "NO";
// message.success("已禁用此计划");
// // }
// }
// })
// },
// });
// }
} }
function toEditPlanPage(item){ function toEditPlanPage(item){
...@@ -251,6 +273,48 @@ function PlanList(props) { ...@@ -251,6 +273,48 @@ function PlanList(props) {
pathname: `/learning-data?id=${item.planId}`, pathname: `/learning-data?id=${item.planId}`,
}) })
} }
function handleDelete(record){
return confirm({
title: '你确定要删除吗?',
content: '删除后,此培训计划的用户将无法继续学习,所有学习数据将同步删除不可恢复',
icon: <span className="icon iconfont default-confirm-icon">&#xe839; </span>,
okText: '删除',
okType: 'danger',
cancelText: '取消',
width:440,
height:188,
onOk: () => {
if(record.enableState === "YES"){
Modal.warning({
title: '无法删除',
content: '培训计划启用中,无法直接删除',
});
}else{
deleteConfirm(record);
}
}
})
}
function deleteConfirm(item){
const params={
"planId": item.planId,
}
PlanService.deleteTrainingPlan(params).then((res)=>{
if(res.success){
message.success("删除成功");
props.onChange();
}
})
}
function onShowSizeChange(current, size){
if (current === size) {
return
}
let _query = props.query
_query.size = size;
props.onChange(_query)
}
return ( return (
<div className="plan-list"> <div className="plan-list">
<Table <Table
...@@ -270,6 +334,7 @@ function PlanList(props) { ...@@ -270,6 +334,7 @@ function PlanList(props) {
const _query = {...props.query, current: page + 1}; const _query = {...props.query, current: page + 1};
props.onChange(_query) props.onChange(_query)
}} }}
onShowSizeChange={onShowSizeChange}
/> />
</div> </div>
{sharePlanModal } {sharePlanModal }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: zhangleyuan * @Author: zhangleyuan
* @Date: 2021-02-20 16:45:51 * @Date: 2021-02-20 16:45:51
* @LastEditors: zhangleyuan * @LastEditors: zhangleyuan
* @LastEditTime: 2021-03-02 20:20:28 * @LastEditTime: 2021-03-03 10:06:14
* @Description: 描述一下 * @Description: 描述一下
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/ */
...@@ -47,20 +47,25 @@ class TrainingTask extends React.Component { ...@@ -47,20 +47,25 @@ class TrainingTask extends React.Component {
render: (val, record,index) => { render: (val, record,index) => {
return ( return (
<div> <div>
{record.type==='text'? {record.type==='input'?
<span>{val}</span> <Form>
: <Form.Item
<Form> validateTrigger={['onChange', 'onBlur']}
<Form.Item name={['taskName']}
validateTrigger={['onChange', 'onBlur']} rules={[
name={['taskName']} {
rules={[ required: true,
{ message: "请输入任务名称",
required: true, },
message: "请输入任务名称", ]}>
}, <Input defaultValue={record.taskName} style={{ width: 300 }} placeholder="请输入任务名称(20字以内)" maxLength={20} onChange={(e) => { this.handleRenameTaskName(e,record)}} onBlur={(e)=>{this.handleTaskNameBlur(e,record)}}/>
]}><Input defaultValue={record.taskName} style={{ width: 300 }} placeholder="请输入任务名称(20字以内)" maxLength={20} onChange={(e) => { this.handleRenameTaskName(e,record)}} onBlur={(e)=>{this.handleTaskNameBlur(e,record)}}/></Form.Item></Form>} </Form.Item>
</Form>
:
<span>{val}</span>
}
</div> </div>
) )
} }
......
import React from 'react'; import React from 'react';
import { withRouter } from "react-router-dom"; import { withRouter } from "react-router-dom";
import {Table, Modal,Input,message} from 'antd'; import {Table, Modal,Input,message,Tooltip} from 'antd';
import { PageControl } from "@/components"; import { PageControl } from "@/components";
import UserLearningDataFilter from './UserLearningDataFilter'; import UserLearningDataFilter from './UserLearningDataFilter';
import './EmployeeShareData.less'; import PlanService from '@/domains/plan-domain/planService';
import Item from 'antd/lib/list/Item'; import UserLearnDetailModal from "../modal/UserLearnDetailModal";
import User from '@/common/js/user';
import './UserLearningData.less';
const { Search } = Input; const { Search } = Input;
const LearnState = { const LearnState = {
UN_PLAY: { UN_PLAY: {
...@@ -22,20 +23,87 @@ const LearnState = { ...@@ -22,20 +23,87 @@ const LearnState = {
class UserLearningData extends React.Component { class UserLearningData extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
const id = getParameterByName("id");
this.state = { this.state = {
id,
dataSource:[], dataSource:[],
size:10, size:10,
query: { query: {
current: 1, current: 1,
}, },
totalCount:0, totalCount:0,
userLearnDetailModalSHow:false,
selectUserId:''
} }
} }
componentDidMount(){
this.handleFetchDataList();
}
handleFetchDataList = (_query)=>{
const { query ,size,id} = this.state;
const params ={
...query,
..._query,
size,
planId:id,
storeId:User.getStoreId(),
storeUserId:User.getStoreUserId(),
}
this.setState({ query: params });
PlanService.getPlanCustomerRecordPage(params).then((res) => {
const { result = {} } = res ;
const { records = [], total = 0 } = result;
this.setState({
dataSource: records,
totalCount: Number(total)
});
});
}
onShowSizeChange = (current, size) => {
if (current == size) {
return
}
this.setState({
size
},()=>{this.handleFetchDataList()})
}
handleChangeTable = (pagination, filters, sorter)=> {
const { columnKey, order } = sorter;
const { query } = this.state;
let _columnKey;
let _order;
if (columnKey === 'latelyLearnTime' && order === 'ascend') {_columnKey="LATE_LEARN_TIME"; _order = 'SORT_ASC'; }
handleFetchDataList = ()=>{ if (columnKey === 'latelyLearnTime' && order === 'descend') { _columnKey="LATE_LEARN_TIME"; _order = 'SORT_DESC';}
if (columnKey === 'startLearnTime' && order === 'ascend') { _columnKey="START_LEARN_TIME"; _order = 'SORT_ASC'; }
if (columnKey === 'startLearnTime' && order === 'descend') { _columnKey="START_LEARN_TIME"; _order = 'SORT_DESC'; }
if (columnKey === 'learnNum' && order === 'ascend') { _columnKey="LEARN_NUM"; _order = 'SORT_ASC'; }
if (columnKey === 'learnNum' && order === 'descend') { _columnKey="LEARN_NUM"; _order = 'SORT_DESC'; }
const _query = {
...query,
sortMap:{}
};
_query.sortMap[_columnKey]=_order;
this.setState({
query:_query
}, ()=>this.handleFetchDataList())
}
watchDetail = (record)=>{
this.setState({
userLearnDetailModalSHow:true,
storeCustomerId:record.storeCustomerId
})
}
closeUserLearnDetailModal = ()=>{
this.setState({
userLearnDetailModalSHow:false,
})
} }
// 请求表头 // 请求表头
parselumns = () => { parselumns = () => {
const columns = [ const columns = [
{ {
...@@ -52,8 +120,8 @@ class UserLearningData extends React.Component { ...@@ -52,8 +120,8 @@ class UserLearningData extends React.Component {
}, },
{ {
title: '学习状态', title: '学习状态',
key: 'roleEnum', key: 'learnState',
dataIndex: 'roleEnum', dataIndex: 'learnState',
render: (val, record) => { render: (val, record) => {
return ( return (
<div> <div>
...@@ -63,7 +131,10 @@ class UserLearningData extends React.Component { ...@@ -63,7 +131,10 @@ class UserLearningData extends React.Component {
} }
}, },
{ {
title: '负责人', title: <span>
<span>负责人</span>
<Tooltip title="用户加入学习时,培训计划的分享者"><i className="icon iconfont" style={{ marginLeft: '5px',cursor:'pointer',color:'#bfbfbf',fontSize:'14px'}}>&#xe61d;</i></Tooltip>
</span>,
key: 'userNameList', key: 'userNameList',
dataIndex: 'userNameList', dataIndex: 'userNameList',
render: (val, record) => { render: (val, record) => {
...@@ -103,7 +174,10 @@ class UserLearningData extends React.Component { ...@@ -103,7 +174,10 @@ class UserLearningData extends React.Component {
} }
}, },
{ {
title: '学习进度', title: <span>
<span>学习进度</span>
<Tooltip title="用户培训计划中达到“已完成”状态的课程数/总课程数"><i className="icon iconfont" style={{ marginLeft: '5px',cursor:'pointer',color:'#bfbfbf',fontSize:'14px'}}>&#xe61d;</i></Tooltip>
</span>,
key: 'learnNum', key: 'learnNum',
dataIndex: 'learnNum', dataIndex: 'learnNum',
sorter:true, sorter:true,
...@@ -123,10 +197,10 @@ class UserLearningData extends React.Component { ...@@ -123,10 +197,10 @@ class UserLearningData extends React.Component {
dataIndex: 'operate', dataIndex: 'operate',
render: (val, record) => { render: (val, record) => {
return ( return (
<div> <div className="operate-area">
<span>学习详情</span> <span className="operate-item" onClick={()=>this.watchDetail(record)}>学习详情</span>
<span>|</span> <span className="split">|</span>
<span>解绑</span> <span className="operate-item">解绑</span>
</div> </div>
) )
} }
...@@ -135,11 +209,11 @@ class UserLearningData extends React.Component { ...@@ -135,11 +209,11 @@ class UserLearningData extends React.Component {
return columns; return columns;
} }
render() { render() {
const { dataSource,query,size,totalCount} = this.state; const { dataSource,query,size,totalCount,userLearnDetailModalSHow,storeCustomerId} = this.state;
return ( return (
<div className="user-learning-data"> <div className="user-learning-data">
<div className="search-container"> <div className="search-container">
<UserLearningDataFilter/> <UserLearningDataFilter onChange={this.handleFetchDataList}/>
</div> </div>
<div> <div>
<Table <Table
...@@ -147,6 +221,8 @@ class UserLearningData extends React.Component { ...@@ -147,6 +221,8 @@ class UserLearningData extends React.Component {
dataSource={dataSource} dataSource={dataSource}
columns={this.parselumns()} columns={this.parselumns()}
pagination={false} pagination={false}
className="user-learning-table"
onChange={this.handleChangeTable}
/> />
{dataSource.length >0 && {dataSource.length >0 &&
<div className="box-footer"> <div className="box-footer">
...@@ -160,10 +236,15 @@ class UserLearningData extends React.Component { ...@@ -160,10 +236,15 @@ class UserLearningData extends React.Component {
query:_query query:_query
},()=>{ this.handleFetchDataList()}) },()=>{ this.handleFetchDataList()})
}} }}
onShowSizeChange={this.onShowSizeChange}
/> />
</div> </div>
} }
</div> </div>
{ userLearnDetailModalSHow &&
<UserLearnDetailModal storeCustomerId={storeCustomerId} visible={userLearnDetailModalSHow} onClose={this.closeUserLearnDetailModal}/>
}
</div> </div>
) )
} }
......
.user-learning-data{
.user-learning-table{
margin-top:4px;
}
.operate-area{
.operate-item{
font-size:14px;
color:#5289FA;
cursor: pointer;
}
.split{
margin:0 4px;
color: #BFBFBF;
}
}
}
\ No newline at end of file
...@@ -12,6 +12,7 @@ import { Row, Input, Select ,Tooltip} from 'antd'; ...@@ -12,6 +12,7 @@ import { Row, Input, Select ,Tooltip} from 'antd';
import RangePicker from "@/modules/common/DateRangePicker"; import RangePicker from "@/modules/common/DateRangePicker";
import moment from 'moment'; import moment from 'moment';
import StoreService from "@/domains/store-domain/storeService"; import StoreService from "@/domains/store-domain/storeService";
import Bus from '@/core/bus';
import './UserLearningDataFilter.less'; import './UserLearningDataFilter.less';
const { Search } = Input; const { Search } = Input;
const { Option } = Select; const { Option } = Select;
...@@ -36,11 +37,18 @@ function UserLearningDataFilter(props) { ...@@ -36,11 +37,18 @@ function UserLearningDataFilter(props) {
const [creatorQuery,setCreatorQuery] = useState(defaultCreatorQuery); const [creatorQuery,setCreatorQuery] = useState(defaultCreatorQuery);
const [creatorList,setCreatorList] = useState([]); const [creatorList,setCreatorList] = useState([]);
useEffect(() => {
Bus.bind('watchDataView',(value) => handleChangeCreatorQuery(value))
}, []);
useEffect(() => { useEffect(() => {
getCreatorList(); getCreatorList();
}, [creatorQuery]); }, [creatorQuery]);
function handleChangeCreatorQuery (value){
const _creatorQuery = {...creatorQuery};
_creatorQuery.operateId = value;
setCreatorQuery(_creatorQuery);
}
// 改变搜索条件 // 改变搜索条件
function handleChangeQuery(field, value){ function handleChangeQuery(field, value){
const _query ={ const _query ={
...@@ -108,33 +116,36 @@ function UserLearningDataFilter(props) { ...@@ -108,33 +116,36 @@ function UserLearningDataFilter(props) {
<Row> <Row>
<div className="search-condition"> <div className="search-condition">
<div className="search-condition__item"> <div className="search-condition__item">
<span className="search-name">用户:</span> <span className="label customer-label">用户:</span>
<Search <Search
value={query.customerName} value={query.customerName}
placeholder="搜索用户名称" placeholder="搜索用户名称"
onChange={(e) => { handleChangeQuery('customerName', e.target.value)}} onChange={(e) => { handleChangeQuery('customerName', e.target.value)}}
onSearch={ () => { props.onChange(query) } } onSearch={ () => { props.onChange(query) } }
style={{ width: "calc(100% - 70px)" }} style={{ width: "calc(100% - 70px)" }}
enterButton={<span className="icon iconfont">&#xe832;</span>}
/> />
</div> </div>
<div className="search-condition__item"> <div className="search-condition__item">
<span>负责人:</span> <span className="label lead-label">负责人:</span>
<Select <Select
id="leadSelect"
placeholder="请选择创建人" placeholder="请选择创建人"
style={{width:"calc(100% - 70px)"}} style={{width:"calc(100% - 70px)"}}
showSearch showSearch
allowClear allowClear
filterOption={(input, option) => option} filterOption={(input, option) => option}
suffixIcon={<span className="icon iconfont" style={{fontSize:'12px',color:'#BFBFBF'}}>&#xe835;</span>}
onPopupScroll={handleScrollCreatorList} onPopupScroll={handleScrollCreatorList}
value={query.operateId} value={query.operateId}
onChange={(value) => { onChange={(value) => {
handleChangeQuery('operateId', value) handleChangeQuery('operateId', value)
}} }}
onSearch={(value) => { onSearch={(value) => {
creatorQuery.nickName = value creatorQuery.nickName = value
setCreatorQuery(creatorQuery) setCreatorQuery(creatorQuery)
getCreatorList() getCreatorList();
} }
} }
onClear ={(value)=>{ onClear ={(value)=>{
...@@ -155,19 +166,19 @@ function UserLearningDataFilter(props) { ...@@ -155,19 +166,19 @@ function UserLearningDataFilter(props) {
</Select> </Select>
</div> </div>
<div className="search-condition__item"> <div className="search-condition__item">
<span className="search-date">最近学习日期:</span> <span className="label learn-date-label">最近学习日期:</span>
<RangePicker <RangePicker
id="course_date_picker" id="course_date_picker"
allowClear={false} allowClear={false}
value={ query.startTime ? [moment(query.startTime), moment(query.endTime)] : null } value={ query.startTime ? [moment(query.startTime), moment(query.endTime)] : null }
format={"YYYY-MM-DD"} format={"YYYY-MM-DD"}
onChange={(dates) => { handleChangeDates(dates) }} onChange={(dates) => { handleChangeDates(dates) }}
style={{ width: "calc(100% - 70px)" }} style={{ width: "calc(100% - 98px)" }}
/> />
</div> </div>
{ expandFilter && { expandFilter &&
<div className="search-condition__item"> <div className="search-condition__item">
<span className="shelf-status">学习状态:</span> <span className="label learn-status-label">学习状态:</span>
<Select <Select
style={{ width: "calc(100% - 70px)" }} style={{ width: "calc(100% - 70px)" }}
placeholder="请选择当前状态" placeholder="请选择当前状态"
......
...@@ -13,11 +13,21 @@ ...@@ -13,11 +13,21 @@
width: 30%; width: 30%;
margin-right: 3%; margin-right: 3%;
margin-bottom: 12px; margin-bottom: 12px;
.search-name{ .label{
font-size:14px;
color:#666;
vertical-align: middle; vertical-align: middle;
width:70px;
text-align:right;
display:inline-block; display:inline-block;
height:32px; }
line-height:32px; .learn-date-label{
width:98px;
text-align:right;
display:inline-block;
}
.ant-input-group-wrapper{
vertical-align: middle;
} }
} }
} }
......
...@@ -104,6 +104,7 @@ class SelectOperatorModal extends React.Component { ...@@ -104,6 +104,7 @@ class SelectOperatorModal extends React.Component {
closable={true} closable={true}
width={800} width={800}
onOk={() => this.props.onSelect(selectOperatorList) } onOk={() => this.props.onSelect(selectOperatorList) }
closeIcon={<span className="icon iconfont modal-close-icon">&#xe6ef;</span>}
> >
<div className="search-container"> <div className="search-container">
<Search placeholder="搜索运营师/手机号" style={{ width: 200 }} onChange={(e) => { this.handleChangNickname(e.target.value)}} onSearch={ () => { this.handleFetchDataList()}} /> <Search placeholder="搜索运营师/手机号" style={{ width: 200 }} onChange={(e) => { this.handleChangNickname(e.target.value)}} onSearch={ () => { this.handleFetchDataList()}} />
......
...@@ -100,7 +100,7 @@ class ShareLiveModal extends React.Component { ...@@ -100,7 +100,7 @@ class ShareLiveModal extends React.Component {
visible={true} visible={true}
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>}
className="share-live-modal" className="share-live-modal"
onCancel={this.props.close} onCancel={this.props.close}
> >
......
import React from 'react';
import {Table, Modal,Input} from 'antd';
import { PageControl } from "@/components";
import StoreService from "@/domains/store-domain/storeService";
import User from '@/common/js/user'
import './UserLearnDetailModal.less';
import _ from "underscore";
const { Search } = Input;
class UserLearnDetailModal extends React.Component {
constructor(props) {
super(props);
this.state = {
planDataSource:[
{
}
],
taskDataSource:[],
taskSize:10,
taskQuery: {
current: 1,
},
taskTotalCount:0,
courseDataSource:[],
};
}
componentDidMount() {
}
parsePlanColumns = () => {
const columns = [
{
title: '培训计划名称',
key: 'planInfo',
dataIndex: 'planInfo',
render: (val, record) => {
return (
<div>
<div>
<img src="https://image.xiaomaiketang.com/xm/YNfi45JwFA.png" style={{width:'100px',height:'50px'}}/>
</div>
<div>培训计划名称培训计划名称</div>
</div>
)
}
},
{
title: '学习进度',
key: 'learnFinishNum',
dataIndex: 'learnFinishNum',
render: (val, record) => {
return (
<div>
12%
</div>
)
}
}
];
return columns;
}
parseTaskColumns = () => {
const columns = [
{
title: '培训任务',
key: 'taskName',
dataIndex: 'taskName',
render: (val, record,index) => {
return (
<div>
{ size*10 + (index + 1) }.{val}
</div>
)
}
},
{
title: '学习进度',
key: 'learnFinishPercentage',
dataIndex: 'learnFinishPercentage',
render: (val, record) => {
return (
<div>
{val}%
</div>
)
}
}
];
return columns;
}
parseCoursecolumns = (parentIndex) => {
const columns = [
{
title: '课程',
key: 'courseName',
dataIndex: 'courseName',
render: (val, record,index) => {
return (
<div>
</div>
)
}
},
{
title: '学习进度',
key: 'learnState',
dataIndex: 'learnState',
render: (val, record) => {
return (
<div>
{val}%
</div>
)
}
}
];
return columns;
}
render() {
const { planDataSource,taskDataSource,taskQuery,taskTotalCount} = this.state;
const { visible } = this.props;
return (
<Modal
title="用户学习详情"
onCancel={this.props.onClose}
maskClosable={false}
visible={visible}
className="user-Learn-modal"
closable={true}
width={800}
closeIcon={<span className="icon iconfont modal-close-icon">&#xe6ef;</span>}
>
<div>
<span>
<span>用户:</span>
<span>巴扎黑</span>
</span>
<span>
<span>手机号</span>
<span>18226927277</span>
</span>
</div>
<div>
<Table
rowKey={record => record.id}
dataSource={planDataSource}
columns={this.parsePlanColumns()}
pagination={false}
bordered
/>
</div>
<div>
<Table
rowKey={record => record.id}
dataSource={taskDataSource}
columns={this.parseTaskColumns()}
pagination={false}
bordered
expandedRowRender={(record,index) => {
if (record.courseList.length !== 0 ){
return <div>
<Table
pagination={false}
dataSource={record.courseList}
columns={this.parseCoursecolumns(index)}
rowKey={record => record.id}
/>
</div>
}
}}
/>
</div>
</Modal>
)
}
}
export default UserLearnDetailModal;
\ No newline at end of file
...@@ -71,11 +71,10 @@ class SelectOperatorModal extends React.Component { ...@@ -71,11 +71,10 @@ class SelectOperatorModal extends React.Component {
return item return item
} }
}); });
console.log('_currentLiveCourseListData',_currentLiveCourseListData);
const params ={ const params ={
...liveQuery, ...liveQuery,
liveSize, liveSize,
excludeCourseIdList:_.pluck(_currentLiveCourseListData,'courseId') // excludeCourseIdList:_.pluck(_currentLiveCourseListData,'courseId')
} }
CourseService.getLiveCloudCourseBasePage(params).then((res) => { CourseService.getLiveCloudCourseBasePage(params).then((res) => {
...@@ -102,7 +101,7 @@ class SelectOperatorModal extends React.Component { ...@@ -102,7 +101,7 @@ class SelectOperatorModal extends React.Component {
const params ={ const params ={
...videoQuery, ...videoQuery,
videoSize, videoSize,
excludeCourseIdList:_.pluck(_currentVideoCourseListData,'courseId') // excludeCourseIdList:_.pluck(_currentVideoCourseListData,'courseId')
} }
CourseService.videoScheduleBasePage(params).then((res) => { CourseService.videoScheduleBasePage(params).then((res) => {
...@@ -118,21 +117,21 @@ class SelectOperatorModal extends React.Component { ...@@ -118,21 +117,21 @@ class SelectOperatorModal extends React.Component {
}); });
} }
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
}) // },()=>{this.handleFetchLiveDataList()})
} // }
onShowLiveSizeChange = (current, size) => { onShowLiveSizeChange = (current, size) => {
if (current == size) { if (current == size) {
return return
...@@ -312,6 +311,7 @@ class SelectOperatorModal extends React.Component { ...@@ -312,6 +311,7 @@ class SelectOperatorModal extends React.Component {
closable={true} closable={true}
width={800} width={800}
onOk={() => this.props.onSelect([...this.handleSelectVideo(selectVideo),...this.handleSelectLive(selectLive)]) } onOk={() => this.props.onSelect([...this.handleSelectVideo(selectVideo),...this.handleSelectLive(selectLive)]) }
closeIcon={<span className="icon iconfont modal-close-icon">&#xe6ef;</span>}
> >
<div> <div>
......
...@@ -60,7 +60,7 @@ class OperateArea extends React.Component { ...@@ -60,7 +60,7 @@ class OperateArea extends React.Component {
// 显示创建文件夹弹窗 // 显示创建文件夹弹窗
handleToggleCreateFolderModal = async () => { handleToggleCreateFolderModal = async () => {
const { instId } = window.currentUserInstInfo; const { instId } = window.currentUserInstInfo;
const ultimateRes = await axios.Business('public/inst/checkInstProduct', { const ultimateRes = await axios.Business('public/inst/checkInstProduct', {
instId: instId || LS.get("instId"), instId: instId || LS.get("instId"),
productCodeList: ['ULTIMATESELL', 'PIP_TO_ULTIMATE', 'HIGH_TO_ULTIMATE'] productCodeList: ['ULTIMATESELL', 'PIP_TO_ULTIMATE', 'HIGH_TO_ULTIMATE']
}); });
......
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