Commit eb0afa1e by chenshu

Merge branch 'feature/zhangleyuan/20200220/training-program' into feature/chenshu/graphics

parents 94f36a3e 84ed76f5
......@@ -68,7 +68,6 @@
"mini-css-extract-plugin": "0.9.0",
"moment": "^2.27.0",
"optimize-css-assets-webpack-plugin": "5.0.3",
"photoclip": "^3.4.8",
"pnp-webpack-plugin": "1.6.4",
"postcss-flexbugs-fixes": "4.1.0",
"postcss-loader": "3.0.0",
......
......@@ -290,7 +290,6 @@ class ChooseMembersModal extends React.Component {
onSearch={this.handleSearch}
onChange={this.handleChangeSearchKey}
className='search search-input'
enterButton={<span className="icon iconfont">&#xe832;</span>}
/>
<div className='container-left-body-table'>
......
......@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
import { Modal, Button } from 'antd';
import Service from '@/common/js/service';
import User from '@/common/js/user';
import PhotoClip from 'photoclip'
// import PhotoClip from 'photoclip'
let cutFlag = false;
class ImgCutModalNew extends React.Component {
......
......@@ -131,6 +131,7 @@
.ant-input {
font-size: 14px !important;
border-color: #d9d9d9;
}
.ant-input[disabled] {
......@@ -616,8 +617,17 @@ mr0 {
.ant-table-thead > tr > th{
font-weight:normal !important;
}
td.ant-table-column-sort{
background: none;
}
.ant-modal-content .ant-table-thead > tr > th{
padding:9px 24px;
}
.ant-modal-content tr > td{
padding:14px 24px !important;
}
//弹框里的table样式的处理
//按钮的样式的公共处理
......@@ -784,4 +794,6 @@ mr0 {
.ant-table-column-sorter {
margin-left: 2px!important;
}
.ant-table-column-sorter-full{
margin-top:-0.32rem !important;
}
......@@ -37,7 +37,10 @@
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>小麦企培</title>
<script type="text/javascript" src="https://image.xiaomaiketang.com/xm/iscroll-zoom-min.js"></script>
<script type="text/javascript" src="https://image.xiaomaiketang.com/xm/hammer.min.js"></script>
<script type="text/javascript" src="https://image.xiaomaiketang.com/xm/lrz.all.bundle.js"></script>
<script type="text/javascript" src="https://image.xiaomaiketang.com/xm/PhotoClip.js"></script>
<script type="text/javascript" charset="utf-8" src="//g.alicdn.com/sd/ncpc/nc.js?t=2015052012"></script>
</head>
<body>
......
......@@ -2,7 +2,7 @@
* @Author: 吴文洁
* @Date: 2020-08-24 12:20:57
* @LastEditors: zhangleyuan
* @LastEditTime: 2021-03-02 15:16:11
* @LastEditTime: 2021-03-11 15:28:14
* @Description:
* @Copyright: 杭州杰竞科技有限公司 版权所有
-->
......@@ -37,7 +37,10 @@
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>小麦企培</title>
<script type="text/javascript" src="https://image.xiaomaiketang.com/xm/iscroll-zoom-min.js"></script>
<script type="text/javascript" src="https://image.xiaomaiketang.com/xm/hammer.min.js"></script>
<script type="text/javascript" src="https://image.xiaomaiketang.com/xm/lrz.all.bundle.js"></script>
<script type="text/javascript" src="https://image.xiaomaiketang.com/xm/PhotoClip.js"></script>
<script type="text/javascript" charset="utf-8" src="//g.alicdn.com/sd/ncpc/nc.js?t=2015052012"></script>
</head>
<body>
......
......@@ -237,17 +237,6 @@ handleChangeBasicInfo = (field, value) => {
assistantStoreUserId:type==='assistantType'?_.pluck(optionValue, "key"):assistantStoreUserId,
}
});
// 批量开始时间改变,结束时间自动同步一致
// if (field === 'startTime') {
// this.setState({
// addLiveClassInfo: {
// ...this.state.addLiveClassInfo,
// [field]: _value,
// endTime: _value,
// }
// });
// }
}
// 修改简介
......@@ -346,7 +335,9 @@ handleChangeBasicInfo = (field, value) => {
CourseService.createLiveCloudCourse(params).then((res) => {
if (res.success){
message.success("新建成功");
window.RCHistory.goBack();
window.RCHistory.push({
pathname: `/live-course`,
});
}
});
......@@ -359,7 +350,9 @@ handleChangeBasicInfo = (field, value) => {
CourseService.updateLiveCloudCourse(params).then((res) => {
if (res.success){
message.success("更新成功");
window.RCHistory.goBack();
window.RCHistory.push({
pathname: `/live-course`,
});
}
});
}
......@@ -493,11 +486,15 @@ handleChangeBasicInfo = (field, value) => {
cancelText: '留在本页',
icon: <span className="icon iconfont default-confirm-icon">&#xe6f4;</span>,
onOk: () => {
window.RCHistory.goBack();
window.RCHistory.push({
pathname: `/live-course`,
});
}
})
} else {
window.RCHistory.goBack();
window.RCHistory.push({
pathname: `/live-course`,
});
}
}
......
......@@ -13,7 +13,7 @@ import { ImgCutModalNew } from '@/components';
import StoreService from "@/domains/store-domain/storeService";
import SelectPrepareFileModal from '@/modules/prepare-lesson/modal/SelectPrepareFileModal';
import Upload from '@/core/upload';
import PhotoClip from 'photoclip'
// import PhotoClip from 'photoclip'
import './AddLiveBasic.less';
......
......@@ -292,15 +292,18 @@ class LiveCourseList extends React.Component {
dataIndex: "planList",
render: (val, record) => {
return (
<span>
<div className="related-task">
{ record.relatedPlanList ?
record.relatedPlanList.map((item,index)=>{
return <span>{item.planName} { (index < record.relatedPlanList.length-1)&&(<span></span>)} </span>
})
<Tooltip title={this.handlePlanName(record.relatedPlanList)} placement="top" arrowPointAtCenter>
{ record.relatedPlanList.map((item,index)=>{
return <span>{item.planName} { (index < record.relatedPlanList.length-1)&&(<span></span>)} </span>
})
}
</Tooltip>
:
<span></span>
}
</span>
</div>
)
},
},
......@@ -509,15 +512,18 @@ class LiveCourseList extends React.Component {
dataIndex: "planList",
render: (val, record) => {
return (
<span>
<div className="related-task">
{ record.relatedPlanList ?
record.relatedPlanList.map((item,index)=>{
return <span>{item.planName} { (index < record.relatedPlanList.length-1)&&(<span></span>)} </span>
})
<Tooltip title={this.handlePlanName(record.relatedPlanList)} placement="top" arrowPointAtCenter>
{ record.relatedPlanList.map((item,index)=>{
return <span>{item.planName} { (index < record.relatedPlanList.length-1)&&(<span></span>)} </span>
})
}
</Tooltip>
:
<span></span>
}
</span>
</div>
)
},
},
......@@ -536,6 +542,19 @@ class LiveCourseList extends React.Component {
})
return adminStr
}
handlePlanName = (planArray)=>{
let planStr = "";
planArray.map((item,index)=>{
if(index < planArray.length-1){
planStr = planStr + item.planName + '、';
}else{
planStr = planStr + item.planName
}
})
return planStr
}
renderMoreOperate = (item) => {
return (
<div className="live-course-more-menu">
......
......@@ -67,6 +67,15 @@
}
.related-task{
text-overflow: -o-ellipsis-lastline;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
line-clamp: 2;
-webkit-box-orient: vertical;
}
.categoryName{
font-size: 14px;
color: #666666;
......
......@@ -122,7 +122,9 @@ class RelatedPlanModal extends React.Component {
item.taskId = selectPlanList[key].taskBaseVOList[0].taskId;
}
}
_selectPlanList.push(item)
if(item.taskId){
_selectPlanList.push(item)
}
}
return _selectPlanList;
}
......@@ -140,7 +142,7 @@ class RelatedPlanModal extends React.Component {
getSelectLength = (selectList)=>{
let num = 0;
for(let key in selectList ){
if(selectList[key].taskBaseVOList){
if(selectList[key].taskBaseVOList.length > 0){
num = num + 1
}
}
......@@ -173,10 +175,16 @@ class RelatedPlanModal extends React.Component {
enterButton={<span className="icon iconfont">&#xe832;</span>}
/>
</div>
<div className="select-container">
<span className="icon iconfont tip">&#xe6f2;</span>
<span className="text">已选择{this.getSelectLength(selectPlanList)}个任务</span>
<span className="clear" onClick={this.clearSelect}>清空</span>
<div className="select-container">
<span className="con">
<div>
<span className="icon iconfont tip">&#xe6f2;</span>
<span className="text">已选择{this.getSelectLength(selectPlanList)}个任务</span>
</div>
<div>
<span className="clear" onClick={this.clearSelect}>清空</span>
</div>
</span>
</div>
<div>
<Table
......@@ -212,13 +220,6 @@ class RelatedPlanModal extends React.Component {
this.selectPlanList(record,selected,_record.planId);
},
onSelectAll: (selected, _selectedRows, changeRows) => {
// let _list = [];
// if (selected) {
// _list = _.uniq(selectVideo.concat(changeRows), false, (item) => item.id);
// } else {
// _list = _.reject(selectVideo, (item) => _.find(changeRows, (data) => data.id === item.id));
// }
// this.setState({selectVideo:_list});
},
}}
/>
......@@ -233,6 +234,7 @@ class RelatedPlanModal extends React.Component {
current={query.current - 1}
pageSize={size}
total={totalCount}
size="small"
toPage={(page) => {
const _query = {...query, current: page + 1};
this.setState({
......
......@@ -4,26 +4,30 @@
}
.select-container{
margin-bottom:12px;
background: #FFF4DD;
border-radius: 4px;
padding:6px 16px;
width: 207px;
height: 32px;
.tip{
font-size:14px;
color:#FF9D14;
margin-right:8px;
}
.text{
font-size:14px;
color:#666;
margin-right:30px;
}
.clear{
color:#5289FA;
font-size:14px;
}
.con{
background: #FFF4DD;
border-radius: 4px;
padding:6px 16px;
display: inline-flex;
align-items: center;
justify-content: space-between;
.tip{
font-size:14px;
color:#FF9D14;
margin-right:8px;
}
.text{
font-size:14px;
color:#666;
margin-right:30px;
}
.clear{
color:#5289FA;
font-size:14px;
}
}
}
.plan-table{
.taskName{
......@@ -39,7 +43,8 @@
.course-type{
font-size:11px;
color:#666666;
padding:1px 8px;
padding:0px 6px;
line-height: 16px;
border: 1px solid #999999;
margin-right:4px;
border-radius: 2px;
......
......@@ -2,7 +2,7 @@
* @Author: 吴文洁
* @Date: 2020-08-05 10:07:47
* @LastEditors: zhangleyuan
* @LastEditTime: 2021-03-08 15:24:25
* @LastEditTime: 2021-03-12 10:12:23
* @Description: 视频课新增/编辑页
* @Copyright: 杭州杰竞科技有限公司 版权所有
*/
......@@ -24,7 +24,7 @@ import CourseService from "@/domains/course-domain/CourseService";
import User from '@/common/js/user';
import _ from "underscore";
import Upload from '@/core/upload';
import PhotoClip from 'photoclip';
// import PhotoClip from 'photoclip';
import './AddVideoCourse.less';
const EDIT_BOX_KEY = Math.random();
......@@ -200,11 +200,15 @@ class AddVideoCourse extends React.Component {
cancelText: '留在本页',
icon: <span className="icon iconfont default-confirm-icon">&#xe6f4;</span>,
onOk: () => {
RCHistory.goBack();
window.RCHistory.push({
pathname: `/video-course`,
});
}
});
}else{
RCHistory.goBack();
window.RCHistory.push({
pathname: `/video-course`,
});
}
}
......@@ -349,7 +353,9 @@ class AddVideoCourse extends React.Component {
CourseService.createVideoSchedule(commonParams).then((res) => {
if (!res) return;
message.success("新建成功");
window.RCHistory.goBack();
window.RCHistory.push({
pathname: `/video-course`,
});
})
} else {
const editParams = {
......@@ -359,7 +365,9 @@ class AddVideoCourse extends React.Component {
CourseService.editVideoSchedule(editParams).then((res) => {
if (!res) return;
message.success("保存成功");
window.RCHistory.goBack();
window.RCHistory.push({
pathname: `/video-course`,
});
});
}
});
......
......@@ -2,7 +2,7 @@
* @Author: 吴文洁
* @Date: 2020-08-05 10:12:45
* @LastEditors: zhangleyuan
* @LastEditTime: 2021-03-10 15:53:11
* @LastEditTime: 2021-03-16 15:20:35
* @Description: 视频课-列表模块
* @Copyright: 杭州杰竞科技有限公司 版权所有
*/
......@@ -93,7 +93,7 @@ class VideoCourseList extends React.Component {
title: '课程分类',
key: 'categoryName',
dataIndex: 'categoryName',
width: '20%',
width: 200,
render: (val, record) => {
return (
<div className="record__item">
......@@ -106,7 +106,7 @@ class VideoCourseList extends React.Component {
title: '创建人',
key: 'createName',
dataIndex: 'createName',
width: '10%',
width: 100,
render: (val) => {
return (
<div>
......@@ -128,7 +128,7 @@ class VideoCourseList extends React.Component {
<span>店铺展示</span>
<Tooltip title={<div>开启后,用户可在店铺内查看到此课程。若课程“未成功开课”,则系统会自动“关闭”店铺展示。<br/>关闭后,店铺内不再展示此课程,但用户仍可通过分享的海报/链接查看此课程。</div>}><i className="icon iconfont" style={{ marginLeft: '5px',cursor:'pointer',color:'#bfbfbf',fontSize:'14px'}}>&#xe61d;</i></Tooltip>
</span>,
width: '12%',
width: 120,
dataIndex: "courseware",
render: (val, item, index) => {
return (
......@@ -174,15 +174,18 @@ class VideoCourseList extends React.Component {
dataIndex: "planList",
render: (val, record) => {
return (
<span>
{ record.relatedPlanList ?
record.relatedPlanList.map((item,index)=>{
return <span>{item.planName} { (index < record.relatedPlanList.length-1)&&(<span></span>)} </span>
})
:
<span></span>
}
</span>
<div className="related-task">
{ record.relatedPlanList ?
<Tooltip title={this.handlePlanName(record.relatedPlanList)} placement="top" arrowPointAtCenter>
{ record.relatedPlanList.map((item,index)=>{
return <span>{item.planName} { (index < record.relatedPlanList.length-1)&&(<span></span>)} </span>
})
}
</Tooltip>
:
<span></span>
}
</div>
)
}
},
......@@ -217,7 +220,7 @@ class VideoCourseList extends React.Component {
];
return columns;
}
renderMoreOperate = (item) => {
return (
<div className="live-course-more-menu">
......@@ -240,7 +243,19 @@ class VideoCourseList extends React.Component {
</div>
)
}
//改变上架状态
handlePlanName = (planArray)=>{
let planStr = "";
planArray.map((item,index)=>{
if(index < planArray.length-1){
planStr = planStr + item.planName + '、';
}else{
planStr = planStr + item.planName
}
})
return planStr
}
//改变上架状态
changeShelfState = (item) =>{
let _shelfState = item.shelfState
if(_shelfState==='NO'){
......
......@@ -70,7 +70,15 @@
height:48px;
}
}
.related-task{
text-overflow: -o-ellipsis-lastline;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
line-clamp: 2;
-webkit-box-orient: vertical;
}
}
.video-course-more-menu {
......
......@@ -2,7 +2,7 @@
* @Author: zhangleyuan
* @Date: 2021-02-20 16:13:39
* @LastEditors: zhangleyuan
* @LastEditTime: 2021-03-10 16:51:57
* @LastEditTime: 2021-03-16 11:27:06
* @Description: 描述一下
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
......@@ -28,7 +28,6 @@ const defaultBasicData = {
operateType:'All_Operate',
percentCompleteLive:80,
percentCompleteVideo:80,
}
const defaultTaskList = [];
......@@ -38,6 +37,8 @@ function AddPlan() {
const [basicData,setBasicData] = useState(defaultBasicData);
const [taskList,setTaskList] = useState(defaultTaskList);
const [expiredCourseList,setExpiredCourseList] = useState([]);
const [hasGetDetail,setHasGetDetail]= useState(false);
const [submitDisabled,setSubmitDisabled] = useState(false);
useEffect(()=>{
if(type==='edit'){
getPlanDetail();
......@@ -91,6 +92,7 @@ function AddPlan() {
return _item
})
}
setTaskList(trainingTaskList);
setBasicData({
planName,
coverUrl:coverUrl || defaultCover,
......@@ -102,10 +104,10 @@ function AddPlan() {
percentCompleteLive,
percentCompleteVideo
})
setTaskList(trainingTaskList)
setHasGetDetail(true);
})
}
function handleChangeBasicInfo(field, value){
function handleChangeBasicInfo(field, value,option){
setBasicData( {
...basicData,
[field]: value,
......@@ -118,7 +120,8 @@ function AddPlan() {
function submitInfo(){
const {planName,enableState,selectOperatorList,instro,operateType,percentCompleteLive,percentCompleteVideo,coverId,coverUrl} = basicData;
if(!planName){
let input = /^[\s]*$/;
if(!planName || input.test(planName)){
message.warning('请输入的培训计划名称');
return;
}
......@@ -138,6 +141,22 @@ function AddPlan() {
message.warning('请输入培训计划内容');
return;
}
for(let i=0;i<taskList.length;i++){
if(input.test(taskList[i].taskName)){
message.warning('培训任务名称不能为空');
return false;
}
if(taskList[i].courseList.length === 0){
Modal.confirm({
title: '保存失败',
content: '每个任务下至少关联一个课程',
okText: '确定',
cancelText: '取消',
icon: <span className="icon iconfont default-confirm-icon">&#xe6f4;</span>,
})
return false;
}
}
let scheduleMediaRequests = [];
let coverObj ={
contentType:'COVER',
......@@ -173,6 +192,7 @@ function AddPlan() {
PlanService.createTrainingPlan(params).then((res) => {
if (res.success){
message.success("新建成功");
setSubmitDisabled(true);
window.RCHistory.goBack();
}
});
......@@ -244,7 +264,7 @@ function AddPlan() {
</div>
<div className="basic-info__wrap">
<div className="title">培训任务</div>
{ (type==='edit' && taskList.length>0) &&
{ (type==='edit' && hasGetDetail) &&
<TrainingTask data={taskList} onChange={handleChangeTaskInfo} />
}
{ type==='add' &&
......@@ -261,7 +281,7 @@ function AddPlan() {
</div>
<div className="footer">
<Button onClick={handleGoBack}>取消</Button>
<Button type="primary" onClick={submitInfo}>保存</Button>
<Button type="primary" onClick={submitInfo} disabled={submitDisabled}>保存</Button>
</div>
</div>
)
......
......@@ -27,6 +27,7 @@ class LearningData extends React.Component {
createName:""
}
}
componentDidMount(){
this.getPlanDetail();
Bus.bind('watchDataView',() =>{this.setState({activeKey:"userLearningData"}) })
......@@ -62,6 +63,7 @@ class LearningData extends React.Component {
})
})
}
render() {
const {planName,coverUrl,courseNum,created,cultureCustomerNum,activeKey,createName} = this.state;
return (
......@@ -97,10 +99,10 @@ class LearningData extends React.Component {
<div className="box">
{ (User.getUserRole() === "CloudManager" || User.getUserRole() === "StoreManager")?
(<Tabs activeKey={activeKey} onChange={(activeKey)=>{this.setState({activeKey})}}>
<Tabs.TabPane tab="员工分享数据" key="employeeShareData">
<Tabs.TabPane tab="员工分享数据" key="employeeShareData" forceRender="true">
<EmployeeShareData/>
</Tabs.TabPane>
<Tabs.TabPane tab="用户学习数据" key="userLearningData">
<Tabs.TabPane tab="用户学习数据" key="userLearningData" forceRender="true">
<UserLearningData/>
</Tabs.TabPane>
</Tabs>)
......
.plan-learn-data-list{
.ant-tabs-tab.ant-tabs-tab-active{
font-weight:normal;
}
.ant-tabs-tab.ant-tabs-tab-active .ant-tabs-tab-btn{
font-weight:normal;
}
.plan-info{
margin:16px;
padding:16px;
......
......@@ -2,7 +2,7 @@
* @Author: zhangleyuan
* @Date: 2021-02-20 16:45:51
* @LastEditors: zhangleyuan
* @LastEditTime: 2021-03-10 19:03:09
* @LastEditTime: 2021-03-15 17:01:47
* @Description: 描述一下
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
......@@ -13,9 +13,10 @@ import SelectOperatorModal from '../modal/SelectOperatorModal';
import { ImgCutModalNew } from '@/components';
import SelectPrepareFileModal from '@/modules/prepare-lesson/modal/SelectPrepareFileModal';
import Upload from '@/core/upload';
import PhotoClip from 'photoclip'
// import PhotoClip from 'photoclip'
import './BasicInfo.less';
const { TextArea } = Input;
const defaultCover = 'https://image.xiaomaiketang.com/xm/YNfi45JwFA.png';
let cutFlag = false;
......@@ -218,7 +219,7 @@ class BasicInfo extends React.Component{
<span className="label"><span className="require">*</span>培训计划名称:</span>
<Input
value={planName}
placeholder="请输入培训计划名称,最多20字"
placeholder="请输入培训计划名称(20字以内)"
maxLength={20}
style={{ width: 240 }}
onChange={(e)=>this.props.onChange('planName', e.target.value)}
......@@ -252,7 +253,7 @@ class BasicInfo extends React.Component{
<TextArea
placeholder="请输入培训计划简介"
maxLength={200}
style={{ width: 480 }}
style={{ width: '552px',height:'110px'}}
className="instro-textarea"
value={instro}
onChange={(e)=>this.props.onChange('instro', e.target.value)}
......@@ -308,28 +309,32 @@ class BasicInfo extends React.Component{
</div>
</div>
<div className="done-standard">
<span className="label"><span className="require">*</span>完成标准:</span>
<span className="label standard-label"><span className="require">*</span>完成标准:</span>
<div>
<div className="live-standard-info">
<span className="icon iconfont">&#xe865;</span>
<span>直播课单个课程,用户学习进度达到
<span className="instro">直播课单个课程,用户学习进度达到
<Input
width="40"
value={percentCompleteLive}
onChange={(e) => { this.props.onChange('percentCompleteLive', e.target.value.replace(/\D/g,'')) }}
onBlur={(e)=>this.percentCompleteBlur(e,'percentCompleteLive')}
/>%
即视为“已完成”学习
className="input-box"
/>%,即视为"已完成"学习
</span>
</div>
<div className="video-standard-info">
<span className="icon iconfont">&#xe864;</span>
<span>视频课单个课程,用户学习进度达到
<Input width="40"
value={percentCompleteVideo}
onChange={(e) => { this.props.onChange('percentCompleteVideo', e.target.value.replace(/\D/g,'')) }}
onBlur={(e)=>this.percentCompleteBlur(e,'percentCompleteVideo')}/>
%即视为“已完成”学习
<span className="instro">视频课单个课程,用户学习进度达到
<Input
width="40"
value={percentCompleteVideo}
onChange={(e) => { this.props.onChange('percentCompleteVideo', e.target.value.replace(/\D/g,'')) }}
onBlur={(e)=>this.percentCompleteBlur(e,'percentCompleteVideo')}
className="input-box"
/>
%,即视为"已完成"学习
</span>
</div>
<div className="video-standard-info">
......
......@@ -3,6 +3,8 @@
width: 110px;
text-align: right;
display:inline-block;
font-size:14px;
color:#666;
.require {
color: #EC4B35;
}
......@@ -16,6 +18,7 @@
margin-top: 16px;
&__wrap {
position: relative;
display: flex;
.tag {
border-radius: 2px;
background: #D6D6D6;
......@@ -29,16 +32,10 @@
left: 8px;
}
}
.cover__wrap {
display: flex;
flex-direction: row;
}
.img-content {
margin-right: 20px;
width: 299px;
height: 169px;
img {
width: 100%;
height: 100%;
......@@ -46,6 +43,22 @@
border: 1px solid #E8e8e8;
}
}
.opt-btns{
.default-btn {
margin:0 8px;
color: #5289FA;
cursor: pointer;
&.disabled {
color: #CCC;
cursor: not-allowed;
}
}
.tips{
margin-top:8px;
font-size:14px;
color:#999;
}
}
}
.introduction{
margin-top:16px;
......@@ -67,6 +80,9 @@
.view-range{
display:flex;
margin-top:16px;
.label{
margin-top:2px;
}
.instro-text{
color:#999;
margin-left:12px;
......@@ -74,10 +90,17 @@
.choose-business{
margin-top:16px;
}
.playback__text{
margin-left:12px;
color:#999999;
}
}
.done-standard{
display: flex;
margin-top:22px;
.standard-label{
margin-top:3px;
}
.live-standard-info{
margin-bottom:10px;
}
......@@ -86,7 +109,24 @@
width:90px;
height:32px;
}
.icon{
color:#A0A0A0;
font-size:14px;
margin-right:4px;
}
.instro{
color:#333333;
font-size:14px;
}
.input-box{
width: 60px;
height: 32px;
border-radius: 4px;
border: 1px solid #E8E8E8;
color:#333333;
font-size:14px;
margin:0 2px;
}
}
}
......@@ -105,7 +105,7 @@ class EmployeeShareData extends React.Component {
})
}
watchDataView = (record)=>{
Bus.trigger('watchDataView',record.storeUserId);
Bus.trigger('watchDataView',record);
}
// 请求表头
parselumns = () => {
......@@ -150,6 +150,7 @@ class EmployeeShareData extends React.Component {
title: '最近分享成功时间',
key: 'recentlyForwardTime',
dataIndex: 'recentlyForwardTime',
width:240,
render: (val, record) => {
return (
<div>
......@@ -162,41 +163,44 @@ class EmployeeShareData extends React.Component {
title: '学习人数',
key: 'learnNum',
dataIndex: 'learnNum',
width:110,
sorter:true,
render: (val, record) => {
return (
<div>
{val}
</div>
)
}
},
{
title: '已学完',
key: 'learnFinishNum',
dataIndex: 'learnFinishNum',
sorter:true,
render: (val, record) => {
return (
<div>
{val}
</div>
)
}
},
{
title: '未学完',
key: 'learnNoFinishNum',
dataIndex: 'learnNoFinishNum',
sorter:true,
render: (val, record) => {
return (
<div>
<div className="learn-num">
{val}
</div>
)
}
},
// {
// title: '已学完',
// key: 'learnFinishNum',
// dataIndex: 'learnFinishNum',
// width:110,
// sorter:true,
// render: (val, record) => {
// return (
// <div className="learn-finish-num">
// {val}
// </div>
// )
// }
// },
// {
// title: '未学完',
// key: 'learnNoFinishNum',
// dataIndex: 'learnNoFinishNum',
// width:110,
// sorter:true,
// render: (val, record) => {
// return (
// <div className="learn-no-finish-num">
// {val}
// </div>
// )
// }
// },
{
title: '操作',
key: 'operate',
......@@ -216,7 +220,7 @@ class EmployeeShareData extends React.Component {
return (
<div className="employee-share-data">
<div className="search-container">
<Search placeholder="搜索员工姓名手机号" onChange={(e) => { this.handleChangNickname(e.target.value)}} onSearch={ () => { this.handleFetchDataList()}} 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>
<Table
......@@ -225,6 +229,7 @@ class EmployeeShareData extends React.Component {
columns={this.parselumns()}
pagination={false}
onChange={this.handleChangeTable}
showSorterTooltip={false}
bordered
/>
{dataSource.length >0 &&
......
......@@ -7,4 +7,16 @@
color:#5289FA;
cursor: pointer;
}
.learn-num{
text-align:right;
margin-right:20px;
}
.learn-finish-num{
text-align:right;
margin-right:30px;
}
.learn-no-finish-num{
text-align:right;
margin-right:35px;
}
}
\ No newline at end of file
.expired-course-list{
margin:18px 10px 16px;
margin:8px 10px 0px;
.course-item{
display:flex;
padding:16px 0;
border-bottom:1px solid #E8E8E8;
border-bottom:1px dotted #E8E8E8;
justify-content: space-between;
&:last-child{
border-bottom:none;
padding-bottom:0px;
}
.course-left{
display:flex;
......@@ -19,11 +22,12 @@
.course-type{
margin-right:16px;
span{
padding:2px 8px;
padding:0px 6px;
color:#666666;
font-size:11px;
border-radius: 2px;
border: 1px solid #999999;
line-height: 16px;
}
}
.course-instro{
......
......@@ -39,7 +39,7 @@ function PlanFilter(props) {
useEffect(() => {
getCreatorList();
}, [creatorQuery]);
}, []);
// 改变搜索条件
function handleChangeQuery(field, value){
......@@ -98,6 +98,9 @@ function PlanFilter(props) {
const container = e.target;
const scrollToBottom = container && container.scrollHeight <= container.clientHeight + container.scrollTop;
if (scrollToBottom && hasNext) {
const _creatorQuery = {...creatorQuery};
_creatorQuery.current = creatorQuery.current + 1;
setCreatorQuery(_creatorQuery);
getCreatorList(creatorQuery.current + 1);
}
}
......
......@@ -2,7 +2,7 @@
* @Author: zhangleyuan
* @Date: 2021-02-20 16:46:46
* @LastEditors: zhangleyuan
* @LastEditTime: 2021-03-10 15:51:26
* @LastEditTime: 2021-03-16 15:53:59
* @Description: 描述一下
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
......@@ -28,10 +28,10 @@ function PlanList(props) {
title: '培训计划',
key: 'planName',
dataIndex: 'planName',
width:'15%',
width:'18%',
render: (val, record) => {
return (
<div className="plan__name">
<div className="plan-name">
{val}
</div>
)
......@@ -41,7 +41,7 @@ function PlanList(props) {
title: '课程总数量',
key: 'courseNum',
dataIndex: 'courseNum',
width: '10%',
width: 110,
render: (val, record) => {
return (
<div className="course-number">
......@@ -75,7 +75,7 @@ function PlanList(props) {
},
{
title: '创建时间',
width: "10%",
width: "12.5%",
key: 'created',
dataIndex: 'created',
sorter: true,
......@@ -95,7 +95,7 @@ function PlanList(props) {
},
{
title: '参培人数',
width: "10%",
width:76,
key: 'cultureCustomerNum',
dataIndex: 'cultureCustomerNum',
sorter: true,
......@@ -111,7 +111,8 @@ function PlanList(props) {
title: '操作',
key: 'operate',
dataIndex: 'operate',
width: '25%',
fixed: 'right',
width: 176,
render: (val, record) => {
return (
<div className="operate">
......@@ -145,6 +146,7 @@ function PlanList(props) {
];
return columns;
}
function renderMoreOperate(item){
return (
<div className="live-course-more-menu">
......@@ -158,6 +160,7 @@ function PlanList(props) {
</div>
)
}
function handleChangeTable(pagination, filters, sorter){
const { columnKey, order } = sorter;
const { query } = props;
......@@ -224,49 +227,6 @@ function PlanList(props) {
props.onChange();
}
})
// 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){
......@@ -325,11 +285,15 @@ function PlanList(props) {
<div className="plan-list">
<Table
rowKey={record => record.id}
showSorterTooltip={false}
dataSource={props.planListData}
columns={ parseColumns() }
pagination={false}
onChange={handleChangeTable}
bordered
size="middle"
scroll={{ x: 1400}}
className="plan-list-table"
/>
<div className="box-footer">
<PageControl
......
.plan-list{
margin-top:12px;
.course-number{
text-align:right;
margin-right:45px;
}
.plan-list-table{
tbody {
tr{
&:nth-child(even){
background: transparent !important;
td{
background:#FFF !important;
}
}
&:nth-child(odd){
background: #FAFAFA !important;
td{
background: #FAFAFA !important;
}
}
&:hover{
td{
background:#F3f6fa !important;
}
}
}
}
}
.plan-name{
text-overflow: -o-ellipsis-lastline;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
line-clamp: 2;
-webkit-box-orient: vertical;
}
.operate-text {
color: #5289FA;
cursor: pointer;
}
.operate {
display: flex;
&__item {
color: #5289FA;
cursor: pointer;
}
.operate {
display: flex;
&__item {
color: #5289FA;
cursor: pointer;
&.split {
margin: 0 8px;
color: #BFBFBF;
}
&.split {
margin: 0 8px;
color: #BFBFBF;
}
}
}
.join-number{
text-align:right;
margin-right:12px;
}
.more-operate{
line-height:20px;
}
}
\ No newline at end of file
......@@ -2,7 +2,7 @@
* @Author: zhangleyuan
* @Date: 2021-02-20 16:45:51
* @LastEditors: zhangleyuan
* @LastEditTime: 2021-03-11 14:02:25
* @LastEditTime: 2021-03-16 11:36:36
* @Description: 描述一下
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
......@@ -41,6 +41,7 @@ const courseStateShow = {
title: "未成功开课",
},
};
const DragHandle = sortableHandle(() => (
<span className="operate__item" >
<span className="icon iconfont">&#xe7cd;</span>
......@@ -245,6 +246,7 @@ class TrainingTask extends React.Component {
}
return Promise.resolve()
}
handleValidatorCourseName = (rule,value)=>{
let input = /^[\s]*$/;
if (input.test(value) || !value){
......@@ -252,8 +254,9 @@ class TrainingTask extends React.Component {
}
return Promise.resolve()
}
renderTaskItem = (record,index)=>{
return <div className="task-item">
return <div className="plan-sort-task-item">
<div className="task-con">
<div className="task-instro">
<span onClick={()=>this.openOrCloseTask(index)}>
......@@ -287,9 +290,9 @@ class TrainingTask extends React.Component {
</div>
<div className="operate">
<DragHandle />
<span className="operate__item">
<span className="operate__item" onClick={()=>{const { dataSource }= this.state; record.type="input";this.setState({dataSource})}}>
<span className="icon iconfont">&#xe6f5;</span>
<span className="text" onClick={()=>{const { dataSource }= this.state; record.type="input";this.setState({dataSource})}}>重命名</span>
<span className="text">重命名</span>
</span>
<span className="operate__item" onClick={()=>{this.handleDeleteTask(index)}} >
<span className="icon iconfont">&#xe6f6;</span>
......@@ -323,7 +326,7 @@ class TrainingTask extends React.Component {
</div>
}
renderCourseItem = (record,index,parentIndex)=>{
return <div className="course-item">
return <div className="plan-course-sort-item">
<div className="course-info">
<span className="course-type">{CourseType[record.courseType].text}</span>
{record.type==='input'?
......@@ -339,7 +342,7 @@ class TrainingTask extends React.Component {
<Input className="course-name-input" defaultValue={record.courseName} style={{ width: 300 }} placeholder="请输入课程名称(40字以内)" maxLength={40} onChange={(e) => { this.handleRenameCourseName(e,record)}} onBlur={(e)=>{this.handleCourseNameBlur(e,record)}}/></Form.Item>
</Form>
:
<span className="course-name">{parentIndex + 1}.{index + 1}{record.courseName}</span>
<span className="course-name">{parentIndex + 1}.{index + 1} {record.courseName}</span>
}
{record.courseState === "EXPIRED" &&
<span className="icon iconfont tip">&#xe834;</span>
......@@ -349,12 +352,12 @@ class TrainingTask extends React.Component {
}
</div>
<div className="operate">
<div className="course-operate">
<DragHandle />
<span className="operate__item">
{/* <span className="operate__item">
<span className="icon iconfont">&#xe6f5;</span>
<span className="text" onClick={(e)=>{const { dataSource } = this.state; record.type="input";this.setState({dataSource})}}>重命名</span>
</span>
</span> */}
<span className="operate__item" onClick={()=>{this.handleDeleteCourse(parentIndex,index)}}>
<span className="icon iconfont">&#xe6f6;</span>
<span className="text">删除</span>
......@@ -373,6 +376,7 @@ class TrainingTask extends React.Component {
disableAutoscroll
helperClass="row-dragging"
onSortEnd={this.onTaskSortEnd}
className="plan-task-sort-container"
>
{dataSource.map((item, index) =>
<SortableTaskItem taskItem={this.renderTaskItem(item,index)} index={index}>
......
......@@ -5,103 +5,7 @@
.ant-form-item{
margin-bottom:0 !important;
}
.task-item{
.task-con{
display:flex;
padding:16px;
background: #F7F8F9;
border-radius: 2px;
justify-content: space-between;
align-items: center;
.task-instro{
display:flex;
align-items: center;
.open-icon{
color:#999999;
font-size:10px;
}
.task-name-con{
display:flex;
align-items: center;
color:#333333;
font-size:14px;
.number{
margin-right:10px;
margin-left:10px;
}
.task-name-input{
width: 300px;
height: 32px;
background: #FFFFFF;
border-radius: 4px;
}
}
}
}
.operate{
.operate__item{
cursor:pointer;
margin-left:16px;
color:#666666;
font-size:14px;
.icon{
color:#999;
}
.text{
margin-left:8px;
}
}
}
.course-box{
.course-item{
display:flex;
padding:16px 16px 16px 51px;
justify-content: space-between;
align-items: center;
.course-info{
.ant-form{
display:inline-block;
}
.course-name-input{
margin-right:8px;
}
.course-type{
font-size:11px;
color:#666666;
padding:1px 8px;
border: 1px solid #999999;
margin-right:4px;
border-radius: 2px;
}
.course-name{
color:#666666;
font-size:14px;
margin-right:8px;
}
.tip{
font-size:14px;
color:#FF4F4F;
margin-right:2px;
}
.course-state{
color:#999;
font-size:14px;
}
}
}
.add-course-con{
padding:16px 51px;
color: #5289FA;
font-size:14px;
.add-course-btn-disabled{
font-size:14px;
color:#ccc;
}
}
}
}
.add-task-con{
height: 52px;
background: #F7F8F9;
......@@ -118,3 +22,132 @@
}
}
}
.plan-sort-task-item{
.task-con{
display:flex;
padding:16px;
background: #F7F8F9;
border-radius: 2px;
justify-content: space-between;
align-items: center;
.task-instro{
display:flex;
align-items: center;
.open-icon{
color:#999999;
font-size:10px;
}
.task-name-con{
display:flex;
align-items: center;
color:#333333;
font-size:14px;
.number{
margin-right:10px;
margin-left:10px;
}
.task-name-input{
width: 300px;
height: 32px;
background: #FFFFFF;
border-radius: 4px;
}
}
}
.operate{
display: none;
.operate__item{
cursor:pointer;
margin-left:16px;
color:#666666;
font-size:14px;
.icon{
font-size:14px;
color:#999;
}
.text{
margin-left:8px;
}
}
}
&:hover{
.operate{
display:block;
}
}
}
.course-box{
.add-course-con{
padding:16px 51px;
color: #5289FA;
font-size:14px;
.add-course-btn-disabled{
font-size:14px;
color:#ccc;
}
}
}
}
.plan-course-sort-item{
display:flex;
padding:16px 16px 16px 0px;
margin-left:51px;
justify-content: space-between;
align-items: center;
border-bottom:1px dotted #E8E8E8;
&:hover{
.course-operate{
display:block;
}
}
.course-operate{
display: none;
.operate__item{
cursor:pointer;
margin-left:16px;
color:#666666;
font-size:14px;
.icon{
font-size:14px;
color:#999;
}
.text{
margin-left:8px;
}
}
}
.course-info{
.ant-form{
display:inline-block;
}
.course-name-input{
margin-right:8px;
}
.course-type{
font-size:11px;
color:#666666;
padding:0px 6px;
border: 1px solid #999999;
margin-right:4px;
border-radius: 2px;
line-height: 16px;
}
.course-name{
color:#666666;
font-size:14px;
margin-right:8px;
}
.tip{
font-size:14px;
color:#FF4F4F;
margin-right:2px;
}
.course-state{
color:#999;
font-size:14px;
}
}
}
......@@ -36,7 +36,7 @@ class UserLearningData extends React.Component {
},
totalCount:0,
userLearnDetailModalSHow:false,
unbundEmployeeModalVisible:false
unbundEmployeeModalVisible:false,
}
}
componentDidMount(){
......@@ -182,7 +182,7 @@ class UserLearningData extends React.Component {
{
title: <span>
<span>负责人</span>
<Tooltip title="用户加入学习时,培训计划的分享者"><i className="icon iconfont" style={{ marginLeft: '5px',cursor:'pointer',color:'#bfbfbf',fontSize:'14px'}}>&#xe61d;</i></Tooltip>
<Tooltip title="培训计划的分享者/跟进人"><i className="icon iconfont" style={{ marginLeft: '5px',cursor:'pointer',color:'#bfbfbf',fontSize:'14px'}}>&#xe61d;</i></Tooltip>
</span>,
key: 'userNameList',
dataIndex: 'userNameList',
......@@ -201,11 +201,10 @@ class UserLearningData extends React.Component {
key: 'latelyLearnTime',
dataIndex: 'latelyLearnTime',
sorter:true,
width:240,
render: (val, record) => {
return (
<div>
{formatDate('YYYY-MM-DD H:i', val)}
</div>
`${formatDate('YYYY-MM-DD H:i',parseInt(record.latelyLearnTime))}`
)
}
},
......@@ -213,6 +212,7 @@ class UserLearningData extends React.Component {
title: '开始学习时间',
key: 'startLearnTime',
dataIndex: 'startLearnTime',
width:240,
sorter:true,
render: (val, record) => {
return (
......@@ -229,10 +229,11 @@ class UserLearningData extends React.Component {
</span>,
key: 'learnNum',
dataIndex: 'learnNum',
width:130,
sorter:true,
render: (val, record) => {
return (
<div>
<div className="learn-num">
<span>{record.courseFinishNum}</span>
<span>/</span>
<span>{record.courseNum}</span>
......@@ -354,12 +355,13 @@ class UserLearningData extends React.Component {
</div>
<div>
<Table
rowKey={record => record.id}
rowKey={record => record.storeCustomerId}
dataSource={dataSource}
columns={this.parselumns()}
pagination={false}
className="user-learning-table"
onChange={this.handleChangeTable}
showSorterTooltip={false}
bordered
/>
{dataSource.length >0 &&
......
......@@ -13,4 +13,8 @@
color: #BFBFBF;
}
}
.learn-num{
text-align:right;
margin-right:20px;
}
}
\ No newline at end of file
......@@ -24,7 +24,7 @@ const DEFAULT_QUERY = {
startTime: null,
endTime:null,
learnState:null,
operateId: null
operateId: null,
}
const defaultCreatorQuery = {
size: 10,
......@@ -35,30 +35,35 @@ function UserLearningDataFilter(props) {
const [expandFilter, setExpandFilter] = useState(false);
const [query,setQuery] = useState(DEFAULT_QUERY);
const [operateName,setOperateName] = useState(null)
const [hasNext,setHasNext] = useState(false);
const [creatorQuery,setCreatorQuery] = useState(defaultCreatorQuery);
const [creatorList,setCreatorList] = useState([]);
useEffect(() => {
Bus.bind('watchDataView',(value) => handleChangeCreatorQuery(value))
}, []);
Bus.bind('watchDataView',(record) => handleChangeCreatorQuery(record))
});
useEffect(() => {
getCreatorList();
}, [creatorQuery]);
}, []);
function handleChangeCreatorQuery (value){
function handleChangeCreatorQuery (record){
const _creatorQuery = {...creatorQuery};
_creatorQuery.operateId = value;
_creatorQuery.operateId = record.storeUserId;
setCreatorQuery(_creatorQuery);
handleChangeQuery('operateId', record.storeUserId,record.storeUserName)
}
// 改变搜索条件
function handleChangeQuery(field, value){
function handleChangeQuery(field,value,optionValue){
const _query ={
...query,
[field]: value,
current: 1,
}
setQuery(_query);
if(field === 'operateId'){
setOperateName(optionValue)
}
if (field === 'customerName') return;
props.onChange( _query);
}
......@@ -108,6 +113,9 @@ function UserLearningDataFilter(props) {
const container = e.target;
const scrollToBottom = container && container.scrollHeight <= container.clientHeight + container.scrollTop;
if (scrollToBottom && hasNext) {
const _creatorQuery = {...creatorQuery};
_creatorQuery.current = creatorQuery.current + 1;
setCreatorQuery(_creatorQuery);
getCreatorList(creatorQuery.current + 1);
}
}
......@@ -133,16 +141,21 @@ function UserLearningDataFilter(props) {
<span className="label lead-label">负责人:</span>
<Select
id="leadSelect"
placeholder="请选择创建人"
placeholder="请选择员工"
style={{width:"calc(100% - 70px)"}}
showSearch
allowClear
filterOption={(input, option) => option}
suffixIcon={<span className="icon iconfont" style={{fontSize:'12px',color:'#BFBFBF'}}>&#xe835;</span>}
onPopupScroll={handleScrollCreatorList}
value={query.operateId}
onChange={(value) => {
handleChangeQuery('operateId', value)
value={operateName}
onChange={(value,option) => {
if(option){
handleChangeQuery('operateId',value,option.children)
}else{
handleChangeQuery('operateId',value,"")
}
}}
onSearch={(value) => {
creatorQuery.nickName = value
......
......@@ -107,7 +107,12 @@ class SelectOperatorModal extends React.Component {
closeIcon={<span className="icon iconfont modal-close-icon">&#xe6ef;</span>}
>
<div className="search-container">
<Search placeholder="搜索运营师/手机号" style={{ width: 200 }} onChange={(e) => { this.handleChangNickname(e.target.value)}} onSearch={ () => { this.handleFetchDataList()}} />
<Search placeholder="搜索运营师/手机号"
enterButton={<span className="icon iconfont">&#xe832;</span>}
style={{ width: 200 }}
onChange={(e) => { this.handleChangNickname(e.target.value)}}
onSearch={ () => { this.handleFetchDataList()}}
/>
</div>
<div>
<Table
......@@ -115,6 +120,7 @@ class SelectOperatorModal extends React.Component {
dataSource={dataSource}
columns={this.parseColumns()}
pagination={false}
bordered
rowSelection={{
type: 'checkbox',
selectedRowKeys: _.pluck(selectOperatorList, 'id'),
......@@ -135,6 +141,7 @@ class SelectOperatorModal extends React.Component {
{dataSource.length >0 &&
<div className="box-footer">
<PageControl
size="small"
current={query.current - 1}
pageSize={size}
total={totalCount}
......
......@@ -142,8 +142,7 @@ class ShareLiveModal extends React.Component {
<div className="share-url right__item">
<div className="title">② 链接分享</div>
<div className="sub-title">用户可通过微信打开以下链接,查看培训计划</div>
<div className="sub-title">用户可通过微信或浏览器打开以下链接,查看培训计划</div>
<div className="content url-content">
<div className="share-url" id="shareUrl">{shareUrl}</div>
<Button type="primary" onClick={this.handleCopy}>复制</Button>
......
......@@ -84,6 +84,10 @@ class UnbundEmployeeModal extends React.Component {
}
confirmUnbund = ()=>{
const { selectOperatorList } = this.state;
if(selectOperatorList.length ===0){
message.warning('请选择需要解绑的员工');
return false;
}
const params = {
planId:getParameterByName("id"),
removeUserIds:_.pluck(selectOperatorList, 'storeUserId'),
......@@ -129,7 +133,7 @@ class UnbundEmployeeModal extends React.Component {
if (selected) {
_list = _.uniq(selectOperatorList.concat(changeRows), false, (item) => item.storeUserId);
} else {
_list = _.reject(selectOperatorList, (item) => _.find(changeRows, (data) => data.id === item.storeUserId));
_list = _.reject(selectOperatorList, (item) => _.find(changeRows, (data) => data.storeUserId === item.storeUserId));
}
this.setState({selectOperatorList:_list});
}
......
......@@ -36,7 +36,7 @@ class UserLearnDetailModal extends React.Component {
constructor(props) {
super(props);
this.state = {
planDataSource:[],
planDataSource:{},
taskDataSource:[],
taskSize:10,
taskQuery: {
......@@ -72,52 +72,19 @@ class UserLearnDetailModal extends React.Component {
}
return item;
})
const planDataSource = [{
const planDataSource = {
planName,
learnFinishPercentage,
coverUrl:coverUrl || defaultCover
}]
}
this.setState({
storeCustomerName,
storeCustomerName,
storeCustomerPhone,
planDataSource,
taskDataSource:taskCustomerVOList
})
})
}
parsePlanColumns = () => {
const columns = [
{
title: '培训计划名称',
key: 'planInfo',
dataIndex: 'planInfo',
render: (val, record) => {
return (
<div className="plan-instro">
<div className="img-con">
<img src={record.coverUrl}/>
</div>
<div className="plan-name">{record.planName}</div>
</div>
)
}
},
{
title: '学习进度',
key: 'learnFinishPercentage',
dataIndex: 'learnFinishPercentage',
width:167,
render: (val, record) => {
return (
<div className="plan-learn-percentage">
{val}%
</div>
)
}
}
];
return columns;
}
parseTaskColumns = () => {
const columns = [
......@@ -158,14 +125,16 @@ class UserLearnDetailModal extends React.Component {
render: (val, record,index) => {
return (
<div className="course-info">
<span className="course-type">{CourseType[record.courseType].text}</span>
<span className="course-name">{parentIndex + 1}.{index + 1}{record.courseName}</span>
{record.courseState === "EXPIRED" &&
<span className="icon iconfont tip">&#xe834;</span>
}
{ record.courseType==="LIVE" &&
<span className="course-state">{courseStateShow[record.courseState].title}</span>
}
<div>
<span className="course-type">{CourseType[record.courseType].text}</span>
<span>{parentIndex + 1}.{index + 1}&nbsp;</span>
</div>
<div className="name-and-state">
<span className="course-name">{record.courseName}</span>
{ record.courseType==="LIVE" &&
<span className="course-state">{courseStateShow[record.courseState].title}</span>
}
</div>
</div>
)
}
......@@ -193,6 +162,7 @@ class UserLearnDetailModal extends React.Component {
<Modal
title="用户学习详情"
onCancel={this.props.onClose}
onOk={this.props.onClose}
maskClosable={false}
visible={visible}
className="user-Learn-modal"
......@@ -210,15 +180,18 @@ class UserLearnDetailModal extends React.Component {
<span>{storeCustomerPhone}</span>
</span>
</div>
<div>
<Table
dataSource={planDataSource}
columns={this.parsePlanColumns()}
pagination={false}
bordered
className="plan-table"
/>
<div className="plan-instro">
<div className="img-con">
<img src={planDataSource.coverUrl}/>
</div>
<div>
<div className="plan-name">{planDataSource.planName}</div>
<div className="task-learn-percentage">
<span>学习进度: {planDataSource.learnFinishPercentage}%</span>
</div>
</div>
</div>
<div>
<Table
rowKey={(record) => record.taskId}
......
.user-Learn-modal{
.customer-info{
margin-bottom:16px;
.customer-name{
......@@ -11,62 +12,84 @@
color:#333;
}
}
.plan-table{
margin-bottom:8px;
.plan-instro{
display: flex;
align-items: center;
.img-con{
margin-right:8px;
img{
width: 97px;
height: 55px;
display: inline-block;
border-radius:4px;
}
}
.plan-name{
color:#666666;
font-size:14px;
}
.plan-learn-percentage{
color:#666666;
font-size:14px;
.plan-instro{
display: flex;
align-items: center;
margin-bottom:16px;
.img-con{
margin-right:8px;
img{
width: 97px;
height: 54px;
display: inline-block;
border-radius:4px;
}
}
.plan-name{
color:#333;
font-size:16px;
}
.plan-learn-percentage{
color:#333;
font-size:14px;
}
}
.task-table{
.ant-table-thead{
tr {
th{
padding:9px 16px;
}
}
}
tr{
td{
padding:14px 16px;
}
}
.taskName{
color:#666666;
color:#333;
font-size:14px;
}
.task-learn-percentage{
color:#666666;
color:#333;
font-size:14px;
}
.course-info{
display:flex;
margin-left:57px;
align-items: center;
.course-type{
font-size:11px;
color:#666666;
padding:1px 8px;
padding:0px 6px;
border: 1px solid #999999;
margin-right:4px;
border-radius: 2px;
line-height: 16px;
}
.course-name{
color:#666666;
font-size:14px;
margin-right:8px;
}
.tip{
font-size:14px;
color:#FF4F4F;
margin-right:2px;
.name-and-state{
flex:1;
.course-name{
color:#666666;
font-size:14px;
margin-right:8px;
}
.tip{
font-size:14px;
color:#FF4F4F;
margin-right:2px;
}
.course-state{
color:#999;
font-size:14px;
}
}
.course-state{
color:#999;
font-size:14px;
}
.ant-table-expanded-row{
td{
padding:0 16px;
}
}
.ant-table-content{
......@@ -76,13 +99,18 @@
border:none;
}
.child-table{
.ant-table-content{
border:none;
thead{
display:none;
}
tbody tr td{
border-bottom:none;
tbody tr {
td{
border-bottom:none;
padding:14px 16px;
}
}
}
......
......@@ -161,14 +161,15 @@ class SelectOperatorModal extends React.Component {
videoSize:size
},()=>{this.handleFetchLiveDataList()})
}
// 请求表头
parseLiveColumns = () => {
const columns = [
{
title: <span><span>课程信息</span><Tooltip title="以下为该培训计划暂未关联的课程。 已关联的课程不支持重复选择,因此不显示。"><i className="icon iconfont" style={{ marginLeft: '5px',cursor:'pointer',color:'#bfbfbf',fontSize:'14px'}}>&#xe61d;</i></Tooltip></span>,
title: <span><span>课程信息</span><Tooltip title="仅显示未关联课程,已关联课程不支持重复选择"><i className="icon iconfont" style={{ marginLeft: '5px',cursor:'pointer',color:'#bfbfbf',fontSize:'14px'}}>&#xe61d;</i></Tooltip></span>,
key: 'course',
dataIndex: 'course',
width:'45%',
width:'40%',
render: (val, record) => {
let hasCover = false;
return (
......@@ -199,7 +200,10 @@ class SelectOperatorModal extends React.Component {
width:'40%',
render: (val, record) => {
return (
<span>{formatDate('YYYY-MM-DD H:i', record.startTime)}</span>
<div>
<div>{formatDate('YYYY-MM-DD', record.startTime)}</div>
<div>{formatDate('H:i', record.startTime)}~{formatDate('H:i', record.endTime)}</div>
</div>
)
}
},
......@@ -207,7 +211,7 @@ class SelectOperatorModal extends React.Component {
title: '店铺展示',
key: 'shelfState',
dataIndex: 'shelfState',
width:'15%',
width:'20%',
render: (val, record) => {
return (
<span>
......@@ -229,7 +233,7 @@ class SelectOperatorModal extends React.Component {
parseVideoColumns = () => {
const columns = [
{
title: <span><span>课程信息</span><Tooltip title="以下为该培训计划暂未关联的课程。 已关联的课程不支持重复选择,因此不显示。"><i className="icon iconfont" style={{ marginLeft: '5px',cursor:'pointer',color:'#bfbfbf',fontSize:'14px'}}>&#xe61d;</i></Tooltip></span>,
title: <span><span>课程信息</span><Tooltip title="仅显示未关联课程,已关联课程不支持重复选择"><i className="icon iconfont" style={{ marginLeft: '5px',cursor:'pointer',color:'#bfbfbf',fontSize:'14px'}}>&#xe61d;</i></Tooltip></span>,
key: 'course',
dataIndex: 'course',
width:'60%',
......@@ -348,9 +352,9 @@ class SelectOperatorModal extends React.Component {
closeIcon={<span className="icon iconfont modal-close-icon">&#xe6ef;</span>}
footer={[
activeKey ==='live'?
<a target='_blank' className="link-create-course" href="https://dev.xiaomai5.com/xiaomai-cloud-class-web/index.html#/create-live-course?type=add">没有找到需要的直播课?<span>去创建</span></a>
<a target='_blank' className="link-create-course" href={window.location.origin + window.location.pathname + '#/create-live-course?type=add'} onClick={this.props.onClose}>没有找到需要的直播课?<span>去创建</span></a>
:
<a target='_blank' className="link-create-course" href="https://dev.xiaomai5.com/xiaomai-cloud-class-web/index.html#/create-video-course?type=add">没有找到需要的视频课?<span>去创建</span></a>
<a target='_blank' className="link-create-course" href={window.location.origin + window.location.pathname + '#/create-video-course?type=add'} onClick={this.props.onClose}>没有找到需要的视频课?<span>去创建</span></a>
,
<Button
onClick={() => {
......
......@@ -5,6 +5,9 @@
.ant-tabs-nav-list{
margin:0 auto;
}
.ant-tabs-tab.ant-tabs-tab-active .ant-tabs-tab-btn{
font-weight:normal;
}
.ant-tabs-nav .ant-tabs-tab{
padding:6px 12px !important;
margin:0;
......@@ -19,9 +22,10 @@
border-radius: 0px 4px 4px 0px;
}
}
.ant-tabs-nav .ant-tabs-tab-active{
border: 1px solid #FFB714;
color:#FFB714;
border: 1px solid #FFB714;
color:#FFB714;
}
.ant-tabs-top .ant-tabs-ink-bar-animated:after{
......
/*
* @Author: 吴文洁
* @Date: 2019-07-10 10:30:49
* @LastEditors: zhangleyuan
* @LastEditTime: 2021-03-09 18:23:29
* @LastEditors: wufan
* @LastEditTime: 2021-03-11 17:22:01
* @Description:
*/
import React, { useContext, useEffect, useState } from 'react';
......@@ -29,9 +29,9 @@ const App: React.FC = (props: any) => {
useEffect(() => {
getStoreAndUserInfo();
window.RCHistory.push({
pathname: `/switch-route`,
})
// window.RCHistory.push({
// pathname: `/switch-route`,
// })
}, [])
async function getStoreAndUserInfo() {
......
......@@ -182,6 +182,7 @@
height: 49px;
display: flex;
position: relative;
align-items: center;
.store-name {
font-size: 14px;
color: #666;
......@@ -191,16 +192,13 @@
text-overflow: ellipsis;
overflow: hidden;
max-width: 230px;
margin-right: 32px;
margin-right: 16px;
}
.line {
width: 1px;
height: 16px;
background-color: #f4f4f4;
position: absolute;
left: 122px;
top: 50%;
transform: translateY(-50%);
margin-right:16px;
}
.link-to-store {
display: flex;
......
.employee-add-modal {
.ant-modal-body {
height: 247px;
}
.mt-4 {
margin-bottom:-6px !important
}
......
......@@ -10,7 +10,7 @@
import React from "react";
import { withRouter } from "react-router-dom";
import _ from "underscore";
import PhotoClip from 'photoclip'
// import PhotoClip from 'photoclip'
import { Table, Modal, message, Button } from "antd";
import StoreService from "@/domains/store-domain/storeService";
import {
......
......@@ -4,7 +4,7 @@ import { Form, Input, Button, Checkbox ,Select,Modal,message} from 'antd';
import {industryList,childIndustryList} from '@/domains/store-domain/constants'
import SelectPrepareFileModal from '@/modules/prepare-lesson/modal/SelectPrepareFileModal';
import Upload from '@/core/upload';
import PhotoClip from 'photoclip';
// import PhotoClip from 'photoclip';
import StoreService from "@/domains/store-domain/storeService";
import User from "@/common/js/user";
import Bus from '@/core/tbus';
......@@ -15,11 +15,11 @@ class StoreInfo extends React.Component {
constructor(props) {
super(props);
this.state = {
storeName:'',
storeFullName:'',
subjectType:'',
corpIndustry:'',
corpSubIndustry:'',
storeName:null,
storeFullName:null,
subjectType:null,
corpIndustry:null,
corpSubIndustry:null,
logo:'',
showSelectFileModal:false,
cutImageBlob: null,
......@@ -196,8 +196,8 @@ class StoreInfo extends React.Component {
message.warning('请选择店铺类型');
return;
}
if(!subjectType){
message.warning('店铺所属行业');
if(!corpIndustry){
message.warning('请选择店铺所属行业');
return;
}
const params= {
......@@ -248,9 +248,11 @@ class StoreInfo extends React.Component {
{ logo ? <img src={logo} className="logo-img"/> : <div className="logo-box"><span className="text">Logo</span></div>}
</div>
<div className="operate-con">
<div><span onClick={() => {this.setState({ showSelectFileModal:true })}} className="upload-btn">上传</span></div>
<div><span onClick={() => {this.setState({ showSelectFileModal:true })}} className="upload-btn">
{logo ? <span>重新上传</span> : <span>上传</span> }
</span></div>
<div className="tip">建议尺寸702*180px。最大2M,支持jpg、jpeg和png。</div>
</div>
</div>
</div>
</Form.Item>
<Form.Item
......
/*
* @Author: wufan
* @Date: 2020-11-30 10:47:38
* @LastEditors: wufan
* @LastEditTime: 2021-01-18 14:59:57
* @LastEditors: zhangleyuan
* @LastEditTime: 2021-03-11 15:30:00
* @Description: web店铺banner页面
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
......@@ -10,7 +10,7 @@
import React from "react";
import { withRouter } from "react-router-dom";
import _ from "underscore";
import PhotoClip from 'photoclip'
// import PhotoClip from 'photoclip'
import { Table, Modal, message, Button } from "antd";
import StoreService from "@/domains/store-domain/storeService";
import {
......
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