Merge branch 'master' of https://e.coding.net/ctcdevteam/examtest
This commit is contained in:
commit
ee1b614411
|
|
@ -0,0 +1,29 @@
|
|||
import request from '@/utils/request'
|
||||
|
||||
export function getexamlist(query) {
|
||||
return request({
|
||||
url: '/examtest/exam/',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
export function createexam(data) {
|
||||
return request({
|
||||
url: '/examtest/exam/',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
export function updateexam(id, data) {
|
||||
return request({
|
||||
url: `/examtest/exam/${id}/`,
|
||||
method: 'put',
|
||||
data
|
||||
})
|
||||
}
|
||||
export function deleteexam(id) {
|
||||
return request({
|
||||
url: `/examtest/exam/${id}/`,
|
||||
method: 'delete',
|
||||
})
|
||||
}
|
||||
|
|
@ -35,10 +35,11 @@ export function deleteTestRule(id) {
|
|||
})
|
||||
}
|
||||
|
||||
export function getWorkScopeAll() {
|
||||
export function getWorkScopeAll(query) {
|
||||
return request({
|
||||
url: '/examtest/workscope/',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -131,4 +132,19 @@ export function exportTest(query) {
|
|||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
export function exportwTest(id,data) {
|
||||
return request({
|
||||
url: `/examtest/examtest/${id}/exportw/`,
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
export function deleteExamtest(id) {
|
||||
return request({
|
||||
url: `/examtest/examtest/${id}/`,
|
||||
method: 'delete',
|
||||
})
|
||||
}
|
||||
|
|
@ -247,6 +247,21 @@ export const asyncRoutes = [
|
|||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/exammanage',
|
||||
component: Layout,
|
||||
redirect: '/exammanage/index',
|
||||
name: 'Exammanage',
|
||||
meta: { title: '考试管理', icon: '', perms: []},
|
||||
children: [
|
||||
{
|
||||
path: 'index',
|
||||
name: 'exam',
|
||||
component: () => import('@/views/exam/index.vue'),
|
||||
meta: { title: '考试管理', icon: 'component', perms: ['exam_view'] }
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/analyse',
|
||||
component: Layout,
|
||||
|
|
@ -268,6 +283,7 @@ export const asyncRoutes = [
|
|||
},
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
path: '/qtest',
|
||||
component: Layout,
|
||||
|
|
|
|||
|
|
@ -64,9 +64,61 @@ div:focus {
|
|||
padding: 10px;
|
||||
}
|
||||
|
||||
.el-table--medium td, .el-table--medium th {
|
||||
padding: 2px 0;
|
||||
}
|
||||
.el-form-item {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
.el-card, .el-message {
|
||||
border-radius: 0px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.el-card__body {
|
||||
padding: 6px;
|
||||
}
|
||||
.el-card__header {
|
||||
padding: 6px;
|
||||
}
|
||||
}
|
||||
.el-tabs--border-card>.el-tabs__content {
|
||||
padding: 6px;
|
||||
}
|
||||
.el-dialog__header {
|
||||
padding: 10px 10px 6px;
|
||||
}
|
||||
// .el-dialog{
|
||||
// display: flex;
|
||||
// flex-direction: column;
|
||||
// margin:0 !important;
|
||||
// position:absolute;
|
||||
// top:50%;
|
||||
// left:50%;
|
||||
// transform:translate(-50%,-50%);
|
||||
// /*height:600px;*/
|
||||
// max-height:calc(100% - 30px);
|
||||
// max-width:calc(100% - 30px);
|
||||
// }
|
||||
.el-dialog .el-dialog__body{
|
||||
// flex:1;
|
||||
// overflow: auto;
|
||||
padding: 8px 12px;
|
||||
}
|
||||
|
||||
.el-form--label-top .el-form-item__label {
|
||||
line-height: 16px;
|
||||
}
|
||||
.el-button+.el-button {
|
||||
margin-left: 1px;
|
||||
}
|
||||
.el-tabs__header {
|
||||
margin: 0 0 6px;
|
||||
}
|
||||
.pagination-container {
|
||||
padding: 0px 0px;
|
||||
}
|
||||
body .el-table th.gutter{
|
||||
display: table-cell!important;
|
||||
}
|
||||
.el-dialog__footer{
|
||||
padding: 6px 6px 6px;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
</el-select>
|
||||
<el-select
|
||||
v-model="listQuery.type"
|
||||
placeholder="模考类型"
|
||||
placeholder="考试类型"
|
||||
clearable
|
||||
style="width: 200px"
|
||||
class="filter-item"
|
||||
|
|
@ -54,7 +54,7 @@
|
|||
icon="el-icon-refresh-left"
|
||||
@click="resetFilter"
|
||||
>刷新重置</el-button>
|
||||
<el-button type="primary" icon="el-icon-download" @click="exportTest">导出Excel</el-button>
|
||||
<el-button type="primary" icon="el-icon-download" @click="exportTest" >导出Excel</el-button>
|
||||
<div style="margin-top:10px">
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -85,6 +85,9 @@
|
|||
<el-table-column align="left" label="押题卷">
|
||||
<template slot-scope="scope">{{ scope.row.paper_name }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="left" label="所属考试">
|
||||
<template slot-scope="scope">{{ scope.row.exam_name }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="left" label="得分" sortable='custom' prop="score">
|
||||
<template slot-scope="scope">{{ scope.row.score }}</template>
|
||||
</el-table-column>
|
||||
|
|
@ -94,14 +97,26 @@
|
|||
<el-table-column align="left" label="答题时间">
|
||||
<template slot-scope="scope">{{ scope.row.start_time }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="操作">
|
||||
<el-table-column align="center" label="操作" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<el-button
|
||||
v-if="scope.row.type=='正式考试'"
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="handleDetail(scope)"
|
||||
icon="el-icon-more"
|
||||
></el-button>
|
||||
@click="handleExport(scope)"
|
||||
>生成Word</el-button>
|
||||
<el-button
|
||||
v-if="scope.row.type=='正式考试'"
|
||||
type="warning"
|
||||
size="small"
|
||||
@click="handleExport2(scope)"
|
||||
>重新生成</el-button>
|
||||
<el-button
|
||||
v-if="scope.row.type=='正式考试'"
|
||||
type="danger"
|
||||
size="small"
|
||||
@click="handleDelete(scope)"
|
||||
>删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
|
@ -116,7 +131,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { getExamTestlist, exportTest } from "@/api/examtest";
|
||||
import { getExamTestlist, exportTest, exportwTest, deleteExamtest } from "@/api/examtest";
|
||||
import checkPermission from "@/utils/permission";
|
||||
import Pagination from "@/components/Pagination";
|
||||
|
||||
|
|
@ -138,6 +153,7 @@ export default {
|
|||
typeOptions: [
|
||||
{ key: "自助模考", label: "自助模考", value: "自助模考" },
|
||||
{ key: "押卷模考", label: "押卷模考", value: "押卷模考"},
|
||||
{ key: "正式考试", label: "正式考试", value: "正式考试"},
|
||||
],
|
||||
passOptions: [
|
||||
{ key: true, label: "通过", value: true },
|
||||
|
|
@ -186,10 +202,19 @@ export default {
|
|||
value:'setTimeRange',
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
this.getQuery();
|
||||
},
|
||||
methods: {
|
||||
checkPermission,
|
||||
getQuery() {
|
||||
if(this.$route.params.exam){
|
||||
this.listQuery.exam = this.$route.params.exam;
|
||||
this.getList()
|
||||
}else{
|
||||
this.getList()
|
||||
}
|
||||
|
||||
},
|
||||
getList() {
|
||||
this.listLoading = true;
|
||||
getExamTestlist(this.listQuery).then(response => {
|
||||
|
|
@ -210,9 +235,37 @@ export default {
|
|||
this.value = []
|
||||
this.getList();
|
||||
},
|
||||
handleDetail(scope) {
|
||||
// this.dialogVisible = true
|
||||
// this.question = scope.row
|
||||
handleExport(scope) {
|
||||
const loading = this.$loading({text: '正在生成word...',});
|
||||
exportwTest(scope.row.id).then(res=>{
|
||||
loading.close()
|
||||
window.open(res.data.path, "_blank");
|
||||
}).catch(e=>{loading.close()})
|
||||
},
|
||||
handleDelete(scope){
|
||||
this.$confirm("确认删除该考试记录吗?将丢失数据!", "警告", {
|
||||
confirmButtonText: "确认",
|
||||
cancelButtonText: "取消",
|
||||
type: "error"
|
||||
})
|
||||
.then(async () => {
|
||||
await deleteExamtest(scope.row.id);
|
||||
this.getList()
|
||||
this.$message({
|
||||
type: "success",
|
||||
message: "成功删除!"
|
||||
});
|
||||
})
|
||||
.catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
},
|
||||
handleExport2(scope) {
|
||||
const loading = this.$loading({text: '正在重新生成word...',});
|
||||
exportwTest(scope.row.id, {anew:true}).then(res=>{
|
||||
loading.close()
|
||||
window.open(res.data.path, "_blank");
|
||||
}).catch(e=>{loading.close()})
|
||||
},
|
||||
exportTest() {
|
||||
const loading = this.$loading();
|
||||
|
|
@ -235,7 +288,8 @@ export default {
|
|||
|
||||
this.getList()
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -212,12 +212,7 @@ export default {
|
|||
updateCompany(this.company.id, this.company).then(() => {
|
||||
this.getList();
|
||||
this.dialogVisible = false;
|
||||
this.$notify({
|
||||
title: "成功",
|
||||
message: "编辑成功",
|
||||
type: "success",
|
||||
duration: 2000
|
||||
});
|
||||
this.$message.success('成功')
|
||||
});
|
||||
} else {
|
||||
createCompany(this.company).then(res => {
|
||||
|
|
@ -225,12 +220,7 @@ export default {
|
|||
// this.tableData.unshift(this.company)
|
||||
this.getList();
|
||||
this.dialogVisible = false;
|
||||
this.$notify({
|
||||
title: "成功",
|
||||
message: "新增成功",
|
||||
type: "success",
|
||||
duration: 2000
|
||||
});
|
||||
this.$message.success('成功')
|
||||
});
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -156,11 +156,7 @@ export default {
|
|||
|
||||
const { description, name } = this.role
|
||||
this.dialogVisible = false
|
||||
this.$notify({
|
||||
title: '成功',
|
||||
dangerouslyUseHTMLString: true,
|
||||
type: 'success'
|
||||
})
|
||||
this.$message.success('成功')
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,274 @@
|
|||
<template>
|
||||
<div class="app-container">
|
||||
<div style="margin-top:10px">
|
||||
<el-input
|
||||
v-model="listQuery.search"
|
||||
placeholder="输入考试名称进行搜索"
|
||||
style="width: 300px;"
|
||||
class="filter-item"
|
||||
@keyup.enter.native="handleFilter"
|
||||
/>
|
||||
<el-button type="primary" @click="handleAdd" icon="el-icon-plus" v-if ="checkPermission(['exam_create'])">新增</el-button>
|
||||
<el-button
|
||||
class="filter-item"
|
||||
type="primary"
|
||||
icon="el-icon-refresh-left"
|
||||
@click="resetFilter"
|
||||
>刷新重置</el-button>
|
||||
</div>
|
||||
|
||||
<el-table
|
||||
:data="tableData.results"
|
||||
style="width: 100%;margin-top:10px;"
|
||||
border
|
||||
fit
|
||||
v-loading="listLoading"
|
||||
highlight-current-row
|
||||
max-height="600"
|
||||
row-key="id"
|
||||
default-expand-all
|
||||
>
|
||||
<el-table-column label="考试名称">
|
||||
<template slot-scope="scope">{{ scope.row.name }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="考试编号">
|
||||
<template slot-scope="scope">{{ scope.row.code }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="考试地点">
|
||||
<template slot-scope="scope">{{ scope.row.place }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="工作类别">
|
||||
<template slot-scope="scope">{{ scope.row.workscope }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="开启时间">
|
||||
<template slot-scope="scope">{{ scope.row.opentime }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="关闭时间">
|
||||
<template slot-scope="scope">{{ scope.row.closetime }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="创建人">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.create_admin_name }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="操作" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<el-button
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="handleView(scope)"
|
||||
:disabled="!checkPermission(['exam_view'])"
|
||||
>详情</el-button>
|
||||
<el-button
|
||||
size="small"
|
||||
@click="handleEdit(scope)"
|
||||
:disabled="!checkPermission(['exam_update'])"
|
||||
>编辑</el-button>
|
||||
<el-button
|
||||
type="danger"
|
||||
size="small"
|
||||
@click="handleDelete(scope)"
|
||||
:disabled="!checkPermission(['exam_delete'])"
|
||||
>删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<pagination
|
||||
v-show="tableData.count>0"
|
||||
:total="tableData.count"
|
||||
:page.sync="listQuery.page"
|
||||
:limit.sync="listQuery.limit"
|
||||
@pagination="getList"
|
||||
/>
|
||||
<el-dialog :visible.sync="dialogVisible" :title="dialogType==='edit'?'编辑考试':'新增考试'" >
|
||||
<el-form :model="exam" label-width="80px" :rules="rule1" ref="examForm">
|
||||
<el-form-item label="名称" prop="name">
|
||||
<el-input v-model="exam.name" placeholder="名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="考试地点" prop="place">
|
||||
<el-input v-model="exam.place" placeholder="考试地点" />
|
||||
</el-form-item>
|
||||
<el-form-item label="工作类别" prop="workscope" >
|
||||
<el-select v-model="exam.workscope" placeholder="请选择工作类别" style="width:100%">
|
||||
<el-option
|
||||
v-for="item in workscopeOptions"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="开启时间" prop="opentime">
|
||||
<el-date-picker
|
||||
v-model="exam.opentime"
|
||||
type="datetime"
|
||||
placeholder="开启时间"
|
||||
style="width:100%">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item label="关闭时间" prop="closetime">
|
||||
<el-date-picker
|
||||
v-model="exam.closetime"
|
||||
type="datetime"
|
||||
placeholder="关闭时间"
|
||||
style="width:100%"
|
||||
></el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item label="监考人姓名" prop="proctor_name" label-width="120px">
|
||||
<el-input v-model="exam.proctor_name" placeholder="监考人姓名" />
|
||||
</el-form-item>
|
||||
<el-form-item label="监考人联系方式" prop="proctor_phone" label-width="120px">
|
||||
<el-input v-model="exam.proctor_phone" placeholder="监考人联系方式" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div style="text-align:right;">
|
||||
<el-button type="danger" @click="dialogVisible=false">取消</el-button>
|
||||
<el-button type="primary" @click="confirmexam('examForm')">确认</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getexamlist, createexam, deleteexam, updateexam} from "@/api/exam";
|
||||
import { getWorkScopeAll } from "@/api/examtest"
|
||||
import { deepClone } from "@/utils";
|
||||
import checkPermission from "@/utils/permission";
|
||||
import Pagination from "@/components/Pagination"
|
||||
|
||||
|
||||
|
||||
const defaultexam = {
|
||||
id: "",
|
||||
name: "",
|
||||
place: "",
|
||||
opentime: null,
|
||||
closetime: null,
|
||||
};
|
||||
const listQuery = {
|
||||
page: 1,
|
||||
limit: 20,
|
||||
search: ""
|
||||
}
|
||||
export default {
|
||||
components: { Pagination },
|
||||
data() {
|
||||
return {
|
||||
selects:[],
|
||||
exam: {
|
||||
id: "",
|
||||
name: "",
|
||||
},
|
||||
listQuery:listQuery,
|
||||
tableData: {count:0},
|
||||
listLoading: true,
|
||||
dialogVisible: false,
|
||||
dialogType: "new",
|
||||
workscopeOptions:[],
|
||||
rule1: {
|
||||
name: [{ required: true, message: "请输入", trigger: "blur" }],
|
||||
place: [{ required: true, message: "请输入", trigger: "change" }],
|
||||
workscope: [{ required: true, message: "请选择", trigger: "change" }],
|
||||
opentime: [{ required: true, message: "请选择", trigger: "change" }],
|
||||
closetime: [{ required: true, message: "请选择", trigger: "change" }],
|
||||
proctor_name: [{ required: true, message: "请输入", trigger: "change" }],
|
||||
proctor_phone: [{ required: true, message: "请输入", trigger: "change" }]
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {},
|
||||
created() {
|
||||
this.getList();
|
||||
this.getworkscopeOptions();
|
||||
},
|
||||
methods: {
|
||||
checkPermission,
|
||||
getworkscopeOptions(){
|
||||
getWorkScopeAll({can_exam:true}).then(res=>{
|
||||
this.workscopeOptions = res.data
|
||||
})
|
||||
},
|
||||
getList() {
|
||||
this.listLoading = true
|
||||
getexamlist(this.listQuery).then(response => {
|
||||
this.tableData = response.data
|
||||
this.listLoading = false
|
||||
});
|
||||
},
|
||||
resetFilter() {
|
||||
this.listQuery = {
|
||||
page: 1,
|
||||
limit: 20,
|
||||
search: ""
|
||||
};
|
||||
this.getList();
|
||||
},
|
||||
handleFilter() {
|
||||
this.listQuery.page = 1;
|
||||
this.getList();
|
||||
},
|
||||
handleAdd() {
|
||||
this.exam = Object.assign({}, defaultexam);
|
||||
this.dialogType = "new";
|
||||
this.dialogVisible = true;
|
||||
this.$nextTick(() => {
|
||||
this.$refs["examForm"].clearValidate();
|
||||
});
|
||||
},
|
||||
handleEdit(scope) {
|
||||
this.exam = Object.assign({}, scope.row); // copy obj
|
||||
this.dialogType = "edit";
|
||||
this.dialogVisible = true;
|
||||
this.$nextTick(() => {
|
||||
this.$refs["examForm"].clearValidate();
|
||||
});
|
||||
},
|
||||
handleDelete(scope) {
|
||||
this.$confirm("确认删除该考试吗?将丢失数据!", "警告", {
|
||||
confirmButtonText: "确认",
|
||||
cancelButtonText: "取消",
|
||||
type: "error"
|
||||
})
|
||||
.then(async () => {
|
||||
await deleteexam(scope.row.id);
|
||||
this.getList()
|
||||
this.$message({
|
||||
type: "success",
|
||||
message: "成功删除!"
|
||||
});
|
||||
})
|
||||
.catch(err => {
|
||||
// console.error(err);
|
||||
});
|
||||
},
|
||||
handleView(scope){
|
||||
this.$router.push({name:'ExamTest', params:{exam:scope.row.id}})
|
||||
|
||||
},
|
||||
async confirmexam(form) {
|
||||
this.$refs[form].validate(valid => {
|
||||
if (valid) {
|
||||
const isEdit = this.dialogType === "edit";
|
||||
if (isEdit) {
|
||||
updateexam(this.exam.id, this.exam).then(() => {
|
||||
this.getList();
|
||||
this.dialogVisible = false;
|
||||
this.$message.success('成功')
|
||||
});
|
||||
} else {
|
||||
createexam(this.exam).then(res => {
|
||||
// this.exam = res.data
|
||||
// this.tableData.unshift(this.exam)
|
||||
this.getList();
|
||||
this.dialogVisible = false;
|
||||
this.$message.success('成功')
|
||||
});
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
@ -20,14 +20,20 @@
|
|||
row-key="id"
|
||||
>
|
||||
<el-table-column type="index" width="50"></el-table-column>
|
||||
<el-table-column align="center" label="名称">
|
||||
<el-table-column label="名称">
|
||||
<template slot-scope="scope">{{ scope.row.name }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="所属学科">
|
||||
<el-table-column label="所属学科">
|
||||
<template slot-scope="scope">
|
||||
<el-tag type="success" >{{scope.row.subject_name}}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="是否可组织考试">
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.can_exam">是</el-tag>
|
||||
<el-tag type="warning" v-else>否</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="创建日期">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.create_time }}</span>
|
||||
|
|
|
|||
|
|
@ -10,6 +10,9 @@
|
|||
<el-form-item label="工作类别" prop="name">
|
||||
<el-input v-model="Form.name" style="width:400px"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="是否可组织考试" prop="can_exam" label-width="120px">
|
||||
<el-switch v-model="Form.can_exam"></el-switch>
|
||||
</el-form-item>
|
||||
<el-form-item label="所属学科" prop="subject">
|
||||
<el-select v-model="Form.subject" placeholder="请选择所属学科" style="width:400px">
|
||||
<el-option
|
||||
|
|
@ -57,6 +60,7 @@ export default {
|
|||
return {
|
||||
Form: {
|
||||
name: "",
|
||||
can_exam:false,
|
||||
subject: null,
|
||||
questioncat: [],
|
||||
},
|
||||
|
|
|
|||
|
|
@ -10,6 +10,9 @@
|
|||
<el-form-item label="工作类别" prop="name">
|
||||
<el-input v-model="Form.name" style="width:400px"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="是否可组织考试" prop="can_exam" label-width="120px">
|
||||
<el-switch v-model="Form.can_exam"></el-switch>
|
||||
</el-form-item>
|
||||
<el-form-item label="所属学科" prop="subject">
|
||||
<el-select v-model="Form.subject" placeholder="请选择所属学科" style="width:400px">
|
||||
<el-option
|
||||
|
|
@ -57,6 +60,7 @@ export default {
|
|||
return {
|
||||
Form: {
|
||||
name: "",
|
||||
can_exam:false,
|
||||
subject: null,
|
||||
questioncat: [],
|
||||
},
|
||||
|
|
|
|||
|
|
@ -43,10 +43,13 @@
|
|||
<span v-else>{{ scope.row.name }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="header-center" label="类型">
|
||||
<el-table-column label="类型">
|
||||
<template slot-scope="scope">{{ scope.row.type }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="header-center" label="上传时间">
|
||||
<el-table-column align="header-center" label="排序码">
|
||||
<template slot-scope="scope">{{ scope.row.sort }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="上传时间">
|
||||
<template slot-scope="scope">{{ scope.row.create_time }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="header-center" label="下载量/播放量">
|
||||
|
|
@ -96,6 +99,9 @@
|
|||
<el-form-item label="描述" prop="description">
|
||||
<el-input v-model="material.description" placeholder="描述" />
|
||||
</el-form-item>
|
||||
<el-form-item label="排序" prop="description">
|
||||
<el-input-number v-model="material.sort" :min="1"></el-input-number>
|
||||
</el-form-item>
|
||||
<!-- <el-form-item label="封面" prop="poster" v-if="material.type=='视频'">
|
||||
<el-upload
|
||||
accept=".png, .jpeg, .jpg"
|
||||
|
|
@ -334,12 +340,7 @@ export default {
|
|||
if (res.code >= 200) {
|
||||
this.getList();
|
||||
this.dialogVisible = false;
|
||||
this.$notify({
|
||||
title: "成功",
|
||||
message: "编辑成功",
|
||||
type: "success",
|
||||
duration: 2000,
|
||||
});
|
||||
this.$message.success('成功')
|
||||
}
|
||||
});
|
||||
} else {
|
||||
|
|
@ -347,10 +348,7 @@ export default {
|
|||
.then((res) => {
|
||||
this.getList();
|
||||
this.dialogVisible = false;
|
||||
this.$notify({
|
||||
title: "成功",
|
||||
type: "success",
|
||||
});
|
||||
this.$message.success('成功')
|
||||
})
|
||||
.catch((error) => {});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -229,12 +229,7 @@ export default {
|
|||
() => {
|
||||
this.getList();
|
||||
this.dialogVisible = false;
|
||||
this.$notify({
|
||||
title: "成功",
|
||||
message: "编辑成功",
|
||||
type: "success",
|
||||
duration: 2000
|
||||
});
|
||||
this.$message.success('成功')
|
||||
}
|
||||
);
|
||||
} else {
|
||||
|
|
@ -243,12 +238,7 @@ export default {
|
|||
// this.tableData.unshift(this.questioncat)
|
||||
this.getList();
|
||||
this.dialogVisible = false;
|
||||
this.$notify({
|
||||
title: "成功",
|
||||
message: "新增成功",
|
||||
type: "success",
|
||||
duration: 2000
|
||||
});
|
||||
this.$message.success('成功')
|
||||
});
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -155,12 +155,7 @@ export default {
|
|||
() => {
|
||||
this.getList();
|
||||
this.dialogVisible = false;
|
||||
this.$notify({
|
||||
title: "成功",
|
||||
message: "编辑成功",
|
||||
type: "success",
|
||||
duration: 2000
|
||||
});
|
||||
this.$message.success('成功')
|
||||
}
|
||||
);
|
||||
} else {
|
||||
|
|
@ -169,12 +164,7 @@ export default {
|
|||
// this.tableData.unshift(this.subject)
|
||||
this.getList();
|
||||
this.dialogVisible = false;
|
||||
this.$notify({
|
||||
title: "成功",
|
||||
message: "新增成功",
|
||||
type: "success",
|
||||
duration: 2000
|
||||
});
|
||||
this.$message.success('成功')
|
||||
});
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -201,12 +201,7 @@ export default {
|
|||
updateBanner(this.banner.id, this.banner).then(() => {
|
||||
this.getList();
|
||||
this.dialogVisible = false;
|
||||
this.$notify({
|
||||
title: "成功",
|
||||
message: "编辑成功",
|
||||
type: "success",
|
||||
duration: 2000
|
||||
});
|
||||
this.$message.success('成功')
|
||||
});
|
||||
} else {
|
||||
createBanner(this.banner).then(res => {
|
||||
|
|
@ -214,12 +209,7 @@ export default {
|
|||
// this.tableData.unshift(this.banner)
|
||||
this.getList();
|
||||
this.dialogVisible = false;
|
||||
this.$notify({
|
||||
title: "成功",
|
||||
message: "新增成功",
|
||||
type: "success",
|
||||
duration: 2000
|
||||
});
|
||||
this.$message.success('成功')
|
||||
});
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -180,12 +180,7 @@ export default {
|
|||
updateOrg(this.org.id, this.org).then(() => {
|
||||
this.getList();
|
||||
this.dialogVisible = false;
|
||||
this.$notify({
|
||||
title: "成功",
|
||||
message: "编辑成功",
|
||||
type: "success",
|
||||
duration: 2000
|
||||
});
|
||||
this.$message.success('成功')
|
||||
});
|
||||
} else {
|
||||
this.org.pid = this.org.pid.pop()
|
||||
|
|
@ -194,12 +189,7 @@ export default {
|
|||
// this.tableData.unshift(this.org)
|
||||
this.getList();
|
||||
this.dialogVisible = false;
|
||||
this.$notify({
|
||||
title: "成功",
|
||||
message: "新增成功",
|
||||
type: "success",
|
||||
duration: 2000
|
||||
});
|
||||
this.$message.success('成功')
|
||||
});
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -377,12 +377,7 @@ export default {
|
|||
}
|
||||
}
|
||||
this.dialogVisible = false;
|
||||
this.$notify({
|
||||
title: "成功",
|
||||
message: "编辑成功",
|
||||
type: "success",
|
||||
duration: 2000
|
||||
});
|
||||
this.$message.success('成功')
|
||||
});
|
||||
} else {
|
||||
this.user.department = this.user.department.pop();
|
||||
|
|
@ -391,12 +386,7 @@ export default {
|
|||
// this.userList.unshift(this.user)
|
||||
this.getList();
|
||||
this.dialogVisible = false;
|
||||
this.$notify({
|
||||
title: "成功",
|
||||
message: "新增成功",
|
||||
type: "success",
|
||||
duration: 2000
|
||||
});
|
||||
this.$message.success('成功')
|
||||
});
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -29,7 +29,9 @@
|
|||
"pages/candidate/detail",
|
||||
"pages/material/video",
|
||||
"pages/qtest/form",
|
||||
"pages/main/start"
|
||||
"pages/main/start",
|
||||
"pages/exam/index",
|
||||
"pages/exam/note"
|
||||
],
|
||||
"window": {
|
||||
"backgroundTextStyle": "light",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
"use strict";function e(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}/*!
|
||||
* mp-html v2.0.5
|
||||
* https://github.com/jin-yufeng/mp-html
|
||||
*
|
||||
* Released under the MIT license
|
||||
* Author: Jin Yufeng
|
||||
*/
|
||||
var t=require("./parser"),n=[];Component({data:{nodes:[]},properties:{content:{type:String,value:"",observer:function(e){this.setContent(e)}},copyLink:{type:Boolean,value:!0},domain:String,errorImg:String,lazyLoad:Boolean,loadingImg:String,pauseVideo:{type:Boolean,value:!0},previewImg:{type:Boolean,value:!0},scrollTable:Boolean,selectable:null,setTitle:{type:Boolean,value:!0},showImgMenu:{type:Boolean,value:!0},tagStyle:Object,useAnchor:null},created:function(){this.plugins=[];for(var e=n.length;e--;)this.plugins.push(new n[e](this))},detached:function(){clearInterval(this._timer),this._hook("onDetached")},methods:{in:function(e,t,n){e&&t&&n&&(this._in={page:e,selector:t,scrollTop:n})},navigateTo:function(t,n){var o=this;return new Promise(function(i,r){if(!o.data.useAnchor)return r("Anchor is disabled");var a=wx.createSelectorQuery().in(o._in?o._in.page:o).select((o._in?o._in.selector:"._root")+(t?"".concat(">>>","#").concat(t):"")).boundingClientRect();o._in?a.select(o._in.selector).scrollOffset().select(o._in.selector).boundingClientRect():a.selectViewport().scrollOffset(),a.exec(function(t){if(!t[0])return r("Label not found");var a=t[1].scrollTop+t[0].top-(t[2]?t[2].top:0)+(n||parseInt(o.data.useAnchor)||0);o._in?o._in.page.setData(e({},o._in.scrollTop,a)):wx.pageScrollTo({scrollTop:a,duration:300}),i()})})},getText:function(e){var t="";return function e(n){for(var o=0;o<n.length;o++){var i=n[o];if("text"==i.type)t+=i.text.replace(/&/g,"&");else if("br"==i.name)t+="\n";else{var r="p"==i.name||"div"==i.name||"tr"==i.name||"li"==i.name||"h"==i.name[0]&&i.name[1]>"0"&&i.name[1]<"7";r&&t&&"\n"!=t[t.length-1]&&(t+="\n"),i.children&&e(i.children),r&&"\n"!=t[t.length-1]?t+="\n":"td"!=i.name&&"th"!=i.name||(t+="\t")}}}(e||this.data.nodes),t},getRect:function(){var e=this;return new Promise(function(t,n){wx.createSelectorQuery().in(e).select("._root").boundingClientRect().exec(function(e){return e[0]?t(e[0]):n("Root label not found")})})},setContent:function(e,n){var o=this;this.imgList&&n||(this.imgList=[]),this._videos=[];var i={},r=new t(this).parse(e);if(n)for(var a=this.data.nodes.length,l=r.length;l--;)i["nodes[".concat(a+l,"]")]=r[l];else i.nodes=r;this.setData(i,function(){o._hook("onLoad"),o.triggerEvent("load")});var s;clearInterval(this._timer),this._timer=setInterval(function(){o.getRect().then(function(e){e.height==s&&(o.triggerEvent("ready",e),clearInterval(o._timer)),s=e.height}).catch(function(){})},350)},_hook:function(e){for(var t=n.length;t--;)this.plugins[t][e]&&this.plugins[t][e]()},_add:function(e){e.detail.root=this}}});
|
||||
|
|
@ -0,0 +1 @@
|
|||
{"component":true,"usingComponents":{"node":"./node/node"}}
|
||||
|
|
@ -0,0 +1 @@
|
|||
<view class="_root {{selectable?'_select':''}}"><slot wx:if="{{!nodes[0]}}"/><node id="_root" childs="{{nodes}}" opts="{{[lazyLoad,loadingImg,errorImg,showImgMenu]}}" catchadd="_add"/></view>
|
||||
|
|
@ -0,0 +1 @@
|
|||
._root{padding:1px 0;overflow-x:auto;overflow-y:hidden;-webkit-overflow-scrolling:touch}._select{-webkit-user-select:text;user-select:text}
|
||||
|
|
@ -0,0 +1 @@
|
|||
"use strict";function t(t,e,i){return e in t?Object.defineProperty(t,e,{value:i,enumerable:!0,configurable:!0,writable:!0}):t[e]=i,t}Component({data:{ctrl:{}},properties:{childs:Array,opts:Array},attached:function(){this.triggerEvent("add",this,{bubbles:!0,composed:!0})},methods:{noop:function(){},getNode:function(t){for(var e=t.split("_"),i=this.data.childs[e[0]],r=1;r<e.length;r++)i=i.children[e[r]];return i},play:function(t){if(this.root.data.pauseVideo){for(var e=!1,i=t.target.id,r=this.root._videos.length;r--;)this.root._videos[r].id==i?e=!0:this.root._videos[r].pause();if(!e){var s=wx.createVideoContext(i,this);s.id=i,this.root._videos.push(s)}}},imgTap:function(t){var e=this.getNode(t.target.dataset.i);if(e.a)return this.linkTap(e.a);if(!e.attrs.ignore&&(this.root.triggerEvent("imgtap",e.attrs),this.root.data.previewImg)){var i=this.root.imgList[e.i];wx.previewImage({current:i,urls:this.root.imgList})}},imgLoad:function(e){var i,r=e.target.dataset.i,s=this.getNode(r);s.w?(this.data.opts[1]&&!this.data.ctrl[r]||-1==this.data.ctrl[r])&&(i=1):i=e.detail.width,i&&this.setData(t({},"ctrl."+r,i))},linkTap:function(t){var e=t.currentTarget?this.getNode(t.currentTarget.dataset.i):{},i=e.attrs||t,r=i.href;this.root.triggerEvent("linktap",Object.assign({innerText:this.root.getText(e.children||[])},i)),r&&("#"==r[0]?this.root.navigateTo(r.substring(1)).catch(function(){}):r.includes("://")?this.root.data.copyLink&&wx.setClipboardData({data:r,success:function(){return wx.showToast({title:"链接已复制"})}}):wx.navigateTo({url:r,fail:function(){wx.switchTab({url:r,fail:function(){}})}}))},mediaError:function(e){var i=e.target.dataset.i,r=this.getNode(i);if("video"==r.name||"audio"==r.name){var s=(this.data.ctrl[i]||0)+1;if(s>r.src.length&&(s=0),s<r.src.length)return this.setData(t({},"ctrl."+i,s))}else"img"==r.name&&this.data.opts[2]&&this.setData(t({},"ctrl."+i,-1));this.root&&this.root.triggerEvent("error",{source:r.name,attrs:r.attrs,errMsg:e.detail.errMsg})}}});
|
||||
|
|
@ -0,0 +1 @@
|
|||
{"component":true,"usingComponents":{"node":"./node"}}
|
||||
|
|
@ -0,0 +1 @@
|
|||
<wxs module="use">var e={abbr:!0,b:!0,big:!0,code:!0,del:!0,em:!0,i:!0,ins:!0,label:!0,q:!0,small:!0,span:!0,strong:!0,sub:!0,sup:!0};module.exports=function(n){return!(e[n.name]||n.children&&-1!=(n.attrs.style||"").indexOf("inline"))&&!n.c};</wxs><template name="el"><block wx:if="{{n.name=='img'}}"><image wx:if="{{(opts[1]&&!ctrl[i])||ctrl[i]<0}}" class="_img" style="{{n.attrs.style}}" src="{{ctrl[i]<0?opts[2]:opts[1]}}" mode="widthFix"/><image id="{{n.attrs.id}}" class="_img {{n.attrs.class}}" style="{{ctrl[i]==-1?'display:none;':''}}width:{{ctrl[i]||1}}px;height:1px;{{n.attrs.style}}" src="{{n.attrs.src}}" mode="{{n.h?'':'widthFix'}}" lazy-load="{{opts[0]}}" webp="{{n.webp}}" show-menu-by-longpress="{{opts[3]&&!n.attrs.ignore}}" data-i="{{i}}" bindload="imgLoad" binderror="mediaError" catchtap="imgTap" bindlongpress="noop"/></block><text wx:elif="{{n.type=='text'}}" user-select="{{n.us}}" decode>{{n.text}}</text><text wx:elif="{{n.name=='br'}}">\n</text><view wx:elif="{{n.name=='a'}}" id="{{n.attrs.id}}" class="{{n.attrs.href?'_a ':''}}{{n.attrs.class}}" hover-class="_hover" style="display:inline;{{n.attrs.style}}" data-i="{{i}}" catchtap="linkTap"><node childs="{{n.children}}" opts="{{opts}}" style="display:inherit"/></view><video wx:elif="{{n.name=='video'}}" id="{{n.attrs.id}}" class="{{n.attrs.class}}" style="{{n.attrs.style}}" autoplay="{{n.attrs.autoplay}}" controls="{{n.attrs.controls}}" loop="{{n.attrs.loop}}" muted="{{n.attrs.muted}}" poster="{{n.attrs.poster}}" src="{{n.src[ctrl[i]||0]}}" data-i="{{i}}" bindplay="play" binderror="mediaError"/><audio wx:elif="{{n.name=='audio'}}" id="{{n.attrs.id}}" class="{{n.attrs.class}}" style="{{n.attrs.style}}" author="{{n.attrs.author}}" controls="{{n.attrs.controls}}" loop="{{n.attrs.loop}}" name="{{n.attrs.name}}" poster="{{n.attrs.poster}}" src="{{n.src[ctrl[i]||0]}}" data-i="{{i}}" bindplay="play" binderror="mediaError"/><rich-text wx:else id="{{n.attrs.id}}" style="{{n.f}}" nodes="{{[n]}}"/></template><block wx:for="{{childs}}" wx:for-item="n1" wx:for-index="i1" wx:key="i1"><template wx:if="{{use(n1)}}" is="el" data="{{n:n1,i:''+i1,opts:opts,ctrl:ctrl}}"/><view wx:else id="{{n1.attrs.id}}" class="_{{n1.name}} {{n1.attrs.class}}" style="{{n1.attrs.style}}"><block wx:for="{{n1.children}}" wx:for-item="n2" wx:for-index="i2" wx:key="i2"><template wx:if="{{use(n2)}}" is="el" data="{{n:n2,i:i1+'_'+i2,opts:opts,ctrl:ctrl}}"/><view wx:else id="{{n2.attrs.id}}" class="_{{n2.name}} {{n2.attrs.class}}" style="{{n2.attrs.style}}"><block wx:for="{{n2.children}}" wx:for-item="n3" wx:for-index="i3" wx:key="i3"><template wx:if="{{use(n3)}}" is="el" data="{{n:n3,i:i1+'_'+i2+'_'+i3,opts:opts,ctrl:ctrl}}"/><view wx:else id="{{n3.attrs.id}}" class="_{{n3.name}} {{n3.attrs.class}}" style="{{n3.attrs.style}}"><block wx:for="{{n3.children}}" wx:for-item="n4" wx:for-index="i4" wx:key="i4"><template wx:if="{{use(n4)}}" is="el" data="{{n:n4,i:i1+'_'+i2+'_'+i3+'_'+i4,opts:opts,ctrl:ctrl}}"/><view wx:else id="{{n4.attrs.id}}" class="_{{n4.name}} {{n4.attrs.class}}" style="{{n4.attrs.style}}"><block wx:for="{{n4.children}}" wx:for-item="n5" wx:for-index="i5" wx:key="i5"><template wx:if="{{use(n5)}}" is="el" data="{{n:n5,i:i1+'_'+i2+'_'+i3+'_'+i4+'_'+i5,opts:opts,ctrl:ctrl}}"/><node wx:else id="{{n5.attrs.id}}" class="_{{n5.name}} {{n5.attrs.class}}" style="{{n5.attrs.style}}" childs="{{n5.children}}" opts="{{opts}}"/></block></view></block></view></block></view></block></view></block>
|
||||
|
|
@ -0,0 +1 @@
|
|||
._a{padding:1.5px 0 1.5px 0;color:#366092;word-break:break-all}._hover{text-decoration:underline;opacity:.7}._img{max-width:100%;-webkit-touch-callout:none}._b,._strong{font-weight:700}._code{font-family:monospace}._del{text-decoration:line-through}._em,._i{font-style:italic}._h1{font-size:2em}._h2{font-size:1.5em}._h3{font-size:1.17em}._h5{font-size:.83em}._h6{font-size:.67em}._h1,._h2,._h3,._h4,._h5,._h6{display:block;font-weight:700}._ins{text-decoration:underline}._li{display:list-item}._ol{list-style-type:decimal}._ol,._ul{display:block;padding-left:40px;margin:1em 0}._q::before{content:'"'}._q::after{content:'"'}._sub{font-size:smaller;vertical-align:sub}._sup{font-size:smaller;vertical-align:super}._tbody,._tfoot,._thead{display:table-row-group}._tr{display:table-row}._td,._th{display:table-cell;vertical-align:middle}._th{font-weight:700;text-align:center}._ul{list-style-type:disc}._ul ._ul{margin:0;list-style-type:circle}._ul ._ul ._ul{list-style-type:square}._abbr,._b,._code,._del,._em,._i,._ins,._label,._q,._span,._strong,._sub,._sup{display:inline}._blockquote,._div,._p{display:block}
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1 @@
|
|||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1615988351221" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4995" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><defs><style type="text/css"></style></defs><path d="M504.5248 189.7472c-43.7248-25.1904-99.4304-13.1072-128.8192 27.9552l-15.36 21.6064c-31.8464 44.544-72.6016 82.0224-119.808 109.8752l-106.1888 62.7712C97.792 433.5616 79.36 476.16 88.4736 517.5296l106.496 482.304 159.5392-276.2752-5.9392-5.0176c-51.9168-46.7968-66.7648-123.2896-31.6416-184.1152 40.6528-70.3488 132.7104-93.2864 205.6192-51.0976 73.0112 42.0864 99.2256 133.2224 58.5728 203.6736l-4.096 6.5536c-37.888 58.2656-112.64 80.4864-178.4832 55.5008L240.2304 1022.7712 709.632 876.032c40.5504-12.6976 68.3008-49.8688 68.8128-92.3648l1.4336-121.2416c0.7168-54.784 12.9024-108.8512 35.7376-158.6176l11.5712-25.088c21.0944-45.9776 3.7888-100.4544-40.0384-125.8496l-282.624-163.1232zM586.752 10.6496C569.856 0.9216 549.7856-1.7408 530.944 3.2768c-18.8416 5.0176-34.9184 17.408-44.6464 34.304l-2.7648 5.3248c-16.384 34.6112-3.4816 75.9808 29.696 95.1296l312.9344 180.6336c16.896 9.728 36.9664 12.3904 55.808 7.3728 18.8416-5.0176 34.9184-17.408 44.6464-34.304l2.8672-5.3248c16.384-34.6112 3.3792-76.0832-29.7984-95.1296L586.752 10.6496z m0 0" p-id="4996" fill="#d81e06"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"usingComponents": {
|
||||
"parser": "/components/parser/parser"
|
||||
"mp-html": "/components/mp-html/index"
|
||||
}
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@
|
|||
<span class="page__desc">{{ifrom}}</span>
|
||||
</view>
|
||||
<view class="weui-article__p">
|
||||
<parser html="{{content}}" domain="{{domain}}" selectable/>
|
||||
<mp-html content="{{content}}" domain="{{domain}}"/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"usingComponents": {
|
||||
"parser": "/components/parser/parser"
|
||||
"mp-html": "/components/mp-html/index"
|
||||
},
|
||||
"navigationBarTitleText": "收藏集"
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@
|
|||
<span style="color:gray"> {{tm_current.questioncat_name}}</span>
|
||||
</view>
|
||||
<view class="weui-article__title">
|
||||
<rich-text nodes="{{tm_current.name}}"></rich-text>
|
||||
<mp-html content="{{tm_current.name}}" domain="{{domain}}"/>
|
||||
</view>
|
||||
<view wx:if="{{tm_current.img}}" style="text-align:center"><image src="{{tm_current.img}}" mode="aspectFit"></image></view>
|
||||
</view>
|
||||
|
|
@ -17,7 +17,9 @@
|
|||
<label class="weui-cell weui-cell_active weui-check__label" wx:for="{{options}}" wx:key="key">
|
||||
<view class="weui-cell__bd">
|
||||
<view style="float:left;width:10%">{{item.key}}:</view>
|
||||
<view style="float:left;width:90%"><rich-text nodes="{{item.value}}"></rich-text></view>
|
||||
<view style="float:left;width:90%">
|
||||
<mp-html content="{{item.value}}" domain="{{domain}}"/>
|
||||
</view>
|
||||
</view>
|
||||
<view class="weui-cell__ft">
|
||||
<radio class="weui-check" value="{{item.key}}" checked="{{item.checked}}" />
|
||||
|
|
@ -32,7 +34,9 @@
|
|||
|
||||
<view class="weui-cell__bd">
|
||||
<view style="float:left;width:10%">{{item.key}}:</view>
|
||||
<view style="float:left;width:90%"><rich-text nodes="{{item.value}}"></rich-text></view>
|
||||
<view style="float:left;width:90%">
|
||||
<mp-html content="{{item.value}}" domain="{{domain}}"/>
|
||||
</view>
|
||||
</view>
|
||||
<view class="weui-cell__hd">
|
||||
<checkbox class="weui-check" value="{{item.key}}" checked="{{item.checked}}"/>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"usingComponents": {
|
||||
"parser": "/components/parser/parser"
|
||||
"mp-html": "/components/mp-html/index"
|
||||
},
|
||||
"navigationBarTitleText": "错题集"
|
||||
}
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
<span style="color:gray"> {{currentTm.questioncat_name}}</span>
|
||||
</view>
|
||||
<view class="weui-article__title">
|
||||
<rich-text nodes="{{currentTm.name}}"></rich-text>
|
||||
<mp-html content="{{currentTm.name}}" domain="{{domain}}"/>
|
||||
</view>
|
||||
<view wx:if="{{currentTm.img}}" style="text-align:center"><image src="{{currentTm.img}}" mode="aspectFit"></image></view>
|
||||
</view>
|
||||
|
|
@ -23,7 +23,7 @@
|
|||
<label class="weui-cell weui-cell_active weui-check__label" wx:for="{{options}}" wx:key="key">
|
||||
<view class="weui-cell__bd">
|
||||
<view style="float:left;width:10%">{{item.key}}:</view>
|
||||
<view style="float:left;width:90%"><rich-text nodes="{{item.value}}"></rich-text></view>
|
||||
<view style="float:left;width:90%"><mp-html content="{{item.value}}" domain="{{domain}}"/></view>
|
||||
</view>
|
||||
<view class="weui-cell__ft">
|
||||
<radio class="weui-check" value="{{item.key}}" checked="{{item.checked}}" />
|
||||
|
|
@ -38,7 +38,7 @@
|
|||
|
||||
<view class="weui-cell__bd">
|
||||
<view style="float:left;width:10%">{{item.key}}:</view>
|
||||
<view style="float:left;width:90%"><rich-text nodes="{{item.value}}"></rich-text></view>
|
||||
<view style="float:left;width:90%"><mp-html content="{{item.value}}" domain="{{domain}}"/></view>
|
||||
</view>
|
||||
<view class="weui-cell__hd">
|
||||
<checkbox class="weui-check" value="{{item.key}}" checked="{{item.checked}}"/>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,127 @@
|
|||
// pages/qtest/form.js
|
||||
const api = require("../../utils/request.js");
|
||||
Page({
|
||||
|
||||
/**
|
||||
* 页面的初始数据
|
||||
*/
|
||||
data: {
|
||||
userInfo:{},
|
||||
form:{
|
||||
deptname:null,
|
||||
code:null
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
deptInput: function(e){
|
||||
this.data.form.deptname = e.detail.value
|
||||
},
|
||||
codeinput: function(e){
|
||||
this.data.form.code = e.detail.value
|
||||
},
|
||||
submit: function(){
|
||||
if(this.data.form.deptname&&this.data.form.code){
|
||||
wx.showToast({
|
||||
title: '加入考试成功',
|
||||
icon:'none'
|
||||
})
|
||||
let data = this.data.form
|
||||
api.request('/examtest/exam/attend/','POST', data).then(res=>{
|
||||
wx.showLoading({
|
||||
title: '正在组卷。。。',
|
||||
mask:true
|
||||
})
|
||||
let exam = res.data.exam
|
||||
api.request(`/examtest/exam/${exam}/init/`,'POST', data).then(res=>{
|
||||
wx.hideLoading()
|
||||
try {
|
||||
wx.setStorageSync('examtest', res.data)
|
||||
} catch (e) { }
|
||||
wx.navigateTo({
|
||||
url: '/pages/exam/note',
|
||||
})
|
||||
|
||||
}).catch(e=>{
|
||||
wx.hideLoading({
|
||||
success: (res) => {},
|
||||
})
|
||||
})
|
||||
})
|
||||
}else{
|
||||
wx.showToast({
|
||||
title: '信息不完整',
|
||||
icon:'none'
|
||||
})
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 生命周期函数--监听页面加载
|
||||
*/
|
||||
onLoad: function (options) {
|
||||
wx.showLoading({
|
||||
title: '获取信息...',
|
||||
})
|
||||
api.request('/crm/consumer/info/','GET').then(res=>{
|
||||
wx.hideLoading()
|
||||
getApp().globalData.userinfo = res.data.userinfo
|
||||
this.setData(
|
||||
{
|
||||
userinfo: res.data.userinfo,
|
||||
form:{
|
||||
deptname:res.data.userinfo.deptname
|
||||
},
|
||||
}
|
||||
)
|
||||
}).catch(e=>{wx.hideLoading()})
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面初次渲染完成
|
||||
*/
|
||||
onReady: function () {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面显示
|
||||
*/
|
||||
onShow: function () {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面隐藏
|
||||
*/
|
||||
onHide: function () {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面卸载
|
||||
*/
|
||||
onUnload: function () {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 页面相关事件处理函数--监听用户下拉动作
|
||||
*/
|
||||
onPullDownRefresh: function () {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 页面上拉触底事件的处理函数
|
||||
*/
|
||||
onReachBottom: function () {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 用户点击右上角分享
|
||||
*/
|
||||
onShareAppMessage: function () {
|
||||
|
||||
}
|
||||
})
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"usingComponents": {}
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
<view >
|
||||
<view class="weui-form__text-area" style="margin-top:20px;padding: 0 18px;">
|
||||
<h2 class="weui-form__title">正式考试</h2>
|
||||
<view class="weui-form__desc">请确认和完善个人信息,并输入考试号加入考试,如有问题请及时联系老师</view>
|
||||
</view>
|
||||
|
||||
<view>
|
||||
<view class="weui-cells__title">个人信息</view>
|
||||
<view class="weui-cells weui-cells_form">
|
||||
<view class="weui-cell weui-cell_active">
|
||||
<view class="weui-cell__hd"><label class="weui-label">姓名</label></view>
|
||||
<view class="weui-cell__bd">
|
||||
{{userinfo.name}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="weui-cell weui-cell_active">
|
||||
<view class="weui-cell__hd"><label class="weui-label">身份证号</label></view>
|
||||
<view class="weui-cell__bd">
|
||||
{{userinfo.ID_number1}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="weui-cell weui-cell_active">
|
||||
<view class="weui-cell__hd">
|
||||
<label class="weui-label">单位</label>
|
||||
</view>
|
||||
<view class="weui-cell__bd">
|
||||
{{userinfo.company_name}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="weui-cell weui-cell_active">
|
||||
<view class="weui-cell__hd">
|
||||
<label class="weui-label">部门</label>
|
||||
</view>
|
||||
<view class="weui-cell__bd">
|
||||
<!-- <span wx:if="{{userinfo.deptname}}">{{userinfo.deptname}}</span> -->
|
||||
<input class="weui-input" placeholder="填写您的部门" placeholder-class="weui-input__placeholder" bindinput="deptInput" value="{{form.deptname}}">
|
||||
</input>
|
||||
</view>
|
||||
</view>
|
||||
<view class="weui-cell weui-cell_active">
|
||||
<view class="weui-cell__hd">
|
||||
<label class="weui-label">考试号</label>
|
||||
</view>
|
||||
<view class="weui-cell__bd">
|
||||
<input class="weui-input" placeholder="填写要加入的考试号" placeholder-class="weui-input__placeholder" bindinput="codeinput" >
|
||||
|
||||
</input>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="weui-form__tips-area">
|
||||
<!-- <view class="weui-form__tips">
|
||||
表单页提示,居中对齐
|
||||
</view> -->
|
||||
</view>
|
||||
<view class="weui-form__opr-area">
|
||||
<a class="weui-btn weui-btn_primary" bindtap="submit">确认</a>
|
||||
</view>
|
||||
</view>
|
||||
|
|
@ -0,0 +1 @@
|
|||
/* pages/exam/index.wxss */
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
// pages/exam/note.js
|
||||
Page({
|
||||
|
||||
/**
|
||||
* 页面的初始数据
|
||||
*/
|
||||
data: {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面加载
|
||||
*/
|
||||
onLoad: function (options) {
|
||||
try {
|
||||
var value = wx.getStorageSync('examtest')
|
||||
if (value) {
|
||||
let examtest = value
|
||||
delete examtest['questions']
|
||||
this.setData(examtest)
|
||||
}
|
||||
} catch (e) { }
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面初次渲染完成
|
||||
*/
|
||||
onReady: function () {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面显示
|
||||
*/
|
||||
onShow: function () {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面隐藏
|
||||
*/
|
||||
onHide: function () {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面卸载
|
||||
*/
|
||||
onUnload: function () {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 页面相关事件处理函数--监听用户下拉动作
|
||||
*/
|
||||
onPullDownRefresh: function () {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 页面上拉触底事件的处理函数
|
||||
*/
|
||||
onReachBottom: function () {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 用户点击右上角分享
|
||||
*/
|
||||
onShareAppMessage: function () {
|
||||
|
||||
},
|
||||
startTest: function () {
|
||||
wx.reLaunch({
|
||||
url: '/pages/test/test',
|
||||
})
|
||||
},
|
||||
})
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"usingComponents": {},
|
||||
"navigationBarTitleText": "考试须知"
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
<view class="page">
|
||||
<view class="page__bd">
|
||||
<view class="weui-article">
|
||||
<view class="weui-article__h1" style="text-align:center">正式考试须知</view>
|
||||
<view class="weui-article__h2">1.考试信息</view>
|
||||
<view>名称:<span style="color:blue">{{exam_.name}}</span></view>
|
||||
<view>监考人:<span style="color:blue">{{exam_.proctor_name}}/{{exam_.proctor_phone}}</span></view>
|
||||
<view class="weui-article__h2">2.试卷信息</view>
|
||||
<view>答卷时长:<span style="color:red">{{limit}}分钟</span></view>
|
||||
<view wx:if="{{danxuan_count>0}}">{{danxuan_count}}道单选题,每题{{danxuan_score}}分</view>
|
||||
<view wx:if="{{duoxuan_count>0}}">{{duoxuan_count}}道多选题,每题{{duoxuan_score}}分</view>
|
||||
<view wx:if="{{panduan_count>0}}">{{panduan_count}}道判断题,每题{{panduan_score}}分</view>
|
||||
<view >多选题漏选每个正确选项得1分,错选0分</view>
|
||||
<view >满分{{total_score}};<span style="color:blue">{{pass_score}}</span>以上通过</view>
|
||||
<view class="weui-article__h2">3.答题须知</view>
|
||||
<view style="color:red">进入答题后请不要后退或返回桌面</view>
|
||||
<view>用户可点击上一题/下一题进行切换答题</view>
|
||||
<view>可点击答题卡复查</view>
|
||||
<view>请合理安排时间答题,可提前交卷,超时会自动提交</view>
|
||||
</view>
|
||||
<a class="weui-btn weui-btn_primary" bindtap="startTest">开始考试</a>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
|
@ -0,0 +1 @@
|
|||
/* pages/exam/note.wxss */
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"usingComponents": {
|
||||
"parser": "/components/parser/parser"
|
||||
"mp-html": "/components/mp-html/index"
|
||||
},
|
||||
"navigationBarTitleText": "练习"
|
||||
}
|
||||
|
|
@ -13,8 +13,7 @@
|
|||
<span class="txlabel">{{tm_current.type}}</span>
|
||||
</view>
|
||||
<view class="weui-article__title">
|
||||
<!-- <parser html="{{tm_current.name}}" domain="{{domain}}" selectable/> -->
|
||||
<rich-text nodes="{{tm_current.name}}"></rich-text>
|
||||
<mp-html content="{{tm_current.name}}" />
|
||||
</view>
|
||||
<view wx:if="{{tm_current.img}}" style="text-align:center"><image src="{{tm_current.img}}" mode="aspectFit"></image></view>
|
||||
</view>
|
||||
|
|
@ -25,15 +24,13 @@
|
|||
<view style="font-weight:bold;color:green" wx:if="{{ moShi == '看题模式' && item.right}}">
|
||||
<view style="float:left;width:10%">{{item.key}}:</view>
|
||||
<view style="float:left;width:90%">
|
||||
<!-- <parser html="{{item.value}}" domain="{{domain}}" selectable /> -->
|
||||
<rich-text nodes="{{item.value}}"></rich-text>
|
||||
<mp-html content="{{item.value}}" />
|
||||
</view>
|
||||
</view>
|
||||
<view wx:else>
|
||||
<view style="float:left;width:10%">{{item.key}}:</view>
|
||||
<view style="float:left;width:90%">
|
||||
<!-- <parser html="{{item.value}}" domain="{{domain}}" selectable /> -->
|
||||
<rich-text nodes="{{item.value}}"></rich-text>
|
||||
<mp-html content="{{item.value}}" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
|
@ -52,15 +49,13 @@
|
|||
<view style="font-weight:bold;color:green" wx:if="{{ moShi == '看题模式' && item.right}}">
|
||||
<view style="float:left;width:10%">{{item.key}}:</view>
|
||||
<view style="float:left;width:90%">
|
||||
<rich-text nodes="{{item.value}}"></rich-text>
|
||||
<!-- <parser html="{{item.value}}" domain="{{domain}}" selectable /> -->
|
||||
<mp-html content="{{item.value}}" domain="{{domain}}"/>
|
||||
</view>
|
||||
</view>
|
||||
<view wx:else>
|
||||
<view style="float:left;width:10%">{{item.key}}:</view>
|
||||
<view style="float:left;width:90%">
|
||||
<rich-text nodes="{{item.value}}"></rich-text>
|
||||
<!-- <parser html="{{item.value}}" domain="{{domain}}" selectable /> -->
|
||||
<mp-html content="{{item.value}}" domain="{{domain}}"/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
|
|
|||
|
|
@ -4,21 +4,21 @@
|
|||
<view class="weui-panel__bd">
|
||||
<view class="weui-media-box weui-media-box_appmsg" hover-class="weui-cell_active" bindtap="register">
|
||||
<view class="weui-media-box__hd weui-media-box__hd_in-appmsg" style="border-radius:6px;overflow:hidden">
|
||||
<open-data type="userAvatarUrl" ></open-data>
|
||||
<open-data type="userAvatarUrl"></open-data>
|
||||
</view>
|
||||
<view class="weui-media-box__bd weui-media-box__bd_in-appmsg">
|
||||
<view class="weui-media-box__title" wx:if="{{userinfo && userinfo.username}}">
|
||||
<span>账号:</span>
|
||||
<span style="font-weight:bold;">{{userinfo.username}}</span>
|
||||
</view>
|
||||
<view class="weui-media-box__title" wx:else>账号:
|
||||
<span style="color:red">未登陆</span>
|
||||
<view class="weui-media-box__title" wx:else>账号:
|
||||
<span style="color:red">未登陆</span>
|
||||
</view>
|
||||
<view class="weui-media-box__desc">昵称:
|
||||
<open-data type="userNickName"></open-data>
|
||||
</view>
|
||||
<view class="weui-media-box__desc">单位:
|
||||
<span wx:if="{{userinfo && userinfo.company_name}}">{{ userinfo.company_name }}</span>
|
||||
<view class="weui-media-box__desc">单位:
|
||||
<span wx:if="{{userinfo && userinfo.company_name}}">{{ userinfo.company_name }}</span>
|
||||
</view>
|
||||
<view class="weui-media-box__desc">如需解绑账号请联系课程顾问
|
||||
</view>
|
||||
|
|
@ -28,46 +28,55 @@
|
|||
</view>
|
||||
<view class="weui-cells__title">统计分析</view>
|
||||
<view class="weui-cells weui-cells_after-title">
|
||||
<view class="weui-cell" >
|
||||
<view class="weui-cell">
|
||||
<view class="weui-cell__hd">
|
||||
<image src="/images/class.svg" style="margin-right: 16px;vertical-align: middle;width:20px; height: 20px;"></image>
|
||||
<image src="/images/class.svg" style="margin-right: 16px;vertical-align: middle;width:20px; height: 20px;">
|
||||
</image>
|
||||
</view>
|
||||
<view class="weui-cell__bd">工作类别</view>
|
||||
<view class="weui-cell__ft" style="font-weight:bold;color:darkblue"
|
||||
wx:if="{{userinfo.workscope_name}}"
|
||||
>{{userinfo.workscope_name}}</view>
|
||||
<view class="weui-cell__ft" style="font-weight:bold;color:darkblue"
|
||||
wx:else
|
||||
>无</view>
|
||||
<view class="weui-cell__ft" style="font-weight:bold;color:darkblue" wx:if="{{userinfo.workscope_name}}">
|
||||
{{userinfo.workscope_name}}</view>
|
||||
<view class="weui-cell__ft" style="font-weight:bold;color:darkblue" wx:else>无</view>
|
||||
</view>
|
||||
<!-- <l-list title="模考次数" tag-content="{{total}}" tag-position="right"/> -->
|
||||
<view class="weui-cell">
|
||||
<view class="weui-cell__hd">
|
||||
<image src="/images/count.svg" style="margin-right: 16px;vertical-align: middle;width:20px; height: 20px;"></image>
|
||||
<image src="/images/count.svg" style="margin-right: 16px;vertical-align: middle;width:20px; height: 20px;">
|
||||
</image>
|
||||
</view>
|
||||
<view class="weui-cell__bd">模考次数</view>
|
||||
<view class="weui-cell__bd">考试次数</view>
|
||||
<view class="weui-cell__ft" style="font-weight:bold;color:darkblue">{{total}}</view>
|
||||
</view>
|
||||
<view class="weui-cell">
|
||||
<view class="weui-cell__hd">
|
||||
<image src="/images/rate.svg" style="margin-right: 16px;vertical-align: middle;width:20px; height: 20px;"></image>
|
||||
<view class="weui-cell">
|
||||
<view class="weui-cell__hd">
|
||||
<image src="/images/rate.svg" style="margin-right: 16px;vertical-align: middle;width:20px; height: 20px;">
|
||||
</image>
|
||||
</view>
|
||||
<view class="weui-cell__bd">通过率</view>
|
||||
<view class="weui-cell__ft" style="font-weight:bold;color:darkblue">{{pass_rate}}%</view>
|
||||
</view>
|
||||
<view class="weui-cell">
|
||||
<view class="weui-cell__hd">
|
||||
<image src="/images/avg.svg" style="margin-right: 16px;vertical-align: middle;width:20px; height: 20px;"></image>
|
||||
<view class="weui-cell">
|
||||
<view class="weui-cell__hd">
|
||||
<image src="/images/avg.svg" style="margin-right: 16px;vertical-align: middle;width:20px; height: 20px;">
|
||||
</image>
|
||||
</view>
|
||||
<view class="weui-cell__bd">平均分</view>
|
||||
<view class="weui-cell__ft" style="font-weight:bold;color:darkblue" wx:if="{{avg_score}}">{{avg_score}}</view>
|
||||
</view>
|
||||
<navigator url="/pages/exam/index" class="weui-cell weui-cell_access" hover-class="weui-cell_active">
|
||||
<view class="weui-cell__hd">
|
||||
<image src="/images/exam.svg" style="margin-right: 16px;vertical-align: middle;width:20px; height: 20px;">
|
||||
</image>
|
||||
</view>
|
||||
<view class="weui-cell__bd">正式考试入口</view>
|
||||
<view class="weui-cell__ft weui-cell__ft_in-access" style="color:red"></view>
|
||||
</navigator>
|
||||
</view>
|
||||
<view class="weui-footer weui-footer_fixed-bottom">
|
||||
<!-- <view class="weui-footer__text" bindtap="intro">点击下载系统/小程序文档介绍</view> -->
|
||||
<view class="weui-footer__text">更多服务请联系课程顾问</view>
|
||||
</view>
|
||||
|
||||
|
||||
<view class="weui-footer weui-footer_fixed-bottom">
|
||||
<!-- <view class="weui-footer__text" bindtap="intro">点击下载系统/小程序文档介绍</view> -->
|
||||
<view class="weui-footer__text">更多服务请联系课程顾问</view>
|
||||
</view>
|
||||
|
||||
|
||||
</view>
|
||||
</view>
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"usingComponents": {
|
||||
"parser": "/components/parser/parser"
|
||||
"mp-html": "/components/mp-html/index"
|
||||
}
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@
|
|||
<span style="color:gray"> {{tm_current.questioncat_name}}</span>
|
||||
</view>
|
||||
<view class="weui-article__title">
|
||||
<rich-text nodes="{{tm_current.name}}"></rich-text>
|
||||
<mp-html content="{{tm_current.name}}" domain="{{domain}}"/>
|
||||
</view>
|
||||
<view wx:if="{{tm_current.img}}" style="text-align:center"><image src="{{tm_current.img}}" mode="aspectFit"></image></view>
|
||||
</view>
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
<view class="weui-cell__bd">
|
||||
<view style="float:left;width:10%">{{item.key}}:</view>
|
||||
<view style="float:left;width:90%">
|
||||
<rich-text nodes="{{item.value}}"></rich-text>
|
||||
<mp-html content="{{item.value}}" domain="{{domain}}"/>
|
||||
</view>
|
||||
</view>
|
||||
<view class="weui-cell__ft">
|
||||
|
|
@ -34,7 +34,7 @@
|
|||
|
||||
<view class="weui-cell__bd">
|
||||
<view style="float:left;width:10%">{{item.key}}:</view>
|
||||
<view style="float:left;width:90%"><rich-text nodes="{{item.value}}"></rich-text></view>
|
||||
<view style="float:left;width:90%"><mp-html content="{{item.value}}" domain="{{domain}}"/></view>
|
||||
</view>
|
||||
<view class="weui-cell__hd">
|
||||
<checkbox class="weui-check" value="{{item.key}}" checked="{{item.checked}}"/>
|
||||
|
|
|
|||
|
|
@ -18,7 +18,12 @@ Page({
|
|||
onLoad: function (options) {
|
||||
var that = this
|
||||
var query = {'examtest':options.id}
|
||||
wx.showLoading({
|
||||
title: '加载中...',
|
||||
mask:true
|
||||
})
|
||||
api.request('/examtest/answerdetail/', 'GET', query).then(res => {
|
||||
wx.hideLoading()
|
||||
for (var i = 0; i < res.data.length; i++) {
|
||||
if(res.data[i].img){
|
||||
res.data[i].img = getApp().globalData.mediahost + res.data[i].img
|
||||
|
|
@ -29,7 +34,7 @@ Page({
|
|||
that.setData({
|
||||
tmtotal:res.data.length
|
||||
})
|
||||
})
|
||||
}).catch(e=>{wx.hideLoading()})
|
||||
try {
|
||||
const res = wx.getSystemInfoSync()
|
||||
that.setData({
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"usingComponents": {
|
||||
"parser": "/components/parser/parser"
|
||||
"mp-html": "/components/mp-html/index"
|
||||
}
|
||||
}
|
||||
|
|
@ -8,8 +8,7 @@
|
|||
<span style="color:gray">({{tm_current.question.questioncat_name}})</span>
|
||||
</view>
|
||||
<view class="weui-article__title">
|
||||
<!-- <parser html="{{tm_current.question.name}}" domain="{{domain}}" selectable/> -->
|
||||
<rich-text nodes="{{tm_current.question.name}}"></rich-text>
|
||||
<mp-html content="{{tm_current.question.name}}" domain="{{domain}}"/>
|
||||
</view>
|
||||
<view wx:if="{{tm_current.img}}" style="text-align:center"><image src="{{tm_current.img}}" mode="aspectFit"></image></view>
|
||||
</view>
|
||||
|
|
@ -18,7 +17,7 @@
|
|||
<label class="weui-cell weui-cell_active weui-check__label" wx:for="{{options}}" wx:key="key">
|
||||
<view class="weui-cell__bd">
|
||||
<view style="float:left;width:10%">{{item.key}}:</view>
|
||||
<view style="float:left;width:90%"><rich-text nodes="{{item.value}}"></rich-text></view>
|
||||
<view style="float:left;width:90%"><mp-html content="{{item.value}}" domain="{{domain}}"/></view>
|
||||
</view>
|
||||
<view class="weui-cell__ft">
|
||||
<radio class="weui-check" value="{{item.key}}" checked="{{item.checked}}" />
|
||||
|
|
@ -33,7 +32,7 @@
|
|||
|
||||
<view class="weui-cell__bd">
|
||||
<view style="float:left;width:10%">{{item.key}}:</view>
|
||||
<view style="float:left;width:90%"><rich-text nodes="{{item.value}}"></rich-text></view>
|
||||
<view style="float:left;width:90%"><mp-html content="{{item.value}}" domain="{{domain}}"/></view>
|
||||
</view>
|
||||
<view class="weui-cell__hd">
|
||||
<checkbox class="weui-check" value="{{item.key}}" checked="{{item.checked}}"/>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
// pages/lianxi/index.js
|
||||
const api = require("../../utils/request.js");
|
||||
var util = require('../../utils/util.js')
|
||||
Page({
|
||||
|
||||
/**
|
||||
|
|
@ -36,6 +37,9 @@ Page({
|
|||
getList: function () {
|
||||
var that = this
|
||||
api.request('/examtest/examtest/self/', 'GET', that.data.query).then(res => {
|
||||
for(var i=0;i<res.data.results.length;i++){
|
||||
res.data.results[i].took = util.formatSecond(res.data.results[i].took)
|
||||
}
|
||||
if (that.data.query.page == 1) {
|
||||
that.data.results = res.data.results
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,8 @@
|
|||
<view class="weui-media-box__bd weui-media-box__bd_in-appmsg">
|
||||
<view class="weui-media-box__title">{{item.name}}</view>
|
||||
<view class="weui-media-box__desc">
|
||||
<span style="font-weight:bold;color:darkblue">{{item.type}}</span>
|
||||
<span style="font-weight:bold;color:brown;" wx:if="{{item.type=='正式考试'}}">{{item.type}}</span>
|
||||
<span style="font-weight:bold;color:darkblue" wx:else>{{item.type}}</span>
|
||||
<span>-</span>
|
||||
<span style="font-weight:bold;color:green;" wx:if="{{item.is_pass}}">通过</span>
|
||||
<span style="font-weight:bold;color:red;" wx:else>未通过</span>
|
||||
|
|
@ -18,7 +19,7 @@
|
|||
<span style="font-weight:bold">{{item.total_score}})</span>
|
||||
</view>
|
||||
<view class="weui-media-box__desc">
|
||||
耗时:{{item.took}}s
|
||||
耗时:{{item.took}}
|
||||
开始答题:{{item.start_time}}
|
||||
</view>
|
||||
</view>
|
||||
|
|
|
|||
|
|
@ -150,6 +150,9 @@ Page({
|
|||
for(var i=0;i<tm_current.user_answer.length;i++){
|
||||
if(tm_current.right.indexOf(tm_current.user_answer[i])!=-1){
|
||||
score = score + 1
|
||||
if(score==2){
|
||||
break;
|
||||
}
|
||||
}else{
|
||||
score = 0
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"usingComponents": {
|
||||
"parser": "/components/parser/parser"
|
||||
"mp-html": "/components/mp-html/index"
|
||||
},
|
||||
"navigationBarTitleText": "答题中"
|
||||
}
|
||||
|
|
@ -17,7 +17,7 @@
|
|||
<span style="color:gray">({{tm_current.questioncat_name}})</span>
|
||||
</view>
|
||||
<view class="weui-article__title">
|
||||
<rich-text nodes="{{tm_current.name}}"></rich-text>
|
||||
<mp-html content="{{tm_current.name}}" domain="{{domain}}"/>
|
||||
</view>
|
||||
<view wx:if="{{tm_current.img}}" style="text-align:center"><image src="{{tm_current.img}}" mode="aspectFit"></image></view>
|
||||
</view>
|
||||
|
|
@ -26,7 +26,9 @@
|
|||
<label class="weui-cell weui-cell_active weui-check__label" wx:for="{{options}}" wx:key="key">
|
||||
<view class="weui-cell__bd">
|
||||
<view style="float:left;width:10%">{{item.key}}:</view>
|
||||
<view style="float:left;width:90%"><rich-text nodes="{{item.value}}"></rich-text></view>
|
||||
<view style="float:left;width:90%">
|
||||
<mp-html content="{{item.value}}" domain="{{domain}}"/>
|
||||
</view>
|
||||
</view>
|
||||
<view class="weui-cell__ft">
|
||||
<radio class="weui-check" value="{{item.key}}" checked="{{item.checked}}" />
|
||||
|
|
@ -41,7 +43,9 @@
|
|||
|
||||
<view class="weui-cell__bd">
|
||||
<view style="float:left;width:10%">{{item.key}}:</view>
|
||||
<view style="float:left;width:90%"><rich-text nodes="{{item.value}}"></rich-text></view>
|
||||
<view style="float:left;width:90%">
|
||||
<mp-html content="{{item.value}}" domain="{{domain}}"/>
|
||||
</view>
|
||||
</view>
|
||||
<view class="weui-cell__hd">
|
||||
<checkbox class="weui-check" value="{{item.key}}" checked="{{item.checked}}"/>
|
||||
|
|
|
|||
|
|
@ -21,15 +21,13 @@
|
|||
"checkSiteMap": true,
|
||||
"uploadWithSourceMap": true,
|
||||
"compileHotReLoad": false,
|
||||
"useMultiFrameRuntime": true,
|
||||
"useMultiFrameRuntime": false,
|
||||
"useApiHook": true,
|
||||
"useApiHostProcess": false,
|
||||
"babelSetting": {
|
||||
"ignore": [],
|
||||
"disablePlugins": [],
|
||||
"outputPath": ""
|
||||
},
|
||||
"enableEngineNative": false,
|
||||
"bundle": false,
|
||||
"useIsolateContext": true,
|
||||
"useCompilerModule": true,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 3.0.4 on 2021-03-13 03:09
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('cms', '0007_auto_20200811_0835'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='material',
|
||||
name='sort',
|
||||
field=models.IntegerField(default=1, verbose_name='排序码'),
|
||||
),
|
||||
]
|
||||
|
|
@ -37,4 +37,5 @@ class Material(CommonModel):
|
|||
poster = models.CharField(max_length=10000, verbose_name='封面地址', null=True, blank=True)
|
||||
type = models.CharField('格式', default='文档', max_length=50)
|
||||
down_count = models.IntegerField('阅读量', default=0)
|
||||
sort = models.IntegerField('排序码', default=1)
|
||||
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ class MaterialViewSet(ModelViewSet):
|
|||
filter_backends = [DjangoFilterBackend,SearchFilter, OrderingFilter]
|
||||
search_fields = ['name','description']
|
||||
ordering_fields = ['update_time', 'down_count']
|
||||
ordering = ['-down_count']
|
||||
ordering = ['sort', '-down_count']
|
||||
filterset_fields = ['type', 'name']
|
||||
|
||||
@action(methods=['get'], detail=True, url_name='down_material', perms_map=[{'*':'down_material'}])
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
# Generated by Django 3.0.4 on 2021-03-13 03:09
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('crm', '0025_auto_20201013_1024'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='consumer',
|
||||
name='ID_number',
|
||||
field=models.CharField(blank=True, max_length=100, null=True, verbose_name='查询身份证号'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='consumer',
|
||||
name='realname',
|
||||
field=models.CharField(blank=True, max_length=100, null=True, verbose_name='查询真实姓名'),
|
||||
),
|
||||
]
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 3.0.4 on 2021-03-17 14:02
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('crm', '0026_auto_20210313_1109'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='consumer',
|
||||
name='deptname',
|
||||
field=models.CharField(blank=True, max_length=100, null=True, verbose_name='所在部门'),
|
||||
),
|
||||
]
|
||||
|
|
@ -74,6 +74,7 @@ class Consumer(CommonModel):
|
|||
|
||||
ID_number1 = models.CharField('身份证号', max_length=100, null=True, blank=True)
|
||||
create_admin = models.ForeignKey(UserProfile, on_delete=models.SET_NULL, null=True, blank=True, related_name='consumer_create_admin')
|
||||
deptname = models.CharField('所在部门', max_length=100, null=True, blank=True)
|
||||
exceed_date = models.DateField('账号过期', null=True, blank=True)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ from django.db.models import Q
|
|||
from django_filters.rest_framework import DjangoFilterBackend
|
||||
from openpyxl import Workbook, load_workbook
|
||||
from rest_framework import status
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.decorators import action, authentication_classes, permission_classes
|
||||
from rest_framework.filters import OrderingFilter, SearchFilter
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
from rest_framework.response import Response
|
||||
|
|
@ -365,17 +365,6 @@ class ConsumerViewSet(ModelViewSet):
|
|||
request.user.save()
|
||||
return Response(status=status.HTTP_200_OK)
|
||||
|
||||
# @action(methods=['put'], detail=False,
|
||||
# url_path='process', url_name='exercise_processcat', perms_map=[{'*':'*'}])
|
||||
# def processcat(self, request):
|
||||
# '''
|
||||
# 练习进度单类别修改
|
||||
# '''
|
||||
# if hasattr(request.user, 'process'):
|
||||
# request.user.process = request.data['process']
|
||||
# request.user.save()
|
||||
# return Response(status=status.HTTP_200_OK)
|
||||
|
||||
@action(methods=['post'], detail=False,
|
||||
url_path='realinfo', url_name='get_realinfo', perms_map=[{'*':'*'}])
|
||||
def realinfo(self, request):
|
||||
|
|
@ -547,6 +536,11 @@ class ConsumerViewSet(ModelViewSet):
|
|||
except:
|
||||
raise Http404
|
||||
|
||||
@action(methods=['get'], detail = False, perms_map=[{'*':'*'}])
|
||||
def info(self, request, *args, **kwargs):
|
||||
serializer = ConsumerDetailSerializer(instance=request.user)
|
||||
return Response({"userinfo":serializer.data})
|
||||
|
||||
from .permission import get_consumerperm_list
|
||||
class ConsumerMPLoginView(APIView):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -1,13 +0,0 @@
|
|||
from sympy import *
|
||||
a1 = Symbol('a1')
|
||||
a2 = Symbol('a2')
|
||||
a3 = Symbol('a3')
|
||||
b1 = Symbol('b1')
|
||||
b2 = Symbol('b2')
|
||||
r = solve([
|
||||
a1+a2-40,
|
||||
b1+b2-10,
|
||||
2*a1+4*b1-60,
|
||||
2*a2+4*b2-40
|
||||
], [a1,a2,b1,b2])
|
||||
print(r)
|
||||
|
|
@ -2,8 +2,13 @@ from openpyxl.workbook import Workbook
|
|||
from django.conf import settings
|
||||
from datetime import datetime
|
||||
from openpyxl.styles import Font, Fill
|
||||
|
||||
|
||||
from rest_framework.serializers import Serializer
|
||||
from .models import ExamTest, AnswerDetail
|
||||
from django.http import HttpResponse
|
||||
from docxtpl import DocxTemplate
|
||||
from io import BytesIO
|
||||
from .serializers import ExamTestDetailSerializer
|
||||
import os
|
||||
BASE_DIR = settings.BASE_DIR
|
||||
|
||||
def export_test(tests):
|
||||
|
|
@ -23,3 +28,24 @@ def export_test(tests):
|
|||
path = '/media/export/' + filename
|
||||
wb.save((BASE_DIR + path).replace('\\', '/'))
|
||||
return path
|
||||
|
||||
def exportw_test(obj, bool):
|
||||
"""
|
||||
导出个人考试记录word版本
|
||||
"""
|
||||
filename = obj.exam.name + '-' + obj.consumer.name + '-' + obj.consumer.username + '.doc'
|
||||
path = '/media/export/' + filename
|
||||
fullpath = BASE_DIR + path
|
||||
if bool or (not os.path.exists(fullpath)):
|
||||
data = ExamTestDetailSerializer(instance=obj).data
|
||||
#开始生成word
|
||||
doc = DocxTemplate(BASE_DIR + "/tmp/examtest.docx")
|
||||
doc.render(data)
|
||||
doc.save(fullpath)
|
||||
# output = BytesIO()
|
||||
# doc.save(output)
|
||||
# output.seek(0)
|
||||
# res = HttpResponse(content_type='application/msword')
|
||||
# res['Content-Disposition'] = 'attachment;filename='+filename+'.docx'
|
||||
# res.write(output.getvalue())
|
||||
return path
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
# Generated by Django 3.0.4 on 2021-03-14 09:16
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import django.utils.timezone
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('examtest', '0024_auto_20200402_2353'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='workscope',
|
||||
name='can_exam',
|
||||
field=models.BooleanField(default=False, verbose_name='是否可组织考试'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='examtest',
|
||||
name='type',
|
||||
field=models.CharField(choices=[('自助模考', '自助模考'), ('押卷模考', '押卷模考'), ('正式考试', '正式考试')], default='自助模考', max_length=50, verbose_name='考试类型'),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Exam',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('create_time', models.DateTimeField(default=django.utils.timezone.now, help_text='创建时间', verbose_name='创建时间')),
|
||||
('update_time', models.DateTimeField(auto_now=True, help_text='修改时间', verbose_name='修改时间')),
|
||||
('is_delete', models.BooleanField(default=False, help_text='删除标记', verbose_name='删除标记')),
|
||||
('code', models.CharField(blank=True, max_length=100, null=True, verbose_name='考试编号')),
|
||||
('name', models.CharField(max_length=100, verbose_name='名称')),
|
||||
('place', models.CharField(blank=True, max_length=100, null=True, verbose_name='考试地点')),
|
||||
('opentime', models.DateTimeField(blank=True, null=True, verbose_name='开启时间')),
|
||||
('closetime', models.DateTimeField(blank=True, null=True, verbose_name='关闭时间')),
|
||||
('proctor_name', models.CharField(max_length=100, verbose_name='监考人姓名')),
|
||||
('proctor_phone', models.CharField(max_length=100, verbose_name='监考人联系方式')),
|
||||
('create_admin', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='exam_create_admin', to=settings.AUTH_USER_MODEL)),
|
||||
('workscope', models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, to='examtest.WorkScope', verbose_name='工作类别')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='examtest',
|
||||
name='exam',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='examtest_exam', to='examtest.Exam', verbose_name='关联的正式考试'),
|
||||
),
|
||||
]
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
# Generated by Django 3.0.4 on 2021-03-21 01:40
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('question', '0012_question_img'),
|
||||
('examtest', '0025_auto_20210314_1716'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='answerdetail',
|
||||
name='examtest',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='answerdetail_examtest', to='examtest.ExamTest'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='examtest',
|
||||
name='detail',
|
||||
field=models.ManyToManyField(through='examtest.AnswerDetail', to='question.Question', verbose_name='答题记录'),
|
||||
),
|
||||
]
|
||||
|
|
@ -1,11 +1,29 @@
|
|||
from django.db import models
|
||||
from rbac.models import SoftCommonModel, CommonModel
|
||||
from rbac.models import SoftCommonModel, CommonModel, UserProfile
|
||||
from django.contrib.postgres.fields import JSONField, ArrayField
|
||||
from question.models import Questioncat, Question
|
||||
from crm.models import Consumer
|
||||
from .models_paper import WorkScope, Paper
|
||||
|
||||
|
||||
class Exam(CommonModel):
|
||||
"""
|
||||
组织的正式考试
|
||||
"""
|
||||
code = models.CharField('考试编号', max_length=100, null=True, blank=True)
|
||||
name = models.CharField('名称', max_length=100)
|
||||
place = models.CharField('考试地点', max_length=100, null=True, blank=True)
|
||||
workscope = models.ForeignKey(WorkScope, verbose_name='工作类别', on_delete= models.DO_NOTHING)
|
||||
opentime = models.DateTimeField('开启时间', null=True, blank=True)
|
||||
closetime = models.DateTimeField('关闭时间', null=True, blank=True)
|
||||
proctor_name = models.CharField('监考人姓名', max_length=100)
|
||||
proctor_phone = models.CharField('监考人联系方式', max_length=100)
|
||||
create_admin = models.ForeignKey(UserProfile, on_delete=models.SET_NULL, null=True, blank=True, related_name='exam_create_admin')
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class ExamTest(CommonModel):
|
||||
'''
|
||||
考试记录表
|
||||
|
|
@ -13,6 +31,7 @@ class ExamTest(CommonModel):
|
|||
type_choices = (
|
||||
('自助模考', '自助模考'),
|
||||
('押卷模考', '押卷模考'),
|
||||
('正式考试', '正式考试')
|
||||
)
|
||||
name = models.CharField(max_length=200, verbose_name='名称')
|
||||
type = models.CharField(max_length=50, default='自助模考',choices = type_choices, verbose_name='考试类型')
|
||||
|
|
@ -25,15 +44,17 @@ class ExamTest(CommonModel):
|
|||
took = models.IntegerField(default=0, verbose_name='耗时(秒)')
|
||||
start_time = models.DateTimeField(verbose_name='开始答题时间')
|
||||
end_time = models.DateTimeField(verbose_name='结束答题时间')
|
||||
detail = models.ManyToManyField(Question, related_name='答题记录', through='AnswerDetail')
|
||||
detail = models.ManyToManyField(Question, verbose_name='答题记录', through='AnswerDetail')
|
||||
is_pass = models.BooleanField(default=True, verbose_name='是否通过')
|
||||
|
||||
exam = models.ForeignKey(Exam, verbose_name='关联的正式考试', null=True, blank=True, related_name='examtest_exam', on_delete= models.SET_NULL)
|
||||
class Meta:
|
||||
verbose_name = '模拟考试'
|
||||
verbose_name_plural = verbose_name
|
||||
|
||||
|
||||
class AnswerDetail(SoftCommonModel):
|
||||
examtest = models.ForeignKey(ExamTest, on_delete=models.CASCADE)
|
||||
examtest = models.ForeignKey(ExamTest, on_delete=models.CASCADE, related_name='answerdetail_examtest')
|
||||
question = models.ForeignKey(Question, on_delete=models.CASCADE)
|
||||
user_answer = JSONField(null=True,blank=True)
|
||||
score = models.FloatField(default=0, verbose_name='本题得分')
|
||||
|
|
@ -47,4 +68,4 @@ class Banner(CommonModel):
|
|||
name = models.CharField(max_length=200, verbose_name='名称')
|
||||
path = models.CharField(max_length=1000, null=True, blank=True, verbose_name='图片地址')
|
||||
url = models.CharField(max_length=1000, null=True, blank=True, verbose_name='链接地址')
|
||||
sort = models.IntegerField(default=1, verbose_name='排序数字')
|
||||
sort = models.IntegerField(default=1, verbose_name='排序数字')
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
from django.db import models
|
||||
from django.template.defaultfilters import default
|
||||
from rbac.models import SoftCommonModel, CommonModel
|
||||
from django.contrib.postgres.fields import JSONField, ArrayField
|
||||
from question.models import Questioncat, Question
|
||||
|
|
@ -31,6 +32,7 @@ class WorkScope(CommonModel):
|
|||
subject = models.ForeignKey(Questioncat, verbose_name='所属学科', on_delete=models.CASCADE , related_name='workscope_subject')
|
||||
questioncat = models.ManyToManyField(Questioncat, verbose_name='所选科目')
|
||||
rule = models.ForeignKey(TestRule, on_delete=models.CASCADE, verbose_name='试卷结构')
|
||||
can_exam = models.BooleanField('是否可组织考试', default=False)
|
||||
|
||||
class Meta:
|
||||
verbose_name = '工作类别'
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
from rest_framework import serializers
|
||||
from question.models import Questioncat
|
||||
from crm.models import Consumer
|
||||
from .models import ExamTest, AnswerDetail, Banner
|
||||
from .models import Exam, ExamTest, AnswerDetail, Banner
|
||||
from .models_paper import TestRule, WorkScope, Paper, PaperQuestions
|
||||
from question.serializers import QuestionSerializer
|
||||
|
||||
|
|
@ -41,7 +41,7 @@ class WorkScopeSerializer(serializers.ModelSerializer):
|
|||
|
||||
class MoniTestSerializer(serializers.ModelSerializer):
|
||||
"""
|
||||
模考序列化
|
||||
考试序列化
|
||||
"""
|
||||
start_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S")
|
||||
end_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S")
|
||||
|
|
@ -61,6 +61,7 @@ class ExamTestListSerializer(serializers.ModelSerializer):
|
|||
end_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S")
|
||||
workscope_name = serializers.StringRelatedField(source='workscope', read_only=True)
|
||||
paper_name = serializers.StringRelatedField(source='paper', read_only=True)
|
||||
exam_name = serializers.StringRelatedField(source='exam', read_only=True)
|
||||
consumer_name = serializers.SerializerMethodField()
|
||||
took_format = serializers.SerializerMethodField()
|
||||
consumer_company_name = serializers.SerializerMethodField()
|
||||
|
|
@ -83,7 +84,7 @@ class ExamTestListSerializer(serializers.ModelSerializer):
|
|||
@staticmethod
|
||||
def setup_eager_loading(queryset):
|
||||
""" Perform necessary eager loading of data. """
|
||||
queryset = queryset.select_related('consumer','paper', 'workscope')
|
||||
queryset = queryset.select_related('consumer','paper', 'workscope', 'exam')
|
||||
return queryset
|
||||
from question.serializers import QuestionSerializer
|
||||
class AnswerDetailSerializer(serializers.ModelSerializer):
|
||||
|
|
@ -163,3 +164,55 @@ class PaperQuestionsCreateSerializer(serializers.ModelSerializer):
|
|||
model = PaperQuestions
|
||||
fields = '__all__'
|
||||
|
||||
class ExamCreateUpdateSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = Exam
|
||||
fields = ['name', 'place', 'opentime', 'closetime', 'proctor_name', 'proctor_phone', 'workscope']
|
||||
|
||||
class ExamListSerializer(serializers.ModelSerializer):
|
||||
create_admin_username = serializers.StringRelatedField(source='create_admin')
|
||||
workscope_name = serializers.StringRelatedField(source='workscope')
|
||||
class Meta:
|
||||
model = Exam
|
||||
fields = '__all__'
|
||||
|
||||
class ExamSimpleSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = Exam
|
||||
exclude = ('create_admin',)
|
||||
|
||||
class ConsumerSimpleSerializer(serializers.ModelSerializer):
|
||||
comanyname = serializers.StringRelatedField(source='company', read_only=True)
|
||||
class Meta:
|
||||
model = Consumer
|
||||
fields = ['id', 'name', 'ID_number1', 'comanyname', 'deptname', 'username']
|
||||
class ExamTestDetailSerializer(serializers.ModelSerializer):
|
||||
"""
|
||||
考试详情序列化(导出用)
|
||||
"""
|
||||
workscope_name = serializers.StringRelatedField(source='workscope', read_only=True)
|
||||
paper_name = serializers.StringRelatedField(source='paper', )
|
||||
took_format = serializers.SerializerMethodField()
|
||||
detail_ = serializers.SerializerMethodField()
|
||||
exam_ = ExamSimpleSerializer(source='exam', read_only=True)
|
||||
consumer_ = ConsumerSimpleSerializer(source='consumer', read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = ExamTest
|
||||
exclude = ('detail',)
|
||||
|
||||
def get_took_format(self, obj):
|
||||
m, s = divmod(obj.took, 60)
|
||||
h, m = divmod(m, 60)
|
||||
return "%02d:%02d:%02d" % (h, m, s)
|
||||
|
||||
def get_detail_(self, obj):
|
||||
objs = obj.answerdetail_examtest.order_by('question__type')
|
||||
return AnswerDetailSerializer(instance=objs, many=True).data
|
||||
|
||||
@staticmethod
|
||||
def setup_eager_loading(queryset):
|
||||
""" Perform necessary eager loading of data. """
|
||||
queryset = queryset.select_related('consumer','paper', 'workscope', 'exam')
|
||||
queryset = queryset.prefetch_related('answerdetail_examtest')
|
||||
return queryset
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
from django.urls import path,include
|
||||
from .views import TestRuleViewSet, AnswerDetailView, WorkScopeViewSet, BannerViewSet, ExamTestViewSet, PaperViewSet
|
||||
from .views import TestRuleViewSet, AnswerDetailView, WorkScopeViewSet, BannerViewSet, ExamTestViewSet, PaperViewSet, ExamViewSet
|
||||
from rest_framework import routers
|
||||
|
||||
|
||||
|
|
@ -9,6 +9,7 @@ router.register('workscope', WorkScopeViewSet, basename="workscope")
|
|||
router.register('banner', BannerViewSet, basename='banner')
|
||||
router.register('examtest', ExamTestViewSet, basename='examtest')
|
||||
router.register('paper', PaperViewSet, basename='paper')
|
||||
router.register('exam', ExamViewSet, basename='exam')
|
||||
|
||||
urlpatterns = [
|
||||
path('answerdetail/', AnswerDetailView.as_view()),
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ from datetime import datetime
|
|||
|
||||
from django.db.models import Avg
|
||||
from django.db.models.query import QuerySet
|
||||
from django.utils.translation import get_language_from_request
|
||||
from django_filters.rest_framework import DjangoFilterBackend
|
||||
from openpyxl import Workbook, load_workbook
|
||||
from rest_framework import status
|
||||
|
|
@ -10,6 +11,7 @@ from rest_framework.filters import OrderingFilter, SearchFilter
|
|||
from rest_framework.generics import GenericAPIView
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.serializers import Serializer
|
||||
from rest_framework.views import APIView
|
||||
from rest_framework.viewsets import ModelViewSet
|
||||
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
|
||||
|
|
@ -18,18 +20,123 @@ from question.models import Question
|
|||
from question.serializers import QuestionSerializer
|
||||
from server import settings
|
||||
from utils.custom import CommonPagination
|
||||
from utils.mixins import OptimizationMixin
|
||||
|
||||
from .exports import export_test
|
||||
from .models import AnswerDetail, Banner, ExamTest
|
||||
from .exports import export_test, exportw_test
|
||||
from .models import AnswerDetail, Banner, ExamTest, Exam
|
||||
from .models_paper import Paper, PaperQuestions, TestRule, WorkScope
|
||||
from .serializers import (
|
||||
AnswerDetailCreateSerializer, AnswerDetailSerializer, BannerSerializer,
|
||||
ExamTestListSerializer, MoniTestSerializer, PaperDetailSerializer,
|
||||
PaperQuestionsCreateSerializer, PaperSerializer, TestRuleSerializer,
|
||||
WorkScopeSerializer)
|
||||
|
||||
WorkScopeSerializer, ExamCreateUpdateSerializer, ExamListSerializer, ExamTestDetailSerializer)
|
||||
from django.utils import timezone
|
||||
# Create your views here.
|
||||
|
||||
class ExamViewSet(ModelViewSet):
|
||||
"""
|
||||
正式考试增删改查
|
||||
"""
|
||||
perms_map = [
|
||||
{'get': 'exam_view'}, {'post': 'exam_create'},
|
||||
{'put': 'exam_update'}, {'delete': 'exam_delete'}]
|
||||
pagination_class = CommonPagination
|
||||
filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
|
||||
ordering = ['-id']
|
||||
search_fields = ['name']
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = Exam.objects.all()
|
||||
if not self.request.user.is_superuser:
|
||||
queryset = queryset.filter(create_admin = self.request.user)
|
||||
if hasattr(self.get_serializer_class(), 'setup_eager_loading'):
|
||||
queryset = self.get_serializer_class().setup_eager_loading(queryset) # 性能优化
|
||||
return queryset
|
||||
|
||||
def get_serializer_class(self):
|
||||
if self.action in ['create', 'update']:
|
||||
return ExamCreateUpdateSerializer
|
||||
return ExamListSerializer
|
||||
|
||||
def create(self, request, *args, **kwargs):
|
||||
serializer = self.get_serializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
instance = serializer.save(create_admin=request.user)
|
||||
instance.code = instance.pk + 10000
|
||||
instance.save()
|
||||
return Response(serializer.data, status=status.HTTP_201_CREATED)
|
||||
|
||||
def destroy(self, request, *args, **kwargs):
|
||||
instance = self.get_object()
|
||||
if ExamTest.objects.filter(exam=instance).exists():
|
||||
return Response({'error':'存在考试记录,禁止删除'})
|
||||
instance.delete()
|
||||
return Response(status=status.HTTP_204_NO_CONTENT)
|
||||
|
||||
|
||||
@action(methods=['post'], detail = False,perms_map=[{'post':'exam_attend'}])
|
||||
def attend(self, request, *args, **kwargs):
|
||||
"""
|
||||
参加考试
|
||||
"""
|
||||
if request.data.get('deptname', None):
|
||||
request.user.deptname = request.data['deptname']
|
||||
request.user.save()
|
||||
if request.data.get('code', None):
|
||||
code = request.data.get('code')
|
||||
now = timezone.now()
|
||||
try:
|
||||
exam = Exam.objects.get(code=code, opentime__lt=now, closetime__gt=now)
|
||||
if ExamTest.objects.filter(exam=exam, consumer=request.user).exists():
|
||||
return Response({'error':'您已参加过该场考试'})
|
||||
return Response({'exam':exam.pk})
|
||||
except:
|
||||
return Response({'error':'考试编号不存在'})
|
||||
return Response({'error':'操作失败'})
|
||||
|
||||
@action(methods=['post'], detail = True,perms_map=[{'post':'exam_attend'}])
|
||||
def init(self, request, *args, **kwargs):
|
||||
"""
|
||||
生成考试卷
|
||||
"""
|
||||
obj = Exam.objects.get(pk=kwargs['pk'])
|
||||
workscope = obj.workscope
|
||||
ret = {}
|
||||
if workscope.name in ['医学Ⅲ类', '非医学Ⅲ类']:
|
||||
ret['name'] = obj.name
|
||||
ret['type'] = '正式考试' # 正式考试
|
||||
ret['exam'] = kwargs['pk']
|
||||
ret['exam_'] = ExamListSerializer(instance=obj).data
|
||||
ret['workscope'] = workscope.id
|
||||
ret['limit'] = 60
|
||||
ret['total_score'] = 120
|
||||
ret['pass_score'] = 90
|
||||
ret['danxuan_count'] = 40
|
||||
ret['danxuan_score'] = 2
|
||||
ret['duoxuan_count'] = 10
|
||||
ret['duoxuan_score'] = 4
|
||||
question_queryset = Question.objects.none()
|
||||
questioncats = workscope.questioncat.order_by('type', 'create_time')
|
||||
if questioncats.count() == 3:
|
||||
queryset = Question.objects.filter(is_delete=0)
|
||||
a1_set = queryset.filter(questioncat=questioncats[0], type='单选').order_by('?')[:12]
|
||||
a2_set = queryset.filter(questioncat=questioncats[1], type='单选').order_by('?')[:12]
|
||||
a3_set = queryset.filter(questioncat=questioncats[2], type='单选').order_by('?')[:16]
|
||||
b1_set = queryset.filter(questioncat=questioncats[0], type='多选').order_by('?')[:3]
|
||||
b2_set = queryset.filter(questioncat=questioncats[1], type='多选').order_by('?')[:3]
|
||||
b3_set = queryset.filter(questioncat=questioncats[2], type='多选').order_by('?')[:4]
|
||||
question_queryset = question_queryset|a1_set|a2_set|a3_set|b1_set|b2_set|b3_set
|
||||
questions = QuestionSerializer(instance=question_queryset.order_by('type'),many=True).data
|
||||
for i in questions:
|
||||
if i['type'] == '单选':
|
||||
i['total_score'] = 2
|
||||
elif i['type'] == '多选':
|
||||
i['total_score'] = 4
|
||||
ret['questions'] = questions
|
||||
return Response(ret)
|
||||
return Response({'error':'生成试卷失败'})
|
||||
|
||||
|
||||
|
||||
class AnswerDetailView(APIView):
|
||||
authentication_classes = []
|
||||
|
|
@ -56,8 +163,8 @@ class WorkScopeViewSet(ModelViewSet):
|
|||
ordering_fields = ('id',)
|
||||
ordering = ['id']
|
||||
filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
|
||||
filterset_fields = ['subject']
|
||||
search_fields = ('^name',)
|
||||
filterset_fields = ['subject', 'can_exam']
|
||||
search_fields = ('name',)
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = self.queryset
|
||||
|
|
@ -102,6 +209,7 @@ class WorkScopeViewSet(ModelViewSet):
|
|||
b3_set = queryset.filter(questioncat=questioncats[2], type='多选').order_by('?')[:b3]
|
||||
question_queryset = question_queryset|a1_set|a2_set|a3_set|b1_set|b2_set|b3_set
|
||||
elif workscope.name == '辐射安全管理':
|
||||
# 辐射安全管理出卷规则
|
||||
queryset = Question.objects.filter(is_delete=0)
|
||||
a1_set = queryset.filter(questioncat=questioncats[0], type='单选').order_by('?')[:16]
|
||||
a2_set = queryset.filter(questioncat=questioncats[1], type='单选').order_by('?')[:24]
|
||||
|
|
@ -109,6 +217,7 @@ class WorkScopeViewSet(ModelViewSet):
|
|||
b2_set = queryset.filter(questioncat=questioncats[1], type='多选').order_by('?')[:6]
|
||||
question_queryset = question_queryset|a1_set|a2_set|b1_set|b2_set
|
||||
elif workscope.name == '科研、生产及其他':
|
||||
# 科研、生产及其他出卷规则
|
||||
queryset = Question.objects.filter(is_delete=0)
|
||||
a1_set = queryset.filter(questioncat=questioncats[0], type='单选').order_by('?')[:24]
|
||||
a2_set = queryset.filter(questioncat=questioncats[1], type='单选').order_by('?')[:16]
|
||||
|
|
@ -233,7 +342,7 @@ class ExamTestViewSet(ModelViewSet):
|
|||
"""
|
||||
考试记录列表和详情
|
||||
"""
|
||||
perms_map = [{'get': 'examtest_view'},{'post': '*'}]
|
||||
perms_map = [{'get': 'examtest_view'},{'post': '*'}, {'delete':'examtest_delete'}]
|
||||
pagination_class = CommonPagination
|
||||
queryset = ExamTest.objects.filter(is_delete=0).all()
|
||||
serializer_class = ExamTestListSerializer
|
||||
|
|
@ -241,7 +350,7 @@ class ExamTestViewSet(ModelViewSet):
|
|||
ordering = ['-create_time']
|
||||
search_fields = ('consumer__name', 'consumer__company__name')
|
||||
filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
|
||||
filterset_fields = ['type','is_pass']
|
||||
filterset_fields = ['type','is_pass', 'exam']
|
||||
|
||||
def get_queryset(self):
|
||||
assert self.queryset is not None, (
|
||||
|
|
@ -302,6 +411,10 @@ class ExamTestViewSet(ModelViewSet):
|
|||
serializer_detail = AnswerDetailCreateSerializer(data=questions, many=True)
|
||||
if serializer_detail.is_valid():
|
||||
serializer_detail.save()
|
||||
# 关联正式考试如有
|
||||
if request.data.get('exam', None):
|
||||
instance.exam = Exam.objects.get(pk=request.data['exam'])
|
||||
instance.save()
|
||||
return Response(MoniTestSerializer(instance).data,status=status.HTTP_200_OK)
|
||||
else:
|
||||
return Response(serializer_detail.errors)
|
||||
|
|
@ -321,6 +434,16 @@ class ExamTestViewSet(ModelViewSet):
|
|||
serializer = ExamTestListSerializer(instance=queryset, many=True)
|
||||
path = export_test(serializer.data)
|
||||
return Response({'path': path})
|
||||
|
||||
@action(methods=['post'], detail = True ,perms_map=[{'post':'export_test'}])
|
||||
def exportw(self, request, *args, **kwargs):
|
||||
obj = self.get_object()
|
||||
if 'anew' in request.data and request.data['anew']:
|
||||
# 是否需要重新生成
|
||||
path = exportw_test(obj, True)
|
||||
else:
|
||||
path = exportw_test(obj, False)
|
||||
return Response({'path': path})
|
||||
|
||||
class PaperViewSet(ModelViewSet):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ class QuestioncatViewSet(ModelViewSet):
|
|||
serializer = QuestioncatSerializer(instance=queryset,many=True)
|
||||
return Response(serializer.data)
|
||||
|
||||
|
||||
from django.db.models import Q
|
||||
class QuestionViewSet(ModelViewSet):
|
||||
"""
|
||||
题目:增删改查
|
||||
|
|
@ -126,12 +126,19 @@ class QuestionViewSet(ModelViewSet):
|
|||
@action(methods=['get'], detail=False,
|
||||
url_path='correct', url_name='correct_question', permission_classes=[IsAuthenticated])
|
||||
def correct(self, request):
|
||||
for i in Question.objects.all():
|
||||
# for i in Question.objects.all():
|
||||
# options = i.options
|
||||
# for k in options:
|
||||
# options[k] = str(options[k]).replace('<p>','').replace('</p>','')\
|
||||
# .replace('×','×').replace('β','β').replace('α','α')\
|
||||
# .replace('γ','γ').replace(' ',' ')
|
||||
# i.options = options
|
||||
# i.save()
|
||||
for i in Question.objects.filter(Q(options__A__contains='μ')|Q(options__B__contains='μ')|Q(options__C__contains='μ')|Q(options__D__contains='μ')|Q(options__E__contains='μ')|Q(options__F__contains='μ')):
|
||||
print(i)
|
||||
options = i.options
|
||||
for k in options:
|
||||
options[k] = str(options[k]).replace('<p>','').replace('</p>','')\
|
||||
.replace('×','×').replace('β','β').replace('α','α')\
|
||||
.replace('γ','γ').replace(' ',' ')
|
||||
options[k] = str(options[k]).replace('μ','μ')
|
||||
i.options = options
|
||||
i.save()
|
||||
return Response()
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -0,0 +1,48 @@
|
|||
from django.db.models.query import QuerySet
|
||||
|
||||
class CreateUpdateModelAMixin:
|
||||
"""
|
||||
业务用基本表A用
|
||||
"""
|
||||
def perform_create(self, serializer):
|
||||
serializer.save(create_by = self.request.user)
|
||||
|
||||
def perform_update(self, serializer):
|
||||
serializer.save(update_by = self.request.user)
|
||||
|
||||
class CreateUpdateModelBMixin:
|
||||
"""
|
||||
业务用基本表B用
|
||||
"""
|
||||
def perform_create(self, serializer):
|
||||
serializer.save(create_by = self.request.user, belong_dept=self.request.user.dept)
|
||||
|
||||
def perform_update(self, serializer):
|
||||
serializer.save(update_by = self.request.user)
|
||||
|
||||
class CreateUpdateCustomMixin:
|
||||
"""
|
||||
整合
|
||||
"""
|
||||
def perform_create(self, serializer):
|
||||
if hasattr(self.queryset.model, 'belong_dept'):
|
||||
serializer.save(create_by = self.request.user, belong_dept=self.request.user.dept)
|
||||
else:
|
||||
serializer.save(create_by = self.request.user)
|
||||
def perform_update(self, serializer):
|
||||
serializer.save(update_by = self.request.user)
|
||||
|
||||
class OptimizationMixin:
|
||||
"""
|
||||
性能优化,需要在序列化器里定义setup_eager_loading,可在必要的View下继承
|
||||
"""
|
||||
def get_queryset(self):
|
||||
queryset = self.queryset
|
||||
if isinstance(queryset, QuerySet):
|
||||
# Ensure queryset is re-evaluated on each request.
|
||||
queryset = queryset.all()
|
||||
if hasattr(self.get_serializer_class(), 'setup_eager_loading'):
|
||||
queryset = self.get_serializer_class().setup_eager_loading(queryset) # 性能优化
|
||||
return queryset
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
from sympy import *
|
||||
|
||||
x1 = Symbol('x1')
|
||||
x2 = Symbol('x2')
|
||||
x3 = Symbol('x3')
|
||||
y1 = Symbol('y1')
|
||||
y2 = Symbol('y2')
|
||||
y3 = Symbol('y3')
|
||||
f = [
|
||||
y1+y2+y3-10,
|
||||
x1+x2+x3-40,
|
||||
2*x1+4*y1-36,
|
||||
2*x2+4*y2-36,
|
||||
]
|
||||
print(solve(f))
|
||||
Loading…
Reference in New Issue