Commit ed917f83 by guomingpang

Merge branch 'dev' of…

Merge branch 'dev' of ssh://xmgit.ixm5.cn:10022/xiaomai-cloud-class/xiaomai-cloud-class-web into dev
parents 557c810e 57ead295
......@@ -13443,7 +13443,7 @@
},
"rc-tabs": {
"version": "11.9.1",
"resolved": "https://registry.nlark.com/rc-tabs/download/rc-tabs-11.9.1.tgz?cache=0&sync_timestamp=1626861953850&other_urls=https%3A%2F%2Fregistry.nlark.com%2Frc-tabs%2Fdownload%2Frc-tabs-11.9.1.tgz",
"resolved": "https://registry.nlark.com/rc-tabs/download/rc-tabs-11.9.1.tgz",
"integrity": "sha1-Wy502ponaXjCFy75oFrorxTadMs=",
"requires": {
"@babel/runtime": "^7.11.2",
......
......@@ -114,7 +114,7 @@
"start:prod": "cross-env DEPLOY_ENV=prod node scripts/start.js",
"start:syoo": "better-npm-run start:syoo",
"build:dev": "cross-env DEPLOY_ENV=dev node scripts/build.js",
"build:dev1": "cross-env DEPLOY_ENV=dev node scripts/build.js",
"build:dev1": "better-npm-run build:dev1",
"build:rc": "cross-env DEPLOY_ENV=rc node scripts/build.js",
"build:gray": "cross-env DEPLOY_ENV=gray node scripts/build.js",
"build:syoo": "better-npm-run build:syoo",
......@@ -134,6 +134,13 @@
"DEPLOY_ENV": "prod",
"BRAND": "syoo"
}
},
"build:dev1":{
"command": "node scripts/build.js",
"env": {
"DEPLOY_ENV": "dev1",
"BRAND": "syoo"
}
}
},
"eslintConfig": {
......
......@@ -104,7 +104,7 @@
const appTermEnum = getParameterByName('appTermEnum');
const code = getParameterByName('code');
const ticket = getParameterByName('ticket');
const corpType = getParameterByName('corpType');
const corpType = getParameterByName('corpType') || 'X_MAI';
......@@ -119,7 +119,8 @@
postJSON("hades/anon/hades/wXWorkUserTicketLogin", {
appTermEnum: appTermEnum,
code: code,
ticket: ticket
ticket: ticket,
corpType
}, (res) => {
if (res.code == 200) {
$('#success').show()
......
......@@ -130,9 +130,7 @@ class Axios {
if (method === 'GET') {
config = Object.assign({ params, url: `${BASIC_HOST}${_url}`, method });
} else {
console.log(corpType)
config = Object.assign({ data: { corpType, ...(params || {}) }, url: `${BASIC_HOST}${_url}`, method });
console.log(config,'config')
}
instance(config).then((res: AxiosResponse): void => {
......
......@@ -40,4 +40,4 @@ module.exports = {
return /xmappc/i.test(ua);
},
};
\ No newline at end of file
......@@ -2,7 +2,7 @@
* @Author: wufan
* @Date: 2021-05-11 10:21:37
* @LastEditors: Please set LastEditors
* @LastEditTime: 2021-07-21 14:25:37
* @LastEditTime: 2021-07-19 15:24:27
* @Description: 企业微信api
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*
......@@ -155,4 +155,21 @@ export default class WechatApi {
});
});
}
//进入直播间
static enterLiveRoom(id) {
return new Promise((resolve, reject) => {
wx.ready(() => {
wx.invoke('startLiving', {
"livingId": id,
}, function(res) {
if (res.err_msg === "startLiving:ok") {
resolve(true)
} else {
reject(res.err_msg); //错误处理
}
});
});
})
}
}
@font-face {
font-family: 'iconfont'; /* Project id 2223403 */
src: url('//at.alicdn.com/t/font_2223403_oe5p510553.woff2?t=1624259078391') format('woff2'),
url('//at.alicdn.com/t/font_2223403_oe5p510553.woff?t=1624259078391') format('woff'),
url('//at.alicdn.com/t/font_2223403_oe5p510553.ttf?t=1624259078391') format('truetype');
font-family: 'iconfont'; /* Project id 2223403 */
src: url('//at.alicdn.com/t/font_2223403_6hd3qwwrou2.woff2?t=1627033726611') format('woff2'),
url('//at.alicdn.com/t/font_2223403_6hd3qwwrou2.woff?t=1627033726611') format('woff'),
url('//at.alicdn.com/t/font_2223403_6hd3qwwrou2.ttf?t=1627033726611') format('truetype');
}
.iconfont {
font-family: 'iconfont' !important;
......
import React, { useRef, useLayoutEffect } from 'react'
export default function WWOpenDataCom({ type, openid }) {
const ref = useRef(null)
useLayoutEffect(() => {
console.log('1111');
console.log(WWOpenData);
WWOpenData && WWOpenData.bind(ref.current)
})
return <ww-open-data ref={ref} type={type} openid={openid} />
}
\ No newline at end of file
import React, { useRef, useLayoutEffect } from 'react'
export default function WWOpenDataCom({ type, openid }) {
import React, { useContext, useRef, useLayoutEffect } from 'react'
import { XMContext } from '@/store/context';
import WWOpenData from './WWOpenData'
export default function WWOpenDataCom(props) {
const ctx = useContext(XMContext);
const ref = useRef(null)
useLayoutEffect(() => {
console.log(WWOpenData)
WWOpenData && WWOpenData.bind(ref.current)
})
return <ww-open-data ref={ref} type={type} openid={openid} />
return ctx.xmState.wechatLogin ? <WWOpenData {...props} /> : <div></div>
}
\ No newline at end of file
......@@ -330,9 +330,9 @@ mr0 {
}
// ant badge改小
.ant-badge {
transform: translate(-8px, -8px) scale(0.7) !important;
}
// .ant-badge {
// transform: translate(-8px, -8px) scale(0.7) !important;
// }
.ant-select-selection {
border-color: @xm-color-border !important;
......
import Bus from './bus';
class routeHook {
constructor() {
this.routeFun = [];
this.callBacks = []
}
add(callback) { //切换路由之前添加的函数
this.routeFun = [callback]
}
addJump(callback) {
this.callBacks = [callback]
}
pop() { //去除回调
this.routeFun.pop();
}
cancel() { //取消跳转
this.routeFun.pop()
}
break() { //切换路由是执行的函数
const enterFun = this.routeFun[0];
enterFun && enterFun()
}
leave() { //切换路由
const callBacks = this.callBacks.pop();
callBacks && callBacks()
this.routeFun = [];
}
//离开保存时的特例
// **
addSaveCase() { //离开保存校验时将方法注入
this.add(this.saveBeforeLeave.bind(this))
}
saveBeforeLeave() { //离开保存时触发的方法
Bus.trigger('showRouteChangeModal')
}
//** */
getCallbackNum() {
return this.routeFun.length
}
}
export default new routeHook()
\ No newline at end of file
......@@ -12,6 +12,9 @@ import Service from "@/common/js/service";
export function fetchLecturerData(params: object) {
return Service.Hades("public/courseCloud/queryTeacherVisitData", params);
}
export function fetchWorkWXLecturerData(params: object) {
return Service.Hades("public/courseCloud/queryWechatLiveTeacherData", params);
}
export function getQrcode(params: object) {
return Service.Sales("public/businessShow/convertShortUrls", params);
}
......@@ -19,11 +22,18 @@ export function getQrcode(params: object) {
export function fetchUserData(params: object) {
return Service.Hades("public/courseCloud/queryStudentVisitData", params);
}
export function fetchWorkWXUserData(params: object) {
return Service.Hades("public/courseCloud/queryWechatLiveStudentData", params);
}
export function createLiveCloudCourse(params: object) {
return Service.Hades("public/courseCloud/createLiveCloudCourse", params);
}
export function createWorkWXLiveCourse(params: object) {
return Service.Hades("public/courseCloud/createWechatLiveCourse", params);
}
export function getLiveCloudCoursePage(params: object) {
return Service.Hades("public/courseCloud/getLiveCloudCoursePage", params);
}
......@@ -42,16 +52,27 @@ export function getLiveCloudCourseDetail(params: object) {
return Service.Hades("public/courseCloud/getLiveCloudCourseDetail", params);
}
export function getWorkWXLiveCourseDetail(params: object) {
return Service.Hades("public/courseCloud/getWechatLiveCourseDetail", params)
}
export function updateLiveCloudCourse(params: object) {
return Service.Hades("public/courseCloud/updateLiveCloudCourse", params);
}
export function updateWorkWXLiveCourse(params: object) {
return Service.Hades("public/courseCloud/editWechatLiveCourse", params);
}
export function turnOnOrOffLiveCloudCourse(params: object) {
return Service.Hades("public/courseCloud/turnOnOrOffLiveCloudCourse", params);
}
export function delLiveCloudCourse(params: object) {
return Service.Hades("public/courseCloud/delLiveCloudCourse", params);
}
export function delWorkWXLiveCourse(params: object) {
return Service.Hades("public/courseCloud/delWechatLiveCourse", params);
}
//该接口主要用于培训计划关联直播课的接口(会筛选掉已关联的直播课)
export function getLiveCloudCourseBasePage(params: object) {
return Service.Hades("public/courseCloud/getLiveCloudCourseBasePage", params);
......
/*
* @Author: wufan
* @Date: 2020-11-25 18:25:02
* @LastEditors: zhangleyuan
* @LastEditTime: 2021-03-09 10:28:03
* @LastEditors: Please set LastEditors
* @LastEditTime: 2021-07-30 17:00:06
* @Description: Description
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
......@@ -75,6 +75,36 @@ export function updateStoreMessage(params: object) {
export function getStoreDetail(params: object) {
return Service.Hades("public/hades/getStoreDetail", params);
}
export function getByDepartmentId(params: object) {
return Service.Hades("public/hades/getByDepartmentId", params);
}
export function getDepartmentUser(params: object) {
return Service.Hades("/public/hades/getDepartmentAndDepartmentUserByName", params);
}
export function getDepartmentUserNotPage(params: object) {
return Service.Hades("public/hades/getDepartmentAndDepartmentUserNotPageByName", params);
}
export function addDepartment(params: object) {
return Service.Hades("public/hades/addDepartment", params);
}
export function editDepartment(params: object) {
return Service.Hades("public/hades/editDepartment", params);
}
export function delDepartment(params: object) {
return Service.Hades("public/hades/delDepartment", params);
}
export function queryDepartmentTree(params: object) {
return Service.Hades("public/hades/queryDepartmentTree", params);
}
export function getStoreCustomerAndDepNamePage(params: object) {
return Service.Hades("public/hades/getStoreCustomerAndDepNamePage", params);
}
export function delDepartmentUser(params: object) {
return Service.Hades("public/hades/delDepartmentUser", params);
}
export function syncWorkWeChatDepartment(params: object) {
return Service.Hades("public/hades/syncWorkWeChatDepartment", params);
}
export function getSyncCount(params: object) {
return Service.Hades("public/hades/getSyncCount", params);
}
......@@ -7,21 +7,21 @@
* @FilePath: /wheat-web-demo/src/domains/basic-domain/constants.ts
*/
import { MapInterface } from '@/domains/basic-domain/interface'
import { path,live } from '@/domains/brand/constants'
import { path, live } from '@/domains/brand/constants'
// 默认是 dev 环境
const ENV: string = process.env.DEPLOY_ENV || 'dev'
console.log('process.env.DEPLOY_ENV', process.env, ENV, 'hjkkkk')
const BASIC_HOST_MAP: MapInterface = {
dev: 'https://dev-heimdall.xiaomai5.com/',
dev1: 'https://dev1-heimdall.xiaomai5.com/',
dev1: 'https://dev-heimdall.xiaomai5.com/',
rc: 'https://rc-heimdall.xiaomai5.com/',
gray: 'https://gray-heimdall.xiaomai5.com/',
prod: 'https://gateway.xiaomai5.com/',
}
const PATH_MAP: MapInterface = {
dev: 'https://dev.xiaomai5.com/xiaomai-cloud-class-web/h5.html',
dev1: 'https://dev.xiaomai5.com/xiaomai-cloud-class-web/h5.html',
dev1: 'https://dev.xiaomai5.com/dev1/xiaomai-cloud-class-web/h5.html',
rc: 'https://rc.xiaomai5.com/xiaomai-cloud-class-web/h5.html',
gray: 'https://res.xiaomai0.com/xiaomai-cloud-class-web/gray/h5.html',
prod: path,
......
......@@ -28,7 +28,7 @@ const PATH_MAP: any = {
const LIVE_SHARE_MAP: any = {
xiaomai: 'https://res.xiaomai0.com/store-live/index.html#/',
syoo: 'https://res.xiaomai0.com/store-live/index.html#/',
syoo: 'https://dev.xiaomai5.com/dev1/store-live/index.html#/',
}
......
......@@ -10,7 +10,7 @@ import {
fetchLecturerData, getCategoryTree, knowledgeMediaCoursePage, fetchUserData, exportStudentCourseData, exportPlayBackCourseData, fetchPlaybackList, createLiveCloudCourse, getLiveCloudCoursePage,
getLiveCloudCourseDetail, updateLiveCloudCourse, turnOnOrOffLiveCloudCourse, delLiveCloudCourse, changeVideoShelfState, createVideoSchedule, delVideoSchedule,
editVideoSchedule, userWatchInfo, videoSchedulePage, videoScheduleDetail, videoWatchInfo, getQrcode, getLiveCloudCourseBasePage, videoScheduleBasePage, relatedCourseToPlan,
lineDetailWatchInfo
lineDetailWatchInfo, createWorkWXLiveCourse, fetchWorkWXLecturerData, fetchWorkWXUserData, getWorkWXLiveCourseDetail, updateWorkWXLiveCourse, delWorkWXLiveCourse
} from '@/data-source/course/request-api';
export default class courseService {
......@@ -18,6 +18,10 @@ export default class courseService {
static fetchLecturerData(params: any) {
return fetchLecturerData(params);
}
// 获取企微讲师上课数据
static fetchWorkWXLecturerData(params: any) {
return fetchWorkWXLecturerData(params);
}
// 生成二维码
static getQrcode(params: any) {
......@@ -28,9 +32,17 @@ export default class courseService {
static fetchUserData(params: any) {
return fetchUserData(params);
}
// 获取企微学员上课数据
static fetchWorkWXUserData(params: any) {
return fetchWorkWXUserData(params);
}
static createLiveCloudCourse(params: any) {
return createLiveCloudCourse(params);
}
//创建企微直播课
static createWorkWXLiveCourse(params: any) {
return createWorkWXLiveCourse(params)
}
static getLiveCloudCoursePage(params: any) {
return getLiveCloudCoursePage(params);
}
......@@ -53,15 +65,27 @@ export default class courseService {
static getLiveCloudCourseDetail(params: any) {
return getLiveCloudCourseDetail(params);
}
//获取企微直播详情
static getWorkWXLiveCourseDetail(params: any) {
return getWorkWXLiveCourseDetail(params);
}
static updateLiveCloudCourse(params: any) {
return updateLiveCloudCourse(params);
}
//编辑企微直播
static updateWorkWXLiveCourse(params: any) {
return updateWorkWXLiveCourse(params);
}
static turnOnOrOffLiveCloudCourse(params: any) {
return turnOnOrOffLiveCloudCourse(params);
}
static delLiveCloudCourse(params: any) {
return delLiveCloudCourse(params);
}
//删除企微直播
static delWorkWXLiveCourse(params: any) {
return delWorkWXLiveCourse(params);
}
static changeVideoShelfState(params: any) {
return changeVideoShelfState(params);
}
......
......@@ -28,7 +28,7 @@ const shareUrlMap: MapInterface = {
const LIVE_SHARE_MAP: MapInterface = {
dev: 'https://dev.xiaomai5.com/store-live/index.html#/',
dev1: 'https://dev.xiaomai5.com/store-live/index.html#/',
dev1: 'https://dev.xiaomai5.com/dev1/store-live/index.html#/',
rc: 'https://rc.xiaomai5.com/store-live/index.html#/',
gray: 'https://res.xiaomai0.com/store-live/gray/index.html#/',
prod: live,
......
/*
* @Author: zhangleyuan
* @Date: 2021-01-19 11:27:56
* @LastEditors: zhangleyuan
* @LastEditTime: 2021-03-08 10:36:04
* @LastEditors: Please set LastEditors
* @LastEditTime: 2021-07-29 13:37:10
* @Description: 描述一下
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
......@@ -12,6 +12,7 @@ export const storeRoleEnum = {
"1": "管理员",
"2": "普通讲师"
};
export const industryList = ["IT服务","制造业","批发/零售","生活服务","文化/体育/娱乐业","建筑/房地产","教育","运输/物流/仓储","医疗","政府","金融","能源/采矿","农林渔牧","其他行业"];
export const childIndustryList = {
......@@ -29,4 +30,9 @@ export const childIndustryList = {
"能源/采矿":["电力/热力/燃气/水供应业","石油/天然气","煤炭","有色金属","钢铁","其他"],
"农林渔牧":["农林渔牧"],
"其他行业":["科学研究和技术服务业","社会组织","水利和环境管理","国际组织","其他"]
}
export const DepType = {
'departMentTab':'DEP_ORG',
'postGrouptab':'DEP_POST',
'customGroupTab':'DEP_CUSTOM'
}
\ No newline at end of file
/*
* @Author: wufan
* @Date: 2020-11-25 18:25:02
* @LastEditors: zhangleyuan
* @LastEditTime: 2021-03-08 11:48:43
* @LastEditors: Please set LastEditors
* @LastEditTime: 2021-08-01 09:38:54
* @Description: Description
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
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';
moveBannerSequence,getStoreUserBasicPage,updateStoreMessage,getStoreDetail,getByDepartmentId,getDepartmentUser,getDepartmentUserNotPage,addDepartment,
editDepartment,delDepartment,queryDepartmentTree,getStoreCustomerAndDepNamePage,delDepartmentUser,syncWorkWeChatDepartment,getSyncCount
} from '@/data-source/store/request-apis';
export default class StoreService {
// 获取员工列表
......@@ -89,4 +91,37 @@ export default class StoreService {
static getStoreDetail(params: any) {
return getStoreDetail(params);
}
static getByDepartmentId(params:any){
return getByDepartmentId(params);
}
static getDepartmentUser(params:any){
return getDepartmentUser(params);
}
static getDepartmentUserNotPage(params:any){
return getDepartmentUserNotPage(params);
}
static addDepartment(params:any){
return addDepartment(params);
}
static editDepartment(params:any){
return editDepartment(params);
}
static delDepartment(params:any){
return delDepartment(params);
}
static queryDepartmentTree(params:any){
return queryDepartmentTree(params);
}
static getStoreCustomerAndDepNamePage(params:any){
return getStoreCustomerAndDepNamePage(params);
}
static delDepartmentUser(params:any){
return delDepartmentUser(params);
}
static syncWorkWeChatDepartment(params:any){
return syncWorkWeChatDepartment(params);
}
static getSyncCount(params:any){
return getSyncCount(params);
}
}
\ No newline at end of file
declare module 'jquery'
declare module 'cropper'
declare module 'ExamShareModal'
declare module 'routeHooks'
// declare var this: any
\ No newline at end of file
......@@ -2,7 +2,7 @@
* @Author: 吴文洁
* @Date: 2020-08-24 12:20:57
* @LastEditors: Please set LastEditors
* @LastEditTime: 2021-08-02 17:00:14
* @LastEditTime: 2021-08-03 14:27:49
* @Description:
* @Copyright: 杭州杰竞科技有限公司 版权所有
-->
......@@ -29,8 +29,8 @@
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<link rel="stylesheet" href="//at.alicdn.com/t/font_2223403_oe5p510553.css" />
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<link rel="stylesheet" href="//at.alicdn.com/t/font_2223403_6hd3qwwrou2.css" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
......
......@@ -24,6 +24,7 @@ import User from '@/common/js/user';
import Service from "@/common/js/service";
import BaseService from '@/domains/basic-domain/baseService';
import {brandName,BRAND,brandIcon} from '@/domains/brand/constants'
import routeHook from '@/core/routeHook'
declare var getParameterByName: any;
declare var window: any;
......@@ -31,11 +32,7 @@ window.currentStoreUserInfo = {}
const history = createHashHistory();
document.title=brandName;
var iconUrl ='https://image.xiaomaiketang.com/xm/WGWCtxiGzE.png'
if(BRAND !='xiaomai'){
iconUrl =brandIcon
}
var iconUrl =brandIcon;
var linkzh = document.createElement('link');
linkzh.setAttribute('rel',"shortcut icon");
linkzh.setAttribute('href',iconUrl);
......@@ -43,7 +40,16 @@ document.head.appendChild(linkzh);
window.RCHistory = _.extend({}, history, {
push: (obj: any) => {
history.push(obj)
console.log(routeHook.getCallbackNum(), 'routeHook.getCallbackNum()')
if (routeHook.getCallbackNum()) {
routeHook.break();
routeHook.addJump(() => {
history.push(obj)
})
} else {
history.push(obj)
}
},
pushState: (obj: any) => {
history.push(obj)
......@@ -51,13 +57,21 @@ window.RCHistory = _.extend({}, history, {
pushStateWithStatus: (obj: any) => {
history.push(obj)
},
goBack: history.goBack,
goBack: () => {
console.log(routeHook.getCallbackNum(), 'routeHook.getCallbackNum()')
history.goBack()
},
location: history.location,
replace: (obj: any) => {
history.replace(obj)
}
});
window.onhashchange = () => {
routeHook.cancel()
}
function mount() {
ReactDOM.render(
<RootRouter />,
......@@ -85,19 +99,19 @@ if (getParameterByName('code') && isWeiXin()) {
window.currentStoreUserInfo.enterpriseId = res.result.enterpriseId;
mount()
})
} else if(getParameterByName('from') === 'customer' && getParameterByName('enterpriseId') && getParameterByName('userId')){
} else if (getParameterByName('from') === 'customer' && getParameterByName('enterpriseId') && getParameterByName('userId')) {
User.setCustomerStoreId(getParameterByName('storeId'));
getWXWorkLoginNoCheck(getParameterByName('enterpriseId'),getParameterByName('userId')); //从C端跳转过来的学院自动执行免登录
}else{
getWXWorkLoginNoCheck(getParameterByName('enterpriseId'), getParameterByName('userId')); //从C端跳转过来的学院自动执行免登录
} else {
mount()
}
function getWXWorkLoginNoCheck(enterpriseId:string,userId:string) {
function getWXWorkLoginNoCheck(enterpriseId: string, userId: string) {
const params = {
appTermEnum: 'XIAOMAI_CLOUD_CLASS_PC_WEB_ADMIN',
enterpriseId,
userId,
};
BaseService.getWXWorkLoginNoCheck(params).then((res:any) => {
BaseService.getWXWorkLoginNoCheck(params).then((res: any) => {
User.setUserId(res.result.loginInfo.userId)
User.setToken(res.result.loginInfo.xmToken)
User.setEnterpriseId(res.result.enterpriseId)
......
......@@ -5,4 +5,16 @@
.add-show-btn{
margin-top:12px;
}
.update-user-btn{
margin-left:8px;
margin-right:8px;
}
.origin-text{
font-size:14px;
color:#999;
}
.view-text{
font-size:14px;
color:#5289FA;
}
}
\ No newline at end of file
......@@ -20,7 +20,7 @@ import WWOpenDataCom from '@/components/WWOpenDataCom';
import LimitTip from "./LimitTip";
import "./EmployeeManage.less";
import ChooseMembersModal from "./modal/ChooseMembersModal";
import NewChooseMembersModal from "./modal/NewChooseMembersModal";
const { confirm } = Modal;
const { Search } = Input;
......@@ -34,6 +34,7 @@ interface RecordTypes {
phone: string;
avatar?: string;
weChatAccount?: string;
depNameList:Array<string>
}
interface RoleItemType {
......@@ -174,7 +175,21 @@ function EmployeeManage() {
},
},
{
title: "角色",
title: "部门",
dataIndex: "depNameList",
key: "depNameList",
render: (val:string,record:RecordTypes) => {
if(!record.depNameList){
return <span>-</span>
}
return record.depNameList.map((item,index)=>{
return <span><WWOpenDataCom type="departmentName" openid={item}/>{index<(record.depNameList.length -1)?'、':''}</span>;
})
},
},
{
title: "身份",
dataIndex: "role",
key: "role",
render: (val: string) => {
......@@ -281,6 +296,55 @@ function EmployeeManage() {
getEmployeeList();
});
}
function updateListData(){
let num:any;
const params = {
enterpriseId:User.getEnterpriseId(),
storeId:User.getStoreId(),
userType:'USER'
}
StoreService.getSyncCount(params).then((res) => {
num = res.result;
if(num<3){
return confirm({
title: "确定更新列表数据吗?",
content: `员工数据来源企微通讯录,一天只能更新3次,今日还能更新${3-num}次。`,
icon: (
<span className="icon iconfont default-confirm-icon">&#xe839; </span>
),
okText: "确定",
cancelText: "取消",
onOk: () => {
confirmUpdateListData()
},
});
}else{
Modal.warning({
title: '提示',
okText: '我知道了',
content: '员工数据今日更新次数已达上限(3次),无法继续更新。',
icon: (
<span className='icon iconfont default-confirm-icon' style={{ color: '#FFBB54 !important' }}>
&#xe834;
</span>
),
});
}
});
}
function confirmUpdateListData(){
const params = {
enterpriseId:User.getEnterpriseId(),
storeId:User.getStoreId(),
userType:'USER'
}
StoreService.syncWorkWeChatDepartment(params).then((res) => {
message.success('已更新');
});
}
return (
<div className="page employee-manage-page">
......@@ -372,16 +436,26 @@ function EmployeeManage() {
</div>
</div>
{(User.getUserRole() === 'CloudManager' || User.getUserRole() === 'StoreManager') &&
<Button
onClick={() => {
handleToAddEmployee();
}}
type="primary"
className="add-show-btn"
>
添加员工
</Button>
}
<>
<Button
onClick={() => {
handleToAddEmployee();
}}
type="primary"
className="add-show-btn"
>
添加员工
</Button>
<Button className="update-user-btn" onClick={()=>{updateListData()}}>更新列表数据</Button>
<span className="origin-text">数据来源企业微信通讯录</span>
<a
href="https://www.yuque.com/wangzhong-zkqw0/qixue"
target="_blank"
>
<span className="view-text">查看数据更新说明</span>
</a>
</>
}
</div>
<LimitTip type="员工" total={realTotal} tip={() => { return (<div>数据为当前学院的员工数,若员工存在多个学院,企业人数只统计为1人</div>) }} />
<div className="box-body">
......@@ -413,16 +487,16 @@ function EmployeeManage() {
</div>
{model}
{employeeModal &&
<ChooseMembersModal
isOpen={employeeModal}
type="USER"
handleChooseModal={(bool: any) => {
<NewChooseMembersModal
treeDepType="DEP_CHAT"
visible={employeeModal}
type="USER"
close={()=>{setEmployeeModal(false)}}
onConfirm={() => {
setEmployeeModal(false)
if (bool) {
message.success('添加成功')
getEmployeeList();
}
}}
}}
/>
}
</div>
......
/*
* @Author: your name
* @Date: 2021-08-04 15:21:36
* @LastEditTime: 2021-08-04 15:27:16
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: /xiaomai-cloud-class-web/src/modules/college-manage/LimitTip.tsx
*/
import React, { useContext, useEffect, useState } from "react";
import { Tooltip } from "antd"
import { VersionContext } from "@/store/context";
......@@ -26,7 +34,7 @@ export default function LimitTip(props:{total:number,type:string,tip:() => React
{
isOver ? (
<>
<div style={{marginLeft:"14px",display:"inline-block"}}>{`当前企业使用人数已达到上限 (<span style={{color:"#333333",fontWeight:"bold"}}>{limitUser}</span>人),将无法添加新员工、新学员,如需增加人数限制,请联系${window.brandName}服务平台。`}</div>
<div style={{marginLeft:"14px",display:"inline-block"}}>当前企业使用人数已达到上限 (<span style={{color:"#333333",fontWeight:"bold"}}>{limitUser}</span>人),将无法添加新员工、新学员,如需增加人数限制,请联系{window.brandName}服务平台。</div>
<ContactWidget trigger="hover" placement="bottom">
<div className="renew-text">立即续费<span className="icon iconfont" style={{fontSize:"10px"}}>&#59291;</span></div>
</ContactWidget>
......
/*
* @Author: wufan
* @Date: 2020-11-30 10:47:38
* @LastEditors: Please set LastEditors
* @LastEditTime: 2021-08-03 16:04:30
* @Description: 学员管理页面
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import React, { useEffect, useState } from "react";
import { withRouter } from "react-router-dom";
import _ from "underscore";
import {Tabs,Input,Tree,Button} from "antd";
import CustomGroupTabCon from './components/CustomGroupTabCon';
import DepartMentTabCon from './components/DepartMentTabCon';
import PostGroupTabCon from './components/PostGroupTabCon';
import "./NewUsersManagePage.less";
const { TabPane } = Tabs;
function UserManagePage() {
const [currentTab, setCurrentTab] = useState("departMentTab");
const [courseList,setCourseList] = useState([]);
const [total, setTotal] = useState(0);
const [query, setQuery] = useState({
current: 0,
size: 10,
});
return (
<div className="page new-user-manage-page">
<div className="content-header">学员管理</div>
<div className="box">
<div className="tab-box">
<Tabs
onChange={(key) => {
setCurrentTab(key);
}}
activeKey={currentTab}
>
<TabPane key="departMentTab" tab="部门"></TabPane>
<TabPane key="postGrouptab" tab="岗位组"></TabPane>
<TabPane key="customGroupTab" tab="自定义分组"></TabPane>
</Tabs>
</div>
<div className="box-body tab-con">
<DepartMentTabCon currentTab={currentTab}/>
</div>
</div>
</div>
);
}
export default withRouter(UserManagePage);
import React, { useEffect, useState } from "react";
import { withRouter } from "react-router-dom";
import { Button, Input, message } from "antd";
import LeftStructureTree from "./LeftStructureTree";
import AddOrEditPostGroupModal from "../modal/AddOrEditPostGroupModal";
import UserTable from "./UserTable";
import "./PostGroupTabCon.less";
const { Search } = Input;
function CustomGroupTabCon() {
const [postGroupTreeData, setPostGroupTreeData] = useState([]);
return (
<div className="post-group-tab-con">
<LeftStructureTree
treeData={postGroupTreeData}
treeType={"customGroupTab"}
editPostGroup={(record)=>editPostGroup(record)}
addPostGroup={(record)=>addPostGroup(record)}
/>
<div className="table-con">
<div className="operate-area">
<Button type="primary" className="add-user-btn">
添加学员
</Button>
<Button className="del-user-btn">移出学员</Button>
</div>
<UserTable />
</div>
</div>
);
}
export default withRouter(CustomGroupTabCon);
import React, { useEffect, useState } from "react";
import { withRouter } from "react-router-dom";
import { Button, Input, message,Modal} from "antd";
import NewChooseMembersModal from "@/modules/college-manage/modal/NewChooseMembersModal";
import LeftStructureTree from "./LeftStructureTree";
import { XMTable, PageControl } from "@/components";
import college from "@/common/lottie/college.json";
import WWOpenDataCom from '@/components/WWOpenDataCom';
import StoreService from "@/domains/store-domain/storeService";
import { DepType } from "@/domains/store-domain/constants";
import User from "@/common/js/user";
import moment from "moment";
import "./DepartMentTabCon.less";
import Bus from "@/core/bus";
import _ from 'underscore';
const { Search } = Input;
const { confirm } = Modal;
const DefaultQuery = {
size: 10,
current: 1,
};
function DepartMentTabCon(props) {
const [chooseMembersModalVisible, setChooseMembersModalVisible] = useState(
false
);
const [query, setQuery] = useState(DefaultQuery);
const [total, setTotal] = useState(0);
const [userListdata, setUserListData] = useState([]);
const [selectUser,setSelectUser] = useState([]); // 设置选中的用户
const [selectDep,setSelectDep] = useState({});
const columns = [
{
title: "学员",
dataIndex: "nickName",
width: 220,
render: (val, item) => {
return (
<div>
{item.sourceEnum === "WORK_WE_CHAT" ?
<span> <WWOpenDataCom type="userName" openid={val}/></span>:
<span>{val}</span>
}
<span
className="tag"
style={{
color:
item.sourceEnum === "WORK_WE_CHAT" ? "#2966FF" : "#1DCC65",
}}
>
{item.sourceEnum === "WORK_WE_CHAT" ? "@企业微信" : "@微信"}
</span>
</div>
);
},
},
{
title: "真实姓名",
dataIndex: "realName",
width: "15%",
render: (val, record) => {
return <span>{val}</span>;
},
},
{
title: "账号",
dataIndex: "nickName",
width: "15%",
render: (val, item) => {
return <span>{val}</span>;
},
},
{
title: "岗位",
dataIndex: "depNameList",
render: (val, record) => {
if(!record.depNameList){
return <span>-</span>
}else{
if(record.depNameList.length === 0){
return <span>-</span>
}
return record.depNameList.map((item, index) => {
return <span>{item}{index!==record.depNameList.length-1 && <span></span>}</span>;
})
}
}
},
{
title: "手机号",
dataIndex: "phone",
render: (val, item) => {
return <span>{val}</span>;
},
},
{
title: "注册时间",
dataIndex: "created",
render: (val, item) => {
return <div>{moment(val).format("YYYY-MM-DD HH:mm:ss")}</div>;
},
},
{
title: "操作",
key: "operate",
dataIndex: "operate",
render: (val, item) => {
return (
<div className="operate">
{props.currentTab==='departMentTab'?
<div className="operate__item" onClick={()=>delUser('single',item.userId)}>删除</div>
:
<div className="operate__item" onClick={()=>delUser('single',item.userId)}>移出</div>
}
</div>
);
},
},
];
function closeChooseMembersModal() {
setChooseMembersModalVisible(false);
}
function getUserList(record,treeType,current) {
const params = {
...query,
depType:DepType[treeType]|| DepType[props.currentTab],
enterpriseId: User.getEnterpriseId(),
source: 0,
storeId: User.getStoreId(),
userId: User.getUserId()
};
if(record){
if(record.id){
params.departmentId = record.id;
}else{
params.departmentId = null;
}
if(record.queryName){
params.nickName = record.queryName;
}else{
params.nickName = null;
}
}
if (current) {
params.current = current;
}
setQuery(params);
console.log('params ++++ ',params);
StoreService.getStoreCustomerAndDepNamePage(params).then((res) => {
const { records = [], total } = res.result;
setUserListData(records);
setTotal(total);
});
}
function confirmAddCustomer() {
const _query = {
...DefaultQuery,
id:query.departmentId
}
Bus.trigger("addCustomer",{treeType:props.currentTab,query:_query});
}
function delUser(type,userId){
let idList = [];
if(type === 'single'){
idList.push(userId);
}
if(type==='multiple'){
idList = _.pluck(selectUser,'userId');
}
if(idList.length===0){
message.warning('请先选择要删除的学员')
return;
}
return confirm({
title: "确定要删除学员吗?",
content: "删除后,该学员将从员工列表中删除,且看不到该学院用户端。",
icon: (
<span className="icon iconfont default-confirm-icon">&#xe839; </span>
),
okText: "删除",
okType: "danger",
cancelText: "取消",
onOk: () => {
handleConfirmDelUser(idList);
},
});
}
function handleConfirmDelUser(idList){
const params = {
depType:DepType[props.currentTab],
idList,
storeId:User.getStoreId()
}
console.log('selectDep',selectDep)
if(selectDep.id==='100'){
params.userType='WE_CHAT';
}else{
params.userType='WORK_WE_CHAT';
}
StoreService.delDepartmentUser(params).then((res) => {
message.success(`删除成功`);
getUserList();
});
}
function handleSelectUserList(record, selected){
let _list = [];
if (selected || !_.find(selectUser, (item) => item.userId === record.userId)) {
_list = _.uniq(selectUser.concat([record]), false, (item) => item.userId);
} else {
_list = _.reject(selectUser, (item) => item.userId === record.userId);
}
if (_list.length > 50) {
message.warning('无法继续选择,最多选择50个');
return;
}
console.log('selectUser',_list);
setSelectUser(_list);
};
function updateListData(){
let num;
const params = {
enterpriseId:User.getEnterpriseId(),
storeId:User.getStoreId(),
userType:'CUSTOMER'
}
StoreService.getSyncCount(params).then((res) => {
num = res.result;
if(num<3){
return confirm({
title: "确定更新列表数据吗?",
content: `学员数据来源企微通讯录,一天只能更新3次,今日还能更新${3-num}次。`,
icon: (
<span className="icon iconfont default-confirm-icon">&#xe839; </span>
),
okText: "确定",
cancelText: "取消",
onOk: () => {
confirmUpdateListData()
},
});
}else{
Modal.warning({
title: '提示',
okText: '我知道了',
content: '学员数据今日更新次数已达上限(3次),无法继续更新。',
icon: (
<span className='icon iconfont default-confirm-icon' style={{ color: '#FFBB54 !important' }}>
&#xe834;
</span>
),
});
}
});
}
function confirmUpdateListData(){
const params = {
enterpriseId:User.getEnterpriseId(),
storeId:User.getStoreId(),
userType:'CUSTOMER'
}
StoreService.syncWorkWeChatDepartment(params).then((res) => {
message.success('已更新');
});
}
return (
<div className="department-tab-con">
<LeftStructureTree
treeType={props.currentTab}
searchUserList={(params,treeType) => getUserList(params,treeType,1)}
onChangeSelectDep={(record)=>{setSelectDep(record);}}
/>
<div className="table-con">
{props.currentTab === "departMentTab" && (
<div className="operate-area">
{ selectDep.id !== '100' &&
<Button
type="primary"
className="add-user-btn"
onClick={() => {
setChooseMembersModalVisible(true);
}}
>
添加学员
</Button>
}
<Button className="del-user-btn" onClick={()=>delUser('multiple')}>删除学员</Button>
{ selectDep.id !== '100' &&
<>
<Button className="update-user-btn" onClick={()=>{updateListData()}}>更新列表数据</Button>
<span className="origin-text">数据来源企业微信通讯录</span>
<a
href="https://www.yuque.com/wangzhong-zkqw0/qixue"
target="_blank"
>
<span className="view-text">查看数据更新说明</span>
</a>
</>
}
</div>
)}
{(props.currentTab === "postGrouptab" ||
props.currentTab === "customGroupTab") && (
<div className="operate-area">
{/* 岗位组和自定义分组只有岗位下和分组才展示添加学员*/}
{(selectDep.depLevel > 0) &&
<Button
type="primary"
className="add-user-btn"
onClick={() => {
setChooseMembersModalVisible(true);
}}
>
添加学员
</Button>
}
<Button className="del-user-btn" onClick={()=>delUser('multiple')}>移出学员</Button>
</div>
)}
<div className="user-table">
<XMTable
renderEmpty={{
image: college,
description: "暂无数据",
}}
bordered
size="middle"
pagination={false}
columns={columns}
scroll={{ x: 800 }}
dataSource={userListdata}
rowKey={(record) => record.userId}
rowSelection={{
type: 'checkbox',
selectedRowKeys: _.pluck(selectUser, 'userId'),
onSelect: (record, selected) => {
console.log('record',record);
handleSelectUserList(record, selected)
},
onSelectAll: (selected, _selectedRows, changeRows) => {
let _list = [];
if (selected) {
_list = _.uniq(selectUser.concat(changeRows), false, (item) => item.userId);
} else {
_list = _.reject(selectUser, (item) => _.find(changeRows, (data) => data.userId === item.userId));
}
if (_list.length > 50) {
message.warning('无法继续选择,一个任务最多关联50个课程');
const extraLength = _list.length - 50;
_list.splice(_list.length - extraLength, extraLength);
}
setSelectUser(_list);
},
}}
/>
<div className="box-footer">
<PageControl
current={query.current}
pageSize={query.size}
total={total}
toPage={(page) => {
const queryStates = _.clone(query);
queryStates.current = page;
setQuery(queryStates);
getUserList(null,null,queryStates.current);
}}
/>
</div>
</div>
</div>
{chooseMembersModalVisible && (
<NewChooseMembersModal
visible={chooseMembersModalVisible}
type="CUSTOMER"
selectDep={selectDep}
treeDepType={
props.currentTab === "departMentTab" ? "DEP_CHAT" : "DEP_ORG"
}
addDepType={DepType[props.currentTab]}
close={() => {
closeChooseMembersModal();
}}
onConfirm={() => {
confirmAddCustomer();
}}
/>
)}
</div>
);
}
export default withRouter(DepartMentTabCon);
.department-tab-con{
display: flex;
.table-con{
margin-left:16px;
flex:1;
.operate-area{
margin-bottom:16px;
.add-user-btn{
margin-right:8px;
}
.del-user-btn{
margin-right:8px;
}
.update-user-btn{
margin-right:8px;
}
.origin-text{
font-size:14px;
color:#999;
}
.view-text{
font-size:14px;
color:#5289FA;
}
}
.operate{
.operate__item{
color:#2966FF;
cursor: pointer;
}
}
}
}
\ No newline at end of file
import React, { useEffect, useState } from "react";
import { withRouter } from "react-router-dom";
import { Tree, Input, Dropdown, Menu,Button,Modal,message,AutoComplete} from "antd";
import AddOrEditPostGroupModal from "../modal/AddOrEditPostGroupModal";
import User from '@/common/js/user'
import StoreService from "@/domains/store-domain/storeService";
import { DepType } from '@/domains/store-domain/constants';
import Bus from '@/core/bus';
import WWOpenDataCom from '@/components/WWOpenDataCom';
import "./LeftStructureTree.less";
const { Search } = Input;
const { DirectoryTree } = Tree;
const { Option } = AutoComplete;
function LeftStructureTree(props) {
const {treeType} = props;
const [treeData,setTreeData]=useState([]);
const [addOrEditPostGroupShow, setAddOrEditPostGroupShow] = useState(false);
const [postGroupModalLevel, setPostGroupModalLevel] = useState("");
const [operatePostGroupModalType,setOperatePostGroupModalType] = useState("");
const [postGroupModalTitle,setPostGroupModalTitle] = useState("");
const [postGroupModalLable,setPostGroupModalLable] = useState("");
const [postGroupName, setPostGroupName] = useState("");
const [currentGroupData,setCurrentGroupData] = useState({});
const [completeOptions,setCompleteOption] = useState([]);
const [selectedKeys,setSelectedKeys]= useState([]); // 设置选中的部门key值
const [queryName,setQueryName] = useState('');
const [postGroupTreeData,setPostGroupTreeData] = useState([]);
const [open,setOpen]=useState(false);
const renderTitle = (title) => (
<span>
{title}
</span>
);
const renderItem = (record,type) => ({
value: record.userName || record.name,
label: (
<div
style={{
display: 'flex',
justifyContent: 'space-between',
}}
>
{type === 'user'?
<div><WWOpenDataCom type="userName" openid={record.userName}/></div>
:
<div><WWOpenDataCom type="departmentName" openid={record.name}/></div>
}
{type === 'user' &&
record.postDepNamesList.map((item,index)=>{
return <span><WWOpenDataCom type="departmentName" openid={item}/></span>
})
}
{type === 'post' &&
<span>{record.parentName}</span>
}
</div>
),
});
const notFoundContentNode = ()=>{
return <span>暂无数据</span>
}
const Complete = () => (
<AutoComplete
dropdownClassName="certain-category-search-dropdown"
dropdownMatchSelectWidth={250}
allowClear
// onChange={(value)=>{setQueryName(value)}}
onSearch={(value)=>{setQueryName(value)}}
notFoundContent={notFoundContentNode()}
value={queryName}
open={open}
onFocus={()=>{setOpen(true)}}
onBlur={()=>{setOpen(false)}}
style={{
width: 250,
}}
options={completeOptions}
onSelect={confirmSearchSelect}
placeholder='搜索员工、部门'
>
</AutoComplete>
);
function confirmSearchSelect(value,option){
console.log('option',option);
setOpen(false);
setQueryName(value);
props.searchUserList({queryName:value},treeType,1);
}
// 获取关键词的搜索结果
function getCompleteOptionData(value){
// setQueryName(value);
console.log("treeType",props.treeType);
const params = {
depType:DepType[props.treeType],
queryName:value,
enterpriseId:User.getEnterpriseId(),
source:0,//0代表来自企培
storeId:User.getStoreId(),
userId:User.getUserId(),
whetherCount:false,
distinct:false,
queryType:'CUSTOMER'
}
StoreService.getDepartmentUser(params).then((res) => {
const _completeOptions = [];
const userObj = {};
const departmentGroupObj = {};
const postobj = {};
const { result = {}} = res;
const {departmentUserVOList=[],departmentVOList=[],subLevelDepartmentVOList=[]} = result;
if(departmentUserVOList.length>0){
userObj.label=renderTitle('员工');
userObj.options=departmentUserVOList.map((item,index)=>{
return renderItem(item,'user');
})
}
if(departmentVOList.length>0){
switch (props.treeType){
case 'departMentTab':
departmentGroupObj.label=renderTitle('部门');
break;
case 'postGrouptab':
departmentGroupObj.label=renderTitle('岗位组');
break;
case 'customGroupTab':
departmentGroupObj.label=renderTitle('分组集合');
break;
default:
break;
}
departmentGroupObj.options=departmentVOList.map((item,index)=>{
return renderItem(item,'group');
})
}
if(subLevelDepartmentVOList.length>0){
switch (props.treeType){
case 'postGrouptab':
postobj.label=renderTitle('岗位');
break;
case 'customGroupTab':
postobj.label=renderTitle('分组');
break;
default:
break;
}
postobj.options=subLevelDepartmentVOList.map((item,index)=>{
return renderItem(item,'post');
})
}
if(Object.keys(userObj).length !==0){
_completeOptions.push(userObj);
}
if(Object.keys(departmentGroupObj).length !==0){
_completeOptions.push(departmentGroupObj);
}
if(Object.keys(postobj).length !==0){
_completeOptions.push(postobj);
}
setCompleteOption(_completeOptions);
});
}
useEffect(()=>{
setQueryName(''); //切换tab时搜索置空
setCompleteOption([]);
setOpen(false); //切换tab时搜索的下拉框置为空
getTreeData().then((res)=>{
const _defaultSelectedKeys = [];
if(res.length > 0){
_defaultSelectedKeys.push(res[0].id);
setSelectedKeys(_defaultSelectedKeys);
props.onChangeSelectDep(res[0])
props.searchUserList(res[0],treeType,1);
}
});
},[props.treeType]);
useEffect(()=>{
Bus.bind("addCustomer",(record)=>{addCustomer(record.treeType,record.query)})
},[]);
async function addCustomer(treeType,query){
await getTreeData(treeType);
props.searchUserList(query,treeType,1);
}
function getTreeData(treeType){
return new Promise((resolve,reject)=>{
const params = {
departmentTypeEnum:DepType[treeType] || DepType[props.treeType],
enterpriseId:User.getEnterpriseId(),
source:0,//0代表来自企培
storeId:User.getStoreId(),
userId:User.getUserId(),
whetherCount:true
}
StoreService.queryDepartmentTree(params).then((res) => {
const { result = []} = res
let { departmentVOList=[] } =result;
let _treeData = handleData(result);
setTreeData(_treeData);
resolve(result);
});
})
}
function handleData(dataArray){
const _dataArray = dataArray.map((item,index)=>{
item.key=item.id;
if(item.sonDepartmentVOList){
item.children = item.sonDepartmentVOList;
handleData(item.sonDepartmentVOList)
}
return item
})
return _dataArray;
}
const leftBoxWidth =
(document.getElementById("left-box") &&
document.getElementById("left-box").style.width) ||
"304px";
const moreOpenGroupOperate = (record) => (
<Menu>
<Menu.Item key="edit">
<span onClick={()=>{props.treeType==='postGrouptab'?editPostGroup(record):editCustomGroup(record)}}>编辑</span>
</Menu.Item>
{record.depLevel ===0 &&
<Menu.Item key="add" >
<span onClick={()=>{props.treeType==='postGrouptab'?addPostGroup(1,record):addCustomGroup(1,record)}}>
{props.treeType==='postGrouptab' &&
<span>新建岗位</span>
}
{props.treeType==='customGroupTab' &&
<span>新建分组</span>
}
</span>
</Menu.Item>
}
{ (record.departmentCount === 0 || !record.departmentCount) &&
<Menu.Item key="del">
<span onClick={()=>{props.treeType==='postGrouptab'?delPostGroup(record):delCustomGroup(record)}}>删除</span>
</Menu.Item>
}
</Menu>
);
function closeAddOrEditPostGroupModal() {
setAddOrEditPostGroupShow(false);
}
//添加岗位组/岗位
function addPostGroup(level,record) {
if (treeData.length === 10) {
message.error("岗位组数量已达10个上限");
return;
}
setCurrentGroupData({});
setAddOrEditPostGroupShow(true);
setOperatePostGroupModalType("add");
setPostGroupModalLevel(level);
setCurrentGroupData(record);
console.log('treeData',record);
if(level===0){
setPostGroupModalTitle('添加岗位组');
setPostGroupModalLable('岗位组');
setPostGroupTreeData(treeData);
}else{
setPostGroupModalTitle('添加岗位'); // sub代表岗位
setPostGroupModalLable('岗位');
setPostGroupTreeData(record.sonDepartmentVOList || []);
}
}
//编辑岗位组/岗位
function editPostGroup(record){
setAddOrEditPostGroupShow(true);
setOperatePostGroupModalType("edit");
//level为0的时候编辑的是岗位组 大于0的时候
setPostGroupModalLevel(record.depLevel);
setCurrentGroupData(record);
console.log('treeData',record);
if(record.depLevel===0){
setPostGroupModalTitle('编辑岗位组');
setPostGroupModalLable('岗位组');
setPostGroupTreeData(treeData);
}else{
setPostGroupModalTitle('编辑岗位');
setPostGroupModalLable('岗位');
setPostGroupTreeData([]);
}
}
function delPostGroup(record){
let title = '确认删除该岗位组吗?';
let content= '删除后,该岗位组下的岗位及也将全部删除。';
if(record.level>0){
title = '确认删除该岗位吗?';
content = '删除后,不可恢复';
}
Modal.confirm({
title,
content,
icon: <span className='icon iconfont default-confirm-icon'>&#xe6f4;</span>,
okText: '确定',
okType: 'danger',
cancelText: '取消',
onOk: () => {
delGroup(record);
},
});
}
function delGroup(record){
let parmas = {
departmentId:record.id,
enterpriseId:User.getEnterpriseId(),
source:0,
storeId:User.getStoreId(),
userId:User.getUserId()
}
StoreService.delDepartment(parmas).then((res) => {
message.success(`删除成功`)
getTreeData();
});
}
//添加自定义分组集合/分组
function addCustomGroup(level,record) {
if (treeData.length === 10) {
message.error("岗位组数量已达10个上限");
return;
}
setCurrentGroupData({});
setAddOrEditPostGroupShow(true);
setOperatePostGroupModalType("add");
setPostGroupModalLevel(level);
setCurrentGroupData(record)
if(level===0){
setPostGroupModalTitle('添加分组集合');
setPostGroupModalLable('分组集合');
setPostGroupTreeData(treeData);
}else{
setPostGroupModalTitle('添加分组'); // sub代表岗位
setPostGroupModalLable('分组');
setPostGroupTreeData(record.sonDepartmentVOList || []);
}
}
//编辑自定义分组集合/分组
function editCustomGroup(record){
setAddOrEditPostGroupShow(true);
setOperatePostGroupModalType("edit");
setPostGroupModalLevel(record.level);
setCurrentGroupData(record)
//level为0的时候编辑的是岗位组 大于0的时候
if(record.level===0){
setPostGroupModalTitle('编辑分组集合');
setPostGroupModalLable('分组集合');
setPostGroupTreeData(treeData);
}else{
setPostGroupModalTitle('编辑分组');
setPostGroupModalLable('分组');
setPostGroupTreeData([]);
}
}
function delCustomGroup(record){
let title = '确认删除该分组集合吗?';
let content= '删除后,该分组集合下的岗位及也将全部删除。';
if(record.level>0){
title = '确认删除该分组吗?';
content = '删除后,不可恢复';
}
Modal.confirm({
title,
content,
icon: <span className='icon iconfont default-confirm-icon'>&#xe6f4;</span>,
okText: '确定',
okType: 'danger',
cancelText: '取消',
onOk: () => {
delGroup(record)
},
});
}
function confirmAddOrEditPostGroup() {
closeAddOrEditPostGroupModal();
getTreeData()
}
function selectUserList(record,e){
const _selectKeys = [];
_selectKeys.push(e.selectedNodes[0].id)
setSelectedKeys(_selectKeys);
props.onChangeSelectDep(e.selectedNodes[0]);
props.searchUserList(e.selectedNodes[0],treeType,1);
}
return (
<div className="left-structure-tree">
<div className="organization">
<div className="search-con">
{/* <Complete/> */}
<AutoComplete
dropdownClassName="certain-category-search-dropdown"
dropdownMatchSelectWidth={250}
allowClear
onChange={(value)=>setQueryName(value)}
onSearch={(value)=>{getCompleteOptionData(value)}}
notFoundContent={notFoundContentNode()}
value={queryName}
open={open}
onFocus={()=>{setOpen(true)}}
onBlur={()=>{setOpen(false)}}
style={{
width: 250,
}}
options={completeOptions}
onSelect={confirmSearchSelect}
placeholder='搜索员工、部门'
>
</AutoComplete>
</div>
{ (props.treeType==='postGrouptab' || props.treeType=== 'customGroupTab') && (
<div className="operate">
{props.treeType==='postGrouptab' &&
<Button
className="add-btn"
onClick={() => {
addPostGroup(0)
}}
>
添加岗位组
</Button>
}
{props.treeType==='customGroupTab' &&
<Button
className="add-btn"
onClick={() => {
addCustomGroup(0)
}}
>
添加自定义分组
</Button>
}
</div>
)}
<div className="tree-con">
<DirectoryTree
defaultExpandAll
showIcon={false}
treeData={treeData}
selectedKeys={selectedKeys}
onSelect={selectUserList}
titleRender={(nodeData) => {
return (
<div
className="node-title-div"
onMouseOver={(e) => {
if((props.treeType==='postGrouptab' || props.treeType=== 'customGroupTab')){
if (nodeData.key === "null") return;
let moreDiv = e.currentTarget.getElementsByClassName(
"item-more"
)[0];
let countDiv = e.currentTarget.getElementsByClassName(
"item-count"
)[0];
if (moreDiv) {
moreDiv.style.visibility = "visible";
}
if (countDiv) {
countDiv.style.visibility = "hidden";
}
}
}}
onMouseOut={(e) => {
if((props.treeType==='postGrouptab' || props.treeType=== 'customGroupTab')){
if (nodeData.key === "null") return;
let moreDiv = e.currentTarget.getElementsByClassName(
"item-more"
)[0];
let countDiv = e.currentTarget.getElementsByClassName(
"item-count"
)[0];
if (moreDiv) {
moreDiv.style.visibility = "hidden";
}
if (countDiv) {
countDiv.style.visibility = "visible";
}
}
}}
>
<div className="item-icon">
<span className="icon iconfont title-icon">&#xe604;</span>
</div>
<div
className="item-title"
style={{
width:
leftBoxWidth <= "240px"
? "35%"
: leftBoxWidth <= "304px"
? "60%"
: "78%",
}}
>
{ props.treeType==='departMentTab'?
<span><WWOpenDataCom type="departmentName" openid={nodeData.name}/></span>
:
<span>{nodeData.name}</span>
}
</div>
<div className="item-count">({nodeData.departmentCount || 0})</div>
{ (props.treeType==='postGrouptab' || props.treeType=== 'customGroupTab') && (
<Dropdown overlay={moreOpenGroupOperate(nodeData)}>
<div className="item-more icon iconfont">&#xe927;</div>
</Dropdown>
)}
</div>
);
}}
/>
</div>
</div>
{addOrEditPostGroupShow && (
<AddOrEditPostGroupModal
onClose={() => {
closeAddOrEditPostGroupModal();
}}
onConfirm={() => {
confirmAddOrEditPostGroup();
}}
title={postGroupModalTitle}
postGroupModalLevel={postGroupModalLevel}
modalOperateType={operatePostGroupModalType}
postGroupName={postGroupName}
postGroupTreeData={postGroupTreeData}
label={postGroupModalLable}
currentTab={props.treeType}
currentGroupData={currentGroupData}
/>
)}
</div>
);
}
export default withRouter(LeftStructureTree);
.left-structure-tree {
margin-right: 24px;
width:250px;
height: calc(~'100vh - 260px');
.organization{
overflow: scroll;
.search-con{
margin-bottom: 10px;
}
.operate {
margin-bottom:16px;
.add-btn {
width: 230px;
height:32px;
}
}
&::-webkit-scrollbar {
display: none;
}
.node-title-div {
display: flex;
justify-content: space-between;
white-space: nowrap;
.item-icon {
img {
width: 16px;
height: 16px;
}
}
.item-title {
position: absolute;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
width: 55%;
left: 28px;
}
.item-more {
visibility: hidden;
position: absolute;
right: 8px;
text-align: right;
}
.item-count {
visibility: visible;
position: absolute;
right: 12px;
text-align: right;
}
}
// 修改树样式
.ant-tree .ant-tree-treenode {
padding: 10px 0 14px 0;
}
.ant-tree.ant-tree-directory {
.ant-tree-node-selected{
color:#2966FF !important;
}
.ant-tree-treenode-selected:hover::before,
.ant-tree-treenode-selected::before {
background: #f3f6fa;
}
.ant-tree-treenode-selected .ant-tree-switcher {
color: #666666;
}
.ant-tree-treenode .ant-tree-node-content-wrapper {
color: #666666;
}
}
}
}
\ No newline at end of file
import React, { useEffect, useState } from "react";
import { withRouter } from "react-router-dom";
import { Tree} from "antd";
import StoreService from "@/domains/store-domain/storeService";
import User from '@/common/js/user';
import WWOpenDataCom from '@/components/WWOpenDataCom';
import "./MemberTree.less";
import _ from 'underscore';
const { DirectoryTree } = Tree;
function MemberTree(props) {
const [treeData,setTreeData]=useState([]);
useEffect(()=>{
getTreeData();
},[]);
function getTreeData(){
const params = {
depType:props.treeDepType,
enterpriseId:User.getEnterpriseId(),
source:0,//0代表来自企培
storeId:User.getStoreId(),
userId:User.getUserId(),
whetherCount:false,
distinct:true,
queryType:props.type
}
if(props.departmentId){
params.departmentId = props.departmentId;
}
if(props.nowTreeDepType){
params.nowDepType = props.nowTreeDepType;
}
StoreService.getDepartmentUserNotPage(params).then((res) => {
let { departmentVOList=[]} = res.result;
let _treeData = handleData(departmentVOList);
console.log("_treeData",_treeData);
setTreeData(_treeData);
});
}
function handleData(dataArray){
const _dataArray = dataArray.map((item,index)=>{
item.key=item.id;
item.children = []
if(item.departmentUserVOList){
item.children = item.departmentUserVOList;
}
if(item.sonDepartmentVOList){
item.children = [...item.children,...item.sonDepartmentVOList];
}
if(item.children.length > 0){
handleData(item.children)
}else{
delete item.children
}
return item
})
return _dataArray;
}
function treeSelected (selectedKeys,e){
const _checkedNodes = e.checkedNodes;
const _selectNodes = [];
_checkedNodes.map((item,index)=>{
if(item.userId){
_selectNodes.push(item);
}
})
console.log('_selectNodes',_selectNodes);
props.onSelect(_selectNodes);
}
return (
<div className="member-tree">
<div className="tree-con">
<DirectoryTree
defaultExpandAll
checkable
showIcon={false}
treeData={treeData}
checkedKeys={_.pluck(props.selectUserList, 'id')}
onCheck={(selectedKeys,e)=>treeSelected(selectedKeys,e)}
titleRender={(nodeData) => {
return (
<div
className="node-title-con"
>
{nodeData.userId ?
<div>
<span className="icon iconfont title-icon">&#xe603;</span>
<span><WWOpenDataCom type="userName" openid={nodeData.userName}/></span>
</div>
:
<div>
<span className="icon iconfont title-icon">&#xe604;</span>
<span><WWOpenDataCom type="departmentName" openid={nodeData.name}/></span>
</div>
}
</div>
);
}}
/>
</div>
</div>
);
}
export default withRouter(MemberTree);
.member-tree{
.node-title-con{
color:#666;
font-size:14px;
.title-icon{
margin-right:8px;
}
}
}
\ No newline at end of file
import React, { useEffect, useState } from "react";
import { withRouter } from "react-router-dom";
import { Button, Input, message,Modal} from "antd";
import LeftStructureTree from "./LeftStructureTree";
import UserTable from "./UserTable";
import "./PostGroupTabCon.less";
const { Search } = Input;
function PostGroupTabCon() {
// const [addOrEditPostGroupShow, setAddOrEditPostGroupShow] = useState(false);
// const [postGroupModalType, setPostGroupModalType] = useState("");
// const [operatePostGroupModalType,setOperatePostGroupModalType] = useState("");
// const [postGroupModalTitle,setPostGroupModalTitle] = useState("");
// const [postGroupModalLable,setPostGroupModalLable] = useState("");
const [postGroupTreeData, setPostGroupTreeData] = useState([]);
// function closeAddOrEditPostGroupModal() {
// setAddOrEditPostGroupShow(false);
// }
// //添加岗位组/岗位
// function addPostGroup(type) {
// if (postGroupTreeData.length === 10) {
// message.error("岗位组数量已达10个上限");
// return;
// }
// setAddOrEditPostGroupShow(true);
// setOperatePostGroupModalType("add");
// if(type==='parentGroup'){
// setPostGroupModalType('parentGroup'); //parentGroup 代表岗位组
// setPostGroupModalTitle('添加岗位组');
// setPostGroupModalLable('岗位组');
// }else{
// setPostGroupModalType('sub');
// setPostGroupModalTitle('添加岗位'); // sub代表岗位
// setPostGroupModalLable('岗位');
// }
// }
// //编辑岗位组/岗位
// function editPostGroup(record){
// setAddOrEditPostGroupShow(true);
// setOperatePostGroupModalType("edit");
// //level为0的时候编辑的是岗位组 大于0的时候
// if(record.level===0){
// setPostGroupModalType('parentGroup');
// setPostGroupModalTitle('编辑岗位组');
// setPostGroupModalLable('岗位组');
// }else{
// setPostGroupModalType('sub');
// setPostGroupModalTitle('编辑岗位');
// setPostGroupModalLable('岗位');
// }
// }
// function delPostGroup(record){
// let title = '确认删除该岗位组吗?';
// let content= '删除后,该岗位组下的岗位及也将全部删除。';
// if(record.level>0){
// title = '确认删除该岗位吗?';
// content = '删除后,不可恢复';
// }
// Modal.confirm({
// title,
// content,
// icon: <span className='icon iconfont default-confirm-icon'>&#xe6f4;</span>,
// okText: '确定',
// okType: 'danger',
// cancelText: '取消',
// onOk: () => {
// },
// });
// }
// function confirmAddOrEditPostGroup() {
// getPostGroupTreeData()
// }
return (
<div className="post-group-tab-con">
{/* <div className="organization">
<div className="search-con">
<Search
placeholder="搜索部门/学员姓名"
className="search search-input"
style={{ width: 245 }}
enterButton={<span className="icon iconfont">&#xe832;</span>}
/>
</div>
<div className="operate">
<Button
className="add-btn"
onClick={() => {
addPostGroup('postGroup');
}}
>
添加岗位组
</Button>
</div>
</div> */}
<LeftStructureTree
treeData={postGroupTreeData}
treeType={"postGrouptab"}
editPostGroup={(record)=>editPostGroup(record)}
addPostGroup={(record)=>addPostGroup(record)}
delPostGroup={(record)=>delPostGroup('record')}
/>
<div className="table-con">
<div className="operate-area">
<Button type="primary" className="add-user-btn">
添加学员
</Button>
<Button className="del-user-btn">移出学员</Button>
</div>
<UserTable />
</div>
{/* {addOrEditPostGroupShow && (
<AddOrEditPostGroupModal
onClose={() => {
closeAddOrEditPostGroupModal();
}}
onConfirm={() => {
confirmAddOrEditPostGroup();
}}
title={postGroupModalTitle}
modalType={postGroupModalType}
modalOperateType={operatePostGroupModalType}
postGroupName={postGroupName}
postGroupTreeData={postGroupTreeData}
label={postGroupModalLable}
/>
)} */}
</div>
);
}
export default withRouter(PostGroupTabCon);
.post-group-tab-con {
display: flex;
.table-con {
margin-left: 16px;
flex: 1;
.operate-area {
margin-bottom: 16px;
.add-user-btn {
margin-right: 8px;
}
.del-user-btn {
margin-right: 8px;
}
.update-user-btn {
margin-right: 8px;
}
.origin-text {
font-size: 14px;
color: #999;
}
.view-text {
font-size: 14px;
color: #5289fa;
}
}
}
}
import React, { useEffect, useState } from "react";
import { withRouter } from "react-router-dom";
import { Input,Checkbox} from "antd";
import StoreService from "@/domains/store-domain/storeService";
import User from '@/common/js/user';
import WWOpenDataCom from '@/components/WWOpenDataCom';
import $ from 'jquery';
import './SearchUser.less'
const { Search } = Input;
function SearchUser(props) {
const [dropDownVisible,setDropDownVisible]=useState(false);
useEffect(()=>{
documentClick();
},[])
function onFocus(e){
setDropDownVisible(true);
}
function onChange(e){
props.onChange(e.target.value)
}
function selectuser(e,item){
if(e.target.checked){
let _record = []
_record.push(item)
props.onSelect(_record,'user')
}
}
function selectDep(e,item){
if(e.target.checked){
console.log('item',item);
props.onSelect(item,'department');
}
}
function documentClick(){
document.onclick = function (e) {
let _con =$('#search-user');
if(!_con.is(e.target) && _con.has(e.target).length === 0){
setDropDownVisible(false);
}
};
}
return (
<div className="search-user" style={{width:'300px'}} id="search-user">
<Search
placeholder='搜索成员'
enterButton={<span className="icon iconfont">&#xe832;</span>}
onFocus={(e)=>{onFocus(e)}}
onChange={(e)=>{onChange(e)}}
className="search-input-item"
// onBlur={()=>{onBlur()}}
/>
{dropDownVisible &&
<div className="drop-down" style={{width:'100%'}}>
<div className="drop-down__list">
{props.data.departmentUserVOList &&
<div>
<div className="drop-down__item__title">
员工
</div>
<div className="drop-down__item__con">
<div>
{props.data.departmentUserVOList.map((item,index)=>{
return <div>
<Checkbox onChange={(e)=>{selectuser(e,item)}} >
<div className="drop-down__item__con__item">
<div className="drop-down__item__con__item__left">
<WWOpenDataCom type="userName" openid={item.userName}/>
</div>
<div className="drop-down__item__con__item__right">
{item.depNamesList.map((_item,index)=>{
return <span> <WWOpenDataCom type="departmentName" openid={_item}/>{index<(item.depNamesList.length -1)?';':''}</span>
})
}
</div>
</div>
</Checkbox>
</div>
})
}
</div>
</div>
</div>
}
{props.data.departmentVOList &&
<div>
<div className="drop-down__item__title">
部门
</div>
<div className="drop-down__item__con">
<div>
{props.data.departmentVOList.map((item,index)=>{
return <div><Checkbox onChange={(e)=>{selectDep(e,item)}}>
<div className="drop-down__item__con__item">
<div className="drop-down__item__con__item__left">
<WWOpenDataCom type="departmentName" openid={item.name}/>
</div>
</div>
</Checkbox>
</div>
})
}
</div>
</div>
</div>
}
{(!props.data.departmentUserVOList && !props.data.departmentVOList)&&
<div>暂无数据</div>
}
</div>
</div>
}
</div>
);
}
export default withRouter(SearchUser);
.search-user{
position: relative;
.drop-down{
padding:18px;
position: absolute;
background: #FFF;
z-index:100001;
background: #FFFFFF;
box-shadow: 0px 2px 15px 6px rgba(0, 0, 0, 0.05);
border-radius:2px;
.ant-checkbox-wrapper{
width:100%;
.drop-down__item__con__item{
display:flex;
width:240px;
justify-content:space-between;
color:#333;
font-size:14px;
.drop-down__item__con__item__right{
width:84px;
text-align:right;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
color:#999;
}
}
}
}
}
\ No newline at end of file
import React, { useEffect, useState } from "react";
import { withRouter } from "react-router-dom";
import { XMTable,PageControl} from '@/components';
import college from '@/common/lottie/college.json';
import "./UserTable.less";
function UserTable() {
const [courseList,setCourseList] = useState([]);
const [total, setTotal] = useState(0);
const [query, setQuery] = useState({
current: 0,
size: 10,
});
const columns = [
{
title: '学员',
dataIndex: 'user',
width:220,
render: (val, record) => {
return <span>{val}</span>
}
},
{
title: '真实姓名',
dataIndex: 'nickname',
width:'15%',
render: (val,record) => {
return <span>{val}</span>
}
},
{
title: '账号',
dataIndex: 'account',
width:'15%',
render: (val,record) => {
return <span>{val}</span>
}
},
{
title: '岗位',
dataIndex: 'post',
render: (val, record) => {
return <span>{val}</span>
}
},
{
title: '手机号',
dataIndex: 'phone',
render: (val, record) => {
return <span>{val}</span>;
}
},
{
title: '注册时间',
dataIndex: 'registerTime',
render: (val, record) => {
return <span>{val}</span>;
}
},
{
title: "操作",
key: "operate",
dataIndex: "operate",
render: (val, record) => {
return (
<div className="operate">
<div
className="operate__item"
>
删除
</div>
</div>
)
}
},
];
return (
<div className="user-table">
<XMTable
renderEmpty={{
image: college,
description: '暂无数据',
}}
bordered
size='middle'
pagination={false}
columns={columns}
scroll={{ x: 1300 }}
dataSource={courseList}
/>
<div className='box-footer'>
<PageControl
current={query.current}
pageSize={query.size}
total={total}
toPage={(page) => {
const queryStates = _.clone(query);
queryStates.current = page;
setQuery(queryStates);
}}
/>
</div>
</div>
);
}
export default withRouter(UserTable);
\ No newline at end of file
.user-table{
}
\ No newline at end of file
/*
* @Author: wufan
* @Date: 2020-11-27 16:21:49
* @LastEditors: Please set LastEditors
* @LastEditTime: 2021-08-03 17:23:40
* @Description: Description
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import React, { useState, useEffect } from "react";
import { Modal,Form,Input,Button,message} from "antd";
import User from '@/common/js/user';
import StoreService from "@/domains/store-domain/storeService";
import { DepType } from '@/domains/store-domain/constants';
import './AddOrEditPostGroupModal.less'
function AddOrEditPostGroupModal(props) {
const [nameErrorMsg,setNameErrorMsg] = useState('');
const [validateStatus,setValidateStatus] = useState('success');
const [postGroupName,setPostGroupName] = useState('');
useEffect(() => {
},[]);
function changePostGroupName(e){
let isError = false;
setValidateStatus('success');
setNameErrorMsg('');
props.postGroupTreeData.map((item,index)=>{
if(item.name === e.target.value){
setValidateStatus('error');
setNameErrorMsg(`该${props.label}已存在`);
isError = true;
}
return item;
})
if(!isError){
setPostGroupName(e.target.value);
}
}
function handleConfirm(){
if(props.modalOperateType === 'add'){
addGroup();
}else{
editGroup();
}
}
function addGroup(){
if(!postGroupName){
return;
}
const { postGroupModalLevel,currentTab,currentGroupData,label} = props
let parmas={
depLevel:postGroupModalLevel,
depType:DepType[currentTab],
departmentName:postGroupName,
enterpriseId:User.getEnterpriseId(),
source:0,
storeId:User.getStoreId(),
userId:User.getUserId()
}
if(postGroupModalLevel===0){
parmas.parentId = 0;
}else{
parmas.parentId = currentGroupData.id
}
StoreService.addDepartment(parmas).then((res) => {
message.success(`${label}创建成功`)
props.onConfirm();
});
}
function editGroup(){
if(!postGroupName){
return;
}
const {postGroupModalLevel,currentTab,currentGroupData,label} = props
let parmas={
departmentLevel:postGroupModalLevel,
departmentId:currentGroupData.id,
depType:DepType[currentTab],
departmentName:postGroupName,
enterpriseId:User.getEnterpriseId(),
source:0,
storeId:User.getStoreId(),
userId:User.getUserId()
}
if(postGroupModalLevel===0){
parmas.parentId = 0;
}else{
parmas.parentId = currentGroupData.parentId
}
StoreService.editDepartment(parmas).then((res) => {
message.success(`${label}修改成功`)
props.onConfirm();
});
}
return (
<Modal
visible={true}
title={props.title}
className="add-edit-post-group-modal"
onCancel={props.onClose}
width={448}
footer={[
<Button
id='cancel_allot_btn'
key="back" onClick={props.onClose}>取消</Button>,
<Button
id='confirm_allot_btn'
key="submit"
type="primary"
onClick={() => {
handleConfirm()
}}>
保存
</Button>
]}
maskClosable={false}
closeIcon={<span className="icon iconfont modal-close-icon">&#xe6ef;</span>}
>
<Form
labelCol={ {span:5 }}
>
<Form.Item
// label={`${props.label}名称`}
name={`${props.label}名称`}
rules={[{ required: true}]}
validateStatus={validateStatus}
help={nameErrorMsg}
>
<Input type="text" placeholder={`请输入${props.label}名称(8个字以内)`} maxLength={8} style={{ width: 348 }}
defaultValue={props.modalOperateType==='edit'?props.currentGroupData.name:''}
onChange={(e) => {
changePostGroupName(e);
}} />
</Form.Item>
</Form>
</Modal>
);
}
export default AddOrEditPostGroupModal;
/*
* @Author: wanghaofeng
* @date: 2020/11/14 17:42
* @Description:权限管理-选择成员弹窗
*/
import React from 'react';
import { Modal, Input, message, Tooltip,AutoComplete} from 'antd';
import { XMTable } from '@/components';
import college from '@/common/lottie/college.json';
import Service from '@/common/js/service';
import User from '@/common/js/user'
import SetEmployeeModal from "./SetEmployeeModal";
import search from '../../lottie/search/data.json';
import MemberTree from '../components/MemberTree'
import { DepType } from "@/domains/store-domain/constants";
import StoreService from "@/domains/store-domain/storeService";
import SearchUser from "../components/SearchUser"
import WWOpenDataCom from '@/components/WWOpenDataCom';
import './ChooseMembersModal.less';
import _ from 'underscore';
const { Search } = Input;
class NewChooseMembersModal extends React.Component {
constructor(props) {
super(props);
this.state = {
selectUserList:[],
selectObject: {},
openSetModal: false,
visible:this.props.visible,
completeOptions:[],
queryName:'',
open:false,
searchUserResultList:{}
}
}
componentDidMount() {
}
handleClose = ()=>{
this.props.close()
}
// 信息列表——右边
selectedColumnsRight = () => {
const selectColumns = [
{
title: '学员名',
key: 'nameRight',
dataIndex: 'userName',
width: '70%',
render: (value, record) => {
const { userName = '', avatar } = record;
return (
<div className='avatar'>
<span className="icon iconfont avatar-icon">&#xe84a;</span>
<Tooltip title={userName}>
<span className='userImg'>
<WWOpenDataCom type="userName" openid={userName}/>
{/* {userName} */}
</span>
</Tooltip>
</div>
)
}
},{
title : '操作',
key : 'edit',
dataIndex : 'edit',
width : '30%',
align : 'right',
render: (value, record) => {
return (
<div className='edit' onClick={() => this.clearOneUser(record)}>
<span className="icon iconfont edit-icon">&#xe717;</span>
</div>
)
}
},
]
return selectColumns;
}
treeSelect = (record)=>{
// console.log('record',record)
this.setState({
selectUserList:record
})
}
clearOneUser = (record) =>{
console.log("record",record);
const {selectUserList} = this.state;
const _selectUserList = selectUserList.filter((item,index)=>{
return item.userId !== record.userId
})
console.log('selectUserList',selectUserList);
this.setState({
selectUserList:_selectUserList
})
}
// 清空所有成员
clearAllUser = () => {
this.setState({
selectUserList : [],
})
}
addCustomer = () => {
const { selectUserList } = this.state;
const { addDepType } = this.props;
let enterpriseUserList = []; // 保存新加进去的成员
enterpriseUserList = selectUserList.map((item) => {
const _item = {}
if(addDepType==='DEP_ORG'){
_item.depUserType = 'VISIBLE_USER';
_item.departmentId = item.departmentId;
_item.enterpriseVisibleUserId = item.userId;
}else{
_item.depUserType = 'STORE_USER';
_item.departmentId = this.props.selectDep.id;
_item.enterpriseVisibleUserId = item.enterpriseUserId;
}
return _item
})
const _params = {
storeId: User.getStoreId(),
depType:addDepType,
userAndDepartmentList:enterpriseUserList
}
Service.Hades('public/hades/addBatchUserAndDepartmentStoreCustomer', _params).then((res) => {
this.handleClose();
this.props.onConfirm();
})
}
// 批量添加成员(点击确定)
addUser = (selectUserList) => {
let enterpriseUserList = []; // 保存新加进去的成员
selectUserList.map((item) => {
enterpriseUserList.push({
roleCode: item.roleCode,
enterpriseVisibleUserId: item.userId
})
return enterpriseUserList
})
const _params = {
storeId: User.getStoreId(),
enterpriseUserList,
}
Service.Hades('public/hades/addBatchEnterpriseStoreUser', _params).then((res) => {
if (res.code === '200') {
this.props.onConfirm();
this.setState({
openSetModal: false,
})
}
})
}
renderTitle = (title) => {
return <span>{title}</span>
}
renderItem = (record,type) => ({
value: record.userName || record.name,
label: (
<div
style={{
display: 'flex',
justifyContent: 'space-between',
}}
>
{type === 'user'?
<div>{record.userName}</div>
:
<div>{record.name}</div>
}
{type === 'user' &&
record.postDepNamesList.map((item,index)=>{
return <span>{item}</span>
})
}
{type === 'post' &&
<span>{item.parentName}</span>
}
</div>
),
});
notFoundContentNode = ()=>{
return <span>暂无数据</span>
}
Complete = () =>{
const {open,completeOptions,queryName} = this.state;
return <AutoComplete
dropdownClassName="certain-category-search-dropdown"
dropdownMatchSelectWidth={250}
allowClear
onChange={(value)=>{this.getCompleteOptionData(value)}}
notFoundContent={()=>{this.notFoundContentNode()}}
value={queryName}
open={open}
onFocus={()=>{this.setState({open:true})}}
onBlur={()=>{this.setState({open:false})}}
style={{
width: 250,
}}
options={completeOptions}
onSelect={()=>this.confirmSearchSelect()}
placeholder='搜索员工、部门'
>
</AutoComplete>
}
getCompleteOptionData=(value)=>{
if(!value){
this.setState({
searchUserResultList:{}
})
return
}
this.setState({
queryName:value
})
const params = {
distinct:true,
queryType:this.props.type,
depType:this.props.treeDepType,
queryName:value,
enterpriseId:User.getEnterpriseId(),
source:0,//0代表来自企培
storeId:User.getStoreId(),
userId:User.getUserId(),
whetherCount:false
}
StoreService.getDepartmentUser(params).then((res) => {
const { result = {}} = res;
this.setState({
searchUserResultList:result
})
});
}
confirmSearchSelect=(record,type)=>{
const { selectUserList } = this.state;
if(type==='user'){
this.setState({selectUserList:[...selectUserList,...record]});
}else{
let _list = [];
if(record.departmentUserVOList){
_list = record.departmentUserVOList;
}
console.log('_list',_list);
this.setState({selectUserList:[...selectUserList,..._list]},()=>{
console.log('selectUserList',this.state.selectUserList);
});
}
// }else{
// const params = {
// depType:this.props.treeDepType,
// enterpriseId: User.getEnterpriseId(),
// source: 0,
// storeId: User.getStoreId(),
// userId: User.getUserId(),
// departmentId:record.id
// }
// StoreService.getStoreCustomerAndDepNamePage(params).then((res) => {
// const { records = []} = res.result;
// this.setState({selectUserList:[...selectUserList,...records]});
// });
// }
}
render() {
const {type,treeDepType,selectDep={},addDepType=''} = this.props;
const { id=''} = selectDep;
const {selectUserList,selectObject,visible,openSetModal,searchUserResultList} = this.state;
const title = type === 'USER' ? '添加员工' : '添加学员';
return (
<div>
{/* 添加学员页面 */}
<Modal
className="choose-member-modal"
visible={visible}
onCancel={() => this.handleClose()}
onOk={() => {
if (User.getVersion() && User.getVersion().whetherReachUserNum) {
message.error("添加失败,企业使用人数超出限制")
return
}
if (_.isEmpty(selectUserList)) {
message.warning(type === 'USER' ? '请选择员工' : '请选择学员')
return null;
}
type === 'USER' ? this.setState({openSetModal:true,visible:false}) : this.addCustomer();
}}
okText={type === 'USER' ? '下一步' : '确定'}
title={title}
width={680}
maskClosable={false}
closeIcon={<span className="icon iconfont modal-close-icon">&#xe6ef;</span>}
>
<div className='member-container'>
<div className='container-left'>
<div className='container-left-body'>
{/* <Search
placeholder='搜索成员'
className='search search-input'
enterButton={<span className="icon iconfont">&#xe832;</span>}
/> */}
{/* {this.Complete()} */}
<SearchUser onChange={(value)=>{this.getCompleteOptionData(value)}} data={searchUserResultList} onSelect={(record,type)=>{this.confirmSearchSelect(record,type)}}/>
<div className='container-left-body-table'>
<MemberTree departmentId={id} treeDepType={treeDepType} nowTreeDepType={addDepType} onSelect={(record)=>{this.treeSelect(record)}} selectUserList={selectUserList} type={type}/>
</div>
</div>
</div>
{/* 已选择的成员列表 */}
<div className='container-right'>
<span className='span-left'>已选择{type === 'USER' ? '员工' : '学员'}</span>
<div className='span-right' onClick={() => this.clearAllUser()}>
<span className={ (selectUserList.length > 0) ? 'span-right-l' : null }>清空</span>
</div>
<div className='container-right-body'>
<XMTable
renderEmpty={{
image: college,
description: '暂无数据'
}}
rowKey={(record) => record.id}
dataSource={selectUserList}
columns={this.selectedColumnsRight()}
showHeader={false}
scroll={{ y: 375 }}
pagination={false}
size={'small'}
/>
</div>
</div>
</div>
</Modal>
{openSetModal &&
<SetEmployeeModal
list={selectUserList}
selectObject={selectObject}
onChange={(key, value) => {
selectObject[key] = value;
this.setState({ selectObject });
}}
onClose={() => {
this.setState({ openSetModal: true},()=>{this.handleClose()})
this.setState({ openSetModal: false, visible: true })
}}
onCancel={() => {
this.handleClose();
this.setState({ openSetModal: false });
}}
onOk={(list) => {
this.addUser(list);
}}
/>
}
</div>
)
}
}
export default NewChooseMembersModal;
\ No newline at end of file
import React from 'react';
import { Modal, Button, Radio, Tooltip } from 'antd';
import WWOpenDataCom from '@/components/WWOpenDataCom';
import './SetEmployeeModal.less'
const RadioGroup = Radio.Group;
......@@ -13,13 +14,13 @@ export default class SetEmployeeModal extends React.Component {
constructor(props) {
super(props);
const list = props.list.map(item => {
item.roleCode = (props.selectObject || {})[item.enterpriseVisibleUserId] || (item.enterpriseRole === 'ADMIN' ? 'Cloud_Manager' : 'Cloud_Lecturer');
item.roleCode = (props.selectObject || {})[item.userId] || (item.enterpriseRole === 'ADMIN' ? 'Cloud_Manager' : 'Cloud_Lecturer');
return item;
})
const selectedData = list[0] || {};
this.state = {
list,
selected: selectedData.enterpriseVisibleUserId,
selected: selectedData.userId,
roleCode: selectedData.roleCode,
}
}
......@@ -27,7 +28,7 @@ export default class SetEmployeeModal extends React.Component {
handleChangeValues(value) {
const { list, selected } = this.state;
list.map((item) => {
if (item.enterpriseVisibleUserId === selected) {
if (item.userId === selected) {
item.roleCode = value;
}
})
......@@ -62,15 +63,18 @@ export default class SetEmployeeModal extends React.Component {
<div className="employee-box">
{list.map((item) => (
<div
className={`item ${selected === item.enterpriseVisibleUserId ? ' selected' : ''}`}
key={item.enterpriseVisibleUserId}
className={`item ${selected === item.userId ? ' selected' : ''}`}
key={item.userId}
onClick={() => {
this.setState({ selected: item.enterpriseVisibleUserId, roleCode: item.roleCode })
this.setState({ selected: item.userId, roleCode: item.roleCode })
}}
>
<span className="icon iconfont avatar-icon">&#xe84a;</span>
<Tooltip title={item.name}>
<span className='name'>{item.name}</span>
<span className='name'>
{/* {item.userName} */}
<WWOpenDataCom type="userName" openid={item.userName}/>
</span>
</Tooltip>
<span className="tag">{tagMap[item.roleCode]}</span>
</div>
......
......@@ -21,6 +21,7 @@ import { randomString } from '@/domains/basic-domain/utils';
import Upload from '@/core/upload';
import PreviewCourseModal from './modal/PreviewCourseModal';
import CourseService from '@/domains/course-domain/CourseService';
import routeHook from '@/core/routeHook'
import moment from 'moment';
import User from '@/common/js/user';
import _ from 'underscore';
......@@ -110,6 +111,7 @@ class AddLive extends React.Component {
}
componentDidMount() {
routeHook.addSaveCase();
const { type } = this.state;
if (type === 'edit') {
this.getCourseDetail();
......@@ -515,19 +517,12 @@ class AddLive extends React.Component {
// 比较state的addLiveBasicInfo, addLiveClassInfo, addLiveIntroInfo和默认数据是否相等
const { addLiveBasicInfo, addLiveClassInfo, addLiveIntroInfo } = this.state;
if (!_.isEqual(addLiveBasicInfo, defaultBasicInfo) || !_.isEqual(addLiveClassInfo, defaultClassInfo) || !_.isEqual(addLiveIntroInfo, defaultIntroInfo)) {
Modal.confirm({
title: '确定要返回吗?',
content: '返回后,本次编辑的内容将不被保存',
okText: '确认返回',
cancelText: '留在本页',
icon: <span className='icon iconfont default-confirm-icon'>&#xe6f4;</span>,
onOk: () => {
window.RCHistory.push({
pathname: `/live-course`,
});
},
console.log('ghjklkjh')
window.RCHistory.push({
pathname: `/live-course`,
});
} else {
routeHook.cancel()
window.RCHistory.push({
pathname: `/live-course`,
});
......
......@@ -2,7 +2,7 @@ import User from '@/common/js/user';
import college from '@/common/lottie/college';
import { PageControl, XMTable } from '@/components';
import CourseService from '@/domains/course-domain/CourseService';
import { Button, message, Popover, Spin } from 'antd';
import { Button, message, Popover, Spin, Tooltip } from 'antd';
import React from 'react';
import { withRouter } from 'react-router-dom';
import dealTimeDuration from '../utils/dealTimeDuration';
......@@ -11,7 +11,7 @@ class DataList extends React.Component {
constructor(props) {
super(props);
const courseId = getParameterByName('id'); // 课程ID
const type = getParameterByName('type'); // 来源: 大班直播 large 互动班课 interactive
const type = getParameterByName('type'); // 来源: 大班直播 large 互动班课 interactive 企微直播 qiwei
this.state = {
type,
teacherData: [], // 老师上课数据
......@@ -39,30 +39,58 @@ class DataList extends React.Component {
current,
size,
};
CourseService.fetchUserData(params).then((res) => {
if (res.result) {
const { records = [], current, size, total } = res.result;
if (this.state.type === "qiwei") {
CourseService.fetchWorkWXUserData(params).then((res) => {
if (res.result) {
const { records = [], current, size, total } = res.result;
this.setState({
studentData: records,
current,
size,
total,
loading: false,
});
}
});
} else {
CourseService.fetchUserData(params).then((res) => {
if (res.result) {
const { records = [], current, size, total } = res.result;
this.setState({
studentData: records,
current,
size,
total,
loading: false,
});
}
});
}
this.setState({
studentData: records,
current,
size,
total,
loading: false,
});
}
});
};
// 获取老师上课数据
fetchLecturerData = () => {
const { liveCourseId } = this.state;
CourseService.fetchLecturerData({ liveCourseId }).then((res) => {
if (res.result) {
this.setState({
teacherData: res.result,
});
}
});
if (this.state.type === "qiwei") {
CourseService.fetchWorkWXLecturerData({ liveCourseId }).then((res) => {
if (res.result) {
this.setState({
teacherData: res.result,
});
}
});
} else {
CourseService.fetchLecturerData({ liveCourseId }).then((res) => {
if (res.result) {
this.setState({
teacherData: res.result,
});
}
});
}
};
// 进入直播次数列表
......@@ -159,7 +187,81 @@ class DataList extends React.Component {
},
];
return columns;
const columnsWorkWX = [
{
title: '学员姓名',
dataIndex: 'userName',
},
{
title: ()=> {
return (
<div>
学员类型
<Tooltip
title={()=> {
return <div>
<div>学员-已加入当前学院的企业员工</div>
<div>待加入-未加入当前学院的企业员工</div>
<div>游客-非企业员工</div>
</div>
}}>
<i className='icon iconfont' style={{fontSize:"14px",fontWeight:"400"}}> &#xe61d;</i>
</Tooltip>
</div>
)
},
dataIndex: 'phone',
render: (text, record) => {
const { phone = '', bindingWeChat } = record;
return <div>{phone}</div>;
},
},
{
title: '账号类型',
dataIndex: 'entryNum',
render: (text, record) => {
if (text > 0) {
if (record.visitorInfoVOList && record.visitorInfoVOList.length > 0) {
const table = (
<XMTable
renderEmpty={{
image: college,
description: '暂无数据',
}}
columns={this.getVisiterColumns()}
dataSource={record.visitorInfoVOList}
scroll={{ y: 75 }}
size={'small'}
style={{ width: 450 }}
pagination={false}
/>
);
return (
<Popover content={table} trigger='click'>
<span className='handel-btn'>{text}</span>
</Popover>
);
} else {
return <div className='live-table--empty'>暂无观看数据</div>;
}
} else {
return <span>{text}</span>;
}
},
},
{
title: '累计在线时长',
dataIndex: 'totalDuration',
sorter: (a, b) => a.totalDuration - b.totalDuration,
sortDirections: ['descend', 'ascend'],
render: (text, record) => {
//如无离开时间,就置空
return <span>{text ? dealTimeDuration(text) : '00:00:00'}</span>;
},
},
];
return this.state.type === "qiwei" ? columnsWorkWX : columns;
}
// 学员导出5.0
handleExportV5 = () => {
......@@ -239,7 +341,7 @@ class DataList extends React.Component {
};
render() {
const { teacherData, studentData, current, size, total, loading, link } = this.state;
const { teacherData, studentData, current, size, total, loading, link, type } = this.state;
return (
<Spin spinning={loading}>
<a href={link} target='_blank' download id='loadExcel' style={{ position: 'absolute', left: '-10000px' }}>
......@@ -257,18 +359,22 @@ class DataList extends React.Component {
</div>
</div>
<div className='times item-block'>
<div className={`times-num ${Number(teacherData.entryNum) > 0 ? 'can-click' : ''}`}>
{Number(teacherData.entryNum) > 0 ? (
<Popover content={this.showTable()} trigger='click'>
<span className='times-num'>{teacherData.entryNum || 0}</span>
</Popover>
) : (
<span className='times-num'>{0}</span>
)}
{
type !== "qiwei" &&
<div className='times item-block'>
<div className={`times-num ${Number(teacherData.entryNum) > 0 ? 'can-click' : ''}`}>
{Number(teacherData.entryNum) > 0 ? (
<Popover content={this.showTable()} trigger='click'>
<span className='times-num'>{teacherData.entryNum || 0}</span>
</Popover>
) : (
<span className='times-num'>{0}</span>
)}
</div>
<div className='text'>进入直播间次数</div>
</div>
<div className='text'>进入直播间次数</div>
</div>
}
<div className='online-duration item-block'>
<div className='duration'>{teacherData.totalDuration ? dealTimeDuration(teacherData.totalDuration) : '00:00:00'}</div>
......
......@@ -21,6 +21,7 @@ class DataList extends React.Component {
}
render() {
const type = window.getParameterByName("type")
return (
<div className="page data-list">
<Breadcrumbs
......@@ -35,9 +36,13 @@ class DataList extends React.Component {
<CourseData></CourseData>
</Tabs.TabPane>
<Tabs.TabPane tab="回放记录" key="playbackData">
<PlaybackData></PlaybackData>
</Tabs.TabPane>
{
type !== "qiwei" &&
<Tabs.TabPane tab="回放记录" key="playbackData">
<PlaybackData></PlaybackData>
</Tabs.TabPane>
}
</Tabs>
</div>
......
......@@ -119,7 +119,13 @@ class AddLiveBasic extends React.Component {
<span className='label'>封面图:</span>
<div className='course-cover__wrap'>
<div className='opt-btns'>
<div className='img-content'>
{isDefaultCover && <span className='tag'>默认图</span>}
<img src={coverUrl} />
</div>
</div>
<div className='opt-btns'>
<Button
onClick={() => {
this.setState({
......@@ -133,11 +139,6 @@ class AddLiveBasic extends React.Component {
</span>
<div className='tips'>建议尺寸1280*720px或16:9。封面图最大5M,支持jpg、jpeg和png。</div>
</div>
<div className='img-content'>
{isDefaultCover && <span className='tag'>默认图</span>}
<img src={coverUrl} />
</div>
</div>
</div>
<div className='course-catalog'>
<span className='label'>
......
......@@ -16,7 +16,6 @@
position: relative;
.img-content {
margin-top: 8px;
margin-right: 20px;
width: 299px;
height: 169px;
......@@ -41,27 +40,26 @@
left: 8px;
}
}
}
.opt-btns {
.default-btn {
margin-left: 14px;
color: #2966ff;
cursor: pointer;
.opt-btns {
.default-btn {
margin-left: 14px;
color: #2966ff;
cursor: pointer;
&.disabled {
color: #ccc;
cursor: not-allowed;
}
&.disabled {
color: #ccc;
cursor: not-allowed;
}
}
.ant-upload-list {
display: none;
}
.ant-upload-list {
display: none;
}
.tips {
margin-top: 8px;
color: #999;
}
.tips {
margin-top: 8px;
color: #999;
}
}
}
......
......@@ -75,7 +75,7 @@ class AddLiveClass extends React.Component {
// 获取助教老师列表
getAssistantList = (current = 1, selectList) => {
const { assistantQuery,assistantList} = this.state;
const { assistantStoreUserId } = this.props.data;
const { assistantStoreUserId } = this.props.data ? this.props.data:[];
const idList = selectList ? selectList : assistantStoreUserId;
const _query = {
...assistantQuery,
......
import React, { useEffect, useState } from "react";
import { DatePicker, TimePicker, Select } from 'antd';
import StoreService from "@/domains/store-domain/storeService";
import "./AddLiveClassInfoWorkWX.less";
import GraphicsEditor from "./GraphicsEditor";
import moment from "moment";
import _ from "underscore";
const { Option } = Select;
const defaultTeacherQuery = {
size: 15,
current: 1,
nickName:null
}
export default function AddLiveClassInfoWorkWX(props) {
const [teacherQuery, setTeacherQuery] = useState(defaultTeacherQuery)
const [teacherList, setTeacherList] = useState([])
const [introduce, setIntroduce] = useState({content:props.introduce})
const [duration, setDuration] = useState(props.data.duration)
const [cusTime, setCusTime] = useState(false)
const [beginDate, setBeginDate] = useState(0)
const [beginTime, setBeginTime] = useState(0)
const [endDate, setEndDate] = useState(0)
const [endTime, setEndTime] = useState(0)
const [teacherId, setTeacherId] = useState()
const [remindTime, setRemindTime] = useState(0)
useEffect(()=> {
getTeacherList()
},[])
useEffect(()=> {
setBeginTime(props.data.startTime)
setBeginDate(moment(props.data.startTime).startOf('day').valueOf())
setEndTime(props.data.startTime+Number(props.data.duration))
setEndDate(moment(props.data.startTime+Number(props.data.duration)).startOf('day').valueOf())
setTeacherId(props.data.teacherId)
setRemindTime(props.data.remindTime)
},[props.data])
useEffect(()=> {
let intro = {content:props.introduce};
setIntroduce(intro)
},[props.introduce])
//开始日期
function onBeginDateChange(date, dateString) {
if (date) {
setBeginDate(date.startOf('day').valueOf())
} else {
setBeginDate(0)
}
}
function onBeginDateOK(date) {
console.log(date)
}
//开始时间
function onBeginTimeChange(date, dateString) {
console.log("onBeginTimeChange",date)
// props.onChange("beginTime",date.valueOf())
}
function onBeginTimeOK(time) {
let begin = beginDate+(time.hour()*60+time.minute())*60*1000
setBeginTime(begin)
props.onChange("beginTime",begin)
if (!cusTime) {
props.onChange("endTime",begin+duration)
}
}
//结束日期
function onEndDateChange(date, dateString) {
if (date) {
setEndDate(date.startOf('day').valueOf())
} else {
setEndDate(0)
}
}
function onEndDateOK(date) {
}
//结束时间
function onEndTimeChange(date, dateString) {
// props.onChange("endTime",date.valueOf())
}
function onEndTimeOK(time) {
let end = endDate+(time.hour()*60+time.minute())*60*1000
setEndTime(end)
props.onChange("endTime",end)
}
function onDurationChange(value, option) {
if (value === 0) {
setCusTime(true)
return
}
let d = value*60*1000;
setDuration(d)
props.onChange("endTime",beginDate+d)
}
function onTeacherChange(value, option) {
setTeacherId(value)
props.onChange("teacherId",value)
}
function onRemindChange(value, option) {
setRemindTime(value)
props.onChange("remindTime",value)
}
function onChangeIntro(val) {
let intro = {...introduce}
intro.content = val
setIntroduce(intro)
props.onChange("intro",val)
}
function getTeacherList(current = 1) {
const _query = {
...teacherQuery,
current,
size:15
};
StoreService.getStoreUserBasicPage( _query).then((res) => {
const { result = {} } = res;
const { records = [], total = 0, hasNext } = result;
const list = current > 1 ? teacherList.concat(records) : records;
setTeacherList(list)
setTeacherQuery({..._query,hasNext})
});
}
// console.log(moment(beginDate).format("YYYY-MM-DD HH:mm"))
// console.log(moment(endDate).format("YYYY-MM-DD HH:mm"))
return (
<div className="AddLiveClassInfoWorkWX">
<div className="begin-time item">
<span className="label"><span className="require">*</span>开始时间:</span>
<DatePicker
value={beginTime===0?undefined:moment(beginTime)}
onChange={onBeginDateChange}
onOk={onBeginDateOK}
/>
<TimePicker
value={beginTime===0?undefined:moment(beginTime)}
onChange={onBeginTimeChange}
onOk={onBeginTimeOK}
format="HH:mm" />
</div>
<div className="duration-time item">
{
cusTime || props.type === "edit" ? (
<>
<span className="label"><span className="require">*</span>结束时间:</span>
<DatePicker
value={endTime === 0?undefined:moment(endTime)}
onChange={onEndDateChange}
onOk={onEndDateOK}
/>
<TimePicker
value={endTime === 0?undefined:moment(endTime)}
onChange={onEndTimeChange}
onOk={onEndTimeOK}
format="HH:mm" />
</>
) : (
<>
<span className="label"><span className="require">*</span>时长:</span>
<Select onChange={onDurationChange} defaultValue={60} style={{width:"140px"}}>
<Option value={30}>0.5小时</Option>
<Option value={60}>1.0小时</Option>
<Option value={120}>2.0小时</Option>
<Option value={180}>3.0小时</Option>
<Option value={0}>自定义结束时间</Option>
</Select>
</>
)
}
</div>
<div className="teacher item">
<span className="label"><span className="require">*</span>讲师:</span>
<Select
value={teacherId}
onChange={onTeacherChange}
style={{width:"240px"}}
placeholder="请选择讲师"
>
{
_.map(teacherList, (item, index) => {
return (
<Select.Option value={item.id} key={item.id}>{item.nickName}</Select.Option>
);
})
}
</Select>
</div>
<div className="remind-time item">
<span className="label"><span className="require">*</span>提醒时间:</span>
<Select value={remindTime} onChange={onRemindChange} defaultValue={0} style={{width:"100px"}}>
<Option value={0}></Option>
<Option value={300}>5分钟前</Option>
<Option value={3600}>1小时前</Option>
<Option value={86400}>1天前</Option>
</Select>
</div>
<div className="introduce item">
<span className="label">直播简介:</span>
<div className="intro-edit">
<GraphicsEditor
id='intro'
isIntro={true}
maxLimit={1000}
detail={introduce}
onChange={(val) => {
onChangeIntro(val);
}}
></GraphicsEditor>
</div>
</div>
</div>
)
}
\ No newline at end of file
.AddLiveClassInfoWorkWX {
margin-left: 16px;
.item {
margin: 24px 0;
.label {
display: inline-block;
text-align: right;
width: 100px;
.require {
color: red;
}
}
}
.introduce {
display: flex;
}
}
\ No newline at end of file
......@@ -136,7 +136,7 @@ class AddLiveIntro extends React.Component {
<span className='label'>观看设置:</span>
<div className='content'>
<Switch checked={whetherVisitorsJoin === 'NO' ? true : false} onChange={this.whetherVisitorsJoinChange} />
<div class='instro-text'>{whetherVisitorsJoin === 'NO' ? '已开启,学员需绑定手机号才可观看' : '已关闭,学员无需绑定手机号即可观看'}</div>
<div className='instro-text'>{whetherVisitorsJoin === 'NO' ? '已开启,学员需绑定手机号才可观看' : '已关闭,学员无需绑定手机号即可观看'}</div>
</div>
</div>
<div className='warmup'>
......
/*
* @Author: 吴文洁
* @Date: 2020-07-17 15:49:11
* @Last Modified by: chenshu
* @Last Modified time: 2021-04-06 16:43:23
* @Description: 大班互动-添加/编辑直播课
*/
import React, { ReactElement, useEffect, useState } from 'react';
import { withRouter } from 'react-router-dom';
import { Button, message, Modal } from 'antd';
import ShowTips from '@/components/ShowTips';
import Breadcrumbs from '@/components/Breadcrumbs';
import Bus from '@/core/tbus';
import AddLiveBasic from './AddLiveBasic';
import AddLiveClass from './AddLiveClass';
import AddLiveIntro from './AddLiveIntro';
import AddLiveClassInfoWorkWX from './AddLiveClassInfoWorkWX';
import { randomString } from '@/domains/basic-domain/utils';
import Upload from '@/core/upload';
import PreviewCourseModal from '../modal/PreviewCourseModal';
import CourseService from '@/domains/course-domain/CourseService';
import routeHook from '@/core/routeHook'
import moment from 'moment';
import User from '@/common/js/user';
import _ from 'underscore';
import $ from 'jquery';
import './CreateWorkWXCourse.less';
const defaultCover = 'https://image.xiaomaiketang.com/xm/Yip2YtFDwH.png';
const defaultBasicInfo = {
courseName: '', // 课程名称
coverUrl: defaultCover,
coverId: '',
categoryId: null,
}
const defaultClassInfo = {
teacherId: '', //讲师的Id
courseName: '', //课程名称
duration: 3600000, //直播时长默认1小时
remindTime: 0, //提醒时间
startTime: new Date().getTime() + 300000,
};
function CreateWorkWXCourse() {
const [id, setId] = useState(getParameterByName('id'))
const [type,setType] = useState(getParameterByName('type'))
const [loading, setLoading] = useState(false)
const [isEdit, setIsEdit] = useState(true)
const [courseState, setCourseState] = useState('UN_START')
const [editorTextLength, setEditorTextLength] = useState(0)
const [loadintroduce, setLoadintroduce] = useState(false)
const [basicInfo, setBasicInfo] = useState(defaultBasicInfo)
const [classInfo, setClassInfo] = useState(defaultClassInfo)
const [endTime, setEndTime] = useState(0)
const [introduce, setIntroduce] = useState('')
const [previewLiveCourseModal, setPreviewLiveCourseModal] = useState()
useEffect(()=> {
routeHook.addSaveCase();
if (type === 'edit') {
getCourseDetail();
}
Bus.bind('editorLimit', (editorTextLength) => {
setEditorTextLength(editorTextLength)
});
},[])
function getCourseDetail() {
setLoading(true)
CourseService.getWorkWXLiveCourseDetail({
liveCourseId: id,
}).then((res) => {
const {
teacherId,
teacherName,
courseName,
startTime,
duration,
courseMediaVOList,
categoryId,
categoryName,
remindTime
} = res.result;
let coverId;
let coverUrl;
let hasIntro = false;
courseMediaVOList && courseMediaVOList.map((item) => {
switch (item.contentType) {
case 'COVER':
coverId = item.mediaContent;
coverUrl = item.mediaUrl;
break;
case 'INTRO':
hasIntro = true;
getIntroduce('introduce', item.mediaUrl);
break;
default:
break;
}
return item;
});
const _basicInfo = {
courseName,
coverUrl: coverUrl || defaultCover,
coverId,
categoryId,
categoryName,
};
const _classInfo = {
teacherId,
teacherName,
duration,
startTime,
remindTime,
};
// 晚于开课前30分钟
if (new Date().getTime() > startTime - 1800000) {
setIsEdit(false)
}
setLoadintroduce(!hasIntro)
setLoading(false)
setBasicInfo(_basicInfo)
setClassInfo(_classInfo)
setCourseState(courseState)
});
};
//获取简介
function getIntroduce(key, url) {
$.ajax({
data: {},
type: 'GET',
url,
contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
success: (res) => {
setLoadintroduce(true)
setIntroduce(res)
},
error: () => {
message.warning('获取简介失败');
},
});
};
// 修改基本信息
function handleChangeBasicInfo(field, value) {
let binfo = {...basicInfo}
binfo[field] = value
setBasicInfo(binfo)
};
//课程信息变更回调
function onClassInfoChange(field, value) {
let classinfo = {...classInfo}
switch (field) {
case 'intro':
setIntroduce(value)
break;
case 'beginTime':
console.log(value)
classinfo.startTime = value
setClassInfo(classinfo)
break;
case 'endTime':
console.log(value)
setEndTime(value)
break;
case 'duration':
classinfo.duration = value
setClassInfo(classinfo)
break;
case 'teacherId':
classinfo.teacherId = value
setClassInfo(classinfo)
break;
case 'remindTime':
classinfo.remindTime = value
setClassInfo(classinfo)
break;
default:
console.log("NULL")
}
}
// 修改简介
function handleChangeIntroInfo(field, value) {
};
// 完成创建/编辑
function handleSubmit() {
//过期判断
if (User.getExpirationTime() && moment().valueOf() > Number(User.getExpirationTime())) {
Modal.warning({
title: '服务已到期',
content: '当前企业购买的小麦企学院服务已到期,如需继续使用学院功能,请尽快续费购买',
okText: '我知道了',
});
return;
}
if (type === 'edit' && isEdit && new Date().getTime() > classInfo.startTime - 1800000) {
Modal.info({
title: '提示',
icon: <span className='icon iconfont default-confirm-icon'>&#xe6f4;</span>,
content: '晚于开课前30分钟,部分信息不可修改',
okText: '我知道了',
onOk: () => {
getCourseDetail();
},
});
return;
}
// this.handleValidate(addLiveBasicInfo, addLiveClassInfo, addLiveIntroInfo, isEdit, editorTextLength).then((res) => {
// if (!res) return;
//上传简介
Upload.uploadTextToOSS(
introduce,
`${randomString()}.txt`,
(introduceId) => {
submitRemote({ introduceId, id });
},
() => message.warning('上传课程简介失败')
);
// });
};
function submitRemote({ introduceId, id }) {
if (type === 'add') {
} else {
}
if (type === 'add') {
if (endTime !== 0) {
classInfo.duration = String(endTime - classInfo.startTime)
}
const params = {
...classInfo,
operatorId:User.getUserId(),
introduceId,
storeId: User.getStoreId(),
...basicInfo
};
CourseService.createWorkWXLiveCourse(params).then((res) => {
if (res.success) {
message.success('新建成功');
window.RCHistory.push({
pathname: `/live-course`,
});
}
});
} else {
if (endTime !== 0) {
classInfo.duration = String(endTime - classInfo.startTime)
}
const params = {
...classInfo,
operatorId:User.getUserId(),
introduceId,
storeId: User.getStoreId(),
...basicInfo,
liveCourseId: id
};
CourseService.updateWorkWXLiveCourse(params).then((res) => {
if (res.success) {
message.success('更新成功');
window.RCHistory.push({
pathname: `/live-course`,
});
}
});
}
};
/*
handleValidate = (addLiveBasicInfo, addLiveClassInfo, addLiveIntroInfo, isEdit, editorTextLength) => {
return new Promise((resolve) => {
const { type } = this.state;
const { courseName, categoryId } = addLiveBasicInfo;
const { liveDate, timeHorizonStart, timeHorizonEnd, teacherId, calendarTime } = addLiveClassInfo;
const { liveCourseMediaRequests } = addLiveIntroInfo;
const currentTime = +new Date();
if (!courseName) {
message.warning('请输入课程名称');
resolve(false);
return;
}
if (!categoryId) {
message.warning('请选择课程分类');
resolve(false);
return;
}
if (type === 'add') {
const { startTime, endTime } = addLiveClassInfo;
if (calendarTime.length === 0) {
message.warning('请选择上课日期');
resolve(false);
return;
} else if (startTime === endTime || startTime > endTime) {
message.warning('结束时间必须晚于开始时间');
resolve(false);
return;
}
// 若有今日排课 校验当前时间
const currentDay = moment(currentTime).format('YYYY-MM-DD');
const itemToday = _.find(calendarTime, (item) => {
const itemDay = moment(item).format('YYYY-MM-DD');
return itemDay === currentDay;
});
if (itemToday) {
const itemDay = moment(itemToday).format('YYYY-MM-DD');
const itemHour = moment(startTime).format('HH:mm');
if (itemDay === currentDay) {
if (moment(itemDay + ' ' + itemHour).format('x') < currentTime) {
message.warning('开始时间不能早于现在');
resolve(false);
return;
}
}
}
} else {
const _liveDate = moment(liveDate).format('YYYY-MM-DD');
const _timeHorizonStart = moment(timeHorizonStart).format('HH:mm');
const _timeHorizonEnd = moment(timeHorizonEnd).format('HH:mm');
const startTime = moment(_liveDate + ' ' + _timeHorizonStart).format('x');
const endTime = moment(_liveDate + ' ' + _timeHorizonEnd).format('x');
if (!startTime || !endTime) {
message.warning('日期不能为空');
resolve(false);
return;
} else if (!timeHorizonStart) {
message.warning('开始时间不能为空');
resolve(false);
return;
} else if (!timeHorizonEnd) {
message.warning('结束时间不能为空');
resolve(false);
return;
} else if (isEdit && startTime < currentTime) {
message.warning('开始时间不能早于当前时间');
resolve(false);
return;
} else if (isEdit && endTime < currentTime) {
message.warning('结束时间不能早于当前时间');
resolve(false);
return;
} else if (isEdit && endTime <= startTime) {
message.warning('结束时间不能早于开始时间');
resolve(false);
return;
}
}
if (!teacherId) {
message.warning('请选择讲师');
resolve(false);
return;
}
if (editorTextLength > 1000) {
message.warning('课程简介超过字数限定');
resolve(false);
return;
}
resolve(true);
});
};
*/
// 显示预览课程弹窗
function handleShowPreviewModal() {
// const { addLiveBasicInfo, addLiveClassInfo, addLiveIntroInfo, type, courseState } = this.state;
const previewLiveCourseModal = (
<PreviewCourseModal
courseBasicInfo={basicInfo}
courseClassInfo={{...classInfo,endTime}}
courseIntroInfo={{introduce:introduce,categoryName:basicInfo.courseName}}
type={type}
courseState={courseState}
close={() => {
setPreviewLiveCourseModal(null)
}}
/>
);
setPreviewLiveCourseModal(previewLiveCourseModal)
};
// 取消编辑并返回上一级路由
function handleGoBack() {
// 比较state的addLiveBasicInfo, addLiveClassInfo, addLiveIntroInfo和默认数据是否相等
// const { addLiveBasicInfo, addLiveClassInfo, addLiveIntroInfo } = this.state;
if (!_.isEqual(basicInfo, defaultBasicInfo) || !_.isEqual(classInfo, defaultClassInfo)) {
console.log('ghjklkjh')
window.RCHistory.push({
pathname: `/live-course`,
});
} else {
routeHook.cancel()
window.RCHistory.push({
pathname: `/live-course`,
});
}
};
// const { id, type, addLiveBasicInfo, addLiveClassInfo, addLiveIntroInfo, isEdit, loadintroduce } = this.state;
return (
<div className='page CreateWorkWXCourse'>
<Breadcrumbs navList={type === 'add' ? '新建直播课' : '编辑直播课'} goBack={handleGoBack} />
<div className='box'>
<div className='show-tips'>
<ShowTips message='请遵守国家相关规定,切勿上传低俗色情、暴力恐怖、谣言诈骗、侵权盗版等相关内容,小麦企学院保有依据国家规定及平台规则进行处理的权利' />
</div>
<div className='add-live-page__form'>
<div className='basic-info__wrap'>
<div className='title'>基本信息</div>
<AddLiveBasic isEdit={isEdit} pageType={type} data={basicInfo} onChange={handleChangeBasicInfo} />
</div>
<div className='class-info__wrap'>
<div className='title'>上课信息</div>
{/* <AddLiveClass isEdit={isEdit} pageType={type} data={{ ...addLiveClassInfo, id }} onChange={handleChangeClassInfo} /> */}
<AddLiveClassInfoWorkWX type={type} data={classInfo} introduce={introduce} onChange={onClassInfoChange}/>
</div>
</div>
</div>
<div className='footer shrink-footer'>
<Button onClick={handleGoBack}>取消</Button>
<Button onClick={handleShowPreviewModal}>预览</Button>
<Button type='primary' onClick={_.debounce(() => handleSubmit(), 3000, true)}>
保存
</Button>
</div>
{previewLiveCourseModal}
</div>
);
}
export default withRouter(CreateWorkWXCourse);
.CreateWorkWXCourse {
.box {
margin-bottom: 52px !important;
}
.add-live-page__form {
margin-top: 16px;
.title {
font-size: 16px;
color: #333;
font-weight: 500;
line-height: 22px;
margin-bottom:8px;
}
.add-live__class-info {
margin-left: 14px;
.student {
margin-bottom: 16px;
}
}
.add-live__basic-info {
.course-name {
margin-left: 14px;
}
}
.add-live__intro-info {
margin-left: 50px;
}
.class-info__wrap{
margin-top: 32px;
}
.intro-info__wrap {
margin-top: 32px;
margin-bottom:74px;
}
.add-live__intro-info {
margin-left: 0;
padding-left: 16px;
.label {
width: 100px;
text-align: right;
}
}
.basic-info__wrap, .class-info__wrap, .intro-info__wrap {
.title {
position: relative;
padding-left: 14px;
&::before {
content: "";
position: absolute;
left: 0px;
top: 50%;
transform: translateY(-50%);
width: 4px;
height: 10px;
background: #2966FF;
}
}
}
}
.footer {
position: fixed;
left: 196px;
bottom: 0;
height: 58px;
width: ~'calc(100% - 218px)';
display: flex;
align-items: center;
justify-content: flex-end;
padding-right: 72px;
background: #fff;
border-top: 1px solid #E8E8E8;
z-index: 9999;
.ant-btn {
margin-left: 10px;
}
}
}
\ No newline at end of file
......@@ -24,6 +24,7 @@ const defaultQuery = {
teacherId: null,
courseState: null,
shelfState: null,
thirdPartType: null
}
const defaultTeacherQuery = {
size: 10,
......@@ -159,7 +160,7 @@ class LiveCourseFilter extends React.Component {
}
render() {
const { courseName, startTime, endTime, courseState, teacherName, teacherId, shelfState } = this.state.query
const { courseName, startTime, endTime, courseState, teacherName, teacherId, shelfState, thirdPartType } = this.state.query
const { expandFilter, teacherList, teacherQuery } = this.state
const { teacherId: _teahcerId } = {}
const isTeacher = !!_teahcerId // 判断是否是老师身份
......@@ -199,7 +200,7 @@ class LiveCourseFilter extends React.Component {
</div>
{User.getUserRole() !== 'CloudLecturer' && (
<div className='search-condition__item'>
<span>讲师:</span>
<span style={{width:"70px",display:"inline-block",textAlign:"right"}}>讲师:</span>
<Select
placeholder='请选择讲师'
style={{ width: 'calc(100% - 70px)' }}
......@@ -295,6 +296,27 @@ class LiveCourseFilter extends React.Component {
</Select>
</div>
)}
{expandFilter && (
<div className='search-condition__item'>
<span className='live-type'>直播方式:</span>
<Select
style={{ width: 'calc(100% - 70px)' }}
placeholder='请选择'
allowClear={true}
value={thirdPartType}
onChange={(value) => {
this.handleChangeQuery('thirdPartType', value)
}}
suffixIcon={
<span className='icon iconfont' style={{ fontSize: '12px', color: '#BFBFBF' }}>
&#xe835;
</span>
}>
<Option value='WECHAT'>企微直播</Option>
<Option value='TENCENT'>小麦直播</Option>
</Select>
</div>
)}
</div>
<div className='reset-fold-area'>
......
......@@ -6,23 +6,25 @@
* @Description: 大班直播、互动班课的直播课列表
*/
import User from '@/common/js/user'
import college from '@/common/lottie/college'
import { PageControl, XMTable } from '@/components'
import DownloadLiveModal from '@/components/DownloadLiveModal'
import BaseService from '@/domains/basic-domain/baseService'
import { LIVE_SHARE } from '@/domains/course-domain/constants'
import CourseService from '@/domains/course-domain/CourseService'
import { QuestionCircleOutlined } from '@ant-design/icons'
import { Dropdown, message, Modal, Switch, Tooltip } from 'antd'
import React from 'react'
import { Route, withRouter } from 'react-router-dom'
import _ from 'underscore'
import DataList from '../DataList/DataList'
import ManageCoursewareModal from '../modal/ManageCoursewareModal'
import RelatedPlanModal from '../modal/RelatedPlanModal'
import ShareLiveModal from '../modal/ShareLiveModal'
import './LiveCourseList.less'
import User from '@/common/js/user';
import WechatApi from '@/common/js/wechatApi';
import college from '@/common/lottie/college';
import { PageControl, XMTable } from '@/components';
import DownloadLiveModal from '@/components/DownloadLiveModal';
import { isWorkWx } from '@/core/platform';
import BaseService from '@/domains/basic-domain/baseService';
import { LIVE_SHARE } from '@/domains/course-domain/constants';
import CourseService from '@/domains/course-domain/CourseService';
import { QuestionCircleOutlined } from '@ant-design/icons';
import { Dropdown, message, Badge, Modal, Switch, Tooltip, Menu } from 'antd';
import React from 'react';
import { Route, withRouter } from 'react-router-dom';
import _ from 'underscore';
import DataList from '../DataList/DataList';
import ManageCoursewareModal from '../modal/ManageCoursewareModal';
import RelatedPlanModal from '../modal/RelatedPlanModal';
import ShareLiveModal from '../modal/ShareLiveModal';
import './LiveCourseList.less';
const { confirm } = Modal
const courseStateShow = {
......@@ -112,12 +114,12 @@ class LiveCourseList extends React.Component {
// 前往上课数据页面
handleLinkToClassData = (item) => {
const { match } = this.props
const { match } = this.props;
let type = item.thirdPartType === "WECHAT" ? "qiwei" : "large"
window.RCHistory.push({
pathname: `${match.url}/live-course-data?type=large&id=${item.liveCourseId}`,
})
}
pathname: `${match.url}/live-course-data?type=${type}&id=${item.liveCourseId}`,
});
};
parseColumns = () => {
let columns
const userRole = User.getUserRole()
......@@ -159,11 +161,6 @@ class LiveCourseList extends React.Component {
<span className='course-time'>
{window.formatDate('YYYY-MM-DD H:i', parseInt(record.startTime))}~{window.formatDate('H:i', parseInt(record.endTime))}
</span>
<span
className='course-status'
style={{ color: courseStateShow[record.courseState].color, border: `1px solid ${courseStateShow[record.courseState].color}` }}>
{courseStateShow[record.courseState].title}
</span>
</div>
<div className='teacher-assistant'>
<Choose>
......@@ -215,6 +212,28 @@ class LiveCourseList extends React.Component {
},
},
{
title: '上课状态',
width: '10%',
key: 'couseCatalog',
dataIndex: 'couseCatalog',
render: (val, item) => {
return <Badge
color={courseStateShow[item.courseState].color}
size="default"
text={<span style={{color:"#666666"}}>{courseStateShow[item.courseState].title}</span>}
/>;
},
},
{
title: '直播方式',
width: '10%',
key: 'couseCatalog',
dataIndex: 'couseCatalog',
render: (val, item) => {
return <div>{item.thirdPartType === "WECHAT" ? "企微直播":"小麦直播"}</div>;
},
},
{
title: '课程分类',
width: '10%',
key: 'couseCatalog',
......@@ -316,7 +335,7 @@ class LiveCourseList extends React.Component {
<Tooltip title={this.handlePlanName(record.relatedPlanList)} placement='top' arrowPointAtCenter>
{record.relatedPlanList.map((item, index) => {
return (
<span>
<span key={index}>
{item.planName} {index < record.relatedPlanList.length - 1 && <span></span>}{' '}
</span>
)
......@@ -447,11 +466,6 @@ class LiveCourseList extends React.Component {
<span className='course-time'>
{window.formatDate('YYYY-MM-DD H:i', parseInt(record.startTime))}~{window.formatDate('H:i', parseInt(record.endTime))}
</span>
<span
className='course-status'
style={{ color: courseStateShow[record.courseState].color, border: `1px solid ${courseStateShow[record.courseState].color}` }}>
{courseStateShow[record.courseState].title}
</span>
</div>
<div className='teacher-assistant'>
<Choose>
......@@ -616,23 +630,46 @@ 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)}>
<Menu
onClick={({key})=> {
if (key === "link") {
this.handleRelatedModalShow(item)
} else if (key === "edit") {
this.toEditCoursePage(item)
} else if (key === "del") {
this.handleDelete(item)
}
}}
>
<Menu.Item disabled={!(User.getUserRole() === 'CloudManager' || User.getUserRole() === 'StoreManager')} key="link">
关联培训计划
</Menu.Item>
<Menu.Item disabled={item.courseState === "STARTING" || item.courseState === "FINISH"} key="edit">
编辑
</div>
{item.courseState !== 'STARTING' && (
<div className='operate__item' onClick={() => this.handleDelete(item)}>
删除
</div>
)}
</div>
</Menu.Item>
<Menu.Item disabled={item.courseState === "STARTING"} key="del">
删除
</Menu.Item>
</Menu>
)
}
// 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)}>
// 编辑
// </div>
// {item.courseState !== 'STARTING' && (
// <div className='operate__item' onClick={() => this.handleDelete(item)}>
// 删除
// </div>
// )}
// </div>
// );
};
handleDelete = (record) => {
return confirm({
title: '你确定要删除直播课?',
......@@ -651,24 +688,58 @@ class LiveCourseList extends React.Component {
deleteConfirm = (item) => {
const params = {
liveCourseId: item.liveCourseId,
};
if (item.thirdPartType === "WECHAT") {
CourseService.delWorkWXLiveCourse(params).then((res) => {
if (res.success) {
message.success('已删除');
this.props.onChange();
}
});
} else {
CourseService.delLiveCloudCourse(params).then((res) => {
if (res.success) {
message.success('已删除');
this.props.onChange();
}
});
}
CourseService.delLiveCloudCourse(params).then((res) => {
if (res.success) {
message.success('已删除')
this.props.onChange()
}
})
}
};
toEditCoursePage = (item) => {
window.RCHistory.push({
pathname: `/create-live-course?type=edit&id=${item.liveCourseId}`,
})
}
if (item.thirdPartType === "WECHAT") {
window.RCHistory.push({
pathname: `/live-course/createqwcourse?type=edit&id=${item.liveCourseId}`,
});
} else {
window.RCHistory.push({
pathname: `/create-live-course?type=edit&id=${item.liveCourseId}`,
});
}
};
refreshCourseList = () => {
this.props.onChange(this.props.query)
}
//进入直播间
handleEnterLiveRoom = (item) => {
if (item.thirdPartType === "WECHAT") {
//进入企微直播间
if (!isWorkWx()) {
Modal.warning({
title: '提示',
content: "请使用企业微信进入直播间"
})
return
}
WechatApi.enterLiveRoom(item.livingId).then((res)=> {
console.log(res)
}).catch((err)=> {
console.log(err)
})
return
}
if (item.startTime - Date.now() > 1800000) {
Modal.warning({
title: '你来得太早了',
......
......@@ -12,22 +12,48 @@ import Service from '@/common/js/service';
import { withRouter ,Route} from "react-router-dom";
import './liveCourseOpt.less';
import BaseService from "@/domains/basic-domain/baseService";
import CerateQWCourse from './CerateQWCourse'
import CreateWorkWXCourse from './CreateWorkWXCourse'
import User from '@/common/js/user'
import LiveModeSelect from './LiveModeSelect';
class LiveCourseOpt extends React.Component {
constructor(props) {
super(props);
this.state = {
isMac: /macintosh|mac os x/i.test(navigator.userAgent),
showModeSelect: false,
}
}
handleCreateLiveCouese = ()=>{
window.RCHistory.push({
pathname: '/create-live-course?type=add',
this.setState({
showModeSelect: true
})
// window.RCHistory.push({
// pathname: '/create-live-course?type=add',
// })
}
onModeSelectClose = ()=> {
this.setState({
showModeSelect: false
})
}
onModeSelected = (type)=> {
this.setState({
showModeSelect: false
})
if (type === 0) {
window.RCHistory.push({
pathname: '/create-live-course?type=add',
})
} else if (type === 1) {
const { match } = this.props;
this.props.history.push(`${match.url}/createqwcourse?type=add`)
}
}
handleCreateQWCouese=()=>{
const { match } = this.props;
this.props.history.push(`${match.url}/createqwcourse`)
......@@ -59,13 +85,15 @@ class LiveCourseOpt extends React.Component {
const { match } = this.props;
return (
<div className="live-course-opt">
<LiveModeSelect onClose={this.onModeSelectClose} onSelected={this.onModeSelected} isShow={this.state.showModeSelect}/>
<div className="opt__left">
{ userRole !== "CloudLecturer" &&
<Button type="primary" onClick={this.handleCreateLiveCouese}>新建直播课</Button>
}
<Button onClick={this.handleDownloadClient}>下载直播客户端</Button>
{/* <Button type="primary" onClick={this.handleCreateQWCouese}>新建企微直播课</Button> */}
{!this.state.isMac && <Button onClick={this.handleDownloadClient}>下载直播客户端</Button>}
</div>
<Route path={`${match.url}/createqwcourse`} component={CerateQWCourse} />
<Route path={`${match.url}/createqwcourse`} component={CreateWorkWXCourse} />
</div>
)
}
......
.livemode-select {
position: fixed;
display: flex;
justify-content: center;
align-items: center;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background-color: rgba(0,0,0,0.4);
z-index: 1000;
.dialog {
width: 680px;
height: 438px;
background: #FFFFFF;
border-radius: 6px;
.header {
display: flex;
justify-content: space-between;
align-items: center;
width: 680px;
height: 50px;
border-bottom: 1px solid #E8E8E8;
.title {
font-size: 16px;
color: #333333;
font-weight: 400;
margin-left: 23px;
}
.close {
color: #999999;
margin-right: 23px;
font-size: 12px;
cursor: pointer;
}
}
.content {
display: flex;
justify-content: space-between;
margin: 43px 95px 50px 95px;
.item {
display: inline-block;
width: 221px;
height: 294px;
background: #FFFFFF;
box-shadow: 0px 2px 8px 3px rgba(41, 102, 255, 0.1);
border-radius: 5px;
text-align: center;
background-size: contain;
background-repeat: no-repeat;
.logo {
width: 80px;
height: 80px;
margin: 31px auto 0 auto;
}
.item-title {
font-size: 16px;
font-weight: 500;
color: #333333;
margin: 25px auto 0 auto;
}
.des {
margin: 14px auto 0 auto;
font-size: 14px;
font-weight: 400;
color: #666666;
}
.button {
font-size: 14px;
font-weight: 400;
color: white;
width: 100px;
height: 32px;
background: #2966FF;
border-radius: 16px;
margin: 25px auto 0 auto;
padding-top: 5px;
cursor: pointer;
}
}
.xiaomai-logo {
background-image: url("https://image.xiaomaiketang.com/xm/rjwN8Yc7xa.png");
}
.qiwei-logo {
background-image: url("https://image.xiaomaiketang.com/xm/CzdyntSxha.png");
}
}
}
}
.livemode-select-none {
display: none;
}
\ No newline at end of file
import React, { useState } from "react";
import "./LiveModeSelect.less"
import { createPortal } from "react-dom";
interface LiveModeSelectProps {
isShow: boolean;
onClose: ()=> void;
onSelected: (type: number)=> void;
}
export default function LiveModeSelect(props: LiveModeSelectProps) {
const handleSelect0 = (e: React.MouseEvent<HTMLDivElement>)=> {
const { onSelected } = props
onSelected(0)
}
const handleSelect1 = (e: React.MouseEvent<HTMLDivElement>)=> {
const { onSelected } = props
onSelected(1)
}
const handleClose = (e: React.MouseEvent<HTMLDivElement>)=> {
props.onClose()
}
return createPortal(
<div className={`livemode-select${props.isShow ? "":" livemode-select-none"}`}>
<div className="dialog">
<div className="header">
<div className="title">选择直播方式</div>
<span className="icon iconfont close" onClick={handleClose}>&#xe6ef;</span>
</div>
<div className="content">
<div className="item xiaomai-logo">
<div className="logo"></div>
<div className="item-title">小麦直播</div>
<div className="des">通过小麦企学院“PC客户<br/>端”进行直播</div>
<div className="button" onClick={handleSelect0}>立即创建</div>
</div>
<div className="item qiwei-logo">
<div className="logo qiwei-logo"></div>
<div className="item-title">企微直播</div>
<div className="des">通过“企业微信APP”进行<br/>直播进行直播</div>
<div className="button" onClick={handleSelect1}>立即创建</div>
</div>
</div>
</div>
</div>,
document.body
)
}
\ No newline at end of file
......@@ -48,6 +48,7 @@ class PreviewCourseModal extends React.Component {
return hours + ":" + mins + ":" + seconds;
};
dealWithTime = (startTime, endTime) => {
debugger
const startDate = new Date(Number(startTime));
const endDate = new Date(Number(endTime));
......
......@@ -3,7 +3,7 @@
padding: 24px 60px 60px 40px !important;
}
.label{
width:84px;
width:100px;
text-align:right;
font-size: 14px;
color: #666666;
......@@ -37,10 +37,10 @@
color:#FFF;
font-size:22px;
}
&:hover{
display: inline-block;
opacity:0.5;
}
// &:hover{
// display: inline-block;
// opacity:0.5;
// }
}
}
.name-item{
......@@ -58,7 +58,8 @@
}
}
.save-btn {
margin-left: 92px;
margin-top:20px;
margin-left: 106px;
}
}
\ No newline at end of file
/*
* @Author: zhangleyuan
* @Date: 2020-11-27 15:06:31
* @LastEditors: wufan
* @LastEditTime: 2021-05-28 15:31:06
* @LastEditors: Please set LastEditors
* @LastEditTime: 2021-08-02 16:35:20
* @Description: 描述一下
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
......@@ -17,6 +17,7 @@ import IdentificationModal from "./IdentificationModal";
import ChangePhoneModal from "./ChangePhoneModal";
import BaseService from "@/domains/basic-domain/baseService";
import StoreService from "@/domains/store-domain/storeService";
import WWOpenDataCom from '@/components/WWOpenDataCom';
import User from "@/common/js/user";
import "./index.less";
import { XMContext } from "@/store/context";
......@@ -35,7 +36,7 @@ function PersonalInfoPage() {
const [roleCodes, setRoleCodes] = useState([]);
const [phone, setPhone] = useState("");
const [weChatAccount, setWeChatAccount] = useState("");
const [departmentList,setDepartmentList] = useState([]);
const storeUserId = User.getStoreUserId();
const ctx: any = useContext(XMContext);
const userId = User.getUserId();
......@@ -51,11 +52,12 @@ function PersonalInfoPage() {
storeUserId: User.getStoreUserId(),
};
BaseService.getStoreUser(param).then((res) => {
const { nickName, phone, roleCodes, weChatAccount } = res.result;
const { nickName, phone, roleCodes, weChatAccount,depNameList=[]} = res.result;
setNickName(nickName);
setPhone(phone);
setRoleCodes(roleCodes);
setWeChatAccount(weChatAccount);
setDepartmentList(depNameList)
if (res.result.avatar) {
setAvatar(res.result.avatar);
}
......@@ -122,7 +124,6 @@ function PersonalInfoPage() {
setPhone(phone);
}
console.log('User.getStoreType()',User.getStoreType());
return (
<div className="page personal-info-page">
<div className="content-header">个人设置</div>
......@@ -130,18 +131,7 @@ console.log('User.getStoreType()',User.getStoreType());
<Form>
<div className="avatat-item">
<span className="label">头像:</span>
<input
type="file"
accept="image/*"
value={""}
id="CrpperAvatarPic"
style={{ display: "none" }}
onChange={_handleUpdateAvatar}
/>
<img className="avatar" src={avatar}></img>
<span className="avatar-cover" onClick={_onUpload}>
<span className="icon iconfont pen">&#xe82c;</span>
</span>
{cropperModalVisible && (
<CropperModal
imgUrl={imgUrl}
......@@ -162,9 +152,13 @@ console.log('User.getStoreType()',User.getStoreType());
}}
/>
</div>
<div className="phone-item">
<span className="label">企业微信姓名:</span>
<span><WWOpenDataCom type="userName" openid={weChatAccount}/></span>
</div>
{isWorkWechat ? (
<div className="phone-item">
<span className="label">企业微信号:</span>
<span className="label">企业微信号:</span>
<span>{weChatAccount}</span>
</div>
) : (
......@@ -181,6 +175,12 @@ console.log('User.getStoreType()',User.getStoreType());
</Button>
</div>
)}
<div>
<span className="label">所在部门:</span>
{departmentList.map((item,index)=>{
return <span>{item}{index<departmentList.length-1?'、':''}</span>
})}
</div>
<div className="save-btn">
<Button
type="primary"
......
/*
* @Author: zhangleyuan
* @Date: 2021-02-20 16:46:46
* @LastEditors: yuananting
* @LastEditTime: 2021-07-18 16:58:52
* @LastEditors: Please set LastEditors
* @LastEditTime: 2021-08-03 14:32:03
* @Description: 描述一下
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
......
......@@ -309,7 +309,6 @@ class SelectOperatorModal extends React.Component {
),
key: 'course',
dataIndex: 'course',
width: '40%',
render: (val, record) => {
let hasCover = false;
return (
......@@ -341,7 +340,7 @@ class SelectOperatorModal extends React.Component {
title: '上课时间',
key: 'courseTime',
dataIndex: 'courseTime',
width: '40%',
width: 150,
render: (val, record) => {
return (
<div>
......@@ -354,10 +353,21 @@ class SelectOperatorModal extends React.Component {
},
},
{
title: '直播方式',
key: 'thirdPartType',
dataIndex: 'thirdPartType',
width: 120,
render: (val, record) => {
return (
<div>{record.thirdPartType === "WECHAT" ? "企微直播":"小麦直播"}</div>
);
},
},
{
title: '学院展示',
key: 'shelfState',
dataIndex: 'shelfState',
width: '20%',
width: 120,
render: (val, record) => {
return (
<span>
......
......@@ -17,10 +17,9 @@ import BaseService from "@/domains/basic-domain/baseService";
import moment from 'moment';
import WechatApi from '@/common/js/wechatApi';
import { VersionContext, VersionInfo, XMContext } from '@/store/context';
import { setStoreGroupPermission, setStorePermission, setStoreGroupList, setStoreList } from '@/store/actions/index';
import { setStoreGroupPermission, setStorePermission, setStoreGroupList, setStoreList, setWechatLogin } from '@/store/actions/index';
import Service from "@/common/js/service";
import Bus from '@/core/tbus';
import { func } from 'prop-types';
const { Footer, Sider, Content } = Layout;
......@@ -32,6 +31,7 @@ const App: React.FC = (props: any) => {
const [versionInfo, setVersionInfo] = useState<VersionInfo | null>(null)
const userId = User.getUserId();
const [menuType, setMenuType] = useState(true);
const [initWechat, setInitWechat] = useState(false);
const enterpriseId = User.getEnterpriseId();
window.ctx = ctx;
......@@ -47,8 +47,17 @@ const App: React.FC = (props: any) => {
}
}, [])
async function initWechatConfig() {
WechatApi.initConfig({ isAgentConfig: true, url: window.location.href.split('#')[0] }).then(() => {
ctx.dispatch(setWechatLogin(true))
})
async function initWechatConfig() {
WechatApi.initConfig({ isAgentConfig: true, url: window.location.href.split('#')[0] })
}
}
useEffect(() => {
getStorePermission();
}, [window.location.hash])
......@@ -164,15 +173,6 @@ const App: React.FC = (props: any) => {
return (
<div id="home">
{/* <Layout>
<Sider><Menu menuType={menuType} handleMenuType={handleMenuType} /></Sider>
<Layout>
<Header id="app" handleMenuType={handleMenuType} menuType={menuType} />
<ConfigProvider locale={zhCN} autoInsertSpaceInButton={false}>
<Main menuType={menuType} />
</ConfigProvider>
</Layout>
</Layout> */}
<Header id="app" handleMenuType={handleMenuType} menuType={menuType} />
<VersionContext.Provider value={versionInfo}>
<ConfigProvider locale={zhCN} autoInsertSpaceInButton={false}>
......
......@@ -5,7 +5,9 @@ import BaseService from "@/domains/basic-domain/baseService";
import User from "@/common/js/user";
import { LIVE_SHARE } from "@/domains/course-domain/constants";
import { Modal, message } from 'antd';
import WechatApi from '@/common/js/wechatApi';
import { brandLogo } from '@/domains/brand/constants'
import WWOpenDataCom from '@/components/WWOpenData';
import './CollegeManagePage.less';
import storage from '@/common/js/storage';
......@@ -19,7 +21,6 @@ const roleMap = {
function ExpirationPopover(props) {
const [showType, setShowType] = useState(0); //0不显示,1剩余30天,2小于等于7天,3已过期
useEffect(() => {
if (props.surplusDayTime === 0) {
//已过期
......@@ -86,9 +87,9 @@ function ExpirationPopover(props) {
<div className="title">{props.surplusDayTime === 0 ? "服务已到期" : "服务到期提醒"}</div>
{
showType === 3 ? (
<div className="tip-text">当前企业购买的{`${window.brandName}`}服务已于<span style={{ color: "#FF4F4F" }}>{moment(props.endTime).format("YYYY-MM-DD HH:mm:ss")}</span>到期,到期后仍可访问,但功能不可使用,建议尽快续费购买哦~</div>
<div className="tip-text">当前企业购买的小麦企学院服务已于<span style={{ color: "#FF4F4F" }}>{moment(props.endTime).format("YYYY-MM-DD HH:mm:ss")}</span>到期,到期后仍可访问,但功能不可使用,建议尽快续费购买哦~</div>
) : (
<div className="tip-text">当前企业购买的{`${window.brandName}`}服务 <span style={{ color: "#FF4F4F" }}>仅剩{props.surplusDayTime}</span>(于<span>{moment(props.endTime).format("YYYY-MM-DD")}</span>到期),为了不影响使用,建议尽快续费购买哦~</div>
<div className="tip-text">当前企业购买的小麦企学院服务 <span style={{ color: "#FF4F4F" }}>仅剩{props.surplusDayTime}</span>(于<span>{moment(props.endTime).format("YYYY-MM-DD")}</span>到期),为了不影响使用,建议尽快续费购买哦~</div>
)
}
......@@ -118,6 +119,7 @@ export default class CollegeManagePage extends React.Component {
isAdmin: false,
createStoreList: [],
joinStoreList: [],
initWechat: false,
surplusDayTime: 365, //剩余天数
endTime: 0, //有效截至时间
};
......@@ -127,6 +129,14 @@ export default class CollegeManagePage extends React.Component {
this.getStoreList();
this.getEnterpriseUser();
this.getVersion()
}
initWechatConfig() {
WechatApi.initConfig({ isAgentConfig: true, url: window.location.href.split('#')[0] }).then(() => {
this.setState({ initWechat: true })
})
}
getEnterpriseUser() {
......@@ -167,6 +177,7 @@ export default class CollegeManagePage extends React.Component {
User.setStoreId(mainStore.id);
User.setStoreUserId(mainStore.storeUserId);
}
this.initWechatConfig();
const createStoreList = list.filter((item) => {
return item.userRole === 'StoreManager'
})
......@@ -223,9 +234,10 @@ export default class CollegeManagePage extends React.Component {
User.removeUserId();
User.removeToken();
User.removeEnterpriseId();
User.clearUserInfo();
const htmlUrl = `${LIVE_SHARE}store/index?id=${User.getCustomerStoreId() || User.getStoreId()}&userId=${User.getUserId()}&from=work_weixin`;
window.location.href = htmlUrl;
window.RCHistory.replace('/login');
// User.clearUserInfo();
// const htmlUrl = `${LIVE_SHARE}store/index?id=${User.getCustomerStoreId()||User.getStoreId()}&userId=${User.getUserId()}&from=work_weixin`;
// window.location.href = htmlUrl;
});
}
......@@ -236,7 +248,8 @@ export default class CollegeManagePage extends React.Component {
list,
isAdmin,
createStoreList,
joinStoreList
joinStoreList,
initWechat
} = this.state;
return (
<div className="college-manage-page">
......@@ -246,7 +259,12 @@ export default class CollegeManagePage extends React.Component {
<img className="box-image" src={brandLogo} />
<div className="user">
<img className="image" src={avatar} />
<span className="name">{name}</span>
<span className="name">
{
initWechat && <WWOpenDataCom type="userName" openid={name} />
}
</span>
<span
className="logout"
onClick={() => {
......@@ -270,7 +288,11 @@ export default class CollegeManagePage extends React.Component {
<div className="college-box">
<div className="user">
<img className="image" src={avatar} />
<span className="name">{name}</span>
<span className="name">
{
initWechat && <WWOpenDataCom type="userName" openid={name} />
}
</span>
</div>
<div>
<div className="title-box">
......
......@@ -71,9 +71,10 @@ export default class ErrorCollege extends React.Component {
User.removeUserId();
User.removeToken();
User.removeEnterpriseId();
User.clearUserInfo();
const url = `${LIVE_SHARE}store/index?id=${User.getCustomerStoreId()||User.getStoreId()}&userId=${User.getUserId()}&from=work_weixin`;
window.location.href = url;
window.RCHistory.replace('/login');
// User.clearUserInfo();
// const url = `${LIVE_SHARE}store/index?id=${User.getCustomerStoreId()||User.getStoreId()}&userId=${User.getUserId()}&from=work_weixin`;
// window.location.href = url;
});
}
......
......@@ -2,7 +2,7 @@
* @Author: 吴文洁
* @Date: 2019-09-10 18:26:03
* @LastEditors: Please set LastEditors
* @LastEditTime: 2021-07-20 17:39:52
* @LastEditTime: 2021-08-04 16:22:40
* @Description:
*/
import React, { useRef, useContext, useEffect, useState } from 'react';
......@@ -19,6 +19,7 @@ import CourseService from '@/domains/course-domain/CourseService';
import qrcode from '@/libs/qrcode/qrcode.js';
import Bus from '@/core/tbus';
import ClickOutside from '../../components/ClickOutside';
import WWOpenDataCom from '@/components/WWOpenDataCom';
import _ from 'underscore';
const baseImg = 'https://image.xiaomaiketang.com/xm/rJeQaZxtc7.png';
......@@ -134,7 +135,10 @@ function Header(props) {
<div className='user-detail'>
<div className='box'>
<Tooltip title={nickName}>
<div className='name'>{nickName}</div>
<div className='name'>
{/* <span>{nickName}</span> */}
<WWOpenDataCom type="userName" openid={nickName}/>
</div>
</Tooltip>
<span className='phone'>{phone}</span>
</div>
......@@ -201,9 +205,10 @@ function Header(props) {
User.removeUserId();
User.removeToken();
User.removeEnterpriseId();
User.clearUserInfo();
const url = `${LIVE_SHARE}store/index?id=${User.getCustomerStoreId() || User.getStoreId()}&userId=${User.getUserId()}&from=work_weixin`;
window.location.href = url;
window.RCHistory.replace('/login');
// User.clearUserInfo();
// const url = `${LIVE_SHARE}store/index?id=${User.getCustomerStoreId() || User.getStoreId()}&userId=${User.getUserId()}&from=work_weixin`;
// window.location.href = url;
});
}
......@@ -218,7 +223,6 @@ function Header(props) {
text: result[0].shortUrl,
size: 110,
});
qrcodeWrapDom && qrcodeWrapDom.appendChild(qrcodeNode);
});
}
......@@ -374,7 +378,10 @@ function Header(props) {
}}
src={avatar || baseImg}
/>
<span className='name'>{nickName}</span>
<span className='name'>
{/* {nickName} */}
<WWOpenDataCom type="userName" openid={nickName}/>
</span>
</div>
</Dropdown>
</div>
......
import React , { useContext, useEffect ,useState}from 'react'
import React, { useContext, useEffect, useState } from 'react'
import './Main.less';
import { MainRoutes, RedirectRoutes } from '@/routes';
import { Modal } from 'antd';
import { MainRoutes, RedirectRoutes } from '@/routes';
import routeHook from '@/core/routeHook'
import Bus from '@/core//bus';
function Main(props) {
const { menuType } = props;
console.log("menuType", menuType);
useEffect(() => {
Bus.bind('showRouteChangeModal', () => {
Modal.confirm({
title: '确定要返回吗?',
content: '返回后,本次编辑的内容将不被保存',
okText: '确认返回',
cancelText: '留在本页',
icon: <span className='icon iconfont default-confirm-icon'>&#xe6f4;</span>,
onOk: () => {
routeHook.leave()
},
});
})
}, [])
function Main(props){
const {menuType} = props;
console.log("menuType",menuType);
return (
<div
className={menuType ? `right-container has-nav` : `right-container has-nav right-container-vertical`}
id="rightContainer"
>
<MainRoutes/>
<RedirectRoutes/>
<MainRoutes />
<RedirectRoutes />
</div>
)
}
......
/*
* @Author: 吴文洁
* @Date: 2020-04-29 10:26:32
* @LastEditors: wufan
* @LastEditTime: 2021-05-13 16:39:51
* @LastEditors: Please set LastEditors
* @LastEditTime: 2021-08-03 14:34:27
* @Description: 内容线路由配置
*/
import Home from '@/modules/home/Home'
import EmployeesManagePage from '@/modules/store-manage/EmployeesManagePage'
import EmployeeManage from '@/modules/college-manage/EmployeeManage'
import personalInfoPage from '@/modules/personalInfo'
import UserManagePage from '@/modules/store-manage/UserManagePage'
import UserManage from '@/modules/college-manage/UserManagePage'
import StoreDecorationPage from '@/modules/store-manage/StoreDecorationPage'
import CourseCatalogPage from '@/modules/store-manage/CourseCatalogPage'
import LiveCoursePage from '@/modules/course-manage/LiveCoursePage'
import AddLivePage from '@/modules/course-manage/AddLive'
import VideoCoursePage from '@/modules/course-manage/video-course'
import GraphicsCoursePage from '@/modules/course-manage/graphics-course'
import OfflineCoursePage from '@/modules/course-manage/offline-course'
import AddVideoCoursePage from '@/modules/course-manage/video-course/AddVideoCourse'
import AddGraphicsCoursePage from '@/modules/course-manage/graphics-course/AddGraphicsCourse'
import AddOfflineCoursePage from '@/modules/course-manage/offline-course/AddOfflineCourse'
import Home from '@/modules/home/Home';
import EmployeesManagePage from '@/modules/store-manage/EmployeesManagePage';
import EmployeeManage from '@/modules/college-manage/EmployeeManage';
import personalInfoPage from '@/modules/personalInfo';
import UserManagePage from '@/modules/store-manage/UserManagePage';
import UserManage from '@/modules/college-manage/NewUsersManagePage';
import StoreDecorationPage from '@/modules/store-manage/StoreDecorationPage';
import CourseCatalogPage from '@/modules/store-manage/CourseCatalogPage';
import LiveCoursePage from '@/modules/course-manage/LiveCoursePage';
import AddLivePage from '@/modules/course-manage/AddLive';
import VideoCoursePage from '@/modules/course-manage/video-course';
import GraphicsCoursePage from '@/modules/course-manage/graphics-course';
import OfflineCoursePage from '@/modules/course-manage/offline-course';
import AddVideoCoursePage from '@/modules/course-manage/video-course/AddVideoCourse';
import AddGraphicsCoursePage from '@/modules/course-manage/graphics-course/AddGraphicsCourse';
import AddOfflineCoursePage from '@/modules/course-manage/offline-course/AddOfflineCourse';
// import DataList from '@/modules/course-manage/DataList/DataList';
// import ClassBook from '@/modules/resource-disk';
import ResourceDisk from '@/modules/resource-disk'
......
......@@ -18,22 +18,6 @@ import _ from 'underscore';
import SwitchRoute from '@/modules/root/SwitchRoute';
import ErrorCollege from '@/modules/root/ErrorCollege';
const history = createHashHistory();
window.RCHistory = _.extend({}, history, {
push: (obj: any) => {
history.push(obj);
},
pushState: (obj: any) => {
history.push(obj);
},
pushStateWithStatus: (obj: any) => {
history.push(obj);
},
goBack: history.goBack,
location: history.location,
replace: (obj: any) => {
history.replace(obj);
},
});
export const RootRouter = () => {
return (
......
......@@ -10,7 +10,8 @@ import {
STORE_GROUP_PERMISSION,
STORE_PERMISSION,
STORE_GROUP_LIST,
STORE_LIST
STORE_LIST,
WECHAT_LOGIN
} from './constants'
......@@ -34,12 +35,18 @@ const setStoreList = (payload: any) => ({
payload
})
const setWechatLogin = (payload: any) => ({
type: WECHAT_LOGIN,
payload
})
export {
setStoreGroupPermission,
setStorePermission,
setStoreGroupList,
setStoreList
setStoreList,
setWechatLogin
}
......@@ -10,11 +10,13 @@ const STORE_GROUP_PERMISSION = 'STORE_GROUP_PERMISSION';
const STORE_PERMISSION = 'STORE_PERMISSION';
const STORE_GROUP_LIST = 'STORE_GROUP_LIST';
const STORE_LIST = 'STORE_LIST';
const WECHAT_LOGIN = 'WECHAT_LOGIN';
export {
STORE_GROUP_PERMISSION,
STORE_PERMISSION,
STORE_GROUP_LIST,
STORE_LIST,
WECHAT_LOGIN,
}
\ No newline at end of file
......@@ -4,12 +4,14 @@ import {
setStoreGroupPermission,
setStorePermission,
setStoreGroupList,
setStoreList
setStoreList,
setWechatLogin
} from './basicAction';
export {
setStoreGroupPermission,
setStorePermission,
setStoreGroupList,
setStoreList
setStoreList,
setWechatLogin
}
\ No newline at end of file
......@@ -10,7 +10,8 @@ import {
STORE_GROUP_PERMISSION,
STORE_PERMISSION,
STORE_GROUP_LIST,
STORE_LIST
STORE_LIST,
WECHAT_LOGIN,
} from '@/store/actions/constants';
import _ from 'underscore';
import Permission from '@/common/js/permission';
......@@ -45,6 +46,11 @@ const basicReducer = (state: any, action: any) => {
return Object.assign({}, state, {
storeList,
});
case WECHAT_LOGIN:
const wechatLogin: any = action.payload;
return Object.assign({}, state, {
wechatLogin,
});
default:
return state;
}
......
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