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调用这个界面就可以了。
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。