Commit 9be455f1 by chenshu

fix:merge

parents aaad704c 042c9ae5
@font-face {
font-family: 'iconfont'; /* project id 2223403 */
src: url('//at.alicdn.com/t/font_2223403_qb6r10go4s.eot');
src: url('//at.alicdn.com/t/font_2223403_qb6r10go4s.eot?#iefix') format('embedded-opentype'),
url('//at.alicdn.com/t/font_2223403_qb6r10go4s.woff2') format('woff2'),
url('//at.alicdn.com/t/font_2223403_qb6r10go4s.woff') format('woff'),
url('//at.alicdn.com/t/font_2223403_qb6r10go4s.ttf') format('truetype'),
url('//at.alicdn.com/t/font_2223403_qb6r10go4s.svg#iconfont') format('svg');
src: url('//at.alicdn.com/t/font_2223403_325yz7wxu2d.eot');
src: url('//at.alicdn.com/t/font_2223403_325yz7wxu2d.eot?#iefix') format('embedded-opentype'),
url('//at.alicdn.com/t/font_2223403_325yz7wxu2d.woff2') format('woff2'),
url('//at.alicdn.com/t/font_2223403_325yz7wxu2d.woff') format('woff'),
url('//at.alicdn.com/t/font_2223403_325yz7wxu2d.ttf') format('truetype'),
url('//at.alicdn.com/t/font_2223403_325yz7wxu2d.svg#iconfont') format('svg');
}
.iconfont{
font-family:"iconfont" !important;
......
/*
* @Author: wufan
* @Date: 2020-12-12 11:57:10
* @LastEditors: wufan
* @LastEditTime: 2021-01-06 20:18:16
* @LastEditors: zhangleyuan
* @LastEditTime: 2021-03-05 17:20:29
* @Description: Description
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
......@@ -52,6 +52,11 @@ export function turnOnOrOffLiveCloudCourse(params: object) {
export function delLiveCloudCourse(params: object) {
return Service.Hades("public/courseCloud/delLiveCloudCourse", params);
}
//该接口主要用于培训计划关联直播课的接口(会筛选掉已关联的直播课)
export function getLiveCloudCourseBasePage(params: object) {
return Service.Hades("public/courseCloud/getLiveCloudCourseBasePage", params);
}
//视频课相关接口
export function changeVideoShelfState(params: object) {
return Service.Hades("public/hades/changeVideoShelfState", params);
......@@ -77,3 +82,9 @@ export function videoSchedulePage(params: object) {
export function videoWatchInfo(params: object) {
return Service.Hades("public/hades/videoWatchInfo", params);
}
export function videoScheduleBasePage(params: object) {
return Service.Hades("public/hades/videoScheduleBasePage", params);
}
export function relatedCourseToPlan(params: object) {
return Service.Hades("public/hades/relatedCourseToPlan", params);
}
\ No newline at end of file
/*
* @Author: zhangleyuan
* @Date: 2021-02-21 16:08:38
* @LastEditors: zhangleyuan
* @LastEditTime: 2021-03-09 12:54:31
* @Description: 描述一下
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import Service from "@/common/js/service";
export function getTrainingPlanPage(params: object) {
return Service.Hades("public/hades/getTrainingPlanPage", params);
}
export function createTrainingPlan(params: object) {
return Service.Hades("public/hades/createTrainingPlan", params);
}
export function updateStateTrainingPlan(params: object) {
return Service.Hades("public/hades/updateStateTrainingPlan", params);
}
export function getTrainingPlanDetail(params: object) {
return Service.Hades("public/hades/getTrainingPlanDetail", params);
}
export function updateTrainingPlan(params: object) {
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);
}
export function getPlanCustomerDetail(params: object) {
return Service.Hades("public/hades/getPlanCustomerDetail", params);
}
export function getPlanCustomerAboutUser(params: object) {
return Service.Hades("public/hades/getPlanCustomerAboutUser", params);
}
export function removePlanCustomer(params: object) {
return Service.Hades("public/hades/removePlanCustomer", params);
}
export function getStorePlanAll(params: object) {
return Service.Hades("public/hades/getStorePlanAll", params);
}
export function getTrainingCourseAutoCancel(params: object) {
return Service.Hades("public/hades/getTrainingCourseAutoCancel", params);
}
\ No newline at end of file
/*
* @Author: wufan
* @Date: 2020-11-25 18:25:02
* @LastEditors: wufan
* @LastEditTime: 2021-01-11 19:38:50
* @LastEditors: zhangleyuan
* @LastEditTime: 2021-03-09 10:28:03
* @Description: Description
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
......@@ -68,3 +68,11 @@ export function delCourseCategory(params: object) {
export function getStoreUserBasicPage(params: object) {
return Service.Hades("public/hades/getStoreUserBasicPage", params);
}
export function updateStoreMessage(params: object) {
return Service.Hades("public/hades/updateStoreMessage", params);
}
export function getStoreDetail(params: object) {
return Service.Hades("public/hades/getStoreDetail", params);
}
/*
* @Author: 陈剑宇
* @Date: 2020-05-07 14:43:01
* @LastEditTime: 2021-01-28 16:28:08
* @LastEditTime: 2021-03-01 10:09:42
* @LastEditors: zhangleyuan
* @Description:
* @FilePath: /wheat-web-demo/src/domains/basic-domain/constants.ts
......
/*
* @Author: wufan
* @Date: 2020-11-25 18:25:02
* @LastEditors: wufan
* @LastEditTime: 2021-01-06 20:17:40
* @LastEditors: zhangleyuan
* @LastEditTime: 2021-03-05 17:20:56
* @Description: Description
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import {
fetchLecturerData, fetchUserData, exportStudentCourseData, exportPlayBackCourseData, fetchPlaybackList, createLiveCloudCourse, getLiveCloudCoursePage,
getLiveCloudCourseDetail, updateLiveCloudCourse, turnOnOrOffLiveCloudCourse, delLiveCloudCourse, changeVideoShelfState, createVideoSchedule, delVideoSchedule, editVideoSchedule, userWatchInfo, videoSchedulePage, videoScheduleDetail, videoWatchInfo, getQrcode
getLiveCloudCourseDetail, updateLiveCloudCourse, turnOnOrOffLiveCloudCourse, delLiveCloudCourse, changeVideoShelfState, createVideoSchedule, delVideoSchedule,
editVideoSchedule, userWatchInfo, videoSchedulePage, videoScheduleDetail, videoWatchInfo, getQrcode,getLiveCloudCourseBasePage,videoScheduleBasePage,relatedCourseToPlan
} from '@/data-source/course/request-api';
export default class courseService {
......@@ -84,4 +85,13 @@ export default class courseService {
static videoWatchInfo(params: any) {
return videoWatchInfo(params);
}
static getLiveCloudCourseBasePage(params: any){
return getLiveCloudCourseBasePage(params);
}
static videoScheduleBasePage(params: any){
return videoScheduleBasePage(params);
}
static relatedCourseToPlan(params: any){
return relatedCourseToPlan(params);
}
}
\ No newline at end of file
......@@ -2,7 +2,7 @@
* @Author: 吴文洁
* @Date: 2020-08-20 09:21:40
* @LastEditors: zhangleyuan
* @LastEditTime: 2021-01-27 19:53:17
* @LastEditTime: 2021-02-20 17:08:58
* @Description:
* @Copyright: 杭州杰竞科技有限公司 版权所有
*/
......
/*
* @Author: zhangleyuan
* @Date: 2021-02-21 16:15:38
* @LastEditors: zhangleyuan
* @LastEditTime: 2021-03-09 12:54:46
* @Description: 描述一下
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import {getTrainingPlanPage,createTrainingPlan,updateStateTrainingPlan,getTrainingPlanDetail,updateTrainingPlan,deleteTrainingPlan,getPlanUserRecordPage,getPlanCustomerRecordPage,getPlanCustomerDetail,getPlanCustomerAboutUser,removePlanCustomer,getStorePlanAll,getTrainingCourseAutoCancel} from '@/data-source/plan/request-apis';
export default class PlanService {
// 获取员工列表
static getTrainingPlanPage(params: any) {
return getTrainingPlanPage(params);
}
static createTrainingPlan(params: any) {
return createTrainingPlan(params);
}
static updateStateTrainingPlan(params: any) {
return updateStateTrainingPlan(params);
}
static getTrainingPlanDetail(params: any) {
return getTrainingPlanDetail(params);
}
static updateTrainingPlan(params: any) {
return updateTrainingPlan(params);
}
static deleteTrainingPlan(params: any) {
return deleteTrainingPlan(params);
}
static getPlanUserRecordPage(params: any) {
return getPlanUserRecordPage(params);
}
static getPlanCustomerRecordPage(params: any) {
return getPlanCustomerRecordPage(params);
}
static getPlanCustomerDetail(params: any) {
return getPlanCustomerDetail(params);
}
static getPlanCustomerAboutUser(params: any) {
return getPlanCustomerAboutUser(params);
}
static removePlanCustomer(params: any) {
return removePlanCustomer(params);
}
static getStorePlanAll(params: any) {
return getStorePlanAll(params);
}
static getTrainingCourseAutoCancel(params: any) {
return getTrainingCourseAutoCancel(params);
}
}
\ No newline at end of file
/*
* @Author: zhangleyuan
* @Date: 2021-01-19 11:27:56
* @LastEditors: zhangleyuan
* @LastEditTime: 2021-03-08 10:36:04
* @Description: 描述一下
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
export const storeRoleEnum = {
"0": "店铺管理员",
"1": "管理员",
"2": "普通讲师"
};
export const industryList = ["IT服务","制造业","批发/零售","生活服务","文化/体育/娱乐业","建筑/房地产","教育","运输/物流/仓储","医疗","政府","金融","能源/采矿","农林渔牧","其他行业"];
export const childIndustryList = {
"IT服务":["计算机软件/硬件/信息服务","互联网和相关服务","其他"],
"制造业":["机械/电子","服装/纺织","汽车","金属制品","家具/家纺","重工制造","家电/数码","橡胶/塑料","日用品/化妆品","化学原料制品","文教/工美/体育/娱乐用品","烟酒/茶","非金属矿物","其他"],
"批发/零售":["批发","零售","超市/便利店/百货商场","进出口","其他"],
"生活服务":["餐饮","居民服务","租赁和商务服务","酒店/住宿","其他"],
"文化/体育/娱乐业":["文化/体育","娱乐/旅游","新闻传媒","其他"],
"建筑/房地产":["建筑业","建材装修","房地产","其他"],
"教育":["学前教育","初中等教育","高等教育","培训机构","其他"],
"运输/物流/仓储":["物流/仓储","道路/铁路运输","邮政/快递","航空运输","水上运输","其他"],
"医疗":["医院/医疗机构","医疗器械","医药制造","医药流通","其他"],
"政府":["党政机关","国家权利/行政机构","检察院/法院/公安","民政/人社/交通/卫生","发改委/经信委/商务局/统计局","国土/规划","税务/海关/工商/环保/物价/药品","政协/民主党派","地方政府","其他"],
"金融":["保险","银行","证券/投资/基金","其他"],
"能源/采矿":["电力/热力/燃气/水供应业","石油/天然气","煤炭","有色金属","钢铁","其他"],
"农林渔牧":["农林渔牧"],
"其他行业":["科学研究和技术服务业","社会组织","水利和环境管理","国际组织","其他"]
}
\ No newline at end of file
......@@ -2,11 +2,13 @@
* @Author: wufan
* @Date: 2020-11-25 18:25:02
* @LastEditors: zhangleyuan
* @LastEditTime: 2020-12-23 16:54:10
* @LastEditTime: 2021-03-08 11:48:43
* @Description: Description
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import { getEmployeeList, getUserList, getStoreDecorationList, getStoreRole, addEmployee, editEmployee, deleteEmployee, getCourseCatalogList, getAllSonCategory, addCourseCategory, delCourseCategory, editCourseCategory, deleteStoreDecorationList, addStoreBanner, editStoreBanner, moveBannerSequence,getStoreUserBasicPage} from '@/data-source/store/request-apis';
import { getEmployeeList, getUserList, getStoreDecorationList, getStoreRole, addEmployee, editEmployee, deleteEmployee, getCourseCatalogList,
getAllSonCategory, addCourseCategory, delCourseCategory, editCourseCategory, deleteStoreDecorationList, addStoreBanner, editStoreBanner,
moveBannerSequence,getStoreUserBasicPage,updateStoreMessage,getStoreDetail} from '@/data-source/store/request-apis';
export default class StoreService {
// 获取员工列表
......@@ -81,5 +83,10 @@ export default class StoreService {
static delCourseCategory(params: any) {
return delCourseCategory(params);
}
static updateStoreMessage(params: any) {
return updateStoreMessage(params);
}
static getStoreDetail(params: any) {
return getStoreDetail(params);
}
}
\ No newline at end of file
<!--
* @Author: 吴文洁
* @Date: 2020-08-24 12:20:57
* @LastEditors: wufan
* @LastEditTime: 2021-01-12 13:52:14
* @LastEditors: zhangleyuan
* @LastEditTime: 2021-03-02 15:16:04
* @Description:
* @Copyright: 杭州杰竞科技有限公司 版权所有
-->
......
<!--
* @Author: 吴文洁
* @Date: 2020-08-24 12:20:57
* @LastEditors: wufan
* @LastEditTime: 2021-01-18 21:18:43
* @LastEditors: zhangleyuan
* @LastEditTime: 2021-03-02 15:16:11
* @Description:
* @Copyright: 杭州杰竞科技有限公司 版权所有
-->
......
......@@ -15,7 +15,7 @@ import DownloadLiveModal from '@/components/DownloadLiveModal';
import ManageCoursewareModal from '../modal/ManageCoursewareModal';
import ShareLiveModal from '../modal/ShareLiveModal';
import RelatedPlanModal from '../modal/RelatedPlanModal';
import './LiveCourseList.less';
import { QuestionCircleOutlined } from '@ant-design/icons';
......@@ -56,7 +56,9 @@ class LiveCourseList extends React.Component {
this.state = {
columns: [],
openDownloadModal:false,
url:''
url:'',
RelatedPlanModalVisible:false,
selectPlanList:{}
}
}
componentWillMount(){
......@@ -271,6 +273,37 @@ class LiveCourseList extends React.Component {
},
},
{
title: '创建时间',
width: "9%",
key: "created",
dataIndex: "created",
sorter: true,
render: (val, item) => {
return (
<span>{formatDate('YYYY-MM-DD H:i', val)}</span>
);
},
},
{
title: '关联项',
width: "15%",
key: "planList",
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>
)
},
},
{
title: "操作",
width: "15%",
key: "operate",
......@@ -456,11 +489,39 @@ class LiveCourseList extends React.Component {
);
},
},
{
title: '创建时间',
width: "9%",
key: "created",
dataIndex: "created",
sorter: true,
render: (val, item) => {
return (
<span>{formatDate('YYYY-MM-DD H:i', val)}</span>
);
},
},
{
title: '关联项',
width: "15%",
key: "planList",
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>
)
},
},
];
}
this.setState({ columns })
}
handleAdminName = (adminArray)=>{
......@@ -477,6 +538,12 @@ class LiveCourseList extends React.Component {
renderMoreOperate = (item) => {
return (
<div className="live-course-more-menu">
{ (User.getUserRole() === "CloudManager" || User.getUserRole() === "StoreManager") &&
<div
className="operate__item"
onClick={()=>this.handleRelatedModalShow(item)}
>关联培训计划</div>
}
<div
className="operate__item"
onClick={()=>this.toEditCoursePage(item)}
......@@ -597,14 +664,65 @@ class LiveCourseList extends React.Component {
}
window.open(htmlUrl);
}
handleRelatedModalShow = (item)=>{
const selectPlanList = {};
if(item.relatedPlanList){
item.relatedPlanList.map((item,index)=>{
selectPlanList[item.planId] = {}
selectPlanList[item.planId].planId = item.planId;
selectPlanList[item.planId].taskBaseVOList = [{taskId:item.taskId}];
return item
})
}
this.setState({
RelatedPlanModalVisible:true,
selectCourseId:item.liveCourseId,
selectPlanList:selectPlanList
})
}
closeRelatedPlanModalVisible = ()=>{
this.setState({
RelatedPlanModalVisible:false
})
}
onChangeSelectPlanList = (selectPlanList)=>{
this.setState({
selectPlanList:selectPlanList
})
}
onConfirmSelectPlanList = ()=>{
this.setState({
RelatedPlanModalVisible:false
},()=>{this.props.onChange();})
}
handleChangeTable = (pagination, filters, sorter) => {
const { columnKey, order } = sorter;
const { query } = this.props;
let _columnKey;
let _order;
// 按创建时间升序排序
if (columnKey === 'created' && order === 'ascend') {_columnKey="CREATED"; _order = 'SORT_ASC'; }
// 按创建时间降序排序
if (columnKey === 'created' && order === 'descend') { _columnKey="CREATED"; _order = 'SORT_DESC';}
const _query = {
...query,
sortMap:{}
};
_query.sortMap[_columnKey]=_order;
this.props.onChange(_query);
}
render() {
const { total, query, courseList, loading} = this.props;
const { current, size } = query;
const { openDownloadModal,
downloadUrl, url, columns,
openCoursewareModal,
editData
editData,
RelatedPlanModalVisible,
selectCourseId,
selectPlanList
} = this.state;
const { match } = this.props;
......@@ -617,6 +735,7 @@ class LiveCourseList extends React.Component {
columns={columns}
loading={loading}
dataSource={courseList}
onChange={this.handleChangeTable}
rowKey={(row) => row.liveCourseId}
/>
{ total>0 &&
......@@ -655,6 +774,16 @@ class LiveCourseList extends React.Component {
}}
/>
)}
{ RelatedPlanModalVisible &&
<RelatedPlanModal
onClose={this.closeRelatedPlanModalVisible}
visible={RelatedPlanModalVisible}
selectCourseId={selectCourseId}
selectPlanList={selectPlanList}
onChange={this.onChangeSelectPlanList}
onConfirm={this.onConfirmSelectPlanList}
/>
}
<iframe src={url} style={{ display: "none" }} />
<Route path={`${match.url}/live-course-data`} component={DataList} />
</div>
......
import React from 'react';
import {Table, Modal,Input} from 'antd';
import { PageControl } from "@/components";
import CourseService from "@/domains/course-domain/CourseService";
import PlanService from "@/domains/plan-domain/planService";
import User from '@/common/js/user'
import './RelatedPlanModal.less';
import _ from "underscore";
const { Search } = Input;
class RelatedPlanModal extends React.Component {
constructor(props) {
super(props);
this.state = {
dataSource:[],
size:10,
query: {
current: 1,
},
totalCount:0,
selectPlanList:{},
};
}
componentDidMount() {
this.handleFetchDataList();
}
// 获取培训计划列表
handleFetchDataList = () => {
const {query,size,totalCount} = this.state
const params ={
...query,
size,
storeId:User.getStoreId()
}
PlanService.getStorePlanAll(params).then((res) => {
const { result = {} } = res ;
const { records = [], total = 0 } = result;
this.setState({
dataSource: records,
totalCount: Number(total)
});
});
}
handleChangePlanName = (value)=>{
const {query} = this.state;
query.planName = value;
query.current = 1;
this.setState({
query
})
}
onShowSizeChange = (current, size) => {
if (current == size) {
return
}
this.setState({
size
},()=>{this.handleFetchDataList()})
}
// 请求表头
parsePlanColumns = () => {
const columns = [
{
title: '培训计划',
key: 'planName',
dataIndex: 'planName',
render:(val,record)=>{
return (
<span>{val}</span>
)
}
}
];
return columns;
}
parseTaskColumns = (parentIndex) => {
const columns = [
{
title: '任务名称',
key: 'taskName',
dataIndex: 'taskName',
render:(val,record)=>{
return (
<span>{val}</span>
)
}
}
];
return columns;
}
selectPlanList = (record,selected,planId) =>{
const { selectPlanList } = this.props;
let _selectPlanList = {...selectPlanList};
if (selected) {
if(!_selectPlanList[planId]){
_selectPlanList[planId] = {}
}
_selectPlanList[planId].taskBaseVOList = [];
_selectPlanList[planId].planId = planId;
_selectPlanList[planId].taskBaseVOList.push(record);
} else {
if(!_selectPlanList[planId]){
_selectPlanList[planId] = {}
}
_selectPlanList[planId].taskBaseVOList = [];
_selectPlanList[planId].planId = planId;
}
this.props.onChange(_selectPlanList);
// this.setState({selectPlanList:_selectPlanList});
}
handleSelectPlanListData(selectPlanList){
let _selectPlanList = [];
for(let key in selectPlanList ){
let item = {};
if(selectPlanList[key].taskBaseVOList){
item.planId = selectPlanList[key].planId;
if(selectPlanList[key].taskBaseVOList[0]){
item.taskId = selectPlanList[key].taskBaseVOList[0].taskId;
}
}
_selectPlanList.push(item)
}
return _selectPlanList;
}
confirmRelatedPlan =()=>{
const {selectPlanList } = this.props;
const params = {
courseId:this.props.selectCourseId,
relatedPlanList:this.handleSelectPlanListData(selectPlanList),
storeId:User.getStoreId(),
}
CourseService.relatedCourseToPlan(params).then((res) => {
this.props.onConfirm();
});
}
getSelectLength = (selectList)=>{
let num = 0;
for(let key in selectList ){
if(selectList[key].taskBaseVOList){
num = num + 1
}
}
return num;
}
clearSelect = ()=>{
const _selectPlanList = {};
this.props.onChange(_selectPlanList);
}
render() {
const { size,dataSource,totalCount,query} = this.state;
const { visible,selectPlanList} = this.props;
return (
<Modal
title="关联培训计划"
onCancel={this.props.onClose}
maskClosable={false}
visible={visible}
className="related-plan-modal"
closable={true}
width={800}
onOk={() => this.confirmRelatedPlan() }
closeIcon={<span className="icon iconfont modal-close-icon">&#xe6ef;</span>}
>
<div className="search-container">
<Search placeholder="搜索培训计划名称"
style={{ width: 207 }}
onChange={(e) => { this.handleChangePlanName(e.target.value)}}
onSearch={ () => { this.handleFetchDataList()}}
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>
<div>
<Table
rowKey={record => record.planId}
className="plan-table"
dataSource={dataSource}
columns={this.parsePlanColumns()}
pagination={false}
expandedRowRender={(_record,index) => {
if(!_record.taskBaseVOList){
return
}
if (_record.taskBaseVOList.length !== 0 ){
const selectPlan = selectPlanList[_record.planId]
let taskBaseVOList = [];
if(selectPlan){
taskBaseVOList = selectPlan.taskBaseVOList;
}
console.log('taskBaseVOList',taskBaseVOList);
return <div>
<Table
rowKey={record => record.taskId}
pagination={false}
dataSource={_record.taskBaseVOList}
columns={this.parseTaskColumns(index)}
className="child-table"
rowSelection={{
type: 'checkbox',
selectedRowKeys: _.pluck(taskBaseVOList, 'taskId'),
onSelect: (record, selected) => {
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});
},
}}
/>
</div>
}
}}
rowClassName={(record,index)=>{if(index%2===0){return 'odd-row'}else{ return 'even-row'}}}
/>
{dataSource.length >0 &&
<div className="box-footer">
<PageControl
current={query.current - 1}
pageSize={size}
total={totalCount}
toPage={(page) => {
const _query = {...query, current: page + 1};
this.setState({
query:_query
},()=>{ this.handleFetchDataList()})
}}
onShowSizeChange={this.onShowSizeChange}
/>
</div>
}
</div>
</Modal>
)
}
}
export default RelatedPlanModal;
\ No newline at end of file
.related-plan-modal{
.search-container{
margin-bottom:16px;
}
.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;
}
}
.plan-table{
.taskName{
color:#666666;
font-size:14px;
}
.task-learn-percentage{
color:#666666;
font-size:14px;
}
.course-info{
margin-left:57px;
.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;
}
}
.ant-table-content{
border:1px solid #e8e8e8;
tr{
td{
border:none;
}
.child-table{
.ant-table-content{
border:none;
thead{
display:none;
}
tbody tr td{
border-bottom:none;
}
}
}
}
.odd-row{
background:transparent;
td{
background: #FFF;
}
& + .ant-table-expanded-row{
background:transparent;
td{
background: #FFF;
}
}
&:hover{
& + .ant-table-expanded-row{
background:transparent;
td{
background: #F3f6fa !important;
}
}
}
}
.even-row{
background:transparent;
td{
background: #FAFAFA;
}
& + .ant-table-expanded-row{
background:transparent;
td{
background: #FAFAFA;
}
}
&:hover{
& + .ant-table-expanded-row{
background:transparent;
td{
background: #F3f6fa !important;
}
}
}
}
}
}
}
\ No newline at end of file
......@@ -2,7 +2,7 @@
* @Author: 吴文洁
* @Date: 2020-08-05 10:12:45
* @LastEditors: zhangleyuan
* @LastEditTime: 2021-02-01 16:34:11
* @LastEditTime: 2021-03-10 15:53:11
* @Description: 视频课-列表模块
* @Copyright: 杭州杰竞科技有限公司 版权所有
*/
......@@ -17,21 +17,23 @@ import { appId, shareUrl, LIVE_SHARE } from '@/domains/course-domain/constants';
import ShareLiveModal from '@/modules/course-manage/modal/ShareLiveModal';
import WatchDataModal from '../modal/WatchDataModal'
import CourseService from "@/domains/course-domain/CourseService";
import RelatedPlanModal from '../../modal/RelatedPlanModal';
import User from '@/common/js/user'
import './VideoCourseList.less';
const ENV = process.env.DEPLOY_ENV || 'dev';
const userRole = User.getUserRole();
class VideoCourseList extends React.Component {
constructor(props) {
super(props);
this.state = {
id: '', // 视频课ID
studentIds:[]
studentIds:[],
RelatedPlanModalVisible:false,
selectPlanList:{}
}
}
......@@ -166,6 +168,25 @@ class VideoCourseList extends React.Component {
}
},
{
title: '关联项',
width: 200,
key: "planList",
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>
)
}
},
{
title: '操作',
key: 'operate',
dataIndex: 'operate',
......@@ -200,6 +221,12 @@ class VideoCourseList extends React.Component {
renderMoreOperate = (item) => {
return (
<div className="live-course-more-menu">
{ (User.getUserRole() === "CloudManager" || User.getUserRole() === "StoreManager") &&
<div
className="operate__item"
onClick={()=>this.handleRelatedModalShow(item)}
>关联培训计划</div>
}
<div
className="operate__item"
onClick={() => {
......@@ -237,6 +264,7 @@ class VideoCourseList extends React.Component {
}
})
}
// 删除视频课
handleDeleteVideoCourse = (scheduleId) => {
Modal.confirm({
......@@ -314,12 +342,42 @@ class VideoCourseList extends React.Component {
};
this.props.onChange(_query);
}
handleRelatedModalShow = (item)=>{
const selectPlanList = {};
if(item.relatedPlanList){
item.relatedPlanList.map((item,index)=>{
selectPlanList[item.planId] = {}
selectPlanList[item.planId].planId = item.planId;
selectPlanList[item.planId].taskBaseVOList = [{taskId:item.taskId}];
return item
})
}
this.setState({
RelatedPlanModalVisible:true,
selectCourseId:item.id,
selectPlanList:selectPlanList
})
}
closeRelatedPlanModalVisible = ()=>{
this.setState({
RelatedPlanModalVisible:false
})
}
onChangeSelectPlanList = (selectPlanList)=>{
this.setState({
selectPlanList:selectPlanList
})
}
onConfirmSelectPlanList = ()=>{
this.setState({
RelatedPlanModalVisible:false
},()=>{this.props.onChange();})
}
render() {
const { dataSource = [], totalCount, query } = this.props;
const { current, size } = query;
const {RelatedPlanModalVisible,selectPlanList,selectCourseId} = this.state;
return (
<div className="video-course-list">
<Table
......@@ -344,6 +402,16 @@ class VideoCourseList extends React.Component {
}}
/>
</div>
{ RelatedPlanModalVisible &&
<RelatedPlanModal
onClose={this.closeRelatedPlanModalVisible}
visible={RelatedPlanModalVisible}
selectCourseId={selectCourseId}
selectPlanList={selectPlanList}
onChange={this.onChangeSelectPlanList}
onConfirm={this.onConfirmSelectPlanList}
/>
}
{ this.state.shareLiveModal }
{ this.state.watchDataModal }
</div>
......
/*
* @Author: zhangleyuan
* @Date: 2020-11-27 15:06:31
* @LastEditors: wufan
* @LastEditTime: 2021-02-01 14:34:44
* @LastEditors: zhangleyuan
* @LastEditTime: 2021-03-09 14:22:10
* @Description: 描述一下
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
......@@ -95,12 +95,14 @@ function PersonalInfoPage() {
phone: String(phone),
roleCodes: roleCodes,
avatar,
storeUserId: User.getStoreUserId()
storeUserId: User.getStoreUserId(),
storeId:User.getStoreId()
} : {
nickName,
roleCodes: roleCodes,
avatar,
storeUserId: User.getStoreUserId()
storeUserId: User.getStoreUserId(),
storeId:User.getStoreId()
};
StoreService.editEmployee(params).then((res) => {
......
/*
* @Author: zhangleyuan
* @Date: 2021-02-20 16:13:39
* @LastEditors: zhangleyuan
* @LastEditTime: 2021-03-10 16:51:57
* @Description: 描述一下
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import React, { useEffect, useState } from "react";
import { Button, message, Modal} from 'antd';
import ShowTips from "@/components/ShowTips";
import Breadcrumbs from "@/components/Breadcrumbs";
import BasicInfo from './components/BasicInfo';
import TrainingTask from './components/TrainingTask';
import ExpiredCourseList from './components/ExpiredCourseList';
import PlanService from '@/domains/plan-domain/planService'
import User from '@/common/js/user';
import _ from "underscore";
import './AddPlan.less'
const defaultCover = 'https://image.xiaomaiketang.com/xm/YNfi45JwFA.png';
const defaultBasicData = {
planName:"",
coverUrl: defaultCover,
coverId:null,
enableState:"YES",
selectOperatorList:[],
instro:'',
operateType:'All_Operate',
percentCompleteLive:80,
percentCompleteVideo:80,
}
const defaultTaskList = [];
function AddPlan() {
const id = getParameterByName("id");
const type = getParameterByName("type");
const [basicData,setBasicData] = useState(defaultBasicData);
const [taskList,setTaskList] = useState(defaultTaskList);
const [expiredCourseList,setExpiredCourseList] = useState([]);
useEffect(()=>{
if(type==='edit'){
getPlanDetail();
getPlanCustomerState();
}
},id)
function getPlanCustomerState(){
PlanService.getTrainingCourseAutoCancel({
planId: id
}).then((res) => {
const expiredCourseList = res.result;
setExpiredCourseList(expiredCourseList)
})
}
function getPlanDetail (){
PlanService.getTrainingPlanDetail({
planId: id
}).then((res) => {
const {
planName,
enableState,
operateType,
operateIds,
percentCompleteLive,
percentCompleteVideo,
courseMediaVOS,
trainingTaskList
} = res.result;
let coverId;
let coverUrl;
let instro;
courseMediaVOS.map((item) => {
switch (item.contentType){
case "COVER":
coverId = item.mediaContent;
coverUrl = item.mediaUrl;
break;
case "INTRO":
instro = item.mediaContent;
break;
default:
break;
}
return item;
})
let _selectOperatorList = [];
if(operateIds){
_selectOperatorList = operateIds.map((item,index)=>{
let _item = {};
_item.id = item;
return _item
})
}
setBasicData({
planName,
coverUrl:coverUrl || defaultCover,
coverId,
enableState,
selectOperatorList:_selectOperatorList,
instro,
operateType,
percentCompleteLive,
percentCompleteVideo
})
setTaskList(trainingTaskList)
})
}
function handleChangeBasicInfo(field, value){
setBasicData( {
...basicData,
[field]: value,
})
}
function handleChangeTaskInfo(value){
setTaskList(value)
}
function submitInfo(){
const {planName,enableState,selectOperatorList,instro,operateType,percentCompleteLive,percentCompleteVideo,coverId,coverUrl} = basicData;
if(!planName){
message.warning('请输入的培训计划名称');
return;
}
if(operateType==='Assign_Operate' && selectOperatorList.length===0){
message.warning('请选择指定运营师');
return;
}
if(!percentCompleteLive && percentCompleteLive !==0 ){
message.warning('请输入完成标准');
return;
}
if(!percentCompleteVideo && percentCompleteVideo !==0 ){
message.warning('请输入完成标准');
return;
}
if(taskList.length === 0){
message.warning('请输入培训计划内容');
return;
}
let scheduleMediaRequests = [];
let coverObj ={
contentType:'COVER',
mediaContent:coverId,
mediaType:'PICTURE',
mediaUrl: coverUrl,
}
if(coverId){
scheduleMediaRequests = [...scheduleMediaRequests,coverObj];
}
let instroObj = {
contentType:"INTRO",
mediaType: 'TEXT',
mediaContent:instro,
}
if(instro){
scheduleMediaRequests = [...scheduleMediaRequests,instroObj];
}
const params = {
createId:User.getStoreUserId(),
enableState,
operateIds:_.pluck(selectOperatorList,'id'),
operateType,
percentCompleteLive,
percentCompleteVideo,
planName,
scheduleMediaRequests,
storeId:User.getStoreId(),
trainingTaskList:handleSubmitTaskData(taskList)
}
if (type === 'add') {
PlanService.createTrainingPlan(params).then((res) => {
if (res.success){
message.success("新建成功");
window.RCHistory.goBack();
}
});
}else{
const _params = {
...params,
id
}
PlanService.updateTrainingPlan(_params).then((res) => {
if (res.success){
message.success("更新成功");
window.RCHistory.goBack();
}
});
}
}
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 (){
if (!_.isEqual(basicData, defaultBasicData) || !_.isEqual(taskList, defaultTaskList)
) {
Modal.confirm({
title: '确定要返回吗?',
content: '返回后,本次编辑的内容将不被保存',
okText: '确认返回',
cancelText: '留在本页',
icon: <span className="icon iconfont default-confirm-icon">&#xe6f4;</span>,
onOk: () => {
window.RCHistory.goBack();
}
})
} else {
window.RCHistory.goBack();
}
}
return (
<div className="page add-plan-page">
<Breadcrumbs
navList={type == "add" ? "新建培训计划" : "编辑培训计划"}
goBack={handleGoBack}
/>
<div className="box">
<div className="show-tips">
<ShowTips message="请遵守国家相关规定,切勿上传低俗色情、暴力恐怖、谣言诈骗、侵权盗版等相关内容,小麦企培保有依据国家规定及平台规则进行处理的权利" />
</div>
<div className="add-plan-page__form">
<div className="basic-info__wrap">
<div className="title">基本信息</div>
<BasicInfo
data={basicData}
onChange={handleChangeBasicInfo}
/>
</div>
<div className="basic-info__wrap">
<div className="title">培训任务</div>
{ (type==='edit' && taskList.length>0) &&
<TrainingTask data={taskList} onChange={handleChangeTaskInfo} />
}
{ type==='add' &&
<TrainingTask data={taskList} onChange={handleChangeTaskInfo} />
}
</div>
{ (type==='edit' && expiredCourseList.length > 0) &&
<div className="expired-info__wrap">
<div className="title">失效课程</div>
<ExpiredCourseList expiredCourseList={expiredCourseList}/>
</div>
}
</div>
</div>
<div className="footer">
<Button onClick={handleGoBack}>取消</Button>
<Button type="primary" onClick={submitInfo}>保存</Button>
</div>
</div>
)
}
export default AddPlan;
\ No newline at end of file
.add-plan-page {
position:relative !important;
.box {
margin-bottom: 66px !important;
.add-plan-page__form {
margin-top: 16px;
.title {
font-size: 16px;
color: #333;
font-weight: 500;
line-height: 22px;
margin-bottom:8px;
}
}
.expired-info__wrap{
margin-top:16px;
}
}
.footer {
position: fixed;
bottom: 0;
height: 58px;
width: 100%;
display: flex;
align-items: center;
justify-content: flex-end;
padding-right: 252px;
background: #fff;
border-top: 1px solid #E8E8E8;
z-index: 9999;
.ant-btn {
margin-left: 10px;
}
}
}
\ No newline at end of file
import React from 'react';
import { withRouter } from "react-router-dom";
import { Tabs } from 'antd';
import Breadcrumbs from "@/components/Breadcrumbs";
import EmployeeShareData from './components/EmployeeShareData';
import UserLearningData from './components/UserLearningData';
import PlanService from '@/domains/plan-domain/planService';
import User from '@/common/js/user'
import Bus from '@/core/bus';
import './LearningData.less';
const userRole = User.getUserRole();
const defaultCover = 'https://image.xiaomaiketang.com/xm/YNfi45JwFA.png';
class LearningData extends React.Component {
constructor(props) {
super(props);
const id = getParameterByName("id");
this.state = {
id,
planName:"",
coverUrl:defaultCover,
courseNum:0,
created:"",
cultureCustomerNum:0,
activeKey:"employeeShareData",
createName:""
}
}
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,
createName
} = 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,
createName
})
})
}
render() {
const {planName,coverUrl,courseNum,created,cultureCustomerNum,activeKey,createName} = this.state;
return (
<div className="page plan-learn-data-list">
<Breadcrumbs
navList="学习数据"
goBack={() => {
RCHistory.goBack();
}}
/>
<div className="plan-info">
<div className="plan-intro">
<div className="plan-img-con">
<img src="https://image.xiaomaiketang.com/xm/YNfi45JwFA.png"/>
</div>
<div>
<div className="plan-name">
{planName}
</div>
<div className="create-course">
<span className="createUser">创建人:{createName}</span>
<span className="split">|</span>
<span className="course-total">课程总数量:{courseNum}</span>
</div>
<div className="create-time">创建时间:{formatDate('YYYY-MM-DD H:i', created)} </div>
</div>
</div>
<div className="join">
<div className="number">{cultureCustomerNum}</div>
<div className="text">参培人数</div>
</div>
</div>
<div className="box">
{ (User.getUserRole() === "CloudManager" || User.getUserRole() === "StoreManager")?
(<Tabs activeKey={activeKey} onChange={(activeKey)=>{this.setState({activeKey})}}>
<Tabs.TabPane tab="员工分享数据" key="employeeShareData">
<EmployeeShareData/>
</Tabs.TabPane>
<Tabs.TabPane tab="用户学习数据" key="userLearningData">
<UserLearningData/>
</Tabs.TabPane>
</Tabs>)
:
(<UserLearningData/>)
}
</div>
</div>
)
}
}
export default withRouter(LearningData);
\ No newline at end of file
.plan-learn-data-list{
.plan-info{
margin:16px;
padding:16px;
background: #FFF;
display:flex;
justify-content: space-between;
align-items: center;
.plan-intro{
display: flex;
align-items: center;
.plan-img-con{
margin-right:8px;
img{
width:136px;
height:77px;
}
}
.plan-name{
font-size: 16px;
font-weight: 500;
color: #333333;
line-height: 22px;
margin-bottom:8px;
}
.create-course{
font-size: 14px;
color: #666666;
.split{
margin:0 8px;
color:#666;
}
margin-bottom:4px;
}
.create-time{
font-size:14px;
color:#666;
}
}
.join{
margin-right:144px;
min-width:54px;
text-align:center;
.number{
font-size: 26px;
font-weight: 500;
color: #333333;
margin-botttom:4px;
}
.text{
font-size: 14px;
color:#999;
}
}
}
}
\ No newline at end of file
/*
* @Author: zhangleyuan
* @Date: 2021-02-20 16:13:39
* @LastEditors: zhangleyuan
* @LastEditTime: 2021-03-10 18:38:50
* @Description: 描述一下
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import React, { useEffect, useState } from "react";
import PlanFilter from './components/PlanFilter';
import PlanOpt from './components/PlanOpt';
import PlanList from './components/PlanList';
import PlanService from "@/domains/plan-domain/planService";
import User from '@/common/js/user';
function PlanPage() {
const [planListData, setPlanListData] = useState([]);
const [query,setQuery] = useState({
current:1,
size:10,
});
useEffect(() => {
handleFetchPlanList();
}, [query]);
const [totalCount,setTotalCount] = useState(0);
function queryChange(_query){
const params = {
...query,
..._query,
};
setQuery(params);
}
function handleFetchPlanList(_query){
const params = {
...query,
..._query,
storeUserId:User.getStoreUserId()
};
//动态获取计划列表
PlanService.getTrainingPlanPage(params).then((res) => {
const { result: { records = [], total } } = res;
setPlanListData(records);
setTotalCount(total);
})
}
return (
<div className="page">
<div className="content-header">培训计划</div>
<div className="box">
<PlanFilter onChange={queryChange}/>
<PlanOpt/>
<PlanList
planListData={planListData}
query={query}
totalCount={totalCount}
onChange={queryChange}
/>
</div>
</div>
)
}
export default PlanPage;
\ No newline at end of file
.plan-basic-info{
.label {
width: 110px;
text-align: right;
display:inline-block;
.require {
color: #EC4B35;
}
.iconfont{
font-size:14px;
color:#BFBFBF;
}
}
.cover {
display: flex;
margin-top: 16px;
&__wrap {
position: relative;
.tag {
border-radius: 2px;
background: #D6D6D6;
font-size: 12px;
height: 18px;
width: 52px;
text-align: center;
color: #FFF;
position: absolute;
top: 8px;
left: 8px;
}
}
.cover__wrap {
display: flex;
flex-direction: row;
}
.img-content {
margin-right: 20px;
width: 299px;
height: 169px;
img {
width: 100%;
height: 100%;
object-fit: contain;
border: 1px solid #E8e8e8;
}
}
}
.introduction{
margin-top:16px;
.instro-textarea{
vertical-align: top;
}
}
.wether-use{
display:flex;
margin-top:16px;
.instro-text{
color:#999;
margin-left:12px;
}
.content{
display:flex;
}
}
.view-range{
display:flex;
margin-top:16px;
.instro-text{
color:#999;
margin-left:12px;
}
.choose-business{
margin-top:16px;
}
}
.done-standard{
display: flex;
margin-top:22px;
.live-standard-info{
margin-bottom:10px;
}
input{
display:inline-block;
width:90px;
height:32px;
}
}
}
import React from 'react';
import { withRouter } from "react-router-dom";
import {Table, Modal,Input,message} from 'antd';
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';
const { Search } = Input;
const UserRole = {
Store_Manager: {
text: "店铺管理员"
},
Cloud_Manager: {
text:"管理员"
},
Cloud_Operator: {
text:'运营师'
},
Cloud_Lecture: {
text:"讲师"
},
};
class EmployeeShareData extends React.Component {
constructor(props) {
super(props);
const id = getParameterByName("id");
this.state = {
id,
dataSource:[],
size:10,
query: {
current: 1,
},
totalCount:0,
}
}
componentDidMount(){
this.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 = () => {
const columns = [
{
title: '员工',
key: 'storeUserName',
dataIndex: 'storeUserName',
render: (val, record) => {
return (
<div>
{val}
</div>
)
}
},
{
title: '角色',
key: 'roleEnum',
dataIndex: 'roleEnum',
render: (val, record) => {
return (
<div>
{UserRole[record.roleEnum].text}
</div>
)
}
},
{
title: '手机号',
key: 'storeUserPhone',
dataIndex: 'storeUserPhone',
render: (val, record) => {
return (
<div>
{val}
</div>
)
}
},
{
title: '最近分享成功时间',
key: 'recentlyForwardTime',
dataIndex: 'recentlyForwardTime',
render: (val, record) => {
return (
<div>
{formatDate('YYYY-MM-DD H:i', val)}
</div>
)
}
},
{
title: '学习人数',
key: 'learnNum',
dataIndex: 'learnNum',
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>
{val}
</div>
)
}
},
{
title: '操作',
key: 'operate',
dataIndex: 'operate',
render: (val, record) => {
return (
<span className="operate-item" onClick={()=>this.watchDataView(record)}>数据详情</span>
)
}
}
];
return columns;
}
render() {
const { dataSource,query,size,totalCount} = this.state;
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>}/>
</div>
<div>
<Table
rowKey={record => record.id}
dataSource={dataSource}
columns={this.parselumns()}
pagination={false}
onChange={this.handleChangeTable}
bordered
/>
{dataSource.length >0 &&
<div className="box-footer">
<PageControl
current={query.current - 1}
pageSize={size}
total={totalCount}
toPage={(page) => {
const _query = {...query, current: page + 1};
this.setState({
query:_query
},()=>{ this.handleFetchDataList()})
}}
onShowSizeChange={this.onShowSizeChange}
/>
</div>
}
</div>
</div>
)
}
}
export default withRouter(EmployeeShareData);
\ No newline at end of file
.employee-share-data{
.search-container{
margin-bottom:12px;
}
.operate-item{
font-size:14px;
color:#5289FA;
cursor: pointer;
}
}
\ No newline at end of file
import React from 'react';
import { Button } from 'antd';
import { withRouter } from 'react-router-dom';
import User from '@/common/js/user';
import './ExpiredCourseList.less';
function ExpiredCourseList(props) {
return (
<div className="expired-course-list">
{ props.expiredCourseList.map((item,index)=>{
return <div className="course-item">
<div className="course-left">
<div className="course-status">
未成功开课
</div>
<div className="course-info">
<div className="course-type">
{ item.courseType === "LIVE" &&
<span>直播课</span>
}
{ item.courseType === "VOICE " &&
<span>视频课</span>
}
</div>
<div className="course-instro">
<div className="course-name">
{item.courseName}
</div>
<div className="task-name">
{item.taskName}
</div>
</div>
</div>
</div>
<div className="course-time">
上课时间:{formatDate('YYYY-MM-DD H:i', item.startTime)}
</div>
</div>
})
}
</div>
);
}
export default withRouter(ExpiredCourseList)
.expired-course-list{
margin:18px 10px 16px;
.course-item{
display:flex;
padding:16px 0;
border-bottom:1px solid #E8E8E8;
justify-content: space-between;
.course-left{
display:flex;
.course-status{
color:#999999;
font-size:14px;
margin-right:16px;
}
.course-info{
display:flex;
.course-type{
margin-right:16px;
span{
padding:2px 8px;
color:#666666;
font-size:11px;
border-radius: 2px;
border: 1px solid #999999;
}
}
.course-instro{
.course-name{
color:#333333;
font-size:14px;
margin-bottom:7px;
}
.task-name{
color:#999;
font-size:14px;
}
}
}
}
.course-time{
color:#999;
font-size:14px;
}
}
}
\ No newline at end of file
/*
* @Author: 吴文洁
* @Date: 2020-07-14 15:41:30
* @Last Modified by: 吴文洁
* @Last Modified time: 2020-07-23 13:45:16
* @Description: 大班直播、互动班课列表的筛选组件
*/
import React, { useState, useRef, useEffect } from 'react';
import { withRouter } from 'react-router-dom';
import { Row, Input, Select ,Tooltip} from 'antd';
import RangePicker from "@/modules/common/DateRangePicker";
import moment from 'moment';
import StoreService from "@/domains/store-domain/storeService";
import './PlanFilter.less';
const { Search } = Input;
const { Option } = Select;
const DEFAULT_QUERY = {
planName: null,
startTime: null,
endTime:null,
enableState:null,
createId: null
}
const defaultCreatorQuery = {
size: 10,
current: 1,
nickName:null
}
function PlanFilter(props) {
const [expandFilter, setExpandFilter] = useState(false);
const [query,setQuery] = useState(DEFAULT_QUERY);
const [hasNext,setHasNext] = useState(false);
const [creatorQuery,setCreatorQuery] = useState(defaultCreatorQuery);
const [creatorList,setCreatorList] = useState([]);
useEffect(() => {
getCreatorList();
}, [creatorQuery]);
// 改变搜索条件
function handleChangeQuery(field, value){
const _query ={
...query,
[field]: value,
current: 1,
}
setQuery(_query);
if (field === 'planName') return;
props.onChange( _query);
}
function handleChangeDates (dates){
const _query = _.clone(query);
if (_.isEmpty(dates)) {
delete _query.startTime;
delete _query.endTime;
} else {
_query.startTime = dates[0].valueOf();
_query.endTime = dates[1].valueOf();
}
const param ={
..._query,
current: 1,
}
setQuery(param);
props.onChange(param);
}
// 重置搜索条件
function handleReset(){
setQuery(DEFAULT_QUERY);
props.onChange(DEFAULT_QUERY);
}
function getCreatorList(current = 1, selectList){
const _query = {
...creatorQuery,
current,
size:10
};
StoreService.getStoreUserBasicPage( _query).then((res) => {
const { result = {} } = res;
const { records = [], total = 0, hasNext } = result;
const list = current > 1 ? creatorList.concat(records) : records;
setHasNext(hasNext);
setCreatorList(list);
});
}
// 滑动加载更多讲师列表
function handleScrollCreatorList(e){
const container = e.target;
const scrollToBottom = container && container.scrollHeight <= container.clientHeight + container.scrollTop;
if (scrollToBottom && hasNext) {
getCreatorList(creatorQuery.current + 1);
}
}
return (
<div className="plan-filter">
<Row>
<div className="search-condition">
<div className="search-condition__item">
<span className="search-name">培训计划:</span>
<Search
value={query.planName}
placeholder="搜索培训计划名称"
onChange={(e) => { handleChangeQuery('planName', e.target.value)}}
onSearch={ () => { props.onChange(query) } }
style={{ width: "calc(100% - 70px)" }}
enterButton={<span className="icon iconfont">&#xe832;</span>}
/>
</div>
<div className="search-condition__item">
<span>创建人:</span>
<Select
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.createId}
onChange={(value) => {
handleChangeQuery('createId', value)
}}
onSearch={(value) => {
creatorQuery.nickName = value
setCreatorQuery(creatorQuery)
getCreatorList()
}
}
onClear ={(value)=>{
setCreatorQuery({
size: 10,
current: 1,
nickName:null
})
getCreatorList()
}
}
>
{_.map(creatorList, (item, index) => {
return (
<Select.Option value={item.id} key={item.id}>{item.nickName}</Select.Option>
);
})}
</Select>
</div>
<div className="search-condition__item">
<span className="search-date">创建日期:</span>
<RangePicker
id="course_date_picker"
allowClear={false}
value={ query.startTime ? [moment(query.startTime), moment(query.endTime)] : null }
format={"YYYY-MM-DD"}
onChange={(dates) => { handleChangeDates(dates) }}
style={{ width: "calc(100% - 70px)" }}
/>
</div>
{ expandFilter &&
<div className="search-condition__item">
<span className="shelf-status">当前状态:</span>
<Select
style={{ width: "calc(100% - 70px)" }}
placeholder="请选择当前状态"
allowClear={true}
value={query.enableState}
onChange={(value) => { handleChangeQuery('enableState', value) }}
suffixIcon={<span className="icon iconfont" style={{fontSize:'12px',color:'#BFBFBF'}}>&#xe835;</span>}
>
<Option value="YES">开启</Option>
<Option value="NO">关闭</Option>
</Select>
</div>
}
</div>
<div className="reset-fold-area">
<Tooltip title="清空筛选"><span className="resetBtn iconfont icon" onClick={handleReset}>&#xe61b; </span></Tooltip>
<span style={{ cursor: 'pointer' }} className="fold-btn" onClick={() => {
setExpandFilter(!expandFilter)
}}>{expandFilter ? <span><span>收起</span><span className="iconfont icon fold-icon" >&#xe82d; </span> </span> : <span>展开<span className="iconfont icon fold-icon" >&#xe835; </span></span>}</span>
</div>
</Row>
</div>
)
}
export default withRouter(PlanFilter);
\ No newline at end of file
.plan-filter {
position: relative;
.ant-input-search-button{
border-left:none;
}
.search-condition {
width: calc(100% - 80px);
display: flex;
align-items: center;
flex-wrap: wrap;
&__item {
width: 30%;
margin-right: 3%;
margin-bottom: 12px;
.search-name{
vertical-align: middle;
display:inline-block;
height:32px;
line-height:32px;
}
}
}
.reset-fold-area {
position: absolute;
right: 12px;
}
.resetBtn {
color: #999999;
font-size: 18px;
margin-right: 8px;
}
.fold-btn {
font-size: 14px;
color: #666666;
line-height: 20px;
.fold-icon {
font-size: 12px;
margin-left:4px;
}
}
}
\ No newline at end of file
.plan-list{
margin-top:12px;
.operate-text {
color: #5289FA;
cursor: pointer;
}
.operate {
display: flex;
&__item {
color: #5289FA;
cursor: pointer;
&.split {
margin: 0 8px;
color: #BFBFBF;
}
}
}
}
\ No newline at end of file
/*
* @Author: zhangleyuan
* @Date: 2021-02-20 16:45:51
* @LastEditors: zhangleyuan
* @LastEditTime: 2021-03-10 15:50:02
* @Description: 描述一下
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import React from 'react';
import { Button } from 'antd';
import { withRouter } from 'react-router-dom';
import User from '@/common/js/user';
import './PlanOpt.less';
function PlanOpt() {
function handleCreatePlan(){
window.RCHistory.push({
pathname: '/create-plan?type=add',
})
}
return (
<div className="plan-opt">
{ (User.getUserRole() === "CloudManager" || User.getUserRole() === "StoreManager") &&
<Button
type="primary"
className="mr12"
onClick={handleCreatePlan}
>新建培训计划</Button>
}
</div>
);
}
export default withRouter(PlanOpt)
.plan-opt{
margin-top:4px;
}
\ No newline at end of file
.training-task{
thead{
display:none;
}
.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;
border-radius: 2px;
padding:16px;
margin-top:16px;
.add-task-btn-disabled{
color:#CCCCCC;
font-size:14px;
}
.add-task-btn{
color: #5289FA;
font-size:14px;
}
}
}
.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
/*
* @Author: 吴文洁
* @Date: 2020-07-14 15:41:30
* @Last Modified by: 吴文洁
* @Last Modified time: 2020-07-23 13:45:16
* @Description: 大班直播、互动班课列表的筛选组件
*/
import React, { useState, useRef, useEffect } from 'react';
import { withRouter } from 'react-router-dom';
import { Row, Input, Select ,Tooltip} from 'antd';
import RangePicker from "@/modules/common/DateRangePicker";
import moment from 'moment';
import StoreService from "@/domains/store-domain/storeService";
import User from '@/common/js/user'
import Bus from '@/core/bus';
import './UserLearningDataFilter.less';
const { Search } = Input;
const { Option } = Select;
const userRole = User.getUserRole();
const DEFAULT_QUERY = {
customerName: null,
startTime: null,
endTime:null,
learnState:null,
operateId: null
}
const defaultCreatorQuery = {
size: 10,
current: 1,
nickName:null
}
function UserLearningDataFilter(props) {
const [expandFilter, setExpandFilter] = useState(false);
const [query,setQuery] = useState(DEFAULT_QUERY);
const [hasNext,setHasNext] = useState(false);
const [creatorQuery,setCreatorQuery] = useState(defaultCreatorQuery);
const [creatorList,setCreatorList] = useState([]);
useEffect(() => {
Bus.bind('watchDataView',(value) => handleChangeCreatorQuery(value))
}, []);
useEffect(() => {
getCreatorList();
}, [creatorQuery]);
function handleChangeCreatorQuery (value){
const _creatorQuery = {...creatorQuery};
_creatorQuery.operateId = value;
setCreatorQuery(_creatorQuery);
}
// 改变搜索条件
function handleChangeQuery(field, value){
const _query ={
...query,
[field]: value,
current: 1,
}
setQuery(_query);
if (field === 'customerName') return;
props.onChange( _query);
}
function handleChangeDates (dates){
const _query = _.clone(query);
if (_.isEmpty(dates)) {
delete _query.startTime;
delete _query.endTime;
} else {
_query.startTime = dates[0].valueOf();
_query.endTime = dates[1].valueOf();
}
const param ={
..._query,
current: 1,
}
setQuery(param);
props.onChange(param);
}
// 重置搜索条件
function handleReset(){
setQuery(DEFAULT_QUERY);
props.onChange(DEFAULT_QUERY);
}
function getCreatorList(current = 1, selectList){
const _query = {
...creatorQuery,
current,
size:10
};
StoreService.getStoreUserBasicPage( _query).then((res) => {
const { result = {} } = res;
const { records = [], total = 0, hasNext } = result;
const list = current > 1 ? creatorList.concat(records) : records;
setHasNext(hasNext);
setCreatorList(list);
});
}
// 滑动加载更多讲师列表
function handleScrollCreatorList(e){
const container = e.target;
const scrollToBottom = container && container.scrollHeight <= container.clientHeight + container.scrollTop;
if (scrollToBottom && hasNext) {
getCreatorList(creatorQuery.current + 1);
}
}
return (
<div className="user-learn-data-filter">
<Row>
<div className="search-condition">
<div className="search-condition__item">
<span className="label customer-label">用户:</span>
<Search
value={query.customerName}
placeholder="搜索用户名称"
onChange={(e) => { handleChangeQuery('customerName', e.target.value)}}
onSearch={ () => { props.onChange(query) } }
style={{ width: "calc(100% - 70px)" }}
enterButton={<span className="icon iconfont">&#xe832;</span>}
/>
</div>
{(User.getUserRole() === "CloudManager" || User.getUserRole() === "StoreManager")&&
<div className="search-condition__item">
<span className="label lead-label">负责人:</span>
<Select
id="leadSelect"
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)
}}
onSearch={(value) => {
creatorQuery.nickName = value
setCreatorQuery(creatorQuery)
getCreatorList();
}
}
onClear ={(value)=>{
setCreatorQuery({
size: 10,
current: 1,
nickName:null
})
getCreatorList()
}
}
>
{_.map(creatorList, (item, index) => {
return (
<Select.Option value={item.id} key={item.id}>{item.nickName}</Select.Option>
);
})}
</Select>
</div>
}
<div className="search-condition__item">
<span className="label learn-date-label">最近学习日期:</span>
<RangePicker
id="course_date_picker"
allowClear={false}
value={ query.startTime ? [moment(query.startTime), moment(query.endTime)] : null }
format={"YYYY-MM-DD"}
onChange={(dates) => { handleChangeDates(dates) }}
style={{ width: "calc(100% - 98px)" }}
/>
</div>
{ ((expandFilter && (User.getUserRole() === "CloudManager" || User.getUserRole() === "StoreManager")) || User.getUserRole === "CloudOperator")&&
<div className="search-condition__item">
<span className="label learn-status-label">学习状态:</span>
<Select
style={{ width: "calc(100% - 70px)" }}
placeholder="请选择当前状态"
allowClear={true}
value={query.learnState}
onChange={(value) => { handleChangeQuery('learnState', value) }}
suffixIcon={<span className="icon iconfont" style={{fontSize:'12px',color:'#BFBFBF'}}>&#xe835;</span>}
>
<Option value="UN_PLAY">未开始</Option>
<Option value="UNDER_WAY">进行中</Option>
<Option value="FINISH">已完成</Option>
</Select>
</div>
}
</div>
{( User.getUserRole() === "CloudManager" || User.getUserRole() === "StoreManager")&&
<div className="reset-fold-area">
<Tooltip title="清空筛选"><span className="resetBtn iconfont icon" onClick={handleReset}>&#xe61b; </span></Tooltip>
<span style={{ cursor: 'pointer' }} className="fold-btn" onClick={() => {
setExpandFilter(!expandFilter)
}}>{expandFilter ? <span><span>收起</span><span className="iconfont icon fold-icon" >&#xe82d; </span> </span> : <span>展开<span className="iconfont icon fold-icon" >&#xe835; </span></span>}</span>
</div>
}
</Row>
</div>
)
}
export default withRouter(UserLearningDataFilter);
\ No newline at end of file
.user-learn-data-filter {
position: relative;
.ant-input-search-button{
border-left:none;
}
.search-condition {
width: calc(100% - 80px);
display: flex;
align-items: center;
flex-wrap: wrap;
&__item {
width: 30%;
margin-right: 3%;
margin-bottom: 12px;
.label{
font-size:14px;
color:#666;
vertical-align: middle;
width:70px;
text-align:right;
display:inline-block;
}
.learn-date-label{
width:98px;
text-align:right;
display:inline-block;
}
.ant-input-group-wrapper{
vertical-align: middle;
}
}
}
.reset-fold-area {
position: absolute;
right: 12px;
}
.resetBtn {
color: #999999;
font-size: 18px;
margin-right: 8px;
}
.fold-btn {
font-size: 14px;
color: #666666;
line-height: 20px;
.fold-icon {
font-size: 12px;
margin-left:4px;
}
}
}
\ No newline at end of file
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 './SelectOperatorModal.less';
import _ from "underscore";
const { Search } = Input;
class SelectOperatorModal extends React.Component {
constructor(props) {
super(props);
this.state = {
dataSource:[],
size:10,
query: {
current: 1,
},
totalCount:0,
selectOperatorList:this.props.selectOperatorList
};
}
componentDidMount() {
this.handleFetchDataList();
}
// 获取运营师列表
handleFetchDataList = () => {
const {query,size,totalCount} = this.state
const params ={
...query,
size,
roleCodes:['CloudOperator']
}
StoreService.getStoreUserBasicPage(params).then((res) => {
const { result = {} } = res ;
const { records = [], total = 0 } = result;
this.setState({
dataSource: records,
totalCount: Number(total)
});
});
}
handleChangNickname = (value)=>{
const isPhone = (value || '').match(/^\d+$/);
const { query } = this.state;
if(isPhone){
query.phone = value;
query.nickName = null;
}else{
query.nickName = value;
query.phone = null;
}
query.current = 1;
this.setState({
query
})
}
onShowSizeChange = (current, size) => {
if (current == size) {
return
}
this.setState({
size
},()=>{this.handleFetchDataList()})
}
// 请求表头
parseColumns = () => {
const columns = [
{
title: '姓名',
key: 'nickName',
dataIndex: 'nickName'
},
{
title: '手机号',
key: 'phone',
dataIndex: 'phone'
}
];
return columns;
}
selectOperator = (record,selected) =>{
const {selectOperatorList} = this.state;
let _list = [];
if (selected || !_.find(selectOperatorList, (item) => item.id == record.id)) {
_list = _.uniq(selectOperatorList.concat([record]), false, (item) => item.id);
} else {
_list = _.reject(selectOperatorList, (item) => item.id === record.id);
}
this.setState({selectOperatorList:_list});
}
render() {
const { size,dataSource,totalCount,query,selectOperatorList} = this.state;
const { visible } = this.props;
return (
<Modal
title="选择运营师"
onCancel={this.props.onClose}
maskClosable={false}
visible={visible}
className="select-operator-modal"
closable={true}
width={800}
onOk={() => this.props.onSelect(selectOperatorList) }
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()}} />
</div>
<div>
<Table
rowKey={record => record.id}
dataSource={dataSource}
columns={this.parseColumns()}
pagination={false}
rowSelection={{
type: 'checkbox',
selectedRowKeys: _.pluck(selectOperatorList, 'id'),
onSelect: (record, selected) => {
this.selectOperator(record, selected)
},
onSelectAll: (selected, _selectedRows, changeRows) => {
let _list = [];
if (selected) {
_list = _.uniq(selectOperatorList.concat(changeRows), false, (item) => item.id);
} else {
_list = _.reject(selectOperatorList, (item) => _.find(changeRows, (data) => data.id === item.id));
}
this.setState({selectOperatorList:_list});
},
}}
/>
{dataSource.length >0 &&
<div className="box-footer">
<PageControl
current={query.current - 1}
pageSize={size}
total={totalCount}
toPage={(page) => {
const _query = {...query, current: page + 1};
this.setState({
query:_query
},()=>{ this.handleFetchDataList()})
}}
onShowSizeChange={this.onShowSizeChange}
/>
</div>
}
</div>
</Modal>
)
}
}
export default SelectOperatorModal;
\ No newline at end of file
.select-operator-modal{
.search-container{
margin-bottom:16px;
}
}
\ No newline at end of file
/*
* @Author: 吴文洁
* @Date: 2020-07-20 19:12:49
* @Last Modified by: 吴文洁
* @Last Modified time: 2020-07-20 20:25:13
* @Description: 大班直播分享弹窗
*/
import React from 'react';
import { Modal, Input, Button, message } from 'antd';
import domtoimage from 'dom-to-image';
import qrcode from "@/libs/qrcode/qrcode.js";
import User from '@/common/js/user';
import $ from 'jquery';
import CourseService from "@/domains/course-domain/CourseService";
import './SharePlanModal.less';
const storeName = User.getStoreName();
const DEFAULT_COVER = 'https://image.xiaomaiketang.com/xm/YNfi45JwFA.png';
class ShareLiveModal extends React.Component {
constructor(props) {
super(props);
this.state = {
shareUrl: ''
}
}
componentDidMount() {
// 获取短链接
this.handleConvertShortUrl();
}
handleConvertShortUrl = () => {
const { longUrl } = this.props.data;
// 发请求
CourseService.getQrcode({
urls: [longUrl]
}).then((res) => {
const { result = [] } = res;
this.setState({
shareUrl: result[0].shortUrl
}, () => {
const qrcodeWrapDom = document.querySelector('#qrcodeWrap');
const qrcodeNode = new qrcode({
text: this.state.shareUrl,
size: 98,
})
qrcodeWrapDom.appendChild(qrcodeNode);
});
})
}
componentWillUnmount() {
// 页面销毁之前清空定时器
clearTimeout(this.timer);
}
// 下载海报
handleDownloadPoster = () => {
this.setState({
showImg:true,
time:new Date().valueOf()
},()=>{
this.setState({time:new Date().valueOf()},()=>{
let node = document.getElementById('poster');
domtoimage.toPng(node)
.then((imgData) => {
console.log(imgData)
const download = document.createElement('a');
const { planName } = this.props.data;
$(download).attr('href', imgData).attr('download', `${planName}.png`).get(0).click();
})
})
})
}
// 复制分享链接
handleCopy = () => {
const textContent = document.getElementById('shareUrl').innerText;
window.copyText(textContent);
message.success('复制成功!');
}
render() {
const {data} = this.props;
const { planName, coverUrl = DEFAULT_COVER} = data;
const { shareUrl,showImg,time} = this.state;
return (
<Modal
title={'分享培训计划'}
width={680}
visible={true}
footer={null}
maskClosable={false}
closeIcon={<span className="icon iconfont modal-close-icon">&#xe6ef;</span>}
className="share-live-modal"
onCancel={this.props.close}
>
<div className="left">
<div id="poster">
<div className="store-name">
<span className="text">{storeName}</span>
</div>
<div className="course-name-title">邀请你参与培训:</div>
<div class="live-couse-name">{planName}</div>
{
showImg ? <img
crossOrigin='*'
src={coverUrl+`?=${time}`}
className="course-cover"
/>: <img
src={coverUrl+`?=${time}`}
className="course-cover"
/>
}
<div className="qrcode-wrap">
<div className="qrcode-wrap__left">
<div className="text">长按识别二维码进入观看</div>
<img className="finger" src="https://image.xiaomaiketang.com/xm/thpkWDwJsC.png"/>
</div>
<div className="qrcode-wrap__right" id="qrcodeWrap">
</div>
</div>
</div>
</div>
<div className="right">
<div className="share-poster right__item">
<div className="title">① 海报分享</div>
<div className="sub-title">用户可通过微信扫描海报二维码,查看培训计划</div>
<div className="content" onClick={this.handleDownloadPoster}>下载海报</div>
</div>
<div className="share-url right__item">
<div className="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>
</div>
</div>
</div>
</Modal>
)
}
}
export default ShareLiveModal;
.share-live-modal {
.ant-modal-body {
display: flex;
#poster{
background: #FFF;
margin:0;
padding: 20px;
}
.left {
width: 303px;
margin: 0 32px 0 16px;
box-shadow:0px 2px 10px 0px rgba(0,0,0,0.05);
border-radius: 12px;
.course-name-title {
font-size: 14px;
color: #333;
line-height: 20px;
margin-bottom: 4px;
}
.live-couse-name{
font-size:16px;
color:#333333;
font-weight: 600;
}
.course-name {
color: #333;
font-size: 16px;
font-weight: 600;
line-height: 20px;
}
.course-cover {
width: 263px;
height: 143px;
border-radius: 6px;
margin-top: 8px;
}
.qrcode-wrap {
padding: 0 16px;
display: flex;
align-items: center;
margin: 24px 0 16px 0;
&__left {
width: 98px;
text-align: center;
margin-right: 22px;
.text {
line-height: 20px;
}
.finger {
width: 40px;
height: 40px;
margin-top: 8px;
}
}
&__right {
width: 110px;
height: 110px;
padding: 6px
}
}
.store-name {
// padding: 8px 16px;
display: flex;
align-items: center;
margin-bottom: 8px;
.text {
font-size: 12px;
color: #999;
font-size: 14px;
line-height: 20px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
width: 100%;
}
}
}
.right {
.title {
color: #333;
font-weight: 500;
}
.sub-title {
color: #999;
margin-top: 16px;
}
.content {
display: flex;
align-items: center;
margin-top: 8px;
.share-url {
width: 212px;
overflow: hidden;
height: 28px;
line-height: 28px;
border-radius: 4px 0 0 4px;
padding-left: 12px;
white-space: nowrap;
color: #999999;
background: #EFEFEF;
}
.ant-btn {
margin-left: -2px;
}
}
.url-content{
position:relative;
&:after{
content:'';
width: 12px;
height: 22px;
background: #EFEFEF;
position:absolute;
right:71px;
}
}
.share-poster {
margin-bottom: 40px;
.content {
color:rgba(82, 137, 250, 1);
cursor: pointer;
}
}
}
}
}
\ No newline at end of file
import React from 'react';
import {Table, Modal,Input,message} from 'antd';
import { PageControl } from "@/components";
import PlanService from '@/domains/plan-domain/planService'
import User from '@/common/js/user'
import './UnbundEmployeeModal.less';
import _ from "underscore";
const { Search } = Input;
const UserRole = {
StoreManager: {
text: "店铺管理员"
},
CloudManager: {
text:"管理员"
},
CloudOperator: {
text:'运营师'
},
Cloud_Lecture: {
text:"讲师"
},
};
class UnbundEmployeeModal extends React.Component {
constructor(props) {
super(props);
this.state = {
dataSource:[],
selectOperatorList:[]
};
}
componentDidMount() {
this.handleFetchDataList();
}
// 获取绑定员工列表
handleFetchDataList = () => {
const params ={
planId: getParameterByName("id"),
storeCustomerId: this.props.storeCustomerId,
storeId:this.props.storeId
}
PlanService.getPlanCustomerAboutUser(params).then((res) => {
const { result = {} } = res ;
this.setState({
dataSource: result,
});
});
}
// 请求表头
parseColumns = () => {
const columns = [
{
title: '员工',
key: 'storeUserName',
dataIndex: 'storeUserName',
},
{
title: '角色',
key: 'role',
dataIndex: 'role',
render:(val,record)=>{
return <span>{UserRole[val].text}</span>
}
},
{
title: '手机号',
key: 'storeUserPhone',
dataIndex: 'storeUserPhone'
}
];
return columns;
}
selectOperator = (record,selected) =>{
const {selectOperatorList} = this.state;
let _list = [];
if (selected || !_.find(selectOperatorList, (item) => item.storeUserId == record.storeUserId)) {
_list = _.uniq(selectOperatorList.concat([record]), false, (item) => item.storeUserId);
} else {
_list = _.reject(selectOperatorList, (item) => item.storeUserId === record.storeUserId);
}
this.setState({selectOperatorList:_list});
}
confirmUnbund = ()=>{
const { selectOperatorList } = this.state;
const params = {
planId:getParameterByName("id"),
removeUserIds:_.pluck(selectOperatorList, 'storeUserId'),
storeCustomerId:this.props.storeCustomerId,
storeId:User.getStoreId(),
storeUserId:User.getStoreUserId()
}
PlanService.removePlanCustomer(params).then((res) => {
message.success('解绑成功');
this.props.onConfirm();
});
}
render() {
const { size,dataSource,totalCount,query,selectOperatorList} = this.state;
const { visible } = this.props;
return (
<Modal
title="选择需解绑的员工"
onCancel={this.props.onClose}
maskClosable={false}
visible={visible}
className="select-operator-modal"
closable={true}
width={800}
onOk={() => {this.confirmUnbund()}}
closeIcon={<span className="icon iconfont modal-close-icon">&#xe6ef;</span>}
>
<div>
<Table
rowKey={record => record.storeUserId}
dataSource={dataSource}
columns={this.parseColumns()}
pagination={false}
bordered
rowSelection={{
type: 'checkbox',
selectedRowKeys: _.pluck(selectOperatorList, 'storeUserId'),
onSelect: (record, selected) => {
this.selectOperator(record, selected)
},
onSelectAll: (selected, _selectedRows, changeRows) => {
let _list = [];
if (selected) {
_list = _.uniq(selectOperatorList.concat(changeRows), false, (item) => item.storeUserId);
} else {
_list = _.reject(selectOperatorList, (item) => _.find(changeRows, (data) => data.id === item.storeUserId));
}
this.setState({selectOperatorList:_list});
}
}}
/>
</div>
</Modal>
)
}
}
export default UnbundEmployeeModal;
\ No newline at end of file
import React from 'react';
import {Table, Modal,Input} from 'antd';
import { PageControl } from "@/components";
import PlanService from '@/domains/plan-domain/planService'
import User from '@/common/js/user'
import './UserLearnDetailModal.less';
import _ from "underscore";
const { Search } = Input;
const defaultCover = 'https://image.xiaomaiketang.com/xm/YNfi45JwFA.png';
const CourseType = {
LIVE: {
text: "直播课"
},
VOICE : {
text:"视频课"
},
RECORD : {
text:'录播课'
}
};
const courseStateShow = {
UN_START: {
title: "待开播",
},
STARTING: {
title: "直播中",
},
FINISH: {
title: "回放",
},
EXPIRED: {
title: "未成功开课",
},
};
class UserLearnDetailModal extends React.Component {
constructor(props) {
super(props);
this.state = {
planDataSource:[],
taskDataSource:[],
taskSize:10,
taskQuery: {
current: 1,
},
taskTotalCount:0,
courseDataSource:[],
storeCustomerName:'',
storeCustomerPhone:''
};
}
componentDidMount() {
this.getPlanCustomerDetail();
}
getPlanCustomerDetail = ()=>{
PlanService.getPlanCustomerDetail({
planId:getParameterByName("id"),
storeCustomerId:this.props.storeCustomerId,
storeId:User.getStoreId()
}).then((res) => {
const {
storeCustomerName,
storeCustomerPhone,
planName,
learnFinishPercentage,
taskCustomerVOList,
courseMediaVOS,
}=res.result;
let coverUrl;
courseMediaVOS.map((item) => {
if(item.contentType === "COVER"){
coverUrl = item.mediaUrl;
}
return item;
})
const planDataSource = [{
planName,
learnFinishPercentage,
coverUrl:coverUrl || defaultCover
}]
this.setState({
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 = [
{
title: '培训任务',
key: 'taskName',
dataIndex: 'taskName',
render: (val, record,index) => {
return (
<div className="taskName">
{index + 1}.{record.taskName}
</div>
)
}
},
{
title: '学习进度',
key: 'learnFinishPercentage',
dataIndex: 'learnFinishPercentage',
width:167,
render: (val, record) => {
return (
<div className="task-learn-percentage">
{ val === 100 ?<span>已完成</span>:<span>{val}%</span>}
</div>
)
}
}
];
return columns;
}
parseCoursecolumns = (parentIndex) => {
const columns = [
{
title: '课程',
key: 'courseName',
dataIndex: 'courseName',
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>
)
}
},
{
title: '学习进度',
key: 'learnFinishPercentage',
dataIndex: 'learnFinishPercentage',
width:152,
render: (val, record) => {
return (
<div className="course-learn-percentage">
{ record.learnState === "FINISH" ?<span>已完成</span>:<span>{val}%</span>}
</div>
)
}
}
];
return columns;
}
render() {
const {storeCustomerName,storeCustomerPhone,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 className="customer-info">
<span className="customer-name">
<span>用户:</span>
<span>{storeCustomerName}</span>
</span>
<span className="customer-phone">
<span>手机号:</span>
<span>{storeCustomerPhone}</span>
</span>
</div>
<div>
<Table
dataSource={planDataSource}
columns={this.parsePlanColumns()}
pagination={false}
bordered
className="plan-table"
/>
</div>
<div>
<Table
rowKey={(record) => record.taskId}
className="task-table"
dataSource={taskDataSource}
columns={this.parseTaskColumns()}
pagination={false}
expandedRowRender={(record,index) => {
if(!record.courseVOList){
return
}
if (record.courseVOList.length !== 0 ){
return <div>
<Table
pagination={false}
dataSource={record.courseVOList}
columns={this.parseCoursecolumns(index)}
className="child-table"
/>
</div>
}
}}
rowClassName={(record,index)=>{if(index%2===0){return 'odd-row'}else{ return 'even-row'}}}
/>
</div>
</Modal>
)
}
}
export default UserLearnDetailModal;
\ No newline at end of file
.user-Learn-modal{
.customer-info{
margin-bottom:16px;
.customer-name{
font-size:14px;
color:#333;
margin-right:32px;
}
.customer-phone{
font-size:14px;
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;
}
}
}
.task-table{
.taskName{
color:#666666;
font-size:14px;
}
.task-learn-percentage{
color:#666666;
font-size:14px;
}
.course-info{
margin-left:57px;
.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;
}
}
.ant-table-content{
border:1px solid #e8e8e8;
tr{
td{
border:none;
}
.child-table{
.ant-table-content{
border:none;
thead{
display:none;
}
tbody tr td{
border-bottom:none;
}
}
}
}
.odd-row{
background:transparent;
td{
background: #FFF;
}
& + .ant-table-expanded-row{
background:transparent;
td{
background: #FFF;
}
}
&:hover{
& + .ant-table-expanded-row{
background:transparent;
td{
background: #F3f6fa !important;
}
}
}
}
.even-row{
background:transparent;
td{
background: #FAFAFA;
}
& + .ant-table-expanded-row{
background:transparent;
td{
background: #FAFAFA;
}
}
&:hover{
& + .ant-table-expanded-row{
background:transparent;
td{
background: #F3f6fa !important;
}
}
}
}
}
}
}
\ No newline at end of file
.related-course-modal{
.ant-tabs-top > .ant-tabs-nav::before{
border-bottom: 0px;
}
.ant-tabs-nav-list{
margin:0 auto;
}
.ant-tabs-nav .ant-tabs-tab{
padding:6px 12px !important;
margin:0;
border: 1px solid #E8E8E8;
font-size:14px !important;
color:#999;
&:nth-child(1){
border-radius: 4px 0px 0px 4px;
}
&:nth-child(2){
border-radius: 0px 4px 4px 0px;
}
}
.ant-tabs-nav .ant-tabs-tab-active{
border: 1px solid #FFB714;
color:#FFB714;
}
.ant-tabs-top .ant-tabs-ink-bar-animated:after{
height:0;
}
.link-create-course{
color:#666666;
font-size:14px;
width:638px;
text-align:left;
display:inline-block;
span{
color:#5289FA;
}
}
.search-container{
margin-bottom:16px;
}
.select-area{
margin-bottom:12px;
display:flex;
justify-content:space-between;
.select-box{
display:inline-box;
width: 186px;
background: #FFF4DD;
border-radius: 4px;
padding:6px 16px;
margin-right:8px;
display: flex;
justify-content: space-between;
.tip-icon{
color:#FF9D14;
font-size:14px;
margin-right:4px;
}
.select-num{
color:#666666;
font-size:14px;
}
.clear-btn{
text-align:right;
color:#5289FA;
font-size:14px;
}
}
.related-box{
padding:6px 16px;
background: #FFF4DD;
border-radius: 4px;
flex:1;
color:#666666;
font-size:14px;
}
}
.course-info{
display: flex;
align-items: center;
.course-cover{
width: 97px;
height: 55px;
display: inline-block;
border-radius:4px;
margin-right:8px;
}
.course-name{
font-size:14px;
color:#666;
text-overflow: -o-ellipsis-lastline;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
line-clamp: 2;
-webkit-box-orient: vertical;
width:238px;
}
.course-status {
font-size:12px;
line-height:18px;
display:inline-block;
border-radius:2px;
padding:0 8px;
margin-top:8px;
}
}
}
\ No newline at end of file
......@@ -2,7 +2,7 @@
* @Author: 吴文洁
* @Date: 2019-07-10 10:30:49
* @LastEditors: zhangleyuan
* @LastEditTime: 2021-02-02 16:42:04
* @LastEditTime: 2021-03-09 18:23:29
* @Description:
*/
import React, { useContext, useEffect, useState } from 'react';
......@@ -16,6 +16,7 @@ import User from '@/common/js/user';
import BaseService from "@/domains/basic-domain/baseService";
import { XMContext } from '@/store/context';
import { setStoreGroupPermission, setStorePermission, setStoreGroupList, setStoreList } from '@/store/actions/index';
import Bus from '@/core/tbus';
declare var window: any;
const App: React.FC = (props: any) => {
......@@ -47,9 +48,9 @@ const App: React.FC = (props: any) => {
User.setStoreId(id);
User.setStoreUserId(storeUserId);
User.setStoreName(storeName);
Bus.trigger('storeNameChange',storeName);
User.setUserRole(userRole);
User.setStoreType(storeType);
ctx.dispatch(setStoreGroupList(storeGroupVOS))
ctx.dispatch(setStoreList(storeVOS));
serStoreUserId(storeUserId)
......
......@@ -2,7 +2,7 @@
* @Author: 吴文洁
* @Date: 2019-09-10 18:26:03
* @LastEditors: zhangleyuan
* @LastEditTime: 2021-01-28 15:24:43
* @LastEditTime: 2021-03-09 19:05:49
* @Description:
*/
import React, { useContext, useEffect, useState } from "react";
......@@ -15,17 +15,22 @@ import { XMContext } from "@/store/context";
import logoImg from "@/common/images/logo.png";
import CourseService from "@/domains/course-domain/CourseService";
import qrcode from "@/libs/qrcode/qrcode.js";
import Bus from '@/core/tbus';
const baseImg = "https://image.xiaomaiketang.com/xm/rJeQaZxtc7.png";
const { confirm } = Modal;
function Header(props) {
const { menuType, handleMenuType } = props;
const [storeName,setStoreName] = useState(User.getStoreName())
const ctx = useContext(XMContext);
const htmlUrl = `${LIVE_SHARE}store/index?id=${User.getStoreId()}&userId=${User.getUserId()}&from=work_weixin`;
useEffect(() => {
htmlUrl && handleConvertShortUrl();
Bus.bind('storeNameChange', (value) => {
setStoreName(value);
});
}, []);
function userMenu() {
......@@ -135,7 +140,7 @@ function Header(props) {
)}
<div className="message-help">
<div className="store-related">
<div className="store-name">{User.getStoreName()}</div>
<div className="store-name">{storeName}</div>
<div className="line"></div>
<div className="link-to-store">
<div className="link">
......
......@@ -2,7 +2,7 @@
* @Author: wufan
* @Date: 2020-12-26 11:51:14
* @LastEditors: wufan
* @LastEditTime: 2020-12-26 15:04:26
* @LastEditTime: 2021-03-09 15:18:09
* @Description: 登录后跳转承载页面
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
......@@ -39,6 +39,11 @@ function SwitchRoute(props: SwitchProps) {
pathname: `/home`,
});
break;
case "CloudOperator":
window.RCHistory.replace({
pathname: `/home`,
});
break;
}
}, [User.getUserRole()]);
return <div></div>
......
/*
* @Author: wufan
* @Date: 2020-11-27 16:21:49
* @LastEditors: wufan
* @LastEditTime: 2021-01-25 21:14:48
* @LastEditors: zhangleyuan
* @LastEditTime: 2021-03-09 14:21:35
* @Description: Description
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
......@@ -40,11 +40,10 @@ interface AddEmployeeModalProps {
onClose: () => void;
isWorkWechat: boolean;
}
function AddEmployeeModal(props: AddEmployeeModalProps) {
const [nickName, setName] = useState("");
const [phone, setPhone] = useState("");
const [role, setRole] = useState("CloudLecturer");
const [role, setRole] = useState("CloudOperator");
const [avatar, setAvatar] = useState(
"https://image.xiaomaiketang.com/xm/rJeQaZxtc7.png"
);
......@@ -64,16 +63,15 @@ function AddEmployeeModal(props: AddEmployeeModalProps) {
const [form] = Form.useForm();
useEffect(() => {
if (props.choosedItem.nickName) {
console.log("props.choosedItem", props.choosedItem);
setName(props.choosedItem.nickName);
console.log('choosedItem',props.choosedItem);
props.choosedItem.phone && setPhone(props.choosedItem.phone);
props.choosedItem.role && setRole(props.choosedItem.role[0]);
props.choosedItem.avatar && setAvatar(props.choosedItem.avatar);
const _role =
props.choosedItem.role[0] === "CloudLecturer"
? "CloudLecturer"
: "CloudManager";
const _role = props.choosedItem.role[0];
form.setFieldsValue({
nickName: props.choosedItem.nickName,
role: _role,
......@@ -190,6 +188,7 @@ function AddEmployeeModal(props: AddEmployeeModalProps) {
roleCodes: [role],
avatar,
storeUserId: storeUserId,
storeId:User.getStoreId()
};
console.log("params", params);
......@@ -284,8 +283,13 @@ function AddEmployeeModal(props: AddEmployeeModalProps) {
}}
className="mt5"
>
<Radio value={"CloudLecturer"} className="mt-4"
>
<Radio value={"CloudOperator"} className="mt-4">
<span style={{ color: "#333" }}>运营师</span>
<p className="radio-tip">
仅可查看/转发培训计划内容,并查看其负责的用户学习进度
</p>
</Radio>
<Radio value={"CloudLecturer"} className="mt-4">
<span style={{ color: "#333" }}>普通讲师</span>
<p className="radio-tip">
仅可查看/使用与自己相关的文件和课表,并进行上课
......
.store-info-page{
.store-info-header{
font-weight:bold;
color:#333;
font-size:16px;
margin-bottom: 16px;
}
.ant-form-item-label > label{
width:112px;
display:inline-block;
text-align:right;
color:#666666;
font-size:14px;
}
.store-info-page-form{
margin-left:29px;
.logo-con{
display: flex;
.logo-img-con{
width: 258px;
height: 60px;
margin-right:8px;
.logo-box{
width: 258px;
height: 60px;
background: #F7F8F9;
border-radius: 1px;
text-align:center;
.text{
text-align:center;
line-height:60px;
color:#ccc;
font-size:14px;
}
}
.logo-img{
width: 258px;
height: 60px;
}
}
.operate-con{
.upload-btn{
color:#5289FA;
font-size:14px;
margin-bottom:4px;
}
.tip{
color:#999999;
font-size:14px;
}
}
}
}
.submit-btn{
margin-left:142px;
}
}
\ No newline at end of file
/*
* @Author: 吴文洁
* @Date: 2020-04-29 10:26:32
* @LastEditors: wufan
* @LastEditTime: 2021-01-18 21:23:08
* @LastEditors: zhangleyuan
* @LastEditTime: 2021-03-02 15:56:22
* @Description: 内容线路由配置
*/
import Home from '@/modules/home/Home';
......@@ -17,10 +17,14 @@ import VideoCoursePage from '@/modules/course-manage/video-course'
import GraphicsCoursePage from '@/modules/course-manage/graphics-course'
import AddVideoCoursePage from '@/modules/course-manage/video-course/AddVideoCourse'
import AddGraphicsCoursePage from '@/modules/course-manage/graphics-course/AddGraphicsCourse'
import DataList from '@/modules/course-manage/DataList/DataList';
import ClassBook from '@/modules/resource-disk';
// import DataList from '@/modules/course-manage/DataList/DataList';
// import ClassBook from '@/modules/resource-disk';
import ResourceDisk from '@/modules/resource-disk';
import SwitchRoute from '@/modules/root/SwitchRoute';
import PlanPage from '@/modules/plan-manage/PlanPage';
import AddPlanPage from '@/modules/plan-manage/AddPlan';
import LearningDataPage from '@/modules/plan-manage/LearningData';
import StoreInfoPage from '@/modules/store-manage/StoreInfo';
const mainRoutes = [
{
......@@ -92,7 +96,28 @@ const mainRoutes = [
path: '/switch-route',
component: SwitchRoute,
name: '登录后跳转承载页'
},
{
path:'/plan',
component: PlanPage,
name: '培训计划'
},
{
path: '/create-plan',
component:AddPlanPage,
name: '创建视频课'
},
{
path: '/store-info',
component:StoreInfoPage,
name: '店铺信息'
},
{
path: '/learning-data',
component:LearningDataPage,
name: '学习数据'
}
]
export default mainRoutes;
\ No newline at end of file
/*
* @Author: zhangleyuan
* @Date: 2021-01-19 11:27:56
* @LastEditors: zhangleyuan
* @LastEditTime: 2021-03-02 15:18:12
* @Description: 描述一下
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
export const menuList: any = [
{
groupName: "中心首页",
......@@ -34,11 +42,28 @@ export const menuList: any = [
link: '/resource-disk'
},
{
groupName: "培训管理",
groupCode: "TrainManage",
icon: '&#xe863;',
children: [
{
groupName: "培训计划",
groupCode: "TrainPlan",
link: '/plan'
}
]
},
{
groupName: "店铺管理",
groupCode: "CloudShop",
icon: '&#xe82e;',
children: [
{
groupName: "店铺信息",
groupCode: "ShopInfo",
link: '/store-info'
},
{
groupName: "员工管理",
groupCode: "ShopStaff",
link: '/employees-manage'
......
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