Commit 8dd6143a by wufan

fix:合并master

parents 6e5d2b61 7928c3ee
...@@ -72,6 +72,7 @@ function getClientEnvironment(publicUrl) { ...@@ -72,6 +72,7 @@ function getClientEnvironment(publicUrl) {
// Useful for determining whether we’re running in production mode. // Useful for determining whether we’re running in production mode.
// Most importantly, it switches React into the correct mode. // Most importantly, it switches React into the correct mode.
NODE_ENV: process.env.NODE_ENV || 'development', NODE_ENV: process.env.NODE_ENV || 'development',
BRAND: process.env.BRAND || 'xiaomai',
DEPLOY_ENV: process.env.DEPLOY_ENV, DEPLOY_ENV: process.env.DEPLOY_ENV,
// Useful for resolving the correct path to static assets in `public`. // Useful for resolving the correct path to static assets in `public`.
// For example, <img src={process.env.PUBLIC_URL + '/img/logo.png'} />. // For example, <img src={process.env.PUBLIC_URL + '/img/logo.png'} />.
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -93,6 +93,7 @@ ...@@ -93,6 +93,7 @@
"style-loader": "0.23.1", "style-loader": "0.23.1",
"terser-webpack-plugin": "2.3.8", "terser-webpack-plugin": "2.3.8",
"ts-pnp": "1.1.6", "ts-pnp": "1.1.6",
"better-npm-run": "^0.1.0",
"typescript": "^4.0.2", "typescript": "^4.0.2",
"underscore": "^1.10.2", "underscore": "^1.10.2",
"url-loader": "2.3.0", "url-loader": "2.3.0",
...@@ -111,12 +112,45 @@ ...@@ -111,12 +112,45 @@
"start:rc": "cross-env DEPLOY_ENV=rc node scripts/start.js", "start:rc": "cross-env DEPLOY_ENV=rc node scripts/start.js",
"start:gray": "cross-env DEPLOY_ENV=gray node scripts/start.js", "start:gray": "cross-env DEPLOY_ENV=gray node scripts/start.js",
"start:prod": "cross-env DEPLOY_ENV=prod node scripts/start.js", "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: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:rc": "cross-env DEPLOY_ENV=rc node scripts/build.js",
"build:gray": "cross-env DEPLOY_ENV=gray node scripts/build.js", "build:gray": "cross-env DEPLOY_ENV=gray node scripts/build.js",
"build:gray-syoo": "better-npm-run build:gray-syoo",
"build:prod-syoo": "better-npm-run build:prod-syoo",
"build:prod": "cross-env DEPLOY_ENV=prod node scripts/build.js" "build:prod": "cross-env DEPLOY_ENV=prod node scripts/build.js"
}, },
"betterScripts": {
"start:syoo": {
"command": "node scripts/start.js",
"env": {
"DEPLOY_ENV": "",
"BRAND": "syoo"
}
},
"build:gray-syoo": {
"command": "node scripts/build.js",
"env": {
"DEPLOY_ENV": "gray",
"BRAND": "syoo"
}
},
"build:prod-syoo": {
"command": "node scripts/build.js",
"env": {
"DEPLOY_ENV": "prod",
"BRAND": "syoo"
}
},
"build:dev1":{
"command": "node scripts/build.js",
"env": {
"DEPLOY_ENV": "dev1",
"BRAND": "syoo"
}
}
},
"eslintConfig": { "eslintConfig": {
"extends": "react-app" "extends": "react-app"
}, },
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
<!-- <link rel="apple-touch-icon" href="../src/common/images/logo.png" /> --> <!-- <link rel="apple-touch-icon" href="../src/common/images/logo.png" /> -->
<link rel="shortcut icon" href="https://image.xiaomaiketang.com/xm/KGSYFEpcHT.png"> <link rel="shortcut icon" href="https://image.xiaomaiketang.com/xm/KGSYFEpcHT.png">
<title>小麦企学院</title> <title>扫码登陆</title>
<script type="text/javascript" charset="utf-8" src="./jquery.min.js"></script> <script type="text/javascript" charset="utf-8" src="./jquery.min.js"></script>
<style type="text/css"> <style type="text/css">
...@@ -75,7 +75,7 @@ ...@@ -75,7 +75,7 @@
$(document).ready(function () { $(document).ready(function () {
var BASIC_HOST_MAP = { var BASIC_HOST_MAP = {
dev: 'https://dev-heimdall.xiaomai5.com/', dev: 'https://dev-heimdall.xiaomai5.com/',
dev1: 'https://dev1-heimdall.xiaomai5.com/', dev1: 'https://dev-heimdall.xiaomai5.com/',
rc: 'https://rc-heimdall.xiaomai5.com/', rc: 'https://rc-heimdall.xiaomai5.com/',
gray: 'https://gray-heimdall.xiaomai5.com/', gray: 'https://gray-heimdall.xiaomai5.com/',
prod: 'https://gateway.xiaomai5.com/' prod: 'https://gateway.xiaomai5.com/'
...@@ -104,11 +104,12 @@ ...@@ -104,11 +104,12 @@
const appTermEnum = getParameterByName('appTermEnum'); const appTermEnum = getParameterByName('appTermEnum');
const code = getParameterByName('code'); const code = getParameterByName('code');
const ticket = getParameterByName('ticket'); const ticket = getParameterByName('ticket');
const corpType = getParameterByName('corpType') || 'X_MAI';
if (!code) { if (!code) {
postJSON('hades/anon/hades/getCorpTrainSuiteId', {}, (res) => { GetJSON('hades/anon/hades/getCorpTrainSuiteId', (res) => {
const url = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${res.result}&redirect_uri=${encodeURIComponent(location.href)}&response_type=code&scope=snsapi_privateinfo&state=STATE#wechat_redirect` const url = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${res.result}&redirect_uri=${encodeURIComponent(location.href)}&response_type=code&scope=snsapi_privateinfo&state=STATE#wechat_redirect`
location.href = url location.href = url
}) })
...@@ -118,7 +119,8 @@ ...@@ -118,7 +119,8 @@
postJSON("hades/anon/hades/wXWorkUserTicketLogin", { postJSON("hades/anon/hades/wXWorkUserTicketLogin", {
appTermEnum: appTermEnum, appTermEnum: appTermEnum,
code: code, code: code,
ticket: ticket ticket: ticket,
corpType
}, (res) => { }, (res) => {
if (res.code == 200) { if (res.code == 200) {
$('#success').show() $('#success').show()
...@@ -133,7 +135,20 @@ ...@@ -133,7 +135,20 @@
} }
function GetJSON(url, callback) {
const ajaxOptions = {
type: 'GET',
url: BASIC_HOST_MAP[env] + url+`?corpType=${corpType}`,
contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
timeout: 20000,
success(res, status, xhr) {
callback(res)
},
};
$.ajax(ajaxOptions)
}
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
} }
.container-left-body-table{ .container-left-body-table{
width: 300px; width: 300px;
height: 330px; height: 360px;
overflow: scroll; overflow: scroll;
.ant-table { .ant-table {
border: none; border: none;
......
/* /*
* @Author: 吴文洁 * @Author: 吴文洁
* @Date: 2020-08-31 09:34:31 * @Date: 2020-08-31 09:34:31
* @LastEditors: yuananting * @LastEditors: Please set LastEditors
* @LastEditTime: 2021-07-12 17:40:26 * @LastEditTime: 2021-08-17 16:27:31
* @Description: * @Description:
* @Copyright: 杭州杰竞科技有限公司 版权所有 * @Copyright: 杭州杰竞科技有限公司 版权所有
*/ */
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, AxiosPromise, AxiosError } from 'axios'; import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, AxiosPromise, AxiosError } from 'axios';
import { message, Modal } from 'antd'; import { message, Modal } from 'antd';
import { corpType } from '@/domains/brand/constants'
import { BASIC_HOST, TIME_OUT, USER_TYPE, VERSION, PROJECT } from '@/domains/basic-domain/constants'; import { BASIC_HOST, TIME_OUT, USER_TYPE, VERSION, PROJECT } from '@/domains/basic-domain/constants';
import User from './user'; import User from './user';
...@@ -24,12 +24,12 @@ interface FetchOptions { ...@@ -24,12 +24,12 @@ interface FetchOptions {
requestType: string, // 请求类型 form为表单类型 json为json类型,默认json类型 requestType: string, // 请求类型 form为表单类型 json为json类型,默认json类型
reject: boolean, reject: boolean,
} }
interface HeadersType{ interface HeadersType {
storeId?:any, storeId?: any,
storeUserId?:any, storeUserId?: any,
userId?:any, userId?: any,
xmtoken?:any, xmtoken?: any,
enterpriseId?:string|null enterpriseId?: string | null
} }
class Axios { class Axios {
static post( static post(
...@@ -40,17 +40,17 @@ class Axios { ...@@ -40,17 +40,17 @@ class Axios {
): Promise<any> { ): Promise<any> {
const _url = `${url}?storeId=${User.getStoreId()}&token=${User.getToken()}&storeUserId=${User.getStoreUserId()}&userId=${User.getUserId()}`; const _url = `${url}?storeId=${User.getStoreId()}&token=${User.getToken()}&storeUserId=${User.getStoreUserId()}&userId=${User.getUserId()}`;
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let headerObject:HeadersType={}; let headerObject: HeadersType = {};
if(User.getStoreId()){ if (User.getStoreId()) {
headerObject.storeId = User.getStoreId(); headerObject.storeId = User.getStoreId();
} }
if(User.getStoreUserId()){ if (User.getStoreUserId()) {
headerObject.storeUserId = User.getStoreUserId(); headerObject.storeUserId = User.getStoreUserId();
} }
if(User.getUserId()){ if (User.getUserId()) {
headerObject.userId = User.getUserId(); headerObject.userId = User.getUserId();
} }
if(User.getToken()){ if (User.getToken()) {
headerObject.xmtoken = User.getToken(); headerObject.xmtoken = User.getToken();
} }
if (User.getEnterpriseId()) { if (User.getEnterpriseId()) {
...@@ -92,8 +92,20 @@ class Axios { ...@@ -92,8 +92,20 @@ class Axios {
const { message: ResMessage, success, resultMsg, code: resultCode } = response.data; const { message: ResMessage, success, resultMsg, code: resultCode } = response.data;
if (resultCode === "CROP_DEPLOY_PAST_BETTER") { if (resultCode === "CROP_DEPLOY_PAST_BETTER") {
Modal.warning({ Modal.warning({
title:"服务已到期", title: "服务已到期",
content: "当前企业购买的小麦企学院服务已到期,如需继续使用学院功能,请尽快续费购买", content: `当前企业购买的${window.brandName}服务已到期,如需继续使用学院功能,请尽快续费购买`,
okText: "我知道了"
})
} else if (resultCode === "LIVE_START_FORBID_DEL") {
Modal.warning({
title:"提示",
content: "直播进行中,无法删除直播",
okText: "我知道了"
})
}else if(resultCode === 'STORE_NUM_FULL'){
Modal.warning({
title:"提示",
content: "企业总学院数达到上限,无法继续创建。",
okText: "我知道了" okText: "我知道了"
}) })
} else if (success || resultCode === 0) { } else if (success || resultCode === 0) {
...@@ -104,7 +116,7 @@ class Axios { ...@@ -104,7 +116,7 @@ class Axios {
return Promise.reject(response.data); return Promise.reject(response.data);
}, (error): AxiosPromise => { }, (error): AxiosPromise => {
const requestStatus = error.request.status const requestStatus = error.request.status
switch (requestStatus){ switch (requestStatus) {
case 401: case 401:
User.removeUserId(); User.removeUserId();
User.removeToken(); User.removeToken();
...@@ -130,7 +142,9 @@ class Axios { ...@@ -130,7 +142,9 @@ class Axios {
if (method === 'GET') { if (method === 'GET') {
config = Object.assign({ params, url: `${BASIC_HOST}${_url}`, method }); config = Object.assign({ params, url: `${BASIC_HOST}${_url}`, method });
} else { } else {
config = Object.assign({ data: params, url: `${BASIC_HOST}${_url}`, method }); console.log(corpType)
config = Object.assign({ data: { corpType, ...(params || {}) }, url: `${BASIC_HOST}${_url}`, method });
console.log(config,'config')
} }
instance(config).then((res: AxiosResponse): void => { instance(config).then((res: AxiosResponse): void => {
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
module.exports = { module.exports = {
isWeiXin() { isWeiXin() {
const ua = navigator.userAgent.toLowerCase(); const ua = navigator.userAgent.toLowerCase();
return ua.indexOf('micromessenger') > 0; return (ua.indexOf('micromessenger') > 0) && !(/wxwork/i.test(navigator.userAgent));
}, },
isWorkWx (){ isWorkWx (){
return /wxwork/i.test(navigator.userAgent) return /wxwork/i.test(navigator.userAgent)
...@@ -39,5 +39,8 @@ module.exports = { ...@@ -39,5 +39,8 @@ module.exports = {
const ua = navigator.userAgent.toLowerCase(); const ua = navigator.userAgent.toLowerCase();
return /xmappc/i.test(ua); return /xmappc/i.test(ua);
}, },
}; isMac() {
const ua = navigator.platform.toLowerCase();
\ No newline at end of file return ua.indexOf("mac") > 0
}
};
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: wufan * @Author: wufan
* @Date: 2021-05-11 10:21:37 * @Date: 2021-05-11 10:21:37
* @LastEditors: Please set LastEditors * @LastEditors: Please set LastEditors
* @LastEditTime: 2021-07-19 15:24:27 * @LastEditTime: 2021-07-21 14:25:37
* @Description: 企业微信api * @Description: 企业微信api
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
* *
...@@ -12,81 +12,82 @@ import Platform from '@/common/js/platform'; ...@@ -12,81 +12,82 @@ import Platform from '@/common/js/platform';
import User from '@/common/js/user'; import User from '@/common/js/user';
import Service from '@/common/js/service'; import Service from '@/common/js/service';
console.log(wx.agentConfig,' console.log(wx.agentConfig) ')
export default class WechatApi { export default class WechatApi {
static async initConfig(params = { isAgentConfig: false, url: '' }) { static initConfig(params = { isAgentConfig: false, url: '' }) {
if (Platform.isWorkWx()) { if (Platform.isWorkWx()) {
return new Promise(async (resolve, reject) => { return new Promise(async (resolve, reject) => {
Service.Hades('anon/hades/getWxCorpJSAPISignature', { Service.Hades('anon/hades/getWxCorpJSAPISignature', {
storeId: User.getStoreId(), storeId: User.getStoreId(),
url: params.url, url: window.location.href.split('#')[0],
}).then((result) => { }).then((result) => {
const res = result.result; const res = result.result;
this.config({ wx.config({
beta: true, // 必须这么写,否则wx.invoke调用形式的jsapi会有问题 beta: true, // 必须这么写,否则wx.invoke调用形式的jsapi会有问题
debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: res.appId, // 必填,企业微信的corpID appId: res.appId, // 必填,企业微信的corpID
timestamp: res.timestamp, // 必填,生成签名的时间戳 timestamp: res.timestamp, // 必填,生成签名的时间戳
nonceStr: res.nonceStr, // 必填,生成签名的随机串 nonceStr: res.nonceStr, // 必填,生成签名的随机串
signature: res.signature, // 必填,签名,见 附录-JS-SDK使用权限签名算法 signature: res.signature, // 必填,签名,见 附录-JS-SDK使用权限签名算法
jsApiList: ['chooseImage', 'shareToExternalContact', 'selectExternalContact', 'selectEnterpriseContact'], jsApiList: ['scanQRCode'],
}).then(() => { });
})
wx.ready(() => {
Service.Hades('anon/hades/getWxWorkJSAPISignature', { Service.Hades('anon/hades/getWxWorkJSAPISignature', {
storeId: User.getStoreId(), storeId: User.getStoreId(),
url: params.url, url: window.location.href.split('#')[0],
}).then((result2) => { }).then((result2) => {
const res2 = result2.result; const res2 = result2.result;
this.agentConfig({ wx.agentConfig({
corpid: res2.corpid, // 必填,企业微信的corpid,必须与当前登录的企业一致 corpid: res2.corpid, // 必填,企业微信的corpid,必须与当前登录的企业一致
agentid: res2.agentid, // 必填,企业微信的应用id (e.g. 1000247) agentid: res2.agentid, // 必填,企业微信的应用id (e.g. 1000247)
timestamp: res2.timestamp, // 必填,生成签名的时间戳 timestamp: res2.timestamp, // 必填,生成签名的时间戳
nonceStr: res2.nonceStr, // 必填,生成签名的随机串 nonceStr: res2.nonceStr, // 必填,生成签名的随机串
signature: res2.signature, // 必填,签名,见附录-JS-SDK使用权限签名算法 signature: res2.signature, // 必填,签名,见附录-JS-SDK使用权限签名算法
jsApiList: ['selectExternalContact', 'getCurExternalContact', 'getContext', 'shareToExternalContact', 'sendChatMessage', 'shareToExternalChat'], jsApiList: ['selectExternalContact', 'getCurExternalContact', 'getContext', 'shareToExternalContact', 'sendChatMessage', 'shareToExternalChat', 'startLiving', 'replayLiving'],
success: (res) => { success: (res) => {
console.log(res, 'res-agentconfig'); console.log(res, 'agentConfig 成功', 'res-agentconfig');
console.info('window.WWOpenData', window.WWOpenData);
resolve(res); resolve(res);
}, },
fail: (err) => { fail: (err) => {
console.log(1213545344545) console.log(1213545344545)
console.log(err, 'err-agentconfig'); console.log(err, 'err-agentconfig');
reject(err);
}, },
}); });
}); });
});
wx.error((err) => {
console.log('getWxCorpJSAPISignature', err)
});
}) })
});
})
} else { } else {
if (params.isAgentConfig) {
console.log(32132132, 'cesgu')
return new Promise(async (resolve, reject) => { return new Promise(async (resolve, reject) => {
Service.Hades('anon/hades/getWxWorkJSAPISignature', { Service.Hades('anon/hades/getWxWorkJSAPISignature', {
storeId: User.getStoreId(), storeId: User.getStoreId(),
url: params.url, url: window.location.href.split('#')[0],
}).then((result2) => { }).then((result2) => {
const res2 = result2.result; const res2 = result2.result;
this.agentConfig({ wx.agentConfig({
corpid: res2.corpid, // 必填,企业微信的corpid,必须与当前登录的企业一致 corpid: res2.corpid, // 必填,企业微信的corpid,必须与当前登录的企业一致
agentid: res2.agentid, // 必填,企业微信的应用id (e.g. 1000247) agentid: res2.agentid, // 必填,企业微信的应用id (e.g. 1000247)
timestamp: res2.timestamp, // 必填,生成签名的时间戳 timestamp: res2.timestamp, // 必填,生成签名的时间戳
nonceStr: res2.nonceStr, // 必填,生成签名的随机串 nonceStr: res2.nonceStr, // 必填,生成签名的随机串
signature: res2.signature, // 必填,签名,见附录-JS-SDK使用权限签名算法 signature: res2.signature, // 必填,签名,见附录-JS-SDK使用权限签名算法
jsApiList: ['selectExternalContact', 'getCurExternalContact', 'getContext', 'shareToExternalContact', 'sendChatMessage', 'shareToExternalChat'], jsApiList: ['selectExternalContact', 'getCurExternalContact', 'getContext', 'shareToExternalContact', 'sendChatMessage', 'shareToExternalChat', 'startLiving', 'replayLiving'],
success: (res) => { success: (res) => {
console.log(res, 'res-agentconfig'); console.log(res, 'agentConfig 成功', 'res-agentconfig');
console.info('window.WWOpenData', window.WWOpenData);
resolve(res); resolve(res);
}, },
fail: (err) => { fail: (err) => {
console.log(1213545344545) console.log(1213545344545)
console.log(err, 'err-agentconfig'); console.log(err, 'err-agentconfig');
reject(err);
}, },
}); });
}); });
...@@ -94,35 +95,13 @@ export default class WechatApi { ...@@ -94,35 +95,13 @@ export default class WechatApi {
} }
} }
}
static async config(config) {
return new Promise((resolve, reject) => {
console.info('wx.config', config);
wx.config(config);
wx.ready(resolve);
wx.error(reject);
}).then(
() => {
console.info('wx.ready');
},
(error) => {
console.error('wx.error', error);
throw error;
}
);
}
static async agentConfig(config) { static getContext() {
wx.agentConfig({ ...config });
}
static getCurExternalContact() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
wx.ready(() => { wx.ready(() => {
wx.invoke('getCurExternalContact', {}, function (res) { wx.invoke('getContext', {}, function (res) {
if (res.err_msg == 'getCurExternalContact:ok') { if (res.err_msg == 'getContext:ok') {
resolve(res.userId); //返回当前外部联系人userId resolve(res.entry); //返回进入H5页面的入口类型,目前有normal、contact_profile、single_chat_tools、group_chat_tools、chat_attachment
} else { } else {
reject(res.err_msg); //错误处理 reject(res.err_msg); //错误处理
} }
...@@ -130,18 +109,53 @@ export default class WechatApi { ...@@ -130,18 +109,53 @@ export default class WechatApi {
}); });
}); });
} }
//进入直播间
static getContext() { static enterLiveRoom(id) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
wx.ready(() => { wx.ready(() => {
wx.invoke('getContext', {}, function (res) { wx.invoke('startLiving', {
if (res.err_msg == 'getContext:ok') { "livingId": id,
resolve(res.entry); //返回进入H5页面的入口类型,目前有normal、contact_profile、single_chat_tools、group_chat_tools、chat_attachment }, function (res) {
if (res.err_msg === "startLiving:ok") {
resolve(true)
} else { } else {
reject(res.err_msg); //错误处理 reject(res.err_msg); //错误处理
} }
}); });
}); });
})
}
static replayLiving(id) {
return new Promise((resolve, reject) => {
wx.ready(() => {
wx.invoke('replayLiving', {
"livingId": id,
}, function (res) {
if (res.err_msg === "replayLiving:ok") {
resolve(true)
} else {
let err = "进入回放失败"
console.log(res.err_msg);
if (res.err_msg === "replayLiving:fail_invalid living id") {
err = "不合法的直播ID"
} else if (res.err_msg === "replayLiving:fail_not allow to cross corp") {
err = "不可跨企业使用直播ID"
} else if (res.err_msg === "replayLiving:fail_not allow to cross app") {
err = "不可跨应用使用直播ID"
} else if (res.err_msg === "replayLiving:fail_living has no replay") {
// err = "直播回放已失效或不存在"
err = "该直播课未录制回放"
} else if (res.err_msg === "replayLiving:fail_replay is beging creating") {
err = "回放生成中,请耐心等待"
} else if (res.err_msg === "replayLiving:fail_create replay failed") {
err = "回放创建失败"
} else if (res.err_msg === "replayLiving:fail_invalid parameter") {
err = "参数不合法"
}
reject(err); //错误处理
}
}); });
});
})
} }
} }
import React, { ReactElement } from "react"; import React, { ReactElement } from "react";
import { Popover } from "antd"; import { Popover } from "antd";
import { TooltipPlacement } from "antd/lib/tooltip"; import { TooltipPlacement } from "antd/lib/tooltip";
import { brandLogo,xfrwm } from '@/domains/brand/constants'
import { ActionType } from "rc-trigger/lib/interface";
import "./ContactWidget.less" import "./ContactWidget.less"
interface ContactWidgetProps { interface ContactWidgetProps {
...@@ -14,7 +16,7 @@ function Content() { ...@@ -14,7 +16,7 @@ function Content() {
return ( return (
<div className="contact-widget"> <div className="contact-widget">
<div className="qrcode"> <div className="qrcode">
<img src="https://cdn.xiaomai5.com/qixueyuankehu.png" alt=""></img> <img src={xfrwm} alt=""></img>
<div className="des">微信/企业微信扫码咨询</div> <div className="des">微信/企业微信扫码咨询</div>
</div> </div>
<div className="phone"><svg style={{position:"relative",top:"2px",marginRight:"4px"}} viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M512.651 3.78c-281.433 0-509.21 228.324-509.21 509.209 0 281.43 228.325 509.203 509.21 509.203 281.427 0 509.202-228.317 509.202-509.203 0.55-280.885-227.775-509.21-509.202-509.21z m198.205 743.553c-36.14 36.136-169.737 1.641-302.24-130.312-131.953-131.959-165.902-266.104-129.768-301.695 31.211-31.21 68.99-85.417 125.939-14.782 56.943 70.629 29.016 90.34-3.291 122.647-22.449 22.448 24.642 79.392 73.37 128.125 49.283 48.73 105.678 95.818 128.126 73.368 32.306-32.305 52.017-60.23 122.646-3.288 71.182 56.949 16.426 95.276-14.782 125.937z" p-id="4409" fill="#999999"></path></svg> <div className="phone"><svg style={{position:"relative",top:"2px",marginRight:"4px"}} viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M512.651 3.78c-281.433 0-509.21 228.324-509.21 509.209 0 281.43 228.325 509.203 509.21 509.203 281.427 0 509.202-228.317 509.202-509.203 0.55-280.885-227.775-509.21-509.202-509.21z m198.205 743.553c-36.14 36.136-169.737 1.641-302.24-130.312-131.953-131.959-165.902-266.104-129.768-301.695 31.211-31.21 68.99-85.417 125.939-14.782 56.943 70.629 29.016 90.34-3.291 122.647-22.449 22.448 24.642 79.392 73.37 128.125 49.283 48.73 105.678 95.818 128.126 73.368 32.306-32.305 52.017-60.23 122.646-3.288 71.182 56.949 16.426 95.276-14.782 125.937z" p-id="4409" fill="#999999"></path></svg>
......
...@@ -5,30 +5,38 @@ ...@@ -5,30 +5,38 @@
* Date: 2016/12/30 * Date: 2016/12/30
* Time: 下午2:32 * Time: 下午2:32
*/ */
import React from 'react' import React from 'react';
import { message } from "antd"; import { message } from 'antd';
import moment from 'moment'; import moment from 'moment';
require("./MultipleDatePicker.less"); require('./MultipleDatePicker.less');
class MultipleDatePicker extends React.Component { class MultipleDatePicker extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
calendar: "", calendar: '',
calendarDate: props.type ? moment(props.startTime):moment(), calendarDate: props.type ? moment(props.startTime) : moment(),
detailList: [], detailList: [],
waitNoticeNumber: 0, waitNoticeNumber: 0,
totalCount: 0, totalCount: 0,
selectDateList: props.selectDateList || [], selectDateList: props.selectDateList || [],
endTime: props.endTime || null, endTime: props.endTime || null,
startTime: props.startTime || null, startTime: props.startTime || null,
homeworkProcessEnum: props.homeworkProcessEnum || '' homeworkProcessEnum: props.homeworkProcessEnum || '',
}; };
} }
componentWillReceiveProps(nextProps) { componentWillReceiveProps(nextProps) {
this.setState({endTime : nextProps.endTime, startTime: nextProps.startTime, selectDateList: nextProps.selectDateList, homeworkProcessEnum:nextProps.homeworkProcessEnum},() => { this.setState(
{
endTime: nextProps.endTime,
startTime: nextProps.startTime,
selectDateList: nextProps.selectDateList,
homeworkProcessEnum: nextProps.homeworkProcessEnum,
},
() => {
this.handleQuery(); this.handleQuery();
}); }
);
} }
componentDidMount() { componentDidMount() {
...@@ -43,25 +51,22 @@ class MultipleDatePicker extends React.Component { ...@@ -43,25 +51,22 @@ class MultipleDatePicker extends React.Component {
} }
renderCalendar() { renderCalendar() {
var start = moment(this.state.calendarDate).startOf("month"), var start = moment(this.state.calendarDate).startOf('month'),
startDay = start.dates(), startDay = start.date(),
// 每月的第一天是星期几 [0-6] 6:日 // 每月的第一天是星期几 [0-6] 6:日
startWeekOf = start.weekday(); startWeekOf = start.weekday();
var end = moment(this.state.calendarDate).endOf("month"), var end = moment(this.state.calendarDate).endOf('month'),
endDay = end.dates(), endDay = end.date(),
endWeekOf = end.weekday(); endWeekOf = end.weekday();
var dateElms = []; var dateElms = [];
// 上月余留的天 // 上月余留的天
var prevMonthDays = moment(start).subtract("month", 1).endOf("month"), var prevMonthDays = moment(start).subtract(1, 'months').endOf('month'),
prevMonthDaysNumber = prevMonthDays.dates(); prevMonthDaysNumber = prevMonthDays.date();
for ( for (var j = prevMonthDaysNumber - startWeekOf, i = 0; i < startWeekOf + 1; i++, j++) {
var j = prevMonthDaysNumber - startWeekOf + 1, i = 0; var time = moment(prevMonthDays).subtract(startWeekOf - 1 - i, 'days');
i < startWeekOf;
i++, j++
) {
var time = moment(prevMonthDays).subtract("days", startWeekOf - 1 - i);
dateElms.push( dateElms.push(
<li className={"disabled"} key={"before" + i}> <li className={'disabled'} key={'before' + i}>
<span>{j}</span> <span>{j}</span>
</li> </li>
); );
...@@ -69,44 +74,40 @@ class MultipleDatePicker extends React.Component { ...@@ -69,44 +74,40 @@ class MultipleDatePicker extends React.Component {
// 本月 // 本月
for (var i = startDay; i <= endDay; i++) { for (var i = startDay; i <= endDay; i++) {
var time = moment(start).add("days", i - 1); var time = moment(start).add(i - 1, 'days');
var className = "";
if(!this.props.canSelectTodayBefore && time.valueOf() < moment().valueOf() && time.format("YYYY-MM-DD") != moment().format("YYYY-MM-DD")) { var className = '';
className = 'before-disabled' if (!this.props.canSelectTodayBefore && time.valueOf() < moment().valueOf() && time.format('YYYY-MM-DD') != moment().format('YYYY-MM-DD')) {
className = 'before-disabled';
} }
// 今日待跟进 // 今日待跟进
if (time.format("YYYY-MM-DD") == moment().format("YYYY-MM-DD")) { if (time.format('YYYY-MM-DD') == moment().format('YYYY-MM-DD')) {
className += " today"; className += ' today';
} }
if (this.state.selectDateList.indexOf(time.valueOf()) > -1) { if (this.state.selectDateList.indexOf(time.valueOf()) > -1) {
className += " active"; className += ' active';
const today = moment().startOf('day').valueOf(); const today = moment().startOf('day').valueOf();
if(this.props.type && this.props.type == 'CALENDAR_CLOCK' && (time.valueOf() < today) && this.state.homeworkProcessEnum == 'ONGOING') { if (this.props.type && this.props.type == 'CALENDAR_CLOCK' && time.valueOf() < today && this.state.homeworkProcessEnum == 'ONGOING') {
className += " past"; className += ' past';
} }
} }
if(this.state.startTime && this.state.endTime && (time.valueOf() > this.state.endTime.valueOf() || time.valueOf() < this.state.startTime.valueOf())) { if (this.state.startTime && this.state.endTime && (time.valueOf() > this.state.endTime.valueOf() || time.valueOf() < this.state.startTime.valueOf())) {
className += " disabled" className += ' disabled';
} }
dateElms.push( dateElms.push(
<li <li className={className} key={'curr' + i} onClick={this.handleShowDetail.bind(this, time, className)}>
className={className}
key={"curr" + i}
onClick={this.handleShowDetail.bind(this, time, className)}
>
<span>{i}</span> <span>{i}</span>
</li> </li>
); );
} }
// 下月预来的天 // 下月预来的天
for (var j = 1, i = endWeekOf; i < 6; i++, j++) { for (var j = 1, i = endWeekOf; i < 6; i++, j++) {
var time = moment(end).add("days", i); var time = moment(end).add(i, 'days');
dateElms.push( dateElms.push(
<li className={"disabled"} key={"after" + i}> <li className={'disabled'} key={'after' + i}>
<span>{j}</span> <span>{j}</span>
</li> </li>
); );
...@@ -115,18 +116,24 @@ class MultipleDatePicker extends React.Component { ...@@ -115,18 +116,24 @@ class MultipleDatePicker extends React.Component {
} }
handleShowDetail(time, className) { handleShowDetail(time, className) {
if((!this.props.canSelectTodayBefore && className === 'before-disabled') || this.props.disabled) { if ((!this.props.canSelectTodayBefore && className === 'before-disabled') || this.props.disabled) {
return return;
} }
let date = time.valueOf(); let date = time.valueOf();
const today = moment().startOf('day').valueOf(); const today = moment().startOf('day').valueOf();
if(this.props.type && this.props.type == 'CALENDAR_CLOCK' && (date < today)) { if (this.props.type && this.props.type === 'CALENDAR_CLOCK' && date < today) {
return; return;
} }
if(this.state.homeworkProcessEnum == 'ONGOING' && date == today) { if (this.state.homeworkProcessEnum === 'ONGOING' && date == today) {
return; return;
} }
if(this.props.type && this.props.type == 'CALENDAR_CLOCK' && this.state.startTime && this.state.endTime && (date > this.state.endTime.valueOf() || date < this.state.startTime.valueOf())) { if (
this.props.type &&
this.props.type == 'CALENDAR_CLOCK' &&
this.state.startTime &&
this.state.endTime &&
(date > this.state.endTime.valueOf() || date < this.state.startTime.valueOf())
) {
return; return;
} }
let tempArr = this.state.selectDateList; let tempArr = this.state.selectDateList;
...@@ -136,7 +143,7 @@ class MultipleDatePicker extends React.Component { ...@@ -136,7 +143,7 @@ class MultipleDatePicker extends React.Component {
tempArr.splice(index, 1); tempArr.splice(index, 1);
} else { } else {
if (tempArr.length > 29 && !this.props.type) { if (tempArr.length > 29 && !this.props.type) {
message.warning("最多选择30天"); message.warning('最多选择30天');
return; return;
} else { } else {
tempArr.push(date); tempArr.push(date);
...@@ -155,95 +162,82 @@ class MultipleDatePicker extends React.Component { ...@@ -155,95 +162,82 @@ class MultipleDatePicker extends React.Component {
render() { render() {
const self = this; const self = this;
const {calendarDate, endTime,startTime } = this.state; const { calendarDate, endTime, startTime } = this.state;
const { type} = this.props; const { type } = this.props;
const prevMonth = startTime && calendarDate.subtract("month", 1).endOf('month').valueOf() < startTime.valueOf(); const prevMonth = startTime && calendarDate.subtract(1, 'months').endOf('month').valueOf() < startTime.valueOf();
const nextMonth = !(endTime && calendarDate.add("month", 1).valueOf() < endTime.valueOf()); const nextMonth = !(endTime && calendarDate.add(1, 'months').valueOf() < endTime.valueOf());
return ( return (
<div <div className={`multiple-calendar ${type === 'CALENDAR_CLOCK' ? 'punch-calender' : ''}`}>
className={`multiple-calendar ${ <Choose>
type == "CALENDAR_CLOCK" ? "punch-calender" : "" <When condition={type == 'CALENDAR_CLOCK'}>
}`} <div className='punch-control'>
> <div className='punch-main'>
{type == "CALENDAR_CLOCK" ? (
<div className="punch-control">
<div className="punch-main">
<div <div
onClick={function () { onClick={function () {
if(prevMonth){return} if (prevMonth) {
this.state.calendarDate = this.state.calendarDate.subtract( return;
"month", }
1 this.state.calendarDate = this.state.calendarDate.subtract(1, 'months');
);
self.handleQuery(); self.handleQuery();
}.bind(this)} }.bind(this)}
className={`prev-icon ${prevMonth?'disbled-icon':''}`} className={`prev-icon ${prevMonth ? 'disbled-icon' : ''}`}>
> <span className='icon iconfont'>&#xe65f;</span>
<span className="icon iconfont">&#xe65f;</span>
</div> </div>
<span className="month">{this.state.calendarDate.format("YYYY年MM月")}</span> <span className='month'>{this.state.calendarDate.format('YYYY年MM月')}</span>
<div <div
className={`next-icon ${nextMonth?'disbled-icon':''}`} className={`next-icon ${nextMonth ? 'disbled-icon' : ''}`}
onClick={function () { onClick={function () {
if(nextMonth){return} if (nextMonth) {
this.state.calendarDate = this.state.calendarDate.add( return;
"month", }
1 this.state.calendarDate = this.state.calendarDate.add(1, 'months');
);
self.handleQuery(); self.handleQuery();
}.bind(this)} }.bind(this)}>
> <span className='icon iconfont'>&#xe65e;</span>
<span className="icon iconfont">&#xe65e;</span>
</div> </div>
</div> </div>
<div <div
className="self" className='self'
onClick={function () { onClick={function () {
this.state.calendarDate = moment(startTime); this.state.calendarDate = moment(startTime);
self.handleQuery(); self.handleQuery();
}.bind(this)} }.bind(this)}>
>
回到起始月 回到起始月
</div> </div>
</div> </div>
) : ( </When>
<div className="t-control"> <Otherwise>
<div className='t-control'>
<div <div
className="prev" className='prev'
onClick={function () { onClick={function () {
this.state.calendarDate = this.state.calendarDate.subtract( this.state.calendarDate = this.state.calendarDate.subtract(1, 'months');
"month",
1
);
self.handleQuery(); self.handleQuery();
}.bind(this)} }.bind(this)}>
>
上月 上月
</div> </div>
<div className="loc"> <div className='loc'>{this.state.calendarDate.format('YYYY年MM月')}</div>
{this.state.calendarDate.format("YYYY年MM月")}
</div>
<div <div
className="self" className='self'
onClick={function () { onClick={function () {
this.state.calendarDate = moment(); this.state.calendarDate = moment();
self.handleQuery(); self.handleQuery();
}.bind(this)} }.bind(this)}>
>
本月 本月
</div> </div>
<div <div
className="next" className='next'
onClick={function () { onClick={function () {
this.state.calendarDate = this.state.calendarDate.add('month', 1); this.state.calendarDate = this.state.calendarDate.add(1, 'months');
self.handleQuery() self.handleQuery();
}.bind(this)} }.bind(this)}>
>
下月 下月
</div> </div>
</div> </div>
)} </Otherwise>
<ul className="week"> </Choose>
<ul className='week'>
<li></li> <li></li>
<li></li> <li></li>
<li></li> <li></li>
...@@ -251,9 +245,8 @@ class MultipleDatePicker extends React.Component { ...@@ -251,9 +245,8 @@ class MultipleDatePicker extends React.Component {
<li></li> <li></li>
<li></li> <li></li>
<li></li> <li></li>
</ul> </ul>
<ul className="calendar" id="multiCalendar"> <ul className='calendar' id='multiCalendar'>
{this.state.calendar} {this.state.calendar}
</ul> </ul>
</div> </div>
...@@ -264,9 +257,9 @@ class MultipleDatePicker extends React.Component { ...@@ -264,9 +257,9 @@ class MultipleDatePicker extends React.Component {
MultipleDatePicker.propTypes = {}; MultipleDatePicker.propTypes = {};
MultipleDatePicker.defaultProps = { MultipleDatePicker.defaultProps = {
reEditUrl: "", reEditUrl: '',
close: function () {}, close: function () {},
canSelectTodayBefore: true // 支持选择今天之前的日期 canSelectTodayBefore: true, // 支持选择今天之前的日期
}; };
export default MultipleDatePicker; export default MultipleDatePicker;
...@@ -330,9 +330,9 @@ mr0 { ...@@ -330,9 +330,9 @@ mr0 {
} }
// ant badge改小 // ant badge改小
.ant-badge { // .ant-badge {
transform: translate(-8px, -8px) scale(0.7) !important; // transform: translate(-8px, -8px) scale(0.7) !important;
} // }
.ant-select-selection { .ant-select-selection {
border-color: @xm-color-border !important; border-color: @xm-color-border !important;
......
...@@ -1723,4 +1723,23 @@ input:focus { ...@@ -1723,4 +1723,23 @@ input:focus {
flex: 1; flex: 1;
} }
.createQWCourse{
.footer {
position: fixed;
bottom: 0;
height: 58px;
width: 100%;
display: flex;
align-items: center;
justify-content: flex-end;
padding-right: 252px;
background: #fff;
border-top: 1px solid #E8E8E8;
z-index: 999;
.ant-btn {
margin-left: 10px;
}
}
}
} }
\ No newline at end of file
module.exports = {
isWeiXin() {
const ua = navigator.userAgent.toLowerCase();
return ua.indexOf('micromessenger') > 0;
},
isWorkWx (){
return /wxwork/i.test(navigator.userAgent)
},
isAlipay() {
const ua = navigator.userAgent.toLowerCase();
return ua.indexOf('aliapp') > 0 || ua.indexOf('alipay') > 0;
},
isXiaoMaiApp() {
const ua = navigator.userAgent.toLowerCase();
return ua.match(/xiaomai_ios/i) === 'xiaomai_ios' || ua.match(/xiaomai_android/i) === 'xiaomai_android';
},
isXiaoMaiIOSApp() {
const ua = navigator.userAgent.toLowerCase();
return ua.match(/xiaomai_ios/i) === 'xiaomai_ios';
},
isXiaoMaiAndroidApp() {
const ua = navigator.userAgent.toLowerCase();
return ua.match(/xiaomai_android/i) === 'xiaomai_android';
},
isAndroid() {
const ua = navigator.userAgent.toLowerCase();
return /android/i.test(ua);
},
isIOS() {
const ua = navigator.userAgent.toLowerCase();
return /iphone|ipad|ipod/i.test(ua);
},
isMeiKe() {
const ua = navigator.userAgent.toLowerCase();
return /xmappc/i.test(ua);
},
isMac() {
const ua = navigator.platform.toLowerCase();
return ua.indexOf("mac") >= 0
}
};
\ No newline at end of file
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() { //取消跳转
console.log('jhgjh')
this.routeFun.pop()
}
break() { //切换路由是执行的函数
const enterFun = this.routeFun[0];
enterFun && enterFun()
}
leave() { //切换路由
const callBacks = this.callBacks.pop();
callBacks && callBacks()
this.routeFun = [];
}
//离开保存时的特例
// **
addSaveCase() { //离开保存校验时将方法注入
setTimeout(()=>{
this.add(this.saveBeforeLeave.bind(this))
},100)
}
saveBeforeLeave() { //离开保存时触发的方法
Bus.trigger('showRouteChangeModal')
}
//** */
getCallbackNum() {
return this.routeFun.length
}
}
export default new routeHook()
\ No newline at end of file
import Platform from './platform';
import Service from "@/common/js/service";
import User from '@/common/js/user';
export default class WechatApi {
static initShareConfig() {
// if (Platform.isWeiXin()) {
const data = { url: window.location.href.split('#')[0], storeId: User.getStoreId(), }
Service.Hades('anon/hades/getWxWorkJSAPISignature', data).then((result) => {
const res = result.result;
const conf ={
corpid: res.corpid, // 必填,企业微信的corpid,必须与当前登录的企业一致
agentid: res.agentid, // 必填,企业微信的应用id (e.g. 1000247)
timestamp: res.timestamp, // 必填,生成签名的时间戳
nonceStr: res.nonceStr,// 必填,生成签名的随机串
signature: res.signature,
jsApiList: ['startLiving','downloadLivingReplay'],
success: function(res) {
console.log('agentConfig注册成功')
console.log(res,'agentConfig')
},
fail: function(res) {
console.log(res,' agentConfig1 错误')
if(res.errMsg.indexOf('function not exist') > -1){
alert('版本过低请升级')
}
},
complete:(res)=>{
console.log(res,' agentConfig2 错误')
}
}
console.log(conf)
wx.agentConfig(conf);
});
// }
}
}
\ No newline at end of file
...@@ -12,6 +12,9 @@ import Service from "@/common/js/service"; ...@@ -12,6 +12,9 @@ import Service from "@/common/js/service";
export function fetchLecturerData(params: object) { export function fetchLecturerData(params: object) {
return Service.Hades("public/courseCloud/queryTeacherVisitData", params); return Service.Hades("public/courseCloud/queryTeacherVisitData", params);
} }
export function fetchWorkWXLecturerData(params: object) {
return Service.Hades("public/courseCloud/queryWechatLiveTeacherData", params);
}
export function getQrcode(params: object) { export function getQrcode(params: object) {
return Service.Sales("public/businessShow/convertShortUrls", params); return Service.Sales("public/businessShow/convertShortUrls", params);
} }
...@@ -19,11 +22,18 @@ export function getQrcode(params: object) { ...@@ -19,11 +22,18 @@ export function getQrcode(params: object) {
export function fetchUserData(params: object) { export function fetchUserData(params: object) {
return Service.Hades("public/courseCloud/queryStudentVisitData", params); return Service.Hades("public/courseCloud/queryStudentVisitData", params);
} }
export function fetchWorkWXUserData(params: object) {
return Service.Hades("public/courseCloud/queryWechatLiveStudentData", params);
}
export function createLiveCloudCourse(params: object) { export function createLiveCloudCourse(params: object) {
return Service.Hades("public/courseCloud/createLiveCloudCourse", params); return Service.Hades("public/courseCloud/createLiveCloudCourse", params);
} }
export function createWorkWXLiveCourse(params: object) {
return Service.Hades("public/courseCloud/createWechatLiveCourse", params);
}
export function getLiveCloudCoursePage(params: object) { export function getLiveCloudCoursePage(params: object) {
return Service.Hades("public/courseCloud/getLiveCloudCoursePage", params); return Service.Hades("public/courseCloud/getLiveCloudCoursePage", params);
} }
...@@ -32,6 +42,10 @@ export function exportStudentCourseData(params: object) { ...@@ -32,6 +42,10 @@ export function exportStudentCourseData(params: object) {
return Service.Hades("public/courseCloud/exportCourseCloudVisitorAsync", params); return Service.Hades("public/courseCloud/exportCourseCloudVisitorAsync", params);
} }
export function exportWorkWXStudentCourseData(params: object) {
return Service.Hades("public/courseCloud/exportWechatLiveStudentData", params);
}
export function exportPlayBackCourseData(params: object) { export function exportPlayBackCourseData(params: object) {
return Service.Hades("public/courseCloud/exportCourseCloudPlayBackSync", params); return Service.Hades("public/courseCloud/exportCourseCloudPlayBackSync", params);
} }
...@@ -42,16 +56,27 @@ export function getLiveCloudCourseDetail(params: object) { ...@@ -42,16 +56,27 @@ export function getLiveCloudCourseDetail(params: object) {
return Service.Hades("public/courseCloud/getLiveCloudCourseDetail", params); return Service.Hades("public/courseCloud/getLiveCloudCourseDetail", params);
} }
export function getWorkWXLiveCourseDetail(params: object) {
return Service.Hades("public/courseCloud/getWechatLiveCourseDetail", params)
}
export function updateLiveCloudCourse(params: object) { export function updateLiveCloudCourse(params: object) {
return Service.Hades("public/courseCloud/updateLiveCloudCourse", params); return Service.Hades("public/courseCloud/updateLiveCloudCourse", params);
} }
export function updateWorkWXLiveCourse(params: object) {
return Service.Hades("public/courseCloud/editWechatLiveCourse", params);
}
export function turnOnOrOffLiveCloudCourse(params: object) { export function turnOnOrOffLiveCloudCourse(params: object) {
return Service.Hades("public/courseCloud/turnOnOrOffLiveCloudCourse", params); return Service.Hades("public/courseCloud/turnOnOrOffLiveCloudCourse", params);
} }
export function delLiveCloudCourse(params: object) { export function delLiveCloudCourse(params: object) {
return Service.Hades("public/courseCloud/delLiveCloudCourse", params); return Service.Hades("public/courseCloud/delLiveCloudCourse", params);
} }
export function delWorkWXLiveCourse(params: object) {
return Service.Hades("public/courseCloud/delWechatLiveCourse", params);
}
//该接口主要用于培训计划关联直播课的接口(会筛选掉已关联的直播课) //该接口主要用于培训计划关联直播课的接口(会筛选掉已关联的直播课)
export function getLiveCloudCourseBasePage(params: object) { export function getLiveCloudCourseBasePage(params: object) {
return Service.Hades("public/courseCloud/getLiveCloudCourseBasePage", params); return Service.Hades("public/courseCloud/getLiveCloudCourseBasePage", params);
......
...@@ -75,6 +75,19 @@ export function updateStoreMessage(params: object) { ...@@ -75,6 +75,19 @@ export function updateStoreMessage(params: object) {
export function getStoreDetail(params: object) { export function getStoreDetail(params: object) {
return Service.Hades("public/hades/getStoreDetail", params); return Service.Hades("public/hades/getStoreDetail", params);
} }
export function getCustomerAuditList(params: object){
return Service.Hades('public/hades/getCustomerAuditList',params);
}
export function getCustomerAuditListCount(params: object){
return Service.Hades('public/hades/getCustomerAuditCount',params);
}
export function auditOperation(params: object){
return Service.Hades('public/hades/auditOperation',params);
}
export function getByDepartmentId(params: object) { export function getByDepartmentId(params: object) {
return Service.Hades("public/hades/getByDepartmentId", params); return Service.Hades("public/hades/getByDepartmentId", params);
} }
......
/* /*
* @Author: 陈剑宇 * @Author: 陈剑宇
* @Date: 2020-05-07 14:43:01 * @Date: 2020-05-07 14:43:01
* @LastEditTime: 2021-08-15 18:31:02 * @LastEditTime: 2021-09-03 10:28:14
* @LastEditors: wufan * @LastEditors: wufan
* @Description: * @Description:
* @FilePath: /wheat-web-demo/src/domains/basic-domain/constants.ts * @FilePath: /wheat-web-demo/src/domains/basic-domain/constants.ts
*/ */
import { MapInterface } from '@/domains/basic-domain/interface' import { MapInterface } from '@/domains/basic-domain/interface'
import { path, live } from '@/domains/brand/constants'
// 默认是 dev 环境 // 默认是 dev 环境
const ENV: string = process.env.DEPLOY_ENV || 'dev' const ENV: string = process.env.DEPLOY_ENV || 'dev'
console.log('process.env.DEPLOY_ENV', process) console.log('process.env.DEPLOY_ENV', process.env, ENV, 'hjkkkk')
const BASIC_HOST_MAP: MapInterface = { const BASIC_HOST_MAP: MapInterface = {
dev: 'https://dev-heimdall.xiaomai5.com/', dev: 'https://dev-heimdall.xiaomai5.com/',
dev1: 'https://dev1-heimdall.xiaomai5.com/', dev1: 'https://dev-heimdall.xiaomai5.com/',
rc: 'https://rc-heimdall.xiaomai5.com/', rc: 'https://rc-heimdall.xiaomai5.com/',
gray: 'https://gray-heimdall.xiaomai5.com/', gray: 'https://gray-heimdall.xiaomai5.com/',
prod: 'https://gateway.xiaomai5.com/', prod: 'https://gateway.xiaomai5.com/',
} }
const PATH_MAP: MapInterface = { const PATH_MAP: MapInterface = {
dev: 'https://dev.xiaomai5.com/xiaomai-cloud-class-web/h5.html', 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', rc: 'https://rc.xiaomai5.com/xiaomai-cloud-class-web/h5.html',
gray: 'https://res.xiaomai0.com/xiaomai-cloud-class-web/gray/h5.html', gray: path + '/gray/h5.html',
prod: 'https://res.xiaomai0.com/xiaomai-cloud-class-web/h5.html', prod: path + '/h5.html',
} }
export const YZ_APPId = "yozoqvpO2Hvz8346"; export const YZ_APPId = "yozoqvpO2Hvz8346";
......
export const BRAND: any = process.env.BRAND;
const BrandNameMap: any = {
xiaomai: '小麦企学院',
syoo: '商有云课堂'
}
const BrandIconMap: any = {
xiaomai: 'https://image.xiaomaiketang.com/xm/bFkRBz7teA.png',
syoo: 'https://image.xiaomaiketang.com/xm/PfDseQHZtB.png'
}
const BrandLogoMap: any = {
xiaomai: 'https://image.xiaomaiketang.com/xm/6k8PPCmywG.png',
syoo: 'https://image.xiaomaiketang.com/xm/T7NRKwrfQE.png'
}
const BrandBannerMap: any = {
xiaomai: 'https://image.xiaomaiketang.com/xm/CDCcdAdaPs.png',
syoo: 'https://image.xiaomaiketang.com/xm/DzMHpX7GWF.png'
}
const PATH_MAP: any = {
xiaomai: 'https://res.xiaomai0.com/xiaomai-cloud-class-web',
syoo: 'https://study.syoo.cn/syoo-cloud-class-web',
}
const LIVE_SHARE_MAP: any = {
xiaomai: 'https://res.xiaomai0.com/store-live',
syoo: 'https://study.syoo.cn/syoo-store-live',
}
const CorpType_MAP: any = {
xiaomai: 'X_MAI',
syoo: 'S_YOU',
}
const XF_RWM_MAP: any = {
xiaomai: 'https://cdn.xiaomai5.com/qixueyuankehu.png',
syoo: 'https://image.xiaomaiketang.com/xm/Z2X2GTmKdj.png'
}
const LiveNameMap: any = {
xiaomai: '小麦直播',
syoo: '商有直播'
}
export const brandName: string = BrandNameMap[BRAND];
export const brandIcon: string = BrandIconMap[BRAND];
export const brandLogo: string = BrandLogoMap[BRAND];
export const brandBanner: string = BrandBannerMap[BRAND];
export const path: string = PATH_MAP[BRAND];
export const live: string = LIVE_SHARE_MAP[BRAND];
export const corpType: string = CorpType_MAP[BRAND];
export const xfrwm: string = XF_RWM_MAP[BRAND]
export const brandLiveName: string = LiveNameMap[BRAND]
window.brandName = BrandNameMap[BRAND];
...@@ -10,7 +10,7 @@ import { ...@@ -10,7 +10,7 @@ import {
fetchLecturerData, getCategoryTree, knowledgeMediaCoursePage, fetchUserData, exportStudentCourseData, exportPlayBackCourseData, fetchPlaybackList, createLiveCloudCourse, getLiveCloudCoursePage, fetchLecturerData, getCategoryTree, knowledgeMediaCoursePage, fetchUserData, exportStudentCourseData, exportPlayBackCourseData, fetchPlaybackList, createLiveCloudCourse, getLiveCloudCoursePage,
getLiveCloudCourseDetail, updateLiveCloudCourse, turnOnOrOffLiveCloudCourse, delLiveCloudCourse, changeVideoShelfState, createVideoSchedule, delVideoSchedule, getLiveCloudCourseDetail, updateLiveCloudCourse, turnOnOrOffLiveCloudCourse, delLiveCloudCourse, changeVideoShelfState, createVideoSchedule, delVideoSchedule,
editVideoSchedule, userWatchInfo, videoSchedulePage, videoScheduleDetail, videoWatchInfo, getQrcode, getLiveCloudCourseBasePage, videoScheduleBasePage, relatedCourseToPlan, editVideoSchedule, userWatchInfo, videoSchedulePage, videoScheduleDetail, videoWatchInfo, getQrcode, getLiveCloudCourseBasePage, videoScheduleBasePage, relatedCourseToPlan,
lineDetailWatchInfo lineDetailWatchInfo, createWorkWXLiveCourse, fetchWorkWXLecturerData, fetchWorkWXUserData, getWorkWXLiveCourseDetail, updateWorkWXLiveCourse, delWorkWXLiveCourse, exportWorkWXStudentCourseData
} from '@/data-source/course/request-api'; } from '@/data-source/course/request-api';
export default class courseService { export default class courseService {
...@@ -18,6 +18,10 @@ export default class courseService { ...@@ -18,6 +18,10 @@ export default class courseService {
static fetchLecturerData(params: any) { static fetchLecturerData(params: any) {
return fetchLecturerData(params); return fetchLecturerData(params);
} }
// 获取企微讲师上课数据
static fetchWorkWXLecturerData(params: any) {
return fetchWorkWXLecturerData(params);
}
// 生成二维码 // 生成二维码
static getQrcode(params: any) { static getQrcode(params: any) {
...@@ -28,17 +32,29 @@ export default class courseService { ...@@ -28,17 +32,29 @@ export default class courseService {
static fetchUserData(params: any) { static fetchUserData(params: any) {
return fetchUserData(params); return fetchUserData(params);
} }
// 获取企微学员上课数据
static fetchWorkWXUserData(params: any) {
return fetchWorkWXUserData(params);
}
static createLiveCloudCourse(params: any) { static createLiveCloudCourse(params: any) {
return createLiveCloudCourse(params); return createLiveCloudCourse(params);
} }
//创建企微直播课
static createWorkWXLiveCourse(params: any) {
return createWorkWXLiveCourse(params)
}
static getLiveCloudCoursePage(params: any) { static getLiveCloudCoursePage(params: any) {
return getLiveCloudCoursePage(params); return getLiveCloudCoursePage({...params,terminalTypeEnum:"B_WEB"});
} }
// 导出学生上课数据 // 导出学生上课数据
static exportStudentCourseData(params: any) { static exportStudentCourseData(params: any) {
return exportStudentCourseData(params); return exportStudentCourseData(params);
} }
// 导出企微学生上课数据
static exportWorkWXStudentCourseData(params: any) {
return exportWorkWXStudentCourseData(params);
}
// 导出回放数据 // 导出回放数据
static exportPlayBackCourseData(params: any) { static exportPlayBackCourseData(params: any) {
...@@ -53,15 +69,27 @@ export default class courseService { ...@@ -53,15 +69,27 @@ export default class courseService {
static getLiveCloudCourseDetail(params: any) { static getLiveCloudCourseDetail(params: any) {
return getLiveCloudCourseDetail(params); return getLiveCloudCourseDetail(params);
} }
//获取企微直播详情
static getWorkWXLiveCourseDetail(params: any) {
return getWorkWXLiveCourseDetail(params);
}
static updateLiveCloudCourse(params: any) { static updateLiveCloudCourse(params: any) {
return updateLiveCloudCourse(params); return updateLiveCloudCourse(params);
} }
//编辑企微直播
static updateWorkWXLiveCourse(params: any) {
return updateWorkWXLiveCourse(params);
}
static turnOnOrOffLiveCloudCourse(params: any) { static turnOnOrOffLiveCloudCourse(params: any) {
return turnOnOrOffLiveCloudCourse(params); return turnOnOrOffLiveCloudCourse(params);
} }
static delLiveCloudCourse(params: any) { static delLiveCloudCourse(params: any) {
return delLiveCloudCourse(params); return delLiveCloudCourse(params);
} }
//删除企微直播
static delWorkWXLiveCourse(params: any) {
return delWorkWXLiveCourse(params);
}
static changeVideoShelfState(params: any) { static changeVideoShelfState(params: any) {
return changeVideoShelfState(params); return changeVideoShelfState(params);
} }
......
...@@ -2,11 +2,12 @@ ...@@ -2,11 +2,12 @@
* @Author: 吴文洁 * @Author: 吴文洁
* @Date: 2020-08-20 09:21:40 * @Date: 2020-08-20 09:21:40
* @LastEditors: wufan * @LastEditors: wufan
* @LastEditTime: 2021-08-15 18:31:08 * @LastEditTime: 2021-09-03 10:28:17
* @Description: * @Description:
* @Copyright: 杭州杰竞科技有限公司 版权所有 * @Copyright: 杭州杰竞科技有限公司 版权所有
*/ */
import { MapInterface } from '@/domains/basic-domain/interface' import { MapInterface } from '@/domains/basic-domain/interface'
import { path, live } from '@/domains/brand/constants'
const ENV: string = process.env.DEPLOY_ENV || 'dev'; const ENV: string = process.env.DEPLOY_ENV || 'dev';
const appIdMap: MapInterface = { const appIdMap: MapInterface = {
...@@ -14,7 +15,7 @@ const appIdMap: MapInterface = { ...@@ -14,7 +15,7 @@ const appIdMap: MapInterface = {
dev1: 'wx3ea60e78ddfa277e', dev1: 'wx3ea60e78ddfa277e',
rc: 'wx5c5a1fb71ecab7bc', rc: 'wx5c5a1fb71ecab7bc',
gray: "wx3dda02036493ada6", // 小麦校讯通 gray: "wx3dda02036493ada6", // 小麦校讯通
prod: 'wx3dda02036493ada6' prod: 'wx3dda02036493ada6',
} }
const shareUrlMap: MapInterface = { const shareUrlMap: MapInterface = {
...@@ -22,15 +23,15 @@ const shareUrlMap: MapInterface = { ...@@ -22,15 +23,15 @@ const shareUrlMap: MapInterface = {
'dev1': 'https://dev.xiaomai5.com/share/show?appid=', 'dev1': 'https://dev.xiaomai5.com/share/show?appid=',
'rc': 'https://rc.xiaomai5.com/share/show?appid=', 'rc': 'https://rc.xiaomai5.com/share/show?appid=',
'prod': 'https://prod.xiaomai5.com/share/show?appid=', 'prod': 'https://prod.xiaomai5.com/share/show?appid=',
'gray': 'https://prod.xiaomai5.com/share/show?appid=' 'gray': 'https://prod.xiaomai5.com/share/show?appid=',
} }
const LIVE_SHARE_MAP: MapInterface = { const LIVE_SHARE_MAP: MapInterface = {
dev: 'https://dev.xiaomai5.com/store-live/index.html#/', 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#/', rc: 'https://rc.xiaomai5.com/store-live/index.html#/',
gray: 'https://res.xiaomai0.com/store-live/gray/index.html#/', gray: live+'/gray/index.html#/',
prod: 'https://res.xiaomai0.com/store-live/index.html#/', prod: live+'/index.html#/',
} }
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
import { getEmployeeList, getUserList, getStoreDecorationList, getStoreRole, addEmployee, editEmployee, deleteEmployee, getCourseCatalogList, import { getEmployeeList, getUserList, getStoreDecorationList, getStoreRole, addEmployee, editEmployee, deleteEmployee, getCourseCatalogList,
getAllSonCategory, addCourseCategory, delCourseCategory, editCourseCategory, deleteStoreDecorationList, addStoreBanner, editStoreBanner, getAllSonCategory, addCourseCategory, delCourseCategory, editCourseCategory, deleteStoreDecorationList, addStoreBanner, editStoreBanner,
moveBannerSequence,getStoreUserBasicPage,updateStoreMessage,getStoreDetail,getByDepartmentId,getDepartmentUser,getDepartmentUserNotPage,addDepartment, moveBannerSequence,getStoreUserBasicPage,updateStoreMessage,getStoreDetail,getByDepartmentId,getDepartmentUser,getDepartmentUserNotPage,addDepartment,
editDepartment,delDepartment,queryDepartmentTree,getStoreCustomerAndDepNamePage,delDepartmentUser,syncWorkWeChatDepartment,getSyncCount editDepartment,delDepartment,queryDepartmentTree,getStoreCustomerAndDepNamePage,delDepartmentUser,syncWorkWeChatDepartment,getSyncCount,getCustomerAuditList,auditOperation,getCustomerAuditListCount
} from '@/data-source/store/request-apis'; } from '@/data-source/store/request-apis';
export default class StoreService { export default class StoreService {
...@@ -91,6 +91,20 @@ export default class StoreService { ...@@ -91,6 +91,20 @@ export default class StoreService {
static getStoreDetail(params: any) { static getStoreDetail(params: any) {
return getStoreDetail(params); return getStoreDetail(params);
} }
// 获取微信学员审核列表
static getCustomerAuditList(params: any){
return getCustomerAuditList(params)
}
// 获取微信学员审核列表数量
static getCustomerAuditListCount(params: any){
return getCustomerAuditListCount(params)
}
//微信学员审核操作
static auditOperation(params: any){
return auditOperation(params)
}
static getByDepartmentId(params:any){ static getByDepartmentId(params:any){
return getByDepartmentId(params); return getByDepartmentId(params);
} }
......
/*
* @Author: wufan
* @Date: 2021-09-03 10:23:20
* @LastEditors: wufan
* @LastEditTime: 2021-09-03 10:24:30
* @Description: Description
* @@Copyrigh: © 2021 杭州杰竞科技有限公司 版权所有
*/
declare module 'jquery' declare module 'jquery'
declare module 'cropper' declare module 'cropper'
declare module 'ExamShareModal' declare module 'ExamShareModal'
declare module 'college' declare module 'college'
declare module '@/common/lottie/college' declare module '@/common/lottie/college'
declare module 'routeHooks'
// declare var this: any // declare var this: any
\ No newline at end of file
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: 吴文洁 * @Author: 吴文洁
* @Date: 2020-08-24 12:20:57 * @Date: 2020-08-24 12:20:57
* @LastEditors: wufan * @LastEditors: wufan
* @LastEditTime: 2021-08-15 19:12:55 * @LastEditTime: 2021-09-03 10:26:25
* @Description: * @Description:
* @Copyright: 杭州杰竞科技有限公司 版权所有 * @Copyright: 杭州杰竞科技有限公司 版权所有
--> -->
...@@ -19,17 +19,18 @@ ...@@ -19,17 +19,18 @@
/> />
<meta <meta
name="keywords" name="keywords"
content="小麦企学院,企业培训,员工培训,企业大学,企业内训,企业外训,培训计划,培训素材,企培,企训,素材库,培训课程,培训任务,直播课,线上课,图文课,线下活动,知识库,作业,考试,排行榜,培训类别管理,定制培训计划,管理数据,学习数据,企学院,资料共享,培训数字化,数字化培训,培训工具,在线培训,线上培训,培训saas,培训管理,企业微信培训,对客培训,客户培训,直播培训,互联网培训,新员工培训,管理培训,管理者培训,工人培训,制造业培训,餐饮培训,服务业培训,零售培训,门店培训,工厂培训,车间培训,培训补贴,人事培训,财务培训,职场培训,企业学院平台,教育企业学院,教育企业平台,教育平台学院,企业学习,酷学院,小鹅通,企业学院,云学堂,时代光华,云课堂,魔学院,云大学,米知云,授课学堂" content="小麦企学院,企业培训,员工培训,企业大学,企业内训,企业外训,培训计划,培训素材,企培,企训,资料云盘,培训课程,培训任务,直播课,线上课,图文课,线下课,知识库,作业,考试,排行榜,培训类别管理,定制培训计划,管理数据,学习数据,企学院,资料共享,培训数字化,数字化培训,培训工具,在线培训,线上培训,培训saas,培训管理,企业微信培训,对客培训,客户培训,直播培训,互联网培训,新员工培训,管理培训,管理者培训,工人培训,制造业培训,餐饮培训,服务业培训,零售培训,门店培训,工厂培训,车间培训,培训补贴,人事培训,财务培训,职场培训,企业学院平台,教育企业学院,教育企业平台,教育平台学院,企业学习,酷学院,小鹅通,企业学院,云学堂,时代光华,云课堂,魔学院,云大学,米知云,授课学堂"
/> />
<!-- <link rel="apple-touch-icon" href="../src/common/images/logo.png" /> --> <!-- <link rel="apple-touch-icon" href="../src/common/images/logo.png" /> -->
<link rel="shortcut icon" href="https://image.xiaomaiketang.com/xm/c4KiP2epBP.png" /> <!-- <link rel="shortcut icon" href="https://image.xiaomaiketang.com/xm/c4KiP2epBP.png" /> -->
<!-- <link rel="shortcut icon" href="https://image.xiaomaiketang.com/xm/WGWCtxiGzE.png"> -->
<!-- <!--
manifest.json provides metadata used when your web app is installed on a 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/ 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="manifest" href="%PUBLIC_URL%/manifest.json" />
<link rel="stylesheet" href="//at.alicdn.com/t/font_2223403_0b87tvtysw45.css" /> <link rel="stylesheet" href="//at.alicdn.com/t/font_2223403_7261tsts1dc.css" />
<!-- <!--
Notice the use of %PUBLIC_URL% in the tags above. Notice the use of %PUBLIC_URL% in the tags above.
...@@ -40,17 +41,25 @@ ...@@ -40,17 +41,25 @@
work correctly both with client-side routing and a non-root public URL. work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`. Learn how to configure a non-root public URL by running `npm run build`.
--> -->
<title>小麦企学院</title> <script src="https://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
<script src="https://open.work.weixin.qq.com/wwopen/js/jwxwork-1.0.0.js"></script>
<script type="text/javascript" src="https://image.xiaomaiketang.com/xm/iscroll-zoom-min.js"></script> <script type="text/javascript" src="https://image.xiaomaiketang.com/xm/iscroll-zoom-min.js"></script>
<script type="text/javascript" src="https://image.xiaomaiketang.com/xm/hammer.min.js"></script> <script type="text/javascript" src="https://image.xiaomaiketang.com/xm/hammer.min.js"></script>
<script type="text/javascript" src="https://image.xiaomaiketang.com/xm/lrz.all.bundle.js"></script> <script type="text/javascript" src="https://image.xiaomaiketang.com/xm/lrz.all.bundle.js"></script>
<script type="text/javascript" src="https://image.xiaomaiketang.com/xm/PhotoClip.js"></script> <script type="text/javascript" src="https://image.xiaomaiketang.com/xm/PhotoClip.js"></script>
<script type="text/javascript" charset="utf-8" src="//g.alicdn.com/sd/ncpc/nc.js?t=2015052012"></script> <script type="text/javascript" charset="utf-8" src="//g.alicdn.com/sd/ncpc/nc.js?t=2015052012"></script>
<script type="text/javascript" src="https://xiaomai-js.oss-cn-hangzhou.aliyuncs.com/loghub-xm-0.0.1-beta.js"></script> <script type="text/javascript" src="https://xiaomai-js.oss-cn-hangzhou.aliyuncs.com/loghub-xm-0.0.1-beta.js"></script>
<script type="text/javascript" src="//res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
<script type="text/javascript" src="//open.work.weixin.qq.com/wwopen/js/jwxwork-1.0.0.js"></script>
</head> </head>
<body> <body>
<script>
setTimeout(()=>{
if(!wx.agentConfig){
window.location.reload()
}
},100)
</script>
<noscript>You need to enable JavaScript to run this app.</noscript> <noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div> <div id="root"></div>
......
...@@ -23,15 +23,33 @@ import '@/core/xmTD'; ...@@ -23,15 +23,33 @@ import '@/core/xmTD';
import User from '@/common/js/user'; import User from '@/common/js/user';
import Service from "@/common/js/service"; import Service from "@/common/js/service";
import BaseService from '@/domains/basic-domain/baseService'; import BaseService from '@/domains/basic-domain/baseService';
import routeHook from '@/core/routeHook'
import {brandName,BRAND,brandIcon} from '@/domains/brand/constants'
declare var getParameterByName: any; declare var getParameterByName: any;
declare var window: any; declare var window: any;
window.currentStoreUserInfo = {} window.currentStoreUserInfo = {}
const history = createHashHistory(); const history = createHashHistory();
document.title=brandName;
var iconUrl =brandIcon;
var linkzh = document.createElement('link');
linkzh.setAttribute('rel',"shortcut icon");
linkzh.setAttribute('href',iconUrl);
document.head.appendChild(linkzh);
window.RCHistory = _.extend({}, history, { window.RCHistory = _.extend({}, history, {
push: (obj: any) => { push: (obj: any) => {
console.log(routeHook.getCallbackNum(), 'routeHook.getCallbackNum()')
if (routeHook.getCallbackNum()) {
routeHook.break();
routeHook.addJump(() => {
history.push(obj)
})
} else {
history.push(obj) history.push(obj)
}
}, },
pushState: (obj: any) => { pushState: (obj: any) => {
history.push(obj) history.push(obj)
...@@ -39,13 +57,22 @@ window.RCHistory = _.extend({}, history, { ...@@ -39,13 +57,22 @@ window.RCHistory = _.extend({}, history, {
pushStateWithStatus: (obj: any) => { pushStateWithStatus: (obj: any) => {
history.push(obj) history.push(obj)
}, },
goBack: history.goBack, goBack: () => {
console.log(routeHook.getCallbackNum(), 'routeHook.getCallbackNum()')
history.goBack()
},
location: history.location, location: history.location,
replace: (obj: any) => { replace: (obj: any) => {
history.replace(obj) history.replace(obj)
} }
}); });
window.onhashchange = () => {
console.log(132121)
routeHook.cancel()
}
function mount() { function mount() {
ReactDOM.render( ReactDOM.render(
<RootRouter />, <RootRouter />,
...@@ -73,19 +100,19 @@ if (getParameterByName('code') && isWeiXin()) { ...@@ -73,19 +100,19 @@ if (getParameterByName('code') && isWeiXin()) {
window.currentStoreUserInfo.enterpriseId = res.result.enterpriseId; window.currentStoreUserInfo.enterpriseId = res.result.enterpriseId;
mount() mount()
}) })
} else if(getParameterByName('from') === 'customer' && getParameterByName('enterpriseId') && getParameterByName('userId')){ } else if (getParameterByName('from') === 'customer' && getParameterByName('enterpriseId') && getParameterByName('userId')) {
User.setCustomerStoreId(getParameterByName('storeId')); User.setCustomerStoreId(getParameterByName('storeId'));
getWXWorkLoginNoCheck(getParameterByName('enterpriseId'),getParameterByName('userId')); //从C端跳转过来的学院自动执行免登录 getWXWorkLoginNoCheck(getParameterByName('enterpriseId'), getParameterByName('userId')); //从C端跳转过来的学院自动执行免登录
}else{ } else {
mount() mount()
} }
function getWXWorkLoginNoCheck(enterpriseId:string,userId:string) { function getWXWorkLoginNoCheck(enterpriseId: string, userId: string) {
const params = { const params = {
appTermEnum: 'XIAOMAI_CLOUD_CLASS_PC_WEB_ADMIN', appTermEnum: 'XIAOMAI_CLOUD_CLASS_PC_WEB_ADMIN',
enterpriseId, enterpriseId,
userId, userId,
}; };
BaseService.getWXWorkLoginNoCheck(params).then((res:any) => { BaseService.getWXWorkLoginNoCheck(params).then((res: any) => {
User.setUserId(res.result.loginInfo.userId) User.setUserId(res.result.loginInfo.userId)
User.setToken(res.result.loginInfo.xmToken) User.setToken(res.result.loginInfo.xmToken)
User.setEnterpriseId(res.result.enterpriseId) User.setEnterpriseId(res.result.enterpriseId)
......
import React from 'react'; import React from 'react';
import { withRouter } from "react-router-dom"; import { withRouter } from 'react-router-dom';
import { Form, Input, Button, Modal, message} from 'antd'; import { Form, Input, Button, Modal,Switch, message, Tooltip } from 'antd';
import SelectPrepareFileModal from '@/modules/prepare-lesson/modal/SelectPrepareFileModal'; import SelectPrepareFileModal from '@/modules/prepare-lesson/modal/SelectPrepareFileModal';
import Upload from '@/core/upload'; import Upload from '@/core/upload';
import StoreService from "@/domains/store-domain/storeService"; import StoreService from '@/domains/store-domain/storeService';
import User from "@/common/js/user"; import User from '@/common/js/user';
import Bus from '@/core/tbus'; import Bus from '@/core/tbus';
import ImgClipModal from '@/components/ImgClipModal' import ImgClipModal from '@/components/ImgClipModal';
import "./CollegeInfoPage.less"; import './CollegeInfoPage.less';
let cutFlag = false;
class CollegeInfoPage extends React.Component { class CollegeInfoPage extends React.Component {
formRef = React.createRef(); formRef = React.createRef();
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
storeName:null, storeName: null,
logo:'', logo: '',
showSelectFileModal:false, showSelectFileModal: false,
cutImageBlob: null, cutImageBlob: null,
imageFile: null, // 需要被截取的图片 imageFile: null, // 需要被截取的图片
} auditSwitch:"OPEN",
videwMoal:false
};
} }
componentWillMount() { componentWillMount() {
if (User.getEnterpriseId()) { if (User.getEnterpriseId()) {
this.getStoreDetail() this.getStoreDetail();
} else { } else {
window.RCHistory.replace('/store-info') window.RCHistory.replace('/store-info');
} }
} }
getStoreDetail = ()=>{ getStoreDetail = () => {
const params= { const params = {
storeId:User.getStoreId() storeId: User.getStoreId(),
} };
StoreService.getStoreDetail(params).then((res) => { StoreService.getStoreDetail(params).then((res) => {
const { result = { } } = res; const { result = {} } = res;
const { const { storeName, logo,auditSwitch } = result;
storeName,
logo
} = result;
this.formRef.current.setFieldsValue({ this.formRef.current.setFieldsValue({
storeName:storeName storeName: storeName,
}); });
this.setState({ this.setState({
storeName, storeName,
logo auditSwitch,
}) logo,
}); });
} });
onChangeFiledValue=(filed,value)=>{ };
onChangeFiledValue = (filed, value) => {
console.log(filed, value)
this.setState({ this.setState({
[filed]:value [filed]: value,
}) });
} };
handleSelectCover = (file)=> {
handleSelectCover = (file) => {
this.setState({ this.setState({
visible: true, visible: true,
imageFile:file imageFile: file,
}); });
} };
//获取resourceId //获取resourceId
getSignature = (blob, fileName) => { getSignature = (blob, fileName) => {
Upload.uploadBlobToOSS(blob, 'cover' + (new Date()).valueOf(),null,'signInfo').then((signInfo) => { Upload.uploadBlobToOSS(blob, 'cover' + new Date().valueOf(), null, 'signInfo').then((signInfo) => {
this.setState({ this.setState(
coverClicpPath:signInfo.fileUrl, {
coverId:signInfo.resourceId, coverClicpPath: signInfo.fileUrl,
visible: false coverId: signInfo.resourceId,
},()=>this.updateCover()) visible: false,
},
() => this.updateCover()
);
}); });
}; };
updateCover = () =>{ updateCover = () => {
const {coverClicpPath,coverId} = this.state const { coverClicpPath, coverId } = this.state;
this.setState({ this.setState({
showSelectFileModal: false showSelectFileModal: false,
}) });
this.setState({ this.setState({
logo:coverClicpPath logo: coverClicpPath,
}) });
} };
updateInfo=()=>{ updateInfo = () => {
const { storeName, logo } = this.state; const { storeName, logo, auditSwitch
if(!storeName){ } = this.state;
if (!storeName) {
message.warning('请输入学院名称'); message.warning('请输入学院名称');
return; return;
} }
const params= { const params = {
storeName, storeName,
logo, logo,
storeId:User.getStoreId() storeId: User.getStoreId(),
} auditSwitch
};
StoreService.updateStoreMessage(params).then((res) => { StoreService.updateStoreMessage(params).then((res) => {
User.setStoreName(storeName); User.setStoreName(storeName);
Bus.trigger('storeNameChange',storeName); Bus.trigger('storeNameChange', storeName);
message.success('保存成功'); message.success('保存成功');
Bus.trigger("updateCollegeInfo") Bus.trigger('updateCollegeInfo');
}); });
};
renderModal (){
const {videwMoal} = this.state
return <Modal
visible={videwMoal}
title={'功能预览'}
width={680}
onCancel={()=>{this.setState({videwMoal:false})}}
maskClosable={false}
footer={null}
closeIcon={<span className="icon iconfont modal-close-icon">&#xe6ef;</span>}
>
<div className='college-info-page-view-modal-box'>
<img src='https://image.xiaomaiketang.com/xm/xRrsNKr8jn.gif' alt=''></img>
</div>
</Modal>
} }
render() { render() {
const { const { storeName, showSelectFileModal, visible, logo, imageFile,auditSwitch } = this.state;
storeName,
showSelectFileModal,
visible,
hasImgReady,
logo,
cutImageBlob,
imageFile
} = this.state;
return ( return (
<div className="page college-info-page"> <div className='page college-info-page'>
<div className="content-header">学院信息</div> <div className='content-header'>学院信息</div>
<div className="box"> <div className='box'>
<div className="college-info-page-form"> <div className='college-info-page-form'>
<Form ref={this.formRef}> <Form ref={this.formRef}>
<Form.Item <div className='title'>基本信息</div>
label="学院LOGO" <Form.Item label='学院LOGO'>
> <div className='logo-con'>
<div className="logo-con"> <div className='logo-img-con'>
<div className="logo-img-con"> <Choose>
{ logo ? <img src={logo} className="logo-img"/> : <div className="logo-box"><span className="text">Logo</span></div>} <When condition={logo}>
<img src={logo} className='logo-img' alt=''/>
</When>
<Otherwise>
<div className='logo-box'>
<span className='text'>Logo</span>
</div>
</Otherwise>
</Choose>
</div> </div>
<div className="upload-box"> <div className='upload-box'>
<span onClick={() => {this.setState({ showSelectFileModal:true })}} className="upload-btn"> <span
onClick={() => {
this.setState({ showSelectFileModal: true });
}}
className='upload-btn'>
<span>上传</span> <span>上传</span>
</span> </span>
<div className="tip">建议尺寸702*180px。最大2M,支持jpg、jpeg和png。</div> <div className='tip'>建议尺寸702*180px。最大2M,支持jpg、jpeg和png。</div>
</div> </div>
</div> </div>
</Form.Item> </Form.Item>
<Form.Item <Form.Item label='学院名称' name='storeName' rules={[{ required: true }]}>
label="学院名称"
name="storeName"
rules={[{ required: true}]}
>
<Input <Input
value={storeName} value={storeName}
style={{ width: '300px' }} style={{ width: '300px' }}
placeholder="请输入学院名称" placeholder='请输入学院名称'
onChange={(e) => this.onChangeFiledValue("storeName", e.target.value)} onChange={(e) => this.onChangeFiledValue('storeName', e.target.value)}
maxLength={30} maxLength={30}
/> />
</Form.Item> </Form.Item>
<div className='title mt40'>高级设置</div>
<Form.Item label={<span className='label-box'>学员审核
<Tooltip title='学院同时支持企微和微信用户加入学院学习。学员审核开启后,微信用户需要先提出申请,学院管理员审核通过后才能成为学院的学员,保证仅可信的微信用户才能加入学院。' placement='top' arrowPointAtCenter>
<span className='icon iconfont icon-tip'>&#xe61d;</span>
</Tooltip>
</span>}
name='storeName' >
<div className='switch-box'>
<Switch checked={auditSwitch ==='OPEN' } onChange={(e) => this.onChangeFiledValue('auditSwitch', e ?'OPEN':'CLOSE')}/>
<Choose>
<When condition={auditSwitch ==='OPEN'}>
<div className='switch-desc'>已开启,成为学院学员需要审核</div>
<div className='switch-prew-link' onClick={()=>this.setState({videwMoal:true})}>功能预览</div>
</When>
<Otherwise>
<div className='switch-desc'>已关闭,成为学院学员不需要审核</div>
</Otherwise>
</Choose>
</div>
</Form.Item>
</Form> </Form>
</div> </div>
{showSelectFileModal && {showSelectFileModal && (
<SelectPrepareFileModal <SelectPrepareFileModal
key="basic" key='basic'
operateType="select" operateType='select'
multiple={false} multiple={false}
accept="image/jpeg,image/png,image/jpg" accept='image/jpeg,image/png,image/jpg'
selectTypeList={['JPG', 'JPEG', 'PNG']} selectTypeList={['JPG', 'JPEG', 'PNG']}
tooltip='支持文件类型:jpg、jpeg、png' tooltip='支持文件类型:jpg、jpeg、png'
isOpen={showSelectFileModal} isOpen={showSelectFileModal}
onClose={() => { onClose={() => {
this.setState({ this.setState({
showSelectFileModal:false showSelectFileModal: false,
}) });
}} }}
onSelect={this.handleSelectCover} onSelect={this.handleSelectCover}
/> />
} )}
{ visible && {visible && (
<ImgClipModal visible={visible} imgUrl={imageFile.ossUrl} aspectRatio='125/32' cropBoxHeight='128' onConfirm={this.getSignature} onClose={()=>{this.setState({ visible: false });}}/> <ImgClipModal
} visible={visible}
<div><Button type="primary" onClick={this.updateInfo} htmlType="submit" className="submit-btn">更新信息</Button></div> imgUrl={imageFile.ossUrl}
aspectRatio='125/32'
cropBoxHeight='128'
onConfirm={this.getSignature}
onClose={() => {
this.setState({ visible: false });
}}
/>
)}
<div>
<Button type='primary' onClick={this.updateInfo} htmlType='submit' className='submit-btn'>
保存设置
</Button>
</div> </div>
</div> </div>
) {this.renderModal()}
</div>
);
} }
} }
......
...@@ -13,7 +13,14 @@ ...@@ -13,7 +13,14 @@
font-size:14px; font-size:14px;
} }
.college-info-page-form{ .college-info-page-form{
margin-left:29px; margin-left:20px;
.title{
font-size: 16px;
color: #333;
font-weight: 500;
margin-left: -20px;
margin-bottom: 20px;
}
.logo-con{ .logo-con{
.logo-img-con{ .logo-img-con{
width: 258px; width: 258px;
...@@ -58,10 +65,37 @@ ...@@ -58,10 +65,37 @@
} }
} }
} }
.switch-box{
display: flex;
align-items: center;
.switch-desc{
color: #999;
font-size: 14px;
margin: 0 8px;
}
.switch-prew-link{
color: #2966FF;
font-size: 14px;
}
}
} }
.submit-btn{ .submit-btn{
margin-left:142px; margin-left:132px;
margin-top: 20px;
}
.label-box{
// display: flex;
// align-content: center;
.icon{
color:#BFBFBF;
margin: 0 2px;
}
} }
} }
.college-info-page-view-modal-box{
img{
width: 100%;
}
}
\ No newline at end of file
...@@ -24,6 +24,6 @@ ...@@ -24,6 +24,6 @@
white-space: nowrap; white-space: nowrap;
} }
.edit-disable{ .edit-disable{
color:#666; color:#CCC !important;
} }
} }
\ No newline at end of file
...@@ -140,8 +140,9 @@ function EmployeeManage() { ...@@ -140,8 +140,9 @@ function EmployeeManage() {
function parseColumn() { function parseColumn() {
const columns = [ const columns = [
{ {
title: '员工', title: "员工",
dataIndex: 'weChatAccount', dataIndex: "weChatAccount",
fixed:'left',
render: (val: string, record: RecordTypes) => { render: (val: string, record: RecordTypes) => {
return ( return (
<div className='employee-info'> <div className='employee-info'>
...@@ -164,47 +165,35 @@ function EmployeeManage() { ...@@ -164,47 +165,35 @@ function EmployeeManage() {
}, },
}, },
{ {
title: '部门', title: "部门",
dataIndex: 'depNameList', dataIndex: "depNameList",
key: 'depNameList', key: "depNameList",
render: (val: string, record: RecordTypes) => { render: (val:string,record:RecordTypes) => {
if (!record.depNameList) { if(!record.depNameList){
return <span>-</span>; return <span>-</span>
} }
if (record.depNameList.length === 0) { if (record.depNameList.length === 0) {
return <span>-</span>; return <span>-</span>;
} }
// return record.depNameList.map((item,index)=>{ return <Tooltip title={<div>{handleDepName(record.depNameList)}</div>} placement='top' arrowPointAtCenter><div className="post-name"> {record.depNameList.map((item:any, index:any) => {
// return <span><WWOpenDataCom type="departmentName" openid={item}/>{index<(record.depNameList.length -1)?';':''}</span>; return <span><WWOpenDataCom type="departmentName" openid={item}/>{index<(record.depNameList.length -1)?';':''}</span>
// })
return (
<Tooltip title={<div>{handleDepName(record.depNameList)}</div>} placement='top' arrowPointAtCenter>
<div className='post-name'>
{' '}
{record.depNameList.map((item: any, index: any) => {
return (
<span>
<WWOpenDataCom type='departmentName' openid={item} />
{index < record.depNameList.length - 1 ? ';' : ''}
</span>
);
})} })}
</div> </div>
</Tooltip> </Tooltip>
);
}, },
}, },
{ {
title: '身份', title: "身份",
dataIndex: 'role', dataIndex: "role",
key: 'role', key: "role",
render: (val: string) => { render: (val: string) => {
return <div>{val.split(',').join('、')}</div>; return <div>{val.split(',').join('、')}</div>;
}, },
}, },
{ {
title: '操作', title: "操作",
dataIndex: 'operation', dataIndex: "operation",
fixed:'right',
render: (val: string, record: RecordTypes) => { render: (val: string, record: RecordTypes) => {
return record.role === '学院管理员' || record.userId === User.getUserId() ? ( return record.role === '学院管理员' || record.userId === User.getUserId() ? (
<div className='no-operate'>-</div> <div className='no-operate'>-</div>
...@@ -322,11 +311,13 @@ function EmployeeManage() { ...@@ -322,11 +311,13 @@ function EmployeeManage() {
num = res.result; num = res.result;
if (num < 3) { if (num < 3) {
return confirm({ return confirm({
title: '确定更新列表数据吗?', title: "确定更新列表数据吗?",
content: `员工数据来源企微通讯录,一天只能更新3次,今日还能更新${3 - num}次。`, content: <span>员工数据来源企微通讯录,一天只能更新3次,今日还能更新<span style={{color:'#2966FF'}}>{3-num}</span>次。</span>,
icon: <span className='icon iconfont default-confirm-icon'>&#xe839; </span>, icon: (
okText: '确定', <span className="icon iconfont default-confirm-icon">&#xe839; </span>
cancelText: '取消', ),
okText: "确定",
cancelText: "取消",
onOk: () => { onOk: () => {
confirmUpdateListData(); confirmUpdateListData();
}, },
...@@ -335,7 +326,7 @@ function EmployeeManage() { ...@@ -335,7 +326,7 @@ function EmployeeManage() {
Modal.warning({ Modal.warning({
title: '提示', title: '提示',
okText: '我知道了', okText: '我知道了',
content: '员工数据今日更新次数已达上限(3次),无法继续更新。', content: <span>员工数据今日更新次数已达上限<span style={{color:'#2966FF'}}>(3次)</span>,无法继续更新。</span>,
icon: ( icon: (
<span className='icon iconfont default-confirm-icon' style={{ color: '#FFBB54 !important' }}> <span className='icon iconfont default-confirm-icon' style={{ color: '#FFBB54 !important' }}>
&#xe834; &#xe834;
...@@ -440,6 +431,55 @@ function EmployeeManage() { ...@@ -440,6 +431,55 @@ function EmployeeManage() {
); );
})} })}
</div> </div>
{(User.getUserRole() === 'CloudManager' || User.getUserRole() === 'StoreManager') &&
<>
<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/docs/share/8c66333f-ed62-469d-909e-b36389a115ea?#"
target="_blank"
>
<span className="view-text">查看说明</span>
</a>
</>
}
</div>
<LimitTip type="员工" total={realTotal} tip={()=>{return (<div>数据为当前学院的员工数,若员工存在多个学院,企业人数只统计为1人</div>)}}/>
<div className="box-body">
<XMTable
renderEmpty={{
image: college,
description: '暂无数据'
}}
scroll={{ x: 1200 }}
size={"middle"}
pagination={false}
dataSource={employeeList}
columns={parseColumn()}
rowKey={(item: any) => item.id}
bordered
/>
</div>
<div className="box-footer">
<PageControl
current={query.current}
pageSize={query.size}
total={total}
toPage={(page: any) => {
const queryStates = _.clone(query);
queryStates.current = page;
setQuery(queryStates);
}}
/>
</div> </div>
{(User.getUserRole() === 'CloudManager' || User.getUserRole() === 'StoreManager') && ( {(User.getUserRole() === 'CloudManager' || User.getUserRole() === 'StoreManager') && (
<> <>
......
/* /*
* @Author: your name * @Author: your name
* @Date: 2021-08-04 15:21:36 * @Date: 2021-08-04 15:21:36
* @LastEditTime: 2021-08-04 15:23:37 * @LastEditTime: 2021-08-11 20:25:26
* @LastEditors: Please set LastEditors * @LastEditors: Please set LastEditors
* @Description: In User Settings Edit * @Description: In User Settings Edit
* @FilePath: /xiaomai-cloud-class-web/src/modules/college-manage/LimitTip.tsx * @FilePath: /xiaomai-cloud-class-web/src/modules/college-manage/LimitTip.tsx
...@@ -34,7 +34,7 @@ export default function LimitTip(props:{total:number,type:string,tip:() => React ...@@ -34,7 +34,7 @@ export default function LimitTip(props:{total:number,type:string,tip:() => React
{ {
isOver ? ( isOver ? (
<> <>
<div style={{marginLeft:"14px",display:"inline-block"}}>当前企业使用人数已达到上限 <span style={{color:"#333333",fontWeight:"bold"}}>{limitUser}</span>人,将无法添加新员工、新学员,如需增加人数限制,请联系小麦企学院服务平台。</div> <div style={{marginLeft:"14px",display:"inline-block"}}>当前企业使用人数已达到上限 <span style={{color:"#333333",fontWeight:"bold"}}>{limitUser}</span>人,将无法添加新员工、新学员,如需增加人数限制,请联系{window.brandName}服务平台。</div>
<ContactWidget trigger="hover" placement="bottom"> <ContactWidget trigger="hover" placement="bottom">
<div className="renew-text">立即续费<span className="icon iconfont" style={{fontSize:"10px"}}>&#59291;</span></div> <div className="renew-text">立即续费<span className="icon iconfont" style={{fontSize:"10px"}}>&#59291;</span></div>
</ContactWidget> </ContactWidget>
......
...@@ -2,35 +2,95 @@ ...@@ -2,35 +2,95 @@
* @Author: wufan * @Author: wufan
* @Date: 2020-11-30 10:47:38 * @Date: 2020-11-30 10:47:38
* @LastEditors: Please set LastEditors * @LastEditors: Please set LastEditors
* @LastEditTime: 2021-08-03 16:04:30 * @LastEditTime: 2021-08-11 20:31:26
* @Description: 学员管理页面 * @Description: 学员管理页面
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/ */
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { withRouter } from "react-router-dom"; import { Route,withRouter } from "react-router-dom";
import StoreService from "@/domains/store-domain/storeService";
import _ from "underscore"; import _ from "underscore";
import {Tabs,Input,Tree,Button} from "antd"; import User from "@/common/js/user";
import CustomGroupTabCon from './components/CustomGroupTabCon'; import {Tabs,Badge} from "antd";
import DepartMentTabCon from './components/DepartMentTabCon'; import DepartMentTabCon from './components/DepartMentTabCon';
import PostGroupTabCon from './components/PostGroupTabCon'; import WechatUserAudit from './WechatUserAudit/WechatUserAudit'
import "./NewUsersManagePage.less"; import "./NewUsersManagePage.less";
const { TabPane } = Tabs; const { TabPane } = Tabs;
function UserManagePage() { function UserManagePage(props) {
const { match } = props;
const [currentTab, setCurrentTab] = useState("departMentTab"); const [currentTab, setCurrentTab] = useState("departMentTab");
const [courseList,setCourseList] = useState([]); const [auditSwitch,setAuditSwitch] = useState('No')
const [total, setTotal] = useState(0); const [listCount, setListCount] = useState({
const [query, setQuery] = useState({ "allCnt": 0,
current: 0, "passedCnt": 0,
size: 10, "rejectedCnt": 0,
"waitCnt": 0
});
useEffect(()=>{
//列表获取
function handleFetchAuditListCount(_query) {
const params = {
storeId: User.getStoreId(),
};
StoreService.getCustomerAuditListCount(params).then((res) => {
const {
result,
} = res;
setListCount(result)
});
}
handleFetchAuditListCount();
},[])
function getStoreDetail(){
const params= {
storeId:User.getStoreId()
}
return StoreService.getStoreDetail(params).then((res) => {
const { result = { } } = res;
const {
auditSwitch
} = result;
setAuditSwitch(auditSwitch)
return auditSwitch
})
}
function jumpWechatAudit(){
getStoreDetail().then((res)=>{
if(res === 'OPEN'){
window.RCHistory.push({
pathname: `${match.url}/wechat-user-audit`,
}); });
}
})
}
useEffect(()=>{
getStoreDetail()
},[])
return ( return (
<div className="page new-user-manage-page"> <div className="page new-user-manage-page">
<div className="content-header">学员管理</div> <div className="content-header">
<div>学员管理</div>
<If condition={auditSwitch === 'OPEN'}>
<div className='wechat-audit' onClick={jumpWechatAudit} >
<div>
<span className='icon iconfont icon-font-weixin'>&#xe8e0;</span>
<span className='content-header-right'>学员审核列表</span>
</div>
<If condition={listCount.waitCnt!=='0'}>
<Badge status="error" text="" offset={[6,-6]} />
</If>
</div>
</If>
</div>
<div className="box"> <div className="box">
<div className="tab-box"> <div className="tab-box">
<Tabs <Tabs
...@@ -48,6 +108,12 @@ function UserManagePage() { ...@@ -48,6 +108,12 @@ function UserManagePage() {
<DepartMentTabCon currentTab={currentTab}/> <DepartMentTabCon currentTab={currentTab}/>
</div> </div>
</div> </div>
<Route
path={`${match.url}/wechat-user-audit`}
render={() => {
return <WechatUserAudit/>;
}}
/>
</div> </div>
); );
} }
......
.new-user-manage-page{
.ant-tabs-tab + .ant-tabs-tab{
margin:0;
}
.content-header{
display: flex;
justify-content: space-between;
.wechat-audit{
display: flex;
&:hover{
cursor: pointer;
}
}
.icon-font-weixin{
color: #5DD333;
margin-right:4px ;
}
.content-header-right{
font-size: 14px;
color: #2966FF;
}
}
}
\ No newline at end of file
.user-manage-page { .user-manage-page {
.content-header{
display: flex;
justify-content: space-between;
align-items: center;
.wechat-audit:hover{
cursor: pointer;
}
.icon-font-weixin{
color: #5DD333;
margin-right:4px ;
}
.content-header-right{
font-size: 14px;
color: #2966FF;
}
}
.box-header { .box-header {
display: flex; display: flex;
width: calc(100% - 80px); width: calc(100% - 80px);
......
/* /*
* @Author: wufan * @Author: wufan
* @Date: 2020-11-30 10:47:38 * @Date: 2020-11-30 10:47:38
* @LastEditors: wufan * @LastEditors: Please set LastEditors
* @LastEditTime: 2021-06-21 11:13:15 * @LastEditTime: 2021-08-13 16:52:16
* @Description: 学员管理页面 * @Description: 学员管理页面
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/ */
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { withRouter } from "react-router-dom"; import { Route, withRouter } from 'react-router-dom';
import _ from "underscore"; import _ from "underscore";
import { PageControl } from "@/components"; import { PageControl } from "@/components";
import { Input, DatePicker, Select, Button, message } from "antd"; import { Input, DatePicker, Select, Button, message } from "antd";
import StoreService from "@/domains/store-domain/storeService"; import StoreService from "@/domains/store-domain/storeService";
import User from "@/common/js/user"; import User from "@/common/js/user";
import ChooseMembersModal from "./modal/ChooseMembersModal"; import ChooseMembersModal from "./modal/ChooseMembersModal";
import WechatUserAudit from './WechatUserAudit/WechatUserAudit'
import LimitTip from "./LimitTip" import LimitTip from "./LimitTip"
import { XMTable } from '@/components'; import { XMTable } from '@/components';
...@@ -30,9 +31,11 @@ declare var window: any; ...@@ -30,9 +31,11 @@ declare var window: any;
function UserManagePage() { function UserManagePage(props:any) {
const { match } = props;
const [userList, setUserList] = useState([]); const [userList, setUserList] = useState([]);
const [model, setModel] = useState<React.ReactNode>(null); const [model, setModel] = useState<React.ReactNode>(null);
const [auditSwitch,setAuditSwitch] = useState('No')
const [query, setQuery] = useState({ const [query, setQuery] = useState({
current: 0, current: 0,
size: 10, size: 10,
...@@ -62,9 +65,24 @@ function UserManagePage() { ...@@ -62,9 +65,24 @@ function UserManagePage() {
StoreService.getUserList(_query).then((res: any) => { StoreService.getUserList(_query).then((res: any) => {
setRealTotal(res.result.total); setRealTotal(res.result.total);
}); });
const params= {
storeId:User.getStoreId()
}
StoreService.getStoreDetail(params).then((res) => {
const { result = { } } = res;
const {
auditSwitch
} = result;
setAuditSwitch(auditSwitch)
})
}, []) }, [])
useEffect(()=>{
},[])
useEffect(() => { useEffect(() => {
getUserList(); getUserList();
}, [query]); }, [query]);
...@@ -137,7 +155,21 @@ function UserManagePage() { ...@@ -137,7 +155,21 @@ function UserManagePage() {
return ( return (
<div className=" page user-manage-page"> <div className=" page user-manage-page">
<div className="content-header">学员管理</div> <div className="content-header">
<div>学员管理</div>
<If condition={auditSwitch === 'OPEN'}>
<div className='wechat-audit' onClick={()=>{
window.RCHistory.push({
pathname: `${match.url}/wechat-user-audit`,
});
}} >
<span className='icon iconfont icon-font-weixin'>&#xe8e0;</span>
<span className='content-header-right'>学员审核列表</span>
</div>
</If>
</div>
<div className="box"> <div className="box">
<div className="box-header"> <div className="box-header">
<div className="header-item"> <div className="header-item">
...@@ -243,6 +275,12 @@ function UserManagePage() { ...@@ -243,6 +275,12 @@ function UserManagePage() {
</div> </div>
</div> </div>
{model} {model}
<Route
path={`${match.url}/wechat-user-audit`}
render={() => {
return <WechatUserAudit/>;
}}
/>
</div> </div>
); );
} }
......
import React, { useState, useEffect } from 'react';
import Breadcrumbs from '@/components/Breadcrumbs';
import WechatUserAuditFilter from './WechatUserAuditFilter';
import WechatUserAuditOpt from './WechatUserAuditOpt'
import WechatUserAuditList from './WechatUserAuditList';
import StoreService from "@/domains/store-domain/storeService";
import User from '@/common/js/user';
import './WechatUserAudit.less';
const WechatUserAudit = function () {
const [listData, setListData] = useState([]);
const [totalCount, setTotalCount] = useState(0);
const [listCount, setListCount] = useState({
"allCnt": 0,
"passedCnt": 0,
"rejectedCnt": 0,
"waitCnt": 0
});
const [query, setQuery] = useState({
current: 1,
size: 10,
applyStatus: 'WAIT' //PASSED, WAIT, REJECTED
});
useEffect(() => {
//列表获取
function handleFetchAuditList(_query) {
const params = {
...query,
..._query,
storeId: User.getStoreId(),
};
StoreService.getCustomerAuditList(params).then((res) => {
const {
result: { records = [], total },
} = res;
setListData(records);
setTotalCount(total);
});
}
//列表获取
function handleFetchAuditListCount(_query) {
const params = {
storeId: User.getStoreId(),
};
StoreService.getCustomerAuditListCount(params).then((res) => {
const {
result,
} = res;
setListCount(result)
});
}
handleFetchAuditList();
handleFetchAuditListCount();
}, [query]);
//搜索条件改变
function queryChange(_query) {
if(_query.realName){
_query.nickName = _query.realName
}
const params = {
...query,
..._query,
};
console.log('params====>',params)
setQuery(params);
}
return (
<div className='page wechat-user-audit'>
<Breadcrumbs navList='学员审核列表' />
<div className='box'>
<WechatUserAuditFilter onChange={queryChange} />
<WechatUserAuditOpt onChange = {queryChange} listCount={listCount} defaultType={query.applyStatus}/>
<WechatUserAuditList listData={listData} query={query} totalCount={totalCount} onChange={queryChange} />
</div>
</div>
);
};
export default WechatUserAudit;
.wechat-user-audit{
}
\ No newline at end of file
/*
* @Author: 庞国铭
* @Description: 学员审核列表 筛选
*/
import React, { useState } from 'react';
import { Row, Input, Tooltip } from 'antd';
import RangePicker from '@/modules/common/DateRangePicker';
import moment from 'moment';
import './WechatUserAuditFilter.less';
const { Search } = Input;
const defaultQuery = {
realName: null,
startDate: null,
endDate: null,
nickName:null
};
const WechatUserAuditFilter = function (props) {
const { onChange = () => {} } = props;
const [query, setQuery] = useState(defaultQuery);
// 改变搜索条件
function handleChangeQuery(field, value) {
let _query = {
...query,
[field]: value,
current: 1,
};
setQuery(_query);
onChange(_query);
}
//日期选择
function handleChangeDates(dates) {
let _query = {
...query,
current: 1,
};
if (_.isEmpty(dates)) {
delete _query.startDate;
delete _query.endDate;
} else {
_query.startDate = dates[0]?.startOf('day').valueOf();
_query.endDate = dates[1]?.endOf('day').valueOf();
}
setQuery(_query);
onChange(_query);
}
//重置
function handleReset() {
setQuery({
...defaultQuery,
current: 1,
});
onChange({
...defaultQuery,
current: 1,
});
}
return (
<div className='wechat-user-audit-filter'>
<Row type='flex' justify='space-between' align='top'>
<div className='search-condition'>
<div className='search-condition__item'>
<span className='search-name'>搜索用户:</span>
<Search
value={query.realName}
placeholder='搜索用户'
onChange={(e) => {
handleChangeQuery('realName', e.target.value);
}}
onSearch={() => {
onChange(query.current);
}}
style={{ width: 'calc(100% - 81px)' }}
className='search-input'
enterButton={<span className='icon iconfont'>&#xe832;</span>}
/>
</div>
<div className='search-condition__item'>
<span className='search-date'>申请时间:</span>
<RangePicker
id='course_date_picker'
allowClear={false}
value={query.startDate ? [moment(query.startDate), moment(query.endDate)] : null}
format={'YYYY-MM-DD'}
onChange={(dates) => {
handleChangeDates(dates);
}}
style={{ width: 'calc(100% - 81px)' }}
/>
</div>
</div>
<div className='reset-fold-area'>
<Tooltip title='清空筛选'>
<span className='resetBtn iconfont icon' onClick={handleReset}>
&#xe61b;
</span>
</Tooltip>
</div>
</Row>
</div>
);
};
export default WechatUserAuditFilter;
.wechat-user-audit-filter{
position: relative;
.ant-input-search-button{
border-left:none;
}
.search-condition {
width: calc(100% - 80px);
display: flex;
align-items: center;
flex-wrap: wrap;
&__item {
width: 30%;
margin-right: 3%;
margin-bottom: 12px;
.search-name{
width: 81px;
vertical-align: middle;
display:inline-block;
height:32px;
line-height:32px;
}
}
}
.reset-fold-area {
position: absolute;
right: 12px;
}
.resetBtn {
color: #999999;
font-size: 18px;
margin-right: 8px;
}
.fold-btn {
font-size: 14px;
color: #666666;
line-height: 20px;
.fold-icon {
font-size: 12px;
margin-left:4px;
}
}
}
.data-icon {
cursor: pointer;
}
import React from 'react';
import { message, Badge } from 'antd';
import { PageControl, XMTable } from '@/components';
import WWOpenDataCom from '@/components/WWOpenDataCom';
import './WechatUserAuditList.less';
import StoreService from '@/domains/store-domain/storeService';
import User from '@/common/js/user';
function WechatUserAuditList(props) {
const { listData, totalCount, query, onChange = () => {} } = props;
function parseColumns() {
const columns = [
{
title: '微信名称',
key: 'nickName',
dataIndex: 'nickName',
width: '12%',
fixed: 'left',
render: (val, record) => {
return <div className='wechat-user-audit-name'>{val}</div>;
},
},
{
title: '真实姓名',
key: 'realName',
dataIndex: 'realName',
width: '12%',
render: (val) => {
return <div className='create-name'>{val}</div>;
},
},
{
title: '申请时间',
width: '12.5%',
key: 'applyDate',
dataIndex: 'applyDate',
render: (val) => {
return <span style={{ whiteSpace: 'nowrap' }}>{window.formatDate('YYYY-MM-DD H:i', val)}</span>;
},
},
{
title: '审批状态',
width: '10%',
key: 'applyStatus',
dataIndex: 'applyStatus',
render: (val) => {
return (
<div className='valid-state-icon'>
<Choose>
<When condition={val === 'PASSED'}>
<Badge color='#0ACCA4' text='已通过' />
</When>
<When condition={val === 'REJECTED'}>
<Badge color='#EC4B35' text='已拒绝' />
</When>
<Otherwise>
<Badge color='#FFB714' text='待审核' />
</Otherwise>
</Choose>
</div>
);
},
},
{
title: '审核人',
width: '10%',
key: 'reviewer',
dataIndex: 'reviewer',
render: (val) => {
return <div>
<WWOpenDataCom type="userName" openid={val} />
</div>;
},
},
{
title: '操作',
key: 'operate',
dataIndex: 'operate',
fixed: 'right',
width: '14.5%',
render: (val, record) => {
return (
<Choose>
<When condition={record.applyStatus === 'WAIT'}>
<div className='operate'>
<div className='operate__item' onClick={() => audit(record, true)}>
通过
</div>
<span className='operate__item split'> | </span>
<div className='operate__item' onClick={() => audit(record, false)}>
拒绝
</div>
</div>
</When>
<Otherwise>
<div className='operate'>
<div></div>
</div>
</Otherwise>
</Choose>
);
},
},
];
return columns;
}
function audit(record, isTrue) {
const { id } = record;
const params = {
applyCustomerId: id,
audit: isTrue,
operatorId: User.getStoreUserId(),
storeId: User.getStoreId(),
};
StoreService.auditOperation(params).then((res) => {
if (res.success) {
message.success('操作成功');
onChange(query)
}
}).catch(res=>{
if(res.code === 'THIS_OPERATION_INVALID'){
window.RCHistory.goBack();
}
if(res.code === 'AUDIT_HAS_OPERATION'){
onChange(query)
}
});
}
function onShowSizeChange(current, size) {
if (current === size) {
return;
}
let _query = query;
_query.size = size;
onChange(_query);
}
return (
<div className='wechat-user-audit-list'>
<XMTable
rowKey={(record) => record.id}
showSorterTooltip={false}
dataSource={listData}
columns={parseColumns()}
pagination={false}
bordered
size='middle'
scroll={{ x: 1400 }}
className='wechat-user-audit-list-table'
renderEmpty={{
description: <span style={{ display: 'block', paddingBottom: 24 }}>暂无数据</span>,
}}
/>
<div className='box-footer'>
<PageControl
current={query.current - 1}
pageSize={query.size}
total={totalCount}
toPage={(page) => {
const _query = { ...query, current: page + 1 };
onChange(_query);
}}
onShowSizeChange={onShowSizeChange}
/>
</div>
</div>
);
}
export default WechatUserAuditList;
.wechat-user-audit-list {
margin-top: 12px;
.course-number {
margin-right: 45px;
}
.wechat-user-audit-list-table {
thead.ant-table-thead {
tr {
th {
padding: 10px 12px;
}
}
}
tbody {
tr {
td.ant-table-cell {
padding: 16px 12px;
color: #333;
}
&:nth-child(even) {
background: transparent;
td {
background: #fff;
}
}
&:nth-child(odd) {
background: #fafafa;
td {
background: #fafafa;
}
}
&:hover {
td {
background: #f3f6fa;
}
}
}
}
}
.operate-text {
color: #2966ff;
cursor: pointer;
}
.operate {
display: flex;
&__item {
color: #2966ff;
cursor: pointer;
&.split {
margin: 0 8px;
color: #bfbfbf;
}
}
}
.join-number {
text-align: right;
margin-right: 12px;
}
.more-operate {
line-height: 20px;
}
.valid-state-icon{
display: flex;
align-items: center;
.ant-badge{
transform: translate(0,0) scale(1) !important;
}
}
}
\ No newline at end of file
import React from 'react';
import { Row, Radio } from 'antd';
const WechatUserAuditOpt = function (props) {
const { onChange = () => {}, listCount = {}, defaultType = '' } = props;
const { allCnt = 0, passedCnt = 0, rejectedCnt = 0, waitCnt = 0 } = listCount;
return (
<div className='wechat-user-audit-filter'>
<Row type='flex' justify='end' align='top'>
<Radio.Group onChange={(e) => onChange({ applyStatus: e.target.value==='' ? null: e.target.value })} defaultValue={defaultType}>
<Radio.Button value=''>{`全部(${allCnt})`}</Radio.Button>
<Radio.Button value='WAIT'>{`待审核(${waitCnt})`}</Radio.Button>
<Radio.Button value='PASSED'>{`已通过(${passedCnt})`}</Radio.Button>
<Radio.Button value='REJECTED'>{`已拒绝(${rejectedCnt})`}</Radio.Button>
</Radio.Group>
</Row>
</div>
);
};
export default WechatUserAuditOpt;
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);
...@@ -8,6 +8,7 @@ import college from "@/common/lottie/college.json"; ...@@ -8,6 +8,7 @@ import college from "@/common/lottie/college.json";
import WWOpenDataCom from '@/components/WWOpenDataCom'; import WWOpenDataCom from '@/components/WWOpenDataCom';
import StoreService from "@/domains/store-domain/storeService"; import StoreService from "@/domains/store-domain/storeService";
import { DepType } from "@/domains/store-domain/constants"; import { DepType } from "@/domains/store-domain/constants";
import Platform from '@/common/js/platform';
import User from "@/common/js/user"; import User from "@/common/js/user";
import moment from "moment"; import moment from "moment";
import "./DepartMentTabCon.less"; import "./DepartMentTabCon.less";
...@@ -31,12 +32,13 @@ function DepartMentTabCon(props) { ...@@ -31,12 +32,13 @@ function DepartMentTabCon(props) {
useEffect(()=>{ useEffect(()=>{
setSelectUser([]); setSelectUser([]);
},[selectDep]); },[selectDep]);
const columns = [ const columns = [
{ {
title: "学员", title: "学员",
dataIndex: "nickName", dataIndex: "nickName",
width: 220, width: 220,
fixed: 'left', fixed:!Platform.isWorkWx(),
render: (val, item) => { render: (val, item) => {
return ( return (
<div> <div>
...@@ -60,9 +62,8 @@ function DepartMentTabCon(props) { ...@@ -60,9 +62,8 @@ function DepartMentTabCon(props) {
{ {
title: "真实姓名", title: "真实姓名",
dataIndex: "realName", dataIndex: "realName",
width: "15%",
render: (val, record) => { render: (val, record) => {
return <span>{val}</span>; return <span>{val}</span>
}, },
}, },
{ {
...@@ -117,16 +118,19 @@ function DepartMentTabCon(props) { ...@@ -117,16 +118,19 @@ function DepartMentTabCon(props) {
title: "操作", title: "操作",
key: "operate", key: "operate",
dataIndex: "operate", dataIndex: "operate",
width: "15%", width: 60,
fixed: 'right', fixed: 'right',
render: (val, item) => { render: (val, item) => {
return ( return (
<div className="operate"> <div className="operate">
{props.currentTab==='departMentTab'? {props.currentTab==='departMentTab'?
<span>-</span> <div className="operate__item" onClick={()=>delUser('single',item.userId)}>删除</div>
// <div className="operate__item" onClick={()=>delUser('single',item.userId)}>删除</div>
: :
(selectDep.depLevel > 0 ?
<div className="operate__item" onClick={()=>delUser('single',item.userId)}>移出</div> <div className="operate__item" onClick={()=>delUser('single',item.userId)}>移出</div>
:
<span>-</span>
)
} }
</div> </div>
); );
...@@ -200,7 +204,7 @@ function DepartMentTabCon(props) { ...@@ -200,7 +204,7 @@ function DepartMentTabCon(props) {
idList = _.pluck(selectUser,'userId'); idList = _.pluck(selectUser,'userId');
} }
if(idList.length===0){ if(idList.length===0){
message.warning('请先选择要删除的学员') message.warning('请先选择要移出的学员')
return; return;
} }
switch (props.currentTab){ switch (props.currentTab){
...@@ -290,7 +294,7 @@ function DepartMentTabCon(props) { ...@@ -290,7 +294,7 @@ function DepartMentTabCon(props) {
if(num<3){ if(num<3){
return confirm({ return confirm({
title: "确定更新列表数据吗?", title: "确定更新列表数据吗?",
content: `学员数据来源企微通讯录,一天只能更新3次,今日还能更新${3-num}次。`, content: <span>学员数据来源企微通讯录,一天只能更新3次,今日还能更新<span style={{color:'#2966FF'}}>{3-num}</span>次。</span>,
icon: ( icon: (
<span className="icon iconfont default-confirm-icon">&#xe839; </span> <span className="icon iconfont default-confirm-icon">&#xe839; </span>
), ),
...@@ -304,7 +308,7 @@ function DepartMentTabCon(props) { ...@@ -304,7 +308,7 @@ function DepartMentTabCon(props) {
Modal.warning({ Modal.warning({
title: '提示', title: '提示',
okText: '我知道了', okText: '我知道了',
content: '学员数据今日更新次数已达上限(3次),无法继续更新。', content: <span>学员数据今日更新次数已达上限<span style={{color:'#2966FF'}}>(3次)</span>,无法继续更新。</span>,
icon: ( icon: (
<span className='icon iconfont default-confirm-icon' style={{ color: '#FFBB54 !important' }}> <span className='icon iconfont default-confirm-icon' style={{ color: '#FFBB54 !important' }}>
&#xe834; &#xe834;
...@@ -347,20 +351,24 @@ function DepartMentTabCon(props) { ...@@ -347,20 +351,24 @@ function DepartMentTabCon(props) {
添加学员 添加学员
</Button> </Button>
} }
{(props.currentTab === "postGrouptab" || props.currentTab === "customGroupTab") &&
<Button className="del-user-btn" onClick={()=>delUser('multiple')}>删除学员</Button> <Button className="del-user-btn" onClick={()=>delUser('multiple')}>删除学员</Button>
}
{ selectDep.depId !== '10000' && { selectDep.depId !== '10000' ?
<> <>
<Button className="update-user-btn" onClick={()=>{updateListData()}}>更新列表数据</Button> <Button className="update-user-btn" onClick={()=>{updateListData()}}>更新列表数据</Button>
<span className="origin-text">数据来源企业微信通讯录</span> <div style={{marginTop:'12px'}}>
<span className="origin-text">系统实时同步企业微信可见范围的学员信息,如需修改请前往企微管理后台通讯录中操作</span>
<a <a
href="https://www.yuque.com/wangzhong-zkqw0/qixue" href="https://www.yuque.com/docs/share/8c66333f-ed62-469d-909e-b36389a115ea?#"
target="_blank" target="_blank"
> >
<span className="view-text">查看数据更新说明</span> <span className="view-text">查看说明</span>
</a> </a>
</div>
</> </>
:
<span className="origin-text">微信学员通过授权或扫码登录后,数据自动同步到系统。</span>
} }
</div> </div>
)} )}
...@@ -379,7 +387,9 @@ function DepartMentTabCon(props) { ...@@ -379,7 +387,9 @@ function DepartMentTabCon(props) {
添加学员 添加学员
</Button> </Button>
} }
{selectDep.depLevel > 0 &&
<Button className="del-user-btn" onClick={()=>delUser('multiple')}>移出学员</Button> <Button className="del-user-btn" onClick={()=>delUser('multiple')}>移出学员</Button>
}
</div> </div>
)} )}
<div className="user-table"> <div className="user-table">
...@@ -388,7 +398,7 @@ function DepartMentTabCon(props) { ...@@ -388,7 +398,7 @@ function DepartMentTabCon(props) {
image: college, image: college,
description: "暂无数据", description: "暂无数据",
}} }}
scroll={{ x: 800 }} scroll={{ x: 1200 }}
bordered bordered
size="middle" size="middle"
pagination={false} pagination={false}
...@@ -418,6 +428,7 @@ function DepartMentTabCon(props) { ...@@ -418,6 +428,7 @@ function DepartMentTabCon(props) {
}, },
}} }}
/> />
{total > 0 &&
<div className="box-footer"> <div className="box-footer">
<PageControl <PageControl
current={query.current - 1} current={query.current - 1}
...@@ -431,6 +442,7 @@ function DepartMentTabCon(props) { ...@@ -431,6 +442,7 @@ function DepartMentTabCon(props) {
}} }}
/> />
</div> </div>
}
</div> </div>
</div> </div>
{chooseMembersModalVisible && ( {chooseMembersModalVisible && (
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
display: flex; display: flex;
.table-con{ .table-con{
flex:1; flex:1;
max-width: calc(100% - 290px);
.post-name{ .post-name{
max-width: 200px; max-width: 200px;
overflow: hidden; overflow: hidden;
......
import React, { useEffect, useState } from "react"; import React, { useEffect, useState, useRef } from "react";
import { withRouter } from "react-router-dom"; import { withRouter } from "react-router-dom";
import { Tree, Input, Dropdown, Menu,Button,Modal,message,AutoComplete} from "antd"; import { Tree, Input, Dropdown, Menu, Button, Modal, message, AutoComplete, Tooltip } from "antd";
import AddOrEditPostGroupModal from "../modal/AddOrEditPostGroupModal"; import AddOrEditPostGroupModal from "../modal/AddOrEditPostGroupModal";
import User from '@/common/js/user' import User from '@/common/js/user'
import StoreService from "@/domains/store-domain/storeService"; import StoreService from "@/domains/store-domain/storeService";
...@@ -13,71 +13,95 @@ const { Search } = Input; ...@@ -13,71 +13,95 @@ const { Search } = Input;
const { DirectoryTree } = Tree; const { DirectoryTree } = Tree;
const { Option } = AutoComplete; const { Option } = AutoComplete;
function LeftStructureTree(props) { function LeftStructureTree(props) {
const {treeType} = props; const { treeType } = props;
const [treeData,setTreeData]=useState([]); const [treeData, setTreeData] = useState([]);
const [addOrEditPostGroupShow, setAddOrEditPostGroupShow] = useState(false); const [addOrEditPostGroupShow, setAddOrEditPostGroupShow] = useState(false);
const [postGroupModalLevel, setPostGroupModalLevel] = useState(""); const [postGroupModalLevel, setPostGroupModalLevel] = useState("");
const [operatePostGroupModalType,setOperatePostGroupModalType] = useState(""); const [operatePostGroupModalType, setOperatePostGroupModalType] = useState("");
const [postGroupModalTitle,setPostGroupModalTitle] = useState(""); const [postGroupModalTitle, setPostGroupModalTitle] = useState("");
const [postGroupModalLable,setPostGroupModalLable] = useState(""); const [postGroupModalLable, setPostGroupModalLable] = useState("");
const [postGroupName, setPostGroupName] = useState(""); const [postGroupName, setPostGroupName] = useState("");
const [currentGroupData,setCurrentGroupData] = useState({}); const [currentGroupData, setCurrentGroupData] = useState({});
const [completeOptions,setCompleteOption] = useState([]); const [completeOptions, setCompleteOption] = useState([]);
const [selectedKeys,setSelectedKeys]= useState([]); // 设置选中的部门key值 const [selectedKeys, setSelectedKeys] = useState([]); // 设置选中的部门key值
const [queryName,setQueryName] = useState(''); // 搜索框内的值 const [queryName, setQueryName] = useState(''); // 搜索框内的值
const [selctQueryName,setSelctQueryName]= useState(''); // 搜索出结果后最终选择的名字 const [selctQueryName, setSelctQueryName] = useState(''); // 搜索出结果后最终选择的名字
const [postGroupTreeData,setPostGroupTreeData] = useState([]); // 为了判定创建和编辑时的数据会不会重明 const [postGroupTreeData, setPostGroupTreeData] = useState([]); // 为了判定创建和编辑时的数据会不会重明
const [open,setOpen]=useState(false); const [open, setOpen] = useState(false);
const timer = useRef(null)
useEffect(()=>{ const queryNameRef = useRef(null)
useEffect(() => {
queryNameRef.current = queryName
}, [
queryName
])
useEffect(() => {
setQueryName(''); //切换tab时搜索置空 setQueryName(''); //切换tab时搜索置空
setCompleteOption([]); setCompleteOption([]);
setOpen(false); //切换tab时搜索的下拉框置为空 setOpen(false); //切换tab时搜索的下拉框置为空
getTreeData().then((res)=>{ getTreeData().then((res) => {
const _defaultSelectedKeys = []; const _defaultSelectedKeys = [];
if(res.length > 0){ if (res.length > 0) {
_defaultSelectedKeys.push(res[0].id); _defaultSelectedKeys.push(res[0].id);
setSelectedKeys(_defaultSelectedKeys); setSelectedKeys(_defaultSelectedKeys);
props.onChangeSelectDep(res[0]) props.onChangeSelectDep(res[0])
props.searchUserList(res[0],treeType,1); props.searchUserList(res[0], treeType, 1);
}else{ } else {
props.searchUserList({id:null},treeType,1); props.searchUserList({ id: null }, treeType, 1);
} }
}); });
},[props.treeType]); }, [props.treeType]);
useEffect(()=>{ useEffect(() => {
Bus.bind("addCustomer",(record)=>{addCustomer(record.treeType,record.query)}) Bus.bind("addCustomer", (record) => { addCustomer(record.treeType, record.query) })
},[]); }, []);
useEffect(()=>{ useEffect(() => {
Bus.bind("changeTreeData",(record)=>{getTreeData(record.treeType)}) Bus.bind("changeTreeData", (record) => { getTreeData(record.treeType) })
},[]); }, []);
const renderTitle = (title) => ( const renderTitle = (title) => (
<span> <span className="catalog-title">
{title} {title}
</span> </span>
); );
const renderItem = (record,type) => ({ const renderItem = (record, type) => ({
value: record.userName || record.name, value: record.userName || record.name,
label: ( label: (
<div <div
className="search-result-item"
style={{ style={{
display: 'flex', display: 'flex',
justifyContent: 'space-between', justifyContent: 'space-between',
}} }}
depId={record.id} depId={record.id}
type={type} type={type}
> >
{type === 'user'? {type === 'user' ?
<div><WWOpenDataCom type="userName" openid={record.userName}/></div> <div className="search-result-item__left">
<span className="icon iconfont title-icon">&#xe603;</span>
<WWOpenDataCom type="userName" openid={record.userName} />
</div>
: :
<div><WWOpenDataCom type="departmentName" openid={record.name}/></div> <div className="search-result-item__left">
{props.treeType === 'departMentTab' ?
<WWOpenDataCom type="departmentName" openid={record.name} />
:
<span>{record.name}</span>
} }
{type === 'user' &&
record.postDepNamesList.map((item,index)=>{ </div>
return <span><WWOpenDataCom type="departmentName" openid={item}/></span>
})
} }
{type === 'user' && (
<div className="search-result-item__right">
<Tooltip title={<div>{handleDepName(record.depNamesList)}</div>} placement='top' arrowPointAtCenter>
{record.depNamesList.map((item, index) => {
return <span><WWOpenDataCom type="departmentName" openid={item} />{index < (record.depNamesList.length - 1) ? ';' : ''}</span>
})}
</Tooltip>
</div>
)}
{type === 'post' && {type === 'post' &&
<span type='post' openid={record.parentName}>{record.parentName}</span> <span type='post' openid={record.parentName}>{record.parentName}</span>
} }
...@@ -85,12 +109,21 @@ function LeftStructureTree(props) { ...@@ -85,12 +109,21 @@ function LeftStructureTree(props) {
), ),
}); });
const notFoundContentNode = ()=>{ const notFoundContentNode = () => {
return <span>暂无数据</span> return <div className="empty-con">
<img src="https://image.xiaomaiketang.com/xm/wRDrb2pJFb.png" className="empty-img" />
<div className="empty-text">暂无数据</div>
</div>
} }
function handlePlaceHolder(){ function handleDepName(depArray) {
const depArrayDom = depArray.map((item, index) => {
return <span><WWOpenDataCom type="departmentName" openid={item} /></span>
});
return depArrayDom;
};
function handlePlaceHolder() {
let placeholder = ''; let placeholder = '';
switch (props.treeType){ switch (props.treeType) {
case 'departMentTab': case 'departMentTab':
placeholder = '搜索学员姓名、部门'; placeholder = '搜索学员姓名、部门';
break; break;
...@@ -105,87 +138,89 @@ function LeftStructureTree(props) { ...@@ -105,87 +138,89 @@ function LeftStructureTree(props) {
} }
return placeholder return placeholder
} }
function confirmSearchSelect(value,option){ function confirmSearchSelect(value, option) {
const param = {} const param = {}
setOpen(false); setOpen(false);
setQueryName(value); setQueryName(value);
if(option.label.props.type === 'user'){ if (option.label.props.type === 'user') {
param.queryName = value; param.queryName = value;
}else{ } else {
param.id = option.label.props.depId; param.id = option.label.props.depId;
} }
props.searchUserList(param,treeType,1); props.searchUserList(param, treeType, 1);
} }
// 获取关键词的搜索结果 // 获取关键词的搜索结果
function getCompleteOptionData(value){ function getCompleteOptionData(value) {
// setQueryName(value); // setQueryName(value);
setCompleteOption([]); setCompleteOption([]);
console.log("treeType",props.treeType); if (!value) {
return
}
const params = { const params = {
depType:DepType[props.treeType], depType: DepType[props.treeType],
queryName:value, queryName: value,
enterpriseId:User.getEnterpriseId(), enterpriseId: User.getEnterpriseId(),
source:0,//0代表来自企培 source: 0,//0代表来自企培
storeId:User.getStoreId(), storeId: User.getStoreId(),
userId:User.getUserId(), userId: User.getUserId(),
whetherCount:false, whetherCount: false,
distinct:false, distinct: false,
queryType:'CUSTOMER' queryType: 'CUSTOMER'
} }
StoreService.getDepartmentUser(params).then((res) => { StoreService.getDepartmentUser(params).then((res) => {
const _completeOptions = []; const _completeOptions = [];
const userObj = {}; const userObj = {};
const departmentGroupObj = {}; const departmentGroupObj = {};
const postobj = {}; const postobj = {};
const { result = {}} = res; const { result = {} } = res;
const {departmentUserVOList=[],departmentVOList=[],subLevelDepartmentVOList=[]} = result; const { departmentUserVOList = [], departmentVOList = [], subLevelDepartmentVOList = [] } = result;
if(departmentUserVOList.length>0){ if (departmentUserVOList.length > 0) {
userObj.label=renderTitle('学员'); userObj.label = renderTitle('学员');
userObj.options=departmentUserVOList.map((item,index)=>{ userObj.options = departmentUserVOList.map((item, index) => {
return renderItem(item,'user'); return renderItem(item, 'user');
}) })
} }
if(departmentVOList.length>0){ if (departmentVOList.length > 0) {
switch (props.treeType){ switch (props.treeType) {
case 'departMentTab': case 'departMentTab':
departmentGroupObj.label=renderTitle('部门'); departmentGroupObj.label = renderTitle('部门');
break; break;
case 'postGrouptab': case 'postGrouptab':
departmentGroupObj.label=renderTitle('岗位组'); departmentGroupObj.label = renderTitle('岗位组');
break; break;
case 'customGroupTab': case 'customGroupTab':
departmentGroupObj.label=renderTitle('分组集合'); departmentGroupObj.label = renderTitle('分组集合');
break; break;
default: default:
break; break;
} }
departmentGroupObj.options=departmentVOList.map((item,index)=>{ departmentGroupObj.options = departmentVOList.map((item, index) => {
return renderItem(item,'group'); return renderItem(item, 'group');
}) })
} }
if(subLevelDepartmentVOList.length>0){ if (subLevelDepartmentVOList.length > 0) {
switch (props.treeType){ switch (props.treeType) {
case 'postGrouptab': case 'postGrouptab':
postobj.label=renderTitle('岗位'); postobj.label = renderTitle('岗位');
break; break;
case 'customGroupTab': case 'customGroupTab':
postobj.label=renderTitle('分组'); postobj.label = renderTitle('分组');
break; break;
default: default:
break; break;
} }
postobj.options=subLevelDepartmentVOList.map((item,index)=>{ postobj.options = subLevelDepartmentVOList.map((item, index) => {
return renderItem(item,'post'); return renderItem(item, 'post');
}) })
} }
if(Object.keys(userObj).length !==0){ if (Object.keys(userObj).length !== 0) {
_completeOptions.push(userObj); _completeOptions.push(userObj);
} }
if(Object.keys(departmentGroupObj).length !==0){ if (Object.keys(departmentGroupObj).length !== 0) {
_completeOptions.push(departmentGroupObj); _completeOptions.push(departmentGroupObj);
} }
if(Object.keys(postobj).length !==0){ if (Object.keys(postobj).length !== 0) {
_completeOptions.push(postobj); _completeOptions.push(postobj);
} }
setCompleteOption(_completeOptions); setCompleteOption(_completeOptions);
...@@ -193,23 +228,23 @@ function LeftStructureTree(props) { ...@@ -193,23 +228,23 @@ function LeftStructureTree(props) {
} }
async function addCustomer(treeType,query){ async function addCustomer(treeType, query) {
await getTreeData(treeType); await getTreeData(treeType);
props.searchUserList(query,treeType,1); props.searchUserList(query, treeType, 1);
} }
function getTreeData(treeType){ function getTreeData(treeType) {
return new Promise((resolve,reject)=>{ return new Promise((resolve, reject) => {
const params = { const params = {
departmentTypeEnum:DepType[treeType] || DepType[props.treeType], departmentTypeEnum: DepType[treeType] || DepType[props.treeType],
enterpriseId:User.getEnterpriseId(), enterpriseId: User.getEnterpriseId(),
source:0,//0代表来自企培 source: 0,//0代表来自企培
storeId:User.getStoreId(), storeId: User.getStoreId(),
userId:User.getUserId(), userId: User.getUserId(),
whetherCount:true whetherCount: true
} }
StoreService.queryDepartmentTree(params).then((res) => { StoreService.queryDepartmentTree(params).then((res) => {
const { result = []} = res const { result = [] } = res
let { departmentVOList=[] } =result; let { departmentVOList = [] } = result;
let _treeData = handleData(result); let _treeData = handleData(result);
setTreeData(_treeData); setTreeData(_treeData);
resolve(result); resolve(result);
...@@ -218,11 +253,11 @@ function LeftStructureTree(props) { ...@@ -218,11 +253,11 @@ function LeftStructureTree(props) {
}) })
} }
function handleData(dataArray){ function handleData(dataArray) {
const _dataArray = dataArray.map((item,index)=>{ const _dataArray = dataArray.map((item, index) => {
item.title = ""; item.title = "";
item.key=item.id; item.key = item.id;
if(item.sonDepartmentVOList){ if (item.sonDepartmentVOList) {
item.children = item.sonDepartmentVOList; item.children = item.sonDepartmentVOList;
handleData(item.sonDepartmentVOList) handleData(item.sonDepartmentVOList)
} }
...@@ -238,15 +273,15 @@ function LeftStructureTree(props) { ...@@ -238,15 +273,15 @@ function LeftStructureTree(props) {
const moreOpenGroupOperate = (record) => ( const moreOpenGroupOperate = (record) => (
<Menu> <Menu>
<Menu.Item key="edit"> <Menu.Item key="edit">
<span onClick={()=>{props.treeType==='postGrouptab'?editPostGroup(record):editCustomGroup(record)}}>编辑</span> <span onClick={() => { props.treeType === 'postGrouptab' ? editPostGroup(record) : editCustomGroup(record) }}>编辑</span>
</Menu.Item> </Menu.Item>
{record.depLevel ===0 && {record.depLevel === 0 &&
<Menu.Item key="add" > <Menu.Item key="add" >
<span onClick={()=>{props.treeType==='postGrouptab'?addPostGroup(1,record):addCustomGroup(1,record)}}> <span onClick={() => { props.treeType === 'postGrouptab' ? addPostGroup(1, record) : addCustomGroup(1, record) }}>
{props.treeType==='postGrouptab' && {props.treeType === 'postGrouptab' &&
<span>新建岗位</span> <span>新建岗位</span>
} }
{props.treeType==='customGroupTab' && {props.treeType === 'customGroupTab' &&
<span>新建分组</span> <span>新建分组</span>
} }
</span> </span>
...@@ -254,7 +289,7 @@ function LeftStructureTree(props) { ...@@ -254,7 +289,7 @@ function LeftStructureTree(props) {
} }
{/* { (record.departmentCount === 0 || !record.departmentCount) && */} {/* { (record.departmentCount === 0 || !record.departmentCount) && */}
<Menu.Item key="del"> <Menu.Item key="del">
<span onClick={()=>{props.treeType==='postGrouptab'?delPostGroup(record):delCustomGroup(record)}}>删除</span> <span onClick={() => { props.treeType === 'postGrouptab' ? delPostGroup(record) : delCustomGroup(record) }}>删除</span>
</Menu.Item> </Menu.Item>
{/* } */} {/* } */}
</Menu> </Menu>
...@@ -266,16 +301,16 @@ function LeftStructureTree(props) { ...@@ -266,16 +301,16 @@ function LeftStructureTree(props) {
} }
//添加岗位组/岗位 //添加岗位组/岗位
function addPostGroup(level,record) { function addPostGroup(level, record) {
if(level===0){ if (level === 0) {
if (treeData.length > 9) { if (treeData.length > 9) {
message.error("岗位组数量已达10个上限"); message.error("岗位组数量已达10个上限");
return; return;
} }
} }
if(level===1){ if (level === 1) {
if(record.sonDepartmentVOList){ if (record.sonDepartmentVOList) {
if(record.sonDepartmentVOList.length > 19){ if (record.sonDepartmentVOList.length > 19) {
message.error("岗位数量已达20个上限"); message.error("岗位数量已达20个上限");
return; return;
} }
...@@ -287,30 +322,30 @@ function LeftStructureTree(props) { ...@@ -287,30 +322,30 @@ function LeftStructureTree(props) {
setOperatePostGroupModalType("add"); setOperatePostGroupModalType("add");
setPostGroupModalLevel(level); setPostGroupModalLevel(level);
setCurrentGroupData(record); setCurrentGroupData(record);
console.log('treeData',record); console.log('treeData', record);
if(level===0){ if (level === 0) {
setPostGroupModalTitle('添加岗位组'); setPostGroupModalTitle('添加岗位组');
setPostGroupModalLable('岗位组'); setPostGroupModalLable('岗位组');
setPostGroupTreeData(treeData); setPostGroupTreeData(treeData);
}else{ } else {
setPostGroupModalTitle('添加岗位'); // sub代表岗位 setPostGroupModalTitle('添加岗位'); // sub代表岗位
setPostGroupModalLable('岗位'); setPostGroupModalLable('岗位');
setPostGroupTreeData(record.sonDepartmentVOList || []); setPostGroupTreeData(record.sonDepartmentVOList || []);
} }
} }
//编辑岗位组/岗位 //编辑岗位组/岗位
function editPostGroup(record){ function editPostGroup(record) {
setAddOrEditPostGroupShow(true); setAddOrEditPostGroupShow(true);
setOperatePostGroupModalType("edit"); setOperatePostGroupModalType("edit");
//level为0的时候编辑的是岗位组 大于0的时候 //level为0的时候编辑的是岗位组 大于0的时候
setPostGroupModalLevel(record.depLevel); setPostGroupModalLevel(record.depLevel);
setCurrentGroupData(record); setCurrentGroupData(record);
console.log('treeData',record); console.log('treeData', record);
if(record.depLevel===0){ if (record.depLevel === 0) {
setPostGroupModalTitle('编辑岗位组'); setPostGroupModalTitle('编辑岗位组');
setPostGroupModalLable('岗位组'); setPostGroupModalLable('岗位组');
setPostGroupTreeData(treeData); setPostGroupTreeData(treeData);
}else{ } else {
setPostGroupModalTitle('编辑岗位'); setPostGroupModalTitle('编辑岗位');
setPostGroupModalLable('岗位'); setPostGroupModalLable('岗位');
setPostGroupTreeData(getParentChildernData(record.parentId)); setPostGroupTreeData(getParentChildernData(record.parentId));
...@@ -318,23 +353,23 @@ function LeftStructureTree(props) { ...@@ -318,23 +353,23 @@ function LeftStructureTree(props) {
} }
// 获取父节点下的所有的子级数据 // 获取父节点下的所有的子级数据
function getParentChildernData(parentId){ function getParentChildernData(parentId) {
let _parentChildernData = [] let _parentChildernData = []
treeData.map((item,index)=>{ treeData.map((item, index) => {
if( parentId=== item.id){ if (parentId === item.id) {
_parentChildernData = item.sonDepartmentVOList _parentChildernData = item.sonDepartmentVOList
} }
}) })
return _parentChildernData return _parentChildernData
} }
function delPostGroup(record){ function delPostGroup(record) {
let title = '确认删除该岗位组吗?'; let title = '确认删除该岗位组吗?';
let content= '删除后,该岗位组下的岗位及也将全部删除。'; let content = '删除后,该岗位组下的岗位及也将全部删除。';
if(record.departmentCount && record.departmentCount>0 ){ if (record.departmentCount && record.departmentCount > 0) {
title = '删除失败'; title = '删除失败';
if(record.depLevel>0){ if (record.depLevel > 0) {
content = `${record.name}存在学员,不能删除该岗位`; content = `${record.name}存在学员,不能删除该岗位`;
}else{ } else {
content = `${record.name}存在学员,不能删除该岗位组`; content = `${record.name}存在学员,不能删除该岗位组`;
} }
Modal.warning({ Modal.warning({
...@@ -345,7 +380,7 @@ function LeftStructureTree(props) { ...@@ -345,7 +380,7 @@ function LeftStructureTree(props) {
}) })
return return
} }
if(record.level>0){ if (record.level > 0) {
title = '确认删除该岗位吗?'; title = '确认删除该岗位吗?';
content = '删除后,不可恢复'; content = '删除后,不可恢复';
} }
...@@ -361,13 +396,13 @@ function LeftStructureTree(props) { ...@@ -361,13 +396,13 @@ function LeftStructureTree(props) {
}, },
}); });
} }
function delGroup(record){ function delGroup(record) {
let parmas = { let parmas = {
departmentId:record.id, departmentId: record.id,
enterpriseId:User.getEnterpriseId(), enterpriseId: User.getEnterpriseId(),
source:0, source: 0,
storeId:User.getStoreId(), storeId: User.getStoreId(),
userId:User.getUserId() userId: User.getUserId()
} }
StoreService.delDepartment(parmas).then((res) => { StoreService.delDepartment(parmas).then((res) => {
message.success(`删除成功`) message.success(`删除成功`)
...@@ -378,16 +413,16 @@ function LeftStructureTree(props) { ...@@ -378,16 +413,16 @@ function LeftStructureTree(props) {
//添加自定义分组集合/分组 //添加自定义分组集合/分组
function addCustomGroup(level,record) { function addCustomGroup(level, record) {
if(level===0){ if (level === 0) {
if (treeData.length > 9) { if (treeData.length > 9) {
message.error("自定义分组集合数量已达10个上限"); message.error("自定义分组集合数量已达10个上限");
return; return;
} }
} }
if(level===1){ if (level === 1) {
if(record.sonDepartmentVOList){ if (record.sonDepartmentVOList) {
if(record.sonDepartmentVOList.length > 19){ if (record.sonDepartmentVOList.length > 19) {
message.error("自定义分组数量已达20个上限"); message.error("自定义分组数量已达20个上限");
return; return;
} }
...@@ -398,41 +433,41 @@ function LeftStructureTree(props) { ...@@ -398,41 +433,41 @@ function LeftStructureTree(props) {
setOperatePostGroupModalType("add"); setOperatePostGroupModalType("add");
setPostGroupModalLevel(level); setPostGroupModalLevel(level);
setCurrentGroupData(record) setCurrentGroupData(record)
if(level===0){ if (level === 0) {
setPostGroupModalTitle('添加分组集合'); setPostGroupModalTitle('添加分组集合');
setPostGroupModalLable('分组集合'); setPostGroupModalLable('分组集合');
setPostGroupTreeData(treeData); setPostGroupTreeData(treeData);
}else{ } else {
setPostGroupModalTitle('添加分组'); // sub代表岗位 setPostGroupModalTitle('添加分组'); // sub代表岗位
setPostGroupModalLable('分组'); setPostGroupModalLable('分组');
setPostGroupTreeData(record.sonDepartmentVOList || []); setPostGroupTreeData(record.sonDepartmentVOList || []);
} }
} }
//编辑自定义分组集合/分组 //编辑自定义分组集合/分组
function editCustomGroup(record){ function editCustomGroup(record) {
setAddOrEditPostGroupShow(true); setAddOrEditPostGroupShow(true);
setOperatePostGroupModalType("edit"); setOperatePostGroupModalType("edit");
setPostGroupModalLevel(record.level); setPostGroupModalLevel(record.level);
setCurrentGroupData(record) setCurrentGroupData(record)
//level为0的时候编辑的是岗位组 大于0的时候 //level为0的时候编辑的是岗位组 大于0的时候
if(record.depLevel===0){ if (record.depLevel === 0) {
setPostGroupModalTitle('编辑分组集合'); setPostGroupModalTitle('编辑分组集合');
setPostGroupModalLable('分组集合'); setPostGroupModalLable('分组集合');
setPostGroupTreeData(treeData); setPostGroupTreeData(treeData);
}else{ } else {
setPostGroupModalTitle('编辑分组'); setPostGroupModalTitle('编辑分组');
setPostGroupModalLable('分组'); setPostGroupModalLable('分组');
setPostGroupTreeData(getParentChildernData(record.parentId)); setPostGroupTreeData(getParentChildernData(record.parentId));
} }
} }
function delCustomGroup(record){ function delCustomGroup(record) {
let title = '确认删除该分组集合吗?'; let title = '确认删除该分组集合吗?';
let content= '删除后,该分组集合下的岗位及也将全部删除。'; let content = '删除后,该分组集合下的岗位及也将全部删除。';
if(record.departmentCount && record.departmentCount>0 ){ if (record.departmentCount && record.departmentCount > 0) {
title = '删除失败'; title = '删除失败';
if(record.level>0){ if (record.level > 0) {
content = `${record.name}存在学员,不能删除该分组`; content = `${record.name}存在学员,不能删除该分组`;
}else{ } else {
content = `${record.name}存在学员,不能删除该分组集合`; content = `${record.name}存在学员,不能删除该分组集合`;
} }
Modal.warning({ Modal.warning({
...@@ -443,7 +478,7 @@ function LeftStructureTree(props) { ...@@ -443,7 +478,7 @@ function LeftStructureTree(props) {
}) })
return return
} }
if(record.level>0){ if (record.level > 0) {
title = '确认删除该分组吗?'; title = '确认删除该分组吗?';
content = '删除后,不可恢复'; content = '删除后,不可恢复';
} }
...@@ -466,14 +501,25 @@ function LeftStructureTree(props) { ...@@ -466,14 +501,25 @@ function LeftStructureTree(props) {
getTreeData() getTreeData()
} }
function selectUserList(record,e){ function selectUserList(record, e) {
const _selectKeys = []; const _selectKeys = [];
if(e.selectedNodes && e.selectedNodes.length>0){
_selectKeys.push(e.selectedNodes[0].id) _selectKeys.push(e.selectedNodes[0].id)
}
setSelectedKeys(_selectKeys); setSelectedKeys(_selectKeys);
props.onChangeSelectDep(e.selectedNodes[0]); props.onChangeSelectDep(e.selectedNodes[0]);
props.searchUserList(e.selectedNodes[0],treeType,1); props.searchUserList(e.selectedNodes[0], treeType, 1);
} }
function changeName(value) {
setQueryName(value); setOpen(true);
clearTimeout(timer.current)
timer.current = setTimeout(() => {
getCompleteOptionData(queryNameRef.current)
}, 500)
}
return ( return (
<div className="left-structure-tree"> <div className="left-structure-tree">
<div className="organization"> <div className="organization">
...@@ -483,13 +529,13 @@ function LeftStructureTree(props) { ...@@ -483,13 +529,13 @@ function LeftStructureTree(props) {
dropdownClassName="certain-category-search-dropdown" dropdownClassName="certain-category-search-dropdown"
dropdownMatchSelectWidth={250} dropdownMatchSelectWidth={250}
allowClear allowClear
onChange={(value)=>setQueryName(value)} onChange={changeName}
onSearch={(value)=>{getCompleteOptionData(value)}} // onSearch={(value)=>{getCompleteOptionData(value)}}
notFoundContent={notFoundContentNode()} notFoundContent={notFoundContentNode()}
value={queryName} value={queryName}
open={open} open={open}
onFocus={()=>{setOpen(true)}} onFocus={() => { setOpen(true) }}
onBlur={()=>{setOpen(false)}} onBlur={() => { setOpen(false) }}
style={{ style={{
width: 250, width: 250,
}} }}
...@@ -497,11 +543,15 @@ function LeftStructureTree(props) { ...@@ -497,11 +543,15 @@ function LeftStructureTree(props) {
onSelect={confirmSearchSelect} onSelect={confirmSearchSelect}
placeholder={handlePlaceHolder()} placeholder={handlePlaceHolder()}
> >
<Search
style={{ width: 250 }}
enterButton={<span className='icon iconfont'>&#xe832;</span>}
/>
</AutoComplete> </AutoComplete>
</div> </div>
{ (props.treeType==='postGrouptab' || props.treeType=== 'customGroupTab') && ( {(props.treeType === 'postGrouptab' || props.treeType === 'customGroupTab') && (
<div className="operate"> <div className="operate">
{props.treeType==='postGrouptab' && {props.treeType === 'postGrouptab' &&
<Button <Button
className="add-btn" className="add-btn"
onClick={() => { onClick={() => {
...@@ -511,7 +561,7 @@ function LeftStructureTree(props) { ...@@ -511,7 +561,7 @@ function LeftStructureTree(props) {
添加岗位组 添加岗位组
</Button> </Button>
} }
{props.treeType==='customGroupTab' && {props.treeType === 'customGroupTab' &&
<Button <Button
className="add-btn" className="add-btn"
onClick={() => { onClick={() => {
...@@ -536,7 +586,7 @@ function LeftStructureTree(props) { ...@@ -536,7 +586,7 @@ function LeftStructureTree(props) {
<div <div
className="node-title-div" className="node-title-div"
onMouseOver={(e) => { onMouseOver={(e) => {
if((props.treeType==='postGrouptab' || props.treeType=== 'customGroupTab')){ if ((props.treeType === 'postGrouptab' || props.treeType === 'customGroupTab')) {
if (nodeData.key === "null") return; if (nodeData.key === "null") return;
let moreDiv = e.currentTarget.getElementsByClassName( let moreDiv = e.currentTarget.getElementsByClassName(
"item-more" "item-more"
...@@ -553,7 +603,7 @@ function LeftStructureTree(props) { ...@@ -553,7 +603,7 @@ function LeftStructureTree(props) {
} }
}} }}
onMouseOut={(e) => { onMouseOut={(e) => {
if((props.treeType==='postGrouptab' || props.treeType=== 'customGroupTab')){ if ((props.treeType === 'postGrouptab' || props.treeType === 'customGroupTab')) {
if (nodeData.key === "null") return; if (nodeData.key === "null") return;
let moreDiv = e.currentTarget.getElementsByClassName( let moreDiv = e.currentTarget.getElementsByClassName(
"item-more" "item-more"
...@@ -584,14 +634,14 @@ function LeftStructureTree(props) { ...@@ -584,14 +634,14 @@ function LeftStructureTree(props) {
: "78%", : "78%",
}} }}
> >
{ props.treeType==='departMentTab'? {props.treeType === 'departMentTab' ?
<span><WWOpenDataCom type="departmentName" openid={nodeData.name}/></span> <span><WWOpenDataCom type="departmentName" openid={nodeData.name} /></span>
: :
<span>{nodeData.name}</span> <span>{nodeData.name}</span>
} }
</div> </div>
<div className="item-count">({nodeData.departmentCount || 0})</div> <div className="item-count">({nodeData.departmentCount || 0})</div>
{ (props.treeType==='postGrouptab' || props.treeType=== 'customGroupTab') && ( {(props.treeType === 'postGrouptab' || props.treeType === 'customGroupTab') && (
<Dropdown overlay={moreOpenGroupOperate(nodeData)}> <Dropdown overlay={moreOpenGroupOperate(nodeData)}>
<div className="item-more icon iconfont">&#xe927;</div> <div className="item-more icon iconfont">&#xe927;</div>
</Dropdown> </Dropdown>
...@@ -604,10 +654,10 @@ function LeftStructureTree(props) { ...@@ -604,10 +654,10 @@ function LeftStructureTree(props) {
<div> <div>
{/* { (props.treeType==='departMentTab') && */} {/* { (props.treeType==='departMentTab') && */}
<div> <div>
{ selctQueryName.type==='userName'? {selctQueryName.type === 'userName' ?
<WWOpenDataCom type="userName" openid={selctQueryName.openid}/> <WWOpenDataCom type="userName" openid={selctQueryName.openid} />
: :
<WWOpenDataCom type="departmentName" openid={selctQueryName.openid}/> <WWOpenDataCom type="departmentName" openid={selctQueryName.openid} />
} }
</div> </div>
......
...@@ -70,7 +70,48 @@ ...@@ -70,7 +70,48 @@
color: #666666; color: #666666;
} }
} }
} }
} }
.certain-category-search-dropdown{
.catalog-title{
font-size:14px;
color:#666;
margin-bottom:14px;
}
.search-result-item{
padding:14px 0;
color:#333;
.title-icon{
color:#999;
margin-right:3px;
}
.search-result-item__left{
font-size:14px;
}
.search-result-item__right{
font-size:14px;
width:84px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
color:#999;
text-align:right;
}
}
.ant-select-item-option-grouped{
padding-left:12px;
}
.empty-con{
text-align:center;
.empty-img{
width:150px;
height:150px;
}
.empty-text{
color:#666;
}
}
}
\ No newline at end of file
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { withRouter } from "react-router-dom"; import { withRouter } from "react-router-dom";
import { Tree} from "antd"; import { Tree,Tooltip} from "antd";
import StoreService from "@/domains/store-domain/storeService"; import StoreService from "@/domains/store-domain/storeService";
import User from '@/common/js/user'; import User from '@/common/js/user';
import WWOpenDataCom from '@/components/WWOpenDataCom'; import WWOpenDataCom from '@/components/WWOpenDataCom';
...@@ -40,7 +40,7 @@ function MemberTree(props) { ...@@ -40,7 +40,7 @@ function MemberTree(props) {
const _dataArray = dataArray.map((item,index)=>{ const _dataArray = dataArray.map((item,index)=>{
item.title = ""; item.title = "";
item.key=item.id; item.key=item.id;
item.children = [] item.children = [];
if(item.departmentUserVOList){ if(item.departmentUserVOList){
item.children = item.departmentUserVOList; item.children = item.departmentUserVOList;
} }
...@@ -60,11 +60,10 @@ function MemberTree(props) { ...@@ -60,11 +60,10 @@ function MemberTree(props) {
const _checkedNodes = e.checkedNodes; const _checkedNodes = e.checkedNodes;
const _selectNodes = []; const _selectNodes = [];
_checkedNodes.map((item,index)=>{ _checkedNodes.map((item,index)=>{
if(item.userId){ // if(item.userId){
_selectNodes.push(item); _selectNodes.push(item);
} // }
}) })
console.log('_selectNodes',_selectNodes);
props.onSelect(_selectNodes); props.onSelect(_selectNodes);
} }
return ( return (
...@@ -75,7 +74,7 @@ function MemberTree(props) { ...@@ -75,7 +74,7 @@ function MemberTree(props) {
checkable checkable
showIcon={false} showIcon={false}
treeData={treeData} treeData={treeData}
checkedKeys={_.pluck(props.selectUserList, 'id')} checkedKeys={_.pluck(props.selectList, 'id')}
onCheck={(selectedKeys,e)=>treeSelected(selectedKeys,e)} onCheck={(selectedKeys,e)=>treeSelected(selectedKeys,e)}
titleRender={(nodeData) => { titleRender={(nodeData) => {
return ( return (
...@@ -83,15 +82,20 @@ function MemberTree(props) { ...@@ -83,15 +82,20 @@ function MemberTree(props) {
className="node-title-con" className="node-title-con"
> >
{nodeData.userId ? {nodeData.userId ?
<div> <>
<span className="icon iconfont title-icon">&#xe603;</span> <span className="icon iconfont title-icon">&#xe603;</span>
<span><WWOpenDataCom type="userName" openid={nodeData.userName}/></span> <Tooltip title={<WWOpenDataCom type="userName" openid={nodeData.userName}/>}>
</div> <span className="name"><WWOpenDataCom type="userName" openid={nodeData.userName}/></span>
</Tooltip>
</>
: :
<div> <>
<span className="icon iconfont title-icon">&#xe604;</span> <span className="icon iconfont title-icon">&#xe604;</span>
<span><WWOpenDataCom type="departmentName" openid={nodeData.name}/></span> <Tooltip title={<WWOpenDataCom type="departmentName" openid={nodeData.name}/>}>
</div> <span className="name"><WWOpenDataCom type="departmentName" openid={nodeData.name}/></span>
</Tooltip>
<span>({nodeData.departmentCount || 0})</span>
</>
} }
</div> </div>
); );
......
...@@ -2,8 +2,29 @@ ...@@ -2,8 +2,29 @@
.node-title-con{ .node-title-con{
color:#666; color:#666;
font-size:14px; font-size:14px;
display: flex;
.name{
display: inline-block;
vertical-align: middle;
max-width:190px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.title-icon{ .title-icon{
font-size:14px;
color:#999;
margin-right:8px; margin-right:8px;
} }
} }
.ant-tree .ant-tree-treenode {
padding: 8px 0 14px 0;
}
.ant-tree.ant-tree-directory .ant-tree-treenode-selected:hover::before, .ant-tree.ant-tree-directory .ant-tree-treenode-selected::before{
background:transparent;
}
.ant-tree.ant-tree-directory .ant-tree-treenode-selected .ant-tree-switcher{
color:#000;
}
} }
\ 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 React, { useEffect, useState } from "react";
import { withRouter } from "react-router-dom"; import { withRouter } from "react-router-dom";
import { Input,Checkbox} from "antd"; import { Input,Checkbox,Tooltip} from "antd";
import StoreService from "@/domains/store-domain/storeService"; import StoreService from "@/domains/store-domain/storeService";
import User from '@/common/js/user'; import User from '@/common/js/user';
import WWOpenDataCom from '@/components/WWOpenDataCom'; import WWOpenDataCom from '@/components/WWOpenDataCom';
import $ from 'jquery'; import $ from 'jquery';
import _ from 'underscore';
import './SearchUser.less' import './SearchUser.less'
const { Search } = Input; const { Search } = Input;
function SearchUser(props) { function SearchUser(props) {
...@@ -17,19 +18,53 @@ function SearchUser(props) { ...@@ -17,19 +18,53 @@ function SearchUser(props) {
} }
function onChange(e){ function onChange(e){
setDropDownVisible(true);
props.onChange(e.target.value) props.onChange(e.target.value)
} }
function selectuser(e,item){ function selectuser(e,item){
if(e.target.checked){ if(e.target.checked){
let _record = [] let _record = props.selectList
_record.push(item) _record.push(item)
props.onSelect(_record,'user') props.onSelect(_record,'user')
}else{
let _record = props.selectList
_record.map((_item,index)=>{
if(_item.userId === item.userId){
_record.splice(index,1)
}
})
props.onSelect(_record,'user')
} }
} }
function selectDep(e,item){ function selectDep(e,item){
if(e.target.checked){
console.log('item',item); console.log('item',item);
props.onSelect(item,'department'); if(e.target.checked){
let _record = props.selectList;
let _userList = [];
_record.push(item); // 将当前选中的部门塞进来
if(item.departmentUserVOList){
_userList = item.departmentUserVOList; //获取当前选中的人
}
_record = [..._record,..._userList];
props.onSelect(_record,'department');
}else{
let _record = [];
let _userList = [];
props.selectList.map((_item,index)=>{
if(_item.id !== item.id){ //取消选择后将当前的部门移除也要将父部门也移除
_record.push(_item);
}
})
if(item.departmentUserVOList){
_userList = item.departmentUserVOList; //获取当前选中的人
}
const new_arr = _record.filter((x) => {return !_userList.some((item) => x.id === item.id)});
// _userList.map((_item,index)=>{
// if(_item.id === item.id){
// _record.splice(_item,index);
// }
// })
props.onSelect(new_arr,'department');
} }
} }
function documentClick(){ function documentClick(){
...@@ -41,6 +76,12 @@ function SearchUser(props) { ...@@ -41,6 +76,12 @@ function SearchUser(props) {
}; };
} }
function handleDepName(depArray){
const depArrayDom = depArray.map((item, index) => {
return <span><WWOpenDataCom type="departmentName" openid={item}/></span>
});
return depArrayDom;
};
return ( return (
<div className="search-user" style={{width:'300px'}} id="search-user"> <div className="search-user" style={{width:'300px'}} id="search-user">
<Search <Search
...@@ -49,13 +90,12 @@ function SearchUser(props) { ...@@ -49,13 +90,12 @@ function SearchUser(props) {
onFocus={(e)=>{onFocus(e)}} onFocus={(e)=>{onFocus(e)}}
onChange={(e)=>{onChange(e)}} onChange={(e)=>{onChange(e)}}
className="search-input-item" className="search-input-item"
// onBlur={()=>{onBlur()}}
/> />
{dropDownVisible && {dropDownVisible &&
<div className="drop-down"> <div className="drop-down">
<div className="drop-down__list"> <div className="drop-down__list">
{props.data.departmentUserVOList && {props.data.departmentUserVOList &&
<div> ( props.data.departmentUserVOList.length>0 && <div className="drop-down__item-user">
<div className="drop-down__item__title"> <div className="drop-down__item__title">
员工 员工
</div> </div>
...@@ -63,17 +103,19 @@ function SearchUser(props) { ...@@ -63,17 +103,19 @@ function SearchUser(props) {
<div> <div>
{props.data.departmentUserVOList.map((item,index)=>{ {props.data.departmentUserVOList.map((item,index)=>{
return <div> return <div>
<Checkbox onChange={(e)=>{selectuser(e,item)}} > <Checkbox onChange={(e)=>{selectuser(e,item)}} checked={_.pluck(props.selectList, 'userId').indexOf(item.userId)=== -1?false:true}>
<div className="drop-down__item__con__item"> <div className="drop-down__item__con__item">
<div className="drop-down__item__con__item__left"> <div className="drop-down__item__con__item__left">
<span className="icon iconfont title-icon">&#xe603;</span> <span className="icon iconfont title-icon">&#xe603;</span>
<WWOpenDataCom type="userName" openid={item.userName}/> <WWOpenDataCom type="userName" openid={item.userName}/>
</div> </div>
<div className="drop-down__item__con__item__right"> <div className="drop-down__item__con__item__right">
<Tooltip title={<div>{handleDepName(item.depNamesList)}</div>} placement='top' arrowPointAtCenter>
{item.depNamesList.map((_item,index)=>{ {item.depNamesList.map((_item,index)=>{
return <span> <WWOpenDataCom type="departmentName" openid={_item}/>{index<(item.depNamesList.length -1)?';':''}</span> return <span> <WWOpenDataCom type="departmentName" openid={_item}/>{index<(item.depNamesList.length -1)?';':''}</span>
}) })
} }
</Tooltip>
</div> </div>
</div> </div>
</Checkbox> </Checkbox>
...@@ -82,20 +124,24 @@ function SearchUser(props) { ...@@ -82,20 +124,24 @@ function SearchUser(props) {
} }
</div> </div>
</div> </div>
</div> </div>)
} }
{props.data.departmentVOList && {props.data.departmentVOList &&
<div> (props.data.departmentVOList.length>0 && <div>
<div className="drop-down__item__title"> <div className="drop-down__item__title drop-down__item__title-dep">
部门 部门
</div> </div>
<div className="drop-down__item__con"> <div className="drop-down__item__con">
<div> <div>
{props.data.departmentVOList.map((item,index)=>{ {props.data.departmentVOList.map((item,index)=>{
return <div><Checkbox onChange={(e)=>{selectDep(e,item)}}> return <div><Checkbox onChange={(e)=>{selectDep(e,item)}} checked={_.pluck(props.selectList, 'id').indexOf(item.id)=== -1?false:true}>
<div className="drop-down__item__con__item"> <div className="drop-down__item__con__item">
<div className="drop-down__item__con__item__left"> <div className="drop-down__item__con__item__left">
<Tooltip title={ <WWOpenDataCom type="departmentName" openid={item.name}/>}>
<span className="departmentName">
<WWOpenDataCom type="departmentName" openid={item.name}/> <WWOpenDataCom type="departmentName" openid={item.name}/>
</span>
</Tooltip>
</div> </div>
</div> </div>
</Checkbox> </Checkbox>
...@@ -104,10 +150,21 @@ function SearchUser(props) { ...@@ -104,10 +150,21 @@ function SearchUser(props) {
} }
</div> </div>
</div> </div>
</div> </div>)
} }
{(!props.data.departmentUserVOList && !props.data.departmentVOList)&& {(!props.data.departmentUserVOList && !props.data.departmentVOList)&&
<div>暂无数据</div> <div className="empty-con">
<img src="https://image.xiaomaiketang.com/xm/wRDrb2pJFb.png" className="empty-img"/>
<div className="empty-text">暂无数据</div>
</div>
}
{ (props.data.departmentUserVOList && props.data.departmentVOList) &&(
(props.data.departmentUserVOList.length === 0 && props.data.departmentVOList.length ===0) &&
<div className="empty-con">
<img src="https://image.xiaomaiketang.com/xm/wRDrb2pJFb.png" className="empty-img"/>
<div className="empty-text">暂无数据</div>
</div>
)
} }
</div> </div>
</div> </div>
......
...@@ -10,14 +10,39 @@ ...@@ -10,14 +10,39 @@
box-shadow: 0px 2px 15px 6px rgba(0, 0, 0, 0.05); box-shadow: 0px 2px 15px 6px rgba(0, 0, 0, 0.05);
border-radius:2px; border-radius:2px;
width:270px; width:270px;
max-height:280px;
overflow-y: scroll;
// .drop-down__item-user{
// margin-bottom:30px;
// }
.drop-down__item__title{
font-size:14px;
color:#666;
margin-bottom:14px;
}
.ant-checkbox-wrapper{ .ant-checkbox-wrapper{
width:100%; width:100%;
.drop-down__item__con__item{ .drop-down__item__con__item{
margin-bottom:24px;
display:flex; display:flex;
width:220px; width:220px;
justify-content:space-between; justify-content:space-between;
color:#333; color:#333;
font-size:14px; font-size:14px;
.drop-down__item__con__item__left{
.title-icon{
color:#999;
margin-right:3px;
}
.departmentName{
display: inline-block;
vertical-align: middle;
max-width:190px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
}
.drop-down__item__con__item__right{ .drop-down__item__con__item__right{
width:84px; width:84px;
text-align:right; text-align:right;
...@@ -28,5 +53,15 @@ ...@@ -28,5 +53,15 @@
} }
} }
} }
.empty-con{
text-align:center;
.empty-img{
width:150px;
height:150px;
}
.empty-text{
color:#666;
}
}
} }
} }
\ No newline at end of file
...@@ -285,10 +285,11 @@ class ChooseMembersModal extends React.Component { ...@@ -285,10 +285,11 @@ class ChooseMembersModal extends React.Component {
visible={isOpen} visible={isOpen}
onCancel={() => this.handleClose()} onCancel={() => this.handleClose()}
onOk={() => { onOk={() => {
if (User.getVersion() && User.getVersion().whetherReachUserNum) { //xmqxy446去除此优化
message.error("添加失败,企业使用人数超出限制") // if (User.getVersion() && User.getVersion().whetherReachUserNum) {
return // message.error("添加失败,企业使用人数超出限制")
} // return
// }
if (_.isEmpty(selectUserList)) { if (_.isEmpty(selectUserList)) {
message.warning(type === 'USER' ? '请选择员工' : '请选择学员') message.warning(type === 'USER' ? '请选择员工' : '请选择学员')
return null; return null;
......
...@@ -17,7 +17,7 @@ import { DepType } from "@/domains/store-domain/constants"; ...@@ -17,7 +17,7 @@ import { DepType } from "@/domains/store-domain/constants";
import StoreService from "@/domains/store-domain/storeService"; import StoreService from "@/domains/store-domain/storeService";
import SearchUser from "../components/SearchUser" import SearchUser from "../components/SearchUser"
import WWOpenDataCom from '@/components/WWOpenDataCom'; import WWOpenDataCom from '@/components/WWOpenDataCom';
import './ChooseMembersModal.less'; import './NewChooseMembersModal.less';
import _ from 'underscore'; import _ from 'underscore';
const { Search } = Input; const { Search } = Input;
...@@ -26,7 +26,8 @@ class NewChooseMembersModal extends React.Component { ...@@ -26,7 +26,8 @@ class NewChooseMembersModal extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
selectUserList:[], selectList:[], //所有的选中项
selectUserList:[], // 所有的选中的用户
selectObject: {}, selectObject: {},
openSetModal: false, openSetModal: false,
visible:this.props.visible, visible:this.props.visible,
...@@ -57,7 +58,7 @@ class NewChooseMembersModal extends React.Component { ...@@ -57,7 +58,7 @@ class NewChooseMembersModal extends React.Component {
<div className='avatar'> <div className='avatar'>
<span className="icon iconfont avatar-icon">&#xe84a;</span> <span className="icon iconfont avatar-icon">&#xe84a;</span>
<Tooltip title={<WWOpenDataCom type="userName" openid={userName}/>}> <Tooltip title={<WWOpenDataCom type="userName" openid={userName}/>}>
<span className='userImg'> <span className='userName'>
<WWOpenDataCom type="userName" openid={userName}/> <WWOpenDataCom type="userName" openid={userName}/>
{/* {userName} */} {/* {userName} */}
</span> </span>
...@@ -84,26 +85,41 @@ class NewChooseMembersModal extends React.Component { ...@@ -84,26 +85,41 @@ class NewChooseMembersModal extends React.Component {
} }
treeSelect = (record)=>{ treeSelect = (record)=>{
// console.log('record',record)
this.setState({ this.setState({
selectUserList:record selectList:record,
selectUserList:this.handleSelectUserList(record)
}) })
} }
clearOneUser = (record) =>{
console.log("record",record); // 将所有的选中项里的人员挑出来
const {selectUserList} = this.state; handleSelectUserList =(list)=>{
const _selectUserList = selectUserList.filter((item,index)=>{ const _list = [];
return item.userId !== record.userId list.map((item,index)=>{
if(item.userId){
_list.push(item);
}
}) })
console.log('selectUserList',selectUserList); return _list
}
clearOneUser = (record) =>{
const {selectUserList,selectList} = this.state;
const _selectList = [];
selectList.map((item,index)=>{
if(item.userId !== record.userId && item.id !==record.departmentId){
_selectList.push(item);
}
}); //字部门移除时将其对应的父部门也移除
console.log('_selectList',_selectList);
this.setState({ this.setState({
selectUserList:_selectUserList selectList:_selectList,
selectUserList:this.handleSelectUserList(_selectList)
}) })
} }
// 清空所有成员 // 清空所有成员
clearAllUser = () => { clearAllUser = () => {
this.setState({ this.setState({
selectList:[],
selectUserList : [], selectUserList : [],
}) })
} }
...@@ -127,7 +143,6 @@ class NewChooseMembersModal extends React.Component { ...@@ -127,7 +143,6 @@ class NewChooseMembersModal extends React.Component {
} }
_item.enterpriseVisibleUserId = item.enterpriseUserId; _item.enterpriseVisibleUserId = item.enterpriseUserId;
_item.departmentId = this.props.selectDep.id; _item.departmentId = this.props.selectDep.id;
} }
return _item return _item
}) })
...@@ -138,6 +153,7 @@ class NewChooseMembersModal extends React.Component { ...@@ -138,6 +153,7 @@ class NewChooseMembersModal extends React.Component {
} }
Service.Hades('public/hades/addBatchUserAndDepartmentStoreCustomer', _params).then((res) => { Service.Hades('public/hades/addBatchUserAndDepartmentStoreCustomer', _params).then((res) => {
this.handleClose(); this.handleClose();
message.success('添加成功')
this.props.onConfirm(); this.props.onConfirm();
}) })
} }
...@@ -254,39 +270,23 @@ class NewChooseMembersModal extends React.Component { ...@@ -254,39 +270,23 @@ class NewChooseMembersModal extends React.Component {
} }
confirmSearchSelect=(record,type)=>{ confirmSearchSelect=(record,type)=>{
const { selectUserList } = this.state; const { selectUserList,selectList} = this.state;
if(type==='user'){ this.setState({selectList:record,selectUserList:this.handleSelectUserList(record)});
this.setState({selectUserList:[...selectUserList,...record]}); // if(type==='user'){
}else{ // this.setState({selectList:[...record],selectUserList:this.handleSelectUserList(record)});
let _list = [];
if(record.departmentUserVOList){
_list = record.departmentUserVOList;
}
console.log('_list',_list);
this.setState({selectUserList:[...selectUserList,..._list]},()=>{
console.log('selectUserList',this.state.selectUserList);
});
}
// }else{ // }else{
// const params = { // let _userList = [];
// depType:this.props.treeDepType, // if(record.departmentUserVOList){
// enterpriseId: User.getEnterpriseId(), // _userList = record.departmentUserVOList;
// source: 0,
// storeId: User.getStoreId(),
// userId: User.getUserId(),
// departmentId:record.id
// } // }
// StoreService.getStoreCustomerAndDepNamePage(params).then((res) => { // this.setState({selectList:[...selectList,..._userList],selectUserList:[...selectUserList,..._userList]});
// const { records = []} = res.result;
// this.setState({selectUserList:[...selectUserList,...records]});
// });
// } // }
} }
render() { render() {
const {type,treeDepType,selectDep={},addDepType=''} = this.props; const {type,treeDepType,selectDep={},addDepType=''} = this.props;
const { id=''} = selectDep; const { id=''} = selectDep;
const {selectUserList,selectObject,visible,openSetModal,searchUserResultList} = this.state; const {selectUserList,selectObject,visible,openSetModal,searchUserResultList,selectList} = this.state;
const title = type === 'USER' ? '添加员工' : '添加学员'; const title = type === 'USER' ? '添加员工' : '添加学员';
return ( return (
<div> <div>
...@@ -296,10 +296,11 @@ class NewChooseMembersModal extends React.Component { ...@@ -296,10 +296,11 @@ class NewChooseMembersModal extends React.Component {
visible={visible} visible={visible}
onCancel={() => this.handleClose()} onCancel={() => this.handleClose()}
onOk={() => { onOk={() => {
if (User.getVersion() && User.getVersion().whetherReachUserNum) { //xmqxy446去除此优化
message.error("添加失败,企业使用人数超出限制") // if (User.getVersion() && User.getVersion().whetherReachUserNum) {
return // message.error("添加失败,企业使用人数超出限制")
} // return
// }
if (_.isEmpty(selectUserList)) { if (_.isEmpty(selectUserList)) {
message.warning(type === 'USER' ? '请选择员工' : '请选择学员') message.warning(type === 'USER' ? '请选择员工' : '请选择学员')
return null; return null;
...@@ -315,15 +316,9 @@ class NewChooseMembersModal extends React.Component { ...@@ -315,15 +316,9 @@ class NewChooseMembersModal extends React.Component {
<div className='member-container'> <div className='member-container'>
<div className='container-left'> <div className='container-left'>
<div className='container-left-body'> <div className='container-left-body'>
{/* <Search <SearchUser onChange={(value)=>{this.getCompleteOptionData(value)}} data={searchUserResultList} onSelect={(record,type)=>{this.confirmSearchSelect(record,type)}} selectUserList={selectUserList} selectList={selectList}/>
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'> <div className='container-left-body-table'>
<MemberTree departmentId={id} treeDepType={treeDepType} nowTreeDepType={addDepType} onSelect={(record)=>{this.treeSelect(record)}} selectUserList={selectUserList} type={type}/> <MemberTree departmentId={id} treeDepType={treeDepType} nowTreeDepType={addDepType} onSelect={(record)=>{this.treeSelect(record)}} selectUserList={selectUserList} type={type} selectList={selectList}/>
</div> </div>
</div> </div>
</div> </div>
......
.choose-member-modal {
.member-container{
display: flex;
height: 417px;
.container-left{
width: 50%;
padding-right: 10px;
margin-left: 10px;
.container-left-header{
margin-bottom: 12px;
}
.container-left-body{
border: 1px solid #E9E9E9;
height: 100%;
.ant-table-thead > tr > th {
font-weight:400!important;
}
.search{
width: 305px;
padding: 7px 7px;
}
.container-left-body-table{
width: 300px;
max-height: 360px;
overflow: scroll;
.ant-table {
border: none;
min-height: 250px !important;
.ant-table-header{
margin-bottom: -7px !important;
>table > .ant-table-thead > tr > th {
background-color: #fff !important;
}
}
.ant-table-tbody{
>tr {
>td {
border-bottom: none;
background-color: #fff !important;
padding: 11px 0!important;
}
&:hover {
>td {
background: #F3F6FA !important;
}
}
}
}
}
.ant-empty-normal {
margin: 80px 0 !important;
}
.avatar{
display: flex;
align-items: center;
.avatar-icon {
font-size:14px;
color:#999;
margin-right: 6px;
}
.userName {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-size:14px;
color:#333;
}
}
}
}
}
.container-right{
width: 50%;
border: 1px solid #E9E9E9;
.span-left{
line-height: 45px;
margin-left: 10px;
.span-left-l{
color: #2966FF;
cursor: pointer;
}
}
.span-right{
line-height: 45px;
float: right;
margin-right: 10px;
color: #999;
.span-right-l{
color: #2966FF;
cursor: pointer;
}
}
.container-right-body{
min-height:376px;
border-top: 1px solid #e8e8e8;
.edit {
.edit-icon {
color:#999;
font-size:14px;
}
}
.edit-img{
width: 16px;
height: 16px;
}
.ant-table .ant-table-body {
overflow: auto;
max-height: 376px!important;
}
.ant-table tbody {
tr{
background: #fff;
&:first-child {
display: block;
overflow: hidden;
}
td{
padding:12px 18px !important;
}
}
}
.ant-empty-normal {
margin: 120px 0 !important;
}
.ant-empty {
margin-top: 76px;
}
.avatar{
display: flex;
align-items: center;
.avatar-icon {
font-size:14px;
color:#999;
margin-right: 6px;
}
.userName {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-size:14px;
color:#333;
}
}
.ant-table-tbody{
>tr >td {
border-bottom:none;
}
>tr .ant-table-selection-column{
width: 30px !important;
}
}
}
}
}
}
\ No newline at end of file
...@@ -47,7 +47,7 @@ ...@@ -47,7 +47,7 @@
flex-shrink: 0; flex-shrink: 0;
} }
&.selected { &.selected {
background: rgba(255, 183, 20, 0.1); background:rgba(41, 102, 255,0.1);
&::after { &::after {
content: ''; content: '';
position: absolute; position: absolute;
......
...@@ -42,6 +42,7 @@ function CourseCatalogSelect(props) { ...@@ -42,6 +42,7 @@ function CourseCatalogSelect(props) {
return ( return (
<TreeSelect <TreeSelect
className={props.className}
treeNodeLabelProp='categoryName' treeNodeLabelProp='categoryName'
showSearch={showSearch} showSearch={showSearch}
treeNodeFilterProp={treeNodeFilterProp} treeNodeFilterProp={treeNodeFilterProp}
......
...@@ -21,6 +21,7 @@ import { randomString } from '@/domains/basic-domain/utils'; ...@@ -21,6 +21,7 @@ import { randomString } from '@/domains/basic-domain/utils';
import Upload from '@/core/upload'; import Upload from '@/core/upload';
import PreviewCourseModal from './modal/PreviewCourseModal'; import PreviewCourseModal from './modal/PreviewCourseModal';
import CourseService from '@/domains/course-domain/CourseService'; import CourseService from '@/domains/course-domain/CourseService';
import routeHook from '@/core/routeHook'
import moment from 'moment'; import moment from 'moment';
import User from '@/common/js/user'; import User from '@/common/js/user';
import _ from 'underscore'; import _ from 'underscore';
...@@ -110,6 +111,7 @@ class AddLive extends React.Component { ...@@ -110,6 +111,7 @@ class AddLive extends React.Component {
} }
componentDidMount() { componentDidMount() {
routeHook.addSaveCase();
const { type } = this.state; const { type } = this.state;
if (type === 'edit') { if (type === 'edit') {
this.getCourseDetail(); this.getCourseDetail();
...@@ -279,7 +281,7 @@ class AddLive extends React.Component { ...@@ -279,7 +281,7 @@ class AddLive extends React.Component {
if (User.getExpirationTime() && moment().valueOf() > Number(User.getExpirationTime())) { if (User.getExpirationTime() && moment().valueOf() > Number(User.getExpirationTime())) {
Modal.warning({ Modal.warning({
title: '服务已到期', title: '服务已到期',
content: '当前企业购买的小麦企学院服务已到期,如需继续使用学院功能,请尽快续费购买', content: `当前企业购买的${window.brandName}服务已到期,如需继续使用学院功能,请尽快续费购买`,
okText: '我知道了', okText: '我知道了',
}); });
return; return;
...@@ -370,6 +372,7 @@ class AddLive extends React.Component { ...@@ -370,6 +372,7 @@ class AddLive extends React.Component {
CourseService.createLiveCloudCourse(params).then((res) => { CourseService.createLiveCloudCourse(params).then((res) => {
if (res.success) { if (res.success) {
message.success('新建成功'); message.success('新建成功');
routeHook.cancel()
window.RCHistory.push({ window.RCHistory.push({
pathname: `/live-course`, pathname: `/live-course`,
}); });
...@@ -385,6 +388,7 @@ class AddLive extends React.Component { ...@@ -385,6 +388,7 @@ class AddLive extends React.Component {
CourseService.updateLiveCloudCourse(params).then((res) => { CourseService.updateLiveCloudCourse(params).then((res) => {
if (res.success) { if (res.success) {
message.success('更新成功'); message.success('更新成功');
routeHook.cancel()
window.RCHistory.push({ window.RCHistory.push({
pathname: `/live-course`, pathname: `/live-course`,
}); });
...@@ -515,19 +519,12 @@ class AddLive extends React.Component { ...@@ -515,19 +519,12 @@ class AddLive extends React.Component {
// 比较state的addLiveBasicInfo, addLiveClassInfo, addLiveIntroInfo和默认数据是否相等 // 比较state的addLiveBasicInfo, addLiveClassInfo, addLiveIntroInfo和默认数据是否相等
const { addLiveBasicInfo, addLiveClassInfo, addLiveIntroInfo } = this.state; const { addLiveBasicInfo, addLiveClassInfo, addLiveIntroInfo } = this.state;
if (!_.isEqual(addLiveBasicInfo, defaultBasicInfo) || !_.isEqual(addLiveClassInfo, defaultClassInfo) || !_.isEqual(addLiveIntroInfo, defaultIntroInfo)) { if (!_.isEqual(addLiveBasicInfo, defaultBasicInfo) || !_.isEqual(addLiveClassInfo, defaultClassInfo) || !_.isEqual(addLiveIntroInfo, defaultIntroInfo)) {
Modal.confirm({ console.log('ghjklkjh')
title: '确定要返回吗?',
content: '返回后,本次编辑的内容将不被保存',
okText: '确认返回',
cancelText: '留在本页',
icon: <span className='icon iconfont default-confirm-icon'>&#xe6f4;</span>,
onOk: () => {
window.RCHistory.push({ window.RCHistory.push({
pathname: `/live-course`, pathname: `/live-course`,
}); });
},
});
} else { } else {
routeHook.cancel()
window.RCHistory.push({ window.RCHistory.push({
pathname: `/live-course`, pathname: `/live-course`,
}); });
...@@ -541,7 +538,7 @@ class AddLive extends React.Component { ...@@ -541,7 +538,7 @@ class AddLive extends React.Component {
<Breadcrumbs navList={type == 'add' ? '新建直播课' : '编辑直播课'} goBack={this.handleGoBack} /> <Breadcrumbs navList={type == 'add' ? '新建直播课' : '编辑直播课'} goBack={this.handleGoBack} />
<div className='box'> <div className='box'>
<div className='show-tips'> <div className='show-tips'>
<ShowTips message='请遵守国家相关规定,切勿上传低俗色情、暴力恐怖、谣言诈骗、侵权盗版等相关内容,小麦企学院保有依据国家规定及平台规则进行处理的权利' /> <ShowTips message={`请遵守国家相关规定,切勿上传低俗色情、暴力恐怖、谣言诈骗、侵权盗版等相关内容,${window.brandName}保有依据国家规定及平台规则进行处理的权利`} />
</div> </div>
<div className='add-live-page__form'> <div className='add-live-page__form'>
<div className='basic-info__wrap'> <div className='basic-info__wrap'>
......
...@@ -2,7 +2,7 @@ import User from '@/common/js/user'; ...@@ -2,7 +2,7 @@ import User from '@/common/js/user';
import college from '@/common/lottie/college'; import college from '@/common/lottie/college';
import { PageControl, XMTable } from '@/components'; import { PageControl, XMTable } from '@/components';
import CourseService from '@/domains/course-domain/CourseService'; 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 React from 'react';
import { withRouter } from 'react-router-dom'; import { withRouter } from 'react-router-dom';
import dealTimeDuration from '../utils/dealTimeDuration'; import dealTimeDuration from '../utils/dealTimeDuration';
...@@ -11,7 +11,7 @@ class DataList extends React.Component { ...@@ -11,7 +11,7 @@ class DataList extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
const courseId = getParameterByName('id'); // 课程ID const courseId = getParameterByName('id'); // 课程ID
const type = getParameterByName('type'); // 来源: 大班直播 large 互动班课 interactive const type = getParameterByName('type'); // 来源: 大班直播 large 互动班课 interactive 企微直播 qiwei
this.state = { this.state = {
type, type,
teacherData: [], // 老师上课数据 teacherData: [], // 老师上课数据
...@@ -39,6 +39,21 @@ class DataList extends React.Component { ...@@ -39,6 +39,21 @@ class DataList extends React.Component {
current, current,
size, size,
}; };
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) => { CourseService.fetchUserData(params).then((res) => {
if (res.result) { if (res.result) {
const { records = [], current, size, total } = res.result; const { records = [], current, size, total } = res.result;
...@@ -52,10 +67,21 @@ class DataList extends React.Component { ...@@ -52,10 +67,21 @@ class DataList extends React.Component {
}); });
} }
}); });
}
}; };
// 获取老师上课数据 // 获取老师上课数据
fetchLecturerData = () => { fetchLecturerData = () => {
const { liveCourseId } = this.state; const { liveCourseId } = this.state;
if (this.state.type === "qiwei") {
CourseService.fetchWorkWXLecturerData({ liveCourseId }).then((res) => {
if (res.result) {
this.setState({
teacherData: res.result,
});
}
});
} else {
CourseService.fetchLecturerData({ liveCourseId }).then((res) => { CourseService.fetchLecturerData({ liveCourseId }).then((res) => {
if (res.result) { if (res.result) {
this.setState({ this.setState({
...@@ -63,8 +89,22 @@ class DataList extends React.Component { ...@@ -63,8 +89,22 @@ class DataList extends React.Component {
}); });
} }
}); });
}
}; };
studentTypeEnum = (type)=> {
if (type === "STUDENT") {
return "学员"
}
if (type === "NON_STUDENT") {
return "待加入"
}
if (type === "GUEST") {
return "游客"
}
}
// 进入直播次数列表 // 进入直播次数列表
getVisiterColumns() { getVisiterColumns() {
const columns = [ const columns = [
...@@ -159,12 +199,75 @@ class DataList extends React.Component { ...@@ -159,12 +199,75 @@ class DataList extends React.Component {
}, },
]; ];
return columns; const columnsWorkWX = [
{
title: '学员姓名',
dataIndex: 'name',
},
{
title: ()=> {
return (
<div>
学员类型
<Tooltip
title={()=> {
return <div>
<div>学员:已加入当前学院的企业员工</div>
<div>待加入:未加入当前学院的企业员工</div>
<div>游客:非企业员工</div>
<div>*企业员工以企业微信通讯录为准</div>
</div>
}}>
<i className='icon iconfont' style={{fontSize:"14px",fontWeight:"400"}}> &#xe61d;</i>
</Tooltip>
</div>
)
},
dataIndex: 'studentTypeEnum',
render: (text, record) => {
return <div>{this.studentTypeEnum(record.studentTypeEnum)}</div>;
},
},
{
title: '账号类型',
dataIndex: 'accountTypeEnum',
render: (text, record) => {
return record.accountTypeEnum === "ENTERPRISE_WECHAT" ? <span style={{color:"#5289FA"}}>企业微信</span> : <span style={{color:"#1DCC65"}}>微信</span>
},
},
{
title: '累计在线时长',
dataIndex: 'totalDuration',
render: (text, record) => {
//如无离开时间,就置空
return <span>{text ? dealTimeDuration(text) : '00:00:00'}</span>;
},
},
];
return this.state.type === "qiwei" ? columnsWorkWX : columns;
} }
// 学员导出5.0 // 学员导出5.0
handleExportV5 = () => { handleExportV5 = () => {
const { liveCourseId, storeId } = this.state; const { liveCourseId, storeId } = this.state;
if (this.state.type === "qiwei") {
CourseService.exportWorkWXStudentCourseData({
liveCourseId: liveCourseId,
exportLiveType: 'VISITOR',
storeId,
}).then((res) => {
const link = res.result;
this.setState({
link,
});
document.getElementById('loadExcel').click();
if (res.success) {
message.success('导出成功!');
}
});
} else {
CourseService.exportStudentCourseData({ CourseService.exportStudentCourseData({
liveCourseId: liveCourseId, liveCourseId: liveCourseId,
exportLiveType: 'VISITOR', exportLiveType: 'VISITOR',
...@@ -180,6 +283,8 @@ class DataList extends React.Component { ...@@ -180,6 +283,8 @@ class DataList extends React.Component {
message.success('导出成功!'); message.success('导出成功!');
} }
}); });
}
}; };
handleCheckEnterTimes = () => { handleCheckEnterTimes = () => {
...@@ -239,7 +344,7 @@ class DataList extends React.Component { ...@@ -239,7 +344,7 @@ class DataList extends React.Component {
}; };
render() { render() {
const { teacherData, studentData, current, size, total, loading, link } = this.state; const { teacherData, studentData, current, size, total, loading, link, type } = this.state;
return ( return (
<Spin spinning={loading}> <Spin spinning={loading}>
<a href={link} target='_blank' download id='loadExcel' style={{ position: 'absolute', left: '-10000px' }}> <a href={link} target='_blank' download id='loadExcel' style={{ position: 'absolute', left: '-10000px' }}>
...@@ -257,6 +362,8 @@ class DataList extends React.Component { ...@@ -257,6 +362,8 @@ class DataList extends React.Component {
</div> </div>
</div> </div>
{
type !== "qiwei" &&
<div className='times item-block'> <div className='times item-block'>
<div className={`times-num ${Number(teacherData.entryNum) > 0 ? 'can-click' : ''}`}> <div className={`times-num ${Number(teacherData.entryNum) > 0 ? 'can-click' : ''}`}>
{Number(teacherData.entryNum) > 0 ? ( {Number(teacherData.entryNum) > 0 ? (
...@@ -269,6 +376,8 @@ class DataList extends React.Component { ...@@ -269,6 +376,8 @@ class DataList extends React.Component {
</div> </div>
<div className='text'>进入直播间次数</div> <div className='text'>进入直播间次数</div>
</div> </div>
}
<div className='online-duration item-block'> <div className='online-duration item-block'>
<div className='duration'>{teacherData.totalDuration ? dealTimeDuration(teacherData.totalDuration) : '00:00:00'}</div> <div className='duration'>{teacherData.totalDuration ? dealTimeDuration(teacherData.totalDuration) : '00:00:00'}</div>
......
...@@ -21,6 +21,7 @@ class DataList extends React.Component { ...@@ -21,6 +21,7 @@ class DataList extends React.Component {
} }
render() { render() {
const type = window.getParameterByName("type")
return ( return (
<div className="page data-list"> <div className="page data-list">
<Breadcrumbs <Breadcrumbs
...@@ -35,9 +36,13 @@ class DataList extends React.Component { ...@@ -35,9 +36,13 @@ class DataList extends React.Component {
<CourseData></CourseData> <CourseData></CourseData>
</Tabs.TabPane> </Tabs.TabPane>
{
type !== "qiwei" &&
<Tabs.TabPane tab="回放记录" key="playbackData"> <Tabs.TabPane tab="回放记录" key="playbackData">
<PlaybackData></PlaybackData> <PlaybackData></PlaybackData>
</Tabs.TabPane> </Tabs.TabPane>
}
</Tabs> </Tabs>
</div> </div>
......
...@@ -38,7 +38,7 @@ ...@@ -38,7 +38,7 @@
.title { .title {
font-size: 16px; font-size: 16px;
font-family: PingFangSC-Medium, PingFang SC; font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500; font-weight: 600;
color: #333333; color: #333333;
margin-bottom: 16px; margin-bottom: 16px;
position: relative; position: relative;
...@@ -84,6 +84,7 @@ ...@@ -84,6 +84,7 @@
background: #ffffff; background: #ffffff;
border: 1px solid #e8e8e8; border: 1px solid #e8e8e8;
display: flex; display: flex;
justify-content: space-between;
align-items: center; align-items: center;
margin-bottom: 32px; margin-bottom: 32px;
.item-block { .item-block {
......
...@@ -28,7 +28,8 @@ class AddLiveBasic extends React.Component { ...@@ -28,7 +28,8 @@ class AddLiveBasic extends React.Component {
showSelectFileModal: false, showSelectFileModal: false,
cutImageBlob: null, cutImageBlob: null,
hasImgReady: false, // 图片是否上传成功 hasImgReady: false, // 图片是否上传成功
cropperInstace: null, cropperInstace:null,
courseNameLimit: props.courseNameLimit?props.courseNameLimit:40
} }
} }
componentWillUnmount() {} componentWillUnmount() {}
...@@ -105,20 +106,29 @@ class AddLiveBasic extends React.Component { ...@@ -105,20 +106,29 @@ class AddLiveBasic extends React.Component {
<span className='label'> <span className='label'>
<span className='require'>*</span>课程名称: <span className='require'>*</span>课程名称:
</span> </span>
<div id="courseName" style={{display:"inline-block"}}>
<Input <Input
className={_.find(this.props.exItems,(item)=>{return item === "courseName"})?"err":""}
value={courseName} value={courseName}
placeholder='请输入直播名称(40字以内)' placeholder={`请输入直播名称(${this.state.courseNameLimit}字以内)`}
maxLength={40} maxLength={this.state.courseNameLimit}
style={{ width: 240 }} style={{ width: 240 }}
onChange={(e) => { onChange={(e) => {
this.props.onChange('courseName', e.target.value) this.props.onChange('courseName', e.target.value)
}} }}
/> />
</div> </div>
</div>
<div className='course-cover'> <div className='course-cover'>
<span className='label'>封面图:</span> <span className='label'>封面图:</span>
<div className='course-cover__wrap'> <div className='course-cover__wrap'>
<div className='img-content'>
{isDefaultCover && <span className='tag'>默认图</span>}
<img src={coverUrl} />
</div>
</div>
<div className='opt-btns'> <div className='opt-btns'>
<Button <Button
onClick={() => { onClick={() => {
...@@ -133,23 +143,21 @@ class AddLiveBasic extends React.Component { ...@@ -133,23 +143,21 @@ class AddLiveBasic extends React.Component {
</span> </span>
<div className='tips'>建议尺寸1280*720px或16:9。封面图最大5M,支持jpg、jpeg和png。</div> <div className='tips'>建议尺寸1280*720px或16:9。封面图最大5M,支持jpg、jpeg和png。</div>
</div> </div>
<div className='img-content'>
{isDefaultCover && <span className='tag'>默认图</span>}
<img src={coverUrl} />
</div>
</div>
</div> </div>
<div className='course-catalog'> <div className='course-catalog'>
<span className='label'> <span className='label'>
<span className='require'>*</span>课程分类: <span className='require'>*</span>课程分类:
</span> </span>
<div id="categoryId" style={{display:"inline-block"}}>
<CourseCatalogSelect <CourseCatalogSelect
className={_.find(this.props.exItems,(item)=>{return item === "categoryId"})?"err":""}
value={categoryId} value={categoryId}
onChange={(value, label) => { onChange={(value, label) => {
this.handleChangeCatalogList(value, label) this.handleChangeCatalogList(value, label)
}} }}
/> />
</div> </div>
</div>
{showSelectFileModal && ( {showSelectFileModal && (
<SelectPrepareFileModal <SelectPrepareFileModal
key='basic' key='basic'
......
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
position: relative; position: relative;
.img-content { .img-content {
margin-top: 8px;
margin-right: 20px; margin-right: 20px;
width: 299px; width: 299px;
height: 169px; height: 169px;
...@@ -41,7 +40,7 @@ ...@@ -41,7 +40,7 @@
left: 8px; left: 8px;
} }
} }
}
.opt-btns { .opt-btns {
.default-btn { .default-btn {
margin-left: 14px; margin-left: 14px;
...@@ -64,10 +63,33 @@ ...@@ -64,10 +63,33 @@
} }
} }
} }
}
.course-catalog { .course-catalog {
margin: 20px 0 0 14px; margin: 20px 0 0 14px;
} }
//输入框异常项
.err.ant-input:hover {
border-color: #FF4F4F;
}
.err.ant-input:focus {
border-color: #FF4F4F !important;
box-shadow: 0 0 0 2px rgba(255,0,0,0.2);
}
.err.ant-input {
border-color: #FF4F4F;
}
//下拉选择异常项
.err.ant-select-focused:not(.ant-select-disabled).ant-select:not(.ant-select-customize-input) .ant-select-selector {
border-color: #FF4F4F;
box-shadow: 0 0 0 2px rgba(255,0,0,0.2);
}
.err.ant-select:not(.ant-select-disabled):hover {
.ant-select-selector {
border-color: #FF4F4F;
}
}
.err.ant-select:not(.ant-select-customize-input) .ant-select-selector {
border-color: #FF4F4F;
}
} }
.ant-cascader-menu-item-active:not(.ant-cascader-menu-item-disabled) { .ant-cascader-menu-item-active:not(.ant-cascader-menu-item-disabled) {
font-weight: normal !important; font-weight: normal !important;
......
...@@ -75,7 +75,7 @@ class AddLiveClass extends React.Component { ...@@ -75,7 +75,7 @@ class AddLiveClass extends React.Component {
// 获取助教老师列表 // 获取助教老师列表
getAssistantList = (current = 1, selectList) => { getAssistantList = (current = 1, selectList) => {
const { assistantQuery,assistantList} = this.state; const { assistantQuery,assistantList} = this.state;
const { assistantStoreUserId } = this.props.data; const { assistantStoreUserId } = this.props.data ? this.props.data:[];
const idList = selectList ? selectList : assistantStoreUserId; const idList = selectList ? selectList : assistantStoreUserId;
const _query = { const _query = {
...assistantQuery, ...assistantQuery,
......
import React, { useEffect, useState } from "react";
import { DatePicker, TimePicker, Select, Form, message } 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 [hasNext, setHasNext] = useState(false)
const [introduce, setIntroduce] = useState({content:props.introduce})
const [duration, setDuration] = useState(props.data.duration)
const [cusTime, setCusTime] = useState(false)
const [beginDate, setBeginDate] = useState(props.data.startTime===0?0:moment(props.data.startTime).startOf('day').valueOf())
const [beginTime, setBeginTime] = useState(props.data.startTime)
const [endDate, setEndDate] = useState((moment(props.data.endTime).startOf('day').valueOf()))
const [endTime, setEndTime] = useState(props.data.endTime)
const [teacherId, setTeacherId] = useState(props.data.teacherId)
const [remindTime, setRemindTime] = useState(props.data.remindTime)
// useEffect(()=> {
// setBeginTime(props.data.startTime)
// setBeginDate(props.data.startTime===0?0:moment(props.data.startTime).startOf('day').valueOf())
// if (props.data.startTime !== 0) {
// setEndTime(props.data.startTime+Number(props.data.duration)*1000)
// setEndDate(moment(props.data.startTime+Number(props.data.duration)*1000).startOf('day').valueOf())
// }
// setTeacherId(props.data.teacherId)
// setRemindTime(props.data.remindTime)
// },[props.data])
useEffect(()=> {
let intro = {content:props.introduce};
setIntroduce(intro)
},[props.introduce])
useEffect(()=> {
let query = {...defaultTeacherQuery,nickName:props.data.teacherName}
setTeacherQuery(query)
},[])
function disabledDate(current) {
// Can not select days before today and today
return current && current < moment().startOf('day');
}
//开始日期
function onBeginDateChange(date, dateString) {
if (date) {
// if (date.isBefore(moment())) {
// message.warning('开始日期不能早于当前日期')
// setBeginDate(moment().startOf('day').valueOf())
// } else {
let _begindate = date.startOf('day').valueOf();
let _begintime = beginTime === 0 ? moment().add(5,'minutes') : moment(beginTime)
let datetime = _begindate+(_begintime.hour()*60+_begintime.minute())*60*1000
setBeginTime(datetime)
props.onChange("beginTime",datetime)
setBeginDate(_begindate)
// }
} else {
setBeginDate(0)
}
}
function onBeginDateOK(date) {
console.log(date)
}
//开始时间
function onBeginTimeChange(time, dateString) {
let begin = beginDate+(time.hour()*60+time.minute())*60*1000
if (beginDate === 0) {
begin = time.valueOf()
}
setBeginTime(begin)
props.onChange("beginTime",begin)
}
function onBeginTimeOK(time) {
// if (time.isBefore(moment())) {
// message.warning('开始时间不能早于当前时间')
// return
// }
let begin = beginDate+(time.hour()*60+time.minute())*60*1000
if (beginDate === 0) {
begin = time.valueOf()
}
setBeginTime(begin)
props.onChange("beginTime",begin)
}
//结束日期
function onEndDateChange(date, dateString) {
if (date) {
let _endDate = date.startOf('day').valueOf()
let _endtime = moment(endTime)
let datetime = _endDate+(_endtime.hour()*60+_endtime.minute())*60*1000
setEndTime(datetime)
props.onChange("endTime",datetime)
setEndDate(_endDate)
} else {
setEndDate(0)
}
}
function onEndDateOK(date) {
}
//结束时间
function onEndTimeChange(time, dateString) {
// if (time.isSameOrBefore(moment(beginTime))) {
// message.warning('结束时间不能早于开始时间')
// return
// }
let end = endDate+(time.hour()*60+time.minute())*60*1000
if (endDate === 0) {
end = time.valueOf()
}
setEndTime(end)
props.onChange("endTime",end)
}
function onEndTimeOK(time) {
// if (time.isSameOrBefore(moment(beginTime))) {
// message.warning('结束时间不能早于开始时间')
// return
// }
let end = endDate+(time.hour()*60+time.minute())*60*1000
if (endDate === 0) {
end = time.valueOf()
}
setEndTime(end)
props.onChange("endTime",end)
}
function onDurationChange(value, option) {
if (value === 0) {
setCusTime(true)
props.onChange("endTime",new Date().getTime())
return
}
let d = value*60*1000;
setDuration(d)
props.onChange("endTime",beginTime+d)
}
function onTeacherChange(value, option) {
setTeacherId(value)
props.onChange("teacherId",{teacherId:value,teacherName:option ? option.children:undefined})
}
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) {
let _query = {
...teacherQuery
};
StoreService.getStoreUserBasicPage(_query).then((res) => {
const { result = {} } = res;
const { records = [], total = 0, hasNext } = result;
const list = _query.current > 1 ? teacherList.concat(records) : records;
setTeacherList(list)
setHasNext(hasNext)
});
}
useEffect(()=> {
getTeacherList()
},[teacherQuery])
// 滑动加载更多讲师列表
function handleScrollTeacherList(e) {
const container = e.target;
//判定元素是否滚动到底部
const scrollToBottom = container && container.scrollHeight <= container.clientHeight + container.scrollTop;
if (scrollToBottom && hasNext) {
let _teacherQuery = teacherQuery;
_teacherQuery.current = _teacherQuery.current + 1
setTeacherQuery({..._teacherQuery})
}
}
return (
<div className="AddLiveClassInfoWorkWX">
<div className="begin-time item">
<span className="label"><span className="require">*</span>开始时间:</span>
<div id="startTime" style={{display:"inline-block"}}>
<DatePicker
className={_.find(props.exItems,(item)=>{return item === "startTime"})?"err":""}
placeholder="请选择开始日期"
value={beginDate===0?undefined:moment(beginDate)}
onChange={onBeginDateChange}
onOk={onBeginDateOK}
disabledDate={disabledDate}
style={{width:"180px"}}
/>
<TimePicker
className={_.find(props.exItems,(item)=>{return item === "startTime"})?"err":""}
value={beginTime===0?undefined:moment(beginTime)}
onChange={onBeginTimeChange}
onOk={onBeginTimeOK}
allowClear={false}
format="HH:mm"
style={{width:"120px"}}
/>
<div style={{position:"absolute"}}></div>
</div>
</div>
<div className="duration-time item" id="odqboqwdq">
{
cusTime || props.type === "edit" ? (
<>
<span className="label"><span className="require">*</span>结束时间:</span>
<div id="endTime" style={{display:"inline-block"}}>
<DatePicker
className={_.find(props.exItems,(item)=>{return item === "endTime"})?"err":""}
placeholder="请选择结束日期"
value={endDate===0?undefined:moment(endDate)}
onChange={onEndDateChange}
onOk={onEndDateOK}
disabledDate={(current)=> {
return current && current < beginDate
}}
style={{width:"180px"}}
/>
<TimePicker
className={_.find(props.exItems,(item)=>{return item === "endTime"})?"err":""}
value={endTime === 0?moment().add(5,'minutes'):moment(endTime)}
onChange={onEndTimeChange}
onOk={onEndTimeOK}
allowClear={false}
format="HH:mm"
style={{width:"120px"}}
/>
</div>
</>
) : (
<>
<span className="label"><span className="require">*</span>时长:</span>
<Select onChange={onDurationChange} defaultValue={60} style={{width:"300px"}} getPopupContainer={()=> document.getElementById("odqboqwdq")} className="eerr">
<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" id="ieouwowerwe">
<span className="label"><span className="require">*</span>讲师:</span>
<div id="teacherId" style={{display:"inline-block"}}>
<Select
value={teacherId}
onChange={onTeacherChange}
className={_.find(props.exItems,(item)=>{return item === "teacherId"})?"err":""}
placeholder="请选择讲师"
disabled={!props.isEdit ? true: false}
filterOption={(input, option) => option}
getPopupContainer={()=> document.getElementById("ieouwowerwe")}
style={{width:"300px"}}
showSearch
allowClear
onPopupScroll={handleScrollTeacherList}
onSearch={(value)=> {
let query = {...teacherQuery}
query.nickName = value
query.current = 1
setTeacherQuery(query)
}}
onClear={()=> {
setTeacherQuery({
current: 1,
nickName: null,
size: 15
})
setTeacherId(undefined)
props.onChange("teacherId",{teacherId:undefined,teacherName:undefined})
}}
onDropdownVisibleChange={(open)=> {
if (open) {
let query = {...teacherQuery,nickName:null}
setTeacherQuery(query)
}
}}
>
{
teacherList.map((item, index) => {
return (
<Select.Option value={item.id} key={item.id}>{item.nickName}</Select.Option>
);
})
}
</Select>
</div>
</div>
<div className="remind-time item" id="jfjfiemc">
<span className="label"><span className="require">*</span>提醒时间:</span>
<Select
onChange={onRemindChange}
placeholder={"15分钟前"}
style={{width:"180px"}}
getPopupContainer={()=> document.getElementById("jfjfiemc")}
>
<Option value={0}></Option>
<Option value={300}>5分钟前</Option>
<Option value={900}>15分钟前</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" id="intro">
<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;
margin-bottom: 98px;
.remind-time {
.ant-select-single.ant-select-show-arrow .ant-select-selection-placeholder {
color: #333333;
}
}
.item {
margin: 24px 0;
.label {
display: inline-block;
text-align: right;
width: 100px;
.require {
color: red;
}
}
//日期时间选择异常项
.err.ant-picker-focused {
border-color: #FF4F4F;
box-shadow: 0 0 0 2px rgba(255,0,0,0.2);
}
.err.ant-picker:hover {
border-color: #FF4F4F;
}
.err.ant-picker {
border-color: #FF4F4F;
}
}
.introduce {
display: flex;
}
.ant-select-item-option-selected:not(.ant-select-item-option-disabled) {
color: #2966FF;
}
// .eerr .ant-select-focused:not(.ant-select-disabled) .ant-select:not(.ant-select-customize-input) {
// .ant-select-selector {
// border-color: red;
// box-shadow: 0 0 0 2px rgba(255,0,0,0.2);
// }
// }
// .eerr .ant-select:not(.ant-select-disabled):hover {
// .ant-select-selector {
// border-color: red;
// }
// }
//下拉选择异常项
.err.ant-select-focused:not(.ant-select-disabled).ant-select:not(.ant-select-customize-input) .ant-select-selector {
border-color: #FF4F4F;
box-shadow: 0 0 0 2px rgba(255,0,0,0.2);
}
.err.ant-select:not(.ant-select-disabled):hover {
.ant-select-selector {
border-color: #FF4F4F;
}
}
.err.ant-select:not(.ant-select-customize-input) .ant-select-selector {
border-color: #FF4F4F;
}
//输入框异常项
.err.ant-input:hover {
border-color: #FF4F4F;
}
.err.ant-input:focus {
border-color: #FF4F4F;
box-shadow: 0 0 0 2px rgba(255,0,0,0.2);
}
.err.ant-input {
border-color: #FF4F4F;
}
}
\ No newline at end of file
...@@ -136,7 +136,7 @@ class AddLiveIntro extends React.Component { ...@@ -136,7 +136,7 @@ class AddLiveIntro extends React.Component {
<span className='label'>观看设置:</span> <span className='label'>观看设置:</span>
<div className='content'> <div className='content'>
<Switch checked={whetherVisitorsJoin === 'NO' ? true : false} onChange={this.whetherVisitorsJoinChange} /> <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> </div>
<div className='warmup'> <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, useRef, 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 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: null, //讲师的Id
courseName: '', //课程名称
duration: 3600, //直播时长默认1小时
remindTime: 900, //提醒时间
// startTime: new Date().getTime() + 300000,
startTime: 0
};
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 [getInfo, setGetInfo] = useState(false)
const [previewLiveCourseModal, setPreviewLiveCourseModal] = useState()
const [exItems, setExItems] = useState([])
const [enableSubmit, setEnableSubmit] = useState(true)
useEffect(()=> {
routeHook.addSaveCase();
if (type === 'edit') {
getCourseDetail();
}else{
setGetInfo(true)
}
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,
endTime: startTime+Number(duration)*1000,
remindTime,
};
setEndTime(startTime+Number(duration)*1000)
// 晚于开课前30分钟
if (new Date().getTime() > startTime - 1800000) {
setIsEdit(false)
}
setLoadintroduce(!hasIntro)
setLoading(false)
setBasicInfo(_basicInfo)
setClassInfo(_classInfo)
setCourseState(courseState)
if (!hasIntro) {
setGetInfo(true)
}
});
};
//获取简介
function getIntroduce(key, url) {
$.ajax({
data: {},
type: 'GET',
url,
contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
success: (res) => {
setLoadintroduce(true)
setIntroduce(res)
setGetInfo(true)
},
error: () => {
message.warning('获取简介失败');
},
});
};
// 修改基本信息
function handleChangeBasicInfo(field, value) {
let binfo = {...basicInfo}
binfo[field] = value
setBasicInfo(binfo)
};
//课程信息变更回调
function onClassInfoChange(field, value) {
let classinfo = {...classInfo}
console.log(field,value)
switch (field) {
case 'intro':
setIntroduce(value)
console.log(value.length)
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.teacherId
classinfo.teacherName = value.teacherName
setClassInfo(classinfo)
break;
case 'remindTime':
classinfo.remindTime = value
setClassInfo(classinfo)
break;
default:
console.log("NULL")
}
}
// 完成创建/编辑
function handleSubmit() {
setExItems([])
//过期判断
if (User.getExpirationTime() && moment().valueOf() > Number(User.getExpirationTime())) {
Modal.warning({
title: '服务已到期',
content: `当前企业购买的${window.brandName}服务已到期,如需继续使用学院功能,请尽快续费购买`,
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;
}
handleValidate().then((res) => {
if (!res) return;
//上传简介
Upload.uploadTextToOSS(
introduce,
`${randomString()}.txt`,
(introduceId) => {
submitRemote({ introduceId, id });
},
() => message.warning('上传课程简介失败')
);
});
};
function submitRemote({ introduceId, id }) {
setEnableSubmit(false)
routeHook.cancel()
if (type === 'add') {
if (endTime !== 0) {
classInfo.duration = String((endTime - classInfo.startTime)/1000)
}
const params = {
...classInfo,
operatorId:User.getUserId(),
introduceId,
storeId: User.getStoreId(),
...basicInfo
};
CourseService.createWorkWXLiveCourse(params).then((res) => {
setEnableSubmit(true)
if (res.success) {
message.success('新建成功');
Bus.trigger('freshCourseList')
window.RCHistory.push({
pathname: `/live-course`,
});
}
})
.catch((err)=> {
setEnableSubmit(true)
});
} else {
if (endTime !== 0) {
classInfo.duration = String((endTime - classInfo.startTime)/1000)
}
const params = {
...classInfo,
operatorId:User.getUserId(),
introduceId,
storeId: User.getStoreId(),
...basicInfo,
liveCourseId: id
};
CourseService.updateWorkWXLiveCourse(params).then((res) => {
setEnableSubmit(true)
if (res.success) {
Bus.trigger('freshCourseList')
message.success('更新成功');
window.RCHistory.push({
pathname: `/live-course`,
});
}
})
.catch((err)=> {
setEnableSubmit(true)
});
}
};
function handleValidate() {
return new Promise((resolve) => {
let _exitem = []
if (_.isEmpty(basicInfo.courseName)) {
_exitem.push("courseName")
}
if (_.isEmpty(basicInfo.categoryId)) {
_exitem.push("categoryId")
}
if (!classInfo.startTime) {
_exitem.push("startTime")
}
if (classInfo.startTime < new Date().getTime()) {
_exitem.push("startTime")
}
if (endTime !== 0 && (endTime < classInfo.startTime)) {
_exitem.push("endTime")
}
if (_.isEmpty(classInfo.teacherId)) {
_exitem.push("teacherId")
}
if (editorTextLength > 1000) {
_exitem.push("intro")
}
setExItems(_exitem)
if (_.isEmpty(basicInfo.courseName)) {
message.warning("课程名称不能为空")
let item = document.getElementById("courseName")
if (item) {
item.scrollIntoView(true)
}
resolve(false)
return
}
if (_.isEmpty(basicInfo.categoryId)) {
message.warning("课程分类未选择")
let item = document.getElementById("categoryId")
if (item) {
item.scrollIntoView(true)
}
resolve(false)
return
}
if (!classInfo.startTime) {
message.warning("未设置开始时间")
let item = document.getElementById("startTime")
if (item) {
item.scrollIntoView(true)
}
resolve(false)
return
}
if (classInfo.startTime < new Date().getTime()) {
message.warning("开始时间不能早于现在")
let item = document.getElementById("startTime")
if (item) {
item.scrollIntoView(true)
}
resolve(false)
return
}
if (endTime !== 0 && (endTime < classInfo.startTime)) {
message.warning("结束时间不能早于开始时间")
let item = document.getElementById("endTime")
if (item) {
item.scrollIntoView(true)
}
resolve(false)
return
}
if (_.isEmpty(classInfo.teacherId)) {
message.warning("未设置讲师")
let item = document.getElementById("teacherId")
if (item) {
item.scrollIntoView(true)
}
resolve(false)
return
}
if (editorTextLength > 1000) {
message.warning("直播简介超过1000个字")
let item = document.getElementById("intro")
if (item) {
item.scrollIntoView(true)
}
resolve(false)
return
}
resolve(true)
});
};
// 显示预览课程弹窗
function handleShowPreviewModal() {
// const { addLiveBasicInfo, addLiveClassInfo, addLiveIntroInfo, type, courseState } = this.state;
const previewLiveCourseModal = (
<PreviewCourseModal
bizType="qiwei"
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) || introduce.length > 0) {
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={`请遵守国家相关规定,切勿上传低俗色情、暴力恐怖、谣言诈骗、侵权盗版等相关内容,${window.brandName}保有依据国家规定及平台规则进行处理的权利`} />
</div>
<div className='add-live-page__form'>
<div className='basic-info__wrap'>
<div className='title'>基本信息<span style={{marginLeft:"24px",color:"#2966FF",fontSize:"14px"}}>温馨提示:在直播间可控制回放录制功能。</span></div>
<AddLiveBasic isEdit={isEdit} pageType={type} data={basicInfo} onChange={handleChangeBasicInfo} courseNameLimit={20} exItems={exItems}/>
</div>
<div className='class-info__wrap'>
<div className='title'>上课信息</div>
{/* <AddLiveClass isEdit={isEdit} pageType={type} data={{ ...addLiveClassInfo, id }} onChange={handleChangeClassInfo} /> */}
{
getInfo && <AddLiveClassInfoWorkWX type={type} data={classInfo} isEdit={isEdit} introduce={introduce} onChange={onClassInfoChange} exItems={exItems}/>
}
</div>
</div>
</div>
<div className='footer shrink-footer'>
<Button onClick={handleGoBack}>取消</Button>
<Button onClick={handleShowPreviewModal}>预览</Button>
<Button type='primary' onClick={_.debounce(() => handleSubmit(), 3000, true)} disabled={!enableSubmit}>
{enableSubmit?"保存":"正在提交"}
</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:25px;
}
.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
...@@ -156,6 +156,7 @@ class GraphicsEditor extends React.Component { ...@@ -156,6 +156,7 @@ class GraphicsEditor extends React.Component {
message.warning(`内容过长,不能超过${maxLimit}字`); message.warning(`内容过长,不能超过${maxLimit}字`);
} }
Bus.trigger('editorLimit', textLength, editorType); Bus.trigger('editorLimit', textLength, editorType);
console.log(onChange,html, this.state.textLength)
onChange(html, this.state.textLength); onChange(html, this.state.textLength);
}); });
}; };
......
...@@ -14,6 +14,7 @@ import moment from 'moment' ...@@ -14,6 +14,7 @@ import moment from 'moment'
import StoreService from '@/domains/store-domain/storeService' import StoreService from '@/domains/store-domain/storeService'
import User from '@/common/js/user' import User from '@/common/js/user'
import './LiveCourseFilter.less' import './LiveCourseFilter.less'
import { brandLiveName } from '@/domains/brand/constants'
const { Search } = Input const { Search } = Input
const { Option } = Select const { Option } = Select
...@@ -24,6 +25,7 @@ const defaultQuery = { ...@@ -24,6 +25,7 @@ const defaultQuery = {
teacherId: null, teacherId: null,
courseState: null, courseState: null,
shelfState: null, shelfState: null,
thirdPartType: null
} }
const defaultTeacherQuery = { const defaultTeacherQuery = {
size: 10, size: 10,
...@@ -50,6 +52,7 @@ class LiveCourseFilter extends React.Component { ...@@ -50,6 +52,7 @@ class LiveCourseFilter extends React.Component {
current, current,
size: 10, size: 10,
} }
StoreService.getStoreUserBasicPage(_query).then((res) => { StoreService.getStoreUserBasicPage(_query).then((res) => {
const { result = {} } = res const { result = {} } = res
const { records = [], total = 0, hasNext } = result const { records = [], total = 0, hasNext } = result
...@@ -104,7 +107,7 @@ class LiveCourseFilter extends React.Component { ...@@ -104,7 +107,7 @@ class LiveCourseFilter extends React.Component {
delete query.endTime delete query.endTime
} else { } else {
query.startTime = dates[0]?.startOf('day').valueOf() query.startTime = dates[0]?.startOf('day').valueOf()
query.endTime = dates[0]?.endOf('day').valueOf() query.endTime = dates[1]?.endOf('day').valueOf()
} }
this.setState( this.setState(
{ {
...@@ -150,6 +153,7 @@ class LiveCourseFilter extends React.Component { ...@@ -150,6 +153,7 @@ class LiveCourseFilter extends React.Component {
courseState: undefined, courseState: undefined,
current: 1, current: 1,
shelfState: null, shelfState: null,
thirdPartType: null
}, },
}, },
() => { () => {
...@@ -159,7 +163,7 @@ class LiveCourseFilter extends React.Component { ...@@ -159,7 +163,7 @@ class LiveCourseFilter extends React.Component {
} }
render() { 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 { expandFilter, teacherList, teacherQuery } = this.state
const { teacherId: _teahcerId } = {} const { teacherId: _teahcerId } = {}
const isTeacher = !!_teahcerId // 判断是否是老师身份 const isTeacher = !!_teahcerId // 判断是否是老师身份
...@@ -199,7 +203,7 @@ class LiveCourseFilter extends React.Component { ...@@ -199,7 +203,7 @@ class LiveCourseFilter extends React.Component {
</div> </div>
{User.getUserRole() !== 'CloudLecturer' && ( {User.getUserRole() !== 'CloudLecturer' && (
<div className='search-condition__item'> <div className='search-condition__item'>
<span>讲师:</span> <span style={{width:"70px",display:"inline-block",textAlign:"right"}}>讲师:</span>
<Select <Select
placeholder='请选择讲师' placeholder='请选择讲师'
style={{ width: 'calc(100% - 70px)' }} style={{ width: 'calc(100% - 70px)' }}
...@@ -295,6 +299,37 @@ class LiveCourseFilter extends React.Component { ...@@ -295,6 +299,37 @@ class LiveCourseFilter extends React.Component {
</Select> </Select>
</div> </div>
)} )}
{expandFilter && (
<div className='search-condition__item'>
<span className='live-type'>直播方式:</span>
<Select
style={{ width: 'calc(100% - 70px)' }}
placeholder='请选择'
allowClear={true}
onClear={(value) => {
this.setState(
{
query: {...this.state.query,thirdPartType:null}
},
() => {
this.props.onChange(this.state.query)
}
)
}}
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'>{brandLiveName}</Option>
</Select>
</div>
)}
</div> </div>
<div className='reset-fold-area'> <div className='reset-fold-area'>
......
...@@ -7,22 +7,26 @@ ...@@ -7,22 +7,26 @@
*/ */
import User from '@/common/js/user'; import User from '@/common/js/user';
import WechatApi from '@/common/js/wechatApi';
import college from '@/common/lottie/college'; import college from '@/common/lottie/college';
import { PageControl, XMTable } from '@/components'; import { PageControl, XMTable } from '@/components';
import DownloadLiveModal from '@/components/DownloadLiveModal'; import DownloadLiveModal from '@/components/DownloadLiveModal';
import { isWorkWx, isMac } from '@/core/platform';
import BaseService from '@/domains/basic-domain/baseService'; import BaseService from '@/domains/basic-domain/baseService';
import { LIVE_SHARE } from '@/domains/course-domain/constants'; import { LIVE_SHARE } from '@/domains/course-domain/constants';
import CourseService from '@/domains/course-domain/CourseService'; import CourseService from '@/domains/course-domain/CourseService';
import { QuestionCircleOutlined } from '@ant-design/icons'; import { QuestionCircleOutlined } from '@ant-design/icons';
import { Dropdown, message, Modal, Switch, Tooltip } from 'antd'; import { Dropdown, message, Badge, Modal, Switch, Tooltip, Menu } from 'antd';
import React from 'react'; import React, { Fragment } from 'react';
import { Route, withRouter } from 'react-router-dom'; import { Route, withRouter } from 'react-router-dom';
import _ from 'underscore'; import _ from 'underscore';
import DataList from '../DataList/DataList'; import DataList from '../DataList/DataList';
import ManageCoursewareModal from '../modal/ManageCoursewareModal'; import ManageCoursewareModal from '../modal/ManageCoursewareModal';
import RelatedPlanModal from '../modal/RelatedPlanModal'; import RelatedPlanModal from '../modal/RelatedPlanModal';
import ShareLiveModal from '../modal/ShareLiveModal'; import ShareLiveModal from '../modal/ShareLiveModal';
import Bus from '@/core/bus';
import './LiveCourseList.less'; import './LiveCourseList.less';
import { brandLiveName } from '@/domains/brand/constants';
const { confirm } = Modal; const { confirm } = Modal;
const courseStateShow = { const courseStateShow = {
...@@ -62,7 +66,10 @@ class LiveCourseList extends React.Component { ...@@ -62,7 +66,10 @@ class LiveCourseList extends React.Component {
this.parseColumns(); this.parseColumns();
} }
componentDidMount() { componentDidMount() {
this.getDownloadVersion(); this.getDownloadVersion()
Bus.bind('freshCourseList',()=>{
this.refreshCourseList()
})
} }
// 显示分享弹窗 // 显示分享弹窗
handleShowShareModal = (item, needStr = false) => { handleShowShareModal = (item, needStr = false) => {
...@@ -112,9 +119,9 @@ class LiveCourseList extends React.Component { ...@@ -112,9 +119,9 @@ class LiveCourseList extends React.Component {
// 前往上课数据页面 // 前往上课数据页面
handleLinkToClassData = (item) => { handleLinkToClassData = (item) => {
const { match } = this.props; const { match } = this.props;
let type = item.thirdPartType === "WECHAT" ? "qiwei" : "large"
window.RCHistory.push({ 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 = () => { parseColumns = () => {
...@@ -124,7 +131,7 @@ class LiveCourseList extends React.Component { ...@@ -124,7 +131,7 @@ class LiveCourseList extends React.Component {
columns = [ columns = [
{ {
title: '直播课', title: '直播课',
width: '23%', width: '260px',
key: 'course', key: 'course',
fixed: 'left', fixed: 'left',
dataIndex: 'courseName', dataIndex: 'courseName',
...@@ -158,11 +165,6 @@ class LiveCourseList extends React.Component { ...@@ -158,11 +165,6 @@ class LiveCourseList extends React.Component {
<span className='course-time'> <span className='course-time'>
{window.formatDate('YYYY-MM-DD H:i', parseInt(record.startTime))}~{window.formatDate('H:i', parseInt(record.endTime))} {window.formatDate('YYYY-MM-DD H:i', parseInt(record.startTime))}~{window.formatDate('H:i', parseInt(record.endTime))}
</span> </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>
<div className='teacher-assistant'> <div className='teacher-assistant'>
<Choose> <Choose>
...@@ -214,6 +216,28 @@ class LiveCourseList extends React.Component { ...@@ -214,6 +216,28 @@ class LiveCourseList extends React.Component {
}, },
}, },
{ {
title: '上课状态',
width: '115px',
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" ? "企微直播":`${brandLiveName}`}</div>;
},
},
{
title: '课程分类', title: '课程分类',
width: '10%', width: '10%',
key: 'couseCatalog', key: 'couseCatalog',
...@@ -224,7 +248,7 @@ class LiveCourseList extends React.Component { ...@@ -224,7 +248,7 @@ class LiveCourseList extends React.Component {
}, },
{ {
title: '课件管理', title: '课件管理',
width: '8%', width: '75px',
key: 'courseware', key: 'courseware',
dataIndex: 'courseware', dataIndex: 'courseware',
render: (val, item) => { render: (val, item) => {
...@@ -277,7 +301,7 @@ class LiveCourseList extends React.Component { ...@@ -277,7 +301,7 @@ class LiveCourseList extends React.Component {
</Tooltip> </Tooltip>
</span> </span>
), ),
width: '9%', width: '100px',
key: 'shelfState', key: 'shelfState',
dataIndex: 'shelfState', dataIndex: 'shelfState',
render: (val, item, index) => { render: (val, item, index) => {
...@@ -293,7 +317,7 @@ class LiveCourseList extends React.Component { ...@@ -293,7 +317,7 @@ class LiveCourseList extends React.Component {
}, },
{ {
title: '创建时间', title: '创建时间',
width: '9%', width: '170px',
key: 'created', key: 'created',
dataIndex: 'created', dataIndex: 'created',
sorter: true, sorter: true,
...@@ -315,7 +339,7 @@ class LiveCourseList extends React.Component { ...@@ -315,7 +339,7 @@ class LiveCourseList extends React.Component {
<Tooltip title={this.handlePlanName(record.relatedPlanList)} placement='top' arrowPointAtCenter> <Tooltip title={this.handlePlanName(record.relatedPlanList)} placement='top' arrowPointAtCenter>
{record.relatedPlanList.map((item, index) => { {record.relatedPlanList.map((item, index) => {
return ( return (
<span> <span key={index}>
{item.planName} {index < record.relatedPlanList.length - 1 && <span></span>}{' '} {item.planName} {index < record.relatedPlanList.length - 1 && <span></span>}{' '}
</span> </span>
); );
...@@ -342,30 +366,53 @@ class LiveCourseList extends React.Component { ...@@ -342,30 +366,53 @@ class LiveCourseList extends React.Component {
{(item.courseState === 'UN_START' || item.courseState === 'STARTING') && {(item.courseState === 'UN_START' || item.courseState === 'STARTING') &&
(item.teacherId === User.getUserId() || _.pluck(item.admins, 'adminId').includes(User.getUserId())) && ( (item.teacherId === User.getUserId() || _.pluck(item.admins, 'adminId').includes(User.getUserId())) && (
<> <>
{
isMac() && item.thirdPartType === "WECHAT" ? (
<Tooltip title="请使用windows电脑进入直播间" placement="left">
<div style={{fontSize:"14px",color:"#999999"}}>
进入直播间
</div>
</Tooltip>
):(
<div <div
key='enter_live_room1' key='enter_live_room1'
className='operate__item' className='operate__item'
onClick={() => { onClick={() => {
this.handleEnterLiveRoom(item); this.handleEnterLiveRoom(item)
}}> }}>
进入直播间 进入直播间
</div> </div>
)
}
<span className='operate__item split' key='view_play_back_split'> <span className='operate__item split' key='view_play_back_split'>
{' '} {' '}
|{' '} |{' '}
</span> </span>
</> </>
)} )}
{item.courseState === 'FINISH' && item.haveRecord === 'YES' && ( {item.courseState === 'FINISH' && (
<> <>
{
item.haveRecord === 'YES' ? (
<div <div
key='view_play_back' key='view_play_back'
className='operate__item' className='operate__item'
onClick={() => { onClick={() => {
this.handleViewPlayBack(item); this.handleViewPlayBack(item)
}}> }}>
查看回放 查看回放
</div> </div>
) : (
<Tooltip title="该直播未录制回放" placement="left">
<div style={{fontSize:"14px",color:"#999999"}}>
查看回放
</div>
</Tooltip>
)
}
<span className='operate__item split' key='view_play_back_split'> <span className='operate__item split' key='view_play_back_split'>
{' '} {' '}
|{' '} |{' '}
...@@ -416,7 +463,7 @@ class LiveCourseList extends React.Component { ...@@ -416,7 +463,7 @@ class LiveCourseList extends React.Component {
columns = [ columns = [
{ {
title: '直播课', title: '直播课',
width: '25%', width: '260px',
key: 'course', key: 'course',
dataIndex: 'courseName', dataIndex: 'courseName',
render: (val, record) => { render: (val, record) => {
...@@ -446,11 +493,6 @@ class LiveCourseList extends React.Component { ...@@ -446,11 +493,6 @@ class LiveCourseList extends React.Component {
<span className='course-time'> <span className='course-time'>
{window.formatDate('YYYY-MM-DD H:i', parseInt(record.startTime))}~{window.formatDate('H:i', parseInt(record.endTime))} {window.formatDate('YYYY-MM-DD H:i', parseInt(record.startTime))}~{window.formatDate('H:i', parseInt(record.endTime))}
</span> </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>
<div className='teacher-assistant'> <div className='teacher-assistant'>
<Choose> <Choose>
...@@ -549,7 +591,7 @@ class LiveCourseList extends React.Component { ...@@ -549,7 +591,7 @@ class LiveCourseList extends React.Component {
}, },
{ {
title: '创建时间', title: '创建时间',
width: '9%', width: '170px',
key: 'created', key: 'created',
dataIndex: 'created', dataIndex: 'created',
sorter: true, sorter: true,
...@@ -614,6 +656,66 @@ class LiveCourseList extends React.Component { ...@@ -614,6 +656,66 @@ class LiveCourseList extends React.Component {
}; };
renderMoreOperate = (item) => { renderMoreOperate = (item) => {
let now = new Date().getTime()
if (item.thirdPartType === "WECHAT") {
return (
<Menu
onClick={({key})=> {
if (key === "link") {
this.handleRelatedModalShow(item)
} else if (key === "edit") {
this.toEditCoursePage(item)
} else if (key === "del") {
this.handleDelete(item)
}
}}
>
{
item.thirdPartType === "WECHAT" &&
<Tooltip placement="left" title="企微直播,暂不支持关联培训任务">
<Menu.Item style={{color:"#999999"}}>
关联培训计划
</Menu.Item>
</Tooltip>
}
{
item.thirdPartType !== "WECHAT" &&
<Menu.Item disabled={!(User.getUserRole() === 'CloudManager' || User.getUserRole() === 'StoreManager')} key="link">
关联培训计划
</Menu.Item>
}
{
(item.courseState === "STARTING" || item.courseState === "FINISH") &&
<Tooltip placement="left" title={`${item.courseState === "STARTING"?"直播已开始,不能编辑":"直播已结束,不能编辑"}`}>
<Menu.Item style={{color:"#999999"}}>
编辑
</Menu.Item>
</Tooltip>
}
{
item.courseState !== "STARTING" && item.courseState !== "FINISH" &&
<Menu.Item key="edit">
编辑
</Menu.Item>
}
{
(item.courseState === "STARTING" || ((now > item.startTime && now < item.endTime) && item.courseState !== "FINISH")) &&
<Tooltip placement="left" title={item.courseState === "STARTING"?"直播进行中,不能删除":"已到预定时间,无法删除"}>
<Menu.Item style={{color:"#999999"}}>
删除
</Menu.Item>
</Tooltip>
}
{
(item.courseState !== "STARTING" && ((now < item.startTime || now > item.endTime) || item.courseState === "FINISH")) &&
<Menu.Item key="del">
删除
</Menu.Item>
}
</Menu>
)
}
return ( return (
<div className='live-course-more-menu'> <div className='live-course-more-menu'>
{(User.getUserRole() === 'CloudManager' || User.getUserRole() === 'StoreManager') && ( {(User.getUserRole() === 'CloudManager' || User.getUserRole() === 'StoreManager') && (
...@@ -651,23 +753,86 @@ class LiveCourseList extends React.Component { ...@@ -651,23 +753,86 @@ class LiveCourseList extends React.Component {
const params = { const params = {
liveCourseId: item.liveCourseId, 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) => { CourseService.delLiveCloudCourse(params).then((res) => {
if (res.success) { if (res.success) {
message.success('已删除'); message.success('已删除');
this.props.onChange(); this.props.onChange();
} }
}); });
}
}; };
toEditCoursePage = (item) => { toEditCoursePage = (item) => {
if (item.thirdPartType === "WECHAT") {
window.RCHistory.push({
pathname: `/live-course/createqwcourse?type=edit&id=${item.liveCourseId}`,
});
} else {
window.RCHistory.push({ window.RCHistory.push({
pathname: `/create-live-course?type=edit&id=${item.liveCourseId}`, pathname: `/create-live-course?type=edit&id=${item.liveCourseId}`,
}); });
}
}; };
refreshCourseList = () => { refreshCourseList = () => {
this.props.onChange(this.props.query); this.props.onChange(this.props.query);
}; };
//进入直播间 //进入直播间
handleEnterLiveRoom = (item) => { handleEnterLiveRoom = (item) => {
if (item.thirdPartType === "WECHAT") {
//进入企微直播间
if (!isWorkWx()) {
Modal.warning({
title: '提示',
content: (
<Fragment>
<div>请使用企业微信进入直播间</div>
<div style={{color:"#999999"}}>备注:Mac版企业微信暂不支持进入直播间</div>
</Fragment>
)
})
return
}
if (isMac()) {
Modal.warning({
title:"提示",
content:"请使用windows客户端打开"
})
return
}
CourseService.getWorkWXLiveCourseDetail({
liveCourseId: item.liveCourseId,
}).then((res) => {
const {
courseState
} = res.result;
if (courseState === "FINISH") {
Modal.warning({
title:"刷新页面",
content:"该课程已结束,请查看回放"
})
} else {
WechatApi.enterLiveRoom(item.livingId).then((res)=> {
console.log(res)
}).catch((err)=> {
Modal.warning({
title:"提示",
content: err
})
})
}
})
return
}
if (item.startTime - Date.now() > 1800000) { if (item.startTime - Date.now() > 1800000) {
Modal.warning({ Modal.warning({
title: '你来得太早了', title: '你来得太早了',
...@@ -722,6 +887,33 @@ class LiveCourseList extends React.Component { ...@@ -722,6 +887,33 @@ class LiveCourseList extends React.Component {
}); });
} }
handleViewPlayBack = (item) => { handleViewPlayBack = (item) => {
if (item.thirdPartType === "WECHAT") {
if (!isWorkWx()) {
Modal.warning({
title:"提示",
content:"请使用企业微信进入回放"
})
return
}
if (item.startTime + 15*24*60*60*1000 < new Date().getTime()) {
Modal.warning({
title: '提示',
content: "该直播课的回放视频已失效",
});
return
}
WechatApi.replayLiving(item.livingId)
.then((res)=> {
console.log("进入企微回放")
})
.catch((err)=> {
Modal.warning({
title: '提示',
content: err,
});
})
return
}
let htmlUrl; let htmlUrl;
if (item.teacherId === User.getUserId()) { if (item.teacherId === User.getUserId()) {
htmlUrl = `${LIVE_SHARE}replay/${item.liveCourseId}?teacherId=${User.getUserId()}&id=${User.getStoreId()}`; htmlUrl = `${LIVE_SHARE}replay/${item.liveCourseId}?teacherId=${User.getUserId()}&id=${User.getStoreId()}`;
......
...@@ -9,34 +9,70 @@ ...@@ -9,34 +9,70 @@
import React from 'react'; import React from 'react';
import { Button, Modal, message } from 'antd'; import { Button, Modal, message } from 'antd';
import Service from '@/common/js/service'; import Service from '@/common/js/service';
import { withRouter ,Route} from "react-router-dom";
import './liveCourseOpt.less'; import './liveCourseOpt.less';
import BaseService from "@/domains/basic-domain/baseService"; import BaseService from "@/domains/basic-domain/baseService";
import CreateWorkWXCourse from './CreateWorkWXCourse'
import User from '@/common/js/user' import User from '@/common/js/user'
import LiveModeSelect from './LiveModeSelect';
class LiveCourseOpt extends React.Component { class LiveCourseOpt extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
isMac: /macintosh|mac os x/i.test(navigator.userAgent), isMac: /macintosh|mac os x/i.test(navigator.userAgent),
showModeSelect: false,
} }
} }
handleCreateLiveCouese = ()=>{ handleCreateLiveCouese = ()=>{
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({ window.RCHistory.push({
pathname: '/create-live-course?type=add', 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`)
}
// 下载直播客户端 // 下载直播客户端
handleDownloadClient = () => { handleDownloadClient = () => {
const { isMac } = this.state; const { isMac } = this.state;
const BRAND = process.env.BRAND;
// 判断学员系统 // 判断学员系统
let platform; let platform;
if(!isMac){ if (!isMac) {
platform = 1 platform = 1
} else { } else {
platform = 4 platform = 4
} }
BaseService BaseService
.getLastedVersion({ model: 5, platform}) .getLastedVersion({ model: 5, platform })
.then((res) => { .then((res) => {
const a = document.createElement("a"); const a = document.createElement("a");
document.body.appendChild(a); document.body.appendChild(a);
...@@ -44,20 +80,25 @@ class LiveCourseOpt extends React.Component { ...@@ -44,20 +80,25 @@ class LiveCourseOpt extends React.Component {
a.click(); a.click();
document.body.removeChild(a); document.body.removeChild(a);
}) })
} }
render() { render() {
const userRole = User.getUserRole(); const userRole = User.getUserRole();
const { match } = this.props;
return ( return (
<div className="live-course-opt"> <div className="live-course-opt">
<LiveModeSelect onClose={this.onModeSelectClose} onSelected={this.onModeSelected} isShow={this.state.showModeSelect}/>
<div className="opt__left"> <div className="opt__left">
{ userRole !== "CloudLecturer" && {userRole !== "CloudLecturer" &&
<Button type="primary" onClick={this.handleCreateLiveCouese}>新建直播课</Button> <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> </div>
<Route path={`${match.url}/createqwcourse`} component={CreateWorkWXCourse} />
</div> </div>
) )
} }
} }
export default LiveCourseOpt; export default withRouter(LiveCourseOpt);
\ No newline at end of file \ No newline at end of file
.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";
import { brandLiveName } from "@/domains/brand/constants";
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">{brandLiveName}</div>
<div className="des">通过{window.brandName}“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
...@@ -280,7 +280,7 @@ class AddGraphicsCourse extends React.Component { ...@@ -280,7 +280,7 @@ class AddGraphicsCourse extends React.Component {
if (User.getExpirationTime() && moment().valueOf() > Number(User.getExpirationTime())) { if (User.getExpirationTime() && moment().valueOf() > Number(User.getExpirationTime())) {
Modal.warning({ Modal.warning({
title: '服务已到期', title: '服务已到期',
content: '当前企业购买的小麦企学院服务已到期,如需继续使用学院功能,请尽快续费购买', content: `当前企业购买的${window.brandName}服务已到期,如需继续使用学院功能,请尽快续费购买`,
okText: '我知道了', okText: '我知道了',
}) })
return return
...@@ -423,7 +423,7 @@ class AddGraphicsCourse extends React.Component { ...@@ -423,7 +423,7 @@ class AddGraphicsCourse extends React.Component {
<div className='box'> <div className='box'>
<div className='show-tips'> <div className='show-tips'>
<ShowTips message='请遵守国家相关规定,切勿上传低俗色情、暴力恐怖、谣言诈骗、侵权盗版等相关内容,小麦企学院保有依据国家规定及平台规则进行处理的权利' /> <ShowTips message={`请遵守国家相关规定,切勿上传低俗色情、暴力恐怖、谣言诈骗、侵权盗版等相关内容,${window.brandName}保有依据国家规定及平台规则进行处理的权利`} />
</div> </div>
<div className='form'> <div className='form'>
......
...@@ -98,7 +98,7 @@ class GraphicsCourseFilter extends React.Component { ...@@ -98,7 +98,7 @@ class GraphicsCourseFilter extends React.Component {
delete query.endTime delete query.endTime
} else { } else {
query.beginTime = dates[0]?.startOf('day').valueOf() query.beginTime = dates[0]?.startOf('day').valueOf()
query.endTime = dates[0]?.endOf('day').valueOf() query.endTime = dates[1]?.endOf('day').valueOf()
} }
this.setState( this.setState(
{ {
......
...@@ -333,6 +333,7 @@ class ManageCoursewareModal extends React.Component { ...@@ -333,6 +333,7 @@ class ManageCoursewareModal extends React.Component {
]; ];
const { list, scanFileModal, editData, cancelObject, showSelectFileModal, selectedFileList, diskList, showPreviewModal, previewStatus, url } = this.state; const { list, scanFileModal, editData, cancelObject, showSelectFileModal, selectedFileList, diskList, showPreviewModal, previewStatus, url } = this.state;
const _list = _.reject(list, (item) => cancelObject[item.id]); const _list = _.reject(list, (item) => cancelObject[item.id]);
const { thirdPartType } = this.props.data
return ( return (
<Modal <Modal
visible={true} visible={true}
...@@ -348,10 +349,17 @@ class ManageCoursewareModal extends React.Component { ...@@ -348,10 +349,17 @@ class ManageCoursewareModal extends React.Component {
{_.isEmpty(_list) ? ( {_.isEmpty(_list) ? (
<div className='empty-body'> <div className='empty-body'>
<div id='lottie-box' className='empty-image'></div> <div id='lottie-box' className='empty-image'></div>
<Button className='empty-button' type='primary' onClick={() => this.addFile()}> { thirdPartType === "WECHAT" && <div className="qiwei-tip">企微直播<br/>Mac暂不支持上传课件,Windows可在直播间添加课件</div>}
<Button className='empty-button' type='primary'
disabled={thirdPartType === "WECHAT"}
onClick={() => {
if (thirdPartType !== "WECHAT") {
this.addFile()
}
}}>
上传课件 上传课件
</Button> </Button>
<p className='empty-tip'>提前上传直播需要的课件和素材,直播将会变得更便捷!</p> { thirdPartType !== "WECHAT" && <p className='empty-tip'>提前上传直播需要的课件和素材,直播将会变得更便捷!</p>}
</div> </div>
) : ( ) : (
<div className='manage-body'> <div className='manage-body'>
......
...@@ -11,6 +11,14 @@ ...@@ -11,6 +11,14 @@
width:150px; width:150px;
height:150px; height:150px;
} }
.qiwei-tip {
font-size: 14px;
font-weight: 400;
color: #999;
text-align: center;
margin-top: 12px;
margin-bottom: 12px;
}
.empty-button { .empty-button {
display: block; display: block;
margin: 0 auto 8px; margin: 0 auto 8px;
......
...@@ -107,12 +107,19 @@ class PreviewCourseModal extends React.Component { ...@@ -107,12 +107,19 @@ class PreviewCourseModal extends React.Component {
timeHorizonStart, timeHorizonStart,
timeHorizonEnd, timeHorizonEnd,
teacherName, teacherName,
duration
} = courseClassInfo; } = courseClassInfo;
const { introduce, categoryName } = courseIntroInfo; const { introduce, categoryName } = courseIntroInfo;
let { activeTab } = this.state; let { activeTab } = this.state;
let liveDateStr, startTimeStr, endTimeStr; let liveDateStr, startTimeStr, endTimeStr;
if (this.props.bizType === "qiwei") {
let _startTime = startTime === 0 ? moment().valueOf():startTime
startTimeStr = moment(_startTime).format("YYYY-MM-DD HH:mm")
endTimeStr = moment(endTime === 0?moment(_startTime+Number(duration)*1000).valueOf():endTime).format("HH:mm")
console.log(duration)
} else {
if (type === "add") { if (type === "add") {
const _liveDate = moment(calendarTime[0]).format("YYYY-MM-DD"); const _liveDate = moment(calendarTime[0]).format("YYYY-MM-DD");
console.log("_liveDate", _liveDate); console.log("_liveDate", _liveDate);
...@@ -147,6 +154,8 @@ class PreviewCourseModal extends React.Component { ...@@ -147,6 +154,8 @@ class PreviewCourseModal extends React.Component {
startTimeStr = _startTimeStr; startTimeStr = _startTimeStr;
endTimeStr = _endTimeStr; endTimeStr = _endTimeStr;
} }
}
return ( return (
<Modal <Modal
......
...@@ -60,10 +60,12 @@ ...@@ -60,10 +60,12 @@
.title__state { .title__state {
min-width: 40px; min-width: 40px;
height: 17px; height: 17px;
padding: 0px 8px; padding-left: 8px;
padding-right: 8px;
border-radius: 10px; border-radius: 10px;
margin-left: 6px; margin-left: 6px;
font-size: 12px; font-size: 12px;
line-height: 17px;
color: #FFF; color: #FFF;
background-color: #34B88B; background-color: #34B88B;
} }
......
...@@ -102,7 +102,7 @@ class ShareLiveModal extends React.Component { ...@@ -102,7 +102,7 @@ class ShareLiveModal extends React.Component {
render() { render() {
const { courseDivision, data, type, title } = this.props; const { courseDivision, data, type, title } = this.props;
const { courseName, scheduleVideoUrl, courseMediaVOS, coverUrl } = data; const { courseName, scheduleVideoUrl, courseMediaVOS, coverUrl, thirdPartType } = data;
const { shareUrl, showImg, time } = this.state; const { shareUrl, showImg, time } = this.state;
// 判断是否是默认图, 默认图不需要在URL后面增加字符串 // 判断是否是默认图, 默认图不需要在URL后面增加字符串
let coverImgSrc = ''; let coverImgSrc = '';
...@@ -188,8 +188,8 @@ class ShareLiveModal extends React.Component { ...@@ -188,8 +188,8 @@ class ShareLiveModal extends React.Component {
<div className='right'> <div className='right'>
<div className='share-poster right__item'> <div className='share-poster right__item'>
<div className='title'>① 海报分享</div> <div className='title'>① 海报分享</div>
{type === 'liveClass' && <div className='sub-title'>学员可通过微信扫描海报二维码,观看{title}</div>} {type === 'liveClass' && <div className='sub-title'>学员可通过微信{thirdPartType === "WECHAT"?"/企业微信":""}扫描海报二维码,观看{title}</div>}
{type === 'videoClass' && <div className='sub-title'>学员可通过微信识别二维码,报名观看{title}</div>} {type === 'videoClass' && <div className='sub-title'>学员可通过微信{thirdPartType === "WECHAT"?"/企业微信":""}识别二维码,报名观看{title}</div>}
<div className='content' onClick={_.debounce(this.handleDownloadPoster, 1000, true)}> <div className='content' onClick={_.debounce(this.handleDownloadPoster, 1000, true)}>
下载海报 下载海报
...@@ -198,7 +198,7 @@ class ShareLiveModal extends React.Component { ...@@ -198,7 +198,7 @@ class ShareLiveModal extends React.Component {
<div className='share-url right__item'> <div className='share-url right__item'>
<div className='title'>② 链接分享</div> <div className='title'>② 链接分享</div>
{type === 'liveClass' && <div className='sub-title'>学员可通过微信打开以下链接,观看{title}</div>} {type === 'liveClass' && <div className='sub-title'>学员可通过微信{thirdPartType === "WECHAT"?"/企业微信":""}打开以下链接,观看{title}</div>}
{type === 'videoClass' && <div className='sub-title'>学员可通过打开链接,报名观看{title}</div>} {type === 'videoClass' && <div className='sub-title'>学员可通过打开链接,报名观看{title}</div>}
<div className='content url-content'> <div className='content url-content'>
<div className='share-url' id='shareUrl'> <div className='share-url' id='shareUrl'>
......
...@@ -373,7 +373,7 @@ class AddOfflineCourse extends React.Component { ...@@ -373,7 +373,7 @@ class AddOfflineCourse extends React.Component {
if (User.getExpirationTime() && moment().valueOf() > Number(User.getExpirationTime())) { if (User.getExpirationTime() && moment().valueOf() > Number(User.getExpirationTime())) {
Modal.warning({ Modal.warning({
title: '服务已到期', title: '服务已到期',
content: '当前企业购买的小麦企学院服务已到期,如需继续使用学院功能,请尽快续费购买', content: `当前企业购买的${window.brandName}服务已到期,如需继续使用学院功能,请尽快续费购买`,
okText: '我知道了', okText: '我知道了',
}) })
return return
...@@ -711,7 +711,7 @@ class AddOfflineCourse extends React.Component { ...@@ -711,7 +711,7 @@ class AddOfflineCourse extends React.Component {
<div className='box'> <div className='box'>
<div className='show-tips'> <div className='show-tips'>
<ShowTips message='请遵守国家相关规定,切勿上传低俗色情、暴力恐怖、谣言诈骗、侵权盗版等相关内容,小麦企学院保有依据国家规定及平台规则进行处理的权利' /> <ShowTips message={`请遵守国家相关规定,切勿上传低俗色情、暴力恐怖、谣言诈骗、侵权盗版等相关内容,${window.brandName}保有依据国家规定及平台规则进行处理的权利`} />
</div> </div>
<div className='form'> <div className='form'>
......
...@@ -366,11 +366,11 @@ class AddVideoCourse extends React.Component { ...@@ -366,11 +366,11 @@ class AddVideoCourse extends React.Component {
//过期判断 //过期判断
if (User.getExpirationTime() && moment().valueOf() > Number(User.getExpirationTime())) { if (User.getExpirationTime() && moment().valueOf() > Number(User.getExpirationTime())) {
Modal.warning({ Modal.warning({
title: '服务已到期', title:"服务已到期",
content: '当前企业购买的小麦企学院服务已到期,如需继续使用学院功能,请尽快续费购买', content:`当前企业购买的${window.brandName}服务已到期,如需继续使用学院功能,请尽快续费购买`,
okText: '我知道了', okText: "我知道了"
}); })
return; return
} }
const { const {
...@@ -695,7 +695,7 @@ class AddVideoCourse extends React.Component { ...@@ -695,7 +695,7 @@ class AddVideoCourse extends React.Component {
<div className='box'> <div className='box'>
<div className='show-tips'> <div className='show-tips'>
<ShowTips message='请遵守国家相关规定,切勿上传低俗色情、暴力恐怖、谣言诈骗、侵权盗版等相关内容,小麦企学院保有依据国家规定及平台规则进行处理的权利' /> <ShowTips message={`请遵守国家相关规定,切勿上传低俗色情、暴力恐怖、谣言诈骗、侵权盗版等相关内容,${window.brandName}保有依据国家规定及平台规则进行处理的权利`} />
</div> </div>
<div className='form'> <div className='form'>
......
...@@ -427,8 +427,8 @@ class Home extends React.Component { ...@@ -427,8 +427,8 @@ class Home extends React.Component {
<Choose> <Choose>
<When condition={_.isEmpty(list)}> <When condition={_.isEmpty(list)}>
<div className='study-empty'> <div className='study-empty'>
<img src='https://image.xiaomaiketang.com/xm/52dmait5Bx.png' alt='' /> <img src='https://image.xiaomaiketang.com/xm/fFnpKMJD6x.png' alt='' />
<div>暂无课程上榜</div> <div className="text">暂无学员上榜</div>
</div> </div>
</When> </When>
<Otherwise> <Otherwise>
......
...@@ -64,9 +64,11 @@ ...@@ -64,9 +64,11 @@
font-size: 28px; font-size: 28px;
color: #333; color: #333;
margin-top: 24px; margin-top: 24px;
margin-left: 22px;
} }
.data-footer { .data-footer {
margin-top: 12px; margin-top: 12px;
margin-left: 22px;
.footer-word { .footer-word {
font-size: 12px; font-size: 12px;
color: #999; color: #999;
...@@ -238,13 +240,13 @@ ...@@ -238,13 +240,13 @@
margin-top: 102px; margin-top: 102px;
img { img {
display: block; display: block;
width: 100px; width: 150px;
height: 100px; height: 150px;
margin: 0 auto 8px; margin: 0 auto 8px;
} }
div { div {
text-align: center; text-align: center;
color: #333; color: #999;
} }
} }
.circle-box { .circle-box {
......
...@@ -13,7 +13,7 @@ export default function HomeTip() { ...@@ -13,7 +13,7 @@ export default function HomeTip() {
const [surplusDay, setSurplusDay] = useState(0) const [surplusDay, setSurplusDay] = useState(0)
const versionInfo = useContext(VersionContext) const versionInfo = useContext(VersionContext)
useEffect(()=> { useEffect(() => {
if (versionInfo) { if (versionInfo) {
setIsOverNum(versionInfo.userNum === -1 ? false : versionInfo.whetherReachUserNum) setIsOverNum(versionInfo.userNum === -1 ? false : versionInfo.whetherReachUserNum)
setSurplusDay(versionInfo.surplusDayTime) setSurplusDay(versionInfo.surplusDayTime)
...@@ -25,7 +25,7 @@ export default function HomeTip() { ...@@ -25,7 +25,7 @@ export default function HomeTip() {
} }
} }
},[versionInfo]) }, [versionInfo])
return ( return (
<div className="home-tip"> <div className="home-tip">
...@@ -36,7 +36,7 @@ export default function HomeTip() { ...@@ -36,7 +36,7 @@ export default function HomeTip() {
{ {
isOverNum && ( isOverNum && (
<div className="content"> <div className="content">
<span className="icon iconfont" style={{color:"#FF4F4F",marginRight:"8px"}}>&#xe61d;</span>温馨提示:企业使用人数已达上限,将无法新增员工、学员,如需增加人数限制,请联系小麦企学院服务平台。 <span className="icon iconfont" style={{ color: "#FF4F4F", marginRight: "8px" }}>&#xe61d;</span>{`温馨提示:企业使用人数已达上限,将无法新增员工、学员,如需增加人数限制,请联系${window.brandName}服务平台。`}
<ContactWidget placement="bottom" trigger="hover"><div className="renew-btn">立即续费</div></ContactWidget> <ContactWidget placement="bottom" trigger="hover"><div className="renew-btn">立即续费</div></ContactWidget>
</div> </div>
) )
...@@ -44,7 +44,7 @@ export default function HomeTip() { ...@@ -44,7 +44,7 @@ export default function HomeTip() {
{ {
tipType === 2 && ( tipType === 2 && (
<div className="content"> <div className="content">
<span className="icon iconfont" style={{color:"#FF4F4F",marginRight:"8px"}}>&#xe61d;</span>版本到期提醒:当前企业购买的小麦企学院服务已于{moment(versionInfo?.validEndTimeST).format("YYYY-MM-DD HH:mm:ss")}到期,到期后仍可访问,但功能不可使用,建议尽快续费购买哦~ <span className="icon iconfont" style={{ color: "#FF4F4F", marginRight: "8px" }}>&#xe61d;</span>版本到期提醒:当前企业购买的{`${window.brandName}`}服务已于{moment(versionInfo?.validEndTimeST).format("YYYY-MM-DD HH:mm:ss")}到期,到期后仍可访问,但功能不可使用,建议尽快续费购买哦~
<ContactWidget placement="bottom" trigger="hover"><div className="renew-btn">立即续费</div></ContactWidget> <ContactWidget placement="bottom" trigger="hover"><div className="renew-btn">立即续费</div></ContactWidget>
</div> </div>
) )
...@@ -52,7 +52,7 @@ export default function HomeTip() { ...@@ -52,7 +52,7 @@ export default function HomeTip() {
{ {
tipType === 1 && ( tipType === 1 && (
<div className="content"> <div className="content">
<span className="icon iconfont" style={{color:"#FF4F4F",marginRight:"8px"}}>&#xe61d;</span>当前企业购买的小麦企学院服务仅剩{surplusDay}天(于{expirationTime}到期),为了不影响使用,建议尽快续费购买哦~ <span className="icon iconfont" style={{ color: "#FF4F4F", marginRight: "8px" }}>&#xe61d;</span>当前企业购买的{`${window.brandName}`}服务仅剩{surplusDay}天(于{expirationTime}到期),为了不影响使用,建议尽快续费购买哦~
<ContactWidget placement="bottom" trigger="hover"><div className="renew-btn">立即续费</div></ContactWidget> <ContactWidget placement="bottom" trigger="hover"><div className="renew-btn">立即续费</div></ContactWidget>
</div> </div>
) )
...@@ -62,4 +62,4 @@ export default function HomeTip() { ...@@ -62,4 +62,4 @@ export default function HomeTip() {
} }
</div> </div>
) )
} }
\ No newline at end of file \ No newline at end of file
...@@ -22,7 +22,6 @@ import "./KnowledgeBaseList.less"; ...@@ -22,7 +22,6 @@ import "./KnowledgeBaseList.less";
const DEFAULT_SIZE_UNIT = 1000 * 1000 // 将B转换成M const DEFAULT_SIZE_UNIT = 1000 * 1000 // 将B转换成M
const { confirm } = Modal const { confirm } = Modal
const ENV = process.env.DEPLOY_ENV || "dev"
class KnowledgeBaseList extends React.Component { class KnowledgeBaseList extends React.Component {
constructor(props) { constructor(props) {
......
...@@ -19,7 +19,6 @@ import "./LiveList.less"; ...@@ -19,7 +19,6 @@ import "./LiveList.less";
import CourseService from "@/domains/course-domain/CourseService"; import CourseService from "@/domains/course-domain/CourseService";
import User from "@/common/js/user"; import User from "@/common/js/user";
const ENV = process.env.DEPLOY_ENV || "dev";
class VideoList extends React.Component { class VideoList extends React.Component {
constructor(props) { constructor(props) {
......
...@@ -281,7 +281,7 @@ function AddPlan() { ...@@ -281,7 +281,7 @@ function AddPlan() {
<Breadcrumbs navList={type == 'add' ? '新建培训计划' : '编辑培训计划'} goBack={handleGoBack} /> <Breadcrumbs navList={type == 'add' ? '新建培训计划' : '编辑培训计划'} goBack={handleGoBack} />
<div className='box'> <div className='box'>
<div className='show-tips'> <div className='show-tips'>
<ShowTips message='请遵守国家相关规定,切勿上传低俗色情、暴力恐怖、谣言诈骗、侵权盗版等相关内容,小麦企学院保有依据国家规定及平台规则进行处理的权利' /> <ShowTips message={`请遵守国家相关规定,切勿上传低俗色情、暴力恐怖、谣言诈骗、侵权盗版等相关内容,${window.brandName}保有依据国家规定及平台规则进行处理的权利`} />
</div> </div>
<div className='add-plan-page__form'> <div className='add-plan-page__form'>
<div className='basic-info__wrap'> <div className='basic-info__wrap'>
......
...@@ -309,7 +309,6 @@ class SelectOperatorModal extends React.Component { ...@@ -309,7 +309,6 @@ class SelectOperatorModal extends React.Component {
), ),
key: 'course', key: 'course',
dataIndex: 'course', dataIndex: 'course',
width: '40%',
render: (val, record) => { render: (val, record) => {
let hasCover = false; let hasCover = false;
return ( return (
...@@ -341,7 +340,7 @@ class SelectOperatorModal extends React.Component { ...@@ -341,7 +340,7 @@ class SelectOperatorModal extends React.Component {
title: '上课时间', title: '上课时间',
key: 'courseTime', key: 'courseTime',
dataIndex: 'courseTime', dataIndex: 'courseTime',
width: '40%', width: 150,
render: (val, record) => { render: (val, record) => {
return ( return (
<div> <div>
...@@ -357,7 +356,7 @@ class SelectOperatorModal extends React.Component { ...@@ -357,7 +356,7 @@ class SelectOperatorModal extends React.Component {
title: '学院展示', title: '学院展示',
key: 'shelfState', key: 'shelfState',
dataIndex: 'shelfState', dataIndex: 'shelfState',
width: '20%', width: 120,
render: (val, record) => { render: (val, record) => {
return ( return (
<span> <span>
......
...@@ -34,7 +34,7 @@ class ScanFileModal extends React.Component { ...@@ -34,7 +34,7 @@ class ScanFileModal extends React.Component {
style={{ width: 632, objectFit: "cover" }} style={{ width: 632, objectFit: "cover" }}
/> />
)} )}
{fileType === "VIDEO" && ( {(fileType ==="VIDEO" || fileType === "MP4") && (
<div> <div>
<Player <Player
src={item.mediaUrl || item.ossAddress || item.ossUrl} src={item.mediaUrl || item.ossAddress || item.ossUrl}
......
...@@ -16,11 +16,10 @@ import User from '@/common/js/user'; ...@@ -16,11 +16,10 @@ import User from '@/common/js/user';
import BaseService from "@/domains/basic-domain/baseService"; import BaseService from "@/domains/basic-domain/baseService";
import moment from 'moment'; import moment from 'moment';
import { VersionContext, VersionInfo, XMContext } from '@/store/context'; import { VersionContext, VersionInfo, XMContext } from '@/store/context';
import WechatApi from '@/common/js/wechatApi';
import { setStoreGroupPermission, setStorePermission, setStoreGroupList, setStoreList, setWechatLogin } from '@/store/actions/index'; import { setStoreGroupPermission, setStorePermission, setStoreGroupList, setStoreList, setWechatLogin } from '@/store/actions/index';
import Service from "@/common/js/service"; import Service from "@/common/js/service";
import Bus from '@/core/tbus'; import Bus from '@/core/tbus';
import WechatApi from '@/common/js/wechatApi';
import { func } from 'prop-types';
const { Footer, Sider, Content } = Layout; const { Footer, Sider, Content } = Layout;
......
...@@ -7,6 +7,7 @@ import { LIVE_SHARE } from "@/domains/course-domain/constants"; ...@@ -7,6 +7,7 @@ import { LIVE_SHARE } from "@/domains/course-domain/constants";
import { Modal, message } from 'antd'; import { Modal, message } from 'antd';
import WechatApi from '@/common/js/wechatApi'; import WechatApi from '@/common/js/wechatApi';
import WWOpenDataCom from '@/components/WWOpenData'; import WWOpenDataCom from '@/components/WWOpenData';
import { brandLogo,xfrwm } from '@/domains/brand/constants'
import './CollegeManagePage.less'; import './CollegeManagePage.less';
import storage from '@/common/js/storage'; import storage from '@/common/js/storage';
...@@ -87,14 +88,14 @@ function ExpirationPopover(props) { ...@@ -87,14 +88,14 @@ function ExpirationPopover(props) {
<div className="title">{props.surplusDayTime === 0 ? "服务已到期" : "服务到期提醒"}</div> <div className="title">{props.surplusDayTime === 0 ? "服务已到期" : "服务到期提醒"}</div>
{ {
showType === 3 ? ( showType === 3 ? (
<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" }}>{moment(props.endTime).format("YYYY-MM-DD HH:mm:ss")}</span>到期,到期后仍可访问,但功能不可使用,建议尽快续费购买哦~</div>
) : ( ) : (
<div className="tip-text">当前企业购买的小麦企学院服务 <span style={{ color: "#FF4F4F" }}>仅剩{props.surplusDayTime}</span>(于<span>{moment(props.endTime).format("YYYY-MM-DD")}</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="qrcode"> <div className="qrcode">
<img src="https://cdn.xiaomai5.com/qixueyuankehu.png" alt=""></img> <img src={xfrwm} alt=""></img>
<div className="des">微信/企业微信扫码咨询</div> <div className="des">微信/企业微信扫码咨询</div>
</div> </div>
<div className="phone"><svg style={{ position: "relative", top: "2px", marginRight: "4px" }} viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M512.651 3.78c-281.433 0-509.21 228.324-509.21 509.209 0 281.43 228.325 509.203 509.21 509.203 281.427 0 509.202-228.317 509.202-509.203 0.55-280.885-227.775-509.21-509.202-509.21z m198.205 743.553c-36.14 36.136-169.737 1.641-302.24-130.312-131.953-131.959-165.902-266.104-129.768-301.695 31.211-31.21 68.99-85.417 125.939-14.782 56.943 70.629 29.016 90.34-3.291 122.647-22.449 22.448 24.642 79.392 73.37 128.125 49.283 48.73 105.678 95.818 128.126 73.368 32.306-32.305 52.017-60.23 122.646-3.288 71.182 56.949 16.426 95.276-14.782 125.937z" p-id="4409" fill="#999999"></path></svg> <div className="phone"><svg style={{ position: "relative", top: "2px", marginRight: "4px" }} viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M512.651 3.78c-281.433 0-509.21 228.324-509.21 509.209 0 281.43 228.325 509.203 509.21 509.203 281.427 0 509.202-228.317 509.202-509.203 0.55-280.885-227.775-509.21-509.202-509.21z m198.205 743.553c-36.14 36.136-169.737 1.641-302.24-130.312-131.953-131.959-165.902-266.104-129.768-301.695 31.211-31.21 68.99-85.417 125.939-14.782 56.943 70.629 29.016 90.34-3.291 122.647-22.449 22.448 24.642 79.392 73.37 128.125 49.283 48.73 105.678 95.818 128.126 73.368 32.306-32.305 52.017-60.23 122.646-3.288 71.182 56.949 16.426 95.276-14.782 125.937z" p-id="4409" fill="#999999"></path></svg>
...@@ -235,9 +236,6 @@ export default class CollegeManagePage extends React.Component { ...@@ -235,9 +236,6 @@ export default class CollegeManagePage extends React.Component {
User.removeToken(); User.removeToken();
User.removeEnterpriseId(); User.removeEnterpriseId();
window.RCHistory.replace('/login'); 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;
}); });
} }
...@@ -256,14 +254,13 @@ export default class CollegeManagePage extends React.Component { ...@@ -256,14 +254,13 @@ export default class CollegeManagePage extends React.Component {
<ExpirationPopover surplusDayTime={this.state.surplusDayTime} endTime={this.state.endTime} /> <ExpirationPopover surplusDayTime={this.state.surplusDayTime} endTime={this.state.endTime} />
<div className="college-header"> <div className="college-header">
<div className="box"> <div className="box">
<img className="box-image" src="https://image.xiaomaiketang.com/xm/fe4NCjr7XF.png" /> <img className="box-image" src={brandLogo} />
<div className="user"> <div className="user">
<img className="image" src={avatar} /> <img className="image" src={avatar} />
<span className="name"> <span className="name">
{ {
initWechat && <WWOpenDataCom type="userName" openid={name} /> initWechat && <WWOpenDataCom type="userName" openid={name} />
} }
</span> </span>
<span <span
className="logout" className="logout"
...@@ -317,7 +314,7 @@ export default class CollegeManagePage extends React.Component { ...@@ -317,7 +314,7 @@ export default class CollegeManagePage extends React.Component {
}} }}
> >
<div className="header"> <div className="header">
<img className="image" src={item.logo || "https://image.xiaomaiketang.com/xm/fe4NCjr7XF.png"} /> <img className="image" src={item.logo || brandLogo} />
<span className="tag">{roleMap[item.userRole]}</span> <span className="tag">{roleMap[item.userRole]}</span>
</div> </div>
<div className="title">{item.storeName}</div> <div className="title">{item.storeName}</div>
...@@ -394,7 +391,7 @@ export default class CollegeManagePage extends React.Component { ...@@ -394,7 +391,7 @@ export default class CollegeManagePage extends React.Component {
}} }}
> >
<div className="header"> <div className="header">
<img className="image" src={item.logo || "https://image.xiaomaiketang.com/xm/fe4NCjr7XF.png"} /> <img className="image" src={item.logo || brandLogo} />
<span className="tag">{roleMap[item.userRole]}</span> <span className="tag">{roleMap[item.userRole]}</span>
</div> </div>
<div className="title">{item.storeName}</div> <div className="title">{item.storeName}</div>
......
import React from 'react'; import React from 'react';
import { Input, Button, Modal, message, Form } from 'antd'; import { Input, Button, Switch, message, Form, Tooltip } from 'antd';
import Upload from '@/core/upload'; import Upload from '@/core/upload';
import Service from "@/common/js/service"; import Service from "@/common/js/service";
import BaseService from "@/domains/basic-domain/baseService"; import BaseService from "@/domains/basic-domain/baseService";
import User from "@/common/js/user"; import User from "@/common/js/user";
import Breadcrumbs from "@/components/Breadcrumbs"; import Breadcrumbs from "@/components/Breadcrumbs";
import ImgClipModal from '@/components/ImgClipModal' import ImgClipModal from '@/components/ImgClipModal'
import {debounce} from 'underscore'
import { brandLogo } from '@/domains/brand/constants'
import './CreateCollege.less'; import './CreateCollege.less';
let cutFlag = false;
export default class CreateCollege extends React.Component { export default class CreateCollege extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
avatar: 'https://image.xiaomaiketang.com/xm/rJeQaZxtc7.png', avatar: 'https://image.xiaomaiketang.com/xm/rJeQaZxtc7.png',
logo: 'https://image.xiaomaiketang.com/xm/fe4NCjr7XF.png', logo: brandLogo,
name: '', name: '',
enterpriseId: User.getEnterpriseId(), enterpriseId: User.getEnterpriseId(),
imageFile: null, // 需要被截取的图片 imageFile: null, // 需要被截取的图片
auditSwitch:'OPEN',
}; };
this.loginInputRef = React.createRef() this.loginInputRef = React.createRef()
} }
...@@ -70,14 +70,14 @@ export default class CreateCollege extends React.Component { ...@@ -70,14 +70,14 @@ export default class CreateCollege extends React.Component {
}; };
updateCover = () =>{ updateCover = () =>{
const {coverClicpPath,coverId} = this.state const {coverClicpPath} = this.state
this.setState({ this.setState({
logo:coverClicpPath logo:coverClicpPath
}) })
} }
submit = () => { submit = () => {
const { logo, collegeName, enterpriseId } = this.state; const { logo, collegeName, enterpriseId,auditSwitch } = this.state;
if (!collegeName) { if (!collegeName) {
this.setState({ showError: true }) this.setState({ showError: true })
} else { } else {
...@@ -86,6 +86,7 @@ export default class CreateCollege extends React.Component { ...@@ -86,6 +86,7 @@ export default class CreateCollege extends React.Component {
userId: User.getUserId(), userId: User.getUserId(),
logo, logo,
storeName: collegeName, storeName: collegeName,
auditSwitch
} }
Service.Hades('public/customerHades/createStore', params).then((res) => { Service.Hades('public/customerHades/createStore', params).then((res) => {
if (res.success) { if (res.success) {
...@@ -95,23 +96,27 @@ export default class CreateCollege extends React.Component { ...@@ -95,23 +96,27 @@ export default class CreateCollege extends React.Component {
} }
} }
onChangeFiledValue = (filed, value) => {
this.setState({
[filed]: value,
});
};
render() { render() {
const { const {
avatar,
name,
collegeName, collegeName,
logo, logo,
visible, visible,
hasImgReady,
cutImageBlob,
showError, showError,
imageFile imageFile,
auditSwitch
} = this.state; } = this.state;
return ( return (
<div className="college-manage-page"> <div className="college-manage-page">
<div className="college-header"> <div className="college-header">
<div className="box"> <div className="box">
<img className="box-image" src="https://image.xiaomaiketang.com/xm/fe4NCjr7XF.png" /> <img className="box-image" src={brandLogo} />
</div> </div>
</div> </div>
<div className="breadcrumb-wrap"> <div className="breadcrumb-wrap">
...@@ -124,7 +129,7 @@ export default class CreateCollege extends React.Component { ...@@ -124,7 +129,7 @@ export default class CreateCollege extends React.Component {
</div> </div>
<div className="create-box"> <div className="create-box">
<div className="image-box"> <div className="image-box">
<img className="image" src={logo}/> <img className="image" src={logo} alt=''/>
<div className="image-mask"> <div className="image-mask">
<span <span
className="icon iconfont" className="icon iconfont"
...@@ -134,7 +139,7 @@ export default class CreateCollege extends React.Component { ...@@ -134,7 +139,7 @@ export default class CreateCollege extends React.Component {
className="icon iconfont" className="icon iconfont"
onClick={() => { onClick={() => {
this.setState({ this.setState({
logo: 'https://image.xiaomaiketang.com/xm/fe4NCjr7XF.png', logo: brandLogo,
visible: false, visible: false,
}) })
}} }}
...@@ -154,11 +159,29 @@ export default class CreateCollege extends React.Component { ...@@ -154,11 +159,29 @@ export default class CreateCollege extends React.Component {
}} }}
></Input> ></Input>
</Form.Item> </Form.Item>
<Form.Item label={<div className='label-box'>学员审核
<Tooltip title='学院同时支持企微和微信用户加入学院学习。学员审核开启后,微信用户需要先提出申请,学院管理员审核通过后才能成为学院的学员,保证仅可信的微信用户才能加入学院。' placement='top' arrowPointAtCenter>
<span className='icon iconfont icon-tip'>&#xe61d;</span>
</Tooltip>
</div>} name='auditSwitch' rules={[{ required: true }]}>
<div className='switch-box'>
<Switch checked={auditSwitch ==='OPEN' } onChange={(e) => this.onChangeFiledValue('auditSwitch', e ?'OPEN':'CLOSE')}/>
<Choose>
<When condition={auditSwitch ==='OPEN'}>
<div className='switch-desc'>已开启,成为学院学员需要审核</div>
</When>
<Otherwise>
<div className='switch-desc'>已关闭,成为学院学员不需要审核</div>
</Otherwise>
</Choose>
</div>
</Form.Item>
</Form> </Form>
<Button <Button
className="button" className="button"
type="primary" type="primary"
onClick={_.debounce(() => this.submit(), 3000, { onClick={debounce(() => this.submit(), 3000, {
leading: true, leading: true,
trailing: false trailing: false
})} })}
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
.create-box { .create-box {
padding-top: 108px; padding-top: 108px;
margin: 0 auto; margin: 0 auto;
width: 350px; width: 380px;
.image-box { .image-box {
position: relative; position: relative;
display: block; display: block;
...@@ -45,6 +45,27 @@ ...@@ -45,6 +45,27 @@
} }
} }
} }
.label-box{
display: flex;
align-content: center;
.icon{
color:#BFBFBF;
margin: 0 2px;
}
}
.switch-box{
display: flex;
align-items: center;
.switch-desc{
color: #999;
font-size: 14px;
margin: 0 8px;
}
.switch-prew-link{
color: #2966FF;
font-size: 14px;
}
}
.tip { .tip {
display: block; display: block;
color: #999999; color: #999999;
...@@ -52,10 +73,10 @@ ...@@ -52,10 +73,10 @@
margin-bottom: 24px; margin-bottom: 24px;
} }
.input { .input {
width: 350px; width: 380px;
} }
.button { .button {
width: 350px; width: 380px;
margin-top: 36px; margin-top: 36px;
height: 32px !important; height: 32px !important;
} }
......
/* /*
* @Author: 吴文洁 * @Author: 吴文洁
* @Date: 2019-09-10 18:26:03 * @Date: 2019-09-10 18:26:03
* @LastEditors: yuananting * @LastEditors: wufan
* @LastEditTime: 2021-08-17 19:19:42 * @LastEditTime: 2021-09-03 10:32:44
* @Description: * @Description:
*/ */
import React, { useRef, useContext, useEffect, useState } from 'react'; import React, { useRef, useContext, useEffect, useState } from 'react';
...@@ -343,11 +343,7 @@ function Header(props) { ...@@ -343,11 +343,7 @@ function Header(props) {
<div <div
className='url-link' className='url-link'
onClick={() => { onClick={() => {
window.open( window.open(`${LIVE_SHARE}store/index?id=${window.currentStoreUserInfo.storeId || User.getStoreId()}&userId=${window.currentStoreUserInfo.userId || User.getUserId()}&enterpriseId=${window.currentStoreUserInfo.enterpriseId || User.getEnterpriseId()}&from=admin&avatar=${avatar}`);
`${LIVE_SHARE}store/index?id=${window.currentStoreUserInfo.storeId || User.getStoreId()}&userId=${
window.currentStoreUserInfo.userId || User.getUserId()
}&enterpriseId=${window.currentStoreUserInfo.enterpriseId || User.getEnterpriseId()}&from=admin&avatar=${avatar}`
);
}}> }}>
{'立即前往 >'} {'立即前往 >'}
</div> </div>
...@@ -365,12 +361,15 @@ function Header(props) { ...@@ -365,12 +361,15 @@ function Header(props) {
<span className='text'>分享学院</span> <span className='text'>分享学院</span>
</span> </span>
</div> </div>
<div className='help'> {
process.env.BRAND == 'xiaomai' && <div className='help'>
<a href={helpCenterUrl} target='_blank' className='help-btn'> <a href={helpCenterUrl} target='_blank' className='help-btn'>
<span className='icon iconfont tool-tip-right'>&#xe8ed;</span> <span className='icon iconfont tool-tip-right'>&#xe8ed;</span>
<span className='text'>帮助中心</span> <span className='text'>帮助中心</span>
</a> </a>
</div> </div>
}
</div> </div>
<Dropdown overlay={userMenu()} arrow> <Dropdown overlay={userMenu()} arrow>
<div className='user'> <div className='user'>
......
...@@ -9,7 +9,7 @@ import BaseService from '@/domains/basic-domain/baseService'; ...@@ -9,7 +9,7 @@ import BaseService from '@/domains/basic-domain/baseService';
import axios from 'axios'; import axios from 'axios';
import storage from '@/common/js/storage'; import storage from '@/common/js/storage';
import _ from 'underscore'; import _ from 'underscore';
import user from '@/common/js/user'; import {brandLogo,brandBanner} from '@/domains/brand/constants'
const { TabPane } = Tabs; const { TabPane } = Tabs;
function Login(props) { function Login(props) {
...@@ -156,12 +156,12 @@ function Login(props) { ...@@ -156,12 +156,12 @@ function Login(props) {
return ( return (
<div className='login-page'> <div className='login-page'>
<div className='logo-img-box'> <div className='logo-img-box'>
<img src='https://image.xiaomaiketang.com/xm/6k8PPCmywG.png' className='logo-img' /> <img src={brandLogo} className='logo-img' />
</div> </div>
<div className='login-main'> <div className='login-main'>
<div className='left-banner'> <div className='left-banner'>
<div className='img-box'> <div className='img-box'>
<img src='https://image.xiaomaiketang.com/xm/CDCcdAdaPs.png' alt='' /> <img src={brandBanner} alt='' />
</div> </div>
</div> </div>
<div className='login-box'> <div className='login-box'>
......
import React , { useContext, useEffect ,useState}from 'react' import React, { useContext, useEffect, useState } from 'react'
import './Main.less'; import './Main.less';
import { Modal } from 'antd';
import { MainRoutes, RedirectRoutes } from '@/routes'; 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',showModal )
return ()=>{
Bus.unbind('showRouteChangeModal',showModal)
}
}, [])
function showModal(){
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 ( return (
<div <div
className={menuType ? `right-container has-nav` : `right-container has-nav right-container-vertical`} className={menuType ? `right-container has-nav` : `right-container has-nav right-container-vertical`}
id="rightContainer" id="rightContainer"
> >
<MainRoutes/> <MainRoutes />
<RedirectRoutes/> <RedirectRoutes />
</div> </div>
) )
} }
......
...@@ -12,6 +12,7 @@ import classNames from 'classnames'; ...@@ -12,6 +12,7 @@ import classNames from 'classnames';
import User from "@/common/js/user" import User from "@/common/js/user"
import _ from 'underscore'; import _ from 'underscore';
import tBus from '@/core/tbus' import tBus from '@/core/tbus'
import { brandLogo } from '@/domains/brand/constants'
import "./Menu.less"; import "./Menu.less";
import { display } from 'html2canvas/dist/types/css/property-descriptors/display'; import { display } from 'html2canvas/dist/types/css/property-descriptors/display';
import ContactWidget from '@/components/ContactWidget'; import ContactWidget from '@/components/ContactWidget';
...@@ -158,7 +159,7 @@ function Aside(props: any) { ...@@ -158,7 +159,7 @@ function Aside(props: any) {
if (User.getToken()) { if (User.getToken()) {
StoreService.getStoreDetail({ storeId: User.getStoreId() }).then((res) => { StoreService.getStoreDetail({ storeId: User.getStoreId() }).then((res) => {
if (_.isEmpty(res.result.logo)) { if (_.isEmpty(res.result.logo)) {
setTopLogoUrl('https://image.xiaomaiketang.com/xm/fe4NCjr7XF.png'); setTopLogoUrl(brandLogo);
} else { } else {
setTopLogoUrl(res.result.logo); setTopLogoUrl(res.result.logo);
} }
......
import React, { useState, useRef, useEffect } from 'react'; import React, { useState, useRef, useEffect } from 'react';
import qrcode from '@/libs/qrcode/qrcode.js'; import Service from "@/common/js/service";
import Service from '@/common/js/service';
import User from '@/common/js/user'; import User from '@/common/js/user';
import qrcode from "@/libs/qrcode/qrcode.js";
import { PATH } from '@/domains/basic-domain/constants'; import { PATH } from '@/domains/basic-domain/constants';
import { corpType } from '@/domains/brand/constants'
import './WechatLogin.less'; import './WechatLogin.less';
const Logo = require('@/common/images/logo.png'); import { brandName, BRAND, brandIcon, brandLogo } from '@/domains/brand/constants'
declare var location: any; declare var location: any;
declare var window: any; declare var window: any;
export default function WechatLogin(props: any) { export default function WechatLogin(props: any) {
const freshTime = 60; const freshTime = 60;
const init: any = null; const init: any = null;
...@@ -27,13 +29,13 @@ export default function WechatLogin(props: any) { ...@@ -27,13 +29,13 @@ export default function WechatLogin(props: any) {
if (status === 0) { if (status === 0) {
Service.Hades('anon/hades/getTicket', {}).then((res: any) => { Service.Hades('anon/hades/getTicket', {}).then((res: any) => {
setTicket(res.result); setTicket(res.result);
const redirect = `${PATH}?ticket=${res.result}&appTermEnum=XIAOMAI_CLOUD_CLASS_PC_WEB_ADMIN&env=${process.env.DEPLOY_ENV || 'dev'}`; const redirect = `${PATH}?ticket=${res.result}&appTermEnum=XIAOMAI_CLOUD_CLASS_PC_WEB_ADMIN&env=${process.env.DEPLOY_ENV || 'dev'}&corpType=${corpType}`;
const qrcodeWrapDom: any = document.querySelector('#qrcode'); const qrcodeWrapDom: any = document.querySelector('#qrcode');
let qrnode = new qrcode({ let qrnode = new qrcode({
text: redirect, text: redirect,
correctLevel: 2, correctLevel: 2,
size: 180, size: 180,
image: 'https://image.xiaomaiketang.com/xm/bFkRBz7teA.png', image: brandIcon,
imageSize: 50, imageSize: 50,
}); });
qrcodeWrapDom.innerHTML = ''; qrcodeWrapDom.innerHTML = '';
......
...@@ -251,7 +251,7 @@ function EmployeesManagePage() { ...@@ -251,7 +251,7 @@ function EmployeesManagePage() {
function handleDeleteWorkWechatEmployeeConfirm(record: RecordTypes) { function handleDeleteWorkWechatEmployeeConfirm(record: RecordTypes) {
return confirm({ return confirm({
title: "你确定要删除此员工吗?", title: "你确定要删除此员工吗?",
content: "管理员需在企业微信后台的“小麦企学院”应用管理中移除此员工,此员工才无法继续登陆小麦企学院", content:`管理员需在企业微信后台的“${window.brandName}”应用管理中移除此员工,此员工才无法继续登陆${window.brandName}`,
icon: ( icon: (
<span className="icon iconfont default-confirm-icon">&#xe839; </span> <span className="icon iconfont default-confirm-icon">&#xe839; </span>
), ),
......
import React, { useState, useRef, useEffect, useContext } from 'react' import React, { useState, useRef, useEffect } from 'react'
import Breadcrumbs from "@/components/Breadcrumbs"; import Breadcrumbs from "@/components/Breadcrumbs";
import { Form, Alert, Input, Button, InputNumber, DatePicker, Switch, Radio, message, Modal, Tooltip } from 'antd'; import { Form, Input, Button, InputNumber, DatePicker, Switch, Radio, message, Modal, Tooltip } from 'antd';
import { Route, withRouter } from 'react-router-dom'; import { withRouter } from 'react-router-dom';
import User from "@/common/js/user"; import User from "@/common/js/user";
import moment from 'moment' import moment from 'moment'
import Service from "@/common/js/service"; import Service from "@/common/js/service";
...@@ -84,7 +84,7 @@ function AddExam(props: any) { ...@@ -84,7 +84,7 @@ function AddExam(props: any) {
tenantId: User.getStoreId(), tenantId: User.getStoreId(),
source: 0, source: 0,
} }
Service.Hades('public/hades/queryExamPageList', param).then(res=> { Service.Hades('public/hades/queryExamPageList', param).then(res => {
const { result = {} } = res; const { result = {} } = res;
setExamList(result.records || []) setExamList(result.records || [])
}) })
...@@ -155,7 +155,7 @@ function AddExam(props: any) { ...@@ -155,7 +155,7 @@ function AddExam(props: any) {
return return
} }
if(checkExist(param.examName)) { if (checkExist(param.examName)) {
message.warning('此考试名称已存在'); message.warning('此考试名称已存在');
return return
} }
...@@ -275,8 +275,8 @@ function AddExam(props: any) { ...@@ -275,8 +275,8 @@ function AddExam(props: any) {
// 校验考试名称是否存在 // 校验考试名称是否存在
function checkExist(examName: any) { function checkExist(examName: any) {
var result:any = null; var result: any = null;
examList.length > 0 && examList.forEach((item:any) => { examList.length > 0 && examList.forEach((item: any) => {
if (result != null) { if (result != null) {
return result; return result;
} }
...@@ -315,7 +315,7 @@ function AddExam(props: any) { ...@@ -315,7 +315,7 @@ function AddExam(props: any) {
<div className="box"> <div className="box">
<div className="show-tips"> <div className="show-tips">
<ShowTips message="请遵守国家相关规定,切勿上传低俗色情、暴力恐怖、谣言诈骗、侵权盗版等相关内容,小麦企学院保有依据国家规定及平台规则进行处理的权利" /> <ShowTips message={`请遵守国家相关规定,切勿上传低俗色情、暴力恐怖、谣言诈骗、侵权盗版等相关内容,${window.brandName}保有依据国家规定及平台规则进行处理的权利`} />
</div> <div className="form"> </div> <div className="form">
<div className="title">基本信息</div> <div className="title">基本信息</div>
<Form <Form
...@@ -324,7 +324,7 @@ function AddExam(props: any) { ...@@ -324,7 +324,7 @@ function AddExam(props: any) {
layout="horizontal" layout="horizontal"
> >
<Form.Item label="考试名称" <Form.Item label="考试名称"
validateStatus={(check && (!examName || (examName.length > 40 || checkExist(examName)) )) ? 'error' : ''} validateStatus={(check && (!examName || (examName.length > 40 || checkExist(examName)))) ? 'error' : ''}
help={check && (!examName ? '请输入考试名称' : (examName.length > 40 ? '考试名称最多40字' : (checkExist(examName) && '此考试名称已存在')))} help={check && (!examName ? '请输入考试名称' : (examName.length > 40 ? '考试名称最多40字' : (checkExist(examName) && '此考试名称已存在')))}
required> required>
......
...@@ -800,7 +800,7 @@ class OperatePaper extends Component { ...@@ -800,7 +800,7 @@ class OperatePaper extends Component {
<Spin spinning={loading}> <Spin spinning={loading}>
<div className='box'> <div className='box'>
<div className='show-tips'> <div className='show-tips'>
<ShowTips message='请遵守国家相关规定,切勿上传低俗色情、暴力恐怖、谣言诈骗、侵权盗版等相关内容,小麦企学院保有依据国家规定及平台规则进行处理的权利' /> <ShowTips message={`请遵守国家相关规定,切勿上传低俗色情、暴力恐怖、谣言诈骗、侵权盗版等相关内容,${window.brandName}保有依据国家规定及平台规则进行处理的权利`} />
</div> </div>
<Form ref={this.formRef} style={{ marginTop: 24 }}> <Form ref={this.formRef} style={{ marginTop: 24 }}>
<Form.Item <Form.Item
......
...@@ -303,7 +303,7 @@ class OperateQuestion extends Component { ...@@ -303,7 +303,7 @@ class OperateQuestion extends Component {
/> />
<div className="box"> <div className="box">
<div className="show-tips"> <div className="show-tips">
<ShowTips message="请遵守国家相关规定,切勿上传低俗色情、暴力恐怖、谣言诈骗、侵权盗版等相关内容,小麦企学院保有依据国家规定及平台规则进行处理的权利" /> <ShowTips message={`请遵守国家相关规定,切勿上传低俗色情、暴力恐怖、谣言诈骗、侵权盗版等相关内容,${window.brandName}保有依据国家规定及平台规则进行处理的权利`} />
</div> </div>
<Tabs <Tabs
style={{ marginTop: 32 }} style={{ marginTop: 32 }}
......
/* /*
* @Author: yuananting * @Author: yuananting
* @Date: 2021-02-25 11:23:47 * @Date: 2021-02-25 11:23:47
* @LastEditors: yuananting * @LastEditors: Please set LastEditors
* @LastEditTime: 2021-06-03 17:12:01 * @LastEditTime: 2021-08-13 17:05:37
* @Description: 助学工具-题库-题目列表数据 * @Description: 助学工具-题库-题目列表数据
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/ */
......
...@@ -53,7 +53,7 @@ class BatchImportQuestionModal extends Component { ...@@ -53,7 +53,7 @@ class BatchImportQuestionModal extends Component {
if (User.getExpirationTime() && moment().valueOf() > Number(User.getExpirationTime())) { if (User.getExpirationTime() && moment().valueOf() > Number(User.getExpirationTime())) {
Modal.warning({ Modal.warning({
title:"服务已到期", title:"服务已到期",
content: "当前企业购买的小麦企学院服务已到期,如需继续使用学院功能,请尽快续费购买", content: `当前企业购买的${window.brandName}服务已到期,如需继续使用学院功能,请尽快续费购买`,
okText: "我知道了" okText: "我知道了"
}) })
return return
......
/* /*
* @Author: 吴文洁 * @Author: 吴文洁
* @Date: 2020-04-29 10:26:32 * @Date: 2020-04-29 10:26:32
* @LastEditors: yuananting * @LastEditors: wufan
* @LastEditTime: 2021-08-18 12:39:30 * @LastEditTime: 2021-09-03 10:33:05
* @Description: 内容线路由配置 * @Description: 内容线路由配置
*/ */
import Home from '@/modules/home/Home'; import Home from '@/modules/home/Home';
......
...@@ -18,22 +18,6 @@ import _ from 'underscore'; ...@@ -18,22 +18,6 @@ import _ from 'underscore';
import SwitchRoute from '@/modules/root/SwitchRoute'; import SwitchRoute from '@/modules/root/SwitchRoute';
import ErrorCollege from '@/modules/root/ErrorCollege'; import ErrorCollege from '@/modules/root/ErrorCollege';
const history = createHashHistory(); 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 = () => { export const RootRouter = () => {
return ( return (
......
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