add: chart of work load for each member in department & millions of bugs.

This commit is contained in:
raiots 2021-05-05 00:48:03 +08:00
parent 3d08ffce71
commit d7359e3ea8
10 changed files with 512 additions and 53 deletions

View File

@ -62,6 +62,13 @@ class TaskAdmin(ImportExportModelAdmin):
else:
return qs.filter(department=request.user.department)
def save_model(self, request, obj, form, change):
mvDict = dict(request.POST)
print(len(mvDict['related_task-0-sub_executor']))
obj.related_task__sub_executor_count = int(len(mvDict['related_task-0-sub_executor']))
super().save_model(request, obj, form, change)
list_display = (
'task_property', 'task_id', 'task_topic', 'task_origin', 'aim_value', 'deadline', 'duty_group', 'principal',
'leader', 'task_note',
@ -124,9 +131,9 @@ class TodoAdmin(ImportExportModelAdmin):
(None, {
'fields': [
'related_task', 'todo_topic', 'todo_note', 'deadline', 'duty_group', 'main_executor', 'sub_executor',
'predict_work', 'evaluate_factor',
'sub_executor_count', 'predict_work', 'evaluate_factor', 'real_work'
],
'description': 'aaa'
'description': ''
}),
(None, {
@ -157,6 +164,7 @@ class TodoAdmin(ImportExportModelAdmin):
# raw_id_fields = ("sub_executor",)
search_fields = ('todo_topic',)
ordering = ('related_task', )
readonly_fields = [ "attachment"]
def approval_state(self, obj):
return format_html('<span style="color:{};">{}</span>', 'green', obj.approval)
@ -191,6 +199,17 @@ class TodoAdmin(ImportExportModelAdmin):
else:
return False
def save_model(self, request, obj, form, change):
# 这一行代码写了一个晚上呜呜! 解决了当保存时,无法从未保存的数据中获取协办人数的问题!
mvDict = dict(request.POST)
# dicts = request.POST
# print(dicts)
# for key, values in dicts:
# print(key, values)
# obj.user = request.user
obj.sub_executor_count = int(len(mvDict['sub_executor']))
super().save_model(request, obj, form, change)
# 增加批量操作按钮
actions = ['bulk_action']

View File

@ -1,4 +1,8 @@
import time
from django.db import models
from django.http import request
from apps.users.models import User, MyGroup, QualityMark, TaskProperty, Department
@ -18,8 +22,9 @@ class Todo(models.Model):
main_executor = models.ForeignKey(User, related_name='main_executor', on_delete=models.CASCADE,
verbose_name='承/督办人', blank=True, null=True)
sub_executor = models.ManyToManyField(User, related_name='sub_executor', verbose_name='协办人', blank=True)
sub_executor_count = models.CharField('协办人数', max_length=32)
related_task = models.ForeignKey('Task', related_name='related_task', on_delete=models.CASCADE, verbose_name='年度任务')
predict_work = models.DecimalField('预计工作量', max_digits=5, decimal_places=1, blank=True, null=True)
predict_work = models.DecimalField('预计工作量', default=0, max_digits=5, decimal_places=1, blank=False)
evaluate_factor = models.DecimalField('折算系数', max_digits=5, decimal_places=1, blank=True, default='1')
maturity = models.CharField(
verbose_name='成熟度',
@ -28,17 +33,17 @@ class Todo(models.Model):
('0%', '0%'),
('10%', '10%'),
('50%', '50%'),
('70%', '70%'),
('90%', '90%'),
('100%', '100%')
),
blank=True,
default='0%',
)
real_work = models.DecimalField('实际工作量', max_digits=5, decimal_places=1, blank=True, null=True)
real_work = models.DecimalField('实际工作量', default=0, max_digits=5, decimal_places=1, blank=False)
complete_note = models.TextField('完成情况说明', max_length=150, blank=True)
quality_mark = models.ForeignKey('users.QualityMark', on_delete=models.SET_NULL, blank=True, null=True,
verbose_name='质量评价')
attachment = models.FileField('交付物查看', blank=True)
def __str__(self):
date = str(self.deadline)
@ -50,6 +55,13 @@ class Todo(models.Model):
verbose_name = '工作包'
verbose_name_plural = '工作包'
# def save(self, *args, **kwargs):
# super(Todo, self).save(*args, **kwargs)
# print(request.HttpRequest)
# # 直接保存报错 needs to have a value for field "id" before this many-to-many relationship can be used.
# # self.sub_executor_count = int(self.sub_executor.count())
# # Todo.objects.update(sub_executor_count=self.sub_executor.count())
@property
def task_id(self):
return self.related_task.task_id
@ -74,6 +86,18 @@ class Todo(models.Model):
def points(self):
return int(self.predict_work * self.evaluate_factor)
@property
def main_workload(self):
return int(self.predict_work) * int(self.evaluate_factor)
@property
def sub_workload(self):
return self.predict_work * (1-int(self.evaluate_factor))/self.sub_executor.count
@classmethod
def sub_member(cls):
return cls.sub_executor.count
def list_sub_executor(self):
return ', '.join([a.real_name for a in self.sub_executor.all()])
list_sub_executor.short_description = '协办人'

View File

@ -6,6 +6,9 @@ from .models import Todo, Task
class TodoResources(resources.ModelResource):
class Meta:
model = Todo
fields = ('todo_topic', 'todo_note', 'deadline', 'duty_group__name', 'main_executor__real_name',
'sub_executor__real_name', 'sub_executor_count', 'related_task', 'predict_work', 'evaluate_factor',
'maturity', 'real_work', 'complete_note', 'quality_mark')
class TaskResources(resources.ModelResource):

View File

@ -4,6 +4,7 @@ from apps.tasks import views
app_name = 'tasks'
urlpatterns = [
path('', views.IndexView.as_view(), name='index'),
path('<int:year>/<int:month>/', views.IndexView.as_view(), name='index_month'),
path('login/', views.UserLoginView.as_view(), name='login'),
path('logout/', views.UserLogoutView.as_view(), name='logout'),
path('todolist/', views.TodoListView.as_view(), name='todolist'),

View File

@ -1,7 +1,11 @@
import re
from copy import deepcopy
from django.contrib import auth, messages
from django.contrib.auth import logout
from django.contrib.auth.decorators import login_required
from django.db.models import Sum, F
from django.db.models import Sum, F, FloatField, Count, Q
from django.db.models.functions import Coalesce
from django.shortcuts import render, redirect
from django.utils.decorators import method_decorator
import django.utils.timezone as timezone
@ -10,19 +14,177 @@ from django.views import View
from apps.tasks.models import Todo, Task
from apps.tasks.forms import TodoForm
from apps.users.models import User
from functools import reduce
import pandas as pd
class IndexView(View):
@method_decorator(login_required)
def get(self, request):
users = User.objects.filter(department=request.user.department)
def get(self, request, year=timezone.now().year, month=timezone.now().month):
basic_users = User.objects.filter(department=request.user.department).annotate(
main_executor_count=Count('main_executor',
filter=Q(main_executor__deadline__year=year, main_executor__deadline__month=month)
, distinct=True),
sub_executor_count=Count('sub_executor',
filter=Q(sub_executor__deadline__year=year, sub_executor__deadline__month=month),
distinct=True)
).values('id', 'real_name', 'main_executor_count', 'sub_executor_count')
basic_users = [entry for entry in basic_users]
basic_user_cal = {}
for i in basic_users:
basic_user_cal.update({i['id']: i})
print(basic_user_cal)
current_user = User.objects.filter(username=request.user.username).annotate(
main_executor_count=Count('main_executor',
filter=Q(main_executor__deadline__year=year, main_executor__deadline__month=month)
, distinct=True),
sub_executor_count=Count('sub_executor',
filter=Q(sub_executor__deadline__year=year, sub_executor__deadline__month=month),
distinct=True),
pre_credit=Sum(
F('main_executor__predict_work') * F('main_executor__evaluate_factor'),
filter=Q(main_executor__deadline__year=year, main_executor__deadline__month=month),
distinct=True,
output_field=FloatField()
),
real_credit=Sum(
F('main_executor__real_work') * F('main_executor__evaluate_factor'),
filter=Q(main_executor__deadline__year=year, main_executor__deadline__month=month),
distinct=True,
output_field=FloatField()
)
)
department_cal = Todo.objects.filter(main_executor__department=request.user.department,
deadline__year=year, deadline__month=month).aggregate(count=Count('id'),
pre_total=Sum('predict_work'), real_total=Sum('real_work'), pre_avg=Sum('predict_work'), real_avg=Sum('real_work')).values()
keys = ['count', 'pre_total', 'real_total', 'pre_avg', 'real_avg']
temp = []
for values in department_cal:
print(values)
temp.append(values)
#TODO 解决部门tem无数据报错问题
try:
tem = [float(tem) for tem in temp]
whole = dict(zip(keys, tem))
pre_avg = {'pre_avg': float(whole['pre_avg'])/request.user.department.get_user_number}
real_avg = {'real_avg': float(whole['real_avg']) / request.user.department.get_user_number}
whole.update(pre_avg)
whole.update(real_avg)
except:
whole = {}
print('无数据')
# print(whole)
date = str(year) + '' + str(month) + ''
# points = []
# point = User.objects.all()
# for i in point:
# points.append(i)
# points = User.objects.annotate(a=F('main_executor__evaluate_factor'))
points = User.objects.annotate(a=Sum(F('main_executor__predict_work') * F('main_executor__evaluate_factor') + F('sub_executor__predict_work') * F('sub_executor__evaluate_factor')))
context = {'users': users, 'points': points}
# points = User.objects.annotate(a=Coalesce(Sum(F('main_executor__predict_work') * F('main_executor__evaluate_factor')) + Sum(F('sub_executor__predict_work') * F('sub_executor__evaluate_factor')), 0))
# points = User.objects.annotate(a=Sum(F('main_executor__predict_work') * F('main_executor__evaluate_factor')), b=Sum(F('sub_executor__predict_work') * F('sub_executor__evaluate_factor')))
# points = User.objects.annotate(a=Sum(F('main_executor__main_workload')))
main_credit = User.objects.filter(department=request.user.department, ).annotate(
pre_credit=Sum(
F('main_executor__predict_work') * F('main_executor__evaluate_factor'),
filter=Q(main_executor__deadline__year=year, main_executor__deadline__month=month),
distinct=True,
output_field=FloatField()
),
real_credit=Sum(
F('main_executor__real_work') * F('main_executor__evaluate_factor'),
filter=Q(main_executor__deadline__year=year, main_executor__deadline__month=month),
distinct=True,
output_field=FloatField()
)
).values('id', 'real_name', 'pre_credit', 'real_credit')
main_credit = [entry for entry in main_credit] # converts ValuesQuerySet into Python list
sub_credit = User.objects.filter(department=request.user.department).annotate(
pre_credit=Sum(
(F('sub_executor__predict_work') * (1 - F('sub_executor__evaluate_factor')) / F(
'sub_executor__sub_executor_count')
),
filter=Q(sub_executor__deadline__year=year, sub_executor__deadline__month=month),
output_field=FloatField()
),
real_credit=Sum(
(F('sub_executor__real_work') * (1 - F('sub_executor__evaluate_factor')) / F(
'sub_executor__sub_executor_count')
),
filter=Q(sub_executor__deadline__year=year, sub_executor__deadline__month=month),
output_field=FloatField()
)
).values('id', 'real_name', 'pre_credit', 'real_credit')
sub_credit = [entry for entry in sub_credit]
total_credit = main_credit + sub_credit
print(total_credit)
basic_user_credit = {}
if total_credit:
df = pd.DataFrame(total_credit)
cols = ['id', 'real_name', 'pre_credit', 'real_credit']
df = df.loc[:, cols]
result = df.groupby(['id', ]).sum()
cal_credit = result.T.to_dict('dict')
# print(cal_credit)
temp_credit = {}
basic_user_credit = {}
for key, values in cal_credit.items():
# print(values['real_credit'])
temp_credit['pre_credit'] = values['pre_credit']
temp_credit['real_credit'] = values['real_credit']
# print(temp_credit)
basic_user_credit.update({key: temp_credit})
# print(basic_user_credit)
temp_credit = {}
print(basic_user_credit)
else:
print("当前页Index无任何人员具有工作包")
for key in basic_user_cal:
basic_user_cal[key].update(basic_user_credit[key])
print(basic_user_cal)
# ids = []
# person_list = []
# for person in total_points:
# id = person["id"]
# temp = {}
# if id not in ids:
# ids.append(id)
# temp_list = filter(lambda x: x["id"] == person["id"], total_points)
# for i in temp_list:
# temp.update(i)
# person_list.append(temp)
# else:
# continue
# for i in main_points:
# for key, value in i.items():
# def sum_dict(a, b):
# temp = dict()
# # python3,dict_keys类似set | 并集
# for key in a.keys() | b.keys():
# temp[key] = sum([d.get(key, 0) for d in (a, b)])
# return temp
#
# def test():
# # [a,b,c]列表中的参数可以2个也可以多个自己尝试。
# return print(reduce(sum_dict, [a, b, c]))
context = {'users_data': basic_user_cal, 'date': date, 'current_user': current_user, 'department': whole}
return render(request, 'tasks/index.html', context)
@ -53,6 +215,7 @@ class TaskListView(View):
context = {'tasks': tasks}
return render(request, 'tasks/tasklist.html', context)
class UserLoginView(View):
def get(self, request):
return render(request, 'tasks/login.html')
@ -68,6 +231,7 @@ class UserLoginView(View):
else:
return redirect('tasks:index')
class UserLogoutView(View):
def get(self, request):
logout(request)
@ -92,4 +256,4 @@ class TodoEntryView(View):
class AboutView(View):
def get(self, request):
return render(request, 'tasks/about.html')
return render(request, 'tasks/about.html')

View File

@ -9,7 +9,7 @@ from django.db.models import Avg, Sum, F, Value
class User(AbstractUser):
real_name = models.CharField(max_length=150, verbose_name='姓名')
staff_id = models.CharField(max_length=150, verbose_name='工号')
department = models.ForeignKey('Department', on_delete=models.SET_NULL, null=True, blank=True)
department = models.ForeignKey('Department', related_name='member', on_delete=models.SET_NULL, null=True, blank=True)
class Meta:
verbose_name = '用户'
@ -45,6 +45,10 @@ class Department(models.Model):
verbose_name = '部门'
verbose_name_plural = '部门'
@property
def get_user_number(self):
return self.member.count()
class MarkValue(models.Model):
mark_value = models.DecimalField('评价等级考核系数', max_digits=3, decimal_places=2)

View File

@ -6,8 +6,10 @@ django-import-export==2.5.0
django-simpleui==2021.4.1
et-xmlfile==1.0.1
MarkupPy==1.14
numpy==1.20.2
odfpy==1.4.1
openpyxl==3.0.7
pandas==1.2.4
python-dateutil==2.8.1
pytz==2020.5
PyYAML==5.4.1

View File

@ -12,4 +12,9 @@
.table-d-center{
text-align: center;
vertical-align: middle;
}
.col-xs-1-5 {
width: 20%;
float: left;
}

View File

@ -8,12 +8,19 @@
<div class="container-fluid">
<div class="row mb-2">
<div class="col-sm-6">
<h1>总览</h1>
<h1>总览 ({{ date }}) </h1>
</div>
<div class="col-sm-6">
<ol class="breadcrumb float-sm-right">
<li class="breadcrumb-item active"><a href="#">主页</a></li>
</ol>
{# <ol class="breadcrumb float-sm-right">#}
{# <li class="breadcrumb-item active"><a href="#">主页</a></li>#}
{# </ol>#}
<br>
{% load taskfilter %}
<ul class="pagination float-md-right">
<li class="page-item"><a class="page-link" href="/{{ date|last_month }}">«</a></li>
<li class="page-item"><a class="page-link"> {{ date|this_month }}月 </a></li>
<li class="page-item"><a class="page-link" href="/{{ date|next_month }}">»</a></li>
</ul>
</div>
</div>
</div><!-- /.container-fluid -->
@ -23,14 +30,13 @@
<section class="content">
<div class="container-fluid">
<div class="row">
<div class="col-12 col-sm-6 col-md-3">
<div class="col">
<div class="info-box">
<span class="info-box-icon bg-info elevation-1"><i class="fas fa-tasks"></i></span>
<span class="info-box-icon bg-danger elevation-1"><i class="fas fa-tasks"></i></span>
<div class="info-box-content">
<span class="info-box-text">承办任务数</span>
<span class="info-box-text">部门总任务数</span>
<span class="info-box-number">
{{ request.user.main_executor.count }}
{{ department.count|floatformat:'0'|default_if_none:'0' }}
<small></small>
</span>
</div>
@ -38,22 +44,173 @@
</div>
<!-- /.info-box -->
</div>
<!-- /.col -->
<div class="col-12 col-sm-6 col-md-3">
<div class="info-box mb-3">
<span class="info-box-icon bg-danger elevation-1"><i class="fas fa-tasks"></i></span>
<!-- /.col -->
<div class="col">
<div class="info-box mb-3">
<div class="info-box-content">
<span class="info-box-text">部门预计总工作量</span>
<span class="info-box-number">
{{ department.pre_total|default_if_none:'0'|floatformat:'1' }}
<small></small>
</span>
</div>
<!-- /.info-box-content -->
</div>
<!-- /.info-box -->
</div>
<!-- /.col -->
<div class="col">
<div class="info-box mb-3">
<div class="info-box-content">
<span class="info-box-text">部门实际总工作量</span>
<span class="info-box-number">
{{ department.real_total|default_if_none:'0'|floatformat:'1' }}
<small></small>
</span>
</div>
<div class="info-box-content">
<span class="info-box-text">协办任务数</span>
<span class="info-box-number">{{ user.sub_executor.count }}
<small></small>
</span>
</div>
<!-- /.info-box-content -->
</div>
<!-- /.info-box -->
</div>
<!-- /.info-box-content -->
</div>
<!-- /.info-box -->
</div>
<!-- /.col -->
<div class="col">
<div class="info-box mb-3">
<div class="info-box-content">
<span class="info-box-text">部门预计平均工作量</span>
<span class="info-box-number">
{{ department.pre_avg|default_if_none:'0'|floatformat:'1' }}
<small></small>
</span>
</div>
<!-- /.info-box-content -->
</div>
<!-- /.info-box -->
</div>
<!-- /.col -->
<div class="col">
<div class="info-box mb-3">
<div class="info-box-content">
<span class="info-box-text">部门实际平均工作量</span>
<span class="info-box-number">
{{ department.real_avg|default_if_none:'0'|floatformat:'1' }}
<small></small>
</span>
</div>
<!-- /.info-box-content -->
</div>
<!-- /.info-box -->
</div>
<!-- /.col -->
<!-- fix for small devices only -->
<div class="clearfix hidden-md-up"></div>
{# <div class="col-12 col-sm-6 col-md-3">#}
{# <div class="info-box mb-3">#}
{# <span class="info-box-icon bg-success elevation-1"><i class="fas fa-shopping-cart"></i></span>#}
{##}
{# <div class="info-box-content">#}
{# <span class="info-box-text">Sales</span>#}
{# <span class="info-box-number">760</span>#}
{# </div>#}
{# <!-- /.info-box-content -->#}
{# </div>#}
{# <!-- /.info-box -->#}
{# </div>#}
{# <!-- /.col -->#}
{# <div class="col-12 col-sm-6 col-md-3">#}
{# <div class="info-box mb-3">#}
{# <span class="info-box-icon bg-warning elevation-1"><i class="fas fa-users"></i></span>#}
{##}
{# <div class="info-box-content">#}
{# <span class="info-box-text">New Members</span>#}
{# <span class="info-box-number">2,000</span>#}
{# </div>#}
{# <!-- /.info-box-content -->#}
{# </div>#}
{# <!-- /.info-box -->#}
{# </div>#}
<!-- /.col -->
</div>
<div class="row">
<div class="col">
<div class="info-box">
<span class="info-box-icon bg-info elevation-1"><i class="fas fa-tasks"></i></span>
<div class="info-box-content">
<span class="info-box-text"><b>个人任务数据统计:</b></span>
{# <span class="info-box-number">#}
{# {% for user in current_user %}{{ user.main_executor_count }}{% endfor %}#}
{# <small></small>#}
{# </span>#}
</div>
<!-- /.info-box-content -->
</div>
<!-- /.info-box -->
</div>
<div class="col">
<div class="info-box">
{# <span class="info-box-icon bg-info elevation-1"><i class="fas fa-tasks"></i></span>#}
<div class="info-box-content">
<span class="info-box-text">承办任务数</span>
<span class="info-box-number">
{% for user in current_user %}{{ user.main_executor_count }}{% endfor %}
<small></small>
</span>
</div>
<!-- /.info-box-content -->
</div>
<!-- /.info-box -->
</div>
<!-- /.col -->
<div class="col">
<div class="info-box mb-3">
{# <span class="info-box-icon bg-danger elevation-1"><i class="fas fa-tasks"></i></span>#}
<div class="info-box-content">
<span class="info-box-text">协办任务数</span>
<span class="info-box-number">
{% for user in current_user %}{{ user.sub_executor_count }}{% endfor %}
<small></small>
</span>
</div>
<!-- /.info-box-content -->
</div>
<!-- /.info-box -->
</div>
<!-- /.col -->
<div class="col">
<div class="info-box mb-3">
<div class="info-box-content">
<span class="info-box-text">预计工作量</span>
<span class="info-box-number">
{% for user in current_user %}{{ user.pre_credit|default_if_none:'0' }}{% endfor %}
<small></small>
</span>
</div>
<!-- /.info-box-content -->
</div>
<!-- /.info-box -->
</div>
<!-- /.col -->
<div class="col">
<div class="info-box mb-3">
<div class="info-box-content">
<span class="info-box-text">实际工作量</span>
<span class="info-box-number">
{% for user in current_user %}{{ user.real_credit|default_if_none:'0' }}{% endfor %}
<small></small>
</span>
</div>
<!-- /.info-box-content -->
</div>
<!-- /.info-box -->
</div>
<!-- /.col -->
<!-- fix for small devices only -->
<div class="clearfix hidden-md-up"></div>
@ -124,17 +281,65 @@
<!-- /.col (MAIN) -->
</div>
<!-- /.row -->
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-header">
<h3 class="card-title">部门工作统计表</h3>
</div>
<!-- /.card-header -->
<div class="card-body">
<div id="example2_wrapper" class="dataTables_wrapper dt-bootstrap4"><div class="row"><div class="col-sm-12 col-md-6"></div><div class="col-sm-12 col-md-6"></div></div><div class="row"><div class="col-sm-12"><table id="example2" class="table table-bordered table-hover dataTable" role="grid" aria-describedby="example2_info">
<thead>
<tr role="row">
<th class="sorting_asc" tabindex="0" aria-controls="example2" rowspan="1" colspan="1" aria-sort="ascending" aria-label="Rendering engine: activate to sort column descending">姓名</th>
<th class="sorting" tabindex="0" aria-controls="example2" rowspan="1" colspan="1" aria-label="Browser: activate to sort column ascending">承办任务数</th>
<th class="sorting" tabindex="0" aria-controls="example2" rowspan="1" colspan="1" aria-label="Platform(s): activate to sort column ascending">协办任务数</th>
<th class="sorting" tabindex="0" aria-controls="example2" rowspan="1" colspan="1" aria-label="Engine version: activate to sort column ascending">预计工作量</th>
<th class="sorting" tabindex="0" aria-controls="example2" rowspan="1" colspan="1" aria-label="CSS grade: activate to sort column ascending">实际工作量</th>
</tr>
</thead>
<tbody>
{% for user in users_data.values %}
<tr role="row" class="odd">
<td class="sorting_1">{{ user.real_name }}</td>
<td>{{ user.main_executor_count}}</td>
<td>{{ user.sub_executor_count}}</td>
<td>{{ user.pre_credit|floatformat:'1' }}</td>
<td>{{ user.real_credit|floatformat:'1' }}</td>
</tr>
{% endfor %}
</tbody>
{# <tfoot>#}
{# <tr><th rowspan="1" colspan="1">Rendering engine</th><th rowspan="1" colspan="1">Browser</th><th rowspan="1" colspan="1">Platform(s)</th><th rowspan="1" colspan="1">Engine version</th><th rowspan="1" colspan="1">CSS grade</th></tr>#}
{# </tfoot>#}
</table></div></div>
</div>
</div>
<!-- /.card-body -->
</div>
<!-- /.card -->
</div>
<!-- /.col -->
</div>
</div><!-- /.container-fluid -->
</section>
<!-- /.content -->
</div>
{# <div class="content-wrapper">#}
{# {{ main_points }}#}
{# <br>#}
{# {{ sub_points }}#}
{# <br>#}
{# {{ points }}#}
{# {{ points.3.credit }}#}
{# {% for point in points.values %}'{{ point }}', {% endfor %}#}
{# {% for point in points %}#}
{# {{ point }}#}
{# {{ point.a }}#}
{# {% endfor %}#}
{##}
{# {% for user in users %}#}
{# {{ user }}#}
{# {{ user.get_predict_work_count.total_predict_work }}#}
@ -146,7 +351,7 @@
{# {% endfor %}#}
{# </br>#}
{# {% endfor %}#}
{##}
{# </div>#}
{% endblock %}
@ -160,29 +365,51 @@
* Here we will create a few charts using ChartJS
*/
var areaChartData = {
labels : [{% for user in users %}'{{ user }}', {% endfor %}],
labels : [{% for user in users_data.values %}'{{ user.real_name }}', {% endfor %}],
datasets: [
{
label : '协办任务',
backgroundColor : 'rgba(114,140,212,1)',
borderColor : 'rgba(114,140,212,1)',
pointRadius : false,
pointColor : 'rgba(114,140,212,1)',
pointStrokeColor : '#c1c7d1',
pointHighlightFill : '#fff',
pointHighlightStroke: 'rgba(220,220,220,1)',
data : [{% for user in users_data.values %}'{{ user.sub_executor_count }}', {% endfor %}]
},
{
label : '承办任务',
backgroundColor : 'rgba(60,141,188,0.9)',
borderColor : 'rgba(60,141,188,0.8)',
backgroundColor : 'rgba(23,162,184,0.9)',
borderColor : 'rgba(100,98,204,0.8)',
pointRadius : false,
pointColor : '#3b8bba',
pointStrokeColor : 'rgba(60,141,188,1)',
pointHighlightFill : '#fff',
pointHighlightStroke: 'rgba(60,141,188,1)',
data : [{% for user in users %}'{{ user.main_executor.count }}', {% endfor %}]
data : [{% for user in users_data.values %}'{{ user.main_executor_count }}', {% endfor %}]
},
{
label : '协办任务',
backgroundColor : 'rgba(210, 214, 222, 1)',
borderColor : 'rgba(210, 214, 222, 1)',
pointRadius : false,
pointColor : 'rgba(210, 214, 222, 1)',
pointStrokeColor : '#c1c7d1',
{
label : '预计工作量',
backgroundColor : 'rgba(210, 214, 222,1)',
borderColor : 'rgba(210, 214, 222,1)',
pointRadius : false,
pointColor : '#3b8bba',
pointStrokeColor : 'rgba(60,141,188,1)',
pointHighlightFill : '#fff',
pointHighlightStroke: 'rgba(220,220,220,1)',
data : [{% for user in users %}'{{ user.sub_executor.count }}', {% endfor %}]
pointHighlightStroke: 'rgba(60,141,188,1)',
data : [{% for user in users_data.values %}'{{ user.pre_credit|floatformat:'1' }}', {% endfor %}]
},
{
label : '工作量',
backgroundColor : 'rgba(253,199,101,0.9)',
borderColor : 'rgba(253,199,101,0.8)',
pointRadius : false,
pointColor : '#3b8bba',
pointStrokeColor : 'rgba(60,141,188,1)',
pointHighlightFill : '#fff',
pointHighlightStroke: 'rgba(60,141,188,1)',
data : [{% for user in users_data.values %}'{{ user.real_credit|floatformat:'1' }}', {% endfor %}]
},
]
}

View File

@ -37,11 +37,15 @@
<dl class="row">
<dt class="col-sm-4">工作事项</dt>
<dd class="col-sm-8">{{ todo_detail.todo_topic }}</dd>
<dt class="col-sm-4">交付物</dt>
<dd class="col-sm-8">{{ todo_detail.todo_note }}</dd>
<dt class="col-sm-4">完成时间</dt>
<dd class="col-sm-8">{{ todo_detail.deadline }}</dd>
{# <dd class="col-sm-8 offset-sm-4">Donec id elit non mi porta gravida at eget metus.</dd>#}
<dt class="col-sm-4">交付物</dt>
<dd class="col-sm-8">{{ todo_detail.todo_note }}</dd>
<dt class="col-sm-4">任务编号</dt>
<dd class="col-sm-8">{{ todo_detail.task_id }}</dd>
<dt class="col-sm-4">任务来源</dt>
<dd class="col-sm-8">{{ todo_detail.task_origin }}</dd>
<dt class="col-sm-4">责任单位</dt>
<dd class="col-sm-8">{{ todo_detail.duty_group }}</dd>
<dt class="col-sm-4">承/督办人</dt>
@ -50,6 +54,12 @@
<dd class="col-sm-8">{{ todo_detail.sub_executor.all|join:', ' }}</dd>
<dt class="col-sm-4">预计工作量</dt>
<dd class="col-sm-8">{{ todo_detail.predict_work }}</dd>
<dt class="col-sm-4">折算系数</dt>
<dd class="col-sm-8">{{ todo_detail.evaluate_factor }}</dd>
<dt class="col-sm-4">实际工作量</dt>
<dd class="col-sm-8">{{ todo_detail.real_work }}</dd>
<dt class="col-sm-4">成熟度</dt>
<dd class="col-sm-8">{{ todo_detail.maturity }}</dd>
</dl>
</div>
<!-- /.card-body -->