Commit b61f0978 by yuananting

fix:解决合并分类拖拽接口修改及分类数为0隐藏的冲突

parents 9c90120f 495240cf
......@@ -2,89 +2,89 @@
* @Author: yuananting
* @Date: 2021-03-03 15:13:12
* @LastEditors: fusanqiasng
* @LastEditTime: 2021-05-25 10:07:03
* @LastEditTime: 2021-06-15 11:53:12
* @Description: 助学工具接口
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import Service from '@/common/js/service'
import Service from '@/common/js/service';
export function queryExternalCategoryTree(params: object) {
return Service.Hades('public/externalHades/queryCategoryTree', params)
return Service.Hades('public/externalHades/queryCategoryTree', params);
}
export function queryCategoryTree(params: object) {
return Service.Hades('public/hades/queryCategoryTree', params)
return Service.Hades('public/hades/queryCategoryTree', params);
}
export function addCategory(params: object) {
return Service.Hades('public/hades/addCategory', params)
return Service.Hades('public/hades/addCategory', params);
}
export function delCategory(params: object) {
return Service.Hades('public/hades/delCategory', params)
return Service.Hades('public/hades/delCategory', params);
}
export function editCategory(params: object) {
return Service.Hades('public/hades/editCategory', params)
return Service.Hades('public/hades/editCategory', params);
}
export function editCategoryTree(params: object) {
return Service.Hades('public/hades/editCategoryTree', params)
export function moveCategoryTree(params: object) {
return Service.Hades('public/hades/moveCategory', params);
}
export function queryQuestionPageList(params: object) {
return Service.Hades('public/hades/queryQuestionPageList', params)
return Service.Hades('public/hades/queryQuestionPageList', params);
}
export function addQuestion(params: object) {
return Service.Hades('public/hades/addQuestion', params)
return Service.Hades('public/hades/addQuestion', params);
}
export function deleteQuestion(params: object) {
return Service.Hades('public/hades/deleteQuestion', params)
return Service.Hades('public/hades/deleteQuestion', params);
}
export function queryQuestionDetails(params: object) {
return Service.Hades('public/hades/queryQuestionDetails', params)
return Service.Hades('public/hades/queryQuestionDetails', params);
}
export function editQuestion(params: object) {
return Service.Hades('public/hades/editQuestion', params)
return Service.Hades('public/hades/editQuestion', params);
}
export function batchImport(params: object) {
return Service.Hades('public/hades/batchImport', params)
return Service.Hades('public/hades/batchImport', params);
}
export function createPaper(params: object) {
return Service.Hades('public/hades/createPaper', params)
return Service.Hades('public/hades/createPaper', params);
}
export function queryPaperPageList(params: object) {
return Service.Hades('public/hades/queryPaperPageList', params)
return Service.Hades('public/hades/queryPaperPageList', params);
}
export function deletePaper(params: object) {
return Service.Hades('public/hades/deletePaper', params)
return Service.Hades('public/hades/deletePaper', params);
}
export function queryPaperDetail(params: object) {
return Service.Hades('public/hades/queryPaperDetail', params)
return Service.Hades('public/hades/queryPaperDetail', params);
}
export function viewPaper(params: object) {
return Service.Hades('public/hades/viewPaper', params)
return Service.Hades('public/hades/viewPaper', params);
}
export function editPaper(params: object) {
return Service.Hades('public/hades/editPaper', params)
return Service.Hades('public/hades/editPaper', params);
}
export function batchQueryQuestionDetails(params: object) {
return Service.Hades('public/hades/batchQueryQuestionDetails', params)
return Service.Hades('public/hades/batchQueryQuestionDetails', params);
}
export function queryQuestionPageListWithContent(params: object) {
return Service.Hades('public/hades/queryQuestionPageListWithContent', params)
return Service.Hades('public/hades/queryQuestionPageListWithContent', params);
}
......@@ -2,7 +2,7 @@
* @Author: yuananting
* @Date: 2021-03-11 11:34:37
* @LastEditors: fusanqiasng
* @LastEditTime: 2021-05-24 23:44:39
* @LastEditTime: 2021-06-15 11:25:18
* @Description: 助学工具接口
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
......@@ -12,7 +12,7 @@ import {
addCategory,
delCategory,
editCategory,
editCategoryTree,
moveCategoryTree,
addQuestion,
queryQuestionPageList,
deleteQuestion,
......@@ -26,8 +26,8 @@ import {
viewPaper,
editPaper,
batchQueryQuestionDetails,
queryQuestionPageListWithContent
} from '@/data-source/aidTool/request-apis'
queryQuestionPageListWithContent,
} from '@/data-source/aidTool/request-apis';
export default class AidToolService {
/**
* 查询运营端分类书
......@@ -35,101 +35,101 @@ export default class AidToolService {
* @returns
*/
static queryExternalCategoryTree(parmas: any) {
return queryExternalCategoryTree(parmas)
return queryExternalCategoryTree(parmas);
}
// 获取题目分类树
static queryCategoryTree(params: any) {
return queryCategoryTree(params)
return queryCategoryTree(params);
}
// 新增题目分类
static addCategory(params: any) {
return addCategory(params)
return addCategory(params);
}
// 删除分类
static delCategory(params: any) {
return delCategory(params)
return delCategory(params);
}
// 编辑分类
static editCategory(params: any) {
return editCategory(params)
return editCategory(params);
}
// 编辑分类树(拖拽)
static editCategoryTree(params: any) {
return editCategoryTree(params)
// 拖拽移动分类树
static moveCategoryTree(params: any) {
return moveCategoryTree(params);
}
// 查询题目列表
static queryQuestionPageList(params: any) {
return queryQuestionPageList(params)
return queryQuestionPageList(params);
}
// 添加题目
static addQuestion(params: any) {
return addQuestion(params)
return addQuestion(params);
}
// 删除题目
static deleteQuestion(params: any) {
return deleteQuestion(params)
return deleteQuestion(params);
}
// 预览题目
static queryQuestionDetails(params: any) {
return queryQuestionDetails(params)
return queryQuestionDetails(params);
}
// 编辑题目
static editQuestion(params: any) {
return editQuestion(params)
return editQuestion(params);
}
// 批量导入
static batchImport(params: any) {
return batchImport(params)
return batchImport(params);
}
// 创建试卷
static createPaper(params: any) {
return createPaper(params)
return createPaper(params);
}
// 查询试卷列表
static queryPaperPageList(params: any) {
return queryPaperPageList(params)
return queryPaperPageList(params);
}
// 删除试卷
static deletePaper(params: any) {
return deletePaper(params)
return deletePaper(params);
}
// 编辑前查询试卷信息
static queryPaperDetail(params: any) {
return queryPaperDetail(params)
return queryPaperDetail(params);
}
// 预览试卷
static viewPaper(params: any) {
return viewPaper(params)
return viewPaper(params);
}
// 编辑试卷
static editPaper(params: any) {
return editPaper(params)
return editPaper(params);
}
// 操作试卷-预览查询多题目信息
static batchQueryQuestionDetails(params: any) {
return batchQueryQuestionDetails(params)
return batchQueryQuestionDetails(params);
}
// 操作试卷-选择题目列表带题目详情
static queryQuestionPageListWithContent(params: any) {
return queryQuestionPageListWithContent(params)
return queryQuestionPageListWithContent(params);
}
}
......@@ -2,17 +2,17 @@
* @Description:
* @Author: zangsuyun
* @Date: 2021-03-19 18:05:23
* @LastEditors: wufan
* @LastEditTime: 2021-05-30 16:48:46
* @LastEditors: fusanqiasng
* @LastEditTime: 2021-06-15 11:20:24
* @Copyright: © 2020 杭州杰竞科技有限公司 版权所有
*/
import React, { Component } from "react";
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";
import React, { Component } from 'react';
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;
......@@ -21,7 +21,7 @@ class Classification extends Component {
constructor(props) {
super(props);
this.state = {
selectedKeys: props.selectedKeys ? [props.selectedKeys] : ["0"],
selectedKeys: props.selectedKeys ? [props.selectedKeys] : ['0'],
searchValue: null,
NewEditQuestionBankCategory: null, //新增或编辑分类模态框
ImportCourseCategory: null, // 引用课程分类模态框
......@@ -32,11 +32,11 @@ class Classification extends Component {
componentDidMount() {
this.queryCategoryTree();
Bus.bind('knowledgeCategoryTree', this.queryCategoryTree)
Bus.bind('knowledgeCategoryTree', this.queryCategoryTree);
}
componentWillUnmount() {
Bus.unbind('knowledgeCategoryTree', this.queryCategoryTree)
Bus.unbind('knowledgeCategoryTree', this.queryCategoryTree);
}
shouldComponentUpdate = (nextProps, nextState) => {
......@@ -79,7 +79,7 @@ class Classification extends Component {
};
KnowledgeAPI.getCategoryTree(query).then((res) => {
const { categoryList = [], noCategoryCnt = 0 } = res.result;
let str = "未分类";
let str = '未分类';
if (categoryName) {
this.setState({ autoExpandParent: true });
if (str.indexOf(categoryName) < 0) {
......@@ -93,8 +93,8 @@ class Classification extends Component {
this.setState({ expandedKeys: nodeId });
} else {
const defaultNode = {
id: "0",
categoryName: "未分类",
id: '0',
categoryName: '未分类',
categoryCount: noCategoryCnt,
};
categoryList.unshift(defaultNode);
......@@ -110,8 +110,8 @@ class Classification extends Component {
} else {
this.setState({ autoExpandParent: false });
const defaultNode = {
id: "0",
categoryName: "未分类",
id: '0',
categoryName: '未分类',
categoryCount: noCategoryCnt,
};
categoryList.unshift(defaultNode);
......@@ -140,39 +140,35 @@ class Classification extends Component {
item.title =
!value || (value && item.categoryName.indexOf(value) > -1) ? (
<span>
{item.categoryName}{item.categoryCount}
{item.categoryName}
{item.categoryCount > 0 && <span>{item.categoryCount}</span>}
</span>
) : (
<span style={{ opacity: 0.5 }}>
{item.categoryName}{item.categoryCount}
{item.categoryName}
{item.categoryCount > 0 && <span>{item.categoryCount}</span>}
</span>
);
item.icon =
item.categoryName === "未分类" ? (
item.categoryName === '未分类' ? (
<img
style={{
width: "24px",
height: "24px",
opacity:
!value || (value && item.categoryName.indexOf(value) > -1)
? 1
: 0.5,
width: '24px',
height: '24px',
opacity: !value || (value && item.categoryName.indexOf(value) > -1) ? 1 : 0.5,
}}
src="https://image.xiaomaiketang.com/xm/defaultCategory.png"
alt=""
src='https://image.xiaomaiketang.com/xm/defaultCategory.png'
alt=''
/>
) : (
<img
style={{
width: "24px",
height: "24px",
opacity:
!value || (value && item.categoryName.indexOf(value) > -1)
? 1
: 0.5,
width: '24px',
height: '24px',
opacity: !value || (value && item.categoryName.indexOf(value) > -1) ? 1 : 0.5,
}}
src="https://image.xiaomaiketang.com/xm/hasCategory.png"
alt=""
src='https://image.xiaomaiketang.com/xm/hasCategory.png'
alt=''
/>
);
if (item.sonCategoryList) {
......@@ -186,36 +182,30 @@ class Classification extends Component {
};
render() {
const {
treeData,
expandedKeys,
selectedKeys,
autoExpandParent,
} = this.state;
const { treeData, expandedKeys, selectedKeys, autoExpandParent } = this.state;
return (
<div className="question-bank-sider">
<div className="sider-title">知识分类</div>
<div className='question-bank-sider'>
<div className='sider-title'>知识分类</div>
<Search
className="sider-search"
placeholder="搜索名称分类"
className='sider-search'
placeholder='搜索名称分类'
onSearch={(value) => {
this.queryCategoryTree(value);
}}
enterButton={<span className="icon iconfont">&#xe832;</span>}
style={{width: 230}}
enterButton={<span className='icon iconfont'>&#xe832;</span>}
style={{ width: 230 }}
/>
<div className="sider-btn">
<div className='sider-btn'>
<Button
onClick={() => {
window.RCHistory.push({
pathname: "/course-category-manage?from=knowledge",
pathname: '/course-category-manage?from=knowledge',
});
}}
>
}}>
分类管理
</Button>
</div>
<div className="sider-tree">
<div className='sider-tree'>
<DirectoryTree
expandedKeys={expandedKeys}
autoExpandParent={autoExpandParent}
......
......@@ -2,7 +2,7 @@
* @Author: zhangleyuan
* @Date: 2021-02-20 16:46:46
* @LastEditors: fusanqiasng
* @LastEditTime: 2021-06-01 11:45:34
* @LastEditTime: 2021-06-15 14:37:20
* @Description: 描述一下
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
......@@ -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, XMTable } 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';
......@@ -317,7 +317,7 @@ function PlanList(props) {
scroll={{ x: 1400 }}
className='plan-list-table'
renderEmpty={{
description: <span style={{ display: 'block', paddingBottom: 24 }}>还没有试卷</span>
description: <span style={{ display: 'block', paddingBottom: 24 }}>暂无数据</span>,
}}
/>
<div className='box-footer'>
......
/*
* @Author: yuananting
* @Date: 2021-02-23 18:28:50
* @LastEditors: yuananting
* @LastEditTime: 2021-06-02 14:25:06
* @LastEditors: fusanqiasng
* @LastEditTime: 2021-06-15 14:10:53
* @Description: 助学工具-课程分类
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import React, { Component } from 'react'
import Breadcrumbs from '@/components/Breadcrumbs'
import './CourseCategoryManage.less'
import OpearteCourseCategoryModal from '../modal/OpearteCourseCategoryModal'
import AidToolService from '@/domains/aid-tool-domain/AidToolService'
import User from '@/common/js/user'
import { Tree, Input, Space, Button, Menu, Dropdown, message, Modal } from 'antd'
import ShowTips from '@/components/ShowTips'
const { DirectoryTree } = Tree
const { Search } = Input
const { confirm } = Modal
import React, { Component } from 'react';
import Breadcrumbs from '@/components/Breadcrumbs';
import './CourseCategoryManage.less';
import OpearteCourseCategoryModal from '../modal/OpearteCourseCategoryModal';
import AidToolService from '@/domains/aid-tool-domain/AidToolService';
import User from '@/common/js/user';
import { Tree, Input, Space, Button, Menu, Dropdown, message, Modal } from 'antd';
import ShowTips from '@/components/ShowTips';
const { DirectoryTree } = Tree;
const { Search } = Input;
const { confirm } = Modal;
class CourseCategoryManage extends Component {
constructor(props) {
super(props)
super(props);
this.state = {
operateCourseCategoryModal: null, //新增或编辑分类模态框
treeData: [],
originTreeData: [],
treeMap: {},
selectedKeys: ['null'],
autoExpandParent: true
}
autoExpandParent: true,
};
}
componentDidMount() {
this.queryCategoryTree('init')
this.queryCategoryTree('init');
}
getWholeTree = () => {
......@@ -40,112 +40,112 @@ class CourseCategoryManage extends Component {
count: false,
source: 0,
userId: User.getStoreUserId(),
tenantId: User.getStoreId()
}
tenantId: User.getStoreId(),
};
AidToolService.queryCategoryTree(query).then((res) => {
const { categoryList = [] } = res.result
const { categoryList = [] } = res.result;
this.setState({ originTreeData: categoryList }, () => {
let map = {}
let topItem = []
let map = {};
let topItem = [];
categoryList.forEach((item) => {
topItem.push(item)
})
topItem.push(item);
});
this.setState({
treeMap: Object.assign(this.getTreeMap(categoryList, map), {
0: {
sonCategoryList: topItem
}
})
})
})
})
}
sonCategoryList: topItem,
},
}),
});
});
});
};
// 查询分类树
queryCategoryTree = (operateType, categoryName) => {
this.getWholeTree()
this.setState({ categoryName })
this.getWholeTree();
this.setState({ categoryName });
let query = {
bizType: 'QUESTION',
count: false,
source: 0,
categoryName,
userId: User.getStoreUserId(),
tenantId: User.getStoreId()
}
tenantId: User.getStoreId(),
};
AidToolService.queryCategoryTree(query).then((res) => {
const { categoryList = [] } = res.result
let str = '未分类'
const { categoryList = [] } = res.result;
let str = '未分类';
if (categoryName) {
this.setState({ autoExpandParent: true })
this.setState({ autoExpandParent: true });
if (str.indexOf(categoryName) < 0) {
this.setState({
treeData: this.renderTreeNodes(categoryList, categoryName)
})
let nodeId = []
treeData: this.renderTreeNodes(categoryList, categoryName),
});
let nodeId = [];
Object.keys(this.state.treeMap).forEach((item) => {
nodeId.push(item)
})
this.setState({ expandedKeys: nodeId })
nodeId.push(item);
});
this.setState({ expandedKeys: nodeId });
} else {
const defaultNode = {
id: 'null',
categoryName: '未分类',
categoryCount: 0,
parentId: '0',
categoryLevel: 0
}
categoryList.unshift(defaultNode)
categoryLevel: 0,
};
categoryList.unshift(defaultNode);
this.setState({
treeData: this.renderTreeNodes(categoryList, categoryName)
})
let nodeId = []
treeData: this.renderTreeNodes(categoryList, categoryName),
});
let nodeId = [];
Object.keys(this.state.treeMap).forEach((item) => {
nodeId.push(item)
})
nodeId.push(item);
});
if (operateType === 'init') {
this.setState({ expandedKeys: nodeId })
this.setState({ expandedKeys: nodeId });
}
}
} else {
this.setState({ autoExpandParent: false })
this.setState({ autoExpandParent: false });
const defaultNode = {
id: 'null',
categoryName: '未分类',
categoryCount: 0,
parentId: '0',
categoryLevel: 0
}
categoryList.unshift(defaultNode)
this.setState({ treeData: this.renderTreeNodes(categoryList, categoryName) })
categoryLevel: 0,
};
categoryList.unshift(defaultNode);
this.setState({ treeData: this.renderTreeNodes(categoryList, categoryName) });
if (operateType === 'init') {
this.setState({ expandedKeys: [] })
this.setState({ expandedKeys: [] });
}
}
})
}
});
};
// 树节点渲染-内容处理
renderTreeNodes = (data, value) => {
let newTreeData = data.map((item) => {
item.title = item.categoryName
item.key = item.id
item.title = item.categoryName;
item.key = item.id;
item.title = (
<div
style={{
opacity: !value || (value && item.categoryName.indexOf(value) > -1) ? 1 : 0.5
opacity: !value || (value && item.categoryName.indexOf(value) > -1) ? 1 : 0.5,
}}
className='node-title-div'
onMouseOver={(e) => {
let mouseNodeOpts = e.currentTarget.getElementsByTagName('div')[0]
let mouseNodeOpts = e.currentTarget.getElementsByTagName('div')[0];
if (mouseNodeOpts) {
mouseNodeOpts.style.visibility = 'visible'
mouseNodeOpts.style.visibility = 'visible';
}
}}
onMouseOut={(e) => {
let mouseNodeOpts = e.currentTarget.getElementsByTagName('div')[0]
let mouseNodeOpts = e.currentTarget.getElementsByTagName('div')[0];
if (mouseNodeOpts) {
mouseNodeOpts.style.visibility = 'hidden'
mouseNodeOpts.style.visibility = 'hidden';
}
}}>
<span>{item.categoryName}</span>
......@@ -158,9 +158,9 @@ class CourseCategoryManage extends Component {
(item.categoryLevel === 0 && originTreeData.length >= 29) ||
(item.categoryLevel > 0 && this.getRelatedNodes(item.parentId).length >= 30)
) {
return message.info('最多只能添加30个分类')
return message.info('最多只能添加30个分类');
}
this.newEditCourseCategory('newEqualLevelCategory', 'equal', 'new', item)
this.newEditCourseCategory('newEqualLevelCategory', 'equal', 'new', item);
}}>
<span className='icon iconfont' style={{ color: '#BFBFBF' }}>
&#xe7f5;{' '}
......@@ -171,10 +171,10 @@ class CourseCategoryManage extends Component {
<span
onClick={() => {
if (this.getRelatedNodes(item.id) && this.getRelatedNodes(item.id).length >= 30) {
message.info('最多只能添加30个子分类')
return
message.info('最多只能添加30个子分类');
return;
}
this.newEditCourseCategory('newChildLevelCategory', 'child', 'new', item)
this.newEditCourseCategory('newChildLevelCategory', 'child', 'new', item);
}}>
<span className='icon iconfont' style={{ color: '#BFBFBF' }}>
&#xe7f8;{' '}
......@@ -193,14 +193,14 @@ class CourseCategoryManage extends Component {
</Space>
)}
</div>
)
);
item.icon =
item.categoryName === '未分类' ? (
<img
style={{
width: '24px',
height: '24px',
opacity: !value || (value && item.categoryName.indexOf(value) > -1) ? 1 : 0.5
opacity: !value || (value && item.categoryName.indexOf(value) > -1) ? 1 : 0.5,
}}
src='https://image.xiaomaiketang.com/xm/defaultCategory.png'
alt=''
......@@ -210,54 +210,54 @@ class CourseCategoryManage extends Component {
style={{
width: '24px',
height: '24px',
opacity: !value || (value && item.categoryName.indexOf(value) > -1) ? 1 : 0.5
opacity: !value || (value && item.categoryName.indexOf(value) > -1) ? 1 : 0.5,
}}
src='https://image.xiaomaiketang.com/xm/hasCategory.png'
alt=''
/>
)
);
if (item.sonCategoryList) {
item.children = this.renderTreeNodes(item.sonCategoryList, value)
item.children = this.renderTreeNodes(item.sonCategoryList, value);
}
return item
})
return newTreeData
}
return item;
});
return newTreeData;
};
// 树结构平铺
getTreeMap = (data, map) => {
data.forEach((item) => {
map[item.id] = item
map[item.id] = item;
if (item.sonCategoryList && item.sonCategoryList.length > 0) {
this.getTreeMap(item.sonCategoryList, map)
this.getTreeMap(item.sonCategoryList, map);
}
})
});
return map
}
return map;
};
// 新增或编辑分类
newEditCourseCategory = (categoryType, addLevelType, type, node) => {
let title = ''
let label = ''
let title = '';
let label = '';
switch (categoryType) {
case 'newEqualLevelCategory':
title = '新增分类'
label = '分类名称'
break
title = '新增分类';
label = '分类名称';
break;
case 'newChildLevelCategory':
title = '新增子分类'
label = '子分类名称'
break
title = '新增子分类';
label = '子分类名称';
break;
case 'editEqualLevelCategory':
title = '编辑分类'
label = '分类名称'
break
title = '编辑分类';
label = '分类名称';
break;
case 'editChildLevelCategory':
title = '编辑子分类'
label = '子分类名称'
break
title = '编辑子分类';
label = '子分类名称';
break;
}
const m = (
<OpearteCourseCategoryModal
......@@ -267,15 +267,15 @@ class CourseCategoryManage extends Component {
title={title}
label={label}
close={() => {
this.queryCategoryTree('remain', this.state.categoryName)
this.queryCategoryTree('remain', this.state.categoryName);
this.setState({
operateCourseCategoryModal: null
})
operateCourseCategoryModal: null,
});
}}
/>
)
this.setState({ operateCourseCategoryModal: m })
}
);
this.setState({ operateCourseCategoryModal: m });
};
// 删除分类
delCategory = (item) => {
......@@ -291,17 +291,17 @@ class CourseCategoryManage extends Component {
categoryId: item.id,
source: 0,
tenantId: User.getStoreId(),
userId: User.getStoreUserId()
}
userId: User.getStoreUserId(),
};
AidToolService.delCategory(params).then((res) => {
if (res.success) {
message.success('删除分类成功')
this.queryCategoryTree('remain', this.state.categoryName)
message.success('删除分类成功');
this.queryCategoryTree('remain', this.state.categoryName);
}
})
}
})
}
});
},
});
};
// 更多操作-【重命名 删除】
initDropMenu = (item) => {
......@@ -310,8 +310,8 @@ class CourseCategoryManage extends Component {
<Menu.Item key='0'>
<span
onClick={() => {
let categoryType = item.categoryLevel === 0 ? 'editEqualLevelCategory' : 'editChildLevelCategory'
this.newEditCourseCategory(categoryType, 'equal', 'edit', item)
let categoryType = item.categoryLevel === 0 ? 'editEqualLevelCategory' : 'editChildLevelCategory';
this.newEditCourseCategory(categoryType, 'equal', 'edit', item);
}}>
重命名
</span>
......@@ -319,49 +319,47 @@ class CourseCategoryManage extends Component {
<Menu.Item key='1'>
<span
onClick={() => {
this.delCategory(item)
this.delCategory(item);
}}>
删除
</span>
</Menu.Item>
</Menu>
)
}
);
};
// 获取相关节点
getRelatedNodes = (parentId) => {
return this.state.treeMap[parentId] ? this.state.treeMap[parentId].sonCategoryList : []
}
return this.state.treeMap[parentId] ? this.state.treeMap[parentId].sonCategoryList : [];
};
// 获取拖拽目标父节点层级
getParentDragNodesLevel = (dragNode) => {
if (!dragNode) {
return []
return [];
}
let dragNodes = []
dragNodes.push(dragNode.id)
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
}
return dragNodes;
};
// 获取拖拽节点层级
getDragNodesLevel = (dragNode) => {
let dragNodes = []
let dragNodes = [];
if (dragNode.sonCategoryList && dragNode.sonCategoryList.length > 0) {
dragNode.sonCategoryList.forEach((item) => {
dragNodes.push(item.categoryLevel)
dragNodes.push(item.categoryLevel);
if (item.sonCategoryList && item.sonCategoryList.length > 0) {
dragNodes = dragNodes.concat(this.getDragNodesLevel(item))
dragNodes = dragNodes.concat(this.getDragNodesLevel(item));
}
})
});
}
return [...new Set(dragNodes)]
}
return [...new Set(dragNodes)];
};
// 拖拽
onDrop = (info) => {
......@@ -370,148 +368,165 @@ class CourseCategoryManage extends Component {
// 不允许其他节点拖拽到未分类之前
if (
this.state.categoryName ||
(info.node.categoryName === "未分类" && info.dropPosition === 0) ||
(info.node.categoryName === "未分类" &&
info.dropToGap &&
info.dropPosition === -1)
(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.dragNode.categoryName === '未分类' && info.dragNode.categoryLevel === 0) return message.info('“未分类”为默认分类暂不支持移动');
let targetParentId = info.dropToGap ? info.node.parentId : info.node.id
let relatedNodes = this.getRelatedNodes(targetParentId)
let targetParentId = info.dropToGap ? info.node.parentId : info.node.id;
let relatedNodes = this.getRelatedNodes(targetParentId);
if (!((info.dropToGap && info.node.parentId === info.dragNode.parentId) || (!info.dropToGap && info.node.id === info.dragNode.parentId))) {
if (this.state.treeMap[targetParentId].categoryLevel === 4) {
return message.info('最多支持5级分类')
console.log('this.state.treeMap[targetParentId].categoryLevel', this.state.treeMap[targetParentId].categoryLevel);
if (this.state.treeMap[targetParentId].categoryLevel >= 4) {
return message.info('最多支持5级分类');
} else {
let nodesArr = this.getDragNodesLevel(this.state.treeMap[info.dragNode.id])
let parentArr = this.getParentDragNodesLevel(this.state.treeMap[targetParentId])
let nodesArr = this.getDragNodesLevel(this.state.treeMap[info.dragNode.id]);
let parentArr = this.getParentDragNodesLevel(this.state.treeMap[targetParentId]);
console.log(nodesArr.length, parentArr.length);
if (nodesArr.length + parentArr.length > 4) {
return message.info("最多支持5级分类");
return message.info('最多支持5级分类');
}
}
if (relatedNodes && relatedNodes.length >= 30) {
return message.info('最多只能添加30个分类')
return message.info('最多只能添加30个分类');
}
}
const dropKey = info.node.key
const dragKey = info.dragNode.key
const dropPos = info.node.pos.split('-')
const dropPosition = info.dropPosition - Number(dropPos[dropPos.length - 1])
const dropKey = info.node.key;
const dragKey = info.dragNode.key;
const dropPos = info.node.pos.split('-');
const dropPosition = info.dropPosition - Number(dropPos[dropPos.length - 1]);
const loop = (data, key, callback) => {
for (let i = 0; i < data.length; i++) {
if (data[i].key === key) {
return callback(data[i], i, data)
return callback(data[i], i, data);
}
if (data[i].sonCategoryList) {
loop(data[i].sonCategoryList, key, callback)
loop(data[i].sonCategoryList, key, callback);
}
}
}
const data = [...this.state.treeData]
};
const data = [...this.state.treeData];
let getSuf = function (name, originCategoryName, sufIndex) {
if (relatedNodes && relatedNodes.length > 0) {
let sameNameNodes = []
let sameNameNodes = [];
relatedNodes.forEach((item) => {
if (item.id === info.dragNode.id) return true
if (item.id === info.dragNode.id) return true;
if (item.categoryName === name) {
sameNameNodes.push(item)
sameNameNodes.push(item);
}
})
});
if (sameNameNodes.length > 0) {
sufIndex++
return getSuf(originCategoryName + `(${sufIndex})`, originCategoryName, sufIndex)
sufIndex++;
return getSuf(originCategoryName + `(${sufIndex})`, originCategoryName, sufIndex);
}
}
return sufIndex
}
return sufIndex;
};
let dragObj
let dragObj;
loop(data, dragKey, (item, index, arr) => {
arr.splice(index, 1)
item.parentId = targetParentId
arr.splice(index, 1);
item.parentId = targetParentId;
if (item.originCategoryName) {
item.categoryName = item.originCategoryName
item.categoryName = item.originCategoryName;
} else {
item.originCategoryName = item.categoryName
item.originCategoryName = item.categoryName;
}
info.dragNode.categoryName = item.originCategoryName
let sufIndex = getSuf(info.dragNode.categoryName, item.originCategoryName, 0)
item.categoryName = item.categoryName + (sufIndex ? `(${sufIndex})` : '')
item.categoryName = item.originCategoryName + (sufIndex ? `(${sufIndex})` : '')
dragObj = item
})
info.dragNode.categoryName = item.originCategoryName;
let sufIndex = getSuf(info.dragNode.categoryName, item.originCategoryName, 0);
item.categoryName = item.categoryName + (sufIndex ? `(${sufIndex})` : '');
item.categoryName = item.originCategoryName + (sufIndex ? `(${sufIndex})` : '');
dragObj = item;
});
if (!info.dropToGap) {
loop(data, dropKey, (item) => {
item.sonCategoryList = item.sonCategoryList || []
item.sonCategoryList.unshift(dragObj)
})
item.sonCategoryList = item.sonCategoryList || [];
item.sonCategoryList.unshift(dragObj);
});
} else if ((info.node.props.sonCategoryList || []).length > 0 && info.node.props.expanded && dropPosition === 1) {
loop(data, dropKey, (item) => {
item.sonCategoryList = item.children || []
item.sonCategoryList.unshift(dragObj)
})
item.sonCategoryList = item.children || [];
item.sonCategoryList.unshift(dragObj);
});
} else {
let ar
let i
let ar;
let i;
loop(data, dropKey, (item, index, arr) => {
ar = arr
i = index
})
ar = arr;
i = index;
});
if (dropPosition === -1) {
ar.splice(i, 0, dragObj)
ar.splice(i, 0, dragObj);
} else {
ar.splice(i + 1, 0, dragObj)
ar.splice(i + 1, 0, dragObj);
}
console.log('ar:', ar);
}
data.shift()
let newTreeData = this.renderTreeNodes(this.handleLoop(data, 0))
this.setState({ treeData: newTreeData })
data.shift();
let newTreeData = this.renderTreeNodes(this.handleLoop(data, 0));
this.setState({ treeData: newTreeData });
let firstParentNode = {
categoryCount: 0,
categoryLevel: 0,
categoryName: '',
id: 0,
parentId: 0,
parentName: '',
rootId: 0,
sonCategoryList: [...newTreeData],
sort: 0,
source: 0,
tenantId: User.getStoreId(),
userId: User.getStoreUserId(),
};
let newTreeMap = this.getTreeMap(newTreeData, {});
let movedCategory = _.filter(newTreeMap, (item) => item.id === info.dragNode.id)[0];
let parentCategory = info.dropToGap ? firstParentNode : _.filter(newTreeMap, (item) => item.id === info.node.id)[0];
let params = {
categoryList: newTreeData,
movedCategory,
parentCategory,
source: 0,
tenantId: User.getStoreId(),
userId: User.getStoreUserId()
}
AidToolService.editCategoryTree(params).then((res) => {
this.queryCategoryTree('remain')
})
}
userId: User.getStoreUserId(),
};
AidToolService.moveCategoryTree(params).then((res) => {
this.queryCategoryTree('remain');
});
};
handleLoop = (data, level) => {
data.map((item, index) => {
item.sort = index
item.categoryLevel = level
item.sort = index;
item.categoryLevel = level;
if (item.sonCategoryList) {
item.children = this.handleLoop(item.sonCategoryList, level + 1)
item.sonCategoryList = this.handleLoop(item.sonCategoryList, level + 1)
item.children = this.handleLoop(item.sonCategoryList, level + 1);
item.sonCategoryList = this.handleLoop(item.sonCategoryList, level + 1);
}
return item
})
return data
}
return item;
});
return data;
};
// 树状展开事件
onExpand = (expandedKeys) => {
this.setState({ expandedKeys })
}
this.setState({ expandedKeys });
};
// 树状选中事件
onSelect = (selectedKeys) => {
this.setState({ selectedKeys })
}
this.setState({ selectedKeys });
};
render() {
const { treeData, originTreeData, expandedKeys, selectedKeys, autoExpandParent, operateCourseCategoryModal } = this.state
const { treeData, originTreeData, expandedKeys, selectedKeys, autoExpandParent, operateCourseCategoryModal } = this.state;
return (
<div className='page course-category-manage'>
{['aid', 'knowledge'].includes(getParameterByName('from')) ? (
......@@ -534,10 +549,10 @@ class CourseCategoryManage extends Component {
type='primary'
onClick={() => {
if (originTreeData.length >= 29) {
message.info('最多只能添加30个分类')
return
message.info('最多只能添加30个分类');
return;
}
this.newEditCourseCategory('newEqualLevelCategory', 'equal', 'new')
this.newEditCourseCategory('newEqualLevelCategory', 'equal', 'new');
}}>
新增一级分类
</Button>
......@@ -559,8 +574,8 @@ class CourseCategoryManage extends Component {
</div>
{operateCourseCategoryModal}
</div>
)
);
}
}
export default CourseCategoryManage
export default CourseCategoryManage;
/*
* @Author: yuananting
* @Date: 2021-02-22 10:59:43
* @LastEditors: yuananting
* @LastEditTime: 2021-04-13 13:55:37
* @LastEditors: fusanqiasng
* @LastEditTime: 2021-06-15 11:20:48
* @Description: 助学工具-侧边课程分类树
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import React, { Component } from "react";
import { Input, Button, Tree } from "antd";
import "./CourseCategorySiderTree.less";
import User from "@/common/js/user";
import AidToolService from "@/domains/aid-tool-domain/AidToolService";
import Bus from "@/core/bus";
import React, { Component } from 'react';
import { Input, Button, Tree } from 'antd';
import './CourseCategorySiderTree.less';
import User from '@/common/js/user';
import AidToolService from '@/domains/aid-tool-domain/AidToolService';
import Bus from '@/core/bus';
const { Search } = Input;
const { DirectoryTree } = Tree;
......@@ -20,31 +20,25 @@ class CourseCategorySiderTree extends Component {
constructor(props) {
super(props);
this.state = {
selectedKeys: ["QUESTION_INDEX", "PAPER_INDEX"].includes(props.fromModule)
? [getParameterByName("categoryId") || "null"]
: ["null"],
selectedKeys: ['QUESTION_INDEX', 'PAPER_INDEX'].includes(props.fromModule) ? [getParameterByName('categoryId') || 'null'] : ['null'],
treeData: props.treeData || [],
autoExpandParent: false,
};
}
componentDidMount() {
this.queryCategoryTree("init");
Bus.bind("queryCategoryTree", this.queryCategoryTree);
this.queryCategoryTree('init');
Bus.bind('queryCategoryTree', this.queryCategoryTree);
}
componentWillUnmount() {
Bus.unbind("queryCategoryTree", this.queryCategoryTree);
Bus.unbind('queryCategoryTree', this.queryCategoryTree);
}
// 查询分类树
queryCategoryTree = (type = "init", categoryName) => {
queryCategoryTree = (type = 'init', categoryName) => {
let query = {
bizType: ["QUESTION_INDEX", "QUESTION_MODAL"].includes(
this.props.fromModule
)
? "QUESTION"
: "PAPER",
bizType: ['QUESTION_INDEX', 'QUESTION_MODAL'].includes(this.props.fromModule) ? 'QUESTION' : 'PAPER',
categoryName,
count: true,
source: 0,
......@@ -53,7 +47,7 @@ class CourseCategorySiderTree extends Component {
};
AidToolService.queryCategoryTree(query).then((res) => {
const { categoryList = [], noCategoryCnt = 0 } = res.result;
let str = "未分类";
let str = '未分类';
if (categoryName) {
this.setState({ autoExpandParent: true });
if (str.indexOf(categoryName) < 0) {
......@@ -64,15 +58,15 @@ class CourseCategorySiderTree extends Component {
Object.keys(this.state.treeMap).forEach((item) => {
nodeId.push(item);
});
if (type === "init") {
if (type === 'init') {
this.setState({ expandedKeys: nodeId });
}
} else {
const defaultNode = {
id: "null",
categoryName: "未分类",
id: 'null',
categoryName: '未分类',
categoryCount: noCategoryCnt,
parentId: "0",
parentId: '0',
categoryLevel: 0,
};
categoryList.unshift(defaultNode);
......@@ -83,24 +77,24 @@ class CourseCategorySiderTree extends Component {
Object.keys(this.state.treeMap).forEach((item) => {
nodeId.push(item);
});
if (type === "init") {
if (type === 'init') {
this.setState({ expandedKeys: nodeId });
}
}
} else {
this.setState({ autoExpandParent: false });
const defaultNode = {
id: "null",
categoryName: "未分类",
id: 'null',
categoryName: '未分类',
categoryCount: noCategoryCnt,
parentId: "0",
parentId: '0',
categoryLevel: 0,
};
categoryList.unshift(defaultNode);
this.setState({
treeData: this.renderTreeNodes(categoryList, categoryName),
});
if (type === "init") {
if (type === 'init') {
this.setState({ expandedKeys: [] });
}
}
......@@ -126,12 +120,12 @@ class CourseCategorySiderTree extends Component {
// 树状选中事件
onSelect = (selectedKeys) => {
this.setState({ selectedKeys }, () => {
if (this.props.fromModule === "QUESTION_INDEX") {
Bus.trigger("queryQuestionPageList", selectedKeys[0]);
} else if (this.props.fromModule === "QUESTION_MODAL") {
Bus.trigger("queryQuestionPageListWithContent", selectedKeys[0]);
if (this.props.fromModule === 'QUESTION_INDEX') {
Bus.trigger('queryQuestionPageList', selectedKeys[0]);
} else if (this.props.fromModule === 'QUESTION_MODAL') {
Bus.trigger('queryQuestionPageListWithContent', selectedKeys[0]);
} else {
Bus.trigger("queryPaperPageList", selectedKeys[0], 0);
Bus.trigger('queryPaperPageList', selectedKeys[0], 0);
}
});
};
......@@ -144,39 +138,35 @@ class CourseCategorySiderTree extends Component {
item.title =
!value || (value && item.categoryName.indexOf(value) > -1) ? (
<span>
{item.categoryName}{item.categoryCount}
{item.categoryName}
{item.categoryCount > 0 && <span>{item.categoryCount}</span>}
</span>
) : (
<span style={{ opacity: 0.5 }}>
{item.categoryName}{item.categoryCount}
{item.categoryName}
{item.categoryCount > 0 && <span>{item.categoryCount}</span>}
</span>
);
item.icon =
item.categoryName === "未分类" ? (
item.categoryName === '未分类' ? (
<img
style={{
width: "24px",
height: "24px",
opacity:
!value || (value && item.categoryName.indexOf(value) > -1)
? 1
: 0.5,
width: '24px',
height: '24px',
opacity: !value || (value && item.categoryName.indexOf(value) > -1) ? 1 : 0.5,
}}
src="https://image.xiaomaiketang.com/xm/defaultCategory.png"
alt=""
src='https://image.xiaomaiketang.com/xm/defaultCategory.png'
alt=''
/>
) : (
<img
style={{
width: "24px",
height: "24px",
opacity:
!value || (value && item.categoryName.indexOf(value) > -1)
? 1
: 0.5,
width: '24px',
height: '24px',
opacity: !value || (value && item.categoryName.indexOf(value) > -1) ? 1 : 0.5,
}}
src="https://image.xiaomaiketang.com/xm/hasCategory.png"
alt=""
src='https://image.xiaomaiketang.com/xm/hasCategory.png'
alt=''
/>
);
if (item.sonCategoryList) {
......@@ -190,46 +180,34 @@ class CourseCategorySiderTree extends Component {
};
render() {
const {
treeData,
expandedKeys,
selectedKeys,
autoExpandParent,
} = this.state;
const { treeData, expandedKeys, selectedKeys, autoExpandParent } = this.state;
return (
<div className="category-tree-sider">
{["QUESTION_INDEX", "PAPER_INDEX"].includes(this.props.fromModule) && (
<div className="sider-title">
{this.props.fromModule === "QUESTION_INDEX"
? "题目分类"
: "试卷分类"}
</div>
<div className='category-tree-sider'>
{['QUESTION_INDEX', 'PAPER_INDEX'].includes(this.props.fromModule) && (
<div className='sider-title'>{this.props.fromModule === 'QUESTION_INDEX' ? '题目分类' : '试卷分类'}</div>
)}
<Search
className="sider-search"
placeholder="搜索名称分类"
className='sider-search'
placeholder='搜索名称分类'
onSearch={(value) => {
this.queryCategoryTree("init", value);
this.queryCategoryTree('init', value);
}}
enterButton={<span className="icon iconfont">&#xe832;</span>}
enterButton={<span className='icon iconfont'>&#xe832;</span>}
/>
{["QUESTION_INDEX", "PAPER_INDEX"].includes(this.props.fromModule) &&
User.getUserRole() !== "CloudLecturer" &&
this.props.type !== "modal-select" && (
<div className="sider-btn">
<Button
onClick={() => {
window.RCHistory.push({
pathname: "/course-category-manage?from=aid",
});
}}
>
分类管理
</Button>
</div>
)}
<div className="sider-tree">
{['QUESTION_INDEX', 'PAPER_INDEX'].includes(this.props.fromModule) && User.getUserRole() !== 'CloudLecturer' && this.props.type !== 'modal-select' && (
<div className='sider-btn'>
<Button
onClick={() => {
window.RCHistory.push({
pathname: '/course-category-manage?from=aid',
});
}}>
分类管理
</Button>
</div>
)}
<div className='sider-tree'>
<DirectoryTree
expandedKeys={expandedKeys}
autoExpandParent={autoExpandParent}
......
......@@ -6,12 +6,12 @@ import Service from '@/common/js/service';
import moment from 'moment';
import { PageControl, XMTable } from '@/components';
import AddExam from './AddExam';
import User from "@/common/js/user";
import { XMContext } from "@/store/context";
import ExamShareModal from './ExamShareModal'
import DataAnalysic from './DataAnalysic'
import PreviewModal from './PreviewModal'
import './index.less'
import User from '@/common/js/user';
import { XMContext } from '@/store/context';
import ExamShareModal from './ExamShareModal';
import DataAnalysic from './DataAnalysic';
import PreviewModal from './PreviewModal';
import './index.less';
const { RangePicker } = DatePicker;
const { Search } = Input;
const { Option } = Select;
......@@ -434,7 +434,7 @@ function ExaminationManager(props: any) {
pagination={false}
style={{ margin: '0px 0 16px' }}
renderEmpty={{
description: <span style={{ display: 'block', paddingBottom: 24 }}>暂无数据</span>
description: <span style={{ display: 'block', paddingBottom: 24 }}>暂无数据</span>,
}}></XMTable>
{total > 0 && (
<PageControl
......
......@@ -184,7 +184,7 @@ function DataAnalysic(props: any) {
onClick={() => {
checkAnswerDetail(record);
}}>
答题详情
答题详情
</div>
</When>
<Otherwise>-</Otherwise>
......
/*
* @Author: yuananting
* @Date: 2021-03-27 16:15:13
* @LastEditors: yuananting
* @LastEditTime: 2021-06-10 11:11:30
* @LastEditors: fusanqiasng
* @LastEditTime: 2021-06-15 14:36:37
* @Description: 助学工具-新建/复制/编辑试卷
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import React, { Component } from "react";
import {
Form,
Button,
Input,
Table,
InputNumber,
ConfigProvider,
Empty,
Tooltip,
message,
Modal,
Spin,
Space,
Radio,
} from "antd";
import { PlusOutlined } from "@ant-design/icons";
import { XMTable } from "@/components";
import ShowTips from "@/components/ShowTips";
import Breadcrumbs from "@/components/Breadcrumbs";
import "./OperatePaper.less";
import SelectQuestionModal from "./modal/SelectQuestionModal";
import PaperPreviewModal from "./modal/PreviewPaperModal";
import User from "@/common/js/user";
import AidToolService from "@/domains/aid-tool-domain/AidToolService";
import Bus from "@/core/bus";
import { Route, withRouter } from "react-router-dom";
import React, { Component } from 'react';
import { Form, Button, Input, Table, InputNumber, ConfigProvider, Empty, Tooltip, message, Modal, Spin, Space, Radio } from 'antd';
import { PlusOutlined } from '@ant-design/icons';
import { XMTable } from '@/components';
import ShowTips from '@/components/ShowTips';
import Breadcrumbs from '@/components/Breadcrumbs';
import './OperatePaper.less';
import SelectQuestionModal from './modal/SelectQuestionModal';
import PaperPreviewModal from './modal/PreviewPaperModal';
import User from '@/common/js/user';
import AidToolService from '@/domains/aid-tool-domain/AidToolService';
import Bus from '@/core/bus';
import _ from 'underscore';
import { Route, withRouter } from 'react-router-dom';
import * as paperEmpty from '../../lottie/paperEmpty/data.json';
import AddExam from "@/modules/teach-tool/examination-manager/AddExam";
import _ from "underscore";
import AddExam from '@/modules/teach-tool/examination-manager/AddExam';
const questionTypeEnum = {
SINGLE_CHOICE: "单选题",
MULTI_CHOICE: "多选题",
JUDGE: "判断题",
GAP_FILLING: "填空题",
INDEFINITE_CHOICE: "不定项选择题",
SINGLE_CHOICE: '单选题',
MULTI_CHOICE: '多选题',
JUDGE: '判断题',
GAP_FILLING: '填空题',
INDEFINITE_CHOICE: '不定项选择题',
};
class OperatePaper extends Component {
formRef = React.createRef();
......@@ -50,7 +36,7 @@ class OperatePaper extends Component {
super(props);
this.state = {
formData: {
categoryId: getParameterByName("categoryId"), // 分类ID
categoryId: getParameterByName('categoryId'), // 分类ID
singleChoiceCnt: 0, // 单选题数量
multiChoiceCnt: 0, // 多选题数量
judgeCnt: 0, // 判断题数量
......@@ -73,36 +59,30 @@ class OperatePaper extends Component {
},
selectQuestionModal: null,
paperPreviewModal: null,
quickSortModalVisible: false, // 快捷排序弹窗显隐
quickSortModalVisible: false, // 快捷排序弹窗显隐
selectQuestionList: [],
currentOperate: "",
currentNav: "",
currentOperate: '',
currentNav: '',
currentCategoryPapers: [],
loading: false,
check: false,
sorterMethod: "addOrder",
sorterBy: [
"SINGLE_CHOICE",
"MULTI_CHOICE",
"JUDGE",
"GAP_FILLING",
"INDEFINITE_CHOICE",
],
sorterMethod: 'addOrder',
sorterBy: ['SINGLE_CHOICE', 'MULTI_CHOICE', 'JUDGE', 'GAP_FILLING', 'INDEFINITE_CHOICE'],
sorterTypeList: [
{
typeKey: "SINGLE_CHOICE",
typeKey: 'SINGLE_CHOICE',
},
{
typeKey: "MULTI_CHOICE",
typeKey: 'MULTI_CHOICE',
},
{
typeKey: "JUDGE",
typeKey: 'JUDGE',
},
{
typeKey: "GAP_FILLING",
typeKey: 'GAP_FILLING',
},
{
typeKey: "INDEFINITE_CHOICE",
typeKey: 'INDEFINITE_CHOICE',
},
],
};
......@@ -110,30 +90,26 @@ class OperatePaper extends Component {
componentDidMount() {
this.queryCurrentCategoryPapers();
switch (getParameterByName("type")) {
case "new":
this.setState({ currentOperate: "new", currentNav: "新建试卷" });
switch (getParameterByName('type')) {
case 'new':
this.setState({ currentOperate: 'new', currentNav: '新建试卷' });
break;
case "edit":
this.setState({ currentOperate: "edit", currentNav: "编辑试卷" }, () =>
this.queryPaperDetail()
);
case 'edit':
this.setState({ currentOperate: 'edit', currentNav: '编辑试卷' }, () => this.queryPaperDetail());
break;
case "copy":
this.setState({ currentOperate: "copy", currentNav: "复制试卷" }, () =>
this.queryPaperDetail()
);
case 'copy':
this.setState({ currentOperate: 'copy', currentNav: '复制试卷' }, () => this.queryPaperDetail());
break;
}
}
// 获取当前分类下的所有试卷
queryCurrentCategoryPapers = () => {
const categoryId = getParameterByName("categoryId");
const categoryId = getParameterByName('categoryId');
let params = {
current: 1,
size: 9999,
categoryId: categoryId === "null" ? null : categoryId,
categoryId: categoryId === 'null' ? null : categoryId,
paperName: null, // 试卷名称
source: 0,
tenantId: User.getStoreId(),
......@@ -150,7 +126,7 @@ class OperatePaper extends Component {
this.setState({ loading: true });
const { currentOperate } = this.state;
let query = {
paperId: getParameterByName("paperId"),
paperId: getParameterByName('paperId'),
source: 0,
userId: User.getStoreUserId(),
tenantId: User.getStoreId(),
......@@ -163,9 +139,8 @@ class OperatePaper extends Component {
selectQuestionList: questionList,
formData: {
...result,
paperId: getParameterByName("paperId"),
paperName:
currentOperate === "copy" ? paperName + "(复制)" : paperName,
paperId: getParameterByName('paperId'),
paperName: currentOperate === 'copy' ? paperName + '(复制)' : paperName,
},
loading: false,
},
......@@ -188,26 +163,11 @@ class OperatePaper extends Component {
const _selectQuestionList = [...list];
// 各类型题目汇总
const singleQuestion = _.filter(
_selectQuestionList,
(item) => item.questionType === "SINGLE_CHOICE"
);
const multiQuestion = _.filter(
_selectQuestionList,
(item) => item.questionType === "MULTI_CHOICE"
);
const judgeQuestion = _.filter(
_selectQuestionList,
(item) => item.questionType === "JUDGE"
);
const gapQuestion = _.filter(
_selectQuestionList,
(item) => item.questionType === "GAP_FILLING"
);
const indefiniteQuestion = _.filter(
_selectQuestionList,
(item) => item.questionType === "INDEFINITE_CHOICE"
);
const singleQuestion = _.filter(_selectQuestionList, (item) => item.questionType === 'SINGLE_CHOICE');
const multiQuestion = _.filter(_selectQuestionList, (item) => item.questionType === 'MULTI_CHOICE');
const judgeQuestion = _.filter(_selectQuestionList, (item) => item.questionType === 'JUDGE');
const gapQuestion = _.filter(_selectQuestionList, (item) => item.questionType === 'GAP_FILLING');
const indefiniteQuestion = _.filter(_selectQuestionList, (item) => item.questionType === 'INDEFINITE_CHOICE');
// 各类型题目总分值
const singleChoiceScore = singleQuestion.reduce((prev, cur) => {
......@@ -277,9 +237,7 @@ class OperatePaper extends Component {
const selectQuestionList = [...this.state.selectQuestionList];
const item = selectQuestionList.splice(index + moveLength, 1);
selectQuestionList.splice(index, 0, item[0]);
this.setState({ selectQuestionList }, () =>
this.setFormData(this.state.selectQuestionList)
);
this.setState({ selectQuestionList }, () => this.setFormData(this.state.selectQuestionList));
};
// 移除已选题目
......@@ -287,9 +245,7 @@ class OperatePaper extends Component {
const { selectQuestionList } = this.state;
this.setState(
{
selectQuestionList: [...selectQuestionList].filter(
(item) => item.questionId !== delQuestionId
),
selectQuestionList: [...selectQuestionList].filter((item) => item.questionId !== delQuestionId),
},
() => this.setFormData(this.state.selectQuestionList)
);
......@@ -303,15 +259,12 @@ class OperatePaper extends Component {
if (result != null) {
return result;
}
if (["new", "copy"].includes(currentOperate)) {
if (['new', 'copy'].includes(currentOperate)) {
if (item.paperName === paperName) {
result = item;
}
} else if (currentOperate === "edit") {
if (
item.paperName === paperName &&
item.paperId !== getParameterByName("paperId")
) {
} else if (currentOperate === 'edit') {
if (item.paperName === paperName && item.paperId !== getParameterByName('paperId')) {
result = item;
}
}
......@@ -321,15 +274,15 @@ class OperatePaper extends Component {
validatePaperName = (paperName) => {
if (this.state.check && !paperName) {
return "请输入试卷名称";
return '请输入试卷名称';
}
if (this.checkExist(paperName)) {
return "该试卷名称已存在";
return '该试卷名称已存在';
}
if (paperName && paperName.length > 40) {
return "试卷名称最多40字";
return '试卷名称最多40字';
}
};
......@@ -337,19 +290,14 @@ class OperatePaper extends Component {
savePaper = (saveType) => {
this.setState({ check: true });
const { selectQuestionList, formData, currentOperate } = this.state;
const categoryId = getParameterByName("categoryId");
const categoryId = getParameterByName('categoryId');
const { match } = this.props;
let questionList = [];
if (
!formData.passRate ||
!formData.paperName ||
this.checkExist(formData.paperName) ||
(formData.paperName && formData.paperName.length > 40)
) {
if (!formData.passRate || !formData.paperName || this.checkExist(formData.paperName) || (formData.paperName && formData.paperName.length > 40)) {
return;
}
if (selectQuestionList.length === 0) {
return message.warning("请选择题目");
return message.warning('请选择题目');
}
selectQuestionList.forEach((item, index) => {
......@@ -370,29 +318,23 @@ class OperatePaper extends Component {
},
},
() => {
if (["new", "copy"].includes(currentOperate)) {
if (['new', 'copy'].includes(currentOperate)) {
AidToolService.createPaper(this.state.formData)
.then((res) => {
if (res.success) {
if (saveType === "saveToAddExam") {
this.setState({formData:{ ...formData, paperId: res.result}},() => {
if (saveType === 'saveToAddExam') {
this.setState({ formData: { ...formData, paperId: res.result } }, () => {
window.RCHistory.push({
pathname: `${match.url}/exam-operate-page`,
});
})
});
} else {
message.success(
currentOperate === "new" ? "新建成功" : "复制成功"
);
message.success(currentOperate === 'new' ? '新建成功' : '复制成功');
window.RCHistory.push({
pathname: `/paper-manage-index?categoryId=${categoryId}`,
});
Bus.trigger(
"queryPaperPageList",
categoryId,
selectQuestionList.length
);
Bus.trigger("queryCategoryTree", "remain");
Bus.trigger('queryPaperPageList', categoryId, selectQuestionList.length);
Bus.trigger('queryCategoryTree', 'remain');
}
}
})
......@@ -400,34 +342,26 @@ class OperatePaper extends Component {
window.RCHistory.push({
pathname: `/paper-manage-index?categoryId=${categoryId}`,
});
Bus.trigger(
"queryPaperPageList",
categoryId,
selectQuestionList.length
);
Bus.trigger("queryCategoryTree", "remain");
Bus.trigger('queryPaperPageList', categoryId, selectQuestionList.length);
Bus.trigger('queryCategoryTree', 'remain');
});
} else if (currentOperate === "edit") {
} else if (currentOperate === 'edit') {
AidToolService.editPaper({
...this.state.formData,
paperId: getParameterByName("paperId"),
paperId: getParameterByName('paperId'),
})
.then((res) => {
if (res.success) {
if (saveType === "saveToAddExam") {
if (saveType === 'saveToAddExam') {
window.RCHistory.push({
pathname: `${match.url}/exam-operate-page`,
});
} else {
message.success("编辑成功");
message.success('编辑成功');
window.RCHistory.push({
pathname: `/paper-manage-index?categoryId=${categoryId}`,
});
Bus.trigger(
"queryPaperPageList",
categoryId,
selectQuestionList.length
);
Bus.trigger('queryPaperPageList', categoryId, selectQuestionList.length);
}
}
})
......@@ -435,11 +369,7 @@ class OperatePaper extends Component {
window.RCHistory.push({
pathname: `/paper-manage-index?categoryId=${categoryId}`,
});
Bus.trigger(
"queryPaperPageList",
categoryId,
selectQuestionList.length
);
Bus.trigger('queryPaperPageList', categoryId, selectQuestionList.length);
});
}
}
......@@ -451,7 +381,7 @@ class OperatePaper extends Component {
const { selectQuestionList, formData } = this.state;
const m = (
<PaperPreviewModal
previewPage="paper-operate"
previewPage='paper-operate'
paperInfo={{ ...formData, questionList: selectQuestionList }}
close={() => {
this.setState({
......@@ -466,21 +396,17 @@ class OperatePaper extends Component {
// 取消/返回
handleGoBack = () => {
Modal.confirm({
title: "确定要返回吗?",
content: "返回后,本次编辑的内容将不被保存",
okText: "确认返回",
cancelText: "留在本页",
icon: (
<span className="icon iconfont default-confirm-icon">&#xe6f4;</span>
),
title: '确定要返回吗?',
content: '返回后,本次编辑的内容将不被保存',
okText: '确认返回',
cancelText: '留在本页',
icon: <span className='icon iconfont default-confirm-icon'>&#xe6f4;</span>,
onOk: () => {
window.RCHistory.push({
pathname: `/paper-manage-index?categoryId=${getParameterByName(
"categoryId"
)}`,
pathname: `/paper-manage-index?categoryId=${getParameterByName('categoryId')}`,
});
Bus.trigger("queryCategoryTree", "remain");
Bus.trigger("queryPaperPageList", getParameterByName("categoryId"), 0);
Bus.trigger('queryCategoryTree', 'remain');
Bus.trigger('queryPaperPageList', getParameterByName('categoryId'), 0);
},
});
};
......@@ -490,39 +416,39 @@ class OperatePaper extends Component {
const { selectQuestionList } = this.state;
const columns = [
{
title: "序号",
dataIndex: "index",
key: "index",
width: "10%",
title: '序号',
dataIndex: 'index',
key: 'index',
width: '10%',
render: (val, record, index) => {
return <span>{index + 1}</span>;
},
},
{
title: "题型",
dataIndex: "questionType",
key: "questionType",
width: "12%",
title: '题型',
dataIndex: 'questionType',
key: 'questionType',
width: '12%',
filters: [
{
text: "单选题",
value: "SINGLE_CHOICE",
text: '单选题',
value: 'SINGLE_CHOICE',
},
{
text: "多选题",
value: "MULTI_CHOICE",
text: '多选题',
value: 'MULTI_CHOICE',
},
{
text: "判断题",
value: "JUDGE",
text: '判断题',
value: 'JUDGE',
},
{
text: "填空题",
value: "GAP_FILLING",
text: '填空题',
value: 'GAP_FILLING',
},
{
text: "不定项选择题",
value: "INDEFINITE_CHOICE",
text: '不定项选择题',
value: 'INDEFINITE_CHOICE',
},
],
filterMultiple: true,
......@@ -530,26 +456,23 @@ class OperatePaper extends Component {
render: (val) => questionTypeEnum[val],
},
{
title: "题目",
dataIndex: "questionStem",
key: "questionStem",
title: '题目',
dataIndex: 'questionStem',
key: 'questionStem',
ellipsis: {
showTitle: false,
},
render: (val) => {
var handleVal = val;
handleVal = handleVal.replace(/<(?!img|input).*?>/g, "");
handleVal = handleVal.replace(/<\s?input[^>]*>/gi, "_、");
handleVal = handleVal.replace(/\&nbsp\;/gi, " ");
handleVal = handleVal.replace(/<(?!img|input).*?>/g, '');
handleVal = handleVal.replace(/<\s?input[^>]*>/gi, '_、');
handleVal = handleVal.replace(/\&nbsp\;/gi, ' ');
return (
<Tooltip
overlayClassName="aid-tool-list"
title={
<div style={{ maxWidth: 700, width: "auto" }}>{handleVal}</div>
}
placement="topLeft"
overlayStyle={{ maxWidth: 700 }}
>
overlayClassName='aid-tool-list'
title={<div style={{ maxWidth: 700, width: 'auto' }}>{handleVal}</div>}
placement='topLeft'
overlayStyle={{ maxWidth: 700 }}>
{handleVal}
</Tooltip>
);
......@@ -558,20 +481,17 @@ class OperatePaper extends Component {
{
title: (
<span>
分值{" "}
<Tooltip title="多选题和填空题的漏选/半对得分不能高于题目本身分值">
<span
className="icon iconfont"
style={{ color: "#BFBFBF", fontSize: 14, fontWeight: "400" }}
>
分值{' '}
<Tooltip title='多选题和填空题的漏选/半对得分不能高于题目本身分值'>
<span className='icon iconfont' style={{ color: '#BFBFBF', fontSize: 14, fontWeight: '400' }}>
&#xe7c4;
</span>
</Tooltip>
</span>
),
dataIndex: "score",
key: "score",
width: "12%",
dataIndex: 'score',
key: 'score',
width: '12%',
render: (val, record, index) => {
return (
<InputNumber
......@@ -582,11 +502,7 @@ class OperatePaper extends Component {
const _selectQuestionList = [...selectQuestionList];
this.setState(
{
selectQuestionList: _selectQuestionList.map((item) =>
item.questionId === record.questionId
? { ...item, score: value }
: item
),
selectQuestionList: _selectQuestionList.map((item) => (item.questionId === record.questionId ? { ...item, score: value } : item)),
},
() => this.setFormData(this.state.selectQuestionList)
);
......@@ -596,20 +512,14 @@ class OperatePaper extends Component {
},
},
{
dataIndex: "portionScore",
key: "portionScore",
width: "18%",
dataIndex: 'portionScore',
key: 'portionScore',
width: '18%',
render: (val, record, index) => {
return (
["MULTI_CHOICE", "GAP_FILLING", "INDEFINITE_CHOICE"].includes(
record.questionType
) && (
['MULTI_CHOICE', 'GAP_FILLING', 'INDEFINITE_CHOICE'].includes(record.questionType) && (
<div>
{record.questionType === "GAP_FILLING" ? (
<span>半对得</span>
) : (
<span>漏选得</span>
)}{" "}
{record.questionType === 'GAP_FILLING' ? <span>半对得</span> : <span>漏选得</span>}{' '}
<InputNumber
min={0}
max={record.score - 1}
......@@ -619,9 +529,7 @@ class OperatePaper extends Component {
this.setState(
{
selectQuestionList: _selectQuestionList.map((item) =>
item.questionId === record.questionId
? { ...item, portionScore: value }
: item
item.questionId === record.questionId ? { ...item, portionScore: value } : item
),
},
() => this.setFormData(this.state.selectQuestionList)
......@@ -634,43 +542,34 @@ class OperatePaper extends Component {
},
},
{
title: "操作",
dataIndex: "operate",
key: "operate",
width: "16%",
title: '操作',
dataIndex: 'operate',
key: 'operate',
width: '16%',
render: (val, record, index) => {
return (
<div className="record-operate">
<div className='record-operate'>
<div
className={
index > 0 ? "record-operate__item" : "record-operate__ban"
}
className={index > 0 ? 'record-operate__item' : 'record-operate__ban'}
onClick={() => {
this.handleMoveItem(index, -1);
}}
>
}}>
上移
</div>
<span className="record-operate__item split"> | </span>
<span className='record-operate__item split'> | </span>
<div
className={
index < selectQuestionList.length - 1
? "record-operate__item"
: "record-operate__ban"
}
className={index < selectQuestionList.length - 1 ? 'record-operate__item' : 'record-operate__ban'}
onClick={() => {
this.handleMoveItem(index, 1);
}}
>
}}>
下移
</div>
<span className="record-operate__item split"> | </span>
<span className='record-operate__item split'> | </span>
<div
className="record-operate__item"
className='record-operate__item'
onClick={() => {
this.handleDelItem(record.questionId);
}}
>
}}>
移除
</div>
</div>
......@@ -686,7 +585,7 @@ class OperatePaper extends Component {
const sorterTypeList = [...this.state.sorterTypeList];
const item = sorterTypeList.splice(index + moveLength, 1);
sorterTypeList.splice(index, 0, item[0]);
const sorterBy = _.pluck(sorterTypeList, "typeKey");
const sorterBy = _.pluck(sorterTypeList, 'typeKey');
this.setState({ sorterTypeList, sorterBy });
};
......@@ -694,13 +593,9 @@ class OperatePaper extends Component {
quickSorter = (list, sorterMethod, sorterBy) => {
this.setState({
selectQuestionList:
sorterMethod === "addOrder"
sorterMethod === 'addOrder'
? list.sort((a, b) => a.sorterIndex - b.sorterIndex)
: list.sort(
(a, b) =>
sorterBy.indexOf(a.questionTypeEnum || a.questionType) -
sorterBy.indexOf(b.questionTypeEnum || b.questionType)
),
: list.sort((a, b) => sorterBy.indexOf(a.questionTypeEnum || a.questionType) - sorterBy.indexOf(b.questionTypeEnum || b.questionType)),
});
};
......@@ -736,77 +631,70 @@ class OperatePaper extends Component {
totalScore,
} = formData;
const { match } = this.props;
const selectQuestionList = [...this.state.selectQuestionList];
const questionTypeEnum = {
SINGLE_CHOICE: "【单选题】",
MULTI_CHOICE: "【多选题】",
JUDGE: "【判断题】",
GAP_FILLING: "【填空题】",
INDEFINITE_CHOICE: "【不定项选择题】",
SINGLE_CHOICE: '【单选题】',
MULTI_CHOICE: '【多选题】',
JUDGE: '【判断题】',
GAP_FILLING: '【填空题】',
INDEFINITE_CHOICE: '【不定项选择题】',
};
const typeColumns = [
{
title: "题型",
dataIndex: "typeKey",
key: "typeKey",
render: (text, record, index) => <span style={{color: '#333333'}}>{questionTypeEnum[text]}</span>,
title: '题型',
dataIndex: 'typeKey',
key: 'typeKey',
render: (text, record, index) => <span style={{ color: '#333333' }}>{questionTypeEnum[text]}</span>,
},
{
title: "操作",
key: "action",
title: '操作',
key: 'action',
align: 'right',
render: (text, record, index) => (
<Space size="middle">
<Space size='middle'>
<span
style={{color: index > 0 ? '#2966FF' : '#CCCCCC', cursor: 'pointer'}}
style={{ color: index > 0 ? '#2966FF' : '#CCCCCC', cursor: 'pointer' }}
onClick={() => {
index > 0 && this.handleMoveTypeSorter(index, -1);
}}
>
}}>
上移
</span>
<span style={{color: '#BFBFBF'}}> | </span>
<span style={{ color: '#BFBFBF' }}> | </span>
<span
style={{color: index < 4 ? '#2966FF' : '#CCCCCC', cursor: 'pointer'}}
style={{ color: index < 4 ? '#2966FF' : '#CCCCCC', cursor: 'pointer' }}
onClick={() => {
index < 4 && this.handleMoveTypeSorter(index, 1);
}}
>
}}>
下移
</span>
</Space>
),
},
];
return (
<div>
<div className="page operate-paper-page">
<div className='page operate-paper-page'>
<Breadcrumbs navList={currentNav} goBack={() => this.handleGoBack()} />
<Spin spinning={loading}>
<div className="box">
<div className="show-tips">
<ShowTips message="请遵守国家相关规定,切勿上传低俗色情、暴力恐怖、谣言诈骗、侵权盗版等相关内容,小麦企学院保有依据国家规定及平台规则进行处理的权利" />
<div className='box'>
<div className='show-tips'>
<ShowTips message='请遵守国家相关规定,切勿上传低俗色情、暴力恐怖、谣言诈骗、侵权盗版等相关内容,小麦企学院保有依据国家规定及平台规则进行处理的权利' />
</div>
<Form ref={this.formRef} style={{ marginTop: 24 }}>
<Form.Item
name="paperName"
label="试卷名称:"
name='paperName'
label='试卷名称:'
required
validateStatus={
this.validatePaperName(paperName) ? "error" : ""
}
help={this.validatePaperName(paperName)}
>
validateStatus={this.validatePaperName(paperName) ? 'error' : ''}
help={this.validatePaperName(paperName)}>
<Input
value={paperName}
autoComplete="off"
autoComplete='off'
maxLength={40}
style={{ width: 300 }}
placeholder="请输入试卷名称(40字以内)"
placeholder='请输入试卷名称(40字以内)'
onChange={(e) => {
this.setState({
formData: {
......@@ -817,82 +705,65 @@ class OperatePaper extends Component {
}}
/>
</Form.Item>
<Form.Item
name="passRate"
label="及格线:"
required
validateStatus={check && !passRate ? "error" : ""}
help={check && !passRate && "请输入及格线"}
>
<div>
<InputNumber
min={1}
max={100}
value={passRate}
onChange={(value) => {
this.setState(
{
formData: {
...formData,
passRate: parseInt(value) || undefined,
},
<Form.Item
name='passRate'
label='及格线:'
required
validateStatus={check && !passRate ? 'error' : ''}
help={check && !passRate && '请输入及格线'}>
<div>
<InputNumber
min={1}
max={100}
value={passRate}
onChange={(value) => {
this.setState(
{
formData: {
...formData,
passRate: parseInt(value) || undefined,
},
() => this.setFormData(selectQuestionList)
);
}}
/>{" "}
%
<span className="score-info">
总分({Number(totalScore) || 0})*及格线(
{Number(passRate) || 0}
%)=及格分数(
{Number(passScore) || 0}
</span>
</div>
</Form.Item>
<Space size={8}>
<Button
className="choose-btn"
type="primary"
icon={<PlusOutlined />}
onClick={this.chooseQuestion}
>
自选题目
</Button>
<Button
className="choose-btn"
onClick={() => {
this.setState({
quickSortModalVisible: true,
});
},
() => this.setFormData(selectQuestionList)
);
}}
>
快捷排序
</Button>
</Space>
/>{' '}
%
<span className='score-info'>
总分({Number(totalScore) || 0})*及格线(
{Number(passRate) || 0}
%)=及格分数(
{Number(passScore) || 0}
</span>
</div>
</Form.Item>
<Space size={8}>
<Button className='choose-btn' type='primary' icon={<PlusOutlined />} onClick={this.chooseQuestion}>
自选题目
</Button>
<Button
className='choose-btn'
onClick={() => {
this.setState({
quickSortModalVisible: true,
});
}}>
快捷排序
</Button>
</Space>
{questionCnt > 0 && (
<div
className="paper-info-tip"
style={{ margin: "0 auto 12px" }}
>
<div className='paper-info-tip' style={{ margin: '0 auto 12px' }}>
总计<span>{totalScore}</span>分,共
<span>{questionCnt}</span>
题。{" "}
{singleChoiceCnt > 0 &&
`单选题${singleChoiceCnt}题,共${singleChoiceScore}分;`}
{multiChoiceCnt > 0 &&
`多选题${multiChoiceCnt}题,共${multiChoiceScore}分;`}
题。 {singleChoiceCnt > 0 && `单选题${singleChoiceCnt}题,共${singleChoiceScore}分;`}
{multiChoiceCnt > 0 && `多选题${multiChoiceCnt}题,共${multiChoiceScore}分;`}
{judgeCnt > 0 && `判断题${judgeCnt}题,共${judgeScore}分,`}
{gapFillingCnt > 0 &&
`填空题${gapFillingCnt}题,共${gapFillingScore}分,`}
{indefiniteChoiceCnt > 0 &&
`不定项选择题${indefiniteChoiceCnt}题,共${indefiniteChoiceScore}分`}
{gapFillingCnt > 0 && `填空题${gapFillingCnt}题,共${gapFillingScore}分,`}
{indefiniteChoiceCnt > 0 && `不定项选择题${indefiniteChoiceCnt}题,共${indefiniteChoiceScore}分`}
</div>
)}
<XMTable
className="table-style"
className='table-style'
scroll={{ y: 350 }}
columns={this.parseColumns()}
dataSource={selectQuestionList}
......@@ -900,18 +771,16 @@ class OperatePaper extends Component {
onChange={this.sortByQuestionType}
renderEmpty={{
image: paperEmpty,
description: <span style={{ display: 'block', paddingBottom: 24 }}>请在左上角添加题目</span>
description: <span style={{ display: 'block', paddingBottom: 24 }}>请在左上角添加题目</span>,
}}
/>
</Form>
</div>
<div className="footer">
<div className='footer'>
<Button onClick={this.handleGoBack}>取消</Button>
<Button onClick={this.previewPaper}>预览</Button>
<Button onClick={() => this.savePaper("saveToAddExam")}>
保存并组织考试
</Button>
<Button type="primary" onClick={() => this.savePaper()}>
<Button onClick={() => this.savePaper('saveToAddExam')}>保存并组织考试</Button>
<Button type='primary' onClick={() => this.savePaper()}>
保存
</Button>
</div>
......@@ -920,8 +789,8 @@ class OperatePaper extends Component {
{paperPreviewModal}
<Modal
maskClosable={false}
className="type-order-modal"
title="快捷排序"
className='type-order-modal'
title='快捷排序'
width={560}
visible={quickSortModalVisible}
onOk={() => {
......@@ -934,27 +803,26 @@ class OperatePaper extends Component {
}}
onCancel={() => {
this.setState({ quickSortModalVisible: false });
}}
>
}}>
<Radio.Group
onChange={(e) =>
this.setState({
sorterMethod: e.target.value,
})
}
value={sorterMethod}
>
<Radio value={"addOrder"}>按添加顺序排序</Radio>
<Radio value={"typeOrder"}>按题型排序</Radio>
value={sorterMethod}>
<Radio value={'addOrder'}>按添加顺序排序</Radio>
<Radio value={'typeOrder'}>按题型排序</Radio>
</Radio.Group>
{sorterMethod === "typeOrder" && (
{sorterMethod === 'typeOrder' && (
<Table
className="type-order-table"
style={{marginTop: '24px'}}
className='type-order-table'
style={{ marginTop: '24px' }}
showHeader={false}
columns={typeColumns}
dataSource={sorterTypeList}
pagination={false}
bordered={false}
/>
)}
</Modal>
......@@ -962,19 +830,10 @@ class OperatePaper extends Component {
<Route
path={`${match.url}/exam-operate-page`}
render={() => {
return (
<AddExam
paperInfo={formData}
type={
currentOperate === "edit"
? "editPaperToAddExam"
: "newPaperToAddExam"
}
/>
);
return <AddExam paperInfo={formData} type={currentOperate === 'edit' ? 'editPaperToAddExam' : 'newPaperToAddExam'} />;
}}
/>
</div>
</div>
);
}
}
......
/*
* @Author: yuananting
* @Date: 2021-03-27 11:15:03
* @LastEditors: yuananting
* @LastEditTime: 2021-06-01 17:28:21
* @LastEditors: fusanqiasng
* @LastEditTime: 2021-06-15 14:33:49
* @Description: 助学工具-试卷-预览试卷
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import React, { Component } from "react";
import { Modal, ConfigProvider, Empty } from "antd";
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";
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 User from '@/common/js/user';
import AidToolService from '@/domains/aid-tool-domain/AidToolService';
import './PreviewPaperModal.less';
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: "多选题",
JUDGE: "判断题",
GAP_FILLING: "填空题",
INDEFINITE_CHOICE: "不定项选择题",
SINGLE_CHOICE: '单选题',
MULTI_CHOICE: '多选题',
JUDGE: '判断题',
GAP_FILLING: '填空题',
INDEFINITE_CHOICE: '不定项选择题',
};
class PreviewPaperModal extends Component {
......@@ -36,9 +36,9 @@ class PreviewPaperModal extends Component {
componentDidMount() {
const { previewPage, paperInfo } = this.props;
if (previewPage === "paper-list") {
if (previewPage === 'paper-list') {
this.queryPaperDetail();
} else if (previewPage === "paper-operate") {
} else if (previewPage === 'paper-operate') {
this.setState({ paperInfo });
}
}
......@@ -69,16 +69,16 @@ class PreviewPaperModal extends Component {
renderStem = (questionStemList, questionType, score, questionIndex) => {
const textContent = _.filter(questionStemList, (item) => {
return item.type == "RICH_TEXT";
return item.type == 'RICH_TEXT';
});
const mediaContent = _.filter(questionStemList, (item) => {
return item.type !== "RICH_TEXT";
return item.type !== 'RICH_TEXT';
});
let content = "";
let content = '';
if (textContent.length > 0) {
content = textContent[0].content;
if (questionType === "GAP_FILLING") {
if (questionType === 'GAP_FILLING') {
content = content.replace(
/_/g,
`<input
......@@ -96,7 +96,7 @@ class PreviewPaperModal extends Component {
let textDom = (
<div
key={0}
className="input-box"
className='input-box'
dangerouslySetInnerHTML={{
__html: content,
}}
......@@ -104,11 +104,11 @@ class PreviewPaperModal extends Component {
);
return (
<div className="stem-line-item">
<div className="text">
<div className="question-tip">
<span className="question-sort">{questionIndex + 1}</span>
<span className="question-type-score">
<div className='stem-line-item'>
<div className='text'>
<div className='question-tip'>
<span className='question-sort'>{questionIndex + 1}</span>
<span className='question-type-score'>
({questionTypeList[questionType]} | {score}分)
</span>
</div>
......@@ -122,27 +122,27 @@ class PreviewPaperModal extends Component {
renderOption = (optionItem, questionType) => {
const { questionOptionContentList, optionSort } = optionItem;
const textContent = _.filter(questionOptionContentList, (item) => {
return item.type == "RICH_TEXT";
return item.type == 'RICH_TEXT';
});
const mediaContent = _.filter(questionOptionContentList, (item) => {
return item.type !== "RICH_TEXT";
return item.type !== 'RICH_TEXT';
});
let content = textContent.length > 0 && textContent[0].content;
if (questionType !== "GAP_FILLING") {
if (questionType !== 'GAP_FILLING') {
let textDom = (
<span
key={0}
className="input-box"
className='input-box'
dangerouslySetInnerHTML={{
__html: content,
}}
/>
);
return (
<div className="option-line-item">
<div className="text">
<div className='option-line-item'>
<div className='text'>
{NUM_TO_WORD_MAP[optionSort]}: {textDom}
</div>
{mediaContent.length > 0 && this.renderMediaContent(mediaContent)}
......@@ -152,23 +152,21 @@ class PreviewPaperModal extends Component {
};
renderAnswer = (optionList, gapFillingAnswerList, questionType) => {
if (questionType === "GAP_FILLING") {
if (questionType === 'GAP_FILLING') {
{
return (
<div className="answer-line-item">
<div className='answer-line-item'>
<div style={{ marginBottom: 8 }}>正确答案: </div>
{_.map(gapFillingAnswerList, (gapItem, gapIndex) => {
const { correctAnswerList } = gapItem;
return (
<div className="gap-list">
<div className='gap-list'>
<span>[填空{gapIndex + 1}] </span>
{_.map(correctAnswerList, (answerItem, answerIndex) => {
return (
<span>
{answerItem}
{answerIndex < correctAnswerList.length - 1 && (
<span></span>
)}
{answerIndex < correctAnswerList.length - 1 && <span></span>}
</span>
);
})}
......@@ -180,19 +178,14 @@ class PreviewPaperModal extends Component {
);
}
} else {
const correctAnswerOption = _.filter(
optionList,
(item) => item.isCorrectAnswer === 1
);
const correctAnswerOption = _.filter(optionList, (item) => item.isCorrectAnswer === 1);
const correctOptionSort = correctAnswerOption.map((item) => {
return NUM_TO_WORD_MAP[item.optionSort];
});
return (
<div className="answer-line-item">
<div className='answer-line-item'>
<div style={{ marginBottom: 8 }}>正确答案: </div>
<span style={{ lineHeight: "20px", color: "#666666" }}>
{correctOptionSort.length > 0 && correctOptionSort.join("、")}
</span>
<span style={{ lineHeight: '20px', color: '#666666' }}>{correctOptionSort.length > 0 && correctOptionSort.join('、')}</span>
</div>
);
}
......@@ -200,24 +193,21 @@ class PreviewPaperModal extends Component {
renderMediaContent = (mediaContent) => {
return (
<div className="media">
<div className='media'>
{_.map(mediaContent, (mediaItem, mediaIndex) => {
let dom = "";
let dom = '';
let { type, content, size } = mediaItem;
switch (type) {
case "PICTURE":
case 'PICTURE':
dom = (
<div key={mediaIndex + 1} className="picture-box">
<img
src={content}
onClick={() => this.handleScanFile("JPG", content)}
/>
<div key={mediaIndex + 1} className='picture-box'>
<img src={content} onClick={() => this.handleScanFile('JPG', content)} />
</div>
);
break;
case "VOICE":
case 'VOICE':
dom = (
<div key={mediaIndex + 1} className="voice-box">
<div key={mediaIndex + 1} className='voice-box'>
<XMAudio
forbidParse
url={content}
......@@ -231,9 +221,9 @@ class PreviewPaperModal extends Component {
</div>
);
break;
case "AUDIO":
case 'AUDIO':
dom = (
<div key={mediaIndex} className="voice-box">
<div key={mediaIndex} className='voice-box'>
<XMAudio
forbidParse
url={content}
......@@ -261,73 +251,38 @@ class PreviewPaperModal extends Component {
autoplay: true,
animationData: previewEmpty,
rendererSettings: {
preserveAspectRatio: 'xMidYMid slice'
}
}
preserveAspectRatio: 'xMidYMid slice',
},
};
return (
<Empty
image={
<div style={{ marginTop: 24 }}>
<Lottie
options={defaultOptions}
height={150}
width={150}
isStopped={false}
isPaused={false}
/>
<Lottie options={defaultOptions} height={150} width={150} isStopped={false} isPaused={false} />
</div>
}
description={<span style={{ display: 'block', paddingBottom: 24 }}>暂无内容</span>}
></Empty>
description={<span style={{ display: 'block', paddingBottom: 24, marginTop: 50 }}>暂无内容</span>}></Empty>
);
};
render() {
const {
paperInfo,
showScanFile,
scanFileType,
scanFileAddress,
} = this.state;
const { paperInfo, showScanFile, scanFileType, scanFileAddress } = this.state;
const { paperName, questionList } = paperInfo;
return (
<div>
<Modal
className="paper-preview-modal"
visible={true}
title="试卷预览"
width={560}
centered={true}
footer={null}
onCancel={this.props.close}
>
{paperName && <div className="paper-title">{paperName.length > 40 ? paperName.substring(0, 40) : paperName}</div>}
<Modal className='paper-preview-modal' visible={true} title='试卷预览' width={560} centered={true} footer={null} onCancel={this.props.close}>
{paperName && <div className='paper-title'>{paperName.length > 40 ? paperName.substring(0, 40) : paperName}</div>}
{questionList && questionList.length > 0 ? (
<div className="question-list-box">
<div className='question-list-box'>
{_.map(questionList, (questionItem, questionIndex) => {
const {
questionStemList,
optionList,
gapFillingAnswerList,
questionType,
score,
} = questionItem;
const { questionStemList, optionList, gapFillingAnswerList, questionType, score } = questionItem;
return (
<div className="question-info-item">
{this.renderStem(
questionStemList,
questionType,
score,
questionIndex
)}
<div className='question-info-item'>
{this.renderStem(questionStemList, questionType, score, questionIndex)}
{_.map(optionList, (optionItem, optionIndex) => {
return this.renderOption(optionItem, questionType);
})}
{this.renderAnswer(
optionList,
gapFillingAnswerList,
questionType
)}
{this.renderAnswer(optionList, gapFillingAnswerList, questionType)}
</div>
);
})}
......
/*
* @Author: yuananting
* @Date: 2021-02-25 11:23:47
* @LastEditors: yuananting
* @LastEditTime: 2021-06-03 17:12:01
* @LastEditors: fusanqiasng
* @LastEditTime: 2021-06-15 14:33:35
* @Description: 助学工具-题库-题目列表数据
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import React, { Component } from "react";
import {
Table,
ConfigProvider,
Empty,
Row,
Input,
Select,
Tooltip,
Space,
Button,
Modal,
message,
Menu,
Dropdown,
DatePicker,
} from "antd";
import _ from "underscore";
import { Route, withRouter } from "react-router-dom";
import React, { Component } from 'react';
import { Table, ConfigProvider, Empty, Row, Input, Select, Tooltip, Space, Button, Modal, message, Menu, Dropdown, DatePicker } from 'antd';
import _ from 'underscore';
import { Route, withRouter } from 'react-router-dom';
import { DownOutlined } from '@ant-design/icons';
import { PageControl, XMTable } from '@/components';
import User from '@/common/js/user';
......@@ -36,7 +21,7 @@ import Bus from '@/core/bus';
import moment from 'moment';
import Service from '@/common/js/service';
import MoveModal from '../../modal/MoveModal';
import "./QuestionList.less";
import './QuestionList.less';
const { RangePicker } = DatePicker;
const { Search } = Input;
......@@ -686,9 +671,10 @@ class QuestionList extends Component {
onChange={this.handleChangeTable}
rowSelection={rowSelection}
renderEmpty={{
description: <span style={{ display: 'block', paddingBottom: 24 }}><span>还没有题目</span>
{["CloudManager", "StoreManager"].includes(User.getUserRole()) &&
categoryId && (
description: (
<span style={{ display: 'block', paddingBottom: 24 }}>
<span>还没有题目</span>
{['CloudManager', 'StoreManager'].includes(User.getUserRole()) && categoryId && (
<span>
,快去
<span
......
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