django+xadmin打造个性CRM营销管理系统之CEO工作台篇,根据CRM系统数据,用小工具打造一个CEO个性看版,大概效果如下图:
以下是操作步骤:
1、修改几个文件,
在合适位置,加上以下代码:
#测试美化页面 START def shujvmeihua(request): hetongjine = "" # 数据库操作 from app1.models import Order_admin,Product_admin,Customer_admin,Kuaidi_admin,Buy_admin from django.db.models import Sum,Q,F #Q为多条件使用,F为多条件相乘求和 from decimal import Decimal #获取前端URL的数据 if request.method == 'GET': kaishi_shijian = request.GET.get('start_time','2025-1-1') jieshu_shijian = request.GET.get('end_time','2025-1-31') tishi = "当前是GET方法获取数据" nianfen = request.GET.get('nian',"2025") #如果获取的年为空,则默认年的值为2025 fanwei = kaishi_shijian + "到" + jieshu_shijian elif request.method == 'POST': kaishi_shijian = request.POST.get('start_time','2025-1-1') jieshu_shijian = request.POST.get('end_time','2025-1-31') tishi = "当前是POST方法获取数据" fanwei = kaishi_shijian + "到" + jieshu_shijian nianfen = request.POST.get('nian',"2025") else: nianfen = 2025 kaishi_shijian = 2025-5-1 jieshu_shijian = 2025-5-31 #计算指定日期期间数据 #1合同金额 total_money = Order_admin.objects.filter(qiandingriqi__range=(kaishi_shijian, jieshu_shijian)).aggregate(num=Sum("hetongjine")) hetongjine = "{:.2f}".format(total_money['num']) #2合同成本 total_money = Order_admin.objects.filter(qiandingriqi__range=(kaishi_shijian, jieshu_shijian)).aggregate(num=Sum("hetongchengben")) hetongchengben = "{:.2f}".format(total_money['num']) #3合同毛利,保留两位小数 total_money = Order_admin.objects.filter(qiandingriqi__range=(kaishi_shijian, jieshu_shijian)).aggregate(num=Sum("maolirun")) hetongmaoli = "{:.2f}".format(total_money['num']) #4应付款项 yingfukuanxiang = Buy_admin.objects.filter(chuangjianshijian__range=(kaishi_shijian, jieshu_shijian)).aggregate(total=Sum(F('caigoudanjia') * F('caigoushuliang'))) yingfukuanxiang = "{:.2f}".format(yingfukuanxiang['total']) #5应收款项 total_money = Order_admin.objects.filter(qiandingriqi__range=(kaishi_shijian, jieshu_shijian)).aggregate(num=Sum("weishoujine")) yingshoukuanxiang = total_money['num'] #6物流成本 2023年11月21日, PM 06:07:46 wuliufeiyong = Kuaidi_admin.objects.filter(qiandingriqi__range=(kaishi_shijian, jieshu_shijian)).aggregate(num=Sum("chanpinchengben")) wuliuchengben = wuliufeiyong['num'] #7库存成本 2023年11月21日, PM 04:41:00 kucun_total_money = Product_admin.objects.all().aggregate(num=Sum("kucunchengben")) kucunchengben = kucun_total_money['num'] #8库存数量 2023年11月21日, PM 04:41:00 kucunshuliang = Product_admin.objects.all().aggregate(num=Sum("chanpinkucun")) kucunshuliang = kucunshuliang['num'] #9合同数量 2023年11月21日 17:40:10 hetongshuliang = Order_admin.objects.filter(qiandingriqi__range=(kaishi_shijian, jieshu_shijian)).count() #10客户数量 2023年11月21日, PM 04:41:00 kehushuliang = Customer_admin.objects.all().count() #11已完结 yiwanjie = Order_admin.objects.filter(Q(hetongzhuangtai='完毕') & Q(qiandingriqi__range=(kaishi_shijian, jieshu_shijian))).count() #12进行中 jinxingzhong = Order_admin.objects.filter(Q(hetongzhuangtai='执行中') & Q(qiandingriqi__range=(kaishi_shijian, jieshu_shijian))).count() #13签约【未开始】 qianyue = Order_admin.objects.filter(Q(hetongzhuangtai='签约') & Q(qiandingriqi__range=(kaishi_shijian, jieshu_shijian))).count() #13签约【未开始】 zhongzhi = Order_admin.objects.filter(Q(hetongzhuangtai='终止') & Q(qiandingriqi__range=(kaishi_shijian, jieshu_shijian))).count() #15产品销量 cpxl10 = Order_admin.objects.filter(qiandingriqi__range=(kaishi_shijian, jieshu_shijian)).aggregate(num=Sum("chanpinshuliang")) chanpinxiaoliang = cpxl10['num'] #16所有月份数据 #导入时间判断模块 from django.db import models from datetime import datetime, timedelta #获取得到的年份 year = int(nianfen) yuefenjihe=[] aa = 1 while(aa <= 12): # 分别判断每个月有多少天 month=int(aa) # 计算下一个月的第一天 next_month = datetime(year, month, 28) + timedelta(days=4) last_day = next_month - timedelta(days=next_month.day) num_of_days1 = last_day.day num_of_days1=num_of_days1 # 输出值 aa=aa+1 yuefenjihe.append(str(num_of_days1)) zyuefen=[] for index,h in enumerate(yuefenjihe): et1="{}-{}-{}".format(year,index+1,h) #print(et1) zyuefen.append(et1) st1=nianfen+"-1-1" st2=nianfen+"-2-1" st3=nianfen+"-3-1" st4=nianfen+"-4-1" st5=nianfen+"-5-1" st6=nianfen+"-6-1" st7=nianfen+"-7-1" st8=nianfen+"-8-1" st9=nianfen+"-9-1" st10=nianfen+"-10-1" st11=nianfen+"-11-1" st12=nianfen+"-12-1" et1=zyuefen[0] et2=zyuefen[1] et3=zyuefen[2] et4=zyuefen[3] et5=zyuefen[4] et6=zyuefen[5] et7=zyuefen[6] et8=zyuefen[7] et9=zyuefen[8] et10=zyuefen[9] et11=zyuefen[10] et12=zyuefen[11] #先判断是否为空,不为空再聚合数据 #1月份数据 try1=Order_admin.objects.filter(qiandingriqi__range=(st1,et1)) if try1.exists(): total_money_01= Order_admin.objects.filter(qiandingriqi__range=(st1,et1)).aggregate(num=Sum("hetongjine")) total_maoli_01 = Order_admin.objects.filter(qiandingriqi__range=(st1,et1)).aggregate(num=Sum("maolirun")) jine_01 = "{:.2f}".format(total_money_01['num']) maoli_01 = "{:.2f}".format(total_maoli_01['num']) else: jine_01 = 0 maoli_01 = 0 #2月份数据 try2=Order_admin.objects.filter(qiandingriqi__range=(st2,et2)) if try2.exists(): total_money_02= Order_admin.objects.filter(qiandingriqi__range=(st2,et2)).aggregate(num=Sum("hetongjine")) total_maoli_02 = Order_admin.objects.filter(qiandingriqi__range=(st2,et2)).aggregate(num=Sum("maolirun")) jine_02 = "{:.2f}".format(total_money_02['num']) maoli_02 = "{:.2f}".format(total_maoli_02['num']) else: jine_02 = 0 maoli_02 = 0 #3月份数据 try3=Order_admin.objects.filter(qiandingriqi__range=(st3,et3)) if try3.exists(): total_money_03= Order_admin.objects.filter(qiandingriqi__range=(st3,et3)).aggregate(num=Sum("hetongjine")) total_maoli_03 = Order_admin.objects.filter(qiandingriqi__range=(st3,et3)).aggregate(num=Sum("maolirun")) jine_03 = "{:.2f}".format(total_money_03['num']) maoli_03 = "{:.2f}".format(total_maoli_03['num']) else: jine_03 = 0 maoli_03 = 0 #4月份数据 try4=Order_admin.objects.filter(qiandingriqi__range=(st4,et4)) if try4.exists(): total_money_04= Order_admin.objects.filter(qiandingriqi__range=(st4,et4)).aggregate(num=Sum("hetongjine")) total_maoli_04 = Order_admin.objects.filter(qiandingriqi__range=(st4,et4)).aggregate(num=Sum("maolirun")) jine_04 = "{:.2f}".format(total_money_04['num']) maoli_04 = "{:.2f}".format(total_maoli_04['num']) else: jine_04 = 0 maoli_04 = 0 #5月份数据 try5=Order_admin.objects.filter(qiandingriqi__range=(st5,et5)) if try5.exists(): total_money_05= Order_admin.objects.filter(qiandingriqi__range=(st5,et5)).aggregate(num=Sum("hetongjine")) total_maoli_05 = Order_admin.objects.filter(qiandingriqi__range=(st5,et5)).aggregate(num=Sum("maolirun")) jine_05 = "{:.2f}".format(total_money_05['num']) maoli_05 = "{:.2f}".format(total_maoli_05['num']) else: jine_05 = 0 maoli_05 = 0 #6月份数据 try6=Order_admin.objects.filter(qiandingriqi__range=(st6,et6)) if try6.exists(): total_money_06= Order_admin.objects.filter(qiandingriqi__range=(st6,et6)).aggregate(num=Sum("hetongjine")) total_maoli_06 = Order_admin.objects.filter(qiandingriqi__range=(st6,et6)).aggregate(num=Sum("maolirun")) jine_06 = "{:.2f}".format(total_money_06['num']) maoli_06 = "{:.2f}".format(total_maoli_06['num']) else: jine_06 = 0 maoli_06 = 0 #7月份数据 try7=Order_admin.objects.filter(qiandingriqi__range=(st7,et7)) if try7.exists(): total_money_07= Order_admin.objects.filter(qiandingriqi__range=(st7,et7)).aggregate(num=Sum("hetongjine")) total_maoli_07 = Order_admin.objects.filter(qiandingriqi__range=(st7,et7)).aggregate(num=Sum("maolirun")) jine_07 = "{:.2f}".format(total_money_07['num']) maoli_07 = "{:.2f}".format(total_maoli_07['num']) else: jine_07 = 0 maoli_07 = 0 #8月份数据 try8=Order_admin.objects.filter(qiandingriqi__range=(st8,et8)) if try8.exists(): total_money_08= Order_admin.objects.filter(qiandingriqi__range=(st8,et8)).aggregate(num=Sum("hetongjine")) total_maoli_08 = Order_admin.objects.filter(qiandingriqi__range=(st8,et8)).aggregate(num=Sum("maolirun")) jine_08 = "{:.2f}".format(total_money_08['num']) maoli_08 = "{:.2f}".format(total_maoli_08['num']) else: jine_08 = 0 maoli_08 = 0 #9月份数据 try9=Order_admin.objects.filter(qiandingriqi__range=(st9,et9)) if try9.exists(): total_money_09= Order_admin.objects.filter(qiandingriqi__range=(st9,et9)).aggregate(num=Sum("hetongjine")) total_maoli_09 = Order_admin.objects.filter(qiandingriqi__range=(st9,et9)).aggregate(num=Sum("maolirun")) jine_09 = "{:.2f}".format(total_money_09['num']) maoli_09 = "{:.2f}".format(total_maoli_09['num']) else: jine_09 = 0 maoli_09 = 0 #10月份数据 try10=Order_admin.objects.filter(qiandingriqi__range=(st10,et10)) if try10.exists(): total_money_10= Order_admin.objects.filter(qiandingriqi__range=(st10,et10)).aggregate(num=Sum("hetongjine")) total_maoli_10 = Order_admin.objects.filter(qiandingriqi__range=(st10,et10)).aggregate(num=Sum("maolirun")) jine_10 = "{:.2f}".format(total_money_10['num']) maoli_10 = "{:.2f}".format(total_maoli_10['num']) else: jine_10 = 0 maoli_10 = 0 #11月份数据 try11=Order_admin.objects.filter(qiandingriqi__range=(st11,et11)) if try11.exists(): total_money_11= Order_admin.objects.filter(qiandingriqi__range=(st11,et11)).aggregate(num=Sum("hetongjine")) total_maoli_11 = Order_admin.objects.filter(qiandingriqi__range=(st11,et11)).aggregate(num=Sum("maolirun")) jine_11 = "{:.2f}".format(total_money_11['num']) maoli_11 = "{:.2f}".format(total_maoli_11['num']) else: jine_11 = 0 maoli_11 = 0 #12月份数据 try12=Order_admin.objects.filter(qiandingriqi__range=(st12,et12)) if try12.exists(): total_money_12= Order_admin.objects.filter(qiandingriqi__range=(st12,et12)).aggregate(num=Sum("hetongjine")) total_maoli_12 = Order_admin.objects.filter(qiandingriqi__range=(st12,et12)).aggregate(num=Sum("maolirun")) jine_12 = "{:.2f}".format(total_money_12['num']) maoli_12 = "{:.2f}".format(total_maoli_12['num']) else: jine_12 = 0 maoli_12 = 0 return render(request, 'shujvmeihua.html', { "hetongjine":hetongjine, #1合同金额 "hetongchengben":hetongchengben,#2合同成本 "hetongmaoli":hetongmaoli,#3合同毛利 "yingfukuanxiang":yingfukuanxiang,#4应付款项 "yingshoukuanxiang":yingshoukuanxiang,#5应收款项 "wuliuchengben":wuliuchengben,#6物流成本 "kucunchengben":kucunchengben,#7库存成本 "kucunshuliang":kucunshuliang,#8库存数量 "hetongshuliang":hetongshuliang,#9合同数量 "kehushuliang":kehushuliang,#10客户数量 "yiwanjie":yiwanjie,#11已完结 "jinxingzhong":jinxingzhong,#12进行中 "qianyue":qianyue,#13未开始 "zhongzhi":zhongzhi,#14已终止 "chanpinxiaoliang":chanpinxiaoliang,#15产品销量 "je01":jine_01,#16所有月份数据 "ml01":maoli_01, "je02":jine_02, "ml02":maoli_02, "je03":jine_03, "ml03":maoli_03, "je04":jine_04, "ml04":maoli_04, "je05":jine_05, "ml05":maoli_05, "je06":jine_06, "ml06":maoli_06, "je07":jine_07, "ml07":maoli_07, "je08":jine_08, "ml08":maoli_08, "je09":jine_09, "ml09":maoli_09, "je10":jine_10, "ml10":maoli_10, "je11":jine_11, "ml11":maoli_11, "je12":jine_12, "ml12":maoli_12, }) #测试美化页面 END
以上实现了数据的获取部分,MYSQL数据这里就不提供了,具体看代码自己去构建即可。下面是前端界面部分。
放入以下代码,根据自己项目修改就行:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>项目管理仪表盘</title> <style> /* 基础样式重置 */ * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Arial', sans-serif; } body { background-color: #f5f7fa; color: #333; line-height: 1.6; } /* 容器布局 */ .container { max-width: 1200px; margin: 0 auto; padding: 20px; } /* 响应式行布局 */ .row { display: flex; flex-wrap: wrap; gap: 20px; margin-top: 15px; } /* 卡片组件 */ .card { background-color: white; border-radius: 10px; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); padding: 20px; flex: 1; min-width: 300px; transition: all 0.3s ease; } .card:hover { transform: translateY(-5px); box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); } /* 头部布局 */ .header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; } .chart-title { color: #666; font-size: 18px; } .header h3 { font-size: 18px; font-weight: 600; margin-bottom: 5px; } /* 视图选项 */ .view-options button { background: none; border: none; color: #888; margin-left: 10px; cursor: pointer; font-size: 14px; } .view-options button.active { color: #42b983; font-weight: 600; } /* 统计卡片 */ .project-stats { display: flex; justify-content: space-around; margin-top: 20px; } .stat-item { text-align: center; } .circle { display: inline-flex; justify-content: center; align-items: center; width: 40px; height: 40px; border-radius: 50%; background-color: #42b983; color: white; font-size: 18px; margin-bottom: 10px; } /* 图表容器 */ canvas { max-width: 100%; height: auto !important; } /* 待办事项 */ .todo-list { margin-top: 20px; } .todo-section { margin-bottom: 20px; } .todo-section h4 { font-size: 16px; color: #666; margin-bottom: 10px; display: flex; align-items: center; } .todo-item { background-color: #f9f9f9; border-radius: 5px; padding: 10px; margin-bottom: 10px; display: flex; justify-content: space-between; align-items: center; } .todo-item.completed { background-color: #e8f4f8; opacity: 0.7; } .todo-content { flex-grow: 1; } .todo-title { font-size: 14px; margin-bottom: 5px; } .todo-time { font-size: 12px; color: #888; } .todo-actions button { background: none; border: none; color: #aaa; font-size: 18px; cursor: pointer; margin-left: 10px; } .todo-actions button:hover { color: #42b983; } /* 响应式布局 */ @media (max-width: 768px) { .row { flex-direction: column; } } </style> </head> <body> <div class="container"> <!-- 统计卡片组 --> <div class="row"> <!-- 合同相关卡片 --> <div class="card full-width"> <div class="header"> <h3>合同金额</h3> <i class="fas fa-dollar-sign"></i> </div> <p class="number">¥{{ hetongjine }}</p> </div> <!-- 其他统计卡片... --> </div> <!-- 年度数据图表 --> <div class="row"> <div class="card full-width"> <div class="header"> <h3>2025年各月数据概览</h3> </div> <div id="main" style="width: 100%; height: 600px;"></div> <script src="https://cdn.jsdelivr.net/npm/echarts@5.2.2/dist/echarts.js"></script> <script> // ECharts配置 const option = { title: { text: '合同金额 & 合同毛利', subtext: '2025年全年' }, tooltip: { trigger: 'axis' }, legend: { data: ['合同金额', '合同毛利'] }, toolbox: { feature: { dataView: { readOnly: false }, magicType: { type: ['line', 'bar'] }, restore: {}, saveAsImage: {} } }, xAxis: [{ type: 'category', data: ['1月','2月','3月','4月','5月','6月','7月','8月','9月','10月','11月','12月'] }], yAxis: [{ type: 'value' }], series: [ { name: '合同金额', type: 'bar', data: [{{ je01 }}, {{ je02 }}], // 省略其他数据点 markPoint: { data: [{ type: 'max' }, { type: 'min' }] } }, // 毛利系列配置... ] }; // 初始化图表 const chart = echarts.init(document.getElementById('main')); chart.setOption(option); </script> </div> </div> <!-- 项目总览 --> <div class="row"> <div class="card full-width"> <div class="header"> <h3>项目总览</h3> <div class="view-options"> <button class="active">Day</button> <!-- 其他时间选项... --> </div> </div> <canvas id="projectsChart"></canvas> </div> </div> <!-- 待办事项 --> <div class="row"> <div class="card"> <div class="header"> <h3>我的任务清单</h3> <button><i class="fas fa-plus"></i> 加入清单</button> </div> <div class="todo-list"> <!-- 待办事项列表... --> </div> </div> </div> <!-- 收益图表 --> <div class="row"> <div class="card full-width"> <div class="header"> <h3>收入报表</h3> <div class="view-options"> <button>Day</button> <!-- 其他时间选项... --> </div> </div> <canvas id="earningsChart"></canvas> </div> </div> </div> <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> <script> // 图表初始化 const projectsCtx = document.getElementById('projectsChart').getContext('2d'); new Chart(projectsCtx, { type: 'bar', data: { labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], datasets: [{ label: '项目数量', data: [120, 130, 150, 140, 160, 180, 170, 190, 200, 180, 160, 140], backgroundColor: '#42b983' }] }, options: { responsive: true } }); // 收益图表配置... </script> </body> </html>
以上就完成了前端部分,但是访问https://你的网址:端口号/shujvmeihua.html?start_time=2025-04-01&end_time=2025-04-30后还是无法访问,需要修改第三个文件:
在合适位置,添加对应代码:
urlpatterns = [ # 主页路由 url(r'^$', app1_views.index), # 首页(新增) # 后台管理路由 url(r'^xadmin/', xadmin.site.urls), # xadmin 后台(新增 lky) # url(r'^admin/', admin.site.urls), # 默认 admin 后台(已禁用) # 应用核心路由 url(r'^home$', app1_views.home, name='home'), url(r'^hetong$', app1_views.hetong, name='hetong'), url(r'^test$', app1_views.test, name='test'), url(r'^article$', app1_views.article, name='article'), url(r'^id_get_product$', app1_views.id_get_product, name='id_get_product'), url(r'^huoqumaoli$', app1_views.huoqumaoli, name='huoqumaoli'), url(r'^zihetong$', app1_views.zihetong, name='zihetong'), url(r'^zongjine$', app1_views.zongjine, name='zongjine'), url(r'^czongchengben$', app1_views.czongchengben, name='czongchengben'), url(r'^shujvmeihua$', app1_views.shujvmeihua, name='shujvmeihua'), # CRM 数据美化模块 # 数据列表路由 url(r'^list$', app1_views.test_dpp, name='list'), # 前台列表显示 # 博客系统路由 url(r'^blog/', include('blog.urls')), # 博客分类模块(START) # API 接口路由(示例) # url(r'^api/v1/', include('api.urls')), ]
保存,上传替换,再次访问前端页面,DUAN~! 已经显示界面了,后端直接用HTML小工具,在里面用iframe调用这个界面就可以了。
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。
评论(0)