task rate

This commit is contained in:
caoqianming 2021-03-17 09:23:55 +08:00
parent ec2499a147
commit 7d53e69be0
12 changed files with 180 additions and 48 deletions

View File

@ -5,6 +5,9 @@
<breadcrumb class="breadcrumb-container" />
<div class="right-menu">
<div class="right-menu-item" >
{{name}}
</div>
<el-dropdown class="avatar-container" trigger="click">
<div class="avatar-wrapper">
<img :src="avatar+'?imageView2/1/w/80/h/80'" class="user-avatar">
@ -40,7 +43,6 @@
import { mapGetters } from 'vuex'
import Breadcrumb from '@/components/Breadcrumb'
import Hamburger from '@/components/Hamburger'
export default {
components: {
Breadcrumb,
@ -49,7 +51,8 @@ export default {
computed: {
...mapGetters([
'sidebar',
'avatar'
'avatar',
'name'
])
},
methods: {

View File

@ -112,13 +112,13 @@ export const asyncRoutes = [
component: Layout,
redirect: '/supervision/task',
name:'Supervision',
meta: { title: '日常监督', icon: 'table', perms: ['supervision_manage'] },
meta: { title: '日常监督', icon: 'table', perms: ['supervision'] },
children: [
{
path: 'content',
name: 'Content',
component: () => import('@/views/supervision/content.vue'),
meta: { title: '材料清单', icon: 'documentation', perms: ['content_manage'] }
meta: { title: '材料清单', icon: 'documentation', perms: ['content'] }
},
{
path: 'task',

View File

@ -100,7 +100,7 @@
</el-table-column>
<el-table-column label="上报单位">
<template slot-scope="scope">{{ scope.row.dept_.name }}</template>
<template slot-scope="scope">{{ scope.row.belong_dept_.name }}</template>
</el-table-column>
<el-table-column label="记录状态">
<template slot-scope="scope">{{ scope.row.state }}</template>

View File

@ -23,7 +23,7 @@
v-model="record.note"
placeholder=""
type="textarea"
:readonly="record.state != '待上报'"
:readonly="data.action!= 'update'"
>
</el-input>
</div>
@ -41,13 +41,13 @@
v-model="record.noteb"
placeholder=""
type="textarea"
:readonly="record.state == '已上报' && record.state == '已确认'"
:readonly="data.action!='up'"
>
</el-input>
</div>
<div class="ma">
<span class="term">是否适用</span>
<el-switch v-model="record.is_yes"></el-switch>
<el-switch v-model="record.is_yes" :disabled="data.action=='view'"></el-switch>
</div>
<div class="ma">
<el-upload
@ -61,7 +61,7 @@
:file-list="fileList"
accept="image/*,application/pdf,application/vnd.openxmlformats-officedocument.wordprocessingml.document, application/msword,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel"
>
<el-button size="small" type="primary">上传文件</el-button>
<el-button size="small" type="primary" :disabled="data.action!='up'">上传文件</el-button>
<template #tip>
<div class="el-upload__tip">
可上传pdf,word,ppt,excel,图片文件,大小不超过20M
@ -72,7 +72,7 @@
<el-divider></el-divider>
<div style="text-align: right">
<el-button type="primary" @click="confirm()" v-if="this.data.action =='reject'">驳回</el-button>
<el-button type="primary" @click="confirm()" >确认</el-button>
<el-button type="primary" @click="confirm()" v-else>确认</el-button>
</div>
</div>
</template>

View File

@ -118,7 +118,7 @@
</el-table-column>
<el-table-column label="文件">
<template slot-scope="scope">
</template>
</el-table-column>
<el-table-column align="center" label="操作">
@ -147,6 +147,12 @@
@click="handleReject(scope)"
>驳回</el-button
>
<el-button
:disabled="!checkPermission(['record_view'])"
size="small"
@click="handleView(scope)"
>查看</el-button
>
</template>
</el-table-column>
</el-table>
@ -180,7 +186,7 @@
当前选择的是
<span style="color: red">{{ now.name }}</span>
</div>
<el-table
<el-table
v-loading="listLoading"
:data="recordList"
border
@ -189,11 +195,61 @@
highlight-current-row
max-height="600px"
>
<el-table-column label="名称">
<el-table-column label="序号" type="index" align="center" />
<el-table-column label="材料">
<template slot-scope="scope">{{
scope.row.content_.name
}}</template>
</el-table-column>
<el-table-column label="状态">
<template slot-scope="scope">{{
scope.row.state
}}</template>
</el-table-column>
<el-table-column label="上报情况">
<template slot-scope="scope"
>{{ scope.row.up_user }}/{{ scope.row.up_date }}</template
>
</el-table-column>
<el-table-column label="文件">
<template slot-scope="scope">
</template>
</el-table-column>
<el-table-column align="center" label="操作">
<template slot-scope="scope">
<el-button
v-if="scope.row.state == '待上报'"
type="primary"
:disabled="!checkPermission(['record_update'])"
size="small"
@click="handleUpdate(scope)"
>编辑</el-button
>
<el-button
v-if="scope.row.state == '已提交'"
type="primary"
:disabled="!checkPermission(['record_confirm'])"
size="small"
@click="handleConfirm(scope)"
>确认</el-button
>
<el-button
v-if="scope.state == '已提交'"
:disabled="!checkPermission(['record_reject'])"
type="danger"
size="small"
@click="handleReject(scope)"
>驳回</el-button
>
<el-button
:disabled="!checkPermission(['record_view'])"
size="small"
@click="handleView(scope)"
>查看</el-button
>
</template>
</el-table-column>
</el-table>
</el-card>
</el-col>
@ -346,7 +402,18 @@ export default {
this.drawer = true;
},
handleConfirm(scope) {
this.data = {
action: "reject",
record: scope.row,
};
this.drawer = true;
},
handleView(scope) {
this.data = {
action: "view",
record: scope.row,
};
this.drawer = true;
},
handleDo(data){
this.drawer = false

View File

@ -1,5 +1,6 @@
from django.shortcuts import render
from rest_framework.mixins import ListModelMixin
from rest_framework.permissions import IsAuthenticated
from rest_framework.viewsets import GenericViewSet, ModelViewSet
from .models import *
from .serializers import *

View File

@ -0,0 +1,27 @@
# Generated by Django 3.0.5 on 2021-03-17 01:22
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('supervision', '0008_auto_20210316_0827'),
]
operations = [
migrations.RemoveField(
model_name='task',
name='complete_rate',
),
migrations.AddField(
model_name='task',
name='confirm_rate',
field=models.IntegerField(default=0, verbose_name='确认率'),
),
migrations.AddField(
model_name='task',
name='up_rate',
field=models.IntegerField(default=0, verbose_name='上报率'),
),
]

View File

@ -29,7 +29,8 @@ class Task(CommonBModel):
name = models.CharField('名称', max_length=100)
end_date = models.DateField('截止时间', null=True, blank=True)
note = models.TextField('任务备注', null=True, blank=True)
complete_rate = models.IntegerField('完成度', default=0)
up_rate = models.IntegerField('上报率', default=0)
confirm_rate = models.IntegerField('确认率', default=0)
contents = models.ManyToManyField('supervision.content', through='supervision.record')
depts = models.ManyToManyField('system.organization', through='supervision.record')
state = models.CharField('任务状态', max_length=50, choices=state_choices, default='创建中')

View File

@ -35,7 +35,7 @@ class TaskCreateUpdateSerializer(serializers.ModelSerializer):
class TaskListSerializer(serializers.ModelSerializer):
class Meta:
model = Task
fields = ['name', 'end_date', 'note', 'complete_rate', 'state', 'id']
fields = ['name', 'end_date', 'note', 'up_rate', 'state', 'id', 'confirm_rate']
class RecordSerializer(serializers.ModelSerializer):
task_ = TaskListSerializer(source='task')

View File

@ -10,11 +10,13 @@ from rest_framework.response import Response
from apps.system.models import Organization
from django.db.models import Count
from utils.pagination import PageOrNot
from apps.system.mixins import OptimizationMixin
from apps.system.mixins import CreateUpdateCustomMixin
from apps.system.permission_data import RbacFilterSet
from django.utils import timezone
from .filters import RecordFilter
from django.db.models.query import QuerySet
from django.core.cache import cache
from apps.system.permission import get_permission_list
# Create your views here.
class ContentViewSet(CreateUpdateCustomMixin, ModelViewSet):
@ -97,7 +99,20 @@ class TaskViewSet(CreateUpdateCustomMixin, ModelViewSet):
serializer = OrganizationSimpleSerializer(obj.depts.distinct(), many=True)
return Response(serializer.data)
class RecordViewSet(OptimizationMixin,PageOrNot, CreateUpdateCustomMixin, ModelViewSet):
def cal_task_rate(task):
"""
计算任务上报率, 确认率
"""
objs = Record.objects.filter(task=task)
if objs.exists():
count = objs.count()
up_rate = objs.filter(state__in=['已确认','已上报']).count()/count
confirm_rate = objs.filter(state='已确认').count()/count
task.up_rate = int(up_rate)
task.confirm_rate = int(confirm_rate)
task.save()
class RecordViewSet(RbacFilterSet, PageOrNot, CreateUpdateCustomMixin, ModelViewSet):
perms_map = {'get': '*', 'post': 'record_create',
'put': 'record_update', 'delete': 'record_delete'}
queryset = Record.objects.all()

View File

@ -18,8 +18,7 @@ def get_permission_list(user):
perms = perms | i.perms.all()
perms_list = perms.values_list('method', flat=True)
perms_list = list(set(perms_list))
cache.set(user.username, perms_list)
# cache.persist(user.username)
cache.set(user.username + '__perms', perms_list)
return perms_list
@ -35,7 +34,10 @@ class RbacPermission(BasePermission):
:param view:
:return:
"""
perms = cache.get(request.user)
if not request.user:
perms = ['visitor'] # 如果没有经过认证,视为游客
else:
perms = cache.get(request.user.username + '__perms')
if not perms:
perms = get_permission_list(request.user)
if perms:
@ -59,7 +61,10 @@ class RbacPermission(BasePermission):
"""
Return `True` if permission is granted, `False` otherwise.
"""
has_obj_perm(request.user, obj)
# if not request.user:
# return False
# if hasattr(obj, 'belong_dept'):
# has_obj_perm(request.user, obj)
return True
def has_obj_perm(user, obj):
@ -78,8 +83,8 @@ def has_obj_perm(user, obj):
if obj.belong_dept not in roles.depts:
return False
elif '同级及以下' in data_range:
if user.dept.pid:
belong_depts = get_child_queryset2(user.dept.pid)
if user.dept.parent:
belong_depts = get_child_queryset2(user.dept.parent)
if obj.belong_dept not in belong_depts:
return False
elif '本级及以下' in data_range:

View File

@ -1,15 +1,18 @@
from django.db.models import Q
from django.db.models.query import QuerySet
from rest_framework.generics import GenericAPIView
from apps.system.mixins import CreateUpdateModelBMixin
from utils.queryset import get_child_queryset2
class RbacFilterSet(GenericAPIView):
class RbacFilterSet(object):
"""
数据权限控权返回的queryset
在必须的View下继承
需要控数据权限的表需有belong_dept, create_by, update_by字段(部门, 创建人, 编辑人)
带性能优化
此处对性能有较大影响,根据业务需求进行修改或取舍
"""
def get_queryset(self):
assert self.queryset is not None, (
@ -22,6 +25,13 @@ class RbacFilterSet(GenericAPIView):
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) # 性能优化
if self.request.user.is_superuser:
return queryset
if hasattr(queryset.model, 'belong_dept'):
user = self.request.user
roles = user.roles
@ -33,8 +43,8 @@ class RbacFilterSet(GenericAPIView):
queryset = queryset.filter(belong_dept__in = roles.depts)
return queryset
elif '同级及以下' in data_range:
if user.dept.pid:
belong_depts = get_child_queryset2(user.dept.pid)
if user.dept.parent:
belong_depts = get_child_queryset2(user.dept.parent)
queryset = queryset.filter(belong_dept__in = belong_depts)
return queryset
elif '本级及以下' in data_range:
@ -47,7 +57,6 @@ class RbacFilterSet(GenericAPIView):
elif '仅本人' in data_range:
queryset = queryset.filter(Q(create_by=user)|Q(update_by=user))
return queryset
return queryset
@ -57,28 +66,32 @@ def rbac_filter_queryset(user, queryset):
需要控数据权限的表需有belong_dept, create_by, update_by字段(部门, 创建人, 编辑人)
传入user实例,queryset
"""
if user.is_superuser:
return queryset
roles = user.roles
data_range = roles.values_list('datas', flat=True)
if '全部' in data_range:
return queryset
elif '自定义' in data_range:
if roles.depts.exists():
queryset = queryset.filter(belong_dept__in = roles.depts)
if hasattr(queryset.model, 'belong_dept'):
if '全部' in data_range:
return queryset
elif '同级及以下' in data_range:
if user.dept.pid:
belong_depts = get_child_queryset2(user.dept.pid)
elif '自定义' in data_range:
if roles.depts.exists():
queryset = queryset.filter(belong_dept__in = roles.depts)
return queryset
elif '同级及以下' in data_range:
if user.dept.parent:
belong_depts = get_child_queryset2(user.dept.parent)
queryset = queryset.filter(belong_dept__in = belong_depts)
return queryset
elif '本级及以下' in data_range:
belong_depts = get_child_queryset2(user.dept)
queryset = queryset.filter(belong_dept__in = belong_depts)
return queryset
elif '本级及以下' in data_range:
belong_depts = get_child_queryset2(user.dept)
queryset = queryset.filter(belong_dept__in = belong_depts)
return queryset
elif '本级' in data_range:
queryset = queryset.filter(belong_dept = user.dept)
return queryset
elif '仅本人' in data_range:
queryset = queryset.filter(Q(create_by=user)|Q(update_by=user))
return queryset
elif '本级' in data_range:
queryset = queryset.filter(belong_dept = user.dept)
return queryset
elif '仅本人' in data_range:
queryset = queryset.filter(Q(create_by=user)|Q(update_by=user))
return queryset
return queryset