Commit 90015a99 by guomingpang
parents b89d9538 c36c396c
......@@ -72,6 +72,7 @@ function getClientEnvironment(publicUrl) {
// Useful for determining whether we’re running in production mode.
// Most importantly, it switches React into the correct mode.
NODE_ENV: process.env.NODE_ENV || 'development',
BRAND: process.env.BRAND || 'xiaomai',
DEPLOY_ENV: process.env.DEPLOY_ENV,
// Useful for resolving the correct path to static assets in `public`.
// 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 @@
"style-loader": "0.23.1",
"terser-webpack-plugin": "2.3.8",
"ts-pnp": "1.1.6",
"better-npm-run": "^0.1.0",
"typescript": "^4.0.2",
"underscore": "^1.10.2",
"url-loader": "2.3.0",
......@@ -111,12 +112,45 @@
"start:rc": "cross-env DEPLOY_ENV=rc 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:syoo": "better-npm-run start:syoo",
"build:dev": "cross-env DEPLOY_ENV=dev node scripts/build.js",
"build:dev1": "cross-env DEPLOY_ENV=dev node scripts/build.js",
"build:dev1": "better-npm-run build:dev1",
"build:rc": "cross-env DEPLOY_ENV=rc node scripts/build.js",
"build:gray": "cross-env DEPLOY_ENV=gray node scripts/build.js",
"build: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"
},
"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": {
"extends": "react-app"
},
......@@ -146,4 +180,4 @@
"ali-oss": "^6.12.0",
"react-sortable-hoc": "^1.11.0"
}
}
}
\ No newline at end of file
......@@ -17,7 +17,7 @@
<!-- <link rel="apple-touch-icon" href="../src/common/images/logo.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>
<style type="text/css">
......@@ -75,7 +75,7 @@
$(document).ready(function () {
var BASIC_HOST_MAP = {
dev: 'https://dev-heimdall.xiaomai5.com/',
dev1: 'https://dev1-heimdall.xiaomai5.com/',
dev1: 'https://dev-heimdall.xiaomai5.com/',
rc: 'https://rc-heimdall.xiaomai5.com/',
gray: 'https://gray-heimdall.xiaomai5.com/',
prod: 'https://gateway.xiaomai5.com/'
......@@ -104,11 +104,12 @@
const appTermEnum = getParameterByName('appTermEnum');
const code = getParameterByName('code');
const ticket = getParameterByName('ticket');
const corpType = getParameterByName('corpType') || 'X_MAI';
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`
location.href = url
})
......@@ -118,7 +119,8 @@
postJSON("hades/anon/hades/wXWorkUserTicketLogin", {
appTermEnum: appTermEnum,
code: code,
ticket: ticket
ticket: ticket,
corpType
}, (res) => {
if (res.code == 200) {
$('#success').show()
......@@ -133,7 +135,20 @@
}
function GetJSON(url, callback) {
const ajaxOptions = {
type: 'GET',
url: BASIC_HOST_MAP[env] + url+`?corpType=${corpType}`,
contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
timeout: 20000,
success(res, status, xhr) {
callback(res)
},
};
$.ajax(ajaxOptions)
}
......
......@@ -20,8 +20,8 @@
}
.container-left-body-table{
width: 300px;
height: 330px;
height: 360px;
overflow: scroll;
.ant-table {
border: none;
min-height: 250px !important;
......
/*
* @Author: 吴文洁
* @Date: 2020-08-31 09:34:31
* @LastEditors: yuananting
* @LastEditTime: 2021-07-12 17:40:26
* @LastEditors: Please set LastEditors
* @LastEditTime: 2021-08-17 16:27:31
* @Description:
* @Copyright: 杭州杰竞科技有限公司 版权所有
*/
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, AxiosPromise, AxiosError } from 'axios';
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 User from './user';
......@@ -24,12 +24,12 @@ interface FetchOptions {
requestType: string, // 请求类型 form为表单类型 json为json类型,默认json类型
reject: boolean,
}
interface HeadersType{
storeId?:any,
storeUserId?:any,
userId?:any,
xmtoken?:any,
enterpriseId?:string|null
interface HeadersType {
storeId?: any,
storeUserId?: any,
userId?: any,
xmtoken?: any,
enterpriseId?: string | null
}
class Axios {
static post(
......@@ -40,18 +40,18 @@ class Axios {
): Promise<any> {
const _url = `${url}?storeId=${User.getStoreId()}&token=${User.getToken()}&storeUserId=${User.getStoreUserId()}&userId=${User.getUserId()}`;
return new Promise((resolve, reject) => {
let headerObject:HeadersType={};
if(User.getStoreId()){
headerObject.storeId = User.getStoreId();
let headerObject: HeadersType = {};
if (User.getStoreId()) {
headerObject.storeId = User.getStoreId();
}
if(User.getStoreUserId()){
headerObject.storeUserId = User.getStoreUserId();
if (User.getStoreUserId()) {
headerObject.storeUserId = User.getStoreUserId();
}
if(User.getUserId()){
headerObject.userId = User.getUserId();
if (User.getUserId()) {
headerObject.userId = User.getUserId();
}
if(User.getToken()){
headerObject.xmtoken = User.getToken();
if (User.getToken()) {
headerObject.xmtoken = User.getToken();
}
if (User.getEnterpriseId()) {
headerObject.enterpriseId = User.getEnterpriseId();
......@@ -65,7 +65,7 @@ class Axios {
'Content-Type': options.requestType === 'form' ? 'application/x-www-form-urlencoded' : 'application/json; charset=UTF-8',
}
});
if (method !== 'GET' && options.requestType === 'form') {
instance.defaults.transformRequest = [(queryParam): string => {
let ret: string = '';
......@@ -92,8 +92,20 @@ class Axios {
const { message: ResMessage, success, resultMsg, code: resultCode } = response.data;
if (resultCode === "CROP_DEPLOY_PAST_BETTER") {
Modal.warning({
title:"服务已到期",
content: "当前企业购买的小麦企学院服务已到期,如需继续使用学院功能,请尽快续费购买",
title: "服务已到期",
content: `当前企业购买的${window.brandName}服务已到期,如需继续使用学院功能,请尽快续费购买`,
okText: "我知道了"
})
} else if (resultCode === "LIVE_START_FORBID_DEL") {
Modal.warning({
title:"提示",
content: "直播进行中,无法删除直播",
okText: "我知道了"
})
}else if(resultCode === 'STORE_NUM_FULL'){
Modal.warning({
title:"提示",
content: "企业总学院数达到上限,无法继续创建。",
okText: "我知道了"
})
} else if (success || resultCode === 0) {
......@@ -104,24 +116,24 @@ class Axios {
return Promise.reject(response.data);
}, (error): AxiosPromise => {
const requestStatus = error.request.status
switch (requestStatus){
switch (requestStatus) {
case 401:
User.removeUserId();
User.removeToken();
window.RCHistory.replace('/login');
break;
break;
case 403:
message.error('暂无查看权限');
window.RCHistory.replace('/login');
return Promise.reject();
break;
break;
case 504:
message.error('网络状况不稳定,如果出现数据异常,请刷新页面');
Promise.reject();
break;
break;
default:
message.error(error.message);
break;
break;
}
return Promise.reject(error.message);
});
......@@ -130,7 +142,9 @@ class Axios {
if (method === 'GET') {
config = Object.assign({ params, url: `${BASIC_HOST}${_url}`, method });
} 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 => {
......
module.exports = {
isWeiXin() {
const ua = navigator.userAgent.toLowerCase();
return (ua.indexOf('micromessenger') > 0) && !(/wxwork/i.test(navigator.userAgent));
},
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';
console.log(wx.agentConfig,' console.log(wx.agentConfig) ')
export default class WechatApi {
static initConfig(params = { isAgentConfig: false, url: '' }) {
if (Platform.isWorkWx()) {
return new Promise(async (resolve, reject) => {
Service.Hades('anon/hades/getWxCorpJSAPISignature', {
storeId: User.getStoreId(),
url: window.location.href.split('#')[0],
}).then((result) => {
const res = result.result;
wx.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: ['scanQRCode'],
});
})
wx.ready(() => {
Service.Hades('anon/hades/getWxWorkJSAPISignature', {
storeId: User.getStoreId(),
url: window.location.href.split('#')[0],
}).then((result2) => {
const res2 = result2.result;
wx.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, 'agentConfig 成功', 'res-agentconfig');
resolve(res);
},
fail: (err) => {
console.log(1213545344545)
console.log(err, 'err-agentconfig');
},
});
});
});
wx.error((err) => {
console.log('getWxCorpJSAPISignature', err)
});
})
} else {
return new Promise(async (resolve, reject) => {
Service.Hades('anon/hades/getWxWorkJSAPISignature', {
storeId: User.getStoreId(),
url: window.location.href.split('#')[0],
}).then((result2) => {
const res2 = result2.result;
wx.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, 'agentConfig 成功', 'res-agentconfig');
resolve(res);
},
fail: (err) => {
console.log(1213545344545)
console.log(err, 'err-agentconfig');
},
});
});
});
}
}
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); //错误处理
}
});
});
})
}
}
@font-face {
font-family: 'iconfont'; /* Project id 2223403 */
src: url('//at.alicdn.com/t/font_2223403_oe5p510553.woff2?t=1624259078391') format('woff2'),
url('//at.alicdn.com/t/font_2223403_oe5p510553.woff?t=1624259078391') format('woff'),
url('//at.alicdn.com/t/font_2223403_oe5p510553.ttf?t=1624259078391') format('truetype');
font-family: 'iconfont'; /* Project id 2223403 */
src: url('//at.alicdn.com/t/font_2223403_7261tsts1dc.woff2?t=1628475376853') format('woff2'),
url('//at.alicdn.com/t/font_2223403_7261tsts1dc.woff?t=1628475376853') format('woff'),
url('//at.alicdn.com/t/font_2223403_7261tsts1dc.ttf?t=1628475376853') format('truetype');
}
.iconfont {
font-family: 'iconfont' !important;
......
import React, { ReactElement } from "react";
import { Popover } from "antd";
import { TooltipPlacement } from "antd/lib/tooltip";
import { brandLogo,xfrwm } from '@/domains/brand/constants'
import { ActionType } from "rc-trigger/lib/interface";
import "./ContactWidget.less"
interface ContactWidgetProps {
......@@ -14,7 +16,7 @@ function Content() {
return (
<div className="contact-widget">
<div className="qrcode">
<img src="https://cdn.xiaomai5.com/qixueyuankehu.png" alt=""></img>
<img src={xfrwm} alt=""></img>
<div className="des">微信/企业微信扫码咨询</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>
......
import React, { useRef, useLayoutEffect } from 'react'
export default function WWOpenDataCom({ type, openid }) {
const ref = useRef(null)
useLayoutEffect(() => {
console.log('1111');
console.log(WWOpenData);
WWOpenData && WWOpenData.bind(ref.current)
})
return <ww-open-data ref={ref} type={type} openid={openid} />
}
\ No newline at end of file
import React, { useContext, useRef, useLayoutEffect } from 'react'
import { XMContext } from '@/store/context';
import WWOpenData from './WWOpenData'
export default function WWOpenDataCom(props) {
const ctx = useContext(XMContext);
const ref = useRef(null)
return ctx.xmState.wechatLogin ? <WWOpenData {...props} /> : <div></div>
}
\ No newline at end of file
......@@ -330,9 +330,9 @@ mr0 {
}
// ant badge改小
.ant-badge {
transform: translate(-8px, -8px) scale(0.7) !important;
}
// .ant-badge {
// transform: translate(-8px, -8px) scale(0.7) !important;
// }
.ant-select-selection {
border-color: @xm-color-border !important;
......
......@@ -1605,7 +1605,13 @@ input:focus {
color: #2966FF !important;
margin-right: 16px !important;
}
.default-warning-icon {
font-size: 22px !important;
line-height: 22px !important;
float: left !important;
color: #FF4F4F !important;
margin-right: 16px !important;
}
.m-content {
position: absolute;
top: 0;
......@@ -1698,4 +1704,24 @@ input:focus {
.ant-tag-blue{
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";
export function fetchLecturerData(params: object) {
return Service.Hades("public/courseCloud/queryTeacherVisitData", params);
}
export function fetchWorkWXLecturerData(params: object) {
return Service.Hades("public/courseCloud/queryWechatLiveTeacherData", params);
}
export function getQrcode(params: object) {
return Service.Sales("public/businessShow/convertShortUrls", params);
}
......@@ -19,11 +22,18 @@ export function getQrcode(params: object) {
export function fetchUserData(params: object) {
return Service.Hades("public/courseCloud/queryStudentVisitData", params);
}
export function fetchWorkWXUserData(params: object) {
return Service.Hades("public/courseCloud/queryWechatLiveStudentData", params);
}
export function createLiveCloudCourse(params: object) {
return Service.Hades("public/courseCloud/createLiveCloudCourse", params);
}
export function createWorkWXLiveCourse(params: object) {
return Service.Hades("public/courseCloud/createWechatLiveCourse", params);
}
export function getLiveCloudCoursePage(params: object) {
return Service.Hades("public/courseCloud/getLiveCloudCoursePage", params);
}
......@@ -32,6 +42,10 @@ export function exportStudentCourseData(params: object) {
return Service.Hades("public/courseCloud/exportCourseCloudVisitorAsync", params);
}
export function exportWorkWXStudentCourseData(params: object) {
return Service.Hades("public/courseCloud/exportWechatLiveStudentData", params);
}
export function exportPlayBackCourseData(params: object) {
return Service.Hades("public/courseCloud/exportCourseCloudPlayBackSync", params);
}
......@@ -42,16 +56,27 @@ export function getLiveCloudCourseDetail(params: object) {
return Service.Hades("public/courseCloud/getLiveCloudCourseDetail", params);
}
export function getWorkWXLiveCourseDetail(params: object) {
return Service.Hades("public/courseCloud/getWechatLiveCourseDetail", params)
}
export function updateLiveCloudCourse(params: object) {
return Service.Hades("public/courseCloud/updateLiveCloudCourse", params);
}
export function updateWorkWXLiveCourse(params: object) {
return Service.Hades("public/courseCloud/editWechatLiveCourse", params);
}
export function turnOnOrOffLiveCloudCourse(params: object) {
return Service.Hades("public/courseCloud/turnOnOrOffLiveCloudCourse", params);
}
export function delLiveCloudCourse(params: object) {
return Service.Hades("public/courseCloud/delLiveCloudCourse", params);
}
export function delWorkWXLiveCourse(params: object) {
return Service.Hades("public/courseCloud/delWechatLiveCourse", params);
}
//该接口主要用于培训计划关联直播课的接口(会筛选掉已关联的直播课)
export function getLiveCloudCourseBasePage(params: object) {
return Service.Hades("public/courseCloud/getLiveCloudCourseBasePage", params);
......
/*
* @Author: wufan
* @Date: 2020-11-25 18:25:02
* @LastEditors: zhangleyuan
* @LastEditTime: 2021-03-09 10:28:03
* @LastEditors: Please set LastEditors
* @LastEditTime: 2021-07-30 17:00:06
* @Description: Description
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
......@@ -75,6 +75,36 @@ export function updateStoreMessage(params: object) {
export function getStoreDetail(params: object) {
return Service.Hades("public/hades/getStoreDetail", params);
}
export function getByDepartmentId(params: object) {
return Service.Hades("public/hades/getByDepartmentId", params);
}
export function getDepartmentUser(params: object) {
return Service.Hades("/public/hades/getDepartmentAndDepartmentUserByName", params);
}
export function getDepartmentUserNotPage(params: object) {
return Service.Hades("public/hades/getDepartmentAndDepartmentUserNotPageByName", params);
}
export function addDepartment(params: object) {
return Service.Hades("public/hades/addDepartment", params);
}
export function editDepartment(params: object) {
return Service.Hades("public/hades/editDepartment", params);
}
export function delDepartment(params: object) {
return Service.Hades("public/hades/delDepartment", params);
}
export function queryDepartmentTree(params: object) {
return Service.Hades("public/hades/queryDepartmentTree", params);
}
export function getStoreCustomerAndDepNamePage(params: object) {
return Service.Hades("public/hades/getStoreCustomerAndDepNamePage", params);
}
export function delDepartmentUser(params: object) {
return Service.Hades("public/hades/delDepartmentUser", params);
}
export function syncWorkWeChatDepartment(params: object) {
return Service.Hades("public/hades/syncWorkWeChatDepartment", params);
}
export function getSyncCount(params: object) {
return Service.Hades("public/hades/getSyncCount", params);
}
/*
* @Author: 陈剑宇
* @Date: 2020-05-07 14:43:01
* @LastEditTime: 2021-06-22 16:49:06
* @LastEditTime: 2021-08-11 22:52:04
* @LastEditors: Please set LastEditors
* @Description:
* @FilePath: /wheat-web-demo/src/domains/basic-domain/constants.ts
*/
import { MapInterface } from '@/domains/basic-domain/interface'
import { path, live } from '@/domains/brand/constants'
// 默认是 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 = {
dev: 'https://dev-heimdall.xiaomai5.com/',
dev1: 'https://dev1-heimdall.xiaomai5.com/',
dev1: 'https://dev-heimdall.xiaomai5.com/',
rc: 'https://rc-heimdall.xiaomai5.com/',
gray: 'https://gray-heimdall.xiaomai5.com/',
prod: 'https://gateway.xiaomai5.com/',
}
const PATH_MAP: MapInterface = {
dev: 'https://dev.xiaomai5.com/xiaomai-cloud-class-web/h5.html',
dev1: 'https://dev.xiaomai5.com/xiaomai-cloud-class-web/h5.html',
dev1: 'https://dev.xiaomai5.com/dev1/xiaomai-cloud-class-web/h5.html',
rc: 'https://rc.xiaomai5.com/xiaomai-cloud-class-web/h5.html',
gray: 'https://res.xiaomai0.com/xiaomai-cloud-class-web/gray/h5.html',
prod: 'https://res.xiaomai0.com/xiaomai-cloud-class-web/h5.html',
gray: path + '/gray/h5.html',
prod: path + '/h5.html',
}
export const YZ_APPId = "yozoqvpO2Hvz8346";
......
export const BRAND: any = process.env.BRAND;
const BrandNameMap: any = {
xiaomai: '小麦企学院',
syoo: '商有云课堂'
}
const BrandIconMap: any = {
xiaomai: 'https://image.xiaomaiketang.com/xm/bFkRBz7teA.png',
syoo: 'https://image.xiaomaiketang.com/xm/PfDseQHZtB.png'
}
const BrandLogoMap: any = {
xiaomai: 'https://image.xiaomaiketang.com/xm/6k8PPCmywG.png',
syoo: 'https://image.xiaomaiketang.com/xm/T7NRKwrfQE.png'
}
const BrandBannerMap: any = {
xiaomai: 'https://image.xiaomaiketang.com/xm/CDCcdAdaPs.png',
syoo: 'https://image.xiaomaiketang.com/xm/DzMHpX7GWF.png'
}
const PATH_MAP: any = {
xiaomai: 'https://res.xiaomai0.com/xiaomai-cloud-class-web',
syoo: 'https://study.syoo.cn/syoo-cloud-class-web',
}
const LIVE_SHARE_MAP: any = {
xiaomai: 'https://res.xiaomai0.com/store-live',
syoo: 'https://study.syoo.cn/syoo-store-live',
}
const CorpType_MAP: any = {
xiaomai: 'X_MAI',
syoo: 'S_YOU',
}
const XF_RWM_MAP: any = {
xiaomai: 'https://cdn.xiaomai5.com/qixueyuankehu.png',
syoo: 'https://image.xiaomaiketang.com/xm/Z2X2GTmKdj.png'
}
const LiveNameMap: any = {
xiaomai: '小麦直播',
syoo: '商有直播'
}
export const brandName: string = BrandNameMap[BRAND];
export const brandIcon: string = BrandIconMap[BRAND];
export const brandLogo: string = BrandLogoMap[BRAND];
export const brandBanner: string = BrandBannerMap[BRAND];
export const path: string = PATH_MAP[BRAND];
export const live: string = LIVE_SHARE_MAP[BRAND];
export const corpType: string = CorpType_MAP[BRAND];
export const xfrwm: string = XF_RWM_MAP[BRAND]
export const brandLiveName: string = LiveNameMap[BRAND]
window.brandName = BrandNameMap[BRAND];
......@@ -10,7 +10,7 @@ import {
fetchLecturerData, getCategoryTree, knowledgeMediaCoursePage, fetchUserData, exportStudentCourseData, exportPlayBackCourseData, fetchPlaybackList, createLiveCloudCourse, getLiveCloudCoursePage,
getLiveCloudCourseDetail, updateLiveCloudCourse, turnOnOrOffLiveCloudCourse, delLiveCloudCourse, changeVideoShelfState, createVideoSchedule, delVideoSchedule,
editVideoSchedule, userWatchInfo, videoSchedulePage, videoScheduleDetail, videoWatchInfo, getQrcode, getLiveCloudCourseBasePage, videoScheduleBasePage, relatedCourseToPlan,
lineDetailWatchInfo
lineDetailWatchInfo, createWorkWXLiveCourse, fetchWorkWXLecturerData, fetchWorkWXUserData, getWorkWXLiveCourseDetail, updateWorkWXLiveCourse, delWorkWXLiveCourse, exportWorkWXStudentCourseData
} from '@/data-source/course/request-api';
export default class courseService {
......@@ -18,6 +18,10 @@ export default class courseService {
static fetchLecturerData(params: any) {
return fetchLecturerData(params);
}
// 获取企微讲师上课数据
static fetchWorkWXLecturerData(params: any) {
return fetchWorkWXLecturerData(params);
}
// 生成二维码
static getQrcode(params: any) {
......@@ -28,17 +32,29 @@ export default class courseService {
static fetchUserData(params: any) {
return fetchUserData(params);
}
// 获取企微学员上课数据
static fetchWorkWXUserData(params: any) {
return fetchWorkWXUserData(params);
}
static createLiveCloudCourse(params: any) {
return createLiveCloudCourse(params);
}
//创建企微直播课
static createWorkWXLiveCourse(params: any) {
return createWorkWXLiveCourse(params)
}
static getLiveCloudCoursePage(params: any) {
return getLiveCloudCoursePage(params);
return getLiveCloudCoursePage({...params,terminalTypeEnum:"B_WEB"});
}
// 导出学生上课数据
static exportStudentCourseData(params: any) {
return exportStudentCourseData(params);
}
// 导出企微学生上课数据
static exportWorkWXStudentCourseData(params: any) {
return exportWorkWXStudentCourseData(params);
}
// 导出回放数据
static exportPlayBackCourseData(params: any) {
......@@ -53,15 +69,27 @@ export default class courseService {
static getLiveCloudCourseDetail(params: any) {
return getLiveCloudCourseDetail(params);
}
//获取企微直播详情
static getWorkWXLiveCourseDetail(params: any) {
return getWorkWXLiveCourseDetail(params);
}
static updateLiveCloudCourse(params: any) {
return updateLiveCloudCourse(params);
}
//编辑企微直播
static updateWorkWXLiveCourse(params: any) {
return updateWorkWXLiveCourse(params);
}
static turnOnOrOffLiveCloudCourse(params: any) {
return turnOnOrOffLiveCloudCourse(params);
}
static delLiveCloudCourse(params: any) {
return delLiveCloudCourse(params);
}
//删除企微直播
static delWorkWXLiveCourse(params: any) {
return delWorkWXLiveCourse(params);
}
static changeVideoShelfState(params: any) {
return changeVideoShelfState(params);
}
......
......@@ -2,11 +2,12 @@
* @Author: 吴文洁
* @Date: 2020-08-20 09:21:40
* @LastEditors: Please set LastEditors
* @LastEditTime: 2021-06-11 15:17:56
* @LastEditTime: 2021-08-11 22:50:48
* @Description:
* @Copyright: 杭州杰竞科技有限公司 版权所有
*/
import { MapInterface } from '@/domains/basic-domain/interface'
import { path, live } from '@/domains/brand/constants'
const ENV: string = process.env.DEPLOY_ENV || 'dev';
const appIdMap: MapInterface = {
......@@ -14,7 +15,7 @@ const appIdMap: MapInterface = {
dev1: 'wx3ea60e78ddfa277e',
rc: 'wx5c5a1fb71ecab7bc',
gray: "wx3dda02036493ada6", // 小麦校讯通
prod: 'wx3dda02036493ada6'
prod: 'wx3dda02036493ada6',
}
const shareUrlMap: MapInterface = {
......@@ -22,15 +23,15 @@ const shareUrlMap: MapInterface = {
'dev1': 'https://dev.xiaomai5.com/share/show?appid=',
'rc': 'https://rc.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 = {
dev: 'https://dev.xiaomai5.com/store-live/index.html#/',
dev1: 'https://dev.xiaomai5.com/store-live/index.html#/',
dev1: 'https://dev.xiaomai5.com/dev1/store-live/index.html#/',
rc: 'https://rc.xiaomai5.com/store-live/index.html#/',
gray: 'https://res.xiaomai0.com/store-live/gray/index.html#/',
prod: 'https://res.xiaomai0.com/store-live/index.html#/',
gray: live+'/gray/index.html#/',
prod: live+'/index.html#/',
}
......
/*
* @Author: zhangleyuan
* @Date: 2021-01-19 11:27:56
* @LastEditors: zhangleyuan
* @LastEditTime: 2021-03-08 10:36:04
* @LastEditors: Please set LastEditors
* @LastEditTime: 2021-07-29 13:37:10
* @Description: 描述一下
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
......@@ -12,6 +12,7 @@ export const storeRoleEnum = {
"1": "管理员",
"2": "普通讲师"
};
export const industryList = ["IT服务","制造业","批发/零售","生活服务","文化/体育/娱乐业","建筑/房地产","教育","运输/物流/仓储","医疗","政府","金融","能源/采矿","农林渔牧","其他行业"];
export const childIndustryList = {
......@@ -29,4 +30,9 @@ export const childIndustryList = {
"能源/采矿":["电力/热力/燃气/水供应业","石油/天然气","煤炭","有色金属","钢铁","其他"],
"农林渔牧":["农林渔牧"],
"其他行业":["科学研究和技术服务业","社会组织","水利和环境管理","国际组织","其他"]
}
export const DepType = {
'departMentTab':'DEP_ORG',
'postGrouptab':'DEP_POST',
'customGroupTab':'DEP_CUSTOM'
}
\ No newline at end of file
/*
* @Author: wufan
* @Date: 2020-11-25 18:25:02
* @LastEditors: zhangleyuan
* @LastEditTime: 2021-03-08 11:48:43
* @LastEditors: Please set LastEditors
* @LastEditTime: 2021-08-01 09:38:54
* @Description: Description
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import { getEmployeeList, getUserList, getStoreDecorationList, getStoreRole, addEmployee, editEmployee, deleteEmployee, getCourseCatalogList,
getAllSonCategory, addCourseCategory, delCourseCategory, editCourseCategory, deleteStoreDecorationList, addStoreBanner, editStoreBanner,
moveBannerSequence,getStoreUserBasicPage,updateStoreMessage,getStoreDetail} from '@/data-source/store/request-apis';
moveBannerSequence,getStoreUserBasicPage,updateStoreMessage,getStoreDetail,getByDepartmentId,getDepartmentUser,getDepartmentUserNotPage,addDepartment,
editDepartment,delDepartment,queryDepartmentTree,getStoreCustomerAndDepNamePage,delDepartmentUser,syncWorkWeChatDepartment,getSyncCount
} from '@/data-source/store/request-apis';
export default class StoreService {
// 获取员工列表
......@@ -89,4 +91,37 @@ export default class StoreService {
static getStoreDetail(params: any) {
return getStoreDetail(params);
}
static getByDepartmentId(params:any){
return getByDepartmentId(params);
}
static getDepartmentUser(params:any){
return getDepartmentUser(params);
}
static getDepartmentUserNotPage(params:any){
return getDepartmentUserNotPage(params);
}
static addDepartment(params:any){
return addDepartment(params);
}
static editDepartment(params:any){
return editDepartment(params);
}
static delDepartment(params:any){
return delDepartment(params);
}
static queryDepartmentTree(params:any){
return queryDepartmentTree(params);
}
static getStoreCustomerAndDepNamePage(params:any){
return getStoreCustomerAndDepNamePage(params);
}
static delDepartmentUser(params:any){
return delDepartmentUser(params);
}
static syncWorkWeChatDepartment(params:any){
return syncWorkWeChatDepartment(params);
}
static getSyncCount(params:any){
return getSyncCount(params);
}
}
\ No newline at end of file
declare module 'jquery'
declare module 'cropper'
declare module 'ExamShareModal'
declare module 'routeHooks'
// declare var this: any
\ No newline at end of file
......@@ -2,34 +2,35 @@
* @Author: 吴文洁
* @Date: 2020-08-24 12:20:57
* @LastEditors: Please set LastEditors
* @LastEditTime: 2021-07-08 19:38:52
* @LastEditTime: 2021-08-11 20:25:11
* @Description:
* @Copyright: 杭州杰竞科技有限公司 版权所有
-->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link rel="icon" href="" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="小麦企学院,一站式企业培训数字化服务商,通过“工具+内容”,帮助企业快速从0到1搭建数字化培训体系,并让整个培训过程可视化,降低培训成本,提升培训效率。"
/>
<meta
name="keywords"
content="小麦企学院,企业培训,员工培训,企业大学,企业内训,企业外训,培训计划,培训素材,企培,企训,素材库,培训课程,培训任务,直播课,线上课,图文课,线下活动,知识库,作业,考试,排行榜,培训类别管理,定制培训计划,管理数据,学习数据,企学院,资料共享,培训数字化,数字化培训,培训工具,在线培训,线上培训,培训saas,培训管理,企业微信培训,对客培训,客户培训,直播培训,互联网培训,新员工培训,管理培训,管理者培训,工人培训,制造业培训,餐饮培训,服务业培训,零售培训,门店培训,工厂培训,车间培训,培训补贴,人事培训,财务培训,职场培训,企业学院平台,教育企业学院,教育企业平台,教育平台学院,企业学习,酷学院,小鹅通,企业学院,云学堂,时代光华,云课堂,魔学院,云大学,米知云,授课学堂"
/>
<!-- <link rel="apple-touch-icon" href="../src/common/images/logo.png" /> -->
<link rel="shortcut icon" href="https://image.xiaomaiketang.com/xm/c4KiP2epBP.png" />
<head>
<meta charset="utf-8" />
<link rel="icon" href="" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="小麦企学院,一站式企业培训数字化服务商,通过“工具+内容”,帮助企业快速从0到1搭建数字化培训体系,并让整个培训过程可视化,降低培训成本,提升培训效率。"
/>
<meta
name="keywords"
content="小麦企学院,企业培训,员工培训,企业大学,企业内训,企业外训,培训计划,培训素材,企培,企训,资料云盘,培训课程,培训任务,直播课,线上课,图文课,线下课,知识库,作业,考试,排行榜,培训类别管理,定制培训计划,管理数据,学习数据,企学院,资料共享,培训数字化,数字化培训,培训工具,在线培训,线上培训,培训saas,培训管理,企业微信培训,对客培训,客户培训,直播培训,互联网培训,新员工培训,管理培训,管理者培训,工人培训,制造业培训,餐饮培训,服务业培训,零售培训,门店培训,工厂培训,车间培训,培训补贴,人事培训,财务培训,职场培训,企业学院平台,教育企业学院,教育企业平台,教育平台学院,企业学习,酷学院,小鹅通,企业学院,云学堂,时代光华,云课堂,魔学院,云大学,米知云,授课学堂"
/>
<!-- <link rel="apple-touch-icon" href="../src/common/images/logo.png" /> -->
<!-- <link rel="shortcut icon" href="https://image.xiaomaiketang.com/xm/c4KiP2epBP.png" /> -->
<!-- <link rel="shortcut icon" href="https://image.xiaomaiketang.com/xm/WGWCtxiGzE.png"> -->
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<link rel="stylesheet" href="//at.alicdn.com/t/font_2223403_oe5p510553.css" />
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<link rel="stylesheet" href="//at.alicdn.com/t/font_2223403_7261tsts1dc.css" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
......@@ -40,19 +41,29 @@
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>小麦企学院</title>
<script type="text/javascript" src="https://image.xiaomaiketang.com/xm/iscroll-zoom-min.js"></script>
<script type="text/javascript" src="https://image.xiaomaiketang.com/xm/hammer.min.js"></script>
<script type="text/javascript" src="https://image.xiaomaiketang.com/xm/lrz.all.bundle.js"></script>
<script type="text/javascript" src="https://image.xiaomaiketang.com/xm/PhotoClip.js"></script>
<script type="text/javascript" charset="utf-8" src="//g.alicdn.com/sd/ncpc/nc.js?t=2015052012"></script>
<script type="text/javascript" src="https://xiaomai-js.oss-cn-hangzhou.aliyuncs.com/loghub-xm-0.0.1-beta.js"></script>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
<script src="https://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
<script src="https://open.work.weixin.qq.com/wwopen/js/jwxwork-1.0.0.js"></script>
<script type="text/javascript" src="https://image.xiaomaiketang.com/xm/iscroll-zoom-min.js"></script>
<script type="text/javascript" src="https://image.xiaomaiketang.com/xm/hammer.min.js"></script>
<script type="text/javascript" src="https://image.xiaomaiketang.com/xm/lrz.all.bundle.js"></script>
<script type="text/javascript" src="https://image.xiaomaiketang.com/xm/PhotoClip.js"></script>
<script type="text/javascript" charset="utf-8" src="//g.alicdn.com/sd/ncpc/nc.js?t=2015052012"></script>
<script type="text/javascript" src="https://xiaomai-js.oss-cn-hangzhou.aliyuncs.com/loghub-xm-0.0.1-beta.js"></script>
</head>
<body>
<script>
setTimeout(()=>{
if(!wx.agentConfig){
window.location.reload()
}
},100)
</script>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
......
......@@ -23,15 +23,33 @@ import '@/core/xmTD';
import User from '@/common/js/user';
import Service from "@/common/js/service";
import BaseService from '@/domains/basic-domain/baseService';
import {brandName,BRAND,brandIcon} from '@/domains/brand/constants'
import routeHook from '@/core/routeHook'
declare var getParameterByName: any;
declare var window: any;
window.currentStoreUserInfo = {}
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, {
push: (obj: any) => {
history.push(obj)
console.log(routeHook.getCallbackNum(), 'routeHook.getCallbackNum()')
if (routeHook.getCallbackNum()) {
routeHook.break();
routeHook.addJump(() => {
history.push(obj)
})
} else {
history.push(obj)
}
},
pushState: (obj: any) => {
history.push(obj)
......@@ -39,13 +57,21 @@ window.RCHistory = _.extend({}, history, {
pushStateWithStatus: (obj: any) => {
history.push(obj)
},
goBack: history.goBack,
goBack: () => {
console.log(routeHook.getCallbackNum(), 'routeHook.getCallbackNum()')
history.goBack()
},
location: history.location,
replace: (obj: any) => {
history.replace(obj)
}
});
window.onhashchange = () => {
routeHook.cancel()
}
function mount() {
ReactDOM.render(
<RootRouter />,
......@@ -73,19 +99,19 @@ if (getParameterByName('code') && isWeiXin()) {
window.currentStoreUserInfo.enterpriseId = res.result.enterpriseId;
mount()
})
} else if(getParameterByName('from') === 'customer' && getParameterByName('enterpriseId') && getParameterByName('userId')){
} else if (getParameterByName('from') === 'customer' && getParameterByName('enterpriseId') && getParameterByName('userId')) {
User.setCustomerStoreId(getParameterByName('storeId'));
getWXWorkLoginNoCheck(getParameterByName('enterpriseId'),getParameterByName('userId')); //从C端跳转过来的学院自动执行免登录
}else{
getWXWorkLoginNoCheck(getParameterByName('enterpriseId'), getParameterByName('userId')); //从C端跳转过来的学院自动执行免登录
} else {
mount()
}
function getWXWorkLoginNoCheck(enterpriseId:string,userId:string) {
function getWXWorkLoginNoCheck(enterpriseId: string, userId: string) {
const params = {
appTermEnum: 'XIAOMAI_CLOUD_CLASS_PC_WEB_ADMIN',
enterpriseId,
userId,
};
BaseService.getWXWorkLoginNoCheck(params).then((res:any) => {
BaseService.getWXWorkLoginNoCheck(params).then((res: any) => {
User.setUserId(res.result.loginInfo.userId)
User.setToken(res.result.loginInfo.xmToken)
User.setEnterpriseId(res.result.enterpriseId)
......
......@@ -5,4 +5,25 @@
.add-show-btn{
margin-top:12px;
}
.update-user-btn{
margin-left:8px;
margin-right:8px;
}
.origin-text{
font-size:14px;
color:#999;
}
.view-text{
font-size:14px;
color:#5289FA;
}
.post-name{
max-width: 200px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.edit-disable{
color:#CCC !important;
}
}
\ No newline at end of file
......@@ -9,16 +9,17 @@ import React, { useEffect, useState } from "react";
import { withRouter } from "react-router-dom";
import _ from "underscore";
import { CheckBox, PageControl } from "@/components";
import { Button, Table, Modal, message, Input } from "antd";
import { Button, Table, Modal, message, Input,Tooltip} from "antd";
import { XMTable } from '@/components';
import college from '@/common/lottie/college.json';
import StoreService from "@/domains/store-domain/storeService";
import EmployeeAddOrEditModal from "../store-manage/EmployeeAddOrEditModal";
import User from "@/common/js/user";
import LimitTip from "./LimitTip";
import WWOpenDataCom from '@/components/WWOpenDataCom';
import "./EmployeeManage.less";
import ChooseMembersModal from "./modal/ChooseMembersModal";
import NewChooseMembersModal from "./modal/NewChooseMembersModal";
const { confirm } = Modal;
const { Search } = Input;
......@@ -32,6 +33,7 @@ interface RecordTypes {
phone: string;
avatar?: string;
weChatAccount?: string;
depNameList:any
}
interface RoleItemType {
......@@ -56,6 +58,7 @@ interface ChoosedItemType {
avatar?: string;
storeUserId?: string;
weChatAccount?: string;
depNameList?:any;
}
function EmployeeManage() {
......@@ -138,7 +141,8 @@ function EmployeeManage() {
const columns = [
{
title: "员工",
dataIndex: "nickName",
dataIndex: "weChatAccount",
fixed:'left',
render: (val: string, record: RecordTypes) => {
return (
<div className="employee-info">
......@@ -152,7 +156,10 @@ function EmployeeManage() {
/>
)}
<span className="title">{val}</span>
{/* <span className="title">{val}</span> */}
<span className="title">
<WWOpenDataCom type="userName" openid={val}/>
</span>
</div>
);
},
......@@ -166,7 +173,25 @@ function EmployeeManage() {
},
},
{
title: "角色",
title: "部门",
dataIndex: "depNameList",
key: "depNameList",
render: (val:string,record:RecordTypes) => {
if(!record.depNameList){
return <span>-</span>
}
if(record.depNameList.length === 0){
return <span>-</span>
}
return <Tooltip title={<div>{handleDepName(record.depNameList)}</div>} placement='top' arrowPointAtCenter><div className="post-name"> {record.depNameList.map((item:any, index:any) => {
return <span><WWOpenDataCom type="departmentName" openid={item}/>{index<(record.depNameList.length -1)?';':''}</span>
})}
</div>
</Tooltip>
},
},
{
title: "身份",
dataIndex: "role",
key: "role",
render: (val: string) => {
......@@ -176,15 +201,29 @@ function EmployeeManage() {
{
title: "操作",
dataIndex: "operation",
fixed:'right',
render: (val: string, record: RecordTypes) => {
return record.role === "学院管理员" ||
record.userId === User.getUserId() ? (
<div className="no-operate">-</div>
) : (
<div className="operation">
<span className="edit" onClick={() => handleEditEmployee(record)}>
编辑
</span>
{!record.depNameList &&
<span className="edit edit-disable">
编辑
</span>
}
{record.depNameList &&
(record.depNameList.length > 0 ?
<span className="edit" onClick={() => handleEditEmployee(record)}>
编辑
</span>
:
<span className="edit edit-disable">
编辑
</span>
)
}
<span className="divider-line">{" | "}</span>
<span
className="delete"
......@@ -214,15 +253,23 @@ function EmployeeManage() {
return columns;
}
function handleDepName(depArray:any):any{
const depArrayDom = depArray.map((item:any, index:any) => {
return <span><WWOpenDataCom type="departmentName" openid={item}/></span>
});
return depArrayDom;
};
function handleEditEmployee(record: RecordTypes) {
const { nickName, phone, roleCodes, avatar, id, weChatAccount } = record;
const { nickName, phone, roleCodes, avatar, id, weChatAccount,depNameList} = record;
const _choosesItem = {
nickName: nickName,
phone: phone,
role: roleCodes,
avatar: avatar,
storeUserId: id,
weChatAccount
weChatAccount,
depNameList:depNameList
};
setChooseItem(_choosesItem);
const model: React.ReactNode = (
......@@ -237,7 +284,8 @@ function EmployeeManage() {
role: [],
avatar: "",
storeUserId: "",
weChatAccount:""
weChatAccount:"",
depNameList:[]
});
}}
isWorkWechat={isWorkWechat}
......@@ -273,7 +321,56 @@ function EmployeeManage() {
getEmployeeList();
});
}
function updateListData(){
let num:any;
const params = {
enterpriseId:User.getEnterpriseId(),
storeId:User.getStoreId(),
userType:'USER'
}
StoreService.getSyncCount(params).then((res) => {
num = res.result;
if(num<3){
return confirm({
title: "确定更新列表数据吗?",
content: <span>员工数据来源企微通讯录,一天只能更新3次,今日还能更新<span style={{color:'#2966FF'}}>{3-num}</span>次。</span>,
icon: (
<span className="icon iconfont default-confirm-icon">&#xe839; </span>
),
okText: "确定",
cancelText: "取消",
onOk: () => {
confirmUpdateListData()
},
});
}else{
Modal.warning({
title: '提示',
okText: '我知道了',
content: <span>员工数据今日更新次数已达上限<span style={{color:'#2966FF'}}>(3次)</span>,无法继续更新。</span>,
icon: (
<span className='icon iconfont default-confirm-icon' style={{ color: '#FFBB54 !important' }}>
&#xe834;
</span>
),
});
}
});
}
function confirmUpdateListData(){
const params = {
enterpriseId:User.getEnterpriseId(),
storeId:User.getStoreId(),
userType:'USER'
}
StoreService.syncWorkWeChatDepartment(params).then((res) => {
getEmployeeList();
message.success('已更新');
});
}
return (
<div className="page employee-manage-page">
<div className="content-header">角色管理</div>
......@@ -364,15 +461,25 @@ function EmployeeManage() {
</div>
</div>
{(User.getUserRole() === 'CloudManager' || User.getUserRole() === 'StoreManager') &&
<Button
onClick={() => {
handleToAddEmployee();
}}
type="primary"
className="add-show-btn"
>
添加员工
</Button>
<>
<Button
onClick={() => {
handleToAddEmployee();
}}
type="primary"
className="add-show-btn"
>
添加员工
</Button>
<Button className="update-user-btn" onClick={()=>{updateListData()}}>更新列表数据</Button>
<span className="origin-text">系统实时同步企业微信可见范围的员工信息,如需修改请前往企微管理后台通讯录中操作</span>
<a
href="https://www.yuque.com/docs/share/8c66333f-ed62-469d-909e-b36389a115ea?#"
target="_blank"
>
<span className="view-text">查看说明</span>
</a>
</>
}
</div>
<LimitTip type="员工" total={realTotal} tip={()=>{return (<div>数据为当前学院的员工数,若员工存在多个学院,企业人数只统计为1人</div>)}}/>
......@@ -382,6 +489,7 @@ function EmployeeManage() {
image: college,
description: '暂无数据'
}}
scroll={{ x: 1200 }}
size={"middle"}
pagination={false}
dataSource={employeeList}
......@@ -404,17 +512,17 @@ function EmployeeManage() {
</div>
</div>
{model}
{employeeModal &&
<ChooseMembersModal
isOpen={employeeModal}
{ employeeModal &&
<NewChooseMembersModal
treeDepType="DEP_CHAT"
visible={employeeModal}
type="USER"
handleChooseModal={(bool: any) => {
close={()=>{setEmployeeModal(false)}}
onConfirm={() => {
setEmployeeModal(false)
if (bool) {
message.success('添加成功')
getEmployeeList();
}
}}
message.success('添加成功')
getEmployeeList();
}}
/>
}
</div>
......
/*
* @Author: your name
* @Date: 2021-08-04 15:21:36
* @LastEditTime: 2021-08-11 20:25:26
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: /xiaomai-cloud-class-web/src/modules/college-manage/LimitTip.tsx
*/
import React, { useContext, useEffect, useState } from "react";
import { Tooltip } from "antd"
import { VersionContext } from "@/store/context";
......@@ -26,7 +34,7 @@ export default function LimitTip(props:{total:number,type:string,tip:() => React
{
isOver ? (
<>
<div style={{marginLeft:"14px",display:"inline-block"}}>当前企业使用人数已达到上限 (<span style={{color:"#333333",fontWeight:"bold"}}>{limitUser}</span>人),将无法添加新员工、新学员,如需增加人数限制,请联系小麦企学院服务平台。</div>
<div style={{marginLeft:"14px",display:"inline-block"}}>当前企业使用人数已达到上限 <span style={{color:"#333333",fontWeight:"bold"}}>{limitUser}</span>人,将无法添加新员工、新学员,如需增加人数限制,请联系{window.brandName}服务平台。</div>
<ContactWidget trigger="hover" placement="bottom">
<div className="renew-text">立即续费<span className="icon iconfont" style={{fontSize:"10px"}}>&#59291;</span></div>
</ContactWidget>
......
/*
* @Author: wufan
* @Date: 2020-11-30 10:47:38
* @LastEditors: Please set LastEditors
* @LastEditTime: 2021-08-11 20:31:26
* @Description: 学员管理页面
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import React, { useEffect, useState } from "react";
import { withRouter } from "react-router-dom";
import _ from "underscore";
import {Tabs,Input,Tree,Button} from "antd";
import DepartMentTabCon from './components/DepartMentTabCon';
import "./NewUsersManagePage.less";
const { TabPane } = Tabs;
function UserManagePage() {
const [currentTab, setCurrentTab] = useState("departMentTab");
const [courseList,setCourseList] = useState([]);
const [total, setTotal] = useState(0);
const [query, setQuery] = useState({
current: 0,
size: 10,
});
return (
<div className="page new-user-manage-page">
<div className="content-header">学员管理</div>
<div className="box">
<div className="tab-box">
<Tabs
onChange={(key) => {
setCurrentTab(key);
}}
activeKey={currentTab}
>
<TabPane key="departMentTab" tab="部门"></TabPane>
<TabPane key="postGrouptab" tab="岗位组"></TabPane>
<TabPane key="customGroupTab" tab="自定义分组"></TabPane>
</Tabs>
</div>
<div className="box-body tab-con">
<DepartMentTabCon currentTab={currentTab}/>
</div>
</div>
</div>
);
}
export default withRouter(UserManagePage);
.new-user-manage-page{
.ant-tabs-tab + .ant-tabs-tab{
margin:0;
}
}
\ No newline at end of file
/*
* @Author: wufan
* @Date: 2020-11-30 10:47:38
* @LastEditors: wufan
* @LastEditTime: 2021-06-21 11:13:15
* @LastEditors: Please set LastEditors
* @LastEditTime: 2021-08-13 16:52:16
* @Description: 学员管理页面
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
......
.department-tab-con{
display: flex;
.table-con{
flex:1;
max-width: calc(100% - 290px);
.post-name{
max-width: 200px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.student-name{
max-width: 120px;
white-space:nowrap;
overflow:hidden;
text-overflow:ellipsis;
vertical-align: middle;
display: inline-block;
}
.operate-area{
margin-bottom:16px;
.add-user-btn{
margin-right:8px;
}
.del-user-btn{
margin-right:8px;
}
.update-user-btn{
margin-right:8px;
}
.origin-text{
font-size:14px;
color:#999;
}
.view-text{
font-size:14px;
color:#5289FA;
}
}
.operate{
.operate__item{
color:#2966FF;
cursor: pointer;
}
}
}
}
\ No newline at end of file
.left-structure-tree {
margin-right: 17px;
width:260px;
flex-shrink: 0;
height: calc(~'100vh - 260px');
overflow: scroll;
border-right:1px solid #eee;
.organization{
.search-con{
margin-bottom: 10px;
}
.operate {
margin-bottom:16px;
.add-btn {
width: 230px;
height:32px;
}
}
&::-webkit-scrollbar {
display: none;
}
.node-title-div {
display: flex;
justify-content: space-between;
white-space: nowrap;
.item-icon {
img {
width: 16px;
height: 16px;
}
}
.item-title {
position: absolute;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
width: 55%;
left: 28px;
}
.item-more {
visibility: hidden;
position: absolute;
right: 8px;
text-align: right;
}
.item-count {
visibility: visible;
position: absolute;
right: 12px;
text-align: right;
}
}
// 修改树样式
.ant-tree .ant-tree-treenode {
padding: 10px 0 14px 0;
}
.ant-tree.ant-tree-directory {
.ant-tree-node-selected{
color:#2966FF !important;
}
.ant-tree-treenode-selected:hover::before,
.ant-tree-treenode-selected::before {
background: #f3f6fa;
}
.ant-tree-treenode-selected .ant-tree-switcher {
color: #666666;
}
.ant-tree-treenode .ant-tree-node-content-wrapper {
color: #666666;
}
}
}
}
.certain-category-search-dropdown{
.catalog-title{
font-size:14px;
color:#666;
margin-bottom:14px;
}
.search-result-item{
padding:14px 0;
color:#333;
.title-icon{
color:#999;
margin-right:3px;
}
.search-result-item__left{
font-size:14px;
}
.search-result-item__right{
font-size:14px;
width:84px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
color:#999;
text-align:right;
}
}
.ant-select-item-option-grouped{
padding-left:12px;
}
.empty-con{
text-align:center;
.empty-img{
width:150px;
height:150px;
}
.empty-text{
color:#666;
}
}
}
\ No newline at end of file
import React, { useEffect, useState } from "react";
import { withRouter } from "react-router-dom";
import { Tree,Tooltip} from "antd";
import StoreService from "@/domains/store-domain/storeService";
import User from '@/common/js/user';
import WWOpenDataCom from '@/components/WWOpenDataCom';
import "./MemberTree.less";
import _ from 'underscore';
const { DirectoryTree } = Tree;
function MemberTree(props) {
const [treeData,setTreeData]=useState([]);
useEffect(()=>{
getTreeData();
},[]);
function getTreeData(){
const params = {
depType:props.treeDepType,
enterpriseId:User.getEnterpriseId(),
source:0,//0代表来自企培
storeId:User.getStoreId(),
userId:User.getUserId(),
whetherCount:false,
distinct:true,
queryType:props.type
}
if(props.departmentId){
params.departmentId = props.departmentId;
}
if(props.nowTreeDepType){
params.nowDepType = props.nowTreeDepType;
}
StoreService.getDepartmentUserNotPage(params).then((res) => {
let { departmentVOList=[]} = res.result;
let _treeData = handleData(departmentVOList);
console.log("_treeData",_treeData);
setTreeData(_treeData);
});
}
function handleData(dataArray){
const _dataArray = dataArray.map((item,index)=>{
item.title = "";
item.key=item.id;
item.children = [];
if(item.departmentUserVOList){
item.children = item.departmentUserVOList;
}
if(item.sonDepartmentVOList){
item.children = [...item.children,...item.sonDepartmentVOList];
}
if(item.children.length > 0){
handleData(item.children)
}else{
delete item.children
}
return item
})
return _dataArray;
}
function treeSelected (selectedKeys,e){
const _checkedNodes = e.checkedNodes;
const _selectNodes = [];
_checkedNodes.map((item,index)=>{
// if(item.userId){
_selectNodes.push(item);
// }
})
props.onSelect(_selectNodes);
}
return (
<div className="member-tree">
<div className="tree-con">
<DirectoryTree
defaultExpandAll
checkable
showIcon={false}
treeData={treeData}
checkedKeys={_.pluck(props.selectList, 'id')}
onCheck={(selectedKeys,e)=>treeSelected(selectedKeys,e)}
titleRender={(nodeData) => {
return (
<div
className="node-title-con"
>
{nodeData.userId ?
<>
<span className="icon iconfont title-icon">&#xe603;</span>
<Tooltip title={<WWOpenDataCom type="userName" openid={nodeData.userName}/>}>
<span className="name"><WWOpenDataCom type="userName" openid={nodeData.userName}/></span>
</Tooltip>
</>
:
<>
<span className="icon iconfont title-icon">&#xe604;</span>
<Tooltip title={<WWOpenDataCom type="departmentName" openid={nodeData.name}/>}>
<span className="name"><WWOpenDataCom type="departmentName" openid={nodeData.name}/></span>
</Tooltip>
<span>({nodeData.departmentCount || 0})</span>
</>
}
</div>
);
}}
/>
</div>
</div>
);
}
export default withRouter(MemberTree);
.member-tree{
.node-title-con{
color:#666;
font-size:14px;
display: flex;
.name{
display: inline-block;
vertical-align: middle;
max-width:190px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.title-icon{
font-size:14px;
color:#999;
margin-right:8px;
}
}
.ant-tree .ant-tree-treenode {
padding: 8px 0 14px 0;
}
.ant-tree.ant-tree-directory .ant-tree-treenode-selected:hover::before, .ant-tree.ant-tree-directory .ant-tree-treenode-selected::before{
background:transparent;
}
.ant-tree.ant-tree-directory .ant-tree-treenode-selected .ant-tree-switcher{
color:#000;
}
}
\ No newline at end of file
import React, { useEffect, useState } from "react";
import { withRouter } from "react-router-dom";
import { Input,Checkbox,Tooltip} from "antd";
import StoreService from "@/domains/store-domain/storeService";
import User from '@/common/js/user';
import WWOpenDataCom from '@/components/WWOpenDataCom';
import $ from 'jquery';
import _ from 'underscore';
import './SearchUser.less'
const { Search } = Input;
function SearchUser(props) {
const [dropDownVisible,setDropDownVisible]=useState(false);
useEffect(()=>{
documentClick();
},[])
function onFocus(e){
setDropDownVisible(true);
}
function onChange(e){
setDropDownVisible(true);
props.onChange(e.target.value)
}
function selectuser(e,item){
if(e.target.checked){
let _record = props.selectList
_record.push(item)
props.onSelect(_record,'user')
}else{
let _record = props.selectList
_record.map((_item,index)=>{
if(_item.userId === item.userId){
_record.splice(index,1)
}
})
props.onSelect(_record,'user')
}
}
function selectDep(e,item){
console.log('item',item);
if(e.target.checked){
let _record = props.selectList;
let _userList = [];
_record.push(item); // 将当前选中的部门塞进来
if(item.departmentUserVOList){
_userList = item.departmentUserVOList; //获取当前选中的人
}
_record = [..._record,..._userList];
props.onSelect(_record,'department');
}else{
let _record = [];
let _userList = [];
props.selectList.map((_item,index)=>{
if(_item.id !== item.id){ //取消选择后将当前的部门移除也要将父部门也移除
_record.push(_item);
}
})
if(item.departmentUserVOList){
_userList = item.departmentUserVOList; //获取当前选中的人
}
const new_arr = _record.filter((x) => {return !_userList.some((item) => x.id === item.id)});
// _userList.map((_item,index)=>{
// if(_item.id === item.id){
// _record.splice(_item,index);
// }
// })
props.onSelect(new_arr,'department');
}
}
function documentClick(){
document.onclick = function (e) {
let _con =$('#search-user');
if(!_con.is(e.target) && _con.has(e.target).length === 0){
setDropDownVisible(false);
}
};
}
function handleDepName(depArray){
const depArrayDom = depArray.map((item, index) => {
return <span><WWOpenDataCom type="departmentName" openid={item}/></span>
});
return depArrayDom;
};
return (
<div className="search-user" style={{width:'300px'}} id="search-user">
<Search
placeholder='搜索成员'
enterButton={<span className="icon iconfont">&#xe832;</span>}
onFocus={(e)=>{onFocus(e)}}
onChange={(e)=>{onChange(e)}}
className="search-input-item"
/>
{dropDownVisible &&
<div className="drop-down">
<div className="drop-down__list">
{props.data.departmentUserVOList &&
( props.data.departmentUserVOList.length>0 && <div className="drop-down__item-user">
<div className="drop-down__item__title">
员工
</div>
<div className="drop-down__item__con">
<div>
{props.data.departmentUserVOList.map((item,index)=>{
return <div>
<Checkbox onChange={(e)=>{selectuser(e,item)}} checked={_.pluck(props.selectList, 'userId').indexOf(item.userId)=== -1?false:true}>
<div className="drop-down__item__con__item">
<div className="drop-down__item__con__item__left">
<span className="icon iconfont title-icon">&#xe603;</span>
<WWOpenDataCom type="userName" openid={item.userName}/>
</div>
<div className="drop-down__item__con__item__right">
<Tooltip title={<div>{handleDepName(item.depNamesList)}</div>} placement='top' arrowPointAtCenter>
{item.depNamesList.map((_item,index)=>{
return <span> <WWOpenDataCom type="departmentName" openid={_item}/>{index<(item.depNamesList.length -1)?';':''}</span>
})
}
</Tooltip>
</div>
</div>
</Checkbox>
</div>
})
}
</div>
</div>
</div>)
}
{props.data.departmentVOList &&
(props.data.departmentVOList.length>0 && <div>
<div className="drop-down__item__title drop-down__item__title-dep">
部门
</div>
<div className="drop-down__item__con">
<div>
{props.data.departmentVOList.map((item,index)=>{
return <div><Checkbox onChange={(e)=>{selectDep(e,item)}} checked={_.pluck(props.selectList, 'id').indexOf(item.id)=== -1?false:true}>
<div className="drop-down__item__con__item">
<div className="drop-down__item__con__item__left">
<Tooltip title={ <WWOpenDataCom type="departmentName" openid={item.name}/>}>
<span className="departmentName">
<WWOpenDataCom type="departmentName" openid={item.name}/>
</span>
</Tooltip>
</div>
</div>
</Checkbox>
</div>
})
}
</div>
</div>
</div>)
}
{(!props.data.departmentUserVOList && !props.data.departmentVOList)&&
<div className="empty-con">
<img src="https://image.xiaomaiketang.com/xm/wRDrb2pJFb.png" className="empty-img"/>
<div className="empty-text">暂无数据</div>
</div>
}
{ (props.data.departmentUserVOList && props.data.departmentVOList) &&(
(props.data.departmentUserVOList.length === 0 && props.data.departmentVOList.length ===0) &&
<div className="empty-con">
<img src="https://image.xiaomaiketang.com/xm/wRDrb2pJFb.png" className="empty-img"/>
<div className="empty-text">暂无数据</div>
</div>
)
}
</div>
</div>
}
</div>
);
}
export default withRouter(SearchUser);
.search-user{
position: relative;
padding:12px 16px;
.drop-down{
padding:18px;
position: absolute;
background: #FFF;
z-index:100001;
background: #FFFFFF;
box-shadow: 0px 2px 15px 6px rgba(0, 0, 0, 0.05);
border-radius:2px;
width:270px;
max-height:280px;
overflow-y: scroll;
// .drop-down__item-user{
// margin-bottom:30px;
// }
.drop-down__item__title{
font-size:14px;
color:#666;
margin-bottom:14px;
}
.ant-checkbox-wrapper{
width:100%;
.drop-down__item__con__item{
margin-bottom:24px;
display:flex;
width:220px;
justify-content:space-between;
color:#333;
font-size:14px;
.drop-down__item__con__item__left{
.title-icon{
color:#999;
margin-right:3px;
}
.departmentName{
display: inline-block;
vertical-align: middle;
max-width:190px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
}
.drop-down__item__con__item__right{
width:84px;
text-align:right;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
color:#999;
}
}
}
.empty-con{
text-align:center;
.empty-img{
width:150px;
height:150px;
}
.empty-text{
color:#666;
}
}
}
}
\ No newline at end of file
import React, { useEffect, useState } from "react";
import { withRouter } from "react-router-dom";
import { XMTable,PageControl} from '@/components';
import college from '@/common/lottie/college.json';
import "./UserTable.less";
function UserTable() {
const [courseList,setCourseList] = useState([]);
const [total, setTotal] = useState(0);
const [query, setQuery] = useState({
current: 0,
size: 10,
});
const columns = [
{
title: '学员',
dataIndex: 'user',
width:220,
render: (val, record) => {
return <span>{val}</span>
}
},
{
title: '真实姓名',
dataIndex: 'nickname',
width:'15%',
render: (val,record) => {
return <span>{val}</span>
}
},
{
title: '账号',
dataIndex: 'account',
width:'15%',
render: (val,record) => {
return <span>{val}</span>
}
},
{
title: '岗位',
dataIndex: 'post',
render: (val, record) => {
return <span className="post-name">{val}</span>
}
},
{
title: '手机号',
dataIndex: 'phone',
render: (val, record) => {
return <span>{val}</span>;
}
},
{
title: '注册时间',
dataIndex: 'registerTime',
render: (val, record) => {
return <span>{val}</span>;
}
},
{
title: "操作",
key: "operate",
dataIndex: "operate",
render: (val, record) => {
return (
<div className="operate">
<div
className="operate__item"
>
删除
</div>
</div>
)
}
},
];
return (
<div className="user-table">
<XMTable
renderEmpty={{
image: college,
description: '暂无数据',
}}
bordered
size='middle'
pagination={false}
columns={columns}
scroll={{ x: 1300 }}
dataSource={courseList}
/>
<div className='box-footer'>
<PageControl
current={query.current}
pageSize={query.size}
total={total}
toPage={(page) => {
const queryStates = _.clone(query);
queryStates.current = page;
setQuery(queryStates);
}}
/>
</div>
</div>
);
}
export default withRouter(UserTable);
\ No newline at end of file
.user-table{
.post-name{
max-width: 100px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
\ No newline at end of file
/*
* @Author: wufan
* @Date: 2020-11-27 16:21:49
* @LastEditors: Please set LastEditors
* @LastEditTime: 2021-08-06 17:10:50
* @Description: Description
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import React, { useState, useEffect } from "react";
import { Modal,Form,Input,Button,message} from "antd";
import User from '@/common/js/user';
import StoreService from "@/domains/store-domain/storeService";
import { DepType } from '@/domains/store-domain/constants';
import './AddOrEditPostGroupModal.less'
function AddOrEditPostGroupModal(props) {
const [nameErrorMsg,setNameErrorMsg] = useState('');
const [validateStatus,setValidateStatus] = useState('success');
const [postGroupName,setPostGroupName] = useState('');
const [isError,setIsError] = useState(false)
useEffect(() => {
},[]);
function changePostGroupName(e){
setIsError(false)
setValidateStatus('success');
setNameErrorMsg('');
if((!e.target.value) || /^\s+$/.test(e.target.value)){
setValidateStatus('error');
setNameErrorMsg(`${props.label}不能为空`);
setIsError(true)
}
props.postGroupTreeData.map((item,index)=>{
if(item.name === e.target.value){
setValidateStatus('error');
setNameErrorMsg(`该${props.label}已存在`);
setIsError(true)
}
return item;
})
setPostGroupName(e.target.value);
}
function handleConfirm(){
if(props.modalOperateType === 'add'){
addGroup();
}else{
editGroup();
}
}
function addGroup(){
if(isError){
return;
}
const { postGroupModalLevel,currentTab,currentGroupData,label} = props
let parmas={
depLevel:postGroupModalLevel,
depType:DepType[currentTab],
departmentName:postGroupName,
enterpriseId:User.getEnterpriseId(),
source:0,
storeId:User.getStoreId(),
userId:User.getUserId()
}
if(postGroupModalLevel===0){
parmas.parentId = 0;
}else{
parmas.parentId = currentGroupData.id
}
StoreService.addDepartment(parmas).then((res) => {
message.success(`${label}创建成功`)
props.onConfirm();
});
}
function editGroup(){
if(isError){
return;
}
const {postGroupModalLevel,currentTab,currentGroupData,label} = props
let parmas={
departmentLevel:postGroupModalLevel,
departmentId:currentGroupData.id,
depType:DepType[currentTab],
departmentName:postGroupName,
enterpriseId:User.getEnterpriseId(),
source:0,
storeId:User.getStoreId(),
userId:User.getUserId()
}
if(postGroupModalLevel===0){
parmas.parentId = 0;
}else{
parmas.parentId = currentGroupData.parentId
}
StoreService.editDepartment(parmas).then((res) => {
message.success(`${label}修改成功`)
props.onConfirm();
});
}
return (
<Modal
visible={true}
title={props.title}
className="add-edit-post-group-modal"
onCancel={props.onClose}
width={448}
footer={[
<Button
id='cancel_allot_btn'
key="back" onClick={props.onClose}>取消</Button>,
<Button
id='confirm_allot_btn'
key="submit"
type="primary"
onClick={() => {
handleConfirm()
}}>
保存
</Button>
]}
maskClosable={false}
closeIcon={<span className="icon iconfont modal-close-icon">&#xe6ef;</span>}
>
<Form
labelCol={ {span:5 }}
>
<Form.Item
// label={`${props.label}名称`}
name={`${props.label}名称`}
rules={[{ required: true}]}
validateStatus={validateStatus}
help={nameErrorMsg}
>
<Input type="text" placeholder={`请输入${props.label}名称(8个字以内)`} maxLength={8} style={{ width: 348 }}
defaultValue={props.modalOperateType==='edit'?props.currentGroupData.name:''}
onChange={(e) => {
changePostGroupName(e);
}} />
</Form.Item>
</Form>
</Modal>
);
}
export default AddOrEditPostGroupModal;
......@@ -16,7 +16,6 @@ import './ChooseMembersModal.less';
import _ from 'underscore';
const { Search } = Input;
class ChooseMembersModal extends React.Component {
constructor(props) {
super(props);
......@@ -162,6 +161,7 @@ class ChooseMembersModal extends React.Component {
})
}
})
}
addCustomer = () => {
......@@ -285,10 +285,11 @@ class ChooseMembersModal extends React.Component {
visible={isOpen}
onCancel={() => this.handleClose()}
onOk={() => {
if (User.getVersion() && User.getVersion().whetherReachUserNum) {
message.error("添加失败,企业使用人数超出限制")
return
}
//xmqxy446去除此优化
// if (User.getVersion() && User.getVersion().whetherReachUserNum) {
// message.error("添加失败,企业使用人数超出限制")
// return
// }
if (_.isEmpty(selectUserList)) {
message.warning(type === 'USER' ? '请选择员工' : '请选择学员')
return null;
......
......@@ -23,7 +23,7 @@
.container-left-body-table{
width: 300px;
height: 330px;
overflow: scroll;
.ant-table {
border: none;
min-height: 250px !important;
......
.choose-member-modal {
.member-container{
display: flex;
height: 417px;
.container-left{
width: 50%;
padding-right: 10px;
margin-left: 10px;
.container-left-header{
margin-bottom: 12px;
}
.container-left-body{
border: 1px solid #E9E9E9;
height: 100%;
.ant-table-thead > tr > th {
font-weight:400!important;
}
.search{
width: 305px;
padding: 7px 7px;
}
.container-left-body-table{
width: 300px;
max-height: 360px;
overflow: scroll;
.ant-table {
border: none;
min-height: 250px !important;
.ant-table-header{
margin-bottom: -7px !important;
>table > .ant-table-thead > tr > th {
background-color: #fff !important;
}
}
.ant-table-tbody{
>tr {
>td {
border-bottom: none;
background-color: #fff !important;
padding: 11px 0!important;
}
&:hover {
>td {
background: #F3F6FA !important;
}
}
}
}
}
.ant-empty-normal {
margin: 80px 0 !important;
}
.avatar{
display: flex;
align-items: center;
.avatar-icon {
font-size:14px;
color:#999;
margin-right: 6px;
}
.userName {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-size:14px;
color:#333;
}
}
}
}
}
.container-right{
width: 50%;
border: 1px solid #E9E9E9;
.span-left{
line-height: 45px;
margin-left: 10px;
.span-left-l{
color: #2966FF;
cursor: pointer;
}
}
.span-right{
line-height: 45px;
float: right;
margin-right: 10px;
color: #999;
.span-right-l{
color: #2966FF;
cursor: pointer;
}
}
.container-right-body{
min-height:376px;
border-top: 1px solid #e8e8e8;
.edit {
.edit-icon {
color:#999;
font-size:14px;
}
}
.edit-img{
width: 16px;
height: 16px;
}
.ant-table .ant-table-body {
overflow: auto;
max-height: 376px!important;
}
.ant-table tbody {
tr{
background: #fff;
&:first-child {
display: block;
overflow: hidden;
}
td{
padding:12px 18px !important;
}
}
}
.ant-empty-normal {
margin: 120px 0 !important;
}
.ant-empty {
margin-top: 76px;
}
.avatar{
display: flex;
align-items: center;
.avatar-icon {
font-size:14px;
color:#999;
margin-right: 6px;
}
.userName {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-size:14px;
color:#333;
}
}
.ant-table-tbody{
>tr >td {
border-bottom:none;
}
>tr .ant-table-selection-column{
width: 30px !important;
}
}
}
}
}
}
\ No newline at end of file
import React from 'react';
import { Modal, Button, Radio, Tooltip } from 'antd';
import WWOpenDataCom from '@/components/WWOpenDataCom';
import './SetEmployeeModal.less'
const RadioGroup = Radio.Group;
......@@ -13,26 +14,41 @@ export default class SetEmployeeModal extends React.Component {
constructor(props) {
super(props);
const list = props.list.map(item => {
item.roleCode = (props.selectObject || {})[item.enterpriseVisibleUserId] || (item.enterpriseRole === 'ADMIN' ? 'Cloud_Manager' : 'Cloud_Lecturer');
item.roleCode = (props.selectObject || {})[item.userId] || (item.enterpriseRole === 'ADMIN' ? 'Cloud_Manager' : 'Cloud_Lecturer');
return item;
})
const selectedData = list[0] || {};
this.state = {
list,
selected: selectedData.enterpriseVisibleUserId,
list:this.uniqArr([...list]),
selected: selectedData.userId,
roleCode: selectedData.roleCode,
submit:false
}
}
uniqArr(arr){
let obj={};
arr.map((item,index)=>{
// 若重复则删除该项
if(obj.hasOwnProperty(item.userId)){
arr.splice(index,1);
// 不重复则存入obj
}else{
obj[item.userId]=item.userName;
}
});
return arr;
}
handleChangeValues(value) {
const { list, selected } = this.state;
list.map((item) => {
if (item.enterpriseVisibleUserId === selected) {
if (item.userId === selected) {
item.roleCode = value;
}
})
this.props.onChange(selected, value);
this.setState({ roleCode: value, list });
this.setState({ roleCode: value, list});
}
render() {
......@@ -40,6 +56,7 @@ export default class SetEmployeeModal extends React.Component {
list,
roleCode,
selected,
submit
} = this.state;
return (
<Modal
......@@ -54,7 +71,7 @@ export default class SetEmployeeModal extends React.Component {
<div className="modal-footer">
<Button style={{ float: 'left' }} onClick={() => this.props.onClose()}>上一步</Button>
<Button onClick={() => this.props.onCancel()}>取消</Button>
<Button onClick={() => this.props.onOk(list)} type="primary">确定</Button>
<Button onClick={() =>{this.setState({submit:true},()=>this.props.onOk(list))}} type="primary" disabled={submit}>确定</Button>
</div>
}
>
......@@ -62,15 +79,18 @@ export default class SetEmployeeModal extends React.Component {
<div className="employee-box">
{list.map((item) => (
<div
className={`item ${selected === item.enterpriseVisibleUserId ? ' selected' : ''}`}
key={item.enterpriseVisibleUserId}
className={`item ${selected === item.userId ? ' selected' : ''}`}
key={item.userId}
onClick={() => {
this.setState({ selected: item.enterpriseVisibleUserId, roleCode: item.roleCode })
this.setState({ selected: item.userId, roleCode: item.roleCode })
}}
>
<span className="icon iconfont avatar-icon">&#xe84a;</span>
<Tooltip title={item.name}>
<span className='name'>{item.name}</span>
<span className='name'>
{/* {item.userName} */}
<WWOpenDataCom type="userName" openid={item.userName}/>
</span>
</Tooltip>
<span className="tag">{tagMap[item.roleCode]}</span>
</div>
......
......@@ -47,7 +47,7 @@
flex-shrink: 0;
}
&.selected {
background: rgba(255, 183, 20, 0.1);
background:rgba(41, 102, 255,0.1);
&::after {
content: '';
position: absolute;
......
......@@ -42,6 +42,7 @@ function CourseCatalogSelect(props) {
return (
<TreeSelect
className={props.className}
treeNodeLabelProp='categoryName'
showSearch={showSearch}
treeNodeFilterProp={treeNodeFilterProp}
......
......@@ -21,6 +21,7 @@ import { randomString } from '@/domains/basic-domain/utils';
import Upload from '@/core/upload';
import PreviewCourseModal from './modal/PreviewCourseModal';
import CourseService from '@/domains/course-domain/CourseService';
import routeHook from '@/core/routeHook'
import moment from 'moment';
import User from '@/common/js/user';
import _ from 'underscore';
......@@ -110,6 +111,7 @@ class AddLive extends React.Component {
}
componentDidMount() {
routeHook.addSaveCase();
const { type } = this.state;
if (type === 'edit') {
this.getCourseDetail();
......@@ -279,7 +281,7 @@ class AddLive extends React.Component {
if (User.getExpirationTime() && moment().valueOf() > Number(User.getExpirationTime())) {
Modal.warning({
title: '服务已到期',
content: '当前企业购买的小麦企学院服务已到期,如需继续使用学院功能,请尽快续费购买',
content: `当前企业购买的${window.brandName}服务已到期,如需继续使用学院功能,请尽快续费购买`,
okText: '我知道了',
});
return;
......@@ -370,6 +372,7 @@ class AddLive extends React.Component {
CourseService.createLiveCloudCourse(params).then((res) => {
if (res.success) {
message.success('新建成功');
routeHook.cancel()
window.RCHistory.push({
pathname: `/live-course`,
});
......@@ -385,6 +388,7 @@ class AddLive extends React.Component {
CourseService.updateLiveCloudCourse(params).then((res) => {
if (res.success) {
message.success('更新成功');
routeHook.cancel()
window.RCHistory.push({
pathname: `/live-course`,
});
......@@ -515,19 +519,12 @@ class AddLive extends React.Component {
// 比较state的addLiveBasicInfo, addLiveClassInfo, addLiveIntroInfo和默认数据是否相等
const { addLiveBasicInfo, addLiveClassInfo, addLiveIntroInfo } = this.state;
if (!_.isEqual(addLiveBasicInfo, defaultBasicInfo) || !_.isEqual(addLiveClassInfo, defaultClassInfo) || !_.isEqual(addLiveIntroInfo, defaultIntroInfo)) {
Modal.confirm({
title: '确定要返回吗?',
content: '返回后,本次编辑的内容将不被保存',
okText: '确认返回',
cancelText: '留在本页',
icon: <span className='icon iconfont default-confirm-icon'>&#xe6f4;</span>,
onOk: () => {
window.RCHistory.push({
pathname: `/live-course`,
});
},
console.log('ghjklkjh')
window.RCHistory.push({
pathname: `/live-course`,
});
} else {
routeHook.cancel()
window.RCHistory.push({
pathname: `/live-course`,
});
......@@ -541,7 +538,7 @@ class AddLive extends React.Component {
<Breadcrumbs navList={type == 'add' ? '新建直播课' : '编辑直播课'} goBack={this.handleGoBack} />
<div className='box'>
<div className='show-tips'>
<ShowTips message='请遵守国家相关规定,切勿上传低俗色情、暴力恐怖、谣言诈骗、侵权盗版等相关内容,小麦企学院保有依据国家规定及平台规则进行处理的权利' />
<ShowTips message={`请遵守国家相关规定,切勿上传低俗色情、暴力恐怖、谣言诈骗、侵权盗版等相关内容,${window.brandName}保有依据国家规定及平台规则进行处理的权利`} />
</div>
<div className='add-live-page__form'>
<div className='basic-info__wrap'>
......
......@@ -2,7 +2,7 @@ import User from '@/common/js/user';
import college from '@/common/lottie/college';
import { PageControl, XMTable } from '@/components';
import CourseService from '@/domains/course-domain/CourseService';
import { Button, message, Popover, Spin } from 'antd';
import { Button, message, Popover, Spin, Tooltip } from 'antd';
import React from 'react';
import { withRouter } from 'react-router-dom';
import dealTimeDuration from '../utils/dealTimeDuration';
......@@ -11,7 +11,7 @@ class DataList extends React.Component {
constructor(props) {
super(props);
const courseId = getParameterByName('id'); // 课程ID
const type = getParameterByName('type'); // 来源: 大班直播 large 互动班课 interactive
const type = getParameterByName('type'); // 来源: 大班直播 large 互动班课 interactive 企微直播 qiwei
this.state = {
type,
teacherData: [], // 老师上课数据
......@@ -39,32 +39,72 @@ class DataList extends React.Component {
current,
size,
};
CourseService.fetchUserData(params).then((res) => {
if (res.result) {
const { records = [], current, size, total } = res.result;
if (this.state.type === "qiwei") {
CourseService.fetchWorkWXUserData(params).then((res) => {
if (res.result) {
const { records = [], current, size, total } = res.result;
this.setState({
studentData: records,
current,
size,
total,
loading: false,
});
}
});
} else {
CourseService.fetchUserData(params).then((res) => {
if (res.result) {
const { records = [], current, size, total } = res.result;
this.setState({
studentData: records,
current,
size,
total,
loading: false,
});
}
});
}
this.setState({
studentData: records,
current,
size,
total,
loading: false,
});
}
});
};
// 获取老师上课数据
fetchLecturerData = () => {
const { liveCourseId } = this.state;
CourseService.fetchLecturerData({ liveCourseId }).then((res) => {
if (res.result) {
this.setState({
teacherData: res.result,
});
}
});
if (this.state.type === "qiwei") {
CourseService.fetchWorkWXLecturerData({ liveCourseId }).then((res) => {
if (res.result) {
this.setState({
teacherData: res.result,
});
}
});
} else {
CourseService.fetchLecturerData({ liveCourseId }).then((res) => {
if (res.result) {
this.setState({
teacherData: res.result,
});
}
});
}
};
studentTypeEnum = (type)=> {
if (type === "STUDENT") {
return "学员"
}
if (type === "NON_STUDENT") {
return "待加入"
}
if (type === "GUEST") {
return "游客"
}
}
// 进入直播次数列表
getVisiterColumns() {
const columns = [
......@@ -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
handleExportV5 = () => {
const { liveCourseId, storeId } = this.state;
CourseService.exportStudentCourseData({
liveCourseId: liveCourseId,
exportLiveType: 'VISITOR',
storeId,
}).then((res) => {
const link = res.result;
this.setState({
link,
if (this.state.type === "qiwei") {
CourseService.exportWorkWXStudentCourseData({
liveCourseId: liveCourseId,
exportLiveType: 'VISITOR',
storeId,
}).then((res) => {
const link = res.result;
this.setState({
link,
});
document.getElementById('loadExcel').click();
if (res.success) {
message.success('导出成功!');
}
});
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 = () => {
......@@ -239,7 +344,7 @@ class DataList extends React.Component {
};
render() {
const { teacherData, studentData, current, size, total, loading, link } = this.state;
const { teacherData, studentData, current, size, total, loading, link, type } = this.state;
return (
<Spin spinning={loading}>
<a href={link} target='_blank' download id='loadExcel' style={{ position: 'absolute', left: '-10000px' }}>
......@@ -257,18 +362,22 @@ class DataList extends React.Component {
</div>
</div>
<div className='times item-block'>
<div className={`times-num ${Number(teacherData.entryNum) > 0 ? 'can-click' : ''}`}>
{Number(teacherData.entryNum) > 0 ? (
<Popover content={this.showTable()} trigger='click'>
<span className='times-num'>{teacherData.entryNum || 0}</span>
</Popover>
) : (
<span className='times-num'>{0}</span>
)}
{
type !== "qiwei" &&
<div className='times item-block'>
<div className={`times-num ${Number(teacherData.entryNum) > 0 ? 'can-click' : ''}`}>
{Number(teacherData.entryNum) > 0 ? (
<Popover content={this.showTable()} trigger='click'>
<span className='times-num'>{teacherData.entryNum || 0}</span>
</Popover>
) : (
<span className='times-num'>{0}</span>
)}
</div>
<div className='text'>进入直播间次数</div>
</div>
<div className='text'>进入直播间次数</div>
</div>
}
<div className='online-duration item-block'>
<div className='duration'>{teacherData.totalDuration ? dealTimeDuration(teacherData.totalDuration) : '00:00:00'}</div>
......
......@@ -21,6 +21,7 @@ class DataList extends React.Component {
}
render() {
const type = window.getParameterByName("type")
return (
<div className="page data-list">
<Breadcrumbs
......@@ -35,9 +36,13 @@ class DataList extends React.Component {
<CourseData></CourseData>
</Tabs.TabPane>
<Tabs.TabPane tab="回放记录" key="playbackData">
<PlaybackData></PlaybackData>
</Tabs.TabPane>
{
type !== "qiwei" &&
<Tabs.TabPane tab="回放记录" key="playbackData">
<PlaybackData></PlaybackData>
</Tabs.TabPane>
}
</Tabs>
</div>
......
......@@ -38,7 +38,7 @@
.title {
font-size: 16px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
font-weight: 600;
color: #333333;
margin-bottom: 16px;
position: relative;
......@@ -84,6 +84,7 @@
background: #ffffff;
border: 1px solid #e8e8e8;
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 32px;
.item-block {
......
......@@ -28,7 +28,8 @@ class AddLiveBasic extends React.Component {
showSelectFileModal: false,
cutImageBlob: null,
hasImgReady: false, // 图片是否上传成功
cropperInstace: null,
cropperInstace:null,
courseNameLimit: props.courseNameLimit?props.courseNameLimit:40
}
}
componentWillUnmount() {}
......@@ -105,21 +106,30 @@ class AddLiveBasic extends React.Component {
<span className='label'>
<span className='require'>*</span>课程名称:
</span>
<div id="courseName" style={{display:"inline-block"}}>
<Input
className={_.find(this.props.exItems,(item)=>{return item === "courseName"})?"err":""}
value={courseName}
placeholder='请输入直播名称(40字以内)'
maxLength={40}
placeholder={`请输入直播名称(${this.state.courseNameLimit}字以内)`}
maxLength={this.state.courseNameLimit}
style={{ width: 240 }}
onChange={(e) => {
this.props.onChange('courseName', e.target.value)
}}
/>
</div>
</div>
<div className='course-cover'>
<span className='label'>封面图:</span>
<div className='course-cover__wrap'>
<div className='opt-btns'>
<div className='img-content'>
{isDefaultCover && <span className='tag'>默认图</span>}
<img src={coverUrl} />
</div>
</div>
<div className='opt-btns'>
<Button
onClick={() => {
this.setState({
......@@ -133,22 +143,20 @@ class AddLiveBasic extends React.Component {
</span>
<div className='tips'>建议尺寸1280*720px或16:9。封面图最大5M,支持jpg、jpeg和png。</div>
</div>
<div className='img-content'>
{isDefaultCover && <span className='tag'>默认图</span>}
<img src={coverUrl} />
</div>
</div>
</div>
<div className='course-catalog'>
<span className='label'>
<span className='require'>*</span>课程分类:
</span>
<div id="categoryId" style={{display:"inline-block"}}>
<CourseCatalogSelect
className={_.find(this.props.exItems,(item)=>{return item === "categoryId"})?"err":""}
value={categoryId}
onChange={(value, label) => {
this.handleChangeCatalogList(value, label)
}}
/>
</div>
</div>
{showSelectFileModal && (
<SelectPrepareFileModal
......
......@@ -16,7 +16,6 @@
position: relative;
.img-content {
margin-top: 8px;
margin-right: 20px;
width: 299px;
height: 169px;
......@@ -41,33 +40,56 @@
left: 8px;
}
}
}
.opt-btns {
.default-btn {
margin-left: 14px;
color: #2966ff;
cursor: pointer;
.opt-btns {
.default-btn {
margin-left: 14px;
color: #2966ff;
cursor: pointer;
&.disabled {
color: #ccc;
cursor: not-allowed;
}
&.disabled {
color: #ccc;
cursor: not-allowed;
}
}
.ant-upload-list {
display: none;
}
.ant-upload-list {
display: none;
}
.tips {
margin-top: 8px;
color: #999;
}
.tips {
margin-top: 8px;
color: #999;
}
}
}
.course-catalog {
margin: 20px 0 0 14px;
}
//输入框异常项
.err.ant-input:hover {
border-color: #FF4F4F;
}
.err.ant-input:focus {
border-color: #FF4F4F !important;
box-shadow: 0 0 0 2px rgba(255,0,0,0.2);
}
.err.ant-input {
border-color: #FF4F4F;
}
//下拉选择异常项
.err.ant-select-focused:not(.ant-select-disabled).ant-select:not(.ant-select-customize-input) .ant-select-selector {
border-color: #FF4F4F;
box-shadow: 0 0 0 2px rgba(255,0,0,0.2);
}
.err.ant-select:not(.ant-select-disabled):hover {
.ant-select-selector {
border-color: #FF4F4F;
}
}
.err.ant-select:not(.ant-select-customize-input) .ant-select-selector {
border-color: #FF4F4F;
}
}
.ant-cascader-menu-item-active:not(.ant-cascader-menu-item-disabled) {
font-weight: normal !important;
......
......@@ -75,7 +75,7 @@ class AddLiveClass extends React.Component {
// 获取助教老师列表
getAssistantList = (current = 1, selectList) => {
const { assistantQuery,assistantList} = this.state;
const { assistantStoreUserId } = this.props.data;
const { assistantStoreUserId } = this.props.data ? this.props.data:[];
const idList = selectList ? selectList : assistantStoreUserId;
const _query = {
...assistantQuery,
......
.AddLiveClassInfoWorkWX {
margin-left: 16px;
margin-bottom: 98px;
.remind-time {
.ant-select-single.ant-select-show-arrow .ant-select-selection-placeholder {
color: #333333;
}
}
.item {
margin: 24px 0;
.label {
display: inline-block;
text-align: right;
width: 100px;
.require {
color: red;
}
}
//日期时间选择异常项
.err.ant-picker-focused {
border-color: #FF4F4F;
box-shadow: 0 0 0 2px rgba(255,0,0,0.2);
}
.err.ant-picker:hover {
border-color: #FF4F4F;
}
.err.ant-picker {
border-color: #FF4F4F;
}
}
.introduce {
display: flex;
}
.ant-select-item-option-selected:not(.ant-select-item-option-disabled) {
color: #2966FF;
}
// .eerr .ant-select-focused:not(.ant-select-disabled) .ant-select:not(.ant-select-customize-input) {
// .ant-select-selector {
// border-color: red;
// box-shadow: 0 0 0 2px rgba(255,0,0,0.2);
// }
// }
// .eerr .ant-select:not(.ant-select-disabled):hover {
// .ant-select-selector {
// border-color: red;
// }
// }
//下拉选择异常项
.err.ant-select-focused:not(.ant-select-disabled).ant-select:not(.ant-select-customize-input) .ant-select-selector {
border-color: #FF4F4F;
box-shadow: 0 0 0 2px rgba(255,0,0,0.2);
}
.err.ant-select:not(.ant-select-disabled):hover {
.ant-select-selector {
border-color: #FF4F4F;
}
}
.err.ant-select:not(.ant-select-customize-input) .ant-select-selector {
border-color: #FF4F4F;
}
//输入框异常项
.err.ant-input:hover {
border-color: #FF4F4F;
}
.err.ant-input:focus {
border-color: #FF4F4F;
box-shadow: 0 0 0 2px rgba(255,0,0,0.2);
}
.err.ant-input {
border-color: #FF4F4F;
}
}
\ No newline at end of file
......@@ -136,7 +136,7 @@ class AddLiveIntro extends React.Component {
<span className='label'>观看设置:</span>
<div className='content'>
<Switch checked={whetherVisitorsJoin === 'NO' ? true : false} onChange={this.whetherVisitorsJoinChange} />
<div class='instro-text'>{whetherVisitorsJoin === 'NO' ? '已开启,学员需绑定手机号才可观看' : '已关闭,学员无需绑定手机号即可观看'}</div>
<div className='instro-text'>{whetherVisitorsJoin === 'NO' ? '已开启,学员需绑定手机号才可观看' : '已关闭,学员无需绑定手机号即可观看'}</div>
</div>
</div>
<div className='warmup'>
......
.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
......@@ -14,6 +14,7 @@ import moment from 'moment'
import StoreService from '@/domains/store-domain/storeService'
import User from '@/common/js/user'
import './LiveCourseFilter.less'
import { brandLiveName } from '@/domains/brand/constants'
const { Search } = Input
const { Option } = Select
......@@ -24,6 +25,7 @@ const defaultQuery = {
teacherId: null,
courseState: null,
shelfState: null,
thirdPartType: null
}
const defaultTeacherQuery = {
size: 10,
......@@ -50,6 +52,7 @@ class LiveCourseFilter extends React.Component {
current,
size: 10,
}
StoreService.getStoreUserBasicPage(_query).then((res) => {
const { result = {} } = res
const { records = [], total = 0, hasNext } = result
......@@ -150,6 +153,7 @@ class LiveCourseFilter extends React.Component {
courseState: undefined,
current: 1,
shelfState: null,
thirdPartType: null
},
},
() => {
......@@ -159,7 +163,7 @@ class LiveCourseFilter extends React.Component {
}
render() {
const { courseName, startTime, endTime, courseState, teacherName, teacherId, shelfState } = this.state.query
const { courseName, startTime, endTime, courseState, teacherName, teacherId, shelfState, thirdPartType } = this.state.query
const { expandFilter, teacherList, teacherQuery } = this.state
const { teacherId: _teahcerId } = {}
const isTeacher = !!_teahcerId // 判断是否是老师身份
......@@ -199,7 +203,7 @@ class LiveCourseFilter extends React.Component {
</div>
{User.getUserRole() !== 'CloudLecturer' && (
<div className='search-condition__item'>
<span>讲师:</span>
<span style={{width:"70px",display:"inline-block",textAlign:"right"}}>讲师:</span>
<Select
placeholder='请选择讲师'
style={{ width: 'calc(100% - 70px)' }}
......@@ -295,6 +299,37 @@ class LiveCourseFilter extends React.Component {
</Select>
</div>
)}
{expandFilter && (
<div className='search-condition__item'>
<span className='live-type'>直播方式:</span>
<Select
style={{ width: 'calc(100% - 70px)' }}
placeholder='请选择'
allowClear={true}
onClear={(value) => {
this.setState(
{
query: {...this.state.query,thirdPartType:null}
},
() => {
this.props.onChange(this.state.query)
}
)
}}
value={thirdPartType}
onChange={(value) => {
this.handleChangeQuery('thirdPartType', value)
}}
suffixIcon={
<span className='icon iconfont' style={{ fontSize: '12px', color: '#BFBFBF' }}>
&#xe835;
</span>
}>
<Option value='WECHAT'>企微直播</Option>
<Option value='TENCENT'>{brandLiveName}</Option>
</Select>
</div>
)}
</div>
<div className='reset-fold-area'>
......
......@@ -9,55 +9,96 @@
import React from 'react';
import { Button, Modal, message } from 'antd';
import Service from '@/common/js/service';
import { withRouter ,Route} from "react-router-dom";
import './liveCourseOpt.less';
import BaseService from "@/domains/basic-domain/baseService";
import CreateWorkWXCourse from './CreateWorkWXCourse'
import User from '@/common/js/user'
import LiveModeSelect from './LiveModeSelect';
class LiveCourseOpt extends React.Component {
constructor(props) {
super(props);
this.state = {
isMac: /macintosh|mac os x/i.test(navigator.userAgent),
showModeSelect: false,
}
}
handleCreateLiveCouese = ()=>{
window.RCHistory.push({
pathname: '/create-live-course?type=add',
this.setState({
showModeSelect: true
})
// window.RCHistory.push({
// pathname: '/create-live-course?type=add',
// })
}
onModeSelectClose = ()=> {
this.setState({
showModeSelect: false
})
}
onModeSelected = (type)=> {
this.setState({
showModeSelect: false
})
if (type === 0) {
window.RCHistory.push({
pathname: '/create-live-course?type=add',
})
} else if (type === 1) {
const { match } = this.props;
this.props.history.push(`${match.url}/createqwcourse?type=add`)
}
}
handleCreateQWCouese=()=>{
const { match } = this.props;
this.props.history.push(`${match.url}/createqwcourse`)
}
// 下载直播客户端
handleDownloadClient = () => {
const { isMac } = this.state;
const BRAND = process.env.BRAND;
// 判断学员系统
let platform;
if(!isMac){
if (!isMac) {
platform = 1
} else {
platform = 4
}
BaseService
.getLastedVersion({ model: 5, platform})
.then((res) => {
const a = document.createElement("a");
document.body.appendChild(a);
a.href = res.result.releaseUrl;
a.click();
document.body.removeChild(a);
})
.getLastedVersion({ model: 5, platform })
.then((res) => {
const a = document.createElement("a");
document.body.appendChild(a);
a.href = res.result.releaseUrl;
a.click();
document.body.removeChild(a);
})
}
render() {
const userRole = User.getUserRole();
const { match } = this.props;
return (
<div className="live-course-opt">
<LiveModeSelect onClose={this.onModeSelectClose} onSelected={this.onModeSelected} isShow={this.state.showModeSelect}/>
<div className="opt__left">
{ userRole !== "CloudLecturer" &&
{userRole !== "CloudLecturer" &&
<Button type="primary" onClick={this.handleCreateLiveCouese}>新建直播课</Button>
}
<Button onClick={this.handleDownloadClient}>下载直播客户端</Button>
{/* <Button type="primary" onClick={this.handleCreateQWCouese}>新建企微直播课</Button> */}
{!this.state.isMac && <Button onClick={this.handleDownloadClient}>下载直播客户端</Button>}
</div>
<Route path={`${match.url}/createqwcourse`} component={CreateWorkWXCourse} />
</div>
)
}
}
export default LiveCourseOpt;
\ No newline at end of file
export default withRouter(LiveCourseOpt);
\ No newline at end of file
.livemode-select {
position: fixed;
display: flex;
justify-content: center;
align-items: center;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background-color: rgba(0,0,0,0.4);
z-index: 1000;
.dialog {
width: 680px;
height: 438px;
background: #FFFFFF;
border-radius: 6px;
.header {
display: flex;
justify-content: space-between;
align-items: center;
width: 680px;
height: 50px;
border-bottom: 1px solid #E8E8E8;
.title {
font-size: 16px;
color: #333333;
font-weight: 400;
margin-left: 23px;
}
.close {
color: #999999;
margin-right: 23px;
font-size: 12px;
cursor: pointer;
}
}
.content {
display: flex;
justify-content: space-between;
margin: 43px 95px 50px 95px;
.item {
display: inline-block;
width: 221px;
height: 294px;
background: #FFFFFF;
box-shadow: 0px 2px 8px 3px rgba(41, 102, 255, 0.1);
border-radius: 5px;
text-align: center;
background-size: contain;
background-repeat: no-repeat;
.logo {
width: 80px;
height: 80px;
margin: 31px auto 0 auto;
}
.item-title {
font-size: 16px;
font-weight: 500;
color: #333333;
margin: 25px auto 0 auto;
}
.des {
margin: 14px auto 0 auto;
font-size: 14px;
font-weight: 400;
color: #666666;
}
.button {
font-size: 14px;
font-weight: 400;
color: white;
width: 100px;
height: 32px;
background: #2966FF;
border-radius: 16px;
margin: 25px auto 0 auto;
padding-top: 5px;
cursor: pointer;
}
}
.xiaomai-logo {
background-image: url("https://image.xiaomaiketang.com/xm/rjwN8Yc7xa.png");
}
.qiwei-logo {
background-image: url("https://image.xiaomaiketang.com/xm/CzdyntSxha.png");
}
}
}
}
.livemode-select-none {
display: none;
}
\ No newline at end of file
import React, { useState } from "react";
import "./LiveModeSelect.less"
import { createPortal } from "react-dom";
import { brandLiveName } from "@/domains/brand/constants";
interface LiveModeSelectProps {
isShow: boolean;
onClose: ()=> void;
onSelected: (type: number)=> void;
}
export default function LiveModeSelect(props: LiveModeSelectProps) {
const handleSelect0 = (e: React.MouseEvent<HTMLDivElement>)=> {
const { onSelected } = props
onSelected(0)
}
const handleSelect1 = (e: React.MouseEvent<HTMLDivElement>)=> {
const { onSelected } = props
onSelected(1)
}
const handleClose = (e: React.MouseEvent<HTMLDivElement>)=> {
props.onClose()
}
return createPortal(
<div className={`livemode-select${props.isShow ? "":" livemode-select-none"}`}>
<div className="dialog">
<div className="header">
<div className="title">选择直播方式</div>
<span className="icon iconfont close" onClick={handleClose}>&#xe6ef;</span>
</div>
<div className="content">
<div className="item xiaomai-logo">
<div className="logo"></div>
<div className="item-title">{brandLiveName}</div>
<div className="des">通过{window.brandName}“PC客户<br/>端”进行直播</div>
<div className="button" onClick={handleSelect0}>立即创建</div>
</div>
<div className="item qiwei-logo">
<div className="logo qiwei-logo"></div>
<div className="item-title">企微直播</div>
<div className="des">通过“企业微信APP”<br/>进行直播</div>
<div className="button" onClick={handleSelect1}>立即创建</div>
</div>
</div>
</div>
</div>,
document.body
)
}
\ No newline at end of file
......@@ -280,7 +280,7 @@ class AddGraphicsCourse extends React.Component {
if (User.getExpirationTime() && moment().valueOf() > Number(User.getExpirationTime())) {
Modal.warning({
title: '服务已到期',
content: '当前企业购买的小麦企学院服务已到期,如需继续使用学院功能,请尽快续费购买',
content: `当前企业购买的${window.brandName}服务已到期,如需继续使用学院功能,请尽快续费购买`,
okText: '我知道了',
})
return
......@@ -423,7 +423,7 @@ class AddGraphicsCourse extends React.Component {
<div className='box'>
<div className='show-tips'>
<ShowTips message='请遵守国家相关规定,切勿上传低俗色情、暴力恐怖、谣言诈骗、侵权盗版等相关内容,小麦企学院保有依据国家规定及平台规则进行处理的权利' />
<ShowTips message={`请遵守国家相关规定,切勿上传低俗色情、暴力恐怖、谣言诈骗、侵权盗版等相关内容,${window.brandName}保有依据国家规定及平台规则进行处理的权利`} />
</div>
<div className='form'>
......
......@@ -333,6 +333,7 @@ class ManageCoursewareModal extends React.Component {
];
const { list, scanFileModal, editData, cancelObject, showSelectFileModal, selectedFileList, diskList, showPreviewModal, previewStatus, url } = this.state;
const _list = _.reject(list, (item) => cancelObject[item.id]);
const { thirdPartType } = this.props.data
return (
<Modal
visible={true}
......@@ -348,10 +349,17 @@ class ManageCoursewareModal extends React.Component {
{_.isEmpty(_list) ? (
<div className='empty-body'>
<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>
<p className='empty-tip'>提前上传直播需要的课件和素材,直播将会变得更便捷!</p>
{ thirdPartType !== "WECHAT" && <p className='empty-tip'>提前上传直播需要的课件和素材,直播将会变得更便捷!</p>}
</div>
) : (
<div className='manage-body'>
......
......@@ -11,6 +11,14 @@
width:150px;
height:150px;
}
.qiwei-tip {
font-size: 14px;
font-weight: 400;
color: #999;
text-align: center;
margin-top: 12px;
margin-bottom: 12px;
}
.empty-button {
display: block;
margin: 0 auto 8px;
......
......@@ -107,47 +107,56 @@ class PreviewCourseModal extends React.Component {
timeHorizonStart,
timeHorizonEnd,
teacherName,
duration
} = courseClassInfo;
const { introduce, categoryName } = courseIntroInfo;
let { activeTab } = this.state;
let liveDateStr, startTimeStr, endTimeStr;
if (type === "add") {
const _liveDate = moment(calendarTime[0]).format("YYYY-MM-DD");
console.log("_liveDate", _liveDate);
const _timeHorizonStart = moment(startTime).format("HH:mm");
const _timeHorizonEnd = moment(endTime).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;
if (this.props.bizType === "qiwei") {
let _startTime = startTime === 0 ? moment().valueOf():startTime
startTimeStr = moment(_startTime).format("YYYY-MM-DD HH:mm")
endTimeStr = moment(endTime === 0?moment(_startTime+Number(duration)*1000).valueOf():endTime).format("HH:mm")
console.log(duration)
} else {
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;
if (type === "add") {
const _liveDate = moment(calendarTime[0]).format("YYYY-MM-DD");
console.log("_liveDate", _liveDate);
const _timeHorizonStart = moment(startTime).format("HH:mm");
const _timeHorizonEnd = moment(endTime).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;
} 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 (
<Modal
title="预览"
......
......@@ -60,10 +60,12 @@
.title__state {
min-width: 40px;
height: 17px;
padding: 0px 8px;
padding-left: 8px;
padding-right: 8px;
border-radius: 10px;
margin-left: 6px;
font-size: 12px;
line-height: 17px;
color: #FFF;
background-color: #34B88B;
}
......
......@@ -102,7 +102,7 @@ class ShareLiveModal extends React.Component {
render() {
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;
// 判断是否是默认图, 默认图不需要在URL后面增加字符串
let coverImgSrc = '';
......@@ -188,8 +188,8 @@ class ShareLiveModal extends React.Component {
<div className='right'>
<div className='share-poster right__item'>
<div className='title'>① 海报分享</div>
{type === 'liveClass' && <div className='sub-title'>学员可通过微信扫描海报二维码,观看{title}</div>}
{type === 'videoClass' && <div className='sub-title'>学员可通过微信识别二维码,报名观看{title}</div>}
{type === 'liveClass' && <div className='sub-title'>学员可通过微信{thirdPartType === "WECHAT"?"/企业微信":""}扫描海报二维码,观看{title}</div>}
{type === 'videoClass' && <div className='sub-title'>学员可通过微信{thirdPartType === "WECHAT"?"/企业微信":""}识别二维码,报名观看{title}</div>}
<div className='content' onClick={_.debounce(this.handleDownloadPoster, 1000, true)}>
下载海报
......@@ -198,7 +198,7 @@ class ShareLiveModal extends React.Component {
<div className='share-url right__item'>
<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>}
<div className='content url-content'>
<div className='share-url' id='shareUrl'>
......
......@@ -373,7 +373,7 @@ class AddOfflineCourse extends React.Component {
if (User.getExpirationTime() && moment().valueOf() > Number(User.getExpirationTime())) {
Modal.warning({
title: '服务已到期',
content: '当前企业购买的小麦企学院服务已到期,如需继续使用学院功能,请尽快续费购买',
content: `当前企业购买的${window.brandName}服务已到期,如需继续使用学院功能,请尽快续费购买`,
okText: '我知道了',
})
return
......@@ -711,7 +711,7 @@ class AddOfflineCourse extends React.Component {
<div className='box'>
<div className='show-tips'>
<ShowTips message='请遵守国家相关规定,切勿上传低俗色情、暴力恐怖、谣言诈骗、侵权盗版等相关内容,小麦企学院保有依据国家规定及平台规则进行处理的权利' />
<ShowTips message={`请遵守国家相关规定,切勿上传低俗色情、暴力恐怖、谣言诈骗、侵权盗版等相关内容,${window.brandName}保有依据国家规定及平台规则进行处理的权利`} />
</div>
<div className='form'>
......
......@@ -363,15 +363,15 @@ class AddVideoCourse extends React.Component {
// 保存
handleSubmit = () => {
//过期判断
if (User.getExpirationTime() && moment().valueOf() > Number(User.getExpirationTime())) {
Modal.warning({
title: '服务已到期',
content: '当前企业购买的小麦企学院服务已到期,如需继续使用学院功能,请尽快续费购买',
okText: '我知道了',
});
return;
}
//过期判断
if (User.getExpirationTime() && moment().valueOf() > Number(User.getExpirationTime())) {
Modal.warning({
title:"服务已到期",
content:`当前企业购买的${window.brandName}服务已到期,如需继续使用学院功能,请尽快续费购买`,
okText: "我知道了"
})
return
}
const {
id,
......@@ -695,7 +695,7 @@ class AddVideoCourse extends React.Component {
<div className='box'>
<div className='show-tips'>
<ShowTips message='请遵守国家相关规定,切勿上传低俗色情、暴力恐怖、谣言诈骗、侵权盗版等相关内容,小麦企学院保有依据国家规定及平台规则进行处理的权利' />
<ShowTips message={`请遵守国家相关规定,切勿上传低俗色情、暴力恐怖、谣言诈骗、侵权盗版等相关内容,${window.brandName}保有依据国家规定及平台规则进行处理的权利`} />
</div>
<div className='form'>
......
......@@ -427,8 +427,8 @@ class Home extends React.Component {
<Choose>
<When condition={_.isEmpty(list)}>
<div className='study-empty'>
<img src='https://image.xiaomaiketang.com/xm/52dmait5Bx.png' alt='' />
<div>暂无课程上榜</div>
<img src='https://image.xiaomaiketang.com/xm/fFnpKMJD6x.png' alt='' />
<div className="text">暂无学员上榜</div>
</div>
</When>
<Otherwise>
......
......@@ -64,9 +64,11 @@
font-size: 28px;
color: #333;
margin-top: 24px;
margin-left: 22px;
}
.data-footer {
margin-top: 12px;
margin-left: 22px;
.footer-word {
font-size: 12px;
color: #999;
......@@ -238,13 +240,13 @@
margin-top: 102px;
img {
display: block;
width: 100px;
height: 100px;
width: 150px;
height: 150px;
margin: 0 auto 8px;
}
div {
text-align: center;
color: #333;
color: #999;
}
}
.circle-box {
......
......@@ -7,59 +7,59 @@ import moment from "moment";
export default function HomeTip() {
const [isOverNum, setIsOverNum] = useState<boolean>(false)
const [tipType, setTipType] = useState(0) //0不显示1即将过期2已过期
const [expirationTime, setExpirationTime] = useState("")
const [surplusDay, setSurplusDay] = useState(0)
const versionInfo = useContext(VersionContext)
useEffect(()=> {
if (versionInfo) {
setIsOverNum(versionInfo.userNum === -1 ? false : versionInfo.whetherReachUserNum)
setSurplusDay(versionInfo.surplusDayTime)
setExpirationTime(versionInfo.validEndTime)
if (versionInfo.stateEnum === "NO") {
setTipType(2)
} else if (versionInfo.surplusDayTime === 30 || versionInfo.surplusDayTime <= 7) {
setTipType(1)
}
const [isOverNum, setIsOverNum] = useState<boolean>(false)
const [tipType, setTipType] = useState(0) //0不显示1即将过期2已过期
const [expirationTime, setExpirationTime] = useState("")
const [surplusDay, setSurplusDay] = useState(0)
const versionInfo = useContext(VersionContext)
useEffect(() => {
if (versionInfo) {
setIsOverNum(versionInfo.userNum === -1 ? false : versionInfo.whetherReachUserNum)
setSurplusDay(versionInfo.surplusDayTime)
setExpirationTime(versionInfo.validEndTime)
if (versionInfo.stateEnum === "NO") {
setTipType(2)
} else if (versionInfo.surplusDayTime === 30 || versionInfo.surplusDayTime <= 7) {
setTipType(1)
}
},[versionInfo])
return (
<div className="home-tip">
{
(isOverNum || tipType !== 0) &&
}
}, [versionInfo])
return (
<div className="home-tip">
{
(isOverNum || tipType !== 0) &&
<div className="tip">
<Carousel dotPosition="left" dots={false} autoplay={true} autoplaySpeed={5000}>
{
isOverNum && (
<div className="content">
<span className="icon iconfont" style={{color:"#FF4F4F",marginRight:"8px"}}>&#xe61d;</span>温馨提示:企业使用人数已达上限,将无法新增员工、学员,如需增加人数限制,请联系小麦企学院服务平台。
<ContactWidget placement="bottom" trigger="hover"><div className="renew-btn">立即续费</div></ContactWidget>
<span className="icon iconfont" style={{ color: "#FF4F4F", marginRight: "8px" }}>&#xe61d;</span>{`温馨提示:企业使用人数已达上限,将无法新增员工、学员,如需增加人数限制,请联系${window.brandName}服务平台。`}
<ContactWidget placement="bottom" trigger="hover"><div className="renew-btn">立即续费</div></ContactWidget>
</div>
)
}
{
tipType === 2 && (
<div className="content">
<span className="icon iconfont" style={{color:"#FF4F4F",marginRight:"8px"}}>&#xe61d;</span>版本到期提醒:当前企业购买的小麦企学院服务已于{moment(versionInfo?.validEndTimeST).format("YYYY-MM-DD HH:mm:ss")}到期,到期后仍可访问,但功能不可使用,建议尽快续费购买哦~
<ContactWidget placement="bottom" trigger="hover"><div className="renew-btn">立即续费</div></ContactWidget>
<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>
</div>
)
}
{
tipType === 1 && (
<div className="content">
<span className="icon iconfont" style={{color:"#FF4F4F",marginRight:"8px"}}>&#xe61d;</span>当前企业购买的小麦企学院服务仅剩{surplusDay}天(于{expirationTime}到期),为了不影响使用,建议尽快续费购买哦~
<ContactWidget placement="bottom" trigger="hover"><div className="renew-btn">立即续费</div></ContactWidget>
<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>
</div>
)
}
</Carousel>
</div>
}
}
</div>
)
}
\ No newline at end of file
)
}
\ No newline at end of file
......@@ -22,7 +22,6 @@ import "./KnowledgeBaseList.less";
const DEFAULT_SIZE_UNIT = 1000 * 1000 // 将B转换成M
const { confirm } = Modal
const ENV = process.env.DEPLOY_ENV || "dev"
class KnowledgeBaseList extends React.Component {
constructor(props) {
......
......@@ -19,7 +19,6 @@ import "./LiveList.less";
import CourseService from "@/domains/course-domain/CourseService";
import User from "@/common/js/user";
const ENV = process.env.DEPLOY_ENV || "dev";
class VideoList extends React.Component {
constructor(props) {
......
......@@ -3,7 +3,7 @@
padding: 24px 60px 60px 40px !important;
}
.label{
width:84px;
width:100px;
text-align:right;
font-size: 14px;
color: #666666;
......@@ -37,10 +37,10 @@
color:#FFF;
font-size:22px;
}
&:hover{
display: inline-block;
opacity:0.5;
}
// &:hover{
// display: inline-block;
// opacity:0.5;
// }
}
}
.name-item{
......@@ -58,7 +58,8 @@
}
}
.save-btn {
margin-left: 92px;
margin-top:20px;
margin-left: 106px;
}
}
\ No newline at end of file
/*
* @Author: zhangleyuan
* @Date: 2020-11-27 15:06:31
* @LastEditors: wufan
* @LastEditTime: 2021-05-28 15:31:06
* @LastEditors: Please set LastEditors
* @LastEditTime: 2021-08-05 10:26:25
* @Description: 描述一下
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
......@@ -17,6 +17,7 @@ import IdentificationModal from "./IdentificationModal";
import ChangePhoneModal from "./ChangePhoneModal";
import BaseService from "@/domains/basic-domain/baseService";
import StoreService from "@/domains/store-domain/storeService";
import WWOpenDataCom from '@/components/WWOpenDataCom';
import User from "@/common/js/user";
import "./index.less";
import { XMContext } from "@/store/context";
......@@ -35,7 +36,7 @@ function PersonalInfoPage() {
const [roleCodes, setRoleCodes] = useState([]);
const [phone, setPhone] = useState("");
const [weChatAccount, setWeChatAccount] = useState("");
const [departmentList,setDepartmentList] = useState([]);
const storeUserId = User.getStoreUserId();
const ctx: any = useContext(XMContext);
const userId = User.getUserId();
......@@ -51,11 +52,12 @@ function PersonalInfoPage() {
storeUserId: User.getStoreUserId(),
};
BaseService.getStoreUser(param).then((res) => {
const { nickName, phone, roleCodes, weChatAccount } = res.result;
const { nickName, phone, roleCodes, weChatAccount,depNameList=[]} = res.result;
setNickName(nickName);
setPhone(phone);
setRoleCodes(roleCodes);
setWeChatAccount(weChatAccount);
setDepartmentList(depNameList)
if (res.result.avatar) {
setAvatar(res.result.avatar);
}
......@@ -122,7 +124,6 @@ function PersonalInfoPage() {
setPhone(phone);
}
console.log('User.getStoreType()',User.getStoreType());
return (
<div className="page personal-info-page">
<div className="content-header">个人设置</div>
......@@ -130,18 +131,7 @@ console.log('User.getStoreType()',User.getStoreType());
<Form>
<div className="avatat-item">
<span className="label">头像:</span>
<input
type="file"
accept="image/*"
value={""}
id="CrpperAvatarPic"
style={{ display: "none" }}
onChange={_handleUpdateAvatar}
/>
<img className="avatar" src={avatar}></img>
<span className="avatar-cover" onClick={_onUpload}>
<span className="icon iconfont pen">&#xe82c;</span>
</span>
{cropperModalVisible && (
<CropperModal
imgUrl={imgUrl}
......@@ -162,9 +152,13 @@ console.log('User.getStoreType()',User.getStoreType());
}}
/>
</div>
<div className="phone-item">
<span className="label">企业微信姓名:</span>
<span><WWOpenDataCom type="userName" openid={weChatAccount}/></span>
</div>
{isWorkWechat ? (
<div className="phone-item">
<span className="label">企业微信号:</span>
<span className="label">企业微信号:</span>
<span>{weChatAccount}</span>
</div>
) : (
......@@ -181,6 +175,12 @@ console.log('User.getStoreType()',User.getStoreType());
</Button>
</div>
)}
<div>
<span className="label">所在部门:</span>
{departmentList.map((item,index)=>{
return <span><WWOpenDataCom type="departmentName" openid={item}/>{index<departmentList.length-1?'、':''}</span>
})}
</div>
<div className="save-btn">
<Button
type="primary"
......
......@@ -281,7 +281,7 @@ function AddPlan() {
<Breadcrumbs navList={type == 'add' ? '新建培训计划' : '编辑培训计划'} goBack={handleGoBack} />
<div className='box'>
<div className='show-tips'>
<ShowTips message='请遵守国家相关规定,切勿上传低俗色情、暴力恐怖、谣言诈骗、侵权盗版等相关内容,小麦企学院保有依据国家规定及平台规则进行处理的权利' />
<ShowTips message={`请遵守国家相关规定,切勿上传低俗色情、暴力恐怖、谣言诈骗、侵权盗版等相关内容,${window.brandName}保有依据国家规定及平台规则进行处理的权利`} />
</div>
<div className='add-plan-page__form'>
<div className='basic-info__wrap'>
......
......@@ -61,8 +61,8 @@ function PlanFilter(props) {
delete _query.startTime;
delete _query.endTime;
} else {
_query.startTime = dates[0].valueOf();
_query.endTime = dates[1].valueOf();
_query.startTime = dates[0]?.startOf('day').valueOf()
_query.endTime = dates[1]?.endOf('day').valueOf()
}
const param ={
..._query,
......
/*
* @Author: zhangleyuan
* @Date: 2021-02-20 16:46:46
* @LastEditors: wufan
* @LastEditTime: 2021-07-16 11:29:13
* @LastEditors: Please set LastEditors
* @LastEditTime: 2021-07-21 16:03:02
* @Description: 描述一下
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
......
......@@ -309,7 +309,6 @@ class SelectOperatorModal extends React.Component {
),
key: 'course',
dataIndex: 'course',
width: '40%',
render: (val, record) => {
let hasCover = false;
return (
......@@ -341,7 +340,7 @@ class SelectOperatorModal extends React.Component {
title: '上课时间',
key: 'courseTime',
dataIndex: 'courseTime',
width: '40%',
width: 150,
render: (val, record) => {
return (
<div>
......@@ -357,7 +356,7 @@ class SelectOperatorModal extends React.Component {
title: '学院展示',
key: 'shelfState',
dataIndex: 'shelfState',
width: '20%',
width: 120,
render: (val, record) => {
return (
<span>
......
......@@ -2,7 +2,7 @@
* @Author: 吴文洁
* @Date: 2019-07-10 10:30:49
* @LastEditors: Please set LastEditors
* @LastEditTime: 2021-06-22 17:47:02
* @LastEditTime: 2021-07-19 16:21:07
* @Description:
*/
import React, { useContext, useEffect, useState } from 'react';
......@@ -16,10 +16,10 @@ import User from '@/common/js/user';
import BaseService from "@/domains/basic-domain/baseService";
import moment from 'moment';
import { VersionContext, VersionInfo, XMContext } from '@/store/context';
import { setStoreGroupPermission, setStorePermission, setStoreGroupList, setStoreList } from '@/store/actions/index';
import WechatApi from '@/common/js/wechatApi';
import { setStoreGroupPermission, setStorePermission, setStoreGroupList, setStoreList, setWechatLogin } from '@/store/actions/index';
import Service from "@/common/js/service";
import Bus from '@/core/tbus';
import { func } from 'prop-types';
const { Footer, Sider, Content } = Layout;
......@@ -28,14 +28,16 @@ declare var window: any;
const App: React.FC = (props: any) => {
const [storeUserId, setStoreUserId] = useState('')
const ctx: any = useContext(XMContext);
const [versionInfo, setVersionInfo] = useState<VersionInfo|null>(null)
const [versionInfo, setVersionInfo] = useState<VersionInfo | null>(null)
const userId = User.getUserId();
const [menuType, setMenuType] = useState(true);
const [initWechat, setInitWechat] = useState(false);
const enterpriseId = User.getEnterpriseId();
window.ctx = ctx;
useEffect(() => {
initWechatConfig();
getStoreAndUserInfo();
getVersion();
if (window.location.hash === "#/") {
......@@ -44,7 +46,13 @@ const App: React.FC = (props: any) => {
})
}
}, [])
async function initWechatConfig() {
WechatApi.initConfig({ isAgentConfig: true, url: window.location.href.split('#')[0] }).then(() => {
ctx.dispatch(setWechatLogin(true))
})
}
useEffect(() => {
getStorePermission();
}, [window.location.hash])
......@@ -66,7 +74,7 @@ const App: React.FC = (props: any) => {
let version = res.result;
User.setVersion(version);
User.setExpirationTime(res.result.validEndTime)
let versioninfo:VersionInfo = {
let versioninfo: VersionInfo = {
dayTime: version.dayTime,
stateEnum: version.stateEnum,
userNum: version.userNum === -1 ? '不限人数' : version.userNum,
......@@ -85,30 +93,30 @@ const App: React.FC = (props: any) => {
async function getStoreAndUserInfo() {
await (enterpriseId ? getStoreInfo() : getStoreGroupAndStoreList());
}
function getStoreInfo() {
console.log("currentStoreUserInfo",window.currentStoreUserInfo);
console.log("currentStoreUserInfo", window.currentStoreUserInfo);
const params = {
storeId: User.getStoreId(),
userId: User.getUserId(),
};
Service.Hades('public/customerHades/getStoreAndUserMsg', params).then((res) => {
if(res.success){
if (res.success) {
const { id, storeUserId, storeName, userRole, storeType } = res.result;
User.setStoreId(id);
User.setStoreUserId(storeUserId);
User.setStoreName(storeName);
Bus.trigger('storeNameChange',storeName);
Bus.trigger('storeNameChange', storeName);
User.setUserRole(userRole);
User.setStoreType(storeType);
setCurrentStoreUserInfo(id,storeUserId)
setCurrentStoreUserInfo(id, storeUserId)
setStoreUserId(storeUserId);
getUserPermission();
}
})
}
function setCurrentStoreUserInfo(storeId:any,storeUserId:any){
function setCurrentStoreUserInfo(storeId: any, storeUserId: any) {
window.currentStoreUserInfo.storeId = storeId;
window.currentStoreUserInfo.storeUserId = storeUserId;
window.currentStoreUserInfo.userId = User.getUserId();
......@@ -134,7 +142,7 @@ const App: React.FC = (props: any) => {
Bus.trigger('storeNameChange', storeName);
User.setUserRole(userRole);
User.setStoreType(storeType);
setCurrentStoreUserInfo(id,storeUserId);
setCurrentStoreUserInfo(id, storeUserId);
ctx.dispatch(setStoreGroupList(storeGroupVOS))
ctx.dispatch(setStoreList(storeVOS));
setStoreUserId(storeUserId)
......
......@@ -6,6 +6,7 @@ import BaseService from "@/domains/basic-domain/baseService";
import User from "@/common/js/user";
import Breadcrumbs from "@/components/Breadcrumbs";
import ImgClipModal from '@/components/ImgClipModal'
import { brandLogo } from '@/domains/brand/constants'
import './CreateCollege.less';
let cutFlag = false;
......@@ -16,7 +17,7 @@ export default class CreateCollege extends React.Component {
super(props);
this.state = {
avatar: 'https://image.xiaomaiketang.com/xm/rJeQaZxtc7.png',
logo: 'https://image.xiaomaiketang.com/xm/fe4NCjr7XF.png',
logo: brandLogo,
name: '',
enterpriseId: User.getEnterpriseId(),
imageFile: null, // 需要被截取的图片
......@@ -111,7 +112,7 @@ export default class CreateCollege extends React.Component {
<div className="college-manage-page">
<div className="college-header">
<div className="box">
<img className="box-image" src="https://image.xiaomaiketang.com/xm/fe4NCjr7XF.png" />
<img className="box-image" src={brandLogo} />
</div>
</div>
<div className="breadcrumb-wrap">
......@@ -134,7 +135,7 @@ export default class CreateCollege extends React.Component {
className="icon iconfont"
onClick={() => {
this.setState({
logo: 'https://image.xiaomaiketang.com/xm/fe4NCjr7XF.png',
logo: brandLogo,
visible: false,
})
}}
......
......@@ -71,9 +71,10 @@ export default class ErrorCollege extends React.Component {
User.removeUserId();
User.removeToken();
User.removeEnterpriseId();
User.clearUserInfo();
const url = `${LIVE_SHARE}store/index?id=${User.getCustomerStoreId()||User.getStoreId()}&userId=${User.getUserId()}&from=work_weixin`;
window.location.href = url;
window.RCHistory.replace('/login');
// User.clearUserInfo();
// const url = `${LIVE_SHARE}store/index?id=${User.getCustomerStoreId()||User.getStoreId()}&userId=${User.getUserId()}&from=work_weixin`;
// window.location.href = url;
});
}
......
/*
* @Author: 吴文洁
* @Date: 2019-09-10 18:26:03
* @LastEditors: yuananting
* @LastEditTime: 2021-07-21 14:03:30
* @LastEditors: Please set LastEditors
* @LastEditTime: 2021-08-11 20:26:53
* @Description:
*/
import React, { useRef, useContext, useEffect, useState } from 'react';
......@@ -19,6 +19,7 @@ import CourseService from '@/domains/course-domain/CourseService';
import qrcode from '@/libs/qrcode/qrcode.js';
import Bus from '@/core/tbus';
import ClickOutside from '../../components/ClickOutside';
import WWOpenDataCom from '@/components/WWOpenDataCom';
import _ from 'underscore';
const baseImg = 'https://image.xiaomaiketang.com/xm/rJeQaZxtc7.png';
......@@ -75,8 +76,8 @@ function Header(props) {
storeUserId: User.getStoreUserId(),
};
BaseService.getStoreUser(param).then((res) => {
const { nickName, phone } = res.result;
setNickName(nickName);
const { weChatAccount, phone } = res.result;
setNickName(weChatAccount);
setPhone(phone);
setAvatar(res.result.avatar);
User.setAvatar(res.result.avatar);
......@@ -134,7 +135,10 @@ function Header(props) {
<div className='user-detail'>
<div className='box'>
<Tooltip title={nickName}>
<div className='name'>{nickName}</div>
<div className='name'>
{/* <span>{nickName}</span> */}
<WWOpenDataCom type="userName" openid={nickName}/>
</div>
</Tooltip>
<span className='phone'>{phone}</span>
</div>
......@@ -201,9 +205,10 @@ function Header(props) {
User.removeUserId();
User.removeToken();
User.removeEnterpriseId();
User.clearUserInfo();
const url = `${LIVE_SHARE}store/index?id=${User.getCustomerStoreId() || User.getStoreId()}&userId=${User.getUserId()}&from=work_weixin`;
window.location.href = url;
window.RCHistory.replace('/login');
// User.clearUserInfo();
// const url = `${LIVE_SHARE}store/index?id=${User.getCustomerStoreId() || User.getStoreId()}&userId=${User.getUserId()}&from=work_weixin`;
// window.location.href = url;
});
}
......@@ -337,7 +342,7 @@ function Header(props) {
<div
className='url-link'
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>
......@@ -355,12 +360,15 @@ function Header(props) {
<span className='text'>分享学院</span>
</span>
</div>
<div className='help'>
<a href={helpCenterUrl} target='_blank' className='help-btn'>
<span className='icon iconfont tool-tip-right'>&#xe8ed;</span>
<span className='text'>帮助中心</span>
</a>
</div>
{
process.env.BRAND == 'xiaomai' && <div className='help'>
<a href={helpCenterUrl} target='_blank' className='help-btn'>
<span className='icon iconfont tool-tip-right'>&#xe8ed;</span>
<span className='text'>帮助中心</span>
</a>
</div>
}
</div>
<Dropdown overlay={userMenu()} arrow>
<div className='user'>
......@@ -374,7 +382,10 @@ function Header(props) {
}}
src={avatar || baseImg}
/>
<span className='name'>{nickName}</span>
<span className='name'>
{/* {nickName} */}
<WWOpenDataCom type="userName" openid={nickName}/>
</span>
</div>
</Dropdown>
</div>
......
......@@ -9,7 +9,7 @@ import BaseService from '@/domains/basic-domain/baseService';
import axios from 'axios';
import storage from '@/common/js/storage';
import _ from 'underscore';
import user from '@/common/js/user';
import {brandLogo,brandBanner} from '@/domains/brand/constants'
const { TabPane } = Tabs;
function Login(props) {
......@@ -156,12 +156,12 @@ function Login(props) {
return (
<div className='login-page'>
<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 className='login-main'>
<div className='left-banner'>
<div className='img-box'>
<img src='https://image.xiaomaiketang.com/xm/CDCcdAdaPs.png' alt='' />
<img src={brandBanner} alt='' />
</div>
</div>
<div className='login-box'>
......
import React , { useContext, useEffect ,useState}from 'react'
import React, { useContext, useEffect, useState } from 'react'
import './Main.less';
import { MainRoutes, RedirectRoutes } from '@/routes';
import { Modal } from 'antd';
import { MainRoutes, RedirectRoutes } from '@/routes';
import routeHook from '@/core/routeHook'
import Bus from '@/core//bus';
function Main(props) {
const { menuType } = props;
console.log("menuType", menuType);
useEffect(() => {
Bus.bind('showRouteChangeModal',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 (
<div
className={menuType ? `right-container has-nav` : `right-container has-nav right-container-vertical`}
id="rightContainer"
>
<MainRoutes/>
<RedirectRoutes/>
<MainRoutes />
<RedirectRoutes />
</div>
)
}
......
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