Commit 31a23f0c by guomingpang
parents 93f294e8 1cbac6f2
import React, { Component } from 'react'
import PropTypes from 'prop-types'
export default class ClickOutside extends Component {
static propTypes = {
onClickOutside: PropTypes.func.isRequired
}
constructor(props) {
super(props)
this.getContainer = this.getContainer.bind(this)
this.isTouch = false
}
getContainer(ref) {
this.container = ref
}
render() {
const { children, onClickOutside, ...props } = this.props
return <div {...props} ref={this.getContainer}>{children}</div>
}
componentDidMount() {
document.addEventListener('touchend', this.handle, true)
document.addEventListener('click', this.handle, true)
}
componentWillUnmount() {
document.removeEventListener('touchend', this.handle, true)
document.removeEventListener('click', this.handle, true)
}
handle = e => {
if (e.type === 'touchend') this.isTouch = true
if (e.type === 'click' && this.isTouch) return
const { onClickOutside } = this.props
const el = this.container
if (el && !el.contains(e.target)) onClickOutside(e)
}
}
\ No newline at end of file
...@@ -1305,7 +1305,6 @@ input:focus { ...@@ -1305,7 +1305,6 @@ input:focus {
.ant-modal-content { .ant-modal-content {
.ant-modal-body { .ant-modal-body {
min-height: 130px; min-height: 130px;
max-height: 600px;
overflow: auto; overflow: auto;
// padding-top:0px!important; // padding-top:0px!important;
.xm-page-control { .xm-page-control {
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/ user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
--> -->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" /> <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<link rel="stylesheet" href="//at.alicdn.com/t/font_2223403_boiin24pch6.css"> <link rel="stylesheet" href="//at.alicdn.com/t/font_2223403_vs61tfrogho.css">
<!-- <!--
Notice the use of %PUBLIC_URL% in the tags above. Notice the use of %PUBLIC_URL% in the tags above.
......
<!-- <!--
* @Author: 吴文洁 * @Author: 吴文洁
* @Date: 2020-08-24 12:20:57 * @Date: 2020-08-24 12:20:57
* @LastEditors: zhangleyuan * @LastEditors: wufan
* @LastEditTime: 2021-05-10 13:41:52 * @LastEditTime: 2021-05-17 19:53:24
* @Description: * @Description:
* @Copyright: 杭州杰竞科技有限公司 版权所有 * @Copyright: 杭州杰竞科技有限公司 版权所有
--> -->
...@@ -13,10 +13,8 @@ ...@@ -13,10 +13,8 @@
<link rel="icon" href="" /> <link rel="icon" href="" />
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" /> <meta name="theme-color" content="#000000" />
<meta <meta name="description" content="小麦企学院,一站式企业培训数字化服务商,通过“工具+内容”,帮助企业快速从0到1搭建数字化培训体系,并让整个培训过程可视化,降低培训成本,提升培训效率。">
name="description" <meta name="keywords" content="小麦企学院,企业培训,员工培训,企业大学,企业内训,企业外训,培训计划,培训素材,企培,企训,资料云盘,培训课程,培训任务,直播课,视频课,图文课,线下课,知识库,作业,考试,排行榜,培训类别管理,定制培训计划,管理数据,学习数据,企学院,资料共享,培训数字化,数字化培训,培训工具,在线培训,线上培训,培训saas,培训管理,企业微信培训,对客培训,客户培训,直播培训,互联网培训,新员工培训,管理培训,管理者培训,工人培训,制造业培训,餐饮培训,服务业培训,零售培训,门店培训,工厂培训,车间培训,培训补贴,人事培训,财务培训,职场培训,企业学院平台,教育企业学院,教育企业平台,教育平台学院,企业学习,酷学院,小鹅通,企业学院,云学堂,时代光华,云课堂,魔学院,云大学,米知云,授课学堂">
content="Web site created using create-react-app"
/>
<!-- <link rel="apple-touch-icon" href="../src/common/images/logo.png" /> --> <!-- <link rel="apple-touch-icon" href="../src/common/images/logo.png" /> -->
<link rel="shortcut icon" href="https://image.xiaomaiketang.com/xm/c4KiP2epBP.png"> <link rel="shortcut icon" href="https://image.xiaomaiketang.com/xm/c4KiP2epBP.png">
...@@ -25,7 +23,7 @@ ...@@ -25,7 +23,7 @@
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/ user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
--> -->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" /> <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<link rel="stylesheet" href="//at.alicdn.com/t/font_2223403_boiin24pch6.css"> <link rel="stylesheet" href="//at.alicdn.com/t/font_2223403_vs61tfrogho.css">
<!-- <!--
Notice the use of %PUBLIC_URL% in the tags above. Notice the use of %PUBLIC_URL% in the tags above.
......
...@@ -301,7 +301,6 @@ class AddGraphicsCourse extends React.Component { ...@@ -301,7 +301,6 @@ class AddGraphicsCourse extends React.Component {
//上传图片 //上传图片
uploadCoverImage = (imageFile) => { uploadCoverImage = (imageFile) => {
debugger
const { folderName } = imageFile; const { folderName } = imageFile;
const fileName = window.random_string(16) + folderName.slice(folderName.lastIndexOf(".")); const fileName = window.random_string(16) + folderName.slice(folderName.lastIndexOf("."));
const self = this; const self = this;
......
...@@ -40,6 +40,23 @@ const App: React.FC = (props: any) => { ...@@ -40,6 +40,23 @@ const App: React.FC = (props: any) => {
} }
}, []) }, [])
useEffect(() => {
getStorePermission();
}, [window.location.hash])
function getStorePermission() {
const params = {
storeId: User.getStoreId(),
};
Service.Hades('public/customerHades/whetherStopStore', params).then((res) => {
if (res.result) {
window.RCHistory.replace({
pathname: '/error-college',
})
}
});
}
async function getStoreAndUserInfo() { async function getStoreAndUserInfo() {
await (enterpriseId ? getStoreInfo() : getStoreGroupAndStoreList()); await (enterpriseId ? getStoreInfo() : getStoreGroupAndStoreList());
} }
...@@ -106,7 +123,7 @@ const App: React.FC = (props: any) => { ...@@ -106,7 +123,7 @@ const App: React.FC = (props: any) => {
return ( return (
<div id="home"> <div id="home">
<Header handleMenuType={handleMenuType} menuType={menuType} /> <Header id="app" handleMenuType={handleMenuType} menuType={menuType} />
<ConfigProvider locale={zhCN} autoInsertSpaceInButton={false}> <ConfigProvider locale={zhCN} autoInsertSpaceInButton={false}>
<Main menuType={menuType} /> <Main menuType={menuType} />
</ConfigProvider> </ConfigProvider>
......
...@@ -45,6 +45,7 @@ export default class CollegeManagePage extends React.Component { ...@@ -45,6 +45,7 @@ export default class CollegeManagePage extends React.Component {
getStoreList() { getStoreList() {
const { enterpriseId } = this.state; const { enterpriseId } = this.state;
if (!enterpriseId) return null;
const params = { const params = {
enterpriseId, enterpriseId,
userId: User.getUserId(), userId: User.getUserId(),
...@@ -52,7 +53,7 @@ export default class CollegeManagePage extends React.Component { ...@@ -52,7 +53,7 @@ export default class CollegeManagePage extends React.Component {
Service.Hades('public/customerHades/getStoreListUser', params).then((res) => { Service.Hades('public/customerHades/getStoreListUser', params).then((res) => {
const list = res.result; const list = res.result;
if (!User.getStoreId()) { if (!User.getStoreId()) {
const mainStore = _.find(list, item => item.mainStore) || {}; const mainStore = _.find(list, item => item.mainStore) || list[0] || {};
User.setStoreId(mainStore.id); User.setStoreId(mainStore.id);
User.setStoreUserId(mainStore.storeUserId); User.setStoreUserId(mainStore.storeUserId);
} }
...@@ -60,6 +61,34 @@ export default class CollegeManagePage extends React.Component { ...@@ -60,6 +61,34 @@ export default class CollegeManagePage extends React.Component {
}); });
} }
checkCollege(item, bool) {
const data = {
storeId: item.id,
}
Service.Hades('public/hades/whetherStartLiveCourse', data).then((res) => {
if (res.result) {
Modal.warning({
title: '停用失败',
content: '当前学院有正在上课的直播课,请课程结束后再进行操作。',
icon: <span className="icon iconfont default-confirm-icon">&#xe6f4;</span>,
okText: '我知道了',
})
} else {
Modal.confirm({
title: '确定停用吗?',
content: '停用学院,所有学院相关信息不可使用,用户无法继续学习,请谨慎操作!',
icon: <span className="icon iconfont default-confirm-icon">&#xe6f4;</span>,
onOk: () => {
this.changeCollege(item, bool);
},
okText: '停用',
cancelText: '取消',
})
}
})
}
changeCollege(item, bool) { changeCollege(item, bool) {
const data = { const data = {
storeId: item.id, storeId: item.id,
...@@ -168,16 +197,7 @@ export default class CollegeManagePage extends React.Component { ...@@ -168,16 +197,7 @@ export default class CollegeManagePage extends React.Component {
if (item.state !== 'VALID') return null; if (item.state !== 'VALID') return null;
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
Modal.confirm({ this.checkCollege(item, false);
title: '确定停用吗?',
content: '禁用学院,所有学院相关信息不可使用,用户无法继续学习,请谨慎操作!',
icon: <span className="icon iconfont default-confirm-icon">&#xe6f4;</span>,
onOk: () => {
this.changeCollege(item, false);
},
okText: '停用',
cancelText: '取消',
})
}} }}
>{item.state === 'VALID' ? '停用' : '已停用'}</span> >{item.state === 'VALID' ? '停用' : '已停用'}</span>
} }
......
import User from '@/common/js/user';
import React from 'react';
import Header from './Header'
import Service from "@/common/js/service";
import './ErrorCollege.less';
export default class ErrorCollege extends React.Component {
constructor(props) {
super(props);
this.state = {
menuType: true,
}
}
componentDidMount() {
this.getStorePermission();
}
getStorePermission() {
const params = {
storeId: User.getStoreId(),
};
Service.Hades('public/customerHades/whetherStopStore', params).then((res) => {
if (!res.result) {
window.RCHistory.replace({
pathname: '/home',
})
}
});
}
handleMenuType() {
this.setState({ menuType: !menuType });
}
render() {
const { menuType } = this.state;
return (
<div className="error-college-page">
<Header id="error" handleMenuType={this.handleMenuType} menuType={menuType} />
<div className="error-college-box">
<img src="https://image.xiaomaiketang.com/xm/MQRaYkbr6J.png" className="error-college-image" />
<span className="error-college-tip">{User.getStoreName()}已停用</span>
</div>
</div>
)
}
}
\ No newline at end of file
.error-college-page {
position: relative;
width: 100vw;
height: 100vh;
.error-college-box {
position: absolute;
top: 50px;
left: 0;
right: 0;
bottom: 0;
.error-college-image {
position: absolute;
top: 246px;
left: 50%;
transform: translateX(-50%);
width: 246px;
height: 132px;
display: block;
}
.error-college-tip {
position: absolute;
top: 404px;
left: 50%;
transform: translateX(-50%);
color: #8C8E93;
font-size: 13px;
}
}
}
\ No newline at end of file
...@@ -5,37 +5,48 @@ ...@@ -5,37 +5,48 @@
* @LastEditTime: 2021-05-10 10:34:13 * @LastEditTime: 2021-05-10 10:34:13
* @Description: * @Description:
*/ */
import React, { useContext, useEffect, useState } from "react"; import React, { useRef, useContext, useEffect, useState } from "react";
import "./Header.less"; import "./Header.less";
import { Menu, Dropdown, Modal, Tooltip, message } from "antd"; import { Radio, Button, Dropdown, Modal, Tooltip, message } from "antd";
import { LIVE_SHARE } from "@/domains/course-domain/constants"; import { LIVE_SHARE } from "@/domains/course-domain/constants";
import User from "@/common/js/user"; import User from "@/common/js/user";
import Service from "@/common/js/service";
import BaseService from "@/domains/basic-domain/baseService"; import BaseService from "@/domains/basic-domain/baseService";
import { XMContext } from "@/store/context"; import { XMContext } from "@/store/context";
import logoImg from "@/common/images/logo.png"; import logoImg from "@/common/images/logo.png";
import CourseService from "@/domains/course-domain/CourseService"; import CourseService from "@/domains/course-domain/CourseService";
import qrcode from "@/libs/qrcode/qrcode.js"; import qrcode from "@/libs/qrcode/qrcode.js";
import Bus from '@/core/tbus'; import Bus from '@/core/tbus';
import ClickOutside from '../../components/ClickOutside';
const baseImg = "https://image.xiaomaiketang.com/xm/rJeQaZxtc7.png"; const baseImg = "https://image.xiaomaiketang.com/xm/rJeQaZxtc7.png";
const { confirm } = Modal; const { confirm } = Modal;
const RadioGroup = Radio.Group;
function Header(props) { function Header(props) {
const { menuType, handleMenuType } = props; const { menuType, handleMenuType } = props;
const [storeId, setStoreId] = useState(User.getStoreId());
const [storeName, setStoreName] = useState(User.getStoreName()) const [storeName, setStoreName] = useState(User.getStoreName())
const [avatar, setAvatar] = useState(''); const [avatar, setAvatar] = useState('');
const [nickName, setNickName] = useState(''); const [nickName, setNickName] = useState('');
const [phone, setPhone] = useState(''); const [phone, setPhone] = useState('');
const [list, setList] = useState([]);
const [openDropdown, setOpenDropdown] = useState(false);
const [instScroll, setInstScroll] = useState(false);
const ctx = useContext(XMContext); const ctx = useContext(XMContext);
const htmlUrl = `${LIVE_SHARE}store/index?id=${User.getStoreId()}&userId=${User.getUserId()}&from=work_weixin`; const htmlUrl = `${LIVE_SHARE}store/index?id=${User.getStoreId()}&userId=${User.getUserId()}&from=work_weixin`;
const storeUserId = User.getStoreUserId(); const storeUserId = User.getStoreUserId();
const enterpriseId = User.getEnterpriseId(); const enterpriseId = User.getEnterpriseId();
const domRef = useRef(null);
const listRef = useRef(list);
useEffect(() => { useEffect(() => {
htmlUrl && handleConvertShortUrl(); htmlUrl && handleConvertShortUrl();
Bus.bind('storeNameChange', (value) => { Bus.bind('storeNameChange', (value) => {
setStoreName(value); setStoreName(value);
}); });
getStoreList();
}, []); }, []);
useEffect(() => { useEffect(() => {
...@@ -66,6 +77,40 @@ function Header(props) { ...@@ -66,6 +77,40 @@ function Header(props) {
}); });
} }
function getStoreList() {
if (!enterpriseId) return null;
const params = {
enterpriseId,
userId: User.getUserId(),
};
Service.Hades('public/customerHades/getStoreListUser', params).then((res) => {
const newList = _.filter(res.result, item => item.state === 'VALID');
setList(newList);
listRef.current = newList;
});
}
// 动态改变校区选择的阴影
function addShadow() {
domRef.current = document.querySelector('#college-radio-group');
if (listRef.current.length > 4) {
setInstScroll(true);
} else {
setInstScroll(false);
}
// 滚动到底部阴影就消失
domRef.current.addEventListener('scroll', scrollEventListener);
}
function scrollEventListener() {
if (domRef.current.scrollHeight === 190 + domRef.current.scrollTop) {
setInstScroll(false);
} else {
setInstScroll(true);
}
};
function userMenu() { function userMenu() {
return ( return (
<div className="user-center-dropdown"> <div className="user-center-dropdown">
...@@ -145,6 +190,7 @@ function Header(props) { ...@@ -145,6 +190,7 @@ function Header(props) {
User.clearUserInfo(); User.clearUserInfo();
const url = `${LIVE_SHARE}store/index?id=${User.getCustomerStoreId()||User.getStoreId()}&userId=${User.getUserId()}&from=work_weixin`; const url = `${LIVE_SHARE}store/index?id=${User.getCustomerStoreId()||User.getStoreId()}&userId=${User.getUserId()}&from=work_weixin`;
window.location.href = url; window.location.href = url;
}); });
} }
...@@ -163,11 +209,11 @@ function Header(props) { ...@@ -163,11 +209,11 @@ function Header(props) {
}); });
} }
// 复制分享链接 // 复制分享链接
function handleCopy() { function handleCopy() {
window.copyText(htmlUrl); window.copyText(htmlUrl);
message.success('已复制学院地址,快去分享吧~'); message.success('已复制学院地址,快去分享吧~');
} }
return ( return (
<div id="top-container" className="top-container"> <div id="top-container" className="top-container">
...@@ -191,14 +237,86 @@ function Header(props) { ...@@ -191,14 +237,86 @@ function Header(props) {
</span> </span>
)} )}
<div className="message-help"> <div className="message-help">
<div className="store-related"> {list.length ? (
<div className="store-name">{storeName}</div> <ClickOutside
<div className="line"></div> onClickOutside={() => {
if (openDropdown) {
setOpenDropdown(false);
}
}}
className="college-container"
>
<div>
<div className="college" onClick={() => setOpenDropdown(false)}>
<span
className="college-name"
onClick={(e) => {
e.stopPropagation();
setOpenDropdown(!openDropdown);
addShadow();
}}
>{storeName}</span>
{list.length > 1 && <span
className={`icon iconfont ${list.length > 1 ? 'select' : ''}`}
onClick={(e) => {
e.stopPropagation();
setOpenDropdown(!openDropdown);
addShadow();
}}
>&#xe651;</span>}
</div>
<div className={`select-college ${openDropdown ? 'active' : ''}`}>
<h2>切换学院</h2>
<RadioGroup
onChange={(e) => {
setStoreId(e.target.value)
User.setStoreId(e.target.value);
window.RCHistory.push('/home');
window.location.reload();
}}
value={storeId}
id="college-radio-group"
>
{_.map(list, (item) => (
<Radio value={item.id} key={item.id}>
<span className="name">{item.storeName}</span>
</Radio>
))}
</RadioGroup>
{instScroll && <div className="scroll-shadow"></div>}
{/* <div className="control">
<Button
size="small"
onClick={() => {
setOpenDropdown(false);
}}
>
取消
</Button>
<Button
size="small"
type="primary"
onClick={() => {
User.setStoreId(storeId);
window.location.reload();
}}
>
确定
</Button>
</div> */}
</div>
</div>
</ClickOutside>
) : (
<div className="store-related">
<div className="store-name">{storeName}</div>
</div>
)}
<div className="right-box">
<div className="link-to-store"> <div className="link-to-store">
<div className="link"> <div className="link">
<span className="icon iconfont tool-tip-right">&#xe85d;</span> <span className="icon iconfont tool-tip-right">&#xe85d;</span>
<div className="text">前往学院</div> <div className="text">前往学院</div>
<div className="store-popover"> <div className="store-popover">
<div className="pc-url"> <div className="pc-url">
<div className="name">网页端学院</div> <div className="name">网页端学院</div>
...@@ -222,26 +340,25 @@ function Header(props) { ...@@ -222,26 +340,25 @@ function Header(props) {
<span className="icon iconfont tool-tip-right">&#xe85e;</span> <span className="icon iconfont tool-tip-right">&#xe85e;</span>
<div className="text">分享学院</div> <div className="text">分享学院</div>
</div> </div>
</div> </div>
<Dropdown overlay={userMenu()} arrow>
<div className="user">
<img
style={{
width: 32 + "px",
height: 32 + "px",
borderRadius: "50%",
overflow: "hidden",
flexShrink: 0,
}}
src={avatar || baseImg}
/>
<span className="name">
{nickName}
</span>
</div>
</Dropdown>
</div> </div>
<Dropdown overlay={userMenu()} arrow>
<div className="user">
<img
style={{
width: 32 + "px",
height: 32 + "px",
borderRadius: "50%",
overflow: "hidden",
flexShrink: 0,
}}
src={avatar || baseImg}
/>
<span className="name">
{nickName}
</span>
</div>
</Dropdown>
</div> </div>
</div> </div>
</div> </div>
......
...@@ -177,136 +177,30 @@ ...@@ -177,136 +177,30 @@
flex: 1; flex: 1;
-webkit-flex: 1; -webkit-flex: 1;
justify-content: space-between; justify-content: space-between;
.store-related { margin-left: 54px;
width: 500px; .college-container {
height: 49px;
display: flex;
position: relative; position: relative;
width: 360px;
height: 50px;
display: flex;
align-items: center; align-items: center;
.store-name { .college {
font-size: 14px;
color: #666;
line-height: 49px;
margin-left: 36px;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
max-width: 230px;
margin-right: 16px;
}
.line {
width: 1px;
height: 16px;
background-color: #f4f4f4;
margin-right:16px;
}
.link-to-store {
display: flex;
height: 49px;
line-height: 49px;
.text {
font-size: 14px;
color: #666;
line-height: 49px;
margin-left: 7px;
}
.iconfont {
color: #8c8e93;
&:hover {
color: #555;
}
}
.link {
display: flex;
cursor: pointer;
position: relative;
.store-popover {
display: none;
}
&:hover {
.store-popover {
position: absolute;
display: flex;
width: 216px;
height: 260px;
top: 49px;
left: 0;
background-color: #fff;
flex-wrap: wrap;
box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 0.1);
z-index: 10;
.pc-url {
display: flex;
justify-content: space-between;
width: 100%;
height: 56px;
padding: 16px;
border-bottom: 1px solid #e8e8e8;
.name {
width: 70px;
font-size: 14px;
color: #333333;
line-height: 20px;
}
.url-link {
color: #5289fa;
font-size: 14px;
line-height: 20px;
}
}
.h5-url {
width: 100%;
.name,
.tip {
width: 70px;
font-size: 14px;
color: #333333;
line-height: 52px;
margin: 0 auto;
}
#h5-qrcode {
width: 110px;
height: 110px;
margin: 0 auto;
}
.tip {
line-height: 41px;
width: 130px;
}
}
}
}
}
.share {
cursor: pointer;
display: flex;
margin-left: 16px;
}
}
}
.inst-container {
width: calc(~"100% - 420px");
position: relative;
.inst {
margin-right: 12px;
display: flex; display: flex;
align-items: center; align-items: center;
border-right: 1px solid #e8e8e8; margin-right: 16px;
padding-right: 24px; cursor: pointer;
justify-content: flex-end;
.select { .select {
cursor: pointer; cursor: pointer;
} }
.name { .college-name {
color: #333; color: #666;
white-space: nowrap; white-space: nowrap;
text-overflow: ellipsis; text-overflow: ellipsis;
overflow: hidden; overflow: hidden;
max-width: 230px; max-width: 280px;
} }
.icon { .icon {
font-size: 16px; font-size: 14px;
margin-left: 8px; margin-left: 8px;
color: #8c8e93; color: #8c8e93;
&:hover { &:hover {
...@@ -314,30 +208,35 @@ ...@@ -314,30 +208,35 @@
} }
} }
} }
.select-inst { .select-college {
position: absolute; position: absolute;
top: 37px; top: 50px;
right: 11px; left: 0;
background: #fff; background: #fff;
width: 285px; width: 282px;
padding: 14px; padding: 14px;
box-shadow: 0 2px 7px 0 rgba(0, 0, 0, 0.06); box-shadow: 0 2px 7px 0 rgba(0, 0, 0, 0.06);
max-height: 321px; max-height: 240px;
border-radius: 2px; border-radius: 2px;
display: none; display: none;
padding-right: 0;
z-index: 10;
&.active { &.active {
display: block; display: block;
} }
h2 { h2 {
margin-bottom: 10px; margin-bottom: 10px;
font-size: 16px;
font-weight: 500;
} }
.ant-radio-group { .ant-radio-group {
overflow-y: auto; overflow-y: auto;
max-height: 200px; width: 100%;
max-height: 190px;
} }
.ant-radio-wrapper { .ant-radio-wrapper {
display: inline-block; display: flex;
width: calc(~"100% - 28px"); width: calc(~'100% - 8px');
margin: 8px 0; margin: 8px 0;
.ant-radio { .ant-radio {
float: left; float: left;
...@@ -355,6 +254,126 @@ ...@@ -355,6 +254,126 @@
margin-left: 8px; margin-left: 8px;
} }
} }
.scroll-shadow {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 40px;
background: linear-gradient(rgba(255, 255, 255, 0), rgba(255, 255, 255, 1));
}
}
}
.store-related {
width: 360px;
height: 49px;
display: flex;
position: relative;
align-items: center;
.store-name {
font-size: 14px;
color: #666;
line-height: 49px;
margin-left: 36px;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
max-width: 230px;
margin-right: 16px;
}
.line {
width: 1px;
height: 16px;
background-color: #f4f4f4;
margin-right:16px;
}
}
.right-box {
display: flex;
align-items: center;
}
.link-to-store {
display: flex;
height: 49px;
line-height: 49px;
.text {
font-size: 14px;
color: #666;
line-height: 49px;
margin-left: 7px;
}
.iconfont {
color: #8c8e93;
&:hover {
color: #555;
}
}
.link {
display: flex;
cursor: pointer;
position: relative;
.store-popover {
display: none;
}
&:hover {
.store-popover {
position: absolute;
display: flex;
width: 216px;
height: 260px;
top: 49px;
left: 0;
background-color: #fff;
flex-wrap: wrap;
box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 0.1);
z-index: 10;
.pc-url {
display: flex;
justify-content: space-between;
width: 100%;
height: 56px;
padding: 16px;
border-bottom: 1px solid #e8e8e8;
.name {
width: 70px;
font-size: 14px;
color: #333333;
line-height: 20px;
}
.url-link {
color: #5289fa;
font-size: 14px;
line-height: 20px;
}
}
.h5-url {
width: 100%;
.name,
.tip {
width: 70px;
font-size: 14px;
color: #333333;
line-height: 52px;
margin: 0 auto;
}
#h5-qrcode {
width: 110px;
height: 110px;
margin: 0 auto;
}
.tip {
line-height: 41px;
width: 130px;
}
}
}
}
}
.share {
cursor: pointer;
display: flex;
margin-left: 16px;
} }
} }
.drop-menu { .drop-menu {
......
...@@ -12,11 +12,12 @@ ...@@ -12,11 +12,12 @@
margin-top: 5px !important; margin-top: 5px !important;
} }
.radio-tip { .radio-tip {
padding-left: 24px;
font-size: 14px; font-size: 14px;
font-weight: 400; font-weight: 400;
color: #999; color: #999;
line-height: 20px; line-height: 20px;
white-space: nowrap;
margin: 6px 0 16px;
} }
.avatar-box { .avatar-box {
text-align: center; text-align: center;
......
...@@ -83,8 +83,8 @@ function AddEmployeeModal(props: AddEmployeeModalProps) { ...@@ -83,8 +83,8 @@ function AddEmployeeModal(props: AddEmployeeModalProps) {
}, [props.choosedItem.nickName]); }, [props.choosedItem.nickName]);
const layout = { const layout = {
labelCol: { span: 5 }, labelCol: { span: 6 },
wrapperCol: { span: 12 }, wrapperCol: { span: 18 },
}; };
function handleChangeRole(value: string) { function handleChangeRole(value: string) {
...@@ -210,8 +210,8 @@ function AddEmployeeModal(props: AddEmployeeModalProps) { ...@@ -210,8 +210,8 @@ function AddEmployeeModal(props: AddEmployeeModalProps) {
maskClosable={false} maskClosable={false}
closeIcon={<span className="icon iconfont modal-close-icon">&#xe6ef;</span>} closeIcon={<span className="icon iconfont modal-close-icon">&#xe6ef;</span>}
> >
<Row> <Row style={{ height: 271 }}>
<Col span={16}> <Col span={18}>
<Form <Form
{...layout} {...layout}
form={form} form={form}
...@@ -223,9 +223,8 @@ function AddEmployeeModal(props: AddEmployeeModalProps) { ...@@ -223,9 +223,8 @@ function AddEmployeeModal(props: AddEmployeeModalProps) {
name="nickName" name="nickName"
rules={[{ required: true }]} rules={[{ required: true }]}
validateStatus={nameStatus} validateStatus={nameStatus}
help={nameErrorMsg} help={nameErrorMsg || undefined}
style={{marginBottom:'-2px !important'}} style={{ marginBottom: 0 }}
className="mt-4"
> >
<Input <Input
style={{ width: 200 }} style={{ width: 200 }}
...@@ -239,8 +238,6 @@ function AddEmployeeModal(props: AddEmployeeModalProps) { ...@@ -239,8 +238,6 @@ function AddEmployeeModal(props: AddEmployeeModalProps) {
<Form.Item <Form.Item
label="企业微信账号" label="企业微信账号"
name="weChatAccount" name="weChatAccount"
style={{marginBottom:'-2px !important'}}
className="mt-10"
> >
<Tooltip title={props.choosedItem.weChatAccount}> <Tooltip title={props.choosedItem.weChatAccount}>
<div style={{ <div style={{
...@@ -257,8 +254,6 @@ function AddEmployeeModal(props: AddEmployeeModalProps) { ...@@ -257,8 +254,6 @@ function AddEmployeeModal(props: AddEmployeeModalProps) {
rules={[{ required: true }]} rules={[{ required: true }]}
validateStatus={phoneStatus} validateStatus={phoneStatus}
help={phoneErrorMessage} help={phoneErrorMessage}
style={{marginBottom:'-2px !important'}}
className="mt-10"
> >
<Input <Input
style={{ width: 200 }} style={{ width: 200 }}
...@@ -290,12 +285,6 @@ function AddEmployeeModal(props: AddEmployeeModalProps) { ...@@ -290,12 +285,6 @@ function AddEmployeeModal(props: AddEmployeeModalProps) {
}} }}
className="mt5" className="mt5"
> >
<Radio value={"CloudOperator"} className="mt-4">
<span style={{ color: "#333" }}>运营师</span>
<p className="radio-tip">
仅可查看/转发培训计划内容,并查看其负责的用户学习进度
</p>
</Radio>
<Radio value={"CloudLecturer"} className="mt-4"> <Radio value={"CloudLecturer"} className="mt-4">
<span style={{ color: "#333" }}>普通讲师</span> <span style={{ color: "#333" }}>普通讲师</span>
<p className="radio-tip"> <p className="radio-tip">
...@@ -306,12 +295,18 @@ function AddEmployeeModal(props: AddEmployeeModalProps) { ...@@ -306,12 +295,18 @@ function AddEmployeeModal(props: AddEmployeeModalProps) {
<span style={{ color: "#333" }}>管理员</span> <span style={{ color: "#333" }}>管理员</span>
<p className="radio-tip">可执行学院中所有的操作</p> <p className="radio-tip">可执行学院中所有的操作</p>
</Radio> </Radio>
<Radio value={"CloudOperator"} className="mt-4">
<span style={{ color: "#333" }}>运营师</span>
<p className="radio-tip">
仅可查看/转发培训计划内容,并查看其负责的用户学习进度
</p>
</Radio>
</RadioGroup> </RadioGroup>
</Form.Item> </Form.Item>
</Form> </Form>
</Col> </Col>
<Col span={8}> <Col span={6}>
<div className="avatar-box"> <div className="avatar-box">
<div className="avatar-text">头像</div> <div className="avatar-text">头像</div>
<div className="avatart-img"> <div className="avatart-img">
...@@ -319,7 +314,7 @@ function AddEmployeeModal(props: AddEmployeeModalProps) { ...@@ -319,7 +314,7 @@ function AddEmployeeModal(props: AddEmployeeModalProps) {
</div> </div>
<div className="upload-avatar"> <div className="upload-avatar">
<Button id="click_upload_btn" onClick={_onUpload}> <Button id="click_upload_btn" onClick={_onUpload}>
点击上传 上传头像
</Button> </Button>
<input <input
type="file" type="file"
......
...@@ -54,7 +54,7 @@ function AddExam(props: any) { ...@@ -54,7 +54,7 @@ function AddExam(props: any) {
}, [paperInfo.paperId]) }, [paperInfo.paperId])
useEffect(() => { useEffect(() => {
setPassScore(parseInt((paperInfo.totalScore || 0) * (passRate || 0) as any / 100 + '')) setPassScore(Math.round((paperInfo.totalScore || 0) * (passRate || 0) as any / 100))
setExamTotal(paperInfo.singleChoiceCnt + paperInfo.multiChoiceCnt + paperInfo.judgeCnt + paperInfo.gapFillingCnt + paperInfo.indefiniteChoiceCnt || 0) setExamTotal(paperInfo.singleChoiceCnt + paperInfo.multiChoiceCnt + paperInfo.judgeCnt + paperInfo.gapFillingCnt + paperInfo.indefiniteChoiceCnt || 0)
}, [paperInfo.paperId, passRate]) }, [paperInfo.paperId, passRate])
...@@ -243,7 +243,7 @@ function AddExam(props: any) { ...@@ -243,7 +243,7 @@ function AddExam(props: any) {
help={check && !examName && '请选择课程'} help={check && !examName && '请选择课程'}
required> required>
<Input placeholder='请输入试卷名称(40字以内)' maxLength={40} value={examName} onChange={(e) => { <Input placeholder='请输入考试名称(40字以内)' maxLength={40} value={examName} onChange={(e) => {
setExamName(e.target.value) setExamName(e.target.value)
}} style={{ width: 320 }} /> }} style={{ width: 320 }} />
</Form.Item> </Form.Item>
......
...@@ -16,6 +16,7 @@ function SelectPaperModal(props: any) { ...@@ -16,6 +16,7 @@ function SelectPaperModal(props: any) {
}, [item]) }, [item])
return <Modal return <Modal
maskClosable={false}
width={900} width={900}
title="选择试卷" title="选择试卷"
visible={true} visible={true}
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: yuananting * @Author: yuananting
* @Date: 2021-03-29 10:52:26 * @Date: 2021-03-29 10:52:26
* @LastEditors: yuananting * @LastEditors: yuananting
* @LastEditTime: 2021-04-07 15:23:06 * @LastEditTime: 2021-05-08 16:11:27
* @Description: 助学工具-试卷-新建选择题目弹窗 * @Description: 助学工具-试卷-新建选择题目弹窗
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/ */
...@@ -35,6 +35,7 @@ class SelectQuestionModal extends Component { ...@@ -35,6 +35,7 @@ class SelectQuestionModal extends Component {
return ( return (
<Modal <Modal
className="select-question-modal" className="select-question-modal"
maskClosable={false}
destroyOnClose={true} destroyOnClose={true}
title="选择题目" title="选择题目"
visible={true} visible={true}
......
/* /*
* @Author: yuananting * @Author: yuananting
* @Date: 2021-02-25 13:46:35 * @Date: 2021-02-25 13:46:35
* @LastEditors: zhangleyuan * @LastEditors: yuananting
* @LastEditTime: 2021-05-10 10:16:53 * @LastEditTime: 2021-05-10 20:33:16
* @Description: 助学工具-题库-新建/编辑题目 * @Description: 助学工具-题库-新建/编辑题目
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/ */
...@@ -164,6 +164,8 @@ class OperateQuestion extends Component { ...@@ -164,6 +164,8 @@ class OperateQuestion extends Component {
window.RCHistory.push({ window.RCHistory.push({
pathname: `/question-manage-index?categoryId=${getParameterByName("categoryId")}`, pathname: `/question-manage-index?categoryId=${getParameterByName("categoryId")}`,
}); });
Bus.trigger("queryCategoryTree", "remain");
Bus.trigger("queryQuestionPageList", getParameterByName("categoryId"));
}, },
}); });
}; };
...@@ -334,7 +336,7 @@ class OperateQuestion extends Component { ...@@ -334,7 +336,7 @@ class OperateQuestion extends Component {
key="SINGLE_CHOICE" key="SINGLE_CHOICE"
> >
<OperateQuestionTab <OperateQuestionTab
questionTypeKey={activeKey} questionTypeKey={"SINGLE_CHOICE"}
onRef={(ref) => { onRef={(ref) => {
this.singleChoiceRef = ref; this.singleChoiceRef = ref;
}} }}
...@@ -363,7 +365,7 @@ class OperateQuestion extends Component { ...@@ -363,7 +365,7 @@ class OperateQuestion extends Component {
key="MULTI_CHOICE" key="MULTI_CHOICE"
> >
<OperateQuestionTab <OperateQuestionTab
questionTypeKey={activeKey} questionTypeKey={"MULTI_CHOICE"}
onRef={(ref) => { onRef={(ref) => {
this.multiChoiceRef = ref; this.multiChoiceRef = ref;
}} }}
...@@ -391,7 +393,7 @@ class OperateQuestion extends Component { ...@@ -391,7 +393,7 @@ class OperateQuestion extends Component {
key="JUDGE" key="JUDGE"
> >
<OperateQuestionTab <OperateQuestionTab
questionTypeKey={activeKey} questionTypeKey={"JUDGE"}
onRef={(ref) => { onRef={(ref) => {
this.judgeRef = ref; this.judgeRef = ref;
}} }}
...@@ -419,7 +421,7 @@ class OperateQuestion extends Component { ...@@ -419,7 +421,7 @@ class OperateQuestion extends Component {
key="GAP_FILLING" key="GAP_FILLING"
> >
<OperateQuestionTab <OperateQuestionTab
questionTypeKey={activeKey} questionTypeKey={"GAP_FILLING"}
onRef={(ref) => { onRef={(ref) => {
this.gapRef = ref; this.gapRef = ref;
}} }}
...@@ -457,7 +459,7 @@ class OperateQuestion extends Component { ...@@ -457,7 +459,7 @@ class OperateQuestion extends Component {
key="INDEFINITE_CHOICE" key="INDEFINITE_CHOICE"
> >
<OperateQuestionTab <OperateQuestionTab
questionTypeKey={activeKey} questionTypeKey={"INDEFINITE_CHOICE"}
onRef={(ref) => { onRef={(ref) => {
this.indefiniteRef = ref; this.indefiniteRef = ref;
}} }}
......
...@@ -634,6 +634,9 @@ class OperateQuestionTab extends Component { ...@@ -634,6 +634,9 @@ class OperateQuestionTab extends Component {
this.state.stemContent, this.state.stemContent,
(contentItem) => contentItem.type === "RICH_TEXT" (contentItem) => contentItem.type === "RICH_TEXT"
); );
if(stemContent.textLength > 1000) {
validateError++;
}
let stem = stemContent.content.replace(/<[^>]+>/g, ""); let stem = stemContent.content.replace(/<[^>]+>/g, "");
stem = stem.replace(/\&nbsp\;/gi, ""); stem = stem.replace(/\&nbsp\;/gi, "");
stem = stem.replace(/\s+/g, ""); stem = stem.replace(/\s+/g, "");
...@@ -691,7 +694,9 @@ class OperateQuestionTab extends Component { ...@@ -691,7 +694,9 @@ class OperateQuestionTab extends Component {
optionUnChecked = item.isCorrectAnswer optionUnChecked = item.isCorrectAnswer
? optionUnChecked ? optionUnChecked
: optionUnChecked + 1; : optionUnChecked + 1;
if(optionContent[0].textLength > 1000) {
validateError++;
}
let optionInput = optionContent[0].content.replace(/<[^>]+>/g, ""); let optionInput = optionContent[0].content.replace(/<[^>]+>/g, "");
optionInput = optionInput.replace(/\&nbsp\;/gi, ""); optionInput = optionInput.replace(/\&nbsp\;/gi, "");
optionInput = optionInput.replace(/\s+/g, ""); optionInput = optionInput.replace(/\s+/g, "");
......
...@@ -126,18 +126,24 @@ class QuestionEditor extends Component { ...@@ -126,18 +126,24 @@ class QuestionEditor extends Component {
// 自定义处理粘贴的文本内容 // 自定义处理粘贴的文本内容
editorRoot.config.pasteTextHandle = function (content) { editorRoot.config.pasteTextHandle = function (content) {
if (content == "" && !content) return ""; if (content == "" && !content) return "";
var str = content; var str1 = content; // 所有特殊字符
str = str.replace(/<xml>[\s\S]*?<\/xml>/gi, ""); str1 = str1.replace(/<xml>[\s\S]*?<\/xml>/gi, "");
str = str.replace(/<style>[\s\S]*?<\/style>/gi, ""); str1 = str1.replace(/<style>[\s\S]*?<\/style>/gi, "");
str = str.replace(/<\/?[^>]*>/g, ""); str1 = str1.replace(/<\/?[^>]*>/g, "");
str = str.replace(/[ | ]*\n/g, "\n"); str1 = str1.replace(/[ | ]*\n/g, "\n");
str = str.replace(/\&nbsp\;/gi, " "); str1 = str1.replace(/\&nbsp\;/gi, " ");
str = str.replace(/[\r\n]/g, ""); str1 = str1.replace(/[\r\n]/g, "");
if (str.length > 1000) { var str2 = content; // 保留空格和换行的其他字符
str = str.substring(0, 1000); str2 = str2.replace(/<xml>[\s\S]*?<\/xml>/gi, "");
str2 = str2.replace(/<style>[\s\S]*?<\/style>/gi, "");
str2 = str2.replace(/<(?!br).*?>/g, "");
if (editorRoot.txt.text().length + str1.length > 1000) {
content = str2.substring(0, 1000);
message.error("内容过长,不能超过1000字"); message.error("内容过长,不能超过1000字");
} else {
content = str2;
} }
return str; return content;
}; };
let prevList = []; let prevList = [];
......
...@@ -41,7 +41,7 @@ ...@@ -41,7 +41,7 @@
.editor-box_content { .editor-box_content {
width: calc(100% - 80px); width: calc(100% - 80px);
p { p {
display: inline-block; display: inline;
} }
} }
.editor-limit { .editor-limit {
...@@ -60,7 +60,7 @@ ...@@ -60,7 +60,7 @@
max-height: 110px; max-height: 110px;
overflow: auto; overflow: auto;
p { p {
display: inline-block; display: inline;
overflow-y: scroll; overflow-y: scroll;
} }
} }
......
...@@ -18,6 +18,7 @@ import CreateCollege from '../modules/root/CreateCollege'; ...@@ -18,6 +18,7 @@ import CreateCollege from '../modules/root/CreateCollege';
import _ from 'underscore'; import _ from 'underscore';
import { asyncComponent } from 'react-async-component' import { asyncComponent } from 'react-async-component'
import SwitchRoute from '@/modules/root/SwitchRoute'; import SwitchRoute from '@/modules/root/SwitchRoute';
import ErrorCollege from '@/modules/root/ErrorCollege';
const history = createHashHistory(); const history = createHashHistory();
window.RCHistory = _.extend({}, history, { window.RCHistory = _.extend({}, history, {
push: (obj: any) => { push: (obj: any) => {
...@@ -55,10 +56,11 @@ export const RootRouter = () => { ...@@ -55,10 +56,11 @@ export const RootRouter = () => {
<Router {...history}> <Router {...history}>
<Switch> <Switch>
<Route key="1" exact path="/login" render={() => <Login />} /> <Route key="1" exact path="/login" render={() => <Login />} />
<Route key="1" exact path="/switch-route" render={() => <SwitchRoute />} /> <Route key="2" exact path="/switch-route" render={() => <SwitchRoute />} />
<Route key="1" exact path="/college-manage" render={() => <CollegeManagePage />} /> <Route key="3" exact path="/college-manage" render={() => <CollegeManagePage />} />
<Route key="1" exact path="/college-manage/create" render={() => <CreateCollege />} /> <Route key="4" exact path="/college-manage/create" render={() => <CreateCollege />} />
<Route key="2" path="/" render={() => <AppContext />} /> <Route key="6" exact path="/error-college" render={() => <ErrorCollege />} />
<Route key="5" path="/" render={() => <AppContext />} />
</Switch> </Switch>
</Router> </Router>
) )
......
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