This commit is contained in:
fan 2024-02-27 08:46:32 +08:00
commit 508afb9954
12 changed files with 594 additions and 476 deletions

View File

@ -2,14 +2,14 @@ import request from '@/utils/request';
/** /**
* 获取竞赛试卷分页列表 * 获取竞赛试卷分页列表
* @param {Object} data * @param {Object} params
* @param {String} data.name 试卷名称 * @param {String} params.name 试卷名称
*/ */
export function getPaperList(data) { export function getPaperList(params) {
return request({ return request({
url: '/api/exercise/race/pager/page', url: '/api/exercise/race/paper/page',
method: 'GET', method: 'GET',
data params
}); });
} }
@ -19,6 +19,7 @@ export function getPaperList(data) {
* @param {String} data.name 试卷名称 * @param {String} data.name 试卷名称
* @param {String} data.desc 基础描述 * @param {String} data.desc 基础描述
* @param {Number} data.seasonId 所属赛季id * @param {Number} data.seasonId 所属赛季id
* @param {Boolean} data.supportCopy 是否支持拷贝
*/ */
export function createPaper(data) { export function createPaper(data) {
return request({ return request({
@ -50,81 +51,42 @@ export function deletePaper(id) {
}); });
} }
/** /**
* 获取竞赛模块分页列表
* @param {Object} data * @param {Object} data
* @param {String} data.paperName 试卷名称 * @param {Array} data.modules 所有模块
* @param {Number} data.paperId 试卷id * @param {Number} data.modules[i].module_name 模块名字
* @param {String} data.code 模块名称 * @param {Number} data.modules[i].duration 考试总时间
* @param {Number} data.modules[i].group 任务分组
* @param {Number} data.modules[i].group.taskIds 此分组中的任务id
* @param {Number} data.modules[i].group.name 此组的名字
* @param {Number} data.modules[i].group.group 此分组的子分组
*/ */
export function getModuleList(data) { export function paperModuleTaskSetting(paperId, data) {
return request({ return request({
url: '/api/exercise/race/module/page', url: `/api/exercise/race/paper/${paperId}/config`,
method: 'GET',
data
});
}
/**
* 创建模块
* @param {Object} data
* @param {String} data.code 模块名称
* @param {String} data.desc 基础描述
* @param {Number} data.paperId 试卷id
*/
export function createModule(data) {
return request({
url: '/api/exercise/race/module',
method: 'POST', method: 'POST',
data data
}); });
} }
/** /**
* @param {Object} data 同创建试卷
* @param {Number} id 模块id * @param {Number} id 模块id
*/ */
export function editModule(id, data) { export function getPaperDetail(id) {
return request({ return request({
url: `/api/exercise/race/module/${id}`, url: `/api/exercise/race/paper/${id}`,
method: 'POST',
data
});
}
/**
* @param {Number} id 模块id
*/
export function deleteModule(id) {
return request({
url: `/api/exercise/race/module/${id}`,
method: 'DELETE'
});
}
/**
* @param {Number} id 模块id
*/
export function getModuleDetail(id) {
return request({
url: `/api/exercise/race/module/${id}`,
method: 'GET' method: 'GET'
}); });
} }
/** /**
* @param {Object} data * @param {Number} id 模块id
* @param {Number} data.taskIds 模块里所有任务id一级任务的id
* @param {Number} data.group 任务分组
* @param {Number} data.group.taskIds 次分组中的任务id
* @param {Number} data.group.name 分组的名字
* @param {Number} data.group.group 次分组的子分组
*/ */
export function moduleTaskSetting(moudleId, data) { export function copyPaper(id) {
console.log(id);
return request({ return request({
url: `/api/exercise/race/module/setting/${moudleId}/task`, url: `/api/exercise/race/paper/${id}/copy`,
method: 'POST', method: 'PUT'
data
}); });
} }

View File

@ -40,7 +40,6 @@ export default {
userRulesManage: 'User Rights Statistics', userRulesManage: 'User Rights Statistics',
contestDataManage:'Contest data management', contestDataManage:'Contest data management',
contestSubjectManage:'contest subject management', contestSubjectManage:'contest subject management',
contestModuleManage:'contest module management',
contestTaskManage:'contest task management', contestTaskManage:'contest task management',
contestSceneManage:'contest scene management', contestSceneManage:'contest scene management',
contestTaskScoreManage:'contest task score management', contestTaskScoreManage:'contest task score management',

View File

@ -40,7 +40,6 @@ export default {
userRulesManage: '用户权限管理', userRulesManage: '用户权限管理',
contestDataManage:'竞赛数据管理', contestDataManage:'竞赛数据管理',
contestSubjectManage:'竞赛题目管理', contestSubjectManage:'竞赛题目管理',
contestModuleManage:'竞赛模块管理',
contestTaskManage:'竞赛任务管理', contestTaskManage:'竞赛任务管理',
contestSceneManage:'竞赛场景管理', contestSceneManage:'竞赛场景管理',
contestTaskScoreManage:'竞赛任务评分管理', contestTaskScoreManage:'竞赛任务评分管理',

View File

@ -223,7 +223,6 @@ const ThirdJumpSim = () => import('@/views/newMap/display/thirdJump');
const TmsPage = () => import('@/views/jlmap3d/drive/sceneview/tmsPage'); const TmsPage = () => import('@/views/jlmap3d/drive/sceneview/tmsPage');
const ContestSubjectManage = () => import('@/views/contestDataManage/contestSubjectManage/ContestSubjectManage'); const ContestSubjectManage = () => import('@/views/contestDataManage/contestSubjectManage/ContestSubjectManage');
const ContestModuleManage = () => import('@/views/contestDataManage/contestModuleManage/ContestModuleManage');
const ContestTaskManage = () => import('@/views/contestDataManage/contestTaskManage/ContestTaskManage'); const ContestTaskManage = () => import('@/views/contestDataManage/contestTaskManage/ContestTaskManage');
const ContestSceneManage = () => import('@/views/contestDataManage/contestSceneManage/ContestSceneManage'); const ContestSceneManage = () => import('@/views/contestDataManage/contestSceneManage/ContestSceneManage');
const ContestTaskScoreManage = () => import('@/views/contestDataManage/contestTaskScoreManage/ContestTaskScoreManage'); const ContestTaskScoreManage = () => import('@/views/contestDataManage/contestTaskScoreManage/ContestTaskScoreManage');
@ -2040,14 +2039,6 @@ export const asyncRouter = [
i18n: 'newRouter.contestSubjectManage' i18n: 'newRouter.contestSubjectManage'
} }
}, },
{
// 竞赛模块管理
path: 'contestModuleManage',
component: ContestModuleManage,
meta: {
i18n: 'newRouter.contestModuleManage'
}
},
{ {
// 竞赛任务管理 // 竞赛任务管理
path: 'contestTaskManage', path: 'contestTaskManage',

View File

@ -1,128 +0,0 @@
<template>
<el-dialog v-dialogDrag :title="title" :visible.sync="dialogVisible" width="500px" :before-close="handleClose" center :close-on-click-modal="false">
<el-form ref="ruleForm" :model="formModel" :rules="rules" label-width="100px">
<el-form-item label="模块名称:" prop="code">
<el-input v-model="formModel.code" style="width: 350px;" />
</el-form-item>
<el-form-item label="模块描述:" prop="desc">
<el-input v-model="formModel.desc" type="textarea" style="width:350px;" />
</el-form-item>
<el-form-item label="试卷:" prop="paperId">
<el-select v-model="formModel.seasonId" placeholder="请选择" style="width:350px;">
<el-option
v-for="item in paperOptions"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button v-loading="loading" type="primary" @click="doSave">{{ $t('global.confirm') }}</el-button>
<el-button @click="handleClose">{{ $t('global.cancel') }}</el-button>
</span>
</el-dialog>
</template>
<script>
import { createModule, editModule, getPaperList} from '@/api/contest';
export default {
name: 'AddContestTask',
data() {
return {
dialogVisible: false,
formModel: {
id: '',
code: '', //
desc: '', //
paperId: '' // id
},
paperOptions:[],
loading: false
};
},
computed: {
rules() {
const crules = {
code: [
{ required: true, message: '请输入模块名称', trigger: 'blur' }
],
desc: [
{ required: true, message: '请输入模块描述', trigger: 'blur' }
],
paperId: [
{ required: true, message: '请选择所属试卷', trigger: 'blur' }
]
};
return crules;
},
title() {
return this.formModel.id ? '修改模块' : '创建模块';
}
},
methods:{
doShow(row) {
getPaperList().then((res) => {
this.paperOptions = res.data.list;
});
this.dialogVisible = true;
if (row) {
this.formModel.id = row.id;
this.formModel.code = row.code;
this.formModel.desc = row.desc;
this.formModel.paperId = row.paperId;
} else {
this.formModel = {
id: '',
code: '',
desc: '',
paperId: ''
};
this.$nextTick(() => {
this.$refs.ruleForm.resetFields();
});
}
},
handleClose() {
this.formModel = {
id: '',
code: '',
desc: '',
paperId: ''
};
this.$refs.ruleForm.resetFields();
this.dialogVisible = false;
this.loading = false;
},
doSave() {
this.$refs.ruleForm.validate((valid) => {
if (valid) {
this.loading = true;
const data = Object.assign({}, this.formModel);
delete data.id;
if (this.formModel.id) {
editModule(data).then(() => {
this.$message.success('修改模块成功!');
this.handleClose();
this.$emit('moduleListRefresh');
}).catch(error => {
this.$message.error(error.message);
this.loading = false;
});
} else {
createModule(data).then(() => {
this.$message.success('创建模块成功!');
this.handleClose();
this.$emit('moduleListRefresh');
}).catch(error => {
this.$message.error(error.message);
this.loading = false;
});
}
}
});
}
}
};
</script>

View File

@ -1,155 +0,0 @@
<template>
<div style="width: 100%;">
<QueryListPage
ref="moduleQueryListPage"
:card-padding="10"
:query-form="examQueryForm"
:pager-config="pagerConfig"
:query-list="examQueryList"
/>
<add-edit-module ref="addEditModule" @moduleListRefresh="moduleListRefresh" />
<detail-module ref="detailModule" />
</div>
</template>
<script>
import { getModuleList, deleteModule } from '@/api/contest';
import AddEditModule from './AddEditModule.vue';
import DetailModule from './DetailModule.vue';
export default {
name: 'MoudleManage',
components: { AddEditModule, DetailModule },
data() {
return {
pagerConfig: {
pageSize: 'pageSize',
pageIndex: 'pageNum'
},
seasonlist: [],
examQueryForm: {
leftSpan: 14,
textAlign: 'right',
labelWidth: '90px',
reset: true,
columnNum: 3,
queryObject: {
code: {
type: 'text',
label: '模块名称:'
},
paperName: {
type: 'text',
label: '试卷名称:'
}
}
},
examQueryList: {
query: obj => this.getListApi(obj),
selectCheckShow: false,
indexShow: false,
columns: [
{
title: '模块名称',
prop: 'code'
},
{
title: '模块描述',
prop: 'desc'
},
{
title: '试卷名称',
prop: 'paperName'
},
{
title: '考试时间',
prop: 'duration'
},
{
title: '创建时间',
prop: 'createTime',
type: 'tag',
columnValue: (row) => { return row.modifyInfo.createTime; }
},
{
title: '修改时间',
prop: 'updateTime',
type: 'tag',
columnValue: (row) => { return row.modifyInfo.updateTime; }
},
{
type: 'button',
title: this.$t('global.operate'),
width: '350',
buttons: [
{
name: '编辑',
handleClick: this.editPaper,
type: 'primary'
},
{
name: '删除',
handleClick: this.handleDelete,
type: 'danger'
},
{
name: '模块详情',
handleClick: this.openDetailDialog,
type: 'info'
}
]
}
],
actions: [{ text: '新建模块', handler: this.creatPaper }]
}
};
},
computed: {
userId() {
return this.$store.state.user.id;
}
},
methods: {
getListApi(obj) {
return getModuleList({ ...obj });
},
editPaper(index, row) {
this.$refs.addEditModule.doShow(row);
},
creatPaper() {
this.$refs.addEditModule.doShow();
},
handleDelete(data) {
this.$confirm('确定删除该模块吗?', this.$t('global.tips'), {
confirmButtonText: this.$t('global.confirm'),
cancelButtonText: this.$t('global.cancel'),
type: 'warning'
})
.then(() => deleteModule(data.id))
.then(() => {
this.moduleListRefresh();
this.$message({
type: 'success',
message: '删除成功!'
});
})
.catch(res => {
if (res.code && res.code !== 200) {
this.$message({ type: 'error', message: res.message });
}
});
},
openDetailDialog(index, row) {
this.$refs.detailModule.doShow(row.id);
},
moduleListRefresh() {
this.$nextTick(() => {
this.$refs.moduleQueryListPage.refresh(true);
});
}
}
};
</script>
<style scoped></style>

View File

@ -1,97 +0,0 @@
<template>
<el-dialog v-dialogDrag title="模块详情" :visible.sync="dialogVisible" width="500px" :before-close="handleClose" center :close-on-click-modal="false">
<el-form ref="ruleForm" :model="formModel" :rules="rules" label-width="100px">
<el-form-item label="任务:" prop="paperId">
<el-select v-model="formModel.taskIds" multiple placeholder="请选择" style="width:350px;">
<el-option
v-for="item in taskOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item label="分组:" prop="paperId">
<el-tree
:data="formModel.group"
:props="defaultProps"
accordion
/>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button v-loading="loading" type="primary" @click="doSave">设置模块任务</el-button>
<el-button @click="handleClose">{{ $t('global.cancel') }}</el-button>
</span>
</el-dialog>
</template>
<script>
import { getModuleDetail, getTaskTreeDatas, moduleTaskSetting} from '@/api/contest';
export default {
name: 'DetailModule',
data() {
return {
dialogVisible: false,
formModel: {
taskIds: [], //
group:[{name:'', taskIds: [], group:[] }]//
},
taskOptions:[],
loading: false,
moduleId:'',
defaultProps: {
children: 'children',
label: 'label'
}
};
},
computed: {
rules() {
const crules = {
taskIds: [
{ required: true, message: '请选择模块任务', trigger: 'blur' }
]
};
return crules;
}
},
methods:{
doShow(moduleId) {
getTaskTreeDatas().then((res) => {
this.taskOptions = res.data;
});
getModuleDetail(moduleId).then((res) => {
this.formModel = res.data;
});
this.dialogVisible = true;
this.moduleId = moduleId;
},
handleClose() {
this.formModel = {
taskIds: [], //
group:[{name:'', taskIds: [], group:[] }]//
};
this.$refs.ruleForm.resetFields();
this.dialogVisible = false;
this.loading = false;
},
doSave() {
this.$refs.ruleForm.validate((valid) => {
if (valid) {
this.loading = true;
const data = Object.assign({}, this.formModel);
moduleTaskSetting(this.moduleId, data).then(() => {
this.$message.success('模块任务设置成功!');
this.handleClose();
}).catch(error => {
this.$message.error(error.message);
this.loading = false;
});
}
});
}
}
};
</script>

View File

@ -17,6 +17,9 @@
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="支持拷贝:" prop="supportCopy">
<el-checkbox v-model="formModel.supportCopy" />
</el-form-item>
</el-form> </el-form>
<span slot="footer" class="dialog-footer"> <span slot="footer" class="dialog-footer">
<el-button v-loading="loading" type="primary" @click="doSave">{{ $t('global.confirm') }}</el-button> <el-button v-loading="loading" type="primary" @click="doSave">{{ $t('global.confirm') }}</el-button>
@ -35,7 +38,8 @@ export default {
id: '', id: '',
name: '', // name: '', //
desc: '', // desc: '', //
seasonId: '' // id seasonId: '', // id
supportCopy:false //
}, },
seasonOptions:[], seasonOptions:[],
loading: false loading: false
@ -71,6 +75,7 @@ export default {
this.formModel.name = row.name; this.formModel.name = row.name;
this.formModel.desc = row.desc; this.formModel.desc = row.desc;
this.formModel.seasonId = row.seasonId; this.formModel.seasonId = row.seasonId;
this.formModel.supportCopy = row.supportCopy;
} else { } else {
this.formModel = { this.formModel = {
id: '', id: '',
@ -78,9 +83,6 @@ export default {
desc: '', desc: '',
seasonId: '' seasonId: ''
}; };
this.$nextTick(() => {
this.$refs.ruleForm.resetFields();
});
} }
}, },
handleClose() { handleClose() {
@ -88,9 +90,9 @@ export default {
id: '', id: '',
name: '', name: '',
desc: '', desc: '',
seasonId: '' seasonId: '',
supportCopy:false
}; };
this.$refs.ruleForm.resetFields();
this.dialogVisible = false; this.dialogVisible = false;
this.loading = false; this.loading = false;
}, },
@ -101,7 +103,7 @@ export default {
const data = Object.assign({}, this.formModel); const data = Object.assign({}, this.formModel);
delete data.id; delete data.id;
if (this.formModel.id) { if (this.formModel.id) {
editPaper(data).then(() => { editPaper(this.formModel.id, data).then(() => {
this.$message.success('修改试卷成功!'); this.$message.success('修改试卷成功!');
this.handleClose(); this.handleClose();
this.$emit('paperListRefresh'); this.$emit('paperListRefresh');

View File

@ -8,17 +8,19 @@
:query-list="examQueryList" :query-list="examQueryList"
/> />
<add-edit-paper ref="addEditPaper" @paperListRefresh="paperListRefresh" /> <add-edit-paper ref="addEditPaper" @paperListRefresh="paperListRefresh" />
<edit-module ref="editModule" />
</div> </div>
</template> </template>
<script> <script>
import { getPaperList, deletePaper } from '@/api/contest'; import { getPaperList, deletePaper, copyPaper } from '@/api/contest';
import AddEditPaper from './AddEditPaper.vue'; import AddEditPaper from './AddEditPaper.vue';
import EditModule from './EditModule.vue';
export default { export default {
name: 'SubjectManage', name: 'SubjectManage',
components: { AddEditPaper }, components: { AddEditPaper, EditModule },
data() { data() {
return { return {
pagerConfig: { pagerConfig: {
@ -27,11 +29,10 @@ export default {
}, },
seasonlist: [], seasonlist: [],
examQueryForm: { examQueryForm: {
reset: true,
leftSpan: 14, leftSpan: 14,
textAlign: 'right', textAlign: 'right',
labelWidth: '90px', labelWidth: '90px',
reset: true,
columnNum: 3,
queryObject: { queryObject: {
name: { name: {
type: 'text', type: 'text',
@ -54,19 +55,21 @@ export default {
}, },
{ {
title: '所属赛季', title: '所属赛季',
prop: 'seasonId' prop: 'seasonName'
}, },
{ {
title: '创建时间', title: '创建时间',
prop: 'createTime', prop: 'createTime',
type: 'tag', type: 'tag',
columnValue: (row) => { return row.modifyInfo.createTime; } columnValue: (row) => { return row.modifyInfo.createTime; },
tagType: (row) => { return ''; }
}, },
{ {
title: '修改时间', title: '修改时间',
prop: 'updateTime', prop: 'updateTime',
type: 'tag', type: 'tag',
columnValue: (row) => { return row.modifyInfo.updateTime; } columnValue: (row) => { return row.modifyInfo.updateTime; },
tagType: (row) => { return ''; }
}, },
{ {
type: 'button', type: 'button',
@ -82,6 +85,19 @@ export default {
name: '删除', name: '删除',
handleClick: this.handleDelete, handleClick: this.handleDelete,
type: 'danger' type: 'danger'
},
{
name: '模块配置',
handleClick: this.editModule,
type: 'primary'
},
{
name: '拷贝试卷',
handleClick: this.copyContestPaper,
type: 'warning',
showControl: row => {
return row.supportCopy;
}
} }
] ]
} }
@ -128,6 +144,16 @@ export default {
} }
}); });
}, },
editModule(index, row) {
this.$refs.editModule.doShow(row);
},
copyContestPaper(index, row) {
copyPaper(row.id).then(() => {
this.paperListRefresh();
}).catch(error => {
this.$message.error(error.message);
});
},
paperListRefresh() { paperListRefresh() {
this.$nextTick(() => { this.$nextTick(() => {
this.$refs.examQueryListPage.refresh(true); this.$refs.examQueryListPage.refresh(true);

View File

@ -0,0 +1,353 @@
<template>
<el-dialog v-dialogDrag title="模块配置" :visible.sync="dialogVisible" width="50%" :before-close="handleClose" center :close-on-click-modal="false">
<div class="taskContainer">
<div style="margin-bottom: 10px;">
<el-card>
<div class="taskTitle">
<div>试卷模块管理</div>
<div>
<el-button
type="primary"
size="small"
@click="creatModule"
>
新建模块
</el-button>
</div>
</div>
</el-card>
</div>
<el-card>
<el-tree
:data="taskTreeDatas"
node-key="id"
default-expand-all
:expand-on-click-node="false"
>
<span slot-scope="{ node, data }" class="custom-tree-node">
<span :class="getLabeColorClass(data.type)">{{ node.label }}</span>
<span>
<el-button
v-if="data.type=='module'"
type="text"
size="mini"
@click="() => editModule(data)"
>
修改模块信息
</el-button>
<el-button
v-if="data.type=='taskCatalog'"
type="text"
size="mini"
@click="() => editTaskCatalog(data)"
>
修改任务目录
</el-button>
<el-button
v-if="data.type=='module'||data.type=='taskCatalog'"
type="text"
size="mini"
@click="() => addTaskCatalog(data)"
>
添加任务目录
</el-button>
<el-button
v-if="data.type=='taskCatalog'"
type="text"
size="mini"
@click="() => addTasks(data)"
>
添加任务
</el-button>
<el-button
v-if="data.type=='tasks'"
type="text"
size="mini"
@click="() => moveUp(data)"
>
上移
</el-button>
<el-button
v-if="data.type=='tasks'"
type="text"
size="mini"
@click="() => moveDown(data)"
>
下移
</el-button>
<el-button
type="text"
style="color: red;"
size="mini"
@click="() => deleteTreeData(data)"
>
删除
</el-button>
</span>
</span></el-tree>
</el-card>
<edit-module-task ref="editModuleTask" @changeTreeData="changeTreeData" />
</div>
<span slot="footer" class="dialog-footer">
<el-button v-loading="loading" type="primary" @click="doSave">{{ $t('global.confirm') }}</el-button>
<el-button @click="handleClose">{{ $t('global.cancel') }}</el-button>
</span>
</el-dialog>
</template>
<script>
import EditModuleTask from './EditModuleTask';
import { getTaskTreeDatas, getPaperDetail, paperModuleTaskSetting} from '@/api/contest';
let id = 1;
export default {
name:'ContestTaskManage',
components: {
EditModuleTask
},
data() {
return {
dialogVisible: false,
loading:false,
paperId:'',
taskTreeDatas:[],
allTaskDatas:{}
};
},
methods: {
doShow(row) {
getTaskTreeDatas().then((res) => {
this.allTaskDatas = res.data.reduce((acc, obj) => {
acc[obj.name] = obj.id;
return acc;
}, {});
getPaperDetail(row.id).then((res) => {
if (res.data.moduleVo) {
this.taskTreeDatas = res.data.moduleVo.map(moduleItem=>{
let children = [];
if (moduleItem.group.length) {
children = moduleItem.group.map(taskCatalog=> this.transformTree(taskCatalog));
}
return {
id:id++,
label:moduleItem.moduleName,
duration:moduleItem.duration,
moduleScoreRuleId:moduleItem.moduleScoreRuleId,
type:'module',
children
};
});
}
}).catch(error => {
this.$message.error(error.message);
});
}).catch(error => {
this.$message.error(error.message);
});
this.paperId = row.id;
this.dialogVisible = true;
},
handleClose() {
id = 1;
this.dialogVisible = false;
this.taskTreeDatas = [];
},
creatModule() {
this.$refs.editModuleTask.doShow('module', undefined, true);
},
editModule(data) {
this.$refs.editModuleTask.doShow('module', data);
},
addTaskCatalog(data) {
this.$refs.editModuleTask.doShow('taskCatalog', data, true);
},
editTaskCatalog(data) {
this.$refs.editModuleTask.doShow('taskCatalog', data);
},
addTasks(data) {
this.$refs.editModuleTask.doShow('tasks', data, true);
},
deleteTreeData(data) {
this.$confirm(`确定删除${data.label}吗?`, this.$t('global.tips'), {
confirmButtonText: this.$t('global.confirm'),
cancelButtonText: this.$t('global.cancel'),
type: 'warning'
})
.then(() => this.findLabel(this.taskTreeDatas, data.id, true));
},
moveUp(data) {
const targetData = this.findLabel(this.taskTreeDatas, data.parentId);
const index = targetData.children.findIndex(item=>item.label == data.label);
if (index === 0) {
return;
}
const temp = targetData.children[index];
this.$set(targetData.children, index, targetData.children[index - 1]);
this.$set(targetData.children, index - 1, temp);
const copy = JSON.parse(JSON.stringify(this.taskTreeDatas));
this.taskTreeDatas = [];
this.taskTreeDatas = copy;
},
moveDown(data) {
const targetData = this.findLabel(this.taskTreeDatas, data.parentId).children;
const index = targetData.findIndex(item=>item.label == data.label);
if (index === targetData.length - 1 || targetData[index + 1].type == 'taskCatalog') {
return;
}
const temp = targetData[index];
this.$set(targetData, index, targetData[index + 1]);
this.$set(targetData, index + 1, temp);
const copy = JSON.parse(JSON.stringify(this.taskTreeDatas));
this.taskTreeDatas = [];
this.taskTreeDatas = copy;
},
changeTreeData(type, data, isAdd) {
if (data instanceof Array) {
if (data.length > 0 && !data[0].id) {
for (let i = 0; i < data.length; i++) {
data[i].id = id++;
}
}
} else if (!data.id) {
data.id = id++;
}
if (type == 'module') {
if (isAdd) {
this.taskTreeDatas.push(data);
} else {
const targetData = this.findLabel(this.taskTreeDatas, data.id);
targetData.label = data.label;
targetData.duration = data.duration;
}
} else if (type == 'taskCatalog') {
if (isAdd) {
const targetData = this.findLabel(this.taskTreeDatas, data.parentId);
targetData.children.push(data);
} else {
const targetData = this.findLabel(this.taskTreeDatas, data.id);
targetData.label = data.label;
}
} else {
const targetData = this.findLabel(this.taskTreeDatas, data[0].parentId);
data.forEach(item=>{
const hasTasks = targetData.children.map(item=>item.label);
if ( !hasTasks.includes(item.label)) {
targetData.children.unshift(item);
}
});
}
},
doSave() {
const allTaskDatas = this.allTaskDatas;
const moduleDatas = this.taskTreeDatas.map(moduleItem=>{
let group = [];
if (moduleItem.children.length) {
group = moduleItem.children.map(taskCatalog=> transformTreeDataToSend(taskCatalog));
}
return {
moduleName:moduleItem.label, duration:moduleItem.duration, moduleScoreRuleId:moduleItem.moduleScoreRuleId, group};
});
paperModuleTaskSetting(this.paperId, {modules:moduleDatas}).then(() => {
this.$message.success('模块配置任务成功!');
this.handleClose();
}).catch(error => {
this.$message.error(error.message);
this.loading = false;
});
function transformTreeDataToSend(taskCatalog) {
const result = {taskIds:[], name:taskCatalog.label, group:[]};
for (let i = 0; i < taskCatalog.children.length; i++) {
const node = taskCatalog.children[i];
if (node.type == 'tasks') {
result.taskIds.push(allTaskDatas[node.label]);
} else if (node.type == 'taskCatalog') {
result.group.push(transformTreeDataToSend(node));
}
}
return result;
}
},
transformTree(data) {
const result = {label:data.name, children:[], id:id++, type:'taskCatalog' };
data.taskIds.forEach(taskId => {
let label = '';
for (const key in this.allTaskDatas) {
if (this.allTaskDatas[key] === taskId) {
label = key;
break;
}
}
result.children.push({label, id:id++, type:'tasks', parentId:result.id });
});
if (data.group.length) {
const changeGroup = data.group.map(taskCatalog=>
this.transformTree(taskCatalog)
);
result.children.push(...changeGroup);
}
return result;
},
findLabel( treeData, targetLabelId, isDelete) {
for (let i = 0; i < treeData.length; i++) {
if (treeData[i].id === targetLabelId) {
if (isDelete) {
treeData.splice(i, 1);
}
return treeData[i];
}
if (treeData[i].children) {
const result = this.findLabel(treeData[i].children, targetLabelId, isDelete);
if (result) {
return result;
}
}
}
return undefined;
},
findName( treeData, targetName) {
for (const item of treeData) {
if (item.name === targetName) {
return item;
}
if (item.group) {
const result = this.findName(item.group, targetName);
if (result) {
return result;
}
}
}
return undefined;
},
getLabeColorClass(value) {
return {
'yellow': value === 'module',
'green': value === 'taskCatalog'
};
}
}
};
</script>
<style lang="scss" scoped>
.taskContainer{
margin: 0 auto;
.taskTitle {
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px;
}
.custom-tree-node {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 16px;
padding-right: 20px;
}
}
.yellow { color: rgb(230, 162, 60); }
.green { color: green; }
</style>

View File

@ -0,0 +1,166 @@
<template>
<el-dialog v-dialogDrag :title="title" :visible.sync="dialogVisible" width="500px" :before-close="handleClose" center :close-on-click-modal="false" append-to-body>
<el-form ref="ruleForm" :model="formModel" :rules="rules" label-width="100px">
<el-form-item v-if="editType == 'module'" label="模块名称:" prop="moduleName">
<el-input v-model="formModel.moduleName" style="width: 350px;" />
</el-form-item>
<el-form-item v-if="editType == 'module'" label="考试时间:" prop="duration">
<el-input v-model="formModel.duration" style="width:350px;" />
</el-form-item>
<el-form-item v-if="editType == 'module'" label="评分规则:" prop="moduleScoreRuleId">
<el-select v-model="formModel.moduleScoreRuleId" placeholder="请选择" style="width:320px;">
<el-option
v-for="item in bindRuleOptions"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item v-if="editType == 'taskCatalog'" label="目录名称:" prop="taskCatalogName">
<el-input v-model="formModel.taskCatalogName" style="width: 350px;" />
</el-form-item>
<el-form-item v-if="editType == 'tasks'" label="任务:" prop="tasks">
<el-select v-model="formModel.tasks" multiple placeholder="请选择" style="width: 350px;">
<el-option
v-for="item in taskOptions"
:key="item.id"
:label="item.name"
:value="item.name"
/>
</el-select>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button v-loading="loading" type="primary" @click="doSave">{{ $t('global.confirm') }}</el-button>
<el-button @click="handleClose">{{ $t('global.cancel') }}</el-button>
</span>
</el-dialog>
</template>
<script>
import { getTaskTreeDatas, queryContextScorePaged} from '@/api/contest';
export default {
name: 'AddContestTask',
data() {
return {
dialogVisible: false,
formModel:{
moduleName:'',
duration:'',
moduleScoreRuleId:'',
moduleId:'',
taskCatalogName:'',
taskCatalogId:'',
tasks:[]
},
bindRuleOptions:[],
taskOptions:[],
loading: false,
title:'',
editType:'',
parentId:'',
idAdd:false
};
},
computed: {
rules() {
const crules = {
moduleName: [
{ required: true, message: '请输入模块名称', trigger: 'blur' }
],
duration: [
{ required: true, message: '请输入考试时间', trigger: 'blur' }
],
moduleScoreRuleId: [
{ required: true, message: '请选择任务', trigger: 'blur' }
],
taskCatalogName: [
{ required: true, message: '请输入任务名称', trigger: 'blur' }
],
tasks: [
{ required: true, message: '请选择任务', trigger: 'blur' }
]
};
return crules;
}
},
methods:{
doShow(type, data, isAdd) {
this.isAdd = isAdd;
if (type == 'module') {
queryContextScorePaged().then((res) => {
this.bindRuleOptions = res.data.list;
});
this.editType = 'module';
this.title = '创建模块';
if (data) {
this.title = '修改模块信息';
this.formModel.moduleName = data.label;
this.formModel.duration = data.duration;
this.formModel.moduleScoreRuleId = data.moduleScoreRuleId;
this.formModel.moduleId = data.id;
}
} else if (type == 'taskCatalog') {
this.editType = 'taskCatalog';
this.title = isAdd ? '创建任务目录' : '修改任务目录';
this.parentId = isAdd ? data.id : data.parentId;
if (!isAdd) {
this.formModel.taskCatalogId = data.id;
this.formModel.taskCatalogName = data.label;
}
} else {
this.editType = 'tasks';
this.parentId = data.id;
getTaskTreeDatas().then((res) => {
this.taskOptions = res.data;
this.formModel.tasks = data.children.filter(item => !item.children).map(item=>item.label);
}).catch(error => {
this.$message.error(error.message);
});
this.title = data.label;
}
this.dialogVisible = true;
},
handleClose() {
this.formModel = {
moduleName:'',
duration:'',
moduleScoreRuleId:'',
taskCatalogName:'',
tasks: []
};
this.parentId = '';
this.editType = '';
this.isAdd = false;
this.dialogVisible = false;
this.loading = false;
},
doSave() {
this.$refs.ruleForm.validate((valid) => {
if (valid) {
if (this.editType == 'module') {
const data = {label:this.formModel.moduleName, duration:this.formModel.duration, moduleScoreRuleId:this.formModel.moduleScoreRuleId, type:'module', children:[]};
if (!this.isAdd) {
data.id = this.formModel.moduleId;
}
this.$emit('changeTreeData', 'module', data, this.isAdd);
} else if (this.editType == 'taskCatalog') {
const data = {label:this.formModel.taskCatalogName, type:'taskCatalog', parentId:this.parentId, children:[]};
if (!this.isAdd) {
data.id = this.formModel.taskCatalogId;
}
this.$emit('changeTreeData', 'taskCatalog', data, this.isAdd);
} else {
const data = this.formModel.tasks.map(task=>{ return {label:task, type:'tasks', parentId:this.parentId}; });
this.$emit('changeTreeData', 'task', data);
}
this.handleClose();
this.dialogVisible = false;
}
});
}
}
};
</script>

View File

@ -7,8 +7,8 @@
<el-form-item label="任务描述:" prop="desc"> <el-form-item label="任务描述:" prop="desc">
<el-input v-model="formModel.desc" type="textarea" style="width:350px;" /> <el-input v-model="formModel.desc" type="textarea" style="width:350px;" />
</el-form-item> </el-form-item>
<el-form-item label="考核内容:" prop="contest"> <el-form-item label="考核内容:" prop="content">
<el-input v-model="formModel.contest" type="textarea" style="width: 350px;" /> <el-input v-model="formModel.content" type="textarea" style="width: 350px;" />
</el-form-item> </el-form-item>
<el-form-item label="评价标准:" prop="standards"> <el-form-item label="评价标准:" prop="standards">
<el-input v-model="formModel.standards" type="textarea" style="width: 350px;" /> <el-input v-model="formModel.standards" type="textarea" style="width: 350px;" />
@ -31,7 +31,7 @@ export default {
id: '', id: '',
name: '', // name: '', //
desc: '', // desc: '', //
contest: '', // content: '', //
standards: '', // standards: '', //
parentId:'' parentId:''
}, },
@ -48,7 +48,7 @@ export default {
desc: [ desc: [
{ required: true, message: '请输入任务描述', trigger: 'blur' } { required: true, message: '请输入任务描述', trigger: 'blur' }
], ],
contest: [ content: [
{ required: true, message: '请输入考核内容', trigger: 'blur' } { required: true, message: '请输入考核内容', trigger: 'blur' }
], ],
standards: [ standards: [
@ -72,14 +72,14 @@ export default {
this.formModel.id = row.id; this.formModel.id = row.id;
this.formModel.name = row.name; this.formModel.name = row.name;
this.formModel.desc = row.desc; this.formModel.desc = row.desc;
this.formModel.contest = row.contest; this.formModel.content = row.content;
this.formModel.standards = row.standards; this.formModel.standards = row.standards;
} else { } else {
this.formModel = { this.formModel = {
id: '', id: '',
name: '', name: '',
desc: '', desc: '',
contest: '', content: '',
standards:'', standards:'',
parentId:'' parentId:''
}; };
@ -93,7 +93,7 @@ export default {
id: '', id: '',
name: '', name: '',
desc: '', desc: '',
contest: '', content: '',
standards:'', standards:'',
parentId:'' parentId:''
}; };
@ -111,7 +111,7 @@ export default {
delete data.parentId; delete data.parentId;
} }
if (this.formModel.id) { if (this.formModel.id) {
editTask(data).then(() => { editTask(this.formModel.id, data).then(() => {
this.$message.success('修改任务成功!'); this.$message.success('修改任务成功!');
this.handleClose(); this.handleClose();
this.$emit('reloadTaskTree'); this.$emit('reloadTaskTree');