This commit is contained in:
shilixia 2021-03-16 08:39:41 +08:00
commit 4a53a07df1
7 changed files with 308 additions and 106 deletions

View File

@ -48,3 +48,17 @@ export function inittask(id, data) {
}) })
} }
export function gettaskcontents(id) {
return request({
url: `/supervision/task/${id}/contents/`,
method: 'get'
})
}
export function gettaskdepts(id) {
return request({
url: `/supervision/task/${id}/depts/`,
method: 'get'
})
}

View File

@ -69,7 +69,6 @@
align="center" align="center"
label="操作" label="操作"
width="220px" width="220px"
fixed="right"
> >
<template slot-scope="scope"> <template slot-scope="scope">
<el-button <el-button

View File

@ -1,122 +1,253 @@
<template> <template>
<div class="app-container"> <div class="app-container">
<el-card> <el-card>
<div slot="header" class="clearfix"> <div slot="header" class="clearfix">
<span>任务详情</span> <span>任务详情</span>
</div> </div>
<div style="margin-left:10px;margin-right:10px"> <div style="margin-left: 10px; margin-right: 10px">
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="8"> <el-col :span="8">
<div style="margin-bottom:6px"> <div style="margin-bottom: 6px">
<span class="term">任务名称</span> <span class="term">任务名称</span>
<span class="desc"> {{ task.name}}</span> <span class="desc"> {{ task.name }}</span>
</div> </div>
</el-col> </el-col>
<el-col :span="8"> <el-col :span="8">
<div style="margin-bottom:6px"> <div style="margin-bottom: 6px">
<span class="term">截止日期</span> <span class="term">截止日期</span>
<span class="desc"> {{ task.end_date}}</span> <span class="desc"> {{ task.end_date }}</span>
</div> </div>
</el-col> </el-col>
<el-col :span="8"> <el-col :span="8">
<div style="margin-bottom:6px"> <div style="margin-bottom: 6px">
<span class="term">创建人</span> <span class="term">创建人</span>
<span class="desc" v-if="task.create_by_"> {{ task.create_by_.name}}/</span> <span class="desc" v-if="task.create_by_">
<span v-if="task.belong_dept_">{{ task.belong_dept_.name }}</span> {{ task.create_by_.name }}/</span
>
<span class="desc" v-if="task.belong_dept_">{{
task.belong_dept_.name
}}</span>
</div>
</el-col>
<el-col :span="8">
<div style="margin-bottom: 6px">
<span class="term">任务状态</span>
<span class="desc"> {{ task.state }}</span>
</div>
</el-col>
<el-col :span="8">
<div style="margin-bottom: 6px">
<span class="term">完成度</span>
<span class="desc"> {{ task.complete_rate }}%</span>
</div>
</el-col>
<el-col :span="8">
<div style="margin-bottom: 6px">
<span class="term">备注</span>
<span class="desc"> {{ task.note }}</span>
</div>
</el-col>
</el-row>
<div style="margin-top: 4px">
<el-button
type="primary"
@click="init()"
v-if="task.state == '创建中'"
size="small"
>初始化任务</el-button
>
</div>
</div>
</el-card>
</div> <el-card style="margin-top: 2px">
</el-col> <div slot="header" class="clearfix">
<el-col :span="8"> <span>执行详情</span>
<div style="margin-bottom:6px"> </div>
<span class="term">任务状态</span> <el-tabs v-model="activeName">
<span class="desc"> {{ task.state}}</span> <el-tab-pane label="按清单" name="tab1" lazy>
</div> <el-row :gutter="10">
</el-col> <el-col :span="4">
<el-col :span="8"> <el-card
<div style="margin-bottom:6px"> shadow="never"
<span class="term">完成度</span> style="height: 600px; overflow-y: auto; overflow-x: auto"
<span class="desc"> {{ task.complete_rate}}%</span> >
</div> <div
</el-col> v-for="item in contents"
<el-col :span="8"> v-bind:key="item.id"
<div style="margin-bottom:6px"> class="litem"
<span class="term">备注</span> @click="chose1(item)"
<span class="desc"> {{ task.note}}</span> >
</div> {{ item.name }}
</el-col> </div>
</el-row> </el-card>
<div style="margin-top:4px"> </el-col>
<el-button type="primary" @click="init()" v-if="task.state=='创建中'" size="small">初始化任务</el-button> <el-col :span="20">
</div> <el-card shadow="never" style="height: 600px; overflow-y: auto; overflow-x: auto">
</div> <el-table
</el-card> v-loading="listLoading"
:data="recordList"
border
fit
stripe
highlight-current-row
max-height="600px"
>
<el-table-column label="状态">
<template slot-scope="scope">{{ scope.row.state }}</template>
</el-table-column>
</el-table>
<el-card style="margin-top:2px"> </el-card>
<div slot="header" class="clearfix"> </el-col>
<span>执行详情</span> </el-row>
</div> </el-tab-pane>
</el-card> <el-tab-pane label="按单位" name="tab2" lazy>
<el-row :gutter="10">
<el-col :span="4">
<el-card
shadow="never"
style="height: 600px; overflow-y: auto; overflow-x: auto"
>
<div
v-for="item in depts"
v-bind:key="item.id"
class="litem"
@click="chose2(item)"
>
{{ item.name }}
</div>
</el-card>
</el-col>
<el-col :span="20">
<el-card
shadow="never"
style="height: 600px; overflow-y: auto; overflow-x: auto"
>
<div>
当前选择的是
<span style="color:red">{{now.name}}</span>
</div>
<el-table
v-loading="listLoading"
:data="recordList"
border
fit
stripe
highlight-current-row
max-height="600px"
>
<el-table-column label="名称">
<template slot-scope="scope">{{ scope.row.state }}</template>
</el-table-column>
</el-table>
</el-card>
</el-col>
</el-row>
</el-tab-pane>
</el-tabs>
</el-card>
<el-dialog <el-dialog
:visible.sync="dialogVisible" :visible.sync="dialogVisible"
title="初始化任务" title="初始化任务"
:close-on-click-modal="false" :close-on-click-modal="false"
> >
<taskinit ref="taskinit" @handleChose="chooseComplete"></taskinit> <taskinit ref="taskinit" @handleChose="chooseComplete"></taskinit>
</el-dialog> </el-dialog>
</div> </div>
</template> </template>
<style > <style >
.term{ .term {
color: rgba(0,0,0,.85); color: rgba(0, 0, 0, 0.85);
font-weight: bold; font-weight: bold;
font-size: 16px; font-size: 16px;
} }
.desc{ .desc {
color: rgba(0, 0, 0, 0.65); color: rgba(0, 0, 0, 0.65);
font-weight: bold; font-weight: bold;
font-size: 16px; font-size: 16px;
}
.litem {
margin-bottom: 4px;
margin-left: 2px;
cursor: pointer;
color: #409EFF;
} }
</style> </style>
<script> <script>
import {gettask, inittask} from "@/api/task" import { gettask, inittask, gettaskcontents, gettaskdepts } from "@/api/task";
import { getRecordList } from "@/api/record";
import Pagination from "@/components/Pagination"; import Pagination from "@/components/Pagination";
import taskinit from "@/views/supervision/taskinit"; import taskinit from "@/views/supervision/taskinit";
export default { export default {
components: {Pagination, taskinit}, components: { Pagination, taskinit },
data(){ data() {
return { return {
task:{id:0}, task: { id: 0 },
dialogVisible:false dialogVisible: false,
activeName: "tab1",
contents: [],
depts: [],
listLoading: false,
recordList: [],
now:{}
};
},
created() {
this.task.id = this.$route.params.id;
this.gettask();
this.gettaskcontents();
this.gettaskdepts();
},
methods: {
gettask() {
gettask(this.task.id).then((res) => {
this.task = res.data;
if (this.task.state == "创建中") {
this.dialogVisible = true;
} }
});
}, },
created() { init() {
this.task.id = this.$route.params.id this.dialogVisible = true;
this.gettask()
}, },
methods:{ chooseComplete(data) {
gettask(){ this.dialogVisible = false;
gettask(this.task.id).then(res=>{ const rLoading = this.openLoading("正在初始化任务,请稍等...");
this.task = res.data inittask(this.task.id, data).then((res) => {
if(this.task.state=='创建中'){ rLoading.close();
this.dialogVisible = true this.$message.success("成功");
} this.$router.go(0);
}) });
},
init(){
this.dialogVisible = true
},
chooseComplete(data){
this.dialogVisible = false;
const rLoading = this.openLoading('正在初始化任务,请稍等...');
inittask(this.task.id, data).then(res=>{
rLoading.close()
this.$message.success('成功')
this.$router.go(0);
})
}
}, },
gettaskcontents() {
gettaskcontents(this.task.id).then((res) => {
this.contents = res.data;
});
},
gettaskdepts() {
gettaskdepts(this.task.id).then((res) => {
this.depts = res.data;
});
},
chose1(item){
this.now = item
this.listLoading = true
getRecordList({pageoff:true, content:item.id}).then(res=>{
this.listLoading = false
this.recordList = res.data
})
},
chose2(item){
this.now = item
this.listLoading = true
getRecordList({pageoff:true, belong_dept:item.id}).then(res=>{
this.listLoading = false
this.recordList = res.data
})
}
},
}; };
</script> </script>

View File

@ -0,0 +1,40 @@
# Generated by Django 3.0.5 on 2021-03-16 00:27
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('supervision', '0007_auto_20210315_1412'),
]
operations = [
migrations.RemoveField(
model_name='task',
name='is_self',
),
migrations.AddField(
model_name='record',
name='is_self',
field=models.BooleanField(default=False, verbose_name='是否主动报送'),
),
migrations.AlterField(
model_name='record',
name='content',
field=models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, related_name='record_content', to='supervision.Content', verbose_name='材料内容'),
),
migrations.AlterField(
model_name='record',
name='task',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='record_task', to='supervision.Task', verbose_name='关联任务'),
),
migrations.AlterField(
model_name='record',
name='up_user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='record_up_user', to=settings.AUTH_USER_MODEL, verbose_name='上报人'),
),
]

View File

@ -27,7 +27,6 @@ class Task(CommonBModel):
('已完成', '已完成'), ('已完成', '已完成'),
) )
name = models.CharField('名称', max_length=100) name = models.CharField('名称', max_length=100)
is_self = models.BooleanField('是否主动报送', default=False)
end_date = models.DateField('截止时间', null=True, blank=True) end_date = models.DateField('截止时间', null=True, blank=True)
note = models.TextField('任务备注', null=True, blank=True) note = models.TextField('任务备注', null=True, blank=True)
complete_rate = models.IntegerField('完成度', default=0) complete_rate = models.IntegerField('完成度', default=0)
@ -49,10 +48,11 @@ class Record(CommonBModel):
('已确认', '已确认'), ('已确认', '已确认'),
('待整改', '待整改') ('待整改', '待整改')
) )
content = models.ForeignKey(Content, verbose_name='材料内容', on_delete=models.DO_NOTHING) content = models.ForeignKey(Content, verbose_name='材料内容', on_delete=models.DO_NOTHING, related_name='record_content')
task = models.ForeignKey(Task, verbose_name='关联任务', null=True, blank=True, on_delete=models.SET_NULL) task = models.ForeignKey(Task, verbose_name='关联任务', null=True, blank=True, on_delete=models.SET_NULL, related_name='record_task')
is_self = models.BooleanField('是否主动报送', default=False)
up_date = models.DateField('上报时间', null=True, blank=True) up_date = models.DateField('上报时间', null=True, blank=True)
up_user = models.ForeignKey(User, verbose_name='上报人', null=True, blank=True,on_delete=models.SET_NULL) up_user = models.ForeignKey(User, verbose_name='上报人', null=True, blank=True,on_delete=models.SET_NULL, related_name='record_up_user')
end_date = models.DateField('截止时间', null=True, blank=True) end_date = models.DateField('截止时间', null=True, blank=True)
state = models.CharField('记录状态', max_length=50, choices=state_choices, default='待上报') state = models.CharField('记录状态', max_length=50, choices=state_choices, default='待上报')
is_yes = models.BooleanField('是否适用', default=True) is_yes = models.BooleanField('是否适用', default=True)

View File

@ -24,7 +24,7 @@ class ContentSerializer(serializers.ModelSerializer):
class ContentListSerializer(serializers.ModelSerializer): class ContentListSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = Content model = Content
fields = ['name', 'desc'] fields = ['name', 'desc', 'id']
class TaskCreateUpdateSerializer(serializers.ModelSerializer): class TaskCreateUpdateSerializer(serializers.ModelSerializer):
class Meta: class Meta:

View File

@ -10,6 +10,7 @@ from rest_framework.response import Response
from apps.system.models import Organization from apps.system.models import Organization
from django.db.models import Count from django.db.models import Count
from utils.pagination import PageOrNot from utils.pagination import PageOrNot
from apps.system.mixins import OptimizationMixin
from apps.system.mixins import CreateUpdateCustomMixin from apps.system.mixins import CreateUpdateCustomMixin
# Create your views here. # Create your views here.
@ -33,12 +34,14 @@ class TaskViewSet(CreateUpdateCustomMixin, ModelViewSet):
queryset = Task.objects.all() queryset = Task.objects.all()
search_fields = ['name'] search_fields = ['name']
ordering = ['-create_time'] ordering = ['-create_time']
def get_serializer_class(self): def get_serializer_class(self):
if self.action in ['create', 'update']: if self.action in ['create', 'update']:
return TaskCreateUpdateSerializer return TaskCreateUpdateSerializer
elif self.action == 'retrieve': elif self.action == 'retrieve':
return TaksDetailSerializer return TaksDetailSerializer
return TaskListSerializer return TaskListSerializer
@action(methods=['post'], detail=False, perms_map = {'post':'task_createself'}) @action(methods=['post'], detail=False, perms_map = {'post':'task_createself'})
def createself(self, request): def createself(self, request):
""" """
@ -49,7 +52,6 @@ class TaskViewSet(CreateUpdateCustomMixin, ModelViewSet):
serializer.save(is_self=True, create_by=request.user, belong_dept=request.user.dept) serializer.save(is_self=True, create_by=request.user, belong_dept=request.user.dept)
return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.data, status=status.HTTP_201_CREATED)
@action(methods=['post'], detail=True, perms_map = {'post':'task_init'}) @action(methods=['post'], detail=True, perms_map = {'post':'task_init'})
def init(self, request, *args, **kwargs): def init(self, request, *args, **kwargs):
""" """
@ -74,15 +76,31 @@ class TaskViewSet(CreateUpdateCustomMixin, ModelViewSet):
obj.save() obj.save()
return Response(status=status.HTTP_200_OK) return Response(status=status.HTTP_200_OK)
return Response('单位或清单不能为空', status=status.HTTP_400_BAD_REQUEST) return Response('单位或清单不能为空', status=status.HTTP_400_BAD_REQUEST)
class RecordViewSet(CreateUpdateCustomMixin,ModelViewSet):
perms_map = {'get': '*'} @action(methods=['get'], detail=True, perms_map = {'get':'*'})
def contents(self, request, *args, **kwargs):
"""
聚合
"""
obj = self.get_object()
serializer = ContentListSerializer(obj.contents.distinct(), many=True)
return Response(serializer.data)
@action(methods=['get'], detail=True, perms_map = {'get':'*'})
def depts(self, request, *args, **kwargs):
"""
聚合
"""
obj = self.get_object()
serializer = OrganizationSimpleSerializer(obj.depts.distinct(), many=True)
return Response(serializer.data)
class RecordViewSet(OptimizationMixin,PageOrNot, CreateUpdateCustomMixin, ModelViewSet):
perms_map = {'get': '*', 'post': 'record_create',
'put': 'record_update', 'delete': 'record_delete'}
queryset = Record.objects.all() queryset = Record.objects.all()
serializer_class = RecordSerializer serializer_class = RecordSerializer
search_fields = ['content','task','up_date','state'] search_fields = ['content','task','up_date','state']
ordering = ['-create_time'] ordering = ['-create_time']
def get_queryset(self): filterset_fields = ['content', 'belong_dept']
queryset = self.queryset
if hasattr(self.get_serializer_class(), 'setup_eager_loading'):
queryset = self.get_serializer_class().setup_eager_loading(queryset) # 性能优化
return queryset