Commit 67db1181 by zhujian

'merge'

parents 7974214f 9e16f517
...@@ -663,9 +663,9 @@ module.exports = function (webpackEnv) { ...@@ -663,9 +663,9 @@ module.exports = function (webpackEnv) {
// The formatter is invoked directly in WebpackDevServerUtils during development // The formatter is invoked directly in WebpackDevServerUtils during development
formatter: isEnvProduction ? typescriptFormatter : undefined, formatter: isEnvProduction ? typescriptFormatter : undefined,
}), }),
new vConsolePlugin({ // new vConsolePlugin({
enable: (process.env.DEPLOY_ENV === 'prod' || process.env.DEPLOY_ENV === 'beta') ? false : true // enable: (process.env.DEPLOY_ENV === 'prod' || process.env.DEPLOY_ENV === 'beta') ? false : true
}) // })
].filter(Boolean), ].filter(Boolean),
// Some libraries import Node modules but don't use them in the browser. // Some libraries import Node modules but don't use them in the browser.
// Tell webpack to provide empty mocks for them so importing them works. // Tell webpack to provide empty mocks for them so importing them works.
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -66,4 +66,6 @@ declare module '*.module.css' { ...@@ -66,4 +66,6 @@ declare module '*.module.css' {
declare module '*.module.less' { declare module '*.module.less' {
const classes: { readonly [key: string]: string }; const classes: { readonly [key: string]: string };
export default classes; export default classes;
} }
\ No newline at end of file
declare module '@/components/GraphicsEditor'
\ No newline at end of file
...@@ -7,15 +7,34 @@ ...@@ -7,15 +7,34 @@
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/ */
class Permission { class Permission {
constructor(permissionCodes) { constructor(permissionCodes) {
this.permissionCodes = permissionCodes; this.permissionCodes = permissionCodes;
}
// 添加、编辑、删除排课
ContentClass_Schedule() {
return this.permissionCodes.includes('ShopStaff');
}
} }
export default Permission;
// 添加、编辑、删除排课
\ No newline at end of file ContentClass_Schedule() {
return this.permissionCodes.includes('ShopStaff');
}
CreateNewExam() {
return this.permissionCodes.includes('AddExam');
}
// AddExam() { //创建考试
// return this.permissionCodes.includes('AddExam');
// }
SeeExamData() { // 查看考试数据
return this.permissionCodes.includes('SeeExamData');
}
DelExam() { // 删除考试
return this.permissionCodes.includes('SeeExamData');
}
}
Permission.prototype.AddExam = function () { //创建考试
return this.permissionCodes.includes('AddExam');
}
export default Permission;
...@@ -11,6 +11,7 @@ import CheckBox from './CheckBox.tsx'; ...@@ -11,6 +11,7 @@ import CheckBox from './CheckBox.tsx';
import CropperModal from './CropperModal.tsx'; import CropperModal from './CropperModal.tsx';
import ImgCutModalNew from './ImgCutModalNew'; import ImgCutModalNew from './ImgCutModalNew';
export { export {
SearchBar, SearchBar,
PageControl, PageControl,
......
.xm-search-filter {
position: relative;
.ant-input-search-button{
border-left:none;
}
.search-condition {
width: calc(100% - 80px);
display: flex;
align-items: center;
flex-wrap: wrap;
&__item {
width: 30%;
margin-right: 3%;
margin-bottom: 12px;
display: flex;
.search-name{
vertical-align: middle;
display:inline-block;
height:32px;
line-height:32px;
margin-right: 4px;
}
.search-input{
flex:1;
}
}
}
.reset-fold-area {
position: absolute;
right: 12px;
}
.resetBtn {
color: #999999;
font-size: 18px;
margin-right: 8px;
}
.fold-btn {
font-size: 14px;
color: #666666;
line-height: 20px;
.fold-icon {
font-size: 12px;
margin-left:4px;
}
}
}
\ No newline at end of file
...@@ -10,7 +10,7 @@ import React from 'react' ...@@ -10,7 +10,7 @@ import React from 'react'
// 时间控件优化方法 // 时间控件优化方法
window.setCorrectDate = date => { window.setCorrectDate = date => {
let _date = date; let _date = date;
if ((date - (+new Date()) < 30 * 60 * 1000)) { if ((date - (+new Date()) < 30 * 60 * 1000)) {
const currentMinute = new Date().getMinutes(); const currentMinute = new Date().getMinutes();
...@@ -33,7 +33,7 @@ if (!Number.prototype.toFixedCorrect) { ...@@ -33,7 +33,7 @@ if (!Number.prototype.toFixedCorrect) {
window.processMonthCourseDate = courseList => { window.processMonthCourseDate = courseList => {
if (Array.isArray(courseList) && courseList.length > 0) { if (Array.isArray(courseList) && courseList.length > 0) {
// 因为所购买的时间不可能有重叠,先排序 // 因为所购买的时间不可能有重叠,先排序
courseList = courseList.sort(function(now, next) { courseList = courseList.sort(function (now, next) {
return parseInt(now.startDate) - parseInt(next.startDate) return parseInt(now.startDate) - parseInt(next.startDate)
}) })
...@@ -41,7 +41,7 @@ window.processMonthCourseDate = courseList => { ...@@ -41,7 +41,7 @@ window.processMonthCourseDate = courseList => {
let sumDays = 0, let sumDays = 0,
finishDays = 0, finishDays = 0,
givingDays = 0 givingDays = 0
courseList.forEach(function(item) { courseList.forEach(function (item) {
if (item.endDate != item.purchaseEndDate) { if (item.endDate != item.purchaseEndDate) {
givingDays += moment(parseInt(item.endDate)).diff( givingDays += moment(parseInt(item.endDate)).diff(
parseInt(item.purchaseEndDate), parseInt(item.purchaseEndDate),
...@@ -73,8 +73,8 @@ window.processMonthCourseDate = courseList => { ...@@ -73,8 +73,8 @@ window.processMonthCourseDate = courseList => {
.valueOf()) .valueOf())
const endDate = (course.endDate = course.endDate const endDate = (course.endDate = course.endDate
? moment(parseInt(course.endDate)) ? moment(parseInt(course.endDate))
.endOf('day') .endOf('day')
.valueOf() .valueOf()
: undefined) : undefined)
if (i == 0 && Date.now() < startDate) { if (i == 0 && Date.now() < startDate) {
...@@ -327,7 +327,7 @@ window.getRequest = () => { ...@@ -327,7 +327,7 @@ window.getRequest = () => {
return theRequest return theRequest
} }
window.getParameterByName = function(name) { window.getParameterByName = function (name) {
name = name.replace(/[\\[]/, '\\[').replace(/[\]]/, '\\]') name = name.replace(/[\\[]/, '\\[').replace(/[\]]/, '\\]')
const regex = new RegExp('[\\?&]' + name + '=([^&#]*)') const regex = new RegExp('[\\?&]' + name + '=([^&#]*)')
const results = regex.exec(window.location.href) const results = regex.exec(window.location.href)
...@@ -344,7 +344,7 @@ window.getUrlParam = function () { ...@@ -344,7 +344,7 @@ window.getUrlParam = function () {
return isNaN(param) ? '' : str; return isNaN(param) ? '' : str;
} }
window.getStringParamete = function(string, name) { window.getStringParamete = function (string, name) {
const theRequest = {} const theRequest = {}
if (string.indexOf('?') != -1) { if (string.indexOf('?') != -1) {
const str = string.substr(1) const str = string.substr(1)
...@@ -379,8 +379,8 @@ window.timeFormat = (time, defaultValue) => { ...@@ -379,8 +379,8 @@ window.timeFormat = (time, defaultValue) => {
const stringTime = time const stringTime = time
? (time / CONFIG.timeUnit).toFixed(2) ? (time / CONFIG.timeUnit).toFixed(2)
: defaultValue == undefined : defaultValue == undefined
? 0 ? 0
: defaultValue : defaultValue
return Number(stringTime) return Number(stringTime)
} }
...@@ -410,8 +410,8 @@ window.timeFormatSixty = (time, defaultValue) => { ...@@ -410,8 +410,8 @@ window.timeFormatSixty = (time, defaultValue) => {
const stringTime = time const stringTime = time
? (time / 60).toFixed(2) ? (time / 60).toFixed(2)
: defaultValue == undefined : defaultValue == undefined
? 0 ? 0
: defaultValue : defaultValue
return Number(stringTime) return Number(stringTime)
} }
...@@ -465,8 +465,8 @@ window.moneyFormat = (money, defaultValue) => { ...@@ -465,8 +465,8 @@ window.moneyFormat = (money, defaultValue) => {
const stringMoney = money const stringMoney = money
? (Math.round(money) / CONFIG.moneyUnit).toFixed(2) ? (Math.round(money) / CONFIG.moneyUnit).toFixed(2)
: defaultValue == undefined : defaultValue == undefined
? 0 ? 0
: defaultValue : defaultValue
return Number(stringMoney) return Number(stringMoney)
} }
...@@ -487,9 +487,9 @@ window.moneyFormatThousands = (number, places, symbol, thousand, decimal) => { ...@@ -487,9 +487,9 @@ window.moneyFormatThousands = (number, places, symbol, thousand, decimal) => {
i.substr(j).replace(/(\d{3})(?=\d)/g, '$1' + thousand) + i.substr(j).replace(/(\d{3})(?=\d)/g, '$1' + thousand) +
(places (places
? decimal + ? decimal +
Math.abs(number - i) Math.abs(number - i)
.toFixed(places) .toFixed(places)
.slice(2) .slice(2)
: '') : '')
) )
} }
...@@ -530,6 +530,14 @@ window.getMonthLastDate = timestamp => { ...@@ -530,6 +530,14 @@ window.getMonthLastDate = timestamp => {
return time return time
} }
window.formatHourTime = (timestr) => {
const h = Math.floor(timestr / 1000 / 60 / 60);
const m = Math.floor((timestr - h * 1000 * 60 * 60) / 1000 / 60);
const s = Math.floor((timestr - h * 1000 * 60 * 60 - m * 1000 * 60) / 1000);
return `${h > 9 ? h : ('0' + h)}:${m > 9 ? m : ('0' + m)}:${s > 9 ? s : ('0' + s)}`
}
/* /*
获取日期相差多少天 获取日期相差多少天
* */ * */
...@@ -666,7 +674,7 @@ window.getLeftExpiredDay = (expiredDate, minWarningDays, onlyShowTimeover) => { ...@@ -666,7 +674,7 @@ window.getLeftExpiredDay = (expiredDate, minWarningDays, onlyShowTimeover) => {
} }
// 处理月份 // 处理月份
window.handleMonth = (num) => { window.handleMonth = (num) => {
var result = '' var result = ''
if (num < 12) { if (num < 12) {
result = `${num}个月` result = `${num}个月`
...@@ -832,7 +840,7 @@ window.getNumberInput = (str, ret = 1) => { ...@@ -832,7 +840,7 @@ window.getNumberInput = (str, ret = 1) => {
return str * ret return str * ret
} }
window.removeNull = function(param) { window.removeNull = function (param) {
if (!param) { if (!param) {
return return
} }
...@@ -853,7 +861,7 @@ window.removeNull = function(param) { ...@@ -853,7 +861,7 @@ window.removeNull = function(param) {
} }
} }
window.convertBase64ToBlob = function(base64) { window.convertBase64ToBlob = function (base64) {
var base64Arr = base64.split(',') var base64Arr = base64.split(',')
var imgtype = '' var imgtype = ''
var base64String = '' var base64String = ''
...@@ -881,20 +889,20 @@ window.convertBase64ToBlob = function(base64) { ...@@ -881,20 +889,20 @@ window.convertBase64ToBlob = function(base64) {
return new Blob([bytesCode], { type: imgtype }) return new Blob([bytesCode], { type: imgtype })
} }
window.formatMsgCreateTime = function(createTime) { window.formatMsgCreateTime = function (createTime) {
const newTime = const newTime =
moment().year() > moment(parseInt(createTime)).year() moment().year() > moment(parseInt(createTime)).year()
? formatDate('YYYY-MM-DD H:i', parseInt(createTime)) ? formatDate('YYYY-MM-DD H:i', parseInt(createTime))
: moment().dayOfYear() - 1 > moment(parseInt(createTime)).dayOfYear() : moment().dayOfYear() - 1 > moment(parseInt(createTime)).dayOfYear()
? formatDate('MM-DD H:i', parseInt(createTime)) ? formatDate('MM-DD H:i', parseInt(createTime))
: moment().dayOfYear() - 1 == moment(parseInt(createTime)).dayOfYear() : moment().dayOfYear() - 1 == moment(parseInt(createTime)).dayOfYear()
? '昨天 ' + formatDate('H:i', parseInt(createTime)) ? '昨天 ' + formatDate('H:i', parseInt(createTime))
: Math.floor((moment().valueOf() - parseInt(createTime)) / 1000 / 60) > 60 : Math.floor((moment().valueOf() - parseInt(createTime)) / 1000 / 60) > 60
? '今天' + formatDate('H:i', parseInt(createTime)) ? '今天' + formatDate('H:i', parseInt(createTime))
: Math.floor((moment().valueOf() - parseInt(createTime)) / 1000 / 60) > 1 : Math.floor((moment().valueOf() - parseInt(createTime)) / 1000 / 60) > 1
? Math.floor((moment().valueOf() - parseInt(createTime)) / 1000 / 60) + ? Math.floor((moment().valueOf() - parseInt(createTime)) / 1000 / 60) +
'分钟前' '分钟前'
: '刚刚' : '刚刚'
return newTime return newTime
} }
...@@ -1070,7 +1078,7 @@ window.getMoneyFormatYuan = (price) => { ...@@ -1070,7 +1078,7 @@ window.getMoneyFormatYuan = (price) => {
// 处理定价标准 仅订单详情,打印收据预览可用 // 处理定价标准 仅订单详情,打印收据预览可用
window.formatPriceStandard = (info) => { window.formatPriceStandard = (info) => {
let { quantityUnit, specName, commoditySpecs, purchaseItemType, unitPriceAfterDiscount,specCurrentPrice } = info let { quantityUnit, specName, commoditySpecs, purchaseItemType, unitPriceAfterDiscount, specCurrentPrice } = info
let newCommoditySpecs = JSON.parse(commoditySpecs || '[]') || {} let newCommoditySpecs = JSON.parse(commoditySpecs || '[]') || {}
let { containQuantity, unitPrice, measurementUnits } = newCommoditySpecs let { containQuantity, unitPrice, measurementUnits } = newCommoditySpecs
let content = '' let content = ''
...@@ -1121,7 +1129,7 @@ window.renderCourseName = (list) => { ...@@ -1121,7 +1129,7 @@ window.renderCourseName = (list) => {
} }
</div> </div>
) )
return length > 1 ? return length > 1 ?
<span>{majorCourse.name} <span>{majorCourse.name}
<Popover placement="bottomLeft" content={content} arrowPointAtCenter> <Popover placement="bottomLeft" content={content} arrowPointAtCenter>
...@@ -1130,7 +1138,7 @@ window.renderCourseName = (list) => { ...@@ -1130,7 +1138,7 @@ window.renderCourseName = (list) => {
</span> : </span> :
<span>{majorCourse.name}</span> <span>{majorCourse.name}</span>
} }
return '' return ''
} }
...@@ -1145,13 +1153,13 @@ window.convertBase64UrlToBlob = (urlData) => { ...@@ -1145,13 +1153,13 @@ window.convertBase64UrlToBlob = (urlData) => {
} }
// 小麦秀 new 标签显示 // 小麦秀 new 标签显示
window.XMShowClassName = (date,itemName) => { window.XMShowClassName = (date, itemName) => {
// 超过时间不显示 // 超过时间不显示
if (new Date().getTime() > date ) { if (new Date().getTime() > date) {
return ''; return '';
} }
// 用户点击相应区域后不显示 // 用户点击相应区域后不显示
if (localStorage.getItem(itemName) === 'true') { if (localStorage.getItem(itemName) === 'true') {
return ''; return '';
} }
return 'new-icon' return 'new-icon'
......
...@@ -1665,3 +1665,38 @@ input:focus { ...@@ -1665,3 +1665,38 @@ input:focus {
.row-dragging .drag-visible { .row-dragging .drag-visible {
visibility: visible; visibility: visible;
} }
.oneLineText{
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.table_operate {
display: flex;
align-items: center;
flex-wrap: wrap;
.operate-text {
color: #5289FA;
cursor: pointer;
}
.operate__item {
color: #5289FA;
cursor: pointer;
&.split {
margin: 0 8px;
color: #BFBFBF;
}
}
.more{
color: #5289FA;
cursor: pointer;
cursor: pointer;
}
}
.ant-tag-blue{
background: transparent !important;
}
\ No newline at end of file
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: yuananting * @Author: yuananting
* @Date: 2021-03-03 15:13:12 * @Date: 2021-03-03 15:13:12
* @LastEditors: yuananting * @LastEditors: yuananting
* @LastEditTime: 2021-03-17 11:40:41 * @LastEditTime: 2021-04-13 13:58:40
* @Description: 助学工具接口 * @Description: 助学工具接口
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/ */
...@@ -29,10 +29,6 @@ export function editCategoryTree(params: object) { ...@@ -29,10 +29,6 @@ export function editCategoryTree(params: object) {
return Service.Hades("public/hades/editCategoryTree", params); return Service.Hades("public/hades/editCategoryTree", params);
} }
export function queryQuestionCategoryTree(params: object) {
return Service.Hades("public/hades/queryQuestionCategoryTree", params);
}
export function queryQuestionPageList(params: object) { export function queryQuestionPageList(params: object) {
return Service.Hades("public/hades/queryQuestionPageList", params); return Service.Hades("public/hades/queryQuestionPageList", params);
} }
...@@ -55,4 +51,36 @@ export function editQuestion(params: object) { ...@@ -55,4 +51,36 @@ export function editQuestion(params: object) {
export function batchImport(params: object) { 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);
}
export function queryPaperPageList(params: object) {
return Service.Hades("public/hades/queryPaperPageList", params);
}
export function deletePaper(params: object) {
return Service.Hades("public/hades/deletePaper", params);
}
export function queryPaperDetail(params: object) {
return Service.Hades("public/hades/queryPaperDetail", params);
}
export function viewPaper(params: object) {
return Service.Hades("public/hades/viewPaper", params);
}
export function editPaper(params: object) {
return Service.Hades("public/hades/editPaper", params);
}
export function batchQueryQuestionDetails(params: object) {
return Service.Hades("public/hades/batchQueryQuestionDetails", params);
}
export function queryQuestionPageListWithContent(params: object) {
return Service.Hades("public/hades/queryQuestionPageListWithContent", params);
} }
\ No newline at end of file
...@@ -2,12 +2,32 @@ ...@@ -2,12 +2,32 @@
* @Author: yuananting * @Author: yuananting
* @Date: 2021-03-11 11:34:37 * @Date: 2021-03-11 11:34:37
* @LastEditors: yuananting * @LastEditors: yuananting
* @LastEditTime: 2021-03-16 15:12:09 * @LastEditTime: 2021-04-13 13:58:11
* @Description: 描述一下咯 * @Description: 助学工具接口
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/ */
import { queryCategoryTree, addCategory, delCategory, editCategory, editCategoryTree, queryQuestionCategoryTree, addQuestion, queryQuestionPageList, deleteQuestion, queryQuestionDetails, editQuestion, batchImport } from '@/data-source/questionBank/request-apis'; import {
export default class QuestionBankService { queryCategoryTree,
addCategory,
delCategory,
editCategory,
editCategoryTree,
addQuestion,
queryQuestionPageList,
deleteQuestion,
queryQuestionDetails,
editQuestion,
batchImport,
createPaper,
queryPaperPageList,
deletePaper,
queryPaperDetail,
viewPaper,
editPaper,
batchQueryQuestionDetails,
queryQuestionPageListWithContent,
} from '@/data-source/aidTool/request-apis';
export default class AidToolService {
// 获取题目分类树 // 获取题目分类树
static queryCategoryTree(params: any) { static queryCategoryTree(params: any) {
return queryCategoryTree(params); return queryCategoryTree(params);
...@@ -33,11 +53,6 @@ export default class QuestionBankService { ...@@ -33,11 +53,6 @@ export default class QuestionBankService {
return editCategoryTree(params); return editCategoryTree(params);
} }
// 查询分类树列表
static queryQuestionCategoryTree(params: any) {
return queryQuestionCategoryTree(params);
}
// 查询题目列表 // 查询题目列表
static queryQuestionPageList(params: any) { static queryQuestionPageList(params: any) {
return queryQuestionPageList(params); return queryQuestionPageList(params);
...@@ -67,4 +82,44 @@ export default class QuestionBankService { ...@@ -67,4 +82,44 @@ export default class QuestionBankService {
static batchImport(params: any) { static batchImport(params: any) {
return batchImport(params); return batchImport(params);
} }
// 创建试卷
static createPaper(params: any) {
return createPaper(params);
}
// 查询试卷列表
static queryPaperPageList(params: any) {
return queryPaperPageList(params);
}
// 删除试卷
static deletePaper(params: any) {
return deletePaper(params);
}
// 编辑前查询试卷信息
static queryPaperDetail(params: any) {
return queryPaperDetail(params);
}
// 预览试卷
static viewPaper(params: any) {
return viewPaper(params);
}
// 编辑试卷
static editPaper(params: any) {
return editPaper(params);
}
// 操作试卷-预览查询多题目信息
static batchQueryQuestionDetails(params: any) {
return batchQueryQuestionDetails(params);
}
// 操作试卷-选择题目列表带题目详情
static queryQuestionPageListWithContent(params: any) {
return queryQuestionPageListWithContent(params);
}
} }
\ No newline at end of file
/* /*
* @Author: 陈剑宇 * @Author: 陈剑宇
* @Date: 2020-05-07 14:43:01 * @Date: 2020-05-07 14:43:01
* @LastEditTime: 2021-03-26 14:05:25 * @LastEditTime: 2021-04-15 21:42:47
* @LastEditors: zhangleyuan * @LastEditors: yuananting
* @Description: * @Description:
* @FilePath: /wheat-web-demo/src/domains/basic-domain/constants.ts * @FilePath: /wheat-web-demo/src/domains/basic-domain/constants.ts
*/ */
......
declare module 'jquery' declare module 'jquery'
declare module 'cropper' declare module 'cropper'
declare var this: any declare module 'ExamShareModal'
\ No newline at end of file // declare var this: any
\ No newline at end of file
import React, { useState, useRef, useEffect } from 'react'
import { Select } from 'antd';
import StoreService from "@/domains/store-domain/storeService";
export default function ExaminationManager(props: any) {
const queryInit: any = {
planName: ''
}
const teacherQueryInit: any = {};
const [teacherQuery, setTeacherQuery] = useState({
current:1,
size: 10,
roleCodes:props.roleCodes
});
const [teacherList, setTeacherList] = useState([]);
const [hasNext, setHasNext] = useState(true);
const teacherQueryRef = useRef({})
useEffect(() => {
teacherQueryRef.current = teacherQuery;
getTeacherList()
}, [teacherQuery])
function getTeacherList() {
const _query: any = {
...teacherQueryRef.current,
};
StoreService.getStoreUserBasicPage(_query).then((res) => {
const { result = {} } = res;
const { records = [], total = 0, hasNext } = result;
const list = _query.current > 1 ? teacherList.concat(records) : records;
setTeacherList(list);
setHasNext(hasNext)
});
}
// 滑动加载更多讲师列表
function handleScrollTeacherList(e: any) {
const container = e.target;
const scrollToBottom = container && container.scrollHeight <= container.clientHeight + container.scrollTop;
if (scrollToBottom && hasNext) {
let _teacherQuery: any = { ...teacherQueryRef.current };
_teacherQuery.current = _teacherQuery.current + 1;
setTeacherQuery(_teacherQuery)
}
}
return <div className="search-condition__item">
<span className="search-name">创建人:</span>
<Select
placeholder="请选择创建人"
className='search-input'
showSearch
allowClear
onPopupScroll={handleScrollTeacherList}
suffixIcon={<span className="icon iconfont" style={{ fontSize: '12px', color: '#BFBFBF' }}>&#xe835;</span>}
value={props.val || null}
onChange={(value) => {
props.onChange(value)
}}
onSearch={(value) => {
let _teacherQuery: any = { ...teacherQueryRef.current };
_teacherQuery.nickName = value;
setTeacherQuery(_teacherQuery)
}}
onClear={() => {
props.onChange(null)
setTeacherQuery({
roleCodes:props.roleCodes,
current:1,
size: 10
})
}}
>
{teacherList.map((item: any) => {
return (
<Select.Option value={item.id} key={item.id}>{item.nickName}</Select.Option>
);
})}
</Select>
</div>
}
\ No newline at end of file
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: 吴文洁 * @Author: 吴文洁
* @Date: 2020-07-17 15:49:11 * @Date: 2020-07-17 15:49:11
* @Last Modified by: chenshu * @Last Modified by: chenshu
* @Last Modified time: 2021-03-24 14:13:04 * @Last Modified time: 2021-04-06 16:43:23
* @Description: 大班互动-添加/编辑直播课 * @Description: 大班互动-添加/编辑直播课
*/ */
...@@ -20,7 +20,6 @@ import AddLiveIntro from './components/AddLiveIntro'; ...@@ -20,7 +20,6 @@ import AddLiveIntro from './components/AddLiveIntro';
import { randomString } from '@/domains/basic-domain/utils'; import { randomString } from '@/domains/basic-domain/utils';
import Upload from '@/core/upload'; import Upload from '@/core/upload';
import PreviewCourseModal from './modal/PreviewCourseModal'; import PreviewCourseModal from './modal/PreviewCourseModal';
import SelectPrepareFileModal from '../prepare-lesson/modal/SelectPrepareFileModal';
import CourseService from "@/domains/course-domain/CourseService"; import CourseService from "@/domains/course-domain/CourseService";
import moment from 'moment'; import moment from 'moment';
import User from '@/common/js/user'; import User from '@/common/js/user';
...@@ -113,23 +112,6 @@ class AddLive extends React.Component { ...@@ -113,23 +112,6 @@ class AddLive extends React.Component {
if (type === 'edit') { if (type === 'edit') {
this.getCourseDetail(); this.getCourseDetail();
} }
this.initBus();
}
componentWillUnmount() {
this.removeBus();
}
initBus = () => {
Bus.bind('graphicsEditorImage', this.uploadImage)
}
removeBus = () => {
Bus.unbind('graphicsEditorImage', this.uploadImage)
}
uploadImage = () => {
this.setState({ showSelectImageModal: true })
} }
getCourseDetail = () => { getCourseDetail = () => {
...@@ -543,20 +525,6 @@ handleChangeBasicInfo = (field, value) => { ...@@ -543,20 +525,6 @@ handleChangeBasicInfo = (field, value) => {
} }
} }
handleSelectImage = (file) => {
this.setState({
showSelectImageModal: false
})
const { ossUrl } = file;
const { addLiveIntroInfo } = this.state;
this.setState({
addLiveIntroInfo: {
...addLiveIntroInfo,
introduce: `${addLiveIntroInfo.introduce}<p><img style="max-width: 100%;" src="${ossUrl}" /><br/><p>`
}
});
}
render() { render() {
const { const {
...@@ -567,9 +535,7 @@ handleChangeBasicInfo = (field, value) => { ...@@ -567,9 +535,7 @@ handleChangeBasicInfo = (field, value) => {
addLiveIntroInfo, addLiveIntroInfo,
isEdit, isEdit,
loadintroduce, loadintroduce,
showSelectImageModal,
} = this.state; } = this.state;
console.log(loadintroduce, addLiveIntroInfo, 888888)
return ( return (
<div className="page add-live-page"> <div className="page add-live-page">
<Breadcrumbs <Breadcrumbs
...@@ -617,22 +583,6 @@ handleChangeBasicInfo = (field, value) => { ...@@ -617,22 +583,6 @@ handleChangeBasicInfo = (field, value) => {
<Button onClick={this.handleShowPreviewModal}>预览</Button> <Button onClick={this.handleShowPreviewModal}>预览</Button>
<Button type="primary" onClick={_.debounce(() => this.handleSubmit(), 3000, true)}>保存</Button> <Button type="primary" onClick={_.debounce(() => this.handleSubmit(), 3000, true)}>保存</Button>
</div> </div>
{showSelectImageModal &&
<SelectPrepareFileModal
key="basic"
operateType="select"
multiple={false}
accept="image/jpeg,image/png,image/jpg"
selectTypeList={['JPG', 'JPEG', 'PNG']}
tooltip='支持文件类型:jpg、jpeg、png'
isOpen={showSelectImageModal}
onClose={() => {
this.setState({ showSelectImageModal: false })
}}
onSelect={this.handleSelectImage}
/>
}
{ this.state.previewLiveCourseModal } { this.state.previewLiveCourseModal }
{ this.state.lackConsumeStudentModal } { this.state.lackConsumeStudentModal }
</div> </div>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: 吴文洁 * @Author: 吴文洁
* @Date: 2020-07-16 11:05:17 * @Date: 2020-07-16 11:05:17
* @Last Modified by: chenshu * @Last Modified by: chenshu
* @Last Modified time: 2021-03-23 17:39:50 * @Last Modified time: 2021-04-06 16:40:24
* @Description: 添加直播-简介 * @Description: 添加直播-简介
*/ */
...@@ -83,61 +83,6 @@ class AddLiveIntro extends React.Component { ...@@ -83,61 +83,6 @@ class AddLiveIntro extends React.Component {
} }
// 删除简介
handleDeleteIntro = (index) => {
const { liveCourseMediaRequests } = this.props.data;
liveCourseMediaRequests.splice(index, 1);
this.props.onChange('liveCourseMediaRequests', liveCourseMediaRequests);
}
// 上移简介
handleMoveUpIntro = (index) => {
const { liveCourseMediaRequests } = this.props.data;
const prevItem = liveCourseMediaRequests[index];
const nextItem = liveCourseMediaRequests[index + 1];
liveCourseMediaRequests.splice(index, 2, nextItem, prevItem);
this.props.onChange('liveCourseMediaRequests', liveCourseMediaRequests);
}
// 下移简介
handleMoveDownIntro = (index) => {
const { liveCourseMediaRequests } = this.props.data;
const prevItem = liveCourseMediaRequests[index - 1];
const nextItem = liveCourseMediaRequests[index];
liveCourseMediaRequests.splice(index - 1, 2, nextItem, prevItem);
this.props.onChange('liveCourseMediaRequests', liveCourseMediaRequests);
}
renderLittleIcon = (index) => {
const { liveCourseMediaRequests } = this.props.data;
return (
<div className="little-icon">
<span
className="icon iconfont close"
onClick={() => { this.handleDeleteIntro(index); }}
></span>
{
index > 0 &&
<span
className="icon iconfont"
onClick={() => { this.handleMoveDownIntro(index); }}
>&#xe6d1;</span>
}
{
index !== liveCourseMediaRequests.length - 1 &&
<span
className="icon iconfont"
onClick={() => { this.handleMoveUpIntro(index); }}
>&#xe6cf;</span>
}
</div>
)
}
changeIntro = (value) => { changeIntro = (value) => {
this.props.onChange('introduce', value); this.props.onChange('introduce', value);
} }
...@@ -149,9 +94,6 @@ class AddLiveIntro extends React.Component { ...@@ -149,9 +94,6 @@ class AddLiveIntro extends React.Component {
this.props.onChange('whetherVisitorsJoin','NO') this.props.onChange('whetherVisitorsJoin','NO')
} }
} }
componentWillMount() {
}
render() { render() {
const {liveType, isXiaomai, isEdit, data: { id, introduce, needRecord,whetherVisitorsJoin, loadintroduce, liveCourseWarmMedia = {} } } = this.props; const {liveType, isXiaomai, isEdit, data: { id, introduce, needRecord,whetherVisitorsJoin, loadintroduce, liveCourseWarmMedia = {} } } = this.props;
......
import { message } from 'antd';
import React from 'react'; import React from 'react';
import E from 'wangeditor'; import E from 'wangeditor';
import Bus from '../../../core/bus'; import Bus from '../../../core/bus';
import SelectPrepareFileModal from '../../prepare-lesson/modal/SelectPrepareFileModal';
import './GraphicsEditor.less'; import './GraphicsEditor.less';
const { BtnMenu } = E; const { BtnMenu } = E;
class ImageMenu extends BtnMenu {
constructor(editor) {
// data-title属性表示当鼠标悬停在该按钮上时提示该按钮的功能简述
const $elem = E.$(
`<div class="w-e-menu" data-title="图片">
<i class="w-e-icon-image"></i>
</div>`
)
super($elem, editor)
}
// 菜单点击事件
clickHandler() {
Bus.trigger('graphicsEditorImage')
}
tryChangeActive() {
}
}
class VideoMenu extends BtnMenu {
constructor(editor) {
// data-title属性表示当鼠标悬停在该按钮上时提示该按钮的功能简述
const $elem = E.$(
`<div class="w-e-menu" data-title="视频">
<i class="w-e-icon-play"></i>
</div>`
)
super($elem, editor)
}
// 菜单点击事件
clickHandler() {
Bus.trigger('graphicsEditorVideo')
}
tryChangeActive() {
}
}
class GraphicsEditor extends React.Component { class GraphicsEditor extends React.Component {
constructor(props) { constructor(props) {
super(props) super(props)
this.state = { this.state = {
editorId: window.random_string(16), editorId: window.random_string(16),
textLength: 0, textLength: 0,
showSelectImageModal: false,
showSelectVideoModal: false,
} }
this.editorInt = null; this.editorInt = null;
this.isContent = true;
} }
componentDidMount() { componentDidMount() {
this.renderEditor() this.renderEditor()
this.resetIndex(true); this.resetIndex(true);
this.initBus();
this.bindClick();
} }
componentWillReceiveProps(nextProps) {
const { content } = this.props.detail;
const { content: nextContent } = nextProps.detail;
const videoCount = ((content || '').match(/<iframe/g) || []).length;
const nextVideoCount = ((nextContent || '').match(/<iframe/g) || []).length;
const imageCount = ((content || '').match(/<img/g) || []).length;
const nextImageCount = ((nextContent || '').match(/<img/g) || []).length;
if ((videoCount !== nextVideoCount) || (imageCount !== nextImageCount)) {
this.editorInt && this.editorInt.txt.html(nextProps.detail.content);
}
}
componentWillUnmount() { componentWillUnmount() {
this.resetIndex(); this.resetIndex();
this.removeBus();
this.removeClick();
}
bindClick = () => {
window.addEventListener('click', this.clickEditor)
}
removeClick = () => {
window.removeEventListener('click', this.clickEditor)
}
clickEditor = (e) => {
if (e && e.target.closest('.content-editor')) {
this.isContent = true
} else if (e && e.target.closest('.introduce-editor')) {
this.isContent = false
}
} }
resetIndex = (bool) => { resetIndex = (bool) => {
...@@ -85,7 +60,47 @@ class GraphicsEditor extends React.Component { ...@@ -85,7 +60,47 @@ class GraphicsEditor extends React.Component {
renderEditor() { renderEditor() {
const { editorId } = this.state; const { editorId } = this.state;
const { detail, onChange, isIntro } = this.props; const { detail, onChange, isIntro, maxLimit } = this.props;
class ImageMenu extends BtnMenu {
constructor(editor) {
// data-title属性表示当鼠标悬停在该按钮上时提示该按钮的功能简述
const $elem = E.$(
`<div class="w-e-menu" data-title="图片">
<i class="w-e-icon-image"></i>
</div>`
)
super($elem, editor)
}
// 菜单点击事件
clickHandler() {
Bus.trigger(`graphicsEditorImage${isIntro ? '' : 'Content'}`)
}
tryChangeActive() {
}
}
class VideoMenu extends BtnMenu {
constructor(editor) {
// data-title属性表示当鼠标悬停在该按钮上时提示该按钮的功能简述
const $elem = E.$(
`<div class="w-e-menu" data-title="视频">
<i class="w-e-icon-play"></i>
</div>`
)
super($elem, editor)
}
// 菜单点击事件
clickHandler() {
Bus.trigger('graphicsEditorVideo')
}
tryChangeActive() {
}
}
this.editorInt = new E(`#editor${editorId}`); this.editorInt = new E(`#editor${editorId}`);
this.editorInt.config.showFullScreen = !isIntro this.editorInt.config.showFullScreen = !isIntro
this.editorInt.menus.extend('xmimage', ImageMenu); this.editorInt.menus.extend('xmimage', ImageMenu);
...@@ -157,6 +172,9 @@ class GraphicsEditor extends React.Component { ...@@ -157,6 +172,9 @@ class GraphicsEditor extends React.Component {
const imageCount = ((html || '').match(/<img/g) || []).length; const imageCount = ((html || '').match(/<img/g) || []).length;
const textLength = this.editorInt.txt.text().replace(/\&nbsp\;/ig, ' ').length + videoCount + imageCount; const textLength = this.editorInt.txt.text().replace(/\&nbsp\;/ig, ' ').length + videoCount + imageCount;
this.setState({ textLength }, () => { this.setState({ textLength }, () => {
if (textLength > maxLimit) {
// message.warning('超过字数限定');
}
onChange(html, this.state.textLength); onChange(html, this.state.textLength);
}) })
} }
...@@ -164,12 +182,85 @@ class GraphicsEditor extends React.Component { ...@@ -164,12 +182,85 @@ class GraphicsEditor extends React.Component {
this.editorInt.txt.html(detail.content); this.editorInt.txt.html(detail.content);
} }
// 选择图文
handleSelectVideo = (file) => {
this.setState({
showSelectVideoModal: false
})
const { ossUrl } = file;
const { detail } = this.props;
this.editorInt && this.editorInt.txt.html(`${detail.content}<p style="width: 100%;padding-top: 56.25%;position: relative;"><iframe style="position: absolute;width: 100%;height: 100%;top: 0;left: 0;" src="${ossUrl}"></iframe><br/></p><p><br/></p>`)
}
handleSelectImage = (file) => {
this.setState({
showSelectImageModal: false
})
const { ossUrl } = file;
const { detail } = this.props;
this.editorInt && this.editorInt.txt.html(`${detail.content}<p><img style="max-width: 100%;" src="${ossUrl}" /><br/><p>`)
}
initBus = () => {
const { isIntro } = this.props;
Bus.bind(`graphicsEditorImage${isIntro ? '' : 'Content'}`, this.uploadImage)
Bus.bind('graphicsEditorVideo', this.uploadVideo)
}
removeBus = () => {
const { isIntro } = this.props;
Bus.unbind(`graphicsEditorImage${isIntro ? '' : 'Content'}`, this.uploadImage)
Bus.unbind('graphicsEditorVideo', this.uploadVideo)
}
uploadImage = () => {
this.setState({ showSelectImageModal: true })
}
uploadVideo = () => {
this.setState({ showSelectVideoModal: true })
}
render() { render() {
const { editorId, textLength } = this.state; const { editorId, textLength, showSelectImageModal, showSelectVideoModal } = this.state;
const { limitLength = 1000, isIntro } = this.props; const { limitLength = 1000, isIntro, maxLimit } = this.props;
return <div className={`graphics-editor-container${isIntro ? ' introduce' : ''}`}> return <div className={`graphics-editor-container${isIntro ? ' introduce' : ''} ${(textLength > maxLimit)&& 'warning'}`}>
<div className="editor-box" id={`editor${editorId}`}></div> <div className="editor-box" id={`editor${editorId}`} ></div>
<div className="editor-tips">({textLength}/100000)</div> <div className="editor-tips">( {(textLength > maxLimit) ? <span style={{ color: 'red' }} >{textLength}</span> : textLength}/{maxLimit || 100000})</div>
{showSelectVideoModal &&
<SelectPrepareFileModal
operateType="select"
selectTypeList={['MP4']}
accept="video/mp4"
confirm={{
title: '文件过大,无法上传',
content: '为保障学员的观看体验,上传的图文大小不能超过2G',
}}
tooltip={'格式支持mp4,大小不超过2G'}
isOpen={showSelectVideoModal}
diskList={diskList}
addVideo={true}
onClose={() => {
this.setState({ showSelectVideoModal: false })
}}
onSelect={this.handleSelectVideo}
/>
}
{showSelectImageModal &&
<SelectPrepareFileModal
key="basic"
operateType="select"
multiple={false}
accept="image/jpeg,image/png,image/jpg"
selectTypeList={['JPG', 'JPEG', 'PNG']}
tooltip='支持文件类型:jpg、jpeg、png'
isOpen={showSelectImageModal}
onClose={() => {
this.setState({ showSelectImageModal: false })
}}
onSelect={this.handleSelectImage}
/>
}
</div> </div>
} }
} }
......
...@@ -49,4 +49,8 @@ ...@@ -49,4 +49,8 @@
height: ~'calc(100% - 69px)' !important; height: ~'calc(100% - 69px)' !important;
} }
} }
&.warning{
border-color: red;
}
} }
\ No newline at end of file
...@@ -15,7 +15,6 @@ import { DISK_MAP, FileTypeIcon, FileVerifyMap } from '@/common/constants/academ ...@@ -15,7 +15,6 @@ import { DISK_MAP, FileTypeIcon, FileVerifyMap } from '@/common/constants/academ
import { ImgCutModalNew } from '@/components'; import { ImgCutModalNew } from '@/components';
import ShowTips from "@/components/ShowTips"; import ShowTips from "@/components/ShowTips";
import Breadcrumbs from "@/components/Breadcrumbs"; import Breadcrumbs from "@/components/Breadcrumbs";
import Bus from '../../../core/bus'
import AddGraphicsIntro from './components/AddGraphicsIntro'; import AddGraphicsIntro from './components/AddGraphicsIntro';
import SelectStudent from '../modal/select-student'; import SelectStudent from '../modal/select-student';
import SelectPrepareFileModal from '../../prepare-lesson/modal/SelectPrepareFileModal'; import SelectPrepareFileModal from '../../prepare-lesson/modal/SelectPrepareFileModal';
...@@ -70,10 +69,6 @@ class AddGraphicsCourse extends React.Component { ...@@ -70,10 +69,6 @@ class AddGraphicsCourse extends React.Component {
} }
} }
componentDidMount() {
this.initBus()
}
componentWillMount() { componentWillMount() {
const { id, pageType } = this.state; const { id, pageType } = this.state;
this.getCourseCatalogList(); this.getCourseCatalogList();
...@@ -82,10 +77,6 @@ class AddGraphicsCourse extends React.Component { ...@@ -82,10 +77,6 @@ class AddGraphicsCourse extends React.Component {
} }
} }
componentWillUnmount() {
this.removeBus();
}
initBus = () => { initBus = () => {
Bus.bind('graphicsEditorImage', this.uploadImage) Bus.bind('graphicsEditorImage', this.uploadImage)
Bus.bind('graphicsEditorVideo', this.uploadVideo) Bus.bind('graphicsEditorVideo', this.uploadVideo)
...@@ -303,29 +294,6 @@ class AddGraphicsCourse extends React.Component { ...@@ -303,29 +294,6 @@ class AddGraphicsCourse extends React.Component {
this.setState({ previewGraphicsModal }); this.setState({ previewGraphicsModal });
} }
// 选择图文
handleSelectVideo = (file) => {
this.setState({
showSelectVideoModal: false
})
const { ossUrl } = file;
const { courseMedia } = this.state;
this.setState({
courseMedia: `${courseMedia}<p style="width: 100%;padding-top: 56.25%;position: relative;"><iframe style="position: absolute;width: 100%;height: 100%;top: 0;left: 0;" src="${ossUrl}"></iframe><br/></p><p><br/></p>`
});
}
handleSelectImage = (file) => {
this.setState({
showSelectImageModal: false
})
const { ossUrl } = file;
const { courseMedia, introduce, isContent } = this.state;
this.setState({
[isContent ? 'courseMedia' : 'introduce']: `${isContent ? courseMedia : introduce}<p><img style="max-width: 100%;" src="${ossUrl}" /><br/><p>`
});
}
handleSelectCover = (file)=> { handleSelectCover = (file)=> {
this.uploadCoverImage(file); this.uploadCoverImage(file);
...@@ -546,8 +514,6 @@ class AddGraphicsCourse extends React.Component { ...@@ -546,8 +514,6 @@ class AddGraphicsCourse extends React.Component {
courseMedia, courseMedia,
introduce, introduce,
showCutModal, showCutModal,
showSelectVideoModal,
showSelectImageModal,
diskList, diskList,
imageFile, imageFile,
videoType, videoType,
...@@ -640,41 +606,6 @@ class AddGraphicsCourse extends React.Component { ...@@ -640,41 +606,6 @@ class AddGraphicsCourse extends React.Component {
<Button type="primary" onClick={_.debounce(() => this.handleSubmit(), 3000, true)}>保存</Button> <Button type="primary" onClick={_.debounce(() => this.handleSubmit(), 3000, true)}>保存</Button>
</div> </div>
{/* 选择备课文件弹窗 */}
{ showSelectVideoModal &&
<SelectPrepareFileModal
operateType="select"
selectTypeList={['MP4']}
accept="video/mp4"
confirm={{
title: '文件过大,无法上传',
content: '为保障学员的观看体验,上传的图文大小不能超过2G',
}}
tooltip={'格式支持mp4,大小不超过2G'}
isOpen={showSelectVideoModal}
diskList={diskList}
addVideo={true}
onClose={() => {
this.setState({ showSelectVideoModal: false })
}}
onSelect={this.handleSelectVideo}
/>
}
{showSelectImageModal &&
<SelectPrepareFileModal
key="basic"
operateType="select"
multiple={false}
accept="image/jpeg,image/png,image/jpg"
selectTypeList={['JPG', 'JPEG', 'PNG']}
tooltip='支持文件类型:jpg、jpeg、png'
isOpen={showSelectImageModal}
onClose={() => {
this.setState({ showSelectImageModal: false })
}}
onSelect={this.handleSelectImage}
/>
}
{showSelectCoverModal && {showSelectCoverModal &&
<SelectPrepareFileModal <SelectPrepareFileModal
key="basic" key="basic"
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: 吴文洁 * @Author: 吴文洁
* @Date: 2020-07-16 11:05:17 * @Date: 2020-07-16 11:05:17
* @Last Modified by: chenshu * @Last Modified by: chenshu
* @Last Modified time: 2021-03-25 11:25:02 * @Last Modified time: 2021-04-06 16:17:57
* @Description: 添加直播-简介 * @Description: 添加直播-简介
*/ */
...@@ -28,33 +28,6 @@ class AddGraphicsIntro extends React.Component { ...@@ -28,33 +28,6 @@ class AddGraphicsIntro extends React.Component {
diskList: [], diskList: [],
selectType: null, selectType: null,
} }
this.isContent = true;
}
componentDidMount() {
this.bindClick();
}
componentWillUnmount() {
this.removeClick();
}
bindClick = () => {
window.addEventListener('click', this.clickEditor)
}
removeClick = () => {
window.removeEventListener('click', this.clickEditor)
}
clickEditor = (e) => {
if (e && e.target.closest('.content-editor')) {
this.isContent = true
console.log(11111111)
} else if (e && e.target.closest('.introduce-editor')) {
this.isContent = false
console.log(222222222)
}
} }
// 上传封面图 // 上传封面图
...@@ -109,17 +82,11 @@ class AddGraphicsIntro extends React.Component { ...@@ -109,17 +82,11 @@ class AddGraphicsIntro extends React.Component {
} }
changeDetail = (value) => { changeDetail = (value) => {
this.props.onChange('isContent', !!this.isContent); this.props.onChange('courseMedia', value);
setTimeout(() => {
this.props.onChange('courseMedia', value);
}, 0)
} }
changeIntro = (value) => { changeIntro = (value) => {
this.props.onChange('isContent', !!this.isContent); this.props.onChange('introduce', value);
setTimeout(() => {
this.props.onChange('introduce', value);
}, 0)
} }
whetherVisitorsJoinChange = ()=>{ whetherVisitorsJoinChange = ()=>{
......
...@@ -33,9 +33,11 @@ class GraphicsCourseFilter extends React.Component { ...@@ -33,9 +33,11 @@ class GraphicsCourseFilter extends React.Component {
expandFilter:false expandFilter:false
} }
} }
componentDidMount() { componentDidMount() {
this.getTeacherList(); this.getTeacherList();
} }
getTeacherList(current = 1, selectList){ getTeacherList(current = 1, selectList){
const { teacherQuery,teacherList} = this.state; const { teacherQuery,teacherList} = this.state;
const _query = { const _query = {
...@@ -53,6 +55,7 @@ class GraphicsCourseFilter extends React.Component { ...@@ -53,6 +55,7 @@ class GraphicsCourseFilter extends React.Component {
}) })
}); });
} }
// 滑动加载更多讲师列表 // 滑动加载更多讲师列表
handleScrollTeacherList = (e) => { handleScrollTeacherList = (e) => {
const { hasNext } = this.state; const { hasNext } = this.state;
......
...@@ -27,7 +27,6 @@ import _ from "underscore"; ...@@ -27,7 +27,6 @@ import _ from "underscore";
import Upload from '@/core/upload'; import Upload from '@/core/upload';
import { randomString } from '@/domains/basic-domain/utils'; import { randomString } from '@/domains/basic-domain/utils';
import $ from 'jquery'; import $ from 'jquery';
import Bus from '../../../core/bus'
// import PhotoClip from 'photoclip'; // import PhotoClip from 'photoclip';
import './AddVideoCourse.less'; import './AddVideoCourse.less';
...@@ -90,19 +89,6 @@ class AddVideoCourse extends React.Component { ...@@ -90,19 +89,6 @@ class AddVideoCourse extends React.Component {
if (pageType === 'edit') { if (pageType === 'edit') {
this.handleFetchScheudleDetail(id); this.handleFetchScheudleDetail(id);
} }
this.initBus()
}
initBus = () => {
Bus.bind('graphicsEditorImage', this.uploadIntroImage)
}
removeBus = () => {
Bus.unbind('graphicsEditorImage', this.uploadIntroImage)
}
uploadIntroImage = () => {
this.setState({ showSelectImageModal: true })
} }
//获取分类列表 //获取分类列表
...@@ -447,17 +433,6 @@ class AddVideoCourse extends React.Component { ...@@ -447,17 +433,6 @@ class AddVideoCourse extends React.Component {
handleSelectCover = (file)=> { handleSelectCover = (file)=> {
this.uploadImage(file); this.uploadImage(file);
} }
handleSelectImage = (file) => {
this.setState({
showSelectImageModal: false
})
const { ossUrl } = file;
const { introduce } = this.state;
this.setState({
introduce: `${introduce}<p><img style="max-width: 100%;" src="${ossUrl}" /><br/><p>`
});
}
//上传图片 //上传图片
uploadImage = (imageFile) => { uploadImage = (imageFile) => {
...@@ -574,7 +549,6 @@ class AddVideoCourse extends React.Component { ...@@ -574,7 +549,6 @@ class AddVideoCourse extends React.Component {
introduce, introduce,
loadintroduce, loadintroduce,
id, id,
showSelectImageModal,
} = this.state; } = this.state;
// 已选择的上课学员数量 // 已选择的上课学员数量
...@@ -702,21 +676,6 @@ class AddVideoCourse extends React.Component { ...@@ -702,21 +676,6 @@ class AddVideoCourse extends React.Component {
onSelect={this.handleSelectVideo} onSelect={this.handleSelectVideo}
/> />
} }
{showSelectImageModal &&
<SelectPrepareFileModal
key="basic"
operateType="select"
multiple={false}
accept="image/jpeg,image/png,image/jpg"
selectTypeList={['JPG', 'JPEG', 'PNG']}
tooltip='支持文件类型:jpg、jpeg、png'
isOpen={showSelectImageModal}
onClose={() => {
this.setState({ showSelectImageModal: false })
}}
onSelect={this.handleSelectImage}
/>
}
{showSelectCoverModal && {showSelectCoverModal &&
<SelectPrepareFileModal <SelectPrepareFileModal
key="basic" key="basic"
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: 吴文洁 * @Author: 吴文洁
* @Date: 2020-07-16 11:05:17 * @Date: 2020-07-16 11:05:17
* @Last Modified by: chenshu * @Last Modified by: chenshu
* @Last Modified time: 2021-03-23 18:12:05 * @Last Modified time: 2021-04-06 16:44:09
* @Description: 添加直播-简介 * @Description: 添加直播-简介
*/ */
...@@ -82,84 +82,11 @@ class AddVideoIntro extends React.Component { ...@@ -82,84 +82,11 @@ class AddVideoIntro extends React.Component {
} }
} }
// 删除简介
handleDeleteIntro = (index) => {
const { liveCourseMediaRequests } = this.props.data;
liveCourseMediaRequests.splice(index, 1);
this.props.onChange('liveCourseMediaRequests', liveCourseMediaRequests);
}
// 上移简介
handleMoveUpIntro = (index) => {
const { liveCourseMediaRequests } = this.props.data;
const prevItem = liveCourseMediaRequests[index];
const nextItem = liveCourseMediaRequests[index + 1];
liveCourseMediaRequests.splice(index, 2, nextItem, prevItem);
this.props.onChange('liveCourseMediaRequests', liveCourseMediaRequests);
}
// 下移简介
handleMoveDownIntro = (index) => {
const { liveCourseMediaRequests } = this.props.data;
const prevItem = liveCourseMediaRequests[index - 1];
const nextItem = liveCourseMediaRequests[index];
liveCourseMediaRequests.splice(index - 1, 2, nextItem, prevItem);
this.props.onChange('liveCourseMediaRequests', liveCourseMediaRequests);
}
renderLittleIcon = (index) => {
const { liveCourseMediaRequests } = this.props.data;
return (
<div className="little-icon">
<span
className="icon iconfont close"
onClick={() => { this.handleDeleteIntro(index); }}
></span>
{
index > 0 &&
<span
className="icon iconfont"
onClick={() => { this.handleMoveDownIntro(index); }}
>&#xe6d1;</span>
}
{
index !== liveCourseMediaRequests.length - 1 &&
<span
className="icon iconfont"
onClick={() => { this.handleMoveUpIntro(index); }}
>&#xe6cf;</span>
}
</div>
)
}
handleChangeIntro = (index, value, length) => {
const { liveCourseMediaRequests } = this.props.data;
liveCourseMediaRequests[index].mediaContent = value;
liveCourseMediaRequests[index].mediaContentLength = length
this.props.onChange('liveCourseMediaRequests', liveCourseMediaRequests);
}
changeIntro = (value) => { changeIntro = (value) => {
this.props.onChange('introduce', value); this.props.onChange('introduce', value);
} }
handleAddIntroText = () => {
const { liveCourseMediaRequests } = this.props.data;
liveCourseMediaRequests.push({
contentType:"INTRO",
mediaType: 'TEXT',
mediaContent: '',
key: Math.random()
});
this.props.onChange('liveCourseMediaRequests', liveCourseMediaRequests);
}
handleUpload = (Blob) => { handleUpload = (Blob) => {
this.setState({ this.setState({
showSelectFileModal: true, showSelectFileModal: true,
...@@ -180,9 +107,7 @@ class AddVideoIntro extends React.Component { ...@@ -180,9 +107,7 @@ class AddVideoIntro extends React.Component {
this.props.onChange('shelfState','NO') this.props.onChange('shelfState','NO')
} }
} }
componentWillMount() {
}
render() { render() {
const {data: { whetherVisitorsJoin,liveCourseMediaRequests = [], shelfState, id, introduce, loadintroduce } } = this.props; const {data: { whetherVisitorsJoin,liveCourseMediaRequests = [], shelfState, id, introduce, loadintroduce } } = this.props;
const {showSelectFileModal,selectType} = this.state const {showSelectFileModal,selectType} = this.state
......
...@@ -96,7 +96,9 @@ class Home extends React.Component { ...@@ -96,7 +96,9 @@ class Home extends React.Component {
Service.Hades('public/hades/storePanelInfo', { storeId: User.getStoreId() }).then((res) => { Service.Hades('public/hades/storePanelInfo', { storeId: User.getStoreId() }).then((res) => {
if (res.success) { if (res.success) {
this.setState({ this.setState({
examNum: res.result.examNum,
incCustomerNum: res.result.incCustomerNum, incCustomerNum: res.result.incCustomerNum,
incExamNum: res.result.incExamNum,
incLiveCourseNum: res.result.incLiveCourseNum, incLiveCourseNum: res.result.incLiveCourseNum,
incVideoCourseNum: res.result.incVideoCourseNum, incVideoCourseNum: res.result.incVideoCourseNum,
incPictureCourseNum: res.result.incPictureCourseNum, incPictureCourseNum: res.result.incPictureCourseNum,
...@@ -210,6 +212,8 @@ class Home extends React.Component { ...@@ -210,6 +212,8 @@ class Home extends React.Component {
render() { render() {
const { const {
examNum,
incExamNum,
list, list,
incCustomerNum, incCustomerNum,
incLiveCourseNum, incLiveCourseNum,
...@@ -340,18 +344,19 @@ class Home extends React.Component { ...@@ -340,18 +344,19 @@ class Home extends React.Component {
<span className="footer-number">{incTrainingPlanNum}</span> <span className="footer-number">{incTrainingPlanNum}</span>
</div> </div>
</div> </div>
<div className="data-item"> <div className="data-item">
<div className="header"> <div className="header">
<img className="header-icon" src="https://image.xiaomaiketang.com/xm/3CfrPs23Re.png" /> <img className="header-icon" src="https://image.xiaomaiketang.com/xm/3CfrPs23Re.png" />
<span className="header-word">考试总数 (个)</span> <span className="header-word">考试总数 (个)</span>
</div> </div>
<div className="data-number">0</div> <div className="data-number">{examNum}</div>
<div className="data-footer"> <div className="data-footer">
<span className="footer-word">本月新增</span> <span className="footer-word">本月新增</span>
{false && {incExamNum > 0 &&
<span className="icon iconfont">&#xe635;</span> <span className="icon iconfont">&#xe635;</span>
} }
<span className="footer-number">0</span> <span className="footer-number">{incExamNum}</span>
</div> </div>
</div> </div>
</div> </div>
......
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
* @Description: * @Description:
* @Author: zangsuyun * @Author: zangsuyun
* @Date: 2021-03-19 18:05:23 * @Date: 2021-03-19 18:05:23
* @LastEditors: zangsuyun * @LastEditors: yuananting
* @LastEditTime: 2021-04-08 11:29:12 * @LastEditTime: 2021-04-15 21:46:41
* @Copyright: © 2020 杭州杰竞科技有限公司 版权所有 * @Copyright: © 2020 杭州杰竞科技有限公司 版权所有
*/ */
...@@ -202,7 +202,7 @@ class Classification extends Component { ...@@ -202,7 +202,7 @@ class Classification extends Component {
<Button <Button
onClick={() => { onClick={() => {
window.RCHistory.push({ window.RCHistory.push({
pathname: "/question-category-manage?from=knowledge", pathname: "/course-category-manage?from=knowledge",
}); });
}} }}
> >
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
*/ */
import React, { useContext, useEffect, useState } from 'react'; import React, { useContext, useEffect, useState } from 'react';
import { withRouter } from 'react-router-dom'; import { withRouter } from 'react-router-dom';
import { ConfigProvider } from 'antd'; import { ConfigProvider, message } from 'antd';
import Header from './Header' import Header from './Header'
import Menu from './Menu' import Menu from './Menu'
import Main from './Main' import Main from './Main'
...@@ -67,12 +67,17 @@ const App: React.FC = (props: any) => { ...@@ -67,12 +67,17 @@ const App: React.FC = (props: any) => {
BaseService.getUserStore({ userId }).then((res) => { BaseService.getUserStore({ userId }).then((res) => {
const { storeGroupVOS = [], storeVOS = [] } = res.result; const { storeGroupVOS = [], storeVOS = [] } = res.result;
if (storeVOS.length < 1) {
message.warning('店铺不存在');
window.RCHistory.replace('/login');
return
}
const { id, storeUserId, storeName, userRole, storeType } = storeVOS[0]; const { id, storeUserId, storeName, userRole, storeType } = storeVOS[0];
User.setStoreId(id); User.setStoreId(id);
User.setStoreUserId(storeUserId); User.setStoreUserId(storeUserId);
User.setStoreName(storeName); User.setStoreName(storeName);
Bus.trigger('storeNameChange',storeName); Bus.trigger('storeNameChange', storeName);
User.setUserRole(userRole); User.setUserRole(userRole);
User.setStoreType(storeType); User.setStoreType(storeType);
ctx.dispatch(setStoreGroupList(storeGroupVOS)) ctx.dispatch(setStoreGroupList(storeGroupVOS))
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
@import '../../core/page.less'; @import '../../core/page.less';
@import '../../core/table.less'; @import '../../core/table.less';
@import '../../core/global.less'; @import '../../core/global.less';
@import '../../core/filter.less';
@top-height: 50px; @top-height: 50px;
......
/* .course-category-manage {
* @Author: yuananting
* @Date: 2021-02-23 19:41:42
* @LastEditors: yuananting
* @LastEditTime: 2021-03-24 17:16:43
* @Description: 助学工具-题库-题目分类管理样式
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
.question-category-manage {
position: relative; position: relative;
.search-condition { .search-condition {
width: 30%;
margin-bottom: 16px; margin-bottom: 16px;
.search-label { .search-label {
vertical-align: middle; vertical-align: middle;
...@@ -22,7 +13,7 @@ ...@@ -22,7 +13,7 @@
position: relative; position: relative;
margin-top: 16px; margin-top: 16px;
width: 900px; width: 900px;
border: 1px solid #E8E8E8; border: 1px solid #e8e8e8;
.ant-tree.ant-tree-directory { .ant-tree.ant-tree-directory {
font-size: 14px; font-size: 14px;
font-weight: 400; font-weight: 400;
...@@ -75,6 +66,6 @@ ...@@ -75,6 +66,6 @@
} }
.ant-tree.ant-tree-directory .ant-tree-treenode:hover::before { .ant-tree.ant-tree-directory .ant-tree-treenode:hover::before {
background-color: #F3F6FA; background-color: #f3f6fa;
} }
} }
...@@ -2,88 +2,56 @@ ...@@ -2,88 +2,56 @@
* @Author: yuananting * @Author: yuananting
* @Date: 2021-02-22 10:59:43 * @Date: 2021-02-22 10:59:43
* @LastEditors: yuananting * @LastEditors: yuananting
* @LastEditTime: 2021-03-24 14:50:08 * @LastEditTime: 2021-04-13 13:55:37
* @Description: 助学工具-题库-题库主页面侧边栏 * @Description: 助学工具-侧边课程分类树
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/ */
import React, { Component } from "react"; import React, { Component } from "react";
import { Input, Button, Tree } from "antd"; import { Input, Button, Tree } from "antd";
import "./QuestionBankSider.less"; import "./CourseCategorySiderTree.less";
import User from "@/common/js/user"; import User from "@/common/js/user";
import QuestionBankService from "@/domains/question-bank-domain/QuestionBankService"; import AidToolService from "@/domains/aid-tool-domain/AidToolService";
import Bus from "@/core/bus";
const { Search } = Input; const { Search } = Input;
const { DirectoryTree } = Tree; const { DirectoryTree } = Tree;
class QuestionBankSider extends Component { class CourseCategorySiderTree extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
const categoryId = getParameterByName("categoryId");
this.state = { this.state = {
selectedKeys: categoryId selectedKeys: ["QUESTION_INDEX", "PAPER_INDEX"].includes(props.fromModule)
? categoryId === "null" ? [getParameterByName("categoryId") || "null"]
? ["0"] : ["null"],
: [categoryId] treeData: props.treeData || [],
: ["0"],
searchValue: null,
NewEditQuestionBankCategory: null, //新增或编辑分类模态框
ImportCourseCategory: null, // 引用课程分类模态框
treeData: this.props.treeData || [],
autoExpandParent: false, autoExpandParent: false,
}; };
} }
componentDidMount() { componentDidMount() {
this.queryCategoryTree("change"); this.queryCategoryTree("init");
this.props.getSelectedCategoryId( Bus.bind("queryCategoryTree", this.queryCategoryTree);
getParameterByName("categoryId")
? [getParameterByName("categoryId")]
: ["0"]
);
} }
shouldComponentUpdate(nextProps, nextState) { componentWillUnmount() {
const { currentTotal, updatedCategoryId } = nextProps; Bus.unbind("queryCategoryTree", this.queryCategoryTree);
if (
this.props.currentTotal !== currentTotal &&
this.props.updatedCategoryId === updatedCategoryId
) {
this.queryCategoryTree("remain");
}
return true;
} }
/** 获取树状第一级key 设置默认展开第一项 */
getFirstLevelKeys = (data) => {
let firstLevelKeys = [];
data.forEach((item) => {
if (item.categoryLevel === 0) {
firstLevelKeys.push(item.key);
}
});
return firstLevelKeys;
};
/** 树状展开事件 */
onExpand = (expandedKeys) => {
this.setState({ expandedKeys });
};
/** 树状选中事件 */
onSelect = (selectedKeys) => {
this.setState({ selectedKeys });
this.props.getSelectedCategoryId(selectedKeys);
};
// 查询分类树 // 查询分类树
queryCategoryTree = (type, categoryName) => { queryCategoryTree = (type = "init", categoryName) => {
let query = { let query = {
source: 0, bizType: ["QUESTION_INDEX", "QUESTION_MODAL"].includes(
this.props.fromModule
)
? "QUESTION"
: "PAPER",
categoryName, categoryName,
count: true,
source: 0,
userId: User.getStoreUserId(), userId: User.getStoreUserId(),
tenantId: User.getStoreId(), tenantId: User.getStoreId(),
}; };
QuestionBankService.queryQuestionCategoryTree(query).then((res) => { AidToolService.queryCategoryTree(query).then((res) => {
const { categoryList = [], noCategoryCnt = 0 } = res.result; const { categoryList = [], noCategoryCnt = 0 } = res.result;
let str = "未分类"; let str = "未分类";
if (categoryName) { if (categoryName) {
...@@ -96,12 +64,12 @@ class QuestionBankSider extends Component { ...@@ -96,12 +64,12 @@ class QuestionBankSider extends Component {
Object.keys(this.state.treeMap).forEach((item) => { Object.keys(this.state.treeMap).forEach((item) => {
nodeId.push(item); nodeId.push(item);
}); });
if (type === "change") { if (type === "init") {
this.setState({ expandedKeys: nodeId }); this.setState({ expandedKeys: nodeId });
} }
} else { } else {
const defaultNode = { const defaultNode = {
id: "0", id: "null",
categoryName: "未分类", categoryName: "未分类",
categoryCount: noCategoryCnt, categoryCount: noCategoryCnt,
parentId: "0", parentId: "0",
...@@ -115,14 +83,14 @@ class QuestionBankSider extends Component { ...@@ -115,14 +83,14 @@ class QuestionBankSider extends Component {
Object.keys(this.state.treeMap).forEach((item) => { Object.keys(this.state.treeMap).forEach((item) => {
nodeId.push(item); nodeId.push(item);
}); });
if (type === "change") { if (type === "init") {
this.setState({ expandedKeys: nodeId }); this.setState({ expandedKeys: nodeId });
} }
} }
} else { } else {
this.setState({ autoExpandParent: false }); this.setState({ autoExpandParent: false });
const defaultNode = { const defaultNode = {
id: "0", id: "null",
categoryName: "未分类", categoryName: "未分类",
categoryCount: noCategoryCnt, categoryCount: noCategoryCnt,
parentId: "0", parentId: "0",
...@@ -132,13 +100,14 @@ class QuestionBankSider extends Component { ...@@ -132,13 +100,14 @@ class QuestionBankSider extends Component {
this.setState({ this.setState({
treeData: this.renderTreeNodes(categoryList, categoryName), treeData: this.renderTreeNodes(categoryList, categoryName),
}); });
if (type === "change") { if (type === "init") {
this.setState({ expandedKeys: [] }); this.setState({ expandedKeys: [] });
} }
} }
}); });
}; };
// 树结构平铺
getTreeMap = (data, map) => { getTreeMap = (data, map) => {
data.forEach((item) => { data.forEach((item) => {
map[item.id] = item; map[item.id] = item;
...@@ -149,6 +118,25 @@ class QuestionBankSider extends Component { ...@@ -149,6 +118,25 @@ class QuestionBankSider extends Component {
return map; return map;
}; };
// 树状展开事件
onExpand = (expandedKeys) => {
this.setState({ expandedKeys });
};
// 树状选中事件
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]);
} else {
Bus.trigger("queryPaperPageList", selectedKeys[0], 0);
}
});
};
// 树节点渲染-内容处理
renderTreeNodes = (data, value) => { renderTreeNodes = (data, value) => {
let newTreeData = data.map((item) => { let newTreeData = data.map((item) => {
item.title = item.categoryName; item.title = item.categoryName;
...@@ -166,13 +154,27 @@ class QuestionBankSider extends Component { ...@@ -166,13 +154,27 @@ class QuestionBankSider extends Component {
item.icon = item.icon =
item.categoryName === "未分类" ? ( item.categoryName === "未分类" ? (
<img <img
style={{ width: "24px", height: "24px", opacity: !value || (value && item.categoryName.indexOf(value) > -1) ? 1 : 0.5 }} style={{
width: "24px",
height: "24px",
opacity:
!value || (value && item.categoryName.indexOf(value) > -1)
? 1
: 0.5,
}}
src="https://image.xiaomaiketang.com/xm/defaultCategory.png" src="https://image.xiaomaiketang.com/xm/defaultCategory.png"
alt="" alt=""
/> />
) : ( ) : (
<img <img
style={{ width: "24px", height: "24px", opacity: !value || (value && item.categoryName.indexOf(value) > -1) ? 1 : 0.5 }} style={{
width: "24px",
height: "24px",
opacity:
!value || (value && item.categoryName.indexOf(value) > -1)
? 1
: 0.5,
}}
src="https://image.xiaomaiketang.com/xm/hasCategory.png" src="https://image.xiaomaiketang.com/xm/hasCategory.png"
alt="" alt=""
/> />
...@@ -194,30 +196,39 @@ class QuestionBankSider extends Component { ...@@ -194,30 +196,39 @@ class QuestionBankSider extends Component {
selectedKeys, selectedKeys,
autoExpandParent, autoExpandParent,
} = this.state; } = this.state;
return ( return (
<div className="question-bank-sider"> <div className="category-tree-sider">
<div className="sider-title">题目分类</div> {["QUESTION_INDEX", "PAPER_INDEX"].includes(this.props.fromModule) && (
<div className="sider-title">
{this.props.fromModule === "QUESTION_INDEX"
? "题目分类"
: "试卷分类"}
</div>
)}
<Search <Search
className="sider-search" className="sider-search"
placeholder="搜索名称分类" placeholder="搜索名称分类"
onSearch={(value) => { onSearch={(value) => {
this.queryCategoryTree("change", value); this.queryCategoryTree("init", value);
}} }}
enterButton={<span className="icon iconfont">&#xe832;</span>} enterButton={<span className="icon iconfont">&#xe832;</span>}
/> />
{User.getUserRole() !== "CloudLecturer" && ( {["QUESTION_INDEX", "PAPER_INDEX"].includes(this.props.fromModule) &&
<div className="sider-btn"> User.getUserRole() !== "CloudLecturer" &&
<Button this.props.type !== "modal-select" && (
onClick={() => { <div className="sider-btn">
window.RCHistory.push({ <Button
pathname: "/question-category-manage?from=aid", onClick={() => {
}); window.RCHistory.push({
}} pathname: "/course-category-manage?from=aid",
> });
分类管理 }}
</Button> >
</div> 分类管理
)} </Button>
</div>
)}
<div className="sider-tree"> <div className="sider-tree">
<DirectoryTree <DirectoryTree
expandedKeys={expandedKeys} expandedKeys={expandedKeys}
...@@ -229,11 +240,9 @@ class QuestionBankSider extends Component { ...@@ -229,11 +240,9 @@ class QuestionBankSider extends Component {
treeData={treeData} treeData={treeData}
/> />
</div> </div>
{this.state.NewEditQuestionBankCategory}
{this.state.ImportCourseCategory}
</div> </div>
); );
} }
} }
export default QuestionBankSider; export default CourseCategorySiderTree;
/* .category-tree-sider {
* @Author: yuananting
* @Date: 2021-02-22 12:02:34
* @LastEditors: yuananting
* @LastEditTime: 2021-03-24 15:57:12
* @Description: 助学工具-题库-题库主页面侧边栏样式
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
.question-bank-sider {
position: relative; position: relative;
.sider-title { .sider-title {
height: 22px; height: 22px;
...@@ -68,6 +60,6 @@ ...@@ -68,6 +60,6 @@
} }
.ant-tree.ant-tree-directory .ant-tree-treenode:hover::before { .ant-tree.ant-tree-directory .ant-tree-treenode:hover::before {
background-color: #F3F6FA; background-color: #f3f6fa;
} }
} }
...@@ -8,16 +8,6 @@ ...@@ -8,16 +8,6 @@
import React, { useState, useEffect, useRef } from "react"; import React, { useState, useEffect, useRef } from "react";
import "./XMAudio.less"; import "./XMAudio.less";
import VideoUpload from "@/core/upload"; import VideoUpload from "@/core/upload";
import { string } from "prop-types";
// interface XMAudioProps {
// style?: any;
// index?: any;
// size?: number | string;
// url?: any;
// forbidParse?:boolean;
// getDuration?: (value: number) => void;
// }
let timerInterval; let timerInterval;
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: 吴文洁 * @Author: 吴文洁
* @Date: 2020-03-18 10:01:28 * @Date: 2020-03-18 10:01:28
* @LastEditors: yuananting * @LastEditors: yuananting
* @LastEditTime: 2021-03-22 17:24:38 * @LastEditTime: 2021-03-27 14:44:31
* @Description: 录音组件 * @Description: 录音组件
*/ */
...@@ -11,7 +11,7 @@ import { Button, Modal } from "antd"; ...@@ -11,7 +11,7 @@ import { Button, Modal } from "antd";
import UploadOss from "@/core/upload"; import UploadOss from "@/core/upload";
import { RECORD_ERROR } from "@/common/constants/academic"; import { RECORD_ERROR } from "@/common/constants/academic";
import AudioRecorder from "./audioRecord"; import AudioRecorder from "../components/audioRecord";
import "./XMRecord.less"; import "./XMRecord.less";
......
/* /*
* @Author: chenjianyu * @Author: chenjianyu
* @Date: 2020-09-12 17:00:44 * @Date: 2020-09-12 17:00:44
* @LastEditTime: 2021-03-18 17:23:09 * @LastEditTime: 2021-03-27 14:02:17
* @LastEditors: sunbingqing * @LastEditors: yuananting
* @Description: 答题模式模板 * @Description: 答题模式模板
* @Copyright © 2020 杭州杰竞科技有限公司 版权所有 * @Copyright © 2020 杭州杰竞科技有限公司 版权所有
*/ */
......
.examPage{
padding-bottom: 62px;
.ant-alert-info{
background: rgba(255, 244, 221, 1);
border: none;
}
.ant-form-item{
&:last-child{
margin-bottom: 0px !important;
}
}
.form{
margin-top: 12px;
width: 1000px;
.title{
font-size: 16px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: bold;
color: #333333;
line-height: 22px;
margin-bottom: 8px;
}
}
.paperTitle{
background-color:rgba(247, 248, 249, 1) ;
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #333333;
line-height: 40px;
border: 2px;
margin: 8px 0;
padding-left: 12px;
img{
width: 20px;
height: 20px;
margin-right: 4px;
position: relative;
top: -2px;
}
}
.table{
border: 1px solid #e8e8e8;
width: 600px;
.header,.body-list{
background-color: #fafafa;
display: flex;
.item{
width: 16%;
box-sizing: border-box;
line-height: 32px;
text-align: center;
&.long{
width: 20%;
}
}
}
.body-list{
background-color: transparent;
}
}
.footer {
position: fixed;
bottom: 0;
height: 58px;
width: 100%;
display: flex;
align-items: center;
justify-content: flex-end;
padding-right: 252px;
background: #fff;
border-top: 1px solid #E8E8E8;
z-index: 9999;
.ant-btn {
margin-left: 10px;
}
}
}
\ No newline at end of file
import React, { useState, useRef, useEffect, useContext } from 'react'
import { Route, withRouter } from 'react-router-dom';
import Breadcrumbs from "@/components/Breadcrumbs";
import UserData from './UserData';
import ExamData from './ExamData'
import Service from "@/common/js/service";
import { Tabs } from 'antd';
import User from "@/common/js/user";
import './dataAnalysic.less'
const { TabPane } = Tabs;
function DataAnalysic(props: any) {
const examDetailInit: any = {};
const [selectKey, setSelectKey] = useState('user')
const [examDetail, setExamDetail] = useState(examDetailInit);
const { match } = props;
const examId =match.params.id;
useEffect(() => {
queryExamDetail();
}, [])
function queryExamDetail() {
Service.Hades("public/hades/queryExamDetail", {
examId:examId,
tenantId: User.getStoreId(),
userId: User.getStoreUserId(),
source: 0
}).then((res) => {
const { result } = res
setExamDetail(result)
})
}
return <div className="page dataAnalysic">
<Breadcrumbs navList={"考试数据"} goBack={props.history.goBack} />
<div className="box">
<div className="titleBox ">
<span className='tips'></span>
考试名称:{examDetail.examName}
</div>
</div>
<div className="box">
<Tabs activeKey={selectKey} onChange={(key: any) => {
setSelectKey(key)
}}>
<TabPane tab="考试人员数据" key="user">
<UserData examDetail ={examDetail } examId={examId} />
</TabPane>
<TabPane tab="题目数据" key="exam">
<ExamData examDetail ={examDetail } examId={examId}></ExamData>
</TabPane>
</Tabs>
</div>
</div>
}
export default withRouter(DataAnalysic);
\ No newline at end of file
import React, { useState, useRef, useEffect, useContext } from 'react'
import Service from "@/common/js/service";
import { PageControl } from "@/components";
import { Input, Select, Tooltip, Button, Table } from 'antd';
import User from "@/common/js/user";
import moment from 'moment';
import './userData.less'
const { Search } = Input;
const { Option } = Select;
interface sortType {
type: "ascend" | "descend" | null | undefined
}
function ExamData(props: any) {
const sortStatus: sortType = {
type: undefined
}
const examDataInit: any = {};
const queryInit: any = { current: 1, size: 10, order: 'SORT_ASC' };
const [examData, setUserData] = useState(examDataInit);
const [list, setList] = useState([]);
const [query, setQuery] = useState(queryInit);
const [total, setTotal] = useState(0);
const [field, setfield] = useState('');
const [allData, setAllData] = useState(0);
const [order, setOrder] = useState(sortStatus.type);
const questionTypeList = {
SINGLE_CHOICE: "单选题",
MULTI_CHOICE: "多选题",
JUDGE: "判断题",
GAP_FILLING: "填空题",
INDEFINITE_CHOICE: "不定项选择题",
};
const userTypeEnum = {
WORK_WE_CHAT: '企业微信',
WE_CHAT: '微信'
}
const userExamStateEnum = {
EXAM: '进行中',
LACK_EXAM: '缺考',
FINISH_EXAM: '已考试'
}
const orderEnum = {
currentAccuracy: {
ascend: 'ACCURACY_ASC',
descend: 'ACCURACY_DESC'
},
}
const queryRef = useRef({});
useEffect(() => {
queryExamUserData();
}, [])
useEffect(() => {
queryRef.current = query;
queryExamUserDataList();
}, [query])
function queryExamUserData() {
Service.Hades('public/hades/queryExamQuestionData', {
examId: props.examId,
tenantId: User.getStoreId(),
userId: User.getStoreUserId(),
source: 0
}).then((res) => {
setUserData(res.result)
})
}
function queryExamUserDataList() {
Service.Hades('public/hades/queryExamQuestionDataList', {
...query,
examId: props.examId,
tenantId: User.getStoreId(),
userId: User.getStoreUserId(),
source: 0
}).then((res) => {
setList(res.result.records);
setTotal(parseInt(res.result.total))
if (!allData) {
setAllData(parseInt(res.result.total))
}
})
}
const columns = [
{
title: "序号",
dataIndex: "sort",
width: 60,
render: (text: any) => <span>{text + 1}</span>,
},
{
title: "题目",
dataIndex: "questionStem",
ellipsis: true,
width: 350,
render: (val: any) => {
var handleVal = val;
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 }}
>
{handleVal}
</Tooltip>
);
},
},
{
title: "题型",
dataIndex: "questionType",
render: (text: any) => <span>{(questionTypeList as any)[text]}</span>,
filters: Object.keys(questionTypeList).map((key) => {
return {
text: (questionTypeList as any)[key],
value: key
}
}),
},
{
title: "本次正确率",
dataIndex: "currentAccuracy",
sorter: true,
sortOrder: field === "currentAccuracy" ? order : sortStatus.type,
render: (text: any) => <span>{parseInt(text * 100 as any)}%</span>,
},
{
title: <div>历史正确率 <Tooltip
overlayClassName="tool-list"
title='包含本次考试正确率'
placement="top"
overlayStyle={{ maxWidth: 700 }}
> <span style={{ color: 'rgba(191, 191, 191, 1)' }} className="icon iconfont">&#xe61d;</span>
</Tooltip>
</div>,
dataIndex: "totalAccuracy",
render: (text: any) => <span>{parseInt(text * 100 as any)}%</span>,
},
];
function onChange(pagination: any, filters: any, sorter: any, extra: any) {
console.log(filters, sorter);
setfield(sorter.field);
setOrder(sorter.order)
console.log(sorter.field, sorter.order, (orderEnum as any)[sorter.field])
let _query: any = { ...queryRef.current };
console.log(filters.questionType)
if (filters.questionType) {
console.log(233232)
_query.questionType = filters.questionType;
_query.current = 1;
} else {
delete _query.questionType
}
_query.order = (orderEnum as any)[sorter.field][sorter.order]
setQuery(_query)
}
function download() {
Service.Hades('public/hades/exportExamData', {
// ...query,
examId: props.examId,
exportDataType: 'EXAM_QUESTION_DATA',
tenantId: User.getStoreId(),
userId: User.getStoreUserId(),
source: 0
}).then((res) => {
const dom = (document as any).getElementById("load-play-back-excel")
dom.setAttribute('href', res.result);
dom.click();
})
}
return <div className="rr">
<a
target="_blank"
download
id="load-play-back-excel"
style={{ position: "absolute", left: "-10000px" }}
></a>
<div className="dataPanal">
{
!!examData.singleChoiceCnt && <div className="item">
<div className="num">{(examData.singleChoiceAccuracy || 0) * 100}%</div>
<div className="percent">正确率</div>
<div className="subTitle"><div className="type"><span className="icon iconfont">&#xe7fa;</span>单选题 <span>(共{examData.singleChoiceCnt}题)</span></div></div>
</div>
}
{
!!examData.multiChoiceCnt && <div className="item">
<div className="num">{(examData.multiChoiceAccuracy || 0) * 100}%</div>
<div className="percent">正确率</div>
<div className="subTitle"><div className="type"><span className="icon iconfont">&#xe7fb;</span>多选题<span>(共{examData.multiChoiceCnt}题)</span></div></div>
</div>
}
{
!!examData.judgeCnt && <div className="item">
<div className="num">{(examData.judgeAccuracy || 0) * 100}%</div>
<div className="percent">正确率</div>
<div className="subTitle"><div className="type"><span className="icon iconfont">&#xe7fc;</span>判断题<span>(共{examData.judgeCnt}题)</span></div></div>
</div>
}
{
!!examData.gapFillingCnt && <div className="item">
<div className="num">{(examData.gapFillingAccuracy || 0) * 100}%</div>
<div className="percent">正确率</div>
<div className="subTitle"><div className="type"><span className="icon iconfont">&#xe7fd;</span>填空题<span>(共{examData.gapFillingCnt}题)</span></div></div>
</div>
}
{
!!examData.indefiniteChoiceCnt && <div className="item">
<div className="num">{(examData.indefiniteChoiceAccuracy || 0) * 100}%</div>
<div className="percent">正确率</div>
<div className="subTitle"><div className="type"><span className="icon iconfont">&#xe7fe;</span>不定项选择题 <span>(共{examData.indefiniteChoiceCnt}题)</span></div></div>
</div>
}
</div>
{
!!allData && <Button style={{ marginBottom: 12, marginTop: 12 }} onClick={download} >导出</Button>
}
<div className="content">
<Table
bordered
size="small"
columns={columns}
dataSource={list}
onChange={onChange}
pagination={false}
>
</Table>
{total > 0 &&
<PageControl
size="small"
current={query.current - 1}
pageSize={query.size}
total={total}
toPage={(page: any) => {
console.log(page)
let _query: any = { ...queryRef.current };
_query.current = page + 1;
setQuery(_query)
}}
/>
}
</div>
</div>
}
export default ExamData;
\ No newline at end of file
import React from 'react';
import { Modal, Button, message } from 'antd';
import html2canvas from 'html2canvas';
import User from "../../../common/js/user";
import QRCode from '../../../libs/qrcode/qrcode';
import { LIVE_SHARE } from '../../../domains/course-domain/constants';
import Service from '../../../common/js/service';
import { copyText } from '../../../domains/basic-domain/utils';
import './ExamShareModal.less';
class ExamShareModal extends React.Component {
constructor(props) {
super(props);
this.state = {
shareUrl: '',
storeName: User.getStoreName()
}
}
componentDidMount() {
// 获取短链接
this.handleConvertShortUrl();
}
handleConvertShortUrl = () => {
const longUrl = `${LIVE_SHARE}test_detail/${this.props.data.examId}?id=${User.getStoreId()}`
console.log(longUrl)
// 发请求
Service.Sales('public/businessShow/convertShortUrls', {
urls: [longUrl]
}).then((res) => {
const { result = [] } = res;
this.setState({
shareUrl: result[0].shortUrl
}, () => {
const qrcodeWrapDom = document.querySelector('#qrcodeWrap');
const qrcodeNode = new QRCode({
text: this.state.shareUrl,
size: 98,
})
qrcodeWrapDom.appendChild(qrcodeNode);
});
})
}
// 下载海报
handleDownloadPoster = () => {
const { data } = this.props;
const dom = document.querySelector('#poster');
html2canvas(dom, {
useCORS: true,
}).then(canvas => {
const downloadDOM = document.createElement('a');
const { courseName } = this.props.data;
const dataUrl = canvas.toDataURL('image/png');
downloadDOM.href = dataUrl;
downloadDOM.download = `${data.examName}.png`;
downloadDOM.click();
});
}
// 复制分享链接
handleCopy = () => {
const textContent = document.getElementById('shareUrl').innerText;
copyText(textContent);
message.success('复制成功!');
}
render() {
const { data } = this.props;
const { shareUrl, storeName } = this.state;
return (
<Modal
title="分享考试"
width={680}
visible={true}
footer={null}
maskClosable={false}
className="ExamShareModal"
onCancel={this.props.close}
closeIcon={<span className="icon iconfont modal-close-icon">&#xe6ef;</span>}
>
<div className="left" id="poster">
<div
className="inst-name oneLineText"
>
{storeName}
</div>
<div style={{ color: '#333' }}>邀请你参与考试:</div>
<div className="examName">{data.examName}</div>
<img
src={'https://image.xiaomaiketang.com/xm/HQXwFsyf3e.png'}
className="course-cover"
alt="course-cover"
/>
<div className="qrcode-wrap">
<div className="qrcode-wrap__left">
<div className="text">长按识别二维码进入考试</div>
<img
className="finger"
alt="finger"
src="https://image.xiaomaiketang.com/xm/thpkWDwJsC.png"
/>
</div>
<div className="qrcode-wrap__right" id="qrcodeWrap">
</div>
</div>
</div>
<div className="right">
<div className="share-poster right__item">
<div className="title">① 海报分享</div>
<div className="sub-title">用户可通过微信扫描海报二维码,查看考试</div>
<div className="content" onClick={this.handleDownloadPoster}>下载海报</div>
</div>
{/* <div className="share-url right__item" style={{ marginTop: 40 }}>
<div className="title">② 链接分享</div>
<div className="sub-title">用户可通过微信或浏览器打开以下链接,查看考试(建议使用谷歌浏览器)</div>
<div className="content">
<div className="share-url" id="shareUrl">{shareUrl}</div>
<Button
type="primary"
onClick={this.handleCopy}
>复制</Button>
</div>
</div> */}
</div>
</Modal>
)
}
}
export default ExamShareModal;
.ExamShareModal{
.ant-modal-body {
display: flex;
.left {
width: 303px;
padding: 20px;
margin: 0 32px 0 16px;
box-shadow:0px 2px 10px 0px rgba(0,0,0,0.05);
border-radius: 12px;
.course-cover {
width: 263px;
height: 143px;
border-radius: 6px;
margin-top: 8px;
}
.examName{
font-size: 16px;
font-family: PingFangSC-Semibold, PingFang SC;
font-weight: 600;
color: #333333;
line-height: 22px;
max-height: 45px;
overflow: hidden;
// text-overflow: -o-ellipsis-lastline;
// overflow: hidden;
// text-overflow: ellipsis;
// display: -webkit-box;
// -webkit-line-clamp: 2;
// line-clamp: 2;
// -webkit-box-orient: vertical;
}
.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;
}
.finger {
width: 40px;
height: 40px;
margin-top: 8px;
}
}
&__right {
width: 110px;
height: 110px;
padding: 6px
}
}
.inst-name {
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #999999;
line-height: 20px;
.iconfont {
color: #999;
margin-right: 4px;
}
.text {
font-size: 12px;
color: #999;
}
}
}
.right {
.title {
color: #333;
font-weight: 500;
}
.sub-title {
color: #999;
margin-top: 16px;
}
.content {
display: flex;
align-items: center;
margin-top: 8px;
.share-url {
width: 212px;
overflow: hidden;
height: 29px;
line-height: 32px;
border-radius: 4px 0 0 4px;
padding-left: 12px;
white-space: nowrap;
color: #999999;
background: #EFEFEF;
}
.ant-btn {
margin-left: -2px;
}
}
.share-poster {
.content {
color: rgba(82, 137, 250, 1);
cursor: pointer;
}
}
}
}
}
\ No newline at end of file
.ExamPreviewModal{
// height: 880px;
.ant-modal-content .ant-modal-body{
padding: 0 24px !important;
max-height: 80vh !important;
}
.ExamPreview{
display: flex;
}
.left{
width: 460px;
.phone{
background:url(https://image.xiaomaiketang.com/xm/PpKc6zYKCG.png) ;
height:746px ;
background-size: 100% 100%;
padding-top: 1px;
.content{
width: 326px;
height: 520px;
background-color: #fff;
margin: 137px auto;
position: relative;
overflow: auto;
&::-webkit-scrollbar {
display: none;
}
.topContent{
width: 100%;
height: 198px;
background: url(https://image.xiaomaiketang.com/xm/bNHBZZfFzb.png);
background-size: 100% 100%;
padding-top: 1px;
position: relative;
.title{
width: 274px;
height: 60px;
font-size: 22px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #FFFFFF;
// line-height: 30px;
text-align: center;
margin: 20px auto 0;
word-break: break-all;
}
.time{
font-size: 11px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #FFFFFF;
line-height: 16px;
transform: scale(0.9);
margin-top: 12px;
text-align: center;
}
.rule{
width: 298px;
height: 113px;
background: #FFFFFF;
box-shadow: 0px -13px 9px 0px rgba(0, 34, 121, 0.1);
border-radius: 3px 3px 0px 0px;
position: absolute;
left: 14px;
top: 124px;
background: #fff;
display: flex;
.item{
width: 25%;
text-align: center;
.num{
margin-top: 28px;
font-size: 17px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #333333;
line-height: 24px;
}
.text{
font-size: 12px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #666666;
line-height: 16px;
transform: scale(0.9);
margin-top: 12px;
.dw{
transform: scale(0.8);
}
}
}
}
}
.fg{
margin-top: 60px;
text-align: center;
img{
width: 164px;
}
}
.examDesc{
width: 298px;
margin: 4px auto 0;
}
}
}
}
.right{
width: 353px;
.title{
font-size: 16px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #333333;
line-height: 22px;
text-align: center;
margin-bottom: 16px;
margin-top: 48px;
}
.rule{
background: #F4F6FA;
border-radius: 4px;
padding: 14px;
padding-bottom: 8px;
.item{
margin-bottom: 8px;
.name{
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #999999;
line-height: 14px;
width: 90px;
display: inline-block;
margin-right: 4px;
}
.text{
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #333333;
line-height: 20px;
}
}
}
}
}
\ No newline at end of file
import React, { useState, useRef, useEffect, useContext } from 'react'
import moment from 'moment';
import { Modal } from 'antd';
import './PreviewModal.less'
function PreviewModal(props: any) {
console.log(props.info)
const resultContentEnum = {
PASS_AND_SCORE: '显示考试分数和是否及格',
ONLY_SCORE: '仅显示考试分数',
ONLY_PASS: '仅显示是否及格'
}
const answerAnalysisEnum = {
ANALYSE_AND_RIGHT_OR_WRONG: '显示对错与解析',
RIGHT_OR_WRONG: '仅显示对错',
CAN_NOT_CHECK: '都不显示'
}
return <Modal
title="预览"
onCancel={props.onClose}
onOk={props.onClose}
maskClosable={true}
visible={true}
footer={null}
className='ExamPreviewModal'
closable={true}
width={800}
>
<div className="ExamPreview">
<div className="left">
<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>
{
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="text">总分 <span className="dw" style={{color:'#999'}}>(分)</span></div>
</div>
<div className="item">
<div className="num">{props.info.examTotal || 0}</div>
<div className="text">总题数<span className="dw" style={{color:'#999'}} >(道)</span></div>
</div>
<div className="item">
<div className="num">{props.info.passScore || 0}</div>
<div className="text">及格分<span className="dw" style={{color:'#999'}} >(分)</span></div>
</div>
<div className="item">
<div className="num">{props.info.examDuration || 60}</div>
<div className="text">时长<span className="dw" style={{color:'#999'}} >(分钟)</span></div>
</div>
</div>
</div>
<div className="fg">
<img src="https://image.xiaomaiketang.com/xm/8ASbb6TQ6Q.png" alt="" />
</div>
<div className="examDesc" style={{color:'#666'}} dangerouslySetInnerHTML={{ __html: props.info.examDesc }}></div>
</div>
</div>
</div>
<div className="right">
<div className="title">本次考试设置</div>
<div className="rule">
<div className="item">
<span className="name"> 身份证验证: </span>
<span className="text">{props.info.needPhone == 'NEED_PHONE_VERIFY' ? '需要验证手机号才能参加考试' : '仅需微信/企业微信授权登录验证'}</span>
</div>
<div className="item" style={{marginBottom:18}}>
<span className="name"> 选择乱序: </span>
<span className="text">{props.info.needOptionDisorder == 'OPTION_RANDOM' ? '选择题的选项随机排序' : '选择题按题目原有顺序展示'}</span>
</div>
<div className="item">
<span className="name"> 考试结果查看: </span>
<span className="text">{props.info.resultShow === 'IMMEDIATELY' ? '交卷后立即显示考试结果' : '到达考试截止日期才显示结果'}</span>
</div>
<div className="item">
<span className="name"> 考试结果内容: </span>
<span className="text">{(resultContentEnum as any)[props.info.resultContent]}</span>
</div>
<div className="item">
<span className="name"> 答案与解析: </span>
<span className="text">{(answerAnalysisEnum as any)[props.info.answerAnalysis]}</span>
</div>
</div>
</div>
</div>
</Modal>
}
export default PreviewModal
\ No newline at end of file
import React, { useState, useRef, useEffect, useContext } from 'react'
import { message, Modal } from 'antd';
import { withRouter } from 'react-router-dom';
import PaperContent from '../paper-manage/PaperContent'
import './AddExam.less';
import user from '@/common/js/user';
function SelectPaperModal(props: any) {
const [item, setItem] = useState(props.paperInfo);
const itemRef = useRef({})
useEffect(() => {
itemRef.current = item
console.log(item, 'khjkhjkhjk')
}, [item])
return <Modal
width={900}
title="选择试卷"
visible={true}
onOk={() => {
props.onSelect(itemRef.current);
props.close();
}
}
onCancel={() => { props.close() }}
>
<div style={{ maxHeight: 500 }}>
<PaperContent paperId={item.paperId} onSelect={(item: any) => { setItem(item) }} type='modal-select'></PaperContent>
</div>
</Modal >
}
export default withRouter(SelectPaperModal);
\ No newline at end of file
.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;
}
}
}
\ No newline at end of file
.examination-manager{
.status{
display: inline-block;
margin-left: 4px;
border: 1px solid #999;
padding: 2px 4px;
line-height: 16px;
}
}
\ No newline at end of file
.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;
top: 1px;
}
}
&: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;
}
}
\ No newline at end of file
...@@ -2,15 +2,15 @@ ...@@ -2,15 +2,15 @@
* @Author: yuananting * @Author: yuananting
* @Date: 2021-02-22 17:51:28 * @Date: 2021-02-22 17:51:28
* @LastEditors: yuananting * @LastEditors: yuananting
* @LastEditTime: 2021-03-24 15:02:53 * @LastEditTime: 2021-04-01 11:21:09
* @Description: 助学工具-题库-题库新建或编辑题库分类模态框 * @Description: 助学工具-新建编辑课程分类模态框
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/ */
import React, { Component } from "react"; import React, { Component } from "react";
import { Modal, Form, Input, message } from "antd"; import { Modal, Form, Input } from "antd";
import User from "@/common/js/user"; import User from "@/common/js/user";
import QuestionBankService from "@/domains/question-bank-domain/QuestionBankService"; import AidToolService from "@/domains/aid-tool-domain/AidToolService";
class NewEditQuestionBankCategory extends Component { class NewEditCourseCategoryModal extends Component {
formRef = React.createRef(); formRef = React.createRef();
constructor(props) { constructor(props) {
super(props); super(props);
...@@ -22,20 +22,21 @@ class NewEditQuestionBankCategory extends Component { ...@@ -22,20 +22,21 @@ class NewEditQuestionBankCategory extends Component {
} }
componentDidMount() { componentDidMount() {
// document.getElementById("categoryName").setAttribute("style", "autocomplete","off")
this.queryCategoryTree(); this.queryCategoryTree();
} }
// 查询分类树 // 查询分类树
queryCategoryTree = () => { queryCategoryTree = () => {
let query = { let query = {
bizType: "QUESTION",
count: false,
source: 0, source: 0,
userId: User.getStoreUserId(), userId: User.getStoreUserId(),
tenantId: User.getStoreId(), tenantId: User.getStoreId(),
}; };
QuestionBankService.queryCategoryTree(query).then((res) => { AidToolService.queryCategoryTree(query).then((res) => {
const { result = [] } = res; const { categoryList = [] } = res.result;
this.setState({ treeData: result }); this.setState({ treeData: categoryList });
}); });
}; };
...@@ -52,7 +53,7 @@ class NewEditQuestionBankCategory extends Component { ...@@ -52,7 +53,7 @@ class NewEditQuestionBankCategory extends Component {
//新增 //新增
params.categoryName = categoryName; params.categoryName = categoryName;
if (addLevelType === "equal") { if (addLevelType === "equal") {
params.parentId = node ? node.parentId : 0 params.parentId = node ? node.parentId : 0;
params.categoryLevel = node ? node.categoryLevel : 0; params.categoryLevel = node ? node.categoryLevel : 0;
} else { } else {
params.parentId = node.id; params.parentId = node.id;
...@@ -60,7 +61,7 @@ class NewEditQuestionBankCategory extends Component { ...@@ -60,7 +61,7 @@ class NewEditQuestionBankCategory extends Component {
} }
try { try {
await this.formRef.current.validateFields(); await this.formRef.current.validateFields();
QuestionBankService.addCategory(params).then((res) => { AidToolService.addCategory(params).then((res) => {
if (res.success) { if (res.success) {
this.props.close(); this.props.close();
} }
...@@ -76,7 +77,7 @@ class NewEditQuestionBankCategory extends Component { ...@@ -76,7 +77,7 @@ class NewEditQuestionBankCategory extends Component {
params.categoryName = categoryName; params.categoryName = categoryName;
try { try {
await this.formRef.current.validateFields(); await this.formRef.current.validateFields();
QuestionBankService.editCategory(params).then((res) => { AidToolService.editCategory(params).then((res) => {
if (res.success) { if (res.success) {
this.props.close(); this.props.close();
} }
...@@ -87,27 +88,48 @@ class NewEditQuestionBankCategory extends Component { ...@@ -87,27 +88,48 @@ class NewEditQuestionBankCategory extends Component {
} }
}; };
// 校验是否重名
checkExist = (sameLevelNodes, categoryName) => {
if (sameLevelNodes.length > 0 && sameLevelNodes[0].parentId === "0") {
if (categoryName === "未分类") {
return true;
}
}
var result = null;
sameLevelNodes.forEach((item) => {
if (result != null) {
return result;
}
if (item.categoryName === categoryName) {
result = item;
}
});
return result;
};
// 查询同级节点
getEqualLevelNodes = (data, parentId) => { getEqualLevelNodes = (data, parentId) => {
let nodes = []; let nodes = [];
data.forEach((item) => { data.forEach((item) => {
if (item.parentId === parentId) { if (item.parentId === parentId) {
nodes.push(item); nodes.push(item);
} }
if (item.children) { if (item.sonCategoryList) {
nodes.push(...this.getEqualLevelNodes(item.children, parentId)); nodes.push(...this.getEqualLevelNodes(item.sonCategoryList, parentId));
} }
}); });
return nodes; return nodes;
}; };
// 查询子级节点
getChildLevelNodes = (data, id) => { getChildLevelNodes = (data, id) => {
let nodes = []; let nodes = [];
data.forEach((item) => { data.forEach((item) => {
if (item.id === id && item.children) { if (item.id === id && item.sonCategoryList) {
nodes.push(...item.children); nodes.push(...item.sonCategoryList);
} }
if (item.children) { if (item.sonCategoryList) {
nodes.push(...this.getChildLevelNodes(item.children, id)); nodes.push(...this.getChildLevelNodes(item.sonCategoryList, id));
} }
}); });
return nodes; return nodes;
...@@ -124,28 +146,9 @@ class NewEditQuestionBankCategory extends Component { ...@@ -124,28 +146,9 @@ class NewEditQuestionBankCategory extends Component {
return sameLevelNodes; return sameLevelNodes;
}; };
// 查询是否重名
checkExist = (sameLevelNodes, categoryName) => {
if ((sameLevelNodes.length > 0 && sameLevelNodes[0].parentId === "0")) {
if (categoryName === "未分类") {
return true;
}
}
var result = null;
sameLevelNodes.forEach((item) => {
if (result != null) {
return result;
}
if (item.categoryName === categoryName) {
result = item;
}
});
return result;
};
render() { render() {
const { title, label, treeData, addLevelType } = this.props; const { title, label, addLevelType } = this.props;
const { categoryName } = this.state; const { categoryName, treeData } = this.state;
const _that = this; const _that = this;
return ( return (
<Modal <Modal
...@@ -183,7 +186,7 @@ class NewEditQuestionBankCategory extends Component { ...@@ -183,7 +186,7 @@ class NewEditQuestionBankCategory extends Component {
defaultValue={categoryName} defaultValue={categoryName}
placeholder={`请输入${title},最多10个字`} placeholder={`请输入${title},最多10个字`}
maxLength={10} maxLength={10}
autoComplete="off" autoComplete="off"
onChange={(e) => { onChange={(e) => {
this.setState({ this.setState({
categoryName: e.target.value, categoryName: e.target.value,
...@@ -196,4 +199,4 @@ class NewEditQuestionBankCategory extends Component { ...@@ -196,4 +199,4 @@ class NewEditQuestionBankCategory extends Component {
); );
} }
} }
export default NewEditQuestionBankCategory; export default NewEditCourseCategoryModal;
/*
* @Author: yuananting
* @Date: 2021-03-27 14:55:14
* @LastEditors: yuananting
* @LastEditTime: 2021-04-01 14:00:47
* @Description: 助学工具-试卷
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import React, { Component } from "react";
import PaperContent from "./PaperContent";
class PaperIndex extends Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
return (
<div className="paper-manage-index page">
<div className="content-header">试卷</div>
<div className="box content-body">
<PaperContent type=''></PaperContent>
</div>
</div>
);
}
}
export default PaperIndex;
.operate-paper-page {
.box {
margin-bottom: 66px !important;
.table-style {
border: 1px solid #f0f0f0 !important;
}
.ant-tabs {
color: #666666;
}
.score-info {
color: #999999;
margin-left: 12px;
}
.choose-btn {
margin-top: 8px;
margin-bottom: 12px;
}
.paper-info-tip {
height: 20px;
color: #999999;
line-height: 20px;
span {
color: #ffb714;
}
}
.record-operate {
display: flex;
&__item {
color: #5289fa;
cursor: pointer;
&.split {
margin: 0 8px;
color: #bfbfbf;
}
}
&__ban {
color: #cccccc;
pointer-events: none;
}
}
}
.footer {
position: fixed;
bottom: 0;
height: 58px;
width: 100%;
display: flex;
align-items: center;
justify-content: flex-end;
padding-right: 252px;
background: #fff;
border-top: 1px solid #e8e8e8;
z-index: 999;
.ant-btn {
margin-left: 10px;
}
}
}
.aid-tool-list {
.ant-tooltip-inner {
max-width: 700px !important;
}
}
.ant-dropdown-menu-item-selected > span {
color: #333333;
}
\ No newline at end of file
/*
* @Author: yuananting
* @Date: 2021-03-27 14:55:14
* @LastEditors: yuananting
* @LastEditTime: 2021-04-07 10:25:44
* @Description: 助学工具-试卷主页面
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import React, { Component } from "react";
import "./PaperContent.less";
import CourseCategorySiderTree from "../components/CourseCategorySiderTree";
import PaperList from "./components/PaperList";
class PaperContent extends Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
return (
<div className={this.props.type == "modal-select"? "paper-content-page paper-content-modal":"paper-content-page"} >
<div
style={{ borderRight: "0.5px solid #EEEEEE", paddingRight: "4px" }}
>
<div className="sider" >
<CourseCategorySiderTree
type={this.props.type}
fromModule="PAPER_INDEX"
/>
</div>
</div>
<div className="content" >
<PaperList
type={this.props.type}
paperId={this.props.paperId}
onSelect={this.props.onSelect}
/>
</div>
</div>
);
}
}
export default PaperContent;
.paper-content-page {
display: flex;
&.paper-content-modal{
max-height: 500px;
.sider,.content{
max-height: 100%;
overflow: auto;
}
.content{
height: auto;
overflow: auto;
}
}
.sider {
min-width: 244px;
}
.content {
width: 100%;
margin-left: 24px;
height: calc(100vh - 160px);
}
}
\ No newline at end of file
.paper-list {
.ant-radio-wrapper{
left: -10px;
}
.paper-list-filter {
position: relative;
.search-condition {
width: calc(100% - 80px);
display: flex;
align-items: center;
flex-wrap: wrap;
&__item {
margin-bottom: 16px;
.search-label {
vertical-align: middle;
display: inline-block;
height: 32px;
line-height: 32px;
}
}
}
.reset-fold-area {
position: absolute;
right: 12px;
.resetBtn {
color: #999999;
font-size: 18px;
margin-right: 8px;
}
.fold-btn {
font-size: 14px;
color: #666666;
line-height: 20px;
.fold-icon {
font-size: 12px;
margin-left: 4px;
}
}
}
}
.data-icon {
cursor: pointer;
}
.paper-list-content {
position: relative;
margin-top: 16px;
.empty-list-tip {
color: #ffb714;
cursor: pointer;
}
.record-name {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.record-operate {
display: flex;
&__item {
color: #5289fa;
cursor: pointer;
&.split {
margin: 0 8px;
color: #bfbfbf;
}
}
}
}
&.modal-select{
.search-condition {
width: calc(100% - 80px);
display: flex;
align-items: center;
flex-wrap: wrap;
&__item {
width: auto;
}
}
}
}
.tool-list {
.ant-tooltip-inner {
max-width: 700px !important;
}
}
.fill-line {
padding: 0 10px;
border-bottom: 1px solid;
}
.select-question-list {
.select-question-filter {
position: relative;
.search-condition {
width: calc(100% - 80px);
display: flex;
align-items: center;
flex-wrap: wrap;
&__item {
margin-right: 3%;
margin-bottom: 16px;
.search-label {
vertical-align: middle;
display: inline-block;
height: 32px;
line-height: 32px;
}
}
}
.reset-fold-area {
position: absolute;
right: 12px;
.resetBtn {
color: #999999;
font-size: 18px;
margin-right: 8px;
}
.fold-btn {
font-size: 14px;
color: #666666;
line-height: 20px;
.fold-icon {
font-size: 12px;
margin-left: 4px;
}
}
}
}
.data-icon {
cursor: pointer;
}
.select-question-content {
position: relative;
margin-top: 16px;
.empty-list-tip {
color: #ffb714;
cursor: pointer;
}
.record-name {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.record-operate {
display: flex;
&__item {
color: #5289fa;
cursor: pointer;
&.split {
margin: 0 8px;
color: #bfbfbf;
}
}
}
}
.select-tip-box {
background: #fff4dd;
border-radius: 4px;
padding: 6px 16px;
display: flex;
justify-content: space-between;
.tip-icon {
color: #ff9d14;
font-size: 14px;
margin-right: 4px;
}
.select-num {
color: #666666;
font-size: 14px;
}
.clear-btn {
color: #5289fa;
font-size: 14px;
cursor: pointer;
}
}
}
.tool-list {
.ant-tooltip-inner {
max-width: 700px !important;
}
}
/*
* @Author: yuananting
* @Date: 2021-03-27 11:15:03
* @LastEditors: yuananting
* @LastEditTime: 2021-04-15 13:22:10
* @Description: 助学工具-试卷-预览试卷
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import React, { Component } from "react";
import { Modal, ConfigProvider, Empty } from "antd";
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";
const questionTypeList = {
SINGLE_CHOICE: "单选题",
MULTI_CHOICE: "多选题",
JUDGE: "判断题",
GAP_FILLING: "填空题",
INDEFINITE_CHOICE: "不定项选择题",
};
class PreviewPaperModal extends Component {
formRef = React.createRef();
constructor(props) {
super(props);
this.state = {
paperInfo: {},
};
}
componentDidMount() {
const { previewPage, paperInfo } = this.props;
if (previewPage === "paper-list") {
this.queryPaperDetail();
} else if (previewPage === "paper-operate") {
this.setState({ paperInfo });
}
}
// 题目预览
queryPaperDetail = () => {
let query = {
categoryId: this.props.categoryId,
paperId: this.props.paperId,
source: 0,
userId: User.getStoreUserId(),
tenantId: User.getStoreId(),
};
AidToolService.viewPaper(query).then((res) => {
const { result = [] } = res;
this.setState({ paperInfo: result });
});
};
// 查看图片
handleScanFile = (scanFileType, scanFileAddress) => {
this.setState({
showScanFile: true,
scanFileAddress,
scanFileType,
});
};
renderStem = (questionStemList, questionType, score, questionIndex) => {
const textContent = _.filter(questionStemList, (item) => {
return item.type == "RICH_TEXT";
});
const mediaContent = _.filter(questionStemList, (item) => {
return item.type !== "RICH_TEXT";
});
let content = "";
if (textContent.length > 0) {
content = textContent[0].content;
if (questionType === "GAP_FILLING") {
content = content.replace(
/_/g,
`<input
class="add-fill-line"
disabled
correctAnswerList=""
id=${window.random_string(16)}
value=" "
/>`
);
content = content.replace(/value="填空"/g, "value=' '");
}
}
let textDom = (
<div
key={0}
className="input-box"
dangerouslySetInnerHTML={{
__html: content,
}}
/>
);
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">
({questionTypeList[questionType]} | {score}分)
</span>
</div>
{textDom}
</div>
{this.renderMediaContent(mediaContent)}
</div>
);
};
renderOption = (optionItem, questionType) => {
const { questionOptionContentList, optionSort } = optionItem;
const textContent = _.filter(questionOptionContentList, (item) => {
return item.type == "RICH_TEXT";
});
const mediaContent = _.filter(questionOptionContentList, (item) => {
return item.type !== "RICH_TEXT";
});
let content = textContent.length > 0 && textContent[0].content;
if (questionType !== "GAP_FILLING") {
let textDom = (
<span
key={0}
className="input-box"
dangerouslySetInnerHTML={{
__html: content,
}}
/>
);
return (
<div className="option-line-item">
<div className="text">
{NUM_TO_WORD_MAP[optionSort]}: {textDom}
</div>
{mediaContent.length > 0 && this.renderMediaContent(mediaContent)}
</div>
);
}
};
renderAnswer = (optionList, gapFillingAnswerList, questionType) => {
if (questionType === "GAP_FILLING") {
{
return (
<div className="answer-line-item">
<div style={{ marginBottom: 8 }}>正确答案: </div>
{_.map(gapFillingAnswerList, (gapItem, gapIndex) => {
const { correctAnswerList } = gapItem;
return (
<div className="gap-list">
<span>[填空{gapIndex + 1}] </span>
{_.map(correctAnswerList, (answerItem, answerIndex) => {
return (
<span>
{answerItem}
{answerIndex < correctAnswerList.length - 1 && (
<span></span>
)}
</span>
);
})}
<span>; </span>
</div>
);
})}
</div>
);
}
} else {
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 style={{ marginBottom: 8 }}>正确答案: </div>
<span style={{ lineHeight: "20px", color: "#666666" }}>
{correctOptionSort.length > 0 && correctOptionSort.join("、")}
</span>
</div>
);
}
};
renderMediaContent = (mediaContent) => {
return (
<div className="media">
{_.map(mediaContent, (mediaItem, mediaIndex) => {
let dom = "";
let { type, content, size } = mediaItem;
switch (type) {
case "PICTURE":
dom = (
<div key={mediaIndex + 1} className="picture-box">
<img
src={content}
onClick={() => this.handleScanFile("JPG", content)}
/>
</div>
);
break;
case "VOICE":
dom = (
<div key={mediaIndex + 1} className="voice-box">
<XMAudio
forbidParse
url={content}
getDuration={(durationSize) => {
size = durationSize;
this.setState({});
}}
index={mediaIndex + 1}
size={size || 1000}
/>
</div>
);
break;
case "AUDIO":
dom = (
<div key={mediaIndex} className="voice-box">
<XMAudio
forbidParse
url={content}
getDuration={(durationSize) => {
size = durationSize;
this.setState({});
}}
index={mediaIndex}
size={size || 1000}
/>
</div>
);
break;
}
return dom;
})}
</div>
);
};
// 自定义空状态
customizeRenderEmpty = () => {
return (
<Empty
image="https://image.xiaomaiketang.com/xm/emptyTable.png"
imageStyle={{
height: 100,
}}
description={"暂无内容"}
></Empty>
);
};
render() {
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}</div>}
{questionList && questionList.length > 0 ? (
<div className="question-list-box">
{_.map(questionList, (questionItem, questionIndex) => {
const {
questionStemList,
optionList,
gapFillingAnswerList,
questionType,
score,
} = questionItem;
return (
<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
)}
</div>
);
})}
</div>
) : (
this.customizeRenderEmpty()
)}
</Modal>
{showScanFile && (
<ScanFileModal
fileType={scanFileType}
item={{
ossAddress: scanFileAddress,
}}
close={() => {
this.setState({ showScanFile: false });
}}
/>
)}
</div>
);
}
}
export default PreviewPaperModal;
.paper-preview-modal {
.paper-title {
width: 400px;
font-size: 19px;
font-weight: 500;
color: #333333;
line-height: 26px;
margin: 0 auto 24px;
text-align: center;
}
.question-list-box {
.question-info-item {
margin-bottom: 24px;
padding-bottom: 24px;
border-bottom: 1px solid #e8e8e8;
.stem-line-item {
color: #666666;
margin-bottom: 20px;
.question-sort {
font-size: 16px;
font-weight: 500;
color: #333333;
margin-right: 4px;
}
.question-type-score {
color: #999999;
}
}
.option-line-item {
color: #666666;
margin-top: 12px;
line-height: 20px;
}
.answer-line-item {
color: #333333;
line-height: 20px;
margin-top: 20px;
.gap-list {
display: inline;
color: #666666;
line-height: 20px;
}
}
}
.question-info-item:last-child {
border-bottom: none;
}
.text {
margin-bottom: 8px;
color: #666666;
.question-tip {
margin-bottom: 8px;
}
.input-box {
line-height: 20px;
* {
display: inline;
}
.add-fill-line {
padding: 0 10px;
border-bottom: 1px solid !important;
margin: 0 4px;
text-align: center;
border: none;
width: 54px;
}
}
}
.media {
.picture-box {
width: 88px;
height: 88px;
border-radius: 4px;
overflow: hidden;
align-items: center;
justify-content: center;
margin-right: 12px;
margin-top: 8px;
position: relative;
display: inline-flex;
border: 1px solid #e8e8e8;
img {
max-width: 100%;
max-height: 100%;
border-radius: 4px;
vertical-align: middle;
width: auto;
height: auto;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
}
.voice-box {
margin-bottom: 12px;
box-shadow: 0px 2px 6px 0px rgba(0, 0, 0, 0.1);
padding: 10px 20px;
width: 320px;
}
}
}
}
.paper-preview-modal.ant-modal {
max-height: 60% !important;
}
.paper-preview-modal.ant-modal .ant-modal-content .ant-modal-body {
min-height: 145px !important;
}
/*
* @Author: yuananting
* @Date: 2021-03-29 10:52:26
* @LastEditors: yuananting
* @LastEditTime: 2021-04-07 15:23:06
* @Description: 助学工具-试卷-新建选择题目弹窗
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import React, { Component } from "react";
import { Modal } from "antd";
import CourseCategorySiderTree from "../../components/CourseCategorySiderTree";
import SelectQuestionList from "../components/SelectQuestionList";
import "./SelectQuestionModal.less";
class SelectQuestionModal extends Component {
listRef = React.createRef();
constructor(props) {
super(props);
this.state = {
selectedCategoryId: null,
};
}
componentDidMount() {
this.listRef.current.state.selectQuestionKeys = this.props.getSelectedQuestion.map(
(item) => {
item.id = item.questionId;
item.questionTypeEnum = item.questionType;
return item;
}
);
}
render() {
return (
<Modal
className="select-question-modal"
destroyOnClose={true}
title="选择题目"
visible={true}
width={1080}
onOk={() => {
this.props.setSelectedQuestion(
this.listRef.current.state.selectQuestionKeys.map((item) => {
item.questionId = item.id || item.questionId;
item.questionType = item.questionTypeEnum || item.questionType;
item.score = item.score || 2;
if (
["MULTI_CHOICE", "GAP_FILLING", "INDEFINITE_CHOICE"].includes(
item.questionTypeEnum
)
) {
item.portionScore = item.portionScore || 0;
}
return item;
})
);
}}
onCancel={this.props.close}
>
<div className="box content-body" style={{maxHeight:500}}>
<div
style={{ borderRight: "0.5px solid #EEEEEE", paddingRight: "4px",overflowY:'auto',overflowX:'hidden'}}
>
<div className="sider">
<CourseCategorySiderTree fromModule="QUESTION_MODAL" />
</div>
</div>
<div className="content" style={{height:'auto',overflowY:'auto'}}>
<SelectQuestionList ref={this.listRef} />
</div>
</div>
</Modal>
);
}
}
export default SelectQuestionModal;
.select-question-modal {
.content-body {
display: flex;
height: calc(~'100% - 48px');
.sider {
min-width: 244px;
}
.content {
width: 100%;
margin-left: 24px;
height: calc(100vh - 160px);
}
}
.ant-table-column-sorters {
padding: 0;
}
}
.select-question-modal.ant-modal {
max-height: 70% !important;
}
\ No newline at end of file
...@@ -2,56 +2,35 @@ ...@@ -2,56 +2,35 @@
* @Author: yuananting * @Author: yuananting
* @Date: 2021-02-21 17:51:01 * @Date: 2021-02-21 17:51:01
* @LastEditors: yuananting * @LastEditors: yuananting
* @LastEditTime: 2021-03-24 13:55:56 * @LastEditTime: 2021-04-07 10:45:07
* @Description: 助学工具-题库-题库主页面 * @Description: 助学工具-题库
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/ */
import React, { Component } from "react"; import React, { Component } from "react";
import "./QuestionBankIndex.less"; import "./Index.less";
import QuestionBankSider from "./components/QuestionBankSider"; import CourseCategorySiderTree from "../components/CourseCategorySiderTree";
import QuestionManageContent from "./components/QuestionManageContent"; import QuestionList from "./components/QuestionList";
class QuestionBankIndex extends Component { class QuestionIndex extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {};
selectedCategoryId: "",
};
} }
componentDidMount() {}
getCategoryIdFromSider = (selectedCategoryId) => {
if (selectedCategoryId && selectedCategoryId.length > 0) {
this.setState({ selectedCategoryId: selectedCategoryId[0] });
}
};
updatedSiderTreeFromList = (currentTotal, updatedCategoryId) => {
this.setState({ currentTotal });
this.setState({ updatedCategoryId });
};
render() { render() {
return ( return (
<div className="question-bank-index page"> <div className="question-manage-index page">
<div className="content-header">题目</div> <div className="content-header">题目</div>
<div className="box content-body"> <div className="box content-body">
<div style={{borderRight: "0.5px solid #EEEEEE", paddingRight: "4px"}}> <div
style={{ borderRight: "0.5px solid #EEEEEE", paddingRight: "4px" }}
>
<div className="sider"> <div className="sider">
<QuestionBankSider <CourseCategorySiderTree fromModule="QUESTION_INDEX" />
getSelectedCategoryId={this.getCategoryIdFromSider.bind(this)}
currentTotal={this.state.currentTotal}
updatedCategoryId={this.state.updatedCategoryId}
/>
</div> </div>
</div> </div>
<div className="content"> <div className="content">
<QuestionManageContent <QuestionList />
updatedSiderTree={this.updatedSiderTreeFromList.bind(this)}
selectedCategoryId={this.state.selectedCategoryId}
/>
</div> </div>
</div> </div>
</div> </div>
...@@ -59,4 +38,4 @@ class QuestionBankIndex extends Component { ...@@ -59,4 +38,4 @@ class QuestionBankIndex extends Component {
} }
} }
export default QuestionBankIndex; export default QuestionIndex;
/* .question-manage-index {
* @Author: yuananting
* @Date: 2021-02-21 18:27:43
* @LastEditors: yuananting
* @LastEditTime: 2021-03-24 16:15:03
* @Description: 助学工具-题库-题库主页面样式
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
.question-bank-index {
.content-body { .content-body {
display: flex; display: flex;
.site-layout-background {
background: #fff;
}
.sider { .sider {
min-width: 244px; min-width: 244px;
} }
......
/* .operate-question-page {
* @Author: yuananting
* @Date: 2021-02-25 13:52:01
* @LastEditors: yuananting
* @LastEditTime: 2021-03-18 09:32:11
* @Description: 助学工具-题库-题目管理-新增题目样式
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
.add-new-question {
position: relative !important;
.box { .box {
margin-bottom: 66px !important; margin-bottom: 66px !important;
.ant-tabs { .ant-tabs {
......
...@@ -175,12 +175,6 @@ ...@@ -175,12 +175,6 @@
margin-right: 187px; margin-right: 187px;
} }
// .question-item_options {
// display: flex;
// align-items: center;
// padding-bottom: 15px;
// }
.question-item_options__list { .question-item_options__list {
flex: 1; flex: 1;
position: relative; position: relative;
...@@ -440,38 +434,3 @@ ...@@ -440,38 +434,3 @@
} }
} }
} }
.question_skeleton {
background: linear-gradient(90deg, #f2f2f2 25%, #e6e6e6 37%, #f2f2f2 63%);
background-size: 400% 100%;
animation: question-editor_skeleton__loading 1.4s ease infinite;
}
.question_skeleton__editor {
min-height: 33px;
max-height: 140px;
overflow: hidden;
}
.question_skeleton__img {
width: 88px;
height: 88px;
}
.question_skeleton__voice {
height: 48px;
width: 280px;
}
.question_skeleton__video {
width: 100%;
height: 100%;
}
@keyframes question-editor_skeleton__loading {
0% {
background-position: 100% 50%;
}
100% {
background-position: 0 50%;
}
}
import React, { Component } from "react"; import React, { Component } from "react";
import E from "wangeditor"; import E from "wangeditor";
import { message, Button } from "antd"; import { message } from "antd";
import UploadOss from "@/core/upload"; import UploadOss from "@/core/upload";
import "./QuestionEditor.less"; import "./QuestionEditor.less";
const MEDIA_MAP = [ const MEDIA_MAP = [
......
/* .question-list {
* @Author: yuananting .question-list-filter {
* @Date: 2021-02-25 11:26:28
* @LastEditors: yuananting
* @LastEditTime: 2021-03-25 14:32:01
* @Description: 助学工具-题库-题目管理右侧内容样式
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
.question-manage-content {
.question-manage-filter {
position: relative; position: relative;
.search-condition { .search-condition {
width: calc(100% - 80px); width: calc(100% - 80px);
...@@ -16,7 +8,6 @@ ...@@ -16,7 +8,6 @@
flex-wrap: wrap; flex-wrap: wrap;
&__item { &__item {
width: 30%;
margin-right: 3%; margin-right: 3%;
margin-bottom: 16px; margin-bottom: 16px;
.search-label { .search-label {
...@@ -49,7 +40,7 @@ ...@@ -49,7 +40,7 @@
.data-icon { .data-icon {
cursor: pointer; cursor: pointer;
} }
.question-manage-list { .question-list-content {
position: relative; position: relative;
margin-top: 16px; margin-top: 16px;
.empty-list-tip { .empty-list-tip {
...@@ -76,13 +67,8 @@ ...@@ -76,13 +67,8 @@
} }
} }
} }
.tool-list { .aid-tool-list {
.ant-tooltip-inner { .ant-tooltip-inner {
max-width: 700px !important; max-width: 700px !important;
} }
} }
.fill-line {
padding: 0 10px;
border-bottom: 1px solid;
}
/* /*
* @Author: zhangyi * @Author: yuananting
* @Date: 2019-12-09 10:29:55 * @Date: 2021-03-27 11:15:03
* @Last Modified by: mikey.wanghaofeng * @LastEditors: yuananting
* @Last Modified time: 2020-09-25 11:03:47 * @LastEditTime: 2021-03-29 16:22:28
* @Description: 助学工具-题库-批量导入题目
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/ */
import React, { Component } from "react"; import React, { Component } from "react";
import { Modal, Button, Upload, message, Spin, Progress } from "antd"; import { Modal, Button, message, Spin } from "antd";
import "./BatchImportQuestionModal.less"; import "./BatchImportQuestionModal.less";
import SelectPrepareFileModal from "@/modules/prepare-lesson/modal/SelectPrepareFileModal"; import SelectPrepareFileModal from "@/modules/prepare-lesson/modal/SelectPrepareFileModal";
import User from "@/common/js/user"; import User from "@/common/js/user";
import QuestionBankService from "@/domains/question-bank-domain/QuestionBankService"; import AidToolService from "@/domains/aid-tool-domain/AidToolService";
import { LoadingOutlined } from "@ant-design/icons"; import { LoadingOutlined } from "@ant-design/icons";
class BatchImportQuestionModal extends Component { class BatchImportQuestionModal extends Component {
constructor(props) { constructor(props) {
...@@ -65,7 +66,7 @@ class BatchImportQuestionModal extends Component { ...@@ -65,7 +66,7 @@ class BatchImportQuestionModal extends Component {
tenantId: User.getStoreId(), tenantId: User.getStoreId(),
userId: User.getStoreUserId(), userId: User.getStoreUserId(),
}; };
const res = await QuestionBankService.batchImport(params); const res = await AidToolService.batchImport(params);
const { result } = res; const { result } = res;
const { bizSuccess, bizMessage } = result; const { bizSuccess, bizMessage } = result;
if (res) { if (res) {
...@@ -222,9 +223,11 @@ class BatchImportQuestionModal extends Component { ...@@ -222,9 +223,11 @@ class BatchImportQuestionModal extends Component {
type="primary" type="primary"
className="down-btn" className="down-btn"
onClick={() => { onClick={() => {
this.setState({ status: "init" }); this.setState({
this.setState({ uploadFile: null }); status: "init",
this.setState({ showSelectFileModal: true }); uploadFile: null,
showSelectFileModal: true,
});
}} }}
> >
重新上传文件 重新上传文件
......
@import '../../../core/mixins.less'; @import "@/core/mixins.less";
.import-score-modal { .import-score-modal {
.step-section { .step-section {
margin-bottom: 24px; margin-bottom: 24px;
...@@ -49,7 +48,7 @@ ...@@ -49,7 +48,7 @@
} }
} }
.file-box :hover { .file-box :hover {
background-color: #FFF8E8; background-color: #fff8e8;
.del-img { .del-img {
visibility: visible !important; visibility: visible !important;
} }
...@@ -64,7 +63,7 @@ ...@@ -64,7 +63,7 @@
} }
.down-btn { .down-btn {
text-align: left; text-align: left;
color: #5289FA; color: #5289fa;
font-size: 12px; font-size: 12px;
display: block; display: block;
margin-top: 8px; margin-top: 8px;
...@@ -74,18 +73,18 @@ ...@@ -74,18 +73,18 @@
width: 200px; width: 200px;
.ant-upload-list-item-name { .ant-upload-list-item-name {
.text-overflow-ellipsis(); .text-overflow-ellipsis();
width:70%; width: 70%;
} }
} }
} }
.import-status-box { .import-status-box {
height:430px; height: 430px;
overflow: hidden; overflow: hidden;
.status-content { .status-content {
margin:auto; margin: auto;
text-align: center; text-align: center;
margin-top:100px; margin-top: 100px;
>img { > img {
width: 76px; width: 76px;
} }
.status { .status {
...@@ -98,9 +97,9 @@ ...@@ -98,9 +97,9 @@
color: #666666; color: #666666;
margin-bottom: 16px; margin-bottom: 16px;
.num { .num {
color: #FC9C6B; color: #fc9c6b;
} }
} }
} }
} }
} }
\ No newline at end of file
/*
* @Author: yuananting
* @Date: 2021-03-27 11:15:03
* @LastEditors: yuananting
* @LastEditTime: 2021-04-01 19:47:12
* @Description: 助学工具-题库-预览题目
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import React, { Component } from "react"; import React, { Component } from "react";
import { Modal, Divider } from "antd"; import { Modal } from "antd";
import User from "@/common/js/user"; import User from "@/common/js/user";
import QuestionBankService from "@/domains/question-bank-domain/QuestionBankService"; import AidToolService from "@/domains/aid-tool-domain/AidToolService";
import "./QuestionPreviewModal.less"; import "./PreviewQuestionModal.less";
import ScanFileModal from "@/modules/resource-disk/modal/ScanFileModal"; import ScanFileModal from "@/modules/resource-disk/modal/ScanFileModal";
import _ from "underscore"; import _ from "underscore";
import XMAudio from "../components/XMAudio"; import XMAudio from "../../components/XMAudio";
import { NUM_TO_WORD_MAP } from "@/common/constants/punchClock/punchClock"; import { NUM_TO_WORD_MAP } from "@/common/constants/punchClock/punchClock";
const questionTypeList = { const questionTypeList = {
SINGLE_CHOICE: "单选题", SINGLE_CHOICE: "单选题",
...@@ -15,7 +23,7 @@ const questionTypeList = { ...@@ -15,7 +23,7 @@ const questionTypeList = {
INDEFINITE_CHOICE: "不定项选择题", INDEFINITE_CHOICE: "不定项选择题",
}; };
class QuestionPreviewModal extends Component { class PreviewQuestionModal extends Component {
formRef = React.createRef(); formRef = React.createRef();
constructor(props) { constructor(props) {
super(props); super(props);
...@@ -36,12 +44,13 @@ class QuestionPreviewModal extends Component { ...@@ -36,12 +44,13 @@ class QuestionPreviewModal extends Component {
userId: User.getStoreUserId(), userId: User.getStoreUserId(),
tenantId: User.getStoreId(), tenantId: User.getStoreId(),
}; };
QuestionBankService.queryQuestionDetails(query).then((res) => { AidToolService.queryQuestionDetails(query).then((res) => {
const { result = [] } = res; const { result = [] } = res;
this.setState({ questionInfo: result }); this.setState({ questionInfo: result });
}); });
}; };
// 查看图片或视频
handleScanFile = (scanFileType, scanFileAddress) => { handleScanFile = (scanFileType, scanFileAddress) => {
this.setState({ this.setState({
showScanFile: true, showScanFile: true,
...@@ -50,13 +59,6 @@ class QuestionPreviewModal extends Component { ...@@ -50,13 +59,6 @@ class QuestionPreviewModal extends Component {
}); });
}; };
transferStemDocument = (txt) => {
const template = `<p class='content'>${txt}</p>`;
let doc = new DOMParser().parseFromString(template, "text/html");
let p = doc.querySelector(".content");
return p;
};
render() { render() {
const { const {
showScanFile, showScanFile,
...@@ -96,7 +98,7 @@ class QuestionPreviewModal extends Component { ...@@ -96,7 +98,7 @@ class QuestionPreviewModal extends Component {
return ( return (
<div> <div>
<Modal <Modal
className="question-preview-modal" className="preview-question-modal"
visible={true} visible={true}
title="题目预览" title="题目预览"
width={560} width={560}
...@@ -225,7 +227,10 @@ class QuestionPreviewModal extends Component { ...@@ -225,7 +227,10 @@ class QuestionPreviewModal extends Component {
)} )}
{["JUDGE"].includes(questionTypeEnum) && {["JUDGE"].includes(questionTypeEnum) &&
_.map(questionOptionContentList, (item, index) => { _.map(questionOptionContentList, (item, index) => {
item.content = item.content.replace(/<\/?[^>]*>/g, ""); item.content = item.content.replace(
/<\/?[^>]*>/g,
""
);
return <span key={index}>{item.content}</span>; return <span key={index}>{item.content}</span>;
})} })}
</div> </div>
...@@ -444,4 +449,4 @@ class QuestionPreviewModal extends Component { ...@@ -444,4 +449,4 @@ class QuestionPreviewModal extends Component {
); );
} }
} }
export default QuestionPreviewModal; export default PreviewQuestionModal;
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
} }
.question-stem { .question-stem {
margin-bottom: 16px; margin-bottom: 16px;
border-bottom: 1px solid #E8E8E8; border-bottom: 1px solid #e8e8e8;
padding-bottom: 16px; padding-bottom: 16px;
&__title { &__title {
height: 22px; height: 22px;
...@@ -140,7 +140,7 @@ ...@@ -140,7 +140,7 @@
} }
.question-answer { .question-answer {
margin-bottom: 16px; margin-bottom: 16px;
border-bottom: 1px solid #E8E8E8; border-bottom: 1px solid #e8e8e8;
padding-bottom: 16px; padding-bottom: 16px;
img { img {
max-width: 88px; max-width: 88px;
...@@ -277,6 +277,6 @@ ...@@ -277,6 +277,6 @@
} }
} }
} }
.question-preview-modal.ant-modal { .preview-question-modal.ant-modal {
max-height: 60% !important; max-height: 60% !important;
} }
/* /*
* @Author: 吴文洁 * @Author: 吴文洁
* @Date: 2020-04-29 10:26:32 * @Date: 2020-04-29 10:26:32
* @LastEditors: zangsuyun * @LastEditors: yuananting
* @LastEditTime: 2021-04-07 16:12:14 * @LastEditTime: 2021-04-15 21:45:42
* @Description: 内容线路由配置 * @Description: 内容线路由配置
*/ */
import Home from '@/modules/home/Home'; import Home from '@/modules/home/Home';
...@@ -27,11 +27,12 @@ import PlanPage from '@/modules/plan-manage/PlanPage'; ...@@ -27,11 +27,12 @@ import PlanPage from '@/modules/plan-manage/PlanPage';
import AddPlanPage from '@/modules/plan-manage/AddPlan'; import AddPlanPage from '@/modules/plan-manage/AddPlan';
import LearningDataPage from '@/modules/plan-manage/LearningData'; import LearningDataPage from '@/modules/plan-manage/LearningData';
import StoreInfoPage from '@/modules/store-manage/StoreInfo'; import StoreInfoPage from '@/modules/store-manage/StoreInfo';
import CourseCategoryManage from '@/modules/teach-tool/components/CourseCategoryManage';
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 KnowledgeBase from "@/modules/knowledge-base/index";
import CollegeInfoPage from '@/modules/college-manage/CollegeInfoPage'; import CollegeInfoPage from '@/modules/college-manage/CollegeInfoPage';
import QuestionBankIndex from '@/modules/teach-tool/QuestionBankIndex';
import QuestionCategoryManage from '@/modules/teach-tool/QuestionCategoryManage';
import AddNewQuestion from '@/modules/teach-tool/AddNewQuestion';
const mainRoutes = [ const mainRoutes = [
{ {
...@@ -116,19 +117,24 @@ const mainRoutes = [ ...@@ -116,19 +117,24 @@ const mainRoutes = [
name: "资料云盘", name: "资料云盘",
}, },
{ {
path: "/question-bank-index", path: '/question-manage-index',
component: QuestionBankIndex, component:QuestionManageIndex,
name: "题库", name: '题库'
}, },
{ {
path: "/question-category-manage", path: '/paper-manage-index',
component: QuestionCategoryManage, component:PaperManageIndex,
name: "分类管理", name: '试卷'
}, },
{ {
path: "/create-new-question", path: '/examination-manage-index',
component: AddNewQuestion, component:ExaminationManagerIndex,
name: "新增题目", name: '考试'
},
{
path: '/course-category-manage',
component:CourseCategoryManage,
name: '分类管理'
}, },
{ {
path: "/switch-route", path: "/switch-route",
......
/* /*
* @Author: yuananting * @Author: yuananting
* @Date: 2021-02-21 15:53:31 * @Date: 2021-02-21 15:53:31
* @LastEditors: zangsuyun * @LastEditors: yuananting
* @LastEditTime: 2021-03-27 10:32:29 * @LastEditTime: 2021-03-27 15:20:42
* @Description: 描述一下咯 * @Description: 描述一下咯
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/ */
...@@ -67,8 +67,18 @@ export const menuList: any = [ ...@@ -67,8 +67,18 @@ export const menuList: any = [
{ {
groupName: "题库", groupName: "题库",
groupCode: "QuestionBank", groupCode: "QuestionBank",
link: '/question-bank-index' link: '/question-manage-index'
} },
{
groupName: "试卷",
groupCode: "ExamPaper",
link: '/paper-manage-index'
},
{
groupName: "考试",
groupCode: "CloudExam",
link: '/examination-manage-index'
},
] ]
}, },
{ {
...@@ -94,7 +104,7 @@ export const menuList: any = [ ...@@ -94,7 +104,7 @@ export const menuList: any = [
{ {
groupName: "课程分类", groupName: "课程分类",
groupCode: "CourseCategory", groupCode: "CourseCategory",
link: '/question-category-manage' link: '/course-category-manage'
}, },
{ {
groupName: "学院装修", groupName: "学院装修",
......
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