Commit f1159a1c by chenshu

feat:多学院优化

parent 93f294e8
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
......@@ -25,7 +25,7 @@
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_boiin24pch6.css">
<link rel="stylesheet" href="//at.alicdn.com/t/font_2223403_vs61tfrogho.css">
<!--
Notice the use of %PUBLIC_URL% in the tags above.
......
......@@ -25,7 +25,7 @@
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_boiin24pch6.css">
<link rel="stylesheet" href="//at.alicdn.com/t/font_2223403_vs61tfrogho.css">
<!--
Notice the use of %PUBLIC_URL% in the tags above.
......
......@@ -32,6 +32,7 @@ const App: React.FC = (props: any) => {
useEffect(() => {
getStorePermission();
getStoreAndUserInfo();
if (window.location.hash === "#/") {
window.RCHistory.replace({
......@@ -40,6 +41,19 @@ const App: React.FC = (props: any) => {
}
}, [])
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() {
await (enterpriseId ? getStoreInfo() : getStoreGroupAndStoreList());
}
......
......@@ -60,6 +60,24 @@ 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 {
this.changeCollege(item, bool);
}
})
}
changeCollege(item, bool) {
const data = {
storeId: item.id,
......@@ -173,7 +191,7 @@ export default class CollegeManagePage extends React.Component {
content: '禁用学院,所有学院相关信息不可使用,用户无法继续学习,请谨慎操作!',
icon: <span className="icon iconfont default-confirm-icon">&#xe6f4;</span>,
onOk: () => {
this.changeCollege(item, false);
this.checkCollege(item, false);
},
okText: '停用',
cancelText: '取消',
......
import User from '@/common/js/user';
import React from 'react';
import Header from './Header'
import './ErrorCollege.less';
export default class ErrorCollege extends React.Component {
constructor(props) {
super(props);
this.state = {
menuType: true,
}
}
handleMenuType() {
this.setState({ menuType: !menuType });
}
render() {
const { menuType } = this.state;
return (
<div className="error-college-page">
<Header 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 @@
* @LastEditTime: 2021-05-10 10:34:13
* @Description:
*/
import React, { useContext, useEffect, useState } from "react";
import React, { useRef, useContext, useEffect, useState } from "react";
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 User from "@/common/js/user";
import Service from "@/common/js/service";
import BaseService from "@/domains/basic-domain/baseService";
import { XMContext } from "@/store/context";
import logoImg from "@/common/images/logo.png";
import CourseService from "@/domains/course-domain/CourseService";
import qrcode from "@/libs/qrcode/qrcode.js";
import Bus from '@/core/tbus';
import ClickOutside from '../../components/ClickOutside';
const baseImg = "https://image.xiaomaiketang.com/xm/rJeQaZxtc7.png";
const { confirm } = Modal;
const RadioGroup = Radio.Group;
function Header(props) {
const { menuType, handleMenuType } = props;
const [storeId, setStoreId] = useState(User.getStoreId());
const [storeName, setStoreName] = useState(User.getStoreName())
const [avatar, setAvatar] = useState('');
const [nickName, setNickName] = useState('');
const [phone, setPhone] = useState('');
const [list, setList] = useState([]);
const [openDropdown, setOpenDropdown] = useState(false);
const [instScroll, setInstScroll] = useState(false);
const ctx = useContext(XMContext);
const htmlUrl = `${LIVE_SHARE}store/index?id=${User.getStoreId()}&userId=${User.getUserId()}&from=work_weixin`;
const storeUserId = User.getStoreUserId();
const enterpriseId = User.getEnterpriseId();
const domRef = useRef(null);
const listRef = useRef(list);
useEffect(() => {
htmlUrl && handleConvertShortUrl();
Bus.bind('storeNameChange', (value) => {
setStoreName(value);
});
getStoreList();
}, []);
useEffect(() => {
......@@ -66,6 +77,38 @@ function Header(props) {
});
}
function getStoreList() {
const params = {
enterpriseId,
userId: User.getUserId(),
};
Service.Hades('public/customerHades/getStoreListUser', params).then((res) => {
setList(res.result);
listRef.current = res.result;
});
}
// 动态改变校区选择的阴影
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() {
return (
<div className="user-center-dropdown">
......@@ -191,14 +234,83 @@ function Header(props) {
</span>
)}
<div className="message-help">
{list.length ? (
<ClickOutside
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)
}}
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 className="line"></div>
</div>
)}
<div className="right-box">
<div className="link-to-store">
<div className="link">
<span className="icon iconfont tool-tip-right">&#xe85d;</span>
<div className="text">前往学院</div>
<div className="store-popover">
<div className="pc-url">
<div className="name">网页端学院</div>
......@@ -222,8 +334,6 @@ function Header(props) {
<span className="icon iconfont tool-tip-right">&#xe85e;</span>
<div className="text">分享学院</div>
</div>
</div>
</div>
<Dropdown overlay={userMenu()} arrow>
<div className="user">
......@@ -245,6 +355,7 @@ function Header(props) {
</div>
</div>
</div>
</div>
);
}
export default Header;
......@@ -177,8 +177,94 @@
flex: 1;
-webkit-flex: 1;
justify-content: space-between;
.college-container {
position: relative;
width: 360px;
height: 50px;
display: flex;
align-items: center;
.college {
display: flex;
align-items: center;
margin-left: 36px;
margin-right: 16px;
cursor: pointer;
.select {
cursor: pointer;
}
.college-name {
color: #666;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
max-width: 230px;
}
.icon {
font-size: 14px;
margin-left: 8px;
color: #8c8e93;
&:hover {
color: #555;
}
}
}
.select-college {
position: absolute;
top: 50px;
left: 36px;
background: #fff;
width: 282px;
padding: 14px;
box-shadow: 0 2px 7px 0 rgba(0, 0, 0, 0.06);
max-height: 240px;
border-radius: 2px;
display: none;
padding-right: 0;
&.active {
display: block;
}
h2 {
margin-bottom: 10px;
font-size: 16px;
font-weight: 500;
}
.ant-radio-group {
overflow-y: auto;
width: 100%;
height: 190px;
}
.ant-radio-wrapper {
display: flex;
width: calc(~'100% - 28px');
margin: 8px 0;
.ant-radio {
float: left;
margin: 3px 0;
}
.name {
color: #666;
white-space: pre-wrap;
}
}
.control {
display: flex;
justify-content: flex-end;
button {
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: 500px;
width: 360px;
height: 49px;
display: flex;
position: relative;
......@@ -200,6 +286,11 @@
background-color: #f4f4f4;
margin-right:16px;
}
}
.right-box {
display: flex;
align-items: center;
}
.link-to-store {
display: flex;
height: 49px;
......@@ -284,79 +375,6 @@
margin-left: 16px;
}
}
}
.inst-container {
width: calc(~"100% - 420px");
position: relative;
.inst {
margin-right: 12px;
display: flex;
align-items: center;
border-right: 1px solid #e8e8e8;
padding-right: 24px;
justify-content: flex-end;
.select {
cursor: pointer;
}
.name {
color: #333;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
max-width: 230px;
}
.icon {
font-size: 16px;
margin-left: 8px;
color: #8c8e93;
&:hover {
color: #555;
}
}
}
.select-inst {
position: absolute;
top: 37px;
right: 11px;
background: #fff;
width: 285px;
padding: 14px;
box-shadow: 0 2px 7px 0 rgba(0, 0, 0, 0.06);
max-height: 321px;
border-radius: 2px;
display: none;
&.active {
display: block;
}
h2 {
margin-bottom: 10px;
}
.ant-radio-group {
overflow-y: auto;
max-height: 200px;
}
.ant-radio-wrapper {
display: inline-block;
width: calc(~"100% - 28px");
margin: 8px 0;
.ant-radio {
float: left;
margin: 3px 0;
}
.name {
color: #666;
white-space: pre-wrap;
}
}
.control {
display: flex;
justify-content: flex-end;
button {
margin-left: 8px;
}
}
}
}
.drop-menu {
height: 100%;
display: flex;
......
......@@ -18,6 +18,7 @@ import CreateCollege from '../modules/root/CreateCollege';
import _ from 'underscore';
import { asyncComponent } from 'react-async-component'
import SwitchRoute from '@/modules/root/SwitchRoute';
import ErrorCollege from '@/modules/root/ErrorCollege';
const history = createHashHistory();
window.RCHistory = _.extend({}, history, {
push: (obj: any) => {
......@@ -55,10 +56,11 @@ export const RootRouter = () => {
<Router {...history}>
<Switch>
<Route key="1" exact path="/login" render={() => <Login />} />
<Route key="1" exact path="/switch-route" render={() => <SwitchRoute />} />
<Route key="1" exact path="/college-manage" render={() => <CollegeManagePage />} />
<Route key="1" exact path="/college-manage/create" render={() => <CreateCollege />} />
<Route key="2" path="/" render={() => <AppContext />} />
<Route key="2" exact path="/switch-route" render={() => <SwitchRoute />} />
<Route key="3" exact path="/college-manage" render={() => <CollegeManagePage />} />
<Route key="4" exact path="/college-manage/create" render={() => <CreateCollege />} />
<Route key="6" exact path="/error-college" render={() => <ErrorCollege />} />
<Route key="5" path="/" render={() => <AppContext />} />
</Switch>
</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