wushaodong hace 4 años
padre
commit
62a4abe8b0

+ 3 - 3
apps/tenant/repair_order/models.py

@@ -28,8 +28,8 @@ class RepairOrder(models.Model):
     TURN_EMPLOYEE = 5
     TURN_EMPLOYEE = 5
     FINISH = 6
     FINISH = 6
     APPRAISE = 7
     APPRAISE = 7
-    INVALID = 8
-    CANCEL_HANG_UP = 9
+    CANCEL_HANG_UP = 8
+    INVALID = 9
     REPAIR_STATUS_CHOICES = (
     REPAIR_STATUS_CHOICES = (
         (NOT_CHECKED, '待审核'),
         (NOT_CHECKED, '待审核'),
         (CHECKED, '已审核,待派单'),
         (CHECKED, '已审核,待派单'),
@@ -38,8 +38,8 @@ class RepairOrder(models.Model):
         (TURN_EMPLOYEE, '转单'),
         (TURN_EMPLOYEE, '转单'),
         (FINISH, '已完工,待评价'),
         (FINISH, '已完工,待评价'),
         (APPRAISE, '已评价'),
         (APPRAISE, '已评价'),
-        (INVALID, '作废'),
         (CANCEL_HANG_UP, '取消挂起'),
         (CANCEL_HANG_UP, '取消挂起'),
+        (INVALID, '作废'),
     )
     )
     no = models.CharField(max_length=50, verbose_name='单号', blank=True)
     no = models.CharField(max_length=50, verbose_name='单号', blank=True)
     tenant = models.ForeignKey(Tenant, verbose_name=u'企业', on_delete=models.PROTECT, blank=True)
     tenant = models.ForeignKey(Tenant, verbose_name=u'企业', on_delete=models.PROTECT, blank=True)

+ 3 - 0
apps/tenant/repair_order/urls.py

@@ -9,6 +9,9 @@ urlpatterns = [
     url(r'dict/$', DictView.as_view()),
     url(r'dict/$', DictView.as_view()),
     url(r'get_employee/$', GetEmployeeView.as_view()),
     url(r'get_employee/$', GetEmployeeView.as_view()),
     url(r'get_repair_order_record/$', OrderRecordView.as_view()),
     url(r'get_repair_order_record/$', OrderRecordView.as_view()),
+    url(r'statistics/$', HomeStatisticsView.as_view()),
+    url(r'statistics/repair_type/$', RepairTypeView.as_view()),
+    url(r'statistics/repair_order/$', RepairOrderView.as_view()),
 ]
 ]
 
 
 router = SimpleRouter()
 router = SimpleRouter()

+ 66 - 4
apps/tenant/repair_order/views.py

@@ -1,21 +1,22 @@
 # coding=utf-8
 # coding=utf-8
 from django.db import transaction
 from django.db import transaction
+import datetime
+from django.utils import timezone
+from django.db.models import Count
 from rest_framework.decorators import action
 from rest_framework.decorators import action
 from django.conf import settings
 from django.conf import settings
 from rest_framework.views import APIView
 from rest_framework.views import APIView
 from utils import response_ok, response_error
 from utils import response_ok, response_error
 from utils.custom_modelviewset import CustomModelViewSet
 from utils.custom_modelviewset import CustomModelViewSet
 from utils.exceptions import CustomError
 from utils.exceptions import CustomError
-from utils.permission import IsTenantUser, permission_required
+from utils.permission import IsTenantUser
 from .serializers import RepairOrderSerializer
 from .serializers import RepairOrderSerializer
-from .models import RepairOrder, RepairOrderRecord, RepairOrderFinish
+from .models import RepairOrder, RepairOrderRecord
 from .filters import RepairOrderFilter
 from .filters import RepairOrderFilter
 from apps.tenant import tenant_log
 from apps.tenant import tenant_log
 from apps.log.models import BizLog
 from apps.log.models import BizLog
-from apps.tenant.area.serializers import AreaSerializer, AreaDepartmentSerializer, Area, Department
 from apps.tenant.employee.serializers import Employee, EmployeeSerializer
 from apps.tenant.employee.serializers import Employee, EmployeeSerializer
 
 
-
 class DictView(APIView):
 class DictView(APIView):
     permission_classes = [IsTenantUser, ]
     permission_classes = [IsTenantUser, ]
 
 
@@ -147,3 +148,64 @@ class RepairOrderViewSet(CustomModelViewSet):
         except Exception as e:
         except Exception as e:
             return response_error(str(e))
             return response_error(str(e))
         return response_ok('工单作废完成!')
         return response_ok('工单作废完成!')
+
+class HomeStatisticsView(APIView):
+    '''首页统计数据'''
+    permission_classes = [IsTenantUser, ]
+    def get(self, request):
+        statistics = {
+            'wait_check':0, #待审核
+            'is_check':0, # 待接单
+            'working':0, #维修中
+            'hang_up':0, #挂起中
+            'complete':0, #已完成
+            'appraise':0, #已评价
+        }
+        if request.user or request.user.is_authenticated:
+            tenant = request.user.employee.tenant
+            rows = RepairOrder.objects.filter(tenant=tenant)
+            # statistics['total'] = rows.filter(status__gte=RepairOrder.CHECKED).count()
+            statistics['wait_check'] = rows.filter(status=RepairOrder.NOT_CHECKED).count()
+            statistics['is_check'] = rows.filter(status=RepairOrder.CHECKED).count()
+            statistics['working'] = rows.filter(status=RepairOrder.DISPATCH).count()
+            statistics['hang_up'] = rows.filter(status=RepairOrder.HANG_UP).count()
+            statistics['complete'] = rows.filter(status=RepairOrder.FINISH).count()
+            statistics['appraise'] = rows.filter(status=RepairOrder.APPRAISE).count()
+            return response_ok(statistics)
+        else:
+            return response_ok(statistics)
+
+class RepairTypeView(APIView):
+    permission_classes = [IsTenantUser, ]
+
+    def get(self, request):
+        tenant = request.user.employee.tenant
+        order_records = RepairOrder.objects.filter(tenant=tenant,status__gte=RepairOrder.CHECKED)
+        order_records = order_records.values('repair_type').annotate(count=Count('id')).order_by('repair_type').values(
+            'repair_type__name', 'count')
+        return response_ok(
+            [{'name': order_record['repair_type__name'], 'value': order_record['count']} for order_record in order_records])
+
+class RepairOrderView(APIView):
+    permission_classes = [IsTenantUser, ]
+
+    def get(self, request):
+        order_mouth = []  # 日期
+        repair_counts = []  # 报修量
+        finish_counts = []  # 完工量
+        tenant = request.user.employee.tenant
+        now = timezone.now()
+
+        for d in range(30):
+            date = (now + datetime.timedelta(days=-d)).strftime('%Y-%m-%d')
+            order_mouth.append(date[5:])
+            rows = RepairOrder.objects.filter(tenant=tenant,create_time__gte=date, create_time__lte=date + ' 23:59:59', status__in=[RepairOrder.CHECKED, RepairOrder.FINISH])
+            check_counts = rows.filter(status__gte=RepairOrder.CHECKED).count()
+            finish_count = rows.filter(status__gte=RepairOrder.FINISH).count()
+            repair_counts.append(check_counts)
+            finish_counts.append(finish_count)
+        return response_ok({
+            'finish_counts': finish_counts,
+            'repair_counts': repair_counts,
+            'order_mouth': order_mouth,
+        })

+ 3 - 4
apps/wxapp/views.py

@@ -128,7 +128,7 @@ class StatisticsRepairView(APIView):
             for d in range(days):
             for d in range(days):
                 date = (now + datetime.timedelta(days=-d)).strftime('%Y-%m-%d')
                 date = (now + datetime.timedelta(days=-d)).strftime('%Y-%m-%d')
                 item = {
                 item = {
-                    'title':date,
+                    'title':date[5:],
                     'data':rows.filter(create_time__gte=date,create_time__lte=date+' 23:59:59').count(),
                     'data':rows.filter(create_time__gte=date,create_time__lte=date+' 23:59:59').count(),
                 }
                 }
                 data.append(item)
                 data.append(item)
@@ -183,10 +183,9 @@ class StatisticsEvaluateView(APIView):
         now = timezone.now()
         now = timezone.now()
         date = (now + datetime.timedelta(days=-days)).strftime('%Y-%m-%d')
         date = (now + datetime.timedelta(days=-days)).strftime('%Y-%m-%d')
         rows = RepairOrderComment.objects.filter(repair_order__tenant=tenant,create_time__gte=date,) \
         rows = RepairOrderComment.objects.filter(repair_order__tenant=tenant,create_time__gte=date,) \
-            .values('user__employee__name') \
+            .values('user_id') \
             .annotate(count=Sum('start')) \
             .annotate(count=Sum('start')) \
-            .values('user__employee__name', 'count') \
-            .order_by('user__employee__name')
+            .values('user__employee__name', 'count')
         for row in rows:
         for row in rows:
             item = {
             item = {
                 'title':row['user__employee__name'],
                 'title':row['user__employee__name'],

+ 3 - 3
ly_baoxiu_admin/settings.py

@@ -186,8 +186,8 @@ HANG_UP = 4
 TURN_EMPLOYEE = 5
 TURN_EMPLOYEE = 5
 FINISH = 6
 FINISH = 6
 APPRAISE = 7
 APPRAISE = 7
-INVALID = 8
-CANCEL_HANG_UP = 9
+CANCEL_HANG_UP = 8
+INVALID = 9
 REPAIR_STATUS_CHOICES = (
 REPAIR_STATUS_CHOICES = (
     (NOT_CHECKED, '待审核'),
     (NOT_CHECKED, '待审核'),
     (CHECKED, '已审核,待派单'),
     (CHECKED, '已审核,待派单'),
@@ -196,8 +196,8 @@ REPAIR_STATUS_CHOICES = (
     (TURN_EMPLOYEE, '转单'),
     (TURN_EMPLOYEE, '转单'),
     (FINISH, '已完工,待评价'),
     (FINISH, '已完工,待评价'),
     (APPRAISE, '已评价'),
     (APPRAISE, '已评价'),
-    (INVALID, '作废'),
     (CANCEL_HANG_UP, '取消挂起'),
     (CANCEL_HANG_UP, '取消挂起'),
+    (INVALID, '作废'),
 )
 )
 
 
 # Internationalization
 # Internationalization

+ 296 - 7
uis/tenant/dashboard/index.html

@@ -8,14 +8,303 @@
   <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
   <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
   <link rel="stylesheet" href="../../layuiadmin/layui/css/layui.css" media="all">
   <link rel="stylesheet" href="../../layuiadmin/layui/css/layui.css" media="all">
   <link rel="stylesheet" href="../../layuiadmin/style/admin.css" media="all">
   <link rel="stylesheet" href="../../layuiadmin/style/admin.css" media="all">
+  <style>
+    .topPart{
+        display: flex;
+        justify-content: space-between;
+        flex-direction: row;
+        flex-wrap: wrap;
+        padding: 0 20px;
+        background: #ffffff;
+    }
+    .dayAmount{
+        width: 31%;
+        margin: 10px 0;
+        padding: 20px 0 20px 10px;
+        background: #ff6600;
+    }
+    .monthAmount{
+        width: 31%;
+        margin: 10px 0;
+        padding: 20px 0 20px 10px;
+        background: #1abc9b;
+    }
+    .yearAmount{
+        width: 31%;
+        padding: 20px 0 20px 10px;
+        margin: 10px 0;
+        background: #1e9eb3;
+    }
+    .dayCount{
+        width: 31%;
+        padding: 20px 0 20px 10px;
+        margin: 10px 0;
+        background: #ee7c5c;
+    }
+    .monthCount{
+        width: 31%;
+        padding: 20px 0 20px 10px;
+        margin: 10px 0;
+        background: #ff9900;
+    }
+    .yearCount{
+        width: 31%;
+        padding: 20px 0 20px 10px;
+        margin: 10px 0;
+        background: #2ec7c9;
+    }
+    h4{
+        margin-top: 5px;
+        color: #ffffff;
+    }
+    cite{
+        color: #ffffff;
+        font-size: 30px;
+    }
+    .layui-card-header{
+        padding-left: 20px;
+        color: #000;
+        font-size: 18px;
+    }
+  </style>
 </head>
 </head>
-<body style="height: 100%;">
-
-<div class="layui-card" style="height: 100%;display:flex;">
-  <div style="margin:auto;font-weight:bold;font-size: 32px;font-style: normal;color:#868686;">
-    欢迎使用维修管理系统
-  </div>
-</div>
+<body>
+    <div class="layui-fluid">
+        <div class="layui-row layui-col-space15">
+            <div class="layui-col-md12">
+               <div class="layui-row layui-col-space15">
+                    <!-- 统计数据 -->
+                    <div class="layui-col-md12">
+                         <div class="layui-card">
+                            <div class="layui-card-header">数据概览</div>
+                            <ul class="layui-col-md12 topPart">
+                                <li class="dayAmount">
+                                    <p><cite id="wait_check"></cite></p>
+                                    <h4>待审核</h4>
+                                </li>
+                                <li class="monthAmount">
+                                    <p><cite id="is_check"></cite></p>
+                                    <h4>待接单</h4>
+                                </li>
+                                <li class="yearAmount">
+                                    <p><cite id="working"></cite></p>
+                                    <h4>维修中</h4>
+                                </li>
+                                <li class="dayCount">
+                                    <p><cite id="hang_up"></cite></p>
+                                    <h4>挂起中</h4>
+                                </li>
+                                <li class="dayCount">
+                                    <p><cite id="complete"></cite></p>
+                                    <h4>已完工</h4>
+                                </li>
+                                <li class="monthCount">
+                                    <p><cite id="appraise"></cite></p>
+                                    <h4>已评价</h4>
+                                </li>
+                            </ul>
+                         </div>
+                    </div>
+                    <!-- 统计图表 -->
+                    <div class="layui-col-md8">
+                        <div style="padding-top: 20px" class="layui-card">
+                            <div id="chart1" style="height:400px;"></div>
+                        </div>
+                    </div>
+                    <div class="layui-col-md4">
+                        <div style="padding-top: 20px" class="layui-card">
+                            <div id="chart2" style="height:400px"></div>
+                        </div>
+                    </div>
+               </div>
+            </div>
+        </div>
+    </div>
+    <script src="../../layuiadmin/layui/layui.js?t=1"></script>
+    <script>
+        layui.config({
+              base: '../../layuiadmin/' //静态资源所在路径
+            }).extend({
+              index: 'lib/index', //主入口模块
+            }).use(['index', 'home','echarts'], function() {
+                var $ = layui.$
+                ,admin = layui.admin
+                ,echarts = layui.echarts
+                ,xData = [];
+                var chart1 = echarts.init($('#chart1')[0]);
+                var chart2 = echarts.init($('#chart2')[0]);
+            //echarts容器自适应大小
+            var setContain = () => {
+                var chartDom1 = document.getElementById("chart1");
+                var chartDom2 = document.getElementById("chart2");
+                chartDom1.style.width = $(".layui-col-md8").clientWidth + 'px';
+                chartDom1.style.height = $(".llayui-col-md8").clientHeight + 'px';
+                chartDom2.style.width = $(".layui-col-md4").clientWidth + 'px';
+                chartDom2.style.height = $(".llayui-col-md4").clientHeight + 'px';
+            };
+            // 设置echarts的容器大小
+            setContain();
 
 
+         admin.req({
+            url: '/tenant/repair_order/statistics/'
+            ,type: 'get'
+            , done: function (res) {
+                $('#wait_check').html(res.data.wait_check);
+                $('#is_check').html(res.data.is_check);
+                $('#working').html(res.data.working);
+                $('#hang_up').html(res.data.hang_up);
+                $('#complete').html(res.data.complete);
+                $('#appraise').html(res.data.appraise);
+            }
+        });
+         //设置饼图数据
+         admin.req({
+            url: '/tenant/repair_order/statistics/repair_type/'
+            ,type: 'get'
+            , done: function (res) {
+                if(res.data && res.data.length > 0){
+                    res.data.forEach(item=>{
+                        xData.push(item.name)
+                    })
+                }
+                var option2 = {
+                title: {
+                        text: '报修类型占比',
+                        x: 'center' //标题居中
+                    },
+                    tooltip: {
+                        // trigger: 'item' //悬浮显示对比
+                    },
+                    legend: {
+                        orient: 'vertical', //类型垂直,默认水平
+                        x:'left',      //可设定图例在左、右、居中
+                        y:'top',     //可设定图例在上、下、居中
+                        padding:[5,0,0,20],
+                        data: xData
+                    },
+                    series: [{
+                        type: 'pie', //饼状
+                        radius: '60%', //圆的大小
+                        center: ['50%', '50%'], //居中
+                        data: res.data
+                     }]
+            };
+            chart2.setOption(option2);
+            }
+        });
+         // 柱状图和折线图
+         admin.req({
+            url: "/tenant/repair_order/statistics/repair_order/"
+            ,type: 'get'
+            , done: function (res) {
+            var option1 = {
+                  title: {
+                      text: '报修趋势统计',
+                      x: 'center',
+                      itemGap:20
+                  },
+                  tooltip: {
+                      trigger: 'axis',
+                      axisPointer: {
+                          type: 'cross',
+                          crossStyle: {
+                              color: '#999'
+                          }
+                      }
+                  },
+                  toolbox: {
+                      feature: {
+                          dataView: {show: true, readOnly: false},
+                          magicType: {show: true, type: ['line', 'bar']},
+                          restore: {show: true},
+                          saveAsImage: {show: true}
+                      }
+                  },
+                  legend: {
+                      data:['报修量','完工量'],
+                      padding:[30,0,0,0]
+                  },
+                  xAxis: [
+                      {
+                          type: 'category',
+                          data: res.data.order_mouth,
+                          axisPointer: {
+                              type: 'shadow'
+                          },
+                          axisLine: {
+                              lineStyle: {
+                                  color: '#009688', // 颜色
+                              }
+                          }
+                      }
+                  ],
+                  yAxis: [
+                      {
+                          type: 'value',
+                          name: '报修量',
+                          min: 0,
+                          axisLabel: {
+                              formatter: '{value} '
+                          },
+                          axisLine: {
+                              lineStyle: {
+                                  color: '#009688', // 颜色
+                              }
+                          }
+                      },
+                      {
+                          type: 'value',
+                          name: '完工量',
+                          min: 0,
+                          axisLabel: {
+                              formatter: '{value} '
+                          },
+                          axisLine: {
+                              lineStyle: {
+                                  color: '#009688', // 颜色
+                              }
+                          }
+                      }
+                  ],
+                  series: [
+                      {
+                          name:'报修量',
+                          type:'bar',
+                          itemStyle: {
+                              normal: {
+                                  color: "#FFB800",
+                                  lineStyle: {
+                                      color: "#FFB800"
+                                  }
+                              }
+                          },
+                          data: res.data.repair_counts
+                      },
+                      {
+                          name:'完工量',
+                          type:'line',
+                          yAxisIndex: 1,
+                          itemStyle: {
+                              normal: {
+                                  color: "#1E9FFF",
+                                  lineStyle: {
+                                      color: "#1E9FFF"
+                                  }
+                              }
+                          },
+                          data:res.data.finish_counts
+                      }
+                  ]
+              };
+                chart1.setOption(option1);
+            }
+         });
+         window.onresize = function () {//用于使chart自适应高度和宽度
+                setContain();//重置容器高宽
+                chart1.resize();
+                chart2.resize();
+            };
+        })
+    </script>
 </body>
 </body>
 </html>
 </html>