Commit ca9abf13 by zhangleyuan

Merge branch 'master' into feature/zahngleyuan/20210607/cloud-cass-remodel

parents 64af316b 2021ecd0
......@@ -105,6 +105,10 @@
},
"scripts": {
"start": "node scripts/start.js",
"start:dev": "cross-env DEPLOY_ENV=dev node scripts/start.js",
"start:dev1": "cross-env DEPLOY_ENV=dev node scripts/start.js",
"start:rc": "cross-env DEPLOY_ENV=rc node scripts/start.js",
"start:gray": "cross-env DEPLOY_ENV=gray node scripts/start.js",
"build:dev": "cross-env DEPLOY_ENV=dev node scripts/build.js",
"build:dev1": "cross-env DEPLOY_ENV=dev node scripts/build.js",
"build:rc": "cross-env DEPLOY_ENV=rc node scripts/build.js",
......
......@@ -80,7 +80,7 @@ class CopyFileModal extends React.Component {
// const { folderPathList, folderList } = this.state;
const { folderPathList, disk } = this.state;
const { dataInfo } = this.props;
const { id, createId, folderName } = dataInfo;
const { id, createId, folderName,folderType} = dataInfo;
const newParentId = folderPathList[folderPathList.length-1].id;
const _params = {
copyIds : [id], // 复制文件的ID
......@@ -99,7 +99,10 @@ class CopyFileModal extends React.Component {
}
return allowCopy;
})
if(folderPathList.length > 9 && folderType === 'FOLDER'){
allowCopy = 1;
message.warning('不能将文件夹复制到10级目录下');
}
if (allowCopy === 0) {
Service.Hades('public/hadesStore/copyFolder', _params).then((res) => {
if (res.success) {
......
......@@ -20,7 +20,8 @@ interface FetchParams {
}
interface FetchOptions {
requestType: string // 请求类型 form为表单类型 json为json类型,默认json类型
requestType: string, // 请求类型 form为表单类型 json为json类型,默认json类型
reject: boolean,
}
interface HeadersType{
storeId?:any,
......@@ -33,7 +34,7 @@ class Axios {
method: string,
url: string,
params: any,
options: FetchOptions = { requestType: 'json' }
options: FetchOptions = { requestType: 'json', reject: false }
): Promise<any> {
const _url = `${url}?storeId=${User.getStoreId()}&token=${User.getToken()}&storeUserId=${User.getStoreUserId()}&userId=${User.getUserId()}`;
return new Promise((resolve, reject) => {
......@@ -86,8 +87,9 @@ class Axios {
const { message: ResMessage, success, resultMsg, resultCode } = response.data;
if (success || resultCode === 0) {
return response;
} else if (!options.reject) {
message.error(ResMessage || resultMsg);
}
message.error(ResMessage || resultMsg);
return Promise.reject(response.data);
}, (error): AxiosPromise => {
const requestStatus = error.request.status
......
......@@ -3,7 +3,7 @@
* @Date: 2020-08-31 09:34:25
* @LastEditors: Please set LastEditors
* @LastEditTime: 2021-05-12 17:27:08
* @Description:
* @Description:
* @Copyright: 杭州杰竞科技有限公司 版权所有
*/
......@@ -11,32 +11,34 @@ import Storage from './storage';
import { PREFIX, USER_PREFIX } from '@/domains/basic-domain/constants';
class User {
getStoreId(){
return Storage.get(`${PREFIX}_storeId`)
getStoreId() {
return Storage.get(`${PREFIX}_storeId`);
}
getEnterpriseId() {
return Storage.get(`${PREFIX}_enterpriseId`)
return Storage.get(`${PREFIX}_enterpriseId`);
}
getStoreName(){
return Storage.get(`${PREFIX}_storeName`)
getStoreName() {
return Storage.get(`${PREFIX}_storeName`);
}
getStoreType(){
return Storage.get(`${PREFIX}_storeType`)
getStoreType() {
return Storage.get(`${PREFIX}_storeType`);
}
getStoreUserId(){
return Storage.get(`${PREFIX}_storeUserId`)
getStoreUserId() {
return Storage.get(`${PREFIX}_storeUserId`);
}
getUserId(){
return Storage.get(`${PREFIX}_userId`)
getCustomerId() {
return Storage.get(`${PREFIX}_customerId`);
}
getUserRole(){
return Storage.get(`${PREFIX}_userRole`)
getUserId() {
return Storage.get(`${PREFIX}_userId`);
}
getUserRole() {
return Storage.get(`${PREFIX}_userRole`);
}
getToken() {
......@@ -47,67 +49,71 @@ class User {
return Storage.get(`${PREFIX}_isAdmin`);
}
setStoreId(value:any){
return Storage.set(`${PREFIX}_storeId`,value)
setStoreId(value: any) {
return Storage.set(`${PREFIX}_storeId`, value);
}
setEnterpriseId(value: any) {
return Storage.set(`${PREFIX}_enterpriseId`,value)
return Storage.set(`${PREFIX}_enterpriseId`, value);
}
setStoreName(value: any) {
return Storage.set(`${PREFIX}_storeName`, value);
}
setStoreName(value:any){
return Storage.set(`${PREFIX}_storeName`,value)
setStoreType(value: any) {
return Storage.set(`${PREFIX}_storeType`, value);
}
setStoreType(value:any){
return Storage.set(`${PREFIX}_storeType`,value)
setStoreUserId(value: any) {
return Storage.set(`${PREFIX}_storeUserId`, value);
}
setStoreUserId(value:any){
return Storage.set(`${PREFIX}_storeUserId`,value)
setCustomerId(value: any) {
return Storage.set(`${PREFIX}_customerId`, value);
}
setUserId(value:any){
return Storage.set(`${PREFIX}_userId`,value)
setUserId(value: any) {
return Storage.set(`${PREFIX}_userId`, value);
}
setUserRole(value:any){
return Storage.set(`${PREFIX}_userRole`,value)
setUserRole(value: any) {
return Storage.set(`${PREFIX}_userRole`, value);
}
setToken(value:any) {
return Storage.set(`${PREFIX}_token`,value);
setToken(value: any) {
return Storage.set(`${PREFIX}_token`, value);
}
setIsAdmin(value: any) {
return Storage.set(`${PREFIX}_isAdmin`, value);
}
removeToken(){
removeToken() {
return Storage.remove(`${PREFIX}_token`);
}
removeUserId(){
removeUserId() {
return Storage.remove(`${PREFIX}_userId`);
}
removeEnterpriseId() {
return Storage.remove(`${PREFIX}_enterpriseId`)
return Storage.remove(`${PREFIX}_enterpriseId`);
}
getCustomerStoreId(){
getCustomerStoreId() {
return Storage.get(`${PREFIX}_customerStoreId`);
}
setCustomerStoreId(value:any) {
return Storage.set(`${PREFIX}_customerStoreId`,value);
setCustomerStoreId(value: any) {
return Storage.set(`${PREFIX}_customerStoreId`, value);
}
setIdentifier(value:any){
return Storage.set(`${PREFIX}_identifier`,value);
setIdentifier(value: any) {
return Storage.set(`${PREFIX}_identifier`, value);
}
getIdentifier(){
getIdentifier() {
return Storage.get(`${PREFIX}_identifier`);
}
clearUserInfo(){
clearUserInfo() {
Storage.remove(`${USER_PREFIX}_token`);
Storage.remove(`${USER_PREFIX}_userId`);
Storage.remove(`${USER_PREFIX}_userPhone`);
......@@ -119,4 +125,4 @@ class User {
}
}
export default new User();
\ No newline at end of file
export default new User();
import React, { useEffect, useState } from 'react';
import { Empty, ConfigProvider, Table } from 'antd';
import Lottie from 'react-lottie';
import * as nodata from '../modules/lottie/nodata/data.json';
function XMTable(props) {
const [empty, setEmpty] = useState(props.renderEmpty || {});
const [data, setData] = useState({});
useEffect(() => {
setEmpty(props.renderEmpty || {})
setData(props);
}, [props]);
// 自定义表格空状态
function customizeRenderEmpty() {
const defaultOptions = {
loop: true,
autoplay: true,
animationData: empty.image || nodata,
rendererSettings: {
preserveAspectRatio: 'xMidYMid slice'
}
}
return (
<Empty
image={<div style={{ marginTop: 24 }}>
<Lottie
options={defaultOptions}
height={150}
width={150}
isStopped={false}
isPaused={false}
/>
</div>}
imageStyle={{
height: 150,
}}
description={empty.description}
></Empty>
);
};
return (
<ConfigProvider className="xm-table-component" renderEmpty={customizeRenderEmpty}>
<Table
{...data}
/>
</ConfigProvider>
)
}
export default XMTable;
\ No newline at end of file
.xm-table-component {
}
\ No newline at end of file
/*
* @Author: wufan
* @Date: 2020-11-26 14:48:57
* @Last Modified by: mikey.zhaopeng
* @Last Modified time: 2020-11-26 14:52:02
* @Last Modified by: chenshu
* @Last Modified time: 2021-06-03 15:21:09
*/
import SearchBar from './SearchBar.tsx';
......@@ -10,6 +10,7 @@ import PageControl from './PageControl.tsx';
import CheckBox from './CheckBox.tsx';
import CropperModal from './CropperModal.tsx';
import ImgCutModalNew from './ImgCutModalNew';
import XMTable from './XMTable';
export {
......@@ -17,5 +18,6 @@ export {
PageControl,
CheckBox,
CropperModal,
ImgCutModalNew
ImgCutModalNew,
XMTable,
}
\ No newline at end of file
......@@ -2,7 +2,7 @@
* @Author: Michael
* @Date: 2017-09-08 17:38:18
* @Last Modified by: chenshu
* @Last Modified time: 2020-08-31 14:55:30
* @Last Modified time: 2021-06-04 18:19:23
*/
@import './variables.less';
......@@ -602,7 +602,7 @@ td.ant-table-column-sort {
background: none;
}
.ant-modal-content .ant-table-thead > tr > th {
padding: 9px 24px;
padding: 9px 24px !important;
}
.ant-modal-content tr > td {
......@@ -766,11 +766,12 @@ td.ant-table-column-sort {
}
}
.ant-table-column-title {
flex: initial !important;
}
// 排序小三角
.ant-table-column-sorter {
margin-left: 2px !important;
}
.ant-table-column-sorter-full {
margin-top: -0.32rem !important;
margin-left: 8px !important;
}
......@@ -7,7 +7,7 @@
left: 0px;
right: 0;
bottom: 0;
z-index:3;
z-index: 3;
background-color: #fff;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
......@@ -20,12 +20,12 @@
bottom: 0;
z-index: 102;
overflow: auto;
margin:0 16px;
.box{
&:first-child{
margin: 0 16px;
.box {
&:first-child {
margin-bottom: 8px;
}
&:last-child{
&:last-child {
margin-bottom: 16px;
}
}
......@@ -48,10 +48,10 @@
.content-header {
padding: 16px 16px 8px 16px;
line-height: 30px;
font-size:24px;
color:#333;
font-weight:bold;
background: #FFF;
font-size: 24px;
color: #333;
font-weight: bold;
background: #fff;
h1 {
font-weight: normal;
display: inline-block;
......
/*
* @Author: 陈剑宇
* @Date: 2020-05-07 14:43:01
* @LastEditTime: 2021-05-28 15:20:40
* @LastEditors: fusanqiasng
* @LastEditTime: 2021-06-11 16:44:17
* @LastEditors: Please set LastEditors
* @Description:
* @FilePath: /wheat-web-demo/src/domains/basic-domain/constants.ts
*/
......
/*
* @Author: 吴文洁
* @Date: 2020-08-20 09:21:40
* @LastEditors: zhangleyuan
* @LastEditTime: 2021-02-20 17:08:58
* @LastEditors: Please set LastEditors
* @LastEditTime: 2021-06-11 15:17:56
* @Description:
* @Copyright: 杭州杰竞科技有限公司 版权所有
*/
......
......@@ -6,9 +6,11 @@
import React from 'react';
import { Modal, Input, Table, message, Tooltip, Empty } from 'antd';
import { XMTable } from '@/components';
import Service from '@/common/js/service';
import User from '@/common/js/user'
import SetEmployeeModal from "./SetEmployeeModal";
import search from '../../lottie/search/data.json';
import './ChooseMembersModal.less';
import _ from 'underscore';
......@@ -311,19 +313,18 @@ class ChooseMembersModal extends React.Component {
enterButton={<span className="icon iconfont">&#xe832;</span>}
/>
<div className='container-left-body-table'>
<Table
<XMTable
rowKey={(record) => record.enterpriseVisibleUserId}
dataSource={allUserList}
columns={this.selectedColumnsLeft()}
pagination={false}
scroll={{ y: 290}}
// bordered={true}
locale={{
emptyText: <div>
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description={false} />
<div style={{ color: '#333', marginTop: -70 }}>暂无数据</div>
renderEmpty={{
image: searchKey ? search : '',
description: <div>
<div style={{ color: '#333' }}>暂无数据</div>
<div style={{ color: '#666', padding: '0 32px', fontSize: '12px' }}>需要先将员工添加到企微可见范围后,员工才会出现在这里</div>
</div>,
</div>
}}
size={'small'}
rowSelection={{
......
/*
* @Author: zhujian
* @Date: 2018-10-10 20:49:11
* @Last Modified by: zhujiapeng
* @Last Modified time: 2020-11-16 17:02:11
* @Last Modified by: chenshu
* @Last Modified time: 2021-06-03 16:42:22
*/
// import './s.less'
......@@ -42,6 +42,7 @@ class DefaultIcon extends React.Component {
preserveAspectRatio: 'xMidYMid slice'
}
}
console.log(defaultOptions, this.props, 777777)
return (
<div style={this.props.style} className="DefaultIcon" key="icon">
<Lottie
......
......@@ -2,7 +2,7 @@
* @Author: 吴文洁
* @Date: 2020-08-05 10:12:45
* @LastEditors: Please set LastEditors
* @LastEditTime: 2021-05-27 20:13:53
* @LastEditTime: 2021-06-15 20:01:05
* @Description: 视频课-列表模块
* @Copyright: 杭州杰竞科技有限公司 版权所有
*/
......@@ -364,7 +364,7 @@ class GraphicsCourseList extends React.Component {
<ShareLiveModal
needStr={needStr}
data={shareData}
type="videoClass"
type="graphicsClass"
title="图文课"
close={() => {
this.setState({
......
/*
* @Author: 吴文洁
* @Date: 2020-06-22 14:26:37
* @Last Modified by: 吴文洁
* @Last Modified time: 2020-07-23 09:33:02
* @Last Modified by: chenshu
* @Last Modified time: 2021-06-08 18:18:46
*/
import React, { useEffect, useState } from 'react';
import { Modal, Button, Table, Progress, message, Tooltip, Spin, Popconfirm } from 'antd';
......@@ -40,7 +40,7 @@ class ManageCoursewareModal extends React.Component {
componentDidMount() {
this.getCoursewareList();
var animation = Lottie.loadAnimation({
path: "https://image.xiaomaiketang.com/xm/MQwp2aJaxf.json",
path: "https://image.xiaomaiketang.com/xm/SDBkP7mbJX.json",
name: "test",
renderer: "svg",
loop: true,
......
......@@ -8,8 +8,8 @@
.empty-image {
display: block;
margin: 24px auto 12px;
width:100px;
height:100px;
width:150px;
height:150px;
}
.empty-button {
display: block;
......
......@@ -18,8 +18,6 @@ import CourseService from '@/domains/course-domain/CourseService'
import './ShareLiveModal.less'
const DEFAULT_COVER = 'https://image.xiaomaiketang.com/xm/YNfi45JwFA.png'
class ShareLiveModal extends React.Component {
constructor(props) {
super(props)
......@@ -54,6 +52,13 @@ class ShareLiveModal extends React.Component {
size: 98,
})
qrcodeWrapDom.appendChild(qrcodeNode)
const qrcodeWrapDomDownload = document.querySelector('#qrcodeWrap-dowload')
const qrcodeNodeDownLoad = new qrcode({
text: this.state.shareUrl,
size: 196,
})
qrcodeWrapDomDownload.appendChild(qrcodeNodeDownLoad)
}
)
})
......@@ -74,13 +79,12 @@ class ShareLiveModal extends React.Component {
() => {
this.setState({ time: new Date().valueOf() }, () => {
setTimeout(() => {
let node = document.getElementById('poster')
let node = document.getElementById('poster-dowload')
domtoimage.toPng(node).then((imgData) => {
console.log(imgData)
const download = document.createElement('a')
const { courseName } = this.props.data
$(download).attr('href', imgData).attr('download', `${courseName}.png`).get(0).click()
// this.props.close()
})
}, 1000)
})
......@@ -98,27 +102,31 @@ class ShareLiveModal extends React.Component {
render() {
const { courseDivision, data, type, title } = this.props
const { courseName, coverUrl = DEFAULT_COVER, scheduleVideoUrl } = data
const { courseName, scheduleVideoUrl, courseMediaVOS, coverUrl } = data
const { shareUrl, showImg, time } = this.state
// 判断是否是默认图, 默认图不需要在URL后面增加字符串
const isDefaultCover = coverUrl === DEFAULT_COVER
let coverImgSrc = coverUrl
if (type === 'videoClass') {
if ((!coverUrl || isDefaultCover) && title !== '图文课' && title !== '线下课') {
if (courseDivision === 'external') {
coverImgSrc = 'https://image.xiaomaiketang.com/xm/mt3ZQRxGKB.png'
let coverImgSrc = '';
switch (type) {
case 'liveClass': // 直播课
if (courseMediaVOS && courseMediaVOS.length > 0) {
data.courseMediaVOS.map((item, index) => {
if (item.contentType === 'COVER') {
coverImgSrc = item.mediaUrl
}
})
} else {
coverImgSrc = `${scheduleVideoUrl}?x-oss-process=video/snapshot,t_0,m_fast&anystring=anystring`
}
}
} else {
data.courseMediaVOS.map((item, index) => {
if (item.contentType === 'COVER') {
coverImgSrc = item.mediaUrl
coverImgSrc = 'https://image.xiaomaiketang.com/xm/Yip2YtFDwH.png';
}
})
break;
case 'videoClass': // 视频课
coverImgSrc = coverUrl || (courseDivision === 'internal' ? `${scheduleVideoUrl}?x-oss-process=video/snapshot,t_0,m_fast&anystring=anystring` : 'https://image.xiaomaiketang.com/xm/mt3ZQRxGKB.png')
break;
case 'graphicsClass': // 图文课
coverImgSrc = coverUrl || 'https://image.xiaomaiketang.com/xm/wFnpZtp2yB.png';
break;
case 'offlineClass': // 线下课
coverImgSrc = coverUrl || 'https://image.xiaomaiketang.com/xm/pxbWKsYA87.png';
break;
}
return (
......@@ -137,7 +145,7 @@ class ShareLiveModal extends React.Component {
<span className='text'>{User.getStoreName()}</span>
</div>
<div className='course-name-title'>{type === 'videoClass' ? `${courseName}开课啦` : `邀请你观看直播:`}</div>
<div className='course-name-title'>{type === 'liveClass' ? `邀请你观看直播:` : `${courseName}开课啦`}</div>
{type === 'liveClass' && <div class='live-couse-name'>{courseName}</div>}
<Choose>
<When condition={showImg}>
......@@ -156,6 +164,29 @@ class ShareLiveModal extends React.Component {
<div className='qrcode-wrap__right' id='qrcodeWrap'></div>
</div>
</div>
<div id='poster-dowload'>
<div className='store-name'>
<span className='text'>{User.getStoreName()}</span>
</div>
<div className='course-name-title'>{type === 'videoClass' ? `${courseName}开课啦` : `邀请你观看直播:`}</div>
{type === 'liveClass' && <div class='live-couse-name'>{courseName}</div>}
<Choose>
<When condition={showImg}>
<img crossOrigin='*' src={coverImgSrc + `?=${time}`} className='course-cover' alt='' />
</When>
<Otherwise>
<img src={coverImgSrc + `?=${time}`} className='course-cover' alt='' />
</Otherwise>
</Choose>
<div className='qrcode-wrap'>
<div className='qrcode-wrap__left'>
<div className='text'>长按识别二维码进入观看</div>
<img className='finger' src='https://image.xiaomaiketang.com/xm/thpkWDwJsC.png' alt='' />
</div>
<div className='qrcode-wrap__right' id='qrcodeWrap-dowload'></div>
</div>
</div>
</div>
<div className='right'>
<div className='share-poster right__item'>
......
.share-live-modal {
.ant-modal-body {
display: flex;
#poster{
background: #FFF;
margin:0;
padding: 20px;
}
height:510px !important;
overflow: hidden !important;
.left {
width: 303px;
margin: 0 32px 0 16px;
box-shadow:0px 2px 10px 0px rgba(0,0,0,0.05);
border-radius: 12px;
.course-name-title {
font-size: 14px;
color: #333;
line-height: 20px;
margin-bottom: 4px;
}
.live-couse-name{
font-size:16px;
color:#333333;
font-weight: 600;
}
.course-name {
#poster{
background: #FFF;
margin:0;
padding: 20px;
margin-bottom:140px;
.course-name-title {
font-size: 14px;
color: #333;
font-size: 16px;
font-weight: 600;
line-height: 20px;
}
.course-cover {
width: 263px;
height: 143px;
border-radius: 6px;
margin-top: 8px;
}
margin-bottom: 4px;
}
.live-couse-name{
font-size:16px;
color:#333333;
font-weight: 600;
}
.course-name {
color: #333;
font-size: 16px;
font-weight: 600;
line-height: 20px;
}
.course-cover {
width: 263px;
height: 143px;
border-radius: 6px;
margin-top: 8px;
}
.qrcode-wrap {
padding: 0 16px;
display: flex;
align-items: center;
margin: 24px 0 16px 0;
.qrcode-wrap {
padding: 0 16px;
display: flex;
align-items: center;
margin: 24px 0 16px 0;
&__left {
width: 98px;
text-align: center;
margin-right: 22px;
.text {
line-height: 20px;
&__left {
width: 98px;
text-align: center;
margin-right: 22px;
.text {
line-height: 20px;
}
.finger {
width: 40px;
height: 40px;
margin-top: 8px;
}
}
.finger {
width: 40px;
height: 40px;
margin-top: 8px;
&__right {
width: 110px;
height: 110px;
padding: 6px
}
}
&__right {
width: 110px;
height: 110px;
padding: 6px
.store-name {
// padding: 8px 16px;
display: flex;
align-items: center;
margin-bottom: 8px;
.text {
font-size: 12px;
color: #999;
font-size: 14px;
line-height: 20px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
width: 100%;
}
}
}
.store-name {
// padding: 8px 16px;
display: flex;
align-items: center;
#poster-dowload{
background: #FFF;
margin:0;
padding: 40px;
width:606px;
.course-name-title {
font-size: 28px;
color: #333;
line-height: 40px;
margin-bottom: 8px;
.text {
font-size: 12px;
color: #999;
font-size: 14px;
line-height: 20px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
width: 100%;
}
.live-couse-name{
font-size:32px;
color:#333333;
font-weight: 600;
}
.course-name {
color: #333;
font-size: 32px;
font-weight: 600;
line-height: 40px;
}
.course-cover {
width: 526px;
height: 286px;
border-radius: 6px;
margin-top: 16px;
}
.qrcode-wrap {
padding: 0 32px;
display: flex;
align-items: center;
margin: 48px 0 32px 0;
&__left {
width: 196px;
text-align: center;
margin-right: 44px;
.text {
line-height: 40px;
}
.finger {
width: 80px;
height: 80px;
margin-top: 16px;
}
}
&__right {
width: 220px;
height: 220px;
padding: 12px
}
}
.store-name {
// padding: 8px 16px;
display: flex;
align-items: center;
margin-bottom: 16px;
.text {
font-size: 24px;
color: #999;
font-size: 28px;
line-height: 40px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
width: 100%;
}
}
}
}
.right {
.title {
color: #333;
......
/*
* @Author: 吴文洁
* @Date: 2020-08-05 10:07:47
* @LastEditors: wufan
* @LastEditTime: 2021-05-27 19:25:48
* @LastEditors: yuananting
* @LastEditTime: 2021-06-07 15:06:26
* @Description: 线下课新增/编辑页
* @Copyright: 杭州杰竞科技有限公司 版权所有
*/
......@@ -518,6 +518,11 @@ class AddOfflineCourse extends React.Component {
if(coverId){
scheduleMediaRequests = [coverObj]
}
// 编辑且使用默认图时不传
if (pageType === 'edit' && coverUrl === defaultCoverUrl) {
scheduleMediaRequests = []
}
const commonParams = {
categoryId,
courseName,
......
......@@ -2,7 +2,7 @@
* @Author: 吴文洁
* @Date: 2020-08-05 10:12:45
* @LastEditors: Please set LastEditors
* @LastEditTime: 2021-05-27 20:14:01
* @LastEditTime: 2021-06-11 16:44:42
* @Description: 视频课-列表模块
* @Copyright: 杭州杰竞科技有限公司 版权所有
*/
......@@ -25,7 +25,7 @@ import QRCodeModal from '../modal/QRCodeModal';
import './OfflineCourseList.less';
const ENV = process.env.DEPLOY_ENV || 'dev';
const defaultCoverUrl = 'https://image.xiaomaiketang.com/xm/YNfi45JwFA.png';
const defaultCoverUrl = 'https://image.xiaomaiketang.com/xm/pxbWKsYA87.png';
class OfflineCourseList extends React.Component {
......@@ -358,7 +358,7 @@ class OfflineCourseList extends React.Component {
<ShareLiveModal
needStr={needStr}
data={shareData}
type="videoClass"
type="offlineClass"
title="线下课"
close={() => {
this.setState({
......
......@@ -6,7 +6,7 @@ import Service from "@/common/js/service";
import './PreviewOfflineModal.less';
import ENUM from '@/modules/knowledge-base/ENUM';
const defaultCoverUrl = 'https://image.xiaomaiketang.com/xm/YNfi45JwFA.png';
const defaultCoverUrl = 'https://image.xiaomaiketang.com/xm/pxbWKsYA87.png';
class PreviewOfflineModal extends React.Component {
......
import React from 'react'
import { Tabs } from 'antd'
import VideoCourseFilter from './components/VideoCourseFilter'
import VideoCourseOpt from './components/VieoCourseOpt'
import VideoCourseList from './components/VideoCourseList'
import CourseService from '@/domains/course-domain/CourseService'
import User from '@/common/js/user'
const { TabPane } = Tabs
import React from 'react';
import { Tabs } from 'antd';
import VideoCourseFilter from './components/VideoCourseFilter';
import VideoCourseOpt from './components/VieoCourseOpt';
import VideoCourseList from './components/VideoCourseList';
import CourseService from '@/domains/course-domain/CourseService';
import User from '@/common/js/user';
const { TabPane } = Tabs;
class VideoCourse extends React.Component {
constructor(props) {
super(props)
super(props);
this.state = {
query: {
size: 10,
......@@ -18,45 +18,43 @@ class VideoCourse extends React.Component {
dataSource: [], // 视频课列表
totalCount: 0, // 视频课数据总条数
currentTabKey: 'internal',
}
};
}
componentWillMount() {
// 获取视频课列表
this.handleFetchScheduleList()
this.handleFetchScheduleList();
}
// 获取视频课列表
handleFetchScheduleList = (_query = {}) => {
const { currentTabKey } = this.state
const { currentTabKey } = this.state;
const query = {
...this.state.query,
..._query,
courseDivision: currentTabKey === 'external' ? 1 : null,
}
// 更新请求参数
this.setState({ query })
};
CourseService.videoSchedulePage(query).then((res) => {
const { result = {} } = res || {}
const { records = [], total = 0 } = result
const { result = {} } = res || {};
const { records = [], total = 0 } = result;
if (Number(total) && query.size * (query.current - 1) >= Number(total)) {
this.handleFetchScheduleList({
...query,
current: 1,
})
return
});
return;
}
this.setState({
query,
dataSource: records,
totalCount: Number(total),
})
})
}
});
});
};
currenTabChange = (currentTabKey) => {
const { query } = this.state
const { query } = this.state;
this.setState(
{
currentTabKey,
......@@ -66,20 +64,21 @@ class VideoCourse extends React.Component {
},
},
() => {
this.handleFetchScheduleList()
console.log('this.state.query===>', this.state.query);
// this.handleFetchScheduleList()
}
)
}
);
};
changeShelfState = (index, shelfState) => {
const { dataSource } = this.state
dataSource[index].shelfState = shelfState
const { dataSource } = this.state;
dataSource[index].shelfState = shelfState;
this.setState({
dataSource,
})
}
});
};
render() {
const { dataSource, totalCount, query, currentTabKey } = this.state
const { dataSource, totalCount, query, currentTabKey } = this.state;
return (
<div className='page video-course-page'>
<div className='content-header'>视频课</div>
......@@ -107,8 +106,8 @@ class VideoCourse extends React.Component {
/>
</div>
</div>
)
);
}
}
export default VideoCourse
export default VideoCourse;
......@@ -12,6 +12,7 @@ import { Input, Button, Tree } from "antd";
import "./Classification.less";
import User from "@/common/js/user";
import KnowledgeAPI from "@/data-source/knowledge/request-api";
import Bus from "@/core/bus";
const { Search } = Input;
const { DirectoryTree } = Tree;
......@@ -31,6 +32,11 @@ class Classification extends Component {
componentDidMount() {
this.queryCategoryTree();
Bus.bind('knowledgeCategoryTree', this.queryCategoryTree)
}
componentWillUnmount() {
Bus.unbind('knowledgeCategoryTree', this.queryCategoryTree)
}
shouldComponentUpdate = (nextProps, nextState) => {
......
......@@ -2,22 +2,22 @@
* @Description:
* @Author: zangsuyun
* @Date: 2021-03-12 14:49:40
* @LastEditors: wufan
* @LastEditTime: 2021-05-30 20:37:42
* @LastEditors: Please set LastEditors
* @LastEditTime: 2021-06-11 16:44:59
* @Copyright: © 2020 杭州杰竞科技有限公司 版权所有
*/
import React from "react"
import { Table, Modal, message, Tooltip, Switch, Dropdown, Button } from "antd"
import { Route, withRouter } from "react-router-dom"
import { PageControl } from "@/components"
import { LIVE_SHARE_MAP } from "@/common/constants/academic/cloudClass"
import { appId, shareUrl, LIVE_SHARE } from "@/domains/course-domain/constants"
import ScanFileModal from "../../resource-disk/modal/ScanFileModal"
import WatchData from "./WatchData"
import KnowledgeAPI from "@/data-source/knowledge/request-api"
import ENUM from "../ENUM.js"
import "./KnowledgeBaseList.less"
import React from "react";
import { Modal, message, Tooltip, Switch, Dropdown, Button } from "antd";
import { Route, withRouter } from "react-router-dom";
import { PageControl, XMTable } from "@/components";
import { LIVE_SHARE_MAP } from "@/common/constants/academic/cloudClass";
import { appId, shareUrl, LIVE_SHARE } from "@/domains/course-domain/constants";
import ScanFileModal from "../../resource-disk/modal/ScanFileModal";
import WatchData from "./WatchData";
import KnowledgeAPI from "@/data-source/knowledge/request-api";
import ENUM from "../ENUM.js";
import "./KnowledgeBaseList.less";
const DEFAULT_SIZE_UNIT = 1000 * 1000 // 将B转换成M
const { confirm } = Modal
......@@ -127,8 +127,7 @@ class KnowledgeBaseList extends React.Component {
// 预览文件
handleScanFile = (folder) => {
console.log(folder)
const { folderFormat, folderSize, ossUrl } = folder
const { folderFormat, folderSize, ossUrl } = folder;
switch (folderFormat) {
case "PDF":
window.open(ossUrl, "_blank")
......@@ -403,7 +402,6 @@ class KnowledgeBaseList extends React.Component {
width: 160,
fixed: "right",
render: (val, record, index) => {
console.log(this.props.categoryId)
return this.props.categoryId === "0" ? (
<div className='operate'>
<div className='operate__item' onClick={() => this.handleDelete(record)}>
......@@ -451,9 +449,8 @@ class KnowledgeBaseList extends React.Component {
// 前往上课数据页面
handleLinkToClassData = (item) => {
const { match } = this.props
console.log(item)
localStorage.setItem("WatchData_CourseName", item.name)
const { match } = this.props;
localStorage.setItem("WatchData_CourseName", item.name);
window.RCHistory.push({
// pathname: `${match.url}/course-data?type=${item.courseType}&id=${item.liveCourseId}`,
pathname: `${match.url}/course-data?type=${item.type}&id=${item.id}`
......@@ -467,9 +464,13 @@ class KnowledgeBaseList extends React.Component {
}
KnowledgeAPI.delKnowledge(params).then((res) => {
if (res.success) {
message.success("移出成功")
this.props.onChange()
this.props.updateCategoryTree()
const { onChange, updateCategoryTree, selectedRowKeys, onSelectChange } = this.props;
message.success("移出成功");
onChange();
updateCategoryTree();
if (selectedRowKeys.includes(item.id)) {
onSelectChange(_.reject(selectedRowKeys, value => value === item.id));
}
}
})
}
......@@ -484,19 +485,28 @@ class KnowledgeBaseList extends React.Component {
}
render() {
const { dataSource = [], totalCount, query, match } = this.props
const { current, size } = query
const { dataSource = [], totalCount, query, match, selectedRowKeys, onSelectChange } = this.props;
const { current, size } = query;
const rowSelection = {
selectedRowKeys,
preserveSelectedRowKeys: true,
onChange: onSelectChange,
}
return (
<div className='knowledge-base-list'>
<Table
<div className="knowledge-base-list">
<XMTable
rowKey={(record) => record.id}
size='middle'
rowSelection={rowSelection}
size="middle"
dataSource={dataSource}
columns={this.parseColumns()}
pagination={false}
scroll={{ x: 900 }}
bordered
className='knowledge-list-table'
className="knowledge-list-table"
renderEmpty={{
description: <span style={{ display: 'block', paddingBottom: 24 }}>暂无数据</span>
}}
/>
<div className='box-footer'>
......
......@@ -9,19 +9,27 @@
import React, { useState, useEffect } from "react";
import { Button, Menu, Dropdown,message } from "antd";
import { Button, Menu, Dropdown,message, Modal } from "antd";
import SelectPrepareFileModal from "@/modules/prepare-lesson/modal/SelectPrepareFileModal";
import { DownOutlined } from "@ant-design/icons";
import AddCourse from "../modal/AddCourse";
import User from "@/common/js/user";
import Service from "@/common/js/service";
import KnowledgeAPI from "@/data-source/knowledge/request-api";
import MoveModal from '../../teach-tool/modal/MoveModal';
import Bus from "@/core/bus";
import './KnowledgeBaseOpt.less';
export default function KnowledgeBaseOpt({
categoryId,
selectedRowKeys,
updateCategoryTree,
onChange,
onChangeKeys,
}) {
const [modal, setModal] = useState(null);
const [openMoveModal, setOpenMoveModal] = useState(false);
const [data, setData] = useState([]);
const menu = (
<Menu>
......@@ -34,6 +42,40 @@ export default function KnowledgeBaseOpt({
</Menu>
);
useEffect(() => {
queryCategoryTree();
}, []);
useEffect(() => {
clearSelect();
}, [categoryId])
// 查询分类树
function queryCategoryTree() {
let query = {
storeId: User.getStoreId(),
withCount: true,
};
KnowledgeAPI.getCategoryTree(query).then((res) => {
const { categoryList = [] } = res.result;
let list = renderTreeNodes(categoryList);
setData(list);
});
}
function renderTreeNodes(data) {
let newTreeData = data.map((item) => {
item.title = item.categoryName;
item.value = item.id;
item.key = item.id;
if (item.sonCategoryList) {
item.children = renderTreeNodes(item.sonCategoryList);
}
return item;
});
return newTreeData;
};
function handAddCourse() {
let modal = (
<AddCourse
......@@ -86,16 +128,127 @@ export default function KnowledgeBaseOpt({
setModal(modal);
}
return (
<div className="video-course-opt">
<Dropdown overlay={menu}>
<Button type="primary" className="mr12">
添加知识
<DownOutlined />
</Button>
</Dropdown>
function batchMove() {
if (_.isEmpty(selectedRowKeys)) {
message.warning('请先选择要移动的知识');
return null;
}
setOpenMoveModal(true);
}
function batchMoveRemote(categoryId) {
const data = {
categoryId,
ids: selectedRowKeys,
storeId: User.getStoreId(),
};
Service.Hades('public/hades/batchMoveKnowledgeCategory', data, { reject: true }).then((res) => {
if (res.success) {
message.success('移动成功');
onChange();
Bus.trigger('knowledgeCategoryTree');
clearSelect();
} else {
message.error('移动失败');
}
}).catch(() => {
message.error('移动失败');
})
}
function batchDelete() {
if (_.isEmpty(selectedRowKeys)) {
message.warning('请先选择要删除的知识');
return null;
}
Modal.confirm({
title: "确定要删除知识吗?",
content: "删除后,不可恢复。",
icon: (
<span className="icon iconfont default-confirm-icon">&#xe839; </span>
),
okText: "删除",
cancelText: "取消",
onOk: () => {
const data = {
ids: selectedRowKeys,
storeId: User.getStoreId(),
};
Service.Hades('public/hades/batchDelKnowledge', data, { reject: true }).then((res) => {
if (res.success) {
message.success('删除成功');
onChange();
Bus.trigger('knowledgeCategoryTree');
clearSelect();
} else {
message.error('删除失败');
}
}).catch(() => {
message.error('删除失败');
})
},
})
}
function onSelectPaper(keys) {
if (keys.length > 50) {
message.warning('最多只能选择50个知识');
return null;
}
onChangeKeys(keys);
};
function clearSelect() {
onChangeKeys([]);
}
return (
<div className="knowledge-course-opt">
{_.isEmpty(selectedRowKeys) ?
(categoryId !== '0' && <Dropdown overlay={menu}>
<Button type="primary" className="mr8">
添加知识
<DownOutlined />
</Button>
</Dropdown>)
: <div className="select-container">
<span className="con">
<div>
<span className="icon iconfont tip">&#xe6f2;</span>
<span className="text">已选择{selectedRowKeys.length}</span>
</div>
<div>
<span className="clear" onClick={clearSelect}>清空</span>
</div>
</span>
</div>
}
<Button
className="mr8"
onClick={() => {
batchMove();
}}
>批量移动</Button>
<Button
onClick={() => {
batchDelete();
}}
>批量删除</Button>
{modal}
{openMoveModal &&
<MoveModal
visible={openMoveModal}
title="知识"
data={data}
categoryId={categoryId}
length={selectedRowKeys.length}
onCancel={() => setOpenMoveModal(false)}
onOk={(categoryId) => {
batchMoveRemote(categoryId);
setOpenMoveModal(false);
}}
/>
}
</div>
);
}
.knowledge-course-opt {
display: flex;
.select-container{
margin-right: 24px;
.con{
background: #E9EFFF;
border-radius: 4px;
padding: 3px 16px;
display: inline-flex;
align-items: center;
justify-content: space-between;
.tip{
font-size:14px;
color:#2966FF;
margin-right:8px;
}
.text{
font-size:14px;
color:#666;
margin-right:30px;
}
.clear{
color:#5289FA;
font-size:14px;
}
}
}
}
\ No newline at end of file
......@@ -6,12 +6,12 @@
* @LastEditTime: 2021-05-30 20:36:42
* @Copyright: © 2020 杭州杰竞科技有限公司 版权所有
*/
import React from "react"
import KnowledgeBaseFilter from "./components/KnowledgeBaseFilter"
import KnowledgeBaseOpt from "./components/KnowledgeBaseOpt"
import KnowledgeBaseList from "./components/KnowledgeBaseList"
import Classification from "./components/Classification"
import React from "react";
import { message } from 'antd'
import KnowledgeBaseFilter from "./components/KnowledgeBaseFilter";
import KnowledgeBaseOpt from "./components/KnowledgeBaseOpt";
import KnowledgeBaseList from "./components/KnowledgeBaseList";
import Classification from "./components/Classification";
import KnowledgeAPI from "@/data-source/knowledge/request-api"
import User from "@/common/js/user"
......@@ -28,9 +28,10 @@ export default class KnowledgeBase extends React.Component {
},
dataSource: [], // 知识库列表
totalCount: 0, // 知识库数据总条数
categoryId: "0",
updateCategoryFlag: false
}
categoryId: '0',
updateCategoryFlag: false,
selectedRowKeys: [],
};
}
componentWillMount() {
......@@ -73,8 +74,23 @@ export default class KnowledgeBase extends React.Component {
})
}
onSelectChange = (selectedRowKeys) => {
if (selectedRowKeys.length > 50) {
message.warning('最多只能选择50个题目');
}
const list = _.filter(selectedRowKeys, (item, index) => index < 50);
this.setState({ selectedRowKeys: list });
};
render() {
const { dataSource, totalCount, query, categoryId, updateCategoryFlag } = this.state
const {
dataSource,
totalCount,
query,
categoryId,
updateCategoryFlag,
selectedRowKeys,
} = this.state;
return (
<div className='page'>
<div className='content-header'>知识库</div>
......@@ -92,13 +108,19 @@ export default class KnowledgeBase extends React.Component {
<KnowledgeBaseFilter onChange={this.handleFetchScheduleList} />
{/* 操作模块 */}
{categoryId !== "0" && (
<KnowledgeBaseOpt onChange={this.handleFetchScheduleList} updateCategoryTree={this.updateCategoryTree} categoryId={categoryId} />
)}
<KnowledgeBaseOpt
onChange={this.handleFetchScheduleList}
updateCategoryTree={this.updateCategoryTree}
categoryId={categoryId}
selectedRowKeys={selectedRowKeys}
onChangeKeys={(keys) => this.setState({ selectedRowKeys: keys })}
/>
{/* 知识库列表模块 */}
<KnowledgeBaseList
query={query}
selectedRowKeys={selectedRowKeys}
onSelectChange={this.onSelectChange}
categoryId={categoryId}
dataSource={dataSource}
totalCount={totalCount}
......
......@@ -2,8 +2,8 @@
* @Description:
* @Author: zangsuyun
* @Date: 2021-03-13 09:54:26
* @LastEditors: fusanqiasng
* @LastEditTime: 2021-06-01 10:26:46
* @LastEditors: yuananting
* @LastEditTime: 2021-06-10 19:55:24
* @Copyright: © 2020 杭州杰竞科技有限公司 版权所有
*/
......@@ -324,7 +324,7 @@ class AddCourse extends React.Component {
return <img className='course-cover' src={item.mediaUrl} alt='' />;
}
})}
{!hasCover && <img className='course-cover' src={'https://image.xiaomaiketang.com/xm/YNfi45JwFA.png'} alt='' />}
{!hasCover && <img className='course-cover' src={'https://image.xiaomaiketang.com/xm/Yip2YtFDwH.png'} alt='' />}
<div>
<Choose>
<When condition={record.courseName.length > 17}>
......@@ -501,8 +501,7 @@ class AddCourse extends React.Component {
const { coverUrl } = record;
return (
<div className='record__item'>
{/* 上传了封面的话就用上传的封面, 没有的话就取视频的第一帧 */}
<img className='course-cover' src={coverUrl || 'https://image.xiaomaiketang.com/xm/YNfi45JwFA.png'} alt='' />
<img className='course-cover' src={coverUrl || 'https://image.xiaomaiketang.com/xm/wFnpZtp2yB.png'} alt='' />
<Choose>
<When condition={record.courseName.length > 25}>
<Tooltip title={record.courseName}>
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -10,7 +10,7 @@
import React, { useState } from 'react';
import { Table, Modal, message, Tooltip, Switch, Dropdown } from 'antd';
import { withRouter } from 'react-router-dom';
import { PageControl } from '@/components';
import { PageControl, XMTable } from "@/components";
import PlanService from '@/domains/plan-domain/planService';
import SharePlanModal from '../modal/SharePlanModal';
import { LIVE_SHARE } from '@/domains/course-domain/constants';
......@@ -305,7 +305,7 @@ function PlanList(props) {
}
return (
<div className='plan-list'>
<Table
<XMTable
rowKey={(record) => record.id}
showSorterTooltip={false}
dataSource={props.planListData}
......@@ -316,6 +316,9 @@ function PlanList(props) {
size='middle'
scroll={{ x: 1400 }}
className='plan-list-table'
renderEmpty={{
description: <span style={{ display: 'block', paddingBottom: 24 }}>暂无数据</span>
}}
/>
<div className='box-footer'>
<PageControl
......
......@@ -16,7 +16,7 @@ import CourseService from '@/domains/course-domain/CourseService'
import './SharePlanModal.less'
const DEFAULT_COVER = 'https://image.xiaomaiketang.com/xm/YNfi45JwFA.png'
const DEFAULT_COVER = 'https://image.xiaomaiketang.com/xm/rEAetaTEh3.png'
class ShareLiveModal extends React.Component {
constructor(props) {
......@@ -51,6 +51,13 @@ class ShareLiveModal extends React.Component {
size: 98,
})
qrcodeWrapDom.appendChild(qrcodeNode)
const qrcodeWrapDomDownload = document.querySelector('#qrcodeWrap-dowload')
const qrcodeNodeDownLoad = new qrcode({
text: this.state.shareUrl,
size: 196,
})
qrcodeWrapDomDownload.appendChild(qrcodeNodeDownLoad)
}
)
})
......@@ -70,9 +77,8 @@ class ShareLiveModal extends React.Component {
},
() => {
this.setState({ time: new Date().valueOf() }, () => {
let node = document.getElementById('poster')
let node = document.getElementById('poster-dowload')
domtoimage.toPng(node).then((imgData) => {
console.log(imgData)
const download = document.createElement('a')
const { planName } = this.props.data
$(download).attr('href', imgData).attr('download', `${planName}.png`).get(0).click()
......@@ -112,7 +118,7 @@ class ShareLiveModal extends React.Component {
<div className='course-name-title'>邀请你参与培训:</div>
<div class='live-couse-name'>{planName}</div>
<div className='live-couse-name'>{planName}</div>
<Choose>
<When condition={showImg}>
<img crossOrigin='*' src={coverUrl + `?=${time}`} className='course-cover' alt='' />
......@@ -130,6 +136,31 @@ class ShareLiveModal extends React.Component {
<div className='qrcode-wrap__right' id='qrcodeWrap'></div>
</div>
</div>
<div id='poster-dowload'>
<div className='store-name'>
<span className='text'>{User.getStoreName()}</span>
</div>
<div className='course-name-title'>邀请你参与培训:</div>
<div className='live-couse-name'>{planName}</div>
<Choose>
<When condition={showImg}>
<img crossOrigin='*' src={coverUrl + `?=${time}`} className='course-cover' alt='' />
</When>
<Otherwise>
<img src={coverUrl + `?=${time}`} className='course-cover' alt='' />
</Otherwise>
</Choose>
<div className='qrcode-wrap'>
<div className='qrcode-wrap__left'>
<div className='text'>长按识别二维码进入观看</div>
<img className='finger' src='https://image.xiaomaiketang.com/xm/thpkWDwJsC.png' alt='' />
</div>
<div className='qrcode-wrap__right' id='qrcodeWrap-dowload'></div>
</div>
</div>
</div>
<div className='right'>
<div className='share-poster right__item'>
......
.share-live-modal {
.ant-modal-body {
display: flex;
#poster{
background: #FFF;
margin:0;
padding: 20px;
}
height:510px !important;
overflow: hidden !important;
.left {
width: 303px;
margin: 0 32px 0 16px;
box-shadow:0px 2px 10px 0px rgba(0,0,0,0.05);
border-radius: 12px;
.course-name-title {
font-size: 14px;
color: #333;
line-height: 20px;
margin-bottom: 4px;
}
.live-couse-name{
font-size:16px;
color:#333333;
font-weight: 600;
}
.course-name {
color: #333;
font-size: 16px;
font-weight: 600;
line-height: 20px;
}
.course-cover {
width: 263px;
height: 143px;
border-radius: 6px;
margin-top: 8px;
}
#poster{
background: #FFF;
margin:0;
padding: 20px;
margin-bottom:140px;
.course-name-title {
font-size: 14px;
color: #333;
line-height: 20px;
margin-bottom: 4px;
}
.live-couse-name{
font-size:16px;
color:#333333;
font-weight: 600;
}
.course-name {
color: #333;
font-size: 16px;
font-weight: 600;
line-height: 20px;
}
.course-cover {
width: 263px;
height: 143px;
border-radius: 6px;
margin-top: 8px;
}
.qrcode-wrap {
padding: 0 16px;
display: flex;
align-items: center;
margin: 24px 0 16px 0;
.qrcode-wrap {
padding: 0 16px;
display: flex;
align-items: center;
margin: 24px 0 16px 0;
&__left {
width: 98px;
text-align: center;
margin-right: 22px;
.text {
line-height: 20px;
&__left {
width: 98px;
text-align: center;
margin-right: 22px;
.text {
line-height: 20px;
}
.finger {
width: 40px;
height: 40px;
margin-top: 8px;
}
}
.finger {
width: 40px;
height: 40px;
margin-top: 8px;
&__right {
width: 110px;
height: 110px;
padding: 6px
}
}
&__right {
width: 110px;
height: 110px;
padding: 6px
.store-name {
// padding: 8px 16px;
display: flex;
align-items: center;
margin-bottom: 8px;
.text {
font-size: 12px;
color: #999;
font-size: 14px;
line-height: 20px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
width: 100%;
}
}
}
#poster-dowload{
background: #FFF;
margin:0;
padding: 40px;
width:606px;
.course-name-title {
font-size: 28px;
color: #333;
line-height: 40px;
margin-bottom: 8px;
}
.live-couse-name{
font-size:32px;
color:#333333;
font-weight: 600;
}
.course-name {
color: #333;
font-size: 32px;
font-weight: 600;
line-height: 40px;
}
.course-cover {
width: 526px;
height: 286px;
border-radius: 6px;
margin-top: 16px;
}
.store-name {
// padding: 8px 16px;
display: flex;
align-items: center;
margin-bottom: 8px;
.text {
font-size: 12px;
color: #999;
font-size: 14px;
line-height: 20px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
width: 100%;
.qrcode-wrap {
padding: 0 32px;
display: flex;
align-items: center;
margin: 48px 0 32px 0;
&__left {
width: 196px;
text-align: center;
margin-right: 44px;
.text {
line-height: 40px;
}
.finger {
width: 80px;
height: 80px;
margin-top: 16px;
}
}
&__right {
width: 220px;
height: 220px;
padding: 12px
}
}
.store-name {
// padding: 8px 16px;
display: flex;
align-items: center;
margin-bottom: 16px;
.text {
font-size: 12px;
color: #999;
font-size: 28px;
line-height: 40px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
width: 100%;
}
}
}
}
......
......@@ -304,7 +304,7 @@ class SelectOperatorModal extends React.Component {
return null
})}
<If condition={!hasCover}>
<img className='course-cover' src={"https://image.xiaomaiketang.com/xm/YNfi45JwFA.png"} alt='' />
<img className='course-cover' src={"https://image.xiaomaiketang.com/xm/Yip2YtFDwH.png"} alt='' />
</If>
<div>
......@@ -432,8 +432,7 @@ class SelectOperatorModal extends React.Component {
const { coverUrl } = record
return (
<div className='course-info'>
{/* 上传了封面的话就用上传的封面, 没有的话就取视频的第一帧 */}
<img className='course-cover' src={coverUrl || "https://image.xiaomaiketang.com/xm/YNfi45JwFA.png"} alt='' />
<img className='course-cover' src={coverUrl || "https://image.xiaomaiketang.com/xm/wFnpZtp2yB.png"} alt='' />
<div className='course-name'>{record.courseName}</div>
</div>
)
......
/*
* @Author: 吴文洁
* @Date: 2020-06-09 10:47:51
* @Last Modified by: 吴文洁
* @Last Modified time: 2020-07-23 09:33:09
* @Last Modified by: chenshu
* @Last Modified time: 2021-06-08 18:10:25
* @Description: 文件夹列表
*/
......@@ -11,12 +11,13 @@ import { Table, Menu, Dropdown, Modal, message,Tooltip } from 'antd';
import _ from 'underscore';
// import * as lodash from 'lodash';
import { PageControl, LottieIcon } from 'xiaomai-b-components';
import { XMTable } from '@/components';
import Service from '@/common/js/service';
import { formatDate } from '@/domains/basic-domain/utils';
import { FILE_TYPE_ICON_MAP, SUPPORT_FILE_TYPE_MAP, DEFAULT_SIZE_UNIT } from '@/domains/resource-disk/constants';
import { getFileTypeByName } from '@/domains/resource-disk/utils';
import addData from '../../lottie/addData/data.json';
import search from '../../lottie/search/data.json';
import UploadProgressModal from '@/bu-components/UploadProgressModal';
import SelectPrepareFileModal from '@/bu-components/SelectPrepareFileModal';
import CopyFileModal from '@/bu-components/CopyFileModal';
......@@ -817,9 +818,11 @@ class FolderList extends React.Component {
</When>
<Otherwise>
<LottieIcon
title={
<Choose>
<XMTable
className="add-empty"
renderEmpty={{
image: !showResultPage ? addData : search,
description: <Choose>
<When condition={!showResultPage}>
<input
multiple
......@@ -833,7 +836,7 @@ class FolderList extends React.Component {
{
<Choose>
<When condition={hasManagementAuthority}>
<div>你还没有上传文件,点击
<div className="lottie-icon-title">你还没有上传文件,点击
<Tooltip title="支持文件类型:ppt、word、excel、pdf、jpg、mp3、mp4">
<span
className="upload-btn"
......@@ -853,7 +856,7 @@ class FolderList extends React.Component {
<div className="desc">搜索无结果</div>
</Otherwise>
</Choose>
}
}}
/>
</Otherwise>
</Choose>
......@@ -886,7 +889,7 @@ class FolderList extends React.Component {
}}
onMove={(query) => {
this.setState({ showSelectFileModal: false });
this.props.onMove(query, [currentFile.id]);
this.props.onMove(query, [currentFile.id],[currentFile.folderType]);
}}
/>
{
......
......@@ -47,6 +47,7 @@ class FolderManage extends React.Component {
folderPathList: [props.currentRootDisk],
selectedFileIds: [], // 已被选择的文件
selectedFileRights: [], // 已被选择的文件对应权限
selectedFileType:[], // 已选择的文件的类型
folderList: [], // 当前目录下的文件
searchKey: null, // 搜索关键字
totalCount: 0, // 该磁盘总共有的文件个数
......@@ -200,10 +201,12 @@ class FolderManage extends React.Component {
handleChangeRow = (selectedRowKeys) => {
const { folderList } = this.state;
let _selectedFileRights = [];
let _selectedFileType = [];
selectedRowKeys.map(folderId => {
folderList.map(item => {
if (item.id === folderId) {
_selectedFileRights.push(item.rights);
_selectedFileType.push(item.folderType);
}
return _selectedFileRights;
})
......@@ -211,7 +214,8 @@ class FolderManage extends React.Component {
})
this.setState({
selectedFileIds: selectedRowKeys,
selectedFileRights: _selectedFileRights
selectedFileRights: _selectedFileRights,
selectedFileType:_selectedFileType
})
}
......@@ -255,12 +259,13 @@ class FolderManage extends React.Component {
}
// 移动文件
handleMove = (query, sourceFileIds = this.state.selectedFileIds) => {
handleMove = (query, sourceFileIds = this.state.selectedFileIds,selectedFileTypes=this.state.selectedFileType) => {
const { targetFolder, selectFolderPathList } = query;
const { currentRootDisk: { disk} } = this.props;
const { folderPathList } = this.state;
const currentFolder = folderPathList[folderPathList.length - 1];
const { id } = targetFolder;
let canRemove = true;
// 将selectedFileIds移动到targetFolder
let params = {
disk,
......@@ -271,28 +276,38 @@ class FolderManage extends React.Component {
if (selectFolderPathList.length > 1) {
params.newParentId = id
}
Service.Hades('public/hadesStore/moveFolder', params).then((res) => {
// 判断是否将文件移动到了自身或者子目录
const { result = {} } = res;
const { code, message: _message } = result;
if (code === 'PARAM_ERROR') {
message.warning(_message);
return;
}
if (id == null) {
Modal.success({
title: '文件移动成功',
content: '移动到一级目录的文件仅自己可以查看,如需其他成员查看请设置权限'
})
} else {
message.success('文件移动成功');
}
if(selectFolderPathList.length > 9){
selectedFileTypes.map((item)=>{
//判定是否存在文件夹
if(item==="FOLDER"){
canRemove = false;
message.warning('不能将文件夹移动到10级目录下');
}
})
}
if(canRemove){
Service.Hades('public/hadesStore/moveFolder', params).then((res) => {
// 判断是否将文件移动到了自身或者子目录
const { result = {} } = res;
const { code, message: _message } = result;
if (code === 'PARAM_ERROR') {
message.warning(_message);
return;
}
if (id == null) {
Modal.success({
title: '文件移动成功',
content: '移动到一级目录的文件仅自己可以查看,如需其他成员查看请设置权限'
})
} else {
message.success('文件移动成功');
}
// 移动成功之后需要将selectedFileIds置为空
this.setState({ selectedFileIds: [] });
this.handleFetchFolderList({ parentId: currentFolder.id, current: 1});
})
// 移动成功之后需要将selectedFileIds置为空
this.setState({ selectedFileIds: [] });
this.handleFetchFolderList({ parentId: currentFolder.id, current: 1});
})
}
}
// 修改文件路径
......
......@@ -70,7 +70,7 @@ class OperateArea extends React.Component {
// 判断当前目录是否在第10层,如果是的话提示最多只能创建10层文件夹
const { folderPathList } = this.props;
if (folderPathList.length > 10) {
if (folderPathList.length > 9) {
message.warning('最多只能创建10层文件夹');
return;
}
......
......@@ -215,14 +215,12 @@
cursor: pointer;
}
.lottie-icon {
&__title {
color: #999;
.upload-btn {
color: #5A8EFA;
margin: 0 4px;
cursor: pointer;
}
.lottie-icon-title {
color: #999;
.upload-btn {
color: #5A8EFA;
margin: 0 4px;
cursor: pointer;
}
}
// td.ant-table-column-sort{
......@@ -230,6 +228,11 @@
// }
}
}
.add-empty {
.ant-table-cell {
border: none;
}
}
}
......
import User from '@/common/js/user';
import React from 'react';
import Header from './Header'
import Lottie from "lottie-web";
import { Modal } from "antd";
import Service from "@/common/js/service";
import { LIVE_SHARE } from "@/domains/course-domain/constants";
import BaseService from "@/domains/basic-domain/baseService";
import './ErrorCollege.less';
export default class ErrorCollege extends React.Component {
constructor(props) {
super(props);
this.state = {
menuType: true,
nickName: '',
}
}
componentDidMount() {
this.getUserInfo();
this.getStorePermission();
var animation = Lottie.loadAnimation({
path: "https://image.xiaomaiketang.com/xm/AhcJZHdMZf.json",
name: "test",
renderer: "svg",
loop: true,
autoplay: true,
container: document.getElementById("lottie-box")
});
}
getStorePermission() {
......@@ -29,17 +41,62 @@ export default class ErrorCollege extends React.Component {
});
}
handleMenuType() {
this.setState({ menuType: !menuType });
getUserInfo() {
const param = {
storeUserId: User.getStoreUserId(),
};
BaseService.getStoreUser(param).then((res) => {
const { nickName } = res.result;
this.setState({ nickName });
});
}
handleLogoutConfirm() {
return Modal.confirm({
title: "你确定要退出登录吗?",
content: "退出后,需重新登录",
icon: (
<span className="icon iconfont default-confirm-icon">&#xe839; </span>
),
okText: "退出登录",
cancelText: "点错了",
onOk: () => {
this.handleLogout();
},
});
}
handleLogout() {
BaseService.logout({identifier:User.getIdentifier()}).then((res) => {
User.removeUserId();
User.removeToken();
User.removeEnterpriseId();
User.clearUserInfo();
const url = `${LIVE_SHARE}store/index?id=${User.getCustomerStoreId()||User.getStoreId()}&userId=${User.getUserId()}&from=work_weixin`;
window.location.href = url;
});
}
render() {
const { menuType } = this.state;
const { nickName } = this.state;
return (
<div className="error-college-page">
<Header id="error" handleMenuType={this.handleMenuType} menuType={menuType} />
<div className="header">
<img src='https://image.xiaomaiketang.com/xm/FEdG7BMwKr.png' className="logo" alt="" />
<div className="name-box">
<img src='https://image.xiaomaiketang.com/xm/hcp6zs5HTn.png' className="avatar" alt="" />
<span className="name">{nickName}</span>
<span
className="control"
onClick={() => {
this.handleLogoutConfirm();
}}
>退出登录</span>
</div>
</div>
<div className="error-college-box">
<img src="https://image.xiaomaiketang.com/xm/MQRaYkbr6J.png" className="error-college-image" />
<div id="lottie-box" className="error-college-image"></div>
<span className="error-college-tip">{User.getStoreName()}已停用</span>
</div>
</div>
......
......@@ -2,6 +2,36 @@
position: relative;
width: 100vw;
height: 100vh;
.header {
display: flex;
align-items: center;
height: 60px;
padding: 0 344px;
justify-content: space-between;
.logo {
width: 117px;
height: 30px;
}
.name-box {
display: flex;
align-items: center;
.avatar {
width: 24px;
height: 24px;
border-radius: 50%;
margin-right: 6px;
}
.name {
color: #666;
font-size: 16px;
margin-right: 8px;
}
.control {
color: #2966FF;
cursor: pointer;
}
}
}
.error-college-box {
position: absolute;
top: 50px;
......@@ -10,20 +40,20 @@
bottom: 0;
.error-college-image {
position: absolute;
top: 246px;
top: 266px;
left: 50%;
transform: translateX(-50%);
width: 246px;
height: 132px;
width: 200px;
height: 200px;
display: block;
}
.error-college-tip {
position: absolute;
top: 404px;
top: 482px;
left: 50%;
transform: translateX(-50%);
color: #8C8E93;
font-size: 13px;
color: #000;
font-size: 18px;
}
}
}
\ No newline at end of file
......@@ -48,8 +48,8 @@
margin-right: 20px
}
.icon-img{
width:16px;
height:16px;
width:18px;
height:18px;
margin-right:16px;
}
.listType {
......
/*
* @Author: yuananting
* @Date: 2021-02-23 18:28:50
* @LastEditors: fusanqiasng
* @LastEditTime: 2021-05-21 17:57:59
* @LastEditors: yuananting
* @LastEditTime: 2021-06-02 14:25:06
* @Description: 助学工具-课程分类
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
......@@ -153,9 +153,7 @@ class CourseCategoryManage extends Component {
<Space className='title-opts' size={16}>
<span
onClick={() => {
let nodesCount = 0
const { originTreeData } = this.state
console.log('orororo', originTreeData)
const { originTreeData } = this.state;
if (
(item.categoryLevel === 0 && originTreeData.length >= 29) ||
(item.categoryLevel > 0 && this.getRelatedNodes(item.parentId).length >= 30)
......@@ -343,8 +341,10 @@ class CourseCategoryManage extends Component {
let dragNodes = []
dragNodes.push(dragNode.id)
if (dragNode.parentId != 0) {
dragNodes = dragNodes.concat(this.getParentDragNodesLevel(this.state.treeMap[dragNode.parentId]))
if (dragNode.parentId !== "0") {
dragNodes = dragNodes.concat(
this.getParentDragNodesLevel(this.state.treeMap[dragNode.parentId])
);
}
return dragNodes
}
......@@ -365,14 +365,24 @@ class CourseCategoryManage extends Component {
// 拖拽
onDrop = (info) => {
if (this.state.categoryName) {
return
// 带搜索时的分类树不允许拖拽
// 不允许其他节点拖拽到未分类中
// 不允许其他节点拖拽到未分类之前
if (
this.state.categoryName ||
(info.node.categoryName === "未分类" && info.dropPosition === 0) ||
(info.node.categoryName === "未分类" &&
info.dropToGap &&
info.dropPosition === -1)
) {
return;
}
// 未分类不可以拖拽
if (info.dragNode.categoryName === '未分类' && info.dragNode.categoryLevel === 0) return message.info('未分类”为默认分类暂不支持移动')
// 不允许其他节点拖拽到未分类之前
if (info.node.categoryName === '未分类' && info.dropToGap && info.dropPosition === -1) return
if (
info.dragNode.categoryName === "未分类" &&
info.dragNode.categoryLevel === 0
)
return message.info("“未分类”为默认分类暂不支持移动");
let targetParentId = info.dropToGap ? info.node.parentId : info.node.id
let relatedNodes = this.getRelatedNodes(targetParentId)
......@@ -383,8 +393,7 @@ class CourseCategoryManage extends Component {
let nodesArr = this.getDragNodesLevel(this.state.treeMap[info.dragNode.id])
let parentArr = this.getParentDragNodesLevel(this.state.treeMap[targetParentId])
if (nodesArr.length + parentArr.length > 4) {
console.log(nodesArr.length, parentArr.length)
return message.info('最多支持5级分类')
return message.info("最多支持5级分类");
}
}
if (relatedNodes && relatedNodes.length >= 30) {
......
......@@ -44,7 +44,7 @@
white-space: nowrap;
}
.ant-tree-node-content-wrapper.ant-tree-node-selected {
color: #666666;
color: #2966FF;
}
}
.ant-tree-treenode-selected:hover::before,
......
......@@ -5,15 +5,15 @@
* @Last Modified time: 2020-04-18 10:54:32
*/
import React, { useState, useEffect, useRef } from "react";
import "./XMAudio.less";
import VideoUpload from "@/core/upload";
import React, { useState, useEffect, useRef } from 'react';
import './XMAudio.less';
import VideoUpload from '@/core/upload';
let timerInterval;
const XMAudio = (props) => {
const ref = useRef();
const { style, size, getDuration } = props;
const { style, size, getDuration } = props;
const [url, setUrl] = useState(props.url);
const [playing, setPlaying] = useState(false);
const [timer, setTimer] = useState(null);
......@@ -22,7 +22,7 @@ const XMAudio = (props) => {
const [totalTime, setTotalTime] = useState(Math.round(Number(size)));
const prevTimeRef = useRef();
useEffect(() => {
if(!props.forbidParse){
if (!props.forbidParse) {
VideoUpload.getVideoParseRoute(props.url).then((newUrl) => {
setUrl(newUrl);
});
......@@ -30,7 +30,7 @@ const XMAudio = (props) => {
setLeftTime(Math.round(Number(size)));
setTotalTime(Math.round(Number(size)));
ref.current.addEventListener("pause", () => {
ref.current.addEventListener('pause', () => {
clearInterval(timer);
setPlaying(false);
setTimer(null);
......@@ -42,7 +42,6 @@ const XMAudio = (props) => {
}, [props.url]);
useEffect(() => {
if (playing) {
timerInterval = setInterval(() => {
setPlayedTime((preTime) => {
......@@ -53,18 +52,18 @@ const XMAudio = (props) => {
if ((prevTimeRef.current + 20) % 1000 === 0) {
setLeftTime(totalTime - (prevTimeRef.current + 20));
}
if ((prevTimeRef.current + 30) >= totalTime) {
if (prevTimeRef.current + 30 >= totalTime) {
clearInterval(timerInterval);
setPlayedTime(0);
setLeftTime(totalTime);
setPlaying(false);
}
}, 20);
const audioDomList = document.querySelectorAll("audio");
const audioDomList = document.querySelectorAll('audio');
for (let i = 0; i < Array.from(audioDomList).length; i++) {
if (audioDomList[i] === ref.current) {
ref.current.play();
setTimer(timerInterval)
setTimer(timerInterval);
} else {
audioDomList[i].pause();
}
......@@ -75,9 +74,7 @@ const XMAudio = (props) => {
}
}, [playing]);
const audioImg = `https://xiaomai-image.oss-cn-hangzhou.aliyuncs.com/${
playing ? 1584514990496 : 1584514999661
}.png`;
const audioImg = `https://xiaomai-image.oss-cn-hangzhou.aliyuncs.com/${playing ? 1584514990496 : 1584514999661}.png`;
function _togglePlay() {
playing ? pausePlay() : startPlay();
......@@ -112,78 +109,74 @@ const XMAudio = (props) => {
}
}
function _startTime() {
let time = Math.floor(playedTime / 1000);
let second = 0
let second = 0;
let minute = 0;
let result = 0
let result = 0;
if (time > 0) {
minute = Math.floor(time % 3600 / 60);
minute = Math.floor((time % 3600) / 60);
second = Math.floor((time - 60 * minute) % 60);
if (minute < 10) {
minute = "0" + minute;
minute = '0' + minute;
}
if (second < 10) {
second = "0" + second;
second = '0' + second;
}
result = minute + ':' + second
}else{
result = "00:00"
result = minute + ':' + second;
} else {
result = '00:00';
}
return result;
}
function _endTime() {
let time = Math.floor(totalTime / 1000);
let second = 0
let second = 0;
let minute = 0;
let result = 0
let result = 0;
if (time > 0) {
minute = Math.floor(time % 3600 / 60);
minute = Math.floor((time % 3600) / 60);
second = Math.floor((time - 60 * minute) % 60);
if (minute < 10) {
minute = "0" + minute;
minute = '0' + minute;
}
if (second < 10) {
second = "0" + second;
second = '0' + second;
}
result = minute + ':' + second
result = minute + ':' + second;
}
if(time === 0){
result = "00:00"
if (time === 0) {
result = '00:00';
}
return result;
}
function putDownFlag(event) {
let dragDiv = event.target;
dragDiv.style.cursor = "pointer";
dragDiv.style.cursor = 'pointer';
let offsetX = parseInt(dragDiv.style.left); // 获取当前的x轴距离
let innerX = event.clientX - offsetX; // 获取鼠标在方块内的x轴距
// 按住鼠标时为div修改样式
dragDiv.style.width = "16px";
dragDiv.style.height = "16px";
dragDiv.style.top = "-7px";
dragDiv.style.backGround = "linear-gradient(180deg, #FFB467 0%, #FF9143 100%)"
dragDiv.style.width = '16px';
dragDiv.style.height = '16px';
dragDiv.style.top = '-7px';
dragDiv.style.backGround = 'linear-gradient(180deg, #FFB467 0%, #FF9143 100%)';
// 鼠标移动的时候不停的修改div的left和top值
document.onmousemove = function (event) {
dragDiv.style.left = event.clientX - innerX + "px";
dragDiv.style.left = event.clientX - innerX + 'px';
// 边界判断
if (parseInt(dragDiv.style.left) <= 0) {
dragDiv.style.left = "0px";
dragDiv.style.left = '0px';
}
if (parseInt(dragDiv.style.left) >= 154) {
dragDiv.style.left = "149px";
dragDiv.style.left = '149px';
}
setPlayedTime(parseInt(dragDiv.style.left) / 150 * totalTime)
}
setPlayedTime((parseInt(dragDiv.style.left) / 150) * totalTime);
};
// 鼠标抬起时,清除绑定在文档上的mousemove和mouseup事件
// 否则鼠标抬起后还可以继续拖拽方块
document.onmouseup = function () {
......@@ -191,50 +184,43 @@ const XMAudio = (props) => {
document.onmouseup = null;
// 清除border
dragDiv.style.top = "-4px";
dragDiv.style.width = "10px";
dragDiv.style.height = "10px";
}
dragDiv.style.top = '-4px';
dragDiv.style.width = '10px';
dragDiv.style.height = '10px';
};
}
function mouseOver(event){
function mouseOver(event) {
let dragDiv = event.target;
dragDiv.style.cursor = "pointer";
dragDiv.style.width = "16px";
dragDiv.style.height = "16px";
dragDiv.style.top = "-7px";
dragDiv.style.backGround = "linear-gradient(180deg, #FFB467 0%, #FF9143 100%)"
dragDiv.style.cursor = 'pointer';
dragDiv.style.width = '16px';
dragDiv.style.height = '16px';
dragDiv.style.top = '-7px';
dragDiv.style.backGround = 'linear-gradient(180deg, #FFB467 0%, #FF9143 100%)';
}
function mouseLeave (event){
function mouseLeave(event) {
let dragDiv = event.target;
dragDiv.style.top = "-4px";
dragDiv.style.width = "10px";
dragDiv.style.height = "10px";
dragDiv.style.top = '-4px';
dragDiv.style.width = '10px';
dragDiv.style.height = '10px';
ref.current.currentTime = playedTime / 1000;
}
return (
<div className="xm-audio" style={style}>
<img src={audioImg} onClick={_togglePlay} className="audio-image" />
<div className="process-area">
<div
className="complete-area"
style={{ width: `${(playedTime / totalTime) * 150}px ` }}
/>
<div className='xm-audio' style={style}>
<img src={audioImg} onClick={_togglePlay} className='audio-image' />
<div className='process-area'>
<div className='complete-area' style={{ width: `${(playedTime / totalTime) * 150}px ` }} />
<div
className="flag"
className='flag'
style={{ left: `${(playedTime / totalTime) * 150}px ` }}
onMouseDown={(e) => putDownFlag(e)}
onMouseOver={(e)=> mouseOver(e)}
onMouseLeave={(e)=>mouseLeave(e)}
onMouseOver={(e) => mouseOver(e)}
onMouseLeave={(e) => mouseLeave(e)}
/>
</div>
<span className="sec-time">
{`${_startTime()}`}/{`${_endTime()}`}
</span>
<audio
src={url}
ref={ref}
autoPlay={false}
onCanPlayThrough={_getDuration}
/>
<span className='sec-time'>
{`${_startTime()}`}/{`${_endTime()}`}
</span>
<audio src={url} ref={ref} autoPlay={false} onCanPlayThrough={_getDuration} />
</div>
);
};
......
......@@ -5,10 +5,11 @@
* @Last Modified time: 2020-03-24 10:18:43
*/
.xm-audio {
.xm-audio {
display: flex;
align-items: center;
width: 280px;
padding: 10px 20px;
border-radius: 5px;
background-color: #ffffff;
.audio-image {
......@@ -24,11 +25,11 @@
cursor: pointer;
}
.play-icon {
color: #FC8540;
color: #fc8540;
}
.sec-time{
.sec-time {
white-space: nowrap;
color: #FF8534;
color: #ff8534;
margin-left: 12px;
font-size: 13px;
}
......@@ -38,11 +39,11 @@
border-radius: 3px;
margin-left: 12px;
position: relative;
background:rgba(255,133,52,0.2);
background: rgba(255, 133, 52, 0.2);
.complete-area {
height: 100%;
background-color: #FF8534;
background-color: #ff8534;
border-top-left-radius: 3px;
border-bottom-left-radius: 3px;
}
......@@ -52,7 +53,7 @@
width: 10px;
height: 10px;
border-radius: 50%;
background:linear-gradient(180deg,rgba(255,180,103,1) 0%,rgba(255,145,67,1) 100%);
background: linear-gradient(180deg, rgba(255, 180, 103, 1) 0%, rgba(255, 145, 67, 1) 100%);
}
}
}
.examPage{
padding-bottom: 50px;
.box {
padding-bottom: 40px!important;
padding-bottom: 66px!important;
}
.ant-form-item{
margin-bottom: 24px !important;
&:last-child{
margin-bottom: 0px !important;
}
}
.form{
margin-top: 12px;
margin-top: 24px;
margin-bottom: 32px;
width: 1000px;
.title{
position: relative;
padding-left: 28px;
font-size: 16px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: bold;
color: #333333;
line-height: 22px;
margin-bottom: 8px;
margin-bottom: 24px;
&.first {
&::before{
width:4px;
height:12px;
content:'';
background-image: linear-gradient(#2966FF 83.5%, #0ACCA4 16.5%);
display:inline-block;
position: absolute;
left:16px;
top:6px;
}
}
}
}
......
import React, { useState, useRef, useEffect, useContext } from 'react'
import Breadcrumbs from "@/components/Breadcrumbs";
import { Form, Alert, Input, Button, InputNumber, DatePicker, Switch, Radio, message, Modal } from 'antd';
import { Form, Alert, Input, Button, InputNumber, DatePicker, Switch, Radio, message, Modal, Tooltip } from 'antd';
import { Route, withRouter } from 'react-router-dom';
import User from "@/common/js/user";
import moment from 'moment'
......@@ -36,20 +36,27 @@ function AddExam(props: any) {
const [getData, setGetData] = useState(false);
const [preview, setPreview] = useState(false);
const [examTotal, setExamTotal] = useState(0);
const timer = useRef({});
const request = useRef(false);
const { match } = props;
const [examDuration, setExamDuration] = useState(undefined);
useEffect(() => {
if (props.type === 'edit') {
queryExamDetail()
switch (props.type) {
case "copy": // 考试列表-复制考试进入
case "edit": // 考试列表-编辑考试进入
queryExamDetail();
break;
case "organizeExam": // 试卷列表-组织考试进入
case "newPaperToAddExam": // 组卷页面-新建保存试卷并组织考试
case "editPaperToAddExam": // 组卷页面-编辑保存试卷并组织考试
setGetData(true);
setPaperInfo(props.paperInfo);
break;
}
}, [])
useEffect(() => {
console.log(paperInfo)
setPaperId(paperInfo.paperId)
setPassRate(paperInfo.passRate)
......@@ -75,9 +82,9 @@ function AddExam(props: any) {
const { result } = res
setPaperInfo(result.examPaper)
setPaperId(result.examPaper.paperId)
setStartTime(result.examStartTime)
setExamEndTime(result.examEndTime)
setExamName(result.examName)
setStartTime(props.type === 'edit' ? result.examStartTime : '')
setExamEndTime(props.type === 'edit' ? result.examEndTime : '')
setExamName(props.type === 'edit' ? result.examName : `${result.examName}(复制)`)
setPassRate(result.passRate * 100)
setNeedPhone(result.needPhone)
setExamDesc(result.examDesc)
......@@ -125,6 +132,11 @@ function AddExam(props: any) {
return
}
if (param.examName && param.examName.length > 40) {
message.warning('考试名称最多40字');
return
}
if (!paperId) {
message.warning('请选择试卷');
return
......@@ -174,8 +186,19 @@ function AddExam(props: any) {
Service.Hades(props.type === 'edit' ? 'public/hades/editExam' : "public/hades/createExam", param).then((res) => {
message.success(props.type === 'edit' ? '编辑成功' : '创建成功');
props.freshList()
props.history.goBack();
switch (props.type) {
case "organizeExam": // 试卷列表-组织考试进入
case "newPaperToAddExam": // 组卷保存组织考试
case "editPaperToAddExam":
window.RCHistory.push("/examination-manage-index")
break;
case "add":
case "edit": // 考试列表-新建或编辑
case "copy": // 考试列表-新建或编辑
props.freshList()
props.history.goBack();
break;
}
})
}
......@@ -222,14 +245,30 @@ function AddExam(props: any) {
cancelText: '留在本页',
icon: <span className="icon iconfont default-confirm-icon">&#xe6f4;</span>,
onOk: () => {
props.history.goBack();
window.RCHistory.push("/examination-manage-index")
}
})
}
let title = '';
switch (props.type) {
case 'add':
case "organizeExam":
case "newPaperToAddExam":
case "editPaperToAddExam":
title = '新建考试';
break;
case 'edit':
title = '编辑考试';
break;
case 'copy':
title = '复制考试';
break;
default:
break;
}
return <div className="page examPage">
<Breadcrumbs navList={props.type === 'edit' ? "编辑考试" : "新建考试"} goBack={handleGoBack} />
<Breadcrumbs navList={title} goBack={handleGoBack} />
<div className="box">
<div className="show-tips">
......@@ -242,8 +281,8 @@ function AddExam(props: any) {
layout="horizontal"
>
<Form.Item label="考试名称"
validateStatus={(check && !examName) ? 'error' : ''}
help={check && !examName && '请选择课程'}
validateStatus={(check && (!examName ? '请输入考试名称' : (examName.length > 40) && '考试名称最多40字')) ? 'error' : ''}
help={check && (!examName ? '请输入考试名称' : (examName.length > 40) && '考试名称最多40字')}
required>
<Input placeholder='请输入考试名称(40字以内)' maxLength={40} value={examName} onChange={(e) => {
......@@ -296,11 +335,18 @@ function AddExam(props: any) {
<Form.Item label="及格线"
<Form.Item
label={<div>
<span>及格线</span>
<Tooltip title="默认为选中试卷所设置的及格线,可修改">
<span className="icon iconfont" style={{ color: '#BFBFBF', marginLeft: 4 }}>&#xe61d;</span>
</Tooltip>
</div>}
style={{ marginTop: 24 }}
validateStatus={(check && !passRate) ? 'error' : ''}
help={check && !passRate && '请输入及格线'}
required>
required
>
<InputNumber value={passRate} min={0} max={100} onChange={(value: any) => { setPassRate(parseInt(value)) }} style={{ width: 100 }} />
<span style={{ marginLeft: 4 }}>%
</span>
......@@ -314,10 +360,11 @@ function AddExam(props: any) {
required>
<RangePicker
style={{ width: 320 }}
showTime={{ defaultValue: [moment().add(5, 'minutes'), moment().add(5, 'minutes')] }}
ranges={{
'近七天': [moment(), moment().add(6, 'day').endOf('day')],
'近1个月': [moment(), moment().add(1, 'month').endOf('day')],
'近3个月': [moment(), moment().add(3, 'month').endOf('day')],
'近七天': [moment().add(5, 'minute'), moment().add(6, 'day').endOf('day')],
'近1个月': [moment().add(5, 'minute'), moment().add(1, 'month').endOf('day')],
'近3个月': [moment().add(5, 'minute'), moment().add(3, 'month').endOf('day')],
}}
disabledDate={disabledDate}
value={[
......@@ -325,7 +372,6 @@ function AddExam(props: any) {
examEndTime ? moment(Number(examEndTime)) : null
]}
disabledTime={disabledRangeTime}
showTime
format="YYYY/MM/DD HH:mm"
onChange={(date: any) => {
setStartTime(date && date[0]?.valueOf());
......@@ -350,7 +396,7 @@ function AddExam(props: any) {
help={check && (desclen > 1000) && '最多只能输入1000个字'}
>
{
(getData || (props.type !== 'edit')) && <GraphicsEditor
(getData || (props.type === 'add')) && <GraphicsEditor
maxLimit={1000}
isIntro={true}
detail={{
......
......@@ -39,11 +39,10 @@ function DataAnalysic(props: any) {
<Breadcrumbs navList={"考试数据"} goBack={props.history.goBack} />
<div className="box">
<div className="titleBox ">
<span className='tips'></span>
考试名称:{examDetail.examName}
</div>
</div>
<div className="box">
<div className="box" style={{ paddingTop: 0 }}>
<Tabs activeKey={selectKey} onChange={(key: any) => {
setSelectKey(key)
}}>
......
......@@ -207,7 +207,6 @@ function ExamData(props: any) {
return <div className="rr">
<a
target="_blank"
download
id="load-play-back-excel"
style={{ position: "absolute", left: "-10000px" }}
......
......@@ -123,6 +123,7 @@
border-radius: 4px;
padding: 14px;
padding-bottom: 8px;
padding-right: 0;
.item{
margin-bottom: 8px;
.name{
......
......@@ -33,18 +33,18 @@ function PreviewModal(props: any) {
<div className="phone">
<div className="content">
<div className="topContent">
<div className="title" style={{ fontSize: props.info.examName.length > 24 ? 13 : 22 ,marginTop:props.info.examName.length > 24?44:20}}>{props.info.examName || ' '}</div>
<div className="title" style={{ fontSize: props.info.examName.length > 24 ? 13 : 22 ,marginTop: 20 }}>{(props.info.examName.length > 40 ? props.info.examName.substring(0, 40) : props.info.examName) || ' '}</div>
{
props.info.examStartTime && <div className="time">{moment(props.info.examStartTime).format("YYYY-MM-DD HH:mm")}~{moment(props.info.examEndTime).format("YYYY-MM-DD HH:mm")}</div>
}
<div className="rule">
<div className="item">
<div className="num">{props.info.totalScore || 0}</div>
<div className="num">{props.info.totalScore || (props.info.examPaper || {}).totalScore || 0}</div>
<div className="text">总分 <span className="dw" style={{color:'#999'}}>(分)</span></div>
</div>
<div className="item">
<div className="num">{props.info.examTotal || 0}</div>
<div className="num">{props.info.examTotal || (props.info.examPaper || {}).questionCnt || 0}</div>
<div className="text">总题数<span className="dw" style={{color:'#999'}} >(道)</span></div>
</div>
<div className="item">
......
/*
* @Author: yuananting
* @Date: 2021-04-07 16:10:21
* @LastEditors: wufan
* @LastEditTime: 2021-04-26 10:21:19
* @Description: 助学工具-考试-考试结果
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import React, { useState, useEffect } from 'react';
import { withRouter } from 'react-router-dom';
import User from '@/common/js/user';
import './TestDetailPage.less';
import Service from '@/common/js/service';
import { message } from 'antd';
import AnswerDescPage from '../components/AnswerDescPage';
import Breadcrumbs from '@/components/Breadcrumbs';
function TestDetailPage(props) {
const examId = props.match.params.testId.replace(/\?.+/, '');
const paperId = window.getParameterByName('paperId');
const userId = window.getParameterByName('userId');
const [examDetail, setExamDetail] = useState({
answerAnalysis: '',
resultShow: '',
examDesc: '',
examDuration: 0,
examEndTime: '',
examName: '',
examStartTime: '',
paperId: 0,
passRate: 0,
passScore: 0,
resultContent: '',
totalQuestionCount: 0,
totalScore: 0,
userCorrectQuestion: 0,
userExamDuration: 0,
userScore: 0,
}); // 考试详情
const [paperDetail, setPaperDetail] = useState({}); // 试卷详情
const [questionList, setQuestionList] = useState([]); // 试卷题目列表
const [userAnswerList, setUserAnswerList] = useState([]); // 用户答案列表
const [isScrollShow, setIsScrollShow] = useState(false); // 是否展示回到顶部按钮
const { answerAnalysis, resultContent, examName, totalScore, totalQuestionCount, passScore, examDuration, userExamDuration, userScore, userCorrectQuestion } =
examDetail;
useEffect(() => {
bindScroll();
getPaperDetail();
getExamDetail();
}, []);
function bindScroll() {
window.addEventListener('scroll', handleScroll, true);
}
function getExamDetail() {
const params = {
examId,
source: 0,
tenantId: User.getStoreId() || window.getParameterByName('id'),
userId,
};
Service.Hades('public/customerHades/queryUserExamResult', params, {
reject: true,
})
.then((res) => {
const data = { ...res.result };
setExamDetail(data);
})
.catch((res) => {
if (res.code === 'EXAM_IS_NOT_EXIST') {
handleChangeShowErrorPage();
} else {
message.error(res.message);
}
});
}
function getPaperDetail() {
Service.Hades('public/customerHades/queryUserExamAnswer', {
examId,
paperId,
source: 0,
readAnswer: true,
tenantId: User.getStoreId() || window.getParameterByName('id'),
userId,
}).then((res) => {
if (res.success) {
const { paperDetailVO, userExamAnswerVO } = res.result;
const userAnswerList = [...userExamAnswerVO];
const { questionList } = paperDetailVO;
setPaperDetail(paperDetail);
setUserAnswerList(userAnswerList);
setQuestionList(questionList || []);
}
});
}
function handleChangeShowErrorPage() {
setIsShowErrorPage(true);
}
// 用户时长转换
function formatTime(msTime) {
let time = msTime / 1000;
let hour = Math.floor(time / 60 / 60) % 24 > 9 ? Math.floor(time / 60 / 60) % 24 : '0' + (Math.floor(time / 60 / 60) % 24);
let minute = Math.floor(time / 60) % 60 > 9 ? Math.floor(time / 60) % 60 : '0' + (Math.floor(time / 60) % 60);
let second = time % 60 > 9 ? Math.round(time % 60) : '0' + Math.round(time % 60);
return `${hour}:${minute}:${second}`;
}
// 快速跳转题目
function handleQuickActiveQuestion(questionId) {
let selectDom = document.getElementById(`${questionId}`);
selectDom.scrollIntoView({
block: 'center',
});
}
// 回到顶部
function handleGoTop() {
window.scrollTo(0, 0);
}
// 监听滚动,200以后出现回到顶部按钮
function handleScroll() {
if (window.pageYOffset > 200) {
setIsScrollShow(true);
} else {
setIsScrollShow(false);
}
}
function renderResultInfo() {
return (
<div>
<div className='exam-info'>
<div className='info-score item'>
<div className='current-score'>
{userScore}
<img src='https://image.xiaomaiketang.com/xm/TsaApiPyxA.png' />
</div>
<div className='origin-data'>总分{totalScore}</div>
</div>
<div className='info-level item'>
<div className='current-level'>{userScore < passScore ? '不及格' : '及格'}</div>
<div className='origin-data'>及格分{passScore}</div>
</div>
<div className='info-correct item'>
<div className='current-correct'>
{userCorrectQuestion}
<div className='text'>答对题数</div>
</div>
<div className='origin-data'>{totalQuestionCount}</div>
</div>
<div className='info-time item'>
<div className='current-time'>
{formatTime(Number(userExamDuration > examDuration ? examDuration : userExamDuration || 0))}
<div className='text'>用时</div>
</div>
<div className='origin-data'>考试时长{(examDuration || 0) / 60 / 1000}分钟</div>
</div>
</div>
<div className='exam-result'>
<div className='result-title'>
<div className='left-title'>答题情况</div>
<div className='right-tip'>
<span className='correct-num'>{userCorrectQuestion}</span>
<span className='incorrect-num'>/{totalQuestionCount} </span>
道正确
</div>
</div>
<div className='result-content'>
{sortedAnswerList.map((item, index) => {
return (
<div
className='result-content__item'
onClick={() => {
console.log('item', item);
handleQuickActiveQuestion(item.questionId);
}}>
<img
className='icon'
src={item.isCorrect === 1 ? 'https://image.xiaomaiketang.com/xm/FwZa2Kaypc.png' : 'https://image.xiaomaiketang.com/xm/7tRHDf6ysA.png'}
/>
<div className='result-content-box'>{index + 1}</div>
</div>
);
})}
</div>
</div>
<AnswerDescPage userId={userId} />
</div>
);
}
let sortedAnswerList = [];
questionList.map((item) => {
userAnswerList &&
userAnswerList.map((answerItem) => {
if (item.questionId === answerItem.questionId) {
sortedAnswerList.push(answerItem);
}
});
});
return (
<div className='exam-result-page page'>
<Breadcrumbs navList={'答题详情'} goBack={props.history.goBack} />
<div className='center'>
<div className='box'>
<div className='box-content'>
<div
className='exam-head'
style={{
padding: examName.length > 20 ? '8px 0 14px' : '16px 0 29px',
}}>
<div className={`exam-name ${examName.length > 20 ? 'many' : 'few'}`}>{examName}</div>
</div>
{renderResultInfo()}
</div>
</div>
</div>
{isScrollShow && <div className='go-top' onClick={handleGoTop}></div>}
</div>
);
}
export default withRouter(TestDetailPage);
.exam-result-page {
margin: 0 auto;
.go-top {
cursor: pointer;
position: fixed;
width: 48px;
height: 48px;
background-image: url('https://image.xiaomaiketang.com/xm/jWix2xDm4t.png');
background-size: 100%;
box-shadow: 0px 2px 8px 0px rgba(0, 0, 0, 0.08);
border-radius: 4px;
bottom: 125px;
right: calc(~'(100vw - 1232px)/2');
display: flex;
justify-content: center;
align-items: center;
&:hover {
background-image: url('https://image.xiaomaiketang.com/xm/GHBBNDtTDd.png');
}
}
.box {
.box-content {
position: relative;
width: 840px;
margin: 0 auto;
.exam-head {
color: #333;
text-align: center;
.exam-name {
width: 600px;
font-weight: 500;
margin: 0 auto;
font-size: 24px;
line-height: 33px;
}
.many {
font-size: 21px;
line-height: 29px;
}
.few {
font-size: 25px;
line-height: 36px;
}
}
.empty-result {
box-sizing: border-box;
margin: 0 16px;
background: #ffffff;
box-shadow: 0 -15px 10px 0 rgba(0, 34, 121, 0.1);
border-radius: 4px 4px 0 0;
padding-top: 56px;
.lack-desc {
margin-top: 16px;
.title {
font-size: 17px;
font-weight: 500;
color: #333333;
line-height: 24px;
margin-bottom: 4px;
}
.content {
font-size: 15px;
color: #999999;
line-height: 21px;
}
}
.after-desc {
margin-top: 16px;
.title {
font-size: 17px;
font-weight: 500;
color: #333333;
line-height: 24px;
margin-bottom: 20px;
}
.after-show-box {
// margin: 0 37px;
padding: 11px 21px;
background: #f4f6fa;
border-radius: 4px;
font-size: 15px;
color: #999999;
line-height: 21px;
text-align: center;
}
}
}
.exam-info {
width: 840px;
box-sizing: border-box;
margin: 0 auto;
padding: 24px 0 12px;
height: 130px;
background: #ffffff;
box-shadow: 0px 5px 30px 0px rgba(12, 54, 158, 0.08);
border-radius: 4px;
display: flex;
justify-content: center;
.item {
flex: 1 25%;
display: flex;
flex-direction: column;
// height: 130px;
align-items: center;
justify-content: space-between;
position: relative;
.origin-data {
text-align: center;
font-size: 14px;
color: #999999;
line-height: 20px;
}
.line {
&::before {
width: 1px;
height: 40px;
content: '';
position: absolute;
right: 0;
top: 0;
background-color: rgba(232, 232, 232, 1);
}
}
&.info-score {
.current-score {
font-size: 40px;
font-weight: 500;
color: #ff4f4f;
text-align: center;
line-height: 42px;
img {
display: block;
margin: 0 auto;
width: 27px;
height: 12px;
padding-left: 4px;
}
}
}
&.info-level {
.current-level {
font-size: 24px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #333333;
line-height: 33px;
text-align: center;
}
}
&.info-correct {
.current-correct {
display: flex;
flex-direction: column;
padding-bottom: 20px;
justify-content: space-between;
align-items: center;
font-size: 20px;
font-weight: 500;
color: #333333;
line-height: 28px;
.text {
margin-top: 4px;
width: 48px;
height: 17px;
font-size: 12px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #9b9b9b;
line-height: 17px;
text-align: center;
}
}
}
&.info-time {
.current-time {
display: flex;
flex-direction: column;
padding-bottom: 20px;
justify-content: space-between;
align-items: center;
font-size: 20px;
font-weight: 500;
color: #333333;
line-height: 28px;
}
.text {
margin-top: 4px;
width: 48px;
height: 17px;
font-size: 12px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #9b9b9b;
line-height: 17px;
text-align: center;
}
}
}
}
.left-title {
font-size: 20px;
font-weight: 500;
color: #333333;
position: relative;
margin-left: 8px;
line-height: 28px;
&::before {
position: absolute;
content: '';
left: -8px;
top: 50%;
transform: translateY(-50%);
width: 4px;
height: 16px;
background-image: linear-gradient(#2966ff 83.5%, #0acca4 16.5%);
}
}
.exam-result {
padding: 44px 0 24px 0;
vertical-align: middle;
.result-title {
display: flex;
justify-content: space-between;
margin-bottom: 30px;
line-height: 24px;
.right-tip {
font-size: 15px;
font-weight: 500;
color: #999999;
.correct-num {
color: #16e0b7;
}
.incorrect-num {
font-size: 11px;
}
}
}
.result-content {
display: flex;
flex-wrap: wrap;
&__item {
position: relative;
margin: 0 16px 16px 0;
width: 36px;
height: 36px;
background: #f4f6fa;
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
&:nth-child(5n) {
margin-right: 50px;
}
&:nth-child(15n) {
margin-right: 0px;
}
.icon {
width: 16px;
height: 16px;
position: absolute;
left: 50%;
top: 0;
transform: translate(-50%, -50%);
}
.result-content-box {
width: 36px;
height: 36px;
font-size: 15px;
line-height: 36px;
background: #f4f6fa;
border-radius: 4px;
text-align: center;
}
}
}
}
}
}
.footer-btn {
width: 100%;
position: fixed;
bottom: 0;
left: 0;
height: 64px;
background-color: #fff;
display: flex;
align-items: center;
justify-content: center;
border-top: 1px solid rgba(238, 238, 238, 1);
box-sizing: border-box;
.text {
cursor: pointer;
background: #ffb714;
border-radius: 5px;
width: 342px;
font-size: 15px;
color: #ffffff;
line-height: 44px;
text-align: center;
&.disabled {
background-color: #ccc;
}
}
}
}
.dataAnalysic{
.titleBox{
font-size: 19px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #333333;
line-height: 26px;
background: #FFFFFF;
// padding: 20px 24px;
// margin-bottom: 8px;
.tips{
width: 4px;
height: 16px;
background: #336DFF;
display: inline-block;
margin-right: 4px;
}
.dataAnalysic {
.titleBox {
position: relative;
font-size: 19px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #333333;
line-height: 26px;
background: #ffffff;
&::before {
width: 4px;
height: 12px;
content: '';
background-image: linear-gradient(#2966ff 83.5%, #0acca4 16.5%);
display: inline-block;
margin-right: 8px;
}
}
\ No newline at end of file
}
.ant-tabs-content-holder {
margin-top: 8px;
}
}
.examination-manager{
.status{
display: inline-block;
margin-left: 4px;
border: 1px solid #999;
padding: 2px 4px;
line-height: 16px;
}
.ant-table-column-sorters {
justify-content: flex-end;
}
.examination-manager {
.status {
display: inline-block;
margin-left: 4px;
border: 1px solid #999;
padding: 2px 4px;
line-height: 16px;
}
.ant-table-column-sorter {
margin-top: 0px !important;
.ant-table-column-sorter {
margin-top: 0px !important;
}
.ant-table tbody tr {
&:nth-child(even) {
background: #fff;
}
&:nth-child(odd) {
background: #fafafa;
}
}
\ No newline at end of file
}
}
.dataPanal{
border-radius: 4px;
border: 1px solid #E8E8E8;
display: flex;
.item{
text-align: center;
// width: 29.9%;
.dataPanal {
border-radius: 4px;
border: 1px solid #e8e8e8;
display: flex;
.item {
text-align: center;
// width: 29.9%;
position: relative;
flex: 1;
.num {
font-size: 26px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #333333;
line-height: 26px;
margin-top: 12px;
}
.percent {
margin-top: 6px;
font-size: 12px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #999999;
line-height: 17px;
height: 20px;
margin-bottom: 18px;
}
.subTitle {
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #666666;
line-height: 20px;
margin-bottom: 12px;
}
.type {
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #333333;
line-height: 20px;
span {
color: rgba(153, 153, 153, 1);
}
.icon {
color: rgba(204, 204, 204, 1);
font-size: 16px;
margin-right: 4px;
position: relative;
flex: 1;
.num{
font-size: 26px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #333333;
line-height: 26px;
margin-top: 12px;
}
.percent{
margin-top: 6px;
font-size: 12px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #999999;
line-height: 17px;
height: 20px;
margin-bottom: 18px;
}
.subTitle{
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #666666;
line-height: 20px;
margin-bottom: 12px;
}
.type{
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #333333;
line-height: 20px;
span{
color: rgba(153, 153, 153, 1);
}
.icon{
color: rgba(204, 204, 204, 1);
font-size: 16px;
margin-right: 4px;
position: relative;
top: 1px;
}
}
&:after{
content: '';
width: 0px;
height: 40px;
position: absolute;
width: 1px;
background-color: rgba(232, 232, 232, 1);
top: 40px;
right: 0px;
}
top: 1px;
}
}
&:last-child{
&:after{
display: none;
}
}
&:after {
content: '';
width: 0px;
height: 40px;
position: absolute;
width: 1px;
background-color: rgba(232, 232, 232, 1);
top: 40px;
right: 0px;
}
&:last-child {
&:after {
display: none;
}
}
.exstatus{
width: 4px;
height: 4px;
background: rgb(35, 143, 255);
display: inline-block;
border-radius: 50%;
position: relative;
top: -4px;
}
.exstatus {
width: 4px;
height: 4px;
background: rgb(35, 143, 255);
display: inline-block;
border-radius: 50%;
position: relative;
top: -4px;
}
}
.answer-detail {
color: rgb(35, 143, 255);
}
.analysic-content {
.ant-table-bordered .ant-table-tbody tr {
&.analysic-content-row {
height: 50px;
}
}
\ No newline at end of file
}
}
import React from 'react';
import { Modal, TreeSelect } from 'antd';
import './MoveModal.less';
class MoveModal extends React.Component {
constructor(props) {
super(props);
this.state = {
categoryId: undefined,
};
}
handleChangeCatalogList = (value, label) => {
this.setState({ categoryId: value, categoryName: label[0] });
};
filterData = (data, id) => {
let newTreeData = data.map((item) => {
item.disabled = id === item.id;
if (item.children) {
item.children = this.filterData(item.children, id);
}
return item;
});
return newTreeData;
}
render() {
const { visible, title, onCancel, onOk, data, length, categoryId: id } = this.props;
const { categoryId } = this.state;
const moveData = this.filterData(data, id);
return (
<Modal
title={`移动${title}`}
visible={visible}
onCancel={onCancel}
maskClosable={false}
className="common-move-modal"
onOk={() => onOk(categoryId)}
>
<div className="tip">
<span className="icon iconfont">&#xe6f2;</span>
<span className="text">已选择<span style={{ color: '#2966FF' }}>{length}</span>{title},移动后,原有分类将移除此{title}</span>
</div>
<div className="move-item" id="move-item">
<span className="label">选择分类:</span>
<TreeSelect
showSearch
treeNodeFilterProp="title"
getPopupContainer={() => document.querySelector('#move-item')}
style={{ width: 240 }}
treeData={moveData}
placeholder="请选择分类"
allowClear
value={categoryId}
onChange={(value, label) => {
this.handleChangeCatalogList(value, label);
}}
/>
</div>
</Modal>
)
}
}
export default MoveModal;
\ No newline at end of file
.common-move-modal {
.tip {
display: flex;
align-items: center;
margin-bottom: 16px;
.iconfont {
font-size: 14px;
color: #BFBFBF;
margin-right: 8px;
}
.text {
color: #999;
font-size: 14px;
}
}
.move-item {
.label {
color: #333;
}
}
.ant-select-tree .ant-select-tree-node-content-wrapper.ant-select-tree-node-selected {
background: rgba(41, 102, 255, 0.06);
}
}
\ No newline at end of file
.operate-paper-page {
.box {
margin-bottom: 52px !important;
.ant-form-item {
margin-bottom: 24px !important;
}
.table-style {
border: 1px solid #f0f0f0 !important;
}
......@@ -12,7 +15,6 @@
margin-left: 12px;
}
.choose-btn {
margin-top: 8px;
margin-bottom: 12px;
}
.paper-info-tip {
......@@ -60,10 +62,14 @@
}
}
.ant-table tbody tr {
&:last-child {
td {
border-bottom: none!important;
}
&:nth-child(even) {
background: #fff;
}
&:nth-child(odd) {
background: #fafafa;
}
td {
border-bottom: none!important;
}
}
......@@ -82,4 +88,23 @@
.ant-dropdown-menu-item-selected > span {
color: #333333;
}
\ No newline at end of file
}
.type-order-modal {
.type-order-table {
tr {
background: #F7F8F9 !important;
display: flex;
margin-bottom: 8px;
width: 521px;
justify-content: space-between;
td {
border: none !important;
}
}
.ant-table-tbody > tr:hover:not(.ant-table-expanded-row):not(.ant-table-row-selected) > td {
background: #F7F8F9 !important;
}
}
}
.paper-list {
.select-box {
display: flex;
align-items: center;
.select-container{
margin-right: 24px;
.con{
background: #E9EFFF;
border-radius: 4px;
padding: 3px 16px;
display: inline-flex;
align-items: center;
justify-content: space-between;
.tip{
font-size:14px;
color:#2966FF;
margin-right:8px;
}
.text{
font-size:14px;
color:#666;
margin-right:30px;
}
.clear{
color:#5289FA;
font-size:14px;
}
}
}
}
.ant-radio-wrapper{
left: -10px;
}
......@@ -45,7 +74,7 @@
}
.paper-list-content {
position: relative;
margin-top: 16px;
margin-top: 12px;
.empty-list-tip {
color: #2966FF;
cursor: pointer;
......
......@@ -2,7 +2,7 @@
* @Author: yuananting
* @Date: 2021-02-25 11:23:47
* @LastEditors: yuananting
* @LastEditTime: 2021-05-20 11:43:21
* @LastEditTime: 2021-05-30 18:17:05
* @Description: 助学工具-新建试卷-选择题目列表
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
......@@ -16,6 +16,7 @@ import {
Select,
Tooltip,
message,
DatePicker,
} from "antd";
import { PageControl } from "@/components";
import "./SelectQuestionList.less";
......@@ -23,8 +24,10 @@ import User from "@/common/js/user";
import AidToolService from "@/domains/aid-tool-domain/AidToolService";
import _ from "underscore";
import Bus from "@/core/bus";
import moment from 'moment';
const { Search } = Input;
const { RangePicker } = DatePicker;
const questionTypeEnum = {
SINGLE_CHOICE: "单选题",
......@@ -68,12 +71,15 @@ class SelectQuestionList extends Component {
categoryId: null, // 当前题库分类Id
questionName: null, // 题目名称
questionType: null, // 题目类型
updateDateStart: null,
updateDateEnd: null,
source: 0,
tenantId: User.getStoreId(),
userId: User.getStoreUserId(),
},
dataSource: [],
selectQuestionKeys: [],
expandFilter: false,
};
}
......@@ -98,6 +104,8 @@ class SelectQuestionList extends Component {
order: "UPDATED_DESC", // 排序规则
questionName: null, // 题目名称
questionType: null, // 题目类型
updateDateStart: null,
updateDateEnd: null,
};
this.setState({ query: _query }, () => {
this.queryQuestionPageListWithContent();
......@@ -134,6 +142,8 @@ class SelectQuestionList extends Component {
order: "UPDATED_DESC", // 排序规则
questionName: null, // 题目名称
questionType: null, // 题目类型
updateDateStart: null,
updateDateEnd: null,
};
this.setState({ query: _query }, () => {
this.queryQuestionPageListWithContent();
......@@ -144,6 +154,14 @@ class SelectQuestionList extends Component {
parseColumns = () => {
const columns = [
{
title: "题型",
key: "questionTypeEnum",
dataIndex: "questionTypeEnum",
render: (val) => {
return questionTypeEnum[val];
},
},
{
title: "题目",
key: "questionStem",
dataIndex: "questionStem",
......@@ -170,14 +188,6 @@ class SelectQuestionList extends Component {
},
},
{
title: "题型",
key: "questionTypeEnum",
dataIndex: "questionTypeEnum",
render: (val) => {
return questionTypeEnum[val];
},
},
{
title: "正确率",
key: "accuracy",
dataIndex: "accuracy",
......@@ -215,11 +225,23 @@ class SelectQuestionList extends Component {
// 改变搜索条件
handleChangeQuery = (searchType, value) => {
const _query = this.state.query;
switch (searchType) {
case "questionName":
_query.questionName = value;
break;
case "updatedTime":
_query.updateDateStart = value && value[0]?.startOf('day').valueOf();
_query.updateDateEnd = value && value[1]?.endOf('day').valueOf();
break;
case "questionType":
_query.questionType = value;
break
}
this.setState(
{
query: {
...this.state.query,
[searchType]: value || null,
..._query,
current: 1,
},
},
......@@ -281,6 +303,7 @@ class SelectQuestionList extends Component {
total,
query,
selectQuestionKeys = [],
expandFilter,
} = this.state;
const { current, size, questionName, questionType } = query;
const rowSelection = {
......@@ -364,6 +387,17 @@ class SelectQuestionList extends Component {
})}
</Select>
</div>
<div className="search-condition__item">
<span className="search-label">更新时间:</span>
<RangePicker
value={[
query.updateDateStart ? moment(Number(query.updateDateStart)) : null,
query.updateDateEnd ? moment(Number(query.updateDateEnd)) : null
]}
onChange={(value) => {
this.handleChangeQuery("updatedTime", value)
}} />
</div>
</div>
<div className="reset-fold-area">
......
......@@ -2,19 +2,22 @@
.select-question-filter {
position: relative;
.search-condition {
width: calc(100% - 80px);
width: calc(100% - 20px);
display: flex;
align-items: center;
flex-wrap: wrap;
&__item {
margin-right: 3%;
width: 30%;
margin-bottom: 16px;
display: flex;
.search-label {
vertical-align: middle;
display: inline-block;
height: 32px;
line-height: 32px;
flex-shrink: 0;
}
}
}
......
......@@ -2,12 +2,13 @@
* @Author: yuananting
* @Date: 2021-03-27 11:15:03
* @LastEditors: yuananting
* @LastEditTime: 2021-04-15 13:22:10
* @LastEditTime: 2021-06-01 17:28:21
* @Description: 助学工具-试卷-预览试卷
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import React, { Component } from "react";
import { Modal, ConfigProvider, Empty } from "antd";
import Lottie from 'react-lottie';
import User from "@/common/js/user";
import AidToolService from "@/domains/aid-tool-domain/AidToolService";
import "./PreviewPaperModal.less";
......@@ -15,6 +16,7 @@ import ScanFileModal from "@/modules/resource-disk/modal/ScanFileModal";
import _ from "underscore";
import XMAudio from "../../components/XMAudio";
import { NUM_TO_WORD_MAP } from "@/common/constants/punchClock/punchClock";
import previewEmpty from '../../../lottie/previewEmpty/data.json';
const questionTypeList = {
SINGLE_CHOICE: "单选题",
MULTI_CHOICE: "多选题",
......@@ -254,13 +256,28 @@ class PreviewPaperModal extends Component {
// 自定义空状态
customizeRenderEmpty = () => {
const defaultOptions = {
loop: true,
autoplay: true,
animationData: previewEmpty,
rendererSettings: {
preserveAspectRatio: 'xMidYMid slice'
}
}
return (
<Empty
image="https://image.xiaomaiketang.com/xm/emptyTable.png"
imageStyle={{
height: 100,
}}
description={"暂无内容"}
image={
<div style={{ marginTop: 24 }}>
<Lottie
options={defaultOptions}
height={150}
width={150}
isStopped={false}
isPaused={false}
/>
</div>
}
description={<span style={{ display: 'block', paddingBottom: 24, marginTop: 50 }}>暂无内容</span>}
></Empty>
);
};
......@@ -284,7 +301,7 @@ class PreviewPaperModal extends Component {
footer={null}
onCancel={this.props.close}
>
{paperName && <div className="paper-title">{paperName}</div>}
{paperName && <div className="paper-title">{paperName.length > 40 ? paperName.substring(0, 40) : paperName}</div>}
{questionList && questionList.length > 0 ? (
<div className="question-list-box">
{_.map(questionList, (questionItem, questionIndex) => {
......
......@@ -2,7 +2,7 @@
* @Author: yuananting
* @Date: 2021-03-29 10:52:26
* @LastEditors: yuananting
* @LastEditTime: 2021-05-08 16:11:27
* @LastEditTime: 2021-06-07 14:45:02
* @Description: 助学工具-试卷-新建选择题目弹窗
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
......@@ -42,7 +42,8 @@ class SelectQuestionModal extends Component {
width={1080}
onOk={() => {
this.props.setSelectedQuestion(
this.listRef.current.state.selectQuestionKeys.map((item) => {
this.listRef.current.state.selectQuestionKeys.map((item, index) => {
item.sorterIndex = index;
item.questionId = item.id || item.questionId;
item.questionType = item.questionTypeEnum || item.questionType;
item.score = item.score || 2;
......
/*
* @Author: yuananting
* @Date: 2021-02-25 14:34:29
* @LastEditors: wufan
* @LastEditTime: 2021-05-14 18:17:08
* @LastEditors: yuananting
* @LastEditTime: 2021-06-09 12:00:12
* @Description: 助学工具-题库-操作题目Tab
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
......@@ -66,23 +66,25 @@ class OperateQuestionTab extends Component {
}
componentDidMount() {
const { chooseOptions } = this.state;
const { questionTypeKey } = this.props;
const isEditCurrent =
getParameterByName("id") &&
getParameterByName("type") === questionTypeKey;
const optionSize = isEditCurrent ? 20 : 4;
if (
["INDEFINITE_CHOICE", "MULTI_CHOICE", "SINGLE_CHOICE"].includes(
this.props.questionTypeKey
questionTypeKey
)
) {
if (chooseOptions.length === 0) {
// 选择题(单选 多选 不定项)-插入4条默认选项
for (var i = 0; i < 4; i++) {
this.handleAddOption();
this.setState({
[`optionsValidate_${i}`]: "success",
[`optionsText_${i}`]: "",
});
}
// 选择题(单选 多选 不定项)-插入4条默认选项
for (var i = 0; i < optionSize; i++) {
this.handleAddOption();
this.setState({
[`optionsValidate_${i}`]: "success",
[`optionsText_${i}`]: "",
});
}
} else if (this.props.questionTypeKey === "JUDGE") {
} else if (questionTypeKey === "JUDGE") {
this.initJudgeOption("正确");
this.initJudgeOption("错误");
}
......@@ -634,9 +636,9 @@ class OperateQuestionTab extends Component {
this.state.stemContent,
(contentItem) => contentItem.type === "RICH_TEXT"
);
if(stemContent.textLength > 1000) {
if (stemContent.textLength > 1000) {
validateError++;
}
}
let stem = stemContent.content.replace(/<[^>]+>/g, "");
stem = stem.replace(/\&nbsp\;/gi, "");
stem = stem.replace(/\s+/g, "");
......@@ -694,7 +696,7 @@ class OperateQuestionTab extends Component {
optionUnChecked = item.isCorrectAnswer
? optionUnChecked
: optionUnChecked + 1;
if(optionContent[0].textLength > 1000) {
if (optionContent[0].textLength > 1000) {
validateError++;
}
let optionInput = optionContent[0].content.replace(/<[^>]+>/g, "");
......@@ -1040,11 +1042,11 @@ class OperateQuestionTab extends Component {
return dom ? (
<div
className="question-item_question-content"
style={{
display: ["PICTURE", "VIDEO"].includes(type)
? "inline-grid"
: "flex",
}}
style={
!["PICTURE", "VIDEO"].includes(type)
? { display: "flex" }
: { float: "left" }
}
key={index}
>
{dom}
......@@ -1194,10 +1196,8 @@ class OperateQuestionTab extends Component {
data-label="正确答案"
>
{_.map(chooseOptions, (optionItem, optionIndex) => {
const {
questionOptionContentList,
isCorrectAnswer,
} = optionItem;
const { questionOptionContentList, isCorrectAnswer } =
optionItem;
optionItem.optionSort = optionIndex;
const mediaBtn = ["VOICE", "AUDIO", "PICTURE"];
const placeHold =
......
......@@ -2,7 +2,7 @@
border-radius: 2px;
padding: 16px;
position: relative;
margin-bottom: 35px;
margin-bottom: 70px;
.editor-fill-box_single {
border-radius: 4px;
......@@ -24,7 +24,7 @@
color: #999999;
margin-top: 8px;
.fill-info_icon {
color: #2966FF;
color: #2966ff;
font-size: 14px;
padding-left: 9px;
cursor: pointer;
......@@ -72,7 +72,6 @@
}
.audio-box {
box-shadow: 0px 2px 6px 0px rgba(0, 0, 0, 0.1);
padding: 10px 20px;
}
.img-box {
max-width: 88px;
......@@ -229,7 +228,7 @@
line-height: 33px;
align-self: stretch;
.option-operate_item__icon:hover {
color: #2966FF;
color: #2966ff;
}
.icon {
color: #bfbfbf;
......@@ -252,7 +251,7 @@
border-radius: 4px;
border: 1px dashed #e8e8e8;
font-size: 14px;
color: #2966FF;
color: #2966ff;
line-height: 44px;
text-align: center;
cursor: pointer;
......
......@@ -8,13 +8,16 @@
flex-wrap: wrap;
&__item {
display: flex;
margin-right: 3%;
margin-bottom: 16px;
width: 30%;
.search-label {
vertical-align: middle;
display: inline-block;
height: 32px;
line-height: 32px;
flex-shrink: 0;
}
}
}
......@@ -37,12 +40,37 @@
}
}
}
.select-container{
.con {
background: #E9EFFF;
border-radius: 4px;
padding: 3px 16px;
display: inline-flex;
align-items: center;
justify-content: space-between;
.tip {
font-size: 14px;
color: #2966FF;
margin-right: 8px;
}
.text {
font-size: 14px;
color: #666;
margin-right: 30px;
}
.clear {
color: #5289FA;
font-size: 14px;
}
}
}
.data-icon {
cursor: pointer;
}
.question-list-content {
position: relative;
margin-top: 16px;
margin-top: 12px;
.empty-list-tip {
color: #2966FF;
cursor: pointer;
......
......@@ -32,7 +32,7 @@
color: #666666;
.input-box {
margin-bottom: 8px;
display: inline-block;
// display: inline-block;
*:not(p) {
font-weight: normal !important;
font-size: 14px !important;
......
......@@ -14,13 +14,13 @@ import UserManage from '@/modules/college-manage/UserManagePage';
import StoreDecorationPage from '@/modules/store-manage/StoreDecorationPage';
import CourseCatalogPage from '@/modules/store-manage/CourseCatalogPage';
import LiveCoursePage from '@/modules/course-manage/LiveCoursePage';
import AddLivePage from '@/modules/course-manage/AddLive'
import VideoCoursePage from '@/modules/course-manage/video-course'
import GraphicsCoursePage from '@/modules/course-manage/graphics-course'
import OfflineCoursePage from '@/modules/course-manage/offline-course'
import AddVideoCoursePage from '@/modules/course-manage/video-course/AddVideoCourse'
import AddGraphicsCoursePage from '@/modules/course-manage/graphics-course/AddGraphicsCourse'
import AddOfflineCoursePage from '@/modules/course-manage/offline-course/AddOfflineCourse'
import AddLivePage from '@/modules/course-manage/AddLive';
import VideoCoursePage from '@/modules/course-manage/video-course';
import GraphicsCoursePage from '@/modules/course-manage/graphics-course';
import OfflineCoursePage from '@/modules/course-manage/offline-course';
import AddVideoCoursePage from '@/modules/course-manage/video-course/AddVideoCourse';
import AddGraphicsCoursePage from '@/modules/course-manage/graphics-course/AddGraphicsCourse';
import AddOfflineCoursePage from '@/modules/course-manage/offline-course/AddOfflineCourse';
// import DataList from '@/modules/course-manage/DataList/DataList';
// import ClassBook from '@/modules/resource-disk';
import ResourceDisk from '@/modules/resource-disk';
......@@ -33,145 +33,152 @@ import CourseCategoryManage from '@/modules/teach-tool/components/CourseCategory
import QuestionManageIndex from '@/modules/teach-tool/question-manage/Index';
import PaperManageIndex from '@/modules/teach-tool/paper-manage/Index';
import ExaminationManagerIndex from '@/modules/teach-tool/examination-manager/Index';
import KnowledgeBase from "@/modules/knowledge-base/index";
import ExaminationManagerTestDetail from '@/modules/teach-tool/examination-manager/TestDetailPage';
import KnowledgeBase from '@/modules/knowledge-base/index';
import CollegeInfoPage from '@/modules/college-manage/CollegeInfoPage';
const mainRoutes = [
{
path: "/home",
path: '/home',
component: Home,
name: "中心首页",
name: '中心首页',
},
{
path: "/employees-manage",
path: '/employees-manage',
component: EmployeesManagePage,
name: "员工管理",
name: '员工管理',
},
{
path: '/college-employee',
component: EmployeeManage,
name: '员工管理'
component: EmployeeManage,
name: '员工管理',
},
{
path: '/personal-info',
component: personalInfoPage,
name: '个人信息'
component: personalInfoPage,
name: '个人信息',
},
{
path: "/user-manage",
path: '/user-manage',
component: UserManagePage,
name: "学员管理",
name: '学员管理',
},
{
path: '/college-user',
component: UserManage,
name: '学员管理'
component: UserManage,
name: '学员管理',
},
{
path: '/store-decoration',
component: StoreDecorationPage,
name: '学院装修'
component: StoreDecorationPage,
name: '学院装修',
},
{
path: "/live-course",
path: '/live-course',
component: LiveCoursePage,
name: "直播课",
name: '直播课',
},
{
path: "/video-course",
path: '/video-course',
component: VideoCoursePage,
name: "视频课",
name: '视频课',
},
{
path: "/graphics-course",
path: '/graphics-course',
component: GraphicsCoursePage,
name: "图文课",
name: '图文课',
},
{
path: "/offline-course",
path: '/offline-course',
component: OfflineCoursePage,
name: "线下课",
name: '线下课',
},
{
path: "/create-live-course",
path: '/create-live-course',
component: AddLivePage,
name: "创建直播课",
name: '创建直播课',
},
{
path: "/create-video-course",
path: '/create-video-course',
component: AddVideoCoursePage,
name: "创建视频课",
name: '创建视频课',
},
{
path: "/knowledge-base",
path: '/knowledge-base',
// component:ResourceDisk,
component: KnowledgeBase,
name: "知识库",
name: '知识库',
},
{
path: "/create-graphics-course",
path: '/create-graphics-course',
component: AddGraphicsCoursePage,
name: "创建图文课",
name: '创建图文课',
},
{
path: "/create-offline-course",
path: '/create-offline-course',
component: AddOfflineCoursePage,
name: "创建线下课",
name: '创建线下课',
},
{
path: "/resource-disk",
path: '/resource-disk',
component: ResourceDisk,
name: "资料云盘",
name: '资料云盘',
},
{
path: '/question-manage-index',
component:QuestionManageIndex,
name: '题库'
component: QuestionManageIndex,
name: '题库',
},
{
path: '/paper-manage-index',
component:PaperManageIndex,
name: '试卷'
component: PaperManageIndex,
name: '试卷',
},
{
path: '/examination-manage-index',
component:ExaminationManagerIndex,
name: '考试'
component: ExaminationManagerIndex,
name: '考试',
},
{
path: '/test-detail/:testId',
component: ExaminationManagerTestDetail,
// () => import('@/modules/teach-tool/examination-manager/TestDetailPage'),
name: '答题详情',
},
{
path: '/course-category-manage',
component:CourseCategoryManage,
name: '分类管理'
component: CourseCategoryManage,
name: '分类管理',
},
{
path: "/switch-route",
path: '/switch-route',
component: SwitchRoute,
name: "登录后跳转承载页",
name: '登录后跳转承载页',
},
{
path: "/plan",
path: '/plan',
component: PlanPage,
name: "培训计划",
name: '培训计划',
},
{
path: "/create-plan",
path: '/create-plan',
component: AddPlanPage,
name: "创建视频课",
name: '创建视频课',
},
{
path: '/store-info',
component:StoreInfoPage,
name: '学院信息'
component: StoreInfoPage,
name: '学院信息',
},
{
path: '/college-info',
component: CollegeInfoPage,
name: '学院信息'
component: CollegeInfoPage,
name: '学院信息',
},
{
path: "/learning-data",
path: '/learning-data',
component: LearningDataPage,
name: "学习数据",
name: '学习数据',
},
];
......
......@@ -2,7 +2,7 @@
* @Author: yuananting
* @Date: 2021-02-21 15:53:31
* @LastEditors: Please set LastEditors
* @LastEditTime: 2021-05-30 11:00:09
* @LastEditTime: 2021-06-08 16:46:15
* @Description: 描述一下咯
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
......@@ -44,22 +44,6 @@ export const menuList: any = [
]
},
{
groupName: "知识库",
groupCode: "CloudKnowledge",
icon: '&#xe8a8;',
link: '/knowledge-base',
img:'https://image.xiaomaiketang.com/xm/8sbP5rGQWh.png',
selectImg:'https://image.xiaomaiketang.com/xm/hJKCfibC22.png'
},
{
groupName: "资料云盘",
groupCode: "CloudDisk",
icon: '&#xe8aa;',
link: '/resource-disk',
img:'https://image.xiaomaiketang.com/xm/zGKbXJPzXx.png',
selectImg:'https://image.xiaomaiketang.com/xm/5sN4MzjxYc.png',
},
{
groupName: "培训管理",
groupCode: "TrainManage",
icon: '&#xe8a6;',
......@@ -96,17 +80,28 @@ export const menuList: any = [
]
},
{
groupName: "学院管理",
groupCode: "CloudShop",
groupName: "知识库",
groupCode: "CloudKnowledge",
icon: '&#xe8a8;',
link: '/knowledge-base',
img:'https://image.xiaomaiketang.com/xm/8sbP5rGQWh.png',
selectImg:'https://image.xiaomaiketang.com/xm/hJKCfibC22.png'
},
{
groupName: "资料云盘",
groupCode: "CloudDisk",
icon: '&#xe8aa;',
link: '/resource-disk',
img:'https://image.xiaomaiketang.com/xm/zGKbXJPzXx.png',
selectImg:'https://image.xiaomaiketang.com/xm/5sN4MzjxYc.png',
},
{
groupName: "人员管理",
groupCode: "PersonManage",
icon: '&#xe8a4;',
img:'https://image.xiaomaiketang.com/xm/Q8i5RSMKNc.png',
img:'https://image.xiaomaiketang.com/xm/PRCnrt35y8.png',
children: [
{
groupName: "学院信息",
groupCode: "ShopInfo",
link: '/college-info'
},
{
groupName: "员工管理",
groupCode: "ShopStaff",
link: '/college-employee'
......@@ -115,11 +110,19 @@ export const menuList: any = [
groupName: "学员管理",
groupCode: "ShopUser",
link: '/college-user'
},
}
]
},
{
groupName: "学院管理",
groupCode: "CloudShop",
icon: '&#xe8a4;',
img:'https://image.xiaomaiketang.com/xm/Q8i5RSMKNc.png',
children: [
{
groupName: "课程分类",
groupCode: "CourseCategory",
link: '/course-category-manage'
groupName: "学院信息",
groupCode: "ShopInfo",
link: '/college-info'
},
{
groupName: "学院装修",
......@@ -127,6 +130,11 @@ export const menuList: any = [
link: '/store-decoration'
},
{
groupName: "分类管理",
groupCode: "CourseCategory",
link: '/course-category-manage'
},
{
groupName: "H5学院",
groupCode: "ShopDecorationH5",
link: '/store-decoration/h5'
......@@ -138,5 +146,4 @@ export const menuList: any = [
}
]
},
]
\ No newline at end of file
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