Commit cca0d6c9 by guomingpang
parents 64f4b1f6 4bb97c9a
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
"@typescript-eslint/eslint-plugin": "^2.10.0", "@typescript-eslint/eslint-plugin": "^2.10.0",
"@typescript-eslint/parser": "^2.10.0", "@typescript-eslint/parser": "^2.10.0",
"ali-oss": "^6.12.0", "ali-oss": "^6.12.0",
"antd": "^4.9.4", "antd": "^4.16.3",
"array-move": "^3.0.1", "array-move": "^3.0.1",
"axios": "^0.20.0", "axios": "^0.20.0",
"babel-eslint": "10.1.0", "babel-eslint": "10.1.0",
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
"bizcharts": "^3.3.0", "bizcharts": "^3.3.0",
"camelcase": "^5.3.1", "camelcase": "^5.3.1",
"case-sensitive-paths-webpack-plugin": "2.3.0", "case-sensitive-paths-webpack-plugin": "2.3.0",
"classnames": "^2.2.6", "classnames": "^2.3.1",
"cropper": "^3.1.4", "cropper": "^3.1.4",
"cross-env": "^7.0.3", "cross-env": "^7.0.3",
"css-loader": "3.4.2", "css-loader": "3.4.2",
......
...@@ -7,11 +7,12 @@ ...@@ -7,11 +7,12 @@
* @Copyright: 杭州杰竞科技有限公司 版权所有 * @Copyright: 杭州杰竞科技有限公司 版权所有
*/ */
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, AxiosPromise, AxiosError } from 'axios'; import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, AxiosPromise, AxiosError } from 'axios';
import { message } from 'antd'; import { message, Modal } from 'antd';
import { BASIC_HOST, TIME_OUT, USER_TYPE, VERSION, PROJECT } from '@/domains/basic-domain/constants'; import { BASIC_HOST, TIME_OUT, USER_TYPE, VERSION, PROJECT } from '@/domains/basic-domain/constants';
import User from './user'; import User from './user';
import { content } from 'html2canvas/dist/types/css/property-descriptors/content';
interface FetchParams { interface FetchParams {
url: string, url: string,
...@@ -27,7 +28,8 @@ interface HeadersType{ ...@@ -27,7 +28,8 @@ interface HeadersType{
storeId?:any, storeId?:any,
storeUserId?:any, storeUserId?:any,
userId?:any, userId?:any,
xmtoken?:any xmtoken?:any,
enterpriseId?:string|null
} }
class Axios { class Axios {
static post( static post(
...@@ -51,6 +53,9 @@ class Axios { ...@@ -51,6 +53,9 @@ class Axios {
if(User.getToken()){ if(User.getToken()){
headerObject.xmtoken = User.getToken(); headerObject.xmtoken = User.getToken();
} }
if (User.getEnterpriseId()) {
headerObject.enterpriseId = User.getEnterpriseId();
}
const instance: AxiosInstance = axios.create({ const instance: AxiosInstance = axios.create({
timeout: TIME_OUT, timeout: TIME_OUT,
responseType: 'json', responseType: 'json',
...@@ -84,8 +89,14 @@ class Axios { ...@@ -84,8 +89,14 @@ class Axios {
}) })
instance.interceptors.response.use((response: AxiosResponse): AxiosResponse | AxiosPromise => { instance.interceptors.response.use((response: AxiosResponse): AxiosResponse | AxiosPromise => {
const { message: ResMessage, success, resultMsg, resultCode,code} = response.data; const { message: ResMessage, success, resultMsg, code: resultCode } = response.data;
if (success || resultCode === 0) { if (resultCode === "CROP_DEPLOY_PAST_BETTER") {
Modal.warning({
title:"服务已到期",
content: "当前企业购买的小麦企学院服务已到期,如需继续使用学院功能,请尽快续费购买",
okText: "我知道了"
})
} else if (success || resultCode === 0) {
return response; return response;
} else if (!options.reject) { } else if (!options.reject) {
message.error(ResMessage || resultMsg); message.error(ResMessage || resultMsg);
......
...@@ -12,6 +12,10 @@ import { PREFIX, USER_PREFIX } from '@/domains/basic-domain/constants'; ...@@ -12,6 +12,10 @@ import { PREFIX, USER_PREFIX } from '@/domains/basic-domain/constants';
declare var window:any; declare var window:any;
class User { class User {
getExpirationTime() {
return Storage.get(`${PREFIX}_expiration_time`)
}
getVersion() { getVersion() {
return Storage.getObj(`${PREFIX}_version`) return Storage.getObj(`${PREFIX}_version`)
} }
...@@ -56,8 +60,16 @@ class User { ...@@ -56,8 +60,16 @@ class User {
return Storage.get(`${PREFIX}_isAdmin`); return Storage.get(`${PREFIX}_isAdmin`);
} }
setStoreId(value: any) { setExpirationTime(value:number) {
return Storage.set(`${PREFIX}_storeId`, value); return Storage.set(`${PREFIX}_expiration_time`,value)
}
setVersion(value:any) {
return Storage.setObj(`${PREFIX}_version`,value)
}
setStoreId(value:any){
return Storage.set(`${PREFIX}_storeId`,value)
} }
setEnterpriseId(value: any) { setEnterpriseId(value: any) {
......
...@@ -10,4 +10,7 @@ ...@@ -10,4 +10,7 @@
height: 100vh; height: 100vh;
padding: 16px; padding: 16px;
background-color: #F0F2F5; background-color: #F0F2F5;
}
.ant-tooltip-inner {
max-width: 1000px;
} }
\ No newline at end of file
.ant-popover .ant-popover-content .ant-popover-inner {
box-shadow: 0px 2px 20px 0px rgba(0, 0, 0, 0.06);
.ant-popover-inner-content {
padding: 0;
}
}
.contact-widget {
width: 276px;
height: 294px;
overflow: hidden;
background-color: white;
background-image: url(https://image.xiaomaiketang.com/xm/CZ4a752jzi.png);
background-repeat: no-repeat;
background-size: cover;
text-align: center;
font-size: 14px;
font-weight: 400;
color: #333333;
line-height: 22px;
.qrcode {
width: 182px;
height: 204px;
background-color: white;
margin: 28px auto 16px auto;
img {
width: 150px;
height: 150px;
margin: 16px 16px 8px 16px;
}
}
}
\ No newline at end of file
import React, { ReactElement } from "react";
import { Popover } from "antd";
import { TooltipPlacement } from "antd/lib/tooltip";
import { ActionType } from "rc-trigger/lib/interface";
import "./ContactWidget.less"
interface ContactWidgetProps {
placement: TooltipPlacement
children: React.ReactElement
visible?: boolean
trigger: ActionType | ActionType[]
}
function Content() {
return (
<div className="contact-widget">
<div className="qrcode">
<img src="https://cdn.xiaomai5.com/qixueyuankehu.png" 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>
咨询电话:19157875632</div>
</div>
)
}
export default function ContactWidget(props:ContactWidgetProps) {
return <Popover
placement={props.placement}
arrowPointAtCenter
content={Content}
visible={props.visible}
trigger={props.trigger}
>
{props.children}
</Popover>
}
\ No newline at end of file
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
min-height: 100%; min-height: 100%;
overflow: hidden;
.page { .page {
position: fixed; position: fixed;
top: 60px; top: 60px;
...@@ -21,6 +22,7 @@ ...@@ -21,6 +22,7 @@
z-index: 102; z-index: 102;
overflow: auto; overflow: auto;
margin: 0 16px; margin: 0 16px;
.box { .box {
&:first-child { &:first-child {
margin-bottom: 8px; margin-bottom: 8px;
......
...@@ -7,7 +7,9 @@ ...@@ -7,7 +7,9 @@
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/ */
import Service from "@/common/js/service"; import Service from "@/common/js/service";
import User from "@/common/js/user";
import axios from 'axios'; import axios from 'axios';
export function sendLoginAuthCode(params: object) { export function sendLoginAuthCode(params: object) {
return Service.Hades("anon/hades/sendLoginAuthCode", params); return Service.Hades("anon/hades/sendLoginAuthCode", params);
} }
...@@ -47,6 +49,9 @@ export function getEnterpriseUser(params: object) { ...@@ -47,6 +49,9 @@ export function getEnterpriseUser(params: object) {
export function getWXWorkLoginNoCheck(params: object) { export function getWXWorkLoginNoCheck(params: object) {
return Service.Hades('anon/hades/getWXWorkLoginNoCheck', params); return Service.Hades('anon/hades/getWXWorkLoginNoCheck', params);
} }
export function getLesseeVersionMsg() {
return Service.Hades("public/customerHades/getLesseeVersionMsg",{enterpriseId:User.getEnterpriseId()})
}
export function getYoZoSign(params: object) { export function getYoZoSign(params: object) {
return Service.Apollo('public/apollo/getYoZoSign', params); return Service.Apollo('public/apollo/getYoZoSign', params);
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/ */
import Service from "@/common/js/service"; import Service from "@/common/js/service";
import User from "@/common/js/user"
export function getEmployeeList(params: object) { export function getEmployeeList(params: object) {
return Service.Hades("public/hades/getStoreUserPage", params); return Service.Hades("public/hades/getStoreUserPage", params);
...@@ -76,3 +77,4 @@ export function getStoreDetail(params: object) { ...@@ -76,3 +77,4 @@ export function getStoreDetail(params: object) {
} }
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/ */
import { getUserStore, getUserPermission ,logout,getStoreUser,sendBizAuthCode,editUserPhone,checkBizAuthCode,sendNewPhoneAuthCode,sendLoginAuthCode,login,getLastedVersion, getEnterpriseUser,getWXWorkLoginNoCheck,getYoZoSign,saveYoZoFileVersionId,yoZoUpload} from '@/data-source/base/request-apis'; import { getUserStore, getUserPermission ,logout,getStoreUser,sendBizAuthCode,editUserPhone,checkBizAuthCode,sendNewPhoneAuthCode,sendLoginAuthCode,login,getLastedVersion, getEnterpriseUser,getWXWorkLoginNoCheck,getLesseeVersionMsg,getYoZoSign,saveYoZoFileVersionId,yoZoUpload} from '@/data-source/base/request-apis';
export default class StoreService { export default class StoreService {
// 获取员工列表 // 获取员工列表
...@@ -55,6 +55,10 @@ export default class StoreService { ...@@ -55,6 +55,10 @@ export default class StoreService {
static getWXWorkLoginNoCheck(params: any){ static getWXWorkLoginNoCheck(params: any){
return getWXWorkLoginNoCheck(params); return getWXWorkLoginNoCheck(params);
} }
//获取企业配置的版本信息
static getLesseeVersionMsg() {
return getLesseeVersionMsg();
}
static getYoZoSign(params:any){ static getYoZoSign(params:any){
return new Promise((resolve) => { return new Promise((resolve) => {
getYoZoSign(params).then(res => { getYoZoSign(params).then(res => {
......
...@@ -15,6 +15,7 @@ import college from '@/common/lottie/college.json'; ...@@ -15,6 +15,7 @@ import college from '@/common/lottie/college.json';
import StoreService from "@/domains/store-domain/storeService"; import StoreService from "@/domains/store-domain/storeService";
import EmployeeAddOrEditModal from "../store-manage/EmployeeAddOrEditModal"; import EmployeeAddOrEditModal from "../store-manage/EmployeeAddOrEditModal";
import User from "@/common/js/user"; import User from "@/common/js/user";
import LimitTip from "./LimitTip";
import "./EmployeeManage.less"; import "./EmployeeManage.less";
import ChooseMembersModal from "./modal/ChooseMembersModal"; import ChooseMembersModal from "./modal/ChooseMembersModal";
...@@ -68,6 +69,7 @@ function EmployeeManage() { ...@@ -68,6 +69,7 @@ function EmployeeManage() {
}); });
const [total, setTotal] = useState(0); const [total, setTotal] = useState(0);
const [realTotal, setRealTotal] = useState(0)
const [model, setModel] = useState<React.ReactNode>(null); const [model, setModel] = useState<React.ReactNode>(null);
const [employeeModal, setEmployeeModal] = useState(false); const [employeeModal, setEmployeeModal] = useState(false);
const [choosedItem, setChooseItem] = useState<ChoosedItemType>({ const [choosedItem, setChooseItem] = useState<ChoosedItemType>({
...@@ -85,6 +87,17 @@ function EmployeeManage() { ...@@ -85,6 +87,17 @@ function EmployeeManage() {
if (!User.getEnterpriseId()) { if (!User.getEnterpriseId()) {
window.RCHistory.replace('/employees-manage'); window.RCHistory.replace('/employees-manage');
} }
//获取员工数
const _query = {
current: 0,
size: 10,
nickName: "",
phone: "",
roleCodes: [],
}
StoreService.getEmployeeList(_query).then((res: any) => {
setRealTotal(res.result.total);
});
}, []) }, [])
useEffect(() => { useEffect(() => {
...@@ -362,6 +375,7 @@ function EmployeeManage() { ...@@ -362,6 +375,7 @@ function EmployeeManage() {
</Button> </Button>
} }
</div> </div>
<LimitTip type="员工" total={realTotal} tip={()=>{return (<div>数据为当前学院的员工数,若员工存在多个学院,企业人数只统计为1人</div>)}}/>
<div className="box-body"> <div className="box-body">
<XMTable <XMTable
renderEmpty={{ renderEmpty={{
......
.limit-tip {
background: #E9EFFF;
border-radius: 2px;
margin-bottom: 13px;
.always {
display: inline-block;
font-size: 14px;
line-height: 32px;
font-weight: 400;
color: #666666;
margin-left: 16px;
.renew-text {
display: inline-block;
color: #2966FF;
cursor: pointer;
}
}
}
\ No newline at end of file
import React, { useContext, useEffect, useState } from "react";
import { Tooltip } from "antd"
import { VersionContext } from "@/store/context";
import ContactWidget from "@/components/ContactWidget";
import "./LimitTip.less"
export default function LimitTip(props:{total:number,type:string,tip:() => React.ReactNode}) {
const [isOver, setIsOver] = useState(false)
const [limitUser, setLimitUser] = useState("0")
const versionInfo = useContext(VersionContext)
useEffect(()=> {
if (versionInfo) {
setIsOver(versionInfo.userNum === -1 ? false : versionInfo.whetherReachUserNum)
setLimitUser(versionInfo.userNum === -1 ? "不限人数" : String(versionInfo.userNum))
}
},[versionInfo])
return (
<div className="limit-tip">
<div className="always">本学院{props.type}<span style={{color:"#333333",fontWeight:"bold"}}>{props.total}</span>
<Tooltip overlayStyle={{maxWidth:"587px",width:"fit-content"}} placement="topLeft" arrowPointAtCenter title={props.tip}>
<span className="icon iconfont" style={{cursor:"pointer",marginLeft:"4px",color:"#bfbfbf"}}>&#59449;</span>
</Tooltip>
{
isOver ? (
<>
<div style={{marginLeft:"14px",display:"inline-block"}}>当前企业使用人数已达到上限 (<span style={{color:"#333333",fontWeight:"bold"}}>{limitUser}</span>人),将无法添加新员工、新学员,如需增加人数限制,请联系小麦企学院服务平台。</div>
<ContactWidget trigger="hover" placement="bottom">
<div className="renew-text">立即续费<span className="icon iconfont" style={{fontSize:"10px"}}>&#59291;</span></div>
</ContactWidget>
</>
) : ("")
}
</div>
</div>
)
}
\ No newline at end of file
...@@ -17,4 +17,5 @@ ...@@ -17,4 +17,5 @@
margin-left: 4px; margin-left: 4px;
} }
} }
} }
\ No newline at end of file
...@@ -15,6 +15,8 @@ import { Input, DatePicker, Select, Button, message } from "antd"; ...@@ -15,6 +15,8 @@ import { Input, DatePicker, Select, Button, message } from "antd";
import StoreService from "@/domains/store-domain/storeService"; import StoreService from "@/domains/store-domain/storeService";
import User from "@/common/js/user"; import User from "@/common/js/user";
import ChooseMembersModal from "./modal/ChooseMembersModal"; import ChooseMembersModal from "./modal/ChooseMembersModal";
import LimitTip from "./LimitTip"
import { XMTable } from '@/components'; import { XMTable } from '@/components';
import college from '@/common/lottie/college.json'; import college from '@/common/lottie/college.json';
import "./UserManagePage.less"; import "./UserManagePage.less";
...@@ -26,6 +28,8 @@ const { RangePicker } = DatePicker; ...@@ -26,6 +28,8 @@ const { RangePicker } = DatePicker;
declare var window: any; declare var window: any;
function UserManagePage() { function UserManagePage() {
const [userList, setUserList] = useState([]); const [userList, setUserList] = useState([]);
const [model, setModel] = useState<React.ReactNode>(null); const [model, setModel] = useState<React.ReactNode>(null);
...@@ -39,11 +43,25 @@ function UserManagePage() { ...@@ -39,11 +43,25 @@ function UserManagePage() {
sourceEnum: undefined, sourceEnum: undefined,
}); });
const [total, setTotal] = useState(0); const [total, setTotal] = useState(0);
const [realTotal, setRealTotal] = useState(0)
useEffect(() => { useEffect(() => {
if (!User.getEnterpriseId()) { if (!User.getEnterpriseId()) {
window.RCHistory.replace('/user-manage'); window.RCHistory.replace('/user-manage');
} }
//获取学员数
const _query = {
current: 0,
size: 10,
nickName: "",
phone: "",
registerBegin: null,
registerEnd: null,
sourceEnum: undefined,
}
StoreService.getUserList(_query).then((res: any) => {
setRealTotal(res.result.total);
});
}, []) }, [])
useEffect(() => { useEffect(() => {
...@@ -125,9 +143,6 @@ function UserManagePage() { ...@@ -125,9 +143,6 @@ function UserManagePage() {
<div className="header-item"> <div className="header-item">
<span className="item-name">搜索学员:</span> <span className="item-name">搜索学员:</span>
<Search <Search
style={{
width: 300,
}}
placeholder="搜索学员姓名/手机号" placeholder="搜索学员姓名/手机号"
onSearch={(value) => { onSearch={(value) => {
const _query = { ...query }; const _query = { ...query };
...@@ -199,6 +214,7 @@ function UserManagePage() { ...@@ -199,6 +214,7 @@ function UserManagePage() {
}} }}
>添加学员</Button> >添加学员</Button>
} }
<LimitTip type="学员" total={realTotal} tip={()=>{ return (<div><div>1、数据为当前学院的员工数,若学员存在多个学院,企业人数只统计为1人;</div><div>2、若一个学员既用「企业微信」登录学习又用「微信」登录学习,企业人数将统计为2人。</div></div>)}}/>
<div className="box-body"> <div className="box-body">
<XMTable <XMTable
renderEmpty={{ renderEmpty={{
......
...@@ -285,6 +285,10 @@ class ChooseMembersModal extends React.Component { ...@@ -285,6 +285,10 @@ class ChooseMembersModal extends React.Component {
visible={isOpen} visible={isOpen}
onCancel={() => this.handleClose()} onCancel={() => this.handleClose()}
onOk={() => { onOk={() => {
if (User.getVersion() && User.getVersion().whetherReachUserNum) {
message.error("添加失败,企业使用人数超出限制")
return
}
if (_.isEmpty(selectUserList)) { if (_.isEmpty(selectUserList)) {
message.warning(type === 'USER' ? '请选择员工' : '请选择学员') message.warning(type === 'USER' ? '请选择员工' : '请选择学员')
return null; return null;
......
...@@ -269,6 +269,15 @@ handleChangeBasicInfo = (field, value) => { ...@@ -269,6 +269,15 @@ handleChangeBasicInfo = (field, value) => {
// 完成创建/编辑 // 完成创建/编辑
handleSubmit = () => { handleSubmit = () => {
//过期判断
if (User.getExpirationTime() && moment().valueOf() > Number(User.getExpirationTime())) {
Modal.warning({
title:"服务已到期",
content: "当前企业购买的小麦企学院服务已到期,如需继续使用学院功能,请尽快续费购买",
okText: "我知道了"
})
return
}
const { addLiveBasicInfo, addLiveClassInfo, addLiveIntroInfo, id, isEdit, type } = this.state; const { addLiveBasicInfo, addLiveClassInfo, addLiveIntroInfo, id, isEdit, type } = this.state;
const {liveDate, timeHorizonStart} = addLiveClassInfo; const {liveDate, timeHorizonStart} = addLiveClassInfo;
const _liveDate = moment(liveDate).format("YYYY-MM-DD"); const _liveDate = moment(liveDate).format("YYYY-MM-DD");
......
...@@ -22,6 +22,13 @@ class LiveCoursePage extends React.Component { ...@@ -22,6 +22,13 @@ class LiveCoursePage extends React.Component {
componentWillMount() { componentWillMount() {
this.handleFetchLiveList(this.state.query); this.handleFetchLiveList(this.state.query);
} }
changeShelfState = (index, shelfState) => {
const { courseList } = this.state;
courseList[index].shelfState = shelfState;
this.setState({
courseList,
});
};
// 获取直播课列表 // 获取直播课列表
handleFetchLiveList = (_query) => { handleFetchLiveList = (_query) => {
const { query } = this.state; const { query } = this.state;
...@@ -54,6 +61,7 @@ class LiveCoursePage extends React.Component { ...@@ -54,6 +61,7 @@ class LiveCoursePage extends React.Component {
total={total} total={total}
courseList={courseList} courseList={courseList}
onChange={this.handleFetchLiveList} onChange={this.handleFetchLiveList}
changeShelfState={this.changeShelfState}
/> />
</div> </div>
</div> </div>
......
...@@ -93,15 +93,13 @@ class LiveCourseList extends React.Component { ...@@ -93,15 +93,13 @@ class LiveCourseList extends React.Component {
}; };
//改变上架状态 //改变上架状态
changeShelfState = (item) => { changeShelfState = (index,item,checked) => {
let _shelfState = item.shelfState; let _shelfState = checked ? "YES" : "NO"
if (_shelfState === 'NO') { // if (_shelfState === 'NO') {
_shelfState = 'YES'; // _shelfState = 'YES';
item.shelfState = 'YES'; // } else {
} else { // _shelfState = 'NO';
_shelfState = 'NO'; // }
item.shelfState = 'NO';
}
const params = { const params = {
liveCourseId: item.liveCourseId, liveCourseId: item.liveCourseId,
shelfState: _shelfState, shelfState: _shelfState,
...@@ -113,6 +111,7 @@ class LiveCourseList extends React.Component { ...@@ -113,6 +111,7 @@ class LiveCourseList extends React.Component {
} else { } else {
message.success('已取消展示'); message.success('已取消展示');
} }
this.props.changeShelfState(index,_shelfState)
} }
}); });
}; };
...@@ -288,7 +287,10 @@ class LiveCourseList extends React.Component { ...@@ -288,7 +287,10 @@ class LiveCourseList extends React.Component {
key: 'shelfState', key: 'shelfState',
dataIndex: 'shelfState', dataIndex: 'shelfState',
render: (val, item, index) => { render: (val, item, index) => {
return <Switch defaultChecked={item.shelfState === 'YES' ? true : false} onChange={() => this.changeShelfState(item)} />; return <Switch
checked={item.shelfState === "YES"}
defaultChecked={item.shelfState === 'YES' ? true : false}
onChange={(checked) => this.changeShelfState(index,item,checked)} />;
}, },
}, },
{ {
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
import React from 'react'; import React from 'react';
import { Button, Input, Radio, message, Modal, Cascader } from 'antd'; import { Button, Input, Radio, message, Modal, Cascader } from 'antd';
import $ from 'jquery'; import $ from 'jquery';
import moment from 'moment';
import { DISK_MAP, FileTypeIcon, FileVerifyMap } from '@/common/constants/academic/lessonEnum'; import { DISK_MAP, FileTypeIcon, FileVerifyMap } from '@/common/constants/academic/lessonEnum';
import { ImgCutModalNew } from '@/components'; import { ImgCutModalNew } from '@/components';
import ShowTips from '@/components/ShowTips'; import ShowTips from '@/components/ShowTips';
...@@ -390,6 +390,15 @@ class AddGraphicsCourse extends React.Component { ...@@ -390,6 +390,15 @@ class AddGraphicsCourse extends React.Component {
// 保存 // 保存
handleSubmit = () => { handleSubmit = () => {
//过期判断
if (User.getExpirationTime() && moment().valueOf() > Number(User.getExpirationTime())) {
Modal.warning({
title:"服务已到期",
content: "当前企业购买的小麦企学院服务已到期,如需继续使用学院功能,请尽快续费购买",
okText: "我知道了"
})
return
}
const { id, coverId, pageType, courseName, courseMedia, introduce, categoryId, shelfState, whetherVisitorsJoin } = this.state; const { id, coverId, pageType, courseName, courseMedia, introduce, categoryId, shelfState, whetherVisitorsJoin } = this.state;
const commonParams = { const commonParams = {
......
...@@ -144,7 +144,12 @@ class GraphicsCourseList extends React.Component { ...@@ -144,7 +144,12 @@ class GraphicsCourseList extends React.Component {
width: 120, width: 120,
dataIndex: 'courseware', dataIndex: 'courseware',
render: (val, item, index) => { render: (val, item, index) => {
return <Switch defaultChecked={item.shelfState === 'YES' ? true : false} onChange={() => this.changeShelfState(item)} />; return (
<Switch
checked={item.shelfState === "YES"}
defaultChecked={item.shelfState==="YES"?true:false}
onChange={(checked)=>this.changeShelfState(index,item,checked)}/>
)
}, },
}, },
{ {
...@@ -300,19 +305,17 @@ class GraphicsCourseList extends React.Component { ...@@ -300,19 +305,17 @@ class GraphicsCourseList extends React.Component {
删除 删除
</div> </div>
</div> </div>
); )
}; }
//改变上架状态 //改变上架状态
changeShelfState = (item) => { changeShelfState = (index,item,checked) =>{
let _shelfState = item.shelfState; let _shelfState = checked ? "YES" : "NO"
if (_shelfState === 'NO') { // if(_shelfState==='NO'){
_shelfState = 'YES'; // _shelfState = "YES";
item.shelfState = 'YES'; // }else{
} else { // _shelfState = "NO"
_shelfState = 'NO'; // }
item.shelfState = 'NO'; const params={
}
const params = {
courseId: item.id, courseId: item.id,
shelfState: _shelfState, shelfState: _shelfState,
}; };
...@@ -323,6 +326,7 @@ class GraphicsCourseList extends React.Component { ...@@ -323,6 +326,7 @@ class GraphicsCourseList extends React.Component {
} else { } else {
message.success('已取消展示'); message.success('已取消展示');
} }
this.props.changeShelfState(index,_shelfState)
} }
}); });
}; };
......
...@@ -27,6 +27,13 @@ class GraphicsCourse extends React.Component { ...@@ -27,6 +27,13 @@ class GraphicsCourse extends React.Component {
this.handleFetchScheduleList(); this.handleFetchScheduleList();
} }
changeShelfState = (index, shelfState) => {
const { dataSource } = this.state;
dataSource[index].shelfState = shelfState;
this.setState({
dataSource,
});
};
// 获取视频课列表 // 获取视频课列表
handleFetchScheduleList = (_query = {}) => { handleFetchScheduleList = (_query = {}) => {
const query = { const query = {
...@@ -75,6 +82,7 @@ class GraphicsCourse extends React.Component { ...@@ -75,6 +82,7 @@ class GraphicsCourse extends React.Component {
dataSource={dataSource} dataSource={dataSource}
totalCount={totalCount} totalCount={totalCount}
onChange={this.handleFetchScheduleList} onChange={this.handleFetchScheduleList}
changeShelfState={this.changeShelfState}
/> />
</div> </div>
</div> </div>
......
...@@ -466,6 +466,15 @@ class AddOfflineCourse extends React.Component { ...@@ -466,6 +466,15 @@ class AddOfflineCourse extends React.Component {
}; };
preSubmit = () => { preSubmit = () => {
//过期判断
if (User.getExpirationTime() && moment().valueOf() > Number(User.getExpirationTime())) {
Modal.warning({
title:"服务已到期",
content: "当前企业购买的小麦企学院服务已到期,如需继续使用学院功能,请尽快续费购买",
okText: "我知道了"
})
return
}
const { courseId } = this.state; const { courseId } = this.state;
if (courseId) { if (courseId) {
this.checkDetail(courseId).then(bool => bool ? this.handleSubmit() : message.warning('课程已开始,无法继续编辑')) this.checkDetail(courseId).then(bool => bool ? this.handleSubmit() : message.warning('课程已开始,无法继续编辑'))
......
...@@ -14,7 +14,7 @@ import { DISK_MAP, FileTypeIcon, FileVerifyMap } from '@/common/constants/academ ...@@ -14,7 +14,7 @@ import { DISK_MAP, FileTypeIcon, FileVerifyMap } from '@/common/constants/academ
import { ImgCutModalNew } from '@/components' import { ImgCutModalNew } from '@/components'
import ShowTips from '@/components/ShowTips' import ShowTips from '@/components/ShowTips'
import Breadcrumbs from '@/components/Breadcrumbs' import Breadcrumbs from '@/components/Breadcrumbs'
import moment from 'moment'
import AddVideoIntro from './components/AddVideoIntro' import AddVideoIntro from './components/AddVideoIntro'
import SelectStudent from '../modal/select-student' import SelectStudent from '../modal/select-student'
import SelectPrepareFileModal from '../../prepare-lesson/modal/SelectPrepareFileModal' import SelectPrepareFileModal from '../../prepare-lesson/modal/SelectPrepareFileModal'
...@@ -321,6 +321,15 @@ class AddVideoCourse extends React.Component { ...@@ -321,6 +321,15 @@ class AddVideoCourse extends React.Component {
// 保存 // 保存
handleSubmit = () => { handleSubmit = () => {
//过期判断
if (User.getExpirationTime() && moment().valueOf() > Number(User.getExpirationTime())) {
Modal.warning({
title:"服务已到期",
content: "当前企业购买的小麦企学院服务已到期,如需继续使用学院功能,请尽快续费购买",
okText: "我知道了"
})
return
}
const { instId, adminId } = window.currentUserInstInfo const { instId, adminId } = window.currentUserInstInfo
const { const {
......
import React from 'react'; import React, { useEffect, useState } from 'react';
import { Select, Tooltip } from 'antd'; import { Select, Tooltip, Carousel, Popover } from 'antd';
import DataSet from "@antv/data-set"; import DataSet from "@antv/data-set";
import { Chart as G2Chart } from '@antv/g2'; import { Chart as G2Chart } from '@antv/g2';
import { import {
...@@ -20,6 +20,8 @@ import { ...@@ -20,6 +20,8 @@ import {
import moment from 'moment' import moment from 'moment'
import Service from "@/common/js/service"; import Service from "@/common/js/service";
import User from '@/common/js/user'; import User from '@/common/js/user';
import HomeTip from './HomeTip';
import './Home.less'; import './Home.less';
const Option = Select.Option; const Option = Select.Option;
...@@ -42,7 +44,11 @@ class Home extends React.Component { ...@@ -42,7 +44,11 @@ class Home extends React.Component {
studyTimeRange: '7', studyTimeRange: '7',
completeNum: 0, completeNum: 0,
unfinishedNum: 0, unfinishedNum: 0,
} weekVisitCustomerNum: 0,
incWeekVisitCustomerNum: 0,
courseNum: 0, //课程总数
inCourseNum: 0, //本月新增课程总数
};
this._chart = null; this._chart = null;
} }
...@@ -56,7 +62,7 @@ class Home extends React.Component { ...@@ -56,7 +62,7 @@ class Home extends React.Component {
getTrainingInfo() { getTrainingInfo() {
Service.Hades('public/hades/planOverview', { storeId: User.getStoreId() }).then((res) => { Service.Hades('public/hades/planOverview', { storeId: User.getStoreId() }).then((res) => {
if (res.success) { if (res.success) {
this.setState(res.result) this.setState(res.result);
} }
}); });
} }
...@@ -68,25 +74,25 @@ class Home extends React.Component { ...@@ -68,25 +74,25 @@ class Home extends React.Component {
scheduleType, scheduleType,
storeId: User.getStoreId(), storeId: User.getStoreId(),
timeRange, timeRange,
} };
Service.Hades('public/courseCloud/hotCourse', data).then((res) => { Service.Hades('public/courseCloud/hotCourse', data).then((res) => {
if (res.success) { if (res.success) {
this.setState({ this.setState({
list: res.result list: res.result,
}) });
} }
}) });
} }
getStudyInfo() { getStudyInfo() {
const { studyTimeRange } = this.state; const { studyTimeRange } = this.state;
Service.Hades('public/hades/studyInfo', { storeId: User.getStoreId(), timeRange: studyTimeRange }).then((res) => { Service.Hades('public/hades/studyInfo', { storeId: User.getStoreId(), timeRange: studyTimeRange }).then((res) => {
if (res.success) { if (res.success) {
const dataList = res.result.map(item => ({ const dataList = res.result.map((item) => ({
time: moment(item.dateline).format('MM-DD'), time: moment(item.dateline).format('MM-DD'),
studyNum: item.studyNum, studyNum: item.studyNum,
studyTime: Math.round(item.studyTime / 6) / 10, studyTime: Math.round(item.studyTime / 6) / 10,
})) }));
this.createChart(dataList); this.createChart(dataList);
} }
}); });
...@@ -110,9 +116,13 @@ class Home extends React.Component { ...@@ -110,9 +116,13 @@ class Home extends React.Component {
pictureCourseNum: res.result.pictureCourseNum, pictureCourseNum: res.result.pictureCourseNum,
offlineCourseNum: res.result.offlineCourseNum, offlineCourseNum: res.result.offlineCourseNum,
trainingPlanNum: res.result.trainingPlanNum, trainingPlanNum: res.result.trainingPlanNum,
}) weekVisitCustomerNum: res.result.weekVisitCustomerNum,
incWeekVisitCustomerNum: res.result.incWeekVisitCustomerNum,
courseNum: res.result.videoCourseNum + res.result.liveCourseNum + res.result.pictureCourseNum + res.result.offlineCourseNum,
inCourseNum: res.result.incLiveCourseNum + res.result.incVideoCourseNum + res.result.incPictureCourseNum + res.result.incOfflineCourseNum,
});
} }
}) });
} }
showNumber(index) { showNumber(index) {
...@@ -123,97 +133,109 @@ class Home extends React.Component { ...@@ -123,97 +133,109 @@ class Home extends React.Component {
return 'https://image.xiaomaiketang.com/xm/Qfib4mnGJT.png'; return 'https://image.xiaomaiketang.com/xm/Qfib4mnGJT.png';
case 2: case 2:
return 'https://image.xiaomaiketang.com/xm/8jKXHyrDaG.png'; return 'https://image.xiaomaiketang.com/xm/8jKXHyrDaG.png';
default: default:
return 'https://image.xiaomaiketang.com/xm/D64QhNn74S.png'; return 'https://image.xiaomaiketang.com/xm/D64QhNn74S.png';
} }
} }
createChart = (data) => { createChart = (data) => {
if (!this._chart) { if (!this._chart) {
this._chart = new G2Chart({ this._chart = new G2Chart({
container: 'chart-id', container: 'chart-id',
forceFit: true, forceFit: true,
height: 290, height: 290,
padding: [48, 64] padding: [48, 64],
}) });
} }
this._chart.clear(); this._chart.clear();
this._chart.source(data, { this._chart.source(data, {
studyTime: { studyTime: {
formatter: (val) => { formatter: (val) => {
return val return val;
}, },
tickCount: 5,
},
time: {
formatter: (val) => {
return `${val}`;
},
},
studyNum: {
formatter: (val) => {
return val;
},
tickCount: 5, tickCount: 5,
}, },
time: { });
formatter: (val) => { this._chart.axis('time', {
return `${val}` label: {
}, offset: 20,
}, textStyle: {
studyNum: { fill: '#666666',
formatter: (val) => { fontSize: 14,
return val },
}, },
tickCount: 5, line: {
} stroke: '#E8E8E8',
}); },
this._chart.axis('time', { tickLine: {
label: { stroke: '#E8E8E8',
offset: 20, },
textStyle: { });
fill: '#666666', this._chart.axis('submitCount', {
fontSize: 14 label: {
} textStyle: {
}, fill: '#666666',
line: { fontSize: 14,
stroke: '#E8E8E8' },
}, },
tickLine: { });
stroke: '#E8E8E8' this._chart.axis('studyTime', {
} label: {
}) textStyle: {
this._chart.axis('submitCount', { fill: '#666666',
label: { fontSize: 14,
textStyle: { },
fill: '#666666', },
fontSize: 14 });
} this._chart
} .line()
}) .position('time*studyNum')
this._chart.axis('studyTime', { .color('#2966FF')
label: { .tooltip('time*studyNum', function (time, studyNum) {
textStyle: { return {
fill: '#666666', name: '学习人数',
fontSize: 14 value: studyNum + '人',
} };
} });
}) this._chart
this._chart.line().position('time*studyNum').color('#2966FF').tooltip('time*studyNum', function( time, studyNum){ .line()
return { .position('time*studyTime')
name: '学习人数', .color('#FFBB54')
value: studyNum + '人' .tooltip('time*studyTime', function (time, studyTime) {
} return {
}); name: '人均学习时长',
this._chart.line().position('time*studyTime').color('#FFBB54').tooltip('time*studyTime', function( time, studyTime){ value: studyTime + '分钟',
return { };
name: '人均学习时长', });
value: studyTime + '分钟'
}
});
this._chart.legend(false); this._chart.legend(false);
this._chart.tooltip({ this._chart.tooltip({
containerTpl: '<div class="g2-tooltip" style="background: #fff !important;">' containerTpl:
+ '<div class="g2-tooltip-title" style="margin:10px 0;"></div>' '<div class="g2-tooltip" style="background: #fff !important;">' +
+ '<ul class="g2-tooltip-list"></ul></div>', // tooltip 容器模板 '<div class="g2-tooltip-title" style="margin:10px 0;"></div>' +
itemTpl: '<li data-index={index}><span style="background-color:{color};width:8px;height:8px;border-radius:50%;display:inline-block;margin-right:8px;"></span>{name}<span style="display: inline-block; float: right; margin-left: 30px;">{value}</span></li>', // tooltip 每项记录的默认模板 '<ul class="g2-tooltip-list"></ul></div>', // tooltip 容器模板
}) itemTpl:
this._chart.render(); '<li data-index={index}><span style="background-color:{color};width:8px;height:8px;border-radius:50%;display:inline-block;margin-right:8px;"></span>{name}<span style="display: inline-block; float: right; margin-left: 30px;">{value}</span></li>', // tooltip 每项记录的默认模板
} });
this._chart.render();
};
render() { render() {
const { const {
courseNum,
inCourseNum,
examNum, examNum,
incExamNum, incExamNum,
list, list,
...@@ -235,314 +257,347 @@ class Home extends React.Component { ...@@ -235,314 +257,347 @@ class Home extends React.Component {
planCustomerNum, planCustomerNum,
incOfflineCourseNum, incOfflineCourseNum,
offlineCourseNum, offlineCourseNum,
weekVisitCustomerNum,
incWeekVisitCustomerNum,
} = this.state; } = this.state;
const data = [ const data = [
{ {
item: '已完成培训', item: '已完成培训',
count: completeNum, count: completeNum,
}, { },
{
item: '未完成培训', item: '未完成培训',
count: unfinishedNum, count: unfinishedNum,
} },
]; ];
const { DataView } = DataSet; const { DataView } = DataSet;
const { Html } = Guide; const { Html } = Guide;
const sum = data[0].count + data[1].count; const sum = data[0].count + data[1].count;
const dv = new DataView(); const dv = new DataView();
sum && dv.source(data).transform({ sum &&
type: "percent", dv.source(data).transform({
field: "count", type: 'percent',
dimension: "item", field: 'count',
as: "percent" dimension: 'item',
}); as: 'percent',
});
const cols = { const cols = {
percent: { percent: {
formatter: val => { formatter: (val) => {
val = val * 100 + "%"; val = val * 100 + '%';
return val; return val;
} },
} },
}; };
return ( return (
<div className="home-page"> <div className='home-page'>
<div className="data-wrap"> <HomeTip />
<div className="home-title">数据概况</div> <div className='data-wrap'>
<div className="data-box"> <div className='home-title'>数据概况</div>
<div className="data-item"> <div className='data-box'>
<div className="header"> <div className='data-item'>
<img className="header-icon" src="https://image.xiaomaiketang.com/xm/wAaFtjeRsM.png" /> <div className='header'>
<span className="header-word">学员总数 (人)</span> <img className='header-icon' src='https://image.xiaomaiketang.com/xm/wAaFtjeRsM.png' alt='' />
</div> <span className='header-word'>学员总数 (人)</span>
<div className="data-number">{totalCustomerNum}</div> </div>
<div className="data-footer"> <div className='data-number'>{totalCustomerNum}</div>
<span className="footer-word">本月新增</span> <div className='data-footer'>
{incCustomerNum > 0 && <span className='footer-word'>本月新增</span>
<span className="icon iconfont">&#xe635;</span> {incCustomerNum > 0 && <span className='icon iconfont'>&#xe635;</span>}
} <span className='footer-number'>{incCustomerNum > 0 ? incCustomerNum : 0}</span>
<span className="footer-number">{incCustomerNum}</span> </div>
</div> </div>
</div> <div className='data-item'>
<div className="data-item course-data"> <div className='header'>
<div className="header"> <img className='header-icon' src='https://image.xiaomaiketang.com/xm/nXYAHExPrX.png' alt='' />
<img className="header-icon" src="https://image.xiaomaiketang.com/xm/jPrRhw8EMF.png" /> <span className='header-word'>学员周活跃 (人)</span>
<span className="header-word">课程总数 (个)</span> </div>
<div className='data-number'>{weekVisitCustomerNum || 0}</div>
<div className='data-footer'>
<span className='footer-word'>本周新增</span>
{incWeekVisitCustomerNum > 0 && <span className='icon iconfont'>&#xe635;</span>}
<span className='footer-number'>{incWeekVisitCustomerNum > 0 ? incWeekVisitCustomerNum : 0}</span>
</div>
</div> </div>
<div className="data-number">{videoCourseNum + liveCourseNum + pictureCourseNum}</div>
<div className="course-box"> <div className='data-item course-data'>
<div className="course-item"> <div className='header'>
<div className="course-title">直播课</div> <img className='header-icon' src='https://image.xiaomaiketang.com/xm/jPrRhw8EMF.png' alt='' />
<div className="data"> <span className='header-word'>课程总数 (个)</span>
<span className="course-number">{liveCourseNum}</span>
<span className="course-word">本月新增</span>
{incLiveCourseNum > 0 &&
<span className="icon iconfont">&#xe635;</span>
}
<span className="add-number">{incLiveCourseNum}</span>
</div>
</div> </div>
<div className="course-item">
<div className="course-title">视频课</div> <div className='data-number'>{courseNum}</div>
<div className="data"> <div className='data-footer'>
<span className="course-number">{videoCourseNum}</span> <span className='footer-word'>本月新增</span>
<span className="course-word">本月新增</span> {inCourseNum > 0 && <span className='icon iconfont'>&#xe635;</span>}
{incVideoCourseNum > 0 && <span className='footer-number'>{inCourseNum > 0 ? inCourseNum : 0}</span>
<span className="icon iconfont">&#xe635;</span>
}
<span className="add-number">{incVideoCourseNum}</span>
</div>
</div> </div>
<div className="course-item"> <div className='course-box'>
<div className="course-title">图文课</div> <div className='course-item'>
<div className="data"> <div className='course-title'>直播课</div>
<span className="course-number">{pictureCourseNum}</span> <div className='data'>
<span className="course-word">本月新增</span> <span className='course-number'>{liveCourseNum}</span>
{incPictureCourseNum > 0 && {incLiveCourseNum > 0 && <span className='icon iconfont'>&#xe635;</span>}
<span className="icon iconfont">&#xe635;</span> <span className='add-number'>{incLiveCourseNum > 0 ? incLiveCourseNum : 0}</span>
} </div>
<span className="add-number">{incPictureCourseNum}</span>
</div> </div>
</div> <div className='course-item'>
<div className="course-item"> <div className='course-title'>视频课</div>
<div className="course-title">线下课</div> <div className='data'>
<div className="data"> <span className='course-number'>{videoCourseNum}</span>
<span className="course-number">{offlineCourseNum}</span> {incVideoCourseNum > 0 && <span className='icon iconfont'>&#xe635;</span>}
<span className="course-word">本月新增</span> <span className='add-number'>{incVideoCourseNum > 0 ? incVideoCourseNum : 0}</span>
{incOfflineCourseNum > 0 && </div>
<span className="icon iconfont">&#xe635;</span> </div>
} <div className='course-item'>
<span className="add-number">{incOfflineCourseNum}</span> <div className='course-title'>图文课</div>
<div className='data'>
<span className='course-number'>{pictureCourseNum}</span>
{incPictureCourseNum > 0 && <span className='icon iconfont'>&#xe635;</span>}
<span className='add-number'>{incPictureCourseNum > 0 ? incPictureCourseNum : 0}</span>
</div>
</div>
<div className='course-item'>
<div className='course-title'>线下课</div>
<div className='data'>
<span className='course-number'>{offlineCourseNum}</span>
{incOfflineCourseNum > 0 && <span className='icon iconfont'>&#xe635;</span>}
<span className='add-number'>{incOfflineCourseNum > 0 ? incOfflineCourseNum : 0}</span>
</div>
</div> </div>
</div> </div>
</div> </div>
</div> <div className='data-item'>
<div className="data-item"> <div className='header'>
<div className="header"> <img className='header-icon' src='https://image.xiaomaiketang.com/xm/jZf3GNY5tY.png' alt='' />
<img className="header-icon" src="https://image.xiaomaiketang.com/xm/jZf3GNY5tY.png" /> <span className='header-word'>培训计划总数 (个)</span>
<span className="header-word">培训计划总数 (个)</span> </div>
</div> <div className='data-number'>{trainingPlanNum}</div>
<div className="data-number">{trainingPlanNum}</div> <div className='data-footer'>
<div className="data-footer"> <span className='footer-word'>本月新增</span>
<span className="footer-word">本月新增</span> {incTrainingPlanNum > 0 && <span className='icon iconfont'>&#xe635;</span>}
{incTrainingPlanNum > 0 && <span className='footer-number'>{incTrainingPlanNum > 0 ? incTrainingPlanNum : 0}</span>
<span className="icon iconfont">&#xe635;</span> </div>
}
<span className="footer-number">{incTrainingPlanNum}</span>
</div> </div>
</div>
<div className="data-item"> <div className='data-item'>
<div className="header"> <div className='header'>
<img className="header-icon" src="https://image.xiaomaiketang.com/xm/3CfrPs23Re.png" /> <img className='header-icon' src='https://image.xiaomaiketang.com/xm/3CfrPs23Re.png' alt='' />
<span className="header-word">考试总数 (个)</span> <span className='header-word'>考试总数 (个)</span>
</div> </div>
<div className="data-number">{examNum}</div> <div className='data-number'>{examNum}</div>
<div className="data-footer"> <div className='data-footer'>
<span className="footer-word">本月新增</span> <span className='footer-word'>本月新增</span>
{incExamNum > 0 && {incExamNum > 0 && <span className='icon iconfont'>&#xe635;</span>}
<span className="icon iconfont">&#xe635;</span> <span className='footer-number'>{incExamNum > 0 ? incExamNum : 0}</span>
} </div>
<span className="footer-number">{incExamNum}</span>
</div> </div>
</div> </div>
</div> </div>
</div> <div className='study-wrap'>
<div className="study-wrap"> <div className='home-title'>学习概况</div>
<div className="home-title">学习概况</div> <div className='study-box'>
<div className="study-box"> <div className='study-item'>
<div className="study-item"> <div className='study-title'>课程学习排行榜</div>
<div className="study-title">课程学习排行榜</div> <div className='study-header'>
<div className="study-header"> <div className='study-tab'>
<div className="study-tab"> <span
<span
className={`tab${scheduleType === 'LIVE' ? ' selected' : ''}`} className={`tab${scheduleType === 'LIVE' ? ' selected' : ''}`}
onClick={() => this.setState({ scheduleType: 'LIVE' }, () => this.getHotCourse())} onClick={() => this.setState({ scheduleType: 'LIVE' }, () => this.getHotCourse())}>
>直播课</span> 直播课
<span </span>
<span
className={`tab${scheduleType === 'VOICE' ? ' selected' : ''}`} className={`tab${scheduleType === 'VOICE' ? ' selected' : ''}`}
onClick={() => this.setState({ scheduleType: 'VOICE' }, () => this.getHotCourse())} onClick={() => this.setState({ scheduleType: 'VOICE' }, () => this.getHotCourse())}>
>视频课</span> 视频课
<span </span>
<span
className={`tab${scheduleType === 'PICTURE' ? ' selected' : ''}`} className={`tab${scheduleType === 'PICTURE' ? ' selected' : ''}`}
onClick={() => this.setState({ scheduleType: 'PICTURE' }, () => this.getHotCourse())} onClick={() => this.setState({ scheduleType: 'PICTURE' }, () => this.getHotCourse())}>
>图文课</span> 图文课
</span>
</div> </div>
<div className="study-select"> <div className='study-select'>
<span className="select-word">{moment().subtract(timeRange - 1, 'day').format('MM.DD')} ~ {moment().format('MM.DD')}</span> <span className='select-word'>
{moment()
.subtract(timeRange - 1, 'day')
.format('MM.DD')}{' '}
~ {moment().format('MM.DD')}
</span>
<Select <Select
style={{ width: 88 }} style={{ width: 88 }}
value={timeRange} value={timeRange}
onChange={(value) => { onChange={(value) => {
this.setState({ timeRange: value }, () => this.getHotCourse()); this.setState({ timeRange: value }, () => this.getHotCourse());
}} }}>
> <Option value='7'>近7天</Option>
<Option value="7">近7天</Option> <Option value='15'>近15天</Option>
<Option value="15">近15天</Option> <Option value='30'>近30天</Option>
<Option value="30">近30天</Option>
</Select> </Select>
</div> </div>
</div> </div>
{_.isEmpty(list) ? <Choose>
<div className="study-empty"> <When condition={_.isEmpty(list)}>
<img src="https://image.xiaomaiketang.com/xm/52dmait5Bx.png" /> <div className='study-empty'>
<div>暂无课程上榜</div> <img src='https://image.xiaomaiketang.com/xm/52dmait5Bx.png' alt='' />
</div> <div>暂无课程上榜</div>
: list.map((item, index) => ( </div>
<div className={`table-item${index % 2 ? '' : ' odd'}`} key={item.id}> </When>
{index < 3 ? <Otherwise>
<span className="table-number"><img src={this.showNumber(index)} className="table-image" /></span> {list.map((item, index) => (
: <span className="table-number">{index + 1}</span> <div className={`table-item${index % 2 ? '' : ' odd'}`} key={item.id}>
} <Choose>
<div className="table-data"> <When condition={index < 3}>
<div className="table-name"> <span className='table-number'>
<Tooltip title={item.courseName}> <img src={this.showNumber(index)} className='table-image' alt='' />
{item.courseName} </span>
</Tooltip> </When>
<Otherwise>
<span className='table-number'>{index + 1}</span>
</Otherwise>
</Choose>
<div className='table-data'>
<div className='table-name'>
<Tooltip title={item.courseName}>{item.courseName}</Tooltip>
</div>
<div className='table-tag'>{item.categoryName}</div>
</div> </div>
<div className="table-tag">{item.categoryName}</div> <span className='table-study'>{item.studyNum || 0}人已学习</span>
</div> </div>
<span className="table-study">{item.studyNum || 0}人已学习</span> ))}
</div> </Otherwise>
)) </Choose>
}
</div> </div>
<div className="study-item"> <div className='study-item'>
<div className="study-title">培训计划完成情况 <div className='study-title'>
<Tooltip overlayClassName="data-plan-tooltip" title="若某人加入多个培训计划,则需完成所有已加入的培训计划后,才视为已完成培训"> 培训计划完成情况
<span className="iconfont icon">&#xe61d;</span> <Tooltip overlayClassName='data-plan-tooltip' title='若某人加入多个培训计划,则需完成所有已加入的培训计划后,才视为已完成培训'>
</Tooltip> <span className='iconfont icon'>&#xe61d;</span>
<span className="tip">(本月)</span> </Tooltip>
</div> <span className='tip'>(本月)</span>
{(unfinishedNum || completeNum) ?
<div
className="left-graph-container"
id="mountNode"
style={{ width: '100%', marginLeft: '-20%', marginTop: -30 }}
ref={e => e && (this.width = e.clientWidth)}
>
{this.width && <div>
<Chart
height={400}
width={this.width}
data={dv}
scale={cols}
padding={20}
>
<Coord type={"theta"} radius={0.75} innerRadius={0.6} />
<Axis name="percent" />
<G2Tooltip
showTitle={false}
itemTpl="<li><span style=&quot;background-color:{color};&quot; class=&quot;g2-tooltip-marker&quot;></span>{name}: {value}</li>"
/>
<Guide>
<Html
position={['50%', "50%"]}
html={`<div style="color:#8c8c8c;font-size:14px;text-align: center;width: ${this.width}px;"><span style="color:#333;font-size:20px">${planCustomerNum}人</span><br>新增培训人数</div>`}
alignX="middle"
alignY="middle"
/>
</Guide>
<Geom
type="intervalStack"
position="percent"
color={['item', ['#FFBB54', '#2966FF']]}
tooltip={[
"item*percent",
(item, percent) => {
percent = Math.round(percent * 100) + "%";
return {
name: item,
value: percent,
};
}
]}
style={{
lineWidth: 1,
stroke: "#fff"
}}
>
</Geom>
</Chart>
</div>
}
</div> </div>
: <div className="circle-box"> <Choose>
<div className="big-circle"> <When condition={unfinishedNum || completeNum}>
<div className="small-circle"> <div
<div className="tip-box"> className='left-graph-container'
<div style={{ color: '#333', fontSize: '20px', marginBottom: 4 }}>{planCustomerNum}</div> id='mountNode'
<div style={{ color: '#999' }}>新增培训人数</div> style={{ width: '100%', marginLeft: '-20%', marginTop: -30 }}
ref={(e) => e && (this.width = e.clientWidth)}>
{this.width && (
<div>
<Chart height={400} width={this.width} data={dv} scale={cols} padding={20}>
<Coord type={'theta'} radius={0.75} innerRadius={0.6} />
<Axis name='percent' />
<G2Tooltip
showTitle={false}
itemTpl='<li><span style="background-color:{color};" class="g2-tooltip-marker"></span>{name}: {value}</li>'
/>
<Guide>
<Html
position={['50%', '50%']}
html={`<div style="color:#8c8c8c;font-size:14px;text-align: center;width: ${this.width}px;"><span style="color:#333;font-size:20px">${planCustomerNum}人</span><br>新增培训人数</div>`}
alignX='middle'
alignY='middle'
/>
</Guide>
<Geom
type='intervalStack'
position='percent'
color={['item', ['#FFBB54', '#2966FF']]}
tooltip={[
'item*percent',
(item, percent) => {
percent = Math.round(percent * 100) + '%';
return {
name: item,
value: percent,
};
},
]}
style={{
lineWidth: 1,
stroke: '#fff',
}}></Geom>
</Chart>
</div>
)}
</div>
</When>
<Otherwise>
<div className='circle-box'>
<div className='big-circle'>
<div className='small-circle'>
<div className='tip-box'>
<div style={{ color: '#333', fontSize: '20px', marginBottom: 4 }}>{planCustomerNum}</div>
<div style={{ color: '#999' }}>新增培训人数</div>
</div>
</div>
</div> </div>
</div> </div>
</div> </Otherwise>
</Choose>
<div className='circle-tip unfinished'>
<div className='spot'></div>
<div className='number'>{unfinishedNum}</div>
<div className='word'>未完成培训</div>
</div>
<div className='circle-tip finished'>
<div className='spot'></div>
<div className='number'>{completeNum}</div>
<div className='word'>完成培训</div>
</div> </div>
}
<div className="circle-tip unfinished">
<div className="spot"></div>
<div className="number">{unfinishedNum}</div>
<div className="word">未完成培训</div>
</div>
<div className="circle-tip finished">
<div className="spot"></div>
<div className="number">{completeNum}</div>
<div className="word">完成培训</div>
</div> </div>
</div> </div>
</div>
</div> </div>
<div className="study-chart"> <div className='study-chart'>
<div className="study-title">学习人数与时长 <div className='study-title'>
<div className="study-select"> 学习人数与时长
<span className="select-word">{moment().subtract(studyTimeRange - 1, 'day').format('MM.DD')} ~ {moment().format('MM.DD')}</span> <div className='study-select'>
<span className='select-word'>
{moment()
.subtract(studyTimeRange - 1, 'day')
.format('MM.DD')}{' '}
~ {moment().format('MM.DD')}
</span>
<Select <Select
style={{ width: 88 }} style={{ width: 88 }}
value={studyTimeRange} value={studyTimeRange}
onChange={(value) => { onChange={(value) => {
this.setState({ studyTimeRange: value }, () => this.getStudyInfo()); this.setState({ studyTimeRange: value }, () => this.getStudyInfo());
}} }}>
> <Option value='7'>近7天</Option>
<Option value="7">近7天</Option> <Option value='15'>近15天</Option>
<Option value="15">近15天</Option> <Option value='30'>近30天</Option>
<Option value="30">近30天</Option>
</Select> </Select>
</div> </div>
</div> </div>
<div className="chart-tip"> <div className='chart-tip'>
<div>学习人数(人) <div>
<Tooltip title="参与任意课程进行学习的人数"> 学习人数(人)
<span className="iconfont icon">&#xe61d;</span> <Tooltip title='参与任意课程进行学习的人数'>
<span className='iconfont icon'>&#xe61d;</span>
</Tooltip> </Tooltip>
</div> </div>
<div>人均学习时长(分钟)</div> <div>人均学习时长(分钟)</div>
</div> </div>
<div id="chart-id"></div> <div id='chart-id'></div>
<div className="chart-bottom-tip"> <div className='chart-bottom-tip'>
<div className="tip-item" style={{ marginRight: 100 }}><span className="student-dot"></span>学习人数</div> <div className='tip-item' style={{ marginRight: 100 }}>
<div className="tip-item"><span className="time-dot"></span>人均学习时长</div> <span className='student-dot'></span>学习人数
</div>
<div className='tip-item'>
<span className='time-dot'></span>人均学习时长
</div>
</div> </div>
</div> </div>
</div> </div>
) );
} }
} }
export default Home; export default Home;
\ No newline at end of file
...@@ -2,34 +2,35 @@ ...@@ -2,34 +2,35 @@
// padding: 0 16px 16px; // padding: 0 16px 16px;
min-width: 1100px; min-width: 1100px;
position: relative; position: relative;
z-index:3; z-index: 3;
.g2-tooltip-marker { .g2-tooltip-marker {
border-radius: 50% !important; border-radius: 50% !important;
} }
.home-title { .home-title {
color: #333; color: #333;
padding-left:28px; padding-left: 28px;
font-size:16px; font-size: 16px;
font-weight:bold; font-weight: bold;
position: relative; position: relative;
padding-top:16px; padding-top: 16px;
&::before{ &::before {
width:4px; width: 4px;
height:12px; height: 12px;
content:''; content: '';
background-image: linear-gradient(#2966FF 83.5%, #0ACCA4 16.5%); background-image: linear-gradient(#2966ff 83.5%, #0acca4 16.5%);
display:inline-block; display: inline-block;
position: absolute; position: absolute;
left:16px; left: 16px;
top:22px; top: 22px;
} }
} }
@font-face { @font-face {
font-family: 'number'; font-family: 'number';
src: url('https://image.xiaomaiketang.com/xm/n2sADd2jY6.TTF'); src: url('https://image.xiaomaiketang.com/xm/n2sADd2jY6.TTF');
} }
.data-wrap{ .data-wrap {
background: #FFF; background: #fff;
padding-bottom: 25px;
.data-box { .data-box {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
...@@ -41,7 +42,7 @@ ...@@ -41,7 +42,7 @@
width: ~'calc(16.67% - 8px)'; width: ~'calc(16.67% - 8px)';
padding: 16px; padding: 16px;
&.course-data { &.course-data {
width: ~'calc(50% - 24px)'; width: 33%;
} }
.header { .header {
display: flex; display: flex;
...@@ -55,7 +56,7 @@ ...@@ -55,7 +56,7 @@
font-size: 14px; font-size: 14px;
line-height: 18px; line-height: 18px;
color: #333; color: #333;
font-weight:500; font-weight: 500;
} }
} }
.data-number { .data-number {
...@@ -74,7 +75,7 @@ ...@@ -74,7 +75,7 @@
.iconfont { .iconfont {
font-size: 12px; font-size: 12px;
margin-right: 4px; margin-right: 4px;
color: #EC4B35; color: #ec4b35;
} }
.footer-number { .footer-number {
font-size: 12px; font-size: 12px;
...@@ -83,17 +84,17 @@ ...@@ -83,17 +84,17 @@
} }
.course-box { .course-box {
border-radius: 4px; border-radius: 4px;
background: #FAFAFA; background: #fafafa;
height: 124px; height: 124px;
width: 66%; width: 60%;
position: absolute; position: absolute;
right: 16px; right: 16px;
top: 16px; top: 28px;
padding: 8px 24px 0; padding: 8px 0 0;
.course-item { .course-item {
display: inline-block; display: inline-block;
width: 50%; width: 50%;
padding: 4px 0 12px; padding: 4px 24px 12px;
.course-title { .course-title {
font-size: 12px; font-size: 12px;
color: #999; color: #999;
...@@ -105,6 +106,7 @@ ...@@ -105,6 +106,7 @@
font-size: 16px; font-size: 16px;
font-family: 'number'; font-family: 'number';
margin-right: 16px; margin-right: 16px;
white-space: nowrap;
} }
.course-word { .course-word {
font-size: 12px; font-size: 12px;
...@@ -114,11 +116,12 @@ ...@@ -114,11 +116,12 @@
.iconfont { .iconfont {
font-size: 12px; font-size: 12px;
margin-right: 4px; margin-right: 4px;
color: #EC4B35; color: #ec4b35;
} }
.add-number { .add-number {
font-size: 12px; font-size: 12px;
color: #999; color: #999;
white-space: nowrap;
} }
} }
} }
...@@ -126,9 +129,9 @@ ...@@ -126,9 +129,9 @@
} }
} }
} }
.study-wrap{ .study-wrap {
background: #FFF; background: #fff;
margin-top:16px; margin-top: 16px;
.study-box { .study-box {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
...@@ -148,7 +151,7 @@ ...@@ -148,7 +151,7 @@
margin-bottom: 12px; margin-bottom: 12px;
.iconfont { .iconfont {
font-size: 14px; font-size: 14px;
color: #BFBFBF; color: #bfbfbf;
margin-left: 4px; margin-left: 4px;
} }
.tip { .tip {
...@@ -169,13 +172,13 @@ ...@@ -169,13 +172,13 @@
color: #666; color: #666;
cursor: pointer; cursor: pointer;
&.selected { &.selected {
color: #2966FF; color: #2966ff;
&::after { &::after {
position: absolute; position: absolute;
width: 24px; width: 24px;
height: 2px; height: 2px;
content: ''; content: '';
background: #2966FF; background: #2966ff;
border-radius: 1px; border-radius: 1px;
left: 9px; left: 9px;
bottom: -4px; bottom: -4px;
...@@ -196,7 +199,7 @@ ...@@ -196,7 +199,7 @@
display: flex; display: flex;
align-items: center; align-items: center;
&.odd { &.odd {
background: #FAFAFA; background: #fafafa;
} }
.table-image { .table-image {
width: 24px; width: 24px;
...@@ -257,7 +260,7 @@ ...@@ -257,7 +260,7 @@
width: 204px; width: 204px;
height: 204px; height: 204px;
border-radius: 102px; border-radius: 102px;
background: #F1F3F6; background: #f1f3f6;
margin-top: -20px; margin-top: -20px;
.small-circle { .small-circle {
display: flex; display: flex;
...@@ -280,13 +283,13 @@ ...@@ -280,13 +283,13 @@
&.unfinished { &.unfinished {
top: 152px; top: 152px;
.spot { .spot {
background: #2966FF; background: #2966ff;
} }
} }
&.finished { &.finished {
top: 232px; top: 232px;
.spot { .spot {
background: #FFBB54; background: #ffbb54;
} }
} }
.spot { .spot {
...@@ -309,7 +312,7 @@ ...@@ -309,7 +312,7 @@
} }
} }
} }
.study-chart { .study-chart {
width: 100%; width: 100%;
height: 432px; height: 432px;
...@@ -352,14 +355,14 @@ ...@@ -352,14 +355,14 @@
align-items: center; align-items: center;
color: #666; color: #666;
.student-dot { .student-dot {
background: #2966FF; background: #2966ff;
height: 8px; height: 8px;
width: 8px; width: 8px;
border-radius: 50%; border-radius: 50%;
margin-right: 8px; margin-right: 8px;
} }
.time-dot { .time-dot {
background: #FEB613; background: #feb613;
height: 8px; height: 8px;
width: 8px; width: 8px;
border-radius: 50%; border-radius: 50%;
...@@ -382,7 +385,8 @@ ...@@ -382,7 +385,8 @@
font-size: 14px; font-size: 14px;
} }
.g2-tooltip-list { .g2-tooltip-list {
li,span { li,
span {
display: flex; display: flex;
align-items: center; align-items: center;
font-size: 14px; font-size: 14px;
...@@ -397,4 +401,4 @@ ...@@ -397,4 +401,4 @@
white-space: nowrap; white-space: nowrap;
max-width: none !important; max-width: none !important;
} }
} }
\ No newline at end of file
.home-tip {
.tip {
height: 40px;
background: #FFE7E7;
margin-bottom: 16px;
.content {
font-size: 14px;
color: #666666;
font-weight: 400;
line-height: 40px;
padding-left: 16px;
.renew-btn {
display: inline-block;
width: 80px;
height: 28px;
background: #FF4F4F;
border-radius: 2px;
color: #ffffff;
font-size: 14px;
font-weight: 400;
line-height: 28px;
text-align: center;
cursor: pointer;
margin-left: 8px;
}
}
}
}
\ No newline at end of file
import React, { useContext, useEffect, useState, version } from "react";
import "./HomeTip.less"
import { VersionContext } from "@/store/context";
import ContactWidget from '@/components/ContactWidget';
import { Carousel } from "antd";
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)
}
}
},[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>
</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>
</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>
</div>
)
}
</Carousel>
</div>
}
</div>
)
}
\ No newline at end of file
...@@ -14,7 +14,8 @@ import Main from './Main' ...@@ -14,7 +14,8 @@ import Main from './Main'
import zhCN from 'antd/es/locale/zh_CN' import zhCN from 'antd/es/locale/zh_CN'
import User from '@/common/js/user'; import User from '@/common/js/user';
import BaseService from "@/domains/basic-domain/baseService"; import BaseService from "@/domains/basic-domain/baseService";
import { XMContext } from '@/store/context'; import moment from 'moment';
import { VersionContext, VersionInfo, XMContext } from '@/store/context';
import { setStoreGroupPermission, setStorePermission, setStoreGroupList, setStoreList } from '@/store/actions/index'; import { setStoreGroupPermission, setStorePermission, setStoreGroupList, setStoreList } from '@/store/actions/index';
import Service from "@/common/js/service"; import Service from "@/common/js/service";
import Bus from '@/core/tbus'; import Bus from '@/core/tbus';
...@@ -27,6 +28,7 @@ declare var window: any; ...@@ -27,6 +28,7 @@ declare var window: any;
const App: React.FC = (props: any) => { const App: React.FC = (props: any) => {
const [storeUserId, setStoreUserId] = useState('') const [storeUserId, setStoreUserId] = useState('')
const ctx: any = useContext(XMContext); const ctx: any = useContext(XMContext);
const [versionInfo, setVersionInfo] = useState<VersionInfo|null>(null)
const userId = User.getUserId(); const userId = User.getUserId();
const [menuType, setMenuType] = useState(true); const [menuType, setMenuType] = useState(true);
const enterpriseId = User.getEnterpriseId(); const enterpriseId = User.getEnterpriseId();
...@@ -35,6 +37,7 @@ const App: React.FC = (props: any) => { ...@@ -35,6 +37,7 @@ const App: React.FC = (props: any) => {
useEffect(() => { useEffect(() => {
getStoreAndUserInfo(); getStoreAndUserInfo();
getVersion();
if (window.location.hash === "#/") { if (window.location.hash === "#/") {
window.RCHistory.replace({ window.RCHistory.replace({
pathname: '/home', pathname: '/home',
...@@ -58,6 +61,26 @@ const App: React.FC = (props: any) => { ...@@ -58,6 +61,26 @@ const App: React.FC = (props: any) => {
} }
}); });
} }
function getVersion() {
BaseService.getLesseeVersionMsg().then((res) => {
let version = res.result;
User.setVersion(version);
User.setExpirationTime(res.result.validEndTime)
let versioninfo:VersionInfo = {
dayTime: version.dayTime,
stateEnum: version.stateEnum,
userNum: version.userNum === -1 ? '不限人数' : version.userNum,
surplusUserNum: version.userNum === -1 ? '不限人数' : version.surplusUserNum,
surplusDayTime: version.surplusDayTime,
validEndTime: moment(version.validEndTime).format('YYYY-MM-DD'),
validStartTime: moment(version.validStartTime).format('YYYY-MM-DD'),
validEndTimeST: version.validEndTime,
validStartTimeST: version.validStartTime,
whetherReachUserNum: version.whetherReachUserNum,
};
setVersionInfo(versioninfo)
});
}
async function getStoreAndUserInfo() { async function getStoreAndUserInfo() {
await (enterpriseId ? getStoreInfo() : getStoreGroupAndStoreList()); await (enterpriseId ? getStoreInfo() : getStoreGroupAndStoreList());
...@@ -147,10 +170,13 @@ const App: React.FC = (props: any) => { ...@@ -147,10 +170,13 @@ const App: React.FC = (props: any) => {
</Layout> </Layout>
</Layout> */} </Layout> */}
<Header id="app" handleMenuType={handleMenuType} menuType={menuType} /> <Header id="app" handleMenuType={handleMenuType} menuType={menuType} />
<ConfigProvider locale={zhCN} autoInsertSpaceInButton={false}> <VersionContext.Provider value={versionInfo}>
<Main menuType={menuType} /> <ConfigProvider locale={zhCN} autoInsertSpaceInButton={false}>
</ConfigProvider> <Main menuType={menuType} />
<Menu menuType={menuType} handleMenuType={handleMenuType} /> </ConfigProvider>
<Menu menuType={menuType} handleMenuType={handleMenuType} />
</VersionContext.Provider>
</div> </div>
) )
} }
......
import React from 'react'; import React, { useEffect, useState } from 'react';
import moment from "moment"
import Service from "@/common/js/service"; import Service from "@/common/js/service";
import BaseService from "@/domains/basic-domain/baseService"; import BaseService from "@/domains/basic-domain/baseService";
import User from "@/common/js/user"; import User from "@/common/js/user";
import { LIVE_SHARE } from "@/domains/course-domain/constants"; import { LIVE_SHARE } from "@/domains/course-domain/constants";
import moment from 'moment';
import { Modal, message } from 'antd'; import { Modal, message } from 'antd';
import './CollegeManagePage.less'; import './CollegeManagePage.less';
import storage from '@/common/js/storage';
const roleMap = { const roleMap = {
CloudManager: "管理员", CloudManager: "管理员",
...@@ -14,6 +15,97 @@ const roleMap = { ...@@ -14,6 +15,97 @@ const roleMap = {
CloudOperator: '运营师', CloudOperator: '运营师',
}; };
function ExpirationPopover(props) {
const [showType, setShowType] = useState(0); //0不显示,1剩余30天,2小于等于7天,3已过期
useEffect(()=> {
if (props.surplusDayTime === 0 ) {
//已过期
let loginflag = storage.get("expiration_tip_login")
if (loginflag === null || loginflag === "true") {
//只有登陆进来的时候提示一次
setShowType(3)
}
return
}
//即将过期
if (props.surplusDayTime === 30 || props.surplusDayTime <= 7) {
let daysflag = storage.get("expiration_tip"+User.getUserId()+"_days")
if (daysflag === null || daysflag !== moment().format("YYYYMMDD")) {
setShowType(2)
}
}
// if (props.surplusDayTime === 30) {
// if (storage.get("expiration_tip"+User.getUserId()+"_thirty") == null || storage.get("expiration_tip"+User.getUserId()+"_thirty") === "true") {
// setShowType(1)
// }
// return
// }
// if (props.surplusDayTime <= 7) {
// let daysflag = storage.getObj("expiration_tip"+User.getUserId()+"_7day");
// if (!daysflag) {
// setShowType(2)
// return
// }
// if (daysflag[props.surplusDayTime - 1] === 0) {
// setShowType(2)
// }
// }
},[props.endTime,props.surplusDayTime])
function iknow() {
storage.set("expiration_tip_login",false)
storage.set("expiration_tip"+User.getUserId()+"_days",moment().format("YYYYMMDD"))
/*
if (props.surplusDayTime === 0 ) {
//已过期
storage.set("expiration_tip_login",false)
} else if (props.surplusDayTime === 30) {
storage.set("expiration_tip"+User.getUserId()+"_thirty",false)
} else if (props.surplusDayTime <= 7) {
let daysflag = [0,0,0,0,0,0,0]
daysflag[props.surplusDayTime - 1] = 1
storage.setObj("expiration_tip"+User.getUserId()+"_7day",daysflag)
}
*/
setShowType(0)
}
if (props.surplusDayTime > 30) {
return ("")
}
return (
<>
{
showType === 0 ? ("") :(
<div className="expirationpopover">
<div className="dialog">
<div className="title">{props.surplusDayTime === 0 ? "服务已到期":"服务到期提醒"}</div>
{
showType === 3 ? (
<div className="tip-text">当前企业购买的小麦企学院服务已于<span style={{color:"#FF4F4F"}}>{moment(props.endTime).format("YYYY-MM-DD HH:mm:ss")}</span>到期,到期后仍可访问,但功能不可使用,建议尽快续费购买哦~</div>
) : (
<div className="tip-text">当前企业购买的小麦企学院服务 <span style={{color:"#FF4F4F"}}>仅剩{props.surplusDayTime}</span>(于<span>{moment(props.endTime).format("YYYY-MM-DD")}</span>到期),为了不影响使用,建议尽快续费购买哦~</div>
)
}
<div className="qrcode">
<img src="https://cdn.xiaomai5.com/qixueyuankehu.png" 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>
咨询电话:19157875632</div>
<div className="button" onClick={iknow}>我知道了</div>
</div>
</div>
)
}
</>
)
}
export default class CollegeManagePage extends React.Component { export default class CollegeManagePage extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
...@@ -24,13 +116,16 @@ export default class CollegeManagePage extends React.Component { ...@@ -24,13 +116,16 @@ export default class CollegeManagePage extends React.Component {
enterpriseId: User.getEnterpriseId(), enterpriseId: User.getEnterpriseId(),
isAdmin: false, isAdmin: false,
createStoreList:[], createStoreList:[],
joinStoreList:[] joinStoreList:[],
surplusDayTime:365, //剩余天数
endTime: 0, //有效截至时间
}; };
} }
componentDidMount() { componentDidMount() {
this.getStoreList(); this.getStoreList();
this.getEnterpriseUser(); this.getEnterpriseUser();
this.getVersion()
} }
getEnterpriseUser() { getEnterpriseUser() {
...@@ -44,6 +139,18 @@ export default class CollegeManagePage extends React.Component { ...@@ -44,6 +139,18 @@ export default class CollegeManagePage extends React.Component {
this.setState({ name, avatar, isAdmin }) this.setState({ name, avatar, isAdmin })
}); });
} }
getVersion() {
BaseService.getLesseeVersionMsg()
.then(res=> {
User.setVersion(res.result)
User.setExpirationTime(res.result.validEndTime)
this.setState({
surplusDayTime: res.result.stateEnum === "NO" ? 0 : res.result.surplusDayTime,
endTime: res.result.validEndTime
})
})
}
getStoreList() { getStoreList() {
const { enterpriseId } = this.state; const { enterpriseId } = this.state;
...@@ -132,6 +239,7 @@ export default class CollegeManagePage extends React.Component { ...@@ -132,6 +239,7 @@ export default class CollegeManagePage extends React.Component {
} = this.state; } = this.state;
return ( return (
<div className="college-manage-page"> <div className="college-manage-page">
<ExpirationPopover surplusDayTime={this.state.surplusDayTime} endTime={this.state.endTime}/>
<div className="college-header"> <div className="college-header">
<div className="box"> <div className="box">
<img className="box-image" src="https://image.xiaomaiketang.com/xm/fe4NCjr7XF.png" /> <img className="box-image" src="https://image.xiaomaiketang.com/xm/fe4NCjr7XF.png" />
......
...@@ -183,4 +183,78 @@ ...@@ -183,4 +183,78 @@
} }
} }
} }
.expirationpopover {
display: flex;
justify-content: center;
align-items: center;
position: absolute;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background-color: rgba(0,0,0,0.7);
z-index: 1000;
.dialog {
width: 560px;
height: 486px;
background: #FFFFFF;
border-radius: 4px;
.title {
text-align: center;
font-size: 20px;
color: #333333;
font-weight: 500;
margin-top: 40px;
}
.tip-text {
font-size: 16px;
color: #666666;
font-weight: 400;
margin-top: 16px;
margin-right: 40px;
margin-left: 40px;
}
.qrcode {
width: 182px;
height: 204px;
background: #F1F3F6;
border-radius: 2px;
margin-top: 16px;
margin-left: auto;
margin-right: auto;
img {
width: 150px;
height: 150px;
margin: 16px 16px 8px 16px;
}
.des {
text-align: center;
font-size: 14px;
color: #333333;
font-weight: 400;
}
}
.phone {
text-align: center;
font-size: 14px;
color: #333333;
font-weight: 400;
margin-top: 16px;
}
.button {
width: 80px;
height: 32px;
background: #2966FF;
cursor: pointer;
margin-left: auto;
margin-right: auto;
margin-top: 24px;
font-size: 14px;
font-weight: 400;
color: #ffffff;
line-height: 32px;
text-align: center;
}
}
}
} }
\ No newline at end of file
...@@ -346,7 +346,7 @@ ...@@ -346,7 +346,7 @@
width: 216px; width: 216px;
height: 260px; height: 260px;
top: 49px; top: 49px;
left: 0; left: -50px;
background-color: #fff; background-color: #fff;
flex-wrap: wrap; flex-wrap: wrap;
box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 0.1); box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 0.1);
......
...@@ -7,6 +7,7 @@ import User from '@/common/js/user'; ...@@ -7,6 +7,7 @@ import User from '@/common/js/user';
import WechatLogin from './WechatLogin'; import WechatLogin from './WechatLogin';
import BaseService from '@/domains/basic-domain/baseService'; import BaseService from '@/domains/basic-domain/baseService';
import axios from 'axios'; import axios from 'axios';
import storage from '@/common/js/storage';
import _ from 'underscore'; import _ from 'underscore';
import user from '@/common/js/user'; import user from '@/common/js/user';
const { TabPane } = Tabs; const { TabPane } = Tabs;
...@@ -34,6 +35,7 @@ function Login(props) { ...@@ -34,6 +35,7 @@ function Login(props) {
User.removeUserId(); User.removeUserId();
User.removeToken(); User.removeToken();
User.removeEnterpriseId(); User.removeEnterpriseId();
storage.set("expiration_tip_login",true)
}, []); }, []);
function getWXWorkLoginNoCheck(enterpriseId, userId) { function getWXWorkLoginNoCheck(enterpriseId, userId) {
const params = { const params = {
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
@active-color: #2966ff; @active-color: #2966ff;
.left-container { .left-container {
position: absolute; position: absolute;
z-index: 2; z-index: 10;
top: @top-height; top: @top-height;
left: 0; left: 0;
bottom: 0; bottom: 0;
...@@ -51,12 +51,13 @@ ...@@ -51,12 +51,13 @@
display: -webkit-flex; display: -webkit-flex;
flex-direction: column; flex-direction: column;
-webkit-flex-direction: column; -webkit-flex-direction: column;
height: calc(~'100% - 60px');
.nav { .nav {
-webkit-flex: 1; -webkit-flex: 1;
cursor: default; cursor: default;
font-size: 16px; font-size: 16px;
height: calc(~'100% - 72px'); height: calc(~'100% - 84px');
overflow: auto; overflow: auto;
&::-webkit-scrollbar { &::-webkit-scrollbar {
display: none; display: none;
...@@ -134,6 +135,121 @@ ...@@ -134,6 +135,121 @@
color: #5e606a; color: #5e606a;
} }
} }
.version-info {
// position: absolute;
height: 84px;
bottom: 0;
width: 180px;
cursor: pointer;
// z-index: 10;
padding-top: 10px;
background-color: white;
.row-1 {
width: fit-content;
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #999999;
line-height: 20px;
margin: 0 auto;
.version-name {
display: inline-block;
width: 58px;
text-align: center;
color: #333333;
margin: 0 auto;
border-radius: 2px;
border: 1px solid #E8E8E8;
}
.renew {
display: inline-block;
width: 58px;
color: #2966FF;
margin-left: 8px;
}
}
.expiration-time {
height: 24px;
text-align: center;
font-size: 12px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #999999;
line-height: 22px;
margin: 6px auto 0 auto;
}
.popover {
display: none;
position: absolute;
z-index: 100;
padding: 16px 22px;
bottom: 22px;
width: 352px;
height: 198px;
right: -342px;
background: #FFFFFF;
box-shadow: 0px 2px 15px 0px rgba(0, 0, 0, 0.06);
.title {
display: inline-block;
width: 68px;
height: 22px;
font-size: 16px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #333333;
line-height: 22px;
margin-right: 8px;
}
.expiration-tag {
display: inline-block;
width: 52px;
height: 18px;
background: #EEEEEE;
border-radius: 2px;
text-align: center;
font-size: 12px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #999999;
line-height: 17px;
}
&::before {
position: absolute;
content: "";
width: 16px;
height: 16px;
left: -8px;
top: 80%;
border: 8px solid transparent;
box-shadow: 0px 2px 15px 0px rgba(0, 0, 0, 0.06);
}
.content {
margin-top: 24px;
.widget {
display: inline-block;
}
.lable {
font-size: 14px;
font-weight: 400;
color: #999999;
line-height: 22px;
}
.lable-text {
margin-top: 4px;
font-size: 16px;
font-weight: 500;
color: #333333;
line-height: 22px;
}
}
}
.popover-show {
display: block;
}
}
} }
&.left-container-vertical { &.left-container-vertical {
...@@ -155,7 +271,9 @@ ...@@ -155,7 +271,9 @@
// display:inline-block; // display:inline-block;
// } // }
// } // }
} }
.ant-menu:not(.ant-menu-horizontal) .ant-menu-item-selected { .ant-menu:not(.ant-menu-horizontal) .ant-menu-item-selected {
background: @active-color !important; background: @active-color !important;
} }
......
import User from '@/common/js/user'; import React, { Key, useContext, useEffect, useRef, useState, useMemo } from 'react';
import {
withRouter,
} from 'react-router-dom';
import { Menu, Popover, Tooltip } from 'antd';
import { RightOutlined } from '@ant-design/icons';
import { menuList } from '../../routes//config/menuList';
import { XMContext, VersionContext } from '../../store/context';
import BaseService from '@/domains/basic-domain/baseService';
import StoreService from '@/domains/store-domain/storeService'; import StoreService from '@/domains/store-domain/storeService';
import { Menu } from 'antd'; import classNames from 'classnames';
import React, { Key, useContext, useEffect, useMemo, useState } from 'react'; import User from "@/common/js/user"
import { withRouter } from 'react-router-dom';
import _ from 'underscore'; import _ from 'underscore';
import { menuList } from '../../routes//config/menuList'; import "./Menu.less";
import { XMContext } from '../../store/context'; import { display } from 'html2canvas/dist/types/css/property-descriptors/display';
import './Menu.less'; import ContactWidget from '@/components/ContactWidget';
const { SubMenu } = Menu; const { SubMenu } = Menu;
function VersionPanel(props: any) {
const [versionName, setVersionName] = useState('标准版');
const [showVersionPopover, setShowVersionPopover] = useState(false);
const [showRenewPopover, setShowRenewPopover] = useState(false);
const versionInfo = useContext(VersionContext);
function onVersionEnter() {
setShowVersionPopover(true)
}
function onVersionLeave() {
setShowVersionPopover(false)
setShowRenewPopover(false)
}
function onRenewClick() {
setShowRenewPopover(true)
setShowVersionPopover(false)
}
const versionPopoverClass = classNames({
'popover':true,
'popover-show':showVersionPopover
})
return (
<div className='version-info' onMouseEnter={onVersionEnter} onMouseLeave={onVersionLeave}>
<div className='row-1'>
<div className='version-name'>{versionName}</div>
<ContactWidget trigger='click' placement='rightBottom' visible={showRenewPopover}>
<div className='renew' onClick={onRenewClick}>
去续费
<span className='icon iconfont' style={{ fontSize: '10px' }}>
&#59291;
</span>
</div>
</ContactWidget>
</div>
<div className='expiration-time'>
有效期至{versionInfo?.validEndTime}
{versionInfo?.stateEnum === "NO" ? '(已过期)' : ''}
</div>
<div className={versionPopoverClass}>
<div className='title'>版本信息</div>
{versionInfo?.stateEnum === "NO" ? <div className='expiration-tag'>已过期</div> : ''}
<div className='content'>
<div className='widget' style={{ marginRight: '26px', marginBottom: '16px', width: '70px' }}>
<div className='lable'>剩余天数</div>
<div className='lable-text'>{versionInfo?.surplusDayTime}</div>
</div>
<div className='widget' style={{ marginBottom: '16px', width:"212px"}}>
<div className='lable'>有效起止日期</div>
<div className='lable-text'>
{versionInfo?.validStartTimeST === versionInfo?.validEndTimeST ? "-" : `${versionInfo?.validStartTime}~${versionInfo?.validEndTime}`}
</div>
</div>
<div className='widget' style={{ marginRight: '26px', marginBottom: '8px', width: '70px' }}>
<div className='lable'>剩余人数</div>
<div className='lable-text'>{versionInfo?.surplusUserNum}</div>
</div>
<div className='widget' style={{ marginBottom: '8px' }}>
<div className='lable' style={{ display: 'inline-block' }}>
人数限制
</div>
<Tooltip
overlayStyle={{ maxWidth: '587px', width: '587px' }}
placement='topLeft'
arrowPointAtCenter
title={() => {
return (
<div>
<div>1、若员工/学员存在多个学院,企业人数只统计为1人;</div>
<div>2、若一个学员既用「企业微信」登录学习又用「微信」登录学习,企业人数将统计为2人。</div>
</div>
);
}}>
<div style={{ display: 'inline-block', position: 'relative', top: '2px', marginLeft: '4px' }}>
<span>
<svg viewBox='0 0 1024 1024' version='1.1' xmlns='http://www.w3.org/2000/svg' p-id='1026' width='14' height='14'>
<path
d='M512 68.266667c245.111467 0 443.733333 198.656 443.733333 443.733333s-198.621867 443.733333-443.733333 443.733333C266.922667 955.733333 68.266667 757.077333 68.266667 512S266.922667 68.266667 512 68.266667z m29.320533 596.548266c0.477867-27.989333 2.4576-48.196267 5.802667-60.654933 3.413333-12.458667 8.567467-23.4496 15.633067-33.0752 6.997333-9.557333 21.9136-24.507733 44.714666-44.714667 33.928533-30.037333 56.797867-55.637333 68.437334-76.5952a139.1616 139.1616 0 0 0 17.5104-68.846933c0-43.008-16.5888-79.701333-49.800534-110.011733-33.1776-30.378667-77.6192-45.533867-133.358933-45.533867-52.6336 0-94.958933 14.1312-126.976 42.3936-31.9488 28.2624-51.268267 68.949333-57.685333 122.094933l71.8848 8.533334c6.212267-39.6288 19.3536-68.778667 39.3216-87.483734 19.933867-18.6368 44.817067-27.989333 74.6496-27.989333 30.788267 0 56.900267 10.308267 78.165333 30.9248 21.265067 20.5824 31.880533 44.544 31.880533 71.748267 0 15.018667-3.618133 28.910933-10.922666 41.608533-7.168 12.731733-22.971733 29.764267-47.240534 51.131733-24.200533 21.367467-41.028267 37.649067-50.346666 48.810667-12.6976 15.291733-21.9136 30.481067-27.613867 45.533867-7.748267 19.933867-11.639467 43.690667-11.639467 71.133866 0 4.676267 0.1024 11.707733 0.341334 21.026134h67.242666z m8.192 140.3904v-79.735466h-79.701333v79.735466h79.701333z'
fill='#bfbfbf'
p-id='1027'></path>
</svg>
</span>
</div>
</Tooltip>
<div className='lable-text'>{versionInfo?.userNum}</div>
</div>
</div>
</div>
</div>
)
}
function Aside(props: any) { function Aside(props: any) {
const { menuType, handleMenuType } = props; const { menuType, handleMenuType } = props;
const ctx: any = useContext(XMContext); const ctx: any = useContext(XMContext);
...@@ -178,7 +281,11 @@ function Aside(props: any) { ...@@ -178,7 +281,11 @@ function Aside(props: any) {
})} })}
</Menu> </Menu>
</div> </div>
</div> {
menuType ? <VersionPanel /> : ""
}
</div>
</div> </div>
); );
} }
......
...@@ -21,7 +21,8 @@ import Bus from '@/core/bus'; ...@@ -21,7 +21,8 @@ import Bus from '@/core/bus';
import _ from 'underscore'; import _ from 'underscore';
import { Route, withRouter } from 'react-router-dom'; import { Route, withRouter } from 'react-router-dom';
import * as paperEmpty from '../../lottie/paperEmpty/data.json'; import * as paperEmpty from '../../lottie/paperEmpty/data.json';
import AddExam from '@/modules/teach-tool/examination-manager/AddExam'; import AddExam from "@/modules/teach-tool/examination-manager/AddExam";
import BatchScore from "./components/BatchScore";
const questionTypeEnum = { const questionTypeEnum = {
SINGLE_CHOICE: '单选题', SINGLE_CHOICE: '单选题',
...@@ -59,7 +60,8 @@ class OperatePaper extends Component { ...@@ -59,7 +60,8 @@ class OperatePaper extends Component {
}, },
selectQuestionModal: null, selectQuestionModal: null,
paperPreviewModal: null, paperPreviewModal: null,
quickSortModalVisible: false, // 快捷排序弹窗显隐 quickSortModalVisible: false, // 快捷排序弹窗显隐
batchSetScoreVisible: false, //批量设置题型分数
selectQuestionList: [], selectQuestionList: [],
currentOperate: '', currentOperate: '',
currentNav: '', currentNav: '',
...@@ -85,6 +87,38 @@ class OperatePaper extends Component { ...@@ -85,6 +87,38 @@ class OperatePaper extends Component {
typeKey: 'INDEFINITE_CHOICE', typeKey: 'INDEFINITE_CHOICE',
}, },
], ],
scoreRule: [
{
typeKey: "SINGLE_CHOICE",
score: 2,
portionScore: 0,
totalQuestion: 0,
},
{
typeKey: "MULTI_CHOICE",
score: 2,
portionScore: 0,
totalQuestion: 0,
},
{
typeKey: "JUDGE",
score: 2,
portionScore: 0,
totalQuestion: 0,
},
{
typeKey: "GAP_FILLING",
score: 2,
portionScore: 0,
totalQuestion: 0,
},
{
typeKey: "INDEFINITE_CHOICE",
score: 2,
portionScore: 0,
totalQuestion: 0,
},
]
}; };
} }
...@@ -191,6 +225,29 @@ class OperatePaper extends Component { ...@@ -191,6 +225,29 @@ class OperatePaper extends Component {
}, 0); }, 0);
const passScore = Math.round(totalScore * formData.passRate * 0.01); const passScore = Math.round(totalScore * formData.passRate * 0.01);
let _scorerule = _.map(this.state.scoreRule,(item)=> {
switch(item.typeKey) {
case "SINGLE_CHOICE":
item.totalQuestion = singleQuestion.length;
break;
case "MULTI_CHOICE":
item.totalQuestion = multiQuestion.length;
break;
case "JUDGE":
item.totalQuestion = judgeQuestion.length;
break;
case "GAP_FILLING":
item.totalQuestion = gapQuestion.length;
break;
case "INDEFINITE_CHOICE":
item.totalQuestion = indefiniteQuestion.length;
break;
default:
item.totalQuestion = 0
break;
}
return item
})
this.setState({ this.setState({
formData: { formData: {
...formData, ...formData,
...@@ -208,6 +265,7 @@ class OperatePaper extends Component { ...@@ -208,6 +265,7 @@ class OperatePaper extends Component {
questionCnt: _selectQuestionList.length, questionCnt: _selectQuestionList.length,
totalScore, totalScore,
}, },
scoreRule:_scorerule,
}); });
}; };
...@@ -218,9 +276,11 @@ class OperatePaper extends Component { ...@@ -218,9 +276,11 @@ class OperatePaper extends Component {
<SelectQuestionModal <SelectQuestionModal
getSelectedQuestion={selectQuestionList} getSelectedQuestion={selectQuestionList}
setSelectedQuestion={(list) => { setSelectedQuestion={(list) => {
//按分数规则给每一题重新设置分数(只对新增题目有效)
let _list = this.setScoreByRule(list)
this.setState({ selectQuestionModal: null }, () => { this.setState({ selectQuestionModal: null }, () => {
this.setFormData(list); this.setFormData(_list);
this.quickSorter(list, sorterMethod, sorterBy); this.quickSorter(_list, sorterMethod, sorterBy);
}); });
}} }}
close={() => { close={() => {
...@@ -233,6 +293,25 @@ class OperatePaper extends Component { ...@@ -233,6 +293,25 @@ class OperatePaper extends Component {
this.setState({ selectQuestionModal: m }); this.setState({ selectQuestionModal: m });
}; };
setScoreByRule = (list) => {
//按批量设置分数规则给每一题重新设置分数(只对新增题目有效)
return _.map(list, (item)=> {
let exist = _.find(this.state.selectQuestionList, (q)=> {
return q.questionId === item.questionId
})
if (exist) {
return item
}
let rule = _.find(this.state.scoreRule,(g)=> {
return g.typeKey === item.questionType
})
if (rule) {
item.score = rule.score
item.portionScore = rule.portionScore
}
return item
})
}
// 移动已选题目 // 移动已选题目
handleMoveItem = (index, moveLength) => { handleMoveItem = (index, moveLength) => {
const selectQuestionList = [...this.state.selectQuestionList]; const selectQuestionList = [...this.state.selectQuestionList];
...@@ -499,7 +578,13 @@ class OperatePaper extends Component { ...@@ -499,7 +578,13 @@ class OperatePaper extends Component {
min={1} min={1}
max={100} max={100}
value={record.score || 2} value={record.score || 2}
formatter={value => parseInt(value)}
parser={value => parseInt(value)}
onChange={(value) => { onChange={(value) => {
value = Math.round(value)
if (value <= record.portionScore) {
return
}
const _selectQuestionList = [...selectQuestionList]; const _selectQuestionList = [...selectQuestionList];
this.setState( this.setState(
{ {
...@@ -523,9 +608,12 @@ class OperatePaper extends Component { ...@@ -523,9 +608,12 @@ class OperatePaper extends Component {
{record.questionType === 'GAP_FILLING' ? <span>半对得</span> : <span>漏选得</span>}{' '} {record.questionType === 'GAP_FILLING' ? <span>半对得</span> : <span>漏选得</span>}{' '}
<InputNumber <InputNumber
min={0} min={0}
max={record.score - 1} max={ record.score <= 0 ? 0 : record.score - 1}
formatter={value => parseInt(value)}
parser={value => parseInt(value)}
value={record.portionScore || 0} value={record.portionScore || 0}
onChange={(value) => { onChange={(value) => {
value = Math.round(value)
const _selectQuestionList = [...selectQuestionList]; const _selectQuestionList = [...selectQuestionList];
this.setState( this.setState(
{ {
...@@ -581,6 +669,52 @@ class OperatePaper extends Component { ...@@ -581,6 +669,52 @@ class OperatePaper extends Component {
return columns; return columns;
}; };
//
onBatchScoreOK = (rules) => {
this.setState({
batchSetScoreVisible:false,
scoreRule:rules
},()=> {
let questionList = _.map(this.state.selectQuestionList,(item)=> {
let rule = _.find(this.state.scoreRule,(s)=> {
return s.typeKey === item.questionType
})
if (rule) {
item.score = rule.score
item.portionScore = rule.portionScore
}
return item
})
// 各类型题目总分值
const { formData, scoreRule } = this.state
const {singleChoiceCnt, multiChoiceCnt, judgeCnt, gapFillingCnt, indefiniteChoiceCnt} = formData
const singleChoiceScore = singleChoiceCnt*scoreRule.find((item)=> {return item.typeKey === "SINGLE_CHOICE"}).score
const multiChoiceScore = multiChoiceCnt*scoreRule.find((item)=> {return item.typeKey === "MULTI_CHOICE"}).score
const judgeScore = judgeCnt*scoreRule.find((item)=> {return item.typeKey === "JUDGE"}).score
const gapFillingScore = gapFillingCnt*scoreRule.find((item)=> {return item.typeKey === "GAP_FILLING"}).score
const indefiniteChoiceScore = indefiniteChoiceCnt*scoreRule.find((item)=> {return item.typeKey === "INDEFINITE_CHOICE"}).score
const totalScore = questionList.reduce((prev, cur) => {
return prev + Number(cur.score) || 0;
}, 0);
const passScore = Math.round(totalScore * formData.passRate * 0.01);
this.setState({
selectQuestionList:questionList,
formData: {
...formData,
singleChoiceScore,
multiChoiceScore,
judgeScore,
gapFillingScore,
indefiniteChoiceScore,
totalScore,
passScore,
}
})
message.success("设置成功")
})
}
// 上下移题型 // 上下移题型
handleMoveTypeSorter = (index, moveLength) => { handleMoveTypeSorter = (index, moveLength) => {
const sorterTypeList = [...this.state.sorterTypeList]; const sorterTypeList = [...this.state.sorterTypeList];
...@@ -719,6 +853,7 @@ class OperatePaper extends Component { ...@@ -719,6 +853,7 @@ class OperatePaper extends Component {
max={100} max={100}
value={passRate} value={passRate}
onChange={(value) => { onChange={(value) => {
value = Math.round(value)
this.setState( this.setState(
{ {
formData: { formData: {
...@@ -752,22 +887,36 @@ class OperatePaper extends Component { ...@@ -752,22 +887,36 @@ class OperatePaper extends Component {
}}> }}>
快捷排序 快捷排序
</Button> </Button>
<Button
className="choose-btn"
onClick={() => {
this.setState({
batchSetScoreVisible: true,
});
}}
>
批量设置分数
</Button>
</Space> </Space>
{questionCnt > 0 && ( {questionCnt > 0 && (
<div className='paper-info-tip' style={{ margin: '0 auto 12px' }}> <div className='paper-info-tip' style={{ margin: '0 auto 12px' }}>
总计<span>{totalScore}</span>分,共 总计<span>{totalScore}</span>分,共
<span>{questionCnt}</span> <span>{questionCnt}</span>
题。 {singleChoiceCnt > 0 && `单选题${singleChoiceCnt}题,共${singleChoiceScore}分;`} 题。{" "}
{multiChoiceCnt > 0 && `多选题${multiChoiceCnt}题,共${multiChoiceScore}分;`} {singleChoiceCnt > 0 &&
{judgeCnt > 0 && `判断题${judgeCnt}题,共${judgeScore}分,`} `单选题${singleChoiceCnt}题,共${singleChoiceScore}分;`}
{gapFillingCnt > 0 && `填空题${gapFillingCnt}题,共${gapFillingScore}分,`} {multiChoiceCnt > 0 &&
{indefiniteChoiceCnt > 0 && `不定项选择题${indefiniteChoiceCnt}题,共${indefiniteChoiceScore}分`} `多选题${multiChoiceCnt}题,共${multiChoiceScore}分;`}
{judgeCnt > 0 && `判断题${judgeCnt}题,共${judgeScore}分;`}
{gapFillingCnt > 0 &&
`填空题${gapFillingCnt}题,共${gapFillingScore}分;`}
{indefiniteChoiceCnt > 0 &&
`不定项选择题${indefiniteChoiceCnt}题,共${indefiniteChoiceScore}分;`}
</div> </div>
)} )}
<XMTable <XMTable
className='table-style' className='table-style'
scroll={{ y: 350 }}
columns={this.parseColumns()} columns={this.parseColumns()}
dataSource={selectQuestionList} dataSource={selectQuestionList}
pagination={false} pagination={false}
...@@ -829,6 +978,13 @@ class OperatePaper extends Component { ...@@ -829,6 +978,13 @@ class OperatePaper extends Component {
/> />
)} )}
</Modal> </Modal>
{/* 批量设置分数规则 */}
<BatchScore
visible={this.state.batchSetScoreVisible}
onOK={this.onBatchScoreOK}
onCancel={()=> this.setState({batchSetScoreVisible:false})}
rules={this.state.scoreRule}
/>
</div> </div>
<Route <Route
path={`${match.url}/exam-operate-page`} path={`${match.url}/exam-operate-page`}
......
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
.table-style { .table-style {
border: 1px solid #f0f0f0 !important; border: 1px solid #f0f0f0 !important;
margin-bottom: 70px; margin-bottom: 70px;
max-height: calc(~'100vh - 465px');
overflow: scroll;
} }
.ant-tabs { .ant-tabs {
color: #666666; color: #666666;
......
.batchscore {
.content {
.item {
display: flex;
width: 612px;
height: 48px;
background: #F7F8F9;
font-size: 14px;
line-height: 48px;
font-weight: 400;
color: #333333;
padding-left: 16px;
.type {
width: 112px;
}
.score {
margin-left: 8px;
margin-right: 29px;
width: 258px;
}
}
.item:not(:last-of-type) {
margin-bottom: 8px;
}
}
}
\ No newline at end of file
import React, { useEffect, useState} from "react";
import { Modal, Button, InputNumber, message } from 'antd';
import "./BatchScore.less"
import _ from "underscore";
interface Rule {
typeKey: "GAP_FILLING"|"INDEFINITE_CHOICE"| "JUDGE"|"MULTI_CHOICE"|"SINGLE_CHOICE",
score: number,
portionScore: number,
totalQuestion: number,
}
interface BatchScoreProps {
visible:boolean,
rules: Rule[],
onOK: (rules:Rule[]) => void,
onCancel: () => void,
}
export default function BatchScore(props:BatchScoreProps) {
const [rules, setRules] = useState<Rule[]>(_.sortBy(props.rules,"typeKey"))
const [singleCount, setSingleCount] = useState<number[]>([0])
const [multiCount, setMultiCount] = useState<number[]>([0])
const [judgeCount, setJudgeCount] = useState<number[]>([0])
const [gapCount, setgapCount] = useState<number[]>([0])
const [indefiniteCount, setIndefiniteCount] = useState<number[]>([0])
useEffect(()=> {
_.map(props.rules,(item)=> {
//更新分数统计
switch(item.typeKey) {
case "SINGLE_CHOICE":
setSingleCount([item.totalQuestion,item.totalQuestion*item.score])
break;
case "MULTI_CHOICE":
setMultiCount([item.totalQuestion,item.totalQuestion*item.score])
break;
case "JUDGE":
setJudgeCount([item.totalQuestion,item.totalQuestion*item.score])
break;
case "GAP_FILLING":
setgapCount([item.totalQuestion,item.totalQuestion*item.score])
break;
case "INDEFINITE_CHOICE":
setIndefiniteCount([item.totalQuestion,item.totalQuestion*item.score])
break;
default:
break;
}
})
},[props.rules,rules])
if (!props.visible) {
return ("")
}
function onOk() {
for (let i = 0;i < rules.length;++i) {
if (rules[i].score <= 0 || rules[i].score > 100) {
message.error("分值设置错误")
return;
}
}
props.onOK(rules)
}
function onCancel() {
props.onCancel()
}
const inputNumberStyle = {width:"57px",margin:"0 8px"}
return (
<Modal
className="batchscore"
title="批量设置分数"
onCancel={onCancel}
onOk={onOk}
visible={props.visible}
maskClosable={false}
width={660}
>
<div className="content">
<div className="item">
<span className="type">【单选题】</span>
<span className="score">每题
<InputNumber
min={1}
max={100}
value={rules[4].score}
defaultValue={rules[4].score}
style={inputNumberStyle}
formatter={(value:number|undefined) => String(value)}
parser={(value:string|undefined) => parseInt(String(value))}
onChange={(v)=> {
v = Math.round(v)
let _rules = [...rules]
rules[4].score = v
setRules(_rules)
}}
/>
</span>
<span className="total"><span style={{color:"#2966FF"}}>{singleCount[0]}</span>题,合计<span style={{color:"#2966FF"}}>{singleCount[1]}</span></span>
</div>
<div className="item">
<span className="type">【多选题】</span>
<span className="score">每题
<InputNumber
min={1}
max={100}
defaultValue={rules[3].score}
value={rules[3].score}
style={inputNumberStyle}
formatter={(value:number|undefined) => String(value)}
parser={(value:string|undefined) => parseInt(String(value))}
onChange={(v)=> {
v = Math.round(v)
if (v <= rules[3].portionScore) {
return
}
let _r = [...rules]
_r[3].score = v
setRules(_r)
}}
/>
分,漏选得
<InputNumber
min={0}
max={rules[3].score <= 0 ? 0 : rules[3].score-1}
defaultValue={rules[3].portionScore}
value={rules[3].portionScore}
style={inputNumberStyle}
formatter={(value:number|undefined) => String(value)}
parser={(value:string|undefined) => parseInt(String(value))}
onChange={(v)=> {
v = Math.round(v)
let _r = [...rules]
_r[3].portionScore = v
setRules(_r)
}}
/>
</span>
<span className="total"><span style={{color:"#2966FF"}}>{multiCount[0]}</span>题,合计<span style={{color:"#2966FF"}}>{multiCount[1]}</span></span>
</div>
<div className="item">
<span className="type">【不定项选择题】</span>
<span className="score">每题
<InputNumber
min={1}
max={100}
defaultValue={rules[1].score}
value={rules[1].score}
style={inputNumberStyle}
formatter={(value:number|undefined) => String(value)}
parser={(value:string|undefined) => parseInt(String(value))}
onChange={(v)=> {
v = Math.round(v)
if (v <= rules[1].portionScore) {
return
}
let _r = [...rules]
_r[1].score = v
setRules(_r)
}}
/>
分,漏选得
<InputNumber
min={0}
max={rules[1].score <= 0 ? 0 : rules[1].score-1}
defaultValue={rules[1].portionScore}
value={rules[1].portionScore}
style={inputNumberStyle}
formatter={(value:number|undefined) => String(value)}
parser={(value:string|undefined) => parseInt(String(value))}
onChange={(v)=> {
v = Math.round(v)
let _r = [...rules]
_r[1].portionScore = v
setRules(_r)
}}
/></span>
<span className="total"><span style={{color:"#2966FF"}}>{indefiniteCount[0]}</span>题,合计<span style={{color:"#2966FF"}}>{indefiniteCount[1]}</span></span>
</div>
<div className="item">
<span className="type">【判断题】</span>
<span className="score">每题
<InputNumber
min={1}
max={100}
defaultValue={rules[2].score}
value={rules[2].score}
style={inputNumberStyle}
formatter={(value:number|undefined) => String(value)}
parser={(value:string|undefined) => parseInt(String(value))}
onChange={(v)=> {
v = Math.round(v)
let _r = [...rules]
_r[2].score = v
setRules(_r)
}}
/>
</span>
<span className="total"><span style={{color:"#2966FF"}}>{judgeCount[0]}</span>题,合计<span style={{color:"#2966FF"}}>{judgeCount[1]}</span></span>
</div>
<div className="item">
<span className="type">【填空题】</span>
<span className="score">每题
<InputNumber
min={1}
max={100}
defaultValue={rules[0].score}
value={rules[0].score}
style={inputNumberStyle}
formatter={(value:number|undefined) => String(value)}
parser={(value:string|undefined) => parseInt(String(value))}
onChange={(v)=> {
v = Math.round(v)
if (v <= rules[0].portionScore) {
return
}
let _r = [...rules]
_r[0].score = v
setRules(_r)
}}
/>
分,半对得<InputNumber
min={0}
max={rules[0].score <= 0 ? 0 : rules[0].score-1}
defaultValue={rules[0].portionScore}
value={rules[0].portionScore}
style={inputNumberStyle}
formatter={(value:number|undefined) => String(value)}
parser={(value:string|undefined) => parseInt(String(value))}
onChange={(v)=> {
v = Math.round(v)
let _r = [...rules]
_r[0].portionScore = v
setRules(_r)
}}
/>
</span>
<span className="total"><span style={{color:"#2966FF"}}>{gapCount[0]}</span>题,合计<span style={{color:"#2966FF"}}>{gapCount[1]}</span></span>
</div>
</div>
</Modal>
)
}
\ No newline at end of file
...@@ -11,6 +11,7 @@ import { Modal, Button, message, Spin } from "antd"; ...@@ -11,6 +11,7 @@ import { Modal, Button, message, Spin } from "antd";
import "./BatchImportQuestionModal.less"; import "./BatchImportQuestionModal.less";
import SelectPrepareFileModal from "@/modules/prepare-lesson/modal/SelectPrepareFileModal"; import SelectPrepareFileModal from "@/modules/prepare-lesson/modal/SelectPrepareFileModal";
import User from "@/common/js/user"; import User from "@/common/js/user";
import moment from "moment";
import AidToolService from "@/domains/aid-tool-domain/AidToolService"; import AidToolService from "@/domains/aid-tool-domain/AidToolService";
import { LoadingOutlined } from "@ant-design/icons"; import { LoadingOutlined } from "@ant-design/icons";
class BatchImportQuestionModal extends Component { class BatchImportQuestionModal extends Component {
...@@ -48,6 +49,15 @@ class BatchImportQuestionModal extends Component { ...@@ -48,6 +49,15 @@ class BatchImportQuestionModal extends Component {
// 导入 // 导入
handleImport = async () => { handleImport = async () => {
//过期判断
if (User.getExpirationTime() && moment().valueOf() > Number(User.getExpirationTime())) {
Modal.warning({
title:"服务已到期",
content: "当前企业购买的小麦企学院服务已到期,如需继续使用学院功能,请尽快续费购买",
okText: "我知道了"
})
return
}
const { uploadFile } = this.state; const { uploadFile } = this.state;
if (!uploadFile) { if (!uploadFile) {
message.warning("请选择要导入的文件"); message.warning("请选择要导入的文件");
......
...@@ -7,4 +7,19 @@ ...@@ -7,4 +7,19 @@
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/ */
import React from 'react'; import React from 'react';
export const XMContext: any = React.createContext(null);
\ No newline at end of file export interface VersionInfo {
dayTime: number; //有效时长
stateEnum: string; //"NO"已过期,"YES"未过期
surplusDayTime: number; //剩余有效天数
surplusUserNum: number; //剩余限制人数
userNum: number; //限制人数
validEndTime: string;
validStartTime: string;
validEndTimeST: number;
validStartTimeST: number;
whetherReachUserNum: boolean;
}
export const XMContext: any = React.createContext(null);
export const VersionContext = React.createContext<VersionInfo|null>(null)
\ No newline at end of file
...@@ -2451,10 +2451,10 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: ...@@ -2451,10 +2451,10 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0:
"@types/color-name" "^1.1.1" "@types/color-name" "^1.1.1"
color-convert "^2.0.1" color-convert "^2.0.1"
antd@^4.9.4: antd@4.16.5:
version "4.15.6" version "4.16.5"
resolved "https://registry.yarnpkg.com/antd/-/antd-4.15.6.tgz#bc4359b8f232c8bbb073d7236446edc9aa658d38" resolved "https://registry.nlark.com/antd/download/antd-4.16.5.tgz#6105bd848fb2e468e0d1d3ec024c82d2516587ef"
integrity sha512-uXn1uRFlPLrAmjfkyxKc3avMVO5N30o3YoSMSJPRw5OLNjOfWsnZDPKvZwinn+QQE9N7dRXylcMfNvl11LH2gA== integrity sha1-YQW9hI+y5Gjg0dPsAkyC0lFlh+8=
dependencies: dependencies:
"@ant-design/colors" "^6.0.0" "@ant-design/colors" "^6.0.0"
"@ant-design/icons" "^4.6.2" "@ant-design/icons" "^4.6.2"
...@@ -2474,10 +2474,10 @@ antd@^4.9.4: ...@@ -2474,10 +2474,10 @@ antd@^4.9.4:
rc-field-form "~1.20.0" rc-field-form "~1.20.0"
rc-image "~5.2.4" rc-image "~5.2.4"
rc-input-number "~7.1.0" rc-input-number "~7.1.0"
rc-mentions "~1.5.0" rc-mentions "~1.6.1"
rc-menu "~8.10.0" rc-menu "~9.0.12"
rc-motion "^2.4.0" rc-motion "^2.4.0"
rc-notification "~4.5.2" rc-notification "~4.5.7"
rc-pagination "~3.1.6" rc-pagination "~3.1.6"
rc-picker "~2.5.10" rc-picker "~2.5.10"
rc-progress "~3.1.0" rc-progress "~3.1.0"
...@@ -2487,15 +2487,15 @@ antd@^4.9.4: ...@@ -2487,15 +2487,15 @@ antd@^4.9.4:
rc-slider "~9.7.1" rc-slider "~9.7.1"
rc-steps "~4.1.0" rc-steps "~4.1.0"
rc-switch "~3.2.0" rc-switch "~3.2.0"
rc-table "~7.13.0" rc-table "~7.15.1"
rc-tabs "~11.7.0" rc-tabs "~11.9.1"
rc-textarea "~0.3.0" rc-textarea "~0.3.0"
rc-tooltip "~5.1.1" rc-tooltip "~5.1.1"
rc-tree "~4.1.0" rc-tree "~4.1.0"
rc-tree-select "~4.3.0" rc-tree-select "~4.3.0"
rc-trigger "^5.2.1" rc-trigger "^5.2.1"
rc-upload "~4.3.0" rc-upload "~4.3.0"
rc-util "^5.9.4" rc-util "^5.13.1"
scroll-into-view-if-needed "^2.2.25" scroll-into-view-if-needed "^2.2.25"
warning "^4.0.3" warning "^4.0.3"
...@@ -3552,6 +3552,11 @@ classnames@2.x, classnames@^2.2.1, classnames@^2.2.3, classnames@^2.2.5, classna ...@@ -3552,6 +3552,11 @@ classnames@2.x, classnames@^2.2.1, classnames@^2.2.3, classnames@^2.2.5, classna
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce" resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce"
integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q== integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==
classnames@^2.3.1:
version "2.3.1"
resolved "https://registry.npm.taobao.org/classnames/download/classnames-2.3.1.tgz#dfcfa3891e306ec1dad105d0e88f4417b8535e8e"
integrity sha1-38+jiR4wbsHa0QXQ6I9EF7hTXo4=
clean-css@^4.2.3: clean-css@^4.2.3:
version "4.2.3" version "4.2.3"
resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.3.tgz#507b5de7d97b48ee53d84adb0160ff6216380f78" resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.3.tgz#507b5de7d97b48ee53d84adb0160ff6216380f78"
...@@ -3927,6 +3932,17 @@ cosmiconfig@^6.0.0: ...@@ -3927,6 +3932,17 @@ cosmiconfig@^6.0.0:
path-type "^4.0.0" path-type "^4.0.0"
yaml "^1.7.2" yaml "^1.7.2"
cosmiconfig@^7.0.0:
version "7.0.0"
resolved "https://registry.npm.taobao.org/cosmiconfig/download/cosmiconfig-7.0.0.tgz?cache=0&sync_timestamp=1596310773001&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcosmiconfig%2Fdownload%2Fcosmiconfig-7.0.0.tgz#ef9b44d773959cae63ddecd122de23853b60f8d3"
integrity sha1-75tE13OVnK5j3ezRIt4jhTtg+NM=
dependencies:
"@types/parse-json" "^4.0.0"
import-fresh "^3.2.1"
parse-json "^5.0.0"
path-type "^4.0.0"
yaml "^1.10.0"
create-ecdh@^4.0.0: create-ecdh@^4.0.0:
version "4.0.3" version "4.0.3"
resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.3.tgz#c9111b6f33045c4697f144787f9254cdc77c45ff" resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.3.tgz#c9111b6f33045c4697f144787f9254cdc77c45ff"
...@@ -5750,12 +5766,20 @@ find-up@^3.0.0: ...@@ -5750,12 +5766,20 @@ find-up@^3.0.0:
dependencies: dependencies:
locate-path "^3.0.0" locate-path "^3.0.0"
find-versions@^3.2.0: find-up@^5.0.0:
version "3.2.0" version "5.0.0"
resolved "https://registry.yarnpkg.com/find-versions/-/find-versions-3.2.0.tgz#10297f98030a786829681690545ef659ed1d254e" resolved "https://registry.npm.taobao.org/find-up/download/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc"
integrity sha512-P8WRou2S+oe222TOCHitLy8zj+SIsVJh52VP4lvXkaFVnOFFdoWv1H1Jjvel1aI6NCFOAaeAVm8qrI0odiLcww== integrity sha1-TJKBnstwg1YeT0okCoa+UZj1Nvw=
dependencies: dependencies:
semver-regex "^2.0.0" locate-path "^6.0.0"
path-exists "^4.0.0"
find-versions@^4.0.0:
version "4.0.0"
resolved "https://registry.nlark.com/find-versions/download/find-versions-4.0.0.tgz?cache=0&sync_timestamp=1619599444272&other_urls=https%3A%2F%2Fregistry.nlark.com%2Ffind-versions%2Fdownload%2Ffind-versions-4.0.0.tgz#3c57e573bf97769b8cb8df16934b627915da4965"
integrity sha1-PFflc7+XdpuMuN8Wk0tieRXaSWU=
dependencies:
semver-regex "^3.1.2"
flat-cache@^2.0.1: flat-cache@^2.0.1:
version "2.0.1" version "2.0.1"
...@@ -6352,7 +6376,7 @@ hmac-drbg@^1.0.0: ...@@ -6352,7 +6376,7 @@ hmac-drbg@^1.0.0:
minimalistic-assert "^1.0.0" minimalistic-assert "^1.0.0"
minimalistic-crypto-utils "^1.0.1" minimalistic-crypto-utils "^1.0.1"
hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.2: hoist-non-react-statics@^3.1.0:
version "3.3.2" version "3.3.2"
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
...@@ -6554,18 +6578,18 @@ humanize-ms@^1.2.0, humanize-ms@^1.2.1: ...@@ -6554,18 +6578,18 @@ humanize-ms@^1.2.0, humanize-ms@^1.2.1:
dependencies: dependencies:
ms "^2.0.0" ms "^2.0.0"
husky@^4.2.5: husky@^4.3.0:
version "4.2.5" version "4.3.8"
resolved "https://registry.yarnpkg.com/husky/-/husky-4.2.5.tgz#2b4f7622673a71579f901d9885ed448394b5fa36" resolved "https://registry.npm.taobao.org/husky/download/husky-4.3.8.tgz?cache=0&sync_timestamp=1617004245593&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhusky%2Fdownload%2Fhusky-4.3.8.tgz#31144060be963fd6850e5cc8f019a1dfe194296d"
integrity sha512-SYZ95AjKcX7goYVZtVZF2i6XiZcHknw50iXvY7b0MiGoj5RwdgRQNEHdb+gPDPCXKlzwrybjFjkL6FOj8uRhZQ== integrity sha1-MRRAYL6WP9aFDlzI8Bmh3+GUKW0=
dependencies: dependencies:
chalk "^4.0.0" chalk "^4.0.0"
ci-info "^2.0.0" ci-info "^2.0.0"
compare-versions "^3.6.0" compare-versions "^3.6.0"
cosmiconfig "^6.0.0" cosmiconfig "^7.0.0"
find-versions "^3.2.0" find-versions "^4.0.0"
opencollective-postinstall "^2.0.2" opencollective-postinstall "^2.0.2"
pkg-dir "^4.2.0" pkg-dir "^5.0.0"
please-upgrade-node "^3.2.0" please-upgrade-node "^3.2.0"
slash "^3.0.0" slash "^3.0.0"
which-pm-runs "^1.0.0" which-pm-runs "^1.0.0"
...@@ -6649,6 +6673,14 @@ import-fresh@^3.0.0, import-fresh@^3.1.0: ...@@ -6649,6 +6673,14 @@ import-fresh@^3.0.0, import-fresh@^3.1.0:
parent-module "^1.0.0" parent-module "^1.0.0"
resolve-from "^4.0.0" resolve-from "^4.0.0"
import-fresh@^3.2.1:
version "3.3.0"
resolved "https://registry.npm.taobao.org/import-fresh/download/import-fresh-3.3.0.tgz?cache=0&sync_timestamp=1608469579940&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fimport-fresh%2Fdownload%2Fimport-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b"
integrity sha1-NxYsJfy566oublPVtNiM4X2eDCs=
dependencies:
parent-module "^1.0.0"
resolve-from "^4.0.0"
import-from@^2.1.0: import-from@^2.1.0:
version "2.1.0" version "2.1.0"
resolved "https://registry.yarnpkg.com/import-from/-/import-from-2.1.0.tgz#335db7f2a7affd53aaa471d4b8021dee36b7f3b1" resolved "https://registry.yarnpkg.com/import-from/-/import-from-2.1.0.tgz#335db7f2a7affd53aaa471d4b8021dee36b7f3b1"
...@@ -8088,6 +8120,13 @@ locate-path@^5.0.0: ...@@ -8088,6 +8120,13 @@ locate-path@^5.0.0:
dependencies: dependencies:
p-locate "^4.1.0" p-locate "^4.1.0"
locate-path@^6.0.0:
version "6.0.0"
resolved "https://registry.npm.taobao.org/locate-path/download/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286"
integrity sha1-VTIeswn+u8WcSAHZMackUqaB0oY=
dependencies:
p-locate "^5.0.0"
lodash._reinterpolate@^3.0.0: lodash._reinterpolate@^3.0.0:
version "3.0.0" version "3.0.0"
resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d"
...@@ -8406,14 +8445,6 @@ mini-css-extract-plugin@0.9.0: ...@@ -8406,14 +8445,6 @@ mini-css-extract-plugin@0.9.0:
schema-utils "^1.0.0" schema-utils "^1.0.0"
webpack-sources "^1.1.0" webpack-sources "^1.1.0"
mini-store@^3.0.1:
version "3.0.6"
resolved "https://registry.yarnpkg.com/mini-store/-/mini-store-3.0.6.tgz#44b86be5b2877271224ce0689b3a35a2dffb1ca9"
integrity sha512-YzffKHbYsMQGUWQRKdsearR79QsMzzJcDDmZKlJBqt5JNkqpyJHYlK6gP61O36X+sLf76sO9G6mhKBe83gIZIQ==
dependencies:
hoist-non-react-statics "^3.3.2"
shallowequal "^1.0.2"
minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7"
...@@ -9083,6 +9114,13 @@ p-limit@^2.3.0: ...@@ -9083,6 +9114,13 @@ p-limit@^2.3.0:
dependencies: dependencies:
p-try "^2.0.0" p-try "^2.0.0"
p-limit@^3.0.2:
version "3.1.0"
resolved "https://registry.nlark.com/p-limit/download/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b"
integrity sha1-4drMvnjQ0TiMoYxk/qOOPlfjcGs=
dependencies:
yocto-queue "^0.1.0"
p-locate@^2.0.0: p-locate@^2.0.0:
version "2.0.0" version "2.0.0"
resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43"
...@@ -9104,6 +9142,13 @@ p-locate@^4.1.0: ...@@ -9104,6 +9142,13 @@ p-locate@^4.1.0:
dependencies: dependencies:
p-limit "^2.2.0" p-limit "^2.2.0"
p-locate@^5.0.0:
version "5.0.0"
resolved "https://registry.nlark.com/p-locate/download/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834"
integrity sha1-g8gxXGeFAF470CGDlBHJ4RDm2DQ=
dependencies:
p-limit "^3.0.2"
p-map@^2.0.0: p-map@^2.0.0:
version "2.1.0" version "2.1.0"
resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175"
...@@ -9439,13 +9484,20 @@ pkg-dir@^3.0.0: ...@@ -9439,13 +9484,20 @@ pkg-dir@^3.0.0:
dependencies: dependencies:
find-up "^3.0.0" find-up "^3.0.0"
pkg-dir@^4.1.0, pkg-dir@^4.2.0: pkg-dir@^4.1.0:
version "4.2.0" version "4.2.0"
resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3"
integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==
dependencies: dependencies:
find-up "^4.0.0" find-up "^4.0.0"
pkg-dir@^5.0.0:
version "5.0.0"
resolved "https://registry.nlark.com/pkg-dir/download/pkg-dir-5.0.0.tgz#a02d6aebe6ba133a928f74aec20bafdfe6b8e760"
integrity sha1-oC1q6+a6EzqSj3Suwguv3+a452A=
dependencies:
find-up "^5.0.0"
pkg-up@3.1.0, pkg-up@^3.1.0: pkg-up@3.1.0, pkg-up@^3.1.0:
version "3.1.0" version "3.1.0"
resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-3.1.0.tgz#100ec235cc150e4fd42519412596a28512a0def5" resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-3.1.0.tgz#100ec235cc150e4fd42519412596a28512a0def5"
...@@ -10518,7 +10570,7 @@ rc-drawer@~4.3.0: ...@@ -10518,7 +10570,7 @@ rc-drawer@~4.3.0:
classnames "^2.2.6" classnames "^2.2.6"
rc-util "^5.7.0" rc-util "^5.7.0"
rc-dropdown@^3.1.3, rc-dropdown@~3.2.0: rc-dropdown@^3.2.0, rc-dropdown@~3.2.0:
version "3.2.0" version "3.2.0"
resolved "https://registry.yarnpkg.com/rc-dropdown/-/rc-dropdown-3.2.0.tgz#da6c2ada403842baee3a9e909a0b1a91ba3e1090" resolved "https://registry.yarnpkg.com/rc-dropdown/-/rc-dropdown-3.2.0.tgz#da6c2ada403842baee3a9e909a0b1a91ba3e1090"
integrity sha512-j1HSw+/QqlhxyTEF6BArVZnTmezw2LnSmRk6I9W7BCqNCKaRwleRmMMs1PHbuaG8dKHVqP6e21RQ7vPBLVnnNw== integrity sha512-j1HSw+/QqlhxyTEF6BArVZnTmezw2LnSmRk6I9W7BCqNCKaRwleRmMMs1PHbuaG8dKHVqP6e21RQ7vPBLVnnNw==
...@@ -10555,30 +10607,29 @@ rc-input-number@~7.1.0: ...@@ -10555,30 +10607,29 @@ rc-input-number@~7.1.0:
classnames "^2.2.5" classnames "^2.2.5"
rc-util "^5.9.8" rc-util "^5.9.8"
rc-mentions@~1.5.0: rc-mentions@~1.6.1:
version "1.5.3" version "1.6.1"
resolved "https://registry.yarnpkg.com/rc-mentions/-/rc-mentions-1.5.3.tgz#b92bebadf8ad9fb3586ba1af922d63b49d991c67" resolved "https://registry.nlark.com/rc-mentions/download/rc-mentions-1.6.1.tgz?cache=0&sync_timestamp=1621867143484&other_urls=https%3A%2F%2Fregistry.nlark.com%2Frc-mentions%2Fdownload%2Frc-mentions-1.6.1.tgz#46035027d64aa33ef840ba0fbd411871e34617ae"
integrity sha512-NG/KB8YiKBCJPHHvr/QapAb4f9YzLJn7kDHtmI1K6t7ZMM5YgrjIxNNhoRKKP9zJvb9PdPts69Hbg4ZMvLVIFQ== integrity sha1-RgNQJ9ZKoz74QLoPvUEYceNGF64=
dependencies: dependencies:
"@babel/runtime" "^7.10.1" "@babel/runtime" "^7.10.1"
classnames "^2.2.6" classnames "^2.2.6"
rc-menu "^8.0.1" rc-menu "^9.0.0"
rc-textarea "^0.3.0" rc-textarea "^0.3.0"
rc-trigger "^5.0.4" rc-trigger "^5.0.4"
rc-util "^5.0.1" rc-util "^5.0.1"
rc-menu@^8.0.1, rc-menu@^8.6.1, rc-menu@~8.10.0: rc-menu@^9.0.0, rc-menu@~9.0.12:
version "8.10.8" version "9.0.12"
resolved "https://registry.yarnpkg.com/rc-menu/-/rc-menu-8.10.8.tgz#c3eb2158b3983e42a67192babad9c8128755d26a" resolved "https://registry.nlark.com/rc-menu/download/rc-menu-9.0.12.tgz#492c4bb07a596e2ce07587c669b27ee28c3810c5"
integrity sha512-0gnSR0nmR/60NnK+72EGd+QheHyPSQ3wYg1TwX1zl0JJ9Gm0purFFykCXVv/G0Jynpt0QySPAos+bpHpjMZdoQ== integrity sha1-SSxLsHpZbizgdYfGabJ+4ow4EMU=
dependencies: dependencies:
"@babel/runtime" "^7.10.1" "@babel/runtime" "^7.10.1"
classnames "2.x" classnames "2.x"
mini-store "^3.0.1" rc-motion "^2.4.3"
rc-motion "^2.0.1" rc-overflow "^1.2.0"
rc-trigger "^5.1.2" rc-trigger "^5.1.2"
rc-util "^5.7.0" rc-util "^5.12.0"
resize-observer-polyfill "^1.5.0"
shallowequal "^1.1.0" shallowequal "^1.1.0"
rc-motion@^2.0.0, rc-motion@^2.0.1, rc-motion@^2.2.0, rc-motion@^2.3.0, rc-motion@^2.3.4, rc-motion@^2.4.0: rc-motion@^2.0.0, rc-motion@^2.0.1, rc-motion@^2.2.0, rc-motion@^2.3.0, rc-motion@^2.3.4, rc-motion@^2.4.0:
...@@ -10590,10 +10641,19 @@ rc-motion@^2.0.0, rc-motion@^2.0.1, rc-motion@^2.2.0, rc-motion@^2.3.0, rc-motio ...@@ -10590,10 +10641,19 @@ rc-motion@^2.0.0, rc-motion@^2.0.1, rc-motion@^2.2.0, rc-motion@^2.3.0, rc-motio
classnames "^2.2.1" classnames "^2.2.1"
rc-util "^5.2.1" rc-util "^5.2.1"
rc-notification@~4.5.2: rc-motion@^2.4.3:
version "4.5.5" version "2.4.4"
resolved "https://registry.yarnpkg.com/rc-notification/-/rc-notification-4.5.5.tgz#9660a495d5f20bd677686e4f7fc00e4f0c1a3849" resolved "https://registry.nlark.com/rc-motion/download/rc-motion-2.4.4.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Frc-motion%2Fdownload%2Frc-motion-2.4.4.tgz#e995d5fa24fc93065c24f714857cf2677d655bb0"
integrity sha512-YIfhTSw+h5GsSdgMnuMx24wqiPlg3FeamuOlkh9RkyHx+SeZVAKzQ0juy2NGvPEF2hDWi5xTqxUqLdo0L2AmGg== integrity sha1-6ZXV+iT8kwZcJPcUhXzyZ31lW7A=
dependencies:
"@babel/runtime" "^7.11.1"
classnames "^2.2.1"
rc-util "^5.2.1"
rc-notification@~4.5.7:
version "4.5.7"
resolved "https://registry.nlark.com/rc-notification/download/rc-notification-4.5.7.tgz#265e6e6a0c1a0fac63d6abd4d832eb8ff31522f1"
integrity sha1-Jl5uagwaD6xj1qvU2DLrj/MVIvE=
dependencies: dependencies:
"@babel/runtime" "^7.10.1" "@babel/runtime" "^7.10.1"
classnames "2.x" classnames "2.x"
...@@ -10610,6 +10670,16 @@ rc-overflow@^1.0.0: ...@@ -10610,6 +10670,16 @@ rc-overflow@^1.0.0:
rc-resize-observer "^1.0.0" rc-resize-observer "^1.0.0"
rc-util "^5.5.1" rc-util "^5.5.1"
rc-overflow@^1.2.0:
version "1.2.2"
resolved "https://registry.nlark.com/rc-overflow/download/rc-overflow-1.2.2.tgz#95b0222016c0cdbdc0db85f569c262e7706a5f22"
integrity sha1-lbAiIBbAzb3A24X1acJi53BqXyI=
dependencies:
"@babel/runtime" "^7.11.1"
classnames "^2.2.1"
rc-resize-observer "^1.0.0"
rc-util "^5.5.1"
rc-pagination@~3.1.6: rc-pagination@~3.1.6:
version "3.1.6" version "3.1.6"
resolved "https://registry.yarnpkg.com/rc-pagination/-/rc-pagination-3.1.6.tgz#db3c06e50270b52fe272ac527c1fdc2c8d28af1f" resolved "https://registry.yarnpkg.com/rc-pagination/-/rc-pagination-3.1.6.tgz#db3c06e50270b52fe272ac527c1fdc2c8d28af1f"
...@@ -10700,26 +10770,26 @@ rc-switch@~3.2.0: ...@@ -10700,26 +10770,26 @@ rc-switch@~3.2.0:
classnames "^2.2.1" classnames "^2.2.1"
rc-util "^5.0.1" rc-util "^5.0.1"
rc-table@~7.13.0: rc-table@~7.15.1:
version "7.13.3" version "7.15.2"
resolved "https://registry.yarnpkg.com/rc-table/-/rc-table-7.13.3.tgz#25d5f5ec47ee2d8a293aff18c4c4b8876f78c22b" resolved "https://registry.nlark.com/rc-table/download/rc-table-7.15.2.tgz#f6ab73b2cfb1c76f3cf9682c855561423c6b5b22"
integrity sha512-oP4fknjvKCZAaiDnvj+yzBaWcg+JYjkASbeWonU1BbrLcomkpKvMUgPODNEzg0QdXA9OGW0PO86h4goDSW06Kg== integrity sha1-9qtzss+xx288+WgshVVhQjxrWyI=
dependencies: dependencies:
"@babel/runtime" "^7.10.1" "@babel/runtime" "^7.10.1"
classnames "^2.2.5" classnames "^2.2.5"
rc-resize-observer "^1.0.0" rc-resize-observer "^1.0.0"
rc-util "^5.4.0" rc-util "^5.13.0"
shallowequal "^1.1.0" shallowequal "^1.1.0"
rc-tabs@~11.7.0: rc-tabs@~11.9.1:
version "11.7.3" version "11.9.1"
resolved "https://registry.yarnpkg.com/rc-tabs/-/rc-tabs-11.7.3.tgz#32a30e59c6992d60fb58115ba0bf2652b337ed43" resolved "https://registry.nlark.com/rc-tabs/download/rc-tabs-11.9.1.tgz?cache=0&sync_timestamp=1621867452307&other_urls=https%3A%2F%2Fregistry.nlark.com%2Frc-tabs%2Fdownload%2Frc-tabs-11.9.1.tgz#5b2e74da9a276978c2172ef9a05ae8af14da74cb"
integrity sha512-5nd2NVss9TprPRV9r8N05SjQyAE7zDrLejxFLcbJ+BdLxSwnGnk3ws/Iq0smqKZUnPQC0XEvnpF3+zlllUUT2w== integrity sha1-Wy502ponaXjCFy75oFrorxTadMs=
dependencies: dependencies:
"@babel/runtime" "^7.11.2" "@babel/runtime" "^7.11.2"
classnames "2.x" classnames "2.x"
rc-dropdown "^3.1.3" rc-dropdown "^3.2.0"
rc-menu "^8.6.1" rc-menu "^9.0.0"
rc-resize-observer "^1.0.0" rc-resize-observer "^1.0.0"
rc-util "^5.5.0" rc-util "^5.5.0"
...@@ -10800,6 +10870,15 @@ rc-util@^5.0.1: ...@@ -10800,6 +10870,15 @@ rc-util@^5.0.1:
react-is "^16.12.0" react-is "^16.12.0"
shallowequal "^1.1.0" shallowequal "^1.1.0"
rc-util@^5.12.0, rc-util@^5.13.0, rc-util@^5.13.1:
version "5.13.1"
resolved "https://registry.nlark.com/rc-util/download/rc-util-5.13.1.tgz#03e74955b5c46a58cbc6236e4d30dd462c755290"
integrity sha1-A+dJVbXEaljLxiNuTTDdRix1UpA=
dependencies:
"@babel/runtime" "^7.12.5"
react-is "^16.12.0"
shallowequal "^1.1.0"
rc-virtual-list@^3.0.1, rc-virtual-list@^3.2.0: rc-virtual-list@^3.0.1, rc-virtual-list@^3.2.0:
version "3.2.6" version "3.2.6"
resolved "https://registry.yarnpkg.com/rc-virtual-list/-/rc-virtual-list-3.2.6.tgz#2c92a40f4425e19881b38134d6bd286a11137d2d" resolved "https://registry.yarnpkg.com/rc-virtual-list/-/rc-virtual-list-3.2.6.tgz#2c92a40f4425e19881b38134d6bd286a11137d2d"
...@@ -11551,10 +11630,10 @@ semver-compare@^1.0.0: ...@@ -11551,10 +11630,10 @@ semver-compare@^1.0.0:
resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc"
integrity sha1-De4hahyUGrN+nvsXiPavxf9VN/w= integrity sha1-De4hahyUGrN+nvsXiPavxf9VN/w=
semver-regex@^2.0.0: semver-regex@^3.1.2:
version "2.0.0" version "3.1.2"
resolved "https://registry.yarnpkg.com/semver-regex/-/semver-regex-2.0.0.tgz#a93c2c5844539a770233379107b38c7b4ac9d338" resolved "https://registry.nlark.com/semver-regex/download/semver-regex-3.1.2.tgz#34b4c0d361eef262e07199dbef316d0f2ab11807"
integrity sha512-mUdIBBvdn0PLOeP3TEkMH7HHeUP3GjsXCwKarjv/kGmUFOYg1VqEemKhoQpWMu6X2I8kHeuVdGibLGkVK+/5Qw== integrity sha1-NLTA02Hu8mLgcZnb7zFtDyqxGAc=
"semver@2 || 3 || 4 || 5", semver@^5.0.1, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0: "semver@2 || 3 || 4 || 5", semver@^5.0.1, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0:
version "5.7.1" version "5.7.1"
...@@ -11673,7 +11752,7 @@ shallow-clone@^0.1.2: ...@@ -11673,7 +11752,7 @@ shallow-clone@^0.1.2:
lazy-cache "^0.2.3" lazy-cache "^0.2.3"
mixin-object "^2.0.1" mixin-object "^2.0.1"
shallowequal@^1.0.2, shallowequal@^1.1.0: shallowequal@^1.1.0:
version "1.1.0" version "1.1.0"
resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8" resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8"
integrity sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ== integrity sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==
...@@ -13026,17 +13105,17 @@ vary@~1.1.2: ...@@ -13026,17 +13105,17 @@ vary@~1.1.2:
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=
vconsole-webpack-plugin@^1.5.2: vconsole-webpack-plugin@^1.6.1:
version "1.5.2" version "1.6.1"
resolved "https://registry.yarnpkg.com/vconsole-webpack-plugin/-/vconsole-webpack-plugin-1.5.2.tgz#4c25b6cc51add03bb4e1562c4d3653431c89af60" resolved "https://registry.nlark.com/vconsole-webpack-plugin/download/vconsole-webpack-plugin-1.6.1.tgz#7a9ee82c0a90d58964034f6d6bd349242ce65a70"
integrity sha512-v3goAnjsurFUy+qUmJCGjW+tzeKzlkrlbY8YnctSbhbrKiyC40hDeVFdGJvv7Drvd+w4xCQ1hJFZa5ESadmljQ== integrity sha1-ep7oLAqQ1YlkA09ta9NJJCzmWnA=
dependencies: dependencies:
vconsole "^3.3.4" vconsole "^3.6"
vconsole@^3.3.4: vconsole@^3.6:
version "3.6.0" version "3.7.0"
resolved "https://registry.yarnpkg.com/vconsole/-/vconsole-3.6.0.tgz#3affe6082271014f8a169ea429b85c148c2cc796" resolved "https://registry.nlark.com/vconsole/download/vconsole-3.7.0.tgz#7b347fc635eb09646bb50f0ce0cbfba1852af1b1"
integrity sha512-vNyB9AwO0gqGub3BLbj4FtwQjlQ8EwhrD1zfcaAwToP/wKcfAoozJiD+6kAzL85FIklgptERcM+c621IEPuItQ== integrity sha1-ezR/xjXrCWRrtQ8M4Mv7oYUq8bE=
dependencies: dependencies:
copy-text-to-clipboard "^3.0.1" copy-text-to-clipboard "^3.0.1"
core-js "^3.11.0" core-js "^3.11.0"
...@@ -13650,6 +13729,11 @@ yallist@^4.0.0: ...@@ -13650,6 +13729,11 @@ yallist@^4.0.0:
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
yaml@^1.10.0:
version "1.10.2"
resolved "https://registry.nlark.com/yaml/download/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
integrity sha1-IwHF/78StGfejaIzOkWeKeeSDks=
yaml@^1.7.2: yaml@^1.7.2:
version "1.8.2" version "1.8.2"
resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.8.2.tgz#a29c03f578faafd57dcb27055f9a5d569cb0c3d9" resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.8.2.tgz#a29c03f578faafd57dcb27055f9a5d569cb0c3d9"
...@@ -13698,3 +13782,8 @@ yauzl@^2.4.2: ...@@ -13698,3 +13782,8 @@ yauzl@^2.4.2:
dependencies: dependencies:
buffer-crc32 "~0.2.3" buffer-crc32 "~0.2.3"
fd-slicer "~1.1.0" fd-slicer "~1.1.0"
yocto-queue@^0.1.0:
version "0.1.0"
resolved "https://registry.nlark.com/yocto-queue/download/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
integrity sha1-ApTrPe4FAo0x7hpfosVWpqrxChs=
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