Commit fab2e284 by maolipeng

Merge branch 'feature/zhujian/0726/qwLiving' into gray

# Conflicts:
#	src/index.html
#	src/index.tsx
#	src/modules/knowledge-base/components/KnowledgeBaseList.jsx
#	src/modules/root/App.tsx
parents 1746cbc5 ca0e4096
...@@ -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"
}, },
...@@ -146,4 +180,4 @@ ...@@ -146,4 +180,4 @@
"ali-oss": "^6.12.0", "ali-oss": "^6.12.0",
"react-sortable-hoc": "^1.11.0" "react-sortable-hoc": "^1.11.0"
} }
} }
\ No newline at end of file
...@@ -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)
}
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
*/ */
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,18 +40,18 @@ class Axios { ...@@ -40,18 +40,18 @@ 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()) {
headerObject.enterpriseId = User.getEnterpriseId(); headerObject.enterpriseId = User.getEnterpriseId();
...@@ -65,7 +65,7 @@ class Axios { ...@@ -65,7 +65,7 @@ class Axios {
'Content-Type': options.requestType === 'form' ? 'application/x-www-form-urlencoded' : 'application/json; charset=UTF-8', 'Content-Type': options.requestType === 'form' ? 'application/x-www-form-urlencoded' : 'application/json; charset=UTF-8',
} }
}); });
if (method !== 'GET' && options.requestType === 'form') { if (method !== 'GET' && options.requestType === 'form') {
instance.defaults.transformRequest = [(queryParam): string => { instance.defaults.transformRequest = [(queryParam): string => {
let ret: string = ''; let ret: string = '';
...@@ -92,8 +92,14 @@ class Axios { ...@@ -92,8 +92,14 @@ 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: "我知道了" okText: "我知道了"
}) })
} else if (success || resultCode === 0) { } else if (success || resultCode === 0) {
...@@ -104,24 +110,24 @@ class Axios { ...@@ -104,24 +110,24 @@ 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();
window.RCHistory.replace('/login'); window.RCHistory.replace('/login');
break; break;
case 403: case 403:
message.error('暂无查看权限'); message.error('暂无查看权限');
window.RCHistory.replace('/login'); window.RCHistory.replace('/login');
return Promise.reject(); return Promise.reject();
break; break;
case 504: case 504:
message.error('网络状况不稳定,如果出现数据异常,请刷新页面'); message.error('网络状况不稳定,如果出现数据异常,请刷新页面');
Promise.reject(); Promise.reject();
break; break;
default: default:
message.error(error.message); message.error(error.message);
break; break;
} }
return Promise.reject(error.message); return Promise.reject(error.message);
}); });
...@@ -130,7 +136,9 @@ class Axios { ...@@ -130,7 +136,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 => {
......
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
}
};
/*
* @Author: wufan
* @Date: 2021-05-11 10:21:37
* @LastEditors: Please set LastEditors
* @LastEditTime: 2021-07-21 14:25:37
* @Description: 企业微信api
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*
*/
import Platform from '@/common/js/platform';
import User from '@/common/js/user';
import Service from '@/common/js/service';
export default class WechatApi {
static async initConfig(params = { isAgentConfig: false, url: '' }) {
if(Platform.isWorkWx()){
return Service.Hades('anon/hades/getWxCorpJSAPISignature', {
storeId: User.getStoreId(),
url: params.url,
}).then((result) => {
const res = result.result;
this.config({
beta: true, // 必须这么写,否则wx.invoke调用形式的jsapi会有问题
debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: res.appId, // 必填,企业微信的corpID
timestamp: res.timestamp, // 必填,生成签名的时间戳
nonceStr: res.nonceStr, // 必填,生成签名的随机串
signature: res.signature, // 必填,签名,见 附录-JS-SDK使用权限签名算法
jsApiList: ['chooseImage', 'shareToExternalContact', 'selectExternalContact', 'selectEnterpriseContact'],
}).then(() => {
if (params.isAgentConfig) {
return new Promise(async (resolve, reject) => {
Service.Hades('anon/hades/getWxWorkJSAPISignature', {
storeId: User.getStoreId(),
url: params.url,
}).then((result2) => {
const res2 = result2.result;
this.agentConfig({
corpid: res2.corpid, // 必填,企业微信的corpid,必须与当前登录的企业一致
agentid: res2.agentid, // 必填,企业微信的应用id (e.g. 1000247)
timestamp: res2.timestamp, // 必填,生成签名的时间戳
nonceStr: res2.nonceStr, // 必填,生成签名的随机串
signature: res2.signature, // 必填,签名,见附录-JS-SDK使用权限签名算法
jsApiList: ['selectExternalContact', 'getCurExternalContact', 'getContext', 'shareToExternalContact', 'sendChatMessage', 'shareToExternalChat', 'startLiving', 'replayLiving'],
success: (res) => {
console.log(res, 'res-agentconfig');
console.info('window.WWOpenData', window.WWOpenData);
resolve(res);
},
fail: (err) => {
console.log(1213545344545)
console.log(err, 'err-agentconfig');
reject(err);
},
});
});
});
}
})
});
}else{
if (params.isAgentConfig) {
console.log(32132132,'cesgu')
return new Promise(async (resolve, reject) => {
Service.Hades('anon/hades/getWxWorkJSAPISignature', {
storeId: User.getStoreId(),
url: params.url,
}).then((result2) => {
const res2 = result2.result;
this.agentConfig({
corpid: res2.corpid, // 必填,企业微信的corpid,必须与当前登录的企业一致
agentid: res2.agentid, // 必填,企业微信的应用id (e.g. 1000247)
timestamp: res2.timestamp, // 必填,生成签名的时间戳
nonceStr: res2.nonceStr, // 必填,生成签名的随机串
signature: res2.signature, // 必填,签名,见附录-JS-SDK使用权限签名算法
jsApiList: ['selectExternalContact', 'getCurExternalContact', 'getContext', 'shareToExternalContact', 'sendChatMessage', 'shareToExternalChat', 'startLiving', 'replayLiving'],
success: (res) => {
console.log(res, 'res-agentconfig');
console.info('window.WWOpenData', window.WWOpenData);
resolve(res);
},
fail: (err) => {
console.log(1213545344545)
console.log(err, 'err-agentconfig');
reject(err);
},
});
});
});
}
}
}
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) {
return new Promise((success, fail) => {
console.info('wx.agentConfig', config);
wx.agentConfig({ ...config, success, fail });
}).then(
(res) => {
console.info('wx.agentConfig success', res);
return res;
},
(error) => {
console.error('wx.agentConfig fail', error);
throw error;
}
);
}
static getCurExternalContact() {
return new Promise((resolve, reject) => {
wx.ready(() => {
wx.invoke('getCurExternalContact', {}, function (res) {
if (res.err_msg == 'getCurExternalContact:ok') {
resolve(res.userId); //返回当前外部联系人userId
} else {
reject(res.err_msg); //错误处理
}
});
});
});
}
static getContext() {
return new Promise((resolve, reject) => {
wx.ready(() => {
wx.invoke('getContext', {}, function (res) {
if (res.err_msg == 'getContext:ok') {
resolve(res.entry); //返回进入H5页面的入口类型,目前有normal、contact_profile、single_chat_tools、group_chat_tools、chat_attachment
} else {
reject(res.err_msg); //错误处理
}
});
});
});
}
//进入直播间
static enterLiveRoom(id) {
return new Promise((resolve, reject) => {
wx.ready(() => {
wx.invoke('startLiving', {
"livingId": id,
}, function(res) {
if (res.err_msg === "startLiving:ok") {
resolve(true)
} else {
reject(res.err_msg); //错误处理
}
});
});
})
}
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>
......
...@@ -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;
......
...@@ -1698,4 +1698,24 @@ input:focus { ...@@ -1698,4 +1698,24 @@ input:focus {
.ant-tag-blue{ .ant-tag-blue{
background: transparent !important; background: transparent !important;
}
.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
...@@ -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);
......
...@@ -7,23 +7,24 @@ ...@@ -7,23 +7,24 @@
* @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'
}
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]
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);
} }
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
* @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#/',
} }
......
declare module 'jquery' declare module 'jquery'
declare module 'cropper' declare module 'cropper'
declare module 'ExamShareModal' declare module 'ExamShareModal'
declare module 'routeHooks'
// declare var this: any // declare var this: any
\ No newline at end of file
...@@ -47,11 +47,12 @@ ...@@ -47,11 +47,12 @@
<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 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>
</head> </head>
<body> <body>
<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>
<!-- <!--
This HTML file is a template. This HTML file is a template.
If you open it directly in the browser, you will see an empty page. If you open it directly in the browser, you will see an empty page.
......
...@@ -20,12 +20,21 @@ import '@/core/xmTD'; ...@@ -20,12 +20,21 @@ 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) => {
history.push(obj); history.push(obj);
...@@ -36,13 +45,22 @@ window.RCHistory = _.extend({}, history, { ...@@ -36,13 +45,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(<RootRouter />, document.getElementById('root')); ReactDOM.render(<RootRouter />, document.getElementById('root'));
} }
......
/*
* @Author: your name
* @Date: 2021-08-04 15:21:36
* @LastEditTime: 2021-08-04 15:23:37
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: /xiaomai-cloud-class-web/src/modules/college-manage/LimitTip.tsx
*/
import React, { useContext, useEffect, useState } from "react"; import React, { useContext, useEffect, useState } from "react";
import { Tooltip } from "antd" import { Tooltip } from "antd"
import { VersionContext } from "@/store/context"; import { VersionContext } from "@/store/context";
...@@ -26,7 +34,7 @@ export default function LimitTip(props:{total:number,type:string,tip:() => React ...@@ -26,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>
......
...@@ -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: '确定要返回吗?', window.RCHistory.push({
content: '返回后,本次编辑的内容将不被保存', pathname: `/live-course`,
okText: '确认返回',
cancelText: '留在本页',
icon: <span className='icon iconfont default-confirm-icon'>&#xe6f4;</span>,
onOk: () => {
window.RCHistory.push({
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,32 +39,72 @@ class DataList extends React.Component { ...@@ -39,32 +39,72 @@ class DataList extends React.Component {
current, current,
size, size,
}; };
CourseService.fetchUserData(params).then((res) => { if (this.state.type === "qiwei") {
if (res.result) { CourseService.fetchWorkWXUserData(params).then((res) => {
const { records = [], current, size, total } = res.result; if (res.result) {
const { records = [], current, size, total } = res.result;
this.setState({
studentData: records,
current,
size,
total,
loading: false,
});
}
});
} else {
CourseService.fetchUserData(params).then((res) => {
if (res.result) {
const { records = [], current, size, total } = res.result;
this.setState({
studentData: records,
current,
size,
total,
loading: false,
});
}
});
}
this.setState({
studentData: records,
current,
size,
total,
loading: false,
});
}
});
}; };
// 获取老师上课数据 // 获取老师上课数据
fetchLecturerData = () => { fetchLecturerData = () => {
const { liveCourseId } = this.state; const { liveCourseId } = this.state;
CourseService.fetchLecturerData({ liveCourseId }).then((res) => { if (this.state.type === "qiwei") {
if (res.result) { CourseService.fetchWorkWXLecturerData({ liveCourseId }).then((res) => {
this.setState({ if (res.result) {
teacherData: res.result, this.setState({
}); teacherData: res.result,
} });
}); }
});
} else {
CourseService.fetchLecturerData({ liveCourseId }).then((res) => {
if (res.result) {
this.setState({
teacherData: res.result,
});
}
});
}
}; };
studentTypeEnum = (type)=> {
if (type === "STUDENT") {
return "学员"
}
if (type === "NON_STUDENT") {
return "待加入"
}
if (type === "GUEST") {
return "游客"
}
}
// 进入直播次数列表 // 进入直播次数列表
getVisiterColumns() { getVisiterColumns() {
const columns = [ const columns = [
...@@ -159,27 +199,92 @@ class DataList extends React.Component { ...@@ -159,27 +199,92 @@ 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;
CourseService.exportStudentCourseData({ if (this.state.type === "qiwei") {
liveCourseId: liveCourseId, CourseService.exportWorkWXStudentCourseData({
exportLiveType: 'VISITOR', liveCourseId: liveCourseId,
storeId, exportLiveType: 'VISITOR',
}).then((res) => { storeId,
const link = res.result; }).then((res) => {
this.setState({ const link = res.result;
link, this.setState({
link,
});
document.getElementById('loadExcel').click();
if (res.success) {
message.success('导出成功!');
}
}); });
document.getElementById('loadExcel').click(); } else {
CourseService.exportStudentCourseData({
liveCourseId: liveCourseId,
exportLiveType: 'VISITOR',
storeId,
}).then((res) => {
const link = res.result;
this.setState({
link,
});
document.getElementById('loadExcel').click();
if (res.success) {
message.success('导出成功!');
}
});
}
if (res.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,18 +362,22 @@ class DataList extends React.Component { ...@@ -257,18 +362,22 @@ class DataList extends React.Component {
</div> </div>
</div> </div>
<div className='times item-block'> {
<div className={`times-num ${Number(teacherData.entryNum) > 0 ? 'can-click' : ''}`}> type !== "qiwei" &&
{Number(teacherData.entryNum) > 0 ? ( <div className='times item-block'>
<Popover content={this.showTable()} trigger='click'> <div className={`times-num ${Number(teacherData.entryNum) > 0 ? 'can-click' : ''}`}>
<span className='times-num'>{teacherData.entryNum || 0}</span> {Number(teacherData.entryNum) > 0 ? (
</Popover> <Popover content={this.showTable()} trigger='click'>
) : ( <span className='times-num'>{teacherData.entryNum || 0}</span>
<span className='times-num'>{0}</span> </Popover>
)} ) : (
<span className='times-num'>{0}</span>
)}
</div>
<div className='text'>进入直播间次数</div>
</div> </div>
<div className='text'>进入直播间次数</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>
<Tabs.TabPane tab="回放记录" key="playbackData"> {
<PlaybackData></PlaybackData> type !== "qiwei" &&
</Tabs.TabPane> <Tabs.TabPane tab="回放记录" key="playbackData">
<PlaybackData></PlaybackData>
</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,21 +106,29 @@ class AddLiveBasic extends React.Component { ...@@ -105,21 +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={_.find(this.props.exItems,(item)=>{return item === "courseName"})?{border:"1px solid red",display:"inline-block"}:{display:"inline-block"}}>
<Input <Input
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='opt-btns'>
<div className='img-content'>
{isDefaultCover && <span className='tag'>默认图</span>}
<img src={coverUrl} />
</div>
</div>
<div className='opt-btns'>
<Button <Button
onClick={() => { onClick={() => {
this.setState({ this.setState({
...@@ -133,22 +142,19 @@ class AddLiveBasic extends React.Component { ...@@ -133,22 +142,19 @@ 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 style={_.find(this.props.exItems,(item)=>{return item === "categoryId"})?{border:"1px solid red",display:"inline-block"}:{display:"inline-block"}}>
<CourseCatalogSelect <CourseCatalogSelect
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
......
...@@ -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,27 +40,26 @@ ...@@ -41,27 +40,26 @@
left: 8px; left: 8px;
} }
} }
}
.opt-btns {
.default-btn {
margin-left: 14px;
color: #2966ff;
cursor: pointer;
.opt-btns { &.disabled {
.default-btn { color: #ccc;
margin-left: 14px; cursor: not-allowed;
color: #2966ff;
cursor: pointer;
&.disabled {
color: #ccc;
cursor: not-allowed;
}
} }
}
.ant-upload-list { .ant-upload-list {
display: none; display: none;
} }
.tips { .tips {
margin-top: 8px; margin-top: 8px;
color: #999; color: #999;
}
} }
} }
} }
......
...@@ -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,
......
.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;
}
}
// .ant-picker:hover .ant-picker-focused {
// border-color: red;
// }
}
.introduce {
display: flex;
}
.ant-select-item-option-selected:not(.ant-select-item-option-disabled) {
color: #2966FF;
}
// .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);
// }
// .ant-select:not(.ant-select-disabled):hover .ant-select-selector {
// border-color: red;
// }
}
\ 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'>
......
import React, { useState, useRef, useEffect, useContext } from 'react'
import { Route, withRouter } from 'react-router-dom';
import Breadcrumbs from "@/components/Breadcrumbs";
import moment from 'moment'
import { Form, Alert, Input, Button, InputNumber, DatePicker, Select, Radio, message, Modal } from 'antd';
import Service from "@/common/js/service";
import User from "@/common/js/user";
declare var wx: any;
const { Option } = Select;
const courseType = {
0: '通用直播',
1: '小班课',
2: '大班课',
3: '企业培训',
4: '活动直播'
}
function CerateQWCourse(props: any) {
const [courseName, setCourseName] = useState('');
const [liveDuration, setLiveDuration] = useState(60);
const [liveStart, setLiveStart] = useState(0);
const [type, setType] = useState('0');
function handleSave() {
const param = {
courseName,
description: '直播的简介,最多支持300个字节直播的简介,最多支持300个字节直播的简介,最多支持300个字节直播的简介,最多支持300个字节直播的简介,最多支持300个字节直播的简介,最多支持300个字节',
liveDuration: liveDuration * 60 * 100,
liveStart,
remindTime: 1000 * 60 * 10,
storeId: User.getStoreId(),
storeUserId: User.getStoreUserId(),
type: parseInt(type)
}
Service.Hades('anon/hades/wxWorkCreateLiveDemo', param).then((res) => {
wx.invoke('startLiving', {
"livingId": res.result,
}, function (res: any) {
if (res.err_msg == "startLiving:ok") {
// livingId = res.livingId;
}
});
})
}
return <div className="page createQWCourse ">
<Breadcrumbs navList={props.type === 'edit' ? "编辑考试" : "新建直播课"} goBack={props.history.goBack} />
<div className="box">
<div className="form">
<div className="title">直播信息</div>
<Form
labelCol={{ span: 3 }}
wrapperCol={{ span: 14 }}
layout="horizontal"
>
<Form.Item label="课程名称"
required>
<Input value={courseName} onChange={(e) => { setCourseName(e.target.value) }} style={{ width: 200 }} ></Input>
</Form.Item>
<Form.Item label="持续时长"
required>
<InputNumber value={liveDuration} max={1440} min={1} onChange={(value: any) => { setLiveDuration(parseInt(value) as any) }} style={{ width: 100 }} />
</Form.Item>
<Form.Item label="开始时间"
required>
<DatePicker
format="YYYY/MM/DD HH:mm"
value={liveStart ? moment(Number(liveStart)) : null}
style={{ width: 200 }}
placeholder="开始时间"
showTime
onChange={(date: any) => { setLiveStart(date ? date.valueOf() : 0) }}
/>
</Form.Item>
<Form.Item label="直播的类型"
required>
<Select value={type} placeholder="请选直播的类型" style={{ width: 200 }} onChange={(val) => {
setType(val)
}} >
{
Object.keys(courseType).map((key: any) => {
return <Option value={key}>{(courseType as any)[key]}</Option>
})
}
</Select>
</Form.Item>
</Form>
</div>
</div>
<div className="footer">
<Button onClick={props.history.goBack}>取消</Button>
<Button type="primary" onClick={handleSave}>保存</Button>
</div>
</div>
}
export default withRouter(CerateQWCourse);
\ No newline at end of file
.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
...@@ -24,6 +24,7 @@ const defaultQuery = { ...@@ -24,6 +24,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 +51,7 @@ class LiveCourseFilter extends React.Component { ...@@ -50,6 +51,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
...@@ -150,6 +152,7 @@ class LiveCourseFilter extends React.Component { ...@@ -150,6 +152,7 @@ class LiveCourseFilter extends React.Component {
courseState: undefined, courseState: undefined,
current: 1, current: 1,
shelfState: null, shelfState: null,
thirdPartType: null
}, },
}, },
() => { () => {
...@@ -159,7 +162,7 @@ class LiveCourseFilter extends React.Component { ...@@ -159,7 +162,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 +202,7 @@ class LiveCourseFilter extends React.Component { ...@@ -199,7 +202,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 +298,37 @@ class LiveCourseFilter extends React.Component { ...@@ -295,6 +298,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'>小麦直播</Option>
</Select>
</div>
)}
</div> </div>
<div className='reset-fold-area'> <div className='reset-fold-area'>
......
...@@ -9,55 +9,96 @@ ...@@ -9,55 +9,96 @@
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 = ()=>{
window.RCHistory.push({ this.setState({
pathname: '/create-live-course?type=add', showModeSelect: true
})
// window.RCHistory.push({
// pathname: '/create-live-course?type=add',
// })
}
onModeSelectClose = ()=> {
this.setState({
showModeSelect: false
})
}
onModeSelected = (type)=> {
this.setState({
showModeSelect: false
}) })
if (type === 0) {
window.RCHistory.push({
pathname: '/create-live-course?type=add',
})
} else if (type === 1) {
const { match } = this.props;
this.props.history.push(`${match.url}/createqwcourse?type=add`)
}
}
handleCreateQWCouese=()=>{
const { match } = this.props;
this.props.history.push(`${match.url}/createqwcourse`)
} }
// 下载直播客户端 // 下载直播客户端
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);
a.href = res.result.releaseUrl; a.href = res.result.releaseUrl;
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";
interface LiveModeSelectProps {
isShow: boolean;
onClose: ()=> void;
onSelected: (type: number)=> void;
}
export default function LiveModeSelect(props: LiveModeSelectProps) {
const handleSelect0 = (e: React.MouseEvent<HTMLDivElement>)=> {
const { onSelected } = props
onSelected(0)
}
const handleSelect1 = (e: React.MouseEvent<HTMLDivElement>)=> {
const { onSelected } = props
onSelected(1)
}
const handleClose = (e: React.MouseEvent<HTMLDivElement>)=> {
props.onClose()
}
return createPortal(
<div className={`livemode-select${props.isShow ? "":" livemode-select-none"}`}>
<div className="dialog">
<div className="header">
<div className="title">选择直播方式</div>
<span className="icon iconfont close" onClick={handleClose}>&#xe6ef;</span>
</div>
<div className="content">
<div className="item xiaomai-logo">
<div className="logo"></div>
<div className="item-title">小麦直播</div>
<div className="des">通过小麦企学院“PC客户<br/>端”进行直播</div>
<div className="button" onClick={handleSelect0}>立即创建</div>
</div>
<div className="item qiwei-logo">
<div className="logo qiwei-logo"></div>
<div className="item-title">企微直播</div>
<div className="des">通过“企业微信APP”<br/>进行直播</div>
<div className="button" onClick={handleSelect1}>立即创建</div>
</div>
</div>
</div>
</div>,
document.body
)
}
\ No newline at end of file
...@@ -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'>
......
...@@ -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,47 +107,56 @@ class PreviewCourseModal extends React.Component { ...@@ -107,47 +107,56 @@ 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 (type === "add") { if (this.props.bizType === "qiwei") {
const _liveDate = moment(calendarTime[0]).format("YYYY-MM-DD"); let _startTime = startTime === 0 ? moment().valueOf():startTime
console.log("_liveDate", _liveDate); startTimeStr = moment(_startTime).format("YYYY-MM-DD HH:mm")
const _timeHorizonStart = moment(startTime).format("HH:mm"); endTimeStr = moment(endTime === 0?moment(_startTime+Number(duration)*1000).valueOf():endTime).format("HH:mm")
const _timeHorizonEnd = moment(endTime).format("HH:mm"); console.log(duration)
const _startTime = moment(_liveDate + " " + _timeHorizonStart).format(
"x"
);
const _endTime = moment(_liveDate + " " + _timeHorizonEnd).format("x");
const {
liveDateStr: _liveDateStr,
startTimeStr: _startTimeStr,
endTimeStr: _endTimeStr,
} = this.dealWithTime(_startTime, _endTime);
liveDateStr = _liveDateStr;
startTimeStr = _startTimeStr;
endTimeStr = _endTimeStr;
} else { } else {
const _liveDate = moment(liveDate).format("YYYY-MM-DD"); if (type === "add") {
const _timeHorizonStart = moment(timeHorizonStart).format("HH:mm"); const _liveDate = moment(calendarTime[0]).format("YYYY-MM-DD");
const _timeHorizonEnd = moment(timeHorizonEnd).format("HH:mm"); console.log("_liveDate", _liveDate);
const startTime = moment(_liveDate + " " + _timeHorizonStart).format("x"); const _timeHorizonStart = moment(startTime).format("HH:mm");
const endTime = moment(_liveDate + " " + _timeHorizonEnd).format("x"); const _timeHorizonEnd = moment(endTime).format("HH:mm");
const { const _startTime = moment(_liveDate + " " + _timeHorizonStart).format(
liveDateStr: _liveDateStr, "x"
startTimeStr: _startTimeStr, );
endTimeStr: _endTimeStr, const _endTime = moment(_liveDate + " " + _timeHorizonEnd).format("x");
} = this.dealWithTime(startTime, endTime); const {
liveDateStr: _liveDateStr,
liveDateStr = _liveDateStr; startTimeStr: _startTimeStr,
startTimeStr = _startTimeStr; endTimeStr: _endTimeStr,
endTimeStr = _endTimeStr; } = this.dealWithTime(_startTime, _endTime);
liveDateStr = _liveDateStr;
startTimeStr = _startTimeStr;
endTimeStr = _endTimeStr;
} else {
const _liveDate = moment(liveDate).format("YYYY-MM-DD");
const _timeHorizonStart = moment(timeHorizonStart).format("HH:mm");
const _timeHorizonEnd = moment(timeHorizonEnd).format("HH:mm");
const startTime = moment(_liveDate + " " + _timeHorizonStart).format("x");
const endTime = moment(_liveDate + " " + _timeHorizonEnd).format("x");
const {
liveDateStr: _liveDateStr,
startTimeStr: _startTimeStr,
endTimeStr: _endTimeStr,
} = this.dealWithTime(startTime, endTime);
liveDateStr = _liveDateStr;
startTimeStr = _startTimeStr;
endTimeStr = _endTimeStr;
}
} }
return ( return (
<Modal <Modal
title="预览" title="预览"
......
...@@ -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'>
......
...@@ -363,15 +363,15 @@ class AddVideoCourse extends React.Component { ...@@ -363,15 +363,15 @@ class AddVideoCourse extends React.Component {
// 保存 // 保存
handleSubmit = () => { handleSubmit = () => {
//过期判断 //过期判断
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 {
id, id,
...@@ -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'>
......
...@@ -7,59 +7,59 @@ import moment from "moment"; ...@@ -7,59 +7,59 @@ import moment from "moment";
export default function HomeTip() { export default function HomeTip() {
const [isOverNum, setIsOverNum] = useState<boolean>(false) const [isOverNum, setIsOverNum] = useState<boolean>(false)
const [tipType, setTipType] = useState(0) //0不显示1即将过期2已过期 const [tipType, setTipType] = useState(0) //0不显示1即将过期2已过期
const [expirationTime, setExpirationTime] = useState("") const [expirationTime, setExpirationTime] = useState("")
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)
setExpirationTime(versionInfo.validEndTime) setExpirationTime(versionInfo.validEndTime)
if (versionInfo.stateEnum === "NO") { if (versionInfo.stateEnum === "NO") {
setTipType(2) setTipType(2)
} else if (versionInfo.surplusDayTime === 30 || versionInfo.surplusDayTime <= 7) { } else if (versionInfo.surplusDayTime === 30 || versionInfo.surplusDayTime <= 7) {
setTipType(1) setTipType(1)
}
} }
}
},[versionInfo])
}, [versionInfo])
return (
<div className="home-tip"> return (
{ <div className="home-tip">
(isOverNum || tipType !== 0) && {
(isOverNum || tipType !== 0) &&
<div className="tip"> <div className="tip">
<Carousel dotPosition="left" dots={false} autoplay={true} autoplaySpeed={5000}> <Carousel dotPosition="left" dots={false} autoplay={true} autoplaySpeed={5000}>
{ {
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>
) )
} }
{ {
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>
) )
} }
{ {
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>
) )
} }
</Carousel> </Carousel>
</div> </div>
} }
</div> </div>
) )
} }
\ No newline at end of file \ No newline at end of file
...@@ -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>
......
...@@ -16,10 +16,10 @@ import User from '@/common/js/user'; ...@@ -16,10 +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 } from '@/store/actions/index'; import { setStoreGroupPermission, setStorePermission, setStoreGroupList, setStoreList } 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 { func } from 'prop-types';
const { Footer, Sider, Content } = Layout; const { Footer, Sider, Content } = Layout;
...@@ -37,6 +37,8 @@ const App: React.FC = (props: any) => { ...@@ -37,6 +37,8 @@ const App: React.FC = (props: any) => {
useEffect(() => { useEffect(() => {
getStorePermission(); getStorePermission();
initWechatConfig();
getStoreAndUserInfo(); getStoreAndUserInfo();
getVersion(); getVersion();
if (window.location.hash === "#/") { if (window.location.hash === "#/") {
...@@ -46,6 +48,11 @@ const App: React.FC = (props: any) => { ...@@ -46,6 +48,11 @@ const App: React.FC = (props: any) => {
} }
}, []) }, [])
async function initWechatConfig() {
WechatApi.initConfig({ isAgentConfig: true, url: window.location.href.split('#')[0] })
}
useEffect(() => { useEffect(() => {
getStorePermission(); getStorePermission();
}, [window.location.hash]) }, [window.location.hash])
......
...@@ -6,6 +6,7 @@ import BaseService from "@/domains/basic-domain/baseService"; ...@@ -6,6 +6,7 @@ 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 { brandLogo } from '@/domains/brand/constants'
import './CreateCollege.less'; import './CreateCollege.less';
let cutFlag = false; let cutFlag = false;
...@@ -16,7 +17,7 @@ export default class CreateCollege extends React.Component { ...@@ -16,7 +17,7 @@ export default class CreateCollege extends React.Component {
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, // 需要被截取的图片
...@@ -111,7 +112,7 @@ export default class CreateCollege extends React.Component { ...@@ -111,7 +112,7 @@ export default class CreateCollege extends React.Component {
<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">
...@@ -134,7 +135,7 @@ export default class CreateCollege extends React.Component { ...@@ -134,7 +135,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,
}) })
}} }}
......
...@@ -337,7 +337,7 @@ function Header(props) { ...@@ -337,7 +337,7 @@ function Header(props) {
<div <div
className='url-link' className='url-link'
onClick={() => { onClick={() => {
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}`); 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}`);
}}> }}>
{'立即前往 >'} {'立即前往 >'}
</div> </div>
...@@ -355,12 +355,15 @@ function Header(props) { ...@@ -355,12 +355,15 @@ function Header(props) {
<span className='text'>分享学院</span> <span className='text'>分享学院</span>
</span> </span>
</div> </div>
<div className='help'> {
<a href={helpCenterUrl} target='_blank' className='help-btn'> process.env.BRAND == 'xiaomai' && <div className='help'>
<span className='icon iconfont tool-tip-right'>&#xe8ed;</span> <a href={helpCenterUrl} target='_blank' className='help-btn'>
<span className='text'>帮助中心</span> <span className='icon iconfont tool-tip-right'>&#xe8ed;</span>
</a> <span className='text'>帮助中心</span>
</div> </a>
</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 { MainRoutes, RedirectRoutes } from '@/routes'; import { Modal } from 'antd';
import { MainRoutes, RedirectRoutes } from '@/routes';
import routeHook from '@/core/routeHook'
import Bus from '@/core//bus';
function Main(props) {
const { menuType } = props;
console.log("menuType", menuType);
useEffect(() => {
Bus.bind('showRouteChangeModal',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>
), ),
......
...@@ -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,14 +275,14 @@ function AddExam(props: any) { ...@@ -275,14 +275,14 @@ 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;
} }
if (props.type === 'edit') { if (props.type === 'edit') {
if (item.examName === examName && item.examId !== match.params.id) { if (item.examName === examName && item.examId !== match.params.id) {
result = item; result = item;
} }
} else { } else {
if (item.examName === examName) { if (item.examName === examName) {
...@@ -314,9 +314,9 @@ function AddExam(props: any) { ...@@ -314,9 +314,9 @@ function AddExam(props: any) {
<Breadcrumbs navList={title} goBack={handleGoBack} /> <Breadcrumbs navList={title} goBack={handleGoBack} />
<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
labelCol={{ span: 3 }} labelCol={{ span: 3 }}
...@@ -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>
...@@ -458,7 +458,7 @@ function AddExam(props: any) { ...@@ -458,7 +458,7 @@ function AddExam(props: any) {
onChange={(val) => { setNeedPhone(val ? 'NEED_PHONE_VERIFY' : 'DO_NOT_NEED_PHONE_VERIFY') }} onChange={(val) => { setNeedPhone(val ? 'NEED_PHONE_VERIFY' : 'DO_NOT_NEED_PHONE_VERIFY') }}
></Switch> ></Switch>
<div style={{ position: 'relative', left: 8, color: "#999" }}> <div style={{ position: 'relative', left: 8, color: "#999" }}>
{needPhone == 'NEED_PHONE_VERIFY' ? '已开启,学员需绑定手机号才可参与考试' : '已关闭,学员无需绑定手机号即可参与考试'} {needPhone == 'NEED_PHONE_VERIFY' ? '已开启,学员需绑定手机号才可参与考试' : '已关闭,学员无需绑定手机号即可参与考试'}
</div> </div>
</div> </div>
</Form.Item> </Form.Item>
...@@ -470,7 +470,7 @@ function AddExam(props: any) { ...@@ -470,7 +470,7 @@ function AddExam(props: any) {
onChange={(val) => { setNeedOptionDisorder(val ? 'OPTION_RANDOM' : 'OPTION_SORT') }} onChange={(val) => { setNeedOptionDisorder(val ? 'OPTION_RANDOM' : 'OPTION_SORT') }}
></Switch> ></Switch>
<div style={{ position: 'relative', left: 8, color: "#999" }}> <div style={{ position: 'relative', left: 8, color: "#999" }}>
{needOptionDisorder == 'OPTION_RANDOM' ? '已开启,选项随机排序' : '已关闭,选项按设置顺序排序'} {needOptionDisorder == 'OPTION_RANDOM' ? '已开启,选项随机排序' : '已关闭,选项按设置顺序排序'}
</div> </div>
</div> </div>
......
...@@ -799,7 +799,7 @@ class OperatePaper extends Component { ...@@ -799,7 +799,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 }}
......
...@@ -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
......
...@@ -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