monitest complete

This commit is contained in:
caoqianming 2020-03-20 18:24:17 +08:00
parent 54ee7e06f1
commit fc66951a17
46 changed files with 1053 additions and 153 deletions

View File

@ -16,7 +16,7 @@
:value="item.value"
/>
</el-select>
<el-select
<!-- <el-select
v-model="listQuery.is_paid"
placeholder="是否缴费"
clearable
@ -30,7 +30,7 @@
:label="item.display_name"
:value="item.key"
/>
</el-select>
</el-select> -->
<el-input
v-model="search"
placeholder="姓名"
@ -96,10 +96,14 @@
v-if="scope.row.company_name != null"
>{{ scope.row.company_name }}</template>
</el-table-column>
<el-table-column align="center" label="是否付费">
<template slot-scope="scope">
<el-tag type="success" v-if="scope.row.is_paid">已付费</el-tag>
<el-tag type="danger" v-else>未付费</el-tag>
<el-table-column align="center" label="缴费科目">
<template slot-scope="scope" >
<el-tag
v-for="item in scope.row.subjects"
:key="item.id"
effect="dark">
{{ item.name }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="创建日期">
@ -153,7 +157,7 @@
</el-form-item>
<el-form-item label="单位" prop="company">
<el-cascader
v-model="consumer.company"
v-model="consumer.company.id"
:options="companyData"
:props="{ checkStrictly: true }"
clearable
@ -188,8 +192,10 @@ const defaultConsumer = {
id: "",
name: "",
username: "",
company: null,
is_paid: false
company: {
id:0,
name:''
},
};
const listQuery = {
page: 1,
@ -206,13 +212,7 @@ export default {
return {
uploadUrl: uploadUrl(),
popovervisible: false,
consumer: {
id: "",
name: "",
username: "",
company: null,
ispaid: false
},
consumer: defaultConsumer,
myHeaders: { Authorization: "JWT " + getToken() },
consumerList: [],
total: 0,
@ -345,7 +345,9 @@ export default {
if (valid) {
const isEdit = this.dialogType === "edit";
if (isEdit) {
updateConsumer(this.consumer.id, this.consumer).then(() => {
let consumer = this.consumer
consumer.company = consumer.company.id
updateConsumer(this.consumer.id, consumer).then(() => {
for (let index = 0; index < this.consumerList.length; index++) {
if (this.consumerList[index].id === this.consumer.id) {
this.consumerList.splice(
@ -365,8 +367,10 @@ export default {
});
});
} else {
this.consumer.company = this.consumer.company.pop();
createConsumer(this.consumer).then(res => {
this.consumer.company.id = this.consumer.company.id.pop();
let consumer = this.consumer
consumer.company = consumer.company.id
createConsumer(consumer).then(res => {
// this.consumer = res.data
// this.consumerList.unshift(this.consumer)
this.getList();

View File

@ -11,7 +11,11 @@
"pages/cuoti/index",
"pages/moni/index",
"pages/moni/note",
"pages/test/test"
"pages/test/test",
"pages/test/result",
"pages/test/detail",
"pages/test/sheet",
"pages/test/list"
],
"window": {
"backgroundTextStyle": "light",

View File

@ -8,20 +8,20 @@ Page({
*/
data: {
ctms: [],
tmIndex: 0,
tm_index: 0,
isright:false,
answerP:false
},
radioChange: function (e) {
var that = this
that.data.currentTm['user_answer'] = e.detail.value
that.data.ctms[that.data.tmIndex] = that.data.currentTm
that.data.ctms[that.data.tm_index] = that.data.currentTm
that.showAnswer()
},
checkboxChange: function (e) {
var that = this
that.data.currentTm['user_answer'] = e.detail.value
that.data.ctms[that.data.tmIndex] = that.data.currentTm
that.data.ctms[that.data.tm_index] = that.data.currentTm
},
/**
* 生命周期函数--监听页面加载
@ -64,7 +64,7 @@ Page({
}
})
}else{
that.showTm(that.data.tmIndex)
that.showTm(that.data.tm_index)
}
},
@ -123,7 +123,7 @@ Page({
var that = this
var currentTm = that.data.ctms[index]
that.setData({
'tmIndex': index,
'tm_index': index,
'tmtotal':that.data.ctms.length,
'currentTm': currentTm
})
@ -165,13 +165,13 @@ Page({
},
next: function () {
var that = this
var tmIndex = that.data.tmIndex + 1
that.showTm(tmIndex)
var tm_index = that.data.tm_index + 1
that.showTm(tm_index)
},
previous: function () {
var that = this
var tmIndex = that.data.tmIndex - 1
that.showTm(tmIndex)
var tm_index = that.data.tm_index - 1
that.showTm(tm_index)
},
showOptions: function () {
let currentTm = this.data.currentTm
@ -195,7 +195,7 @@ Page({
},
remove: function () {
var that = this
var index = that.data.tmIndex
var index = that.data.tm_index
that.data.ctms.splice(index,1)
if(that.data.ctms.length>index){
that.showTm(index)

View File

@ -1,9 +1,9 @@
<view class="head">
题量: {{tmIndex+1}}/{{tmtotal}}
题量: {{tm_index+1}}/{{tmtotal}}
</view>
<scroll-view scroll-y="true" style="height: {{scrollHeight}}px;">
<view class="weui-article">
<view class="weui-article__h2">{{tmIndex+1}}.
<view class="weui-article__h2">{{tm_index+1}}.
<span class="txlabel">{{currentTm.type}}</span>
</view>
<view style="text-align:center">
@ -52,10 +52,10 @@
</scroll-view>
<view class="btns">
<view style="width:25%">
<button type="primary" size="mini" bindtap="previous" disabled="{{tmIndex==0}}">上题</button>
<button type="primary" size="mini" bindtap="previous" disabled="{{tm_index==0}}">上题</button>
</view>
<view style="width:25%">
<button type="primary" size="mini" bindtap="next" disabled="{{tmIndex==tmtotal-1}}">下题</button>
<button type="primary" size="mini" bindtap="next" disabled="{{tm_index==tmtotal-1}}">下题</button>
</view>
<view style="width:25%">
<button type="primary" size="mini" bindtap="showAnswer">答案</button>

View File

@ -11,14 +11,14 @@ Page({
tms:[],
ydtms:[],
ctms:[],
tmIndex: 0,
tm_index: 0,
answerP: false,
isLoad:true,
},
radioChange: function (e) {
var that = this
that.data.tm_current['user_answer'] = e.detail.value
that.data.tms[that.data.tmIndex] = that.data.tm_current
that.data.tms[that.data.tm_index] = that.data.tm_current
that.showAnswer()
if (that.data.ydtms.indexOf(that.data.tm_current.id)==-1){
that.data.ydtms.push(that.data.tm_current.id)
@ -27,7 +27,7 @@ Page({
checkboxChange: function (e) {
var that = this
that.data.tm_current['user_answer'] = e.detail.value
that.data.tms[that.data.tmIndex] = that.data.tm_current
that.data.tms[that.data.tm_index] = that.data.tm_current
if (that.data.ydtms.indexOf(that.data.tm_current.id) == -1) {
that.data.ydtms.push(that.data.tm_current.id)
}
@ -81,7 +81,7 @@ Page({
})
}else{
that.data.tms = that.data.tms.concat(res.data.results)
that.showTm(that.data.tmIndex) //展示题目和答案
that.showTm(that.data.tm_index) //展示题目和答案
if(that.data.isLoad){
that.setData({
tmtotal: res.data.total,
@ -152,7 +152,7 @@ Page({
var that = this
var tm_current = that.data.tms[index]
that.setData({
'tmIndex': index,
'tm_index': index,
'tm_current': tm_current
})
that.showOptions()
@ -193,25 +193,25 @@ Page({
},
next: function () {
var that = this
var tmIndex = that.data.tmIndex + 1
var tm_index = that.data.tm_index + 1
that.setData({
tmIndex: tmIndex,
tm_index: tm_index,
answerP: false
})
if (tmIndex + 1 > that.data.tms.length) {
if (tm_index + 1 > that.data.tms.length) {
that.getTms()
} else {
that.showTm(tmIndex)
that.showTm(tm_index)
}
},
previous: function () {
var that = this
var tmIndex = that.data.tmIndex - 1
var tm_index = that.data.tm_index - 1
that.setData({
answerP: false
})
that.showTm(tmIndex)
that.showTm(tm_index)
},
showOptions: function () {
let tm_current = this.data.tm_current

View File

@ -1,9 +1,9 @@
<view class="head">
题量: {{tmIndex+1}}/{{tmtotal}}
题量: {{tm_index+1}}/{{tmtotal}}
</view>
<scroll-view scroll-y="true" style="height: {{scrollHeight}}px;">
<view class="weui-article">
<view class="weui-article__h2">{{tmIndex+1}}.
<view class="weui-article__h2">{{tm_index+1}}.
<span class="txlabel">{{tm_current.type}}</span>
</view>
<view class="weui-article__title">{{tm_current.name}}</view>
@ -48,10 +48,10 @@
</scroll-view>
<view class="btns">
<view style="width:25%">
<button type="primary" size="mini" bindtap="previous" disabled="{{tmIndex==0}}">上题</button>
<button type="primary" size="mini" bindtap="previous" disabled="{{tm_index==0}}">上题</button>
</view>
<view style="width:25%">
<button type="primary" size="mini" bindtap="next" disabled="{{tmIndex==tmtotal-1}}">下题</button>
<button type="primary" size="mini" bindtap="next" disabled="{{tm_index==tmtotal-1}}">下题</button>
</view>
<view style="width:25%">
<button type="primary" size="mini" bindtap="showAnswer">答案</button>

View File

@ -143,5 +143,16 @@ Page({
duration: 1500
})
}
},
goYati: function () {
wx.showToast({
title: '暂未开放',
icon:'none'
})
},
testList: function (){
wx.navigateTo({
url: '/pages/test/list',
})
}
})

View File

@ -47,14 +47,14 @@
</view>
<view class="weui-grid__label">自助模考</view>
</a>
<a class="weui-grid">
<view class="weui-grid__icon">
<a class="weui-grid" bindtap="goYati">
<view class="weui-grid__icon" >
<image src="/images/yati.svg" alt></image>
</view>
<view class="weui-grid__label">押题考试</view>
</a>
<a class="weui-grid">
<view class="weui-grid__icon">
<a class="weui-grid" bindtap="testList">
<view class="weui-grid__icon" >
<image src="/images/ksjl.svg" alt></image>
</view>
<view class="weui-grid__label">考试记录</view>

View File

@ -91,7 +91,7 @@ Page({
wx.showLoading({
title: '正在生成试卷',
})
api.request('examtest/monitest/', 'GET', { 'rule': e.currentTarget.id }).then(res => {
api.request('examtest/testrule/' + e.currentTarget.id + '/monitest', 'GET').then(res => {
try {
wx.setStorageSync('monitest', res.data)
} catch (e) { }

View File

@ -0,0 +1,125 @@
// pages/test/detail.js
const api = require("../../utils/request.js");
Page({
/**
* 页面的初始数据
*/
data: {
tm_index:0,
results:[]
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
var that = this
var query = {'examtest':options.id}
api.request('examtest/answerdetail/', 'GET', query).then(res => {
that.data.results= res.data
that.showTm(0)
that.setData({
tmtotal:res.data.length
})
})
try {
const res = wx.getSystemInfoSync()
that.setData({
scrollHeight: res.windowHeight - 70
})
} catch (e) {
}
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
},
showTm: function (index) {
var that = this
var tm_current = that.data.results[index]
that.setData({
'tm_index': index,
'tm_current': tm_current
})
that.showOptions()
},
next: function () {
var that = this
var tm_index = that.data.tm_index + 1
that.showTm(tm_index)
},
previous: function () {
var that = this
var tm_index = that.data.tm_index - 1
that.showTm(tm_index)
},
showOptions: function () {
var that = this
let question_options = that.data.tm_current.question.options
let options = []
let user_answer = that.data.tm_current.user_answer
for (let key in question_options) {
let option = {}
option.key = key
option.value = key + ':' + question_options[key]
if (user_answer) {
if (key == user_answer || user_answer.indexOf(key) != -1) {
option.checked = true
}
} else {
option.checked = false
}
options.push(option)
}
that.setData({
options: options
})
},
})

View File

@ -0,0 +1,3 @@
{
"usingComponents": {}
}

View File

@ -0,0 +1,60 @@
<view class="head">
题量: {{tm_index+1}}/{{tmtotal}}
</view>
<scroll-view scroll-y="true" style="height: {{scrollHeight}}px;">
<view class="weui-article">
<view class="weui-article__h2">{{tm_index+1}}.
<span class="txlabel">{{tm_current.question.type}}</span>
</view>
<view class="weui-article__title">{{tm_current.question.name}}</view>
</view>
<view class="weui-cells weui-cells_radio">
<radio-group class="radio-group" wx:if="{{(tm_current.question.type=='单选' ||tm_current.question.type=='判断')}}">
<label class="weui-cell weui-cell_active weui-check__label" wx:for="{{options}}" wx:key="key">
<view class="weui-cell__bd">
<view>{{item.value}}</view>
</view>
<view class="weui-cell__ft">
<radio class="weui-check" value="{{item.key}}" checked="{{item.checked}}" />
<i class="weui-icon-checked"></i>
</view>
</label>
</radio-group>
</view>
<view class="weui-cells weui-cells_checkbox">
<checkbox-group bindchange="checkboxChange" wx:if="{{tm_current.question.type=='多选'}}">
<label class="weui-cell weui-cell_active weui-check__label" wx:for="{{options}}" wx:key="key">
<view class="weui-cell__bd">
<view>{{item.value}}</view>
</view>
<view class="weui-cell__hd">
<checkbox class="weui-check" value="{{item.key}}" checked="{{item.checked}}"/>
<i class="weui-icon-checked"></i>
</view>
</label>
</checkbox-group>
</view>
<view class="weui-article">
<view class="weui-article__h2" wx:if="{{tm_current.is_right}}" style="color:green;font-weight:bold">回答正确!</view>
<view class="weui-article__h2" wx:else style="color:red;font-weight:bold">回答有误!</view>
<view class="weui-article__h2">正确答案是{{tm_current.question.right}},你的答案是{{tm_current.user_answer}}</view>
<view class="weui-article__title">
<span style="color:blue">解析: </span>
<span wx:if="{{tm_current.question.resoluation != null}}">{{tm_current.question.resoluation}}</span>
<span wx:else>无</span>
</view>
</view>
</scroll-view>
<view class="btns">
<view style="width:33%">
<button type="primary" size="mini" bindtap="previous" disabled="{{tm_index==0}}">上题</button>
</view>
<view style="width:33%">
<button type="primary" size="mini" bindtap="next" disabled="{{tm_index==tmtotal-1}}">下题</button>
</view>
<view style="width:33%">
<image style="height: 80%;" src="/images/weishoucang.svg" bindtap="shoucang" wx:if="weishoucang"></image>
<image style="height: 80%;" src="/images/yishoucang.svg" bindtap="shoucang" wx:else></image>
</view>
</view>

View File

@ -0,0 +1,20 @@
.head{
width:100%;
height:30px;
color:#fff;
background-color: cornflowerblue;
text-align: center;
}
.btns{
height:40px;
display:flex;
flex-direction: row;
flex-wrap: wrap;
text-align:center;
}
.txlabel{
color:#fff;
background-color: rgb(216, 140, 0);
padding: 2px
}

View File

@ -0,0 +1,102 @@
// pages/lianxi/index.js
const api = require("../../utils/request.js");
Page({
/**
* 页面的初始数据
*/
data: {
results: [],
query:{
page:1,
limit:10
}
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function () {
var that = this
that.getList(that.data.query)
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
getList: function () {
var that = this
api.request('examtest/myexamtest/', 'GET', that.data.query).then(res => {
if(res.data.length==0){
wx.showToast({
title: '没有更多了',
icon:''
})
}else{
if (that.data.query.page == 1){
that.data.results = res.data.results
}else{
that.data.results = that.data.results.concat(res.data.results)
}
that.setData({
results:that.data.results,
count:res.data.count
})
}
})
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
var that = this
that.data.query.page = 1;
that.getList();
wx.stopPullDownRefresh();
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
that.data.query.page = that.data.query.page + 1
that.getList()
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
},
detail: function (e) {
wx.navigateTo({
url: '',
})
},
})

View File

@ -0,0 +1,6 @@
{
"usingComponents": {},
"navigationBarTitleText": "考试记录",
"enablePullDownRefresh": true,
"onReachBottomDistance": 50
}

View File

@ -0,0 +1,30 @@
<view class="head">
共{{count}}条考试记录</view>
<view class="weui-cells weui-cells_after-title">
<block wx:for="{{results}}" wx:key="unique">
<navigator url="detail?id={{item.id}}" class="weui-media-box weui-media-box_appmsg" hover-class="weui-cell_active">
<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" style="color:orange">
<span style="font-weight:bold;color:white;background-color:orange;">{{item.type}}</span>
<span>-</span>
<span style="font-weight:bold;color:white;background-color:green;" wx:if="{{item.is_pass}}">通过</span>
<span style="font-weight:bold;color:white;background-color:red;" wx:else>未通过</span>
(得分
<span style="color:green;font-weight:bold" wx:if="{{item.is_pass}}">{{item.score}}</span>
<span style="color:red;font-weight:bold" wx:else>{{item.score}}</span>
-满分
<span style="font-weight:bold">{{item.total_score}})</span>
</view>
<view class="weui-media-box__desc" style="color:orange">
耗时:{{item.took}}s
开始答题:{{item.start_time}}
</view>
</view>
<view class="weui-panel__ft weui-cell__ft_in-access">
<view class="weui-media-box__desc">答卷详情</view>
</view>
</navigator>
</block>
</view>

View File

@ -0,0 +1,5 @@
.head{
color:#fff;
background-color: cornflowerblue;
text-align: center;
}

View File

@ -0,0 +1,76 @@
// pages/examtest/result.js
Page({
/**
* 页面的初始数据
*/
data: {
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function () {
this.setData(getApp().globalData.testData)
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
},
detail: function () {
wx.redirectTo({
url: 'detail?id=' + this.data.id,
})
},
back: function () {
wx.switchTab({
url: '/pages/main/main'
})
},
})

View File

@ -0,0 +1,3 @@
{
"usingComponents": {}
}

View File

@ -0,0 +1,29 @@
<view class="page">
<view class="weui-msg">
<view class="weui-msg__icon-area" wx:if="{{is_pass}}"><i class="weui-icon-success weui-icon_msg"></i></view>
<view class="weui-msg__icon-area" wx:else><i class="weui-icon-warn weui-icon_msg"></i></view>
<view class="weui-msg__text-area">
<h2 class="weui-msg__title" wx:if="{{is_pass}}">恭喜您,通过考试</h2>
<h2 class="weui-msg__title" wx:else>很遗憾,下次加油</h2>
<view class="weui-msg__desc">
得分
<span style="color:green;font-weight:bold" wx:if="{{is_pass}}">{{score}}</span>
<span style="color:red;font-weight:bold" wx:else>{{score}}</span>
——满分
<span style="font-weight:bold">{{total_score}}</span>
</view>
<view class="weui-msg__desc">
用时:
<span style="color:green;font-weight:bold" wx:if="{{is_pass}}">{{took}}</span>
<span style="color:red;font-weight:bold" wx:else>{{took}}</span>
</view>
</view>
<view class="weui-msg__opr-area">
<view class="weui-btn-area">
<a class="weui-btn weui-btn_primary" bindtap="detail">查看答卷详情</a>
<a class="weui-btn weui-btn_default" bindtap="back">返回首页</a>
</view>
</view>
</view>
</view>

View File

@ -0,0 +1 @@
/* pages/test/note.wxss */

View File

@ -0,0 +1,86 @@
// pages/examtest/sheet.js
Page({
/**
* 页面的初始数据
*/
data: {
},
back: function (e) {
console.log(e.currentTarget.dataset.index);
var tm_index = e.currentTarget.dataset.index
var pages = getCurrentPages();
var prevPage = pages[pages.length - 2]; //上一个页面
prevPage.setData({
tm_index: tm_index
})
prevPage.showTm(tm_index)
prevPage.showOptions()
wx.navigateBack({
})
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
var pages = getCurrentPages();
var prevPage = pages[pages.length - 2]; //上一个页面
var tms = prevPage.data.tms //取上页data里的数据也可以修改
this.setData({
tms: tms
})
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
}
})

View File

@ -0,0 +1,4 @@
{
"usingComponents": {},
"navigationBarTitleText": "答题卡"
}

View File

@ -0,0 +1,13 @@
<!--pages/examtest/sheet.wxml-->
<view style="width:100%;display:flex;padding:20rpx;flex-wrap: wrap ">
<view wx:for="{{tms}}" wx:key="id" >
<view wx:if="{{item.user_answer && item.user_answer.length !=0 }}" class="ok" data-index="{{index}}" bindtap='back'>
{{index+1}}
</view>
<view wx:else class="no" data-index="{{index}}" bindtap='back'>
{{index+1}}
</view>
</view>
</view>

View File

@ -0,0 +1,21 @@
/* pages/examtest/sheet.wxss */
.ok{
display: flex;
color:#fff;
background-color: green;
border:4rpx solid green;
height:100rpx;
width:100rpx;
margin:20rpx;
justify-content: center;
align-items: center;
}
.no{
display: flex;
border:4rpx solid red;
height:100rpx;
width:100rpx;
margin:20rpx;
justify-content: center;
align-items: center;
}

View File

@ -43,6 +43,12 @@ Page({
})
} catch (e) {
}
try {
var value = wx.getStorageSync('ctms')
if (value) {
that.data.ctms = value
}
} catch (e) { }
let mil = that.data.monitest.limit * 60 * 1000
let starttimes = (new Date()).getTime() //时间戳
let endtimes = starttimes + mil
@ -78,6 +84,9 @@ Page({
*/
onUnload: function () {
clearInterval(getApp().globalData.timer)
try {
wx.setStorageSync('ctms', this.data.ctms)
} catch (e) { }
},
/**
@ -178,6 +187,11 @@ Page({
options: options
})
},
sheet: function () {
wx.navigateTo({
url: 'sheet',
})
},
hand: function () {
var that = this
for (var i = 0, len = that.data.tms.length; i < len; i++) {
@ -219,19 +233,35 @@ Page({
for (var i = 0, len = that.data.tms.length; i < len; i++) {
let tm_result = that.panTi(that.data.tms[i])
that.data.tms[i].is_right = tm_result.is_right
if (tm_result.is_right == false){
that.data.ctms.unshift(that.data.tms[i])
if (that.data.ctms.length > 40) {
that.data.ctms.length = 40
}
}
that.data.tms[i].score = tm_result.score
score = score + tm_result.score
}
that.data.monitest.score = score
if (score >= that.data.monitest.pass_score){
that.data.monitest.is_pass = true
}else{
that.data.monitest.is_pass = false
}
console.log(that.data.tms)
that.data.monitest.questions = that.data.tms
that.data.monitest.start_time = util.formatTime(new Date(that.data.starttimes))
that.data.monitest.end_time = util.formatTime(new Date())
that.data.monitest.took = Math.floor(((new Date()).getTime() - this.data.starttimes) / 1000)
console.log(that.data.monitest)
// api.request('examtest/monitest/', 'POST', that.data.monitest).then(res => {
// wx.redirectTo({
// url: 'note',
// })
// })
api.request('examtest/monitest/', 'POST', that.data.monitest).then(res => {
getApp().globalData.testData = res.data
try {
wx.removeStorageSync('monitest')
} catch (e) {
}
wx.redirectTo({
url: 'result',
})
})
}
})

View File

@ -1,4 +1,4 @@
{
"usingComponents": {},
"navigationBarTitleText": "考试中"
"navigationBarTitleText": "答题中"
}

View File

@ -53,7 +53,7 @@
<button type="primary" size="mini" bindtap="next" disabled="{{tm_index==tm_total-1}}">下题</button>
</view>
<view style="width:25%">
<button type="primary" size="mini" bindtap="sheet">答题卡</button>
<a class="weui-btn weui-btn_mini weui-btn_primary" bindtap="sheet">答题卡</a>
</view>
<view style="width:25%">
<a class="weui-btn weui-btn_mini weui-btn_warn" bindtap="hand">交卷</a>

View File

@ -6,7 +6,7 @@ const formatTime = date => {
const minute = date.getMinutes()
const second = date.getSeconds()
return [year, month, day].map(formatNumber).join('/') + ' ' + [hour, minute, second].map(formatNumber).join(':')
return [year, month, day].map(formatNumber).join('-') + ' ' + [hour, minute, second].map(formatNumber).join(':')
}
const formatNumber = n => {

View File

@ -0,0 +1,39 @@
# Generated by Django 3.0.4 on 2020-03-20 09:26
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
('question', '0007_auto_20200319_0846'),
('crm', '0006_auto_20200310_1531'),
]
operations = [
migrations.RemoveField(
model_name='consumer',
name='is_paid',
),
migrations.CreateModel(
name='PaySubject',
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='删除标记')),
('consumer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='crm.Consumer')),
('subject', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='question.Questioncat')),
],
options={
'abstract': False,
},
),
migrations.AddField(
model_name='consumer',
name='subjects',
field=models.ManyToManyField(through='crm.PaySubject', to='question.Questioncat', verbose_name='付费学科'),
),
]

View File

@ -1,9 +1,10 @@
from django.db import models
import django.utils.timezone as timezone
from rbac.models import CommonModel
from rbac.models import SoftCommonModel, CommonModel
from question.models import Questioncat
# Create your models here.
class Company(CommonModel):
class Company(SoftCommonModel):
"""
客户企业
"""
@ -17,7 +18,7 @@ class Company(CommonModel):
def __str__(self):
return self.name
class Consumer(CommonModel):
class Consumer(SoftCommonModel):
"""
学员
"""
@ -27,7 +28,7 @@ class Consumer(CommonModel):
openid = models.CharField(max_length=200, verbose_name="openid", null=True, blank=True, unique=True)
avatar = models.CharField(default="/media/default/avatar.png",max_length=1000, null=True, blank=True, verbose_name="头像")
nickname = models.CharField(max_length=200, verbose_name="昵称", null=True, blank=True)
is_paid = models.BooleanField(default=False,verbose_name="是否付费")
subjects = models.ManyToManyField(Questioncat, verbose_name="付费学科", through="PaySubject")
class Meta:
@ -35,4 +36,11 @@ class Consumer(CommonModel):
verbose_name_plural = verbose_name
def __str__(self):
return self.name
return self.name
class PaySubject(CommonModel):
'''
付费学科关联表
'''
consumer = models.ForeignKey(Consumer, on_delete=models.CASCADE)
subject = models.ForeignKey(Questioncat, on_delete=models.CASCADE)

View File

@ -24,3 +24,15 @@ class ConsumerSerializer(serializers.ModelSerializer):
class Meta:
model = Consumer
fields = '__all__'
depth = 1
class ConsumerCUSerializer(serializers.ModelSerializer):
"""
客户新增编辑序列化
"""
create_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False, read_only=True)
update_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False, read_only=True)
class Meta:
model = Consumer
fields = '__all__'

View File

@ -14,9 +14,10 @@ import json
from utils.custom import CommonPagination
from rbac.permission import RbacPermission
from .models import Company, Consumer
from .serializers import CompanySerializer, ConsumerSerializer
from .models import Company, Consumer, PaySubject
from .serializers import CompanySerializer, ConsumerSerializer, ConsumerCUSerializer
from server import settings
from question.models import Questioncat
appid = 'wx5c39b569f01c27db'
secret = '68762892f8df2b4a0b1940c5250a8dc0'
@ -70,9 +71,14 @@ class ConsumerViewSet(ModelViewSet):
ordering_fields = ('id',)
ordering = ['id']
filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
filterset_fields = ('is_paid','company')
filterset_fields = ('company',)
search_fields = ('^name',)
def get_serializer_class(self):
if self.action == 'list':
return ConsumerSerializer
else:
return ConsumerCUSerializer
def destroy(self, request, *args, **kwargs): #逻辑删除
instance = self.get_object()
@ -125,8 +131,10 @@ class ConsumerViewSet(ModelViewSet):
obj.name = name
obj.username = username
obj.company = companyobj
obj.is_paid = True
obj.save()
subjects = Questioncat.objects.filter(is_subject=True,is_delete=False)
if subjects.exists():
PaySubject.objects.create(subject=subjects.first(), consumer=obj)
i = i + 1
if consumerdict:
return {"code":206,"data":consumerdict,"msg":"导入部分成功"}

View File

@ -50,7 +50,7 @@ class Migration(migrations.Migration):
field=models.FloatField(default=0, verbose_name='判断分数'),
),
migrations.CreateModel(
name='MoniTest',
name='ExamTest',
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='创建时间')),
@ -73,8 +73,8 @@ class Migration(migrations.Migration):
),
migrations.AddField(
model_name='answerdetail',
name='monitest',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='examtest.MoniTest'),
name='examtest',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='examtest.ExamTest'),
),
migrations.AddField(
model_name='answerdetail',

View File

@ -29,7 +29,7 @@ class Migration(migrations.Migration):
options={'verbose_name': '答题记录', 'verbose_name_plural': '答题记录'},
),
migrations.AlterModelOptions(
name='monitest',
name='examtest',
options={'verbose_name': '自助模考', 'verbose_name_plural': '自助模考'},
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 3.0.4 on 2020-03-20 03:12
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('examtest', '0009_auto_20200319_1850'),
]
operations = [
migrations.AddField(
model_name='testrule',
name='is_pass',
field=models.BooleanField(default=True, verbose_name='是否通过'),
),
]

View File

@ -0,0 +1,42 @@
# Generated by Django 3.0.4 on 2020-03-20 03:15
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('examtest', '0010_testrule_is_pass'),
]
operations = [
migrations.RemoveField(
model_name='testrule',
name='is_pass',
),
migrations.AddField(
model_name='examtest',
name='is_pass',
field=models.BooleanField(default=True, verbose_name='是否通过'),
),
migrations.AddField(
model_name='examtest',
name='total_score',
field=models.FloatField(default=0, verbose_name='总分'),
),
migrations.AlterField(
model_name='examtest',
name='score',
field=models.FloatField(default=0, verbose_name='得分'),
),
migrations.AlterField(
model_name='testrule',
name='pass_score',
field=models.FloatField(default=0, verbose_name='及格分数'),
),
migrations.AlterField(
model_name='testrule',
name='total_score',
field=models.FloatField(default=0, verbose_name='满分'),
),
]

View File

@ -0,0 +1,50 @@
# Generated by Django 3.0.4 on 2020-03-20 06:39
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
('examtest', '0011_auto_20200320_1115'),
]
operations = [
migrations.CreateModel(
name='Paper',
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='删除标记')),
('name', models.CharField(max_length=200, verbose_name='名称')),
],
options={
'abstract': False,
},
),
migrations.DeleteModel(
name='PaperTest',
),
migrations.AlterModelOptions(
name='examtest',
options={'verbose_name': '考试表', 'verbose_name_plural': '考试表'},
),
migrations.AlterField(
model_name='examtest',
name='rule',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='examtest.TestRule', verbose_name='所用规则'),
),
migrations.AlterField(
model_name='examtest',
name='type',
field=models.CharField(choices=[('自助模考', '自助模考'), ('押卷模考', '押卷模考')], default='自助模考', max_length=50, verbose_name='考试类型'),
),
migrations.AddField(
model_name='examtest',
name='paper',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='examtest.Paper', verbose_name='所用试卷'),
),
]

View File

@ -1,11 +1,11 @@
from django.db import models
from rbac.models import CommonModel
from rbac.models import SoftCommonModel, CommonModel
from django.contrib.postgres.fields import JSONField, ArrayField
from question.models import Questioncat, Question
from crm.models import Consumer
# Create your models here.
class TestRule(CommonModel):
class TestRule(SoftCommonModel):
name = models.CharField(max_length=200, unique=True, verbose_name='名称')
desc = models.TextField(verbose_name='描述', default='')
subject = models.ForeignKey(Questioncat, blank=True, null=True, on_delete=models.CASCADE, verbose_name='所属学科', related_name='subject')
@ -17,8 +17,9 @@ class TestRule(CommonModel):
panduan_count = models.IntegerField(default=0, verbose_name='判断数量')
panduan_score = models.FloatField(default=0, verbose_name='判断分数')
limit = models.IntegerField(default=0, verbose_name='限时(分钟)')
total_score = models.IntegerField(default=0, verbose_name='满分')
pass_score = models.IntegerField(default=0, verbose_name='及格分数')
total_score = models.FloatField(default=0, verbose_name='满分')
pass_score = models.FloatField(default=0, verbose_name='及格分数')
class Meta:
verbose_name = '出题规则'
@ -27,31 +28,38 @@ class TestRule(CommonModel):
def __str__(self):
return self.name
class PaperTest(CommonModel):
pass
class Meta:
verbose_name = '押题模考'
verbose_name_plural = verbose_name
class MoniTest(CommonModel):
class Paper(SoftCommonModel):
name = models.CharField(max_length=200, verbose_name='名称')
type = models.CharField(max_length=50, default='自助模考',verbose_name='考试类型')
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='考试类型')
limit = models.IntegerField(default=0, verbose_name='限时(分钟)')
rule = models.ForeignKey(TestRule, on_delete=models.CASCADE, verbose_name='出题规则')
rule = models.ForeignKey(TestRule, on_delete=models.CASCADE, verbose_name='所用规则', null=True, blank=True)
paper = models.ForeignKey(Paper, on_delete=models.CASCADE, verbose_name='所用试卷', null=True, blank=True)
consumer = models.ForeignKey(Consumer, on_delete=models.CASCADE, verbose_name='模考人')
score = models.IntegerField(default=0, verbose_name='得分')
total_score = models.FloatField(default=0, verbose_name='总分')
score = models.FloatField(default=0, verbose_name='得分')
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')
is_pass = models.BooleanField(default=True, verbose_name='是否通过')
class Meta:
verbose_name = '自助模考'
verbose_name = '试表'
verbose_name_plural = verbose_name
class AnswerDetail(CommonModel):
monitest = models.ForeignKey(MoniTest, on_delete=models.CASCADE)
class AnswerDetail(SoftCommonModel):
examtest = models.ForeignKey(ExamTest, on_delete=models.CASCADE)
question = models.ForeignKey(Question, on_delete=models.CASCADE)
user_answer = JSONField()
score = models.FloatField(default=0, verbose_name='本题得分')

View File

@ -1,6 +1,7 @@
from rest_framework import serializers
from question.models import Questioncat
from .models import TestRule, MoniTest
from crm.models import Consumer
from .models import TestRule, ExamTest, AnswerDetail
@ -41,12 +42,36 @@ class MoniTestSerializer(serializers.ModelSerializer):
"""
自助模考序列化
"""
start_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", read_only=True)
end_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", read_only=True)
start_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S")
end_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S")
consumer = serializers.PrimaryKeyRelatedField(queryset=Consumer.objects.all(), required=False)
rule = serializers.PrimaryKeyRelatedField(queryset=TestRule.objects.all(), required=True)
create_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False, read_only=True)
update_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False, read_only=True)
class Meta:
model = MoniTest
model = ExamTest
fields = '__all__'
class ExamTestListSerializer(serializers.ModelSerializer):
"""
考试列表序列化
"""
start_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S")
end_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S")
create_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False, read_only=True)
update_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False, read_only=True)
class Meta:
model = ExamTest
fields = '__all__'
class AnswerDetailSerializer(serializers.ModelSerializer):
class Meta:
model = AnswerDetail
fields = '__all__'
depth = 1
class AnswerDetailCreateSerializer(serializers.ModelSerializer):
class Meta:
model = AnswerDetail
fields = '__all__'

View File

@ -1,5 +1,5 @@
from django.urls import path,include
from .views import TestRuleViewSet, MoniTestView
from .views import TestRuleViewSet, MoniTestView, MyExamTestView, AnswerDetailView
from rest_framework import routers
@ -8,5 +8,7 @@ router.register('testrule', TestRuleViewSet, basename="testrule")
urlpatterns = [
path('monitest/',MoniTestView.as_view()),
path('myexamtest/',MyExamTestView.as_view()),
path('answerdetail/', AnswerDetailView.as_view()),
path('', include(router.urls)),
]

View File

@ -15,60 +15,65 @@ from utils.custom import CommonPagination
from rbac.permission import RbacPermission
from question.models import Question
from question.serializers import QuestionSerializer
from .models import TestRule
from .serializers import TestRuleSerializer, TestRuleListSerializer, TestRuleCreateSerializer, MoniTestSerializer
from .models import TestRule, ExamTest, AnswerDetail
from .serializers import TestRuleSerializer, TestRuleListSerializer, TestRuleCreateSerializer, MoniTestSerializer, AnswerDetailSerializer, ExamTestListSerializer, AnswerDetailCreateSerializer
from server import settings
from crm.authentication import ConsumerTokenAuthentication
from utils.custom import CommonPagination
# Create your views here.
class MoniTestView(APIView):
authentication_classes = [ConsumerTokenAuthentication]
permission_classes = []
def post(self, request, *args, **kwargs):
data = request.data
pass
def get(self, request, *args, **kwargs):
'''
生成模拟考试
'''
if request.query_params.get('rule', None):
ret = {}
testrule = TestRule.objects.get(id = request.query_params.get('rule'))
ret['name'] = '自助模考' + datetime.now().strftime('%Y%m%d%H%M')
ret['type'] = '自助模考' # 自助模拟考试
ret['rule'] = testrule.id
ret['limit'] = testrule.limit
ret['total_score'] = testrule.total_score
ret['pass_score'] = testrule.pass_score
ret['danxuan_count'] = testrule.danxuan_count
ret['danxuan_score'] = testrule.danxuan_score
ret['duoxuan_count'] = testrule.duoxuan_count
ret['duoxuan_score'] = testrule.duoxuan_score
ret['panduan_count'] = testrule.panduan_count
ret['panduan_score'] = testrule.panduan_score
question_queryset = Question.objects.none()
queryset = Question.objects.filter(is_delete=0,questioncat__in = testrule.questioncat.all())
if ret['danxuan_count']:
danxuan = queryset.filter(type='单选').order_by('?')[:ret['danxuan_count']]
question_queryset = question_queryset | danxuan
if ret['duoxuan_count']:
duoxuan = queryset.filter(type='多选').order_by('?')[:ret['duoxuan_count']]
question_queryset = question_queryset | duoxuan
if ret['panduan_count']:
panduan = queryset.filter(type='判断').order_by('?')[:ret['panduan_count']]
question_queryset = question_queryset | panduan
questions = QuestionSerializer(instance=question_queryset.order_by('type'),many=True).data
for i in questions:
if i['type'] == 1:
i['total_score'] = ret['danxuan_score']
elif i['type'] == 2:
i['total_score'] = ret['duoxuan_score']
serializer = MoniTestSerializer(data = request.data)
if serializer.is_valid():
instance = serializer.save(consumer = request.user)
if 'questions' in request.data:
questions = []
for i in request.data['questions']:
question = {}
question['question'] = i['id']
question['examtest'] = instance.id
question['score'] = i['score']
if 'user_answer' in i:
question['user_answer'] = i['user_answer']
question['is_right'] = i['is_right']
questions.append(question)
serializer_detail = AnswerDetailCreateSerializer(data=questions, many=True)
if serializer_detail.is_valid():
serializer_detail.save()
return Response(MoniTestSerializer(instance).data,status=status.HTTP_200_OK)
else:
i['total_score'] = ret['panduan_score']
ret['questions'] = questions
return Response(ret)
return Response(serializer_detail.errors)
else:
return Response({'error':'答题记录不存在'})
else:
return Response(serializer.errors)
class MyExamTestView(APIView):
authentication_classes = [ConsumerTokenAuthentication]
permission_classes = []
def get(self, request, *args, **kwargs):
queryset = ExamTest.objects.filter(consumer=request.user)
pg = CommonPagination()
p = pg.paginate_queryset(queryset=queryset,request=request,view=self)
serializer = ExamTestListSerializer(instance=p,many=True)
return pg.get_paginated_response(serializer.data)
class AnswerDetailView(APIView):
authentication_classes = []
permission_classes = []
def get(self, request, *args, **kwargs):
queryset = AnswerDetail.objects.all()
if request.query_params.get('examtest', None):
queryset = queryset.filter(examtest=request.query_params.get('examtest'))
serializer = AnswerDetailSerializer(instance=queryset,many=True)
return Response(serializer.data)
@ -114,4 +119,46 @@ class TestRuleViewSet(ModelViewSet):
"""
if self.request.method == 'GET':
self.permission_classes = []
return [permission() for permission in self.permission_classes]
return [permission() for permission in self.permission_classes]
@action(methods=['get'], detail=True, permission_classes=[IsAuthenticated],
url_path='monitest', url_name='gen_monitest')
def monitest(self, request, pk=None):
'''
生成自助模拟考试
'''
ret = {}
testrule = self.get_object()
ret['name'] = '自助模考' + datetime.now().strftime('%Y%m%d%H%M')
ret['type'] = '自助模考' # 自助模拟考试
ret['rule'] = testrule.id
ret['limit'] = testrule.limit
ret['total_score'] = testrule.total_score
ret['pass_score'] = testrule.pass_score
ret['danxuan_count'] = testrule.danxuan_count
ret['danxuan_score'] = testrule.danxuan_score
ret['duoxuan_count'] = testrule.duoxuan_count
ret['duoxuan_score'] = testrule.duoxuan_score
ret['panduan_count'] = testrule.panduan_count
ret['panduan_score'] = testrule.panduan_score
question_queryset = Question.objects.none()
queryset = Question.objects.filter(is_delete=0,questioncat__in = testrule.questioncat.all())
if ret['danxuan_count']:
danxuan = queryset.filter(type='单选').order_by('?')[:ret['danxuan_count']]
question_queryset = question_queryset | danxuan
if ret['duoxuan_count']:
duoxuan = queryset.filter(type='多选').order_by('?')[:ret['duoxuan_count']]
question_queryset = question_queryset | duoxuan
if ret['panduan_count']:
panduan = queryset.filter(type='判断').order_by('?')[:ret['panduan_count']]
question_queryset = question_queryset | panduan
questions = QuestionSerializer(instance=question_queryset.order_by('type'),many=True).data
for i in questions:
if i['type'] == 1:
i['total_score'] = ret['danxuan_score']
elif i['type'] == 2:
i['total_score'] = ret['duoxuan_score']
else:
i['total_score'] = ret['panduan_score']
ret['questions'] = questions
return Response(ret)

View File

@ -1,10 +1,10 @@
from django.db import models
from rbac.models import CommonModel
from rbac.models import SoftCommonModel
from django.contrib.postgres.fields import JSONField, ArrayField
# Create your models here.
class Questioncat(CommonModel):
class Questioncat(SoftCommonModel):
name = models.CharField(max_length=200, unique=True, verbose_name='名称')
pid = models.ForeignKey('self', verbose_name='', null=True, blank=True, on_delete=models.CASCADE, related_name='questioncatpid')
is_subject = models.BooleanField(default=False, verbose_name='是否是学科')
@ -20,7 +20,7 @@ class Questioncat(CommonModel):
return self.questioncat.count()
class Question(CommonModel):
class Question(SoftCommonModel):
type_choices = (
('单选', '单选'),
('多选', '多选'),

View File

@ -13,7 +13,7 @@ class SoftDeletManager(models.Manager):
'''
def get_queryset(self):
"""
在这里处理一下QuerySet, 然后返回没被标记位is_deleted的QuerySet
在这里处理一下QuerySet, 然后返回没被标记位is_delete的QuerySet
"""
kwargs = {'model': self.model, 'using': self._db}
if hasattr(self, '_hints'):
@ -21,7 +21,7 @@ class SoftDeletManager(models.Manager):
return self._queryset_class(**kwargs).filter(is_delete=False)
class CommonModel(models.Model):
class SoftCommonModel(models.Model):
create_time = models.DateTimeField(default=timezone.now, verbose_name='创建时间', help_text='创建时间')
update_time = models.DateTimeField(auto_now=True, verbose_name='修改时间', help_text='修改时间')
is_delete = models.BooleanField(default=False, verbose_name='删除标记', help_text='删除标记')
@ -39,10 +39,18 @@ class CommonModel(models.Model):
self.is_delete = True
self.save(using=using)
else:
return super(CommonModel, self).delete(using=using, *args, **kwargs)
return super(SoftCommonModel, self).delete(using=using, *args, **kwargs)
class CommonModel(models.Model):
create_time = models.DateTimeField(default=timezone.now, verbose_name='创建时间', help_text='创建时间')
update_time = models.DateTimeField(auto_now=True, verbose_name='修改时间', help_text='修改时间')
is_delete = models.BooleanField(default=False, verbose_name='删除标记', help_text='删除标记')
class Meta:
abstract = True
class Menu(CommonModel):
class Menu(SoftCommonModel):
"""
功能权限:目录,菜单,权限
"""
@ -68,7 +76,7 @@ class Menu(CommonModel):
ordering = ['id']
class Role(CommonModel):
class Role(SoftCommonModel):
"""
角色
"""
@ -83,7 +91,7 @@ class Role(CommonModel):
def __str__(self):
return self.name
class Organization(CommonModel):
class Organization(SoftCommonModel):
"""
组织架构
"""